LyoKICogRGVidWdnZXIgc3RhY2sgaGFuZGxpbmcKICoKICogQ29weXJpZ2h0IDE5OTUgQWxleGFuZHJlIEp1bGxpYXJkCiAqIENvcHlyaWdodCAxOTk2IEVyaWMgWW91bmdkYWxlCiAqIENvcHlyaWdodCAxOTk5IE92ZSBL5XZlbgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKICovCgojaW5jbHVkZSAiY29uZmlnLmgiCgojaW5jbHVkZSA8c3RkbGliLmg+CgojaW5jbHVkZSAiZGVidWdnZXIuaCIKI2luY2x1ZGUgInN0YWNrZnJhbWUuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKI2luY2x1ZGUgInRsaGVscDMyLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTCh3aW5lZGJnKTsKCnN0YXRpYyBpbnQgICAgICAgICAgICAgICAgICAgICAgbmZyYW1lOwpzdGF0aWMgSU1BR0VITFBfU1RBQ0tfRlJBTUUqICAgIGZyYW1lcyA9IE5VTEw7CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogICAgICAgICAgIHN0YWNrX2luZm8KICoKICogRHVtcCB0aGUgdG9wIG9mIHRoZSBzdGFjawogKi8Kdm9pZCBzdGFja19pbmZvKHZvaWQpCnsKICAgIEFERFJFU1MgICAgICAgICAgICAgYWRkcjsKCiAgICAvKiBGSVhNRTogd2UgYXNzdW1lIHN0YWNrIGdyb3dzIHRoZSBzYW1lIHdheSBhcyBvbiBpMzg2ICovCiAgICBpZiAoIW1lbW9yeV9nZXRfY3VycmVudF9zdGFjaygmYWRkcikpCiAgICAgICAgZGJnX3ByaW50ZigiQmFkIHNlZ21lbnQgKCVkKVxuIiwgYWRkci5TZWdtZW50KTsKCiAgICBkYmdfcHJpbnRmKCJTdGFjayBkdW1wOlxuIik7CiAgICBzd2l0Y2ggKGFkZHIuTW9kZSkKICAgIHsKICAgIGNhc2UgQWRkck1vZGVGbGF0OiAvKiAzMi1iaXQgbW9kZSAqLwogICAgY2FzZSBBZGRyTW9kZTE2MzI6IC8qIDMyLWJpdCBtb2RlICovCiAgICAgICAgbWVtb3J5X2V4YW1pbmUobWVtb3J5X3RvX2xpbmVhcl9hZGRyKCZhZGRyKSwgMjQsICd4Jyk7CiAgICAgICAgYnJlYWs7CiAgICBjYXNlIEFkZHJNb2RlUmVhbDogIC8qIDE2LWJpdCBtb2RlICovCiAgICBjYXNlIEFkZHJNb2RlMTYxNjoKICAgICAgICBtZW1vcnlfZXhhbWluZShtZW1vcnlfdG9fbGluZWFyX2FkZHIoJmFkZHIpLCAyNCwgJ3cnKTsKCWJyZWFrOwogICAgfQp9CgppbnQgc3RhY2tfc2V0X2ZyYW1lKGludCBuZXdmcmFtZSkKewogICAgQUREUkVTUyAgICAgYWRkcjsKCiAgICBkYmdfY3Vycl9mcmFtZSA9IG5ld2ZyYW1lOwogICAgaWYgKGRiZ19jdXJyX2ZyYW1lID49IG5mcmFtZSkgZGJnX2N1cnJfZnJhbWUgPSBuZnJhbWUgLSAxOwogICAgaWYgKGRiZ19jdXJyX2ZyYW1lIDwgMCkgICAgICAgZGJnX2N1cnJfZnJhbWUgPSAwOwoKICAgIGFkZHIuTW9kZSA9IEFkZHJNb2RlRmxhdDsKICAgIGFkZHIuT2Zmc2V0ID0gZnJhbWVzW2RiZ19jdXJyX2ZyYW1lXS5JbnN0cnVjdGlvbk9mZnNldDsKICAgIHNvdXJjZV9saXN0X2Zyb21fYWRkcigmYWRkciwgMCk7CiAgICByZXR1cm4gVFJVRTsKfQoKaW50IHN0YWNrX2dldF9mcmFtZShTWU1CT0xfSU5GTyogc3ltYm9sLCBJTUFHRUhMUF9TVEFDS19GUkFNRSogaWhzZikKewogICAgRFdPUkQ2NCAgICAgZGlzcDsKICAgIC8qCiAgICAgKiBJZiB3ZSBkb24ndCBoYXZlIGEgdmFsaWQgYmFja3RyYWNlLCB0aGVuIGp1c3QgcmV0dXJuLgogICAgICovCiAgICBpZiAoZnJhbWVzID09IE5VTEwpIHJldHVybiBGQUxTRTsKCiAgICAvKgogICAgICogSWYgd2UgZG9uJ3Qga25vdyB3aGF0IHRoZSBjdXJyZW50IGZ1bmN0aW9uIGlzLCB0aGVuIHdlIGFsc28gaGF2ZQogICAgICogbm90aGluZyB0byByZXBvcnQgaGVyZS4KICAgICAqLwogICAgaWYgKCFTeW1Gcm9tQWRkcihkYmdfY3Vycl9wcm9jZXNzLT5oYW5kbGUsIGZyYW1lc1tkYmdfY3Vycl9mcmFtZV0uSW5zdHJ1Y3Rpb25PZmZzZXQsCiAgICAgICAgICAgICAgICAgICAgICZkaXNwLCBzeW1ib2wpKQogICAgICAgIHJldHVybiBGQUxTRTsKICAgIGlmIChpaHNmKSAqaWhzZiA9IGZyYW1lc1tkYmdfY3Vycl9mcmFtZV07CgogICAgcmV0dXJuIFRSVUU7Cn0KCnZvaWQgc3RhY2tfYmFja3RyYWNlKERXT1JEIHRpZCwgQk9PTCBub2lzeSkKewogICAgU1RBQ0tGUkFNRSAgICAgICAgICAgICAgICAgIHNmOwogICAgQ09OVEVYVCAgICAgICAgICAgICAgICAgICAgIHNhdmVkX2RiZ19jb250ZXh0OwogICAgc3RydWN0IGRiZ190aHJlYWQqICAgICAgICAgIHRocmVhZDsKICAgIHVuc2lnbmVkICAgICAgICAgICAgICAgICAgICBuZjsKCiAgICBpZiAodGlkID09IC0xKSAgLyogYmFja3RyYWNlIGV2ZXJ5IHRocmVhZCBpbiBldmVyeSBwcm9jZXNzIGV4Y2VwdCB0aGUgZGVidWdnZXIgaXRzZWxmLCBpbnZva2luZyB2aWEgImJ0IGFsbCIgKi8KICAgIHsKICAgICAgICBUSFJFQURFTlRSWTMyIGVudHJ5OwogICAgICAgIEhBTkRMRSBzbmFwc2hvdCA9IENyZWF0ZVRvb2xoZWxwMzJTbmFwc2hvdChUSDMyQ1NfU05BUFRIUkVBRCwgMCk7CiAgICAgICAgCiAgICAgICAgaWYgKHNuYXBzaG90ID09IElOVkFMSURfSEFORExFX1ZBTFVFKQogICAgICAgIHsKICAgICAgICAgICAgZGJnX3ByaW50ZigidW5hYmxlIHRvIGNyZWF0ZSB0b29saGVscCBzbmFwc2hvdFxuIik7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgZW50cnkuZHdTaXplID0gc2l6ZW9mKGVudHJ5KTsKICAgICAgICAKICAgICAgICBpZiAoIVRocmVhZDMyRmlyc3Qoc25hcHNob3QsICZlbnRyeSkpCiAgICAgICAgewogICAgICAgICAgICBDbG9zZUhhbmRsZShzbmFwc2hvdCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgZG8KICAgICAgICB7CiAgICAgICAgICAgIGlmIChlbnRyeS50aDMyT3duZXJQcm9jZXNzSUQgPT0gR2V0Q3VycmVudFByb2Nlc3NJZCgpKSBjb250aW51ZTsKICAgICAgICAgICAgaWYgKGRiZ19jdXJyX3Byb2Nlc3MpIGRiZ19kZXRhY2hfZGVidWdnZWUoKTsKCiAgICAgICAgICAgIGRiZ19wcmludGYoIlxuIik7CiAgICAgICAgICAgIGlmICghZGJnX2F0dGFjaF9kZWJ1Z2dlZShlbnRyeS50aDMyT3duZXJQcm9jZXNzSUQsIEZBTFNFLCBUUlVFKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZGJnX3ByaW50ZigiXG53YXJuaW5nOiBjb3VsZCBub3QgYXR0YWNoIHRvIDB4JWx4XG4iLCBlbnRyeS50aDMyT3duZXJQcm9jZXNzSUQpOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGRiZ19wcmludGYoIkJhY2t0cmFjaW5nIGZvciB0aHJlYWQgMHglbHggaW4gcHJvY2VzcyAweCVseCAoJXMpOlxuIiwgZW50cnkudGgzMlRocmVhZElELCBkYmdfY3Vycl9waWQsIGRiZ19jdXJyX3Byb2Nlc3MtPmltYWdlTmFtZSk7CiAgICAgICAgICAgIAogICAgICAgICAgICBzdGFja19iYWNrdHJhY2UoZW50cnkudGgzMlRocmVhZElELCBUUlVFKTsKICAgICAgICB9CiAgICAgICAgd2hpbGUgKFRocmVhZDMyTmV4dChzbmFwc2hvdCwgJmVudHJ5KSk7CgogICAgICAgIGlmIChkYmdfY3Vycl9wcm9jZXNzKSBkYmdfZGV0YWNoX2RlYnVnZ2VlKCk7CiAgICAgICAgQ2xvc2VIYW5kbGUoc25hcHNob3QpOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoIWRiZ19jdXJyX3Byb2Nlc3MpIAogICAgewogICAgICAgIGRiZ19wcmludGYoIllvdSBtdXN0IGJlIGF0dGFjaGVkIHRvIGEgcHJvY2VzcyB0byBydW4gdGhpcyBjb21tYW5kLlxuIik7CiAgICAgICAgcmV0dXJuOwogICAgfQogICAgCiAgICBzYXZlZF9kYmdfY29udGV4dCA9IGRiZ19jb250ZXh0OyAvKiBhcyB3ZSBtYXkgbW9kaWZ5IGRiZ19jb250ZXh0Li4uICovCiAgICBpZiAodGlkID09IGRiZ19jdXJyX3RpZCkKICAgIHsKICAgICAgICB0aHJlYWQgPSBkYmdfY3Vycl90aHJlYWQ7CiAgICAgICAgSGVhcEZyZWUoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgZnJhbWVzKTsKICAgICAgICBmcmFtZXMgPSBOVUxMOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgICB0aHJlYWQgPSBkYmdfZ2V0X3RocmVhZChkYmdfY3Vycl9wcm9jZXNzLCB0aWQpOwogICAgICAgICBpZiAoIXRocmVhZCkKICAgICAgICAgewogICAgICAgICAgICAgIGRiZ19wcmludGYoIlVua25vd24gdGhyZWFkIGlkICgweCUwOGx4KSBpbiBjdXJyZW50IHByb2Nlc3NcbiIsIHRpZCk7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICB9CiAgICAgICAgIG1lbXNldCgmZGJnX2NvbnRleHQsIDAsIHNpemVvZihkYmdfY29udGV4dCkpOwogICAgICAgICBkYmdfY29udGV4dC5Db250ZXh0RmxhZ3MgPSBDT05URVhUX0ZVTEw7CiAgICAgICAgIGlmIChTdXNwZW5kVGhyZWFkKHRocmVhZC0+aGFuZGxlKSAhPSAtMSkKICAgICAgICAgewogICAgICAgICAgICAgaWYgKCFHZXRUaHJlYWRDb250ZXh0KHRocmVhZC0+aGFuZGxlLCAmZGJnX2NvbnRleHQpKQogICAgICAgICAgICAgewogICAgICAgICAgICAgICAgIGRiZ19wcmludGYoIkNhbid0IGdldCBjb250ZXh0IGZvciB0aHJlYWQgMHglbHggaW4gY3VycmVudCBwcm9jZXNzXG4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlkKTsKICAgICAgICAgICAgICAgICBSZXN1bWVUaHJlYWQodGhyZWFkLT5oYW5kbGUpOwogICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgIH0KICAgICAgICAgfQogICAgICAgICBlbHNlCiAgICAgICAgIHsKICAgICAgICAgICAgIGRiZ19wcmludGYoIkNhbid0IHN1c3BlbmQgdGhyZWFkIDB4JWx4IGluIGN1cnJlbnQgcHJvY2Vzc1xuIiwgdGlkKTsKICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgfQogICAgfQoKICAgIG5mID0gMDsKICAgIG1lbXNldCgmc2YsIDAsIHNpemVvZihzZikpOwogICAgbWVtb3J5X2dldF9jdXJyZW50X2ZyYW1lKCZzZi5BZGRyRnJhbWUpOwogICAgbWVtb3J5X2dldF9jdXJyZW50X3BjKCZzZi5BZGRyUEMpOwoKICAgIC8qIGRvbid0IGNvbmZ1c2UgU3RhY2tXYWxrIGJ5IHBhc3NpbmcgaW4gaW5jb25zaXN0ZW50IGFkZHJlc3NlcyAqLwogICAgaWYgKChzZi5BZGRyUEMuTW9kZSA9PSBBZGRyTW9kZUZsYXQpICYmIChzZi5BZGRyRnJhbWUuTW9kZSAhPSBBZGRyTW9kZUZsYXQpKQogICAgewogICAgICAgIHNmLkFkZHJGcmFtZS5PZmZzZXQgPSAoRFdPUkQpbWVtb3J5X3RvX2xpbmVhcl9hZGRyKCZzZi5BZGRyRnJhbWUpOwogICAgICAgIHNmLkFkZHJGcmFtZS5Nb2RlID0gQWRkck1vZGVGbGF0OwogICAgfQoKICAgIGlmIChub2lzeSkgZGJnX3ByaW50ZigiQmFja3RyYWNlOlxuIik7CiAgICB3aGlsZSAoU3RhY2tXYWxrKElNQUdFX0ZJTEVfTUFDSElORV9JMzg2LCBkYmdfY3Vycl9wcm9jZXNzLT5oYW5kbGUsIAogICAgICAgICAgICAgICAgICAgICB0aHJlYWQtPmhhbmRsZSwgJnNmLCAmZGJnX2NvbnRleHQsIE5VTEwsIFN5bUZ1bmN0aW9uVGFibGVBY2Nlc3MsCiAgICAgICAgICAgICAgICAgICAgIFN5bUdldE1vZHVsZUJhc2UsIE5VTEwpKQogICAgewogICAgICAgIGlmICh0aWQgPT0gZGJnX2N1cnJfdGlkKQogICAgICAgIHsKICAgICAgICAgICAgZnJhbWVzID0gZGJnX2hlYXBfcmVhbGxvYyhmcmFtZXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZiArIDEpICogc2l6ZW9mKElNQUdFSExQX1NUQUNLX0ZSQU1FKSk7CgogICAgICAgICAgICBmcmFtZXNbbmZdLkluc3RydWN0aW9uT2Zmc2V0ID0gKHVuc2lnbmVkIGxvbmcpbWVtb3J5X3RvX2xpbmVhcl9hZGRyKCZzZi5BZGRyUEMpOwogICAgICAgICAgICBmcmFtZXNbbmZdLkZyYW1lT2Zmc2V0ID0gKHVuc2lnbmVkIGxvbmcpbWVtb3J5X3RvX2xpbmVhcl9hZGRyKCZzZi5BZGRyRnJhbWUpOwogICAgICAgIH0KICAgICAgICBpZiAobm9pc3kpCiAgICAgICAgewogICAgICAgICAgICBkYmdfcHJpbnRmKCIlcyVkICIsIAogICAgICAgICAgICAgICAgICAgICAgICh0aWQgPT0gZGJnX2N1cnJfdGlkICYmIG5mID09IGRiZ19jdXJyX2ZyYW1lID8gIj0+IiA6ICIgICIpLAogICAgICAgICAgICAgICAgICAgICAgIG5mICsgMSk7CiAgICAgICAgICAgIHByaW50X2FkZHJfYW5kX2FyZ3MoJnNmLkFkZHJQQywgJnNmLkFkZHJGcmFtZSk7CiAgICAgICAgICAgIGRiZ19wcmludGYoIiAoIik7CiAgICAgICAgICAgIHByaW50X2JhcmVfYWRkcmVzcygmc2YuQWRkckZyYW1lKTsKICAgICAgICAgICAgZGJnX3ByaW50ZigiKVxuIik7CiAgICAgICAgfQogICAgICAgIG5mKys7CiAgICAgICAgLyogd2UndmUgcHJvYmFibHkgZ290dGVuIG91cnNlbHZlcyBpbnRvIGFuIGluZmluaXRlIGxvb3Agc28gYmFpbCAqLwogICAgICAgIGlmIChuZiA+IDIwMCkKICAgICAgICAgICAgYnJlYWs7CiAgICB9CgogICAgZGJnX2NvbnRleHQgPSBzYXZlZF9kYmdfY29udGV4dDsKICAgIGlmICh0aWQgPT0gZGJnX2N1cnJfdGlkKQogICAgewogICAgICAgIG5mcmFtZSA9IG5mOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIFJlc3VtZVRocmVhZCh0aHJlYWQtPmhhbmRsZSk7CiAgICB9Cn0K