LyoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqIENvcHlyaWdodCAoQykgMTk5Ni0xOTk5LCBJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uIGFuZCAgICAqCiogb3RoZXJzLiBBbGwgUmlnaHRzIFJlc2VydmVkLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqLwovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ci8vCi8vIEZpbGUgY29sZWl0ci5jcHAKLy8KLy8gCi8vCi8vIENyZWF0ZWQgYnk6IEhlbGVuYSBTaGloCi8vCi8vIE1vZGlmaWNhdGlvbiBIaXN0b3J5OgovLwovLyAgRGF0ZSAgICAgICAgIE5hbWUgICAgICAgICAgRGVzY3JpcHRpb24KLy8KLy8gIDYvMjMvOTcgICAgIGhlbGVuYSAgICAgIEFkZGluZyBjb21tZW50cyB0byBtYWtlIGNvZGUgbW9yZSByZWFkYWJsZS4KLy8gMDgvMDMvOTggICAgIGVybSAgICAgICAgIFN5bmNoZWQgd2l0aCAxLjIgdmVyc2lvbiBvZiBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IuamF2YQovLyAxMi8xMC85OSAgICAgIGFsaXUgICAgICAgICAgUG9ydGVkIFRoYWkgY29sbGF0aW9uIHN1cHBvcnQgZnJvbSBKYXZhLgovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojaW5jbHVkZSAidW5pY29kZS9zb3J0a2V5LmgiCiNpbmNsdWRlICJ1bmljb2RlL2NvbGVpdHIuaCIKCiNpbmNsdWRlICJ1bmljb2RlL2NoYXJpdGVyLmgiCiNpbmNsdWRlICJ0YWJsZXMuaCIKI2luY2x1ZGUgInVuaWNvZGUvbm9ybWx6ci5oIgojaW5jbHVkZSAidW5pY29kZS91bmljb2RlLmgiCiNpbmNsdWRlICJ0Y29sZGF0YS5oIgojaW5jbHVkZSAidWNtcDMyLmgiCgoKaW50MzJfdCBjb25zdCBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUiA9IDB4ZmZmZmZmZmY7CmludDMyX3QgY29uc3QgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpVTk1BUFBFRENIQVJWQUxVRSA9IDB4N2ZmZjAwMDA7CgoKLy8gVGhpcyBwcml2YXRlIG1ldGhvZCB3aWxsIG5ldmVyIGJlIGNhbGxlZCwgYnV0IGl0IG1ha2VzIHRoZSBsaW5rZXIgaGFwcHkKCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6Q29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yKCkKOiBleHBJbmRleCgwKSwKICB0ZXh0KDApLAogIGJ1ZmZlckFsaWFzKDApLAogIG93bkJ1ZmZlcihuZXcgVmVjdG9yT2ZJbnQoMikpLAogIHJlb3JkZXJCdWZmZXIoMCksCiAgb3JkZXJBbGlhcygwKQp7Cn0KCi8vIFRoaXMgcHJpdmF0ZSBtZXRob2Qgd2lsbCBuZXZlciBiZSBjYWxsZWQsIGJ1dCBpdCBtYWtlcyB0aGUgbGlua2VyIGhhcHB5CgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcihjb25zdCBSdWxlQmFzZWRDb2xsYXRvciogb3JkZXIpCjogZXhwSW5kZXgoMCksCiAgdGV4dCgwKSwKICBidWZmZXJBbGlhcygwKSwKICBvd25CdWZmZXIobmV3IFZlY3Rvck9mSW50KDIpKSwKICByZW9yZGVyQnVmZmVyKDApLAogIG9yZGVyQWxpYXMob3JkZXIpCnsKfQoKLy8gVGhpcyBpcyB0aGUgInJlYWwiIGNvbnN0cnVjdG9yIGZvciB0aGlzIGNsYXNzOyBpdCBjb25zdHJ1Y3RzIGFuIGl0ZXJhdG9yCi8vIG92ZXIgdGhlIHNvdXJjZSB0ZXh0IHVzaW5nIHRoZSBzcGVjaWZpZWQgY29sbGF0b3IKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IoIGNvbnN0IFVuaWNvZGVTdHJpbmcmIHNvdXJjZVRleHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBSdWxlQmFzZWRDb2xsYXRvciogb3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpIAo6IGV4cEluZGV4KDApLCAKICB0ZXh0KE5VTEwpLAogIGJ1ZmZlckFsaWFzKE5VTEwpLAogIG93bkJ1ZmZlcihuZXcgVmVjdG9yT2ZJbnQoMikpLAogIHJlb3JkZXJCdWZmZXIoMCksCiAgb3JkZXJBbGlhcyhvcmRlcikKewogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKSB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmICggc291cmNlVGV4dC5sZW5ndGgoKSAhPSAwICkgewogICAgICAgIC8vCiAgICAgICAgLy8gQSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IgaXMgcmVhbGx5IGEgdHdvLWxheWVyZWQgYmVhc3QuCiAgICAgICAgLy8gSW50ZXJuYWxseSBpdCB1c2VzIGEgTm9ybWFsaXplciB0byBtdW5nZSB0aGUgc291cmNlIHRleHQKICAgICAgICAvLyBpbnRvIGEgZm9ybSB3aGVyZSBhbGwgImNvbXBvc2VkIiBVbmljb2RlIGNoYXJhY3RlcnMgKHN1Y2ggYXMg/CkgYXJlCiAgICAgICAgLy8gc3BsaXQgaW50byBhIG5vcm1hbCBjaGFyYWN0ZXIgYW5kIGEgY29tYmluaW5nIGFjY2VudCBjaGFyYWN0ZXIuICAKICAgICAgICAvLyBBZnRlcndhcmQsIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciBkb2VzIGl0cyBvd24gcHJvY2Vzc2luZyB0byBoYW5kbGUKICAgICAgICAvLyBleHBhbmRpbmcgYW5kIGNvbnRyYWN0aW5nIGNvbGxhdGlvbiBzZXF1ZW5jZXMsIGlnbm9yYWJsZXMsIGFuZCBzbyBvbi4KICAgICAgICAvLwogICAgICBOb3JtYWxpemVyOjpFTW9kZSBkZWNvbXAgPSAob3JkZXItPmdldFN0cmVuZ3RoKCkgPT0gQ29sbGF0b3I6OklERU5USUNBTCkKICAgID8gTm9ybWFsaXplcjo6Tk9fT1AKICAgIDogb3JkZXItPmdldERlY29tcG9zaXRpb24oKTsKICAgICAgCiAgICAgIHRleHQgPSBuZXcgTm9ybWFsaXplcihzb3VyY2VUZXh0LCBkZWNvbXApOwogICAgICBpZiAodGV4dCA9PSBOVUxMKSB7CiAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICB9CiAgICB9Cn0KCgovLyBUaGlzIGlzIHRoZSAicmVhbCIgY29uc3RydWN0b3IgZm9yIHRoaXMgY2xhc3M7IGl0IGNvbnN0cnVjdHMgYW4gaXRlcmF0b3IKLy8gb3ZlciB0aGUgc291cmNlIHRleHQgdXNpbmcgdGhlIHNwZWNpZmllZCBjb2xsYXRvcgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciggY29uc3QgQ2hhcmFjdGVySXRlcmF0b3ImIHNvdXJjZVRleHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBSdWxlQmFzZWRDb2xsYXRvciogb3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpIAo6IGV4cEluZGV4KDApLCAKICB0ZXh0KE5VTEwpLAogIGJ1ZmZlckFsaWFzKE5VTEwpLAogIG93bkJ1ZmZlcihuZXcgVmVjdG9yT2ZJbnQoMikpLAogIHJlb3JkZXJCdWZmZXIoMCksCiAgb3JkZXJBbGlhcyhvcmRlcikKewogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKSB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIC8vICoqKiogc2hvdWxkIEkganVzdCBkcm9wIHRoaXMgdGVzdD8gKioqKgogICAgaWYgKCBzb3VyY2VUZXh0LmVuZEluZGV4KCkgIT0gMCApCiAgICB7CiAgICAgICAgLy8KICAgICAgICAvLyBBIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciBpcyByZWFsbHkgYSB0d28tbGF5ZXJlZCBiZWFzdC4KICAgICAgICAvLyBJbnRlcm5hbGx5IGl0IHVzZXMgYSBOb3JtYWxpemVyIHRvIG11bmdlIHRoZSBzb3VyY2UgdGV4dAogICAgICAgIC8vIGludG8gYSBmb3JtIHdoZXJlIGFsbCAiY29tcG9zZWQiIFVuaWNvZGUgY2hhcmFjdGVycyAoc3VjaCBhcyD8KSBhcmUKICAgICAgICAvLyBzcGxpdCBpbnRvIGEgbm9ybWFsIGNoYXJhY3RlciBhbmQgYSBjb21iaW5pbmcgYWNjZW50IGNoYXJhY3Rlci4gIAogICAgICAgIC8vIEFmdGVyd2FyZCwgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yIGRvZXMgaXRzIG93biBwcm9jZXNzaW5nIHRvIGhhbmRsZQogICAgICAgIC8vIGV4cGFuZGluZyBhbmQgY29udHJhY3RpbmcgY29sbGF0aW9uIHNlcXVlbmNlcywgaWdub3JhYmxlcywgYW5kIHNvIG9uLgogICAgICAgIC8vCiAgICAgIE5vcm1hbGl6ZXI6OkVNb2RlIGRlY29tcCA9IG9yZGVyLT5nZXRTdHJlbmd0aCgpID09IENvbGxhdG9yOjpJREVOVElDQUwKICAgICAgICA/IE5vcm1hbGl6ZXI6Ok5PX09QCiAgICAgICAgOiBvcmRlci0+Z2V0RGVjb21wb3NpdGlvbigpOwogICAgICAKICAgICAgdGV4dCA9IG5ldyBOb3JtYWxpemVyKHNvdXJjZVRleHQsIGRlY29tcCk7CiAgICAgIGlmICh0ZXh0ID09IE5VTEwpIHsKICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICB9CiAgICB9Cn0KCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6Q29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yKGNvbnN0ICAgIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciYgb3RoZXIpCiAgICA6IGV4cEluZGV4KG90aGVyLmV4cEluZGV4KSwgdGV4dCgwKSwKICAgICAgb3duQnVmZmVyKG5ldyBWZWN0b3JPZkludCgyKSksCiAgICAgIHJlb3JkZXJCdWZmZXIoMCkKewogICAgKnRoaXMgPSBvdGhlcjsKfQoKY29uc3QgICBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3ImCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6b3BlcmF0b3I9KGNvbnN0ICAgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yJiBvdGhlcikKewogICAgaWYgKHRoaXMgIT0gJm90aGVyKQogICAgewogICAgICAgIGV4cEluZGV4ID0gb3RoZXIuZXhwSW5kZXg7CgogICAgICAgIGRlbGV0ZSB0ZXh0OwogICAgICAgIHRleHQgPSAoTm9ybWFsaXplciopb3RoZXIudGV4dC0+Y2xvbmUoKTsKCiAgICAgICAgaWYgKG90aGVyLmJ1ZmZlckFsaWFzID09IG90aGVyLm93bkJ1ZmZlcikgewogICAgICAgICAgICAqb3duQnVmZmVyID0gKm90aGVyLm93bkJ1ZmZlcjsKICAgICAgICAgICAgYnVmZmVyQWxpYXMgPSBvd25CdWZmZXI7CiAgICAgICAgfSBlbHNlIGlmIChvdGhlci5idWZmZXJBbGlhcyAhPSBOVUxMICYmCiAgICAgICAgICAgICAgICAgICBvdGhlci5idWZmZXJBbGlhcyA9PSBvdGhlci5yZW9yZGVyQnVmZmVyKSB7CiAgICAgICAgICAgIGlmIChyZW9yZGVyQnVmZmVyID09IE5VTEwpIHsKICAgICAgICAgICAgICAgIHJlb3JkZXJCdWZmZXIgPSBuZXcgVmVjdG9yT2ZJbnQoKm90aGVyLnJlb3JkZXJCdWZmZXIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgKnJlb3JkZXJCdWZmZXIgPSAqb3RoZXIucmVvcmRlckJ1ZmZlcjsKICAgICAgICAgICAgfQogICAgICAgICAgICBidWZmZXJBbGlhcyA9IHJlb3JkZXJCdWZmZXI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYnVmZmVyQWxpYXMgPSBvdGhlci5idWZmZXJBbGlhczsKICAgICAgICB9CiAgICAgICAgb3JkZXJBbGlhcyA9IG90aGVyLm9yZGVyQWxpYXM7CiAgICB9CgogICAgcmV0dXJuICp0aGlzOwp9CgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6On5Db2xsYXRpb25FbGVtZW50SXRlcmF0b3IoKQp7CiAgICBkZWxldGUgdGV4dDsKICAgIHRleHQgPSBOVUxMOwogICAgYnVmZmVyQWxpYXMgPSBOVUxMOwogICAgb3JkZXJBbGlhcyA9IE5VTEw7CiAgICBkZWxldGUgb3duQnVmZmVyOwogICAgZGVsZXRlIHJlb3JkZXJCdWZmZXI7Cn0KCmJvb2xfdApDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Om9wZXJhdG9yPT0oY29uc3QgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yJiB0aGF0KSBjb25zdAp7CiAgICBpZiAodGhpcyA9PSAmdGhhdCkKICAgIHsKICAgICAgICByZXR1cm4gVFJVRTsKICAgIH0KCiAgICBpZiAoKnRleHQgIT0gKih0aGF0LnRleHQpKQogICAgewogICAgICAgIHJldHVybiBGQUxTRTsKICAgIH0KCiAgICBpZiAoKChidWZmZXJBbGlhcyA9PSBOVUxMKSAhPSAodGhhdC5idWZmZXJBbGlhcyA9PSBOVUxMKSkgfHwKICAgICAgICAoYnVmZmVyQWxpYXMgIT0gTlVMTCAmJiAqYnVmZmVyQWxpYXMgIT0gKih0aGF0LmJ1ZmZlckFsaWFzKSkpCiAgICB7CiAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgfQoKICAgIGlmIChleHBJbmRleCAhPSB0aGF0LmV4cEluZGV4KQogICAgewogICAgICAgIHJldHVybiBGQUxTRTsKICAgIH0KCiAgICBpZiAob3JkZXJBbGlhcyAhPSB0aGF0Lm9yZGVyQWxpYXMpCiAgICB7CiAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgfQoKICAgIHJldHVybiBUUlVFOwp9Cgpib29sX3QKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpvcGVyYXRvciE9KGNvbnN0IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciYgb3RoZXIpIGNvbnN0CnsKICAgIHJldHVybiAhKCp0aGlzID09IG90aGVyKTsKfQoKLyoqCiAqIFJlc2V0cyB0aGUgY3Vyc29yIHRvIHRoZSBiZWdpbm5pbmcgb2YgdGhlIHN0cmluZy4KICovCnZvaWQgCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6cmVzZXQoKQp7CiAgaWYgKHRleHQgIT0gTlVMTCkKICAgIHsKICAgICAgdGV4dC0+cmVzZXQoKTsKICAgICAgdGV4dC0+c2V0TW9kZShvcmRlckFsaWFzLT5nZXREZWNvbXBvc2l0aW9uKCkpOwogICAgfQoKICBidWZmZXJBbGlhcyA9IE5VTEw7CiAgZXhwSW5kZXggPSAwOwp9CgovLyBTZXRzIHRoZSBzb3VyY2UgdG8gdGhlIG5ldyBzb3VyY2Ugc3RyaW5nLgp2b2lkCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6c2V0VGV4dChjb25zdCBVbmljb2RlU3RyaW5nJiAgc291cmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgICAgICBzdGF0dXMpCnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgYnVmZmVyQWxpYXMgPSAwOwoKICAgIGlmICh0ZXh0ID09IE5VTEwpCiAgICB7CiAgICAgICAgdGV4dCA9IG5ldyBOb3JtYWxpemVyKHNvdXJjZSwgb3JkZXJBbGlhcy0+Z2V0RGVjb21wb3NpdGlvbigpKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICB0ZXh0LT5zZXRUZXh0KHNvdXJjZSwgc3RhdHVzKTsKICAgICAgICB0ZXh0LT5zZXRNb2RlKG9yZGVyQWxpYXMtPmdldERlY29tcG9zaXRpb24oKSk7CiAgICB9Cn0KCi8vIFNldHMgdGhlIHNvdXJjZSB0byB0aGUgbmV3IGNoYXJhY3RlciBpdGVyYXRvci4Kdm9pZApDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnNldFRleHQoQ2hhcmFjdGVySXRlcmF0b3ImICBzb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiAgICAgIHN0YXR1cykKewogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKSB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGJ1ZmZlckFsaWFzID0gMDsKCiAgICBpZiAodGV4dCA9PSBOVUxMKSB7CiAgICAgICAgdGV4dCA9IG5ldyBOb3JtYWxpemVyKHNvdXJjZSwgb3JkZXJBbGlhcy0+Z2V0RGVjb21wb3NpdGlvbigpKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICB0ZXh0LT5zZXRNb2RlKG9yZGVyQWxpYXMtPmdldERlY29tcG9zaXRpb24oKSk7CiAgICAgICAgdGV4dC0+c2V0VGV4dChzb3VyY2UsIHN0YXR1cyk7CiAgICB9Cn0KCi8qKgogKiBHZXQgdGhlIG9yZGVyaW5nIHByaW9yaXR5IG9mIHRoZSBuZXh0IGNoYXJhY3RlciBpbiB0aGUgc3RyaW5nLgogKiBAcmV0dXJuIHRoZSBuZXh0IGNoYXJhY3RlcidzIG9yZGVyaW5nLiAgUmV0dXJucyBOVUxMT1JERVIgaWYKICogdGhlIGVuZCBvZiBzdHJpbmcgaXMgcmVhY2hlZC4KICovCmludDMyX3QKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpuZXh0KFVFcnJvckNvZGUmIHN0YXR1cykKewogICAgaWYgKHRleHQgPT0gTlVMTCB8fCBVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm4gTlVMTE9SREVSOwogICAgfQoKICAgIC8vIFVwZGF0ZSB0aGUgZGVjb21wb3NpdGlvbiBtb2RlIGlmIG5lY2Vzc2FyeS4KICAgIHRleHQtPnNldE1vZGUob3JkZXJBbGlhcy0+Z2V0RGVjb21wb3NpdGlvbigpKTsKICAgIAogICAgaWYgKGJ1ZmZlckFsaWFzICE9IE5VTEwpCiAgICB7CiAgICAgICAgLy8gYnVmZmVyQWxpYXMgbmVlZHMgYSBiaXQgb2YgYW4gZXhwbGFuYXRpb24uCiAgICAgICAgLy8gV2hlbiB3ZSBoaXQgYW4gZXhwYW5kaW5nIGNoYXJhY3RlciBpbiB0aGUgdGV4dCwgd2UgY2FsbCB0aGUgb3JkZXIncwogICAgICAgIC8vIGdldEV4cGFuZFZhbHVlcyBtZXRob2QgdG8gcmV0cmlldmUgYW4gYXJyYXkgb2YgdGhlIG9yZGVyaW5ncyBmb3IgYWxsCiAgICAgICAgLy8gb2YgdGhlIGNoYXJhY3RlcnMgaW4gdGhlIGV4cGFuc2lvbiAoc2VlIHRoZSBlbmQgb2YgdGhpcyBtZXRob2QpLgogICAgICAgIC8vIFRoZSBmaXJzdCBvcmRlcmluZyBpcyByZXR1cm5lZCwgYW5kIGFuIGFsaWFzIHRvIHRoZSBvcmRlcmluZ3MgYXJyYXkKICAgICAgICAvLyBpcyBzYXZlZCBzbyB0aGF0IHRoZSByZW1haW5pbmcgb3JkZXJpbmdzIGNhbiBiZSByZXR1cm5lZCBvbiBzdWJzZXF1ZW50CiAgICAgICAgLy8gY2FsbHMgdG8gbmV4dC4gIFNvLCBpZiB0aGUgZXhwYW5kaW5nIGJ1ZmZlciBpcyBub3QgZXhoYXVzdGVkLCAKICAgICAgICAvLyBhbGwgd2UgaGF2ZSB0byBkbyBoZXJlIGlzIHJldHVybiB0aGUgbmV4dCBvcmRlcmluZyBpbiB0aGUgYnVmZmVyLiAgCiAgICAgICAgaWYgKGV4cEluZGV4IDwgYnVmZmVyQWxpYXMtPnNpemUoKSkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBzdHJlbmd0aE9yZGVyKGJ1ZmZlckFsaWFzLT5hdChleHBJbmRleCsrKSk7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIGJ1ZmZlckFsaWFzID0gTlVMTDsKICAgICAgICB9CiAgICB9CgogICAgLy8gR2V0cyB0aGUgbmV4dCBjaGFyYWN0ZXIgZnJvbSB0aGUgc3RyaW5nIHVzaW5nIGRlY29tcG9zaXRpb24gaXRlcmF0b3IuCiAgICBVQ2hhciBjaCA9IHRleHQtPmN1cnJlbnQoKTsKICAgIHRleHQtPm5leHQoKTsKCiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuIE5VTExPUkRFUjsKICAgIH0KCiAgICBpZiAoY2ggPT0gTm9ybWFsaXplcjo6RE9ORSkKICAgIHsKICAgICAgICByZXR1cm4gTlVMTE9SREVSOwogICAgfQogICAgCiAgICAvLyBBc2sgdGhlIGNvbGxhdG9yIGZvciB0aGlzIGNoYXJhY3RlcidzIG9yZGVyaW5nLgogICAgLyogVXNlZCB0byBiZSBSdWxlQmFzZWRDb2xsYXRvci5nZXRVbmljb2RlT3JkZXIoKS4gIEl0IAogICAgICAgY2FuJ3QgYmUgaW5saW5lZCBpbiB0Ymxjb2xsLmggZmlsZSB1bmZvcnR1bmF0ZWx5LiAqLwogICAgaW50MzJfdCB2YWx1ZSA9IHVjbXAzMl9nZXQob3JkZXJBbGlhcy0+ZGF0YS0+bWFwcGluZywgY2gpOwoKICAgIGlmICh2YWx1ZSA9PSBSdWxlQmFzZWRDb2xsYXRvcjo6VU5NQVBQRUQpCiAgICB7CiAgICAgICAgLy8gUmV0dXJuZWQgYW4gInVubWFwcGVkIiBmbGFnIGFuZCBzYXZlIHRoZSBjaGFyYWN0ZXIgc28gaXQgY2FuIGJlIAogICAgICAgIC8vIHJldHVybmVkIG5leHQgdGltZSB0aGlzIG1ldGhvZCBpcyBjYWxsZWQuCiAgICAgICAgaWYgKGNoID09IDB4MDAwMCkgcmV0dXJuIGNoOwogICAgICAgIC8vIFx1MDAwMCBpcyBub3QgdmFsaWQgaW4gQysrJ3MgVW5pY29kZVN0cmluZwogICAgICAgIG93bkJ1ZmZlci0+YXQoMCkgPSBVTk1BUFBFRENIQVJWQUxVRTsKICAgICAgICBvd25CdWZmZXItPmF0KDEpID0gY2ggPDwgMTY7CiAgICAgICAgYnVmZmVyQWxpYXMgPSBvd25CdWZmZXI7CiAgICB9CiAgICBlbHNlIHsKICAgICAgICBpZiAodmFsdWUgPj0gUnVsZUJhc2VkQ29sbGF0b3I6OkNPTlRSQUNUQ0hBUklOREVYKSB7CiAgICAgICAgICAgIHZhbHVlID0gbmV4dENvbnRyYWN0Q2hhcihjaCwgc3RhdHVzKTsKICAgICAgICB9CiAgICAgICAgaWYgKHZhbHVlID49IFJ1bGVCYXNlZENvbGxhdG9yOjpFWFBBTkRDSEFSSU5ERVgpIHsKICAgICAgICAgICAgYnVmZmVyQWxpYXMgPSBvcmRlckFsaWFzLT5nZXRFeHBhbmRWYWx1ZUxpc3QodmFsdWUpOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBpZiAoaXNUaGFpUHJlVm93ZWwoY2gpKSB7CiAgICAgICAgICAgIFVDaGFyIGNvbnNvbmFudCA9IHRleHQtPm5leHQoKTsKICAgICAgICAgICAgaWYgKGlzVGhhaUJhc2VDb25zb25hbnQoY29uc29uYW50KSkgewogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBidWZmZXJBbGlhcyA9IG1ha2VSZW9yZGVyZWRCdWZmZXIoY29uc29uYW50LCB2YWx1ZSwgYnVmZmVyQWxpYXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSwgc3RhdHVzKTsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdGV4dC0+cHJldmlvdXMoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBpZiAoYnVmZmVyQWxpYXMgIT0gTlVMTCkgewogICAgICAgIGV4cEluZGV4ID0gMTsKICAgICAgICB2YWx1ZSA9IGJ1ZmZlckFsaWFzLT5hdCgwKTsKICAgIH0KCiAgICByZXR1cm4gc3RyZW5ndGhPcmRlcih2YWx1ZSk7Cn0KCiAvKioKICAqIEdldCB0aGUgb3JkZXJpbmcgcHJpb3JpdHkgb2YgdGhlIHByZXZpb3VzIGNvbGxhdGlvbiBlbGVtZW50IGluIHRoZSBzdHJpbmcuCiAgKiBAcGFyYW0gc3RhdHVzIHRoZSBlcnJvciBjb2RlIHN0YXR1cy4KICAqIEByZXR1cm4gdGhlIHByZXZpb3VzIGVsZW1lbnQncyBvcmRlcmluZy4gIFJldHVybnMgTlVMTE9SREVSIGlmCiAgKiB0aGUgYmVnaW5uaW5nIG9mIHN0cmluZyBpcyByZWFjaGVkLgogICovCmludDMyX3QKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpwcmV2aW91cyhVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIGlmICh0ZXh0ID09IE5VTEwgfHwgVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuIE5VTExPUkRFUjsKICAgIH0KCiAgICB0ZXh0LT5zZXRNb2RlKG9yZGVyQWxpYXMtPmdldERlY29tcG9zaXRpb24oKSk7CgogICAgaWYgKGJ1ZmZlckFsaWFzICE9IE5VTEwpCiAgICB7CiAgICAgICAgaWYgKGV4cEluZGV4ID4gMCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBzdHJlbmd0aE9yZGVyKGJ1ZmZlckFsaWFzLT5hdCgtLWV4cEluZGV4KSk7CiAgICAgICAgfQoKICAgICAgICBidWZmZXJBbGlhcyA9IE5VTEw7CiAgICB9CgogICAgVUNoYXIgY2ggPSB0ZXh0LT5wcmV2aW91cygpOwoKICAgIGlmIChjaCA9PSBOb3JtYWxpemVyOjpET05FKQogICAgewogICAgICAgIHJldHVybiBOVUxMT1JERVI7CiAgICB9CiAgICAvKiBVc2VkIHRvIGJlIFJ1bGVCYXNlZENvbGxhdG9yLmdldFVuaWNvZGVPcmRlcigpLiAgSXQgCiAgICAgICBjYW4ndCBiZSBpbmxpbmVkIGluIHRibGNvbGwuaCBmaWxlIHVuZm9ydHVuYXRlbHkuICovCiAgICBpbnQzMl90IHZhbHVlID0gdWNtcDMyX2dldChvcmRlckFsaWFzLT5kYXRhLT5tYXBwaW5nLCBjaCk7CgogICAgaWYgKHZhbHVlID09IFJ1bGVCYXNlZENvbGxhdG9yOjpVTk1BUFBFRCkKICAgIHsKICAgICAgICBpZiAoY2ggPT0gMHgwMDAwKSByZXR1cm4gY2g7CiAgICAgICAgb3duQnVmZmVyLT5hdCgwKSA9IFVOTUFQUEVEQ0hBUlZBTFVFOwogICAgICAgIG93bkJ1ZmZlci0+YXQoMSkgPSBjaCA8PCAxNjsKICAgICAgICBidWZmZXJBbGlhcyA9IG93bkJ1ZmZlcjsKICAgIH0KICAgIGVsc2UgewogICAgICAgIGlmICh2YWx1ZSA+PSBSdWxlQmFzZWRDb2xsYXRvcjo6Q09OVFJBQ1RDSEFSSU5ERVgpIHsKICAgICAgICAgICAgdmFsdWUgPSBwcmV2Q29udHJhY3RDaGFyKGNoLCBzdGF0dXMpOwogICAgICAgIH0KICAgICAgICBpZiAodmFsdWUgPj0gUnVsZUJhc2VkQ29sbGF0b3I6OkVYUEFORENIQVJJTkRFWCkgewogICAgICAgICAgICBidWZmZXJBbGlhcyA9IG9yZGVyQWxpYXMtPmdldEV4cGFuZFZhbHVlTGlzdCh2YWx1ZSk7CiAgICAgICAgfQoKICAgICAgICBpZiAoaXNUaGFpQmFzZUNvbnNvbmFudChjaCkpIHsKCiAgICAgICAgICAgIFVDaGFyIHZvd2VsID0gdGV4dC0+cHJldmlvdXMoKTsKICAgICAgICAgICAgaWYgKGlzVGhhaVByZVZvd2VsKHZvd2VsKSkgewogICAgICAgICAgICAgICAgYnVmZmVyQWxpYXMgPSBtYWtlUmVvcmRlcmVkQnVmZmVyKHZvd2VsLCB2YWx1ZSwgYnVmZmVyQWxpYXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRkFMU0UsIHN0YXR1cyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB0ZXh0LT5uZXh0KCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgaWYgKGJ1ZmZlckFsaWFzICE9IE5VTEwpIHsKICAgICAgICBleHBJbmRleCA9IGJ1ZmZlckFsaWFzLT5zaXplKCktMTsKICAgICAgICB2YWx1ZSA9IGJ1ZmZlckFsaWFzLT5hdChleHBJbmRleCk7CiAgICB9CgogICAgcmV0dXJuIHN0cmVuZ3RoT3JkZXIodmFsdWUpOwp9CgppbnQzMl90CkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6c3RyZW5ndGhPcmRlcihpbnQzMl90IG9yZGVyKSBjb25zdAp7CiAgICBDb2xsYXRvcjo6RUNvbGxhdGlvblN0cmVuZ3RoIHMgPSBvcmRlckFsaWFzLT5nZXRTdHJlbmd0aCgpOwogICAgLy8gTWFzayBvZmYgdGhlIHVud2FudGVkIGRpZmZlcmVuY2VzLgogICAgaWYgKHMgPT0gQ29sbGF0b3I6OlBSSU1BUlkpCiAgICB7CiAgICAgICAgb3JkZXIgJj0gUnVsZUJhc2VkQ29sbGF0b3I6OlBSSU1BUllESUZGRVJFTkNFT05MWTsKICAgIH0gZWxzZSBpZiAocyA9PSBDb2xsYXRvcjo6U0VDT05EQVJZKQogICAgewogICAgICAgIG9yZGVyICY9IFJ1bGVCYXNlZENvbGxhdG9yOjpTRUNPTkRBUllESUZGRVJFTkNFT05MWTsKICAgIH0KICAgIHJldHVybiBvcmRlcjsKfQoKVVRleHRPZmZzZXQKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpnZXRPZmZzZXQoKSBjb25zdAp7CiAgICAvLyBTaW5jZSB0aGUgRGVjb21wb3NpdGlvbkl0ZXJhdG9yIGlzIGRvaW5nIHRoZSB3b3JrIG9mIGl0ZXJhdGluZyB0aHJvdWdoCiAgICAvLyB0aGUgdGV4dCBzdHJpbmcsIHdlIGNhbiBqdXN0IGFzayBpdCB3aGF0IGl0cyBvZmZzZXQgaXMuCiAgICByZXR1cm4gKHRleHQgIT0gTlVMTCkgPyB0ZXh0LT5nZXRJbmRleCgpIDogMDsKfQoKdm9pZCAKQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpzZXRPZmZzZXQoVVRleHRPZmZzZXQgbmV3T2Zmc2V0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmICh0ZXh0ICE9IE5VTEwpCiAgICB7CiAgICAgICAgdGV4dC0+c2V0SW5kZXgobmV3T2Zmc2V0KTsKICAgIH0KCiAgICBidWZmZXJBbGlhcyA9IE5VTEw7Cn0KCi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ci8vIHByaXZhdGVzCi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgovKioKICogR2V0IHRoZSBvcmRlcmluZyBwcmlvcml0eSBvZiB0aGUgbmV4dCBjb250cmFjdGluZyBjaGFyYWN0ZXIgaW4gdGhlCiAqIHN0cmluZy4KICogQHBhcmFtIGNoIHRoZSBzdGFydGluZyBjaGFyYWN0ZXIgb2YgYSBjb250cmFjdGluZyBjaGFyYWN0ZXIgdG9rZW4KICogQHJldHVybiB0aGUgbmV4dCBjb250cmFjdGluZyBjaGFyYWN0ZXIncyBvcmRlcmluZy4gIFJldHVybnMgTlVMTE9SREVSCiAqIGlmIHRoZSBlbmQgb2Ygc3RyaW5nIGlzIHJlYWNoZWQuCiAqLwppbnQzMl90CkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6bmV4dENvbnRyYWN0Q2hhcihVQ2hhciBjaCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN0YXR1cykKewogICAgLy8gRmlyc3QgZ2V0IHRoZSBvcmRlcmluZyBvZiB0aGlzIHNpbmdsZSBjaGFyYWN0ZXIKICAgIFZlY3Rvck9mUFRvQ29udHJhY3RFbGVtZW50ICpsaXN0ID0gb3JkZXJBbGlhcy0+Z2V0Q29udHJhY3RWYWx1ZXMoY2gpOwogICAgRW50cnlQYWlyICpwYWlyID0gKEVudHJ5UGFpciAqKWxpc3QtPmF0KDApOwogICAgaW50MzJfdCBvcmRlciA9IHBhaXItPnZhbHVlOwoKICAgIC8vIE5vdyBpdGVyYXRlIHRocm91Z2ggdGhlIGNoYXJzIGZvbGxvd2luZyBpdCBhbmQKICAgIC8vIGxvb2sgZm9yIHRoZSBsb25nZXN0IG1hdGNoCiAgICBrZXkucmVtb3ZlKCk7CiAgICBrZXkgKz0gY2g7CgogICAgd2hpbGUgKChjaCA9IHRleHQtPmN1cnJlbnQoKSkgIT0gTm9ybWFsaXplcjo6RE9ORSkKICAgIHsKICAgICAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gTlVMTE9SREVSOwogICAgICAgIH0KCiAgICAgICAga2V5ICs9IGNoOwoKICAgICAgICBpbnQzMl90IG4gPSBSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0RW50cnkobGlzdCwga2V5LCBUUlVFKTsKCiAgICAgICAgaWYgKG4gPT0gUnVsZUJhc2VkQ29sbGF0b3I6OlVOTUFQUEVEKQogICAgICAgIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHRleHQtPm5leHQoKTsKCiAgICAgICAgcGFpciA9IChFbnRyeVBhaXIgKilsaXN0LT5hdChuKTsKICAgICAgICBvcmRlciA9IHBhaXItPnZhbHVlOwogICAgfQoKICAgIHJldHVybiBvcmRlcjsKfQoKLyoqCiAqIEdldCB0aGUgb3JkZXJpbmcgcHJpb3JpdHkgb2YgdGhlIHByZXZpb3VzIGNvbnRyYWN0aW5nIGNoYXJhY3RlciBpbiB0aGUKICogc3RyaW5nLgogKiBAcGFyYW0gY2ggdGhlIHN0YXJ0aW5nIGNoYXJhY3RlciBvZiBhIGNvbnRyYWN0aW5nIGNoYXJhY3RlciB0b2tlbgogKiBAcmV0dXJuIHRoZSBuZXh0IGNvbnRyYWN0aW5nIGNoYXJhY3RlcidzIG9yZGVyaW5nLiAgUmV0dXJucyBOVUxMT1JERVIKICogaWYgdGhlIGVuZCBvZiBzdHJpbmcgaXMgcmVhY2hlZC4KICovCmludDMyX3QgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpwcmV2Q29udHJhY3RDaGFyKFVDaGFyIGNoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlICZzdGF0dXMpCnsKICAgIC8vIEZpcnN0IGdldCB0aGUgb3JkZXJpbmcgb2YgdGhpcyBzaW5nbGUgY2hhcmFjdGVyCiAgICBWZWN0b3JPZlBUb0NvbnRyYWN0RWxlbWVudCAqbGlzdCA9IG9yZGVyQWxpYXMtPmdldENvbnRyYWN0VmFsdWVzKGNoKTsKICAgIEVudHJ5UGFpciAqcGFpciA9IChFbnRyeVBhaXIgKilsaXN0LT5hdCgwKTsKICAgIGludDMyX3Qgb3JkZXIgPSBwYWlyLT52YWx1ZTsKCiAgICAvLyBOb3cgaXRlcmF0ZSB0aHJvdWdoIHRoZSBjaGFycyBmb2xsb3dpbmcgaXQgYW5kCiAgICAvLyBsb29rIGZvciB0aGUgbG9uZ2VzdCBtYXRjaAogICAga2V5LnJlbW92ZSgpOwogICAga2V5ICs9IGNoOwoKICAgIHdoaWxlICgoY2ggPSB0ZXh0LT5wcmV2aW91cygpKSAhPSBOb3JtYWxpemVyOjpET05FKQogICAgewogICAgICAgIGtleSArPSBjaDsKCiAgICAgICAgaW50MzJfdCBuID0gUnVsZUJhc2VkQ29sbGF0b3I6OmdldEVudHJ5KGxpc3QsIGtleSwgRkFMU0UpOwoKICAgICAgICBpZiAobiA9PSBSdWxlQmFzZWRDb2xsYXRvcjo6VU5NQVBQRUQpCiAgICAgICAgewogICAgICAgICAgICBjaCA9IHRleHQtPm5leHQoKTsKCiAgICAgICAgICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmV0dXJuIE5VTExPUkRFUjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICBwYWlyID0gKEVudHJ5UGFpciAqKWxpc3QtPmF0KG4pOwogICAgICAgIG9yZGVyID0gcGFpci0+dmFsdWU7CiAgICB9CgogICAgcmV0dXJuIG9yZGVyOwp9CgovKioKICogVGhpcyBtZXRob2QgcHJvZHVjZXMgYSBidWZmZXIgd2hpY2ggY29udGFpbnMgdGhlIGNvbGxhdGlvbgogKiBlbGVtZW50cyBmb3IgdGhlIHR3byBjaGFyYWN0ZXJzLCB3aXRoIGNvbEZpcnN0J3MgdmFsdWVzIHByZWNlZGluZwogKiBhbm90aGVyIGNoYXJhY3RlcidzLiAgUHJlc3VtYWJseSwgdGhlIG90aGVyIGNoYXJhY3RlciBwcmVjZWRlcyBjb2xGaXJzdAogKiBpbiBsb2dpY2FsCiAqIG9yZGVyIChvdGhlcndpc2UgeW91IHdvdWxkbid0IG5lZWQgdGhpcyBtZXRob2Qgd291bGQgeW91PykuCiAqIFRoZSBhc3N1bXB0aW9uIGlzIHRoYXQgdGhlIG90aGVyIGNoYXIncyB2YWx1ZShzKSBoYXZlIGFscmVhZHkgYmVlbgogKiBjb21wdXRlZC4gIElmIHRoaXMgY2hhciBoYXMgYSBzaW5nbGUgZWxlbWVudCBpdCBpcyBwYXNzZWQgdG8gdGhpcwogKiBtZXRob2QgYXMgbGFzdFZhbHVlLCBhbmQgbGFzdEV4cGFzaW9uIGlzIG51bGwuICBJZiBpdCBoYXMgYW4KICogZXhwYXNpb24gaXQgaXMgcGFzc2VkIGluIGxhc3RFeHBhbnNpb24sIGFuZCBjb2xMYXN0VmFsdWUgaXMgaWdub3JlZC4KICogVGhpcyBtZXRob2QgbWF5IHJldHVybiB0aGUgb3duQnVmZmVyIGFycmF5IGFzIGl0cyB2YWx1ZSBzbyBvd25CdWZmZXIKICogaGFkIGJldHRlciBub3QgYmUgaW4gdXNlIGFueXdoZXJlIGVsc2UuCiAqLwpWZWN0b3JPZkludCogQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjptYWtlUmVvcmRlcmVkQnVmZmVyKFVDaGFyIGNvbEZpcnN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludDMyX3QgbGFzdFZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZlY3Rvck9mSW50KiBsYXN0RXhwYW5zaW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvb2xfdCBmb3J3YXJkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN0YXR1cykgewoKICAgIFZlY3Rvck9mSW50KiByZXN1bHQ7CgogICAgaW50MzJfdCBmaXJzdFZhbHVlID0gdWNtcDMyX2dldChvcmRlckFsaWFzLT5kYXRhLT5tYXBwaW5nLCBjb2xGaXJzdCk7CiAgICBpZiAoZmlyc3RWYWx1ZSA+PSBSdWxlQmFzZWRDb2xsYXRvcjo6Q09OVFJBQ1RDSEFSSU5ERVgpIHsKICAgICAgICBmaXJzdFZhbHVlID0gZm9yd2FyZCA/IG5leHRDb250cmFjdENoYXIoY29sRmlyc3QsIHN0YXR1cykKICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHByZXZDb250cmFjdENoYXIoY29sRmlyc3QsIHN0YXR1cyk7CiAgICB9CgogICAgVmVjdG9yT2ZJbnQqIGZpcnN0RXhwYW5zaW9uID0gTlVMTDsKICAgIGlmIChmaXJzdFZhbHVlID49IFJ1bGVCYXNlZENvbGxhdG9yOjpFWFBBTkRDSEFSSU5ERVgpIHsKICAgICAgICBmaXJzdEV4cGFuc2lvbiA9IG9yZGVyQWxpYXMtPmdldEV4cGFuZFZhbHVlTGlzdChmaXJzdFZhbHVlKTsKICAgIH0KCiAgICBpZiAoIWZvcndhcmQpIHsKICAgICAgICBpbnQzMl90IHRlbXAxID0gZmlyc3RWYWx1ZTsKICAgICAgICBmaXJzdFZhbHVlID0gbGFzdFZhbHVlOwogICAgICAgIGxhc3RWYWx1ZSA9IHRlbXAxOwogICAgICAgIFZlY3Rvck9mSW50KiB0ZW1wMiA9IGZpcnN0RXhwYW5zaW9uOwogICAgICAgIGZpcnN0RXhwYW5zaW9uID0gbGFzdEV4cGFuc2lvbjsKICAgICAgICBsYXN0RXhwYW5zaW9uID0gdGVtcDI7CiAgICB9CgogICAgaWYgKGZpcnN0RXhwYW5zaW9uID09IE5VTEwgJiYgbGFzdEV4cGFuc2lvbiA9PSBOVUxMKSB7CiAgICAgICAgb3duQnVmZmVyLT5hdCgwKSA9IGZpcnN0VmFsdWU7CiAgICAgICAgb3duQnVmZmVyLT5hdCgxKSA9IGxhc3RWYWx1ZTsKICAgICAgICByZXN1bHQgPSBvd25CdWZmZXI7CiAgICB9CiAgICBlbHNlIHsKICAgICAgICBpbnQzMl90IGZpcnN0TGVuZ3RoID0gZmlyc3RFeHBhbnNpb249PU5VTEw/IDEgOiBmaXJzdEV4cGFuc2lvbi0+c2l6ZSgpOwogICAgICAgIGludDMyX3QgbGFzdExlbmd0aCA9IGxhc3RFeHBhbnNpb249PU5VTEw/IDEgOiBsYXN0RXhwYW5zaW9uLT5zaXplKCk7CiAgICAgICAgaWYgKHJlb3JkZXJCdWZmZXIgPT0gTlVMTCkgewogICAgICAgICAgICByZW9yZGVyQnVmZmVyID0gbmV3IFZlY3Rvck9mSW50KGZpcnN0TGVuZ3RoK2xhc3RMZW5ndGgpOwogICAgICAgIH0KICAgICAgICAvLyByZW9yZGVyZEJ1ZmZlciBnZXRzIHJldXNlZCBmb3IgdGhlIGxpZmUgb2YgdGhpcyBvYmplY3QuCiAgICAgICAgLy8gU2luY2UgaXRzIGludGVybmFsIGJ1ZmZlciBvbmx5IGdyb3dzLCB0aGVyZSBpcyBhIGRhbmdlcgogICAgICAgIC8vIHRoYXQgaXQgd2lsbCBnZXQgcmVhbGx5LCByZWFsbHkgYmlnLCBhbmQgbmV2ZXIgc2hyaW5rLiAgSWYKICAgICAgICAvLyB0aGlzIGlzIGFjdHVhbGx5IGhhcHBlbmluZywgaW5zZXJ0IGNvZGUgaGVyZSB0byBjaGVjayBmb3IKICAgICAgICAvLyB0aGUgY29uZGl0aW9uLiAgU29tZXRoaW5nIGFsb25nIHRoZSBsaW5lcyBvZjoKICAgICAgICAvLyEgZWxzZSBpZiAocmVvcmRlckJ1ZmZlci0+c2l6ZSgpID49IDI1NiAmJgogICAgICAgIC8vISAgICAgICAgICAoZmlyc3RMZW5ndGgrbGFzdExlbmd0aCkgPCAxNikgewogICAgICAgIC8vISAgICAgZGVsZXRlIHJlb3JkZXJCdWZmZXI7CiAgICAgICAgLy8hICAgICByZW9yZGVyQnVmZmVyID0gbmV3IFZlY3Rvck9mSW50KGZpcnN0TGVuZ3RoK2xhc3RMZW5ndGgpOwogICAgICAgIC8vISB9CiAgICAgICAgLy8gVGhlIHNwZWNpZmljIG51bWVyaWMgdmFsdWVzIG5lZWQgdG8gYmUgZGV0ZXJtaW5lZAogICAgICAgIC8vIGVtcGlyaWNhbGx5LiBbYWxpdV0KICAgICAgICByZXN1bHQgPSByZW9yZGVyQnVmZmVyOwoKICAgICAgICBpZiAoZmlyc3RFeHBhbnNpb24gPT0gTlVMTCkgewogICAgICAgICAgICByZXN1bHQtPmF0UHV0KDAsIGZpcnN0VmFsdWUpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgLy8gU3lzdGVtLmFycmF5Y29weShmaXJzdEV4cGFuc2lvbiwgMCwgcmVzdWx0LCAwLCBmaXJzdExlbmd0aCk7CiAgICAgICAgICAgICpyZXN1bHQgPSAqZmlyc3RFeHBhbnNpb247CiAgICAgICAgfQoKICAgICAgICBpZiAobGFzdEV4cGFuc2lvbiA9PSBOVUxMKSB7CiAgICAgICAgICAgIHJlc3VsdC0+YXRQdXQoZmlyc3RMZW5ndGgsIGxhc3RWYWx1ZSk7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAvLyBTeXN0ZW0uYXJyYXljb3B5KGxhc3RFeHBhbnNpb24sIDAsIHJlc3VsdCwgZmlyc3RMZW5ndGgsIGxhc3RMZW5ndGgpOwogICAgICAgICAgICBmb3IgKGludDMyX3QgaT0wOyBpPGxhc3RMZW5ndGg7ICsraSkgewogICAgICAgICAgICAgICAgcmVzdWx0LT5hdFB1dChmaXJzdExlbmd0aCArIGksIGxhc3RFeHBhbnNpb24tPmF0KGkpKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXN1bHQtPnNldFNpemUoZmlyc3RMZW5ndGgrbGFzdExlbmd0aCk7CiAgICB9CgogICAgcmV0dXJuIHJlc3VsdDsKfQo=