LyoKICogRGVidWdnZXIgc3RhY2sgaGFuZGxpbmcKICoKICogQ29weXJpZ2h0IDE5OTUgQWxleGFuZHJlIEp1bGxpYXJkCiAqIENvcHlyaWdodCAxOTk2IEVyaWMgWW91bmdkYWxlCiAqIENvcHlyaWdodCAxOTk5IE92ZSBL5XZlbgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKICovCgojaW5jbHVkZSAiY29uZmlnLmgiCgojaW5jbHVkZSA8c3RkbGliLmg+CgojaW5jbHVkZSAiZGVidWdnZXIuaCIKI2luY2x1ZGUgInN0YWNrZnJhbWUuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKI2luY2x1ZGUgInRsaGVscDMyLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTCh3aW5lZGJnKTsKCnN0YXRpYyBpbnQgICAgICAgICAgICAgICAgICAgICAgbmZyYW1lOwpzdGF0aWMgSU1BR0VITFBfU1RBQ0tfRlJBTUUqICAgIGZyYW1lcyA9IE5VTEw7CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogICAgICAgICAgIHN0YWNrX2luZm8KICoKICogRHVtcCB0aGUgdG9wIG9mIHRoZSBzdGFjawogKi8Kdm9pZCBzdGFja19pbmZvKHZvaWQpCnsKICAgIHN0cnVjdCBkYmdfbHZhbHVlIGx2YWx1ZTsKCiAgICBsdmFsdWUuY29va2llID0gMDsKICAgIGx2YWx1ZS50eXBlLmlkID0gZGJnX2l0eXBlX25vbmU7CiAgICBsdmFsdWUudHlwZS5tb2R1bGUgPSAwOwoKICAgIC8qIEZJWE1FOiB3ZSBhc3N1bWUgc3RhY2sgZ3Jvd3MgdGhlIHNhbWUgd2F5IGFzIG9uIGkzODYgKi8KICAgIGlmICghbWVtb3J5X2dldF9jdXJyZW50X3N0YWNrKCZsdmFsdWUuYWRkcikpCiAgICAgICAgZGJnX3ByaW50ZigiQmFkIHNlZ21lbnQgKCVkKVxuIiwgbHZhbHVlLmFkZHIuU2VnbWVudCk7CgogICAgZGJnX3ByaW50ZigiU3RhY2sgZHVtcDpcbiIpOwogICAgc3dpdGNoIChsdmFsdWUuYWRkci5Nb2RlKQogICAgewogICAgY2FzZSBBZGRyTW9kZUZsYXQ6IC8qIDMyLWJpdCBtb2RlICovCiAgICBjYXNlIEFkZHJNb2RlMTYzMjogLyogMzItYml0IG1vZGUgKi8KICAgICAgICBtZW1vcnlfZXhhbWluZSgmbHZhbHVlLCAyNCwgJ3gnKTsKICAgICAgICBicmVhazsKICAgIGNhc2UgQWRkck1vZGVSZWFsOiAgLyogMTYtYml0IG1vZGUgKi8KICAgIGNhc2UgQWRkck1vZGUxNjE2OgogICAgICAgIG1lbW9yeV9leGFtaW5lKCZsdmFsdWUsIDI0LCAndycpOwoJYnJlYWs7CiAgICB9Cn0KCmludCBzdGFja19zZXRfZnJhbWUoaW50IG5ld2ZyYW1lKQp7CiAgICBBRERSRVNTICAgICBhZGRyOwoKICAgIGRiZ19jdXJyX2ZyYW1lID0gbmV3ZnJhbWU7CiAgICBpZiAoZGJnX2N1cnJfZnJhbWUgPj0gbmZyYW1lKSBkYmdfY3Vycl9mcmFtZSA9IG5mcmFtZSAtIDE7CiAgICBpZiAoZGJnX2N1cnJfZnJhbWUgPCAwKSAgICAgICBkYmdfY3Vycl9mcmFtZSA9IDA7CgogICAgYWRkci5Nb2RlID0gQWRkck1vZGVGbGF0OwogICAgYWRkci5PZmZzZXQgPSBmcmFtZXNbZGJnX2N1cnJfZnJhbWVdLkluc3RydWN0aW9uT2Zmc2V0OwogICAgc291cmNlX2xpc3RfZnJvbV9hZGRyKCZhZGRyLCAwKTsKICAgIHJldHVybiBUUlVFOwp9CgppbnQgc3RhY2tfZ2V0X2ZyYW1lKFNZTUJPTF9JTkZPKiBzeW1ib2wsIElNQUdFSExQX1NUQUNLX0ZSQU1FKiBpaHNmKQp7CiAgICBEV09SRDY0ICAgICBkaXNwOwogICAgLyoKICAgICAqIElmIHdlIGRvbid0IGhhdmUgYSB2YWxpZCBiYWNrdHJhY2UsIHRoZW4ganVzdCByZXR1cm4uCiAgICAgKi8KICAgIGlmIChmcmFtZXMgPT0gTlVMTCkgcmV0dXJuIEZBTFNFOwoKICAgIC8qCiAgICAgKiBJZiB3ZSBkb24ndCBrbm93IHdoYXQgdGhlIGN1cnJlbnQgZnVuY3Rpb24gaXMsIHRoZW4gd2UgYWxzbyBoYXZlCiAgICAgKiBub3RoaW5nIHRvIHJlcG9ydCBoZXJlLgogICAgICovCiAgICBpZiAoIVN5bUZyb21BZGRyKGRiZ19jdXJyX3Byb2Nlc3MtPmhhbmRsZSwgZnJhbWVzW2RiZ19jdXJyX2ZyYW1lXS5JbnN0cnVjdGlvbk9mZnNldCwKICAgICAgICAgICAgICAgICAgICAgJmRpc3AsIHN5bWJvbCkpCiAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgaWYgKGloc2YpICppaHNmID0gZnJhbWVzW2RiZ19jdXJyX2ZyYW1lXTsKCiAgICByZXR1cm4gVFJVRTsKfQoKdm9pZCBzdGFja19iYWNrdHJhY2UoRFdPUkQgdGlkLCBCT09MIG5vaXN5KQp7CiAgICBTVEFDS0ZSQU1FICAgICAgICAgICAgICAgICAgc2Y7CiAgICBDT05URVhUICAgICAgICAgICAgICAgICAgICAgc2F2ZWRfZGJnX2NvbnRleHQ7CiAgICBzdHJ1Y3QgZGJnX3RocmVhZCogICAgICAgICAgdGhyZWFkOwogICAgdW5zaWduZWQgICAgICAgICAgICAgICAgICAgIG5mOwoKICAgIGlmICh0aWQgPT0gLTEpICAvKiBiYWNrdHJhY2UgZXZlcnkgdGhyZWFkIGluIGV2ZXJ5IHByb2Nlc3MgZXhjZXB0IHRoZSBkZWJ1Z2dlciBpdHNlbGYsIGludm9raW5nIHZpYSAiYnQgYWxsIiAqLwogICAgewogICAgICAgIFRIUkVBREVOVFJZMzIgZW50cnk7CiAgICAgICAgSEFORExFIHNuYXBzaG90ID0gQ3JlYXRlVG9vbGhlbHAzMlNuYXBzaG90KFRIMzJDU19TTkFQVEhSRUFELCAwKTsKICAgICAgICAKICAgICAgICBpZiAoc25hcHNob3QgPT0gSU5WQUxJRF9IQU5ETEVfVkFMVUUpCiAgICAgICAgewogICAgICAgICAgICBkYmdfcHJpbnRmKCJ1bmFibGUgdG8gY3JlYXRlIHRvb2xoZWxwIHNuYXBzaG90XG4iKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBlbnRyeS5kd1NpemUgPSBzaXplb2YoZW50cnkpOwogICAgICAgIAogICAgICAgIGlmICghVGhyZWFkMzJGaXJzdChzbmFwc2hvdCwgJmVudHJ5KSkKICAgICAgICB7CiAgICAgICAgICAgIENsb3NlSGFuZGxlKHNuYXBzaG90KTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBkbwogICAgICAgIHsKICAgICAgICAgICAgaWYgKGVudHJ5LnRoMzJPd25lclByb2Nlc3NJRCA9PSBHZXRDdXJyZW50UHJvY2Vzc0lkKCkpIGNvbnRpbnVlOwogICAgICAgICAgICBpZiAoZGJnX2N1cnJfcHJvY2VzcykgZGJnX2RldGFjaF9kZWJ1Z2dlZSgpOwoKICAgICAgICAgICAgZGJnX3ByaW50ZigiXG4iKTsKICAgICAgICAgICAgaWYgKCFkYmdfYXR0YWNoX2RlYnVnZ2VlKGVudHJ5LnRoMzJPd25lclByb2Nlc3NJRCwgRkFMU0UsIFRSVUUpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBkYmdfcHJpbnRmKCJcbndhcm5pbmc6IGNvdWxkIG5vdCBhdHRhY2ggdG8gMHglbHhcbiIsIGVudHJ5LnRoMzJPd25lclByb2Nlc3NJRCk7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgZGJnX3ByaW50ZigiQmFja3RyYWNpbmcgZm9yIHRocmVhZCAweCVseCBpbiBwcm9jZXNzIDB4JWx4ICglcyk6XG4iLCBlbnRyeS50aDMyVGhyZWFkSUQsIGRiZ19jdXJyX3BpZCwgZGJnX2N1cnJfcHJvY2Vzcy0+aW1hZ2VOYW1lKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIHN0YWNrX2JhY2t0cmFjZShlbnRyeS50aDMyVGhyZWFkSUQsIFRSVUUpOwogICAgICAgIH0KICAgICAgICB3aGlsZSAoVGhyZWFkMzJOZXh0KHNuYXBzaG90LCAmZW50cnkpKTsKCiAgICAgICAgaWYgKGRiZ19jdXJyX3Byb2Nlc3MpIGRiZ19kZXRhY2hfZGVidWdnZWUoKTsKICAgICAgICBDbG9zZUhhbmRsZShzbmFwc2hvdCk7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmICghZGJnX2N1cnJfcHJvY2VzcykgCiAgICB7CiAgICAgICAgZGJnX3ByaW50ZigiWW91IG11c3QgYmUgYXR0YWNoZWQgdG8gYSBwcm9jZXNzIHRvIHJ1biB0aGlzIGNvbW1hbmQuXG4iKTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICAKICAgIHNhdmVkX2RiZ19jb250ZXh0ID0gZGJnX2NvbnRleHQ7IC8qIGFzIHdlIG1heSBtb2RpZnkgZGJnX2NvbnRleHQuLi4gKi8KICAgIGlmICh0aWQgPT0gZGJnX2N1cnJfdGlkKQogICAgewogICAgICAgIHRocmVhZCA9IGRiZ19jdXJyX3RocmVhZDsKICAgICAgICBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCBmcmFtZXMpOwogICAgICAgIGZyYW1lcyA9IE5VTEw7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgIHRocmVhZCA9IGRiZ19nZXRfdGhyZWFkKGRiZ19jdXJyX3Byb2Nlc3MsIHRpZCk7CiAgICAgICAgIGlmICghdGhyZWFkKQogICAgICAgICB7CiAgICAgICAgICAgICAgZGJnX3ByaW50ZigiVW5rbm93biB0aHJlYWQgaWQgKDB4JTA4bHgpIGluIGN1cnJlbnQgcHJvY2Vzc1xuIiwgdGlkKTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgIH0KICAgICAgICAgbWVtc2V0KCZkYmdfY29udGV4dCwgMCwgc2l6ZW9mKGRiZ19jb250ZXh0KSk7CiAgICAgICAgIGRiZ19jb250ZXh0LkNvbnRleHRGbGFncyA9IENPTlRFWFRfRlVMTDsKICAgICAgICAgaWYgKFN1c3BlbmRUaHJlYWQodGhyZWFkLT5oYW5kbGUpICE9IC0xKQogICAgICAgICB7CiAgICAgICAgICAgICBpZiAoIUdldFRocmVhZENvbnRleHQodGhyZWFkLT5oYW5kbGUsICZkYmdfY29udGV4dCkpCiAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgZGJnX3ByaW50ZigiQ2FuJ3QgZ2V0IGNvbnRleHQgZm9yIHRocmVhZCAweCVseCBpbiBjdXJyZW50IHByb2Nlc3NcbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWQpOwogICAgICAgICAgICAgICAgIFJlc3VtZVRocmVhZCh0aHJlYWQtPmhhbmRsZSk7CiAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgfQogICAgICAgICB9CiAgICAgICAgIGVsc2UKICAgICAgICAgewogICAgICAgICAgICAgZGJnX3ByaW50ZigiQ2FuJ3Qgc3VzcGVuZCB0aHJlYWQgMHglbHggaW4gY3VycmVudCBwcm9jZXNzXG4iLCB0aWQpOwogICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICB9CiAgICB9CgogICAgbmYgPSAwOwogICAgbWVtc2V0KCZzZiwgMCwgc2l6ZW9mKHNmKSk7CiAgICBtZW1vcnlfZ2V0X2N1cnJlbnRfZnJhbWUoJnNmLkFkZHJGcmFtZSk7CiAgICBtZW1vcnlfZ2V0X2N1cnJlbnRfcGMoJnNmLkFkZHJQQyk7CgogICAgLyogZG9uJ3QgY29uZnVzZSBTdGFja1dhbGsgYnkgcGFzc2luZyBpbiBpbmNvbnNpc3RlbnQgYWRkcmVzc2VzICovCiAgICBpZiAoKHNmLkFkZHJQQy5Nb2RlID09IEFkZHJNb2RlRmxhdCkgJiYgKHNmLkFkZHJGcmFtZS5Nb2RlICE9IEFkZHJNb2RlRmxhdCkpCiAgICB7CiAgICAgICAgc2YuQWRkckZyYW1lLk9mZnNldCA9IChEV09SRCltZW1vcnlfdG9fbGluZWFyX2FkZHIoJnNmLkFkZHJGcmFtZSk7CiAgICAgICAgc2YuQWRkckZyYW1lLk1vZGUgPSBBZGRyTW9kZUZsYXQ7CiAgICB9CgogICAgaWYgKG5vaXN5KSBkYmdfcHJpbnRmKCJCYWNrdHJhY2U6XG4iKTsKICAgIHdoaWxlIChTdGFja1dhbGsoSU1BR0VfRklMRV9NQUNISU5FX0kzODYsIGRiZ19jdXJyX3Byb2Nlc3MtPmhhbmRsZSwgCiAgICAgICAgICAgICAgICAgICAgIHRocmVhZC0+aGFuZGxlLCAmc2YsICZkYmdfY29udGV4dCwgTlVMTCwgU3ltRnVuY3Rpb25UYWJsZUFjY2VzcywKICAgICAgICAgICAgICAgICAgICAgU3ltR2V0TW9kdWxlQmFzZSwgTlVMTCkpCiAgICB7CiAgICAgICAgaWYgKHRpZCA9PSBkYmdfY3Vycl90aWQpCiAgICAgICAgewogICAgICAgICAgICBmcmFtZXMgPSBkYmdfaGVhcF9yZWFsbG9jKGZyYW1lcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG5mICsgMSkgKiBzaXplb2YoSU1BR0VITFBfU1RBQ0tfRlJBTUUpKTsKCiAgICAgICAgICAgIGZyYW1lc1tuZl0uSW5zdHJ1Y3Rpb25PZmZzZXQgPSAodW5zaWduZWQgbG9uZyltZW1vcnlfdG9fbGluZWFyX2FkZHIoJnNmLkFkZHJQQyk7CiAgICAgICAgICAgIGZyYW1lc1tuZl0uRnJhbWVPZmZzZXQgPSAodW5zaWduZWQgbG9uZyltZW1vcnlfdG9fbGluZWFyX2FkZHIoJnNmLkFkZHJGcmFtZSk7CiAgICAgICAgfQogICAgICAgIGlmIChub2lzeSkKICAgICAgICB7CiAgICAgICAgICAgIGRiZ19wcmludGYoIiVzJWQgIiwgCiAgICAgICAgICAgICAgICAgICAgICAgKHRpZCA9PSBkYmdfY3Vycl90aWQgJiYgbmYgPT0gZGJnX2N1cnJfZnJhbWUgPyAiPT4iIDogIiAgIiksCiAgICAgICAgICAgICAgICAgICAgICAgbmYgKyAxKTsKICAgICAgICAgICAgcHJpbnRfYWRkcl9hbmRfYXJncygmc2YuQWRkclBDLCAmc2YuQWRkckZyYW1lKTsKICAgICAgICAgICAgZGJnX3ByaW50ZigiICgiKTsKICAgICAgICAgICAgcHJpbnRfYmFyZV9hZGRyZXNzKCZzZi5BZGRyRnJhbWUpOwogICAgICAgICAgICBkYmdfcHJpbnRmKCIpXG4iKTsKICAgICAgICB9CiAgICAgICAgbmYrKzsKICAgICAgICAvKiB3ZSd2ZSBwcm9iYWJseSBnb3R0ZW4gb3Vyc2VsdmVzIGludG8gYW4gaW5maW5pdGUgbG9vcCBzbyBiYWlsICovCiAgICAgICAgaWYgKG5mID4gMjAwKQogICAgICAgICAgICBicmVhazsKICAgIH0KCiAgICBkYmdfY29udGV4dCA9IHNhdmVkX2RiZ19jb250ZXh0OwogICAgaWYgKHRpZCA9PSBkYmdfY3Vycl90aWQpCiAgICB7CiAgICAgICAgbmZyYW1lID0gbmY7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgUmVzdW1lVGhyZWFkKHRocmVhZC0+aGFuZGxlKTsKICAgIH0KfQo=