LyoKICogRGVidWdnZXIgc3RhY2sgaGFuZGxpbmcKICoKICogQ29weXJpZ2h0IDE5OTUgQWxleGFuZHJlIEp1bGxpYXJkCiAqIENvcHlyaWdodCAxOTk2IEVyaWMgWW91bmdkYWxlCiAqIENvcHlyaWdodCAxOTk5IE92ZSBL5XZlbgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKICovCgojaW5jbHVkZSAiY29uZmlnLmgiCgojaW5jbHVkZSA8c3RkbGliLmg+CgojaW5jbHVkZSAiZGVidWdnZXIuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmUvd2luYmFzZTE2LmgiCiNpbmNsdWRlICJ3aW5lL2RlYnVnLmgiCiNpbmNsdWRlICJ0bGhlbHAzMi5oIgoKV0lORV9ERUZBVUxUX0RFQlVHX0NIQU5ORUwod2luZWRiZyk7CgpzdGF0aWMgaW50ICAgICAgICAgICAgICAgICAgICAgIG5mcmFtZTsKc3RhdGljIElNQUdFSExQX1NUQUNLX0ZSQU1FKiAgICBmcmFtZXMgPSBOVUxMOwoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqICAgICAgICAgICBzdGFja19pbmZvCiAqCiAqIER1bXAgdGhlIHRvcCBvZiB0aGUgc3RhY2sKICovCnZvaWQgc3RhY2tfaW5mbyh2b2lkKQp7CiAgICBzdHJ1Y3QgZGJnX2x2YWx1ZSBsdmFsdWU7CgogICAgbHZhbHVlLmNvb2tpZSA9IDA7CiAgICBsdmFsdWUudHlwZS5pZCA9IGRiZ19pdHlwZV9ub25lOwogICAgbHZhbHVlLnR5cGUubW9kdWxlID0gMDsKCiAgICAvKiBGSVhNRTogd2UgYXNzdW1lIHN0YWNrIGdyb3dzIHRoZSBzYW1lIHdheSBhcyBvbiBpMzg2ICovCiAgICBpZiAoIW1lbW9yeV9nZXRfY3VycmVudF9zdGFjaygmbHZhbHVlLmFkZHIpKQogICAgICAgIGRiZ19wcmludGYoIkJhZCBzZWdtZW50ICglZClcbiIsIGx2YWx1ZS5hZGRyLlNlZ21lbnQpOwoKICAgIGRiZ19wcmludGYoIlN0YWNrIGR1bXA6XG4iKTsKICAgIHN3aXRjaCAobHZhbHVlLmFkZHIuTW9kZSkKICAgIHsKICAgIGNhc2UgQWRkck1vZGVGbGF0OiAvKiAzMi1iaXQgbW9kZSAqLwogICAgY2FzZSBBZGRyTW9kZTE2MzI6IC8qIDMyLWJpdCBtb2RlICovCiAgICAgICAgbWVtb3J5X2V4YW1pbmUoJmx2YWx1ZSwgMjQsICd4Jyk7CiAgICAgICAgYnJlYWs7CiAgICBjYXNlIEFkZHJNb2RlUmVhbDogIC8qIDE2LWJpdCBtb2RlICovCiAgICBjYXNlIEFkZHJNb2RlMTYxNjoKICAgICAgICBtZW1vcnlfZXhhbWluZSgmbHZhbHVlLCAyNCwgJ3cnKTsKCWJyZWFrOwogICAgfQp9CgppbnQgc3RhY2tfc2V0X2ZyYW1lKGludCBuZXdmcmFtZSkKewogICAgQUREUkVTUyAgICAgYWRkcjsKCiAgICBkYmdfY3Vycl9mcmFtZSA9IG5ld2ZyYW1lOwogICAgaWYgKGRiZ19jdXJyX2ZyYW1lID49IG5mcmFtZSkgZGJnX2N1cnJfZnJhbWUgPSBuZnJhbWUgLSAxOwogICAgaWYgKGRiZ19jdXJyX2ZyYW1lIDwgMCkgICAgICAgZGJnX2N1cnJfZnJhbWUgPSAwOwoKICAgIGFkZHIuTW9kZSA9IEFkZHJNb2RlRmxhdDsKICAgIGFkZHIuT2Zmc2V0ID0gZnJhbWVzW2RiZ19jdXJyX2ZyYW1lXS5JbnN0cnVjdGlvbk9mZnNldDsKICAgIHNvdXJjZV9saXN0X2Zyb21fYWRkcigmYWRkciwgMCk7CiAgICByZXR1cm4gVFJVRTsKfQoKQk9PTCBzdGFja19nZXRfZnJhbWUoU1lNQk9MX0lORk8qIHN5bWJvbCwgSU1BR0VITFBfU1RBQ0tfRlJBTUUqIGloc2YpCnsKICAgIERXT1JENjQgICAgIGRpc3A7CiAgICAvKgogICAgICogSWYgd2UgZG9uJ3QgaGF2ZSBhIHZhbGlkIGJhY2t0cmFjZSwgdGhlbiBqdXN0IHJldHVybi4KICAgICAqLwogICAgaWYgKGZyYW1lcyA9PSBOVUxMKSByZXR1cm4gRkFMU0U7CgogICAgLyoKICAgICAqIElmIHdlIGRvbid0IGtub3cgd2hhdCB0aGUgY3VycmVudCBmdW5jdGlvbiBpcywgdGhlbiB3ZSBhbHNvIGhhdmUKICAgICAqIG5vdGhpbmcgdG8gcmVwb3J0IGhlcmUuCiAgICAgKi8KICAgIGlmICghU3ltRnJvbUFkZHIoZGJnX2N1cnJfcHJvY2Vzcy0+aGFuZGxlLCBmcmFtZXNbZGJnX2N1cnJfZnJhbWVdLkluc3RydWN0aW9uT2Zmc2V0LAogICAgICAgICAgICAgICAgICAgICAmZGlzcCwgc3ltYm9sKSkKICAgICAgICByZXR1cm4gRkFMU0U7CiAgICBpZiAoaWhzZikgKmloc2YgPSBmcmFtZXNbZGJnX2N1cnJfZnJhbWVdOwoKICAgIHJldHVybiBUUlVFOwp9Cgp2b2lkIHN0YWNrX2JhY2t0cmFjZShEV09SRCB0aWQsIEJPT0wgbm9pc3kpCnsKICAgIFNUQUNLRlJBTUUgICAgICAgICAgICAgICAgICBzZjsKICAgIENPTlRFWFQgICAgICAgICAgICAgICAgICAgICBzYXZlZF9kYmdfY29udGV4dDsKICAgIHN0cnVjdCBkYmdfdGhyZWFkKiAgICAgICAgICB0aHJlYWQ7CiAgICB1bnNpZ25lZCAgICAgICAgICAgICAgICAgICAgbmY7CgogICAgaWYgKHRpZCA9PSAtMSkgIC8qIGJhY2t0cmFjZSBldmVyeSB0aHJlYWQgaW4gZXZlcnkgcHJvY2VzcyBleGNlcHQgdGhlIGRlYnVnZ2VyIGl0c2VsZiwgaW52b2tpbmcgdmlhICJidCBhbGwiICovCiAgICB7CiAgICAgICAgVEhSRUFERU5UUlkzMiBlbnRyeTsKICAgICAgICBIQU5ETEUgc25hcHNob3QgPSBDcmVhdGVUb29saGVscDMyU25hcHNob3QoVEgzMkNTX1NOQVBUSFJFQUQsIDApOwogICAgICAgIAogICAgICAgIGlmIChzbmFwc2hvdCA9PSBJTlZBTElEX0hBTkRMRV9WQUxVRSkKICAgICAgICB7CiAgICAgICAgICAgIGRiZ19wcmludGYoInVuYWJsZSB0byBjcmVhdGUgdG9vbGhlbHAgc25hcHNob3RcbiIpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIAogICAgICAgIGVudHJ5LmR3U2l6ZSA9IHNpemVvZihlbnRyeSk7CiAgICAgICAgCiAgICAgICAgaWYgKCFUaHJlYWQzMkZpcnN0KHNuYXBzaG90LCAmZW50cnkpKQogICAgICAgIHsKICAgICAgICAgICAgQ2xvc2VIYW5kbGUoc25hcHNob3QpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIAogICAgICAgIGRvCiAgICAgICAgewogICAgICAgICAgICBpZiAoZW50cnkudGgzMk93bmVyUHJvY2Vzc0lEID09IEdldEN1cnJlbnRQcm9jZXNzSWQoKSkgY29udGludWU7CiAgICAgICAgICAgIGlmIChkYmdfY3Vycl9wcm9jZXNzKSBkYmdfZGV0YWNoX2RlYnVnZ2VlKCk7CgogICAgICAgICAgICBkYmdfcHJpbnRmKCJcbiIpOwogICAgICAgICAgICBpZiAoIWRiZ19hdHRhY2hfZGVidWdnZWUoZW50cnkudGgzMk93bmVyUHJvY2Vzc0lELCBGQUxTRSwgVFJVRSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGRiZ19wcmludGYoIlxud2FybmluZzogY291bGQgbm90IGF0dGFjaCB0byAweCVseFxuIiwgZW50cnkudGgzMk93bmVyUHJvY2Vzc0lEKTsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBkYmdfcHJpbnRmKCJCYWNrdHJhY2luZyBmb3IgdGhyZWFkIDB4JWx4IGluIHByb2Nlc3MgMHglbHggKCVzKTpcbiIsIGVudHJ5LnRoMzJUaHJlYWRJRCwgZGJnX2N1cnJfcGlkLCBkYmdfY3Vycl9wcm9jZXNzLT5pbWFnZU5hbWUpOwogICAgICAgICAgICAKICAgICAgICAgICAgc3RhY2tfYmFja3RyYWNlKGVudHJ5LnRoMzJUaHJlYWRJRCwgVFJVRSk7CiAgICAgICAgfQogICAgICAgIHdoaWxlIChUaHJlYWQzMk5leHQoc25hcHNob3QsICZlbnRyeSkpOwoKICAgICAgICBpZiAoZGJnX2N1cnJfcHJvY2VzcykgZGJnX2RldGFjaF9kZWJ1Z2dlZSgpOwogICAgICAgIENsb3NlSGFuZGxlKHNuYXBzaG90KTsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKCFkYmdfY3Vycl9wcm9jZXNzKSAKICAgIHsKICAgICAgICBkYmdfcHJpbnRmKCJZb3UgbXVzdCBiZSBhdHRhY2hlZCB0byBhIHByb2Nlc3MgdG8gcnVuIHRoaXMgY29tbWFuZC5cbiIpOwogICAgICAgIHJldHVybjsKICAgIH0KICAgIAogICAgc2F2ZWRfZGJnX2NvbnRleHQgPSBkYmdfY29udGV4dDsgLyogYXMgd2UgbWF5IG1vZGlmeSBkYmdfY29udGV4dC4uLiAqLwogICAgaWYgKHRpZCA9PSBkYmdfY3Vycl90aWQpCiAgICB7CiAgICAgICAgdGhyZWFkID0gZGJnX2N1cnJfdGhyZWFkOwogICAgICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIGZyYW1lcyk7CiAgICAgICAgZnJhbWVzID0gTlVMTDsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICAgdGhyZWFkID0gZGJnX2dldF90aHJlYWQoZGJnX2N1cnJfcHJvY2VzcywgdGlkKTsKICAgICAgICAgaWYgKCF0aHJlYWQpCiAgICAgICAgIHsKICAgICAgICAgICAgICBkYmdfcHJpbnRmKCJVbmtub3duIHRocmVhZCBpZCAoMHglMDhseCkgaW4gY3VycmVudCBwcm9jZXNzXG4iLCB0aWQpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgfQogICAgICAgICBtZW1zZXQoJmRiZ19jb250ZXh0LCAwLCBzaXplb2YoZGJnX2NvbnRleHQpKTsKICAgICAgICAgZGJnX2NvbnRleHQuQ29udGV4dEZsYWdzID0gQ09OVEVYVF9GVUxMOwogICAgICAgICBpZiAoU3VzcGVuZFRocmVhZCh0aHJlYWQtPmhhbmRsZSkgIT0gLTEpCiAgICAgICAgIHsKICAgICAgICAgICAgIGlmICghR2V0VGhyZWFkQ29udGV4dCh0aHJlYWQtPmhhbmRsZSwgJmRiZ19jb250ZXh0KSkKICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICBkYmdfcHJpbnRmKCJDYW4ndCBnZXQgY29udGV4dCBmb3IgdGhyZWFkIDB4JWx4IGluIGN1cnJlbnQgcHJvY2Vzc1xuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpZCk7CiAgICAgICAgICAgICAgICAgUmVzdW1lVGhyZWFkKHRocmVhZC0+aGFuZGxlKTsKICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICB9CiAgICAgICAgIH0KICAgICAgICAgZWxzZQogICAgICAgICB7CiAgICAgICAgICAgICBkYmdfcHJpbnRmKCJDYW4ndCBzdXNwZW5kIHRocmVhZCAweCVseCBpbiBjdXJyZW50IHByb2Nlc3NcbiIsIHRpZCk7CiAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgIH0KICAgIH0KCiAgICBuZiA9IDA7CiAgICBtZW1zZXQoJnNmLCAwLCBzaXplb2Yoc2YpKTsKICAgIG1lbW9yeV9nZXRfY3VycmVudF9mcmFtZSgmc2YuQWRkckZyYW1lKTsKICAgIG1lbW9yeV9nZXRfY3VycmVudF9wYygmc2YuQWRkclBDKTsKCiAgICAvKiBkb24ndCBjb25mdXNlIFN0YWNrV2FsayBieSBwYXNzaW5nIGluIGluY29uc2lzdGVudCBhZGRyZXNzZXMgKi8KICAgIGlmICgoc2YuQWRkclBDLk1vZGUgPT0gQWRkck1vZGVGbGF0KSAmJiAoc2YuQWRkckZyYW1lLk1vZGUgIT0gQWRkck1vZGVGbGF0KSkKICAgIHsKICAgICAgICBzZi5BZGRyRnJhbWUuT2Zmc2V0ID0gKERXT1JEKW1lbW9yeV90b19saW5lYXJfYWRkcigmc2YuQWRkckZyYW1lKTsKICAgICAgICBzZi5BZGRyRnJhbWUuTW9kZSA9IEFkZHJNb2RlRmxhdDsKICAgIH0KCiAgICBpZiAobm9pc3kpIGRiZ19wcmludGYoIkJhY2t0cmFjZTpcbiIpOwogICAgd2hpbGUgKFN0YWNrV2FsayhJTUFHRV9GSUxFX01BQ0hJTkVfSTM4NiwgZGJnX2N1cnJfcHJvY2Vzcy0+aGFuZGxlLCAKICAgICAgICAgICAgICAgICAgICAgdGhyZWFkLT5oYW5kbGUsICZzZiwgJmRiZ19jb250ZXh0LCBOVUxMLCBTeW1GdW5jdGlvblRhYmxlQWNjZXNzLAogICAgICAgICAgICAgICAgICAgICBTeW1HZXRNb2R1bGVCYXNlLCBOVUxMKSkKICAgIHsKICAgICAgICBpZiAodGlkID09IGRiZ19jdXJyX3RpZCkKICAgICAgICB7CiAgICAgICAgICAgIGZyYW1lcyA9IGRiZ19oZWFwX3JlYWxsb2MoZnJhbWVzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobmYgKyAxKSAqIHNpemVvZihJTUFHRUhMUF9TVEFDS19GUkFNRSkpOwoKICAgICAgICAgICAgZnJhbWVzW25mXS5JbnN0cnVjdGlvbk9mZnNldCA9ICh1bnNpZ25lZCBsb25nKW1lbW9yeV90b19saW5lYXJfYWRkcigmc2YuQWRkclBDKTsKICAgICAgICAgICAgZnJhbWVzW25mXS5GcmFtZU9mZnNldCA9ICh1bnNpZ25lZCBsb25nKW1lbW9yeV90b19saW5lYXJfYWRkcigmc2YuQWRkckZyYW1lKTsKICAgICAgICB9CiAgICAgICAgaWYgKG5vaXN5KQogICAgICAgIHsKICAgICAgICAgICAgZGJnX3ByaW50ZigiJXMlZCAiLCAKICAgICAgICAgICAgICAgICAgICAgICAodGlkID09IGRiZ19jdXJyX3RpZCAmJiBuZiA9PSBkYmdfY3Vycl9mcmFtZSA/ICI9PiIgOiAiICAiKSwKICAgICAgICAgICAgICAgICAgICAgICBuZiArIDEpOwogICAgICAgICAgICBwcmludF9hZGRyX2FuZF9hcmdzKCZzZi5BZGRyUEMsICZzZi5BZGRyRnJhbWUpOwogICAgICAgICAgICBkYmdfcHJpbnRmKCIgKCIpOwogICAgICAgICAgICBwcmludF9iYXJlX2FkZHJlc3MoJnNmLkFkZHJGcmFtZSk7CiAgICAgICAgICAgIGRiZ19wcmludGYoIilcbiIpOwogICAgICAgIH0KICAgICAgICBuZisrOwogICAgICAgIC8qIHdlJ3ZlIHByb2JhYmx5IGdvdHRlbiBvdXJzZWx2ZXMgaW50byBhbiBpbmZpbml0ZSBsb29wIHNvIGJhaWwgKi8KICAgICAgICBpZiAobmYgPiAyMDApCiAgICAgICAgICAgIGJyZWFrOwogICAgfQoKICAgIGRiZ19jb250ZXh0ID0gc2F2ZWRfZGJnX2NvbnRleHQ7CiAgICBpZiAodGlkID09IGRiZ19jdXJyX3RpZCkKICAgIHsKICAgICAgICBuZnJhbWUgPSBuZjsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBSZXN1bWVUaHJlYWQodGhyZWFkLT5oYW5kbGUpOwogICAgfQp9Cg==