LyoKICogIFN5c3RlbSBNSUIgZ3JvdXAgaW1wbGVtZW50YXRpb24gLSBzeXN0ZW0uYwogKgogKi8KLyogUG9ydGlvbnMgb2YgdGhpcyBmaWxlIGFyZSBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29weXJpZ2h0KHMpLiAgU2VlCiAqIHRoZSBOZXQtU05NUCdzIENPUFlJTkcgZmlsZSBmb3IgbW9yZSBkZXRhaWxzIGFuZCBvdGhlciBjb3B5cmlnaHRzCiAqIHRoYXQgbWF5IGFwcGx5OgogKi8KLyoKICogUG9ydGlvbnMgb2YgdGhpcyBmaWxlIGFyZSBjb3B5cmlnaHRlZCBieToKICogQ29weXJpZ2h0IKkgMjAwMyBTdW4gTWljcm9zeXN0ZW1zLCBJbmMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiAqIFVzZSBpcyBzdWJqZWN0IHRvIGxpY2Vuc2UgdGVybXMgc3BlY2lmaWVkIGluIHRoZSBDT1BZSU5HIGZpbGUKICogZGlzdHJpYnV0ZWQgd2l0aCB0aGUgTmV0LVNOTVAgcGFja2FnZS4KICovCgojaW5jbHVkZSA8bmV0LXNubXAvbmV0LXNubXAtY29uZmlnLmg+CgojaWYgSEFWRV9TVERMSUJfSAojaW5jbHVkZSA8c3RkbGliLmg+CiNlbmRpZgojaWZkZWYgSEFWRV9VTklTVERfSAojaW5jbHVkZSA8dW5pc3RkLmg+CiNlbmRpZgojaWYgSEFWRV9TVFJJTkdfSAojaW5jbHVkZSA8c3RyaW5nLmg+CiNlbHNlCiNpbmNsdWRlIDxzdHJpbmdzLmg+CiNlbmRpZgojaW5jbHVkZSA8c3lzL3R5cGVzLmg+CgojaWYgSEFWRV9VVFNOQU1FX0gKI2luY2x1ZGUgPHV0c25hbWUuaD4KI2Vsc2UKI2lmIEhBVkVfU1lTX1VUU05BTUVfSAojaW5jbHVkZSA8c3lzL3V0c25hbWUuaD4KI2VuZGlmCiNlbmRpZgoKI2luY2x1ZGUgPG5ldC1zbm1wL25ldC1zbm1wLWluY2x1ZGVzLmg+CiNpbmNsdWRlIDxuZXQtc25tcC9hZ2VudC9uZXQtc25tcC1hZ2VudC1pbmNsdWRlcy5oPgojaW5jbHVkZSA8bmV0LXNubXAvYWdlbnQvc3lzT1JUYWJsZS5oPgoKI2luY2x1ZGUgInV0aWxfZnVuY3MuaCIKI2luY2x1ZGUgInN5c3RlbV9taWIuaCIKI2luY2x1ZGUgInVwZGF0ZXMuaCIKCiAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKgoJICoKCSAqICBLZXJuZWwgJiBpbnRlcmZhY2UgaW5mb3JtYXRpb24sCgkgKiAgIGFuZCBpbnRlcm5hbCBmb3J3YXJkIGRlY2xhcmF0aW9ucwoJICoKCSAqKioqKioqKioqKioqKioqKioqKiovCgojZGVmaW5lIFNZU19TVFJJTkdfTEVOCTI1NgpzdGF0aWMgY2hhciAgICAgdmVyc2lvbl9kZXNjcltTWVNfU1RSSU5HX0xFTl0gPSBORVRTTk1QX1ZFUlNfREVTQzsKc3RhdGljIGNoYXIgICAgIHN5c0NvbnRhY3RbU1lTX1NUUklOR19MRU5dID0gTkVUU05NUF9TWVNfQ09OVEFDVDsKc3RhdGljIGNoYXIgICAgIHN5c05hbWVbU1lTX1NUUklOR19MRU5dID0gTkVUU05NUF9TWVNfTkFNRTsKc3RhdGljIGNoYXIgICAgIHN5c0xvY2F0aW9uW1NZU19TVFJJTkdfTEVOXSA9IE5FVFNOTVBfU1lTX0xPQzsKc3RhdGljIG9pZCAgICAgIHN5c09iamVjdElEW01BWF9PSURfTEVOXTsKc3RhdGljIHNpemVfdCBzeXNPYmplY3RJREJ5dGVMZW5ndGg7CgpleHRlcm4gb2lkICAgICAgdmVyc2lvbl9zeXNvaWRbXTsKZXh0ZXJuIGludCAgICAgIHZlcnNpb25fc3lzb2lkX2xlbjsKCnN0YXRpYyBpbnQgICAgICBzeXNTZXJ2aWNlcyA9IDcyOwpzdGF0aWMgaW50ICAgICAgc3lzU2VydmljZXNDb25maWdlZCA9IDA7CgpleHRlcm4gb2lkICAgICAgdmVyc2lvbl9pZFtdOwpleHRlcm4gaW50ICAgICAgdmVyc2lvbl9pZF9sZW47CgpzdGF0aWMgaW50ICAgICAgc3lzQ29udGFjdFNldCA9IDAsIHN5c0xvY2F0aW9uU2V0ID0gMCwgc3lzTmFtZVNldCA9IDA7CgojaWYgKGRlZmluZWQgKFdJTjMyKSAmJiBkZWZpbmVkIChIQVZFX1dJTjMyX1BMQVRGT1JNX1NESykpIHx8IGRlZmluZWQgKG1pbmd3MzIpCnN0YXRpYyB2b2lkICAgICB3aW5kb3dzT1NWZXJzaW9uU3RyaW5nKGNoYXIgW10sIHNpemVfdCk7CiNlbmRpZgoKICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqCgkgKgoJICogIHNubXBkLmNvbmYgY29uZmlnIHBhcnNpbmcKCSAqCgkgKioqKioqKioqKioqKioqKioqKioqLwoKc3RhdGljIHZvaWQKc3lzdGVtX3BhcnNlX2NvbmZpZ19zeXNkZXNjcihjb25zdCBjaGFyICp0b2tlbiwgY2hhciAqY3B0cikKewogICAgaWYgKHN0cmxlbihjcHRyKSA+PSBzaXplb2YodmVyc2lvbl9kZXNjcikpIHsKCW5ldHNubXBfY29uZmlnX2Vycm9yKCJzeXNkZXNjciB0b2tlbiB0b28gbG9uZyAobXVzdCBiZSA8ICVsdSk6XG5cdCVzIiwKCQkJICAgICAodW5zaWduZWQgbG9uZylzaXplb2YodmVyc2lvbl9kZXNjciksIGNwdHIpOwogICAgfSBlbHNlIGlmIChzdHJjbXAoY3B0ciwgIlwiXCIiKSA9PSAwKSB7CiAgICAgICAgdmVyc2lvbl9kZXNjclswXSA9ICdcMCc7CiAgICB9IGVsc2UgewogICAgICAgIHN0cmNweSh2ZXJzaW9uX2Rlc2NyLCBjcHRyKTsKICAgIH0KfQoKTkVUU05NUF9TVEFUSUNfSU5MSU5FIHZvaWQKc3lzdGVtX3BhcnNlX2NvbmZpZ19zdHJpbmcoY29uc3QgY2hhciAqdG9rZW4sIGNoYXIgKmNwdHIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNoYXIgKm5hbWUsIGNoYXIqIHZhbHVlLCBzaXplX3Qgc2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50KiBndWFyZCkKewogICAgaWYgKHN0cmxlbihjcHRyKSA+PSBzaXplKSB7CgluZXRzbm1wX2NvbmZpZ19lcnJvcigiJXMgdG9rZW4gdG9vIGxvbmcgKG11c3QgYmUgPCAlbHUpOlxuXHQlcyIsCgkJCSAgICAgdG9rZW4sICh1bnNpZ25lZCBsb25nKXNpemUsIGNwdHIpOwogICAgfQoKICAgIGlmICgqdG9rZW4gPT0gJ3AnICYmIHN0cmNhc2VjbXAodG9rZW4gKyAxLCBuYW1lKSA9PSAwKSB7CiAgICAgICAgaWYgKCpndWFyZCA8IDApIHsKICAgICAgICAgICAgLyoKICAgICAgICAgICAgICogVGhpcyBpcyBib2d1cyAoYW5kIHNob3VsZG4ndCBoYXBwZW4gYW55d2F5KSAtLSB0aGUgdmFsdWUgaXMKICAgICAgICAgICAgICogYWxyZWFkeSBjb25maWd1cmVkIHJlYWQtb25seS4KICAgICAgICAgICAgICovCiAgICAgICAgICAgIHNubXBfbG9nKExPR19XQVJOSU5HLAogICAgICAgICAgICAgICAgICAgICAiaWdub3JpbmcgYXR0ZW1wdGVkIG92ZXJyaWRlIG9mIHJlYWQtb25seSAlcy4wXG4iLCBuYW1lKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICsrKCpndWFyZCk7CiAgICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgICBpZiAoKmd1YXJkID4gMCkgewogICAgICAgICAgICAvKgogICAgICAgICAgICAgKiBUaGlzIGlzIGJvZ3VzIChhbmQgc2hvdWxkbid0IGhhcHBlbiBhbnl3YXkpIC0tIHdlIGFscmVhZHkgcmVhZCBhCiAgICAgICAgICAgICAqIHBlcnNpc3RlbnQgdmFsdWUgd2hpY2ggd2Ugc2hvdWxkIGlnbm9yZSBpbiBmYXZvdXIgb2YgdGhpcyBvbmUuCiAgICAgICAgICAgICAqLwogICAgICAgICAgICBzbm1wX2xvZyhMT0dfV0FSTklORywKICAgICAgICAgICAgICAgICAgICAgImlnbm9yaW5nIGF0dGVtcHRlZCBvdmVycmlkZSBvZiByZWFkLW9ubHkgJXMuMFxuIiwgbmFtZSk7CiAgICAgICAgICAgIC8qCiAgICAgICAgICAgICAqIEZhbGwgdGhyb3VnaCBhbmQgY29weSBpbiB0aGlzIHZhbHVlLgogICAgICAgICAgICAgKi8KICAgICAgICB9CiAgICAgICAgKmd1YXJkID0gLTE7CiAgICB9CgogICAgaWYgKHN0cmNtcChjcHRyLCAiXCJcIiIpID09IDApIHsKICAgICAgICAqdmFsdWUgPSAnXDAnOwogICAgfSBlbHNlIGlmIChzdHJsZW4oY3B0cikgPCBzaXplKSB7CiAgICAgICAgc3RyY3B5KHZhbHVlLCBjcHRyKTsKICAgIH0KfQoKc3RhdGljIHZvaWQKc3lzdGVtX3BhcnNlX2NvbmZpZ19zeXNsb2MoY29uc3QgY2hhciAqdG9rZW4sIGNoYXIgKmNwdHIpCnsKICAgIHN5c3RlbV9wYXJzZV9jb25maWdfc3RyaW5nKHRva2VuLCBjcHRyLCAic3lzTG9jYXRpb24iLCBzeXNMb2NhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemVvZihzeXNMb2NhdGlvbiksICZzeXNMb2NhdGlvblNldCk7Cn0KCnN0YXRpYyB2b2lkCnN5c3RlbV9wYXJzZV9jb25maWdfc3lzY29uKGNvbnN0IGNoYXIgKnRva2VuLCBjaGFyICpjcHRyKQp7CiAgICBzeXN0ZW1fcGFyc2VfY29uZmlnX3N0cmluZyh0b2tlbiwgY3B0ciwgInN5c0NvbnRhY3QiLCBzeXNDb250YWN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZW9mKHN5c0NvbnRhY3QpLCAmc3lzQ29udGFjdFNldCk7Cn0KCnN0YXRpYyB2b2lkCnN5c3RlbV9wYXJzZV9jb25maWdfc3lzbmFtZShjb25zdCBjaGFyICp0b2tlbiwgY2hhciAqY3B0cikKewogICAgc3lzdGVtX3BhcnNlX2NvbmZpZ19zdHJpbmcodG9rZW4sIGNwdHIsICJzeXNOYW1lIiwgc3lzTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemVvZihzeXNOYW1lKSwgJnN5c05hbWVTZXQpOwp9CgpzdGF0aWMgdm9pZApzeXN0ZW1fcGFyc2VfY29uZmlnX3N5c1NlcnZpY2VzKGNvbnN0IGNoYXIgKnRva2VuLCBjaGFyICpjcHRyKQp7CiAgICBzeXNTZXJ2aWNlcyA9IGF0b2koY3B0cik7CiAgICBzeXNTZXJ2aWNlc0NvbmZpZ2VkID0gMTsKfQoKc3RhdGljIHZvaWQKc3lzdGVtX3BhcnNlX2NvbmZpZ19zeXNPYmplY3RJRChjb25zdCBjaGFyICp0b2tlbiwgY2hhciAqY3B0cikKewogICAgc2l6ZV90IHN5c09iamVjdElETGVuZ3RoID0gTUFYX09JRF9MRU47CiAgICBpZiAoIXJlYWRfb2JqaWQoY3B0ciwgc3lzT2JqZWN0SUQsICZzeXNPYmplY3RJRExlbmd0aCkpIHsKCW5ldHNubXBfY29uZmlnX2Vycm9yKCJzeXNvYmplY3RpZCB0b2tlbiBub3QgYSBwYXJzYWJsZSBPSUQ6XG5cdCVzIiwKCQkJICAgICBjcHRyKTsKICAgICAgICBzeXNPYmplY3RJREJ5dGVMZW5ndGggPSB2ZXJzaW9uX3N5c29pZF9sZW4gICogc2l6ZW9mKG9pZCk7CiAgICAgICAgbWVtY3B5KHN5c09iamVjdElELCB2ZXJzaW9uX3N5c29pZCwgc3lzT2JqZWN0SURCeXRlTGVuZ3RoKTsKICAgIH0gZWxzZQogICAgICAgIHN5c09iamVjdElEQnl0ZUxlbmd0aCA9IHN5c09iamVjdElETGVuZ3RoICogc2l6ZW9mKG9pZCk7Cn0KCgogICAgICAgIC8qKioqKioqKioqKioqKioqKioqKioKCSAqCgkgKiAgSW5pdGlhbGlzYXRpb24gJiBjb21tb24gaW1wbGVtZW50YXRpb24gZnVuY3Rpb25zCgkgKgoJICoqKioqKioqKioqKioqKioqKioqKi8KCm9pZCAgICAgICAgICAgICBzeXN0ZW1fbW9kdWxlX29pZFtdID0geyBTTk1QX09JRF9TTk1QTU9EVUxFUywgMSB9OwppbnQgICAgICAgICAgICAgc3lzdGVtX21vZHVsZV9vaWRfbGVuID0gT0lEX0xFTkdUSChzeXN0ZW1fbW9kdWxlX29pZCk7CmludCAgICAgICAgICAgICBzeXN0ZW1fbW9kdWxlX2NvdW50ID0gMDsKCnN0YXRpYyBpbnQKc3lzdGVtX3N0b3JlKGludCBhLCBpbnQgYiwgdm9pZCAqYywgdm9pZCAqZCkKewogICAgY2hhciAgICAgICAgICAgIGxpbmVbU05NUF9NQVhCVUZfU01BTExdOwoKICAgIGlmIChzeXNMb2NhdGlvblNldCA+IDApIHsKICAgICAgICBzbnByaW50ZihsaW5lLCBTTk1QX01BWEJVRl9TTUFMTCwgInBzeXNsb2NhdGlvbiAlcyIsIHN5c0xvY2F0aW9uKTsKICAgICAgICBzbm1wZF9zdG9yZV9jb25maWcobGluZSk7CiAgICB9CiAgICBpZiAoc3lzQ29udGFjdFNldCA+IDApIHsKICAgICAgICBzbnByaW50ZihsaW5lLCBTTk1QX01BWEJVRl9TTUFMTCwgInBzeXNjb250YWN0ICVzIiwgc3lzQ29udGFjdCk7CiAgICAgICAgc25tcGRfc3RvcmVfY29uZmlnKGxpbmUpOwogICAgfQogICAgaWYgKHN5c05hbWVTZXQgPiAwKSB7CiAgICAgICAgc25wcmludGYobGluZSwgU05NUF9NQVhCVUZfU01BTEwsICJwc3lzbmFtZSAlcyIsIHN5c05hbWUpOwogICAgICAgIHNubXBkX3N0b3JlX2NvbmZpZyhsaW5lKTsKICAgIH0KCiAgICByZXR1cm4gMDsKfQoKc3RhdGljIGludApoYW5kbGVfc3lzU2VydmljZXMobmV0c25tcF9taWJfaGFuZGxlciAqaGFuZGxlciwKICAgICAgICAgICAgICAgICAgIG5ldHNubXBfaGFuZGxlcl9yZWdpc3RyYXRpb24gKnJlZ2luZm8sCiAgICAgICAgICAgICAgICAgICBuZXRzbm1wX2FnZW50X3JlcXVlc3RfaW5mbyAqcmVxaW5mbywKICAgICAgICAgICAgICAgICAgIG5ldHNubXBfcmVxdWVzdF9pbmZvICpyZXF1ZXN0cykKewojaWYgTkVUU05NUF9OT19EVU1NWV9WQUxVRVMKICAgIGlmIChyZXFpbmZvLT5tb2RlID09IE1PREVfR0VUICYmICFzeXNTZXJ2aWNlc0NvbmZpZ2VkKQogICAgICAgIG5ldHNubXBfcmVxdWVzdF9zZXRfZXJyb3IocmVxdWVzdHMsIFNOTVBfTk9TVUNISU5TVEFOQ0UpOwojZW5kaWYKICAgIHJldHVybiBTTk1QX0VSUl9OT0VSUk9SOwp9CgpzdGF0aWMgaW50CmhhbmRsZV9zeXNVcFRpbWUobmV0c25tcF9taWJfaGFuZGxlciAqaGFuZGxlciwKICAgICAgICAgICAgICAgICAgIG5ldHNubXBfaGFuZGxlcl9yZWdpc3RyYXRpb24gKnJlZ2luZm8sCiAgICAgICAgICAgICAgICAgICBuZXRzbm1wX2FnZW50X3JlcXVlc3RfaW5mbyAqcmVxaW5mbywKICAgICAgICAgICAgICAgICAgIG5ldHNubXBfcmVxdWVzdF9pbmZvICpyZXF1ZXN0cykKewogICAgc25tcF9zZXRfdmFyX3R5cGVkX2ludGVnZXIocmVxdWVzdHMtPnJlcXVlc3R2YiwgQVNOX1RJTUVUSUNLUywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldHNubXBfZ2V0X2FnZW50X3VwdGltZSgpKTsKICAgIHJldHVybiBTTk1QX0VSUl9OT0VSUk9SOwp9Cgp2b2lkCmluaXRfc3lzdGVtX21pYih2b2lkKQp7CgojaWZkZWYgSEFWRV9VTkFNRQogICAgc3RydWN0IHV0c25hbWUgIHV0c05hbWU7CgogICAgdW5hbWUoJnV0c05hbWUpOwogICAgc25wcmludGYodmVyc2lvbl9kZXNjciwgc2l6ZW9mKHZlcnNpb25fZGVzY3IpLAogICAgICAgICAgICAiJXMgJXMgJXMgJXMgJXMiLCB1dHNOYW1lLnN5c25hbWUsCiAgICAgICAgICAgIHV0c05hbWUubm9kZW5hbWUsIHV0c05hbWUucmVsZWFzZSwgdXRzTmFtZS52ZXJzaW9uLAogICAgICAgICAgICB1dHNOYW1lLm1hY2hpbmUpOwogICAgdmVyc2lvbl9kZXNjclsgc2l6ZW9mKHZlcnNpb25fZGVzY3IpLTEgXSA9IDA7CiNlbHNlCiNpZiBIQVZFX0VYRUNWCiAgICBzdHJ1Y3QgZXh0ZW5zaWJsZSBleHRtcDsKCiAgICAvKgogICAgICogc2V0IGRlZmF1bHQgdmFsdWVzIG9mIHN5c3RlbSBzdHVmZiAKICAgICAqLwogICAgc3ByaW50ZihleHRtcC5jb21tYW5kLCAiJXMgLWEiLCBVTkFNRVBST0cpOwogICAgLyoKICAgICAqIHNldHVwIGRlZmF1bHRzIAogICAgICovCiAgICBleHRtcC50eXBlID0gRVhFQ1BST0M7CiAgICBleHRtcC5uZXh0ID0gTlVMTDsKICAgIGV4ZWNfY29tbWFuZCgmZXh0bXApOwogICAgc3RybGNweSh2ZXJzaW9uX2Rlc2NyLCBleHRtcC5vdXRwdXQsIHNpemVvZih2ZXJzaW9uX2Rlc2NyKSk7CiAgICBpZiAoc3RybGVuKHZlcnNpb25fZGVzY3IpID49IDEpCiAgICAgICAgdmVyc2lvbl9kZXNjcltzdHJsZW4odmVyc2lvbl9kZXNjcikgLSAxXSA9IDA7IC8qIGNob21wIG5ldyBsaW5lICovCiNlbHNlCiNpZiAoZGVmaW5lZCAoV0lOMzIpICYmIGRlZmluZWQgKEhBVkVfV0lOMzJfUExBVEZPUk1fU0RLKSkgfHwgZGVmaW5lZCAobWluZ3czMikKICAgIHdpbmRvd3NPU1ZlcnNpb25TdHJpbmcodmVyc2lvbl9kZXNjciwgc2l6ZW9mKHZlcnNpb25fZGVzY3IpKTsKI2Vsc2UKICAgIHN0cmNweSh2ZXJzaW9uX2Rlc2NyLCAidW5rbm93biIpOwojZW5kaWYKI2VuZGlmCiNlbmRpZgoKI2lmZGVmIEhBVkVfR0VUSE9TVE5BTUUKICAgIGdldGhvc3RuYW1lKHN5c05hbWUsIHNpemVvZihzeXNOYW1lKSk7CiNlbHNlCiNpZmRlZiBIQVZFX1VOQU1FCiAgICBzdHJsY3B5KHN5c05hbWUsIHV0c05hbWUubm9kZW5hbWUsIHNpemVvZihzeXNOYW1lKSk7CiNlbHNlCiNpZiBkZWZpbmVkIChIQVZFX0VYRUNWKSAmJiAhZGVmaW5lZCAobWluZ3czMikKICAgIHNwcmludGYoZXh0bXAuY29tbWFuZCwgIiVzIC1uIiwgVU5BTUVQUk9HKTsKICAgIC8qCiAgICAgKiBzZXR1cCBkZWZhdWx0cyAKICAgICAqLwogICAgZXh0bXAudHlwZSA9IEVYRUNQUk9DOwogICAgZXh0bXAubmV4dCA9IE5VTEw7CiAgICBleGVjX2NvbW1hbmQoJmV4dG1wKTsKICAgIHN0cmxjcHkoc3lzTmFtZSwgZXh0bXAub3V0cHV0LCBzaXplb2Yoc3lzTmFtZSkpOwogICAgaWYgKHN0cmxlbihzeXNOYW1lKSA+PSAxKQogICAgICAgIHN5c05hbWVbc3RybGVuKHN5c05hbWUpIC0gMV0gPSAwOyAvKiBjaG9tcCBuZXcgbGluZSAqLwojZWxzZQogICAgc3RyY3B5KHN5c05hbWUsICJ1bmtub3duIik7CiNlbmRpZiAgICAgICAgICAgICAgICAgICAgICAgICAgLyogSEFWRV9FWEVDViAqLwojZW5kaWYgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIEhBVkVfVU5BTUUgKi8KI2VuZGlmICAgICAgICAgICAgICAgICAgICAgICAgICAvKiBIQVZFX0dFVEhPU1ROQU1FICovCgojaWYgKGRlZmluZWQgKFdJTjMyKSAmJiBkZWZpbmVkIChIQVZFX1dJTjMyX1BMQVRGT1JNX1NESykpIHx8IGRlZmluZWQgKG1pbmd3MzIpCiAgICB7CiAgICAgIEhLRVkgaEtleTsKICAgICAgLyogRGVmYXVsdCBzeXNDb250YWN0IGlzIHRoZSByZWdpc3RlcmVkIHdpbmRvd3MgdXNlciAqLwogICAgICBpZiAoUmVnT3BlbktleUV4KEhLRVlfTE9DQUxfTUFDSElORSwKICAgICAgICAgICAgICAgICAgICAgICAiU09GVFdBUkVcXE1pY3Jvc29mdFxcV2luZG93cyBOVFxcQ3VycmVudFZlcnNpb24iLCAwLAogICAgICAgICAgICAgICAgICAgICAgIEtFWV9RVUVSWV9WQUxVRSwgJmhLZXkpID09IEVSUk9SX1NVQ0NFU1MpIHsKICAgICAgICAgIGNoYXIgcmVnaXN0ZXJlZE93bmVyWzI1Nl0gPSAiIjsKICAgICAgICAgIERXT1JEIHJlZ2lzdGVyZWRPd25lclN6ID0gMjU2OwogICAgICAgICAgaWYgKFJlZ1F1ZXJ5VmFsdWVFeChoS2V5LCAiUmVnaXN0ZXJlZE93bmVyIiwgTlVMTCwgTlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKExQQllURSlyZWdpc3RlcmVkT3duZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICZyZWdpc3RlcmVkT3duZXJTeikgPT0gRVJST1JfU1VDQ0VTUykgewogICAgICAgICAgICAgIHN0cmNweShzeXNDb250YWN0LCByZWdpc3RlcmVkT3duZXIpOwogICAgICAgICAgfQogICAgICAgICAgUmVnQ2xvc2VLZXkoaEtleSk7CiAgICAgIH0KICAgIH0KI2VuZGlmCgogICAgLyogZGVmYXVsdCBzeXNPYmplY3RJRCAqLwogICAgbWVtY3B5KHN5c09iamVjdElELCB2ZXJzaW9uX3N5c29pZCwgdmVyc2lvbl9zeXNvaWRfbGVuICogc2l6ZW9mKG9pZCkpOwogICAgc3lzT2JqZWN0SURCeXRlTGVuZ3RoID0gdmVyc2lvbl9zeXNvaWRfbGVuICogc2l6ZW9mKG9pZCk7CgogICAgewogICAgICAgIGNvbnN0IG9pZCBzeXNEZXNjcl9vaWRbXSA9IHsgMSwgMywgNiwgMSwgMiwgMSwgMSwgMSB9OwogICAgICAgIHN0YXRpYyBuZXRzbm1wX3dhdGNoZXJfaW5mbyBzeXNEZXNjcl93aW5mbzsKICAgICAgICBuZXRzbm1wX3JlZ2lzdGVyX3dhdGNoZWRfc2NhbGFyKAogICAgICAgICAgICBuZXRzbm1wX2NyZWF0ZV9oYW5kbGVyX3JlZ2lzdHJhdGlvbigKICAgICAgICAgICAgICAgICJtaWJJSS9zeXNEZXNjciIsIE5VTEwsIHN5c0Rlc2NyX29pZCwgT0lEX0xFTkdUSChzeXNEZXNjcl9vaWQpLAogICAgICAgICAgICAgICAgSEFORExFUl9DQU5fUk9OTFkpLAogICAgICAgICAgICBuZXRzbm1wX2luaXRfd2F0Y2hlcl9pbmZvKCZzeXNEZXNjcl93aW5mbywgdmVyc2lvbl9kZXNjciwgMCwKCQkJCSAgICAgIEFTTl9PQ1RFVF9TVFIsIFdBVENIRVJfU0laRV9TVFJMRU4pKTsKICAgIH0KICAgIHsKICAgICAgICBjb25zdCBvaWQgc3lzT2JqZWN0SURfb2lkW10gPSB7IDEsIDMsIDYsIDEsIDIsIDEsIDEsIDIgfTsKICAgICAgICBzdGF0aWMgbmV0c25tcF93YXRjaGVyX2luZm8gc3lzT2JqZWN0SURfd2luZm87CiAgICAgICAgbmV0c25tcF9yZWdpc3Rlcl93YXRjaGVkX3NjYWxhcigKICAgICAgICAgICAgbmV0c25tcF9jcmVhdGVfaGFuZGxlcl9yZWdpc3RyYXRpb24oCiAgICAgICAgICAgICAgICAibWliSUkvc3lzT2JqZWN0SUQiLCBOVUxMLAogICAgICAgICAgICAgICAgc3lzT2JqZWN0SURfb2lkLCBPSURfTEVOR1RIKHN5c09iamVjdElEX29pZCksCiAgICAgICAgICAgICAgICBIQU5ETEVSX0NBTl9ST05MWSksCiAgICAgICAgICAgIG5ldHNubXBfaW5pdF93YXRjaGVyX2luZm82KAoJCSZzeXNPYmplY3RJRF93aW5mbywgc3lzT2JqZWN0SUQsIDAsIEFTTl9PQkpFQ1RfSUQsCiAgICAgICAgICAgICAgICBXQVRDSEVSX01BWF9TSVpFIHwgV0FUQ0hFUl9TSVpFX0lTX1BUUiwKICAgICAgICAgICAgICAgIE1BWF9PSURfTEVOLCAmc3lzT2JqZWN0SURCeXRlTGVuZ3RoKSk7CiAgICB9CiAgICB7CiAgICAgICAgY29uc3Qgb2lkIHN5c1VwVGltZV9vaWRbXSA9IHsgMSwgMywgNiwgMSwgMiwgMSwgMSwgMyB9OwogICAgICAgIG5ldHNubXBfcmVnaXN0ZXJfc2NhbGFyKAogICAgICAgICAgICBuZXRzbm1wX2NyZWF0ZV9oYW5kbGVyX3JlZ2lzdHJhdGlvbigKICAgICAgICAgICAgICAgICJtaWJJSS9zeXNVcFRpbWUiLCBoYW5kbGVfc3lzVXBUaW1lLAogICAgICAgICAgICAgICAgc3lzVXBUaW1lX29pZCwgT0lEX0xFTkdUSChzeXNVcFRpbWVfb2lkKSwKICAgICAgICAgICAgICAgIEhBTkRMRVJfQ0FOX1JPTkxZKSk7CiAgICB9CiAgICB7CiAgICAgICAgY29uc3Qgb2lkIHN5c0NvbnRhY3Rfb2lkW10gPSB7IDEsIDMsIDYsIDEsIDIsIDEsIDEsIDQgfTsKICAgICAgICBzdGF0aWMgbmV0c25tcF93YXRjaGVyX2luZm8gc3lzQ29udGFjdF93aW5mbzsKICAgICAgICBuZXRzbm1wX3JlZ2lzdGVyX3dhdGNoZWRfc2NhbGFyKAogICAgICAgICAgICBuZXRzbm1wX2NyZWF0ZV91cGRhdGVfaGFuZGxlcl9yZWdpc3RyYXRpb24oCiAgICAgICAgICAgICAgICAibWliSUkvc3lzQ29udGFjdCIsIHN5c0NvbnRhY3Rfb2lkLCBPSURfTEVOR1RIKHN5c0NvbnRhY3Rfb2lkKSwKICAgICAgICAgICAgICAgIEhBTkRMRVJfQ0FOX1JXUklURSwgJnN5c0NvbnRhY3RTZXQpLAogICAgICAgICAgICBuZXRzbm1wX2luaXRfd2F0Y2hlcl9pbmZvKAoJCSZzeXNDb250YWN0X3dpbmZvLCBzeXNDb250YWN0LCBTWVNfU1RSSU5HX0xFTiAtIDEsCgkJQVNOX09DVEVUX1NUUiwgV0FUQ0hFUl9NQVhfU0laRSB8IFdBVENIRVJfU0laRV9TVFJMRU4pKTsKICAgIH0KICAgIHsKICAgICAgICBjb25zdCBvaWQgc3lzTmFtZV9vaWRbXSA9IHsgMSwgMywgNiwgMSwgMiwgMSwgMSwgNSB9OwogICAgICAgIHN0YXRpYyBuZXRzbm1wX3dhdGNoZXJfaW5mbyBzeXNOYW1lX3dpbmZvOwogICAgICAgIG5ldHNubXBfcmVnaXN0ZXJfd2F0Y2hlZF9zY2FsYXIoCiAgICAgICAgICAgIG5ldHNubXBfY3JlYXRlX3VwZGF0ZV9oYW5kbGVyX3JlZ2lzdHJhdGlvbigKICAgICAgICAgICAgICAgICJtaWJJSS9zeXNOYW1lIiwgc3lzTmFtZV9vaWQsIE9JRF9MRU5HVEgoc3lzTmFtZV9vaWQpLAogICAgICAgICAgICAgICAgSEFORExFUl9DQU5fUldSSVRFLCAmc3lzTmFtZVNldCksCiAgICAgICAgICAgIG5ldHNubXBfaW5pdF93YXRjaGVyX2luZm8oCiAgICAgICAgICAgICAgICAmc3lzTmFtZV93aW5mbywgc3lzTmFtZSwgU1lTX1NUUklOR19MRU4gLSAxLCBBU05fT0NURVRfU1RSLAogICAgICAgICAgICAgICAgV0FUQ0hFUl9NQVhfU0laRSB8IFdBVENIRVJfU0laRV9TVFJMRU4pKTsKICAgIH0KICAgIHsKICAgICAgICBjb25zdCBvaWQgc3lzTG9jYXRpb25fb2lkW10gPSB7IDEsIDMsIDYsIDEsIDIsIDEsIDEsIDYgfTsKICAgICAgICBzdGF0aWMgbmV0c25tcF93YXRjaGVyX2luZm8gc3lzTG9jYXRpb25fd2luZm87CiAgICAgICAgbmV0c25tcF9yZWdpc3Rlcl93YXRjaGVkX3NjYWxhcigKICAgICAgICAgICAgbmV0c25tcF9jcmVhdGVfdXBkYXRlX2hhbmRsZXJfcmVnaXN0cmF0aW9uKAogICAgICAgICAgICAgICAgIm1pYklJL3N5c0xvY2F0aW9uIiwgc3lzTG9jYXRpb25fb2lkLAogICAgICAgICAgICAgICAgT0lEX0xFTkdUSChzeXNMb2NhdGlvbl9vaWQpLAogICAgICAgICAgICAgICAgSEFORExFUl9DQU5fUldSSVRFLCAmc3lzTG9jYXRpb25TZXQpLAogICAgICAgICAgICBuZXRzbm1wX2luaXRfd2F0Y2hlcl9pbmZvKAoJCSZzeXNMb2NhdGlvbl93aW5mbywgc3lzTG9jYXRpb24sIFNZU19TVFJJTkdfTEVOIC0gMSwKCQlBU05fT0NURVRfU1RSLCBXQVRDSEVSX01BWF9TSVpFIHwgV0FUQ0hFUl9TSVpFX1NUUkxFTikpOwogICAgfQogICAgewogICAgICAgIGNvbnN0IG9pZCBzeXNTZXJ2aWNlc19vaWRbXSA9IHsgMSwgMywgNiwgMSwgMiwgMSwgMSwgNyB9OwogICAgICAgIG5ldHNubXBfcmVnaXN0ZXJfcmVhZF9vbmx5X2ludF9zY2FsYXIoCiAgICAgICAgICAgICJtaWJJSS9zeXNTZXJ2aWNlcyIsIHN5c1NlcnZpY2VzX29pZCwgT0lEX0xFTkdUSChzeXNTZXJ2aWNlc19vaWQpLAogICAgICAgICAgICAmc3lzU2VydmljZXMsIGhhbmRsZV9zeXNTZXJ2aWNlcyk7CiAgICB9CiAgICBpZiAoKytzeXN0ZW1fbW9kdWxlX2NvdW50ID09IDMpCiAgICAgICAgUkVHSVNURVJfU1lTT1JfRU5UUlkoc3lzdGVtX21vZHVsZV9vaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRoZSBNSUIgbW9kdWxlIGZvciBTTk1QdjIgZW50aXRpZXMiKTsKCiAgICBzeXNDb250YWN0U2V0ID0gc3lzTG9jYXRpb25TZXQgPSBzeXNOYW1lU2V0ID0gMDsKCiAgICAvKgogICAgICogcmVnaXN0ZXIgb3VyIGNvbmZpZyBoYW5kbGVycyAKICAgICAqLwogICAgc25tcGRfcmVnaXN0ZXJfY29uZmlnX2hhbmRsZXIoInN5c2Rlc2NyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN5c3RlbV9wYXJzZV9jb25maWdfc3lzZGVzY3IsIE5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGVzY3JpcHRpb24iKTsKICAgIHNubXBkX3JlZ2lzdGVyX2NvbmZpZ19oYW5kbGVyKCJzeXNsb2NhdGlvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzeXN0ZW1fcGFyc2VfY29uZmlnX3N5c2xvYywgTlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJsb2NhdGlvbiIpOwogICAgc25tcGRfcmVnaXN0ZXJfY29uZmlnX2hhbmRsZXIoInN5c2NvbnRhY3QiLCBzeXN0ZW1fcGFyc2VfY29uZmlnX3N5c2NvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5VTEwsICJjb250YWN0LW5hbWUiKTsKICAgIHNubXBkX3JlZ2lzdGVyX2NvbmZpZ19oYW5kbGVyKCJzeXNuYW1lIiwgc3lzdGVtX3BhcnNlX2NvbmZpZ19zeXNuYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTlVMTCwgIm5vZGUtbmFtZSIpOwogICAgc25tcGRfcmVnaXN0ZXJfY29uZmlnX2hhbmRsZXIoInBzeXNsb2NhdGlvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzeXN0ZW1fcGFyc2VfY29uZmlnX3N5c2xvYywgTlVMTCwgTlVMTCk7CiAgICBzbm1wZF9yZWdpc3Rlcl9jb25maWdfaGFuZGxlcigicHN5c2NvbnRhY3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3lzdGVtX3BhcnNlX2NvbmZpZ19zeXNjb24sIE5VTEwsIE5VTEwpOwogICAgc25tcGRfcmVnaXN0ZXJfY29uZmlnX2hhbmRsZXIoInBzeXNuYW1lIiwgc3lzdGVtX3BhcnNlX2NvbmZpZ19zeXNuYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTlVMTCwgTlVMTCk7CiAgICBzbm1wZF9yZWdpc3Rlcl9jb25maWdfaGFuZGxlcigic3lzc2VydmljZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3lzdGVtX3BhcnNlX2NvbmZpZ19zeXNTZXJ2aWNlcywgTlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOVU1CRVIiKTsKICAgIHNubXBkX3JlZ2lzdGVyX2NvbmZpZ19oYW5kbGVyKCJzeXNvYmplY3RpZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzeXN0ZW1fcGFyc2VfY29uZmlnX3N5c09iamVjdElELCBOVUxMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9JRCIpOwogICAgc25tcF9yZWdpc3Rlcl9jYWxsYmFjayhTTk1QX0NBTExCQUNLX0xJQlJBUlksIFNOTVBfQ0FMTEJBQ0tfU1RPUkVfREFUQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3lzdGVtX3N0b3JlLCBOVUxMKTsKfQoKICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqCgkgKgoJICogIEludGVybmFsIGltcGxlbWVudGF0aW9uIGZ1bmN0aW9ucyAtIE5vbmUKCSAqCgkgKioqKioqKioqKioqKioqKioqKioqLwoKI2lmIChkZWZpbmVkIChXSU4zMikgJiYgZGVmaW5lZCAoSEFWRV9XSU4zMl9QTEFURk9STV9TREspKSB8fCBkZWZpbmVkIChtaW5ndzMyKQpzdGF0aWMgdm9pZAp3aW5kb3dzT1NWZXJzaW9uU3RyaW5nKGNoYXIgc3RyaW5nYnVmW10sIHNpemVfdCBzdHJpbmdidWZsZW4pCnsKICAgIC8qIGNvcHkgT1MgdmVyc2lvbiB0byBzdHJpbmcgYnVmZmVyIGluICd1bmFtZSAtYScgZm9ybWF0ICovCiAgICBPU1ZFUlNJT05JTkZPRVggb3NWZXJzaW9uSW5mbzsKICAgIEJPT0wgZ290T3NWZXJzaW9uSW5mb0V4OwogICAgY2hhciB3aW5kb3dzVmVyc2lvblsyNTZdID0gIiI7CiAgICBjaGFyIGhvc3RuYW1lWzI1Nl0gPSAiIjsKICAgIGNoYXIgaWRlbnRpZmllclsyNTZdID0gIiI7CiAgICBEV09SRCBpZGVudGlmaWVyU3ogPSAyNTY7CiAgICBIS0VZIGhLZXk7CgogICAgWmVyb01lbW9yeSgmb3NWZXJzaW9uSW5mbywgc2l6ZW9mKE9TVkVSU0lPTklORk9FWCkpOwogICAgb3NWZXJzaW9uSW5mby5kd09TVmVyc2lvbkluZm9TaXplID0gc2l6ZW9mKE9TVkVSU0lPTklORk9FWCk7CiAgICBnb3RPc1ZlcnNpb25JbmZvRXggPSBHZXRWZXJzaW9uRXgoKE9TVkVSU0lPTklORk8gKikmb3NWZXJzaW9uSW5mbyk7CiAgICBpZiAoZ290T3NWZXJzaW9uSW5mb0V4ID09IEZBTFNFKSB7CiAgICAgICBHZXRWZXJzaW9uRXgoKE9TVkVSU0lPTklORk8gKikmb3NWZXJzaW9uSW5mbyk7CiAgICB9CgogICAgc3dpdGNoIChvc1ZlcnNpb25JbmZvLmR3UGxhdGZvcm1JZCkgewogICAgICAgY2FzZSBWRVJfUExBVEZPUk1fV0lOMzJfTlQ6CiAgICAgICAgICBpZiAoKG9zVmVyc2lvbkluZm8uZHdNYWpvclZlcnNpb24gPT0gNSkgJiYgKG9zVmVyc2lvbkluZm8uZHdNaW5vclZlcnNpb24gPT0gMikpIHsKICAgICAgICAgICAgIHN0cmNhdCh3aW5kb3dzVmVyc2lvbiwgIlNlcnZlciAyMDAzIik7CiAgICAgICAgICB9IGVsc2UgaWYgKChvc1ZlcnNpb25JbmZvLmR3TWFqb3JWZXJzaW9uID09IDUpICYmIChvc1ZlcnNpb25JbmZvLmR3TWlub3JWZXJzaW9uID09IDEpKSB7CiAgICAgICAgICAgICBzdHJjYXQod2luZG93c1ZlcnNpb24sICJYUCIpOwogICAgICAgICAgfSBlbHNlIGlmICgob3NWZXJzaW9uSW5mby5kd01ham9yVmVyc2lvbiA9PSA1KSAmJiAob3NWZXJzaW9uSW5mby5kd01pbm9yVmVyc2lvbiA9PSAwKSkgewogICAgICAgICAgICAgc3RyY2F0KHdpbmRvd3NWZXJzaW9uLCAiMjAwMCIpOwogICAgICAgICAgfSBlbHNlIGlmIChvc1ZlcnNpb25JbmZvLmR3TWFqb3JWZXJzaW9uIDw9IDQpIHsKICAgICAgICAgICAgIHN0cmNhdCh3aW5kb3dzVmVyc2lvbiwgIk5UIik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZ290T3NWZXJzaW9uSW5mb0V4ID09IFRSVUUpIHsKICAgICAgICAgICAgIGlmIChvc1ZlcnNpb25JbmZvLndQcm9kdWN0VHlwZSA9PSBWRVJfTlRfV09SS1NUQVRJT04pIHsKICAgICAgICAgICAgICAgIGlmIChvc1ZlcnNpb25JbmZvLmR3TWFqb3JWZXJzaW9uID09IDQpIHsKICAgICAgICAgICAgICAgICAgIHN0cmNhdCh3aW5kb3dzVmVyc2lvbiwgIiBXb3Jrc3RhdGlvbiA0LjAiKTsKICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAob3NWZXJzaW9uSW5mby53U3VpdGVNYXNrICYgVkVSX1NVSVRFX1BFUlNPTkFMKSB7CiAgICAgICAgICAgICAgICAgICBzdHJjYXQod2luZG93c1ZlcnNpb24sICIgSG9tZSBFZGl0aW9uIik7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgc3RyY2F0KHdpbmRvd3NWZXJzaW9uLCAiIFByb2Zlc3Npb25hbCIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgfSBlbHNlIGlmIChvc1ZlcnNpb25JbmZvLndQcm9kdWN0VHlwZSA9PSBWRVJfTlRfU0VSVkVSKSB7CiAgICAgICAgICAgICAgICBpZiAoKG9zVmVyc2lvbkluZm8uZHdNYWpvclZlcnNpb24gPT0gNSkgJiYgKG9zVmVyc2lvbkluZm8uZHdNaW5vclZlcnNpb24gPT0gMikpIHsKICAgICAgICAgICAgICAgICAgIGlmIChvc1ZlcnNpb25JbmZvLndTdWl0ZU1hc2sgJiBWRVJfU1VJVEVfREFUQUNFTlRFUikgewogICAgICAgICAgICAgICAgICAgICAgc3RyY2F0KHdpbmRvd3NWZXJzaW9uLCAiIERhdGFjZW50ZXIgRWRpdGlvbiIpOwogICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvc1ZlcnNpb25JbmZvLndTdWl0ZU1hc2sgJiBWRVJfU1VJVEVfRU5URVJQUklTRSkgewogICAgICAgICAgICAgICAgICAgICAgc3RyY2F0KHdpbmRvd3NWZXJzaW9uLCAiIEVudGVycHJpc2UgRWRpdGlvbiIpOwogICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvc1ZlcnNpb25JbmZvLndTdWl0ZU1hc2sgPT0gVkVSX1NVSVRFX0JMQURFKSB7CiAgICAgICAgICAgICAgICAgICAgICBzdHJjYXQod2luZG93c1ZlcnNpb24sICIgV2ViIEVkaXRpb24iKTsKICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICBzdHJjYXQod2luZG93c1ZlcnNpb24sICIgU3RhbmRhcmQgRWRpdGlvbiIpOwogICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSBlbHNlIGlmICgob3NWZXJzaW9uSW5mby5kd01ham9yVmVyc2lvbiA9PSA1KSAmJiAob3NWZXJzaW9uSW5mby5kd01pbm9yVmVyc2lvbiA9PSAwKSkgewogICAgICAgICAgICAgICAgICAgaWYgKG9zVmVyc2lvbkluZm8ud1N1aXRlTWFzayAmIFZFUl9TVUlURV9EQVRBQ0VOVEVSKSB7CiAgICAgICAgICAgICAgICAgICAgICBzdHJjYXQod2luZG93c1ZlcnNpb24sICIgRGF0YWNlbnRlciBTZXJ2ZXIiKTsKICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAob3NWZXJzaW9uSW5mby53U3VpdGVNYXNrICYgVkVSX1NVSVRFX0VOVEVSUFJJU0UpIHsKICAgICAgICAgICAgICAgICAgICAgIHN0cmNhdCh3aW5kb3dzVmVyc2lvbiwgIiBBZHZhbmNlZCBTZXJ2ZXIiKTsKICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICBzdHJjYXQod2luZG93c1ZlcnNpb24sICIgU2VydmVyIik7CiAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgaWYgKG9zVmVyc2lvbkluZm8ud1N1aXRlTWFzayAmIFZFUl9TVUlURV9FTlRFUlBSSVNFKSB7CiAgICAgICAgICAgICAgICAgICAgICBzdHJjYXQod2luZG93c1ZlcnNpb24sICIgU2VydmVyIDQuMCwgRW50ZXJwcmlzZSBFZGl0aW9uIik7CiAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgc3RyY2F0KHdpbmRvd3NWZXJzaW9uLCAiIFNlcnZlciA0LjAiKTsKICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICBjaGFyIHByb2R1Y3RUeXBlWzgwXTsKICAgICAgICAgICAgIERXT1JEIHByb2R1Y3RUeXBlU3ogPSA4MDsKCiAgICAgICAgICAgICBpZiAoUmVnT3BlbktleUV4KEhLRVlfTE9DQUxfTUFDSElORSwgIlNZU1RFTVxcQ3VycmVudENvbnRyb2xTZXRcXENvbnRyb2xcXFByb2R1Y3RPcHRpb25zIiwgMCwgS0VZX1FVRVJZX1ZBTFVFLCAmaEtleSkgPT0gRVJST1JfU1VDQ0VTUykgewogICAgICAgICAgICAgICAgaWYgKFJlZ1F1ZXJ5VmFsdWVFeChoS2V5LCAiUHJvZHVjdFR5cGUiLCBOVUxMLCBOVUxMLCAoTFBCWVRFKSBwcm9kdWN0VHlwZSwgJnByb2R1Y3RUeXBlU3opID09IEVSUk9SX1NVQ0NFU1MpIHsKICAgICAgICAgICAgICAgICAgIGNoYXIgdmVyc2lvblN0clsxMF07CiAgICAgICAgICAgICAgICAgICBpZiAoc3RyY21waSgiV0lOTlQiLCBwcm9kdWN0VHlwZSkgPT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgc3RyY2F0KHdpbmRvd3NWZXJzaW9uLCAiIFdvcmtzdGF0aW9uIik7CiAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0cmNtcGkoIkxBTk1BTk5UIiwgcHJvZHVjdFR5cGUpID09IDApIHsKICAgICAgICAgICAgICAgICAgICAgIHN0cmNhdCh3aW5kb3dzVmVyc2lvbiwgIiBTZXJ2ZXIiKTsKICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RyY21waSgiU0VSVkVSTlQiLCBwcm9kdWN0VHlwZSkgPT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgc3RyY2F0KHdpbmRvd3NWZXJzaW9uLCAiIEFkdmFuY2VkIFNlcnZlciIpOwogICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgc3ByaW50Zih2ZXJzaW9uU3RyLCAiICVkLiVkIiwgKGludClvc1ZlcnNpb25JbmZvLmR3TWFqb3JWZXJzaW9uLCAoaW50KW9zVmVyc2lvbkluZm8uZHdNaW5vclZlcnNpb24pOwogICAgICAgICAgICAgICAgICAgc3RyY2F0KHdpbmRvd3NWZXJzaW9uLCB2ZXJzaW9uU3RyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIFJlZ0Nsb3NlS2V5KGhLZXkpOwogICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICBjYXNlIFZFUl9QTEFURk9STV9XSU4zMl9XSU5ET1dTOgogICAgICAgICAgaWYgKChvc1ZlcnNpb25JbmZvLmR3TWFqb3JWZXJzaW9uID09IDQpICYmIChvc1ZlcnNpb25JbmZvLmR3TWlub3JWZXJzaW9uID09IDkwKSkgewogICAgICAgICAgICAgc3RyY2F0KHdpbmRvd3NWZXJzaW9uLCAiTUUiKTsKICAgICAgICAgIH0gZWxzZSBpZiAoKG9zVmVyc2lvbkluZm8uZHdNYWpvclZlcnNpb24gPT0gNCkgJiYgKG9zVmVyc2lvbkluZm8uZHdNaW5vclZlcnNpb24gPT0gMTApKSB7CiAgICAgICAgICAgICBzdHJjYXQod2luZG93c1ZlcnNpb24sICI5OCIpOwogICAgICAgICAgICAgaWYgKG9zVmVyc2lvbkluZm8uc3pDU0RWZXJzaW9uWzFdID09ICdBJykgewogICAgICAgICAgICAgICAgc3RyY2F0KHdpbmRvd3NWZXJzaW9uLCAiIFNFIik7CiAgICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgaWYgKChvc1ZlcnNpb25JbmZvLmR3TWFqb3JWZXJzaW9uID09IDQpICYmIChvc1ZlcnNpb25JbmZvLmR3TWlub3JWZXJzaW9uID09IDApKSB7CiAgICAgICAgICAgICBzdHJjYXQod2luZG93c1ZlcnNpb24sICI5NSIpOwogICAgICAgICAgICAgaWYgKChvc1ZlcnNpb25JbmZvLnN6Q1NEVmVyc2lvblsxXSA9PSAnQycpIHx8IChvc1ZlcnNpb25JbmZvLnN6Q1NEVmVyc2lvblsxXSA9PSAnQicpKSB7CiAgICAgICAgICAgICAgICBzdHJjYXQod2luZG93c1ZlcnNpb24sICIgT1NSMiIpOwogICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICB9CgogICAgZ2V0aG9zdG5hbWUoaG9zdG5hbWUsIHNpemVvZihob3N0bmFtZSkpOwoKICAgIGlmIChSZWdPcGVuS2V5RXgoSEtFWV9MT0NBTF9NQUNISU5FLCAiSEFSRFdBUkVcXERFU0NSSVBUSU9OXFxTeXN0ZW1cXENlbnRyYWxQcm9jZXNzb3JcXDAiLCAwLCBLRVlfQUxMX0FDQ0VTUywgJmhLZXkpID09IEVSUk9SX1NVQ0NFU1MpIHsKICAgICAgIFJlZ1F1ZXJ5VmFsdWVFeChoS2V5LCAiSWRlbnRpZmllciIsIE5VTEwsIE5VTEwsIChMUEJZVEUpJmlkZW50aWZpZXIsICZpZGVudGlmaWVyU3opOwogICAgICAgUmVnQ2xvc2VLZXkoaEtleSk7CiAgICB9CgogICAgLyogT3V0cHV0IGlzIG1hZGUgdG8gbG9vayBsaWtlIHJlc3VsdHMgZnJvbSB1bmFtZSAtYSAqLwogICAgc25wcmludGYoc3RyaW5nYnVmLCBzdHJpbmdidWZsZW4sCiAgICAgICAgICAgICJXaW5kb3dzICVzICVkLiVkLiVkICVzICVzICVzIiwgaG9zdG5hbWUsCiAgICAgICAgICAgICAoaW50KW9zVmVyc2lvbkluZm8uZHdNYWpvclZlcnNpb24sIChpbnQpb3NWZXJzaW9uSW5mby5kd01pbm9yVmVyc2lvbiwKICAgICAgICAgICAgIChpbnQpb3NWZXJzaW9uSW5mby5kd0J1aWxkTnVtYmVyLCBvc1ZlcnNpb25JbmZvLnN6Q1NEVmVyc2lvbiwKICAgICAgICAgICAgIHdpbmRvd3NWZXJzaW9uLCBpZGVudGlmaWVyKTsKfQojZW5kaWYgLyogV0lOMzIgYW5kIEhBVkVfV0lOMzJfUExBVEZPUk1fU0RLIG9yIG1pbmd3MzIgKi8KCg==