LyoKICogQ29weXJpZ2h0IChjKSAyMDA5LCBKYXkgTG9kZW4sIEdpYW1wYW9sbyBSb2RvbGEnLiBBbGwgcmlnaHRzIHJlc2VydmVkLgogKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlCiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUuCiAqCiAqIFNlY3VyaXR5IHJlbGF0ZWQgZnVuY3Rpb25zIGZvciBXaW5kb3dzIHBsYXRmb3JtIChTZXQgcHJpdmlsZWdlcyBzdWNoIGFzCiAqIFNlRGVidWcpLCBhcyB3ZWxsIGFzIHNlY3VyaXR5IGhlbHBlciBmdW5jdGlvbnMuCiAqLwoKI2luY2x1ZGUgPHdpbmRvd3MuaD4KI2luY2x1ZGUgPFB5dGhvbi5oPgoKLyoKICogQ29udmVydCBhIHByb2Nlc3MgaGFuZGxlIHRvIGEgcHJvY2VzcyB0b2tlbiBoYW5kbGUuCiAqLwpIQU5ETEUKdG9rZW5fZnJvbV9oYW5kbGUoSEFORExFIGhQcm9jZXNzKSB7CiAgICBIQU5ETEUgaFRva2VuID0gTlVMTDsKCiAgICBpZiAoISBPcGVuUHJvY2Vzc1Rva2VuKGhQcm9jZXNzLCBUT0tFTl9RVUVSWSwgJmhUb2tlbikgKSB7CiAgICAgICAgcmV0dXJuIFB5RXJyX1NldEZyb21XaW5kb3dzRXJyKDApOwogICAgfQoKICAgIHJldHVybiBoVG9rZW47Cn0KCgovKgogKiBodHRwOi8vd3d3LmRkai5jb20vd2luZG93cy8xODQ0MDU5ODYKICoKICogVGhlcmUncyBhIHdheSB0byBkZXRlcm1pbmUgd2hldGhlciB3ZSdyZSBydW5uaW5nIHVuZGVyIHRoZSBMb2NhbCBTeXN0ZW0KICogYWNjb3VudC4gSG93ZXZlciAoeW91IGd1ZXNzZWQgaXQpLCB3ZSBoYXZlIHRvIGNhbGwgbW9yZSBXaW4zMiBmdW5jdGlvbnMgdG8KICogZGV0ZXJtaW5lIHRoaXMuIEJhY2tpbmcgdXAgdGhyb3VnaCB0aGUgY29kZSBsaXN0aW5nLCB3ZSBuZWVkIHRvIG1ha2UgYW5vdGhlcgogKiBjYWxsIHRvIEdldFRva2VuSW5mb3JtYXRpb24sIGJ1dCBpbnN0ZWFkIG9mIHBhc3NpbmcgdGhyb3VnaCB0aGUgVE9LRU5fVVNFUgogKiBjb25zdGFudCwgd2UgcGFzcyB0aHJvdWdoIHRoZSBUT0tFTl9QUklWSUxFR0VTIGNvbnN0YW50LiBUaGlzIHZhbHVlIHJldHVybnMKICogYW4gYXJyYXkgb2YgcHJpdmlsZWdlcyB0aGF0IHRoZSBhY2NvdW50IGhhcyBpbiB0aGUgZW52aXJvbm1lbnQuIEl0ZXJhdGluZwogKiB0aHJvdWdoIHRoZSBhcnJheSwgd2UgY2FsbCB0aGUgZnVuY3Rpb24gTG9va3VwUHJpdmlsZWdlTmFtZSBsb29raW5nIGZvciB0aGUKICogc3RyaW5nIJNTZVRjYlByaXZpbGVnZS4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdGhpcyBzdHJpbmcsIHRoZW4gdGhpcwogKiBhY2NvdW50IGhhcyBMb2NhbCBTeXN0ZW0gcHJpdmlsZWdlcwogKi8KaW50IEhhc1N5c3RlbVByaXZpbGVnZShIQU5ETEUgaFByb2Nlc3MpIHsKICAgIERXT1JEIGk7CiAgICBEV09SRCBkd1NpemUgPSAwOwogICAgRFdPUkQgZHdSZXR2YWwgPSAwOwogICAgVENIQVIgcHJpdk5hbWVbMjU2XTsKICAgIERXT1JEIGR3TmFtZVNpemUgPSAyNTY7CiAgICAvL1BUT0tFTl9QUklWSUxFR0VTIHRwID0gTlVMTDsKICAgIEJZVEUgKnBCdWZmZXIgPSBOVUxMOwogICAgVE9LRU5fUFJJVklMRUdFUyogdHAgPSBOVUxMOwogICAgSEFORExFIGhUb2tlbiA9IHRva2VuX2Zyb21faGFuZGxlKGhQcm9jZXNzKTsKCiAgICBpZiAoTlVMTCA9PSBoVG9rZW4pIHsKICAgICAgICByZXR1cm4gLTE7CiAgICB9CgogICAgLy8gY2FsbCBHZXRUb2tlbkluZm9ybWF0aW9uIGZpcnN0IHRvIGdldCB0aGUgYnVmZmVyIHNpemUKICAgIGlmICghIEdldFRva2VuSW5mb3JtYXRpb24oaFRva2VuLCBUb2tlblByaXZpbGVnZXMsIE5VTEwsIDAsICZkd1NpemUpKSB7CiAgICAgICAgZHdSZXR2YWwgPSBHZXRMYXN0RXJyb3IoKTsKICAgICAgICAvLyBpZiBpdCBmYWlsZWQgZm9yIGEgcmVhc29uIG90aGVyIHRoYW4gdGhlIGJ1ZmZlciwgYmFpbCBvdXQKICAgICAgICBpZiAoZHdSZXR2YWwgIT0gRVJST1JfSU5TVUZGSUNJRU5UX0JVRkZFUiApIHsKICAgICAgICAgICAgUHlFcnJfU2V0RnJvbVdpbmRvd3NFcnIoZHdSZXR2YWwpOwogICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICB9CiAgICB9CgogICAgLy8gYWxsb2NhdGUgYnVmZmVyIGFuZCBjYWxsIEdldFRva2VuSW5mb3JtYXRpb24gYWdhaW4KICAgIC8vdHAgPSAoUFRPS0VOX1BSSVZJTEVHRVMpIEdsb2JhbEFsbG9jKEdQVFIsIGR3U2l6ZSk7CiAgICBwQnVmZmVyID0gKEJZVEUgKikgbWFsbG9jKGR3U2l6ZSk7CiAgICBpZiAocEJ1ZmZlciA9PSBOVUxMKSB7CiAgICAgICAgUHlFcnJfTm9NZW1vcnkoKTsKICAgICAgICByZXR1cm4gLTE7CiAgICB9CgogICAgaWYgKCEgR2V0VG9rZW5JbmZvcm1hdGlvbihoVG9rZW4sIFRva2VuUHJpdmlsZWdlcywgcEJ1ZmZlciwgZHdTaXplLCAmZHdTaXplKSApIHsKICAgICAgICBQeUVycl9TZXRGcm9tV2luZG93c0VycigwKTsKICAgICAgICBmcmVlKHBCdWZmZXIpOwogICAgICAgIHJldHVybiAtMTsKICAgIH0KCiAgICAvLyBjb252ZXJ0IHRoZSBCWVRFIGJ1ZmZlciB0byBhIFRPS0VOX1BSSVZJTEVHRVMgc3RydWN0IHBvaW50ZXIKICAgIHRwID0gKFRPS0VOX1BSSVZJTEVHRVMqKXBCdWZmZXI7CgogICAgLy8gY2hlY2sgYWxsIHRoZSBwcml2aWxlZ2VzIGxvb2tpbmcgZm9yIFNlVGNiUHJpdmlsZWdlCiAgICBmb3IoaT0wOyBpIDwgdHAtPlByaXZpbGVnZUNvdW50OyBpKyspIHsKICAgICAgICAvLyByZXNldCB0aGUgYnVmZmVyIGNvbnRlbnRzIGFuZCB0aGUgYnVmZmVyIHNpemUKICAgICAgICBzdHJjcHkocHJpdk5hbWUsICIiKTsKICAgICAgICBkd05hbWVTaXplID0gc2l6ZW9mKHByaXZOYW1lKSAvIHNpemVvZihUQ0hBUik7CiAgICAgICAgaWYgKCEgTG9va3VwUHJpdmlsZWdlTmFtZShOVUxMLAogICAgICAgICAgICAgICAgJnRwLT5Qcml2aWxlZ2VzW2ldLkx1aWQsCiAgICAgICAgICAgICAgICAoTFBUU1RSKXByaXZOYW1lLAogICAgICAgICAgICAgICAgJmR3TmFtZVNpemUpKSB7CgogICAgICAgICAgICBQeUVycl9TZXRGcm9tV2luZG93c0VycigwKTsKICAgICAgICAgICAgZnJlZShwQnVmZmVyKTsKICAgICAgICAgICAgcmV0dXJuIC0xOwogICAgICAgIH0KCiAgICAgICAgLy8gaWYgd2UgZmluZCB0aGUgU2VUY2JQcml2aWxlZ2UgdGhlbiBpdCdzIGEgTG9jYWxTeXN0ZW0gcHJvY2VzcwogICAgICAgIGlmICghIGxzdHJjbXBpKHByaXZOYW1lLCBURVhUKCJTZVRjYlByaXZpbGVnZSIpKSkgewogICAgICAgICAgICBmcmVlKHBCdWZmZXIpOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CgogICAgfSAvL2ZvcgoKICAgIGZyZWUocEJ1ZmZlcik7CiAgICByZXR1cm4gMDsKfQoKCkJPT0wgU2V0UHJpdmlsZWdlKEhBTkRMRSBoVG9rZW4sIExQQ1RTVFIgUHJpdmlsZWdlLCBCT09MIGJFbmFibGVQcml2aWxlZ2UpCnsKICAgIFRPS0VOX1BSSVZJTEVHRVMgdHA7CiAgICBMVUlEIGx1aWQ7CiAgICBUT0tFTl9QUklWSUxFR0VTIHRwUHJldmlvdXM7CiAgICBEV09SRCBjYlByZXZpb3VzPXNpemVvZihUT0tFTl9QUklWSUxFR0VTKTsKCiAgICBpZighTG9va3VwUHJpdmlsZWdlVmFsdWUoIE5VTEwsIFByaXZpbGVnZSwgJmx1aWQgKSkgcmV0dXJuIEZBTFNFOwoKICAgIC8vIGZpcnN0IHBhc3MuICBnZXQgY3VycmVudCBwcml2aWxlZ2Ugc2V0dGluZwogICAgdHAuUHJpdmlsZWdlQ291bnQgPSAxOwogICAgdHAuUHJpdmlsZWdlc1swXS5MdWlkID0gbHVpZDsKICAgIHRwLlByaXZpbGVnZXNbMF0uQXR0cmlidXRlcyA9IDA7CgogICAgQWRqdXN0VG9rZW5Qcml2aWxlZ2VzKAogICAgICAgIGhUb2tlbiwKICAgICAgICBGQUxTRSwKICAgICAgICAmdHAsCiAgICAgICAgc2l6ZW9mKFRPS0VOX1BSSVZJTEVHRVMpLAogICAgICAgICZ0cFByZXZpb3VzLAogICAgICAgICZjYlByZXZpb3VzCiAgICApOwoKICAgIGlmIChHZXRMYXN0RXJyb3IoKSAhPSBFUlJPUl9TVUNDRVNTKSByZXR1cm4gRkFMU0U7CgogICAgLy8gc2Vjb25kIHBhc3MuIHNldCBwcml2aWxlZ2UgYmFzZWQgb24gcHJldmlvdXMgc2V0dGluZwogICAgdHBQcmV2aW91cy5Qcml2aWxlZ2VDb3VudCA9IDE7CiAgICB0cFByZXZpb3VzLlByaXZpbGVnZXNbMF0uTHVpZCA9IGx1aWQ7CgogICAgaWYoYkVuYWJsZVByaXZpbGVnZSkgewogICAgICAgIHRwUHJldmlvdXMuUHJpdmlsZWdlc1swXS5BdHRyaWJ1dGVzIHw9IChTRV9QUklWSUxFR0VfRU5BQkxFRCk7CiAgICB9CgogICAgZWxzZSB7CiAgICAgICAgdHBQcmV2aW91cy5Qcml2aWxlZ2VzWzBdLkF0dHJpYnV0ZXMgXj0gKFNFX1BSSVZJTEVHRV9FTkFCTEVEICYKICAgICAgICAgICAgICAgIHRwUHJldmlvdXMuUHJpdmlsZWdlc1swXS5BdHRyaWJ1dGVzKTsKICAgIH0KCiAgICBBZGp1c3RUb2tlblByaXZpbGVnZXMoCiAgICAgICAgaFRva2VuLAogICAgICAgIEZBTFNFLAogICAgICAgICZ0cFByZXZpb3VzLAogICAgICAgIGNiUHJldmlvdXMsCiAgICAgICAgTlVMTCwKICAgICAgICBOVUxMCiAgICApOwoKICAgIGlmIChHZXRMYXN0RXJyb3IoKSAhPSBFUlJPUl9TVUNDRVNTKSByZXR1cm4gRkFMU0U7CgogICAgcmV0dXJuIFRSVUU7Cn0KCgppbnQgU2V0U2VEZWJ1ZygpCnsKICAgIEhBTkRMRSBoVG9rZW47CiAgICBpZighIE9wZW5UaHJlYWRUb2tlbihHZXRDdXJyZW50VGhyZWFkKCksCiAgICAgICAgICAgICAgICAgICAgICAgICBUT0tFTl9BREpVU1RfUFJJVklMRUdFUyB8IFRPS0VOX1FVRVJZLAogICAgICAgICAgICAgICAgICAgICAgICAgRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAmaFRva2VuKQogICAgICAgICAgICAgICAgICAgICAgICAgKXsKICAgICAgICBpZiAoR2V0TGFzdEVycm9yKCkgPT0gRVJST1JfTk9fVE9LRU4pewogICAgICAgICAgICBpZiAoIUltcGVyc29uYXRlU2VsZihTZWN1cml0eUltcGVyc29uYXRpb24pKXsKICAgICAgICAgICAgICAgIENsb3NlSGFuZGxlKGhUb2tlbik7CiAgICAgICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoIU9wZW5UaHJlYWRUb2tlbihHZXRDdXJyZW50VGhyZWFkKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRPS0VOX0FESlVTVF9QUklWSUxFR0VTIHwgVE9LRU5fUVVFUlksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmaFRva2VuKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApewogICAgICAgICAgICAgICAgUmV2ZXJ0VG9TZWxmKCk7CiAgICAgICAgICAgICAgICBDbG9zZUhhbmRsZShoVG9rZW4pOwogICAgICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgLy8gZW5hYmxlIFNlRGVidWdQcml2aWxlZ2UgKG9wZW4gYW55IHByb2Nlc3MpCiAgICBpZiAoISBTZXRQcml2aWxlZ2UoaFRva2VuLCBTRV9ERUJVR19OQU1FLCBUUlVFKSl7CiAgICAgICAgUmV2ZXJ0VG9TZWxmKCk7CiAgICAgICAgQ2xvc2VIYW5kbGUoaFRva2VuKTsKICAgICAgICByZXR1cm4gMDsKICAgIH0KCiAgICBSZXZlcnRUb1NlbGYoKTsKICAgIENsb3NlSGFuZGxlKGhUb2tlbik7CiAgICByZXR1cm4gMTsKfQoKCmludCBVbnNldFNlRGVidWcoKQp7CiAgICBIQU5ETEUgaFRva2VuOwogICAgaWYoISBPcGVuVGhyZWFkVG9rZW4oR2V0Q3VycmVudFRocmVhZCgpLAogICAgICAgICAgICAgICAgICAgICAgICBUT0tFTl9BREpVU1RfUFJJVklMRUdFUyB8IFRPS0VOX1FVRVJZLAogICAgICAgICAgICAgICAgICAgICAgICBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgJmhUb2tlbikKICAgICAgICAgICAgICAgICAgICAgICAgKXsKICAgICAgICBpZihHZXRMYXN0RXJyb3IoKSA9PSBFUlJPUl9OT19UT0tFTil7CiAgICAgICAgICAgIGlmKCEgSW1wZXJzb25hdGVTZWxmKFNlY3VyaXR5SW1wZXJzb25hdGlvbikpewogICAgICAgICAgICAgICAgLy9Mb2cyRmlsZSgiRXJyb3Igc2V0dGluZyBpbXBlcnNvbmF0aW9uISBbVW5zZXRTZURlYnVnKCldIiwgTF9ERUJVRyk7CiAgICAgICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaWYoIU9wZW5UaHJlYWRUb2tlbihHZXRDdXJyZW50VGhyZWFkKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVE9LRU5fQURKVVNUX1BSSVZJTEVHRVMgfCBUT0tFTl9RVUVSWSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmaFRva2VuKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICl7CiAgICAgICAgICAgICAgICAvL0xvZzJGaWxlKCJFcnJvciBPcGVuaW5nIFRocmVhZCBUb2tlbiEgW1Vuc2V0U2VEZWJ1ZygpXSIsIExfREVCVUcpOwogICAgICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgLy9ub3cgZGlzYWJsZSBTZURlYnVnCiAgICBpZighU2V0UHJpdmlsZWdlKGhUb2tlbiwgU0VfREVCVUdfTkFNRSwgRkFMU0UpKXsKICAgICAgICAvL0xvZzJGaWxlKCJFcnJvciB1bnNldHRpbmcgU2VEZWJ1ZyBQcml2aWxlZ2UgW1NldFByaXZpbGVnZSgpXSIsIExfV0FSTik7CiAgICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgQ2xvc2VIYW5kbGUoaFRva2VuKTsKICAgIHJldHVybiAxOwp9Cg==