UmVmYWN0b3JpbmdzIC8gVGlkeWluZyB0aGluZ3MgdXAKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgoqIHJlZmFjdG9yIEludm9rZXJFeGNlcHRpb24gJiByZWxhdGVkIGV4Y2VwdGlvbnMgdG8gYmUgZ3Jvb3Z5LmxhbmcKCS0gYmV0dGVyIG5hbWUgZm9yIEludm9rZXJFeGNlcHRpb24/CgktIG1heWJlIHJvb3QgR3Jvb3Z5UnVudGltZUV4Y2VwdGlvbgoJCiogcmVmYWN0b3IgTWV0YUNsYXNzIHRvIEdyb292eUNsYXNzPwoqIG1heWJlIHJlZmFjdG9yIFNjcmlwdENvbnRleHQgaW50byBHcm9vdnlTaGVsbD8KKiBncm9vdnkubW9kZWwgLT4gZ3Jvb3Z5Lm12Yz8KKiBncm9vdnkuZ2RvIC0+IGdyb292eS5zcWw/CgoKVGhpbmdzIHRvIFRlc3QKPT09PT09PT09PT09PT0KCiogaG9tZSBwYWdlIHRlc3RlcgoKKiBkbyB3aWtpIHBsdWdpbiB0byBhdXRvLXRlc3QgdGhlIGV4YW1wbGVzCgoqIHRlc3Qgc3luY2hyb25pemVkIHN0YXRlbWVudAoKKiBleHBvcnQgc2NyaXB0IHZhcmlhYmxlcyB3aGVuIHVzaW5nIHRoZSBjb25zb2xlCgoqIHRlc3QgZG8gd2hpbGUKCiogdGVzdCBjb21waWxlciBlcnJvcnMgd2hlbgoJLSBkdXBsaWNhdGUgbWV0aG9kcyB0ZXN0CgktIGR1cGxpY2F0ZSBjbGFzcyBpbiBtb2R1bGUKCQoqIGR1cGxpY2F0ZSBjbGFzcyBkZWZpbml0aW9uOiBDbG9zdXJlTWV0aG9kVGVzdCQ0Cgk8Ym9iPglqYXZhLmxhbmcuTGlua2FnZUVycm9yOiBkdXBsaWNhdGUgY2xhc3MgZGVmaW5pdGlvbjogQ2xvc3VyZU1ldGhvZFRlc3QkNAoJPGJvYj4JICAgICAgICBhdCBqYXZhLmxhbmcuQ2xhc3NMb2FkZXIuZGVmaW5lQ2xhc3MwKE5hdGl2ZSBNZXRob2QpCgk8Ym9iPgkgICAgICAgIGF0IGphdmEubGFuZy5DbGFzc0xvYWRlci5kZWZpbmVDbGFzcyhDbGFzc0xvYWRlci5qYXZhOjUwMikKCTxib2I+CSAgICAgICAgYXQgamF2YS5sYW5nLkNsYXNzTG9hZGVyLmRlZmluZUNsYXNzKENsYXNzTG9hZGVyLmphdmE6NDMxKQoJPGJvYj4JICAgICAgICBhdCBncm9vdnkubGFuZy5Hcm9vdnlDbGFzc0xvYWRlci5vbkNsYXNzTm9kZShHcm9vdnlDbGFzc0xvYWRlci5qYXZhOjEwOCkKCTxib2I+CSAgICAgICAgYXQgb3JnLmNvZGVoYXVzLmdyb292eS5jbGFzc2dlbi5UZXN0U3VwcG9ydCQxLm9uQ2xhc3NOb2RlKFRlc3RTdXBwb3J0LmphdmE6OTYpCgoKKiB0ZXN0IGRhdGUgcmFuZ2UgdXNpbmcgUmFuZ2Ugb2JqZWN0CgoqIHRlc3QgbWF4LCBtaW4sIHNvcnQgd2l0aCBjbG9zdXJlIGNvbXBhcmF0b3IKCS0gbWluL21heC9zb3J0IHRvIGFsbG93IGNsb3N1cmVzIGZvciBjb21wYXJhdG9ycwoJCWZvby5tYXggeyBhLCBiIHwgYS5sZW5ndGggPD0+IGIubGVuZ3RoIH0KCS0gQ2xvc3VyZUNvbXBhcmF0b3IKCQkJCiogdGVzdCBCdXR0b24oYWN0aW9uUGVyZm9ybWVkOntldmVudHwgZXZlbnQucHJpbnRsbigpIH0KCiogcmVtb3ZlIGRlcGVuZGVuY3kgb24gYXNtLXV0aWwgb24gdGhlIGNvbXBpbGVyCgoJCkNvcmUgR3Jvb3Z5IFRhc2tzCj09PT09PT09PT09PT09PT09CgoqIGFsbG93IG1hcHMgdG8gYmUgY3JlYXRlZCB1c2luZyBpZGVudGlmaWVycz8KCXtuYW1lOidKYW1lcycsIGFkZHJlc3M6J0xvbmRvbid9CgkKCW9ubHkgaXNzdWUgaXMgdGhlIGlkZW50aWZpZXJzIGNvdWxkIGNvbmZsaWN0LgoKKiBoYW5kbGluZyBzZXF1ZW5jZXMgKDAtbiwgMS1uKQoJdGhleSBhcmUgTGlzdHMgJiBiZWhhdmUgbGlrZSBsaXN0cywgYW55IG1ldGhvZHMgb24gdGhlIGl0ZW1zIHdpbGwKCWJlIGNhbGxlZCBldGMuCgkKCWhvd2V2ZXIgaG93IGFyZSB0aGV5IGFzc2lnbmVkIC8gbW9kaWZpZWQuCgkKCQlmb28uY3VzdG9tZXJzICs9IGN1c3RvbWVyCgkJCgkJZm9vLmN1c3RvbWVycyA9IFtjdXN0b21lcjEsIGN1c3RvbWVyMl0KCQkKCQlzbyBhc3NpZ25tZW50IG9mIHNlcXVlbmNlIGZpZWxkcyBkb24ndCByZWFsbHkgZG8gYW4gYXNzaWduOyB0aGV5IGRvIGEgc2V0KExpc3QpIGluc3RlYWQKCQkKCQktIHNob3VsZCB3ZSBhbGxvdyByZWFsIGFzc2lnbm1lbnRzLiBlLmcuCgkJCgkJQWRkcmVzcyogZm9vID0gLi4uOwoJCWZvbyA9IFsxLCAyLCAzXQoJCQoJCWZvbyBrZWVwcyBpdHMgdHlwZSBzbyBpdHMgbm90IGEgTGlzdAoJCQoJaG93IGFib3V0IGhhbmRsaW5nIG1hbmRhdG9yeSB2YWx1ZXMgLSAKCQl0aGUgc2V0IHdlIG92ZXJsb2FkIHRvIGRvIHRoZSBub24tbnVsbCBjaGVja3M/CgkJdGhpcyBtdXN0IGJlIGEgdHlwZS4gZS5nLgoJCQoJCQlTdHJpbmchIHggPSAiaGVsbG8iCgkJCXggPSBudWxsIC8vIGVycm9yCgkJCQoqIG5ldyBHcm9vdnlNZXRob2RzCXRvIGJlIGFkZGVkCgktIE9iamVjdC5nZXRNZXRhQ2xhc3MoKQoJLSBPYmplY3QuZWFjaFByb3BlcnR5CgktIE9iamVjdC5lYWNoUHJvcGVydHlOYW1lIHsgb2JqZWN0LmdldFByb3BlcnR5KGl0KSB9CgktIE9iamVjdC5zZXRQcm9wZXJ0aWVzKGZvbzonYWJjJywgeDoxMjMpCgkKCS0gcmVtb3ZlSWYgeyB4IHwgeCA+IDAgfQoJLSBMaXN0LmZpcnN0LCBMaXN0Lmxhc3QsIHBvcAoJLSBMaXN0LmVhY2hXaXRoaW5kZXggeyBpdGVtLCBpZHggfCAuLi4gfQoJLSByZXZlcnNlRWFjaCB7IC4uLiB9CgktIE1hcC5lYWNoS2V5LCBlYWNoVmFsdWUKCS0gTWFwLmluZGV4LCBNYXAuaW5kZXhlcwoJLSBPYmplY3QuZGlzcGxheSAocmF0aGVyIHRoYW4gdG9Db25zb2xlT3V0cHV0KQoJLSBncmVwKHBhdHRlcm4pICB7IGNsb3N1cmUgfQoJCXdoZXJlIHBhdHRlcm4gPSByYW5nZSAvIHJlZ2V4cAoJLSBldmFsKCIuLi4uIikKCS0gZ2V0cwoJLSBsb2FkKC4uLikKCS0gRmlsZS5lYWNoQnl0ZQoJLSBjb25maWd1cmUgbWV0aG9kIG9uIGJlYW5zPwoJCWJlYW4uc2V0UHJvcGVydGllcyhuYW1lOidKYW1lcycsIGxvY2F0aW9uOidMb25kb24nKQoJLSBzb21lIGtpbmQgb2YgUmVnZXhwIGl0ZXJhdG9yIG9mIHN0cmluZ3MgbGlrZSBSdWJ5J3Mgc2NhbgoJLSBtYXliZSBzdXBwb3J0IFB5dGhvbnMnIHppcCBhbmQgcmVkdWNlIGZ1bmN0aW9ucz8KCS0gTWFwLmdldChrZXksIGRlZmF1bHRWYWx1ZSkKCS0gTWFwLnNldERlZmF1bHQoa2V5LCBkZWZhdWx0VmFsdWUpIGZvciB0aGluZ3MgbGlrZQoJIG1hcC5zZXREZWZhdWx0KGtleSwgW10pLmFkZChuZXdWYWx1ZSkKCQoJLSBsaXN0LnNvcnRCeSB7IFtpdC5uYW1lLCBpdC5sb2NhdGlvbl0gfQoJLSBsaXN0LnNvcnQgeyBhLCBiIHwgYS5uYW1lIDw9PiBiLm5hbWUgfQoJCgl0byBlbnN1cmUgdGhlIG1hcCBoYXMgYSBsaXN0IG9mIHRoaW5ncwoKCQltYXliZSBhZGQgdGhlIHZhcmlvdXMgcmVhZG9ubHkgTGlzdCBBUElzIHRvIE9iamVjdFtdIGFuZCAqW10gdHlwZXMKCQlpZiB3ZSBldmVyIHN1cHBvcnQgdGhlIERURCAvIFhlZCBzdHlsZSB0eXBlKiwgdHlwZSsgdGhlbiB3ZSBjYW4gZG8gdGhlIHNhbWUKCQl0aGVyZSB0b28KCiogYWRkIGRvZXNOb3RVbmRlcnN0YW5kKCkgbWV0aG9kIGZvciBjYXRjaGluZyAmIGhhbmRsaW5nIHVua25vd24gbWV0aG9kcwkKCQkKKiA8PCBmb3IgbGlzdCBhcHBlbmQgYW5kIGZvciBvdXRwdXQgdG8gc3RyZWFtcwoJbWF5YmUgb3RoZXIgb3B0aW9uYWwgSU8gbWV0aG9kcyBsaWtlIGdldHM/CgoqIGlzIHRoZXJlIGEgYmV0dGVyIHdheSB0byBhZGQgbGlzdGVuZXJzIGluIEdyb292eS4gZS5nLiBob3cgdG8gcmVtb3ZlIGFkZGVkIGxpc3RlbmVycwoKCWxpc3RlbmVyID0gYmVhbi5wcm9wZXJ0eSArIHsgc29tZSBjbG9zdXJlIH0KCWJlYW4ucHJvcGVydHkgLSBsaXN0ZW5lcgoJCiogLkAgc3VwcG9ydCBvbiBXM0MgRE9NIHRyZWVzLi4uCgl0aG91Z2ggd2UgbWlnaHQgd2FubmEgdXNlIEAgdG8gcmVmZXIgdG8gYXR0cmlidXRlcz8KCQoqIEJlYW5CdWlsZGVyIC0gYnVpbGRlciB3aGljaCBjcmVhdGVzIGEgdHJlZSBvZiBiZWFucwoJYnVpbGRlci5iZWFuKGNsYXNzOlNvbWVDbGFzcywgeDoxMjMsIGI6J2hlbGxvJykgewoJCW5lc3RlZFByb3BlcnR5KGE6MTIzKQoJCW5lc3RlZFByb3BlcnR5MihjbGFzczpEZXJpdmVkQ2xhc3MsIGI6NDMpCgl9Cgl1c2luZyBhZGRlciBtZXRob2QgYXMgd2VsbCBhcyBzZXR0ZXIgbWV0aG9kcwoKKiBNQmVhbkJ1aWxkZXI/CglidWlsZGVyLm1sZXQgewoJCW1iZWFuKGNsYXNzOlNvbWVDbGFzcykgewoJCQlzb21lQXR0cmlidXRlKHZhbHVlKQoJCX0KCQltYmVhbihjbGFzczpTb21lQ2xhc3MsIHNvbWVBdHRyaWJ1dGU6dmFsdWUpIHsKCQkJb3BlcmF0aW9uKDEsIDIpCgkJfQoJfQoKKiB0ZW1wbGF0aW5nIC0gYWxsb3cgbG9vcGluZyAmIGNvbmRpdGlvbmFscz8KCnRleHQgPSAiCjx0YWJsZT4KI2ZvciAoZiBpbiBmb28pCjx0cj4KPHRkPiR7Zi5uYW1lfQo8L3RyPgojZW5kCjwvdGFibGU+CiIKCiogYWxsb3cgaWYvc3dpdGNoIHRvIGJlIHRoZSBhbmQgb2YgYSBmdW5jdGlvbi4gaS5lLgoJZm9vKCkgewoJCWlmICh4ID4gMSkgewoJCQkiaGVsbG8iCgkJfQoJCWVsc2UgewoJCQkiY2hlZXNlIgoJCX0KCX0KCWRpdHRvIGZvciBzd2l0Y2g/IGkuZS4gbWFrZSByZXR1cm4gc3RhdGVtZW50IG9wdGlvbmFsLgoJCgoqIFNRTCBidWlsZGVyCgpzcWwudGFibGUoInVzZXJzIikgewrKysogY29sdW1uKCd1c2VyLWlkJykgeyBhdXRvaW5jKCksIHByaW1hcnlLZXkoKSwgcmVmZXJlbmNlcygnZm9vJyksIGluaXRpYWxWYWx1ZSgxMjM0KSB9CsrKyiBjb2x1bW4oJ25pY2tuYW1lJykgeyB2YXJjaGFyKDIwMCkgfQoJY29sdW1uKG5hbWU6J2ZvbycsIHR5cGU6J3ZhcmNoYXIoMjAwKScsIHJlZmVyZW5jZXM6WydhJywgJ2InXSwgaW5pdGlhbFZhbHVlOjEyMzQpCiAgfQp9CgoqIHVzaW5nIG1peGluIGZvciBhZGRpbmcgdXNpbmcgc3R5bGUgYmVoYXZpb3VyIHRvIGFueSBvYmplY3Q/PwoKCW1peGluIFVzaW5nIHsKCQoJCXN0YXRpYyB1c2luZyh5aWVsZCkgewoJCQlvYmplY3QgPSB0aGlzLm5ld0luc3RhbmNlKCkKCQkJdHJ5IHsKCQkJCXlpZWxkKG9iamVjdCkKCQkJCW9iamVjdC5jbG9zZSgpCgkJCX0KCQkJY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQl0cnkgewoJCQkJCW9iamVjdC5jbG9zZSgpCgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGUyKQoJCQkJCS8vIGlnbm9yZSBlMgoJCQkJCXRocm93IGUKCQkJCX0KCQkJfQoJCX0KCQkKCQlvcgoJCQoJCXVzaW5nKHlpZWxkKSB7CgkJCXRyeSB7CgkJCQl5aWVsZCh0aGlzKQoJCQkJY2xvc2UoKQoJCQl9CgkJCWNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJdHJ5IHsKCQkJCQljbG9zZSgpCgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGUyKQoJCQkJCS8vIGlnbm9yZSBlMgoJCQkJCXRocm93IGUKCQkJCX0KCQkJfQoJCX0KCX0KCQoJdGhlbiB1c2UgaXQgYXMgCgkKCQluZXcgRmlsZUlucHV0U3RyZWFtKCkudXNpbmcgeyBpbiB8CgkJCS4uLgoJCX0KCiogbG9va3MgbGlrZSBhIGJ1ZyBvbiBnZW5lcmF0ZWQgbWV0aG9kcywgc2hvdWxkIHVzZSBwYXJhbSBuYW1lIG92ZXIgYW55IGZpZWxkIG5hbWUKCS0gYWxzbyBpdCBsb29rcyBsaWtlIHRoZXJlJ3MgdmFyaW91cyB1bm5lY2Vzc2FyeSBzdHVmZiAoY3JlYXRpb24gb2YgdHVwbGVzKSB3aGVuIGludm9raW5nCgltZXRob2RzCgkKKiBidWcgLSB4ID0gbWV0aG9kTmFtZSBmYWlscywgYnV0IHggPSB0aGlzLm1ldGhvZE5hbWUgd29ya3MKCiogZ3Jvb3Z5IHRocmVhZC4uLgoJZm9vID0gbmV3IEdyb292eVRocmVhZChhcmdzKSB7IGNsb3N1cmUgfQoJCiogZG9jIHRvIHdyaXRlCgktIHVzaW5nIGJlYW5zICsgbGlzdGVuZXJzCgktIGV4cHJlc3Npb24gbGFuZ3VhZ2UKCiogYWxsb3cgY29uc3RydWN0b3JzIHRvIGhhdmUgb3B0aW9uYWwgdHJhaWxpbmcgY2xvc3VyZS4uLgoJbmV3IEpGcmFtZSgpIHsgdGV4dCA9ICdoZWxsbyc7IHNpemUgPSBbMSwgMl0gfQogIGNsb3N1cmUgb24gY29uc3RydWN0aW9uIG9mIGJlYW5zPwoJbmV3IEpUYWJsZSgpIHsuLi4ufQoJCWludm9rZXMgdGhlIGNsb3N1cmUgd2l0aCB0aGUgbmV3IG9iamVjdCBhcyBkZWxlZ2F0ZSBmb3Igc2V0dGluZyBwcm9wZXJ0aWVzIGV0YwoKKiBzdXBwb3J0IC12ZSBpbmRpY2VzIG9uIHN1YnNjcmlwdCBvcGVyYXRvcgoKKiBmb29bMSwgMl0gdmVyc3VzIGZvb1sxLi4yXSBldGMKCiogTWV0YUNsYXNzIC0+IGFkZCBnZXRQcm9wZXJ0eURlc2NyaXB0b3Igd2hpY2ggaGFzIG1ldGhvZHMKCS0gZ2V0KCksIHNldCgpLCB0eXBlKCksIGNhcmRpbmFsaXR5KCkgZXRjCgkKCWNvdWxkIHVzZSBuYW1pbmcgY29udmVudGlvbnMgdG8gZGV0ZWN0IGNhcmRpbmFsaXR5IC0gZS5nLiBhZGRGb28oKSwgZ2V0Rm9vcygpCgkKKiBnZW5lcmF0ZSBwcm9wZXJ0eSBjaGFuZ2UgbGlzdGVuZXIgc3R1ZmYgb24gcHJvcGVydGllcwoKKiB0ZXN0IGlkZW50aXR5IC0+IGhhc2hDb2RlICsgZXF1YWxzIG1ldGhvZHMKCiogc3VwcG9ydCBmb3IgcHJvcGVydHkgY29udmVydGVycywgYmFzZWQgb24gdHlwZQoKKiBtYXliZSBhZGQgcHl0aG9uJ3MgKiBhbmQgKiogZm9yIGFueSBudW1iZXIgb2YgYXJncyBvciBtYXBzIGluIG1ldGhvZCBkZWNsCgoqIHVzZSAqYXJncyBpbiBtZXRob2QgaW52b2NhdGlvbiB0byBleHBhbmQgYSBsaXN0IGFzIGFyZ3VtZW50IHZhbHVlcwkKCQoqIGdvIHRocm91Z2ggYWxsIG5vdC13b3JraW5nIEB0b2RvIHRlc3RzIGluIHNyYy90ZXN0CgkKKiB0byBzdXBwb3J0IGR5bmFtaWMgbWl4aW5zIHdlIHNob3VsZCB1c2UgZHluYW1pYyBwcm94aWVzIHRvIGFsbG93CglhIGdyb292eSBvYmplY3QgdG8gY2hhbmdlIG1ldGFjbGFzcyBhdCBydW50aW1lCgoqIGdyb292eSBkeW5hbWljIHByb3h5IG9mIGFueSBKYXZhIG9iamVjdCBpbiBKYXZhLWxhbmQ/CglOdWxsT2JqZWN0IHBhdHRlcm4KCQoqIGltbXV0YWJsZSBiZWFuCgoqIE1ldGFDbGFzcy5kZXJpdmVNZXRhQ2xhc3MoKQoJTWV0YUNsYXNzLmFkZE1peGluKG1peGluKQoKKiBjb25zdHJ1Y3RvcnMgd2l0aCBtYXAgLyB0dXBsZSBleHByZXNzaW9ucywgbmFtZWQgcGFyYW1ldGVyIGNhbGxpbmcKIAoqIGRlZmF1bHQgdmFsdWVzIGZvciBwYXJhbWV0ZXJzCgoqIHRlc3QgdHJ5IC8gY2F0Y2ggd2l0aCBtdWx0aXBsZSBleGNlcHRpb24gdHlwZXMKCiogdGVzdCBbXSBvbiBsaXN0cyAmIG1hcHM/CgoqIHNob3VsZCB3ZSBpbXBsZW1lbnQgKyBhbmQgLSBmb3IgY29sbGVjdGlvbnMgYW5kIG1hcHM/CgoJbCA9IFsxLCAyXSArIFszLCA0XTsKCWFzc2VydCBsIDo9IFsxLCAyLCAzLCA0XTsKCQoqIHRlc3QgdXNlIG9mIG92ZXJsb2FkZWQgc2V0dGVyIG1ldGhvZHMgJiB1c2Ugb2YgcHJvcGVydHkgbm90YXRpb24KICBzbyB0aGF0IHRoZSB1c2Ugb2YgcHJvcGVydGllcyB3aXRoaW4gYSBjbGFzcyBzaG91bGQgdXNlIHNldHRlcmVzIC8gZ2V0dGVycy4KCiogdGVzdCB0aGUgdXNlIG9mIFByb3BlcnR5RXhwcmVzc2lvbgoJYS5iID0gYy5kCgkKKiBzdXBwb3J0IHN0YXRpYyBuZXdJbnN0YW5jZSgpIG1ldGhvZCBmb3IgY29uc3RydWN0b3JzCgoqIG1heWJlIHNwbGl0IHVwIENsYXNzR2VuZXJhdG9yIC0gZG8gY29kZSBnZW4gJiBjbGFzcyBnZW4gc2VwYXJhdGVseQoKKiBtaXhpbiBzdXBwb3J0Li4uCgoJU29tZUNsYXNzLmFkZE1peGluKEZvbyk7CgkKCU1ldGFDbGFzcy5hZGRJbnRlcmNlcHRvciggbmV3IEludGVyY2VwdG9yKCkgewoJCWZpbHRlcihtZXRob2QpIHsKCQkJcmV0dXJuIG1ldGhvZC5pc1B1YmxpYygpOwoJCX0KCQlpbnZva2UobWV0aG9kLCBhcmdzKSB7CgkJCS8vIGRvIHNvbWV0aGluZwoJCQltZXRob2QuaW52b2tlKGFyZ3MpOwoJCX0KCX0pOwoKCSogYWxsb3cgbWV0YSBjbGFzc2VzIHRvIGJlIGFkZGVkIGR5bmFtaWNhbGx5IHVzaW5nIGNsb3N1cmUgc3ludGF4PwoJZS5nLiBNYXA/CgkKClNUVUZGIFRPIFBPTkRFUgo9PT09PT09PT09PT09PT0KCiogaWYgd2UgYWxsb3cgc3RhdGVtZW50cyBpbiBjbGFzcyBkZWNsYXJhdGlvbnMsIHRoZW4gd2UgY291bGQgZGlzYWxsb3cgdGhlIHN5bnRheCBzdWdhcgoJZm9yIG1ldGhvZCBpbnZvY2F0aW9uIHdpdGggY2xvc3VyZXMuIGkuZS4gZm9vIHsgY29kZSB9IHdvdWxkIGhhdmUgdG8gYmUgZm9vICh7Y29kZX0pCglvdGhlcndpc2UgaXQnZCBiZSBpbnRlcnBldGVkIGFzIGEgbWV0aG9kIGRlY2xhcmF0aW9uLgoJCgllLmcuCgkKCW1vZHVsZSBNeVZhbGlkYXRpbmdNb2R1bGUKCQoJY2xhc3MgQ2hlZXNlIHsKCQlyZWFkT25seVByb3BlcnR5KCdoZWxsbycpCgkJdmFsaWRhdGluZ1Byb3BlcnR5KCduYW1lJywgeyBpdC5sZW5ndGggPiAwIH0gKQoJCQoJCWxhemlseUNyZWF0ZWRQcm9wZXJ0eSg6Y2hlZXNlLCB7IG5ldyBNeVNwZWNpYWxDaGVlc2UoKSB9KQoJCQoJCXB1YmxpYyg6bWV0aG9kQSwgOm1ldGhvZEIsIDptZXRob2RDKQoJfQoJIAoJZm9yIG5vdyB3ZSBjb3VsZCBhcmd1ZSB0aGF0IG9ubHkgbWV0aG9kcyBhcmUgYWxsb3dlZCB0byBiZSBpbnZva2VkIGluc2lkZSB0aGUgY2xhc3MgZGVjbGFyYXRpb24uCglXZSBjb3VsZCBzdGlsbCBkbyBtYXJrdXAgYnV0IGp1c3Qgbm90IGFzIG5pY2UKCQoJY2xhc3MgV2hhdG5vdCB7CgkJdGFibGUoIHsKCQkJZm9vIHsKCQkJfQoJCQl3aGF0bm90IHsKCQkJfQoJCX0pCgkJCgkJYmxhaCA9IHsgCgkJCWEoeDoxMjM0LCBiOjk0MikgewoJCQkJZCgpCgkJCX0KCQl9CgkJCgkKKiBTdXBwb3J0IG11bHRpcGxlIHJldHVybiB2YWx1ZXMuLi4KCglTdHJpbmcsIE51bWJlciBjaGVlc2UoKSB7CgkJImhlbGxvIiwgNwoJfQoJCglhLCBiID0gY2hlZXNlKCkKCQoJYWxzbyBpZiB3ZSBkbyB0aGlzIHdlIHNob3VsZCBkbyBhc3NpZ25tZW50IC8gc3dhcHBpbmcKCQoJCWEsIGIgPSAxLCAyCgkJYSwgYiA9IGIsIGEKCiogbWF5YmUgdXNlIHN5bnRheCAjWzEsIDJdIHRvIGNyZWF0ZSBhcnJheXMgd2hpY2ggYmVoYXZlIGp1c3QgbGlrZSBpbW11dGFibGUgbGlzdHM/CgkJCiogbWF5YmUgdXNlICogdG8gcmVwcmVzZW50IGZpZWxkcyBpZiB3ZSBuZWVkIHRvIGRpZmZlcmVudGlhdGUgcHJvcGVydGllcyAmIGZpZWxkcz8JCgoqIHVzaW5nIG1hY3JvcyB0byBhdm9pZCBkZXBlbmRlbmNpZXMgb24gbG9nZ2luZyBzdHVmZiAoc2F5KQoKCWNsYXNzIEdyb292eUxvZyB7CgkJc3dpdGNoIChTeXN0ZW0uZ2V0UHJvcGVydHkoJ2dyb292eS5sb2cuaW1wbCcsICd1c2VDb21tb25zTG9nZ2luZycpKSB7CgkJCWNhc2UgJ3VzZUNvbW1vbnNMb2dnaW5nJzogewoJCQkJLy8gbGV0cyBkZWZpbmUgdGhlIG5ldyBpbnN0YW5jZSBtZXRob2QKCQkJCW5ld0luc3RhbmNlKCkgewoJCQkJCXJldHVybiBuZXcgQ29tbW9uc0xvZ2dpbmdUaGluZ3koKQoJCQkJfQoJCQl9CgkJCWRlZmF1bHQgewoJCQkJbmV3SW5zdGFuY2UoKSB7CgkJCQkJcmV0dXJuIG5ldyBTaW1wbGVHcm9vdnlMb2coKQoJCQkJfQoJCQl9CgkJfQoJfQoJCglkb2luZyB0aGluZ3MgbGlrZSB0aGlzIGF0IGNvbXBpbGUgdGltZSBtZWFucyBubyBydW50aW1lIGRlcGVuZGVuY2llcy4gRGl0dG8gdG8gZG8gSkRLIGJhc2VkIGNvbXBpbGVzCgkKCQoJClVJIFdPUksKPT09PT09PQoKKiB0cmVlIGRlbW8uLi4KCiogd2hlbiBuYW1lZCBtZXRob2QgY2FsbHMgYXJlIHN1cHBvcnRlZCB3aXRoIGRlZmF1bHQgdmFsdWVzLCByZWZhY3RvciBTd2luZ0J1aWxkZXIKCXNvIHRoYXQgYWxsIHRoZSBjcmVhdGlvbnMgb2Ygd2lkZ2V0cyBvY2N1ciB3aXRoIFN3aW5nRmFjdG9yeSB3aGljaCB3b3VsZCBiZSAKCXVzZWZ1bCBpbiBhbmQgb2YgaXRzZWxmCgktIHBsdXMgd2Ugc2hvdWxkIGJlIHVzaW5nIG5vcm1hbCBtZXRob2QgY2FsbCBtZWNoYW5pc20gJiBmb3IgZ3Jvb3Z5IHRvIGRvIHRoZSByZXN0IHRvIGF2b2lkCgl0aGUgbG9uZyBsYWJvcmlvdXMgTWFwIGNvZGluZwoJCiogYWRkIHRhYmxlIGxheW91dCBjZWxsIHNwYWNpbmcgdGhpbmd5CgoqIEZvcm1Nb2RlbC5hZGRQcm9wZXJ0eU1vZGVsKHByb3BlcnR5KQoJRm9ybU1vZGVsLmFkZENsb3N1cmVNb2RlbChyZWFkQ2xvc3VyZSwgd3JpdGVDbG9zdXJlKQoKKiBMaXN0TW9kZWwgaXMtYSBMaXN0IGJ1dCBkZWxlZ2F0ZXMgdG8gYW4gdW5kZXJseWluZyBsaXN0IGFuZCBoYXMgZXZlbnRzCgoqIHJlbmFtZSB0YWJsZUxheW91dCAtPiB0YWJsZSBhbmQgdGFibGUgLT4gZ3JpZAoKKiBhZGQgc29ydGFibGVHcmlkCgoqIGNyZWF0ZSBhIEdyb292eVVJCgktPiBpbnRlcmFjdGl2ZSBzY3JpcHQgKyBhbGxvd3Mgc2NyaXB0cyB0byBiZSBydW4gJiBvYmplY3RzIGV4cGxvcmVkCgoKCgpFQ0xJUFNFIFdPUksKPT09PT09PT09PT09CgoqIFJ1biBhcyBKVW5pdCBzdXBwb3J0IGZvciBHcm9vdnkhIAoKKiBSZWZhY3RvcmluZyBzdXBwb3J0IGZvciBHcm9vdnkgYW5kIHRpZSBpdCBpbnRvIHRoZSBKYXZhIHJlZmFjdG9yaW5nCgoKSlVOSVQgV09SSwo9PT09PT09PT09CgoqIHBhdGNoIEdyb292eVRlc3RDYXNlIHNvIHRoYXQgbWV0aG9kcyB3aGljaCByZXR1cm4gT2JqZWN0IGFyZSBpbmNsdWRlZCBpbiB0aGUgdGVzdC4gVGhpcyBhdm9pZHMgdXMgaGF2aW5nIHRvCnNwZWNpZnkgdm9pZCBmb3IgbWV0aG9kIHJldHVybiB0eXBlcy5UaGlzIHJlcXVpcmVzIGEgY2xldmVyIHN0YXRpYyBtZXRob2Qgd2hlbiB3ZSBnZW5lcmF0ZSB0aGUKCWJ5dGVjb2RlIHdoaWNoIGNhbiBpbnN0YW50aWF0ZSBhIHNwZWNpYWwga2luZCBvZiBUZXN0U3VpdGUKCXVubGVzcyB0aGVyZSdzIGFub3RoZXIgd2F5PwoKCk9QVElNSVNBVElPTlMKPT09PT09PT09PT09PQoqIG1ldGhvZCBpbnZvY2F0aW9ucyAtIGlmIGZvbyBpbnN0YW5jZW9mIEdyb292eU9iamVjdAp0aGVuIGdlbmVyYXRlIGJ5dGVjb2RlCgpmb28uaW52b2tlTWV0aG9kKG1ldGhvZCwgYXJncyk7CgoqIGNvdWxkIGNvZGUgZ2VuZXJhdGUgdGhlIE1ldGFDbGFzcyB3aXRoIHZlcnkgZWZmaWNpZW50IGR5bmFtaWMgZGlzcGF0Y2gKCWUuZy4gY291bGQgc3dpdGNoKCkgb24gdGhlIG1ldGhvZCBuYW1lICYgdGhlbiB1c2UgcmVhbCBtZXRob2QgaW52b2NhdGlvbgoJb24gdGhlIG1ldGhvZCBpbnN0YW5jZQoKCg==