LyoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqIENvcHlyaWdodCAoQykgMTk5Ni0xOTk5LCBJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uIGFuZCAgICAqCiogb3RoZXJzLiBBbGwgUmlnaHRzIFJlc2VydmVkLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqCiogRmlsZSB0Ymxjb2xsLmNwcAoqCiogQ3JlYXRlZCBieTogSGVsZW5hIFNoaWgKKgoqIE1vZGlmaWNhdGlvbiBIaXN0b3J5OgoqCiogIERhdGUgICAgICAgIE5hbWUgICAgICAgIERlc2NyaXB0aW9uCiogIDIvNS85NyAgICAgIGFsaXUgICAgICAgIEFkZGVkIHN0cmVhbUluIGFuZCBzdHJlYW1PdXQgbWV0aG9kcy4gIEFkZGVkCiogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yIHdoaWNoIHJlYWRzIFJ1bGVCYXNlZENvbGxhdG9yIG9iamVjdCBmcm9tCiogICAgICAgICAgICAgICAgICAgICAgICAgIGEgYmluYXJ5IGZpbGUuICBBZGRlZCB3cml0ZVRvRmlsZSBtZXRob2Qgd2hpY2ggc3RyZWFtcwoqICAgICAgICAgICAgICAgICAgICAgICAgICBSdWxlQmFzZWRDb2xsYXRvciBvdXQgdG8gYSBiaW5hcnkgZmlsZS4gIFRoZSBzdHJlYW1JbgoqICAgICAgICAgICAgICAgICAgICAgICAgICBhbmQgc3RyZWFtT3V0IG1ldGhvZHMgdXNlIGlzdHJlYW0gYW5kIG9zdHJlYW0gb2JqZWN0cwoqICAgICAgICAgICAgICAgICAgICAgICAgICBpbiBiaW5hcnkgbW9kZS4KKiAgMi8xMS85NyAgICAgYWxpdSAgICAgICAgTW92ZWQgZGVjbGFyYXRpb25zIG91dCBvZiBmb3IgbG9vcCBpbml0aWFsaXplci4KKiAgICAgICAgICAgICAgICAgICAgICAgICAgQWRkZWQgTWFjIGNvbXBhdGliaWxpdHkgI2lmZGVmIGZvciBpb3M6Om5vY3JlYXRlLgoqICAyLzEyLzk3ICAgICBhbGl1ICAgICAgICBNb2RpZmllZCB0byB1c2UgVGFibGVDb2xsYXRpb25EYXRhIHN1Yi1vYmplY3QgdG8KKiAgICAgICAgICAgICAgICAgICAgICAgICAgaG9sZCBpbnZhcmlhbnQgZGF0YS4KKiAgMi8xMy85NyAgICAgYWxpdSAgICAgICAgTW92ZWQgc2V2ZXJhbCBtZXRob2RzIGludG8gdGhpcyBjbGFzcyBmcm9tIENvbGxhdGlvbi4KKiAgICAgICAgICAgICAgICAgICAgICAgICAgQWRkZWQgYSBwcml2YXRlIFJ1bGVCYXNlZENvbGxhdG9yKExvY2FsZSYpIGNvbnN0cnVjdG9yLAoqICAgICAgICAgICAgICAgICAgICAgICAgICB0byBiZSB1c2VkIGJ5IENvbGxhdG9yOjpnZXRJbnN0YW5jZSgpLiAgR2VuZXJhbAoqICAgICAgICAgICAgICAgICAgICAgICAgICBjbGVhbiB1cC4gIE1hZGUgdXNlIG9mIFVFcnJvckNvZGUgdmFyaWFibGVzIGNvbnNpc3RlbnQuCiogIDIvMjAvOTcgICAgIGhlbGVuYSAgICAgIEFkZGVkIGNsb25lLCBvcGVyYXRvcj09LCBvcGVyYXRvciE9LCBvcGVyYXRvcj0sIGFuZCBjb3B5CiogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yIGFuZCBnZXREeW5hbWljQ2xhc3NJRC4KKiAgMy81Lzk3ICAgICAgYWxpdSAgICAgICAgQ2hhbmdlZCBjb21wYWN0aW9uIGN5Y2xlIHRvIGltcHJvdmUgcGVyZm9ybWFuY2UuICBXZQoqICAgICAgICAgICAgICAgICAgICAgICAgICB1c2UgdGhlIG1heGltdW0gYWxsb3dhYmxlIHZhbHVlIHdoaWNoIGlzIGtCbG9ja0NvdW50LgoqICAgICAgICAgICAgICAgICAgICAgICAgICBNb2RpZmllZCBnZXRSdWxlcygpIHRvIGxvYWQgcnVsZXMgZHluYW1pY2FsbHkuICBDaGFuZ2VkCiogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdEZyb21GaWxlKCkgY2FsbCB0byBhY2NvbW9kYXRlIHRoaXMgKGFkZGVkCiogICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlciB0byBzcGVjaWZ5IHdoZXRoZXIgYmluYXJ5IGxvYWRpbmcgaXMgdG8KKiAgICAgICAgICAgICAgICAgICAgICAgICAgdGFrZSBwbGFjZSkuCiogMDUvMDYvOTcgICAgIGhlbGVuYSAgICAgIEFkZGVkIG1lbW9yeSBhbGxvY2F0aW9uIGVycm9yIGNoZWNrLgoqICA2LzIwLzk3ICAgICBoZWxlbmEgICAgICBKYXZhIGNsYXNzIG5hbWUgY2hhbmdlLgoqICA2LzIzLzk3ICAgICBoZWxlbmEgICAgICBBZGRpbmcgY29tbWVudHMgdG8gbWFrZSBjb2RlIG1vcmUgcmVhZGFibGUuCiogMDkvMDMvOTcgICAgIGhlbGVuYSAgICAgIEFkZGVkIGNyZWF0ZUNvbGxhdGlvbktleVZhbHVlcygpLgoqIDA2LzI2Lzk4ICAgICBlcm0gICAgICAgICBDaGFuZ2VzIGZvciBDb2xsYXRpb25LZXlzIHVzaW5nIGJ5dGUgYXJyYXlzLgoqIDA4LzEwLzk4ICAgICBlcm0gICAgICAgICBTeW5jaGVkIHdpdGggMS4yIHZlcnNpb24gb2YgUnVsZUJhc2VkQ29sbGF0b3IuamF2YQoqIDA0LzIzLzk5ICAgICBzdGVwaGVuICAgICBSZW1vdmVkIEVEZWNvbXBvc2l0aW9uTW9kZSwgbWVyZ2VkIHdpdGgKKiAgICAgICAgICAgICAgICAgICAgICAgICAgTm9ybWFsaXplcjo6RU1vZGUKKiAwNi8xNC85OSAgICAgc3RlcGhlbiAgICAgUmVtb3ZlZCBrUmVzb3VyY2VCdW5kbGVTdWZmaXgKKiAwNi8yMi85OSAgICAgc3RlcGhlbiAgICAgRml4ZWQgbG9naWMgaW4gY29uc3RydWN0RnJvbUZpbGUoKSBzaW5jZSAuY3R4CiogICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVzIGFyZSBubyBsb25nZXIgdXNlZC4KKiAxMS8wMi85OSAgICAgaGVsZW5hICAgICAgQ29sbGF0b3IgcGVyZm9ybWFuY2UgZW5oYW5jZW1lbnRzLiAgU3BlY2lhbCBjYXNlCiogICAgICAgICAgICAgICAgICAgICAgICAgIGZvciBOT19PUCBzaXR1YXRpb25zLiAKKiAxMS8xNy85OSAgICAgc3JsICAgICAgICAgTW9yZSBwZXJmb3JtYW5jZSBlbmhhbmNlbWVudHMuIElubGluZWQgc29tZSBpbnRlcm5hbCBmdW5jdGlvbnMuCiogMTIvMTUvOTkgICAgIGFsaXUgICAgICAgIFVwZGF0ZSB0byBzdXBwb3J0IFRoYWkgY29sbGF0aW9uLiAgTW92ZSBOb3JtYWxpemVySXRlcmF0b3IKKiAgICAgICAgICAgICAgICAgICAgICAgICAgdG8gaW1wbGVtZW50YXRpb24gZmlsZS4KKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqLwoKI2luY2x1ZGUgInVjbXAzMi5oIgojaW5jbHVkZSAidGNvbGRhdGEuaCIKCiNpbmNsdWRlICJ1bmljb2RlL3RibGNvbGwuaCIKCiNpbmNsdWRlICJ1bmljb2RlL2NvbGVpdHIuaCIKI2luY2x1ZGUgInVuaWNvZGUvbG9jaWQuaCIKI2luY2x1ZGUgInVuaWNvZGUvdW5pY29kZS5oIgojaW5jbHVkZSAidGFibGVzLmgiCiNpbmNsdWRlICJ1bmljb2RlL25vcm1senIuaCIKI2luY2x1ZGUgIm1lcmdlY29sLmgiCiNpbmNsdWRlICJ1bmljb2RlL3Jlc2J1bmQuaCIKI2luY2x1ZGUgImZpbGVzdHJtLmgiCiNpbmNsdWRlICJ1bWVtc3RybS5oIgoKI2lmZGVmIF9ERUJVRwojaW5jbHVkZSAidW5pc3RybS5oIgojZW5kaWYKCiNpbmNsdWRlICJjb21waXRyLmgiCgojaW5jbHVkZSA8c3RyaW5nLmg+CgojaW5jbHVkZSAidW5pY29kZS91c3RyaW5nLmgiCgojaW5jbHVkZSAiY21lbW9yeS5oIgoKCmNsYXNzIFJ1bGVCYXNlZENvbGxhdG9yU3RyZWFtZXIKewpwdWJsaWM6CiAgIHN0YXRpYyB2b2lkIHN0cmVhbUluKFJ1bGVCYXNlZENvbGxhdG9yKiBjb2xsYXRvciwgRmlsZVN0cmVhbSogaXMpOwogICBzdGF0aWMgdm9pZCBzdHJlYW1PdXQoY29uc3QgUnVsZUJhc2VkQ29sbGF0b3IqIGNvbGxhdG9yLCBGaWxlU3RyZWFtKiBvcyk7CiAgIHN0YXRpYyB2b2lkIHN0cmVhbUluKFJ1bGVCYXNlZENvbGxhdG9yKiBjb2xsYXRvciwgVU1lbW9yeVN0cmVhbSogaXMpOwogICBzdGF0aWMgdm9pZCBzdHJlYW1PdXQoY29uc3QgUnVsZUJhc2VkQ29sbGF0b3IqIGNvbGxhdG9yLCBVTWVtb3J5U3RyZWFtKiBvcyk7Cn07CgovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gIFRoZSBmb2xsb3dpbmcgZGlhZ3JhbSBzaG93cyB0aGUgZGF0YSBzdHJ1Y3R1cmUgb2YgdGhlIFJ1bGVCYXNlZENvbGxhdG9yIG9iamVjdC4KLy8gIFN1cHBvc2Ugd2UgaGF2ZSB0aGUgcnVsZSwgd2hlcmUgJ28tdW1sYXV0JyBpcyB0aGUgdW5pY29kZSBjaGFyIDB4MDBGNi4KLy8gICJhLCBBIDwgYiwgQiA8IGMsIEMsIGNoLCBjSCwgQ2gsIENIIDwgZCwgRCAuLi4gPCBvLCBPOyAnby11bWxhdXQnL0UsICdPLXVtbGF1dCcvRSAuLi4iLgovLyAgV2hhdCB0aGUgcnVsZSBzYXlzIGlzLCBzb3J0cyAnY2gnbGlnYXR1cmVzIGFuZCAnYycgb25seSB3aXRoIHRlcnRpYXJ5IGRpZmZlcmVuY2UgYW5kCi8vICBzb3J0cyAnby11bWxhdXQnIGFzIGlmIGl0J3MgYWx3YXlzIGV4cGFuZGVkIHdpdGggJ2UnLgovLwovLyBtYXBwaW5nIHRhYmxlICAgICAgICAgICAgICAgICAgICAgICBjb250cmFjdGluZyBsaXN0ICAgICAgICAgICAgICAgICAgZXhwYW5kaW5nIGxpc3QKLy8gKGNvbnRhaW5zIGFsbCB1bmljb2RlIGNoYXIKLy8gIGVudHJpZXMpICAgICAgICAgICAgICAgICAgICAgICAgIF9fXyAgICAgX19fX19fX19fX19fXyAgICAgICAgIF9fX19fX19fX19fX19fX19fX19fX19fX18KLy8gICBfX19fX19fXyAgICAgICAgICAgICAgICAgICB8PT0+fF8qX3wtLT58J2MnICB8dignYycpIHwgICB8PT0+fHYoJ28nKXx2KCd1bWxhdXQnKXx2KCdlJyl8Ci8vICB8X1x1MDAwMV98LS0+IHYoJ1x1MDAwMScpICAgfCAgIHxfOl98ICAgfC0tLS0tLS0tLS0tLS18ICAgfCAgIHwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAovLyAgfF9cdTAwMDJffC0tPiB2KCdcdTAwMDInKSAgIHwgICB8XzpffCAgIHwnY2gnIHx2KCdjaCcpfCAgIHwgICB8ICAgICAgICAgICAgIDogICAgICAgICAgIHwKLy8gIHxfX19fOl9fX3wgICAgICAgICAgICAgICAgICB8ICAgfF86X3wgICB8LS0tLS0tLS0tLS0tLXwgICB8ICAgfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18Ci8vICB8X19fXzpfX198ICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgfCdjSCcgfHYoJ2NIJyl8ICAgfCAgIHwgICAgICAgICAgICAgOiAgICAgICAgICAgfAovLyAgfF9fJ2EnX19ffC0tPiB2KCdhJykgICAgICAgIHwgICAgICAgICAgIHwtLS0tLS0tLS0tLS0tfCAgIHwgICB8LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwKLy8gIHxfXydiJ19fX3wtLT4gdignYicpICAgICAgICB8ICAgICAgICAgICB8J0NoJyB8dignQ2gnKXwgICB8ICAgfCAgICAgICAgICAgICA6ICAgICAgICAgICB8Ci8vICB8X19fXzpfX198ICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgfC0tLS0tLS0tLS0tLS18ICAgfCAgIHwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAovLyAgfF9fX186X19ffCAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgIHwnQ0gnIHx2KCdDSCcpfCAgIHwgICB8ICAgICAgICAgICAgIDogICAgICAgICAgIHwKLy8gIHxfX18nYydfX3wtLS0tLS0tLS0tLS0tLS0tLS0tICAgICAgICAgICAgLS0tLS0tLS0tLS0tLSAgICB8ICAgfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18Ci8vICB8X19fXzpfX198ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIHwgICAgICAgICAgICAgOiAgICAgICAgICAgfAovLyAgfG8tdW1sYXV0fC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgICB8X19fX19fX19fX19fX19fX19fX19fX19fX3wKLy8gIHxfX19fOl9fX3wKLy8KLy8KLy8gTm90ZWQgYnkgSGVsZW5hIFNoaWggb24gNi8yMy85NyB3aXRoIHBlbmRpbmcgZGVzaWduIGNoYW5nZXMgKHNsaW1taW5nIGNvbGxhdGlvbikuCi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OkNIQVJJTkRFWCA9IDB4NzAwMDAwMDA7ICAgICAgICAgICAgIC8vIG5lZWQgbG9vayB1cCBpbiAuY29tbWl0KCkKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6RVhQQU5EQ0hBUklOREVYID0gMHg3RTAwMDAwMDsgICAgICAgLy8gRXhwYW5kIGluZGV4IGZvbGxvd3MKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6Q09OVFJBQ1RDSEFSSU5ERVggPSAweDdGMDAwMDAwOyAgICAgLy8gY29udHJhY3QgaW5kZXhlcyBmb2xsb3dzCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlVOTUFQUEVEID0gMHhGRkZGRkZGRjsgICAgICAgICAgICAgIC8vIHVubWFwcGVkIGNoYXJhY3RlciB2YWx1ZXMKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6UFJJTUFSWU9SREVSSU5DUkVNRU5UID0gMHgwMDAxMDAwMDsgLy8gcHJpbWFyeSBzdHJlbmd0aCBpbmNyZW1lbnQKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6U0VDT05EQVJZT1JERVJJTkNSRU1FTlQgPSAweDAwMDAwMTAwOyAvLyBzZWNvbmRhcnkgc3RyZW5ndGggaW5jcmVtZW50CmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlRFUlRJQVJZT1JERVJJTkNSRU1FTlQgPSAweDAwMDAwMDAxOyAvLyB0ZXJ0aWFyeSBzdHJlbmd0aCBpbmNyZW1lbnQKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6TUFYSUdOT1JBQkxFID0gMHgwMDAxMDAwMDsgICAgICAgICAgLy8gbWF4aW11bSBpZ25vcmFibGUgY2hhciBvcmRlciB2YWx1ZQpjb25zdCBpbnQzMl90IFJ1bGVCYXNlZENvbGxhdG9yOjpQUklNQVJZT1JERVJNQVNLID0gMHhmZmZmMDAwMDsgICAgICAvLyBtYXNrIG9mZiBhbnl0aGluZyBidXQgcHJpbWFyeSBvcmRlcgpjb25zdCBpbnQzMl90IFJ1bGVCYXNlZENvbGxhdG9yOjpTRUNPTkRBUllPUkRFUk1BU0sgPSAweDAwMDBmZjAwOyAgICAvLyBtYXNrIG9mZiBhbnl0aGluZyBidXQgc2Vjb25kYXJ5IG9yZGVyCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlRFUlRJQVJZT1JERVJNQVNLID0gMHgwMDAwMDBmZjsgICAgIC8vIG1hc2sgb2ZmIGFueXRoaW5nIGJ1dCB0ZXJ0aWFyeSBvcmRlcgpjb25zdCBpbnQzMl90IFJ1bGVCYXNlZENvbGxhdG9yOjpTRUNPTkRBUllSRVNFVE1BU0sgPSAweDAwMDBmZmZmOyAgICAvLyBtYXNrIG9mZiBzZWNvbmRhcnkgYW5kIHRlcnRpYXJ5IG9yZGVyCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OklHTk9SQUJMRU1BU0sgPSAweDAwMDBmZmZmOyAgICAgICAgIC8vIG1hc2sgb2ZmIGlnbm9yYWJsZSBjaGFyIG9yZGVyCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlBSSU1BUllESUZGRVJFTkNFT05MWSA9IDB4ZmZmZjAwMDA7IC8vIHVzZSBvbmx5IHRoZSBwcmltYXJ5IGRpZmZlcmVuY2UKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6U0VDT05EQVJZRElGRkVSRU5DRU9OTFkgPSAweGZmZmZmZjAwOyAgLy8gdXNlIG9ubHkgdGhlIHByaW1hcnkgYW5kIHNlY29uZGFyeSBkaWZmZXJlbmNlCmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlBSSU1BUllPUkRFUlNISUZUID0gMTY7ICAgICAgICAgICAgIC8vIHByaW1hcnkgb3JkZXIgc2hpZnQKY29uc3QgaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6U0VDT05EQVJZT1JERVJTSElGVCA9IDg7ICAgICAgICAgICAgLy8gc2Vjb25kYXJ5IG9yZGVyIHNoaWZ0CmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OlNPUlRLRVlPRkZTRVQgPSAxOyAgICAgICAgICAgICAgICAgIC8vIG1pbmltdW0gc29ydCBrZXkgb2Zmc2V0CmNvbnN0IGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OkNPTlRSQUNUQ0hBUk9WRVJGTE9XID0gMHg3RkZGRkZGRjsgIC8vIEluZGljYXRlcyB0aGUgY2hhciBpcyBhIGNvbnRyYWN0IGNoYXIKCmNvbnN0IGludDE2X3QgUnVsZUJhc2VkQ29sbGF0b3I6OkZJTEVJRCA9IDB4NTQ0MzsgICAgICAgICAgICAgICAgICAgIC8vIHVuaXF1ZSBmaWxlIGlkIGZvciBwYXJpdHkgY2hlY2sKY29uc3QgY2hhciogUnVsZUJhc2VkQ29sbGF0b3I6OmtGaWxlbmFtZVN1ZmZpeCA9ICIuY29sIjsgICAgICAgICAgICAgLy8gYmluYXJ5IGNvbGxhdGlvbiBmaWxlIGV4dGVuc2lvbgpjaGFyICBSdWxlQmFzZWRDb2xsYXRvcjo6ZmdDbGFzc0lEID0gMDsgLy8gVmFsdWUgaXMgaXJyZWxldmFudCAgICAgICAvLyBjbGFzcyBpZAoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCi8vIE5vcm1hbGl6ZXJJdGVyYXRvcgovLwovLyBUaGlzIGNsYXNzIGlzIGVzc2VudGlhbGx5IGEgZHVwbGljYXRlIG9mIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciwKLy8gc3RyaXBwZWQgZG93biBmb3Igc3BlZWQuICBJdCBpcyBkZWNsYXJlZCBoZXJlIHNvIHdlIGNhbiBpbmNvcnBvcmF0ZQovLyBpbnRlcm5hbCBjbGFzc2VzIGFzIHN1Ym9iamVjdHMsIGFzIHdlbGwgYXMganVzdCB0byBoaWRlIGl0IGZyb20gdGhlCi8vIHB1YmxpYyBpbnRlcmZhY2UuCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoKLyogSW50ZXJuYWwgY2xhc3MgZm9yIHF1aWNrIGl0ZXJhdGlvbiBvdmVyIHRoZSB0ZXh0LgogICAxMDAlIHB1cmUgaW5saW5lIGNvZGUKKi8KY2xhc3MgTm9ybWFsaXplckl0ZXJhdG9yIHsgCnB1YmxpYzoKICAgIE5vcm1hbGl6ZXIgKmN1cnNvcjsKICAgIFZlY3Rvck9mSW50ICpidWZmZXJBbGlhczsKICAgIFZlY3Rvck9mSW50ICpyZW9yZGVyQnVmZmVyOwogICAgVmVjdG9yT2ZJbnQgb3duQnVmZmVyOwogICAgVUNoYXIqICAgICAgdGV4dDsKICAgIGludDMyX3QgICAgIGV4cEluZGV4OwogICAgaW50MzJfdCAgICAgdGV4dExlbjsKICAgIFVUZXh0T2Zmc2V0ICBjdXJyZW50T2Zmc2V0OwogICAgCiAgICBOb3JtYWxpemVySXRlcmF0b3Iodm9pZCk7CiAgICBOb3JtYWxpemVySXRlcmF0b3IoY29uc3QgVUNoYXIqIHNvdXJjZSwgaW50MzJfdCBsZW5ndGgsIE5vcm1hbGl6ZXI6OkVNb2RlIG1vZGUpOwogICAgfk5vcm1hbGl6ZXJJdGVyYXRvcih2b2lkKTsKICAgIHZvaWQgc2V0VGV4dChjb25zdCBVQ2hhciogc291cmNlLCBpbnQzMl90IGxlbmd0aCwgVUVycm9yQ29kZSYgc3RhdHVzKTsKICAgIHZvaWQgc2V0TW9kZUFuZFRleHQoTm9ybWFsaXplcjo6RU1vZGUgbW9kZSwgY29uc3QgVUNoYXIqIHNvdXJjZSwgaW50MzJfdCBsZW5ndGgsIFVFcnJvckNvZGUmIHN0YXR1cyk7CiAgICAKICAgIFVDaGFyIGN1cnJlbnQodm9pZCkgY29uc3Q7CiAgICBVQ2hhciBuZXh0KHZvaWQpOwogICAgdm9pZCByZXNldCh2b2lkKTsKfTsKCmlubGluZQpOb3JtYWxpemVySXRlcmF0b3I6Ok5vcm1hbGl6ZXJJdGVyYXRvcigpIDoKICAgIGN1cnNvcigwKSwKICAgIGJ1ZmZlckFsaWFzKDApLAogICAgcmVvcmRlckJ1ZmZlcigwKSwKICAgIG93bkJ1ZmZlcigyKSwKICAgIHRleHQoMCksCiAgICB0ZXh0TGVuKDApLAogICAgY3VycmVudE9mZnNldCgwKSwKICAgIGV4cEluZGV4KDApCnsKfQoKaW5saW5lCk5vcm1hbGl6ZXJJdGVyYXRvcjo6Tm9ybWFsaXplckl0ZXJhdG9yKGNvbnN0IFVDaGFyKiBzb3VyY2UsIGludDMyX3QgbGVuZ3RoLCBOb3JtYWxpemVyOjpFTW9kZSBtb2RlKSA6CiAgICBjdXJzb3IoMCksCiAgICBidWZmZXJBbGlhcygwKSwKICAgIHJlb3JkZXJCdWZmZXIoMCksCiAgICBvd25CdWZmZXIoMiksCiAgICB0ZXh0KDApLAogICAgdGV4dExlbigwKSwKICAgIGN1cnJlbnRPZmZzZXQoMCksCiAgICBleHBJbmRleCgwKQp7CiAgICBpZiAobW9kZSA9PSBOb3JtYWxpemVyOjpOT19PUCkgewogICAgICAgIHRleHQgPSAoVUNoYXIqKXNvdXJjZTsKICAgICAgICB0ZXh0TGVuID0gbGVuZ3RoOwogICAgICAgIGN1cnJlbnRPZmZzZXQgPSAwOwogICAgfSBlbHNlIHsKICAgICAgICBjdXJzb3IgPSBuZXcgTm9ybWFsaXplcihzb3VyY2UsIGxlbmd0aCwgbW9kZSk7CgogICAgfQp9CgppbmxpbmUKTm9ybWFsaXplckl0ZXJhdG9yOjp+Tm9ybWFsaXplckl0ZXJhdG9yKCkgCnsKICAgIGlmIChjdXJzb3IgIT0gMCkgewogICAgICAgIGRlbGV0ZSBjdXJzb3I7CiAgICAgICAgY3Vyc29yID0gMDsKICAgIH0KICAgIGlmIChyZW9yZGVyQnVmZmVyICE9IDApIHsKICAgICAgICBkZWxldGUgcmVvcmRlckJ1ZmZlcjsKICAgIH0KfQoKaW5saW5lCnZvaWQKTm9ybWFsaXplckl0ZXJhdG9yOjpzZXRUZXh0KGNvbnN0IFVDaGFyKiBzb3VyY2UsIGludDMyX3QgbGVuZ3RoLCBVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIGlmIChjdXJzb3IgPT0gMCkgewogICAgICAgIHRleHQgPSAoVUNoYXIqKXNvdXJjZTsKICAgICAgICB0ZXh0TGVuID0gbGVuZ3RoOwogICAgICAgIGN1cnJlbnRPZmZzZXQgPSAwOwoKICAgIH0gZWxzZSB7CiAgICAgICAgdGV4dCA9IDA7CiAgICAgICAgY3Vyc29yLT5zZXRUZXh0KHNvdXJjZSwgbGVuZ3RoLCBzdGF0dXMpOwogICAgfQogICAgYnVmZmVyQWxpYXMgPSAwOwogICAgY3VycmVudE9mZnNldCA9IDA7Cn0KCi8qIFlvdSBjYW4gb25seSBzZXQgbW9kZSBhZnRlciB0aGUgY29tcGFyaXNpb24gb2YgdHdvIHN0cmluZ3MgaXMgY29tcGxldGVkLgogICBTZXR0aW5nIHRoZSBtb2RlIGluIHRoZSBtaWRkbGUgb2YgYSBjb21wYXJpc29uIGlzIG5vdCBhbGxvd2VkLgogICAqLwppbmxpbmUKdm9pZAoKTm9ybWFsaXplckl0ZXJhdG9yOjpzZXRNb2RlQW5kVGV4dChOb3JtYWxpemVyOjpFTW9kZSBtb2RlLCBjb25zdCBVQ2hhciogc291cmNlLCBpbnQzMl90IGxlbmd0aCwgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgICBpZihtb2RlICE9IE5vcm1hbGl6ZXI6Ok5PX09QKQogICAgewogICAgICAgIC8qIERPIGhhdmUgYSBtb2RlIC0gIHdpbGwgbmVlZCBhIG5vcm1hbGl6ZXIgb2JqZWN0ICovCiAgICAgICAgaWYoY3Vyc29yICE9IE5VTEwpCiAgICAgICAgewogICAgICAgICAgICAvKiBKdXN0IG1vZGlmeSB0aGUgZXhpc3RpbmcgY3Vyc29yICovCiAgICAgICAgICAgIGN1cnNvci0+c2V0TW9kZShtb2RlKTsKICAgICAgICAgICAgY3Vyc29yLT5zZXRUZXh0KHNvdXJjZSwgbGVuZ3RoLCBzdGF0dXMpOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBjdXJzb3IgPSBuZXcgTm9ybWFsaXplcihzb3VyY2UsIGxlbmd0aCwgbW9kZSk7CiAgICAgICAgfQoKICAgICAgICAvKiBSRVNFVCB0aGUgb2xkIGRhdGEgKi8KICAgICAgICB0ZXh0ID0gMDsKICAgICAgICB0ZXh0TGVuID0gMDsKICAgIH0KICAgIGVsc2UgCiAgICB7CiAgICAgICAgLyogTk9fT1AgbW9kZS4uICovCiAgICAgICAgaWYoY3Vyc29yICE9IE5VTEwpCiAgICAgICAgeyAvKiBnZXQgcmlkIG9mIHRoZSBvbGQgY3Vyc29yICovCiAgICAgICAgICAgIGRlbGV0ZSBjdXJzb3I7IAogICAgICAgICAgICBjdXJzb3IgPSAwOwogICAgICAgIH0KCiAgICAgICAgdGV4dCA9IChVQ2hhciopc291cmNlOwogICAgICAgIHRleHRMZW4gPSBsZW5ndGg7CiAgICB9CiAgICBjdXJyZW50T2Zmc2V0ID0gMDsgLyogYWx3YXlzICovCiAgIAogICAgYnVmZmVyQWxpYXMgPSAwOwp9CgppbmxpbmUKVUNoYXIKTm9ybWFsaXplckl0ZXJhdG9yOjpjdXJyZW50KHZvaWQpIGNvbnN0CnsKICAgIGlmICh0ZXh0ICE9IDApIHsKICAgICAgICBpZihjdXJyZW50T2Zmc2V0ID49IHRleHRMZW4pCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gTm9ybWFsaXplcjo6RE9ORTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIHRleHRbY3VycmVudE9mZnNldF07CiAgICAgICAgfQogICAgfQoKICAgIHJldHVybiAoVUNoYXIpY3Vyc29yLT5jdXJyZW50KCk7Cn0KCgppbmxpbmUKVUNoYXIKTm9ybWFsaXplckl0ZXJhdG9yOjpuZXh0KHZvaWQpCnsKICAgIGlmICh0ZXh0ICE9IDApIHsKICAgICAgICByZXR1cm4gKChjdXJyZW50T2Zmc2V0IDwgdGV4dExlbikgPyB0ZXh0WysrY3VycmVudE9mZnNldF0gOiBOb3JtYWxpemVyOjpET05FKTsKICAgIH0KICAgIHJldHVybiAoVUNoYXIpY3Vyc29yLT5uZXh0KCk7Cn0KCmlubGluZQp2b2lkCk5vcm1hbGl6ZXJJdGVyYXRvcjo6cmVzZXQodm9pZCkKewogICAgY3VycmVudE9mZnNldCA9IDA7CiAgICBpZihjdXJzb3IpCiAgICB7CiAgICAgICAgY3Vyc29yLT5yZXNldCgpOwogICAgfQp9CgovLz09PT09PT09PT09PT09PT0gU29tZSBpbmxpbmUgZGVmaW5pdGlvbnMgb2YgaW1wbGVtZW50YXRpb24gZnVuY3Rpb25zLi4uLi4uLi4gPT09PT09PT0KLyoqCiAqIEEgY2xvbmUgb2YgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjptYWtlUmVvcmRlcmVkQnVmZmVyLCB0cmltbWVkIGRvd24KICogdG8gb25seSBoYW5kbGUgZm9yd2FyZC4KICovCmlubGluZSBWZWN0b3JPZkludCoKUnVsZUJhc2VkQ29sbGF0b3I6Om1ha2VSZW9yZGVyZWRCdWZmZXIoTm9ybWFsaXplckl0ZXJhdG9yKiBjdXJzb3IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVDaGFyIGNvbEZpcnN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQzMl90IGxhc3RWYWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVmVjdG9yT2ZJbnQqIGxhc3RFeHBhbnNpb24pIGNvbnN0IHsKICAgIFZlY3Rvck9mSW50KiByZXN1bHQ7CgogICAgaW50MzJfdCBmaXJzdFZhbHVlID0gdWNtcDMyX2dldChkYXRhLT5tYXBwaW5nLCBjb2xGaXJzdCk7CiAgICBpZiAoZmlyc3RWYWx1ZSA+PSBDT05UUkFDVENIQVJJTkRFWCkgewogICAgICAgIFVFcnJvckNvZGUgc3RhdHVzID0gVV9aRVJPX0VSUk9SOwogICAgICAgIGZpcnN0VmFsdWUgPSBuZXh0Q29udHJhY3RDaGFyKGN1cnNvciwgY29sRmlyc3QsIHN0YXR1cyk7CiAgICB9CgogICAgVmVjdG9yT2ZJbnQqIGZpcnN0RXhwYW5zaW9uID0gTlVMTDsKICAgIGlmIChmaXJzdFZhbHVlID49IEVYUEFORENIQVJJTkRFWCkgewogICAgICAgIGZpcnN0RXhwYW5zaW9uID0gZ2V0RXhwYW5kVmFsdWVMaXN0KGZpcnN0VmFsdWUpOwogICAgfQoKICAgIGlmIChmaXJzdEV4cGFuc2lvbiA9PSBOVUxMICYmIGxhc3RFeHBhbnNpb24gPT0gTlVMTCkgewogICAgICAgIGN1cnNvci0+b3duQnVmZmVyLmF0KDApID0gZmlyc3RWYWx1ZTsKICAgICAgICBjdXJzb3ItPm93bkJ1ZmZlci5hdCgxKSA9IGxhc3RWYWx1ZTsKICAgICAgICByZXN1bHQgPSAmY3Vyc29yLT5vd25CdWZmZXI7CiAgICB9CiAgICBlbHNlIHsKICAgICAgICBpbnQzMl90IGZpcnN0TGVuZ3RoID0gZmlyc3RFeHBhbnNpb249PU5VTEw/IDEgOiBmaXJzdEV4cGFuc2lvbi0+c2l6ZSgpOwogICAgICAgIGludDMyX3QgbGFzdExlbmd0aCA9IGxhc3RFeHBhbnNpb249PU5VTEw/IDEgOiBsYXN0RXhwYW5zaW9uLT5zaXplKCk7CiAgICAgICAgaWYgKGN1cnNvci0+cmVvcmRlckJ1ZmZlciA9PSBOVUxMKSB7CiAgICAgICAgICAgIGN1cnNvci0+cmVvcmRlckJ1ZmZlciA9IG5ldyBWZWN0b3JPZkludChmaXJzdExlbmd0aCtsYXN0TGVuZ3RoKTsKICAgICAgICB9CiAgICAgICAgLy8gcmVvcmRlcmRCdWZmZXIgZ2V0cyByZXVzZWQgZm9yIHRoZSBsaWZlIG9mIHRoaXMgb2JqZWN0LgogICAgICAgIC8vIFNpbmNlIGl0cyBpbnRlcm5hbCBidWZmZXIgb25seSBncm93cywgdGhlcmUgaXMgYSBkYW5nZXIKICAgICAgICAvLyB0aGF0IGl0IHdpbGwgZ2V0IHJlYWxseSwgcmVhbGx5IGJpZywgYW5kIG5ldmVyIHNocmluay4gIElmCiAgICAgICAgLy8gdGhpcyBpcyBhY3R1YWxseSBoYXBwZW5pbmcsIGluc2VydCBjb2RlIGhlcmUgdG8gY2hlY2sgZm9yCiAgICAgICAgLy8gdGhlIGNvbmRpdGlvbi4gIFNvbWV0aGluZyBhbG9uZyB0aGUgbGluZXMgb2Y6CiAgICAgICAgLy8hIGVsc2UgaWYgKHJlb3JkZXJCdWZmZXItPnNpemUoKSA+PSAyNTYgJiYKICAgICAgICAvLyEgICAgICAgICAgKGZpcnN0TGVuZ3RoK2xhc3RMZW5ndGgpIDwgMTYpIHsKICAgICAgICAvLyEgICAgIGRlbGV0ZSByZW9yZGVyQnVmZmVyOwogICAgICAgIC8vISAgICAgcmVvcmRlckJ1ZmZlciA9IG5ldyBWZWN0b3JPZkludChmaXJzdExlbmd0aCtsYXN0TGVuZ3RoKTsKICAgICAgICAvLyEgfQogICAgICAgIC8vIFRoZSBzcGVjaWZpYyBudW1lcmljIHZhbHVlcyBuZWVkIHRvIGJlIGRldGVybWluZWQKICAgICAgICAvLyBlbXBpcmljYWxseS4gW2FsaXVdCiAgICAgICAgcmVzdWx0ID0gY3Vyc29yLT5yZW9yZGVyQnVmZmVyOwoKICAgICAgICBpZiAoZmlyc3RFeHBhbnNpb24gPT0gTlVMTCkgewogICAgICAgICAgICByZXN1bHQtPmF0UHV0KDAsIGZpcnN0VmFsdWUpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgLy8gU3lzdGVtLmFycmF5Y29weShmaXJzdEV4cGFuc2lvbiwgMCwgcmVzdWx0LCAwLCBmaXJzdExlbmd0aCk7CiAgICAgICAgICAgICpyZXN1bHQgPSAqZmlyc3RFeHBhbnNpb247CiAgICAgICAgfQoKICAgICAgICBpZiAobGFzdEV4cGFuc2lvbiA9PSBOVUxMKSB7CiAgICAgICAgICAgIHJlc3VsdC0+YXRQdXQoZmlyc3RMZW5ndGgsIGxhc3RWYWx1ZSk7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAvLyBTeXN0ZW0uYXJyYXljb3B5KGxhc3RFeHBhbnNpb24sIDAsIHJlc3VsdCwgZmlyc3RMZW5ndGgsIGxhc3RMZW5ndGgpOwogICAgICAgICAgICBmb3IgKGludDMyX3QgaT0wOyBpPGxhc3RMZW5ndGg7ICsraSkgewogICAgICAgICAgICAgICAgcmVzdWx0LT5hdFB1dChmaXJzdExlbmd0aCArIGksIGxhc3RFeHBhbnNpb24tPmF0KGkpKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXN1bHQtPnNldFNpemUoZmlyc3RMZW5ndGgrbGFzdExlbmd0aCk7CiAgICB9CgogICAgcmV0dXJuIHJlc3VsdDsKfQoKCgoKCmlubGluZSBpbnQzMl90ClJ1bGVCYXNlZENvbGxhdG9yOjpzdHJlbmd0aE9yZGVyKGludDMyX3QgdmFsdWUpIGNvbnN0CnsKICAgIGlmIChnZXRTdHJlbmd0aCgpID09IFBSSU1BUlkpCiAgICB7CiAgICAgICAgcmV0dXJuICh2YWx1ZSAmIFBSSU1BUllESUZGRVJFTkNFT05MWSk7CiAgICB9IGVsc2UgaWYgKGdldFN0cmVuZ3RoKCkgPT0gU0VDT05EQVJZKQogICAgewogICAgICAgIHJldHVybiAodmFsdWUgJiBTRUNPTkRBUllESUZGRVJFTkNFT05MWSk7CiAgICB9CiAgICByZXR1cm4gdmFsdWU7Cn0KCgppbmxpbmUgaW50MzJfdApSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0U3RyZW5ndGhPcmRlcihOb3JtYWxpemVySXRlcmF0b3IqIGN1cnNvciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUgc3RhdHVzKSBjb25zdAp7CiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6TlVMTE9SREVSOwogICAgfQoKICAgIGlmIChjdXJzb3ItPmJ1ZmZlckFsaWFzICE9IE5VTEwpCiAgICB7CiAgICAgICAgLy8gYnVmZmVyQWxpYXMgbmVlZHMgYSBiaXQgb2YgYW4gZXhwbGFuYXRpb24uCiAgICAgICAgLy8gV2hlbiB3ZSBoaXQgYW4gZXhwYW5kaW5nIGNoYXJhY3RlciBpbiB0aGUgdGV4dCwgd2UgY2FsbCB0aGUgb3JkZXIncwogICAgICAgIC8vIGdldEV4cGFuZFZhbHVlcyBtZXRob2QgdG8gcmV0cmlldmUgYW4gYXJyYXkgb2YgdGhlIG9yZGVyaW5ncyBmb3IgYWxsCiAgICAgICAgLy8gb2YgdGhlIGNoYXJhY3RlcnMgaW4gdGhlIGV4cGFuc2lvbiAoc2VlIHRoZSBlbmQgb2YgdGhpcyBtZXRob2QpLgogICAgICAgIC8vIFRoZSBmaXJzdCBvcmRlcmluZyBpcyByZXR1cm5lZCwgYW5kIGFuIGFsaWFzIHRvIHRoZSBvcmRlcmluZ3MgYXJyYXkKICAgICAgICAvLyBpcyBzYXZlZCBzbyB0aGF0IHRoZSByZW1haW5pbmcgb3JkZXJpbmdzIGNhbiBiZSByZXR1cm5lZCBvbiBzdWJzZXF1ZW50CiAgICAgICAgLy8gY2FsbHMgdG8gbmV4dC4gIFNvLCBpZiB0aGUgZXhwYW5kaW5nIGJ1ZmZlciBpcyBub3QgZXhoYXVzdGVkLCAKICAgICAgICAvLyBhbGwgd2UgaGF2ZSB0byBkbyBoZXJlIGlzIHJldHVybiB0aGUgbmV4dCBvcmRlcmluZyBpbiB0aGUgYnVmZmVyLiAgCiAgICAgICAgaWYgKGN1cnNvci0+ZXhwSW5kZXggPCBjdXJzb3ItPmJ1ZmZlckFsaWFzLT5zaXplKCkpCiAgICAgICAgewogICAgICAgICAgICAvL19MKChzdGRlcnIsICJuZXh0IGZyb20gWyUwOFhdIGZyb20gYnVmZmVyQWxpYXNcbiIsIHRoaXMpKTsKICAgICAgICAgICAgcmV0dXJuIHN0cmVuZ3RoT3JkZXIoY3Vyc29yLT5idWZmZXJBbGlhcy0+YXQoY3Vyc29yLT5leHBJbmRleCsrKSk7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIGN1cnNvci0+YnVmZmVyQWxpYXMgPSBOVUxMOwogICAgICAgIH0KICAgIH0KCiAgICBVQ2hhciBjaCA9IGN1cnNvci0+Y3VycmVudCgpOwogICAgY3Vyc29yLT5uZXh0KCk7CgogICAgLy9fTCgoc3RkZXJyLCAiTmV4dCBmcm9tIFslMDhYXSA9IFslMDRYXSwgWyVjXVxuIiwgY3Vyc29yLCAoaW50KWNoICYgMHhGRkZGLCAoY2hhcikoY2ggJiAweEZGKSkpOwogICAgCiAgICBpZiAoY2ggPT0gTm9ybWFsaXplcjo6RE9ORSkgewogICAgICAgIHJldHVybiBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUjsKICAgIH0KICAgIC8vIEFzayB0aGUgY29sbGF0b3IgZm9yIHRoaXMgY2hhcmFjdGVyJ3Mgb3JkZXJpbmcuCiAgICBpbnQzMl90IHZhbHVlID0gdWNtcDMyX2dldChkYXRhLT5tYXBwaW5nLCBjaCk7CgogICAgaWYgKHZhbHVlID09IFVOTUFQUEVEKQogICAgewogICAgICAgIC8vIFJldHVybmVkIGFuICJ1bm1hcHBlZCIgZmxhZyBhbmQgc2F2ZSB0aGUgY2hhcmFjdGVyIHNvIGl0IGNhbiBiZSAKICAgICAgICAvLyByZXR1cm5lZCBuZXh0IHRpbWUgdGhpcyBtZXRob2QgaXMgY2FsbGVkLgogICAgICAgIGlmIChjaCA9PSAweDAwMDApIHJldHVybiBjaDsgLy8gXHUwMDAwIGlzIG5vdCB2YWxpZCBpbiBDKysncyBVbmljb2RlU3RyaW5nCiAgICAgICAgY3Vyc29yLT5vd25CdWZmZXIuYXQoMCkgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OlVOTUFQUEVEQ0hBUlZBTFVFOwogICAgICAgIGN1cnNvci0+b3duQnVmZmVyLmF0KDEpID0gY2ggPDwgMTY7CiAgICAgICAgY3Vyc29yLT5idWZmZXJBbGlhcyA9ICZjdXJzb3ItPm93bkJ1ZmZlcjsKCiAgICB9IGVsc2UgewogICAgICAgIAogICAgICAgIGlmICh2YWx1ZSA+PSBDT05UUkFDVENIQVJJTkRFWCkKICAgICAgICB7CiAgICAgICAgICAgIHZhbHVlID0gbmV4dENvbnRyYWN0Q2hhcihjdXJzb3IsIGNoLCBzdGF0dXMpOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBpZiAodmFsdWUgPj0gRVhQQU5EQ0hBUklOREVYKSB7CiAgICAgICAgICAgIGN1cnNvci0+YnVmZmVyQWxpYXMgPSBnZXRFeHBhbmRWYWx1ZUxpc3QodmFsdWUpOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBpZiAoQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjppc1RoYWlQcmVWb3dlbChjaCkpIHsKICAgICAgICAgICAgVUNoYXIgY29uc29uYW50ID0gY3Vyc29yLT5jdXJyZW50KCk7CiAgICAgICAgICAgIGlmIChDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OmlzVGhhaUJhc2VDb25zb25hbnQoY29uc29uYW50KSkgewogICAgICAgICAgICAgICAgY3Vyc29yLT5uZXh0KCk7CiAgICAgICAgICAgICAgICBjdXJzb3ItPmJ1ZmZlckFsaWFzID0gbWFrZVJlb3JkZXJlZEJ1ZmZlcihjdXJzb3IsIGNvbnNvbmFudCwgdmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJzb3ItPmJ1ZmZlckFsaWFzKTsgICAgICAgICAgICAgICAgCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgaWYgKGN1cnNvci0+YnVmZmVyQWxpYXMgIT0gTlVMTCkgewogICAgICAgIGN1cnNvci0+ZXhwSW5kZXggPSAxOwogICAgICAgIHZhbHVlID0gY3Vyc29yLT5idWZmZXJBbGlhcy0+YXQoMCk7CiAgICB9CgogICAgcmV0dXJuIHN0cmVuZ3RoT3JkZXIodmFsdWUpOwp9CgovLyA9PT09PT09PT09PT09PT09PT09PSBFbmQgaW5saW5lcyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKCi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKUnVsZUJhc2VkQ29sbGF0b3I6OlJ1bGVCYXNlZENvbGxhdG9yKCkKICAgIDogQ29sbGF0b3IoKSwKICAgICAgaXNPdmVySWdub3JlKEZBTFNFKSwKICAgICAgbVBhdHRlcm4oMCksCiAgICAgIC8vICAgICAgc291cmNlQ3Vyc29yKDApLAogICAgICAvL3RhcmdldEN1cnNvcigwKSwKICAgICAgY3Vyc29yMSgwKSwKICAgICAgY3Vyc29yMigwKSwKICAgICAgZGF0YSgwKSwKICAgICAgZGF0YUlzT3duZWQoRkFMU0UpCnsKfQoKUnVsZUJhc2VkQ29sbGF0b3I6OlJ1bGVCYXNlZENvbGxhdG9yKGNvbnN0ICBSdWxlQmFzZWRDb2xsYXRvciYgIHRoYXQpCiAgICA6IENvbGxhdG9yKHRoYXQpLAogICAgICBpc092ZXJJZ25vcmUodGhhdC5pc092ZXJJZ25vcmUpLAogICAgICBtUGF0dGVybigwKSwKICAgICAgLy8gICAgICBzb3VyY2VDdXJzb3IoMCksCiAgICAgIC8vdGFyZ2V0Q3Vyc29yKDApLAogICAgICBjdXJzb3IxKDApLAogICAgICBjdXJzb3IyKDApLAogICAgICBkYXRhSXNPd25lZChGQUxTRSksCiAgICAgIGRhdGEodGhhdC5kYXRhKSAvLyBBbGlhcyB0aGUgZGF0YSBwb2ludGVyCnsKfQoKVUJvb2wKUnVsZUJhc2VkQ29sbGF0b3I6Om9wZXJhdG9yPT0oY29uc3QgQ29sbGF0b3ImIHRoYXQpIGNvbnN0CnsKICAgIGlmICh0aGlzID09ICZ0aGF0KQogICAgewogICAgICAgIHJldHVybiBUUlVFOwogICAgfQoKICAgIGlmICh0aGlzLT5nZXREeW5hbWljQ2xhc3NJRCgpICE9IHRoYXQuZ2V0RHluYW1pY0NsYXNzSUQoKSkKICAgIHsKICAgICAgICByZXR1cm4gRkFMU0U7ICAvLyBub3QgdGhlIHNhbWUgY2xhc3MKICAgIH0KCiAgICBpZiAoIUNvbGxhdG9yOjpvcGVyYXRvcj09KHRoYXQpKQogICAgewogICAgICAgIHJldHVybiBGQUxTRTsKICAgIH0KCiAgICBSdWxlQmFzZWRDb2xsYXRvciYgdGhhdEFsaWFzID0gKFJ1bGVCYXNlZENvbGxhdG9yJil0aGF0OwoKICAgIGlmIChpc092ZXJJZ25vcmUgIT0gdGhhdEFsaWFzLmlzT3Zlcklnbm9yZSkKICAgIHsKICAgICAgICByZXR1cm4gRkFMU0U7CiAgICB9CgogICAgaWYgKGRhdGEgIT0gdGhhdEFsaWFzLmRhdGEpCiAgICB7CiAgICAgICAgcmV0dXJuIEZBTFNFOwogICAgfQoKICAgIHJldHVybiBUUlVFOwp9CgpSdWxlQmFzZWRDb2xsYXRvciYKUnVsZUJhc2VkQ29sbGF0b3I6Om9wZXJhdG9yPShjb25zdCAgUnVsZUJhc2VkQ29sbGF0b3ImIHRoYXQpCnsKICAgIGlmICh0aGlzICE9ICZ0aGF0KQogICAgewogICAgICAgIENvbGxhdG9yOjpvcGVyYXRvcj0odGhhdCk7CiAgICAgICAgaXNPdmVySWdub3JlID0gdGhhdC5pc092ZXJJZ25vcmU7CgogICAgICAgIGlmIChkYXRhSXNPd25lZCkKICAgICAgICB7CiAgICAgICAgICAgIGRlbGV0ZSBkYXRhOwogICAgICAgIH0KCiAgICAgICAgZGF0YSA9IDA7CiAgICAgICAgZGVsZXRlIG1QYXR0ZXJuOwogICAgICAgIG1QYXR0ZXJuID0gMDsKICAgICAgICBkYXRhSXNPd25lZCA9IEZBTFNFOwogICAgICAgIGRhdGEgPSB0aGF0LmRhdGE7CiAgICB9CgogICAgcmV0dXJuICp0aGlzOwp9CgpSdWxlQmFzZWRDb2xsYXRvcjo6UnVsZUJhc2VkQ29sbGF0b3IoY29uc3QgIFVuaWNvZGVTdHJpbmcmICBydWxlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmICAgICAgc3RhdHVzKQogICAgOiBDb2xsYXRvcigpLAogICAgICBpc092ZXJJZ25vcmUoRkFMU0UpLAogICAgICBtUGF0dGVybigwKSwKICAgICAgLy8gICAgICBzb3VyY2VDdXJzb3IoMCksCiAgICAgIC8vLyAgICAgIHRhcmdldEN1cnNvcigwKSwKICAgICAgY3Vyc29yMSgwKSwKICAgICAgY3Vyc29yMigwKSwKICAgICAgZGF0YSgwKSwKICAgICAgZGF0YUlzT3duZWQoRkFMU0UpCnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgY29uc3RydWN0RnJvbVJ1bGVzKHJ1bGVzLCBzdGF0dXMpOwp9CgpSdWxlQmFzZWRDb2xsYXRvcjo6UnVsZUJhc2VkQ29sbGF0b3IoY29uc3QgIFVuaWNvZGVTdHJpbmcmICBydWxlcywKICAgICAgICAgICAgICAgICAgICAgRUNvbGxhdGlvblN0cmVuZ3RoIGNvbGxhdGlvblN0cmVuZ3RoLAogICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiAgICAgIHN0YXR1cykKICA6IENvbGxhdG9yKGNvbGxhdGlvblN0cmVuZ3RoLCBOb3JtYWxpemVyOjpOT19PUCksCiAgICBpc092ZXJJZ25vcmUoRkFMU0UpLAogICAgbVBhdHRlcm4oMCksCiAgICAvLyAgICBzb3VyY2VDdXJzb3IoMCksCiAgICAvLyAgICB0YXJnZXRDdXJzb3IoMCksCiAgICAgIGN1cnNvcjEoMCksCiAgICAgIGN1cnNvcjIoMCksCiAgICBkYXRhKDApLAogICAgZGF0YUlzT3duZWQoRkFMU0UpCnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdHJ1Y3RGcm9tUnVsZXMocnVsZXMsIHN0YXR1cyk7Cn0KClJ1bGVCYXNlZENvbGxhdG9yOjpSdWxlQmFzZWRDb2xsYXRvcihjb25zdCAgVW5pY29kZVN0cmluZyYgIHJ1bGVzLAogICAgICAgICAgICAgICAgICAgICBOb3JtYWxpemVyOjpFTW9kZSBkZWNvbXBvc2l0aW9uTW9kZSwKICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgICAgICBzdGF0dXMpCiAgOiBDb2xsYXRvcihURVJUSUFSWSwgZGVjb21wb3NpdGlvbk1vZGUpLAogICAgaXNPdmVySWdub3JlKEZBTFNFKSwKICAgIG1QYXR0ZXJuKDApLAogICAgLy8gICAgc291cmNlQ3Vyc29yKDApLAogICAgLy8gICAgdGFyZ2V0Q3Vyc29yKDApLAogICAgICBjdXJzb3IxKDApLAogICAgICBjdXJzb3IyKDApLAogICAgZGF0YSgwKSwKICAgIGRhdGFJc093bmVkKEZBTFNFKQp7CiAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgewogICAgICByZXR1cm47CiAgICB9CiAgCiAgY29uc3RydWN0RnJvbVJ1bGVzKHJ1bGVzLCBzdGF0dXMpOwp9CgpSdWxlQmFzZWRDb2xsYXRvcjo6UnVsZUJhc2VkQ29sbGF0b3IoY29uc3QgIFVuaWNvZGVTdHJpbmcmICBydWxlcywKICAgICAgICAgICAgICAgICAgICAgRUNvbGxhdGlvblN0cmVuZ3RoIGNvbGxhdGlvblN0cmVuZ3RoLAogICAgICAgICAgICAgICAgICAgICBOb3JtYWxpemVyOjpFTW9kZSBkZWNvbXBvc2l0aW9uTW9kZSwKICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgICAgICBzdGF0dXMpCiAgOiBDb2xsYXRvcihjb2xsYXRpb25TdHJlbmd0aCwgZGVjb21wb3NpdGlvbk1vZGUpLAogICAgICBpc092ZXJJZ25vcmUoRkFMU0UpLAogICAgICBtUGF0dGVybigwKSwKICAgIC8vICAgICAgc291cmNlQ3Vyc29yKDApLAogICAgLy90YXJnZXRDdXJzb3IoMCksCiAgICAgIGN1cnNvcjEoMCksCiAgICAgIGN1cnNvcjIoMCksCiAgICAgIGRhdGEoMCksCiAgICAgIGRhdGFJc093bmVkKEZBTFNFKQp7CiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGNvbnN0cnVjdEZyb21SdWxlcyhydWxlcywgc3RhdHVzKTsKfQoKdm9pZCBSdWxlQmFzZWRDb2xsYXRvcjo6Y29uc3RydWN0RnJvbVJ1bGVzKGNvbnN0IFVuaWNvZGVTdHJpbmcmIHJ1bGVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKQp7CiAgICAvLyBDb25zdHJ1Y3QgdGhpcyBjb2xsYXRvcidzIHJ1bGVzZXQgZnJvbSBpdHMgc3RyaW5nIHJlcHJlc2VudGF0aW9uCiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmIChydWxlcy5pc0JvZ3VzKCkpCiAgICB7CiAgICAgICAgc3RhdHVzID0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUjsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKGRhdGFJc093bmVkKQogICAgewogICAgICAgIGRlbGV0ZSBkYXRhOwogICAgICAgIGRhdGEgPSAwOwogICAgfQoKICAgIGlzT3Zlcklnbm9yZSA9IEZBTFNFOwogICAgc2V0U3RyZW5ndGgoQ29sbGF0b3I6OlRFUlRJQVJZKTsKCiAgICBkYXRhID0gbmV3IFRhYmxlQ29sbGF0aW9uRGF0YTsKICAgIGlmIChkYXRhLT5pc0JvZ3VzKCkpCiAgICB7CiAgICAgICAgc3RhdHVzID0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUjsKICAgICAgICBkZWxldGUgZGF0YTsKICAgICAgICBkYXRhID0gMDsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgLy8gV2UgY29uc3RydWN0ZWQgdGhlIGRhdGEgdXNpbmcgdGhlIGJ1aWxkIG1ldGhvZCwgc28gd2Ugb3duIGl0LgogICAgZGF0YUlzT3duZWQgPSBUUlVFOwoKICAgIC8vIE5vdyB0aGF0IHdlJ3ZlIGdvdCBhbGwgdGhlIGJ1ZmZlcnMgYWxsb2NhdGVkLCBkbyB0aGUgYWN0dWFsIHdvcmsKICAgIG1QYXR0ZXJuID0gMDsKICAgIGJ1aWxkKHJ1bGVzLCBzdGF0dXMpOwp9Cgp2b2lkClJ1bGVCYXNlZENvbGxhdG9yOjpjb25zdHJ1Y3RGcm9tRmlsZShjb25zdCBjaGFyKiBmaWxlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN0YXR1cykKewogICAgLy8gVGhpcyBtZXRob2QgdHJpZXMgdG8gcmVhZCBpbiBhIGZsYXR0ZW5lZCBSdWxlQmFzZWRDb2xsYXRvciB0aGF0CiAgICAvLyBoYXMgYmVlbiBwcmV2aW91c2x5IHN0cmVhbWVkIG91dCB1c2luZyB0aGUgc3RyZWFtT3V0KCkgbWV0aG9kLgogICAgLy8gVGhlICdmaWxlTmFtZScgcGFyYW1ldGVyIHNob3VsZCBjb250YWluIGEgZnVsbCBwYXRobmFtZSB2YWxpZCBvbgogICAgLy8gdGhlIGxvY2FsIGVudmlyb25tZW50LgoKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKGRhdGFJc093bmVkKQogICAgewogICAgICAgIGRlbGV0ZSBkYXRhOwogICAgICAgIGRhdGEgPSAwOwogICAgfQoKICAgIG1QYXR0ZXJuID0gMDsKICAgIGlzT3Zlcklnbm9yZSA9IEZBTFNFOwogICAgc2V0U3RyZW5ndGgoQ29sbGF0b3I6OlRFUlRJQVJZKTsgLy8gVGhpcyBpcyB0aGUgZGVmYXVsdCBzdHJlbmd0aAoKICAgIEZpbGVTdHJlYW0qIGlmcyA9IFRfRmlsZVN0cmVhbV9vcGVuKGZpbGVOYW1lLCAicmIiKTsKICAgIGlmIChpZnMgPT0gMCkgewogICAgICAgIHN0YXR1cyA9IFVfRklMRV9BQ0NFU1NfRVJST1I7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIC8vIFRoZSBzdHJlYW1JbiBmdW5jdGlvbiBkb2VzIHRoZSBhY3R1YWwgd29yayBoZXJlLi4uCiAgICBSdWxlQmFzZWRDb2xsYXRvclN0cmVhbWVyOjpzdHJlYW1Jbih0aGlzLCBpZnMpOwoKICAgIGlmICghVF9GaWxlU3RyZWFtX2Vycm9yKGlmcykpCiAgICB7CiAgICAgICAgc3RhdHVzID0gVV9aRVJPX0VSUk9SOwogICAgfQogICAgZWxzZSBpZiAoZGF0YSAmJiBkYXRhLT5pc0JvZ3VzKCkpCiAgICB7CiAgICAgICAgc3RhdHVzID0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUjsKICAgICAgICBkZWxldGUgZGF0YTsKICAgICAgICBkYXRhID0gMDsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBzdGF0dXMgPSBVX01JU1NJTkdfUkVTT1VSQ0VfRVJST1I7CiAgICAgICAgZGVsZXRlIGRhdGE7CiAgICAgICAgZGF0YSA9IDA7CiAgICB9CgojaWZkZWYgQ09MTERFQlVHCiAgICBmcHJpbnRmKHN0ZGVyciwgImJpbmFyeSByZWFkICVzIHNpemUgJWQsICVzXG4iLCBmaWxlTmFtZSwgVF9GaWxlU3RyZWFtX3NpemUoaWZzKSwgdV9lcnJvck5hbWUoc3RhdHVzKSk7CiNlbmRpZgoKICAgIC8vIFdlIGNvbnN0cnVjdGVkIHRoZSBkYXRhIHdoZW4gc3RyZWFtaW5nIGl0IGluLCBzbyB3ZSBvd24gaXQKICAgIGRhdGFJc093bmVkID0gVFJVRTsKCiAgICBUX0ZpbGVTdHJlYW1fY2xvc2UoaWZzKTsKfQoKY29uc3QgY2hhciAqClJ1bGVCYXNlZENvbGxhdG9yOjpjb25zdHJ1Y3RGcm9tQnVuZGxlKGNvbnN0IExvY2FsZSAmIG5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAvLyBUaGlzIG1ldGhvZCB0cmllcyB0byBsb2NhdGUgYmluYXJ5IGNvbGxhdGlvbiBkYXRhIHdoaWNoIGhhcyBiZWVuIAogIC8vIHByZXZpb3VzbHkgc3RyZWFtZWQgdG8gYSBiaW5hcnkgb2JqZWN0ICIlJUNvbGxhdGlvbiIgaW4gYSAKICAvLyByZXNvdXJjZSBidW5kbGUuIElmIHRoZSBkYXRhIGlzIGZvdW5kLCBpdCBpcyBjYWNoZWQuCiAgLy8gY2FjaGUgaXMgY2hlY2tlZCBiZWZvcmUgYWN0dWFsbHkgc3RyZWFtaW5nIGluIGRhdGEKICAvLyByZXNvdXJjZSBidW5kbGUgZmFsbGJhY2sgbWVjaGFuaXNtIGlzIHVzZWQuCgogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgewogICAgICAgIHJldHVybiAwOwogICAgfQoKICAgIGlmIChkYXRhSXNPd25lZCkKICAgIHsKICAgICAgICBkZWxldGUgZGF0YTsKICAgICAgICBkYXRhID0gMDsKICAgIH0KICAgIGNvbnN0IGNoYXIqIHJlYWxOYW1lID0gMDsKCiAgICBtUGF0dGVybiA9IDA7CiAgICBpc092ZXJJZ25vcmUgPSBGQUxTRTsKICAgIHNldFN0cmVuZ3RoKENvbGxhdG9yOjpURVJUSUFSWSk7IC8vIFRoaXMgaXMgdGhlIGRlZmF1bHQgc3RyZW5ndGgKCiAgICBSZXNvdXJjZUJ1bmRsZSByYigwLCBuYW1lLCBzdGF0dXMpOwogICAgaWYoVV9TVUNDRVNTKHN0YXR1cykpIHsKICAgICAgUmVzb3VyY2VCdW5kbGUgYmluYXJ5ID0gcmIuZ2V0KCIlJUNvbGxhdGlvbiIsIHN0YXR1cyk7IC8vVGhpcyBpcyB0aGUgYnVuZGxlIHRoYXQgYWN0dWFsbHkgY29udGFpbnMgdGhlIGNvbGxhdGlvbiBkYXRhCiAgICAgIHJlYWxOYW1lID0gYmluYXJ5LmdldE5hbWUoKTsKICAgICAgaWYoVV9TVUNDRVNTKHN0YXR1cykpIHsKCVVFcnJvckNvZGUgaW50U3RhdHVzID0gVV9aRVJPX0VSUk9SOwoJY29uc3RydWN0RnJvbUNhY2hlKHJlYWxOYW1lLCBpbnRTdGF0dXMpOyAvLyBjaGVjayB3aGV0aGVyIHdlIGFscmVhZHkgaGF2ZSB0aGlzIGRhdGEgaW4gY2FjaGUKCWlmKFVfU1VDQ0VTUyhpbnRTdGF0dXMpKSB7CgkgIHJldHVybiByZWFsTmFtZTsKCX0KCWludDMyX3QgaW5EYXRhTGVuID0gMDsKCWNvbnN0IHVpbnQ4X3QgKmluRGF0YSA9IGJpbmFyeS5nZXRCaW5hcnkoaW5EYXRhTGVuLCBzdGF0dXMpOyAvL1RoaXMgZ290IHVzIHRoZSByZWFsIGJpbmFyeSBkYXRhCgkKCVVNZW1vcnlTdHJlYW0gKmlmcyA9IHVwcnZfbXN0cm1fb3BlbkJ1ZmZlcihpbkRhdGEsIGluRGF0YUxlbik7CgkKCWlmIChpZnMgPT0gMCkgewoJICBzdGF0dXMgPSBVX0ZJTEVfQUNDRVNTX0VSUk9SOwoJICByZXR1cm4gMDsKCX0KCgkvLyBUaGUgc3RyZWFtSW4gZnVuY3Rpb24gZG9lcyB0aGUgYWN0dWFsIHdvcmsgaGVyZS4uLgoJUnVsZUJhc2VkQ29sbGF0b3JTdHJlYW1lcjo6c3RyZWFtSW4odGhpcywgaWZzKTsKCglpZiAoIXVwcnZfbXN0cm1fZXJyb3IoaWZzKSkgewoJfQoJZWxzZSBpZiAoZGF0YSAmJiBkYXRhLT5pc0JvZ3VzKCkpIHsKCSAgc3RhdHVzID0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUjsKCSAgZGVsZXRlIGRhdGE7CgkgIGRhdGEgPSAwOwoJfSBlbHNlIHsKCSAgc3RhdHVzID0gVV9NSVNTSU5HX1JFU09VUkNFX0VSUk9SOwoJICBkZWxldGUgZGF0YTsKCSAgZGF0YSA9IDA7Cgl9CgoJLy8gV2UgY29uc3RydWN0ZWQgdGhlIGRhdGEgd2hlbiBzdHJlYW1pbmcgaXQgaW4sIHNvIHdlIG93biBpdAoJZGF0YUlzT3duZWQgPSBUUlVFOwoKCXVwcnZfbXN0cm1fY2xvc2UoaWZzKTsKCWFkZFRvQ2FjaGUocmVhbE5hbWUpOyAvLyBhZGQgdGhlIG5ld2x5IGNvbnN0cnVjdGVkIGRhdGEgdG8gY2FjaGUKCXJldHVybiByZWFsTmFtZTsKICAgICAgfSBlbHNlIHsKCXN0YXR1cyA9IFVfTUlTU0lOR19SRVNPVVJDRV9FUlJPUjsKCXJldHVybiAwOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAwOwogICAgfQp9CgpSdWxlQmFzZWRDb2xsYXRvcjo6UnVsZUJhc2VkQ29sbGF0b3IoICAgY29uc3QgTG9jYWxlJiBkZXNpcmVkTG9jYWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN0YXR1cykKICAgIDogQ29sbGF0b3IoKSwKICAgICAgaXNPdmVySWdub3JlKEZBTFNFKSwKICAgICAgZGF0YUlzT3duZWQoRkFMU0UpLAogICAgICBkYXRhKDApLAogICAgICAvLyAgICAgIHNvdXJjZUN1cnNvcigwKSwKICAgICAgLy90YXJnZXRDdXJzb3IoMCksCiAgICAgIGN1cnNvcjEoMCksCiAgICAgIGN1cnNvcjIoMCksCiAgICAgIG1QYXR0ZXJuKDApCnsKCgogIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkgewogICAgcmV0dXJuOwogIH0KICAKICAvLyBUcnkgdG8gbG9hZCwgaW4gb3JkZXI6CiAgLy8gMS4gVGhlIGRlc2lyZWQgbG9jYWxlJ3MgY29sbGF0aW9uLgogIC8vIDIuIEEgZmFsbGJhY2sgb2YgdGhlIGRlc2lyZWQgbG9jYWxlLgogIC8vIDMuIFRoZSBkZWZhdWx0IGxvY2FsZSdzIGNvbGxhdGlvbi4KICAvLyA0LiBBIGZhbGxiYWNrIG9mIHRoZSBkZWZhdWx0IGxvY2FsZS4KICAvLyA1LiBUaGUgZGVmYXVsdCBjb2xsYXRpb24gcnVsZXMsIHdoaWNoIGNvbnRhaW5zIGVuX1VTIGNvbGxhdGlvbiBydWxlcy4KCiAgLy8gVG8gcmVpdGVyYXRlLCB3ZSB0cnk6CiAgLy8gU3BlY2lmaWM6CiAgLy8gIGxhbmd1YWdlK2NvdW50cnkrdmFyaWFudAogIC8vICBsYW5ndWFnZStjb3VudHJ5CiAgLy8gIGxhbmd1YWdlCiAgLy8gRGVmYXVsdDoKICAvLyAgbGFuZ3VhZ2UrY291bnRyeSt2YXJpYW50CiAgLy8gIGxhbmd1YWdlK2NvdW50cnkKICAvLyAgbGFuZ3VhZ2UKICAvLyBSb290OiAoYWthIERFRkFVTFRSVUxFUykKICAvLyBzdGVwcyAxLTUgYXJlIGhhbmRsZWQgYnkgcmVzb3VyY2UgYnVuZGxlIGZhbGxiYWNrIG1lY2hhbmlzbS4gCiAgLy8gaG93ZXZlciwgaW4gYSB2ZXJ5IHVucHJvYmFibGUgc2l0dWF0aW9uIHRoYXQgbm8gcmVzb3VyY2UgYnVuZGxlCiAgLy8gZGF0YSBleGlzdHMsIHN0ZXAgNSBpcyByZXBlYXRlZCB3aXRoIGhhcmRjb2RlZCBkZWZhdWx0IHJ1bGVzLgoKICBjb25zdCBjaGFyICpsb2NOYW1lID0gY29uc3RydWN0RnJvbUJ1bmRsZShkZXNpcmVkTG9jYWxlLCBzdGF0dXMpOyAgLyohKi8KICBkYXRhLT5kZXNpcmVkTG9jYWxlID0gZGVzaXJlZExvY2FsZTsKICAKICBpZiAoVV9TVUNDRVNTKHN0YXR1cykpIHsKICAgIGRhdGEtPnJlYWxMb2NhbGVOYW1lID0gbG9jTmFtZTsKICAgIGlmKHN0YXR1cyAhPSBVX1VTSU5HX0RFRkFVTFRfRVJST1IpIHsKICAgICAgc2V0RGVjb21wb3NpdGlvbihOb3JtYWxpemVyOjpOT19PUCk7CiAgICB9CiAgfSBlbHNlIHsKICAgIFVFcnJvckNvZGUgaW50U3RhdHVzID0gVV9aRVJPX0VSUk9SOwogICAgY29uc3RydWN0RnJvbUNhY2hlKFJlc291cmNlQnVuZGxlOjprRGVmYXVsdEZpbGVuYW1lLCBpbnRTdGF0dXMpOwogICAgaWYoVV9GQUlMVVJFKGludFN0YXR1cykpIHsKICAgICAgaW50U3RhdHVzID0gVV9aRVJPX0VSUk9SOwogICAgICBjb25zdHJ1Y3RGcm9tUnVsZXMoUnVsZUJhc2VkQ29sbGF0b3I6OkRFRkFVTFRSVUxFUywgaW50U3RhdHVzKTsKICAgICAgaWYgKGludFN0YXR1cyA9PSBVX1pFUk9fRVJST1IpIHsKCXN0YXR1cyA9IFVfVVNJTkdfREVGQVVMVF9FUlJPUjsKICAgICAgfSBlbHNlIHsKCXN0YXR1cyA9IGludFN0YXR1czsgICAgIC8vIGJ1YmJsZSBiYWNrCiAgICAgIH0KICAgIAogICAgICBpZiAoc3RhdHVzID09IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1IpIHsKCXJldHVybjsKICAgICAgfQogICAgfQogICAgZGF0YS0+cmVhbExvY2FsZU5hbWUgPSBSZXNvdXJjZUJ1bmRsZTo6a0RlZmF1bHRGaWxlbmFtZTsKICAgIHNldERlY29tcG9zaXRpb24oTm9ybWFsaXplcjo6Tk9fT1ApOwogICAgYWRkVG9DYWNoZShSZXNvdXJjZUJ1bmRsZTo6a0RlZmF1bHRGaWxlbmFtZSk7CiAgfQogIHJldHVybjsKfQoKdm9pZApSdWxlQmFzZWRDb2xsYXRvcjo6Y29uc3RydWN0RnJvbUZpbGUoICAgY29uc3QgTG9jYWxlJiAgICAgICAgICAgbG9jYWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBVbmljb2RlU3RyaW5nJiAgICBsb2NhbGVGaWxlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUJvb2wgICAgICAgICAgICAgICAgICB0cnlCaW5hcnlGaWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiAgICAgICAgICAgICAgc3RhdHVzKQp7CiAgLy8gY29uc3RydWN0RnJvbUZpbGUgY3JlYXRlcyBhIGNvbGxhdGlvbiBvYmplY3QgYnkgcmVhZGluZyBmcm9tIGEKICAvLyBmaWxlLiAgSXQgZG9lcyBub3QgZW1wbG95IHRoZSB1c3VhbCBGSUxFIHNlYXJjaCBtZWNoYW5pc20gd2l0aAogIC8vIGxvY2FsZXMsIGRlZmF1bHQgbG9jYWxlcywgYW5kIGJhc2UgbG9jYWxlcy4gIEluc3RlYWQsIGl0IHRyaWVzIHRvCiAgLy8gbG9vayBvbmx5IGluIGZpbGVzIHdpdGggdGhlIGdpdmVuIGxvY2FsRmlsZU5hbWUuICBJdCBkb2VzLAogIC8vIGhvd2V2ZXIsIGVtcGxveSB0aGUgTE9DQUxFIHNlYXJjaCBtZWNoYW5pc20uCiAgCiAgLy8gVGhpcyBtZXRob2QgbWFpbnRhaW5zIHRoZSBiaW5hcnkgY29sbGF0aW9uIGZpbGVzLiAgSWYgYSBjb2xsYXRpb24KICAvLyBpcyBub3QgcHJlc2VudCBpbiBiaW5hcnkgZm9ybSwgYnV0IGlzIHByZXNlbnQgaW4gdGV4dCBmb3JtIChpbiBhCiAgLy8gcmVzb3VyY2UgYnVuZGxlIGZpbGUpLCBpdCB3aWxsIGJlIGxvYWRlZCBpbiB0ZXh0IGZvcm0sIGFuZCB0aGVuCiAgLy8gd3JpdHRlbiB0byBkaXNrLgogIAogIC8vIElmIHRyeUJpbmFyeUZpbGUgaXMgdHJ1ZSwgdGhlbiB0cnkgdG8gbG9hZCBmcm9tIHRoZSBiaW5hcnkgZmlsZSBmaXJzdC4KCiAgaWYoVV9GQUlMVVJFKHN0YXR1cykpIHsKICAgIHJldHVybjsKICB9CiAgCiAgaWYoZGF0YUlzT3duZWQpIHsKICAgIGRlbGV0ZSBkYXRhOwogICAgZGF0YSA9IDA7CiAgfQogIAogIGNoYXIgKmJpbmFyeUZpbGVQYXRoID0gY3JlYXRlUGF0aE5hbWUoVW5pY29kZVN0cmluZyh1X2dldERhdGFEaXJlY3RvcnkoKSwiIiksIAoJCQkJCWxvY2FsZUZpbGVOYW1lLCBVbmljb2RlU3RyaW5nKGtGaWxlbmFtZVN1ZmZpeCwiIikpOwogIAogICAgaWYodHJ5QmluYXJ5RmlsZSkgewogICAgICAgIC8vIFRyeSB0byBsb2FkIHVwIHRoZSBjb2xsYXRpb24gZnJvbSBhIGJpbmFyeSBmaWxlIGZpcnN0CiAgICAgICAgY29uc3RydWN0RnJvbUZpbGUoYmluYXJ5RmlsZVBhdGgsIHN0YXR1cyk7CiAgICAgICAgI2lmZGVmIENPTExERUJVRwogICAgICAgICAgICBjZXJyIDw8IGxvY2FsZUZpbGVOYW1lICA8PCBrRmlsZW5hbWVTdWZmaXggPDwgIiBiaW5hcnkgbG9hZCAiIDw8IHVfZXJyb3JOYW1lKHN0YXR1cykgPDwgZW5kbDsKICAgICAgICAjZW5kaWYKICAgICAgICBpZihVX1NVQ0NFU1Moc3RhdHVzKSB8fCBzdGF0dXMgPT0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUikgewogICAgICAgICAgICBkZWxldGUgW10gYmluYXJ5RmlsZVBhdGg7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgaWYoc3RhdHVzID09IFVfRklMRV9BQ0NFU1NfRVJST1IpIHsKICAgICAgICAgICAgc3RhdHVzID0gVV9aRVJPX0VSUk9SOwogICAgICAgIH0KICAgIH0KCiAgLy8gTm93IHRyeSB0byBsb2FkIGl0IHVwIGZyb20gYSByZXNvdXJjZSBidW5kbGUgdGV4dCBzb3VyY2UgZmlsZQogIFVuaWNvZGVTdHJpbmcgZGF0YURpciA9IFVuaWNvZGVTdHJpbmcodV9nZXREYXRhRGlyZWN0b3J5KCksIiIpOwoKICAgIGNoYXIgKmNoOwogICAgY2ggPSBuZXcgY2hhcltsb2NhbGVGaWxlTmFtZS5zaXplKCkgKyAxXTsKICAgIGNoW2xvY2FsZUZpbGVOYW1lLmV4dHJhY3QoMCwgMHg3ZmZmZmZmZiwgY2gsICIiKV0gPSAwOwogICAgUmVzb3VyY2VCdW5kbGUgYnVuZGxlKGRhdGFEaXIsIGNoLCBzdGF0dXMpOwogIAogICAgZGVsZXRlIFtdIGNoOwogIAogIC8vIGlmIHRoZXJlIGlzIG5vIHJlc291cmNlIGJ1bmRsZSBmaWxlIGZvciB0aGUgZ2l2ZSBsb2NhbGUsIGJyZWFrIG91dAogIGlmKFVfRkFJTFVSRShzdGF0dXMpKQogIHsKICAgICAgZGVsZXRlIFtdIGJpbmFyeUZpbGVQYXRoOwogICAgICByZXR1cm47CiAgfQoKICAgICNpZmRlZiBDT0xMREVCVUcKICAgICAgICBjZXJyIDw8IGxvY2FsZUZpbGVOYW1lIDw8ICIgYXNjaWkgbG9hZCAiIDw8IHVfZXJyb3JOYW1lKHN0YXR1cykgPDwgZW5kbDsKICAgICNlbmRpZgoKICAgIC8vIGNoZWNrIGFuZCBzZWUgaWYgdGhpcyByZXNvdXJjZSBidW5kbGUgY29udGFpbnMgY29sbGF0aW9uIGRhdGEKICAKICAgIFVuaWNvZGVTdHJpbmcgY29sU3RyaW5nOwogICAgVUVycm9yQ29kZSBpbnRTdGF0dXMgPSBVX1pFUk9fRVJST1I7Ci8qIFJFRE8gKi8KICAgIGNvbnN0IFVuaWNvZGVTdHJpbmcgKnQgPSBidW5kbGUuZ2V0U3RyaW5nKCJDb2xsYXRpb25FbGVtZW50cyIsIGludFN0YXR1cyk7CgogICAgaWYodCAhPSBOVUxMKSB7CiAgICAgICAgY29sU3RyaW5nID0gKnQ7CiAgICB9IAoKICAgIGlmKGNvbFN0cmluZy5pc0JvZ3VzKCkpIHsKICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgIGRlbGV0ZSBbXSBiaW5hcnlGaWxlUGF0aDsKICAgICAgICByZXR1cm47CiAgICB9CgogIC8vIGlmIHRoaXMgYnVuZGxlIGRvZXNuJ3QgY29udGFpbiBjb2xsYXRpb24gZGF0YSwgYnJlYWsgb3V0CiAgaWYoVV9GQUlMVVJFKGludFN0YXR1cykpIHsKICAgIHN0YXR1cyA9IFVfTUlTU0lOR19SRVNPVVJDRV9FUlJPUjsKICAgIGRlbGV0ZSBbXSBiaW5hcnlGaWxlUGF0aDsKICAgIHJldHVybjsKICB9CgogIC8vIEhhdmluZyBsb2FkZWQgdGhlIGNvbGxhdGlvbiBmcm9tIHRoZSByZXNvdXJjZSBidW5kbGUgdGV4dCBmaWxlLAogIC8vIG5vdyByZXRyaWV2ZSB0aGUgQ29sbGF0aW9uRWxlbWVudHMgdGFnZ2VkIGRhdGEsIG1lcmdlZCB3aXRoIHRoZQogIC8vIGRlZmF1bHQgcnVsZXMuICBJZiB0aGF0IGZhaWxzLCB1c2UgdGhlIGRlZmF1bHQgcnVsZXMgYWxvbmUuCgogIGNvbFN0cmluZy5pbnNlcnQoMCwgREVGQVVMVFJVTEVTKTsKICBpZihjb2xTdHJpbmcuaXNCb2d1cygpKSB7CiAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgZGVsZXRlIFtdIGJpbmFyeUZpbGVQYXRoOwogICAgcmV0dXJuOwogIH0KICAgIAogIGNvbnN0cnVjdEZyb21SdWxlcyhjb2xTdHJpbmcsIGludFN0YXR1cyk7CiAgaWYoaW50U3RhdHVzID09IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1IpIHsKICAgIHN0YXR1cyA9IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1I7CiAgICBkZWxldGUgW10gYmluYXJ5RmlsZVBhdGg7CiAgICByZXR1cm47CiAgfQogIAogIGlmKGludFN0YXR1cyAhPSBVX1pFUk9fRVJST1IpICB7CiAgICBzdGF0dXMgPSBVX1VTSU5HX0RFRkFVTFRfRVJST1I7CiAgICAgIAogICAgLy8gcHJlZGVmaW5lZCB0YWJsZXMgc2hvdWxkIGNvbnRhaW4gY29ycmVjdCBncmFtbWFyCiAgICBpbnRTdGF0dXMgPSBVX1pFUk9fRVJST1I7CiAgICBjb25zdHJ1Y3RGcm9tUnVsZXMoREVGQVVMVFJVTEVTLCBpbnRTdGF0dXMpOwogICAgaWYoaW50U3RhdHVzICE9IFVfWkVST19FUlJPUikgewogICAgICBzdGF0dXMgPSBpbnRTdGF0dXM7CiAgICB9CiAgfSAKICAKI2lmZGVmIENPTExERUJVRwogIGNlcnIgPDwgbG9jYWxlRmlsZU5hbWUgPDwgIiBhc2NpaSBsb2FkICIgPDwgKFVfU1VDQ0VTUyhzdGF0dXMpID8gIk9LIiA6ICJGYWlsZWQiKSA8PCAiIC0gdHJ5PSAiIDw8ICh0cnlCaW5hcnlGaWxlPyJ0cnVlIjoiZmFsc2UiKSA8PCBlbmRsOwojZW5kaWYKICAKICBpZihVX1NVQ0NFU1Moc3RhdHVzKSAmJiB0cnlCaW5hcnlGaWxlKSB7CiAgICAvLyBJZiB3ZSBnZXQgYSBSdWxlQmFzZWRDb2xsYXRvciByZXN1bHQsIGV2ZW4gaWYgaXQgaXMgZGVyaXZlZAogICAgLy8gZnJvbSBhIGRlZmF1bHQgb3IgYSBmYWxsYmFjaywgdGhlbiB3ZSB3cml0ZSBpdCBvdXQgYXMgYQogICAgLy8gYmluYXJ5IGZpbGUgdG8gdGhlIGRpc2suICBUaGUgbmV4dCB0aW1lIHRoZSBzeXN0ZW0gd2FudHMgdG8KICAgIC8vIGdldCB0aGlzIGNvbGxhdGlvbiwgaXQgd2lsbCBsb2FkIHVwIHZlcnkgcXVpY2tseSBmcm9tIHRoZQogICAgLy8gYmluYXJ5IGZpbGUuCiAgICAvKlVCb29sIG9rID0gd3JpdGVUb0ZpbGUoYmluYXJ5RmlsZVBhdGgpOyovIC8qISovCiAgICBkZWxldGUgW10gYmluYXJ5RmlsZVBhdGg7CiNpZmRlZiBDT0xMREVCVUcKICAgIGNlcnIgPDwgbG9jYWxlRmlsZU5hbWUgPDwgIiBiaW5hcnkgd3JpdGUgIiA8PCAob2s/ICJPSyIgOiAiRmFpbGVkIikgPDwgZW5kbDsKI2VuZGlmCiAgfQp9CgpSdWxlQmFzZWRDb2xsYXRvcjo6flJ1bGVCYXNlZENvbGxhdG9yKCkKewogICAgaWYgKGRhdGFJc093bmVkKQogICAgewogICAgICAgIGRlbGV0ZSBkYXRhOwogICAgfQoKICAgIGRhdGEgPSAwOwoKICAgIC8vICAgIGRlbGV0ZSBzb3VyY2VDdXJzb3I7CiAgICAvLyAgICBzb3VyY2VDdXJzb3IgPSAwOwoKICAgIC8vICAgIGRlbGV0ZSB0YXJnZXRDdXJzb3I7CiAgICAvLyAgICB0YXJnZXRDdXJzb3IgPSAwOwoKICAgIGlmIChjdXJzb3IxICE9IE5VTEwpIHsKICAgICAgICBkZWxldGUgY3Vyc29yMTsKICAgICAgICBjdXJzb3IxID0gMDsKICAgIH0KICAgIGlmIChjdXJzb3IyICE9IE5VTEwpIHsKICAgICAgICBkZWxldGUgY3Vyc29yMjsKICAgICAgICBjdXJzb3IyID0gMDsKICAgIH0KCiAgICBkZWxldGUgbVBhdHRlcm47CiAgICBtUGF0dGVybiA9IDA7Cn0KCkNvbGxhdG9yKgpSdWxlQmFzZWRDb2xsYXRvcjo6Y2xvbmUoKSBjb25zdAp7CiAgICByZXR1cm4gbmV3IFJ1bGVCYXNlZENvbGxhdG9yKCp0aGlzKTsKfQoKLy8gQ3JlYXRlIGEgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yIG9iamVjdCB0aGF0IHdpbGwgaXRlcmF0b3Igb3ZlciB0aGUgZWxlbWVudHMKLy8gaW4gYSBzdHJpbmcsIHVzaW5nIHRoZSBjb2xsYXRpb24gcnVsZXMgZGVmaW5lZCBpbiB0aGlzIFJ1bGVCYXNlZENvbGxhdG9yCkNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcioKUnVsZUJhc2VkQ29sbGF0b3I6OmNyZWF0ZUNvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcihjb25zdCBVbmljb2RlU3RyaW5nJiBzb3VyY2UpIGNvbnN0CnsKICAgIFVFcnJvckNvZGUgc3RhdHVzID0gVV9aRVJPX0VSUk9SOwogICAgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yICpuZXdDdXJzb3IgPSAwOwoKICAgIG5ld0N1cnNvciA9IG5ldyBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3Ioc291cmNlLCB0aGlzLCBzdGF0dXMpOwogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgewogICAgICAgIHJldHVybiBOVUxMOwogICAgfQoKICAgIHJldHVybiBuZXdDdXJzb3I7Cn0KCi8vIENyZWF0ZSBhIENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvciBvYmplY3QgdGhhdCB3aWxsIGl0ZXJhdG9yIG92ZXIgdGhlIGVsZW1lbnRzCi8vIGluIGEgc3RyaW5nLCB1c2luZyB0aGUgY29sbGF0aW9uIHJ1bGVzIGRlZmluZWQgaW4gdGhpcyBSdWxlQmFzZWRDb2xsYXRvcgpDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IqClJ1bGVCYXNlZENvbGxhdG9yOjpjcmVhdGVDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IoY29uc3QgQ2hhcmFjdGVySXRlcmF0b3ImIHNvdXJjZSkgY29uc3QKewogICAgVUVycm9yQ29kZSBzdGF0dXMgPSBVX1pFUk9fRVJST1I7CiAgICBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IgKm5ld0N1cnNvciA9IDA7CgogICAgbmV3Q3Vyc29yID0gbmV3IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcihzb3VyY2UsIHRoaXMsIHN0YXR1cyk7CiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuIE5VTEw7CiAgICB9CgogICAgcmV0dXJuIG5ld0N1cnNvcjsKfQoKLy8gUmV0dXJuIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgY29sbGF0b3IncyBydWxlcy4KLy8gVGhlIHN0cmluZyBjYW4gbGF0ZXIgYmUgcGFzc2VkIHRvIHRoZSBjb25zdHJ1Y3RvciB0aGF0IHRha2VzIGEKLy8gVW5pY29kZVN0cmluZyBhcmd1bWVudCwgd2hpY2ggd2lsbCBjb25zdHJ1Y3QgYSBjb2xsYXRvciB0aGF0J3MKLy8gZnVuY3Rpb25hbGx5IGlkZW50aWNhbCB0byB0aGlzIG9uZS4KLy8gWW91IGNhbiBhbHNvIGFsbG93IHVzZXJzIHRvIGVkaXQgdGhlIHN0cmluZyBpbiBvcmRlciB0byBjaGFuZ2UKLy8gdGhlIGNvbGxhdGlvbiBkYXRhLCBvciB5b3UgY2FuIHByaW50IGl0IG91dCBmb3IgaW5zcGVjdGlvbiwgb3Igd2hhdGV2ZXIuCgpjb25zdCBVbmljb2RlU3RyaW5nJgpSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0UnVsZXMoKSBjb25zdAp7CiAgICBpZiAobVBhdHRlcm4gIT0gMCkKICAgIHsKICAgICAgICBNZXJnZUNvbGxhdGlvbiomIG5vbkNvbnN0TVBhdHRlcm4gPSAqKE1lcmdlQ29sbGF0aW9uKiopJm1QYXR0ZXJuOwogICAgICAgIG1QYXR0ZXJuLT5lbWl0UGF0dGVybihkYXRhLT5ydWxlVGFibGUpOwogICAgICAgIGRhdGEtPmlzUnVsZVRhYmxlTG9hZGVkID0gVFJVRTsKICAgICAgICBkZWxldGUgbm9uQ29uc3RNUGF0dGVybjsKICAgICAgICBub25Db25zdE1QYXR0ZXJuID0gMDsKICAgIH0KICAgIGVsc2UgaWYgKCFkYXRhLT5pc1J1bGVUYWJsZUxvYWRlZCkKICAgIHsKICAgICAgICAvLyBBdCB0aGlzIHBvaW50IHRoZSBjYWxsZXIgd2FudHMgdGhlIHJ1bGVzLCBidXQgdGhlIHJ1bGUgdGFibGUgZGF0YQogICAgICAgIC8vIGlzIG5vdCBsb2FkZWQuICBGdXJ0aGVybW9yZSwgdGhlcmUgaXMgbm8gbVBhdHRlcm4gb2JqZWN0IHRvIGxvYWQKICAgICAgICAvLyB0aGUgcnVsZXMgZnJvbS4gIFRoZXJlZm9yZSwgd2UgZmV0Y2ggdGhlIHJ1bGVzIG9mZiB0aGUgZGlzay4KICAgICAgICAvLyBOb3RpY2UgdGhhdCB3ZSBwYXNzIGluIGEgdHJ5QmluYXJ5RmlsZSB2YWx1ZSBvZiBGQUxTRSwgc2luY2UKICAgICAgICAvLyBieSBkZXNpZ24gdGhlIGJpbmFyeSBmaWxlIGhhcyBOTyBydWxlcyBpbiBpdCEKICAgICAgICBSdWxlQmFzZWRDb2xsYXRvciB0ZW1wOwogICAgICAgIFVFcnJvckNvZGUgc3RhdHVzID0gVV9aRVJPX0VSUk9SOwogICAgICAgIHRlbXAuY29uc3RydWN0RnJvbUZpbGUoZGF0YS0+ZGVzaXJlZExvY2FsZSwgZGF0YS0+cmVhbExvY2FsZU5hbWUsIEZBTFNFLCBzdGF0dXMpOwoKICAgICAgICAvLyBXZSBtdXN0IGNoZWNrIHRoYXQgbVBhdHRlcm4gaXMgbm9uemVybyBoZXJlLCBvciB3ZSBydW4gdGhlIHJpc2sKICAgICAgICAvLyBvZiBhbiBpbmZpbml0ZSBsb29wLgogICAgICAgIGlmIChVX1NVQ0NFU1Moc3RhdHVzKSAmJiB0ZW1wLm1QYXR0ZXJuICE9IDApCiAgICAgICAgewogICAgICAgICAgICBkYXRhLT5ydWxlVGFibGUgPSB0ZW1wLmdldFJ1bGVzKCk7CiAgICAgICAgICAgIGRhdGEtPmlzUnVsZVRhYmxlTG9hZGVkID0gVFJVRTsKI2lmZGVmIF9ERUJVRwovLyAgICAgICAgICAgICAgLy8gdGhlIGZvbGxvd2luZyBpcyB1c2VmdWwgZm9yIHNwZWNpZmljIGRlYnVnZ2luZyBwdXJwb3NlcwovLyAgICAgICAgICAgICAgIFVuaWNvZGVTdHJpbmcgbmFtZTsKLy8gICAgICAgICAgICAgICBjZXJyIDw8ICJUYWJsZSBjb2xsYXRpb24gcnVsZXMgbG9hZGVkIGR5bmFtaWNhbGx5IGZvciAiCi8vICAgICAgICAgICAgICAgICAgIDw8IGRhdGEtPmRlc2lyZWRMb2NhbGUuZ2V0TmFtZShuYW1lKQovLyAgICAgICAgICAgICAgICAgICA8PCAiIGF0ICIKLy8gICAgICAgICAgICAgICAgICAgPDwgZGF0YS0+cmVhbExvY2FsZU5hbWUKLy8gICAgICAgICAgICAgICAgICAgPDwgIiwgIiA8PCBkZWMgPDwgZGF0YS0+cnVsZVRhYmxlLnNpemUoKSA8PCAiIGNoYXJhY3RlcnMiCi8vICAgICAgICAgICAgICAgICAgIDw8IGVuZGw7CiNlbmRpZgogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewojaWZkZWYgX0RFQlVHCi8vICAgICAgICAgICAgICBVbmljb2RlU3RyaW5nIG5hbWU7Ci8vICAgICAgICAgICAgICBjZXJyIDw8ICJVbmFibGUgdG8gbG9hZCB0YWJsZSBjb2xsYXRpb24gcnVsZXMgZHluYW1pY2FsbHkgZm9yICIKLy8gICAgICAgICAgICAgICAgICA8PCBkYXRhLT5kZXNpcmVkTG9jYWxlLmdldE5hbWUobmFtZSkKLy8gICAgICAgICAgICAgICAgICA8PCAiIGF0ICIKLy8gICAgICAgICAgICAgICAgICA8PCBkYXRhLT5yZWFsTG9jYWxlTmFtZQovLyAgICAgICAgICAgICAgICAgIDw8IGVuZGw7Ci8vICAgICAgICAgICAgICBjZXJyIDw8ICJTdGF0dXMgIiA8PCB1X2Vycm9yTmFtZShzdGF0dXMpIDw8ICIsIG1QYXR0ZXJuICIgPDwgdGVtcC5tUGF0dGVybiA8PCBlbmRsOwojZW5kaWYKCSAgICAvKiBTUkwgaGF2ZSB0byBhZGQgdGhpcyBiZWNhdXNlIHdlIG5vdyBoYXZlIHRoZSBzaXR1YXRpb24gd2hlcmUKCSAgICAgICBERUZBVUxUIGlzIGxvYWRlZCBmcm9tIGEgYmluYXJ5IGZpbGUgdy8gbm8gcnVsZXMuICovCgkgICAgVUVycm9yQ29kZSBpbnRTdGF0dXMgPSBVX1pFUk9fRVJST1I7CgkgICAgdGVtcC5jb25zdHJ1Y3RGcm9tUnVsZXMoUnVsZUJhc2VkQ29sbGF0b3I6OkRFRkFVTFRSVUxFUywgaW50U3RhdHVzKTsKCSAgICAKCSAgICBpZihVX1NVQ0NFU1MoaW50U3RhdHVzKSAmJiAodGVtcC5tUGF0dGVybiAhPSAwKSkKCSAgICAgIHsKCQlkYXRhLT5ydWxlVGFibGUgPSB0ZW1wLmdldFJ1bGVzKCk7CgkJZGF0YS0+aXNSdWxlVGFibGVMb2FkZWQgPSBUUlVFOwoJICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gZGF0YS0+cnVsZVRhYmxlOwp9CgoKQ29sbGF0b3I6OkVDb21wYXJpc29uUmVzdWx0ClJ1bGVCYXNlZENvbGxhdG9yOjpjb21wYXJlKCBjb25zdCBVbmljb2RlU3RyaW5nJiBzb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBVbmljb2RlU3RyaW5nJiB0YXJnZXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQzMl90IGxlbmd0aCkgY29uc3QKewogICAgVW5pY29kZVN0cmluZyBzb3VyY2VfdG9nbzsKICAgIFVuaWNvZGVTdHJpbmcgdGFyZ2V0X3RvZ287CiAgICBVVGV4dE9mZnNldCBiZWdpbj0wOwoKICAgIHNvdXJjZS5leHRyYWN0KGJlZ2luLCB1cHJ2X21pbihsZW5ndGgsc291cmNlLmxlbmd0aCgpKSwgc291cmNlX3RvZ28pOwogICAgdGFyZ2V0LmV4dHJhY3QoYmVnaW4sIHVwcnZfbWluKGxlbmd0aCx0YXJnZXQubGVuZ3RoKCkpLCB0YXJnZXRfdG9nbyk7CiAgICByZXR1cm4gKFJ1bGVCYXNlZENvbGxhdG9yOjpjb21wYXJlKHNvdXJjZV90b2dvLCB0YXJnZXRfdG9nbykpOwp9CgpDb2xsYXRvcjo6RUNvbXBhcmlzb25SZXN1bHQgICAKUnVsZUJhc2VkQ29sbGF0b3I6OmNvbXBhcmUoY29uc3QgICBVQ2hhciogc291cmNlLCAKICAgICAgICAgICAgICAgICAgICAgIGludDMyX3Qgc291cmNlTGVuZ3RoLAogICAgICAgICAgICAgICAgICAgICAgY29uc3QgICBVQ2hhciogIHRhcmdldCwKICAgICAgICAgICAgICAgICAgICAgIGludDMyX3QgdGFyZ2V0TGVuZ3RoKSBjb25zdAp7CiAgICAvLyBjaGVjayBpZiBzb3VyY2UgYW5kIHRhcmdldCBhcmUgdmFsaWQgc3RyaW5ncwogICAgaWYgKCgoc291cmNlID09IDApICYmICh0YXJnZXQgPT0gMCkpIHx8CiAgICAgICAgKChzb3VyY2VMZW5ndGggPT0gMCkgJiYgKHRhcmdldExlbmd0aCA9PSAwKSkpCiAgICB7CiAgICAgICAgcmV0dXJuIENvbGxhdG9yOjpFUVVBTDsKICAgIH0KCiAgICBDb2xsYXRvcjo6RUNvbXBhcmlzb25SZXN1bHQgcmVzdWx0ID0gQ29sbGF0b3I6OkVRVUFMOwogICAgVUVycm9yQ29kZSBzdGF0dXMgPSBVX1pFUk9fRVJST1I7CgogICAgaWYgKGN1cnNvcjEgPT0gTlVMTCkKICAgIHsKICAgICAgICAoKFJ1bGVCYXNlZENvbGxhdG9yICopdGhpcyktPmN1cnNvcjEgPSBuZXcgTm9ybWFsaXplckl0ZXJhdG9yKHNvdXJjZSwgc291cmNlTGVuZ3RoLCBnZXREZWNvbXBvc2l0aW9uKCkpOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIGN1cnNvcjEtPnNldE1vZGVBbmRUZXh0KGdldERlY29tcG9zaXRpb24oKSwgc291cmNlLCBzb3VyY2VMZW5ndGgsIHN0YXR1cyk7CiAgICB9CgogICAgaWYgKCAvKmN1cnNvcjEtPmN1cnNvciA9PSBOVUxMIHx8Ki8gVV9GQUlMVVJFKHN0YXR1cykpCiAgICB7CiAgICAgICAgcmV0dXJuIENvbGxhdG9yOjpFUVVBTDsKICAgIH0KCiAgICBpZiAoY3Vyc29yMiA9PSBOVUxMKQogICAgewogICAgICAgICgoUnVsZUJhc2VkQ29sbGF0b3IgKil0aGlzKS0+Y3Vyc29yMiA9IG5ldyBOb3JtYWxpemVySXRlcmF0b3IodGFyZ2V0LCB0YXJnZXRMZW5ndGgsIGdldERlY29tcG9zaXRpb24oKSk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgY3Vyc29yMi0+c2V0TW9kZUFuZFRleHQoZ2V0RGVjb21wb3NpdGlvbigpLCB0YXJnZXQsIHRhcmdldExlbmd0aCwgc3RhdHVzKTsKICAgIH0KCiAgICBpZiAoLypjdXJzb3IyID09IE5VTEwgfHwqLyBVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm4gQ29sbGF0b3I6OkVRVUFMOwogICAgfQoKICAgIGludDMyX3Qgc09yZGVyLCB0T3JkZXI7CiAgICAvLyAgICBpbnQzMl90IHNPcmRlciA9IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6TlVMTE9SREVSLCB0T3JkZXIgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUjsKICAgIFVCb29sIGdldHMgPSBUUlVFLCBnZXR0ID0gVFJVRTsKICAgIFVCb29sIGluaXRpYWxDaGVja1NlY1RlciA9IGdldFN0cmVuZ3RoKCkgPj0gQ29sbGF0b3I6OlNFQ09OREFSWTsKICAgIFVCb29sIGNoZWNrU2VjVGVyID0gaW5pdGlhbENoZWNrU2VjVGVyOwogICAgVUJvb2wgY2hlY2tUZXJ0aWFyeSA9IGdldFN0cmVuZ3RoKCkgPj0gQ29sbGF0b3I6OlRFUlRJQVJZOwogICAgVUJvb2wgaXNGcmVuY2hTZWMgPSBkYXRhLT5pc0ZyZW5jaFNlYzsKICAgIHVpbnQzMl90IHBTT3JkZXIsIHBUT3JkZXI7CgogICAgd2hpbGUoVFJVRSkKICAgIHsKICAgICAgICAvLyBHZXQgdGhlIG5leHQgY29sbGF0aW9uIGVsZW1lbnQgaW4gZWFjaCBvZiB0aGUgc3RyaW5ncywgdW5sZXNzCiAgICAgICAgLy8gd2UndmUgYmVlbiByZXF1ZXN0ZWQgdG8gc2tpcCBpdC4KICAgICAgICBpZiAoZ2V0cykKICAgICAgICB7CiAgICAgICAgICAgIHNPcmRlciA9IGdldFN0cmVuZ3RoT3JkZXIoKE5vcm1hbGl6ZXJJdGVyYXRvciopY3Vyc29yMSwgc3RhdHVzKTsKCiAgICAgICAgICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmV0dXJuIENvbGxhdG9yOjpFUVVBTDsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZ2V0cyA9IFRSVUU7CgogICAgICAgIGlmIChnZXR0KQogICAgICAgIHsKICAgICAgICAgICAgdE9yZGVyID0gZ2V0U3RyZW5ndGhPcmRlcigoTm9ybWFsaXplckl0ZXJhdG9yKiljdXJzb3IyLCBzdGF0dXMpOwoKICAgICAgICAgICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXR1cm4gQ29sbGF0b3I6OkVRVUFMOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIAogICAgICAgIGdldHQgPSBUUlVFOwoKICAgICAgICAvLyBJZiB3ZSd2ZSBoaXQgdGhlIGVuZCBvZiBvbmUgb2YgdGhlIHN0cmluZ3MsIGp1bXAgb3V0IG9mIHRoZSBsb29wCiAgICAgICAgaWYgKChzT3JkZXIgPT0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpOVUxMT1JERVIpfHwKICAgICAgICAgICAgKHRPcmRlciA9PSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUikpCiAgICAgICAgewogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIC8vIElmIHRoZXJlJ3Mgbm8gZGlmZmVyZW5jZSBhdCB0aGlzIHBvc2l0aW9uLCB3ZSBjYW4gc2tpcCB0byB0aGUKICAgICAgICAvLyBuZXh0IG9uZS4KICAgICAgICBwU09yZGVyID0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpwcmltYXJ5T3JkZXIoc09yZGVyKTsKICAgICAgICBwVE9yZGVyID0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpwcmltYXJ5T3JkZXIodE9yZGVyKTsKICAgICAgICBpZiAoc09yZGVyID09IHRPcmRlcikKICAgICAgICB7CiAgICAgICAgICAgIGlmIChpc0ZyZW5jaFNlYyAmJiBwU09yZGVyICE9IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGlmICghY2hlY2tTZWNUZXIpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgLy8gaW4gZnJlbmNoLCBhIHNlY29uZGFyeSBkaWZmZXJlbmNlIG1vcmUgdG8gdGhlIHJpZ2h0IGlzIHN0cm9uZ2VyLAogICAgICAgICAgICAgICAgICAgIC8vIHNvIGFjY2VudHMgaGF2ZSB0byBiZSBjaGVja2VkIHdpdGggZWFjaCBiYXNlIGVsZW1lbnQKICAgICAgICAgICAgICAgICAgICBjaGVja1NlY1RlciA9IGluaXRpYWxDaGVja1NlY1RlcjsKCiAgICAgICAgICAgICAgICAgICAgLy8gYnV0IHRlcnRpYXJ5IGRpZmZlcmVuY2VzIGFyZSBsZXNzIGltcG9ydGFudCB0aGFuIHRoZSBmaXJzdCAKICAgICAgICAgICAgICAgICAgICAvLyBzZWNvbmRhcnkgZGlmZmVyZW5jZSwgc28gY2hlY2tpbmcgdGVydGlhcnkgcmVtYWlucyBkaXNhYmxlZAogICAgICAgICAgICAgICAgICAgIGNoZWNrVGVydGlhcnkgPSBGQUxTRTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICAvLyBDb21wYXJlIHByaW1hcnkgZGlmZmVyZW5jZXMgZmlyc3QuCiAgICAgICAgaWYgKHBTT3JkZXIgIT0gcFRPcmRlcikKICAgICAgICB7CiAgICAgICAgICAgIGlmIChzT3JkZXIgPT0gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gVGhlIGVudGlyZSBzb3VyY2UgZWxlbWVudCBpcyBpZ25vcmFibGUuCiAgICAgICAgICAgICAgICAvLyBTa2lwIHRvIHRoZSBuZXh0IHNvdXJjZSBlbGVtZW50LCBidXQgZG9uJ3QgZmV0Y2ggYW5vdGhlciB0YXJnZXQgZWxlbWVudC4KICAgICAgICAgICAgICAgIGdldHQgPSBGQUxTRTsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAodE9yZGVyID09IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGdldHMgPSBGQUxTRTsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBUaGUgc291cmNlIGFuZCB0YXJnZXQgZWxlbWVudHMgYXJlbid0IGlnbm9yYWJsZSwgYnV0IGl0J3Mgc3RpbGwgcG9zc2libGUKICAgICAgICAgICAgLy8gZm9yIHRoZSBwcmltYXJ5IGNvbXBvbmVudCBvZiBvbmUgb2YgdGhlIGVsZW1lbnRzIHRvIGJlIGlnbm9yYWJsZS4uLi4KICAgICAgICAgICAgaWYgKHBTT3JkZXIgPT0gMCkgIC8vIHByaW1hcnkgb3JkZXIgaW4gc291cmNlIGlzIGlnbm9yYWJsZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvLyBUaGUgc291cmNlJ3MgcHJpbWFyeSBpcyBpZ25vcmFibGUsIGJ1dCB0aGUgdGFyZ2V0J3MgaXNuJ3QuICBXZSB0cmVhdCBpZ25vcmFibGVzCiAgICAgICAgICAgICAgICAvLyBhcyBhIHNlY29uZGFyeSBkaWZmZXJlbmNlLCBzbyByZW1lbWJlciB0aGF0IHdlIGZvdW5kIG9uZS4KICAgICAgICAgICAgICAgIGlmIChjaGVja1NlY1RlcikKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBDb2xsYXRvcjo6R1JFQVRFUjsgIC8vIChzdHJlbmd0aCBpcyBTRUNPTkRBUlkpCiAgICAgICAgICAgICAgICAgICAgY2hlY2tTZWNUZXIgPSBGQUxTRTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvLyBTa2lwIHRvIHRoZSBuZXh0IHNvdXJjZSBlbGVtZW50LCBidXQgZG9uJ3QgZmV0Y2ggYW5vdGhlciB0YXJnZXQgZWxlbWVudC4KICAgICAgICAgICAgICAgIGdldHQgPSBGQUxTRTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIGlmIChwVE9yZGVyID09IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIHJlY29yZCBkaWZmZXJlbmNlcyAtIHNlZSB0aGUgY29tbWVudCBhYm92ZS4KICAgICAgICAgICAgICAgIGlmIChjaGVja1NlY1RlcikKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBDb2xsYXRvcjo6TEVTUzsgIC8vIChzdHJlbmd0aCBpcyBTRUNPTkRBUlkpCiAgICAgICAgICAgICAgICAgICAgY2hlY2tTZWNUZXIgPSBGQUxTRTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvLyBTa2lwIHRvIHRoZSBuZXh0IHRhcmdldCBlbGVtZW50LCBidXQgZG9uJ3QgZmV0Y2ggYW5vdGhlciBzb3VyY2UgZWxlbWVudC4KICAgICAgICAgICAgICAgIGdldHMgPSBGQUxTRTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIE5laXRoZXIgb2YgdGhlIG9yZGVycyBpcyBpZ25vcmFibGUsIGFuZCB3ZSBhbHJlYWR5IGtub3cgdGhhdCB0aGUgcHJpbWFyeQogICAgICAgICAgICAgICAgLy8gb3JkZXJzIGFyZSBkaWZmZXJlbnQgYmVjYXVzZSBvZiB0aGUgKHBTT3JkZXIgIT0gcFRPcmRlcikgdGVzdCBhYm92ZS4KICAgICAgICAgICAgICAgIC8vIFJlY29yZCB0aGUgZGlmZmVyZW5jZSBhbmQgc3RvcCB0aGUgY29tcGFyaXNvbi4KICAgICAgICAgICAgICAgIGlmIChwU09yZGVyIDwgcFRPcmRlcikKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gQ29sbGF0b3I6OkxFU1M7ICAvLyAoc3RyZW5ndGggaXMgUFJJTUFSWSkKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICByZXR1cm4gQ29sbGF0b3I6OkdSRUFURVI7ICAvLyAoc3RyZW5ndGggaXMgUFJJTUFSWSkKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgeyAvLyBlbHNlIG9mIGlmICggcFNPcmRlciAhPSBwVE9yZGVyICkKICAgICAgICAgICAgLy8gcHJpbWFyeSBvcmRlciBpcyB0aGUgc2FtZSwgYnV0IGNvbXBsZXRlIG9yZGVyIGlzIGRpZmZlcmVudC4gU28gdGhlcmUKICAgICAgICAgICAgLy8gYXJlIG5vIGJhc2UgZWxlbWVudHMgYXQgdGhpcyBwb2ludCwgb25seSBpZ25vcmFibGVzIChTaW5jZSB0aGUgc3RyaW5ncyBhcmUKICAgICAgICAgICAgLy8gbm9ybWFsaXplZCkKCiAgICAgICAgICAgIGlmIChjaGVja1NlY1RlcikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gYSBzZWNvbmRhcnkgb3IgdGVydGlhcnkgZGlmZmVyZW5jZSBtYXkgc3RpbGwgbWF0dGVyCiAgICAgICAgICAgICAgICB1aW50MzJfdCBzZWNTT3JkZXIgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnNlY29uZGFyeU9yZGVyKHNPcmRlcik7CiAgICAgICAgICAgICAgICB1aW50MzJfdCBzZWNUT3JkZXIgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnNlY29uZGFyeU9yZGVyKHRPcmRlcik7CgogICAgICAgICAgICAgICAgaWYgKHNlY1NPcmRlciAhPSBzZWNUT3JkZXIpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgLy8gdGhlcmUgaXMgYSBzZWNvbmRhcnkgZGlmZmVyZW5jZQogICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IChzZWNTT3JkZXIgPCBzZWNUT3JkZXIpID8gQ29sbGF0b3I6OkxFU1MgOiBDb2xsYXRvcjo6R1JFQVRFUjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAoc3RyZW5ndGggaXMgU0VDT05EQVJZKQogICAgICAgICAgICAgICAgICAgIGNoZWNrU2VjVGVyID0gRkFMU0U7IAogICAgICAgICAgICAgICAgICAgIC8vIChldmVuIGluIGZyZW5jaCwgb25seSB0aGUgZmlyc3Qgc2Vjb25kYXJ5IGRpZmZlcmVuY2Ugd2l0aGluCiAgICAgICAgICAgICAgICAgICAgLy8gIGEgYmFzZSBjaGFyYWN0ZXIgbWF0dGVycykKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpZiAoY2hlY2tUZXJ0aWFyeSkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEgdGVydGlhcnkgZGlmZmVyZW5jZSBtYXkgc3RpbGwgbWF0dGVyCiAgICAgICAgICAgICAgICAgICAgICAgIHVpbnQzMl90IHRlclNPcmRlciA9IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6dGVydGlhcnlPcmRlcihzT3JkZXIpOwogICAgICAgICAgICAgICAgICAgICAgICB1aW50MzJfdCB0ZXJUT3JkZXIgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnRlcnRpYXJ5T3JkZXIodE9yZGVyKTsKCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXJTT3JkZXIgIT0gdGVyVE9yZGVyKQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGVyZSBpcyBhIHRlcnRpYXJ5IGRpZmZlcmVuY2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9ICh0ZXJTT3JkZXIgPCB0ZXJUT3JkZXIpID8gQ29sbGF0b3I6OkxFU1MgOiBDb2xsYXRvcjo6R1JFQVRFUjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAoc3RyZW5ndGggaXMgVEVSVElBUlkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVja1RlcnRpYXJ5ID0gRkFMU0U7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gLy8gaWYgKGNoZWNrU2VjVGVyKQoKICAgICAgICB9ICAvLyBpZiAoIHBTT3JkZXIgIT0gcFRPcmRlciApCiAgICB9IC8vIHdoaWxlKCkKCiAgICBpZiAoc09yZGVyICE9IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6TlVMTE9SREVSKQogICAgewogICAgICAgIC8vICh0T3JkZXIgbXVzdCBiZSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUiwKICAgICAgICAvLyAgc2luY2UgdGhpcyBwb2ludCBpcyBvbmx5IHJlYWNoZWQgd2hlbiBzT3JkZXIgb3IgdE9yZGVyIGlzIE5VTExPUkRFUi4pCiAgICAgICAgLy8gVGhlIHNvdXJjZSBzdHJpbmcgaGFzIG1vcmUgZWxlbWVudHMsIGJ1dCB0aGUgdGFyZ2V0IHN0cmluZyBoYXNuJ3QuCiAgICAgICAgZG8KICAgICAgICB7CiAgICAgICAgICAgIGlmIChDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnByaW1hcnlPcmRlcihzT3JkZXIpICE9IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIFdlIGZvdW5kIGFuIGFkZGl0aW9uYWwgbm9uLWlnbm9yYWJsZSBiYXNlIGNoYXJhY3RlciBpbiB0aGUgc291cmNlIHN0cmluZy4KICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYSBwcmltYXJ5IGRpZmZlcmVuY2UsIHNvIHRoZSBzb3VyY2UgaXMgZ3JlYXRlcgogICAgICAgICAgICAgICAgcmV0dXJuIENvbGxhdG9yOjpHUkVBVEVSOyAvLyAoc3RyZW5ndGggaXMgUFJJTUFSWSkKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaWYgKENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6c2Vjb25kYXJ5T3JkZXIoc09yZGVyKSAhPSAwKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvLyBBZGRpdGlvbmFsIHNlY29uZGFyeSBlbGVtZW50cyBtZWFuIHRoZSBzb3VyY2Ugc3RyaW5nIGlzIGdyZWF0ZXIKICAgICAgICAgICAgICAgIGlmIChjaGVja1NlY1RlcikKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBDb2xsYXRvcjo6R1JFQVRFUjsgIC8vIChzdHJlbmd0aCBpcyBTRUNPTkRBUlkpCiAgICAgICAgICAgICAgICAgICAgY2hlY2tTZWNUZXIgPSBGQUxTRTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSAKICAgICAgICB9CiAgICAgICAgd2hpbGUgKChzT3JkZXIgPSBnZXRTdHJlbmd0aE9yZGVyKGN1cnNvcjEsIHN0YXR1cykpICE9IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6TlVMTE9SREVSKTsKICAgIH0KICAgIGVsc2UgaWYgKHRPcmRlciAhPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUikKICAgIHsKICAgICAgICAvLyBUaGUgdGFyZ2V0IHN0cmluZyBoYXMgbW9yZSBlbGVtZW50cywgYnV0IHRoZSBzb3VyY2Ugc3RyaW5nIGhhc24ndC4KICAgICAgICBkbwogICAgICAgIHsKICAgICAgICAgICAgaWYgKENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6cHJpbWFyeU9yZGVyKHRPcmRlcikgIT0gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gV2UgZm91bmQgYW4gYWRkaXRpb25hbCBub24taWdub3JhYmxlIGJhc2UgY2hhcmFjdGVyIGluIHRoZSB0YXJnZXQgc3RyaW5nLgogICAgICAgICAgICAgICAgLy8gVGhpcyBpcyBhIHByaW1hcnkgZGlmZmVyZW5jZSwgc28gdGhlIHNvdXJjZSBpcyBsZXNzCiAgICAgICAgICAgICAgICByZXR1cm4gQ29sbGF0b3I6OkxFU1M7IC8vIChzdHJlbmd0aCBpcyBQUklNQVJZKQogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAoQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpzZWNvbmRhcnlPcmRlcih0T3JkZXIpICE9IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIEFkZGl0aW9uYWwgc2Vjb25kYXJ5IGVsZW1lbnRzIGluIHRoZSB0YXJnZXQgbWVhbiB0aGUgc291cmNlIHN0cmluZyBpcyBsZXNzCiAgICAgICAgICAgICAgICBpZiAoY2hlY2tTZWNUZXIpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQ29sbGF0b3I6OkxFU1M7ICAvLyAoc3RyZW5ndGggaXMgU0VDT05EQVJZKQogICAgICAgICAgICAgICAgICAgIGNoZWNrU2VjVGVyID0gRkFMU0U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gCiAgICAgICAgfQogICAgICAgIHdoaWxlICgodE9yZGVyID0gZ2V0U3RyZW5ndGhPcmRlcihjdXJzb3IyLCBzdGF0dXMpKSAhPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6Ok5VTExPUkRFUik7CiAgICB9CgoKICAgIC8vIEZvciBJREVOVElDQUwgY29tcGFyaXNvbnMsIHdlIHVzZSBhIGJpdHdpc2UgY2hhcmFjdGVyIGNvbXBhcmlzb24KICAgIC8vIGFzIGEgdGllYnJlYWtlciBpZiBhbGwgZWxzZSBpcyBlcXVhbAogICAgLy8gTk9URTogVGhlIGphdmEgY29kZSBjb21wYXJlcyByZXN1bHQgd2l0aCAwLCBhbmQgCiAgICAvLyBwdXRzIHRoZSByZXN1bHQgb2YgdGhlIHN0cmluZyBjb21wYXJpc29uIGRpcmVjdGx5IGludG8gcmVzdWx0CiAgICBpZiAocmVzdWx0ID09IENvbGxhdG9yOjpFUVVBTCAmJiBnZXRTdHJlbmd0aCgpID09IElERU5USUNBTCkKICAgIHsKI2lmIDAKICAgICAgLy8gKioqKioqKiogZm9yIHRoZSAgVUNoYXIgbm9ybWFsaXphdGlvbiBpbnRlcmZhY2UuCiAgICAgIC8vIEl0IGRvZXNuJ3Qgd29yayBtdWNoIGZhc3RlciwgYW5kIHRoZSBjb2RlIHdhcyBicm9rZW4KICAgICAgLy8gc28gaXQncyBjb21tZW50ZWQgb3V0LiAtLXNybAovLyAgICAgICAgICBVQ2hhciBzb3VyY2VEZWNvbXBbMTAyNF0sIHRhcmdldERlY29tcFsxMDI0XTsKLy8gIAlpbnQzMl90IHNvdXJjZURlY29tcExlbmd0aCA9IDEwMjQ7Ci8vICAJaW50MzJfdCB0YXJnZXREZWNvbXBMZW5ndGggPSAxMDI0OwoJCi8vICAgICAgICAgIGludDhfdCBjb21wYXJpc29uOwovLyAgCU5vcm1hbGl6ZXI6OkVNb2RlIGRlY29tcE1vZGUgPSBnZXREZWNvbXBvc2l0aW9uKCk7CiAgICAgICAgCi8vICAJaWYgKGRlY29tcE1vZGUgIT0gTm9ybWFsaXplcjo6Tk9fT1ApCi8vICAJICB7Ci8vICAJICAgIE5vcm1hbGl6ZXI6Om5vcm1hbGl6ZShzb3VyY2UsIHNvdXJjZUxlbmd0aCwgZGVjb21wTW9kZSwKLy8gIAkJCQkgIDAsIHNvdXJjZURlY29tcCwgc291cmNlRGVjb21wTGVuZ3RoLCBzdGF0dXMpOwoJICAgIAovLyAgCSAgICBOb3JtYWxpemVyOjpub3JtYWxpemUodGFyZ2V0LCB0YXJnZXRMZW5ndGgsIGRlY29tcE1vZGUsCi8vICAJCQkJICAwLCB0YXJnZXREZWNvbXAsIHRhcmdldERlY29tcExlbmd0aCwgc3RhdHVzKTsKCSAgICAKLy8gIAkgICAgY29tcGFyaXNvbiA9IHVfc3RyY21wKHNvdXJjZURlY29tcCx0YXJnZXREZWNvbXApOwovLyAgCSAgfQovLyAgCWVsc2UKLy8gIAkgIHsKLy8gIAkgICAgY29tcGFyaXNvbiA9IHVfc3RyY21wKHNvdXJjZSwgdGFyZ2V0KTsgLyogISAqLwovLyAgCSAgfQoKI2Vsc2UKCglVbmljb2RlU3RyaW5nIHNvdXJjZURlY29tcCwgdGFyZ2V0RGVjb21wOwoKICAgICAgICBpbnQ4X3QgY29tcGFyaXNvbjsKICAgICAgICAKICAgICAgICBOb3JtYWxpemVyOjpub3JtYWxpemUoc291cmNlLCBnZXREZWNvbXBvc2l0aW9uKCksIAogICAgICAgICAgICAgICAgICAgICAgMCwgc291cmNlRGVjb21wLCAgc3RhdHVzKTsKCiAgICAgICAgTm9ybWFsaXplcjo6bm9ybWFsaXplKHRhcmdldCwgZ2V0RGVjb21wb3NpdGlvbigpLCAKICAgICAgICAgICAgICAgICAgICAgIDAsIHRhcmdldERlY29tcCwgIHN0YXR1cyk7CiAgICAgICAgCiAgICAgICAgY29tcGFyaXNvbiA9IHNvdXJjZURlY29tcC5jb21wYXJlKHRhcmdldERlY29tcCk7CiNlbmRpZgoKICAgICAgICBpZiAoY29tcGFyaXNvbiA8IDApCiAgICAgICAgewogICAgICAgICAgICByZXN1bHQgPSBDb2xsYXRvcjo6TEVTUzsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoY29tcGFyaXNvbiA9PSAwKQogICAgICAgIHsKICAgICAgICAgICAgcmVzdWx0ID0gQ29sbGF0b3I6OkVRVUFMOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICByZXN1bHQgPSBDb2xsYXRvcjo6R1JFQVRFUjsKICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJlc3VsdDsKfQoKCmludDMyX3QKUnVsZUJhc2VkQ29sbGF0b3I6Om5leHRDb250cmFjdENoYXIoTm9ybWFsaXplckl0ZXJhdG9yICpjdXJzb3IsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVQ2hhciBjaCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgc3RhdHVzKSBjb25zdAp7CiAgICAvLyBGaXJzdCBnZXQgdGhlIG9yZGVyaW5nIG9mIHRoaXMgc2luZ2xlIGNoYXJhY3RlcgogICAgVmVjdG9yT2ZQVG9Db250cmFjdEVsZW1lbnQgKmxpc3QgPSBnZXRDb250cmFjdFZhbHVlcyhjaCk7CiAgICBFbnRyeVBhaXIgKnBhaXIgPSAoRW50cnlQYWlyICopbGlzdC0+YXQoMCk7CiAgICBpbnQzMl90IG9yZGVyID0gcGFpci0+dmFsdWU7CgogICAgLy8gTm93IGl0ZXJhdGUgdGhyb3VnaCB0aGUgY2hhcnMgZm9sbG93aW5nIGl0IGFuZAogICAgLy8gbG9vayBmb3IgdGhlIGxvbmdlc3QgbWF0Y2gKICAgICgoVW5pY29kZVN0cmluZyYpa2V5KS5yZW1vdmUoKTsKICAgICgoVW5pY29kZVN0cmluZyYpa2V5KSArPSBjaDsKCiAgICB3aGlsZSAoKGNoID0gY3Vyc29yLT5jdXJyZW50KCkpICE9IE5vcm1hbGl6ZXI6OkRPTkUpCiAgICB7CiAgICAgICAgKChVbmljb2RlU3RyaW5nJilrZXkpICs9IGNoOwoKICAgICAgICBpbnQzMl90IG4gPSBnZXRFbnRyeShsaXN0LCBrZXksIFRSVUUpOwoKICAgICAgICBpZiAobiA9PSBVTk1BUFBFRCkKICAgICAgICB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjdXJzb3ItPm5leHQoKTsKCiAgICAgICAgcGFpciA9IChFbnRyeVBhaXIgKilsaXN0LT5hdChuKTsKICAgICAgICBvcmRlciA9IHBhaXItPnZhbHVlOwogICAgfQoKICAgIHJldHVybiBvcmRlcjsKfQoKLy8gQ29tcGFyZSB0d28gc3RyaW5ncyB1c2luZyB0aGlzIGNvbGxhdG9yCkNvbGxhdG9yOjpFQ29tcGFyaXNvblJlc3VsdApSdWxlQmFzZWRDb2xsYXRvcjo6Y29tcGFyZShjb25zdCBVbmljb2RlU3RyaW5nJiBzb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFVuaWNvZGVTdHJpbmcmIHRhcmdldCkgY29uc3QKewogICAgcmV0dXJuIGNvbXBhcmUoc291cmNlLmdldFVDaGFycygpLCBzb3VyY2UubGVuZ3RoKCksIHRhcmdldC5nZXRVQ2hhcnMoKSwgdGFyZ2V0Lmxlbmd0aCgpKTsKfQoKLy8gUmV0cmlldmUgYSBjb2xsYXRpb24ga2V5IGZvciB0aGUgc3BlY2lmaWVkIHN0cmluZwovLyBUaGUga2V5IGNhbiBiZSBjb21wYXJlZCB3aXRoIG90aGVyIGNvbGxhdGlvbiBrZXlzIHVzaW5nIGEgYml0d2lzZSBjb21wYXJpc29uCi8vIChlLmcuIG1lbWNtcCkgdG8gZmluZCB0aGUgb3JkZXJpbmcgb2YgdGhlaXIgcmVzcGVjdGl2ZSBzb3VyY2Ugc3RyaW5ncy4KLy8gVGhpcyBpcyBoYW5keSB3aGVuIGRvaW5nIGEgc29ydCwgd2hlcmUgZWFjaCBzb3J0IGtleSBtdXN0IGJlIGNvbXBhcmVkCi8vIG1hbnkgdGltZXMuCi8vCi8vIFRoZSBiYXNpYyBhbGdvcml0aG0gaGVyZSBpcyB0byBmaW5kIGFsbCBvZiB0aGUgY29sbGF0aW9uIGVsZW1lbnRzIGZvciBlYWNoCi8vIGNoYXJhY3RlciBpbiB0aGUgc291cmNlIHN0cmluZywgY29udmVydCB0aGVtIHRvIGFuIEFTQ0lJIHJlcHJlc2VudGF0aW9uLAovLyBhbmQgcHV0IHRoZW0gaW50byB0aGUgY29sbGF0aW9uIGtleS4gIEJ1dCBpdCdzIHRyaWNraWVyIHRoYW4gdGhhdC4KLy8gRWFjaCBjb2xsYXRpb24gZWxlbWVudCBpbiBhIHN0cmluZyBoYXMgdGhyZWUgY29tcG9uZW50czogcHJpbWFyeSAoJ0EnIHZzICdCJyksCi8vIHNlY29uZGFyeSAoJ3UnIHZzICf8JyksIGFuZCB0ZXJ0aWFyeSAoJ0EnIHZzICdhJyksIGFuZCBhIHByaW1hcnkgZGlmZmVyZW5jZQovLyBhdCB0aGUgZW5kIG9mIGEgc3RyaW5nIHRha2VzIHByZWNlZGVuY2Ugb3ZlciBhIHNlY29uZGFyeSBvciB0ZXJ0aWFyeQovLyBkaWZmZXJlbmNlIGVhcmxpZXIgaW4gdGhlIHN0cmluZy4KLy8KLy8gVG8gYWNjb3VudCBmb3IgdGhpcywgd2UgcHV0IGFsbCBvZiB0aGUgcHJpbWFyeSBvcmRlcnMgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUKLy8gc3RyaW5nLCBmb2xsb3dlZCBieSB0aGUgc2Vjb25kYXJ5IGFuZCB0ZXJ0aWFyeSBvcmRlcnMuIEVhY2ggc2V0IG9mIG9yZGVycyBpcwovLyB0ZXJtaW5hdGVkIGJ5IG51bGxzIHNvIHRoYXQgYSBrZXkgZm9yIGEgc3RyaW5nIHdoaWNoIGlzIGEgaW5pdGlhbCBzdWJzdHJpbmcgb2YKLy8gYW5vdGhlciBrZXkgd2lsbCBjb21wYXJlIGxlc3Mgd2l0aG91dCBhbnkgc3BlY2lhbCBjYXNlLgovLwovLyBIZXJlJ3MgYSBoeXBvdGhldGljYWwgZXhhbXBsZSwgd2l0aCB0aGUgY29sbGF0aW9uIGVsZW1lbnQgcmVwcmVzZW50ZWQgYXMKLy8gYSB0aHJlZS1kaWdpdCBudW1iZXIsIG9uZSBkaWdpdCBmb3IgcHJpbWFyeSwgb25lIGZvciBzZWNvbmRhcnksIGV0Yy4KLy8KLy8gU3RyaW5nOiAgICAgICAgICAgICAgQSAgICAgYSAgICAgQiAgICDJCi8vIENvbGxhdGlvbiBFbGVtZW50czogMTAxICAgMTAwICAgMjAxICA1MTEKLy8gQ29sbGF0aW9uIEtleTogICAgICAxMTI1PG51bGw+MDAwMTxudWxsPjEwMTE8bnVsbD4KLy8KLy8gVG8gbWFrZSB0aGluZ3MgZXZlbiB0cmlja2llciwgc2Vjb25kYXJ5IGRpZmZlcmVuY2VzIChhY2NlbnQgbWFya3MpIGFyZSBjb21wYXJlZAovLyBzdGFydGluZyBhdCB0aGUgKmVuZCogb2YgdGhlIHN0cmluZyBpbiBsYW5ndWFnZXMgd2l0aCBGcmVuY2ggc2Vjb25kYXJ5IG9yZGVyaW5nLgovLyBCdXQgd2hlbiBjb21wYXJpbmcgdGhlIGFjY2VudCBtYXJrcyBvbiBhIHNpbmdsZSBiYXNlIGNoYXJhY3RlciwgdGhleSBhcmUgY29tcGFyZWQKLy8gZnJvbSB0aGUgYmVnaW5uaW5nLiAgVG8gaGFuZGxlIHRoaXMsIHdlIHJldmVyc2UgYWxsIG9mIHRoZSBhY2NlbnRzIHRoYXQgYmVsb25nCi8vIHRvIGVhY2ggYmFzZSBjaGFyYWN0ZXIsIHRoZW4gd2UgcmV2ZXJzZSB0aGUgZW50aXJlIHN0cmluZyBvZiBzZWNvbmRhcnkgb3JkZXJpbmdzCi8vIGF0IHRoZSBlbmQuCi8vCkNvbGxhdGlvbktleSYKUnVsZUJhc2VkQ29sbGF0b3I6OmdldENvbGxhdGlvbktleSggY29uc3QgICBVbmljb2RlU3RyaW5nJiAgc291cmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb2xsYXRpb25LZXkmICAgc29ydGtleSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgICAgICBzdGF0dXMpIGNvbnN0CnsKICAgIHJldHVybiBSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0Q29sbGF0aW9uS2V5KHNvdXJjZS5nZXRVQ2hhcnMoKSwgc291cmNlLmxlbmd0aCgpLCBzb3J0a2V5LCBzdGF0dXMpOwp9CgpDb2xsYXRpb25LZXkmClJ1bGVCYXNlZENvbGxhdG9yOjpnZXRDb2xsYXRpb25LZXkoIGNvbnN0ICAgVUNoYXIqICBzb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludDMyX3Qgc291cmNlTGVuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb2xsYXRpb25LZXkmICAgc29ydGtleSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUVycm9yQ29kZSYgICAgICBzdGF0dXMpIGNvbnN0CnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICBzdGF0dXMgPSBVX0lMTEVHQUxfQVJHVU1FTlRfRVJST1I7CiAgICAgICAgcmV0dXJuIHNvcnRrZXkuc2V0VG9Cb2d1cygpOwogICAgfQogICAgCiAgICBpZiAoKCFzb3VyY2UpIHx8IChzb3VyY2VMZW4gPT0gMCkpCiAgICB7CiAgICAgICAgcmV0dXJuIHNvcnRrZXkucmVzZXQoKTsKICAgIH0KCiAgICBpZiAoY3Vyc29yMSA9PSBOVUxMKQogICAgewogICAgICAoKFJ1bGVCYXNlZENvbGxhdG9yICopdGhpcyktPmN1cnNvcjEgPSBuZXcgTm9ybWFsaXplckl0ZXJhdG9yKHNvdXJjZSwgc291cmNlTGVuLCBnZXREZWNvbXBvc2l0aW9uKCkpOwogICAgfQogICAgZWxzZQogICAgewogICAgICBjdXJzb3IxLT5zZXRNb2RlQW5kVGV4dChnZXREZWNvbXBvc2l0aW9uKCksIHNvdXJjZSxzb3VyY2VMZW4sIHN0YXR1cyk7CiAgICB9CgogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgewogICAgICAgIHJldHVybiBzb3J0a2V5LnNldFRvQm9ndXMoKTsKICAgIH0KCiAgICBVQm9vbCAgY29tcGFyZVNlYyAgID0gKGdldFN0cmVuZ3RoKCkgPj0gQ29sbGF0b3I6OlNFQ09OREFSWSk7CiAgICBVQm9vbCAgY29tcGFyZVRlciAgID0gKGdldFN0cmVuZ3RoKCkgPj0gQ29sbGF0b3I6OlRFUlRJQVJZKTsKICAgIFVCb29sICBjb21wYXJlSWRlbnQgPSAoZ2V0U3RyZW5ndGgoKSA9PSBDb2xsYXRvcjo6SURFTlRJQ0FMKTsKICAgIGludDMyX3Qgb3JkZXIgICAgICAgID0gMDsKICAgIGludDMyX3QgdG90YWxQcmltYXJ5ID0gMDsKICAgIGludDMyX3QgdG90YWxTZWMgICAgID0gMDsKICAgIGludDMyX3QgdG90YWxUZXIgICAgID0gMDsKICAgIGludDMyX3QgdG90YWxJZGVudCAgICAgPSAwOwogICAgVW5pY29kZVN0cmluZyBkZWNvbXA7CgogICAgLy8gaXRlcmF0ZSBvdmVyIHRoZSBzb3VyY2UsIGNvdW50aW5nIHByaW1hcnksIHNlY29uZGFyeSwgYW5kIHRlcnRpYXJ5IGVudHJpZXMKICAgIHdoaWxlKChvcmRlciA9IGdldFN0cmVuZ3RoT3JkZXIoKE5vcm1hbGl6ZXJJdGVyYXRvciopY3Vyc29yMSwgc3RhdHVzKSkgIT0KCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpOVUxMT1JERVIpCiAgICB7CiAgICAgICAgaW50MzJfdCBzZWNPcmRlciA9IENvbGxhdGlvbkVsZW1lbnRJdGVyYXRvcjo6c2Vjb25kYXJ5T3JkZXIob3JkZXIpOwogICAgICAgIGludDMyX3QgdGVyT3JkZXIgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnRlcnRpYXJ5T3JkZXIob3JkZXIpOwoKICAgICAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gc29ydGtleS5zZXRUb0JvZ3VzKCk7CiAgICAgICAgfQoKICAgICAgICBpZiAoISBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OmlzSWdub3JhYmxlKG9yZGVyKSkKICAgICAgICB7CiAgICAgICAgICAgIHRvdGFsUHJpbWFyeSArPSAxOwoKICAgICAgICAgICAgaWYgKGNvbXBhcmVTZWMpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRvdGFsU2VjICs9IDE7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChjb21wYXJlVGVyKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICB0b3RhbFRlciArPSAxOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIGlmIChjb21wYXJlU2VjICYmIHNlY09yZGVyICE9IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRvdGFsU2VjICs9IDE7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChjb21wYXJlVGVyICYmIHRlck9yZGVyICE9IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRvdGFsVGVyICs9IDE7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgLy8gY291bnQgdGhlIG51bGwgYnl0ZXMgYWZ0ZXIgdGhlIGVudGlyZXMKICAgIHRvdGFsUHJpbWFyeSArPSAxOwoKICAgIGlmIChjb21wYXJlU2VjKQogICAgewogICAgICAgIHRvdGFsU2VjICs9IDE7CiAgICB9CgogICAgaWYgKGNvbXBhcmVUZXIpCiAgICB7CiAgICAgICAgdG90YWxUZXIgKz0gMTsKICAgIH0KCiAgICBpZiAoY29tcGFyZUlkZW50KQogICAgewogICAgICBOb3JtYWxpemVyOjpub3JtYWxpemUoc291cmNlLCBnZXREZWNvbXBvc2l0aW9uKCksIC8vIFNSTDogPz8KICAgICAgICAgICAgICAgIDAsIGRlY29tcCwgc3RhdHVzKTsKCiAgICAgICAgaWYgKFVfU1VDQ0VTUyhzdGF0dXMpKQogICAgICAgIHsKICAgICAgICAgICAgdG90YWxJZGVudCA9IGRlY29tcC5sZW5ndGgoKSArIDE7CiAgICAgICAgfQogICAgfQoKICAgIC8vIENvbXB1dGUgdG90YWwgbnVtYmVyIG9mIGJ5dGVzIHRvIGhvbGQgdGhlIGVudHJpZXMKICAgIC8vIGFuZCBtYWtlIHN1cmUgdGhlIGtleSBjYW4gaG9sZCB0aGVtCiAgICB1aW50MzJfdCBzaXplICAgPSAyICogKHRvdGFsUHJpbWFyeSArIHRvdGFsU2VjICsgdG90YWxUZXIgKyB0b3RhbElkZW50KTsKCiAgICBzb3J0a2V5LmVuc3VyZUNhcGFjaXR5KHNpemUpOwoKICAgIGlmIChzb3J0a2V5LmlzQm9ndXMoKSkKICAgIHsKICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgIHJldHVybiBzb3J0a2V5OwogICAgfQoKICAgIGludDMyX3QgcHJpbWFyeUN1cnNvciA9IDA7CiAgICBpbnQzMl90IHNlY0N1cnNvciAgICAgPSAyICogdG90YWxQcmltYXJ5OwogICAgaW50MzJfdCBzZWNCYXNlICAgICAgID0gc2VjQ3Vyc29yOwogICAgaW50MzJfdCBwcmVTZWNJZ25vcmUgID0gc2VjQmFzZTsKICAgIGludDMyX3QgdGVyQ3Vyc29yICAgICA9IHNlY0N1cnNvciArICgyICogdG90YWxTZWMpOwogICAgaW50MzJfdCBpZGVudEN1cnNvciAgICAgID0gdGVyQ3Vyc29yICsgKDIgKiB0b3RhbFRlcik7CgogICAgLy8gcmVzZXQgc291cmNlIHRvIHRoZSBiZWdpbm5pbmcKICAgIGN1cnNvcjEtPnJlc2V0KCk7CgogICAgLy8gbm93IGl0ZXJhdGUgb3ZlciB0aGUgc291cmNlIGNvbXB1dGluZyB0aGUgYWN0dWFsIGVudHJpZXMKICAgIHdoaWxlKChvcmRlciA9IGdldFN0cmVuZ3RoT3JkZXIoKE5vcm1hbGl6ZXJJdGVyYXRvciopY3Vyc29yMSwgc3RhdHVzKSkgIT0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpOVUxMT1JERVIpCiAgICB7CiAgICAgICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIHNvcnRrZXkucmVzZXQoKTsKICAgICAgICB9CgogICAgICAgIGludDMyX3QgcHJpbWFyeU9yZGVyID0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpwcmltYXJ5T3JkZXIob3JkZXIpOwogICAgICAgIGludDMyX3Qgc2VjT3JkZXIgICAgID0gQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpzZWNvbmRhcnlPcmRlcihvcmRlcik7CiAgICAgICAgaW50MzJfdCB0ZXJPcmRlciAgICAgPSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OnRlcnRpYXJ5T3JkZXIob3JkZXIpOwoKICAgICAgICBpZiAoISBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3I6OmlzSWdub3JhYmxlKG9yZGVyKSkKICAgICAgICB7CiAgICAgICAgICAgIHByaW1hcnlDdXJzb3IgPSBzb3J0a2V5LnN0b3JlQnl0ZXMocHJpbWFyeUN1cnNvciwgcHJpbWFyeU9yZGVyICsgU09SVEtFWU9GRlNFVCk7CgogICAgICAgICAgICBpZiAoY29tcGFyZVNlYykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaWYgKGRhdGEtPmlzRnJlbmNoU2VjICYmIChwcmVTZWNJZ25vcmUgPCBzZWNDdXJzb3IpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHNvcnRrZXkucmV2ZXJzZUJ5dGVzKHByZVNlY0lnbm9yZSwgc2VjQ3Vyc29yKTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBzZWNDdXJzb3IgPSBzb3J0a2V5LnN0b3JlQnl0ZXMoc2VjQ3Vyc29yLCBzZWNPcmRlciArIFNPUlRLRVlPRkZTRVQpOwoKICAgICAgICAgICAgICAgIHByZVNlY0lnbm9yZSA9IHNlY0N1cnNvcjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaWYgKGNvbXBhcmVUZXIpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRlckN1cnNvciA9IHNvcnRrZXkuc3RvcmVCeXRlcyh0ZXJDdXJzb3IsIHRlck9yZGVyICsgU09SVEtFWU9GRlNFVCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgaWYgKGNvbXBhcmVTZWMgJiYgc2VjT3JkZXIgIT0gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc2VjQ3Vyc29yID0gc29ydGtleS5zdG9yZUJ5dGVzKHNlY0N1cnNvciwgc2VjT3JkZXIgKyBkYXRhLT5tYXhTZWNPcmRlciArIFNPUlRLRVlPRkZTRVQpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAoY29tcGFyZVRlciAmJiB0ZXJPcmRlciAhPSAwKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICB0ZXJDdXJzb3IgPSBzb3J0a2V5LnN0b3JlQnl0ZXModGVyQ3Vyc29yLCB0ZXJPcmRlciArIGRhdGEtPm1heFRlck9yZGVyICsgU09SVEtFWU9GRlNFVCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgLy8gYXBwZW5kIDAgYXQgdGhlIGVuZCBvZiBlYWNoIHBvcnRpb24uCiAgICBzb3J0a2V5LnN0b3JlQnl0ZXMocHJpbWFyeUN1cnNvciwgMCk7CgogICAgaWYgKGNvbXBhcmVTZWMpCiAgICB7CiAgICAgICAgaWYgKGRhdGEtPmlzRnJlbmNoU2VjKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKHByZVNlY0lnbm9yZSA8IHNlY0N1cnNvcikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc29ydGtleS5yZXZlcnNlQnl0ZXMocHJlU2VjSWdub3JlLCBzZWNDdXJzb3IpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBzb3J0a2V5LnJldmVyc2VCeXRlcyhzZWNCYXNlLCBzZWNDdXJzb3IpOwogICAgICAgIH0KCiAgICAgICAgc29ydGtleS5zdG9yZUJ5dGVzKHNlY0N1cnNvciwgMCk7CiAgICB9CgogICAgaWYgKGNvbXBhcmVUZXIpCiAgICB7CiAgICAgICAgc29ydGtleS5zdG9yZUJ5dGVzKHRlckN1cnNvciwgMCk7CiAgICB9CgogICAgaWYgKGNvbXBhcmVJZGVudCkKICAgIHsKICAgICAgICBzb3J0a2V5LnN0b3JlVW5pY29kZVN0cmluZyhpZGVudEN1cnNvciwgZGVjb21wKTsKICAgIH0KCiAgICAvLyAgICBEZWJ1Z2dpbmcgLSBwcmludCBvdXQgdGhlIHNvcnRrZXkgWy0tc3JsXQovLyAgICAgIHsKLy8gICAgICAgIGNvbnN0IHVpbnQ4X3QgKmJ5dGVzOwovLyAgICAgICAgaW50MzJfdCB4Y291bnQ7Ci8vICAgICAgICBieXRlcyA9IHNvcnRrZXkuZ2V0Qnl0ZUFycmF5KHhjb3VudCk7Ci8vICAgICAgICAvLyAgICAgIGZwcmludGYoc3RkZXJyLCAiXG5cbi0gIFslMDJYXSBbJTAyWF1cblxuIiwgKGludCkoYnl0ZXNbMF0mMHhGRiksIChpbnQpKGJ5dGVzWzFdJjB4RkYpICk7Ci8vICAgICAgfQoKICAgIHJldHVybiBzb3J0a2V5Owp9CgoKLy8gQnVpbGQgdGhpcyBjb2xsYXRvcidzIHJ1bGUgdGFibGVzIGJhc2VkIG9uIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBydWxlcwovLyBTZWUgdGhlIGJpZyBkaWFncmFtIGF0IHRoZSB0b3Agb2YgdGhpcyBmaWxlIGZvciBhbiBvdmVydmlldyBvZiBob3cgdGhlIHRhYmxlcwovLyBhcmUgb3JnYW5pemVkLgp2b2lkClJ1bGVCYXNlZENvbGxhdG9yOjpidWlsZChjb25zdCBVbmljb2RlU3RyaW5nJiAgIHBhdHRlcm4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiAgICAgIHN0YXR1cykKewogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKQogICAgewogICAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBUaGlzIGFycmF5IG1hcHMgVW5pY29kZSBjaGFyYWN0ZXJzIHRvIHRoZWlyIGNvbGxhdGlvbiBvcmRlcmluZwogICAgZGF0YS0+bWFwcGluZyA9IHVjbXAzMl9vcGVuKFVOTUFQUEVEKTsKCiAgICBpZiAoZGF0YS0+bWFwcGluZy0+ZkJvZ3VzKQogICAgewogICAgICAgIHN0YXR1cyA9IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1I7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIENvbGxhdG9yOjpFQ29sbGF0aW9uU3RyZW5ndGggYVN0cmVuZ3RoID0gQ29sbGF0b3I6OklERU5USUNBTDsKICAgIFVCb29sIGlzU291cmNlID0gVFJVRTsKICAgIGludDMyX3QgaSA9IDA7CiAgICBVbmljb2RlU3RyaW5nIGxhc3RHcm91cENoYXJzOwogICAgVW5pY29kZVN0cmluZyBleHBDaGFyczsKICAgIFVuaWNvZGVTdHJpbmcgZ3JvdXBDaGFyczsKCiAgICBpZiAocGF0dGVybi5sZW5ndGgoKSA9PSAwKQogICAgewogICAgICAgIHN0YXR1cyA9IFVfSU5WQUxJRF9GT1JNQVRfRVJST1I7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIC8vIEJ1aWxkIHRoZSBtZXJnZWQgY29sbGF0aW9uIGVudHJpZXMKICAgIC8vIFNpbmNlIHJ1bGVzIGNhbiBiZSBzcGVjaWZpZWQgaW4gYW55IG9yZGVyIGluIHRoZSBzdHJpbmcKICAgIC8vIChlLmcuICJjICwgQyA8IGQgLCBEIDwgZSAsIEUgLi4uLiBDIDwgQ0giKQogICAgLy8gdGhpcyBzcGxpdHMgYWxsIG9mIHRoZSBydWxlcyBpbiB0aGUgc3RyaW5nIG91dCBpbnRvIHNlcGFyYXRlCiAgICAvLyBvYmplY3RzIGFuZCB0aGVuIHNvcnRzIHRoZW0uICBJbiB0aGUgYWJvdmUgZXhhbXBsZSwgaXQgbWVyZ2VzIHRoZQogICAgLy8gIkMgPCBDSCIgcnVsZSBpbiBqdXN0IGJlZm9yZSB0aGUgIkMgPCBEIiBydWxlLgoKICAgIG1QYXR0ZXJuID0gbmV3IE1lcmdlQ29sbGF0aW9uKHBhdHRlcm4sIGdldERlY29tcG9zaXRpb24oKSwgc3RhdHVzKTsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICB1Y21wMzJfY2xvc2UoZGF0YS0+bWFwcGluZyk7CiAgICAgICAgZGF0YS0+bWFwcGluZyA9IDA7CiAgICAgICAgZGVsZXRlIG1QYXR0ZXJuOwogICAgICAgIG1QYXR0ZXJuID0gMDsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgaW50MzJfdCBvcmRlciA9IDA7CgogICAgLy8gV2FsayB0aHJvdWdoIGVhY2ggZW50cnkKICAgIGZvciAoaSA9IDA7IGkgPCBtUGF0dGVybi0+Z2V0Q291bnQoKTsgKytpKQogICAgewogICAgICAgIGNvbnN0IFBhdHRlcm5FbnRyeSogZW50cnkgPSBtUGF0dGVybi0+Z2V0SXRlbUF0KGkpOwogICAgICAgIGdyb3VwQ2hhcnMucmVtb3ZlKCk7CiAgICAgICAgZXhwQ2hhcnMucmVtb3ZlKCk7CgogICAgICAgIC8vIGlmIGVudHJ5IGlzIHZhbGlkCiAgICAgICAgaWYgKGVudHJ5ICE9IE5VTEwpCiAgICAgICAgewogICAgICAgICAgICBlbnRyeS0+Z2V0Q2hhcnMoZ3JvdXBDaGFycyk7CgogICAgICAgICAgICAvLyBjaGVjayBpZiBmcmVuY2ggc2Vjb25kYXJ5IG5lZWRzIHRvIGJlIHR1cm5lZCBvbgogICAgICAgICAgICBpZiAoKGdyb3VwQ2hhcnMubGVuZ3RoKCkgPiAxKSAmJgogICAgICAgICAgICAgICAgKGdyb3VwQ2hhcnNbZ3JvdXBDaGFycy5sZW5ndGgoKS0oVF9JTlQzMigxKSldID09IDB4MDA0MCkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGRhdGEtPmlzRnJlbmNoU2VjID0gVFJVRTsKICAgICAgICAgICAgICAgIGdyb3VwQ2hhcnMucmVtb3ZlKGdyb3VwQ2hhcnMubGVuZ3RoKCktKFRfSU5UMzIoMSkpKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgb3JkZXIgPSBpbmNyZW1lbnQoKENvbGxhdG9yOjpFQ29sbGF0aW9uU3RyZW5ndGgpZW50cnktPmdldFN0cmVuZ3RoKCksIG9yZGVyKTsKCiAgICAgICAgICAgIGlmIChlbnRyeS0+Z2V0RXh0ZW5zaW9uKGV4cENoYXJzKS5sZW5ndGgoKSAhPSAwKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvLyBlbmNvdW50ZXJlZCBhbiBleHBhbmRpbmcgY2hhcmFjdGVyLCB3aGVyZSBvbmUgY2hhcmFjdGVyIG9uIGlucHV0CiAgICAgICAgICAgICAgICAvLyBleHBhbmRzIHRvIHNldmVyYWwgc29ydCBlbGVtZW50cyAoZS5nLiAn9icgLS0+ICdvJyAnZScpCiAgICAgICAgICAgICAgICBhZGRFeHBhbmRPcmRlcihncm91cENoYXJzLCBleHBDaGFycywgb3JkZXIsIHN0YXR1cyk7CiAgICAgICAgICAgICAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKGdyb3VwQ2hhcnMubGVuZ3RoKCkgPiAxKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvLyBlbmNvdW50ZXJlZCBhIGNvbnRyYWN0aW5nIGNoYXJhY3Rlciwgd2hlcmUgc2V2ZXJhbCBjaGFyYWN0ZXJzIG9uIGlucHV0CiAgICAgICAgICAgICAgICAvLyBjb250cmFjdCBpbnRvIG9uZSBzb3J0IG9yZGVyLiAgRm9yIGV4YW1wbGUsICJjaCIgaXMgdHJlYXRlZCBhcyBhIHNpbmdsZQogICAgICAgICAgICAgICAgLy8gY2hhcmFjdGVyIGluIHRyYWRpdGlvbmFsIFNwYW5pc2ggc29ydGluZy4KICAgICAgICAgICAgICAgIGFkZENvbnRyYWN0T3JkZXIoZ3JvdXBDaGFycywgb3JkZXIsIHN0YXR1cyk7CiAgICAgICAgICAgICAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gTm90aGluZyBvdXQgb2YgdGhlIG9yZGluYXJ5IC0tIG9uZSBjaGFyYWN0ZXIgbWFwcyB0byBvbmUgc29ydCBvcmRlcgogICAgICAgICAgICAgICAgYWRkT3JkZXIoZ3JvdXBDaGFyc1swXSwgb3JkZXIsIHN0YXR1cyk7CiAgICAgICAgICAgICAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIC8vIGFkZCBleHBhbmRpbmcgZW50cmllcyBmb3IgcHJlLWNvbXBvc2VkIGNoYXJhY3RlcnMKICAgIGFkZENvbXBvc2VkQ2hhcnMoKTsKCiAgICAvLyBGaWxsIGluIGFsbCB0aGUgZXhwYW5kaW5nIGNoYXJzIHZhbHVlcwogICAgY29tbWl0KCk7CgogICAgLy8gQ29tcGFjdCB0aGUgZGF0YSBtYXBwaW5nIHRhYmxlCiAgICB1Y21wMzJfY29tcGFjdChkYXRhLT5tYXBwaW5nLCAxKTsKfQoKLyoqCiAqIEFkZCBleHBhbmRpbmcgZW50cmllcyBmb3IgcHJlLWNvbXBvc2VkIHVuaWNvZGUgY2hhcmFjdGVycyBzbyB0aGF0IHRoaXMKICogY29sbGF0b3IgY2FuIGJlIHVzZWQgcmVhc29uYWJseSB3ZWxsIHdpdGggZGVjb21wb3NpdGlvbiB0dXJuZWQgb2ZmLgogKi8KIHZvaWQgUnVsZUJhc2VkQ29sbGF0b3I6OmFkZENvbXBvc2VkQ2hhcnMoKQogewogICAgVW5pY29kZVN0cmluZyBidWY7CiAgICBVRXJyb3JDb2RlIHN0YXR1cyA9IFVfWkVST19FUlJPUjsKCiAgICAvLyBJdGVyYXRlIHRocm91Z2ggYWxsIG9mIHRoZSBwcmUtY29tcG9zZWQgY2hhcmFjdGVycyBpbiBVbmljb2RlCiAgICBDb21wb3NlZENoYXJJdGVyIGl0ZXI7CiAgICBVbmljb2RlU3RyaW5nIGRlY29tcDsKCiAgICB3aGlsZSAoaXRlci5oYXNOZXh0KCkpCiAgICB7CiAgICAgICAgVUNoYXIgYyA9IGl0ZXIubmV4dCgpOwogICAgICAgIAogICAgICAgIGlmIChnZXRDaGFyT3JkZXIoYykgPT0gVU5NQVBQRUQpCiAgICAgICAgewogICAgICAgICAgICAvLyAKICAgICAgICAgICAgLy8gV2UgZG9uJ3QgYWxyZWFkeSBoYXZlIGFuIG9yZGVyaW5nIGZvciB0aGlzIHByZS1jb21wb3NlZCBjaGFyYWN0ZXIuCiAgICAgICAgICAgIC8vCiAgICAgICAgICAgIC8vIEZpcnN0LCBzZWUgaWYgdGhlIGRlY29tcG9zZWQgc3RyaW5nIGlzIGFscmVhZHkgaW4gb3VyCiAgICAgICAgICAgIC8vIHRhYmxlcyBhcyBhIHNpbmdsZSBjb250cmFjdGluZy1zdHJpbmcgb3JkZXJpbmcuCiAgICAgICAgICAgIC8vIElmIHNvLCBqdXN0IG1hcCB0aGUgcHJlY29tcG9zZWQgY2hhcmFjdGVyIHRvIHRoYXQgb3JkZXIuCiAgICAgICAgICAgIC8vCiAgICAgICAgICAgIC8vIFRPRE86IFdoYXQgd2Ugc2hvdWxkIHJlYWxseSBiZSBkb2luZyBoZXJlIGlzIHRyeWluZyB0byBmaW5kIHRoZQogICAgICAgICAgICAvLyBsb25nZXN0IGluaXRpYWwgc3Vic3RyaW5nIG9mIHRoZSBkZWNvbXBvc2l0aW9uIHRoYXQgaXMgcHJlc2VudAogICAgICAgICAgICAvLyBpbiB0aGUgdGFibGVzIGFzIGEgY29udHJhY3RpbmcgY2hhcmFjdGVyIHNlcXVlbmNlLCBhbmQgZmluZCBpdHMKICAgICAgICAgICAgLy8gb3JkZXJpbmcuICBUaGVuIGRvIHRoaXMgcmVjdXJzaXZlbHkgd2l0aCB0aGUgcmVtYWluaW5nIGNoYXJzCiAgICAgICAgICAgIC8vIHNvIHRoYXQgd2UgYnVpbGQgYSBsaXN0IG9mIG9yZGVyaW5ncywgYW5kIGFkZCB0aGF0IGxpc3QgdG8KICAgICAgICAgICAgLy8gdGhlIGV4cGFuc2lvbiB0YWJsZS4gCiAgICAgICAgICAgIC8vIFRoYXQgd291bGQgYmUgbW9yZSBjb3JyZWN0IGJ1dCBhbHNvIHNpZ25pZmljYW50bHkgc2xvd2VyLCBzbwogICAgICAgICAgICAvLyBJJ20gbm90IHRvdGFsbHkgc3VyZSBpdCdzIHdvcnRoIGRvaW5nLgogICAgICAgICAgICAvLwogICAgICAgICAgICBpdGVyLmdldERlY29tcG9zaXRpb24oZGVjb21wKTsKICAgICAgICAgICAgaW50IGNvbnRyYWN0T3JkZXIgPSBnZXRDb250cmFjdE9yZGVyKGRlY29tcCk7CgogICAgICAgICAgICBpZiAoY29udHJhY3RPcmRlciAhPSBVTk1BUFBFRCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYWRkT3JkZXIoYywgY29udHJhY3RPcmRlciwgc3RhdHVzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vCiAgICAgICAgICAgICAgICAvLyBXZSBkb24ndCBoYXZlIGEgY29udHJhY3Rpbmcgb3JkZXJpbmcgZm9yIHRoZSBlbnRpcmUgc3RyaW5nCiAgICAgICAgICAgICAgICAvLyB0aGF0IHJlc3VsdHMgZnJvbSB0aGUgZGVjb21wb3NpdGlvbiwgYnV0IGlmIHdlIGhhdmUgb3JkZXJzCiAgICAgICAgICAgICAgICAvLyBmb3IgZWFjaCBpbmRpdmlkdWFsIGNoYXJhY3Rlciwgd2UgY2FuIGFkZCBhbiBleHBhbmRpbmcKICAgICAgICAgICAgICAgIC8vIHRhYmxlIGVudHJ5IGZvciB0aGUgcHJlLWNvbXBvc2VkIGNoYXJhY3RlciAKICAgICAgICAgICAgICAgIC8vCiAgICAgICAgICAgICAgICBVQm9vbCBhbGxUaGVyZSA9IFRSVUU7CiAgICAgICAgICAgICAgICBpbnQzMl90IGk7CgogICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGRlY29tcC5sZW5ndGgoKTsgaSArPSAxKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmIChnZXRDaGFyT3JkZXIoZGVjb21wW2ldKSA9PSBVTk1BUFBFRCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGFsbFRoZXJlID0gRkFMU0U7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZiAoYWxsVGhlcmUpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgYnVmLnJlbW92ZSgpOwogICAgICAgICAgICAgICAgICAgIGJ1ZiArPSBjOwogICAgICAgICAgICAgICAgICAgIGFkZEV4cGFuZE9yZGVyKGJ1ZiwgZGVjb21wLCBVTk1BUFBFRCwgc3RhdHVzKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQogICAgCi8vIFdoZW4gdGhlIGV4cGFuZGluZyBjaGFyYWN0ZXIgdGFibGVzIGFyZSBidWlsdCBieSBhZGRFeHBhbmRPcmRlciwKLy8gaXQgZG9lc24ndCBrbm93IHdoYXQgdGhlIGZpbmFsIG9yZGVyaW5nIG9mIGVhY2ggY2hhcmFjdGVyCi8vIGluIHRoZSBleHBhbnNpb24gd2lsbCBiZS4gIEluc3RlYWQsIGl0IGp1c3QgcHV0cyB0aGUgcmF3IGNoYXJhY3RlcgovLyBjb2RlIGludG8gdGhlIHRhYmxlLCBhZGRpbmcgQ0hBUklOREVYIGFzIGEgZmxhZy4gIE5vdyB0aGF0IHdlJ3ZlCi8vIGZpbmlzaGVkIGJ1aWxkaW5nIHRoZSBtYXBwaW5nIHRhYmxlLCB3ZSBjYW4gZ28gYmFjayBhbmQgbG9vayB1cAovLyB0aGF0IGNoYXJhY3RlciB0byBzZWUgd2hhdCBpdHMgcmVhbCBjb2xsYXRpb24gb3JkZXIgaXMgYW5kCi8vIHN0aWNrIHRoYXQgaW50byB0aGUgZXhwYW5zaW9uIHRhYmxlLiAgVGhhdCBsZXRzIHVzIGF2b2lkIGRvaW5nCi8vIGEgdHdvLXN0YWdlIGxvb2t1cCBsYXRlci4KCnZvaWQKUnVsZUJhc2VkQ29sbGF0b3I6OmNvbW1pdCgpCnsKICAgIC8vIGlmIHRoZXJlIGFyZSBhbnkgZXhwYW5kaW5nIGNoYXJhY3RlcnMKICAgIGlmIChkYXRhLT5leHBhbmRUYWJsZSAhPSBOVUxMKQogICAgewogICAgICAgIGludDMyX3QgaTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgZGF0YS0+ZXhwYW5kVGFibGUtPnNpemUoKTsgaSArPSAxKQogICAgICAgIHsKICAgICAgICAgICAgVmVjdG9yT2ZJbnQqIHZhbHVlTGlzdCA9IGRhdGEtPmV4cGFuZFRhYmxlLT5hdChpKTsKICAgICAgICAgICAgaW50MzJfdCBqOwogICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgdmFsdWVMaXN0LT5zaXplKCk7IGorKykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gZm91bmQgYSBleHBhbmRpbmcgY2hhcmFjdGVyCiAgICAgICAgICAgICAgICAvLyB0aGUgZXhwYW5kaW5nIGNoYXIgdmFsdWUgaXMgbm90IGZpbGxlZCBpbiB5ZXQKICAgICAgICAgICAgICAgIGlmICgodmFsdWVMaXN0LT5hdChqKSA8IEVYUEFORENIQVJJTkRFWCkgJiYKICAgICAgICAgICAgICAgICAgICAodmFsdWVMaXN0LT5hdChqKSA+IENIQVJJTkRFWCkpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgLy8gR2V0IHRoZSByZWFsIHZhbHVlcyBmb3IgdGhlIG5vbi1maWxsZWQgZW50cnkKICAgICAgICAgICAgICAgICAgICBVQ2hhciBjaCA9IChVQ2hhcikodmFsdWVMaXN0LT5hdChqKSAtIENIQVJJTkRFWCk7CiAgICAgICAgICAgICAgICAgICAgaW50MzJfdCByZWFsVmFsdWUgPSB1Y21wMzJfZ2V0KGRhdGEtPm1hcHBpbmcsIGNoKTsKCiAgICAgICAgICAgICAgICAgICAgaWYgKHJlYWxWYWx1ZSA9PSBVTk1BUFBFRCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSByZWFsIHZhbHVlIGlzIHN0aWxsIHVubWFwcGVkLCBtYXliZSBpdCdzaWdub3JhYmxlCiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlTGlzdC0+YXRQdXQoaiwgSUdOT1JBQkxFTUFTSyAmIGNoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgLy8gZmlsbCBpbiB0aGUgdmFsdWUKICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZUxpc3QtPmF0UHV0KGosIHJlYWxWYWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogfQoKLyoqCiAqICBJbmNyZW1lbnQgb2YgdGhlIGxhc3Qgb3JkZXIgYmFzZWQgb24gdGhlIGNvbXBhcmlzb24gbGV2ZWwuCiAqLwppbnQzMl90ClJ1bGVCYXNlZENvbGxhdG9yOjppbmNyZW1lbnQoQ29sbGF0b3I6OkVDb2xsYXRpb25TdHJlbmd0aCBhU3RyZW5ndGgsIGludDMyX3QgbGFzdFZhbHVlKQp7CiAgICBzd2l0Y2goYVN0cmVuZ3RoKQogICAgewogICAgY2FzZSBDb2xsYXRvcjo6UFJJTUFSWToKICAgICAgICAvLyBpbmNyZW1lbnQgcHJpYW1yeSBvcmRlciAgYW5kIG1hc2sgb2ZmIHNlY29uZGFyeSBhbmQgdGVydGlhcnkgZGlmZmVyZW5jZQogICAgICAgIGxhc3RWYWx1ZSArPSBQUklNQVJZT1JERVJJTkNSRU1FTlQ7CiAgICAgICAgbGFzdFZhbHVlICY9IFBSSU1BUllPUkRFUk1BU0s7CiAgICAgICAgaXNPdmVySWdub3JlID0gVFJVRTsKICAgICAgICBicmVhazsKCiAgICBjYXNlIENvbGxhdG9yOjpTRUNPTkRBUlk6CiAgICAgICAgLy8gaW5jcmVtZW50IHNlY29uZGFyeSBvcmRlciBhbmQgbWFzayBvZmYgdGVydGlhcnkgZGlmZmVyZW5jZQogICAgICAgIGxhc3RWYWx1ZSArPSBTRUNPTkRBUllPUkRFUklOQ1JFTUVOVDsKICAgICAgICBsYXN0VmFsdWUgJj0gU0VDT05EQVJZRElGRkVSRU5DRU9OTFk7CgogICAgICAgIC8vIHJlY29yZCBtYXggIyBvZiBpZ25vcmFibGUgY2hhcnMgd2l0aCBzZWNvbmRhcnkgZGlmZmVyZW5jZQogICAgICAgIGlmIChpc092ZXJJZ25vcmUgPT0gRkFMU0UpCiAgICAgICAgewogICAgICAgICAgICBkYXRhLT5tYXhTZWNPcmRlciArPSAxOwogICAgICAgIH0KICAgICAgICBicmVhazsKCiAgICBjYXNlIENvbGxhdG9yOjpURVJUSUFSWToKICAgICAgICAvLyBpbmNyZW1lbnQgdGVydGlhcnkgb3JkZXIKICAgICAgICBsYXN0VmFsdWUgKz0gVEVSVElBUllPUkRFUklOQ1JFTUVOVDsKCiAgICAgICAgLy8gcmVjb3JkIG1heCAjIG9mIGlnbm9yYWJsZSBjaGFycyB3aXRoIHRlcnRpYXJ5IGRpZmZlcmVuY2UKICAgICAgICBpZiAoaXNPdmVySWdub3JlID09IEZBTFNFKQogICAgICAgIHsKICAgICAgICAgICAgZGF0YS0+bWF4VGVyT3JkZXIgKz0gMTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CgogIC8vIGNhc2UgSURFTlRJQ0FMPyAgCiAgICB9CgogICAgcmV0dXJuIGxhc3RWYWx1ZTsKfQoKLy8gQWRkcyBhIGNoYXJhY3RlciBhbmQgaXRzIGRlc2lnbmF0ZWQgb3JkZXIgaW50byB0aGUgY29sbGF0aW9uIHRhYmxlLgovLyBUaGlzIGlzIHRoZSBzaW1wbGUgY2FzZSwgd2l0aCBubyBleHBhbnNpb24gb3IgY29udHJhY3Rpb24Kdm9pZApSdWxlQmFzZWRDb2xsYXRvcjo6YWRkT3JkZXIoVUNoYXIgY2gsCiAgICAgICAgICAgICAgICAgICAgICAgICBpbnQzMl90IGFuT3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgLy8gdHJ5IHRvIGZpbmQgdGhlIG9yZGVyIG9mIHRoZSBjaGFyIGluIHRoZSBtYXBwaW5nIHRhYmxlCiAgICBpbnQzMl90IG9yZGVyID0gdWNtcDMyX2dldChkYXRhLT5tYXBwaW5nLCBjaCk7CgogICAgaWYgKG9yZGVyID49IENPTlRSQUNUQ0hBUklOREVYKQogICAgewogICAgICAgIC8vIFRoZXJlJ3MgYWxyZWFkeSBhbiBlbnRyeSBmb3IgdGhpcyBjaGFyYWN0ZXIgdGhhdCBwb2ludHMgdG8gYSBjb250cmFjdGluZwogICAgICAgIC8vIGNoYXJhY3RlciB0YWJsZS4gIEluc3RlYWQgb2YgYWRkaW5nIHRoZSBjaGFyYWN0ZXIgZGlyZWN0bHkgdG8gdGhlIG1hcHBpbmcKICAgICAgICAvLyB0YWJsZSwgd2UgbXVzdCBhZGQgaXQgdG8gdGhlIGNvbnRyYWN0IHRhYmxlIGluc3RlYWQuCiAgICAgICAga2V5LnJlbW92ZSgpOwogICAgICAgIGtleSArPSBjaDsKICAgICAgICBpZiAoa2V5LmlzQm9ndXMoKSkKICAgICAgICB7CiAgICAgICAgICAgIHN0YXR1cyA9IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1I7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIGFkZENvbnRyYWN0T3JkZXIoa2V5LCBhbk9yZGVyLCBzdGF0dXMpOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIC8vIGFkZCB0aGUgZW50cnkgdG8gdGhlIG1hcHBpbmcgdGFibGUsIHRoZSBzYW1lIGxhdGVyIGVudHJ5IHJlcGxhY2VzIHRoZSBwcmV2aW91cyBvbmUKICAgICAgICB1Y21wMzJfc2V0KGRhdGEtPm1hcHBpbmcsIGNoLCBhbk9yZGVyKTsKICAgIH0KfQoKLy8gQWRkIGFuIGV4cGFuZGluZy1jaGFyYWN0ZXIgZW50cnkgdG8gdGhlIHRhYmxlLgp2b2lkClJ1bGVCYXNlZENvbGxhdG9yOjphZGRFeHBhbmRPcmRlciggIGNvbnN0ICAgVW5pY29kZVN0cmluZyYgY29udHJhY3RDaGFycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCAgIFVuaWNvZGVTdHJpbmcmIGV4cGFuZENoYXJzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludDMyX3QgYW5PcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgLy8gQ3JlYXRlIGFuIGV4cGFuc2lvbiB0YWJsZSBlbnRyeQogICAgaW50MzJfdCB0YWJsZUluZGV4ID0gYWRkRXhwYW5zaW9uKGFuT3JkZXIsIGV4cGFuZENoYXJzKTsKICAgIAogICAgLy8gQW5kIGFkZCBpdHMgaW5kZXggaW50byB0aGUgbWFpbiBtYXBwaW5nIHRhYmxlCiAgICBpZiAoY29udHJhY3RDaGFycy5sZW5ndGgoKSA+IDEpCiAgICB7CiAgICAgICAgYWRkQ29udHJhY3RPcmRlcihjb250cmFjdENoYXJzLCB0YWJsZUluZGV4LCBzdGF0dXMpOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIGFkZE9yZGVyKGNvbnRyYWN0Q2hhcnNbMF0sIHRhYmxlSW5kZXgsIHN0YXR1cyk7CiAgICB9Cn0KCmludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OmFkZEV4cGFuc2lvbihpbnQzMl90IGFuT3JkZXIsIGNvbnN0IFVuaWNvZGVTdHJpbmcgJmV4cGFuZENoYXJzKQp7CiAgICBpZiAoZGF0YS0+ZXhwYW5kVGFibGUgPT0gTlVMTCkKICAgIHsKICAgICAgICBkYXRhLT5leHBhbmRUYWJsZSA9IG5ldyBWZWN0b3JPZlBUb0V4cGFuZFRhYmxlKCk7CgogICAgICAgIGlmIChkYXRhLT5leHBhbmRUYWJsZSA9PSBOVUxMKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQogICAgfQogICAgCiAgICAvLyBJZiBhbk9yZGVyIGlzIHZhbGlkLCB3ZSB3YW50IHRvIGFkZCBpdCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaXN0CiAgICBpbnQzMl90IG9mZnNldCA9IChhbk9yZGVyID09IFVOTUFQUEVEKSA/IDAgOiAxOwogICAgCiAgICBWZWN0b3JPZkludCAqdmFsdWVMaXN0ID0gbmV3IFZlY3Rvck9mSW50KGV4cGFuZENoYXJzLmxlbmd0aCgpICsgb2Zmc2V0KTsKCiAgICBpZiAob2Zmc2V0ID09IDEpCiAgICB7CiAgICAgICAgdmFsdWVMaXN0LT5hdFB1dCgwLCBhbk9yZGVyKTsKICAgIH0KCiAgICBpbnQzMl90IGk7CiAgICBmb3IgKGkgPSAwOyBpIDwgZXhwYW5kQ2hhcnMubGVuZ3RoKCk7IGkgKz0gMSkKICAgIHsKICAgICAgICBVQ2hhciBjaCA9IGV4cGFuZENoYXJzW2ldOwogICAgICAgIGludDMyX3QgbWFwVmFsdWUgPSBnZXRDaGFyT3JkZXIoY2gpOwogICAgICAgIAogICAgICAgIGlmIChtYXBWYWx1ZSAhPSBVTk1BUFBFRCkKICAgICAgICB7CiAgICAgICAgICAgIHZhbHVlTGlzdC0+YXRQdXQoaSArIG9mZnNldCwgbWFwVmFsdWUpOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICAvLyBjYW4ndCBmaW5kIGl0IGluIHRoZSB0YWJsZSwgd2lsbCBiZSBmaWxsZWQgaW4gYnkgY29tbWl0KCkuCiAgICAgICAgICAgIHZhbHVlTGlzdC0+YXRQdXQoaSArIG9mZnNldCwgQ0hBUklOREVYICsgKGludDMyX3QpY2gpOwogICAgICAgIH0KICAgIH0KCiAgICAvLyBBZGQgdGhlIGV4cGFuZGluZyBjaGFyIGxpc3QgaW50byB0aGUgZXhwYW5zaW9uIHRhYmxlLgogICAgaW50MzJfdCB0YWJsZUluZGV4ID0gRVhQQU5EQ0hBUklOREVYICsgZGF0YS0+ZXhwYW5kVGFibGUtPnNpemUoKTsKICAgIGRhdGEtPmV4cGFuZFRhYmxlLT5hdFB1dChkYXRhLT5leHBhbmRUYWJsZS0+c2l6ZSgpLCB2YWx1ZUxpc3QpOwogICAgCiAgICByZXR1cm4gdGFibGVJbmRleDsKfQoKLy8gQWRkIGEgc3RyaW5nIG9mIGNoYXJhY3RlcnMgdGhhdCBjb250cmFjdHMgaW50byBhIHNpbmdsZSBvcmRlcmluZy4Kdm9pZApSdWxlQmFzZWRDb2xsYXRvcjo6YWRkQ29udHJhY3RPcmRlcihjb25zdCAgIFVuaWNvZGVTdHJpbmcmIGdyb3VwQ2hhcnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludDMyX3QgYW5PcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUJvb2wgZndkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVRXJyb3JDb2RlJiBzdGF0dXMpCnsKICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzKSkKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKGRhdGEtPmNvbnRyYWN0VGFibGUgPT0gTlVMTCkKICAgIHsKICAgICAgICBkYXRhLT5jb250cmFjdFRhYmxlID0gbmV3IFZlY3Rvck9mUFRvQ29udHJhY3RUYWJsZSgpOwogICAgICAgIGlmIChkYXRhLT5jb250cmFjdFRhYmxlLT5pc0JvZ3VzKCkpCiAgICAgICAgewogICAgICAgICAgICBkZWxldGUgZGF0YS0+Y29udHJhY3RUYWJsZTsKICAgICAgICAgICAgZGF0YS0+Y29udHJhY3RUYWJsZSA9IE5VTEw7CiAgICAgICAgICAgIHN0YXR1cyA9IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1I7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICB9CgogICAgLy8gU2VlIGlmIHRoZSBpbml0aWFsIGNoYXJhY3RlciBvZiB0aGUgc3RyaW5nIGFscmVhZHkgaGFzIGEgY29udHJhY3QgdGFibGUuCiAgICAvLyBlLmcuIGZvciAiY2giLCBsb29rIGZvciAnYycuCiAgICBpbnQzMl90IGVudHJ5ID0gdWNtcDMyX2dldChkYXRhLT5tYXBwaW5nLCBncm91cENoYXJzWzBdKTsKICAgIFZlY3Rvck9mUFRvQ29udHJhY3RFbGVtZW50ICplbnRyeVRhYmxlID0gZ2V0Q29udHJhY3RWYWx1ZXMoZW50cnkgLSBDT05UUkFDVENIQVJJTkRFWCk7CgogICAgaWYgKGVudHJ5VGFibGUgPT0gTlVMTCkKICAgIHsKICAgICAgICAvLyBXZSBuZWVkIHRvIGNyZWF0ZSBhIG5ldyB0YWJsZSBvZiBjb250cmFjdCBlbnRyaWVzIGZvciB0aGlzIGJhc2UgY2hhcgogICAgICAgIGludDMyX3QgdGFibGVJbmRleCA9IENPTlRSQUNUQ0hBUklOREVYICsgZGF0YS0+Y29udHJhY3RUYWJsZS0+c2l6ZSgpOwogICAgICAgIEVudHJ5UGFpciAqcGFpciA9IE5VTEw7CiAgICAgICAgVW5pY29kZVN0cmluZyBzdWJzdHJpbmc7CgogICAgICAgIGVudHJ5VGFibGUgPSBuZXcgVmVjdG9yT2ZQVG9Db250cmFjdEVsZW1lbnQoKTsKICAgICAgICBpZiAoZW50cnlUYWJsZS0+aXNCb2d1cygpKQogICAgICAgIHsKICAgICAgICAgICAgZGVsZXRlIGVudHJ5VGFibGU7CiAgICAgICAgICAgIGRlbGV0ZSBkYXRhLT5jb250cmFjdFRhYmxlOwogICAgICAgICAgICBkYXRhLT5jb250cmFjdFRhYmxlID0gTlVMTDsKICAgICAgICAgICAgc3RhdHVzID0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUjsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgZGF0YS0+Y29udHJhY3RUYWJsZS0+YXRQdXQoZGF0YS0+Y29udHJhY3RUYWJsZS0+c2l6ZSgpLCBlbnRyeVRhYmxlKTsKICAgICAgICBpZiAoZGF0YS0+Y29udHJhY3RUYWJsZS0+aXNCb2d1cygpKQogICAgICAgIHsKICAgICAgICAgICAgZGVsZXRlIGVudHJ5VGFibGU7CiAgICAgICAgICAgIGRlbGV0ZSBkYXRhLT5jb250cmFjdFRhYmxlOwogICAgICAgICAgICBkYXRhLT5jb250cmFjdFRhYmxlID0gTlVMTDsKICAgICAgICAgICAgc3RhdHVzID0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUjsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICAgICAgCgogICAgICAgIC8vIEFkZCB0aGUgaW5pdGlhbCBjaGFyYWN0ZXIncyBjdXJyZW50IG9yZGVyaW5nIGZpcnN0LiB0aGVuCiAgICAgICAgLy8gdXBkYXRlIGl0cyBtYXBwaW5nIHRvIHBvaW50IHRvIHRoaXMgY29udHJhY3QgdGFibGUKICAgICAgICBncm91cENoYXJzLmV4dHJhY3QoMCwgMSwgc3Vic3RyaW5nKTsKICAgICAgICBpZiAoc3Vic3RyaW5nLmlzQm9ndXMoKSkKICAgICAgICB7CiAgICAgICAgICAgIGRlbGV0ZSBlbnRyeVRhYmxlOwogICAgICAgICAgICBkZWxldGUgZGF0YS0+Y29udHJhY3RUYWJsZTsKICAgICAgICAgICAgZGF0YS0+Y29udHJhY3RUYWJsZSA9IE5VTEw7CiAgICAgICAgICAgIHN0YXR1cyA9IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1I7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHBhaXIgPSBuZXcgRW50cnlQYWlyKHN1YnN0cmluZywgZW50cnkpOwoKICAgICAgICBlbnRyeVRhYmxlLT5hdFB1dCgwLCBwYWlyKTsKICAgICAgICBpZiAoZW50cnlUYWJsZS0+aXNCb2d1cygpKQogICAgICAgIHsKICAgICAgICAgICAgZGVsZXRlIGVudHJ5VGFibGU7CiAgICAgICAgICAgIGRlbGV0ZSBkYXRhLT5jb250cmFjdFRhYmxlOwogICAgICAgICAgICBkYXRhLT5jb250cmFjdFRhYmxlID0gTlVMTDsKICAgICAgICAgICAgc3RhdHVzID0gVV9NRU1PUllfQUxMT0NBVElPTl9FUlJPUjsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgdWNtcDMyX3NldChkYXRhLT5tYXBwaW5nLCBncm91cENoYXJzWzBdLCB0YWJsZUluZGV4KTsKICAgIH0KCiAgICAvLyBOb3cgYWRkIChvciByZXBsYWNlKSB0aGlzIHN0cmluZyBpbiB0aGUgdGFibGUKICAgIGludDMyX3QgaW5kZXggPSBnZXRFbnRyeShlbnRyeVRhYmxlLCBncm91cENoYXJzLCBmd2QpOwoKICAgIGlmIChpbmRleCAhPSBVTk1BUFBFRCkKICAgIHsKICAgICAgICBFbnRyeVBhaXIgKnBhaXIgPSAoRW50cnlQYWlyICopIGVudHJ5VGFibGUtPmF0KGluZGV4KTsKICAgICAgICBwYWlyLT52YWx1ZSA9IGFuT3JkZXI7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgRW50cnlQYWlyICpwYWlyID0gbmV3IEVudHJ5UGFpcihncm91cENoYXJzLCBhbk9yZGVyLCBmd2QpOwoKICAgICAgICBlbnRyeVRhYmxlLT5hdFB1dChlbnRyeVRhYmxlLT5zaXplKCksIHBhaXIpOwogICAgfQogICAgCiAgICAvLyBJZiB0aGlzIHdhcyBhIGZvcndhcmQgbWFwcGluZyBmb3IgYSBjb250cmFjdGluZyBzdHJpbmcsIGFsc28gYWRkIGEKICAgIC8vIHJldmVyc2UgbWFwcGluZyBmb3IgaXQsIHNvIHRoYXQgQ29sbGF0aW9uRWxlbWVudEl0ZXJhdG9yOjpwcmV2aW91cwogICAgLy8gY2FuIHdvcmsgcmlnaHQKICAgIGlmIChmd2QpCiAgICB7CiAgICAgICAgVW5pY29kZVN0cmluZyByZXZlcnNlKGdyb3VwQ2hhcnMpOwoKICAgICAgICBpZiAocmV2ZXJzZS5pc0JvZ3VzKCkpCiAgICAgICAgewogICAgICAgICAgICBkZWxldGUgZW50cnlUYWJsZTsKICAgICAgICAgICAgZGVsZXRlIGRhdGEtPmNvbnRyYWN0VGFibGU7CiAgICAgICAgICAgIGRhdGEtPmNvbnRyYWN0VGFibGUgPSBOVUxMOwogICAgICAgICAgICBzdGF0dXMgPSBVX01FTU9SWV9BTExPQ0FUSU9OX0VSUk9SOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBhZGRDb250cmFjdE9yZGVyKHJldmVyc2UucmV2ZXJzZSgpLCBhbk9yZGVyLCBGQUxTRSwgc3RhdHVzKTsKICAgIH0KfQoKLyoqCiAqIElmIHRoZSBnaXZlbiBzdHJpbmcgaGFzIGJlZW4gc3BlY2lmaWVkIGFzIGEgY29udHJhY3Rpbmcgc3RyaW5nCiAqIGluIHRoaXMgY29sbGF0aW9uIHRhYmxlLCByZXR1cm4gaXRzIG9yZGVyaW5nLgogKiBPdGhlcndpc2UgcmV0dXJuIFVOTUFQUEVELgogKi8KIGludDMyX3QgUnVsZUJhc2VkQ29sbGF0b3I6OmdldENvbnRyYWN0T3JkZXIoY29uc3QgVW5pY29kZVN0cmluZyAmZ3JvdXBDaGFycykgY29uc3QKewogICAgaW50MzJfdCByZXN1bHQgPSBVTk1BUFBFRDsKCiAgICBpZiAoZGF0YS0+Y29udHJhY3RUYWJsZSAhPSBOVUxMKQogICAgewogICAgICAgIFZlY3Rvck9mUFRvQ29udHJhY3RFbGVtZW50ICplbnRyeVRhYmxlID0gZ2V0Q29udHJhY3RWYWx1ZXMoZ3JvdXBDaGFyc1swXSk7CgogICAgICAgIGlmIChlbnRyeVRhYmxlICE9IE5VTEwpCiAgICAgICAgewogICAgICAgICAgICBpbnQzMl90IGluZGV4ID0gZ2V0RW50cnkoZW50cnlUYWJsZSwgZ3JvdXBDaGFycywgVFJVRSk7CgogICAgICAgICAgICBpZiAoaW5kZXggIT0gVU5NQVBQRUQpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIEVudHJ5UGFpciAqcGFpciA9IGVudHJ5VGFibGUtPmF0KGluZGV4KTsKCiAgICAgICAgICAgICAgICByZXN1bHQgPSBwYWlyLT52YWx1ZTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcmVzdWx0Owp9CgppbnQzMl90IFJ1bGVCYXNlZENvbGxhdG9yOjpnZXRDaGFyT3JkZXIoVUNoYXIgY2gpIGNvbnN0CnsKICAgIGludDMyX3Qgb3JkZXIgPSB1Y21wMzJfZ2V0KGRhdGEtPm1hcHBpbmcsIGNoKTsKICAgIAogICAgaWYgKG9yZGVyID49IENPTlRSQUNUQ0hBUklOREVYKQogICAgewogICAgICAgIFZlY3Rvck9mUFRvQ29udHJhY3RFbGVtZW50ICpncm91cExpc3QgPSBnZXRDb250cmFjdFZhbHVlcyhvcmRlciAtIENPTlRSQUNUQ0hBUklOREVYKTsKICAgICAgICBFbnRyeVBhaXIgKnBhaXIgPSBncm91cExpc3QtPmF0KDApOwoKICAgICAgICBvcmRlciA9IHBhaXItPnZhbHVlOwogICAgfQoKICAgIHJldHVybiBvcmRlcjsKfQogICAgCi8vIENyZWF0ZSBhIGhhc2ggY29kZSBmb3IgdGhpcyBjb2xsYXRpb24uICBKdXN0IGhhc2ggdGhlIG1haW4gcnVsZSB0YWJsZSAtLQovLyB0aGF0IHNob3VsZCBiZSBnb29kIGVub3VnaCBmb3IgYWxtb3N0IGFueSB1c2UuCmludDMyX3QKUnVsZUJhc2VkQ29sbGF0b3I6Omhhc2hDb2RlKCkgY29uc3QKewogICAgaW50MzJfdCAgICAgICAgIHZhbHVlID0gMDsKICAgIGludDMyX3QgICAgICAgICBjOwogICAgaW50MzJfdCAgICAgICAgIGNvdW50ID0gZ2V0UnVsZXMoKS5sZW5ndGgoKTsKICAgIFVUZXh0T2Zmc2V0ICAgICAgcG9zID0gY291bnQgLSAxOwoKICAgIGlmIChjb3VudCA+IDY0KQogICAgewogICAgICAgIGNvdW50ID0gNjQ7IC8vIG9ubHkgaGFzaCB1cHRvIGxpbWl0CiAgICB9CgogICAgaW50MTZfdCBpID0gMDsKCiAgICB3aGlsZSAoaSA8IGNvdW50KQogICAgewogICAgICAgIGMgPSBkYXRhLT5ydWxlVGFibGVbcG9zXTsKICAgICAgICB2YWx1ZSA9ICgodmFsdWUgPDwgKGMgJiAweDBmKSkgXiAoYyA8PCA4KSkgKyAoYyBeIHZhbHVlKTsKICAgICAgICBpICs9IDE7CiAgICAgICAgcG9zIC09IDE7CiAgICB9CgogICAgaWYgKHZhbHVlID09IDApCiAgICB7CiAgICAgICAgdmFsdWUgPSAxOwogICAgfQoKICAgIHJldHVybiB2YWx1ZTsKfQoKLy8gZmluZCB0aGUgY29udHJhY3RpbmcgY2hhciBlbnRyeSBpbiB0aGUgbGlzdAppbnQzMl90ClJ1bGVCYXNlZENvbGxhdG9yOjpnZXRFbnRyeShWZWN0b3JPZlBUb0NvbnRyYWN0RWxlbWVudCogbGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFVuaWNvZGVTdHJpbmcmIG5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICBVQm9vbCBmd2QpCnsKICAgIGludDMyX3QgaTsKCiAgICBpZiAobGlzdCAhPSBOVUxMKQogICAgewogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0LT5zaXplKCk7IGkgKz0gMSkKICAgICAgICB7CiAgICAgICAgICAgIEVudHJ5UGFpciAqcGFpciA9IGxpc3QtPmF0KGkpOwoKICAgICAgICAgICAgaWYgKChwYWlyICE9IE5VTEwpICYmIChwYWlyLT5md2QgPT0gZndkKSAmJiAocGFpci0+ZW50cnlOYW1lID09IG5hbWUpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXR1cm4gaTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gUnVsZUJhc2VkQ29sbGF0b3I6OlVOTUFQUEVEOwp9CgovLyBsb29rIGZvciB0aGUgY29udHJhY3RpbmcgbGlzdCBlbnRyeSB3aXRoIHRoZSBiZWdpbm5pbmcgY2hhcgpWZWN0b3JPZlBUb0NvbnRyYWN0RWxlbWVudCoKUnVsZUJhc2VkQ29sbGF0b3I6OmdldENvbnRyYWN0VmFsdWVzKFVDaGFyIGNoKSBjb25zdAp7CiAgICBpbnQzMl90IGluZGV4ID0gdWNtcDMyX2dldChkYXRhLT5tYXBwaW5nLCBjaCk7CiAgICByZXR1cm4gZ2V0Q29udHJhY3RWYWx1ZXMoaW5kZXggLSBDT05UUkFDVENIQVJJTkRFWCk7Cn0KCi8vIGxvb2sgZm9yIHRoZSBjb250cmFjdGluZyBsaXN0IGVudHJ5IHdpdGggdGhlIGluZGV4ClZlY3Rvck9mUFRvQ29udHJhY3RFbGVtZW50KgpSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0Q29udHJhY3RWYWx1ZXMoaW50MzJfdCAgICBpbmRleCkgY29uc3QKewogICAgaWYgKGRhdGEtPmNvbnRyYWN0VGFibGUgIT0gTlVMTCkKICAgIHsKICAgICAgICBpZiAoaW5kZXggPj0gMCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBkYXRhLT5jb250cmFjdFRhYmxlLT5hdChpbmRleCk7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIE5VTEw7Cn0KCi8qKgogICogUmV0dXJuIHRoZSBtYXhpbXVtIGxlbmd0aCBvZiBhbnkgZXhwYW5zaW9uIHNlcXVlbmNlcyB0aGF0IGVuZAogICogd2l0aCB0aGUgc3BlY2lmaWVkIGNvbXBhcmlzb24gb3JkZXIuCiAgKgogICogQHBhcmFtIG9yZGVyIGEgY29sbGF0aW9uIG9yZGVyIHJldHVybmVkIGJ5IHByZXZpb3VzIG9yIG5leHQuCiAgKiBAcmV0dXJuIHRoZSBtYXhpbXVtIGxlbmd0aCBvZiBhbnkgZXhwYW5zaW9uIHNldWVuY2VzIGVuZGluZwogICogICAgICAgICB3aXRoIHRoZSBzcGVjaWZpZWQgb3JkZXIuCiAgKgogICogQHNlZSBDb2xsYXRpb25FbGVtZW50SXRlcmF0b3IjZ2V0TWF4RXhwYW5zaW9uCiAgKi8KaW50MzJfdCBSdWxlQmFzZWRDb2xsYXRvcjo6Z2V0TWF4RXhwYW5zaW9uKGludDMyX3Qgb3JkZXIpIGNvbnN0CnsKICAgIGludDMyX3QgcmVzdWx0ID0gMTsKICAgIAogICAgaWYgKGRhdGEtPmV4cGFuZFRhYmxlICE9IE5VTEwpCiAgICB7CiAgICAgICAgLy8gUmlnaHQgbm93IHRoaXMgZG9lcyBhIGxpbmVhciBzZWFyY2ggdGhyb3VnaCB0aGUgZW50aXJlCiAgICAgICAgLy8gZXhwYW5kc2lvbiB0YWJsZS4gIElmIGEgY29sbGF0b3IgaGFkIGEgbGFyZ2UgbnVtYmVyIG9mIGV4cGFuc2lvbnMsCiAgICAgICAgLy8gdGhpcyBjb3VsZCBjYXVzZSBhIHBlcmZvcm1hbmNlIHByb2JsZW0sIGJ1dCBpbiBwcmFjdGljZSB0aGF0CiAgICAgICAgLy8gcmFyZWx5IGhhcHBlbnMKICAgICAgICBpbnQzMl90IGk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGRhdGEtPmV4cGFuZFRhYmxlLT5zaXplKCk7IGkgKz0gMSkKICAgICAgICB7CiAgICAgICAgICAgIFZlY3Rvck9mSW50ICp2YWx1ZUxpc3QgPSBkYXRhLT5leHBhbmRUYWJsZS0+YXQoaSk7CiAgICAgICAgICAgIGludDMyX3QgbGVuZ3RoID0gdmFsdWVMaXN0LT5zaXplKCk7CiAgICAgICAgICAgIAogICAgICAgICAgICBpZiAobGVuZ3RoID4gcmVzdWx0ICYmIHZhbHVlTGlzdC0+YXQobGVuZ3RoLTEpID09IG9yZGVyKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXN1bHQgPSBsZW5ndGg7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJlc3VsdDsKfQogICAgCi8qKgogKiAgR2V0IHRoZSBlbnRyeSBvZiBoYXNoIHRhYmxlIG9mIHRoZSBleHBhbmRpbmcgc3RyaW5nIGluIHRoZSBjb2xsYXRpb24KICogIHRhYmxlLgogKiAgQHBhcmFtIG9mZnNldCB0aGUgaW5kZXggb2YgdGhlIGV4cGFuZGluZyBzdHJpbmcgdmFsdWUgbGlzdAogKi8KVmVjdG9yT2ZJbnQgKlJ1bGVCYXNlZENvbGxhdG9yOjpnZXRFeHBhbmRWYWx1ZUxpc3QoaW50MzJfdCBvcmRlcikgY29uc3QKewogICAgcmV0dXJuIGRhdGEtPmV4cGFuZFRhYmxlLT5hdChvcmRlciAtIEVYUEFORENIQVJJTkRFWCk7Cn0KCgoKdm9pZCBSdWxlQmFzZWRDb2xsYXRvclN0cmVhbWVyOjpzdHJlYW1JbihSdWxlQmFzZWRDb2xsYXRvciogY29sbGF0b3IsIFVNZW1vcnlTdHJlYW0qIGlzKQp7CiAgICBpZiAoIXVwcnZfbXN0cm1fZXJyb3IoaXMpKQogICAgewogICAgICAgIC8vIENoZWNrIHRoYXQgdGhpcyBpcyB0aGUgY29ycmVjdCBmaWxlIHR5cGUKICAgICAgICBpbnQxNl90IGlkOwoKICAgICAgICB1cHJ2X21zdHJtX3JlYWQoaXMsICZpZCwgc2l6ZW9mKGlkKSk7CiAgICAgICAgaWYgKGlkICE9IGNvbGxhdG9yLT5GSUxFSUQpCiAgICAgICAgewogICAgICAgICAgICAvLyBUaGlzIGlzbid0IHRoZSByaWdodCB0eXBlIG9mIGZpbGUuICBNYXJrIHRoZSBpb3MKICAgICAgICAgICAgLy8gYXMgZmFpbGluZyBhbmQgcmV0dXJuLgogICAgICAgICAgICB1cHJ2X21zdHJtX3NldEVycm9yKGlzKTsgLy8gZm9yY2UgdGhlIHN0cmVhbSB0byBzZXQgaXRzIGVycm9yIGZsYWcKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgLy8gU3RyZWFtIGluIGxhcmdlIG9iamVjdHMKICAgICAgICBjaGFyIGlzTnVsbDsKCiAgICAgICAgdXBydl9tc3RybV9yZWFkKGlzLCAmaXNOdWxsLCBzaXplb2YoaXNOdWxsKSk7CiAgICAgICAgaWYgKGlzTnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGRlbGV0ZSBjb2xsYXRvci0+ZGF0YTsKICAgICAgICAgICAgY29sbGF0b3ItPmRhdGEgPSBOVUxMOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBpZiAoY29sbGF0b3ItPmRhdGEgPT0gTlVMTCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgY29sbGF0b3ItPmRhdGEgPSBuZXcgVGFibGVDb2xsYXRpb25EYXRhOwogICAgICAgICAgICB9CiAgICAgICAgICAgIAogICAgICAgICAgICBjb2xsYXRvci0+ZGF0YS0+c3RyZWFtSW4oaXMpOwogICAgICAgICAgICBpZiAoY29sbGF0b3ItPmRhdGEtPmlzQm9ndXMoKSkgewogICAgICAgICAgICAgICAgdXBydl9tc3RybV9zZXRFcnJvcihpcyk7IC8vIGZvcmNlIHRoZSBzdHJlYW0gdG8gc2V0IGl0cyBlcnJvciBmbGFnCiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8vIFZlcmlmeSB0aGF0IHRoZSBlbmQgbWFya2VyIGlzIHByZXNlbnQKICAgICAgICB1cHJ2X21zdHJtX3JlYWQoaXMsICZpZCwgc2l6ZW9mKGlkKSk7CiAgICAgICAgaWYgKGlkICE9IGNvbGxhdG9yLT5GSUxFSUQpCiAgICAgICAgewogICAgICAgICAgICAvLyBUaGlzIGlzbid0IHRoZSByaWdodCB0eXBlIG9mIGZpbGUuICBNYXJrIHRoZSBpb3MKICAgICAgICAgICAgLy8gYXMgZmFpbGluZyBhbmQgcmV0dXJuLgogICAgICAgICAgICB1cHJ2X21zdHJtX3NldEVycm9yKGlzKTsgLy8gZm9yY2UgdGhlIHN0cmVhbSB0byBzZXQgaXRzIGVycm9yIGZsYWcKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgLy8gUmVzZXQgb3RoZXIgZGF0YSBtZW1iZXJzCiAgICAgICAgY29sbGF0b3ItPmlzT3Zlcklnbm9yZSA9IEZBTFNFOwogICAgICAgIGNvbGxhdG9yLT5sYXN0Q2hhciA9IDA7CiAgICAgICAgZGVsZXRlIGNvbGxhdG9yLT5tUGF0dGVybjsKICAgICAgICBjb2xsYXRvci0+bVBhdHRlcm4gPSAwOwogICAgICAgIGNvbGxhdG9yLT5rZXkucmVtb3ZlKCk7CiAgICAgICAgY29sbGF0b3ItPmRhdGFJc093bmVkID0gVFJVRTsKICAgIH0KfQoKdm9pZCBSdWxlQmFzZWRDb2xsYXRvclN0cmVhbWVyOjpzdHJlYW1PdXQoY29uc3QgUnVsZUJhc2VkQ29sbGF0b3IqIGNvbGxhdG9yLCBVTWVtb3J5U3RyZWFtKiBvcykKewogICAgaWYgKCF1cHJ2X21zdHJtX2Vycm9yKG9zKSkKICAgIHsKICAgICAgICAvLyBXZSB1c2UgYSAxNi1iaXQgSUQgY29kZSB0byBpZGVudGlmeSB0aGlzIGZpbGUuCiAgICAgICAgaW50MTZfdCBpZCA9IGNvbGxhdG9yLT5GSUxFSUQ7CiAgICAgICAgdXBydl9tc3RybV93cml0ZShvcywgKHVpbnQ4X3QgKikmaWQsIHNpemVvZihpZCkpOwoKICAgICAgICAvLyBTdHJlYW0gb3V0IHRoZSBkYXRhCiAgICAgICAgY2hhciBpc051bGw7CiAgICAgICAgaXNOdWxsID0gKGNvbGxhdG9yLT5kYXRhID09IDApOwogICAgICAgIHVwcnZfbXN0cm1fd3JpdGUob3MsICh1aW50OF90KikmaXNOdWxsLCBzaXplb2YoaXNOdWxsKSk7CgogICAgICAgIGlmICghaXNOdWxsKQogICAgICAgIHsKICAgICAgICAgICAgY29sbGF0b3ItPmRhdGEtPnN0cmVhbU91dChvcyk7CiAgICAgICAgfQoKICAgICAgICAvLyBXcml0ZSBvdXQgdGhlIElEIHRvIGluZGljYXRlIHRoZSBlbmQKICAgICAgICB1cHJ2X21zdHJtX3dyaXRlKG9zLCAodWludDhfdCAqKSZpZCwgc2l6ZW9mKGlkKSk7CiAgICB9Cn0KCnZvaWQgUnVsZUJhc2VkQ29sbGF0b3JTdHJlYW1lcjo6c3RyZWFtSW4oUnVsZUJhc2VkQ29sbGF0b3IqIGNvbGxhdG9yLCBGaWxlU3RyZWFtKiBpcykKewogICAgaWYgKCFUX0ZpbGVTdHJlYW1fZXJyb3IoaXMpKQogICAgewogICAgICAgIC8vIENoZWNrIHRoYXQgdGhpcyBpcyB0aGUgY29ycmVjdCBmaWxlIHR5cGUKICAgICAgICBpbnQxNl90IGlkOwoKICAgICAgICBUX0ZpbGVTdHJlYW1fcmVhZChpcywgJmlkLCBzaXplb2YoaWQpKTsKICAgICAgICBpZiAoaWQgIT0gY29sbGF0b3ItPkZJTEVJRCkKICAgICAgICB7CiAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGhlIHJpZ2h0IHR5cGUgb2YgZmlsZS4gIE1hcmsgdGhlIGlvcwogICAgICAgICAgICAvLyBhcyBmYWlsaW5nIGFuZCByZXR1cm4uCiAgICAgICAgICAgIFRfRmlsZVN0cmVhbV9zZXRFcnJvcihpcyk7IC8vIGZvcmNlIHRoZSBzdHJlYW0gdG8gc2V0IGl0cyBlcnJvciBmbGFnCiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIC8vIFN0cmVhbSBpbiBsYXJnZSBvYmplY3RzCiAgICAgICAgY2hhciBpc051bGw7CgogICAgICAgIFRfRmlsZVN0cmVhbV9yZWFkKGlzLCAmaXNOdWxsLCBzaXplb2YoaXNOdWxsKSk7CiAgICAgICAgaWYgKGlzTnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGRlbGV0ZSBjb2xsYXRvci0+ZGF0YTsKICAgICAgICAgICAgY29sbGF0b3ItPmRhdGEgPSBOVUxMOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBpZiAoY29sbGF0b3ItPmRhdGEgPT0gTlVMTCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgY29sbGF0b3ItPmRhdGEgPSBuZXcgVGFibGVDb2xsYXRpb25EYXRhOwogICAgICAgICAgICB9CiAgICAgICAgICAgIAogICAgICAgICAgICBjb2xsYXRvci0+ZGF0YS0+c3RyZWFtSW4oaXMpOwogICAgICAgICAgICBpZiAoY29sbGF0b3ItPmRhdGEtPmlzQm9ndXMoKSkgewogICAgICAgICAgICAgICAgVF9GaWxlU3RyZWFtX3NldEVycm9yKGlzKTsgLy8gZm9yY2UgdGhlIHN0cmVhbSB0byBzZXQgaXRzIGVycm9yIGZsYWcKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gVmVyaWZ5IHRoYXQgdGhlIGVuZCBtYXJrZXIgaXMgcHJlc2VudAogICAgICAgIFRfRmlsZVN0cmVhbV9yZWFkKGlzLCAmaWQsIHNpemVvZihpZCkpOwogICAgICAgIGlmIChpZCAhPSBjb2xsYXRvci0+RklMRUlEKQogICAgICAgIHsKICAgICAgICAgICAgLy8gVGhpcyBpc24ndCB0aGUgcmlnaHQgdHlwZSBvZiBmaWxlLiAgTWFyayB0aGUgaW9zCiAgICAgICAgICAgIC8vIGFzIGZhaWxpbmcgYW5kIHJldHVybi4KICAgICAgICAgICAgVF9GaWxlU3RyZWFtX3NldEVycm9yKGlzKTsgLy8gZm9yY2UgdGhlIHN0cmVhbSB0byBzZXQgaXRzIGVycm9yIGZsYWcKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgLy8gUmVzZXQgb3RoZXIgZGF0YSBtZW1iZXJzCiAgICAgICAgY29sbGF0b3ItPmlzT3Zlcklnbm9yZSA9IEZBTFNFOwogICAgICAgIGNvbGxhdG9yLT5sYXN0Q2hhciA9IDA7CiAgICAgICAgZGVsZXRlIGNvbGxhdG9yLT5tUGF0dGVybjsKICAgICAgICBjb2xsYXRvci0+bVBhdHRlcm4gPSAwOwogICAgICAgIGNvbGxhdG9yLT5rZXkucmVtb3ZlKCk7CiAgICAgICAgY29sbGF0b3ItPmRhdGFJc093bmVkID0gVFJVRTsKICAgIH0KfQoKdm9pZCBSdWxlQmFzZWRDb2xsYXRvclN0cmVhbWVyOjpzdHJlYW1PdXQoY29uc3QgUnVsZUJhc2VkQ29sbGF0b3IqIGNvbGxhdG9yLCBGaWxlU3RyZWFtKiBvcykKewogICAgaWYgKCFUX0ZpbGVTdHJlYW1fZXJyb3Iob3MpKQogICAgewogICAgICAgIC8vIFdlIHVzZSBhIDE2LWJpdCBJRCBjb2RlIHRvIGlkZW50aWZ5IHRoaXMgZmlsZS4KICAgICAgICBpbnQxNl90IGlkID0gY29sbGF0b3ItPkZJTEVJRDsKICAgICAgICBUX0ZpbGVTdHJlYW1fd3JpdGUob3MsICZpZCwgc2l6ZW9mKGlkKSk7CgogICAgICAgIC8vIFN0cmVhbSBvdXQgdGhlIGRhdGEKICAgICAgICBjaGFyIGlzTnVsbDsKICAgICAgICBpc051bGwgPSAoY29sbGF0b3ItPmRhdGEgPT0gMCk7CiAgICAgICAgVF9GaWxlU3RyZWFtX3dyaXRlKG9zLCAmaXNOdWxsLCBzaXplb2YoaXNOdWxsKSk7CgogICAgICAgIGlmICghaXNOdWxsKQogICAgICAgIHsKICAgICAgICAgICAgY29sbGF0b3ItPmRhdGEtPnN0cmVhbU91dChvcyk7CiAgICAgICAgfQoKICAgICAgICAvLyBXcml0ZSBvdXQgdGhlIElEIHRvIGluZGljYXRlIHRoZSBlbmQKICAgICAgICBUX0ZpbGVTdHJlYW1fd3JpdGUob3MsICZpZCwgc2l6ZW9mKGlkKSk7CiAgICB9Cn0KClVCb29sIFJ1bGVCYXNlZENvbGxhdG9yOjp3cml0ZVRvRmlsZShjb25zdCBjaGFyKiBmaWxlTmFtZSkgY29uc3QKewogICAgRmlsZVN0cmVhbSogb2ZzID0gVF9GaWxlU3RyZWFtX29wZW4oZmlsZU5hbWUsICJ3YiIpOwogICAgaWYgKG9mcyAhPSAwKQogICAgewogICAgICAgIFJ1bGVCYXNlZENvbGxhdG9yU3RyZWFtZXI6OnN0cmVhbU91dCh0aGlzLCBvZnMpOwogICAgfQoKI2lmZGVmIENPTExERUJVRwogICAgZnByaW50ZihzdGRlcnIsICJiaW5hcnkgd3JpdGUgJXMgc2l6ZSAlZCAlc1xuIiwgZmlsZU5hbWUsIFRfRmlsZVN0cmVhbV9zaXplKG9mcyksCiAgICAgICAgKCFUX0ZpbGVTdHJlYW1fZXJyb3Iob2ZzKSA/ICIsIE9LIiA6ICIsIEZBSUwiKSk7CiNlbmRpZgoKICAgIFVCb29sIGVyciA9IFRfRmlsZVN0cmVhbV9lcnJvcihvZnMpID09IDA7CgogICAgVF9GaWxlU3RyZWFtX2Nsb3NlKG9mcyk7CiAgICByZXR1cm4gZXJyOwp9Ci8qClVCb29sIFJ1bGVCYXNlZENvbGxhdG9yOjpwcmVwYXJlRm9yQnVuZGxlKCkgY29uc3QKewogICAgVU1lbW9yeVN0cmVhbSogb2ZzID0gdXBydl9tc3RybV9vcGVuTmV3KDApOwogICAgaWYgKG9mcyAhPSAwKQogICAgewogICAgICAgIFJ1bGVCYXNlZENvbGxhdG9yU3RyZWFtZXI6OnN0cmVhbU91dCh0aGlzLCBvZnMpOwogICAgfQoKI2lmZGVmIENPTExERUJVRwogICAgZnByaW50ZihzdGRlcnIsICJiaW5hcnkgd3JpdGUgJXMgc2l6ZSAlZCAlc1xuIiwgZmlsZU5hbWUsIFRfRmlsZVN0cmVhbV9zaXplKG9mcyksCiAgICAgICAgKCFUX0ZpbGVTdHJlYW1fZXJyb3Iob2ZzKSA/ICIsIE9LIiA6ICIsIEZBSUwiKSk7CiNlbmRpZgoKICAgIFVCb29sIGVyciA9IHVwcnZfbXN0cm1fZXJyb3Iob2ZzKSA9PSAwOwoKICAgIHVwcnZfbXN0cm1fY2xvc2Uob2ZzKTsKCiAgICByZXR1cm4gZXJyOwp9CiovCgp2b2lkIFJ1bGVCYXNlZENvbGxhdG9yOjphZGRUb0NhY2hlKGNvbnN0IFVuaWNvZGVTdHJpbmcmIGtleSkKewogICAgLy8gVGhpcyBtZXRob2QgZG9lc24ndCBhZGQgdGhlIFJ1bGVCYXNlZENvbGxhdG9yIGl0c2VsZiB0byB0aGUgY2FjaGUuICBJbnN0ZWFkLAogICAgLy8gaXQgYWRkcyB0aGUgZ2l2ZW4gUnVsZUJhc2VkQ29sbGF0b3IncyBkYXRhIG9iamVjdCB0byB0aGUgVGFibGVDb2xsYXRpb25EYXRhCiAgICAvLyBjYWNoZSwgYW5kIG1hcmtzIGl0IGFzIG5vbi1vd25lZCBpbiB0aGUgZ2l2ZW4gUnVsZUJhc2VkQ29sbGF0b3Igb2JqZWN0LgogICAgVGFibGVDb2xsYXRpb25EYXRhOjphZGRUb0NhY2hlKGtleSwgZGF0YSk7CiAgICBkYXRhSXNPd25lZCA9IEZBTFNFOwp9Cgp2b2lkClJ1bGVCYXNlZENvbGxhdG9yOjpjb25zdHJ1Y3RGcm9tQ2FjaGUoY29uc3QgVW5pY29kZVN0cmluZyYga2V5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVFcnJvckNvZGUmIHN0YXR1cykKewogICAgLy8gQXR0ZW1wdCB0byBjb25zdHJ1Y3QgdGhpcyBSdWxlQmFzZWRDb2xsYXRvciBvYmplY3QgZnJvbSBjYWNoZWQgVGFibGVDb2xsYXRpb25EYXRhLgogICAgLy8gSWYgbm8gc3VjaCBkYXRhIGlzIGluIHRoZSBjYWNoZSwgcmV0dXJuIGZhbHNlLgogICAgaWYgKFVfRkFJTFVSRShzdGF0dXMpKSByZXR1cm47CiAgICBpZiAoZGF0YUlzT3duZWQpCiAgICB7CiAgICAgICAgZGVsZXRlIGRhdGE7CiAgICAgICAgZGF0YSA9IE5VTEw7CiAgICB9CgogICAgaXNPdmVySWdub3JlID0gRkFMU0U7CiAgICBsYXN0Q2hhciA9IDA7CiAgICBtUGF0dGVybiA9IDA7CiAgICBzZXRTdHJlbmd0aChDb2xsYXRvcjo6VEVSVElBUlkpOwoKICAgIGRhdGFJc093bmVkID0gRkFMU0U7CiAgICBkYXRhID0gVGFibGVDb2xsYXRpb25EYXRhOjpmaW5kSW5DYWNoZShrZXkpOwogICAgaWYgKGRhdGEgPT0gTlVMTCkKICAgIHsKICAgICAgICBzdGF0dXMgPSBVX01JU1NJTkdfUkVTT1VSQ0VfRVJST1I7CiAgICB9Cn0KCmNoYXIqClJ1bGVCYXNlZENvbGxhdG9yOjpjcmVhdGVQYXRoTmFtZSggIGNvbnN0IFVuaWNvZGVTdHJpbmcmICAgIHByZWZpeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBVbmljb2RlU3RyaW5nJiAgICBuYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFVuaWNvZGVTdHJpbmcmICAgIHN1ZmZpeCkKewogICAgLy8gQ29uY2F0ZW5hdGUgdGhyZWUgZWxlbWVudHMgdG8gZm9ybSBhIGZpbGUgbmFtZSwgYW5kIHJldHVybiBpdC4KCiAgICBVbmljb2RlU3RyaW5nICAgd29ya2luZ05hbWUocHJlZml4KTsKICAgIGludDMyX3QgICAgICAgICBzaXplOwogICAgY2hhciogICAgICAgICAgIHJldHVyblZhbDsKCiAgICB3b3JraW5nTmFtZSArPSBuYW1lOwogICAgd29ya2luZ05hbWUgKz0gc3VmZml4OwoKICAgIHNpemUgPSB3b3JraW5nTmFtZS5sZW5ndGgoKTsKICAgIHJldHVyblZhbCA9IG5ldyBjaGFyW3NpemUgKyAxXTsKICAgIHdvcmtpbmdOYW1lLmV4dHJhY3QoMCwgc2l6ZSwgcmV0dXJuVmFsLCAiIik7CiAgICByZXR1cm5WYWxbc2l6ZV0gPSAwOwoKICAgIHJldHVybiByZXR1cm5WYWw7Cn0KCnZvaWQKUnVsZUJhc2VkQ29sbGF0b3I6OmNob3BMb2NhbGUoVW5pY29kZVN0cmluZyYgbG9jYWxlTmFtZSkKewogICAgLy8gY2hvcExvY2FsZSByZW1vdmVzIHRoZSBmaW5hbCBlbGVtZW50IGZyb20gYSBsb2NhbGUgc3RyaW5nLgogICAgLy8gRm9yIGluc3RhbmNlLCAiZGVfQ0giIGJlY29tZXMgImRlIiwgYW5kICJkZSIgYmVjb21lcyAiIi4KICAgIC8vICIiIHJlbWFpbnMgIiIuCgogICAgaW50MzJfdCAgICAgc2l6ZSA9IGxvY2FsZU5hbWUubGVuZ3RoKCk7CiAgICBpbnQzMl90ICAgICBpOwoKICAgIGZvciAoaSA9IHNpemUgLSAxOyBpID4gMDsgaS0tKQogICAgewogICAgICAgIGlmIChsb2NhbGVOYW1lW2ldID09IDB4MDA1RikKICAgICAgICB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KCiAgICBpZiAoaSA8IDApCiAgICB7CiAgICAgICBpID0gMDsKICAgIH0KCiAgICBsb2NhbGVOYW1lLnJlbW92ZShpLCBzaXplIC0gaSk7Cn0KCgp1aW50OF90ICoKUnVsZUJhc2VkQ29sbGF0b3I6OmNsb25lUnVsZURhdGEoaW50MzJfdCAmbGVuZ3RoLCBVRXJyb3JDb2RlICZzdGF0dXMpCnsKICBVTWVtb3J5U3RyZWFtICptZW1kYXRhID0gMDsKICB1aW50OF90ICpkYXRhID0gMDsKCiAgaWYoVV9GQUlMVVJFKHN0YXR1cykpIHsKICAgIHJldHVybiBOVUxMOwogIH0KCiAgICAgIG1lbWRhdGEgPSB1cHJ2X21zdHJtX29wZW5OZXcoMCk7CgogICAgICBpZiAobWVtZGF0YSAhPSAwKSB7CiAgICAgICAgUnVsZUJhc2VkQ29sbGF0b3JTdHJlYW1lcjo6c3RyZWFtT3V0KHRoaXMsIG1lbWRhdGEpOwogICAgICB9CgogICAgICBVQm9vbCBlcnIgPSB1cHJ2X21zdHJtX2Vycm9yKG1lbWRhdGEpID09IDA7CgoKICAgIGRhdGEgPSAodWludDhfdCAqKXVwcnZfbWFsbG9jKG1lbWRhdGEtPmZQb3MpOwogICAgaWYoZGF0YSA9PSAwKSB7CiAgICAgIHN0YXR1cyA9IFVfTUVNT1JZX0FMTE9DQVRJT05fRVJST1I7CiAgICAgIHVwcnZfbXN0cm1fY2xvc2UobWVtZGF0YSk7CiAgICAgIGxlbmd0aCA9IDA7CiAgICAgIHJldHVybiAwOwogICAgfSBlbHNlIHsKICAgICAgdXBydl9tZW1jcHkoZGF0YSwgbWVtZGF0YS0+ZlN0YXJ0LCBtZW1kYXRhLT5mUG9zKTsKICAgICAgbGVuZ3RoID0gbWVtZGF0YS0+ZlBvczsKICAgICAgdXBydl9tc3RybV9jbG9zZShtZW1kYXRhKTsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9Cn0KCgovL2VvZgo=