LyoKICoJUlBDIE1hbmFnZXIKICoKICogQ29weXJpZ2h0IDIwMDEgIE92ZSBL5XZlbiwgVHJhbnNHYW1pbmcgVGVjaG5vbG9naWVzCiAqIENvcHlyaWdodCAyMDAyICBNYXJjdXMgTWVpc3NuZXIKICogQ29weXJpZ2h0IDIwMDUgIE1pa2UgSGVhcm4sIFJvYiBTaGVhcm1hbiBmb3IgQ29kZVdlYXZlcnMKICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNyAgVVNBCiAqLwoKI2luY2x1ZGUgImNvbmZpZy5oIgojaW5jbHVkZSAid2luZS9wb3J0LmgiCgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxzdGRhcmcuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPGFzc2VydC5oPgoKI2RlZmluZSBDT0JKTUFDUk9TCiNkZWZpbmUgTk9OQU1FTEVTU1VOSU9OCiNkZWZpbmUgTk9OQU1FTEVTU1NUUlVDVAoKI2luY2x1ZGUgIndpbmRlZi5oIgojaW5jbHVkZSAid2luYmFzZS5oIgojaW5jbHVkZSAid2ludXNlci5oIgojaW5jbHVkZSAid2luc3ZjLmgiCiNpbmNsdWRlICJvYmpiYXNlLmgiCiNpbmNsdWRlICJvbGUyLmgiCiNpbmNsdWRlICJycGMuaCIKI2luY2x1ZGUgIndpbmVycm9yLmgiCiNpbmNsdWRlICJ3aW5yZWcuaCIKI2luY2x1ZGUgInd0eXBlcy5oIgojaW5jbHVkZSAid2luZS91bmljb2RlLmgiCgojaW5jbHVkZSAiY29tcG9ial9wcml2YXRlLmgiCgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgoKV0lORV9ERUZBVUxUX0RFQlVHX0NIQU5ORUwob2xlKTsKCnN0YXRpYyB2b2lkIF9fUlBDX1NUVUIgZGlzcGF0Y2hfcnBjKFJQQ19NRVNTQUdFICptc2cpOwoKLyogd2Ugb25seSB1c2Ugb25lIGZ1bmN0aW9uIHRvIGRpc3BhdGNoIGNhbGxzIGZvciBhbGwgbWV0aG9kcyAtIHdlIHVzZSB0aGUKICogUlBDX0lGX09MRSBmbGFnIHRvIHRlbGwgdGhlIFJQQyBydW50aW1lIHRoYXQgdGhpcyBpcyB0aGUgY2FzZSAqLwpzdGF0aWMgUlBDX0RJU1BBVENIX0ZVTkNUSU9OIHJwY19kaXNwYXRjaF90YWJsZVsxXSA9IHsgZGlzcGF0Y2hfcnBjIH07IC8qIChSTykgKi8Kc3RhdGljIFJQQ19ESVNQQVRDSF9UQUJMRSBycGNfZGlzcGF0Y2ggPSB7IDEsIHJwY19kaXNwYXRjaF90YWJsZSB9OyAvKiAoUk8pICovCgpzdGF0aWMgc3RydWN0IGxpc3QgcmVnaXN0ZXJlZF9pbnRlcmZhY2VzID0gTElTVF9JTklUKHJlZ2lzdGVyZWRfaW50ZXJmYWNlcyk7IC8qIChDUyBjc1JlZ0lmKSAqLwpzdGF0aWMgQ1JJVElDQUxfU0VDVElPTiBjc1JlZ0lmOwpzdGF0aWMgQ1JJVElDQUxfU0VDVElPTl9ERUJVRyBjc1JlZ0lmX2RlYnVnID0KewogICAgMCwgMCwgJmNzUmVnSWYsCiAgICB7ICZjc1JlZ0lmX2RlYnVnLlByb2Nlc3NMb2Nrc0xpc3QsICZjc1JlZ0lmX2RlYnVnLlByb2Nlc3NMb2Nrc0xpc3QgfSwKICAgICAgMCwgMCwgeyAoRFdPUkRfUFRSKShfX0ZJTEVfXyAiOiBkY29tIHJlZ2lzdGVyZWQgc2VydmVyIGludGVyZmFjZXMiKSB9Cn07CnN0YXRpYyBDUklUSUNBTF9TRUNUSU9OIGNzUmVnSWYgPSB7ICZjc1JlZ0lmX2RlYnVnLCAtMSwgMCwgMCwgMCwgMCB9OwoKc3RhdGljIFdDSEFSIHdzelJwY1RyYW5zcG9ydFtdID0geyduJywnYycsJ2EnLCdsJywncicsJ3AnLCdjJywwfTsKCgpzdHJ1Y3QgcmVnaXN0ZXJlZF9pZgp7CiAgICBzdHJ1Y3QgbGlzdCBlbnRyeTsKICAgIERXT1JEIHJlZnM7IC8qIHJlZiBjb3VudCAqLwogICAgUlBDX1NFUlZFUl9JTlRFUkZBQ0UgSWY7IC8qIGludGVyZmFjZSByZWdpc3RlcmVkIHdpdGggdGhlIFJQQyBydW50aW1lICovCn07CgovKiBnZXQgdGhlIHBpcGUgZW5kcG9pbnQgc3BlY2lmaWVkIG9mIHRoZSBzcGVjaWZpZWQgYXBhcnRtZW50ICovCnN0YXRpYyBpbmxpbmUgdm9pZCBnZXRfcnBjX2VuZHBvaW50KExQV1NUUiBlbmRwb2ludCwgY29uc3QgT1hJRCAqb3hpZCkKewogICAgLyogRklYTUU6IHNob3VsZCBnZXQgZW5kcG9pbnQgZnJvbSBycGNzcyAqLwogICAgc3RhdGljIGNvbnN0IFdDSEFSIHdzekVuZHBvaW50Rm9ybWF0W10gPSB7J1xcJywncCcsJ2knLCdwJywnZScsJ1xcJywnTycsJ0wnLCdFJywnXycsJyUnLCcwJywnOCcsJ2wnLCd4JywnJScsJzAnLCc4JywnbCcsJ3gnLDB9OwogICAgd3NwcmludGZXKGVuZHBvaW50LCB3c3pFbmRwb2ludEZvcm1hdCwgKERXT1JEKSgqb3hpZCA+PiAzMiksKERXT1JEKSpveGlkKTsKfQoKdHlwZWRlZiBzdHJ1Y3QKewogICAgY29uc3QgSVJwY0NoYW5uZWxCdWZmZXJWdGJsICpscFZ0Ymw7CiAgICBMT05HICAgICAgICAgICAgICAgICAgcmVmczsKfSBScGNDaGFubmVsQnVmZmVyOwoKdHlwZWRlZiBzdHJ1Y3QKewogICAgUnBjQ2hhbm5lbEJ1ZmZlciAgICAgICBzdXBlcjsgLyogc3VwZXJjbGFzcyAqLwoKICAgIFJQQ19CSU5ESU5HX0hBTkRMRSAgICAgYmluZDsgLyogaGFuZGxlIHRvIHRoZSByZW1vdGUgc2VydmVyICovCiAgICBPWElEICAgICAgICAgICAgICAgICAgIG94aWQ7IC8qIGFwYXJ0bWVudCBpbiB3aGljaCB0aGUgY2hhbm5lbCBpcyB2YWxpZCAqLwogICAgRFdPUkQgICAgICAgICAgICAgICAgICBkZXN0X2NvbnRleHQ7IC8qIHJldHVybmVkIGZyb20gR2V0RGVzdEN0eCAqLwogICAgTFBWT0lEICAgICAgICAgICAgICAgICBkZXN0X2NvbnRleHRfZGF0YTsgLyogcmV0dXJuZWQgZnJvbSBHZXREZXN0Q3R4ICovCn0gQ2xpZW50UnBjQ2hhbm5lbEJ1ZmZlcjsKCnN0cnVjdCBkaXNwYXRjaF9wYXJhbXMKewogICAgUlBDT0xFTUVTU0FHRSAgICAgKm1zZzsgLyogbWVzc2FnZSAqLwogICAgSVJwY1N0dWJCdWZmZXIgICAgKnN0dWI7IC8qIHN0dWIgYnVmZmVyLCBpZiBhcHBsaWNhYmxlICovCiAgICBJUnBjQ2hhbm5lbEJ1ZmZlciAqY2hhbjsgLyogc2VydmVyIGNoYW5uZWwgYnVmZmVyLCBpZiBhcHBsaWNhYmxlICovCiAgICBIQU5ETEUgICAgICAgICAgICAgaGFuZGxlOyAvKiBoYW5kbGUgdGhhdCB3aWxsIGJlY29tZSBzaWduYWxlZCB3aGVuIGNhbGwgZmluaXNoZXMgKi8KICAgIFJQQ19TVEFUVVMgICAgICAgICBzdGF0dXM7IC8qIHN0YXR1cyAob3V0KSAqLwogICAgSFJFU1VMVCAgICAgICAgICAgIGhyOyAvKiBocmVzdWx0IChvdXQpICovCn07CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgUnBjQ2hhbm5lbEJ1ZmZlcl9RdWVyeUludGVyZmFjZShMUFJQQ0NIQU5ORUxCVUZGRVIgaWZhY2UsIFJFRklJRCByaWlkLCBMUFZPSUQgKnBwdikKewogICAgKnBwdiA9IE5VTEw7CiAgICBpZiAoSXNFcXVhbElJRChyaWlkLCZJSURfSVJwY0NoYW5uZWxCdWZmZXIpIHx8IElzRXF1YWxJSUQocmlpZCwmSUlEX0lVbmtub3duKSkKICAgIHsKICAgICAgICAqcHB2ID0gKExQVk9JRClpZmFjZTsKICAgICAgICBJVW5rbm93bl9BZGRSZWYoaWZhY2UpOwogICAgICAgIHJldHVybiBTX09LOwogICAgfQogICAgcmV0dXJuIEVfTk9JTlRFUkZBQ0U7Cn0KCnN0YXRpYyBVTE9ORyBXSU5BUEkgUnBjQ2hhbm5lbEJ1ZmZlcl9BZGRSZWYoTFBSUENDSEFOTkVMQlVGRkVSIGlmYWNlKQp7CiAgICBScGNDaGFubmVsQnVmZmVyICpUaGlzID0gKFJwY0NoYW5uZWxCdWZmZXIgKilpZmFjZTsKICAgIHJldHVybiBJbnRlcmxvY2tlZEluY3JlbWVudCgmVGhpcy0+cmVmcyk7Cn0KCnN0YXRpYyBVTE9ORyBXSU5BUEkgU2VydmVyUnBjQ2hhbm5lbEJ1ZmZlcl9SZWxlYXNlKExQUlBDQ0hBTk5FTEJVRkZFUiBpZmFjZSkKewogICAgUnBjQ2hhbm5lbEJ1ZmZlciAqVGhpcyA9IChScGNDaGFubmVsQnVmZmVyICopaWZhY2U7CiAgICBVTE9ORyByZWY7CgogICAgcmVmID0gSW50ZXJsb2NrZWREZWNyZW1lbnQoJlRoaXMtPnJlZnMpOwogICAgaWYgKHJlZikKICAgICAgICByZXR1cm4gcmVmOwoKICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIFRoaXMpOwogICAgcmV0dXJuIDA7Cn0KCnN0YXRpYyBVTE9ORyBXSU5BUEkgQ2xpZW50UnBjQ2hhbm5lbEJ1ZmZlcl9SZWxlYXNlKExQUlBDQ0hBTk5FTEJVRkZFUiBpZmFjZSkKewogICAgQ2xpZW50UnBjQ2hhbm5lbEJ1ZmZlciAqVGhpcyA9IChDbGllbnRScGNDaGFubmVsQnVmZmVyICopaWZhY2U7CiAgICBVTE9ORyByZWY7CgogICAgcmVmID0gSW50ZXJsb2NrZWREZWNyZW1lbnQoJlRoaXMtPnN1cGVyLnJlZnMpOwogICAgaWYgKHJlZikKICAgICAgICByZXR1cm4gcmVmOwoKICAgIFJwY0JpbmRpbmdGcmVlKCZUaGlzLT5iaW5kKTsKICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIFRoaXMpOwogICAgcmV0dXJuIDA7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBTZXJ2ZXJScGNDaGFubmVsQnVmZmVyX0dldEJ1ZmZlcihMUFJQQ0NIQU5ORUxCVUZGRVIgaWZhY2UsIFJQQ09MRU1FU1NBR0UqIG9sZW1zZywgUkVGSUlEIHJpaWQpCnsKICAgIFJwY0NoYW5uZWxCdWZmZXIgKlRoaXMgPSAoUnBjQ2hhbm5lbEJ1ZmZlciAqKWlmYWNlOwogICAgUlBDX01FU1NBR0UgKm1zZyA9IChSUENfTUVTU0FHRSAqKW9sZW1zZzsKICAgIFJQQ19TVEFUVVMgc3RhdHVzOwoKICAgIFRSQUNFKCIoJXApLT4oJXAsJXMpXG4iLCBUaGlzLCBvbGVtc2csIGRlYnVnc3RyX2d1aWQocmlpZCkpOwoKICAgIHN0YXR1cyA9IElfUnBjR2V0QnVmZmVyKG1zZyk7CgogICAgVFJBQ0UoIi0tICVsZFxuIiwgc3RhdHVzKTsKCiAgICByZXR1cm4gSFJFU1VMVF9GUk9NX1dJTjMyKHN0YXR1cyk7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBDbGllbnRScGNDaGFubmVsQnVmZmVyX0dldEJ1ZmZlcihMUFJQQ0NIQU5ORUxCVUZGRVIgaWZhY2UsIFJQQ09MRU1FU1NBR0UqIG9sZW1zZywgUkVGSUlEIHJpaWQpCnsKICAgIENsaWVudFJwY0NoYW5uZWxCdWZmZXIgKlRoaXMgPSAoQ2xpZW50UnBjQ2hhbm5lbEJ1ZmZlciAqKWlmYWNlOwogICAgUlBDX01FU1NBR0UgKm1zZyA9IChSUENfTUVTU0FHRSAqKW9sZW1zZzsKICAgIFJQQ19DTElFTlRfSU5URVJGQUNFICpjaWY7CiAgICBSUENfU1RBVFVTIHN0YXR1czsKCiAgICBUUkFDRSgiKCVwKS0+KCVwLCVzKVxuIiwgVGhpcywgb2xlbXNnLCBkZWJ1Z3N0cl9ndWlkKHJpaWQpKTsKCiAgICBjaWYgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgSEVBUF9aRVJPX01FTU9SWSwgc2l6ZW9mKFJQQ19DTElFTlRfSU5URVJGQUNFKSk7CiAgICBpZiAoIWNpZikKICAgICAgICByZXR1cm4gRV9PVVRPRk1FTU9SWTsKCiAgICBjaWYtPkxlbmd0aCA9IHNpemVvZihSUENfQ0xJRU5UX0lOVEVSRkFDRSk7CiAgICAvKiBSUEMgaW50ZXJmYWNlIElEID0gQ09NIGludGVyZmFjZSBJRCAqLwogICAgY2lmLT5JbnRlcmZhY2VJZC5TeW50YXhHVUlEID0gKnJpaWQ7CiAgICAvKiBDT00gb2JqZWN0cyBhbHdheXMgaGF2ZSBhIHZlcnNpb24gb2YgMC4wICovCiAgICBjaWYtPkludGVyZmFjZUlkLlN5bnRheFZlcnNpb24uTWFqb3JWZXJzaW9uID0gMDsKICAgIGNpZi0+SW50ZXJmYWNlSWQuU3ludGF4VmVyc2lvbi5NaW5vclZlcnNpb24gPSAwOwogICAgbXNnLT5ScGNJbnRlcmZhY2VJbmZvcm1hdGlvbiA9IGNpZjsKICAgIG1zZy0+SGFuZGxlID0gVGhpcy0+YmluZDsKICAgIAogICAgc3RhdHVzID0gSV9ScGNHZXRCdWZmZXIobXNnKTsKCiAgICBUUkFDRSgiLS0gJWxkXG4iLCBzdGF0dXMpOwoKICAgIHJldHVybiBIUkVTVUxUX0ZST01fV0lOMzIoc3RhdHVzKTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIFNlcnZlclJwY0NoYW5uZWxCdWZmZXJfU2VuZFJlY2VpdmUoTFBSUENDSEFOTkVMQlVGRkVSIGlmYWNlLCBSUENPTEVNRVNTQUdFICpvbGVtc2csIFVMT05HICpwc3RhdHVzKQp7CiAgICBGSVhNRSgic3R1YlxuIik7CiAgICByZXR1cm4gRV9OT1RJTVBMOwp9CgovKiB0aGlzIHRocmVhZCBydW5zIGFuIG91dGdvaW5nIFJQQyAqLwpzdGF0aWMgRFdPUkQgV0lOQVBJIHJwY19zZW5kcmVjZWl2ZV90aHJlYWQoTFBWT0lEIHBhcmFtKQp7CiAgICBzdHJ1Y3QgZGlzcGF0Y2hfcGFyYW1zICpkYXRhID0gKHN0cnVjdCBkaXNwYXRjaF9wYXJhbXMgKikgcGFyYW07CgogICAgLyogRklYTUU6IHRyYXAgYW5kIHJldGhyb3cgUlBDIGV4Y2VwdGlvbnMgaW4gYXBwIHRocmVhZCAqLwogICAgZGF0YS0+c3RhdHVzID0gSV9ScGNTZW5kUmVjZWl2ZSgoUlBDX01FU1NBR0UgKilkYXRhLT5tc2cpOwoKICAgIFRSQUNFKCJjb21wbGV0ZWQgd2l0aCBzdGF0dXMgMHglbHhcbiIsIGRhdGEtPnN0YXR1cyk7CgogICAgU2V0RXZlbnQoZGF0YS0+aGFuZGxlKTsKCiAgICByZXR1cm4gMDsKfQoKc3RhdGljIGlubGluZSBIUkVTVUxUIENsaWVudFJwY0NoYW5uZWxCdWZmZXJfSXNDb3JyZWN0QXBhcnRtZW50KENsaWVudFJwY0NoYW5uZWxCdWZmZXIgKlRoaXMsIEFQQVJUTUVOVCAqYXB0KQp7CiAgICBPWElEIG94aWQ7CiAgICBpZiAoIWFwdCkKICAgICAgICByZXR1cm4gU19GQUxTRTsKICAgIGlmIChhcGFydG1lbnRfZ2V0b3hpZChhcHQsICZveGlkKSAhPSBTX09LKQogICAgICAgIHJldHVybiBTX0ZBTFNFOwogICAgaWYgKFRoaXMtPm94aWQgIT0gb3hpZCkKICAgICAgICByZXR1cm4gU19GQUxTRTsKICAgIHJldHVybiBTX09LOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQ2xpZW50UnBjQ2hhbm5lbEJ1ZmZlcl9TZW5kUmVjZWl2ZShMUFJQQ0NIQU5ORUxCVUZGRVIgaWZhY2UsIFJQQ09MRU1FU1NBR0UgKm9sZW1zZywgVUxPTkcgKnBzdGF0dXMpCnsKICAgIENsaWVudFJwY0NoYW5uZWxCdWZmZXIgKlRoaXMgPSAoQ2xpZW50UnBjQ2hhbm5lbEJ1ZmZlciAqKWlmYWNlOwogICAgSFJFU1VMVCBocjsKICAgIFJQQ19NRVNTQUdFICptc2cgPSAoUlBDX01FU1NBR0UgKilvbGVtc2c7CiAgICBSUENfU1RBVFVTIHN0YXR1czsKICAgIERXT1JEIGluZGV4OwogICAgc3RydWN0IGRpc3BhdGNoX3BhcmFtcyAqcGFyYW1zOwogICAgQVBBUlRNRU5UICphcHQgPSBOVUxMOwogICAgSVBJRCBpcGlkOwoKICAgIFRSQUNFKCIoJXApIGlNZXRob2Q9JWxkXG4iLCBvbGVtc2csIG9sZW1zZy0+aU1ldGhvZCk7CgogICAgaHIgPSBDbGllbnRScGNDaGFubmVsQnVmZmVyX0lzQ29ycmVjdEFwYXJ0bWVudChUaGlzLCBDT01fQ3VycmVudEFwdCgpKTsKICAgIGlmIChociAhPSBTX09LKQogICAgewogICAgICAgIEVSUigiY2FsbGVkIGZyb20gd3JvbmcgYXBhcnRtZW50LCBzaG91bGQgaGF2ZSBiZWVuIDB4JXNcbiIsCiAgICAgICAgICAgIHdpbmVfZGJnc3RyX2xvbmdsb25nKFRoaXMtPm94aWQpKTsKICAgICAgICByZXR1cm4gUlBDX0VfV1JPTkdfVEhSRUFEOwogICAgfQoKICAgIHBhcmFtcyA9IEhlYXBBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCBIRUFQX1pFUk9fTUVNT1JZLCBzaXplb2YoKnBhcmFtcykpOwogICAgaWYgKCFwYXJhbXMpIHJldHVybiBFX09VVE9GTUVNT1JZOwoKICAgIHBhcmFtcy0+bXNnID0gb2xlbXNnOwogICAgcGFyYW1zLT5zdGF0dXMgPSBSUENfU19PSzsKICAgIHBhcmFtcy0+aHIgPSBTX09LOwoKICAgIC8qIE5vdGU6IHRoaXMgaXMgYW4gb3B0aW1pemF0aW9uIGluIHRoZSBNaWNyb3NvZnQgT0xFIHJ1bnRpbWUgdGhhdCB3ZSBuZWVkCiAgICAgKiB0byBjb3B5LCBhcyBzaG93biBieSB0aGUgdGVzdF9ub19jb3VuaW5pdGlhbGl6ZV9jbGllbnQgdGVzdC4gd2l0aG91dAogICAgICogc2hvcnQtY2lyY3VpdGluZyB0aGUgUlBDIHJ1bnRpbWUgaW4gdGhlIGNhc2UgYmVsb3csIHRoZSB0ZXN0IHdpbGwKICAgICAqIGRlYWRsb2NrIG9uIHRoZSBsb2FkZXIgbG9jayBkdWUgdG8gdGhlIFJQQyBydW50aW1lIG5lZWRpbmcgdG8gY3JlYXRlCiAgICAgKiBhIHRocmVhZCB0byBwcm9jZXNzIHRoZSBSUEMgd2hlbiB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBpbmRpcmVjdGx5CiAgICAgKiBmcm9tIERsbE1haW4gKi8KCiAgICBScGNCaW5kaW5nSW5xT2JqZWN0KG1zZy0+SGFuZGxlLCAmaXBpZCk7CiAgICBociA9IGlwaWRfZ2V0X2Rpc3BhdGNoX3BhcmFtcygmaXBpZCwgJmFwdCwgJnBhcmFtcy0+c3R1YiwgJnBhcmFtcy0+Y2hhbik7CiAgICBwYXJhbXMtPmhhbmRsZSA9IENyZWF0ZUV2ZW50VyhOVUxMLCBGQUxTRSwgRkFMU0UsIE5VTEwpOwogICAgaWYgKChociA9PSBTX09LKSAmJiAhYXB0LT5tdWx0aV90aHJlYWRlZCkKICAgIHsKICAgICAgICBUUkFDRSgiQ2FsbGluZyBhcGFydG1lbnQgdGhyZWFkIDB4JTA4bHguLi5cbiIsIGFwdC0+dGlkKTsKCiAgICAgICAgaWYgKCFQb3N0TWVzc2FnZVcoYXBhcnRtZW50X2dldHdpbmRvdyhhcHQpLCBETV9FWEVDVVRFUlBDLCAwLCAoTFBBUkFNKXBhcmFtcykpCiAgICAgICAgewogICAgICAgICAgICBFUlIoIlBvc3RNZXNzYWdlIGZhaWxlZCB3aXRoIGVycm9yICVsZFxuIiwgR2V0TGFzdEVycm9yKCkpOwogICAgICAgICAgICBociA9IEhSRVNVTFRfRlJPTV9XSU4zMihHZXRMYXN0RXJyb3IoKSk7CiAgICAgICAgfQogICAgfQogICAgZWxzZQogICAgewogICAgICAgIGlmIChociA9PSBTX09LKQogICAgICAgIHsKICAgICAgICAgICAgLyogb3RoZXJ3aXNlLCB3ZSBnbyB2aWEgUlBDIHJ1bnRpbWUgc28gdGhlIHN0dWIgYW5kIGNoYW5uZWwgYXJlbid0CiAgICAgICAgICAgICAqIG5lZWRlZCBoZXJlICovCiAgICAgICAgICAgIElScGNTdHViQnVmZmVyX1JlbGVhc2UocGFyYW1zLT5zdHViKTsKICAgICAgICAgICAgcGFyYW1zLT5zdHViID0gTlVMTDsKICAgICAgICAgICAgSVJwY0NoYW5uZWxCdWZmZXJfUmVsZWFzZShwYXJhbXMtPmNoYW4pOwogICAgICAgICAgICBwYXJhbXMtPmNoYW4gPSBOVUxMOwogICAgICAgIH0KCiAgICAgICAgLyogd2UgdXNlIGEgc2VwYXJhdGUgdGhyZWFkIGhlcmUgYmVjYXVzZSB3ZSBuZWVkIHRvIGJlIGFibGUgdG8KICAgICAgICAgKiBwdW1wIHRoZSBtZXNzYWdlIGxvb3AgaW4gdGhlIGFwcGxpY2F0aW9uIHRocmVhZDogaWYgd2UgZG8gbm90LAogICAgICAgICAqIGFueSB3aW5kb3dzIGNyZWF0ZWQgYnkgdGhpcyB0aHJlYWQgd2lsbCBoYW5nIGFuZCBSUENzIHRoYXQgdHJ5CiAgICAgICAgICogYW5kIHJlLWVudGVyIHRoaXMgU1RBIGZyb20gYW4gaW5jb21pbmcgc2VydmVyIHRocmVhZCB3aWxsCiAgICAgICAgICogZGVhZGxvY2suIEluc3RhbGxTaGllbGQgaXMgYW4gZXhhbXBsZSBvZiB0aGF0LgogICAgICAgICAqLwogICAgICAgIGlmICghUXVldWVVc2VyV29ya0l0ZW0ocnBjX3NlbmRyZWNlaXZlX3RocmVhZCwgcGFyYW1zLCBXVF9FWEVDVVRFREVGQVVMVCkpCiAgICAgICAgewogICAgICAgICAgICBFUlIoIlF1ZXVlVXNlcldvcmtJdGVtIGZhaWxlZCB3aXRoIGVycm9yICVseFxuIiwgR2V0TGFzdEVycm9yKCkpOwogICAgICAgICAgICBociA9IEVfVU5FWFBFQ1RFRDsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgICAgICBociA9IFNfT0s7CiAgICB9CiAgICBpZiAoYXB0KSBhcGFydG1lbnRfcmVsZWFzZShhcHQpOwoKICAgIGlmIChociA9PSBTX09LKQogICAgewogICAgICAgIGlmIChXYWl0Rm9yU2luZ2xlT2JqZWN0KHBhcmFtcy0+aGFuZGxlLCAwKSkKICAgICAgICAgICAgaHIgPSBDb1dhaXRGb3JNdWx0aXBsZUhhbmRsZXMoMCwgSU5GSU5JVEUsIDEsICZwYXJhbXMtPmhhbmRsZSwgJmluZGV4KTsKICAgIH0KICAgIENsb3NlSGFuZGxlKHBhcmFtcy0+aGFuZGxlKTsKCiAgICBpZiAoaHIgPT0gU19PSykgaHIgPSBwYXJhbXMtPmhyOwoKICAgIHN0YXR1cyA9IHBhcmFtcy0+c3RhdHVzOwogICAgSGVhcEZyZWUoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgcGFyYW1zKTsKICAgIHBhcmFtcyA9IE5VTEw7CgogICAgaWYgKGhyKSByZXR1cm4gaHI7CiAgICAKICAgIGlmIChwc3RhdHVzKSAqcHN0YXR1cyA9IHN0YXR1czsKCiAgICBUUkFDRSgiUlBDIGNhbGwgc3RhdHVzOiAweCVseFxuIiwgc3RhdHVzKTsKICAgIGlmIChzdGF0dXMgPT0gUlBDX1NfT0spCiAgICAgICAgaHIgPSBTX09LOwogICAgZWxzZSBpZiAoc3RhdHVzID09IFJQQ19TX0NBTExfRkFJTEVEKQogICAgICAgIGhyID0gKihIUkVTVUxUICopb2xlbXNnLT5CdWZmZXI7CiAgICBlbHNlCiAgICAgICAgaHIgPSBIUkVTVUxUX0ZST01fV0lOMzIoc3RhdHVzKTsKCiAgICBUUkFDRSgiLS0gMHglMDhseFxuIiwgaHIpOwoKICAgIHJldHVybiBocjsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIFNlcnZlclJwY0NoYW5uZWxCdWZmZXJfRnJlZUJ1ZmZlcihMUFJQQ0NIQU5ORUxCVUZGRVIgaWZhY2UsIFJQQ09MRU1FU1NBR0UqIG9sZW1zZykKewogICAgUlBDX01FU1NBR0UgKm1zZyA9IChSUENfTUVTU0FHRSAqKW9sZW1zZzsKICAgIFJQQ19TVEFUVVMgc3RhdHVzOwoKICAgIFRSQUNFKCIoJXApXG4iLCBtc2cpOwoKICAgIHN0YXR1cyA9IElfUnBjRnJlZUJ1ZmZlcihtc2cpOwoKICAgIFRSQUNFKCItLSAlbGRcbiIsIHN0YXR1cyk7CgogICAgcmV0dXJuIEhSRVNVTFRfRlJPTV9XSU4zMihzdGF0dXMpOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgQ2xpZW50UnBjQ2hhbm5lbEJ1ZmZlcl9GcmVlQnVmZmVyKExQUlBDQ0hBTk5FTEJVRkZFUiBpZmFjZSwgUlBDT0xFTUVTU0FHRSogb2xlbXNnKQp7CiAgICBSUENfTUVTU0FHRSAqbXNnID0gKFJQQ19NRVNTQUdFICopb2xlbXNnOwogICAgUlBDX1NUQVRVUyBzdGF0dXM7CgogICAgVFJBQ0UoIiglcClcbiIsIG1zZyk7CgogICAgc3RhdHVzID0gSV9ScGNGcmVlQnVmZmVyKG1zZyk7CgogICAgSGVhcEZyZWUoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgbXNnLT5ScGNJbnRlcmZhY2VJbmZvcm1hdGlvbik7CiAgICBtc2ctPlJwY0ludGVyZmFjZUluZm9ybWF0aW9uID0gTlVMTDsKCiAgICBUUkFDRSgiLS0gJWxkXG4iLCBzdGF0dXMpOwoKICAgIHJldHVybiBIUkVTVUxUX0ZST01fV0lOMzIoc3RhdHVzKTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIENsaWVudFJwY0NoYW5uZWxCdWZmZXJfR2V0RGVzdEN0eChMUFJQQ0NIQU5ORUxCVUZGRVIgaWZhY2UsIERXT1JEKiBwZHdEZXN0Q29udGV4dCwgdm9pZCoqIHBwdkRlc3RDb250ZXh0KQp7CiAgICBDbGllbnRScGNDaGFubmVsQnVmZmVyICpUaGlzID0gKENsaWVudFJwY0NoYW5uZWxCdWZmZXIgKilpZmFjZTsKCiAgICBUUkFDRSgiKCVwLCVwKVxuIiwgcGR3RGVzdENvbnRleHQsIHBwdkRlc3RDb250ZXh0KTsKCiAgICAqcGR3RGVzdENvbnRleHQgPSBUaGlzLT5kZXN0X2NvbnRleHQ7CiAgICAqcHB2RGVzdENvbnRleHQgPSBUaGlzLT5kZXN0X2NvbnRleHRfZGF0YTsKCiAgICByZXR1cm4gU19PSzsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIFNlcnZlclJwY0NoYW5uZWxCdWZmZXJfR2V0RGVzdEN0eChMUFJQQ0NIQU5ORUxCVUZGRVIgaWZhY2UsIERXT1JEKiBwZHdEZXN0Q29udGV4dCwgdm9pZCoqIHBwdkRlc3RDb250ZXh0KQp7CiAgICBGSVhNRSgiKCVwLCVwKSwgc3R1YiFcbiIsIHBkd0Rlc3RDb250ZXh0LCBwcHZEZXN0Q29udGV4dCk7CiAgICByZXR1cm4gRV9GQUlMOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgUnBjQ2hhbm5lbEJ1ZmZlcl9Jc0Nvbm5lY3RlZChMUFJQQ0NIQU5ORUxCVUZGRVIgaWZhY2UpCnsKICAgIFRSQUNFKCIoKVxuIik7CiAgICAvKiBuYXRpdmUgZG9lcyBub3RoaW5nIHRvbyAqLwogICAgcmV0dXJuIFNfT0s7Cn0KCnN0YXRpYyBjb25zdCBJUnBjQ2hhbm5lbEJ1ZmZlclZ0YmwgQ2xpZW50UnBjQ2hhbm5lbEJ1ZmZlclZ0YmwgPQp7CiAgICBScGNDaGFubmVsQnVmZmVyX1F1ZXJ5SW50ZXJmYWNlLAogICAgUnBjQ2hhbm5lbEJ1ZmZlcl9BZGRSZWYsCiAgICBDbGllbnRScGNDaGFubmVsQnVmZmVyX1JlbGVhc2UsCiAgICBDbGllbnRScGNDaGFubmVsQnVmZmVyX0dldEJ1ZmZlciwKICAgIENsaWVudFJwY0NoYW5uZWxCdWZmZXJfU2VuZFJlY2VpdmUsCiAgICBDbGllbnRScGNDaGFubmVsQnVmZmVyX0ZyZWVCdWZmZXIsCiAgICBDbGllbnRScGNDaGFubmVsQnVmZmVyX0dldERlc3RDdHgsCiAgICBScGNDaGFubmVsQnVmZmVyX0lzQ29ubmVjdGVkCn07CgpzdGF0aWMgY29uc3QgSVJwY0NoYW5uZWxCdWZmZXJWdGJsIFNlcnZlclJwY0NoYW5uZWxCdWZmZXJWdGJsID0KewogICAgUnBjQ2hhbm5lbEJ1ZmZlcl9RdWVyeUludGVyZmFjZSwKICAgIFJwY0NoYW5uZWxCdWZmZXJfQWRkUmVmLAogICAgU2VydmVyUnBjQ2hhbm5lbEJ1ZmZlcl9SZWxlYXNlLAogICAgU2VydmVyUnBjQ2hhbm5lbEJ1ZmZlcl9HZXRCdWZmZXIsCiAgICBTZXJ2ZXJScGNDaGFubmVsQnVmZmVyX1NlbmRSZWNlaXZlLAogICAgU2VydmVyUnBjQ2hhbm5lbEJ1ZmZlcl9GcmVlQnVmZmVyLAogICAgU2VydmVyUnBjQ2hhbm5lbEJ1ZmZlcl9HZXREZXN0Q3R4LAogICAgUnBjQ2hhbm5lbEJ1ZmZlcl9Jc0Nvbm5lY3RlZAp9OwoKLyogcmV0dXJucyBhIGNoYW5uZWwgYnVmZmVyIGZvciBwcm94aWVzICovCkhSRVNVTFQgUlBDX0NyZWF0ZUNsaWVudENoYW5uZWwoY29uc3QgT1hJRCAqb3hpZCwgY29uc3QgSVBJRCAqaXBpZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEV09SRCBkZXN0X2NvbnRleHQsIHZvaWQgKmRlc3RfY29udGV4dF9kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElScGNDaGFubmVsQnVmZmVyICoqY2hhbikKewogICAgQ2xpZW50UnBjQ2hhbm5lbEJ1ZmZlciAqVGhpczsKICAgIFdDSEFSICAgICAgICAgICAgICAgICAgIGVuZHBvaW50WzIwMF07CiAgICBSUENfQklORElOR19IQU5ETEUgICAgICBiaW5kOwogICAgUlBDX1NUQVRVUyAgICAgICAgICAgICAgc3RhdHVzOwogICAgTFBXU1RSICAgICAgICAgICAgICAgICAgc3RyaW5nX2JpbmRpbmc7CgogICAgLyogY29ubmVjdCB0byB0aGUgYXBhcnRtZW50IGxpc3RlbmVyIHRocmVhZCAqLwogICAgZ2V0X3JwY19lbmRwb2ludChlbmRwb2ludCwgb3hpZCk7CgogICAgVFJBQ0UoInByb3h5IHBpcGU6IGNvbm5lY3RpbmcgdG8gZW5kcG9pbnQ6ICVzXG4iLCBkZWJ1Z3N0cl93KGVuZHBvaW50KSk7CgogICAgc3RhdHVzID0gUnBjU3RyaW5nQmluZGluZ0NvbXBvc2VXKAogICAgICAgIE5VTEwsCiAgICAgICAgd3N6UnBjVHJhbnNwb3J0LAogICAgICAgIE5VTEwsCiAgICAgICAgZW5kcG9pbnQsCiAgICAgICAgTlVMTCwKICAgICAgICAmc3RyaW5nX2JpbmRpbmcpOwogICAgICAgIAogICAgaWYgKHN0YXR1cyA9PSBSUENfU19PSykKICAgIHsKICAgICAgICBzdGF0dXMgPSBScGNCaW5kaW5nRnJvbVN0cmluZ0JpbmRpbmdXKHN0cmluZ19iaW5kaW5nLCAmYmluZCk7CgogICAgICAgIGlmIChzdGF0dXMgPT0gUlBDX1NfT0spCiAgICAgICAgewogICAgICAgICAgICBJUElEIGlwaWQyID0gKmlwaWQ7IC8qIHdoeSBjYW4ndCBScGNCaW5kaW5nU2V0T2JqZWN0IHRha2UgYSBjb25zdD8gKi8KICAgICAgICAgICAgc3RhdHVzID0gUnBjQmluZGluZ1NldE9iamVjdChiaW5kLCAmaXBpZDIpOwogICAgICAgICAgICBpZiAoc3RhdHVzICE9IFJQQ19TX09LKQogICAgICAgICAgICAgICAgUnBjQmluZGluZ0ZyZWUoJmJpbmQpOwogICAgICAgIH0KCiAgICAgICAgUnBjU3RyaW5nRnJlZVcoJnN0cmluZ19iaW5kaW5nKTsKICAgIH0KCiAgICBpZiAoc3RhdHVzICE9IFJQQ19TX09LKQogICAgewogICAgICAgIEVSUigiQ291bGRuJ3QgZ2V0IGJpbmRpbmcgZm9yIGVuZHBvaW50ICVzLCBzdGF0dXMgPSAlbGRcbiIsIGRlYnVnc3RyX3coZW5kcG9pbnQpLCBzdGF0dXMpOwogICAgICAgIHJldHVybiBIUkVTVUxUX0ZST01fV0lOMzIoc3RhdHVzKTsKICAgIH0KCiAgICBUaGlzID0gSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksIDAsIHNpemVvZigqVGhpcykpOwogICAgaWYgKCFUaGlzKQogICAgewogICAgICAgIFJwY0JpbmRpbmdGcmVlKCZiaW5kKTsKICAgICAgICByZXR1cm4gRV9PVVRPRk1FTU9SWTsKICAgIH0KCiAgICBUaGlzLT5zdXBlci5scFZ0YmwgPSAmQ2xpZW50UnBjQ2hhbm5lbEJ1ZmZlclZ0Ymw7CiAgICBUaGlzLT5zdXBlci5yZWZzID0gMTsKICAgIFRoaXMtPmJpbmQgPSBiaW5kOwogICAgYXBhcnRtZW50X2dldG94aWQoQ09NX0N1cnJlbnRBcHQoKSwgJlRoaXMtPm94aWQpOwogICAgVGhpcy0+ZGVzdF9jb250ZXh0ID0gZGVzdF9jb250ZXh0OwogICAgVGhpcy0+ZGVzdF9jb250ZXh0X2RhdGEgPSBkZXN0X2NvbnRleHRfZGF0YTsKCiAgICAqY2hhbiA9IChJUnBjQ2hhbm5lbEJ1ZmZlciopVGhpczsKCiAgICByZXR1cm4gU19PSzsKfQoKSFJFU1VMVCBSUENfQ3JlYXRlU2VydmVyQ2hhbm5lbChJUnBjQ2hhbm5lbEJ1ZmZlciAqKmNoYW4pCnsKICAgIFJwY0NoYW5uZWxCdWZmZXIgKlRoaXMgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgc2l6ZW9mKCpUaGlzKSk7CiAgICBpZiAoIVRoaXMpCiAgICAgICAgcmV0dXJuIEVfT1VUT0ZNRU1PUlk7CgogICAgVGhpcy0+bHBWdGJsID0gJlNlcnZlclJwY0NoYW5uZWxCdWZmZXJWdGJsOwogICAgVGhpcy0+cmVmcyA9IDE7CiAgICAKICAgICpjaGFuID0gKElScGNDaGFubmVsQnVmZmVyKilUaGlzOwoKICAgIHJldHVybiBTX09LOwp9CgoKdm9pZCBSUENfRXhlY3V0ZUNhbGwoc3RydWN0IGRpc3BhdGNoX3BhcmFtcyAqcGFyYW1zKQp7CiAgICBwYXJhbXMtPmhyID0gSVJwY1N0dWJCdWZmZXJfSW52b2tlKHBhcmFtcy0+c3R1YiwgcGFyYW1zLT5tc2csIHBhcmFtcy0+Y2hhbik7CgogICAgSVJwY1N0dWJCdWZmZXJfUmVsZWFzZShwYXJhbXMtPnN0dWIpOwogICAgSVJwY0NoYW5uZWxCdWZmZXJfUmVsZWFzZShwYXJhbXMtPmNoYW4pOwogICAgaWYgKHBhcmFtcy0+aGFuZGxlKSBTZXRFdmVudChwYXJhbXMtPmhhbmRsZSk7Cn0KCnN0YXRpYyB2b2lkIF9fUlBDX1NUVUIgZGlzcGF0Y2hfcnBjKFJQQ19NRVNTQUdFICptc2cpCnsKICAgIHN0cnVjdCBkaXNwYXRjaF9wYXJhbXMgKnBhcmFtczsKICAgIEFQQVJUTUVOVCAqYXB0OwogICAgSVBJRCBpcGlkOwogICAgSFJFU1VMVCBocjsKCiAgICBScGNCaW5kaW5nSW5xT2JqZWN0KG1zZy0+SGFuZGxlLCAmaXBpZCk7CgogICAgVFJBQ0UoImlwaWQgPSAlcywgaU1ldGhvZCA9ICVkXG4iLCBkZWJ1Z3N0cl9ndWlkKCZpcGlkKSwgbXNnLT5Qcm9jTnVtKTsKCiAgICBwYXJhbXMgPSBIZWFwQWxsb2MoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgc2l6ZW9mKCpwYXJhbXMpKTsKICAgIGlmICghcGFyYW1zKSByZXR1cm4gUnBjUmFpc2VFeGNlcHRpb24oRV9PVVRPRk1FTU9SWSk7CgogICAgaHIgPSBpcGlkX2dldF9kaXNwYXRjaF9wYXJhbXMoJmlwaWQsICZhcHQsICZwYXJhbXMtPnN0dWIsICZwYXJhbXMtPmNoYW4pOwogICAgaWYgKGhyICE9IFNfT0spCiAgICB7CiAgICAgICAgRVJSKCJubyBhcGFydG1lbnQgZm91bmQgZm9yIGlwaWQgJXNcbiIsIGRlYnVnc3RyX2d1aWQoJmlwaWQpKTsKICAgICAgICByZXR1cm4gUnBjUmFpc2VFeGNlcHRpb24oaHIpOwogICAgfQoKICAgIHBhcmFtcy0+bXNnID0gKFJQQ09MRU1FU1NBR0UgKiltc2c7CiAgICBwYXJhbXMtPnN0YXR1cyA9IFJQQ19TX09LOwogICAgcGFyYW1zLT5ociA9IFNfT0s7CiAgICBwYXJhbXMtPmhhbmRsZSA9IE5VTEw7CgogICAgLyogTm90ZTogdGhpcyBpcyB0aGUgaW1wb3J0YW50IGRpZmZlcmVuY2UgYmV0d2VlbiBTVEFzIGFuZCBNVEFzIC0gd2UKICAgICAqIGFsd2F5cyBleGVjdXRlIFJQQ3MgdG8gU1RBcyBpbiB0aGUgdGhyZWFkIHRoYXQgb3JpZ2luYWxseSBjcmVhdGVkIHRoZQogICAgICogYXBhcnRtZW50IChpLmUuIHRoZSBvbmUgdGhhdCBwdW1wcyBtZXNzYWdlcyB0byB0aGUgd2luZG93KSAqLwogICAgaWYgKCFhcHQtPm11bHRpX3RocmVhZGVkKQogICAgewogICAgICAgIHBhcmFtcy0+aGFuZGxlID0gQ3JlYXRlRXZlbnRXKE5VTEwsIEZBTFNFLCBGQUxTRSwgTlVMTCk7CgogICAgICAgIFRSQUNFKCJDYWxsaW5nIGFwYXJ0bWVudCB0aHJlYWQgMHglMDhseC4uLlxuIiwgYXB0LT50aWQpOwoKICAgICAgICBpZiAoUG9zdE1lc3NhZ2VXKGFwYXJ0bWVudF9nZXR3aW5kb3coYXB0KSwgRE1fRVhFQ1VURVJQQywgMCwgKExQQVJBTSlwYXJhbXMpKQogICAgICAgICAgICBXYWl0Rm9yU2luZ2xlT2JqZWN0KHBhcmFtcy0+aGFuZGxlLCBJTkZJTklURSk7CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgRVJSKCJQb3N0TWVzc2FnZSBmYWlsZWQgd2l0aCBlcnJvciAlbGRcbiIsIEdldExhc3RFcnJvcigpKTsKICAgICAgICAgICAgSVJwY0NoYW5uZWxCdWZmZXJfUmVsZWFzZShwYXJhbXMtPmNoYW4pOwogICAgICAgICAgICBJUnBjU3R1YkJ1ZmZlcl9SZWxlYXNlKHBhcmFtcy0+c3R1Yik7CiAgICAgICAgfQogICAgICAgIENsb3NlSGFuZGxlKHBhcmFtcy0+aGFuZGxlKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBCT09MIGpvaW5lZCA9IEZBTFNFOwogICAgICAgIGlmICghQ09NX0N1cnJlbnRJbmZvKCktPmFwdCkKICAgICAgICB7CiAgICAgICAgICAgIGFwYXJ0bWVudF9qb2lubXRhKCk7CiAgICAgICAgICAgIGpvaW5lZCA9IFRSVUU7CiAgICAgICAgfQogICAgICAgIFJQQ19FeGVjdXRlQ2FsbChwYXJhbXMpOwogICAgICAgIGlmIChqb2luZWQpCiAgICAgICAgewogICAgICAgICAgICBhcGFydG1lbnRfcmVsZWFzZShDT01fQ3VycmVudEluZm8oKS0+YXB0KTsKICAgICAgICAgICAgQ09NX0N1cnJlbnRJbmZvKCktPmFwdCA9IE5VTEw7CiAgICAgICAgfQogICAgfQoKICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIHBhcmFtcyk7CgogICAgYXBhcnRtZW50X3JlbGVhc2UoYXB0KTsKfQoKLyogc3R1YiByZWdpc3RyYXRpb24gKi8KSFJFU1VMVCBSUENfUmVnaXN0ZXJJbnRlcmZhY2UoUkVGSUlEIHJpaWQpCnsKICAgIHN0cnVjdCByZWdpc3RlcmVkX2lmICpyaWY7CiAgICBCT09MIGZvdW5kID0gRkFMU0U7CiAgICBIUkVTVUxUIGhyID0gU19PSzsKICAgIAogICAgVFJBQ0UoIiglcylcbiIsIGRlYnVnc3RyX2d1aWQocmlpZCkpOwoKICAgIEVudGVyQ3JpdGljYWxTZWN0aW9uKCZjc1JlZ0lmKTsKICAgIExJU1RfRk9SX0VBQ0hfRU5UUlkocmlmLCAmcmVnaXN0ZXJlZF9pbnRlcmZhY2VzLCBzdHJ1Y3QgcmVnaXN0ZXJlZF9pZiwgZW50cnkpCiAgICB7CiAgICAgICAgaWYgKElzRXF1YWxHVUlEKCZyaWYtPklmLkludGVyZmFjZUlkLlN5bnRheEdVSUQsIHJpaWQpKQogICAgICAgIHsKICAgICAgICAgICAgcmlmLT5yZWZzKys7CiAgICAgICAgICAgIGZvdW5kID0gVFJVRTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgfQogICAgaWYgKCFmb3VuZCkKICAgIHsKICAgICAgICBUUkFDRSgiQ3JlYXRpbmcgbmV3IGludGVyZmFjZVxuIik7CgogICAgICAgIHJpZiA9IEhlYXBBbGxvYyhHZXRQcm9jZXNzSGVhcCgpLCBIRUFQX1pFUk9fTUVNT1JZLCBzaXplb2YoKnJpZikpOwogICAgICAgIGlmIChyaWYpCiAgICAgICAgewogICAgICAgICAgICBSUENfU1RBVFVTIHN0YXR1czsKCiAgICAgICAgICAgIHJpZi0+cmVmcyA9IDE7CiAgICAgICAgICAgIHJpZi0+SWYuTGVuZ3RoID0gc2l6ZW9mKFJQQ19TRVJWRVJfSU5URVJGQUNFKTsKICAgICAgICAgICAgLyogUlBDIGludGVyZmFjZSBJRCA9IENPTSBpbnRlcmZhY2UgSUQgKi8KICAgICAgICAgICAgcmlmLT5JZi5JbnRlcmZhY2VJZC5TeW50YXhHVUlEID0gKnJpaWQ7CiAgICAgICAgICAgIHJpZi0+SWYuRGlzcGF0Y2hUYWJsZSA9ICZycGNfZGlzcGF0Y2g7CiAgICAgICAgICAgIC8qIGFsbCBvdGhlciBmaWVsZHMgYXJlIDAsIGluY2x1ZGluZyB0aGUgdmVyc2lvbiBhc0NPTSBvYmplY3RzCiAgICAgICAgICAgICAqIGFsd2F5cyBoYXZlIGEgdmVyc2lvbiBvZiAwLjAgKi8KICAgICAgICAgICAgc3RhdHVzID0gUnBjU2VydmVyUmVnaXN0ZXJJZkV4KAogICAgICAgICAgICAgICAgKFJQQ19JRl9IQU5ETEUpJnJpZi0+SWYsCiAgICAgICAgICAgICAgICBOVUxMLCBOVUxMLAogICAgICAgICAgICAgICAgUlBDX0lGX09MRSB8IFJQQ19JRl9BVVRPTElTVEVOLAogICAgICAgICAgICAgICAgUlBDX0NfTElTVEVOX01BWF9DQUxMU19ERUZBVUxULAogICAgICAgICAgICAgICAgTlVMTCk7CiAgICAgICAgICAgIGlmIChzdGF0dXMgPT0gUlBDX1NfT0spCiAgICAgICAgICAgICAgICBsaXN0X2FkZF90YWlsKCZyZWdpc3RlcmVkX2ludGVyZmFjZXMsICZyaWYtPmVudHJ5KTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBFUlIoIlJwY1NlcnZlclJlZ2lzdGVySWZFeCBmYWlsZWQgd2l0aCBlcnJvciAlbGRcbiIsIHN0YXR1cyk7CiAgICAgICAgICAgICAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCByaWYpOwogICAgICAgICAgICAgICAgaHIgPSBIUkVTVUxUX0ZST01fV0lOMzIoc3RhdHVzKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgICAgIGhyID0gRV9PVVRPRk1FTU9SWTsKICAgIH0KICAgIExlYXZlQ3JpdGljYWxTZWN0aW9uKCZjc1JlZ0lmKTsKICAgIHJldHVybiBocjsKfQoKLyogc3R1YiB1bnJlZ2lzdHJhdGlvbiAqLwp2b2lkIFJQQ19VbnJlZ2lzdGVySW50ZXJmYWNlKFJFRklJRCByaWlkKQp7CiAgICBzdHJ1Y3QgcmVnaXN0ZXJlZF9pZiAqcmlmOwogICAgRW50ZXJDcml0aWNhbFNlY3Rpb24oJmNzUmVnSWYpOwogICAgTElTVF9GT1JfRUFDSF9FTlRSWShyaWYsICZyZWdpc3RlcmVkX2ludGVyZmFjZXMsIHN0cnVjdCByZWdpc3RlcmVkX2lmLCBlbnRyeSkKICAgIHsKICAgICAgICBpZiAoSXNFcXVhbEdVSUQoJnJpZi0+SWYuSW50ZXJmYWNlSWQuU3ludGF4R1VJRCwgcmlpZCkpCiAgICAgICAgewogICAgICAgICAgICBpZiAoIS0tcmlmLT5yZWZzKQogICAgICAgICAgICB7CiNpZiAwIC8qIHRoaXMgaXMgYSBzdHViIGluIGJ1aWx0aW4gYW5kIHNwYW1zIHRoZSBjb25zb2xlIHdpdGggRklYTUUncyAqLwogICAgICAgICAgICAgICAgSUlEIGlpZCA9ICpyaWlkOyAvKiBScGNTZXJ2ZXJVbnJlZ2lzdGVySWYgZG9lc24ndCB0YWtlIGNvbnN0IElJRCAqLwogICAgICAgICAgICAgICAgUnBjU2VydmVyVW5yZWdpc3RlcklmKChSUENfSUZfSEFORExFKSZyaWYtPklmLCAmaWlkLCAwKTsKICAgICAgICAgICAgICAgIGxpc3RfcmVtb3ZlKCZyaWYtPmVudHJ5KTsKICAgICAgICAgICAgICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIHJpZik7CiNlbmRpZgogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KICAgIExlYXZlQ3JpdGljYWxTZWN0aW9uKCZjc1JlZ0lmKTsKfQoKLyogbWFrZSB0aGUgYXBhcnRtZW50IHJlYWNoYWJsZSBieSBvdGhlciB0aHJlYWRzIGFuZCBwcm9jZXNzZXMgYW5kIGNyZWF0ZSB0aGUKICogSVJlbVVua25vd24gb2JqZWN0ICovCnZvaWQgUlBDX1N0YXJ0UmVtb3Rpbmcoc3RydWN0IGFwYXJ0bWVudCAqYXB0KQp7CiAgICBpZiAoIUludGVybG9ja2VkRXhjaGFuZ2UoJmFwdC0+cmVtb3Rpbmdfc3RhcnRlZCwgVFJVRSkpCiAgICB7CiAgICAgICAgV0NIQVIgZW5kcG9pbnRbMjAwXTsKICAgICAgICBSUENfU1RBVFVTIHN0YXR1czsKCiAgICAgICAgZ2V0X3JwY19lbmRwb2ludChlbmRwb2ludCwgJmFwdC0+b3hpZCk7CiAgICAKICAgICAgICBzdGF0dXMgPSBScGNTZXJ2ZXJVc2VQcm90c2VxRXBXKAogICAgICAgICAgICB3c3pScGNUcmFuc3BvcnQsCiAgICAgICAgICAgIFJQQ19DX1BST1RTRVFfTUFYX1JFUVNfREVGQVVMVCwKICAgICAgICAgICAgZW5kcG9pbnQsCiAgICAgICAgICAgIE5VTEwpOwogICAgICAgIGlmIChzdGF0dXMgIT0gUlBDX1NfT0spCiAgICAgICAgICAgIEVSUigiQ291bGRuJ3QgcmVnaXN0ZXIgZW5kcG9pbnQgJXNcbiIsIGRlYnVnc3RyX3coZW5kcG9pbnQpKTsKCiAgICAgICAgLyogRklYTUU6IG1vdmUgcmVtb3RlIHVua25vd24gZXhwb3J0aW5nIGludG8gdGhpcyBmdW5jdGlvbiAqLwogICAgfQogICAgc3RhcnRfYXBhcnRtZW50X3JlbW90ZV91bmtub3duKCk7Cn0KCgpzdGF0aWMgSFJFU1VMVCBjcmVhdGVfc2VydmVyKFJFRkNMU0lEIHJjbHNpZCkKewogICAgc3RhdGljIGNvbnN0IFdDSEFSICB3c3pMb2NhbFNlcnZlcjMyW10gPSB7ICdMJywnbycsJ2MnLCdhJywnbCcsJ1MnLCdlJywncicsJ3YnLCdlJywncicsJzMnLCcyJywwIH07CiAgICBzdGF0aWMgY29uc3QgV0NIQVIgIGVtYmVkZGluZ1tdID0geyAnICcsICctJywnRScsJ20nLCdiJywnZScsJ2QnLCdkJywnaScsJ24nLCdnJywwIH07CiAgICBIS0VZICAgICAgICAgICAgICAgIGtleTsKICAgIEhSRVNVTFQgICAgICAgICAgICAgaHJlczsKICAgIFdDSEFSICAgICAgICAgICAgICAgY29tbWFuZFtNQVhfUEFUSCtzaXplb2YoZW1iZWRkaW5nKS9zaXplb2YoV0NIQVIpXTsKICAgIERXT1JEICAgICAgICAgICAgICAgc2l6ZSA9IChNQVhfUEFUSCsxKSAqIHNpemVvZihXQ0hBUik7CiAgICBTVEFSVFVQSU5GT1cgICAgICAgIHNpbmZvOwogICAgUFJPQ0VTU19JTkZPUk1BVElPTiBwaW5mbzsKCiAgICBocmVzID0gQ09NX09wZW5LZXlGb3JDTFNJRChyY2xzaWQsIHdzekxvY2FsU2VydmVyMzIsIEtFWV9SRUFELCAma2V5KTsKICAgIGlmIChGQUlMRUQoaHJlcykpIHsKICAgICAgICBFUlIoImNsYXNzICVzIG5vdCByZWdpc3RlcmVkXG4iLCBkZWJ1Z3N0cl9ndWlkKHJjbHNpZCkpOwogICAgICAgIHJldHVybiBocmVzOwogICAgfQoKICAgIGhyZXMgPSBSZWdRdWVyeVZhbHVlRXhXKGtleSwgTlVMTCwgTlVMTCwgTlVMTCwgKExQQllURSljb21tYW5kLCAmc2l6ZSk7CiAgICBSZWdDbG9zZUtleShrZXkpOwogICAgaWYgKGhyZXMpIHsKICAgICAgICBXQVJOKCJObyBkZWZhdWx0IHZhbHVlIGZvciBMb2NhbFNlcnZlcjMyIGtleVxuIik7CiAgICAgICAgcmV0dXJuIFJFR0RCX0VfQ0xBU1NOT1RSRUc7IC8qIEZJWE1FOiBjaGVjayByZXR2YWwgKi8KICAgIH0KCiAgICBtZW1zZXQoJnNpbmZvLDAsc2l6ZW9mKHNpbmZvKSk7CiAgICBzaW5mby5jYiA9IHNpemVvZihzaW5mbyk7CgogICAgLyogRVhFIHNlcnZlcnMgYXJlIHN0YXJ0ZWQgd2l0aCB0aGUgLUVtYmVkZGluZyBzd2l0Y2guICovCgogICAgc3RyY2F0Vyhjb21tYW5kLCBlbWJlZGRpbmcpOwoKICAgIFRSQUNFKCJhY3RpdmF0aW5nIGxvY2FsIHNlcnZlciAlcyBmb3IgJXNcbiIsIGRlYnVnc3RyX3coY29tbWFuZCksIGRlYnVnc3RyX2d1aWQocmNsc2lkKSk7CgogICAgLyogRklYTUU6IFdpbjIwMDMgc3VwcG9ydHMgYSBTZXJ2ZXJFeGVjdXRhYmxlIHZhbHVlIHRoYXQgaXMgcGFzc2VkIGludG8KICAgICAqIENyZWF0ZVByb2Nlc3MgKi8KICAgIGlmICghQ3JlYXRlUHJvY2Vzc1coTlVMTCwgY29tbWFuZCwgTlVMTCwgTlVMTCwgRkFMU0UsIDAsIE5VTEwsIE5VTEwsICZzaW5mbywgJnBpbmZvKSkgewogICAgICAgIFdBUk4oImZhaWxlZCB0byBydW4gbG9jYWwgc2VydmVyICVzXG4iLCBkZWJ1Z3N0cl93KGNvbW1hbmQpKTsKICAgICAgICByZXR1cm4gSFJFU1VMVF9GUk9NX1dJTjMyKEdldExhc3RFcnJvcigpKTsKICAgIH0KICAgIENsb3NlSGFuZGxlKHBpbmZvLmhQcm9jZXNzKTsKICAgIENsb3NlSGFuZGxlKHBpbmZvLmhUaHJlYWQpOwoKICAgIHJldHVybiBTX09LOwp9CgovKgogKiBzdGFydF9sb2NhbF9zZXJ2aWNlKCkgIC0gc3RhcnQgYSBzZXJ2aWNlIGdpdmVuIGl0cyBuYW1lIGFuZCBwYXJhbWV0ZXJzCiAqLwpzdGF0aWMgRFdPUkQgc3RhcnRfbG9jYWxfc2VydmljZShMUENXU1RSIG5hbWUsIERXT1JEIG51bSwgTFBDV1NUUiAqcGFyYW1zKQp7CiAgICBTQ19IQU5ETEUgaGFuZGxlLCBoc3ZjOwogICAgRFdPUkQgICAgIHIgPSBFUlJPUl9GVU5DVElPTl9GQUlMRUQ7CgogICAgVFJBQ0UoIlN0YXJ0aW5nIHNlcnZpY2UgJXMgJWxkIHBhcmFtc1xuIiwgZGVidWdzdHJfdyhuYW1lKSwgbnVtKTsKCiAgICBoYW5kbGUgPSBPcGVuU0NNYW5hZ2VyVyhOVUxMLCBOVUxMLCBTQ19NQU5BR0VSX0NPTk5FQ1QpOwogICAgaWYgKCFoYW5kbGUpCiAgICAgICAgcmV0dXJuIHI7CiAgICBoc3ZjID0gT3BlblNlcnZpY2VXKGhhbmRsZSwgbmFtZSwgU0VSVklDRV9TVEFSVCk7CiAgICBpZiAoaHN2YykKICAgIHsKICAgICAgICBpZihTdGFydFNlcnZpY2VXKGhzdmMsIG51bSwgcGFyYW1zKSkKICAgICAgICAgICAgciA9IEVSUk9SX1NVQ0NFU1M7CiAgICAgICAgZWxzZQogICAgICAgICAgICByID0gR2V0TGFzdEVycm9yKCk7CiAgICAgICAgaWYgKHIgPT0gRVJST1JfU0VSVklDRV9BTFJFQURZX1JVTk5JTkcpCiAgICAgICAgICAgIHIgPSBFUlJPUl9TVUNDRVNTOwogICAgICAgIENsb3NlU2VydmljZUhhbmRsZShoc3ZjKTsKICAgIH0KICAgIGVsc2UKICAgICAgICByID0gR2V0TGFzdEVycm9yKCk7CiAgICBDbG9zZVNlcnZpY2VIYW5kbGUoaGFuZGxlKTsKCiAgICBUUkFDRSgiU3RhcnRTZXJ2aWNlIHJldHVybmVkIGVycm9yICVsZCAoJXMpXG4iLCByLCAociA9PSBFUlJPUl9TVUNDRVNTKSA/ICJvayI6ImZhaWxlZCIpOwoKICAgIHJldHVybiByOwp9CgovKgogKiBjcmVhdGVfbG9jYWxfc2VydmljZSgpICAtIHN0YXJ0IGEgQ09NIHNlcnZlciBpbiBhIHNlcnZpY2UKICoKICogICBUbyBzdGFydCBhIExvY2FsIFNlcnZpY2UsIHdlIHJlYWQgdGhlIEFwcElEIHZhbHVlIHVuZGVyCiAqIHRoZSBjbGFzcydzIENMU0lEIGtleSwgdGhlbiBvcGVuIHRoZSBIS0NSXFxBcHBJZCBrZXkgc3BlY2lmaWVkCiAqIHRoZXJlIGFuZCBjaGVjayBmb3IgYSBMb2NhbFNlcnZpY2UgdmFsdWUuCiAqCiAqIE5vdGU6ICBMb2NhbCBTZXJ2aWNlcyBhcmUgbm90IHN1cHBvcnRlZCB1bmRlciBXaW5kb3dzIDl4CiAqLwpzdGF0aWMgSFJFU1VMVCBjcmVhdGVfbG9jYWxfc2VydmljZShSRUZDTFNJRCByY2xzaWQpCnsKICAgIEhSRVNVTFQgaHJlczsKICAgIFdDSEFSIGJ1ZltDSEFSU19JTl9HVUlEXSwga2V5bmFtZVs1MF07CiAgICBzdGF0aWMgY29uc3QgV0NIQVIgc3pBcHBJZFtdID0geyAnQScsJ3AnLCdwJywnSScsJ2QnLDAgfTsKICAgIHN0YXRpYyBjb25zdCBXQ0hBUiBzekFwcElkS2V5W10gPSB7ICdBJywncCcsJ3AnLCdJJywnZCcsJ1xcJywwIH07CiAgICBzdGF0aWMgY29uc3QgV0NIQVIgc3pMb2NhbFNlcnZpY2VbXSA9IHsgJ0wnLCdvJywnYycsJ2EnLCdsJywnUycsJ2UnLCdyJywndicsJ2knLCdjJywnZScsMCB9OwogICAgc3RhdGljIGNvbnN0IFdDSEFSIHN6U2VydmljZVBhcmFtc1tdID0geydTJywnZScsJ3InLCd2JywnaScsJ2MnLCdlJywnUCcsJ2EnLCdyJywnYScsJ20nLCdzJywwfTsKICAgIEhLRVkgaGtleTsKICAgIExPTkcgcjsKICAgIERXT1JEIHR5cGUsIHN6OwoKICAgIFRSQUNFKCJBdHRlbXB0aW5nIHRvIHN0YXJ0IExvY2FsIHNlcnZpY2UgZm9yICVzXG4iLCBkZWJ1Z3N0cl9ndWlkKHJjbHNpZCkpOwoKICAgIC8qIHJlYWQgdGhlIEFwcElEIHZhbHVlIHVuZGVyIHRoZSBjbGFzcydzIGtleSAqLwogICAgaHJlcyA9IENPTV9PcGVuS2V5Rm9yQ0xTSUQocmNsc2lkLCBzekFwcElkLCBLRVlfUkVBRCwgJmhrZXkpOwogICAgaWYgKEZBSUxFRChocmVzKSkKICAgICAgICByZXR1cm4gaHJlczsKICAgIHN6ID0gc2l6ZW9mIGJ1ZjsKICAgIHIgPSBSZWdRdWVyeVZhbHVlRXhXKGhrZXksIE5VTEwsIE5VTEwsICZ0eXBlLCAoTFBCWVRFKWJ1ZiwgJnN6KTsKICAgIFJlZ0Nsb3NlS2V5KGhrZXkpOwogICAgaWYgKHIhPUVSUk9SX1NVQ0NFU1MgfHwgdHlwZSE9UkVHX1NaKQogICAgICAgIHJldHVybiBocmVzOwoKICAgIC8qIHJlYWQgdGhlIExvY2FsU2VydmljZSBhbmQgU2VydmljZVBhcmFtZXRlcnMgdmFsdWVzIGZyb20gdGhlIEFwcElEIGtleSAqLwogICAgc3RyY3B5VyhrZXluYW1lLCBzekFwcElkS2V5KTsKICAgIHN0cmNhdFcoa2V5bmFtZSwgYnVmKTsKICAgIHIgPSBSZWdPcGVuS2V5RXhXKEhLRVlfQ0xBU1NFU19ST09ULCBrZXluYW1lLCAwLCBLRVlfUkVBRCwgJmhrZXkpOwogICAgaWYgKHIhPUVSUk9SX1NVQ0NFU1MpCiAgICAgICAgcmV0dXJuIGhyZXM7CiAgICBzeiA9IHNpemVvZiBidWY7CiAgICByID0gUmVnUXVlcnlWYWx1ZUV4Vyhoa2V5LCBzekxvY2FsU2VydmljZSwgTlVMTCwgJnR5cGUsIChMUEJZVEUpYnVmLCAmc3opOwogICAgaWYgKHI9PUVSUk9SX1NVQ0NFU1MgJiYgdHlwZT09UkVHX1NaKQogICAgewogICAgICAgIERXT1JEIG51bV9hcmdzID0gMDsKICAgICAgICBMUFdTVFIgYXJnc1sxXSA9IHsgTlVMTCB9OwoKICAgICAgICAvKgogICAgICAgICAqIEZJWE1FOiBJJ20gbm90IHJlYWxseSBzdXJlIGhvdyB0byBkZWFsIHdpdGggdGhlIHNlcnZpY2UgcGFyYW1ldGVycy4KICAgICAgICAgKiAgICAgICAgSSBzdXNwZWN0IHRoYXQgdGhlIHN0cmluZyByZXR1cm5lZCBmcm9tIFJlZ1F1ZXJ5VmFsdWVFeFcKICAgICAgICAgKiAgICAgICAgc2hvdWxkIGJlIHNwbGl0IGludG8gYSBudW1iZXIgb2YgYXJndW1lbnRzIGJ5IHNwYWNlcy4KICAgICAgICAgKiAgICAgICAgSXQgd291bGQgbWFrZSBtb3JlIHNlbnNlIGlmIFNlcnZpY2VQYXJhbXMgY29udGFpbmVkIGEKICAgICAgICAgKiAgICAgICAgUkVHX01VTFRJX1NaIGhlcmUsIGJ1dCBpdCdzIGEgUkVHX1NaIGZvciB0aGUgc2VydmljZXMKICAgICAgICAgKiAgICAgICAgdGhhdCBJJ20gaW50ZXJlc3RlZCBpbiBmb3IgdGhlIG1vbWVudC4KICAgICAgICAgKi8KICAgICAgICByID0gUmVnUXVlcnlWYWx1ZUV4Vyhoa2V5LCBzelNlcnZpY2VQYXJhbXMsIE5VTEwsICZ0eXBlLCBOVUxMLCAmc3opOwogICAgICAgIGlmIChyID09IEVSUk9SX1NVQ0NFU1MgJiYgdHlwZSA9PSBSRUdfU1ogJiYgc3opCiAgICAgICAgewogICAgICAgICAgICBhcmdzWzBdID0gSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksSEVBUF9aRVJPX01FTU9SWSxzeik7CiAgICAgICAgICAgIG51bV9hcmdzKys7CiAgICAgICAgICAgIFJlZ1F1ZXJ5VmFsdWVFeFcoaGtleSwgc3pTZXJ2aWNlUGFyYW1zLCBOVUxMLCAmdHlwZSwgKExQQllURSlhcmdzWzBdLCAmc3opOwogICAgICAgIH0KICAgICAgICByID0gc3RhcnRfbG9jYWxfc2VydmljZShidWYsIG51bV9hcmdzLCAoTFBDV1NUUiAqKWFyZ3MpOwogICAgICAgIGlmIChyPT1FUlJPUl9TVUNDRVNTKQogICAgICAgICAgICBocmVzID0gU19PSzsKICAgICAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLDAsYXJnc1swXSk7CiAgICB9CiAgICBSZWdDbG9zZUtleShoa2V5KTsKICAgICAgICAKICAgIHJldHVybiBocmVzOwp9CgoKc3RhdGljIHZvaWQgZ2V0X2xvY2Fsc2VydmVyX3BpcGVfbmFtZShXQ0hBUiAqcGlwZWZuLCBSRUZDTFNJRCByY2xzaWQpCnsKICAgIHN0YXRpYyBjb25zdCBXQ0hBUiB3c3pQaXBlUmVmW10gPSB7J1xcJywnXFwnLCcuJywnXFwnLCdwJywnaScsJ3AnLCdlJywnXFwnLDB9OwogICAgc3RyY3B5VyhwaXBlZm4sIHdzelBpcGVSZWYpOwogICAgU3RyaW5nRnJvbUdVSUQyKHJjbHNpZCwgcGlwZWZuICsgc2l6ZW9mKHdzelBpcGVSZWYpL3NpemVvZih3c3pQaXBlUmVmWzBdKSAtIDEsIENIQVJTX0lOX0dVSUQpOwp9CgovKiBGSVhNRTogc2hvdWxkIGNhbGwgdG8gcnBjc3MgaW5zdGVhZCAqLwpIUkVTVUxUIFJQQ19HZXRMb2NhbENsYXNzT2JqZWN0KFJFRkNMU0lEIHJjbHNpZCwgUkVGSUlEIGlpZCwgTFBWT0lEICpwcHYpCnsKICAgIEhSRVNVTFQgICAgICAgIGhyZXM7CiAgICBIQU5ETEUgICAgICAgICBoUGlwZTsKICAgIFdDSEFSICAgICAgICAgIHBpcGVmblsxMDBdOwogICAgRFdPUkQgICAgICAgICAgcmVzLCBidWZmZXJsZW47CiAgICBjaGFyICAgICAgICAgICBtYXJzaGFsYnVmZmVyWzIwMF07CiAgICBJU3RyZWFtICAgICAgICpwU3RtOwogICAgTEFSR0VfSU5URUdFUiAgc2Vla3RvOwogICAgVUxBUkdFX0lOVEVHRVIgbmV3cG9zOwogICAgaW50ICAgICAgICAgICAgdHJpZXMgPSAwOwoKICAgIHN0YXRpYyBjb25zdCBpbnQgTUFYVFJJRVMgPSAzMDsgLyogMzAgc2Vjb25kcyAqLwoKICAgIFRSQUNFKCJyY2xzaWQ9JXMsIGlpZD0lc1xuIiwgZGVidWdzdHJfZ3VpZChyY2xzaWQpLCBkZWJ1Z3N0cl9ndWlkKGlpZCkpOwoKICAgIGdldF9sb2NhbHNlcnZlcl9waXBlX25hbWUocGlwZWZuLCByY2xzaWQpOwoKICAgIHdoaWxlICh0cmllcysrIDwgTUFYVFJJRVMpIHsKICAgICAgICBUUkFDRSgid2FpdGluZyBmb3IgJXNcbiIsIGRlYnVnc3RyX3cocGlwZWZuKSk7CiAgICAgIAogICAgICAgIFdhaXROYW1lZFBpcGVXKCBwaXBlZm4sIE5NUFdBSVRfV0FJVF9GT1JFVkVSICk7CiAgICAgICAgaFBpcGUgPSBDcmVhdGVGaWxlVyhwaXBlZm4sIEdFTkVSSUNfUkVBRCB8IEdFTkVSSUNfV1JJVEUsIDAsIE5VTEwsIE9QRU5fRVhJU1RJTkcsIDAsIDApOwogICAgICAgIGlmIChoUGlwZSA9PSBJTlZBTElEX0hBTkRMRV9WQUxVRSkgewogICAgICAgICAgICBpZiAodHJpZXMgPT0gMSkgewogICAgICAgICAgICAgICAgaWYgKCAoaHJlcyA9IGNyZWF0ZV9sb2NhbF9zZXJ2aWNlKHJjbHNpZCkpICYmCiAgICAgICAgICAgICAgICAgICAgIChocmVzID0gY3JlYXRlX3NlcnZlcihyY2xzaWQpKSApCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGhyZXM7CiAgICAgICAgICAgICAgICBTbGVlcCgxMDAwKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIFdBUk4oIkNvbm5lY3RpbmcgdG8gJXMsIG5vIHJlc3BvbnNlIHlldCwgcmV0cnlpbmc6IGxlIGlzICVseFxuIiwgZGVidWdzdHJfdyhwaXBlZm4pLCBHZXRMYXN0RXJyb3IoKSk7CiAgICAgICAgICAgICAgICBTbGVlcCgxMDAwKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgYnVmZmVybGVuID0gMDsKICAgICAgICBpZiAoIVJlYWRGaWxlKGhQaXBlLG1hcnNoYWxidWZmZXIsc2l6ZW9mKG1hcnNoYWxidWZmZXIpLCZidWZmZXJsZW4sTlVMTCkpIHsKICAgICAgICAgICAgRklYTUUoIkZhaWxlZCB0byByZWFkIG1hcnNoYWwgaWQgZnJvbSBjbGFzc2ZhY3Rvcnkgb2YgJXMuXG4iLGRlYnVnc3RyX2d1aWQocmNsc2lkKSk7CiAgICAgICAgICAgIFNsZWVwKDEwMDApOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgVFJBQ0UoInJlYWQgbWFyc2hhbCBpZCBmcm9tIHBpcGVcbiIpOwogICAgICAgIENsb3NlSGFuZGxlKGhQaXBlKTsKICAgICAgICBicmVhazsKICAgIH0KICAgIAogICAgaWYgKHRyaWVzID49IE1BWFRSSUVTKQogICAgICAgIHJldHVybiBFX05PSU5URVJGQUNFOwogICAgCiAgICBocmVzID0gQ3JlYXRlU3RyZWFtT25IR2xvYmFsKDAsVFJVRSwmcFN0bSk7CiAgICBpZiAoaHJlcykgcmV0dXJuIGhyZXM7CiAgICBocmVzID0gSVN0cmVhbV9Xcml0ZShwU3RtLG1hcnNoYWxidWZmZXIsYnVmZmVybGVuLCZyZXMpOwogICAgaWYgKGhyZXMpIGdvdG8gb3V0OwogICAgc2Vla3RvLnUuTG93UGFydCA9IDA7c2Vla3RvLnUuSGlnaFBhcnQgPSAwOwogICAgaHJlcyA9IElTdHJlYW1fU2VlayhwU3RtLHNlZWt0byxTRUVLX1NFVCwmbmV3cG9zKTsKICAgIAogICAgVFJBQ0UoInVubWFyc2hhbGxpbmcgY2xhc3NmYWN0b3J5XG4iKTsKICAgIGhyZXMgPSBDb1VubWFyc2hhbEludGVyZmFjZShwU3RtLCZJSURfSUNsYXNzRmFjdG9yeSxwcHYpOwpvdXQ6CiAgICBJU3RyZWFtX1JlbGVhc2UocFN0bSk7CiAgICByZXR1cm4gaHJlczsKfQoKCnN0cnVjdCBsb2NhbF9zZXJ2ZXJfcGFyYW1zCnsKICAgIENMU0lEIGNsc2lkOwogICAgSVN0cmVhbSAqc3RyZWFtOwp9OwoKLyogRklYTUU6IHNob3VsZCBjYWxsIHRvIHJwY3NzIGluc3RlYWQgKi8Kc3RhdGljIERXT1JEIFdJTkFQSSBsb2NhbF9zZXJ2ZXJfdGhyZWFkKExQVk9JRCBwYXJhbSkKewogICAgc3RydWN0IGxvY2FsX3NlcnZlcl9wYXJhbXMgKiBsc3AgPSAoc3RydWN0IGxvY2FsX3NlcnZlcl9wYXJhbXMgKilwYXJhbTsKICAgIEhBTkRMRQkJaFBpcGU7CiAgICBXQ0hBUiAJCXBpcGVmblsxMDBdOwogICAgSFJFU1VMVAkJaHJlczsKICAgIElTdHJlYW0JCSpwU3RtID0gbHNwLT5zdHJlYW07CiAgICBTVEFUU1RHCQlzdHN0ZzsKICAgIHVuc2lnbmVkIGNoYXIJKmJ1ZmZlcjsKICAgIGludCAJCWJ1ZmxlbjsKICAgIExBUkdFX0lOVEVHRVIJc2Vla3RvOwogICAgVUxBUkdFX0lOVEVHRVIJbmV3cG9zOwogICAgVUxPTkcJCXJlczsKCiAgICBUUkFDRSgiU3RhcnRpbmcgdGhyZWFkZXIgZm9yICVzLlxuIixkZWJ1Z3N0cl9ndWlkKCZsc3AtPmNsc2lkKSk7CgogICAgZ2V0X2xvY2Fsc2VydmVyX3BpcGVfbmFtZShwaXBlZm4sICZsc3AtPmNsc2lkKTsKCiAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCBsc3ApOwoKICAgIGhQaXBlID0gQ3JlYXRlTmFtZWRQaXBlVyggcGlwZWZuLCBQSVBFX0FDQ0VTU19EVVBMRVgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBJUEVfVFlQRV9CWVRFfFBJUEVfV0FJVCwgUElQRV9VTkxJTUlURURfSU5TVEFOQ0VTLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA0MDk2LCA0MDk2LCA1MDAgLyogMC41IHNlY29uZCB0aW1lb3V0ICovLCBOVUxMICk7CiAgICAKICAgIGlmIChoUGlwZSA9PSBJTlZBTElEX0hBTkRMRV9WQUxVRSkKICAgIHsKICAgICAgICBGSVhNRSgicGlwZSBjcmVhdGlvbiBmYWlsZWQgZm9yICVzLCBsZSBpcyAlbGRcbiIsIGRlYnVnc3RyX3cocGlwZWZuKSwgR2V0TGFzdEVycm9yKCkpOwogICAgICAgIHJldHVybiAxOwogICAgfQogICAgCiAgICB3aGlsZSAoMSkgewogICAgICAgIGlmICghQ29ubmVjdE5hbWVkUGlwZShoUGlwZSxOVUxMKSkgewogICAgICAgICAgICBFUlIoIkZhaWx1cmUgZHVyaW5nIENvbm5lY3ROYW1lZFBpcGUgJWxkLCBBQk9SVCFcbiIsR2V0TGFzdEVycm9yKCkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIFRSQUNFKCJtYXJzaGFsbGluZyBJQ2xhc3NGYWN0b3J5IHRvIGNsaWVudFxuIik7CiAgICAgICAgCiAgICAgICAgaHJlcyA9IElTdHJlYW1fU3RhdChwU3RtLCZzdHN0ZywwKTsKICAgICAgICBpZiAoaHJlcykgcmV0dXJuIGhyZXM7CgogICAgICAgIGJ1ZmxlbiA9IHN0c3RnLmNiU2l6ZS51Lkxvd1BhcnQ7CiAgICAgICAgYnVmZmVyID0gSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksMCxidWZsZW4pOwogICAgICAgIHNlZWt0by51Lkxvd1BhcnQgPSAwOwogICAgICAgIHNlZWt0by51LkhpZ2hQYXJ0ID0gMDsKICAgICAgICBocmVzID0gSVN0cmVhbV9TZWVrKHBTdG0sc2Vla3RvLFNFRUtfU0VULCZuZXdwb3MpOwogICAgICAgIGlmIChocmVzKSB7CiAgICAgICAgICAgIEZJWE1FKCJJU3RyZWFtX1NlZWsgZmFpbGVkLCAlbHhcbiIsaHJlcyk7CiAgICAgICAgICAgIHJldHVybiBocmVzOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBocmVzID0gSVN0cmVhbV9SZWFkKHBTdG0sYnVmZmVyLGJ1ZmxlbiwmcmVzKTsKICAgICAgICBpZiAoaHJlcykgewogICAgICAgICAgICBGSVhNRSgiU3RyZWFtIFJlYWQgZmFpbGVkLCAlbHhcbiIsaHJlcyk7CiAgICAgICAgICAgIHJldHVybiBocmVzOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBXcml0ZUZpbGUoaFBpcGUsYnVmZmVyLGJ1ZmxlbiwmcmVzLE5VTEwpOwogICAgICAgIEZsdXNoRmlsZUJ1ZmZlcnMoaFBpcGUpOwogICAgICAgIERpc2Nvbm5lY3ROYW1lZFBpcGUoaFBpcGUpOwoKICAgICAgICBUUkFDRSgiZG9uZSBtYXJzaGFsbGluZyBJQ2xhc3NGYWN0b3J5XG4iKTsKICAgIH0KICAgIENsb3NlSGFuZGxlKGhQaXBlKTsKICAgIElTdHJlYW1fUmVsZWFzZShwU3RtKTsKICAgIHJldHVybiAwOwp9Cgp2b2lkIFJQQ19TdGFydExvY2FsU2VydmVyKFJFRkNMU0lEIGNsc2lkLCBJU3RyZWFtICpzdHJlYW0pCnsKICAgIERXT1JEIHRpZDsKICAgIEhBTkRMRSB0aHJlYWQ7CiAgICBzdHJ1Y3QgbG9jYWxfc2VydmVyX3BhcmFtcyAqbHNwID0gSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksIDAsIHNpemVvZigqbHNwKSk7CgogICAgbHNwLT5jbHNpZCA9ICpjbHNpZDsKICAgIGxzcC0+c3RyZWFtID0gc3RyZWFtOwoKICAgIHRocmVhZCA9IENyZWF0ZVRocmVhZChOVUxMLCAwLCBsb2NhbF9zZXJ2ZXJfdGhyZWFkLCBsc3AsIDAsICZ0aWQpOwogICAgQ2xvc2VIYW5kbGUodGhyZWFkKTsKICAgIC8qIEZJWE1FOiBmYWlsdXJlIGhhbmRsaW5nICovCn0K