LyoKICogRGVidWdnZXIgc3RhY2sgaGFuZGxpbmcKICoKICogQ29weXJpZ2h0IDE5OTUgQWxleGFuZHJlIEp1bGxpYXJkCiAqIENvcHlyaWdodCAxOTk2IEVyaWMgWW91bmdkYWxlCiAqIENvcHlyaWdodCAxOTk5IE92ZSBL5XZlbgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKICovCgojaW5jbHVkZSAiY29uZmlnLmgiCgojaW5jbHVkZSA8c3RkbGliLmg+CgojaW5jbHVkZSAiZGVidWdnZXIuaCIKI2luY2x1ZGUgInN0YWNrZnJhbWUuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKI2luY2x1ZGUgInRsaGVscDMyLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTCh3aW5lZGJnKTsKCnN0YXRpYyBpbnQgICAgICAgICAgICAgICAgICAgICAgbmZyYW1lOwpzdGF0aWMgSU1BR0VITFBfU1RBQ0tfRlJBTUUqICAgIGZyYW1lcyA9IE5VTEw7CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogICAgICAgICAgIHN0YWNrX2luZm8KICoKICogRHVtcCB0aGUgdG9wIG9mIHRoZSBzdGFjawogKi8Kdm9pZCBzdGFja19pbmZvKHZvaWQpCnsKICAgIEFERFJFU1MgICAgICAgICAgICAgYWRkcjsKCiAgICAvKiBGSVhNRTogd2UgYXNzdW1lIHN0YWNrIGdyb3dzIHRoZSBzYW1lIHdheSBhcyBvbiBpMzg2ICovCiAgICBpZiAoIW1lbW9yeV9nZXRfY3VycmVudF9zdGFjaygmYWRkcikpCiAgICAgICAgZGJnX3ByaW50ZigiQmFkIHNlZ21lbnQgKCVkKVxuIiwgYWRkci5TZWdtZW50KTsKCiAgICBkYmdfcHJpbnRmKCJTdGFjayBkdW1wOlxuIik7CiAgICBzd2l0Y2ggKGFkZHIuTW9kZSkKICAgIHsKICAgIGNhc2UgQWRkck1vZGVGbGF0OiAvKiAzMi1iaXQgbW9kZSAqLwogICAgY2FzZSBBZGRyTW9kZTE2MzI6IC8qIDMyLWJpdCBtb2RlICovCiAgICAgICAgbWVtb3J5X2V4YW1pbmUobWVtb3J5X3RvX2xpbmVhcl9hZGRyKCZhZGRyKSwgMjQsICd4Jyk7CiAgICAgICAgYnJlYWs7CiAgICBjYXNlIEFkZHJNb2RlUmVhbDogIC8qIDE2LWJpdCBtb2RlICovCiAgICBjYXNlIEFkZHJNb2RlMTYxNjoKICAgICAgICBtZW1vcnlfZXhhbWluZShtZW1vcnlfdG9fbGluZWFyX2FkZHIoJmFkZHIpLCAyNCwgJ3cnKTsKCWJyZWFrOwogICAgfQp9CgppbnQgc3RhY2tfc2V0X2ZyYW1lKGludCBuZXdmcmFtZSkKewogICAgQUREUkVTUyAgICAgYWRkcjsKCiAgICBkYmdfY3Vycl9mcmFtZSA9IG5ld2ZyYW1lOwogICAgaWYgKGRiZ19jdXJyX2ZyYW1lID49IG5mcmFtZSkgZGJnX2N1cnJfZnJhbWUgPSBuZnJhbWUgLSAxOwogICAgaWYgKGRiZ19jdXJyX2ZyYW1lIDwgMCkgICAgICAgZGJnX2N1cnJfZnJhbWUgPSAwOwoKICAgIGFkZHIuTW9kZSA9IEFkZHJNb2RlRmxhdDsKICAgIGFkZHIuT2Zmc2V0ID0gZnJhbWVzW2RiZ19jdXJyX2ZyYW1lXS5JbnN0cnVjdGlvbk9mZnNldDsKICAgIHNvdXJjZV9saXN0X2Zyb21fYWRkcigmYWRkciwgMCk7CiAgICByZXR1cm4gVFJVRTsKfQoKaW50IHN0YWNrX2dldF9mcmFtZShTWU1CT0xfSU5GTyogc3ltYm9sLCBJTUFHRUhMUF9TVEFDS19GUkFNRSogaWhzZikKewogICAgLyoKICAgICAqIElmIHdlIGRvbid0IGhhdmUgYSB2YWxpZCBiYWNrdHJhY2UsIHRoZW4ganVzdCByZXR1cm4uCiAgICAgKi8KICAgIGlmIChmcmFtZXMgPT0gTlVMTCkgcmV0dXJuIEZBTFNFOwoKICAgIC8qCiAgICAgKiBJZiB3ZSBkb24ndCBrbm93IHdoYXQgdGhlIGN1cnJlbnQgZnVuY3Rpb24gaXMsIHRoZW4gd2UgYWxzbyBoYXZlCiAgICAgKiBub3RoaW5nIHRvIHJlcG9ydCBoZXJlLgogICAgICovCiAgICBTeW1Gcm9tQWRkcihkYmdfY3Vycl9wcm9jZXNzLT5oYW5kbGUsIGZyYW1lc1tkYmdfY3Vycl9mcmFtZV0uSW5zdHJ1Y3Rpb25PZmZzZXQsCiAgICAgICAgICAgICAgICBOVUxMLCBzeW1ib2wpOwogICAgaWYgKGloc2YpICppaHNmID0gZnJhbWVzW2RiZ19jdXJyX2ZyYW1lXTsKCiAgICByZXR1cm4gVFJVRTsKfQoKdm9pZCBzdGFja19iYWNrdHJhY2UoRFdPUkQgdGlkLCBCT09MIG5vaXN5KQp7CiAgICBTVEFDS0ZSQU1FICAgICAgICAgICAgICAgICAgc2Y7CiAgICBDT05URVhUICAgICAgICAgICAgICAgICAgICAgc2F2ZWRfZGJnX2NvbnRleHQ7CiAgICBzdHJ1Y3QgZGJnX3RocmVhZCogICAgICAgICAgdGhyZWFkOwogICAgdW5zaWduZWQgICAgICAgICAgICAgICAgICAgIG5mOwoKICAgIGlmICh0aWQgPT0gLTEpICAvKiBiYWNrdHJhY2UgZXZlcnkgdGhyZWFkIGluIGV2ZXJ5IHByb2Nlc3MgZXhjZXB0IHRoZSBkZWJ1Z2dlciBpdHNlbGYsIGludm9raW5nIHZpYSAiYnQgYWxsIiAqLwogICAgewogICAgICAgIFRIUkVBREVOVFJZMzIgZW50cnk7CiAgICAgICAgSEFORExFIHNuYXBzaG90ID0gQ3JlYXRlVG9vbGhlbHAzMlNuYXBzaG90KFRIMzJDU19TTkFQVEhSRUFELCAwKTsKICAgICAgICAKICAgICAgICBpZiAoc25hcHNob3QgPT0gSU5WQUxJRF9IQU5ETEVfVkFMVUUpCiAgICAgICAgewogICAgICAgICAgICBkYmdfcHJpbnRmKCJ1bmFibGUgdG8gY3JlYXRlIHRvb2xoZWxwIHNuYXBzaG90XG4iKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBlbnRyeS5kd1NpemUgPSBzaXplb2YoZW50cnkpOwogICAgICAgIAogICAgICAgIGlmICghVGhyZWFkMzJGaXJzdChzbmFwc2hvdCwgJmVudHJ5KSkKICAgICAgICB7CiAgICAgICAgICAgIENsb3NlSGFuZGxlKHNuYXBzaG90KTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBkbwogICAgICAgIHsKICAgICAgICAgICAgaWYgKGVudHJ5LnRoMzJPd25lclByb2Nlc3NJRCA9PSBHZXRDdXJyZW50UHJvY2Vzc0lkKCkpIGNvbnRpbnVlOwogICAgICAgICAgICBpZiAoZGJnX2N1cnJfcHJvY2VzcykgZGJnX2RldGFjaF9kZWJ1Z2dlZSgpOwoKICAgICAgICAgICAgZGJnX3ByaW50ZigiXG4iKTsKICAgICAgICAgICAgaWYgKCFkYmdfYXR0YWNoX2RlYnVnZ2VlKGVudHJ5LnRoMzJPd25lclByb2Nlc3NJRCwgRkFMU0UsIFRSVUUpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBkYmdfcHJpbnRmKCJcbndhcm5pbmc6IGNvdWxkIG5vdCBhdHRhY2ggdG8gMHglbHhcbiIsIGVudHJ5LnRoMzJPd25lclByb2Nlc3NJRCk7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgZGJnX3ByaW50ZigiQmFja3RyYWNpbmcgZm9yIHRocmVhZCAweCVseCBpbiBwcm9jZXNzIDB4JWx4ICglcyk6XG4iLCBlbnRyeS50aDMyVGhyZWFkSUQsIGRiZ19jdXJyX3BpZCwgZGJnX2N1cnJfcHJvY2Vzcy0+aW1hZ2VOYW1lKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIHN0YWNrX2JhY2t0cmFjZShlbnRyeS50aDMyVGhyZWFkSUQsIFRSVUUpOwogICAgICAgIH0KICAgICAgICB3aGlsZSAoVGhyZWFkMzJOZXh0KHNuYXBzaG90LCAmZW50cnkpKTsKCiAgICAgICAgaWYgKGRiZ19jdXJyX3Byb2Nlc3MpIGRiZ19kZXRhY2hfZGVidWdnZWUoKTsKICAgICAgICBDbG9zZUhhbmRsZShzbmFwc2hvdCk7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmICghZGJnX2N1cnJfcHJvY2VzcykgCiAgICB7CiAgICAgICAgZGJnX3ByaW50ZigiWW91IG11c3QgYmUgYXR0YWNoZWQgdG8gYSBwcm9jZXNzIHRvIHJ1biB0aGlzIGNvbW1hbmQuXG4iKTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICAKICAgIHNhdmVkX2RiZ19jb250ZXh0ID0gZGJnX2NvbnRleHQ7IC8qIGFzIHdlIG1heSBtb2RpZnkgZGJnX2NvbnRleHQuLi4gKi8KICAgIGlmICh0aWQgPT0gZGJnX2N1cnJfdGlkKQogICAgewogICAgICAgIHRocmVhZCA9IGRiZ19jdXJyX3RocmVhZDsKICAgICAgICBpZiAoZnJhbWVzKSBIZWFwRnJlZShHZXRQcm9jZXNzSGVhcCgpLCAwLCBmcmFtZXMpOwogICAgICAgIGZyYW1lcyA9IE5VTEw7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgIHRocmVhZCA9IGRiZ19nZXRfdGhyZWFkKGRiZ19jdXJyX3Byb2Nlc3MsIHRpZCk7CiAgICAgICAgIGlmICghdGhyZWFkKQogICAgICAgICB7CiAgICAgICAgICAgICAgZGJnX3ByaW50ZigiVW5rbm93biB0aHJlYWQgaWQgKDB4JTA4bHgpIGluIGN1cnJlbnQgcHJvY2Vzc1xuIiwgdGlkKTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgIH0KICAgICAgICAgbWVtc2V0KCZkYmdfY29udGV4dCwgMCwgc2l6ZW9mKGRiZ19jb250ZXh0KSk7CiAgICAgICAgIGRiZ19jb250ZXh0LkNvbnRleHRGbGFncyA9IENPTlRFWFRfRlVMTDsKICAgICAgICAgaWYgKFN1c3BlbmRUaHJlYWQodGhyZWFkLT5oYW5kbGUpICE9IC0xKQogICAgICAgICB7CiAgICAgICAgICAgICBpZiAoIUdldFRocmVhZENvbnRleHQodGhyZWFkLT5oYW5kbGUsICZkYmdfY29udGV4dCkpCiAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgZGJnX3ByaW50ZigiQ2FuJ3QgZ2V0IGNvbnRleHQgZm9yIHRocmVhZCAweCVseCBpbiBjdXJyZW50IHByb2Nlc3NcbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWQpOwogICAgICAgICAgICAgICAgIFJlc3VtZVRocmVhZCh0aHJlYWQtPmhhbmRsZSk7CiAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgfQogICAgICAgICB9CiAgICAgICAgIGVsc2UKICAgICAgICAgewogICAgICAgICAgICAgZGJnX3ByaW50ZigiQ2FuJ3Qgc3VzcGVuZCB0aHJlYWQgMHglbHggaW4gY3VycmVudCBwcm9jZXNzXG4iLCB0aWQpOwogICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICB9CiAgICB9CgogICAgbmYgPSAwOwogICAgbWVtc2V0KCZzZiwgMCwgc2l6ZW9mKHNmKSk7CiAgICBtZW1vcnlfZ2V0X2N1cnJlbnRfZnJhbWUoJnNmLkFkZHJGcmFtZSk7CiAgICBtZW1vcnlfZ2V0X2N1cnJlbnRfcGMoJnNmLkFkZHJQQyk7CgogICAgaWYgKG5vaXN5KSBkYmdfcHJpbnRmKCJCYWNrdHJhY2U6XG4iKTsKICAgIHdoaWxlIChTdGFja1dhbGsoSU1BR0VfRklMRV9NQUNISU5FX0kzODYsIGRiZ19jdXJyX3Byb2Nlc3MtPmhhbmRsZSwgCiAgICAgICAgICAgICAgICAgICAgIHRocmVhZC0+aGFuZGxlLCAmc2YsICZkYmdfY29udGV4dCwgTlVMTCwgU3ltRnVuY3Rpb25UYWJsZUFjY2VzcywKICAgICAgICAgICAgICAgICAgICAgU3ltR2V0TW9kdWxlQmFzZSwgTlVMTCkpCiAgICB7CiAgICAgICAgaWYgKHRpZCA9PSBkYmdfY3Vycl90aWQpCiAgICAgICAgewogICAgICAgICAgICBmcmFtZXMgPSBkYmdfaGVhcF9yZWFsbG9jKGZyYW1lcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG5mICsgMSkgKiBzaXplb2YoSU1BR0VITFBfU1RBQ0tfRlJBTUUpKTsKCiAgICAgICAgICAgIGZyYW1lc1tuZl0uSW5zdHJ1Y3Rpb25PZmZzZXQgPSAodW5zaWduZWQgbG9uZyltZW1vcnlfdG9fbGluZWFyX2FkZHIoJnNmLkFkZHJQQyk7CiAgICAgICAgICAgIGZyYW1lc1tuZl0uRnJhbWVPZmZzZXQgPSAodW5zaWduZWQgbG9uZyltZW1vcnlfdG9fbGluZWFyX2FkZHIoJnNmLkFkZHJGcmFtZSk7CiAgICAgICAgfQogICAgICAgIGlmIChub2lzeSkKICAgICAgICB7CiAgICAgICAgICAgIGRiZ19wcmludGYoIiVzJWQgIiwgCiAgICAgICAgICAgICAgICAgICAgICAgKHRpZCA9PSBkYmdfY3Vycl90aWQgJiYgbmYgPT0gZGJnX2N1cnJfZnJhbWUgPyAiPT4iIDogIiAgIiksCiAgICAgICAgICAgICAgICAgICAgICAgbmYgKyAxKTsKICAgICAgICAgICAgcHJpbnRfYWRkcl9hbmRfYXJncygmc2YuQWRkclBDLCAmc2YuQWRkckZyYW1lKTsKICAgICAgICAgICAgZGJnX3ByaW50ZigiICgiKTsKICAgICAgICAgICAgcHJpbnRfYmFyZV9hZGRyZXNzKCZzZi5BZGRyRnJhbWUpOwogICAgICAgICAgICBkYmdfcHJpbnRmKCIpXG4iKTsKICAgICAgICB9CiAgICAgICAgbmYrKzsKICAgIH0KCiAgICBkYmdfY29udGV4dCA9IHNhdmVkX2RiZ19jb250ZXh0OwogICAgaWYgKHRpZCA9PSBkYmdfY3Vycl90aWQpCiAgICB7CiAgICAgICAgbmZyYW1lID0gbmY7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgUmVzdW1lVGhyZWFkKHRocmVhZC0+aGFuZGxlKTsKICAgIH0KfQo=