Ly8KLy8gQ29weXJpZ2h0IKkgMjAxMiBMaW5hcm8gTGltaXRlZAovLwovLyBUaGlzIGZpbGUgaXMgcGFydCBvZiB0aGUgZ2xtYXJrMiBPcGVuR0wgKEVTKSAyLjAgYmVuY2htYXJrLgovLwovLyBnbG1hcmsyIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXQgdW5kZXIgdGhlCi8vIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUKLy8gRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIKLy8gdmVyc2lvbi4KLy8KLy8gZ2xtYXJrMiBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVCBBTlkKLy8gV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUwovLyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlCi8vIGRldGFpbHMuCi8vCi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGgKLy8gZ2xtYXJrMi4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi4KLy8KLy8gQXV0aG9yczoKLy8gIEplc3NlIEJhcmtlcgovLwojaW5jbHVkZSAic2NlbmUtcmVmcmFjdC5oIgojaW5jbHVkZSAibW9kZWwuaCIKI2luY2x1ZGUgInRleHR1cmUuaCIKI2luY2x1ZGUgInV0aWwuaCIKI2luY2x1ZGUgImxvZy5oIgojaW5jbHVkZSAic2hhZGVyLXNvdXJjZS5oIgoKdXNpbmcgc3RkOjpzdHJpbmc7CnVzaW5nIHN0ZDo6dmVjdG9yOwp1c2luZyBzdGQ6Om1hcDsKdXNpbmcgTGliTWF0cml4OjptYXQ0Owp1c2luZyBMaWJNYXRyaXg6OnZlYzQ7CnVzaW5nIExpYk1hdHJpeDo6dmVjMzsKCnN0YXRpYyBjb25zdCB2ZWM0IGxpZ2h0UG9zaXRpb24oMC4wZiwgMy4wZiwgMi4wZiwgMS4wZik7CgovLwovLyBQdWJsaWMgaW50ZXJmYWNlcwovLwoKU2NlbmVSZWZyYWN0OjpTY2VuZVJlZnJhY3QoQ2FudmFzJiBjYW52YXMpIDoKICAgIFNjZW5lKGNhbnZhcywgInJlZnJhY3QiKSwKICAgIHByaXZfKDApCnsKICAgIGNvbnN0IE1vZGVsTWFwJiBtb2RlbE1hcCA9IE1vZGVsOjpmaW5kX21vZGVscygpOwogICAgc3RyaW5nIG9wdGlvblZhbHVlczsKICAgIGZvciAoTW9kZWxNYXA6OmNvbnN0X2l0ZXJhdG9yIG1vZGVsSXQgPSBtb2RlbE1hcC5iZWdpbigpOwogICAgICAgICBtb2RlbEl0ICE9IG1vZGVsTWFwLmVuZCgpOwogICAgICAgICBtb2RlbEl0KyspCiAgICB7CiAgICAgICAgc3RhdGljIGJvb2wgZG9TZXBhcmF0b3IoZmFsc2UpOwogICAgICAgIGlmIChkb1NlcGFyYXRvcikKICAgICAgICB7CiAgICAgICAgICAgIG9wdGlvblZhbHVlcyArPSAiLCI7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHN0cmluZyYgY3VyTmFtZSA9IG1vZGVsSXQtPmZpcnN0OwogICAgICAgIG9wdGlvblZhbHVlcyArPSBjdXJOYW1lOwogICAgICAgIGRvU2VwYXJhdG9yID0gdHJ1ZTsKICAgIH0KICAgIG9wdGlvbnNfWyJtb2RlbCJdID0gU2NlbmU6Ok9wdGlvbigibW9kZWwiLCAiYnVubnkiLCAiV2hpY2ggbW9kZWwgdG8gdXNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25WYWx1ZXMpOwogICAgb3B0aW9uVmFsdWVzID0gIiI7CiAgICBjb25zdCBUZXh0dXJlTWFwJiB0ZXh0dXJlTWFwID0gVGV4dHVyZTo6ZmluZF90ZXh0dXJlcygpOwogICAgZm9yIChUZXh0dXJlTWFwOjpjb25zdF9pdGVyYXRvciB0ZXh0dXJlSXQgPSB0ZXh0dXJlTWFwLmJlZ2luKCk7CiAgICAgICAgIHRleHR1cmVJdCAhPSB0ZXh0dXJlTWFwLmVuZCgpOwogICAgICAgICB0ZXh0dXJlSXQrKykKICAgIHsKICAgICAgICBzdGF0aWMgYm9vbCBkb1NlcGFyYXRvcihmYWxzZSk7CiAgICAgICAgaWYgKGRvU2VwYXJhdG9yKQogICAgICAgIHsKICAgICAgICAgICAgb3B0aW9uVmFsdWVzICs9ICIsIjsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc3RyaW5nJiBjdXJOYW1lID0gdGV4dHVyZUl0LT5maXJzdDsKICAgICAgICBvcHRpb25WYWx1ZXMgKz0gY3VyTmFtZTsKICAgICAgICBkb1NlcGFyYXRvciA9IHRydWU7CiAgICB9CiAgICBvcHRpb25zX1sidGV4dHVyZSJdID0gU2NlbmU6Ok9wdGlvbigidGV4dHVyZSIsICJuYXNhMSIsICJXaGljaCB0ZXh0dXJlIHRvIHVzZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25WYWx1ZXMpOwogICAgb3B0aW9uc19bInVzZS12Ym8iXSA9IFNjZW5lOjpPcHRpb24oInVzZS12Ym8iLCAidHJ1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2hldGhlciB0byB1c2UgVkJPcyBmb3IgcmVuZGVyaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmYWxzZSx0cnVlIik7CiAgICBvcHRpb25zX1siaW50ZXJsZWF2ZSJdID0gU2NlbmU6Ok9wdGlvbigiaW50ZXJsZWF2ZSIsICJmYWxzZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2hldGhlciB0byBpbnRlcmxlYXZlIHZlcnRleCBhdHRyaWJ1dGUgZGF0YSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmFsc2UsdHJ1ZSIpOwp9CgpTY2VuZVJlZnJhY3Q6On5TY2VuZVJlZnJhY3QoKQp7CiAgICBkZWxldGUgcHJpdl87Cn0KCmJvb2wKU2NlbmVSZWZyYWN0OjpzdXBwb3J0ZWQoYm9vbCBzaG93X2Vycm9ycykKewogICAgc3RhdGljIGNvbnN0IHN0cmluZyBvZXNfZGVwdGhfdGV4dHVyZSgiR0xfT0VTX2RlcHRoX3RleHR1cmUiKTsKICAgIHN0YXRpYyBjb25zdCBzdHJpbmcgYXJiX2RlcHRoX3RleHR1cmUoIkdMX0FSQl9kZXB0aF90ZXh0dXJlIik7CiAgICBpZiAoIUdMRXh0ZW5zaW9uczo6c3VwcG9ydChvZXNfZGVwdGhfdGV4dHVyZSkgJiYKICAgICAgICAhR0xFeHRlbnNpb25zOjpzdXBwb3J0KGFyYl9kZXB0aF90ZXh0dXJlKSkgewogICAgICAgIGlmIChzaG93X2Vycm9ycykgewogICAgICAgICAgICBMb2c6OmVycm9yKCJXZSBkbyBub3QgaGF2ZSB0aGUgZGVwdGggdGV4dHVyZSBleHRlbnNpb24hISFcbiIpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgcmV0dXJuIHRydWU7Cn0KCmJvb2wKU2NlbmVSZWZyYWN0Ojpsb2FkKCkKewogICAgcnVubmluZ18gPSBmYWxzZTsKICAgIHJldHVybiB0cnVlOwp9Cgp2b2lkClNjZW5lUmVmcmFjdDo6dW5sb2FkKCkKewp9Cgpib29sClNjZW5lUmVmcmFjdDo6c2V0dXAoKQp7CiAgICAvLyBJZiB0aGUgc2NlbmUgaXNuJ3Qgc3VwcG9ydGVkLCBkb24ndCBib3RoZXIgdG8gZ28gdGhyb3VnaCBzZXR1cC4KICAgIGlmICghc3VwcG9ydGVkKGZhbHNlKSB8fCAhU2NlbmU6OnNldHVwKCkpCiAgICB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIHByaXZfID0gbmV3IFJlZnJhY3RQcml2YXRlKGNhbnZhc18pOwogICAgaWYgKCFwcml2Xy0+c2V0dXAob3B0aW9uc18pKSB7CiAgICAgICAgZGVsZXRlIHByaXZfOwogICAgICAgIHByaXZfID0gMDsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgLy8gU2V0IGNvcmUgc2NlbmUgdGltaW5nIGFmdGVyIGFjdHVhbCBpbml0aWFsaXphdGlvbiBzbyB3ZSBkb24ndCBtZWFzdXJlCiAgICAvLyBzZXQgdXAgdGltZS4KICAgIHN0YXJ0VGltZV8gPSBVdGlsOjpnZXRfdGltZXN0YW1wX3VzKCkgLyAxMDAwMDAwLjA7CiAgICBsYXN0VXBkYXRlVGltZV8gPSBzdGFydFRpbWVfOwogICAgcnVubmluZ18gPSB0cnVlOwoKICAgIHJldHVybiB0cnVlOwp9Cgp2b2lkClNjZW5lUmVmcmFjdDo6dGVhcmRvd24oKQp7CiAgICAvLyBBZGQgc2NlbmUtc3BlY2lmaWMgdGVhcmRvd24gaGVyZQogICAgcHJpdl8tPnRlYXJkb3duKCk7CiAgICBTY2VuZTo6dGVhcmRvd24oKTsKfQoKdm9pZApTY2VuZVJlZnJhY3Q6OnVwZGF0ZSgpCnsKICAgIFNjZW5lOjp1cGRhdGUoKTsKICAgIC8vIEFkZCBzY2VuZS1zcGVjaWZpYyB1cGRhdGUgaGVyZQogICAgcHJpdl8tPnVwZGF0ZShsYXN0VXBkYXRlVGltZV8gLSBzdGFydFRpbWVfKTsKfQoKdm9pZApTY2VuZVJlZnJhY3Q6OmRyYXcoKQp7CiAgICBwcml2Xy0+ZHJhdygpOwp9CgpTY2VuZTo6VmFsaWRhdGlvblJlc3VsdApTY2VuZVJlZnJhY3Q6OnZhbGlkYXRlKCkKewogICAgcmV0dXJuIFNjZW5lOjpWYWxpZGF0aW9uVW5rbm93bjsKfQoKLy8KLy8gUHJpdmF0ZSBpbnRlcmZhY2VzCi8vCgpib29sCkRpc3RhbmNlUmVuZGVyVGFyZ2V0OjpzZXR1cCh1bnNpZ25lZCBpbnQgd2lkdGgsIHVuc2lnbmVkIGludCBoZWlnaHQpCnsKICAgIGNhbnZhc193aWR0aF8gPSB3aWR0aDsKICAgIGNhbnZhc19oZWlnaHRfID0gaGVpZ2h0OwogICAgd2lkdGhfID0gY2FudmFzX3dpZHRoXyAqIDI7CiAgICBoZWlnaHRfID0gY2FudmFzX2hlaWdodF8gKiAyOwoKICAgIHN0YXRpYyBjb25zdCBzdHJpbmcgdnR4X3NoYWRlcl9maWxlbmFtZShHTE1BUktfREFUQV9QQVRIIi9zaGFkZXJzL2RlcHRoLnZlcnQiKTsKICAgIHN0YXRpYyBjb25zdCBzdHJpbmcgZnJnX3NoYWRlcl9maWxlbmFtZShHTE1BUktfREFUQV9QQVRIIi9zaGFkZXJzL2RlcHRoLmZyYWciKTsKCiAgICBTaGFkZXJTb3VyY2UgdnR4X3NvdXJjZSh2dHhfc2hhZGVyX2ZpbGVuYW1lKTsKICAgIFNoYWRlclNvdXJjZSBmcmdfc291cmNlKGZyZ19zaGFkZXJfZmlsZW5hbWUpOwoKICAgIGlmICghU2NlbmU6OmxvYWRfc2hhZGVyc19mcm9tX3N0cmluZ3MocHJvZ3JhbV8sIHZ0eF9zb3VyY2Uuc3RyKCksIGZyZ19zb3VyY2Uuc3RyKCkpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIGdsR2VuVGV4dHVyZXMoMSwgJnRleF8pOwogICAgZ2xCaW5kVGV4dHVyZShHTF9URVhUVVJFXzJELCB0ZXhfKTsKICAgIGdsVGV4UGFyYW1ldGVyaShHTF9URVhUVVJFXzJELCBHTF9URVhUVVJFX01JTl9GSUxURVIsIEdMX05FQVJFU1QpOwogICAgZ2xUZXhQYXJhbWV0ZXJpKEdMX1RFWFRVUkVfMkQsIEdMX1RFWFRVUkVfTUFHX0ZJTFRFUiwgR0xfTkVBUkVTVCk7CiAgICBnbFRleFBhcmFtZXRlcmkoR0xfVEVYVFVSRV8yRCwgR0xfVEVYVFVSRV9XUkFQX1MsIEdMX0NMQU1QX1RPX0VER0UpOwogICAgZ2xUZXhQYXJhbWV0ZXJpKEdMX1RFWFRVUkVfMkQsIEdMX1RFWFRVUkVfV1JBUF9ULCBHTF9DTEFNUF9UT19FREdFKTsKICAgIGdsVGV4SW1hZ2UyRChHTF9URVhUVVJFXzJELCAwLCBHTF9ERVBUSF9DT01QT05FTlQsIHdpZHRoXywgaGVpZ2h0XywgMCwKICAgICAgICAgICAgICAgICBHTF9ERVBUSF9DT01QT05FTlQsIEdMX1VOU0lHTkVEX0lOVCwgMCk7CiAgICBnbEJpbmRUZXh0dXJlKEdMX1RFWFRVUkVfMkQsIDApOwoKICAgIGdsR2VuRnJhbWVidWZmZXJzKDEsICZmYm9fKTsKICAgIGdsQmluZEZyYW1lYnVmZmVyKEdMX0ZSQU1FQlVGRkVSLCBmYm9fKTsKICAgIGdsRnJhbWVidWZmZXJUZXh0dXJlMkQoR0xfRlJBTUVCVUZGRVIsIEdMX0RFUFRIX0FUVEFDSE1FTlQsIEdMX1RFWFRVUkVfMkQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleF8sIDApOwogICAgdW5zaWduZWQgaW50IHN0YXR1cyA9IGdsQ2hlY2tGcmFtZWJ1ZmZlclN0YXR1cyhHTF9GUkFNRUJVRkZFUik7CiAgICBpZiAoc3RhdHVzICE9IEdMX0ZSQU1FQlVGRkVSX0NPTVBMRVRFKSB7CiAgICAgICAgTG9nOjplcnJvcigiRGVwdGhSZW5kZXJTdGF0ZTo6c2V0dXA6IGdsQ2hlY2tGcmFtZWJ1ZmZlclN0YXR1cyBmYWlsZWQgKDB4JXgpXG4iLCBzdGF0dXMpOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGdsQmluZEZyYW1lYnVmZmVyKEdMX0ZSQU1FQlVGRkVSLCAwKTsKCiAgICByZXR1cm4gdHJ1ZTsKfQoKdm9pZApEaXN0YW5jZVJlbmRlclRhcmdldDo6dGVhcmRvd24oKQp7CiAgICBwcm9ncmFtXy5zdG9wKCk7CiAgICBwcm9ncmFtXy5yZWxlYXNlKCk7CiAgICBpZiAodGV4XykgewogICAgICAgIGdsRGVsZXRlVGV4dHVyZXMoMSwgJnRleF8pOwogICAgICAgIHRleF8gPSAwOwogICAgfQogICAgaWYgKGZib18pIHsKICAgICAgICBnbERlbGV0ZUZyYW1lYnVmZmVycygxLCAmZmJvXyk7CiAgICAgICAgZmJvXyA9IDA7CiAgICB9Cn0KCnZvaWQKRGlzdGFuY2VSZW5kZXJUYXJnZXQ6OmVuYWJsZShjb25zdCBtYXQ0JiBtdnApCnsKICAgIHByb2dyYW1fLnN0YXJ0KCk7CiAgICBwcm9ncmFtX1siTW9kZWxWaWV3UHJvamVjdGlvbk1hdHJpeCJdID0gbXZwOwogICAgZ2xCaW5kRnJhbWVidWZmZXIoR0xfRlJBTUVCVUZGRVIsIGZib18pOwogICAgZ2xGcmFtZWJ1ZmZlclRleHR1cmUyRChHTF9GUkFNRUJVRkZFUiwgR0xfREVQVEhfQVRUQUNITUVOVCwgR0xfVEVYVFVSRV8yRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4XywgMCk7CiAgICBnbFZpZXdwb3J0KDAsIDAsIHdpZHRoXywgaGVpZ2h0Xyk7CiAgICBnbENvbG9yTWFzayhHTF9GQUxTRSwgR0xfRkFMU0UsIEdMX0ZBTFNFLCBHTF9GQUxTRSk7CiAgICBnbENsZWFyKEdMX0RFUFRIX0JVRkZFUl9CSVQpOwp9Cgp2b2lkIERpc3RhbmNlUmVuZGVyVGFyZ2V0OjpkaXNhYmxlKCkKewogICAgZ2xCaW5kRnJhbWVidWZmZXIoR0xfRlJBTUVCVUZGRVIsIDApOwogICAgZ2xWaWV3cG9ydCgwLCAwLCBjYW52YXNfd2lkdGhfLCBjYW52YXNfaGVpZ2h0Xyk7CiAgICBnbENvbG9yTWFzayhHTF9UUlVFLCBHTF9UUlVFLCBHTF9UUlVFLCBHTF9UUlVFKTsKfQoKYm9vbApSZWZyYWN0UHJpdmF0ZTo6c2V0dXAobWFwPHN0cmluZywgU2NlbmU6Ok9wdGlvbj4mIG9wdGlvbnMpCnsKICAgIC8vIFByb2dyYW0gb2JqZWN0IHNldHVwCiAgICBzdGF0aWMgY29uc3Qgc3RyaW5nIHZ0eF9zaGFkZXJfZmlsZW5hbWUoR0xNQVJLX0RBVEFfUEFUSCIvc2hhZGVycy9saWdodC1yZWZyYWN0LnZlcnQiKTsKICAgIHN0YXRpYyBjb25zdCBzdHJpbmcgZnJnX3NoYWRlcl9maWxlbmFtZShHTE1BUktfREFUQV9QQVRIIi9zaGFkZXJzL2xpZ2h0LXJlZnJhY3QuZnJhZyIpOwogICAgc3RhdGljIGNvbnN0IHZlYzQgbWF0ZXJpYWxEaWZmdXNlKDAuMGYsIDAuMGYsIDAuMGYsIDAuMGYpOwogICAgc3RhdGljIGNvbnN0IHZlYzQgbGlnaHRDb2xvcigxLjAsIDEuMCwgMS4wLCAxLjApOwoKICAgIFNoYWRlclNvdXJjZSB2dHhfc291cmNlKHZ0eF9zaGFkZXJfZmlsZW5hbWUpOwogICAgU2hhZGVyU291cmNlIGZyZ19zb3VyY2UoZnJnX3NoYWRlcl9maWxlbmFtZSk7CgogICAgZnJnX3NvdXJjZS5hZGRfY29uc3QoIkxpZ2h0Q29sb3IiLCBsaWdodENvbG9yKTsKICAgIGZyZ19zb3VyY2UuYWRkX2NvbnN0KCJMaWdodFNvdXJjZVBvc2l0aW9uIiwgbGlnaHRQb3NpdGlvbik7CiAgICBmcmdfc291cmNlLmFkZF9jb25zdCgiTWF0ZXJpYWxEaWZmdXNlIiwgbWF0ZXJpYWxEaWZmdXNlKTsKCiAgICBpZiAoIVNjZW5lOjpsb2FkX3NoYWRlcnNfZnJvbV9zdHJpbmdzKHByb2dyYW1fLCB2dHhfc291cmNlLnN0cigpLCBmcmdfc291cmNlLnN0cigpKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICBjb25zdCBzdHJpbmcmIHdoaWNoVGV4dHVyZShvcHRpb25zWyJ0ZXh0dXJlIl0udmFsdWUpOwogICAgaWYgKCFUZXh0dXJlOjpsb2FkKHdoaWNoVGV4dHVyZSwgJnRleHR1cmVfLCBHTF9MSU5FQVIsIEdMX0xJTkVBUiwgMCkpCiAgICAgICAgcmV0dXJuIGZhbHNlOwoKICAgIC8vIE1vZGVsIHNldHVwCiAgICBNb2RlbCBtb2RlbDsKICAgIGNvbnN0IHN0cmluZyYgd2hpY2hNb2RlbChvcHRpb25zWyJtb2RlbCJdLnZhbHVlKTsKICAgIGJvb2wgbW9kZWxMb2FkZWQgPSBtb2RlbC5sb2FkKHdoaWNoTW9kZWwpOwoKICAgIGlmKCFtb2RlbExvYWRlZCkKICAgICAgICByZXR1cm4gZmFsc2U7CgogICAgLy8gTm93IHRoYXQgd2UncmUgc3VjY2Vzc2Z1bGx5IGxvYWRlZCwgdGhlcmUgYXJlIGEgZmV3IHF1aXJrcyBhYm91dAogICAgLy8gc29tZSBvZiB0aGUga25vd24gbW9kZWxzIHRoYXQgd2UgbmVlZCB0byBhY2NvdW50IGZvci4gIFRoZSBkcmF3CiAgICAvLyBsb2dpYyBmb3IgdGhlIHNjZW5lIHdhbnRzIHRvIHJvdGF0ZSB0aGUgbW9kZWwgYXJvdW5kIHRoZSBZIGF4aXMuCiAgICAvLyBNb3N0IG9mIG91ciBtb2RlbHMgYXJlIGRlc2NyaWJlZCB0aGlzIHdheS4gIFNvbWUgbmVlZCBhZGp1c3RtZW50CiAgICAvLyAoYW4gYWRkaXRpb25hbCByb3RhdGlvbiB0aGF0IGdldHMgdGhlIG1vZGVsIGludG8gdGhlIGNvcnJlY3QKICAgIC8vIG9yaWVudGF0aW9uKS4KICAgIC8vCiAgICAvLyBIZXJlJ3MgYSBzdW1tYXJ5OgogICAgLy8KICAgIC8vIEFuZ2VsIHJvdGF0ZXMgYXJvdW5kIHRoZSBZIGF4aXMKICAgIC8vIEFybWFkaWxsbyByb3RhdGVzIGFyb3VuZCB0aGUgWSBheGlzCiAgICAvLyBCdWRkaGEgcm90YXRlcyBhcm91bmQgdGhlIFggYXhpcwogICAgLy8gQnVubnkgcm90YXRlcyBhcm91bmQgdGhlIFkgYXhpcwogICAgLy8gRHJhZ29uIHJvdGF0ZXMgYXJvdW5kIHRoZSBYIGF4aXMKICAgIC8vIEhvcnNlIHJvdGF0ZXMgYXJvdW5kIHRoZSBZIGF4aXMKICAgIGlmICh3aGljaE1vZGVsID09ICJidWRkaGEiIHx8IHdoaWNoTW9kZWwgPT0gImRyYWdvbiIpCiAgICB7CiAgICAgICAgb3JpZW50TW9kZWxfID0gdHJ1ZTsKICAgICAgICBvcmllbnRhdGlvbkFuZ2xlXyA9IC05MC4wOwogICAgICAgIG9yaWVudGF0aW9uVmVjXyA9IHZlYzMoMS4wLCAwLjAsIDAuMCk7CiAgICB9CiAgICBlbHNlIGlmICh3aGljaE1vZGVsID09ICJhcm1hZGlsbG8iKQogICAgewogICAgICAgIG9yaWVudE1vZGVsXyA9IHRydWU7CiAgICAgICAgb3JpZW50YXRpb25BbmdsZV8gPSAxODAuMDsgCiAgICAgICAgb3JpZW50YXRpb25WZWNfID0gdmVjMygwLjAsIDEuMCwgMC4wKTsKICAgIH0KCiAgICBtb2RlbC5jYWxjdWxhdGVfbm9ybWFscygpOwoKICAgIC8vIE1lc2ggc2V0dXAKICAgIHZlY3RvcjxzdGQ6OnBhaXI8TW9kZWw6OkF0dHJpYlR5cGUsIGludD4gPiBhdHRyaWJzOwogICAgYXR0cmlicy5wdXNoX2JhY2soc3RkOjpwYWlyPE1vZGVsOjpBdHRyaWJUeXBlLCBpbnQ+KE1vZGVsOjpBdHRyaWJUeXBlUG9zaXRpb24sIDMpKTsKICAgIGF0dHJpYnMucHVzaF9iYWNrKHN0ZDo6cGFpcjxNb2RlbDo6QXR0cmliVHlwZSwgaW50PihNb2RlbDo6QXR0cmliVHlwZU5vcm1hbCwgMykpOwogICAgbW9kZWwuY29udmVydF90b19tZXNoKG1lc2hfLCBhdHRyaWJzKTsKCiAgICB1c2VWYm9fID0gKG9wdGlvbnNbInVzZS12Ym8iXS52YWx1ZSA9PSAidHJ1ZSIpOwogICAgYm9vbCBpbnRlcmxlYXZlID0gKG9wdGlvbnNbImludGVybGVhdmUiXS52YWx1ZSA9PSAidHJ1ZSIpOwogICAgbWVzaF8udmJvX3VwZGF0ZV9tZXRob2QoTWVzaDo6VkJPVXBkYXRlTWV0aG9kTWFwKTsKICAgIG1lc2hfLmludGVybGVhdmUoaW50ZXJsZWF2ZSk7CgogICAgaWYgKHVzZVZib18pIHsKICAgICAgICBtZXNoXy5idWlsZF92Ym8oKTsKICAgIH0KICAgIGVsc2UgewogICAgICAgIG1lc2hfLmJ1aWxkX2FycmF5KCk7CiAgICB9CgogICAgLy8gQ2FsY3VsYXRlIGEgcHJvamVjdGlvbiBtYXRyaXggdGhhdCBpcyBhIGdvb2QgZml0IGZvciB0aGUgbW9kZWwKICAgIHZlYzMgbWF4VmVjID0gbW9kZWwubWF4VmVjKCk7CiAgICB2ZWMzIG1pblZlYyA9IG1vZGVsLm1pblZlYygpOwogICAgdmVjMyBkaWZmVmVjID0gbWF4VmVjIC0gbWluVmVjOwogICAgY2VudGVyVmVjXyA9IG1heFZlYyArIG1pblZlYzsKICAgIGNlbnRlclZlY18gLz0gMi4wOwogICAgZmxvYXQgZGlhbWV0ZXIgPSBkaWZmVmVjLmxlbmd0aCgpOwogICAgcmFkaXVzXyA9IGRpYW1ldGVyIC8gMjsKICAgIGZsb2F0IGZvdnkgPSAyLjAgKiBhdGFuZihyYWRpdXNfIC8gKDIuMCArIHJhZGl1c18pKTsKICAgIGZvdnkgLz0gTV9QSTsKICAgIGZvdnkgKj0gMTgwLjA7CiAgICBmbG9hdCBhc3BlY3Qoc3RhdGljX2Nhc3Q8ZmxvYXQ+KGNhbnZhc18ud2lkdGgoKSkvc3RhdGljX2Nhc3Q8ZmxvYXQ+KGNhbnZhc18uaGVpZ2h0KCkpKTsKICAgIHByb2plY3Rpb25fLnBlcnNwZWN0aXZlKGZvdnksIGFzcGVjdCwgMi4wLCA1MC4wKTsKCiAgICBpZiAoIWRlcHRoVGFyZ2V0Xy5zZXR1cChjYW52YXNfLndpZHRoKCksIGNhbnZhc18uaGVpZ2h0KCkpKSB7CiAgICAgICAgTG9nOjplcnJvcigiRmFpbGVkIHRvIHNldCB1cCB0aGUgcmVuZGVyIHRhcmdldCBmb3IgdGhlIGRlcHRoIHBhc3NcbiIpOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKfQp2b2lkClJlZnJhY3RQcml2YXRlOjp0ZWFyZG93bigpCnsKICAgIGRlcHRoVGFyZ2V0Xy50ZWFyZG93bigpOwogICAgcHJvZ3JhbV8uc3RvcCgpOwogICAgcHJvZ3JhbV8ucmVsZWFzZSgpOwogICAgbWVzaF8ucmVzZXQoKTsKfQoKdm9pZApSZWZyYWN0UHJpdmF0ZTo6dXBkYXRlKGRvdWJsZSBlbGFwc2VkVGltZSkKewogICAgcm90YXRpb25fID0gcm90YXRpb25TcGVlZF8gKiBlbGFwc2VkVGltZTsKfQoKdm9pZApSZWZyYWN0UHJpdmF0ZTo6ZHJhdygpCnsKICAgIC8vIFRvIHBlcmZvcm0gdGhlIGRlcHRoIHBhc3MsIHNldCB1cCB0aGUgbW9kZWwtdmlldyB0cmFuc2Zvcm1hdGlvbiBzbwogICAgLy8gdGhhdCB3ZSdyZSBsb29raW5nIGF0IHRoZSBob3JzZSBmcm9tIHRoZSBsaWdodCBwb3NpdGlvbi4gIFRoYXQgd2lsbAogICAgLy8gZ2l2ZSB1cyB0aGUgYXBwcm9wcmlhdGUgdmlldyBmb3IgdGhlIHNoYWRvdy4KICAgIG1vZGVsdmlld18ucHVzaCgpOwogICAgbW9kZWx2aWV3Xy5sb2FkSWRlbnRpdHkoKTsKICAgIG1vZGVsdmlld18ubG9va0F0KGxpZ2h0UG9zaXRpb24ueCgpLCBsaWdodFBvc2l0aW9uLnkoKSwgbGlnaHRQb3NpdGlvbi56KCksCiAgICAgICAgICAgICAgICAgICAgICAwLjAsIDAuMCwgMC4wLAogICAgICAgICAgICAgICAgICAgICAgMC4wLCAxLjAsIDAuMCk7CiAgICBtb2RlbHZpZXdfLnJvdGF0ZShyb3RhdGlvbl8sIDAuMGYsIDEuMGYsIDAuMGYpOwogICAgbWF0NCBtdnAocHJvamVjdGlvbl8uZ2V0Q3VycmVudCgpKTsKICAgIG12cCAqPSBtb2RlbHZpZXdfLmdldEN1cnJlbnQoKTsKICAgIG1vZGVsdmlld18ucG9wKCk7CgogICAgLy8gRW5hYmxlIHRoZSBkZXB0aCByZW5kZXIgdGFyZ2V0IHdpdGggb3VyIHRyYW5zZm9ybWF0aW9uIGFuZCByZW5kZXIuCiAgICBkZXB0aFRhcmdldF8uZW5hYmxlKG12cCk7CiAgICB2ZWN0b3I8R0xpbnQ+IGF0dHJpYl9sb2NhdGlvbnM7CiAgICBhdHRyaWJfbG9jYXRpb25zLnB1c2hfYmFjayhkZXB0aFRhcmdldF8ucHJvZ3JhbSgpWyJwb3NpdGlvbiJdLmxvY2F0aW9uKCkpOwogICAgYXR0cmliX2xvY2F0aW9ucy5wdXNoX2JhY2soZGVwdGhUYXJnZXRfLnByb2dyYW0oKVsibm9ybWFsIl0ubG9jYXRpb24oKSk7CiAgICBtZXNoXy5zZXRfYXR0cmliX2xvY2F0aW9ucyhhdHRyaWJfbG9jYXRpb25zKTsKICAgIGlmICh1c2VWYm9fKSB7CiAgICAgICAgbWVzaF8ucmVuZGVyX3ZibygpOwogICAgfQogICAgZWxzZSB7CiAgICAgICAgbWVzaF8ucmVuZGVyX2FycmF5KCk7CiAgICB9CiAgICBkZXB0aFRhcmdldF8uZGlzYWJsZSgpOwoKICAgIC8vIEdyb3VuZCByZW5kZXJpbmcgdXNpbmcgdGhlIGFib3ZlIGdlbmVyYXRlZCB0ZXh0dXJlLi4uCiAgICAvL2dyb3VuZF8uZHJhdygpOwoKICAgIC8vIERyYXcgdGhlICJub3JtYWwiIHZpZXcgb2YgdGhlIGhvcnNlCiAgICBtb2RlbHZpZXdfLnB1c2goKTsKICAgIG1vZGVsdmlld18udHJhbnNsYXRlKC1jZW50ZXJWZWNfLngoKSwgLWNlbnRlclZlY18ueSgpLCAtKGNlbnRlclZlY18ueigpICsgMi4wICsgcmFkaXVzXykpOwogICAgbW9kZWx2aWV3Xy5yb3RhdGUocm90YXRpb25fLCAwLjBmLCAxLjBmLCAwLjBmKTsKICAgIG12cCA9IHByb2plY3Rpb25fLmdldEN1cnJlbnQoKTsKICAgIG12cCAqPSBtb2RlbHZpZXdfLmdldEN1cnJlbnQoKTsKCiAgICBwcm9ncmFtXy5zdGFydCgpOwogICAgZ2xBY3RpdmVUZXh0dXJlKEdMX1RFWFRVUkUwKTsKICAgIGdsQmluZFRleHR1cmUoR0xfVEVYVFVSRV8yRCwgdGV4dHVyZV8pOwogICAgcHJvZ3JhbV9bIkRpc3RhbmNlTWFwIl0gPSAwOwogICAgcHJvZ3JhbV9bIk1vZGVsVmlld1Byb2plY3Rpb25NYXRyaXgiXSA9IG12cDsKCiAgICAvLyBMb2FkIHRoZSBOb3JtYWxNYXRyaXggdW5pZm9ybSBpbiB0aGUgc2hhZGVyLiBUaGUgTm9ybWFsTWF0cml4IGlzIHRoZQogICAgLy8gaW52ZXJzZSB0cmFuc3Bvc2Ugb2YgdGhlIG1vZGVsIHZpZXcgbWF0cml4LgogICAgbWF0NCBub3JtYWxfbWF0cml4KG1vZGVsdmlld18uZ2V0Q3VycmVudCgpKTsKICAgIG5vcm1hbF9tYXRyaXguaW52ZXJzZSgpLnRyYW5zcG9zZSgpOwogICAgcHJvZ3JhbV9bIk5vcm1hbE1hdHJpeCJdID0gbm9ybWFsX21hdHJpeDsKICAgIGF0dHJpYl9sb2NhdGlvbnMuY2xlYXIoKTsKICAgIGF0dHJpYl9sb2NhdGlvbnMucHVzaF9iYWNrKHByb2dyYW1fWyJwb3NpdGlvbiJdLmxvY2F0aW9uKCkpOwogICAgYXR0cmliX2xvY2F0aW9ucy5wdXNoX2JhY2socHJvZ3JhbV9bIm5vcm1hbCJdLmxvY2F0aW9uKCkpOwogICAgbWVzaF8uc2V0X2F0dHJpYl9sb2NhdGlvbnMoYXR0cmliX2xvY2F0aW9ucyk7CiAgICBpZiAodXNlVmJvXykgewogICAgICAgIG1lc2hfLnJlbmRlcl92Ym8oKTsKICAgIH0KICAgIGVsc2UgewogICAgICAgIG1lc2hfLnJlbmRlcl9hcnJheSgpOwogICAgfQoKICAgIC8vIFBlci1mcmFtZSBjbGVhbnVwCiAgICBtb2RlbHZpZXdfLnBvcCgpOwp9Cgo=