LyoNClRoZSBNSVQgTGljZW5zZQ0KDQpDb3B5cmlnaHQgKGMpIDIwMTAtMjAxNSBHb29nbGUsIEluYy4gaHR0cDovL2FuZ3VsYXJqcy5vcmcNCg0KUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weQ0Kb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksIHRvIGRlYWwNCmluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMNCnRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwNCmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcw0KZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoNCg0KVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4NCmFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLg0KDQpUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUg0KSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksDQpGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUNCkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVINCkxJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sDQpPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElODQpUSEUgU09GVFdBUkUuDQoqLw0KLyoqDQogKiBAbGljZW5zZSBBbmd1bGFySlMgdjEuMy44DQogKiAoYykgMjAxMC0yMDE0IEdvb2dsZSwgSW5jLiBodHRwOi8vYW5ndWxhcmpzLm9yZw0KICogTGljZW5zZTogTUlUDQogKi8NCihmdW5jdGlvbih3aW5kb3csIGRvY3VtZW50LCB1bmRlZmluZWQpIHsndXNlIHN0cmljdCc7DQoNCi8qKg0KICogQGRlc2NyaXB0aW9uDQogKg0KICogVGhpcyBvYmplY3QgcHJvdmlkZXMgYSB1dGlsaXR5IGZvciBwcm9kdWNpbmcgcmljaCBFcnJvciBtZXNzYWdlcyB3aXRoaW4NCiAqIEFuZ3VsYXIuIEl0IGNhbiBiZSBjYWxsZWQgYXMgZm9sbG93czoNCiAqDQogKiB2YXIgZXhhbXBsZU1pbkVyciA9IG1pbkVycignZXhhbXBsZScpOw0KICogdGhyb3cgZXhhbXBsZU1pbkVycignb25lJywgJ1RoaXMgezB9IGlzIHsxfScsIGZvbywgYmFyKTsNCiAqDQogKiBUaGUgYWJvdmUgY3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBtaW5FcnIgaW4gdGhlIGV4YW1wbGUgbmFtZXNwYWNlLiBUaGUNCiAqIHJlc3VsdGluZyBlcnJvciB3aWxsIGhhdmUgYSBuYW1lc3BhY2VkIGVycm9yIGNvZGUgb2YgZXhhbXBsZS5vbmUuICBUaGUNCiAqIHJlc3VsdGluZyBlcnJvciB3aWxsIHJlcGxhY2UgezB9IHdpdGggdGhlIHZhbHVlIG9mIGZvbywgYW5kIHsxfSB3aXRoIHRoZQ0KICogdmFsdWUgb2YgYmFyLiBUaGUgb2JqZWN0IGlzIG5vdCByZXN0cmljdGVkIGluIHRoZSBudW1iZXIgb2YgYXJndW1lbnRzIGl0IGNhbg0KICogdGFrZS4NCiAqDQogKiBJZiBmZXdlciBhcmd1bWVudHMgYXJlIHNwZWNpZmllZCB0aGFuIG5lY2Vzc2FyeSBmb3IgaW50ZXJwb2xhdGlvbiwgdGhlIGV4dHJhDQogKiBpbnRlcnBvbGF0aW9uIG1hcmtlcnMgd2lsbCBiZSBwcmVzZXJ2ZWQgaW4gdGhlIGZpbmFsIHN0cmluZy4NCiAqDQogKiBTaW5jZSBkYXRhIHdpbGwgYmUgcGFyc2VkIHN0YXRpY2FsbHkgZHVyaW5nIGEgYnVpbGQgc3RlcCwgc29tZSByZXN0cmljdGlvbnMNCiAqIGFyZSBhcHBsaWVkIHdpdGggcmVzcGVjdCB0byBob3cgbWluRXJyIGluc3RhbmNlcyBhcmUgY3JlYXRlZCBhbmQgY2FsbGVkLg0KICogSW5zdGFuY2VzIHNob3VsZCBoYXZlIG5hbWVzIG9mIHRoZSBmb3JtIG5hbWVzcGFjZU1pbkVyciBmb3IgYSBtaW5FcnIgY3JlYXRlZA0KICogdXNpbmcgbWluRXJyKCduYW1lc3BhY2UnKSAuIEVycm9yIGNvZGVzLCBuYW1lc3BhY2VzIGFuZCB0ZW1wbGF0ZSBzdHJpbmdzDQogKiBzaG91bGQgYWxsIGJlIHN0YXRpYyBzdHJpbmdzLCBub3QgdmFyaWFibGVzIG9yIGdlbmVyYWwgZXhwcmVzc2lvbnMuDQogKg0KICogQHBhcmFtIHtzdHJpbmd9IG1vZHVsZSBUaGUgbmFtZXNwYWNlIHRvIHVzZSBmb3IgdGhlIG5ldyBtaW5FcnIgaW5zdGFuY2UuDQogKiBAcGFyYW0ge2Z1bmN0aW9ufSBFcnJvckNvbnN0cnVjdG9yIEN1c3RvbSBlcnJvciBjb25zdHJ1Y3RvciB0byBiZSBpbnN0YW50aWF0ZWQgd2hlbiByZXR1cm5pbmcNCiAqICAgZXJyb3IgZnJvbSByZXR1cm5lZCBmdW5jdGlvbiwgZm9yIGNhc2VzIHdoZW4gYSBwYXJ0aWN1bGFyIHR5cGUgb2YgZXJyb3IgaXMgdXNlZnVsLg0KICogQHJldHVybnMge2Z1bmN0aW9uKGNvZGU6c3RyaW5nLCB0ZW1wbGF0ZTpzdHJpbmcsIC4uLnRlbXBsYXRlQXJncyk6IEVycm9yfSBtaW5FcnIgaW5zdGFuY2UNCiAqLw0KDQpmdW5jdGlvbiBtaW5FcnIobW9kdWxlLCBFcnJvckNvbnN0cnVjdG9yKSB7DQogIEVycm9yQ29uc3RydWN0b3IgPSBFcnJvckNvbnN0cnVjdG9yIHx8IEVycm9yOw0KICByZXR1cm4gZnVuY3Rpb24oKSB7DQogICAgdmFyIGNvZGUgPSBhcmd1bWVudHNbMF0sDQogICAgICBwcmVmaXggPSAnWycgKyAobW9kdWxlID8gbW9kdWxlICsgJzonIDogJycpICsgY29kZSArICddICcsDQogICAgICB0ZW1wbGF0ZSA9IGFyZ3VtZW50c1sxXSwNCiAgICAgIHRlbXBsYXRlQXJncyA9IGFyZ3VtZW50cywNCg0KICAgICAgbWVzc2FnZSwgaTsNCg0KICAgIG1lc3NhZ2UgPSBwcmVmaXggKyB0ZW1wbGF0ZS5yZXBsYWNlKC9ce1xkK1x9L2csIGZ1bmN0aW9uKG1hdGNoKSB7DQogICAgICB2YXIgaW5kZXggPSArbWF0Y2guc2xpY2UoMSwgLTEpLCBhcmc7DQoNCiAgICAgIGlmIChpbmRleCArIDIgPCB0ZW1wbGF0ZUFyZ3MubGVuZ3RoKSB7DQogICAgICAgIHJldHVybiB0b0RlYnVnU3RyaW5nKHRlbXBsYXRlQXJnc1tpbmRleCArIDJdKTsNCiAgICAgIH0NCiAgICAgIHJldHVybiBtYXRjaDsNCiAgICB9KTsNCg0KICAgIG1lc3NhZ2UgPSBtZXNzYWdlICsgJ1xuaHR0cDovL2Vycm9ycy5hbmd1bGFyanMub3JnLzEuMy44LycgKw0KICAgICAgKG1vZHVsZSA/IG1vZHVsZSArICcvJyA6ICcnKSArIGNvZGU7DQogICAgZm9yIChpID0gMjsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgew0KICAgICAgbWVzc2FnZSA9IG1lc3NhZ2UgKyAoaSA9PSAyID8gJz8nIDogJyYnKSArICdwJyArIChpIC0gMikgKyAnPScgKw0KICAgICAgICBlbmNvZGVVUklDb21wb25lbnQodG9EZWJ1Z1N0cmluZyhhcmd1bWVudHNbaV0pKTsNCiAgICB9DQogICAgcmV0dXJuIG5ldyBFcnJvckNvbnN0cnVjdG9yKG1lc3NhZ2UpOw0KICB9Ow0KfQ0KDQovKiBXZSBuZWVkIHRvIHRlbGwganNoaW50IHdoYXQgdmFyaWFibGVzIGFyZSBiZWluZyBleHBvcnRlZCAqLw0KLyogZ2xvYmFsIGFuZ3VsYXI6IHRydWUsDQogIG1zaWU6IHRydWUsDQogIGpxTGl0ZTogdHJ1ZSwNCiAgalF1ZXJ5OiB0cnVlLA0KICBzbGljZTogdHJ1ZSwNCiAgc3BsaWNlOiB0cnVlLA0KICBwdXNoOiB0cnVlLA0KICB0b1N0cmluZzogdHJ1ZSwNCiAgbmdNaW5FcnI6IHRydWUsDQogIGFuZ3VsYXJNb2R1bGU6IHRydWUsDQogIHVpZDogdHJ1ZSwNCiAgUkVHRVhfU1RSSU5HX1JFR0VYUDogdHJ1ZSwNCiAgVkFMSURJVFlfU1RBVEVfUFJPUEVSVFk6IHRydWUsDQoNCiAgbG93ZXJjYXNlOiB0cnVlLA0KICB1cHBlcmNhc2U6IHRydWUsDQogIG1hbnVhbExvd2VyY2FzZTogdHJ1ZSwNCiAgbWFudWFsVXBwZXJjYXNlOiB0cnVlLA0KICBub2RlTmFtZV86IHRydWUsDQogIGlzQXJyYXlMaWtlOiB0cnVlLA0KICBmb3JFYWNoOiB0cnVlLA0KICBzb3J0ZWRLZXlzOiB0cnVlLA0KICBmb3JFYWNoU29ydGVkOiB0cnVlLA0KICByZXZlcnNlUGFyYW1zOiB0cnVlLA0KICBuZXh0VWlkOiB0cnVlLA0KICBzZXRIYXNoS2V5OiB0cnVlLA0KICBleHRlbmQ6IHRydWUsDQogIGludDogdHJ1ZSwNCiAgaW5oZXJpdDogdHJ1ZSwNCiAgbm9vcDogdHJ1ZSwNCiAgaWRlbnRpdHk6IHRydWUsDQogIHZhbHVlRm46IHRydWUsDQogIGlzVW5kZWZpbmVkOiB0cnVlLA0KICBpc0RlZmluZWQ6IHRydWUsDQogIGlzT2JqZWN0OiB0cnVlLA0KICBpc1N0cmluZzogdHJ1ZSwNCiAgaXNOdW1iZXI6IHRydWUsDQogIGlzRGF0ZTogdHJ1ZSwNCiAgaXNBcnJheTogdHJ1ZSwNCiAgaXNGdW5jdGlvbjogdHJ1ZSwNCiAgaXNSZWdFeHA6IHRydWUsDQogIGlzV2luZG93OiB0cnVlLA0KICBpc1Njb3BlOiB0cnVlLA0KICBpc0ZpbGU6IHRydWUsDQogIGlzRm9ybURhdGE6IHRydWUsDQogIGlzQmxvYjogdHJ1ZSwNCiAgaXNCb29sZWFuOiB0cnVlLA0KICBpc1Byb21pc2VMaWtlOiB0cnVlLA0KICB0cmltOiB0cnVlLA0KICBlc2NhcGVGb3JSZWdleHA6IHRydWUsDQogIGlzRWxlbWVudDogdHJ1ZSwNCiAgbWFrZU1hcDogdHJ1ZSwNCiAgaW5jbHVkZXM6IHRydWUsDQogIGFycmF5UmVtb3ZlOiB0cnVlLA0KICBjb3B5OiB0cnVlLA0KICBzaGFsbG93Q29weTogdHJ1ZSwNCiAgZXF1YWxzOiB0cnVlLA0KICBjc3A6IHRydWUsDQogIGNvbmNhdDogdHJ1ZSwNCiAgc2xpY2VBcmdzOiB0cnVlLA0KICBiaW5kOiB0cnVlLA0KICB0b0pzb25SZXBsYWNlcjogdHJ1ZSwNCiAgdG9Kc29uOiB0cnVlLA0KICBmcm9tSnNvbjogdHJ1ZSwNCiAgc3RhcnRpbmdUYWc6IHRydWUsDQogIHRyeURlY29kZVVSSUNvbXBvbmVudDogdHJ1ZSwNCiAgcGFyc2VLZXlWYWx1ZTogdHJ1ZSwNCiAgdG9LZXlWYWx1ZTogdHJ1ZSwNCiAgZW5jb2RlVXJpU2VnbWVudDogdHJ1ZSwNCiAgZW5jb2RlVXJpUXVlcnk6IHRydWUsDQogIGFuZ3VsYXJJbml0OiB0cnVlLA0KICBib290c3RyYXA6IHRydWUsDQogIGdldFRlc3RhYmlsaXR5OiB0cnVlLA0KICBzbmFrZV9jYXNlOiB0cnVlLA0KICBiaW5kSlF1ZXJ5OiB0cnVlLA0KICBhc3NlcnRBcmc6IHRydWUsDQogIGFzc2VydEFyZ0ZuOiB0cnVlLA0KICBhc3NlcnROb3RIYXNPd25Qcm9wZXJ0eTogdHJ1ZSwNCiAgZ2V0dGVyOiB0cnVlLA0KICBnZXRCbG9ja05vZGVzOiB0cnVlLA0KICBoYXNPd25Qcm9wZXJ0eTogdHJ1ZSwNCiAgY3JlYXRlTWFwOiB0cnVlLA0KDQogIE5PREVfVFlQRV9FTEVNRU5UOiB0cnVlLA0KICBOT0RFX1RZUEVfVEVYVDogdHJ1ZSwNCiAgTk9ERV9UWVBFX0NPTU1FTlQ6IHRydWUsDQogIE5PREVfVFlQRV9ET0NVTUVOVDogdHJ1ZSwNCiAgTk9ERV9UWVBFX0RPQ1VNRU5UX0ZSQUdNRU5UOiB0cnVlLA0KKi8NCg0KLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vDQoNCi8qKg0KICogQG5nZG9jIG1vZHVsZQ0KICogQG5hbWUgbmcNCiAqIEBtb2R1bGUgbmcNCiAqIEBkZXNjcmlwdGlvbg0KICoNCiAqICMgbmcgKGNvcmUgbW9kdWxlKQ0KICogVGhlIG5nIG1vZHVsZSBpcyBsb2FkZWQgYnkgZGVmYXVsdCB3aGVuIGFuIEFuZ3VsYXJKUyBhcHBsaWNhdGlvbiBpcyBzdGFydGVkLiBUaGUgbW9kdWxlIGl0c2VsZg0KICogY29udGFpbnMgdGhlIGVzc2VudGlhbCBjb21wb25lbnRzIGZvciBhbiBBbmd1bGFySlMgYXBwbGljYXRpb24gdG8gZnVuY3Rpb24uIFRoZSB0YWJsZSBiZWxvdw0KICogbGlzdHMgYSBoaWdoIGxldmVsIGJyZWFrZG93biBvZiBlYWNoIG9mIHRoZSBzZXJ2aWNlcy9mYWN0b3JpZXMsIGZpbHRlcnMsIGRpcmVjdGl2ZXMgYW5kIHRlc3RpbmcNCiAqIGNvbXBvbmVudHMgYXZhaWxhYmxlIHdpdGhpbiB0aGlzIGNvcmUgbW9kdWxlLg0KICoNCiAqIDxkaXYgZG9jLW1vZHVsZS1jb21wb25lbnRzPSJuZyI+PC9kaXY+DQogKi8NCg0KdmFyIFJFR0VYX1NUUklOR19SRUdFWFAgPSAvXlwvKC4rKVwvKFthLXpdKikkLzsNCg0KLy8gVGhlIG5hbWUgb2YgYSBmb3JtIGNvbnRyb2wncyBWYWxpZGl0eVN0YXRlIHByb3BlcnR5Lg0KLy8gVGhpcyBpcyB1c2VkIHNvIHRoYXQgaXQncyBwb3NzaWJsZSBmb3IgaW50ZXJuYWwgdGVzdHMgdG8gY3JlYXRlIG1vY2sgVmFsaWRpdHlTdGF0ZXMuDQp2YXIgVkFMSURJVFlfU1RBVEVfUFJPUEVSVFkgPSAndmFsaWRpdHknOw0KDQovKioNCiAqIEBuZ2RvYyBmdW5jdGlvbg0KICogQG5hbWUgYW5ndWxhci5sb3dlcmNhc2UNCiAqIEBtb2R1bGUgbmcNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uIENvbnZlcnRzIHRoZSBzcGVjaWZpZWQgc3RyaW5nIHRvIGxvd2VyY2FzZS4NCiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgU3RyaW5nIHRvIGJlIGNvbnZlcnRlZCB0byBsb3dlcmNhc2UuDQogKiBAcmV0dXJucyB7c3RyaW5nfSBMb3dlcmNhc2VkIHN0cmluZy4NCiAqLw0KdmFyIGxvd2VyY2FzZSA9IGZ1bmN0aW9uKHN0cmluZykge3JldHVybiBpc1N0cmluZyhzdHJpbmcpID8gc3RyaW5nLnRvTG93ZXJDYXNlKCkgOiBzdHJpbmc7fTsNCnZhciBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7DQoNCi8qKg0KICogQG5nZG9jIGZ1bmN0aW9uDQogKiBAbmFtZSBhbmd1bGFyLnVwcGVyY2FzZQ0KICogQG1vZHVsZSBuZw0KICogQGtpbmQgZnVuY3Rpb24NCiAqDQogKiBAZGVzY3JpcHRpb24gQ29udmVydHMgdGhlIHNwZWNpZmllZCBzdHJpbmcgdG8gdXBwZXJjYXNlLg0KICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBTdHJpbmcgdG8gYmUgY29udmVydGVkIHRvIHVwcGVyY2FzZS4NCiAqIEByZXR1cm5zIHtzdHJpbmd9IFVwcGVyY2FzZWQgc3RyaW5nLg0KICovDQp2YXIgdXBwZXJjYXNlID0gZnVuY3Rpb24oc3RyaW5nKSB7cmV0dXJuIGlzU3RyaW5nKHN0cmluZykgPyBzdHJpbmcudG9VcHBlckNhc2UoKSA6IHN0cmluZzt9Ow0KDQoNCnZhciBtYW51YWxMb3dlcmNhc2UgPSBmdW5jdGlvbihzKSB7DQogIC8qIGpzaGludCBiaXR3aXNlOiBmYWxzZSAqLw0KICByZXR1cm4gaXNTdHJpbmcocykNCiAgICAgID8gcy5yZXBsYWNlKC9bQS1aXS9nLCBmdW5jdGlvbihjaCkge3JldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoLmNoYXJDb2RlQXQoMCkgfCAzMik7fSkNCiAgICAgIDogczsNCn07DQp2YXIgbWFudWFsVXBwZXJjYXNlID0gZnVuY3Rpb24ocykgew0KICAvKiBqc2hpbnQgYml0d2lzZTogZmFsc2UgKi8NCiAgcmV0dXJuIGlzU3RyaW5nKHMpDQogICAgICA/IHMucmVwbGFjZSgvW2Etel0vZywgZnVuY3Rpb24oY2gpIHtyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShjaC5jaGFyQ29kZUF0KDApICYgfjMyKTt9KQ0KICAgICAgOiBzOw0KfTsNCg0KDQovLyBTdHJpbmcjdG9Mb3dlckNhc2UgYW5kIFN0cmluZyN0b1VwcGVyQ2FzZSBkb24ndCBwcm9kdWNlIGNvcnJlY3QgcmVzdWx0cyBpbiBicm93c2VycyB3aXRoIFR1cmtpc2gNCi8vIGxvY2FsZSwgZm9yIHRoaXMgcmVhc29uIHdlIG5lZWQgdG8gZGV0ZWN0IHRoaXMgY2FzZSBhbmQgcmVkZWZpbmUgbG93ZXJjYXNlL3VwcGVyY2FzZSBtZXRob2RzDQovLyB3aXRoIGNvcnJlY3QgYnV0IHNsb3dlciBhbHRlcm5hdGl2ZXMuDQppZiAoJ2knICE9PSAnSScudG9Mb3dlckNhc2UoKSkgew0KICBsb3dlcmNhc2UgPSBtYW51YWxMb3dlcmNhc2U7DQogIHVwcGVyY2FzZSA9IG1hbnVhbFVwcGVyY2FzZTsNCn0NCg0KDQp2YXINCiAgICBtc2llLCAgICAgICAgICAgICAvLyBob2xkcyBtYWpvciB2ZXJzaW9uIG51bWJlciBmb3IgSUUsIG9yIE5hTiBpZiBVQSBpcyBub3QgSUUuDQogICAganFMaXRlLCAgICAgICAgICAgLy8gZGVsYXkgYmluZGluZyBzaW5jZSBqUXVlcnkgY291bGQgYmUgbG9hZGVkIGFmdGVyIHVzLg0KICAgIGpRdWVyeSwgICAgICAgICAgIC8vIGRlbGF5IGJpbmRpbmcNCiAgICBzbGljZSAgICAgICAgICAgICA9IFtdLnNsaWNlLA0KICAgIHNwbGljZSAgICAgICAgICAgID0gW10uc3BsaWNlLA0KICAgIHB1c2ggICAgICAgICAgICAgID0gW10ucHVzaCwNCiAgICB0b1N0cmluZyAgICAgICAgICA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcsDQogICAgbmdNaW5FcnIgICAgICAgICAgPSBtaW5FcnIoJ25nJyksDQoNCiAgICAvKiogQG5hbWUgYW5ndWxhciAqLw0KICAgIGFuZ3VsYXIgICAgICAgICAgID0gd2luZG93LmFuZ3VsYXIgfHwgKHdpbmRvdy5hbmd1bGFyID0ge30pLA0KICAgIGFuZ3VsYXJNb2R1bGUsDQogICAgdWlkICAgICAgICAgICAgICAgPSAwOw0KDQovKioNCiAqIGRvY3VtZW50TW9kZSBpcyBhbiBJRS1vbmx5IHByb3BlcnR5DQogKiBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvaWUvY2MxOTY5ODgodj12cy44NSkuYXNweA0KICovDQptc2llID0gZG9jdW1lbnQuZG9jdW1lbnRNb2RlOw0KDQoNCi8qKg0KICogQHByaXZhdGUNCiAqIEBwYXJhbSB7Kn0gb2JqDQogKiBAcmV0dXJuIHtib29sZWFufSBSZXR1cm5zIHRydWUgaWYgYG9iamAgaXMgYW4gYXJyYXkgb3IgYXJyYXktbGlrZSBvYmplY3QgKE5vZGVMaXN0LCBBcmd1bWVudHMsDQogKiAgICAgICAgICAgICAgICAgICBTdHJpbmcgLi4uKQ0KICovDQpmdW5jdGlvbiBpc0FycmF5TGlrZShvYmopIHsNCiAgaWYgKG9iaiA9PSBudWxsIHx8IGlzV2luZG93KG9iaikpIHsNCiAgICByZXR1cm4gZmFsc2U7DQogIH0NCg0KICB2YXIgbGVuZ3RoID0gb2JqLmxlbmd0aDsNCg0KICBpZiAob2JqLm5vZGVUeXBlID09PSBOT0RFX1RZUEVfRUxFTUVOVCAmJiBsZW5ndGgpIHsNCiAgICByZXR1cm4gdHJ1ZTsNCiAgfQ0KDQogIHJldHVybiBpc1N0cmluZyhvYmopIHx8IGlzQXJyYXkob2JqKSB8fCBsZW5ndGggPT09IDAgfHwNCiAgICAgICAgIHR5cGVvZiBsZW5ndGggPT09ICdudW1iZXInICYmIGxlbmd0aCA+IDAgJiYgKGxlbmd0aCAtIDEpIGluIG9iajsNCn0NCg0KLyoqDQogKiBAbmdkb2MgZnVuY3Rpb24NCiAqIEBuYW1lIGFuZ3VsYXIuZm9yRWFjaA0KICogQG1vZHVsZSBuZw0KICogQGtpbmQgZnVuY3Rpb24NCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIEludm9rZXMgdGhlIGBpdGVyYXRvcmAgZnVuY3Rpb24gb25jZSBmb3IgZWFjaCBpdGVtIGluIGBvYmpgIGNvbGxlY3Rpb24sIHdoaWNoIGNhbiBiZSBlaXRoZXIgYW4NCiAqIG9iamVjdCBvciBhbiBhcnJheS4gVGhlIGBpdGVyYXRvcmAgZnVuY3Rpb24gaXMgaW52b2tlZCB3aXRoIGBpdGVyYXRvcih2YWx1ZSwga2V5LCBvYmopYCwgd2hlcmUgYHZhbHVlYA0KICogaXMgdGhlIHZhbHVlIG9mIGFuIG9iamVjdCBwcm9wZXJ0eSBvciBhbiBhcnJheSBlbGVtZW50LCBga2V5YCBpcyB0aGUgb2JqZWN0IHByb3BlcnR5IGtleSBvcg0KICogYXJyYXkgZWxlbWVudCBpbmRleCBhbmQgb2JqIGlzIHRoZSBgb2JqYCBpdHNlbGYuIFNwZWNpZnlpbmcgYSBgY29udGV4dGAgZm9yIHRoZSBmdW5jdGlvbiBpcyBvcHRpb25hbC4NCiAqDQogKiBJdCBpcyB3b3J0aCBub3RpbmcgdGhhdCBgLmZvckVhY2hgIGRvZXMgbm90IGl0ZXJhdGUgb3ZlciBpbmhlcml0ZWQgcHJvcGVydGllcyBiZWNhdXNlIGl0IGZpbHRlcnMNCiAqIHVzaW5nIHRoZSBgaGFzT3duUHJvcGVydHlgIG1ldGhvZC4NCiAqDQogKiBVbmxpa2UgRVMyNjIncw0KICogW0FycmF5LnByb3RvdHlwZS5mb3JFYWNoXShodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNS4xLyNzZWMtMTUuNC40LjE4KSwNCiAqIFByb3ZpZGluZyAndW5kZWZpbmVkJyBvciAnbnVsbCcgdmFsdWVzIGZvciBgb2JqYCB3aWxsIG5vdCB0aHJvdyBhIFR5cGVFcnJvciwgYnV0IHJhdGhlciBqdXN0DQogKiByZXR1cm4gdGhlIHZhbHVlIHByb3ZpZGVkLg0KICoNCiAgIGBgYGpzDQogICAgIHZhciB2YWx1ZXMgPSB7bmFtZTogJ21pc2tvJywgZ2VuZGVyOiAnbWFsZSd9Ow0KICAgICB2YXIgbG9nID0gW107DQogICAgIGFuZ3VsYXIuZm9yRWFjaCh2YWx1ZXMsIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHsNCiAgICAgICB0aGlzLnB1c2goa2V5ICsgJzogJyArIHZhbHVlKTsNCiAgICAgfSwgbG9nKTsNCiAgICAgZXhwZWN0KGxvZykudG9FcXVhbChbJ25hbWU6IG1pc2tvJywgJ2dlbmRlcjogbWFsZSddKTsNCiAgIGBgYA0KICoNCiAqIEBwYXJhbSB7T2JqZWN0fEFycmF5fSBvYmogT2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci4NCiAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdG9yIEl0ZXJhdG9yIGZ1bmN0aW9uLg0KICogQHBhcmFtIHtPYmplY3Q9fSBjb250ZXh0IE9iamVjdCB0byBiZWNvbWUgY29udGV4dCAoYHRoaXNgKSBmb3IgdGhlIGl0ZXJhdG9yIGZ1bmN0aW9uLg0KICogQHJldHVybnMge09iamVjdHxBcnJheX0gUmVmZXJlbmNlIHRvIGBvYmpgLg0KICovDQoNCmZ1bmN0aW9uIGZvckVhY2gob2JqLCBpdGVyYXRvciwgY29udGV4dCkgew0KICB2YXIga2V5LCBsZW5ndGg7DQogIGlmIChvYmopIHsNCiAgICBpZiAoaXNGdW5jdGlvbihvYmopKSB7DQogICAgICBmb3IgKGtleSBpbiBvYmopIHsNCiAgICAgICAgLy8gTmVlZCB0byBjaGVjayBpZiBoYXNPd25Qcm9wZXJ0eSBleGlzdHMsDQogICAgICAgIC8vIGFzIG9uIElFOCB0aGUgcmVzdWx0IG9mIHF1ZXJ5U2VsZWN0b3JBbGwgaXMgYW4gb2JqZWN0IHdpdGhvdXQgYSBoYXNPd25Qcm9wZXJ0eSBmdW5jdGlvbg0KICAgICAgICBpZiAoa2V5ICE9ICdwcm90b3R5cGUnICYmIGtleSAhPSAnbGVuZ3RoJyAmJiBrZXkgIT0gJ25hbWUnICYmICghb2JqLmhhc093blByb3BlcnR5IHx8IG9iai5oYXNPd25Qcm9wZXJ0eShrZXkpKSkgew0KICAgICAgICAgIGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqW2tleV0sIGtleSwgb2JqKTsNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgIH0gZWxzZSBpZiAoaXNBcnJheShvYmopIHx8IGlzQXJyYXlMaWtlKG9iaikpIHsNCiAgICAgIHZhciBpc1ByaW1pdGl2ZSA9IHR5cGVvZiBvYmogIT09ICdvYmplY3QnOw0KICAgICAgZm9yIChrZXkgPSAwLCBsZW5ndGggPSBvYmoubGVuZ3RoOyBrZXkgPCBsZW5ndGg7IGtleSsrKSB7DQogICAgICAgIGlmIChpc1ByaW1pdGl2ZSB8fCBrZXkgaW4gb2JqKSB7DQogICAgICAgICAgaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmpba2V5XSwga2V5LCBvYmopOw0KICAgICAgICB9DQogICAgICB9DQogICAgfSBlbHNlIGlmIChvYmouZm9yRWFjaCAmJiBvYmouZm9yRWFjaCAhPT0gZm9yRWFjaCkgew0KICAgICAgICBvYmouZm9yRWFjaChpdGVyYXRvciwgY29udGV4dCwgb2JqKTsNCiAgICB9IGVsc2Ugew0KICAgICAgZm9yIChrZXkgaW4gb2JqKSB7DQogICAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkoa2V5KSkgew0KICAgICAgICAgIGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqW2tleV0sIGtleSwgb2JqKTsNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgIH0NCiAgfQ0KICByZXR1cm4gb2JqOw0KfQ0KDQpmdW5jdGlvbiBzb3J0ZWRLZXlzKG9iaikgew0KICByZXR1cm4gT2JqZWN0LmtleXMob2JqKS5zb3J0KCk7DQp9DQoNCmZ1bmN0aW9uIGZvckVhY2hTb3J0ZWQob2JqLCBpdGVyYXRvciwgY29udGV4dCkgew0KICB2YXIga2V5cyA9IHNvcnRlZEtleXMob2JqKTsNCiAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7DQogICAgaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmpba2V5c1tpXV0sIGtleXNbaV0pOw0KICB9DQogIHJldHVybiBrZXlzOw0KfQ0KDQoNCi8qKg0KICogd2hlbiB1c2luZyBmb3JFYWNoIHRoZSBwYXJhbXMgYXJlIHZhbHVlLCBrZXksIGJ1dCBpdCBpcyBvZnRlbiB1c2VmdWwgdG8gaGF2ZSBrZXksIHZhbHVlLg0KICogQHBhcmFtIHtmdW5jdGlvbihzdHJpbmcsICopfSBpdGVyYXRvckZuDQogKiBAcmV0dXJucyB7ZnVuY3Rpb24oKiwgc3RyaW5nKX0NCiAqLw0KZnVuY3Rpb24gcmV2ZXJzZVBhcmFtcyhpdGVyYXRvckZuKSB7DQogIHJldHVybiBmdW5jdGlvbih2YWx1ZSwga2V5KSB7IGl0ZXJhdG9yRm4oa2V5LCB2YWx1ZSk7IH07DQp9DQoNCi8qKg0KICogQSBjb25zaXN0ZW50IHdheSBvZiBjcmVhdGluZyB1bmlxdWUgSURzIGluIGFuZ3VsYXIuDQogKg0KICogVXNpbmcgc2ltcGxlIG51bWJlcnMgYWxsb3dzIHVzIHRvIGdlbmVyYXRlIDI4LjYgbWlsbGlvbiB1bmlxdWUgaWRzIHBlciBzZWNvbmQgZm9yIDEwIHllYXJzIGJlZm9yZQ0KICogd2UgaGl0IG51bWJlciBwcmVjaXNpb24gaXNzdWVzIGluIEphdmFTY3JpcHQuDQogKg0KICogTWF0aC5wb3coMiw1MykgLyA2MCAvIDYwIC8gMjQgLyAzNjUgLyAxMCA9IDI4LjZNDQogKg0KICogQHJldHVybnMge251bWJlcn0gYW4gdW5pcXVlIGFscGhhLW51bWVyaWMgc3RyaW5nDQogKi8NCmZ1bmN0aW9uIG5leHRVaWQoKSB7DQogIHJldHVybiArK3VpZDsNCn0NCg0KDQovKioNCiAqIFNldCBvciBjbGVhciB0aGUgaGFzaGtleSBmb3IgYW4gb2JqZWN0Lg0KICogQHBhcmFtIG9iaiBvYmplY3QNCiAqIEBwYXJhbSBoIHRoZSBoYXNoa2V5ICghdHJ1dGh5IHRvIGRlbGV0ZSB0aGUgaGFzaGtleSkNCiAqLw0KZnVuY3Rpb24gc2V0SGFzaEtleShvYmosIGgpIHsNCiAgaWYgKGgpIHsNCiAgICBvYmouJCRoYXNoS2V5ID0gaDsNCiAgfQ0KICBlbHNlIHsNCiAgICBkZWxldGUgb2JqLiQkaGFzaEtleTsNCiAgfQ0KfQ0KDQovKioNCiAqIEBuZ2RvYyBmdW5jdGlvbg0KICogQG5hbWUgYW5ndWxhci5leHRlbmQNCiAqIEBtb2R1bGUgbmcNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBFeHRlbmRzIHRoZSBkZXN0aW5hdGlvbiBvYmplY3QgYGRzdGAgYnkgY29weWluZyBvd24gZW51bWVyYWJsZSBwcm9wZXJ0aWVzIGZyb20gdGhlIGBzcmNgIG9iamVjdChzKQ0KICogdG8gYGRzdGAuIFlvdSBjYW4gc3BlY2lmeSBtdWx0aXBsZSBgc3JjYCBvYmplY3RzLiBJZiB5b3Ugd2FudCB0byBwcmVzZXJ2ZSBvcmlnaW5hbCBvYmplY3RzLCB5b3UgY2FuIGRvIHNvDQogKiBieSBwYXNzaW5nIGFuIGVtcHR5IG9iamVjdCBhcyB0aGUgdGFyZ2V0OiBgdmFyIG9iamVjdCA9IGFuZ3VsYXIuZXh0ZW5kKHt9LCBvYmplY3QxLCBvYmplY3QyKWAuDQogKiBOb3RlOiBLZWVwIGluIG1pbmQgdGhhdCBgYW5ndWxhci5leHRlbmRgIGRvZXMgbm90IHN1cHBvcnQgcmVjdXJzaXZlIG1lcmdlIChkZWVwIGNvcHkpLg0KICoNCiAqIEBwYXJhbSB7T2JqZWN0fSBkc3QgRGVzdGluYXRpb24gb2JqZWN0Lg0KICogQHBhcmFtIHsuLi5PYmplY3R9IHNyYyBTb3VyY2Ugb2JqZWN0KHMpLg0KICogQHJldHVybnMge09iamVjdH0gUmVmZXJlbmNlIHRvIGBkc3RgLg0KICovDQpmdW5jdGlvbiBleHRlbmQoZHN0KSB7DQogIHZhciBoID0gZHN0LiQkaGFzaEtleTsNCg0KICBmb3IgKHZhciBpID0gMSwgaWkgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgew0KICAgIHZhciBvYmogPSBhcmd1bWVudHNbaV07DQogICAgaWYgKG9iaikgew0KICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvYmopOw0KICAgICAgZm9yICh2YXIgaiA9IDAsIGpqID0ga2V5cy5sZW5ndGg7IGogPCBqajsgaisrKSB7DQogICAgICAgIHZhciBrZXkgPSBrZXlzW2pdOw0KICAgICAgICBkc3Rba2V5XSA9IG9ialtrZXldOw0KICAgICAgfQ0KICAgIH0NCiAgfQ0KDQogIHNldEhhc2hLZXkoZHN0LCBoKTsNCiAgcmV0dXJuIGRzdDsNCn0NCg0KZnVuY3Rpb24gaW50KHN0cikgew0KICByZXR1cm4gcGFyc2VJbnQoc3RyLCAxMCk7DQp9DQoNCg0KZnVuY3Rpb24gaW5oZXJpdChwYXJlbnQsIGV4dHJhKSB7DQogIHJldHVybiBleHRlbmQoT2JqZWN0LmNyZWF0ZShwYXJlbnQpLCBleHRyYSk7DQp9DQoNCi8qKg0KICogQG5nZG9jIGZ1bmN0aW9uDQogKiBAbmFtZSBhbmd1bGFyLm5vb3ANCiAqIEBtb2R1bGUgbmcNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBBIGZ1bmN0aW9uIHRoYXQgcGVyZm9ybXMgbm8gb3BlcmF0aW9ucy4gVGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZnVsIHdoZW4gd3JpdGluZyBjb2RlIGluIHRoZQ0KICogZnVuY3Rpb25hbCBzdHlsZS4NCiAgIGBgYGpzDQogICAgIGZ1bmN0aW9uIGZvbyhjYWxsYmFjaykgew0KICAgICAgIHZhciByZXN1bHQgPSBjYWxjdWxhdGVSZXN1bHQoKTsNCiAgICAgICAoY2FsbGJhY2sgfHwgYW5ndWxhci5ub29wKShyZXN1bHQpOw0KICAgICB9DQogICBgYGANCiAqLw0KZnVuY3Rpb24gbm9vcCgpIHt9DQpub29wLiRpbmplY3QgPSBbXTsNCg0KDQovKioNCiAqIEBuZ2RvYyBmdW5jdGlvbg0KICogQG5hbWUgYW5ndWxhci5pZGVudGl0eQ0KICogQG1vZHVsZSBuZw0KICogQGtpbmQgZnVuY3Rpb24NCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIEEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGl0cyBmaXJzdCBhcmd1bWVudC4gVGhpcyBmdW5jdGlvbiBpcyB1c2VmdWwgd2hlbiB3cml0aW5nIGNvZGUgaW4gdGhlDQogKiBmdW5jdGlvbmFsIHN0eWxlLg0KICoNCiAgIGBgYGpzDQogICAgIGZ1bmN0aW9uIHRyYW5zZm9ybWVyKHRyYW5zZm9ybWF0aW9uRm4sIHZhbHVlKSB7DQogICAgICAgcmV0dXJuICh0cmFuc2Zvcm1hdGlvbkZuIHx8IGFuZ3VsYXIuaWRlbnRpdHkpKHZhbHVlKTsNCiAgICAgfTsNCiAgIGBgYA0KICAqIEBwYXJhbSB7Kn0gdmFsdWUgdG8gYmUgcmV0dXJuZWQuDQogICogQHJldHVybnMgeyp9IHRoZSB2YWx1ZSBwYXNzZWQgaW4uDQogKi8NCmZ1bmN0aW9uIGlkZW50aXR5KCQpIHtyZXR1cm4gJDt9DQppZGVudGl0eS4kaW5qZWN0ID0gW107DQoNCg0KZnVuY3Rpb24gdmFsdWVGbih2YWx1ZSkge3JldHVybiBmdW5jdGlvbigpIHtyZXR1cm4gdmFsdWU7fTt9DQoNCi8qKg0KICogQG5nZG9jIGZ1bmN0aW9uDQogKiBAbmFtZSBhbmd1bGFyLmlzVW5kZWZpbmVkDQogKiBAbW9kdWxlIG5nDQogKiBAa2luZCBmdW5jdGlvbg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogRGV0ZXJtaW5lcyBpZiBhIHJlZmVyZW5jZSBpcyB1bmRlZmluZWQuDQogKg0KICogQHBhcmFtIHsqfSB2YWx1ZSBSZWZlcmVuY2UgdG8gY2hlY2suDQogKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBgdmFsdWVgIGlzIHVuZGVmaW5lZC4NCiAqLw0KZnVuY3Rpb24gaXNVbmRlZmluZWQodmFsdWUpIHtyZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJzt9DQoNCg0KLyoqDQogKiBAbmdkb2MgZnVuY3Rpb24NCiAqIEBuYW1lIGFuZ3VsYXIuaXNEZWZpbmVkDQogKiBAbW9kdWxlIG5nDQogKiBAa2luZCBmdW5jdGlvbg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogRGV0ZXJtaW5lcyBpZiBhIHJlZmVyZW5jZSBpcyBkZWZpbmVkLg0KICoNCiAqIEBwYXJhbSB7Kn0gdmFsdWUgUmVmZXJlbmNlIHRvIGNoZWNrLg0KICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgYHZhbHVlYCBpcyBkZWZpbmVkLg0KICovDQpmdW5jdGlvbiBpc0RlZmluZWQodmFsdWUpIHtyZXR1cm4gdHlwZW9mIHZhbHVlICE9PSAndW5kZWZpbmVkJzt9DQoNCg0KLyoqDQogKiBAbmdkb2MgZnVuY3Rpb24NCiAqIEBuYW1lIGFuZ3VsYXIuaXNPYmplY3QNCiAqIEBtb2R1bGUgbmcNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBEZXRlcm1pbmVzIGlmIGEgcmVmZXJlbmNlIGlzIGFuIGBPYmplY3RgLiBVbmxpa2UgYHR5cGVvZmAgaW4gSmF2YVNjcmlwdCwgYG51bGxgcyBhcmUgbm90DQogKiBjb25zaWRlcmVkIHRvIGJlIG9iamVjdHMuIE5vdGUgdGhhdCBKYXZhU2NyaXB0IGFycmF5cyBhcmUgb2JqZWN0cy4NCiAqDQogKiBAcGFyYW0geyp9IHZhbHVlIFJlZmVyZW5jZSB0byBjaGVjay4NCiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIGB2YWx1ZWAgaXMgYW4gYE9iamVjdGAgYnV0IG5vdCBgbnVsbGAuDQogKi8NCmZ1bmN0aW9uIGlzT2JqZWN0KHZhbHVlKSB7DQogIC8vIGh0dHA6Ly9qc3BlcmYuY29tL2lzb2JqZWN0NA0KICByZXR1cm4gdmFsdWUgIT09IG51bGwgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JzsNCn0NCg0KDQovKioNCiAqIEBuZ2RvYyBmdW5jdGlvbg0KICogQG5hbWUgYW5ndWxhci5pc1N0cmluZw0KICogQG1vZHVsZSBuZw0KICogQGtpbmQgZnVuY3Rpb24NCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIERldGVybWluZXMgaWYgYSByZWZlcmVuY2UgaXMgYSBgU3RyaW5nYC4NCiAqDQogKiBAcGFyYW0geyp9IHZhbHVlIFJlZmVyZW5jZSB0byBjaGVjay4NCiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIGB2YWx1ZWAgaXMgYSBgU3RyaW5nYC4NCiAqLw0KZnVuY3Rpb24gaXNTdHJpbmcodmFsdWUpIHtyZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJzt9DQoNCg0KLyoqDQogKiBAbmdkb2MgZnVuY3Rpb24NCiAqIEBuYW1lIGFuZ3VsYXIuaXNOdW1iZXINCiAqIEBtb2R1bGUgbmcNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBEZXRlcm1pbmVzIGlmIGEgcmVmZXJlbmNlIGlzIGEgYE51bWJlcmAuDQogKg0KICogQHBhcmFtIHsqfSB2YWx1ZSBSZWZlcmVuY2UgdG8gY2hlY2suDQogKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBgdmFsdWVgIGlzIGEgYE51bWJlcmAuDQogKi8NCmZ1bmN0aW9uIGlzTnVtYmVyKHZhbHVlKSB7cmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7fQ0KDQoNCi8qKg0KICogQG5nZG9jIGZ1bmN0aW9uDQogKiBAbmFtZSBhbmd1bGFyLmlzRGF0ZQ0KICogQG1vZHVsZSBuZw0KICogQGtpbmQgZnVuY3Rpb24NCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIERldGVybWluZXMgaWYgYSB2YWx1ZSBpcyBhIGRhdGUuDQogKg0KICogQHBhcmFtIHsqfSB2YWx1ZSBSZWZlcmVuY2UgdG8gY2hlY2suDQogKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBgdmFsdWVgIGlzIGEgYERhdGVgLg0KICovDQpmdW5jdGlvbiBpc0RhdGUodmFsdWUpIHsNCiAgcmV0dXJuIHRvU3RyaW5nLmNhbGwodmFsdWUpID09PSAnW29iamVjdCBEYXRlXSc7DQp9DQoNCg0KLyoqDQogKiBAbmdkb2MgZnVuY3Rpb24NCiAqIEBuYW1lIGFuZ3VsYXIuaXNBcnJheQ0KICogQG1vZHVsZSBuZw0KICogQGtpbmQgZnVuY3Rpb24NCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIERldGVybWluZXMgaWYgYSByZWZlcmVuY2UgaXMgYW4gYEFycmF5YC4NCiAqDQogKiBAcGFyYW0geyp9IHZhbHVlIFJlZmVyZW5jZSB0byBjaGVjay4NCiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIGB2YWx1ZWAgaXMgYW4gYEFycmF5YC4NCiAqLw0KdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5Ow0KDQovKioNCiAqIEBuZ2RvYyBmdW5jdGlvbg0KICogQG5hbWUgYW5ndWxhci5pc0Z1bmN0aW9uDQogKiBAbW9kdWxlIG5nDQogKiBAa2luZCBmdW5jdGlvbg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogRGV0ZXJtaW5lcyBpZiBhIHJlZmVyZW5jZSBpcyBhIGBGdW5jdGlvbmAuDQogKg0KICogQHBhcmFtIHsqfSB2YWx1ZSBSZWZlcmVuY2UgdG8gY2hlY2suDQogKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBgdmFsdWVgIGlzIGEgYEZ1bmN0aW9uYC4NCiAqLw0KZnVuY3Rpb24gaXNGdW5jdGlvbih2YWx1ZSkge3JldHVybiB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbic7fQ0KDQoNCi8qKg0KICogRGV0ZXJtaW5lcyBpZiBhIHZhbHVlIGlzIGEgcmVndWxhciBleHByZXNzaW9uIG9iamVjdC4NCiAqDQogKiBAcHJpdmF0ZQ0KICogQHBhcmFtIHsqfSB2YWx1ZSBSZWZlcmVuY2UgdG8gY2hlY2suDQogKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBgdmFsdWVgIGlzIGEgYFJlZ0V4cGAuDQogKi8NCmZ1bmN0aW9uIGlzUmVnRXhwKHZhbHVlKSB7DQogIHJldHVybiB0b1N0cmluZy5jYWxsKHZhbHVlKSA9PT0gJ1tvYmplY3QgUmVnRXhwXSc7DQp9DQoNCg0KLyoqDQogKiBDaGVja3MgaWYgYG9iamAgaXMgYSB3aW5kb3cgb2JqZWN0Lg0KICoNCiAqIEBwcml2YXRlDQogKiBAcGFyYW0geyp9IG9iaiBPYmplY3QgdG8gY2hlY2sNCiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIGBvYmpgIGlzIGEgd2luZG93IG9iai4NCiAqLw0KZnVuY3Rpb24gaXNXaW5kb3cob2JqKSB7DQogIHJldHVybiBvYmogJiYgb2JqLndpbmRvdyA9PT0gb2JqOw0KfQ0KDQoNCmZ1bmN0aW9uIGlzU2NvcGUob2JqKSB7DQogIHJldHVybiBvYmogJiYgb2JqLiRldmFsQXN5bmMgJiYgb2JqLiR3YXRjaDsNCn0NCg0KDQpmdW5jdGlvbiBpc0ZpbGUob2JqKSB7DQogIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IEZpbGVdJzsNCn0NCg0KDQpmdW5jdGlvbiBpc0Zvcm1EYXRhKG9iaikgew0KICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCBGb3JtRGF0YV0nOw0KfQ0KDQoNCmZ1bmN0aW9uIGlzQmxvYihvYmopIHsNCiAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgQmxvYl0nOw0KfQ0KDQoNCmZ1bmN0aW9uIGlzQm9vbGVhbih2YWx1ZSkgew0KICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7DQp9DQoNCg0KZnVuY3Rpb24gaXNQcm9taXNlTGlrZShvYmopIHsNCiAgcmV0dXJuIG9iaiAmJiBpc0Z1bmN0aW9uKG9iai50aGVuKTsNCn0NCg0KDQp2YXIgdHJpbSA9IGZ1bmN0aW9uKHZhbHVlKSB7DQogIHJldHVybiBpc1N0cmluZyh2YWx1ZSkgPyB2YWx1ZS50cmltKCkgOiB2YWx1ZTsNCn07DQoNCi8vIENvcGllZCBmcm9tOg0KLy8gaHR0cDovL2RvY3MuY2xvc3VyZS1saWJyYXJ5Lmdvb2dsZWNvZGUuY29tL2dpdC9sb2NhbF9jbG9zdXJlX2dvb2dfc3RyaW5nX3N0cmluZy5qcy5zb3VyY2UuaHRtbCNsaW5lMTAyMQ0KLy8gUHJlcmVxOiBzIGlzIGEgc3RyaW5nLg0KdmFyIGVzY2FwZUZvclJlZ2V4cCA9IGZ1bmN0aW9uKHMpIHsNCiAgcmV0dXJuIHMucmVwbGFjZSgvKFstKClcW1xde30rPyouJFxefCw6IzwhXFxdKS9nLCAnXFwkMScpLg0KICAgICAgICAgICByZXBsYWNlKC9ceDA4L2csICdcXHgwOCcpOw0KfTsNCg0KDQovKioNCiAqIEBuZ2RvYyBmdW5jdGlvbg0KICogQG5hbWUgYW5ndWxhci5pc0VsZW1lbnQNCiAqIEBtb2R1bGUgbmcNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBEZXRlcm1pbmVzIGlmIGEgcmVmZXJlbmNlIGlzIGEgRE9NIGVsZW1lbnQgKG9yIHdyYXBwZWQgalF1ZXJ5IGVsZW1lbnQpLg0KICoNCiAqIEBwYXJhbSB7Kn0gdmFsdWUgUmVmZXJlbmNlIHRvIGNoZWNrLg0KICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgYHZhbHVlYCBpcyBhIERPTSBlbGVtZW50IChvciB3cmFwcGVkIGpRdWVyeSBlbGVtZW50KS4NCiAqLw0KZnVuY3Rpb24gaXNFbGVtZW50KG5vZGUpIHsNCiAgcmV0dXJuICEhKG5vZGUgJiYNCiAgICAobm9kZS5ub2RlTmFtZSAgLy8gd2UgYXJlIGEgZGlyZWN0IGVsZW1lbnQNCiAgICB8fCAobm9kZS5wcm9wICYmIG5vZGUuYXR0ciAmJiBub2RlLmZpbmQpKSk7ICAvLyB3ZSBoYXZlIGFuIG9uIGFuZCBmaW5kIG1ldGhvZCBwYXJ0IG9mIGpRdWVyeSBBUEkNCn0NCg0KLyoqDQogKiBAcGFyYW0gc3RyICdrZXkxLGtleTIsLi4uJw0KICogQHJldHVybnMge29iamVjdH0gaW4gdGhlIGZvcm0gb2Yge2tleTE6dHJ1ZSwga2V5Mjp0cnVlLCAuLi59DQogKi8NCmZ1bmN0aW9uIG1ha2VNYXAoc3RyKSB7DQogIHZhciBvYmogPSB7fSwgaXRlbXMgPSBzdHIuc3BsaXQoIiwiKSwgaTsNCiAgZm9yIChpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgaSsrKQ0KICAgIG9ialsgaXRlbXNbaV0gXSA9IHRydWU7DQogIHJldHVybiBvYmo7DQp9DQoNCg0KZnVuY3Rpb24gbm9kZU5hbWVfKGVsZW1lbnQpIHsNCiAgcmV0dXJuIGxvd2VyY2FzZShlbGVtZW50Lm5vZGVOYW1lIHx8IChlbGVtZW50WzBdICYmIGVsZW1lbnRbMF0ubm9kZU5hbWUpKTsNCn0NCg0KZnVuY3Rpb24gaW5jbHVkZXMoYXJyYXksIG9iaikgew0KICByZXR1cm4gQXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbChhcnJheSwgb2JqKSAhPSAtMTsNCn0NCg0KZnVuY3Rpb24gYXJyYXlSZW1vdmUoYXJyYXksIHZhbHVlKSB7DQogIHZhciBpbmRleCA9IGFycmF5LmluZGV4T2YodmFsdWUpOw0KICBpZiAoaW5kZXggPj0gMCkNCiAgICBhcnJheS5zcGxpY2UoaW5kZXgsIDEpOw0KICByZXR1cm4gdmFsdWU7DQp9DQoNCi8qKg0KICogQG5nZG9jIGZ1bmN0aW9uDQogKiBAbmFtZSBhbmd1bGFyLmNvcHkNCiAqIEBtb2R1bGUgbmcNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBDcmVhdGVzIGEgZGVlcCBjb3B5IG9mIGBzb3VyY2VgLCB3aGljaCBzaG91bGQgYmUgYW4gb2JqZWN0IG9yIGFuIGFycmF5Lg0KICoNCiAqICogSWYgbm8gZGVzdGluYXRpb24gaXMgc3VwcGxpZWQsIGEgY29weSBvZiB0aGUgb2JqZWN0IG9yIGFycmF5IGlzIGNyZWF0ZWQuDQogKiAqIElmIGEgZGVzdGluYXRpb24gaXMgcHJvdmlkZWQsIGFsbCBvZiBpdHMgZWxlbWVudHMgKGZvciBhcnJheXMpIG9yIHByb3BlcnRpZXMgKGZvciBvYmplY3RzKQ0KICogICBhcmUgZGVsZXRlZCBhbmQgdGhlbiBhbGwgZWxlbWVudHMvcHJvcGVydGllcyBmcm9tIHRoZSBzb3VyY2UgYXJlIGNvcGllZCB0byBpdC4NCiAqICogSWYgYHNvdXJjZWAgaXMgbm90IGFuIG9iamVjdCBvciBhcnJheSAoaW5jLiBgbnVsbGAgYW5kIGB1bmRlZmluZWRgKSwgYHNvdXJjZWAgaXMgcmV0dXJuZWQuDQogKiAqIElmIGBzb3VyY2VgIGlzIGlkZW50aWNhbCB0byAnZGVzdGluYXRpb24nIGFuIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93bi4NCiAqDQogKiBAcGFyYW0geyp9IHNvdXJjZSBUaGUgc291cmNlIHRoYXQgd2lsbCBiZSB1c2VkIHRvIG1ha2UgYSBjb3B5Lg0KICogICAgICAgICAgICAgICAgICAgQ2FuIGJlIGFueSB0eXBlLCBpbmNsdWRpbmcgcHJpbWl0aXZlcywgYG51bGxgLCBhbmQgYHVuZGVmaW5lZGAuDQogKiBAcGFyYW0geyhPYmplY3R8QXJyYXkpPX0gZGVzdGluYXRpb24gRGVzdGluYXRpb24gaW50byB3aGljaCB0aGUgc291cmNlIGlzIGNvcGllZC4gSWYNCiAqICAgICBwcm92aWRlZCwgbXVzdCBiZSBvZiB0aGUgc2FtZSB0eXBlIGFzIGBzb3VyY2VgLg0KICogQHJldHVybnMgeyp9IFRoZSBjb3B5IG9yIHVwZGF0ZWQgYGRlc3RpbmF0aW9uYCwgaWYgYGRlc3RpbmF0aW9uYCB3YXMgc3BlY2lmaWVkLg0KICoNCiAqIEBleGFtcGxlDQogPGV4YW1wbGUgbW9kdWxlPSJjb3B5RXhhbXBsZSI+DQogPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogPGRpdiBuZy1jb250cm9sbGVyPSJFeGFtcGxlQ29udHJvbGxlciI+DQogPGZvcm0gbm92YWxpZGF0ZSBjbGFzcz0ic2ltcGxlLWZvcm0iPg0KIE5hbWU6IDxpbnB1dCB0eXBlPSJ0ZXh0IiBuZy1tb2RlbD0idXNlci5uYW1lIiAvPjxiciAvPg0KIEUtbWFpbDogPGlucHV0IHR5cGU9ImVtYWlsIiBuZy1tb2RlbD0idXNlci5lbWFpbCIgLz48YnIgLz4NCiBHZW5kZXI6IDxpbnB1dCB0eXBlPSJyYWRpbyIgbmctbW9kZWw9InVzZXIuZ2VuZGVyIiB2YWx1ZT0ibWFsZSIgLz5tYWxlDQogPGlucHV0IHR5cGU9InJhZGlvIiBuZy1tb2RlbD0idXNlci5nZW5kZXIiIHZhbHVlPSJmZW1hbGUiIC8+ZmVtYWxlPGJyIC8+DQogPGJ1dHRvbiBuZy1jbGljaz0icmVzZXQoKSI+UkVTRVQ8L2J1dHRvbj4NCiA8YnV0dG9uIG5nLWNsaWNrPSJ1cGRhdGUodXNlcikiPlNBVkU8L2J1dHRvbj4NCiA8L2Zvcm0+DQogPHByZT5mb3JtID0ge3t1c2VyIHwganNvbn19PC9wcmU+DQogPHByZT5tYXN0ZXIgPSB7e21hc3RlciB8IGpzb259fTwvcHJlPg0KIDwvZGl2Pg0KDQogPHNjcmlwdD4NCiAgYW5ndWxhci5tb2R1bGUoJ2NvcHlFeGFtcGxlJywgW10pDQogICAgLmNvbnRyb2xsZXIoJ0V4YW1wbGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICRzY29wZS5tYXN0ZXI9IHt9Ow0KDQogICAgICAkc2NvcGUudXBkYXRlID0gZnVuY3Rpb24odXNlcikgew0KICAgICAgICAvLyBFeGFtcGxlIHdpdGggMSBhcmd1bWVudA0KICAgICAgICAkc2NvcGUubWFzdGVyPSBhbmd1bGFyLmNvcHkodXNlcik7DQogICAgICB9Ow0KDQogICAgICAkc2NvcGUucmVzZXQgPSBmdW5jdGlvbigpIHsNCiAgICAgICAgLy8gRXhhbXBsZSB3aXRoIDIgYXJndW1lbnRzDQogICAgICAgIGFuZ3VsYXIuY29weSgkc2NvcGUubWFzdGVyLCAkc2NvcGUudXNlcik7DQogICAgICB9Ow0KDQogICAgICAkc2NvcGUucmVzZXQoKTsNCiAgICB9XSk7DQogPC9zY3JpcHQ+DQogPC9maWxlPg0KIDwvZXhhbXBsZT4NCiAqLw0KZnVuY3Rpb24gY29weShzb3VyY2UsIGRlc3RpbmF0aW9uLCBzdGFja1NvdXJjZSwgc3RhY2tEZXN0KSB7DQogIGlmIChpc1dpbmRvdyhzb3VyY2UpIHx8IGlzU2NvcGUoc291cmNlKSkgew0KICAgIHRocm93IG5nTWluRXJyKCdjcHdzJywNCiAgICAgICJDYW4ndCBjb3B5ISBNYWtpbmcgY29waWVzIG9mIFdpbmRvdyBvciBTY29wZSBpbnN0YW5jZXMgaXMgbm90IHN1cHBvcnRlZC4iKTsNCiAgfQ0KDQogIGlmICghZGVzdGluYXRpb24pIHsNCiAgICBkZXN0aW5hdGlvbiA9IHNvdXJjZTsNCiAgICBpZiAoc291cmNlKSB7DQogICAgICBpZiAoaXNBcnJheShzb3VyY2UpKSB7DQogICAgICAgIGRlc3RpbmF0aW9uID0gY29weShzb3VyY2UsIFtdLCBzdGFja1NvdXJjZSwgc3RhY2tEZXN0KTsNCiAgICAgIH0gZWxzZSBpZiAoaXNEYXRlKHNvdXJjZSkpIHsNCiAgICAgICAgZGVzdGluYXRpb24gPSBuZXcgRGF0ZShzb3VyY2UuZ2V0VGltZSgpKTsNCiAgICAgIH0gZWxzZSBpZiAoaXNSZWdFeHAoc291cmNlKSkgew0KICAgICAgICBkZXN0aW5hdGlvbiA9IG5ldyBSZWdFeHAoc291cmNlLnNvdXJjZSwgc291cmNlLnRvU3RyaW5nKCkubWF0Y2goL1teXC9dKiQvKVswXSk7DQogICAgICAgIGRlc3RpbmF0aW9uLmxhc3RJbmRleCA9IHNvdXJjZS5sYXN0SW5kZXg7DQogICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHNvdXJjZSkpIHsNCiAgICAgICAgdmFyIGVtcHR5T2JqZWN0ID0gT2JqZWN0LmNyZWF0ZShPYmplY3QuZ2V0UHJvdG90eXBlT2Yoc291cmNlKSk7DQogICAgICAgIGRlc3RpbmF0aW9uID0gY29weShzb3VyY2UsIGVtcHR5T2JqZWN0LCBzdGFja1NvdXJjZSwgc3RhY2tEZXN0KTsNCiAgICAgIH0NCiAgICB9DQogIH0gZWxzZSB7DQogICAgaWYgKHNvdXJjZSA9PT0gZGVzdGluYXRpb24pIHRocm93IG5nTWluRXJyKCdjcGknLA0KICAgICAgIkNhbid0IGNvcHkhIFNvdXJjZSBhbmQgZGVzdGluYXRpb24gYXJlIGlkZW50aWNhbC4iKTsNCg0KICAgIHN0YWNrU291cmNlID0gc3RhY2tTb3VyY2UgfHwgW107DQogICAgc3RhY2tEZXN0ID0gc3RhY2tEZXN0IHx8IFtdOw0KDQogICAgaWYgKGlzT2JqZWN0KHNvdXJjZSkpIHsNCiAgICAgIHZhciBpbmRleCA9IHN0YWNrU291cmNlLmluZGV4T2Yoc291cmNlKTsNCiAgICAgIGlmIChpbmRleCAhPT0gLTEpIHJldHVybiBzdGFja0Rlc3RbaW5kZXhdOw0KDQogICAgICBzdGFja1NvdXJjZS5wdXNoKHNvdXJjZSk7DQogICAgICBzdGFja0Rlc3QucHVzaChkZXN0aW5hdGlvbik7DQogICAgfQ0KDQogICAgdmFyIHJlc3VsdDsNCiAgICBpZiAoaXNBcnJheShzb3VyY2UpKSB7DQogICAgICBkZXN0aW5hdGlvbi5sZW5ndGggPSAwOw0KICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzb3VyY2UubGVuZ3RoOyBpKyspIHsNCiAgICAgICAgcmVzdWx0ID0gY29weShzb3VyY2VbaV0sIG51bGwsIHN0YWNrU291cmNlLCBzdGFja0Rlc3QpOw0KICAgICAgICBpZiAoaXNPYmplY3Qoc291cmNlW2ldKSkgew0KICAgICAgICAgIHN0YWNrU291cmNlLnB1c2goc291cmNlW2ldKTsNCiAgICAgICAgICBzdGFja0Rlc3QucHVzaChyZXN1bHQpOw0KICAgICAgICB9DQogICAgICAgIGRlc3RpbmF0aW9uLnB1c2gocmVzdWx0KTsNCiAgICAgIH0NCiAgICB9IGVsc2Ugew0KICAgICAgdmFyIGggPSBkZXN0aW5hdGlvbi4kJGhhc2hLZXk7DQogICAgICBpZiAoaXNBcnJheShkZXN0aW5hdGlvbikpIHsNCiAgICAgICAgZGVzdGluYXRpb24ubGVuZ3RoID0gMDsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIGZvckVhY2goZGVzdGluYXRpb24sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHsNCiAgICAgICAgICBkZWxldGUgZGVzdGluYXRpb25ba2V5XTsNCiAgICAgICAgfSk7DQogICAgICB9DQogICAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7DQogICAgICAgIGlmIChzb3VyY2UuaGFzT3duUHJvcGVydHkoa2V5KSkgew0KICAgICAgICAgIHJlc3VsdCA9IGNvcHkoc291cmNlW2tleV0sIG51bGwsIHN0YWNrU291cmNlLCBzdGFja0Rlc3QpOw0KICAgICAgICAgIGlmIChpc09iamVjdChzb3VyY2Vba2V5XSkpIHsNCiAgICAgICAgICAgIHN0YWNrU291cmNlLnB1c2goc291cmNlW2tleV0pOw0KICAgICAgICAgICAgc3RhY2tEZXN0LnB1c2gocmVzdWx0KTsNCiAgICAgICAgICB9DQogICAgICAgICAgZGVzdGluYXRpb25ba2V5XSA9IHJlc3VsdDsNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgc2V0SGFzaEtleShkZXN0aW5hdGlvbixoKTsNCiAgICB9DQoNCiAgfQ0KICByZXR1cm4gZGVzdGluYXRpb247DQp9DQoNCi8qKg0KICogQ3JlYXRlcyBhIHNoYWxsb3cgY29weSBvZiBhbiBvYmplY3QsIGFuIGFycmF5IG9yIGEgcHJpbWl0aXZlLg0KICoNCiAqIEFzc3VtZXMgdGhhdCB0aGVyZSBhcmUgbm8gcHJvdG8gcHJvcGVydGllcyBmb3Igb2JqZWN0cy4NCiAqLw0KZnVuY3Rpb24gc2hhbGxvd0NvcHkoc3JjLCBkc3QpIHsNCiAgaWYgKGlzQXJyYXkoc3JjKSkgew0KICAgIGRzdCA9IGRzdCB8fCBbXTsNCg0KICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHNyYy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7DQogICAgICBkc3RbaV0gPSBzcmNbaV07DQogICAgfQ0KICB9IGVsc2UgaWYgKGlzT2JqZWN0KHNyYykpIHsNCiAgICBkc3QgPSBkc3QgfHwge307DQoNCiAgICBmb3IgKHZhciBrZXkgaW4gc3JjKSB7DQogICAgICBpZiAoIShrZXkuY2hhckF0KDApID09PSAnJCcgJiYga2V5LmNoYXJBdCgxKSA9PT0gJyQnKSkgew0KICAgICAgICBkc3Rba2V5XSA9IHNyY1trZXldOw0KICAgICAgfQ0KICAgIH0NCiAgfQ0KDQogIHJldHVybiBkc3QgfHwgc3JjOw0KfQ0KDQoNCi8qKg0KICogQG5nZG9jIGZ1bmN0aW9uDQogKiBAbmFtZSBhbmd1bGFyLmVxdWFscw0KICogQG1vZHVsZSBuZw0KICogQGtpbmQgZnVuY3Rpb24NCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIERldGVybWluZXMgaWYgdHdvIG9iamVjdHMgb3IgdHdvIHZhbHVlcyBhcmUgZXF1aXZhbGVudC4gU3VwcG9ydHMgdmFsdWUgdHlwZXMsIHJlZ3VsYXINCiAqIGV4cHJlc3Npb25zLCBhcnJheXMgYW5kIG9iamVjdHMuDQogKg0KICogVHdvIG9iamVjdHMgb3IgdmFsdWVzIGFyZSBjb25zaWRlcmVkIGVxdWl2YWxlbnQgaWYgYXQgbGVhc3Qgb25lIG9mIHRoZSBmb2xsb3dpbmcgaXMgdHJ1ZToNCiAqDQogKiAqIEJvdGggb2JqZWN0cyBvciB2YWx1ZXMgcGFzcyBgPT09YCBjb21wYXJpc29uLg0KICogKiBCb3RoIG9iamVjdHMgb3IgdmFsdWVzIGFyZSBvZiB0aGUgc2FtZSB0eXBlIGFuZCBhbGwgb2YgdGhlaXIgcHJvcGVydGllcyBhcmUgZXF1YWwgYnkNCiAqICAgY29tcGFyaW5nIHRoZW0gd2l0aCBgYW5ndWxhci5lcXVhbHNgLg0KICogKiBCb3RoIHZhbHVlcyBhcmUgTmFOLiAoSW4gSmF2YVNjcmlwdCwgTmFOID09IE5hTiA9PiBmYWxzZS4gQnV0IHdlIGNvbnNpZGVyIHR3byBOYU4gYXMgZXF1YWwpDQogKiAqIEJvdGggdmFsdWVzIHJlcHJlc2VudCB0aGUgc2FtZSByZWd1bGFyIGV4cHJlc3Npb24gKEluIEphdmFTY3JpcHQsDQogKiAgIC9hYmMvID09IC9hYmMvID0+IGZhbHNlLiBCdXQgd2UgY29uc2lkZXIgdHdvIHJlZ3VsYXIgZXhwcmVzc2lvbnMgYXMgZXF1YWwgd2hlbiB0aGVpciB0ZXh0dWFsDQogKiAgIHJlcHJlc2VudGF0aW9uIG1hdGNoZXMpLg0KICoNCiAqIER1cmluZyBhIHByb3BlcnR5IGNvbXBhcmlzb24sIHByb3BlcnRpZXMgb2YgYGZ1bmN0aW9uYCB0eXBlIGFuZCBwcm9wZXJ0aWVzIHdpdGggbmFtZXMNCiAqIHRoYXQgYmVnaW4gd2l0aCBgJGAgYXJlIGlnbm9yZWQuDQogKg0KICogU2NvcGUgYW5kIERPTVdpbmRvdyBvYmplY3RzIGFyZSBiZWluZyBjb21wYXJlZCBvbmx5IGJ5IGlkZW50aWZ5IChgPT09YCkuDQogKg0KICogQHBhcmFtIHsqfSBvMSBPYmplY3Qgb3IgdmFsdWUgdG8gY29tcGFyZS4NCiAqIEBwYXJhbSB7Kn0gbzIgT2JqZWN0IG9yIHZhbHVlIHRvIGNvbXBhcmUuDQogKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBhcmd1bWVudHMgYXJlIGVxdWFsLg0KICovDQpmdW5jdGlvbiBlcXVhbHMobzEsIG8yKSB7DQogIGlmIChvMSA9PT0gbzIpIHJldHVybiB0cnVlOw0KICBpZiAobzEgPT09IG51bGwgfHwgbzIgPT09IG51bGwpIHJldHVybiBmYWxzZTsNCiAgaWYgKG8xICE9PSBvMSAmJiBvMiAhPT0gbzIpIHJldHVybiB0cnVlOyAvLyBOYU4gPT09IE5hTg0KICB2YXIgdDEgPSB0eXBlb2YgbzEsIHQyID0gdHlwZW9mIG8yLCBsZW5ndGgsIGtleSwga2V5U2V0Ow0KICBpZiAodDEgPT0gdDIpIHsNCiAgICBpZiAodDEgPT0gJ29iamVjdCcpIHsNCiAgICAgIGlmIChpc0FycmF5KG8xKSkgew0KICAgICAgICBpZiAoIWlzQXJyYXkobzIpKSByZXR1cm4gZmFsc2U7DQogICAgICAgIGlmICgobGVuZ3RoID0gbzEubGVuZ3RoKSA9PSBvMi5sZW5ndGgpIHsNCiAgICAgICAgICBmb3IgKGtleSA9IDA7IGtleSA8IGxlbmd0aDsga2V5KyspIHsNCiAgICAgICAgICAgIGlmICghZXF1YWxzKG8xW2tleV0sIG8yW2tleV0pKSByZXR1cm4gZmFsc2U7DQogICAgICAgICAgfQ0KICAgICAgICAgIHJldHVybiB0cnVlOw0KICAgICAgICB9DQogICAgICB9IGVsc2UgaWYgKGlzRGF0ZShvMSkpIHsNCiAgICAgICAgaWYgKCFpc0RhdGUobzIpKSByZXR1cm4gZmFsc2U7DQogICAgICAgIHJldHVybiBlcXVhbHMobzEuZ2V0VGltZSgpLCBvMi5nZXRUaW1lKCkpOw0KICAgICAgfSBlbHNlIGlmIChpc1JlZ0V4cChvMSkgJiYgaXNSZWdFeHAobzIpKSB7DQogICAgICAgIHJldHVybiBvMS50b1N0cmluZygpID09IG8yLnRvU3RyaW5nKCk7DQogICAgICB9IGVsc2Ugew0KICAgICAgICBpZiAoaXNTY29wZShvMSkgfHwgaXNTY29wZShvMikgfHwgaXNXaW5kb3cobzEpIHx8IGlzV2luZG93KG8yKSB8fCBpc0FycmF5KG8yKSkgcmV0dXJuIGZhbHNlOw0KICAgICAgICBrZXlTZXQgPSB7fTsNCiAgICAgICAgZm9yIChrZXkgaW4gbzEpIHsNCiAgICAgICAgICBpZiAoa2V5LmNoYXJBdCgwKSA9PT0gJyQnIHx8IGlzRnVuY3Rpb24obzFba2V5XSkpIGNvbnRpbnVlOw0KICAgICAgICAgIGlmICghZXF1YWxzKG8xW2tleV0sIG8yW2tleV0pKSByZXR1cm4gZmFsc2U7DQogICAgICAgICAga2V5U2V0W2tleV0gPSB0cnVlOw0KICAgICAgICB9DQogICAgICAgIGZvciAoa2V5IGluIG8yKSB7DQogICAgICAgICAgaWYgKCFrZXlTZXQuaGFzT3duUHJvcGVydHkoa2V5KSAmJg0KICAgICAgICAgICAgICBrZXkuY2hhckF0KDApICE9PSAnJCcgJiYNCiAgICAgICAgICAgICAgbzJba2V5XSAhPT0gdW5kZWZpbmVkICYmDQogICAgICAgICAgICAgICFpc0Z1bmN0aW9uKG8yW2tleV0pKSByZXR1cm4gZmFsc2U7DQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuIHRydWU7DQogICAgICB9DQogICAgfQ0KICB9DQogIHJldHVybiBmYWxzZTsNCn0NCg0KdmFyIGNzcCA9IGZ1bmN0aW9uKCkgew0KICBpZiAoaXNEZWZpbmVkKGNzcC5pc0FjdGl2ZV8pKSByZXR1cm4gY3NwLmlzQWN0aXZlXzsNCg0KICB2YXIgYWN0aXZlID0gISEoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW25nLWNzcF0nKSB8fA0KICAgICAgICAgICAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW2RhdGEtbmctY3NwXScpKTsNCg0KICBpZiAoIWFjdGl2ZSkgew0KICAgIHRyeSB7DQogICAgICAvKiBqc2hpbnQgLVcwMzEsIC1XMDU0ICovDQogICAgICBuZXcgRnVuY3Rpb24oJycpOw0KICAgICAgLyoganNoaW50ICtXMDMxLCArVzA1NCAqLw0KICAgIH0gY2F0Y2ggKGUpIHsNCiAgICAgIGFjdGl2ZSA9IHRydWU7DQogICAgfQ0KICB9DQoNCiAgcmV0dXJuIChjc3AuaXNBY3RpdmVfID0gYWN0aXZlKTsNCn07DQoNCg0KDQpmdW5jdGlvbiBjb25jYXQoYXJyYXkxLCBhcnJheTIsIGluZGV4KSB7DQogIHJldHVybiBhcnJheTEuY29uY2F0KHNsaWNlLmNhbGwoYXJyYXkyLCBpbmRleCkpOw0KfQ0KDQpmdW5jdGlvbiBzbGljZUFyZ3MoYXJncywgc3RhcnRJbmRleCkgew0KICByZXR1cm4gc2xpY2UuY2FsbChhcmdzLCBzdGFydEluZGV4IHx8IDApOw0KfQ0KDQoNCi8qIGpzaGludCAtVzEwMSAqLw0KLyoqDQogKiBAbmdkb2MgZnVuY3Rpb24NCiAqIEBuYW1lIGFuZ3VsYXIuYmluZA0KICogQG1vZHVsZSBuZw0KICogQGtpbmQgZnVuY3Rpb24NCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFJldHVybnMgYSBmdW5jdGlvbiB3aGljaCBjYWxscyBmdW5jdGlvbiBgZm5gIGJvdW5kIHRvIGBzZWxmYCAoYHNlbGZgIGJlY29tZXMgdGhlIGB0aGlzYCBmb3INCiAqIGBmbmApLiBZb3UgY2FuIHN1cHBseSBvcHRpb25hbCBgYXJnc2AgdGhhdCBhcmUgcHJlYm91bmQgdG8gdGhlIGZ1bmN0aW9uLiBUaGlzIGZlYXR1cmUgaXMgYWxzbw0KICoga25vd24gYXMgW3BhcnRpYWwgYXBwbGljYXRpb25dKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUGFydGlhbF9hcHBsaWNhdGlvbiksIGFzDQogKiBkaXN0aW5ndWlzaGVkIGZyb20gW2Z1bmN0aW9uIGN1cnJ5aW5nXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0N1cnJ5aW5nI0NvbnRyYXN0X3dpdGhfcGFydGlhbF9mdW5jdGlvbl9hcHBsaWNhdGlvbikuDQogKg0KICogQHBhcmFtIHtPYmplY3R9IHNlbGYgQ29udGV4dCB3aGljaCBgZm5gIHNob3VsZCBiZSBldmFsdWF0ZWQgaW4uDQogKiBAcGFyYW0ge2Z1bmN0aW9uKCl9IGZuIEZ1bmN0aW9uIHRvIGJlIGJvdW5kLg0KICogQHBhcmFtIHsuLi4qfSBhcmdzIE9wdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwcmVib3VuZCB0byB0aGUgYGZuYCBmdW5jdGlvbiBjYWxsLg0KICogQHJldHVybnMge2Z1bmN0aW9uKCl9IEZ1bmN0aW9uIHRoYXQgd3JhcHMgdGhlIGBmbmAgd2l0aCBhbGwgdGhlIHNwZWNpZmllZCBiaW5kaW5ncy4NCiAqLw0KLyoganNoaW50ICtXMTAxICovDQpmdW5jdGlvbiBiaW5kKHNlbGYsIGZuKSB7DQogIHZhciBjdXJyeUFyZ3MgPSBhcmd1bWVudHMubGVuZ3RoID4gMiA/IHNsaWNlQXJncyhhcmd1bWVudHMsIDIpIDogW107DQogIGlmIChpc0Z1bmN0aW9uKGZuKSAmJiAhKGZuIGluc3RhbmNlb2YgUmVnRXhwKSkgew0KICAgIHJldHVybiBjdXJyeUFyZ3MubGVuZ3RoDQogICAgICA/IGZ1bmN0aW9uKCkgew0KICAgICAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoDQogICAgICAgICAgICA/IGZuLmFwcGx5KHNlbGYsIGNvbmNhdChjdXJyeUFyZ3MsIGFyZ3VtZW50cywgMCkpDQogICAgICAgICAgICA6IGZuLmFwcGx5KHNlbGYsIGN1cnJ5QXJncyk7DQogICAgICAgIH0NCiAgICAgIDogZnVuY3Rpb24oKSB7DQogICAgICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGgNCiAgICAgICAgICAgID8gZm4uYXBwbHkoc2VsZiwgYXJndW1lbnRzKQ0KICAgICAgICAgICAgOiBmbi5jYWxsKHNlbGYpOw0KICAgICAgICB9Ow0KICB9IGVsc2Ugew0KICAgIC8vIGluIElFLCBuYXRpdmUgbWV0aG9kcyBhcmUgbm90IGZ1bmN0aW9ucyBzbyB0aGV5IGNhbm5vdCBiZSBib3VuZCAobm90ZTogdGhleSBkb24ndCBuZWVkIHRvIGJlKQ0KICAgIHJldHVybiBmbjsNCiAgfQ0KfQ0KDQoNCmZ1bmN0aW9uIHRvSnNvblJlcGxhY2VyKGtleSwgdmFsdWUpIHsNCiAgdmFyIHZhbCA9IHZhbHVlOw0KDQogIGlmICh0eXBlb2Yga2V5ID09PSAnc3RyaW5nJyAmJiBrZXkuY2hhckF0KDApID09PSAnJCcgJiYga2V5LmNoYXJBdCgxKSA9PT0gJyQnKSB7DQogICAgdmFsID0gdW5kZWZpbmVkOw0KICB9IGVsc2UgaWYgKGlzV2luZG93KHZhbHVlKSkgew0KICAgIHZhbCA9ICckV0lORE9XJzsNCiAgfSBlbHNlIGlmICh2YWx1ZSAmJiAgZG9jdW1lbnQgPT09IHZhbHVlKSB7DQogICAgdmFsID0gJyRET0NVTUVOVCc7DQogIH0gZWxzZSBpZiAoaXNTY29wZSh2YWx1ZSkpIHsNCiAgICB2YWwgPSAnJFNDT1BFJzsNCiAgfQ0KDQogIHJldHVybiB2YWw7DQp9DQoNCg0KLyoqDQogKiBAbmdkb2MgZnVuY3Rpb24NCiAqIEBuYW1lIGFuZ3VsYXIudG9Kc29uDQogKiBAbW9kdWxlIG5nDQogKiBAa2luZCBmdW5jdGlvbg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogU2VyaWFsaXplcyBpbnB1dCBpbnRvIGEgSlNPTi1mb3JtYXR0ZWQgc3RyaW5nLiBQcm9wZXJ0aWVzIHdpdGggbGVhZGluZyAkJCBjaGFyYWN0ZXJzIHdpbGwgYmUNCiAqIHN0cmlwcGVkIHNpbmNlIGFuZ3VsYXIgdXNlcyB0aGlzIG5vdGF0aW9uIGludGVybmFsbHkuDQogKg0KICogQHBhcmFtIHtPYmplY3R8QXJyYXl8RGF0ZXxzdHJpbmd8bnVtYmVyfSBvYmogSW5wdXQgdG8gYmUgc2VyaWFsaXplZCBpbnRvIEpTT04uDQogKiBAcGFyYW0ge2Jvb2xlYW58bnVtYmVyPX0gcHJldHR5IElmIHNldCB0byB0cnVlLCB0aGUgSlNPTiBvdXRwdXQgd2lsbCBjb250YWluIG5ld2xpbmVzIGFuZCB3aGl0ZXNwYWNlLg0KICogICAgSWYgc2V0IHRvIGFuIGludGVnZXIsIHRoZSBKU09OIG91dHB1dCB3aWxsIGNvbnRhaW4gdGhhdCBtYW55IHNwYWNlcyBwZXIgaW5kZW50YXRpb24gKHRoZSBkZWZhdWx0IGlzIDIpLg0KICogQHJldHVybnMge3N0cmluZ3x1bmRlZmluZWR9IEpTT04taWZpZWQgc3RyaW5nIHJlcHJlc2VudGluZyBgb2JqYC4NCiAqLw0KZnVuY3Rpb24gdG9Kc29uKG9iaiwgcHJldHR5KSB7DQogIGlmICh0eXBlb2Ygb2JqID09PSAndW5kZWZpbmVkJykgcmV0dXJuIHVuZGVmaW5lZDsNCiAgaWYgKCFpc051bWJlcihwcmV0dHkpKSB7DQogICAgcHJldHR5ID0gcHJldHR5ID8gMiA6IG51bGw7DQogIH0NCiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgdG9Kc29uUmVwbGFjZXIsIHByZXR0eSk7DQp9DQoNCg0KLyoqDQogKiBAbmdkb2MgZnVuY3Rpb24NCiAqIEBuYW1lIGFuZ3VsYXIuZnJvbUpzb24NCiAqIEBtb2R1bGUgbmcNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBEZXNlcmlhbGl6ZXMgYSBKU09OIHN0cmluZy4NCiAqDQogKiBAcGFyYW0ge3N0cmluZ30ganNvbiBKU09OIHN0cmluZyB0byBkZXNlcmlhbGl6ZS4NCiAqIEByZXR1cm5zIHtPYmplY3R8QXJyYXl8c3RyaW5nfG51bWJlcn0gRGVzZXJpYWxpemVkIEpTT04gc3RyaW5nLg0KICovDQpmdW5jdGlvbiBmcm9tSnNvbihqc29uKSB7DQogIHJldHVybiBpc1N0cmluZyhqc29uKQ0KICAgICAgPyBKU09OLnBhcnNlKGpzb24pDQogICAgICA6IGpzb247DQp9DQoNCg0KLyoqDQogKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGVsZW1lbnQuDQogKi8NCmZ1bmN0aW9uIHN0YXJ0aW5nVGFnKGVsZW1lbnQpIHsNCiAgZWxlbWVudCA9IGpxTGl0ZShlbGVtZW50KS5jbG9uZSgpOw0KICB0cnkgew0KICAgIC8vIHR1cm5zIG91dCBJRSBkb2VzIG5vdCBsZXQgeW91IHNldCAuaHRtbCgpIG9uIGVsZW1lbnRzIHdoaWNoDQogICAgLy8gYXJlIG5vdCBhbGxvd2VkIHRvIGhhdmUgY2hpbGRyZW4uIFNvIHdlIGp1c3QgaWdub3JlIGl0Lg0KICAgIGVsZW1lbnQuZW1wdHkoKTsNCiAgfSBjYXRjaCAoZSkge30NCiAgdmFyIGVsZW1IdG1sID0ganFMaXRlKCc8ZGl2PicpLmFwcGVuZChlbGVtZW50KS5odG1sKCk7DQogIHRyeSB7DQogICAgcmV0dXJuIGVsZW1lbnRbMF0ubm9kZVR5cGUgPT09IE5PREVfVFlQRV9URVhUID8gbG93ZXJjYXNlKGVsZW1IdG1sKSA6DQogICAgICAgIGVsZW1IdG1sLg0KICAgICAgICAgIG1hdGNoKC9eKDxbXj5dKz4pLylbMV0uDQogICAgICAgICAgcmVwbGFjZSgvXjwoW1x3XC1dKykvLCBmdW5jdGlvbihtYXRjaCwgbm9kZU5hbWUpIHsgcmV0dXJuICc8JyArIGxvd2VyY2FzZShub2RlTmFtZSk7IH0pOw0KICB9IGNhdGNoIChlKSB7DQogICAgcmV0dXJuIGxvd2VyY2FzZShlbGVtSHRtbCk7DQogIH0NCg0KfQ0KDQoNCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCg0KLyoqDQogKiBUcmllcyB0byBkZWNvZGUgdGhlIFVSSSBjb21wb25lbnQgd2l0aG91dCB0aHJvd2luZyBhbiBleGNlcHRpb24uDQogKg0KICogQHByaXZhdGUNCiAqIEBwYXJhbSBzdHIgdmFsdWUgcG90ZW50aWFsIFVSSSBjb21wb25lbnQgdG8gY2hlY2suDQogKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBgdmFsdWVgIGNhbiBiZSBkZWNvZGVkDQogKiB3aXRoIHRoZSBkZWNvZGVVUklDb21wb25lbnQgZnVuY3Rpb24uDQogKi8NCmZ1bmN0aW9uIHRyeURlY29kZVVSSUNvbXBvbmVudCh2YWx1ZSkgew0KICB0cnkgew0KICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpOw0KICB9IGNhdGNoIChlKSB7DQogICAgLy8gSWdub3JlIGFueSBpbnZhbGlkIHVyaSBjb21wb25lbnQNCiAgfQ0KfQ0KDQoNCi8qKg0KICogUGFyc2VzIGFuIGVzY2FwZWQgdXJsIHF1ZXJ5IHN0cmluZyBpbnRvIGtleS12YWx1ZSBwYWlycy4NCiAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZyxib29sZWFufEFycmF5Pn0NCiAqLw0KZnVuY3Rpb24gcGFyc2VLZXlWYWx1ZSgvKipzdHJpbmcqL2tleVZhbHVlKSB7DQogIHZhciBvYmogPSB7fSwga2V5X3ZhbHVlLCBrZXk7DQogIGZvckVhY2goKGtleVZhbHVlIHx8ICIiKS5zcGxpdCgnJicpLCBmdW5jdGlvbihrZXlWYWx1ZSkgew0KICAgIGlmIChrZXlWYWx1ZSkgew0KICAgICAga2V5X3ZhbHVlID0ga2V5VmFsdWUucmVwbGFjZSgvXCsvZywnJTIwJykuc3BsaXQoJz0nKTsNCiAgICAgIGtleSA9IHRyeURlY29kZVVSSUNvbXBvbmVudChrZXlfdmFsdWVbMF0pOw0KICAgICAgaWYgKGlzRGVmaW5lZChrZXkpKSB7DQogICAgICAgIHZhciB2YWwgPSBpc0RlZmluZWQoa2V5X3ZhbHVlWzFdKSA/IHRyeURlY29kZVVSSUNvbXBvbmVudChrZXlfdmFsdWVbMV0pIDogdHJ1ZTsNCiAgICAgICAgaWYgKCFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KSkgew0KICAgICAgICAgIG9ialtrZXldID0gdmFsOw0KICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkob2JqW2tleV0pKSB7DQogICAgICAgICAgb2JqW2tleV0ucHVzaCh2YWwpOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIG9ialtrZXldID0gW29ialtrZXldLHZhbF07DQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQogIH0pOw0KICByZXR1cm4gb2JqOw0KfQ0KDQpmdW5jdGlvbiB0b0tleVZhbHVlKG9iaikgew0KICB2YXIgcGFydHMgPSBbXTsNCiAgZm9yRWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHsNCiAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHsNCiAgICAgIGZvckVhY2godmFsdWUsIGZ1bmN0aW9uKGFycmF5VmFsdWUpIHsNCiAgICAgICAgcGFydHMucHVzaChlbmNvZGVVcmlRdWVyeShrZXksIHRydWUpICsNCiAgICAgICAgICAgICAgICAgICAoYXJyYXlWYWx1ZSA9PT0gdHJ1ZSA/ICcnIDogJz0nICsgZW5jb2RlVXJpUXVlcnkoYXJyYXlWYWx1ZSwgdHJ1ZSkpKTsNCiAgICAgIH0pOw0KICAgIH0gZWxzZSB7DQogICAgcGFydHMucHVzaChlbmNvZGVVcmlRdWVyeShrZXksIHRydWUpICsNCiAgICAgICAgICAgICAgICh2YWx1ZSA9PT0gdHJ1ZSA/ICcnIDogJz0nICsgZW5jb2RlVXJpUXVlcnkodmFsdWUsIHRydWUpKSk7DQogICAgfQ0KICB9KTsNCiAgcmV0dXJuIHBhcnRzLmxlbmd0aCA/IHBhcnRzLmpvaW4oJyYnKSA6ICcnOw0KfQ0KDQoNCi8qKg0KICogV2UgbmVlZCBvdXIgY3VzdG9tIG1ldGhvZCBiZWNhdXNlIGVuY29kZVVSSUNvbXBvbmVudCBpcyB0b28gYWdncmVzc2l2ZSBhbmQgZG9lc24ndCBmb2xsb3cNCiAqIGh0dHA6Ly93d3cuaWV0Zi5vcmcvcmZjL3JmYzM5ODYudHh0IHdpdGggcmVnYXJkcyB0byB0aGUgY2hhcmFjdGVyIHNldCAocGNoYXIpIGFsbG93ZWQgaW4gcGF0aA0KICogc2VnbWVudHM6DQogKiAgICBzZWdtZW50ICAgICAgID0gKnBjaGFyDQogKiAgICBwY2hhciAgICAgICAgID0gdW5yZXNlcnZlZCAvIHBjdC1lbmNvZGVkIC8gc3ViLWRlbGltcyAvICI6IiAvICJAIg0KICogICAgcGN0LWVuY29kZWQgICA9ICIlIiBIRVhESUcgSEVYRElHDQogKiAgICB1bnJlc2VydmVkICAgID0gQUxQSEEgLyBESUdJVCAvICItIiAvICIuIiAvICJfIiAvICJ+Ig0KICogICAgc3ViLWRlbGltcyAgICA9ICIhIiAvICIkIiAvICImIiAvICInIiAvICIoIiAvICIpIg0KICogICAgICAgICAgICAgICAgICAgICAvICIqIiAvICIrIiAvICIsIiAvICI7IiAvICI9Ig0KICovDQpmdW5jdGlvbiBlbmNvZGVVcmlTZWdtZW50KHZhbCkgew0KICByZXR1cm4gZW5jb2RlVXJpUXVlcnkodmFsLCB0cnVlKS4NCiAgICAgICAgICAgICByZXBsYWNlKC8lMjYvZ2ksICcmJykuDQogICAgICAgICAgICAgcmVwbGFjZSgvJTNEL2dpLCAnPScpLg0KICAgICAgICAgICAgIHJlcGxhY2UoLyUyQi9naSwgJysnKTsNCn0NCg0KDQovKioNCiAqIFRoaXMgbWV0aG9kIGlzIGludGVuZGVkIGZvciBlbmNvZGluZyAqa2V5KiBvciAqdmFsdWUqIHBhcnRzIG9mIHF1ZXJ5IGNvbXBvbmVudC4gV2UgbmVlZCBhIGN1c3RvbQ0KICogbWV0aG9kIGJlY2F1c2UgZW5jb2RlVVJJQ29tcG9uZW50IGlzIHRvbyBhZ2dyZXNzaXZlIGFuZCBlbmNvZGVzIHN0dWZmIHRoYXQgZG9lc24ndCBoYXZlIHRvIGJlDQogKiBlbmNvZGVkIHBlciBodHRwOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmMzOTg2Og0KICogICAgcXVlcnkgICAgICAgPSAqKCBwY2hhciAvICIvIiAvICI/IiApDQogKiAgICBwY2hhciAgICAgICAgID0gdW5yZXNlcnZlZCAvIHBjdC1lbmNvZGVkIC8gc3ViLWRlbGltcyAvICI6IiAvICJAIg0KICogICAgdW5yZXNlcnZlZCAgICA9IEFMUEhBIC8gRElHSVQgLyAiLSIgLyAiLiIgLyAiXyIgLyAifiINCiAqICAgIHBjdC1lbmNvZGVkICAgPSAiJSIgSEVYRElHIEhFWERJRw0KICogICAgc3ViLWRlbGltcyAgICA9ICIhIiAvICIkIiAvICImIiAvICInIiAvICIoIiAvICIpIg0KICogICAgICAgICAgICAgICAgICAgICAvICIqIiAvICIrIiAvICIsIiAvICI7IiAvICI9Ig0KICovDQpmdW5jdGlvbiBlbmNvZGVVcmlRdWVyeSh2YWwsIHBjdEVuY29kZVNwYWNlcykgew0KICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KHZhbCkuDQogICAgICAgICAgICAgcmVwbGFjZSgvJTQwL2dpLCAnQCcpLg0KICAgICAgICAgICAgIHJlcGxhY2UoLyUzQS9naSwgJzonKS4NCiAgICAgICAgICAgICByZXBsYWNlKC8lMjQvZywgJyQnKS4NCiAgICAgICAgICAgICByZXBsYWNlKC8lMkMvZ2ksICcsJykuDQogICAgICAgICAgICAgcmVwbGFjZSgvJTNCL2dpLCAnOycpLg0KICAgICAgICAgICAgIHJlcGxhY2UoLyUyMC9nLCAocGN0RW5jb2RlU3BhY2VzID8gJyUyMCcgOiAnKycpKTsNCn0NCg0KdmFyIG5nQXR0clByZWZpeGVzID0gWyduZy0nLCAnZGF0YS1uZy0nLCAnbmc6JywgJ3gtbmctJ107DQoNCmZ1bmN0aW9uIGdldE5nQXR0cmlidXRlKGVsZW1lbnQsIG5nQXR0cikgew0KICB2YXIgYXR0ciwgaSwgaWkgPSBuZ0F0dHJQcmVmaXhlcy5sZW5ndGg7DQogIGVsZW1lbnQgPSBqcUxpdGUoZWxlbWVudCk7DQogIGZvciAoaSA9IDA7IGkgPCBpaTsgKytpKSB7DQogICAgYXR0ciA9IG5nQXR0clByZWZpeGVzW2ldICsgbmdBdHRyOw0KICAgIGlmIChpc1N0cmluZyhhdHRyID0gZWxlbWVudC5hdHRyKGF0dHIpKSkgew0KICAgICAgcmV0dXJuIGF0dHI7DQogICAgfQ0KICB9DQogIHJldHVybiBudWxsOw0KfQ0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nQXBwDQogKiBAbW9kdWxlIG5nDQogKg0KICogQGVsZW1lbnQgQU5ZDQogKiBAcGFyYW0ge2FuZ3VsYXIuTW9kdWxlfSBuZ0FwcCBhbiBvcHRpb25hbCBhcHBsaWNhdGlvbg0KICogICB7QGxpbmsgYW5ndWxhci5tb2R1bGUgbW9kdWxlfSBuYW1lIHRvIGxvYWQuDQogKiBAcGFyYW0ge2Jvb2xlYW49fSBuZ1N0cmljdERpIGlmIHRoaXMgYXR0cmlidXRlIGlzIHByZXNlbnQgb24gdGhlIGFwcCBlbGVtZW50LCB0aGUgaW5qZWN0b3Igd2lsbCBiZQ0KICogICBjcmVhdGVkIGluICJzdHJpY3QtZGkiIG1vZGUuIFRoaXMgbWVhbnMgdGhhdCB0aGUgYXBwbGljYXRpb24gd2lsbCBmYWlsIHRvIGludm9rZSBmdW5jdGlvbnMgd2hpY2gNCiAqICAgZG8gbm90IHVzZSBleHBsaWNpdCBmdW5jdGlvbiBhbm5vdGF0aW9uIChhbmQgYXJlIHRodXMgdW5zdWl0YWJsZSBmb3IgbWluaWZpY2F0aW9uKSwgYXMgZGVzY3JpYmVkDQogKiAgIGluIHtAbGluayBndWlkZS9kaSB0aGUgRGVwZW5kZW5jeSBJbmplY3Rpb24gZ3VpZGV9LCBhbmQgdXNlZnVsIGRlYnVnZ2luZyBpbmZvIHdpbGwgYXNzaXN0IGluDQogKiAgIHRyYWNraW5nIGRvd24gdGhlIHJvb3Qgb2YgdGhlc2UgYnVncy4NCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqDQogKiBVc2UgdGhpcyBkaXJlY3RpdmUgdG8gKiphdXRvLWJvb3RzdHJhcCoqIGFuIEFuZ3VsYXJKUyBhcHBsaWNhdGlvbi4gVGhlIGBuZ0FwcGAgZGlyZWN0aXZlDQogKiBkZXNpZ25hdGVzIHRoZSAqKnJvb3QgZWxlbWVudCoqIG9mIHRoZSBhcHBsaWNhdGlvbiBhbmQgaXMgdHlwaWNhbGx5IHBsYWNlZCBuZWFyIHRoZSByb290IGVsZW1lbnQNCiAqIG9mIHRoZSBwYWdlIC0gZS5nLiBvbiB0aGUgYDxib2R5PmAgb3IgYDxodG1sPmAgdGFncy4NCiAqDQogKiBPbmx5IG9uZSBBbmd1bGFySlMgYXBwbGljYXRpb24gY2FuIGJlIGF1dG8tYm9vdHN0cmFwcGVkIHBlciBIVE1MIGRvY3VtZW50LiBUaGUgZmlyc3QgYG5nQXBwYA0KICogZm91bmQgaW4gdGhlIGRvY3VtZW50IHdpbGwgYmUgdXNlZCB0byBkZWZpbmUgdGhlIHJvb3QgZWxlbWVudCB0byBhdXRvLWJvb3RzdHJhcCBhcyBhbg0KICogYXBwbGljYXRpb24uIFRvIHJ1biBtdWx0aXBsZSBhcHBsaWNhdGlvbnMgaW4gYW4gSFRNTCBkb2N1bWVudCB5b3UgbXVzdCBtYW51YWxseSBib290c3RyYXAgdGhlbSB1c2luZw0KICoge0BsaW5rIGFuZ3VsYXIuYm9vdHN0cmFwfSBpbnN0ZWFkLiBBbmd1bGFySlMgYXBwbGljYXRpb25zIGNhbm5vdCBiZSBuZXN0ZWQgd2l0aGluIGVhY2ggb3RoZXIuDQogKg0KICogWW91IGNhbiBzcGVjaWZ5IGFuICoqQW5ndWxhckpTIG1vZHVsZSoqIHRvIGJlIHVzZWQgYXMgdGhlIHJvb3QgbW9kdWxlIGZvciB0aGUgYXBwbGljYXRpb24uICBUaGlzDQogKiBtb2R1bGUgd2lsbCBiZSBsb2FkZWQgaW50byB0aGUge0BsaW5rIGF1dG8uJGluamVjdG9yfSB3aGVuIHRoZSBhcHBsaWNhdGlvbiBpcyBib290c3RyYXBwZWQuIEl0DQogKiBzaG91bGQgY29udGFpbiB0aGUgYXBwbGljYXRpb24gY29kZSBuZWVkZWQgb3IgaGF2ZSBkZXBlbmRlbmNpZXMgb24gb3RoZXIgbW9kdWxlcyB0aGF0IHdpbGwNCiAqIGNvbnRhaW4gdGhlIGNvZGUuIFNlZSB7QGxpbmsgYW5ndWxhci5tb2R1bGV9IGZvciBtb3JlIGluZm9ybWF0aW9uLg0KICoNCiAqIEluIHRoZSBleGFtcGxlIGJlbG93IGlmIHRoZSBgbmdBcHBgIGRpcmVjdGl2ZSB3ZXJlIG5vdCBwbGFjZWQgb24gdGhlIGBodG1sYCBlbGVtZW50IHRoZW4gdGhlDQogKiBkb2N1bWVudCB3b3VsZCBub3QgYmUgY29tcGlsZWQsIHRoZSBgQXBwQ29udHJvbGxlcmAgd291bGQgbm90IGJlIGluc3RhbnRpYXRlZCBhbmQgdGhlIGB7eyBhK2IgfX1gDQogKiB3b3VsZCBub3QgYmUgcmVzb2x2ZWQgdG8gYDNgLg0KICoNCiAqIGBuZ0FwcGAgaXMgdGhlIGVhc2llc3QsIGFuZCBtb3N0IGNvbW1vbiB3YXkgdG8gYm9vdHN0cmFwIGFuIGFwcGxpY2F0aW9uLg0KICoNCiA8ZXhhbXBsZSBtb2R1bGU9Im5nQXBwRGVtbyI+DQogICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgIDxkaXYgbmctY29udHJvbGxlcj0ibmdBcHBEZW1vQ29udHJvbGxlciI+DQogICAgIEkgY2FuIGFkZDoge3thfX0gKyB7e2J9fSA9ICB7eyBhK2IgfX0NCiAgIDwvZGl2Pg0KICAgPC9maWxlPg0KICAgPGZpbGUgbmFtZT0ic2NyaXB0LmpzIj4NCiAgIGFuZ3VsYXIubW9kdWxlKCduZ0FwcERlbW8nLCBbXSkuY29udHJvbGxlcignbmdBcHBEZW1vQ29udHJvbGxlcicsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAkc2NvcGUuYSA9IDE7DQogICAgICRzY29wZS5iID0gMjsNCiAgIH0pOw0KICAgPC9maWxlPg0KIDwvZXhhbXBsZT4NCiAqDQogKiBVc2luZyBgbmdTdHJpY3REaWAsIHlvdSB3b3VsZCBzZWUgc29tZXRoaW5nIGxpa2UgdGhpczoNCiAqDQogPGV4YW1wbGUgbmctYXBwLWluY2x1ZGVkPSJ0cnVlIj4NCiAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgPGRpdiBuZy1hcHA9Im5nQXBwU3RyaWN0RGVtbyIgbmctc3RyaWN0LWRpPg0KICAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iR29vZENvbnRyb2xsZXIxIj4NCiAgICAgICAgICAgSSBjYW4gYWRkOiB7e2F9fSArIHt7Yn19ID0gIHt7IGErYiB9fQ0KDQogICAgICAgICAgIDxwPlRoaXMgcmVuZGVycyBiZWNhdXNlIHRoZSBjb250cm9sbGVyIGRvZXMgbm90IGZhaWwgdG8NCiAgICAgICAgICAgICAgaW5zdGFudGlhdGUsIGJ5IHVzaW5nIGV4cGxpY2l0IGFubm90YXRpb24gc3R5bGUgKHNlZQ0KICAgICAgICAgICAgICBzY3JpcHQuanMgZm9yIGRldGFpbHMpDQogICAgICAgICAgIDwvcD4NCiAgICAgICA8L2Rpdj4NCg0KICAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iR29vZENvbnRyb2xsZXIyIj4NCiAgICAgICAgICAgTmFtZTogPGlucHV0IG5nLW1vZGVsPSJuYW1lIj48YnIgLz4NCiAgICAgICAgICAgSGVsbG8sIHt7bmFtZX19IQ0KDQogICAgICAgICAgIDxwPlRoaXMgcmVuZGVycyBiZWNhdXNlIHRoZSBjb250cm9sbGVyIGRvZXMgbm90IGZhaWwgdG8NCiAgICAgICAgICAgICAgaW5zdGFudGlhdGUsIGJ5IHVzaW5nIGV4cGxpY2l0IGFubm90YXRpb24gc3R5bGUNCiAgICAgICAgICAgICAgKHNlZSBzY3JpcHQuanMgZm9yIGRldGFpbHMpDQogICAgICAgICAgIDwvcD4NCiAgICAgICA8L2Rpdj4NCg0KICAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iQmFkQ29udHJvbGxlciI+DQogICAgICAgICAgIEkgY2FuIGFkZDoge3thfX0gKyB7e2J9fSA9ICB7eyBhK2IgfX0NCg0KICAgICAgICAgICA8cD5UaGUgY29udHJvbGxlciBjb3VsZCBub3QgYmUgaW5zdGFudGlhdGVkLCBkdWUgdG8gcmVseWluZw0KICAgICAgICAgICAgICBvbiBhdXRvbWF0aWMgZnVuY3Rpb24gYW5ub3RhdGlvbnMgKHdoaWNoIGFyZSBkaXNhYmxlZCBpbg0KICAgICAgICAgICAgICBzdHJpY3QgbW9kZSkuIEFzIHN1Y2gsIHRoZSBjb250ZW50IG9mIHRoaXMgc2VjdGlvbiBpcyBub3QNCiAgICAgICAgICAgICAgaW50ZXJwb2xhdGVkLCBhbmQgdGhlcmUgc2hvdWxkIGJlIGFuIGVycm9yIGluIHlvdXIgd2ViIGNvbnNvbGUuDQogICAgICAgICAgIDwvcD4NCiAgICAgICA8L2Rpdj4NCiAgIDwvZGl2Pg0KICAgPC9maWxlPg0KICAgPGZpbGUgbmFtZT0ic2NyaXB0LmpzIj4NCiAgIGFuZ3VsYXIubW9kdWxlKCduZ0FwcFN0cmljdERlbW8nLCBbXSkNCiAgICAgLy8gQmFkQ29udHJvbGxlciB3aWxsIGZhaWwgdG8gaW5zdGFudGlhdGUsIGR1ZSB0byByZWx5aW5nIG9uIGF1dG9tYXRpYyBmdW5jdGlvbiBhbm5vdGF0aW9uLA0KICAgICAvLyByYXRoZXIgdGhhbiBhbiBleHBsaWNpdCBhbm5vdGF0aW9uDQogICAgIC5jb250cm9sbGVyKCdCYWRDb250cm9sbGVyJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgJHNjb3BlLmEgPSAxOw0KICAgICAgICRzY29wZS5iID0gMjsNCiAgICAgfSkNCiAgICAgLy8gVW5saWtlIEJhZENvbnRyb2xsZXIsIEdvb2RDb250cm9sbGVyMSBhbmQgR29vZENvbnRyb2xsZXIyIHdpbGwgbm90IGZhaWwgdG8gYmUgaW5zdGFudGlhdGVkLA0KICAgICAvLyBkdWUgdG8gdXNpbmcgZXhwbGljaXQgYW5ub3RhdGlvbnMgdXNpbmcgdGhlIGFycmF5IHN0eWxlIGFuZCAkaW5qZWN0IHByb3BlcnR5LCByZXNwZWN0aXZlbHkuDQogICAgIC5jb250cm9sbGVyKCdHb29kQ29udHJvbGxlcjEnLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICRzY29wZS5hID0gMTsNCiAgICAgICAkc2NvcGUuYiA9IDI7DQogICAgIH1dKQ0KICAgICAuY29udHJvbGxlcignR29vZENvbnRyb2xsZXIyJywgR29vZENvbnRyb2xsZXIyKTsNCiAgICAgZnVuY3Rpb24gR29vZENvbnRyb2xsZXIyKCRzY29wZSkgew0KICAgICAgICRzY29wZS5uYW1lID0gIldvcmxkIjsNCiAgICAgfQ0KICAgICBHb29kQ29udHJvbGxlcjIuJGluamVjdCA9IFsnJHNjb3BlJ107DQogICA8L2ZpbGU+DQogICA8ZmlsZSBuYW1lPSJzdHlsZS5jc3MiPg0KICAgZGl2W25nLWNvbnRyb2xsZXJdIHsNCiAgICAgICBtYXJnaW4tYm90dG9tOiAxZW07DQogICAgICAgLXdlYmtpdC1ib3JkZXItcmFkaXVzOiA0cHg7DQogICAgICAgYm9yZGVyLXJhZGl1czogNHB4Ow0KICAgICAgIGJvcmRlcjogMXB4IHNvbGlkOw0KICAgICAgIHBhZGRpbmc6IC41ZW07DQogICB9DQogICBkaXZbbmctY29udHJvbGxlcl49R29vZF0gew0KICAgICAgIGJvcmRlci1jb2xvcjogI2Q2ZTljNjsNCiAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGZmMGQ4Ow0KICAgICAgIGNvbG9yOiAjM2M3NjNkOw0KICAgfQ0KICAgZGl2W25nLWNvbnRyb2xsZXJePUJhZF0gew0KICAgICAgIGJvcmRlci1jb2xvcjogI2ViY2NkMTsNCiAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjJkZWRlOw0KICAgICAgIGNvbG9yOiAjYTk0NDQyOw0KICAgICAgIG1hcmdpbi1ib3R0b206IDA7DQogICB9DQogICA8L2ZpbGU+DQogPC9leGFtcGxlPg0KICovDQpmdW5jdGlvbiBhbmd1bGFySW5pdChlbGVtZW50LCBib290c3RyYXApIHsNCiAgdmFyIGFwcEVsZW1lbnQsDQogICAgICBtb2R1bGUsDQogICAgICBjb25maWcgPSB7fTsNCg0KICAvLyBUaGUgZWxlbWVudCBgZWxlbWVudGAgaGFzIHByaW9yaXR5IG92ZXIgYW55IG90aGVyIGVsZW1lbnQNCiAgZm9yRWFjaChuZ0F0dHJQcmVmaXhlcywgZnVuY3Rpb24ocHJlZml4KSB7DQogICAgdmFyIG5hbWUgPSBwcmVmaXggKyAnYXBwJzsNCg0KICAgIGlmICghYXBwRWxlbWVudCAmJiBlbGVtZW50Lmhhc0F0dHJpYnV0ZSAmJiBlbGVtZW50Lmhhc0F0dHJpYnV0ZShuYW1lKSkgew0KICAgICAgYXBwRWxlbWVudCA9IGVsZW1lbnQ7DQogICAgICBtb2R1bGUgPSBlbGVtZW50LmdldEF0dHJpYnV0ZShuYW1lKTsNCiAgICB9DQogIH0pOw0KICBmb3JFYWNoKG5nQXR0clByZWZpeGVzLCBmdW5jdGlvbihwcmVmaXgpIHsNCiAgICB2YXIgbmFtZSA9IHByZWZpeCArICdhcHAnOw0KICAgIHZhciBjYW5kaWRhdGU7DQoNCiAgICBpZiAoIWFwcEVsZW1lbnQgJiYgKGNhbmRpZGF0ZSA9IGVsZW1lbnQucXVlcnlTZWxlY3RvcignWycgKyBuYW1lLnJlcGxhY2UoJzonLCAnXFw6JykgKyAnXScpKSkgew0KICAgICAgYXBwRWxlbWVudCA9IGNhbmRpZGF0ZTsNCiAgICAgIG1vZHVsZSA9IGNhbmRpZGF0ZS5nZXRBdHRyaWJ1dGUobmFtZSk7DQogICAgfQ0KICB9KTsNCiAgaWYgKGFwcEVsZW1lbnQpIHsNCiAgICBjb25maWcuc3RyaWN0RGkgPSBnZXROZ0F0dHJpYnV0ZShhcHBFbGVtZW50LCAic3RyaWN0LWRpIikgIT09IG51bGw7DQogICAgYm9vdHN0cmFwKGFwcEVsZW1lbnQsIG1vZHVsZSA/IFttb2R1bGVdIDogW10sIGNvbmZpZyk7DQogIH0NCn0NCg0KLyoqDQogKiBAbmdkb2MgZnVuY3Rpb24NCiAqIEBuYW1lIGFuZ3VsYXIuYm9vdHN0cmFwDQogKiBAbW9kdWxlIG5nDQogKiBAZGVzY3JpcHRpb24NCiAqIFVzZSB0aGlzIGZ1bmN0aW9uIHRvIG1hbnVhbGx5IHN0YXJ0IHVwIGFuZ3VsYXIgYXBwbGljYXRpb24uDQogKg0KICogU2VlOiB7QGxpbmsgZ3VpZGUvYm9vdHN0cmFwIEJvb3RzdHJhcH0NCiAqDQogKiBOb3RlIHRoYXQgUHJvdHJhY3RvciBiYXNlZCBlbmQtdG8tZW5kIHRlc3RzIGNhbm5vdCB1c2UgdGhpcyBmdW5jdGlvbiB0byBib290c3RyYXAgbWFudWFsbHkuDQogKiBUaGV5IG11c3QgdXNlIHtAbGluayBuZy5kaXJlY3RpdmU6bmdBcHAgbmdBcHB9Lg0KICoNCiAqIEFuZ3VsYXIgd2lsbCBkZXRlY3QgaWYgaXQgaGFzIGJlZW4gbG9hZGVkIGludG8gdGhlIGJyb3dzZXIgbW9yZSB0aGFuIG9uY2UgYW5kIG9ubHkgYWxsb3cgdGhlDQogKiBmaXJzdCBsb2FkZWQgc2NyaXB0IHRvIGJlIGJvb3RzdHJhcHBlZCBhbmQgd2lsbCByZXBvcnQgYSB3YXJuaW5nIHRvIHRoZSBicm93c2VyIGNvbnNvbGUgZm9yDQogKiBlYWNoIG9mIHRoZSBzdWJzZXF1ZW50IHNjcmlwdHMuIFRoaXMgcHJldmVudHMgc3RyYW5nZSByZXN1bHRzIGluIGFwcGxpY2F0aW9ucywgd2hlcmUgb3RoZXJ3aXNlDQogKiBtdWx0aXBsZSBpbnN0YW5jZXMgb2YgQW5ndWxhciB0cnkgdG8gd29yayBvbiB0aGUgRE9NLg0KICoNCiAqIGBgYGh0bWwNCiAqIDwhZG9jdHlwZSBodG1sPg0KICogPGh0bWw+DQogKiA8Ym9keT4NCiAqIDxkaXYgbmctY29udHJvbGxlcj0iV2VsY29tZUNvbnRyb2xsZXIiPg0KICogICB7e2dyZWV0aW5nfX0NCiAqIDwvZGl2Pg0KICoNCiAqIDxzY3JpcHQgc3JjPSJhbmd1bGFyLmpzIj48L3NjcmlwdD4NCiAqIDxzY3JpcHQ+DQogKiAgIHZhciBhcHAgPSBhbmd1bGFyLm1vZHVsZSgnZGVtbycsIFtdKQ0KICogICAuY29udHJvbGxlcignV2VsY29tZUNvbnRyb2xsZXInLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAqICAgICAgICRzY29wZS5ncmVldGluZyA9ICdXZWxjb21lISc7DQogKiAgIH0pOw0KICogICBhbmd1bGFyLmJvb3RzdHJhcChkb2N1bWVudCwgWydkZW1vJ10pOw0KICogPC9zY3JpcHQ+DQogKiA8L2JvZHk+DQogKiA8L2h0bWw+DQogKiBgYGANCiAqDQogKiBAcGFyYW0ge0RPTUVsZW1lbnR9IGVsZW1lbnQgRE9NIGVsZW1lbnQgd2hpY2ggaXMgdGhlIHJvb3Qgb2YgYW5ndWxhciBhcHBsaWNhdGlvbi4NCiAqIEBwYXJhbSB7QXJyYXk8U3RyaW5nfEZ1bmN0aW9ufEFycmF5Pj19IG1vZHVsZXMgYW4gYXJyYXkgb2YgbW9kdWxlcyB0byBsb2FkIGludG8gdGhlIGFwcGxpY2F0aW9uLg0KICogICAgIEVhY2ggaXRlbSBpbiB0aGUgYXJyYXkgc2hvdWxkIGJlIHRoZSBuYW1lIG9mIGEgcHJlZGVmaW5lZCBtb2R1bGUgb3IgYSAoREkgYW5ub3RhdGVkKQ0KICogICAgIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBpbnZva2VkIGJ5IHRoZSBpbmplY3RvciBhcyBhIHJ1biBibG9jay4NCiAqICAgICBTZWU6IHtAbGluayBhbmd1bGFyLm1vZHVsZSBtb2R1bGVzfQ0KICogQHBhcmFtIHtPYmplY3Q9fSBjb25maWcgYW4gb2JqZWN0IGZvciBkZWZpbmluZyBjb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIHRoZSBhcHBsaWNhdGlvbi4gVGhlDQogKiAgICAgZm9sbG93aW5nIGtleXMgYXJlIHN1cHBvcnRlZDoNCiAqDQogKiAqIGBzdHJpY3REaWAgLSBkaXNhYmxlIGF1dG9tYXRpYyBmdW5jdGlvbiBhbm5vdGF0aW9uIGZvciB0aGUgYXBwbGljYXRpb24uIFRoaXMgaXMgbWVhbnQgdG8NCiAqICAgYXNzaXN0IGluIGZpbmRpbmcgYnVncyB3aGljaCBicmVhayBtaW5pZmllZCBjb2RlLiBEZWZhdWx0cyB0byBgZmFsc2VgLg0KICoNCiAqIEByZXR1cm5zIHthdXRvLiRpbmplY3Rvcn0gUmV0dXJucyB0aGUgbmV3bHkgY3JlYXRlZCBpbmplY3RvciBmb3IgdGhpcyBhcHAuDQogKi8NCmZ1bmN0aW9uIGJvb3RzdHJhcChlbGVtZW50LCBtb2R1bGVzLCBjb25maWcpIHsNCiAgaWYgKCFpc09iamVjdChjb25maWcpKSBjb25maWcgPSB7fTsNCiAgdmFyIGRlZmF1bHRDb25maWcgPSB7DQogICAgc3RyaWN0RGk6IGZhbHNlDQogIH07DQogIGNvbmZpZyA9IGV4dGVuZChkZWZhdWx0Q29uZmlnLCBjb25maWcpOw0KICB2YXIgZG9Cb290c3RyYXAgPSBmdW5jdGlvbigpIHsNCiAgICBlbGVtZW50ID0ganFMaXRlKGVsZW1lbnQpOw0KDQogICAgaWYgKGVsZW1lbnQuaW5qZWN0b3IoKSkgew0KICAgICAgdmFyIHRhZyA9IChlbGVtZW50WzBdID09PSBkb2N1bWVudCkgPyAnZG9jdW1lbnQnIDogc3RhcnRpbmdUYWcoZWxlbWVudCk7DQogICAgICAvL0VuY29kZSBhbmdsZSBicmFja2V0cyB0byBwcmV2ZW50IGlucHV0IGZyb20gYmVpbmcgc2FuaXRpemVkIHRvIGVtcHR5IHN0cmluZyAjODY4Mw0KICAgICAgdGhyb3cgbmdNaW5FcnIoDQogICAgICAgICAgJ2J0c3RycGQnLA0KICAgICAgICAgICJBcHAgQWxyZWFkeSBCb290c3RyYXBwZWQgd2l0aCB0aGlzIEVsZW1lbnQgJ3swfSciLA0KICAgICAgICAgIHRhZy5yZXBsYWNlKC88LywnJmx0OycpLnJlcGxhY2UoLz4vLCcmZ3Q7JykpOw0KICAgIH0NCg0KICAgIG1vZHVsZXMgPSBtb2R1bGVzIHx8IFtdOw0KICAgIG1vZHVsZXMudW5zaGlmdChbJyRwcm92aWRlJywgZnVuY3Rpb24oJHByb3ZpZGUpIHsNCiAgICAgICRwcm92aWRlLnZhbHVlKCckcm9vdEVsZW1lbnQnLCBlbGVtZW50KTsNCiAgICB9XSk7DQoNCiAgICBpZiAoY29uZmlnLmRlYnVnSW5mb0VuYWJsZWQpIHsNCiAgICAgIC8vIFB1c2hpbmcgc28gdGhhdCB0aGlzIG92ZXJyaWRlcyBgZGVidWdJbmZvRW5hYmxlZGAgc2V0dGluZyBkZWZpbmVkIGluIHVzZXIncyBgbW9kdWxlc2AuDQogICAgICBtb2R1bGVzLnB1c2goWyckY29tcGlsZVByb3ZpZGVyJywgZnVuY3Rpb24oJGNvbXBpbGVQcm92aWRlcikgew0KICAgICAgICAkY29tcGlsZVByb3ZpZGVyLmRlYnVnSW5mb0VuYWJsZWQodHJ1ZSk7DQogICAgICB9XSk7DQogICAgfQ0KDQogICAgbW9kdWxlcy51bnNoaWZ0KCduZycpOw0KICAgIHZhciBpbmplY3RvciA9IGNyZWF0ZUluamVjdG9yKG1vZHVsZXMsIGNvbmZpZy5zdHJpY3REaSk7DQogICAgaW5qZWN0b3IuaW52b2tlKFsnJHJvb3RTY29wZScsICckcm9vdEVsZW1lbnQnLCAnJGNvbXBpbGUnLCAnJGluamVjdG9yJywNCiAgICAgICBmdW5jdGlvbiBib290c3RyYXBBcHBseShzY29wZSwgZWxlbWVudCwgY29tcGlsZSwgaW5qZWN0b3IpIHsNCiAgICAgICAgc2NvcGUuJGFwcGx5KGZ1bmN0aW9uKCkgew0KICAgICAgICAgIGVsZW1lbnQuZGF0YSgnJGluamVjdG9yJywgaW5qZWN0b3IpOw0KICAgICAgICAgIGNvbXBpbGUoZWxlbWVudCkoc2NvcGUpOw0KICAgICAgICB9KTsNCiAgICAgIH1dDQogICAgKTsNCiAgICByZXR1cm4gaW5qZWN0b3I7DQogIH07DQoNCiAgdmFyIE5HX0VOQUJMRV9ERUJVR19JTkZPID0gL15OR19FTkFCTEVfREVCVUdfSU5GTyEvOw0KICB2YXIgTkdfREVGRVJfQk9PVFNUUkFQID0gL15OR19ERUZFUl9CT09UU1RSQVAhLzsNCg0KICBpZiAod2luZG93ICYmIE5HX0VOQUJMRV9ERUJVR19JTkZPLnRlc3Qod2luZG93Lm5hbWUpKSB7DQogICAgY29uZmlnLmRlYnVnSW5mb0VuYWJsZWQgPSB0cnVlOw0KICAgIHdpbmRvdy5uYW1lID0gd2luZG93Lm5hbWUucmVwbGFjZShOR19FTkFCTEVfREVCVUdfSU5GTywgJycpOw0KICB9DQoNCiAgaWYgKHdpbmRvdyAmJiAhTkdfREVGRVJfQk9PVFNUUkFQLnRlc3Qod2luZG93Lm5hbWUpKSB7DQogICAgcmV0dXJuIGRvQm9vdHN0cmFwKCk7DQogIH0NCg0KICB3aW5kb3cubmFtZSA9IHdpbmRvdy5uYW1lLnJlcGxhY2UoTkdfREVGRVJfQk9PVFNUUkFQLCAnJyk7DQogIGFuZ3VsYXIucmVzdW1lQm9vdHN0cmFwID0gZnVuY3Rpb24oZXh0cmFNb2R1bGVzKSB7DQogICAgZm9yRWFjaChleHRyYU1vZHVsZXMsIGZ1bmN0aW9uKG1vZHVsZSkgew0KICAgICAgbW9kdWxlcy5wdXNoKG1vZHVsZSk7DQogICAgfSk7DQogICAgZG9Cb290c3RyYXAoKTsNCiAgfTsNCn0NCg0KLyoqDQogKiBAbmdkb2MgZnVuY3Rpb24NCiAqIEBuYW1lIGFuZ3VsYXIucmVsb2FkV2l0aERlYnVnSW5mbw0KICogQG1vZHVsZSBuZw0KICogQGRlc2NyaXB0aW9uDQogKiBVc2UgdGhpcyBmdW5jdGlvbiB0byByZWxvYWQgdGhlIGN1cnJlbnQgYXBwbGljYXRpb24gd2l0aCBkZWJ1ZyBpbmZvcm1hdGlvbiB0dXJuZWQgb24uDQogKiBUaGlzIHRha2VzIHByZWNlZGVuY2Ugb3ZlciBhIGNhbGwgdG8gYCRjb21waWxlUHJvdmlkZXIuZGVidWdJbmZvRW5hYmxlZChmYWxzZSlgLg0KICoNCiAqIFNlZSB7QGxpbmsgbmcuJGNvbXBpbGVQcm92aWRlciNkZWJ1Z0luZm9FbmFibGVkfSBmb3IgbW9yZS4NCiAqLw0KZnVuY3Rpb24gcmVsb2FkV2l0aERlYnVnSW5mbygpIHsNCiAgd2luZG93Lm5hbWUgPSAnTkdfRU5BQkxFX0RFQlVHX0lORk8hJyArIHdpbmRvdy5uYW1lOw0KICB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7DQp9DQoNCi8qKg0KICogQG5hbWUgYW5ndWxhci5nZXRUZXN0YWJpbGl0eQ0KICogQG1vZHVsZSBuZw0KICogQGRlc2NyaXB0aW9uDQogKiBHZXQgdGhlIHRlc3RhYmlsaXR5IHNlcnZpY2UgZm9yIHRoZSBpbnN0YW5jZSBvZiBBbmd1bGFyIG9uIHRoZSBnaXZlbg0KICogZWxlbWVudC4NCiAqIEBwYXJhbSB7RE9NRWxlbWVudH0gZWxlbWVudCBET00gZWxlbWVudCB3aGljaCBpcyB0aGUgcm9vdCBvZiBhbmd1bGFyIGFwcGxpY2F0aW9uLg0KICovDQpmdW5jdGlvbiBnZXRUZXN0YWJpbGl0eShyb290RWxlbWVudCkgew0KICB2YXIgaW5qZWN0b3IgPSBhbmd1bGFyLmVsZW1lbnQocm9vdEVsZW1lbnQpLmluamVjdG9yKCk7DQogIGlmICghaW5qZWN0b3IpIHsNCiAgICB0aHJvdyBuZ01pbkVycigndGVzdCcsDQogICAgICAnbm8gaW5qZWN0b3IgZm91bmQgZm9yIGVsZW1lbnQgYXJndW1lbnQgdG8gZ2V0VGVzdGFiaWxpdHknKTsNCiAgfQ0KICByZXR1cm4gaW5qZWN0b3IuZ2V0KCckJHRlc3RhYmlsaXR5Jyk7DQp9DQoNCnZhciBTTkFLRV9DQVNFX1JFR0VYUCA9IC9bQS1aXS9nOw0KZnVuY3Rpb24gc25ha2VfY2FzZShuYW1lLCBzZXBhcmF0b3IpIHsNCiAgc2VwYXJhdG9yID0gc2VwYXJhdG9yIHx8ICdfJzsNCiAgcmV0dXJuIG5hbWUucmVwbGFjZShTTkFLRV9DQVNFX1JFR0VYUCwgZnVuY3Rpb24obGV0dGVyLCBwb3MpIHsNCiAgICByZXR1cm4gKHBvcyA/IHNlcGFyYXRvciA6ICcnKSArIGxldHRlci50b0xvd2VyQ2FzZSgpOw0KICB9KTsNCn0NCg0KdmFyIGJpbmRKUXVlcnlGaXJlZCA9IGZhbHNlOw0KdmFyIHNraXBEZXN0cm95T25OZXh0SlF1ZXJ5Q2xlYW5EYXRhOw0KZnVuY3Rpb24gYmluZEpRdWVyeSgpIHsNCiAgdmFyIG9yaWdpbmFsQ2xlYW5EYXRhOw0KDQogIGlmIChiaW5kSlF1ZXJ5RmlyZWQpIHsNCiAgICByZXR1cm47DQogIH0NCg0KICAvLyBiaW5kIHRvIGpRdWVyeSBpZiBwcmVzZW50Ow0KICBqUXVlcnkgPSB3aW5kb3cualF1ZXJ5Ow0KICAvLyBVc2UgalF1ZXJ5IGlmIGl0IGV4aXN0cyB3aXRoIHByb3BlciBmdW5jdGlvbmFsaXR5LCBvdGhlcndpc2UgZGVmYXVsdCB0byB1cy4NCiAgLy8gQW5ndWxhciAxLjIrIHJlcXVpcmVzIGpRdWVyeSAxLjcrIGZvciBvbigpL29mZigpIHN1cHBvcnQuDQogIC8vIEFuZ3VsYXIgMS4zKyB0ZWNobmljYWxseSByZXF1aXJlcyBhdCBsZWFzdCBqUXVlcnkgMi4xKyBidXQgaXQgbWF5IHdvcmsgd2l0aCBvbGRlcg0KICAvLyB2ZXJzaW9ucy4gSXQgd2lsbCBub3Qgd29yayBmb3Igc3VyZSB3aXRoIGpRdWVyeSA8MS43LCB0aG91Z2guDQogIGlmIChqUXVlcnkgJiYgalF1ZXJ5LmZuLm9uKSB7DQogICAganFMaXRlID0galF1ZXJ5Ow0KICAgIGV4dGVuZChqUXVlcnkuZm4sIHsNCiAgICAgIHNjb3BlOiBKUUxpdGVQcm90b3R5cGUuc2NvcGUsDQogICAgICBpc29sYXRlU2NvcGU6IEpRTGl0ZVByb3RvdHlwZS5pc29sYXRlU2NvcGUsDQogICAgICBjb250cm9sbGVyOiBKUUxpdGVQcm90b3R5cGUuY29udHJvbGxlciwNCiAgICAgIGluamVjdG9yOiBKUUxpdGVQcm90b3R5cGUuaW5qZWN0b3IsDQogICAgICBpbmhlcml0ZWREYXRhOiBKUUxpdGVQcm90b3R5cGUuaW5oZXJpdGVkRGF0YQ0KICAgIH0pOw0KDQogICAgLy8gQWxsIG5vZGVzIHJlbW92ZWQgZnJvbSB0aGUgRE9NIHZpYSB2YXJpb3VzIGpRdWVyeSBBUElzIGxpa2UgLnJlbW92ZSgpDQogICAgLy8gYXJlIHBhc3NlZCB0aHJvdWdoIGpRdWVyeS5jbGVhbkRhdGEuIE1vbmtleS1wYXRjaCB0aGlzIG1ldGhvZCB0byBmaXJlDQogICAgLy8gdGhlICRkZXN0cm95IGV2ZW50IG9uIGFsbCByZW1vdmVkIG5vZGVzLg0KICAgIG9yaWdpbmFsQ2xlYW5EYXRhID0galF1ZXJ5LmNsZWFuRGF0YTsNCiAgICBqUXVlcnkuY2xlYW5EYXRhID0gZnVuY3Rpb24oZWxlbXMpIHsNCiAgICAgIHZhciBldmVudHM7DQogICAgICBpZiAoIXNraXBEZXN0cm95T25OZXh0SlF1ZXJ5Q2xlYW5EYXRhKSB7DQogICAgICAgIGZvciAodmFyIGkgPSAwLCBlbGVtOyAoZWxlbSA9IGVsZW1zW2ldKSAhPSBudWxsOyBpKyspIHsNCiAgICAgICAgICBldmVudHMgPSBqUXVlcnkuX2RhdGEoZWxlbSwgImV2ZW50cyIpOw0KICAgICAgICAgIGlmIChldmVudHMgJiYgZXZlbnRzLiRkZXN0cm95KSB7DQogICAgICAgICAgICBqUXVlcnkoZWxlbSkudHJpZ2dlckhhbmRsZXIoJyRkZXN0cm95Jyk7DQogICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICB9IGVsc2Ugew0KICAgICAgICBza2lwRGVzdHJveU9uTmV4dEpRdWVyeUNsZWFuRGF0YSA9IGZhbHNlOw0KICAgICAgfQ0KICAgICAgb3JpZ2luYWxDbGVhbkRhdGEoZWxlbXMpOw0KICAgIH07DQogIH0gZWxzZSB7DQogICAganFMaXRlID0gSlFMaXRlOw0KICB9DQoNCiAgYW5ndWxhci5lbGVtZW50ID0ganFMaXRlOw0KDQogIC8vIFByZXZlbnQgZG91YmxlLXByb3h5aW5nLg0KICBiaW5kSlF1ZXJ5RmlyZWQgPSB0cnVlOw0KfQ0KDQovKioNCiAqIHRocm93IGVycm9yIGlmIHRoZSBhcmd1bWVudCBpcyBmYWxzeS4NCiAqLw0KZnVuY3Rpb24gYXNzZXJ0QXJnKGFyZywgbmFtZSwgcmVhc29uKSB7DQogIGlmICghYXJnKSB7DQogICAgdGhyb3cgbmdNaW5FcnIoJ2FyZXEnLCAiQXJndW1lbnQgJ3swfScgaXMgezF9IiwgKG5hbWUgfHwgJz8nKSwgKHJlYXNvbiB8fCAicmVxdWlyZWQiKSk7DQogIH0NCiAgcmV0dXJuIGFyZzsNCn0NCg0KZnVuY3Rpb24gYXNzZXJ0QXJnRm4oYXJnLCBuYW1lLCBhY2NlcHRBcnJheUFubm90YXRpb24pIHsNCiAgaWYgKGFjY2VwdEFycmF5QW5ub3RhdGlvbiAmJiBpc0FycmF5KGFyZykpIHsNCiAgICAgIGFyZyA9IGFyZ1thcmcubGVuZ3RoIC0gMV07DQogIH0NCg0KICBhc3NlcnRBcmcoaXNGdW5jdGlvbihhcmcpLCBuYW1lLCAnbm90IGEgZnVuY3Rpb24sIGdvdCAnICsNCiAgICAgIChhcmcgJiYgdHlwZW9mIGFyZyA9PT0gJ29iamVjdCcgPyBhcmcuY29uc3RydWN0b3IubmFtZSB8fCAnT2JqZWN0JyA6IHR5cGVvZiBhcmcpKTsNCiAgcmV0dXJuIGFyZzsNCn0NCg0KLyoqDQogKiB0aHJvdyBlcnJvciBpZiB0aGUgbmFtZSBnaXZlbiBpcyBoYXNPd25Qcm9wZXJ0eQ0KICogQHBhcmFtICB7U3RyaW5nfSBuYW1lICAgIHRoZSBuYW1lIHRvIHRlc3QNCiAqIEBwYXJhbSAge1N0cmluZ30gY29udGV4dCB0aGUgY29udGV4dCBpbiB3aGljaCB0aGUgbmFtZSBpcyB1c2VkLCBzdWNoIGFzIG1vZHVsZSBvciBkaXJlY3RpdmUNCiAqLw0KZnVuY3Rpb24gYXNzZXJ0Tm90SGFzT3duUHJvcGVydHkobmFtZSwgY29udGV4dCkgew0KICBpZiAobmFtZSA9PT0gJ2hhc093blByb3BlcnR5Jykgew0KICAgIHRocm93IG5nTWluRXJyKCdiYWRuYW1lJywgImhhc093blByb3BlcnR5IGlzIG5vdCBhIHZhbGlkIHswfSBuYW1lIiwgY29udGV4dCk7DQogIH0NCn0NCg0KLyoqDQogKiBSZXR1cm4gdGhlIHZhbHVlIGFjY2Vzc2libGUgZnJvbSB0aGUgb2JqZWN0IGJ5IHBhdGguIEFueSB1bmRlZmluZWQgdHJhdmVyc2FscyBhcmUgaWdub3JlZA0KICogQHBhcmFtIHtPYmplY3R9IG9iaiBzdGFydGluZyBvYmplY3QNCiAqIEBwYXJhbSB7U3RyaW5nfSBwYXRoIHBhdGggdG8gdHJhdmVyc2UNCiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2JpbmRGblRvU2NvcGU9dHJ1ZV0NCiAqIEByZXR1cm5zIHtPYmplY3R9IHZhbHVlIGFzIGFjY2Vzc2libGUgYnkgcGF0aA0KICovDQovL1RPRE8obWlza28pOiB0aGlzIGZ1bmN0aW9uIG5lZWRzIHRvIGJlIHJlbW92ZWQNCmZ1bmN0aW9uIGdldHRlcihvYmosIHBhdGgsIGJpbmRGblRvU2NvcGUpIHsNCiAgaWYgKCFwYXRoKSByZXR1cm4gb2JqOw0KICB2YXIga2V5cyA9IHBhdGguc3BsaXQoJy4nKTsNCiAgdmFyIGtleTsNCiAgdmFyIGxhc3RJbnN0YW5jZSA9IG9iajsNCiAgdmFyIGxlbiA9IGtleXMubGVuZ3RoOw0KDQogIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHsNCiAgICBrZXkgPSBrZXlzW2ldOw0KICAgIGlmIChvYmopIHsNCiAgICAgIG9iaiA9IChsYXN0SW5zdGFuY2UgPSBvYmopW2tleV07DQogICAgfQ0KICB9DQogIGlmICghYmluZEZuVG9TY29wZSAmJiBpc0Z1bmN0aW9uKG9iaikpIHsNCiAgICByZXR1cm4gYmluZChsYXN0SW5zdGFuY2UsIG9iaik7DQogIH0NCiAgcmV0dXJuIG9iajsNCn0NCg0KLyoqDQogKiBSZXR1cm4gdGhlIERPTSBzaWJsaW5ncyBiZXR3ZWVuIHRoZSBmaXJzdCBhbmQgbGFzdCBub2RlIGluIHRoZSBnaXZlbiBhcnJheS4NCiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IGxpa2Ugb2JqZWN0DQogKiBAcmV0dXJucyB7anFMaXRlfSBqcUxpdGUgY29sbGVjdGlvbiBjb250YWluaW5nIHRoZSBub2Rlcw0KICovDQpmdW5jdGlvbiBnZXRCbG9ja05vZGVzKG5vZGVzKSB7DQogIC8vIFRPRE8ocGVyZik6IGp1c3QgY2hlY2sgaWYgYWxsIGl0ZW1zIGluIGBub2Rlc2AgYXJlIHNpYmxpbmdzIGFuZCBpZiB0aGV5IGFyZSByZXR1cm4gdGhlIG9yaWdpbmFsDQogIC8vICAgICAgICAgICAgIGNvbGxlY3Rpb24sIG90aGVyd2lzZSB1cGRhdGUgdGhlIG9yaWdpbmFsIGNvbGxlY3Rpb24uDQogIHZhciBub2RlID0gbm9kZXNbMF07DQogIHZhciBlbmROb2RlID0gbm9kZXNbbm9kZXMubGVuZ3RoIC0gMV07DQogIHZhciBibG9ja05vZGVzID0gW25vZGVdOw0KDQogIGRvIHsNCiAgICBub2RlID0gbm9kZS5uZXh0U2libGluZzsNCiAgICBpZiAoIW5vZGUpIGJyZWFrOw0KICAgIGJsb2NrTm9kZXMucHVzaChub2RlKTsNCiAgfSB3aGlsZSAobm9kZSAhPT0gZW5kTm9kZSk7DQoNCiAgcmV0dXJuIGpxTGl0ZShibG9ja05vZGVzKTsNCn0NCg0KDQovKioNCiAqIENyZWF0ZXMgYSBuZXcgb2JqZWN0IHdpdGhvdXQgYSBwcm90b3R5cGUuIFRoaXMgb2JqZWN0IGlzIHVzZWZ1bCBmb3IgbG9va3VwIHdpdGhvdXQgaGF2aW5nIHRvDQogKiBndWFyZCBhZ2FpbnN0IHByb3RvdHlwaWNhbGx5IGluaGVyaXRlZCBwcm9wZXJ0aWVzIHZpYSBoYXNPd25Qcm9wZXJ0eS4NCiAqDQogKiBSZWxhdGVkIG1pY3JvLWJlbmNobWFya3M6DQogKiAtIGh0dHA6Ly9qc3BlcmYuY29tL29iamVjdC1jcmVhdGUyDQogKiAtIGh0dHA6Ly9qc3BlcmYuY29tL3Byb3RvLW1hcC1sb29rdXAvMg0KICogLSBodHRwOi8vanNwZXJmLmNvbS9mb3ItaW4tdnMtb2JqZWN0LWtleXMyDQogKg0KICogQHJldHVybnMge09iamVjdH0NCiAqLw0KZnVuY3Rpb24gY3JlYXRlTWFwKCkgew0KICByZXR1cm4gT2JqZWN0LmNyZWF0ZShudWxsKTsNCn0NCg0KdmFyIE5PREVfVFlQRV9FTEVNRU5UID0gMTsNCnZhciBOT0RFX1RZUEVfVEVYVCA9IDM7DQp2YXIgTk9ERV9UWVBFX0NPTU1FTlQgPSA4Ow0KdmFyIE5PREVfVFlQRV9ET0NVTUVOVCA9IDk7DQp2YXIgTk9ERV9UWVBFX0RPQ1VNRU5UX0ZSQUdNRU5UID0gMTE7DQoNCi8qKg0KICogQG5nZG9jIHR5cGUNCiAqIEBuYW1lIGFuZ3VsYXIuTW9kdWxlDQogKiBAbW9kdWxlIG5nDQogKiBAZGVzY3JpcHRpb24NCiAqDQogKiBJbnRlcmZhY2UgZm9yIGNvbmZpZ3VyaW5nIGFuZ3VsYXIge0BsaW5rIGFuZ3VsYXIubW9kdWxlIG1vZHVsZXN9Lg0KICovDQoNCmZ1bmN0aW9uIHNldHVwTW9kdWxlTG9hZGVyKHdpbmRvdykgew0KDQogIHZhciAkaW5qZWN0b3JNaW5FcnIgPSBtaW5FcnIoJyRpbmplY3RvcicpOw0KICB2YXIgbmdNaW5FcnIgPSBtaW5FcnIoJ25nJyk7DQoNCiAgZnVuY3Rpb24gZW5zdXJlKG9iaiwgbmFtZSwgZmFjdG9yeSkgew0KICAgIHJldHVybiBvYmpbbmFtZV0gfHwgKG9ialtuYW1lXSA9IGZhY3RvcnkoKSk7DQogIH0NCg0KICB2YXIgYW5ndWxhciA9IGVuc3VyZSh3aW5kb3csICdhbmd1bGFyJywgT2JqZWN0KTsNCg0KICAvLyBXZSBuZWVkIHRvIGV4cG9zZSBgYW5ndWxhci4kJG1pbkVycmAgdG8gbW9kdWxlcyBzdWNoIGFzIGBuZ1Jlc291cmNlYCB0aGF0IHJlZmVyZW5jZSBpdCBkdXJpbmcgYm9vdHN0cmFwDQogIGFuZ3VsYXIuJCRtaW5FcnIgPSBhbmd1bGFyLiQkbWluRXJyIHx8IG1pbkVycjsNCg0KICByZXR1cm4gZW5zdXJlKGFuZ3VsYXIsICdtb2R1bGUnLCBmdW5jdGlvbigpIHsNCiAgICAvKiogQHR5cGUge09iamVjdC48c3RyaW5nLCBhbmd1bGFyLk1vZHVsZT59ICovDQogICAgdmFyIG1vZHVsZXMgPSB7fTsNCg0KICAgIC8qKg0KICAgICAqIEBuZ2RvYyBmdW5jdGlvbg0KICAgICAqIEBuYW1lIGFuZ3VsYXIubW9kdWxlDQogICAgICogQG1vZHVsZSBuZw0KICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAqDQogICAgICogVGhlIGBhbmd1bGFyLm1vZHVsZWAgaXMgYSBnbG9iYWwgcGxhY2UgZm9yIGNyZWF0aW5nLCByZWdpc3RlcmluZyBhbmQgcmV0cmlldmluZyBBbmd1bGFyDQogICAgICogbW9kdWxlcy4NCiAgICAgKiBBbGwgbW9kdWxlcyAoYW5ndWxhciBjb3JlIG9yIDNyZCBwYXJ0eSkgdGhhdCBzaG91bGQgYmUgYXZhaWxhYmxlIHRvIGFuIGFwcGxpY2F0aW9uIG11c3QgYmUNCiAgICAgKiByZWdpc3RlcmVkIHVzaW5nIHRoaXMgbWVjaGFuaXNtLg0KICAgICAqDQogICAgICogV2hlbiBwYXNzZWQgdHdvIG9yIG1vcmUgYXJndW1lbnRzLCBhIG5ldyBtb2R1bGUgaXMgY3JlYXRlZC4gIElmIHBhc3NlZCBvbmx5IG9uZSBhcmd1bWVudCwgYW4NCiAgICAgKiBleGlzdGluZyBtb2R1bGUgKHRoZSBuYW1lIHBhc3NlZCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgdG8gYG1vZHVsZWApIGlzIHJldHJpZXZlZC4NCiAgICAgKg0KICAgICAqDQogICAgICogIyBNb2R1bGUNCiAgICAgKg0KICAgICAqIEEgbW9kdWxlIGlzIGEgY29sbGVjdGlvbiBvZiBzZXJ2aWNlcywgZGlyZWN0aXZlcywgY29udHJvbGxlcnMsIGZpbHRlcnMsIGFuZCBjb25maWd1cmF0aW9uIGluZm9ybWF0aW9uLg0KICAgICAqIGBhbmd1bGFyLm1vZHVsZWAgaXMgdXNlZCB0byBjb25maWd1cmUgdGhlIHtAbGluayBhdXRvLiRpbmplY3RvciAkaW5qZWN0b3J9Lg0KICAgICAqDQogICAgICogYGBganMNCiAgICAgKiAvLyBDcmVhdGUgYSBuZXcgbW9kdWxlDQogICAgICogdmFyIG15TW9kdWxlID0gYW5ndWxhci5tb2R1bGUoJ215TW9kdWxlJywgW10pOw0KICAgICAqDQogICAgICogLy8gcmVnaXN0ZXIgYSBuZXcgc2VydmljZQ0KICAgICAqIG15TW9kdWxlLnZhbHVlKCdhcHBOYW1lJywgJ015Q29vbEFwcCcpOw0KICAgICAqDQogICAgICogLy8gY29uZmlndXJlIGV4aXN0aW5nIHNlcnZpY2VzIGluc2lkZSBpbml0aWFsaXphdGlvbiBibG9ja3MuDQogICAgICogbXlNb2R1bGUuY29uZmlnKFsnJGxvY2F0aW9uUHJvdmlkZXInLCBmdW5jdGlvbigkbG9jYXRpb25Qcm92aWRlcikgew0KICAgICAqICAgLy8gQ29uZmlndXJlIGV4aXN0aW5nIHByb3ZpZGVycw0KICAgICAqICAgJGxvY2F0aW9uUHJvdmlkZXIuaGFzaFByZWZpeCgnIScpOw0KICAgICAqIH1dKTsNCiAgICAgKiBgYGANCiAgICAgKg0KICAgICAqIFRoZW4geW91IGNhbiBjcmVhdGUgYW4gaW5qZWN0b3IgYW5kIGxvYWQgeW91ciBtb2R1bGVzIGxpa2UgdGhpczoNCiAgICAgKg0KICAgICAqIGBgYGpzDQogICAgICogdmFyIGluamVjdG9yID0gYW5ndWxhci5pbmplY3RvcihbJ25nJywgJ215TW9kdWxlJ10pDQogICAgICogYGBgDQogICAgICoNCiAgICAgKiBIb3dldmVyIGl0J3MgbW9yZSBsaWtlbHkgdGhhdCB5b3UnbGwganVzdCB1c2UNCiAgICAgKiB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nQXBwIG5nQXBwfSBvcg0KICAgICAqIHtAbGluayBhbmd1bGFyLmJvb3RzdHJhcH0gdG8gc2ltcGxpZnkgdGhpcyBwcm9jZXNzIGZvciB5b3UuDQogICAgICoNCiAgICAgKiBAcGFyYW0geyFzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIG1vZHVsZSB0byBjcmVhdGUgb3IgcmV0cmlldmUuDQogICAgICogQHBhcmFtIHshQXJyYXkuPHN0cmluZz49fSByZXF1aXJlcyBJZiBzcGVjaWZpZWQgdGhlbiBuZXcgbW9kdWxlIGlzIGJlaW5nIGNyZWF0ZWQuIElmDQogICAgICogICAgICAgIHVuc3BlY2lmaWVkIHRoZW4gdGhlIG1vZHVsZSBpcyBiZWluZyByZXRyaWV2ZWQgZm9yIGZ1cnRoZXIgY29uZmlndXJhdGlvbi4NCiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uPX0gY29uZmlnRm4gT3B0aW9uYWwgY29uZmlndXJhdGlvbiBmdW5jdGlvbiBmb3IgdGhlIG1vZHVsZS4gU2FtZSBhcw0KICAgICAqICAgICAgICB7QGxpbmsgYW5ndWxhci5Nb2R1bGUjY29uZmlnIE1vZHVsZSNjb25maWcoKX0uDQogICAgICogQHJldHVybnMge21vZHVsZX0gbmV3IG1vZHVsZSB3aXRoIHRoZSB7QGxpbmsgYW5ndWxhci5Nb2R1bGV9IGFwaS4NCiAgICAgKi8NCiAgICByZXR1cm4gZnVuY3Rpb24gbW9kdWxlKG5hbWUsIHJlcXVpcmVzLCBjb25maWdGbikgew0KICAgICAgdmFyIGFzc2VydE5vdEhhc093blByb3BlcnR5ID0gZnVuY3Rpb24obmFtZSwgY29udGV4dCkgew0KICAgICAgICBpZiAobmFtZSA9PT0gJ2hhc093blByb3BlcnR5Jykgew0KICAgICAgICAgIHRocm93IG5nTWluRXJyKCdiYWRuYW1lJywgJ2hhc093blByb3BlcnR5IGlzIG5vdCBhIHZhbGlkIHswfSBuYW1lJywgY29udGV4dCk7DQogICAgICAgIH0NCiAgICAgIH07DQoNCiAgICAgIGFzc2VydE5vdEhhc093blByb3BlcnR5KG5hbWUsICdtb2R1bGUnKTsNCiAgICAgIGlmIChyZXF1aXJlcyAmJiBtb2R1bGVzLmhhc093blByb3BlcnR5KG5hbWUpKSB7DQogICAgICAgIG1vZHVsZXNbbmFtZV0gPSBudWxsOw0KICAgICAgfQ0KICAgICAgcmV0dXJuIGVuc3VyZShtb2R1bGVzLCBuYW1lLCBmdW5jdGlvbigpIHsNCiAgICAgICAgaWYgKCFyZXF1aXJlcykgew0KICAgICAgICAgIHRocm93ICRpbmplY3Rvck1pbkVycignbm9tb2QnLCAiTW9kdWxlICd7MH0nIGlzIG5vdCBhdmFpbGFibGUhIFlvdSBlaXRoZXIgbWlzc3BlbGxlZCAiICsNCiAgICAgICAgICAgICAidGhlIG1vZHVsZSBuYW1lIG9yIGZvcmdvdCB0byBsb2FkIGl0LiBJZiByZWdpc3RlcmluZyBhIG1vZHVsZSBlbnN1cmUgdGhhdCB5b3UgIiArDQogICAgICAgICAgICAgInNwZWNpZnkgdGhlIGRlcGVuZGVuY2llcyBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50LiIsIG5hbWUpOw0KICAgICAgICB9DQoNCiAgICAgICAgLyoqIEB0eXBlIHshQXJyYXkuPEFycmF5LjwqPj59ICovDQogICAgICAgIHZhciBpbnZva2VRdWV1ZSA9IFtdOw0KDQogICAgICAgIC8qKiBAdHlwZSB7IUFycmF5LjxGdW5jdGlvbj59ICovDQogICAgICAgIHZhciBjb25maWdCbG9ja3MgPSBbXTsNCg0KICAgICAgICAvKiogQHR5cGUgeyFBcnJheS48RnVuY3Rpb24+fSAqLw0KICAgICAgICB2YXIgcnVuQmxvY2tzID0gW107DQoNCiAgICAgICAgdmFyIGNvbmZpZyA9IGludm9rZUxhdGVyKCckaW5qZWN0b3InLCAnaW52b2tlJywgJ3B1c2gnLCBjb25maWdCbG9ja3MpOw0KDQogICAgICAgIC8qKiBAdHlwZSB7YW5ndWxhci5Nb2R1bGV9ICovDQogICAgICAgIHZhciBtb2R1bGVJbnN0YW5jZSA9IHsNCiAgICAgICAgICAvLyBQcml2YXRlIHN0YXRlDQogICAgICAgICAgX2ludm9rZVF1ZXVlOiBpbnZva2VRdWV1ZSwNCiAgICAgICAgICBfY29uZmlnQmxvY2tzOiBjb25maWdCbG9ja3MsDQogICAgICAgICAgX3J1bkJsb2NrczogcnVuQmxvY2tzLA0KDQogICAgICAgICAgLyoqDQogICAgICAgICAgICogQG5nZG9jIHByb3BlcnR5DQogICAgICAgICAgICogQG5hbWUgYW5ndWxhci5Nb2R1bGUjcmVxdWlyZXMNCiAgICAgICAgICAgKiBAbW9kdWxlIG5nDQogICAgICAgICAgICoNCiAgICAgICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAgICAgKiBIb2xkcyB0aGUgbGlzdCBvZiBtb2R1bGVzIHdoaWNoIHRoZSBpbmplY3RvciB3aWxsIGxvYWQgYmVmb3JlIHRoZSBjdXJyZW50IG1vZHVsZSBpcw0KICAgICAgICAgICAqIGxvYWRlZC4NCiAgICAgICAgICAgKi8NCiAgICAgICAgICByZXF1aXJlczogcmVxdWlyZXMsDQoNCiAgICAgICAgICAvKioNCiAgICAgICAgICAgKiBAbmdkb2MgcHJvcGVydHkNCiAgICAgICAgICAgKiBAbmFtZSBhbmd1bGFyLk1vZHVsZSNuYW1lDQogICAgICAgICAgICogQG1vZHVsZSBuZw0KICAgICAgICAgICAqDQogICAgICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgICAgICogTmFtZSBvZiB0aGUgbW9kdWxlLg0KICAgICAgICAgICAqLw0KICAgICAgICAgIG5hbWU6IG5hbWUsDQoNCg0KICAgICAgICAgIC8qKg0KICAgICAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAgICAgKiBAbmFtZSBhbmd1bGFyLk1vZHVsZSNwcm92aWRlcg0KICAgICAgICAgICAqIEBtb2R1bGUgbmcNCiAgICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBzZXJ2aWNlIG5hbWUNCiAgICAgICAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcm92aWRlclR5cGUgQ29uc3RydWN0aW9uIGZ1bmN0aW9uIGZvciBjcmVhdGluZyBuZXcgaW5zdGFuY2Ugb2YgdGhlDQogICAgICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcnZpY2UuDQogICAgICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgICAgICogU2VlIHtAbGluayBhdXRvLiRwcm92aWRlI3Byb3ZpZGVyICRwcm92aWRlLnByb3ZpZGVyKCl9Lg0KICAgICAgICAgICAqLw0KICAgICAgICAgIHByb3ZpZGVyOiBpbnZva2VMYXRlcignJHByb3ZpZGUnLCAncHJvdmlkZXInKSwNCg0KICAgICAgICAgIC8qKg0KICAgICAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAgICAgKiBAbmFtZSBhbmd1bGFyLk1vZHVsZSNmYWN0b3J5DQogICAgICAgICAgICogQG1vZHVsZSBuZw0KICAgICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIHNlcnZpY2UgbmFtZQ0KICAgICAgICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByb3ZpZGVyRnVuY3Rpb24gRnVuY3Rpb24gZm9yIGNyZWF0aW5nIG5ldyBpbnN0YW5jZSBvZiB0aGUgc2VydmljZS4NCiAgICAgICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAgICAgKiBTZWUge0BsaW5rIGF1dG8uJHByb3ZpZGUjZmFjdG9yeSAkcHJvdmlkZS5mYWN0b3J5KCl9Lg0KICAgICAgICAgICAqLw0KICAgICAgICAgIGZhY3Rvcnk6IGludm9rZUxhdGVyKCckcHJvdmlkZScsICdmYWN0b3J5JyksDQoNCiAgICAgICAgICAvKioNCiAgICAgICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgICAgICogQG5hbWUgYW5ndWxhci5Nb2R1bGUjc2VydmljZQ0KICAgICAgICAgICAqIEBtb2R1bGUgbmcNCiAgICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBzZXJ2aWNlIG5hbWUNCiAgICAgICAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjb25zdHJ1Y3RvciBBIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBpbnN0YW50aWF0ZWQuDQogICAgICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgICAgICogU2VlIHtAbGluayBhdXRvLiRwcm92aWRlI3NlcnZpY2UgJHByb3ZpZGUuc2VydmljZSgpfS4NCiAgICAgICAgICAgKi8NCiAgICAgICAgICBzZXJ2aWNlOiBpbnZva2VMYXRlcignJHByb3ZpZGUnLCAnc2VydmljZScpLA0KDQogICAgICAgICAgLyoqDQogICAgICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICAgICAqIEBuYW1lIGFuZ3VsYXIuTW9kdWxlI3ZhbHVlDQogICAgICAgICAgICogQG1vZHVsZSBuZw0KICAgICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIHNlcnZpY2UgbmFtZQ0KICAgICAgICAgICAqIEBwYXJhbSB7Kn0gb2JqZWN0IFNlcnZpY2UgaW5zdGFuY2Ugb2JqZWN0Lg0KICAgICAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICAgICAqIFNlZSB7QGxpbmsgYXV0by4kcHJvdmlkZSN2YWx1ZSAkcHJvdmlkZS52YWx1ZSgpfS4NCiAgICAgICAgICAgKi8NCiAgICAgICAgICB2YWx1ZTogaW52b2tlTGF0ZXIoJyRwcm92aWRlJywgJ3ZhbHVlJyksDQoNCiAgICAgICAgICAvKioNCiAgICAgICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgICAgICogQG5hbWUgYW5ndWxhci5Nb2R1bGUjY29uc3RhbnQNCiAgICAgICAgICAgKiBAbW9kdWxlIG5nDQogICAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgY29uc3RhbnQgbmFtZQ0KICAgICAgICAgICAqIEBwYXJhbSB7Kn0gb2JqZWN0IENvbnN0YW50IHZhbHVlLg0KICAgICAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICAgICAqIEJlY2F1c2UgdGhlIGNvbnN0YW50IGFyZSBmaXhlZCwgdGhleSBnZXQgYXBwbGllZCBiZWZvcmUgb3RoZXIgcHJvdmlkZSBtZXRob2RzLg0KICAgICAgICAgICAqIFNlZSB7QGxpbmsgYXV0by4kcHJvdmlkZSNjb25zdGFudCAkcHJvdmlkZS5jb25zdGFudCgpfS4NCiAgICAgICAgICAgKi8NCiAgICAgICAgICBjb25zdGFudDogaW52b2tlTGF0ZXIoJyRwcm92aWRlJywgJ2NvbnN0YW50JywgJ3Vuc2hpZnQnKSwNCg0KICAgICAgICAgIC8qKg0KICAgICAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAgICAgKiBAbmFtZSBhbmd1bGFyLk1vZHVsZSNhbmltYXRpb24NCiAgICAgICAgICAgKiBAbW9kdWxlIG5nDQogICAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgYW5pbWF0aW9uIG5hbWUNCiAgICAgICAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBhbmltYXRpb25GYWN0b3J5IEZhY3RvcnkgZnVuY3Rpb24gZm9yIGNyZWF0aW5nIG5ldyBpbnN0YW5jZSBvZiBhbg0KICAgICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5pbWF0aW9uLg0KICAgICAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICAgICAqDQogICAgICAgICAgICogKipOT1RFKio6IGFuaW1hdGlvbnMgdGFrZSBlZmZlY3Qgb25seSBpZiB0aGUgKipuZ0FuaW1hdGUqKiBtb2R1bGUgaXMgbG9hZGVkLg0KICAgICAgICAgICAqDQogICAgICAgICAgICoNCiAgICAgICAgICAgKiBEZWZpbmVzIGFuIGFuaW1hdGlvbiBob29rIHRoYXQgY2FuIGJlIGxhdGVyIHVzZWQgd2l0aA0KICAgICAgICAgICAqIHtAbGluayBuZ0FuaW1hdGUuJGFuaW1hdGUgJGFuaW1hdGV9IHNlcnZpY2UgYW5kIGRpcmVjdGl2ZXMgdGhhdCB1c2UgdGhpcyBzZXJ2aWNlLg0KICAgICAgICAgICAqDQogICAgICAgICAgICogYGBganMNCiAgICAgICAgICAgKiBtb2R1bGUuYW5pbWF0aW9uKCcuYW5pbWF0aW9uLW5hbWUnLCBmdW5jdGlvbigkaW5qZWN0MSwgJGluamVjdDIpIHsNCiAgICAgICAgICAgKiAgIHJldHVybiB7DQogICAgICAgICAgICogICAgIGV2ZW50TmFtZSA6IGZ1bmN0aW9uKGVsZW1lbnQsIGRvbmUpIHsNCiAgICAgICAgICAgKiAgICAgICAvL2NvZGUgdG8gcnVuIHRoZSBhbmltYXRpb24NCiAgICAgICAgICAgKiAgICAgICAvL29uY2UgY29tcGxldGUsIHRoZW4gcnVuIGRvbmUoKQ0KICAgICAgICAgICAqICAgICAgIHJldHVybiBmdW5jdGlvbiBjYW5jZWxsYXRpb25GdW5jdGlvbihlbGVtZW50KSB7DQogICAgICAgICAgICogICAgICAgICAvL2NvZGUgdG8gY2FuY2VsIHRoZSBhbmltYXRpb24NCiAgICAgICAgICAgKiAgICAgICB9DQogICAgICAgICAgICogICAgIH0NCiAgICAgICAgICAgKiAgIH0NCiAgICAgICAgICAgKiB9KQ0KICAgICAgICAgICAqIGBgYA0KICAgICAgICAgICAqDQogICAgICAgICAgICogU2VlIHtAbGluayBuZy4kYW5pbWF0ZVByb3ZpZGVyI3JlZ2lzdGVyICRhbmltYXRlUHJvdmlkZXIucmVnaXN0ZXIoKX0gYW5kDQogICAgICAgICAgICoge0BsaW5rIG5nQW5pbWF0ZSBuZ0FuaW1hdGUgbW9kdWxlfSBmb3IgbW9yZSBpbmZvcm1hdGlvbi4NCiAgICAgICAgICAgKi8NCiAgICAgICAgICBhbmltYXRpb246IGludm9rZUxhdGVyKCckYW5pbWF0ZVByb3ZpZGVyJywgJ3JlZ2lzdGVyJyksDQoNCiAgICAgICAgICAvKioNCiAgICAgICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgICAgICogQG5hbWUgYW5ndWxhci5Nb2R1bGUjZmlsdGVyDQogICAgICAgICAgICogQG1vZHVsZSBuZw0KICAgICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIEZpbHRlciBuYW1lLg0KICAgICAgICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZpbHRlckZhY3RvcnkgRmFjdG9yeSBmdW5jdGlvbiBmb3IgY3JlYXRpbmcgbmV3IGluc3RhbmNlIG9mIGZpbHRlci4NCiAgICAgICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAgICAgKiBTZWUge0BsaW5rIG5nLiRmaWx0ZXJQcm92aWRlciNyZWdpc3RlciAkZmlsdGVyUHJvdmlkZXIucmVnaXN0ZXIoKX0uDQogICAgICAgICAgICovDQogICAgICAgICAgZmlsdGVyOiBpbnZva2VMYXRlcignJGZpbHRlclByb3ZpZGVyJywgJ3JlZ2lzdGVyJyksDQoNCiAgICAgICAgICAvKioNCiAgICAgICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgICAgICogQG5hbWUgYW5ndWxhci5Nb2R1bGUjY29udHJvbGxlcg0KICAgICAgICAgICAqIEBtb2R1bGUgbmcNCiAgICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ3xPYmplY3R9IG5hbWUgQ29udHJvbGxlciBuYW1lLCBvciBhbiBvYmplY3QgbWFwIG9mIGNvbnRyb2xsZXJzIHdoZXJlIHRoZQ0KICAgICAgICAgICAqICAgIGtleXMgYXJlIHRoZSBuYW1lcyBhbmQgdGhlIHZhbHVlcyBhcmUgdGhlIGNvbnN0cnVjdG9ycy4NCiAgICAgICAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjb25zdHJ1Y3RvciBDb250cm9sbGVyIGNvbnN0cnVjdG9yIGZ1bmN0aW9uLg0KICAgICAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICAgICAqIFNlZSB7QGxpbmsgbmcuJGNvbnRyb2xsZXJQcm92aWRlciNyZWdpc3RlciAkY29udHJvbGxlclByb3ZpZGVyLnJlZ2lzdGVyKCl9Lg0KICAgICAgICAgICAqLw0KICAgICAgICAgIGNvbnRyb2xsZXI6IGludm9rZUxhdGVyKCckY29udHJvbGxlclByb3ZpZGVyJywgJ3JlZ2lzdGVyJyksDQoNCiAgICAgICAgICAvKioNCiAgICAgICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgICAgICogQG5hbWUgYW5ndWxhci5Nb2R1bGUjZGlyZWN0aXZlDQogICAgICAgICAgICogQG1vZHVsZSBuZw0KICAgICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfE9iamVjdH0gbmFtZSBEaXJlY3RpdmUgbmFtZSwgb3IgYW4gb2JqZWN0IG1hcCBvZiBkaXJlY3RpdmVzIHdoZXJlIHRoZQ0KICAgICAgICAgICAqICAgIGtleXMgYXJlIHRoZSBuYW1lcyBhbmQgdGhlIHZhbHVlcyBhcmUgdGhlIGZhY3Rvcmllcy4NCiAgICAgICAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkaXJlY3RpdmVGYWN0b3J5IEZhY3RvcnkgZnVuY3Rpb24gZm9yIGNyZWF0aW5nIG5ldyBpbnN0YW5jZSBvZg0KICAgICAgICAgICAqIGRpcmVjdGl2ZXMuDQogICAgICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgICAgICogU2VlIHtAbGluayBuZy4kY29tcGlsZVByb3ZpZGVyI2RpcmVjdGl2ZSAkY29tcGlsZVByb3ZpZGVyLmRpcmVjdGl2ZSgpfS4NCiAgICAgICAgICAgKi8NCiAgICAgICAgICBkaXJlY3RpdmU6IGludm9rZUxhdGVyKCckY29tcGlsZVByb3ZpZGVyJywgJ2RpcmVjdGl2ZScpLA0KDQogICAgICAgICAgLyoqDQogICAgICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICAgICAqIEBuYW1lIGFuZ3VsYXIuTW9kdWxlI2NvbmZpZw0KICAgICAgICAgICAqIEBtb2R1bGUgbmcNCiAgICAgICAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjb25maWdGbiBFeGVjdXRlIHRoaXMgZnVuY3Rpb24gb24gbW9kdWxlIGxvYWQuIFVzZWZ1bCBmb3Igc2VydmljZQ0KICAgICAgICAgICAqICAgIGNvbmZpZ3VyYXRpb24uDQogICAgICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgICAgICogVXNlIHRoaXMgbWV0aG9kIHRvIHJlZ2lzdGVyIHdvcmsgd2hpY2ggbmVlZHMgdG8gYmUgcGVyZm9ybWVkIG9uIG1vZHVsZSBsb2FkaW5nLg0KICAgICAgICAgICAqIEZvciBtb3JlIGFib3V0IGhvdyB0byBjb25maWd1cmUgc2VydmljZXMsIHNlZQ0KICAgICAgICAgICAqIHtAbGluayBwcm92aWRlcnMjcHJvdmlkZXItcmVjaXBlIFByb3ZpZGVyIFJlY2lwZX0uDQogICAgICAgICAgICovDQogICAgICAgICAgY29uZmlnOiBjb25maWcsDQoNCiAgICAgICAgICAvKioNCiAgICAgICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgICAgICogQG5hbWUgYW5ndWxhci5Nb2R1bGUjcnVuDQogICAgICAgICAgICogQG1vZHVsZSBuZw0KICAgICAgICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGluaXRpYWxpemF0aW9uRm4gRXhlY3V0ZSB0aGlzIGZ1bmN0aW9uIGFmdGVyIGluamVjdG9yIGNyZWF0aW9uLg0KICAgICAgICAgICAqICAgIFVzZWZ1bCBmb3IgYXBwbGljYXRpb24gaW5pdGlhbGl6YXRpb24uDQogICAgICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgICAgICogVXNlIHRoaXMgbWV0aG9kIHRvIHJlZ2lzdGVyIHdvcmsgd2hpY2ggc2hvdWxkIGJlIHBlcmZvcm1lZCB3aGVuIHRoZSBpbmplY3RvciBpcyBkb25lDQogICAgICAgICAgICogbG9hZGluZyBhbGwgbW9kdWxlcy4NCiAgICAgICAgICAgKi8NCiAgICAgICAgICBydW46IGZ1bmN0aW9uKGJsb2NrKSB7DQogICAgICAgICAgICBydW5CbG9ja3MucHVzaChibG9jayk7DQogICAgICAgICAgICByZXR1cm4gdGhpczsNCiAgICAgICAgICB9DQogICAgICAgIH07DQoNCiAgICAgICAgaWYgKGNvbmZpZ0ZuKSB7DQogICAgICAgICAgY29uZmlnKGNvbmZpZ0ZuKTsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiBtb2R1bGVJbnN0YW5jZTsNCg0KICAgICAgICAvKioNCiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IHByb3ZpZGVyDQogICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2QNCiAgICAgICAgICogQHBhcmFtIHtTdHJpbmc9fSBpbnNlcnRNZXRob2QNCiAgICAgICAgICogQHJldHVybnMge2FuZ3VsYXIuTW9kdWxlfQ0KICAgICAgICAgKi8NCiAgICAgICAgZnVuY3Rpb24gaW52b2tlTGF0ZXIocHJvdmlkZXIsIG1ldGhvZCwgaW5zZXJ0TWV0aG9kLCBxdWV1ZSkgew0KICAgICAgICAgIGlmICghcXVldWUpIHF1ZXVlID0gaW52b2tlUXVldWU7DQogICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgcXVldWVbaW5zZXJ0TWV0aG9kIHx8ICdwdXNoJ10oW3Byb3ZpZGVyLCBtZXRob2QsIGFyZ3VtZW50c10pOw0KICAgICAgICAgICAgcmV0dXJuIG1vZHVsZUluc3RhbmNlOw0KICAgICAgICAgIH07DQogICAgICAgIH0NCiAgICAgIH0pOw0KICAgIH07DQogIH0pOw0KDQp9DQoNCi8qIGdsb2JhbDogdG9EZWJ1Z1N0cmluZzogdHJ1ZSAqLw0KDQpmdW5jdGlvbiBzZXJpYWxpemVPYmplY3Qob2JqKSB7DQogIHZhciBzZWVuID0gW107DQoNCiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgZnVuY3Rpb24oa2V5LCB2YWwpIHsNCiAgICB2YWwgPSB0b0pzb25SZXBsYWNlcihrZXksIHZhbCk7DQogICAgaWYgKGlzT2JqZWN0KHZhbCkpIHsNCg0KICAgICAgaWYgKHNlZW4uaW5kZXhPZih2YWwpID49IDApIHJldHVybiAnPDxhbHJlYWR5IHNlZW4+Pic7DQoNCiAgICAgIHNlZW4ucHVzaCh2YWwpOw0KICAgIH0NCiAgICByZXR1cm4gdmFsOw0KICB9KTsNCn0NCg0KZnVuY3Rpb24gdG9EZWJ1Z1N0cmluZyhvYmopIHsNCiAgaWYgKHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpIHsNCiAgICByZXR1cm4gb2JqLnRvU3RyaW5nKCkucmVwbGFjZSgvIFx7W1xzXFNdKiQvLCAnJyk7DQogIH0gZWxzZSBpZiAodHlwZW9mIG9iaiA9PT0gJ3VuZGVmaW5lZCcpIHsNCiAgICByZXR1cm4gJ3VuZGVmaW5lZCc7DQogIH0gZWxzZSBpZiAodHlwZW9mIG9iaiAhPT0gJ3N0cmluZycpIHsNCiAgICByZXR1cm4gc2VyaWFsaXplT2JqZWN0KG9iaik7DQogIH0NCiAgcmV0dXJuIG9iajsNCn0NCg0KLyogZ2xvYmFsIGFuZ3VsYXJNb2R1bGU6IHRydWUsDQogIHZlcnNpb246IHRydWUsDQoNCiAgJExvY2FsZVByb3ZpZGVyLA0KICAkQ29tcGlsZVByb3ZpZGVyLA0KDQogIGh0bWxBbmNob3JEaXJlY3RpdmUsDQogIGlucHV0RGlyZWN0aXZlLA0KICBpbnB1dERpcmVjdGl2ZSwNCiAgZm9ybURpcmVjdGl2ZSwNCiAgc2NyaXB0RGlyZWN0aXZlLA0KICBzZWxlY3REaXJlY3RpdmUsDQogIHN0eWxlRGlyZWN0aXZlLA0KICBvcHRpb25EaXJlY3RpdmUsDQogIG5nQmluZERpcmVjdGl2ZSwNCiAgbmdCaW5kSHRtbERpcmVjdGl2ZSwNCiAgbmdCaW5kVGVtcGxhdGVEaXJlY3RpdmUsDQogIG5nQ2xhc3NEaXJlY3RpdmUsDQogIG5nQ2xhc3NFdmVuRGlyZWN0aXZlLA0KICBuZ0NsYXNzT2RkRGlyZWN0aXZlLA0KICBuZ0NzcERpcmVjdGl2ZSwNCiAgbmdDbG9ha0RpcmVjdGl2ZSwNCiAgbmdDb250cm9sbGVyRGlyZWN0aXZlLA0KICBuZ0Zvcm1EaXJlY3RpdmUsDQogIG5nSGlkZURpcmVjdGl2ZSwNCiAgbmdJZkRpcmVjdGl2ZSwNCiAgbmdJbmNsdWRlRGlyZWN0aXZlLA0KICBuZ0luY2x1ZGVGaWxsQ29udGVudERpcmVjdGl2ZSwNCiAgbmdJbml0RGlyZWN0aXZlLA0KICBuZ05vbkJpbmRhYmxlRGlyZWN0aXZlLA0KICBuZ1BsdXJhbGl6ZURpcmVjdGl2ZSwNCiAgbmdSZXBlYXREaXJlY3RpdmUsDQogIG5nU2hvd0RpcmVjdGl2ZSwNCiAgbmdTdHlsZURpcmVjdGl2ZSwNCiAgbmdTd2l0Y2hEaXJlY3RpdmUsDQogIG5nU3dpdGNoV2hlbkRpcmVjdGl2ZSwNCiAgbmdTd2l0Y2hEZWZhdWx0RGlyZWN0aXZlLA0KICBuZ09wdGlvbnNEaXJlY3RpdmUsDQogIG5nVHJhbnNjbHVkZURpcmVjdGl2ZSwNCiAgbmdNb2RlbERpcmVjdGl2ZSwNCiAgbmdMaXN0RGlyZWN0aXZlLA0KICBuZ0NoYW5nZURpcmVjdGl2ZSwNCiAgcGF0dGVybkRpcmVjdGl2ZSwNCiAgcGF0dGVybkRpcmVjdGl2ZSwNCiAgcmVxdWlyZWREaXJlY3RpdmUsDQogIHJlcXVpcmVkRGlyZWN0aXZlLA0KICBtaW5sZW5ndGhEaXJlY3RpdmUsDQogIG1pbmxlbmd0aERpcmVjdGl2ZSwNCiAgbWF4bGVuZ3RoRGlyZWN0aXZlLA0KICBtYXhsZW5ndGhEaXJlY3RpdmUsDQogIG5nVmFsdWVEaXJlY3RpdmUsDQogIG5nTW9kZWxPcHRpb25zRGlyZWN0aXZlLA0KICBuZ0F0dHJpYnV0ZUFsaWFzRGlyZWN0aXZlcywNCiAgbmdFdmVudERpcmVjdGl2ZXMsDQoNCiAgJEFuY2hvclNjcm9sbFByb3ZpZGVyLA0KICAkQW5pbWF0ZVByb3ZpZGVyLA0KICAkQnJvd3NlclByb3ZpZGVyLA0KICAkQ2FjaGVGYWN0b3J5UHJvdmlkZXIsDQogICRDb250cm9sbGVyUHJvdmlkZXIsDQogICREb2N1bWVudFByb3ZpZGVyLA0KICAkRXhjZXB0aW9uSGFuZGxlclByb3ZpZGVyLA0KICAkRmlsdGVyUHJvdmlkZXIsDQogICRJbnRlcnBvbGF0ZVByb3ZpZGVyLA0KICAkSW50ZXJ2YWxQcm92aWRlciwNCiAgJEh0dHBQcm92aWRlciwNCiAgJEh0dHBCYWNrZW5kUHJvdmlkZXIsDQogICRMb2NhdGlvblByb3ZpZGVyLA0KICAkTG9nUHJvdmlkZXIsDQogICRQYXJzZVByb3ZpZGVyLA0KICAkUm9vdFNjb3BlUHJvdmlkZXIsDQogICRRUHJvdmlkZXIsDQogICQkUVByb3ZpZGVyLA0KICAkJFNhbml0aXplVXJpUHJvdmlkZXIsDQogICRTY2VQcm92aWRlciwNCiAgJFNjZURlbGVnYXRlUHJvdmlkZXIsDQogICRTbmlmZmVyUHJvdmlkZXIsDQogICRUZW1wbGF0ZUNhY2hlUHJvdmlkZXIsDQogICRUZW1wbGF0ZVJlcXVlc3RQcm92aWRlciwNCiAgJCRUZXN0YWJpbGl0eVByb3ZpZGVyLA0KICAkVGltZW91dFByb3ZpZGVyLA0KICAkJFJBRlByb3ZpZGVyLA0KICAkJEFzeW5jQ2FsbGJhY2tQcm92aWRlciwNCiAgJFdpbmRvd1Byb3ZpZGVyLA0KICAkJGpxTGl0ZVByb3ZpZGVyDQoqLw0KDQoNCi8qKg0KICogQG5nZG9jIG9iamVjdA0KICogQG5hbWUgYW5ndWxhci52ZXJzaW9uDQogKiBAbW9kdWxlIG5nDQogKiBAZGVzY3JpcHRpb24NCiAqIEFuIG9iamVjdCB0aGF0IGNvbnRhaW5zIGluZm9ybWF0aW9uIGFib3V0IHRoZSBjdXJyZW50IEFuZ3VsYXJKUyB2ZXJzaW9uLiBUaGlzIG9iamVjdCBoYXMgdGhlDQogKiBmb2xsb3dpbmcgcHJvcGVydGllczoNCiAqDQogKiAtIGBmdWxsYCDigD8gYHtzdHJpbmd9YCDigD8gRnVsbCB2ZXJzaW9uIHN0cmluZywgc3VjaCBhcyAiMC45LjE4Ii4NCiAqIC0gYG1ham9yYCDigD8gYHtudW1iZXJ9YCDigD8gTWFqb3IgdmVyc2lvbiBudW1iZXIsIHN1Y2ggYXMgIjAiLg0KICogLSBgbWlub3JgIOKAPyBge251bWJlcn1gIOKAPyBNaW5vciB2ZXJzaW9uIG51bWJlciwgc3VjaCBhcyAiOSIuDQogKiAtIGBkb3RgIOKAPyBge251bWJlcn1gIOKAPyBEb3QgdmVyc2lvbiBudW1iZXIsIHN1Y2ggYXMgIjE4Ii4NCiAqIC0gYGNvZGVOYW1lYCDigD8gYHtzdHJpbmd9YCDigD8gQ29kZSBuYW1lIG9mIHRoZSByZWxlYXNlLCBzdWNoIGFzICJqaWdnbGluZy1hcm1mYXQiLg0KICovDQp2YXIgdmVyc2lvbiA9IHsNCiAgZnVsbDogJzEuMy44JywgICAgLy8gYWxsIG9mIHRoZXNlIHBsYWNlaG9sZGVyIHN0cmluZ3Mgd2lsbCBiZSByZXBsYWNlZCBieSBncnVudCdzDQogIG1ham9yOiAxLCAgICAvLyBwYWNrYWdlIHRhc2sNCiAgbWlub3I6IDMsDQogIGRvdDogOCwNCiAgY29kZU5hbWU6ICdwcm9waGV0aWMtbmFyd2hhbCcNCn07DQoNCg0KZnVuY3Rpb24gcHVibGlzaEV4dGVybmFsQVBJKGFuZ3VsYXIpIHsNCiAgZXh0ZW5kKGFuZ3VsYXIsIHsNCiAgICAnYm9vdHN0cmFwJzogYm9vdHN0cmFwLA0KICAgICdjb3B5JzogY29weSwNCiAgICAnZXh0ZW5kJzogZXh0ZW5kLA0KICAgICdlcXVhbHMnOiBlcXVhbHMsDQogICAgJ2VsZW1lbnQnOiBqcUxpdGUsDQogICAgJ2ZvckVhY2gnOiBmb3JFYWNoLA0KICAgICdpbmplY3Rvcic6IGNyZWF0ZUluamVjdG9yLA0KICAgICdub29wJzogbm9vcCwNCiAgICAnYmluZCc6IGJpbmQsDQogICAgJ3RvSnNvbic6IHRvSnNvbiwNCiAgICAnZnJvbUpzb24nOiBmcm9tSnNvbiwNCiAgICAnaWRlbnRpdHknOiBpZGVudGl0eSwNCiAgICAnaXNVbmRlZmluZWQnOiBpc1VuZGVmaW5lZCwNCiAgICAnaXNEZWZpbmVkJzogaXNEZWZpbmVkLA0KICAgICdpc1N0cmluZyc6IGlzU3RyaW5nLA0KICAgICdpc0Z1bmN0aW9uJzogaXNGdW5jdGlvbiwNCiAgICAnaXNPYmplY3QnOiBpc09iamVjdCwNCiAgICAnaXNOdW1iZXInOiBpc051bWJlciwNCiAgICAnaXNFbGVtZW50JzogaXNFbGVtZW50LA0KICAgICdpc0FycmF5JzogaXNBcnJheSwNCiAgICAndmVyc2lvbic6IHZlcnNpb24sDQogICAgJ2lzRGF0ZSc6IGlzRGF0ZSwNCiAgICAnbG93ZXJjYXNlJzogbG93ZXJjYXNlLA0KICAgICd1cHBlcmNhc2UnOiB1cHBlcmNhc2UsDQogICAgJ2NhbGxiYWNrcyc6IHtjb3VudGVyOiAwfSwNCiAgICAnZ2V0VGVzdGFiaWxpdHknOiBnZXRUZXN0YWJpbGl0eSwNCiAgICAnJCRtaW5FcnInOiBtaW5FcnIsDQogICAgJyQkY3NwJzogY3NwLA0KICAgICdyZWxvYWRXaXRoRGVidWdJbmZvJzogcmVsb2FkV2l0aERlYnVnSW5mbw0KICB9KTsNCg0KICBhbmd1bGFyTW9kdWxlID0gc2V0dXBNb2R1bGVMb2FkZXIod2luZG93KTsNCiAgdHJ5IHsNCiAgICBhbmd1bGFyTW9kdWxlKCduZ0xvY2FsZScpOw0KICB9IGNhdGNoIChlKSB7DQogICAgYW5ndWxhck1vZHVsZSgnbmdMb2NhbGUnLCBbXSkucHJvdmlkZXIoJyRsb2NhbGUnLCAkTG9jYWxlUHJvdmlkZXIpOw0KICB9DQoNCiAgYW5ndWxhck1vZHVsZSgnbmcnLCBbJ25nTG9jYWxlJ10sIFsnJHByb3ZpZGUnLA0KICAgIGZ1bmN0aW9uIG5nTW9kdWxlKCRwcm92aWRlKSB7DQogICAgICAvLyAkJHNhbml0aXplVXJpUHJvdmlkZXIgbmVlZHMgdG8gYmUgYmVmb3JlICRjb21waWxlUHJvdmlkZXIgYXMgaXQgaXMgdXNlZCBieSBpdC4NCiAgICAgICRwcm92aWRlLnByb3ZpZGVyKHsNCiAgICAgICAgJCRzYW5pdGl6ZVVyaTogJCRTYW5pdGl6ZVVyaVByb3ZpZGVyDQogICAgICB9KTsNCiAgICAgICRwcm92aWRlLnByb3ZpZGVyKCckY29tcGlsZScsICRDb21waWxlUHJvdmlkZXIpLg0KICAgICAgICBkaXJlY3RpdmUoew0KICAgICAgICAgICAgYTogaHRtbEFuY2hvckRpcmVjdGl2ZSwNCiAgICAgICAgICAgIGlucHV0OiBpbnB1dERpcmVjdGl2ZSwNCiAgICAgICAgICAgIHRleHRhcmVhOiBpbnB1dERpcmVjdGl2ZSwNCiAgICAgICAgICAgIGZvcm06IGZvcm1EaXJlY3RpdmUsDQogICAgICAgICAgICBzY3JpcHQ6IHNjcmlwdERpcmVjdGl2ZSwNCiAgICAgICAgICAgIHNlbGVjdDogc2VsZWN0RGlyZWN0aXZlLA0KICAgICAgICAgICAgc3R5bGU6IHN0eWxlRGlyZWN0aXZlLA0KICAgICAgICAgICAgb3B0aW9uOiBvcHRpb25EaXJlY3RpdmUsDQogICAgICAgICAgICBuZ0JpbmQ6IG5nQmluZERpcmVjdGl2ZSwNCiAgICAgICAgICAgIG5nQmluZEh0bWw6IG5nQmluZEh0bWxEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ0JpbmRUZW1wbGF0ZTogbmdCaW5kVGVtcGxhdGVEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ0NsYXNzOiBuZ0NsYXNzRGlyZWN0aXZlLA0KICAgICAgICAgICAgbmdDbGFzc0V2ZW46IG5nQ2xhc3NFdmVuRGlyZWN0aXZlLA0KICAgICAgICAgICAgbmdDbGFzc09kZDogbmdDbGFzc09kZERpcmVjdGl2ZSwNCiAgICAgICAgICAgIG5nQ2xvYWs6IG5nQ2xvYWtEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ0NvbnRyb2xsZXI6IG5nQ29udHJvbGxlckRpcmVjdGl2ZSwNCiAgICAgICAgICAgIG5nRm9ybTogbmdGb3JtRGlyZWN0aXZlLA0KICAgICAgICAgICAgbmdIaWRlOiBuZ0hpZGVEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ0lmOiBuZ0lmRGlyZWN0aXZlLA0KICAgICAgICAgICAgbmdJbmNsdWRlOiBuZ0luY2x1ZGVEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ0luaXQ6IG5nSW5pdERpcmVjdGl2ZSwNCiAgICAgICAgICAgIG5nTm9uQmluZGFibGU6IG5nTm9uQmluZGFibGVEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ1BsdXJhbGl6ZTogbmdQbHVyYWxpemVEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ1JlcGVhdDogbmdSZXBlYXREaXJlY3RpdmUsDQogICAgICAgICAgICBuZ1Nob3c6IG5nU2hvd0RpcmVjdGl2ZSwNCiAgICAgICAgICAgIG5nU3R5bGU6IG5nU3R5bGVEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ1N3aXRjaDogbmdTd2l0Y2hEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ1N3aXRjaFdoZW46IG5nU3dpdGNoV2hlbkRpcmVjdGl2ZSwNCiAgICAgICAgICAgIG5nU3dpdGNoRGVmYXVsdDogbmdTd2l0Y2hEZWZhdWx0RGlyZWN0aXZlLA0KICAgICAgICAgICAgbmdPcHRpb25zOiBuZ09wdGlvbnNEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ1RyYW5zY2x1ZGU6IG5nVHJhbnNjbHVkZURpcmVjdGl2ZSwNCiAgICAgICAgICAgIG5nTW9kZWw6IG5nTW9kZWxEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ0xpc3Q6IG5nTGlzdERpcmVjdGl2ZSwNCiAgICAgICAgICAgIG5nQ2hhbmdlOiBuZ0NoYW5nZURpcmVjdGl2ZSwNCiAgICAgICAgICAgIHBhdHRlcm46IHBhdHRlcm5EaXJlY3RpdmUsDQogICAgICAgICAgICBuZ1BhdHRlcm46IHBhdHRlcm5EaXJlY3RpdmUsDQogICAgICAgICAgICByZXF1aXJlZDogcmVxdWlyZWREaXJlY3RpdmUsDQogICAgICAgICAgICBuZ1JlcXVpcmVkOiByZXF1aXJlZERpcmVjdGl2ZSwNCiAgICAgICAgICAgIG1pbmxlbmd0aDogbWlubGVuZ3RoRGlyZWN0aXZlLA0KICAgICAgICAgICAgbmdNaW5sZW5ndGg6IG1pbmxlbmd0aERpcmVjdGl2ZSwNCiAgICAgICAgICAgIG1heGxlbmd0aDogbWF4bGVuZ3RoRGlyZWN0aXZlLA0KICAgICAgICAgICAgbmdNYXhsZW5ndGg6IG1heGxlbmd0aERpcmVjdGl2ZSwNCiAgICAgICAgICAgIG5nVmFsdWU6IG5nVmFsdWVEaXJlY3RpdmUsDQogICAgICAgICAgICBuZ01vZGVsT3B0aW9uczogbmdNb2RlbE9wdGlvbnNEaXJlY3RpdmUNCiAgICAgICAgfSkuDQogICAgICAgIGRpcmVjdGl2ZSh7DQogICAgICAgICAgbmdJbmNsdWRlOiBuZ0luY2x1ZGVGaWxsQ29udGVudERpcmVjdGl2ZQ0KICAgICAgICB9KS4NCiAgICAgICAgZGlyZWN0aXZlKG5nQXR0cmlidXRlQWxpYXNEaXJlY3RpdmVzKS4NCiAgICAgICAgZGlyZWN0aXZlKG5nRXZlbnREaXJlY3RpdmVzKTsNCiAgICAgICRwcm92aWRlLnByb3ZpZGVyKHsNCiAgICAgICAgJGFuY2hvclNjcm9sbDogJEFuY2hvclNjcm9sbFByb3ZpZGVyLA0KICAgICAgICAkYW5pbWF0ZTogJEFuaW1hdGVQcm92aWRlciwNCiAgICAgICAgJGJyb3dzZXI6ICRCcm93c2VyUHJvdmlkZXIsDQogICAgICAgICRjYWNoZUZhY3Rvcnk6ICRDYWNoZUZhY3RvcnlQcm92aWRlciwNCiAgICAgICAgJGNvbnRyb2xsZXI6ICRDb250cm9sbGVyUHJvdmlkZXIsDQogICAgICAgICRkb2N1bWVudDogJERvY3VtZW50UHJvdmlkZXIsDQogICAgICAgICRleGNlcHRpb25IYW5kbGVyOiAkRXhjZXB0aW9uSGFuZGxlclByb3ZpZGVyLA0KICAgICAgICAkZmlsdGVyOiAkRmlsdGVyUHJvdmlkZXIsDQogICAgICAgICRpbnRlcnBvbGF0ZTogJEludGVycG9sYXRlUHJvdmlkZXIsDQogICAgICAgICRpbnRlcnZhbDogJEludGVydmFsUHJvdmlkZXIsDQogICAgICAgICRodHRwOiAkSHR0cFByb3ZpZGVyLA0KICAgICAgICAkaHR0cEJhY2tlbmQ6ICRIdHRwQmFja2VuZFByb3ZpZGVyLA0KICAgICAgICAkbG9jYXRpb246ICRMb2NhdGlvblByb3ZpZGVyLA0KICAgICAgICAkbG9nOiAkTG9nUHJvdmlkZXIsDQogICAgICAgICRwYXJzZTogJFBhcnNlUHJvdmlkZXIsDQogICAgICAgICRyb290U2NvcGU6ICRSb290U2NvcGVQcm92aWRlciwNCiAgICAgICAgJHE6ICRRUHJvdmlkZXIsDQogICAgICAgICQkcTogJCRRUHJvdmlkZXIsDQogICAgICAgICRzY2U6ICRTY2VQcm92aWRlciwNCiAgICAgICAgJHNjZURlbGVnYXRlOiAkU2NlRGVsZWdhdGVQcm92aWRlciwNCiAgICAgICAgJHNuaWZmZXI6ICRTbmlmZmVyUHJvdmlkZXIsDQogICAgICAgICR0ZW1wbGF0ZUNhY2hlOiAkVGVtcGxhdGVDYWNoZVByb3ZpZGVyLA0KICAgICAgICAkdGVtcGxhdGVSZXF1ZXN0OiAkVGVtcGxhdGVSZXF1ZXN0UHJvdmlkZXIsDQogICAgICAgICQkdGVzdGFiaWxpdHk6ICQkVGVzdGFiaWxpdHlQcm92aWRlciwNCiAgICAgICAgJHRpbWVvdXQ6ICRUaW1lb3V0UHJvdmlkZXIsDQogICAgICAgICR3aW5kb3c6ICRXaW5kb3dQcm92aWRlciwNCiAgICAgICAgJCRyQUY6ICQkUkFGUHJvdmlkZXIsDQogICAgICAgICQkYXN5bmNDYWxsYmFjazogJCRBc3luY0NhbGxiYWNrUHJvdmlkZXIsDQogICAgICAgICQkanFMaXRlOiAkJGpxTGl0ZVByb3ZpZGVyDQogICAgICB9KTsNCiAgICB9DQogIF0pOw0KfQ0KDQovKiBnbG9iYWwgSlFMaXRlUHJvdG90eXBlOiB0cnVlLA0KICBhZGRFdmVudExpc3RlbmVyRm46IHRydWUsDQogIHJlbW92ZUV2ZW50TGlzdGVuZXJGbjogdHJ1ZSwNCiAgQk9PTEVBTl9BVFRSOiB0cnVlLA0KICBBTElBU0VEX0FUVFI6IHRydWUsDQoqLw0KDQovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vDQovL0pRTGl0ZQ0KLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KDQovKioNCiAqIEBuZ2RvYyBmdW5jdGlvbg0KICogQG5hbWUgYW5ndWxhci5lbGVtZW50DQogKiBAbW9kdWxlIG5nDQogKiBAa2luZCBmdW5jdGlvbg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogV3JhcHMgYSByYXcgRE9NIGVsZW1lbnQgb3IgSFRNTCBzdHJpbmcgYXMgYSBbalF1ZXJ5XShodHRwOi8vanF1ZXJ5LmNvbSkgZWxlbWVudC4NCiAqDQogKiBJZiBqUXVlcnkgaXMgYXZhaWxhYmxlLCBgYW5ndWxhci5lbGVtZW50YCBpcyBhbiBhbGlhcyBmb3IgdGhlDQogKiBbalF1ZXJ5XShodHRwOi8vYXBpLmpxdWVyeS5jb20valF1ZXJ5LykgZnVuY3Rpb24uIElmIGpRdWVyeSBpcyBub3QgYXZhaWxhYmxlLCBgYW5ndWxhci5lbGVtZW50YA0KICogZGVsZWdhdGVzIHRvIEFuZ3VsYXIncyBidWlsdC1pbiBzdWJzZXQgb2YgalF1ZXJ5LCBjYWxsZWQgImpRdWVyeSBsaXRlIiBvciAianFMaXRlLiINCiAqDQogKiA8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1zdWNjZXNzIj5qcUxpdGUgaXMgYSB0aW55LCBBUEktY29tcGF0aWJsZSBzdWJzZXQgb2YgalF1ZXJ5IHRoYXQgYWxsb3dzDQogKiBBbmd1bGFyIHRvIG1hbmlwdWxhdGUgdGhlIERPTSBpbiBhIGNyb3NzLWJyb3dzZXIgY29tcGF0aWJsZSB3YXkuICoqanFMaXRlKiogaW1wbGVtZW50cyBvbmx5IHRoZSBtb3N0DQogKiBjb21tb25seSBuZWVkZWQgZnVuY3Rpb25hbGl0eSB3aXRoIHRoZSBnb2FsIG9mIGhhdmluZyBhIHZlcnkgc21hbGwgZm9vdHByaW50LjwvZGl2Pg0KICoNCiAqIFRvIHVzZSBqUXVlcnksIHNpbXBseSBsb2FkIGl0IGJlZm9yZSBgRE9NQ29udGVudExvYWRlZGAgZXZlbnQgZmlyZWQuDQogKg0KICogPGRpdiBjbGFzcz0iYWxlcnQiPioqTm90ZToqKiBhbGwgZWxlbWVudCByZWZlcmVuY2VzIGluIEFuZ3VsYXIgYXJlIGFsd2F5cyB3cmFwcGVkIHdpdGggalF1ZXJ5IG9yDQogKiBqcUxpdGU7IHRoZXkgYXJlIG5ldmVyIHJhdyBET00gcmVmZXJlbmNlcy48L2Rpdj4NCiAqDQogKiAjIyBBbmd1bGFyJ3MganFMaXRlDQogKiBqcUxpdGUgcHJvdmlkZXMgb25seSB0aGUgZm9sbG93aW5nIGpRdWVyeSBtZXRob2RzOg0KICoNCiAqIC0gW2BhZGRDbGFzcygpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL2FkZENsYXNzLykNCiAqIC0gW2BhZnRlcigpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL2FmdGVyLykNCiAqIC0gW2BhcHBlbmQoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9hcHBlbmQvKQ0KICogLSBbYGF0dHIoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9hdHRyLykgLSBEb2VzIG5vdCBzdXBwb3J0IGZ1bmN0aW9ucyBhcyBwYXJhbWV0ZXJzDQogKiAtIFtgYmluZCgpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL2JpbmQvKSAtIERvZXMgbm90IHN1cHBvcnQgbmFtZXNwYWNlcywgc2VsZWN0b3JzIG9yIGV2ZW50RGF0YQ0KICogLSBbYGNoaWxkcmVuKClgXShodHRwOi8vYXBpLmpxdWVyeS5jb20vY2hpbGRyZW4vKSAtIERvZXMgbm90IHN1cHBvcnQgc2VsZWN0b3JzDQogKiAtIFtgY2xvbmUoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9jbG9uZS8pDQogKiAtIFtgY29udGVudHMoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9jb250ZW50cy8pDQogKiAtIFtgY3NzKClgXShodHRwOi8vYXBpLmpxdWVyeS5jb20vY3NzLykgLSBPbmx5IHJldHJpZXZlcyBpbmxpbmUtc3R5bGVzLCBkb2VzIG5vdCBjYWxsIGBnZXRDb21wdXRlZFN0eWxlKClgDQogKiAtIFtgZGF0YSgpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL2RhdGEvKQ0KICogLSBbYGRldGFjaCgpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL2RldGFjaC8pDQogKiAtIFtgZW1wdHkoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9lbXB0eS8pDQogKiAtIFtgZXEoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9lcS8pDQogKiAtIFtgZmluZCgpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL2ZpbmQvKSAtIExpbWl0ZWQgdG8gbG9va3VwcyBieSB0YWcgbmFtZQ0KICogLSBbYGhhc0NsYXNzKClgXShodHRwOi8vYXBpLmpxdWVyeS5jb20vaGFzQ2xhc3MvKQ0KICogLSBbYGh0bWwoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9odG1sLykNCiAqIC0gW2BuZXh0KClgXShodHRwOi8vYXBpLmpxdWVyeS5jb20vbmV4dC8pIC0gRG9lcyBub3Qgc3VwcG9ydCBzZWxlY3RvcnMNCiAqIC0gW2BvbigpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL29uLykgLSBEb2VzIG5vdCBzdXBwb3J0IG5hbWVzcGFjZXMsIHNlbGVjdG9ycyBvciBldmVudERhdGENCiAqIC0gW2BvZmYoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9vZmYvKSAtIERvZXMgbm90IHN1cHBvcnQgbmFtZXNwYWNlcyBvciBzZWxlY3RvcnMNCiAqIC0gW2BvbmUoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9vbmUvKSAtIERvZXMgbm90IHN1cHBvcnQgbmFtZXNwYWNlcyBvciBzZWxlY3RvcnMNCiAqIC0gW2BwYXJlbnQoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9wYXJlbnQvKSAtIERvZXMgbm90IHN1cHBvcnQgc2VsZWN0b3JzDQogKiAtIFtgcHJlcGVuZCgpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL3ByZXBlbmQvKQ0KICogLSBbYHByb3AoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9wcm9wLykNCiAqIC0gW2ByZWFkeSgpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL3JlYWR5LykNCiAqIC0gW2ByZW1vdmUoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9yZW1vdmUvKQ0KICogLSBbYHJlbW92ZUF0dHIoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9yZW1vdmVBdHRyLykNCiAqIC0gW2ByZW1vdmVDbGFzcygpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL3JlbW92ZUNsYXNzLykNCiAqIC0gW2ByZW1vdmVEYXRhKClgXShodHRwOi8vYXBpLmpxdWVyeS5jb20vcmVtb3ZlRGF0YS8pDQogKiAtIFtgcmVwbGFjZVdpdGgoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS9yZXBsYWNlV2l0aC8pDQogKiAtIFtgdGV4dCgpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL3RleHQvKQ0KICogLSBbYHRvZ2dsZUNsYXNzKClgXShodHRwOi8vYXBpLmpxdWVyeS5jb20vdG9nZ2xlQ2xhc3MvKQ0KICogLSBbYHRyaWdnZXJIYW5kbGVyKClgXShodHRwOi8vYXBpLmpxdWVyeS5jb20vdHJpZ2dlckhhbmRsZXIvKSAtIFBhc3NlcyBhIGR1bW15IGV2ZW50IG9iamVjdCB0byBoYW5kbGVycy4NCiAqIC0gW2B1bmJpbmQoKWBdKGh0dHA6Ly9hcGkuanF1ZXJ5LmNvbS91bmJpbmQvKSAtIERvZXMgbm90IHN1cHBvcnQgbmFtZXNwYWNlcw0KICogLSBbYHZhbCgpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL3ZhbC8pDQogKiAtIFtgd3JhcCgpYF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL3dyYXAvKQ0KICoNCiAqICMjIGpRdWVyeS9qcUxpdGUgRXh0cmFzDQogKiBBbmd1bGFyIGFsc28gcHJvdmlkZXMgdGhlIGZvbGxvd2luZyBhZGRpdGlvbmFsIG1ldGhvZHMgYW5kIGV2ZW50cyB0byBib3RoIGpRdWVyeSBhbmQganFMaXRlOg0KICoNCiAqICMjIyBFdmVudHMNCiAqIC0gYCRkZXN0cm95YCAtIEFuZ3VsYXJKUyBpbnRlcmNlcHRzIGFsbCBqcUxpdGUvalF1ZXJ5J3MgRE9NIGRlc3RydWN0aW9uIGFwaXMgYW5kIGZpcmVzIHRoaXMgZXZlbnQNCiAqICAgIG9uIGFsbCBET00gbm9kZXMgYmVpbmcgcmVtb3ZlZC4gIFRoaXMgY2FuIGJlIHVzZWQgdG8gY2xlYW4gdXAgYW55IDNyZCBwYXJ0eSBiaW5kaW5ncyB0byB0aGUgRE9NDQogKiAgICBlbGVtZW50IGJlZm9yZSBpdCBpcyByZW1vdmVkLg0KICoNCiAqICMjIyBNZXRob2RzDQogKiAtIGBjb250cm9sbGVyKG5hbWUpYCAtIHJldHJpZXZlcyB0aGUgY29udHJvbGxlciBvZiB0aGUgY3VycmVudCBlbGVtZW50IG9yIGl0cyBwYXJlbnQuIEJ5IGRlZmF1bHQNCiAqICAgcmV0cmlldmVzIGNvbnRyb2xsZXIgYXNzb2NpYXRlZCB3aXRoIHRoZSBgbmdDb250cm9sbGVyYCBkaXJlY3RpdmUuIElmIGBuYW1lYCBpcyBwcm92aWRlZCBhcw0KICogICBjYW1lbENhc2UgZGlyZWN0aXZlIG5hbWUsIHRoZW4gdGhlIGNvbnRyb2xsZXIgZm9yIHRoaXMgZGlyZWN0aXZlIHdpbGwgYmUgcmV0cmlldmVkIChlLmcuDQogKiAgIGAnbmdNb2RlbCdgKS4NCiAqIC0gYGluamVjdG9yKClgIC0gcmV0cmlldmVzIHRoZSBpbmplY3RvciBvZiB0aGUgY3VycmVudCBlbGVtZW50IG9yIGl0cyBwYXJlbnQuDQogKiAtIGBzY29wZSgpYCAtIHJldHJpZXZlcyB0aGUge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUgc2NvcGV9IG9mIHRoZSBjdXJyZW50DQogKiAgIGVsZW1lbnQgb3IgaXRzIHBhcmVudC4gUmVxdWlyZXMge0BsaW5rIGd1aWRlL3Byb2R1Y3Rpb24jZGlzYWJsaW5nLWRlYnVnLWRhdGEgRGVidWcgRGF0YX0gdG8NCiAqICAgYmUgZW5hYmxlZC4NCiAqIC0gYGlzb2xhdGVTY29wZSgpYCAtIHJldHJpZXZlcyBhbiBpc29sYXRlIHtAbGluayBuZy4kcm9vdFNjb3BlLlNjb3BlIHNjb3BlfSBpZiBvbmUgaXMgYXR0YWNoZWQgZGlyZWN0bHkgdG8gdGhlDQogKiAgIGN1cnJlbnQgZWxlbWVudC4gVGhpcyBnZXR0ZXIgc2hvdWxkIGJlIHVzZWQgb25seSBvbiBlbGVtZW50cyB0aGF0IGNvbnRhaW4gYSBkaXJlY3RpdmUgd2hpY2ggc3RhcnRzIGEgbmV3IGlzb2xhdGUNCiAqICAgc2NvcGUuIENhbGxpbmcgYHNjb3BlKClgIG9uIHRoaXMgZWxlbWVudCBhbHdheXMgcmV0dXJucyB0aGUgb3JpZ2luYWwgbm9uLWlzb2xhdGUgc2NvcGUuDQogKiAgIFJlcXVpcmVzIHtAbGluayBndWlkZS9wcm9kdWN0aW9uI2Rpc2FibGluZy1kZWJ1Zy1kYXRhIERlYnVnIERhdGF9IHRvIGJlIGVuYWJsZWQuDQogKiAtIGBpbmhlcml0ZWREYXRhKClgIC0gc2FtZSBhcyBgZGF0YSgpYCwgYnV0IHdhbGtzIHVwIHRoZSBET00gdW50aWwgYSB2YWx1ZSBpcyBmb3VuZCBvciB0aGUgdG9wDQogKiAgIHBhcmVudCBlbGVtZW50IGlzIHJlYWNoZWQuDQogKg0KICogQHBhcmFtIHtzdHJpbmd8RE9NRWxlbWVudH0gZWxlbWVudCBIVE1MIHN0cmluZyBvciBET01FbGVtZW50IHRvIGJlIHdyYXBwZWQgaW50byBqUXVlcnkuDQogKiBAcmV0dXJucyB7T2JqZWN0fSBqUXVlcnkgb2JqZWN0Lg0KICovDQoNCkpRTGl0ZS5leHBhbmRvID0gJ25nMzM5JzsNCg0KdmFyIGpxQ2FjaGUgPSBKUUxpdGUuY2FjaGUgPSB7fSwNCiAgICBqcUlkID0gMSwNCiAgICBhZGRFdmVudExpc3RlbmVyRm4gPSBmdW5jdGlvbihlbGVtZW50LCB0eXBlLCBmbikgew0KICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGZuLCBmYWxzZSk7DQogICAgfSwNCiAgICByZW1vdmVFdmVudExpc3RlbmVyRm4gPSBmdW5jdGlvbihlbGVtZW50LCB0eXBlLCBmbikgew0KICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGZuLCBmYWxzZSk7DQogICAgfTsNCg0KLyoNCiAqICEhISBUaGlzIGlzIGFuIHVuZG9jdW1lbnRlZCAicHJpdmF0ZSIgZnVuY3Rpb24gISEhDQogKi8NCkpRTGl0ZS5fZGF0YSA9IGZ1bmN0aW9uKG5vZGUpIHsNCiAgLy9qUXVlcnkgYWx3YXlzIHJldHVybnMgYW4gb2JqZWN0IG9uIGNhY2hlIG1pc3MNCiAgcmV0dXJuIHRoaXMuY2FjaGVbbm9kZVt0aGlzLmV4cGFuZG9dXSB8fCB7fTsNCn07DQoNCmZ1bmN0aW9uIGpxTmV4dElkKCkgeyByZXR1cm4gKytqcUlkOyB9DQoNCg0KdmFyIFNQRUNJQUxfQ0hBUlNfUkVHRVhQID0gLyhbXDpcLVxfXSsoLikpL2c7DQp2YXIgTU9aX0hBQ0tfUkVHRVhQID0gL15tb3ooW0EtWl0pLzsNCnZhciBNT1VTRV9FVkVOVF9NQVA9IHsgbW91c2VsZWF2ZTogIm1vdXNlb3V0IiwgbW91c2VlbnRlcjogIm1vdXNlb3ZlciJ9Ow0KdmFyIGpxTGl0ZU1pbkVyciA9IG1pbkVycignanFMaXRlJyk7DQoNCi8qKg0KICogQ29udmVydHMgc25ha2VfY2FzZSB0byBjYW1lbENhc2UuDQogKiBBbHNvIHRoZXJlIGlzIHNwZWNpYWwgY2FzZSBmb3IgTW96IHByZWZpeCBzdGFydGluZyB3aXRoIHVwcGVyIGNhc2UgbGV0dGVyLg0KICogQHBhcmFtIG5hbWUgTmFtZSB0byBub3JtYWxpemUNCiAqLw0KZnVuY3Rpb24gY2FtZWxDYXNlKG5hbWUpIHsNCiAgcmV0dXJuIG5hbWUuDQogICAgcmVwbGFjZShTUEVDSUFMX0NIQVJTX1JFR0VYUCwgZnVuY3Rpb24oXywgc2VwYXJhdG9yLCBsZXR0ZXIsIG9mZnNldCkgew0KICAgICAgcmV0dXJuIG9mZnNldCA/IGxldHRlci50b1VwcGVyQ2FzZSgpIDogbGV0dGVyOw0KICAgIH0pLg0KICAgIHJlcGxhY2UoTU9aX0hBQ0tfUkVHRVhQLCAnTW96JDEnKTsNCn0NCg0KdmFyIFNJTkdMRV9UQUdfUkVHRVhQID0gL148KFx3KylccypcLz8+KD86PFwvXDE+fCkkLzsNCnZhciBIVE1MX1JFR0VYUCA9IC88fCYjP1x3KzsvOw0KdmFyIFRBR19OQU1FX1JFR0VYUCA9IC88KFtcdzpdKykvOw0KdmFyIFhIVE1MX1RBR19SRUdFWFAgPSAvPCg/IWFyZWF8YnJ8Y29sfGVtYmVkfGhyfGltZ3xpbnB1dHxsaW5rfG1ldGF8cGFyYW0pKChbXHc6XSspW14+XSopXC8+L2dpOw0KDQp2YXIgd3JhcE1hcCA9IHsNCiAgJ29wdGlvbic6IFsxLCAnPHNlbGVjdCBtdWx0aXBsZT0ibXVsdGlwbGUiPicsICc8L3NlbGVjdD4nXSwNCg0KICAndGhlYWQnOiBbMSwgJzx0YWJsZT4nLCAnPC90YWJsZT4nXSwNCiAgJ2NvbCc6IFsyLCAnPHRhYmxlPjxjb2xncm91cD4nLCAnPC9jb2xncm91cD48L3RhYmxlPiddLA0KICAndHInOiBbMiwgJzx0YWJsZT48dGJvZHk+JywgJzwvdGJvZHk+PC90YWJsZT4nXSwNCiAgJ3RkJzogWzMsICc8dGFibGU+PHRib2R5Pjx0cj4nLCAnPC90cj48L3Rib2R5PjwvdGFibGU+J10sDQogICdfZGVmYXVsdCc6IFswLCAiIiwgIiJdDQp9Ow0KDQp3cmFwTWFwLm9wdGdyb3VwID0gd3JhcE1hcC5vcHRpb247DQp3cmFwTWFwLnRib2R5ID0gd3JhcE1hcC50Zm9vdCA9IHdyYXBNYXAuY29sZ3JvdXAgPSB3cmFwTWFwLmNhcHRpb24gPSB3cmFwTWFwLnRoZWFkOw0Kd3JhcE1hcC50aCA9IHdyYXBNYXAudGQ7DQoNCg0KZnVuY3Rpb24ganFMaXRlSXNUZXh0Tm9kZShodG1sKSB7DQogIHJldHVybiAhSFRNTF9SRUdFWFAudGVzdChodG1sKTsNCn0NCg0KZnVuY3Rpb24ganFMaXRlQWNjZXB0c0RhdGEobm9kZSkgew0KICAvLyBUaGUgd2luZG93IG9iamVjdCBjYW4gYWNjZXB0IGRhdGEgYnV0IGhhcyBubyBub2RlVHlwZQ0KICAvLyBPdGhlcndpc2Ugd2UgYXJlIG9ubHkgaW50ZXJlc3RlZCBpbiBlbGVtZW50cyAoMSkgYW5kIGRvY3VtZW50cyAoOSkNCiAgdmFyIG5vZGVUeXBlID0gbm9kZS5ub2RlVHlwZTsNCiAgcmV0dXJuIG5vZGVUeXBlID09PSBOT0RFX1RZUEVfRUxFTUVOVCB8fCAhbm9kZVR5cGUgfHwgbm9kZVR5cGUgPT09IE5PREVfVFlQRV9ET0NVTUVOVDsNCn0NCg0KZnVuY3Rpb24ganFMaXRlQnVpbGRGcmFnbWVudChodG1sLCBjb250ZXh0KSB7DQogIHZhciB0bXAsIHRhZywgd3JhcCwNCiAgICAgIGZyYWdtZW50ID0gY29udGV4dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCksDQogICAgICBub2RlcyA9IFtdLCBpOw0KDQogIGlmIChqcUxpdGVJc1RleHROb2RlKGh0bWwpKSB7DQogICAgLy8gQ29udmVydCBub24taHRtbCBpbnRvIGEgdGV4dCBub2RlDQogICAgbm9kZXMucHVzaChjb250ZXh0LmNyZWF0ZVRleHROb2RlKGh0bWwpKTsNCiAgfSBlbHNlIHsNCiAgICAvLyBDb252ZXJ0IGh0bWwgaW50byBET00gbm9kZXMNCiAgICB0bXAgPSB0bXAgfHwgZnJhZ21lbnQuYXBwZW5kQ2hpbGQoY29udGV4dC5jcmVhdGVFbGVtZW50KCJkaXYiKSk7DQogICAgdGFnID0gKFRBR19OQU1FX1JFR0VYUC5leGVjKGh0bWwpIHx8IFsiIiwgIiJdKVsxXS50b0xvd2VyQ2FzZSgpOw0KICAgIHdyYXAgPSB3cmFwTWFwW3RhZ10gfHwgd3JhcE1hcC5fZGVmYXVsdDsNCiAgICB0bXAuaW5uZXJIVE1MID0gd3JhcFsxXSArIGh0bWwucmVwbGFjZShYSFRNTF9UQUdfUkVHRVhQLCAiPCQxPjwvJDI+IikgKyB3cmFwWzJdOw0KDQogICAgLy8gRGVzY2VuZCB0aHJvdWdoIHdyYXBwZXJzIHRvIHRoZSByaWdodCBjb250ZW50DQogICAgaSA9IHdyYXBbMF07DQogICAgd2hpbGUgKGktLSkgew0KICAgICAgdG1wID0gdG1wLmxhc3RDaGlsZDsNCiAgICB9DQoNCiAgICBub2RlcyA9IGNvbmNhdChub2RlcywgdG1wLmNoaWxkTm9kZXMpOw0KDQogICAgdG1wID0gZnJhZ21lbnQuZmlyc3RDaGlsZDsNCiAgICB0bXAudGV4dENvbnRlbnQgPSAiIjsNCiAgfQ0KDQogIC8vIFJlbW92ZSB3cmFwcGVyIGZyb20gZnJhZ21lbnQNCiAgZnJhZ21lbnQudGV4dENvbnRlbnQgPSAiIjsNCiAgZnJhZ21lbnQuaW5uZXJIVE1MID0gIiI7IC8vIENsZWFyIGlubmVyIEhUTUwNCiAgZm9yRWFjaChub2RlcywgZnVuY3Rpb24obm9kZSkgew0KICAgIGZyYWdtZW50LmFwcGVuZENoaWxkKG5vZGUpOw0KICB9KTsNCg0KICByZXR1cm4gZnJhZ21lbnQ7DQp9DQoNCmZ1bmN0aW9uIGpxTGl0ZVBhcnNlSFRNTChodG1sLCBjb250ZXh0KSB7DQogIGNvbnRleHQgPSBjb250ZXh0IHx8IGRvY3VtZW50Ow0KICB2YXIgcGFyc2VkOw0KDQogIGlmICgocGFyc2VkID0gU0lOR0xFX1RBR19SRUdFWFAuZXhlYyhodG1sKSkpIHsNCiAgICByZXR1cm4gW2NvbnRleHQuY3JlYXRlRWxlbWVudChwYXJzZWRbMV0pXTsNCiAgfQ0KDQogIGlmICgocGFyc2VkID0ganFMaXRlQnVpbGRGcmFnbWVudChodG1sLCBjb250ZXh0KSkpIHsNCiAgICByZXR1cm4gcGFyc2VkLmNoaWxkTm9kZXM7DQogIH0NCg0KICByZXR1cm4gW107DQp9DQoNCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KZnVuY3Rpb24gSlFMaXRlKGVsZW1lbnQpIHsNCiAgaWYgKGVsZW1lbnQgaW5zdGFuY2VvZiBKUUxpdGUpIHsNCiAgICByZXR1cm4gZWxlbWVudDsNCiAgfQ0KDQogIHZhciBhcmdJc1N0cmluZzsNCg0KICBpZiAoaXNTdHJpbmcoZWxlbWVudCkpIHsNCiAgICBlbGVtZW50ID0gdHJpbShlbGVtZW50KTsNCiAgICBhcmdJc1N0cmluZyA9IHRydWU7DQogIH0NCiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEpRTGl0ZSkpIHsNCiAgICBpZiAoYXJnSXNTdHJpbmcgJiYgZWxlbWVudC5jaGFyQXQoMCkgIT0gJzwnKSB7DQogICAgICB0aHJvdyBqcUxpdGVNaW5FcnIoJ25vc2VsJywgJ0xvb2tpbmcgdXAgZWxlbWVudHMgdmlhIHNlbGVjdG9ycyBpcyBub3Qgc3VwcG9ydGVkIGJ5IGpxTGl0ZSEgU2VlOiBodHRwOi8vZG9jcy5hbmd1bGFyanMub3JnL2FwaS9hbmd1bGFyLmVsZW1lbnQnKTsNCiAgICB9DQogICAgcmV0dXJuIG5ldyBKUUxpdGUoZWxlbWVudCk7DQogIH0NCg0KICBpZiAoYXJnSXNTdHJpbmcpIHsNCiAgICBqcUxpdGVBZGROb2Rlcyh0aGlzLCBqcUxpdGVQYXJzZUhUTUwoZWxlbWVudCkpOw0KICB9IGVsc2Ugew0KICAgIGpxTGl0ZUFkZE5vZGVzKHRoaXMsIGVsZW1lbnQpOw0KICB9DQp9DQoNCmZ1bmN0aW9uIGpxTGl0ZUNsb25lKGVsZW1lbnQpIHsNCiAgcmV0dXJuIGVsZW1lbnQuY2xvbmVOb2RlKHRydWUpOw0KfQ0KDQpmdW5jdGlvbiBqcUxpdGVEZWFsb2MoZWxlbWVudCwgb25seURlc2NlbmRhbnRzKSB7DQogIGlmICghb25seURlc2NlbmRhbnRzKSBqcUxpdGVSZW1vdmVEYXRhKGVsZW1lbnQpOw0KDQogIGlmIChlbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwpIHsNCiAgICB2YXIgZGVzY2VuZGFudHMgPSBlbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJyonKTsNCiAgICBmb3IgKHZhciBpID0gMCwgbCA9IGRlc2NlbmRhbnRzLmxlbmd0aDsgaSA8IGw7IGkrKykgew0KICAgICAganFMaXRlUmVtb3ZlRGF0YShkZXNjZW5kYW50c1tpXSk7DQogICAgfQ0KICB9DQp9DQoNCmZ1bmN0aW9uIGpxTGl0ZU9mZihlbGVtZW50LCB0eXBlLCBmbiwgdW5zdXBwb3J0ZWQpIHsNCiAgaWYgKGlzRGVmaW5lZCh1bnN1cHBvcnRlZCkpIHRocm93IGpxTGl0ZU1pbkVycignb2ZmYXJncycsICdqcUxpdGUjb2ZmKCkgZG9lcyBub3Qgc3VwcG9ydCB0aGUgYHNlbGVjdG9yYCBhcmd1bWVudCcpOw0KDQogIHZhciBleHBhbmRvU3RvcmUgPSBqcUxpdGVFeHBhbmRvU3RvcmUoZWxlbWVudCk7DQogIHZhciBldmVudHMgPSBleHBhbmRvU3RvcmUgJiYgZXhwYW5kb1N0b3JlLmV2ZW50czsNCiAgdmFyIGhhbmRsZSA9IGV4cGFuZG9TdG9yZSAmJiBleHBhbmRvU3RvcmUuaGFuZGxlOw0KDQogIGlmICghaGFuZGxlKSByZXR1cm47IC8vbm8gbGlzdGVuZXJzIHJlZ2lzdGVyZWQNCg0KICBpZiAoIXR5cGUpIHsNCiAgICBmb3IgKHR5cGUgaW4gZXZlbnRzKSB7DQogICAgICBpZiAodHlwZSAhPT0gJyRkZXN0cm95Jykgew0KICAgICAgICByZW1vdmVFdmVudExpc3RlbmVyRm4oZWxlbWVudCwgdHlwZSwgaGFuZGxlKTsNCiAgICAgIH0NCiAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07DQogICAgfQ0KICB9IGVsc2Ugew0KICAgIGZvckVhY2godHlwZS5zcGxpdCgnICcpLCBmdW5jdGlvbih0eXBlKSB7DQogICAgICBpZiAoaXNEZWZpbmVkKGZuKSkgew0KICAgICAgICB2YXIgbGlzdGVuZXJGbnMgPSBldmVudHNbdHlwZV07DQogICAgICAgIGFycmF5UmVtb3ZlKGxpc3RlbmVyRm5zIHx8IFtdLCBmbik7DQogICAgICAgIGlmIChsaXN0ZW5lckZucyAmJiBsaXN0ZW5lckZucy5sZW5ndGggPiAwKSB7DQogICAgICAgICAgcmV0dXJuOw0KICAgICAgICB9DQogICAgICB9DQoNCiAgICAgIHJlbW92ZUV2ZW50TGlzdGVuZXJGbihlbGVtZW50LCB0eXBlLCBoYW5kbGUpOw0KICAgICAgZGVsZXRlIGV2ZW50c1t0eXBlXTsNCiAgICB9KTsNCiAgfQ0KfQ0KDQpmdW5jdGlvbiBqcUxpdGVSZW1vdmVEYXRhKGVsZW1lbnQsIG5hbWUpIHsNCiAgdmFyIGV4cGFuZG9JZCA9IGVsZW1lbnQubmczMzk7DQogIHZhciBleHBhbmRvU3RvcmUgPSBleHBhbmRvSWQgJiYganFDYWNoZVtleHBhbmRvSWRdOw0KDQogIGlmIChleHBhbmRvU3RvcmUpIHsNCiAgICBpZiAobmFtZSkgew0KICAgICAgZGVsZXRlIGV4cGFuZG9TdG9yZS5kYXRhW25hbWVdOw0KICAgICAgcmV0dXJuOw0KICAgIH0NCg0KICAgIGlmIChleHBhbmRvU3RvcmUuaGFuZGxlKSB7DQogICAgICBpZiAoZXhwYW5kb1N0b3JlLmV2ZW50cy4kZGVzdHJveSkgew0KICAgICAgICBleHBhbmRvU3RvcmUuaGFuZGxlKHt9LCAnJGRlc3Ryb3knKTsNCiAgICAgIH0NCiAgICAgIGpxTGl0ZU9mZihlbGVtZW50KTsNCiAgICB9DQogICAgZGVsZXRlIGpxQ2FjaGVbZXhwYW5kb0lkXTsNCiAgICBlbGVtZW50Lm5nMzM5ID0gdW5kZWZpbmVkOyAvLyBkb24ndCBkZWxldGUgRE9NIGV4cGFuZG9zLiBJRSBhbmQgQ2hyb21lIGRvbid0IGxpa2UgaXQNCiAgfQ0KfQ0KDQoNCmZ1bmN0aW9uIGpxTGl0ZUV4cGFuZG9TdG9yZShlbGVtZW50LCBjcmVhdGVJZk5lY2Vzc2FyeSkgew0KICB2YXIgZXhwYW5kb0lkID0gZWxlbWVudC5uZzMzOSwNCiAgICAgIGV4cGFuZG9TdG9yZSA9IGV4cGFuZG9JZCAmJiBqcUNhY2hlW2V4cGFuZG9JZF07DQoNCiAgaWYgKGNyZWF0ZUlmTmVjZXNzYXJ5ICYmICFleHBhbmRvU3RvcmUpIHsNCiAgICBlbGVtZW50Lm5nMzM5ID0gZXhwYW5kb0lkID0ganFOZXh0SWQoKTsNCiAgICBleHBhbmRvU3RvcmUgPSBqcUNhY2hlW2V4cGFuZG9JZF0gPSB7ZXZlbnRzOiB7fSwgZGF0YToge30sIGhhbmRsZTogdW5kZWZpbmVkfTsNCiAgfQ0KDQogIHJldHVybiBleHBhbmRvU3RvcmU7DQp9DQoNCg0KZnVuY3Rpb24ganFMaXRlRGF0YShlbGVtZW50LCBrZXksIHZhbHVlKSB7DQogIGlmIChqcUxpdGVBY2NlcHRzRGF0YShlbGVtZW50KSkgew0KDQogICAgdmFyIGlzU2ltcGxlU2V0dGVyID0gaXNEZWZpbmVkKHZhbHVlKTsNCiAgICB2YXIgaXNTaW1wbGVHZXR0ZXIgPSAhaXNTaW1wbGVTZXR0ZXIgJiYga2V5ICYmICFpc09iamVjdChrZXkpOw0KICAgIHZhciBtYXNzR2V0dGVyID0gIWtleTsNCiAgICB2YXIgZXhwYW5kb1N0b3JlID0ganFMaXRlRXhwYW5kb1N0b3JlKGVsZW1lbnQsICFpc1NpbXBsZUdldHRlcik7DQogICAgdmFyIGRhdGEgPSBleHBhbmRvU3RvcmUgJiYgZXhwYW5kb1N0b3JlLmRhdGE7DQoNCiAgICBpZiAoaXNTaW1wbGVTZXR0ZXIpIHsgLy8gZGF0YSgna2V5JywgdmFsdWUpDQogICAgICBkYXRhW2tleV0gPSB2YWx1ZTsNCiAgICB9IGVsc2Ugew0KICAgICAgaWYgKG1hc3NHZXR0ZXIpIHsgIC8vIGRhdGEoKQ0KICAgICAgICByZXR1cm4gZGF0YTsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIGlmIChpc1NpbXBsZUdldHRlcikgeyAvLyBkYXRhKCdrZXknKQ0KICAgICAgICAgIC8vIGRvbid0IGZvcmNlIGNyZWF0aW9uIG9mIGV4cGFuZG9TdG9yZSBpZiBpdCBkb2Vzbid0IGV4aXN0IHlldA0KICAgICAgICAgIHJldHVybiBkYXRhICYmIGRhdGFba2V5XTsNCiAgICAgICAgfSBlbHNlIHsgLy8gbWFzcy1zZXR0ZXI6IGRhdGEoe2tleTE6IHZhbDEsIGtleTI6IHZhbDJ9KQ0KICAgICAgICAgIGV4dGVuZChkYXRhLCBrZXkpOw0KICAgICAgICB9DQogICAgICB9DQogICAgfQ0KICB9DQp9DQoNCmZ1bmN0aW9uIGpxTGl0ZUhhc0NsYXNzKGVsZW1lbnQsIHNlbGVjdG9yKSB7DQogIGlmICghZWxlbWVudC5nZXRBdHRyaWJ1dGUpIHJldHVybiBmYWxzZTsNCiAgcmV0dXJuICgoIiAiICsgKGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdjbGFzcycpIHx8ICcnKSArICIgIikucmVwbGFjZSgvW1xuXHRdL2csICIgIikuDQogICAgICBpbmRleE9mKCIgIiArIHNlbGVjdG9yICsgIiAiKSA+IC0xKTsNCn0NCg0KZnVuY3Rpb24ganFMaXRlUmVtb3ZlQ2xhc3MoZWxlbWVudCwgY3NzQ2xhc3Nlcykgew0KICBpZiAoY3NzQ2xhc3NlcyAmJiBlbGVtZW50LnNldEF0dHJpYnV0ZSkgew0KICAgIGZvckVhY2goY3NzQ2xhc3Nlcy5zcGxpdCgnICcpLCBmdW5jdGlvbihjc3NDbGFzcykgew0KICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgdHJpbSgNCiAgICAgICAgICAoIiAiICsgKGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdjbGFzcycpIHx8ICcnKSArICIgIikNCiAgICAgICAgICAucmVwbGFjZSgvW1xuXHRdL2csICIgIikNCiAgICAgICAgICAucmVwbGFjZSgiICIgKyB0cmltKGNzc0NsYXNzKSArICIgIiwgIiAiKSkNCiAgICAgICk7DQogICAgfSk7DQogIH0NCn0NCg0KZnVuY3Rpb24ganFMaXRlQWRkQ2xhc3MoZWxlbWVudCwgY3NzQ2xhc3Nlcykgew0KICBpZiAoY3NzQ2xhc3NlcyAmJiBlbGVtZW50LnNldEF0dHJpYnV0ZSkgew0KICAgIHZhciBleGlzdGluZ0NsYXNzZXMgPSAoJyAnICsgKGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdjbGFzcycpIHx8ICcnKSArICcgJykNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvW1xuXHRdL2csICIgIik7DQoNCiAgICBmb3JFYWNoKGNzc0NsYXNzZXMuc3BsaXQoJyAnKSwgZnVuY3Rpb24oY3NzQ2xhc3MpIHsNCiAgICAgIGNzc0NsYXNzID0gdHJpbShjc3NDbGFzcyk7DQogICAgICBpZiAoZXhpc3RpbmdDbGFzc2VzLmluZGV4T2YoJyAnICsgY3NzQ2xhc3MgKyAnICcpID09PSAtMSkgew0KICAgICAgICBleGlzdGluZ0NsYXNzZXMgKz0gY3NzQ2xhc3MgKyAnICc7DQogICAgICB9DQogICAgfSk7DQoNCiAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCB0cmltKGV4aXN0aW5nQ2xhc3NlcykpOw0KICB9DQp9DQoNCg0KZnVuY3Rpb24ganFMaXRlQWRkTm9kZXMocm9vdCwgZWxlbWVudHMpIHsNCiAgLy8gVEhJUyBDT0RFIElTIFZFUlkgSE9ULiBEb24ndCBtYWtlIGNoYW5nZXMgd2l0aG91dCBiZW5jaG1hcmtpbmcuDQoNCiAgaWYgKGVsZW1lbnRzKSB7DQoNCiAgICAvLyBpZiBhIE5vZGUgKHRoZSBtb3N0IGNvbW1vbiBjYXNlKQ0KICAgIGlmIChlbGVtZW50cy5ub2RlVHlwZSkgew0KICAgICAgcm9vdFtyb290Lmxlbmd0aCsrXSA9IGVsZW1lbnRzOw0KICAgIH0gZWxzZSB7DQogICAgICB2YXIgbGVuZ3RoID0gZWxlbWVudHMubGVuZ3RoOw0KDQogICAgICAvLyBpZiBhbiBBcnJheSBvciBOb2RlTGlzdCBhbmQgbm90IGEgV2luZG93DQogICAgICBpZiAodHlwZW9mIGxlbmd0aCA9PT0gJ251bWJlcicgJiYgZWxlbWVudHMud2luZG93ICE9PSBlbGVtZW50cykgew0KICAgICAgICBpZiAobGVuZ3RoKSB7DQogICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgew0KICAgICAgICAgICAgcm9vdFtyb290Lmxlbmd0aCsrXSA9IGVsZW1lbnRzW2ldOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgcm9vdFtyb290Lmxlbmd0aCsrXSA9IGVsZW1lbnRzOw0KICAgICAgfQ0KICAgIH0NCiAgfQ0KfQ0KDQoNCmZ1bmN0aW9uIGpxTGl0ZUNvbnRyb2xsZXIoZWxlbWVudCwgbmFtZSkgew0KICByZXR1cm4ganFMaXRlSW5oZXJpdGVkRGF0YShlbGVtZW50LCAnJCcgKyAobmFtZSB8fCAnbmdDb250cm9sbGVyJykgKyAnQ29udHJvbGxlcicpOw0KfQ0KDQpmdW5jdGlvbiBqcUxpdGVJbmhlcml0ZWREYXRhKGVsZW1lbnQsIG5hbWUsIHZhbHVlKSB7DQogIC8vIGlmIGVsZW1lbnQgaXMgdGhlIGRvY3VtZW50IG9iamVjdCB3b3JrIHdpdGggdGhlIGh0bWwgZWxlbWVudCBpbnN0ZWFkDQogIC8vIHRoaXMgbWFrZXMgJChkb2N1bWVudCkuc2NvcGUoKSBwb3NzaWJsZQ0KICBpZiAoZWxlbWVudC5ub2RlVHlwZSA9PSBOT0RFX1RZUEVfRE9DVU1FTlQpIHsNCiAgICBlbGVtZW50ID0gZWxlbWVudC5kb2N1bWVudEVsZW1lbnQ7DQogIH0NCiAgdmFyIG5hbWVzID0gaXNBcnJheShuYW1lKSA/IG5hbWUgOiBbbmFtZV07DQoNCiAgd2hpbGUgKGVsZW1lbnQpIHsNCiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBuYW1lcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7DQogICAgICBpZiAoKHZhbHVlID0ganFMaXRlLmRhdGEoZWxlbWVudCwgbmFtZXNbaV0pKSAhPT0gdW5kZWZpbmVkKSByZXR1cm4gdmFsdWU7DQogICAgfQ0KDQogICAgLy8gSWYgZGVhbGluZyB3aXRoIGEgZG9jdW1lbnQgZnJhZ21lbnQgbm9kZSB3aXRoIGEgaG9zdCBlbGVtZW50LCBhbmQgbm8gcGFyZW50LCB1c2UgdGhlIGhvc3QNCiAgICAvLyBlbGVtZW50IGFzIHRoZSBwYXJlbnQuIFRoaXMgZW5hYmxlcyBkaXJlY3RpdmVzIHdpdGhpbiBhIFNoYWRvdyBET00gb3IgcG9seWZpbGxlZCBTaGFkb3cgRE9NDQogICAgLy8gdG8gbG9va3VwIHBhcmVudCBjb250cm9sbGVycy4NCiAgICBlbGVtZW50ID0gZWxlbWVudC5wYXJlbnROb2RlIHx8IChlbGVtZW50Lm5vZGVUeXBlID09PSBOT0RFX1RZUEVfRE9DVU1FTlRfRlJBR01FTlQgJiYgZWxlbWVudC5ob3N0KTsNCiAgfQ0KfQ0KDQpmdW5jdGlvbiBqcUxpdGVFbXB0eShlbGVtZW50KSB7DQogIGpxTGl0ZURlYWxvYyhlbGVtZW50LCB0cnVlKTsNCiAgd2hpbGUgKGVsZW1lbnQuZmlyc3RDaGlsZCkgew0KICAgIGVsZW1lbnQucmVtb3ZlQ2hpbGQoZWxlbWVudC5maXJzdENoaWxkKTsNCiAgfQ0KfQ0KDQpmdW5jdGlvbiBqcUxpdGVSZW1vdmUoZWxlbWVudCwga2VlcERhdGEpIHsNCiAgaWYgKCFrZWVwRGF0YSkganFMaXRlRGVhbG9jKGVsZW1lbnQpOw0KICB2YXIgcGFyZW50ID0gZWxlbWVudC5wYXJlbnROb2RlOw0KICBpZiAocGFyZW50KSBwYXJlbnQucmVtb3ZlQ2hpbGQoZWxlbWVudCk7DQp9DQoNCg0KZnVuY3Rpb24ganFMaXRlRG9jdW1lbnRMb2FkZWQoYWN0aW9uLCB3aW4pIHsNCiAgd2luID0gd2luIHx8IHdpbmRvdzsNCiAgaWYgKHdpbi5kb2N1bWVudC5yZWFkeVN0YXRlID09PSAnY29tcGxldGUnKSB7DQogICAgLy8gRm9yY2UgdGhlIGFjdGlvbiB0byBiZSBydW4gYXN5bmMgZm9yIGNvbnNpc3RlbnQgYmVoYXZpb3VyDQogICAgLy8gZnJvbSB0aGUgYWN0aW9uJ3MgcG9pbnQgb2Ygdmlldw0KICAgIC8vIGkuZS4gaXQgd2lsbCBkZWZpbml0ZWx5IG5vdCBiZSBpbiBhICRhcHBseQ0KICAgIHdpbi5zZXRUaW1lb3V0KGFjdGlvbik7DQogIH0gZWxzZSB7DQogICAgLy8gTm8gbmVlZCB0byB1bmJpbmQgdGhpcyBoYW5kbGVyIGFzIGxvYWQgaXMgb25seSBldmVyIGNhbGxlZCBvbmNlDQogICAganFMaXRlKHdpbikub24oJ2xvYWQnLCBhY3Rpb24pOw0KICB9DQp9DQoNCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KLy8gRnVuY3Rpb25zIHdoaWNoIGFyZSBkZWNsYXJlZCBkaXJlY3RseS4NCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KdmFyIEpRTGl0ZVByb3RvdHlwZSA9IEpRTGl0ZS5wcm90b3R5cGUgPSB7DQogIHJlYWR5OiBmdW5jdGlvbihmbikgew0KICAgIHZhciBmaXJlZCA9IGZhbHNlOw0KDQogICAgZnVuY3Rpb24gdHJpZ2dlcigpIHsNCiAgICAgIGlmIChmaXJlZCkgcmV0dXJuOw0KICAgICAgZmlyZWQgPSB0cnVlOw0KICAgICAgZm4oKTsNCiAgICB9DQoNCiAgICAvLyBjaGVjayBpZiBkb2N1bWVudCBpcyBhbHJlYWR5IGxvYWRlZA0KICAgIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnY29tcGxldGUnKSB7DQogICAgICBzZXRUaW1lb3V0KHRyaWdnZXIpOw0KICAgIH0gZWxzZSB7DQogICAgICB0aGlzLm9uKCdET01Db250ZW50TG9hZGVkJywgdHJpZ2dlcik7IC8vIHdvcmtzIGZvciBtb2Rlcm4gYnJvd3NlcnMgYW5kIElFOQ0KICAgICAgLy8gd2UgY2FuIG5vdCB1c2UganFMaXRlIHNpbmNlIHdlIGFyZSBub3QgZG9uZSBsb2FkaW5nIGFuZCBqUXVlcnkgY291bGQgYmUgbG9hZGVkIGxhdGVyLg0KICAgICAgLy8ganNoaW50IC1XMDY0DQogICAgICBKUUxpdGUod2luZG93KS5vbignbG9hZCcsIHRyaWdnZXIpOyAvLyBmYWxsYmFjayB0byB3aW5kb3cub25sb2FkIGZvciBvdGhlcnMNCiAgICAgIC8vIGpzaGludCArVzA2NA0KICAgIH0NCiAgfSwNCiAgdG9TdHJpbmc6IGZ1bmN0aW9uKCkgew0KICAgIHZhciB2YWx1ZSA9IFtdOw0KICAgIGZvckVhY2godGhpcywgZnVuY3Rpb24oZSkgeyB2YWx1ZS5wdXNoKCcnICsgZSk7fSk7DQogICAgcmV0dXJuICdbJyArIHZhbHVlLmpvaW4oJywgJykgKyAnXSc7DQogIH0sDQoNCiAgZXE6IGZ1bmN0aW9uKGluZGV4KSB7DQogICAgICByZXR1cm4gKGluZGV4ID49IDApID8ganFMaXRlKHRoaXNbaW5kZXhdKSA6IGpxTGl0ZSh0aGlzW3RoaXMubGVuZ3RoICsgaW5kZXhdKTsNCiAgfSwNCg0KICBsZW5ndGg6IDAsDQogIHB1c2g6IHB1c2gsDQogIHNvcnQ6IFtdLnNvcnQsDQogIHNwbGljZTogW10uc3BsaWNlDQp9Ow0KDQovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCi8vIEZ1bmN0aW9ucyBpdGVyYXRpbmcgZ2V0dGVyL3NldHRlcnMuDQovLyB0aGVzZSBmdW5jdGlvbnMgcmV0dXJuIHNlbGYgb24gc2V0dGVyIGFuZA0KLy8gdmFsdWUgb24gZ2V0Lg0KLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vDQp2YXIgQk9PTEVBTl9BVFRSID0ge307DQpmb3JFYWNoKCdtdWx0aXBsZSxzZWxlY3RlZCxjaGVja2VkLGRpc2FibGVkLHJlYWRPbmx5LHJlcXVpcmVkLG9wZW4nLnNwbGl0KCcsJyksIGZ1bmN0aW9uKHZhbHVlKSB7DQogIEJPT0xFQU5fQVRUUltsb3dlcmNhc2UodmFsdWUpXSA9IHZhbHVlOw0KfSk7DQp2YXIgQk9PTEVBTl9FTEVNRU5UUyA9IHt9Ow0KZm9yRWFjaCgnaW5wdXQsc2VsZWN0LG9wdGlvbix0ZXh0YXJlYSxidXR0b24sZm9ybSxkZXRhaWxzJy5zcGxpdCgnLCcpLCBmdW5jdGlvbih2YWx1ZSkgew0KICBCT09MRUFOX0VMRU1FTlRTW3ZhbHVlXSA9IHRydWU7DQp9KTsNCnZhciBBTElBU0VEX0FUVFIgPSB7DQogICduZ01pbmxlbmd0aCc6ICdtaW5sZW5ndGgnLA0KICAnbmdNYXhsZW5ndGgnOiAnbWF4bGVuZ3RoJywNCiAgJ25nTWluJzogJ21pbicsDQogICduZ01heCc6ICdtYXgnLA0KICAnbmdQYXR0ZXJuJzogJ3BhdHRlcm4nDQp9Ow0KDQpmdW5jdGlvbiBnZXRCb29sZWFuQXR0ck5hbWUoZWxlbWVudCwgbmFtZSkgew0KICAvLyBjaGVjayBkb20gbGFzdCBzaW5jZSB3ZSB3aWxsIG1vc3QgbGlrZWx5IGZhaWwgb24gbmFtZQ0KICB2YXIgYm9vbGVhbkF0dHIgPSBCT09MRUFOX0FUVFJbbmFtZS50b0xvd2VyQ2FzZSgpXTsNCg0KICAvLyBib29sZWFuQXR0ciBpcyBoZXJlIHR3aWNlIHRvIG1pbmltaXplIERPTSBhY2Nlc3MNCiAgcmV0dXJuIGJvb2xlYW5BdHRyICYmIEJPT0xFQU5fRUxFTUVOVFNbbm9kZU5hbWVfKGVsZW1lbnQpXSAmJiBib29sZWFuQXR0cjsNCn0NCg0KZnVuY3Rpb24gZ2V0QWxpYXNlZEF0dHJOYW1lKGVsZW1lbnQsIG5hbWUpIHsNCiAgdmFyIG5vZGVOYW1lID0gZWxlbWVudC5ub2RlTmFtZTsNCiAgcmV0dXJuIChub2RlTmFtZSA9PT0gJ0lOUFVUJyB8fCBub2RlTmFtZSA9PT0gJ1RFWFRBUkVBJykgJiYgQUxJQVNFRF9BVFRSW25hbWVdOw0KfQ0KDQpmb3JFYWNoKHsNCiAgZGF0YToganFMaXRlRGF0YSwNCiAgcmVtb3ZlRGF0YToganFMaXRlUmVtb3ZlRGF0YQ0KfSwgZnVuY3Rpb24oZm4sIG5hbWUpIHsNCiAgSlFMaXRlW25hbWVdID0gZm47DQp9KTsNCg0KZm9yRWFjaCh7DQogIGRhdGE6IGpxTGl0ZURhdGEsDQogIGluaGVyaXRlZERhdGE6IGpxTGl0ZUluaGVyaXRlZERhdGEsDQoNCiAgc2NvcGU6IGZ1bmN0aW9uKGVsZW1lbnQpIHsNCiAgICAvLyBDYW4ndCB1c2UganFMaXRlRGF0YSBoZXJlIGRpcmVjdGx5IHNvIHdlIHN0YXkgY29tcGF0aWJsZSB3aXRoIGpRdWVyeSENCiAgICByZXR1cm4ganFMaXRlLmRhdGEoZWxlbWVudCwgJyRzY29wZScpIHx8IGpxTGl0ZUluaGVyaXRlZERhdGEoZWxlbWVudC5wYXJlbnROb2RlIHx8IGVsZW1lbnQsIFsnJGlzb2xhdGVTY29wZScsICckc2NvcGUnXSk7DQogIH0sDQoNCiAgaXNvbGF0ZVNjb3BlOiBmdW5jdGlvbihlbGVtZW50KSB7DQogICAgLy8gQ2FuJ3QgdXNlIGpxTGl0ZURhdGEgaGVyZSBkaXJlY3RseSBzbyB3ZSBzdGF5IGNvbXBhdGlibGUgd2l0aCBqUXVlcnkhDQogICAgcmV0dXJuIGpxTGl0ZS5kYXRhKGVsZW1lbnQsICckaXNvbGF0ZVNjb3BlJykgfHwganFMaXRlLmRhdGEoZWxlbWVudCwgJyRpc29sYXRlU2NvcGVOb1RlbXBsYXRlJyk7DQogIH0sDQoNCiAgY29udHJvbGxlcjoganFMaXRlQ29udHJvbGxlciwNCg0KICBpbmplY3RvcjogZnVuY3Rpb24oZWxlbWVudCkgew0KICAgIHJldHVybiBqcUxpdGVJbmhlcml0ZWREYXRhKGVsZW1lbnQsICckaW5qZWN0b3InKTsNCiAgfSwNCg0KICByZW1vdmVBdHRyOiBmdW5jdGlvbihlbGVtZW50LCBuYW1lKSB7DQogICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUobmFtZSk7DQogIH0sDQoNCiAgaGFzQ2xhc3M6IGpxTGl0ZUhhc0NsYXNzLA0KDQogIGNzczogZnVuY3Rpb24oZWxlbWVudCwgbmFtZSwgdmFsdWUpIHsNCiAgICBuYW1lID0gY2FtZWxDYXNlKG5hbWUpOw0KDQogICAgaWYgKGlzRGVmaW5lZCh2YWx1ZSkpIHsNCiAgICAgIGVsZW1lbnQuc3R5bGVbbmFtZV0gPSB2YWx1ZTsNCiAgICB9IGVsc2Ugew0KICAgICAgcmV0dXJuIGVsZW1lbnQuc3R5bGVbbmFtZV07DQogICAgfQ0KICB9LA0KDQogIGF0dHI6IGZ1bmN0aW9uKGVsZW1lbnQsIG5hbWUsIHZhbHVlKSB7DQogICAgdmFyIGxvd2VyY2FzZWROYW1lID0gbG93ZXJjYXNlKG5hbWUpOw0KICAgIGlmIChCT09MRUFOX0FUVFJbbG93ZXJjYXNlZE5hbWVdKSB7DQogICAgICBpZiAoaXNEZWZpbmVkKHZhbHVlKSkgew0KICAgICAgICBpZiAoISF2YWx1ZSkgew0KICAgICAgICAgIGVsZW1lbnRbbmFtZV0gPSB0cnVlOw0KICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKG5hbWUsIGxvd2VyY2FzZWROYW1lKTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBlbGVtZW50W25hbWVdID0gZmFsc2U7DQogICAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUobG93ZXJjYXNlZE5hbWUpOw0KICAgICAgICB9DQogICAgICB9IGVsc2Ugew0KICAgICAgICByZXR1cm4gKGVsZW1lbnRbbmFtZV0gfHwNCiAgICAgICAgICAgICAgICAgKGVsZW1lbnQuYXR0cmlidXRlcy5nZXROYW1lZEl0ZW0obmFtZSkgfHwgbm9vcCkuc3BlY2lmaWVkKQ0KICAgICAgICAgICAgICAgPyBsb3dlcmNhc2VkTmFtZQ0KICAgICAgICAgICAgICAgOiB1bmRlZmluZWQ7DQogICAgICB9DQogICAgfSBlbHNlIGlmIChpc0RlZmluZWQodmFsdWUpKSB7DQogICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSk7DQogICAgfSBlbHNlIGlmIChlbGVtZW50LmdldEF0dHJpYnV0ZSkgew0KICAgICAgLy8gdGhlIGV4dHJhIGFyZ3VtZW50ICIyIiBpcyB0byBnZXQgdGhlIHJpZ2h0IHRoaW5nIGZvciBhLmhyZWYgaW4gSUUsIHNlZSBqUXVlcnkgY29kZQ0KICAgICAgLy8gc29tZSBlbGVtZW50cyAoZS5nLiBEb2N1bWVudCkgZG9uJ3QgaGF2ZSBnZXQgYXR0cmlidXRlLCBzbyByZXR1cm4gdW5kZWZpbmVkDQogICAgICB2YXIgcmV0ID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUobmFtZSwgMik7DQogICAgICAvLyBub3JtYWxpemUgbm9uLWV4aXN0aW5nIGF0dHJpYnV0ZXMgdG8gdW5kZWZpbmVkIChhcyBqUXVlcnkpDQogICAgICByZXR1cm4gcmV0ID09PSBudWxsID8gdW5kZWZpbmVkIDogcmV0Ow0KICAgIH0NCiAgfSwNCg0KICBwcm9wOiBmdW5jdGlvbihlbGVtZW50LCBuYW1lLCB2YWx1ZSkgew0KICAgIGlmIChpc0RlZmluZWQodmFsdWUpKSB7DQogICAgICBlbGVtZW50W25hbWVdID0gdmFsdWU7DQogICAgfSBlbHNlIHsNCiAgICAgIHJldHVybiBlbGVtZW50W25hbWVdOw0KICAgIH0NCiAgfSwNCg0KICB0ZXh0OiAoZnVuY3Rpb24oKSB7DQogICAgZ2V0VGV4dC4kZHYgPSAnJzsNCiAgICByZXR1cm4gZ2V0VGV4dDsNCg0KICAgIGZ1bmN0aW9uIGdldFRleHQoZWxlbWVudCwgdmFsdWUpIHsNCiAgICAgIGlmIChpc1VuZGVmaW5lZCh2YWx1ZSkpIHsNCiAgICAgICAgdmFyIG5vZGVUeXBlID0gZWxlbWVudC5ub2RlVHlwZTsNCiAgICAgICAgcmV0dXJuIChub2RlVHlwZSA9PT0gTk9ERV9UWVBFX0VMRU1FTlQgfHwgbm9kZVR5cGUgPT09IE5PREVfVFlQRV9URVhUKSA/IGVsZW1lbnQudGV4dENvbnRlbnQgOiAnJzsNCiAgICAgIH0NCiAgICAgIGVsZW1lbnQudGV4dENvbnRlbnQgPSB2YWx1ZTsNCiAgICB9DQogIH0pKCksDQoNCiAgdmFsOiBmdW5jdGlvbihlbGVtZW50LCB2YWx1ZSkgew0KICAgIGlmIChpc1VuZGVmaW5lZCh2YWx1ZSkpIHsNCiAgICAgIGlmIChlbGVtZW50Lm11bHRpcGxlICYmIG5vZGVOYW1lXyhlbGVtZW50KSA9PT0gJ3NlbGVjdCcpIHsNCiAgICAgICAgdmFyIHJlc3VsdCA9IFtdOw0KICAgICAgICBmb3JFYWNoKGVsZW1lbnQub3B0aW9ucywgZnVuY3Rpb24ob3B0aW9uKSB7DQogICAgICAgICAgaWYgKG9wdGlvbi5zZWxlY3RlZCkgew0KICAgICAgICAgICAgcmVzdWx0LnB1c2gob3B0aW9uLnZhbHVlIHx8IG9wdGlvbi50ZXh0KTsNCiAgICAgICAgICB9DQogICAgICAgIH0pOw0KICAgICAgICByZXR1cm4gcmVzdWx0Lmxlbmd0aCA9PT0gMCA/IG51bGwgOiByZXN1bHQ7DQogICAgICB9DQogICAgICByZXR1cm4gZWxlbWVudC52YWx1ZTsNCiAgICB9DQogICAgZWxlbWVudC52YWx1ZSA9IHZhbHVlOw0KICB9LA0KDQogIGh0bWw6IGZ1bmN0aW9uKGVsZW1lbnQsIHZhbHVlKSB7DQogICAgaWYgKGlzVW5kZWZpbmVkKHZhbHVlKSkgew0KICAgICAgcmV0dXJuIGVsZW1lbnQuaW5uZXJIVE1MOw0KICAgIH0NCiAgICBqcUxpdGVEZWFsb2MoZWxlbWVudCwgdHJ1ZSk7DQogICAgZWxlbWVudC5pbm5lckhUTUwgPSB2YWx1ZTsNCiAgfSwNCg0KICBlbXB0eToganFMaXRlRW1wdHkNCn0sIGZ1bmN0aW9uKGZuLCBuYW1lKSB7DQogIC8qKg0KICAgKiBQcm9wZXJ0aWVzOiB3cml0ZXMgcmV0dXJuIHNlbGVjdGlvbiwgcmVhZHMgcmV0dXJuIGZpcnN0IHZhbHVlDQogICAqLw0KICBKUUxpdGUucHJvdG90eXBlW25hbWVdID0gZnVuY3Rpb24oYXJnMSwgYXJnMikgew0KICAgIHZhciBpLCBrZXk7DQogICAgdmFyIG5vZGVDb3VudCA9IHRoaXMubGVuZ3RoOw0KDQogICAgLy8ganFMaXRlSGFzQ2xhc3MgaGFzIG9ubHkgdHdvIGFyZ3VtZW50cywgYnV0IGlzIGEgZ2V0dGVyLW9ubHkgZm4sIHNvIHdlIG5lZWQgdG8gc3BlY2lhbC1jYXNlIGl0DQogICAgLy8gaW4gYSB3YXkgdGhhdCBzdXJ2aXZlcyBtaW5pZmljYXRpb24uDQogICAgLy8ganFMaXRlRW1wdHkgdGFrZXMgbm8gYXJndW1lbnRzIGJ1dCBpcyBhIHNldHRlci4NCiAgICBpZiAoZm4gIT09IGpxTGl0ZUVtcHR5ICYmDQogICAgICAgICgoKGZuLmxlbmd0aCA9PSAyICYmIChmbiAhPT0ganFMaXRlSGFzQ2xhc3MgJiYgZm4gIT09IGpxTGl0ZUNvbnRyb2xsZXIpKSA/IGFyZzEgOiBhcmcyKSA9PT0gdW5kZWZpbmVkKSkgew0KICAgICAgaWYgKGlzT2JqZWN0KGFyZzEpKSB7DQoNCiAgICAgICAgLy8gd2UgYXJlIGEgd3JpdGUsIGJ1dCB0aGUgb2JqZWN0IHByb3BlcnRpZXMgYXJlIHRoZSBrZXkvdmFsdWVzDQogICAgICAgIGZvciAoaSA9IDA7IGkgPCBub2RlQ291bnQ7IGkrKykgew0KICAgICAgICAgIGlmIChmbiA9PT0ganFMaXRlRGF0YSkgew0KICAgICAgICAgICAgLy8gZGF0YSgpIHRha2VzIHRoZSB3aG9sZSBvYmplY3QgaW4galF1ZXJ5DQogICAgICAgICAgICBmbih0aGlzW2ldLCBhcmcxKTsNCiAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgZm9yIChrZXkgaW4gYXJnMSkgew0KICAgICAgICAgICAgICBmbih0aGlzW2ldLCBrZXksIGFyZzFba2V5XSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICAgIC8vIHJldHVybiBzZWxmIGZvciBjaGFpbmluZw0KICAgICAgICByZXR1cm4gdGhpczsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIC8vIHdlIGFyZSBhIHJlYWQsIHNvIHJlYWQgdGhlIGZpcnN0IGNoaWxkLg0KICAgICAgICAvLyBUT0RPOiBkbyB3ZSBzdGlsbCBuZWVkIHRoaXM/DQogICAgICAgIHZhciB2YWx1ZSA9IGZuLiRkdjsNCiAgICAgICAgLy8gT25seSBpZiB3ZSBoYXZlICRkdiBkbyB3ZSBpdGVyYXRlIG92ZXIgYWxsLCBvdGhlcndpc2UgaXQgaXMganVzdCB0aGUgZmlyc3QgZWxlbWVudC4NCiAgICAgICAgdmFyIGpqID0gKHZhbHVlID09PSB1bmRlZmluZWQpID8gTWF0aC5taW4obm9kZUNvdW50LCAxKSA6IG5vZGVDb3VudDsNCiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBqajsgaisrKSB7DQogICAgICAgICAgdmFyIG5vZGVWYWx1ZSA9IGZuKHRoaXNbal0sIGFyZzEsIGFyZzIpOw0KICAgICAgICAgIHZhbHVlID0gdmFsdWUgPyB2YWx1ZSArIG5vZGVWYWx1ZSA6IG5vZGVWYWx1ZTsNCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gdmFsdWU7DQogICAgICB9DQogICAgfSBlbHNlIHsNCiAgICAgIC8vIHdlIGFyZSBhIHdyaXRlLCBzbyBhcHBseSB0byBhbGwgY2hpbGRyZW4NCiAgICAgIGZvciAoaSA9IDA7IGkgPCBub2RlQ291bnQ7IGkrKykgew0KICAgICAgICBmbih0aGlzW2ldLCBhcmcxLCBhcmcyKTsNCiAgICAgIH0NCiAgICAgIC8vIHJldHVybiBzZWxmIGZvciBjaGFpbmluZw0KICAgICAgcmV0dXJuIHRoaXM7DQogICAgfQ0KICB9Ow0KfSk7DQoNCmZ1bmN0aW9uIGNyZWF0ZUV2ZW50SGFuZGxlcihlbGVtZW50LCBldmVudHMpIHsNCiAgdmFyIGV2ZW50SGFuZGxlciA9IGZ1bmN0aW9uKGV2ZW50LCB0eXBlKSB7DQogICAgLy8galF1ZXJ5IHNwZWNpZmljIGFwaQ0KICAgIGV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCA9IGZ1bmN0aW9uKCkgew0KICAgICAgcmV0dXJuIGV2ZW50LmRlZmF1bHRQcmV2ZW50ZWQ7DQogICAgfTsNCg0KICAgIHZhciBldmVudEZucyA9IGV2ZW50c1t0eXBlIHx8IGV2ZW50LnR5cGVdOw0KICAgIHZhciBldmVudEZuc0xlbmd0aCA9IGV2ZW50Rm5zID8gZXZlbnRGbnMubGVuZ3RoIDogMDsNCg0KICAgIGlmICghZXZlbnRGbnNMZW5ndGgpIHJldHVybjsNCg0KICAgIGlmIChpc1VuZGVmaW5lZChldmVudC5pbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQpKSB7DQogICAgICB2YXIgb3JpZ2luYWxTdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24gPSBldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb247DQogICAgICBldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24gPSBmdW5jdGlvbigpIHsNCiAgICAgICAgZXZlbnQuaW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkID0gdHJ1ZTsNCg0KICAgICAgICBpZiAoZXZlbnQuc3RvcFByb3BhZ2F0aW9uKSB7DQogICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAob3JpZ2luYWxTdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24pIHsNCiAgICAgICAgICBvcmlnaW5hbFN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbi5jYWxsKGV2ZW50KTsNCiAgICAgICAgfQ0KICAgICAgfTsNCiAgICB9DQoNCiAgICBldmVudC5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCA9IGZ1bmN0aW9uKCkgew0KICAgICAgcmV0dXJuIGV2ZW50LmltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCA9PT0gdHJ1ZTsNCiAgICB9Ow0KDQogICAgLy8gQ29weSBldmVudCBoYW5kbGVycyBpbiBjYXNlIGV2ZW50IGhhbmRsZXJzIGFycmF5IGlzIG1vZGlmaWVkIGR1cmluZyBleGVjdXRpb24uDQogICAgaWYgKChldmVudEZuc0xlbmd0aCA+IDEpKSB7DQogICAgICBldmVudEZucyA9IHNoYWxsb3dDb3B5KGV2ZW50Rm5zKTsNCiAgICB9DQoNCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV2ZW50Rm5zTGVuZ3RoOyBpKyspIHsNCiAgICAgIGlmICghZXZlbnQuaXNJbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQoKSkgew0KICAgICAgICBldmVudEZuc1tpXS5jYWxsKGVsZW1lbnQsIGV2ZW50KTsNCiAgICAgIH0NCiAgICB9DQogIH07DQoNCiAgLy8gVE9ETzogdGhpcyBpcyBhIGhhY2sgZm9yIGFuZ3VsYXJNb2Nrcy9jbGVhckRhdGFDYWNoZSB0aGF0IG1ha2VzIGl0IHBvc3NpYmxlIHRvIGRlcmVnaXN0ZXIgYWxsDQogIC8vICAgICAgIGV2ZW50cyBvbiBgZWxlbWVudGANCiAgZXZlbnRIYW5kbGVyLmVsZW0gPSBlbGVtZW50Ow0KICByZXR1cm4gZXZlbnRIYW5kbGVyOw0KfQ0KDQovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCi8vIEZ1bmN0aW9ucyBpdGVyYXRpbmcgdHJhdmVyc2FsLg0KLy8gVGhlc2UgZnVuY3Rpb25zIGNoYWluIHJlc3VsdHMgaW50byBhIHNpbmdsZQ0KLy8gc2VsZWN0b3IuDQovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCmZvckVhY2goew0KICByZW1vdmVEYXRhOiBqcUxpdGVSZW1vdmVEYXRhLA0KDQogIG9uOiBmdW5jdGlvbiBqcUxpdGVPbihlbGVtZW50LCB0eXBlLCBmbiwgdW5zdXBwb3J0ZWQpIHsNCiAgICBpZiAoaXNEZWZpbmVkKHVuc3VwcG9ydGVkKSkgdGhyb3cganFMaXRlTWluRXJyKCdvbmFyZ3MnLCAnanFMaXRlI29uKCkgZG9lcyBub3Qgc3VwcG9ydCB0aGUgYHNlbGVjdG9yYCBvciBgZXZlbnREYXRhYCBwYXJhbWV0ZXJzJyk7DQoNCiAgICAvLyBEbyBub3QgYWRkIGV2ZW50IGhhbmRsZXJzIHRvIG5vbi1lbGVtZW50cyBiZWNhdXNlIHRoZXkgd2lsbCBub3QgYmUgY2xlYW5lZCB1cC4NCiAgICBpZiAoIWpxTGl0ZUFjY2VwdHNEYXRhKGVsZW1lbnQpKSB7DQogICAgICByZXR1cm47DQogICAgfQ0KDQogICAgdmFyIGV4cGFuZG9TdG9yZSA9IGpxTGl0ZUV4cGFuZG9TdG9yZShlbGVtZW50LCB0cnVlKTsNCiAgICB2YXIgZXZlbnRzID0gZXhwYW5kb1N0b3JlLmV2ZW50czsNCiAgICB2YXIgaGFuZGxlID0gZXhwYW5kb1N0b3JlLmhhbmRsZTsNCg0KICAgIGlmICghaGFuZGxlKSB7DQogICAgICBoYW5kbGUgPSBleHBhbmRvU3RvcmUuaGFuZGxlID0gY3JlYXRlRXZlbnRIYW5kbGVyKGVsZW1lbnQsIGV2ZW50cyk7DQogICAgfQ0KDQogICAgLy8gaHR0cDovL2pzcGVyZi5jb20vc3RyaW5nLWluZGV4b2YtdnMtc3BsaXQNCiAgICB2YXIgdHlwZXMgPSB0eXBlLmluZGV4T2YoJyAnKSA+PSAwID8gdHlwZS5zcGxpdCgnICcpIDogW3R5cGVdOw0KICAgIHZhciBpID0gdHlwZXMubGVuZ3RoOw0KDQogICAgd2hpbGUgKGktLSkgew0KICAgICAgdHlwZSA9IHR5cGVzW2ldOw0KICAgICAgdmFyIGV2ZW50Rm5zID0gZXZlbnRzW3R5cGVdOw0KDQogICAgICBpZiAoIWV2ZW50Rm5zKSB7DQogICAgICAgIGV2ZW50c1t0eXBlXSA9IFtdOw0KDQogICAgICAgIGlmICh0eXBlID09PSAnbW91c2VlbnRlcicgfHwgdHlwZSA9PT0gJ21vdXNlbGVhdmUnKSB7DQogICAgICAgICAgLy8gUmVmZXIgdG8galF1ZXJ5J3MgaW1wbGVtZW50YXRpb24gb2YgbW91c2VlbnRlciAmIG1vdXNlbGVhdmUNCiAgICAgICAgICAvLyBSZWFkIGFib3V0IG1vdXNlZW50ZXIgYW5kIG1vdXNlbGVhdmU6DQogICAgICAgICAgLy8gaHR0cDovL3d3dy5xdWlya3Ntb2RlLm9yZy9qcy9ldmVudHNfbW91c2UuaHRtbCNsaW5rOA0KDQogICAgICAgICAganFMaXRlT24oZWxlbWVudCwgTU9VU0VfRVZFTlRfTUFQW3R5cGVdLCBmdW5jdGlvbihldmVudCkgew0KICAgICAgICAgICAgdmFyIHRhcmdldCA9IHRoaXMsIHJlbGF0ZWQgPSBldmVudC5yZWxhdGVkVGFyZ2V0Ow0KICAgICAgICAgICAgLy8gRm9yIG1vdXNlbnRlci9sZWF2ZSBjYWxsIHRoZSBoYW5kbGVyIGlmIHJlbGF0ZWQgaXMgb3V0c2lkZSB0aGUgdGFyZ2V0Lg0KICAgICAgICAgICAgLy8gTkI6IE5vIHJlbGF0ZWRUYXJnZXQgaWYgdGhlIG1vdXNlIGxlZnQvZW50ZXJlZCB0aGUgYnJvd3NlciB3aW5kb3cNCiAgICAgICAgICAgIGlmICghcmVsYXRlZCB8fCAocmVsYXRlZCAhPT0gdGFyZ2V0ICYmICF0YXJnZXQuY29udGFpbnMocmVsYXRlZCkpKSB7DQogICAgICAgICAgICAgIGhhbmRsZShldmVudCwgdHlwZSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgfSk7DQoNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBpZiAodHlwZSAhPT0gJyRkZXN0cm95Jykgew0KICAgICAgICAgICAgYWRkRXZlbnRMaXN0ZW5lckZuKGVsZW1lbnQsIHR5cGUsIGhhbmRsZSk7DQogICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICAgIGV2ZW50Rm5zID0gZXZlbnRzW3R5cGVdOw0KICAgICAgfQ0KICAgICAgZXZlbnRGbnMucHVzaChmbik7DQogICAgfQ0KICB9LA0KDQogIG9mZjoganFMaXRlT2ZmLA0KDQogIG9uZTogZnVuY3Rpb24oZWxlbWVudCwgdHlwZSwgZm4pIHsNCiAgICBlbGVtZW50ID0ganFMaXRlKGVsZW1lbnQpOw0KDQogICAgLy9hZGQgdGhlIGxpc3RlbmVyIHR3aWNlIHNvIHRoYXQgd2hlbiBpdCBpcyBjYWxsZWQNCiAgICAvL3lvdSBjYW4gcmVtb3ZlIHRoZSBvcmlnaW5hbCBmdW5jdGlvbiBhbmQgc3RpbGwgYmUNCiAgICAvL2FibGUgdG8gY2FsbCBlbGVtZW50Lm9mZihldiwgZm4pIG5vcm1hbGx5DQogICAgZWxlbWVudC5vbih0eXBlLCBmdW5jdGlvbiBvbkZuKCkgew0KICAgICAgZWxlbWVudC5vZmYodHlwZSwgZm4pOw0KICAgICAgZWxlbWVudC5vZmYodHlwZSwgb25Gbik7DQogICAgfSk7DQogICAgZWxlbWVudC5vbih0eXBlLCBmbik7DQogIH0sDQoNCiAgcmVwbGFjZVdpdGg6IGZ1bmN0aW9uKGVsZW1lbnQsIHJlcGxhY2VOb2RlKSB7DQogICAgdmFyIGluZGV4LCBwYXJlbnQgPSBlbGVtZW50LnBhcmVudE5vZGU7DQogICAganFMaXRlRGVhbG9jKGVsZW1lbnQpOw0KICAgIGZvckVhY2gobmV3IEpRTGl0ZShyZXBsYWNlTm9kZSksIGZ1bmN0aW9uKG5vZGUpIHsNCiAgICAgIGlmIChpbmRleCkgew0KICAgICAgICBwYXJlbnQuaW5zZXJ0QmVmb3JlKG5vZGUsIGluZGV4Lm5leHRTaWJsaW5nKTsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIHBhcmVudC5yZXBsYWNlQ2hpbGQobm9kZSwgZWxlbWVudCk7DQogICAgICB9DQogICAgICBpbmRleCA9IG5vZGU7DQogICAgfSk7DQogIH0sDQoNCiAgY2hpbGRyZW46IGZ1bmN0aW9uKGVsZW1lbnQpIHsNCiAgICB2YXIgY2hpbGRyZW4gPSBbXTsNCiAgICBmb3JFYWNoKGVsZW1lbnQuY2hpbGROb2RlcywgZnVuY3Rpb24oZWxlbWVudCkgew0KICAgICAgaWYgKGVsZW1lbnQubm9kZVR5cGUgPT09IE5PREVfVFlQRV9FTEVNRU5UKQ0KICAgICAgICBjaGlsZHJlbi5wdXNoKGVsZW1lbnQpOw0KICAgIH0pOw0KICAgIHJldHVybiBjaGlsZHJlbjsNCiAgfSwNCg0KICBjb250ZW50czogZnVuY3Rpb24oZWxlbWVudCkgew0KICAgIHJldHVybiBlbGVtZW50LmNvbnRlbnREb2N1bWVudCB8fCBlbGVtZW50LmNoaWxkTm9kZXMgfHwgW107DQogIH0sDQoNCiAgYXBwZW5kOiBmdW5jdGlvbihlbGVtZW50LCBub2RlKSB7DQogICAgdmFyIG5vZGVUeXBlID0gZWxlbWVudC5ub2RlVHlwZTsNCiAgICBpZiAobm9kZVR5cGUgIT09IE5PREVfVFlQRV9FTEVNRU5UICYmIG5vZGVUeXBlICE9PSBOT0RFX1RZUEVfRE9DVU1FTlRfRlJBR01FTlQpIHJldHVybjsNCg0KICAgIG5vZGUgPSBuZXcgSlFMaXRlKG5vZGUpOw0KDQogICAgZm9yICh2YXIgaSA9IDAsIGlpID0gbm9kZS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7DQogICAgICB2YXIgY2hpbGQgPSBub2RlW2ldOw0KICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChjaGlsZCk7DQogICAgfQ0KICB9LA0KDQogIHByZXBlbmQ6IGZ1bmN0aW9uKGVsZW1lbnQsIG5vZGUpIHsNCiAgICBpZiAoZWxlbWVudC5ub2RlVHlwZSA9PT0gTk9ERV9UWVBFX0VMRU1FTlQpIHsNCiAgICAgIHZhciBpbmRleCA9IGVsZW1lbnQuZmlyc3RDaGlsZDsNCiAgICAgIGZvckVhY2gobmV3IEpRTGl0ZShub2RlKSwgZnVuY3Rpb24oY2hpbGQpIHsNCiAgICAgICAgZWxlbWVudC5pbnNlcnRCZWZvcmUoY2hpbGQsIGluZGV4KTsNCiAgICAgIH0pOw0KICAgIH0NCiAgfSwNCg0KICB3cmFwOiBmdW5jdGlvbihlbGVtZW50LCB3cmFwTm9kZSkgew0KICAgIHdyYXBOb2RlID0ganFMaXRlKHdyYXBOb2RlKS5lcSgwKS5jbG9uZSgpWzBdOw0KICAgIHZhciBwYXJlbnQgPSBlbGVtZW50LnBhcmVudE5vZGU7DQogICAgaWYgKHBhcmVudCkgew0KICAgICAgcGFyZW50LnJlcGxhY2VDaGlsZCh3cmFwTm9kZSwgZWxlbWVudCk7DQogICAgfQ0KICAgIHdyYXBOb2RlLmFwcGVuZENoaWxkKGVsZW1lbnQpOw0KICB9LA0KDQogIHJlbW92ZToganFMaXRlUmVtb3ZlLA0KDQogIGRldGFjaDogZnVuY3Rpb24oZWxlbWVudCkgew0KICAgIGpxTGl0ZVJlbW92ZShlbGVtZW50LCB0cnVlKTsNCiAgfSwNCg0KICBhZnRlcjogZnVuY3Rpb24oZWxlbWVudCwgbmV3RWxlbWVudCkgew0KICAgIHZhciBpbmRleCA9IGVsZW1lbnQsIHBhcmVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTsNCiAgICBuZXdFbGVtZW50ID0gbmV3IEpRTGl0ZShuZXdFbGVtZW50KTsNCg0KICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IG5ld0VsZW1lbnQubGVuZ3RoOyBpIDwgaWk7IGkrKykgew0KICAgICAgdmFyIG5vZGUgPSBuZXdFbGVtZW50W2ldOw0KICAgICAgcGFyZW50Lmluc2VydEJlZm9yZShub2RlLCBpbmRleC5uZXh0U2libGluZyk7DQogICAgICBpbmRleCA9IG5vZGU7DQogICAgfQ0KICB9LA0KDQogIGFkZENsYXNzOiBqcUxpdGVBZGRDbGFzcywNCiAgcmVtb3ZlQ2xhc3M6IGpxTGl0ZVJlbW92ZUNsYXNzLA0KDQogIHRvZ2dsZUNsYXNzOiBmdW5jdGlvbihlbGVtZW50LCBzZWxlY3RvciwgY29uZGl0aW9uKSB7DQogICAgaWYgKHNlbGVjdG9yKSB7DQogICAgICBmb3JFYWNoKHNlbGVjdG9yLnNwbGl0KCcgJyksIGZ1bmN0aW9uKGNsYXNzTmFtZSkgew0KICAgICAgICB2YXIgY2xhc3NDb25kaXRpb24gPSBjb25kaXRpb247DQogICAgICAgIGlmIChpc1VuZGVmaW5lZChjbGFzc0NvbmRpdGlvbikpIHsNCiAgICAgICAgICBjbGFzc0NvbmRpdGlvbiA9ICFqcUxpdGVIYXNDbGFzcyhlbGVtZW50LCBjbGFzc05hbWUpOw0KICAgICAgICB9DQogICAgICAgIChjbGFzc0NvbmRpdGlvbiA/IGpxTGl0ZUFkZENsYXNzIDoganFMaXRlUmVtb3ZlQ2xhc3MpKGVsZW1lbnQsIGNsYXNzTmFtZSk7DQogICAgICB9KTsNCiAgICB9DQogIH0sDQoNCiAgcGFyZW50OiBmdW5jdGlvbihlbGVtZW50KSB7DQogICAgdmFyIHBhcmVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTsNCiAgICByZXR1cm4gcGFyZW50ICYmIHBhcmVudC5ub2RlVHlwZSAhPT0gTk9ERV9UWVBFX0RPQ1VNRU5UX0ZSQUdNRU5UID8gcGFyZW50IDogbnVsbDsNCiAgfSwNCg0KICBuZXh0OiBmdW5jdGlvbihlbGVtZW50KSB7DQogICAgcmV0dXJuIGVsZW1lbnQubmV4dEVsZW1lbnRTaWJsaW5nOw0KICB9LA0KDQogIGZpbmQ6IGZ1bmN0aW9uKGVsZW1lbnQsIHNlbGVjdG9yKSB7DQogICAgaWYgKGVsZW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUpIHsNCiAgICAgIHJldHVybiBlbGVtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKHNlbGVjdG9yKTsNCiAgICB9IGVsc2Ugew0KICAgICAgcmV0dXJuIFtdOw0KICAgIH0NCiAgfSwNCg0KICBjbG9uZToganFMaXRlQ2xvbmUsDQoNCiAgdHJpZ2dlckhhbmRsZXI6IGZ1bmN0aW9uKGVsZW1lbnQsIGV2ZW50LCBleHRyYVBhcmFtZXRlcnMpIHsNCg0KICAgIHZhciBkdW1teUV2ZW50LCBldmVudEZuc0NvcHksIGhhbmRsZXJBcmdzOw0KICAgIHZhciBldmVudE5hbWUgPSBldmVudC50eXBlIHx8IGV2ZW50Ow0KICAgIHZhciBleHBhbmRvU3RvcmUgPSBqcUxpdGVFeHBhbmRvU3RvcmUoZWxlbWVudCk7DQogICAgdmFyIGV2ZW50cyA9IGV4cGFuZG9TdG9yZSAmJiBleHBhbmRvU3RvcmUuZXZlbnRzOw0KICAgIHZhciBldmVudEZucyA9IGV2ZW50cyAmJiBldmVudHNbZXZlbnROYW1lXTsNCg0KICAgIGlmIChldmVudEZucykgew0KICAgICAgLy8gQ3JlYXRlIGEgZHVtbXkgZXZlbnQgdG8gcGFzcyB0byB0aGUgaGFuZGxlcnMNCiAgICAgIGR1bW15RXZlbnQgPSB7DQogICAgICAgIHByZXZlbnREZWZhdWx0OiBmdW5jdGlvbigpIHsgdGhpcy5kZWZhdWx0UHJldmVudGVkID0gdHJ1ZTsgfSwNCiAgICAgICAgaXNEZWZhdWx0UHJldmVudGVkOiBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMuZGVmYXVsdFByZXZlbnRlZCA9PT0gdHJ1ZTsgfSwNCiAgICAgICAgc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uOiBmdW5jdGlvbigpIHsgdGhpcy5pbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQgPSB0cnVlOyB9LA0KICAgICAgICBpc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZDogZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLmltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCA9PT0gdHJ1ZTsgfSwNCiAgICAgICAgc3RvcFByb3BhZ2F0aW9uOiBub29wLA0KICAgICAgICB0eXBlOiBldmVudE5hbWUsDQogICAgICAgIHRhcmdldDogZWxlbWVudA0KICAgICAgfTsNCg0KICAgICAgLy8gSWYgYSBjdXN0b20gZXZlbnQgd2FzIHByb3ZpZGVkIHRoZW4gZXh0ZW5kIG91ciBkdW1teSBldmVudCB3aXRoIGl0DQogICAgICBpZiAoZXZlbnQudHlwZSkgew0KICAgICAgICBkdW1teUV2ZW50ID0gZXh0ZW5kKGR1bW15RXZlbnQsIGV2ZW50KTsNCiAgICAgIH0NCg0KICAgICAgLy8gQ29weSBldmVudCBoYW5kbGVycyBpbiBjYXNlIGV2ZW50IGhhbmRsZXJzIGFycmF5IGlzIG1vZGlmaWVkIGR1cmluZyBleGVjdXRpb24uDQogICAgICBldmVudEZuc0NvcHkgPSBzaGFsbG93Q29weShldmVudEZucyk7DQogICAgICBoYW5kbGVyQXJncyA9IGV4dHJhUGFyYW1ldGVycyA/IFtkdW1teUV2ZW50XS5jb25jYXQoZXh0cmFQYXJhbWV0ZXJzKSA6IFtkdW1teUV2ZW50XTsNCg0KICAgICAgZm9yRWFjaChldmVudEZuc0NvcHksIGZ1bmN0aW9uKGZuKSB7DQogICAgICAgIGlmICghZHVtbXlFdmVudC5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCgpKSB7DQogICAgICAgICAgZm4uYXBwbHkoZWxlbWVudCwgaGFuZGxlckFyZ3MpOw0KICAgICAgICB9DQogICAgICB9KTsNCiAgICB9DQogIH0NCn0sIGZ1bmN0aW9uKGZuLCBuYW1lKSB7DQogIC8qKg0KICAgKiBjaGFpbmluZyBmdW5jdGlvbnMNCiAgICovDQogIEpRTGl0ZS5wcm90b3R5cGVbbmFtZV0gPSBmdW5jdGlvbihhcmcxLCBhcmcyLCBhcmczKSB7DQogICAgdmFyIHZhbHVlOw0KDQogICAgZm9yICh2YXIgaSA9IDAsIGlpID0gdGhpcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7DQogICAgICBpZiAoaXNVbmRlZmluZWQodmFsdWUpKSB7DQogICAgICAgIHZhbHVlID0gZm4odGhpc1tpXSwgYXJnMSwgYXJnMiwgYXJnMyk7DQogICAgICAgIGlmIChpc0RlZmluZWQodmFsdWUpKSB7DQogICAgICAgICAgLy8gYW55IGZ1bmN0aW9uIHdoaWNoIHJldHVybnMgYSB2YWx1ZSBuZWVkcyB0byBiZSB3cmFwcGVkDQogICAgICAgICAgdmFsdWUgPSBqcUxpdGUodmFsdWUpOw0KICAgICAgICB9DQogICAgICB9IGVsc2Ugew0KICAgICAgICBqcUxpdGVBZGROb2Rlcyh2YWx1ZSwgZm4odGhpc1tpXSwgYXJnMSwgYXJnMiwgYXJnMykpOw0KICAgICAgfQ0KICAgIH0NCiAgICByZXR1cm4gaXNEZWZpbmVkKHZhbHVlKSA/IHZhbHVlIDogdGhpczsNCiAgfTsNCg0KICAvLyBiaW5kIGxlZ2FjeSBiaW5kL3VuYmluZCB0byBvbi9vZmYNCiAgSlFMaXRlLnByb3RvdHlwZS5iaW5kID0gSlFMaXRlLnByb3RvdHlwZS5vbjsNCiAgSlFMaXRlLnByb3RvdHlwZS51bmJpbmQgPSBKUUxpdGUucHJvdG90eXBlLm9mZjsNCn0pOw0KDQoNCi8vIFByb3ZpZGVyIGZvciBwcml2YXRlICQkanFMaXRlIHNlcnZpY2UNCmZ1bmN0aW9uICQkanFMaXRlUHJvdmlkZXIoKSB7DQogIHRoaXMuJGdldCA9IGZ1bmN0aW9uICQkanFMaXRlKCkgew0KICAgIHJldHVybiBleHRlbmQoSlFMaXRlLCB7DQogICAgICBoYXNDbGFzczogZnVuY3Rpb24obm9kZSwgY2xhc3Nlcykgew0KICAgICAgICBpZiAobm9kZS5hdHRyKSBub2RlID0gbm9kZVswXTsNCiAgICAgICAgcmV0dXJuIGpxTGl0ZUhhc0NsYXNzKG5vZGUsIGNsYXNzZXMpOw0KICAgICAgfSwNCiAgICAgIGFkZENsYXNzOiBmdW5jdGlvbihub2RlLCBjbGFzc2VzKSB7DQogICAgICAgIGlmIChub2RlLmF0dHIpIG5vZGUgPSBub2RlWzBdOw0KICAgICAgICByZXR1cm4ganFMaXRlQWRkQ2xhc3Mobm9kZSwgY2xhc3Nlcyk7DQogICAgICB9LA0KICAgICAgcmVtb3ZlQ2xhc3M6IGZ1bmN0aW9uKG5vZGUsIGNsYXNzZXMpIHsNCiAgICAgICAgaWYgKG5vZGUuYXR0cikgbm9kZSA9IG5vZGVbMF07DQogICAgICAgIHJldHVybiBqcUxpdGVSZW1vdmVDbGFzcyhub2RlLCBjbGFzc2VzKTsNCiAgICAgIH0NCiAgICB9KTsNCiAgfTsNCn0NCg0KLyoqDQogKiBDb21wdXRlcyBhIGhhc2ggb2YgYW4gJ29iaicuDQogKiBIYXNoIG9mIGE6DQogKiAgc3RyaW5nIGlzIHN0cmluZw0KICogIG51bWJlciBpcyBudW1iZXIgYXMgc3RyaW5nDQogKiAgb2JqZWN0IGlzIGVpdGhlciByZXN1bHQgb2YgY2FsbGluZyAkJGhhc2hLZXkgZnVuY3Rpb24gb24gdGhlIG9iamVjdCBvciB1bmlxdWVseSBnZW5lcmF0ZWQgaWQsDQogKiAgICAgICAgIHRoYXQgaXMgYWxzbyBhc3NpZ25lZCB0byB0aGUgJCRoYXNoS2V5IHByb3BlcnR5IG9mIHRoZSBvYmplY3QuDQogKg0KICogQHBhcmFtIG9iag0KICogQHJldHVybnMge3N0cmluZ30gaGFzaCBzdHJpbmcgc3VjaCB0aGF0IHRoZSBzYW1lIGlucHV0IHdpbGwgaGF2ZSB0aGUgc2FtZSBoYXNoIHN0cmluZy4NCiAqICAgICAgICAgVGhlIHJlc3VsdGluZyBzdHJpbmcga2V5IGlzIGluICd0eXBlOmhhc2hLZXknIGZvcm1hdC4NCiAqLw0KZnVuY3Rpb24gaGFzaEtleShvYmosIG5leHRVaWRGbikgew0KICB2YXIga2V5ID0gb2JqICYmIG9iai4kJGhhc2hLZXk7DQoNCiAgaWYgKGtleSkgew0KICAgIGlmICh0eXBlb2Yga2V5ID09PSAnZnVuY3Rpb24nKSB7DQogICAgICBrZXkgPSBvYmouJCRoYXNoS2V5KCk7DQogICAgfQ0KICAgIHJldHVybiBrZXk7DQogIH0NCg0KICB2YXIgb2JqVHlwZSA9IHR5cGVvZiBvYmo7DQogIGlmIChvYmpUeXBlID09ICdmdW5jdGlvbicgfHwgKG9ialR5cGUgPT0gJ29iamVjdCcgJiYgb2JqICE9PSBudWxsKSkgew0KICAgIGtleSA9IG9iai4kJGhhc2hLZXkgPSBvYmpUeXBlICsgJzonICsgKG5leHRVaWRGbiB8fCBuZXh0VWlkKSgpOw0KICB9IGVsc2Ugew0KICAgIGtleSA9IG9ialR5cGUgKyAnOicgKyBvYmo7DQogIH0NCg0KICByZXR1cm4ga2V5Ow0KfQ0KDQovKioNCiAqIEhhc2hNYXAgd2hpY2ggY2FuIHVzZSBvYmplY3RzIGFzIGtleXMNCiAqLw0KZnVuY3Rpb24gSGFzaE1hcChhcnJheSwgaXNvbGF0ZWRVaWQpIHsNCiAgaWYgKGlzb2xhdGVkVWlkKSB7DQogICAgdmFyIHVpZCA9IDA7DQogICAgdGhpcy5uZXh0VWlkID0gZnVuY3Rpb24oKSB7DQogICAgICByZXR1cm4gKyt1aWQ7DQogICAgfTsNCiAgfQ0KICBmb3JFYWNoKGFycmF5LCB0aGlzLnB1dCwgdGhpcyk7DQp9DQpIYXNoTWFwLnByb3RvdHlwZSA9IHsNCiAgLyoqDQogICAqIFN0b3JlIGtleSB2YWx1ZSBwYWlyDQogICAqIEBwYXJhbSBrZXkga2V5IHRvIHN0b3JlIGNhbiBiZSBhbnkgdHlwZQ0KICAgKiBAcGFyYW0gdmFsdWUgdmFsdWUgdG8gc3RvcmUgY2FuIGJlIGFueSB0eXBlDQogICAqLw0KICBwdXQ6IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHsNCiAgICB0aGlzW2hhc2hLZXkoa2V5LCB0aGlzLm5leHRVaWQpXSA9IHZhbHVlOw0KICB9LA0KDQogIC8qKg0KICAgKiBAcGFyYW0ga2V5DQogICAqIEByZXR1cm5zIHtPYmplY3R9IHRoZSB2YWx1ZSBmb3IgdGhlIGtleQ0KICAgKi8NCiAgZ2V0OiBmdW5jdGlvbihrZXkpIHsNCiAgICByZXR1cm4gdGhpc1toYXNoS2V5KGtleSwgdGhpcy5uZXh0VWlkKV07DQogIH0sDQoNCiAgLyoqDQogICAqIFJlbW92ZSB0aGUga2V5L3ZhbHVlIHBhaXINCiAgICogQHBhcmFtIGtleQ0KICAgKi8NCiAgcmVtb3ZlOiBmdW5jdGlvbihrZXkpIHsNCiAgICB2YXIgdmFsdWUgPSB0aGlzW2tleSA9IGhhc2hLZXkoa2V5LCB0aGlzLm5leHRVaWQpXTsNCiAgICBkZWxldGUgdGhpc1trZXldOw0KICAgIHJldHVybiB2YWx1ZTsNCiAgfQ0KfTsNCg0KLyoqDQogKiBAbmdkb2MgZnVuY3Rpb24NCiAqIEBtb2R1bGUgbmcNCiAqIEBuYW1lIGFuZ3VsYXIuaW5qZWN0b3INCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBDcmVhdGVzIGFuIGluamVjdG9yIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIGZvciByZXRyaWV2aW5nIHNlcnZpY2VzIGFzIHdlbGwgYXMgZm9yDQogKiBkZXBlbmRlbmN5IGluamVjdGlvbiAoc2VlIHtAbGluayBndWlkZS9kaSBkZXBlbmRlbmN5IGluamVjdGlvbn0pLg0KICoNCiAqIEBwYXJhbSB7QXJyYXkuPHN0cmluZ3xGdW5jdGlvbj59IG1vZHVsZXMgQSBsaXN0IG9mIG1vZHVsZSBmdW5jdGlvbnMgb3IgdGhlaXIgYWxpYXNlcy4gU2VlDQogKiAgICAge0BsaW5rIGFuZ3VsYXIubW9kdWxlfS4gVGhlIGBuZ2AgbW9kdWxlIG11c3QgYmUgZXhwbGljaXRseSBhZGRlZC4NCiAqIEBwYXJhbSB7Ym9vbGVhbj19IFtzdHJpY3REaT1mYWxzZV0gV2hldGhlciB0aGUgaW5qZWN0b3Igc2hvdWxkIGJlIGluIHN0cmljdCBtb2RlLCB3aGljaA0KICogICAgIGRpc2FsbG93cyBhcmd1bWVudCBuYW1lIGFubm90YXRpb24gaW5mZXJlbmNlLg0KICogQHJldHVybnMge2luamVjdG9yfSBJbmplY3RvciBvYmplY3QuIFNlZSB7QGxpbmsgYXV0by4kaW5qZWN0b3IgJGluamVjdG9yfS4NCiAqDQogKiBAZXhhbXBsZQ0KICogVHlwaWNhbCB1c2FnZQ0KICogYGBganMNCiAqICAgLy8gY3JlYXRlIGFuIGluamVjdG9yDQogKiAgIHZhciAkaW5qZWN0b3IgPSBhbmd1bGFyLmluamVjdG9yKFsnbmcnXSk7DQogKg0KICogICAvLyB1c2UgdGhlIGluamVjdG9yIHRvIGtpY2sgb2ZmIHlvdXIgYXBwbGljYXRpb24NCiAqICAgLy8gdXNlIHRoZSB0eXBlIGluZmVyZW5jZSB0byBhdXRvIGluamVjdCBhcmd1bWVudHMsIG9yIHVzZSBpbXBsaWNpdCBpbmplY3Rpb24NCiAqICAgJGluamVjdG9yLmludm9rZShmdW5jdGlvbigkcm9vdFNjb3BlLCAkY29tcGlsZSwgJGRvY3VtZW50KSB7DQogKiAgICAgJGNvbXBpbGUoJGRvY3VtZW50KSgkcm9vdFNjb3BlKTsNCiAqICAgICAkcm9vdFNjb3BlLiRkaWdlc3QoKTsNCiAqICAgfSk7DQogKiBgYGANCiAqDQogKiBTb21ldGltZXMgeW91IHdhbnQgdG8gZ2V0IGFjY2VzcyB0byB0aGUgaW5qZWN0b3Igb2YgYSBjdXJyZW50bHkgcnVubmluZyBBbmd1bGFyIGFwcA0KICogZnJvbSBvdXRzaWRlIEFuZ3VsYXIuIFBlcmhhcHMsIHlvdSB3YW50IHRvIGluamVjdCBhbmQgY29tcGlsZSBzb21lIG1hcmt1cCBhZnRlciB0aGUNCiAqIGFwcGxpY2F0aW9uIGhhcyBiZWVuIGJvb3RzdHJhcHBlZC4gWW91IGNhbiBkbyB0aGlzIHVzaW5nIHRoZSBleHRyYSBgaW5qZWN0b3IoKWAgYWRkZWQNCiAqIHRvIEpRdWVyeS9qcUxpdGUgZWxlbWVudHMuIFNlZSB7QGxpbmsgYW5ndWxhci5lbGVtZW50fS4NCiAqDQogKiAqVGhpcyBpcyBmYWlybHkgcmFyZSBidXQgY291bGQgYmUgdGhlIGNhc2UgaWYgYSB0aGlyZCBwYXJ0eSBsaWJyYXJ5IGlzIGluamVjdGluZyB0aGUNCiAqIG1hcmt1cC4qDQogKg0KICogSW4gdGhlIGZvbGxvd2luZyBleGFtcGxlIGEgbmV3IGJsb2NrIG9mIEhUTUwgY29udGFpbmluZyBhIGBuZy1jb250cm9sbGVyYA0KICogZGlyZWN0aXZlIGlzIGFkZGVkIHRvIHRoZSBlbmQgb2YgdGhlIGRvY3VtZW50IGJvZHkgYnkgSlF1ZXJ5LiBXZSB0aGVuIGNvbXBpbGUgYW5kIGxpbmsNCiAqIGl0IGludG8gdGhlIGN1cnJlbnQgQW5ndWxhckpTIHNjb3BlLg0KICoNCiAqIGBgYGpzDQogKiB2YXIgJGRpdiA9ICQoJzxkaXYgbmctY29udHJvbGxlcj0iTXlDdHJsIj57e2NvbnRlbnQubGFiZWx9fTwvZGl2PicpOw0KICogJChkb2N1bWVudC5ib2R5KS5hcHBlbmQoJGRpdik7DQogKg0KICogYW5ndWxhci5lbGVtZW50KGRvY3VtZW50KS5pbmplY3RvcigpLmludm9rZShmdW5jdGlvbigkY29tcGlsZSkgew0KICogICB2YXIgc2NvcGUgPSBhbmd1bGFyLmVsZW1lbnQoJGRpdikuc2NvcGUoKTsNCiAqICAgJGNvbXBpbGUoJGRpdikoc2NvcGUpOw0KICogfSk7DQogKiBgYGANCiAqLw0KDQoNCi8qKg0KICogQG5nZG9jIG1vZHVsZQ0KICogQG5hbWUgYXV0bw0KICogQGRlc2NyaXB0aW9uDQogKg0KICogSW1wbGljaXQgbW9kdWxlIHdoaWNoIGdldHMgYXV0b21hdGljYWxseSBhZGRlZCB0byBlYWNoIHtAbGluayBhdXRvLiRpbmplY3RvciAkaW5qZWN0b3J9Lg0KICovDQoNCnZhciBGTl9BUkdTID0gL15mdW5jdGlvblxzKlteXChdKlwoXHMqKFteXCldKilcKS9tOw0KdmFyIEZOX0FSR19TUExJVCA9IC8sLzsNCnZhciBGTl9BUkcgPSAvXlxzKihfPykoXFMrPylcMVxzKiQvOw0KdmFyIFNUUklQX0NPTU1FTlRTID0gLygoXC9cLy4qJCl8KFwvXCpbXHNcU10qP1wqXC8pKS9tZzsNCnZhciAkaW5qZWN0b3JNaW5FcnIgPSBtaW5FcnIoJyRpbmplY3RvcicpOw0KDQpmdW5jdGlvbiBhbm9uRm4oZm4pIHsNCiAgLy8gRm9yIGFub255bW91cyBmdW5jdGlvbnMsIHNob3dpbmcgYXQgdGhlIHZlcnkgbGVhc3QgdGhlIGZ1bmN0aW9uIHNpZ25hdHVyZSBjYW4gaGVscCBpbg0KICAvLyBkZWJ1Z2dpbmcuDQogIHZhciBmblRleHQgPSBmbi50b1N0cmluZygpLnJlcGxhY2UoU1RSSVBfQ09NTUVOVFMsICcnKSwNCiAgICAgIGFyZ3MgPSBmblRleHQubWF0Y2goRk5fQVJHUyk7DQogIGlmIChhcmdzKSB7DQogICAgcmV0dXJuICdmdW5jdGlvbignICsgKGFyZ3NbMV0gfHwgJycpLnJlcGxhY2UoL1tcc1xyXG5dKy8sICcgJykgKyAnKSc7DQogIH0NCiAgcmV0dXJuICdmbic7DQp9DQoNCmZ1bmN0aW9uIGFubm90YXRlKGZuLCBzdHJpY3REaSwgbmFtZSkgew0KICB2YXIgJGluamVjdCwNCiAgICAgIGZuVGV4dCwNCiAgICAgIGFyZ0RlY2wsDQogICAgICBsYXN0Ow0KDQogIGlmICh0eXBlb2YgZm4gPT09ICdmdW5jdGlvbicpIHsNCiAgICBpZiAoISgkaW5qZWN0ID0gZm4uJGluamVjdCkpIHsNCiAgICAgICRpbmplY3QgPSBbXTsNCiAgICAgIGlmIChmbi5sZW5ndGgpIHsNCiAgICAgICAgaWYgKHN0cmljdERpKSB7DQogICAgICAgICAgaWYgKCFpc1N0cmluZyhuYW1lKSB8fCAhbmFtZSkgew0KICAgICAgICAgICAgbmFtZSA9IGZuLm5hbWUgfHwgYW5vbkZuKGZuKTsNCiAgICAgICAgICB9DQogICAgICAgICAgdGhyb3cgJGluamVjdG9yTWluRXJyKCdzdHJpY3RkaScsDQogICAgICAgICAgICAnezB9IGlzIG5vdCB1c2luZyBleHBsaWNpdCBhbm5vdGF0aW9uIGFuZCBjYW5ub3QgYmUgaW52b2tlZCBpbiBzdHJpY3QgbW9kZScsIG5hbWUpOw0KICAgICAgICB9DQogICAgICAgIGZuVGV4dCA9IGZuLnRvU3RyaW5nKCkucmVwbGFjZShTVFJJUF9DT01NRU5UUywgJycpOw0KICAgICAgICBhcmdEZWNsID0gZm5UZXh0Lm1hdGNoKEZOX0FSR1MpOw0KICAgICAgICBmb3JFYWNoKGFyZ0RlY2xbMV0uc3BsaXQoRk5fQVJHX1NQTElUKSwgZnVuY3Rpb24oYXJnKSB7DQogICAgICAgICAgYXJnLnJlcGxhY2UoRk5fQVJHLCBmdW5jdGlvbihhbGwsIHVuZGVyc2NvcmUsIG5hbWUpIHsNCiAgICAgICAgICAgICRpbmplY3QucHVzaChuYW1lKTsNCiAgICAgICAgICB9KTsNCiAgICAgICAgfSk7DQogICAgICB9DQogICAgICBmbi4kaW5qZWN0ID0gJGluamVjdDsNCiAgICB9DQogIH0gZWxzZSBpZiAoaXNBcnJheShmbikpIHsNCiAgICBsYXN0ID0gZm4ubGVuZ3RoIC0gMTsNCiAgICBhc3NlcnRBcmdGbihmbltsYXN0XSwgJ2ZuJyk7DQogICAgJGluamVjdCA9IGZuLnNsaWNlKDAsIGxhc3QpOw0KICB9IGVsc2Ugew0KICAgIGFzc2VydEFyZ0ZuKGZuLCAnZm4nLCB0cnVlKTsNCiAgfQ0KICByZXR1cm4gJGluamVjdDsNCn0NCg0KLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vDQoNCi8qKg0KICogQG5nZG9jIHNlcnZpY2UNCiAqIEBuYW1lICRpbmplY3Rvcg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICoNCiAqIGAkaW5qZWN0b3JgIGlzIHVzZWQgdG8gcmV0cmlldmUgb2JqZWN0IGluc3RhbmNlcyBhcyBkZWZpbmVkIGJ5DQogKiB7QGxpbmsgYXV0by4kcHJvdmlkZSBwcm92aWRlcn0sIGluc3RhbnRpYXRlIHR5cGVzLCBpbnZva2UgbWV0aG9kcywNCiAqIGFuZCBsb2FkIG1vZHVsZXMuDQogKg0KICogVGhlIGZvbGxvd2luZyBhbHdheXMgaG9sZHMgdHJ1ZToNCiAqDQogKiBgYGBqcw0KICogICB2YXIgJGluamVjdG9yID0gYW5ndWxhci5pbmplY3RvcigpOw0KICogICBleHBlY3QoJGluamVjdG9yLmdldCgnJGluamVjdG9yJykpLnRvQmUoJGluamVjdG9yKTsNCiAqICAgZXhwZWN0KCRpbmplY3Rvci5pbnZva2UoZnVuY3Rpb24oJGluamVjdG9yKSB7DQogKiAgICAgcmV0dXJuICRpbmplY3RvcjsNCiAqICAgfSkpLnRvQmUoJGluamVjdG9yKTsNCiAqIGBgYA0KICoNCiAqICMgSW5qZWN0aW9uIEZ1bmN0aW9uIEFubm90YXRpb24NCiAqDQogKiBKYXZhU2NyaXB0IGRvZXMgbm90IGhhdmUgYW5ub3RhdGlvbnMsIGFuZCBhbm5vdGF0aW9ucyBhcmUgbmVlZGVkIGZvciBkZXBlbmRlbmN5IGluamVjdGlvbi4gVGhlDQogKiBmb2xsb3dpbmcgYXJlIGFsbCB2YWxpZCB3YXlzIG9mIGFubm90YXRpbmcgZnVuY3Rpb24gd2l0aCBpbmplY3Rpb24gYXJndW1lbnRzIGFuZCBhcmUgZXF1aXZhbGVudC4NCiAqDQogKiBgYGBqcw0KICogICAvLyBpbmZlcnJlZCAob25seSB3b3JrcyBpZiBjb2RlIG5vdCBtaW5pZmllZC9vYmZ1c2NhdGVkKQ0KICogICAkaW5qZWN0b3IuaW52b2tlKGZ1bmN0aW9uKHNlcnZpY2VBKXt9KTsNCiAqDQogKiAgIC8vIGFubm90YXRlZA0KICogICBmdW5jdGlvbiBleHBsaWNpdChzZXJ2aWNlQSkge307DQogKiAgIGV4cGxpY2l0LiRpbmplY3QgPSBbJ3NlcnZpY2VBJ107DQogKiAgICRpbmplY3Rvci5pbnZva2UoZXhwbGljaXQpOw0KICoNCiAqICAgLy8gaW5saW5lDQogKiAgICRpbmplY3Rvci5pbnZva2UoWydzZXJ2aWNlQScsIGZ1bmN0aW9uKHNlcnZpY2VBKXt9XSk7DQogKiBgYGANCiAqDQogKiAjIyBJbmZlcmVuY2UNCiAqDQogKiBJbiBKYXZhU2NyaXB0IGNhbGxpbmcgYHRvU3RyaW5nKClgIG9uIGEgZnVuY3Rpb24gcmV0dXJucyB0aGUgZnVuY3Rpb24gZGVmaW5pdGlvbi4gVGhlIGRlZmluaXRpb24NCiAqIGNhbiB0aGVuIGJlIHBhcnNlZCBhbmQgdGhlIGZ1bmN0aW9uIGFyZ3VtZW50cyBjYW4gYmUgZXh0cmFjdGVkLiBUaGlzIG1ldGhvZCBvZiBkaXNjb3ZlcmluZw0KICogYW5ub3RhdGlvbnMgaXMgZGlzYWxsb3dlZCB3aGVuIHRoZSBpbmplY3RvciBpcyBpbiBzdHJpY3QgbW9kZS4NCiAqICpOT1RFOiogVGhpcyBkb2VzIG5vdCB3b3JrIHdpdGggbWluaWZpY2F0aW9uLCBhbmQgb2JmdXNjYXRpb24gdG9vbHMgc2luY2UgdGhlc2UgdG9vbHMgY2hhbmdlIHRoZQ0KICogYXJndW1lbnQgbmFtZXMuDQogKg0KICogIyMgYCRpbmplY3RgIEFubm90YXRpb24NCiAqIEJ5IGFkZGluZyBhbiBgJGluamVjdGAgcHJvcGVydHkgb250byBhIGZ1bmN0aW9uIHRoZSBpbmplY3Rpb24gcGFyYW1ldGVycyBjYW4gYmUgc3BlY2lmaWVkLg0KICoNCiAqICMjIElubGluZQ0KICogQXMgYW4gYXJyYXkgb2YgaW5qZWN0aW9uIG5hbWVzLCB3aGVyZSB0aGUgbGFzdCBpdGVtIGluIHRoZSBhcnJheSBpcyB0aGUgZnVuY3Rpb24gdG8gY2FsbC4NCiAqLw0KDQovKioNCiAqIEBuZ2RvYyBtZXRob2QNCiAqIEBuYW1lICRpbmplY3RvciNnZXQNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFJldHVybiBhbiBpbnN0YW5jZSBvZiB0aGUgc2VydmljZS4NCiAqDQogKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgaW5zdGFuY2UgdG8gcmV0cmlldmUuDQogKiBAcGFyYW0ge3N0cmluZ30gY2FsbGVyIEFuIG9wdGlvbmFsIHN0cmluZyB0byBwcm92aWRlIHRoZSBvcmlnaW4gb2YgdGhlIGZ1bmN0aW9uIGNhbGwgZm9yIGVycm9yIG1lc3NhZ2VzLg0KICogQHJldHVybiB7Kn0gVGhlIGluc3RhbmNlLg0KICovDQoNCi8qKg0KICogQG5nZG9jIG1ldGhvZA0KICogQG5hbWUgJGluamVjdG9yI2ludm9rZQ0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogSW52b2tlIHRoZSBtZXRob2QgYW5kIHN1cHBseSB0aGUgbWV0aG9kIGFyZ3VtZW50cyBmcm9tIHRoZSBgJGluamVjdG9yYC4NCiAqDQogKiBAcGFyYW0geyFGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIGludm9rZS4gRnVuY3Rpb24gcGFyYW1ldGVycyBhcmUgaW5qZWN0ZWQgYWNjb3JkaW5nIHRvIHRoZQ0KICogICB7QGxpbmsgZ3VpZGUvZGkgJGluamVjdCBBbm5vdGF0aW9ufSBydWxlcy4NCiAqIEBwYXJhbSB7T2JqZWN0PX0gc2VsZiBUaGUgYHRoaXNgIGZvciB0aGUgaW52b2tlZCBtZXRob2QuDQogKiBAcGFyYW0ge09iamVjdD19IGxvY2FscyBPcHRpb25hbCBvYmplY3QuIElmIHByZXNldCB0aGVuIGFueSBhcmd1bWVudCBuYW1lcyBhcmUgcmVhZCBmcm9tIHRoaXMNCiAqICAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdCBmaXJzdCwgYmVmb3JlIHRoZSBgJGluamVjdG9yYCBpcyBjb25zdWx0ZWQuDQogKiBAcmV0dXJucyB7Kn0gdGhlIHZhbHVlIHJldHVybmVkIGJ5IHRoZSBpbnZva2VkIGBmbmAgZnVuY3Rpb24uDQogKi8NCg0KLyoqDQogKiBAbmdkb2MgbWV0aG9kDQogKiBAbmFtZSAkaW5qZWN0b3IjaGFzDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBBbGxvd3MgdGhlIHVzZXIgdG8gcXVlcnkgaWYgdGhlIHBhcnRpY3VsYXIgc2VydmljZSBleGlzdHMuDQogKg0KICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgc2VydmljZSB0byBxdWVyeS4NCiAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgaW5qZWN0b3IgaGFzIGdpdmVuIHNlcnZpY2UuDQogKi8NCg0KLyoqDQogKiBAbmdkb2MgbWV0aG9kDQogKiBAbmFtZSAkaW5qZWN0b3IjaW5zdGFudGlhdGUNCiAqIEBkZXNjcmlwdGlvbg0KICogQ3JlYXRlIGEgbmV3IGluc3RhbmNlIG9mIEpTIHR5cGUuIFRoZSBtZXRob2QgdGFrZXMgYSBjb25zdHJ1Y3RvciBmdW5jdGlvbiwgaW52b2tlcyB0aGUgbmV3DQogKiBvcGVyYXRvciwgYW5kIHN1cHBsaWVzIGFsbCBvZiB0aGUgYXJndW1lbnRzIHRvIHRoZSBjb25zdHJ1Y3RvciBmdW5jdGlvbiBhcyBzcGVjaWZpZWQgYnkgdGhlDQogKiBjb25zdHJ1Y3RvciBhbm5vdGF0aW9uLg0KICoNCiAqIEBwYXJhbSB7RnVuY3Rpb259IFR5cGUgQW5ub3RhdGVkIGNvbnN0cnVjdG9yIGZ1bmN0aW9uLg0KICogQHBhcmFtIHtPYmplY3Q9fSBsb2NhbHMgT3B0aW9uYWwgb2JqZWN0LiBJZiBwcmVzZXQgdGhlbiBhbnkgYXJndW1lbnQgbmFtZXMgYXJlIHJlYWQgZnJvbSB0aGlzDQogKiBvYmplY3QgZmlyc3QsIGJlZm9yZSB0aGUgYCRpbmplY3RvcmAgaXMgY29uc3VsdGVkLg0KICogQHJldHVybnMge09iamVjdH0gbmV3IGluc3RhbmNlIG9mIGBUeXBlYC4NCiAqLw0KDQovKioNCiAqIEBuZ2RvYyBtZXRob2QNCiAqIEBuYW1lICRpbmplY3RvciNhbm5vdGF0ZQ0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogUmV0dXJucyBhbiBhcnJheSBvZiBzZXJ2aWNlIG5hbWVzIHdoaWNoIHRoZSBmdW5jdGlvbiBpcyByZXF1ZXN0aW5nIGZvciBpbmplY3Rpb24uIFRoaXMgQVBJIGlzDQogKiB1c2VkIGJ5IHRoZSBpbmplY3RvciB0byBkZXRlcm1pbmUgd2hpY2ggc2VydmljZXMgbmVlZCB0byBiZSBpbmplY3RlZCBpbnRvIHRoZSBmdW5jdGlvbiB3aGVuIHRoZQ0KICogZnVuY3Rpb24gaXMgaW52b2tlZC4gVGhlcmUgYXJlIHRocmVlIHdheXMgaW4gd2hpY2ggdGhlIGZ1bmN0aW9uIGNhbiBiZSBhbm5vdGF0ZWQgd2l0aCB0aGUgbmVlZGVkDQogKiBkZXBlbmRlbmNpZXMuDQogKg0KICogIyBBcmd1bWVudCBuYW1lcw0KICoNCiAqIFRoZSBzaW1wbGVzdCBmb3JtIGlzIHRvIGV4dHJhY3QgdGhlIGRlcGVuZGVuY2llcyBmcm9tIHRoZSBhcmd1bWVudHMgb2YgdGhlIGZ1bmN0aW9uLiBUaGlzIGlzIGRvbmUNCiAqIGJ5IGNvbnZlcnRpbmcgdGhlIGZ1bmN0aW9uIGludG8gYSBzdHJpbmcgdXNpbmcgYHRvU3RyaW5nKClgIG1ldGhvZCBhbmQgZXh0cmFjdGluZyB0aGUgYXJndW1lbnQNCiAqIG5hbWVzLg0KICogYGBganMNCiAqICAgLy8gR2l2ZW4NCiAqICAgZnVuY3Rpb24gTXlDb250cm9sbGVyKCRzY29wZSwgJHJvdXRlKSB7DQogKiAgICAgLy8gLi4uDQogKiAgIH0NCiAqDQogKiAgIC8vIFRoZW4NCiAqICAgZXhwZWN0KGluamVjdG9yLmFubm90YXRlKE15Q29udHJvbGxlcikpLnRvRXF1YWwoWyckc2NvcGUnLCAnJHJvdXRlJ10pOw0KICogYGBgDQogKg0KICogWW91IGNhbiBkaXNhbGxvdyB0aGlzIG1ldGhvZCBieSB1c2luZyBzdHJpY3QgaW5qZWN0aW9uIG1vZGUuDQogKg0KICogVGhpcyBtZXRob2QgZG9lcyBub3Qgd29yayB3aXRoIGNvZGUgbWluaWZpY2F0aW9uIC8gb2JmdXNjYXRpb24uIEZvciB0aGlzIHJlYXNvbiB0aGUgZm9sbG93aW5nDQogKiBhbm5vdGF0aW9uIHN0cmF0ZWdpZXMgYXJlIHN1cHBvcnRlZC4NCiAqDQogKiAjIFRoZSBgJGluamVjdGAgcHJvcGVydHkNCiAqDQogKiBJZiBhIGZ1bmN0aW9uIGhhcyBhbiBgJGluamVjdGAgcHJvcGVydHkgYW5kIGl0cyB2YWx1ZSBpcyBhbiBhcnJheSBvZiBzdHJpbmdzLCB0aGVuIHRoZSBzdHJpbmdzDQogKiByZXByZXNlbnQgbmFtZXMgb2Ygc2VydmljZXMgdG8gYmUgaW5qZWN0ZWQgaW50byB0aGUgZnVuY3Rpb24uDQogKiBgYGBqcw0KICogICAvLyBHaXZlbg0KICogICB2YXIgTXlDb250cm9sbGVyID0gZnVuY3Rpb24ob2JmdXNjYXRlZFNjb3BlLCBvYmZ1c2NhdGVkUm91dGUpIHsNCiAqICAgICAvLyAuLi4NCiAqICAgfQ0KICogICAvLyBEZWZpbmUgZnVuY3Rpb24gZGVwZW5kZW5jaWVzDQogKiAgIE15Q29udHJvbGxlclsnJGluamVjdCddID0gWyckc2NvcGUnLCAnJHJvdXRlJ107DQogKg0KICogICAvLyBUaGVuDQogKiAgIGV4cGVjdChpbmplY3Rvci5hbm5vdGF0ZShNeUNvbnRyb2xsZXIpKS50b0VxdWFsKFsnJHNjb3BlJywgJyRyb3V0ZSddKTsNCiAqIGBgYA0KICoNCiAqICMgVGhlIGFycmF5IG5vdGF0aW9uDQogKg0KICogSXQgaXMgb2Z0ZW4gZGVzaXJhYmxlIHRvIGlubGluZSBJbmplY3RlZCBmdW5jdGlvbnMgYW5kIHRoYXQncyB3aGVuIHNldHRpbmcgdGhlIGAkaW5qZWN0YCBwcm9wZXJ0eQ0KICogaXMgdmVyeSBpbmNvbnZlbmllbnQuIEluIHRoZXNlIHNpdHVhdGlvbnMgdXNpbmcgdGhlIGFycmF5IG5vdGF0aW9uIHRvIHNwZWNpZnkgdGhlIGRlcGVuZGVuY2llcyBpbg0KICogYSB3YXkgdGhhdCBzdXJ2aXZlcyBtaW5pZmljYXRpb24gaXMgYSBiZXR0ZXIgY2hvaWNlOg0KICoNCiAqIGBgYGpzDQogKiAgIC8vIFdlIHdpc2ggdG8gd3JpdGUgdGhpcyAobm90IG1pbmlmaWNhdGlvbiAvIG9iZnVzY2F0aW9uIHNhZmUpDQogKiAgIGluamVjdG9yLmludm9rZShmdW5jdGlvbigkY29tcGlsZSwgJHJvb3RTY29wZSkgew0KICogICAgIC8vIC4uLg0KICogICB9KTsNCiAqDQogKiAgIC8vIFdlIGFyZSBmb3JjZWQgdG8gd3JpdGUgYnJlYWsgaW5saW5pbmcNCiAqICAgdmFyIHRtcEZuID0gZnVuY3Rpb24ob2JmdXNjYXRlZENvbXBpbGUsIG9iZnVzY2F0ZWRSb290U2NvcGUpIHsNCiAqICAgICAvLyAuLi4NCiAqICAgfTsNCiAqICAgdG1wRm4uJGluamVjdCA9IFsnJGNvbXBpbGUnLCAnJHJvb3RTY29wZSddOw0KICogICBpbmplY3Rvci5pbnZva2UodG1wRm4pOw0KICoNCiAqICAgLy8gVG8gYmV0dGVyIHN1cHBvcnQgaW5saW5lIGZ1bmN0aW9uIHRoZSBpbmxpbmUgYW5ub3RhdGlvbiBpcyBzdXBwb3J0ZWQNCiAqICAgaW5qZWN0b3IuaW52b2tlKFsnJGNvbXBpbGUnLCAnJHJvb3RTY29wZScsIGZ1bmN0aW9uKG9iZkNvbXBpbGUsIG9iZlJvb3RTY29wZSkgew0KICogICAgIC8vIC4uLg0KICogICB9XSk7DQogKg0KICogICAvLyBUaGVyZWZvcmUNCiAqICAgZXhwZWN0KGluamVjdG9yLmFubm90YXRlKA0KICogICAgICBbJyRjb21waWxlJywgJyRyb290U2NvcGUnLCBmdW5jdGlvbihvYmZ1c18kY29tcGlsZSwgb2JmdXNfJHJvb3RTY29wZSkge31dKQ0KICogICAgKS50b0VxdWFsKFsnJGNvbXBpbGUnLCAnJHJvb3RTY29wZSddKTsNCiAqIGBgYA0KICoNCiAqIEBwYXJhbSB7RnVuY3Rpb258QXJyYXkuPHN0cmluZ3xGdW5jdGlvbj59IGZuIEZ1bmN0aW9uIGZvciB3aGljaCBkZXBlbmRlbnQgc2VydmljZSBuYW1lcyBuZWVkIHRvDQogKiBiZSByZXRyaWV2ZWQgYXMgZGVzY3JpYmVkIGFib3ZlLg0KICoNCiAqIEBwYXJhbSB7Ym9vbGVhbj19IFtzdHJpY3REaT1mYWxzZV0gRGlzYWxsb3cgYXJndW1lbnQgbmFtZSBhbm5vdGF0aW9uIGluZmVyZW5jZS4NCiAqDQogKiBAcmV0dXJucyB7QXJyYXkuPHN0cmluZz59IFRoZSBuYW1lcyBvZiB0aGUgc2VydmljZXMgd2hpY2ggdGhlIGZ1bmN0aW9uIHJlcXVpcmVzLg0KICovDQoNCg0KDQoNCi8qKg0KICogQG5nZG9jIHNlcnZpY2UNCiAqIEBuYW1lICRwcm92aWRlDQogKg0KICogQGRlc2NyaXB0aW9uDQogKg0KICogVGhlIHtAbGluayBhdXRvLiRwcm92aWRlICRwcm92aWRlfSBzZXJ2aWNlIGhhcyBhIG51bWJlciBvZiBtZXRob2RzIGZvciByZWdpc3RlcmluZyBjb21wb25lbnRzDQogKiB3aXRoIHRoZSB7QGxpbmsgYXV0by4kaW5qZWN0b3IgJGluamVjdG9yfS4gTWFueSBvZiB0aGVzZSBmdW5jdGlvbnMgYXJlIGFsc28gZXhwb3NlZCBvbg0KICoge0BsaW5rIGFuZ3VsYXIuTW9kdWxlfS4NCiAqDQogKiBBbiBBbmd1bGFyICoqc2VydmljZSoqIGlzIGEgc2luZ2xldG9uIG9iamVjdCBjcmVhdGVkIGJ5IGEgKipzZXJ2aWNlIGZhY3RvcnkqKi4gIFRoZXNlICoqc2VydmljZQ0KICogZmFjdG9yaWVzKiogYXJlIGZ1bmN0aW9ucyB3aGljaCwgaW4gdHVybiwgYXJlIGNyZWF0ZWQgYnkgYSAqKnNlcnZpY2UgcHJvdmlkZXIqKi4NCiAqIFRoZSAqKnNlcnZpY2UgcHJvdmlkZXJzKiogYXJlIGNvbnN0cnVjdG9yIGZ1bmN0aW9ucy4gV2hlbiBpbnN0YW50aWF0ZWQgdGhleSBtdXN0IGNvbnRhaW4gYQ0KICogcHJvcGVydHkgY2FsbGVkIGAkZ2V0YCwgd2hpY2ggaG9sZHMgdGhlICoqc2VydmljZSBmYWN0b3J5KiogZnVuY3Rpb24uDQogKg0KICogV2hlbiB5b3UgcmVxdWVzdCBhIHNlcnZpY2UsIHRoZSB7QGxpbmsgYXV0by4kaW5qZWN0b3IgJGluamVjdG9yfSBpcyByZXNwb25zaWJsZSBmb3IgZmluZGluZyB0aGUNCiAqIGNvcnJlY3QgKipzZXJ2aWNlIHByb3ZpZGVyKiosIGluc3RhbnRpYXRpbmcgaXQgYW5kIHRoZW4gY2FsbGluZyBpdHMgYCRnZXRgICoqc2VydmljZSBmYWN0b3J5KioNCiAqIGZ1bmN0aW9uIHRvIGdldCB0aGUgaW5zdGFuY2Ugb2YgdGhlICoqc2VydmljZSoqLg0KICoNCiAqIE9mdGVuIHNlcnZpY2VzIGhhdmUgbm8gY29uZmlndXJhdGlvbiBvcHRpb25zIGFuZCB0aGVyZSBpcyBubyBuZWVkIHRvIGFkZCBtZXRob2RzIHRvIHRoZSBzZXJ2aWNlDQogKiBwcm92aWRlci4gIFRoZSBwcm92aWRlciB3aWxsIGJlIG5vIG1vcmUgdGhhbiBhIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIHdpdGggYSBgJGdldGAgcHJvcGVydHkuIEZvcg0KICogdGhlc2UgY2FzZXMgdGhlIHtAbGluayBhdXRvLiRwcm92aWRlICRwcm92aWRlfSBzZXJ2aWNlIGhhcyBhZGRpdGlvbmFsIGhlbHBlciBtZXRob2RzIHRvIHJlZ2lzdGVyDQogKiBzZXJ2aWNlcyB3aXRob3V0IHNwZWNpZnlpbmcgYSBwcm92aWRlci4NCiAqDQogKiAqIHtAbGluayBhdXRvLiRwcm92aWRlI3Byb3ZpZGVyIHByb3ZpZGVyKHByb3ZpZGVyKX0gLSByZWdpc3RlcnMgYSAqKnNlcnZpY2UgcHJvdmlkZXIqKiB3aXRoIHRoZQ0KICogICAgIHtAbGluayBhdXRvLiRpbmplY3RvciAkaW5qZWN0b3J9DQogKiAqIHtAbGluayBhdXRvLiRwcm92aWRlI2NvbnN0YW50IGNvbnN0YW50KG9iail9IC0gcmVnaXN0ZXJzIGEgdmFsdWUvb2JqZWN0IHRoYXQgY2FuIGJlIGFjY2Vzc2VkIGJ5DQogKiAgICAgcHJvdmlkZXJzIGFuZCBzZXJ2aWNlcy4NCiAqICoge0BsaW5rIGF1dG8uJHByb3ZpZGUjdmFsdWUgdmFsdWUob2JqKX0gLSByZWdpc3RlcnMgYSB2YWx1ZS9vYmplY3QgdGhhdCBjYW4gb25seSBiZSBhY2Nlc3NlZCBieQ0KICogICAgIHNlcnZpY2VzLCBub3QgcHJvdmlkZXJzLg0KICogKiB7QGxpbmsgYXV0by4kcHJvdmlkZSNmYWN0b3J5IGZhY3RvcnkoZm4pfSAtIHJlZ2lzdGVycyBhIHNlcnZpY2UgKipmYWN0b3J5IGZ1bmN0aW9uKiosIGBmbmAsDQogKiAgICAgdGhhdCB3aWxsIGJlIHdyYXBwZWQgaW4gYSAqKnNlcnZpY2UgcHJvdmlkZXIqKiBvYmplY3QsIHdob3NlIGAkZ2V0YCBwcm9wZXJ0eSB3aWxsIGNvbnRhaW4gdGhlDQogKiAgICAgZ2l2ZW4gZmFjdG9yeSBmdW5jdGlvbi4NCiAqICoge0BsaW5rIGF1dG8uJHByb3ZpZGUjc2VydmljZSBzZXJ2aWNlKGNsYXNzKX0gLSByZWdpc3RlcnMgYSAqKmNvbnN0cnVjdG9yIGZ1bmN0aW9uKiosIGBjbGFzc2ANCiAqICAgICB0aGF0IHdpbGwgYmUgd3JhcHBlZCBpbiBhICoqc2VydmljZSBwcm92aWRlcioqIG9iamVjdCwgd2hvc2UgYCRnZXRgIHByb3BlcnR5IHdpbGwgaW5zdGFudGlhdGUNCiAqICAgICAgYSBuZXcgb2JqZWN0IHVzaW5nIHRoZSBnaXZlbiBjb25zdHJ1Y3RvciBmdW5jdGlvbi4NCiAqDQogKiBTZWUgdGhlIGluZGl2aWR1YWwgbWV0aG9kcyBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhbmQgZXhhbXBsZXMuDQogKi8NCg0KLyoqDQogKiBAbmdkb2MgbWV0aG9kDQogKiBAbmFtZSAkcHJvdmlkZSNwcm92aWRlcg0KICogQGRlc2NyaXB0aW9uDQogKg0KICogUmVnaXN0ZXIgYSAqKnByb3ZpZGVyIGZ1bmN0aW9uKiogd2l0aCB0aGUge0BsaW5rIGF1dG8uJGluamVjdG9yICRpbmplY3Rvcn0uIFByb3ZpZGVyIGZ1bmN0aW9ucw0KICogYXJlIGNvbnN0cnVjdG9yIGZ1bmN0aW9ucywgd2hvc2UgaW5zdGFuY2VzIGFyZSByZXNwb25zaWJsZSBmb3IgInByb3ZpZGluZyIgYSBmYWN0b3J5IGZvciBhDQogKiBzZXJ2aWNlLg0KICoNCiAqIFNlcnZpY2UgcHJvdmlkZXIgbmFtZXMgc3RhcnQgd2l0aCB0aGUgbmFtZSBvZiB0aGUgc2VydmljZSB0aGV5IHByb3ZpZGUgZm9sbG93ZWQgYnkgYFByb3ZpZGVyYC4NCiAqIEZvciBleGFtcGxlLCB0aGUge0BsaW5rIG5nLiRsb2cgJGxvZ30gc2VydmljZSBoYXMgYSBwcm92aWRlciBjYWxsZWQNCiAqIHtAbGluayBuZy4kbG9nUHJvdmlkZXIgJGxvZ1Byb3ZpZGVyfS4NCiAqDQogKiBTZXJ2aWNlIHByb3ZpZGVyIG9iamVjdHMgY2FuIGhhdmUgYWRkaXRpb25hbCBtZXRob2RzIHdoaWNoIGFsbG93IGNvbmZpZ3VyYXRpb24gb2YgdGhlIHByb3ZpZGVyDQogKiBhbmQgaXRzIHNlcnZpY2UuIEltcG9ydGFudGx5LCB5b3UgY2FuIGNvbmZpZ3VyZSB3aGF0IGtpbmQgb2Ygc2VydmljZSBpcyBjcmVhdGVkIGJ5IHRoZSBgJGdldGANCiAqIG1ldGhvZCwgb3IgaG93IHRoYXQgc2VydmljZSB3aWxsIGFjdC4gRm9yIGV4YW1wbGUsIHRoZSB7QGxpbmsgbmcuJGxvZ1Byb3ZpZGVyICRsb2dQcm92aWRlcn0gaGFzIGENCiAqIG1ldGhvZCB7QGxpbmsgbmcuJGxvZ1Byb3ZpZGVyI2RlYnVnRW5hYmxlZCBkZWJ1Z0VuYWJsZWR9DQogKiB3aGljaCBsZXRzIHlvdSBzcGVjaWZ5IHdoZXRoZXIgdGhlIHtAbGluayBuZy4kbG9nICRsb2d9IHNlcnZpY2Ugd2lsbCBsb2cgZGVidWcgbWVzc2FnZXMgdG8gdGhlDQogKiBjb25zb2xlIG9yIG5vdC4NCiAqDQogKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgaW5zdGFuY2UuIE5PVEU6IHRoZSBwcm92aWRlciB3aWxsIGJlIGF2YWlsYWJsZSB1bmRlciBgbmFtZSArDQogICAgICAgICAgICAgICAgICAgICAgICAnUHJvdmlkZXInYCBrZXkuDQogKiBAcGFyYW0geyhPYmplY3R8ZnVuY3Rpb24oKSl9IHByb3ZpZGVyIElmIHRoZSBwcm92aWRlciBpczoNCiAqDQogKiAgIC0gYE9iamVjdGA6IHRoZW4gaXQgc2hvdWxkIGhhdmUgYSBgJGdldGAgbWV0aG9kLiBUaGUgYCRnZXRgIG1ldGhvZCB3aWxsIGJlIGludm9rZWQgdXNpbmcNCiAqICAgICB7QGxpbmsgYXV0by4kaW5qZWN0b3IjaW52b2tlICRpbmplY3Rvci5pbnZva2UoKX0gd2hlbiBhbiBpbnN0YW5jZSBuZWVkcyB0byBiZSBjcmVhdGVkLg0KICogICAtIGBDb25zdHJ1Y3RvcmA6IGEgbmV3IGluc3RhbmNlIG9mIHRoZSBwcm92aWRlciB3aWxsIGJlIGNyZWF0ZWQgdXNpbmcNCiAqICAgICB7QGxpbmsgYXV0by4kaW5qZWN0b3IjaW5zdGFudGlhdGUgJGluamVjdG9yLmluc3RhbnRpYXRlKCl9LCB0aGVuIHRyZWF0ZWQgYXMgYG9iamVjdGAuDQogKg0KICogQHJldHVybnMge09iamVjdH0gcmVnaXN0ZXJlZCBwcm92aWRlciBpbnN0YW5jZQ0KDQogKiBAZXhhbXBsZQ0KICoNCiAqIFRoZSBmb2xsb3dpbmcgZXhhbXBsZSBzaG93cyBob3cgdG8gY3JlYXRlIGEgc2ltcGxlIGV2ZW50IHRyYWNraW5nIHNlcnZpY2UgYW5kIHJlZ2lzdGVyIGl0IHVzaW5nDQogKiB7QGxpbmsgYXV0by4kcHJvdmlkZSNwcm92aWRlciAkcHJvdmlkZS5wcm92aWRlcigpfS4NCiAqDQogKiBgYGBqcw0KICogIC8vIERlZmluZSB0aGUgZXZlbnRUcmFja2VyIHByb3ZpZGVyDQogKiAgZnVuY3Rpb24gRXZlbnRUcmFja2VyUHJvdmlkZXIoKSB7DQogKiAgICB2YXIgdHJhY2tpbmdVcmwgPSAnL3RyYWNrJzsNCiAqDQogKiAgICAvLyBBIHByb3ZpZGVyIG1ldGhvZCBmb3IgY29uZmlndXJpbmcgd2hlcmUgdGhlIHRyYWNrZWQgZXZlbnRzIHNob3VsZCBiZWVuIHNhdmVkDQogKiAgICB0aGlzLnNldFRyYWNraW5nVXJsID0gZnVuY3Rpb24odXJsKSB7DQogKiAgICAgIHRyYWNraW5nVXJsID0gdXJsOw0KICogICAgfTsNCiAqDQogKiAgICAvLyBUaGUgc2VydmljZSBmYWN0b3J5IGZ1bmN0aW9uDQogKiAgICB0aGlzLiRnZXQgPSBbJyRodHRwJywgZnVuY3Rpb24oJGh0dHApIHsNCiAqICAgICAgdmFyIHRyYWNrZWRFdmVudHMgPSB7fTsNCiAqICAgICAgcmV0dXJuIHsNCiAqICAgICAgICAvLyBDYWxsIHRoaXMgdG8gdHJhY2sgYW4gZXZlbnQNCiAqICAgICAgICBldmVudDogZnVuY3Rpb24oZXZlbnQpIHsNCiAqICAgICAgICAgIHZhciBjb3VudCA9IHRyYWNrZWRFdmVudHNbZXZlbnRdIHx8IDA7DQogKiAgICAgICAgICBjb3VudCArPSAxOw0KICogICAgICAgICAgdHJhY2tlZEV2ZW50c1tldmVudF0gPSBjb3VudDsNCiAqICAgICAgICAgIHJldHVybiBjb3VudDsNCiAqICAgICAgICB9LA0KICogICAgICAgIC8vIENhbGwgdGhpcyB0byBzYXZlIHRoZSB0cmFja2VkIGV2ZW50cyB0byB0aGUgdHJhY2tpbmdVcmwNCiAqICAgICAgICBzYXZlOiBmdW5jdGlvbigpIHsNCiAqICAgICAgICAgICRodHRwLnBvc3QodHJhY2tpbmdVcmwsIHRyYWNrZWRFdmVudHMpOw0KICogICAgICAgIH0NCiAqICAgICAgfTsNCiAqICAgIH1dOw0KICogIH0NCiAqDQogKiAgZGVzY3JpYmUoJ2V2ZW50VHJhY2tlcicsIGZ1bmN0aW9uKCkgew0KICogICAgdmFyIHBvc3RTcHk7DQogKg0KICogICAgYmVmb3JlRWFjaChtb2R1bGUoZnVuY3Rpb24oJHByb3ZpZGUpIHsNCiAqICAgICAgLy8gUmVnaXN0ZXIgdGhlIGV2ZW50VHJhY2tlciBwcm92aWRlcg0KICogICAgICAkcHJvdmlkZS5wcm92aWRlcignZXZlbnRUcmFja2VyJywgRXZlbnRUcmFja2VyUHJvdmlkZXIpOw0KICogICAgfSkpOw0KICoNCiAqICAgIGJlZm9yZUVhY2gobW9kdWxlKGZ1bmN0aW9uKGV2ZW50VHJhY2tlclByb3ZpZGVyKSB7DQogKiAgICAgIC8vIENvbmZpZ3VyZSBldmVudFRyYWNrZXIgcHJvdmlkZXINCiAqICAgICAgZXZlbnRUcmFja2VyUHJvdmlkZXIuc2V0VHJhY2tpbmdVcmwoJy9jdXN0b20tdHJhY2snKTsNCiAqICAgIH0pKTsNCiAqDQogKiAgICBpdCgndHJhY2tzIGV2ZW50cycsIGluamVjdChmdW5jdGlvbihldmVudFRyYWNrZXIpIHsNCiAqICAgICAgZXhwZWN0KGV2ZW50VHJhY2tlci5ldmVudCgnbG9naW4nKSkudG9FcXVhbCgxKTsNCiAqICAgICAgZXhwZWN0KGV2ZW50VHJhY2tlci5ldmVudCgnbG9naW4nKSkudG9FcXVhbCgyKTsNCiAqICAgIH0pKTsNCiAqDQogKiAgICBpdCgnc2F2ZXMgdG8gdGhlIHRyYWNraW5nIHVybCcsIGluamVjdChmdW5jdGlvbihldmVudFRyYWNrZXIsICRodHRwKSB7DQogKiAgICAgIHBvc3RTcHkgPSBzcHlPbigkaHR0cCwgJ3Bvc3QnKTsNCiAqICAgICAgZXZlbnRUcmFja2VyLmV2ZW50KCdsb2dpbicpOw0KICogICAgICBldmVudFRyYWNrZXIuc2F2ZSgpOw0KICogICAgICBleHBlY3QocG9zdFNweSkudG9IYXZlQmVlbkNhbGxlZCgpOw0KICogICAgICBleHBlY3QocG9zdFNweS5tb3N0UmVjZW50Q2FsbC5hcmdzWzBdKS5ub3QudG9FcXVhbCgnL3RyYWNrJyk7DQogKiAgICAgIGV4cGVjdChwb3N0U3B5Lm1vc3RSZWNlbnRDYWxsLmFyZ3NbMF0pLnRvRXF1YWwoJy9jdXN0b20tdHJhY2snKTsNCiAqICAgICAgZXhwZWN0KHBvc3RTcHkubW9zdFJlY2VudENhbGwuYXJnc1sxXSkudG9FcXVhbCh7ICdsb2dpbic6IDEgfSk7DQogKiAgICB9KSk7DQogKiAgfSk7DQogKiBgYGANCiAqLw0KDQovKioNCiAqIEBuZ2RvYyBtZXRob2QNCiAqIEBuYW1lICRwcm92aWRlI2ZhY3RvcnkNCiAqIEBkZXNjcmlwdGlvbg0KICoNCiAqIFJlZ2lzdGVyIGEgKipzZXJ2aWNlIGZhY3RvcnkqKiwgd2hpY2ggd2lsbCBiZSBjYWxsZWQgdG8gcmV0dXJuIHRoZSBzZXJ2aWNlIGluc3RhbmNlLg0KICogVGhpcyBpcyBzaG9ydCBmb3IgcmVnaXN0ZXJpbmcgYSBzZXJ2aWNlIHdoZXJlIGl0cyBwcm92aWRlciBjb25zaXN0cyBvZiBvbmx5IGEgYCRnZXRgIHByb3BlcnR5LA0KICogd2hpY2ggaXMgdGhlIGdpdmVuIHNlcnZpY2UgZmFjdG9yeSBmdW5jdGlvbi4NCiAqIFlvdSBzaG91bGQgdXNlIHtAbGluayBhdXRvLiRwcm92aWRlI2ZhY3RvcnkgJHByb3ZpZGUuZmFjdG9yeShnZXRGbil9IGlmIHlvdSBkbyBub3QgbmVlZCB0bw0KICogY29uZmlndXJlIHlvdXIgc2VydmljZSBpbiBhIHByb3ZpZGVyLg0KICoNCiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBpbnN0YW5jZS4NCiAqIEBwYXJhbSB7ZnVuY3Rpb24oKX0gJGdldEZuIFRoZSAkZ2V0Rm4gZm9yIHRoZSBpbnN0YW5jZSBjcmVhdGlvbi4gSW50ZXJuYWxseSB0aGlzIGlzIGEgc2hvcnQgaGFuZA0KICogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIGAkcHJvdmlkZS5wcm92aWRlcihuYW1lLCB7JGdldDogJGdldEZufSlgLg0KICogQHJldHVybnMge09iamVjdH0gcmVnaXN0ZXJlZCBwcm92aWRlciBpbnN0YW5jZQ0KICoNCiAqIEBleGFtcGxlDQogKiBIZXJlIGlzIGFuIGV4YW1wbGUgb2YgcmVnaXN0ZXJpbmcgYSBzZXJ2aWNlDQogKiBgYGBqcw0KICogICAkcHJvdmlkZS5mYWN0b3J5KCdwaW5nJywgWyckaHR0cCcsIGZ1bmN0aW9uKCRodHRwKSB7DQogKiAgICAgcmV0dXJuIGZ1bmN0aW9uIHBpbmcoKSB7DQogKiAgICAgICByZXR1cm4gJGh0dHAuc2VuZCgnL3BpbmcnKTsNCiAqICAgICB9Ow0KICogICB9XSk7DQogKiBgYGANCiAqIFlvdSB3b3VsZCB0aGVuIGluamVjdCBhbmQgdXNlIHRoaXMgc2VydmljZSBsaWtlIHRoaXM6DQogKiBgYGBqcw0KICogICBzb21lTW9kdWxlLmNvbnRyb2xsZXIoJ0N0cmwnLCBbJ3BpbmcnLCBmdW5jdGlvbihwaW5nKSB7DQogKiAgICAgcGluZygpOw0KICogICB9XSk7DQogKiBgYGANCiAqLw0KDQoNCi8qKg0KICogQG5nZG9jIG1ldGhvZA0KICogQG5hbWUgJHByb3ZpZGUjc2VydmljZQ0KICogQGRlc2NyaXB0aW9uDQogKg0KICogUmVnaXN0ZXIgYSAqKnNlcnZpY2UgY29uc3RydWN0b3IqKiwgd2hpY2ggd2lsbCBiZSBpbnZva2VkIHdpdGggYG5ld2AgdG8gY3JlYXRlIHRoZSBzZXJ2aWNlDQogKiBpbnN0YW5jZS4NCiAqIFRoaXMgaXMgc2hvcnQgZm9yIHJlZ2lzdGVyaW5nIGEgc2VydmljZSB3aGVyZSBpdHMgcHJvdmlkZXIncyBgJGdldGAgcHJvcGVydHkgaXMgdGhlIHNlcnZpY2UNCiAqIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSB1c2VkIHRvIGluc3RhbnRpYXRlIHRoZSBzZXJ2aWNlIGluc3RhbmNlLg0KICoNCiAqIFlvdSBzaG91bGQgdXNlIHtAbGluayBhdXRvLiRwcm92aWRlI3NlcnZpY2UgJHByb3ZpZGUuc2VydmljZShjbGFzcyl9IGlmIHlvdSBkZWZpbmUgeW91ciBzZXJ2aWNlDQogKiBhcyBhIHR5cGUvY2xhc3MuDQogKg0KICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIGluc3RhbmNlLg0KICogQHBhcmFtIHtGdW5jdGlvbn0gY29uc3RydWN0b3IgQSBjbGFzcyAoY29uc3RydWN0b3IgZnVuY3Rpb24pIHRoYXQgd2lsbCBiZSBpbnN0YW50aWF0ZWQuDQogKiBAcmV0dXJucyB7T2JqZWN0fSByZWdpc3RlcmVkIHByb3ZpZGVyIGluc3RhbmNlDQogKg0KICogQGV4YW1wbGUNCiAqIEhlcmUgaXMgYW4gZXhhbXBsZSBvZiByZWdpc3RlcmluZyBhIHNlcnZpY2UgdXNpbmcNCiAqIHtAbGluayBhdXRvLiRwcm92aWRlI3NlcnZpY2UgJHByb3ZpZGUuc2VydmljZShjbGFzcyl9Lg0KICogYGBganMNCiAqICAgdmFyIFBpbmcgPSBmdW5jdGlvbigkaHR0cCkgew0KICogICAgIHRoaXMuJGh0dHAgPSAkaHR0cDsNCiAqICAgfTsNCiAqDQogKiAgIFBpbmcuJGluamVjdCA9IFsnJGh0dHAnXTsNCiAqDQogKiAgIFBpbmcucHJvdG90eXBlLnNlbmQgPSBmdW5jdGlvbigpIHsNCiAqICAgICByZXR1cm4gdGhpcy4kaHR0cC5nZXQoJy9waW5nJyk7DQogKiAgIH07DQogKiAgICRwcm92aWRlLnNlcnZpY2UoJ3BpbmcnLCBQaW5nKTsNCiAqIGBgYA0KICogWW91IHdvdWxkIHRoZW4gaW5qZWN0IGFuZCB1c2UgdGhpcyBzZXJ2aWNlIGxpa2UgdGhpczoNCiAqIGBgYGpzDQogKiAgIHNvbWVNb2R1bGUuY29udHJvbGxlcignQ3RybCcsIFsncGluZycsIGZ1bmN0aW9uKHBpbmcpIHsNCiAqICAgICBwaW5nLnNlbmQoKTsNCiAqICAgfV0pOw0KICogYGBgDQogKi8NCg0KDQovKioNCiAqIEBuZ2RvYyBtZXRob2QNCiAqIEBuYW1lICRwcm92aWRlI3ZhbHVlDQogKiBAZGVzY3JpcHRpb24NCiAqDQogKiBSZWdpc3RlciBhICoqdmFsdWUgc2VydmljZSoqIHdpdGggdGhlIHtAbGluayBhdXRvLiRpbmplY3RvciAkaW5qZWN0b3J9LCBzdWNoIGFzIGEgc3RyaW5nLCBhDQogKiBudW1iZXIsIGFuIGFycmF5LCBhbiBvYmplY3Qgb3IgYSBmdW5jdGlvbi4gIFRoaXMgaXMgc2hvcnQgZm9yIHJlZ2lzdGVyaW5nIGEgc2VydmljZSB3aGVyZSBpdHMNCiAqIHByb3ZpZGVyJ3MgYCRnZXRgIHByb3BlcnR5IGlzIGEgZmFjdG9yeSBmdW5jdGlvbiB0aGF0IHRha2VzIG5vIGFyZ3VtZW50cyBhbmQgcmV0dXJucyB0aGUgKip2YWx1ZQ0KICogc2VydmljZSoqLg0KICoNCiAqIFZhbHVlIHNlcnZpY2VzIGFyZSBzaW1pbGFyIHRvIGNvbnN0YW50IHNlcnZpY2VzLCBleGNlcHQgdGhhdCB0aGV5IGNhbm5vdCBiZSBpbmplY3RlZCBpbnRvIGENCiAqIG1vZHVsZSBjb25maWd1cmF0aW9uIGZ1bmN0aW9uIChzZWUge0BsaW5rIGFuZ3VsYXIuTW9kdWxlI2NvbmZpZ30pIGJ1dCB0aGV5IGNhbiBiZSBvdmVycmlkZGVuIGJ5DQogKiBhbiBBbmd1bGFyDQogKiB7QGxpbmsgYXV0by4kcHJvdmlkZSNkZWNvcmF0b3IgZGVjb3JhdG9yfS4NCiAqDQogKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgaW5zdGFuY2UuDQogKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZS4NCiAqIEByZXR1cm5zIHtPYmplY3R9IHJlZ2lzdGVyZWQgcHJvdmlkZXIgaW5zdGFuY2UNCiAqDQogKiBAZXhhbXBsZQ0KICogSGVyZSBhcmUgc29tZSBleGFtcGxlcyBvZiBjcmVhdGluZyB2YWx1ZSBzZXJ2aWNlcy4NCiAqIGBgYGpzDQogKiAgICRwcm92aWRlLnZhbHVlKCdBRE1JTl9VU0VSJywgJ2FkbWluJyk7DQogKg0KICogICAkcHJvdmlkZS52YWx1ZSgnUm9sZUxvb2t1cCcsIHsgYWRtaW46IDAsIHdyaXRlcjogMSwgcmVhZGVyOiAyIH0pOw0KICoNCiAqICAgJHByb3ZpZGUudmFsdWUoJ2hhbGZPZicsIGZ1bmN0aW9uKHZhbHVlKSB7DQogKiAgICAgcmV0dXJuIHZhbHVlIC8gMjsNCiAqICAgfSk7DQogKiBgYGANCiAqLw0KDQoNCi8qKg0KICogQG5nZG9jIG1ldGhvZA0KICogQG5hbWUgJHByb3ZpZGUjY29uc3RhbnQNCiAqIEBkZXNjcmlwdGlvbg0KICoNCiAqIFJlZ2lzdGVyIGEgKipjb25zdGFudCBzZXJ2aWNlKiosIHN1Y2ggYXMgYSBzdHJpbmcsIGEgbnVtYmVyLCBhbiBhcnJheSwgYW4gb2JqZWN0IG9yIGEgZnVuY3Rpb24sDQogKiB3aXRoIHRoZSB7QGxpbmsgYXV0by4kaW5qZWN0b3IgJGluamVjdG9yfS4gVW5saWtlIHtAbGluayBhdXRvLiRwcm92aWRlI3ZhbHVlIHZhbHVlfSBpdCBjYW4gYmUNCiAqIGluamVjdGVkIGludG8gYSBtb2R1bGUgY29uZmlndXJhdGlvbiBmdW5jdGlvbiAoc2VlIHtAbGluayBhbmd1bGFyLk1vZHVsZSNjb25maWd9KSBhbmQgaXQgY2Fubm90DQogKiBiZSBvdmVycmlkZGVuIGJ5IGFuIEFuZ3VsYXIge0BsaW5rIGF1dG8uJHByb3ZpZGUjZGVjb3JhdG9yIGRlY29yYXRvcn0uDQogKg0KICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIGNvbnN0YW50Lg0KICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgY29uc3RhbnQgdmFsdWUuDQogKiBAcmV0dXJucyB7T2JqZWN0fSByZWdpc3RlcmVkIGluc3RhbmNlDQogKg0KICogQGV4YW1wbGUNCiAqIEhlcmUgYSBzb21lIGV4YW1wbGVzIG9mIGNyZWF0aW5nIGNvbnN0YW50czoNCiAqIGBgYGpzDQogKiAgICRwcm92aWRlLmNvbnN0YW50KCdTSEFSRF9IRUlHSFQnLCAzMDYpOw0KICoNCiAqICAgJHByb3ZpZGUuY29uc3RhbnQoJ01ZX0NPTE9VUlMnLCBbJ3JlZCcsICdibHVlJywgJ2dyZXknXSk7DQogKg0KICogICAkcHJvdmlkZS5jb25zdGFudCgnZG91YmxlJywgZnVuY3Rpb24odmFsdWUpIHsNCiAqICAgICByZXR1cm4gdmFsdWUgKiAyOw0KICogICB9KTsNCiAqIGBgYA0KICovDQoNCg0KLyoqDQogKiBAbmdkb2MgbWV0aG9kDQogKiBAbmFtZSAkcHJvdmlkZSNkZWNvcmF0b3INCiAqIEBkZXNjcmlwdGlvbg0KICoNCiAqIFJlZ2lzdGVyIGEgKipzZXJ2aWNlIGRlY29yYXRvcioqIHdpdGggdGhlIHtAbGluayBhdXRvLiRpbmplY3RvciAkaW5qZWN0b3J9LiBBIHNlcnZpY2UgZGVjb3JhdG9yDQogKiBpbnRlcmNlcHRzIHRoZSBjcmVhdGlvbiBvZiBhIHNlcnZpY2UsIGFsbG93aW5nIGl0IHRvIG92ZXJyaWRlIG9yIG1vZGlmeSB0aGUgYmVoYXZpb3VyIG9mIHRoZQ0KICogc2VydmljZS4gVGhlIG9iamVjdCByZXR1cm5lZCBieSB0aGUgZGVjb3JhdG9yIG1heSBiZSB0aGUgb3JpZ2luYWwgc2VydmljZSwgb3IgYSBuZXcgc2VydmljZQ0KICogb2JqZWN0IHdoaWNoIHJlcGxhY2VzIG9yIHdyYXBzIGFuZCBkZWxlZ2F0ZXMgdG8gdGhlIG9yaWdpbmFsIHNlcnZpY2UuDQogKg0KICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIHNlcnZpY2UgdG8gZGVjb3JhdGUuDQogKiBAcGFyYW0ge2Z1bmN0aW9uKCl9IGRlY29yYXRvciBUaGlzIGZ1bmN0aW9uIHdpbGwgYmUgaW52b2tlZCB3aGVuIHRoZSBzZXJ2aWNlIG5lZWRzIHRvIGJlDQogKiAgICBpbnN0YW50aWF0ZWQgYW5kIHNob3VsZCByZXR1cm4gdGhlIGRlY29yYXRlZCBzZXJ2aWNlIGluc3RhbmNlLiBUaGUgZnVuY3Rpb24gaXMgY2FsbGVkIHVzaW5nDQogKiAgICB0aGUge0BsaW5rIGF1dG8uJGluamVjdG9yI2ludm9rZSBpbmplY3Rvci5pbnZva2V9IG1ldGhvZCBhbmQgaXMgdGhlcmVmb3JlIGZ1bGx5IGluamVjdGFibGUuDQogKiAgICBMb2NhbCBpbmplY3Rpb24gYXJndW1lbnRzOg0KICoNCiAqICAgICogYCRkZWxlZ2F0ZWAgLSBUaGUgb3JpZ2luYWwgc2VydmljZSBpbnN0YW5jZSwgd2hpY2ggY2FuIGJlIG1vbmtleSBwYXRjaGVkLCBjb25maWd1cmVkLA0KICogICAgICBkZWNvcmF0ZWQgb3IgZGVsZWdhdGVkIHRvLg0KICoNCiAqIEBleGFtcGxlDQogKiBIZXJlIHdlIGRlY29yYXRlIHRoZSB7QGxpbmsgbmcuJGxvZyAkbG9nfSBzZXJ2aWNlIHRvIGNvbnZlcnQgd2FybmluZ3MgdG8gZXJyb3JzIGJ5IGludGVyY2VwdGluZw0KICogY2FsbHMgdG8ge0BsaW5rIG5nLiRsb2cjZXJyb3IgJGxvZy53YXJuKCl9Lg0KICogYGBganMNCiAqICAgJHByb3ZpZGUuZGVjb3JhdG9yKCckbG9nJywgWyckZGVsZWdhdGUnLCBmdW5jdGlvbigkZGVsZWdhdGUpIHsNCiAqICAgICAkZGVsZWdhdGUud2FybiA9ICRkZWxlZ2F0ZS5lcnJvcjsNCiAqICAgICByZXR1cm4gJGRlbGVnYXRlOw0KICogICB9XSk7DQogKiBgYGANCiAqLw0KDQoNCmZ1bmN0aW9uIGNyZWF0ZUluamVjdG9yKG1vZHVsZXNUb0xvYWQsIHN0cmljdERpKSB7DQogIHN0cmljdERpID0gKHN0cmljdERpID09PSB0cnVlKTsNCiAgdmFyIElOU1RBTlRJQVRJTkcgPSB7fSwNCiAgICAgIHByb3ZpZGVyU3VmZml4ID0gJ1Byb3ZpZGVyJywNCiAgICAgIHBhdGggPSBbXSwNCiAgICAgIGxvYWRlZE1vZHVsZXMgPSBuZXcgSGFzaE1hcChbXSwgdHJ1ZSksDQogICAgICBwcm92aWRlckNhY2hlID0gew0KICAgICAgICAkcHJvdmlkZTogew0KICAgICAgICAgICAgcHJvdmlkZXI6IHN1cHBvcnRPYmplY3QocHJvdmlkZXIpLA0KICAgICAgICAgICAgZmFjdG9yeTogc3VwcG9ydE9iamVjdChmYWN0b3J5KSwNCiAgICAgICAgICAgIHNlcnZpY2U6IHN1cHBvcnRPYmplY3Qoc2VydmljZSksDQogICAgICAgICAgICB2YWx1ZTogc3VwcG9ydE9iamVjdCh2YWx1ZSksDQogICAgICAgICAgICBjb25zdGFudDogc3VwcG9ydE9iamVjdChjb25zdGFudCksDQogICAgICAgICAgICBkZWNvcmF0b3I6IGRlY29yYXRvcg0KICAgICAgICAgIH0NCiAgICAgIH0sDQogICAgICBwcm92aWRlckluamVjdG9yID0gKHByb3ZpZGVyQ2FjaGUuJGluamVjdG9yID0NCiAgICAgICAgICBjcmVhdGVJbnRlcm5hbEluamVjdG9yKHByb3ZpZGVyQ2FjaGUsIGZ1bmN0aW9uKHNlcnZpY2VOYW1lLCBjYWxsZXIpIHsNCiAgICAgICAgICAgIGlmIChhbmd1bGFyLmlzU3RyaW5nKGNhbGxlcikpIHsNCiAgICAgICAgICAgICAgcGF0aC5wdXNoKGNhbGxlcik7DQogICAgICAgICAgICB9DQogICAgICAgICAgICB0aHJvdyAkaW5qZWN0b3JNaW5FcnIoJ3VucHInLCAiVW5rbm93biBwcm92aWRlcjogezB9IiwgcGF0aC5qb2luKCcgPC0gJykpOw0KICAgICAgICAgIH0pKSwNCiAgICAgIGluc3RhbmNlQ2FjaGUgPSB7fSwNCiAgICAgIGluc3RhbmNlSW5qZWN0b3IgPSAoaW5zdGFuY2VDYWNoZS4kaW5qZWN0b3IgPQ0KICAgICAgICAgIGNyZWF0ZUludGVybmFsSW5qZWN0b3IoaW5zdGFuY2VDYWNoZSwgZnVuY3Rpb24oc2VydmljZU5hbWUsIGNhbGxlcikgew0KICAgICAgICAgICAgdmFyIHByb3ZpZGVyID0gcHJvdmlkZXJJbmplY3Rvci5nZXQoc2VydmljZU5hbWUgKyBwcm92aWRlclN1ZmZpeCwgY2FsbGVyKTsNCiAgICAgICAgICAgIHJldHVybiBpbnN0YW5jZUluamVjdG9yLmludm9rZShwcm92aWRlci4kZ2V0LCBwcm92aWRlciwgdW5kZWZpbmVkLCBzZXJ2aWNlTmFtZSk7DQogICAgICAgICAgfSkpOw0KDQoNCiAgZm9yRWFjaChsb2FkTW9kdWxlcyhtb2R1bGVzVG9Mb2FkKSwgZnVuY3Rpb24oZm4pIHsgaW5zdGFuY2VJbmplY3Rvci5pbnZva2UoZm4gfHwgbm9vcCk7IH0pOw0KDQogIHJldHVybiBpbnN0YW5jZUluamVjdG9yOw0KDQogIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KICAvLyAkcHJvdmlkZXINCiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vDQoNCiAgZnVuY3Rpb24gc3VwcG9ydE9iamVjdChkZWxlZ2F0ZSkgew0KICAgIHJldHVybiBmdW5jdGlvbihrZXksIHZhbHVlKSB7DQogICAgICBpZiAoaXNPYmplY3Qoa2V5KSkgew0KICAgICAgICBmb3JFYWNoKGtleSwgcmV2ZXJzZVBhcmFtcyhkZWxlZ2F0ZSkpOw0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgcmV0dXJuIGRlbGVnYXRlKGtleSwgdmFsdWUpOw0KICAgICAgfQ0KICAgIH07DQogIH0NCg0KICBmdW5jdGlvbiBwcm92aWRlcihuYW1lLCBwcm92aWRlcl8pIHsNCiAgICBhc3NlcnROb3RIYXNPd25Qcm9wZXJ0eShuYW1lLCAnc2VydmljZScpOw0KICAgIGlmIChpc0Z1bmN0aW9uKHByb3ZpZGVyXykgfHwgaXNBcnJheShwcm92aWRlcl8pKSB7DQogICAgICBwcm92aWRlcl8gPSBwcm92aWRlckluamVjdG9yLmluc3RhbnRpYXRlKHByb3ZpZGVyXyk7DQogICAgfQ0KICAgIGlmICghcHJvdmlkZXJfLiRnZXQpIHsNCiAgICAgIHRocm93ICRpbmplY3Rvck1pbkVycigncGdldCcsICJQcm92aWRlciAnezB9JyBtdXN0IGRlZmluZSAkZ2V0IGZhY3RvcnkgbWV0aG9kLiIsIG5hbWUpOw0KICAgIH0NCiAgICByZXR1cm4gcHJvdmlkZXJDYWNoZVtuYW1lICsgcHJvdmlkZXJTdWZmaXhdID0gcHJvdmlkZXJfOw0KICB9DQoNCiAgZnVuY3Rpb24gZW5mb3JjZVJldHVyblZhbHVlKG5hbWUsIGZhY3RvcnkpIHsNCiAgICByZXR1cm4gZnVuY3Rpb24gZW5mb3JjZWRSZXR1cm5WYWx1ZSgpIHsNCiAgICAgIHZhciByZXN1bHQgPSBpbnN0YW5jZUluamVjdG9yLmludm9rZShmYWN0b3J5LCB0aGlzKTsNCiAgICAgIGlmIChpc1VuZGVmaW5lZChyZXN1bHQpKSB7DQogICAgICAgIHRocm93ICRpbmplY3Rvck1pbkVycigndW5kZWYnLCAiUHJvdmlkZXIgJ3swfScgbXVzdCByZXR1cm4gYSB2YWx1ZSBmcm9tICRnZXQgZmFjdG9yeSBtZXRob2QuIiwgbmFtZSk7DQogICAgICB9DQogICAgICByZXR1cm4gcmVzdWx0Ow0KICAgIH07DQogIH0NCg0KICBmdW5jdGlvbiBmYWN0b3J5KG5hbWUsIGZhY3RvcnlGbiwgZW5mb3JjZSkgew0KICAgIHJldHVybiBwcm92aWRlcihuYW1lLCB7DQogICAgICAkZ2V0OiBlbmZvcmNlICE9PSBmYWxzZSA/IGVuZm9yY2VSZXR1cm5WYWx1ZShuYW1lLCBmYWN0b3J5Rm4pIDogZmFjdG9yeUZuDQogICAgfSk7DQogIH0NCg0KICBmdW5jdGlvbiBzZXJ2aWNlKG5hbWUsIGNvbnN0cnVjdG9yKSB7DQogICAgcmV0dXJuIGZhY3RvcnkobmFtZSwgWyckaW5qZWN0b3InLCBmdW5jdGlvbigkaW5qZWN0b3IpIHsNCiAgICAgIHJldHVybiAkaW5qZWN0b3IuaW5zdGFudGlhdGUoY29uc3RydWN0b3IpOw0KICAgIH1dKTsNCiAgfQ0KDQogIGZ1bmN0aW9uIHZhbHVlKG5hbWUsIHZhbCkgeyByZXR1cm4gZmFjdG9yeShuYW1lLCB2YWx1ZUZuKHZhbCksIGZhbHNlKTsgfQ0KDQogIGZ1bmN0aW9uIGNvbnN0YW50KG5hbWUsIHZhbHVlKSB7DQogICAgYXNzZXJ0Tm90SGFzT3duUHJvcGVydHkobmFtZSwgJ2NvbnN0YW50Jyk7DQogICAgcHJvdmlkZXJDYWNoZVtuYW1lXSA9IHZhbHVlOw0KICAgIGluc3RhbmNlQ2FjaGVbbmFtZV0gPSB2YWx1ZTsNCiAgfQ0KDQogIGZ1bmN0aW9uIGRlY29yYXRvcihzZXJ2aWNlTmFtZSwgZGVjb3JGbikgew0KICAgIHZhciBvcmlnUHJvdmlkZXIgPSBwcm92aWRlckluamVjdG9yLmdldChzZXJ2aWNlTmFtZSArIHByb3ZpZGVyU3VmZml4KSwNCiAgICAgICAgb3JpZyRnZXQgPSBvcmlnUHJvdmlkZXIuJGdldDsNCg0KICAgIG9yaWdQcm92aWRlci4kZ2V0ID0gZnVuY3Rpb24oKSB7DQogICAgICB2YXIgb3JpZ0luc3RhbmNlID0gaW5zdGFuY2VJbmplY3Rvci5pbnZva2Uob3JpZyRnZXQsIG9yaWdQcm92aWRlcik7DQogICAgICByZXR1cm4gaW5zdGFuY2VJbmplY3Rvci5pbnZva2UoZGVjb3JGbiwgbnVsbCwgeyRkZWxlZ2F0ZTogb3JpZ0luc3RhbmNlfSk7DQogICAgfTsNCiAgfQ0KDQogIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KICAvLyBNb2R1bGUgTG9hZGluZw0KICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCiAgZnVuY3Rpb24gbG9hZE1vZHVsZXMobW9kdWxlc1RvTG9hZCkgew0KICAgIHZhciBydW5CbG9ja3MgPSBbXSwgbW9kdWxlRm47DQogICAgZm9yRWFjaChtb2R1bGVzVG9Mb2FkLCBmdW5jdGlvbihtb2R1bGUpIHsNCiAgICAgIGlmIChsb2FkZWRNb2R1bGVzLmdldChtb2R1bGUpKSByZXR1cm47DQogICAgICBsb2FkZWRNb2R1bGVzLnB1dChtb2R1bGUsIHRydWUpOw0KDQogICAgICBmdW5jdGlvbiBydW5JbnZva2VRdWV1ZShxdWV1ZSkgew0KICAgICAgICB2YXIgaSwgaWk7DQogICAgICAgIGZvciAoaSA9IDAsIGlpID0gcXVldWUubGVuZ3RoOyBpIDwgaWk7IGkrKykgew0KICAgICAgICAgIHZhciBpbnZva2VBcmdzID0gcXVldWVbaV0sDQogICAgICAgICAgICAgIHByb3ZpZGVyID0gcHJvdmlkZXJJbmplY3Rvci5nZXQoaW52b2tlQXJnc1swXSk7DQoNCiAgICAgICAgICBwcm92aWRlcltpbnZva2VBcmdzWzFdXS5hcHBseShwcm92aWRlciwgaW52b2tlQXJnc1syXSk7DQogICAgICAgIH0NCiAgICAgIH0NCg0KICAgICAgdHJ5IHsNCiAgICAgICAgaWYgKGlzU3RyaW5nKG1vZHVsZSkpIHsNCiAgICAgICAgICBtb2R1bGVGbiA9IGFuZ3VsYXJNb2R1bGUobW9kdWxlKTsNCiAgICAgICAgICBydW5CbG9ja3MgPSBydW5CbG9ja3MuY29uY2F0KGxvYWRNb2R1bGVzKG1vZHVsZUZuLnJlcXVpcmVzKSkuY29uY2F0KG1vZHVsZUZuLl9ydW5CbG9ja3MpOw0KICAgICAgICAgIHJ1bkludm9rZVF1ZXVlKG1vZHVsZUZuLl9pbnZva2VRdWV1ZSk7DQogICAgICAgICAgcnVuSW52b2tlUXVldWUobW9kdWxlRm4uX2NvbmZpZ0Jsb2Nrcyk7DQogICAgICAgIH0gZWxzZSBpZiAoaXNGdW5jdGlvbihtb2R1bGUpKSB7DQogICAgICAgICAgICBydW5CbG9ja3MucHVzaChwcm92aWRlckluamVjdG9yLmludm9rZShtb2R1bGUpKTsNCiAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KG1vZHVsZSkpIHsNCiAgICAgICAgICAgIHJ1bkJsb2Nrcy5wdXNoKHByb3ZpZGVySW5qZWN0b3IuaW52b2tlKG1vZHVsZSkpOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIGFzc2VydEFyZ0ZuKG1vZHVsZSwgJ21vZHVsZScpOw0KICAgICAgICB9DQogICAgICB9IGNhdGNoIChlKSB7DQogICAgICAgIGlmIChpc0FycmF5KG1vZHVsZSkpIHsNCiAgICAgICAgICBtb2R1bGUgPSBtb2R1bGVbbW9kdWxlLmxlbmd0aCAtIDFdOw0KICAgICAgICB9DQogICAgICAgIGlmIChlLm1lc3NhZ2UgJiYgZS5zdGFjayAmJiBlLnN0YWNrLmluZGV4T2YoZS5tZXNzYWdlKSA9PSAtMSkgew0KICAgICAgICAgIC8vIFNhZmFyaSAmIEZGJ3Mgc3RhY2sgdHJhY2VzIGRvbid0IGNvbnRhaW4gZXJyb3IubWVzc2FnZSBjb250ZW50DQogICAgICAgICAgLy8gdW5saWtlIHRob3NlIG9mIENocm9tZSBhbmQgSUUNCiAgICAgICAgICAvLyBTbyBpZiBzdGFjayBkb2Vzbid0IGNvbnRhaW4gbWVzc2FnZSwgd2UgY3JlYXRlIGEgbmV3IHN0cmluZyB0aGF0IGNvbnRhaW5zIGJvdGguDQogICAgICAgICAgLy8gU2luY2UgZXJyb3Iuc3RhY2sgaXMgcmVhZC1vbmx5IGluIFNhZmFyaSwgSSdtIG92ZXJyaWRpbmcgZSBhbmQgbm90IGUuc3RhY2sgaGVyZS4NCiAgICAgICAgICAvKiBqc2hpbnQgLVcwMjIgKi8NCiAgICAgICAgICBlID0gZS5tZXNzYWdlICsgJ1xuJyArIGUuc3RhY2s7DQogICAgICAgIH0NCiAgICAgICAgdGhyb3cgJGluamVjdG9yTWluRXJyKCdtb2R1bGVycicsICJGYWlsZWQgdG8gaW5zdGFudGlhdGUgbW9kdWxlIHswfSBkdWUgdG86XG57MX0iLA0KICAgICAgICAgICAgICAgICAgbW9kdWxlLCBlLnN0YWNrIHx8IGUubWVzc2FnZSB8fCBlKTsNCiAgICAgIH0NCiAgICB9KTsNCiAgICByZXR1cm4gcnVuQmxvY2tzOw0KICB9DQoNCiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vDQogIC8vIGludGVybmFsIEluamVjdG9yDQogIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KDQogIGZ1bmN0aW9uIGNyZWF0ZUludGVybmFsSW5qZWN0b3IoY2FjaGUsIGZhY3RvcnkpIHsNCg0KICAgIGZ1bmN0aW9uIGdldFNlcnZpY2Uoc2VydmljZU5hbWUsIGNhbGxlcikgew0KICAgICAgaWYgKGNhY2hlLmhhc093blByb3BlcnR5KHNlcnZpY2VOYW1lKSkgew0KICAgICAgICBpZiAoY2FjaGVbc2VydmljZU5hbWVdID09PSBJTlNUQU5USUFUSU5HKSB7DQogICAgICAgICAgdGhyb3cgJGluamVjdG9yTWluRXJyKCdjZGVwJywgJ0NpcmN1bGFyIGRlcGVuZGVuY3kgZm91bmQ6IHswfScsDQogICAgICAgICAgICAgICAgICAgIHNlcnZpY2VOYW1lICsgJyA8LSAnICsgcGF0aC5qb2luKCcgPC0gJykpOw0KICAgICAgICB9DQogICAgICAgIHJldHVybiBjYWNoZVtzZXJ2aWNlTmFtZV07DQogICAgICB9IGVsc2Ugew0KICAgICAgICB0cnkgew0KICAgICAgICAgIHBhdGgudW5zaGlmdChzZXJ2aWNlTmFtZSk7DQogICAgICAgICAgY2FjaGVbc2VydmljZU5hbWVdID0gSU5TVEFOVElBVElORzsNCiAgICAgICAgICByZXR1cm4gY2FjaGVbc2VydmljZU5hbWVdID0gZmFjdG9yeShzZXJ2aWNlTmFtZSwgY2FsbGVyKTsNCiAgICAgICAgfSBjYXRjaCAoZXJyKSB7DQogICAgICAgICAgaWYgKGNhY2hlW3NlcnZpY2VOYW1lXSA9PT0gSU5TVEFOVElBVElORykgew0KICAgICAgICAgICAgZGVsZXRlIGNhY2hlW3NlcnZpY2VOYW1lXTsNCiAgICAgICAgICB9DQogICAgICAgICAgdGhyb3cgZXJyOw0KICAgICAgICB9IGZpbmFsbHkgew0KICAgICAgICAgIHBhdGguc2hpZnQoKTsNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIGludm9rZShmbiwgc2VsZiwgbG9jYWxzLCBzZXJ2aWNlTmFtZSkgew0KICAgICAgaWYgKHR5cGVvZiBsb2NhbHMgPT09ICdzdHJpbmcnKSB7DQogICAgICAgIHNlcnZpY2VOYW1lID0gbG9jYWxzOw0KICAgICAgICBsb2NhbHMgPSBudWxsOw0KICAgICAgfQ0KDQogICAgICB2YXIgYXJncyA9IFtdLA0KICAgICAgICAgICRpbmplY3QgPSBhbm5vdGF0ZShmbiwgc3RyaWN0RGksIHNlcnZpY2VOYW1lKSwNCiAgICAgICAgICBsZW5ndGgsIGksDQogICAgICAgICAga2V5Ow0KDQogICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSAkaW5qZWN0Lmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7DQogICAgICAgIGtleSA9ICRpbmplY3RbaV07DQogICAgICAgIGlmICh0eXBlb2Yga2V5ICE9PSAnc3RyaW5nJykgew0KICAgICAgICAgIHRocm93ICRpbmplY3Rvck1pbkVycignaXRrbicsDQogICAgICAgICAgICAgICAgICAnSW5jb3JyZWN0IGluamVjdGlvbiB0b2tlbiEgRXhwZWN0ZWQgc2VydmljZSBuYW1lIGFzIHN0cmluZywgZ290IHswfScsIGtleSk7DQogICAgICAgIH0NCiAgICAgICAgYXJncy5wdXNoKA0KICAgICAgICAgIGxvY2FscyAmJiBsb2NhbHMuaGFzT3duUHJvcGVydHkoa2V5KQ0KICAgICAgICAgID8gbG9jYWxzW2tleV0NCiAgICAgICAgICA6IGdldFNlcnZpY2Uoa2V5LCBzZXJ2aWNlTmFtZSkNCiAgICAgICAgKTsNCiAgICAgIH0NCiAgICAgIGlmIChpc0FycmF5KGZuKSkgew0KICAgICAgICBmbiA9IGZuW2xlbmd0aF07DQogICAgICB9DQoNCiAgICAgIC8vIGh0dHA6Ly9qc3BlcmYuY29tL2FuZ3VsYXJqcy1pbnZva2UtYXBwbHktdnMtc3dpdGNoDQogICAgICAvLyAjNTM4OA0KICAgICAgcmV0dXJuIGZuLmFwcGx5KHNlbGYsIGFyZ3MpOw0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIGluc3RhbnRpYXRlKFR5cGUsIGxvY2Fscywgc2VydmljZU5hbWUpIHsNCiAgICAgIC8vIENoZWNrIGlmIFR5cGUgaXMgYW5ub3RhdGVkIGFuZCB1c2UganVzdCB0aGUgZ2l2ZW4gZnVuY3Rpb24gYXQgbi0xIGFzIHBhcmFtZXRlcg0KICAgICAgLy8gZS5nLiBzb21lTW9kdWxlLmZhY3RvcnkoJ2dyZWV0ZXInLCBbJyR3aW5kb3cnLCBmdW5jdGlvbihyZW5hbWVkJHdpbmRvdykge31dKTsNCiAgICAgIC8vIE9iamVjdCBjcmVhdGlvbjogaHR0cDovL2pzcGVyZi5jb20vY3JlYXRlLWNvbnN0cnVjdG9yLzINCiAgICAgIHZhciBpbnN0YW5jZSA9IE9iamVjdC5jcmVhdGUoKGlzQXJyYXkoVHlwZSkgPyBUeXBlW1R5cGUubGVuZ3RoIC0gMV0gOiBUeXBlKS5wcm90b3R5cGUpOw0KICAgICAgdmFyIHJldHVybmVkVmFsdWUgPSBpbnZva2UoVHlwZSwgaW5zdGFuY2UsIGxvY2Fscywgc2VydmljZU5hbWUpOw0KDQogICAgICByZXR1cm4gaXNPYmplY3QocmV0dXJuZWRWYWx1ZSkgfHwgaXNGdW5jdGlvbihyZXR1cm5lZFZhbHVlKSA/IHJldHVybmVkVmFsdWUgOiBpbnN0YW5jZTsNCiAgICB9DQoNCiAgICByZXR1cm4gew0KICAgICAgaW52b2tlOiBpbnZva2UsDQogICAgICBpbnN0YW50aWF0ZTogaW5zdGFudGlhdGUsDQogICAgICBnZXQ6IGdldFNlcnZpY2UsDQogICAgICBhbm5vdGF0ZTogYW5ub3RhdGUsDQogICAgICBoYXM6IGZ1bmN0aW9uKG5hbWUpIHsNCiAgICAgICAgcmV0dXJuIHByb3ZpZGVyQ2FjaGUuaGFzT3duUHJvcGVydHkobmFtZSArIHByb3ZpZGVyU3VmZml4KSB8fCBjYWNoZS5oYXNPd25Qcm9wZXJ0eShuYW1lKTsNCiAgICAgIH0NCiAgICB9Ow0KICB9DQp9DQoNCmNyZWF0ZUluamVjdG9yLiQkYW5ub3RhdGUgPSBhbm5vdGF0ZTsNCg0KLyoqDQogKiBAbmdkb2MgcHJvdmlkZXINCiAqIEBuYW1lICRhbmNob3JTY3JvbGxQcm92aWRlcg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVXNlIGAkYW5jaG9yU2Nyb2xsUHJvdmlkZXJgIHRvIGRpc2FibGUgYXV0b21hdGljIHNjcm9sbGluZyB3aGVuZXZlcg0KICoge0BsaW5rIG5nLiRsb2NhdGlvbiNoYXNoICRsb2NhdGlvbi5oYXNoKCl9IGNoYW5nZXMuDQogKi8NCmZ1bmN0aW9uICRBbmNob3JTY3JvbGxQcm92aWRlcigpIHsNCg0KICB2YXIgYXV0b1Njcm9sbGluZ0VuYWJsZWQgPSB0cnVlOw0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lICRhbmNob3JTY3JvbGxQcm92aWRlciNkaXNhYmxlQXV0b1Njcm9sbGluZw0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogQnkgZGVmYXVsdCwge0BsaW5rIG5nLiRhbmNob3JTY3JvbGwgJGFuY2hvclNjcm9sbCgpfSB3aWxsIGF1dG9tYXRpY2FsbHkgZGV0ZWN0IGNoYW5nZXMgdG8NCiAgICoge0BsaW5rIG5nLiRsb2NhdGlvbiNoYXNoICRsb2NhdGlvbi5oYXNoKCl9IGFuZCBzY3JvbGwgdG8gdGhlIGVsZW1lbnQgbWF0Y2hpbmcgdGhlIG5ldyBoYXNoLjxiciAvPg0KICAgKiBVc2UgdGhpcyBtZXRob2QgdG8gZGlzYWJsZSBhdXRvbWF0aWMgc2Nyb2xsaW5nLg0KICAgKg0KICAgKiBJZiBhdXRvbWF0aWMgc2Nyb2xsaW5nIGlzIGRpc2FibGVkLCBvbmUgbXVzdCBleHBsaWNpdGx5IGNhbGwNCiAgICoge0BsaW5rIG5nLiRhbmNob3JTY3JvbGwgJGFuY2hvclNjcm9sbCgpfSBpbiBvcmRlciB0byBzY3JvbGwgdG8gdGhlIGVsZW1lbnQgcmVsYXRlZCB0byB0aGUNCiAgICogY3VycmVudCBoYXNoLg0KICAgKi8NCiAgdGhpcy5kaXNhYmxlQXV0b1Njcm9sbGluZyA9IGZ1bmN0aW9uKCkgew0KICAgIGF1dG9TY3JvbGxpbmdFbmFibGVkID0gZmFsc2U7DQogIH07DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBzZXJ2aWNlDQogICAqIEBuYW1lICRhbmNob3JTY3JvbGwNCiAgICogQGtpbmQgZnVuY3Rpb24NCiAgICogQHJlcXVpcmVzICR3aW5kb3cNCiAgICogQHJlcXVpcmVzICRsb2NhdGlvbg0KICAgKiBAcmVxdWlyZXMgJHJvb3RTY29wZQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogV2hlbiBjYWxsZWQsIGl0IGNoZWNrcyB0aGUgY3VycmVudCB2YWx1ZSBvZiB7QGxpbmsgbmcuJGxvY2F0aW9uI2hhc2ggJGxvY2F0aW9uLmhhc2goKX0gYW5kDQogICAqIHNjcm9sbHMgdG8gdGhlIHJlbGF0ZWQgZWxlbWVudCwgYWNjb3JkaW5nIHRvIHRoZSBydWxlcyBzcGVjaWZpZWQgaW4gdGhlDQogICAqIFtIdG1sNSBzcGVjXShodHRwOi8vZGV2LnczLm9yZy9odG1sNS9zcGVjL092ZXJ2aWV3Lmh0bWwjdGhlLWluZGljYXRlZC1wYXJ0LW9mLXRoZS1kb2N1bWVudCkuDQogICAqDQogICAqIEl0IGFsc28gd2F0Y2hlcyB0aGUge0BsaW5rIG5nLiRsb2NhdGlvbiNoYXNoICRsb2NhdGlvbi5oYXNoKCl9IGFuZCBhdXRvbWF0aWNhbGx5IHNjcm9sbHMgdG8NCiAgICogbWF0Y2ggYW55IGFuY2hvciB3aGVuZXZlciBpdCBjaGFuZ2VzLiBUaGlzIGNhbiBiZSBkaXNhYmxlZCBieSBjYWxsaW5nDQogICAqIHtAbGluayBuZy4kYW5jaG9yU2Nyb2xsUHJvdmlkZXIjZGlzYWJsZUF1dG9TY3JvbGxpbmcgJGFuY2hvclNjcm9sbFByb3ZpZGVyLmRpc2FibGVBdXRvU2Nyb2xsaW5nKCl9Lg0KICAgKg0KICAgKiBBZGRpdGlvbmFsbHksIHlvdSBjYW4gdXNlIGl0cyB7QGxpbmsgbmcuJGFuY2hvclNjcm9sbCN5T2Zmc2V0IHlPZmZzZXR9IHByb3BlcnR5IHRvIHNwZWNpZnkgYQ0KICAgKiB2ZXJ0aWNhbCBzY3JvbGwtb2Zmc2V0IChlaXRoZXIgZml4ZWQgb3IgZHluYW1pYykuDQogICAqDQogICAqIEBwcm9wZXJ0eSB7KG51bWJlcnxmdW5jdGlvbnxqcUxpdGUpfSB5T2Zmc2V0DQogICAqIElmIHNldCwgc3BlY2lmaWVzIGEgdmVydGljYWwgc2Nyb2xsLW9mZnNldC4gVGhpcyBpcyBvZnRlbiB1c2VmdWwgd2hlbiB0aGVyZSBhcmUgZml4ZWQNCiAgICogcG9zaXRpb25lZCBlbGVtZW50cyBhdCB0aGUgdG9wIG9mIHRoZSBwYWdlLCBzdWNoIGFzIG5hdmJhcnMsIGhlYWRlcnMgZXRjLg0KICAgKg0KICAgKiBgeU9mZnNldGAgY2FuIGJlIHNwZWNpZmllZCBpbiB2YXJpb3VzIHdheXM6DQogICAqIC0gKipudW1iZXIqKjogQSBmaXhlZCBudW1iZXIgb2YgcGl4ZWxzIHRvIGJlIHVzZWQgYXMgb2Zmc2V0LjxiciAvPjxiciAvPg0KICAgKiAtICoqZnVuY3Rpb24qKjogQSBnZXR0ZXIgZnVuY3Rpb24gY2FsbGVkIGV2ZXJ5dGltZSBgJGFuY2hvclNjcm9sbCgpYCBpcyBleGVjdXRlZC4gTXVzdCByZXR1cm4NCiAgICogICBhIG51bWJlciByZXByZXNlbnRpbmcgdGhlIG9mZnNldCAoaW4gcGl4ZWxzKS48YnIgLz48YnIgLz4NCiAgICogLSAqKmpxTGl0ZSoqOiBBIGpxTGl0ZS9qUXVlcnkgZWxlbWVudCB0byBiZSB1c2VkIGZvciBzcGVjaWZ5aW5nIHRoZSBvZmZzZXQuIFRoZSBkaXN0YW5jZSBmcm9tDQogICAqICAgdGhlIHRvcCBvZiB0aGUgcGFnZSB0byB0aGUgZWxlbWVudCdzIGJvdHRvbSB3aWxsIGJlIHVzZWQgYXMgb2Zmc2V0LjxiciAvPg0KICAgKiAgICoqTm90ZSoqOiBUaGUgZWxlbWVudCB3aWxsIGJlIHRha2VuIGludG8gYWNjb3VudCBvbmx5IGFzIGxvbmcgYXMgaXRzIGBwb3NpdGlvbmAgaXMgc2V0IHRvDQogICAqICAgYGZpeGVkYC4gVGhpcyBvcHRpb24gaXMgdXNlZnVsLCB3aGVuIGRlYWxpbmcgd2l0aCByZXNwb25zaXZlIG5hdmJhcnMvaGVhZGVycyB0aGF0IGFkanVzdA0KICAgKiAgIHRoZWlyIGhlaWdodCBhbmQvb3IgcG9zaXRpb25pbmcgYWNjb3JkaW5nIHRvIHRoZSB2aWV3cG9ydCdzIHNpemUuDQogICAqDQogICAqIDxiciAvPg0KICAgKiA8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4NCiAgICogSW4gb3JkZXIgZm9yIGB5T2Zmc2V0YCB0byB3b3JrIHByb3Blcmx5LCBzY3JvbGxpbmcgc2hvdWxkIHRha2UgcGxhY2Ugb24gdGhlIGRvY3VtZW50J3Mgcm9vdCBhbmQNCiAgICogbm90IHNvbWUgY2hpbGQgZWxlbWVudC4NCiAgICogPC9kaXY+DQogICAqDQogICAqIEBleGFtcGxlDQogICAgIDxleGFtcGxlIG1vZHVsZT0iYW5jaG9yU2Nyb2xsRXhhbXBsZSI+DQogICAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgICA8ZGl2IGlkPSJzY3JvbGxBcmVhIiBuZy1jb250cm9sbGVyPSJTY3JvbGxDb250cm9sbGVyIj4NCiAgICAgICAgICAgPGEgbmctY2xpY2s9ImdvdG9Cb3R0b20oKSI+R28gdG8gYm90dG9tPC9hPg0KICAgICAgICAgICA8YSBpZD0iYm90dG9tIj48L2E+IFlvdSdyZSBhdCB0aGUgYm90dG9tIQ0KICAgICAgICAgPC9kaXY+DQogICAgICAgPC9maWxlPg0KICAgICAgIDxmaWxlIG5hbWU9InNjcmlwdC5qcyI+DQogICAgICAgICBhbmd1bGFyLm1vZHVsZSgnYW5jaG9yU2Nyb2xsRXhhbXBsZScsIFtdKQ0KICAgICAgICAgICAuY29udHJvbGxlcignU2Nyb2xsQ29udHJvbGxlcicsIFsnJHNjb3BlJywgJyRsb2NhdGlvbicsICckYW5jaG9yU2Nyb2xsJywNCiAgICAgICAgICAgICBmdW5jdGlvbiAoJHNjb3BlLCAkbG9jYXRpb24sICRhbmNob3JTY3JvbGwpIHsNCiAgICAgICAgICAgICAgICRzY29wZS5nb3RvQm90dG9tID0gZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgICAgIC8vIHNldCB0aGUgbG9jYXRpb24uaGFzaCB0byB0aGUgaWQgb2YNCiAgICAgICAgICAgICAgICAgLy8gdGhlIGVsZW1lbnQgeW91IHdpc2ggdG8gc2Nyb2xsIHRvLg0KICAgICAgICAgICAgICAgICAkbG9jYXRpb24uaGFzaCgnYm90dG9tJyk7DQoNCiAgICAgICAgICAgICAgICAgLy8gY2FsbCAkYW5jaG9yU2Nyb2xsKCkNCiAgICAgICAgICAgICAgICAgJGFuY2hvclNjcm9sbCgpOw0KICAgICAgICAgICAgICAgfTsNCiAgICAgICAgICAgICB9XSk7DQogICAgICAgPC9maWxlPg0KICAgICAgIDxmaWxlIG5hbWU9InN0eWxlLmNzcyI+DQogICAgICAgICAjc2Nyb2xsQXJlYSB7DQogICAgICAgICAgIGhlaWdodDogMjgwcHg7DQogICAgICAgICAgIG92ZXJmbG93OiBhdXRvOw0KICAgICAgICAgfQ0KDQogICAgICAgICAjYm90dG9tIHsNCiAgICAgICAgICAgZGlzcGxheTogYmxvY2s7DQogICAgICAgICAgIG1hcmdpbi10b3A6IDIwMDBweDsNCiAgICAgICAgIH0NCiAgICAgICA8L2ZpbGU+DQogICAgIDwvZXhhbXBsZT4NCiAgICoNCiAgICogPGhyIC8+DQogICAqIFRoZSBleGFtcGxlIGJlbG93IGlsbHVzdHJhdGVzIHRoZSB1c2Ugb2YgYSB2ZXJ0aWNhbCBzY3JvbGwtb2Zmc2V0IChzcGVjaWZpZWQgYXMgYSBmaXhlZCB2YWx1ZSkuDQogICAqIFNlZSB7QGxpbmsgbmcuJGFuY2hvclNjcm9sbCN5T2Zmc2V0ICRhbmNob3JTY3JvbGwueU9mZnNldH0gZm9yIG1vcmUgZGV0YWlscy4NCiAgICoNCiAgICogQGV4YW1wbGUNCiAgICAgPGV4YW1wbGUgbW9kdWxlPSJhbmNob3JTY3JvbGxPZmZzZXRFeGFtcGxlIj4NCiAgICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICAgIDxkaXYgY2xhc3M9ImZpeGVkLWhlYWRlciIgbmctY29udHJvbGxlcj0iaGVhZGVyQ3RybCI+DQogICAgICAgICAgIDxhIGhyZWY9IiIgbmctY2xpY2s9ImdvdG9BbmNob3IoeCkiIG5nLXJlcGVhdD0ieCBpbiBbMSwyLDMsNCw1XSI+DQogICAgICAgICAgICAgR28gdG8gYW5jaG9yIHt7eH19DQogICAgICAgICAgIDwvYT4NCiAgICAgICAgIDwvZGl2Pg0KICAgICAgICAgPGRpdiBpZD0iYW5jaG9ye3t4fX0iIGNsYXNzPSJhbmNob3IiIG5nLXJlcGVhdD0ieCBpbiBbMSwyLDMsNCw1XSI+DQogICAgICAgICAgIEFuY2hvciB7e3h9fSBvZiA1DQogICAgICAgICA8L2Rpdj4NCiAgICAgICA8L2ZpbGU+DQogICAgICAgPGZpbGUgbmFtZT0ic2NyaXB0LmpzIj4NCiAgICAgICAgIGFuZ3VsYXIubW9kdWxlKCdhbmNob3JTY3JvbGxPZmZzZXRFeGFtcGxlJywgW10pDQogICAgICAgICAgIC5ydW4oWyckYW5jaG9yU2Nyb2xsJywgZnVuY3Rpb24oJGFuY2hvclNjcm9sbCkgew0KICAgICAgICAgICAgICRhbmNob3JTY3JvbGwueU9mZnNldCA9IDUwOyAgIC8vIGFsd2F5cyBzY3JvbGwgYnkgNTAgZXh0cmEgcGl4ZWxzDQogICAgICAgICAgIH1dKQ0KICAgICAgICAgICAuY29udHJvbGxlcignaGVhZGVyQ3RybCcsIFsnJGFuY2hvclNjcm9sbCcsICckbG9jYXRpb24nLCAnJHNjb3BlJywNCiAgICAgICAgICAgICBmdW5jdGlvbiAoJGFuY2hvclNjcm9sbCwgJGxvY2F0aW9uLCAkc2NvcGUpIHsNCiAgICAgICAgICAgICAgICRzY29wZS5nb3RvQW5jaG9yID0gZnVuY3Rpb24oeCkgew0KICAgICAgICAgICAgICAgICB2YXIgbmV3SGFzaCA9ICdhbmNob3InICsgeDsNCiAgICAgICAgICAgICAgICAgaWYgKCRsb2NhdGlvbi5oYXNoKCkgIT09IG5ld0hhc2gpIHsNCiAgICAgICAgICAgICAgICAgICAvLyBzZXQgdGhlICRsb2NhdGlvbi5oYXNoIHRvIGBuZXdIYXNoYCBhbmQNCiAgICAgICAgICAgICAgICAgICAvLyAkYW5jaG9yU2Nyb2xsIHdpbGwgYXV0b21hdGljYWxseSBzY3JvbGwgdG8gaXQNCiAgICAgICAgICAgICAgICAgICAkbG9jYXRpb24uaGFzaCgnYW5jaG9yJyArIHgpOw0KICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgIC8vIGNhbGwgJGFuY2hvclNjcm9sbCgpIGV4cGxpY2l0bHksDQogICAgICAgICAgICAgICAgICAgLy8gc2luY2UgJGxvY2F0aW9uLmhhc2ggaGFzbid0IGNoYW5nZWQNCiAgICAgICAgICAgICAgICAgICAkYW5jaG9yU2Nyb2xsKCk7DQogICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgIH07DQogICAgICAgICAgICAgfQ0KICAgICAgICAgICBdKTsNCiAgICAgICA8L2ZpbGU+DQogICAgICAgPGZpbGUgbmFtZT0ic3R5bGUuY3NzIj4NCiAgICAgICAgIGJvZHkgew0KICAgICAgICAgICBwYWRkaW5nLXRvcDogNTBweDsNCiAgICAgICAgIH0NCg0KICAgICAgICAgLmFuY2hvciB7DQogICAgICAgICAgIGJvcmRlcjogMnB4IGRhc2hlZCBEYXJrT3JjaGlkOw0KICAgICAgICAgICBwYWRkaW5nOiAxMHB4IDEwcHggMjAwcHggMTBweDsNCiAgICAgICAgIH0NCg0KICAgICAgICAgLmZpeGVkLWhlYWRlciB7DQogICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwgMCwgMCwgMC4yKTsNCiAgICAgICAgICAgaGVpZ2h0OiA1MHB4Ow0KICAgICAgICAgICBwb3NpdGlvbjogZml4ZWQ7DQogICAgICAgICAgIHRvcDogMDsgbGVmdDogMDsgcmlnaHQ6IDA7DQogICAgICAgICB9DQoNCiAgICAgICAgIC5maXhlZC1oZWFkZXIgPiBhIHsNCiAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrOw0KICAgICAgICAgICBtYXJnaW46IDVweCAxNXB4Ow0KICAgICAgICAgfQ0KICAgICAgIDwvZmlsZT4NCiAgICAgPC9leGFtcGxlPg0KICAgKi8NCiAgdGhpcy4kZ2V0ID0gWyckd2luZG93JywgJyRsb2NhdGlvbicsICckcm9vdFNjb3BlJywgZnVuY3Rpb24oJHdpbmRvdywgJGxvY2F0aW9uLCAkcm9vdFNjb3BlKSB7DQogICAgdmFyIGRvY3VtZW50ID0gJHdpbmRvdy5kb2N1bWVudDsNCg0KICAgIC8vIEhlbHBlciBmdW5jdGlvbiB0byBnZXQgZmlyc3QgYW5jaG9yIGZyb20gYSBOb2RlTGlzdA0KICAgIC8vICh1c2luZyBgQXJyYXkjc29tZSgpYCBpbnN0ZWFkIG9mIGBhbmd1bGFyI2ZvckVhY2goKWAgc2luY2UgaXQncyBtb3JlIHBlcmZvcm1hbnQNCiAgICAvLyAgYW5kIHdvcmtpbmcgaW4gYWxsIHN1cHBvcnRlZCBicm93c2Vycy4pDQogICAgZnVuY3Rpb24gZ2V0Rmlyc3RBbmNob3IobGlzdCkgew0KICAgICAgdmFyIHJlc3VsdCA9IG51bGw7DQogICAgICBBcnJheS5wcm90b3R5cGUuc29tZS5jYWxsKGxpc3QsIGZ1bmN0aW9uKGVsZW1lbnQpIHsNCiAgICAgICAgaWYgKG5vZGVOYW1lXyhlbGVtZW50KSA9PT0gJ2EnKSB7DQogICAgICAgICAgcmVzdWx0ID0gZWxlbWVudDsNCiAgICAgICAgICByZXR1cm4gdHJ1ZTsNCiAgICAgICAgfQ0KICAgICAgfSk7DQogICAgICByZXR1cm4gcmVzdWx0Ow0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIGdldFlPZmZzZXQoKSB7DQoNCiAgICAgIHZhciBvZmZzZXQgPSBzY3JvbGwueU9mZnNldDsNCg0KICAgICAgaWYgKGlzRnVuY3Rpb24ob2Zmc2V0KSkgew0KICAgICAgICBvZmZzZXQgPSBvZmZzZXQoKTsNCiAgICAgIH0gZWxzZSBpZiAoaXNFbGVtZW50KG9mZnNldCkpIHsNCiAgICAgICAgdmFyIGVsZW0gPSBvZmZzZXRbMF07DQogICAgICAgIHZhciBzdHlsZSA9ICR3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtKTsNCiAgICAgICAgaWYgKHN0eWxlLnBvc2l0aW9uICE9PSAnZml4ZWQnKSB7DQogICAgICAgICAgb2Zmc2V0ID0gMDsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBvZmZzZXQgPSBlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmJvdHRvbTsNCiAgICAgICAgfQ0KICAgICAgfSBlbHNlIGlmICghaXNOdW1iZXIob2Zmc2V0KSkgew0KICAgICAgICBvZmZzZXQgPSAwOw0KICAgICAgfQ0KDQogICAgICByZXR1cm4gb2Zmc2V0Ow0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIHNjcm9sbFRvKGVsZW0pIHsNCiAgICAgIGlmIChlbGVtKSB7DQogICAgICAgIGVsZW0uc2Nyb2xsSW50b1ZpZXcoKTsNCg0KICAgICAgICB2YXIgb2Zmc2V0ID0gZ2V0WU9mZnNldCgpOw0KDQogICAgICAgIGlmIChvZmZzZXQpIHsNCiAgICAgICAgICAvLyBgb2Zmc2V0YCBpcyB0aGUgbnVtYmVyIG9mIHBpeGVscyB3ZSBzaG91bGQgc2Nyb2xsIFVQIGluIG9yZGVyIHRvIGFsaWduIGBlbGVtYCBwcm9wZXJseS4NCiAgICAgICAgICAvLyBUaGlzIGlzIHRydWUgT05MWSBpZiB0aGUgY2FsbCB0byBgZWxlbS5zY3JvbGxJbnRvVmlldygpYCBpbml0aWFsbHkgYWxpZ25zIGBlbGVtYCBhdCB0aGUNCiAgICAgICAgICAvLyB0b3Agb2YgdGhlIHZpZXdwb3J0Lg0KICAgICAgICAgIC8vDQogICAgICAgICAgLy8gSUYgdGhlIG51bWJlciBvZiBwaXhlbHMgZnJvbSB0aGUgdG9wIG9mIGBlbGVtYCB0byB0aGUgZW5kIG9mIHRoZSBwYWdlJ3MgY29udGVudCBpcyBsZXNzDQogICAgICAgICAgLy8gdGhhbiB0aGUgaGVpZ2h0IG9mIHRoZSB2aWV3cG9ydCwgdGhlbiBgZWxlbS5zY3JvbGxJbnRvVmlldygpYCB3aWxsIGFsaWduIHRoZSBgZWxlbWAgc29tZQ0KICAgICAgICAgIC8vIHdheSBkb3duIHRoZSBwYWdlLg0KICAgICAgICAgIC8vDQogICAgICAgICAgLy8gVGhpcyBpcyBvZnRlbiB0aGUgY2FzZSBmb3IgZWxlbWVudHMgbmVhciB0aGUgYm90dG9tIG9mIHRoZSBwYWdlLg0KICAgICAgICAgIC8vDQogICAgICAgICAgLy8gSW4gc3VjaCBjYXNlcyB3ZSBkbyBub3QgbmVlZCB0byBzY3JvbGwgdGhlIHdob2xlIGBvZmZzZXRgIHVwLCBqdXN0IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4NCiAgICAgICAgICAvLyB0aGUgdG9wIG9mIHRoZSBlbGVtZW50IGFuZCB0aGUgb2Zmc2V0LCB3aGljaCBpcyBlbm91Z2ggdG8gYWxpZ24gdGhlIHRvcCBvZiBgZWxlbWAgYXQgdGhlDQogICAgICAgICAgLy8gZGVzaXJlZCBwb3NpdGlvbi4NCiAgICAgICAgICB2YXIgZWxlbVRvcCA9IGVsZW0uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wOw0KICAgICAgICAgICR3aW5kb3cuc2Nyb2xsQnkoMCwgZWxlbVRvcCAtIG9mZnNldCk7DQogICAgICAgIH0NCiAgICAgIH0gZWxzZSB7DQogICAgICAgICR3aW5kb3cuc2Nyb2xsVG8oMCwgMCk7DQogICAgICB9DQogICAgfQ0KDQogICAgZnVuY3Rpb24gc2Nyb2xsKCkgew0KICAgICAgdmFyIGhhc2ggPSAkbG9jYXRpb24uaGFzaCgpLCBlbG07DQoNCiAgICAgIC8vIGVtcHR5IGhhc2gsIHNjcm9sbCB0byB0aGUgdG9wIG9mIHRoZSBwYWdlDQogICAgICBpZiAoIWhhc2gpIHNjcm9sbFRvKG51bGwpOw0KDQogICAgICAvLyBlbGVtZW50IHdpdGggZ2l2ZW4gaWQNCiAgICAgIGVsc2UgaWYgKChlbG0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChoYXNoKSkpIHNjcm9sbFRvKGVsbSk7DQoNCiAgICAgIC8vIGZpcnN0IGFuY2hvciB3aXRoIGdpdmVuIG5hbWUgOi1EDQogICAgICBlbHNlIGlmICgoZWxtID0gZ2V0Rmlyc3RBbmNob3IoZG9jdW1lbnQuZ2V0RWxlbWVudHNCeU5hbWUoaGFzaCkpKSkgc2Nyb2xsVG8oZWxtKTsNCg0KICAgICAgLy8gbm8gZWxlbWVudCBhbmQgaGFzaCA9PSAndG9wJywgc2Nyb2xsIHRvIHRoZSB0b3Agb2YgdGhlIHBhZ2UNCiAgICAgIGVsc2UgaWYgKGhhc2ggPT09ICd0b3AnKSBzY3JvbGxUbyhudWxsKTsNCiAgICB9DQoNCiAgICAvLyBkb2VzIG5vdCBzY3JvbGwgd2hlbiB1c2VyIGNsaWNrcyBvbiBhbmNob3IgbGluayB0aGF0IGlzIGN1cnJlbnRseSBvbg0KICAgIC8vIChubyB1cmwgY2hhbmdlLCBubyAkbG9jYXRpb24uaGFzaCgpIGNoYW5nZSksIGJyb3dzZXIgbmF0aXZlIGRvZXMgc2Nyb2xsDQogICAgaWYgKGF1dG9TY3JvbGxpbmdFbmFibGVkKSB7DQogICAgICAkcm9vdFNjb3BlLiR3YXRjaChmdW5jdGlvbiBhdXRvU2Nyb2xsV2F0Y2goKSB7cmV0dXJuICRsb2NhdGlvbi5oYXNoKCk7fSwNCiAgICAgICAgZnVuY3Rpb24gYXV0b1Njcm9sbFdhdGNoQWN0aW9uKG5ld1ZhbCwgb2xkVmFsKSB7DQogICAgICAgICAgLy8gc2tpcCB0aGUgaW5pdGlhbCBzY3JvbGwgaWYgJGxvY2F0aW9uLmhhc2ggaXMgZW1wdHkNCiAgICAgICAgICBpZiAobmV3VmFsID09PSBvbGRWYWwgJiYgbmV3VmFsID09PSAnJykgcmV0dXJuOw0KDQogICAgICAgICAganFMaXRlRG9jdW1lbnRMb2FkZWQoZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAkcm9vdFNjb3BlLiRldmFsQXN5bmMoc2Nyb2xsKTsNCiAgICAgICAgICB9KTsNCiAgICAgICAgfSk7DQogICAgfQ0KDQogICAgcmV0dXJuIHNjcm9sbDsNCiAgfV07DQp9DQoNCnZhciAkYW5pbWF0ZU1pbkVyciA9IG1pbkVycignJGFuaW1hdGUnKTsNCg0KLyoqDQogKiBAbmdkb2MgcHJvdmlkZXINCiAqIEBuYW1lICRhbmltYXRlUHJvdmlkZXINCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIERlZmF1bHQgaW1wbGVtZW50YXRpb24gb2YgJGFuaW1hdGUgdGhhdCBkb2Vzbid0IHBlcmZvcm0gYW55IGFuaW1hdGlvbnMsIGluc3RlYWQganVzdA0KICogc3luY2hyb25vdXNseSBwZXJmb3JtcyBET00NCiAqIHVwZGF0ZXMgYW5kIGNhbGxzIGRvbmUoKSBjYWxsYmFja3MuDQogKg0KICogSW4gb3JkZXIgdG8gZW5hYmxlIGFuaW1hdGlvbnMgdGhlIG5nQW5pbWF0ZSBtb2R1bGUgaGFzIHRvIGJlIGxvYWRlZC4NCiAqDQogKiBUbyBzZWUgdGhlIGZ1bmN0aW9uYWwgaW1wbGVtZW50YXRpb24gY2hlY2sgb3V0IHNyYy9uZ0FuaW1hdGUvYW5pbWF0ZS5qcw0KICovDQp2YXIgJEFuaW1hdGVQcm92aWRlciA9IFsnJHByb3ZpZGUnLCBmdW5jdGlvbigkcHJvdmlkZSkgew0KDQoNCiAgdGhpcy4kJHNlbGVjdG9ycyA9IHt9Ow0KDQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgJGFuaW1hdGVQcm92aWRlciNyZWdpc3Rlcg0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogUmVnaXN0ZXJzIGEgbmV3IGluamVjdGFibGUgYW5pbWF0aW9uIGZhY3RvcnkgZnVuY3Rpb24uIFRoZSBmYWN0b3J5IGZ1bmN0aW9uIHByb2R1Y2VzIHRoZQ0KICAgKiBhbmltYXRpb24gb2JqZWN0IHdoaWNoIGNvbnRhaW5zIGNhbGxiYWNrIGZ1bmN0aW9ucyBmb3IgZWFjaCBldmVudCB0aGF0IGlzIGV4cGVjdGVkIHRvIGJlDQogICAqIGFuaW1hdGVkLg0KICAgKg0KICAgKiAgICogYGV2ZW50Rm5gOiBgZnVuY3Rpb24oRWxlbWVudCwgZG9uZUZ1bmN0aW9uKWAgVGhlIGVsZW1lbnQgdG8gYW5pbWF0ZSwgdGhlIGBkb25lRnVuY3Rpb25gDQogICAqICAgbXVzdCBiZSBjYWxsZWQgb25jZSB0aGUgZWxlbWVudCBhbmltYXRpb24gaXMgY29tcGxldGUuIElmIGEgZnVuY3Rpb24gaXMgcmV0dXJuZWQgdGhlbiB0aGUNCiAgICogICBhbmltYXRpb24gc2VydmljZSB3aWxsIHVzZSB0aGlzIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgYW5pbWF0aW9uIHdoZW5ldmVyIGEgY2FuY2VsIGV2ZW50IGlzDQogICAqICAgdHJpZ2dlcmVkLg0KICAgKg0KICAgKg0KICAgKiBgYGBqcw0KICAgKiAgIHJldHVybiB7DQogICAgICogICAgIGV2ZW50Rm4gOiBmdW5jdGlvbihlbGVtZW50LCBkb25lKSB7DQogICAgICogICAgICAgLy9jb2RlIHRvIHJ1biB0aGUgYW5pbWF0aW9uDQogICAgICogICAgICAgLy9vbmNlIGNvbXBsZXRlLCB0aGVuIHJ1biBkb25lKCkNCiAgICAgKiAgICAgICByZXR1cm4gZnVuY3Rpb24gY2FuY2VsbGF0aW9uRnVuY3Rpb24oKSB7DQogICAgICogICAgICAgICAvL2NvZGUgdG8gY2FuY2VsIHRoZSBhbmltYXRpb24NCiAgICAgKiAgICAgICB9DQogICAgICogICAgIH0NCiAgICAgKiAgIH0NCiAgICogYGBgDQogICAqDQogICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBhbmltYXRpb24uDQogICAqIEBwYXJhbSB7RnVuY3Rpb259IGZhY3RvcnkgVGhlIGZhY3RvcnkgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGV4ZWN1dGVkIHRvIHJldHVybiB0aGUgYW5pbWF0aW9uDQogICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0Lg0KICAgKi8NCiAgdGhpcy5yZWdpc3RlciA9IGZ1bmN0aW9uKG5hbWUsIGZhY3RvcnkpIHsNCiAgICB2YXIga2V5ID0gbmFtZSArICctYW5pbWF0aW9uJzsNCiAgICBpZiAobmFtZSAmJiBuYW1lLmNoYXJBdCgwKSAhPSAnLicpIHRocm93ICRhbmltYXRlTWluRXJyKCdub3Rjc2VsJywNCiAgICAgICAgIkV4cGVjdGluZyBjbGFzcyBzZWxlY3RvciBzdGFydGluZyB3aXRoICcuJyBnb3QgJ3swfScuIiwgbmFtZSk7DQogICAgdGhpcy4kJHNlbGVjdG9yc1tuYW1lLnN1YnN0cigxKV0gPSBrZXk7DQogICAgJHByb3ZpZGUuZmFjdG9yeShrZXksIGZhY3RvcnkpOw0KICB9Ow0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lICRhbmltYXRlUHJvdmlkZXIjY2xhc3NOYW1lRmlsdGVyDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBTZXRzIGFuZC9vciByZXR1cm5zIHRoZSBDU1MgY2xhc3MgcmVndWxhciBleHByZXNzaW9uIHRoYXQgaXMgY2hlY2tlZCB3aGVuIHBlcmZvcm1pbmcNCiAgICogYW4gYW5pbWF0aW9uLiBVcG9uIGJvb3RzdHJhcCB0aGUgY2xhc3NOYW1lRmlsdGVyIHZhbHVlIGlzIG5vdCBzZXQgYXQgYWxsIGFuZCB3aWxsDQogICAqIHRoZXJlZm9yZSBlbmFibGUgJGFuaW1hdGUgdG8gYXR0ZW1wdCB0byBwZXJmb3JtIGFuIGFuaW1hdGlvbiBvbiBhbnkgZWxlbWVudC4NCiAgICogV2hlbiBzZXR0aW5nIHRoZSBjbGFzc05hbWVGaWx0ZXIgdmFsdWUsIGFuaW1hdGlvbnMgd2lsbCBvbmx5IGJlIHBlcmZvcm1lZCBvbiBlbGVtZW50cw0KICAgKiB0aGF0IHN1Y2Nlc3NmdWxseSBtYXRjaCB0aGUgZmlsdGVyIGV4cHJlc3Npb24uIFRoaXMgaW4gdHVybiBjYW4gYm9vc3QgcGVyZm9ybWFuY2UNCiAgICogZm9yIGxvdy1wb3dlcmVkIGRldmljZXMgYXMgd2VsbCBhcyBhcHBsaWNhdGlvbnMgY29udGFpbmluZyBhIGxvdCBvZiBzdHJ1Y3R1cmFsIG9wZXJhdGlvbnMuDQogICAqIEBwYXJhbSB7UmVnRXhwPX0gZXhwcmVzc2lvbiBUaGUgY2xhc3NOYW1lIGV4cHJlc3Npb24gd2hpY2ggd2lsbCBiZSBjaGVja2VkIGFnYWluc3QgYWxsIGFuaW1hdGlvbnMNCiAgICogQHJldHVybiB7UmVnRXhwfSBUaGUgY3VycmVudCBDU1MgY2xhc3NOYW1lIGV4cHJlc3Npb24gdmFsdWUuIElmIG51bGwgdGhlbiB0aGVyZSBpcyBubyBleHByZXNzaW9uIHZhbHVlDQogICAqLw0KICB0aGlzLmNsYXNzTmFtZUZpbHRlciA9IGZ1bmN0aW9uKGV4cHJlc3Npb24pIHsNCiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgew0KICAgICAgdGhpcy4kJGNsYXNzTmFtZUZpbHRlciA9IChleHByZXNzaW9uIGluc3RhbmNlb2YgUmVnRXhwKSA/IGV4cHJlc3Npb24gOiBudWxsOw0KICAgIH0NCiAgICByZXR1cm4gdGhpcy4kJGNsYXNzTmFtZUZpbHRlcjsNCiAgfTsNCg0KICB0aGlzLiRnZXQgPSBbJyQkcScsICckJGFzeW5jQ2FsbGJhY2snLCAnJHJvb3RTY29wZScsIGZ1bmN0aW9uKCQkcSwgJCRhc3luY0NhbGxiYWNrLCAkcm9vdFNjb3BlKSB7DQoNCiAgICB2YXIgY3VycmVudERlZmVyOw0KDQogICAgZnVuY3Rpb24gcnVuQW5pbWF0aW9uUG9zdERpZ2VzdChmbikgew0KICAgICAgdmFyIGNhbmNlbEZuLCBkZWZlciA9ICQkcS5kZWZlcigpOw0KICAgICAgZGVmZXIucHJvbWlzZS4kJGNhbmNlbEZuID0gZnVuY3Rpb24gbmdBbmltYXRlTWF5YmVDYW5jZWwoKSB7DQogICAgICAgIGNhbmNlbEZuICYmIGNhbmNlbEZuKCk7DQogICAgICB9Ow0KDQogICAgICAkcm9vdFNjb3BlLiQkcG9zdERpZ2VzdChmdW5jdGlvbiBuZ0FuaW1hdGVQb3N0RGlnZXN0KCkgew0KICAgICAgICBjYW5jZWxGbiA9IGZuKGZ1bmN0aW9uIG5nQW5pbWF0ZU5vdGlmeUNvbXBsZXRlKCkgew0KICAgICAgICAgIGRlZmVyLnJlc29sdmUoKTsNCiAgICAgICAgfSk7DQogICAgICB9KTsNCg0KICAgICAgcmV0dXJuIGRlZmVyLnByb21pc2U7DQogICAgfQ0KDQogICAgZnVuY3Rpb24gcmVzb2x2ZUVsZW1lbnRDbGFzc2VzKGVsZW1lbnQsIGNsYXNzZXMpIHsNCiAgICAgIHZhciB0b0FkZCA9IFtdLCB0b1JlbW92ZSA9IFtdOw0KDQogICAgICB2YXIgaGFzQ2xhc3NlcyA9IGNyZWF0ZU1hcCgpOw0KICAgICAgZm9yRWFjaCgoZWxlbWVudC5hdHRyKCdjbGFzcycpIHx8ICcnKS5zcGxpdCgvXHMrLyksIGZ1bmN0aW9uKGNsYXNzTmFtZSkgew0KICAgICAgICBoYXNDbGFzc2VzW2NsYXNzTmFtZV0gPSB0cnVlOw0KICAgICAgfSk7DQoNCiAgICAgIGZvckVhY2goY2xhc3NlcywgZnVuY3Rpb24oc3RhdHVzLCBjbGFzc05hbWUpIHsNCiAgICAgICAgdmFyIGhhc0NsYXNzID0gaGFzQ2xhc3Nlc1tjbGFzc05hbWVdOw0KDQogICAgICAgIC8vIElmIHRoZSBtb3N0IHJlY2VudCBjbGFzcyBtYW5pcHVsYXRpb24gKHZpYSAkYW5pbWF0ZSkgd2FzIHRvIHJlbW92ZSB0aGUgY2xhc3MsIGFuZCB0aGUNCiAgICAgICAgLy8gZWxlbWVudCBjdXJyZW50bHkgaGFzIHRoZSBjbGFzcywgdGhlIGNsYXNzIGlzIHNjaGVkdWxlZCBmb3IgcmVtb3ZhbC4gT3RoZXJ3aXNlLCBpZg0KICAgICAgICAvLyB0aGUgbW9zdCByZWNlbnQgY2xhc3MgbWFuaXB1bGF0aW9uICh2aWEgJGFuaW1hdGUpIHdhcyB0byBhZGQgdGhlIGNsYXNzLCBhbmQgdGhlDQogICAgICAgIC8vIGVsZW1lbnQgZG9lcyBub3QgY3VycmVudGx5IGhhdmUgdGhlIGNsYXNzLCB0aGUgY2xhc3MgaXMgc2NoZWR1bGVkIHRvIGJlIGFkZGVkLg0KICAgICAgICBpZiAoc3RhdHVzID09PSBmYWxzZSAmJiBoYXNDbGFzcykgew0KICAgICAgICAgIHRvUmVtb3ZlLnB1c2goY2xhc3NOYW1lKTsNCiAgICAgICAgfSBlbHNlIGlmIChzdGF0dXMgPT09IHRydWUgJiYgIWhhc0NsYXNzKSB7DQogICAgICAgICAgdG9BZGQucHVzaChjbGFzc05hbWUpOw0KICAgICAgICB9DQogICAgICB9KTsNCg0KICAgICAgcmV0dXJuICh0b0FkZC5sZW5ndGggKyB0b1JlbW92ZS5sZW5ndGgpID4gMCAmJg0KICAgICAgICBbdG9BZGQubGVuZ3RoID8gdG9BZGQgOiBudWxsLCB0b1JlbW92ZS5sZW5ndGggPyB0b1JlbW92ZSA6IG51bGxdOw0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIGNhY2hlZENsYXNzTWFuaXB1bGF0aW9uKGNhY2hlLCBjbGFzc2VzLCBvcCkgew0KICAgICAgZm9yICh2YXIgaT0wLCBpaSA9IGNsYXNzZXMubGVuZ3RoOyBpIDwgaWk7ICsraSkgew0KICAgICAgICB2YXIgY2xhc3NOYW1lID0gY2xhc3Nlc1tpXTsNCiAgICAgICAgY2FjaGVbY2xhc3NOYW1lXSA9IG9wOw0KICAgICAgfQ0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIGFzeW5jUHJvbWlzZSgpIHsNCiAgICAgIC8vIG9ubHkgc2VydmUgb25lIGluc3RhbmNlIG9mIGEgcHJvbWlzZSBpbiBvcmRlciB0byBzYXZlIENQVSBjeWNsZXMNCiAgICAgIGlmICghY3VycmVudERlZmVyKSB7DQogICAgICAgIGN1cnJlbnREZWZlciA9ICQkcS5kZWZlcigpOw0KICAgICAgICAkJGFzeW5jQ2FsbGJhY2soZnVuY3Rpb24oKSB7DQogICAgICAgICAgY3VycmVudERlZmVyLnJlc29sdmUoKTsNCiAgICAgICAgICBjdXJyZW50RGVmZXIgPSBudWxsOw0KICAgICAgICB9KTsNCiAgICAgIH0NCiAgICAgIHJldHVybiBjdXJyZW50RGVmZXIucHJvbWlzZTsNCiAgICB9DQoNCiAgICBmdW5jdGlvbiBhcHBseVN0eWxlcyhlbGVtZW50LCBvcHRpb25zKSB7DQogICAgICBpZiAoYW5ndWxhci5pc09iamVjdChvcHRpb25zKSkgew0KICAgICAgICB2YXIgc3R5bGVzID0gZXh0ZW5kKG9wdGlvbnMuZnJvbSB8fCB7fSwgb3B0aW9ucy50byB8fCB7fSk7DQogICAgICAgIGVsZW1lbnQuY3NzKHN0eWxlcyk7DQogICAgICB9DQogICAgfQ0KDQogICAgLyoqDQogICAgICoNCiAgICAgKiBAbmdkb2Mgc2VydmljZQ0KICAgICAqIEBuYW1lICRhbmltYXRlDQogICAgICogQGRlc2NyaXB0aW9uIFRoZSAkYW5pbWF0ZSBzZXJ2aWNlIHByb3ZpZGVzIHJ1ZGltZW50YXJ5IERPTSBtYW5pcHVsYXRpb24gZnVuY3Rpb25zIHRvDQogICAgICogaW5zZXJ0LCByZW1vdmUgYW5kIG1vdmUgZWxlbWVudHMgd2l0aGluIHRoZSBET00sIGFzIHdlbGwgYXMgYWRkaW5nIGFuZCByZW1vdmluZyBjbGFzc2VzLg0KICAgICAqIFRoaXMgc2VydmljZSBpcyB0aGUgY29yZSBzZXJ2aWNlIHVzZWQgYnkgdGhlIG5nQW5pbWF0ZSAkYW5pbWF0b3Igc2VydmljZSB3aGljaCBwcm92aWRlcw0KICAgICAqIGhpZ2gtbGV2ZWwgYW5pbWF0aW9uIGhvb2tzIGZvciBDU1MgYW5kIEphdmFTY3JpcHQuDQogICAgICoNCiAgICAgKiAkYW5pbWF0ZSBpcyBhdmFpbGFibGUgaW4gdGhlIEFuZ3VsYXJKUyBjb3JlLCBob3dldmVyLCB0aGUgbmdBbmltYXRlIG1vZHVsZSBtdXN0IGJlIGluY2x1ZGVkDQogICAgICogdG8gZW5hYmxlIGZ1bGwgb3V0IGFuaW1hdGlvbiBzdXBwb3J0LiBPdGhlcndpc2UsICRhbmltYXRlIHdpbGwgb25seSBwZXJmb3JtIHNpbXBsZSBET00NCiAgICAgKiBtYW5pcHVsYXRpb24gb3BlcmF0aW9ucy4NCiAgICAgKg0KICAgICAqIFRvIGxlYXJuIG1vcmUgYWJvdXQgZW5hYmxpbmcgYW5pbWF0aW9uIHN1cHBvcnQsIGNsaWNrIGhlcmUgdG8gdmlzaXQgdGhlIHtAbGluayBuZ0FuaW1hdGUNCiAgICAgKiBuZ0FuaW1hdGUgbW9kdWxlIHBhZ2V9IGFzIHdlbGwgYXMgdGhlIHtAbGluayBuZ0FuaW1hdGUuJGFuaW1hdGUgbmdBbmltYXRlICRhbmltYXRlIHNlcnZpY2UNCiAgICAgKiBwYWdlfS4NCiAgICAgKi8NCiAgICByZXR1cm4gew0KICAgICAgYW5pbWF0ZTogZnVuY3Rpb24oZWxlbWVudCwgZnJvbSwgdG8pIHsNCiAgICAgICAgYXBwbHlTdHlsZXMoZWxlbWVudCwgeyBmcm9tOiBmcm9tLCB0bzogdG8gfSk7DQogICAgICAgIHJldHVybiBhc3luY1Byb21pc2UoKTsNCiAgICAgIH0sDQoNCiAgICAgIC8qKg0KICAgICAgICoNCiAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAqIEBuYW1lICRhbmltYXRlI2VudGVyDQogICAgICAgKiBAa2luZCBmdW5jdGlvbg0KICAgICAgICogQGRlc2NyaXB0aW9uIEluc2VydHMgdGhlIGVsZW1lbnQgaW50byB0aGUgRE9NIGVpdGhlciBhZnRlciB0aGUgYGFmdGVyYCBlbGVtZW50IG9yDQogICAgICAgKiBhcyB0aGUgZmlyc3QgY2hpbGQgd2l0aGluIHRoZSBgcGFyZW50YCBlbGVtZW50LiBXaGVuIHRoZSBmdW5jdGlvbiBpcyBjYWxsZWQgYSBwcm9taXNlDQogICAgICAgKiBpcyByZXR1cm5lZCB0aGF0IHdpbGwgYmUgcmVzb2x2ZWQgYXQgYSBsYXRlciB0aW1lLg0KICAgICAgICogQHBhcmFtIHtET01FbGVtZW50fSBlbGVtZW50IHRoZSBlbGVtZW50IHdoaWNoIHdpbGwgYmUgaW5zZXJ0ZWQgaW50byB0aGUgRE9NDQogICAgICAgKiBAcGFyYW0ge0RPTUVsZW1lbnR9IHBhcmVudCB0aGUgcGFyZW50IGVsZW1lbnQgd2hpY2ggd2lsbCBhcHBlbmQgdGhlIGVsZW1lbnQgYXMNCiAgICAgICAqICAgYSBjaGlsZCAoaWYgdGhlIGFmdGVyIGVsZW1lbnQgaXMgbm90IHByZXNlbnQpDQogICAgICAgKiBAcGFyYW0ge0RPTUVsZW1lbnR9IGFmdGVyIHRoZSBzaWJsaW5nIGVsZW1lbnQgd2hpY2ggd2lsbCBhcHBlbmQgdGhlIGVsZW1lbnQNCiAgICAgICAqICAgYWZ0ZXIgaXRzZWxmDQogICAgICAgKiBAcGFyYW0ge29iamVjdD19IG9wdGlvbnMgYW4gb3B0aW9uYWwgY29sbGVjdGlvbiBvZiBzdHlsZXMgdGhhdCB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIGVsZW1lbnQuDQogICAgICAgKiBAcmV0dXJuIHtQcm9taXNlfSB0aGUgYW5pbWF0aW9uIGNhbGxiYWNrIHByb21pc2UNCiAgICAgICAqLw0KICAgICAgZW50ZXI6IGZ1bmN0aW9uKGVsZW1lbnQsIHBhcmVudCwgYWZ0ZXIsIG9wdGlvbnMpIHsNCiAgICAgICAgYXBwbHlTdHlsZXMoZWxlbWVudCwgb3B0aW9ucyk7DQogICAgICAgIGFmdGVyID8gYWZ0ZXIuYWZ0ZXIoZWxlbWVudCkNCiAgICAgICAgICAgICAgOiBwYXJlbnQucHJlcGVuZChlbGVtZW50KTsNCiAgICAgICAgcmV0dXJuIGFzeW5jUHJvbWlzZSgpOw0KICAgICAgfSwNCg0KICAgICAgLyoqDQogICAgICAgKg0KICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICogQG5hbWUgJGFuaW1hdGUjbGVhdmUNCiAgICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICAgKiBAZGVzY3JpcHRpb24gUmVtb3ZlcyB0aGUgZWxlbWVudCBmcm9tIHRoZSBET00uIFdoZW4gdGhlIGZ1bmN0aW9uIGlzIGNhbGxlZCBhIHByb21pc2UNCiAgICAgICAqIGlzIHJldHVybmVkIHRoYXQgd2lsbCBiZSByZXNvbHZlZCBhdCBhIGxhdGVyIHRpbWUuDQogICAgICAgKiBAcGFyYW0ge0RPTUVsZW1lbnR9IGVsZW1lbnQgdGhlIGVsZW1lbnQgd2hpY2ggd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIERPTQ0KICAgICAgICogQHBhcmFtIHtvYmplY3Q9fSBvcHRpb25zIGFuIG9wdGlvbmFsIGNvbGxlY3Rpb24gb2Ygb3B0aW9ucyB0aGF0IHdpbGwgYmUgYXBwbGllZCB0byB0aGUgZWxlbWVudC4NCiAgICAgICAqIEByZXR1cm4ge1Byb21pc2V9IHRoZSBhbmltYXRpb24gY2FsbGJhY2sgcHJvbWlzZQ0KICAgICAgICovDQogICAgICBsZWF2ZTogZnVuY3Rpb24oZWxlbWVudCwgb3B0aW9ucykgew0KICAgICAgICBlbGVtZW50LnJlbW92ZSgpOw0KICAgICAgICByZXR1cm4gYXN5bmNQcm9taXNlKCk7DQogICAgICB9LA0KDQogICAgICAvKioNCiAgICAgICAqDQogICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgKiBAbmFtZSAkYW5pbWF0ZSNtb3ZlDQogICAgICAgKiBAa2luZCBmdW5jdGlvbg0KICAgICAgICogQGRlc2NyaXB0aW9uIE1vdmVzIHRoZSBwb3NpdGlvbiBvZiB0aGUgcHJvdmlkZWQgZWxlbWVudCB3aXRoaW4gdGhlIERPTSB0byBiZSBwbGFjZWQNCiAgICAgICAqIGVpdGhlciBhZnRlciB0aGUgYGFmdGVyYCBlbGVtZW50IG9yIGluc2lkZSBvZiB0aGUgYHBhcmVudGAgZWxlbWVudC4gV2hlbiB0aGUgZnVuY3Rpb24NCiAgICAgICAqIGlzIGNhbGxlZCBhIHByb21pc2UgaXMgcmV0dXJuZWQgdGhhdCB3aWxsIGJlIHJlc29sdmVkIGF0IGEgbGF0ZXIgdGltZS4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0ge0RPTUVsZW1lbnR9IGVsZW1lbnQgdGhlIGVsZW1lbnQgd2hpY2ggd2lsbCBiZSBtb3ZlZCBhcm91bmQgd2l0aGluIHRoZQ0KICAgICAgICogICBET00NCiAgICAgICAqIEBwYXJhbSB7RE9NRWxlbWVudH0gcGFyZW50IHRoZSBwYXJlbnQgZWxlbWVudCB3aGVyZSB0aGUgZWxlbWVudCB3aWxsIGJlDQogICAgICAgKiAgIGluc2VydGVkIGludG8gKGlmIHRoZSBhZnRlciBlbGVtZW50IGlzIG5vdCBwcmVzZW50KQ0KICAgICAgICogQHBhcmFtIHtET01FbGVtZW50fSBhZnRlciB0aGUgc2libGluZyBlbGVtZW50IHdoZXJlIHRoZSBlbGVtZW50IHdpbGwgYmUNCiAgICAgICAqICAgcG9zaXRpb25lZCBuZXh0IHRvDQogICAgICAgKiBAcGFyYW0ge29iamVjdD19IG9wdGlvbnMgYW4gb3B0aW9uYWwgY29sbGVjdGlvbiBvZiBvcHRpb25zIHRoYXQgd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBlbGVtZW50Lg0KICAgICAgICogQHJldHVybiB7UHJvbWlzZX0gdGhlIGFuaW1hdGlvbiBjYWxsYmFjayBwcm9taXNlDQogICAgICAgKi8NCiAgICAgIG1vdmU6IGZ1bmN0aW9uKGVsZW1lbnQsIHBhcmVudCwgYWZ0ZXIsIG9wdGlvbnMpIHsNCiAgICAgICAgLy8gRG8gbm90IHJlbW92ZSBlbGVtZW50IGJlZm9yZSBpbnNlcnQuIFJlbW92aW5nIHdpbGwgY2F1c2UgZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhlDQogICAgICAgIC8vIGVsZW1lbnQgdG8gYmUgZHJvcHBlZC4gSW5zZXJ0IHdpbGwgaW1wbGljaXRseSBkbyB0aGUgcmVtb3ZlLg0KICAgICAgICByZXR1cm4gdGhpcy5lbnRlcihlbGVtZW50LCBwYXJlbnQsIGFmdGVyLCBvcHRpb25zKTsNCiAgICAgIH0sDQoNCiAgICAgIC8qKg0KICAgICAgICoNCiAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAqIEBuYW1lICRhbmltYXRlI2FkZENsYXNzDQogICAgICAgKiBAa2luZCBmdW5jdGlvbg0KICAgICAgICogQGRlc2NyaXB0aW9uIEFkZHMgdGhlIHByb3ZpZGVkIGNsYXNzTmFtZSBDU1MgY2xhc3MgdmFsdWUgdG8gdGhlIHByb3ZpZGVkIGVsZW1lbnQuDQogICAgICAgKiBXaGVuIHRoZSBmdW5jdGlvbiBpcyBjYWxsZWQgYSBwcm9taXNlIGlzIHJldHVybmVkIHRoYXQgd2lsbCBiZSByZXNvbHZlZCBhdCBhIGxhdGVyIHRpbWUuDQogICAgICAgKiBAcGFyYW0ge0RPTUVsZW1lbnR9IGVsZW1lbnQgdGhlIGVsZW1lbnQgd2hpY2ggd2lsbCBoYXZlIHRoZSBjbGFzc05hbWUgdmFsdWUNCiAgICAgICAqICAgYWRkZWQgdG8gaXQNCiAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc05hbWUgdGhlIENTUyBjbGFzcyB3aGljaCB3aWxsIGJlIGFkZGVkIHRvIHRoZSBlbGVtZW50DQogICAgICAgKiBAcGFyYW0ge29iamVjdD19IG9wdGlvbnMgYW4gb3B0aW9uYWwgY29sbGVjdGlvbiBvZiBvcHRpb25zIHRoYXQgd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBlbGVtZW50Lg0KICAgICAgICogQHJldHVybiB7UHJvbWlzZX0gdGhlIGFuaW1hdGlvbiBjYWxsYmFjayBwcm9taXNlDQogICAgICAgKi8NCiAgICAgIGFkZENsYXNzOiBmdW5jdGlvbihlbGVtZW50LCBjbGFzc05hbWUsIG9wdGlvbnMpIHsNCiAgICAgICAgcmV0dXJuIHRoaXMuc2V0Q2xhc3MoZWxlbWVudCwgY2xhc3NOYW1lLCBbXSwgb3B0aW9ucyk7DQogICAgICB9LA0KDQogICAgICAkJGFkZENsYXNzSW1tZWRpYXRlbHk6IGZ1bmN0aW9uKGVsZW1lbnQsIGNsYXNzTmFtZSwgb3B0aW9ucykgew0KICAgICAgICBlbGVtZW50ID0ganFMaXRlKGVsZW1lbnQpOw0KICAgICAgICBjbGFzc05hbWUgPSAhaXNTdHJpbmcoY2xhc3NOYW1lKQ0KICAgICAgICAgICAgICAgICAgICAgICAgPyAoaXNBcnJheShjbGFzc05hbWUpID8gY2xhc3NOYW1lLmpvaW4oJyAnKSA6ICcnKQ0KICAgICAgICAgICAgICAgICAgICAgICAgOiBjbGFzc05hbWU7DQogICAgICAgIGZvckVhY2goZWxlbWVudCwgZnVuY3Rpb24oZWxlbWVudCkgew0KICAgICAgICAgIGpxTGl0ZUFkZENsYXNzKGVsZW1lbnQsIGNsYXNzTmFtZSk7DQogICAgICAgIH0pOw0KICAgICAgICBhcHBseVN0eWxlcyhlbGVtZW50LCBvcHRpb25zKTsNCiAgICAgICAgcmV0dXJuIGFzeW5jUHJvbWlzZSgpOw0KICAgICAgfSwNCg0KICAgICAgLyoqDQogICAgICAgKg0KICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICogQG5hbWUgJGFuaW1hdGUjcmVtb3ZlQ2xhc3MNCiAgICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICAgKiBAZGVzY3JpcHRpb24gUmVtb3ZlcyB0aGUgcHJvdmlkZWQgY2xhc3NOYW1lIENTUyBjbGFzcyB2YWx1ZSBmcm9tIHRoZSBwcm92aWRlZCBlbGVtZW50Lg0KICAgICAgICogV2hlbiB0aGUgZnVuY3Rpb24gaXMgY2FsbGVkIGEgcHJvbWlzZSBpcyByZXR1cm5lZCB0aGF0IHdpbGwgYmUgcmVzb2x2ZWQgYXQgYSBsYXRlciB0aW1lLg0KICAgICAgICogQHBhcmFtIHtET01FbGVtZW50fSBlbGVtZW50IHRoZSBlbGVtZW50IHdoaWNoIHdpbGwgaGF2ZSB0aGUgY2xhc3NOYW1lIHZhbHVlDQogICAgICAgKiAgIHJlbW92ZWQgZnJvbSBpdA0KICAgICAgICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzTmFtZSB0aGUgQ1NTIGNsYXNzIHdoaWNoIHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBlbGVtZW50DQogICAgICAgKiBAcGFyYW0ge29iamVjdD19IG9wdGlvbnMgYW4gb3B0aW9uYWwgY29sbGVjdGlvbiBvZiBvcHRpb25zIHRoYXQgd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBlbGVtZW50Lg0KICAgICAgICogQHJldHVybiB7UHJvbWlzZX0gdGhlIGFuaW1hdGlvbiBjYWxsYmFjayBwcm9taXNlDQogICAgICAgKi8NCiAgICAgIHJlbW92ZUNsYXNzOiBmdW5jdGlvbihlbGVtZW50LCBjbGFzc05hbWUsIG9wdGlvbnMpIHsNCiAgICAgICAgcmV0dXJuIHRoaXMuc2V0Q2xhc3MoZWxlbWVudCwgW10sIGNsYXNzTmFtZSwgb3B0aW9ucyk7DQogICAgICB9LA0KDQogICAgICAkJHJlbW92ZUNsYXNzSW1tZWRpYXRlbHk6IGZ1bmN0aW9uKGVsZW1lbnQsIGNsYXNzTmFtZSwgb3B0aW9ucykgew0KICAgICAgICBlbGVtZW50ID0ganFMaXRlKGVsZW1lbnQpOw0KICAgICAgICBjbGFzc05hbWUgPSAhaXNTdHJpbmcoY2xhc3NOYW1lKQ0KICAgICAgICAgICAgICAgICAgICAgICAgPyAoaXNBcnJheShjbGFzc05hbWUpID8gY2xhc3NOYW1lLmpvaW4oJyAnKSA6ICcnKQ0KICAgICAgICAgICAgICAgICAgICAgICAgOiBjbGFzc05hbWU7DQogICAgICAgIGZvckVhY2goZWxlbWVudCwgZnVuY3Rpb24oZWxlbWVudCkgew0KICAgICAgICAgIGpxTGl0ZVJlbW92ZUNsYXNzKGVsZW1lbnQsIGNsYXNzTmFtZSk7DQogICAgICAgIH0pOw0KICAgICAgICBhcHBseVN0eWxlcyhlbGVtZW50LCBvcHRpb25zKTsNCiAgICAgICAgcmV0dXJuIGFzeW5jUHJvbWlzZSgpOw0KICAgICAgfSwNCg0KICAgICAgLyoqDQogICAgICAgKg0KICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICogQG5hbWUgJGFuaW1hdGUjc2V0Q2xhc3MNCiAgICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICAgKiBAZGVzY3JpcHRpb24gQWRkcyBhbmQvb3IgcmVtb3ZlcyB0aGUgZ2l2ZW4gQ1NTIGNsYXNzZXMgdG8gYW5kIGZyb20gdGhlIGVsZW1lbnQuDQogICAgICAgKiBXaGVuIHRoZSBmdW5jdGlvbiBpcyBjYWxsZWQgYSBwcm9taXNlIGlzIHJldHVybmVkIHRoYXQgd2lsbCBiZSByZXNvbHZlZCBhdCBhIGxhdGVyIHRpbWUuDQogICAgICAgKiBAcGFyYW0ge0RPTUVsZW1lbnR9IGVsZW1lbnQgdGhlIGVsZW1lbnQgd2hpY2ggd2lsbCBoYXZlIGl0cyBDU1MgY2xhc3NlcyBjaGFuZ2VkDQogICAgICAgKiAgIHJlbW92ZWQgZnJvbSBpdA0KICAgICAgICogQHBhcmFtIHtzdHJpbmd9IGFkZCB0aGUgQ1NTIGNsYXNzZXMgd2hpY2ggd2lsbCBiZSBhZGRlZCB0byB0aGUgZWxlbWVudA0KICAgICAgICogQHBhcmFtIHtzdHJpbmd9IHJlbW92ZSB0aGUgQ1NTIGNsYXNzIHdoaWNoIHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBlbGVtZW50DQogICAgICAgKiBAcGFyYW0ge29iamVjdD19IG9wdGlvbnMgYW4gb3B0aW9uYWwgY29sbGVjdGlvbiBvZiBvcHRpb25zIHRoYXQgd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBlbGVtZW50Lg0KICAgICAgICogQHJldHVybiB7UHJvbWlzZX0gdGhlIGFuaW1hdGlvbiBjYWxsYmFjayBwcm9taXNlDQogICAgICAgKi8NCiAgICAgIHNldENsYXNzOiBmdW5jdGlvbihlbGVtZW50LCBhZGQsIHJlbW92ZSwgb3B0aW9ucykgew0KICAgICAgICB2YXIgc2VsZiA9IHRoaXM7DQogICAgICAgIHZhciBTVE9SQUdFX0tFWSA9ICckJGFuaW1hdGVDbGFzc2VzJzsNCiAgICAgICAgdmFyIGNyZWF0ZWRDYWNoZSA9IGZhbHNlOw0KICAgICAgICBlbGVtZW50ID0ganFMaXRlKGVsZW1lbnQpOw0KDQogICAgICAgIHZhciBjYWNoZSA9IGVsZW1lbnQuZGF0YShTVE9SQUdFX0tFWSk7DQogICAgICAgIGlmICghY2FjaGUpIHsNCiAgICAgICAgICBjYWNoZSA9IHsNCiAgICAgICAgICAgIGNsYXNzZXM6IHt9LA0KICAgICAgICAgICAgb3B0aW9uczogb3B0aW9ucw0KICAgICAgICAgIH07DQogICAgICAgICAgY3JlYXRlZENhY2hlID0gdHJ1ZTsNCiAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zICYmIGNhY2hlLm9wdGlvbnMpIHsNCiAgICAgICAgICBjYWNoZS5vcHRpb25zID0gYW5ndWxhci5leHRlbmQoY2FjaGUub3B0aW9ucyB8fCB7fSwgb3B0aW9ucyk7DQogICAgICAgIH0NCg0KICAgICAgICB2YXIgY2xhc3NlcyA9IGNhY2hlLmNsYXNzZXM7DQoNCiAgICAgICAgYWRkID0gaXNBcnJheShhZGQpID8gYWRkIDogYWRkLnNwbGl0KCcgJyk7DQogICAgICAgIHJlbW92ZSA9IGlzQXJyYXkocmVtb3ZlKSA/IHJlbW92ZSA6IHJlbW92ZS5zcGxpdCgnICcpOw0KICAgICAgICBjYWNoZWRDbGFzc01hbmlwdWxhdGlvbihjbGFzc2VzLCBhZGQsIHRydWUpOw0KICAgICAgICBjYWNoZWRDbGFzc01hbmlwdWxhdGlvbihjbGFzc2VzLCByZW1vdmUsIGZhbHNlKTsNCg0KICAgICAgICBpZiAoY3JlYXRlZENhY2hlKSB7DQogICAgICAgICAgY2FjaGUucHJvbWlzZSA9IHJ1bkFuaW1hdGlvblBvc3REaWdlc3QoZnVuY3Rpb24oZG9uZSkgew0KICAgICAgICAgICAgdmFyIGNhY2hlID0gZWxlbWVudC5kYXRhKFNUT1JBR0VfS0VZKTsNCiAgICAgICAgICAgIGVsZW1lbnQucmVtb3ZlRGF0YShTVE9SQUdFX0tFWSk7DQoNCiAgICAgICAgICAgIC8vIGluIHRoZSBldmVudCB0aGF0IHRoZSBlbGVtZW50IGlzIHJlbW92ZWQgYmVmb3JlIHBvc3REaWdlc3QNCiAgICAgICAgICAgIC8vIGlzIHJ1biB0aGVuIHRoZSBjYWNoZSB3aWxsIGJlIHVuZGVmaW5lZCBhbmQgdGhlcmUgd2lsbCBiZQ0KICAgICAgICAgICAgLy8gbm8gbmVlZCBhbnltb3JlIHRvIGFkZCBvciByZW1vdmUgYW5kIG9mIHRoZSBlbGVtZW50IGNsYXNzZXMNCiAgICAgICAgICAgIGlmIChjYWNoZSkgew0KICAgICAgICAgICAgICB2YXIgY2xhc3NlcyA9IHJlc29sdmVFbGVtZW50Q2xhc3NlcyhlbGVtZW50LCBjYWNoZS5jbGFzc2VzKTsNCiAgICAgICAgICAgICAgaWYgKGNsYXNzZXMpIHsNCiAgICAgICAgICAgICAgICBzZWxmLiQkc2V0Q2xhc3NJbW1lZGlhdGVseShlbGVtZW50LCBjbGFzc2VzWzBdLCBjbGFzc2VzWzFdLCBjYWNoZS5vcHRpb25zKTsNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBkb25lKCk7DQogICAgICAgICAgfSk7DQogICAgICAgICAgZWxlbWVudC5kYXRhKFNUT1JBR0VfS0VZLCBjYWNoZSk7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gY2FjaGUucHJvbWlzZTsNCiAgICAgIH0sDQoNCiAgICAgICQkc2V0Q2xhc3NJbW1lZGlhdGVseTogZnVuY3Rpb24oZWxlbWVudCwgYWRkLCByZW1vdmUsIG9wdGlvbnMpIHsNCiAgICAgICAgYWRkICYmIHRoaXMuJCRhZGRDbGFzc0ltbWVkaWF0ZWx5KGVsZW1lbnQsIGFkZCk7DQogICAgICAgIHJlbW92ZSAmJiB0aGlzLiQkcmVtb3ZlQ2xhc3NJbW1lZGlhdGVseShlbGVtZW50LCByZW1vdmUpOw0KICAgICAgICBhcHBseVN0eWxlcyhlbGVtZW50LCBvcHRpb25zKTsNCiAgICAgICAgcmV0dXJuIGFzeW5jUHJvbWlzZSgpOw0KICAgICAgfSwNCg0KICAgICAgZW5hYmxlZDogbm9vcCwNCiAgICAgIGNhbmNlbDogbm9vcA0KICAgIH07DQogIH1dOw0KfV07DQoNCmZ1bmN0aW9uICQkQXN5bmNDYWxsYmFja1Byb3ZpZGVyKCkgew0KICB0aGlzLiRnZXQgPSBbJyQkckFGJywgJyR0aW1lb3V0JywgZnVuY3Rpb24oJCRyQUYsICR0aW1lb3V0KSB7DQogICAgcmV0dXJuICQkckFGLnN1cHBvcnRlZA0KICAgICAgPyBmdW5jdGlvbihmbikgeyByZXR1cm4gJCRyQUYoZm4pOyB9DQogICAgICA6IGZ1bmN0aW9uKGZuKSB7DQogICAgICAgIHJldHVybiAkdGltZW91dChmbiwgMCwgZmFsc2UpOw0KICAgICAgfTsNCiAgfV07DQp9DQoNCi8qIGdsb2JhbCBzdHJpcEhhc2g6IHRydWUgKi8NCg0KLyoqDQogKiAhIFRoaXMgaXMgYSBwcml2YXRlIHVuZG9jdW1lbnRlZCBzZXJ2aWNlICENCiAqDQogKiBAbmFtZSAkYnJvd3Nlcg0KICogQHJlcXVpcmVzICRsb2cNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhpcyBvYmplY3QgaGFzIHR3byBnb2FsczoNCiAqDQogKiAtIGhpZGUgYWxsIHRoZSBnbG9iYWwgc3RhdGUgaW4gdGhlIGJyb3dzZXIgY2F1c2VkIGJ5IHRoZSB3aW5kb3cgb2JqZWN0DQogKiAtIGFic3RyYWN0IGF3YXkgYWxsIHRoZSBicm93c2VyIHNwZWNpZmljIGZlYXR1cmVzIGFuZCBpbmNvbnNpc3RlbmNpZXMNCiAqDQogKiBGb3IgdGVzdHMgd2UgcHJvdmlkZSB7QGxpbmsgbmdNb2NrLiRicm93c2VyIG1vY2sgaW1wbGVtZW50YXRpb259IG9mIHRoZSBgJGJyb3dzZXJgDQogKiBzZXJ2aWNlLCB3aGljaCBjYW4gYmUgdXNlZCBmb3IgY29udmVuaWVudCB0ZXN0aW5nIG9mIHRoZSBhcHBsaWNhdGlvbiB3aXRob3V0IHRoZSBpbnRlcmFjdGlvbiB3aXRoDQogKiB0aGUgcmVhbCBicm93c2VyIGFwaXMuDQogKi8NCi8qKg0KICogQHBhcmFtIHtvYmplY3R9IHdpbmRvdyBUaGUgZ2xvYmFsIHdpbmRvdyBvYmplY3QuDQogKiBAcGFyYW0ge29iamVjdH0gZG9jdW1lbnQgalF1ZXJ5IHdyYXBwZWQgZG9jdW1lbnQuDQogKiBAcGFyYW0ge29iamVjdH0gJGxvZyB3aW5kb3cuY29uc29sZSBvciBhbiBvYmplY3Qgd2l0aCB0aGUgc2FtZSBpbnRlcmZhY2UuDQogKiBAcGFyYW0ge29iamVjdH0gJHNuaWZmZXIgJHNuaWZmZXIgc2VydmljZQ0KICovDQpmdW5jdGlvbiBCcm93c2VyKHdpbmRvdywgZG9jdW1lbnQsICRsb2csICRzbmlmZmVyKSB7DQogIHZhciBzZWxmID0gdGhpcywNCiAgICAgIHJhd0RvY3VtZW50ID0gZG9jdW1lbnRbMF0sDQogICAgICBsb2NhdGlvbiA9IHdpbmRvdy5sb2NhdGlvbiwNCiAgICAgIGhpc3RvcnkgPSB3aW5kb3cuaGlzdG9yeSwNCiAgICAgIHNldFRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dCwNCiAgICAgIGNsZWFyVGltZW91dCA9IHdpbmRvdy5jbGVhclRpbWVvdXQsDQogICAgICBwZW5kaW5nRGVmZXJJZHMgPSB7fTsNCg0KICBzZWxmLmlzTW9jayA9IGZhbHNlOw0KDQogIHZhciBvdXRzdGFuZGluZ1JlcXVlc3RDb3VudCA9IDA7DQogIHZhciBvdXRzdGFuZGluZ1JlcXVlc3RDYWxsYmFja3MgPSBbXTsNCg0KICAvLyBUT0RPKHZvanRhKTogcmVtb3ZlIHRoaXMgdGVtcG9yYXJ5IGFwaQ0KICBzZWxmLiQkY29tcGxldGVPdXRzdGFuZGluZ1JlcXVlc3QgPSBjb21wbGV0ZU91dHN0YW5kaW5nUmVxdWVzdDsNCiAgc2VsZi4kJGluY091dHN0YW5kaW5nUmVxdWVzdENvdW50ID0gZnVuY3Rpb24oKSB7IG91dHN0YW5kaW5nUmVxdWVzdENvdW50Kys7IH07DQoNCiAgLyoqDQogICAqIEV4ZWN1dGVzIHRoZSBgZm5gIGZ1bmN0aW9uKHN1cHBvcnRzIGN1cnJ5aW5nKSBhbmQgZGVjcmVtZW50cyB0aGUgYG91dHN0YW5kaW5nUmVxdWVzdENhbGxiYWNrc2ANCiAgICogY291bnRlci4gSWYgdGhlIGNvdW50ZXIgcmVhY2hlcyAwLCBhbGwgdGhlIGBvdXRzdGFuZGluZ1JlcXVlc3RDYWxsYmFja3NgIGFyZSBleGVjdXRlZC4NCiAgICovDQogIGZ1bmN0aW9uIGNvbXBsZXRlT3V0c3RhbmRpbmdSZXF1ZXN0KGZuKSB7DQogICAgdHJ5IHsNCiAgICAgIGZuLmFwcGx5KG51bGwsIHNsaWNlQXJncyhhcmd1bWVudHMsIDEpKTsNCiAgICB9IGZpbmFsbHkgew0KICAgICAgb3V0c3RhbmRpbmdSZXF1ZXN0Q291bnQtLTsNCiAgICAgIGlmIChvdXRzdGFuZGluZ1JlcXVlc3RDb3VudCA9PT0gMCkgew0KICAgICAgICB3aGlsZSAob3V0c3RhbmRpbmdSZXF1ZXN0Q2FsbGJhY2tzLmxlbmd0aCkgew0KICAgICAgICAgIHRyeSB7DQogICAgICAgICAgICBvdXRzdGFuZGluZ1JlcXVlc3RDYWxsYmFja3MucG9wKCkoKTsNCiAgICAgICAgICB9IGNhdGNoIChlKSB7DQogICAgICAgICAgICAkbG9nLmVycm9yKGUpOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgfQ0KICAgIH0NCiAgfQ0KDQogIGZ1bmN0aW9uIGdldEhhc2godXJsKSB7DQogICAgdmFyIGluZGV4ID0gdXJsLmluZGV4T2YoJyMnKTsNCiAgICByZXR1cm4gaW5kZXggPT09IC0xID8gJycgOiB1cmwuc3Vic3RyKGluZGV4ICsgMSk7DQogIH0NCg0KICAvKioNCiAgICogQHByaXZhdGUNCiAgICogTm90ZTogdGhpcyBtZXRob2QgaXMgdXNlZCBvbmx5IGJ5IHNjZW5hcmlvIHJ1bm5lcg0KICAgKiBUT0RPKHZvanRhKTogcHJlZml4IHRoaXMgbWV0aG9kIHdpdGggJCQgPw0KICAgKiBAcGFyYW0ge2Z1bmN0aW9uKCl9IGNhbGxiYWNrIEZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBjYWxsZWQgd2hlbiBubyBvdXRzdGFuZGluZyByZXF1ZXN0DQogICAqLw0KICBzZWxmLm5vdGlmeVdoZW5Ob091dHN0YW5kaW5nUmVxdWVzdHMgPSBmdW5jdGlvbihjYWxsYmFjaykgew0KICAgIC8vIGZvcmNlIGJyb3dzZXIgdG8gZXhlY3V0ZSBhbGwgcG9sbEZucyAtIHRoaXMgaXMgbmVlZGVkIHNvIHRoYXQgY29va2llcyBhbmQgb3RoZXIgcG9sbGVycyBmaXJlDQogICAgLy8gYXQgc29tZSBkZXRlcm1pbmlzdGljIHRpbWUgaW4gcmVzcGVjdCB0byB0aGUgdGVzdCBydW5uZXIncyBhY3Rpb25zLiBMZWF2aW5nIHRoaW5ncyB1cCB0byB0aGUNCiAgICAvLyByZWd1bGFyIHBvbGxlciB3b3VsZCByZXN1bHQgaW4gZmxha3kgdGVzdHMuDQogICAgZm9yRWFjaChwb2xsRm5zLCBmdW5jdGlvbihwb2xsRm4pIHsgcG9sbEZuKCk7IH0pOw0KDQogICAgaWYgKG91dHN0YW5kaW5nUmVxdWVzdENvdW50ID09PSAwKSB7DQogICAgICBjYWxsYmFjaygpOw0KICAgIH0gZWxzZSB7DQogICAgICBvdXRzdGFuZGluZ1JlcXVlc3RDYWxsYmFja3MucHVzaChjYWxsYmFjayk7DQogICAgfQ0KICB9Ow0KDQogIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vDQogIC8vIFBvbGwgV2F0Y2hlciBBUEkNCiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCiAgdmFyIHBvbGxGbnMgPSBbXSwNCiAgICAgIHBvbGxUaW1lb3V0Ow0KDQogIC8qKg0KICAgKiBAbmFtZSAkYnJvd3NlciNhZGRQb2xsRm4NCiAgICoNCiAgICogQHBhcmFtIHtmdW5jdGlvbigpfSBmbiBQb2xsIGZ1bmN0aW9uIHRvIGFkZA0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogQWRkcyBhIGZ1bmN0aW9uIHRvIHRoZSBsaXN0IG9mIGZ1bmN0aW9ucyB0aGF0IHBvbGxlciBwZXJpb2RpY2FsbHkgZXhlY3V0ZXMsDQogICAqIGFuZCBzdGFydHMgcG9sbGluZyBpZiBub3Qgc3RhcnRlZCB5ZXQuDQogICAqDQogICAqIEByZXR1cm5zIHtmdW5jdGlvbigpfSB0aGUgYWRkZWQgZnVuY3Rpb24NCiAgICovDQogIHNlbGYuYWRkUG9sbEZuID0gZnVuY3Rpb24oZm4pIHsNCiAgICBpZiAoaXNVbmRlZmluZWQocG9sbFRpbWVvdXQpKSBzdGFydFBvbGxlcigxMDAsIHNldFRpbWVvdXQpOw0KICAgIHBvbGxGbnMucHVzaChmbik7DQogICAgcmV0dXJuIGZuOw0KICB9Ow0KDQogIC8qKg0KICAgKiBAcGFyYW0ge251bWJlcn0gaW50ZXJ2YWwgSG93IG9mdGVuIHNob3VsZCBicm93c2VyIGNhbGwgcG9sbCBmdW5jdGlvbnMgKG1zKQ0KICAgKiBAcGFyYW0ge2Z1bmN0aW9uKCl9IHNldFRpbWVvdXQgUmVmZXJlbmNlIHRvIGEgcmVhbCBvciBmYWtlIGBzZXRUaW1lb3V0YCBmdW5jdGlvbi4NCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIENvbmZpZ3VyZXMgdGhlIHBvbGxlciB0byBydW4gaW4gdGhlIHNwZWNpZmllZCBpbnRlcnZhbHMsIHVzaW5nIHRoZSBzcGVjaWZpZWQNCiAgICogc2V0VGltZW91dCBmbiBhbmQga2lja3MgaXQgb2ZmLg0KICAgKi8NCiAgZnVuY3Rpb24gc3RhcnRQb2xsZXIoaW50ZXJ2YWwsIHNldFRpbWVvdXQpIHsNCiAgICAoZnVuY3Rpb24gY2hlY2soKSB7DQogICAgICBmb3JFYWNoKHBvbGxGbnMsIGZ1bmN0aW9uKHBvbGxGbikgeyBwb2xsRm4oKTsgfSk7DQogICAgICBwb2xsVGltZW91dCA9IHNldFRpbWVvdXQoY2hlY2ssIGludGVydmFsKTsNCiAgICB9KSgpOw0KICB9DQoNCiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCiAgLy8gVVJMIEFQSQ0KICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KDQogIHZhciBjYWNoZWRTdGF0ZSwgbGFzdEhpc3RvcnlTdGF0ZSwNCiAgICAgIGxhc3RCcm93c2VyVXJsID0gbG9jYXRpb24uaHJlZiwNCiAgICAgIGJhc2VFbGVtZW50ID0gZG9jdW1lbnQuZmluZCgnYmFzZScpLA0KICAgICAgcmVsb2FkTG9jYXRpb24gPSBudWxsOw0KDQogIGNhY2hlU3RhdGUoKTsNCiAgbGFzdEhpc3RvcnlTdGF0ZSA9IGNhY2hlZFN0YXRlOw0KDQogIC8qKg0KICAgKiBAbmFtZSAkYnJvd3NlciN1cmwNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIEdFVFRFUjoNCiAgICogV2l0aG91dCBhbnkgYXJndW1lbnQsIHRoaXMgbWV0aG9kIGp1c3QgcmV0dXJucyBjdXJyZW50IHZhbHVlIG9mIGxvY2F0aW9uLmhyZWYuDQogICAqDQogICAqIFNFVFRFUjoNCiAgICogV2l0aCBhdCBsZWFzdCBvbmUgYXJndW1lbnQsIHRoaXMgbWV0aG9kIHNldHMgdXJsIHRvIG5ldyB2YWx1ZS4NCiAgICogSWYgaHRtbDUgaGlzdG9yeSBhcGkgc3VwcG9ydGVkLCBwdXNoU3RhdGUvcmVwbGFjZVN0YXRlIGlzIHVzZWQsIG90aGVyd2lzZQ0KICAgKiBsb2NhdGlvbi5ocmVmL2xvY2F0aW9uLnJlcGxhY2UgaXMgdXNlZC4NCiAgICogUmV0dXJucyBpdHMgb3duIGluc3RhbmNlIHRvIGFsbG93IGNoYWluaW5nDQogICAqDQogICAqIE5PVEU6IHRoaXMgYXBpIGlzIGludGVuZGVkIGZvciB1c2Ugb25seSBieSB0aGUgJGxvY2F0aW9uIHNlcnZpY2UuIFBsZWFzZSB1c2UgdGhlDQogICAqIHtAbGluayBuZy4kbG9jYXRpb24gJGxvY2F0aW9uIHNlcnZpY2V9IHRvIGNoYW5nZSB1cmwuDQogICAqDQogICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgTmV3IHVybCAod2hlbiB1c2VkIGFzIHNldHRlcikNCiAgICogQHBhcmFtIHtib29sZWFuPX0gcmVwbGFjZSBTaG91bGQgbmV3IHVybCByZXBsYWNlIGN1cnJlbnQgaGlzdG9yeSByZWNvcmQ/DQogICAqIEBwYXJhbSB7b2JqZWN0PX0gc3RhdGUgb2JqZWN0IHRvIHVzZSB3aXRoIHB1c2hTdGF0ZS9yZXBsYWNlU3RhdGUNCiAgICovDQogIHNlbGYudXJsID0gZnVuY3Rpb24odXJsLCByZXBsYWNlLCBzdGF0ZSkgew0KICAgIC8vIEluIG1vZGVybiBicm93c2VycyBgaGlzdG9yeS5zdGF0ZWAgaXMgYG51bGxgIGJ5IGRlZmF1bHQ7IHRyZWF0aW5nIGl0IHNlcGFyYXRlbHkNCiAgICAvLyBmcm9tIGB1bmRlZmluZWRgIHdvdWxkIGNhdXNlIGAkYnJvd3Nlci51cmwoJy9mb28nKWAgdG8gY2hhbmdlIGBoaXN0b3J5LnN0YXRlYA0KICAgIC8vIHRvIHVuZGVmaW5lZCB2aWEgYHB1c2hTdGF0ZWAuIEluc3RlYWQsIGxldCdzIGNoYW5nZSBgdW5kZWZpbmVkYCB0byBgbnVsbGAgaGVyZS4NCiAgICBpZiAoaXNVbmRlZmluZWQoc3RhdGUpKSB7DQogICAgICBzdGF0ZSA9IG51bGw7DQogICAgfQ0KDQogICAgLy8gQW5kcm9pZCBCcm93c2VyIEJGQ2FjaGUgY2F1c2VzIGxvY2F0aW9uLCBoaXN0b3J5IHJlZmVyZW5jZSB0byBiZWNvbWUgc3RhbGUuDQogICAgaWYgKGxvY2F0aW9uICE9PSB3aW5kb3cubG9jYXRpb24pIGxvY2F0aW9uID0gd2luZG93LmxvY2F0aW9uOw0KICAgIGlmIChoaXN0b3J5ICE9PSB3aW5kb3cuaGlzdG9yeSkgaGlzdG9yeSA9IHdpbmRvdy5oaXN0b3J5Ow0KDQogICAgLy8gc2V0dGVyDQogICAgaWYgKHVybCkgew0KICAgICAgdmFyIHNhbWVTdGF0ZSA9IGxhc3RIaXN0b3J5U3RhdGUgPT09IHN0YXRlOw0KDQogICAgICAvLyBEb24ndCBjaGFuZ2UgYW55dGhpbmcgaWYgcHJldmlvdXMgYW5kIGN1cnJlbnQgVVJMcyBhbmQgc3RhdGVzIG1hdGNoLiBUaGlzIGFsc28gcHJldmVudHMNCiAgICAgIC8vIElFPDEwIGZyb20gZ2V0dGluZyBpbnRvIHJlZGlyZWN0IGxvb3Agd2hlbiBpbiBMb2NhdGlvbkhhc2hiYW5nSW5IdG1sNVVybCBtb2RlLg0KICAgICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIuanMvY29tbWl0L2ZmYjI3MDENCiAgICAgIGlmIChsYXN0QnJvd3NlclVybCA9PT0gdXJsICYmICghJHNuaWZmZXIuaGlzdG9yeSB8fCBzYW1lU3RhdGUpKSB7DQogICAgICAgIHJldHVybiBzZWxmOw0KICAgICAgfQ0KICAgICAgdmFyIHNhbWVCYXNlID0gbGFzdEJyb3dzZXJVcmwgJiYgc3RyaXBIYXNoKGxhc3RCcm93c2VyVXJsKSA9PT0gc3RyaXBIYXNoKHVybCk7DQogICAgICBsYXN0QnJvd3NlclVybCA9IHVybDsNCiAgICAgIGxhc3RIaXN0b3J5U3RhdGUgPSBzdGF0ZTsNCiAgICAgIC8vIERvbid0IHVzZSBoaXN0b3J5IEFQSSBpZiBvbmx5IHRoZSBoYXNoIGNoYW5nZWQNCiAgICAgIC8vIGR1ZSB0byBhIGJ1ZyBpbiBJRTEwL0lFMTEgd2hpY2ggbGVhZHMNCiAgICAgIC8vIHRvIG5vdCBmaXJpbmcgYSBgaGFzaGNoYW5nZWAgbm9yIGBwb3BzdGF0ZWAgZXZlbnQNCiAgICAgIC8vIGluIHNvbWUgY2FzZXMgKHNlZSAjOTE0MykuDQogICAgICBpZiAoJHNuaWZmZXIuaGlzdG9yeSAmJiAoIXNhbWVCYXNlIHx8ICFzYW1lU3RhdGUpKSB7DQogICAgICAgIGhpc3RvcnlbcmVwbGFjZSA/ICdyZXBsYWNlU3RhdGUnIDogJ3B1c2hTdGF0ZSddKHN0YXRlLCAnJywgdXJsKTsNCiAgICAgICAgY2FjaGVTdGF0ZSgpOw0KICAgICAgICAvLyBEbyB0aGUgYXNzaWdubWVudCBhZ2FpbiBzbyB0aGF0IHRob3NlIHR3byB2YXJpYWJsZXMgYXJlIHJlZmVyZW50aWFsbHkgaWRlbnRpY2FsLg0KICAgICAgICBsYXN0SGlzdG9yeVN0YXRlID0gY2FjaGVkU3RhdGU7DQogICAgICB9IGVsc2Ugew0KICAgICAgICBpZiAoIXNhbWVCYXNlKSB7DQogICAgICAgICAgcmVsb2FkTG9jYXRpb24gPSB1cmw7DQogICAgICAgIH0NCiAgICAgICAgaWYgKHJlcGxhY2UpIHsNCiAgICAgICAgICBsb2NhdGlvbi5yZXBsYWNlKHVybCk7DQogICAgICAgIH0gZWxzZSBpZiAoIXNhbWVCYXNlKSB7DQogICAgICAgICAgbG9jYXRpb24uaHJlZiA9IHVybDsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBsb2NhdGlvbi5oYXNoID0gZ2V0SGFzaCh1cmwpOw0KICAgICAgICB9DQogICAgICB9DQogICAgICByZXR1cm4gc2VsZjsNCiAgICAvLyBnZXR0ZXINCiAgICB9IGVsc2Ugew0KICAgICAgLy8gLSByZWxvYWRMb2NhdGlvbiBpcyBuZWVkZWQgYXMgYnJvd3NlcnMgZG9uJ3QgYWxsb3cgdG8gcmVhZCBvdXQNCiAgICAgIC8vICAgdGhlIG5ldyBsb2NhdGlvbi5ocmVmIGlmIGEgcmVsb2FkIGhhcHBlbmVkLg0KICAgICAgLy8gLSB0aGUgcmVwbGFjZW1lbnQgaXMgYSB3b3JrYXJvdW5kIGZvciBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD00MDcxNzINCiAgICAgIHJldHVybiByZWxvYWRMb2NhdGlvbiB8fCBsb2NhdGlvbi5ocmVmLnJlcGxhY2UoLyUyNy9nLCInIik7DQogICAgfQ0KICB9Ow0KDQogIC8qKg0KICAgKiBAbmFtZSAkYnJvd3NlciNzdGF0ZQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogVGhpcyBtZXRob2QgaXMgYSBnZXR0ZXIuDQogICAqDQogICAqIFJldHVybiBoaXN0b3J5LnN0YXRlIG9yIG51bGwgaWYgaGlzdG9yeS5zdGF0ZSBpcyB1bmRlZmluZWQuDQogICAqDQogICAqIEByZXR1cm5zIHtvYmplY3R9IHN0YXRlDQogICAqLw0KICBzZWxmLnN0YXRlID0gZnVuY3Rpb24oKSB7DQogICAgcmV0dXJuIGNhY2hlZFN0YXRlOw0KICB9Ow0KDQogIHZhciB1cmxDaGFuZ2VMaXN0ZW5lcnMgPSBbXSwNCiAgICAgIHVybENoYW5nZUluaXQgPSBmYWxzZTsNCg0KICBmdW5jdGlvbiBjYWNoZVN0YXRlQW5kRmlyZVVybENoYW5nZSgpIHsNCiAgICBjYWNoZVN0YXRlKCk7DQogICAgZmlyZVVybENoYW5nZSgpOw0KICB9DQoNCiAgLy8gVGhpcyB2YXJpYWJsZSBzaG91bGQgYmUgdXNlZCAqb25seSogaW5zaWRlIHRoZSBjYWNoZVN0YXRlIGZ1bmN0aW9uLg0KICB2YXIgbGFzdENhY2hlZFN0YXRlID0gbnVsbDsNCiAgZnVuY3Rpb24gY2FjaGVTdGF0ZSgpIHsNCiAgICAvLyBUaGlzIHNob3VsZCBiZSB0aGUgb25seSBwbGFjZSBpbiAkYnJvd3NlciB3aGVyZSBgaGlzdG9yeS5zdGF0ZWAgaXMgcmVhZC4NCiAgICBjYWNoZWRTdGF0ZSA9IHdpbmRvdy5oaXN0b3J5LnN0YXRlOw0KICAgIGNhY2hlZFN0YXRlID0gaXNVbmRlZmluZWQoY2FjaGVkU3RhdGUpID8gbnVsbCA6IGNhY2hlZFN0YXRlOw0KDQogICAgLy8gUHJldmVudCBjYWxsYmFja3MgZm8gZmlyZSB0d2ljZSBpZiBib3RoIGhhc2hjaGFuZ2UgJiBwb3BzdGF0ZSB3ZXJlIGZpcmVkLg0KICAgIGlmIChlcXVhbHMoY2FjaGVkU3RhdGUsIGxhc3RDYWNoZWRTdGF0ZSkpIHsNCiAgICAgIGNhY2hlZFN0YXRlID0gbGFzdENhY2hlZFN0YXRlOw0KICAgIH0NCiAgICBsYXN0Q2FjaGVkU3RhdGUgPSBjYWNoZWRTdGF0ZTsNCiAgfQ0KDQogIGZ1bmN0aW9uIGZpcmVVcmxDaGFuZ2UoKSB7DQogICAgaWYgKGxhc3RCcm93c2VyVXJsID09PSBzZWxmLnVybCgpICYmIGxhc3RIaXN0b3J5U3RhdGUgPT09IGNhY2hlZFN0YXRlKSB7DQogICAgICByZXR1cm47DQogICAgfQ0KDQogICAgbGFzdEJyb3dzZXJVcmwgPSBzZWxmLnVybCgpOw0KICAgIGxhc3RIaXN0b3J5U3RhdGUgPSBjYWNoZWRTdGF0ZTsNCiAgICBmb3JFYWNoKHVybENoYW5nZUxpc3RlbmVycywgZnVuY3Rpb24obGlzdGVuZXIpIHsNCiAgICAgIGxpc3RlbmVyKHNlbGYudXJsKCksIGNhY2hlZFN0YXRlKTsNCiAgICB9KTsNCiAgfQ0KDQogIC8qKg0KICAgKiBAbmFtZSAkYnJvd3NlciNvblVybENoYW5nZQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogUmVnaXN0ZXIgY2FsbGJhY2sgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGNhbGxlZCwgd2hlbiB1cmwgY2hhbmdlcy4NCiAgICoNCiAgICogSXQncyBvbmx5IGNhbGxlZCB3aGVuIHRoZSB1cmwgaXMgY2hhbmdlZCBmcm9tIG91dHNpZGUgb2YgYW5ndWxhcjoNCiAgICogLSB1c2VyIHR5cGVzIGRpZmZlcmVudCB1cmwgaW50byBhZGRyZXNzIGJhcg0KICAgKiAtIHVzZXIgY2xpY2tzIG9uIGhpc3RvcnkgKGZvcndhcmQvYmFjaykgYnV0dG9uDQogICAqIC0gdXNlciBjbGlja3Mgb24gYSBsaW5rDQogICAqDQogICAqIEl0J3Mgbm90IGNhbGxlZCB3aGVuIHVybCBpcyBjaGFuZ2VkIGJ5ICRicm93c2VyLnVybCgpIG1ldGhvZA0KICAgKg0KICAgKiBUaGUgbGlzdGVuZXIgZ2V0cyBjYWxsZWQgd2l0aCBuZXcgdXJsIGFzIHBhcmFtZXRlci4NCiAgICoNCiAgICogTk9URTogdGhpcyBhcGkgaXMgaW50ZW5kZWQgZm9yIHVzZSBvbmx5IGJ5IHRoZSAkbG9jYXRpb24gc2VydmljZS4gUGxlYXNlIHVzZSB0aGUNCiAgICoge0BsaW5rIG5nLiRsb2NhdGlvbiAkbG9jYXRpb24gc2VydmljZX0gdG8gbW9uaXRvciB1cmwgY2hhbmdlcyBpbiBhbmd1bGFyIGFwcHMuDQogICAqDQogICAqIEBwYXJhbSB7ZnVuY3Rpb24oc3RyaW5nKX0gbGlzdGVuZXIgTGlzdGVuZXIgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdXJsIGNoYW5nZXMuDQogICAqIEByZXR1cm4ge2Z1bmN0aW9uKHN0cmluZyl9IFJldHVybnMgdGhlIHJlZ2lzdGVyZWQgbGlzdGVuZXIgZm4gLSBoYW5keSBpZiB0aGUgZm4gaXMgYW5vbnltb3VzLg0KICAgKi8NCiAgc2VsZi5vblVybENoYW5nZSA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7DQogICAgLy8gVE9ETyh2b2p0YSk6IHJlZmFjdG9yIHRvIHVzZSBub2RlJ3Mgc3ludGF4IGZvciBldmVudHMNCiAgICBpZiAoIXVybENoYW5nZUluaXQpIHsNCiAgICAgIC8vIFdlIGxpc3RlbiBvbiBib3RoIChoYXNoY2hhbmdlL3BvcHN0YXRlKSB3aGVuIGF2YWlsYWJsZSwgYXMgc29tZSBicm93c2VycyAoZS5nLiBPcGVyYSkNCiAgICAgIC8vIGRvbid0IGZpcmUgcG9wc3RhdGUgd2hlbiB1c2VyIGNoYW5nZSB0aGUgYWRkcmVzcyBiYXIgYW5kIGRvbid0IGZpcmUgaGFzaGNoYW5nZSB3aGVuIHVybA0KICAgICAgLy8gY2hhbmdlZCBieSBwdXNoL3JlcGxhY2VTdGF0ZQ0KDQogICAgICAvLyBodG1sNSBoaXN0b3J5IGFwaSAtIHBvcHN0YXRlIGV2ZW50DQogICAgICBpZiAoJHNuaWZmZXIuaGlzdG9yeSkganFMaXRlKHdpbmRvdykub24oJ3BvcHN0YXRlJywgY2FjaGVTdGF0ZUFuZEZpcmVVcmxDaGFuZ2UpOw0KICAgICAgLy8gaGFzaGNoYW5nZSBldmVudA0KICAgICAganFMaXRlKHdpbmRvdykub24oJ2hhc2hjaGFuZ2UnLCBjYWNoZVN0YXRlQW5kRmlyZVVybENoYW5nZSk7DQoNCiAgICAgIHVybENoYW5nZUluaXQgPSB0cnVlOw0KICAgIH0NCg0KICAgIHVybENoYW5nZUxpc3RlbmVycy5wdXNoKGNhbGxiYWNrKTsNCiAgICByZXR1cm4gY2FsbGJhY2s7DQogIH07DQoNCiAgLyoqDQogICAqIENoZWNrcyB3aGV0aGVyIHRoZSB1cmwgaGFzIGNoYW5nZWQgb3V0c2lkZSBvZiBBbmd1bGFyLg0KICAgKiBOZWVkcyB0byBiZSBleHBvcnRlZCB0byBiZSBhYmxlIHRvIGNoZWNrIGZvciBjaGFuZ2VzIHRoYXQgaGF2ZSBiZWVuIGRvbmUgaW4gc3luYywNCiAgICogYXMgaGFzaGNoYW5nZS9wb3BzdGF0ZSBldmVudHMgZmlyZSBpbiBhc3luYy4NCiAgICovDQogIHNlbGYuJCRjaGVja1VybENoYW5nZSA9IGZpcmVVcmxDaGFuZ2U7DQoNCiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCiAgLy8gTWlzYyBBUEkNCiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCg0KICAvKioNCiAgICogQG5hbWUgJGJyb3dzZXIjYmFzZUhyZWYNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFJldHVybnMgY3VycmVudCA8YmFzZSBocmVmPg0KICAgKiAoYWx3YXlzIHJlbGF0aXZlIC0gd2l0aG91dCBkb21haW4pDQogICAqDQogICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjdXJyZW50IGJhc2UgaHJlZg0KICAgKi8NCiAgc2VsZi5iYXNlSHJlZiA9IGZ1bmN0aW9uKCkgew0KICAgIHZhciBocmVmID0gYmFzZUVsZW1lbnQuYXR0cignaHJlZicpOw0KICAgIHJldHVybiBocmVmID8gaHJlZi5yZXBsYWNlKC9eKGh0dHBzP1w6KT9cL1wvW15cL10qLywgJycpIDogJyc7DQogIH07DQoNCiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCiAgLy8gQ29va2llcyBBUEkNCiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCiAgdmFyIGxhc3RDb29raWVzID0ge307DQogIHZhciBsYXN0Q29va2llU3RyaW5nID0gJyc7DQogIHZhciBjb29raWVQYXRoID0gc2VsZi5iYXNlSHJlZigpOw0KDQogIGZ1bmN0aW9uIHNhZmVEZWNvZGVVUklDb21wb25lbnQoc3RyKSB7DQogICAgdHJ5IHsNCiAgICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQoc3RyKTsNCiAgICB9IGNhdGNoIChlKSB7DQogICAgICByZXR1cm4gc3RyOw0KICAgIH0NCiAgfQ0KDQogIC8qKg0KICAgKiBAbmFtZSAkYnJvd3NlciNjb29raWVzDQogICAqDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmFtZSBDb29raWUgbmFtZQ0KICAgKiBAcGFyYW0ge3N0cmluZz19IHZhbHVlIENvb2tpZSB2YWx1ZQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogVGhlIGNvb2tpZXMgbWV0aG9kIHByb3ZpZGVzIGEgJ3ByaXZhdGUnIGxvdyBsZXZlbCBhY2Nlc3MgdG8gYnJvd3NlciBjb29raWVzLg0KICAgKiBJdCBpcyBub3QgbWVhbnQgdG8gYmUgdXNlZCBkaXJlY3RseSwgdXNlIHRoZSAkY29va2llIHNlcnZpY2UgaW5zdGVhZC4NCiAgICoNCiAgICogVGhlIHJldHVybiB2YWx1ZXMgdmFyeSBkZXBlbmRpbmcgb24gdGhlIGFyZ3VtZW50cyB0aGF0IHRoZSBtZXRob2Qgd2FzIGNhbGxlZCB3aXRoIGFzIGZvbGxvd3M6DQogICAqDQogICAqIC0gY29va2llcygpIC0+IGhhc2ggb2YgYWxsIGNvb2tpZXMsIHRoaXMgaXMgTk9UIGEgY29weSBvZiB0aGUgaW50ZXJuYWwgc3RhdGUsIHNvIGRvIG5vdCBtb2RpZnkNCiAgICogICBpdA0KICAgKiAtIGNvb2tpZXMobmFtZSwgdmFsdWUpIC0+IHNldCBuYW1lIHRvIHZhbHVlLCBpZiB2YWx1ZSBpcyB1bmRlZmluZWQgZGVsZXRlIHRoZSBjb29raWUNCiAgICogLSBjb29raWVzKG5hbWUpIC0+IHRoZSBzYW1lIGFzIChuYW1lLCB1bmRlZmluZWQpID09IERFTEVURVMgKG5vIG9uZSBjYWxscyBpdCByaWdodCBub3cgdGhhdA0KICAgKiAgIHdheSkNCiAgICoNCiAgICogQHJldHVybnMge09iamVjdH0gSGFzaCBvZiBhbGwgY29va2llcyAoaWYgY2FsbGVkIHdpdGhvdXQgYW55IHBhcmFtZXRlcikNCiAgICovDQogIHNlbGYuY29va2llcyA9IGZ1bmN0aW9uKG5hbWUsIHZhbHVlKSB7DQogICAgdmFyIGNvb2tpZUxlbmd0aCwgY29va2llQXJyYXksIGNvb2tpZSwgaSwgaW5kZXg7DQoNCiAgICBpZiAobmFtZSkgew0KICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHsNCiAgICAgICAgcmF3RG9jdW1lbnQuY29va2llID0gZW5jb2RlVVJJQ29tcG9uZW50KG5hbWUpICsgIj07cGF0aD0iICsgY29va2llUGF0aCArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI7ZXhwaXJlcz1UaHUsIDAxIEphbiAxOTcwIDAwOjAwOjAwIEdNVCI7DQogICAgICB9IGVsc2Ugew0KICAgICAgICBpZiAoaXNTdHJpbmcodmFsdWUpKSB7DQogICAgICAgICAgY29va2llTGVuZ3RoID0gKHJhd0RvY3VtZW50LmNvb2tpZSA9IGVuY29kZVVSSUNvbXBvbmVudChuYW1lKSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudCh2YWx1ZSkgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnO3BhdGg9JyArIGNvb2tpZVBhdGgpLmxlbmd0aCArIDE7DQoNCiAgICAgICAgICAvLyBwZXIgaHR0cDovL3d3dy5pZXRmLm9yZy9yZmMvcmZjMjEwOS50eHQgYnJvd3NlciBtdXN0IGFsbG93IGF0IG1pbmltdW06DQogICAgICAgICAgLy8gLSAzMDAgY29va2llcw0KICAgICAgICAgIC8vIC0gMjAgY29va2llcyBwZXIgdW5pcXVlIGRvbWFpbg0KICAgICAgICAgIC8vIC0gNDA5NiBieXRlcyBwZXIgY29va2llDQogICAgICAgICAgaWYgKGNvb2tpZUxlbmd0aCA+IDQwOTYpIHsNCiAgICAgICAgICAgICRsb2cud2FybigiQ29va2llICciICsgbmFtZSArDQogICAgICAgICAgICAgICInIHBvc3NpYmx5IG5vdCBzZXQgb3Igb3ZlcmZsb3dlZCBiZWNhdXNlIGl0IHdhcyB0b28gbGFyZ2UgKCIgKw0KICAgICAgICAgICAgICBjb29raWVMZW5ndGggKyAiID4gNDA5NiBieXRlcykhIik7DQogICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICB9DQogICAgfSBlbHNlIHsNCiAgICAgIGlmIChyYXdEb2N1bWVudC5jb29raWUgIT09IGxhc3RDb29raWVTdHJpbmcpIHsNCiAgICAgICAgbGFzdENvb2tpZVN0cmluZyA9IHJhd0RvY3VtZW50LmNvb2tpZTsNCiAgICAgICAgY29va2llQXJyYXkgPSBsYXN0Q29va2llU3RyaW5nLnNwbGl0KCI7ICIpOw0KICAgICAgICBsYXN0Q29va2llcyA9IHt9Ow0KDQogICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb29raWVBcnJheS5sZW5ndGg7IGkrKykgew0KICAgICAgICAgIGNvb2tpZSA9IGNvb2tpZUFycmF5W2ldOw0KICAgICAgICAgIGluZGV4ID0gY29va2llLmluZGV4T2YoJz0nKTsNCiAgICAgICAgICBpZiAoaW5kZXggPiAwKSB7IC8vaWdub3JlIG5hbWVsZXNzIGNvb2tpZXMNCiAgICAgICAgICAgIG5hbWUgPSBzYWZlRGVjb2RlVVJJQ29tcG9uZW50KGNvb2tpZS5zdWJzdHJpbmcoMCwgaW5kZXgpKTsNCiAgICAgICAgICAgIC8vIHRoZSBmaXJzdCB2YWx1ZSB0aGF0IGlzIHNlZW4gZm9yIGEgY29va2llIGlzIHRoZSBtb3N0DQogICAgICAgICAgICAvLyBzcGVjaWZpYyBvbmUuICB2YWx1ZXMgZm9yIHRoZSBzYW1lIGNvb2tpZSBuYW1lIHRoYXQNCiAgICAgICAgICAgIC8vIGZvbGxvdyBhcmUgZm9yIGxlc3Mgc3BlY2lmaWMgcGF0aHMuDQogICAgICAgICAgICBpZiAobGFzdENvb2tpZXNbbmFtZV0gPT09IHVuZGVmaW5lZCkgew0KICAgICAgICAgICAgICBsYXN0Q29va2llc1tuYW1lXSA9IHNhZmVEZWNvZGVVUklDb21wb25lbnQoY29va2llLnN1YnN0cmluZyhpbmRleCArIDEpKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgIH0NCiAgICAgIHJldHVybiBsYXN0Q29va2llczsNCiAgICB9DQogIH07DQoNCg0KICAvKioNCiAgICogQG5hbWUgJGJyb3dzZXIjZGVmZXINCiAgICogQHBhcmFtIHtmdW5jdGlvbigpfSBmbiBBIGZ1bmN0aW9uLCB3aG8ncyBleGVjdXRpb24gc2hvdWxkIGJlIGRlZmVycmVkLg0KICAgKiBAcGFyYW0ge251bWJlcj19IFtkZWxheT0wXSBvZiBtaWxsaXNlY29uZHMgdG8gZGVmZXIgdGhlIGZ1bmN0aW9uIGV4ZWN1dGlvbi4NCiAgICogQHJldHVybnMgeyp9IERlZmVySWQgdGhhdCBjYW4gYmUgdXNlZCB0byBjYW5jZWwgdGhlIHRhc2sgdmlhIGAkYnJvd3Nlci5kZWZlci5jYW5jZWwoKWAuDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBFeGVjdXRlcyBhIGZuIGFzeW5jaHJvbm91c2x5IHZpYSBgc2V0VGltZW91dChmbiwgZGVsYXkpYC4NCiAgICoNCiAgICogVW5saWtlIHdoZW4gY2FsbGluZyBgc2V0VGltZW91dGAgZGlyZWN0bHksIGluIHRlc3QgdGhpcyBmdW5jdGlvbiBpcyBtb2NrZWQgYW5kIGluc3RlYWQgb2YgdXNpbmcNCiAgICogYHNldFRpbWVvdXRgIGluIHRlc3RzLCB0aGUgZm5zIGFyZSBxdWV1ZWQgaW4gYW4gYXJyYXksIHdoaWNoIGNhbiBiZSBwcm9ncmFtbWF0aWNhbGx5IGZsdXNoZWQNCiAgICogdmlhIGAkYnJvd3Nlci5kZWZlci5mbHVzaCgpYC4NCiAgICoNCiAgICovDQogIHNlbGYuZGVmZXIgPSBmdW5jdGlvbihmbiwgZGVsYXkpIHsNCiAgICB2YXIgdGltZW91dElkOw0KICAgIG91dHN0YW5kaW5nUmVxdWVzdENvdW50Kys7DQogICAgdGltZW91dElkID0gc2V0VGltZW91dChmdW5jdGlvbigpIHsNCiAgICAgIGRlbGV0ZSBwZW5kaW5nRGVmZXJJZHNbdGltZW91dElkXTsNCiAgICAgIGNvbXBsZXRlT3V0c3RhbmRpbmdSZXF1ZXN0KGZuKTsNCiAgICB9LCBkZWxheSB8fCAwKTsNCiAgICBwZW5kaW5nRGVmZXJJZHNbdGltZW91dElkXSA9IHRydWU7DQogICAgcmV0dXJuIHRpbWVvdXRJZDsNCiAgfTsNCg0KDQogIC8qKg0KICAgKiBAbmFtZSAkYnJvd3NlciNkZWZlci5jYW5jZWwNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIENhbmNlbHMgYSBkZWZlcnJlZCB0YXNrIGlkZW50aWZpZWQgd2l0aCBgZGVmZXJJZGAuDQogICAqDQogICAqIEBwYXJhbSB7Kn0gZGVmZXJJZCBUb2tlbiByZXR1cm5lZCBieSB0aGUgYCRicm93c2VyLmRlZmVyYCBmdW5jdGlvbi4NCiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB0YXNrIGhhc24ndCBleGVjdXRlZCB5ZXQgYW5kIHdhcyBzdWNjZXNzZnVsbHkNCiAgICogICAgICAgICAgICAgICAgICAgIGNhbmNlbGVkLg0KICAgKi8NCiAgc2VsZi5kZWZlci5jYW5jZWwgPSBmdW5jdGlvbihkZWZlcklkKSB7DQogICAgaWYgKHBlbmRpbmdEZWZlcklkc1tkZWZlcklkXSkgew0KICAgICAgZGVsZXRlIHBlbmRpbmdEZWZlcklkc1tkZWZlcklkXTsNCiAgICAgIGNsZWFyVGltZW91dChkZWZlcklkKTsNCiAgICAgIGNvbXBsZXRlT3V0c3RhbmRpbmdSZXF1ZXN0KG5vb3ApOw0KICAgICAgcmV0dXJuIHRydWU7DQogICAgfQ0KICAgIHJldHVybiBmYWxzZTsNCiAgfTsNCg0KfQ0KDQpmdW5jdGlvbiAkQnJvd3NlclByb3ZpZGVyKCkgew0KICB0aGlzLiRnZXQgPSBbJyR3aW5kb3cnLCAnJGxvZycsICckc25pZmZlcicsICckZG9jdW1lbnQnLA0KICAgICAgZnVuY3Rpb24oJHdpbmRvdywgJGxvZywgJHNuaWZmZXIsICRkb2N1bWVudCkgew0KICAgICAgICByZXR1cm4gbmV3IEJyb3dzZXIoJHdpbmRvdywgJGRvY3VtZW50LCAkbG9nLCAkc25pZmZlcik7DQogICAgICB9XTsNCn0NCg0KLyoqDQogKiBAbmdkb2Mgc2VydmljZQ0KICogQG5hbWUgJGNhY2hlRmFjdG9yeQ0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogRmFjdG9yeSB0aGF0IGNvbnN0cnVjdHMge0BsaW5rICRjYWNoZUZhY3RvcnkuQ2FjaGUgQ2FjaGV9IG9iamVjdHMgYW5kIGdpdmVzIGFjY2VzcyB0bw0KICogdGhlbS4NCiAqDQogKiBgYGBqcw0KICoNCiAqICB2YXIgY2FjaGUgPSAkY2FjaGVGYWN0b3J5KCdjYWNoZUlkJyk7DQogKiAgZXhwZWN0KCRjYWNoZUZhY3RvcnkuZ2V0KCdjYWNoZUlkJykpLnRvQmUoY2FjaGUpOw0KICogIGV4cGVjdCgkY2FjaGVGYWN0b3J5LmdldCgnbm9TdWNoQ2FjaGVJZCcpKS5ub3QudG9CZURlZmluZWQoKTsNCiAqDQogKiAgY2FjaGUucHV0KCJrZXkiLCAidmFsdWUiKTsNCiAqICBjYWNoZS5wdXQoImFub3RoZXIga2V5IiwgImFub3RoZXIgdmFsdWUiKTsNCiAqDQogKiAgLy8gV2UndmUgc3BlY2lmaWVkIG5vIG9wdGlvbnMgb24gY3JlYXRpb24NCiAqICBleHBlY3QoY2FjaGUuaW5mbygpKS50b0VxdWFsKHtpZDogJ2NhY2hlSWQnLCBzaXplOiAyfSk7DQogKg0KICogYGBgDQogKg0KICoNCiAqIEBwYXJhbSB7c3RyaW5nfSBjYWNoZUlkIE5hbWUgb3IgaWQgb2YgdGhlIG5ld2x5IGNyZWF0ZWQgY2FjaGUuDQogKiBAcGFyYW0ge29iamVjdD19IG9wdGlvbnMgT3B0aW9ucyBvYmplY3QgdGhhdCBzcGVjaWZpZXMgdGhlIGNhY2hlIGJlaGF2aW9yLiBQcm9wZXJ0aWVzOg0KICoNCiAqICAgLSBge251bWJlcj19YCBgY2FwYWNpdHlgIOKAPyB0dXJucyB0aGUgY2FjaGUgaW50byBMUlUgY2FjaGUuDQogKg0KICogQHJldHVybnMge29iamVjdH0gTmV3bHkgY3JlYXRlZCBjYWNoZSBvYmplY3Qgd2l0aCB0aGUgZm9sbG93aW5nIHNldCBvZiBtZXRob2RzOg0KICoNCiAqIC0gYHtvYmplY3R9YCBgaW5mbygpYCDigD8gUmV0dXJucyBpZCwgc2l6ZSwgYW5kIG9wdGlvbnMgb2YgY2FjaGUuDQogKiAtIGB7eyp9fWAgYHB1dCh7c3RyaW5nfSBrZXksIHsqfSB2YWx1ZSlgIOKAPyBQdXRzIGEgbmV3IGtleS12YWx1ZSBwYWlyIGludG8gdGhlIGNhY2hlIGFuZCByZXR1cm5zDQogKiAgIGl0Lg0KICogLSBge3sqfX1gIGBnZXQoe3N0cmluZ30ga2V5KWAg4oA/IFJldHVybnMgY2FjaGVkIHZhbHVlIGZvciBga2V5YCBvciB1bmRlZmluZWQgZm9yIGNhY2hlIG1pc3MuDQogKiAtIGB7dm9pZH1gIGByZW1vdmUoe3N0cmluZ30ga2V5KWAg4oA/IFJlbW92ZXMgYSBrZXktdmFsdWUgcGFpciBmcm9tIHRoZSBjYWNoZS4NCiAqIC0gYHt2b2lkfWAgYHJlbW92ZUFsbCgpYCDigD8gUmVtb3ZlcyBhbGwgY2FjaGVkIHZhbHVlcy4NCiAqIC0gYHt2b2lkfWAgYGRlc3Ryb3koKWAg4oA/IFJlbW92ZXMgcmVmZXJlbmNlcyB0byB0aGlzIGNhY2hlIGZyb20gJGNhY2hlRmFjdG9yeS4NCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGUgbW9kdWxlPSJjYWNoZUV4YW1wbGVBcHAiPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkNhY2hlQ29udHJvbGxlciI+DQogICAgICAgICA8aW5wdXQgbmctbW9kZWw9Im5ld0NhY2hlS2V5IiBwbGFjZWhvbGRlcj0iS2V5Ij4NCiAgICAgICAgIDxpbnB1dCBuZy1tb2RlbD0ibmV3Q2FjaGVWYWx1ZSIgcGxhY2Vob2xkZXI9IlZhbHVlIj4NCiAgICAgICAgIDxidXR0b24gbmctY2xpY2s9InB1dChuZXdDYWNoZUtleSwgbmV3Q2FjaGVWYWx1ZSkiPkNhY2hlPC9idXR0b24+DQoNCiAgICAgICAgIDxwIG5nLWlmPSJrZXlzLmxlbmd0aCI+Q2FjaGVkIFZhbHVlczwvcD4NCiAgICAgICAgIDxkaXYgbmctcmVwZWF0PSJrZXkgaW4ga2V5cyI+DQogICAgICAgICAgIDxzcGFuIG5nLWJpbmQ9ImtleSI+PC9zcGFuPg0KICAgICAgICAgICA8c3Bhbj46IDwvc3Bhbj4NCiAgICAgICAgICAgPGIgbmctYmluZD0iY2FjaGUuZ2V0KGtleSkiPjwvYj4NCiAgICAgICAgIDwvZGl2Pg0KDQogICAgICAgICA8cD5DYWNoZSBJbmZvPC9wPg0KICAgICAgICAgPGRpdiBuZy1yZXBlYXQ9IihrZXksIHZhbHVlKSBpbiBjYWNoZS5pbmZvKCkiPg0KICAgICAgICAgICA8c3BhbiBuZy1iaW5kPSJrZXkiPjwvc3Bhbj4NCiAgICAgICAgICAgPHNwYW4+OiA8L3NwYW4+DQogICAgICAgICAgIDxiIG5nLWJpbmQ9InZhbHVlIj48L2I+DQogICAgICAgICA8L2Rpdj4NCiAgICAgICA8L2Rpdj4NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJzY3JpcHQuanMiPg0KICAgICAgIGFuZ3VsYXIubW9kdWxlKCdjYWNoZUV4YW1wbGVBcHAnLCBbXSkuDQogICAgICAgICBjb250cm9sbGVyKCdDYWNoZUNvbnRyb2xsZXInLCBbJyRzY29wZScsICckY2FjaGVGYWN0b3J5JywgZnVuY3Rpb24oJHNjb3BlLCAkY2FjaGVGYWN0b3J5KSB7DQogICAgICAgICAgICRzY29wZS5rZXlzID0gW107DQogICAgICAgICAgICRzY29wZS5jYWNoZSA9ICRjYWNoZUZhY3RvcnkoJ2NhY2hlSWQnKTsNCiAgICAgICAgICAgJHNjb3BlLnB1dCA9IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHsNCiAgICAgICAgICAgICBpZiAoJHNjb3BlLmNhY2hlLmdldChrZXkpID09PSB1bmRlZmluZWQpIHsNCiAgICAgICAgICAgICAgICRzY29wZS5rZXlzLnB1c2goa2V5KTsNCiAgICAgICAgICAgICB9DQogICAgICAgICAgICAgJHNjb3BlLmNhY2hlLnB1dChrZXksIHZhbHVlID09PSB1bmRlZmluZWQgPyBudWxsIDogdmFsdWUpOw0KICAgICAgICAgICB9Ow0KICAgICAgICAgfV0pOw0KICAgICA8L2ZpbGU+DQogICAgIDxmaWxlIG5hbWU9InN0eWxlLmNzcyI+DQogICAgICAgcCB7DQogICAgICAgICBtYXJnaW46IDEwcHggMCAzcHg7DQogICAgICAgfQ0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCmZ1bmN0aW9uICRDYWNoZUZhY3RvcnlQcm92aWRlcigpIHsNCg0KICB0aGlzLiRnZXQgPSBmdW5jdGlvbigpIHsNCiAgICB2YXIgY2FjaGVzID0ge307DQoNCiAgICBmdW5jdGlvbiBjYWNoZUZhY3RvcnkoY2FjaGVJZCwgb3B0aW9ucykgew0KICAgICAgaWYgKGNhY2hlSWQgaW4gY2FjaGVzKSB7DQogICAgICAgIHRocm93IG1pbkVycignJGNhY2hlRmFjdG9yeScpKCdpaWQnLCAiQ2FjaGVJZCAnezB9JyBpcyBhbHJlYWR5IHRha2VuISIsIGNhY2hlSWQpOw0KICAgICAgfQ0KDQogICAgICB2YXIgc2l6ZSA9IDAsDQogICAgICAgICAgc3RhdHMgPSBleHRlbmQoe30sIG9wdGlvbnMsIHtpZDogY2FjaGVJZH0pLA0KICAgICAgICAgIGRhdGEgPSB7fSwNCiAgICAgICAgICBjYXBhY2l0eSA9IChvcHRpb25zICYmIG9wdGlvbnMuY2FwYWNpdHkpIHx8IE51bWJlci5NQVhfVkFMVUUsDQogICAgICAgICAgbHJ1SGFzaCA9IHt9LA0KICAgICAgICAgIGZyZXNoRW5kID0gbnVsbCwNCiAgICAgICAgICBzdGFsZUVuZCA9IG51bGw7DQoNCiAgICAgIC8qKg0KICAgICAgICogQG5nZG9jIHR5cGUNCiAgICAgICAqIEBuYW1lICRjYWNoZUZhY3RvcnkuQ2FjaGUNCiAgICAgICAqDQogICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAqIEEgY2FjaGUgb2JqZWN0IHVzZWQgdG8gc3RvcmUgYW5kIHJldHJpZXZlIGRhdGEsIHByaW1hcmlseSB1c2VkIGJ5DQogICAgICAgKiB7QGxpbmsgJGh0dHAgJGh0dHB9IGFuZCB0aGUge0BsaW5rIG5nLmRpcmVjdGl2ZTpzY3JpcHQgc2NyaXB0fSBkaXJlY3RpdmUgdG8gY2FjaGUNCiAgICAgICAqIHRlbXBsYXRlcyBhbmQgb3RoZXIgZGF0YS4NCiAgICAgICAqDQogICAgICAgKiBgYGBqcw0KICAgICAgICogIGFuZ3VsYXIubW9kdWxlKCdzdXBlckNhY2hlJykNCiAgICAgICAqICAgIC5mYWN0b3J5KCdzdXBlckNhY2hlJywgWyckY2FjaGVGYWN0b3J5JywgZnVuY3Rpb24oJGNhY2hlRmFjdG9yeSkgew0KICAgICAgICogICAgICByZXR1cm4gJGNhY2hlRmFjdG9yeSgnc3VwZXItY2FjaGUnKTsNCiAgICAgICAqICAgIH1dKTsNCiAgICAgICAqIGBgYA0KICAgICAgICoNCiAgICAgICAqIEV4YW1wbGUgdGVzdDoNCiAgICAgICAqDQogICAgICAgKiBgYGBqcw0KICAgICAgICogIGl0KCdzaG91bGQgYmVoYXZlIGxpa2UgYSBjYWNoZScsIGluamVjdChmdW5jdGlvbihzdXBlckNhY2hlKSB7DQogICAgICAgKiAgICBzdXBlckNhY2hlLnB1dCgna2V5JywgJ3ZhbHVlJyk7DQogICAgICAgKiAgICBzdXBlckNhY2hlLnB1dCgnYW5vdGhlciBrZXknLCAnYW5vdGhlciB2YWx1ZScpOw0KICAgICAgICoNCiAgICAgICAqICAgIGV4cGVjdChzdXBlckNhY2hlLmluZm8oKSkudG9FcXVhbCh7DQogICAgICAgKiAgICAgIGlkOiAnc3VwZXItY2FjaGUnLA0KICAgICAgICogICAgICBzaXplOiAyDQogICAgICAgKiAgICB9KTsNCiAgICAgICAqDQogICAgICAgKiAgICBzdXBlckNhY2hlLnJlbW92ZSgnYW5vdGhlciBrZXknKTsNCiAgICAgICAqICAgIGV4cGVjdChzdXBlckNhY2hlLmdldCgnYW5vdGhlciBrZXknKSkudG9CZVVuZGVmaW5lZCgpOw0KICAgICAgICoNCiAgICAgICAqICAgIHN1cGVyQ2FjaGUucmVtb3ZlQWxsKCk7DQogICAgICAgKiAgICBleHBlY3Qoc3VwZXJDYWNoZS5pbmZvKCkpLnRvRXF1YWwoew0KICAgICAgICogICAgICBpZDogJ3N1cGVyLWNhY2hlJywNCiAgICAgICAqICAgICAgc2l6ZTogMA0KICAgICAgICogICAgfSk7DQogICAgICAgKiAgfSkpOw0KICAgICAgICogYGBgDQogICAgICAgKi8NCiAgICAgIHJldHVybiBjYWNoZXNbY2FjaGVJZF0gPSB7DQoNCiAgICAgICAgLyoqDQogICAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAgICogQG5hbWUgJGNhY2hlRmFjdG9yeS5DYWNoZSNwdXQNCiAgICAgICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgICAgICoNCiAgICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgICAqIEluc2VydHMgYSBuYW1lZCBlbnRyeSBpbnRvIHRoZSB7QGxpbmsgJGNhY2hlRmFjdG9yeS5DYWNoZSBDYWNoZX0gb2JqZWN0IHRvIGJlDQogICAgICAgICAqIHJldHJpZXZlZCBsYXRlciwgYW5kIGluY3JlbWVudGluZyB0aGUgc2l6ZSBvZiB0aGUgY2FjaGUgaWYgdGhlIGtleSB3YXMgbm90IGFscmVhZHkNCiAgICAgICAgICogcHJlc2VudCBpbiB0aGUgY2FjaGUuIElmIGJlaGF2aW5nIGxpa2UgYW4gTFJVIGNhY2hlLCBpdCB3aWxsIGFsc28gcmVtb3ZlIHN0YWxlDQogICAgICAgICAqIGVudHJpZXMgZnJvbSB0aGUgc2V0Lg0KICAgICAgICAgKg0KICAgICAgICAgKiBJdCB3aWxsIG5vdCBpbnNlcnQgdW5kZWZpbmVkIHZhbHVlcyBpbnRvIHRoZSBjYWNoZS4NCiAgICAgICAgICoNCiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSB0aGUga2V5IHVuZGVyIHdoaWNoIHRoZSBjYWNoZWQgZGF0YSBpcyBzdG9yZWQuDQogICAgICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgdGhlIHZhbHVlIHRvIHN0b3JlIGFsb25nc2lkZSB0aGUga2V5LiBJZiBpdCBpcyB1bmRlZmluZWQsIHRoZSBrZXkNCiAgICAgICAgICogICAgd2lsbCBub3QgYmUgc3RvcmVkLg0KICAgICAgICAgKiBAcmV0dXJucyB7Kn0gdGhlIHZhbHVlIHN0b3JlZC4NCiAgICAgICAgICovDQogICAgICAgIHB1dDogZnVuY3Rpb24oa2V5LCB2YWx1ZSkgew0KICAgICAgICAgIGlmIChjYXBhY2l0eSA8IE51bWJlci5NQVhfVkFMVUUpIHsNCiAgICAgICAgICAgIHZhciBscnVFbnRyeSA9IGxydUhhc2hba2V5XSB8fCAobHJ1SGFzaFtrZXldID0ge2tleToga2V5fSk7DQoNCiAgICAgICAgICAgIHJlZnJlc2gobHJ1RW50cnkpOw0KICAgICAgICAgIH0NCg0KICAgICAgICAgIGlmIChpc1VuZGVmaW5lZCh2YWx1ZSkpIHJldHVybjsNCiAgICAgICAgICBpZiAoIShrZXkgaW4gZGF0YSkpIHNpemUrKzsNCiAgICAgICAgICBkYXRhW2tleV0gPSB2YWx1ZTsNCg0KICAgICAgICAgIGlmIChzaXplID4gY2FwYWNpdHkpIHsNCiAgICAgICAgICAgIHRoaXMucmVtb3ZlKHN0YWxlRW5kLmtleSk7DQogICAgICAgICAgfQ0KDQogICAgICAgICAgcmV0dXJuIHZhbHVlOw0KICAgICAgICB9LA0KDQogICAgICAgIC8qKg0KICAgICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgICAqIEBuYW1lICRjYWNoZUZhY3RvcnkuQ2FjaGUjZ2V0DQogICAgICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICAgICAqDQogICAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICAgKiBSZXRyaWV2ZXMgbmFtZWQgZGF0YSBzdG9yZWQgaW4gdGhlIHtAbGluayAkY2FjaGVGYWN0b3J5LkNhY2hlIENhY2hlfSBvYmplY3QuDQogICAgICAgICAqDQogICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgdGhlIGtleSBvZiB0aGUgZGF0YSB0byBiZSByZXRyaWV2ZWQNCiAgICAgICAgICogQHJldHVybnMgeyp9IHRoZSB2YWx1ZSBzdG9yZWQuDQogICAgICAgICAqLw0KICAgICAgICBnZXQ6IGZ1bmN0aW9uKGtleSkgew0KICAgICAgICAgIGlmIChjYXBhY2l0eSA8IE51bWJlci5NQVhfVkFMVUUpIHsNCiAgICAgICAgICAgIHZhciBscnVFbnRyeSA9IGxydUhhc2hba2V5XTsNCg0KICAgICAgICAgICAgaWYgKCFscnVFbnRyeSkgcmV0dXJuOw0KDQogICAgICAgICAgICByZWZyZXNoKGxydUVudHJ5KTsNCiAgICAgICAgICB9DQoNCiAgICAgICAgICByZXR1cm4gZGF0YVtrZXldOw0KICAgICAgICB9LA0KDQoNCiAgICAgICAgLyoqDQogICAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAgICogQG5hbWUgJGNhY2hlRmFjdG9yeS5DYWNoZSNyZW1vdmUNCiAgICAgICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgICAgICoNCiAgICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgICAqIFJlbW92ZXMgYW4gZW50cnkgZnJvbSB0aGUge0BsaW5rICRjYWNoZUZhY3RvcnkuQ2FjaGUgQ2FjaGV9IG9iamVjdC4NCiAgICAgICAgICoNCiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSB0aGUga2V5IG9mIHRoZSBlbnRyeSB0byBiZSByZW1vdmVkDQogICAgICAgICAqLw0KICAgICAgICByZW1vdmU6IGZ1bmN0aW9uKGtleSkgew0KICAgICAgICAgIGlmIChjYXBhY2l0eSA8IE51bWJlci5NQVhfVkFMVUUpIHsNCiAgICAgICAgICAgIHZhciBscnVFbnRyeSA9IGxydUhhc2hba2V5XTsNCg0KICAgICAgICAgICAgaWYgKCFscnVFbnRyeSkgcmV0dXJuOw0KDQogICAgICAgICAgICBpZiAobHJ1RW50cnkgPT0gZnJlc2hFbmQpIGZyZXNoRW5kID0gbHJ1RW50cnkucDsNCiAgICAgICAgICAgIGlmIChscnVFbnRyeSA9PSBzdGFsZUVuZCkgc3RhbGVFbmQgPSBscnVFbnRyeS5uOw0KICAgICAgICAgICAgbGluayhscnVFbnRyeS5uLGxydUVudHJ5LnApOw0KDQogICAgICAgICAgICBkZWxldGUgbHJ1SGFzaFtrZXldOw0KICAgICAgICAgIH0NCg0KICAgICAgICAgIGRlbGV0ZSBkYXRhW2tleV07DQogICAgICAgICAgc2l6ZS0tOw0KICAgICAgICB9LA0KDQoNCiAgICAgICAgLyoqDQogICAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAgICogQG5hbWUgJGNhY2hlRmFjdG9yeS5DYWNoZSNyZW1vdmVBbGwNCiAgICAgICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgICAgICoNCiAgICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgICAqIENsZWFycyB0aGUgY2FjaGUgb2JqZWN0IG9mIGFueSBlbnRyaWVzLg0KICAgICAgICAgKi8NCiAgICAgICAgcmVtb3ZlQWxsOiBmdW5jdGlvbigpIHsNCiAgICAgICAgICBkYXRhID0ge307DQogICAgICAgICAgc2l6ZSA9IDA7DQogICAgICAgICAgbHJ1SGFzaCA9IHt9Ow0KICAgICAgICAgIGZyZXNoRW5kID0gc3RhbGVFbmQgPSBudWxsOw0KICAgICAgICB9LA0KDQoNCiAgICAgICAgLyoqDQogICAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAgICogQG5hbWUgJGNhY2hlRmFjdG9yeS5DYWNoZSNkZXN0cm95DQogICAgICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICAgICAqDQogICAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICAgKiBEZXN0cm95cyB0aGUge0BsaW5rICRjYWNoZUZhY3RvcnkuQ2FjaGUgQ2FjaGV9IG9iamVjdCBlbnRpcmVseSwNCiAgICAgICAgICogcmVtb3ZpbmcgaXQgZnJvbSB0aGUge0BsaW5rICRjYWNoZUZhY3RvcnkgJGNhY2hlRmFjdG9yeX0gc2V0Lg0KICAgICAgICAgKi8NCiAgICAgICAgZGVzdHJveTogZnVuY3Rpb24oKSB7DQogICAgICAgICAgZGF0YSA9IG51bGw7DQogICAgICAgICAgc3RhdHMgPSBudWxsOw0KICAgICAgICAgIGxydUhhc2ggPSBudWxsOw0KICAgICAgICAgIGRlbGV0ZSBjYWNoZXNbY2FjaGVJZF07DQogICAgICAgIH0sDQoNCg0KICAgICAgICAvKioNCiAgICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICAgKiBAbmFtZSAkY2FjaGVGYWN0b3J5LkNhY2hlI2luZm8NCiAgICAgICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgICAgICoNCiAgICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgICAqIFJldHJpZXZlIGluZm9ybWF0aW9uIHJlZ2FyZGluZyBhIHBhcnRpY3VsYXIge0BsaW5rICRjYWNoZUZhY3RvcnkuQ2FjaGUgQ2FjaGV9Lg0KICAgICAgICAgKg0KICAgICAgICAgKiBAcmV0dXJucyB7b2JqZWN0fSBhbiBvYmplY3Qgd2l0aCB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6DQogICAgICAgICAqICAgPHVsPg0KICAgICAgICAgKiAgICAgPGxpPioqaWQqKjogdGhlIGlkIG9mIHRoZSBjYWNoZSBpbnN0YW5jZTwvbGk+DQogICAgICAgICAqICAgICA8bGk+KipzaXplKio6IHRoZSBudW1iZXIgb2YgZW50cmllcyBrZXB0IGluIHRoZSBjYWNoZSBpbnN0YW5jZTwvbGk+DQogICAgICAgICAqICAgICA8bGk+KiouLi4qKjogYW55IGFkZGl0aW9uYWwgcHJvcGVydGllcyBmcm9tIHRoZSBvcHRpb25zIG9iamVjdCB3aGVuIGNyZWF0aW5nIHRoZQ0KICAgICAgICAgKiAgICAgICBjYWNoZS48L2xpPg0KICAgICAgICAgKiAgIDwvdWw+DQogICAgICAgICAqLw0KICAgICAgICBpbmZvOiBmdW5jdGlvbigpIHsNCiAgICAgICAgICByZXR1cm4gZXh0ZW5kKHt9LCBzdGF0cywge3NpemU6IHNpemV9KTsNCiAgICAgICAgfQ0KICAgICAgfTsNCg0KDQogICAgICAvKioNCiAgICAgICAqIG1ha2VzIHRoZSBgZW50cnlgIHRoZSBmcmVzaEVuZCBvZiB0aGUgTFJVIGxpbmtlZCBsaXN0DQogICAgICAgKi8NCiAgICAgIGZ1bmN0aW9uIHJlZnJlc2goZW50cnkpIHsNCiAgICAgICAgaWYgKGVudHJ5ICE9IGZyZXNoRW5kKSB7DQogICAgICAgICAgaWYgKCFzdGFsZUVuZCkgew0KICAgICAgICAgICAgc3RhbGVFbmQgPSBlbnRyeTsNCiAgICAgICAgICB9IGVsc2UgaWYgKHN0YWxlRW5kID09IGVudHJ5KSB7DQogICAgICAgICAgICBzdGFsZUVuZCA9IGVudHJ5Lm47DQogICAgICAgICAgfQ0KDQogICAgICAgICAgbGluayhlbnRyeS5uLCBlbnRyeS5wKTsNCiAgICAgICAgICBsaW5rKGVudHJ5LCBmcmVzaEVuZCk7DQogICAgICAgICAgZnJlc2hFbmQgPSBlbnRyeTsNCiAgICAgICAgICBmcmVzaEVuZC5uID0gbnVsbDsNCiAgICAgICAgfQ0KICAgICAgfQ0KDQoNCiAgICAgIC8qKg0KICAgICAgICogYmlkaXJlY3Rpb25hbGx5IGxpbmtzIHR3byBlbnRyaWVzIG9mIHRoZSBMUlUgbGlua2VkIGxpc3QNCiAgICAgICAqLw0KICAgICAgZnVuY3Rpb24gbGluayhuZXh0RW50cnksIHByZXZFbnRyeSkgew0KICAgICAgICBpZiAobmV4dEVudHJ5ICE9IHByZXZFbnRyeSkgew0KICAgICAgICAgIGlmIChuZXh0RW50cnkpIG5leHRFbnRyeS5wID0gcHJldkVudHJ5OyAvL3Agc3RhbmRzIGZvciBwcmV2aW91cywgJ3ByZXYnIGRpZG4ndCBtaW5pZnkNCiAgICAgICAgICBpZiAocHJldkVudHJ5KSBwcmV2RW50cnkubiA9IG5leHRFbnRyeTsgLy9uIHN0YW5kcyBmb3IgbmV4dCwgJ25leHQnIGRpZG4ndCBtaW5pZnkNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgIH0NCg0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lICRjYWNoZUZhY3RvcnkjaW5mbw0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogR2V0IGluZm9ybWF0aW9uIGFib3V0IGFsbCB0aGUgY2FjaGVzIHRoYXQgaGF2ZSBiZWVuIGNyZWF0ZWQNCiAgICoNCiAgICogQHJldHVybnMge09iamVjdH0gLSBrZXktdmFsdWUgbWFwIG9mIGBjYWNoZUlkYCB0byB0aGUgcmVzdWx0IG9mIGNhbGxpbmcgYGNhY2hlI2luZm9gDQogICAqLw0KICAgIGNhY2hlRmFjdG9yeS5pbmZvID0gZnVuY3Rpb24oKSB7DQogICAgICB2YXIgaW5mbyA9IHt9Ow0KICAgICAgZm9yRWFjaChjYWNoZXMsIGZ1bmN0aW9uKGNhY2hlLCBjYWNoZUlkKSB7DQogICAgICAgIGluZm9bY2FjaGVJZF0gPSBjYWNoZS5pbmZvKCk7DQogICAgICB9KTsNCiAgICAgIHJldHVybiBpbmZvOw0KICAgIH07DQoNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkY2FjaGVGYWN0b3J5I2dldA0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogR2V0IGFjY2VzcyB0byBhIGNhY2hlIG9iamVjdCBieSB0aGUgYGNhY2hlSWRgIHVzZWQgd2hlbiBpdCB3YXMgY3JlYXRlZC4NCiAgICoNCiAgICogQHBhcmFtIHtzdHJpbmd9IGNhY2hlSWQgTmFtZSBvciBpZCBvZiBhIGNhY2hlIHRvIGFjY2Vzcy4NCiAgICogQHJldHVybnMge29iamVjdH0gQ2FjaGUgb2JqZWN0IGlkZW50aWZpZWQgYnkgdGhlIGNhY2hlSWQgb3IgdW5kZWZpbmVkIGlmIG5vIHN1Y2ggY2FjaGUuDQogICAqLw0KICAgIGNhY2hlRmFjdG9yeS5nZXQgPSBmdW5jdGlvbihjYWNoZUlkKSB7DQogICAgICByZXR1cm4gY2FjaGVzW2NhY2hlSWRdOw0KICAgIH07DQoNCg0KICAgIHJldHVybiBjYWNoZUZhY3Rvcnk7DQogIH07DQp9DQoNCi8qKg0KICogQG5nZG9jIHNlcnZpY2UNCiAqIEBuYW1lICR0ZW1wbGF0ZUNhY2hlDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBUaGUgZmlyc3QgdGltZSBhIHRlbXBsYXRlIGlzIHVzZWQsIGl0IGlzIGxvYWRlZCBpbiB0aGUgdGVtcGxhdGUgY2FjaGUgZm9yIHF1aWNrIHJldHJpZXZhbC4gWW91DQogKiBjYW4gbG9hZCB0ZW1wbGF0ZXMgZGlyZWN0bHkgaW50byB0aGUgY2FjaGUgaW4gYSBgc2NyaXB0YCB0YWcsIG9yIGJ5IGNvbnN1bWluZyB0aGUNCiAqIGAkdGVtcGxhdGVDYWNoZWAgc2VydmljZSBkaXJlY3RseS4NCiAqDQogKiBBZGRpbmcgdmlhIHRoZSBgc2NyaXB0YCB0YWc6DQogKg0KICogYGBgaHRtbA0KICogICA8c2NyaXB0IHR5cGU9InRleHQvbmctdGVtcGxhdGUiIGlkPSJ0ZW1wbGF0ZUlkLmh0bWwiPg0KICogICAgIDxwPlRoaXMgaXMgdGhlIGNvbnRlbnQgb2YgdGhlIHRlbXBsYXRlPC9wPg0KICogICA8L3NjcmlwdD4NCiAqIGBgYA0KICoNCiAqICoqTm90ZToqKiB0aGUgYHNjcmlwdGAgdGFnIGNvbnRhaW5pbmcgdGhlIHRlbXBsYXRlIGRvZXMgbm90IG5lZWQgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGBoZWFkYCBvZg0KICogdGhlIGRvY3VtZW50LCBidXQgaXQgbXVzdCBiZSBhIGRlc2NlbmRlbnQgb2YgdGhlIHtAbGluayBuZy4kcm9vdEVsZW1lbnQgJHJvb3RFbGVtZW50fSAoSUUsDQogKiBlbGVtZW50IHdpdGggbmctYXBwIGF0dHJpYnV0ZSksIG90aGVyd2lzZSB0aGUgdGVtcGxhdGUgd2lsbCBiZSBpZ25vcmVkLg0KICoNCiAqIEFkZGluZyB2aWEgdGhlICR0ZW1wbGF0ZUNhY2hlIHNlcnZpY2U6DQogKg0KICogYGBganMNCiAqIHZhciBteUFwcCA9IGFuZ3VsYXIubW9kdWxlKCdteUFwcCcsIFtdKTsNCiAqIG15QXBwLnJ1bihmdW5jdGlvbigkdGVtcGxhdGVDYWNoZSkgew0KICogICAkdGVtcGxhdGVDYWNoZS5wdXQoJ3RlbXBsYXRlSWQuaHRtbCcsICdUaGlzIGlzIHRoZSBjb250ZW50IG9mIHRoZSB0ZW1wbGF0ZScpOw0KICogfSk7DQogKiBgYGANCiAqDQogKiBUbyByZXRyaWV2ZSB0aGUgdGVtcGxhdGUgbGF0ZXIsIHNpbXBseSB1c2UgaXQgaW4geW91ciBIVE1MOg0KICogYGBgaHRtbA0KICogPGRpdiBuZy1pbmNsdWRlPSIgJ3RlbXBsYXRlSWQuaHRtbCcgIj48L2Rpdj4NCiAqIGBgYA0KICoNCiAqIG9yIGdldCBpdCB2aWEgSmF2YXNjcmlwdDoNCiAqIGBgYGpzDQogKiAkdGVtcGxhdGVDYWNoZS5nZXQoJ3RlbXBsYXRlSWQuaHRtbCcpDQogKiBgYGANCiAqDQogKiBTZWUge0BsaW5rIG5nLiRjYWNoZUZhY3RvcnkgJGNhY2hlRmFjdG9yeX0uDQogKg0KICovDQpmdW5jdGlvbiAkVGVtcGxhdGVDYWNoZVByb3ZpZGVyKCkgew0KICB0aGlzLiRnZXQgPSBbJyRjYWNoZUZhY3RvcnknLCBmdW5jdGlvbigkY2FjaGVGYWN0b3J5KSB7DQogICAgcmV0dXJuICRjYWNoZUZhY3RvcnkoJ3RlbXBsYXRlcycpOw0KICB9XTsNCn0NCg0KLyogISBWQVJJQUJMRS9GVU5DVElPTiBOQU1JTkcgQ09OVkVOVElPTlMgVEhBVCBBUFBMWSBUTyBUSElTIEZJTEUhDQogKg0KICogRE9NLXJlbGF0ZWQgdmFyaWFibGVzOg0KICoNCiAqIC0gIm5vZGUiIC0gRE9NIE5vZGUNCiAqIC0gImVsZW1lbnQiIC0gRE9NIEVsZW1lbnQgb3IgTm9kZQ0KICogLSAiJG5vZGUiIG9yICIkZWxlbWVudCIgLSBqcUxpdGUtd3JhcHBlZCBub2RlIG9yIGVsZW1lbnQNCiAqDQogKg0KICogQ29tcGlsZXIgcmVsYXRlZCBzdHVmZjoNCiAqDQogKiAtICJsaW5rRm4iIC0gbGlua2luZyBmbiBvZiBhIHNpbmdsZSBkaXJlY3RpdmUNCiAqIC0gIm5vZGVMaW5rRm4iIC0gZnVuY3Rpb24gdGhhdCBhZ2dyZWdhdGVzIGFsbCBsaW5raW5nIGZucyBmb3IgYSBwYXJ0aWN1bGFyIG5vZGUNCiAqIC0gImNoaWxkTGlua0ZuIiAtICBmdW5jdGlvbiB0aGF0IGFnZ3JlZ2F0ZXMgYWxsIGxpbmtpbmcgZm5zIGZvciBjaGlsZCBub2RlcyBvZiBhIHBhcnRpY3VsYXIgbm9kZQ0KICogLSAiY29tcG9zaXRlTGlua0ZuIiAtIGZ1bmN0aW9uIHRoYXQgYWdncmVnYXRlcyBhbGwgbGlua2luZyBmbnMgZm9yIGEgY29tcGlsYXRpb24gcm9vdCAobm9kZUxpc3QpDQogKi8NCg0KDQovKioNCiAqIEBuZ2RvYyBzZXJ2aWNlDQogKiBAbmFtZSAkY29tcGlsZQ0KICogQGtpbmQgZnVuY3Rpb24NCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIENvbXBpbGVzIGFuIEhUTUwgc3RyaW5nIG9yIERPTSBpbnRvIGEgdGVtcGxhdGUgYW5kIHByb2R1Y2VzIGEgdGVtcGxhdGUgZnVuY3Rpb24sIHdoaWNoDQogKiBjYW4gdGhlbiBiZSB1c2VkIHRvIGxpbmsge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUgYHNjb3BlYH0gYW5kIHRoZSB0ZW1wbGF0ZSB0b2dldGhlci4NCiAqDQogKiBUaGUgY29tcGlsYXRpb24gaXMgYSBwcm9jZXNzIG9mIHdhbGtpbmcgdGhlIERPTSB0cmVlIGFuZCBtYXRjaGluZyBET00gZWxlbWVudHMgdG8NCiAqIHtAbGluayBuZy4kY29tcGlsZVByb3ZpZGVyI2RpcmVjdGl2ZSBkaXJlY3RpdmVzfS4NCiAqDQogKiA8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4NCiAqICoqTm90ZToqKiBUaGlzIGRvY3VtZW50IGlzIGFuIGluLWRlcHRoIHJlZmVyZW5jZSBvZiBhbGwgZGlyZWN0aXZlIG9wdGlvbnMuDQogKiBGb3IgYSBnZW50bGUgaW50cm9kdWN0aW9uIHRvIGRpcmVjdGl2ZXMgd2l0aCBleGFtcGxlcyBvZiBjb21tb24gdXNlIGNhc2VzLA0KICogc2VlIHRoZSB7QGxpbmsgZ3VpZGUvZGlyZWN0aXZlIGRpcmVjdGl2ZSBndWlkZX0uDQogKiA8L2Rpdj4NCiAqDQogKiAjIyBDb21wcmVoZW5zaXZlIERpcmVjdGl2ZSBBUEkNCiAqDQogKiBUaGVyZSBhcmUgbWFueSBkaWZmZXJlbnQgb3B0aW9ucyBmb3IgYSBkaXJlY3RpdmUuDQogKg0KICogVGhlIGRpZmZlcmVuY2UgcmVzaWRlcyBpbiB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBmYWN0b3J5IGZ1bmN0aW9uLg0KICogWW91IGNhbiBlaXRoZXIgcmV0dXJuIGEgIkRpcmVjdGl2ZSBEZWZpbml0aW9uIE9iamVjdCIgKHNlZSBiZWxvdykgdGhhdCBkZWZpbmVzIHRoZSBkaXJlY3RpdmUgcHJvcGVydGllcywNCiAqIG9yIGp1c3QgdGhlIGBwb3N0TGlua2AgZnVuY3Rpb24gKGFsbCBvdGhlciBwcm9wZXJ0aWVzIHdpbGwgaGF2ZSB0aGUgZGVmYXVsdCB2YWx1ZXMpLg0KICoNCiAqIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXN1Y2Nlc3MiPg0KICogKipCZXN0IFByYWN0aWNlOioqIEl0J3MgcmVjb21tZW5kZWQgdG8gdXNlIHRoZSAiZGlyZWN0aXZlIGRlZmluaXRpb24gb2JqZWN0IiBmb3JtLg0KICogPC9kaXY+DQogKg0KICogSGVyZSdzIGFuIGV4YW1wbGUgZGlyZWN0aXZlIGRlY2xhcmVkIHdpdGggYSBEaXJlY3RpdmUgRGVmaW5pdGlvbiBPYmplY3Q6DQogKg0KICogYGBganMNCiAqICAgdmFyIG15TW9kdWxlID0gYW5ndWxhci5tb2R1bGUoLi4uKTsNCiAqDQogKiAgIG15TW9kdWxlLmRpcmVjdGl2ZSgnZGlyZWN0aXZlTmFtZScsIGZ1bmN0aW9uIGZhY3RvcnkoaW5qZWN0YWJsZXMpIHsNCiAqICAgICB2YXIgZGlyZWN0aXZlRGVmaW5pdGlvbk9iamVjdCA9IHsNCiAqICAgICAgIHByaW9yaXR5OiAwLA0KICogICAgICAgdGVtcGxhdGU6ICc8ZGl2PjwvZGl2PicsIC8vIG9yIC8vIGZ1bmN0aW9uKHRFbGVtZW50LCB0QXR0cnMpIHsgLi4uIH0sDQogKiAgICAgICAvLyBvcg0KICogICAgICAgLy8gdGVtcGxhdGVVcmw6ICdkaXJlY3RpdmUuaHRtbCcsIC8vIG9yIC8vIGZ1bmN0aW9uKHRFbGVtZW50LCB0QXR0cnMpIHsgLi4uIH0sDQogKiAgICAgICB0cmFuc2NsdWRlOiBmYWxzZSwNCiAqICAgICAgIHJlc3RyaWN0OiAnQScsDQogKiAgICAgICB0ZW1wbGF0ZU5hbWVzcGFjZTogJ2h0bWwnLA0KICogICAgICAgc2NvcGU6IGZhbHNlLA0KICogICAgICAgY29udHJvbGxlcjogZnVuY3Rpb24oJHNjb3BlLCAkZWxlbWVudCwgJGF0dHJzLCAkdHJhbnNjbHVkZSwgb3RoZXJJbmplY3RhYmxlcykgeyAuLi4gfSwNCiAqICAgICAgIGNvbnRyb2xsZXJBczogJ3N0cmluZ0FsaWFzJywNCiAqICAgICAgIHJlcXVpcmU6ICdzaWJsaW5nRGlyZWN0aXZlTmFtZScsIC8vIG9yIC8vIFsnXnBhcmVudERpcmVjdGl2ZU5hbWUnLCAnP29wdGlvbmFsRGlyZWN0aXZlTmFtZScsICc/Xm9wdGlvbmFsUGFyZW50J10sDQogKiAgICAgICBjb21waWxlOiBmdW5jdGlvbiBjb21waWxlKHRFbGVtZW50LCB0QXR0cnMsIHRyYW5zY2x1ZGUpIHsNCiAqICAgICAgICAgcmV0dXJuIHsNCiAqICAgICAgICAgICBwcmU6IGZ1bmN0aW9uIHByZUxpbmsoc2NvcGUsIGlFbGVtZW50LCBpQXR0cnMsIGNvbnRyb2xsZXIpIHsgLi4uIH0sDQogKiAgICAgICAgICAgcG9zdDogZnVuY3Rpb24gcG9zdExpbmsoc2NvcGUsIGlFbGVtZW50LCBpQXR0cnMsIGNvbnRyb2xsZXIpIHsgLi4uIH0NCiAqICAgICAgICAgfQ0KICogICAgICAgICAvLyBvcg0KICogICAgICAgICAvLyByZXR1cm4gZnVuY3Rpb24gcG9zdExpbmsoIC4uLiApIHsgLi4uIH0NCiAqICAgICAgIH0sDQogKiAgICAgICAvLyBvcg0KICogICAgICAgLy8gbGluazogew0KICogICAgICAgLy8gIHByZTogZnVuY3Rpb24gcHJlTGluayhzY29wZSwgaUVsZW1lbnQsIGlBdHRycywgY29udHJvbGxlcikgeyAuLi4gfSwNCiAqICAgICAgIC8vICBwb3N0OiBmdW5jdGlvbiBwb3N0TGluayhzY29wZSwgaUVsZW1lbnQsIGlBdHRycywgY29udHJvbGxlcikgeyAuLi4gfQ0KICogICAgICAgLy8gfQ0KICogICAgICAgLy8gb3INCiAqICAgICAgIC8vIGxpbms6IGZ1bmN0aW9uIHBvc3RMaW5rKCAuLi4gKSB7IC4uLiB9DQogKiAgICAgfTsNCiAqICAgICByZXR1cm4gZGlyZWN0aXZlRGVmaW5pdGlvbk9iamVjdDsNCiAqICAgfSk7DQogKiBgYGANCiAqDQogKiA8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4NCiAqICoqTm90ZToqKiBBbnkgdW5zcGVjaWZpZWQgb3B0aW9ucyB3aWxsIHVzZSB0aGUgZGVmYXVsdCB2YWx1ZS4gWW91IGNhbiBzZWUgdGhlIGRlZmF1bHQgdmFsdWVzIGJlbG93Lg0KICogPC9kaXY+DQogKg0KICogVGhlcmVmb3JlIHRoZSBhYm92ZSBjYW4gYmUgc2ltcGxpZmllZCBhczoNCiAqDQogKiBgYGBqcw0KICogICB2YXIgbXlNb2R1bGUgPSBhbmd1bGFyLm1vZHVsZSguLi4pOw0KICoNCiAqICAgbXlNb2R1bGUuZGlyZWN0aXZlKCdkaXJlY3RpdmVOYW1lJywgZnVuY3Rpb24gZmFjdG9yeShpbmplY3RhYmxlcykgew0KICogICAgIHZhciBkaXJlY3RpdmVEZWZpbml0aW9uT2JqZWN0ID0gew0KICogICAgICAgbGluazogZnVuY3Rpb24gcG9zdExpbmsoc2NvcGUsIGlFbGVtZW50LCBpQXR0cnMpIHsgLi4uIH0NCiAqICAgICB9Ow0KICogICAgIHJldHVybiBkaXJlY3RpdmVEZWZpbml0aW9uT2JqZWN0Ow0KICogICAgIC8vIG9yDQogKiAgICAgLy8gcmV0dXJuIGZ1bmN0aW9uIHBvc3RMaW5rKHNjb3BlLCBpRWxlbWVudCwgaUF0dHJzKSB7IC4uLiB9DQogKiAgIH0pOw0KICogYGBgDQogKg0KICoNCiAqDQogKiAjIyMgRGlyZWN0aXZlIERlZmluaXRpb24gT2JqZWN0DQogKg0KICogVGhlIGRpcmVjdGl2ZSBkZWZpbml0aW9uIG9iamVjdCBwcm92aWRlcyBpbnN0cnVjdGlvbnMgdG8gdGhlIHtAbGluayBuZy4kY29tcGlsZQ0KICogY29tcGlsZXJ9LiBUaGUgYXR0cmlidXRlcyBhcmU6DQogKg0KICogIyMjIyBgbXVsdGlFbGVtZW50YA0KICogV2hlbiB0aGlzIHByb3BlcnR5IGlzIHNldCB0byB0cnVlLCB0aGUgSFRNTCBjb21waWxlciB3aWxsIGNvbGxlY3QgRE9NIG5vZGVzIGJldHdlZW4NCiAqIG5vZGVzIHdpdGggdGhlIGF0dHJpYnV0ZXMgYGRpcmVjdGl2ZS1uYW1lLXN0YXJ0YCBhbmQgYGRpcmVjdGl2ZS1uYW1lLWVuZGAsIGFuZCBncm91cCB0aGVtDQogKiB0b2dldGhlciBhcyB0aGUgZGlyZWN0aXZlIGVsZW1lbnRzLiBJdCBpcyByZWNvbW1lbmRlZCB0aGF0IHRoaXMgZmVhdHVyZSBiZSB1c2VkIG9uIGRpcmVjdGl2ZXMNCiAqIHdoaWNoIGFyZSBub3Qgc3RyaWN0bHkgYmVoYXZpb3VyYWwgKHN1Y2ggYXMge0BsaW5rIG5nQ2xpY2t9KSwgYW5kIHdoaWNoDQogKiBkbyBub3QgbWFuaXB1bGF0ZSBvciByZXBsYWNlIGNoaWxkIG5vZGVzIChzdWNoIGFzIHtAbGluayBuZ0luY2x1ZGV9KS4NCiAqDQogKiAjIyMjIGBwcmlvcml0eWANCiAqIFdoZW4gdGhlcmUgYXJlIG11bHRpcGxlIGRpcmVjdGl2ZXMgZGVmaW5lZCBvbiBhIHNpbmdsZSBET00gZWxlbWVudCwgc29tZXRpbWVzIGl0DQogKiBpcyBuZWNlc3NhcnkgdG8gc3BlY2lmeSB0aGUgb3JkZXIgaW4gd2hpY2ggdGhlIGRpcmVjdGl2ZXMgYXJlIGFwcGxpZWQuIFRoZSBgcHJpb3JpdHlgIGlzIHVzZWQNCiAqIHRvIHNvcnQgdGhlIGRpcmVjdGl2ZXMgYmVmb3JlIHRoZWlyIGBjb21waWxlYCBmdW5jdGlvbnMgZ2V0IGNhbGxlZC4gUHJpb3JpdHkgaXMgZGVmaW5lZCBhcyBhDQogKiBudW1iZXIuIERpcmVjdGl2ZXMgd2l0aCBncmVhdGVyIG51bWVyaWNhbCBgcHJpb3JpdHlgIGFyZSBjb21waWxlZCBmaXJzdC4gUHJlLWxpbmsgZnVuY3Rpb25zDQogKiBhcmUgYWxzbyBydW4gaW4gcHJpb3JpdHkgb3JkZXIsIGJ1dCBwb3N0LWxpbmsgZnVuY3Rpb25zIGFyZSBydW4gaW4gcmV2ZXJzZSBvcmRlci4gVGhlIG9yZGVyDQogKiBvZiBkaXJlY3RpdmVzIHdpdGggdGhlIHNhbWUgcHJpb3JpdHkgaXMgdW5kZWZpbmVkLiBUaGUgZGVmYXVsdCBwcmlvcml0eSBpcyBgMGAuDQogKg0KICogIyMjIyBgdGVybWluYWxgDQogKiBJZiBzZXQgdG8gdHJ1ZSB0aGVuIHRoZSBjdXJyZW50IGBwcmlvcml0eWAgd2lsbCBiZSB0aGUgbGFzdCBzZXQgb2YgZGlyZWN0aXZlcw0KICogd2hpY2ggd2lsbCBleGVjdXRlIChhbnkgZGlyZWN0aXZlcyBhdCB0aGUgY3VycmVudCBwcmlvcml0eSB3aWxsIHN0aWxsIGV4ZWN1dGUNCiAqIGFzIHRoZSBvcmRlciBvZiBleGVjdXRpb24gb24gc2FtZSBgcHJpb3JpdHlgIGlzIHVuZGVmaW5lZCkuIE5vdGUgdGhhdCBleHByZXNzaW9ucw0KICogYW5kIG90aGVyIGRpcmVjdGl2ZXMgdXNlZCBpbiB0aGUgZGlyZWN0aXZlJ3MgdGVtcGxhdGUgd2lsbCBhbHNvIGJlIGV4Y2x1ZGVkIGZyb20gZXhlY3V0aW9uLg0KICoNCiAqICMjIyMgYHNjb3BlYA0KICogKipJZiBzZXQgdG8gYHRydWVgLCoqIHRoZW4gYSBuZXcgc2NvcGUgd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIGRpcmVjdGl2ZS4gSWYgbXVsdGlwbGUgZGlyZWN0aXZlcyBvbiB0aGUNCiAqIHNhbWUgZWxlbWVudCByZXF1ZXN0IGEgbmV3IHNjb3BlLCBvbmx5IG9uZSBuZXcgc2NvcGUgaXMgY3JlYXRlZC4gVGhlIG5ldyBzY29wZSBydWxlIGRvZXMgbm90DQogKiBhcHBseSBmb3IgdGhlIHJvb3Qgb2YgdGhlIHRlbXBsYXRlIHNpbmNlIHRoZSByb290IG9mIHRoZSB0ZW1wbGF0ZSBhbHdheXMgZ2V0cyBhIG5ldyBzY29wZS4NCiAqDQogKiAqKklmIHNldCB0byBge31gIChvYmplY3QgaGFzaCksKiogdGhlbiBhIG5ldyAiaXNvbGF0ZSIgc2NvcGUgaXMgY3JlYXRlZC4gVGhlICdpc29sYXRlJyBzY29wZSBkaWZmZXJzIGZyb20NCiAqIG5vcm1hbCBzY29wZSBpbiB0aGF0IGl0IGRvZXMgbm90IHByb3RvdHlwaWNhbGx5IGluaGVyaXQgZnJvbSB0aGUgcGFyZW50IHNjb3BlLiBUaGlzIGlzIHVzZWZ1bA0KICogd2hlbiBjcmVhdGluZyByZXVzYWJsZSBjb21wb25lbnRzLCB3aGljaCBzaG91bGQgbm90IGFjY2lkZW50YWxseSByZWFkIG9yIG1vZGlmeSBkYXRhIGluIHRoZQ0KICogcGFyZW50IHNjb3BlLg0KICoNCiAqIFRoZSAnaXNvbGF0ZScgc2NvcGUgdGFrZXMgYW4gb2JqZWN0IGhhc2ggd2hpY2ggZGVmaW5lcyBhIHNldCBvZiBsb2NhbCBzY29wZSBwcm9wZXJ0aWVzDQogKiBkZXJpdmVkIGZyb20gdGhlIHBhcmVudCBzY29wZS4gVGhlc2UgbG9jYWwgcHJvcGVydGllcyBhcmUgdXNlZnVsIGZvciBhbGlhc2luZyB2YWx1ZXMgZm9yDQogKiB0ZW1wbGF0ZXMuIExvY2FscyBkZWZpbml0aW9uIGlzIGEgaGFzaCBvZiBsb2NhbCBzY29wZSBwcm9wZXJ0eSB0byBpdHMgc291cmNlOg0KICoNCiAqICogYEBgIG9yIGBAYXR0cmAgLSBiaW5kIGEgbG9jYWwgc2NvcGUgcHJvcGVydHkgdG8gdGhlIHZhbHVlIG9mIERPTSBhdHRyaWJ1dGUuIFRoZSByZXN1bHQgaXMNCiAqICAgYWx3YXlzIGEgc3RyaW5nIHNpbmNlIERPTSBhdHRyaWJ1dGVzIGFyZSBzdHJpbmdzLiBJZiBubyBgYXR0cmAgbmFtZSBpcyBzcGVjaWZpZWQgIHRoZW4gdGhlDQogKiAgIGF0dHJpYnV0ZSBuYW1lIGlzIGFzc3VtZWQgdG8gYmUgdGhlIHNhbWUgYXMgdGhlIGxvY2FsIG5hbWUuDQogKiAgIEdpdmVuIGA8d2lkZ2V0IG15LWF0dHI9ImhlbGxvIHt7bmFtZX19Ij5gIGFuZCB3aWRnZXQgZGVmaW5pdGlvbg0KICogICBvZiBgc2NvcGU6IHsgbG9jYWxOYW1lOidAbXlBdHRyJyB9YCwgdGhlbiB3aWRnZXQgc2NvcGUgcHJvcGVydHkgYGxvY2FsTmFtZWAgd2lsbCByZWZsZWN0DQogKiAgIHRoZSBpbnRlcnBvbGF0ZWQgdmFsdWUgb2YgYGhlbGxvIHt7bmFtZX19YC4gQXMgdGhlIGBuYW1lYCBhdHRyaWJ1dGUgY2hhbmdlcyBzbyB3aWxsIHRoZQ0KICogICBgbG9jYWxOYW1lYCBwcm9wZXJ0eSBvbiB0aGUgd2lkZ2V0IHNjb3BlLiBUaGUgYG5hbWVgIGlzIHJlYWQgZnJvbSB0aGUgcGFyZW50IHNjb3BlIChub3QNCiAqICAgY29tcG9uZW50IHNjb3BlKS4NCiAqDQogKiAqIGA9YCBvciBgPWF0dHJgIC0gc2V0IHVwIGJpLWRpcmVjdGlvbmFsIGJpbmRpbmcgYmV0d2VlbiBhIGxvY2FsIHNjb3BlIHByb3BlcnR5IGFuZCB0aGUNCiAqICAgcGFyZW50IHNjb3BlIHByb3BlcnR5IG9mIG5hbWUgZGVmaW5lZCB2aWEgdGhlIHZhbHVlIG9mIHRoZSBgYXR0cmAgYXR0cmlidXRlLiBJZiBubyBgYXR0cmANCiAqICAgbmFtZSBpcyBzcGVjaWZpZWQgdGhlbiB0aGUgYXR0cmlidXRlIG5hbWUgaXMgYXNzdW1lZCB0byBiZSB0aGUgc2FtZSBhcyB0aGUgbG9jYWwgbmFtZS4NCiAqICAgR2l2ZW4gYDx3aWRnZXQgbXktYXR0cj0icGFyZW50TW9kZWwiPmAgYW5kIHdpZGdldCBkZWZpbml0aW9uIG9mDQogKiAgIGBzY29wZTogeyBsb2NhbE1vZGVsOic9bXlBdHRyJyB9YCwgdGhlbiB3aWRnZXQgc2NvcGUgcHJvcGVydHkgYGxvY2FsTW9kZWxgIHdpbGwgcmVmbGVjdCB0aGUNCiAqICAgdmFsdWUgb2YgYHBhcmVudE1vZGVsYCBvbiB0aGUgcGFyZW50IHNjb3BlLiBBbnkgY2hhbmdlcyB0byBgcGFyZW50TW9kZWxgIHdpbGwgYmUgcmVmbGVjdGVkDQogKiAgIGluIGBsb2NhbE1vZGVsYCBhbmQgYW55IGNoYW5nZXMgaW4gYGxvY2FsTW9kZWxgIHdpbGwgcmVmbGVjdCBpbiBgcGFyZW50TW9kZWxgLiBJZiB0aGUgcGFyZW50DQogKiAgIHNjb3BlIHByb3BlcnR5IGRvZXNuJ3QgZXhpc3QsIGl0IHdpbGwgdGhyb3cgYSBOT05fQVNTSUdOQUJMRV9NT0RFTF9FWFBSRVNTSU9OIGV4Y2VwdGlvbi4gWW91DQogKiAgIGNhbiBhdm9pZCB0aGlzIGJlaGF2aW9yIHVzaW5nIGA9P2Agb3IgYD0/YXR0cmAgaW4gb3JkZXIgdG8gZmxhZyB0aGUgcHJvcGVydHkgYXMgb3B0aW9uYWwuIElmDQogKiAgIHlvdSB3YW50IHRvIHNoYWxsb3cgd2F0Y2ggZm9yIGNoYW5nZXMgKGkuZS4gJHdhdGNoQ29sbGVjdGlvbiBpbnN0ZWFkIG9mICR3YXRjaCkgeW91IGNhbiB1c2UNCiAqICAgYD0qYCBvciBgPSphdHRyYCAoYD0qP2Agb3IgYD0qP2F0dHJgIGlmIHRoZSBwcm9wZXJ0eSBpcyBvcHRpb25hbCkuDQogKg0KICogKiBgJmAgb3IgYCZhdHRyYCAtIHByb3ZpZGVzIGEgd2F5IHRvIGV4ZWN1dGUgYW4gZXhwcmVzc2lvbiBpbiB0aGUgY29udGV4dCBvZiB0aGUgcGFyZW50IHNjb3BlLg0KICogICBJZiBubyBgYXR0cmAgbmFtZSBpcyBzcGVjaWZpZWQgdGhlbiB0aGUgYXR0cmlidXRlIG5hbWUgaXMgYXNzdW1lZCB0byBiZSB0aGUgc2FtZSBhcyB0aGUNCiAqICAgbG9jYWwgbmFtZS4gR2l2ZW4gYDx3aWRnZXQgbXktYXR0cj0iY291bnQgPSBjb3VudCArIHZhbHVlIj5gIGFuZCB3aWRnZXQgZGVmaW5pdGlvbiBvZg0KICogICBgc2NvcGU6IHsgbG9jYWxGbjonJm15QXR0cicgfWAsIHRoZW4gaXNvbGF0ZSBzY29wZSBwcm9wZXJ0eSBgbG9jYWxGbmAgd2lsbCBwb2ludCB0bw0KICogICBhIGZ1bmN0aW9uIHdyYXBwZXIgZm9yIHRoZSBgY291bnQgPSBjb3VudCArIHZhbHVlYCBleHByZXNzaW9uLiBPZnRlbiBpdCdzIGRlc2lyYWJsZSB0bw0KICogICBwYXNzIGRhdGEgZnJvbSB0aGUgaXNvbGF0ZWQgc2NvcGUgdmlhIGFuIGV4cHJlc3Npb24gdG8gdGhlIHBhcmVudCBzY29wZSwgdGhpcyBjYW4gYmUNCiAqICAgZG9uZSBieSBwYXNzaW5nIGEgbWFwIG9mIGxvY2FsIHZhcmlhYmxlIG5hbWVzIGFuZCB2YWx1ZXMgaW50byB0aGUgZXhwcmVzc2lvbiB3cmFwcGVyIGZuLg0KICogICBGb3IgZXhhbXBsZSwgaWYgdGhlIGV4cHJlc3Npb24gaXMgYGluY3JlbWVudChhbW91bnQpYCB0aGVuIHdlIGNhbiBzcGVjaWZ5IHRoZSBhbW91bnQgdmFsdWUNCiAqICAgYnkgY2FsbGluZyB0aGUgYGxvY2FsRm5gIGFzIGBsb2NhbEZuKHthbW91bnQ6IDIyfSlgLg0KICoNCiAqDQogKiAjIyMjIGBiaW5kVG9Db250cm9sbGVyYA0KICogV2hlbiBhbiBpc29sYXRlIHNjb3BlIGlzIHVzZWQgZm9yIGEgY29tcG9uZW50IChzZWUgYWJvdmUpLCBhbmQgYGNvbnRyb2xsZXJBc2AgaXMgdXNlZCwgYGJpbmRUb0NvbnRyb2xsZXI6IHRydWVgIHdpbGwNCiAqIGFsbG93IGEgY29tcG9uZW50IHRvIGhhdmUgaXRzIHByb3BlcnRpZXMgYm91bmQgdG8gdGhlIGNvbnRyb2xsZXIsIHJhdGhlciB0aGFuIHRvIHNjb3BlLiBXaGVuIHRoZSBjb250cm9sbGVyDQogKiBpcyBpbnN0YW50aWF0ZWQsIHRoZSBpbml0aWFsIHZhbHVlcyBvZiB0aGUgaXNvbGF0ZSBzY29wZSBiaW5kaW5ncyBhcmUgYWxyZWFkeSBhdmFpbGFibGUuDQogKg0KICogIyMjIyBgY29udHJvbGxlcmANCiAqIENvbnRyb2xsZXIgY29uc3RydWN0b3IgZnVuY3Rpb24uIFRoZSBjb250cm9sbGVyIGlzIGluc3RhbnRpYXRlZCBiZWZvcmUgdGhlDQogKiBwcmUtbGlua2luZyBwaGFzZSBhbmQgaXQgaXMgc2hhcmVkIHdpdGggb3RoZXIgZGlyZWN0aXZlcyAoc2VlDQogKiBgcmVxdWlyZWAgYXR0cmlidXRlKS4gVGhpcyBhbGxvd3MgdGhlIGRpcmVjdGl2ZXMgdG8gY29tbXVuaWNhdGUgd2l0aCBlYWNoIG90aGVyIGFuZCBhdWdtZW50DQogKiBlYWNoIG90aGVyJ3MgYmVoYXZpb3IuIFRoZSBjb250cm9sbGVyIGlzIGluamVjdGFibGUgKGFuZCBzdXBwb3J0cyBicmFja2V0IG5vdGF0aW9uKSB3aXRoIHRoZSBmb2xsb3dpbmcgbG9jYWxzOg0KICoNCiAqICogYCRzY29wZWAgLSBDdXJyZW50IHNjb3BlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZWxlbWVudA0KICogKiBgJGVsZW1lbnRgIC0gQ3VycmVudCBlbGVtZW50DQogKiAqIGAkYXR0cnNgIC0gQ3VycmVudCBhdHRyaWJ1dGVzIG9iamVjdCBmb3IgdGhlIGVsZW1lbnQNCiAqICogYCR0cmFuc2NsdWRlYCAtIEEgdHJhbnNjbHVkZSBsaW5raW5nIGZ1bmN0aW9uIHByZS1ib3VuZCB0byB0aGUgY29ycmVjdCB0cmFuc2NsdXNpb24gc2NvcGU6DQogKiAgIGBmdW5jdGlvbihbc2NvcGVdLCBjbG9uZUxpbmtpbmdGbiwgZnV0dXJlUGFyZW50RWxlbWVudClgLg0KICogICAgKiBgc2NvcGVgOiBvcHRpb25hbCBhcmd1bWVudCB0byBvdmVycmlkZSB0aGUgc2NvcGUuDQogKiAgICAqIGBjbG9uZUxpbmtpbmdGbmA6IG9wdGlvbmFsIGFyZ3VtZW50IHRvIGNyZWF0ZSBjbG9uZXMgb2YgdGhlIG9yaWdpbmFsIHRyYW5zY2x1ZGVkIGNvbnRlbnQuDQogKiAgICAqIGBmdXR1cmVQYXJlbnRFbGVtZW50YDoNCiAqICAgICAgICAqIGRlZmluZXMgdGhlIHBhcmVudCB0byB3aGljaCB0aGUgYGNsb25lTGlua2luZ0ZuYCB3aWxsIGFkZCB0aGUgY2xvbmVkIGVsZW1lbnRzLg0KICogICAgICAgICogZGVmYXVsdDogYCRlbGVtZW50LnBhcmVudCgpYCByZXNwLiBgJGVsZW1lbnRgIGZvciBgdHJhbnNjbHVkZTonZWxlbWVudCdgIHJlc3AuIGB0cmFuc2NsdWRlOnRydWVgLg0KICogICAgICAgICogb25seSBuZWVkZWQgZm9yIHRyYW5zY2x1ZGVzIHRoYXQgYXJlIGFsbG93ZWQgdG8gY29udGFpbiBub24gaHRtbCBlbGVtZW50cyAoZS5nLiBTVkcgZWxlbWVudHMpDQogKiAgICAgICAgICBhbmQgd2hlbiB0aGUgYGNsb25lTGlua2luRm5gIGlzIHBhc3NlZCwNCiAqICAgICAgICAgIGFzIHRob3NlIGVsZW1lbnRzIG5lZWQgdG8gY3JlYXRlZCBhbmQgY2xvbmVkIGluIGEgc3BlY2lhbCB3YXkgd2hlbiB0aGV5IGFyZSBkZWZpbmVkIG91dHNpZGUgdGhlaXINCiAqICAgICAgICAgIHVzdWFsIGNvbnRhaW5lcnMgKGUuZy4gbGlrZSBgPHN2Zz5gKS4NCiAqICAgICAgICAqIFNlZSBhbHNvIHRoZSBgZGlyZWN0aXZlLnRlbXBsYXRlTmFtZXNwYWNlYCBwcm9wZXJ0eS4NCiAqDQogKg0KICogIyMjIyBgcmVxdWlyZWANCiAqIFJlcXVpcmUgYW5vdGhlciBkaXJlY3RpdmUgYW5kIGluamVjdCBpdHMgY29udHJvbGxlciBhcyB0aGUgZm91cnRoIGFyZ3VtZW50IHRvIHRoZSBsaW5raW5nIGZ1bmN0aW9uLiBUaGUNCiAqIGByZXF1aXJlYCB0YWtlcyBhIHN0cmluZyBuYW1lIChvciBhcnJheSBvZiBzdHJpbmdzKSBvZiB0aGUgZGlyZWN0aXZlKHMpIHRvIHBhc3MgaW4uIElmIGFuIGFycmF5IGlzIHVzZWQsIHRoZQ0KICogaW5qZWN0ZWQgYXJndW1lbnQgd2lsbCBiZSBhbiBhcnJheSBpbiBjb3JyZXNwb25kaW5nIG9yZGVyLiBJZiBubyBzdWNoIGRpcmVjdGl2ZSBjYW4gYmUNCiAqIGZvdW5kLCBvciBpZiB0aGUgZGlyZWN0aXZlIGRvZXMgbm90IGhhdmUgYSBjb250cm9sbGVyLCB0aGVuIGFuIGVycm9yIGlzIHJhaXNlZC4gVGhlIG5hbWUgY2FuIGJlIHByZWZpeGVkIHdpdGg6DQogKg0KICogKiAobm8gcHJlZml4KSAtIExvY2F0ZSB0aGUgcmVxdWlyZWQgY29udHJvbGxlciBvbiB0aGUgY3VycmVudCBlbGVtZW50LiBUaHJvdyBhbiBlcnJvciBpZiBub3QgZm91bmQuDQogKiAqIGA/YCAtIEF0dGVtcHQgdG8gbG9jYXRlIHRoZSByZXF1aXJlZCBjb250cm9sbGVyIG9yIHBhc3MgYG51bGxgIHRvIHRoZSBgbGlua2AgZm4gaWYgbm90IGZvdW5kLg0KICogKiBgXmAgLSBMb2NhdGUgdGhlIHJlcXVpcmVkIGNvbnRyb2xsZXIgYnkgc2VhcmNoaW5nIHRoZSBlbGVtZW50IGFuZCBpdHMgcGFyZW50cy4gVGhyb3cgYW4gZXJyb3IgaWYgbm90IGZvdW5kLg0KICogKiBgXl5gIC0gTG9jYXRlIHRoZSByZXF1aXJlZCBjb250cm9sbGVyIGJ5IHNlYXJjaGluZyB0aGUgZWxlbWVudCdzIHBhcmVudHMuIFRocm93IGFuIGVycm9yIGlmIG5vdCBmb3VuZC4NCiAqICogYD9eYCAtIEF0dGVtcHQgdG8gbG9jYXRlIHRoZSByZXF1aXJlZCBjb250cm9sbGVyIGJ5IHNlYXJjaGluZyB0aGUgZWxlbWVudCBhbmQgaXRzIHBhcmVudHMgb3IgcGFzcw0KICogICBgbnVsbGAgdG8gdGhlIGBsaW5rYCBmbiBpZiBub3QgZm91bmQuDQogKiAqIGA/Xl5gIC0gQXR0ZW1wdCB0byBsb2NhdGUgdGhlIHJlcXVpcmVkIGNvbnRyb2xsZXIgYnkgc2VhcmNoaW5nIHRoZSBlbGVtZW50J3MgcGFyZW50cywgb3IgcGFzcw0KICogICBgbnVsbGAgdG8gdGhlIGBsaW5rYCBmbiBpZiBub3QgZm91bmQuDQogKg0KICoNCiAqICMjIyMgYGNvbnRyb2xsZXJBc2ANCiAqIENvbnRyb2xsZXIgYWxpYXMgYXQgdGhlIGRpcmVjdGl2ZSBzY29wZS4gQW4gYWxpYXMgZm9yIHRoZSBjb250cm9sbGVyIHNvIGl0DQogKiBjYW4gYmUgcmVmZXJlbmNlZCBhdCB0aGUgZGlyZWN0aXZlIHRlbXBsYXRlLiBUaGUgZGlyZWN0aXZlIG5lZWRzIHRvIGRlZmluZSBhIHNjb3BlIGZvciB0aGlzDQogKiBjb25maWd1cmF0aW9uIHRvIGJlIHVzZWQuIFVzZWZ1bCBpbiB0aGUgY2FzZSB3aGVuIGRpcmVjdGl2ZSBpcyB1c2VkIGFzIGNvbXBvbmVudC4NCiAqDQogKg0KICogIyMjIyBgcmVzdHJpY3RgDQogKiBTdHJpbmcgb2Ygc3Vic2V0IG9mIGBFQUNNYCB3aGljaCByZXN0cmljdHMgdGhlIGRpcmVjdGl2ZSB0byBhIHNwZWNpZmljIGRpcmVjdGl2ZQ0KICogZGVjbGFyYXRpb24gc3R5bGUuIElmIG9taXR0ZWQsIHRoZSBkZWZhdWx0cyAoZWxlbWVudHMgYW5kIGF0dHJpYnV0ZXMpIGFyZSB1c2VkLg0KICoNCiAqICogYEVgIC0gRWxlbWVudCBuYW1lIChkZWZhdWx0KTogYDxteS1kaXJlY3RpdmU+PC9teS1kaXJlY3RpdmU+YA0KICogKiBgQWAgLSBBdHRyaWJ1dGUgKGRlZmF1bHQpOiBgPGRpdiBteS1kaXJlY3RpdmU9ImV4cCI+PC9kaXY+YA0KICogKiBgQ2AgLSBDbGFzczogYDxkaXYgY2xhc3M9Im15LWRpcmVjdGl2ZTogZXhwOyI+PC9kaXY+YA0KICogKiBgTWAgLSBDb21tZW50OiBgPCEtLSBkaXJlY3RpdmU6IG15LWRpcmVjdGl2ZSBleHAgLS0+YA0KICoNCiAqDQogKiAjIyMjIGB0ZW1wbGF0ZU5hbWVzcGFjZWANCiAqIFN0cmluZyByZXByZXNlbnRpbmcgdGhlIGRvY3VtZW50IHR5cGUgdXNlZCBieSB0aGUgbWFya3VwIGluIHRoZSB0ZW1wbGF0ZS4NCiAqIEFuZ3VsYXJKUyBuZWVkcyB0aGlzIGluZm9ybWF0aW9uIGFzIHRob3NlIGVsZW1lbnRzIG5lZWQgdG8gYmUgY3JlYXRlZCBhbmQgY2xvbmVkDQogKiBpbiBhIHNwZWNpYWwgd2F5IHdoZW4gdGhleSBhcmUgZGVmaW5lZCBvdXRzaWRlIHRoZWlyIHVzdWFsIGNvbnRhaW5lcnMgbGlrZSBgPHN2Zz5gIGFuZCBgPG1hdGg+YC4NCiAqDQogKiAqIGBodG1sYCAtIEFsbCByb290IG5vZGVzIGluIHRoZSB0ZW1wbGF0ZSBhcmUgSFRNTC4gUm9vdCBub2RlcyBtYXkgYWxzbyBiZQ0KICogICB0b3AtbGV2ZWwgZWxlbWVudHMgc3VjaCBhcyBgPHN2Zz5gIG9yIGA8bWF0aD5gLg0KICogKiBgc3ZnYCAtIFRoZSByb290IG5vZGVzIGluIHRoZSB0ZW1wbGF0ZSBhcmUgU1ZHIGVsZW1lbnRzIChleGNsdWRpbmcgYDxtYXRoPmApLg0KICogKiBgbWF0aGAgLSBUaGUgcm9vdCBub2RlcyBpbiB0aGUgdGVtcGxhdGUgYXJlIE1hdGhNTCBlbGVtZW50cyAoZXhjbHVkaW5nIGA8c3ZnPmApLg0KICoNCiAqIElmIG5vIGB0ZW1wbGF0ZU5hbWVzcGFjZWAgaXMgc3BlY2lmaWVkLCB0aGVuIHRoZSBuYW1lc3BhY2UgaXMgY29uc2lkZXJlZCB0byBiZSBgaHRtbGAuDQogKg0KICogIyMjIyBgdGVtcGxhdGVgDQogKiBIVE1MIG1hcmt1cCB0aGF0IG1heToNCiAqICogUmVwbGFjZSB0aGUgY29udGVudHMgb2YgdGhlIGRpcmVjdGl2ZSdzIGVsZW1lbnQgKGRlZmF1bHQpLg0KICogKiBSZXBsYWNlIHRoZSBkaXJlY3RpdmUncyBlbGVtZW50IGl0c2VsZiAoaWYgYHJlcGxhY2VgIGlzIHRydWUgLSBERVBSRUNBVEVEKS4NCiAqICogV3JhcCB0aGUgY29udGVudHMgb2YgdGhlIGRpcmVjdGl2ZSdzIGVsZW1lbnQgKGlmIGB0cmFuc2NsdWRlYCBpcyB0cnVlKS4NCiAqDQogKiBWYWx1ZSBtYXkgYmU6DQogKg0KICogKiBBIHN0cmluZy4gRm9yIGV4YW1wbGUgYDxkaXYgcmVkLW9uLWhvdmVyPnt7ZGVsZXRlX3N0cn19PC9kaXY+YC4NCiAqICogQSBmdW5jdGlvbiB3aGljaCB0YWtlcyB0d28gYXJndW1lbnRzIGB0RWxlbWVudGAgYW5kIGB0QXR0cnNgIChkZXNjcmliZWQgaW4gdGhlIGBjb21waWxlYA0KICogICBmdW5jdGlvbiBhcGkgYmVsb3cpIGFuZCByZXR1cm5zIGEgc3RyaW5nIHZhbHVlLg0KICoNCiAqDQogKiAjIyMjIGB0ZW1wbGF0ZVVybGANCiAqIFRoaXMgaXMgc2ltaWxhciB0byBgdGVtcGxhdGVgIGJ1dCB0aGUgdGVtcGxhdGUgaXMgbG9hZGVkIGZyb20gdGhlIHNwZWNpZmllZCBVUkwsIGFzeW5jaHJvbm91c2x5Lg0KICoNCiAqIEJlY2F1c2UgdGVtcGxhdGUgbG9hZGluZyBpcyBhc3luY2hyb25vdXMgdGhlIGNvbXBpbGVyIHdpbGwgc3VzcGVuZCBjb21waWxhdGlvbiBvZiBkaXJlY3RpdmVzIG9uIHRoYXQgZWxlbWVudA0KICogZm9yIGxhdGVyIHdoZW4gdGhlIHRlbXBsYXRlIGhhcyBiZWVuIHJlc29sdmVkLiAgSW4gdGhlIG1lYW50aW1lIGl0IHdpbGwgY29udGludWUgdG8gY29tcGlsZSBhbmQgbGluaw0KICogc2libGluZyBhbmQgcGFyZW50IGVsZW1lbnRzIGFzIHRob3VnaCB0aGlzIGVsZW1lbnQgaGFkIG5vdCBjb250YWluZWQgYW55IGRpcmVjdGl2ZXMuDQogKg0KICogVGhlIGNvbXBpbGVyIGRvZXMgbm90IHN1c3BlbmQgdGhlIGVudGlyZSBjb21waWxhdGlvbiB0byB3YWl0IGZvciB0ZW1wbGF0ZXMgdG8gYmUgbG9hZGVkIGJlY2F1c2UgdGhpcw0KICogd291bGQgcmVzdWx0IGluIHRoZSB3aG9sZSBhcHAgInN0YWxsaW5nIiB1bnRpbCBhbGwgdGVtcGxhdGVzIGFyZSBsb2FkZWQgYXN5bmNocm9ub3VzbHkgLSBldmVuIGluIHRoZQ0KICogY2FzZSB3aGVuIG9ubHkgb25lIGRlZXBseSBuZXN0ZWQgZGlyZWN0aXZlIGhhcyBgdGVtcGxhdGVVcmxgLg0KICoNCiAqIFRlbXBsYXRlIGxvYWRpbmcgaXMgYXN5bmNocm9ub3VzIGV2ZW4gaWYgdGhlIHRlbXBsYXRlIGhhcyBiZWVuIHByZWxvYWRlZCBpbnRvIHRoZSB7QGxpbmsgJHRlbXBsYXRlQ2FjaGV9DQogKg0KICogWW91IGNhbiBzcGVjaWZ5IGB0ZW1wbGF0ZVVybGAgYXMgYSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBVUkwgb3IgYXMgYSBmdW5jdGlvbiB3aGljaCB0YWtlcyB0d28NCiAqIGFyZ3VtZW50cyBgdEVsZW1lbnRgIGFuZCBgdEF0dHJzYCAoZGVzY3JpYmVkIGluIHRoZSBgY29tcGlsZWAgZnVuY3Rpb24gYXBpIGJlbG93KSBhbmQgcmV0dXJucw0KICogYSBzdHJpbmcgdmFsdWUgcmVwcmVzZW50aW5nIHRoZSB1cmwuICBJbiBlaXRoZXIgY2FzZSwgdGhlIHRlbXBsYXRlIFVSTCBpcyBwYXNzZWQgdGhyb3VnaCB7QGxpbmsNCiAqICRzY2UjZ2V0VHJ1c3RlZFJlc291cmNlVXJsICRzY2UuZ2V0VHJ1c3RlZFJlc291cmNlVXJsfS4NCiAqDQogKg0KICogIyMjIyBgcmVwbGFjZWAgKFsqREVQUkVDQVRFRCohXSwgd2lsbCBiZSByZW1vdmVkIGluIG5leHQgbWFqb3IgcmVsZWFzZSAtIGkuZS4gdjIuMCkNCiAqIHNwZWNpZnkgd2hhdCB0aGUgdGVtcGxhdGUgc2hvdWxkIHJlcGxhY2UuIERlZmF1bHRzIHRvIGBmYWxzZWAuDQogKg0KICogKiBgdHJ1ZWAgLSB0aGUgdGVtcGxhdGUgd2lsbCByZXBsYWNlIHRoZSBkaXJlY3RpdmUncyBlbGVtZW50Lg0KICogKiBgZmFsc2VgIC0gdGhlIHRlbXBsYXRlIHdpbGwgcmVwbGFjZSB0aGUgY29udGVudHMgb2YgdGhlIGRpcmVjdGl2ZSdzIGVsZW1lbnQuDQogKg0KICogVGhlIHJlcGxhY2VtZW50IHByb2Nlc3MgbWlncmF0ZXMgYWxsIG9mIHRoZSBhdHRyaWJ1dGVzIC8gY2xhc3NlcyBmcm9tIHRoZSBvbGQgZWxlbWVudCB0byB0aGUgbmV3DQogKiBvbmUuIFNlZSB0aGUge0BsaW5rIGd1aWRlL2RpcmVjdGl2ZSN0ZW1wbGF0ZS1leHBhbmRpbmctZGlyZWN0aXZlDQogKiBEaXJlY3RpdmVzIEd1aWRlfSBmb3IgYW4gZXhhbXBsZS4NCiAqDQogKiBUaGVyZSBhcmUgdmVyeSBmZXcgc2NlbmFyaW9zIHdoZXJlIGVsZW1lbnQgcmVwbGFjZW1lbnQgaXMgcmVxdWlyZWQgZm9yIHRoZSBhcHBsaWNhdGlvbiBmdW5jdGlvbiwNCiAqIHRoZSBtYWluIG9uZSBiZWluZyByZXVzYWJsZSBjdXN0b20gY29tcG9uZW50cyB0aGF0IGFyZSB1c2VkIHdpdGhpbiBTVkcgY29udGV4dHMNCiAqIChiZWNhdXNlIFNWRyBkb2Vzbid0IHdvcmsgd2l0aCBjdXN0b20gZWxlbWVudHMgaW4gdGhlIERPTSB0cmVlKS4NCiAqDQogKiAjIyMjIGB0cmFuc2NsdWRlYA0KICogRXh0cmFjdCB0aGUgY29udGVudHMgb2YgdGhlIGVsZW1lbnQgd2hlcmUgdGhlIGRpcmVjdGl2ZSBhcHBlYXJzIGFuZCBtYWtlIGl0IGF2YWlsYWJsZSB0byB0aGUgZGlyZWN0aXZlLg0KICogVGhlIGNvbnRlbnRzIGFyZSBjb21waWxlZCBhbmQgcHJvdmlkZWQgdG8gdGhlIGRpcmVjdGl2ZSBhcyBhICoqdHJhbnNjbHVzaW9uIGZ1bmN0aW9uKiouIFNlZSB0aGUNCiAqIHtAbGluayAkY29tcGlsZSN0cmFuc2NsdXNpb24gVHJhbnNjbHVzaW9ufSBzZWN0aW9uIGJlbG93Lg0KICoNCiAqIFRoZXJlIGFyZSB0d28ga2luZHMgb2YgdHJhbnNjbHVzaW9uIGRlcGVuZGluZyB1cG9uIHdoZXRoZXIgeW91IHdhbnQgdG8gdHJhbnNjbHVkZSBqdXN0IHRoZSBjb250ZW50cyBvZiB0aGUNCiAqIGRpcmVjdGl2ZSdzIGVsZW1lbnQgb3IgdGhlIGVudGlyZSBlbGVtZW50Og0KICoNCiAqICogYHRydWVgIC0gdHJhbnNjbHVkZSB0aGUgY29udGVudCAoaS5lLiB0aGUgY2hpbGQgbm9kZXMpIG9mIHRoZSBkaXJlY3RpdmUncyBlbGVtZW50Lg0KICogKiBgJ2VsZW1lbnQnYCAtIHRyYW5zY2x1ZGUgdGhlIHdob2xlIG9mIHRoZSBkaXJlY3RpdmUncyBlbGVtZW50IGluY2x1ZGluZyBhbnkgZGlyZWN0aXZlcyBvbiB0aGlzDQogKiAgIGVsZW1lbnQgdGhhdCBkZWZpbmVkIGF0IGEgbG93ZXIgcHJpb3JpdHkgdGhhbiB0aGlzIGRpcmVjdGl2ZS4gV2hlbiB1c2VkLCB0aGUgYHRlbXBsYXRlYA0KICogICBwcm9wZXJ0eSBpcyBpZ25vcmVkLg0KICoNCiAqDQogKiAjIyMjIGBjb21waWxlYA0KICoNCiAqIGBgYGpzDQogKiAgIGZ1bmN0aW9uIGNvbXBpbGUodEVsZW1lbnQsIHRBdHRycywgdHJhbnNjbHVkZSkgeyAuLi4gfQ0KICogYGBgDQogKg0KICogVGhlIGNvbXBpbGUgZnVuY3Rpb24gZGVhbHMgd2l0aCB0cmFuc2Zvcm1pbmcgdGhlIHRlbXBsYXRlIERPTS4gU2luY2UgbW9zdCBkaXJlY3RpdmVzIGRvIG5vdCBkbw0KICogdGVtcGxhdGUgdHJhbnNmb3JtYXRpb24sIGl0IGlzIG5vdCB1c2VkIG9mdGVuLiBUaGUgY29tcGlsZSBmdW5jdGlvbiB0YWtlcyB0aGUgZm9sbG93aW5nIGFyZ3VtZW50czoNCiAqDQogKiAgICogYHRFbGVtZW50YCAtIHRlbXBsYXRlIGVsZW1lbnQgLSBUaGUgZWxlbWVudCB3aGVyZSB0aGUgZGlyZWN0aXZlIGhhcyBiZWVuIGRlY2xhcmVkLiBJdCBpcw0KICogICAgIHNhZmUgdG8gZG8gdGVtcGxhdGUgdHJhbnNmb3JtYXRpb24gb24gdGhlIGVsZW1lbnQgYW5kIGNoaWxkIGVsZW1lbnRzIG9ubHkuDQogKg0KICogICAqIGB0QXR0cnNgIC0gdGVtcGxhdGUgYXR0cmlidXRlcyAtIE5vcm1hbGl6ZWQgbGlzdCBvZiBhdHRyaWJ1dGVzIGRlY2xhcmVkIG9uIHRoaXMgZWxlbWVudCBzaGFyZWQNCiAqICAgICBiZXR3ZWVuIGFsbCBkaXJlY3RpdmUgY29tcGlsZSBmdW5jdGlvbnMuDQogKg0KICogICAqIGB0cmFuc2NsdWRlYCAtICBbKkRFUFJFQ0FURUQqIV0gQSB0cmFuc2NsdWRlIGxpbmtpbmcgZnVuY3Rpb246IGBmdW5jdGlvbihzY29wZSwgY2xvbmVMaW5raW5nRm4pYA0KICoNCiAqIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXdhcm5pbmciPg0KICogKipOb3RlOioqIFRoZSB0ZW1wbGF0ZSBpbnN0YW5jZSBhbmQgdGhlIGxpbmsgaW5zdGFuY2UgbWF5IGJlIGRpZmZlcmVudCBvYmplY3RzIGlmIHRoZSB0ZW1wbGF0ZSBoYXMNCiAqIGJlZW4gY2xvbmVkLiBGb3IgdGhpcyByZWFzb24gaXQgaXMgKipub3QqKiBzYWZlIHRvIGRvIGFueXRoaW5nIG90aGVyIHRoYW4gRE9NIHRyYW5zZm9ybWF0aW9ucyB0aGF0DQogKiBhcHBseSB0byBhbGwgY2xvbmVkIERPTSBub2RlcyB3aXRoaW4gdGhlIGNvbXBpbGUgZnVuY3Rpb24uIFNwZWNpZmljYWxseSwgRE9NIGxpc3RlbmVyIHJlZ2lzdHJhdGlvbg0KICogc2hvdWxkIGJlIGRvbmUgaW4gYSBsaW5raW5nIGZ1bmN0aW9uIHJhdGhlciB0aGFuIGluIGEgY29tcGlsZSBmdW5jdGlvbi4NCiAqIDwvZGl2Pg0KDQogKiA8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4NCiAqICoqTm90ZToqKiBUaGUgY29tcGlsZSBmdW5jdGlvbiBjYW5ub3QgaGFuZGxlIGRpcmVjdGl2ZXMgdGhhdCByZWN1cnNpdmVseSB1c2UgdGhlbXNlbHZlcyBpbiB0aGVpcg0KICogb3duIHRlbXBsYXRlcyBvciBjb21waWxlIGZ1bmN0aW9ucy4gQ29tcGlsaW5nIHRoZXNlIGRpcmVjdGl2ZXMgcmVzdWx0cyBpbiBhbiBpbmZpbml0ZSBsb29wIGFuZCBhDQogKiBzdGFjayBvdmVyZmxvdyBlcnJvcnMuDQogKg0KICogVGhpcyBjYW4gYmUgYXZvaWRlZCBieSBtYW51YWxseSB1c2luZyAkY29tcGlsZSBpbiB0aGUgcG9zdExpbmsgZnVuY3Rpb24gdG8gaW1wZXJhdGl2ZWx5IGNvbXBpbGUNCiAqIGEgZGlyZWN0aXZlJ3MgdGVtcGxhdGUgaW5zdGVhZCBvZiByZWx5aW5nIG9uIGF1dG9tYXRpYyB0ZW1wbGF0ZSBjb21waWxhdGlvbiB2aWEgYHRlbXBsYXRlYCBvcg0KICogYHRlbXBsYXRlVXJsYCBkZWNsYXJhdGlvbiBvciBtYW51YWwgY29tcGlsYXRpb24gaW5zaWRlIHRoZSBjb21waWxlIGZ1bmN0aW9uLg0KICogPC9kaXY+DQogKg0KICogPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtZXJyb3IiPg0KICogKipOb3RlOioqIFRoZSBgdHJhbnNjbHVkZWAgZnVuY3Rpb24gdGhhdCBpcyBwYXNzZWQgdG8gdGhlIGNvbXBpbGUgZnVuY3Rpb24gaXMgZGVwcmVjYXRlZCwgYXMgaXQNCiAqICAgZS5nLiBkb2VzIG5vdCBrbm93IGFib3V0IHRoZSByaWdodCBvdXRlciBzY29wZS4gUGxlYXNlIHVzZSB0aGUgdHJhbnNjbHVkZSBmdW5jdGlvbiB0aGF0IGlzIHBhc3NlZA0KICogICB0byB0aGUgbGluayBmdW5jdGlvbiBpbnN0ZWFkLg0KICogPC9kaXY+DQoNCiAqIEEgY29tcGlsZSBmdW5jdGlvbiBjYW4gaGF2ZSBhIHJldHVybiB2YWx1ZSB3aGljaCBjYW4gYmUgZWl0aGVyIGEgZnVuY3Rpb24gb3IgYW4gb2JqZWN0Lg0KICoNCiAqICogcmV0dXJuaW5nIGEgKHBvc3QtbGluaykgZnVuY3Rpb24gLSBpcyBlcXVpdmFsZW50IHRvIHJlZ2lzdGVyaW5nIHRoZSBsaW5raW5nIGZ1bmN0aW9uIHZpYSB0aGUNCiAqICAgYGxpbmtgIHByb3BlcnR5IG9mIHRoZSBjb25maWcgb2JqZWN0IHdoZW4gdGhlIGNvbXBpbGUgZnVuY3Rpb24gaXMgZW1wdHkuDQogKg0KICogKiByZXR1cm5pbmcgYW4gb2JqZWN0IHdpdGggZnVuY3Rpb24ocykgcmVnaXN0ZXJlZCB2aWEgYHByZWAgYW5kIGBwb3N0YCBwcm9wZXJ0aWVzIC0gYWxsb3dzIHlvdSB0bw0KICogICBjb250cm9sIHdoZW4gYSBsaW5raW5nIGZ1bmN0aW9uIHNob3VsZCBiZSBjYWxsZWQgZHVyaW5nIHRoZSBsaW5raW5nIHBoYXNlLiBTZWUgaW5mbyBhYm91dA0KICogICBwcmUtbGlua2luZyBhbmQgcG9zdC1saW5raW5nIGZ1bmN0aW9ucyBiZWxvdy4NCiAqDQogKg0KICogIyMjIyBgbGlua2ANCiAqIFRoaXMgcHJvcGVydHkgaXMgdXNlZCBvbmx5IGlmIHRoZSBgY29tcGlsZWAgcHJvcGVydHkgaXMgbm90IGRlZmluZWQuDQogKg0KICogYGBganMNCiAqICAgZnVuY3Rpb24gbGluayhzY29wZSwgaUVsZW1lbnQsIGlBdHRycywgY29udHJvbGxlciwgdHJhbnNjbHVkZUZuKSB7IC4uLiB9DQogKiBgYGANCiAqDQogKiBUaGUgbGluayBmdW5jdGlvbiBpcyByZXNwb25zaWJsZSBmb3IgcmVnaXN0ZXJpbmcgRE9NIGxpc3RlbmVycyBhcyB3ZWxsIGFzIHVwZGF0aW5nIHRoZSBET00uIEl0IGlzDQogKiBleGVjdXRlZCBhZnRlciB0aGUgdGVtcGxhdGUgaGFzIGJlZW4gY2xvbmVkLiBUaGlzIGlzIHdoZXJlIG1vc3Qgb2YgdGhlIGRpcmVjdGl2ZSBsb2dpYyB3aWxsIGJlDQogKiBwdXQuDQogKg0KICogICAqIGBzY29wZWAgLSB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSBTY29wZX0gLSBUaGUgc2NvcGUgdG8gYmUgdXNlZCBieSB0aGUNCiAqICAgICBkaXJlY3RpdmUgZm9yIHJlZ2lzdGVyaW5nIHtAbGluayBuZy4kcm9vdFNjb3BlLlNjb3BlIyR3YXRjaCB3YXRjaGVzfS4NCiAqDQogKiAgICogYGlFbGVtZW50YCAtIGluc3RhbmNlIGVsZW1lbnQgLSBUaGUgZWxlbWVudCB3aGVyZSB0aGUgZGlyZWN0aXZlIGlzIHRvIGJlIHVzZWQuIEl0IGlzIHNhZmUgdG8NCiAqICAgICBtYW5pcHVsYXRlIHRoZSBjaGlsZHJlbiBvZiB0aGUgZWxlbWVudCBvbmx5IGluIGBwb3N0TGlua2AgZnVuY3Rpb24gc2luY2UgdGhlIGNoaWxkcmVuIGhhdmUNCiAqICAgICBhbHJlYWR5IGJlZW4gbGlua2VkLg0KICoNCiAqICAgKiBgaUF0dHJzYCAtIGluc3RhbmNlIGF0dHJpYnV0ZXMgLSBOb3JtYWxpemVkIGxpc3Qgb2YgYXR0cmlidXRlcyBkZWNsYXJlZCBvbiB0aGlzIGVsZW1lbnQgc2hhcmVkDQogKiAgICAgYmV0d2VlbiBhbGwgZGlyZWN0aXZlIGxpbmtpbmcgZnVuY3Rpb25zLg0KICoNCiAqICAgKiBgY29udHJvbGxlcmAgLSBhIGNvbnRyb2xsZXIgaW5zdGFuY2UgLSBBIGNvbnRyb2xsZXIgaW5zdGFuY2UgaWYgYXQgbGVhc3Qgb25lIGRpcmVjdGl2ZSBvbiB0aGUNCiAqICAgICBlbGVtZW50IGRlZmluZXMgYSBjb250cm9sbGVyLiBUaGUgY29udHJvbGxlciBpcyBzaGFyZWQgYW1vbmcgYWxsIHRoZSBkaXJlY3RpdmVzLCB3aGljaCBhbGxvd3MNCiAqICAgICB0aGUgZGlyZWN0aXZlcyB0byB1c2UgdGhlIGNvbnRyb2xsZXJzIGFzIGEgY29tbXVuaWNhdGlvbiBjaGFubmVsLg0KICoNCiAqICAgKiBgdHJhbnNjbHVkZUZuYCAtIEEgdHJhbnNjbHVkZSBsaW5raW5nIGZ1bmN0aW9uIHByZS1ib3VuZCB0byB0aGUgY29ycmVjdCB0cmFuc2NsdXNpb24gc2NvcGUuDQogKiAgICAgVGhpcyBpcyB0aGUgc2FtZSBhcyB0aGUgYCR0cmFuc2NsdWRlYA0KICogICAgIHBhcmFtZXRlciBvZiBkaXJlY3RpdmUgY29udHJvbGxlcnMsIHNlZSB0aGVyZSBmb3IgZGV0YWlscy4NCiAqICAgICBgZnVuY3Rpb24oW3Njb3BlXSwgY2xvbmVMaW5raW5nRm4sIGZ1dHVyZVBhcmVudEVsZW1lbnQpYC4NCiAqDQogKiAjIyMjIFByZS1saW5raW5nIGZ1bmN0aW9uDQogKg0KICogRXhlY3V0ZWQgYmVmb3JlIHRoZSBjaGlsZCBlbGVtZW50cyBhcmUgbGlua2VkLiBOb3Qgc2FmZSB0byBkbyBET00gdHJhbnNmb3JtYXRpb24gc2luY2UgdGhlDQogKiBjb21waWxlciBsaW5raW5nIGZ1bmN0aW9uIHdpbGwgZmFpbCB0byBsb2NhdGUgdGhlIGNvcnJlY3QgZWxlbWVudHMgZm9yIGxpbmtpbmcuDQogKg0KICogIyMjIyBQb3N0LWxpbmtpbmcgZnVuY3Rpb24NCiAqDQogKiBFeGVjdXRlZCBhZnRlciB0aGUgY2hpbGQgZWxlbWVudHMgYXJlIGxpbmtlZC4NCiAqDQogKiBOb3RlIHRoYXQgY2hpbGQgZWxlbWVudHMgdGhhdCBjb250YWluIGB0ZW1wbGF0ZVVybGAgZGlyZWN0aXZlcyB3aWxsIG5vdCBoYXZlIGJlZW4gY29tcGlsZWQNCiAqIGFuZCBsaW5rZWQgc2luY2UgdGhleSBhcmUgd2FpdGluZyBmb3IgdGhlaXIgdGVtcGxhdGUgdG8gbG9hZCBhc3luY2hyb25vdXNseSBhbmQgdGhlaXIgb3duDQogKiBjb21waWxhdGlvbiBhbmQgbGlua2luZyBoYXMgYmVlbiBzdXNwZW5kZWQgdW50aWwgdGhhdCBvY2N1cnMuDQogKg0KICogSXQgaXMgc2FmZSB0byBkbyBET00gdHJhbnNmb3JtYXRpb24gaW4gdGhlIHBvc3QtbGlua2luZyBmdW5jdGlvbiBvbiBlbGVtZW50cyB0aGF0IGFyZSBub3Qgd2FpdGluZw0KICogZm9yIHRoZWlyIGFzeW5jIHRlbXBsYXRlcyB0byBiZSByZXNvbHZlZC4NCiAqDQogKg0KICogIyMjIFRyYW5zY2x1c2lvbg0KICoNCiAqIFRyYW5zY2x1c2lvbiBpcyB0aGUgcHJvY2VzcyBvZiBleHRyYWN0aW5nIGEgY29sbGVjdGlvbiBvZiBET00gZWxlbWVudCBmcm9tIG9uZSBwYXJ0IG9mIHRoZSBET00gYW5kDQogKiBjb3B5aW5nIHRoZW0gdG8gYW5vdGhlciBwYXJ0IG9mIHRoZSBET00sIHdoaWxlIG1haW50YWluaW5nIHRoZWlyIGNvbm5lY3Rpb24gdG8gdGhlIG9yaWdpbmFsIEFuZ3VsYXJKUw0KICogc2NvcGUgZnJvbSB3aGVyZSB0aGV5IHdlcmUgdGFrZW4uDQogKg0KICogVHJhbnNjbHVzaW9uIGlzIHVzZWQgKG9mdGVuIHdpdGgge0BsaW5rIG5nVHJhbnNjbHVkZX0pIHRvIGluc2VydCB0aGUNCiAqIG9yaWdpbmFsIGNvbnRlbnRzIG9mIGEgZGlyZWN0aXZlJ3MgZWxlbWVudCBpbnRvIGEgc3BlY2lmaWVkIHBsYWNlIGluIHRoZSB0ZW1wbGF0ZSBvZiB0aGUgZGlyZWN0aXZlLg0KICogVGhlIGJlbmVmaXQgb2YgdHJhbnNjbHVzaW9uLCBvdmVyIHNpbXBseSBtb3ZpbmcgdGhlIERPTSBlbGVtZW50cyBtYW51YWxseSwgaXMgdGhhdCB0aGUgdHJhbnNjbHVkZWQNCiAqIGNvbnRlbnQgaGFzIGFjY2VzcyB0byB0aGUgcHJvcGVydGllcyBvbiB0aGUgc2NvcGUgZnJvbSB3aGljaCBpdCB3YXMgdGFrZW4sIGV2ZW4gaWYgdGhlIGRpcmVjdGl2ZQ0KICogaGFzIGlzb2xhdGVkIHNjb3BlLg0KICogU2VlIHRoZSB7QGxpbmsgZ3VpZGUvZGlyZWN0aXZlI2NyZWF0aW5nLWEtZGlyZWN0aXZlLXRoYXQtd3JhcHMtb3RoZXItZWxlbWVudHMgRGlyZWN0aXZlcyBHdWlkZX0uDQogKg0KICogVGhpcyBtYWtlcyBpdCBwb3NzaWJsZSBmb3IgdGhlIHdpZGdldCB0byBoYXZlIHByaXZhdGUgc3RhdGUgZm9yIGl0cyB0ZW1wbGF0ZSwgd2hpbGUgdGhlIHRyYW5zY2x1ZGVkDQogKiBjb250ZW50IGhhcyBhY2Nlc3MgdG8gaXRzIG9yaWdpbmF0aW5nIHNjb3BlLg0KICoNCiAqIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXdhcm5pbmciPg0KICogKipOb3RlOioqIFdoZW4gdGVzdGluZyBhbiBlbGVtZW50IHRyYW5zY2x1ZGUgZGlyZWN0aXZlIHlvdSBtdXN0IG5vdCBwbGFjZSB0aGUgZGlyZWN0aXZlIGF0IHRoZSByb290IG9mIHRoZQ0KICogRE9NIGZyYWdtZW50IHRoYXQgaXMgYmVpbmcgY29tcGlsZWQuIFNlZSB7QGxpbmsgZ3VpZGUvdW5pdC10ZXN0aW5nI3Rlc3RpbmctdHJhbnNjbHVzaW9uLWRpcmVjdGl2ZXMNCiAqIFRlc3RpbmcgVHJhbnNjbHVzaW9uIERpcmVjdGl2ZXN9Lg0KICogPC9kaXY+DQogKg0KICogIyMjIyBUcmFuc2NsdXNpb24gRnVuY3Rpb25zDQogKg0KICogV2hlbiBhIGRpcmVjdGl2ZSByZXF1ZXN0cyB0cmFuc2NsdXNpb24sIHRoZSBjb21waWxlciBleHRyYWN0cyBpdHMgY29udGVudHMgYW5kIHByb3ZpZGVzIGEgKip0cmFuc2NsdXNpb24NCiAqIGZ1bmN0aW9uKiogdG8gdGhlIGRpcmVjdGl2ZSdzIGBsaW5rYCBmdW5jdGlvbiBhbmQgYGNvbnRyb2xsZXJgLiBUaGlzIHRyYW5zY2x1c2lvbiBmdW5jdGlvbiBpcyBhIHNwZWNpYWwNCiAqICoqbGlua2luZyBmdW5jdGlvbioqIHRoYXQgd2lsbCByZXR1cm4gdGhlIGNvbXBpbGVkIGNvbnRlbnRzIGxpbmtlZCB0byBhIG5ldyB0cmFuc2NsdXNpb24gc2NvcGUuDQogKg0KICogPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+DQogKiBJZiB5b3UgYXJlIGp1c3QgdXNpbmcge0BsaW5rIG5nVHJhbnNjbHVkZX0gdGhlbiB5b3UgZG9uJ3QgbmVlZCB0byB3b3JyeSBhYm91dCB0aGlzIGZ1bmN0aW9uLCBzaW5jZQ0KICogbmdUcmFuc2NsdWRlIHdpbGwgZGVhbCB3aXRoIGl0IGZvciB1cy4NCiAqIDwvZGl2Pg0KICoNCiAqIElmIHlvdSB3YW50IHRvIG1hbnVhbGx5IGNvbnRyb2wgdGhlIGluc2VydGlvbiBhbmQgcmVtb3ZhbCBvZiB0aGUgdHJhbnNjbHVkZWQgY29udGVudCBpbiB5b3VyIGRpcmVjdGl2ZQ0KICogdGhlbiB5b3UgbXVzdCB1c2UgdGhpcyB0cmFuc2NsdWRlIGZ1bmN0aW9uLiBXaGVuIHlvdSBjYWxsIGEgdHJhbnNjbHVkZSBmdW5jdGlvbiBpdCByZXR1cm5zIGEgYSBqcUxpdGUvSlF1ZXJ5DQogKiBvYmplY3QgdGhhdCBjb250YWlucyB0aGUgY29tcGlsZWQgRE9NLCB3aGljaCBpcyBsaW5rZWQgdG8gdGhlIGNvcnJlY3QgdHJhbnNjbHVzaW9uIHNjb3BlLg0KICoNCiAqIFdoZW4geW91IGNhbGwgYSB0cmFuc2NsdXNpb24gZnVuY3Rpb24geW91IGNhbiBwYXNzIGluIGEgKipjbG9uZSBhdHRhY2ggZnVuY3Rpb24qKi4gVGhpcyBmdW5jdGlvbiBhY2NlcHRzDQogKiB0d28gcGFyYW1ldGVycywgYGZ1bmN0aW9uKGNsb25lLCBzY29wZSkgeyAuLi4gfWAsIHdoZXJlIHRoZSBgY2xvbmVgIGlzIGEgZnJlc2ggY29tcGlsZWQgY29weSBvZiB5b3VyIHRyYW5zY2x1ZGVkDQogKiBjb250ZW50IGFuZCB0aGUgYHNjb3BlYCBpcyB0aGUgbmV3bHkgY3JlYXRlZCB0cmFuc2NsdXNpb24gc2NvcGUsIHRvIHdoaWNoIHRoZSBjbG9uZSBpcyBib3VuZC4NCiAqDQogKiA8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4NCiAqICoqQmVzdCBQcmFjdGljZSoqOiBBbHdheXMgcHJvdmlkZSBhIGBjbG9uZUZuYCAoY2xvbmUgYXR0YWNoIGZ1bmN0aW9uKSB3aGVuIHlvdSBjYWxsIGEgdHJhbnNsdWRlIGZ1bmN0aW9uDQogKiBzaW5jZSB5b3UgdGhlbiBnZXQgYSBmcmVzaCBjbG9uZSBvZiB0aGUgb3JpZ2luYWwgRE9NIGFuZCBhbHNvIGhhdmUgYWNjZXNzIHRvIHRoZSBuZXcgdHJhbnNjbHVzaW9uIHNjb3BlLg0KICogPC9kaXY+DQogKg0KICogSXQgaXMgbm9ybWFsIHByYWN0aWNlIHRvIGF0dGFjaCB5b3VyIHRyYW5zY2x1ZGVkIGNvbnRlbnQgKGBjbG9uZWApIHRvIHRoZSBET00gaW5zaWRlIHlvdXIgKipjbG9uZQ0KICogYXR0YWNoIGZ1bmN0aW9uKio6DQogKg0KICogYGBganMNCiAqIHZhciB0cmFuc2NsdWRlZENvbnRlbnQsIHRyYW5zY2x1c2lvblNjb3BlOw0KICoNCiAqICR0cmFuc2NsdWRlKGZ1bmN0aW9uKGNsb25lLCBzY29wZSkgew0KICogICBlbGVtZW50LmFwcGVuZChjbG9uZSk7DQogKiAgIHRyYW5zY2x1ZGVkQ29udGVudCA9IGNsb25lOw0KICogICB0cmFuc2NsdXNpb25TY29wZSA9IHNjb3BlOw0KICogfSk7DQogKiBgYGANCiAqDQogKiBMYXRlciwgaWYgeW91IHdhbnQgdG8gcmVtb3ZlIHRoZSB0cmFuc2NsdWRlZCBjb250ZW50IGZyb20geW91ciBET00gdGhlbiB5b3Ugc2hvdWxkIGFsc28gZGVzdHJveSB0aGUNCiAqIGFzc29jaWF0ZWQgdHJhbnNjbHVzaW9uIHNjb3BlOg0KICoNCiAqIGBgYGpzDQogKiB0cmFuc2NsdWRlZENvbnRlbnQucmVtb3ZlKCk7DQogKiB0cmFuc2NsdXNpb25TY29wZS4kZGVzdHJveSgpOw0KICogYGBgDQogKg0KICogPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+DQogKiAqKkJlc3QgUHJhY3RpY2UqKjogaWYgeW91IGludGVuZCB0byBhZGQgYW5kIHJlbW92ZSB0cmFuc2NsdWRlZCBjb250ZW50IG1hbnVhbGx5IGluIHlvdXIgZGlyZWN0aXZlDQogKiAoYnkgY2FsbGluZyB0aGUgdHJhbnNjbHVkZSBmdW5jdGlvbiB0byBnZXQgdGhlIERPTSBhbmQgYW5kIGNhbGxpbmcgYGVsZW1lbnQucmVtb3ZlKClgIHRvIHJlbW92ZSBpdCksDQogKiB0aGVuIHlvdSBhcmUgYWxzbyByZXNwb25zaWJsZSBmb3IgY2FsbGluZyBgJGRlc3Ryb3lgIG9uIHRoZSB0cmFuc2NsdXNpb24gc2NvcGUuDQogKiA8L2Rpdj4NCiAqDQogKiBUaGUgYnVpbHQtaW4gRE9NIG1hbmlwdWxhdGlvbiBkaXJlY3RpdmVzLCBzdWNoIGFzIHtAbGluayBuZ0lmfSwge0BsaW5rIG5nU3dpdGNofSBhbmQge0BsaW5rIG5nUmVwZWF0fQ0KICogYXV0b21hdGljYWxseSBkZXN0cm95IHRoZWlyIHRyYW5zbHVkZWQgY2xvbmVzIGFzIG5lY2Vzc2FyeSBzbyB5b3UgZG8gbm90IG5lZWQgdG8gd29ycnkgYWJvdXQgdGhpcyBpZg0KICogeW91IGFyZSBzaW1wbHkgdXNpbmcge0BsaW5rIG5nVHJhbnNjbHVkZX0gdG8gaW5qZWN0IHRoZSB0cmFuc2NsdXNpb24gaW50byB5b3VyIGRpcmVjdGl2ZS4NCiAqDQogKg0KICogIyMjIyBUcmFuc2NsdXNpb24gU2NvcGVzDQogKg0KICogV2hlbiB5b3UgY2FsbCBhIHRyYW5zY2x1ZGUgZnVuY3Rpb24gaXQgcmV0dXJucyBhIERPTSBmcmFnbWVudCB0aGF0IGlzIHByZS1ib3VuZCB0byBhICoqdHJhbnNjbHVzaW9uDQogKiBzY29wZSoqLiBUaGlzIHNjb3BlIGlzIHNwZWNpYWwsIGluIHRoYXQgaXQgaXMgYSBjaGlsZCBvZiB0aGUgZGlyZWN0aXZlJ3Mgc2NvcGUgKGFuZCBzbyBnZXRzIGRlc3Ryb3llZA0KICogd2hlbiB0aGUgZGlyZWN0aXZlJ3Mgc2NvcGUgZ2V0cyBkZXN0cm95ZWQpIGJ1dCBpdCBpbmhlcml0cyB0aGUgcHJvcGVydGllcyBvZiB0aGUgc2NvcGUgZnJvbSB3aGljaCBpdA0KICogd2FzIHRha2VuLg0KICoNCiAqIEZvciBleGFtcGxlIGNvbnNpZGVyIGEgZGlyZWN0aXZlIHRoYXQgdXNlcyB0cmFuc2NsdXNpb24gYW5kIGlzb2xhdGVkIHNjb3BlLiBUaGUgRE9NIGhpZXJhcmNoeSBtaWdodCBsb29rDQogKiBsaWtlIHRoaXM6DQogKg0KICogYGBgaHRtbA0KICogPGRpdiBuZy1hcHA+DQogKiAgIDxkaXYgaXNvbGF0ZT4NCiAqICAgICA8ZGl2IHRyYW5zY2x1c2lvbj4NCiAqICAgICA8L2Rpdj4NCiAqICAgPC9kaXY+DQogKiA8L2Rpdj4NCiAqIGBgYA0KICoNCiAqIFRoZSBgJHBhcmVudGAgc2NvcGUgaGllcmFyY2h5IHdpbGwgbG9vayBsaWtlIHRoaXM6DQogKg0KICogYGBgDQogKiAtICRyb290U2NvcGUNCiAqICAgLSBpc29sYXRlDQogKiAgICAgLSB0cmFuc2NsdXNpb24NCiAqIGBgYA0KICoNCiAqIGJ1dCB0aGUgc2NvcGVzIHdpbGwgaW5oZXJpdCBwcm90b3R5cGljYWxseSBmcm9tIGRpZmZlcmVudCBzY29wZXMgdG8gdGhlaXIgYCRwYXJlbnRgLg0KICoNCiAqIGBgYA0KICogLSAkcm9vdFNjb3BlDQogKiAgIC0gdHJhbnNjbHVzaW9uDQogKiAtIGlzb2xhdGUNCiAqIGBgYA0KICoNCiAqDQogKiAjIyMgQXR0cmlidXRlcw0KICoNCiAqIFRoZSB7QGxpbmsgbmcuJGNvbXBpbGUuZGlyZWN0aXZlLkF0dHJpYnV0ZXMgQXR0cmlidXRlc30gb2JqZWN0IC0gcGFzc2VkIGFzIGEgcGFyYW1ldGVyIGluIHRoZQ0KICogYGxpbmsoKWAgb3IgYGNvbXBpbGUoKWAgZnVuY3Rpb25zLiBJdCBoYXMgYSB2YXJpZXR5IG9mIHVzZXMuDQogKg0KICogYWNjZXNzaW5nICpOb3JtYWxpemVkIGF0dHJpYnV0ZSBuYW1lczoqDQogKiBEaXJlY3RpdmVzIGxpa2UgJ25nQmluZCcgY2FuIGJlIGV4cHJlc3NlZCBpbiBtYW55IHdheXM6ICduZzpiaW5kJywgYGRhdGEtbmctYmluZGAsIG9yICd4LW5nLWJpbmQnLg0KICogdGhlIGF0dHJpYnV0ZXMgb2JqZWN0IGFsbG93cyBmb3Igbm9ybWFsaXplZCBhY2Nlc3MgdG8NCiAqICAgdGhlIGF0dHJpYnV0ZXMuDQogKg0KICogKiAqRGlyZWN0aXZlIGludGVyLWNvbW11bmljYXRpb246KiBBbGwgZGlyZWN0aXZlcyBzaGFyZSB0aGUgc2FtZSBpbnN0YW5jZSBvZiB0aGUgYXR0cmlidXRlcw0KICogICBvYmplY3Qgd2hpY2ggYWxsb3dzIHRoZSBkaXJlY3RpdmVzIHRvIHVzZSB0aGUgYXR0cmlidXRlcyBvYmplY3QgYXMgaW50ZXIgZGlyZWN0aXZlDQogKiAgIGNvbW11bmljYXRpb24uDQogKg0KICogKiAqU3VwcG9ydHMgaW50ZXJwb2xhdGlvbjoqIEludGVycG9sYXRpb24gYXR0cmlidXRlcyBhcmUgYXNzaWduZWQgdG8gdGhlIGF0dHJpYnV0ZSBvYmplY3QNCiAqICAgYWxsb3dpbmcgb3RoZXIgZGlyZWN0aXZlcyB0byByZWFkIHRoZSBpbnRlcnBvbGF0ZWQgdmFsdWUuDQogKg0KICogKiAqT2JzZXJ2aW5nIGludGVycG9sYXRlZCBhdHRyaWJ1dGVzOiogVXNlIGAkb2JzZXJ2ZWAgdG8gb2JzZXJ2ZSB0aGUgdmFsdWUgY2hhbmdlcyBvZiBhdHRyaWJ1dGVzDQogKiAgIHRoYXQgY29udGFpbiBpbnRlcnBvbGF0aW9uIChlLmcuIGBzcmM9Int7YmFyfX0iYCkuIE5vdCBvbmx5IGlzIHRoaXMgdmVyeSBlZmZpY2llbnQgYnV0IGl0J3MgYWxzbw0KICogICB0aGUgb25seSB3YXkgdG8gZWFzaWx5IGdldCB0aGUgYWN0dWFsIHZhbHVlIGJlY2F1c2UgZHVyaW5nIHRoZSBsaW5raW5nIHBoYXNlIHRoZSBpbnRlcnBvbGF0aW9uDQogKiAgIGhhc24ndCBiZWVuIGV2YWx1YXRlZCB5ZXQgYW5kIHNvIHRoZSB2YWx1ZSBpcyBhdCB0aGlzIHRpbWUgc2V0IHRvIGB1bmRlZmluZWRgLg0KICoNCiAqIGBgYGpzDQogKiBmdW5jdGlvbiBsaW5raW5nRm4oc2NvcGUsIGVsbSwgYXR0cnMsIGN0cmwpIHsNCiAqICAgLy8gZ2V0IHRoZSBhdHRyaWJ1dGUgdmFsdWUNCiAqICAgY29uc29sZS5sb2coYXR0cnMubmdNb2RlbCk7DQogKg0KICogICAvLyBjaGFuZ2UgdGhlIGF0dHJpYnV0ZQ0KICogICBhdHRycy4kc2V0KCduZ01vZGVsJywgJ25ldyB2YWx1ZScpOw0KICoNCiAqICAgLy8gb2JzZXJ2ZSBjaGFuZ2VzIHRvIGludGVycG9sYXRlZCBhdHRyaWJ1dGUNCiAqICAgYXR0cnMuJG9ic2VydmUoJ25nTW9kZWwnLCBmdW5jdGlvbih2YWx1ZSkgew0KICogICAgIGNvbnNvbGUubG9nKCduZ01vZGVsIGhhcyBjaGFuZ2VkIHZhbHVlIHRvICcgKyB2YWx1ZSk7DQogKiAgIH0pOw0KICogfQ0KICogYGBgDQogKg0KICogIyMgRXhhbXBsZQ0KICoNCiAqIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXdhcm5pbmciPg0KICogKipOb3RlKio6IFR5cGljYWxseSBkaXJlY3RpdmVzIGFyZSByZWdpc3RlcmVkIHdpdGggYG1vZHVsZS5kaXJlY3RpdmVgLiBUaGUgZXhhbXBsZSBiZWxvdyBpcw0KICogdG8gaWxsdXN0cmF0ZSBob3cgYCRjb21waWxlYCB3b3Jrcy4NCiAqIDwvZGl2Pg0KICoNCiA8ZXhhbXBsZSBtb2R1bGU9ImNvbXBpbGVFeGFtcGxlIj4NCiAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgIDxzY3JpcHQ+DQogICAgICBhbmd1bGFyLm1vZHVsZSgnY29tcGlsZUV4YW1wbGUnLCBbXSwgZnVuY3Rpb24oJGNvbXBpbGVQcm92aWRlcikgew0KICAgICAgICAvLyBjb25maWd1cmUgbmV3ICdjb21waWxlJyBkaXJlY3RpdmUgYnkgcGFzc2luZyBhIGRpcmVjdGl2ZQ0KICAgICAgICAvLyBmYWN0b3J5IGZ1bmN0aW9uLiBUaGUgZmFjdG9yeSBmdW5jdGlvbiBpbmplY3RzIHRoZSAnJGNvbXBpbGUnDQogICAgICAgICRjb21waWxlUHJvdmlkZXIuZGlyZWN0aXZlKCdjb21waWxlJywgZnVuY3Rpb24oJGNvbXBpbGUpIHsNCiAgICAgICAgICAvLyBkaXJlY3RpdmUgZmFjdG9yeSBjcmVhdGVzIGEgbGluayBmdW5jdGlvbg0KICAgICAgICAgIHJldHVybiBmdW5jdGlvbihzY29wZSwgZWxlbWVudCwgYXR0cnMpIHsNCiAgICAgICAgICAgIHNjb3BlLiR3YXRjaCgNCiAgICAgICAgICAgICAgZnVuY3Rpb24oc2NvcGUpIHsNCiAgICAgICAgICAgICAgICAgLy8gd2F0Y2ggdGhlICdjb21waWxlJyBleHByZXNzaW9uIGZvciBjaGFuZ2VzDQogICAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLiRldmFsKGF0dHJzLmNvbXBpbGUpOw0KICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICAgICAgICAgIC8vIHdoZW4gdGhlICdjb21waWxlJyBleHByZXNzaW9uIGNoYW5nZXMNCiAgICAgICAgICAgICAgICAvLyBhc3NpZ24gaXQgaW50byB0aGUgY3VycmVudCBET00NCiAgICAgICAgICAgICAgICBlbGVtZW50Lmh0bWwodmFsdWUpOw0KDQogICAgICAgICAgICAgICAgLy8gY29tcGlsZSB0aGUgbmV3IERPTSBhbmQgbGluayBpdCB0byB0aGUgY3VycmVudA0KICAgICAgICAgICAgICAgIC8vIHNjb3BlLg0KICAgICAgICAgICAgICAgIC8vIE5PVEU6IHdlIG9ubHkgY29tcGlsZSAuY2hpbGROb2RlcyBzbyB0aGF0DQogICAgICAgICAgICAgICAgLy8gd2UgZG9uJ3QgZ2V0IGludG8gaW5maW5pdGUgbG9vcCBjb21waWxpbmcgb3Vyc2VsdmVzDQogICAgICAgICAgICAgICAgJGNvbXBpbGUoZWxlbWVudC5jb250ZW50cygpKShzY29wZSk7DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICk7DQogICAgICAgICAgfTsNCiAgICAgICAgfSk7DQogICAgICB9KQ0KICAgICAgLmNvbnRyb2xsZXIoJ0dyZWV0ZXJDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICAgJHNjb3BlLm5hbWUgPSAnQW5ndWxhcic7DQogICAgICAgICRzY29wZS5odG1sID0gJ0hlbGxvIHt7bmFtZX19JzsNCiAgICAgIH1dKTsNCiAgICA8L3NjcmlwdD4NCiAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkdyZWV0ZXJDb250cm9sbGVyIj4NCiAgICAgIDxpbnB1dCBuZy1tb2RlbD0ibmFtZSI+IDxicj4NCiAgICAgIDx0ZXh0YXJlYSBuZy1tb2RlbD0iaHRtbCI+PC90ZXh0YXJlYT4gPGJyPg0KICAgICAgPGRpdiBjb21waWxlPSJodG1sIj48L2Rpdj4NCiAgICA8L2Rpdj4NCiAgIDwvZmlsZT4NCiAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICBpdCgnc2hvdWxkIGF1dG8gY29tcGlsZScsIGZ1bmN0aW9uKCkgew0KICAgICAgIHZhciB0ZXh0YXJlYSA9ICQoJ3RleHRhcmVhJyk7DQogICAgICAgdmFyIG91dHB1dCA9ICQoJ2Rpdltjb21waWxlXScpOw0KICAgICAgIC8vIFRoZSBpbml0aWFsIHN0YXRlIHJlYWRzICdIZWxsbyBBbmd1bGFyJy4NCiAgICAgICBleHBlY3Qob3V0cHV0LmdldFRleHQoKSkudG9CZSgnSGVsbG8gQW5ndWxhcicpOw0KICAgICAgIHRleHRhcmVhLmNsZWFyKCk7DQogICAgICAgdGV4dGFyZWEuc2VuZEtleXMoJ3t7bmFtZX19IScpOw0KICAgICAgIGV4cGVjdChvdXRwdXQuZ2V0VGV4dCgpKS50b0JlKCdBbmd1bGFyIScpOw0KICAgICB9KTsNCiAgIDwvZmlsZT4NCiA8L2V4YW1wbGU+DQoNCiAqDQogKg0KICogQHBhcmFtIHtzdHJpbmd8RE9NRWxlbWVudH0gZWxlbWVudCBFbGVtZW50IG9yIEhUTUwgc3RyaW5nIHRvIGNvbXBpbGUgaW50byBhIHRlbXBsYXRlIGZ1bmN0aW9uLg0KICogQHBhcmFtIHtmdW5jdGlvbihhbmd1bGFyLlNjb3BlLCBjbG9uZUF0dGFjaEZuPSl9IHRyYW5zY2x1ZGUgZnVuY3Rpb24gYXZhaWxhYmxlIHRvIGRpcmVjdGl2ZXMgLSBERVBSRUNBVEVELg0KICoNCiAqIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWVycm9yIj4NCiAqICoqTm90ZToqKiBQYXNzaW5nIGEgYHRyYW5zY2x1ZGVgIGZ1bmN0aW9uIHRvIHRoZSAkY29tcGlsZSBmdW5jdGlvbiBpcyBkZXByZWNhdGVkLCBhcyBpdA0KICogICBlLmcuIHdpbGwgbm90IHVzZSB0aGUgcmlnaHQgb3V0ZXIgc2NvcGUuIFBsZWFzZSBwYXNzIHRoZSB0cmFuc2NsdWRlIGZ1bmN0aW9uIGFzIGENCiAqICAgYHBhcmVudEJvdW5kVHJhbnNjbHVkZUZuYCB0byB0aGUgbGluayBmdW5jdGlvbiBpbnN0ZWFkLg0KICogPC9kaXY+DQogKg0KICogQHBhcmFtIHtudW1iZXJ9IG1heFByaW9yaXR5IG9ubHkgYXBwbHkgZGlyZWN0aXZlcyBsb3dlciB0aGFuIGdpdmVuIHByaW9yaXR5IChPbmx5IGVmZmVjdHMgdGhlDQogKiAgICAgICAgICAgICAgICAgcm9vdCBlbGVtZW50KHMpLCBub3QgdGhlaXIgY2hpbGRyZW4pDQogKiBAcmV0dXJucyB7ZnVuY3Rpb24oc2NvcGUsIGNsb25lQXR0YWNoRm49LCBvcHRpb25zPSl9IGEgbGluayBmdW5jdGlvbiB3aGljaCBpcyB1c2VkIHRvIGJpbmQgdGVtcGxhdGUNCiAqIChhIERPTSBlbGVtZW50L3RyZWUpIHRvIGEgc2NvcGUuIFdoZXJlOg0KICoNCiAqICAqIGBzY29wZWAgLSBBIHtAbGluayBuZy4kcm9vdFNjb3BlLlNjb3BlIFNjb3BlfSB0byBiaW5kIHRvLg0KICogICogYGNsb25lQXR0YWNoRm5gIC0gSWYgYGNsb25lQXR0YWNoRm5gIGlzIHByb3ZpZGVkLCB0aGVuIHRoZSBsaW5rIGZ1bmN0aW9uIHdpbGwgY2xvbmUgdGhlDQogKiAgYHRlbXBsYXRlYCBhbmQgY2FsbCB0aGUgYGNsb25lQXR0YWNoRm5gIGZ1bmN0aW9uIGFsbG93aW5nIHRoZSBjYWxsZXIgdG8gYXR0YWNoIHRoZQ0KICogIGNsb25lZCBlbGVtZW50cyB0byB0aGUgRE9NIGRvY3VtZW50IGF0IHRoZSBhcHByb3ByaWF0ZSBwbGFjZS4gVGhlIGBjbG9uZUF0dGFjaEZuYCBpcw0KICogIGNhbGxlZCBhczogPGJyPiBgY2xvbmVBdHRhY2hGbihjbG9uZWRFbGVtZW50LCBzY29wZSlgIHdoZXJlOg0KICoNCiAqICAgICAgKiBgY2xvbmVkRWxlbWVudGAgLSBpcyBhIGNsb25lIG9mIHRoZSBvcmlnaW5hbCBgZWxlbWVudGAgcGFzc2VkIGludG8gdGhlIGNvbXBpbGVyLg0KICogICAgICAqIGBzY29wZWAgLSBpcyB0aGUgY3VycmVudCBzY29wZSB3aXRoIHdoaWNoIHRoZSBsaW5raW5nIGZ1bmN0aW9uIGlzIHdvcmtpbmcgd2l0aC4NCiAqDQogKiAgKiBgb3B0aW9uc2AgLSBBbiBvcHRpb25hbCBvYmplY3QgaGFzaCB3aXRoIGxpbmtpbmcgb3B0aW9ucy4gSWYgYG9wdGlvbnNgIGlzIHByb3ZpZGVkLCB0aGVuIHRoZSBmb2xsb3dpbmcNCiAqICBrZXlzIG1heSBiZSB1c2VkIHRvIGNvbnRyb2wgbGlua2luZyBiZWhhdmlvcjoNCiAqDQogKiAgICAgICogYHBhcmVudEJvdW5kVHJhbnNjbHVkZUZuYCAtIHRoZSB0cmFuc2NsdWRlIGZ1bmN0aW9uIG1hZGUgYXZhaWxhYmxlIHRvDQogKiAgICAgICAgZGlyZWN0aXZlczsgaWYgZ2l2ZW4sIGl0IHdpbGwgYmUgcGFzc2VkIHRocm91Z2ggdG8gdGhlIGxpbmsgZnVuY3Rpb25zIG9mDQogKiAgICAgICAgZGlyZWN0aXZlcyBmb3VuZCBpbiBgZWxlbWVudGAgZHVyaW5nIGNvbXBpbGF0aW9uLg0KICogICAgICAqIGB0cmFuc2NsdWRlQ29udHJvbGxlcnNgIC0gYW4gb2JqZWN0IGhhc2ggd2l0aCBrZXlzIHRoYXQgbWFwIGNvbnRyb2xsZXIgbmFtZXMNCiAqICAgICAgICB0byBjb250cm9sbGVyIGluc3RhbmNlczsgaWYgZ2l2ZW4sIGl0IHdpbGwgbWFrZSB0aGUgY29udHJvbGxlcnMNCiAqICAgICAgICBhdmFpbGFibGUgdG8gZGlyZWN0aXZlcy4NCiAqICAgICAgKiBgZnV0dXJlUGFyZW50RWxlbWVudGAgLSBkZWZpbmVzIHRoZSBwYXJlbnQgdG8gd2hpY2ggdGhlIGBjbG9uZUF0dGFjaEZuYCB3aWxsIGFkZA0KICogICAgICAgIHRoZSBjbG9uZWQgZWxlbWVudHM7IG9ubHkgbmVlZGVkIGZvciB0cmFuc2NsdWRlcyB0aGF0IGFyZSBhbGxvd2VkIHRvIGNvbnRhaW4gbm9uIGh0bWwNCiAqICAgICAgICBlbGVtZW50cyAoZS5nLiBTVkcgZWxlbWVudHMpLiBTZWUgYWxzbyB0aGUgZGlyZWN0aXZlLmNvbnRyb2xsZXIgcHJvcGVydHkuDQogKg0KICogQ2FsbGluZyB0aGUgbGlua2luZyBmdW5jdGlvbiByZXR1cm5zIHRoZSBlbGVtZW50IG9mIHRoZSB0ZW1wbGF0ZS4gSXQgaXMgZWl0aGVyIHRoZSBvcmlnaW5hbA0KICogZWxlbWVudCBwYXNzZWQgaW4sIG9yIHRoZSBjbG9uZSBvZiB0aGUgZWxlbWVudCBpZiB0aGUgYGNsb25lQXR0YWNoRm5gIGlzIHByb3ZpZGVkLg0KICoNCiAqIEFmdGVyIGxpbmtpbmcgdGhlIHZpZXcgaXMgbm90IHVwZGF0ZWQgdW50aWwgYWZ0ZXIgYSBjYWxsIHRvICRkaWdlc3Qgd2hpY2ggdHlwaWNhbGx5IGlzIGRvbmUgYnkNCiAqIEFuZ3VsYXIgYXV0b21hdGljYWxseS4NCiAqDQogKiBJZiB5b3UgbmVlZCBhY2Nlc3MgdG8gdGhlIGJvdW5kIHZpZXcsIHRoZXJlIGFyZSB0d28gd2F5cyB0byBkbyBpdDoNCiAqDQogKiAtIElmIHlvdSBhcmUgbm90IGFza2luZyB0aGUgbGlua2luZyBmdW5jdGlvbiB0byBjbG9uZSB0aGUgdGVtcGxhdGUsIGNyZWF0ZSB0aGUgRE9NIGVsZW1lbnQocykNCiAqICAgYmVmb3JlIHlvdSBzZW5kIHRoZW0gdG8gdGhlIGNvbXBpbGVyIGFuZCBrZWVwIHRoaXMgcmVmZXJlbmNlIGFyb3VuZC4NCiAqICAgYGBganMNCiAqICAgICB2YXIgZWxlbWVudCA9ICRjb21waWxlKCc8cD57e3RvdGFsfX08L3A+Jykoc2NvcGUpOw0KICogICBgYGANCiAqDQogKiAtIGlmIG9uIHRoZSBvdGhlciBoYW5kLCB5b3UgbmVlZCB0aGUgZWxlbWVudCB0byBiZSBjbG9uZWQsIHRoZSB2aWV3IHJlZmVyZW5jZSBmcm9tIHRoZSBvcmlnaW5hbA0KICogICBleGFtcGxlIHdvdWxkIG5vdCBwb2ludCB0byB0aGUgY2xvbmUsIGJ1dCByYXRoZXIgdG8gdGhlIG9yaWdpbmFsIHRlbXBsYXRlIHRoYXQgd2FzIGNsb25lZC4gSW4NCiAqICAgdGhpcyBjYXNlLCB5b3UgY2FuIGFjY2VzcyB0aGUgY2xvbmUgdmlhIHRoZSBjbG9uZUF0dGFjaEZuOg0KICogICBgYGBqcw0KICogICAgIHZhciB0ZW1wbGF0ZUVsZW1lbnQgPSBhbmd1bGFyLmVsZW1lbnQoJzxwPnt7dG90YWx9fTwvcD4nKSwNCiAqICAgICAgICAgc2NvcGUgPSAuLi4uOw0KICoNCiAqICAgICB2YXIgY2xvbmVkRWxlbWVudCA9ICRjb21waWxlKHRlbXBsYXRlRWxlbWVudCkoc2NvcGUsIGZ1bmN0aW9uKGNsb25lZEVsZW1lbnQsIHNjb3BlKSB7DQogKiAgICAgICAvL2F0dGFjaCB0aGUgY2xvbmUgdG8gRE9NIGRvY3VtZW50IGF0IHRoZSByaWdodCBwbGFjZQ0KICogICAgIH0pOw0KICoNCiAqICAgICAvL25vdyB3ZSBoYXZlIHJlZmVyZW5jZSB0byB0aGUgY2xvbmVkIERPTSB2aWEgYGNsb25lZEVsZW1lbnRgDQogKiAgIGBgYA0KICoNCiAqDQogKiBGb3IgaW5mb3JtYXRpb24gb24gaG93IHRoZSBjb21waWxlciB3b3Jrcywgc2VlIHRoZQ0KICoge0BsaW5rIGd1aWRlL2NvbXBpbGVyIEFuZ3VsYXIgSFRNTCBDb21waWxlcn0gc2VjdGlvbiBvZiB0aGUgRGV2ZWxvcGVyIEd1aWRlLg0KICovDQoNCnZhciAkY29tcGlsZU1pbkVyciA9IG1pbkVycignJGNvbXBpbGUnKTsNCg0KLyoqDQogKiBAbmdkb2MgcHJvdmlkZXINCiAqIEBuYW1lICRjb21waWxlUHJvdmlkZXINCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqLw0KJENvbXBpbGVQcm92aWRlci4kaW5qZWN0ID0gWyckcHJvdmlkZScsICckJHNhbml0aXplVXJpUHJvdmlkZXInXTsNCmZ1bmN0aW9uICRDb21waWxlUHJvdmlkZXIoJHByb3ZpZGUsICQkc2FuaXRpemVVcmlQcm92aWRlcikgew0KICB2YXIgaGFzRGlyZWN0aXZlcyA9IHt9LA0KICAgICAgU3VmZml4ID0gJ0RpcmVjdGl2ZScsDQogICAgICBDT01NRU5UX0RJUkVDVElWRV9SRUdFWFAgPSAvXlxzKmRpcmVjdGl2ZVw6XHMqKFtcd1wtXSspXHMrKC4qKSQvLA0KICAgICAgQ0xBU1NfRElSRUNUSVZFX1JFR0VYUCA9IC8oKFtcd1wtXSspKD86XDooW147XSspKT87PykvLA0KICAgICAgQUxMX09SX05PVEhJTkdfQVRUUlMgPSBtYWtlTWFwKCduZ1NyYyxuZ1NyY3NldCxzcmMsc3Jjc2V0JyksDQogICAgICBSRVFVSVJFX1BSRUZJWF9SRUdFWFAgPSAvXig/OihcXlxePyk/KFw/KT8oXF5cXj8pPyk/LzsNCg0KICAvLyBSZWY6IGh0dHA6Ly9kZXZlbG9wZXJzLndoYXR3Zy5vcmcvd2ViYXBwYXBpcy5odG1sI2V2ZW50LWhhbmRsZXItaWRsLWF0dHJpYnV0ZXMNCiAgLy8gVGhlIGFzc3VtcHRpb24gaXMgdGhhdCBmdXR1cmUgRE9NIGV2ZW50IGF0dHJpYnV0ZSBuYW1lcyB3aWxsIGJlZ2luIHdpdGgNCiAgLy8gJ29uJyBhbmQgYmUgY29tcG9zZWQgb2Ygb25seSBFbmdsaXNoIGxldHRlcnMuDQogIHZhciBFVkVOVF9IQU5ETEVSX0FUVFJfUkVHRVhQID0gL14ob25bYS16XSt8Zm9ybWFjdGlvbikkLzsNCg0KICBmdW5jdGlvbiBwYXJzZUlzb2xhdGVCaW5kaW5ncyhzY29wZSwgZGlyZWN0aXZlTmFtZSkgew0KICAgIHZhciBMT0NBTF9SRUdFWFAgPSAvXlxzKihbQCZdfD0oXCo/KSkoXD8/KVxzKihcdyopXHMqJC87DQoNCiAgICB2YXIgYmluZGluZ3MgPSB7fTsNCg0KICAgIGZvckVhY2goc2NvcGUsIGZ1bmN0aW9uKGRlZmluaXRpb24sIHNjb3BlTmFtZSkgew0KICAgICAgdmFyIG1hdGNoID0gZGVmaW5pdGlvbi5tYXRjaChMT0NBTF9SRUdFWFApOw0KDQogICAgICBpZiAoIW1hdGNoKSB7DQogICAgICAgIHRocm93ICRjb21waWxlTWluRXJyKCdpc2NwJywNCiAgICAgICAgICAgICJJbnZhbGlkIGlzb2xhdGUgc2NvcGUgZGVmaW5pdGlvbiBmb3IgZGlyZWN0aXZlICd7MH0nLiIgKw0KICAgICAgICAgICAgIiBEZWZpbml0aW9uOiB7Li4uIHsxfTogJ3syfScgLi4ufSIsDQogICAgICAgICAgICBkaXJlY3RpdmVOYW1lLCBzY29wZU5hbWUsIGRlZmluaXRpb24pOw0KICAgICAgfQ0KDQogICAgICBiaW5kaW5nc1tzY29wZU5hbWVdID0gew0KICAgICAgICBtb2RlOiBtYXRjaFsxXVswXSwNCiAgICAgICAgY29sbGVjdGlvbjogbWF0Y2hbMl0gPT09ICcqJywNCiAgICAgICAgb3B0aW9uYWw6IG1hdGNoWzNdID09PSAnPycsDQogICAgICAgIGF0dHJOYW1lOiBtYXRjaFs0XSB8fCBzY29wZU5hbWUNCiAgICAgIH07DQogICAgfSk7DQoNCiAgICByZXR1cm4gYmluZGluZ3M7DQogIH0NCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkY29tcGlsZVByb3ZpZGVyI2RpcmVjdGl2ZQ0KICAgKiBAa2luZCBmdW5jdGlvbg0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogUmVnaXN0ZXIgYSBuZXcgZGlyZWN0aXZlIHdpdGggdGhlIGNvbXBpbGVyLg0KICAgKg0KICAgKiBAcGFyYW0ge3N0cmluZ3xPYmplY3R9IG5hbWUgTmFtZSBvZiB0aGUgZGlyZWN0aXZlIGluIGNhbWVsLWNhc2UgKGkuZS4gPGNvZGU+bmdCaW5kPC9jb2RlPiB3aGljaA0KICAgKiAgICB3aWxsIG1hdGNoIGFzIDxjb2RlPm5nLWJpbmQ8L2NvZGU+KSwgb3IgYW4gb2JqZWN0IG1hcCBvZiBkaXJlY3RpdmVzIHdoZXJlIHRoZSBrZXlzIGFyZSB0aGUNCiAgICogICAgbmFtZXMgYW5kIHRoZSB2YWx1ZXMgYXJlIHRoZSBmYWN0b3JpZXMuDQogICAqIEBwYXJhbSB7RnVuY3Rpb258QXJyYXl9IGRpcmVjdGl2ZUZhY3RvcnkgQW4gaW5qZWN0YWJsZSBkaXJlY3RpdmUgZmFjdG9yeSBmdW5jdGlvbi4gU2VlDQogICAqICAgIHtAbGluayBndWlkZS9kaXJlY3RpdmV9IGZvciBtb3JlIGluZm8uDQogICAqIEByZXR1cm5zIHtuZy4kY29tcGlsZVByb3ZpZGVyfSBTZWxmIGZvciBjaGFpbmluZy4NCiAgICovDQogICB0aGlzLmRpcmVjdGl2ZSA9IGZ1bmN0aW9uIHJlZ2lzdGVyRGlyZWN0aXZlKG5hbWUsIGRpcmVjdGl2ZUZhY3RvcnkpIHsNCiAgICBhc3NlcnROb3RIYXNPd25Qcm9wZXJ0eShuYW1lLCAnZGlyZWN0aXZlJyk7DQogICAgaWYgKGlzU3RyaW5nKG5hbWUpKSB7DQogICAgICBhc3NlcnRBcmcoZGlyZWN0aXZlRmFjdG9yeSwgJ2RpcmVjdGl2ZUZhY3RvcnknKTsNCiAgICAgIGlmICghaGFzRGlyZWN0aXZlcy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgew0KICAgICAgICBoYXNEaXJlY3RpdmVzW25hbWVdID0gW107DQogICAgICAgICRwcm92aWRlLmZhY3RvcnkobmFtZSArIFN1ZmZpeCwgWyckaW5qZWN0b3InLCAnJGV4Y2VwdGlvbkhhbmRsZXInLA0KICAgICAgICAgIGZ1bmN0aW9uKCRpbmplY3RvciwgJGV4Y2VwdGlvbkhhbmRsZXIpIHsNCiAgICAgICAgICAgIHZhciBkaXJlY3RpdmVzID0gW107DQogICAgICAgICAgICBmb3JFYWNoKGhhc0RpcmVjdGl2ZXNbbmFtZV0sIGZ1bmN0aW9uKGRpcmVjdGl2ZUZhY3RvcnksIGluZGV4KSB7DQogICAgICAgICAgICAgIHRyeSB7DQogICAgICAgICAgICAgICAgdmFyIGRpcmVjdGl2ZSA9ICRpbmplY3Rvci5pbnZva2UoZGlyZWN0aXZlRmFjdG9yeSk7DQogICAgICAgICAgICAgICAgaWYgKGlzRnVuY3Rpb24oZGlyZWN0aXZlKSkgew0KICAgICAgICAgICAgICAgICAgZGlyZWN0aXZlID0geyBjb21waWxlOiB2YWx1ZUZuKGRpcmVjdGl2ZSkgfTsNCiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFkaXJlY3RpdmUuY29tcGlsZSAmJiBkaXJlY3RpdmUubGluaykgew0KICAgICAgICAgICAgICAgICAgZGlyZWN0aXZlLmNvbXBpbGUgPSB2YWx1ZUZuKGRpcmVjdGl2ZS5saW5rKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgZGlyZWN0aXZlLnByaW9yaXR5ID0gZGlyZWN0aXZlLnByaW9yaXR5IHx8IDA7DQogICAgICAgICAgICAgICAgZGlyZWN0aXZlLmluZGV4ID0gaW5kZXg7DQogICAgICAgICAgICAgICAgZGlyZWN0aXZlLm5hbWUgPSBkaXJlY3RpdmUubmFtZSB8fCBuYW1lOw0KICAgICAgICAgICAgICAgIGRpcmVjdGl2ZS5yZXF1aXJlID0gZGlyZWN0aXZlLnJlcXVpcmUgfHwgKGRpcmVjdGl2ZS5jb250cm9sbGVyICYmIGRpcmVjdGl2ZS5uYW1lKTsNCiAgICAgICAgICAgICAgICBkaXJlY3RpdmUucmVzdHJpY3QgPSBkaXJlY3RpdmUucmVzdHJpY3QgfHwgJ0VBJzsNCiAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QoZGlyZWN0aXZlLnNjb3BlKSkgew0KICAgICAgICAgICAgICAgICAgZGlyZWN0aXZlLiQkaXNvbGF0ZUJpbmRpbmdzID0gcGFyc2VJc29sYXRlQmluZGluZ3MoZGlyZWN0aXZlLnNjb3BlLCBkaXJlY3RpdmUubmFtZSk7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGRpcmVjdGl2ZXMucHVzaChkaXJlY3RpdmUpOw0KICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7DQogICAgICAgICAgICAgICAgJGV4Y2VwdGlvbkhhbmRsZXIoZSk7DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0pOw0KICAgICAgICAgICAgcmV0dXJuIGRpcmVjdGl2ZXM7DQogICAgICAgICAgfV0pOw0KICAgICAgfQ0KICAgICAgaGFzRGlyZWN0aXZlc1tuYW1lXS5wdXNoKGRpcmVjdGl2ZUZhY3RvcnkpOw0KICAgIH0gZWxzZSB7DQogICAgICBmb3JFYWNoKG5hbWUsIHJldmVyc2VQYXJhbXMocmVnaXN0ZXJEaXJlY3RpdmUpKTsNCiAgICB9DQogICAgcmV0dXJuIHRoaXM7DQogIH07DQoNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkY29tcGlsZVByb3ZpZGVyI2FIcmVmU2FuaXRpemF0aW9uV2hpdGVsaXN0DQogICAqIEBraW5kIGZ1bmN0aW9uDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBSZXRyaWV2ZXMgb3Igb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IHJlZ3VsYXIgZXhwcmVzc2lvbiB0aGF0IGlzIHVzZWQgZm9yIHdoaXRlbGlzdGluZyBvZiBzYWZlDQogICAqIHVybHMgZHVyaW5nIGFbaHJlZl0gc2FuaXRpemF0aW9uLg0KICAgKg0KICAgKiBUaGUgc2FuaXRpemF0aW9uIGlzIGEgc2VjdXJpdHkgbWVhc3VyZSBhaW1lZCBhdCBwcmV2ZW50aW5nIFhTUyBhdHRhY2tzIHZpYSBodG1sIGxpbmtzLg0KICAgKg0KICAgKiBBbnkgdXJsIGFib3V0IHRvIGJlIGFzc2lnbmVkIHRvIGFbaHJlZl0gdmlhIGRhdGEtYmluZGluZyBpcyBmaXJzdCBub3JtYWxpemVkIGFuZCB0dXJuZWQgaW50bw0KICAgKiBhbiBhYnNvbHV0ZSB1cmwuIEFmdGVyd2FyZHMsIHRoZSB1cmwgaXMgbWF0Y2hlZCBhZ2FpbnN0IHRoZSBgYUhyZWZTYW5pdGl6YXRpb25XaGl0ZWxpc3RgDQogICAqIHJlZ3VsYXIgZXhwcmVzc2lvbi4gSWYgYSBtYXRjaCBpcyBmb3VuZCwgdGhlIG9yaWdpbmFsIHVybCBpcyB3cml0dGVuIGludG8gdGhlIGRvbS4gT3RoZXJ3aXNlLA0KICAgKiB0aGUgYWJzb2x1dGUgdXJsIGlzIHByZWZpeGVkIHdpdGggYCd1bnNhZmU6J2Agc3RyaW5nIGFuZCBvbmx5IHRoZW4gaXMgaXQgd3JpdHRlbiBpbnRvIHRoZSBET00uDQogICAqDQogICAqIEBwYXJhbSB7UmVnRXhwPX0gcmVnZXhwIE5ldyByZWdleHAgdG8gd2hpdGVsaXN0IHVybHMgd2l0aC4NCiAgICogQHJldHVybnMge1JlZ0V4cHxuZy4kY29tcGlsZVByb3ZpZGVyfSBDdXJyZW50IFJlZ0V4cCBpZiBjYWxsZWQgd2l0aG91dCB2YWx1ZSBvciBzZWxmIGZvcg0KICAgKiAgICBjaGFpbmluZyBvdGhlcndpc2UuDQogICAqLw0KICB0aGlzLmFIcmVmU2FuaXRpemF0aW9uV2hpdGVsaXN0ID0gZnVuY3Rpb24ocmVnZXhwKSB7DQogICAgaWYgKGlzRGVmaW5lZChyZWdleHApKSB7DQogICAgICAkJHNhbml0aXplVXJpUHJvdmlkZXIuYUhyZWZTYW5pdGl6YXRpb25XaGl0ZWxpc3QocmVnZXhwKTsNCiAgICAgIHJldHVybiB0aGlzOw0KICAgIH0gZWxzZSB7DQogICAgICByZXR1cm4gJCRzYW5pdGl6ZVVyaVByb3ZpZGVyLmFIcmVmU2FuaXRpemF0aW9uV2hpdGVsaXN0KCk7DQogICAgfQ0KICB9Ow0KDQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgJGNvbXBpbGVQcm92aWRlciNpbWdTcmNTYW5pdGl6YXRpb25XaGl0ZWxpc3QNCiAgICogQGtpbmQgZnVuY3Rpb24NCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFJldHJpZXZlcyBvciBvdmVycmlkZXMgdGhlIGRlZmF1bHQgcmVndWxhciBleHByZXNzaW9uIHRoYXQgaXMgdXNlZCBmb3Igd2hpdGVsaXN0aW5nIG9mIHNhZmUNCiAgICogdXJscyBkdXJpbmcgaW1nW3NyY10gc2FuaXRpemF0aW9uLg0KICAgKg0KICAgKiBUaGUgc2FuaXRpemF0aW9uIGlzIGEgc2VjdXJpdHkgbWVhc3VyZSBhaW1lZCBhdCBwcmV2ZW50IFhTUyBhdHRhY2tzIHZpYSBodG1sIGxpbmtzLg0KICAgKg0KICAgKiBBbnkgdXJsIGFib3V0IHRvIGJlIGFzc2lnbmVkIHRvIGltZ1tzcmNdIHZpYSBkYXRhLWJpbmRpbmcgaXMgZmlyc3Qgbm9ybWFsaXplZCBhbmQgdHVybmVkIGludG8NCiAgICogYW4gYWJzb2x1dGUgdXJsLiBBZnRlcndhcmRzLCB0aGUgdXJsIGlzIG1hdGNoZWQgYWdhaW5zdCB0aGUgYGltZ1NyY1Nhbml0aXphdGlvbldoaXRlbGlzdGANCiAgICogcmVndWxhciBleHByZXNzaW9uLiBJZiBhIG1hdGNoIGlzIGZvdW5kLCB0aGUgb3JpZ2luYWwgdXJsIGlzIHdyaXR0ZW4gaW50byB0aGUgZG9tLiBPdGhlcndpc2UsDQogICAqIHRoZSBhYnNvbHV0ZSB1cmwgaXMgcHJlZml4ZWQgd2l0aCBgJ3Vuc2FmZTonYCBzdHJpbmcgYW5kIG9ubHkgdGhlbiBpcyBpdCB3cml0dGVuIGludG8gdGhlIERPTS4NCiAgICoNCiAgICogQHBhcmFtIHtSZWdFeHA9fSByZWdleHAgTmV3IHJlZ2V4cCB0byB3aGl0ZWxpc3QgdXJscyB3aXRoLg0KICAgKiBAcmV0dXJucyB7UmVnRXhwfG5nLiRjb21waWxlUHJvdmlkZXJ9IEN1cnJlbnQgUmVnRXhwIGlmIGNhbGxlZCB3aXRob3V0IHZhbHVlIG9yIHNlbGYgZm9yDQogICAqICAgIGNoYWluaW5nIG90aGVyd2lzZS4NCiAgICovDQogIHRoaXMuaW1nU3JjU2FuaXRpemF0aW9uV2hpdGVsaXN0ID0gZnVuY3Rpb24ocmVnZXhwKSB7DQogICAgaWYgKGlzRGVmaW5lZChyZWdleHApKSB7DQogICAgICAkJHNhbml0aXplVXJpUHJvdmlkZXIuaW1nU3JjU2FuaXRpemF0aW9uV2hpdGVsaXN0KHJlZ2V4cCk7DQogICAgICByZXR1cm4gdGhpczsNCiAgICB9IGVsc2Ugew0KICAgICAgcmV0dXJuICQkc2FuaXRpemVVcmlQcm92aWRlci5pbWdTcmNTYW5pdGl6YXRpb25XaGl0ZWxpc3QoKTsNCiAgICB9DQogIH07DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgICRjb21waWxlUHJvdmlkZXIjZGVidWdJbmZvRW5hYmxlZA0KICAgKg0KICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBlbmFibGVkIHVwZGF0ZSB0aGUgZGVidWdJbmZvRW5hYmxlZCBzdGF0ZSBpZiBwcm92aWRlZCwgb3RoZXJ3aXNlIGp1c3QgcmV0dXJuIHRoZQ0KICAgKiBjdXJyZW50IGRlYnVnSW5mb0VuYWJsZWQgc3RhdGUNCiAgICogQHJldHVybnMgeyp9IGN1cnJlbnQgdmFsdWUgaWYgdXNlZCBhcyBnZXR0ZXIgb3IgaXRzZWxmIChjaGFpbmluZykgaWYgdXNlZCBhcyBzZXR0ZXINCiAgICoNCiAgICogQGtpbmQgZnVuY3Rpb24NCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIENhbGwgdGhpcyBtZXRob2QgdG8gZW5hYmxlL2Rpc2FibGUgdmFyaW91cyBkZWJ1ZyBydW50aW1lIGluZm9ybWF0aW9uIGluIHRoZSBjb21waWxlciBzdWNoIGFzIGFkZGluZw0KICAgKiBiaW5kaW5nIGluZm9ybWF0aW9uIGFuZCBhIHJlZmVyZW5jZSB0byB0aGUgY3VycmVudCBzY29wZSBvbiB0byBET00gZWxlbWVudHMuDQogICAqIElmIGVuYWJsZWQsIHRoZSBjb21waWxlciB3aWxsIGFkZCB0aGUgZm9sbG93aW5nIHRvIERPTSBlbGVtZW50cyB0aGF0IGhhdmUgYmVlbiBib3VuZCB0byB0aGUgc2NvcGUNCiAgICogKiBgbmctYmluZGluZ2AgQ1NTIGNsYXNzDQogICAqICogYCRiaW5kaW5nYCBkYXRhIHByb3BlcnR5IGNvbnRhaW5pbmcgYW4gYXJyYXkgb2YgdGhlIGJpbmRpbmcgZXhwcmVzc2lvbnMNCiAgICoNCiAgICogWW91IG1heSB3YW50IHRvIGRpc2FibGUgdGhpcyBpbiBwcm9kdWN0aW9uIGZvciBhIHNpZ25pZmljYW50IHBlcmZvcm1hbmNlIGJvb3N0LiBTZWUNCiAgICoge0BsaW5rIGd1aWRlL3Byb2R1Y3Rpb24jZGlzYWJsaW5nLWRlYnVnLWRhdGEgRGlzYWJsaW5nIERlYnVnIERhdGF9IGZvciBtb3JlLg0KICAgKg0KICAgKiBUaGUgZGVmYXVsdCB2YWx1ZSBpcyB0cnVlLg0KICAgKi8NCiAgdmFyIGRlYnVnSW5mb0VuYWJsZWQgPSB0cnVlOw0KICB0aGlzLmRlYnVnSW5mb0VuYWJsZWQgPSBmdW5jdGlvbihlbmFibGVkKSB7DQogICAgaWYgKGlzRGVmaW5lZChlbmFibGVkKSkgew0KICAgICAgZGVidWdJbmZvRW5hYmxlZCA9IGVuYWJsZWQ7DQogICAgICByZXR1cm4gdGhpczsNCiAgICB9DQogICAgcmV0dXJuIGRlYnVnSW5mb0VuYWJsZWQ7DQogIH07DQoNCiAgdGhpcy4kZ2V0ID0gWw0KICAgICAgICAgICAgJyRpbmplY3RvcicsICckaW50ZXJwb2xhdGUnLCAnJGV4Y2VwdGlvbkhhbmRsZXInLCAnJHRlbXBsYXRlUmVxdWVzdCcsICckcGFyc2UnLA0KICAgICAgICAgICAgJyRjb250cm9sbGVyJywgJyRyb290U2NvcGUnLCAnJGRvY3VtZW50JywgJyRzY2UnLCAnJGFuaW1hdGUnLCAnJCRzYW5pdGl6ZVVyaScsDQogICAgZnVuY3Rpb24oJGluamVjdG9yLCAgICRpbnRlcnBvbGF0ZSwgICAkZXhjZXB0aW9uSGFuZGxlciwgICAkdGVtcGxhdGVSZXF1ZXN0LCAgICRwYXJzZSwNCiAgICAgICAgICAgICAkY29udHJvbGxlciwgICAkcm9vdFNjb3BlLCAgICRkb2N1bWVudCwgICAkc2NlLCAgICRhbmltYXRlLCAgICQkc2FuaXRpemVVcmkpIHsNCg0KICAgIHZhciBBdHRyaWJ1dGVzID0gZnVuY3Rpb24oZWxlbWVudCwgYXR0cmlidXRlc1RvQ29weSkgew0KICAgICAgaWYgKGF0dHJpYnV0ZXNUb0NvcHkpIHsNCiAgICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhhdHRyaWJ1dGVzVG9Db3B5KTsNCiAgICAgICAgdmFyIGksIGwsIGtleTsNCg0KICAgICAgICBmb3IgKGkgPSAwLCBsID0ga2V5cy5sZW5ndGg7IGkgPCBsOyBpKyspIHsNCiAgICAgICAgICBrZXkgPSBrZXlzW2ldOw0KICAgICAgICAgIHRoaXNba2V5XSA9IGF0dHJpYnV0ZXNUb0NvcHlba2V5XTsNCiAgICAgICAgfQ0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgdGhpcy4kYXR0ciA9IHt9Ow0KICAgICAgfQ0KDQogICAgICB0aGlzLiQkZWxlbWVudCA9IGVsZW1lbnQ7DQogICAgfTsNCg0KICAgIEF0dHJpYnV0ZXMucHJvdG90eXBlID0gew0KICAgICAgLyoqDQogICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgKiBAbmFtZSAkY29tcGlsZS5kaXJlY3RpdmUuQXR0cmlidXRlcyMkbm9ybWFsaXplDQogICAgICAgKiBAa2luZCBmdW5jdGlvbg0KICAgICAgICoNCiAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICogQ29udmVydHMgYW4gYXR0cmlidXRlIG5hbWUgKGUuZy4gZGFzaC9jb2xvbi91bmRlcnNjb3JlLWRlbGltaXRlZCBzdHJpbmcsIG9wdGlvbmFsbHkgcHJlZml4ZWQgd2l0aCBgeC1gIG9yDQogICAgICAgKiBgZGF0YS1gKSB0byBpdHMgbm9ybWFsaXplZCwgY2FtZWxDYXNlIGZvcm0uDQogICAgICAgKg0KICAgICAgICogQWxzbyB0aGVyZSBpcyBzcGVjaWFsIGNhc2UgZm9yIE1veiBwcmVmaXggc3RhcnRpbmcgd2l0aCB1cHBlciBjYXNlIGxldHRlci4NCiAgICAgICAqDQogICAgICAgKiBGb3IgZnVydGhlciBpbmZvcm1hdGlvbiBjaGVjayBvdXQgdGhlIGd1aWRlIG9uIHtAbGluayBndWlkZS9kaXJlY3RpdmUjbWF0Y2hpbmctZGlyZWN0aXZlcyBNYXRjaGluZyBEaXJlY3RpdmVzfQ0KICAgICAgICoNCiAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIE5hbWUgdG8gbm9ybWFsaXplDQogICAgICAgKi8NCiAgICAgICRub3JtYWxpemU6IGRpcmVjdGl2ZU5vcm1hbGl6ZSwNCg0KDQogICAgICAvKioNCiAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAqIEBuYW1lICRjb21waWxlLmRpcmVjdGl2ZS5BdHRyaWJ1dGVzIyRhZGRDbGFzcw0KICAgICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgICAqDQogICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAqIEFkZHMgdGhlIENTUyBjbGFzcyB2YWx1ZSBzcGVjaWZpZWQgYnkgdGhlIGNsYXNzVmFsIHBhcmFtZXRlciB0byB0aGUgZWxlbWVudC4gSWYgYW5pbWF0aW9ucw0KICAgICAgICogYXJlIGVuYWJsZWQgdGhlbiBhbiBhbmltYXRpb24gd2lsbCBiZSB0cmlnZ2VyZWQgZm9yIHRoZSBjbGFzcyBhZGRpdGlvbi4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NWYWwgVGhlIGNsYXNzTmFtZSB2YWx1ZSB0aGF0IHdpbGwgYmUgYWRkZWQgdG8gdGhlIGVsZW1lbnQNCiAgICAgICAqLw0KICAgICAgJGFkZENsYXNzOiBmdW5jdGlvbihjbGFzc1ZhbCkgew0KICAgICAgICBpZiAoY2xhc3NWYWwgJiYgY2xhc3NWYWwubGVuZ3RoID4gMCkgew0KICAgICAgICAgICRhbmltYXRlLmFkZENsYXNzKHRoaXMuJCRlbGVtZW50LCBjbGFzc1ZhbCk7DQogICAgICAgIH0NCiAgICAgIH0sDQoNCiAgICAgIC8qKg0KICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICogQG5hbWUgJGNvbXBpbGUuZGlyZWN0aXZlLkF0dHJpYnV0ZXMjJHJlbW92ZUNsYXNzDQogICAgICAgKiBAa2luZCBmdW5jdGlvbg0KICAgICAgICoNCiAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICogUmVtb3ZlcyB0aGUgQ1NTIGNsYXNzIHZhbHVlIHNwZWNpZmllZCBieSB0aGUgY2xhc3NWYWwgcGFyYW1ldGVyIGZyb20gdGhlIGVsZW1lbnQuIElmDQogICAgICAgKiBhbmltYXRpb25zIGFyZSBlbmFibGVkIHRoZW4gYW4gYW5pbWF0aW9uIHdpbGwgYmUgdHJpZ2dlcmVkIGZvciB0aGUgY2xhc3MgcmVtb3ZhbC4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NWYWwgVGhlIGNsYXNzTmFtZSB2YWx1ZSB0aGF0IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBlbGVtZW50DQogICAgICAgKi8NCiAgICAgICRyZW1vdmVDbGFzczogZnVuY3Rpb24oY2xhc3NWYWwpIHsNCiAgICAgICAgaWYgKGNsYXNzVmFsICYmIGNsYXNzVmFsLmxlbmd0aCA+IDApIHsNCiAgICAgICAgICAkYW5pbWF0ZS5yZW1vdmVDbGFzcyh0aGlzLiQkZWxlbWVudCwgY2xhc3NWYWwpOw0KICAgICAgICB9DQogICAgICB9LA0KDQogICAgICAvKioNCiAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAqIEBuYW1lICRjb21waWxlLmRpcmVjdGl2ZS5BdHRyaWJ1dGVzIyR1cGRhdGVDbGFzcw0KICAgICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgICAqDQogICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAqIEFkZHMgYW5kIHJlbW92ZXMgdGhlIGFwcHJvcHJpYXRlIENTUyBjbGFzcyB2YWx1ZXMgdG8gdGhlIGVsZW1lbnQgYmFzZWQgb24gdGhlIGRpZmZlcmVuY2UNCiAgICAgICAqIGJldHdlZW4gdGhlIG5ldyBhbmQgb2xkIENTUyBjbGFzcyB2YWx1ZXMgKHNwZWNpZmllZCBhcyBuZXdDbGFzc2VzIGFuZCBvbGRDbGFzc2VzKS4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmV3Q2xhc3NlcyBUaGUgY3VycmVudCBDU1MgY2xhc3NOYW1lIHZhbHVlDQogICAgICAgKiBAcGFyYW0ge3N0cmluZ30gb2xkQ2xhc3NlcyBUaGUgZm9ybWVyIENTUyBjbGFzc05hbWUgdmFsdWUNCiAgICAgICAqLw0KICAgICAgJHVwZGF0ZUNsYXNzOiBmdW5jdGlvbihuZXdDbGFzc2VzLCBvbGRDbGFzc2VzKSB7DQogICAgICAgIHZhciB0b0FkZCA9IHRva2VuRGlmZmVyZW5jZShuZXdDbGFzc2VzLCBvbGRDbGFzc2VzKTsNCiAgICAgICAgaWYgKHRvQWRkICYmIHRvQWRkLmxlbmd0aCkgew0KICAgICAgICAgICRhbmltYXRlLmFkZENsYXNzKHRoaXMuJCRlbGVtZW50LCB0b0FkZCk7DQogICAgICAgIH0NCg0KICAgICAgICB2YXIgdG9SZW1vdmUgPSB0b2tlbkRpZmZlcmVuY2Uob2xkQ2xhc3NlcywgbmV3Q2xhc3Nlcyk7DQogICAgICAgIGlmICh0b1JlbW92ZSAmJiB0b1JlbW92ZS5sZW5ndGgpIHsNCiAgICAgICAgICAkYW5pbWF0ZS5yZW1vdmVDbGFzcyh0aGlzLiQkZWxlbWVudCwgdG9SZW1vdmUpOw0KICAgICAgICB9DQogICAgICB9LA0KDQogICAgICAvKioNCiAgICAgICAqIFNldCBhIG5vcm1hbGl6ZWQgYXR0cmlidXRlIG9uIHRoZSBlbGVtZW50IGluIGEgd2F5IHN1Y2ggdGhhdCBhbGwgZGlyZWN0aXZlcw0KICAgICAgICogY2FuIHNoYXJlIHRoZSBhdHRyaWJ1dGUuIFRoaXMgZnVuY3Rpb24gcHJvcGVybHkgaGFuZGxlcyBib29sZWFuIGF0dHJpYnV0ZXMuDQogICAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IE5vcm1hbGl6ZWQga2V5LiAoaWUgbmdBdHRyaWJ1dGUpDQogICAgICAgKiBAcGFyYW0ge3N0cmluZ3xib29sZWFufSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LiBJZiBgbnVsbGAgYXR0cmlidXRlIHdpbGwgYmUgZGVsZXRlZC4NCiAgICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IHdyaXRlQXR0ciBJZiBmYWxzZSwgZG9lcyBub3Qgd3JpdGUgdGhlIHZhbHVlIHRvIERPTSBlbGVtZW50IGF0dHJpYnV0ZS4NCiAgICAgICAqICAgICBEZWZhdWx0cyB0byB0cnVlLg0KICAgICAgICogQHBhcmFtIHtzdHJpbmc9fSBhdHRyTmFtZSBPcHRpb25hbCBub25lIG5vcm1hbGl6ZWQgbmFtZS4gRGVmYXVsdHMgdG8ga2V5Lg0KICAgICAgICovDQogICAgICAkc2V0OiBmdW5jdGlvbihrZXksIHZhbHVlLCB3cml0ZUF0dHIsIGF0dHJOYW1lKSB7DQogICAgICAgIC8vIFRPRE86IGRlY2lkZSB3aGV0aGVyIG9yIG5vdCB0byB0aHJvdyBhbiBlcnJvciBpZiAiY2xhc3MiDQogICAgICAgIC8vaXMgc2V0IHRocm91Z2ggdGhpcyBmdW5jdGlvbiBzaW5jZSBpdCBtYXkgY2F1c2UgJHVwZGF0ZUNsYXNzIHRvDQogICAgICAgIC8vYmVjb21lIHVuc3RhYmxlLg0KDQogICAgICAgIHZhciBub2RlID0gdGhpcy4kJGVsZW1lbnRbMF0sDQogICAgICAgICAgICBib29sZWFuS2V5ID0gZ2V0Qm9vbGVhbkF0dHJOYW1lKG5vZGUsIGtleSksDQogICAgICAgICAgICBhbGlhc2VkS2V5ID0gZ2V0QWxpYXNlZEF0dHJOYW1lKG5vZGUsIGtleSksDQogICAgICAgICAgICBvYnNlcnZlciA9IGtleSwNCiAgICAgICAgICAgIG5vZGVOYW1lOw0KDQogICAgICAgIGlmIChib29sZWFuS2V5KSB7DQogICAgICAgICAgdGhpcy4kJGVsZW1lbnQucHJvcChrZXksIHZhbHVlKTsNCiAgICAgICAgICBhdHRyTmFtZSA9IGJvb2xlYW5LZXk7DQogICAgICAgIH0gZWxzZSBpZiAoYWxpYXNlZEtleSkgew0KICAgICAgICAgIHRoaXNbYWxpYXNlZEtleV0gPSB2YWx1ZTsNCiAgICAgICAgICBvYnNlcnZlciA9IGFsaWFzZWRLZXk7DQogICAgICAgIH0NCg0KICAgICAgICB0aGlzW2tleV0gPSB2YWx1ZTsNCg0KICAgICAgICAvLyB0cmFuc2xhdGUgbm9ybWFsaXplZCBrZXkgdG8gYWN0dWFsIGtleQ0KICAgICAgICBpZiAoYXR0ck5hbWUpIHsNCiAgICAgICAgICB0aGlzLiRhdHRyW2tleV0gPSBhdHRyTmFtZTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBhdHRyTmFtZSA9IHRoaXMuJGF0dHJba2V5XTsNCiAgICAgICAgICBpZiAoIWF0dHJOYW1lKSB7DQogICAgICAgICAgICB0aGlzLiRhdHRyW2tleV0gPSBhdHRyTmFtZSA9IHNuYWtlX2Nhc2Uoa2V5LCAnLScpOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIG5vZGVOYW1lID0gbm9kZU5hbWVfKHRoaXMuJCRlbGVtZW50KTsNCg0KICAgICAgICBpZiAoKG5vZGVOYW1lID09PSAnYScgJiYga2V5ID09PSAnaHJlZicpIHx8DQogICAgICAgICAgICAobm9kZU5hbWUgPT09ICdpbWcnICYmIGtleSA9PT0gJ3NyYycpKSB7DQogICAgICAgICAgLy8gc2FuaXRpemUgYVtocmVmXSBhbmQgaW1nW3NyY10gdmFsdWVzDQogICAgICAgICAgdGhpc1trZXldID0gdmFsdWUgPSAkJHNhbml0aXplVXJpKHZhbHVlLCBrZXkgPT09ICdzcmMnKTsNCiAgICAgICAgfSBlbHNlIGlmIChub2RlTmFtZSA9PT0gJ2ltZycgJiYga2V5ID09PSAnc3Jjc2V0Jykgew0KICAgICAgICAgIC8vIHNhbml0aXplIGltZ1tzcmNzZXRdIHZhbHVlcw0KICAgICAgICAgIHZhciByZXN1bHQgPSAiIjsNCg0KICAgICAgICAgIC8vIGZpcnN0IGNoZWNrIGlmIHRoZXJlIGFyZSBzcGFjZXMgYmVjYXVzZSBpdCdzIG5vdCB0aGUgc2FtZSBwYXR0ZXJuDQogICAgICAgICAgdmFyIHRyaW1tZWRTcmNzZXQgPSB0cmltKHZhbHVlKTsNCiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAoICAgOTk5eCAgICx8ICAgOTk5dyAgICx8ICAgLHwsICAgKQ0KICAgICAgICAgIHZhciBzcmNQYXR0ZXJuID0gLyhccytcZCt4XHMqLHxccytcZCt3XHMqLHxccyssfCxccyspLzsNCiAgICAgICAgICB2YXIgcGF0dGVybiA9IC9ccy8udGVzdCh0cmltbWVkU3Jjc2V0KSA/IHNyY1BhdHRlcm4gOiAvKCwpLzsNCg0KICAgICAgICAgIC8vIHNwbGl0IHNyY3NldCBpbnRvIHR1cGxlIG9mIHVyaSBhbmQgZGVzY3JpcHRvciBleGNlcHQgZm9yIHRoZSBsYXN0IGl0ZW0NCiAgICAgICAgICB2YXIgcmF3VXJpcyA9IHRyaW1tZWRTcmNzZXQuc3BsaXQocGF0dGVybik7DQoNCiAgICAgICAgICAvLyBmb3IgZWFjaCB0dXBsZXMNCiAgICAgICAgICB2YXIgbmJyVXJpc1dpdGgycGFydHMgPSBNYXRoLmZsb29yKHJhd1VyaXMubGVuZ3RoIC8gMik7DQogICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYnJVcmlzV2l0aDJwYXJ0czsgaSsrKSB7DQogICAgICAgICAgICB2YXIgaW5uZXJJZHggPSBpICogMjsNCiAgICAgICAgICAgIC8vIHNhbml0aXplIHRoZSB1cmkNCiAgICAgICAgICAgIHJlc3VsdCArPSAkJHNhbml0aXplVXJpKHRyaW0ocmF3VXJpc1tpbm5lcklkeF0pLCB0cnVlKTsNCiAgICAgICAgICAgIC8vIGFkZCB0aGUgZGVzY3JpcHRvcg0KICAgICAgICAgICAgcmVzdWx0ICs9ICgiICIgKyB0cmltKHJhd1VyaXNbaW5uZXJJZHggKyAxXSkpOw0KICAgICAgICAgIH0NCg0KICAgICAgICAgIC8vIHNwbGl0IHRoZSBsYXN0IGl0ZW0gaW50byB1cmkgYW5kIGRlc2NyaXB0b3INCiAgICAgICAgICB2YXIgbGFzdFR1cGxlID0gdHJpbShyYXdVcmlzW2kgKiAyXSkuc3BsaXQoL1xzLyk7DQoNCiAgICAgICAgICAvLyBzYW5pdGl6ZSB0aGUgbGFzdCB1cmkNCiAgICAgICAgICByZXN1bHQgKz0gJCRzYW5pdGl6ZVVyaSh0cmltKGxhc3RUdXBsZVswXSksIHRydWUpOw0KDQogICAgICAgICAgLy8gYW5kIGFkZCB0aGUgbGFzdCBkZXNjcmlwdG9yIGlmIGFueQ0KICAgICAgICAgIGlmIChsYXN0VHVwbGUubGVuZ3RoID09PSAyKSB7DQogICAgICAgICAgICByZXN1bHQgKz0gKCIgIiArIHRyaW0obGFzdFR1cGxlWzFdKSk7DQogICAgICAgICAgfQ0KICAgICAgICAgIHRoaXNba2V5XSA9IHZhbHVlID0gcmVzdWx0Ow0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKHdyaXRlQXR0ciAhPT0gZmFsc2UpIHsNCiAgICAgICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkgew0KICAgICAgICAgICAgdGhpcy4kJGVsZW1lbnQucmVtb3ZlQXR0cihhdHRyTmFtZSk7DQogICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIHRoaXMuJCRlbGVtZW50LmF0dHIoYXR0ck5hbWUsIHZhbHVlKTsNCiAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICAvLyBmaXJlIG9ic2VydmVycw0KICAgICAgICB2YXIgJCRvYnNlcnZlcnMgPSB0aGlzLiQkb2JzZXJ2ZXJzOw0KICAgICAgICAkJG9ic2VydmVycyAmJiBmb3JFYWNoKCQkb2JzZXJ2ZXJzW29ic2VydmVyXSwgZnVuY3Rpb24oZm4pIHsNCiAgICAgICAgICB0cnkgew0KICAgICAgICAgICAgZm4odmFsdWUpOw0KICAgICAgICAgIH0gY2F0Y2ggKGUpIHsNCiAgICAgICAgICAgICRleGNlcHRpb25IYW5kbGVyKGUpOw0KICAgICAgICAgIH0NCiAgICAgICAgfSk7DQogICAgICB9LA0KDQoNCiAgICAgIC8qKg0KICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICogQG5hbWUgJGNvbXBpbGUuZGlyZWN0aXZlLkF0dHJpYnV0ZXMjJG9ic2VydmUNCiAgICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICAgKg0KICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgKiBPYnNlcnZlcyBhbiBpbnRlcnBvbGF0ZWQgYXR0cmlidXRlLg0KICAgICAgICoNCiAgICAgICAqIFRoZSBvYnNlcnZlciBmdW5jdGlvbiB3aWxsIGJlIGludm9rZWQgb25jZSBkdXJpbmcgdGhlIG5leHQgYCRkaWdlc3RgIGZvbGxvd2luZw0KICAgICAgICogY29tcGlsYXRpb24uIFRoZSBvYnNlcnZlciBpcyB0aGVuIGludm9rZWQgd2hlbmV2ZXIgdGhlIGludGVycG9sYXRlZCB2YWx1ZQ0KICAgICAgICogY2hhbmdlcy4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IE5vcm1hbGl6ZWQga2V5LiAoaWUgbmdBdHRyaWJ1dGUpIC4NCiAgICAgICAqIEBwYXJhbSB7ZnVuY3Rpb24oaW50ZXJwb2xhdGVkVmFsdWUpfSBmbiBGdW5jdGlvbiB0aGF0IHdpbGwgYmUgY2FsbGVkIHdoZW5ldmVyDQogICAgICAgICAgICAgICAgdGhlIGludGVycG9sYXRlZCB2YWx1ZSBvZiB0aGUgYXR0cmlidXRlIGNoYW5nZXMuDQogICAgICAgKiAgICAgICAgU2VlIHRoZSB7QGxpbmsgZ3VpZGUvZGlyZWN0aXZlI3RleHQtYW5kLWF0dHJpYnV0ZS1iaW5kaW5ncyBEaXJlY3RpdmVzfSBndWlkZSBmb3IgbW9yZSBpbmZvLg0KICAgICAgICogQHJldHVybnMge2Z1bmN0aW9uKCl9IFJldHVybnMgYSBkZXJlZ2lzdHJhdGlvbiBmdW5jdGlvbiBmb3IgdGhpcyBvYnNlcnZlci4NCiAgICAgICAqLw0KICAgICAgJG9ic2VydmU6IGZ1bmN0aW9uKGtleSwgZm4pIHsNCiAgICAgICAgdmFyIGF0dHJzID0gdGhpcywNCiAgICAgICAgICAgICQkb2JzZXJ2ZXJzID0gKGF0dHJzLiQkb2JzZXJ2ZXJzIHx8IChhdHRycy4kJG9ic2VydmVycyA9IGNyZWF0ZU1hcCgpKSksDQogICAgICAgICAgICBsaXN0ZW5lcnMgPSAoJCRvYnNlcnZlcnNba2V5XSB8fCAoJCRvYnNlcnZlcnNba2V5XSA9IFtdKSk7DQoNCiAgICAgICAgbGlzdGVuZXJzLnB1c2goZm4pOw0KICAgICAgICAkcm9vdFNjb3BlLiRldmFsQXN5bmMoZnVuY3Rpb24oKSB7DQogICAgICAgICAgaWYgKCFsaXN0ZW5lcnMuJCRpbnRlciAmJiBhdHRycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7DQogICAgICAgICAgICAvLyBubyBvbmUgcmVnaXN0ZXJlZCBhdHRyaWJ1dGUgaW50ZXJwb2xhdGlvbiBmdW5jdGlvbiwgc28gbGV0cyBjYWxsIGl0IG1hbnVhbGx5DQogICAgICAgICAgICBmbihhdHRyc1trZXldKTsNCiAgICAgICAgICB9DQogICAgICAgIH0pOw0KDQogICAgICAgIHJldHVybiBmdW5jdGlvbigpIHsNCiAgICAgICAgICBhcnJheVJlbW92ZShsaXN0ZW5lcnMsIGZuKTsNCiAgICAgICAgfTsNCiAgICAgIH0NCiAgICB9Ow0KDQoNCiAgICBmdW5jdGlvbiBzYWZlQWRkQ2xhc3MoJGVsZW1lbnQsIGNsYXNzTmFtZSkgew0KICAgICAgdHJ5IHsNCiAgICAgICAgJGVsZW1lbnQuYWRkQ2xhc3MoY2xhc3NOYW1lKTsNCiAgICAgIH0gY2F0Y2ggKGUpIHsNCiAgICAgICAgLy8gaWdub3JlLCBzaW5jZSBpdCBtZWFucyB0aGF0IHdlIGFyZSB0cnlpbmcgdG8gc2V0IGNsYXNzIG9uDQogICAgICAgIC8vIFNWRyBlbGVtZW50LCB3aGVyZSBjbGFzcyBuYW1lIGlzIHJlYWQtb25seS4NCiAgICAgIH0NCiAgICB9DQoNCg0KICAgIHZhciBzdGFydFN5bWJvbCA9ICRpbnRlcnBvbGF0ZS5zdGFydFN5bWJvbCgpLA0KICAgICAgICBlbmRTeW1ib2wgPSAkaW50ZXJwb2xhdGUuZW5kU3ltYm9sKCksDQogICAgICAgIGRlbm9ybWFsaXplVGVtcGxhdGUgPSAoc3RhcnRTeW1ib2wgPT0gJ3t7JyB8fCBlbmRTeW1ib2wgID09ICd9fScpDQogICAgICAgICAgICA/IGlkZW50aXR5DQogICAgICAgICAgICA6IGZ1bmN0aW9uIGRlbm9ybWFsaXplVGVtcGxhdGUodGVtcGxhdGUpIHsNCiAgICAgICAgICAgICAgcmV0dXJuIHRlbXBsYXRlLnJlcGxhY2UoL1x7XHsvZywgc3RhcnRTeW1ib2wpLnJlcGxhY2UoL319L2csIGVuZFN5bWJvbCk7DQogICAgICAgIH0sDQogICAgICAgIE5HX0FUVFJfQklORElORyA9IC9ebmdBdHRyW0EtWl0vOw0KDQogICAgY29tcGlsZS4kJGFkZEJpbmRpbmdJbmZvID0gZGVidWdJbmZvRW5hYmxlZCA/IGZ1bmN0aW9uICQkYWRkQmluZGluZ0luZm8oJGVsZW1lbnQsIGJpbmRpbmcpIHsNCiAgICAgIHZhciBiaW5kaW5ncyA9ICRlbGVtZW50LmRhdGEoJyRiaW5kaW5nJykgfHwgW107DQoNCiAgICAgIGlmIChpc0FycmF5KGJpbmRpbmcpKSB7DQogICAgICAgIGJpbmRpbmdzID0gYmluZGluZ3MuY29uY2F0KGJpbmRpbmcpOw0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgYmluZGluZ3MucHVzaChiaW5kaW5nKTsNCiAgICAgIH0NCg0KICAgICAgJGVsZW1lbnQuZGF0YSgnJGJpbmRpbmcnLCBiaW5kaW5ncyk7DQogICAgfSA6IG5vb3A7DQoNCiAgICBjb21waWxlLiQkYWRkQmluZGluZ0NsYXNzID0gZGVidWdJbmZvRW5hYmxlZCA/IGZ1bmN0aW9uICQkYWRkQmluZGluZ0NsYXNzKCRlbGVtZW50KSB7DQogICAgICBzYWZlQWRkQ2xhc3MoJGVsZW1lbnQsICduZy1iaW5kaW5nJyk7DQogICAgfSA6IG5vb3A7DQoNCiAgICBjb21waWxlLiQkYWRkU2NvcGVJbmZvID0gZGVidWdJbmZvRW5hYmxlZCA/IGZ1bmN0aW9uICQkYWRkU2NvcGVJbmZvKCRlbGVtZW50LCBzY29wZSwgaXNvbGF0ZWQsIG5vVGVtcGxhdGUpIHsNCiAgICAgIHZhciBkYXRhTmFtZSA9IGlzb2xhdGVkID8gKG5vVGVtcGxhdGUgPyAnJGlzb2xhdGVTY29wZU5vVGVtcGxhdGUnIDogJyRpc29sYXRlU2NvcGUnKSA6ICckc2NvcGUnOw0KICAgICAgJGVsZW1lbnQuZGF0YShkYXRhTmFtZSwgc2NvcGUpOw0KICAgIH0gOiBub29wOw0KDQogICAgY29tcGlsZS4kJGFkZFNjb3BlQ2xhc3MgPSBkZWJ1Z0luZm9FbmFibGVkID8gZnVuY3Rpb24gJCRhZGRTY29wZUNsYXNzKCRlbGVtZW50LCBpc29sYXRlZCkgew0KICAgICAgc2FmZUFkZENsYXNzKCRlbGVtZW50LCBpc29sYXRlZCA/ICduZy1pc29sYXRlLXNjb3BlJyA6ICduZy1zY29wZScpOw0KICAgIH0gOiBub29wOw0KDQogICAgcmV0dXJuIGNvbXBpbGU7DQoNCiAgICAvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiAgICBmdW5jdGlvbiBjb21waWxlKCRjb21waWxlTm9kZXMsIHRyYW5zY2x1ZGVGbiwgbWF4UHJpb3JpdHksIGlnbm9yZURpcmVjdGl2ZSwNCiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzQ29tcGlsZUNvbnRleHQpIHsNCiAgICAgIGlmICghKCRjb21waWxlTm9kZXMgaW5zdGFuY2VvZiBqcUxpdGUpKSB7DQogICAgICAgIC8vIGpxdWVyeSBhbHdheXMgcmV3cmFwcywgd2hlcmVhcyB3ZSBuZWVkIHRvIHByZXNlcnZlIHRoZSBvcmlnaW5hbCBzZWxlY3RvciBzbyB0aGF0IHdlIGNhbg0KICAgICAgICAvLyBtb2RpZnkgaXQuDQogICAgICAgICRjb21waWxlTm9kZXMgPSBqcUxpdGUoJGNvbXBpbGVOb2Rlcyk7DQogICAgICB9DQogICAgICAvLyBXZSBjYW4gbm90IGNvbXBpbGUgdG9wIGxldmVsIHRleHQgZWxlbWVudHMgc2luY2UgdGV4dCBub2RlcyBjYW4gYmUgbWVyZ2VkIGFuZCB3ZSB3aWxsDQogICAgICAvLyBub3QgYmUgYWJsZSB0byBhdHRhY2ggc2NvcGUgZGF0YSB0byB0aGVtLCBzbyB3ZSB3aWxsIHdyYXAgdGhlbSBpbiA8c3Bhbj4NCiAgICAgIGZvckVhY2goJGNvbXBpbGVOb2RlcywgZnVuY3Rpb24obm9kZSwgaW5kZXgpIHsNCiAgICAgICAgaWYgKG5vZGUubm9kZVR5cGUgPT0gTk9ERV9UWVBFX1RFWFQgJiYgbm9kZS5ub2RlVmFsdWUubWF0Y2goL1xTKy8pIC8qIG5vbi1lbXB0eSAqLyApIHsNCiAgICAgICAgICAkY29tcGlsZU5vZGVzW2luZGV4XSA9IGpxTGl0ZShub2RlKS53cmFwKCc8c3Bhbj48L3NwYW4+JykucGFyZW50KClbMF07DQogICAgICAgIH0NCiAgICAgIH0pOw0KICAgICAgdmFyIGNvbXBvc2l0ZUxpbmtGbiA9DQogICAgICAgICAgICAgIGNvbXBpbGVOb2RlcygkY29tcGlsZU5vZGVzLCB0cmFuc2NsdWRlRm4sICRjb21waWxlTm9kZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhQcmlvcml0eSwgaWdub3JlRGlyZWN0aXZlLCBwcmV2aW91c0NvbXBpbGVDb250ZXh0KTsNCiAgICAgIGNvbXBpbGUuJCRhZGRTY29wZUNsYXNzKCRjb21waWxlTm9kZXMpOw0KICAgICAgdmFyIG5hbWVzcGFjZSA9IG51bGw7DQogICAgICByZXR1cm4gZnVuY3Rpb24gcHVibGljTGlua0ZuKHNjb3BlLCBjbG9uZUNvbm5lY3RGbiwgb3B0aW9ucykgew0KICAgICAgICBhc3NlcnRBcmcoc2NvcGUsICdzY29wZScpOw0KDQogICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9Ow0KICAgICAgICB2YXIgcGFyZW50Qm91bmRUcmFuc2NsdWRlRm4gPSBvcHRpb25zLnBhcmVudEJvdW5kVHJhbnNjbHVkZUZuLA0KICAgICAgICAgIHRyYW5zY2x1ZGVDb250cm9sbGVycyA9IG9wdGlvbnMudHJhbnNjbHVkZUNvbnRyb2xsZXJzLA0KICAgICAgICAgIGZ1dHVyZVBhcmVudEVsZW1lbnQgPSBvcHRpb25zLmZ1dHVyZVBhcmVudEVsZW1lbnQ7DQoNCiAgICAgICAgLy8gV2hlbiBgcGFyZW50Qm91bmRUcmFuc2NsdWRlRm5gIGlzIHBhc3NlZCwgaXQgaXMgYQ0KICAgICAgICAvLyBgY29udHJvbGxlcnNCb3VuZFRyYW5zY2x1ZGVgIGZ1bmN0aW9uIChpdCB3YXMgcHJldmlvdXNseSBwYXNzZWQNCiAgICAgICAgLy8gYXMgYHRyYW5zY2x1ZGVgIHRvIGRpcmVjdGl2ZS5saW5rKSBzbyB3ZSBtdXN0IHVud3JhcCBpdCB0byBnZXQNCiAgICAgICAgLy8gaXRzIGBib3VuZFRyYW5zY2x1ZGVGbmANCiAgICAgICAgaWYgKHBhcmVudEJvdW5kVHJhbnNjbHVkZUZuICYmIHBhcmVudEJvdW5kVHJhbnNjbHVkZUZuLiQkYm91bmRUcmFuc2NsdWRlKSB7DQogICAgICAgICAgcGFyZW50Qm91bmRUcmFuc2NsdWRlRm4gPSBwYXJlbnRCb3VuZFRyYW5zY2x1ZGVGbi4kJGJvdW5kVHJhbnNjbHVkZTsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICghbmFtZXNwYWNlKSB7DQogICAgICAgICAgbmFtZXNwYWNlID0gZGV0ZWN0TmFtZXNwYWNlRm9yQ2hpbGRFbGVtZW50cyhmdXR1cmVQYXJlbnRFbGVtZW50KTsNCiAgICAgICAgfQ0KICAgICAgICB2YXIgJGxpbmtOb2RlOw0KICAgICAgICBpZiAobmFtZXNwYWNlICE9PSAnaHRtbCcpIHsNCiAgICAgICAgICAvLyBXaGVuIHVzaW5nIGEgZGlyZWN0aXZlIHdpdGggcmVwbGFjZTp0cnVlIGFuZCB0ZW1wbGF0ZVVybCB0aGUgJGNvbXBpbGVOb2Rlcw0KICAgICAgICAgIC8vIChvciBhIGNoaWxkIGVsZW1lbnQgaW5zaWRlIG9mIHRoZW0pDQogICAgICAgICAgLy8gbWlnaHQgY2hhbmdlLCBzbyB3ZSBuZWVkIHRvIHJlY3JlYXRlIHRoZSBuYW1lc3BhY2UgYWRhcHRlZCBjb21waWxlTm9kZXMNCiAgICAgICAgICAvLyBmb3IgY2FsbCB0byB0aGUgbGluayBmdW5jdGlvbi4NCiAgICAgICAgICAvLyBOb3RlOiBUaGlzIHdpbGwgYWxyZWFkeSBjbG9uZSB0aGUgbm9kZXMuLi4NCiAgICAgICAgICAkbGlua05vZGUgPSBqcUxpdGUoDQogICAgICAgICAgICB3cmFwVGVtcGxhdGUobmFtZXNwYWNlLCBqcUxpdGUoJzxkaXY+JykuYXBwZW5kKCRjb21waWxlTm9kZXMpLmh0bWwoKSkNCiAgICAgICAgICApOw0KICAgICAgICB9IGVsc2UgaWYgKGNsb25lQ29ubmVjdEZuKSB7DQogICAgICAgICAgLy8gaW1wb3J0YW50ISE6IHdlIG11c3QgY2FsbCBvdXIganFMaXRlLmNsb25lKCkgc2luY2UgdGhlIGpRdWVyeSBvbmUgaXMgdHJ5aW5nIHRvIGJlIHNtYXJ0DQogICAgICAgICAgLy8gYW5kIHNvbWV0aW1lcyBjaGFuZ2VzIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIERPTS4NCiAgICAgICAgICAkbGlua05vZGUgPSBKUUxpdGVQcm90b3R5cGUuY2xvbmUuY2FsbCgkY29tcGlsZU5vZGVzKTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAkbGlua05vZGUgPSAkY29tcGlsZU5vZGVzOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKHRyYW5zY2x1ZGVDb250cm9sbGVycykgew0KICAgICAgICAgIGZvciAodmFyIGNvbnRyb2xsZXJOYW1lIGluIHRyYW5zY2x1ZGVDb250cm9sbGVycykgew0KICAgICAgICAgICAgJGxpbmtOb2RlLmRhdGEoJyQnICsgY29udHJvbGxlck5hbWUgKyAnQ29udHJvbGxlcicsIHRyYW5zY2x1ZGVDb250cm9sbGVyc1tjb250cm9sbGVyTmFtZV0uaW5zdGFuY2UpOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGNvbXBpbGUuJCRhZGRTY29wZUluZm8oJGxpbmtOb2RlLCBzY29wZSk7DQoNCiAgICAgICAgaWYgKGNsb25lQ29ubmVjdEZuKSBjbG9uZUNvbm5lY3RGbigkbGlua05vZGUsIHNjb3BlKTsNCiAgICAgICAgaWYgKGNvbXBvc2l0ZUxpbmtGbikgY29tcG9zaXRlTGlua0ZuKHNjb3BlLCAkbGlua05vZGUsICRsaW5rTm9kZSwgcGFyZW50Qm91bmRUcmFuc2NsdWRlRm4pOw0KICAgICAgICByZXR1cm4gJGxpbmtOb2RlOw0KICAgICAgfTsNCiAgICB9DQoNCiAgICBmdW5jdGlvbiBkZXRlY3ROYW1lc3BhY2VGb3JDaGlsZEVsZW1lbnRzKHBhcmVudEVsZW1lbnQpIHsNCiAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBkZXRlY3QgTWF0aE1MIGFzIHdlbGwuLi4NCiAgICAgIHZhciBub2RlID0gcGFyZW50RWxlbWVudCAmJiBwYXJlbnRFbGVtZW50WzBdOw0KICAgICAgaWYgKCFub2RlKSB7DQogICAgICAgIHJldHVybiAnaHRtbCc7DQogICAgICB9IGVsc2Ugew0KICAgICAgICByZXR1cm4gbm9kZU5hbWVfKG5vZGUpICE9PSAnZm9yZWlnbm9iamVjdCcgJiYgbm9kZS50b1N0cmluZygpLm1hdGNoKC9TVkcvKSA/ICdzdmcnIDogJ2h0bWwnOw0KICAgICAgfQ0KICAgIH0NCg0KICAgIC8qKg0KICAgICAqIENvbXBpbGUgZnVuY3Rpb24gbWF0Y2hlcyBlYWNoIG5vZGUgaW4gbm9kZUxpc3QgYWdhaW5zdCB0aGUgZGlyZWN0aXZlcy4gT25jZSBhbGwgZGlyZWN0aXZlcw0KICAgICAqIGZvciBhIHBhcnRpY3VsYXIgbm9kZSBhcmUgY29sbGVjdGVkIHRoZWlyIGNvbXBpbGUgZnVuY3Rpb25zIGFyZSBleGVjdXRlZC4gVGhlIGNvbXBpbGUNCiAgICAgKiBmdW5jdGlvbnMgcmV0dXJuIHZhbHVlcyAtIHRoZSBsaW5raW5nIGZ1bmN0aW9ucyAtIGFyZSBjb21iaW5lZCBpbnRvIGEgY29tcG9zaXRlIGxpbmtpbmcNCiAgICAgKiBmdW5jdGlvbiwgd2hpY2ggaXMgdGhlIGEgbGlua2luZyBmdW5jdGlvbiBmb3IgdGhlIG5vZGUuDQogICAgICoNCiAgICAgKiBAcGFyYW0ge05vZGVMaXN0fSBub2RlTGlzdCBhbiBhcnJheSBvZiBub2RlcyBvciBOb2RlTGlzdCB0byBjb21waWxlDQogICAgICogQHBhcmFtIHtmdW5jdGlvbihhbmd1bGFyLlNjb3BlLCBjbG9uZUF0dGFjaEZuPSl9IHRyYW5zY2x1ZGVGbiBBIGxpbmtpbmcgZnVuY3Rpb24sIHdoZXJlIHRoZQ0KICAgICAqICAgICAgICBzY29wZSBhcmd1bWVudCBpcyBhdXRvLWdlbmVyYXRlZCB0byB0aGUgbmV3IGNoaWxkIG9mIHRoZSB0cmFuc2NsdWRlZCBwYXJlbnQgc2NvcGUuDQogICAgICogQHBhcmFtIHtET01FbGVtZW50PX0gJHJvb3RFbGVtZW50IElmIHRoZSBub2RlTGlzdCBpcyB0aGUgcm9vdCBvZiB0aGUgY29tcGlsYXRpb24gdHJlZSB0aGVuDQogICAgICogICAgICAgIHRoZSByb290RWxlbWVudCBtdXN0IGJlIHNldCB0aGUganFMaXRlIGNvbGxlY3Rpb24gb2YgdGhlIGNvbXBpbGUgcm9vdC4gVGhpcyBpcw0KICAgICAqICAgICAgICBuZWVkZWQgc28gdGhhdCB0aGUganFMaXRlIGNvbGxlY3Rpb24gaXRlbXMgY2FuIGJlIHJlcGxhY2VkIHdpdGggd2lkZ2V0cy4NCiAgICAgKiBAcGFyYW0ge251bWJlcj19IG1heFByaW9yaXR5IE1heCBkaXJlY3RpdmUgcHJpb3JpdHkuDQogICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBBIGNvbXBvc2l0ZSBsaW5raW5nIGZ1bmN0aW9uIG9mIGFsbCBvZiB0aGUgbWF0Y2hlZCBkaXJlY3RpdmVzIG9yIG51bGwuDQogICAgICovDQogICAgZnVuY3Rpb24gY29tcGlsZU5vZGVzKG5vZGVMaXN0LCB0cmFuc2NsdWRlRm4sICRyb290RWxlbWVudCwgbWF4UHJpb3JpdHksIGlnbm9yZURpcmVjdGl2ZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c0NvbXBpbGVDb250ZXh0KSB7DQogICAgICB2YXIgbGlua0ZucyA9IFtdLA0KICAgICAgICAgIGF0dHJzLCBkaXJlY3RpdmVzLCBub2RlTGlua0ZuLCBjaGlsZE5vZGVzLCBjaGlsZExpbmtGbiwgbGlua0ZuRm91bmQsIG5vZGVMaW5rRm5Gb3VuZDsNCg0KICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2RlTGlzdC5sZW5ndGg7IGkrKykgew0KICAgICAgICBhdHRycyA9IG5ldyBBdHRyaWJ1dGVzKCk7DQoNCiAgICAgICAgLy8gd2UgbXVzdCBhbHdheXMgcmVmZXIgdG8gbm9kZUxpc3RbaV0gc2luY2UgdGhlIG5vZGVzIGNhbiBiZSByZXBsYWNlZCB1bmRlcm5lYXRoIHVzLg0KICAgICAgICBkaXJlY3RpdmVzID0gY29sbGVjdERpcmVjdGl2ZXMobm9kZUxpc3RbaV0sIFtdLCBhdHRycywgaSA9PT0gMCA/IG1heFByaW9yaXR5IDogdW5kZWZpbmVkLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZURpcmVjdGl2ZSk7DQoNCiAgICAgICAgbm9kZUxpbmtGbiA9IChkaXJlY3RpdmVzLmxlbmd0aCkNCiAgICAgICAgICAgID8gYXBwbHlEaXJlY3RpdmVzVG9Ob2RlKGRpcmVjdGl2ZXMsIG5vZGVMaXN0W2ldLCBhdHRycywgdHJhbnNjbHVkZUZuLCAkcm9vdEVsZW1lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bGwsIFtdLCBbXSwgcHJldmlvdXNDb21waWxlQ29udGV4dCkNCiAgICAgICAgICAgIDogbnVsbDsNCg0KICAgICAgICBpZiAobm9kZUxpbmtGbiAmJiBub2RlTGlua0ZuLnNjb3BlKSB7DQogICAgICAgICAgY29tcGlsZS4kJGFkZFNjb3BlQ2xhc3MoYXR0cnMuJCRlbGVtZW50KTsNCiAgICAgICAgfQ0KDQogICAgICAgIGNoaWxkTGlua0ZuID0gKG5vZGVMaW5rRm4gJiYgbm9kZUxpbmtGbi50ZXJtaW5hbCB8fA0KICAgICAgICAgICAgICAgICAgICAgICEoY2hpbGROb2RlcyA9IG5vZGVMaXN0W2ldLmNoaWxkTm9kZXMpIHx8DQogICAgICAgICAgICAgICAgICAgICAgIWNoaWxkTm9kZXMubGVuZ3RoKQ0KICAgICAgICAgICAgPyBudWxsDQogICAgICAgICAgICA6IGNvbXBpbGVOb2RlcyhjaGlsZE5vZGVzLA0KICAgICAgICAgICAgICAgICBub2RlTGlua0ZuID8gKA0KICAgICAgICAgICAgICAgICAgKG5vZGVMaW5rRm4udHJhbnNjbHVkZU9uVGhpc0VsZW1lbnQgfHwgIW5vZGVMaW5rRm4udGVtcGxhdGVPblRoaXNFbGVtZW50KQ0KICAgICAgICAgICAgICAgICAgICAgJiYgbm9kZUxpbmtGbi50cmFuc2NsdWRlKSA6IHRyYW5zY2x1ZGVGbik7DQoNCiAgICAgICAgaWYgKG5vZGVMaW5rRm4gfHwgY2hpbGRMaW5rRm4pIHsNCiAgICAgICAgICBsaW5rRm5zLnB1c2goaSwgbm9kZUxpbmtGbiwgY2hpbGRMaW5rRm4pOw0KICAgICAgICAgIGxpbmtGbkZvdW5kID0gdHJ1ZTsNCiAgICAgICAgICBub2RlTGlua0ZuRm91bmQgPSBub2RlTGlua0ZuRm91bmQgfHwgbm9kZUxpbmtGbjsNCiAgICAgICAgfQ0KDQogICAgICAgIC8vdXNlIHRoZSBwcmV2aW91cyBjb250ZXh0IG9ubHkgZm9yIHRoZSBmaXJzdCBlbGVtZW50IGluIHRoZSB2aXJ0dWFsIGdyb3VwDQogICAgICAgIHByZXZpb3VzQ29tcGlsZUNvbnRleHQgPSBudWxsOw0KICAgICAgfQ0KDQogICAgICAvLyByZXR1cm4gYSBsaW5raW5nIGZ1bmN0aW9uIGlmIHdlIGhhdmUgZm91bmQgYW55dGhpbmcsIG51bGwgb3RoZXJ3aXNlDQogICAgICByZXR1cm4gbGlua0ZuRm91bmQgPyBjb21wb3NpdGVMaW5rRm4gOiBudWxsOw0KDQogICAgICBmdW5jdGlvbiBjb21wb3NpdGVMaW5rRm4oc2NvcGUsIG5vZGVMaXN0LCAkcm9vdEVsZW1lbnQsIHBhcmVudEJvdW5kVHJhbnNjbHVkZUZuKSB7DQogICAgICAgIHZhciBub2RlTGlua0ZuLCBjaGlsZExpbmtGbiwgbm9kZSwgY2hpbGRTY29wZSwgaSwgaWksIGlkeCwgY2hpbGRCb3VuZFRyYW5zY2x1ZGVGbjsNCiAgICAgICAgdmFyIHN0YWJsZU5vZGVMaXN0Ow0KDQoNCiAgICAgICAgaWYgKG5vZGVMaW5rRm5Gb3VuZCkgew0KICAgICAgICAgIC8vIGNvcHkgbm9kZUxpc3Qgc28gdGhhdCBpZiBhIG5vZGVMaW5rRm4gcmVtb3ZlcyBvciBhZGRzIGFuIGVsZW1lbnQgYXQgdGhpcyBET00gbGV2ZWwgb3VyDQogICAgICAgICAgLy8gb2Zmc2V0cyBkb24ndCBnZXQgc2NyZXdlZCB1cA0KICAgICAgICAgIHZhciBub2RlTGlzdExlbmd0aCA9IG5vZGVMaXN0Lmxlbmd0aDsNCiAgICAgICAgICBzdGFibGVOb2RlTGlzdCA9IG5ldyBBcnJheShub2RlTGlzdExlbmd0aCk7DQoNCiAgICAgICAgICAvLyBjcmVhdGUgYSBzcGFyc2UgYXJyYXkgYnkgb25seSBjb3B5aW5nIHRoZSBlbGVtZW50cyB3aGljaCBoYXZlIGEgbGlua0ZuDQogICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpbmtGbnMubGVuZ3RoOyBpKz0zKSB7DQogICAgICAgICAgICBpZHggPSBsaW5rRm5zW2ldOw0KICAgICAgICAgICAgc3RhYmxlTm9kZUxpc3RbaWR4XSA9IG5vZGVMaXN0W2lkeF07DQogICAgICAgICAgfQ0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIHN0YWJsZU5vZGVMaXN0ID0gbm9kZUxpc3Q7DQogICAgICAgIH0NCg0KICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IGxpbmtGbnMubGVuZ3RoOyBpIDwgaWk7KSB7DQogICAgICAgICAgbm9kZSA9IHN0YWJsZU5vZGVMaXN0W2xpbmtGbnNbaSsrXV07DQogICAgICAgICAgbm9kZUxpbmtGbiA9IGxpbmtGbnNbaSsrXTsNCiAgICAgICAgICBjaGlsZExpbmtGbiA9IGxpbmtGbnNbaSsrXTsNCg0KICAgICAgICAgIGlmIChub2RlTGlua0ZuKSB7DQogICAgICAgICAgICBpZiAobm9kZUxpbmtGbi5zY29wZSkgew0KICAgICAgICAgICAgICBjaGlsZFNjb3BlID0gc2NvcGUuJG5ldygpOw0KICAgICAgICAgICAgICBjb21waWxlLiQkYWRkU2NvcGVJbmZvKGpxTGl0ZShub2RlKSwgY2hpbGRTY29wZSk7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICBjaGlsZFNjb3BlID0gc2NvcGU7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmIChub2RlTGlua0ZuLnRyYW5zY2x1ZGVPblRoaXNFbGVtZW50KSB7DQogICAgICAgICAgICAgIGNoaWxkQm91bmRUcmFuc2NsdWRlRm4gPSBjcmVhdGVCb3VuZFRyYW5zY2x1ZGVGbigNCiAgICAgICAgICAgICAgICAgIHNjb3BlLCBub2RlTGlua0ZuLnRyYW5zY2x1ZGUsIHBhcmVudEJvdW5kVHJhbnNjbHVkZUZuLA0KICAgICAgICAgICAgICAgICAgbm9kZUxpbmtGbi5lbGVtZW50VHJhbnNjbHVkZU9uVGhpc0VsZW1lbnQpOw0KDQogICAgICAgICAgICB9IGVsc2UgaWYgKCFub2RlTGlua0ZuLnRlbXBsYXRlT25UaGlzRWxlbWVudCAmJiBwYXJlbnRCb3VuZFRyYW5zY2x1ZGVGbikgew0KICAgICAgICAgICAgICBjaGlsZEJvdW5kVHJhbnNjbHVkZUZuID0gcGFyZW50Qm91bmRUcmFuc2NsdWRlRm47DQoNCiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXBhcmVudEJvdW5kVHJhbnNjbHVkZUZuICYmIHRyYW5zY2x1ZGVGbikgew0KICAgICAgICAgICAgICBjaGlsZEJvdW5kVHJhbnNjbHVkZUZuID0gY3JlYXRlQm91bmRUcmFuc2NsdWRlRm4oc2NvcGUsIHRyYW5zY2x1ZGVGbik7DQoNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgIGNoaWxkQm91bmRUcmFuc2NsdWRlRm4gPSBudWxsOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBub2RlTGlua0ZuKGNoaWxkTGlua0ZuLCBjaGlsZFNjb3BlLCBub2RlLCAkcm9vdEVsZW1lbnQsIGNoaWxkQm91bmRUcmFuc2NsdWRlRm4pOw0KDQogICAgICAgICAgfSBlbHNlIGlmIChjaGlsZExpbmtGbikgew0KICAgICAgICAgICAgY2hpbGRMaW5rRm4oc2NvcGUsIG5vZGUuY2hpbGROb2RlcywgdW5kZWZpbmVkLCBwYXJlbnRCb3VuZFRyYW5zY2x1ZGVGbik7DQogICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICB9DQogICAgfQ0KDQogICAgZnVuY3Rpb24gY3JlYXRlQm91bmRUcmFuc2NsdWRlRm4oc2NvcGUsIHRyYW5zY2x1ZGVGbiwgcHJldmlvdXNCb3VuZFRyYW5zY2x1ZGVGbiwgZWxlbWVudFRyYW5zY2x1c2lvbikgew0KDQogICAgICB2YXIgYm91bmRUcmFuc2NsdWRlRm4gPSBmdW5jdGlvbih0cmFuc2NsdWRlZFNjb3BlLCBjbG9uZUZuLCBjb250cm9sbGVycywgZnV0dXJlUGFyZW50RWxlbWVudCwgY29udGFpbmluZ1Njb3BlKSB7DQoNCiAgICAgICAgaWYgKCF0cmFuc2NsdWRlZFNjb3BlKSB7DQogICAgICAgICAgdHJhbnNjbHVkZWRTY29wZSA9IHNjb3BlLiRuZXcoZmFsc2UsIGNvbnRhaW5pbmdTY29wZSk7DQogICAgICAgICAgdHJhbnNjbHVkZWRTY29wZS4kJHRyYW5zY2x1ZGVkID0gdHJ1ZTsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiB0cmFuc2NsdWRlRm4odHJhbnNjbHVkZWRTY29wZSwgY2xvbmVGbiwgew0KICAgICAgICAgIHBhcmVudEJvdW5kVHJhbnNjbHVkZUZuOiBwcmV2aW91c0JvdW5kVHJhbnNjbHVkZUZuLA0KICAgICAgICAgIHRyYW5zY2x1ZGVDb250cm9sbGVyczogY29udHJvbGxlcnMsDQogICAgICAgICAgZnV0dXJlUGFyZW50RWxlbWVudDogZnV0dXJlUGFyZW50RWxlbWVudA0KICAgICAgICB9KTsNCiAgICAgIH07DQoNCiAgICAgIHJldHVybiBib3VuZFRyYW5zY2x1ZGVGbjsNCiAgICB9DQoNCiAgICAvKioNCiAgICAgKiBMb29rcyBmb3IgZGlyZWN0aXZlcyBvbiB0aGUgZ2l2ZW4gbm9kZSBhbmQgYWRkcyB0aGVtIHRvIHRoZSBkaXJlY3RpdmUgY29sbGVjdGlvbiB3aGljaCBpcw0KICAgICAqIHNvcnRlZC4NCiAgICAgKg0KICAgICAqIEBwYXJhbSBub2RlIE5vZGUgdG8gc2VhcmNoLg0KICAgICAqIEBwYXJhbSBkaXJlY3RpdmVzIEFuIGFycmF5IHRvIHdoaWNoIHRoZSBkaXJlY3RpdmVzIGFyZSBhZGRlZCB0by4gVGhpcyBhcnJheSBpcyBzb3J0ZWQgYmVmb3JlDQogICAgICogICAgICAgIHRoZSBmdW5jdGlvbiByZXR1cm5zLg0KICAgICAqIEBwYXJhbSBhdHRycyBUaGUgc2hhcmVkIGF0dHJzIG9iamVjdCB3aGljaCBpcyB1c2VkIHRvIHBvcHVsYXRlIHRoZSBub3JtYWxpemVkIGF0dHJpYnV0ZXMuDQogICAgICogQHBhcmFtIHtudW1iZXI9fSBtYXhQcmlvcml0eSBNYXggZGlyZWN0aXZlIHByaW9yaXR5Lg0KICAgICAqLw0KICAgIGZ1bmN0aW9uIGNvbGxlY3REaXJlY3RpdmVzKG5vZGUsIGRpcmVjdGl2ZXMsIGF0dHJzLCBtYXhQcmlvcml0eSwgaWdub3JlRGlyZWN0aXZlKSB7DQogICAgICB2YXIgbm9kZVR5cGUgPSBub2RlLm5vZGVUeXBlLA0KICAgICAgICAgIGF0dHJzTWFwID0gYXR0cnMuJGF0dHIsDQogICAgICAgICAgbWF0Y2gsDQogICAgICAgICAgY2xhc3NOYW1lOw0KDQogICAgICBzd2l0Y2ggKG5vZGVUeXBlKSB7DQogICAgICAgIGNhc2UgTk9ERV9UWVBFX0VMRU1FTlQ6IC8qIEVsZW1lbnQgKi8NCiAgICAgICAgICAvLyB1c2UgdGhlIG5vZGUgbmFtZTogPGRpcmVjdGl2ZT4NCiAgICAgICAgICBhZGREaXJlY3RpdmUoZGlyZWN0aXZlcywNCiAgICAgICAgICAgICAgZGlyZWN0aXZlTm9ybWFsaXplKG5vZGVOYW1lXyhub2RlKSksICdFJywgbWF4UHJpb3JpdHksIGlnbm9yZURpcmVjdGl2ZSk7DQoNCiAgICAgICAgICAvLyBpdGVyYXRlIG92ZXIgdGhlIGF0dHJpYnV0ZXMNCiAgICAgICAgICBmb3IgKHZhciBhdHRyLCBuYW1lLCBuTmFtZSwgbmdBdHRyTmFtZSwgdmFsdWUsIGlzTmdBdHRyLCBuQXR0cnMgPSBub2RlLmF0dHJpYnV0ZXMsDQogICAgICAgICAgICAgICAgICAgaiA9IDAsIGpqID0gbkF0dHJzICYmIG5BdHRycy5sZW5ndGg7IGogPCBqajsgaisrKSB7DQogICAgICAgICAgICB2YXIgYXR0clN0YXJ0TmFtZSA9IGZhbHNlOw0KICAgICAgICAgICAgdmFyIGF0dHJFbmROYW1lID0gZmFsc2U7DQoNCiAgICAgICAgICAgIGF0dHIgPSBuQXR0cnNbal07DQogICAgICAgICAgICBuYW1lID0gYXR0ci5uYW1lOw0KICAgICAgICAgICAgdmFsdWUgPSB0cmltKGF0dHIudmFsdWUpOw0KDQogICAgICAgICAgICAvLyBzdXBwb3J0IG5nQXR0ciBhdHRyaWJ1dGUgYmluZGluZw0KICAgICAgICAgICAgbmdBdHRyTmFtZSA9IGRpcmVjdGl2ZU5vcm1hbGl6ZShuYW1lKTsNCiAgICAgICAgICAgIGlmIChpc05nQXR0ciA9IE5HX0FUVFJfQklORElORy50ZXN0KG5nQXR0ck5hbWUpKSB7DQogICAgICAgICAgICAgIG5hbWUgPSBuYW1lLnJlcGxhY2UoUFJFRklYX1JFR0VYUCwgJycpDQogICAgICAgICAgICAgICAgLnN1YnN0cig4KS5yZXBsYWNlKC9fKC4pL2csIGZ1bmN0aW9uKG1hdGNoLCBsZXR0ZXIpIHsNCiAgICAgICAgICAgICAgICAgIHJldHVybiBsZXR0ZXIudG9VcHBlckNhc2UoKTsNCiAgICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgdmFyIGRpcmVjdGl2ZU5OYW1lID0gbmdBdHRyTmFtZS5yZXBsYWNlKC8oU3RhcnR8RW5kKSQvLCAnJyk7DQogICAgICAgICAgICBpZiAoZGlyZWN0aXZlSXNNdWx0aUVsZW1lbnQoZGlyZWN0aXZlTk5hbWUpKSB7DQogICAgICAgICAgICAgIGlmIChuZ0F0dHJOYW1lID09PSBkaXJlY3RpdmVOTmFtZSArICdTdGFydCcpIHsNCiAgICAgICAgICAgICAgICBhdHRyU3RhcnROYW1lID0gbmFtZTsNCiAgICAgICAgICAgICAgICBhdHRyRW5kTmFtZSA9IG5hbWUuc3Vic3RyKDAsIG5hbWUubGVuZ3RoIC0gNSkgKyAnZW5kJzsNCiAgICAgICAgICAgICAgICBuYW1lID0gbmFtZS5zdWJzdHIoMCwgbmFtZS5sZW5ndGggLSA2KTsNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBuTmFtZSA9IGRpcmVjdGl2ZU5vcm1hbGl6ZShuYW1lLnRvTG93ZXJDYXNlKCkpOw0KICAgICAgICAgICAgYXR0cnNNYXBbbk5hbWVdID0gbmFtZTsNCiAgICAgICAgICAgIGlmIChpc05nQXR0ciB8fCAhYXR0cnMuaGFzT3duUHJvcGVydHkobk5hbWUpKSB7DQogICAgICAgICAgICAgICAgYXR0cnNbbk5hbWVdID0gdmFsdWU7DQogICAgICAgICAgICAgICAgaWYgKGdldEJvb2xlYW5BdHRyTmFtZShub2RlLCBuTmFtZSkpIHsNCiAgICAgICAgICAgICAgICAgIGF0dHJzW25OYW1lXSA9IHRydWU7IC8vIHByZXNlbmNlIG1lYW5zIHRydWUNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgICBhZGRBdHRySW50ZXJwb2xhdGVEaXJlY3RpdmUobm9kZSwgZGlyZWN0aXZlcywgdmFsdWUsIG5OYW1lLCBpc05nQXR0cik7DQogICAgICAgICAgICBhZGREaXJlY3RpdmUoZGlyZWN0aXZlcywgbk5hbWUsICdBJywgbWF4UHJpb3JpdHksIGlnbm9yZURpcmVjdGl2ZSwgYXR0clN0YXJ0TmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0ckVuZE5hbWUpOw0KICAgICAgICAgIH0NCg0KICAgICAgICAgIC8vIHVzZSBjbGFzcyBhcyBkaXJlY3RpdmUNCiAgICAgICAgICBjbGFzc05hbWUgPSBub2RlLmNsYXNzTmFtZTsNCiAgICAgICAgICBpZiAoaXNTdHJpbmcoY2xhc3NOYW1lKSAmJiBjbGFzc05hbWUgIT09ICcnKSB7DQogICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBDTEFTU19ESVJFQ1RJVkVfUkVHRVhQLmV4ZWMoY2xhc3NOYW1lKSkgew0KICAgICAgICAgICAgICBuTmFtZSA9IGRpcmVjdGl2ZU5vcm1hbGl6ZShtYXRjaFsyXSk7DQogICAgICAgICAgICAgIGlmIChhZGREaXJlY3RpdmUoZGlyZWN0aXZlcywgbk5hbWUsICdDJywgbWF4UHJpb3JpdHksIGlnbm9yZURpcmVjdGl2ZSkpIHsNCiAgICAgICAgICAgICAgICBhdHRyc1tuTmFtZV0gPSB0cmltKG1hdGNoWzNdKTsNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICBjbGFzc05hbWUgPSBjbGFzc05hbWUuc3Vic3RyKG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9DQogICAgICAgICAgYnJlYWs7DQogICAgICAgIGNhc2UgTk9ERV9UWVBFX1RFWFQ6IC8qIFRleHQgTm9kZSAqLw0KICAgICAgICAgIGFkZFRleHRJbnRlcnBvbGF0ZURpcmVjdGl2ZShkaXJlY3RpdmVzLCBub2RlLm5vZGVWYWx1ZSk7DQogICAgICAgICAgYnJlYWs7DQogICAgICAgIGNhc2UgTk9ERV9UWVBFX0NPTU1FTlQ6IC8qIENvbW1lbnQgKi8NCiAgICAgICAgICB0cnkgew0KICAgICAgICAgICAgbWF0Y2ggPSBDT01NRU5UX0RJUkVDVElWRV9SRUdFWFAuZXhlYyhub2RlLm5vZGVWYWx1ZSk7DQogICAgICAgICAgICBpZiAobWF0Y2gpIHsNCiAgICAgICAgICAgICAgbk5hbWUgPSBkaXJlY3RpdmVOb3JtYWxpemUobWF0Y2hbMV0pOw0KICAgICAgICAgICAgICBpZiAoYWRkRGlyZWN0aXZlKGRpcmVjdGl2ZXMsIG5OYW1lLCAnTScsIG1heFByaW9yaXR5LCBpZ25vcmVEaXJlY3RpdmUpKSB7DQogICAgICAgICAgICAgICAgYXR0cnNbbk5hbWVdID0gdHJpbShtYXRjaFsyXSk7DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9IGNhdGNoIChlKSB7DQogICAgICAgICAgICAvLyB0dXJucyBvdXQgdGhhdCB1bmRlciBzb21lIGNpcmN1bXN0YW5jZXMgSUU5IHRocm93cyBlcnJvcnMgd2hlbiBvbmUgYXR0ZW1wdHMgdG8gcmVhZA0KICAgICAgICAgICAgLy8gY29tbWVudCdzIG5vZGUgdmFsdWUuDQogICAgICAgICAgICAvLyBKdXN0IGlnbm9yZSBpdCBhbmQgY29udGludWUuIChDYW4ndCBzZWVtIHRvIHJlcHJvZHVjZSBpbiB0ZXN0IGNhc2UuKQ0KICAgICAgICAgIH0NCiAgICAgICAgICBicmVhazsNCiAgICAgIH0NCg0KICAgICAgZGlyZWN0aXZlcy5zb3J0KGJ5UHJpb3JpdHkpOw0KICAgICAgcmV0dXJuIGRpcmVjdGl2ZXM7DQogICAgfQ0KDQogICAgLyoqDQogICAgICogR2l2ZW4gYSBub2RlIHdpdGggYW4gZGlyZWN0aXZlLXN0YXJ0IGl0IGNvbGxlY3RzIGFsbCBvZiB0aGUgc2libGluZ3MgdW50aWwgaXQgZmluZHMNCiAgICAgKiBkaXJlY3RpdmUtZW5kLg0KICAgICAqIEBwYXJhbSBub2RlDQogICAgICogQHBhcmFtIGF0dHJTdGFydA0KICAgICAqIEBwYXJhbSBhdHRyRW5kDQogICAgICogQHJldHVybnMgeyp9DQogICAgICovDQogICAgZnVuY3Rpb24gZ3JvdXBTY2FuKG5vZGUsIGF0dHJTdGFydCwgYXR0ckVuZCkgew0KICAgICAgdmFyIG5vZGVzID0gW107DQogICAgICB2YXIgZGVwdGggPSAwOw0KICAgICAgaWYgKGF0dHJTdGFydCAmJiBub2RlLmhhc0F0dHJpYnV0ZSAmJiBub2RlLmhhc0F0dHJpYnV0ZShhdHRyU3RhcnQpKSB7DQogICAgICAgIGRvIHsNCiAgICAgICAgICBpZiAoIW5vZGUpIHsNCiAgICAgICAgICAgIHRocm93ICRjb21waWxlTWluRXJyKCd1dGVyZGlyJywNCiAgICAgICAgICAgICAgICAgICAgICAiVW50ZXJtaW5hdGVkIGF0dHJpYnV0ZSwgZm91bmQgJ3swfScgYnV0IG5vIG1hdGNoaW5nICd7MX0nIGZvdW5kLiIsDQogICAgICAgICAgICAgICAgICAgICAgYXR0clN0YXJ0LCBhdHRyRW5kKTsNCiAgICAgICAgICB9DQogICAgICAgICAgaWYgKG5vZGUubm9kZVR5cGUgPT0gTk9ERV9UWVBFX0VMRU1FTlQpIHsNCiAgICAgICAgICAgIGlmIChub2RlLmhhc0F0dHJpYnV0ZShhdHRyU3RhcnQpKSBkZXB0aCsrOw0KICAgICAgICAgICAgaWYgKG5vZGUuaGFzQXR0cmlidXRlKGF0dHJFbmQpKSBkZXB0aC0tOw0KICAgICAgICAgIH0NCiAgICAgICAgICBub2Rlcy5wdXNoKG5vZGUpOw0KICAgICAgICAgIG5vZGUgPSBub2RlLm5leHRTaWJsaW5nOw0KICAgICAgICB9IHdoaWxlIChkZXB0aCA+IDApOw0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgbm9kZXMucHVzaChub2RlKTsNCiAgICAgIH0NCg0KICAgICAgcmV0dXJuIGpxTGl0ZShub2Rlcyk7DQogICAgfQ0KDQogICAgLyoqDQogICAgICogV3JhcHBlciBmb3IgbGlua2luZyBmdW5jdGlvbiB3aGljaCBjb252ZXJ0cyBub3JtYWwgbGlua2luZyBmdW5jdGlvbiBpbnRvIGEgZ3JvdXBlZA0KICAgICAqIGxpbmtpbmcgZnVuY3Rpb24uDQogICAgICogQHBhcmFtIGxpbmtGbg0KICAgICAqIEBwYXJhbSBhdHRyU3RhcnQNCiAgICAgKiBAcGFyYW0gYXR0ckVuZA0KICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0NCiAgICAgKi8NCiAgICBmdW5jdGlvbiBncm91cEVsZW1lbnRzTGlua0ZuV3JhcHBlcihsaW5rRm4sIGF0dHJTdGFydCwgYXR0ckVuZCkgew0KICAgICAgcmV0dXJuIGZ1bmN0aW9uKHNjb3BlLCBlbGVtZW50LCBhdHRycywgY29udHJvbGxlcnMsIHRyYW5zY2x1ZGVGbikgew0KICAgICAgICBlbGVtZW50ID0gZ3JvdXBTY2FuKGVsZW1lbnRbMF0sIGF0dHJTdGFydCwgYXR0ckVuZCk7DQogICAgICAgIHJldHVybiBsaW5rRm4oc2NvcGUsIGVsZW1lbnQsIGF0dHJzLCBjb250cm9sbGVycywgdHJhbnNjbHVkZUZuKTsNCiAgICAgIH07DQogICAgfQ0KDQogICAgLyoqDQogICAgICogT25jZSB0aGUgZGlyZWN0aXZlcyBoYXZlIGJlZW4gY29sbGVjdGVkLCB0aGVpciBjb21waWxlIGZ1bmN0aW9ucyBhcmUgZXhlY3V0ZWQuIFRoaXMgbWV0aG9kDQogICAgICogaXMgcmVzcG9uc2libGUgZm9yIGlubGluaW5nIGRpcmVjdGl2ZSB0ZW1wbGF0ZXMgYXMgd2VsbCBhcyB0ZXJtaW5hdGluZyB0aGUgYXBwbGljYXRpb24NCiAgICAgKiBvZiB0aGUgZGlyZWN0aXZlcyBpZiB0aGUgdGVybWluYWwgZGlyZWN0aXZlIGhhcyBiZWVuIHJlYWNoZWQuDQogICAgICoNCiAgICAgKiBAcGFyYW0ge0FycmF5fSBkaXJlY3RpdmVzIEFycmF5IG9mIGNvbGxlY3RlZCBkaXJlY3RpdmVzIHRvIGV4ZWN1dGUgdGhlaXIgY29tcGlsZSBmdW5jdGlvbi4NCiAgICAgKiAgICAgICAgdGhpcyBuZWVkcyB0byBiZSBwcmUtc29ydGVkIGJ5IHByaW9yaXR5IG9yZGVyLg0KICAgICAqIEBwYXJhbSB7Tm9kZX0gY29tcGlsZU5vZGUgVGhlIHJhdyBET00gbm9kZSB0byBhcHBseSB0aGUgY29tcGlsZSBmdW5jdGlvbnMgdG8NCiAgICAgKiBAcGFyYW0ge09iamVjdH0gdGVtcGxhdGVBdHRycyBUaGUgc2hhcmVkIGF0dHJpYnV0ZSBmdW5jdGlvbg0KICAgICAqIEBwYXJhbSB7ZnVuY3Rpb24oYW5ndWxhci5TY29wZSwgY2xvbmVBdHRhY2hGbj0pfSB0cmFuc2NsdWRlRm4gQSBsaW5raW5nIGZ1bmN0aW9uLCB3aGVyZSB0aGUNCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGUgYXJndW1lbnQgaXMgYXV0by1nZW5lcmF0ZWQgdG8gdGhlIG5ldw0KICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZCBvZiB0aGUgdHJhbnNjbHVkZWQgcGFyZW50IHNjb3BlLg0KICAgICAqIEBwYXJhbSB7SlFMaXRlfSBqcUNvbGxlY3Rpb24gSWYgd2UgYXJlIHdvcmtpbmcgb24gdGhlIHJvb3Qgb2YgdGhlIGNvbXBpbGUgdHJlZSB0aGVuIHRoaXMNCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3VtZW50IGhhcyB0aGUgcm9vdCBqcUxpdGUgYXJyYXkgc28gdGhhdCB3ZSBjYW4gcmVwbGFjZSBub2Rlcw0KICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb24gaXQuDQogICAgICogQHBhcmFtIHtPYmplY3Q9fSBvcmlnaW5hbFJlcGxhY2VEaXJlY3RpdmUgQW4gb3B0aW9uYWwgZGlyZWN0aXZlIHRoYXQgd2lsbCBiZSBpZ25vcmVkIHdoZW4NCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21waWxpbmcgdGhlIHRyYW5zY2x1c2lvbi4NCiAgICAgKiBAcGFyYW0ge0FycmF5LjxGdW5jdGlvbj59IHByZUxpbmtGbnMNCiAgICAgKiBAcGFyYW0ge0FycmF5LjxGdW5jdGlvbj59IHBvc3RMaW5rRm5zDQogICAgICogQHBhcmFtIHtPYmplY3R9IHByZXZpb3VzQ29tcGlsZUNvbnRleHQgQ29udGV4dCB1c2VkIGZvciBwcmV2aW91cyBjb21waWxhdGlvbiBvZiB0aGUgY3VycmVudA0KICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUNCiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IGxpbmtGbg0KICAgICAqLw0KICAgIGZ1bmN0aW9uIGFwcGx5RGlyZWN0aXZlc1RvTm9kZShkaXJlY3RpdmVzLCBjb21waWxlTm9kZSwgdGVtcGxhdGVBdHRycywgdHJhbnNjbHVkZUZuLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqcUNvbGxlY3Rpb24sIG9yaWdpbmFsUmVwbGFjZURpcmVjdGl2ZSwgcHJlTGlua0ZucywgcG9zdExpbmtGbnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzQ29tcGlsZUNvbnRleHQpIHsNCiAgICAgIHByZXZpb3VzQ29tcGlsZUNvbnRleHQgPSBwcmV2aW91c0NvbXBpbGVDb250ZXh0IHx8IHt9Ow0KDQogICAgICB2YXIgdGVybWluYWxQcmlvcml0eSA9IC1OdW1iZXIuTUFYX1ZBTFVFLA0KICAgICAgICAgIG5ld1Njb3BlRGlyZWN0aXZlLA0KICAgICAgICAgIGNvbnRyb2xsZXJEaXJlY3RpdmVzID0gcHJldmlvdXNDb21waWxlQ29udGV4dC5jb250cm9sbGVyRGlyZWN0aXZlcywNCiAgICAgICAgICBjb250cm9sbGVycywNCiAgICAgICAgICBuZXdJc29sYXRlU2NvcGVEaXJlY3RpdmUgPSBwcmV2aW91c0NvbXBpbGVDb250ZXh0Lm5ld0lzb2xhdGVTY29wZURpcmVjdGl2ZSwNCiAgICAgICAgICB0ZW1wbGF0ZURpcmVjdGl2ZSA9IHByZXZpb3VzQ29tcGlsZUNvbnRleHQudGVtcGxhdGVEaXJlY3RpdmUsDQogICAgICAgICAgbm9uVGxiVHJhbnNjbHVkZURpcmVjdGl2ZSA9IHByZXZpb3VzQ29tcGlsZUNvbnRleHQubm9uVGxiVHJhbnNjbHVkZURpcmVjdGl2ZSwNCiAgICAgICAgICBoYXNUcmFuc2NsdWRlRGlyZWN0aXZlID0gZmFsc2UsDQogICAgICAgICAgaGFzVGVtcGxhdGUgPSBmYWxzZSwNCiAgICAgICAgICBoYXNFbGVtZW50VHJhbnNjbHVkZURpcmVjdGl2ZSA9IHByZXZpb3VzQ29tcGlsZUNvbnRleHQuaGFzRWxlbWVudFRyYW5zY2x1ZGVEaXJlY3RpdmUsDQogICAgICAgICAgJGNvbXBpbGVOb2RlID0gdGVtcGxhdGVBdHRycy4kJGVsZW1lbnQgPSBqcUxpdGUoY29tcGlsZU5vZGUpLA0KICAgICAgICAgIGRpcmVjdGl2ZSwNCiAgICAgICAgICBkaXJlY3RpdmVOYW1lLA0KICAgICAgICAgICR0ZW1wbGF0ZSwNCiAgICAgICAgICByZXBsYWNlRGlyZWN0aXZlID0gb3JpZ2luYWxSZXBsYWNlRGlyZWN0aXZlLA0KICAgICAgICAgIGNoaWxkVHJhbnNjbHVkZUZuID0gdHJhbnNjbHVkZUZuLA0KICAgICAgICAgIGxpbmtGbiwNCiAgICAgICAgICBkaXJlY3RpdmVWYWx1ZTsNCg0KICAgICAgLy8gZXhlY3V0ZXMgYWxsIGRpcmVjdGl2ZXMgb24gdGhlIGN1cnJlbnQgZWxlbWVudA0KICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZGlyZWN0aXZlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7DQogICAgICAgIGRpcmVjdGl2ZSA9IGRpcmVjdGl2ZXNbaV07DQogICAgICAgIHZhciBhdHRyU3RhcnQgPSBkaXJlY3RpdmUuJCRzdGFydDsNCiAgICAgICAgdmFyIGF0dHJFbmQgPSBkaXJlY3RpdmUuJCRlbmQ7DQoNCiAgICAgICAgLy8gY29sbGVjdCBtdWx0aWJsb2NrIHNlY3Rpb25zDQogICAgICAgIGlmIChhdHRyU3RhcnQpIHsNCiAgICAgICAgICAkY29tcGlsZU5vZGUgPSBncm91cFNjYW4oY29tcGlsZU5vZGUsIGF0dHJTdGFydCwgYXR0ckVuZCk7DQogICAgICAgIH0NCiAgICAgICAgJHRlbXBsYXRlID0gdW5kZWZpbmVkOw0KDQogICAgICAgIGlmICh0ZXJtaW5hbFByaW9yaXR5ID4gZGlyZWN0aXZlLnByaW9yaXR5KSB7DQogICAgICAgICAgYnJlYWs7IC8vIHByZXZlbnQgZnVydGhlciBwcm9jZXNzaW5nIG9mIGRpcmVjdGl2ZXMNCiAgICAgICAgfQ0KDQogICAgICAgIGlmIChkaXJlY3RpdmVWYWx1ZSA9IGRpcmVjdGl2ZS5zY29wZSkgew0KDQogICAgICAgICAgLy8gc2tpcCB0aGUgY2hlY2sgZm9yIGRpcmVjdGl2ZXMgd2l0aCBhc3luYyB0ZW1wbGF0ZXMsIHdlJ2xsIGNoZWNrIHRoZSBkZXJpdmVkIHN5bmMNCiAgICAgICAgICAvLyBkaXJlY3RpdmUgd2hlbiB0aGUgdGVtcGxhdGUgYXJyaXZlcw0KICAgICAgICAgIGlmICghZGlyZWN0aXZlLnRlbXBsYXRlVXJsKSB7DQogICAgICAgICAgICBpZiAoaXNPYmplY3QoZGlyZWN0aXZlVmFsdWUpKSB7DQogICAgICAgICAgICAgIC8vIFRoaXMgZGlyZWN0aXZlIGlzIHRyeWluZyB0byBhZGQgYW4gaXNvbGF0ZWQgc2NvcGUuDQogICAgICAgICAgICAgIC8vIENoZWNrIHRoYXQgdGhlcmUgaXMgbm8gc2NvcGUgb2YgYW55IGtpbmQgYWxyZWFkeQ0KICAgICAgICAgICAgICBhc3NlcnROb0R1cGxpY2F0ZSgnbmV3L2lzb2xhdGVkIHNjb3BlJywgbmV3SXNvbGF0ZVNjb3BlRGlyZWN0aXZlIHx8IG5ld1Njb3BlRGlyZWN0aXZlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXJlY3RpdmUsICRjb21waWxlTm9kZSk7DQogICAgICAgICAgICAgIG5ld0lzb2xhdGVTY29wZURpcmVjdGl2ZSA9IGRpcmVjdGl2ZTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgIC8vIFRoaXMgZGlyZWN0aXZlIGlzIHRyeWluZyB0byBhZGQgYSBjaGlsZCBzY29wZS4NCiAgICAgICAgICAgICAgLy8gQ2hlY2sgdGhhdCB0aGVyZSBpcyBubyBpc29sYXRlZCBzY29wZSBhbHJlYWR5DQogICAgICAgICAgICAgIGFzc2VydE5vRHVwbGljYXRlKCduZXcvaXNvbGF0ZWQgc2NvcGUnLCBuZXdJc29sYXRlU2NvcGVEaXJlY3RpdmUsIGRpcmVjdGl2ZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGNvbXBpbGVOb2RlKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9DQoNCiAgICAgICAgICBuZXdTY29wZURpcmVjdGl2ZSA9IG5ld1Njb3BlRGlyZWN0aXZlIHx8IGRpcmVjdGl2ZTsNCiAgICAgICAgfQ0KDQogICAgICAgIGRpcmVjdGl2ZU5hbWUgPSBkaXJlY3RpdmUubmFtZTsNCg0KICAgICAgICBpZiAoIWRpcmVjdGl2ZS50ZW1wbGF0ZVVybCAmJiBkaXJlY3RpdmUuY29udHJvbGxlcikgew0KICAgICAgICAgIGRpcmVjdGl2ZVZhbHVlID0gZGlyZWN0aXZlLmNvbnRyb2xsZXI7DQogICAgICAgICAgY29udHJvbGxlckRpcmVjdGl2ZXMgPSBjb250cm9sbGVyRGlyZWN0aXZlcyB8fCB7fTsNCiAgICAgICAgICBhc3NlcnROb0R1cGxpY2F0ZSgiJyIgKyBkaXJlY3RpdmVOYW1lICsgIicgY29udHJvbGxlciIsDQogICAgICAgICAgICAgIGNvbnRyb2xsZXJEaXJlY3RpdmVzW2RpcmVjdGl2ZU5hbWVdLCBkaXJlY3RpdmUsICRjb21waWxlTm9kZSk7DQogICAgICAgICAgY29udHJvbGxlckRpcmVjdGl2ZXNbZGlyZWN0aXZlTmFtZV0gPSBkaXJlY3RpdmU7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoZGlyZWN0aXZlVmFsdWUgPSBkaXJlY3RpdmUudHJhbnNjbHVkZSkgew0KICAgICAgICAgIGhhc1RyYW5zY2x1ZGVEaXJlY3RpdmUgPSB0cnVlOw0KDQogICAgICAgICAgLy8gU3BlY2lhbCBjYXNlIG5nSWYgYW5kIG5nUmVwZWF0IHNvIHRoYXQgd2UgZG9uJ3QgY29tcGxhaW4gYWJvdXQgZHVwbGljYXRlIHRyYW5zY2x1c2lvbi4NCiAgICAgICAgICAvLyBUaGlzIG9wdGlvbiBzaG91bGQgb25seSBiZSB1c2VkIGJ5IGRpcmVjdGl2ZXMgdGhhdCBrbm93IGhvdyB0byBzYWZlbHkgaGFuZGxlIGVsZW1lbnQgdHJhbnNjbHVzaW9uLA0KICAgICAgICAgIC8vIHdoZXJlIHRoZSB0cmFuc2NsdWRlZCBub2RlcyBhcmUgYWRkZWQgb3IgcmVwbGFjZWQgYWZ0ZXIgbGlua2luZy4NCiAgICAgICAgICBpZiAoIWRpcmVjdGl2ZS4kJHRsYikgew0KICAgICAgICAgICAgYXNzZXJ0Tm9EdXBsaWNhdGUoJ3RyYW5zY2x1c2lvbicsIG5vblRsYlRyYW5zY2x1ZGVEaXJlY3RpdmUsIGRpcmVjdGl2ZSwgJGNvbXBpbGVOb2RlKTsNCiAgICAgICAgICAgIG5vblRsYlRyYW5zY2x1ZGVEaXJlY3RpdmUgPSBkaXJlY3RpdmU7DQogICAgICAgICAgfQ0KDQogICAgICAgICAgaWYgKGRpcmVjdGl2ZVZhbHVlID09ICdlbGVtZW50Jykgew0KICAgICAgICAgICAgaGFzRWxlbWVudFRyYW5zY2x1ZGVEaXJlY3RpdmUgPSB0cnVlOw0KICAgICAgICAgICAgdGVybWluYWxQcmlvcml0eSA9IGRpcmVjdGl2ZS5wcmlvcml0eTsNCiAgICAgICAgICAgICR0ZW1wbGF0ZSA9ICRjb21waWxlTm9kZTsNCiAgICAgICAgICAgICRjb21waWxlTm9kZSA9IHRlbXBsYXRlQXR0cnMuJCRlbGVtZW50ID0NCiAgICAgICAgICAgICAgICBqcUxpdGUoZG9jdW1lbnQuY3JlYXRlQ29tbWVudCgnICcgKyBkaXJlY3RpdmVOYW1lICsgJzogJyArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcGxhdGVBdHRyc1tkaXJlY3RpdmVOYW1lXSArICcgJykpOw0KICAgICAgICAgICAgY29tcGlsZU5vZGUgPSAkY29tcGlsZU5vZGVbMF07DQogICAgICAgICAgICByZXBsYWNlV2l0aChqcUNvbGxlY3Rpb24sIHNsaWNlQXJncygkdGVtcGxhdGUpLCBjb21waWxlTm9kZSk7DQoNCiAgICAgICAgICAgIGNoaWxkVHJhbnNjbHVkZUZuID0gY29tcGlsZSgkdGVtcGxhdGUsIHRyYW5zY2x1ZGVGbiwgdGVybWluYWxQcmlvcml0eSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYWNlRGlyZWN0aXZlICYmIHJlcGxhY2VEaXJlY3RpdmUubmFtZSwgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9uJ3QgcGFzcyBpbjoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0gY29udHJvbGxlckRpcmVjdGl2ZXMgLSBvdGhlcndpc2Ugd2UnbGwgY3JlYXRlIGR1cGxpY2F0ZXMgY29udHJvbGxlcnMNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0gbmV3SXNvbGF0ZVNjb3BlRGlyZWN0aXZlIG9yIHRlbXBsYXRlRGlyZWN0aXZlIC0gY29tYmluaW5nIHRlbXBsYXRlcyB3aXRoDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgIGVsZW1lbnQgdHJhbnNjbHVzaW9uIGRvZXNuJ3QgbWFrZSBzZW5zZS4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBuZWVkIG9ubHkgbm9uVGxiVHJhbnNjbHVkZURpcmVjdGl2ZSBzbyB0aGF0IHdlIHByZXZlbnQgcHV0dGluZyB0cmFuc2NsdXNpb24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9uIHRoZSBzYW1lIGVsZW1lbnQgbW9yZSB0aGFuIG9uY2UuDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25UbGJUcmFuc2NsdWRlRGlyZWN0aXZlOiBub25UbGJUcmFuc2NsdWRlRGlyZWN0aXZlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICR0ZW1wbGF0ZSA9IGpxTGl0ZShqcUxpdGVDbG9uZShjb21waWxlTm9kZSkpLmNvbnRlbnRzKCk7DQogICAgICAgICAgICAkY29tcGlsZU5vZGUuZW1wdHkoKTsgLy8gY2xlYXIgY29udGVudHMNCiAgICAgICAgICAgIGNoaWxkVHJhbnNjbHVkZUZuID0gY29tcGlsZSgkdGVtcGxhdGUsIHRyYW5zY2x1ZGVGbik7DQogICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKGRpcmVjdGl2ZS50ZW1wbGF0ZSkgew0KICAgICAgICAgIGhhc1RlbXBsYXRlID0gdHJ1ZTsNCiAgICAgICAgICBhc3NlcnROb0R1cGxpY2F0ZSgndGVtcGxhdGUnLCB0ZW1wbGF0ZURpcmVjdGl2ZSwgZGlyZWN0aXZlLCAkY29tcGlsZU5vZGUpOw0KICAgICAgICAgIHRlbXBsYXRlRGlyZWN0aXZlID0gZGlyZWN0aXZlOw0KDQogICAgICAgICAgZGlyZWN0aXZlVmFsdWUgPSAoaXNGdW5jdGlvbihkaXJlY3RpdmUudGVtcGxhdGUpKQ0KICAgICAgICAgICAgICA/IGRpcmVjdGl2ZS50ZW1wbGF0ZSgkY29tcGlsZU5vZGUsIHRlbXBsYXRlQXR0cnMpDQogICAgICAgICAgICAgIDogZGlyZWN0aXZlLnRlbXBsYXRlOw0KDQogICAgICAgICAgZGlyZWN0aXZlVmFsdWUgPSBkZW5vcm1hbGl6ZVRlbXBsYXRlKGRpcmVjdGl2ZVZhbHVlKTsNCg0KICAgICAgICAgIGlmIChkaXJlY3RpdmUucmVwbGFjZSkgew0KICAgICAgICAgICAgcmVwbGFjZURpcmVjdGl2ZSA9IGRpcmVjdGl2ZTsNCiAgICAgICAgICAgIGlmIChqcUxpdGVJc1RleHROb2RlKGRpcmVjdGl2ZVZhbHVlKSkgew0KICAgICAgICAgICAgICAkdGVtcGxhdGUgPSBbXTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICR0ZW1wbGF0ZSA9IHJlbW92ZUNvbW1lbnRzKHdyYXBUZW1wbGF0ZShkaXJlY3RpdmUudGVtcGxhdGVOYW1lc3BhY2UsIHRyaW0oZGlyZWN0aXZlVmFsdWUpKSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBjb21waWxlTm9kZSA9ICR0ZW1wbGF0ZVswXTsNCg0KICAgICAgICAgICAgaWYgKCR0ZW1wbGF0ZS5sZW5ndGggIT0gMSB8fCBjb21waWxlTm9kZS5ub2RlVHlwZSAhPT0gTk9ERV9UWVBFX0VMRU1FTlQpIHsNCiAgICAgICAgICAgICAgdGhyb3cgJGNvbXBpbGVNaW5FcnIoJ3RwbHJ0JywNCiAgICAgICAgICAgICAgICAgICJUZW1wbGF0ZSBmb3IgZGlyZWN0aXZlICd7MH0nIG11c3QgaGF2ZSBleGFjdGx5IG9uZSByb290IGVsZW1lbnQuIHsxfSIsDQogICAgICAgICAgICAgICAgICBkaXJlY3RpdmVOYW1lLCAnJyk7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIHJlcGxhY2VXaXRoKGpxQ29sbGVjdGlvbiwgJGNvbXBpbGVOb2RlLCBjb21waWxlTm9kZSk7DQoNCiAgICAgICAgICAgIHZhciBuZXdUZW1wbGF0ZUF0dHJzID0geyRhdHRyOiB7fX07DQoNCiAgICAgICAgICAgIC8vIGNvbWJpbmUgZGlyZWN0aXZlcyBmcm9tIHRoZSBvcmlnaW5hbCBub2RlIGFuZCBmcm9tIHRoZSB0ZW1wbGF0ZToNCiAgICAgICAgICAgIC8vIC0gdGFrZSB0aGUgYXJyYXkgb2YgZGlyZWN0aXZlcyBmb3IgdGhpcyBlbGVtZW50DQogICAgICAgICAgICAvLyAtIHNwbGl0IGl0IGludG8gdHdvIHBhcnRzLCB0aG9zZSB0aGF0IGFscmVhZHkgYXBwbGllZCAocHJvY2Vzc2VkKSBhbmQgdGhvc2UgdGhhdCB3ZXJlbid0ICh1bnByb2Nlc3NlZCkNCiAgICAgICAgICAgIC8vIC0gY29sbGVjdCBkaXJlY3RpdmVzIGZyb20gdGhlIHRlbXBsYXRlIGFuZCBzb3J0IHRoZW0gYnkgcHJpb3JpdHkNCiAgICAgICAgICAgIC8vIC0gY29tYmluZSBkaXJlY3RpdmVzIGFzOiBwcm9jZXNzZWQgKyB0ZW1wbGF0ZSArIHVucHJvY2Vzc2VkDQogICAgICAgICAgICB2YXIgdGVtcGxhdGVEaXJlY3RpdmVzID0gY29sbGVjdERpcmVjdGl2ZXMoY29tcGlsZU5vZGUsIFtdLCBuZXdUZW1wbGF0ZUF0dHJzKTsNCiAgICAgICAgICAgIHZhciB1bnByb2Nlc3NlZERpcmVjdGl2ZXMgPSBkaXJlY3RpdmVzLnNwbGljZShpICsgMSwgZGlyZWN0aXZlcy5sZW5ndGggLSAoaSArIDEpKTsNCg0KICAgICAgICAgICAgaWYgKG5ld0lzb2xhdGVTY29wZURpcmVjdGl2ZSkgew0KICAgICAgICAgICAgICBtYXJrRGlyZWN0aXZlc0FzSXNvbGF0ZSh0ZW1wbGF0ZURpcmVjdGl2ZXMpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgZGlyZWN0aXZlcyA9IGRpcmVjdGl2ZXMuY29uY2F0KHRlbXBsYXRlRGlyZWN0aXZlcykuY29uY2F0KHVucHJvY2Vzc2VkRGlyZWN0aXZlcyk7DQogICAgICAgICAgICBtZXJnZVRlbXBsYXRlQXR0cmlidXRlcyh0ZW1wbGF0ZUF0dHJzLCBuZXdUZW1wbGF0ZUF0dHJzKTsNCg0KICAgICAgICAgICAgaWkgPSBkaXJlY3RpdmVzLmxlbmd0aDsNCiAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJGNvbXBpbGVOb2RlLmh0bWwoZGlyZWN0aXZlVmFsdWUpOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGlmIChkaXJlY3RpdmUudGVtcGxhdGVVcmwpIHsNCiAgICAgICAgICBoYXNUZW1wbGF0ZSA9IHRydWU7DQogICAgICAgICAgYXNzZXJ0Tm9EdXBsaWNhdGUoJ3RlbXBsYXRlJywgdGVtcGxhdGVEaXJlY3RpdmUsIGRpcmVjdGl2ZSwgJGNvbXBpbGVOb2RlKTsNCiAgICAgICAgICB0ZW1wbGF0ZURpcmVjdGl2ZSA9IGRpcmVjdGl2ZTsNCg0KICAgICAgICAgIGlmIChkaXJlY3RpdmUucmVwbGFjZSkgew0KICAgICAgICAgICAgcmVwbGFjZURpcmVjdGl2ZSA9IGRpcmVjdGl2ZTsNCiAgICAgICAgICB9DQoNCiAgICAgICAgICBub2RlTGlua0ZuID0gY29tcGlsZVRlbXBsYXRlVXJsKGRpcmVjdGl2ZXMuc3BsaWNlKGksIGRpcmVjdGl2ZXMubGVuZ3RoIC0gaSksICRjb21waWxlTm9kZSwNCiAgICAgICAgICAgICAgdGVtcGxhdGVBdHRycywganFDb2xsZWN0aW9uLCBoYXNUcmFuc2NsdWRlRGlyZWN0aXZlICYmIGNoaWxkVHJhbnNjbHVkZUZuLCBwcmVMaW5rRm5zLCBwb3N0TGlua0Zucywgew0KICAgICAgICAgICAgICAgIGNvbnRyb2xsZXJEaXJlY3RpdmVzOiBjb250cm9sbGVyRGlyZWN0aXZlcywNCiAgICAgICAgICAgICAgICBuZXdJc29sYXRlU2NvcGVEaXJlY3RpdmU6IG5ld0lzb2xhdGVTY29wZURpcmVjdGl2ZSwNCiAgICAgICAgICAgICAgICB0ZW1wbGF0ZURpcmVjdGl2ZTogdGVtcGxhdGVEaXJlY3RpdmUsDQogICAgICAgICAgICAgICAgbm9uVGxiVHJhbnNjbHVkZURpcmVjdGl2ZTogbm9uVGxiVHJhbnNjbHVkZURpcmVjdGl2ZQ0KICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICBpaSA9IGRpcmVjdGl2ZXMubGVuZ3RoOw0KICAgICAgICB9IGVsc2UgaWYgKGRpcmVjdGl2ZS5jb21waWxlKSB7DQogICAgICAgICAgdHJ5IHsNCiAgICAgICAgICAgIGxpbmtGbiA9IGRpcmVjdGl2ZS5jb21waWxlKCRjb21waWxlTm9kZSwgdGVtcGxhdGVBdHRycywgY2hpbGRUcmFuc2NsdWRlRm4pOw0KICAgICAgICAgICAgaWYgKGlzRnVuY3Rpb24obGlua0ZuKSkgew0KICAgICAgICAgICAgICBhZGRMaW5rRm5zKG51bGwsIGxpbmtGbiwgYXR0clN0YXJ0LCBhdHRyRW5kKTsNCiAgICAgICAgICAgIH0gZWxzZSBpZiAobGlua0ZuKSB7DQogICAgICAgICAgICAgIGFkZExpbmtGbnMobGlua0ZuLnByZSwgbGlua0ZuLnBvc3QsIGF0dHJTdGFydCwgYXR0ckVuZCk7DQogICAgICAgICAgICB9DQogICAgICAgICAgfSBjYXRjaCAoZSkgew0KICAgICAgICAgICAgJGV4Y2VwdGlvbkhhbmRsZXIoZSwgc3RhcnRpbmdUYWcoJGNvbXBpbGVOb2RlKSk7DQogICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKGRpcmVjdGl2ZS50ZXJtaW5hbCkgew0KICAgICAgICAgIG5vZGVMaW5rRm4udGVybWluYWwgPSB0cnVlOw0KICAgICAgICAgIHRlcm1pbmFsUHJpb3JpdHkgPSBNYXRoLm1heCh0ZXJtaW5hbFByaW9yaXR5LCBkaXJlY3RpdmUucHJpb3JpdHkpOw0KICAgICAgICB9DQoNCiAgICAgIH0NCg0KICAgICAgbm9kZUxpbmtGbi5zY29wZSA9IG5ld1Njb3BlRGlyZWN0aXZlICYmIG5ld1Njb3BlRGlyZWN0aXZlLnNjb3BlID09PSB0cnVlOw0KICAgICAgbm9kZUxpbmtGbi50cmFuc2NsdWRlT25UaGlzRWxlbWVudCA9IGhhc1RyYW5zY2x1ZGVEaXJlY3RpdmU7DQogICAgICBub2RlTGlua0ZuLmVsZW1lbnRUcmFuc2NsdWRlT25UaGlzRWxlbWVudCA9IGhhc0VsZW1lbnRUcmFuc2NsdWRlRGlyZWN0aXZlOw0KICAgICAgbm9kZUxpbmtGbi50ZW1wbGF0ZU9uVGhpc0VsZW1lbnQgPSBoYXNUZW1wbGF0ZTsNCiAgICAgIG5vZGVMaW5rRm4udHJhbnNjbHVkZSA9IGNoaWxkVHJhbnNjbHVkZUZuOw0KDQogICAgICBwcmV2aW91c0NvbXBpbGVDb250ZXh0Lmhhc0VsZW1lbnRUcmFuc2NsdWRlRGlyZWN0aXZlID0gaGFzRWxlbWVudFRyYW5zY2x1ZGVEaXJlY3RpdmU7DQoNCiAgICAgIC8vIG1pZ2h0IGJlIG5vcm1hbCBvciBkZWxheWVkIG5vZGVMaW5rRm4gZGVwZW5kaW5nIG9uIGlmIHRlbXBsYXRlVXJsIGlzIHByZXNlbnQNCiAgICAgIHJldHVybiBub2RlTGlua0ZuOw0KDQogICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLw0KDQogICAgICBmdW5jdGlvbiBhZGRMaW5rRm5zKHByZSwgcG9zdCwgYXR0clN0YXJ0LCBhdHRyRW5kKSB7DQogICAgICAgIGlmIChwcmUpIHsNCiAgICAgICAgICBpZiAoYXR0clN0YXJ0KSBwcmUgPSBncm91cEVsZW1lbnRzTGlua0ZuV3JhcHBlcihwcmUsIGF0dHJTdGFydCwgYXR0ckVuZCk7DQogICAgICAgICAgcHJlLnJlcXVpcmUgPSBkaXJlY3RpdmUucmVxdWlyZTsNCiAgICAgICAgICBwcmUuZGlyZWN0aXZlTmFtZSA9IGRpcmVjdGl2ZU5hbWU7DQogICAgICAgICAgaWYgKG5ld0lzb2xhdGVTY29wZURpcmVjdGl2ZSA9PT0gZGlyZWN0aXZlIHx8IGRpcmVjdGl2ZS4kJGlzb2xhdGVTY29wZSkgew0KICAgICAgICAgICAgcHJlID0gY2xvbmVBbmRBbm5vdGF0ZUZuKHByZSwge2lzb2xhdGVTY29wZTogdHJ1ZX0pOw0KICAgICAgICAgIH0NCiAgICAgICAgICBwcmVMaW5rRm5zLnB1c2gocHJlKTsNCiAgICAgICAgfQ0KICAgICAgICBpZiAocG9zdCkgew0KICAgICAgICAgIGlmIChhdHRyU3RhcnQpIHBvc3QgPSBncm91cEVsZW1lbnRzTGlua0ZuV3JhcHBlcihwb3N0LCBhdHRyU3RhcnQsIGF0dHJFbmQpOw0KICAgICAgICAgIHBvc3QucmVxdWlyZSA9IGRpcmVjdGl2ZS5yZXF1aXJlOw0KICAgICAgICAgIHBvc3QuZGlyZWN0aXZlTmFtZSA9IGRpcmVjdGl2ZU5hbWU7DQogICAgICAgICAgaWYgKG5ld0lzb2xhdGVTY29wZURpcmVjdGl2ZSA9PT0gZGlyZWN0aXZlIHx8IGRpcmVjdGl2ZS4kJGlzb2xhdGVTY29wZSkgew0KICAgICAgICAgICAgcG9zdCA9IGNsb25lQW5kQW5ub3RhdGVGbihwb3N0LCB7aXNvbGF0ZVNjb3BlOiB0cnVlfSk7DQogICAgICAgICAgfQ0KICAgICAgICAgIHBvc3RMaW5rRm5zLnB1c2gocG9zdCk7DQogICAgICAgIH0NCiAgICAgIH0NCg0KDQogICAgICBmdW5jdGlvbiBnZXRDb250cm9sbGVycyhkaXJlY3RpdmVOYW1lLCByZXF1aXJlLCAkZWxlbWVudCwgZWxlbWVudENvbnRyb2xsZXJzKSB7DQogICAgICAgIHZhciB2YWx1ZSwgcmV0cmlldmFsTWV0aG9kID0gJ2RhdGEnLCBvcHRpb25hbCA9IGZhbHNlOw0KICAgICAgICB2YXIgJHNlYXJjaEVsZW1lbnQgPSAkZWxlbWVudDsNCiAgICAgICAgdmFyIG1hdGNoOw0KICAgICAgICBpZiAoaXNTdHJpbmcocmVxdWlyZSkpIHsNCiAgICAgICAgICBtYXRjaCA9IHJlcXVpcmUubWF0Y2goUkVRVUlSRV9QUkVGSVhfUkVHRVhQKTsNCiAgICAgICAgICByZXF1aXJlID0gcmVxdWlyZS5zdWJzdHJpbmcobWF0Y2hbMF0ubGVuZ3RoKTsNCg0KICAgICAgICAgIGlmIChtYXRjaFszXSkgew0KICAgICAgICAgICAgaWYgKG1hdGNoWzFdKSBtYXRjaFszXSA9IG51bGw7DQogICAgICAgICAgICBlbHNlIG1hdGNoWzFdID0gbWF0Y2hbM107DQogICAgICAgICAgfQ0KICAgICAgICAgIGlmIChtYXRjaFsxXSA9PT0gJ14nKSB7DQogICAgICAgICAgICByZXRyaWV2YWxNZXRob2QgPSAnaW5oZXJpdGVkRGF0YSc7DQogICAgICAgICAgfSBlbHNlIGlmIChtYXRjaFsxXSA9PT0gJ15eJykgew0KICAgICAgICAgICAgcmV0cmlldmFsTWV0aG9kID0gJ2luaGVyaXRlZERhdGEnOw0KICAgICAgICAgICAgJHNlYXJjaEVsZW1lbnQgPSAkZWxlbWVudC5wYXJlbnQoKTsNCiAgICAgICAgICB9DQogICAgICAgICAgaWYgKG1hdGNoWzJdID09PSAnPycpIHsNCiAgICAgICAgICAgIG9wdGlvbmFsID0gdHJ1ZTsNCiAgICAgICAgICB9DQoNCiAgICAgICAgICB2YWx1ZSA9IG51bGw7DQoNCiAgICAgICAgICBpZiAoZWxlbWVudENvbnRyb2xsZXJzICYmIHJldHJpZXZhbE1ldGhvZCA9PT0gJ2RhdGEnKSB7DQogICAgICAgICAgICBpZiAodmFsdWUgPSBlbGVtZW50Q29udHJvbGxlcnNbcmVxdWlyZV0pIHsNCiAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5pbnN0YW5jZTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9DQogICAgICAgICAgdmFsdWUgPSB2YWx1ZSB8fCAkc2VhcmNoRWxlbWVudFtyZXRyaWV2YWxNZXRob2RdKCckJyArIHJlcXVpcmUgKyAnQ29udHJvbGxlcicpOw0KDQogICAgICAgICAgaWYgKCF2YWx1ZSAmJiAhb3B0aW9uYWwpIHsNCiAgICAgICAgICAgIHRocm93ICRjb21waWxlTWluRXJyKCdjdHJlcScsDQogICAgICAgICAgICAgICAgIkNvbnRyb2xsZXIgJ3swfScsIHJlcXVpcmVkIGJ5IGRpcmVjdGl2ZSAnezF9JywgY2FuJ3QgYmUgZm91bmQhIiwNCiAgICAgICAgICAgICAgICByZXF1aXJlLCBkaXJlY3RpdmVOYW1lKTsNCiAgICAgICAgICB9DQogICAgICAgICAgcmV0dXJuIHZhbHVlIHx8IG51bGw7DQogICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShyZXF1aXJlKSkgew0KICAgICAgICAgIHZhbHVlID0gW107DQogICAgICAgICAgZm9yRWFjaChyZXF1aXJlLCBmdW5jdGlvbihyZXF1aXJlKSB7DQogICAgICAgICAgICB2YWx1ZS5wdXNoKGdldENvbnRyb2xsZXJzKGRpcmVjdGl2ZU5hbWUsIHJlcXVpcmUsICRlbGVtZW50LCBlbGVtZW50Q29udHJvbGxlcnMpKTsNCiAgICAgICAgICB9KTsNCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gdmFsdWU7DQogICAgICB9DQoNCg0KICAgICAgZnVuY3Rpb24gbm9kZUxpbmtGbihjaGlsZExpbmtGbiwgc2NvcGUsIGxpbmtOb2RlLCAkcm9vdEVsZW1lbnQsIGJvdW5kVHJhbnNjbHVkZUZuKSB7DQogICAgICAgIHZhciBpLCBpaSwgbGlua0ZuLCBjb250cm9sbGVyLCBpc29sYXRlU2NvcGUsIGVsZW1lbnRDb250cm9sbGVycywgdHJhbnNjbHVkZUZuLCAkZWxlbWVudCwNCiAgICAgICAgICAgIGF0dHJzOw0KDQogICAgICAgIGlmIChjb21waWxlTm9kZSA9PT0gbGlua05vZGUpIHsNCiAgICAgICAgICBhdHRycyA9IHRlbXBsYXRlQXR0cnM7DQogICAgICAgICAgJGVsZW1lbnQgPSB0ZW1wbGF0ZUF0dHJzLiQkZWxlbWVudDsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAkZWxlbWVudCA9IGpxTGl0ZShsaW5rTm9kZSk7DQogICAgICAgICAgYXR0cnMgPSBuZXcgQXR0cmlidXRlcygkZWxlbWVudCwgdGVtcGxhdGVBdHRycyk7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAobmV3SXNvbGF0ZVNjb3BlRGlyZWN0aXZlKSB7DQogICAgICAgICAgaXNvbGF0ZVNjb3BlID0gc2NvcGUuJG5ldyh0cnVlKTsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmIChib3VuZFRyYW5zY2x1ZGVGbikgew0KICAgICAgICAgIC8vIHRyYWNrIGBib3VuZFRyYW5zY2x1ZGVGbmAgc28gaXQgY2FuIGJlIHVud3JhcHBlZCBpZiBgdHJhbnNjbHVkZUZuYA0KICAgICAgICAgIC8vIGlzIGxhdGVyIHBhc3NlZCBhcyBgcGFyZW50Qm91bmRUcmFuc2NsdWRlRm5gIHRvIGBwdWJsaWNMaW5rRm5gDQogICAgICAgICAgdHJhbnNjbHVkZUZuID0gY29udHJvbGxlcnNCb3VuZFRyYW5zY2x1ZGU7DQogICAgICAgICAgdHJhbnNjbHVkZUZuLiQkYm91bmRUcmFuc2NsdWRlID0gYm91bmRUcmFuc2NsdWRlRm47DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoY29udHJvbGxlckRpcmVjdGl2ZXMpIHsNCiAgICAgICAgICAvLyBUT0RPOiBtZXJnZSBgY29udHJvbGxlcnNgIGFuZCBgZWxlbWVudENvbnRyb2xsZXJzYCBpbnRvIHNpbmdsZSBvYmplY3QuDQogICAgICAgICAgY29udHJvbGxlcnMgPSB7fTsNCiAgICAgICAgICBlbGVtZW50Q29udHJvbGxlcnMgPSB7fTsNCiAgICAgICAgICBmb3JFYWNoKGNvbnRyb2xsZXJEaXJlY3RpdmVzLCBmdW5jdGlvbihkaXJlY3RpdmUpIHsNCiAgICAgICAgICAgIHZhciBsb2NhbHMgPSB7DQogICAgICAgICAgICAgICRzY29wZTogZGlyZWN0aXZlID09PSBuZXdJc29sYXRlU2NvcGVEaXJlY3RpdmUgfHwgZGlyZWN0aXZlLiQkaXNvbGF0ZVNjb3BlID8gaXNvbGF0ZVNjb3BlIDogc2NvcGUsDQogICAgICAgICAgICAgICRlbGVtZW50OiAkZWxlbWVudCwNCiAgICAgICAgICAgICAgJGF0dHJzOiBhdHRycywNCiAgICAgICAgICAgICAgJHRyYW5zY2x1ZGU6IHRyYW5zY2x1ZGVGbg0KICAgICAgICAgICAgfSwgY29udHJvbGxlckluc3RhbmNlOw0KDQogICAgICAgICAgICBjb250cm9sbGVyID0gZGlyZWN0aXZlLmNvbnRyb2xsZXI7DQogICAgICAgICAgICBpZiAoY29udHJvbGxlciA9PSAnQCcpIHsNCiAgICAgICAgICAgICAgY29udHJvbGxlciA9IGF0dHJzW2RpcmVjdGl2ZS5uYW1lXTsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgY29udHJvbGxlckluc3RhbmNlID0gJGNvbnRyb2xsZXIoY29udHJvbGxlciwgbG9jYWxzLCB0cnVlLCBkaXJlY3RpdmUuY29udHJvbGxlckFzKTsNCg0KICAgICAgICAgICAgLy8gRm9yIGRpcmVjdGl2ZXMgd2l0aCBlbGVtZW50IHRyYW5zY2x1c2lvbiB0aGUgZWxlbWVudCBpcyBhIGNvbW1lbnQsDQogICAgICAgICAgICAvLyBidXQgalF1ZXJ5IC5kYXRhIGRvZXNuJ3Qgc3VwcG9ydCBhdHRhY2hpbmcgZGF0YSB0byBjb21tZW50IG5vZGVzIGFzIGl0J3MgaGFyZCB0bw0KICAgICAgICAgICAgLy8gY2xlYW4gdXAgKGh0dHA6Ly9idWdzLmpxdWVyeS5jb20vdGlja2V0LzgzMzUpLg0KICAgICAgICAgICAgLy8gSW5zdGVhZCwgd2Ugc2F2ZSB0aGUgY29udHJvbGxlcnMgZm9yIHRoZSBlbGVtZW50IGluIGEgbG9jYWwgaGFzaCBhbmQgYXR0YWNoIHRvIC5kYXRhDQogICAgICAgICAgICAvLyBsYXRlciwgb25jZSB3ZSBoYXZlIHRoZSBhY3R1YWwgZWxlbWVudC4NCiAgICAgICAgICAgIGVsZW1lbnRDb250cm9sbGVyc1tkaXJlY3RpdmUubmFtZV0gPSBjb250cm9sbGVySW5zdGFuY2U7DQogICAgICAgICAgICBpZiAoIWhhc0VsZW1lbnRUcmFuc2NsdWRlRGlyZWN0aXZlKSB7DQogICAgICAgICAgICAgICRlbGVtZW50LmRhdGEoJyQnICsgZGlyZWN0aXZlLm5hbWUgKyAnQ29udHJvbGxlcicsIGNvbnRyb2xsZXJJbnN0YW5jZS5pbnN0YW5jZSk7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGNvbnRyb2xsZXJzW2RpcmVjdGl2ZS5uYW1lXSA9IGNvbnRyb2xsZXJJbnN0YW5jZTsNCiAgICAgICAgICB9KTsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmIChuZXdJc29sYXRlU2NvcGVEaXJlY3RpdmUpIHsNCiAgICAgICAgICBjb21waWxlLiQkYWRkU2NvcGVJbmZvKCRlbGVtZW50LCBpc29sYXRlU2NvcGUsIHRydWUsICEodGVtcGxhdGVEaXJlY3RpdmUgJiYgKHRlbXBsYXRlRGlyZWN0aXZlID09PSBuZXdJc29sYXRlU2NvcGVEaXJlY3RpdmUgfHwNCiAgICAgICAgICAgICAgdGVtcGxhdGVEaXJlY3RpdmUgPT09IG5ld0lzb2xhdGVTY29wZURpcmVjdGl2ZS4kJG9yaWdpbmFsRGlyZWN0aXZlKSkpOw0KICAgICAgICAgIGNvbXBpbGUuJCRhZGRTY29wZUNsYXNzKCRlbGVtZW50LCB0cnVlKTsNCg0KICAgICAgICAgIHZhciBpc29sYXRlU2NvcGVDb250cm9sbGVyID0gY29udHJvbGxlcnMgJiYgY29udHJvbGxlcnNbbmV3SXNvbGF0ZVNjb3BlRGlyZWN0aXZlLm5hbWVdOw0KICAgICAgICAgIHZhciBpc29sYXRlQmluZGluZ0NvbnRleHQgPSBpc29sYXRlU2NvcGU7DQogICAgICAgICAgaWYgKGlzb2xhdGVTY29wZUNvbnRyb2xsZXIgJiYgaXNvbGF0ZVNjb3BlQ29udHJvbGxlci5pZGVudGlmaWVyICYmDQogICAgICAgICAgICAgIG5ld0lzb2xhdGVTY29wZURpcmVjdGl2ZS5iaW5kVG9Db250cm9sbGVyID09PSB0cnVlKSB7DQogICAgICAgICAgICBpc29sYXRlQmluZGluZ0NvbnRleHQgPSBpc29sYXRlU2NvcGVDb250cm9sbGVyLmluc3RhbmNlOw0KICAgICAgICAgIH0NCg0KICAgICAgICAgIGZvckVhY2goaXNvbGF0ZVNjb3BlLiQkaXNvbGF0ZUJpbmRpbmdzID0gbmV3SXNvbGF0ZVNjb3BlRGlyZWN0aXZlLiQkaXNvbGF0ZUJpbmRpbmdzLCBmdW5jdGlvbihkZWZpbml0aW9uLCBzY29wZU5hbWUpIHsNCiAgICAgICAgICAgIHZhciBhdHRyTmFtZSA9IGRlZmluaXRpb24uYXR0ck5hbWUsDQogICAgICAgICAgICAgICAgb3B0aW9uYWwgPSBkZWZpbml0aW9uLm9wdGlvbmFsLA0KICAgICAgICAgICAgICAgIG1vZGUgPSBkZWZpbml0aW9uLm1vZGUsIC8vIEAsID0sIG9yICYNCiAgICAgICAgICAgICAgICBsYXN0VmFsdWUsDQogICAgICAgICAgICAgICAgcGFyZW50R2V0LCBwYXJlbnRTZXQsIGNvbXBhcmU7DQoNCiAgICAgICAgICAgIHN3aXRjaCAobW9kZSkgew0KDQogICAgICAgICAgICAgIGNhc2UgJ0AnOg0KICAgICAgICAgICAgICAgIGF0dHJzLiRvYnNlcnZlKGF0dHJOYW1lLCBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICAgICAgICAgICAgaXNvbGF0ZUJpbmRpbmdDb250ZXh0W3Njb3BlTmFtZV0gPSB2YWx1ZTsNCiAgICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICAgICAgICBhdHRycy4kJG9ic2VydmVyc1thdHRyTmFtZV0uJCRzY29wZSA9IHNjb3BlOw0KICAgICAgICAgICAgICAgIGlmIChhdHRyc1thdHRyTmFtZV0pIHsNCiAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBhdHRyaWJ1dGUgaGFzIGJlZW4gcHJvdmlkZWQgdGhlbiB3ZSB0cmlnZ2VyIGFuIGludGVycG9sYXRpb24gdG8gZW5zdXJlDQogICAgICAgICAgICAgICAgICAvLyB0aGUgdmFsdWUgaXMgdGhlcmUgZm9yIHVzZSBpbiB0aGUgbGluayBmbg0KICAgICAgICAgICAgICAgICAgaXNvbGF0ZUJpbmRpbmdDb250ZXh0W3Njb3BlTmFtZV0gPSAkaW50ZXJwb2xhdGUoYXR0cnNbYXR0ck5hbWVdKShzY29wZSk7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgIGNhc2UgJz0nOg0KICAgICAgICAgICAgICAgIGlmIChvcHRpb25hbCAmJiAhYXR0cnNbYXR0ck5hbWVdKSB7DQogICAgICAgICAgICAgICAgICByZXR1cm47DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIHBhcmVudEdldCA9ICRwYXJzZShhdHRyc1thdHRyTmFtZV0pOw0KICAgICAgICAgICAgICAgIGlmIChwYXJlbnRHZXQubGl0ZXJhbCkgew0KICAgICAgICAgICAgICAgICAgY29tcGFyZSA9IGVxdWFsczsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgY29tcGFyZSA9IGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIGEgPT09IGIgfHwgKGEgIT09IGEgJiYgYiAhPT0gYik7IH07DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIHBhcmVudFNldCA9IHBhcmVudEdldC5hc3NpZ24gfHwgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgICAgICAvLyByZXNldCB0aGUgY2hhbmdlLCBvciB3ZSB3aWxsIHRocm93IHRoaXMgZXhjZXB0aW9uIG9uIGV2ZXJ5ICRkaWdlc3QNCiAgICAgICAgICAgICAgICAgIGxhc3RWYWx1ZSA9IGlzb2xhdGVCaW5kaW5nQ29udGV4dFtzY29wZU5hbWVdID0gcGFyZW50R2V0KHNjb3BlKTsNCiAgICAgICAgICAgICAgICAgIHRocm93ICRjb21waWxlTWluRXJyKCdub25hc3NpZ24nLA0KICAgICAgICAgICAgICAgICAgICAgICJFeHByZXNzaW9uICd7MH0nIHVzZWQgd2l0aCBkaXJlY3RpdmUgJ3sxfScgaXMgbm9uLWFzc2lnbmFibGUhIiwNCiAgICAgICAgICAgICAgICAgICAgICBhdHRyc1thdHRyTmFtZV0sIG5ld0lzb2xhdGVTY29wZURpcmVjdGl2ZS5uYW1lKTsNCiAgICAgICAgICAgICAgICB9Ow0KICAgICAgICAgICAgICAgIGxhc3RWYWx1ZSA9IGlzb2xhdGVCaW5kaW5nQ29udGV4dFtzY29wZU5hbWVdID0gcGFyZW50R2V0KHNjb3BlKTsNCiAgICAgICAgICAgICAgICB2YXIgcGFyZW50VmFsdWVXYXRjaCA9IGZ1bmN0aW9uIHBhcmVudFZhbHVlV2F0Y2gocGFyZW50VmFsdWUpIHsNCiAgICAgICAgICAgICAgICAgIGlmICghY29tcGFyZShwYXJlbnRWYWx1ZSwgaXNvbGF0ZUJpbmRpbmdDb250ZXh0W3Njb3BlTmFtZV0pKSB7DQogICAgICAgICAgICAgICAgICAgIC8vIHdlIGFyZSBvdXQgb2Ygc3luYyBhbmQgbmVlZCB0byBjb3B5DQogICAgICAgICAgICAgICAgICAgIGlmICghY29tcGFyZShwYXJlbnRWYWx1ZSwgbGFzdFZhbHVlKSkgew0KICAgICAgICAgICAgICAgICAgICAgIC8vIHBhcmVudCBjaGFuZ2VkIGFuZCBpdCBoYXMgcHJlY2VkZW5jZQ0KICAgICAgICAgICAgICAgICAgICAgIGlzb2xhdGVCaW5kaW5nQ29udGV4dFtzY29wZU5hbWVdID0gcGFyZW50VmFsdWU7DQogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHBhcmVudCBjYW4gYmUgYXNzaWduZWQgdGhlbiBkbyBzbw0KICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFNldChzY29wZSwgcGFyZW50VmFsdWUgPSBpc29sYXRlQmluZGluZ0NvbnRleHRbc2NvcGVOYW1lXSk7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgIHJldHVybiBsYXN0VmFsdWUgPSBwYXJlbnRWYWx1ZTsNCiAgICAgICAgICAgICAgICB9Ow0KICAgICAgICAgICAgICAgIHBhcmVudFZhbHVlV2F0Y2guJHN0YXRlZnVsID0gdHJ1ZTsNCiAgICAgICAgICAgICAgICB2YXIgdW53YXRjaDsNCiAgICAgICAgICAgICAgICBpZiAoZGVmaW5pdGlvbi5jb2xsZWN0aW9uKSB7DQogICAgICAgICAgICAgICAgICB1bndhdGNoID0gc2NvcGUuJHdhdGNoQ29sbGVjdGlvbihhdHRyc1thdHRyTmFtZV0sIHBhcmVudFZhbHVlV2F0Y2gpOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICB1bndhdGNoID0gc2NvcGUuJHdhdGNoKCRwYXJzZShhdHRyc1thdHRyTmFtZV0sIHBhcmVudFZhbHVlV2F0Y2gpLCBudWxsLCBwYXJlbnRHZXQubGl0ZXJhbCk7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGlzb2xhdGVTY29wZS4kb24oJyRkZXN0cm95JywgdW53YXRjaCk7DQogICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgY2FzZSAnJic6DQogICAgICAgICAgICAgICAgcGFyZW50R2V0ID0gJHBhcnNlKGF0dHJzW2F0dHJOYW1lXSk7DQogICAgICAgICAgICAgICAgaXNvbGF0ZUJpbmRpbmdDb250ZXh0W3Njb3BlTmFtZV0gPSBmdW5jdGlvbihsb2NhbHMpIHsNCiAgICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnRHZXQoc2NvcGUsIGxvY2Fscyk7DQogICAgICAgICAgICAgICAgfTsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9KTsNCiAgICAgICAgfQ0KICAgICAgICBpZiAoY29udHJvbGxlcnMpIHsNCiAgICAgICAgICBmb3JFYWNoKGNvbnRyb2xsZXJzLCBmdW5jdGlvbihjb250cm9sbGVyKSB7DQogICAgICAgICAgICBjb250cm9sbGVyKCk7DQogICAgICAgICAgfSk7DQogICAgICAgICAgY29udHJvbGxlcnMgPSBudWxsOw0KICAgICAgICB9DQoNCiAgICAgICAgLy8gUFJFTElOS0lORw0KICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IHByZUxpbmtGbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykgew0KICAgICAgICAgIGxpbmtGbiA9IHByZUxpbmtGbnNbaV07DQogICAgICAgICAgaW52b2tlTGlua0ZuKGxpbmtGbiwNCiAgICAgICAgICAgICAgbGlua0ZuLmlzb2xhdGVTY29wZSA/IGlzb2xhdGVTY29wZSA6IHNjb3BlLA0KICAgICAgICAgICAgICAkZWxlbWVudCwNCiAgICAgICAgICAgICAgYXR0cnMsDQogICAgICAgICAgICAgIGxpbmtGbi5yZXF1aXJlICYmIGdldENvbnRyb2xsZXJzKGxpbmtGbi5kaXJlY3RpdmVOYW1lLCBsaW5rRm4ucmVxdWlyZSwgJGVsZW1lbnQsIGVsZW1lbnRDb250cm9sbGVycyksDQogICAgICAgICAgICAgIHRyYW5zY2x1ZGVGbg0KICAgICAgICAgICk7DQogICAgICAgIH0NCg0KICAgICAgICAvLyBSRUNVUlNJT04NCiAgICAgICAgLy8gV2Ugb25seSBwYXNzIHRoZSBpc29sYXRlIHNjb3BlLCBpZiB0aGUgaXNvbGF0ZSBkaXJlY3RpdmUgaGFzIGEgdGVtcGxhdGUsDQogICAgICAgIC8vIG90aGVyd2lzZSB0aGUgY2hpbGQgZWxlbWVudHMgZG8gbm90IGJlbG9uZyB0byB0aGUgaXNvbGF0ZSBkaXJlY3RpdmUuDQogICAgICAgIHZhciBzY29wZVRvQ2hpbGQgPSBzY29wZTsNCiAgICAgICAgaWYgKG5ld0lzb2xhdGVTY29wZURpcmVjdGl2ZSAmJiAobmV3SXNvbGF0ZVNjb3BlRGlyZWN0aXZlLnRlbXBsYXRlIHx8IG5ld0lzb2xhdGVTY29wZURpcmVjdGl2ZS50ZW1wbGF0ZVVybCA9PT0gbnVsbCkpIHsNCiAgICAgICAgICBzY29wZVRvQ2hpbGQgPSBpc29sYXRlU2NvcGU7DQogICAgICAgIH0NCiAgICAgICAgY2hpbGRMaW5rRm4gJiYgY2hpbGRMaW5rRm4oc2NvcGVUb0NoaWxkLCBsaW5rTm9kZS5jaGlsZE5vZGVzLCB1bmRlZmluZWQsIGJvdW5kVHJhbnNjbHVkZUZuKTsNCg0KICAgICAgICAvLyBQT1NUTElOS0lORw0KICAgICAgICBmb3IgKGkgPSBwb3N0TGlua0Zucy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgew0KICAgICAgICAgIGxpbmtGbiA9IHBvc3RMaW5rRm5zW2ldOw0KICAgICAgICAgIGludm9rZUxpbmtGbihsaW5rRm4sDQogICAgICAgICAgICAgIGxpbmtGbi5pc29sYXRlU2NvcGUgPyBpc29sYXRlU2NvcGUgOiBzY29wZSwNCiAgICAgICAgICAgICAgJGVsZW1lbnQsDQogICAgICAgICAgICAgIGF0dHJzLA0KICAgICAgICAgICAgICBsaW5rRm4ucmVxdWlyZSAmJiBnZXRDb250cm9sbGVycyhsaW5rRm4uZGlyZWN0aXZlTmFtZSwgbGlua0ZuLnJlcXVpcmUsICRlbGVtZW50LCBlbGVtZW50Q29udHJvbGxlcnMpLA0KICAgICAgICAgICAgICB0cmFuc2NsdWRlRm4NCiAgICAgICAgICApOw0KICAgICAgICB9DQoNCiAgICAgICAgLy8gVGhpcyBpcyB0aGUgZnVuY3Rpb24gdGhhdCBpcyBpbmplY3RlZCBhcyBgJHRyYW5zY2x1ZGVgLg0KICAgICAgICAvLyBOb3RlOiBhbGwgYXJndW1lbnRzIGFyZSBvcHRpb25hbCENCiAgICAgICAgZnVuY3Rpb24gY29udHJvbGxlcnNCb3VuZFRyYW5zY2x1ZGUoc2NvcGUsIGNsb25lQXR0YWNoRm4sIGZ1dHVyZVBhcmVudEVsZW1lbnQpIHsNCiAgICAgICAgICB2YXIgdHJhbnNjbHVkZUNvbnRyb2xsZXJzOw0KDQogICAgICAgICAgLy8gTm8gc2NvcGUgcGFzc2VkIGluOg0KICAgICAgICAgIGlmICghaXNTY29wZShzY29wZSkpIHsNCiAgICAgICAgICAgIGZ1dHVyZVBhcmVudEVsZW1lbnQgPSBjbG9uZUF0dGFjaEZuOw0KICAgICAgICAgICAgY2xvbmVBdHRhY2hGbiA9IHNjb3BlOw0KICAgICAgICAgICAgc2NvcGUgPSB1bmRlZmluZWQ7DQogICAgICAgICAgfQ0KDQogICAgICAgICAgaWYgKGhhc0VsZW1lbnRUcmFuc2NsdWRlRGlyZWN0aXZlKSB7DQogICAgICAgICAgICB0cmFuc2NsdWRlQ29udHJvbGxlcnMgPSBlbGVtZW50Q29udHJvbGxlcnM7DQogICAgICAgICAgfQ0KICAgICAgICAgIGlmICghZnV0dXJlUGFyZW50RWxlbWVudCkgew0KICAgICAgICAgICAgZnV0dXJlUGFyZW50RWxlbWVudCA9IGhhc0VsZW1lbnRUcmFuc2NsdWRlRGlyZWN0aXZlID8gJGVsZW1lbnQucGFyZW50KCkgOiAkZWxlbWVudDsNCiAgICAgICAgICB9DQogICAgICAgICAgcmV0dXJuIGJvdW5kVHJhbnNjbHVkZUZuKHNjb3BlLCBjbG9uZUF0dGFjaEZuLCB0cmFuc2NsdWRlQ29udHJvbGxlcnMsIGZ1dHVyZVBhcmVudEVsZW1lbnQsIHNjb3BlVG9DaGlsZCk7DQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQoNCiAgICBmdW5jdGlvbiBtYXJrRGlyZWN0aXZlc0FzSXNvbGF0ZShkaXJlY3RpdmVzKSB7DQogICAgICAvLyBtYXJrIGFsbCBkaXJlY3RpdmVzIGFzIG5lZWRpbmcgaXNvbGF0ZSBzY29wZS4NCiAgICAgIGZvciAodmFyIGogPSAwLCBqaiA9IGRpcmVjdGl2ZXMubGVuZ3RoOyBqIDwgamo7IGorKykgew0KICAgICAgICBkaXJlY3RpdmVzW2pdID0gaW5oZXJpdChkaXJlY3RpdmVzW2pdLCB7JCRpc29sYXRlU2NvcGU6IHRydWV9KTsNCiAgICAgIH0NCiAgICB9DQoNCiAgICAvKioNCiAgICAgKiBsb29rcyB1cCB0aGUgZGlyZWN0aXZlIGFuZCBkZWNvcmF0ZXMgaXQgd2l0aCBleGNlcHRpb24gaGFuZGxpbmcgYW5kIHByb3BlciBwYXJhbWV0ZXJzLiBXZQ0KICAgICAqIGNhbGwgdGhpcyB0aGUgYm91bmREaXJlY3RpdmUuDQogICAgICoNCiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBuYW1lIG9mIHRoZSBkaXJlY3RpdmUgdG8gbG9vayB1cC4NCiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbG9jYXRpb24gVGhlIGRpcmVjdGl2ZSBtdXN0IGJlIGZvdW5kIGluIHNwZWNpZmljIGZvcm1hdC4NCiAgICAgKiAgIFN0cmluZyBjb250YWluaW5nIGFueSBvZiB0aGVzZXMgY2hhcmFjdGVyczoNCiAgICAgKg0KICAgICAqICAgKiBgRWA6IGVsZW1lbnQgbmFtZQ0KICAgICAqICAgKiBgQSc6IGF0dHJpYnV0ZQ0KICAgICAqICAgKiBgQ2A6IGNsYXNzDQogICAgICogICAqIGBNYDogY29tbWVudA0KICAgICAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIGRpcmVjdGl2ZSB3YXMgYWRkZWQuDQogICAgICovDQogICAgZnVuY3Rpb24gYWRkRGlyZWN0aXZlKHREaXJlY3RpdmVzLCBuYW1lLCBsb2NhdGlvbiwgbWF4UHJpb3JpdHksIGlnbm9yZURpcmVjdGl2ZSwgc3RhcnRBdHRyTmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kQXR0ck5hbWUpIHsNCiAgICAgIGlmIChuYW1lID09PSBpZ25vcmVEaXJlY3RpdmUpIHJldHVybiBudWxsOw0KICAgICAgdmFyIG1hdGNoID0gbnVsbDsNCiAgICAgIGlmIChoYXNEaXJlY3RpdmVzLmhhc093blByb3BlcnR5KG5hbWUpKSB7DQogICAgICAgIGZvciAodmFyIGRpcmVjdGl2ZSwgZGlyZWN0aXZlcyA9ICRpbmplY3Rvci5nZXQobmFtZSArIFN1ZmZpeCksDQogICAgICAgICAgICBpID0gMCwgaWkgPSBkaXJlY3RpdmVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsNCiAgICAgICAgICB0cnkgew0KICAgICAgICAgICAgZGlyZWN0aXZlID0gZGlyZWN0aXZlc1tpXTsNCiAgICAgICAgICAgIGlmICgobWF4UHJpb3JpdHkgPT09IHVuZGVmaW5lZCB8fCBtYXhQcmlvcml0eSA+IGRpcmVjdGl2ZS5wcmlvcml0eSkgJiYNCiAgICAgICAgICAgICAgICAgZGlyZWN0aXZlLnJlc3RyaWN0LmluZGV4T2YobG9jYXRpb24pICE9IC0xKSB7DQogICAgICAgICAgICAgIGlmIChzdGFydEF0dHJOYW1lKSB7DQogICAgICAgICAgICAgICAgZGlyZWN0aXZlID0gaW5oZXJpdChkaXJlY3RpdmUsIHskJHN0YXJ0OiBzdGFydEF0dHJOYW1lLCAkJGVuZDogZW5kQXR0ck5hbWV9KTsNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICB0RGlyZWN0aXZlcy5wdXNoKGRpcmVjdGl2ZSk7DQogICAgICAgICAgICAgIG1hdGNoID0gZGlyZWN0aXZlOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0gY2F0Y2ggKGUpIHsgJGV4Y2VwdGlvbkhhbmRsZXIoZSk7IH0NCiAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgcmV0dXJuIG1hdGNoOw0KICAgIH0NCg0KDQogICAgLyoqDQogICAgICogbG9va3MgdXAgdGhlIGRpcmVjdGl2ZSBhbmQgcmV0dXJucyB0cnVlIGlmIGl0IGlzIGEgbXVsdGktZWxlbWVudCBkaXJlY3RpdmUsDQogICAgICogYW5kIHRoZXJlZm9yZSByZXF1aXJlcyBET00gbm9kZXMgYmV0d2VlbiAtc3RhcnQgYW5kIC1lbmQgbWFya2VycyB0byBiZSBncm91cGVkDQogICAgICogdG9nZXRoZXIuDQogICAgICoNCiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBuYW1lIG9mIHRoZSBkaXJlY3RpdmUgdG8gbG9vayB1cC4NCiAgICAgKiBAcmV0dXJucyB0cnVlIGlmIGRpcmVjdGl2ZSB3YXMgcmVnaXN0ZXJlZCBhcyBtdWx0aS1lbGVtZW50Lg0KICAgICAqLw0KICAgIGZ1bmN0aW9uIGRpcmVjdGl2ZUlzTXVsdGlFbGVtZW50KG5hbWUpIHsNCiAgICAgIGlmIChoYXNEaXJlY3RpdmVzLmhhc093blByb3BlcnR5KG5hbWUpKSB7DQogICAgICAgIGZvciAodmFyIGRpcmVjdGl2ZSwgZGlyZWN0aXZlcyA9ICRpbmplY3Rvci5nZXQobmFtZSArIFN1ZmZpeCksDQogICAgICAgICAgICBpID0gMCwgaWkgPSBkaXJlY3RpdmVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsNCiAgICAgICAgICBkaXJlY3RpdmUgPSBkaXJlY3RpdmVzW2ldOw0KICAgICAgICAgIGlmIChkaXJlY3RpdmUubXVsdGlFbGVtZW50KSB7DQogICAgICAgICAgICByZXR1cm4gdHJ1ZTsNCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgIH0NCiAgICAgIHJldHVybiBmYWxzZTsNCiAgICB9DQoNCiAgICAvKioNCiAgICAgKiBXaGVuIHRoZSBlbGVtZW50IGlzIHJlcGxhY2VkIHdpdGggSFRNTCB0ZW1wbGF0ZSB0aGVuIHRoZSBuZXcgYXR0cmlidXRlcw0KICAgICAqIG9uIHRoZSB0ZW1wbGF0ZSBuZWVkIHRvIGJlIG1lcmdlZCB3aXRoIHRoZSBleGlzdGluZyBhdHRyaWJ1dGVzIGluIHRoZSBET00uDQogICAgICogVGhlIGRlc2lyZWQgZWZmZWN0IGlzIHRvIGhhdmUgYm90aCBvZiB0aGUgYXR0cmlidXRlcyBwcmVzZW50Lg0KICAgICAqDQogICAgICogQHBhcmFtIHtvYmplY3R9IGRzdCBkZXN0aW5hdGlvbiBhdHRyaWJ1dGVzIChvcmlnaW5hbCBET00pDQogICAgICogQHBhcmFtIHtvYmplY3R9IHNyYyBzb3VyY2UgYXR0cmlidXRlcyAoZnJvbSB0aGUgZGlyZWN0aXZlIHRlbXBsYXRlKQ0KICAgICAqLw0KICAgIGZ1bmN0aW9uIG1lcmdlVGVtcGxhdGVBdHRyaWJ1dGVzKGRzdCwgc3JjKSB7DQogICAgICB2YXIgc3JjQXR0ciA9IHNyYy4kYXR0ciwNCiAgICAgICAgICBkc3RBdHRyID0gZHN0LiRhdHRyLA0KICAgICAgICAgICRlbGVtZW50ID0gZHN0LiQkZWxlbWVudDsNCg0KICAgICAgLy8gcmVhcHBseSB0aGUgb2xkIGF0dHJpYnV0ZXMgdG8gdGhlIG5ldyBlbGVtZW50DQogICAgICBmb3JFYWNoKGRzdCwgZnVuY3Rpb24odmFsdWUsIGtleSkgew0KICAgICAgICBpZiAoa2V5LmNoYXJBdCgwKSAhPSAnJCcpIHsNCiAgICAgICAgICBpZiAoc3JjW2tleV0gJiYgc3JjW2tleV0gIT09IHZhbHVlKSB7DQogICAgICAgICAgICB2YWx1ZSArPSAoa2V5ID09PSAnc3R5bGUnID8gJzsnIDogJyAnKSArIHNyY1trZXldOw0KICAgICAgICAgIH0NCiAgICAgICAgICBkc3QuJHNldChrZXksIHZhbHVlLCB0cnVlLCBzcmNBdHRyW2tleV0pOw0KICAgICAgICB9DQogICAgICB9KTsNCg0KICAgICAgLy8gY29weSB0aGUgbmV3IGF0dHJpYnV0ZXMgb24gdGhlIG9sZCBhdHRycyBvYmplY3QNCiAgICAgIGZvckVhY2goc3JjLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7DQogICAgICAgIGlmIChrZXkgPT0gJ2NsYXNzJykgew0KICAgICAgICAgIHNhZmVBZGRDbGFzcygkZWxlbWVudCwgdmFsdWUpOw0KICAgICAgICAgIGRzdFsnY2xhc3MnXSA9IChkc3RbJ2NsYXNzJ10gPyBkc3RbJ2NsYXNzJ10gKyAnICcgOiAnJykgKyB2YWx1ZTsNCiAgICAgICAgfSBlbHNlIGlmIChrZXkgPT0gJ3N0eWxlJykgew0KICAgICAgICAgICRlbGVtZW50LmF0dHIoJ3N0eWxlJywgJGVsZW1lbnQuYXR0cignc3R5bGUnKSArICc7JyArIHZhbHVlKTsNCiAgICAgICAgICBkc3RbJ3N0eWxlJ10gPSAoZHN0WydzdHlsZSddID8gZHN0WydzdHlsZSddICsgJzsnIDogJycpICsgdmFsdWU7DQogICAgICAgICAgLy8gYGRzdGAgd2lsbCBuZXZlciBjb250YWluIGhhc093blByb3BlcnR5IGFzIERPTSBwYXJzZXIgd29uJ3QgbGV0IGl0Lg0KICAgICAgICAgIC8vIFlvdSB3aWxsIGdldCBhbiAiSW52YWxpZENoYXJhY3RlckVycm9yOiBET00gRXhjZXB0aW9uIDUiIGVycm9yIGlmIHlvdQ0KICAgICAgICAgIC8vIGhhdmUgYW4gYXR0cmlidXRlIGxpa2UgImhhcy1vd24tcHJvcGVydHkiIG9yICJkYXRhLWhhcy1vd24tcHJvcGVydHkiLCBldGMuDQogICAgICAgIH0gZWxzZSBpZiAoa2V5LmNoYXJBdCgwKSAhPSAnJCcgJiYgIWRzdC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7DQogICAgICAgICAgZHN0W2tleV0gPSB2YWx1ZTsNCiAgICAgICAgICBkc3RBdHRyW2tleV0gPSBzcmNBdHRyW2tleV07DQogICAgICAgIH0NCiAgICAgIH0pOw0KICAgIH0NCg0KDQogICAgZnVuY3Rpb24gY29tcGlsZVRlbXBsYXRlVXJsKGRpcmVjdGl2ZXMsICRjb21waWxlTm9kZSwgdEF0dHJzLA0KICAgICAgICAkcm9vdEVsZW1lbnQsIGNoaWxkVHJhbnNjbHVkZUZuLCBwcmVMaW5rRm5zLCBwb3N0TGlua0ZucywgcHJldmlvdXNDb21waWxlQ29udGV4dCkgew0KICAgICAgdmFyIGxpbmtRdWV1ZSA9IFtdLA0KICAgICAgICAgIGFmdGVyVGVtcGxhdGVOb2RlTGlua0ZuLA0KICAgICAgICAgIGFmdGVyVGVtcGxhdGVDaGlsZExpbmtGbiwNCiAgICAgICAgICBiZWZvcmVUZW1wbGF0ZUNvbXBpbGVOb2RlID0gJGNvbXBpbGVOb2RlWzBdLA0KICAgICAgICAgIG9yaWdBc3luY0RpcmVjdGl2ZSA9IGRpcmVjdGl2ZXMuc2hpZnQoKSwNCiAgICAgICAgICAvLyBUaGUgZmFjdCB0aGF0IHdlIGhhdmUgdG8gY29weSBhbmQgcGF0Y2ggdGhlIGRpcmVjdGl2ZSBzZWVtcyB3cm9uZyENCiAgICAgICAgICBkZXJpdmVkU3luY0RpcmVjdGl2ZSA9IGV4dGVuZCh7fSwgb3JpZ0FzeW5jRGlyZWN0aXZlLCB7DQogICAgICAgICAgICB0ZW1wbGF0ZVVybDogbnVsbCwgdHJhbnNjbHVkZTogbnVsbCwgcmVwbGFjZTogbnVsbCwgJCRvcmlnaW5hbERpcmVjdGl2ZTogb3JpZ0FzeW5jRGlyZWN0aXZlDQogICAgICAgICAgfSksDQogICAgICAgICAgdGVtcGxhdGVVcmwgPSAoaXNGdW5jdGlvbihvcmlnQXN5bmNEaXJlY3RpdmUudGVtcGxhdGVVcmwpKQ0KICAgICAgICAgICAgICA/IG9yaWdBc3luY0RpcmVjdGl2ZS50ZW1wbGF0ZVVybCgkY29tcGlsZU5vZGUsIHRBdHRycykNCiAgICAgICAgICAgICAgOiBvcmlnQXN5bmNEaXJlY3RpdmUudGVtcGxhdGVVcmwsDQogICAgICAgICAgdGVtcGxhdGVOYW1lc3BhY2UgPSBvcmlnQXN5bmNEaXJlY3RpdmUudGVtcGxhdGVOYW1lc3BhY2U7DQoNCiAgICAgICRjb21waWxlTm9kZS5lbXB0eSgpOw0KDQogICAgICAkdGVtcGxhdGVSZXF1ZXN0KCRzY2UuZ2V0VHJ1c3RlZFJlc291cmNlVXJsKHRlbXBsYXRlVXJsKSkNCiAgICAgICAgLnRoZW4oZnVuY3Rpb24oY29udGVudCkgew0KICAgICAgICAgIHZhciBjb21waWxlTm9kZSwgdGVtcFRlbXBsYXRlQXR0cnMsICR0ZW1wbGF0ZSwgY2hpbGRCb3VuZFRyYW5zY2x1ZGVGbjsNCg0KICAgICAgICAgIGNvbnRlbnQgPSBkZW5vcm1hbGl6ZVRlbXBsYXRlKGNvbnRlbnQpOw0KDQogICAgICAgICAgaWYgKG9yaWdBc3luY0RpcmVjdGl2ZS5yZXBsYWNlKSB7DQogICAgICAgICAgICBpZiAoanFMaXRlSXNUZXh0Tm9kZShjb250ZW50KSkgew0KICAgICAgICAgICAgICAkdGVtcGxhdGUgPSBbXTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICR0ZW1wbGF0ZSA9IHJlbW92ZUNvbW1lbnRzKHdyYXBUZW1wbGF0ZSh0ZW1wbGF0ZU5hbWVzcGFjZSwgdHJpbShjb250ZW50KSkpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgY29tcGlsZU5vZGUgPSAkdGVtcGxhdGVbMF07DQoNCiAgICAgICAgICAgIGlmICgkdGVtcGxhdGUubGVuZ3RoICE9IDEgfHwgY29tcGlsZU5vZGUubm9kZVR5cGUgIT09IE5PREVfVFlQRV9FTEVNRU5UKSB7DQogICAgICAgICAgICAgIHRocm93ICRjb21waWxlTWluRXJyKCd0cGxydCcsDQogICAgICAgICAgICAgICAgICAiVGVtcGxhdGUgZm9yIGRpcmVjdGl2ZSAnezB9JyBtdXN0IGhhdmUgZXhhY3RseSBvbmUgcm9vdCBlbGVtZW50LiB7MX0iLA0KICAgICAgICAgICAgICAgICAgb3JpZ0FzeW5jRGlyZWN0aXZlLm5hbWUsIHRlbXBsYXRlVXJsKTsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgdGVtcFRlbXBsYXRlQXR0cnMgPSB7JGF0dHI6IHt9fTsNCiAgICAgICAgICAgIHJlcGxhY2VXaXRoKCRyb290RWxlbWVudCwgJGNvbXBpbGVOb2RlLCBjb21waWxlTm9kZSk7DQogICAgICAgICAgICB2YXIgdGVtcGxhdGVEaXJlY3RpdmVzID0gY29sbGVjdERpcmVjdGl2ZXMoY29tcGlsZU5vZGUsIFtdLCB0ZW1wVGVtcGxhdGVBdHRycyk7DQoNCiAgICAgICAgICAgIGlmIChpc09iamVjdChvcmlnQXN5bmNEaXJlY3RpdmUuc2NvcGUpKSB7DQogICAgICAgICAgICAgIG1hcmtEaXJlY3RpdmVzQXNJc29sYXRlKHRlbXBsYXRlRGlyZWN0aXZlcyk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBkaXJlY3RpdmVzID0gdGVtcGxhdGVEaXJlY3RpdmVzLmNvbmNhdChkaXJlY3RpdmVzKTsNCiAgICAgICAgICAgIG1lcmdlVGVtcGxhdGVBdHRyaWJ1dGVzKHRBdHRycywgdGVtcFRlbXBsYXRlQXR0cnMpOw0KICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBjb21waWxlTm9kZSA9IGJlZm9yZVRlbXBsYXRlQ29tcGlsZU5vZGU7DQogICAgICAgICAgICAkY29tcGlsZU5vZGUuaHRtbChjb250ZW50KTsNCiAgICAgICAgICB9DQoNCiAgICAgICAgICBkaXJlY3RpdmVzLnVuc2hpZnQoZGVyaXZlZFN5bmNEaXJlY3RpdmUpOw0KDQogICAgICAgICAgYWZ0ZXJUZW1wbGF0ZU5vZGVMaW5rRm4gPSBhcHBseURpcmVjdGl2ZXNUb05vZGUoZGlyZWN0aXZlcywgY29tcGlsZU5vZGUsIHRBdHRycywNCiAgICAgICAgICAgICAgY2hpbGRUcmFuc2NsdWRlRm4sICRjb21waWxlTm9kZSwgb3JpZ0FzeW5jRGlyZWN0aXZlLCBwcmVMaW5rRm5zLCBwb3N0TGlua0ZucywNCiAgICAgICAgICAgICAgcHJldmlvdXNDb21waWxlQ29udGV4dCk7DQogICAgICAgICAgZm9yRWFjaCgkcm9vdEVsZW1lbnQsIGZ1bmN0aW9uKG5vZGUsIGkpIHsNCiAgICAgICAgICAgIGlmIChub2RlID09IGNvbXBpbGVOb2RlKSB7DQogICAgICAgICAgICAgICRyb290RWxlbWVudFtpXSA9ICRjb21waWxlTm9kZVswXTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9KTsNCiAgICAgICAgICBhZnRlclRlbXBsYXRlQ2hpbGRMaW5rRm4gPSBjb21waWxlTm9kZXMoJGNvbXBpbGVOb2RlWzBdLmNoaWxkTm9kZXMsIGNoaWxkVHJhbnNjbHVkZUZuKTsNCg0KICAgICAgICAgIHdoaWxlIChsaW5rUXVldWUubGVuZ3RoKSB7DQogICAgICAgICAgICB2YXIgc2NvcGUgPSBsaW5rUXVldWUuc2hpZnQoKSwNCiAgICAgICAgICAgICAgICBiZWZvcmVUZW1wbGF0ZUxpbmtOb2RlID0gbGlua1F1ZXVlLnNoaWZ0KCksDQogICAgICAgICAgICAgICAgbGlua1Jvb3RFbGVtZW50ID0gbGlua1F1ZXVlLnNoaWZ0KCksDQogICAgICAgICAgICAgICAgYm91bmRUcmFuc2NsdWRlRm4gPSBsaW5rUXVldWUuc2hpZnQoKSwNCiAgICAgICAgICAgICAgICBsaW5rTm9kZSA9ICRjb21waWxlTm9kZVswXTsNCg0KICAgICAgICAgICAgaWYgKHNjb3BlLiQkZGVzdHJveWVkKSBjb250aW51ZTsNCg0KICAgICAgICAgICAgaWYgKGJlZm9yZVRlbXBsYXRlTGlua05vZGUgIT09IGJlZm9yZVRlbXBsYXRlQ29tcGlsZU5vZGUpIHsNCiAgICAgICAgICAgICAgdmFyIG9sZENsYXNzZXMgPSBiZWZvcmVUZW1wbGF0ZUxpbmtOb2RlLmNsYXNzTmFtZTsNCg0KICAgICAgICAgICAgICBpZiAoIShwcmV2aW91c0NvbXBpbGVDb250ZXh0Lmhhc0VsZW1lbnRUcmFuc2NsdWRlRGlyZWN0aXZlICYmDQogICAgICAgICAgICAgICAgICBvcmlnQXN5bmNEaXJlY3RpdmUucmVwbGFjZSkpIHsNCiAgICAgICAgICAgICAgICAvLyBpdCB3YXMgY2xvbmVkIHRoZXJlZm9yZSB3ZSBoYXZlIHRvIGNsb25lIGFzIHdlbGwuDQogICAgICAgICAgICAgICAgbGlua05vZGUgPSBqcUxpdGVDbG9uZShjb21waWxlTm9kZSk7DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgcmVwbGFjZVdpdGgobGlua1Jvb3RFbGVtZW50LCBqcUxpdGUoYmVmb3JlVGVtcGxhdGVMaW5rTm9kZSksIGxpbmtOb2RlKTsNCg0KICAgICAgICAgICAgICAvLyBDb3B5IGluIENTUyBjbGFzc2VzIGZyb20gb3JpZ2luYWwgbm9kZQ0KICAgICAgICAgICAgICBzYWZlQWRkQ2xhc3MoanFMaXRlKGxpbmtOb2RlKSwgb2xkQ2xhc3Nlcyk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBpZiAoYWZ0ZXJUZW1wbGF0ZU5vZGVMaW5rRm4udHJhbnNjbHVkZU9uVGhpc0VsZW1lbnQpIHsNCiAgICAgICAgICAgICAgY2hpbGRCb3VuZFRyYW5zY2x1ZGVGbiA9IGNyZWF0ZUJvdW5kVHJhbnNjbHVkZUZuKHNjb3BlLCBhZnRlclRlbXBsYXRlTm9kZUxpbmtGbi50cmFuc2NsdWRlLCBib3VuZFRyYW5zY2x1ZGVGbik7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICBjaGlsZEJvdW5kVHJhbnNjbHVkZUZuID0gYm91bmRUcmFuc2NsdWRlRm47DQogICAgICAgICAgICB9DQogICAgICAgICAgICBhZnRlclRlbXBsYXRlTm9kZUxpbmtGbihhZnRlclRlbXBsYXRlQ2hpbGRMaW5rRm4sIHNjb3BlLCBsaW5rTm9kZSwgJHJvb3RFbGVtZW50LA0KICAgICAgICAgICAgICBjaGlsZEJvdW5kVHJhbnNjbHVkZUZuKTsNCiAgICAgICAgICB9DQogICAgICAgICAgbGlua1F1ZXVlID0gbnVsbDsNCiAgICAgICAgfSk7DQoNCiAgICAgIHJldHVybiBmdW5jdGlvbiBkZWxheWVkTm9kZUxpbmtGbihpZ25vcmVDaGlsZExpbmtGbiwgc2NvcGUsIG5vZGUsIHJvb3RFbGVtZW50LCBib3VuZFRyYW5zY2x1ZGVGbikgew0KICAgICAgICB2YXIgY2hpbGRCb3VuZFRyYW5zY2x1ZGVGbiA9IGJvdW5kVHJhbnNjbHVkZUZuOw0KICAgICAgICBpZiAoc2NvcGUuJCRkZXN0cm95ZWQpIHJldHVybjsNCiAgICAgICAgaWYgKGxpbmtRdWV1ZSkgew0KICAgICAgICAgIGxpbmtRdWV1ZS5wdXNoKHNjb3BlLA0KICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEVsZW1lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRCb3VuZFRyYW5zY2x1ZGVGbik7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgaWYgKGFmdGVyVGVtcGxhdGVOb2RlTGlua0ZuLnRyYW5zY2x1ZGVPblRoaXNFbGVtZW50KSB7DQogICAgICAgICAgICBjaGlsZEJvdW5kVHJhbnNjbHVkZUZuID0gY3JlYXRlQm91bmRUcmFuc2NsdWRlRm4oc2NvcGUsIGFmdGVyVGVtcGxhdGVOb2RlTGlua0ZuLnRyYW5zY2x1ZGUsIGJvdW5kVHJhbnNjbHVkZUZuKTsNCiAgICAgICAgICB9DQogICAgICAgICAgYWZ0ZXJUZW1wbGF0ZU5vZGVMaW5rRm4oYWZ0ZXJUZW1wbGF0ZUNoaWxkTGlua0ZuLCBzY29wZSwgbm9kZSwgcm9vdEVsZW1lbnQsIGNoaWxkQm91bmRUcmFuc2NsdWRlRm4pOw0KICAgICAgICB9DQogICAgICB9Ow0KICAgIH0NCg0KDQogICAgLyoqDQogICAgICogU29ydGluZyBmdW5jdGlvbiBmb3IgYm91bmQgZGlyZWN0aXZlcy4NCiAgICAgKi8NCiAgICBmdW5jdGlvbiBieVByaW9yaXR5KGEsIGIpIHsNCiAgICAgIHZhciBkaWZmID0gYi5wcmlvcml0eSAtIGEucHJpb3JpdHk7DQogICAgICBpZiAoZGlmZiAhPT0gMCkgcmV0dXJuIGRpZmY7DQogICAgICBpZiAoYS5uYW1lICE9PSBiLm5hbWUpIHJldHVybiAoYS5uYW1lIDwgYi5uYW1lKSA/IC0xIDogMTsNCiAgICAgIHJldHVybiBhLmluZGV4IC0gYi5pbmRleDsNCiAgICB9DQoNCg0KICAgIGZ1bmN0aW9uIGFzc2VydE5vRHVwbGljYXRlKHdoYXQsIHByZXZpb3VzRGlyZWN0aXZlLCBkaXJlY3RpdmUsIGVsZW1lbnQpIHsNCiAgICAgIGlmIChwcmV2aW91c0RpcmVjdGl2ZSkgew0KICAgICAgICB0aHJvdyAkY29tcGlsZU1pbkVycignbXVsdGlkaXInLCAnTXVsdGlwbGUgZGlyZWN0aXZlcyBbezB9LCB7MX1dIGFza2luZyBmb3IgezJ9IG9uOiB7M30nLA0KICAgICAgICAgICAgcHJldmlvdXNEaXJlY3RpdmUubmFtZSwgZGlyZWN0aXZlLm5hbWUsIHdoYXQsIHN0YXJ0aW5nVGFnKGVsZW1lbnQpKTsNCiAgICAgIH0NCiAgICB9DQoNCg0KICAgIGZ1bmN0aW9uIGFkZFRleHRJbnRlcnBvbGF0ZURpcmVjdGl2ZShkaXJlY3RpdmVzLCB0ZXh0KSB7DQogICAgICB2YXIgaW50ZXJwb2xhdGVGbiA9ICRpbnRlcnBvbGF0ZSh0ZXh0LCB0cnVlKTsNCiAgICAgIGlmIChpbnRlcnBvbGF0ZUZuKSB7DQogICAgICAgIGRpcmVjdGl2ZXMucHVzaCh7DQogICAgICAgICAgcHJpb3JpdHk6IDAsDQogICAgICAgICAgY29tcGlsZTogZnVuY3Rpb24gdGV4dEludGVycG9sYXRlQ29tcGlsZUZuKHRlbXBsYXRlTm9kZSkgew0KICAgICAgICAgICAgdmFyIHRlbXBsYXRlTm9kZVBhcmVudCA9IHRlbXBsYXRlTm9kZS5wYXJlbnQoKSwNCiAgICAgICAgICAgICAgICBoYXNDb21waWxlUGFyZW50ID0gISF0ZW1wbGF0ZU5vZGVQYXJlbnQubGVuZ3RoOw0KDQogICAgICAgICAgICAvLyBXaGVuIHRyYW5zY2x1ZGluZyBhIHRlbXBsYXRlIHRoYXQgaGFzIGJpbmRpbmdzIGluIHRoZSByb290DQogICAgICAgICAgICAvLyB3ZSBkb24ndCBoYXZlIGEgcGFyZW50IGFuZCB0aHVzIG5lZWQgdG8gYWRkIHRoZSBjbGFzcyBkdXJpbmcgbGlua2luZyBmbi4NCiAgICAgICAgICAgIGlmIChoYXNDb21waWxlUGFyZW50KSBjb21waWxlLiQkYWRkQmluZGluZ0NsYXNzKHRlbXBsYXRlTm9kZVBhcmVudCk7DQoNCiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiB0ZXh0SW50ZXJwb2xhdGVMaW5rRm4oc2NvcGUsIG5vZGUpIHsNCiAgICAgICAgICAgICAgdmFyIHBhcmVudCA9IG5vZGUucGFyZW50KCk7DQogICAgICAgICAgICAgIGlmICghaGFzQ29tcGlsZVBhcmVudCkgY29tcGlsZS4kJGFkZEJpbmRpbmdDbGFzcyhwYXJlbnQpOw0KICAgICAgICAgICAgICBjb21waWxlLiQkYWRkQmluZGluZ0luZm8ocGFyZW50LCBpbnRlcnBvbGF0ZUZuLmV4cHJlc3Npb25zKTsNCiAgICAgICAgICAgICAgc2NvcGUuJHdhdGNoKGludGVycG9sYXRlRm4sIGZ1bmN0aW9uIGludGVycG9sYXRlRm5XYXRjaEFjdGlvbih2YWx1ZSkgew0KICAgICAgICAgICAgICAgIG5vZGVbMF0ubm9kZVZhbHVlID0gdmFsdWU7DQogICAgICAgICAgICAgIH0pOw0KICAgICAgICAgICAgfTsNCiAgICAgICAgICB9DQogICAgICAgIH0pOw0KICAgICAgfQ0KICAgIH0NCg0KDQogICAgZnVuY3Rpb24gd3JhcFRlbXBsYXRlKHR5cGUsIHRlbXBsYXRlKSB7DQogICAgICB0eXBlID0gbG93ZXJjYXNlKHR5cGUgfHwgJ2h0bWwnKTsNCiAgICAgIHN3aXRjaCAodHlwZSkgew0KICAgICAgY2FzZSAnc3ZnJzoNCiAgICAgIGNhc2UgJ21hdGgnOg0KICAgICAgICB2YXIgd3JhcHBlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOw0KICAgICAgICB3cmFwcGVyLmlubmVySFRNTCA9ICc8JyArIHR5cGUgKyAnPicgKyB0ZW1wbGF0ZSArICc8LycgKyB0eXBlICsgJz4nOw0KICAgICAgICByZXR1cm4gd3JhcHBlci5jaGlsZE5vZGVzWzBdLmNoaWxkTm9kZXM7DQogICAgICBkZWZhdWx0Og0KICAgICAgICByZXR1cm4gdGVtcGxhdGU7DQogICAgICB9DQogICAgfQ0KDQoNCiAgICBmdW5jdGlvbiBnZXRUcnVzdGVkQ29udGV4dChub2RlLCBhdHRyTm9ybWFsaXplZE5hbWUpIHsNCiAgICAgIGlmIChhdHRyTm9ybWFsaXplZE5hbWUgPT0gInNyY2RvYyIpIHsNCiAgICAgICAgcmV0dXJuICRzY2UuSFRNTDsNCiAgICAgIH0NCiAgICAgIHZhciB0YWcgPSBub2RlTmFtZV8obm9kZSk7DQogICAgICAvLyBtYWN0aW9uW3hsaW5rOmhyZWZdIGNhbiBzb3VyY2UgU1ZHLiAgSXQncyBub3QgbGltaXRlZCB0byA8bWFjdGlvbj4uDQogICAgICBpZiAoYXR0ck5vcm1hbGl6ZWROYW1lID09ICJ4bGlua0hyZWYiIHx8DQogICAgICAgICAgKHRhZyA9PSAiZm9ybSIgJiYgYXR0ck5vcm1hbGl6ZWROYW1lID09ICJhY3Rpb24iKSB8fA0KICAgICAgICAgICh0YWcgIT0gImltZyIgJiYgKGF0dHJOb3JtYWxpemVkTmFtZSA9PSAic3JjIiB8fA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dHJOb3JtYWxpemVkTmFtZSA9PSAibmdTcmMiKSkpIHsNCiAgICAgICAgcmV0dXJuICRzY2UuUkVTT1VSQ0VfVVJMOw0KICAgICAgfQ0KICAgIH0NCg0KDQogICAgZnVuY3Rpb24gYWRkQXR0ckludGVycG9sYXRlRGlyZWN0aXZlKG5vZGUsIGRpcmVjdGl2ZXMsIHZhbHVlLCBuYW1lLCBhbGxPck5vdGhpbmcpIHsNCiAgICAgIHZhciB0cnVzdGVkQ29udGV4dCA9IGdldFRydXN0ZWRDb250ZXh0KG5vZGUsIG5hbWUpOw0KICAgICAgYWxsT3JOb3RoaW5nID0gQUxMX09SX05PVEhJTkdfQVRUUlNbbmFtZV0gfHwgYWxsT3JOb3RoaW5nOw0KDQogICAgICB2YXIgaW50ZXJwb2xhdGVGbiA9ICRpbnRlcnBvbGF0ZSh2YWx1ZSwgdHJ1ZSwgdHJ1c3RlZENvbnRleHQsIGFsbE9yTm90aGluZyk7DQoNCiAgICAgIC8vIG5vIGludGVycG9sYXRpb24gZm91bmQgLT4gaWdub3JlDQogICAgICBpZiAoIWludGVycG9sYXRlRm4pIHJldHVybjsNCg0KDQogICAgICBpZiAobmFtZSA9PT0gIm11bHRpcGxlIiAmJiBub2RlTmFtZV8obm9kZSkgPT09ICJzZWxlY3QiKSB7DQogICAgICAgIHRocm93ICRjb21waWxlTWluRXJyKCJzZWxtdWx0aSIsDQogICAgICAgICAgICAiQmluZGluZyB0byB0aGUgJ211bHRpcGxlJyBhdHRyaWJ1dGUgaXMgbm90IHN1cHBvcnRlZC4gRWxlbWVudDogezB9IiwNCiAgICAgICAgICAgIHN0YXJ0aW5nVGFnKG5vZGUpKTsNCiAgICAgIH0NCg0KICAgICAgZGlyZWN0aXZlcy5wdXNoKHsNCiAgICAgICAgcHJpb3JpdHk6IDEwMCwNCiAgICAgICAgY29tcGlsZTogZnVuY3Rpb24oKSB7DQogICAgICAgICAgICByZXR1cm4gew0KICAgICAgICAgICAgICBwcmU6IGZ1bmN0aW9uIGF0dHJJbnRlcnBvbGF0ZVByZUxpbmtGbihzY29wZSwgZWxlbWVudCwgYXR0cikgew0KICAgICAgICAgICAgICAgIHZhciAkJG9ic2VydmVycyA9IChhdHRyLiQkb2JzZXJ2ZXJzIHx8IChhdHRyLiQkb2JzZXJ2ZXJzID0ge30pKTsNCg0KICAgICAgICAgICAgICAgIGlmIChFVkVOVF9IQU5ETEVSX0FUVFJfUkVHRVhQLnRlc3QobmFtZSkpIHsNCiAgICAgICAgICAgICAgICAgIHRocm93ICRjb21waWxlTWluRXJyKCdub2RvbWV2ZW50cycsDQogICAgICAgICAgICAgICAgICAgICAgIkludGVycG9sYXRpb25zIGZvciBIVE1MIERPTSBldmVudCBhdHRyaWJ1dGVzIGFyZSBkaXNhbGxvd2VkLiAgUGxlYXNlIHVzZSB0aGUgIiArDQogICAgICAgICAgICAgICAgICAgICAgICAgICJuZy0gdmVyc2lvbnMgKHN1Y2ggYXMgbmctY2xpY2sgaW5zdGVhZCBvZiBvbmNsaWNrKSBpbnN0ZWFkLiIpOw0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgIC8vIElmIHRoZSBhdHRyaWJ1dGUgaGFzIGNoYW5nZWQgc2luY2UgbGFzdCAkaW50ZXJwb2xhdGUoKWVkDQogICAgICAgICAgICAgICAgdmFyIG5ld1ZhbHVlID0gYXR0cltuYW1lXTsNCiAgICAgICAgICAgICAgICBpZiAobmV3VmFsdWUgIT09IHZhbHVlKSB7DQogICAgICAgICAgICAgICAgICAvLyB3ZSBuZWVkIHRvIGludGVycG9sYXRlIGFnYWluIHNpbmNlIHRoZSBhdHRyaWJ1dGUgdmFsdWUgaGFzIGJlZW4gdXBkYXRlZA0KICAgICAgICAgICAgICAgICAgLy8gKGUuZy4gYnkgYW5vdGhlciBkaXJlY3RpdmUncyBjb21waWxlIGZ1bmN0aW9uKQ0KICAgICAgICAgICAgICAgICAgLy8gZW5zdXJlIHVuc2V0L2VtcHR5IHZhbHVlcyBtYWtlIGludGVycG9sYXRlRm4gZmFsc3kNCiAgICAgICAgICAgICAgICAgIGludGVycG9sYXRlRm4gPSBuZXdWYWx1ZSAmJiAkaW50ZXJwb2xhdGUobmV3VmFsdWUsIHRydWUsIHRydXN0ZWRDb250ZXh0LCBhbGxPck5vdGhpbmcpOw0KICAgICAgICAgICAgICAgICAgdmFsdWUgPSBuZXdWYWx1ZTsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAvLyBpZiBhdHRyaWJ1dGUgd2FzIHVwZGF0ZWQgc28gdGhhdCB0aGVyZSBpcyBubyBpbnRlcnBvbGF0aW9uIGdvaW5nIG9uIHdlIGRvbid0IHdhbnQgdG8NCiAgICAgICAgICAgICAgICAvLyByZWdpc3RlciBhbnkgb2JzZXJ2ZXJzDQogICAgICAgICAgICAgICAgaWYgKCFpbnRlcnBvbGF0ZUZuKSByZXR1cm47DQoNCiAgICAgICAgICAgICAgICAvLyBpbml0aWFsaXplIGF0dHIgb2JqZWN0IHNvIHRoYXQgaXQncyByZWFkeSBpbiBjYXNlIHdlIG5lZWQgdGhlIHZhbHVlIGZvciBpc29sYXRlDQogICAgICAgICAgICAgICAgLy8gc2NvcGUgaW5pdGlhbGl6YXRpb24sIG90aGVyd2lzZSB0aGUgdmFsdWUgd291bGQgbm90IGJlIGF2YWlsYWJsZSBmcm9tIGlzb2xhdGUNCiAgICAgICAgICAgICAgICAvLyBkaXJlY3RpdmUncyBsaW5raW5nIGZuIGR1cmluZyBsaW5raW5nIHBoYXNlDQogICAgICAgICAgICAgICAgYXR0cltuYW1lXSA9IGludGVycG9sYXRlRm4oc2NvcGUpOw0KDQogICAgICAgICAgICAgICAgKCQkb2JzZXJ2ZXJzW25hbWVdIHx8ICgkJG9ic2VydmVyc1tuYW1lXSA9IFtdKSkuJCRpbnRlciA9IHRydWU7DQogICAgICAgICAgICAgICAgKGF0dHIuJCRvYnNlcnZlcnMgJiYgYXR0ci4kJG9ic2VydmVyc1tuYW1lXS4kJHNjb3BlIHx8IHNjb3BlKS4NCiAgICAgICAgICAgICAgICAgICR3YXRjaChpbnRlcnBvbGF0ZUZuLCBmdW5jdGlvbiBpbnRlcnBvbGF0ZUZuV2F0Y2hBY3Rpb24obmV3VmFsdWUsIG9sZFZhbHVlKSB7DQogICAgICAgICAgICAgICAgICAgIC8vc3BlY2lhbCBjYXNlIGZvciBjbGFzcyBhdHRyaWJ1dGUgYWRkaXRpb24gKyByZW1vdmFsDQogICAgICAgICAgICAgICAgICAgIC8vc28gdGhhdCBjbGFzcyBjaGFuZ2VzIGNhbiB0YXAgaW50byB0aGUgYW5pbWF0aW9uDQogICAgICAgICAgICAgICAgICAgIC8vaG9va3MgcHJvdmlkZWQgYnkgdGhlICRhbmltYXRlIHNlcnZpY2UuIEJlIHN1cmUgdG8NCiAgICAgICAgICAgICAgICAgICAgLy9za2lwIGFuaW1hdGlvbnMgd2hlbiB0aGUgZmlyc3QgZGlnZXN0IG9jY3VycyAod2hlbg0KICAgICAgICAgICAgICAgICAgICAvL2JvdGggdGhlIG5ldyBhbmQgdGhlIG9sZCB2YWx1ZXMgYXJlIHRoZSBzYW1lKSBzaW5jZQ0KICAgICAgICAgICAgICAgICAgICAvL3RoZSBDU1MgY2xhc3NlcyBhcmUgdGhlIG5vbi1pbnRlcnBvbGF0ZWQgdmFsdWVzDQogICAgICAgICAgICAgICAgICAgIGlmIChuYW1lID09PSAnY2xhc3MnICYmIG5ld1ZhbHVlICE9IG9sZFZhbHVlKSB7DQogICAgICAgICAgICAgICAgICAgICAgYXR0ci4kdXBkYXRlQ2xhc3MobmV3VmFsdWUsIG9sZFZhbHVlKTsNCiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICBhdHRyLiRzZXQobmFtZSwgbmV3VmFsdWUpOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfTsNCiAgICAgICAgICB9DQogICAgICB9KTsNCiAgICB9DQoNCg0KICAgIC8qKg0KICAgICAqIFRoaXMgaXMgYSBzcGVjaWFsIGpxTGl0ZS5yZXBsYWNlV2l0aCwgd2hpY2ggY2FuIHJlcGxhY2UgaXRlbXMgd2hpY2gNCiAgICAgKiBoYXZlIG5vIHBhcmVudHMsIHByb3ZpZGVkIHRoYXQgdGhlIGNvbnRhaW5pbmcganFMaXRlIGNvbGxlY3Rpb24gaXMgcHJvdmlkZWQuDQogICAgICoNCiAgICAgKiBAcGFyYW0ge0pxTGl0ZT19ICRyb290RWxlbWVudCBUaGUgcm9vdCBvZiB0aGUgY29tcGlsZSB0cmVlLiBVc2VkIHNvIHRoYXQgd2UgY2FuIHJlcGxhY2Ugbm9kZXMNCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbiB0aGUgcm9vdCBvZiB0aGUgdHJlZS4NCiAgICAgKiBAcGFyYW0ge0pxTGl0ZX0gZWxlbWVudHNUb1JlbW92ZSBUaGUganFMaXRlIGVsZW1lbnQgd2hpY2ggd2UgYXJlIGdvaW5nIHRvIHJlcGxhY2UuIFdlIGtlZXANCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgc2hlbGwsIGJ1dCByZXBsYWNlIGl0cyBET00gbm9kZSByZWZlcmVuY2UuDQogICAgICogQHBhcmFtIHtOb2RlfSBuZXdOb2RlIFRoZSBuZXcgRE9NIG5vZGUuDQogICAgICovDQogICAgZnVuY3Rpb24gcmVwbGFjZVdpdGgoJHJvb3RFbGVtZW50LCBlbGVtZW50c1RvUmVtb3ZlLCBuZXdOb2RlKSB7DQogICAgICB2YXIgZmlyc3RFbGVtZW50VG9SZW1vdmUgPSBlbGVtZW50c1RvUmVtb3ZlWzBdLA0KICAgICAgICAgIHJlbW92ZUNvdW50ID0gZWxlbWVudHNUb1JlbW92ZS5sZW5ndGgsDQogICAgICAgICAgcGFyZW50ID0gZmlyc3RFbGVtZW50VG9SZW1vdmUucGFyZW50Tm9kZSwNCiAgICAgICAgICBpLCBpaTsNCg0KICAgICAgaWYgKCRyb290RWxlbWVudCkgew0KICAgICAgICBmb3IgKGkgPSAwLCBpaSA9ICRyb290RWxlbWVudC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7DQogICAgICAgICAgaWYgKCRyb290RWxlbWVudFtpXSA9PSBmaXJzdEVsZW1lbnRUb1JlbW92ZSkgew0KICAgICAgICAgICAgJHJvb3RFbGVtZW50W2krK10gPSBuZXdOb2RlOw0KICAgICAgICAgICAgZm9yICh2YXIgaiA9IGksIGoyID0gaiArIHJlbW92ZUNvdW50IC0gMSwNCiAgICAgICAgICAgICAgICAgICAgIGpqID0gJHJvb3RFbGVtZW50Lmxlbmd0aDsNCiAgICAgICAgICAgICAgICAgaiA8IGpqOyBqKyssIGoyKyspIHsNCiAgICAgICAgICAgICAgaWYgKGoyIDwgamopIHsNCiAgICAgICAgICAgICAgICAkcm9vdEVsZW1lbnRbal0gPSAkcm9vdEVsZW1lbnRbajJdOw0KICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgIGRlbGV0ZSAkcm9vdEVsZW1lbnRbal07DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgICRyb290RWxlbWVudC5sZW5ndGggLT0gcmVtb3ZlQ291bnQgLSAxOw0KDQogICAgICAgICAgICAvLyBJZiB0aGUgcmVwbGFjZWQgZWxlbWVudCBpcyBhbHNvIHRoZSBqUXVlcnkgLmNvbnRleHQgdGhlbiByZXBsYWNlIGl0DQogICAgICAgICAgICAvLyAuY29udGV4dCBpcyBhIGRlcHJlY2F0ZWQgalF1ZXJ5IGFwaSwgc28gd2Ugc2hvdWxkIHNldCBpdCBvbmx5IHdoZW4galF1ZXJ5IHNldCBpdA0KICAgICAgICAgICAgLy8gaHR0cDovL2FwaS5qcXVlcnkuY29tL2NvbnRleHQvDQogICAgICAgICAgICBpZiAoJHJvb3RFbGVtZW50LmNvbnRleHQgPT09IGZpcnN0RWxlbWVudFRvUmVtb3ZlKSB7DQogICAgICAgICAgICAgICRyb290RWxlbWVudC5jb250ZXh0ID0gbmV3Tm9kZTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgfQ0KDQogICAgICBpZiAocGFyZW50KSB7DQogICAgICAgIHBhcmVudC5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZmlyc3RFbGVtZW50VG9SZW1vdmUpOw0KICAgICAgfQ0KDQogICAgICAvLyBUT0RPKHBlcmYpOiB3aGF0J3MgdGhpcyBkb2N1bWVudCBmcmFnbWVudCBmb3I/IGlzIGl0IG5lZWRlZD8gY2FuIHdlIGF0IGxlYXN0IHJldXNlIGl0Pw0KICAgICAgdmFyIGZyYWdtZW50ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpOw0KICAgICAgZnJhZ21lbnQuYXBwZW5kQ2hpbGQoZmlyc3RFbGVtZW50VG9SZW1vdmUpOw0KDQogICAgICAvLyBDb3B5IG92ZXIgdXNlciBkYXRhICh0aGF0IGluY2x1ZGVzIEFuZ3VsYXIncyAkc2NvcGUgZXRjLikuIERvbid0IGNvcHkgcHJpdmF0ZQ0KICAgICAgLy8gZGF0YSBoZXJlIGJlY2F1c2UgdGhlcmUncyBubyBwdWJsaWMgaW50ZXJmYWNlIGluIGpRdWVyeSB0byBkbyB0aGF0IGFuZCBjb3B5aW5nIG92ZXINCiAgICAgIC8vIGV2ZW50IGxpc3RlbmVycyAod2hpY2ggaXMgdGhlIG1haW4gdXNlIG9mIHByaXZhdGUgZGF0YSkgd291bGRuJ3Qgd29yayBhbnl3YXkuDQogICAgICBqcUxpdGUobmV3Tm9kZSkuZGF0YShqcUxpdGUoZmlyc3RFbGVtZW50VG9SZW1vdmUpLmRhdGEoKSk7DQoNCiAgICAgIC8vIFJlbW92ZSBkYXRhIG9mIHRoZSByZXBsYWNlZCBlbGVtZW50LiBXZSBjYW5ub3QganVzdCBjYWxsIC5yZW1vdmUoKQ0KICAgICAgLy8gb24gdGhlIGVsZW1lbnQgaXQgc2luY2UgdGhhdCB3b3VsZCBkZWFsbG9jYXRlIHNjb3BlIHRoYXQgaXMgbmVlZGVkDQogICAgICAvLyBmb3IgdGhlIG5ldyBub2RlLiBJbnN0ZWFkLCByZW1vdmUgdGhlIGRhdGEgIm1hbnVhbGx5Ii4NCiAgICAgIGlmICghalF1ZXJ5KSB7DQogICAgICAgIGRlbGV0ZSBqcUxpdGUuY2FjaGVbZmlyc3RFbGVtZW50VG9SZW1vdmVbanFMaXRlLmV4cGFuZG9dXTsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIC8vIGpRdWVyeSAyLnggZG9lc24ndCBleHBvc2UgdGhlIGRhdGEgc3RvcmFnZS4gVXNlIGpRdWVyeS5jbGVhbkRhdGEgdG8gY2xlYW4gdXAgYWZ0ZXINCiAgICAgICAgLy8gdGhlIHJlcGxhY2VkIGVsZW1lbnQuIFRoZSBjbGVhbkRhdGEgdmVyc2lvbiBtb25rZXktcGF0Y2hlZCBieSBBbmd1bGFyIHdvdWxkIGNhdXNlDQogICAgICAgIC8vIHRoZSBzY29wZSB0byBiZSB0cmFzaGVkIGFuZCB3ZSBkbyBuZWVkIHRoZSB2ZXJ5IHNhbWUgc2NvcGUgdG8gd29yayB3aXRoIHRoZSBuZXcNCiAgICAgICAgLy8gZWxlbWVudC4gSG93ZXZlciwgd2UgY2Fubm90IGp1c3QgY2FjaGUgdGhlIG5vbi1wYXRjaGVkIHZlcnNpb24gYW5kIHVzZSBpdCBoZXJlIGFzDQogICAgICAgIC8vIHRoYXQgd291bGQgYnJlYWsgaWYgYW5vdGhlciBsaWJyYXJ5IHBhdGNoZXMgdGhlIG1ldGhvZCBhZnRlciBBbmd1bGFyIGRvZXMgKG9uZQ0KICAgICAgICAvLyBleGFtcGxlIGlzIGpRdWVyeSBVSSkuIEluc3RlYWQsIHNldCBhIGZsYWcgaW5kaWNhdGluZyBzY29wZSBkZXN0cm95aW5nIHNob3VsZCBiZQ0KICAgICAgICAvLyBza2lwcGVkIHRoaXMgb25lIHRpbWUuDQogICAgICAgIHNraXBEZXN0cm95T25OZXh0SlF1ZXJ5Q2xlYW5EYXRhID0gdHJ1ZTsNCiAgICAgICAgalF1ZXJ5LmNsZWFuRGF0YShbZmlyc3RFbGVtZW50VG9SZW1vdmVdKTsNCiAgICAgIH0NCg0KICAgICAgZm9yICh2YXIgayA9IDEsIGtrID0gZWxlbWVudHNUb1JlbW92ZS5sZW5ndGg7IGsgPCBrazsgaysrKSB7DQogICAgICAgIHZhciBlbGVtZW50ID0gZWxlbWVudHNUb1JlbW92ZVtrXTsNCiAgICAgICAganFMaXRlKGVsZW1lbnQpLnJlbW92ZSgpOyAvLyBtdXN0IGRvIHRoaXMgd2F5IHRvIGNsZWFuIHVwIGV4cGFuZG8NCiAgICAgICAgZnJhZ21lbnQuYXBwZW5kQ2hpbGQoZWxlbWVudCk7DQogICAgICAgIGRlbGV0ZSBlbGVtZW50c1RvUmVtb3ZlW2tdOw0KICAgICAgfQ0KDQogICAgICBlbGVtZW50c1RvUmVtb3ZlWzBdID0gbmV3Tm9kZTsNCiAgICAgIGVsZW1lbnRzVG9SZW1vdmUubGVuZ3RoID0gMTsNCiAgICB9DQoNCg0KICAgIGZ1bmN0aW9uIGNsb25lQW5kQW5ub3RhdGVGbihmbiwgYW5ub3RhdGlvbikgew0KICAgICAgcmV0dXJuIGV4dGVuZChmdW5jdGlvbigpIHsgcmV0dXJuIGZuLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7IH0sIGZuLCBhbm5vdGF0aW9uKTsNCiAgICB9DQoNCg0KICAgIGZ1bmN0aW9uIGludm9rZUxpbmtGbihsaW5rRm4sIHNjb3BlLCAkZWxlbWVudCwgYXR0cnMsIGNvbnRyb2xsZXJzLCB0cmFuc2NsdWRlRm4pIHsNCiAgICAgIHRyeSB7DQogICAgICAgIGxpbmtGbihzY29wZSwgJGVsZW1lbnQsIGF0dHJzLCBjb250cm9sbGVycywgdHJhbnNjbHVkZUZuKTsNCiAgICAgIH0gY2F0Y2ggKGUpIHsNCiAgICAgICAgJGV4Y2VwdGlvbkhhbmRsZXIoZSwgc3RhcnRpbmdUYWcoJGVsZW1lbnQpKTsNCiAgICAgIH0NCiAgICB9DQogIH1dOw0KfQ0KDQp2YXIgUFJFRklYX1JFR0VYUCA9IC9eKCg/Onh8ZGF0YSlbXDpcLV9dKS9pOw0KLyoqDQogKiBDb252ZXJ0cyBhbGwgYWNjZXB0ZWQgZGlyZWN0aXZlcyBmb3JtYXQgaW50byBwcm9wZXIgZGlyZWN0aXZlIG5hbWUuDQogKiBAcGFyYW0gbmFtZSBOYW1lIHRvIG5vcm1hbGl6ZQ0KICovDQpmdW5jdGlvbiBkaXJlY3RpdmVOb3JtYWxpemUobmFtZSkgew0KICByZXR1cm4gY2FtZWxDYXNlKG5hbWUucmVwbGFjZShQUkVGSVhfUkVHRVhQLCAnJykpOw0KfQ0KDQovKioNCiAqIEBuZ2RvYyB0eXBlDQogKiBAbmFtZSAkY29tcGlsZS5kaXJlY3RpdmUuQXR0cmlidXRlcw0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogQSBzaGFyZWQgb2JqZWN0IGJldHdlZW4gZGlyZWN0aXZlIGNvbXBpbGUgLyBsaW5raW5nIGZ1bmN0aW9ucyB3aGljaCBjb250YWlucyBub3JtYWxpemVkIERPTQ0KICogZWxlbWVudCBhdHRyaWJ1dGVzLiBUaGUgdmFsdWVzIHJlZmxlY3QgY3VycmVudCBiaW5kaW5nIHN0YXRlIGB7eyB9fWAuIFRoZSBub3JtYWxpemF0aW9uIGlzDQogKiBuZWVkZWQgc2luY2UgYWxsIG9mIHRoZXNlIGFyZSB0cmVhdGVkIGFzIGVxdWl2YWxlbnQgaW4gQW5ndWxhcjoNCiAqDQogKiBgYGANCiAqICAgIDxzcGFuIG5nOmJpbmQ9ImEiIG5nLWJpbmQ9ImEiIGRhdGEtbmctYmluZD0iYSIgeC1uZy1iaW5kPSJhIj4NCiAqIGBgYA0KICovDQoNCi8qKg0KICogQG5nZG9jIHByb3BlcnR5DQogKiBAbmFtZSAkY29tcGlsZS5kaXJlY3RpdmUuQXR0cmlidXRlcyMkYXR0cg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogQSBtYXAgb2YgRE9NIGVsZW1lbnQgYXR0cmlidXRlIG5hbWVzIHRvIHRoZSBub3JtYWxpemVkIG5hbWUuIFRoaXMgaXMNCiAqIG5lZWRlZCB0byBkbyByZXZlcnNlIGxvb2t1cCBmcm9tIG5vcm1hbGl6ZWQgbmFtZSBiYWNrIHRvIGFjdHVhbCBuYW1lLg0KICovDQoNCg0KLyoqDQogKiBAbmdkb2MgbWV0aG9kDQogKiBAbmFtZSAkY29tcGlsZS5kaXJlY3RpdmUuQXR0cmlidXRlcyMkc2V0DQogKiBAa2luZCBmdW5jdGlvbg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogU2V0IERPTSBlbGVtZW50IGF0dHJpYnV0ZSB2YWx1ZS4NCiAqDQogKg0KICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgTm9ybWFsaXplZCBlbGVtZW50IGF0dHJpYnV0ZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBtb2RpZnkuIFRoZSBuYW1lIGlzDQogKiAgICAgICAgICByZXZlcnNlLXRyYW5zbGF0ZWQgdXNpbmcgdGhlIHtAbGluayBuZy4kY29tcGlsZS5kaXJlY3RpdmUuQXR0cmlidXRlcyMkYXR0ciAkYXR0cn0NCiAqICAgICAgICAgIHByb3BlcnR5IHRvIHRoZSBvcmlnaW5hbCBuYW1lLg0KICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIFZhbHVlIHRvIHNldCB0aGUgYXR0cmlidXRlIHRvLiBUaGUgdmFsdWUgY2FuIGJlIGFuIGludGVycG9sYXRlZCBzdHJpbmcuDQogKi8NCg0KDQoNCi8qKg0KICogQ2xvc3VyZSBjb21waWxlciB0eXBlIGluZm9ybWF0aW9uDQogKi8NCg0KZnVuY3Rpb24gbm9kZXNldExpbmtpbmdGbigNCiAgLyogYW5ndWxhci5TY29wZSAqLyBzY29wZSwNCiAgLyogTm9kZUxpc3QgKi8gbm9kZUxpc3QsDQogIC8qIEVsZW1lbnQgKi8gcm9vdEVsZW1lbnQsDQogIC8qIGZ1bmN0aW9uKEZ1bmN0aW9uKSAqLyBib3VuZFRyYW5zY2x1ZGVGbg0KKSB7fQ0KDQpmdW5jdGlvbiBkaXJlY3RpdmVMaW5raW5nRm4oDQogIC8qIG5vZGVzZXRMaW5raW5nRm4gKi8gbm9kZXNldExpbmtpbmdGbiwNCiAgLyogYW5ndWxhci5TY29wZSAqLyBzY29wZSwNCiAgLyogTm9kZSAqLyBub2RlLA0KICAvKiBFbGVtZW50ICovIHJvb3RFbGVtZW50LA0KICAvKiBmdW5jdGlvbihGdW5jdGlvbikgKi8gYm91bmRUcmFuc2NsdWRlRm4NCikge30NCg0KZnVuY3Rpb24gdG9rZW5EaWZmZXJlbmNlKHN0cjEsIHN0cjIpIHsNCiAgdmFyIHZhbHVlcyA9ICcnLA0KICAgICAgdG9rZW5zMSA9IHN0cjEuc3BsaXQoL1xzKy8pLA0KICAgICAgdG9rZW5zMiA9IHN0cjIuc3BsaXQoL1xzKy8pOw0KDQogIG91dGVyOg0KICBmb3IgKHZhciBpID0gMDsgaSA8IHRva2VuczEubGVuZ3RoOyBpKyspIHsNCiAgICB2YXIgdG9rZW4gPSB0b2tlbnMxW2ldOw0KICAgIGZvciAodmFyIGogPSAwOyBqIDwgdG9rZW5zMi5sZW5ndGg7IGorKykgew0KICAgICAgaWYgKHRva2VuID09IHRva2VuczJbal0pIGNvbnRpbnVlIG91dGVyOw0KICAgIH0NCiAgICB2YWx1ZXMgKz0gKHZhbHVlcy5sZW5ndGggPiAwID8gJyAnIDogJycpICsgdG9rZW47DQogIH0NCiAgcmV0dXJuIHZhbHVlczsNCn0NCg0KZnVuY3Rpb24gcmVtb3ZlQ29tbWVudHMoanFOb2Rlcykgew0KICBqcU5vZGVzID0ganFMaXRlKGpxTm9kZXMpOw0KICB2YXIgaSA9IGpxTm9kZXMubGVuZ3RoOw0KDQogIGlmIChpIDw9IDEpIHsNCiAgICByZXR1cm4ganFOb2RlczsNCiAgfQ0KDQogIHdoaWxlIChpLS0pIHsNCiAgICB2YXIgbm9kZSA9IGpxTm9kZXNbaV07DQogICAgaWYgKG5vZGUubm9kZVR5cGUgPT09IE5PREVfVFlQRV9DT01NRU5UKSB7DQogICAgICBzcGxpY2UuY2FsbChqcU5vZGVzLCBpLCAxKTsNCiAgICB9DQogIH0NCiAgcmV0dXJuIGpxTm9kZXM7DQp9DQoNCi8qKg0KICogQG5nZG9jIHByb3ZpZGVyDQogKiBAbmFtZSAkY29udHJvbGxlclByb3ZpZGVyDQogKiBAZGVzY3JpcHRpb24NCiAqIFRoZSB7QGxpbmsgbmcuJGNvbnRyb2xsZXIgJGNvbnRyb2xsZXIgc2VydmljZX0gaXMgdXNlZCBieSBBbmd1bGFyIHRvIGNyZWF0ZSBuZXcNCiAqIGNvbnRyb2xsZXJzLg0KICoNCiAqIFRoaXMgcHJvdmlkZXIgYWxsb3dzIGNvbnRyb2xsZXIgcmVnaXN0cmF0aW9uIHZpYSB0aGUNCiAqIHtAbGluayBuZy4kY29udHJvbGxlclByb3ZpZGVyI3JlZ2lzdGVyIHJlZ2lzdGVyfSBtZXRob2QuDQogKi8NCmZ1bmN0aW9uICRDb250cm9sbGVyUHJvdmlkZXIoKSB7DQogIHZhciBjb250cm9sbGVycyA9IHt9LA0KICAgICAgZ2xvYmFscyA9IGZhbHNlLA0KICAgICAgQ05UUkxfUkVHID0gL14oXFMrKShccythc1xzKyhcdyspKT8kLzsNCg0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lICRjb250cm9sbGVyUHJvdmlkZXIjcmVnaXN0ZXINCiAgICogQHBhcmFtIHtzdHJpbmd8T2JqZWN0fSBuYW1lIENvbnRyb2xsZXIgbmFtZSwgb3IgYW4gb2JqZWN0IG1hcCBvZiBjb250cm9sbGVycyB3aGVyZSB0aGUga2V5cyBhcmUNCiAgICogICAgdGhlIG5hbWVzIGFuZCB0aGUgdmFsdWVzIGFyZSB0aGUgY29uc3RydWN0b3JzLg0KICAgKiBAcGFyYW0ge0Z1bmN0aW9ufEFycmF5fSBjb25zdHJ1Y3RvciBDb250cm9sbGVyIGNvbnN0cnVjdG9yIGZuIChvcHRpb25hbGx5IGRlY29yYXRlZCB3aXRoIERJDQogICAqICAgIGFubm90YXRpb25zIGluIHRoZSBhcnJheSBub3RhdGlvbikuDQogICAqLw0KICB0aGlzLnJlZ2lzdGVyID0gZnVuY3Rpb24obmFtZSwgY29uc3RydWN0b3IpIHsNCiAgICBhc3NlcnROb3RIYXNPd25Qcm9wZXJ0eShuYW1lLCAnY29udHJvbGxlcicpOw0KICAgIGlmIChpc09iamVjdChuYW1lKSkgew0KICAgICAgZXh0ZW5kKGNvbnRyb2xsZXJzLCBuYW1lKTsNCiAgICB9IGVsc2Ugew0KICAgICAgY29udHJvbGxlcnNbbmFtZV0gPSBjb25zdHJ1Y3RvcjsNCiAgICB9DQogIH07DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgJGNvbnRyb2xsZXJQcm92aWRlciNhbGxvd0dsb2JhbHMNCiAgICogQGRlc2NyaXB0aW9uIElmIGNhbGxlZCwgYWxsb3dzIGAkY29udHJvbGxlcmAgdG8gZmluZCBjb250cm9sbGVyIGNvbnN0cnVjdG9ycyBvbiBgd2luZG93YA0KICAgKi8NCiAgdGhpcy5hbGxvd0dsb2JhbHMgPSBmdW5jdGlvbigpIHsNCiAgICBnbG9iYWxzID0gdHJ1ZTsNCiAgfTsNCg0KDQogIHRoaXMuJGdldCA9IFsnJGluamVjdG9yJywgJyR3aW5kb3cnLCBmdW5jdGlvbigkaW5qZWN0b3IsICR3aW5kb3cpIHsNCg0KICAgIC8qKg0KICAgICAqIEBuZ2RvYyBzZXJ2aWNlDQogICAgICogQG5hbWUgJGNvbnRyb2xsZXINCiAgICAgKiBAcmVxdWlyZXMgJGluamVjdG9yDQogICAgICoNCiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gY29uc3RydWN0b3IgSWYgY2FsbGVkIHdpdGggYSBmdW5jdGlvbiB0aGVuIGl0J3MgY29uc2lkZXJlZCB0byBiZSB0aGUNCiAgICAgKiAgICBjb250cm9sbGVyIGNvbnN0cnVjdG9yIGZ1bmN0aW9uLiBPdGhlcndpc2UgaXQncyBjb25zaWRlcmVkIHRvIGJlIGEgc3RyaW5nIHdoaWNoIGlzIHVzZWQNCiAgICAgKiAgICB0byByZXRyaWV2ZSB0aGUgY29udHJvbGxlciBjb25zdHJ1Y3RvciB1c2luZyB0aGUgZm9sbG93aW5nIHN0ZXBzOg0KICAgICAqDQogICAgICogICAgKiBjaGVjayBpZiBhIGNvbnRyb2xsZXIgd2l0aCBnaXZlbiBuYW1lIGlzIHJlZ2lzdGVyZWQgdmlhIGAkY29udHJvbGxlclByb3ZpZGVyYA0KICAgICAqICAgICogY2hlY2sgaWYgZXZhbHVhdGluZyB0aGUgc3RyaW5nIG9uIHRoZSBjdXJyZW50IHNjb3BlIHJldHVybnMgYSBjb25zdHJ1Y3Rvcg0KICAgICAqICAgICogaWYgJGNvbnRyb2xsZXJQcm92aWRlciNhbGxvd0dsb2JhbHMsIGNoZWNrIGB3aW5kb3dbY29uc3RydWN0b3JdYCBvbiB0aGUgZ2xvYmFsDQogICAgICogICAgICBgd2luZG93YCBvYmplY3QgKG5vdCByZWNvbW1lbmRlZCkNCiAgICAgKg0KICAgICAqICAgIFRoZSBzdHJpbmcgY2FuIHVzZSB0aGUgYGNvbnRyb2xsZXIgYXMgcHJvcGVydHlgIHN5bnRheCwgd2hlcmUgdGhlIGNvbnRyb2xsZXIgaW5zdGFuY2UgaXMgcHVibGlzaGVkDQogICAgICogICAgYXMgdGhlIHNwZWNpZmllZCBwcm9wZXJ0eSBvbiB0aGUgYHNjb3BlYDsgdGhlIGBzY29wZWAgbXVzdCBiZSBpbmplY3RlZCBpbnRvIGBsb2NhbHNgIHBhcmFtIGZvciB0aGlzDQogICAgICogICAgdG8gd29yayBjb3JyZWN0bHkuDQogICAgICoNCiAgICAgKiBAcGFyYW0ge09iamVjdH0gbG9jYWxzIEluamVjdGlvbiBsb2NhbHMgZm9yIENvbnRyb2xsZXIuDQogICAgICogQHJldHVybiB7T2JqZWN0fSBJbnN0YW5jZSBvZiBnaXZlbiBjb250cm9sbGVyLg0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogYCRjb250cm9sbGVyYCBzZXJ2aWNlIGlzIHJlc3BvbnNpYmxlIGZvciBpbnN0YW50aWF0aW5nIGNvbnRyb2xsZXJzLg0KICAgICAqDQogICAgICogSXQncyBqdXN0IGEgc2ltcGxlIGNhbGwgdG8ge0BsaW5rIGF1dG8uJGluamVjdG9yICRpbmplY3Rvcn0sIGJ1dCBleHRyYWN0ZWQgaW50bw0KICAgICAqIGEgc2VydmljZSwgc28gdGhhdCBvbmUgY2FuIG92ZXJyaWRlIHRoaXMgc2VydmljZSB3aXRoIFtCQyB2ZXJzaW9uXShodHRwczovL2dpc3QuZ2l0aHViLmNvbS8xNjQ5Nzg4KS4NCiAgICAgKi8NCiAgICByZXR1cm4gZnVuY3Rpb24oZXhwcmVzc2lvbiwgbG9jYWxzLCBsYXRlciwgaWRlbnQpIHsNCiAgICAgIC8vIFBSSVZBVEUgQVBJOg0KICAgICAgLy8gICBwYXJhbSBgbGF0ZXJgIC0tLSBpbmRpY2F0ZXMgdGhhdCB0aGUgY29udHJvbGxlcidzIGNvbnN0cnVjdG9yIGlzIGludm9rZWQgYXQgYSBsYXRlciB0aW1lLg0KICAgICAgLy8gICAgICAgICAgICAgICAgICAgICBJZiB0cnVlLCAkY29udHJvbGxlciB3aWxsIGFsbG9jYXRlIHRoZSBvYmplY3Qgd2l0aCB0aGUgY29ycmVjdA0KICAgICAgLy8gICAgICAgICAgICAgICAgICAgICBwcm90b3R5cGUgY2hhaW4sIGJ1dCB3aWxsIG5vdCBpbnZva2UgdGhlIGNvbnRyb2xsZXIgdW50aWwgYSByZXR1cm5lZA0KICAgICAgLy8gICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayBpcyBpbnZva2VkLg0KICAgICAgLy8gICBwYXJhbSBgaWRlbnRgIC0tLSBBbiBvcHRpb25hbCBsYWJlbCB3aGljaCBvdmVycmlkZXMgdGhlIGxhYmVsIHBhcnNlZCBmcm9tIHRoZSBjb250cm9sbGVyDQogICAgICAvLyAgICAgICAgICAgICAgICAgICAgIGV4cHJlc3Npb24sIGlmIGFueS4NCiAgICAgIHZhciBpbnN0YW5jZSwgbWF0Y2gsIGNvbnN0cnVjdG9yLCBpZGVudGlmaWVyOw0KICAgICAgbGF0ZXIgPSBsYXRlciA9PT0gdHJ1ZTsNCiAgICAgIGlmIChpZGVudCAmJiBpc1N0cmluZyhpZGVudCkpIHsNCiAgICAgICAgaWRlbnRpZmllciA9IGlkZW50Ow0KICAgICAgfQ0KDQogICAgICBpZiAoaXNTdHJpbmcoZXhwcmVzc2lvbikpIHsNCiAgICAgICAgbWF0Y2ggPSBleHByZXNzaW9uLm1hdGNoKENOVFJMX1JFRyksDQogICAgICAgIGNvbnN0cnVjdG9yID0gbWF0Y2hbMV0sDQogICAgICAgIGlkZW50aWZpZXIgPSBpZGVudGlmaWVyIHx8IG1hdGNoWzNdOw0KICAgICAgICBleHByZXNzaW9uID0gY29udHJvbGxlcnMuaGFzT3duUHJvcGVydHkoY29uc3RydWN0b3IpDQogICAgICAgICAgICA/IGNvbnRyb2xsZXJzW2NvbnN0cnVjdG9yXQ0KICAgICAgICAgICAgOiBnZXR0ZXIobG9jYWxzLiRzY29wZSwgY29uc3RydWN0b3IsIHRydWUpIHx8DQogICAgICAgICAgICAgICAgKGdsb2JhbHMgPyBnZXR0ZXIoJHdpbmRvdywgY29uc3RydWN0b3IsIHRydWUpIDogdW5kZWZpbmVkKTsNCg0KICAgICAgICBhc3NlcnRBcmdGbihleHByZXNzaW9uLCBjb25zdHJ1Y3RvciwgdHJ1ZSk7DQogICAgICB9DQoNCiAgICAgIGlmIChsYXRlcikgew0KICAgICAgICAvLyBJbnN0YW50aWF0ZSBjb250cm9sbGVyIGxhdGVyOg0KICAgICAgICAvLyBUaGlzIG1hY2hpbmVyeSBpcyB1c2VkIHRvIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiB0aGUgb2JqZWN0IGJlZm9yZSBjYWxsaW5nIHRoZQ0KICAgICAgICAvLyBjb250cm9sbGVyJ3MgY29uc3RydWN0b3IgaXRzZWxmLg0KICAgICAgICAvLw0KICAgICAgICAvLyBUaGlzIGFsbG93cyBwcm9wZXJ0aWVzIHRvIGJlIGFkZGVkIHRvIHRoZSBjb250cm9sbGVyIGJlZm9yZSB0aGUgY29uc3RydWN0b3IgaXMNCiAgICAgICAgLy8gaW52b2tlZC4gUHJpbWFyaWx5LCB0aGlzIGlzIHVzZWQgZm9yIGlzb2xhdGUgc2NvcGUgYmluZGluZ3MgaW4gJGNvbXBpbGUuDQogICAgICAgIC8vDQogICAgICAgIC8vIFRoaXMgZmVhdHVyZSBpcyBub3QgaW50ZW5kZWQgZm9yIHVzZSBieSBhcHBsaWNhdGlvbnMsIGFuZCBpcyB0aHVzIG5vdCBkb2N1bWVudGVkDQogICAgICAgIC8vIHB1YmxpY2x5Lg0KICAgICAgICAvLyBPYmplY3QgY3JlYXRpb246IGh0dHA6Ly9qc3BlcmYuY29tL2NyZWF0ZS1jb25zdHJ1Y3Rvci8yDQogICAgICAgIHZhciBjb250cm9sbGVyUHJvdG90eXBlID0gKGlzQXJyYXkoZXhwcmVzc2lvbikgPw0KICAgICAgICAgIGV4cHJlc3Npb25bZXhwcmVzc2lvbi5sZW5ndGggLSAxXSA6IGV4cHJlc3Npb24pLnByb3RvdHlwZTsNCiAgICAgICAgaW5zdGFuY2UgPSBPYmplY3QuY3JlYXRlKGNvbnRyb2xsZXJQcm90b3R5cGUpOw0KDQogICAgICAgIGlmIChpZGVudGlmaWVyKSB7DQogICAgICAgICAgYWRkSWRlbnRpZmllcihsb2NhbHMsIGlkZW50aWZpZXIsIGluc3RhbmNlLCBjb25zdHJ1Y3RvciB8fCBleHByZXNzaW9uLm5hbWUpOw0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuIGV4dGVuZChmdW5jdGlvbigpIHsNCiAgICAgICAgICAkaW5qZWN0b3IuaW52b2tlKGV4cHJlc3Npb24sIGluc3RhbmNlLCBsb2NhbHMsIGNvbnN0cnVjdG9yKTsNCiAgICAgICAgICByZXR1cm4gaW5zdGFuY2U7DQogICAgICAgIH0sIHsNCiAgICAgICAgICBpbnN0YW5jZTogaW5zdGFuY2UsDQogICAgICAgICAgaWRlbnRpZmllcjogaWRlbnRpZmllcg0KICAgICAgICB9KTsNCiAgICAgIH0NCg0KICAgICAgaW5zdGFuY2UgPSAkaW5qZWN0b3IuaW5zdGFudGlhdGUoZXhwcmVzc2lvbiwgbG9jYWxzLCBjb25zdHJ1Y3Rvcik7DQoNCiAgICAgIGlmIChpZGVudGlmaWVyKSB7DQogICAgICAgIGFkZElkZW50aWZpZXIobG9jYWxzLCBpZGVudGlmaWVyLCBpbnN0YW5jZSwgY29uc3RydWN0b3IgfHwgZXhwcmVzc2lvbi5uYW1lKTsNCiAgICAgIH0NCg0KICAgICAgcmV0dXJuIGluc3RhbmNlOw0KICAgIH07DQoNCiAgICBmdW5jdGlvbiBhZGRJZGVudGlmaWVyKGxvY2FscywgaWRlbnRpZmllciwgaW5zdGFuY2UsIG5hbWUpIHsNCiAgICAgIGlmICghKGxvY2FscyAmJiBpc09iamVjdChsb2NhbHMuJHNjb3BlKSkpIHsNCiAgICAgICAgdGhyb3cgbWluRXJyKCckY29udHJvbGxlcicpKCdub3NjcCcsDQogICAgICAgICAgIkNhbm5vdCBleHBvcnQgY29udHJvbGxlciAnezB9JyBhcyAnezF9JyEgTm8gJHNjb3BlIG9iamVjdCBwcm92aWRlZCB2aWEgYGxvY2Fsc2AuIiwNCiAgICAgICAgICBuYW1lLCBpZGVudGlmaWVyKTsNCiAgICAgIH0NCg0KICAgICAgbG9jYWxzLiRzY29wZVtpZGVudGlmaWVyXSA9IGluc3RhbmNlOw0KICAgIH0NCiAgfV07DQp9DQoNCi8qKg0KICogQG5nZG9jIHNlcnZpY2UNCiAqIEBuYW1lICRkb2N1bWVudA0KICogQHJlcXVpcmVzICR3aW5kb3cNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIEEge0BsaW5rIGFuZ3VsYXIuZWxlbWVudCBqUXVlcnkgb3IganFMaXRlfSB3cmFwcGVyIGZvciB0aGUgYnJvd3NlcidzIGB3aW5kb3cuZG9jdW1lbnRgIG9iamVjdC4NCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGUgbW9kdWxlPSJkb2N1bWVudEV4YW1wbGUiPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICAgIDxwPiRkb2N1bWVudCB0aXRsZTogPGIgbmctYmluZD0idGl0bGUiPjwvYj48L3A+DQogICAgICAgICA8cD53aW5kb3cuZG9jdW1lbnQgdGl0bGU6IDxiIG5nLWJpbmQ9IndpbmRvd1RpdGxlIj48L2I+PC9wPg0KICAgICAgIDwvZGl2Pg0KICAgICA8L2ZpbGU+DQogICAgIDxmaWxlIG5hbWU9InNjcmlwdC5qcyI+DQogICAgICAgYW5ndWxhci5tb2R1bGUoJ2RvY3VtZW50RXhhbXBsZScsIFtdKQ0KICAgICAgICAgLmNvbnRyb2xsZXIoJ0V4YW1wbGVDb250cm9sbGVyJywgWyckc2NvcGUnLCAnJGRvY3VtZW50JywgZnVuY3Rpb24oJHNjb3BlLCAkZG9jdW1lbnQpIHsNCiAgICAgICAgICAgJHNjb3BlLnRpdGxlID0gJGRvY3VtZW50WzBdLnRpdGxlOw0KICAgICAgICAgICAkc2NvcGUud2luZG93VGl0bGUgPSBhbmd1bGFyLmVsZW1lbnQod2luZG93LmRvY3VtZW50KVswXS50aXRsZTsNCiAgICAgICAgIH1dKTsNCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICovDQpmdW5jdGlvbiAkRG9jdW1lbnRQcm92aWRlcigpIHsNCiAgdGhpcy4kZ2V0ID0gWyckd2luZG93JywgZnVuY3Rpb24od2luZG93KSB7DQogICAgcmV0dXJuIGpxTGl0ZSh3aW5kb3cuZG9jdW1lbnQpOw0KICB9XTsNCn0NCg0KLyoqDQogKiBAbmdkb2Mgc2VydmljZQ0KICogQG5hbWUgJGV4Y2VwdGlvbkhhbmRsZXINCiAqIEByZXF1aXJlcyBuZy4kbG9nDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBBbnkgdW5jYXVnaHQgZXhjZXB0aW9uIGluIGFuZ3VsYXIgZXhwcmVzc2lvbnMgaXMgZGVsZWdhdGVkIHRvIHRoaXMgc2VydmljZS4NCiAqIFRoZSBkZWZhdWx0IGltcGxlbWVudGF0aW9uIHNpbXBseSBkZWxlZ2F0ZXMgdG8gYCRsb2cuZXJyb3JgIHdoaWNoIGxvZ3MgaXQgaW50bw0KICogdGhlIGJyb3dzZXIgY29uc29sZS4NCiAqDQogKiBJbiB1bml0IHRlc3RzLCBpZiBgYW5ndWxhci1tb2Nrcy5qc2AgaXMgbG9hZGVkLCB0aGlzIHNlcnZpY2UgaXMgb3ZlcnJpZGRlbiBieQ0KICoge0BsaW5rIG5nTW9jay4kZXhjZXB0aW9uSGFuZGxlciBtb2NrICRleGNlcHRpb25IYW5kbGVyfSB3aGljaCBhaWRzIGluIHRlc3RpbmcuDQogKg0KICogIyMgRXhhbXBsZToNCiAqDQogKiBgYGBqcw0KICogICBhbmd1bGFyLm1vZHVsZSgnZXhjZXB0aW9uT3ZlcnJpZGUnLCBbXSkuZmFjdG9yeSgnJGV4Y2VwdGlvbkhhbmRsZXInLCBmdW5jdGlvbigpIHsNCiAqICAgICByZXR1cm4gZnVuY3Rpb24oZXhjZXB0aW9uLCBjYXVzZSkgew0KICogICAgICAgZXhjZXB0aW9uLm1lc3NhZ2UgKz0gJyAoY2F1c2VkIGJ5ICInICsgY2F1c2UgKyAnIiknOw0KICogICAgICAgdGhyb3cgZXhjZXB0aW9uOw0KICogICAgIH07DQogKiAgIH0pOw0KICogYGBgDQogKg0KICogVGhpcyBleGFtcGxlIHdpbGwgb3ZlcnJpZGUgdGhlIG5vcm1hbCBhY3Rpb24gb2YgYCRleGNlcHRpb25IYW5kbGVyYCwgdG8gbWFrZSBhbmd1bGFyDQogKiBleGNlcHRpb25zIGZhaWwgaGFyZCB3aGVuIHRoZXkgaGFwcGVuLCBpbnN0ZWFkIG9mIGp1c3QgbG9nZ2luZyB0byB0aGUgY29uc29sZS4NCiAqDQogKiA8aHIgLz4NCiAqIE5vdGUsIHRoYXQgY29kZSBleGVjdXRlZCBpbiBldmVudC1saXN0ZW5lcnMgKGV2ZW4gdGhvc2UgcmVnaXN0ZXJlZCB1c2luZyBqcUxpdGUncyBgb25gL2BiaW5kYA0KICogbWV0aG9kcykgZG9lcyBub3QgZGVsZWdhdGUgZXhjZXB0aW9ucyB0byB0aGUge0BsaW5rIG5nLiRleGNlcHRpb25IYW5kbGVyICRleGNlcHRpb25IYW5kbGVyfQ0KICogKHVubGVzcyBleGVjdXRlZCBkdXJpbmcgYSBkaWdlc3QpLg0KICoNCiAqIElmIHlvdSB3aXNoLCB5b3UgY2FuIG1hbnVhbGx5IGRlbGVnYXRlIGV4Y2VwdGlvbnMsIGUuZy4NCiAqIGB0cnkgeyAuLi4gfSBjYXRjaChlKSB7ICRleGNlcHRpb25IYW5kbGVyKGUpOyB9YA0KICoNCiAqIEBwYXJhbSB7RXJyb3J9IGV4Y2VwdGlvbiBFeGNlcHRpb24gYXNzb2NpYXRlZCB3aXRoIHRoZSBlcnJvci4NCiAqIEBwYXJhbSB7c3RyaW5nPX0gY2F1c2Ugb3B0aW9uYWwgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGNvbnRleHQgaW4gd2hpY2gNCiAqICAgICAgIHRoZSBlcnJvciB3YXMgdGhyb3duLg0KICoNCiAqLw0KZnVuY3Rpb24gJEV4Y2VwdGlvbkhhbmRsZXJQcm92aWRlcigpIHsNCiAgdGhpcy4kZ2V0ID0gWyckbG9nJywgZnVuY3Rpb24oJGxvZykgew0KICAgIHJldHVybiBmdW5jdGlvbihleGNlcHRpb24sIGNhdXNlKSB7DQogICAgICAkbG9nLmVycm9yLmFwcGx5KCRsb2csIGFyZ3VtZW50cyk7DQogICAgfTsNCiAgfV07DQp9DQoNCnZhciBBUFBMSUNBVElPTl9KU09OID0gJ2FwcGxpY2F0aW9uL2pzb24nOw0KdmFyIENPTlRFTlRfVFlQRV9BUFBMSUNBVElPTl9KU09OID0geydDb250ZW50LVR5cGUnOiBBUFBMSUNBVElPTl9KU09OICsgJztjaGFyc2V0PXV0Zi04J307DQp2YXIgSlNPTl9TVEFSVCA9IC9eXFt8Xlx7KD8hXHspLzsNCnZhciBKU09OX0VORFMgPSB7DQogICdbJzogL10kLywNCiAgJ3snOiAvfSQvDQp9Ow0KdmFyIEpTT05fUFJPVEVDVElPTl9QUkVGSVggPSAvXlwpXF1cfScsP1xuLzsNCg0KZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXNwb25zZVRyYW5zZm9ybShkYXRhLCBoZWFkZXJzKSB7DQogIGlmIChpc1N0cmluZyhkYXRhKSkgew0KICAgIC8vIFN0cmlwIGpzb24gdnVsbmVyYWJpbGl0eSBwcm90ZWN0aW9uIHByZWZpeCBhbmQgdHJpbSB3aGl0ZXNwYWNlDQogICAgdmFyIHRlbXBEYXRhID0gZGF0YS5yZXBsYWNlKEpTT05fUFJPVEVDVElPTl9QUkVGSVgsICcnKS50cmltKCk7DQoNCiAgICBpZiAodGVtcERhdGEpIHsNCiAgICAgIHZhciBjb250ZW50VHlwZSA9IGhlYWRlcnMoJ0NvbnRlbnQtVHlwZScpOw0KICAgICAgaWYgKChjb250ZW50VHlwZSAmJiAoY29udGVudFR5cGUuaW5kZXhPZihBUFBMSUNBVElPTl9KU09OKSA9PT0gMCkpIHx8IGlzSnNvbkxpa2UodGVtcERhdGEpKSB7DQogICAgICAgIGRhdGEgPSBmcm9tSnNvbih0ZW1wRGF0YSk7DQogICAgICB9DQogICAgfQ0KICB9DQoNCiAgcmV0dXJuIGRhdGE7DQp9DQoNCmZ1bmN0aW9uIGlzSnNvbkxpa2Uoc3RyKSB7DQogICAgdmFyIGpzb25TdGFydCA9IHN0ci5tYXRjaChKU09OX1NUQVJUKTsNCiAgICByZXR1cm4ganNvblN0YXJ0ICYmIEpTT05fRU5EU1tqc29uU3RhcnRbMF1dLnRlc3Qoc3RyKTsNCn0NCg0KLyoqDQogKiBQYXJzZSBoZWFkZXJzIGludG8ga2V5IHZhbHVlIG9iamVjdA0KICoNCiAqIEBwYXJhbSB7c3RyaW5nfSBoZWFkZXJzIFJhdyBoZWFkZXJzIGFzIGEgc3RyaW5nDQogKiBAcmV0dXJucyB7T2JqZWN0fSBQYXJzZWQgaGVhZGVycyBhcyBrZXkgdmFsdWUgb2JqZWN0DQogKi8NCmZ1bmN0aW9uIHBhcnNlSGVhZGVycyhoZWFkZXJzKSB7DQogIHZhciBwYXJzZWQgPSBjcmVhdGVNYXAoKSwga2V5LCB2YWwsIGk7DQoNCiAgaWYgKCFoZWFkZXJzKSByZXR1cm4gcGFyc2VkOw0KDQogIGZvckVhY2goaGVhZGVycy5zcGxpdCgnXG4nKSwgZnVuY3Rpb24obGluZSkgew0KICAgIGkgPSBsaW5lLmluZGV4T2YoJzonKTsNCiAgICBrZXkgPSBsb3dlcmNhc2UodHJpbShsaW5lLnN1YnN0cigwLCBpKSkpOw0KICAgIHZhbCA9IHRyaW0obGluZS5zdWJzdHIoaSArIDEpKTsNCg0KICAgIGlmIChrZXkpIHsNCiAgICAgIHBhcnNlZFtrZXldID0gcGFyc2VkW2tleV0gPyBwYXJzZWRba2V5XSArICcsICcgKyB2YWwgOiB2YWw7DQogICAgfQ0KICB9KTsNCg0KICByZXR1cm4gcGFyc2VkOw0KfQ0KDQoNCi8qKg0KICogUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgcHJvdmlkZXMgYWNjZXNzIHRvIHBhcnNlZCBoZWFkZXJzLg0KICoNCiAqIEhlYWRlcnMgYXJlIGxhenkgcGFyc2VkIHdoZW4gZmlyc3QgcmVxdWVzdGVkLg0KICogQHNlZSBwYXJzZUhlYWRlcnMNCiAqDQogKiBAcGFyYW0geyhzdHJpbmd8T2JqZWN0KX0gaGVhZGVycyBIZWFkZXJzIHRvIHByb3ZpZGUgYWNjZXNzIHRvLg0KICogQHJldHVybnMge2Z1bmN0aW9uKHN0cmluZz0pfSBSZXR1cm5zIGEgZ2V0dGVyIGZ1bmN0aW9uIHdoaWNoIGlmIGNhbGxlZCB3aXRoOg0KICoNCiAqICAgLSBpZiBjYWxsZWQgd2l0aCBzaW5nbGUgYW4gYXJndW1lbnQgcmV0dXJucyBhIHNpbmdsZSBoZWFkZXIgdmFsdWUgb3IgbnVsbA0KICogICAtIGlmIGNhbGxlZCB3aXRoIG5vIGFyZ3VtZW50cyByZXR1cm5zIGFuIG9iamVjdCBjb250YWluaW5nIGFsbCBoZWFkZXJzLg0KICovDQpmdW5jdGlvbiBoZWFkZXJzR2V0dGVyKGhlYWRlcnMpIHsNCiAgdmFyIGhlYWRlcnNPYmogPSBpc09iamVjdChoZWFkZXJzKSA/IGhlYWRlcnMgOiB1bmRlZmluZWQ7DQoNCiAgcmV0dXJuIGZ1bmN0aW9uKG5hbWUpIHsNCiAgICBpZiAoIWhlYWRlcnNPYmopIGhlYWRlcnNPYmogPSAgcGFyc2VIZWFkZXJzKGhlYWRlcnMpOw0KDQogICAgaWYgKG5hbWUpIHsNCiAgICAgIHZhciB2YWx1ZSA9IGhlYWRlcnNPYmpbbG93ZXJjYXNlKG5hbWUpXTsNCiAgICAgIGlmICh2YWx1ZSA9PT0gdm9pZCAwKSB7DQogICAgICAgIHZhbHVlID0gbnVsbDsNCiAgICAgIH0NCiAgICAgIHJldHVybiB2YWx1ZTsNCiAgICB9DQoNCiAgICByZXR1cm4gaGVhZGVyc09iajsNCiAgfTsNCn0NCg0KDQovKioNCiAqIENoYWluIGFsbCBnaXZlbiBmdW5jdGlvbnMNCiAqDQogKiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgZm9yIGJvdGggcmVxdWVzdCBhbmQgcmVzcG9uc2UgdHJhbnNmb3JtaW5nDQogKg0KICogQHBhcmFtIHsqfSBkYXRhIERhdGEgdG8gdHJhbnNmb3JtLg0KICogQHBhcmFtIHtmdW5jdGlvbihzdHJpbmc9KX0gaGVhZGVycyBIVFRQIGhlYWRlcnMgZ2V0dGVyIGZuLg0KICogQHBhcmFtIHtudW1iZXJ9IHN0YXR1cyBIVFRQIHN0YXR1cyBjb2RlIG9mIHRoZSByZXNwb25zZS4NCiAqIEBwYXJhbSB7KEZ1bmN0aW9ufEFycmF5LjxGdW5jdGlvbj4pfSBmbnMgRnVuY3Rpb24gb3IgYW4gYXJyYXkgb2YgZnVuY3Rpb25zLg0KICogQHJldHVybnMgeyp9IFRyYW5zZm9ybWVkIGRhdGEuDQogKi8NCmZ1bmN0aW9uIHRyYW5zZm9ybURhdGEoZGF0YSwgaGVhZGVycywgc3RhdHVzLCBmbnMpIHsNCiAgaWYgKGlzRnVuY3Rpb24oZm5zKSkNCiAgICByZXR1cm4gZm5zKGRhdGEsIGhlYWRlcnMsIHN0YXR1cyk7DQoNCiAgZm9yRWFjaChmbnMsIGZ1bmN0aW9uKGZuKSB7DQogICAgZGF0YSA9IGZuKGRhdGEsIGhlYWRlcnMsIHN0YXR1cyk7DQogIH0pOw0KDQogIHJldHVybiBkYXRhOw0KfQ0KDQoNCmZ1bmN0aW9uIGlzU3VjY2VzcyhzdGF0dXMpIHsNCiAgcmV0dXJuIDIwMCA8PSBzdGF0dXMgJiYgc3RhdHVzIDwgMzAwOw0KfQ0KDQoNCi8qKg0KICogQG5nZG9jIHByb3ZpZGVyDQogKiBAbmFtZSAkaHR0cFByb3ZpZGVyDQogKiBAZGVzY3JpcHRpb24NCiAqIFVzZSBgJGh0dHBQcm92aWRlcmAgdG8gY2hhbmdlIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIHRoZSB7QGxpbmsgbmcuJGh0dHAgJGh0dHB9IHNlcnZpY2UuDQogKiAqLw0KZnVuY3Rpb24gJEh0dHBQcm92aWRlcigpIHsNCiAgLyoqDQogICAqIEBuZ2RvYyBwcm9wZXJ0eQ0KICAgKiBAbmFtZSAkaHR0cFByb3ZpZGVyI2RlZmF1bHRzDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKg0KICAgKiBPYmplY3QgY29udGFpbmluZyBkZWZhdWx0IHZhbHVlcyBmb3IgYWxsIHtAbGluayBuZy4kaHR0cCAkaHR0cH0gcmVxdWVzdHMuDQogICAqDQogICAqIC0gKipgZGVmYXVsdHMuY2FjaGVgKiogLSB7T2JqZWN0fSAtIGFuIG9iamVjdCBidWlsdCB3aXRoIHtAbGluayBuZy4kY2FjaGVGYWN0b3J5IGAkY2FjaGVGYWN0b3J5YH0NCiAgICogdGhhdCB3aWxsIHByb3ZpZGUgdGhlIGNhY2hlIGZvciBhbGwgcmVxdWVzdHMgd2hvIHNldCB0aGVpciBgY2FjaGVgIHByb3BlcnR5IHRvIGB0cnVlYC4NCiAgICogSWYgeW91IHNldCB0aGUgYGRlZmF1bHQuY2FjaGUgPSBmYWxzZWAgdGhlbiBvbmx5IHJlcXVlc3RzIHRoYXQgc3BlY2lmeSB0aGVpciBvd24gY3VzdG9tDQogICAqIGNhY2hlIG9iamVjdCB3aWxsIGJlIGNhY2hlZC4gU2VlIHtAbGluayAkaHR0cCNjYWNoaW5nICRodHRwIENhY2hpbmd9IGZvciBtb3JlIGluZm9ybWF0aW9uLg0KICAgKg0KICAgKiAtICoqYGRlZmF1bHRzLnhzcmZDb29raWVOYW1lYCoqIC0ge3N0cmluZ30gLSBOYW1lIG9mIGNvb2tpZSBjb250YWluaW5nIHRoZSBYU1JGIHRva2VuLg0KICAgKiBEZWZhdWx0cyB2YWx1ZSBpcyBgJ1hTUkYtVE9LRU4nYC4NCiAgICoNCiAgICogLSAqKmBkZWZhdWx0cy54c3JmSGVhZGVyTmFtZWAqKiAtIHtzdHJpbmd9IC0gTmFtZSBvZiBIVFRQIGhlYWRlciB0byBwb3B1bGF0ZSB3aXRoIHRoZQ0KICAgKiBYU1JGIHRva2VuLiBEZWZhdWx0cyB2YWx1ZSBpcyBgJ1gtWFNSRi1UT0tFTidgLg0KICAgKg0KICAgKiAtICoqYGRlZmF1bHRzLmhlYWRlcnNgKiogLSB7T2JqZWN0fSAtIERlZmF1bHQgaGVhZGVycyBmb3IgYWxsICRodHRwIHJlcXVlc3RzLg0KICAgKiBSZWZlciB0byB7QGxpbmsgbmcuJGh0dHAjc2V0dGluZy1odHRwLWhlYWRlcnMgJGh0dHB9IGZvciBkb2N1bWVudGF0aW9uIG9uDQogICAqIHNldHRpbmcgZGVmYXVsdCBoZWFkZXJzLg0KICAgKiAgICAgLSAqKmBkZWZhdWx0cy5oZWFkZXJzLmNvbW1vbmAqKg0KICAgKiAgICAgLSAqKmBkZWZhdWx0cy5oZWFkZXJzLnBvc3RgKioNCiAgICogICAgIC0gKipgZGVmYXVsdHMuaGVhZGVycy5wdXRgKioNCiAgICogICAgIC0gKipgZGVmYXVsdHMuaGVhZGVycy5wYXRjaGAqKg0KICAgKg0KICAgKiovDQogIHZhciBkZWZhdWx0cyA9IHRoaXMuZGVmYXVsdHMgPSB7DQogICAgLy8gdHJhbnNmb3JtIGluY29taW5nIHJlc3BvbnNlIGRhdGENCiAgICB0cmFuc2Zvcm1SZXNwb25zZTogW2RlZmF1bHRIdHRwUmVzcG9uc2VUcmFuc2Zvcm1dLA0KDQogICAgLy8gdHJhbnNmb3JtIG91dGdvaW5nIHJlcXVlc3QgZGF0YQ0KICAgIHRyYW5zZm9ybVJlcXVlc3Q6IFtmdW5jdGlvbihkKSB7DQogICAgICByZXR1cm4gaXNPYmplY3QoZCkgJiYgIWlzRmlsZShkKSAmJiAhaXNCbG9iKGQpICYmICFpc0Zvcm1EYXRhKGQpID8gdG9Kc29uKGQpIDogZDsNCiAgICB9XSwNCg0KICAgIC8vIGRlZmF1bHQgaGVhZGVycw0KICAgIGhlYWRlcnM6IHsNCiAgICAgIGNvbW1vbjogew0KICAgICAgICAnQWNjZXB0JzogJ2FwcGxpY2F0aW9uL2pzb24sIHRleHQvcGxhaW4sICovKicNCiAgICAgIH0sDQogICAgICBwb3N0OiAgIHNoYWxsb3dDb3B5KENPTlRFTlRfVFlQRV9BUFBMSUNBVElPTl9KU09OKSwNCiAgICAgIHB1dDogICAgc2hhbGxvd0NvcHkoQ09OVEVOVF9UWVBFX0FQUExJQ0FUSU9OX0pTT04pLA0KICAgICAgcGF0Y2g6ICBzaGFsbG93Q29weShDT05URU5UX1RZUEVfQVBQTElDQVRJT05fSlNPTikNCiAgICB9LA0KDQogICAgeHNyZkNvb2tpZU5hbWU6ICdYU1JGLVRPS0VOJywNCiAgICB4c3JmSGVhZGVyTmFtZTogJ1gtWFNSRi1UT0tFTicNCiAgfTsNCg0KICB2YXIgdXNlQXBwbHlBc3luYyA9IGZhbHNlOw0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkaHR0cFByb3ZpZGVyI3VzZUFwcGx5QXN5bmMNCiAgICogQGRlc2NyaXB0aW9uDQogICAqDQogICAqIENvbmZpZ3VyZSAkaHR0cCBzZXJ2aWNlIHRvIGNvbWJpbmUgcHJvY2Vzc2luZyBvZiBtdWx0aXBsZSBodHRwIHJlc3BvbnNlcyByZWNlaXZlZCBhdCBhcm91bmQNCiAgICogdGhlIHNhbWUgdGltZSB2aWEge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJGFwcGx5QXN5bmMgJHJvb3RTY29wZS4kYXBwbHlBc3luY30uIFRoaXMgY2FuIHJlc3VsdCBpbg0KICAgKiBzaWduaWZpY2FudCBwZXJmb3JtYW5jZSBpbXByb3ZlbWVudCBmb3IgYmlnZ2VyIGFwcGxpY2F0aW9ucyB0aGF0IG1ha2UgbWFueSBIVFRQIHJlcXVlc3RzDQogICAqIGNvbmN1cnJlbnRseSAoY29tbW9uIGR1cmluZyBhcHBsaWNhdGlvbiBib290c3RyYXApLg0KICAgKg0KICAgKiBEZWZhdWx0cyB0byBmYWxzZS4gSWYgbm8gdmFsdWUgaXMgc3BlY2lmZWQsIHJldHVybnMgdGhlIGN1cnJlbnQgY29uZmlndXJlZCB2YWx1ZS4NCiAgICoNCiAgICogQHBhcmFtIHtib29sZWFuPX0gdmFsdWUgSWYgdHJ1ZSwgd2hlbiByZXF1ZXN0cyBhcmUgbG9hZGVkLCB0aGV5IHdpbGwgc2NoZWR1bGUgYSBkZWZlcnJlZA0KICAgKiAgICAiYXBwbHkiIG9uIHRoZSBuZXh0IHRpY2ssIGdpdmluZyB0aW1lIGZvciBzdWJzZXF1ZW50IHJlcXVlc3RzIGluIGEgcm91Z2hseSB+MTBtcyB3aW5kb3cNCiAgICogICAgdG8gbG9hZCBhbmQgc2hhcmUgdGhlIHNhbWUgZGlnZXN0IGN5Y2xlLg0KICAgKg0KICAgKiBAcmV0dXJucyB7Ym9vbGVhbnxPYmplY3R9IElmIGEgdmFsdWUgaXMgc3BlY2lmaWVkLCByZXR1cm5zIHRoZSAkaHR0cFByb3ZpZGVyIGZvciBjaGFpbmluZy4NCiAgICogICAgb3RoZXJ3aXNlLCByZXR1cm5zIHRoZSBjdXJyZW50IGNvbmZpZ3VyZWQgdmFsdWUuDQogICAqKi8NCiAgdGhpcy51c2VBcHBseUFzeW5jID0gZnVuY3Rpb24odmFsdWUpIHsNCiAgICBpZiAoaXNEZWZpbmVkKHZhbHVlKSkgew0KICAgICAgdXNlQXBwbHlBc3luYyA9ICEhdmFsdWU7DQogICAgICByZXR1cm4gdGhpczsNCiAgICB9DQogICAgcmV0dXJuIHVzZUFwcGx5QXN5bmM7DQogIH07DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBwcm9wZXJ0eQ0KICAgKiBAbmFtZSAkaHR0cFByb3ZpZGVyI2ludGVyY2VwdG9ycw0KICAgKiBAZGVzY3JpcHRpb24NCiAgICoNCiAgICogQXJyYXkgY29udGFpbmluZyBzZXJ2aWNlIGZhY3RvcmllcyBmb3IgYWxsIHN5bmNocm9ub3VzIG9yIGFzeW5jaHJvbm91cyB7QGxpbmsgbmcuJGh0dHAgJGh0dHB9DQogICAqIHByZS1wcm9jZXNzaW5nIG9mIHJlcXVlc3Qgb3IgcG9zdHByb2Nlc3Npbmcgb2YgcmVzcG9uc2VzLg0KICAgKg0KICAgKiBUaGVzZSBzZXJ2aWNlIGZhY3RvcmllcyBhcmUgb3JkZXJlZCBieSByZXF1ZXN0LCBpLmUuIHRoZXkgYXJlIGFwcGxpZWQgaW4gdGhlIHNhbWUgb3JkZXIgYXMgdGhlDQogICAqIGFycmF5LCBvbiByZXF1ZXN0LCBidXQgcmV2ZXJzZSBvcmRlciwgb24gcmVzcG9uc2UuDQogICAqDQogICAqIHtAbGluayBuZy4kaHR0cCNpbnRlcmNlcHRvcnMgSW50ZXJjZXB0b3JzIGRldGFpbGVkIGluZm99DQogICAqKi8NCiAgdmFyIGludGVyY2VwdG9yRmFjdG9yaWVzID0gdGhpcy5pbnRlcmNlcHRvcnMgPSBbXTsNCg0KICB0aGlzLiRnZXQgPSBbJyRodHRwQmFja2VuZCcsICckYnJvd3NlcicsICckY2FjaGVGYWN0b3J5JywgJyRyb290U2NvcGUnLCAnJHEnLCAnJGluamVjdG9yJywNCiAgICAgIGZ1bmN0aW9uKCRodHRwQmFja2VuZCwgJGJyb3dzZXIsICRjYWNoZUZhY3RvcnksICRyb290U2NvcGUsICRxLCAkaW5qZWN0b3IpIHsNCg0KICAgIHZhciBkZWZhdWx0Q2FjaGUgPSAkY2FjaGVGYWN0b3J5KCckaHR0cCcpOw0KDQogICAgLyoqDQogICAgICogSW50ZXJjZXB0b3JzIHN0b3JlZCBpbiByZXZlcnNlIG9yZGVyLiBJbm5lciBpbnRlcmNlcHRvcnMgYmVmb3JlIG91dGVyIGludGVyY2VwdG9ycy4NCiAgICAgKiBUaGUgcmV2ZXJzYWwgaXMgbmVlZGVkIHNvIHRoYXQgd2UgY2FuIGJ1aWxkIHVwIHRoZSBpbnRlcmNlcHRpb24gY2hhaW4gYXJvdW5kIHRoZQ0KICAgICAqIHNlcnZlciByZXF1ZXN0Lg0KICAgICAqLw0KICAgIHZhciByZXZlcnNlZEludGVyY2VwdG9ycyA9IFtdOw0KDQogICAgZm9yRWFjaChpbnRlcmNlcHRvckZhY3RvcmllcywgZnVuY3Rpb24oaW50ZXJjZXB0b3JGYWN0b3J5KSB7DQogICAgICByZXZlcnNlZEludGVyY2VwdG9ycy51bnNoaWZ0KGlzU3RyaW5nKGludGVyY2VwdG9yRmFjdG9yeSkNCiAgICAgICAgICA/ICRpbmplY3Rvci5nZXQoaW50ZXJjZXB0b3JGYWN0b3J5KSA6ICRpbmplY3Rvci5pbnZva2UoaW50ZXJjZXB0b3JGYWN0b3J5KSk7DQogICAgfSk7DQoNCiAgICAvKioNCiAgICAgKiBAbmdkb2Mgc2VydmljZQ0KICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICogQG5hbWUgJGh0dHANCiAgICAgKiBAcmVxdWlyZXMgbmcuJGh0dHBCYWNrZW5kDQogICAgICogQHJlcXVpcmVzICRjYWNoZUZhY3RvcnkNCiAgICAgKiBAcmVxdWlyZXMgJHJvb3RTY29wZQ0KICAgICAqIEByZXF1aXJlcyAkcQ0KICAgICAqIEByZXF1aXJlcyAkaW5qZWN0b3INCiAgICAgKg0KICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAqIFRoZSBgJGh0dHBgIHNlcnZpY2UgaXMgYSBjb3JlIEFuZ3VsYXIgc2VydmljZSB0aGF0IGZhY2lsaXRhdGVzIGNvbW11bmljYXRpb24gd2l0aCB0aGUgcmVtb3RlDQogICAgICogSFRUUCBzZXJ2ZXJzIHZpYSB0aGUgYnJvd3NlcidzIFtYTUxIdHRwUmVxdWVzdF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4veG1saHR0cHJlcXVlc3QpDQogICAgICogb2JqZWN0IG9yIHZpYSBbSlNPTlBdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSlNPTlApLg0KICAgICAqDQogICAgICogRm9yIHVuaXQgdGVzdGluZyBhcHBsaWNhdGlvbnMgdGhhdCB1c2UgYCRodHRwYCBzZXJ2aWNlLCBzZWUNCiAgICAgKiB7QGxpbmsgbmdNb2NrLiRodHRwQmFja2VuZCAkaHR0cEJhY2tlbmQgbW9ja30uDQogICAgICoNCiAgICAgKiBGb3IgYSBoaWdoZXIgbGV2ZWwgb2YgYWJzdHJhY3Rpb24sIHBsZWFzZSBjaGVjayBvdXQgdGhlIHtAbGluayBuZ1Jlc291cmNlLiRyZXNvdXJjZQ0KICAgICAqICRyZXNvdXJjZX0gc2VydmljZS4NCiAgICAgKg0KICAgICAqIFRoZSAkaHR0cCBBUEkgaXMgYmFzZWQgb24gdGhlIHtAbGluayBuZy4kcSBkZWZlcnJlZC9wcm9taXNlIEFQSXN9IGV4cG9zZWQgYnkNCiAgICAgKiB0aGUgJHEgc2VydmljZS4gV2hpbGUgZm9yIHNpbXBsZSB1c2FnZSBwYXR0ZXJucyB0aGlzIGRvZXNuJ3QgbWF0dGVyIG11Y2gsIGZvciBhZHZhbmNlZCB1c2FnZQ0KICAgICAqIGl0IGlzIGltcG9ydGFudCB0byBmYW1pbGlhcml6ZSB5b3Vyc2VsZiB3aXRoIHRoZXNlIEFQSXMgYW5kIHRoZSBndWFyYW50ZWVzIHRoZXkgcHJvdmlkZS4NCiAgICAgKg0KICAgICAqDQogICAgICogIyMgR2VuZXJhbCB1c2FnZQ0KICAgICAqIFRoZSBgJGh0dHBgIHNlcnZpY2UgaXMgYSBmdW5jdGlvbiB3aGljaCB0YWtlcyBhIHNpbmdsZSBhcmd1bWVudCDigD8gYSBjb25maWd1cmF0aW9uIG9iamVjdCDigD8NCiAgICAgKiB0aGF0IGlzIHVzZWQgdG8gZ2VuZXJhdGUgYW4gSFRUUCByZXF1ZXN0IGFuZCByZXR1cm5zICBhIHtAbGluayBuZy4kcSBwcm9taXNlfQ0KICAgICAqIHdpdGggdHdvICRodHRwIHNwZWNpZmljIG1ldGhvZHM6IGBzdWNjZXNzYCBhbmQgYGVycm9yYC4NCiAgICAgKg0KICAgICAqIGBgYGpzDQogICAgICogICAvLyBTaW1wbGUgR0VUIHJlcXVlc3QgZXhhbXBsZSA6DQogICAgICogICAkaHR0cC5nZXQoJy9zb21lVXJsJykuDQogICAgICogICAgIHN1Y2Nlc3MoZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHsNCiAgICAgKiAgICAgICAvLyB0aGlzIGNhbGxiYWNrIHdpbGwgYmUgY2FsbGVkIGFzeW5jaHJvbm91c2x5DQogICAgICogICAgICAgLy8gd2hlbiB0aGUgcmVzcG9uc2UgaXMgYXZhaWxhYmxlDQogICAgICogICAgIH0pLg0KICAgICAqICAgICBlcnJvcihmdW5jdGlvbihkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykgew0KICAgICAqICAgICAgIC8vIGNhbGxlZCBhc3luY2hyb25vdXNseSBpZiBhbiBlcnJvciBvY2N1cnMNCiAgICAgKiAgICAgICAvLyBvciBzZXJ2ZXIgcmV0dXJucyByZXNwb25zZSB3aXRoIGFuIGVycm9yIHN0YXR1cy4NCiAgICAgKiAgICAgfSk7DQogICAgICogYGBgDQogICAgICoNCiAgICAgKiBgYGBqcw0KICAgICAqICAgLy8gU2ltcGxlIFBPU1QgcmVxdWVzdCBleGFtcGxlIChwYXNzaW5nIGRhdGEpIDoNCiAgICAgKiAgICRodHRwLnBvc3QoJy9zb21lVXJsJywge21zZzonaGVsbG8gd29yZCEnfSkuDQogICAgICogICAgIHN1Y2Nlc3MoZnVuY3Rpb24oZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHsNCiAgICAgKiAgICAgICAvLyB0aGlzIGNhbGxiYWNrIHdpbGwgYmUgY2FsbGVkIGFzeW5jaHJvbm91c2x5DQogICAgICogICAgICAgLy8gd2hlbiB0aGUgcmVzcG9uc2UgaXMgYXZhaWxhYmxlDQogICAgICogICAgIH0pLg0KICAgICAqICAgICBlcnJvcihmdW5jdGlvbihkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykgew0KICAgICAqICAgICAgIC8vIGNhbGxlZCBhc3luY2hyb25vdXNseSBpZiBhbiBlcnJvciBvY2N1cnMNCiAgICAgKiAgICAgICAvLyBvciBzZXJ2ZXIgcmV0dXJucyByZXNwb25zZSB3aXRoIGFuIGVycm9yIHN0YXR1cy4NCiAgICAgKiAgICAgfSk7DQogICAgICogYGBgDQogICAgICoNCiAgICAgKg0KICAgICAqIFNpbmNlIHRoZSByZXR1cm5lZCB2YWx1ZSBvZiBjYWxsaW5nIHRoZSAkaHR0cCBmdW5jdGlvbiBpcyBhIGBwcm9taXNlYCwgeW91IGNhbiBhbHNvIHVzZQ0KICAgICAqIHRoZSBgdGhlbmAgbWV0aG9kIHRvIHJlZ2lzdGVyIGNhbGxiYWNrcywgYW5kIHRoZXNlIGNhbGxiYWNrcyB3aWxsIHJlY2VpdmUgYSBzaW5nbGUgYXJndW1lbnQg4oA/DQogICAgICogYW4gb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgcmVzcG9uc2UuIFNlZSB0aGUgQVBJIHNpZ25hdHVyZSBhbmQgdHlwZSBpbmZvIGJlbG93IGZvciBtb3JlDQogICAgICogZGV0YWlscy4NCiAgICAgKg0KICAgICAqIEEgcmVzcG9uc2Ugc3RhdHVzIGNvZGUgYmV0d2VlbiAyMDAgYW5kIDI5OSBpcyBjb25zaWRlcmVkIGEgc3VjY2VzcyBzdGF0dXMgYW5kDQogICAgICogd2lsbCByZXN1bHQgaW4gdGhlIHN1Y2Nlc3MgY2FsbGJhY2sgYmVpbmcgY2FsbGVkLiBOb3RlIHRoYXQgaWYgdGhlIHJlc3BvbnNlIGlzIGEgcmVkaXJlY3QsDQogICAgICogWE1MSHR0cFJlcXVlc3Qgd2lsbCB0cmFuc3BhcmVudGx5IGZvbGxvdyBpdCwgbWVhbmluZyB0aGF0IHRoZSBlcnJvciBjYWxsYmFjayB3aWxsIG5vdCBiZQ0KICAgICAqIGNhbGxlZCBmb3Igc3VjaCByZXNwb25zZXMuDQogICAgICoNCiAgICAgKiAjIyBXcml0aW5nIFVuaXQgVGVzdHMgdGhhdCB1c2UgJGh0dHANCiAgICAgKiBXaGVuIHVuaXQgdGVzdGluZyAodXNpbmcge0BsaW5rIG5nTW9jayBuZ01vY2t9KSwgaXQgaXMgbmVjZXNzYXJ5IHRvIGNhbGwNCiAgICAgKiB7QGxpbmsgbmdNb2NrLiRodHRwQmFja2VuZCNmbHVzaCAkaHR0cEJhY2tlbmQuZmx1c2goKX0gdG8gZmx1c2ggZWFjaCBwZW5kaW5nDQogICAgICogcmVxdWVzdCB1c2luZyB0cmFpbmVkIHJlc3BvbnNlcy4NCiAgICAgKg0KICAgICAqIGBgYA0KICAgICAqICRodHRwQmFja2VuZC5leHBlY3RHRVQoLi4uKTsNCiAgICAgKiAkaHR0cC5nZXQoLi4uKTsNCiAgICAgKiAkaHR0cEJhY2tlbmQuZmx1c2goKTsNCiAgICAgKiBgYGANCiAgICAgKg0KICAgICAqICMjIFNob3J0Y3V0IG1ldGhvZHMNCiAgICAgKg0KICAgICAqIFNob3J0Y3V0IG1ldGhvZHMgYXJlIGFsc28gYXZhaWxhYmxlLiBBbGwgc2hvcnRjdXQgbWV0aG9kcyByZXF1aXJlIHBhc3NpbmcgaW4gdGhlIFVSTCwgYW5kDQogICAgICogcmVxdWVzdCBkYXRhIG11c3QgYmUgcGFzc2VkIGluIGZvciBQT1NUL1BVVCByZXF1ZXN0cy4NCiAgICAgKg0KICAgICAqIGBgYGpzDQogICAgICogICAkaHR0cC5nZXQoJy9zb21lVXJsJykuc3VjY2VzcyhzdWNjZXNzQ2FsbGJhY2spOw0KICAgICAqICAgJGh0dHAucG9zdCgnL3NvbWVVcmwnLCBkYXRhKS5zdWNjZXNzKHN1Y2Nlc3NDYWxsYmFjayk7DQogICAgICogYGBgDQogICAgICoNCiAgICAgKiBDb21wbGV0ZSBsaXN0IG9mIHNob3J0Y3V0IG1ldGhvZHM6DQogICAgICoNCiAgICAgKiAtIHtAbGluayBuZy4kaHR0cCNnZXQgJGh0dHAuZ2V0fQ0KICAgICAqIC0ge0BsaW5rIG5nLiRodHRwI2hlYWQgJGh0dHAuaGVhZH0NCiAgICAgKiAtIHtAbGluayBuZy4kaHR0cCNwb3N0ICRodHRwLnBvc3R9DQogICAgICogLSB7QGxpbmsgbmcuJGh0dHAjcHV0ICRodHRwLnB1dH0NCiAgICAgKiAtIHtAbGluayBuZy4kaHR0cCNkZWxldGUgJGh0dHAuZGVsZXRlfQ0KICAgICAqIC0ge0BsaW5rIG5nLiRodHRwI2pzb25wICRodHRwLmpzb25wfQ0KICAgICAqIC0ge0BsaW5rIG5nLiRodHRwI3BhdGNoICRodHRwLnBhdGNofQ0KICAgICAqDQogICAgICoNCiAgICAgKiAjIyBTZXR0aW5nIEhUVFAgSGVhZGVycw0KICAgICAqDQogICAgICogVGhlICRodHRwIHNlcnZpY2Ugd2lsbCBhdXRvbWF0aWNhbGx5IGFkZCBjZXJ0YWluIEhUVFAgaGVhZGVycyB0byBhbGwgcmVxdWVzdHMuIFRoZXNlIGRlZmF1bHRzDQogICAgICogY2FuIGJlIGZ1bGx5IGNvbmZpZ3VyZWQgYnkgYWNjZXNzaW5nIHRoZSBgJGh0dHBQcm92aWRlci5kZWZhdWx0cy5oZWFkZXJzYCBjb25maWd1cmF0aW9uDQogICAgICogb2JqZWN0LCB3aGljaCBjdXJyZW50bHkgY29udGFpbnMgdGhpcyBkZWZhdWx0IGNvbmZpZ3VyYXRpb246DQogICAgICoNCiAgICAgKiAtIGAkaHR0cFByb3ZpZGVyLmRlZmF1bHRzLmhlYWRlcnMuY29tbW9uYCAoaGVhZGVycyB0aGF0IGFyZSBjb21tb24gZm9yIGFsbCByZXF1ZXN0cyk6DQogICAgICogICAtIGBBY2NlcHQ6IGFwcGxpY2F0aW9uL2pzb24sIHRleHQvcGxhaW4sICogLyAqYA0KICAgICAqIC0gYCRodHRwUHJvdmlkZXIuZGVmYXVsdHMuaGVhZGVycy5wb3N0YDogKGhlYWRlciBkZWZhdWx0cyBmb3IgUE9TVCByZXF1ZXN0cykNCiAgICAgKiAgIC0gYENvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbmANCiAgICAgKiAtIGAkaHR0cFByb3ZpZGVyLmRlZmF1bHRzLmhlYWRlcnMucHV0YCAoaGVhZGVyIGRlZmF1bHRzIGZvciBQVVQgcmVxdWVzdHMpDQogICAgICogICAtIGBDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL2pzb25gDQogICAgICoNCiAgICAgKiBUbyBhZGQgb3Igb3ZlcndyaXRlIHRoZXNlIGRlZmF1bHRzLCBzaW1wbHkgYWRkIG9yIHJlbW92ZSBhIHByb3BlcnR5IGZyb20gdGhlc2UgY29uZmlndXJhdGlvbg0KICAgICAqIG9iamVjdHMuIFRvIGFkZCBoZWFkZXJzIGZvciBhbiBIVFRQIG1ldGhvZCBvdGhlciB0aGFuIFBPU1Qgb3IgUFVULCBzaW1wbHkgYWRkIGEgbmV3IG9iamVjdA0KICAgICAqIHdpdGggdGhlIGxvd2VyY2FzZWQgSFRUUCBtZXRob2QgbmFtZSBhcyB0aGUga2V5LCBlLmcuDQogICAgICogYCRodHRwUHJvdmlkZXIuZGVmYXVsdHMuaGVhZGVycy5nZXQgPSB7ICdNeS1IZWFkZXInIDogJ3ZhbHVlJyB9Lg0KICAgICAqDQogICAgICogVGhlIGRlZmF1bHRzIGNhbiBhbHNvIGJlIHNldCBhdCBydW50aW1lIHZpYSB0aGUgYCRodHRwLmRlZmF1bHRzYCBvYmplY3QgaW4gdGhlIHNhbWUNCiAgICAgKiBmYXNoaW9uLiBGb3IgZXhhbXBsZToNCiAgICAgKg0KICAgICAqIGBgYA0KICAgICAqIG1vZHVsZS5ydW4oZnVuY3Rpb24oJGh0dHApIHsNCiAgICAgKiAgICRodHRwLmRlZmF1bHRzLmhlYWRlcnMuY29tbW9uLkF1dGhvcml6YXRpb24gPSAnQmFzaWMgWW1WbGNEcGliMjl3Jw0KICAgICAqIH0pOw0KICAgICAqIGBgYA0KICAgICAqDQogICAgICogSW4gYWRkaXRpb24sIHlvdSBjYW4gc3VwcGx5IGEgYGhlYWRlcnNgIHByb3BlcnR5IGluIHRoZSBjb25maWcgb2JqZWN0IHBhc3NlZCB3aGVuDQogICAgICogY2FsbGluZyBgJGh0dHAoY29uZmlnKWAsIHdoaWNoIG92ZXJyaWRlcyB0aGUgZGVmYXVsdHMgd2l0aG91dCBjaGFuZ2luZyB0aGVtIGdsb2JhbGx5Lg0KICAgICAqDQogICAgICogVG8gZXhwbGljaXRseSByZW1vdmUgYSBoZWFkZXIgYXV0b21hdGljYWxseSBhZGRlZCB2aWEgJGh0dHBQcm92aWRlci5kZWZhdWx0cy5oZWFkZXJzIG9uIGEgcGVyIHJlcXVlc3QgYmFzaXMsDQogICAgICogVXNlIHRoZSBgaGVhZGVyc2AgcHJvcGVydHksIHNldHRpbmcgdGhlIGRlc2lyZWQgaGVhZGVyIHRvIGB1bmRlZmluZWRgLiBGb3IgZXhhbXBsZToNCiAgICAgKg0KICAgICAqIGBgYGpzDQogICAgICogdmFyIHJlcSA9IHsNCiAgICAgKiAgbWV0aG9kOiAnUE9TVCcsDQogICAgICogIHVybDogJ2h0dHA6Ly9leGFtcGxlLmNvbScsDQogICAgICogIGhlYWRlcnM6IHsNCiAgICAgKiAgICAnQ29udGVudC1UeXBlJzogdW5kZWZpbmVkDQogICAgICogIH0sDQogICAgICogIGRhdGE6IHsgdGVzdDogJ3Rlc3QnIH0sDQogICAgICogfQ0KICAgICAqDQogICAgICogJGh0dHAocmVxKS5zdWNjZXNzKGZ1bmN0aW9uKCl7Li4ufSkuZXJyb3IoZnVuY3Rpb24oKXsuLi59KTsNCiAgICAgKiBgYGANCiAgICAgKg0KICAgICAqICMjIFRyYW5zZm9ybWluZyBSZXF1ZXN0cyBhbmQgUmVzcG9uc2VzDQogICAgICoNCiAgICAgKiBCb3RoIHJlcXVlc3RzIGFuZCByZXNwb25zZXMgY2FuIGJlIHRyYW5zZm9ybWVkIHVzaW5nIHRyYW5zZm9ybWF0aW9uIGZ1bmN0aW9uczogYHRyYW5zZm9ybVJlcXVlc3RgDQogICAgICogYW5kIGB0cmFuc2Zvcm1SZXNwb25zZWAuIFRoZXNlIHByb3BlcnRpZXMgY2FuIGJlIGEgc2luZ2xlIGZ1bmN0aW9uIHRoYXQgcmV0dXJucw0KICAgICAqIHRoZSB0cmFuc2Zvcm1lZCB2YWx1ZSAoYHtmdW5jdGlvbihkYXRhLCBoZWFkZXJzR2V0dGVyLCBzdGF0dXMpYCkgb3IgYW4gYXJyYXkgb2Ygc3VjaCB0cmFuc2Zvcm1hdGlvbiBmdW5jdGlvbnMsDQogICAgICogd2hpY2ggYWxsb3dzIHlvdSB0byBgcHVzaGAgb3IgYHVuc2hpZnRgIGEgbmV3IHRyYW5zZm9ybWF0aW9uIGZ1bmN0aW9uIGludG8gdGhlIHRyYW5zZm9ybWF0aW9uIGNoYWluLg0KICAgICAqDQogICAgICogIyMjIERlZmF1bHQgVHJhbnNmb3JtYXRpb25zDQogICAgICoNCiAgICAgKiBUaGUgYCRodHRwUHJvdmlkZXJgIHByb3ZpZGVyIGFuZCBgJGh0dHBgIHNlcnZpY2UgZXhwb3NlIGBkZWZhdWx0cy50cmFuc2Zvcm1SZXF1ZXN0YCBhbmQNCiAgICAgKiBgZGVmYXVsdHMudHJhbnNmb3JtUmVzcG9uc2VgIHByb3BlcnRpZXMuIElmIGEgcmVxdWVzdCBkb2VzIG5vdCBwcm92aWRlIGl0cyBvd24gdHJhbnNmb3JtYXRpb25zDQogICAgICogdGhlbiB0aGVzZSB3aWxsIGJlIGFwcGxpZWQuDQogICAgICoNCiAgICAgKiBZb3UgY2FuIGF1Z21lbnQgb3IgcmVwbGFjZSB0aGUgZGVmYXVsdCB0cmFuc2Zvcm1hdGlvbnMgYnkgbW9kaWZ5aW5nIHRoZXNlIHByb3BlcnRpZXMgYnkgYWRkaW5nIHRvIG9yDQogICAgICogcmVwbGFjaW5nIHRoZSBhcnJheS4NCiAgICAgKg0KICAgICAqIEFuZ3VsYXIgcHJvdmlkZXMgdGhlIGZvbGxvd2luZyBkZWZhdWx0IHRyYW5zZm9ybWF0aW9uczoNCiAgICAgKg0KICAgICAqIFJlcXVlc3QgdHJhbnNmb3JtYXRpb25zIChgJGh0dHBQcm92aWRlci5kZWZhdWx0cy50cmFuc2Zvcm1SZXF1ZXN0YCBhbmQgYCRodHRwLmRlZmF1bHRzLnRyYW5zZm9ybVJlcXVlc3RgKToNCiAgICAgKg0KICAgICAqIC0gSWYgdGhlIGBkYXRhYCBwcm9wZXJ0eSBvZiB0aGUgcmVxdWVzdCBjb25maWd1cmF0aW9uIG9iamVjdCBjb250YWlucyBhbiBvYmplY3QsIHNlcmlhbGl6ZSBpdA0KICAgICAqICAgaW50byBKU09OIGZvcm1hdC4NCiAgICAgKg0KICAgICAqIFJlc3BvbnNlIHRyYW5zZm9ybWF0aW9ucyAoYCRodHRwUHJvdmlkZXIuZGVmYXVsdHMudHJhbnNmb3JtUmVzcG9uc2VgIGFuZCBgJGh0dHAuZGVmYXVsdHMudHJhbnNmb3JtUmVzcG9uc2VgKToNCiAgICAgKg0KICAgICAqICAtIElmIFhTUkYgcHJlZml4IGlzIGRldGVjdGVkLCBzdHJpcCBpdCAoc2VlIFNlY3VyaXR5IENvbnNpZGVyYXRpb25zIHNlY3Rpb24gYmVsb3cpLg0KICAgICAqICAtIElmIEpTT04gcmVzcG9uc2UgaXMgZGV0ZWN0ZWQsIGRlc2VyaWFsaXplIGl0IHVzaW5nIGEgSlNPTiBwYXJzZXIuDQogICAgICoNCiAgICAgKg0KICAgICAqICMjIyBPdmVycmlkaW5nIHRoZSBEZWZhdWx0IFRyYW5zZm9ybWF0aW9ucyBQZXIgUmVxdWVzdA0KICAgICAqDQogICAgICogSWYgeW91IHdpc2ggb3ZlcnJpZGUgdGhlIHJlcXVlc3QvcmVzcG9uc2UgdHJhbnNmb3JtYXRpb25zIG9ubHkgZm9yIGEgc2luZ2xlIHJlcXVlc3QgdGhlbiBwcm92aWRlDQogICAgICogYHRyYW5zZm9ybVJlcXVlc3RgIGFuZC9vciBgdHJhbnNmb3JtUmVzcG9uc2VgIHByb3BlcnRpZXMgb24gdGhlIGNvbmZpZ3VyYXRpb24gb2JqZWN0IHBhc3NlZA0KICAgICAqIGludG8gYCRodHRwYC4NCiAgICAgKg0KICAgICAqIE5vdGUgdGhhdCBpZiB5b3UgcHJvdmlkZSB0aGVzZSBwcm9wZXJ0aWVzIG9uIHRoZSBjb25maWcgb2JqZWN0IHRoZSBkZWZhdWx0IHRyYW5zZm9ybWF0aW9ucyB3aWxsIGJlDQogICAgICogb3ZlcndyaXR0ZW4uIElmIHlvdSB3aXNoIHRvIGF1Z21lbnQgdGhlIGRlZmF1bHQgdHJhbnNmb3JtYXRpb25zIHRoZW4geW91IG11c3QgaW5jbHVkZSB0aGVtIGluIHlvdXINCiAgICAgKiBsb2NhbCB0cmFuc2Zvcm1hdGlvbiBhcnJheS4NCiAgICAgKg0KICAgICAqIFRoZSBmb2xsb3dpbmcgY29kZSBkZW1vbnN0cmF0ZXMgYWRkaW5nIGEgbmV3IHJlc3BvbnNlIHRyYW5zZm9ybWF0aW9uIHRvIGJlIHJ1biBhZnRlciB0aGUgZGVmYXVsdCByZXNwb25zZQ0KICAgICAqIHRyYW5zZm9ybWF0aW9ucyBoYXZlIGJlZW4gcnVuLg0KICAgICAqDQogICAgICogYGBganMNCiAgICAgKiBmdW5jdGlvbiBhcHBlbmRUcmFuc2Zvcm0oZGVmYXVsdHMsIHRyYW5zZm9ybSkgew0KICAgICAqDQogICAgICogICAvLyBXZSBjYW4ndCBndWFyYW50ZWUgdGhhdCB0aGUgZGVmYXVsdCB0cmFuc2Zvcm1hdGlvbiBpcyBhbiBhcnJheQ0KICAgICAqICAgZGVmYXVsdHMgPSBhbmd1bGFyLmlzQXJyYXkoZGVmYXVsdHMpID8gZGVmYXVsdHMgOiBbZGVmYXVsdHNdOw0KICAgICAqDQogICAgICogICAvLyBBcHBlbmQgdGhlIG5ldyB0cmFuc2Zvcm1hdGlvbiB0byB0aGUgZGVmYXVsdHMNCiAgICAgKiAgIHJldHVybiBkZWZhdWx0cy5jb25jYXQodHJhbnNmb3JtKTsNCiAgICAgKiB9DQogICAgICoNCiAgICAgKiAkaHR0cCh7DQogICAgICogICB1cmw6ICcuLi4nLA0KICAgICAqICAgbWV0aG9kOiAnR0VUJywNCiAgICAgKiAgIHRyYW5zZm9ybVJlc3BvbnNlOiBhcHBlbmRUcmFuc2Zvcm0oJGh0dHAuZGVmYXVsdHMudHJhbnNmb3JtUmVzcG9uc2UsIGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgICogICAgIHJldHVybiBkb1RyYW5zZm9ybSh2YWx1ZSk7DQogICAgICogICB9KQ0KICAgICAqIH0pOw0KICAgICAqIGBgYA0KICAgICAqDQogICAgICoNCiAgICAgKiAjIyBDYWNoaW5nDQogICAgICoNCiAgICAgKiBUbyBlbmFibGUgY2FjaGluZywgc2V0IHRoZSByZXF1ZXN0IGNvbmZpZ3VyYXRpb24gYGNhY2hlYCBwcm9wZXJ0eSB0byBgdHJ1ZWAgKHRvIHVzZSBkZWZhdWx0DQogICAgICogY2FjaGUpIG9yIHRvIGEgY3VzdG9tIGNhY2hlIG9iamVjdCAoYnVpbHQgd2l0aCB7QGxpbmsgbmcuJGNhY2hlRmFjdG9yeSBgJGNhY2hlRmFjdG9yeWB9KS4NCiAgICAgKiBXaGVuIHRoZSBjYWNoZSBpcyBlbmFibGVkLCBgJGh0dHBgIHN0b3JlcyB0aGUgcmVzcG9uc2UgZnJvbSB0aGUgc2VydmVyIGluIHRoZSBzcGVjaWZpZWQNCiAgICAgKiBjYWNoZS4gVGhlIG5leHQgdGltZSB0aGUgc2FtZSByZXF1ZXN0IGlzIG1hZGUsIHRoZSByZXNwb25zZSBpcyBzZXJ2ZWQgZnJvbSB0aGUgY2FjaGUgd2l0aG91dA0KICAgICAqIHNlbmRpbmcgYSByZXF1ZXN0IHRvIHRoZSBzZXJ2ZXIuDQogICAgICoNCiAgICAgKiBOb3RlIHRoYXQgZXZlbiBpZiB0aGUgcmVzcG9uc2UgaXMgc2VydmVkIGZyb20gY2FjaGUsIGRlbGl2ZXJ5IG9mIHRoZSBkYXRhIGlzIGFzeW5jaHJvbm91cyBpbg0KICAgICAqIHRoZSBzYW1lIHdheSB0aGF0IHJlYWwgcmVxdWVzdHMgYXJlLg0KICAgICAqDQogICAgICogSWYgdGhlcmUgYXJlIG11bHRpcGxlIEdFVCByZXF1ZXN0cyBmb3IgdGhlIHNhbWUgVVJMIHRoYXQgc2hvdWxkIGJlIGNhY2hlZCB1c2luZyB0aGUgc2FtZQ0KICAgICAqIGNhY2hlLCBidXQgdGhlIGNhY2hlIGlzIG5vdCBwb3B1bGF0ZWQgeWV0LCBvbmx5IG9uZSByZXF1ZXN0IHRvIHRoZSBzZXJ2ZXIgd2lsbCBiZSBtYWRlIGFuZA0KICAgICAqIHRoZSByZW1haW5pbmcgcmVxdWVzdHMgd2lsbCBiZSBmdWxmaWxsZWQgdXNpbmcgdGhlIHJlc3BvbnNlIGZyb20gdGhlIGZpcnN0IHJlcXVlc3QuDQogICAgICoNCiAgICAgKiBZb3UgY2FuIGNoYW5nZSB0aGUgZGVmYXVsdCBjYWNoZSB0byBhIG5ldyBvYmplY3QgKGJ1aWx0IHdpdGgNCiAgICAgKiB7QGxpbmsgbmcuJGNhY2hlRmFjdG9yeSBgJGNhY2hlRmFjdG9yeWB9KSBieSB1cGRhdGluZyB0aGUNCiAgICAgKiB7QGxpbmsgbmcuJGh0dHAjZGVmYXVsdHMgYCRodHRwLmRlZmF1bHRzLmNhY2hlYH0gcHJvcGVydHkuIEFsbCByZXF1ZXN0cyB3aG8gc2V0DQogICAgICogdGhlaXIgYGNhY2hlYCBwcm9wZXJ0eSB0byBgdHJ1ZWAgd2lsbCBub3cgdXNlIHRoaXMgY2FjaGUgb2JqZWN0Lg0KICAgICAqDQogICAgICogSWYgeW91IHNldCB0aGUgZGVmYXVsdCBjYWNoZSB0byBgZmFsc2VgIHRoZW4gb25seSByZXF1ZXN0cyB0aGF0IHNwZWNpZnkgdGhlaXIgb3duIGN1c3RvbQ0KICAgICAqIGNhY2hlIG9iamVjdCB3aWxsIGJlIGNhY2hlZC4NCiAgICAgKg0KICAgICAqICMjIEludGVyY2VwdG9ycw0KICAgICAqDQogICAgICogQmVmb3JlIHlvdSBzdGFydCBjcmVhdGluZyBpbnRlcmNlcHRvcnMsIGJlIHN1cmUgdG8gdW5kZXJzdGFuZCB0aGUNCiAgICAgKiB7QGxpbmsgbmcuJHEgJHEgYW5kIGRlZmVycmVkL3Byb21pc2UgQVBJc30uDQogICAgICoNCiAgICAgKiBGb3IgcHVycG9zZXMgb2YgZ2xvYmFsIGVycm9yIGhhbmRsaW5nLCBhdXRoZW50aWNhdGlvbiwgb3IgYW55IGtpbmQgb2Ygc3luY2hyb25vdXMgb3INCiAgICAgKiBhc3luY2hyb25vdXMgcHJlLXByb2Nlc3Npbmcgb2YgcmVxdWVzdCBvciBwb3N0cHJvY2Vzc2luZyBvZiByZXNwb25zZXMsIGl0IGlzIGRlc2lyYWJsZSB0byBiZQ0KICAgICAqIGFibGUgdG8gaW50ZXJjZXB0IHJlcXVlc3RzIGJlZm9yZSB0aGV5IGFyZSBoYW5kZWQgdG8gdGhlIHNlcnZlciBhbmQNCiAgICAgKiByZXNwb25zZXMgYmVmb3JlIHRoZXkgYXJlIGhhbmRlZCBvdmVyIHRvIHRoZSBhcHBsaWNhdGlvbiBjb2RlIHRoYXQNCiAgICAgKiBpbml0aWF0ZWQgdGhlc2UgcmVxdWVzdHMuIFRoZSBpbnRlcmNlcHRvcnMgbGV2ZXJhZ2UgdGhlIHtAbGluayBuZy4kcQ0KICAgICAqIHByb21pc2UgQVBJc30gdG8gZnVsZmlsbCB0aGlzIG5lZWQgZm9yIGJvdGggc3luY2hyb25vdXMgYW5kIGFzeW5jaHJvbm91cyBwcmUtcHJvY2Vzc2luZy4NCiAgICAgKg0KICAgICAqIFRoZSBpbnRlcmNlcHRvcnMgYXJlIHNlcnZpY2UgZmFjdG9yaWVzIHRoYXQgYXJlIHJlZ2lzdGVyZWQgd2l0aCB0aGUgYCRodHRwUHJvdmlkZXJgIGJ5DQogICAgICogYWRkaW5nIHRoZW0gdG8gdGhlIGAkaHR0cFByb3ZpZGVyLmludGVyY2VwdG9yc2AgYXJyYXkuIFRoZSBmYWN0b3J5IGlzIGNhbGxlZCBhbmQNCiAgICAgKiBpbmplY3RlZCB3aXRoIGRlcGVuZGVuY2llcyAoaWYgc3BlY2lmaWVkKSBhbmQgcmV0dXJucyB0aGUgaW50ZXJjZXB0b3IuDQogICAgICoNCiAgICAgKiBUaGVyZSBhcmUgdHdvIGtpbmRzIG9mIGludGVyY2VwdG9ycyAoYW5kIHR3byBraW5kcyBvZiByZWplY3Rpb24gaW50ZXJjZXB0b3JzKToNCiAgICAgKg0KICAgICAqICAgKiBgcmVxdWVzdGA6IGludGVyY2VwdG9ycyBnZXQgY2FsbGVkIHdpdGggYSBodHRwIGBjb25maWdgIG9iamVjdC4gVGhlIGZ1bmN0aW9uIGlzIGZyZWUgdG8NCiAgICAgKiAgICAgbW9kaWZ5IHRoZSBgY29uZmlnYCBvYmplY3Qgb3IgY3JlYXRlIGEgbmV3IG9uZS4gVGhlIGZ1bmN0aW9uIG5lZWRzIHRvIHJldHVybiB0aGUgYGNvbmZpZ2ANCiAgICAgKiAgICAgb2JqZWN0IGRpcmVjdGx5LCBvciBhIHByb21pc2UgY29udGFpbmluZyB0aGUgYGNvbmZpZ2Agb3IgYSBuZXcgYGNvbmZpZ2Agb2JqZWN0Lg0KICAgICAqICAgKiBgcmVxdWVzdEVycm9yYDogaW50ZXJjZXB0b3IgZ2V0cyBjYWxsZWQgd2hlbiBhIHByZXZpb3VzIGludGVyY2VwdG9yIHRocmV3IGFuIGVycm9yIG9yDQogICAgICogICAgIHJlc29sdmVkIHdpdGggYSByZWplY3Rpb24uDQogICAgICogICAqIGByZXNwb25zZWA6IGludGVyY2VwdG9ycyBnZXQgY2FsbGVkIHdpdGggaHR0cCBgcmVzcG9uc2VgIG9iamVjdC4gVGhlIGZ1bmN0aW9uIGlzIGZyZWUgdG8NCiAgICAgKiAgICAgbW9kaWZ5IHRoZSBgcmVzcG9uc2VgIG9iamVjdCBvciBjcmVhdGUgYSBuZXcgb25lLiBUaGUgZnVuY3Rpb24gbmVlZHMgdG8gcmV0dXJuIHRoZSBgcmVzcG9uc2VgDQogICAgICogICAgIG9iamVjdCBkaXJlY3RseSwgb3IgYXMgYSBwcm9taXNlIGNvbnRhaW5pbmcgdGhlIGByZXNwb25zZWAgb3IgYSBuZXcgYHJlc3BvbnNlYCBvYmplY3QuDQogICAgICogICAqIGByZXNwb25zZUVycm9yYDogaW50ZXJjZXB0b3IgZ2V0cyBjYWxsZWQgd2hlbiBhIHByZXZpb3VzIGludGVyY2VwdG9yIHRocmV3IGFuIGVycm9yIG9yDQogICAgICogICAgIHJlc29sdmVkIHdpdGggYSByZWplY3Rpb24uDQogICAgICoNCiAgICAgKg0KICAgICAqIGBgYGpzDQogICAgICogICAvLyByZWdpc3RlciB0aGUgaW50ZXJjZXB0b3IgYXMgYSBzZXJ2aWNlDQogICAgICogICAkcHJvdmlkZS5mYWN0b3J5KCdteUh0dHBJbnRlcmNlcHRvcicsIGZ1bmN0aW9uKCRxLCBkZXBlbmRlbmN5MSwgZGVwZW5kZW5jeTIpIHsNCiAgICAgKiAgICAgcmV0dXJuIHsNCiAgICAgKiAgICAgICAvLyBvcHRpb25hbCBtZXRob2QNCiAgICAgKiAgICAgICAncmVxdWVzdCc6IGZ1bmN0aW9uKGNvbmZpZykgew0KICAgICAqICAgICAgICAgLy8gZG8gc29tZXRoaW5nIG9uIHN1Y2Nlc3MNCiAgICAgKiAgICAgICAgIHJldHVybiBjb25maWc7DQogICAgICogICAgICAgfSwNCiAgICAgKg0KICAgICAqICAgICAgIC8vIG9wdGlvbmFsIG1ldGhvZA0KICAgICAqICAgICAgJ3JlcXVlc3RFcnJvcic6IGZ1bmN0aW9uKHJlamVjdGlvbikgew0KICAgICAqICAgICAgICAgLy8gZG8gc29tZXRoaW5nIG9uIGVycm9yDQogICAgICogICAgICAgICBpZiAoY2FuUmVjb3ZlcihyZWplY3Rpb24pKSB7DQogICAgICogICAgICAgICAgIHJldHVybiByZXNwb25zZU9yTmV3UHJvbWlzZQ0KICAgICAqICAgICAgICAgfQ0KICAgICAqICAgICAgICAgcmV0dXJuICRxLnJlamVjdChyZWplY3Rpb24pOw0KICAgICAqICAgICAgIH0sDQogICAgICoNCiAgICAgKg0KICAgICAqDQogICAgICogICAgICAgLy8gb3B0aW9uYWwgbWV0aG9kDQogICAgICogICAgICAgJ3Jlc3BvbnNlJzogZnVuY3Rpb24ocmVzcG9uc2UpIHsNCiAgICAgKiAgICAgICAgIC8vIGRvIHNvbWV0aGluZyBvbiBzdWNjZXNzDQogICAgICogICAgICAgICByZXR1cm4gcmVzcG9uc2U7DQogICAgICogICAgICAgfSwNCiAgICAgKg0KICAgICAqICAgICAgIC8vIG9wdGlvbmFsIG1ldGhvZA0KICAgICAqICAgICAgJ3Jlc3BvbnNlRXJyb3InOiBmdW5jdGlvbihyZWplY3Rpb24pIHsNCiAgICAgKiAgICAgICAgIC8vIGRvIHNvbWV0aGluZyBvbiBlcnJvcg0KICAgICAqICAgICAgICAgaWYgKGNhblJlY292ZXIocmVqZWN0aW9uKSkgew0KICAgICAqICAgICAgICAgICByZXR1cm4gcmVzcG9uc2VPck5ld1Byb21pc2UNCiAgICAgKiAgICAgICAgIH0NCiAgICAgKiAgICAgICAgIHJldHVybiAkcS5yZWplY3QocmVqZWN0aW9uKTsNCiAgICAgKiAgICAgICB9DQogICAgICogICAgIH07DQogICAgICogICB9KTsNCiAgICAgKg0KICAgICAqICAgJGh0dHBQcm92aWRlci5pbnRlcmNlcHRvcnMucHVzaCgnbXlIdHRwSW50ZXJjZXB0b3InKTsNCiAgICAgKg0KICAgICAqDQogICAgICogICAvLyBhbHRlcm5hdGl2ZWx5LCByZWdpc3RlciB0aGUgaW50ZXJjZXB0b3IgdmlhIGFuIGFub255bW91cyBmYWN0b3J5DQogICAgICogICAkaHR0cFByb3ZpZGVyLmludGVyY2VwdG9ycy5wdXNoKGZ1bmN0aW9uKCRxLCBkZXBlbmRlbmN5MSwgZGVwZW5kZW5jeTIpIHsNCiAgICAgKiAgICAgcmV0dXJuIHsNCiAgICAgKiAgICAgICdyZXF1ZXN0JzogZnVuY3Rpb24oY29uZmlnKSB7DQogICAgICogICAgICAgICAgLy8gc2FtZSBhcyBhYm92ZQ0KICAgICAqICAgICAgIH0sDQogICAgICoNCiAgICAgKiAgICAgICAncmVzcG9uc2UnOiBmdW5jdGlvbihyZXNwb25zZSkgew0KICAgICAqICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUNCiAgICAgKiAgICAgICB9DQogICAgICogICAgIH07DQogICAgICogICB9KTsNCiAgICAgKiBgYGANCiAgICAgKg0KICAgICAqICMjIFNlY3VyaXR5IENvbnNpZGVyYXRpb25zDQogICAgICoNCiAgICAgKiBXaGVuIGRlc2lnbmluZyB3ZWIgYXBwbGljYXRpb25zLCBjb25zaWRlciBzZWN1cml0eSB0aHJlYXRzIGZyb206DQogICAgICoNCiAgICAgKiAtIFtKU09OIHZ1bG5lcmFiaWxpdHldKGh0dHA6Ly9oYWFja2VkLmNvbS9hcmNoaXZlLzIwMDgvMTEvMjAvYW5hdG9teS1vZi1hLXN1YnRsZS1qc29uLXZ1bG5lcmFiaWxpdHkuYXNweCkNCiAgICAgKiAtIFtYU1JGXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXNpdGVfcmVxdWVzdF9mb3JnZXJ5KQ0KICAgICAqDQogICAgICogQm90aCBzZXJ2ZXIgYW5kIHRoZSBjbGllbnQgbXVzdCBjb29wZXJhdGUgaW4gb3JkZXIgdG8gZWxpbWluYXRlIHRoZXNlIHRocmVhdHMuIEFuZ3VsYXIgY29tZXMNCiAgICAgKiBwcmUtY29uZmlndXJlZCB3aXRoIHN0cmF0ZWdpZXMgdGhhdCBhZGRyZXNzIHRoZXNlIGlzc3VlcywgYnV0IGZvciB0aGlzIHRvIHdvcmsgYmFja2VuZCBzZXJ2ZXINCiAgICAgKiBjb29wZXJhdGlvbiBpcyByZXF1aXJlZC4NCiAgICAgKg0KICAgICAqICMjIyBKU09OIFZ1bG5lcmFiaWxpdHkgUHJvdGVjdGlvbg0KICAgICAqDQogICAgICogQSBbSlNPTiB2dWxuZXJhYmlsaXR5XShodHRwOi8vaGFhY2tlZC5jb20vYXJjaGl2ZS8yMDA4LzExLzIwL2FuYXRvbXktb2YtYS1zdWJ0bGUtanNvbi12dWxuZXJhYmlsaXR5LmFzcHgpDQogICAgICogYWxsb3dzIHRoaXJkIHBhcnR5IHdlYnNpdGUgdG8gdHVybiB5b3VyIEpTT04gcmVzb3VyY2UgVVJMIGludG8NCiAgICAgKiBbSlNPTlBdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSlNPTlApIHJlcXVlc3QgdW5kZXIgc29tZSBjb25kaXRpb25zLiBUbw0KICAgICAqIGNvdW50ZXIgdGhpcyB5b3VyIHNlcnZlciBjYW4gcHJlZml4IGFsbCBKU09OIHJlcXVlc3RzIHdpdGggZm9sbG93aW5nIHN0cmluZyBgIildfScsXG4iYC4NCiAgICAgKiBBbmd1bGFyIHdpbGwgYXV0b21hdGljYWxseSBzdHJpcCB0aGUgcHJlZml4IGJlZm9yZSBwcm9jZXNzaW5nIGl0IGFzIEpTT04uDQogICAgICoNCiAgICAgKiBGb3IgZXhhbXBsZSBpZiB5b3VyIHNlcnZlciBuZWVkcyB0byByZXR1cm46DQogICAgICogYGBganMNCiAgICAgKiBbJ29uZScsJ3R3byddDQogICAgICogYGBgDQogICAgICoNCiAgICAgKiB3aGljaCBpcyB2dWxuZXJhYmxlIHRvIGF0dGFjaywgeW91ciBzZXJ2ZXIgY2FuIHJldHVybjoNCiAgICAgKiBgYGBqcw0KICAgICAqICldfScsDQogICAgICogWydvbmUnLCd0d28nXQ0KICAgICAqIGBgYA0KICAgICAqDQogICAgICogQW5ndWxhciB3aWxsIHN0cmlwIHRoZSBwcmVmaXgsIGJlZm9yZSBwcm9jZXNzaW5nIHRoZSBKU09OLg0KICAgICAqDQogICAgICoNCiAgICAgKiAjIyMgQ3Jvc3MgU2l0ZSBSZXF1ZXN0IEZvcmdlcnkgKFhTUkYpIFByb3RlY3Rpb24NCiAgICAgKg0KICAgICAqIFtYU1JGXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXNpdGVfcmVxdWVzdF9mb3JnZXJ5KSBpcyBhIHRlY2huaXF1ZSBieSB3aGljaA0KICAgICAqIGFuIHVuYXV0aG9yaXplZCBzaXRlIGNhbiBnYWluIHlvdXIgdXNlcidzIHByaXZhdGUgZGF0YS4gQW5ndWxhciBwcm92aWRlcyBhIG1lY2hhbmlzbQ0KICAgICAqIHRvIGNvdW50ZXIgWFNSRi4gV2hlbiBwZXJmb3JtaW5nIFhIUiByZXF1ZXN0cywgdGhlICRodHRwIHNlcnZpY2UgcmVhZHMgYSB0b2tlbiBmcm9tIGEgY29va2llDQogICAgICogKGJ5IGRlZmF1bHQsIGBYU1JGLVRPS0VOYCkgYW5kIHNldHMgaXQgYXMgYW4gSFRUUCBoZWFkZXIgKGBYLVhTUkYtVE9LRU5gKS4gU2luY2Ugb25seQ0KICAgICAqIEphdmFTY3JpcHQgdGhhdCBydW5zIG9uIHlvdXIgZG9tYWluIGNvdWxkIHJlYWQgdGhlIGNvb2tpZSwgeW91ciBzZXJ2ZXIgY2FuIGJlIGFzc3VyZWQgdGhhdA0KICAgICAqIHRoZSBYSFIgY2FtZSBmcm9tIEphdmFTY3JpcHQgcnVubmluZyBvbiB5b3VyIGRvbWFpbi4gVGhlIGhlYWRlciB3aWxsIG5vdCBiZSBzZXQgZm9yDQogICAgICogY3Jvc3MtZG9tYWluIHJlcXVlc3RzLg0KICAgICAqDQogICAgICogVG8gdGFrZSBhZHZhbnRhZ2Ugb2YgdGhpcywgeW91ciBzZXJ2ZXIgbmVlZHMgdG8gc2V0IGEgdG9rZW4gaW4gYSBKYXZhU2NyaXB0IHJlYWRhYmxlIHNlc3Npb24NCiAgICAgKiBjb29raWUgY2FsbGVkIGBYU1JGLVRPS0VOYCBvbiB0aGUgZmlyc3QgSFRUUCBHRVQgcmVxdWVzdC4gT24gc3Vic2VxdWVudCBYSFIgcmVxdWVzdHMgdGhlDQogICAgICogc2VydmVyIGNhbiB2ZXJpZnkgdGhhdCB0aGUgY29va2llIG1hdGNoZXMgYFgtWFNSRi1UT0tFTmAgSFRUUCBoZWFkZXIsIGFuZCB0aGVyZWZvcmUgYmUgc3VyZQ0KICAgICAqIHRoYXQgb25seSBKYXZhU2NyaXB0IHJ1bm5pbmcgb24geW91ciBkb21haW4gY291bGQgaGF2ZSBzZW50IHRoZSByZXF1ZXN0LiBUaGUgdG9rZW4gbXVzdCBiZQ0KICAgICAqIHVuaXF1ZSBmb3IgZWFjaCB1c2VyIGFuZCBtdXN0IGJlIHZlcmlmaWFibGUgYnkgdGhlIHNlcnZlciAodG8gcHJldmVudCB0aGUgSmF2YVNjcmlwdCBmcm9tDQogICAgICogbWFraW5nIHVwIGl0cyBvd24gdG9rZW5zKS4gV2UgcmVjb21tZW5kIHRoYXQgdGhlIHRva2VuIGlzIGEgZGlnZXN0IG9mIHlvdXIgc2l0ZSdzDQogICAgICogYXV0aGVudGljYXRpb24gY29va2llIHdpdGggYSBbc2FsdF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2FsdF8oY3J5cHRvZ3JhcGh5JiM0MTspDQogICAgICogZm9yIGFkZGVkIHNlY3VyaXR5Lg0KICAgICAqDQogICAgICogVGhlIG5hbWUgb2YgdGhlIGhlYWRlcnMgY2FuIGJlIHNwZWNpZmllZCB1c2luZyB0aGUgeHNyZkhlYWRlck5hbWUgYW5kIHhzcmZDb29raWVOYW1lDQogICAgICogcHJvcGVydGllcyBvZiBlaXRoZXIgJGh0dHBQcm92aWRlci5kZWZhdWx0cyBhdCBjb25maWctdGltZSwgJGh0dHAuZGVmYXVsdHMgYXQgcnVuLXRpbWUsDQogICAgICogb3IgdGhlIHBlci1yZXF1ZXN0IGNvbmZpZyBvYmplY3QuDQogICAgICoNCiAgICAgKg0KICAgICAqIEBwYXJhbSB7b2JqZWN0fSBjb25maWcgT2JqZWN0IGRlc2NyaWJpbmcgdGhlIHJlcXVlc3QgdG8gYmUgbWFkZSBhbmQgaG93IGl0IHNob3VsZCBiZQ0KICAgICAqICAgIHByb2Nlc3NlZC4gVGhlIG9iamVjdCBoYXMgZm9sbG93aW5nIHByb3BlcnRpZXM6DQogICAgICoNCiAgICAgKiAgICAtICoqbWV0aG9kKiog4oA/IGB7c3RyaW5nfWAg4oA/IEhUVFAgbWV0aG9kIChlLmcuICdHRVQnLCAnUE9TVCcsIGV0YykNCiAgICAgKiAgICAtICoqdXJsKiog4oA/IGB7c3RyaW5nfWAg4oA/IEFic29sdXRlIG9yIHJlbGF0aXZlIFVSTCBvZiB0aGUgcmVzb3VyY2UgdGhhdCBpcyBiZWluZyByZXF1ZXN0ZWQuDQogICAgICogICAgLSAqKnBhcmFtcyoqIOKAPyBge09iamVjdC48c3RyaW5nfE9iamVjdD59YCDigD8gTWFwIG9mIHN0cmluZ3Mgb3Igb2JqZWN0cyB3aGljaCB3aWxsIGJlIHR1cm5lZA0KICAgICAqICAgICAgdG8gYD9rZXkxPXZhbHVlMSZrZXkyPXZhbHVlMmAgYWZ0ZXIgdGhlIHVybC4gSWYgdGhlIHZhbHVlIGlzIG5vdCBhIHN0cmluZywgaXQgd2lsbCBiZQ0KICAgICAqICAgICAgSlNPTmlmaWVkLg0KICAgICAqICAgIC0gKipkYXRhKiog4oA/IGB7c3RyaW5nfE9iamVjdH1gIOKAPyBEYXRhIHRvIGJlIHNlbnQgYXMgdGhlIHJlcXVlc3QgbWVzc2FnZSBkYXRhLg0KICAgICAqICAgIC0gKipoZWFkZXJzKiog4oA/IGB7T2JqZWN0fWAg4oA/IE1hcCBvZiBzdHJpbmdzIG9yIGZ1bmN0aW9ucyB3aGljaCByZXR1cm4gc3RyaW5ncyByZXByZXNlbnRpbmcNCiAgICAgKiAgICAgIEhUVFAgaGVhZGVycyB0byBzZW5kIHRvIHRoZSBzZXJ2ZXIuIElmIHRoZSByZXR1cm4gdmFsdWUgb2YgYSBmdW5jdGlvbiBpcyBudWxsLCB0aGUNCiAgICAgKiAgICAgIGhlYWRlciB3aWxsIG5vdCBiZSBzZW50Lg0KICAgICAqICAgIC0gKip4c3JmSGVhZGVyTmFtZSoqIOKAPyBge3N0cmluZ31gIOKAPyBOYW1lIG9mIEhUVFAgaGVhZGVyIHRvIHBvcHVsYXRlIHdpdGggdGhlIFhTUkYgdG9rZW4uDQogICAgICogICAgLSAqKnhzcmZDb29raWVOYW1lKiog4oA/IGB7c3RyaW5nfWAg4oA/IE5hbWUgb2YgY29va2llIGNvbnRhaW5pbmcgdGhlIFhTUkYgdG9rZW4uDQogICAgICogICAgLSAqKnRyYW5zZm9ybVJlcXVlc3QqKiDigD8NCiAgICAgKiAgICAgIGB7ZnVuY3Rpb24oZGF0YSwgaGVhZGVyc0dldHRlcil8QXJyYXkuPGZ1bmN0aW9uKGRhdGEsIGhlYWRlcnNHZXR0ZXIpPn1gIOKAPw0KICAgICAqICAgICAgdHJhbnNmb3JtIGZ1bmN0aW9uIG9yIGFuIGFycmF5IG9mIHN1Y2ggZnVuY3Rpb25zLiBUaGUgdHJhbnNmb3JtIGZ1bmN0aW9uIHRha2VzIHRoZSBodHRwDQogICAgICogICAgICByZXF1ZXN0IGJvZHkgYW5kIGhlYWRlcnMgYW5kIHJldHVybnMgaXRzIHRyYW5zZm9ybWVkICh0eXBpY2FsbHkgc2VyaWFsaXplZCkgdmVyc2lvbi4NCiAgICAgKiAgICAgIFNlZSB7QGxpbmsgbmcuJGh0dHAjb3ZlcnJpZGluZy10aGUtZGVmYXVsdC10cmFuc2Zvcm1hdGlvbnMtcGVyLXJlcXVlc3QNCiAgICAgKiAgICAgIE92ZXJyaWRpbmcgdGhlIERlZmF1bHQgVHJhbnNmb3JtYXRpb25zfQ0KICAgICAqICAgIC0gKip0cmFuc2Zvcm1SZXNwb25zZSoqIOKAPw0KICAgICAqICAgICAgYHtmdW5jdGlvbihkYXRhLCBoZWFkZXJzR2V0dGVyLCBzdGF0dXMpfEFycmF5LjxmdW5jdGlvbihkYXRhLCBoZWFkZXJzR2V0dGVyLCBzdGF0dXMpPn1gIOKAPw0KICAgICAqICAgICAgdHJhbnNmb3JtIGZ1bmN0aW9uIG9yIGFuIGFycmF5IG9mIHN1Y2ggZnVuY3Rpb25zLiBUaGUgdHJhbnNmb3JtIGZ1bmN0aW9uIHRha2VzIHRoZSBodHRwDQogICAgICogICAgICByZXNwb25zZSBib2R5LCBoZWFkZXJzIGFuZCBzdGF0dXMgYW5kIHJldHVybnMgaXRzIHRyYW5zZm9ybWVkICh0eXBpY2FsbHkgZGVzZXJpYWxpemVkKSB2ZXJzaW9uLg0KICAgICAqICAgICAgU2VlIHtAbGluayBuZy4kaHR0cCNvdmVycmlkaW5nLXRoZS1kZWZhdWx0LXRyYW5zZm9ybWF0aW9ucy1wZXItcmVxdWVzdA0KICAgICAqICAgICAgT3ZlcnJpZGluZyB0aGUgRGVmYXVsdCBUcmFuc2Zvcm1hdGlvbnN9DQogICAgICogICAgLSAqKmNhY2hlKiog4oA/IGB7Ym9vbGVhbnxDYWNoZX1gIOKAPyBJZiB0cnVlLCBhIGRlZmF1bHQgJGh0dHAgY2FjaGUgd2lsbCBiZSB1c2VkIHRvIGNhY2hlIHRoZQ0KICAgICAqICAgICAgR0VUIHJlcXVlc3QsIG90aGVyd2lzZSBpZiBhIGNhY2hlIGluc3RhbmNlIGJ1aWx0IHdpdGgNCiAgICAgKiAgICAgIHtAbGluayBuZy4kY2FjaGVGYWN0b3J5ICRjYWNoZUZhY3Rvcnl9LCB0aGlzIGNhY2hlIHdpbGwgYmUgdXNlZCBmb3INCiAgICAgKiAgICAgIGNhY2hpbmcuDQogICAgICogICAgLSAqKnRpbWVvdXQqKiDigD8gYHtudW1iZXJ8UHJvbWlzZX1gIOKAPyB0aW1lb3V0IGluIG1pbGxpc2Vjb25kcywgb3Ige0BsaW5rIG5nLiRxIHByb21pc2V9DQogICAgICogICAgICB0aGF0IHNob3VsZCBhYm9ydCB0aGUgcmVxdWVzdCB3aGVuIHJlc29sdmVkLg0KICAgICAqICAgIC0gKip3aXRoQ3JlZGVudGlhbHMqKiAtIGB7Ym9vbGVhbn1gIC0gd2hldGhlciB0byBzZXQgdGhlIGB3aXRoQ3JlZGVudGlhbHNgIGZsYWcgb24gdGhlDQogICAgICogICAgICBYSFIgb2JqZWN0LiBTZWUgW3JlcXVlc3RzIHdpdGggY3JlZGVudGlhbHNdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0hUVFAvQWNjZXNzX2NvbnRyb2xfQ09SUyNSZXF1ZXN0c193aXRoX2NyZWRlbnRpYWxzKQ0KICAgICAqICAgICAgZm9yIG1vcmUgaW5mb3JtYXRpb24uDQogICAgICogICAgLSAqKnJlc3BvbnNlVHlwZSoqIC0gYHtzdHJpbmd9YCAtIHNlZQ0KICAgICAqICAgICAgW3JlcXVlc3RUeXBlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL0RPTS9YTUxIdHRwUmVxdWVzdCNyZXNwb25zZVR5cGUpLg0KICAgICAqDQogICAgICogQHJldHVybnMge0h0dHBQcm9taXNlfSBSZXR1cm5zIGEge0BsaW5rIG5nLiRxIHByb21pc2V9IG9iamVjdCB3aXRoIHRoZQ0KICAgICAqICAgc3RhbmRhcmQgYHRoZW5gIG1ldGhvZCBhbmQgdHdvIGh0dHAgc3BlY2lmaWMgbWV0aG9kczogYHN1Y2Nlc3NgIGFuZCBgZXJyb3JgLiBUaGUgYHRoZW5gDQogICAgICogICBtZXRob2QgdGFrZXMgdHdvIGFyZ3VtZW50cyBhIHN1Y2Nlc3MgYW5kIGFuIGVycm9yIGNhbGxiYWNrIHdoaWNoIHdpbGwgYmUgY2FsbGVkIHdpdGggYQ0KICAgICAqICAgcmVzcG9uc2Ugb2JqZWN0LiBUaGUgYHN1Y2Nlc3NgIGFuZCBgZXJyb3JgIG1ldGhvZHMgdGFrZSBhIHNpbmdsZSBhcmd1bWVudCAtIGEgZnVuY3Rpb24gdGhhdA0KICAgICAqICAgd2lsbCBiZSBjYWxsZWQgd2hlbiB0aGUgcmVxdWVzdCBzdWNjZWVkcyBvciBmYWlscyByZXNwZWN0aXZlbHkuIFRoZSBhcmd1bWVudHMgcGFzc2VkIGludG8NCiAgICAgKiAgIHRoZXNlIGZ1bmN0aW9ucyBhcmUgZGVzdHJ1Y3R1cmVkIHJlcHJlc2VudGF0aW9uIG9mIHRoZSByZXNwb25zZSBvYmplY3QgcGFzc2VkIGludG8gdGhlDQogICAgICogICBgdGhlbmAgbWV0aG9kLiBUaGUgcmVzcG9uc2Ugb2JqZWN0IGhhcyB0aGVzZSBwcm9wZXJ0aWVzOg0KICAgICAqDQogICAgICogICAtICoqZGF0YSoqIOKAPyBge3N0cmluZ3xPYmplY3R9YCDigD8gVGhlIHJlc3BvbnNlIGJvZHkgdHJhbnNmb3JtZWQgd2l0aCB0aGUgdHJhbnNmb3JtDQogICAgICogICAgIGZ1bmN0aW9ucy4NCiAgICAgKiAgIC0gKipzdGF0dXMqKiDigD8gYHtudW1iZXJ9YCDigD8gSFRUUCBzdGF0dXMgY29kZSBvZiB0aGUgcmVzcG9uc2UuDQogICAgICogICAtICoqaGVhZGVycyoqIOKAPyBge2Z1bmN0aW9uKFtoZWFkZXJOYW1lXSl9YCDigD8gSGVhZGVyIGdldHRlciBmdW5jdGlvbi4NCiAgICAgKiAgIC0gKipjb25maWcqKiDigD8gYHtPYmplY3R9YCDigD8gVGhlIGNvbmZpZ3VyYXRpb24gb2JqZWN0IHRoYXQgd2FzIHVzZWQgdG8gZ2VuZXJhdGUgdGhlIHJlcXVlc3QuDQogICAgICogICAtICoqc3RhdHVzVGV4dCoqIOKAPyBge3N0cmluZ31gIOKAPyBIVFRQIHN0YXR1cyB0ZXh0IG9mIHRoZSByZXNwb25zZS4NCiAgICAgKg0KICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPE9iamVjdD59IHBlbmRpbmdSZXF1ZXN0cyBBcnJheSBvZiBjb25maWcgb2JqZWN0cyBmb3IgY3VycmVudGx5IHBlbmRpbmcNCiAgICAgKiAgIHJlcXVlc3RzLiBUaGlzIGlzIHByaW1hcmlseSBtZWFudCB0byBiZSB1c2VkIGZvciBkZWJ1Z2dpbmcgcHVycG9zZXMuDQogICAgICoNCiAgICAgKg0KICAgICAqIEBleGFtcGxlDQo8ZXhhbXBsZSBtb2R1bGU9Imh0dHBFeGFtcGxlIj4NCjxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkZldGNoQ29udHJvbGxlciI+DQogICAgPHNlbGVjdCBuZy1tb2RlbD0ibWV0aG9kIj4NCiAgICAgIDxvcHRpb24+R0VUPC9vcHRpb24+DQogICAgICA8b3B0aW9uPkpTT05QPC9vcHRpb24+DQogICAgPC9zZWxlY3Q+DQogICAgPGlucHV0IHR5cGU9InRleHQiIG5nLW1vZGVsPSJ1cmwiIHNpemU9IjgwIi8+DQogICAgPGJ1dHRvbiBpZD0iZmV0Y2hidG4iIG5nLWNsaWNrPSJmZXRjaCgpIj5mZXRjaDwvYnV0dG9uPjxicj4NCiAgICA8YnV0dG9uIGlkPSJzYW1wbGVnZXRidG4iIG5nLWNsaWNrPSJ1cGRhdGVNb2RlbCgnR0VUJywgJ2h0dHAtaGVsbG8uaHRtbCcpIj5TYW1wbGUgR0VUPC9idXR0b24+DQogICAgPGJ1dHRvbiBpZD0ic2FtcGxlanNvbnBidG4iDQogICAgICBuZy1jbGljaz0idXBkYXRlTW9kZWwoJ0pTT05QJywNCiAgICAgICAgICAgICAgICAgICAgJ2h0dHBzOi8vYW5ndWxhcmpzLm9yZy9ncmVldC5waHA/Y2FsbGJhY2s9SlNPTl9DQUxMQkFDSyZuYW1lPVN1cGVyJTIwSGVybycpIj4NCiAgICAgIFNhbXBsZSBKU09OUA0KICAgIDwvYnV0dG9uPg0KICAgIDxidXR0b24gaWQ9ImludmFsaWRqc29ucGJ0biINCiAgICAgIG5nLWNsaWNrPSJ1cGRhdGVNb2RlbCgnSlNPTlAnLCAnaHR0cHM6Ly9hbmd1bGFyanMub3JnL2RvZXNudGV4aXN0JmNhbGxiYWNrPUpTT05fQ0FMTEJBQ0snKSI+DQogICAgICAgIEludmFsaWQgSlNPTlANCiAgICAgIDwvYnV0dG9uPg0KICAgIDxwcmU+aHR0cCBzdGF0dXMgY29kZToge3tzdGF0dXN9fTwvcHJlPg0KICAgIDxwcmU+aHR0cCByZXNwb25zZSBkYXRhOiB7e2RhdGF9fTwvcHJlPg0KICA8L2Rpdj4NCjwvZmlsZT4NCjxmaWxlIG5hbWU9InNjcmlwdC5qcyI+DQogIGFuZ3VsYXIubW9kdWxlKCdodHRwRXhhbXBsZScsIFtdKQ0KICAgIC5jb250cm9sbGVyKCdGZXRjaENvbnRyb2xsZXInLCBbJyRzY29wZScsICckaHR0cCcsICckdGVtcGxhdGVDYWNoZScsDQogICAgICBmdW5jdGlvbigkc2NvcGUsICRodHRwLCAkdGVtcGxhdGVDYWNoZSkgew0KICAgICAgICAkc2NvcGUubWV0aG9kID0gJ0dFVCc7DQogICAgICAgICRzY29wZS51cmwgPSAnaHR0cC1oZWxsby5odG1sJzsNCg0KICAgICAgICAkc2NvcGUuZmV0Y2ggPSBmdW5jdGlvbigpIHsNCiAgICAgICAgICAkc2NvcGUuY29kZSA9IG51bGw7DQogICAgICAgICAgJHNjb3BlLnJlc3BvbnNlID0gbnVsbDsNCg0KICAgICAgICAgICRodHRwKHttZXRob2Q6ICRzY29wZS5tZXRob2QsIHVybDogJHNjb3BlLnVybCwgY2FjaGU6ICR0ZW1wbGF0ZUNhY2hlfSkuDQogICAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uKGRhdGEsIHN0YXR1cykgew0KICAgICAgICAgICAgICAkc2NvcGUuc3RhdHVzID0gc3RhdHVzOw0KICAgICAgICAgICAgICAkc2NvcGUuZGF0YSA9IGRhdGE7DQogICAgICAgICAgICB9KS4NCiAgICAgICAgICAgIGVycm9yKGZ1bmN0aW9uKGRhdGEsIHN0YXR1cykgew0KICAgICAgICAgICAgICAkc2NvcGUuZGF0YSA9IGRhdGEgfHwgIlJlcXVlc3QgZmFpbGVkIjsNCiAgICAgICAgICAgICAgJHNjb3BlLnN0YXR1cyA9IHN0YXR1czsNCiAgICAgICAgICB9KTsNCiAgICAgICAgfTsNCg0KICAgICAgICAkc2NvcGUudXBkYXRlTW9kZWwgPSBmdW5jdGlvbihtZXRob2QsIHVybCkgew0KICAgICAgICAgICRzY29wZS5tZXRob2QgPSBtZXRob2Q7DQogICAgICAgICAgJHNjb3BlLnVybCA9IHVybDsNCiAgICAgICAgfTsNCiAgICAgIH1dKTsNCjwvZmlsZT4NCjxmaWxlIG5hbWU9Imh0dHAtaGVsbG8uaHRtbCI+DQogIEhlbGxvLCAkaHR0cCENCjwvZmlsZT4NCjxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICB2YXIgc3RhdHVzID0gZWxlbWVudChieS5iaW5kaW5nKCdzdGF0dXMnKSk7DQogIHZhciBkYXRhID0gZWxlbWVudChieS5iaW5kaW5nKCdkYXRhJykpOw0KICB2YXIgZmV0Y2hCdG4gPSBlbGVtZW50KGJ5LmlkKCdmZXRjaGJ0bicpKTsNCiAgdmFyIHNhbXBsZUdldEJ0biA9IGVsZW1lbnQoYnkuaWQoJ3NhbXBsZWdldGJ0bicpKTsNCiAgdmFyIHNhbXBsZUpzb25wQnRuID0gZWxlbWVudChieS5pZCgnc2FtcGxlanNvbnBidG4nKSk7DQogIHZhciBpbnZhbGlkSnNvbnBCdG4gPSBlbGVtZW50KGJ5LmlkKCdpbnZhbGlkanNvbnBidG4nKSk7DQoNCiAgaXQoJ3Nob3VsZCBtYWtlIGFuIHhociBHRVQgcmVxdWVzdCcsIGZ1bmN0aW9uKCkgew0KICAgIHNhbXBsZUdldEJ0bi5jbGljaygpOw0KICAgIGZldGNoQnRuLmNsaWNrKCk7DQogICAgZXhwZWN0KHN0YXR1cy5nZXRUZXh0KCkpLnRvTWF0Y2goJzIwMCcpOw0KICAgIGV4cGVjdChkYXRhLmdldFRleHQoKSkudG9NYXRjaCgvSGVsbG8sIFwkaHR0cCEvKTsNCiAgfSk7DQoNCi8vIENvbW1lbnRlZCBvdXQgZHVlIHRvIGZsYWtlcy4gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIuanMvaXNzdWVzLzkxODUNCi8vIGl0KCdzaG91bGQgbWFrZSBhIEpTT05QIHJlcXVlc3QgdG8gYW5ndWxhcmpzLm9yZycsIGZ1bmN0aW9uKCkgew0KLy8gICBzYW1wbGVKc29ucEJ0bi5jbGljaygpOw0KLy8gICBmZXRjaEJ0bi5jbGljaygpOw0KLy8gICBleHBlY3Qoc3RhdHVzLmdldFRleHQoKSkudG9NYXRjaCgnMjAwJyk7DQovLyAgIGV4cGVjdChkYXRhLmdldFRleHQoKSkudG9NYXRjaCgvU3VwZXIgSGVybyEvKTsNCi8vIH0pOw0KDQogIGl0KCdzaG91bGQgbWFrZSBKU09OUCByZXF1ZXN0IHRvIGludmFsaWQgVVJMIGFuZCBpbnZva2UgdGhlIGVycm9yIGhhbmRsZXInLA0KICAgICAgZnVuY3Rpb24oKSB7DQogICAgaW52YWxpZEpzb25wQnRuLmNsaWNrKCk7DQogICAgZmV0Y2hCdG4uY2xpY2soKTsNCiAgICBleHBlY3Qoc3RhdHVzLmdldFRleHQoKSkudG9NYXRjaCgnMCcpOw0KICAgIGV4cGVjdChkYXRhLmdldFRleHQoKSkudG9NYXRjaCgnUmVxdWVzdCBmYWlsZWQnKTsNCiAgfSk7DQo8L2ZpbGU+DQo8L2V4YW1wbGU+DQogICAgICovDQogICAgZnVuY3Rpb24gJGh0dHAocmVxdWVzdENvbmZpZykgew0KDQogICAgICBpZiAoIWFuZ3VsYXIuaXNPYmplY3QocmVxdWVzdENvbmZpZykpIHsNCiAgICAgICAgdGhyb3cgbWluRXJyKCckaHR0cCcpKCdiYWRyZXEnLCAnSHR0cCByZXF1ZXN0IGNvbmZpZ3VyYXRpb24gbXVzdCBiZSBhbiBvYmplY3QuICBSZWNlaXZlZDogezB9JywgcmVxdWVzdENvbmZpZyk7DQogICAgICB9DQoNCiAgICAgIHZhciBjb25maWcgPSBleHRlbmQoew0KICAgICAgICBtZXRob2Q6ICdnZXQnLA0KICAgICAgICB0cmFuc2Zvcm1SZXF1ZXN0OiBkZWZhdWx0cy50cmFuc2Zvcm1SZXF1ZXN0LA0KICAgICAgICB0cmFuc2Zvcm1SZXNwb25zZTogZGVmYXVsdHMudHJhbnNmb3JtUmVzcG9uc2UNCiAgICAgIH0sIHJlcXVlc3RDb25maWcpOw0KDQogICAgICBjb25maWcuaGVhZGVycyA9IG1lcmdlSGVhZGVycyhyZXF1ZXN0Q29uZmlnKTsNCiAgICAgIGNvbmZpZy5tZXRob2QgPSB1cHBlcmNhc2UoY29uZmlnLm1ldGhvZCk7DQoNCiAgICAgIHZhciBzZXJ2ZXJSZXF1ZXN0ID0gZnVuY3Rpb24oY29uZmlnKSB7DQogICAgICAgIHZhciBoZWFkZXJzID0gY29uZmlnLmhlYWRlcnM7DQogICAgICAgIHZhciByZXFEYXRhID0gdHJhbnNmb3JtRGF0YShjb25maWcuZGF0YSwgaGVhZGVyc0dldHRlcihoZWFkZXJzKSwgdW5kZWZpbmVkLCBjb25maWcudHJhbnNmb3JtUmVxdWVzdCk7DQoNCiAgICAgICAgLy8gc3RyaXAgY29udGVudC10eXBlIGlmIGRhdGEgaXMgdW5kZWZpbmVkDQogICAgICAgIGlmIChpc1VuZGVmaW5lZChyZXFEYXRhKSkgew0KICAgICAgICAgIGZvckVhY2goaGVhZGVycywgZnVuY3Rpb24odmFsdWUsIGhlYWRlcikgew0KICAgICAgICAgICAgaWYgKGxvd2VyY2FzZShoZWFkZXIpID09PSAnY29udGVudC10eXBlJykgew0KICAgICAgICAgICAgICAgIGRlbGV0ZSBoZWFkZXJzW2hlYWRlcl07DQogICAgICAgICAgICB9DQogICAgICAgICAgfSk7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoaXNVbmRlZmluZWQoY29uZmlnLndpdGhDcmVkZW50aWFscykgJiYgIWlzVW5kZWZpbmVkKGRlZmF1bHRzLndpdGhDcmVkZW50aWFscykpIHsNCiAgICAgICAgICBjb25maWcud2l0aENyZWRlbnRpYWxzID0gZGVmYXVsdHMud2l0aENyZWRlbnRpYWxzOw0KICAgICAgICB9DQoNCiAgICAgICAgLy8gc2VuZCByZXF1ZXN0DQogICAgICAgIHJldHVybiBzZW5kUmVxKGNvbmZpZywgcmVxRGF0YSkudGhlbih0cmFuc2Zvcm1SZXNwb25zZSwgdHJhbnNmb3JtUmVzcG9uc2UpOw0KICAgICAgfTsNCg0KICAgICAgdmFyIGNoYWluID0gW3NlcnZlclJlcXVlc3QsIHVuZGVmaW5lZF07DQogICAgICB2YXIgcHJvbWlzZSA9ICRxLndoZW4oY29uZmlnKTsNCg0KICAgICAgLy8gYXBwbHkgaW50ZXJjZXB0b3JzDQogICAgICBmb3JFYWNoKHJldmVyc2VkSW50ZXJjZXB0b3JzLCBmdW5jdGlvbihpbnRlcmNlcHRvcikgew0KICAgICAgICBpZiAoaW50ZXJjZXB0b3IucmVxdWVzdCB8fCBpbnRlcmNlcHRvci5yZXF1ZXN0RXJyb3IpIHsNCiAgICAgICAgICBjaGFpbi51bnNoaWZ0KGludGVyY2VwdG9yLnJlcXVlc3QsIGludGVyY2VwdG9yLnJlcXVlc3RFcnJvcik7DQogICAgICAgIH0NCiAgICAgICAgaWYgKGludGVyY2VwdG9yLnJlc3BvbnNlIHx8IGludGVyY2VwdG9yLnJlc3BvbnNlRXJyb3IpIHsNCiAgICAgICAgICBjaGFpbi5wdXNoKGludGVyY2VwdG9yLnJlc3BvbnNlLCBpbnRlcmNlcHRvci5yZXNwb25zZUVycm9yKTsNCiAgICAgICAgfQ0KICAgICAgfSk7DQoNCiAgICAgIHdoaWxlIChjaGFpbi5sZW5ndGgpIHsNCiAgICAgICAgdmFyIHRoZW5GbiA9IGNoYWluLnNoaWZ0KCk7DQogICAgICAgIHZhciByZWplY3RGbiA9IGNoYWluLnNoaWZ0KCk7DQoNCiAgICAgICAgcHJvbWlzZSA9IHByb21pc2UudGhlbih0aGVuRm4sIHJlamVjdEZuKTsNCiAgICAgIH0NCg0KICAgICAgcHJvbWlzZS5zdWNjZXNzID0gZnVuY3Rpb24oZm4pIHsNCiAgICAgICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7DQogICAgICAgICAgZm4ocmVzcG9uc2UuZGF0YSwgcmVzcG9uc2Uuc3RhdHVzLCByZXNwb25zZS5oZWFkZXJzLCBjb25maWcpOw0KICAgICAgICB9KTsNCiAgICAgICAgcmV0dXJuIHByb21pc2U7DQogICAgICB9Ow0KDQogICAgICBwcm9taXNlLmVycm9yID0gZnVuY3Rpb24oZm4pIHsNCiAgICAgICAgcHJvbWlzZS50aGVuKG51bGwsIGZ1bmN0aW9uKHJlc3BvbnNlKSB7DQogICAgICAgICAgZm4ocmVzcG9uc2UuZGF0YSwgcmVzcG9uc2Uuc3RhdHVzLCByZXNwb25zZS5oZWFkZXJzLCBjb25maWcpOw0KICAgICAgICB9KTsNCiAgICAgICAgcmV0dXJuIHByb21pc2U7DQogICAgICB9Ow0KDQogICAgICByZXR1cm4gcHJvbWlzZTsNCg0KICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUmVzcG9uc2UocmVzcG9uc2UpIHsNCiAgICAgICAgLy8gbWFrZSBhIGNvcHkgc2luY2UgdGhlIHJlc3BvbnNlIG11c3QgYmUgY2FjaGVhYmxlDQogICAgICAgIHZhciByZXNwID0gZXh0ZW5kKHt9LCByZXNwb25zZSk7DQogICAgICAgIGlmICghcmVzcG9uc2UuZGF0YSkgew0KICAgICAgICAgIHJlc3AuZGF0YSA9IHJlc3BvbnNlLmRhdGE7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgcmVzcC5kYXRhID0gdHJhbnNmb3JtRGF0YShyZXNwb25zZS5kYXRhLCByZXNwb25zZS5oZWFkZXJzLCByZXNwb25zZS5zdGF0dXMsIGNvbmZpZy50cmFuc2Zvcm1SZXNwb25zZSk7DQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuIChpc1N1Y2Nlc3MocmVzcG9uc2Uuc3RhdHVzKSkNCiAgICAgICAgICA/IHJlc3ANCiAgICAgICAgICA6ICRxLnJlamVjdChyZXNwKTsNCiAgICAgIH0NCg0KICAgICAgZnVuY3Rpb24gZXhlY3V0ZUhlYWRlckZucyhoZWFkZXJzKSB7DQogICAgICAgIHZhciBoZWFkZXJDb250ZW50LCBwcm9jZXNzZWRIZWFkZXJzID0ge307DQoNCiAgICAgICAgZm9yRWFjaChoZWFkZXJzLCBmdW5jdGlvbihoZWFkZXJGbiwgaGVhZGVyKSB7DQogICAgICAgICAgaWYgKGlzRnVuY3Rpb24oaGVhZGVyRm4pKSB7DQogICAgICAgICAgICBoZWFkZXJDb250ZW50ID0gaGVhZGVyRm4oKTsNCiAgICAgICAgICAgIGlmIChoZWFkZXJDb250ZW50ICE9IG51bGwpIHsNCiAgICAgICAgICAgICAgcHJvY2Vzc2VkSGVhZGVyc1toZWFkZXJdID0gaGVhZGVyQ29udGVudDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgcHJvY2Vzc2VkSGVhZGVyc1toZWFkZXJdID0gaGVhZGVyRm47DQogICAgICAgICAgfQ0KICAgICAgICB9KTsNCg0KICAgICAgICByZXR1cm4gcHJvY2Vzc2VkSGVhZGVyczsNCiAgICAgIH0NCg0KICAgICAgZnVuY3Rpb24gbWVyZ2VIZWFkZXJzKGNvbmZpZykgew0KICAgICAgICB2YXIgZGVmSGVhZGVycyA9IGRlZmF1bHRzLmhlYWRlcnMsDQogICAgICAgICAgICByZXFIZWFkZXJzID0gZXh0ZW5kKHt9LCBjb25maWcuaGVhZGVycyksDQogICAgICAgICAgICBkZWZIZWFkZXJOYW1lLCBsb3dlcmNhc2VEZWZIZWFkZXJOYW1lLCByZXFIZWFkZXJOYW1lOw0KDQogICAgICAgIGRlZkhlYWRlcnMgPSBleHRlbmQoe30sIGRlZkhlYWRlcnMuY29tbW9uLCBkZWZIZWFkZXJzW2xvd2VyY2FzZShjb25maWcubWV0aG9kKV0pOw0KDQogICAgICAgIC8vIHVzaW5nIGZvci1pbiBpbnN0ZWFkIG9mIGZvckVhY2ggdG8gYXZvaWQgdW5lY2Vzc2FyeSBpdGVyYXRpb24gYWZ0ZXIgaGVhZGVyIGhhcyBiZWVuIGZvdW5kDQogICAgICAgIGRlZmF1bHRIZWFkZXJzSXRlcmF0aW9uOg0KICAgICAgICBmb3IgKGRlZkhlYWRlck5hbWUgaW4gZGVmSGVhZGVycykgew0KICAgICAgICAgIGxvd2VyY2FzZURlZkhlYWRlck5hbWUgPSBsb3dlcmNhc2UoZGVmSGVhZGVyTmFtZSk7DQoNCiAgICAgICAgICBmb3IgKHJlcUhlYWRlck5hbWUgaW4gcmVxSGVhZGVycykgew0KICAgICAgICAgICAgaWYgKGxvd2VyY2FzZShyZXFIZWFkZXJOYW1lKSA9PT0gbG93ZXJjYXNlRGVmSGVhZGVyTmFtZSkgew0KICAgICAgICAgICAgICBjb250aW51ZSBkZWZhdWx0SGVhZGVyc0l0ZXJhdGlvbjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9DQoNCiAgICAgICAgICByZXFIZWFkZXJzW2RlZkhlYWRlck5hbWVdID0gZGVmSGVhZGVyc1tkZWZIZWFkZXJOYW1lXTsNCiAgICAgICAgfQ0KDQogICAgICAgIC8vIGV4ZWN1dGUgaWYgaGVhZGVyIHZhbHVlIGlzIGEgZnVuY3Rpb24gZm9yIG1lcmdlZCBoZWFkZXJzDQogICAgICAgIHJldHVybiBleGVjdXRlSGVhZGVyRm5zKHJlcUhlYWRlcnMpOw0KICAgICAgfQ0KICAgIH0NCg0KICAgICRodHRwLnBlbmRpbmdSZXF1ZXN0cyA9IFtdOw0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRodHRwI2dldA0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRjdXQgbWV0aG9kIHRvIHBlcmZvcm0gYEdFVGAgcmVxdWVzdC4NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgUmVsYXRpdmUgb3IgYWJzb2x1dGUgVVJMIHNwZWNpZnlpbmcgdGhlIGRlc3RpbmF0aW9uIG9mIHRoZSByZXF1ZXN0DQogICAgICogQHBhcmFtIHtPYmplY3Q9fSBjb25maWcgT3B0aW9uYWwgY29uZmlndXJhdGlvbiBvYmplY3QNCiAgICAgKiBAcmV0dXJucyB7SHR0cFByb21pc2V9IEZ1dHVyZSBvYmplY3QNCiAgICAgKi8NCg0KICAgIC8qKg0KICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgKiBAbmFtZSAkaHR0cCNkZWxldGUNCiAgICAgKg0KICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAqIFNob3J0Y3V0IG1ldGhvZCB0byBwZXJmb3JtIGBERUxFVEVgIHJlcXVlc3QuDQogICAgICoNCiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIFJlbGF0aXZlIG9yIGFic29sdXRlIFVSTCBzcGVjaWZ5aW5nIHRoZSBkZXN0aW5hdGlvbiBvZiB0aGUgcmVxdWVzdA0KICAgICAqIEBwYXJhbSB7T2JqZWN0PX0gY29uZmlnIE9wdGlvbmFsIGNvbmZpZ3VyYXRpb24gb2JqZWN0DQogICAgICogQHJldHVybnMge0h0dHBQcm9taXNlfSBGdXR1cmUgb2JqZWN0DQogICAgICovDQoNCiAgICAvKioNCiAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICogQG5hbWUgJGh0dHAjaGVhZA0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRjdXQgbWV0aG9kIHRvIHBlcmZvcm0gYEhFQURgIHJlcXVlc3QuDQogICAgICoNCiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIFJlbGF0aXZlIG9yIGFic29sdXRlIFVSTCBzcGVjaWZ5aW5nIHRoZSBkZXN0aW5hdGlvbiBvZiB0aGUgcmVxdWVzdA0KICAgICAqIEBwYXJhbSB7T2JqZWN0PX0gY29uZmlnIE9wdGlvbmFsIGNvbmZpZ3VyYXRpb24gb2JqZWN0DQogICAgICogQHJldHVybnMge0h0dHBQcm9taXNlfSBGdXR1cmUgb2JqZWN0DQogICAgICovDQoNCiAgICAvKioNCiAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICogQG5hbWUgJGh0dHAjanNvbnANCiAgICAgKg0KICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAqIFNob3J0Y3V0IG1ldGhvZCB0byBwZXJmb3JtIGBKU09OUGAgcmVxdWVzdC4NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgUmVsYXRpdmUgb3IgYWJzb2x1dGUgVVJMIHNwZWNpZnlpbmcgdGhlIGRlc3RpbmF0aW9uIG9mIHRoZSByZXF1ZXN0Lg0KICAgICAqICAgICAgICAgICAgICAgICAgICAgVGhlIG5hbWUgb2YgdGhlIGNhbGxiYWNrIHNob3VsZCBiZSB0aGUgc3RyaW5nIGBKU09OX0NBTExCQUNLYC4NCiAgICAgKiBAcGFyYW0ge09iamVjdD19IGNvbmZpZyBPcHRpb25hbCBjb25maWd1cmF0aW9uIG9iamVjdA0KICAgICAqIEByZXR1cm5zIHtIdHRwUHJvbWlzZX0gRnV0dXJlIG9iamVjdA0KICAgICAqLw0KICAgIGNyZWF0ZVNob3J0TWV0aG9kcygnZ2V0JywgJ2RlbGV0ZScsICdoZWFkJywgJ2pzb25wJyk7DQoNCiAgICAvKioNCiAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICogQG5hbWUgJGh0dHAjcG9zdA0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRjdXQgbWV0aG9kIHRvIHBlcmZvcm0gYFBPU1RgIHJlcXVlc3QuDQogICAgICoNCiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIFJlbGF0aXZlIG9yIGFic29sdXRlIFVSTCBzcGVjaWZ5aW5nIHRoZSBkZXN0aW5hdGlvbiBvZiB0aGUgcmVxdWVzdA0KICAgICAqIEBwYXJhbSB7Kn0gZGF0YSBSZXF1ZXN0IGNvbnRlbnQNCiAgICAgKiBAcGFyYW0ge09iamVjdD19IGNvbmZpZyBPcHRpb25hbCBjb25maWd1cmF0aW9uIG9iamVjdA0KICAgICAqIEByZXR1cm5zIHtIdHRwUHJvbWlzZX0gRnV0dXJlIG9iamVjdA0KICAgICAqLw0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRodHRwI3B1dA0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRjdXQgbWV0aG9kIHRvIHBlcmZvcm0gYFBVVGAgcmVxdWVzdC4NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgUmVsYXRpdmUgb3IgYWJzb2x1dGUgVVJMIHNwZWNpZnlpbmcgdGhlIGRlc3RpbmF0aW9uIG9mIHRoZSByZXF1ZXN0DQogICAgICogQHBhcmFtIHsqfSBkYXRhIFJlcXVlc3QgY29udGVudA0KICAgICAqIEBwYXJhbSB7T2JqZWN0PX0gY29uZmlnIE9wdGlvbmFsIGNvbmZpZ3VyYXRpb24gb2JqZWN0DQogICAgICogQHJldHVybnMge0h0dHBQcm9taXNlfSBGdXR1cmUgb2JqZWN0DQogICAgICovDQoNCiAgICAgLyoqDQogICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICogQG5hbWUgJGh0dHAjcGF0Y2gNCiAgICAgICoNCiAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAqIFNob3J0Y3V0IG1ldGhvZCB0byBwZXJmb3JtIGBQQVRDSGAgcmVxdWVzdC4NCiAgICAgICoNCiAgICAgICogQHBhcmFtIHtzdHJpbmd9IHVybCBSZWxhdGl2ZSBvciBhYnNvbHV0ZSBVUkwgc3BlY2lmeWluZyB0aGUgZGVzdGluYXRpb24gb2YgdGhlIHJlcXVlc3QNCiAgICAgICogQHBhcmFtIHsqfSBkYXRhIFJlcXVlc3QgY29udGVudA0KICAgICAgKiBAcGFyYW0ge09iamVjdD19IGNvbmZpZyBPcHRpb25hbCBjb25maWd1cmF0aW9uIG9iamVjdA0KICAgICAgKiBAcmV0dXJucyB7SHR0cFByb21pc2V9IEZ1dHVyZSBvYmplY3QNCiAgICAgICovDQogICAgY3JlYXRlU2hvcnRNZXRob2RzV2l0aERhdGEoJ3Bvc3QnLCAncHV0JywgJ3BhdGNoJyk7DQoNCiAgICAgICAgLyoqDQogICAgICAgICAqIEBuZ2RvYyBwcm9wZXJ0eQ0KICAgICAgICAgKiBAbmFtZSAkaHR0cCNkZWZhdWx0cw0KICAgICAgICAgKg0KICAgICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAgICogUnVudGltZSBlcXVpdmFsZW50IG9mIHRoZSBgJGh0dHBQcm92aWRlci5kZWZhdWx0c2AgcHJvcGVydHkuIEFsbG93cyBjb25maWd1cmF0aW9uIG9mDQogICAgICAgICAqIGRlZmF1bHQgaGVhZGVycywgd2l0aENyZWRlbnRpYWxzIGFzIHdlbGwgYXMgcmVxdWVzdCBhbmQgcmVzcG9uc2UgdHJhbnNmb3JtYXRpb25zLg0KICAgICAgICAgKg0KICAgICAgICAgKiBTZWUgIlNldHRpbmcgSFRUUCBIZWFkZXJzIiBhbmQgIlRyYW5zZm9ybWluZyBSZXF1ZXN0cyBhbmQgUmVzcG9uc2VzIiBzZWN0aW9ucyBhYm92ZS4NCiAgICAgICAgICovDQogICAgJGh0dHAuZGVmYXVsdHMgPSBkZWZhdWx0czsNCg0KDQogICAgcmV0dXJuICRodHRwOw0KDQoNCiAgICBmdW5jdGlvbiBjcmVhdGVTaG9ydE1ldGhvZHMobmFtZXMpIHsNCiAgICAgIGZvckVhY2goYXJndW1lbnRzLCBmdW5jdGlvbihuYW1lKSB7DQogICAgICAgICRodHRwW25hbWVdID0gZnVuY3Rpb24odXJsLCBjb25maWcpIHsNCiAgICAgICAgICByZXR1cm4gJGh0dHAoZXh0ZW5kKGNvbmZpZyB8fCB7fSwgew0KICAgICAgICAgICAgbWV0aG9kOiBuYW1lLA0KICAgICAgICAgICAgdXJsOiB1cmwNCiAgICAgICAgICB9KSk7DQogICAgICAgIH07DQogICAgICB9KTsNCiAgICB9DQoNCg0KICAgIGZ1bmN0aW9uIGNyZWF0ZVNob3J0TWV0aG9kc1dpdGhEYXRhKG5hbWUpIHsNCiAgICAgIGZvckVhY2goYXJndW1lbnRzLCBmdW5jdGlvbihuYW1lKSB7DQogICAgICAgICRodHRwW25hbWVdID0gZnVuY3Rpb24odXJsLCBkYXRhLCBjb25maWcpIHsNCiAgICAgICAgICByZXR1cm4gJGh0dHAoZXh0ZW5kKGNvbmZpZyB8fCB7fSwgew0KICAgICAgICAgICAgbWV0aG9kOiBuYW1lLA0KICAgICAgICAgICAgdXJsOiB1cmwsDQogICAgICAgICAgICBkYXRhOiBkYXRhDQogICAgICAgICAgfSkpOw0KICAgICAgICB9Ow0KICAgICAgfSk7DQogICAgfQ0KDQoNCiAgICAvKioNCiAgICAgKiBNYWtlcyB0aGUgcmVxdWVzdC4NCiAgICAgKg0KICAgICAqICEhISBBQ0NFU1NFUyBDTE9TVVJFIFZBUlM6DQogICAgICogJGh0dHBCYWNrZW5kLCBkZWZhdWx0cywgJGxvZywgJHJvb3RTY29wZSwgZGVmYXVsdENhY2hlLCAkaHR0cC5wZW5kaW5nUmVxdWVzdHMNCiAgICAgKi8NCiAgICBmdW5jdGlvbiBzZW5kUmVxKGNvbmZpZywgcmVxRGF0YSkgew0KICAgICAgdmFyIGRlZmVycmVkID0gJHEuZGVmZXIoKSwNCiAgICAgICAgICBwcm9taXNlID0gZGVmZXJyZWQucHJvbWlzZSwNCiAgICAgICAgICBjYWNoZSwNCiAgICAgICAgICBjYWNoZWRSZXNwLA0KICAgICAgICAgIHJlcUhlYWRlcnMgPSBjb25maWcuaGVhZGVycywNCiAgICAgICAgICB1cmwgPSBidWlsZFVybChjb25maWcudXJsLCBjb25maWcucGFyYW1zKTsNCg0KICAgICAgJGh0dHAucGVuZGluZ1JlcXVlc3RzLnB1c2goY29uZmlnKTsNCiAgICAgIHByb21pc2UudGhlbihyZW1vdmVQZW5kaW5nUmVxLCByZW1vdmVQZW5kaW5nUmVxKTsNCg0KDQogICAgICBpZiAoKGNvbmZpZy5jYWNoZSB8fCBkZWZhdWx0cy5jYWNoZSkgJiYgY29uZmlnLmNhY2hlICE9PSBmYWxzZSAmJg0KICAgICAgICAgIChjb25maWcubWV0aG9kID09PSAnR0VUJyB8fCBjb25maWcubWV0aG9kID09PSAnSlNPTlAnKSkgew0KICAgICAgICBjYWNoZSA9IGlzT2JqZWN0KGNvbmZpZy5jYWNoZSkgPyBjb25maWcuY2FjaGUNCiAgICAgICAgICAgICAgOiBpc09iamVjdChkZWZhdWx0cy5jYWNoZSkgPyBkZWZhdWx0cy5jYWNoZQ0KICAgICAgICAgICAgICA6IGRlZmF1bHRDYWNoZTsNCiAgICAgIH0NCg0KICAgICAgaWYgKGNhY2hlKSB7DQogICAgICAgIGNhY2hlZFJlc3AgPSBjYWNoZS5nZXQodXJsKTsNCiAgICAgICAgaWYgKGlzRGVmaW5lZChjYWNoZWRSZXNwKSkgew0KICAgICAgICAgIGlmIChpc1Byb21pc2VMaWtlKGNhY2hlZFJlc3ApKSB7DQogICAgICAgICAgICAvLyBjYWNoZWQgcmVxdWVzdCBoYXMgYWxyZWFkeSBiZWVuIHNlbnQsIGJ1dCB0aGVyZSBpcyBubyByZXNwb25zZSB5ZXQNCiAgICAgICAgICAgIGNhY2hlZFJlc3AudGhlbihyZXNvbHZlUHJvbWlzZVdpdGhSZXN1bHQsIHJlc29sdmVQcm9taXNlV2l0aFJlc3VsdCk7DQogICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIC8vIHNlcnZpbmcgZnJvbSBjYWNoZQ0KICAgICAgICAgICAgaWYgKGlzQXJyYXkoY2FjaGVkUmVzcCkpIHsNCiAgICAgICAgICAgICAgcmVzb2x2ZVByb21pc2UoY2FjaGVkUmVzcFsxXSwgY2FjaGVkUmVzcFswXSwgc2hhbGxvd0NvcHkoY2FjaGVkUmVzcFsyXSksIGNhY2hlZFJlc3BbM10pOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgcmVzb2x2ZVByb21pc2UoY2FjaGVkUmVzcCwgMjAwLCB7fSwgJ09LJyk7DQogICAgICAgICAgICB9DQogICAgICAgICAgfQ0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIC8vIHB1dCB0aGUgcHJvbWlzZSBmb3IgdGhlIG5vbi10cmFuc2Zvcm1lZCByZXNwb25zZSBpbnRvIGNhY2hlIGFzIGEgcGxhY2Vob2xkZXINCiAgICAgICAgICBjYWNoZS5wdXQodXJsLCBwcm9taXNlKTsNCiAgICAgICAgfQ0KICAgICAgfQ0KDQoNCiAgICAgIC8vIGlmIHdlIHdvbid0IGhhdmUgdGhlIHJlc3BvbnNlIGluIGNhY2hlLCBzZXQgdGhlIHhzcmYgaGVhZGVycyBhbmQNCiAgICAgIC8vIHNlbmQgdGhlIHJlcXVlc3QgdG8gdGhlIGJhY2tlbmQNCiAgICAgIGlmIChpc1VuZGVmaW5lZChjYWNoZWRSZXNwKSkgew0KICAgICAgICB2YXIgeHNyZlZhbHVlID0gdXJsSXNTYW1lT3JpZ2luKGNvbmZpZy51cmwpDQogICAgICAgICAgICA/ICRicm93c2VyLmNvb2tpZXMoKVtjb25maWcueHNyZkNvb2tpZU5hbWUgfHwgZGVmYXVsdHMueHNyZkNvb2tpZU5hbWVdDQogICAgICAgICAgICA6IHVuZGVmaW5lZDsNCiAgICAgICAgaWYgKHhzcmZWYWx1ZSkgew0KICAgICAgICAgIHJlcUhlYWRlcnNbKGNvbmZpZy54c3JmSGVhZGVyTmFtZSB8fCBkZWZhdWx0cy54c3JmSGVhZGVyTmFtZSldID0geHNyZlZhbHVlOw0KICAgICAgICB9DQoNCiAgICAgICAgJGh0dHBCYWNrZW5kKGNvbmZpZy5tZXRob2QsIHVybCwgcmVxRGF0YSwgZG9uZSwgcmVxSGVhZGVycywgY29uZmlnLnRpbWVvdXQsDQogICAgICAgICAgICBjb25maWcud2l0aENyZWRlbnRpYWxzLCBjb25maWcucmVzcG9uc2VUeXBlKTsNCiAgICAgIH0NCg0KICAgICAgcmV0dXJuIHByb21pc2U7DQoNCg0KICAgICAgLyoqDQogICAgICAgKiBDYWxsYmFjayByZWdpc3RlcmVkIHRvICRodHRwQmFja2VuZCgpOg0KICAgICAgICogIC0gY2FjaGVzIHRoZSByZXNwb25zZSBpZiBkZXNpcmVkDQogICAgICAgKiAgLSByZXNvbHZlcyB0aGUgcmF3ICRodHRwIHByb21pc2UNCiAgICAgICAqICAtIGNhbGxzICRhcHBseQ0KICAgICAgICovDQogICAgICBmdW5jdGlvbiBkb25lKHN0YXR1cywgcmVzcG9uc2UsIGhlYWRlcnNTdHJpbmcsIHN0YXR1c1RleHQpIHsNCiAgICAgICAgaWYgKGNhY2hlKSB7DQogICAgICAgICAgaWYgKGlzU3VjY2VzcyhzdGF0dXMpKSB7DQogICAgICAgICAgICBjYWNoZS5wdXQodXJsLCBbc3RhdHVzLCByZXNwb25zZSwgcGFyc2VIZWFkZXJzKGhlYWRlcnNTdHJpbmcpLCBzdGF0dXNUZXh0XSk7DQogICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIC8vIHJlbW92ZSBwcm9taXNlIGZyb20gdGhlIGNhY2hlDQogICAgICAgICAgICBjYWNoZS5yZW1vdmUodXJsKTsNCiAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICBmdW5jdGlvbiByZXNvbHZlSHR0cFByb21pc2UoKSB7DQogICAgICAgICAgcmVzb2x2ZVByb21pc2UocmVzcG9uc2UsIHN0YXR1cywgaGVhZGVyc1N0cmluZywgc3RhdHVzVGV4dCk7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAodXNlQXBwbHlBc3luYykgew0KICAgICAgICAgICRyb290U2NvcGUuJGFwcGx5QXN5bmMocmVzb2x2ZUh0dHBQcm9taXNlKTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICByZXNvbHZlSHR0cFByb21pc2UoKTsNCiAgICAgICAgICBpZiAoISRyb290U2NvcGUuJCRwaGFzZSkgJHJvb3RTY29wZS4kYXBwbHkoKTsNCiAgICAgICAgfQ0KICAgICAgfQ0KDQoNCiAgICAgIC8qKg0KICAgICAgICogUmVzb2x2ZXMgdGhlIHJhdyAkaHR0cCBwcm9taXNlLg0KICAgICAgICovDQogICAgICBmdW5jdGlvbiByZXNvbHZlUHJvbWlzZShyZXNwb25zZSwgc3RhdHVzLCBoZWFkZXJzLCBzdGF0dXNUZXh0KSB7DQogICAgICAgIC8vIG5vcm1hbGl6ZSBpbnRlcm5hbCBzdGF0dXNlcyB0byAwDQogICAgICAgIHN0YXR1cyA9IE1hdGgubWF4KHN0YXR1cywgMCk7DQoNCiAgICAgICAgKGlzU3VjY2VzcyhzdGF0dXMpID8gZGVmZXJyZWQucmVzb2x2ZSA6IGRlZmVycmVkLnJlamVjdCkoew0KICAgICAgICAgIGRhdGE6IHJlc3BvbnNlLA0KICAgICAgICAgIHN0YXR1czogc3RhdHVzLA0KICAgICAgICAgIGhlYWRlcnM6IGhlYWRlcnNHZXR0ZXIoaGVhZGVycyksDQogICAgICAgICAgY29uZmlnOiBjb25maWcsDQogICAgICAgICAgc3RhdHVzVGV4dDogc3RhdHVzVGV4dA0KICAgICAgICB9KTsNCiAgICAgIH0NCg0KICAgICAgZnVuY3Rpb24gcmVzb2x2ZVByb21pc2VXaXRoUmVzdWx0KHJlc3VsdCkgew0KICAgICAgICByZXNvbHZlUHJvbWlzZShyZXN1bHQuZGF0YSwgcmVzdWx0LnN0YXR1cywgc2hhbGxvd0NvcHkocmVzdWx0LmhlYWRlcnMoKSksIHJlc3VsdC5zdGF0dXNUZXh0KTsNCiAgICAgIH0NCg0KICAgICAgZnVuY3Rpb24gcmVtb3ZlUGVuZGluZ1JlcSgpIHsNCiAgICAgICAgdmFyIGlkeCA9ICRodHRwLnBlbmRpbmdSZXF1ZXN0cy5pbmRleE9mKGNvbmZpZyk7DQogICAgICAgIGlmIChpZHggIT09IC0xKSAkaHR0cC5wZW5kaW5nUmVxdWVzdHMuc3BsaWNlKGlkeCwgMSk7DQogICAgICB9DQogICAgfQ0KDQoNCiAgICBmdW5jdGlvbiBidWlsZFVybCh1cmwsIHBhcmFtcykgew0KICAgICAgaWYgKCFwYXJhbXMpIHJldHVybiB1cmw7DQogICAgICB2YXIgcGFydHMgPSBbXTsNCiAgICAgIGZvckVhY2hTb3J0ZWQocGFyYW1zLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7DQogICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCBpc1VuZGVmaW5lZCh2YWx1ZSkpIHJldHVybjsNCiAgICAgICAgaWYgKCFpc0FycmF5KHZhbHVlKSkgdmFsdWUgPSBbdmFsdWVdOw0KDQogICAgICAgIGZvckVhY2godmFsdWUsIGZ1bmN0aW9uKHYpIHsNCiAgICAgICAgICBpZiAoaXNPYmplY3QodikpIHsNCiAgICAgICAgICAgIGlmIChpc0RhdGUodikpIHsNCiAgICAgICAgICAgICAgdiA9IHYudG9JU09TdHJpbmcoKTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgIHYgPSB0b0pzb24odik7DQogICAgICAgICAgICB9DQogICAgICAgICAgfQ0KICAgICAgICAgIHBhcnRzLnB1c2goZW5jb2RlVXJpUXVlcnkoa2V5KSArICc9JyArDQogICAgICAgICAgICAgICAgICAgICBlbmNvZGVVcmlRdWVyeSh2KSk7DQogICAgICAgIH0pOw0KICAgICAgfSk7DQogICAgICBpZiAocGFydHMubGVuZ3RoID4gMCkgew0KICAgICAgICB1cmwgKz0gKCh1cmwuaW5kZXhPZignPycpID09IC0xKSA/ICc/JyA6ICcmJykgKyBwYXJ0cy5qb2luKCcmJyk7DQogICAgICB9DQogICAgICByZXR1cm4gdXJsOw0KICAgIH0NCiAgfV07DQp9DQoNCmZ1bmN0aW9uIGNyZWF0ZVhocigpIHsNCiAgICByZXR1cm4gbmV3IHdpbmRvdy5YTUxIdHRwUmVxdWVzdCgpOw0KfQ0KDQovKioNCiAqIEBuZ2RvYyBzZXJ2aWNlDQogKiBAbmFtZSAkaHR0cEJhY2tlbmQNCiAqIEByZXF1aXJlcyAkd2luZG93DQogKiBAcmVxdWlyZXMgJGRvY3VtZW50DQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBIVFRQIGJhY2tlbmQgdXNlZCBieSB0aGUge0BsaW5rIG5nLiRodHRwIHNlcnZpY2V9IHRoYXQgZGVsZWdhdGVzIHRvDQogKiBYTUxIdHRwUmVxdWVzdCBvYmplY3Qgb3IgSlNPTlAgYW5kIGRlYWxzIHdpdGggYnJvd3NlciBpbmNvbXBhdGliaWxpdGllcy4NCiAqDQogKiBZb3Ugc2hvdWxkIG5ldmVyIG5lZWQgdG8gdXNlIHRoaXMgc2VydmljZSBkaXJlY3RseSwgaW5zdGVhZCB1c2UgdGhlIGhpZ2hlci1sZXZlbCBhYnN0cmFjdGlvbnM6DQogKiB7QGxpbmsgbmcuJGh0dHAgJGh0dHB9IG9yIHtAbGluayBuZ1Jlc291cmNlLiRyZXNvdXJjZSAkcmVzb3VyY2V9Lg0KICoNCiAqIER1cmluZyB0ZXN0aW5nIHRoaXMgaW1wbGVtZW50YXRpb24gaXMgc3dhcHBlZCB3aXRoIHtAbGluayBuZ01vY2suJGh0dHBCYWNrZW5kIG1vY2sNCiAqICRodHRwQmFja2VuZH0gd2hpY2ggY2FuIGJlIHRyYWluZWQgd2l0aCByZXNwb25zZXMuDQogKi8NCmZ1bmN0aW9uICRIdHRwQmFja2VuZFByb3ZpZGVyKCkgew0KICB0aGlzLiRnZXQgPSBbJyRicm93c2VyJywgJyR3aW5kb3cnLCAnJGRvY3VtZW50JywgZnVuY3Rpb24oJGJyb3dzZXIsICR3aW5kb3csICRkb2N1bWVudCkgew0KICAgIHJldHVybiBjcmVhdGVIdHRwQmFja2VuZCgkYnJvd3NlciwgY3JlYXRlWGhyLCAkYnJvd3Nlci5kZWZlciwgJHdpbmRvdy5hbmd1bGFyLmNhbGxiYWNrcywgJGRvY3VtZW50WzBdKTsNCiAgfV07DQp9DQoNCmZ1bmN0aW9uIGNyZWF0ZUh0dHBCYWNrZW5kKCRicm93c2VyLCBjcmVhdGVYaHIsICRicm93c2VyRGVmZXIsIGNhbGxiYWNrcywgcmF3RG9jdW1lbnQpIHsNCiAgLy8gVE9ETyh2b2p0YSk6IGZpeCB0aGUgc2lnbmF0dXJlDQogIHJldHVybiBmdW5jdGlvbihtZXRob2QsIHVybCwgcG9zdCwgY2FsbGJhY2ssIGhlYWRlcnMsIHRpbWVvdXQsIHdpdGhDcmVkZW50aWFscywgcmVzcG9uc2VUeXBlKSB7DQogICAgJGJyb3dzZXIuJCRpbmNPdXRzdGFuZGluZ1JlcXVlc3RDb3VudCgpOw0KICAgIHVybCA9IHVybCB8fCAkYnJvd3Nlci51cmwoKTsNCg0KICAgIGlmIChsb3dlcmNhc2UobWV0aG9kKSA9PSAnanNvbnAnKSB7DQogICAgICB2YXIgY2FsbGJhY2tJZCA9ICdfJyArIChjYWxsYmFja3MuY291bnRlcisrKS50b1N0cmluZygzNik7DQogICAgICBjYWxsYmFja3NbY2FsbGJhY2tJZF0gPSBmdW5jdGlvbihkYXRhKSB7DQogICAgICAgIGNhbGxiYWNrc1tjYWxsYmFja0lkXS5kYXRhID0gZGF0YTsNCiAgICAgICAgY2FsbGJhY2tzW2NhbGxiYWNrSWRdLmNhbGxlZCA9IHRydWU7DQogICAgICB9Ow0KDQogICAgICB2YXIganNvbnBEb25lID0ganNvbnBSZXEodXJsLnJlcGxhY2UoJ0pTT05fQ0FMTEJBQ0snLCAnYW5ndWxhci5jYWxsYmFja3MuJyArIGNhbGxiYWNrSWQpLA0KICAgICAgICAgIGNhbGxiYWNrSWQsIGZ1bmN0aW9uKHN0YXR1cywgdGV4dCkgew0KICAgICAgICBjb21wbGV0ZVJlcXVlc3QoY2FsbGJhY2ssIHN0YXR1cywgY2FsbGJhY2tzW2NhbGxiYWNrSWRdLmRhdGEsICIiLCB0ZXh0KTsNCiAgICAgICAgY2FsbGJhY2tzW2NhbGxiYWNrSWRdID0gbm9vcDsNCiAgICAgIH0pOw0KICAgIH0gZWxzZSB7DQoNCiAgICAgIHZhciB4aHIgPSBjcmVhdGVYaHIoKTsNCg0KICAgICAgeGhyLm9wZW4obWV0aG9kLCB1cmwsIHRydWUpOw0KICAgICAgZm9yRWFjaChoZWFkZXJzLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7DQogICAgICAgIGlmIChpc0RlZmluZWQodmFsdWUpKSB7DQogICAgICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihrZXksIHZhbHVlKTsNCiAgICAgICAgfQ0KICAgICAgfSk7DQoNCiAgICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbiByZXF1ZXN0TG9hZGVkKCkgew0KICAgICAgICB2YXIgc3RhdHVzVGV4dCA9IHhoci5zdGF0dXNUZXh0IHx8ICcnOw0KDQogICAgICAgIC8vIHJlc3BvbnNlVGV4dCBpcyB0aGUgb2xkLXNjaG9vbCB3YXkgb2YgcmV0cmlldmluZyByZXNwb25zZSAoc3VwcG9ydGVkIGJ5IElFOCAmIDkpDQogICAgICAgIC8vIHJlc3BvbnNlL3Jlc3BvbnNlVHlwZSBwcm9wZXJ0aWVzIHdlcmUgaW50cm9kdWNlZCBpbiBYSFIgTGV2ZWwyIHNwZWMgKHN1cHBvcnRlZCBieSBJRTEwKQ0KICAgICAgICB2YXIgcmVzcG9uc2UgPSAoJ3Jlc3BvbnNlJyBpbiB4aHIpID8geGhyLnJlc3BvbnNlIDogeGhyLnJlc3BvbnNlVGV4dDsNCg0KICAgICAgICAvLyBub3JtYWxpemUgSUU5IGJ1ZyAoaHR0cDovL2J1Z3MuanF1ZXJ5LmNvbS90aWNrZXQvMTQ1MCkNCiAgICAgICAgdmFyIHN0YXR1cyA9IHhoci5zdGF0dXMgPT09IDEyMjMgPyAyMDQgOiB4aHIuc3RhdHVzOw0KDQogICAgICAgIC8vIGZpeCBzdGF0dXMgY29kZSB3aGVuIGl0IGlzIDAgKDAgc3RhdHVzIGlzIHVuZG9jdW1lbnRlZCkuDQogICAgICAgIC8vIE9jY3VycyB3aGVuIGFjY2Vzc2luZyBmaWxlIHJlc291cmNlcyBvciBvbiBBbmRyb2lkIDQuMSBzdG9jayBicm93c2VyDQogICAgICAgIC8vIHdoaWxlIHJldHJpZXZpbmcgZmlsZXMgZnJvbSBhcHBsaWNhdGlvbiBjYWNoZS4NCiAgICAgICAgaWYgKHN0YXR1cyA9PT0gMCkgew0KICAgICAgICAgIHN0YXR1cyA9IHJlc3BvbnNlID8gMjAwIDogdXJsUmVzb2x2ZSh1cmwpLnByb3RvY29sID09ICdmaWxlJyA/IDQwNCA6IDA7DQogICAgICAgIH0NCg0KICAgICAgICBjb21wbGV0ZVJlcXVlc3QoY2FsbGJhY2ssDQogICAgICAgICAgICBzdGF0dXMsDQogICAgICAgICAgICByZXNwb25zZSwNCiAgICAgICAgICAgIHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKSwNCiAgICAgICAgICAgIHN0YXR1c1RleHQpOw0KICAgICAgfTsNCg0KICAgICAgdmFyIHJlcXVlc3RFcnJvciA9IGZ1bmN0aW9uKCkgew0KICAgICAgICAvLyBUaGUgcmVzcG9uc2UgaXMgYWx3YXlzIGVtcHR5DQogICAgICAgIC8vIFNlZSBodHRwczovL3hoci5zcGVjLndoYXR3Zy5vcmcvI3JlcXVlc3QtZXJyb3Itc3RlcHMgYW5kIGh0dHBzOi8vZmV0Y2guc3BlYy53aGF0d2cub3JnLyNjb25jZXB0LW5ldHdvcmstZXJyb3INCiAgICAgICAgY29tcGxldGVSZXF1ZXN0KGNhbGxiYWNrLCAtMSwgbnVsbCwgbnVsbCwgJycpOw0KICAgICAgfTsNCg0KICAgICAgeGhyLm9uZXJyb3IgPSByZXF1ZXN0RXJyb3I7DQogICAgICB4aHIub25hYm9ydCA9IHJlcXVlc3RFcnJvcjsNCg0KICAgICAgaWYgKHdpdGhDcmVkZW50aWFscykgew0KICAgICAgICB4aHIud2l0aENyZWRlbnRpYWxzID0gdHJ1ZTsNCiAgICAgIH0NCg0KICAgICAgaWYgKHJlc3BvbnNlVHlwZSkgew0KICAgICAgICB0cnkgew0KICAgICAgICAgIHhoci5yZXNwb25zZVR5cGUgPSByZXNwb25zZVR5cGU7DQogICAgICAgIH0gY2F0Y2ggKGUpIHsNCiAgICAgICAgICAvLyBXZWJLaXQgYWRkZWQgc3VwcG9ydCBmb3IgdGhlIGpzb24gcmVzcG9uc2VUeXBlIHZhbHVlIG9uIDA5LzAzLzIwMTMNCiAgICAgICAgICAvLyBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9NzM2NDguIFZlcnNpb25zIG9mIFNhZmFyaSBwcmlvciB0byA3IGFyZQ0KICAgICAgICAgIC8vIGtub3duIHRvIHRocm93IHdoZW4gc2V0dGluZyB0aGUgdmFsdWUgImpzb24iIGFzIHRoZSByZXNwb25zZSB0eXBlLiBPdGhlciBvbGRlcg0KICAgICAgICAgIC8vIGJyb3dzZXJzIGltcGxlbWVudGluZyB0aGUgcmVzcG9uc2VUeXBlDQogICAgICAgICAgLy8NCiAgICAgICAgICAvLyBUaGUganNvbiByZXNwb25zZSB0eXBlIGNhbiBiZSBpZ25vcmVkIGlmIG5vdCBzdXBwb3J0ZWQsIGJlY2F1c2UgSlNPTiBwYXlsb2FkcyBhcmUNCiAgICAgICAgICAvLyBwYXJzZWQgb24gdGhlIGNsaWVudC1zaWRlIHJlZ2FyZGxlc3MuDQogICAgICAgICAgaWYgKHJlc3BvbnNlVHlwZSAhPT0gJ2pzb24nKSB7DQogICAgICAgICAgICB0aHJvdyBlOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgfQ0KDQogICAgICB4aHIuc2VuZChwb3N0IHx8IG51bGwpOw0KICAgIH0NCg0KICAgIGlmICh0aW1lb3V0ID4gMCkgew0KICAgICAgdmFyIHRpbWVvdXRJZCA9ICRicm93c2VyRGVmZXIodGltZW91dFJlcXVlc3QsIHRpbWVvdXQpOw0KICAgIH0gZWxzZSBpZiAoaXNQcm9taXNlTGlrZSh0aW1lb3V0KSkgew0KICAgICAgdGltZW91dC50aGVuKHRpbWVvdXRSZXF1ZXN0KTsNCiAgICB9DQoNCg0KICAgIGZ1bmN0aW9uIHRpbWVvdXRSZXF1ZXN0KCkgew0KICAgICAganNvbnBEb25lICYmIGpzb25wRG9uZSgpOw0KICAgICAgeGhyICYmIHhoci5hYm9ydCgpOw0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIGNvbXBsZXRlUmVxdWVzdChjYWxsYmFjaywgc3RhdHVzLCByZXNwb25zZSwgaGVhZGVyc1N0cmluZywgc3RhdHVzVGV4dCkgew0KICAgICAgLy8gY2FuY2VsIHRpbWVvdXQgYW5kIHN1YnNlcXVlbnQgdGltZW91dCBwcm9taXNlIHJlc29sdXRpb24NCiAgICAgIGlmICh0aW1lb3V0SWQgIT09IHVuZGVmaW5lZCkgew0KICAgICAgICAkYnJvd3NlckRlZmVyLmNhbmNlbCh0aW1lb3V0SWQpOw0KICAgICAgfQ0KICAgICAganNvbnBEb25lID0geGhyID0gbnVsbDsNCg0KICAgICAgY2FsbGJhY2soc3RhdHVzLCByZXNwb25zZSwgaGVhZGVyc1N0cmluZywgc3RhdHVzVGV4dCk7DQogICAgICAkYnJvd3Nlci4kJGNvbXBsZXRlT3V0c3RhbmRpbmdSZXF1ZXN0KG5vb3ApOw0KICAgIH0NCiAgfTsNCg0KICBmdW5jdGlvbiBqc29ucFJlcSh1cmwsIGNhbGxiYWNrSWQsIGRvbmUpIHsNCiAgICAvLyB3ZSBjYW4ndCB1c2UgalF1ZXJ5L2pxTGl0ZSBoZXJlIGJlY2F1c2UgalF1ZXJ5IGRvZXMgY3Jhenkgc2hpdCB3aXRoIHNjcmlwdCBlbGVtZW50cywgZS5nLjoNCiAgICAvLyAtIGZldGNoZXMgbG9jYWwgc2NyaXB0cyB2aWEgWEhSIGFuZCBldmFscyB0aGVtDQogICAgLy8gLSBhZGRzIGFuZCBpbW1lZGlhdGVseSByZW1vdmVzIHNjcmlwdCBlbGVtZW50cyBmcm9tIHRoZSBkb2N1bWVudA0KICAgIHZhciBzY3JpcHQgPSByYXdEb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKSwgY2FsbGJhY2sgPSBudWxsOw0KICAgIHNjcmlwdC50eXBlID0gInRleHQvamF2YXNjcmlwdCI7DQogICAgc2NyaXB0LnNyYyA9IHVybDsNCiAgICBzY3JpcHQuYXN5bmMgPSB0cnVlOw0KDQogICAgY2FsbGJhY2sgPSBmdW5jdGlvbihldmVudCkgew0KICAgICAgcmVtb3ZlRXZlbnRMaXN0ZW5lckZuKHNjcmlwdCwgImxvYWQiLCBjYWxsYmFjayk7DQogICAgICByZW1vdmVFdmVudExpc3RlbmVyRm4oc2NyaXB0LCAiZXJyb3IiLCBjYWxsYmFjayk7DQogICAgICByYXdEb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKHNjcmlwdCk7DQogICAgICBzY3JpcHQgPSBudWxsOw0KICAgICAgdmFyIHN0YXR1cyA9IC0xOw0KICAgICAgdmFyIHRleHQgPSAidW5rbm93biI7DQoNCiAgICAgIGlmIChldmVudCkgew0KICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gImxvYWQiICYmICFjYWxsYmFja3NbY2FsbGJhY2tJZF0uY2FsbGVkKSB7DQogICAgICAgICAgZXZlbnQgPSB7IHR5cGU6ICJlcnJvciIgfTsNCiAgICAgICAgfQ0KICAgICAgICB0ZXh0ID0gZXZlbnQudHlwZTsNCiAgICAgICAgc3RhdHVzID0gZXZlbnQudHlwZSA9PT0gImVycm9yIiA/IDQwNCA6IDIwMDsNCiAgICAgIH0NCg0KICAgICAgaWYgKGRvbmUpIHsNCiAgICAgICAgZG9uZShzdGF0dXMsIHRleHQpOw0KICAgICAgfQ0KICAgIH07DQoNCiAgICBhZGRFdmVudExpc3RlbmVyRm4oc2NyaXB0LCAibG9hZCIsIGNhbGxiYWNrKTsNCiAgICBhZGRFdmVudExpc3RlbmVyRm4oc2NyaXB0LCAiZXJyb3IiLCBjYWxsYmFjayk7DQogICAgcmF3RG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChzY3JpcHQpOw0KICAgIHJldHVybiBjYWxsYmFjazsNCiAgfQ0KfQ0KDQp2YXIgJGludGVycG9sYXRlTWluRXJyID0gbWluRXJyKCckaW50ZXJwb2xhdGUnKTsNCg0KLyoqDQogKiBAbmdkb2MgcHJvdmlkZXINCiAqIEBuYW1lICRpbnRlcnBvbGF0ZVByb3ZpZGVyDQogKg0KICogQGRlc2NyaXB0aW9uDQogKg0KICogVXNlZCBmb3IgY29uZmlndXJpbmcgdGhlIGludGVycG9sYXRpb24gbWFya3VwLiBEZWZhdWx0cyB0byBge3tgIGFuZCBgfX1gLg0KICoNCiAqIEBleGFtcGxlDQo8ZXhhbXBsZSBtb2R1bGU9ImN1c3RvbUludGVycG9sYXRpb25BcHAiPg0KPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQo8c2NyaXB0Pg0KICB2YXIgY3VzdG9tSW50ZXJwb2xhdGlvbkFwcCA9IGFuZ3VsYXIubW9kdWxlKCdjdXN0b21JbnRlcnBvbGF0aW9uQXBwJywgW10pOw0KDQogIGN1c3RvbUludGVycG9sYXRpb25BcHAuY29uZmlnKGZ1bmN0aW9uKCRpbnRlcnBvbGF0ZVByb3ZpZGVyKSB7DQogICAgJGludGVycG9sYXRlUHJvdmlkZXIuc3RhcnRTeW1ib2woJy8vJyk7DQogICAgJGludGVycG9sYXRlUHJvdmlkZXIuZW5kU3ltYm9sKCcvLycpOw0KICB9KTsNCg0KDQogIGN1c3RvbUludGVycG9sYXRpb25BcHAuY29udHJvbGxlcignRGVtb0NvbnRyb2xsZXInLCBmdW5jdGlvbigpIHsNCiAgICAgIHRoaXMubGFiZWwgPSAiVGhpcyBiaW5kaW5nIGlzIGJyb3VnaHQgeW91IGJ5IC8vIGludGVycG9sYXRpb24gc3ltYm9scy4iOw0KICB9KTsNCjwvc2NyaXB0Pg0KPGRpdiBuZy1hcHA9IkFwcCIgbmctY29udHJvbGxlcj0iRGVtb0NvbnRyb2xsZXIgYXMgZGVtbyI+DQogICAgLy9kZW1vLmxhYmVsLy8NCjwvZGl2Pg0KPC9maWxlPg0KPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogIGl0KCdzaG91bGQgaW50ZXJwb2xhdGUgYmluZGluZyB3aXRoIGN1c3RvbSBzeW1ib2xzJywgZnVuY3Rpb24oKSB7DQogICAgZXhwZWN0KGVsZW1lbnQoYnkuYmluZGluZygnZGVtby5sYWJlbCcpKS5nZXRUZXh0KCkpLnRvQmUoJ1RoaXMgYmluZGluZyBpcyBicm91Z2h0IHlvdSBieSAvLyBpbnRlcnBvbGF0aW9uIHN5bWJvbHMuJyk7DQogIH0pOw0KPC9maWxlPg0KPC9leGFtcGxlPg0KICovDQpmdW5jdGlvbiAkSW50ZXJwb2xhdGVQcm92aWRlcigpIHsNCiAgdmFyIHN0YXJ0U3ltYm9sID0gJ3t7JzsNCiAgdmFyIGVuZFN5bWJvbCA9ICd9fSc7DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgJGludGVycG9sYXRlUHJvdmlkZXIjc3RhcnRTeW1ib2wNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFN5bWJvbCB0byBkZW5vdGUgc3RhcnQgb2YgZXhwcmVzc2lvbiBpbiB0aGUgaW50ZXJwb2xhdGVkIHN0cmluZy4gRGVmYXVsdHMgdG8gYHt7YC4NCiAgICoNCiAgICogQHBhcmFtIHtzdHJpbmc9fSB2YWx1ZSBuZXcgdmFsdWUgdG8gc2V0IHRoZSBzdGFydGluZyBzeW1ib2wgdG8uDQogICAqIEByZXR1cm5zIHtzdHJpbmd8c2VsZn0gUmV0dXJucyB0aGUgc3ltYm9sIHdoZW4gdXNlZCBhcyBnZXR0ZXIgYW5kIHNlbGYgaWYgdXNlZCBhcyBzZXR0ZXIuDQogICAqLw0KICB0aGlzLnN0YXJ0U3ltYm9sID0gZnVuY3Rpb24odmFsdWUpIHsNCiAgICBpZiAodmFsdWUpIHsNCiAgICAgIHN0YXJ0U3ltYm9sID0gdmFsdWU7DQogICAgICByZXR1cm4gdGhpczsNCiAgICB9IGVsc2Ugew0KICAgICAgcmV0dXJuIHN0YXJ0U3ltYm9sOw0KICAgIH0NCiAgfTsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkaW50ZXJwb2xhdGVQcm92aWRlciNlbmRTeW1ib2wNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFN5bWJvbCB0byBkZW5vdGUgdGhlIGVuZCBvZiBleHByZXNzaW9uIGluIHRoZSBpbnRlcnBvbGF0ZWQgc3RyaW5nLiBEZWZhdWx0cyB0byBgfX1gLg0KICAgKg0KICAgKiBAcGFyYW0ge3N0cmluZz19IHZhbHVlIG5ldyB2YWx1ZSB0byBzZXQgdGhlIGVuZGluZyBzeW1ib2wgdG8uDQogICAqIEByZXR1cm5zIHtzdHJpbmd8c2VsZn0gUmV0dXJucyB0aGUgc3ltYm9sIHdoZW4gdXNlZCBhcyBnZXR0ZXIgYW5kIHNlbGYgaWYgdXNlZCBhcyBzZXR0ZXIuDQogICAqLw0KICB0aGlzLmVuZFN5bWJvbCA9IGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgaWYgKHZhbHVlKSB7DQogICAgICBlbmRTeW1ib2wgPSB2YWx1ZTsNCiAgICAgIHJldHVybiB0aGlzOw0KICAgIH0gZWxzZSB7DQogICAgICByZXR1cm4gZW5kU3ltYm9sOw0KICAgIH0NCiAgfTsNCg0KDQogIHRoaXMuJGdldCA9IFsnJHBhcnNlJywgJyRleGNlcHRpb25IYW5kbGVyJywgJyRzY2UnLCBmdW5jdGlvbigkcGFyc2UsICRleGNlcHRpb25IYW5kbGVyLCAkc2NlKSB7DQogICAgdmFyIHN0YXJ0U3ltYm9sTGVuZ3RoID0gc3RhcnRTeW1ib2wubGVuZ3RoLA0KICAgICAgICBlbmRTeW1ib2xMZW5ndGggPSBlbmRTeW1ib2wubGVuZ3RoLA0KICAgICAgICBlc2NhcGVkU3RhcnRSZWdleHAgPSBuZXcgUmVnRXhwKHN0YXJ0U3ltYm9sLnJlcGxhY2UoLy4vZywgZXNjYXBlKSwgJ2cnKSwNCiAgICAgICAgZXNjYXBlZEVuZFJlZ2V4cCA9IG5ldyBSZWdFeHAoZW5kU3ltYm9sLnJlcGxhY2UoLy4vZywgZXNjYXBlKSwgJ2cnKTsNCg0KICAgIGZ1bmN0aW9uIGVzY2FwZShjaCkgew0KICAgICAgcmV0dXJuICdcXFxcXFwnICsgY2g7DQogICAgfQ0KDQogICAgLyoqDQogICAgICogQG5nZG9jIHNlcnZpY2UNCiAgICAgKiBAbmFtZSAkaW50ZXJwb2xhdGUNCiAgICAgKiBAa2luZCBmdW5jdGlvbg0KICAgICAqDQogICAgICogQHJlcXVpcmVzICRwYXJzZQ0KICAgICAqIEByZXF1aXJlcyAkc2NlDQogICAgICoNCiAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgKg0KICAgICAqIENvbXBpbGVzIGEgc3RyaW5nIHdpdGggbWFya3VwIGludG8gYW4gaW50ZXJwb2xhdGlvbiBmdW5jdGlvbi4gVGhpcyBzZXJ2aWNlIGlzIHVzZWQgYnkgdGhlDQogICAgICogSFRNTCB7QGxpbmsgbmcuJGNvbXBpbGUgJGNvbXBpbGV9IHNlcnZpY2UgZm9yIGRhdGEgYmluZGluZy4gU2VlDQogICAgICoge0BsaW5rIG5nLiRpbnRlcnBvbGF0ZVByb3ZpZGVyICRpbnRlcnBvbGF0ZVByb3ZpZGVyfSBmb3IgY29uZmlndXJpbmcgdGhlDQogICAgICogaW50ZXJwb2xhdGlvbiBtYXJrdXAuDQogICAgICoNCiAgICAgKg0KICAgICAqIGBgYGpzDQogICAgICogICB2YXIgJGludGVycG9sYXRlID0gLi4uOyAvLyBpbmplY3RlZA0KICAgICAqICAgdmFyIGV4cCA9ICRpbnRlcnBvbGF0ZSgnSGVsbG8ge3tuYW1lIHwgdXBwZXJjYXNlfX0hJyk7DQogICAgICogICBleHBlY3QoZXhwKHtuYW1lOidBbmd1bGFyJ30pLnRvRXF1YWwoJ0hlbGxvIEFOR1VMQVIhJyk7DQogICAgICogYGBgDQogICAgICoNCiAgICAgKiBgJGludGVycG9sYXRlYCB0YWtlcyBhbiBvcHRpb25hbCBmb3VydGggYXJndW1lbnQsIGBhbGxPck5vdGhpbmdgLiBJZiBgYWxsT3JOb3RoaW5nYCBpcw0KICAgICAqIGB0cnVlYCwgdGhlIGludGVycG9sYXRpb24gZnVuY3Rpb24gd2lsbCByZXR1cm4gYHVuZGVmaW5lZGAgdW5sZXNzIGFsbCBlbWJlZGRlZCBleHByZXNzaW9ucw0KICAgICAqIGV2YWx1YXRlIHRvIGEgdmFsdWUgb3RoZXIgdGhhbiBgdW5kZWZpbmVkYC4NCiAgICAgKg0KICAgICAqIGBgYGpzDQogICAgICogICB2YXIgJGludGVycG9sYXRlID0gLi4uOyAvLyBpbmplY3RlZA0KICAgICAqICAgdmFyIGNvbnRleHQgPSB7Z3JlZXRpbmc6ICdIZWxsbycsIG5hbWU6IHVuZGVmaW5lZCB9Ow0KICAgICAqDQogICAgICogICAvLyBkZWZhdWx0ICJmb3JnaXZpbmciIG1vZGUNCiAgICAgKiAgIHZhciBleHAgPSAkaW50ZXJwb2xhdGUoJ3t7Z3JlZXRpbmd9fSB7e25hbWV9fSEnKTsNCiAgICAgKiAgIGV4cGVjdChleHAoY29udGV4dCkpLnRvRXF1YWwoJ0hlbGxvICEnKTsNCiAgICAgKg0KICAgICAqICAgLy8gImFsbE9yTm90aGluZyIgbW9kZQ0KICAgICAqICAgZXhwID0gJGludGVycG9sYXRlKCd7e2dyZWV0aW5nfX0ge3tuYW1lfX0hJywgZmFsc2UsIG51bGwsIHRydWUpOw0KICAgICAqICAgZXhwZWN0KGV4cChjb250ZXh0KSkudG9CZVVuZGVmaW5lZCgpOw0KICAgICAqICAgY29udGV4dC5uYW1lID0gJ0FuZ3VsYXInOw0KICAgICAqICAgZXhwZWN0KGV4cChjb250ZXh0KSkudG9FcXVhbCgnSGVsbG8gQW5ndWxhciEnKTsNCiAgICAgKiBgYGANCiAgICAgKg0KICAgICAqIGBhbGxPck5vdGhpbmdgIGlzIHVzZWZ1bCBmb3IgaW50ZXJwb2xhdGluZyBVUkxzLiBgbmdTcmNgIGFuZCBgbmdTcmNzZXRgIHVzZSB0aGlzIGJlaGF2aW9yLg0KICAgICAqDQogICAgICogIyMjI0VzY2FwZWQgSW50ZXJwb2xhdGlvbg0KICAgICAqICRpbnRlcnBvbGF0ZSBwcm92aWRlcyBhIG1lY2hhbmlzbSBmb3IgZXNjYXBpbmcgaW50ZXJwb2xhdGlvbiBtYXJrZXJzLiBTdGFydCBhbmQgZW5kIG1hcmtlcnMNCiAgICAgKiBjYW4gYmUgZXNjYXBlZCBieSBwcmVjZWRpbmcgZWFjaCBvZiB0aGVpciBjaGFyYWN0ZXJzIHdpdGggYSBSRVZFUlNFIFNPTElEVVMgVSswMDVDIChiYWNrc2xhc2gpLg0KICAgICAqIEl0IHdpbGwgYmUgcmVuZGVyZWQgYXMgYSByZWd1bGFyIHN0YXJ0L2VuZCBtYXJrZXIsIGFuZCB3aWxsIG5vdCBiZSBpbnRlcnByZXRlZCBhcyBhbiBleHByZXNzaW9uDQogICAgICogb3IgYmluZGluZy4NCiAgICAgKg0KICAgICAqIFRoaXMgZW5hYmxlcyB3ZWItc2VydmVycyB0byBwcmV2ZW50IHNjcmlwdCBpbmplY3Rpb24gYXR0YWNrcyBhbmQgZGVmYWNpbmcgYXR0YWNrcywgdG8gc29tZQ0KICAgICAqIGRlZ3JlZSwgd2hpbGUgYWxzbyBlbmFibGluZyBjb2RlIGV4YW1wbGVzIHRvIHdvcmsgd2l0aG91dCByZWx5aW5nIG9uIHRoZQ0KICAgICAqIHtAbGluayBuZy5kaXJlY3RpdmU6bmdOb25CaW5kYWJsZSBuZ05vbkJpbmRhYmxlfSBkaXJlY3RpdmUuDQogICAgICoNCiAgICAgKiAqKkZvciBzZWN1cml0eSBwdXJwb3NlcywgaXQgaXMgc3Ryb25nbHkgZW5jb3VyYWdlZCB0aGF0IHdlYiBzZXJ2ZXJzIGVzY2FwZSB1c2VyLXN1cHBsaWVkIGRhdGEsDQogICAgICogcmVwbGFjaW5nIGFuZ2xlIGJyYWNrZXRzICgmbHQ7LCAmZ3Q7KSB3aXRoICZhbXA7bHQ7IGFuZCAmYW1wO2d0OyByZXNwZWN0aXZlbHksIGFuZCByZXBsYWNpbmcgYWxsDQogICAgICogaW50ZXJwb2xhdGlvbiBzdGFydC9lbmQgbWFya2VycyB3aXRoIHRoZWlyIGVzY2FwZWQgY291bnRlcnBhcnRzLioqDQogICAgICoNCiAgICAgKiBFc2NhcGVkIGludGVycG9sYXRpb24gbWFya2VycyBhcmUgb25seSByZXBsYWNlZCB3aXRoIHRoZSBhY3R1YWwgaW50ZXJwb2xhdGlvbiBtYXJrZXJzIGluIHJlbmRlcmVkDQogICAgICogb3V0cHV0IHdoZW4gdGhlICRpbnRlcnBvbGF0ZSBzZXJ2aWNlIHByb2Nlc3NlcyB0aGUgdGV4dC4gU28sIGZvciBIVE1MIGVsZW1lbnRzIGludGVycG9sYXRlZA0KICAgICAqIGJ5IHtAbGluayBuZy4kY29tcGlsZSAkY29tcGlsZX0sIG9yIG90aGVyd2lzZSBpbnRlcnBvbGF0ZWQgd2l0aCB0aGUgYG11c3RIYXZlRXhwcmVzc2lvbmAgcGFyYW1ldGVyDQogICAgICogc2V0IHRvIGB0cnVlYCwgdGhlIGludGVycG9sYXRlZCB0ZXh0IG11c3QgY29udGFpbiBhbiB1bmVzY2FwZWQgaW50ZXJwb2xhdGlvbiBleHByZXNzaW9uLiBBcyBzdWNoLA0KICAgICAqIHRoaXMgaXMgdHlwaWNhbGx5IHVzZWZ1bCBvbmx5IHdoZW4gdXNlci1kYXRhIGlzIHVzZWQgaW4gcmVuZGVyaW5nIGEgdGVtcGxhdGUgZnJvbSB0aGUgc2VydmVyLCBvcg0KICAgICAqIHdoZW4gb3RoZXJ3aXNlIHVudHJ1c3RlZCBkYXRhIGlzIHVzZWQgYnkgYSBkaXJlY3RpdmUuDQogICAgICoNCiAgICAgKiA8ZXhhbXBsZT4NCiAgICAgKiAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICogICAgPGRpdiBuZy1pbml0PSJ1c2VybmFtZT0nQSB1c2VyJyI+DQogICAgICogICAgICA8cCBuZy1pbml0PSJhcHB0aXRsZT0nRXNjYXBpbmcgZGVtbyciPnt7YXBwdGl0bGV9fTogXHtceyB1c2VybmFtZSA9ICJkZWZhY2VkIHZhbHVlIjsgXH1cfQ0KICAgICAqICAgICAgICA8L3A+DQogICAgICogICAgICA8cD48c3Ryb25nPnt7dXNlcm5hbWV9fTwvc3Ryb25nPiBhdHRlbXB0cyB0byBpbmplY3QgY29kZSB3aGljaCB3aWxsIGRlZmFjZSB0aGUNCiAgICAgKiAgICAgICAgYXBwbGljYXRpb24sIGJ1dCBmYWlscyB0byBhY2NvbXBsaXNoIHRoZWlyIHRhc2ssIGJlY2F1c2UgdGhlIHNlcnZlciBoYXMgY29ycmVjdGx5DQogICAgICogICAgICAgIGVzY2FwZWQgdGhlIGludGVycG9sYXRpb24gc3RhcnQvZW5kIG1hcmtlcnMgd2l0aCBSRVZFUlNFIFNPTElEVVMgVSswMDVDIChiYWNrc2xhc2gpDQogICAgICogICAgICAgIGNoYXJhY3RlcnMuPC9wPg0KICAgICAqICAgICAgPHA+SW5zdGVhZCwgdGhlIHJlc3VsdCBvZiB0aGUgYXR0ZW1wdGVkIHNjcmlwdCBpbmplY3Rpb24gaXMgdmlzaWJsZSwgYW5kIGNhbiBiZSByZW1vdmVkDQogICAgICogICAgICAgIGZyb20gdGhlIGRhdGFiYXNlIGJ5IGFuIGFkbWluaXN0cmF0b3IuPC9wPg0KICAgICAqICAgIDwvZGl2Pg0KICAgICAqICA8L2ZpbGU+DQogICAgICogPC9leGFtcGxlPg0KICAgICAqDQogICAgICogQHBhcmFtIHtzdHJpbmd9IHRleHQgVGhlIHRleHQgd2l0aCBtYXJrdXAgdG8gaW50ZXJwb2xhdGUuDQogICAgICogQHBhcmFtIHtib29sZWFuPX0gbXVzdEhhdmVFeHByZXNzaW9uIGlmIHNldCB0byB0cnVlIHRoZW4gdGhlIGludGVycG9sYXRpb24gc3RyaW5nIG11c3QgaGF2ZQ0KICAgICAqICAgIGVtYmVkZGVkIGV4cHJlc3Npb24gaW4gb3JkZXIgdG8gcmV0dXJuIGFuIGludGVycG9sYXRpb24gZnVuY3Rpb24uIFN0cmluZ3Mgd2l0aCBubw0KICAgICAqICAgIGVtYmVkZGVkIGV4cHJlc3Npb24gd2lsbCByZXR1cm4gbnVsbCBmb3IgdGhlIGludGVycG9sYXRpb24gZnVuY3Rpb24uDQogICAgICogQHBhcmFtIHtzdHJpbmc9fSB0cnVzdGVkQ29udGV4dCB3aGVuIHByb3ZpZGVkLCB0aGUgcmV0dXJuZWQgZnVuY3Rpb24gcGFzc2VzIHRoZSBpbnRlcnBvbGF0ZWQNCiAgICAgKiAgICByZXN1bHQgdGhyb3VnaCB7QGxpbmsgbmcuJHNjZSNnZXRUcnVzdGVkICRzY2UuZ2V0VHJ1c3RlZChpbnRlcnBvbGF0ZWRSZXN1bHQsDQogICAgICogICAgdHJ1c3RlZENvbnRleHQpfSBiZWZvcmUgcmV0dXJuaW5nIGl0LiAgUmVmZXIgdG8gdGhlIHtAbGluayBuZy4kc2NlICRzY2V9IHNlcnZpY2UgdGhhdA0KICAgICAqICAgIHByb3ZpZGVzIFN0cmljdCBDb250ZXh0dWFsIEVzY2FwaW5nIGZvciBkZXRhaWxzLg0KICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IGFsbE9yTm90aGluZyBpZiBgdHJ1ZWAsIHRoZW4gdGhlIHJldHVybmVkIGZ1bmN0aW9uIHJldHVybnMgdW5kZWZpbmVkDQogICAgICogICAgdW5sZXNzIGFsbCBlbWJlZGRlZCBleHByZXNzaW9ucyBldmFsdWF0ZSB0byBhIHZhbHVlIG90aGVyIHRoYW4gYHVuZGVmaW5lZGAuDQogICAgICogQHJldHVybnMge2Z1bmN0aW9uKGNvbnRleHQpfSBhbiBpbnRlcnBvbGF0aW9uIGZ1bmN0aW9uIHdoaWNoIGlzIHVzZWQgdG8gY29tcHV0ZSB0aGUNCiAgICAgKiAgICBpbnRlcnBvbGF0ZWQgc3RyaW5nLiBUaGUgZnVuY3Rpb24gaGFzIHRoZXNlIHBhcmFtZXRlcnM6DQogICAgICoNCiAgICAgKiAtIGBjb250ZXh0YDogZXZhbHVhdGlvbiBjb250ZXh0IGZvciBhbGwgZXhwcmVzc2lvbnMgZW1iZWRkZWQgaW4gdGhlIGludGVycG9sYXRlZCB0ZXh0DQogICAgICovDQogICAgZnVuY3Rpb24gJGludGVycG9sYXRlKHRleHQsIG11c3RIYXZlRXhwcmVzc2lvbiwgdHJ1c3RlZENvbnRleHQsIGFsbE9yTm90aGluZykgew0KICAgICAgYWxsT3JOb3RoaW5nID0gISFhbGxPck5vdGhpbmc7DQogICAgICB2YXIgc3RhcnRJbmRleCwNCiAgICAgICAgICBlbmRJbmRleCwNCiAgICAgICAgICBpbmRleCA9IDAsDQogICAgICAgICAgZXhwcmVzc2lvbnMgPSBbXSwNCiAgICAgICAgICBwYXJzZUZucyA9IFtdLA0KICAgICAgICAgIHRleHRMZW5ndGggPSB0ZXh0Lmxlbmd0aCwNCiAgICAgICAgICBleHAsDQogICAgICAgICAgY29uY2F0ID0gW10sDQogICAgICAgICAgZXhwcmVzc2lvblBvc2l0aW9ucyA9IFtdOw0KDQogICAgICB3aGlsZSAoaW5kZXggPCB0ZXh0TGVuZ3RoKSB7DQogICAgICAgIGlmICgoKHN0YXJ0SW5kZXggPSB0ZXh0LmluZGV4T2Yoc3RhcnRTeW1ib2wsIGluZGV4KSkgIT0gLTEpICYmDQogICAgICAgICAgICAgKChlbmRJbmRleCA9IHRleHQuaW5kZXhPZihlbmRTeW1ib2wsIHN0YXJ0SW5kZXggKyBzdGFydFN5bWJvbExlbmd0aCkpICE9IC0xKSkgew0KICAgICAgICAgIGlmIChpbmRleCAhPT0gc3RhcnRJbmRleCkgew0KICAgICAgICAgICAgY29uY2F0LnB1c2godW5lc2NhcGVUZXh0KHRleHQuc3Vic3RyaW5nKGluZGV4LCBzdGFydEluZGV4KSkpOw0KICAgICAgICAgIH0NCiAgICAgICAgICBleHAgPSB0ZXh0LnN1YnN0cmluZyhzdGFydEluZGV4ICsgc3RhcnRTeW1ib2xMZW5ndGgsIGVuZEluZGV4KTsNCiAgICAgICAgICBleHByZXNzaW9ucy5wdXNoKGV4cCk7DQogICAgICAgICAgcGFyc2VGbnMucHVzaCgkcGFyc2UoZXhwLCBwYXJzZVN0cmluZ2lmeUludGVyY2VwdG9yKSk7DQogICAgICAgICAgaW5kZXggPSBlbmRJbmRleCArIGVuZFN5bWJvbExlbmd0aDsNCiAgICAgICAgICBleHByZXNzaW9uUG9zaXRpb25zLnB1c2goY29uY2F0Lmxlbmd0aCk7DQogICAgICAgICAgY29uY2F0LnB1c2goJycpOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIC8vIHdlIGRpZCBub3QgZmluZCBhbiBpbnRlcnBvbGF0aW9uLCBzbyB3ZSBoYXZlIHRvIGFkZCB0aGUgcmVtYWluZGVyIHRvIHRoZSBzZXBhcmF0b3JzIGFycmF5DQogICAgICAgICAgaWYgKGluZGV4ICE9PSB0ZXh0TGVuZ3RoKSB7DQogICAgICAgICAgICBjb25jYXQucHVzaCh1bmVzY2FwZVRleHQodGV4dC5zdWJzdHJpbmcoaW5kZXgpKSk7DQogICAgICAgICAgfQ0KICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQogICAgICB9DQoNCiAgICAgIC8vIENvbmNhdGVuYXRpbmcgZXhwcmVzc2lvbnMgbWFrZXMgaXQgaGFyZCB0byByZWFzb24gYWJvdXQgd2hldGhlciBzb21lIGNvbWJpbmF0aW9uIG9mDQogICAgICAvLyBjb25jYXRlbmF0ZWQgdmFsdWVzIGFyZSB1bnNhZmUgdG8gdXNlIGFuZCBjb3VsZCBlYXNpbHkgbGVhZCB0byBYU1MuICBCeSByZXF1aXJpbmcgdGhhdCBhDQogICAgICAvLyBzaW5nbGUgZXhwcmVzc2lvbiBiZSB1c2VkIGZvciBpZnJhbWVbc3JjXSwgb2JqZWN0W3NyY10sIGV0Yy4sIHdlIGVuc3VyZSB0aGF0IHRoZSB2YWx1ZQ0KICAgICAgLy8gdGhhdCdzIHVzZWQgaXMgYXNzaWduZWQgb3IgY29uc3RydWN0ZWQgYnkgc29tZSBKUyBjb2RlIHNvbWV3aGVyZSB0aGF0IGlzIG1vcmUgdGVzdGFibGUgb3INCiAgICAgIC8vIG1ha2UgaXQgb2J2aW91cyB0aGF0IHlvdSBib3VuZCB0aGUgdmFsdWUgdG8gc29tZSB1c2VyIGNvbnRyb2xsZWQgdmFsdWUuICBUaGlzIGhlbHBzIHJlZHVjZQ0KICAgICAgLy8gdGhlIGxvYWQgd2hlbiBhdWRpdGluZyBmb3IgWFNTIGlzc3Vlcy4NCiAgICAgIGlmICh0cnVzdGVkQ29udGV4dCAmJiBjb25jYXQubGVuZ3RoID4gMSkgew0KICAgICAgICAgIHRocm93ICRpbnRlcnBvbGF0ZU1pbkVycignbm9jb25jYXQnLA0KICAgICAgICAgICAgICAiRXJyb3Igd2hpbGUgaW50ZXJwb2xhdGluZzogezB9XG5TdHJpY3QgQ29udGV4dHVhbCBFc2NhcGluZyBkaXNhbGxvd3MgIiArDQogICAgICAgICAgICAgICJpbnRlcnBvbGF0aW9ucyB0aGF0IGNvbmNhdGVuYXRlIG11bHRpcGxlIGV4cHJlc3Npb25zIHdoZW4gYSB0cnVzdGVkIHZhbHVlIGlzICIgKw0KICAgICAgICAgICAgICAicmVxdWlyZWQuICBTZWUgaHR0cDovL2RvY3MuYW5ndWxhcmpzLm9yZy9hcGkvbmcuJHNjZSIsIHRleHQpOw0KICAgICAgfQ0KDQogICAgICBpZiAoIW11c3RIYXZlRXhwcmVzc2lvbiB8fCBleHByZXNzaW9ucy5sZW5ndGgpIHsNCiAgICAgICAgdmFyIGNvbXB1dGUgPSBmdW5jdGlvbih2YWx1ZXMpIHsNCiAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBleHByZXNzaW9ucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7DQogICAgICAgICAgICBpZiAoYWxsT3JOb3RoaW5nICYmIGlzVW5kZWZpbmVkKHZhbHVlc1tpXSkpIHJldHVybjsNCiAgICAgICAgICAgIGNvbmNhdFtleHByZXNzaW9uUG9zaXRpb25zW2ldXSA9IHZhbHVlc1tpXTsNCiAgICAgICAgICB9DQogICAgICAgICAgcmV0dXJuIGNvbmNhdC5qb2luKCcnKTsNCiAgICAgICAgfTsNCg0KICAgICAgICB2YXIgZ2V0VmFsdWUgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICAgIHJldHVybiB0cnVzdGVkQ29udGV4dCA/DQogICAgICAgICAgICAkc2NlLmdldFRydXN0ZWQodHJ1c3RlZENvbnRleHQsIHZhbHVlKSA6DQogICAgICAgICAgICAkc2NlLnZhbHVlT2YodmFsdWUpOw0KICAgICAgICB9Ow0KDQogICAgICAgIHZhciBzdHJpbmdpZnkgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7IC8vIG51bGwgfHwgdW5kZWZpbmVkDQogICAgICAgICAgICByZXR1cm4gJyc7DQogICAgICAgICAgfQ0KICAgICAgICAgIHN3aXRjaCAodHlwZW9mIHZhbHVlKSB7DQogICAgICAgICAgICBjYXNlICdzdHJpbmcnOg0KICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIGNhc2UgJ251bWJlcic6DQogICAgICAgICAgICAgIHZhbHVlID0gJycgKyB2YWx1ZTsNCiAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBkZWZhdWx0Og0KICAgICAgICAgICAgICB2YWx1ZSA9IHRvSnNvbih2YWx1ZSk7DQogICAgICAgICAgfQ0KDQogICAgICAgICAgcmV0dXJuIHZhbHVlOw0KICAgICAgICB9Ow0KDQogICAgICAgIHJldHVybiBleHRlbmQoZnVuY3Rpb24gaW50ZXJwb2xhdGlvbkZuKGNvbnRleHQpIHsNCiAgICAgICAgICAgIHZhciBpID0gMDsNCiAgICAgICAgICAgIHZhciBpaSA9IGV4cHJlc3Npb25zLmxlbmd0aDsNCiAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBuZXcgQXJyYXkoaWkpOw0KDQogICAgICAgICAgICB0cnkgew0KICAgICAgICAgICAgICBmb3IgKDsgaSA8IGlpOyBpKyspIHsNCiAgICAgICAgICAgICAgICB2YWx1ZXNbaV0gPSBwYXJzZUZuc1tpXShjb250ZXh0KTsNCiAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgIHJldHVybiBjb21wdXRlKHZhbHVlcyk7DQogICAgICAgICAgICB9IGNhdGNoIChlcnIpIHsNCiAgICAgICAgICAgICAgdmFyIG5ld0VyciA9ICRpbnRlcnBvbGF0ZU1pbkVycignaW50ZXJyJywgIkNhbid0IGludGVycG9sYXRlOiB7MH1cbnsxfSIsIHRleHQsDQogICAgICAgICAgICAgICAgICBlcnIudG9TdHJpbmcoKSk7DQogICAgICAgICAgICAgICRleGNlcHRpb25IYW5kbGVyKG5ld0Vycik7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICB9LCB7DQogICAgICAgICAgLy8gYWxsIG9mIHRoZXNlIHByb3BlcnRpZXMgYXJlIHVuZG9jdW1lbnRlZCBmb3Igbm93DQogICAgICAgICAgZXhwOiB0ZXh0LCAvL2p1c3QgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCByZWd1bGFyIHdhdGNoZXJzIGNyZWF0ZWQgdmlhICR3YXRjaA0KICAgICAgICAgIGV4cHJlc3Npb25zOiBleHByZXNzaW9ucywNCiAgICAgICAgICAkJHdhdGNoRGVsZWdhdGU6IGZ1bmN0aW9uKHNjb3BlLCBsaXN0ZW5lciwgb2JqZWN0RXF1YWxpdHkpIHsNCiAgICAgICAgICAgIHZhciBsYXN0VmFsdWU7DQogICAgICAgICAgICByZXR1cm4gc2NvcGUuJHdhdGNoR3JvdXAocGFyc2VGbnMsIGZ1bmN0aW9uIGludGVycG9sYXRlRm5XYXRjaGVyKHZhbHVlcywgb2xkVmFsdWVzKSB7DQogICAgICAgICAgICAgIHZhciBjdXJyVmFsdWUgPSBjb21wdXRlKHZhbHVlcyk7DQogICAgICAgICAgICAgIGlmIChpc0Z1bmN0aW9uKGxpc3RlbmVyKSkgew0KICAgICAgICAgICAgICAgIGxpc3RlbmVyLmNhbGwodGhpcywgY3VyclZhbHVlLCB2YWx1ZXMgIT09IG9sZFZhbHVlcyA/IGxhc3RWYWx1ZSA6IGN1cnJWYWx1ZSwgc2NvcGUpOw0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgIGxhc3RWYWx1ZSA9IGN1cnJWYWx1ZTsNCiAgICAgICAgICAgIH0sIG9iamVjdEVxdWFsaXR5KTsNCiAgICAgICAgICB9DQogICAgICAgIH0pOw0KICAgICAgfQ0KDQogICAgICBmdW5jdGlvbiB1bmVzY2FwZVRleHQodGV4dCkgew0KICAgICAgICByZXR1cm4gdGV4dC5yZXBsYWNlKGVzY2FwZWRTdGFydFJlZ2V4cCwgc3RhcnRTeW1ib2wpLg0KICAgICAgICAgIHJlcGxhY2UoZXNjYXBlZEVuZFJlZ2V4cCwgZW5kU3ltYm9sKTsNCiAgICAgIH0NCg0KICAgICAgZnVuY3Rpb24gcGFyc2VTdHJpbmdpZnlJbnRlcmNlcHRvcih2YWx1ZSkgew0KICAgICAgICB0cnkgew0KICAgICAgICAgIHZhbHVlID0gZ2V0VmFsdWUodmFsdWUpOw0KICAgICAgICAgIHJldHVybiBhbGxPck5vdGhpbmcgJiYgIWlzRGVmaW5lZCh2YWx1ZSkgPyB2YWx1ZSA6IHN0cmluZ2lmeSh2YWx1ZSk7DQogICAgICAgIH0gY2F0Y2ggKGVycikgew0KICAgICAgICAgIHZhciBuZXdFcnIgPSAkaW50ZXJwb2xhdGVNaW5FcnIoJ2ludGVycicsICJDYW4ndCBpbnRlcnBvbGF0ZTogezB9XG57MX0iLCB0ZXh0LA0KICAgICAgICAgICAgZXJyLnRvU3RyaW5nKCkpOw0KICAgICAgICAgICRleGNlcHRpb25IYW5kbGVyKG5ld0Vycik7DQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQoNCg0KICAgIC8qKg0KICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgKiBAbmFtZSAkaW50ZXJwb2xhdGUjc3RhcnRTeW1ib2wNCiAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgKiBTeW1ib2wgdG8gZGVub3RlIHRoZSBzdGFydCBvZiBleHByZXNzaW9uIGluIHRoZSBpbnRlcnBvbGF0ZWQgc3RyaW5nLiBEZWZhdWx0cyB0byBge3tgLg0KICAgICAqDQogICAgICogVXNlIHtAbGluayBuZy4kaW50ZXJwb2xhdGVQcm92aWRlciNzdGFydFN5bWJvbCBgJGludGVycG9sYXRlUHJvdmlkZXIuc3RhcnRTeW1ib2xgfSB0byBjaGFuZ2UNCiAgICAgKiB0aGUgc3ltYm9sLg0KICAgICAqDQogICAgICogQHJldHVybnMge3N0cmluZ30gc3RhcnQgc3ltYm9sLg0KICAgICAqLw0KICAgICRpbnRlcnBvbGF0ZS5zdGFydFN5bWJvbCA9IGZ1bmN0aW9uKCkgew0KICAgICAgcmV0dXJuIHN0YXJ0U3ltYm9sOw0KICAgIH07DQoNCg0KICAgIC8qKg0KICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgKiBAbmFtZSAkaW50ZXJwb2xhdGUjZW5kU3ltYm9sDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU3ltYm9sIHRvIGRlbm90ZSB0aGUgZW5kIG9mIGV4cHJlc3Npb24gaW4gdGhlIGludGVycG9sYXRlZCBzdHJpbmcuIERlZmF1bHRzIHRvIGB9fWAuDQogICAgICoNCiAgICAgKiBVc2Uge0BsaW5rIG5nLiRpbnRlcnBvbGF0ZVByb3ZpZGVyI2VuZFN5bWJvbCBgJGludGVycG9sYXRlUHJvdmlkZXIuZW5kU3ltYm9sYH0gdG8gY2hhbmdlDQogICAgICogdGhlIHN5bWJvbC4NCiAgICAgKg0KICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IGVuZCBzeW1ib2wuDQogICAgICovDQogICAgJGludGVycG9sYXRlLmVuZFN5bWJvbCA9IGZ1bmN0aW9uKCkgew0KICAgICAgcmV0dXJuIGVuZFN5bWJvbDsNCiAgICB9Ow0KDQogICAgcmV0dXJuICRpbnRlcnBvbGF0ZTsNCiAgfV07DQp9DQoNCmZ1bmN0aW9uICRJbnRlcnZhbFByb3ZpZGVyKCkgew0KICB0aGlzLiRnZXQgPSBbJyRyb290U2NvcGUnLCAnJHdpbmRvdycsICckcScsICckJHEnLA0KICAgICAgIGZ1bmN0aW9uKCRyb290U2NvcGUsICAgJHdpbmRvdywgICAkcSwgICAkJHEpIHsNCiAgICB2YXIgaW50ZXJ2YWxzID0ge307DQoNCg0KICAgICAvKioNCiAgICAgICogQG5nZG9jIHNlcnZpY2UNCiAgICAgICogQG5hbWUgJGludGVydmFsDQogICAgICAqDQogICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgKiBBbmd1bGFyJ3Mgd3JhcHBlciBmb3IgYHdpbmRvdy5zZXRJbnRlcnZhbGAuIFRoZSBgZm5gIGZ1bmN0aW9uIGlzIGV4ZWN1dGVkIGV2ZXJ5IGBkZWxheWANCiAgICAgICogbWlsbGlzZWNvbmRzLg0KICAgICAgKg0KICAgICAgKiBUaGUgcmV0dXJuIHZhbHVlIG9mIHJlZ2lzdGVyaW5nIGFuIGludGVydmFsIGZ1bmN0aW9uIGlzIGEgcHJvbWlzZS4gVGhpcyBwcm9taXNlIHdpbGwgYmUNCiAgICAgICogbm90aWZpZWQgdXBvbiBlYWNoIHRpY2sgb2YgdGhlIGludGVydmFsLCBhbmQgd2lsbCBiZSByZXNvbHZlZCBhZnRlciBgY291bnRgIGl0ZXJhdGlvbnMsIG9yDQogICAgICAqIHJ1biBpbmRlZmluaXRlbHkgaWYgYGNvdW50YCBpcyBub3QgZGVmaW5lZC4gVGhlIHZhbHVlIG9mIHRoZSBub3RpZmljYXRpb24gd2lsbCBiZSB0aGUNCiAgICAgICogbnVtYmVyIG9mIGl0ZXJhdGlvbnMgdGhhdCBoYXZlIHJ1bi4NCiAgICAgICogVG8gY2FuY2VsIGFuIGludGVydmFsLCBjYWxsIGAkaW50ZXJ2YWwuY2FuY2VsKHByb21pc2UpYC4NCiAgICAgICoNCiAgICAgICogSW4gdGVzdHMgeW91IGNhbiB1c2Uge0BsaW5rIG5nTW9jay4kaW50ZXJ2YWwjZmx1c2ggYCRpbnRlcnZhbC5mbHVzaChtaWxsaXMpYH0gdG8NCiAgICAgICogbW92ZSBmb3J3YXJkIGJ5IGBtaWxsaXNgIG1pbGxpc2Vjb25kcyBhbmQgdHJpZ2dlciBhbnkgZnVuY3Rpb25zIHNjaGVkdWxlZCB0byBydW4gaW4gdGhhdA0KICAgICAgKiB0aW1lLg0KICAgICAgKg0KICAgICAgKiA8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4NCiAgICAgICogKipOb3RlKio6IEludGVydmFscyBjcmVhdGVkIGJ5IHRoaXMgc2VydmljZSBtdXN0IGJlIGV4cGxpY2l0bHkgZGVzdHJveWVkIHdoZW4geW91IGFyZSBmaW5pc2hlZA0KICAgICAgKiB3aXRoIHRoZW0uICBJbiBwYXJ0aWN1bGFyIHRoZXkgYXJlIG5vdCBhdXRvbWF0aWNhbGx5IGRlc3Ryb3llZCB3aGVuIGEgY29udHJvbGxlcidzIHNjb3BlIG9yIGENCiAgICAgICogZGlyZWN0aXZlJ3MgZWxlbWVudCBhcmUgZGVzdHJveWVkLg0KICAgICAgKiBZb3Ugc2hvdWxkIHRha2UgdGhpcyBpbnRvIGNvbnNpZGVyYXRpb24gYW5kIG1ha2Ugc3VyZSB0byBhbHdheXMgY2FuY2VsIHRoZSBpbnRlcnZhbCBhdCB0aGUNCiAgICAgICogYXBwcm9wcmlhdGUgbW9tZW50LiAgU2VlIHRoZSBleGFtcGxlIGJlbG93IGZvciBtb3JlIGRldGFpbHMgb24gaG93IGFuZCB3aGVuIHRvIGRvIHRoaXMuDQogICAgICAqIDwvZGl2Pg0KICAgICAgKg0KICAgICAgKiBAcGFyYW0ge2Z1bmN0aW9uKCl9IGZuIEEgZnVuY3Rpb24gdGhhdCBzaG91bGQgYmUgY2FsbGVkIHJlcGVhdGVkbHkuDQogICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkZWxheSBOdW1iZXIgb2YgbWlsbGlzZWNvbmRzIGJldHdlZW4gZWFjaCBmdW5jdGlvbiBjYWxsLg0KICAgICAgKiBAcGFyYW0ge251bWJlcj19IFtjb3VudD0wXSBOdW1iZXIgb2YgdGltZXMgdG8gcmVwZWF0LiBJZiBub3Qgc2V0LCBvciAwLCB3aWxsIHJlcGVhdA0KICAgICAgKiAgIGluZGVmaW5pdGVseS4NCiAgICAgICogQHBhcmFtIHtib29sZWFuPX0gW2ludm9rZUFwcGx5PXRydWVdIElmIHNldCB0byBgZmFsc2VgIHNraXBzIG1vZGVsIGRpcnR5IGNoZWNraW5nLCBvdGhlcndpc2UNCiAgICAgICogICB3aWxsIGludm9rZSBgZm5gIHdpdGhpbiB0aGUge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJGFwcGx5ICRhcHBseX0gYmxvY2suDQogICAgICAqIEByZXR1cm5zIHtwcm9taXNlfSBBIHByb21pc2Ugd2hpY2ggd2lsbCBiZSBub3RpZmllZCBvbiBlYWNoIGl0ZXJhdGlvbi4NCiAgICAgICoNCiAgICAgICogQGV4YW1wbGUNCiAgICAgICogPGV4YW1wbGUgbW9kdWxlPSJpbnRlcnZhbEV4YW1wbGUiPg0KICAgICAgKiA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICogICA8c2NyaXB0Pg0KICAgICAgKiAgICAgYW5ndWxhci5tb2R1bGUoJ2ludGVydmFsRXhhbXBsZScsIFtdKQ0KICAgICAgKiAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsICckaW50ZXJ2YWwnLA0KICAgICAgKiAgICAgICAgIGZ1bmN0aW9uKCRzY29wZSwgJGludGVydmFsKSB7DQogICAgICAqICAgICAgICAgICAkc2NvcGUuZm9ybWF0ID0gJ00vZC95eSBoOm1tOnNzIGEnOw0KICAgICAgKiAgICAgICAgICAgJHNjb3BlLmJsb29kXzEgPSAxMDA7DQogICAgICAqICAgICAgICAgICAkc2NvcGUuYmxvb2RfMiA9IDEyMDsNCiAgICAgICoNCiAgICAgICogICAgICAgICAgIHZhciBzdG9wOw0KICAgICAgKiAgICAgICAgICAgJHNjb3BlLmZpZ2h0ID0gZnVuY3Rpb24oKSB7DQogICAgICAqICAgICAgICAgICAgIC8vIERvbid0IHN0YXJ0IGEgbmV3IGZpZ2h0IGlmIHdlIGFyZSBhbHJlYWR5IGZpZ2h0aW5nDQogICAgICAqICAgICAgICAgICAgIGlmICggYW5ndWxhci5pc0RlZmluZWQoc3RvcCkgKSByZXR1cm47DQogICAgICAqDQogICAgICAqICAgICAgICAgICAgIHN0b3AgPSAkaW50ZXJ2YWwoZnVuY3Rpb24oKSB7DQogICAgICAqICAgICAgICAgICAgICAgaWYgKCRzY29wZS5ibG9vZF8xID4gMCAmJiAkc2NvcGUuYmxvb2RfMiA+IDApIHsNCiAgICAgICogICAgICAgICAgICAgICAgICRzY29wZS5ibG9vZF8xID0gJHNjb3BlLmJsb29kXzEgLSAzOw0KICAgICAgKiAgICAgICAgICAgICAgICAgJHNjb3BlLmJsb29kXzIgPSAkc2NvcGUuYmxvb2RfMiAtIDQ7DQogICAgICAqICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICogICAgICAgICAgICAgICAgICRzY29wZS5zdG9wRmlnaHQoKTsNCiAgICAgICogICAgICAgICAgICAgICB9DQogICAgICAqICAgICAgICAgICAgIH0sIDEwMCk7DQogICAgICAqICAgICAgICAgICB9Ow0KICAgICAgKg0KICAgICAgKiAgICAgICAgICAgJHNjb3BlLnN0b3BGaWdodCA9IGZ1bmN0aW9uKCkgew0KICAgICAgKiAgICAgICAgICAgICBpZiAoYW5ndWxhci5pc0RlZmluZWQoc3RvcCkpIHsNCiAgICAgICogICAgICAgICAgICAgICAkaW50ZXJ2YWwuY2FuY2VsKHN0b3ApOw0KICAgICAgKiAgICAgICAgICAgICAgIHN0b3AgPSB1bmRlZmluZWQ7DQogICAgICAqICAgICAgICAgICAgIH0NCiAgICAgICogICAgICAgICAgIH07DQogICAgICAqDQogICAgICAqICAgICAgICAgICAkc2NvcGUucmVzZXRGaWdodCA9IGZ1bmN0aW9uKCkgew0KICAgICAgKiAgICAgICAgICAgICAkc2NvcGUuYmxvb2RfMSA9IDEwMDsNCiAgICAgICogICAgICAgICAgICAgJHNjb3BlLmJsb29kXzIgPSAxMjA7DQogICAgICAqICAgICAgICAgICB9Ow0KICAgICAgKg0KICAgICAgKiAgICAgICAgICAgJHNjb3BlLiRvbignJGRlc3Ryb3knLCBmdW5jdGlvbigpIHsNCiAgICAgICogICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIGludGVydmFsIGlzIGRlc3Ryb3llZCB0b28NCiAgICAgICogICAgICAgICAgICAgJHNjb3BlLnN0b3BGaWdodCgpOw0KICAgICAgKiAgICAgICAgICAgfSk7DQogICAgICAqICAgICAgICAgfV0pDQogICAgICAqICAgICAgIC8vIFJlZ2lzdGVyIHRoZSAnbXlDdXJyZW50VGltZScgZGlyZWN0aXZlIGZhY3RvcnkgbWV0aG9kLg0KICAgICAgKiAgICAgICAvLyBXZSBpbmplY3QgJGludGVydmFsIGFuZCBkYXRlRmlsdGVyIHNlcnZpY2Ugc2luY2UgdGhlIGZhY3RvcnkgbWV0aG9kIGlzIERJLg0KICAgICAgKiAgICAgICAuZGlyZWN0aXZlKCdteUN1cnJlbnRUaW1lJywgWyckaW50ZXJ2YWwnLCAnZGF0ZUZpbHRlcicsDQogICAgICAqICAgICAgICAgZnVuY3Rpb24oJGludGVydmFsLCBkYXRlRmlsdGVyKSB7DQogICAgICAqICAgICAgICAgICAvLyByZXR1cm4gdGhlIGRpcmVjdGl2ZSBsaW5rIGZ1bmN0aW9uLiAoY29tcGlsZSBmdW5jdGlvbiBub3QgbmVlZGVkKQ0KICAgICAgKiAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHNjb3BlLCBlbGVtZW50LCBhdHRycykgew0KICAgICAgKiAgICAgICAgICAgICB2YXIgZm9ybWF0LCAgLy8gZGF0ZSBmb3JtYXQNCiAgICAgICogICAgICAgICAgICAgICAgIHN0b3BUaW1lOyAvLyBzbyB0aGF0IHdlIGNhbiBjYW5jZWwgdGhlIHRpbWUgdXBkYXRlcw0KICAgICAgKg0KICAgICAgKiAgICAgICAgICAgICAvLyB1c2VkIHRvIHVwZGF0ZSB0aGUgVUkNCiAgICAgICogICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlVGltZSgpIHsNCiAgICAgICogICAgICAgICAgICAgICBlbGVtZW50LnRleHQoZGF0ZUZpbHRlcihuZXcgRGF0ZSgpLCBmb3JtYXQpKTsNCiAgICAgICogICAgICAgICAgICAgfQ0KICAgICAgKg0KICAgICAgKiAgICAgICAgICAgICAvLyB3YXRjaCB0aGUgZXhwcmVzc2lvbiwgYW5kIHVwZGF0ZSB0aGUgVUkgb24gY2hhbmdlLg0KICAgICAgKiAgICAgICAgICAgICBzY29wZS4kd2F0Y2goYXR0cnMubXlDdXJyZW50VGltZSwgZnVuY3Rpb24odmFsdWUpIHsNCiAgICAgICogICAgICAgICAgICAgICBmb3JtYXQgPSB2YWx1ZTsNCiAgICAgICogICAgICAgICAgICAgICB1cGRhdGVUaW1lKCk7DQogICAgICAqICAgICAgICAgICAgIH0pOw0KICAgICAgKg0KICAgICAgKiAgICAgICAgICAgICBzdG9wVGltZSA9ICRpbnRlcnZhbCh1cGRhdGVUaW1lLCAxMDAwKTsNCiAgICAgICoNCiAgICAgICogICAgICAgICAgICAgLy8gbGlzdGVuIG9uIERPTSBkZXN0cm95IChyZW1vdmFsKSBldmVudCwgYW5kIGNhbmNlbCB0aGUgbmV4dCBVSSB1cGRhdGUNCiAgICAgICogICAgICAgICAgICAgLy8gdG8gcHJldmVudCB1cGRhdGluZyB0aW1lIGFmdGVyIHRoZSBET00gZWxlbWVudCB3YXMgcmVtb3ZlZC4NCiAgICAgICogICAgICAgICAgICAgZWxlbWVudC5vbignJGRlc3Ryb3knLCBmdW5jdGlvbigpIHsNCiAgICAgICogICAgICAgICAgICAgICAkaW50ZXJ2YWwuY2FuY2VsKHN0b3BUaW1lKTsNCiAgICAgICogICAgICAgICAgICAgfSk7DQogICAgICAqICAgICAgICAgICB9DQogICAgICAqICAgICAgICAgfV0pOw0KICAgICAgKiAgIDwvc2NyaXB0Pg0KICAgICAgKg0KICAgICAgKiAgIDxkaXY+DQogICAgICAqICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICogICAgICAgRGF0ZSBmb3JtYXQ6IDxpbnB1dCBuZy1tb2RlbD0iZm9ybWF0Ij4gPGhyLz4NCiAgICAgICogICAgICAgQ3VycmVudCB0aW1lIGlzOiA8c3BhbiBteS1jdXJyZW50LXRpbWU9ImZvcm1hdCI+PC9zcGFuPg0KICAgICAgKiAgICAgICA8aHIvPg0KICAgICAgKiAgICAgICBCbG9vZCAxIDogPGZvbnQgY29sb3I9J3JlZCc+e3tibG9vZF8xfX08L2ZvbnQ+DQogICAgICAqICAgICAgIEJsb29kIDIgOiA8Zm9udCBjb2xvcj0ncmVkJz57e2Jsb29kXzJ9fTwvZm9udD4NCiAgICAgICogICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGRhdGEtbmctY2xpY2s9ImZpZ2h0KCkiPkZpZ2h0PC9idXR0b24+DQogICAgICAqICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBkYXRhLW5nLWNsaWNrPSJzdG9wRmlnaHQoKSI+U3RvcEZpZ2h0PC9idXR0b24+DQogICAgICAqICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBkYXRhLW5nLWNsaWNrPSJyZXNldEZpZ2h0KCkiPnJlc2V0RmlnaHQ8L2J1dHRvbj4NCiAgICAgICogICAgIDwvZGl2Pg0KICAgICAgKiAgIDwvZGl2Pg0KICAgICAgKg0KICAgICAgKiA8L2ZpbGU+DQogICAgICAqIDwvZXhhbXBsZT4NCiAgICAgICovDQogICAgZnVuY3Rpb24gaW50ZXJ2YWwoZm4sIGRlbGF5LCBjb3VudCwgaW52b2tlQXBwbHkpIHsNCiAgICAgIHZhciBzZXRJbnRlcnZhbCA9ICR3aW5kb3cuc2V0SW50ZXJ2YWwsDQogICAgICAgICAgY2xlYXJJbnRlcnZhbCA9ICR3aW5kb3cuY2xlYXJJbnRlcnZhbCwNCiAgICAgICAgICBpdGVyYXRpb24gPSAwLA0KICAgICAgICAgIHNraXBBcHBseSA9IChpc0RlZmluZWQoaW52b2tlQXBwbHkpICYmICFpbnZva2VBcHBseSksDQogICAgICAgICAgZGVmZXJyZWQgPSAoc2tpcEFwcGx5ID8gJCRxIDogJHEpLmRlZmVyKCksDQogICAgICAgICAgcHJvbWlzZSA9IGRlZmVycmVkLnByb21pc2U7DQoNCiAgICAgIGNvdW50ID0gaXNEZWZpbmVkKGNvdW50KSA/IGNvdW50IDogMDsNCg0KICAgICAgcHJvbWlzZS50aGVuKG51bGwsIG51bGwsIGZuKTsNCg0KICAgICAgcHJvbWlzZS4kJGludGVydmFsSWQgPSBzZXRJbnRlcnZhbChmdW5jdGlvbiB0aWNrKCkgew0KICAgICAgICBkZWZlcnJlZC5ub3RpZnkoaXRlcmF0aW9uKyspOw0KDQogICAgICAgIGlmIChjb3VudCA+IDAgJiYgaXRlcmF0aW9uID49IGNvdW50KSB7DQogICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZShpdGVyYXRpb24pOw0KICAgICAgICAgIGNsZWFySW50ZXJ2YWwocHJvbWlzZS4kJGludGVydmFsSWQpOw0KICAgICAgICAgIGRlbGV0ZSBpbnRlcnZhbHNbcHJvbWlzZS4kJGludGVydmFsSWRdOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCFza2lwQXBwbHkpICRyb290U2NvcGUuJGFwcGx5KCk7DQoNCiAgICAgIH0sIGRlbGF5KTsNCg0KICAgICAgaW50ZXJ2YWxzW3Byb21pc2UuJCRpbnRlcnZhbElkXSA9IGRlZmVycmVkOw0KDQogICAgICByZXR1cm4gcHJvbWlzZTsNCiAgICB9DQoNCg0KICAgICAvKioNCiAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgKiBAbmFtZSAkaW50ZXJ2YWwjY2FuY2VsDQogICAgICAqDQogICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgKiBDYW5jZWxzIGEgdGFzayBhc3NvY2lhdGVkIHdpdGggdGhlIGBwcm9taXNlYC4NCiAgICAgICoNCiAgICAgICogQHBhcmFtIHtwcm9taXNlfSBwcm9taXNlIHJldHVybmVkIGJ5IHRoZSBgJGludGVydmFsYCBmdW5jdGlvbi4NCiAgICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB0YXNrIHdhcyBzdWNjZXNzZnVsbHkgY2FuY2VsZWQuDQogICAgICAqLw0KICAgIGludGVydmFsLmNhbmNlbCA9IGZ1bmN0aW9uKHByb21pc2UpIHsNCiAgICAgIGlmIChwcm9taXNlICYmIHByb21pc2UuJCRpbnRlcnZhbElkIGluIGludGVydmFscykgew0KICAgICAgICBpbnRlcnZhbHNbcHJvbWlzZS4kJGludGVydmFsSWRdLnJlamVjdCgnY2FuY2VsZWQnKTsNCiAgICAgICAgJHdpbmRvdy5jbGVhckludGVydmFsKHByb21pc2UuJCRpbnRlcnZhbElkKTsNCiAgICAgICAgZGVsZXRlIGludGVydmFsc1twcm9taXNlLiQkaW50ZXJ2YWxJZF07DQogICAgICAgIHJldHVybiB0cnVlOw0KICAgICAgfQ0KICAgICAgcmV0dXJuIGZhbHNlOw0KICAgIH07DQoNCiAgICByZXR1cm4gaW50ZXJ2YWw7DQogIH1dOw0KfQ0KDQovKioNCiAqIEBuZ2RvYyBzZXJ2aWNlDQogKiBAbmFtZSAkbG9jYWxlDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiAkbG9jYWxlIHNlcnZpY2UgcHJvdmlkZXMgbG9jYWxpemF0aW9uIHJ1bGVzIGZvciB2YXJpb3VzIEFuZ3VsYXIgY29tcG9uZW50cy4gQXMgb2YgcmlnaHQgbm93IHRoZQ0KICogb25seSBwdWJsaWMgYXBpIGlzOg0KICoNCiAqICogYGlkYCDigD8gYHtzdHJpbmd9YCDigD8gbG9jYWxlIGlkIGZvcm1hdHRlZCBhcyBgbGFuZ3VhZ2VJZC1jb3VudHJ5SWRgIChlLmcuIGBlbi11c2ApDQogKi8NCmZ1bmN0aW9uICRMb2NhbGVQcm92aWRlcigpIHsNCiAgdGhpcy4kZ2V0ID0gZnVuY3Rpb24oKSB7DQogICAgcmV0dXJuIHsNCiAgICAgIGlkOiAnZW4tdXMnLA0KDQogICAgICBOVU1CRVJfRk9STUFUUzogew0KICAgICAgICBERUNJTUFMX1NFUDogJy4nLA0KICAgICAgICBHUk9VUF9TRVA6ICcsJywNCiAgICAgICAgUEFUVEVSTlM6IFsNCiAgICAgICAgICB7IC8vIERlY2ltYWwgUGF0dGVybg0KICAgICAgICAgICAgbWluSW50OiAxLA0KICAgICAgICAgICAgbWluRnJhYzogMCwNCiAgICAgICAgICAgIG1heEZyYWM6IDMsDQogICAgICAgICAgICBwb3NQcmU6ICcnLA0KICAgICAgICAgICAgcG9zU3VmOiAnJywNCiAgICAgICAgICAgIG5lZ1ByZTogJy0nLA0KICAgICAgICAgICAgbmVnU3VmOiAnJywNCiAgICAgICAgICAgIGdTaXplOiAzLA0KICAgICAgICAgICAgbGdTaXplOiAzDQogICAgICAgICAgfSx7IC8vQ3VycmVuY3kgUGF0dGVybg0KICAgICAgICAgICAgbWluSW50OiAxLA0KICAgICAgICAgICAgbWluRnJhYzogMiwNCiAgICAgICAgICAgIG1heEZyYWM6IDIsDQogICAgICAgICAgICBwb3NQcmU6ICdcdTAwQTQnLA0KICAgICAgICAgICAgcG9zU3VmOiAnJywNCiAgICAgICAgICAgIG5lZ1ByZTogJyhcdTAwQTQnLA0KICAgICAgICAgICAgbmVnU3VmOiAnKScsDQogICAgICAgICAgICBnU2l6ZTogMywNCiAgICAgICAgICAgIGxnU2l6ZTogMw0KICAgICAgICAgIH0NCiAgICAgICAgXSwNCiAgICAgICAgQ1VSUkVOQ1lfU1lNOiAnJCcNCiAgICAgIH0sDQoNCiAgICAgIERBVEVUSU1FX0ZPUk1BVFM6IHsNCiAgICAgICAgTU9OVEg6DQogICAgICAgICAgICAnSmFudWFyeSxGZWJydWFyeSxNYXJjaCxBcHJpbCxNYXksSnVuZSxKdWx5LEF1Z3VzdCxTZXB0ZW1iZXIsT2N0b2JlcixOb3ZlbWJlcixEZWNlbWJlcicNCiAgICAgICAgICAgIC5zcGxpdCgnLCcpLA0KICAgICAgICBTSE9SVE1PTlRIOiAgJ0phbixGZWIsTWFyLEFwcixNYXksSnVuLEp1bCxBdWcsU2VwLE9jdCxOb3YsRGVjJy5zcGxpdCgnLCcpLA0KICAgICAgICBEQVk6ICdTdW5kYXksTW9uZGF5LFR1ZXNkYXksV2VkbmVzZGF5LFRodXJzZGF5LEZyaWRheSxTYXR1cmRheScuc3BsaXQoJywnKSwNCiAgICAgICAgU0hPUlREQVk6ICdTdW4sTW9uLFR1ZSxXZWQsVGh1LEZyaSxTYXQnLnNwbGl0KCcsJyksDQogICAgICAgIEFNUE1TOiBbJ0FNJywnUE0nXSwNCiAgICAgICAgbWVkaXVtOiAnTU1NIGQsIHkgaDptbTpzcyBhJywNCiAgICAgICAgJ3Nob3J0JzogJ00vZC95eSBoOm1tIGEnLA0KICAgICAgICBmdWxsRGF0ZTogJ0VFRUUsIE1NTU0gZCwgeScsDQogICAgICAgIGxvbmdEYXRlOiAnTU1NTSBkLCB5JywNCiAgICAgICAgbWVkaXVtRGF0ZTogJ01NTSBkLCB5JywNCiAgICAgICAgc2hvcnREYXRlOiAnTS9kL3l5JywNCiAgICAgICAgbWVkaXVtVGltZTogJ2g6bW06c3MgYScsDQogICAgICAgIHNob3J0VGltZTogJ2g6bW0gYScNCiAgICAgIH0sDQoNCiAgICAgIHBsdXJhbENhdDogZnVuY3Rpb24obnVtKSB7DQogICAgICAgIGlmIChudW0gPT09IDEpIHsNCiAgICAgICAgICByZXR1cm4gJ29uZSc7DQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuICdvdGhlcic7DQogICAgICB9DQogICAgfTsNCiAgfTsNCn0NCg0KdmFyIFBBVEhfTUFUQ0ggPSAvXihbXlw/I10qKShcPyhbXiNdKikpPygjKC4qKSk/JC8sDQogICAgREVGQVVMVF9QT1JUUyA9IHsnaHR0cCc6IDgwLCAnaHR0cHMnOiA0NDMsICdmdHAnOiAyMX07DQp2YXIgJGxvY2F0aW9uTWluRXJyID0gbWluRXJyKCckbG9jYXRpb24nKTsNCg0KDQovKioNCiAqIEVuY29kZSBwYXRoIHVzaW5nIGVuY29kZVVyaVNlZ21lbnQsIGlnbm9yaW5nIGZvcndhcmQgc2xhc2hlcw0KICoNCiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIFBhdGggdG8gZW5jb2RlDQogKiBAcmV0dXJucyB7c3RyaW5nfQ0KICovDQpmdW5jdGlvbiBlbmNvZGVQYXRoKHBhdGgpIHsNCiAgdmFyIHNlZ21lbnRzID0gcGF0aC5zcGxpdCgnLycpLA0KICAgICAgaSA9IHNlZ21lbnRzLmxlbmd0aDsNCg0KICB3aGlsZSAoaS0tKSB7DQogICAgc2VnbWVudHNbaV0gPSBlbmNvZGVVcmlTZWdtZW50KHNlZ21lbnRzW2ldKTsNCiAgfQ0KDQogIHJldHVybiBzZWdtZW50cy5qb2luKCcvJyk7DQp9DQoNCmZ1bmN0aW9uIHBhcnNlQWJzb2x1dGVVcmwoYWJzb2x1dGVVcmwsIGxvY2F0aW9uT2JqKSB7DQogIHZhciBwYXJzZWRVcmwgPSB1cmxSZXNvbHZlKGFic29sdXRlVXJsKTsNCg0KICBsb2NhdGlvbk9iai4kJHByb3RvY29sID0gcGFyc2VkVXJsLnByb3RvY29sOw0KICBsb2NhdGlvbk9iai4kJGhvc3QgPSBwYXJzZWRVcmwuaG9zdG5hbWU7DQogIGxvY2F0aW9uT2JqLiQkcG9ydCA9IGludChwYXJzZWRVcmwucG9ydCkgfHwgREVGQVVMVF9QT1JUU1twYXJzZWRVcmwucHJvdG9jb2xdIHx8IG51bGw7DQp9DQoNCg0KZnVuY3Rpb24gcGFyc2VBcHBVcmwocmVsYXRpdmVVcmwsIGxvY2F0aW9uT2JqKSB7DQogIHZhciBwcmVmaXhlZCA9IChyZWxhdGl2ZVVybC5jaGFyQXQoMCkgIT09ICcvJyk7DQogIGlmIChwcmVmaXhlZCkgew0KICAgIHJlbGF0aXZlVXJsID0gJy8nICsgcmVsYXRpdmVVcmw7DQogIH0NCiAgdmFyIG1hdGNoID0gdXJsUmVzb2x2ZShyZWxhdGl2ZVVybCk7DQogIGxvY2F0aW9uT2JqLiQkcGF0aCA9IGRlY29kZVVSSUNvbXBvbmVudChwcmVmaXhlZCAmJiBtYXRjaC5wYXRobmFtZS5jaGFyQXQoMCkgPT09ICcvJyA/DQogICAgICBtYXRjaC5wYXRobmFtZS5zdWJzdHJpbmcoMSkgOiBtYXRjaC5wYXRobmFtZSk7DQogIGxvY2F0aW9uT2JqLiQkc2VhcmNoID0gcGFyc2VLZXlWYWx1ZShtYXRjaC5zZWFyY2gpOw0KICBsb2NhdGlvbk9iai4kJGhhc2ggPSBkZWNvZGVVUklDb21wb25lbnQobWF0Y2guaGFzaCk7DQoNCiAgLy8gbWFrZSBzdXJlIHBhdGggc3RhcnRzIHdpdGggJy8nOw0KICBpZiAobG9jYXRpb25PYmouJCRwYXRoICYmIGxvY2F0aW9uT2JqLiQkcGF0aC5jaGFyQXQoMCkgIT0gJy8nKSB7DQogICAgbG9jYXRpb25PYmouJCRwYXRoID0gJy8nICsgbG9jYXRpb25PYmouJCRwYXRoOw0KICB9DQp9DQoNCg0KLyoqDQogKg0KICogQHBhcmFtIHtzdHJpbmd9IGJlZ2luDQogKiBAcGFyYW0ge3N0cmluZ30gd2hvbGUNCiAqIEByZXR1cm5zIHtzdHJpbmd9IHJldHVybnMgdGV4dCBmcm9tIHdob2xlIGFmdGVyIGJlZ2luIG9yIHVuZGVmaW5lZCBpZiBpdCBkb2VzIG5vdCBiZWdpbiB3aXRoDQogKiAgICAgICAgICAgICAgICAgICBleHBlY3RlZCBzdHJpbmcuDQogKi8NCmZ1bmN0aW9uIGJlZ2luc1dpdGgoYmVnaW4sIHdob2xlKSB7DQogIGlmICh3aG9sZS5pbmRleE9mKGJlZ2luKSA9PT0gMCkgew0KICAgIHJldHVybiB3aG9sZS5zdWJzdHIoYmVnaW4ubGVuZ3RoKTsNCiAgfQ0KfQ0KDQoNCmZ1bmN0aW9uIHN0cmlwSGFzaCh1cmwpIHsNCiAgdmFyIGluZGV4ID0gdXJsLmluZGV4T2YoJyMnKTsNCiAgcmV0dXJuIGluZGV4ID09IC0xID8gdXJsIDogdXJsLnN1YnN0cigwLCBpbmRleCk7DQp9DQoNCmZ1bmN0aW9uIHRyaW1FbXB0eUhhc2godXJsKSB7DQogIHJldHVybiB1cmwucmVwbGFjZSgvKCMuKyl8IyQvLCAnJDEnKTsNCn0NCg0KDQpmdW5jdGlvbiBzdHJpcEZpbGUodXJsKSB7DQogIHJldHVybiB1cmwuc3Vic3RyKDAsIHN0cmlwSGFzaCh1cmwpLmxhc3RJbmRleE9mKCcvJykgKyAxKTsNCn0NCg0KLyogcmV0dXJuIHRoZSBzZXJ2ZXIgb25seSAoc2NoZW1lOi8vaG9zdDpwb3J0KSAqLw0KZnVuY3Rpb24gc2VydmVyQmFzZSh1cmwpIHsNCiAgcmV0dXJuIHVybC5zdWJzdHJpbmcoMCwgdXJsLmluZGV4T2YoJy8nLCB1cmwuaW5kZXhPZignLy8nKSArIDIpKTsNCn0NCg0KDQovKioNCiAqIExvY2F0aW9uSHRtbDVVcmwgcmVwcmVzZW50cyBhbiB1cmwNCiAqIFRoaXMgb2JqZWN0IGlzIGV4cG9zZWQgYXMgJGxvY2F0aW9uIHNlcnZpY2Ugd2hlbiBIVE1MNSBtb2RlIGlzIGVuYWJsZWQgYW5kIHN1cHBvcnRlZA0KICoNCiAqIEBjb25zdHJ1Y3Rvcg0KICogQHBhcmFtIHtzdHJpbmd9IGFwcEJhc2UgYXBwbGljYXRpb24gYmFzZSBVUkwNCiAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlUHJlZml4IHVybCBwYXRoIHByZWZpeA0KICovDQpmdW5jdGlvbiBMb2NhdGlvbkh0bWw1VXJsKGFwcEJhc2UsIGJhc2VQcmVmaXgpIHsNCiAgdGhpcy4kJGh0bWw1ID0gdHJ1ZTsNCiAgYmFzZVByZWZpeCA9IGJhc2VQcmVmaXggfHwgJyc7DQogIHZhciBhcHBCYXNlTm9GaWxlID0gc3RyaXBGaWxlKGFwcEJhc2UpOw0KICBwYXJzZUFic29sdXRlVXJsKGFwcEJhc2UsIHRoaXMpOw0KDQoNCiAgLyoqDQogICAqIFBhcnNlIGdpdmVuIGh0bWw1IChyZWd1bGFyKSB1cmwgc3RyaW5nIGludG8gcHJvcGVydGllcw0KICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIEhUTUw1IHVybA0KICAgKiBAcHJpdmF0ZQ0KICAgKi8NCiAgdGhpcy4kJHBhcnNlID0gZnVuY3Rpb24odXJsKSB7DQogICAgdmFyIHBhdGhVcmwgPSBiZWdpbnNXaXRoKGFwcEJhc2VOb0ZpbGUsIHVybCk7DQogICAgaWYgKCFpc1N0cmluZyhwYXRoVXJsKSkgew0KICAgICAgdGhyb3cgJGxvY2F0aW9uTWluRXJyKCdpcHRocHJmeCcsICdJbnZhbGlkIHVybCAiezB9IiwgbWlzc2luZyBwYXRoIHByZWZpeCAiezF9Ii4nLCB1cmwsDQogICAgICAgICAgYXBwQmFzZU5vRmlsZSk7DQogICAgfQ0KDQogICAgcGFyc2VBcHBVcmwocGF0aFVybCwgdGhpcyk7DQoNCiAgICBpZiAoIXRoaXMuJCRwYXRoKSB7DQogICAgICB0aGlzLiQkcGF0aCA9ICcvJzsNCiAgICB9DQoNCiAgICB0aGlzLiQkY29tcG9zZSgpOw0KICB9Ow0KDQogIC8qKg0KICAgKiBDb21wb3NlIHVybCBhbmQgdXBkYXRlIGBhYnNVcmxgIHByb3BlcnR5DQogICAqIEBwcml2YXRlDQogICAqLw0KICB0aGlzLiQkY29tcG9zZSA9IGZ1bmN0aW9uKCkgew0KICAgIHZhciBzZWFyY2ggPSB0b0tleVZhbHVlKHRoaXMuJCRzZWFyY2gpLA0KICAgICAgICBoYXNoID0gdGhpcy4kJGhhc2ggPyAnIycgKyBlbmNvZGVVcmlTZWdtZW50KHRoaXMuJCRoYXNoKSA6ICcnOw0KDQogICAgdGhpcy4kJHVybCA9IGVuY29kZVBhdGgodGhpcy4kJHBhdGgpICsgKHNlYXJjaCA/ICc/JyArIHNlYXJjaCA6ICcnKSArIGhhc2g7DQogICAgdGhpcy4kJGFic1VybCA9IGFwcEJhc2VOb0ZpbGUgKyB0aGlzLiQkdXJsLnN1YnN0cigxKTsgLy8gZmlyc3QgY2hhciBpcyBhbHdheXMgJy8nDQogIH07DQoNCiAgdGhpcy4kJHBhcnNlTGlua1VybCA9IGZ1bmN0aW9uKHVybCwgcmVsSHJlZikgew0KICAgIGlmIChyZWxIcmVmICYmIHJlbEhyZWZbMF0gPT09ICcjJykgew0KICAgICAgLy8gc3BlY2lhbCBjYXNlIGZvciBsaW5rcyB0byBoYXNoIGZyYWdtZW50czoNCiAgICAgIC8vIGtlZXAgdGhlIG9sZCB1cmwgYW5kIG9ubHkgcmVwbGFjZSB0aGUgaGFzaCBmcmFnbWVudA0KICAgICAgdGhpcy5oYXNoKHJlbEhyZWYuc2xpY2UoMSkpOw0KICAgICAgcmV0dXJuIHRydWU7DQogICAgfQ0KICAgIHZhciBhcHBVcmwsIHByZXZBcHBVcmw7DQogICAgdmFyIHJld3JpdHRlblVybDsNCg0KICAgIGlmICgoYXBwVXJsID0gYmVnaW5zV2l0aChhcHBCYXNlLCB1cmwpKSAhPT0gdW5kZWZpbmVkKSB7DQogICAgICBwcmV2QXBwVXJsID0gYXBwVXJsOw0KICAgICAgaWYgKChhcHBVcmwgPSBiZWdpbnNXaXRoKGJhc2VQcmVmaXgsIGFwcFVybCkpICE9PSB1bmRlZmluZWQpIHsNCiAgICAgICAgcmV3cml0dGVuVXJsID0gYXBwQmFzZU5vRmlsZSArIChiZWdpbnNXaXRoKCcvJywgYXBwVXJsKSB8fCBhcHBVcmwpOw0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgcmV3cml0dGVuVXJsID0gYXBwQmFzZSArIHByZXZBcHBVcmw7DQogICAgICB9DQogICAgfSBlbHNlIGlmICgoYXBwVXJsID0gYmVnaW5zV2l0aChhcHBCYXNlTm9GaWxlLCB1cmwpKSAhPT0gdW5kZWZpbmVkKSB7DQogICAgICByZXdyaXR0ZW5VcmwgPSBhcHBCYXNlTm9GaWxlICsgYXBwVXJsOw0KICAgIH0gZWxzZSBpZiAoYXBwQmFzZU5vRmlsZSA9PSB1cmwgKyAnLycpIHsNCiAgICAgIHJld3JpdHRlblVybCA9IGFwcEJhc2VOb0ZpbGU7DQogICAgfQ0KICAgIGlmIChyZXdyaXR0ZW5VcmwpIHsNCiAgICAgIHRoaXMuJCRwYXJzZShyZXdyaXR0ZW5VcmwpOw0KICAgIH0NCiAgICByZXR1cm4gISFyZXdyaXR0ZW5Vcmw7DQogIH07DQp9DQoNCg0KLyoqDQogKiBMb2NhdGlvbkhhc2hiYW5nVXJsIHJlcHJlc2VudHMgdXJsDQogKiBUaGlzIG9iamVjdCBpcyBleHBvc2VkIGFzICRsb2NhdGlvbiBzZXJ2aWNlIHdoZW4gZGV2ZWxvcGVyIGRvZXNuJ3Qgb3B0IGludG8gaHRtbDUgbW9kZS4NCiAqIEl0IGFsc28gc2VydmVzIGFzIHRoZSBiYXNlIGNsYXNzIGZvciBodG1sNSBtb2RlIGZhbGxiYWNrIG9uIGxlZ2FjeSBicm93c2Vycy4NCiAqDQogKiBAY29uc3RydWN0b3INCiAqIEBwYXJhbSB7c3RyaW5nfSBhcHBCYXNlIGFwcGxpY2F0aW9uIGJhc2UgVVJMDQogKiBAcGFyYW0ge3N0cmluZ30gaGFzaFByZWZpeCBoYXNoYmFuZyBwcmVmaXgNCiAqLw0KZnVuY3Rpb24gTG9jYXRpb25IYXNoYmFuZ1VybChhcHBCYXNlLCBoYXNoUHJlZml4KSB7DQogIHZhciBhcHBCYXNlTm9GaWxlID0gc3RyaXBGaWxlKGFwcEJhc2UpOw0KDQogIHBhcnNlQWJzb2x1dGVVcmwoYXBwQmFzZSwgdGhpcyk7DQoNCg0KICAvKioNCiAgICogUGFyc2UgZ2l2ZW4gaGFzaGJhbmcgdXJsIGludG8gcHJvcGVydGllcw0KICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIEhhc2hiYW5nIHVybA0KICAgKiBAcHJpdmF0ZQ0KICAgKi8NCiAgdGhpcy4kJHBhcnNlID0gZnVuY3Rpb24odXJsKSB7DQogICAgdmFyIHdpdGhvdXRCYXNlVXJsID0gYmVnaW5zV2l0aChhcHBCYXNlLCB1cmwpIHx8IGJlZ2luc1dpdGgoYXBwQmFzZU5vRmlsZSwgdXJsKTsNCiAgICB2YXIgd2l0aG91dEhhc2hVcmw7DQoNCiAgICBpZiAod2l0aG91dEJhc2VVcmwuY2hhckF0KDApID09PSAnIycpIHsNCg0KICAgICAgLy8gVGhlIHJlc3Qgb2YgdGhlIHVybCBzdGFydHMgd2l0aCBhIGhhc2ggc28gd2UgaGF2ZQ0KICAgICAgLy8gZ290IGVpdGhlciBhIGhhc2hiYW5nIHBhdGggb3IgYSBwbGFpbiBoYXNoIGZyYWdtZW50DQogICAgICB3aXRob3V0SGFzaFVybCA9IGJlZ2luc1dpdGgoaGFzaFByZWZpeCwgd2l0aG91dEJhc2VVcmwpOw0KICAgICAgaWYgKGlzVW5kZWZpbmVkKHdpdGhvdXRIYXNoVXJsKSkgew0KICAgICAgICAvLyBUaGVyZSB3YXMgbm8gaGFzaGJhbmcgcHJlZml4IHNvIHdlIGp1c3QgaGF2ZSBhIGhhc2ggZnJhZ21lbnQNCiAgICAgICAgd2l0aG91dEhhc2hVcmwgPSB3aXRob3V0QmFzZVVybDsNCiAgICAgIH0NCg0KICAgIH0gZWxzZSB7DQogICAgICAvLyBUaGVyZSB3YXMgbm8gaGFzaGJhbmcgcGF0aCBub3IgaGFzaCBmcmFnbWVudDoNCiAgICAgIC8vIElmIHdlIGFyZSBpbiBIVE1MNSBtb2RlIHdlIHVzZSB3aGF0IGlzIGxlZnQgYXMgdGhlIHBhdGg7DQogICAgICAvLyBPdGhlcndpc2Ugd2UgaWdub3JlIHdoYXQgaXMgbGVmdA0KICAgICAgd2l0aG91dEhhc2hVcmwgPSB0aGlzLiQkaHRtbDUgPyB3aXRob3V0QmFzZVVybCA6ICcnOw0KICAgIH0NCg0KICAgIHBhcnNlQXBwVXJsKHdpdGhvdXRIYXNoVXJsLCB0aGlzKTsNCg0KICAgIHRoaXMuJCRwYXRoID0gcmVtb3ZlV2luZG93c0RyaXZlTmFtZSh0aGlzLiQkcGF0aCwgd2l0aG91dEhhc2hVcmwsIGFwcEJhc2UpOw0KDQogICAgdGhpcy4kJGNvbXBvc2UoKTsNCg0KICAgIC8qDQogICAgICogSW4gV2luZG93cywgb24gYW4gYW5jaG9yIG5vZGUgb24gZG9jdW1lbnRzIGxvYWRlZCBmcm9tDQogICAgICogdGhlIGZpbGVzeXN0ZW0sIHRoZSBicm93c2VyIHdpbGwgcmV0dXJuIGEgcGF0aG5hbWUNCiAgICAgKiBwcmVmaXhlZCB3aXRoIHRoZSBkcml2ZSBuYW1lICgnL0M6L3BhdGgnKSB3aGVuIGENCiAgICAgKiBwYXRobmFtZSB3aXRob3V0IGEgZHJpdmUgaXMgc2V0Og0KICAgICAqICAqIGEuc2V0QXR0cmlidXRlKCdocmVmJywgJy9mb28nKQ0KICAgICAqICAgKiBhLnBhdGhuYW1lID09PSAnL0M6L2ZvbycgLy90cnVlDQogICAgICoNCiAgICAgKiBJbnNpZGUgb2YgQW5ndWxhciwgd2UncmUgYWx3YXlzIHVzaW5nIHBhdGhuYW1lcyB0aGF0DQogICAgICogZG8gbm90IGluY2x1ZGUgZHJpdmUgbmFtZXMgZm9yIHJvdXRpbmcuDQogICAgICovDQogICAgZnVuY3Rpb24gcmVtb3ZlV2luZG93c0RyaXZlTmFtZShwYXRoLCB1cmwsIGJhc2UpIHsNCiAgICAgIC8qDQogICAgICBNYXRjaGVzIHBhdGhzIGZvciBmaWxlIHByb3RvY29sIG9uIHdpbmRvd3MsDQogICAgICBzdWNoIGFzIC9DOi9mb28vYmFyLCBhbmQgY2FwdHVyZXMgb25seSAvZm9vL2Jhci4NCiAgICAgICovDQogICAgICB2YXIgd2luZG93c0ZpbGVQYXRoRXhwID0gL15cL1tBLVpdOihcLy4qKS87DQoNCiAgICAgIHZhciBmaXJzdFBhdGhTZWdtZW50TWF0Y2g7DQoNCiAgICAgIC8vR2V0IHRoZSByZWxhdGl2ZSBwYXRoIGZyb20gdGhlIGlucHV0IFVSTC4NCiAgICAgIGlmICh1cmwuaW5kZXhPZihiYXNlKSA9PT0gMCkgew0KICAgICAgICB1cmwgPSB1cmwucmVwbGFjZShiYXNlLCAnJyk7DQogICAgICB9DQoNCiAgICAgIC8vIFRoZSBpbnB1dCBVUkwgaW50ZW50aW9uYWxseSBjb250YWlucyBhIGZpcnN0IHBhdGggc2VnbWVudCB0aGF0IGVuZHMgd2l0aCBhIGNvbG9uLg0KICAgICAgaWYgKHdpbmRvd3NGaWxlUGF0aEV4cC5leGVjKHVybCkpIHsNCiAgICAgICAgcmV0dXJuIHBhdGg7DQogICAgICB9DQoNCiAgICAgIGZpcnN0UGF0aFNlZ21lbnRNYXRjaCA9IHdpbmRvd3NGaWxlUGF0aEV4cC5leGVjKHBhdGgpOw0KICAgICAgcmV0dXJuIGZpcnN0UGF0aFNlZ21lbnRNYXRjaCA/IGZpcnN0UGF0aFNlZ21lbnRNYXRjaFsxXSA6IHBhdGg7DQogICAgfQ0KICB9Ow0KDQogIC8qKg0KICAgKiBDb21wb3NlIGhhc2hiYW5nIHVybCBhbmQgdXBkYXRlIGBhYnNVcmxgIHByb3BlcnR5DQogICAqIEBwcml2YXRlDQogICAqLw0KICB0aGlzLiQkY29tcG9zZSA9IGZ1bmN0aW9uKCkgew0KICAgIHZhciBzZWFyY2ggPSB0b0tleVZhbHVlKHRoaXMuJCRzZWFyY2gpLA0KICAgICAgICBoYXNoID0gdGhpcy4kJGhhc2ggPyAnIycgKyBlbmNvZGVVcmlTZWdtZW50KHRoaXMuJCRoYXNoKSA6ICcnOw0KDQogICAgdGhpcy4kJHVybCA9IGVuY29kZVBhdGgodGhpcy4kJHBhdGgpICsgKHNlYXJjaCA/ICc/JyArIHNlYXJjaCA6ICcnKSArIGhhc2g7DQogICAgdGhpcy4kJGFic1VybCA9IGFwcEJhc2UgKyAodGhpcy4kJHVybCA/IGhhc2hQcmVmaXggKyB0aGlzLiQkdXJsIDogJycpOw0KICB9Ow0KDQogIHRoaXMuJCRwYXJzZUxpbmtVcmwgPSBmdW5jdGlvbih1cmwsIHJlbEhyZWYpIHsNCiAgICBpZiAoc3RyaXBIYXNoKGFwcEJhc2UpID09IHN0cmlwSGFzaCh1cmwpKSB7DQogICAgICB0aGlzLiQkcGFyc2UodXJsKTsNCiAgICAgIHJldHVybiB0cnVlOw0KICAgIH0NCiAgICByZXR1cm4gZmFsc2U7DQogIH07DQp9DQoNCg0KLyoqDQogKiBMb2NhdGlvbkhhc2hiYW5nVXJsIHJlcHJlc2VudHMgdXJsDQogKiBUaGlzIG9iamVjdCBpcyBleHBvc2VkIGFzICRsb2NhdGlvbiBzZXJ2aWNlIHdoZW4gaHRtbDUgaGlzdG9yeSBhcGkgaXMgZW5hYmxlZCBidXQgdGhlIGJyb3dzZXINCiAqIGRvZXMgbm90IHN1cHBvcnQgaXQuDQogKg0KICogQGNvbnN0cnVjdG9yDQogKiBAcGFyYW0ge3N0cmluZ30gYXBwQmFzZSBhcHBsaWNhdGlvbiBiYXNlIFVSTA0KICogQHBhcmFtIHtzdHJpbmd9IGhhc2hQcmVmaXggaGFzaGJhbmcgcHJlZml4DQogKi8NCmZ1bmN0aW9uIExvY2F0aW9uSGFzaGJhbmdJbkh0bWw1VXJsKGFwcEJhc2UsIGhhc2hQcmVmaXgpIHsNCiAgdGhpcy4kJGh0bWw1ID0gdHJ1ZTsNCiAgTG9jYXRpb25IYXNoYmFuZ1VybC5hcHBseSh0aGlzLCBhcmd1bWVudHMpOw0KDQogIHZhciBhcHBCYXNlTm9GaWxlID0gc3RyaXBGaWxlKGFwcEJhc2UpOw0KDQogIHRoaXMuJCRwYXJzZUxpbmtVcmwgPSBmdW5jdGlvbih1cmwsIHJlbEhyZWYpIHsNCiAgICBpZiAocmVsSHJlZiAmJiByZWxIcmVmWzBdID09PSAnIycpIHsNCiAgICAgIC8vIHNwZWNpYWwgY2FzZSBmb3IgbGlua3MgdG8gaGFzaCBmcmFnbWVudHM6DQogICAgICAvLyBrZWVwIHRoZSBvbGQgdXJsIGFuZCBvbmx5IHJlcGxhY2UgdGhlIGhhc2ggZnJhZ21lbnQNCiAgICAgIHRoaXMuaGFzaChyZWxIcmVmLnNsaWNlKDEpKTsNCiAgICAgIHJldHVybiB0cnVlOw0KICAgIH0NCg0KICAgIHZhciByZXdyaXR0ZW5Vcmw7DQogICAgdmFyIGFwcFVybDsNCg0KICAgIGlmIChhcHBCYXNlID09IHN0cmlwSGFzaCh1cmwpKSB7DQogICAgICByZXdyaXR0ZW5VcmwgPSB1cmw7DQogICAgfSBlbHNlIGlmICgoYXBwVXJsID0gYmVnaW5zV2l0aChhcHBCYXNlTm9GaWxlLCB1cmwpKSkgew0KICAgICAgcmV3cml0dGVuVXJsID0gYXBwQmFzZSArIGhhc2hQcmVmaXggKyBhcHBVcmw7DQogICAgfSBlbHNlIGlmIChhcHBCYXNlTm9GaWxlID09PSB1cmwgKyAnLycpIHsNCiAgICAgIHJld3JpdHRlblVybCA9IGFwcEJhc2VOb0ZpbGU7DQogICAgfQ0KICAgIGlmIChyZXdyaXR0ZW5VcmwpIHsNCiAgICAgIHRoaXMuJCRwYXJzZShyZXdyaXR0ZW5VcmwpOw0KICAgIH0NCiAgICByZXR1cm4gISFyZXdyaXR0ZW5Vcmw7DQogIH07DQoNCiAgdGhpcy4kJGNvbXBvc2UgPSBmdW5jdGlvbigpIHsNCiAgICB2YXIgc2VhcmNoID0gdG9LZXlWYWx1ZSh0aGlzLiQkc2VhcmNoKSwNCiAgICAgICAgaGFzaCA9IHRoaXMuJCRoYXNoID8gJyMnICsgZW5jb2RlVXJpU2VnbWVudCh0aGlzLiQkaGFzaCkgOiAnJzsNCg0KICAgIHRoaXMuJCR1cmwgPSBlbmNvZGVQYXRoKHRoaXMuJCRwYXRoKSArIChzZWFyY2ggPyAnPycgKyBzZWFyY2ggOiAnJykgKyBoYXNoOw0KICAgIC8vIGluY2x1ZGUgaGFzaFByZWZpeCBpbiAkJGFic1VybCB3aGVuICQkdXJsIGlzIGVtcHR5IHNvIElFOCAmIDkgZG8gbm90IHJlbG9hZCBwYWdlIGJlY2F1c2Ugb2YgcmVtb3ZhbCBvZiAnIycNCiAgICB0aGlzLiQkYWJzVXJsID0gYXBwQmFzZSArIGhhc2hQcmVmaXggKyB0aGlzLiQkdXJsOw0KICB9Ow0KDQp9DQoNCg0KdmFyIGxvY2F0aW9uUHJvdG90eXBlID0gew0KDQogIC8qKg0KICAgKiBBcmUgd2UgaW4gaHRtbDUgbW9kZT8NCiAgICogQHByaXZhdGUNCiAgICovDQogICQkaHRtbDU6IGZhbHNlLA0KDQogIC8qKg0KICAgKiBIYXMgYW55IGNoYW5nZSBiZWVuIHJlcGxhY2luZz8NCiAgICogQHByaXZhdGUNCiAgICovDQogICQkcmVwbGFjZTogZmFsc2UsDQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgJGxvY2F0aW9uI2Fic1VybA0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogVGhpcyBtZXRob2QgaXMgZ2V0dGVyIG9ubHkuDQogICAqDQogICAqIFJldHVybiBmdWxsIHVybCByZXByZXNlbnRhdGlvbiB3aXRoIGFsbCBzZWdtZW50cyBlbmNvZGVkIGFjY29yZGluZyB0byBydWxlcyBzcGVjaWZpZWQgaW4NCiAgICogW1JGQyAzOTg2XShodHRwOi8vd3d3LmlldGYub3JnL3JmYy9yZmMzOTg2LnR4dCkuDQogICAqDQogICAqDQogICAqIGBgYGpzDQogICAqIC8vIGdpdmVuIHVybCBodHRwOi8vZXhhbXBsZS5jb20vIy9zb21lL3BhdGg/Zm9vPWJhciZiYXo9eG94bw0KICAgKiB2YXIgYWJzVXJsID0gJGxvY2F0aW9uLmFic1VybCgpOw0KICAgKiAvLyA9PiAiaHR0cDovL2V4YW1wbGUuY29tLyMvc29tZS9wYXRoP2Zvbz1iYXImYmF6PXhveG8iDQogICAqIGBgYA0KICAgKg0KICAgKiBAcmV0dXJuIHtzdHJpbmd9IGZ1bGwgdXJsDQogICAqLw0KICBhYnNVcmw6IGxvY2F0aW9uR2V0dGVyKCckJGFic1VybCcpLA0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lICRsb2NhdGlvbiN1cmwNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFRoaXMgbWV0aG9kIGlzIGdldHRlciAvIHNldHRlci4NCiAgICoNCiAgICogUmV0dXJuIHVybCAoZS5nLiBgL3BhdGg/YT1iI2hhc2hgKSB3aGVuIGNhbGxlZCB3aXRob3V0IGFueSBwYXJhbWV0ZXIuDQogICAqDQogICAqIENoYW5nZSBwYXRoLCBzZWFyY2ggYW5kIGhhc2gsIHdoZW4gY2FsbGVkIHdpdGggcGFyYW1ldGVyIGFuZCByZXR1cm4gYCRsb2NhdGlvbmAuDQogICAqDQogICAqDQogICAqIGBgYGpzDQogICAqIC8vIGdpdmVuIHVybCBodHRwOi8vZXhhbXBsZS5jb20vIy9zb21lL3BhdGg/Zm9vPWJhciZiYXo9eG94bw0KICAgKiB2YXIgdXJsID0gJGxvY2F0aW9uLnVybCgpOw0KICAgKiAvLyA9PiAiL3NvbWUvcGF0aD9mb289YmFyJmJhej14b3hvIg0KICAgKiBgYGANCiAgICoNCiAgICogQHBhcmFtIHtzdHJpbmc9fSB1cmwgTmV3IHVybCB3aXRob3V0IGJhc2UgcHJlZml4IChlLmcuIGAvcGF0aD9hPWIjaGFzaGApDQogICAqIEByZXR1cm4ge3N0cmluZ30gdXJsDQogICAqLw0KICB1cmw6IGZ1bmN0aW9uKHVybCkgew0KICAgIGlmIChpc1VuZGVmaW5lZCh1cmwpKQ0KICAgICAgcmV0dXJuIHRoaXMuJCR1cmw7DQoNCiAgICB2YXIgbWF0Y2ggPSBQQVRIX01BVENILmV4ZWModXJsKTsNCiAgICBpZiAobWF0Y2hbMV0gfHwgdXJsID09PSAnJykgdGhpcy5wYXRoKGRlY29kZVVSSUNvbXBvbmVudChtYXRjaFsxXSkpOw0KICAgIGlmIChtYXRjaFsyXSB8fCBtYXRjaFsxXSB8fCB1cmwgPT09ICcnKSB0aGlzLnNlYXJjaChtYXRjaFszXSB8fCAnJyk7DQogICAgdGhpcy5oYXNoKG1hdGNoWzVdIHx8ICcnKTsNCg0KICAgIHJldHVybiB0aGlzOw0KICB9LA0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lICRsb2NhdGlvbiNwcm90b2NvbA0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogVGhpcyBtZXRob2QgaXMgZ2V0dGVyIG9ubHkuDQogICAqDQogICAqIFJldHVybiBwcm90b2NvbCBvZiBjdXJyZW50IHVybC4NCiAgICoNCiAgICoNCiAgICogYGBganMNCiAgICogLy8gZ2l2ZW4gdXJsIGh0dHA6Ly9leGFtcGxlLmNvbS8jL3NvbWUvcGF0aD9mb289YmFyJmJhej14b3hvDQogICAqIHZhciBwcm90b2NvbCA9ICRsb2NhdGlvbi5wcm90b2NvbCgpOw0KICAgKiAvLyA9PiAiaHR0cCINCiAgICogYGBgDQogICAqDQogICAqIEByZXR1cm4ge3N0cmluZ30gcHJvdG9jb2wgb2YgY3VycmVudCB1cmwNCiAgICovDQogIHByb3RvY29sOiBsb2NhdGlvbkdldHRlcignJCRwcm90b2NvbCcpLA0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lICRsb2NhdGlvbiNob3N0DQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBUaGlzIG1ldGhvZCBpcyBnZXR0ZXIgb25seS4NCiAgICoNCiAgICogUmV0dXJuIGhvc3Qgb2YgY3VycmVudCB1cmwuDQogICAqDQogICAqDQogICAqIGBgYGpzDQogICAqIC8vIGdpdmVuIHVybCBodHRwOi8vZXhhbXBsZS5jb20vIy9zb21lL3BhdGg/Zm9vPWJhciZiYXo9eG94bw0KICAgKiB2YXIgaG9zdCA9ICRsb2NhdGlvbi5ob3N0KCk7DQogICAqIC8vID0+ICJleGFtcGxlLmNvbSINCiAgICogYGBgDQogICAqDQogICAqIEByZXR1cm4ge3N0cmluZ30gaG9zdCBvZiBjdXJyZW50IHVybC4NCiAgICovDQogIGhvc3Q6IGxvY2F0aW9uR2V0dGVyKCckJGhvc3QnKSwNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkbG9jYXRpb24jcG9ydA0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogVGhpcyBtZXRob2QgaXMgZ2V0dGVyIG9ubHkuDQogICAqDQogICAqIFJldHVybiBwb3J0IG9mIGN1cnJlbnQgdXJsLg0KICAgKg0KICAgKg0KICAgKiBgYGBqcw0KICAgKiAvLyBnaXZlbiB1cmwgaHR0cDovL2V4YW1wbGUuY29tLyMvc29tZS9wYXRoP2Zvbz1iYXImYmF6PXhveG8NCiAgICogdmFyIHBvcnQgPSAkbG9jYXRpb24ucG9ydCgpOw0KICAgKiAvLyA9PiA4MA0KICAgKiBgYGANCiAgICoNCiAgICogQHJldHVybiB7TnVtYmVyfSBwb3J0DQogICAqLw0KICBwb3J0OiBsb2NhdGlvbkdldHRlcignJCRwb3J0JyksDQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgJGxvY2F0aW9uI3BhdGgNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFRoaXMgbWV0aG9kIGlzIGdldHRlciAvIHNldHRlci4NCiAgICoNCiAgICogUmV0dXJuIHBhdGggb2YgY3VycmVudCB1cmwgd2hlbiBjYWxsZWQgd2l0aG91dCBhbnkgcGFyYW1ldGVyLg0KICAgKg0KICAgKiBDaGFuZ2UgcGF0aCB3aGVuIGNhbGxlZCB3aXRoIHBhcmFtZXRlciBhbmQgcmV0dXJuIGAkbG9jYXRpb25gLg0KICAgKg0KICAgKiBOb3RlOiBQYXRoIHNob3VsZCBhbHdheXMgYmVnaW4gd2l0aCBmb3J3YXJkIHNsYXNoICgvKSwgdGhpcyBtZXRob2Qgd2lsbCBhZGQgdGhlIGZvcndhcmQgc2xhc2gNCiAgICogaWYgaXQgaXMgbWlzc2luZy4NCiAgICoNCiAgICoNCiAgICogYGBganMNCiAgICogLy8gZ2l2ZW4gdXJsIGh0dHA6Ly9leGFtcGxlLmNvbS8jL3NvbWUvcGF0aD9mb289YmFyJmJhej14b3hvDQogICAqIHZhciBwYXRoID0gJGxvY2F0aW9uLnBhdGgoKTsNCiAgICogLy8gPT4gIi9zb21lL3BhdGgiDQogICAqIGBgYA0KICAgKg0KICAgKiBAcGFyYW0geyhzdHJpbmd8bnVtYmVyKT19IHBhdGggTmV3IHBhdGgNCiAgICogQHJldHVybiB7c3RyaW5nfSBwYXRoDQogICAqLw0KICBwYXRoOiBsb2NhdGlvbkdldHRlclNldHRlcignJCRwYXRoJywgZnVuY3Rpb24ocGF0aCkgew0KICAgIHBhdGggPSBwYXRoICE9PSBudWxsID8gcGF0aC50b1N0cmluZygpIDogJyc7DQogICAgcmV0dXJuIHBhdGguY2hhckF0KDApID09ICcvJyA/IHBhdGggOiAnLycgKyBwYXRoOw0KICB9KSwNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkbG9jYXRpb24jc2VhcmNoDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBUaGlzIG1ldGhvZCBpcyBnZXR0ZXIgLyBzZXR0ZXIuDQogICAqDQogICAqIFJldHVybiBzZWFyY2ggcGFydCAoYXMgb2JqZWN0KSBvZiBjdXJyZW50IHVybCB3aGVuIGNhbGxlZCB3aXRob3V0IGFueSBwYXJhbWV0ZXIuDQogICAqDQogICAqIENoYW5nZSBzZWFyY2ggcGFydCB3aGVuIGNhbGxlZCB3aXRoIHBhcmFtZXRlciBhbmQgcmV0dXJuIGAkbG9jYXRpb25gLg0KICAgKg0KICAgKg0KICAgKiBgYGBqcw0KICAgKiAvLyBnaXZlbiB1cmwgaHR0cDovL2V4YW1wbGUuY29tLyMvc29tZS9wYXRoP2Zvbz1iYXImYmF6PXhveG8NCiAgICogdmFyIHNlYXJjaE9iamVjdCA9ICRsb2NhdGlvbi5zZWFyY2goKTsNCiAgICogLy8gPT4ge2ZvbzogJ2JhcicsIGJhejogJ3hveG8nfQ0KICAgKg0KICAgKiAvLyBzZXQgZm9vIHRvICd5aXBlZScNCiAgICogJGxvY2F0aW9uLnNlYXJjaCgnZm9vJywgJ3lpcGVlJyk7DQogICAqIC8vICRsb2NhdGlvbi5zZWFyY2goKSA9PiB7Zm9vOiAneWlwZWUnLCBiYXo6ICd4b3hvJ30NCiAgICogYGBgDQogICAqDQogICAqIEBwYXJhbSB7c3RyaW5nfE9iamVjdC48c3RyaW5nPnxPYmplY3QuPEFycmF5LjxzdHJpbmc+Pn0gc2VhcmNoIE5ldyBzZWFyY2ggcGFyYW1zIC0gc3RyaW5nIG9yDQogICAqIGhhc2ggb2JqZWN0Lg0KICAgKg0KICAgKiBXaGVuIGNhbGxlZCB3aXRoIGEgc2luZ2xlIGFyZ3VtZW50IHRoZSBtZXRob2QgYWN0cyBhcyBhIHNldHRlciwgc2V0dGluZyB0aGUgYHNlYXJjaGAgY29tcG9uZW50DQogICAqIG9mIGAkbG9jYXRpb25gIHRvIHRoZSBzcGVjaWZpZWQgdmFsdWUuDQogICAqDQogICAqIElmIHRoZSBhcmd1bWVudCBpcyBhIGhhc2ggb2JqZWN0IGNvbnRhaW5pbmcgYW4gYXJyYXkgb2YgdmFsdWVzLCB0aGVzZSB2YWx1ZXMgd2lsbCBiZSBlbmNvZGVkDQogICAqIGFzIGR1cGxpY2F0ZSBzZWFyY2ggcGFyYW1ldGVycyBpbiB0aGUgdXJsLg0KICAgKg0KICAgKiBAcGFyYW0geyhzdHJpbmd8TnVtYmVyfEFycmF5PHN0cmluZz58Ym9vbGVhbik9fSBwYXJhbVZhbHVlIElmIGBzZWFyY2hgIGlzIGEgc3RyaW5nIG9yIG51bWJlciwgdGhlbiBgcGFyYW1WYWx1ZWANCiAgICogd2lsbCBvdmVycmlkZSBvbmx5IGEgc2luZ2xlIHNlYXJjaCBwcm9wZXJ0eS4NCiAgICoNCiAgICogSWYgYHBhcmFtVmFsdWVgIGlzIGFuIGFycmF5LCBpdCB3aWxsIG92ZXJyaWRlIHRoZSBwcm9wZXJ0eSBvZiB0aGUgYHNlYXJjaGAgY29tcG9uZW50IG9mDQogICAqIGAkbG9jYXRpb25gIHNwZWNpZmllZCB2aWEgdGhlIGZpcnN0IGFyZ3VtZW50Lg0KICAgKg0KICAgKiBJZiBgcGFyYW1WYWx1ZWAgaXMgYG51bGxgLCB0aGUgcHJvcGVydHkgc3BlY2lmaWVkIHZpYSB0aGUgZmlyc3QgYXJndW1lbnQgd2lsbCBiZSBkZWxldGVkLg0KICAgKg0KICAgKiBJZiBgcGFyYW1WYWx1ZWAgaXMgYHRydWVgLCB0aGUgcHJvcGVydHkgc3BlY2lmaWVkIHZpYSB0aGUgZmlyc3QgYXJndW1lbnQgd2lsbCBiZSBhZGRlZCB3aXRoIG5vDQogICAqIHZhbHVlIG5vciB0cmFpbGluZyBlcXVhbCBzaWduLg0KICAgKg0KICAgKiBAcmV0dXJuIHtPYmplY3R9IElmIGNhbGxlZCB3aXRoIG5vIGFyZ3VtZW50cyByZXR1cm5zIHRoZSBwYXJzZWQgYHNlYXJjaGAgb2JqZWN0LiBJZiBjYWxsZWQgd2l0aA0KICAgKiBvbmUgb3IgbW9yZSBhcmd1bWVudHMgcmV0dXJucyBgJGxvY2F0aW9uYCBvYmplY3QgaXRzZWxmLg0KICAgKi8NCiAgc2VhcmNoOiBmdW5jdGlvbihzZWFyY2gsIHBhcmFtVmFsdWUpIHsNCiAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHsNCiAgICAgIGNhc2UgMDoNCiAgICAgICAgcmV0dXJuIHRoaXMuJCRzZWFyY2g7DQogICAgICBjYXNlIDE6DQogICAgICAgIGlmIChpc1N0cmluZyhzZWFyY2gpIHx8IGlzTnVtYmVyKHNlYXJjaCkpIHsNCiAgICAgICAgICBzZWFyY2ggPSBzZWFyY2gudG9TdHJpbmcoKTsNCiAgICAgICAgICB0aGlzLiQkc2VhcmNoID0gcGFyc2VLZXlWYWx1ZShzZWFyY2gpOw0KICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHNlYXJjaCkpIHsNCiAgICAgICAgICBzZWFyY2ggPSBjb3B5KHNlYXJjaCwge30pOw0KICAgICAgICAgIC8vIHJlbW92ZSBvYmplY3QgdW5kZWZpbmVkIG9yIG51bGwgcHJvcGVydGllcw0KICAgICAgICAgIGZvckVhY2goc2VhcmNoLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7DQogICAgICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkgZGVsZXRlIHNlYXJjaFtrZXldOw0KICAgICAgICAgIH0pOw0KDQogICAgICAgICAgdGhpcy4kJHNlYXJjaCA9IHNlYXJjaDsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICB0aHJvdyAkbG9jYXRpb25NaW5FcnIoJ2lzcmNoYXJnJywNCiAgICAgICAgICAgICAgJ1RoZSBmaXJzdCBhcmd1bWVudCBvZiB0aGUgYCRsb2NhdGlvbiNzZWFyY2goKWAgY2FsbCBtdXN0IGJlIGEgc3RyaW5nIG9yIGFuIG9iamVjdC4nKTsNCiAgICAgICAgfQ0KICAgICAgICBicmVhazsNCiAgICAgIGRlZmF1bHQ6DQogICAgICAgIGlmIChpc1VuZGVmaW5lZChwYXJhbVZhbHVlKSB8fCBwYXJhbVZhbHVlID09PSBudWxsKSB7DQogICAgICAgICAgZGVsZXRlIHRoaXMuJCRzZWFyY2hbc2VhcmNoXTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICB0aGlzLiQkc2VhcmNoW3NlYXJjaF0gPSBwYXJhbVZhbHVlOw0KICAgICAgICB9DQogICAgfQ0KDQogICAgdGhpcy4kJGNvbXBvc2UoKTsNCiAgICByZXR1cm4gdGhpczsNCiAgfSwNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkbG9jYXRpb24jaGFzaA0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogVGhpcyBtZXRob2QgaXMgZ2V0dGVyIC8gc2V0dGVyLg0KICAgKg0KICAgKiBSZXR1cm4gaGFzaCBmcmFnbWVudCB3aGVuIGNhbGxlZCB3aXRob3V0IGFueSBwYXJhbWV0ZXIuDQogICAqDQogICAqIENoYW5nZSBoYXNoIGZyYWdtZW50IHdoZW4gY2FsbGVkIHdpdGggcGFyYW1ldGVyIGFuZCByZXR1cm4gYCRsb2NhdGlvbmAuDQogICAqDQogICAqDQogICAqIGBgYGpzDQogICAqIC8vIGdpdmVuIHVybCBodHRwOi8vZXhhbXBsZS5jb20vIy9zb21lL3BhdGg/Zm9vPWJhciZiYXo9eG94byNoYXNoVmFsdWUNCiAgICogdmFyIGhhc2ggPSAkbG9jYXRpb24uaGFzaCgpOw0KICAgKiAvLyA9PiAiaGFzaFZhbHVlIg0KICAgKiBgYGANCiAgICoNCiAgICogQHBhcmFtIHsoc3RyaW5nfG51bWJlcik9fSBoYXNoIE5ldyBoYXNoIGZyYWdtZW50DQogICAqIEByZXR1cm4ge3N0cmluZ30gaGFzaA0KICAgKi8NCiAgaGFzaDogbG9jYXRpb25HZXR0ZXJTZXR0ZXIoJyQkaGFzaCcsIGZ1bmN0aW9uKGhhc2gpIHsNCiAgICByZXR1cm4gaGFzaCAhPT0gbnVsbCA/IGhhc2gudG9TdHJpbmcoKSA6ICcnOw0KICB9KSwNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkbG9jYXRpb24jcmVwbGFjZQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogSWYgY2FsbGVkLCBhbGwgY2hhbmdlcyB0byAkbG9jYXRpb24gZHVyaW5nIGN1cnJlbnQgYCRkaWdlc3RgIHdpbGwgYmUgcmVwbGFjaW5nIGN1cnJlbnQgaGlzdG9yeQ0KICAgKiByZWNvcmQsIGluc3RlYWQgb2YgYWRkaW5nIG5ldyBvbmUuDQogICAqLw0KICByZXBsYWNlOiBmdW5jdGlvbigpIHsNCiAgICB0aGlzLiQkcmVwbGFjZSA9IHRydWU7DQogICAgcmV0dXJuIHRoaXM7DQogIH0NCn07DQoNCmZvckVhY2goW0xvY2F0aW9uSGFzaGJhbmdJbkh0bWw1VXJsLCBMb2NhdGlvbkhhc2hiYW5nVXJsLCBMb2NhdGlvbkh0bWw1VXJsXSwgZnVuY3Rpb24oTG9jYXRpb24pIHsNCiAgTG9jYXRpb24ucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShsb2NhdGlvblByb3RvdHlwZSk7DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgJGxvY2F0aW9uI3N0YXRlDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBUaGlzIG1ldGhvZCBpcyBnZXR0ZXIgLyBzZXR0ZXIuDQogICAqDQogICAqIFJldHVybiB0aGUgaGlzdG9yeSBzdGF0ZSBvYmplY3Qgd2hlbiBjYWxsZWQgd2l0aG91dCBhbnkgcGFyYW1ldGVyLg0KICAgKg0KICAgKiBDaGFuZ2UgdGhlIGhpc3Rvcnkgc3RhdGUgb2JqZWN0IHdoZW4gY2FsbGVkIHdpdGggb25lIHBhcmFtZXRlciBhbmQgcmV0dXJuIGAkbG9jYXRpb25gLg0KICAgKiBUaGUgc3RhdGUgb2JqZWN0IGlzIGxhdGVyIHBhc3NlZCB0byBgcHVzaFN0YXRlYCBvciBgcmVwbGFjZVN0YXRlYC4NCiAgICoNCiAgICogTk9URTogVGhpcyBtZXRob2QgaXMgc3VwcG9ydGVkIG9ubHkgaW4gSFRNTDUgbW9kZSBhbmQgb25seSBpbiBicm93c2VycyBzdXBwb3J0aW5nDQogICAqIHRoZSBIVE1MNSBIaXN0b3J5IEFQSSAoaS5lLiBtZXRob2RzIGBwdXNoU3RhdGVgIGFuZCBgcmVwbGFjZVN0YXRlYCkuIElmIHlvdSBuZWVkIHRvIHN1cHBvcnQNCiAgICogb2xkZXIgYnJvd3NlcnMgKGxpa2UgSUU5IG9yIEFuZHJvaWQgPCA0LjApLCBkb24ndCB1c2UgdGhpcyBtZXRob2QuDQogICAqDQogICAqIEBwYXJhbSB7b2JqZWN0PX0gc3RhdGUgU3RhdGUgb2JqZWN0IGZvciBwdXNoU3RhdGUgb3IgcmVwbGFjZVN0YXRlDQogICAqIEByZXR1cm4ge29iamVjdH0gc3RhdGUNCiAgICovDQogIExvY2F0aW9uLnByb3RvdHlwZS5zdGF0ZSA9IGZ1bmN0aW9uKHN0YXRlKSB7DQogICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKQ0KICAgICAgcmV0dXJuIHRoaXMuJCRzdGF0ZTsNCg0KICAgIGlmIChMb2NhdGlvbiAhPT0gTG9jYXRpb25IdG1sNVVybCB8fCAhdGhpcy4kJGh0bWw1KSB7DQogICAgICB0aHJvdyAkbG9jYXRpb25NaW5FcnIoJ25vc3RhdGUnLCAnSGlzdG9yeSBBUEkgc3RhdGUgc3VwcG9ydCBpcyBhdmFpbGFibGUgb25seSAnICsNCiAgICAgICAgJ2luIEhUTUw1IG1vZGUgYW5kIG9ubHkgaW4gYnJvd3NlcnMgc3VwcG9ydGluZyBIVE1MNSBIaXN0b3J5IEFQSScpOw0KICAgIH0NCiAgICAvLyBUaGUgdXNlciBtaWdodCBtb2RpZnkgYHN0YXRlT2JqZWN0YCBhZnRlciBpbnZva2luZyBgJGxvY2F0aW9uLnN0YXRlKHN0YXRlT2JqZWN0KWANCiAgICAvLyBidXQgd2UncmUgY2hhbmdpbmcgdGhlICQkc3RhdGUgcmVmZXJlbmNlIHRvICRicm93c2VyLnN0YXRlKCkgZHVyaW5nIHRoZSAkZGlnZXN0DQogICAgLy8gc28gdGhlIG1vZGlmaWNhdGlvbiB3aW5kb3cgaXMgbmFycm93Lg0KICAgIHRoaXMuJCRzdGF0ZSA9IGlzVW5kZWZpbmVkKHN0YXRlKSA/IG51bGwgOiBzdGF0ZTsNCg0KICAgIHJldHVybiB0aGlzOw0KICB9Ow0KfSk7DQoNCg0KZnVuY3Rpb24gbG9jYXRpb25HZXR0ZXIocHJvcGVydHkpIHsNCiAgcmV0dXJuIGZ1bmN0aW9uKCkgew0KICAgIHJldHVybiB0aGlzW3Byb3BlcnR5XTsNCiAgfTsNCn0NCg0KDQpmdW5jdGlvbiBsb2NhdGlvbkdldHRlclNldHRlcihwcm9wZXJ0eSwgcHJlcHJvY2Vzcykgew0KICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHsNCiAgICBpZiAoaXNVbmRlZmluZWQodmFsdWUpKQ0KICAgICAgcmV0dXJuIHRoaXNbcHJvcGVydHldOw0KDQogICAgdGhpc1twcm9wZXJ0eV0gPSBwcmVwcm9jZXNzKHZhbHVlKTsNCiAgICB0aGlzLiQkY29tcG9zZSgpOw0KDQogICAgcmV0dXJuIHRoaXM7DQogIH07DQp9DQoNCg0KLyoqDQogKiBAbmdkb2Mgc2VydmljZQ0KICogQG5hbWUgJGxvY2F0aW9uDQogKg0KICogQHJlcXVpcmVzICRyb290RWxlbWVudA0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlICRsb2NhdGlvbiBzZXJ2aWNlIHBhcnNlcyB0aGUgVVJMIGluIHRoZSBicm93c2VyIGFkZHJlc3MgYmFyIChiYXNlZCBvbiB0aGUNCiAqIFt3aW5kb3cubG9jYXRpb25dKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL3dpbmRvdy5sb2NhdGlvbikpIGFuZCBtYWtlcyB0aGUgVVJMDQogKiBhdmFpbGFibGUgdG8geW91ciBhcHBsaWNhdGlvbi4gQ2hhbmdlcyB0byB0aGUgVVJMIGluIHRoZSBhZGRyZXNzIGJhciBhcmUgcmVmbGVjdGVkIGludG8NCiAqICRsb2NhdGlvbiBzZXJ2aWNlIGFuZCBjaGFuZ2VzIHRvICRsb2NhdGlvbiBhcmUgcmVmbGVjdGVkIGludG8gdGhlIGJyb3dzZXIgYWRkcmVzcyBiYXIuDQogKg0KICogKipUaGUgJGxvY2F0aW9uIHNlcnZpY2U6KioNCiAqDQogKiAtIEV4cG9zZXMgdGhlIGN1cnJlbnQgVVJMIGluIHRoZSBicm93c2VyIGFkZHJlc3MgYmFyLCBzbyB5b3UgY2FuDQogKiAgIC0gV2F0Y2ggYW5kIG9ic2VydmUgdGhlIFVSTC4NCiAqICAgLSBDaGFuZ2UgdGhlIFVSTC4NCiAqIC0gU3luY2hyb25pemVzIHRoZSBVUkwgd2l0aCB0aGUgYnJvd3NlciB3aGVuIHRoZSB1c2VyDQogKiAgIC0gQ2hhbmdlcyB0aGUgYWRkcmVzcyBiYXIuDQogKiAgIC0gQ2xpY2tzIHRoZSBiYWNrIG9yIGZvcndhcmQgYnV0dG9uIChvciBjbGlja3MgYSBIaXN0b3J5IGxpbmspLg0KICogICAtIENsaWNrcyBvbiBhIGxpbmsuDQogKiAtIFJlcHJlc2VudHMgdGhlIFVSTCBvYmplY3QgYXMgYSBzZXQgb2YgbWV0aG9kcyAocHJvdG9jb2wsIGhvc3QsIHBvcnQsIHBhdGgsIHNlYXJjaCwgaGFzaCkuDQogKg0KICogRm9yIG1vcmUgaW5mb3JtYXRpb24gc2VlIHtAbGluayBndWlkZS8kbG9jYXRpb24gRGV2ZWxvcGVyIEd1aWRlOiBVc2luZyAkbG9jYXRpb259DQogKi8NCg0KLyoqDQogKiBAbmdkb2MgcHJvdmlkZXINCiAqIEBuYW1lICRsb2NhdGlvblByb3ZpZGVyDQogKiBAZGVzY3JpcHRpb24NCiAqIFVzZSB0aGUgYCRsb2NhdGlvblByb3ZpZGVyYCB0byBjb25maWd1cmUgaG93IHRoZSBhcHBsaWNhdGlvbiBkZWVwIGxpbmtpbmcgcGF0aHMgYXJlIHN0b3JlZC4NCiAqLw0KZnVuY3Rpb24gJExvY2F0aW9uUHJvdmlkZXIoKSB7DQogIHZhciBoYXNoUHJlZml4ID0gJycsDQogICAgICBodG1sNU1vZGUgPSB7DQogICAgICAgIGVuYWJsZWQ6IGZhbHNlLA0KICAgICAgICByZXF1aXJlQmFzZTogdHJ1ZSwNCiAgICAgICAgcmV3cml0ZUxpbmtzOiB0cnVlDQogICAgICB9Ow0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lICRsb2NhdGlvblByb3ZpZGVyI2hhc2hQcmVmaXgNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gcHJlZml4IFByZWZpeCBmb3IgaGFzaCBwYXJ0IChjb250YWluaW5nIHBhdGggYW5kIHNlYXJjaCkNCiAgICogQHJldHVybnMgeyp9IGN1cnJlbnQgdmFsdWUgaWYgdXNlZCBhcyBnZXR0ZXIgb3IgaXRzZWxmIChjaGFpbmluZykgaWYgdXNlZCBhcyBzZXR0ZXINCiAgICovDQogIHRoaXMuaGFzaFByZWZpeCA9IGZ1bmN0aW9uKHByZWZpeCkgew0KICAgIGlmIChpc0RlZmluZWQocHJlZml4KSkgew0KICAgICAgaGFzaFByZWZpeCA9IHByZWZpeDsNCiAgICAgIHJldHVybiB0aGlzOw0KICAgIH0gZWxzZSB7DQogICAgICByZXR1cm4gaGFzaFByZWZpeDsNCiAgICB9DQogIH07DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgJGxvY2F0aW9uUHJvdmlkZXIjaHRtbDVNb2RlDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBAcGFyYW0geyhib29sZWFufE9iamVjdCk9fSBtb2RlIElmIGJvb2xlYW4sIHNldHMgYGh0bWw1TW9kZS5lbmFibGVkYCB0byB2YWx1ZS4NCiAgICogICBJZiBvYmplY3QsIHNldHMgYGVuYWJsZWRgLCBgcmVxdWlyZUJhc2VgIGFuZCBgcmV3cml0ZUxpbmtzYCB0byByZXNwZWN0aXZlIHZhbHVlcy4gU3VwcG9ydGVkDQogICAqICAgcHJvcGVydGllczoNCiAgICogICAtICoqZW5hYmxlZCoqIOKAPyBge2Jvb2xlYW59YCDigD8gKGRlZmF1bHQ6IGZhbHNlKSBJZiB0cnVlLCB3aWxsIHJlbHkgb24gYGhpc3RvcnkucHVzaFN0YXRlYCB0bw0KICAgKiAgICAgY2hhbmdlIHVybHMgd2hlcmUgc3VwcG9ydGVkLiBXaWxsIGZhbGwgYmFjayB0byBoYXNoLXByZWZpeGVkIHBhdGhzIGluIGJyb3dzZXJzIHRoYXQgZG8gbm90DQogICAqICAgICBzdXBwb3J0IGBwdXNoU3RhdGVgLg0KICAgKiAgIC0gKipyZXF1aXJlQmFzZSoqIC0gYHtib29sZWFufWAgLSAoZGVmYXVsdDogYHRydWVgKSBXaGVuIGh0bWw1TW9kZSBpcyBlbmFibGVkLCBzcGVjaWZpZXMNCiAgICogICAgIHdoZXRoZXIgb3Igbm90IGEgPGJhc2U+IHRhZyBpcyByZXF1aXJlZCB0byBiZSBwcmVzZW50LiBJZiBgZW5hYmxlZGAgYW5kIGByZXF1aXJlQmFzZWAgYXJlDQogICAqICAgICB0cnVlLCBhbmQgYSBiYXNlIHRhZyBpcyBub3QgcHJlc2VudCwgYW4gZXJyb3Igd2lsbCBiZSB0aHJvd24gd2hlbiBgJGxvY2F0aW9uYCBpcyBpbmplY3RlZC4NCiAgICogICAgIFNlZSB0aGUge0BsaW5rIGd1aWRlLyRsb2NhdGlvbiAkbG9jYXRpb24gZ3VpZGUgZm9yIG1vcmUgaW5mb3JtYXRpb259DQogICAqICAgLSAqKnJld3JpdGVMaW5rcyoqIC0gYHtib29sZWFufWAgLSAoZGVmYXVsdDogYHRydWVgKSBXaGVuIGh0bWw1TW9kZSBpcyBlbmFibGVkLA0KICAgKiAgICAgZW5hYmxlcy9kaXNhYmxlcyB1cmwgcmV3cml0aW5nIGZvciByZWxhdGl2ZSBsaW5rcy4NCiAgICoNCiAgICogQHJldHVybnMge09iamVjdH0gaHRtbDVNb2RlIG9iamVjdCBpZiB1c2VkIGFzIGdldHRlciBvciBpdHNlbGYgKGNoYWluaW5nKSBpZiB1c2VkIGFzIHNldHRlcg0KICAgKi8NCiAgdGhpcy5odG1sNU1vZGUgPSBmdW5jdGlvbihtb2RlKSB7DQogICAgaWYgKGlzQm9vbGVhbihtb2RlKSkgew0KICAgICAgaHRtbDVNb2RlLmVuYWJsZWQgPSBtb2RlOw0KICAgICAgcmV0dXJuIHRoaXM7DQogICAgfSBlbHNlIGlmIChpc09iamVjdChtb2RlKSkgew0KDQogICAgICBpZiAoaXNCb29sZWFuKG1vZGUuZW5hYmxlZCkpIHsNCiAgICAgICAgaHRtbDVNb2RlLmVuYWJsZWQgPSBtb2RlLmVuYWJsZWQ7DQogICAgICB9DQoNCiAgICAgIGlmIChpc0Jvb2xlYW4obW9kZS5yZXF1aXJlQmFzZSkpIHsNCiAgICAgICAgaHRtbDVNb2RlLnJlcXVpcmVCYXNlID0gbW9kZS5yZXF1aXJlQmFzZTsNCiAgICAgIH0NCg0KICAgICAgaWYgKGlzQm9vbGVhbihtb2RlLnJld3JpdGVMaW5rcykpIHsNCiAgICAgICAgaHRtbDVNb2RlLnJld3JpdGVMaW5rcyA9IG1vZGUucmV3cml0ZUxpbmtzOw0KICAgICAgfQ0KDQogICAgICByZXR1cm4gdGhpczsNCiAgICB9IGVsc2Ugew0KICAgICAgcmV0dXJuIGh0bWw1TW9kZTsNCiAgICB9DQogIH07DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBldmVudA0KICAgKiBAbmFtZSAkbG9jYXRpb24jJGxvY2F0aW9uQ2hhbmdlU3RhcnQNCiAgICogQGV2ZW50VHlwZSBicm9hZGNhc3Qgb24gcm9vdCBzY29wZQ0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogQnJvYWRjYXN0ZWQgYmVmb3JlIGEgVVJMIHdpbGwgY2hhbmdlLg0KICAgKg0KICAgKiBUaGlzIGNoYW5nZSBjYW4gYmUgcHJldmVudGVkIGJ5IGNhbGxpbmcNCiAgICogYHByZXZlbnREZWZhdWx0YCBtZXRob2Qgb2YgdGhlIGV2ZW50LiBTZWUge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJG9ufSBmb3IgbW9yZQ0KICAgKiBkZXRhaWxzIGFib3V0IGV2ZW50IG9iamVjdC4gVXBvbiBzdWNjZXNzZnVsIGNoYW5nZQ0KICAgKiB7QGxpbmsgbmcuJGxvY2F0aW9uIyRsb2NhdGlvbkNoYW5nZVN1Y2Nlc3MgJGxvY2F0aW9uQ2hhbmdlU3VjY2Vzc30gaXMgZmlyZWQuDQogICAqDQogICAqIFRoZSBgbmV3U3RhdGVgIGFuZCBgb2xkU3RhdGVgIHBhcmFtZXRlcnMgbWF5IGJlIGRlZmluZWQgb25seSBpbiBIVE1MNSBtb2RlIGFuZCB3aGVuDQogICAqIHRoZSBicm93c2VyIHN1cHBvcnRzIHRoZSBIVE1MNSBIaXN0b3J5IEFQSS4NCiAgICoNCiAgICogQHBhcmFtIHtPYmplY3R9IGFuZ3VsYXJFdmVudCBTeW50aGV0aWMgZXZlbnQgb2JqZWN0Lg0KICAgKiBAcGFyYW0ge3N0cmluZ30gbmV3VXJsIE5ldyBVUkwNCiAgICogQHBhcmFtIHtzdHJpbmc9fSBvbGRVcmwgVVJMIHRoYXQgd2FzIGJlZm9yZSBpdCB3YXMgY2hhbmdlZC4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSBuZXdTdGF0ZSBOZXcgaGlzdG9yeSBzdGF0ZSBvYmplY3QNCiAgICogQHBhcmFtIHtzdHJpbmc9fSBvbGRTdGF0ZSBIaXN0b3J5IHN0YXRlIG9iamVjdCB0aGF0IHdhcyBiZWZvcmUgaXQgd2FzIGNoYW5nZWQuDQogICAqLw0KDQogIC8qKg0KICAgKiBAbmdkb2MgZXZlbnQNCiAgICogQG5hbWUgJGxvY2F0aW9uIyRsb2NhdGlvbkNoYW5nZVN1Y2Nlc3MNCiAgICogQGV2ZW50VHlwZSBicm9hZGNhc3Qgb24gcm9vdCBzY29wZQ0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogQnJvYWRjYXN0ZWQgYWZ0ZXIgYSBVUkwgd2FzIGNoYW5nZWQuDQogICAqDQogICAqIFRoZSBgbmV3U3RhdGVgIGFuZCBgb2xkU3RhdGVgIHBhcmFtZXRlcnMgbWF5IGJlIGRlZmluZWQgb25seSBpbiBIVE1MNSBtb2RlIGFuZCB3aGVuDQogICAqIHRoZSBicm93c2VyIHN1cHBvcnRzIHRoZSBIVE1MNSBIaXN0b3J5IEFQSS4NCiAgICoNCiAgICogQHBhcmFtIHtPYmplY3R9IGFuZ3VsYXJFdmVudCBTeW50aGV0aWMgZXZlbnQgb2JqZWN0Lg0KICAgKiBAcGFyYW0ge3N0cmluZ30gbmV3VXJsIE5ldyBVUkwNCiAgICogQHBhcmFtIHtzdHJpbmc9fSBvbGRVcmwgVVJMIHRoYXQgd2FzIGJlZm9yZSBpdCB3YXMgY2hhbmdlZC4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSBuZXdTdGF0ZSBOZXcgaGlzdG9yeSBzdGF0ZSBvYmplY3QNCiAgICogQHBhcmFtIHtzdHJpbmc9fSBvbGRTdGF0ZSBIaXN0b3J5IHN0YXRlIG9iamVjdCB0aGF0IHdhcyBiZWZvcmUgaXQgd2FzIGNoYW5nZWQuDQogICAqLw0KDQogIHRoaXMuJGdldCA9IFsnJHJvb3RTY29wZScsICckYnJvd3NlcicsICckc25pZmZlcicsICckcm9vdEVsZW1lbnQnLCAnJHdpbmRvdycsDQogICAgICBmdW5jdGlvbigkcm9vdFNjb3BlLCAkYnJvd3NlciwgJHNuaWZmZXIsICRyb290RWxlbWVudCwgJHdpbmRvdykgew0KICAgIHZhciAkbG9jYXRpb24sDQogICAgICAgIExvY2F0aW9uTW9kZSwNCiAgICAgICAgYmFzZUhyZWYgPSAkYnJvd3Nlci5iYXNlSHJlZigpLCAvLyBpZiBiYXNlW2hyZWZdIGlzIHVuZGVmaW5lZCwgaXQgZGVmYXVsdHMgdG8gJycNCiAgICAgICAgaW5pdGlhbFVybCA9ICRicm93c2VyLnVybCgpLA0KICAgICAgICBhcHBCYXNlOw0KDQogICAgaWYgKGh0bWw1TW9kZS5lbmFibGVkKSB7DQogICAgICBpZiAoIWJhc2VIcmVmICYmIGh0bWw1TW9kZS5yZXF1aXJlQmFzZSkgew0KICAgICAgICB0aHJvdyAkbG9jYXRpb25NaW5FcnIoJ25vYmFzZScsDQogICAgICAgICAgIiRsb2NhdGlvbiBpbiBIVE1MNSBtb2RlIHJlcXVpcmVzIGEgPGJhc2U+IHRhZyB0byBiZSBwcmVzZW50ISIpOw0KICAgICAgfQ0KICAgICAgYXBwQmFzZSA9IHNlcnZlckJhc2UoaW5pdGlhbFVybCkgKyAoYmFzZUhyZWYgfHwgJy8nKTsNCiAgICAgIExvY2F0aW9uTW9kZSA9ICRzbmlmZmVyLmhpc3RvcnkgPyBMb2NhdGlvbkh0bWw1VXJsIDogTG9jYXRpb25IYXNoYmFuZ0luSHRtbDVVcmw7DQogICAgfSBlbHNlIHsNCiAgICAgIGFwcEJhc2UgPSBzdHJpcEhhc2goaW5pdGlhbFVybCk7DQogICAgICBMb2NhdGlvbk1vZGUgPSBMb2NhdGlvbkhhc2hiYW5nVXJsOw0KICAgIH0NCiAgICAkbG9jYXRpb24gPSBuZXcgTG9jYXRpb25Nb2RlKGFwcEJhc2UsICcjJyArIGhhc2hQcmVmaXgpOw0KICAgICRsb2NhdGlvbi4kJHBhcnNlTGlua1VybChpbml0aWFsVXJsLCBpbml0aWFsVXJsKTsNCg0KICAgICRsb2NhdGlvbi4kJHN0YXRlID0gJGJyb3dzZXIuc3RhdGUoKTsNCg0KICAgIHZhciBJR05PUkVfVVJJX1JFR0VYUCA9IC9eXHMqKGphdmFzY3JpcHR8bWFpbHRvKTovaTsNCg0KICAgIGZ1bmN0aW9uIHNldEJyb3dzZXJVcmxXaXRoRmFsbGJhY2sodXJsLCByZXBsYWNlLCBzdGF0ZSkgew0KICAgICAgdmFyIG9sZFVybCA9ICRsb2NhdGlvbi51cmwoKTsNCiAgICAgIHZhciBvbGRTdGF0ZSA9ICRsb2NhdGlvbi4kJHN0YXRlOw0KICAgICAgdHJ5IHsNCiAgICAgICAgJGJyb3dzZXIudXJsKHVybCwgcmVwbGFjZSwgc3RhdGUpOw0KDQogICAgICAgIC8vIE1ha2Ugc3VyZSAkbG9jYXRpb24uc3RhdGUoKSByZXR1cm5zIHJlZmVyZW50aWFsbHkgaWRlbnRpY2FsIChub3QganVzdCBkZWVwbHkgZXF1YWwpDQogICAgICAgIC8vIHN0YXRlIG9iamVjdDsgdGhpcyBtYWtlcyBwb3NzaWJsZSBxdWljayBjaGVja2luZyBpZiB0aGUgc3RhdGUgY2hhbmdlZCBpbiB0aGUgZGlnZXN0DQogICAgICAgIC8vIGxvb3AuIENoZWNraW5nIGRlZXAgZXF1YWxpdHkgd291bGQgYmUgdG9vIGV4cGVuc2l2ZS4NCiAgICAgICAgJGxvY2F0aW9uLiQkc3RhdGUgPSAkYnJvd3Nlci5zdGF0ZSgpOw0KICAgICAgfSBjYXRjaCAoZSkgew0KICAgICAgICAvLyBSZXN0b3JlIG9sZCB2YWx1ZXMgaWYgcHVzaFN0YXRlIGZhaWxzDQogICAgICAgICRsb2NhdGlvbi51cmwob2xkVXJsKTsNCiAgICAgICAgJGxvY2F0aW9uLiQkc3RhdGUgPSBvbGRTdGF0ZTsNCg0KICAgICAgICB0aHJvdyBlOw0KICAgICAgfQ0KICAgIH0NCg0KICAgICRyb290RWxlbWVudC5vbignY2xpY2snLCBmdW5jdGlvbihldmVudCkgew0KICAgICAgLy8gVE9ETyh2b2p0YSk6IHJld3JpdGUgbGluayB3aGVuIG9wZW5pbmcgaW4gbmV3IHRhYi93aW5kb3cgKGluIGxlZ2FjeSBicm93c2VyKQ0KICAgICAgLy8gY3VycmVudGx5IHdlIG9wZW4gbmljZSB1cmwgbGluayBhbmQgcmVkaXJlY3QgdGhlbg0KDQogICAgICBpZiAoIWh0bWw1TW9kZS5yZXdyaXRlTGlua3MgfHwgZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5IHx8IGV2ZW50LndoaWNoID09IDIpIHJldHVybjsNCg0KICAgICAgdmFyIGVsbSA9IGpxTGl0ZShldmVudC50YXJnZXQpOw0KDQogICAgICAvLyB0cmF2ZXJzZSB0aGUgRE9NIHVwIHRvIGZpbmQgZmlyc3QgQSB0YWcNCiAgICAgIHdoaWxlIChub2RlTmFtZV8oZWxtWzBdKSAhPT0gJ2EnKSB7DQogICAgICAgIC8vIGlnbm9yZSByZXdyaXRpbmcgaWYgbm8gQSB0YWcgKHJlYWNoZWQgcm9vdCBlbGVtZW50LCBvciBubyBwYXJlbnQgLSByZW1vdmVkIGZyb20gZG9jdW1lbnQpDQogICAgICAgIGlmIChlbG1bMF0gPT09ICRyb290RWxlbWVudFswXSB8fCAhKGVsbSA9IGVsbS5wYXJlbnQoKSlbMF0pIHJldHVybjsNCiAgICAgIH0NCg0KICAgICAgdmFyIGFic0hyZWYgPSBlbG0ucHJvcCgnaHJlZicpOw0KICAgICAgLy8gZ2V0IHRoZSBhY3R1YWwgaHJlZiBhdHRyaWJ1dGUgLSBzZWUNCiAgICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9pZS9kZDM0NzE0OCh2PXZzLjg1KS5hc3B4DQogICAgICB2YXIgcmVsSHJlZiA9IGVsbS5hdHRyKCdocmVmJykgfHwgZWxtLmF0dHIoJ3hsaW5rOmhyZWYnKTsNCg0KICAgICAgaWYgKGlzT2JqZWN0KGFic0hyZWYpICYmIGFic0hyZWYudG9TdHJpbmcoKSA9PT0gJ1tvYmplY3QgU1ZHQW5pbWF0ZWRTdHJpbmddJykgew0KICAgICAgICAvLyBTVkdBbmltYXRlZFN0cmluZy5hbmltVmFsIHNob3VsZCBiZSBpZGVudGljYWwgdG8gU1ZHQW5pbWF0ZWRTdHJpbmcuYmFzZVZhbCwgdW5sZXNzIGR1cmluZw0KICAgICAgICAvLyBhbiBhbmltYXRpb24uDQogICAgICAgIGFic0hyZWYgPSB1cmxSZXNvbHZlKGFic0hyZWYuYW5pbVZhbCkuaHJlZjsNCiAgICAgIH0NCg0KICAgICAgLy8gSWdub3JlIHdoZW4gdXJsIGlzIHN0YXJ0ZWQgd2l0aCBqYXZhc2NyaXB0OiBvciBtYWlsdG86DQogICAgICBpZiAoSUdOT1JFX1VSSV9SRUdFWFAudGVzdChhYnNIcmVmKSkgcmV0dXJuOw0KDQogICAgICBpZiAoYWJzSHJlZiAmJiAhZWxtLmF0dHIoJ3RhcmdldCcpICYmICFldmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgew0KICAgICAgICBpZiAoJGxvY2F0aW9uLiQkcGFyc2VMaW5rVXJsKGFic0hyZWYsIHJlbEhyZWYpKSB7DQogICAgICAgICAgLy8gV2UgZG8gYSBwcmV2ZW50RGVmYXVsdCBmb3IgYWxsIHVybHMgdGhhdCBhcmUgcGFydCBvZiB0aGUgYW5ndWxhciBhcHBsaWNhdGlvbiwNCiAgICAgICAgICAvLyBpbiBodG1sNW1vZGUgYW5kIGFsc28gd2l0aG91dCwgc28gdGhhdCB3ZSBhcmUgYWJsZSB0byBhYm9ydCBuYXZpZ2F0aW9uIHdpdGhvdXQNCiAgICAgICAgICAvLyBnZXR0aW5nIGRvdWJsZSBlbnRyaWVzIGluIHRoZSBsb2NhdGlvbiBoaXN0b3J5Lg0KICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7DQogICAgICAgICAgLy8gdXBkYXRlIGxvY2F0aW9uIG1hbnVhbGx5DQogICAgICAgICAgaWYgKCRsb2NhdGlvbi5hYnNVcmwoKSAhPSAkYnJvd3Nlci51cmwoKSkgew0KICAgICAgICAgICAgJHJvb3RTY29wZS4kYXBwbHkoKTsNCiAgICAgICAgICAgIC8vIGhhY2sgdG8gd29yayBhcm91bmQgRkY2IGJ1ZyA2ODQyMDggd2hlbiBzY2VuYXJpbyBydW5uZXIgY2xpY2tzIG9uIGxpbmtzDQogICAgICAgICAgICAkd2luZG93LmFuZ3VsYXJbJ2ZmLTY4NDIwOC1wcmV2ZW50RGVmYXVsdCddID0gdHJ1ZTsNCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9KTsNCg0KDQogICAgLy8gcmV3cml0ZSBoYXNoYmFuZyB1cmwgPD4gaHRtbDUgdXJsDQogICAgaWYgKCRsb2NhdGlvbi5hYnNVcmwoKSAhPSBpbml0aWFsVXJsKSB7DQogICAgICAkYnJvd3Nlci51cmwoJGxvY2F0aW9uLmFic1VybCgpLCB0cnVlKTsNCiAgICB9DQoNCiAgICB2YXIgaW5pdGlhbGl6aW5nID0gdHJ1ZTsNCg0KICAgIC8vIHVwZGF0ZSAkbG9jYXRpb24gd2hlbiAkYnJvd3NlciB1cmwgY2hhbmdlcw0KICAgICRicm93c2VyLm9uVXJsQ2hhbmdlKGZ1bmN0aW9uKG5ld1VybCwgbmV3U3RhdGUpIHsNCiAgICAgICRyb290U2NvcGUuJGV2YWxBc3luYyhmdW5jdGlvbigpIHsNCiAgICAgICAgdmFyIG9sZFVybCA9ICRsb2NhdGlvbi5hYnNVcmwoKTsNCiAgICAgICAgdmFyIG9sZFN0YXRlID0gJGxvY2F0aW9uLiQkc3RhdGU7DQogICAgICAgIHZhciBkZWZhdWx0UHJldmVudGVkOw0KDQogICAgICAgICRsb2NhdGlvbi4kJHBhcnNlKG5ld1VybCk7DQogICAgICAgICRsb2NhdGlvbi4kJHN0YXRlID0gbmV3U3RhdGU7DQoNCiAgICAgICAgZGVmYXVsdFByZXZlbnRlZCA9ICRyb290U2NvcGUuJGJyb2FkY2FzdCgnJGxvY2F0aW9uQ2hhbmdlU3RhcnQnLCBuZXdVcmwsIG9sZFVybCwNCiAgICAgICAgICAgIG5ld1N0YXRlLCBvbGRTdGF0ZSkuZGVmYXVsdFByZXZlbnRlZDsNCg0KICAgICAgICAvLyBpZiB0aGUgbG9jYXRpb24gd2FzIGNoYW5nZWQgYnkgYSBgJGxvY2F0aW9uQ2hhbmdlU3RhcnRgIGhhbmRsZXIgdGhlbiBzdG9wDQogICAgICAgIC8vIHByb2Nlc3NpbmcgdGhpcyBsb2NhdGlvbiBjaGFuZ2UNCiAgICAgICAgaWYgKCRsb2NhdGlvbi5hYnNVcmwoKSAhPT0gbmV3VXJsKSByZXR1cm47DQoNCiAgICAgICAgaWYgKGRlZmF1bHRQcmV2ZW50ZWQpIHsNCiAgICAgICAgICAkbG9jYXRpb24uJCRwYXJzZShvbGRVcmwpOw0KICAgICAgICAgICRsb2NhdGlvbi4kJHN0YXRlID0gb2xkU3RhdGU7DQogICAgICAgICAgc2V0QnJvd3NlclVybFdpdGhGYWxsYmFjayhvbGRVcmwsIGZhbHNlLCBvbGRTdGF0ZSk7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7DQogICAgICAgICAgYWZ0ZXJMb2NhdGlvbkNoYW5nZShvbGRVcmwsIG9sZFN0YXRlKTsNCiAgICAgICAgfQ0KICAgICAgfSk7DQogICAgICBpZiAoISRyb290U2NvcGUuJCRwaGFzZSkgJHJvb3RTY29wZS4kZGlnZXN0KCk7DQogICAgfSk7DQoNCiAgICAvLyB1cGRhdGUgYnJvd3Nlcg0KICAgICRyb290U2NvcGUuJHdhdGNoKGZ1bmN0aW9uICRsb2NhdGlvbldhdGNoKCkgew0KICAgICAgdmFyIG9sZFVybCA9IHRyaW1FbXB0eUhhc2goJGJyb3dzZXIudXJsKCkpOw0KICAgICAgdmFyIG5ld1VybCA9IHRyaW1FbXB0eUhhc2goJGxvY2F0aW9uLmFic1VybCgpKTsNCiAgICAgIHZhciBvbGRTdGF0ZSA9ICRicm93c2VyLnN0YXRlKCk7DQogICAgICB2YXIgY3VycmVudFJlcGxhY2UgPSAkbG9jYXRpb24uJCRyZXBsYWNlOw0KICAgICAgdmFyIHVybE9yU3RhdGVDaGFuZ2VkID0gb2xkVXJsICE9PSBuZXdVcmwgfHwNCiAgICAgICAgKCRsb2NhdGlvbi4kJGh0bWw1ICYmICRzbmlmZmVyLmhpc3RvcnkgJiYgb2xkU3RhdGUgIT09ICRsb2NhdGlvbi4kJHN0YXRlKTsNCg0KICAgICAgaWYgKGluaXRpYWxpemluZyB8fCB1cmxPclN0YXRlQ2hhbmdlZCkgew0KICAgICAgICBpbml0aWFsaXppbmcgPSBmYWxzZTsNCg0KICAgICAgICAkcm9vdFNjb3BlLiRldmFsQXN5bmMoZnVuY3Rpb24oKSB7DQogICAgICAgICAgdmFyIG5ld1VybCA9ICRsb2NhdGlvbi5hYnNVcmwoKTsNCiAgICAgICAgICB2YXIgZGVmYXVsdFByZXZlbnRlZCA9ICRyb290U2NvcGUuJGJyb2FkY2FzdCgnJGxvY2F0aW9uQ2hhbmdlU3RhcnQnLCBuZXdVcmwsIG9sZFVybCwNCiAgICAgICAgICAgICAgJGxvY2F0aW9uLiQkc3RhdGUsIG9sZFN0YXRlKS5kZWZhdWx0UHJldmVudGVkOw0KDQogICAgICAgICAgLy8gaWYgdGhlIGxvY2F0aW9uIHdhcyBjaGFuZ2VkIGJ5IGEgYCRsb2NhdGlvbkNoYW5nZVN0YXJ0YCBoYW5kbGVyIHRoZW4gc3RvcA0KICAgICAgICAgIC8vIHByb2Nlc3NpbmcgdGhpcyBsb2NhdGlvbiBjaGFuZ2UNCiAgICAgICAgICBpZiAoJGxvY2F0aW9uLmFic1VybCgpICE9PSBuZXdVcmwpIHJldHVybjsNCg0KICAgICAgICAgIGlmIChkZWZhdWx0UHJldmVudGVkKSB7DQogICAgICAgICAgICAkbG9jYXRpb24uJCRwYXJzZShvbGRVcmwpOw0KICAgICAgICAgICAgJGxvY2F0aW9uLiQkc3RhdGUgPSBvbGRTdGF0ZTsNCiAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgaWYgKHVybE9yU3RhdGVDaGFuZ2VkKSB7DQogICAgICAgICAgICAgIHNldEJyb3dzZXJVcmxXaXRoRmFsbGJhY2sobmV3VXJsLCBjdXJyZW50UmVwbGFjZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRTdGF0ZSA9PT0gJGxvY2F0aW9uLiQkc3RhdGUgPyBudWxsIDogJGxvY2F0aW9uLiQkc3RhdGUpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgYWZ0ZXJMb2NhdGlvbkNoYW5nZShvbGRVcmwsIG9sZFN0YXRlKTsNCiAgICAgICAgICB9DQogICAgICAgIH0pOw0KICAgICAgfQ0KDQogICAgICAkbG9jYXRpb24uJCRyZXBsYWNlID0gZmFsc2U7DQoNCiAgICAgIC8vIHdlIGRvbid0IG5lZWQgdG8gcmV0dXJuIGFueXRoaW5nIGJlY2F1c2UgJGV2YWxBc3luYyB3aWxsIG1ha2UgdGhlIGRpZ2VzdCBsb29wIGRpcnR5IHdoZW4NCiAgICAgIC8vIHRoZXJlIGlzIGEgY2hhbmdlDQogICAgfSk7DQoNCiAgICByZXR1cm4gJGxvY2F0aW9uOw0KDQogICAgZnVuY3Rpb24gYWZ0ZXJMb2NhdGlvbkNoYW5nZShvbGRVcmwsIG9sZFN0YXRlKSB7DQogICAgICAkcm9vdFNjb3BlLiRicm9hZGNhc3QoJyRsb2NhdGlvbkNoYW5nZVN1Y2Nlc3MnLCAkbG9jYXRpb24uYWJzVXJsKCksIG9sZFVybCwNCiAgICAgICAgJGxvY2F0aW9uLiQkc3RhdGUsIG9sZFN0YXRlKTsNCiAgICB9DQp9XTsNCn0NCg0KLyoqDQogKiBAbmdkb2Mgc2VydmljZQ0KICogQG5hbWUgJGxvZw0KICogQHJlcXVpcmVzICR3aW5kb3cNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFNpbXBsZSBzZXJ2aWNlIGZvciBsb2dnaW5nLiBEZWZhdWx0IGltcGxlbWVudGF0aW9uIHNhZmVseSB3cml0ZXMgdGhlIG1lc3NhZ2UNCiAqIGludG8gdGhlIGJyb3dzZXIncyBjb25zb2xlIChpZiBwcmVzZW50KS4NCiAqDQogKiBUaGUgbWFpbiBwdXJwb3NlIG9mIHRoaXMgc2VydmljZSBpcyB0byBzaW1wbGlmeSBkZWJ1Z2dpbmcgYW5kIHRyb3VibGVzaG9vdGluZy4NCiAqDQogKiBUaGUgZGVmYXVsdCBpcyB0byBsb2cgYGRlYnVnYCBtZXNzYWdlcy4gWW91IGNhbiB1c2UNCiAqIHtAbGluayBuZy4kbG9nUHJvdmlkZXIgbmcuJGxvZ1Byb3ZpZGVyI2RlYnVnRW5hYmxlZH0gdG8gY2hhbmdlIHRoaXMuDQogKg0KICogQGV4YW1wbGUNCiAgIDxleGFtcGxlIG1vZHVsZT0ibG9nRXhhbXBsZSI+DQogICAgIDxmaWxlIG5hbWU9InNjcmlwdC5qcyI+DQogICAgICAgYW5ndWxhci5tb2R1bGUoJ2xvZ0V4YW1wbGUnLCBbXSkNCiAgICAgICAgIC5jb250cm9sbGVyKCdMb2dDb250cm9sbGVyJywgWyckc2NvcGUnLCAnJGxvZycsIGZ1bmN0aW9uKCRzY29wZSwgJGxvZykgew0KICAgICAgICAgICAkc2NvcGUuJGxvZyA9ICRsb2c7DQogICAgICAgICAgICRzY29wZS5tZXNzYWdlID0gJ0hlbGxvIFdvcmxkISc7DQogICAgICAgICB9XSk7DQogICAgIDwvZmlsZT4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPGRpdiBuZy1jb250cm9sbGVyPSJMb2dDb250cm9sbGVyIj4NCiAgICAgICAgIDxwPlJlbG9hZCB0aGlzIHBhZ2Ugd2l0aCBvcGVuIGNvbnNvbGUsIGVudGVyIHRleHQgYW5kIGhpdCB0aGUgbG9nIGJ1dHRvbi4uLjwvcD4NCiAgICAgICAgIE1lc3NhZ2U6DQogICAgICAgICA8aW5wdXQgdHlwZT0idGV4dCIgbmctbW9kZWw9Im1lc3NhZ2UiLz4NCiAgICAgICAgIDxidXR0b24gbmctY2xpY2s9IiRsb2cubG9nKG1lc3NhZ2UpIj5sb2c8L2J1dHRvbj4NCiAgICAgICAgIDxidXR0b24gbmctY2xpY2s9IiRsb2cud2FybihtZXNzYWdlKSI+d2FybjwvYnV0dG9uPg0KICAgICAgICAgPGJ1dHRvbiBuZy1jbGljaz0iJGxvZy5pbmZvKG1lc3NhZ2UpIj5pbmZvPC9idXR0b24+DQogICAgICAgICA8YnV0dG9uIG5nLWNsaWNrPSIkbG9nLmVycm9yKG1lc3NhZ2UpIj5lcnJvcjwvYnV0dG9uPg0KICAgICAgIDwvZGl2Pg0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCg0KLyoqDQogKiBAbmdkb2MgcHJvdmlkZXINCiAqIEBuYW1lICRsb2dQcm92aWRlcg0KICogQGRlc2NyaXB0aW9uDQogKiBVc2UgdGhlIGAkbG9nUHJvdmlkZXJgIHRvIGNvbmZpZ3VyZSBob3cgdGhlIGFwcGxpY2F0aW9uIGxvZ3MgbWVzc2FnZXMNCiAqLw0KZnVuY3Rpb24gJExvZ1Byb3ZpZGVyKCkgew0KICB2YXIgZGVidWcgPSB0cnVlLA0KICAgICAgc2VsZiA9IHRoaXM7DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgJGxvZ1Byb3ZpZGVyI2RlYnVnRW5hYmxlZA0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogQHBhcmFtIHtib29sZWFuPX0gZmxhZyBlbmFibGUgb3IgZGlzYWJsZSBkZWJ1ZyBsZXZlbCBtZXNzYWdlcw0KICAgKiBAcmV0dXJucyB7Kn0gY3VycmVudCB2YWx1ZSBpZiB1c2VkIGFzIGdldHRlciBvciBpdHNlbGYgKGNoYWluaW5nKSBpZiB1c2VkIGFzIHNldHRlcg0KICAgKi8NCiAgdGhpcy5kZWJ1Z0VuYWJsZWQgPSBmdW5jdGlvbihmbGFnKSB7DQogICAgaWYgKGlzRGVmaW5lZChmbGFnKSkgew0KICAgICAgZGVidWcgPSBmbGFnOw0KICAgIHJldHVybiB0aGlzOw0KICAgIH0gZWxzZSB7DQogICAgICByZXR1cm4gZGVidWc7DQogICAgfQ0KICB9Ow0KDQogIHRoaXMuJGdldCA9IFsnJHdpbmRvdycsIGZ1bmN0aW9uKCR3aW5kb3cpIHsNCiAgICByZXR1cm4gew0KICAgICAgLyoqDQogICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgKiBAbmFtZSAkbG9nI2xvZw0KICAgICAgICoNCiAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICogV3JpdGUgYSBsb2cgbWVzc2FnZQ0KICAgICAgICovDQogICAgICBsb2c6IGNvbnNvbGVMb2coJ2xvZycpLA0KDQogICAgICAvKioNCiAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAqIEBuYW1lICRsb2cjaW5mbw0KICAgICAgICoNCiAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICogV3JpdGUgYW4gaW5mb3JtYXRpb24gbWVzc2FnZQ0KICAgICAgICovDQogICAgICBpbmZvOiBjb25zb2xlTG9nKCdpbmZvJyksDQoNCiAgICAgIC8qKg0KICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICogQG5hbWUgJGxvZyN3YXJuDQogICAgICAgKg0KICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgKiBXcml0ZSBhIHdhcm5pbmcgbWVzc2FnZQ0KICAgICAgICovDQogICAgICB3YXJuOiBjb25zb2xlTG9nKCd3YXJuJyksDQoNCiAgICAgIC8qKg0KICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICogQG5hbWUgJGxvZyNlcnJvcg0KICAgICAgICoNCiAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICogV3JpdGUgYW4gZXJyb3IgbWVzc2FnZQ0KICAgICAgICovDQogICAgICBlcnJvcjogY29uc29sZUxvZygnZXJyb3InKSwNCg0KICAgICAgLyoqDQogICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgKiBAbmFtZSAkbG9nI2RlYnVnDQogICAgICAgKg0KICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgKiBXcml0ZSBhIGRlYnVnIG1lc3NhZ2UNCiAgICAgICAqLw0KICAgICAgZGVidWc6IChmdW5jdGlvbigpIHsNCiAgICAgICAgdmFyIGZuID0gY29uc29sZUxvZygnZGVidWcnKTsNCg0KICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7DQogICAgICAgICAgaWYgKGRlYnVnKSB7DQogICAgICAgICAgICBmbi5hcHBseShzZWxmLCBhcmd1bWVudHMpOw0KICAgICAgICAgIH0NCiAgICAgICAgfTsNCiAgICAgIH0oKSkNCiAgICB9Ow0KDQogICAgZnVuY3Rpb24gZm9ybWF0RXJyb3IoYXJnKSB7DQogICAgICBpZiAoYXJnIGluc3RhbmNlb2YgRXJyb3IpIHsNCiAgICAgICAgaWYgKGFyZy5zdGFjaykgew0KICAgICAgICAgIGFyZyA9IChhcmcubWVzc2FnZSAmJiBhcmcuc3RhY2suaW5kZXhPZihhcmcubWVzc2FnZSkgPT09IC0xKQ0KICAgICAgICAgICAgICA/ICdFcnJvcjogJyArIGFyZy5tZXNzYWdlICsgJ1xuJyArIGFyZy5zdGFjaw0KICAgICAgICAgICAgICA6IGFyZy5zdGFjazsNCiAgICAgICAgfSBlbHNlIGlmIChhcmcuc291cmNlVVJMKSB7DQogICAgICAgICAgYXJnID0gYXJnLm1lc3NhZ2UgKyAnXG4nICsgYXJnLnNvdXJjZVVSTCArICc6JyArIGFyZy5saW5lOw0KICAgICAgICB9DQogICAgICB9DQogICAgICByZXR1cm4gYXJnOw0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIGNvbnNvbGVMb2codHlwZSkgew0KICAgICAgdmFyIGNvbnNvbGUgPSAkd2luZG93LmNvbnNvbGUgfHwge30sDQogICAgICAgICAgbG9nRm4gPSBjb25zb2xlW3R5cGVdIHx8IGNvbnNvbGUubG9nIHx8IG5vb3AsDQogICAgICAgICAgaGFzQXBwbHkgPSBmYWxzZTsNCg0KICAgICAgLy8gTm90ZTogcmVhZGluZyBsb2dGbi5hcHBseSB0aHJvd3MgYW4gZXJyb3IgaW4gSUUxMSBpbiBJRTggZG9jdW1lbnQgbW9kZS4NCiAgICAgIC8vIFRoZSByZWFzb24gYmVoaW5kIHRoaXMgaXMgdGhhdCBjb25zb2xlLmxvZyBoYXMgdHlwZSAib2JqZWN0IiBpbiBJRTguLi4NCiAgICAgIHRyeSB7DQogICAgICAgIGhhc0FwcGx5ID0gISFsb2dGbi5hcHBseTsNCiAgICAgIH0gY2F0Y2ggKGUpIHt9DQoNCiAgICAgIGlmIChoYXNBcHBseSkgew0KICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7DQogICAgICAgICAgdmFyIGFyZ3MgPSBbXTsNCiAgICAgICAgICBmb3JFYWNoKGFyZ3VtZW50cywgZnVuY3Rpb24oYXJnKSB7DQogICAgICAgICAgICBhcmdzLnB1c2goZm9ybWF0RXJyb3IoYXJnKSk7DQogICAgICAgICAgfSk7DQogICAgICAgICAgcmV0dXJuIGxvZ0ZuLmFwcGx5KGNvbnNvbGUsIGFyZ3MpOw0KICAgICAgICB9Ow0KICAgICAgfQ0KDQogICAgICAvLyB3ZSBhcmUgSUUgd2hpY2ggZWl0aGVyIGRvZXNuJ3QgaGF2ZSB3aW5kb3cuY29uc29sZSA9PiB0aGlzIGlzIG5vb3AgYW5kIHdlIGRvIG5vdGhpbmcsDQogICAgICAvLyBvciB3ZSBhcmUgSUUgd2hlcmUgY29uc29sZS5sb2cgZG9lc24ndCBoYXZlIGFwcGx5IHNvIHdlIGxvZyBhdCBsZWFzdCBmaXJzdCAyIGFyZ3MNCiAgICAgIHJldHVybiBmdW5jdGlvbihhcmcxLCBhcmcyKSB7DQogICAgICAgIGxvZ0ZuKGFyZzEsIGFyZzIgPT0gbnVsbCA/ICcnIDogYXJnMik7DQogICAgICB9Ow0KICAgIH0NCiAgfV07DQp9DQoNCnZhciAkcGFyc2VNaW5FcnIgPSBtaW5FcnIoJyRwYXJzZScpOw0KDQovLyBTYW5kYm94aW5nIEFuZ3VsYXIgRXhwcmVzc2lvbnMNCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KLy8gQW5ndWxhciBleHByZXNzaW9ucyBhcmUgZ2VuZXJhbGx5IGNvbnNpZGVyZWQgc2FmZSBiZWNhdXNlIHRoZXNlIGV4cHJlc3Npb25zIG9ubHkgaGF2ZSBkaXJlY3QNCi8vIGFjY2VzcyB0byBgJHNjb3BlYCBhbmQgbG9jYWxzLiBIb3dldmVyLCBvbmUgY2FuIG9idGFpbiB0aGUgYWJpbGl0eSB0byBleGVjdXRlIGFyYml0cmFyeSBKUyBjb2RlIGJ5DQovLyBvYnRhaW5pbmcgYSByZWZlcmVuY2UgdG8gbmF0aXZlIEpTIGZ1bmN0aW9ucyBzdWNoIGFzIHRoZSBGdW5jdGlvbiBjb25zdHJ1Y3Rvci4NCi8vDQovLyBBcyBhbiBleGFtcGxlLCBjb25zaWRlciB0aGUgZm9sbG93aW5nIEFuZ3VsYXIgZXhwcmVzc2lvbjoNCi8vDQovLyAgIHt9LnRvU3RyaW5nLmNvbnN0cnVjdG9yKCdhbGVydCgiZXZpbCBKUyBjb2RlIiknKQ0KLy8NCi8vIFRoaXMgc2FuZGJveGluZyB0ZWNobmlxdWUgaXMgbm90IHBlcmZlY3QgYW5kIGRvZXNuJ3QgYWltIHRvIGJlLiBUaGUgZ29hbCBpcyB0byBwcmV2ZW50IGV4cGxvaXRzDQovLyBhZ2FpbnN0IHRoZSBleHByZXNzaW9uIGxhbmd1YWdlLCBidXQgbm90IHRvIHByZXZlbnQgZXhwbG9pdHMgdGhhdCB3ZXJlIGVuYWJsZWQgYnkgZXhwb3NpbmcNCi8vIHNlbnNpdGl2ZSBKYXZhU2NyaXB0IG9yIGJyb3dzZXIgQVBJcyBvbiBTY29wZS4gRXhwb3Npbmcgc3VjaCBvYmplY3RzIG9uIGEgU2NvcGUgaXMgbmV2ZXIgYSBnb29kDQovLyBwcmFjdGljZSBhbmQgdGhlcmVmb3JlIHdlIGFyZSBub3QgZXZlbiB0cnlpbmcgdG8gcHJvdGVjdCBhZ2FpbnN0IGludGVyYWN0aW9uIHdpdGggYW4gb2JqZWN0DQovLyBleHBsaWNpdGx5IGV4cG9zZWQgaW4gdGhpcyB3YXkuDQovLw0KLy8gSW4gZ2VuZXJhbCwgaXQgaXMgbm90IHBvc3NpYmxlIHRvIGFjY2VzcyBhIFdpbmRvdyBvYmplY3QgZnJvbSBhbiBhbmd1bGFyIGV4cHJlc3Npb24gdW5sZXNzIGENCi8vIHdpbmRvdyBvciBzb21lIERPTSBvYmplY3QgdGhhdCBoYXMgYSByZWZlcmVuY2UgdG8gd2luZG93IGlzIHB1Ymxpc2hlZCBvbnRvIGEgU2NvcGUuDQovLyBTaW1pbGFybHkgd2UgcHJldmVudCBpbnZvY2F0aW9ucyBvZiBmdW5jdGlvbiBrbm93biB0byBiZSBkYW5nZXJvdXMsIGFzIHdlbGwgYXMgYXNzaWdubWVudHMgdG8NCi8vIG5hdGl2ZSBvYmplY3RzLg0KLy8NCi8vIFNlZSBodHRwczovL2RvY3MuYW5ndWxhcmpzLm9yZy9ndWlkZS9zZWN1cml0eQ0KDQoNCmZ1bmN0aW9uIGVuc3VyZVNhZmVNZW1iZXJOYW1lKG5hbWUsIGZ1bGxFeHByZXNzaW9uKSB7DQogIGlmIChuYW1lID09PSAiX19kZWZpbmVHZXR0ZXJfXyIgfHwgbmFtZSA9PT0gIl9fZGVmaW5lU2V0dGVyX18iDQogICAgICB8fCBuYW1lID09PSAiX19sb29rdXBHZXR0ZXJfXyIgfHwgbmFtZSA9PT0gIl9fbG9va3VwU2V0dGVyX18iDQogICAgICB8fCBuYW1lID09PSAiX19wcm90b19fIikgew0KICAgIHRocm93ICRwYXJzZU1pbkVycignaXNlY2ZsZCcsDQogICAgICAgICdBdHRlbXB0aW5nIHRvIGFjY2VzcyBhIGRpc2FsbG93ZWQgZmllbGQgaW4gQW5ndWxhciBleHByZXNzaW9ucyEgJw0KICAgICAgICArICdFeHByZXNzaW9uOiB7MH0nLCBmdWxsRXhwcmVzc2lvbik7DQogIH0NCiAgcmV0dXJuIG5hbWU7DQp9DQoNCmZ1bmN0aW9uIGVuc3VyZVNhZmVPYmplY3Qob2JqLCBmdWxsRXhwcmVzc2lvbikgew0KICAvLyBuaWZ0eSBjaGVjayBpZiBvYmogaXMgRnVuY3Rpb24gdGhhdCBpcyBmYXN0IGFuZCB3b3JrcyBhY3Jvc3MgaWZyYW1lcyBhbmQgb3RoZXIgY29udGV4dHMNCiAgaWYgKG9iaikgew0KICAgIGlmIChvYmouY29uc3RydWN0b3IgPT09IG9iaikgew0KICAgICAgdGhyb3cgJHBhcnNlTWluRXJyKCdpc2VjZm4nLA0KICAgICAgICAgICdSZWZlcmVuY2luZyBGdW5jdGlvbiBpbiBBbmd1bGFyIGV4cHJlc3Npb25zIGlzIGRpc2FsbG93ZWQhIEV4cHJlc3Npb246IHswfScsDQogICAgICAgICAgZnVsbEV4cHJlc3Npb24pOw0KICAgIH0gZWxzZSBpZiAoLy8gaXNXaW5kb3cob2JqKQ0KICAgICAgICBvYmoud2luZG93ID09PSBvYmopIHsNCiAgICAgIHRocm93ICRwYXJzZU1pbkVycignaXNlY3dpbmRvdycsDQogICAgICAgICAgJ1JlZmVyZW5jaW5nIHRoZSBXaW5kb3cgaW4gQW5ndWxhciBleHByZXNzaW9ucyBpcyBkaXNhbGxvd2VkISBFeHByZXNzaW9uOiB7MH0nLA0KICAgICAgICAgIGZ1bGxFeHByZXNzaW9uKTsNCiAgICB9IGVsc2UgaWYgKC8vIGlzRWxlbWVudChvYmopDQogICAgICAgIG9iai5jaGlsZHJlbiAmJiAob2JqLm5vZGVOYW1lIHx8IChvYmoucHJvcCAmJiBvYmouYXR0ciAmJiBvYmouZmluZCkpKSB7DQogICAgICB0aHJvdyAkcGFyc2VNaW5FcnIoJ2lzZWNkb20nLA0KICAgICAgICAgICdSZWZlcmVuY2luZyBET00gbm9kZXMgaW4gQW5ndWxhciBleHByZXNzaW9ucyBpcyBkaXNhbGxvd2VkISBFeHByZXNzaW9uOiB7MH0nLA0KICAgICAgICAgIGZ1bGxFeHByZXNzaW9uKTsNCiAgICB9IGVsc2UgaWYgKC8vIGJsb2NrIE9iamVjdCBzbyB0aGF0IHdlIGNhbid0IGdldCBob2xkIG9mIGRhbmdlcm91cyBPYmplY3QuKiBtZXRob2RzDQogICAgICAgIG9iaiA9PT0gT2JqZWN0KSB7DQogICAgICB0aHJvdyAkcGFyc2VNaW5FcnIoJ2lzZWNvYmonLA0KICAgICAgICAgICdSZWZlcmVuY2luZyBPYmplY3QgaW4gQW5ndWxhciBleHByZXNzaW9ucyBpcyBkaXNhbGxvd2VkISBFeHByZXNzaW9uOiB7MH0nLA0KICAgICAgICAgIGZ1bGxFeHByZXNzaW9uKTsNCiAgICB9DQogIH0NCiAgcmV0dXJuIG9iajsNCn0NCg0KdmFyIENBTEwgPSBGdW5jdGlvbi5wcm90b3R5cGUuY2FsbDsNCnZhciBBUFBMWSA9IEZ1bmN0aW9uLnByb3RvdHlwZS5hcHBseTsNCnZhciBCSU5EID0gRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQ7DQoNCmZ1bmN0aW9uIGVuc3VyZVNhZmVGdW5jdGlvbihvYmosIGZ1bGxFeHByZXNzaW9uKSB7DQogIGlmIChvYmopIHsNCiAgICBpZiAob2JqLmNvbnN0cnVjdG9yID09PSBvYmopIHsNCiAgICAgIHRocm93ICRwYXJzZU1pbkVycignaXNlY2ZuJywNCiAgICAgICAgJ1JlZmVyZW5jaW5nIEZ1bmN0aW9uIGluIEFuZ3VsYXIgZXhwcmVzc2lvbnMgaXMgZGlzYWxsb3dlZCEgRXhwcmVzc2lvbjogezB9JywNCiAgICAgICAgZnVsbEV4cHJlc3Npb24pOw0KICAgIH0gZWxzZSBpZiAob2JqID09PSBDQUxMIHx8IG9iaiA9PT0gQVBQTFkgfHwgb2JqID09PSBCSU5EKSB7DQogICAgICB0aHJvdyAkcGFyc2VNaW5FcnIoJ2lzZWNmZicsDQogICAgICAgICdSZWZlcmVuY2luZyBjYWxsLCBhcHBseSBvciBiaW5kIGluIEFuZ3VsYXIgZXhwcmVzc2lvbnMgaXMgZGlzYWxsb3dlZCEgRXhwcmVzc2lvbjogezB9JywNCiAgICAgICAgZnVsbEV4cHJlc3Npb24pOw0KICAgIH0NCiAgfQ0KfQ0KDQovL0tleXdvcmQgY29uc3RhbnRzDQp2YXIgQ09OU1RBTlRTID0gY3JlYXRlTWFwKCk7DQpmb3JFYWNoKHsNCiAgJ251bGwnOiBmdW5jdGlvbigpIHsgcmV0dXJuIG51bGw7IH0sDQogICd0cnVlJzogZnVuY3Rpb24oKSB7IHJldHVybiB0cnVlOyB9LA0KICAnZmFsc2UnOiBmdW5jdGlvbigpIHsgcmV0dXJuIGZhbHNlOyB9LA0KICAndW5kZWZpbmVkJzogZnVuY3Rpb24oKSB7fQ0KfSwgZnVuY3Rpb24oY29uc3RhbnRHZXR0ZXIsIG5hbWUpIHsNCiAgY29uc3RhbnRHZXR0ZXIuY29uc3RhbnQgPSBjb25zdGFudEdldHRlci5saXRlcmFsID0gY29uc3RhbnRHZXR0ZXIuc2hhcmVkR2V0dGVyID0gdHJ1ZTsNCiAgQ09OU1RBTlRTW25hbWVdID0gY29uc3RhbnRHZXR0ZXI7DQp9KTsNCg0KLy9Ob3QgcXVpdGUgYSBjb25zdGFudCwgYnV0IGNhbiBiZSBsZXgvcGFyc2VkIHRoZSBzYW1lDQpDT05TVEFOVFNbJ3RoaXMnXSA9IGZ1bmN0aW9uKHNlbGYpIHsgcmV0dXJuIHNlbGY7IH07DQpDT05TVEFOVFNbJ3RoaXMnXS5zaGFyZWRHZXR0ZXIgPSB0cnVlOw0KDQoNCi8vT3BlcmF0b3JzIC0gd2lsbCBiZSB3cmFwcGVkIGJ5IGJpbmFyeUZuL3VuYXJ5Rm4vYXNzaWdubWVudC9maWx0ZXINCnZhciBPUEVSQVRPUlMgPSBleHRlbmQoY3JlYXRlTWFwKCksIHsNCiAgICAnKyc6ZnVuY3Rpb24oc2VsZiwgbG9jYWxzLCBhLCBiKSB7DQogICAgICBhPWEoc2VsZiwgbG9jYWxzKTsgYj1iKHNlbGYsIGxvY2Fscyk7DQogICAgICBpZiAoaXNEZWZpbmVkKGEpKSB7DQogICAgICAgIGlmIChpc0RlZmluZWQoYikpIHsNCiAgICAgICAgICByZXR1cm4gYSArIGI7DQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuIGE7DQogICAgICB9DQogICAgICByZXR1cm4gaXNEZWZpbmVkKGIpID8gYiA6IHVuZGVmaW5lZDt9LA0KICAgICctJzpmdW5jdGlvbihzZWxmLCBsb2NhbHMsIGEsIGIpIHsNCiAgICAgICAgICBhPWEoc2VsZiwgbG9jYWxzKTsgYj1iKHNlbGYsIGxvY2Fscyk7DQogICAgICAgICAgcmV0dXJuIChpc0RlZmluZWQoYSkgPyBhIDogMCkgLSAoaXNEZWZpbmVkKGIpID8gYiA6IDApOw0KICAgICAgICB9LA0KICAgICcqJzpmdW5jdGlvbihzZWxmLCBsb2NhbHMsIGEsIGIpIHtyZXR1cm4gYShzZWxmLCBsb2NhbHMpICogYihzZWxmLCBsb2NhbHMpO30sDQogICAgJy8nOmZ1bmN0aW9uKHNlbGYsIGxvY2FscywgYSwgYikge3JldHVybiBhKHNlbGYsIGxvY2FscykgLyBiKHNlbGYsIGxvY2Fscyk7fSwNCiAgICAnJSc6ZnVuY3Rpb24oc2VsZiwgbG9jYWxzLCBhLCBiKSB7cmV0dXJuIGEoc2VsZiwgbG9jYWxzKSAlIGIoc2VsZiwgbG9jYWxzKTt9LA0KICAgICc9PT0nOmZ1bmN0aW9uKHNlbGYsIGxvY2FscywgYSwgYikge3JldHVybiBhKHNlbGYsIGxvY2FscykgPT09IGIoc2VsZiwgbG9jYWxzKTt9LA0KICAgICchPT0nOmZ1bmN0aW9uKHNlbGYsIGxvY2FscywgYSwgYikge3JldHVybiBhKHNlbGYsIGxvY2FscykgIT09IGIoc2VsZiwgbG9jYWxzKTt9LA0KICAgICc9PSc6ZnVuY3Rpb24oc2VsZiwgbG9jYWxzLCBhLCBiKSB7cmV0dXJuIGEoc2VsZiwgbG9jYWxzKSA9PSBiKHNlbGYsIGxvY2Fscyk7fSwNCiAgICAnIT0nOmZ1bmN0aW9uKHNlbGYsIGxvY2FscywgYSwgYikge3JldHVybiBhKHNlbGYsIGxvY2FscykgIT0gYihzZWxmLCBsb2NhbHMpO30sDQogICAgJzwnOmZ1bmN0aW9uKHNlbGYsIGxvY2FscywgYSwgYikge3JldHVybiBhKHNlbGYsIGxvY2FscykgPCBiKHNlbGYsIGxvY2Fscyk7fSwNCiAgICAnPic6ZnVuY3Rpb24oc2VsZiwgbG9jYWxzLCBhLCBiKSB7cmV0dXJuIGEoc2VsZiwgbG9jYWxzKSA+IGIoc2VsZiwgbG9jYWxzKTt9LA0KICAgICc8PSc6ZnVuY3Rpb24oc2VsZiwgbG9jYWxzLCBhLCBiKSB7cmV0dXJuIGEoc2VsZiwgbG9jYWxzKSA8PSBiKHNlbGYsIGxvY2Fscyk7fSwNCiAgICAnPj0nOmZ1bmN0aW9uKHNlbGYsIGxvY2FscywgYSwgYikge3JldHVybiBhKHNlbGYsIGxvY2FscykgPj0gYihzZWxmLCBsb2NhbHMpO30sDQogICAgJyYmJzpmdW5jdGlvbihzZWxmLCBsb2NhbHMsIGEsIGIpIHtyZXR1cm4gYShzZWxmLCBsb2NhbHMpICYmIGIoc2VsZiwgbG9jYWxzKTt9LA0KICAgICd8fCc6ZnVuY3Rpb24oc2VsZiwgbG9jYWxzLCBhLCBiKSB7cmV0dXJuIGEoc2VsZiwgbG9jYWxzKSB8fCBiKHNlbGYsIGxvY2Fscyk7fSwNCiAgICAnISc6ZnVuY3Rpb24oc2VsZiwgbG9jYWxzLCBhKSB7cmV0dXJuICFhKHNlbGYsIGxvY2Fscyk7fSwNCg0KICAgIC8vVG9rZW5pemVkIGFzIG9wZXJhdG9ycyBidXQgcGFyc2VkIGFzIGFzc2lnbm1lbnQvZmlsdGVycw0KICAgICc9Jzp0cnVlLA0KICAgICd8Jzp0cnVlDQp9KTsNCnZhciBFU0NBUEUgPSB7Im4iOiJcbiIsICJmIjoiXGYiLCAiciI6IlxyIiwgInQiOiJcdCIsICJ2IjoiXHYiLCAiJyI6IiciLCAnIic6JyInfTsNCg0KDQovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KDQoNCi8qKg0KICogQGNvbnN0cnVjdG9yDQogKi8NCnZhciBMZXhlciA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsNCiAgdGhpcy5vcHRpb25zID0gb3B0aW9uczsNCn07DQoNCkxleGVyLnByb3RvdHlwZSA9IHsNCiAgY29uc3RydWN0b3I6IExleGVyLA0KDQogIGxleDogZnVuY3Rpb24odGV4dCkgew0KICAgIHRoaXMudGV4dCA9IHRleHQ7DQogICAgdGhpcy5pbmRleCA9IDA7DQogICAgdGhpcy50b2tlbnMgPSBbXTsNCg0KICAgIHdoaWxlICh0aGlzLmluZGV4IDwgdGhpcy50ZXh0Lmxlbmd0aCkgew0KICAgICAgdmFyIGNoID0gdGhpcy50ZXh0LmNoYXJBdCh0aGlzLmluZGV4KTsNCiAgICAgIGlmIChjaCA9PT0gJyInIHx8IGNoID09PSAiJyIpIHsNCiAgICAgICAgdGhpcy5yZWFkU3RyaW5nKGNoKTsNCiAgICAgIH0gZWxzZSBpZiAodGhpcy5pc051bWJlcihjaCkgfHwgY2ggPT09ICcuJyAmJiB0aGlzLmlzTnVtYmVyKHRoaXMucGVlaygpKSkgew0KICAgICAgICB0aGlzLnJlYWROdW1iZXIoKTsNCiAgICAgIH0gZWxzZSBpZiAodGhpcy5pc0lkZW50KGNoKSkgew0KICAgICAgICB0aGlzLnJlYWRJZGVudCgpOw0KICAgICAgfSBlbHNlIGlmICh0aGlzLmlzKGNoLCAnKCl7fVtdLiw7Oj8nKSkgew0KICAgICAgICB0aGlzLnRva2Vucy5wdXNoKHtpbmRleDogdGhpcy5pbmRleCwgdGV4dDogY2h9KTsNCiAgICAgICAgdGhpcy5pbmRleCsrOw0KICAgICAgfSBlbHNlIGlmICh0aGlzLmlzV2hpdGVzcGFjZShjaCkpIHsNCiAgICAgICAgdGhpcy5pbmRleCsrOw0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgdmFyIGNoMiA9IGNoICsgdGhpcy5wZWVrKCk7DQogICAgICAgIHZhciBjaDMgPSBjaDIgKyB0aGlzLnBlZWsoMik7DQogICAgICAgIHZhciBvcDEgPSBPUEVSQVRPUlNbY2hdOw0KICAgICAgICB2YXIgb3AyID0gT1BFUkFUT1JTW2NoMl07DQogICAgICAgIHZhciBvcDMgPSBPUEVSQVRPUlNbY2gzXTsNCiAgICAgICAgaWYgKG9wMSB8fCBvcDIgfHwgb3AzKSB7DQogICAgICAgICAgdmFyIHRva2VuID0gb3AzID8gY2gzIDogKG9wMiA/IGNoMiA6IGNoKTsNCiAgICAgICAgICB0aGlzLnRva2Vucy5wdXNoKHtpbmRleDogdGhpcy5pbmRleCwgdGV4dDogdG9rZW4sIG9wZXJhdG9yOiB0cnVlfSk7DQogICAgICAgICAgdGhpcy5pbmRleCArPSB0b2tlbi5sZW5ndGg7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgdGhpcy50aHJvd0Vycm9yKCdVbmV4cGVjdGVkIG5leHQgY2hhcmFjdGVyICcsIHRoaXMuaW5kZXgsIHRoaXMuaW5kZXggKyAxKTsNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgIH0NCiAgICByZXR1cm4gdGhpcy50b2tlbnM7DQogIH0sDQoNCiAgaXM6IGZ1bmN0aW9uKGNoLCBjaGFycykgew0KICAgIHJldHVybiBjaGFycy5pbmRleE9mKGNoKSAhPT0gLTE7DQogIH0sDQoNCiAgcGVlazogZnVuY3Rpb24oaSkgew0KICAgIHZhciBudW0gPSBpIHx8IDE7DQogICAgcmV0dXJuICh0aGlzLmluZGV4ICsgbnVtIDwgdGhpcy50ZXh0Lmxlbmd0aCkgPyB0aGlzLnRleHQuY2hhckF0KHRoaXMuaW5kZXggKyBudW0pIDogZmFsc2U7DQogIH0sDQoNCiAgaXNOdW1iZXI6IGZ1bmN0aW9uKGNoKSB7DQogICAgcmV0dXJuICgnMCcgPD0gY2ggJiYgY2ggPD0gJzknKSAmJiB0eXBlb2YgY2ggPT09ICJzdHJpbmciOw0KICB9LA0KDQogIGlzV2hpdGVzcGFjZTogZnVuY3Rpb24oY2gpIHsNCiAgICAvLyBJRSB0cmVhdHMgbm9uLWJyZWFraW5nIHNwYWNlIGFzIFx1MDBBMA0KICAgIHJldHVybiAoY2ggPT09ICcgJyB8fCBjaCA9PT0gJ1xyJyB8fCBjaCA9PT0gJ1x0JyB8fA0KICAgICAgICAgICAgY2ggPT09ICdcbicgfHwgY2ggPT09ICdcdicgfHwgY2ggPT09ICdcdTAwQTAnKTsNCiAgfSwNCg0KICBpc0lkZW50OiBmdW5jdGlvbihjaCkgew0KICAgIHJldHVybiAoJ2EnIDw9IGNoICYmIGNoIDw9ICd6JyB8fA0KICAgICAgICAgICAgJ0EnIDw9IGNoICYmIGNoIDw9ICdaJyB8fA0KICAgICAgICAgICAgJ18nID09PSBjaCB8fCBjaCA9PT0gJyQnKTsNCiAgfSwNCg0KICBpc0V4cE9wZXJhdG9yOiBmdW5jdGlvbihjaCkgew0KICAgIHJldHVybiAoY2ggPT09ICctJyB8fCBjaCA9PT0gJysnIHx8IHRoaXMuaXNOdW1iZXIoY2gpKTsNCiAgfSwNCg0KICB0aHJvd0Vycm9yOiBmdW5jdGlvbihlcnJvciwgc3RhcnQsIGVuZCkgew0KICAgIGVuZCA9IGVuZCB8fCB0aGlzLmluZGV4Ow0KICAgIHZhciBjb2xTdHIgPSAoaXNEZWZpbmVkKHN0YXJ0KQ0KICAgICAgICAgICAgPyAncyAnICsgc3RhcnQgKyAgJy0nICsgdGhpcy5pbmRleCArICcgWycgKyB0aGlzLnRleHQuc3Vic3RyaW5nKHN0YXJ0LCBlbmQpICsgJ10nDQogICAgICAgICAgICA6ICcgJyArIGVuZCk7DQogICAgdGhyb3cgJHBhcnNlTWluRXJyKCdsZXhlcnInLCAnTGV4ZXIgRXJyb3I6IHswfSBhdCBjb2x1bW57MX0gaW4gZXhwcmVzc2lvbiBbezJ9XS4nLA0KICAgICAgICBlcnJvciwgY29sU3RyLCB0aGlzLnRleHQpOw0KICB9LA0KDQogIHJlYWROdW1iZXI6IGZ1bmN0aW9uKCkgew0KICAgIHZhciBudW1iZXIgPSAnJzsNCiAgICB2YXIgc3RhcnQgPSB0aGlzLmluZGV4Ow0KICAgIHdoaWxlICh0aGlzLmluZGV4IDwgdGhpcy50ZXh0Lmxlbmd0aCkgew0KICAgICAgdmFyIGNoID0gbG93ZXJjYXNlKHRoaXMudGV4dC5jaGFyQXQodGhpcy5pbmRleCkpOw0KICAgICAgaWYgKGNoID09ICcuJyB8fCB0aGlzLmlzTnVtYmVyKGNoKSkgew0KICAgICAgICBudW1iZXIgKz0gY2g7DQogICAgICB9IGVsc2Ugew0KICAgICAgICB2YXIgcGVla0NoID0gdGhpcy5wZWVrKCk7DQogICAgICAgIGlmIChjaCA9PSAnZScgJiYgdGhpcy5pc0V4cE9wZXJhdG9yKHBlZWtDaCkpIHsNCiAgICAgICAgICBudW1iZXIgKz0gY2g7DQogICAgICAgIH0gZWxzZSBpZiAodGhpcy5pc0V4cE9wZXJhdG9yKGNoKSAmJg0KICAgICAgICAgICAgcGVla0NoICYmIHRoaXMuaXNOdW1iZXIocGVla0NoKSAmJg0KICAgICAgICAgICAgbnVtYmVyLmNoYXJBdChudW1iZXIubGVuZ3RoIC0gMSkgPT0gJ2UnKSB7DQogICAgICAgICAgbnVtYmVyICs9IGNoOw0KICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaXNFeHBPcGVyYXRvcihjaCkgJiYNCiAgICAgICAgICAgICghcGVla0NoIHx8ICF0aGlzLmlzTnVtYmVyKHBlZWtDaCkpICYmDQogICAgICAgICAgICBudW1iZXIuY2hhckF0KG51bWJlci5sZW5ndGggLSAxKSA9PSAnZScpIHsNCiAgICAgICAgICB0aGlzLnRocm93RXJyb3IoJ0ludmFsaWQgZXhwb25lbnQnKTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgdGhpcy5pbmRleCsrOw0KICAgIH0NCiAgICB0aGlzLnRva2Vucy5wdXNoKHsNCiAgICAgIGluZGV4OiBzdGFydCwNCiAgICAgIHRleHQ6IG51bWJlciwNCiAgICAgIGNvbnN0YW50OiB0cnVlLA0KICAgICAgdmFsdWU6IE51bWJlcihudW1iZXIpDQogICAgfSk7DQogIH0sDQoNCiAgcmVhZElkZW50OiBmdW5jdGlvbigpIHsNCiAgICB2YXIgc3RhcnQgPSB0aGlzLmluZGV4Ow0KICAgIHdoaWxlICh0aGlzLmluZGV4IDwgdGhpcy50ZXh0Lmxlbmd0aCkgew0KICAgICAgdmFyIGNoID0gdGhpcy50ZXh0LmNoYXJBdCh0aGlzLmluZGV4KTsNCiAgICAgIGlmICghKHRoaXMuaXNJZGVudChjaCkgfHwgdGhpcy5pc051bWJlcihjaCkpKSB7DQogICAgICAgIGJyZWFrOw0KICAgICAgfQ0KICAgICAgdGhpcy5pbmRleCsrOw0KICAgIH0NCiAgICB0aGlzLnRva2Vucy5wdXNoKHsNCiAgICAgIGluZGV4OiBzdGFydCwNCiAgICAgIHRleHQ6IHRoaXMudGV4dC5zbGljZShzdGFydCwgdGhpcy5pbmRleCksDQogICAgICBpZGVudGlmaWVyOiB0cnVlDQogICAgfSk7DQogIH0sDQoNCiAgcmVhZFN0cmluZzogZnVuY3Rpb24ocXVvdGUpIHsNCiAgICB2YXIgc3RhcnQgPSB0aGlzLmluZGV4Ow0KICAgIHRoaXMuaW5kZXgrKzsNCiAgICB2YXIgc3RyaW5nID0gJyc7DQogICAgdmFyIHJhd1N0cmluZyA9IHF1b3RlOw0KICAgIHZhciBlc2NhcGUgPSBmYWxzZTsNCiAgICB3aGlsZSAodGhpcy5pbmRleCA8IHRoaXMudGV4dC5sZW5ndGgpIHsNCiAgICAgIHZhciBjaCA9IHRoaXMudGV4dC5jaGFyQXQodGhpcy5pbmRleCk7DQogICAgICByYXdTdHJpbmcgKz0gY2g7DQogICAgICBpZiAoZXNjYXBlKSB7DQogICAgICAgIGlmIChjaCA9PT0gJ3UnKSB7DQogICAgICAgICAgdmFyIGhleCA9IHRoaXMudGV4dC5zdWJzdHJpbmcodGhpcy5pbmRleCArIDEsIHRoaXMuaW5kZXggKyA1KTsNCiAgICAgICAgICBpZiAoIWhleC5tYXRjaCgvW1xkYS1mXXs0fS9pKSkNCiAgICAgICAgICAgIHRoaXMudGhyb3dFcnJvcignSW52YWxpZCB1bmljb2RlIGVzY2FwZSBbXFx1JyArIGhleCArICddJyk7DQogICAgICAgICAgdGhpcy5pbmRleCArPSA0Ow0KICAgICAgICAgIHN0cmluZyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHBhcnNlSW50KGhleCwgMTYpKTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICB2YXIgcmVwID0gRVNDQVBFW2NoXTsNCiAgICAgICAgICBzdHJpbmcgPSBzdHJpbmcgKyAocmVwIHx8IGNoKTsNCiAgICAgICAgfQ0KICAgICAgICBlc2NhcGUgPSBmYWxzZTsNCiAgICAgIH0gZWxzZSBpZiAoY2ggPT09ICdcXCcpIHsNCiAgICAgICAgZXNjYXBlID0gdHJ1ZTsNCiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IHF1b3RlKSB7DQogICAgICAgIHRoaXMuaW5kZXgrKzsNCiAgICAgICAgdGhpcy50b2tlbnMucHVzaCh7DQogICAgICAgICAgaW5kZXg6IHN0YXJ0LA0KICAgICAgICAgIHRleHQ6IHJhd1N0cmluZywNCiAgICAgICAgICBjb25zdGFudDogdHJ1ZSwNCiAgICAgICAgICB2YWx1ZTogc3RyaW5nDQogICAgICAgIH0pOw0KICAgICAgICByZXR1cm47DQogICAgICB9IGVsc2Ugew0KICAgICAgICBzdHJpbmcgKz0gY2g7DQogICAgICB9DQogICAgICB0aGlzLmluZGV4Kys7DQogICAgfQ0KICAgIHRoaXMudGhyb3dFcnJvcignVW50ZXJtaW5hdGVkIHF1b3RlJywgc3RhcnQpOw0KICB9DQp9Ow0KDQoNCmZ1bmN0aW9uIGlzQ29uc3RhbnQoZXhwKSB7DQogIHJldHVybiBleHAuY29uc3RhbnQ7DQp9DQoNCi8qKg0KICogQGNvbnN0cnVjdG9yDQogKi8NCnZhciBQYXJzZXIgPSBmdW5jdGlvbihsZXhlciwgJGZpbHRlciwgb3B0aW9ucykgew0KICB0aGlzLmxleGVyID0gbGV4ZXI7DQogIHRoaXMuJGZpbHRlciA9ICRmaWx0ZXI7DQogIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7DQp9Ow0KDQpQYXJzZXIuWkVSTyA9IGV4dGVuZChmdW5jdGlvbigpIHsNCiAgcmV0dXJuIDA7DQp9LCB7DQogIHNoYXJlZEdldHRlcjogdHJ1ZSwNCiAgY29uc3RhbnQ6IHRydWUNCn0pOw0KDQpQYXJzZXIucHJvdG90eXBlID0gew0KICBjb25zdHJ1Y3RvcjogUGFyc2VyLA0KDQogIHBhcnNlOiBmdW5jdGlvbih0ZXh0KSB7DQogICAgdGhpcy50ZXh0ID0gdGV4dDsNCiAgICB0aGlzLnRva2VucyA9IHRoaXMubGV4ZXIubGV4KHRleHQpOw0KDQogICAgdmFyIHZhbHVlID0gdGhpcy5zdGF0ZW1lbnRzKCk7DQoNCiAgICBpZiAodGhpcy50b2tlbnMubGVuZ3RoICE9PSAwKSB7DQogICAgICB0aGlzLnRocm93RXJyb3IoJ2lzIGFuIHVuZXhwZWN0ZWQgdG9rZW4nLCB0aGlzLnRva2Vuc1swXSk7DQogICAgfQ0KDQogICAgdmFsdWUubGl0ZXJhbCA9ICEhdmFsdWUubGl0ZXJhbDsNCiAgICB2YWx1ZS5jb25zdGFudCA9ICEhdmFsdWUuY29uc3RhbnQ7DQoNCiAgICByZXR1cm4gdmFsdWU7DQogIH0sDQoNCiAgcHJpbWFyeTogZnVuY3Rpb24oKSB7DQogICAgdmFyIHByaW1hcnk7DQogICAgaWYgKHRoaXMuZXhwZWN0KCcoJykpIHsNCiAgICAgIHByaW1hcnkgPSB0aGlzLmZpbHRlckNoYWluKCk7DQogICAgICB0aGlzLmNvbnN1bWUoJyknKTsNCiAgICB9IGVsc2UgaWYgKHRoaXMuZXhwZWN0KCdbJykpIHsNCiAgICAgIHByaW1hcnkgPSB0aGlzLmFycmF5RGVjbGFyYXRpb24oKTsNCiAgICB9IGVsc2UgaWYgKHRoaXMuZXhwZWN0KCd7JykpIHsNCiAgICAgIHByaW1hcnkgPSB0aGlzLm9iamVjdCgpOw0KICAgIH0gZWxzZSBpZiAodGhpcy5wZWVrKCkuaWRlbnRpZmllciAmJiB0aGlzLnBlZWsoKS50ZXh0IGluIENPTlNUQU5UUykgew0KICAgICAgcHJpbWFyeSA9IENPTlNUQU5UU1t0aGlzLmNvbnN1bWUoKS50ZXh0XTsNCiAgICB9IGVsc2UgaWYgKHRoaXMucGVlaygpLmlkZW50aWZpZXIpIHsNCiAgICAgIHByaW1hcnkgPSB0aGlzLmlkZW50aWZpZXIoKTsNCiAgICB9IGVsc2UgaWYgKHRoaXMucGVlaygpLmNvbnN0YW50KSB7DQogICAgICBwcmltYXJ5ID0gdGhpcy5jb25zdGFudCgpOw0KICAgIH0gZWxzZSB7DQogICAgICB0aGlzLnRocm93RXJyb3IoJ25vdCBhIHByaW1hcnkgZXhwcmVzc2lvbicsIHRoaXMucGVlaygpKTsNCiAgICB9DQoNCiAgICB2YXIgbmV4dCwgY29udGV4dDsNCiAgICB3aGlsZSAoKG5leHQgPSB0aGlzLmV4cGVjdCgnKCcsICdbJywgJy4nKSkpIHsNCiAgICAgIGlmIChuZXh0LnRleHQgPT09ICcoJykgew0KICAgICAgICBwcmltYXJ5ID0gdGhpcy5mdW5jdGlvbkNhbGwocHJpbWFyeSwgY29udGV4dCk7DQogICAgICAgIGNvbnRleHQgPSBudWxsOw0KICAgICAgfSBlbHNlIGlmIChuZXh0LnRleHQgPT09ICdbJykgew0KICAgICAgICBjb250ZXh0ID0gcHJpbWFyeTsNCiAgICAgICAgcHJpbWFyeSA9IHRoaXMub2JqZWN0SW5kZXgocHJpbWFyeSk7DQogICAgICB9IGVsc2UgaWYgKG5leHQudGV4dCA9PT0gJy4nKSB7DQogICAgICAgIGNvbnRleHQgPSBwcmltYXJ5Ow0KICAgICAgICBwcmltYXJ5ID0gdGhpcy5maWVsZEFjY2VzcyhwcmltYXJ5KTsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIHRoaXMudGhyb3dFcnJvcignSU1QT1NTSUJMRScpOw0KICAgICAgfQ0KICAgIH0NCiAgICByZXR1cm4gcHJpbWFyeTsNCiAgfSwNCg0KICB0aHJvd0Vycm9yOiBmdW5jdGlvbihtc2csIHRva2VuKSB7DQogICAgdGhyb3cgJHBhcnNlTWluRXJyKCdzeW50YXgnLA0KICAgICAgICAnU3ludGF4IEVycm9yOiBUb2tlbiBcJ3swfVwnIHsxfSBhdCBjb2x1bW4gezJ9IG9mIHRoZSBleHByZXNzaW9uIFt7M31dIHN0YXJ0aW5nIGF0IFt7NH1dLicsDQogICAgICAgICAgdG9rZW4udGV4dCwgbXNnLCAodG9rZW4uaW5kZXggKyAxKSwgdGhpcy50ZXh0LCB0aGlzLnRleHQuc3Vic3RyaW5nKHRva2VuLmluZGV4KSk7DQogIH0sDQoNCiAgcGVla1Rva2VuOiBmdW5jdGlvbigpIHsNCiAgICBpZiAodGhpcy50b2tlbnMubGVuZ3RoID09PSAwKQ0KICAgICAgdGhyb3cgJHBhcnNlTWluRXJyKCd1ZW9lJywgJ1VuZXhwZWN0ZWQgZW5kIG9mIGV4cHJlc3Npb246IHswfScsIHRoaXMudGV4dCk7DQogICAgcmV0dXJuIHRoaXMudG9rZW5zWzBdOw0KICB9LA0KDQogIHBlZWs6IGZ1bmN0aW9uKGUxLCBlMiwgZTMsIGU0KSB7DQogICAgcmV0dXJuIHRoaXMucGVla0FoZWFkKDAsIGUxLCBlMiwgZTMsIGU0KTsNCiAgfSwNCiAgcGVla0FoZWFkOiBmdW5jdGlvbihpLCBlMSwgZTIsIGUzLCBlNCkgew0KICAgIGlmICh0aGlzLnRva2Vucy5sZW5ndGggPiBpKSB7DQogICAgICB2YXIgdG9rZW4gPSB0aGlzLnRva2Vuc1tpXTsNCiAgICAgIHZhciB0ID0gdG9rZW4udGV4dDsNCiAgICAgIGlmICh0ID09PSBlMSB8fCB0ID09PSBlMiB8fCB0ID09PSBlMyB8fCB0ID09PSBlNCB8fA0KICAgICAgICAgICghZTEgJiYgIWUyICYmICFlMyAmJiAhZTQpKSB7DQogICAgICAgIHJldHVybiB0b2tlbjsNCiAgICAgIH0NCiAgICB9DQogICAgcmV0dXJuIGZhbHNlOw0KICB9LA0KDQogIGV4cGVjdDogZnVuY3Rpb24oZTEsIGUyLCBlMywgZTQpIHsNCiAgICB2YXIgdG9rZW4gPSB0aGlzLnBlZWsoZTEsIGUyLCBlMywgZTQpOw0KICAgIGlmICh0b2tlbikgew0KICAgICAgdGhpcy50b2tlbnMuc2hpZnQoKTsNCiAgICAgIHJldHVybiB0b2tlbjsNCiAgICB9DQogICAgcmV0dXJuIGZhbHNlOw0KICB9LA0KDQogIGNvbnN1bWU6IGZ1bmN0aW9uKGUxKSB7DQogICAgaWYgKHRoaXMudG9rZW5zLmxlbmd0aCA9PT0gMCkgew0KICAgICAgdGhyb3cgJHBhcnNlTWluRXJyKCd1ZW9lJywgJ1VuZXhwZWN0ZWQgZW5kIG9mIGV4cHJlc3Npb246IHswfScsIHRoaXMudGV4dCk7DQogICAgfQ0KDQogICAgdmFyIHRva2VuID0gdGhpcy5leHBlY3QoZTEpOw0KICAgIGlmICghdG9rZW4pIHsNCiAgICAgIHRoaXMudGhyb3dFcnJvcignaXMgdW5leHBlY3RlZCwgZXhwZWN0aW5nIFsnICsgZTEgKyAnXScsIHRoaXMucGVlaygpKTsNCiAgICB9DQogICAgcmV0dXJuIHRva2VuOw0KICB9LA0KDQogIHVuYXJ5Rm46IGZ1bmN0aW9uKG9wLCByaWdodCkgew0KICAgIHZhciBmbiA9IE9QRVJBVE9SU1tvcF07DQogICAgcmV0dXJuIGV4dGVuZChmdW5jdGlvbiAkcGFyc2VVbmFyeUZuKHNlbGYsIGxvY2Fscykgew0KICAgICAgcmV0dXJuIGZuKHNlbGYsIGxvY2FscywgcmlnaHQpOw0KICAgIH0sIHsNCiAgICAgIGNvbnN0YW50OnJpZ2h0LmNvbnN0YW50LA0KICAgICAgaW5wdXRzOiBbcmlnaHRdDQogICAgfSk7DQogIH0sDQoNCiAgYmluYXJ5Rm46IGZ1bmN0aW9uKGxlZnQsIG9wLCByaWdodCwgaXNCcmFuY2hpbmcpIHsNCiAgICB2YXIgZm4gPSBPUEVSQVRPUlNbb3BdOw0KICAgIHJldHVybiBleHRlbmQoZnVuY3Rpb24gJHBhcnNlQmluYXJ5Rm4oc2VsZiwgbG9jYWxzKSB7DQogICAgICByZXR1cm4gZm4oc2VsZiwgbG9jYWxzLCBsZWZ0LCByaWdodCk7DQogICAgfSwgew0KICAgICAgY29uc3RhbnQ6IGxlZnQuY29uc3RhbnQgJiYgcmlnaHQuY29uc3RhbnQsDQogICAgICBpbnB1dHM6ICFpc0JyYW5jaGluZyAmJiBbbGVmdCwgcmlnaHRdDQogICAgfSk7DQogIH0sDQoNCiAgaWRlbnRpZmllcjogZnVuY3Rpb24oKSB7DQogICAgdmFyIGlkID0gdGhpcy5jb25zdW1lKCkudGV4dDsNCg0KICAgIC8vQ29udGludWUgcmVhZGluZyBlYWNoIGAuaWRlbnRpZmllcmAgdW5sZXNzIGl0IGlzIGEgbWV0aG9kIGludm9jYXRpb24NCiAgICB3aGlsZSAodGhpcy5wZWVrKCcuJykgJiYgdGhpcy5wZWVrQWhlYWQoMSkuaWRlbnRpZmllciAmJiAhdGhpcy5wZWVrQWhlYWQoMiwgJygnKSkgew0KICAgICAgaWQgKz0gdGhpcy5jb25zdW1lKCkudGV4dCArIHRoaXMuY29uc3VtZSgpLnRleHQ7DQogICAgfQ0KDQogICAgcmV0dXJuIGdldHRlckZuKGlkLCB0aGlzLm9wdGlvbnMsIHRoaXMudGV4dCk7DQogIH0sDQoNCiAgY29uc3RhbnQ6IGZ1bmN0aW9uKCkgew0KICAgIHZhciB2YWx1ZSA9IHRoaXMuY29uc3VtZSgpLnZhbHVlOw0KDQogICAgcmV0dXJuIGV4dGVuZChmdW5jdGlvbiAkcGFyc2VDb25zdGFudCgpIHsNCiAgICAgIHJldHVybiB2YWx1ZTsNCiAgICB9LCB7DQogICAgICBjb25zdGFudDogdHJ1ZSwNCiAgICAgIGxpdGVyYWw6IHRydWUNCiAgICB9KTsNCiAgfSwNCg0KICBzdGF0ZW1lbnRzOiBmdW5jdGlvbigpIHsNCiAgICB2YXIgc3RhdGVtZW50cyA9IFtdOw0KICAgIHdoaWxlICh0cnVlKSB7DQogICAgICBpZiAodGhpcy50b2tlbnMubGVuZ3RoID4gMCAmJiAhdGhpcy5wZWVrKCd9JywgJyknLCAnOycsICddJykpDQogICAgICAgIHN0YXRlbWVudHMucHVzaCh0aGlzLmZpbHRlckNoYWluKCkpOw0KICAgICAgaWYgKCF0aGlzLmV4cGVjdCgnOycpKSB7DQogICAgICAgIC8vIG9wdGltaXplIGZvciB0aGUgY29tbW9uIGNhc2Ugd2hlcmUgdGhlcmUgaXMgb25seSBvbmUgc3RhdGVtZW50Lg0KICAgICAgICAvLyBUT0RPKHNpemUpOiBtYXliZSB3ZSBzaG91bGQgbm90IHN1cHBvcnQgbXVsdGlwbGUgc3RhdGVtZW50cz8NCiAgICAgICAgcmV0dXJuIChzdGF0ZW1lbnRzLmxlbmd0aCA9PT0gMSkNCiAgICAgICAgICAgID8gc3RhdGVtZW50c1swXQ0KICAgICAgICAgICAgOiBmdW5jdGlvbiAkcGFyc2VTdGF0ZW1lbnRzKHNlbGYsIGxvY2Fscykgew0KICAgICAgICAgICAgICAgIHZhciB2YWx1ZTsNCiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBzdGF0ZW1lbnRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsNCiAgICAgICAgICAgICAgICAgIHZhbHVlID0gc3RhdGVtZW50c1tpXShzZWxmLCBsb2NhbHMpOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7DQogICAgICAgICAgICAgIH07DQogICAgICB9DQogICAgfQ0KICB9LA0KDQogIGZpbHRlckNoYWluOiBmdW5jdGlvbigpIHsNCiAgICB2YXIgbGVmdCA9IHRoaXMuZXhwcmVzc2lvbigpOw0KICAgIHZhciB0b2tlbjsNCiAgICB3aGlsZSAoKHRva2VuID0gdGhpcy5leHBlY3QoJ3wnKSkpIHsNCiAgICAgIGxlZnQgPSB0aGlzLmZpbHRlcihsZWZ0KTsNCiAgICB9DQogICAgcmV0dXJuIGxlZnQ7DQogIH0sDQoNCiAgZmlsdGVyOiBmdW5jdGlvbihpbnB1dEZuKSB7DQogICAgdmFyIGZuID0gdGhpcy4kZmlsdGVyKHRoaXMuY29uc3VtZSgpLnRleHQpOw0KICAgIHZhciBhcmdzRm47DQogICAgdmFyIGFyZ3M7DQoNCiAgICBpZiAodGhpcy5wZWVrKCc6JykpIHsNCiAgICAgIGFyZ3NGbiA9IFtdOw0KICAgICAgYXJncyA9IFtdOyAvLyB3ZSBjYW4gc2FmZWx5IHJldXNlIHRoZSBhcnJheQ0KICAgICAgd2hpbGUgKHRoaXMuZXhwZWN0KCc6JykpIHsNCiAgICAgICAgYXJnc0ZuLnB1c2godGhpcy5leHByZXNzaW9uKCkpOw0KICAgICAgfQ0KICAgIH0NCg0KICAgIHZhciBpbnB1dHMgPSBbaW5wdXRGbl0uY29uY2F0KGFyZ3NGbiB8fCBbXSk7DQoNCiAgICByZXR1cm4gZXh0ZW5kKGZ1bmN0aW9uICRwYXJzZUZpbHRlcihzZWxmLCBsb2NhbHMpIHsNCiAgICAgIHZhciBpbnB1dCA9IGlucHV0Rm4oc2VsZiwgbG9jYWxzKTsNCiAgICAgIGlmIChhcmdzKSB7DQogICAgICAgIGFyZ3NbMF0gPSBpbnB1dDsNCg0KICAgICAgICB2YXIgaSA9IGFyZ3NGbi5sZW5ndGg7DQogICAgICAgIHdoaWxlIChpLS0pIHsNCiAgICAgICAgICBhcmdzW2kgKyAxXSA9IGFyZ3NGbltpXShzZWxmLCBsb2NhbHMpOw0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuIGZuLmFwcGx5KHVuZGVmaW5lZCwgYXJncyk7DQogICAgICB9DQoNCiAgICAgIHJldHVybiBmbihpbnB1dCk7DQogICAgfSwgew0KICAgICAgY29uc3RhbnQ6ICFmbi4kc3RhdGVmdWwgJiYgaW5wdXRzLmV2ZXJ5KGlzQ29uc3RhbnQpLA0KICAgICAgaW5wdXRzOiAhZm4uJHN0YXRlZnVsICYmIGlucHV0cw0KICAgIH0pOw0KICB9LA0KDQogIGV4cHJlc3Npb246IGZ1bmN0aW9uKCkgew0KICAgIHJldHVybiB0aGlzLmFzc2lnbm1lbnQoKTsNCiAgfSwNCg0KICBhc3NpZ25tZW50OiBmdW5jdGlvbigpIHsNCiAgICB2YXIgbGVmdCA9IHRoaXMudGVybmFyeSgpOw0KICAgIHZhciByaWdodDsNCiAgICB2YXIgdG9rZW47DQogICAgaWYgKCh0b2tlbiA9IHRoaXMuZXhwZWN0KCc9JykpKSB7DQogICAgICBpZiAoIWxlZnQuYXNzaWduKSB7DQogICAgICAgIHRoaXMudGhyb3dFcnJvcignaW1wbGllcyBhc3NpZ25tZW50IGJ1dCBbJyArDQogICAgICAgICAgICB0aGlzLnRleHQuc3Vic3RyaW5nKDAsIHRva2VuLmluZGV4KSArICddIGNhbiBub3QgYmUgYXNzaWduZWQgdG8nLCB0b2tlbik7DQogICAgICB9DQogICAgICByaWdodCA9IHRoaXMudGVybmFyeSgpOw0KICAgICAgcmV0dXJuIGV4dGVuZChmdW5jdGlvbiAkcGFyc2VBc3NpZ25tZW50KHNjb3BlLCBsb2NhbHMpIHsNCiAgICAgICAgcmV0dXJuIGxlZnQuYXNzaWduKHNjb3BlLCByaWdodChzY29wZSwgbG9jYWxzKSwgbG9jYWxzKTsNCiAgICAgIH0sIHsNCiAgICAgICAgaW5wdXRzOiBbbGVmdCwgcmlnaHRdDQogICAgICB9KTsNCiAgICB9DQogICAgcmV0dXJuIGxlZnQ7DQogIH0sDQoNCiAgdGVybmFyeTogZnVuY3Rpb24oKSB7DQogICAgdmFyIGxlZnQgPSB0aGlzLmxvZ2ljYWxPUigpOw0KICAgIHZhciBtaWRkbGU7DQogICAgdmFyIHRva2VuOw0KICAgIGlmICgodG9rZW4gPSB0aGlzLmV4cGVjdCgnPycpKSkgew0KICAgICAgbWlkZGxlID0gdGhpcy5hc3NpZ25tZW50KCk7DQogICAgICBpZiAodGhpcy5jb25zdW1lKCc6JykpIHsNCiAgICAgICAgdmFyIHJpZ2h0ID0gdGhpcy5hc3NpZ25tZW50KCk7DQoNCiAgICAgICAgcmV0dXJuIGV4dGVuZChmdW5jdGlvbiAkcGFyc2VUZXJuYXJ5KHNlbGYsIGxvY2Fscykgew0KICAgICAgICAgIHJldHVybiBsZWZ0KHNlbGYsIGxvY2FscykgPyBtaWRkbGUoc2VsZiwgbG9jYWxzKSA6IHJpZ2h0KHNlbGYsIGxvY2Fscyk7DQogICAgICAgIH0sIHsNCiAgICAgICAgICBjb25zdGFudDogbGVmdC5jb25zdGFudCAmJiBtaWRkbGUuY29uc3RhbnQgJiYgcmlnaHQuY29uc3RhbnQNCiAgICAgICAgfSk7DQogICAgICB9DQogICAgfQ0KDQogICAgcmV0dXJuIGxlZnQ7DQogIH0sDQoNCiAgbG9naWNhbE9SOiBmdW5jdGlvbigpIHsNCiAgICB2YXIgbGVmdCA9IHRoaXMubG9naWNhbEFORCgpOw0KICAgIHZhciB0b2tlbjsNCiAgICB3aGlsZSAoKHRva2VuID0gdGhpcy5leHBlY3QoJ3x8JykpKSB7DQogICAgICBsZWZ0ID0gdGhpcy5iaW5hcnlGbihsZWZ0LCB0b2tlbi50ZXh0LCB0aGlzLmxvZ2ljYWxBTkQoKSwgdHJ1ZSk7DQogICAgfQ0KICAgIHJldHVybiBsZWZ0Ow0KICB9LA0KDQogIGxvZ2ljYWxBTkQ6IGZ1bmN0aW9uKCkgew0KICAgIHZhciBsZWZ0ID0gdGhpcy5lcXVhbGl0eSgpOw0KICAgIHZhciB0b2tlbjsNCiAgICB3aGlsZSAoKHRva2VuID0gdGhpcy5leHBlY3QoJyYmJykpKSB7DQogICAgICBsZWZ0ID0gdGhpcy5iaW5hcnlGbihsZWZ0LCB0b2tlbi50ZXh0LCB0aGlzLmVxdWFsaXR5KCksIHRydWUpOw0KICAgIH0NCiAgICByZXR1cm4gbGVmdDsNCiAgfSwNCg0KICBlcXVhbGl0eTogZnVuY3Rpb24oKSB7DQogICAgdmFyIGxlZnQgPSB0aGlzLnJlbGF0aW9uYWwoKTsNCiAgICB2YXIgdG9rZW47DQogICAgd2hpbGUgKCh0b2tlbiA9IHRoaXMuZXhwZWN0KCc9PScsJyE9JywnPT09JywnIT09JykpKSB7DQogICAgICBsZWZ0ID0gdGhpcy5iaW5hcnlGbihsZWZ0LCB0b2tlbi50ZXh0LCB0aGlzLnJlbGF0aW9uYWwoKSk7DQogICAgfQ0KICAgIHJldHVybiBsZWZ0Ow0KICB9LA0KDQogIHJlbGF0aW9uYWw6IGZ1bmN0aW9uKCkgew0KICAgIHZhciBsZWZ0ID0gdGhpcy5hZGRpdGl2ZSgpOw0KICAgIHZhciB0b2tlbjsNCiAgICB3aGlsZSAoKHRva2VuID0gdGhpcy5leHBlY3QoJzwnLCAnPicsICc8PScsICc+PScpKSkgew0KICAgICAgbGVmdCA9IHRoaXMuYmluYXJ5Rm4obGVmdCwgdG9rZW4udGV4dCwgdGhpcy5hZGRpdGl2ZSgpKTsNCiAgICB9DQogICAgcmV0dXJuIGxlZnQ7DQogIH0sDQoNCiAgYWRkaXRpdmU6IGZ1bmN0aW9uKCkgew0KICAgIHZhciBsZWZ0ID0gdGhpcy5tdWx0aXBsaWNhdGl2ZSgpOw0KICAgIHZhciB0b2tlbjsNCiAgICB3aGlsZSAoKHRva2VuID0gdGhpcy5leHBlY3QoJysnLCctJykpKSB7DQogICAgICBsZWZ0ID0gdGhpcy5iaW5hcnlGbihsZWZ0LCB0b2tlbi50ZXh0LCB0aGlzLm11bHRpcGxpY2F0aXZlKCkpOw0KICAgIH0NCiAgICByZXR1cm4gbGVmdDsNCiAgfSwNCg0KICBtdWx0aXBsaWNhdGl2ZTogZnVuY3Rpb24oKSB7DQogICAgdmFyIGxlZnQgPSB0aGlzLnVuYXJ5KCk7DQogICAgdmFyIHRva2VuOw0KICAgIHdoaWxlICgodG9rZW4gPSB0aGlzLmV4cGVjdCgnKicsJy8nLCclJykpKSB7DQogICAgICBsZWZ0ID0gdGhpcy5iaW5hcnlGbihsZWZ0LCB0b2tlbi50ZXh0LCB0aGlzLnVuYXJ5KCkpOw0KICAgIH0NCiAgICByZXR1cm4gbGVmdDsNCiAgfSwNCg0KICB1bmFyeTogZnVuY3Rpb24oKSB7DQogICAgdmFyIHRva2VuOw0KICAgIGlmICh0aGlzLmV4cGVjdCgnKycpKSB7DQogICAgICByZXR1cm4gdGhpcy5wcmltYXJ5KCk7DQogICAgfSBlbHNlIGlmICgodG9rZW4gPSB0aGlzLmV4cGVjdCgnLScpKSkgew0KICAgICAgcmV0dXJuIHRoaXMuYmluYXJ5Rm4oUGFyc2VyLlpFUk8sIHRva2VuLnRleHQsIHRoaXMudW5hcnkoKSk7DQogICAgfSBlbHNlIGlmICgodG9rZW4gPSB0aGlzLmV4cGVjdCgnIScpKSkgew0KICAgICAgcmV0dXJuIHRoaXMudW5hcnlGbih0b2tlbi50ZXh0LCB0aGlzLnVuYXJ5KCkpOw0KICAgIH0gZWxzZSB7DQogICAgICByZXR1cm4gdGhpcy5wcmltYXJ5KCk7DQogICAgfQ0KICB9LA0KDQogIGZpZWxkQWNjZXNzOiBmdW5jdGlvbihvYmplY3QpIHsNCiAgICB2YXIgZ2V0dGVyID0gdGhpcy5pZGVudGlmaWVyKCk7DQoNCiAgICByZXR1cm4gZXh0ZW5kKGZ1bmN0aW9uICRwYXJzZUZpZWxkQWNjZXNzKHNjb3BlLCBsb2NhbHMsIHNlbGYpIHsNCiAgICAgIHZhciBvID0gc2VsZiB8fCBvYmplY3Qoc2NvcGUsIGxvY2Fscyk7DQogICAgICByZXR1cm4gKG8gPT0gbnVsbCkgPyB1bmRlZmluZWQgOiBnZXR0ZXIobyk7DQogICAgfSwgew0KICAgICAgYXNzaWduOiBmdW5jdGlvbihzY29wZSwgdmFsdWUsIGxvY2Fscykgew0KICAgICAgICB2YXIgbyA9IG9iamVjdChzY29wZSwgbG9jYWxzKTsNCiAgICAgICAgaWYgKCFvKSBvYmplY3QuYXNzaWduKHNjb3BlLCBvID0ge30pOw0KICAgICAgICByZXR1cm4gZ2V0dGVyLmFzc2lnbihvLCB2YWx1ZSk7DQogICAgICB9DQogICAgfSk7DQogIH0sDQoNCiAgb2JqZWN0SW5kZXg6IGZ1bmN0aW9uKG9iaikgew0KICAgIHZhciBleHByZXNzaW9uID0gdGhpcy50ZXh0Ow0KDQogICAgdmFyIGluZGV4Rm4gPSB0aGlzLmV4cHJlc3Npb24oKTsNCiAgICB0aGlzLmNvbnN1bWUoJ10nKTsNCg0KICAgIHJldHVybiBleHRlbmQoZnVuY3Rpb24gJHBhcnNlT2JqZWN0SW5kZXgoc2VsZiwgbG9jYWxzKSB7DQogICAgICB2YXIgbyA9IG9iaihzZWxmLCBsb2NhbHMpLA0KICAgICAgICAgIGkgPSBpbmRleEZuKHNlbGYsIGxvY2FscyksDQogICAgICAgICAgdjsNCg0KICAgICAgZW5zdXJlU2FmZU1lbWJlck5hbWUoaSwgZXhwcmVzc2lvbik7DQogICAgICBpZiAoIW8pIHJldHVybiB1bmRlZmluZWQ7DQogICAgICB2ID0gZW5zdXJlU2FmZU9iamVjdChvW2ldLCBleHByZXNzaW9uKTsNCiAgICAgIHJldHVybiB2Ow0KICAgIH0sIHsNCiAgICAgIGFzc2lnbjogZnVuY3Rpb24oc2VsZiwgdmFsdWUsIGxvY2Fscykgew0KICAgICAgICB2YXIga2V5ID0gZW5zdXJlU2FmZU1lbWJlck5hbWUoaW5kZXhGbihzZWxmLCBsb2NhbHMpLCBleHByZXNzaW9uKTsNCiAgICAgICAgLy8gcHJldmVudCBvdmVyd3JpdGluZyBvZiBGdW5jdGlvbi5jb25zdHJ1Y3RvciB3aGljaCB3b3VsZCBicmVhayBlbnN1cmVTYWZlT2JqZWN0IGNoZWNrDQogICAgICAgIHZhciBvID0gZW5zdXJlU2FmZU9iamVjdChvYmooc2VsZiwgbG9jYWxzKSwgZXhwcmVzc2lvbik7DQogICAgICAgIGlmICghbykgb2JqLmFzc2lnbihzZWxmLCBvID0ge30pOw0KICAgICAgICByZXR1cm4gb1trZXldID0gdmFsdWU7DQogICAgICB9DQogICAgfSk7DQogIH0sDQoNCiAgZnVuY3Rpb25DYWxsOiBmdW5jdGlvbihmbkdldHRlciwgY29udGV4dEdldHRlcikgew0KICAgIHZhciBhcmdzRm4gPSBbXTsNCiAgICBpZiAodGhpcy5wZWVrVG9rZW4oKS50ZXh0ICE9PSAnKScpIHsNCiAgICAgIGRvIHsNCiAgICAgICAgYXJnc0ZuLnB1c2godGhpcy5leHByZXNzaW9uKCkpOw0KICAgICAgfSB3aGlsZSAodGhpcy5leHBlY3QoJywnKSk7DQogICAgfQ0KICAgIHRoaXMuY29uc3VtZSgnKScpOw0KDQogICAgdmFyIGV4cHJlc3Npb25UZXh0ID0gdGhpcy50ZXh0Ow0KICAgIC8vIHdlIGNhbiBzYWZlbHkgcmV1c2UgdGhlIGFycmF5IGFjcm9zcyBpbnZvY2F0aW9ucw0KICAgIHZhciBhcmdzID0gYXJnc0ZuLmxlbmd0aCA/IFtdIDogbnVsbDsNCg0KICAgIHJldHVybiBmdW5jdGlvbiAkcGFyc2VGdW5jdGlvbkNhbGwoc2NvcGUsIGxvY2Fscykgew0KICAgICAgdmFyIGNvbnRleHQgPSBjb250ZXh0R2V0dGVyID8gY29udGV4dEdldHRlcihzY29wZSwgbG9jYWxzKSA6IGlzRGVmaW5lZChjb250ZXh0R2V0dGVyKSA/IHVuZGVmaW5lZCA6IHNjb3BlOw0KICAgICAgdmFyIGZuID0gZm5HZXR0ZXIoc2NvcGUsIGxvY2FscywgY29udGV4dCkgfHwgbm9vcDsNCg0KICAgICAgaWYgKGFyZ3MpIHsNCiAgICAgICAgdmFyIGkgPSBhcmdzRm4ubGVuZ3RoOw0KICAgICAgICB3aGlsZSAoaS0tKSB7DQogICAgICAgICAgYXJnc1tpXSA9IGVuc3VyZVNhZmVPYmplY3QoYXJnc0ZuW2ldKHNjb3BlLCBsb2NhbHMpLCBleHByZXNzaW9uVGV4dCk7DQogICAgICAgIH0NCiAgICAgIH0NCg0KICAgICAgZW5zdXJlU2FmZU9iamVjdChjb250ZXh0LCBleHByZXNzaW9uVGV4dCk7DQogICAgICBlbnN1cmVTYWZlRnVuY3Rpb24oZm4sIGV4cHJlc3Npb25UZXh0KTsNCg0KICAgICAgLy8gSUUgZG9lc24ndCBoYXZlIGFwcGx5IGZvciBzb21lIG5hdGl2ZSBmdW5jdGlvbnMNCiAgICAgIHZhciB2ID0gZm4uYXBwbHkNCiAgICAgICAgICAgID8gZm4uYXBwbHkoY29udGV4dCwgYXJncykNCiAgICAgICAgICAgIDogZm4oYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSk7DQoNCiAgICAgIHJldHVybiBlbnN1cmVTYWZlT2JqZWN0KHYsIGV4cHJlc3Npb25UZXh0KTsNCiAgICAgIH07DQogIH0sDQoNCiAgLy8gVGhpcyBpcyB1c2VkIHdpdGgganNvbiBhcnJheSBkZWNsYXJhdGlvbg0KICBhcnJheURlY2xhcmF0aW9uOiBmdW5jdGlvbigpIHsNCiAgICB2YXIgZWxlbWVudEZucyA9IFtdOw0KICAgIGlmICh0aGlzLnBlZWtUb2tlbigpLnRleHQgIT09ICddJykgew0KICAgICAgZG8gew0KICAgICAgICBpZiAodGhpcy5wZWVrKCddJykpIHsNCiAgICAgICAgICAvLyBTdXBwb3J0IHRyYWlsaW5nIGNvbW1hcyBwZXIgRVM1LjEuDQogICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCiAgICAgICAgZWxlbWVudEZucy5wdXNoKHRoaXMuZXhwcmVzc2lvbigpKTsNCiAgICAgIH0gd2hpbGUgKHRoaXMuZXhwZWN0KCcsJykpOw0KICAgIH0NCiAgICB0aGlzLmNvbnN1bWUoJ10nKTsNCg0KICAgIHJldHVybiBleHRlbmQoZnVuY3Rpb24gJHBhcnNlQXJyYXlMaXRlcmFsKHNlbGYsIGxvY2Fscykgew0KICAgICAgdmFyIGFycmF5ID0gW107DQogICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbGVtZW50Rm5zLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsNCiAgICAgICAgYXJyYXkucHVzaChlbGVtZW50Rm5zW2ldKHNlbGYsIGxvY2FscykpOw0KICAgICAgfQ0KICAgICAgcmV0dXJuIGFycmF5Ow0KICAgIH0sIHsNCiAgICAgIGxpdGVyYWw6IHRydWUsDQogICAgICBjb25zdGFudDogZWxlbWVudEZucy5ldmVyeShpc0NvbnN0YW50KSwNCiAgICAgIGlucHV0czogZWxlbWVudEZucw0KICAgIH0pOw0KICB9LA0KDQogIG9iamVjdDogZnVuY3Rpb24oKSB7DQogICAgdmFyIGtleXMgPSBbXSwgdmFsdWVGbnMgPSBbXTsNCiAgICBpZiAodGhpcy5wZWVrVG9rZW4oKS50ZXh0ICE9PSAnfScpIHsNCiAgICAgIGRvIHsNCiAgICAgICAgaWYgKHRoaXMucGVlaygnfScpKSB7DQogICAgICAgICAgLy8gU3VwcG9ydCB0cmFpbGluZyBjb21tYXMgcGVyIEVTNS4xLg0KICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQogICAgICAgIHZhciB0b2tlbiA9IHRoaXMuY29uc3VtZSgpOw0KICAgICAgICBpZiAodG9rZW4uY29uc3RhbnQpIHsNCiAgICAgICAgICBrZXlzLnB1c2godG9rZW4udmFsdWUpOw0KICAgICAgICB9IGVsc2UgaWYgKHRva2VuLmlkZW50aWZpZXIpIHsNCiAgICAgICAgICBrZXlzLnB1c2godG9rZW4udGV4dCk7DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgdGhpcy50aHJvd0Vycm9yKCJpbnZhbGlkIGtleSIsIHRva2VuKTsNCiAgICAgICAgfQ0KICAgICAgICB0aGlzLmNvbnN1bWUoJzonKTsNCiAgICAgICAgdmFsdWVGbnMucHVzaCh0aGlzLmV4cHJlc3Npb24oKSk7DQogICAgICB9IHdoaWxlICh0aGlzLmV4cGVjdCgnLCcpKTsNCiAgICB9DQogICAgdGhpcy5jb25zdW1lKCd9Jyk7DQoNCiAgICByZXR1cm4gZXh0ZW5kKGZ1bmN0aW9uICRwYXJzZU9iamVjdExpdGVyYWwoc2VsZiwgbG9jYWxzKSB7DQogICAgICB2YXIgb2JqZWN0ID0ge307DQogICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSB2YWx1ZUZucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7DQogICAgICAgIG9iamVjdFtrZXlzW2ldXSA9IHZhbHVlRm5zW2ldKHNlbGYsIGxvY2Fscyk7DQogICAgICB9DQogICAgICByZXR1cm4gb2JqZWN0Ow0KICAgIH0sIHsNCiAgICAgIGxpdGVyYWw6IHRydWUsDQogICAgICBjb25zdGFudDogdmFsdWVGbnMuZXZlcnkoaXNDb25zdGFudCksDQogICAgICBpbnB1dHM6IHZhbHVlRm5zDQogICAgfSk7DQogIH0NCn07DQoNCg0KLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCi8vIFBhcnNlciBoZWxwZXIgZnVuY3Rpb25zDQovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KDQpmdW5jdGlvbiBzZXR0ZXIob2JqLCBwYXRoLCBzZXRWYWx1ZSwgZnVsbEV4cCkgew0KICBlbnN1cmVTYWZlT2JqZWN0KG9iaiwgZnVsbEV4cCk7DQoNCiAgdmFyIGVsZW1lbnQgPSBwYXRoLnNwbGl0KCcuJyksIGtleTsNCiAgZm9yICh2YXIgaSA9IDA7IGVsZW1lbnQubGVuZ3RoID4gMTsgaSsrKSB7DQogICAga2V5ID0gZW5zdXJlU2FmZU1lbWJlck5hbWUoZWxlbWVudC5zaGlmdCgpLCBmdWxsRXhwKTsNCiAgICB2YXIgcHJvcGVydHlPYmogPSBlbnN1cmVTYWZlT2JqZWN0KG9ialtrZXldLCBmdWxsRXhwKTsNCiAgICBpZiAoIXByb3BlcnR5T2JqKSB7DQogICAgICBwcm9wZXJ0eU9iaiA9IHt9Ow0KICAgICAgb2JqW2tleV0gPSBwcm9wZXJ0eU9iajsNCiAgICB9DQogICAgb2JqID0gcHJvcGVydHlPYmo7DQogIH0NCiAga2V5ID0gZW5zdXJlU2FmZU1lbWJlck5hbWUoZWxlbWVudC5zaGlmdCgpLCBmdWxsRXhwKTsNCiAgZW5zdXJlU2FmZU9iamVjdChvYmpba2V5XSwgZnVsbEV4cCk7DQogIG9ialtrZXldID0gc2V0VmFsdWU7DQogIHJldHVybiBzZXRWYWx1ZTsNCn0NCg0KdmFyIGdldHRlckZuQ2FjaGVEZWZhdWx0ID0gY3JlYXRlTWFwKCk7DQp2YXIgZ2V0dGVyRm5DYWNoZUV4cGVuc2l2ZSA9IGNyZWF0ZU1hcCgpOw0KDQpmdW5jdGlvbiBpc1Bvc3NpYmx5RGFuZ2Vyb3VzTWVtYmVyTmFtZShuYW1lKSB7DQogIHJldHVybiBuYW1lID09ICdjb25zdHJ1Y3Rvcic7DQp9DQoNCi8qKg0KICogSW1wbGVtZW50YXRpb24gb2YgdGhlICJCbGFjayBIb2xlIiB2YXJpYW50IGZyb206DQogKiAtIGh0dHA6Ly9qc3BlcmYuY29tL2FuZ3VsYXJqcy1wYXJzZS1nZXR0ZXIvNA0KICogLSBodHRwOi8vanNwZXJmLmNvbS9wYXRoLWV2YWx1YXRpb24tc2ltcGxpZmllZC83DQogKi8NCmZ1bmN0aW9uIGNzcFNhZmVHZXR0ZXJGbihrZXkwLCBrZXkxLCBrZXkyLCBrZXkzLCBrZXk0LCBmdWxsRXhwLCBleHBlbnNpdmVDaGVja3MpIHsNCiAgZW5zdXJlU2FmZU1lbWJlck5hbWUoa2V5MCwgZnVsbEV4cCk7DQogIGVuc3VyZVNhZmVNZW1iZXJOYW1lKGtleTEsIGZ1bGxFeHApOw0KICBlbnN1cmVTYWZlTWVtYmVyTmFtZShrZXkyLCBmdWxsRXhwKTsNCiAgZW5zdXJlU2FmZU1lbWJlck5hbWUoa2V5MywgZnVsbEV4cCk7DQogIGVuc3VyZVNhZmVNZW1iZXJOYW1lKGtleTQsIGZ1bGxFeHApOw0KICB2YXIgZXNvID0gZnVuY3Rpb24obykgew0KICAgIHJldHVybiBlbnN1cmVTYWZlT2JqZWN0KG8sIGZ1bGxFeHApOw0KICB9Ow0KICB2YXIgZXNvMCA9IChleHBlbnNpdmVDaGVja3MgfHwgaXNQb3NzaWJseURhbmdlcm91c01lbWJlck5hbWUoa2V5MCkpID8gZXNvIDogaWRlbnRpdHk7DQogIHZhciBlc28xID0gKGV4cGVuc2l2ZUNoZWNrcyB8fCBpc1Bvc3NpYmx5RGFuZ2Vyb3VzTWVtYmVyTmFtZShrZXkxKSkgPyBlc28gOiBpZGVudGl0eTsNCiAgdmFyIGVzbzIgPSAoZXhwZW5zaXZlQ2hlY2tzIHx8IGlzUG9zc2libHlEYW5nZXJvdXNNZW1iZXJOYW1lKGtleTIpKSA/IGVzbyA6IGlkZW50aXR5Ow0KICB2YXIgZXNvMyA9IChleHBlbnNpdmVDaGVja3MgfHwgaXNQb3NzaWJseURhbmdlcm91c01lbWJlck5hbWUoa2V5MykpID8gZXNvIDogaWRlbnRpdHk7DQogIHZhciBlc280ID0gKGV4cGVuc2l2ZUNoZWNrcyB8fCBpc1Bvc3NpYmx5RGFuZ2Vyb3VzTWVtYmVyTmFtZShrZXk0KSkgPyBlc28gOiBpZGVudGl0eTsNCg0KICByZXR1cm4gZnVuY3Rpb24gY3NwU2FmZUdldHRlcihzY29wZSwgbG9jYWxzKSB7DQogICAgdmFyIHBhdGhWYWwgPSAobG9jYWxzICYmIGxvY2Fscy5oYXNPd25Qcm9wZXJ0eShrZXkwKSkgPyBsb2NhbHMgOiBzY29wZTsNCg0KICAgIGlmIChwYXRoVmFsID09IG51bGwpIHJldHVybiBwYXRoVmFsOw0KICAgIHBhdGhWYWwgPSBlc28wKHBhdGhWYWxba2V5MF0pOw0KDQogICAgaWYgKCFrZXkxKSByZXR1cm4gcGF0aFZhbDsNCiAgICBpZiAocGF0aFZhbCA9PSBudWxsKSByZXR1cm4gdW5kZWZpbmVkOw0KICAgIHBhdGhWYWwgPSBlc28xKHBhdGhWYWxba2V5MV0pOw0KDQogICAgaWYgKCFrZXkyKSByZXR1cm4gcGF0aFZhbDsNCiAgICBpZiAocGF0aFZhbCA9PSBudWxsKSByZXR1cm4gdW5kZWZpbmVkOw0KICAgIHBhdGhWYWwgPSBlc28yKHBhdGhWYWxba2V5Ml0pOw0KDQogICAgaWYgKCFrZXkzKSByZXR1cm4gcGF0aFZhbDsNCiAgICBpZiAocGF0aFZhbCA9PSBudWxsKSByZXR1cm4gdW5kZWZpbmVkOw0KICAgIHBhdGhWYWwgPSBlc28zKHBhdGhWYWxba2V5M10pOw0KDQogICAgaWYgKCFrZXk0KSByZXR1cm4gcGF0aFZhbDsNCiAgICBpZiAocGF0aFZhbCA9PSBudWxsKSByZXR1cm4gdW5kZWZpbmVkOw0KICAgIHBhdGhWYWwgPSBlc280KHBhdGhWYWxba2V5NF0pOw0KDQogICAgcmV0dXJuIHBhdGhWYWw7DQogIH07DQp9DQoNCmZ1bmN0aW9uIGdldHRlckZuV2l0aEVuc3VyZVNhZmVPYmplY3QoZm4sIGZ1bGxFeHByZXNzaW9uKSB7DQogIHJldHVybiBmdW5jdGlvbihzLCBsKSB7DQogICAgcmV0dXJuIGZuKHMsIGwsIGVuc3VyZVNhZmVPYmplY3QsIGZ1bGxFeHByZXNzaW9uKTsNCiAgfTsNCn0NCg0KZnVuY3Rpb24gZ2V0dGVyRm4ocGF0aCwgb3B0aW9ucywgZnVsbEV4cCkgew0KICB2YXIgZXhwZW5zaXZlQ2hlY2tzID0gb3B0aW9ucy5leHBlbnNpdmVDaGVja3M7DQogIHZhciBnZXR0ZXJGbkNhY2hlID0gKGV4cGVuc2l2ZUNoZWNrcyA/IGdldHRlckZuQ2FjaGVFeHBlbnNpdmUgOiBnZXR0ZXJGbkNhY2hlRGVmYXVsdCk7DQogIHZhciBmbiA9IGdldHRlckZuQ2FjaGVbcGF0aF07DQogIGlmIChmbikgcmV0dXJuIGZuOw0KDQoNCiAgdmFyIHBhdGhLZXlzID0gcGF0aC5zcGxpdCgnLicpLA0KICAgICAgcGF0aEtleXNMZW5ndGggPSBwYXRoS2V5cy5sZW5ndGg7DQoNCiAgLy8gaHR0cDovL2pzcGVyZi5jb20vYW5ndWxhcmpzLXBhcnNlLWdldHRlci82DQogIGlmIChvcHRpb25zLmNzcCkgew0KICAgIGlmIChwYXRoS2V5c0xlbmd0aCA8IDYpIHsNCiAgICAgIGZuID0gY3NwU2FmZUdldHRlckZuKHBhdGhLZXlzWzBdLCBwYXRoS2V5c1sxXSwgcGF0aEtleXNbMl0sIHBhdGhLZXlzWzNdLCBwYXRoS2V5c1s0XSwgZnVsbEV4cCwgZXhwZW5zaXZlQ2hlY2tzKTsNCiAgICB9IGVsc2Ugew0KICAgICAgZm4gPSBmdW5jdGlvbiBjc3BTYWZlR2V0dGVyKHNjb3BlLCBsb2NhbHMpIHsNCiAgICAgICAgdmFyIGkgPSAwLCB2YWw7DQogICAgICAgIGRvIHsNCiAgICAgICAgICB2YWwgPSBjc3BTYWZlR2V0dGVyRm4ocGF0aEtleXNbaSsrXSwgcGF0aEtleXNbaSsrXSwgcGF0aEtleXNbaSsrXSwgcGF0aEtleXNbaSsrXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aEtleXNbaSsrXSwgZnVsbEV4cCwgZXhwZW5zaXZlQ2hlY2tzKShzY29wZSwgbG9jYWxzKTsNCg0KICAgICAgICAgIGxvY2FscyA9IHVuZGVmaW5lZDsgLy8gY2xlYXIgYWZ0ZXIgZmlyc3QgaXRlcmF0aW9uDQogICAgICAgICAgc2NvcGUgPSB2YWw7DQogICAgICAgIH0gd2hpbGUgKGkgPCBwYXRoS2V5c0xlbmd0aCk7DQogICAgICAgIHJldHVybiB2YWw7DQogICAgICB9Ow0KICAgIH0NCiAgfSBlbHNlIHsNCiAgICB2YXIgY29kZSA9ICcnOw0KICAgIGlmIChleHBlbnNpdmVDaGVja3MpIHsNCiAgICAgIGNvZGUgKz0gJ3MgPSBlc28ocywgZmUpO1xubCA9IGVzbyhsLCBmZSk7XG4nOw0KICAgIH0NCiAgICB2YXIgbmVlZHNFbnN1cmVTYWZlT2JqZWN0ID0gZXhwZW5zaXZlQ2hlY2tzOw0KICAgIGZvckVhY2gocGF0aEtleXMsIGZ1bmN0aW9uKGtleSwgaW5kZXgpIHsNCiAgICAgIGVuc3VyZVNhZmVNZW1iZXJOYW1lKGtleSwgZnVsbEV4cCk7DQogICAgICB2YXIgbG9va3VwSnMgPSAoaW5kZXgNCiAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSBzaW1wbHkgZGVyZWZlcmVuY2UgJ3MnIG9uIGFueSAuZG90IG5vdGF0aW9uDQogICAgICAgICAgICAgICAgICAgICAgPyAncycNCiAgICAgICAgICAgICAgICAgICAgICAvLyBidXQgaWYgd2UgYXJlIGZpcnN0IHRoZW4gd2UgY2hlY2sgbG9jYWxzIGZpcnN0LCBhbmQgaWYgc28gcmVhZCBpdCBmaXJzdA0KICAgICAgICAgICAgICAgICAgICAgIDogJygobCYmbC5oYXNPd25Qcm9wZXJ0eSgiJyArIGtleSArICciKSk/bDpzKScpICsgJy4nICsga2V5Ow0KICAgICAgaWYgKGV4cGVuc2l2ZUNoZWNrcyB8fCBpc1Bvc3NpYmx5RGFuZ2Vyb3VzTWVtYmVyTmFtZShrZXkpKSB7DQogICAgICAgIGxvb2t1cEpzID0gJ2VzbygnICsgbG9va3VwSnMgKyAnLCBmZSknOw0KICAgICAgICBuZWVkc0Vuc3VyZVNhZmVPYmplY3QgPSB0cnVlOw0KICAgICAgfQ0KICAgICAgY29kZSArPSAnaWYocyA9PSBudWxsKSByZXR1cm4gdW5kZWZpbmVkO1xuJyArDQogICAgICAgICAgICAgICdzPScgKyBsb29rdXBKcyArICc7XG4nOw0KICAgIH0pOw0KICAgIGNvZGUgKz0gJ3JldHVybiBzOyc7DQoNCiAgICAvKiBqc2hpbnQgLVcwNTQgKi8NCiAgICB2YXIgZXZhbGVkRm5HZXR0ZXIgPSBuZXcgRnVuY3Rpb24oJ3MnLCAnbCcsICdlc28nLCAnZmUnLCBjb2RlKTsgLy8gcz1zY29wZSwgbD1sb2NhbHMsIGVzbz1lbnN1cmVTYWZlT2JqZWN0DQogICAgLyoganNoaW50ICtXMDU0ICovDQogICAgZXZhbGVkRm5HZXR0ZXIudG9TdHJpbmcgPSB2YWx1ZUZuKGNvZGUpOw0KICAgIGlmIChuZWVkc0Vuc3VyZVNhZmVPYmplY3QpIHsNCiAgICAgIGV2YWxlZEZuR2V0dGVyID0gZ2V0dGVyRm5XaXRoRW5zdXJlU2FmZU9iamVjdChldmFsZWRGbkdldHRlciwgZnVsbEV4cCk7DQogICAgfQ0KICAgIGZuID0gZXZhbGVkRm5HZXR0ZXI7DQogIH0NCg0KICBmbi5zaGFyZWRHZXR0ZXIgPSB0cnVlOw0KICBmbi5hc3NpZ24gPSBmdW5jdGlvbihzZWxmLCB2YWx1ZSkgew0KICAgIHJldHVybiBzZXR0ZXIoc2VsZiwgcGF0aCwgdmFsdWUsIHBhdGgpOw0KICB9Ow0KICBnZXR0ZXJGbkNhY2hlW3BhdGhdID0gZm47DQogIHJldHVybiBmbjsNCn0NCg0KdmFyIG9iamVjdFZhbHVlT2YgPSBPYmplY3QucHJvdG90eXBlLnZhbHVlT2Y7DQoNCmZ1bmN0aW9uIGdldFZhbHVlT2YodmFsdWUpIHsNCiAgcmV0dXJuIGlzRnVuY3Rpb24odmFsdWUudmFsdWVPZikgPyB2YWx1ZS52YWx1ZU9mKCkgOiBvYmplY3RWYWx1ZU9mLmNhbGwodmFsdWUpOw0KfQ0KDQovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KDQovKioNCiAqIEBuZ2RvYyBzZXJ2aWNlDQogKiBAbmFtZSAkcGFyc2UNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKg0KICogQ29udmVydHMgQW5ndWxhciB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBleHByZXNzaW9ufSBpbnRvIGEgZnVuY3Rpb24uDQogKg0KICogYGBganMNCiAqICAgdmFyIGdldHRlciA9ICRwYXJzZSgndXNlci5uYW1lJyk7DQogKiAgIHZhciBzZXR0ZXIgPSBnZXR0ZXIuYXNzaWduOw0KICogICB2YXIgY29udGV4dCA9IHt1c2VyOntuYW1lOidhbmd1bGFyJ319Ow0KICogICB2YXIgbG9jYWxzID0ge3VzZXI6e25hbWU6J2xvY2FsJ319Ow0KICoNCiAqICAgZXhwZWN0KGdldHRlcihjb250ZXh0KSkudG9FcXVhbCgnYW5ndWxhcicpOw0KICogICBzZXR0ZXIoY29udGV4dCwgJ25ld1ZhbHVlJyk7DQogKiAgIGV4cGVjdChjb250ZXh0LnVzZXIubmFtZSkudG9FcXVhbCgnbmV3VmFsdWUnKTsNCiAqICAgZXhwZWN0KGdldHRlcihjb250ZXh0LCBsb2NhbHMpKS50b0VxdWFsKCdsb2NhbCcpOw0KICogYGBgDQogKg0KICoNCiAqIEBwYXJhbSB7c3RyaW5nfSBleHByZXNzaW9uIFN0cmluZyBleHByZXNzaW9uIHRvIGNvbXBpbGUuDQogKiBAcmV0dXJucyB7ZnVuY3Rpb24oY29udGV4dCwgbG9jYWxzKX0gYSBmdW5jdGlvbiB3aGljaCByZXByZXNlbnRzIHRoZSBjb21waWxlZCBleHByZXNzaW9uOg0KICoNCiAqICAgICogYGNvbnRleHRgIOKAPyBge29iamVjdH1gIOKAPyBhbiBvYmplY3QgYWdhaW5zdCB3aGljaCBhbnkgZXhwcmVzc2lvbnMgZW1iZWRkZWQgaW4gdGhlIHN0cmluZ3MNCiAqICAgICAgYXJlIGV2YWx1YXRlZCBhZ2FpbnN0ICh0eXBpY2FsbHkgYSBzY29wZSBvYmplY3QpLg0KICogICAgKiBgbG9jYWxzYCDigD8gYHtvYmplY3Q9fWAg4oA/IGxvY2FsIHZhcmlhYmxlcyBjb250ZXh0IG9iamVjdCwgdXNlZnVsIGZvciBvdmVycmlkaW5nIHZhbHVlcyBpbg0KICogICAgICBgY29udGV4dGAuDQogKg0KICogICAgVGhlIHJldHVybmVkIGZ1bmN0aW9uIGFsc28gaGFzIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllczoNCiAqICAgICAgKiBgbGl0ZXJhbGAg4oA/IGB7Ym9vbGVhbn1gIOKAPyB3aGV0aGVyIHRoZSBleHByZXNzaW9uJ3MgdG9wLWxldmVsIG5vZGUgaXMgYSBKYXZhU2NyaXB0DQogKiAgICAgICAgbGl0ZXJhbC4NCiAqICAgICAgKiBgY29uc3RhbnRgIOKAPyBge2Jvb2xlYW59YCDigD8gd2hldGhlciB0aGUgZXhwcmVzc2lvbiBpcyBtYWRlIGVudGlyZWx5IG9mIEphdmFTY3JpcHQNCiAqICAgICAgICBjb25zdGFudCBsaXRlcmFscy4NCiAqICAgICAgKiBgYXNzaWduYCDigD8gYHs/ZnVuY3Rpb24oY29udGV4dCwgdmFsdWUpfWAg4oA/IGlmIHRoZSBleHByZXNzaW9uIGlzIGFzc2lnbmFibGUsIHRoaXMgd2lsbCBiZQ0KICogICAgICAgIHNldCB0byBhIGZ1bmN0aW9uIHRvIGNoYW5nZSBpdHMgdmFsdWUgb24gdGhlIGdpdmVuIGNvbnRleHQuDQogKg0KICovDQoNCg0KLyoqDQogKiBAbmdkb2MgcHJvdmlkZXINCiAqIEBuYW1lICRwYXJzZVByb3ZpZGVyDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBgJHBhcnNlUHJvdmlkZXJgIGNhbiBiZSB1c2VkIGZvciBjb25maWd1cmluZyB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZiB0aGUge0BsaW5rIG5nLiRwYXJzZSAkcGFyc2V9DQogKiAgc2VydmljZS4NCiAqLw0KZnVuY3Rpb24gJFBhcnNlUHJvdmlkZXIoKSB7DQogIHZhciBjYWNoZURlZmF1bHQgPSBjcmVhdGVNYXAoKTsNCiAgdmFyIGNhY2hlRXhwZW5zaXZlID0gY3JlYXRlTWFwKCk7DQoNCg0KDQogIHRoaXMuJGdldCA9IFsnJGZpbHRlcicsICckc25pZmZlcicsIGZ1bmN0aW9uKCRmaWx0ZXIsICRzbmlmZmVyKSB7DQogICAgdmFyICRwYXJzZU9wdGlvbnMgPSB7DQogICAgICAgICAgY3NwOiAkc25pZmZlci5jc3AsDQogICAgICAgICAgZXhwZW5zaXZlQ2hlY2tzOiBmYWxzZQ0KICAgICAgICB9LA0KICAgICAgICAkcGFyc2VPcHRpb25zRXhwZW5zaXZlID0gew0KICAgICAgICAgIGNzcDogJHNuaWZmZXIuY3NwLA0KICAgICAgICAgIGV4cGVuc2l2ZUNoZWNrczogdHJ1ZQ0KICAgICAgICB9Ow0KDQogICAgZnVuY3Rpb24gd3JhcFNoYXJlZEV4cHJlc3Npb24oZXhwKSB7DQogICAgICB2YXIgd3JhcHBlZCA9IGV4cDsNCg0KICAgICAgaWYgKGV4cC5zaGFyZWRHZXR0ZXIpIHsNCiAgICAgICAgd3JhcHBlZCA9IGZ1bmN0aW9uICRwYXJzZVdyYXBwZXIoc2VsZiwgbG9jYWxzKSB7DQogICAgICAgICAgcmV0dXJuIGV4cChzZWxmLCBsb2NhbHMpOw0KICAgICAgICB9Ow0KICAgICAgICB3cmFwcGVkLmxpdGVyYWwgPSBleHAubGl0ZXJhbDsNCiAgICAgICAgd3JhcHBlZC5jb25zdGFudCA9IGV4cC5jb25zdGFudDsNCiAgICAgICAgd3JhcHBlZC5hc3NpZ24gPSBleHAuYXNzaWduOw0KICAgICAgfQ0KDQogICAgICByZXR1cm4gd3JhcHBlZDsNCiAgICB9DQoNCiAgICByZXR1cm4gZnVuY3Rpb24gJHBhcnNlKGV4cCwgaW50ZXJjZXB0b3JGbiwgZXhwZW5zaXZlQ2hlY2tzKSB7DQogICAgICB2YXIgcGFyc2VkRXhwcmVzc2lvbiwgb25lVGltZSwgY2FjaGVLZXk7DQoNCiAgICAgIHN3aXRjaCAodHlwZW9mIGV4cCkgew0KICAgICAgICBjYXNlICdzdHJpbmcnOg0KICAgICAgICAgIGNhY2hlS2V5ID0gZXhwID0gZXhwLnRyaW0oKTsNCg0KICAgICAgICAgIHZhciBjYWNoZSA9IChleHBlbnNpdmVDaGVja3MgPyBjYWNoZUV4cGVuc2l2ZSA6IGNhY2hlRGVmYXVsdCk7DQogICAgICAgICAgcGFyc2VkRXhwcmVzc2lvbiA9IGNhY2hlW2NhY2hlS2V5XTsNCg0KICAgICAgICAgIGlmICghcGFyc2VkRXhwcmVzc2lvbikgew0KICAgICAgICAgICAgaWYgKGV4cC5jaGFyQXQoMCkgPT09ICc6JyAmJiBleHAuY2hhckF0KDEpID09PSAnOicpIHsNCiAgICAgICAgICAgICAgb25lVGltZSA9IHRydWU7DQogICAgICAgICAgICAgIGV4cCA9IGV4cC5zdWJzdHJpbmcoMik7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIHZhciBwYXJzZU9wdGlvbnMgPSBleHBlbnNpdmVDaGVja3MgPyAkcGFyc2VPcHRpb25zRXhwZW5zaXZlIDogJHBhcnNlT3B0aW9uczsNCiAgICAgICAgICAgIHZhciBsZXhlciA9IG5ldyBMZXhlcihwYXJzZU9wdGlvbnMpOw0KICAgICAgICAgICAgdmFyIHBhcnNlciA9IG5ldyBQYXJzZXIobGV4ZXIsICRmaWx0ZXIsIHBhcnNlT3B0aW9ucyk7DQogICAgICAgICAgICBwYXJzZWRFeHByZXNzaW9uID0gcGFyc2VyLnBhcnNlKGV4cCk7DQoNCiAgICAgICAgICAgIGlmIChwYXJzZWRFeHByZXNzaW9uLmNvbnN0YW50KSB7DQogICAgICAgICAgICAgIHBhcnNlZEV4cHJlc3Npb24uJCR3YXRjaERlbGVnYXRlID0gY29uc3RhbnRXYXRjaERlbGVnYXRlOw0KICAgICAgICAgICAgfSBlbHNlIGlmIChvbmVUaW1lKSB7DQogICAgICAgICAgICAgIC8vb25lVGltZSBpcyBub3QgcGFydCBvZiB0aGUgZXhwIHBhc3NlZCB0byB0aGUgUGFyc2VyIHNvIHdlIG1heSBoYXZlIHRvDQogICAgICAgICAgICAgIC8vd3JhcCB0aGUgcGFyc2VkRXhwcmVzc2lvbiBiZWZvcmUgYWRkaW5nIGEgJCR3YXRjaERlbGVnYXRlDQogICAgICAgICAgICAgIHBhcnNlZEV4cHJlc3Npb24gPSB3cmFwU2hhcmVkRXhwcmVzc2lvbihwYXJzZWRFeHByZXNzaW9uKTsNCiAgICAgICAgICAgICAgcGFyc2VkRXhwcmVzc2lvbi4kJHdhdGNoRGVsZWdhdGUgPSBwYXJzZWRFeHByZXNzaW9uLmxpdGVyYWwgPw0KICAgICAgICAgICAgICAgIG9uZVRpbWVMaXRlcmFsV2F0Y2hEZWxlZ2F0ZSA6IG9uZVRpbWVXYXRjaERlbGVnYXRlOw0KICAgICAgICAgICAgfSBlbHNlIGlmIChwYXJzZWRFeHByZXNzaW9uLmlucHV0cykgew0KICAgICAgICAgICAgICBwYXJzZWRFeHByZXNzaW9uLiQkd2F0Y2hEZWxlZ2F0ZSA9IGlucHV0c1dhdGNoRGVsZWdhdGU7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGNhY2hlW2NhY2hlS2V5XSA9IHBhcnNlZEV4cHJlc3Npb247DQogICAgICAgICAgfQ0KICAgICAgICAgIHJldHVybiBhZGRJbnRlcmNlcHRvcihwYXJzZWRFeHByZXNzaW9uLCBpbnRlcmNlcHRvckZuKTsNCg0KICAgICAgICBjYXNlICdmdW5jdGlvbic6DQogICAgICAgICAgcmV0dXJuIGFkZEludGVyY2VwdG9yKGV4cCwgaW50ZXJjZXB0b3JGbik7DQoNCiAgICAgICAgZGVmYXVsdDoNCiAgICAgICAgICByZXR1cm4gYWRkSW50ZXJjZXB0b3Iobm9vcCwgaW50ZXJjZXB0b3JGbik7DQogICAgICB9DQogICAgfTsNCg0KICAgIGZ1bmN0aW9uIGNvbGxlY3RFeHByZXNzaW9uSW5wdXRzKGlucHV0cywgbGlzdCkgew0KICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gaW5wdXRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsNCiAgICAgICAgdmFyIGlucHV0ID0gaW5wdXRzW2ldOw0KICAgICAgICBpZiAoIWlucHV0LmNvbnN0YW50KSB7DQogICAgICAgICAgaWYgKGlucHV0LmlucHV0cykgew0KICAgICAgICAgICAgY29sbGVjdEV4cHJlc3Npb25JbnB1dHMoaW5wdXQuaW5wdXRzLCBsaXN0KTsNCiAgICAgICAgICB9IGVsc2UgaWYgKGxpc3QuaW5kZXhPZihpbnB1dCkgPT09IC0xKSB7IC8vIFRPRE8ocGVyZikgY2FuIHdlIGRvIGJldHRlcj8NCiAgICAgICAgICAgIGxpc3QucHVzaChpbnB1dCk7DQogICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICB9DQoNCiAgICAgIHJldHVybiBsaXN0Ow0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIGV4cHJlc3Npb25JbnB1dERpcnR5Q2hlY2sobmV3VmFsdWUsIG9sZFZhbHVlT2ZWYWx1ZSkgew0KDQogICAgICBpZiAobmV3VmFsdWUgPT0gbnVsbCB8fCBvbGRWYWx1ZU9mVmFsdWUgPT0gbnVsbCkgeyAvLyBudWxsL3VuZGVmaW5lZA0KICAgICAgICByZXR1cm4gbmV3VmFsdWUgPT09IG9sZFZhbHVlT2ZWYWx1ZTsNCiAgICAgIH0NCg0KICAgICAgaWYgKHR5cGVvZiBuZXdWYWx1ZSA9PT0gJ29iamVjdCcpIHsNCg0KICAgICAgICAvLyBhdHRlbXB0IHRvIGNvbnZlcnQgdGhlIHZhbHVlIHRvIGEgcHJpbWl0aXZlIHR5cGUNCiAgICAgICAgLy8gVE9ETyhkb2NzKTogYWRkIGEgbm90ZSB0byBkb2NzIHRoYXQgYnkgaW1wbGVtZW50aW5nIHZhbHVlT2YgZXZlbiBvYmplY3RzIGFuZCBhcnJheXMgY2FuDQogICAgICAgIC8vICAgICAgICAgICAgIGJlIGNoZWFwbHkgZGlydHktY2hlY2tlZA0KICAgICAgICBuZXdWYWx1ZSA9IGdldFZhbHVlT2YobmV3VmFsdWUpOw0KDQogICAgICAgIGlmICh0eXBlb2YgbmV3VmFsdWUgPT09ICdvYmplY3QnKSB7DQogICAgICAgICAgLy8gb2JqZWN0cy9hcnJheXMgYXJlIG5vdCBzdXBwb3J0ZWQgLSBkZWVwLXdhdGNoaW5nIHRoZW0gd291bGQgYmUgdG9vIGV4cGVuc2l2ZQ0KICAgICAgICAgIHJldHVybiBmYWxzZTsNCiAgICAgICAgfQ0KDQogICAgICAgIC8vIGZhbGwtdGhyb3VnaCB0byB0aGUgcHJpbWl0aXZlIGVxdWFsaXR5IGNoZWNrDQogICAgICB9DQoNCiAgICAgIC8vUHJpbWl0aXZlIG9yIE5hTg0KICAgICAgcmV0dXJuIG5ld1ZhbHVlID09PSBvbGRWYWx1ZU9mVmFsdWUgfHwgKG5ld1ZhbHVlICE9PSBuZXdWYWx1ZSAmJiBvbGRWYWx1ZU9mVmFsdWUgIT09IG9sZFZhbHVlT2ZWYWx1ZSk7DQogICAgfQ0KDQogICAgZnVuY3Rpb24gaW5wdXRzV2F0Y2hEZWxlZ2F0ZShzY29wZSwgbGlzdGVuZXIsIG9iamVjdEVxdWFsaXR5LCBwYXJzZWRFeHByZXNzaW9uKSB7DQogICAgICB2YXIgaW5wdXRFeHByZXNzaW9ucyA9IHBhcnNlZEV4cHJlc3Npb24uJCRpbnB1dHMgfHwNCiAgICAgICAgICAgICAgICAgICAgKHBhcnNlZEV4cHJlc3Npb24uJCRpbnB1dHMgPSBjb2xsZWN0RXhwcmVzc2lvbklucHV0cyhwYXJzZWRFeHByZXNzaW9uLmlucHV0cywgW10pKTsNCg0KICAgICAgdmFyIGxhc3RSZXN1bHQ7DQoNCiAgICAgIGlmIChpbnB1dEV4cHJlc3Npb25zLmxlbmd0aCA9PT0gMSkgew0KICAgICAgICB2YXIgb2xkSW5wdXRWYWx1ZSA9IGV4cHJlc3Npb25JbnB1dERpcnR5Q2hlY2s7IC8vIGluaXQgdG8gc29tZXRoaW5nIHVuaXF1ZSBzbyB0aGF0IGVxdWFscyBjaGVjayBmYWlscw0KICAgICAgICBpbnB1dEV4cHJlc3Npb25zID0gaW5wdXRFeHByZXNzaW9uc1swXTsNCiAgICAgICAgcmV0dXJuIHNjb3BlLiR3YXRjaChmdW5jdGlvbiBleHByZXNzaW9uSW5wdXRXYXRjaChzY29wZSkgew0KICAgICAgICAgIHZhciBuZXdJbnB1dFZhbHVlID0gaW5wdXRFeHByZXNzaW9ucyhzY29wZSk7DQogICAgICAgICAgaWYgKCFleHByZXNzaW9uSW5wdXREaXJ0eUNoZWNrKG5ld0lucHV0VmFsdWUsIG9sZElucHV0VmFsdWUpKSB7DQogICAgICAgICAgICBsYXN0UmVzdWx0ID0gcGFyc2VkRXhwcmVzc2lvbihzY29wZSk7DQogICAgICAgICAgICBvbGRJbnB1dFZhbHVlID0gbmV3SW5wdXRWYWx1ZSAmJiBnZXRWYWx1ZU9mKG5ld0lucHV0VmFsdWUpOw0KICAgICAgICAgIH0NCiAgICAgICAgICByZXR1cm4gbGFzdFJlc3VsdDsNCiAgICAgICAgfSwgbGlzdGVuZXIsIG9iamVjdEVxdWFsaXR5KTsNCiAgICAgIH0NCg0KICAgICAgdmFyIG9sZElucHV0VmFsdWVPZlZhbHVlcyA9IFtdOw0KICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gaW5wdXRFeHByZXNzaW9ucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7DQogICAgICAgIG9sZElucHV0VmFsdWVPZlZhbHVlc1tpXSA9IGV4cHJlc3Npb25JbnB1dERpcnR5Q2hlY2s7IC8vIGluaXQgdG8gc29tZXRoaW5nIHVuaXF1ZSBzbyB0aGF0IGVxdWFscyBjaGVjayBmYWlscw0KICAgICAgfQ0KDQogICAgICByZXR1cm4gc2NvcGUuJHdhdGNoKGZ1bmN0aW9uIGV4cHJlc3Npb25JbnB1dHNXYXRjaChzY29wZSkgew0KICAgICAgICB2YXIgY2hhbmdlZCA9IGZhbHNlOw0KDQogICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGlucHV0RXhwcmVzc2lvbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykgew0KICAgICAgICAgIHZhciBuZXdJbnB1dFZhbHVlID0gaW5wdXRFeHByZXNzaW9uc1tpXShzY29wZSk7DQogICAgICAgICAgaWYgKGNoYW5nZWQgfHwgKGNoYW5nZWQgPSAhZXhwcmVzc2lvbklucHV0RGlydHlDaGVjayhuZXdJbnB1dFZhbHVlLCBvbGRJbnB1dFZhbHVlT2ZWYWx1ZXNbaV0pKSkgew0KICAgICAgICAgICAgb2xkSW5wdXRWYWx1ZU9mVmFsdWVzW2ldID0gbmV3SW5wdXRWYWx1ZSAmJiBnZXRWYWx1ZU9mKG5ld0lucHV0VmFsdWUpOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGlmIChjaGFuZ2VkKSB7DQogICAgICAgICAgbGFzdFJlc3VsdCA9IHBhcnNlZEV4cHJlc3Npb24oc2NvcGUpOw0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuIGxhc3RSZXN1bHQ7DQogICAgICB9LCBsaXN0ZW5lciwgb2JqZWN0RXF1YWxpdHkpOw0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIG9uZVRpbWVXYXRjaERlbGVnYXRlKHNjb3BlLCBsaXN0ZW5lciwgb2JqZWN0RXF1YWxpdHksIHBhcnNlZEV4cHJlc3Npb24pIHsNCiAgICAgIHZhciB1bndhdGNoLCBsYXN0VmFsdWU7DQogICAgICByZXR1cm4gdW53YXRjaCA9IHNjb3BlLiR3YXRjaChmdW5jdGlvbiBvbmVUaW1lV2F0Y2goc2NvcGUpIHsNCiAgICAgICAgcmV0dXJuIHBhcnNlZEV4cHJlc3Npb24oc2NvcGUpOw0KICAgICAgfSwgZnVuY3Rpb24gb25lVGltZUxpc3RlbmVyKHZhbHVlLCBvbGQsIHNjb3BlKSB7DQogICAgICAgIGxhc3RWYWx1ZSA9IHZhbHVlOw0KICAgICAgICBpZiAoaXNGdW5jdGlvbihsaXN0ZW5lcikpIHsNCiAgICAgICAgICBsaXN0ZW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOw0KICAgICAgICB9DQogICAgICAgIGlmIChpc0RlZmluZWQodmFsdWUpKSB7DQogICAgICAgICAgc2NvcGUuJCRwb3N0RGlnZXN0KGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgaWYgKGlzRGVmaW5lZChsYXN0VmFsdWUpKSB7DQogICAgICAgICAgICAgIHVud2F0Y2goKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9KTsNCiAgICAgICAgfQ0KICAgICAgfSwgb2JqZWN0RXF1YWxpdHkpOw0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIG9uZVRpbWVMaXRlcmFsV2F0Y2hEZWxlZ2F0ZShzY29wZSwgbGlzdGVuZXIsIG9iamVjdEVxdWFsaXR5LCBwYXJzZWRFeHByZXNzaW9uKSB7DQogICAgICB2YXIgdW53YXRjaCwgbGFzdFZhbHVlOw0KICAgICAgcmV0dXJuIHVud2F0Y2ggPSBzY29wZS4kd2F0Y2goZnVuY3Rpb24gb25lVGltZVdhdGNoKHNjb3BlKSB7DQogICAgICAgIHJldHVybiBwYXJzZWRFeHByZXNzaW9uKHNjb3BlKTsNCiAgICAgIH0sIGZ1bmN0aW9uIG9uZVRpbWVMaXN0ZW5lcih2YWx1ZSwgb2xkLCBzY29wZSkgew0KICAgICAgICBsYXN0VmFsdWUgPSB2YWx1ZTsNCiAgICAgICAgaWYgKGlzRnVuY3Rpb24obGlzdGVuZXIpKSB7DQogICAgICAgICAgbGlzdGVuZXIuY2FsbCh0aGlzLCB2YWx1ZSwgb2xkLCBzY29wZSk7DQogICAgICAgIH0NCiAgICAgICAgaWYgKGlzQWxsRGVmaW5lZCh2YWx1ZSkpIHsNCiAgICAgICAgICBzY29wZS4kJHBvc3REaWdlc3QoZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBpZiAoaXNBbGxEZWZpbmVkKGxhc3RWYWx1ZSkpIHVud2F0Y2goKTsNCiAgICAgICAgICB9KTsNCiAgICAgICAgfQ0KICAgICAgfSwgb2JqZWN0RXF1YWxpdHkpOw0KDQogICAgICBmdW5jdGlvbiBpc0FsbERlZmluZWQodmFsdWUpIHsNCiAgICAgICAgdmFyIGFsbERlZmluZWQgPSB0cnVlOw0KICAgICAgICBmb3JFYWNoKHZhbHVlLCBmdW5jdGlvbih2YWwpIHsNCiAgICAgICAgICBpZiAoIWlzRGVmaW5lZCh2YWwpKSBhbGxEZWZpbmVkID0gZmFsc2U7DQogICAgICAgIH0pOw0KICAgICAgICByZXR1cm4gYWxsRGVmaW5lZDsNCiAgICAgIH0NCiAgICB9DQoNCiAgICBmdW5jdGlvbiBjb25zdGFudFdhdGNoRGVsZWdhdGUoc2NvcGUsIGxpc3RlbmVyLCBvYmplY3RFcXVhbGl0eSwgcGFyc2VkRXhwcmVzc2lvbikgew0KICAgICAgdmFyIHVud2F0Y2g7DQogICAgICByZXR1cm4gdW53YXRjaCA9IHNjb3BlLiR3YXRjaChmdW5jdGlvbiBjb25zdGFudFdhdGNoKHNjb3BlKSB7DQogICAgICAgIHJldHVybiBwYXJzZWRFeHByZXNzaW9uKHNjb3BlKTsNCiAgICAgIH0sIGZ1bmN0aW9uIGNvbnN0YW50TGlzdGVuZXIodmFsdWUsIG9sZCwgc2NvcGUpIHsNCiAgICAgICAgaWYgKGlzRnVuY3Rpb24obGlzdGVuZXIpKSB7DQogICAgICAgICAgbGlzdGVuZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsNCiAgICAgICAgfQ0KICAgICAgICB1bndhdGNoKCk7DQogICAgICB9LCBvYmplY3RFcXVhbGl0eSk7DQogICAgfQ0KDQogICAgZnVuY3Rpb24gYWRkSW50ZXJjZXB0b3IocGFyc2VkRXhwcmVzc2lvbiwgaW50ZXJjZXB0b3JGbikgew0KICAgICAgaWYgKCFpbnRlcmNlcHRvckZuKSByZXR1cm4gcGFyc2VkRXhwcmVzc2lvbjsNCiAgICAgIHZhciB3YXRjaERlbGVnYXRlID0gcGFyc2VkRXhwcmVzc2lvbi4kJHdhdGNoRGVsZWdhdGU7DQoNCiAgICAgIHZhciByZWd1bGFyV2F0Y2ggPQ0KICAgICAgICAgIHdhdGNoRGVsZWdhdGUgIT09IG9uZVRpbWVMaXRlcmFsV2F0Y2hEZWxlZ2F0ZSAmJg0KICAgICAgICAgIHdhdGNoRGVsZWdhdGUgIT09IG9uZVRpbWVXYXRjaERlbGVnYXRlOw0KDQogICAgICB2YXIgZm4gPSByZWd1bGFyV2F0Y2ggPyBmdW5jdGlvbiByZWd1bGFySW50ZXJjZXB0ZWRFeHByZXNzaW9uKHNjb3BlLCBsb2NhbHMpIHsNCiAgICAgICAgdmFyIHZhbHVlID0gcGFyc2VkRXhwcmVzc2lvbihzY29wZSwgbG9jYWxzKTsNCiAgICAgICAgcmV0dXJuIGludGVyY2VwdG9yRm4odmFsdWUsIHNjb3BlLCBsb2NhbHMpOw0KICAgICAgfSA6IGZ1bmN0aW9uIG9uZVRpbWVJbnRlcmNlcHRlZEV4cHJlc3Npb24oc2NvcGUsIGxvY2Fscykgew0KICAgICAgICB2YXIgdmFsdWUgPSBwYXJzZWRFeHByZXNzaW9uKHNjb3BlLCBsb2NhbHMpOw0KICAgICAgICB2YXIgcmVzdWx0ID0gaW50ZXJjZXB0b3JGbih2YWx1ZSwgc2NvcGUsIGxvY2Fscyk7DQogICAgICAgIC8vIHdlIG9ubHkgcmV0dXJuIHRoZSBpbnRlcmNlcHRvcidzIHJlc3VsdCBpZiB0aGUNCiAgICAgICAgLy8gaW5pdGlhbCB2YWx1ZSBpcyBkZWZpbmVkIChmb3IgYmluZC1vbmNlKQ0KICAgICAgICByZXR1cm4gaXNEZWZpbmVkKHZhbHVlKSA/IHJlc3VsdCA6IHZhbHVlOw0KICAgICAgfTsNCg0KICAgICAgLy8gUHJvcGFnYXRlICQkd2F0Y2hEZWxlZ2F0ZXMgb3RoZXIgdGhlbiBpbnB1dHNXYXRjaERlbGVnYXRlDQogICAgICBpZiAocGFyc2VkRXhwcmVzc2lvbi4kJHdhdGNoRGVsZWdhdGUgJiYNCiAgICAgICAgICBwYXJzZWRFeHByZXNzaW9uLiQkd2F0Y2hEZWxlZ2F0ZSAhPT0gaW5wdXRzV2F0Y2hEZWxlZ2F0ZSkgew0KICAgICAgICBmbi4kJHdhdGNoRGVsZWdhdGUgPSBwYXJzZWRFeHByZXNzaW9uLiQkd2F0Y2hEZWxlZ2F0ZTsNCiAgICAgIH0gZWxzZSBpZiAoIWludGVyY2VwdG9yRm4uJHN0YXRlZnVsKSB7DQogICAgICAgIC8vIElmIHRoZXJlIGlzIGFuIGludGVyY2VwdG9yLCBidXQgbm8gd2F0Y2hEZWxlZ2F0ZSB0aGVuIHRyZWF0IHRoZSBpbnRlcmNlcHRvciBsaWtlDQogICAgICAgIC8vIHdlIHRyZWF0IGZpbHRlcnMgLSBpdCBpcyBhc3N1bWVkIHRvIGJlIGEgcHVyZSBmdW5jdGlvbiB1bmxlc3MgZmxhZ2dlZCB3aXRoICRzdGF0ZWZ1bA0KICAgICAgICBmbi4kJHdhdGNoRGVsZWdhdGUgPSBpbnB1dHNXYXRjaERlbGVnYXRlOw0KICAgICAgICBmbi5pbnB1dHMgPSBbcGFyc2VkRXhwcmVzc2lvbl07DQogICAgICB9DQoNCiAgICAgIHJldHVybiBmbjsNCiAgICB9DQogIH1dOw0KfQ0KDQovKioNCiAqIEBuZ2RvYyBzZXJ2aWNlDQogKiBAbmFtZSAkcQ0KICogQHJlcXVpcmVzICRyb290U2NvcGUNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIEEgc2VydmljZSB0aGF0IGhlbHBzIHlvdSBydW4gZnVuY3Rpb25zIGFzeW5jaHJvbm91c2x5LCBhbmQgdXNlIHRoZWlyIHJldHVybiB2YWx1ZXMgKG9yIGV4Y2VwdGlvbnMpDQogKiB3aGVuIHRoZXkgYXJlIGRvbmUgcHJvY2Vzc2luZy4NCiAqDQogKiBUaGlzIGlzIGFuIGltcGxlbWVudGF0aW9uIG9mIHByb21pc2VzL2RlZmVycmVkIG9iamVjdHMgaW5zcGlyZWQgYnkNCiAqIFtLcmlzIEtvd2FsJ3MgUV0oaHR0cHM6Ly9naXRodWIuY29tL2tyaXNrb3dhbC9xKS4NCiAqDQogKiAkcSBjYW4gYmUgdXNlZCBpbiB0d28gZmFzaGlvbnMgLS0tIG9uZSB3aGljaCBpcyBtb3JlIHNpbWlsYXIgdG8gS3JpcyBLb3dhbCdzIFEgb3IgalF1ZXJ5J3MgRGVmZXJyZWQNCiAqIGltcGxlbWVudGF0aW9ucywgYW5kIHRoZSBvdGhlciB3aGljaCByZXNlbWJsZXMgRVM2IHByb21pc2VzIHRvIHNvbWUgZGVncmVlLg0KICoNCiAqICMgJHEgY29uc3RydWN0b3INCiAqDQogKiBUaGUgc3RyZWFtbGluZWQgRVM2IHN0eWxlIHByb21pc2UgaXMgZXNzZW50aWFsbHkganVzdCB1c2luZyAkcSBhcyBhIGNvbnN0cnVjdG9yIHdoaWNoIHRha2VzIGEgYHJlc29sdmVyYA0KICogZnVuY3Rpb24gYXMgdGhlIGZpcnN0IGFyZ3VtZW50LiBUaGlzIGlzIHNpbWlsYXIgdG8gdGhlIG5hdGl2ZSBQcm9taXNlIGltcGxlbWVudGF0aW9uIGZyb20gRVM2IEhhcm1vbnksDQogKiBzZWUgW01ETl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvUHJvbWlzZSkuDQogKg0KICogV2hpbGUgdGhlIGNvbnN0cnVjdG9yLXN0eWxlIHVzZSBpcyBzdXBwb3J0ZWQsIG5vdCBhbGwgb2YgdGhlIHN1cHBvcnRpbmcgbWV0aG9kcyBmcm9tIEVTNiBIYXJtb255IHByb21pc2VzIGFyZQ0KICogYXZhaWxhYmxlIHlldC4NCiAqDQogKiBJdCBjYW4gYmUgdXNlZCBsaWtlIHNvOg0KICoNCiAqIGBgYGpzDQogKiAgIC8vIGZvciB0aGUgcHVycG9zZSBvZiB0aGlzIGV4YW1wbGUgbGV0J3MgYXNzdW1lIHRoYXQgdmFyaWFibGVzIGAkcWAgYW5kIGBva1RvR3JlZXRgDQogKiAgIC8vIGFyZSBhdmFpbGFibGUgaW4gdGhlIGN1cnJlbnQgbGV4aWNhbCBzY29wZSAodGhleSBjb3VsZCBoYXZlIGJlZW4gaW5qZWN0ZWQgb3IgcGFzc2VkIGluKS4NCiAqDQogKiAgIGZ1bmN0aW9uIGFzeW5jR3JlZXQobmFtZSkgew0KICogICAgIC8vIHBlcmZvcm0gc29tZSBhc3luY2hyb25vdXMgb3BlcmF0aW9uLCByZXNvbHZlIG9yIHJlamVjdCB0aGUgcHJvbWlzZSB3aGVuIGFwcHJvcHJpYXRlLg0KICogICAgIHJldHVybiAkcShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHsNCiAqICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7DQogKiAgICAgICAgIGlmIChva1RvR3JlZXQobmFtZSkpIHsNCiAqICAgICAgICAgICByZXNvbHZlKCdIZWxsbywgJyArIG5hbWUgKyAnIScpOw0KICogICAgICAgICB9IGVsc2Ugew0KICogICAgICAgICAgIHJlamVjdCgnR3JlZXRpbmcgJyArIG5hbWUgKyAnIGlzIG5vdCBhbGxvd2VkLicpOw0KICogICAgICAgICB9DQogKiAgICAgICB9LCAxMDAwKTsNCiAqICAgICB9KTsNCiAqICAgfQ0KICoNCiAqICAgdmFyIHByb21pc2UgPSBhc3luY0dyZWV0KCdSb2JpbiBIb29kJyk7DQogKiAgIHByb21pc2UudGhlbihmdW5jdGlvbihncmVldGluZykgew0KICogICAgIGFsZXJ0KCdTdWNjZXNzOiAnICsgZ3JlZXRpbmcpOw0KICogICB9LCBmdW5jdGlvbihyZWFzb24pIHsNCiAqICAgICBhbGVydCgnRmFpbGVkOiAnICsgcmVhc29uKTsNCiAqICAgfSk7DQogKiBgYGANCiAqDQogKiBOb3RlOiBwcm9ncmVzcy9ub3RpZnkgY2FsbGJhY2tzIGFyZSBub3QgY3VycmVudGx5IHN1cHBvcnRlZCB2aWEgdGhlIEVTNi1zdHlsZSBpbnRlcmZhY2UuDQogKg0KICogSG93ZXZlciwgdGhlIG1vcmUgdHJhZGl0aW9uYWwgQ29tbW9uSlMtc3R5bGUgdXNhZ2UgaXMgc3RpbGwgYXZhaWxhYmxlLCBhbmQgZG9jdW1lbnRlZCBiZWxvdy4NCiAqDQogKiBbVGhlIENvbW1vbkpTIFByb21pc2UgcHJvcG9zYWxdKGh0dHA6Ly93aWtpLmNvbW1vbmpzLm9yZy93aWtpL1Byb21pc2VzKSBkZXNjcmliZXMgYSBwcm9taXNlIGFzIGFuDQogKiBpbnRlcmZhY2UgZm9yIGludGVyYWN0aW5nIHdpdGggYW4gb2JqZWN0IHRoYXQgcmVwcmVzZW50cyB0aGUgcmVzdWx0IG9mIGFuIGFjdGlvbiB0aGF0IGlzDQogKiBwZXJmb3JtZWQgYXN5bmNocm9ub3VzbHksIGFuZCBtYXkgb3IgbWF5IG5vdCBiZSBmaW5pc2hlZCBhdCBhbnkgZ2l2ZW4gcG9pbnQgaW4gdGltZS4NCiAqDQogKiBGcm9tIHRoZSBwZXJzcGVjdGl2ZSBvZiBkZWFsaW5nIHdpdGggZXJyb3IgaGFuZGxpbmcsIGRlZmVycmVkIGFuZCBwcm9taXNlIEFQSXMgYXJlIHRvDQogKiBhc3luY2hyb25vdXMgcHJvZ3JhbW1pbmcgd2hhdCBgdHJ5YCwgYGNhdGNoYCBhbmQgYHRocm93YCBrZXl3b3JkcyBhcmUgdG8gc3luY2hyb25vdXMgcHJvZ3JhbW1pbmcuDQogKg0KICogYGBganMNCiAqICAgLy8gZm9yIHRoZSBwdXJwb3NlIG9mIHRoaXMgZXhhbXBsZSBsZXQncyBhc3N1bWUgdGhhdCB2YXJpYWJsZXMgYCRxYCBhbmQgYG9rVG9HcmVldGANCiAqICAgLy8gYXJlIGF2YWlsYWJsZSBpbiB0aGUgY3VycmVudCBsZXhpY2FsIHNjb3BlICh0aGV5IGNvdWxkIGhhdmUgYmVlbiBpbmplY3RlZCBvciBwYXNzZWQgaW4pLg0KICoNCiAqICAgZnVuY3Rpb24gYXN5bmNHcmVldChuYW1lKSB7DQogKiAgICAgdmFyIGRlZmVycmVkID0gJHEuZGVmZXIoKTsNCiAqDQogKiAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsNCiAqICAgICAgIGRlZmVycmVkLm5vdGlmeSgnQWJvdXQgdG8gZ3JlZXQgJyArIG5hbWUgKyAnLicpOw0KICoNCiAqICAgICAgIGlmIChva1RvR3JlZXQobmFtZSkpIHsNCiAqICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZSgnSGVsbG8sICcgKyBuYW1lICsgJyEnKTsNCiAqICAgICAgIH0gZWxzZSB7DQogKiAgICAgICAgIGRlZmVycmVkLnJlamVjdCgnR3JlZXRpbmcgJyArIG5hbWUgKyAnIGlzIG5vdCBhbGxvd2VkLicpOw0KICogICAgICAgfQ0KICogICAgIH0sIDEwMDApOw0KICoNCiAqICAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZTsNCiAqICAgfQ0KICoNCiAqICAgdmFyIHByb21pc2UgPSBhc3luY0dyZWV0KCdSb2JpbiBIb29kJyk7DQogKiAgIHByb21pc2UudGhlbihmdW5jdGlvbihncmVldGluZykgew0KICogICAgIGFsZXJ0KCdTdWNjZXNzOiAnICsgZ3JlZXRpbmcpOw0KICogICB9LCBmdW5jdGlvbihyZWFzb24pIHsNCiAqICAgICBhbGVydCgnRmFpbGVkOiAnICsgcmVhc29uKTsNCiAqICAgfSwgZnVuY3Rpb24odXBkYXRlKSB7DQogKiAgICAgYWxlcnQoJ0dvdCBub3RpZmljYXRpb246ICcgKyB1cGRhdGUpOw0KICogICB9KTsNCiAqIGBgYA0KICoNCiAqIEF0IGZpcnN0IGl0IG1pZ2h0IG5vdCBiZSBvYnZpb3VzIHdoeSB0aGlzIGV4dHJhIGNvbXBsZXhpdHkgaXMgd29ydGggdGhlIHRyb3VibGUuIFRoZSBwYXlvZmYNCiAqIGNvbWVzIGluIHRoZSB3YXkgb2YgZ3VhcmFudGVlcyB0aGF0IHByb21pc2UgYW5kIGRlZmVycmVkIEFQSXMgbWFrZSwgc2VlDQogKiBodHRwczovL2dpdGh1Yi5jb20va3Jpc2tvd2FsL3VuY29tbW9uanMvYmxvYi9tYXN0ZXIvcHJvbWlzZXMvc3BlY2lmaWNhdGlvbi5tZC4NCiAqDQogKiBBZGRpdGlvbmFsbHkgdGhlIHByb21pc2UgYXBpIGFsbG93cyBmb3IgY29tcG9zaXRpb24gdGhhdCBpcyB2ZXJ5IGhhcmQgdG8gZG8gd2l0aCB0aGUNCiAqIHRyYWRpdGlvbmFsIGNhbGxiYWNrIChbQ1BTXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NvbnRpbnVhdGlvbi1wYXNzaW5nX3N0eWxlKSkgYXBwcm9hY2guDQogKiBGb3IgbW9yZSBvbiB0aGlzIHBsZWFzZSBzZWUgdGhlIFtRIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9rcmlza293YWwvcSkgZXNwZWNpYWxseSB0aGUNCiAqIHNlY3Rpb24gb24gc2VyaWFsIG9yIHBhcmFsbGVsIGpvaW5pbmcgb2YgcHJvbWlzZXMuDQogKg0KICogIyBUaGUgRGVmZXJyZWQgQVBJDQogKg0KICogQSBuZXcgaW5zdGFuY2Ugb2YgZGVmZXJyZWQgaXMgY29uc3RydWN0ZWQgYnkgY2FsbGluZyBgJHEuZGVmZXIoKWAuDQogKg0KICogVGhlIHB1cnBvc2Ugb2YgdGhlIGRlZmVycmVkIG9iamVjdCBpcyB0byBleHBvc2UgdGhlIGFzc29jaWF0ZWQgUHJvbWlzZSBpbnN0YW5jZSBhcyB3ZWxsIGFzIEFQSXMNCiAqIHRoYXQgY2FuIGJlIHVzZWQgZm9yIHNpZ25hbGluZyB0aGUgc3VjY2Vzc2Z1bCBvciB1bnN1Y2Nlc3NmdWwgY29tcGxldGlvbiwgYXMgd2VsbCBhcyB0aGUgc3RhdHVzDQogKiBvZiB0aGUgdGFzay4NCiAqDQogKiAqKk1ldGhvZHMqKg0KICoNCiAqIC0gYHJlc29sdmUodmFsdWUpYCDigD8gcmVzb2x2ZXMgdGhlIGRlcml2ZWQgcHJvbWlzZSB3aXRoIHRoZSBgdmFsdWVgLiBJZiB0aGUgdmFsdWUgaXMgYSByZWplY3Rpb24NCiAqICAgY29uc3RydWN0ZWQgdmlhIGAkcS5yZWplY3RgLCB0aGUgcHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkIGluc3RlYWQuDQogKiAtIGByZWplY3QocmVhc29uKWAg4oA/IHJlamVjdHMgdGhlIGRlcml2ZWQgcHJvbWlzZSB3aXRoIHRoZSBgcmVhc29uYC4gVGhpcyBpcyBlcXVpdmFsZW50IHRvDQogKiAgIHJlc29sdmluZyBpdCB3aXRoIGEgcmVqZWN0aW9uIGNvbnN0cnVjdGVkIHZpYSBgJHEucmVqZWN0YC4NCiAqIC0gYG5vdGlmeSh2YWx1ZSlgIC0gcHJvdmlkZXMgdXBkYXRlcyBvbiB0aGUgc3RhdHVzIG9mIHRoZSBwcm9taXNlJ3MgZXhlY3V0aW9uLiBUaGlzIG1heSBiZSBjYWxsZWQNCiAqICAgbXVsdGlwbGUgdGltZXMgYmVmb3JlIHRoZSBwcm9taXNlIGlzIGVpdGhlciByZXNvbHZlZCBvciByZWplY3RlZC4NCiAqDQogKiAqKlByb3BlcnRpZXMqKg0KICoNCiAqIC0gcHJvbWlzZSDigD8gYHtQcm9taXNlfWAg4oA/IHByb21pc2Ugb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGlzIGRlZmVycmVkLg0KICoNCiAqDQogKiAjIFRoZSBQcm9taXNlIEFQSQ0KICoNCiAqIEEgbmV3IHByb21pc2UgaW5zdGFuY2UgaXMgY3JlYXRlZCB3aGVuIGEgZGVmZXJyZWQgaW5zdGFuY2UgaXMgY3JlYXRlZCBhbmQgY2FuIGJlIHJldHJpZXZlZCBieQ0KICogY2FsbGluZyBgZGVmZXJyZWQucHJvbWlzZWAuDQogKg0KICogVGhlIHB1cnBvc2Ugb2YgdGhlIHByb21pc2Ugb2JqZWN0IGlzIHRvIGFsbG93IGZvciBpbnRlcmVzdGVkIHBhcnRpZXMgdG8gZ2V0IGFjY2VzcyB0byB0aGUgcmVzdWx0DQogKiBvZiB0aGUgZGVmZXJyZWQgdGFzayB3aGVuIGl0IGNvbXBsZXRlcy4NCiAqDQogKiAqKk1ldGhvZHMqKg0KICoNCiAqIC0gYHRoZW4oc3VjY2Vzc0NhbGxiYWNrLCBlcnJvckNhbGxiYWNrLCBub3RpZnlDYWxsYmFjaylgIOKAPyByZWdhcmRsZXNzIG9mIHdoZW4gdGhlIHByb21pc2Ugd2FzIG9yDQogKiAgIHdpbGwgYmUgcmVzb2x2ZWQgb3IgcmVqZWN0ZWQsIGB0aGVuYCBjYWxscyBvbmUgb2YgdGhlIHN1Y2Nlc3Mgb3IgZXJyb3IgY2FsbGJhY2tzIGFzeW5jaHJvbm91c2x5DQogKiAgIGFzIHNvb24gYXMgdGhlIHJlc3VsdCBpcyBhdmFpbGFibGUuIFRoZSBjYWxsYmFja3MgYXJlIGNhbGxlZCB3aXRoIGEgc2luZ2xlIGFyZ3VtZW50OiB0aGUgcmVzdWx0DQogKiAgIG9yIHJlamVjdGlvbiByZWFzb24uIEFkZGl0aW9uYWxseSwgdGhlIG5vdGlmeSBjYWxsYmFjayBtYXkgYmUgY2FsbGVkIHplcm8gb3IgbW9yZSB0aW1lcyB0bw0KICogICBwcm92aWRlIGEgcHJvZ3Jlc3MgaW5kaWNhdGlvbiwgYmVmb3JlIHRoZSBwcm9taXNlIGlzIHJlc29sdmVkIG9yIHJlamVjdGVkLg0KICoNCiAqICAgVGhpcyBtZXRob2QgKnJldHVybnMgYSBuZXcgcHJvbWlzZSogd2hpY2ggaXMgcmVzb2x2ZWQgb3IgcmVqZWN0ZWQgdmlhIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlDQogKiAgIGBzdWNjZXNzQ2FsbGJhY2tgLCBgZXJyb3JDYWxsYmFja2AuIEl0IGFsc28gbm90aWZpZXMgdmlhIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlDQogKiAgIGBub3RpZnlDYWxsYmFja2AgbWV0aG9kLiBUaGUgcHJvbWlzZSBjYW5ub3QgYmUgcmVzb2x2ZWQgb3IgcmVqZWN0ZWQgZnJvbSB0aGUgbm90aWZ5Q2FsbGJhY2sNCiAqICAgbWV0aG9kLg0KICoNCiAqIC0gYGNhdGNoKGVycm9yQ2FsbGJhY2spYCDigD8gc2hvcnRoYW5kIGZvciBgcHJvbWlzZS50aGVuKG51bGwsIGVycm9yQ2FsbGJhY2spYA0KICoNCiAqIC0gYGZpbmFsbHkoY2FsbGJhY2ssIG5vdGlmeUNhbGxiYWNrKWAg4oA/IGFsbG93cyB5b3UgdG8gb2JzZXJ2ZSBlaXRoZXIgdGhlIGZ1bGZpbGxtZW50IG9yIHJlamVjdGlvbiBvZiBhIHByb21pc2UsDQogKiAgIGJ1dCB0byBkbyBzbyB3aXRob3V0IG1vZGlmeWluZyB0aGUgZmluYWwgdmFsdWUuIFRoaXMgaXMgdXNlZnVsIHRvIHJlbGVhc2UgcmVzb3VyY2VzIG9yIGRvIHNvbWUNCiAqICAgY2xlYW4tdXAgdGhhdCBuZWVkcyB0byBiZSBkb25lIHdoZXRoZXIgdGhlIHByb21pc2Ugd2FzIHJlamVjdGVkIG9yIHJlc29sdmVkLiBTZWUgdGhlIFtmdWxsDQogKiAgIHNwZWNpZmljYXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9rcmlza293YWwvcS93aWtpL0FQSS1SZWZlcmVuY2UjcHJvbWlzZWZpbmFsbHljYWxsYmFjaykgZm9yDQogKiAgIG1vcmUgaW5mb3JtYXRpb24uDQogKg0KICogIyBDaGFpbmluZyBwcm9taXNlcw0KICoNCiAqIEJlY2F1c2UgY2FsbGluZyB0aGUgYHRoZW5gIG1ldGhvZCBvZiBhIHByb21pc2UgcmV0dXJucyBhIG5ldyBkZXJpdmVkIHByb21pc2UsIGl0IGlzIGVhc2lseQ0KICogcG9zc2libGUgdG8gY3JlYXRlIGEgY2hhaW4gb2YgcHJvbWlzZXM6DQogKg0KICogYGBganMNCiAqICAgcHJvbWlzZUIgPSBwcm9taXNlQS50aGVuKGZ1bmN0aW9uKHJlc3VsdCkgew0KICogICAgIHJldHVybiByZXN1bHQgKyAxOw0KICogICB9KTsNCiAqDQogKiAgIC8vIHByb21pc2VCIHdpbGwgYmUgcmVzb2x2ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgcHJvbWlzZUEgaXMgcmVzb2x2ZWQgYW5kIGl0cyB2YWx1ZQ0KICogICAvLyB3aWxsIGJlIHRoZSByZXN1bHQgb2YgcHJvbWlzZUEgaW5jcmVtZW50ZWQgYnkgMQ0KICogYGBgDQogKg0KICogSXQgaXMgcG9zc2libGUgdG8gY3JlYXRlIGNoYWlucyBvZiBhbnkgbGVuZ3RoIGFuZCBzaW5jZSBhIHByb21pc2UgY2FuIGJlIHJlc29sdmVkIHdpdGggYW5vdGhlcg0KICogcHJvbWlzZSAod2hpY2ggd2lsbCBkZWZlciBpdHMgcmVzb2x1dGlvbiBmdXJ0aGVyKSwgaXQgaXMgcG9zc2libGUgdG8gcGF1c2UvZGVmZXIgcmVzb2x1dGlvbiBvZg0KICogdGhlIHByb21pc2VzIGF0IGFueSBwb2ludCBpbiB0aGUgY2hhaW4uIFRoaXMgbWFrZXMgaXQgcG9zc2libGUgdG8gaW1wbGVtZW50IHBvd2VyZnVsIEFQSXMgbGlrZQ0KICogJGh0dHAncyByZXNwb25zZSBpbnRlcmNlcHRvcnMuDQogKg0KICoNCiAqICMgRGlmZmVyZW5jZXMgYmV0d2VlbiBLcmlzIEtvd2FsJ3MgUSBhbmQgJHENCiAqDQogKiAgVGhlcmUgYXJlIHR3byBtYWluIGRpZmZlcmVuY2VzOg0KICoNCiAqIC0gJHEgaXMgaW50ZWdyYXRlZCB3aXRoIHRoZSB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZX0gU2NvcGUgbW9kZWwgb2JzZXJ2YXRpb24NCiAqICAgbWVjaGFuaXNtIGluIGFuZ3VsYXIsIHdoaWNoIG1lYW5zIGZhc3RlciBwcm9wYWdhdGlvbiBvZiByZXNvbHV0aW9uIG9yIHJlamVjdGlvbiBpbnRvIHlvdXINCiAqICAgbW9kZWxzIGFuZCBhdm9pZGluZyB1bm5lY2Vzc2FyeSBicm93c2VyIHJlcGFpbnRzLCB3aGljaCB3b3VsZCByZXN1bHQgaW4gZmxpY2tlcmluZyBVSS4NCiAqIC0gUSBoYXMgbWFueSBtb3JlIGZlYXR1cmVzIHRoYW4gJHEsIGJ1dCB0aGF0IGNvbWVzIGF0IGEgY29zdCBvZiBieXRlcy4gJHEgaXMgdGlueSwgYnV0IGNvbnRhaW5zDQogKiAgIGFsbCB0aGUgaW1wb3J0YW50IGZ1bmN0aW9uYWxpdHkgbmVlZGVkIGZvciBjb21tb24gYXN5bmMgdGFza3MuDQogKg0KICogICMgVGVzdGluZw0KICoNCiAqICBgYGBqcw0KICogICAgaXQoJ3Nob3VsZCBzaW11bGF0ZSBwcm9taXNlJywgaW5qZWN0KGZ1bmN0aW9uKCRxLCAkcm9vdFNjb3BlKSB7DQogKiAgICAgIHZhciBkZWZlcnJlZCA9ICRxLmRlZmVyKCk7DQogKiAgICAgIHZhciBwcm9taXNlID0gZGVmZXJyZWQucHJvbWlzZTsNCiAqICAgICAgdmFyIHJlc29sdmVkVmFsdWU7DQogKg0KICogICAgICBwcm9taXNlLnRoZW4oZnVuY3Rpb24odmFsdWUpIHsgcmVzb2x2ZWRWYWx1ZSA9IHZhbHVlOyB9KTsNCiAqICAgICAgZXhwZWN0KHJlc29sdmVkVmFsdWUpLnRvQmVVbmRlZmluZWQoKTsNCiAqDQogKiAgICAgIC8vIFNpbXVsYXRlIHJlc29sdmluZyBvZiBwcm9taXNlDQogKiAgICAgIGRlZmVycmVkLnJlc29sdmUoMTIzKTsNCiAqICAgICAgLy8gTm90ZSB0aGF0IHRoZSAndGhlbicgZnVuY3Rpb24gZG9lcyBub3QgZ2V0IGNhbGxlZCBzeW5jaHJvbm91c2x5Lg0KICogICAgICAvLyBUaGlzIGlzIGJlY2F1c2Ugd2Ugd2FudCB0aGUgcHJvbWlzZSBBUEkgdG8gYWx3YXlzIGJlIGFzeW5jLCB3aGV0aGVyIG9yIG5vdA0KICogICAgICAvLyBpdCBnb3QgY2FsbGVkIHN5bmNocm9ub3VzbHkgb3IgYXN5bmNocm9ub3VzbHkuDQogKiAgICAgIGV4cGVjdChyZXNvbHZlZFZhbHVlKS50b0JlVW5kZWZpbmVkKCk7DQogKg0KICogICAgICAvLyBQcm9wYWdhdGUgcHJvbWlzZSByZXNvbHV0aW9uIHRvICd0aGVuJyBmdW5jdGlvbnMgdXNpbmcgJGFwcGx5KCkuDQogKiAgICAgICRyb290U2NvcGUuJGFwcGx5KCk7DQogKiAgICAgIGV4cGVjdChyZXNvbHZlZFZhbHVlKS50b0VxdWFsKDEyMyk7DQogKiAgICB9KSk7DQogKiAgYGBgDQogKg0KICogQHBhcmFtIHtmdW5jdGlvbihmdW5jdGlvbiwgZnVuY3Rpb24pfSByZXNvbHZlciBGdW5jdGlvbiB3aGljaCBpcyByZXNwb25zaWJsZSBmb3IgcmVzb2x2aW5nIG9yDQogKiAgIHJlamVjdGluZyB0aGUgbmV3bHkgY3JlYXRlZCBwcm9taXNlLiBUaGUgZmlyc3QgcGFyYW1ldGVyIGlzIGEgZnVuY3Rpb24gd2hpY2ggcmVzb2x2ZXMgdGhlDQogKiAgIHByb21pc2UsIHRoZSBzZWNvbmQgcGFyYW1ldGVyIGlzIGEgZnVuY3Rpb24gd2hpY2ggcmVqZWN0cyB0aGUgcHJvbWlzZS4NCiAqDQogKiBAcmV0dXJucyB7UHJvbWlzZX0gVGhlIG5ld2x5IGNyZWF0ZWQgcHJvbWlzZS4NCiAqLw0KZnVuY3Rpb24gJFFQcm92aWRlcigpIHsNCg0KICB0aGlzLiRnZXQgPSBbJyRyb290U2NvcGUnLCAnJGV4Y2VwdGlvbkhhbmRsZXInLCBmdW5jdGlvbigkcm9vdFNjb3BlLCAkZXhjZXB0aW9uSGFuZGxlcikgew0KICAgIHJldHVybiBxRmFjdG9yeShmdW5jdGlvbihjYWxsYmFjaykgew0KICAgICAgJHJvb3RTY29wZS4kZXZhbEFzeW5jKGNhbGxiYWNrKTsNCiAgICB9LCAkZXhjZXB0aW9uSGFuZGxlcik7DQogIH1dOw0KfQ0KDQpmdW5jdGlvbiAkJFFQcm92aWRlcigpIHsNCiAgdGhpcy4kZ2V0ID0gWyckYnJvd3NlcicsICckZXhjZXB0aW9uSGFuZGxlcicsIGZ1bmN0aW9uKCRicm93c2VyLCAkZXhjZXB0aW9uSGFuZGxlcikgew0KICAgIHJldHVybiBxRmFjdG9yeShmdW5jdGlvbihjYWxsYmFjaykgew0KICAgICAgJGJyb3dzZXIuZGVmZXIoY2FsbGJhY2spOw0KICAgIH0sICRleGNlcHRpb25IYW5kbGVyKTsNCiAgfV07DQp9DQoNCi8qKg0KICogQ29uc3RydWN0cyBhIHByb21pc2UgbWFuYWdlci4NCiAqDQogKiBAcGFyYW0ge2Z1bmN0aW9uKGZ1bmN0aW9uKX0gbmV4dFRpY2sgRnVuY3Rpb24gZm9yIGV4ZWN1dGluZyBmdW5jdGlvbnMgaW4gdGhlIG5leHQgdHVybi4NCiAqIEBwYXJhbSB7ZnVuY3Rpb24oLi4uKil9IGV4Y2VwdGlvbkhhbmRsZXIgRnVuY3Rpb24gaW50byB3aGljaCB1bmV4cGVjdGVkIGV4Y2VwdGlvbnMgYXJlIHBhc3NlZCBmb3INCiAqICAgICBkZWJ1Z2dpbmcgcHVycG9zZXMuDQogKiBAcmV0dXJucyB7b2JqZWN0fSBQcm9taXNlIG1hbmFnZXIuDQogKi8NCmZ1bmN0aW9uIHFGYWN0b3J5KG5leHRUaWNrLCBleGNlcHRpb25IYW5kbGVyKSB7DQogIHZhciAkcU1pbkVyciA9IG1pbkVycignJHEnLCBUeXBlRXJyb3IpOw0KICBmdW5jdGlvbiBjYWxsT25jZShzZWxmLCByZXNvbHZlRm4sIHJlamVjdEZuKSB7DQogICAgdmFyIGNhbGxlZCA9IGZhbHNlOw0KICAgIGZ1bmN0aW9uIHdyYXAoZm4pIHsNCiAgICAgIHJldHVybiBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICBpZiAoY2FsbGVkKSByZXR1cm47DQogICAgICAgIGNhbGxlZCA9IHRydWU7DQogICAgICAgIGZuLmNhbGwoc2VsZiwgdmFsdWUpOw0KICAgICAgfTsNCiAgICB9DQoNCiAgICByZXR1cm4gW3dyYXAocmVzb2x2ZUZuKSwgd3JhcChyZWplY3RGbildOw0KICB9DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgbmcuJHEjZGVmZXINCiAgICogQGtpbmQgZnVuY3Rpb24NCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIENyZWF0ZXMgYSBgRGVmZXJyZWRgIG9iamVjdCB3aGljaCByZXByZXNlbnRzIGEgdGFzayB3aGljaCB3aWxsIGZpbmlzaCBpbiB0aGUgZnV0dXJlLg0KICAgKg0KICAgKiBAcmV0dXJucyB7RGVmZXJyZWR9IFJldHVybnMgYSBuZXcgaW5zdGFuY2Ugb2YgZGVmZXJyZWQuDQogICAqLw0KICB2YXIgZGVmZXIgPSBmdW5jdGlvbigpIHsNCiAgICByZXR1cm4gbmV3IERlZmVycmVkKCk7DQogIH07DQoNCiAgZnVuY3Rpb24gUHJvbWlzZSgpIHsNCiAgICB0aGlzLiQkc3RhdGUgPSB7IHN0YXR1czogMCB9Ow0KICB9DQoNCiAgUHJvbWlzZS5wcm90b3R5cGUgPSB7DQogICAgdGhlbjogZnVuY3Rpb24ob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQsIHByb2dyZXNzQmFjaykgew0KICAgICAgdmFyIHJlc3VsdCA9IG5ldyBEZWZlcnJlZCgpOw0KDQogICAgICB0aGlzLiQkc3RhdGUucGVuZGluZyA9IHRoaXMuJCRzdGF0ZS5wZW5kaW5nIHx8IFtdOw0KICAgICAgdGhpcy4kJHN0YXRlLnBlbmRpbmcucHVzaChbcmVzdWx0LCBvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCwgcHJvZ3Jlc3NCYWNrXSk7DQogICAgICBpZiAodGhpcy4kJHN0YXRlLnN0YXR1cyA+IDApIHNjaGVkdWxlUHJvY2Vzc1F1ZXVlKHRoaXMuJCRzdGF0ZSk7DQoNCiAgICAgIHJldHVybiByZXN1bHQucHJvbWlzZTsNCiAgICB9LA0KDQogICAgImNhdGNoIjogZnVuY3Rpb24oY2FsbGJhY2spIHsNCiAgICAgIHJldHVybiB0aGlzLnRoZW4obnVsbCwgY2FsbGJhY2spOw0KICAgIH0sDQoNCiAgICAiZmluYWxseSI6IGZ1bmN0aW9uKGNhbGxiYWNrLCBwcm9ncmVzc0JhY2spIHsNCiAgICAgIHJldHVybiB0aGlzLnRoZW4oZnVuY3Rpb24odmFsdWUpIHsNCiAgICAgICAgcmV0dXJuIGhhbmRsZUNhbGxiYWNrKHZhbHVlLCB0cnVlLCBjYWxsYmFjayk7DQogICAgICB9LCBmdW5jdGlvbihlcnJvcikgew0KICAgICAgICByZXR1cm4gaGFuZGxlQ2FsbGJhY2soZXJyb3IsIGZhbHNlLCBjYWxsYmFjayk7DQogICAgICB9LCBwcm9ncmVzc0JhY2spOw0KICAgIH0NCiAgfTsNCg0KICAvL0Zhc3RlciwgbW9yZSBiYXNpYyB0aGFuIGFuZ3VsYXIuYmluZCBodHRwOi8vanNwZXJmLmNvbS9hbmd1bGFyLWJpbmQtdnMtY3VzdG9tLXZzLW5hdGl2ZQ0KICBmdW5jdGlvbiBzaW1wbGVCaW5kKGNvbnRleHQsIGZuKSB7DQogICAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgICBmbi5jYWxsKGNvbnRleHQsIHZhbHVlKTsNCiAgICB9Ow0KICB9DQoNCiAgZnVuY3Rpb24gcHJvY2Vzc1F1ZXVlKHN0YXRlKSB7DQogICAgdmFyIGZuLCBwcm9taXNlLCBwZW5kaW5nOw0KDQogICAgcGVuZGluZyA9IHN0YXRlLnBlbmRpbmc7DQogICAgc3RhdGUucHJvY2Vzc1NjaGVkdWxlZCA9IGZhbHNlOw0KICAgIHN0YXRlLnBlbmRpbmcgPSB1bmRlZmluZWQ7DQogICAgZm9yICh2YXIgaSA9IDAsIGlpID0gcGVuZGluZy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7DQogICAgICBwcm9taXNlID0gcGVuZGluZ1tpXVswXTsNCiAgICAgIGZuID0gcGVuZGluZ1tpXVtzdGF0ZS5zdGF0dXNdOw0KICAgICAgdHJ5IHsNCiAgICAgICAgaWYgKGlzRnVuY3Rpb24oZm4pKSB7DQogICAgICAgICAgcHJvbWlzZS5yZXNvbHZlKGZuKHN0YXRlLnZhbHVlKSk7DQogICAgICAgIH0gZWxzZSBpZiAoc3RhdGUuc3RhdHVzID09PSAxKSB7DQogICAgICAgICAgcHJvbWlzZS5yZXNvbHZlKHN0YXRlLnZhbHVlKTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBwcm9taXNlLnJlamVjdChzdGF0ZS52YWx1ZSk7DQogICAgICAgIH0NCiAgICAgIH0gY2F0Y2ggKGUpIHsNCiAgICAgICAgcHJvbWlzZS5yZWplY3QoZSk7DQogICAgICAgIGV4Y2VwdGlvbkhhbmRsZXIoZSk7DQogICAgICB9DQogICAgfQ0KICB9DQoNCiAgZnVuY3Rpb24gc2NoZWR1bGVQcm9jZXNzUXVldWUoc3RhdGUpIHsNCiAgICBpZiAoc3RhdGUucHJvY2Vzc1NjaGVkdWxlZCB8fCAhc3RhdGUucGVuZGluZykgcmV0dXJuOw0KICAgIHN0YXRlLnByb2Nlc3NTY2hlZHVsZWQgPSB0cnVlOw0KICAgIG5leHRUaWNrKGZ1bmN0aW9uKCkgeyBwcm9jZXNzUXVldWUoc3RhdGUpOyB9KTsNCiAgfQ0KDQogIGZ1bmN0aW9uIERlZmVycmVkKCkgew0KICAgIHRoaXMucHJvbWlzZSA9IG5ldyBQcm9taXNlKCk7DQogICAgLy9OZWNlc3NhcnkgdG8gc3VwcG9ydCB1bmJvdW5kIGV4ZWN1dGlvbiA6Lw0KICAgIHRoaXMucmVzb2x2ZSA9IHNpbXBsZUJpbmQodGhpcywgdGhpcy5yZXNvbHZlKTsNCiAgICB0aGlzLnJlamVjdCA9IHNpbXBsZUJpbmQodGhpcywgdGhpcy5yZWplY3QpOw0KICAgIHRoaXMubm90aWZ5ID0gc2ltcGxlQmluZCh0aGlzLCB0aGlzLm5vdGlmeSk7DQogIH0NCg0KICBEZWZlcnJlZC5wcm90b3R5cGUgPSB7DQogICAgcmVzb2x2ZTogZnVuY3Rpb24odmFsKSB7DQogICAgICBpZiAodGhpcy5wcm9taXNlLiQkc3RhdGUuc3RhdHVzKSByZXR1cm47DQogICAgICBpZiAodmFsID09PSB0aGlzLnByb21pc2UpIHsNCiAgICAgICAgdGhpcy4kJHJlamVjdCgkcU1pbkVycigNCiAgICAgICAgICAncWN5Y2xlJywNCiAgICAgICAgICAiRXhwZWN0ZWQgcHJvbWlzZSB0byBiZSByZXNvbHZlZCB3aXRoIHZhbHVlIG90aGVyIHRoYW4gaXRzZWxmICd7MH0nIiwNCiAgICAgICAgICB2YWwpKTsNCiAgICAgIH0NCiAgICAgIGVsc2Ugew0KICAgICAgICB0aGlzLiQkcmVzb2x2ZSh2YWwpOw0KICAgICAgfQ0KDQogICAgfSwNCg0KICAgICQkcmVzb2x2ZTogZnVuY3Rpb24odmFsKSB7DQogICAgICB2YXIgdGhlbiwgZm5zOw0KDQogICAgICBmbnMgPSBjYWxsT25jZSh0aGlzLCB0aGlzLiQkcmVzb2x2ZSwgdGhpcy4kJHJlamVjdCk7DQogICAgICB0cnkgew0KICAgICAgICBpZiAoKGlzT2JqZWN0KHZhbCkgfHwgaXNGdW5jdGlvbih2YWwpKSkgdGhlbiA9IHZhbCAmJiB2YWwudGhlbjsNCiAgICAgICAgaWYgKGlzRnVuY3Rpb24odGhlbikpIHsNCiAgICAgICAgICB0aGlzLnByb21pc2UuJCRzdGF0ZS5zdGF0dXMgPSAtMTsNCiAgICAgICAgICB0aGVuLmNhbGwodmFsLCBmbnNbMF0sIGZuc1sxXSwgdGhpcy5ub3RpZnkpOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIHRoaXMucHJvbWlzZS4kJHN0YXRlLnZhbHVlID0gdmFsOw0KICAgICAgICAgIHRoaXMucHJvbWlzZS4kJHN0YXRlLnN0YXR1cyA9IDE7DQogICAgICAgICAgc2NoZWR1bGVQcm9jZXNzUXVldWUodGhpcy5wcm9taXNlLiQkc3RhdGUpOw0KICAgICAgICB9DQogICAgICB9IGNhdGNoIChlKSB7DQogICAgICAgIGZuc1sxXShlKTsNCiAgICAgICAgZXhjZXB0aW9uSGFuZGxlcihlKTsNCiAgICAgIH0NCiAgICB9LA0KDQogICAgcmVqZWN0OiBmdW5jdGlvbihyZWFzb24pIHsNCiAgICAgIGlmICh0aGlzLnByb21pc2UuJCRzdGF0ZS5zdGF0dXMpIHJldHVybjsNCiAgICAgIHRoaXMuJCRyZWplY3QocmVhc29uKTsNCiAgICB9LA0KDQogICAgJCRyZWplY3Q6IGZ1bmN0aW9uKHJlYXNvbikgew0KICAgICAgdGhpcy5wcm9taXNlLiQkc3RhdGUudmFsdWUgPSByZWFzb247DQogICAgICB0aGlzLnByb21pc2UuJCRzdGF0ZS5zdGF0dXMgPSAyOw0KICAgICAgc2NoZWR1bGVQcm9jZXNzUXVldWUodGhpcy5wcm9taXNlLiQkc3RhdGUpOw0KICAgIH0sDQoNCiAgICBub3RpZnk6IGZ1bmN0aW9uKHByb2dyZXNzKSB7DQogICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5wcm9taXNlLiQkc3RhdGUucGVuZGluZzsNCg0KICAgICAgaWYgKCh0aGlzLnByb21pc2UuJCRzdGF0ZS5zdGF0dXMgPD0gMCkgJiYgY2FsbGJhY2tzICYmIGNhbGxiYWNrcy5sZW5ndGgpIHsNCiAgICAgICAgbmV4dFRpY2soZnVuY3Rpb24oKSB7DQogICAgICAgICAgdmFyIGNhbGxiYWNrLCByZXN1bHQ7DQogICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gY2FsbGJhY2tzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsNCiAgICAgICAgICAgIHJlc3VsdCA9IGNhbGxiYWNrc1tpXVswXTsNCiAgICAgICAgICAgIGNhbGxiYWNrID0gY2FsbGJhY2tzW2ldWzNdOw0KICAgICAgICAgICAgdHJ5IHsNCiAgICAgICAgICAgICAgcmVzdWx0Lm5vdGlmeShpc0Z1bmN0aW9uKGNhbGxiYWNrKSA/IGNhbGxiYWNrKHByb2dyZXNzKSA6IHByb2dyZXNzKTsNCiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHsNCiAgICAgICAgICAgICAgZXhjZXB0aW9uSGFuZGxlcihlKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9DQogICAgICAgIH0pOw0KICAgICAgfQ0KICAgIH0NCiAgfTsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkcSNyZWplY3QNCiAgICogQGtpbmQgZnVuY3Rpb24NCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIENyZWF0ZXMgYSBwcm9taXNlIHRoYXQgaXMgcmVzb2x2ZWQgYXMgcmVqZWN0ZWQgd2l0aCB0aGUgc3BlY2lmaWVkIGByZWFzb25gLiBUaGlzIGFwaSBzaG91bGQgYmUNCiAgICogdXNlZCB0byBmb3J3YXJkIHJlamVjdGlvbiBpbiBhIGNoYWluIG9mIHByb21pc2VzLiBJZiB5b3UgYXJlIGRlYWxpbmcgd2l0aCB0aGUgbGFzdCBwcm9taXNlIGluDQogICAqIGEgcHJvbWlzZSBjaGFpbiwgeW91IGRvbid0IG5lZWQgdG8gd29ycnkgYWJvdXQgaXQuDQogICAqDQogICAqIFdoZW4gY29tcGFyaW5nIGRlZmVycmVkcy9wcm9taXNlcyB0byB0aGUgZmFtaWxpYXIgYmVoYXZpb3Igb2YgdHJ5L2NhdGNoL3Rocm93LCB0aGluayBvZg0KICAgKiBgcmVqZWN0YCBhcyB0aGUgYHRocm93YCBrZXl3b3JkIGluIEphdmFTY3JpcHQuIFRoaXMgYWxzbyBtZWFucyB0aGF0IGlmIHlvdSAiY2F0Y2giIGFuIGVycm9yIHZpYQ0KICAgKiBhIHByb21pc2UgZXJyb3IgY2FsbGJhY2sgYW5kIHlvdSB3YW50IHRvIGZvcndhcmQgdGhlIGVycm9yIHRvIHRoZSBwcm9taXNlIGRlcml2ZWQgZnJvbSB0aGUNCiAgICogY3VycmVudCBwcm9taXNlLCB5b3UgaGF2ZSB0byAicmV0aHJvdyIgdGhlIGVycm9yIGJ5IHJldHVybmluZyBhIHJlamVjdGlvbiBjb25zdHJ1Y3RlZCB2aWENCiAgICogYHJlamVjdGAuDQogICAqDQogICAqIGBgYGpzDQogICAqICAgcHJvbWlzZUIgPSBwcm9taXNlQS50aGVuKGZ1bmN0aW9uKHJlc3VsdCkgew0KICAgKiAgICAgLy8gc3VjY2VzczogZG8gc29tZXRoaW5nIGFuZCByZXNvbHZlIHByb21pc2VCDQogICAqICAgICAvLyAgICAgICAgICB3aXRoIHRoZSBvbGQgb3IgYSBuZXcgcmVzdWx0DQogICAqICAgICByZXR1cm4gcmVzdWx0Ow0KICAgKiAgIH0sIGZ1bmN0aW9uKHJlYXNvbikgew0KICAgKiAgICAgLy8gZXJyb3I6IGhhbmRsZSB0aGUgZXJyb3IgaWYgcG9zc2libGUgYW5kDQogICAqICAgICAvLyAgICAgICAgcmVzb2x2ZSBwcm9taXNlQiB3aXRoIG5ld1Byb21pc2VPclZhbHVlLA0KICAgKiAgICAgLy8gICAgICAgIG90aGVyd2lzZSBmb3J3YXJkIHRoZSByZWplY3Rpb24gdG8gcHJvbWlzZUINCiAgICogICAgIGlmIChjYW5IYW5kbGUocmVhc29uKSkgew0KICAgKiAgICAgIC8vIGhhbmRsZSB0aGUgZXJyb3IgYW5kIHJlY292ZXINCiAgICogICAgICByZXR1cm4gbmV3UHJvbWlzZU9yVmFsdWU7DQogICAqICAgICB9DQogICAqICAgICByZXR1cm4gJHEucmVqZWN0KHJlYXNvbik7DQogICAqICAgfSk7DQogICAqIGBgYA0KICAgKg0KICAgKiBAcGFyYW0geyp9IHJlYXNvbiBDb25zdGFudCwgbWVzc2FnZSwgZXhjZXB0aW9uIG9yIGFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIHJlamVjdGlvbiByZWFzb24uDQogICAqIEByZXR1cm5zIHtQcm9taXNlfSBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHdhcyBhbHJlYWR5IHJlc29sdmVkIGFzIHJlamVjdGVkIHdpdGggdGhlIGByZWFzb25gLg0KICAgKi8NCiAgdmFyIHJlamVjdCA9IGZ1bmN0aW9uKHJlYXNvbikgew0KICAgIHZhciByZXN1bHQgPSBuZXcgRGVmZXJyZWQoKTsNCiAgICByZXN1bHQucmVqZWN0KHJlYXNvbik7DQogICAgcmV0dXJuIHJlc3VsdC5wcm9taXNlOw0KICB9Ow0KDQogIHZhciBtYWtlUHJvbWlzZSA9IGZ1bmN0aW9uIG1ha2VQcm9taXNlKHZhbHVlLCByZXNvbHZlZCkgew0KICAgIHZhciByZXN1bHQgPSBuZXcgRGVmZXJyZWQoKTsNCiAgICBpZiAocmVzb2x2ZWQpIHsNCiAgICAgIHJlc3VsdC5yZXNvbHZlKHZhbHVlKTsNCiAgICB9IGVsc2Ugew0KICAgICAgcmVzdWx0LnJlamVjdCh2YWx1ZSk7DQogICAgfQ0KICAgIHJldHVybiByZXN1bHQucHJvbWlzZTsNCiAgfTsNCg0KICB2YXIgaGFuZGxlQ2FsbGJhY2sgPSBmdW5jdGlvbiBoYW5kbGVDYWxsYmFjayh2YWx1ZSwgaXNSZXNvbHZlZCwgY2FsbGJhY2spIHsNCiAgICB2YXIgY2FsbGJhY2tPdXRwdXQgPSBudWxsOw0KICAgIHRyeSB7DQogICAgICBpZiAoaXNGdW5jdGlvbihjYWxsYmFjaykpIGNhbGxiYWNrT3V0cHV0ID0gY2FsbGJhY2soKTsNCiAgICB9IGNhdGNoIChlKSB7DQogICAgICByZXR1cm4gbWFrZVByb21pc2UoZSwgZmFsc2UpOw0KICAgIH0NCiAgICBpZiAoaXNQcm9taXNlTGlrZShjYWxsYmFja091dHB1dCkpIHsNCiAgICAgIHJldHVybiBjYWxsYmFja091dHB1dC50aGVuKGZ1bmN0aW9uKCkgew0KICAgICAgICByZXR1cm4gbWFrZVByb21pc2UodmFsdWUsIGlzUmVzb2x2ZWQpOw0KICAgICAgfSwgZnVuY3Rpb24oZXJyb3IpIHsNCiAgICAgICAgcmV0dXJuIG1ha2VQcm9taXNlKGVycm9yLCBmYWxzZSk7DQogICAgICB9KTsNCiAgICB9IGVsc2Ugew0KICAgICAgcmV0dXJuIG1ha2VQcm9taXNlKHZhbHVlLCBpc1Jlc29sdmVkKTsNCiAgICB9DQogIH07DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgJHEjd2hlbg0KICAgKiBAa2luZCBmdW5jdGlvbg0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogV3JhcHMgYW4gb2JqZWN0IHRoYXQgbWlnaHQgYmUgYSB2YWx1ZSBvciBhICgzcmQgcGFydHkpIHRoZW4tYWJsZSBwcm9taXNlIGludG8gYSAkcSBwcm9taXNlLg0KICAgKiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdSBhcmUgZGVhbGluZyB3aXRoIGFuIG9iamVjdCB0aGF0IG1pZ2h0IG9yIG1pZ2h0IG5vdCBiZSBhIHByb21pc2UsIG9yIGlmDQogICAqIHRoZSBwcm9taXNlIGNvbWVzIGZyb20gYSBzb3VyY2UgdGhhdCBjYW4ndCBiZSB0cnVzdGVkLg0KICAgKg0KICAgKiBAcGFyYW0geyp9IHZhbHVlIFZhbHVlIG9yIGEgcHJvbWlzZQ0KICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gUmV0dXJucyBhIHByb21pc2Ugb2YgdGhlIHBhc3NlZCB2YWx1ZSBvciBwcm9taXNlDQogICAqLw0KDQoNCiAgdmFyIHdoZW4gPSBmdW5jdGlvbih2YWx1ZSwgY2FsbGJhY2ssIGVycmJhY2ssIHByb2dyZXNzQmFjaykgew0KICAgIHZhciByZXN1bHQgPSBuZXcgRGVmZXJyZWQoKTsNCiAgICByZXN1bHQucmVzb2x2ZSh2YWx1ZSk7DQogICAgcmV0dXJuIHJlc3VsdC5wcm9taXNlLnRoZW4oY2FsbGJhY2ssIGVycmJhY2ssIHByb2dyZXNzQmFjayk7DQogIH07DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgJHEjYWxsDQogICAqIEBraW5kIGZ1bmN0aW9uDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBDb21iaW5lcyBtdWx0aXBsZSBwcm9taXNlcyBpbnRvIGEgc2luZ2xlIHByb21pc2UgdGhhdCBpcyByZXNvbHZlZCB3aGVuIGFsbCBvZiB0aGUgaW5wdXQNCiAgICogcHJvbWlzZXMgYXJlIHJlc29sdmVkLg0KICAgKg0KICAgKiBAcGFyYW0ge0FycmF5LjxQcm9taXNlPnxPYmplY3QuPFByb21pc2U+fSBwcm9taXNlcyBBbiBhcnJheSBvciBoYXNoIG9mIHByb21pc2VzLg0KICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gUmV0dXJucyBhIHNpbmdsZSBwcm9taXNlIHRoYXQgd2lsbCBiZSByZXNvbHZlZCB3aXRoIGFuIGFycmF5L2hhc2ggb2YgdmFsdWVzLA0KICAgKiAgIGVhY2ggdmFsdWUgY29ycmVzcG9uZGluZyB0byB0aGUgcHJvbWlzZSBhdCB0aGUgc2FtZSBpbmRleC9rZXkgaW4gdGhlIGBwcm9taXNlc2AgYXJyYXkvaGFzaC4NCiAgICogICBJZiBhbnkgb2YgdGhlIHByb21pc2VzIGlzIHJlc29sdmVkIHdpdGggYSByZWplY3Rpb24sIHRoaXMgcmVzdWx0aW5nIHByb21pc2Ugd2lsbCBiZSByZWplY3RlZA0KICAgKiAgIHdpdGggdGhlIHNhbWUgcmVqZWN0aW9uIHZhbHVlLg0KICAgKi8NCg0KICBmdW5jdGlvbiBhbGwocHJvbWlzZXMpIHsNCiAgICB2YXIgZGVmZXJyZWQgPSBuZXcgRGVmZXJyZWQoKSwNCiAgICAgICAgY291bnRlciA9IDAsDQogICAgICAgIHJlc3VsdHMgPSBpc0FycmF5KHByb21pc2VzKSA/IFtdIDoge307DQoNCiAgICBmb3JFYWNoKHByb21pc2VzLCBmdW5jdGlvbihwcm9taXNlLCBrZXkpIHsNCiAgICAgIGNvdW50ZXIrKzsNCiAgICAgIHdoZW4ocHJvbWlzZSkudGhlbihmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICBpZiAocmVzdWx0cy5oYXNPd25Qcm9wZXJ0eShrZXkpKSByZXR1cm47DQogICAgICAgIHJlc3VsdHNba2V5XSA9IHZhbHVlOw0KICAgICAgICBpZiAoISgtLWNvdW50ZXIpKSBkZWZlcnJlZC5yZXNvbHZlKHJlc3VsdHMpOw0KICAgICAgfSwgZnVuY3Rpb24ocmVhc29uKSB7DQogICAgICAgIGlmIChyZXN1bHRzLmhhc093blByb3BlcnR5KGtleSkpIHJldHVybjsNCiAgICAgICAgZGVmZXJyZWQucmVqZWN0KHJlYXNvbik7DQogICAgICB9KTsNCiAgICB9KTsNCg0KICAgIGlmIChjb3VudGVyID09PSAwKSB7DQogICAgICBkZWZlcnJlZC5yZXNvbHZlKHJlc3VsdHMpOw0KICAgIH0NCg0KICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlOw0KICB9DQoNCiAgdmFyICRRID0gZnVuY3Rpb24gUShyZXNvbHZlcikgew0KICAgIGlmICghaXNGdW5jdGlvbihyZXNvbHZlcikpIHsNCiAgICAgIHRocm93ICRxTWluRXJyKCdub3JzbHZyJywgIkV4cGVjdGVkIHJlc29sdmVyRm4sIGdvdCAnezB9JyIsIHJlc29sdmVyKTsNCiAgICB9DQoNCiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUSkpIHsNCiAgICAgIC8vIE1vcmUgdXNlZnVsIHdoZW4gJFEgaXMgdGhlIFByb21pc2UgaXRzZWxmLg0KICAgICAgcmV0dXJuIG5ldyBRKHJlc29sdmVyKTsNCiAgICB9DQoNCiAgICB2YXIgZGVmZXJyZWQgPSBuZXcgRGVmZXJyZWQoKTsNCg0KICAgIGZ1bmN0aW9uIHJlc29sdmVGbih2YWx1ZSkgew0KICAgICAgZGVmZXJyZWQucmVzb2x2ZSh2YWx1ZSk7DQogICAgfQ0KDQogICAgZnVuY3Rpb24gcmVqZWN0Rm4ocmVhc29uKSB7DQogICAgICBkZWZlcnJlZC5yZWplY3QocmVhc29uKTsNCiAgICB9DQoNCiAgICByZXNvbHZlcihyZXNvbHZlRm4sIHJlamVjdEZuKTsNCg0KICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlOw0KICB9Ow0KDQogICRRLmRlZmVyID0gZGVmZXI7DQogICRRLnJlamVjdCA9IHJlamVjdDsNCiAgJFEud2hlbiA9IHdoZW47DQogICRRLmFsbCA9IGFsbDsNCg0KICByZXR1cm4gJFE7DQp9DQoNCmZ1bmN0aW9uICQkUkFGUHJvdmlkZXIoKSB7IC8vckFGDQogIHRoaXMuJGdldCA9IFsnJHdpbmRvdycsICckdGltZW91dCcsIGZ1bmN0aW9uKCR3aW5kb3csICR0aW1lb3V0KSB7DQogICAgdmFyIHJlcXVlc3RBbmltYXRpb25GcmFtZSA9ICR3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR3aW5kb3cud2Via2l0UmVxdWVzdEFuaW1hdGlvbkZyYW1lOw0KDQogICAgdmFyIGNhbmNlbEFuaW1hdGlvbkZyYW1lID0gJHdpbmRvdy5jYW5jZWxBbmltYXRpb25GcmFtZSB8fA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR3aW5kb3cud2Via2l0Q2FuY2VsQW5pbWF0aW9uRnJhbWUgfHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkd2luZG93LndlYmtpdENhbmNlbFJlcXVlc3RBbmltYXRpb25GcmFtZTsNCg0KICAgIHZhciByYWZTdXBwb3J0ZWQgPSAhIXJlcXVlc3RBbmltYXRpb25GcmFtZTsNCiAgICB2YXIgcmFmID0gcmFmU3VwcG9ydGVkDQogICAgICA/IGZ1bmN0aW9uKGZuKSB7DQogICAgICAgICAgdmFyIGlkID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKGZuKTsNCiAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBjYW5jZWxBbmltYXRpb25GcmFtZShpZCk7DQogICAgICAgICAgfTsNCiAgICAgICAgfQ0KICAgICAgOiBmdW5jdGlvbihmbikgew0KICAgICAgICAgIHZhciB0aW1lciA9ICR0aW1lb3V0KGZuLCAxNi42NiwgZmFsc2UpOyAvLyAxMDAwIC8gNjAgPSAxNi42NjYNCiAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAkdGltZW91dC5jYW5jZWwodGltZXIpOw0KICAgICAgICAgIH07DQogICAgICAgIH07DQoNCiAgICByYWYuc3VwcG9ydGVkID0gcmFmU3VwcG9ydGVkOw0KDQogICAgcmV0dXJuIHJhZjsNCiAgfV07DQp9DQoNCi8qKg0KICogREVTSUdOIE5PVEVTDQogKg0KICogVGhlIGRlc2lnbiBkZWNpc2lvbnMgYmVoaW5kIHRoZSBzY29wZSBhcmUgaGVhdmlseSBmYXZvcmVkIGZvciBzcGVlZCBhbmQgbWVtb3J5IGNvbnN1bXB0aW9uLg0KICoNCiAqIFRoZSB0eXBpY2FsIHVzZSBvZiBzY29wZSBpcyB0byB3YXRjaCB0aGUgZXhwcmVzc2lvbnMsIHdoaWNoIG1vc3Qgb2YgdGhlIHRpbWUgcmV0dXJuIHRoZSBzYW1lDQogKiB2YWx1ZSBhcyBsYXN0IHRpbWUgc28gd2Ugb3B0aW1pemUgdGhlIG9wZXJhdGlvbi4NCiAqDQogKiBDbG9zdXJlcyBjb25zdHJ1Y3Rpb24gaXMgZXhwZW5zaXZlIGluIHRlcm1zIG9mIHNwZWVkIGFzIHdlbGwgYXMgbWVtb3J5Og0KICogICAtIE5vIGNsb3N1cmVzLCBpbnN0ZWFkIHVzZSBwcm90b3R5cGljYWwgaW5oZXJpdGFuY2UgZm9yIEFQSQ0KICogICAtIEludGVybmFsIHN0YXRlIG5lZWRzIHRvIGJlIHN0b3JlZCBvbiBzY29wZSBkaXJlY3RseSwgd2hpY2ggbWVhbnMgdGhhdCBwcml2YXRlIHN0YXRlIGlzDQogKiAgICAgZXhwb3NlZCBhcyAkJF9fX18gcHJvcGVydGllcw0KICoNCiAqIExvb3Agb3BlcmF0aW9ucyBhcmUgb3B0aW1pemVkIGJ5IHVzaW5nIHdoaWxlKGNvdW50LS0pIHsgLi4uIH0NCiAqICAgLSB0aGlzIG1lYW5zIHRoYXQgaW4gb3JkZXIgdG8ga2VlcCB0aGUgc2FtZSBvcmRlciBvZiBleGVjdXRpb24gYXMgYWRkaXRpb24gd2UgaGF2ZSB0byBhZGQNCiAqICAgICBpdGVtcyB0byB0aGUgYXJyYXkgYXQgdGhlIGJlZ2lubmluZyAodW5zaGlmdCkgaW5zdGVhZCBvZiBhdCB0aGUgZW5kIChwdXNoKQ0KICoNCiAqIENoaWxkIHNjb3BlcyBhcmUgY3JlYXRlZCBhbmQgcmVtb3ZlZCBvZnRlbg0KICogICAtIFVzaW5nIGFuIGFycmF5IHdvdWxkIGJlIHNsb3cgc2luY2UgaW5zZXJ0cyBpbiBtaWRkbGUgYXJlIGV4cGVuc2l2ZSBzbyB3ZSB1c2UgbGlua2VkIGxpc3QNCiAqDQogKiBUaGVyZSBhcmUgZmV3IHdhdGNoZXMgdGhlbiBhIGxvdCBvZiBvYnNlcnZlcnMuIFRoaXMgaXMgd2h5IHlvdSBkb24ndCB3YW50IHRoZSBvYnNlcnZlciB0byBiZQ0KICogaW1wbGVtZW50ZWQgaW4gdGhlIHNhbWUgd2F5IGFzIHdhdGNoLiBXYXRjaCByZXF1aXJlcyByZXR1cm4gb2YgaW5pdGlhbGl6YXRpb24gZnVuY3Rpb24gd2hpY2gNCiAqIGFyZSBleHBlbnNpdmUgdG8gY29uc3RydWN0Lg0KICovDQoNCg0KLyoqDQogKiBAbmdkb2MgcHJvdmlkZXINCiAqIEBuYW1lICRyb290U2NvcGVQcm92aWRlcg0KICogQGRlc2NyaXB0aW9uDQogKg0KICogUHJvdmlkZXIgZm9yIHRoZSAkcm9vdFNjb3BlIHNlcnZpY2UuDQogKi8NCg0KLyoqDQogKiBAbmdkb2MgbWV0aG9kDQogKiBAbmFtZSAkcm9vdFNjb3BlUHJvdmlkZXIjZGlnZXN0VHRsDQogKiBAZGVzY3JpcHRpb24NCiAqDQogKiBTZXRzIHRoZSBudW1iZXIgb2YgYCRkaWdlc3RgIGl0ZXJhdGlvbnMgdGhlIHNjb3BlIHNob3VsZCBhdHRlbXB0IHRvIGV4ZWN1dGUgYmVmb3JlIGdpdmluZyB1cCBhbmQNCiAqIGFzc3VtaW5nIHRoYXQgdGhlIG1vZGVsIGlzIHVuc3RhYmxlLg0KICoNCiAqIFRoZSBjdXJyZW50IGRlZmF1bHQgaXMgMTAgaXRlcmF0aW9ucy4NCiAqDQogKiBJbiBjb21wbGV4IGFwcGxpY2F0aW9ucyBpdCdzIHBvc3NpYmxlIHRoYXQgdGhlIGRlcGVuZGVuY2llcyBiZXR3ZWVuIGAkd2F0Y2hgcyB3aWxsIHJlc3VsdCBpbg0KICogc2V2ZXJhbCBkaWdlc3QgaXRlcmF0aW9ucy4gSG93ZXZlciBpZiBhbiBhcHBsaWNhdGlvbiBuZWVkcyBtb3JlIHRoYW4gdGhlIGRlZmF1bHQgMTAgZGlnZXN0DQogKiBpdGVyYXRpb25zIGZvciBpdHMgbW9kZWwgdG8gc3RhYmlsaXplIHRoZW4geW91IHNob3VsZCBpbnZlc3RpZ2F0ZSB3aGF0IGlzIGNhdXNpbmcgdGhlIG1vZGVsIHRvDQogKiBjb250aW51b3VzbHkgY2hhbmdlIGR1cmluZyB0aGUgZGlnZXN0Lg0KICoNCiAqIEluY3JlYXNpbmcgdGhlIFRUTCBjb3VsZCBoYXZlIHBlcmZvcm1hbmNlIGltcGxpY2F0aW9ucywgc28geW91IHNob3VsZCBub3QgY2hhbmdlIGl0IHdpdGhvdXQNCiAqIHByb3BlciBqdXN0aWZpY2F0aW9uLg0KICoNCiAqIEBwYXJhbSB7bnVtYmVyfSBsaW1pdCBUaGUgbnVtYmVyIG9mIGRpZ2VzdCBpdGVyYXRpb25zLg0KICovDQoNCg0KLyoqDQogKiBAbmdkb2Mgc2VydmljZQ0KICogQG5hbWUgJHJvb3RTY29wZQ0KICogQGRlc2NyaXB0aW9uDQogKg0KICogRXZlcnkgYXBwbGljYXRpb24gaGFzIGEgc2luZ2xlIHJvb3Qge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUgc2NvcGV9Lg0KICogQWxsIG90aGVyIHNjb3BlcyBhcmUgZGVzY2VuZGFudCBzY29wZXMgb2YgdGhlIHJvb3Qgc2NvcGUuIFNjb3BlcyBwcm92aWRlIHNlcGFyYXRpb24NCiAqIGJldHdlZW4gdGhlIG1vZGVsIGFuZCB0aGUgdmlldywgdmlhIGEgbWVjaGFuaXNtIGZvciB3YXRjaGluZyB0aGUgbW9kZWwgZm9yIGNoYW5nZXMuDQogKiBUaGV5IGFsc28gcHJvdmlkZSBhbiBldmVudCBlbWlzc2lvbi9icm9hZGNhc3QgYW5kIHN1YnNjcmlwdGlvbiBmYWNpbGl0eS4gU2VlIHRoZQ0KICoge0BsaW5rIGd1aWRlL3Njb3BlIGRldmVsb3BlciBndWlkZSBvbiBzY29wZXN9Lg0KICovDQpmdW5jdGlvbiAkUm9vdFNjb3BlUHJvdmlkZXIoKSB7DQogIHZhciBUVEwgPSAxMDsNCiAgdmFyICRyb290U2NvcGVNaW5FcnIgPSBtaW5FcnIoJyRyb290U2NvcGUnKTsNCiAgdmFyIGxhc3REaXJ0eVdhdGNoID0gbnVsbDsNCiAgdmFyIGFwcGx5QXN5bmNJZCA9IG51bGw7DQoNCiAgdGhpcy5kaWdlc3RUdGwgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgIGlmIChhcmd1bWVudHMubGVuZ3RoKSB7DQogICAgICBUVEwgPSB2YWx1ZTsNCiAgICB9DQogICAgcmV0dXJuIFRUTDsNCiAgfTsNCg0KICB0aGlzLiRnZXQgPSBbJyRpbmplY3RvcicsICckZXhjZXB0aW9uSGFuZGxlcicsICckcGFyc2UnLCAnJGJyb3dzZXInLA0KICAgICAgZnVuY3Rpb24oJGluamVjdG9yLCAkZXhjZXB0aW9uSGFuZGxlciwgJHBhcnNlLCAkYnJvd3Nlcikgew0KDQogICAgLyoqDQogICAgICogQG5nZG9jIHR5cGUNCiAgICAgKiBAbmFtZSAkcm9vdFNjb3BlLlNjb3BlDQogICAgICoNCiAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgKiBBIHJvb3Qgc2NvcGUgY2FuIGJlIHJldHJpZXZlZCB1c2luZyB0aGUge0BsaW5rIG5nLiRyb290U2NvcGUgJHJvb3RTY29wZX0ga2V5IGZyb20gdGhlDQogICAgICoge0BsaW5rIGF1dG8uJGluamVjdG9yICRpbmplY3Rvcn0uIENoaWxkIHNjb3BlcyBhcmUgY3JlYXRlZCB1c2luZyB0aGUNCiAgICAgKiB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSMkbmV3ICRuZXcoKX0gbWV0aG9kLiAoTW9zdCBzY29wZXMgYXJlIGNyZWF0ZWQgYXV0b21hdGljYWxseSB3aGVuDQogICAgICogY29tcGlsZWQgSFRNTCB0ZW1wbGF0ZSBpcyBleGVjdXRlZC4pDQogICAgICoNCiAgICAgKiBIZXJlIGlzIGEgc2ltcGxlIHNjb3BlIHNuaXBwZXQgdG8gc2hvdyBob3cgeW91IGNhbiBpbnRlcmFjdCB3aXRoIHRoZSBzY29wZS4NCiAgICAgKiBgYGBodG1sDQogICAgICogPGZpbGUgc3JjPSIuL3Rlc3Qvbmcvcm9vdFNjb3BlU3BlYy5qcyIgdGFnPSJkb2NzMSIgLz4NCiAgICAgKiBgYGANCiAgICAgKg0KICAgICAqICMgSW5oZXJpdGFuY2UNCiAgICAgKiBBIHNjb3BlIGNhbiBpbmhlcml0IGZyb20gYSBwYXJlbnQgc2NvcGUsIGFzIGluIHRoaXMgZXhhbXBsZToNCiAgICAgKiBgYGBqcw0KICAgICAgICAgdmFyIHBhcmVudCA9ICRyb290U2NvcGU7DQogICAgICAgICB2YXIgY2hpbGQgPSBwYXJlbnQuJG5ldygpOw0KDQogICAgICAgICBwYXJlbnQuc2FsdXRhdGlvbiA9ICJIZWxsbyI7DQogICAgICAgICBleHBlY3QoY2hpbGQuc2FsdXRhdGlvbikudG9FcXVhbCgnSGVsbG8nKTsNCg0KICAgICAgICAgY2hpbGQuc2FsdXRhdGlvbiA9ICJXZWxjb21lIjsNCiAgICAgICAgIGV4cGVjdChjaGlsZC5zYWx1dGF0aW9uKS50b0VxdWFsKCdXZWxjb21lJyk7DQogICAgICAgICBleHBlY3QocGFyZW50LnNhbHV0YXRpb24pLnRvRXF1YWwoJ0hlbGxvJyk7DQogICAgICogYGBgDQogICAgICoNCiAgICAgKiBXaGVuIGludGVyYWN0aW5nIHdpdGggYFNjb3BlYCBpbiB0ZXN0cywgYWRkaXRpb25hbCBoZWxwZXIgbWV0aG9kcyBhcmUgYXZhaWxhYmxlIG9uIHRoZQ0KICAgICAqIGluc3RhbmNlcyBvZiBgU2NvcGVgIHR5cGUuIFNlZSB7QGxpbmsgbmdNb2NrLiRyb290U2NvcGUuU2NvcGUgbmdNb2NrIFNjb3BlfSBmb3IgYWRkaXRpb25hbA0KICAgICAqIGRldGFpbHMuDQogICAgICoNCiAgICAgKg0KICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsIGZ1bmN0aW9uKCk+PX0gcHJvdmlkZXJzIE1hcCBvZiBzZXJ2aWNlIGZhY3Rvcnkgd2hpY2ggbmVlZCB0byBiZQ0KICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvdmlkZWQgZm9yIHRoZSBjdXJyZW50IHNjb3BlLiBEZWZhdWx0cyB0byB7QGxpbmsgbmd9Lg0KICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsICo+PX0gaW5zdGFuY2VDYWNoZSBQcm92aWRlcyBwcmUtaW5zdGFudGlhdGVkIHNlcnZpY2VzIHdoaWNoIHNob3VsZA0KICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwZW5kL292ZXJyaWRlIHNlcnZpY2VzIHByb3ZpZGVkIGJ5IGBwcm92aWRlcnNgLiBUaGlzIGlzIGhhbmR5DQogICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGVuIHVuaXQtdGVzdGluZyBhbmQgaGF2aW5nIHRoZSBuZWVkIHRvIG92ZXJyaWRlIGEgZGVmYXVsdA0KICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VydmljZS4NCiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBOZXdseSBjcmVhdGVkIHNjb3BlLg0KICAgICAqDQogICAgICovDQogICAgZnVuY3Rpb24gU2NvcGUoKSB7DQogICAgICB0aGlzLiRpZCA9IG5leHRVaWQoKTsNCiAgICAgIHRoaXMuJCRwaGFzZSA9IHRoaXMuJHBhcmVudCA9IHRoaXMuJCR3YXRjaGVycyA9DQogICAgICAgICAgICAgICAgICAgICB0aGlzLiQkbmV4dFNpYmxpbmcgPSB0aGlzLiQkcHJldlNpYmxpbmcgPQ0KICAgICAgICAgICAgICAgICAgICAgdGhpcy4kJGNoaWxkSGVhZCA9IHRoaXMuJCRjaGlsZFRhaWwgPSBudWxsOw0KICAgICAgdGhpcy4kcm9vdCA9IHRoaXM7DQogICAgICB0aGlzLiQkZGVzdHJveWVkID0gZmFsc2U7DQogICAgICB0aGlzLiQkbGlzdGVuZXJzID0ge307DQogICAgICB0aGlzLiQkbGlzdGVuZXJDb3VudCA9IHt9Ow0KICAgICAgdGhpcy4kJGlzb2xhdGVCaW5kaW5ncyA9IG51bGw7DQogICAgfQ0KDQogICAgLyoqDQogICAgICogQG5nZG9jIHByb3BlcnR5DQogICAgICogQG5hbWUgJHJvb3RTY29wZS5TY29wZSMkaWQNCiAgICAgKg0KICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAqIFVuaXF1ZSBzY29wZSBJRCAobW9ub3RvbmljYWxseSBpbmNyZWFzaW5nKSB1c2VmdWwgZm9yIGRlYnVnZ2luZy4NCiAgICAgKi8NCg0KICAgICAvKioNCiAgICAgICogQG5nZG9jIHByb3BlcnR5DQogICAgICAqIEBuYW1lICRyb290U2NvcGUuU2NvcGUjJHBhcmVudA0KICAgICAgKg0KICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICogUmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgc2NvcGUuDQogICAgICAqLw0KDQogICAgICAvKioNCiAgICAgICAqIEBuZ2RvYyBwcm9wZXJ0eQ0KICAgICAgICogQG5hbWUgJHJvb3RTY29wZS5TY29wZSMkcm9vdA0KICAgICAgICoNCiAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICogUmVmZXJlbmNlIHRvIHRoZSByb290IHNjb3BlLg0KICAgICAgICovDQoNCiAgICBTY29wZS5wcm90b3R5cGUgPSB7DQogICAgICBjb25zdHJ1Y3RvcjogU2NvcGUsDQogICAgICAvKioNCiAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAqIEBuYW1lICRyb290U2NvcGUuU2NvcGUjJG5ldw0KICAgICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgICAqDQogICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAqIENyZWF0ZXMgYSBuZXcgY2hpbGQge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUgc2NvcGV9Lg0KICAgICAgICoNCiAgICAgICAqIFRoZSBwYXJlbnQgc2NvcGUgd2lsbCBwcm9wYWdhdGUgdGhlIHtAbGluayBuZy4kcm9vdFNjb3BlLlNjb3BlIyRkaWdlc3QgJGRpZ2VzdCgpfSBldmVudC4NCiAgICAgICAqIFRoZSBzY29wZSBjYW4gYmUgcmVtb3ZlZCBmcm9tIHRoZSBzY29wZSBoaWVyYXJjaHkgdXNpbmcge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJGRlc3Ryb3kgJGRlc3Ryb3koKX0uDQogICAgICAgKg0KICAgICAgICoge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJGRlc3Ryb3kgJGRlc3Ryb3koKX0gbXVzdCBiZSBjYWxsZWQgb24gYSBzY29wZSB3aGVuIGl0IGlzDQogICAgICAgKiBkZXNpcmVkIGZvciB0aGUgc2NvcGUgYW5kIGl0cyBjaGlsZCBzY29wZXMgdG8gYmUgcGVybWFuZW50bHkgZGV0YWNoZWQgZnJvbSB0aGUgcGFyZW50IGFuZA0KICAgICAgICogdGh1cyBzdG9wIHBhcnRpY2lwYXRpbmcgaW4gbW9kZWwgY2hhbmdlIGRldGVjdGlvbiBhbmQgbGlzdGVuZXIgbm90aWZpY2F0aW9uIGJ5IGludm9raW5nLg0KICAgICAgICoNCiAgICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNvbGF0ZSBJZiB0cnVlLCB0aGVuIHRoZSBzY29wZSBkb2VzIG5vdCBwcm90b3R5cGljYWxseSBpbmhlcml0IGZyb20gdGhlDQogICAgICAgKiAgICAgICAgIHBhcmVudCBzY29wZS4gVGhlIHNjb3BlIGlzIGlzb2xhdGVkLCBhcyBpdCBjYW4gbm90IHNlZSBwYXJlbnQgc2NvcGUgcHJvcGVydGllcy4NCiAgICAgICAqICAgICAgICAgV2hlbiBjcmVhdGluZyB3aWRnZXRzLCBpdCBpcyB1c2VmdWwgZm9yIHRoZSB3aWRnZXQgdG8gbm90IGFjY2lkZW50YWxseSByZWFkIHBhcmVudA0KICAgICAgICogICAgICAgICBzdGF0ZS4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0ge1Njb3BlfSBbcGFyZW50PXRoaXNdIFRoZSB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSBgU2NvcGVgfSB0aGF0IHdpbGwgYmUgdGhlIGAkcGFyZW50YA0KICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZiB0aGUgbmV3bHkgY3JlYXRlZCBzY29wZS4gRGVmYXVsdHMgdG8gYHRoaXNgIHNjb3BlIGlmIG5vdCBwcm92aWRlZC4NCiAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGhpcyBpcyB1c2VkIHdoZW4gY3JlYXRpbmcgYSB0cmFuc2NsdWRlIHNjb3BlIHRvIGNvcnJlY3RseSBwbGFjZSBpdA0KICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbiB0aGUgc2NvcGUgaGllcmFyY2h5IHdoaWxlIG1haW50YWluaW5nIHRoZSBjb3JyZWN0IHByb3RvdHlwaWNhbA0KICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmhlcml0YW5jZS4NCiAgICAgICAqDQogICAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgbmV3bHkgY3JlYXRlZCBjaGlsZCBzY29wZS4NCiAgICAgICAqDQogICAgICAgKi8NCiAgICAgICRuZXc6IGZ1bmN0aW9uKGlzb2xhdGUsIHBhcmVudCkgew0KICAgICAgICB2YXIgY2hpbGQ7DQoNCiAgICAgICAgcGFyZW50ID0gcGFyZW50IHx8IHRoaXM7DQoNCiAgICAgICAgaWYgKGlzb2xhdGUpIHsNCiAgICAgICAgICBjaGlsZCA9IG5ldyBTY29wZSgpOw0KICAgICAgICAgIGNoaWxkLiRyb290ID0gdGhpcy4kcm9vdDsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAvLyBPbmx5IGNyZWF0ZSBhIGNoaWxkIHNjb3BlIGNsYXNzIGlmIHNvbWVib2R5IGFza3MgZm9yIG9uZSwNCiAgICAgICAgICAvLyBidXQgY2FjaGUgaXQgdG8gYWxsb3cgdGhlIFZNIHRvIG9wdGltaXplIGxvb2t1cHMuDQogICAgICAgICAgaWYgKCF0aGlzLiQkQ2hpbGRTY29wZSkgew0KICAgICAgICAgICAgdGhpcy4kJENoaWxkU2NvcGUgPSBmdW5jdGlvbiBDaGlsZFNjb3BlKCkgew0KICAgICAgICAgICAgICB0aGlzLiQkd2F0Y2hlcnMgPSB0aGlzLiQkbmV4dFNpYmxpbmcgPQ0KICAgICAgICAgICAgICAgICAgdGhpcy4kJGNoaWxkSGVhZCA9IHRoaXMuJCRjaGlsZFRhaWwgPSBudWxsOw0KICAgICAgICAgICAgICB0aGlzLiQkbGlzdGVuZXJzID0ge307DQogICAgICAgICAgICAgIHRoaXMuJCRsaXN0ZW5lckNvdW50ID0ge307DQogICAgICAgICAgICAgIHRoaXMuJGlkID0gbmV4dFVpZCgpOw0KICAgICAgICAgICAgICB0aGlzLiQkQ2hpbGRTY29wZSA9IG51bGw7DQogICAgICAgICAgICB9Ow0KICAgICAgICAgICAgdGhpcy4kJENoaWxkU2NvcGUucHJvdG90eXBlID0gdGhpczsNCiAgICAgICAgICB9DQogICAgICAgICAgY2hpbGQgPSBuZXcgdGhpcy4kJENoaWxkU2NvcGUoKTsNCiAgICAgICAgfQ0KICAgICAgICBjaGlsZC4kcGFyZW50ID0gcGFyZW50Ow0KICAgICAgICBjaGlsZC4kJHByZXZTaWJsaW5nID0gcGFyZW50LiQkY2hpbGRUYWlsOw0KICAgICAgICBpZiAocGFyZW50LiQkY2hpbGRIZWFkKSB7DQogICAgICAgICAgcGFyZW50LiQkY2hpbGRUYWlsLiQkbmV4dFNpYmxpbmcgPSBjaGlsZDsNCiAgICAgICAgICBwYXJlbnQuJCRjaGlsZFRhaWwgPSBjaGlsZDsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBwYXJlbnQuJCRjaGlsZEhlYWQgPSBwYXJlbnQuJCRjaGlsZFRhaWwgPSBjaGlsZDsNCiAgICAgICAgfQ0KDQogICAgICAgIC8vIFdoZW4gdGhlIG5ldyBzY29wZSBpcyBub3QgaXNvbGF0ZWQgb3Igd2UgaW5oZXJpdCBmcm9tIGB0aGlzYCwgYW5kDQogICAgICAgIC8vIHRoZSBwYXJlbnQgc2NvcGUgaXMgZGVzdHJveWVkLCB0aGUgcHJvcGVydHkgYCQkZGVzdHJveWVkYCBpcyBpbmhlcml0ZWQNCiAgICAgICAgLy8gcHJvdG90eXBpY2FsbHkuIEluIGFsbCBvdGhlciBjYXNlcywgdGhpcyBwcm9wZXJ0eSBuZWVkcyB0byBiZSBzZXQNCiAgICAgICAgLy8gd2hlbiB0aGUgcGFyZW50IHNjb3BlIGlzIGRlc3Ryb3llZC4NCiAgICAgICAgLy8gVGhlIGxpc3RlbmVyIG5lZWRzIHRvIGJlIGFkZGVkIGFmdGVyIHRoZSBwYXJlbnQgaXMgc2V0DQogICAgICAgIGlmIChpc29sYXRlIHx8IHBhcmVudCAhPSB0aGlzKSBjaGlsZC4kb24oJyRkZXN0cm95JywgZGVzdHJveUNoaWxkKTsNCg0KICAgICAgICByZXR1cm4gY2hpbGQ7DQoNCiAgICAgICAgZnVuY3Rpb24gZGVzdHJveUNoaWxkKCkgew0KICAgICAgICAgIGNoaWxkLiQkZGVzdHJveWVkID0gdHJ1ZTsNCiAgICAgICAgfQ0KICAgICAgfSwNCg0KICAgICAgLyoqDQogICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgKiBAbmFtZSAkcm9vdFNjb3BlLlNjb3BlIyR3YXRjaA0KICAgICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgICAqDQogICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAqIFJlZ2lzdGVycyBhIGBsaXN0ZW5lcmAgY2FsbGJhY2sgdG8gYmUgZXhlY3V0ZWQgd2hlbmV2ZXIgdGhlIGB3YXRjaEV4cHJlc3Npb25gIGNoYW5nZXMuDQogICAgICAgKg0KICAgICAgICogLSBUaGUgYHdhdGNoRXhwcmVzc2lvbmAgaXMgY2FsbGVkIG9uIGV2ZXJ5IGNhbGwgdG8ge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJGRpZ2VzdA0KICAgICAgICogICAkZGlnZXN0KCl9IGFuZCBzaG91bGQgcmV0dXJuIHRoZSB2YWx1ZSB0aGF0IHdpbGwgYmUgd2F0Y2hlZC4gKFNpbmNlDQogICAgICAgKiAgIHtAbGluayBuZy4kcm9vdFNjb3BlLlNjb3BlIyRkaWdlc3QgJGRpZ2VzdCgpfSByZXJ1bnMgd2hlbiBpdCBkZXRlY3RzIGNoYW5nZXMgdGhlDQogICAgICAgKiAgIGB3YXRjaEV4cHJlc3Npb25gIGNhbiBleGVjdXRlIG11bHRpcGxlIHRpbWVzIHBlcg0KICAgICAgICogICB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSMkZGlnZXN0ICRkaWdlc3QoKX0gYW5kIHNob3VsZCBiZSBpZGVtcG90ZW50LikNCiAgICAgICAqIC0gVGhlIGBsaXN0ZW5lcmAgaXMgY2FsbGVkIG9ubHkgd2hlbiB0aGUgdmFsdWUgZnJvbSB0aGUgY3VycmVudCBgd2F0Y2hFeHByZXNzaW9uYCBhbmQgdGhlDQogICAgICAgKiAgIHByZXZpb3VzIGNhbGwgdG8gYHdhdGNoRXhwcmVzc2lvbmAgYXJlIG5vdCBlcXVhbCAod2l0aCB0aGUgZXhjZXB0aW9uIG9mIHRoZSBpbml0aWFsIHJ1biwNCiAgICAgICAqICAgc2VlIGJlbG93KS4gSW5lcXVhbGl0eSBpcyBkZXRlcm1pbmVkIGFjY29yZGluZyB0byByZWZlcmVuY2UgaW5lcXVhbGl0eSwNCiAgICAgICAqICAgW3N0cmljdCBjb21wYXJpc29uXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9PcGVyYXRvcnMvQ29tcGFyaXNvbl9PcGVyYXRvcnMpDQogICAgICAgKiAgICB2aWEgdGhlIGAhPT1gIEphdmFzY3JpcHQgb3BlcmF0b3IsIHVubGVzcyBgb2JqZWN0RXF1YWxpdHkgPT0gdHJ1ZWANCiAgICAgICAqICAgKHNlZSBuZXh0IHBvaW50KQ0KICAgICAgICogLSBXaGVuIGBvYmplY3RFcXVhbGl0eSA9PSB0cnVlYCwgaW5lcXVhbGl0eSBvZiB0aGUgYHdhdGNoRXhwcmVzc2lvbmAgaXMgZGV0ZXJtaW5lZA0KICAgICAgICogICBhY2NvcmRpbmcgdG8gdGhlIHtAbGluayBhbmd1bGFyLmVxdWFsc30gZnVuY3Rpb24uIFRvIHNhdmUgdGhlIHZhbHVlIG9mIHRoZSBvYmplY3QgZm9yDQogICAgICAgKiAgIGxhdGVyIGNvbXBhcmlzb24sIHRoZSB7QGxpbmsgYW5ndWxhci5jb3B5fSBmdW5jdGlvbiBpcyB1c2VkLiBUaGlzIHRoZXJlZm9yZSBtZWFucyB0aGF0DQogICAgICAgKiAgIHdhdGNoaW5nIGNvbXBsZXggb2JqZWN0cyB3aWxsIGhhdmUgYWR2ZXJzZSBtZW1vcnkgYW5kIHBlcmZvcm1hbmNlIGltcGxpY2F0aW9ucy4NCiAgICAgICAqIC0gVGhlIHdhdGNoIGBsaXN0ZW5lcmAgbWF5IGNoYW5nZSB0aGUgbW9kZWwsIHdoaWNoIG1heSB0cmlnZ2VyIG90aGVyIGBsaXN0ZW5lcmBzIHRvIGZpcmUuDQogICAgICAgKiAgIFRoaXMgaXMgYWNoaWV2ZWQgYnkgcmVydW5uaW5nIHRoZSB3YXRjaGVycyB1bnRpbCBubyBjaGFuZ2VzIGFyZSBkZXRlY3RlZC4gVGhlIHJlcnVuDQogICAgICAgKiAgIGl0ZXJhdGlvbiBsaW1pdCBpcyAxMCB0byBwcmV2ZW50IGFuIGluZmluaXRlIGxvb3AgZGVhZGxvY2suDQogICAgICAgKg0KICAgICAgICoNCiAgICAgICAqIElmIHlvdSB3YW50IHRvIGJlIG5vdGlmaWVkIHdoZW5ldmVyIHtAbGluayBuZy4kcm9vdFNjb3BlLlNjb3BlIyRkaWdlc3QgJGRpZ2VzdH0gaXMgY2FsbGVkLA0KICAgICAgICogeW91IGNhbiByZWdpc3RlciBhIGB3YXRjaEV4cHJlc3Npb25gIGZ1bmN0aW9uIHdpdGggbm8gYGxpc3RlbmVyYC4gKFNpbmNlIGB3YXRjaEV4cHJlc3Npb25gDQogICAgICAgKiBjYW4gZXhlY3V0ZSBtdWx0aXBsZSB0aW1lcyBwZXIge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJGRpZ2VzdCAkZGlnZXN0fSBjeWNsZSB3aGVuIGENCiAgICAgICAqIGNoYW5nZSBpcyBkZXRlY3RlZCwgYmUgcHJlcGFyZWQgZm9yIG11bHRpcGxlIGNhbGxzIHRvIHlvdXIgbGlzdGVuZXIuKQ0KICAgICAgICoNCiAgICAgICAqIEFmdGVyIGEgd2F0Y2hlciBpcyByZWdpc3RlcmVkIHdpdGggdGhlIHNjb3BlLCB0aGUgYGxpc3RlbmVyYCBmbiBpcyBjYWxsZWQgYXN5bmNocm9ub3VzbHkNCiAgICAgICAqICh2aWEge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJGV2YWxBc3luYyAkZXZhbEFzeW5jfSkgdG8gaW5pdGlhbGl6ZSB0aGUNCiAgICAgICAqIHdhdGNoZXIuIEluIHJhcmUgY2FzZXMsIHRoaXMgaXMgdW5kZXNpcmFibGUgYmVjYXVzZSB0aGUgbGlzdGVuZXIgaXMgY2FsbGVkIHdoZW4gdGhlIHJlc3VsdA0KICAgICAgICogb2YgYHdhdGNoRXhwcmVzc2lvbmAgZGlkbid0IGNoYW5nZS4gVG8gZGV0ZWN0IHRoaXMgc2NlbmFyaW8gd2l0aGluIHRoZSBgbGlzdGVuZXJgIGZuLCB5b3UNCiAgICAgICAqIGNhbiBjb21wYXJlIHRoZSBgbmV3VmFsYCBhbmQgYG9sZFZhbGAuIElmIHRoZXNlIHR3byB2YWx1ZXMgYXJlIGlkZW50aWNhbCAoYD09PWApIHRoZW4gdGhlDQogICAgICAgKiBsaXN0ZW5lciB3YXMgY2FsbGVkIGR1ZSB0byBpbml0aWFsaXphdGlvbi4NCiAgICAgICAqDQogICAgICAgKg0KICAgICAgICoNCiAgICAgICAqICMgRXhhbXBsZQ0KICAgICAgICogYGBganMNCiAgICAgICAgICAgLy8gbGV0J3MgYXNzdW1lIHRoYXQgc2NvcGUgd2FzIGRlcGVuZGVuY3kgaW5qZWN0ZWQgYXMgdGhlICRyb290U2NvcGUNCiAgICAgICAgICAgdmFyIHNjb3BlID0gJHJvb3RTY29wZTsNCiAgICAgICAgICAgc2NvcGUubmFtZSA9ICdtaXNrbyc7DQogICAgICAgICAgIHNjb3BlLmNvdW50ZXIgPSAwOw0KDQogICAgICAgICAgIGV4cGVjdChzY29wZS5jb3VudGVyKS50b0VxdWFsKDApOw0KICAgICAgICAgICBzY29wZS4kd2F0Y2goJ25hbWUnLCBmdW5jdGlvbihuZXdWYWx1ZSwgb2xkVmFsdWUpIHsNCiAgICAgICAgICAgICBzY29wZS5jb3VudGVyID0gc2NvcGUuY291bnRlciArIDE7DQogICAgICAgICAgIH0pOw0KICAgICAgICAgICBleHBlY3Qoc2NvcGUuY291bnRlcikudG9FcXVhbCgwKTsNCg0KICAgICAgICAgICBzY29wZS4kZGlnZXN0KCk7DQogICAgICAgICAgIC8vIHRoZSBsaXN0ZW5lciBpcyBhbHdheXMgY2FsbGVkIGR1cmluZyB0aGUgZmlyc3QgJGRpZ2VzdCBsb29wIGFmdGVyIGl0IHdhcyByZWdpc3RlcmVkDQogICAgICAgICAgIGV4cGVjdChzY29wZS5jb3VudGVyKS50b0VxdWFsKDEpOw0KDQogICAgICAgICAgIHNjb3BlLiRkaWdlc3QoKTsNCiAgICAgICAgICAgLy8gYnV0IG5vdyBpdCB3aWxsIG5vdCBiZSBjYWxsZWQgdW5sZXNzIHRoZSB2YWx1ZSBjaGFuZ2VzDQogICAgICAgICAgIGV4cGVjdChzY29wZS5jb3VudGVyKS50b0VxdWFsKDEpOw0KDQogICAgICAgICAgIHNjb3BlLm5hbWUgPSAnYWRhbSc7DQogICAgICAgICAgIHNjb3BlLiRkaWdlc3QoKTsNCiAgICAgICAgICAgZXhwZWN0KHNjb3BlLmNvdW50ZXIpLnRvRXF1YWwoMik7DQoNCg0KDQogICAgICAgICAgIC8vIFVzaW5nIGEgZnVuY3Rpb24gYXMgYSB3YXRjaEV4cHJlc3Npb24NCiAgICAgICAgICAgdmFyIGZvb2Q7DQogICAgICAgICAgIHNjb3BlLmZvb2RDb3VudGVyID0gMDsNCiAgICAgICAgICAgZXhwZWN0KHNjb3BlLmZvb2RDb3VudGVyKS50b0VxdWFsKDApOw0KICAgICAgICAgICBzY29wZS4kd2F0Y2goDQogICAgICAgICAgICAgLy8gVGhpcyBmdW5jdGlvbiByZXR1cm5zIHRoZSB2YWx1ZSBiZWluZyB3YXRjaGVkLiBJdCBpcyBjYWxsZWQgZm9yIGVhY2ggdHVybiBvZiB0aGUgJGRpZ2VzdCBsb29wDQogICAgICAgICAgICAgZnVuY3Rpb24oKSB7IHJldHVybiBmb29kOyB9LA0KICAgICAgICAgICAgIC8vIFRoaXMgaXMgdGhlIGNoYW5nZSBsaXN0ZW5lciwgY2FsbGVkIHdoZW4gdGhlIHZhbHVlIHJldHVybmVkIGZyb20gdGhlIGFib3ZlIGZ1bmN0aW9uIGNoYW5nZXMNCiAgICAgICAgICAgICBmdW5jdGlvbihuZXdWYWx1ZSwgb2xkVmFsdWUpIHsNCiAgICAgICAgICAgICAgIGlmICggbmV3VmFsdWUgIT09IG9sZFZhbHVlICkgew0KICAgICAgICAgICAgICAgICAvLyBPbmx5IGluY3JlbWVudCB0aGUgY291bnRlciBpZiB0aGUgdmFsdWUgY2hhbmdlZA0KICAgICAgICAgICAgICAgICBzY29wZS5mb29kQ291bnRlciA9IHNjb3BlLmZvb2RDb3VudGVyICsgMTsNCiAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICB9DQogICAgICAgICAgICk7DQogICAgICAgICAgIC8vIE5vIGRpZ2VzdCBoYXMgYmVlbiBydW4gc28gdGhlIGNvdW50ZXIgd2lsbCBiZSB6ZXJvDQogICAgICAgICAgIGV4cGVjdChzY29wZS5mb29kQ291bnRlcikudG9FcXVhbCgwKTsNCg0KICAgICAgICAgICAvLyBSdW4gdGhlIGRpZ2VzdCBidXQgc2luY2UgZm9vZCBoYXMgbm90IGNoYW5nZWQgY291bnQgd2lsbCBzdGlsbCBiZSB6ZXJvDQogICAgICAgICAgIHNjb3BlLiRkaWdlc3QoKTsNCiAgICAgICAgICAgZXhwZWN0KHNjb3BlLmZvb2RDb3VudGVyKS50b0VxdWFsKDApOw0KDQogICAgICAgICAgIC8vIFVwZGF0ZSBmb29kIGFuZCBydW4gZGlnZXN0LiAgTm93IHRoZSBjb3VudGVyIHdpbGwgaW5jcmVtZW50DQogICAgICAgICAgIGZvb2QgPSAnY2hlZXNlYnVyZ2VyJzsNCiAgICAgICAgICAgc2NvcGUuJGRpZ2VzdCgpOw0KICAgICAgICAgICBleHBlY3Qoc2NvcGUuZm9vZENvdW50ZXIpLnRvRXF1YWwoMSk7DQoNCiAgICAgICAqIGBgYA0KICAgICAgICoNCiAgICAgICAqDQogICAgICAgKg0KICAgICAgICogQHBhcmFtIHsoZnVuY3Rpb24oKXxzdHJpbmcpfSB3YXRjaEV4cHJlc3Npb24gRXhwcmVzc2lvbiB0aGF0IGlzIGV2YWx1YXRlZCBvbiBlYWNoDQogICAgICAgKiAgICB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSMkZGlnZXN0ICRkaWdlc3R9IGN5Y2xlLiBBIGNoYW5nZSBpbiB0aGUgcmV0dXJuIHZhbHVlIHRyaWdnZXJzDQogICAgICAgKiAgICBhIGNhbGwgdG8gdGhlIGBsaXN0ZW5lcmAuDQogICAgICAgKg0KICAgICAgICogICAgLSBgc3RyaW5nYDogRXZhbHVhdGVkIGFzIHtAbGluayBndWlkZS9leHByZXNzaW9uIGV4cHJlc3Npb259DQogICAgICAgKiAgICAtIGBmdW5jdGlvbihzY29wZSlgOiBjYWxsZWQgd2l0aCBjdXJyZW50IGBzY29wZWAgYXMgYSBwYXJhbWV0ZXIuDQogICAgICAgKiBAcGFyYW0ge2Z1bmN0aW9uKG5ld1ZhbCwgb2xkVmFsLCBzY29wZSl9IGxpc3RlbmVyIENhbGxiYWNrIGNhbGxlZCB3aGVuZXZlciB0aGUgdmFsdWUNCiAgICAgICAqICAgIG9mIGB3YXRjaEV4cHJlc3Npb25gIGNoYW5nZXMuDQogICAgICAgKg0KICAgICAgICogICAgLSBgbmV3VmFsYCBjb250YWlucyB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgYHdhdGNoRXhwcmVzc2lvbmANCiAgICAgICAqICAgIC0gYG9sZFZhbGAgY29udGFpbnMgdGhlIHByZXZpb3VzIHZhbHVlIG9mIHRoZSBgd2F0Y2hFeHByZXNzaW9uYA0KICAgICAgICogICAgLSBgc2NvcGVgIHJlZmVycyB0byB0aGUgY3VycmVudCBzY29wZQ0KICAgICAgICogQHBhcmFtIHtib29sZWFuPX0gb2JqZWN0RXF1YWxpdHkgQ29tcGFyZSBmb3Igb2JqZWN0IGVxdWFsaXR5IHVzaW5nIHtAbGluayBhbmd1bGFyLmVxdWFsc30gaW5zdGVhZCBvZg0KICAgICAgICogICAgIGNvbXBhcmluZyBmb3IgcmVmZXJlbmNlIGVxdWFsaXR5Lg0KICAgICAgICogQHJldHVybnMge2Z1bmN0aW9uKCl9IFJldHVybnMgYSBkZXJlZ2lzdHJhdGlvbiBmdW5jdGlvbiBmb3IgdGhpcyBsaXN0ZW5lci4NCiAgICAgICAqLw0KICAgICAgJHdhdGNoOiBmdW5jdGlvbih3YXRjaEV4cCwgbGlzdGVuZXIsIG9iamVjdEVxdWFsaXR5KSB7DQogICAgICAgIHZhciBnZXQgPSAkcGFyc2Uod2F0Y2hFeHApOw0KDQogICAgICAgIGlmIChnZXQuJCR3YXRjaERlbGVnYXRlKSB7DQogICAgICAgICAgcmV0dXJuIGdldC4kJHdhdGNoRGVsZWdhdGUodGhpcywgbGlzdGVuZXIsIG9iamVjdEVxdWFsaXR5LCBnZXQpOw0KICAgICAgICB9DQogICAgICAgIHZhciBzY29wZSA9IHRoaXMsDQogICAgICAgICAgICBhcnJheSA9IHNjb3BlLiQkd2F0Y2hlcnMsDQogICAgICAgICAgICB3YXRjaGVyID0gew0KICAgICAgICAgICAgICBmbjogbGlzdGVuZXIsDQogICAgICAgICAgICAgIGxhc3Q6IGluaXRXYXRjaFZhbCwNCiAgICAgICAgICAgICAgZ2V0OiBnZXQsDQogICAgICAgICAgICAgIGV4cDogd2F0Y2hFeHAsDQogICAgICAgICAgICAgIGVxOiAhIW9iamVjdEVxdWFsaXR5DQogICAgICAgICAgICB9Ow0KDQogICAgICAgIGxhc3REaXJ0eVdhdGNoID0gbnVsbDsNCg0KICAgICAgICBpZiAoIWlzRnVuY3Rpb24obGlzdGVuZXIpKSB7DQogICAgICAgICAgd2F0Y2hlci5mbiA9IG5vb3A7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoIWFycmF5KSB7DQogICAgICAgICAgYXJyYXkgPSBzY29wZS4kJHdhdGNoZXJzID0gW107DQogICAgICAgIH0NCiAgICAgICAgLy8gd2UgdXNlIHVuc2hpZnQgc2luY2Ugd2UgdXNlIGEgd2hpbGUgbG9vcCBpbiAkZGlnZXN0IGZvciBzcGVlZC4NCiAgICAgICAgLy8gdGhlIHdoaWxlIGxvb3AgcmVhZHMgaW4gcmV2ZXJzZSBvcmRlci4NCiAgICAgICAgYXJyYXkudW5zaGlmdCh3YXRjaGVyKTsNCg0KICAgICAgICByZXR1cm4gZnVuY3Rpb24gZGVyZWdpc3RlcldhdGNoKCkgew0KICAgICAgICAgIGFycmF5UmVtb3ZlKGFycmF5LCB3YXRjaGVyKTsNCiAgICAgICAgICBsYXN0RGlydHlXYXRjaCA9IG51bGw7DQogICAgICAgIH07DQogICAgICB9LA0KDQogICAgICAvKioNCiAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAqIEBuYW1lICRyb290U2NvcGUuU2NvcGUjJHdhdGNoR3JvdXANCiAgICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICAgKg0KICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgKiBBIHZhcmlhbnQgb2Yge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJHdhdGNoICR3YXRjaCgpfSB3aGVyZSBpdCB3YXRjaGVzIGFuIGFycmF5IG9mIGB3YXRjaEV4cHJlc3Npb25zYC4NCiAgICAgICAqIElmIGFueSBvbmUgZXhwcmVzc2lvbiBpbiB0aGUgY29sbGVjdGlvbiBjaGFuZ2VzIHRoZSBgbGlzdGVuZXJgIGlzIGV4ZWN1dGVkLg0KICAgICAgICoNCiAgICAgICAqIC0gVGhlIGl0ZW1zIGluIHRoZSBgd2F0Y2hFeHByZXNzaW9uc2AgYXJyYXkgYXJlIG9ic2VydmVkIHZpYSBzdGFuZGFyZCAkd2F0Y2ggb3BlcmF0aW9uIGFuZCBhcmUgZXhhbWluZWQgb24gZXZlcnkNCiAgICAgICAqICAgY2FsbCB0byAkZGlnZXN0KCkgdG8gc2VlIGlmIGFueSBpdGVtcyBjaGFuZ2VzLg0KICAgICAgICogLSBUaGUgYGxpc3RlbmVyYCBpcyBjYWxsZWQgd2hlbmV2ZXIgYW55IGV4cHJlc3Npb24gaW4gdGhlIGB3YXRjaEV4cHJlc3Npb25zYCBhcnJheSBjaGFuZ2VzLg0KICAgICAgICoNCiAgICAgICAqIEBwYXJhbSB7QXJyYXkuPHN0cmluZ3xGdW5jdGlvbihzY29wZSk+fSB3YXRjaEV4cHJlc3Npb25zIEFycmF5IG9mIGV4cHJlc3Npb25zIHRoYXQgd2lsbCBiZSBpbmRpdmlkdWFsbHkNCiAgICAgICAqIHdhdGNoZWQgdXNpbmcge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJHdhdGNoICR3YXRjaCgpfQ0KICAgICAgICoNCiAgICAgICAqIEBwYXJhbSB7ZnVuY3Rpb24obmV3VmFsdWVzLCBvbGRWYWx1ZXMsIHNjb3BlKX0gbGlzdGVuZXIgQ2FsbGJhY2sgY2FsbGVkIHdoZW5ldmVyIHRoZSByZXR1cm4gdmFsdWUgb2YgYW55DQogICAgICAgKiAgICBleHByZXNzaW9uIGluIGB3YXRjaEV4cHJlc3Npb25zYCBjaGFuZ2VzDQogICAgICAgKiAgICBUaGUgYG5ld1ZhbHVlc2AgYXJyYXkgY29udGFpbnMgdGhlIGN1cnJlbnQgdmFsdWVzIG9mIHRoZSBgd2F0Y2hFeHByZXNzaW9uc2AsIHdpdGggdGhlIGluZGV4ZXMgbWF0Y2hpbmcNCiAgICAgICAqICAgIHRob3NlIG9mIGB3YXRjaEV4cHJlc3Npb25gDQogICAgICAgKiAgICBhbmQgdGhlIGBvbGRWYWx1ZXNgIGFycmF5IGNvbnRhaW5zIHRoZSBwcmV2aW91cyB2YWx1ZXMgb2YgdGhlIGB3YXRjaEV4cHJlc3Npb25zYCwgd2l0aCB0aGUgaW5kZXhlcyBtYXRjaGluZw0KICAgICAgICogICAgdGhvc2Ugb2YgYHdhdGNoRXhwcmVzc2lvbmANCiAgICAgICAqICAgIFRoZSBgc2NvcGVgIHJlZmVycyB0byB0aGUgY3VycmVudCBzY29wZS4NCiAgICAgICAqIEByZXR1cm5zIHtmdW5jdGlvbigpfSBSZXR1cm5zIGEgZGUtcmVnaXN0cmF0aW9uIGZ1bmN0aW9uIGZvciBhbGwgbGlzdGVuZXJzLg0KICAgICAgICovDQogICAgICAkd2F0Y2hHcm91cDogZnVuY3Rpb24od2F0Y2hFeHByZXNzaW9ucywgbGlzdGVuZXIpIHsNCiAgICAgICAgdmFyIG9sZFZhbHVlcyA9IG5ldyBBcnJheSh3YXRjaEV4cHJlc3Npb25zLmxlbmd0aCk7DQogICAgICAgIHZhciBuZXdWYWx1ZXMgPSBuZXcgQXJyYXkod2F0Y2hFeHByZXNzaW9ucy5sZW5ndGgpOw0KICAgICAgICB2YXIgZGVyZWdpc3RlckZucyA9IFtdOw0KICAgICAgICB2YXIgc2VsZiA9IHRoaXM7DQogICAgICAgIHZhciBjaGFuZ2VSZWFjdGlvblNjaGVkdWxlZCA9IGZhbHNlOw0KICAgICAgICB2YXIgZmlyc3RSdW4gPSB0cnVlOw0KDQogICAgICAgIGlmICghd2F0Y2hFeHByZXNzaW9ucy5sZW5ndGgpIHsNCiAgICAgICAgICAvLyBObyBleHByZXNzaW9ucyBtZWFucyB3ZSBjYWxsIHRoZSBsaXN0ZW5lciBBU0FQDQogICAgICAgICAgdmFyIHNob3VsZENhbGwgPSB0cnVlOw0KICAgICAgICAgIHNlbGYuJGV2YWxBc3luYyhmdW5jdGlvbigpIHsNCiAgICAgICAgICAgIGlmIChzaG91bGRDYWxsKSBsaXN0ZW5lcihuZXdWYWx1ZXMsIG5ld1ZhbHVlcywgc2VsZik7DQogICAgICAgICAgfSk7DQogICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGRlcmVnaXN0ZXJXYXRjaEdyb3VwKCkgew0KICAgICAgICAgICAgc2hvdWxkQ2FsbCA9IGZhbHNlOw0KICAgICAgICAgIH07DQogICAgICAgIH0NCg0KICAgICAgICBpZiAod2F0Y2hFeHByZXNzaW9ucy5sZW5ndGggPT09IDEpIHsNCiAgICAgICAgICAvLyBTcGVjaWFsIGNhc2Ugc2l6ZSBvZiBvbmUNCiAgICAgICAgICByZXR1cm4gdGhpcy4kd2F0Y2god2F0Y2hFeHByZXNzaW9uc1swXSwgZnVuY3Rpb24gd2F0Y2hHcm91cEFjdGlvbih2YWx1ZSwgb2xkVmFsdWUsIHNjb3BlKSB7DQogICAgICAgICAgICBuZXdWYWx1ZXNbMF0gPSB2YWx1ZTsNCiAgICAgICAgICAgIG9sZFZhbHVlc1swXSA9IG9sZFZhbHVlOw0KICAgICAgICAgICAgbGlzdGVuZXIobmV3VmFsdWVzLCAodmFsdWUgPT09IG9sZFZhbHVlKSA/IG5ld1ZhbHVlcyA6IG9sZFZhbHVlcywgc2NvcGUpOw0KICAgICAgICAgIH0pOw0KICAgICAgICB9DQoNCiAgICAgICAgZm9yRWFjaCh3YXRjaEV4cHJlc3Npb25zLCBmdW5jdGlvbihleHByLCBpKSB7DQogICAgICAgICAgdmFyIHVud2F0Y2hGbiA9IHNlbGYuJHdhdGNoKGV4cHIsIGZ1bmN0aW9uIHdhdGNoR3JvdXBTdWJBY3Rpb24odmFsdWUsIG9sZFZhbHVlKSB7DQogICAgICAgICAgICBuZXdWYWx1ZXNbaV0gPSB2YWx1ZTsNCiAgICAgICAgICAgIG9sZFZhbHVlc1tpXSA9IG9sZFZhbHVlOw0KICAgICAgICAgICAgaWYgKCFjaGFuZ2VSZWFjdGlvblNjaGVkdWxlZCkgew0KICAgICAgICAgICAgICBjaGFuZ2VSZWFjdGlvblNjaGVkdWxlZCA9IHRydWU7DQogICAgICAgICAgICAgIHNlbGYuJGV2YWxBc3luYyh3YXRjaEdyb3VwQWN0aW9uKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9KTsNCiAgICAgICAgICBkZXJlZ2lzdGVyRm5zLnB1c2godW53YXRjaEZuKTsNCiAgICAgICAgfSk7DQoNCiAgICAgICAgZnVuY3Rpb24gd2F0Y2hHcm91cEFjdGlvbigpIHsNCiAgICAgICAgICBjaGFuZ2VSZWFjdGlvblNjaGVkdWxlZCA9IGZhbHNlOw0KDQogICAgICAgICAgaWYgKGZpcnN0UnVuKSB7DQogICAgICAgICAgICBmaXJzdFJ1biA9IGZhbHNlOw0KICAgICAgICAgICAgbGlzdGVuZXIobmV3VmFsdWVzLCBuZXdWYWx1ZXMsIHNlbGYpOw0KICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBsaXN0ZW5lcihuZXdWYWx1ZXMsIG9sZFZhbHVlcywgc2VsZik7DQogICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGRlcmVnaXN0ZXJXYXRjaEdyb3VwKCkgew0KICAgICAgICAgIHdoaWxlIChkZXJlZ2lzdGVyRm5zLmxlbmd0aCkgew0KICAgICAgICAgICAgZGVyZWdpc3RlckZucy5zaGlmdCgpKCk7DQogICAgICAgICAgfQ0KICAgICAgICB9Ow0KICAgICAgfSwNCg0KDQogICAgICAvKioNCiAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAqIEBuYW1lICRyb290U2NvcGUuU2NvcGUjJHdhdGNoQ29sbGVjdGlvbg0KICAgICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgICAqDQogICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAqIFNoYWxsb3cgd2F0Y2hlcyB0aGUgcHJvcGVydGllcyBvZiBhbiBvYmplY3QgYW5kIGZpcmVzIHdoZW5ldmVyIGFueSBvZiB0aGUgcHJvcGVydGllcyBjaGFuZ2UNCiAgICAgICAqIChmb3IgYXJyYXlzLCB0aGlzIGltcGxpZXMgd2F0Y2hpbmcgdGhlIGFycmF5IGl0ZW1zOyBmb3Igb2JqZWN0IG1hcHMsIHRoaXMgaW1wbGllcyB3YXRjaGluZw0KICAgICAgICogdGhlIHByb3BlcnRpZXMpLiBJZiBhIGNoYW5nZSBpcyBkZXRlY3RlZCwgdGhlIGBsaXN0ZW5lcmAgY2FsbGJhY2sgaXMgZmlyZWQuDQogICAgICAgKg0KICAgICAgICogLSBUaGUgYG9iamAgY29sbGVjdGlvbiBpcyBvYnNlcnZlZCB2aWEgc3RhbmRhcmQgJHdhdGNoIG9wZXJhdGlvbiBhbmQgaXMgZXhhbWluZWQgb24gZXZlcnkNCiAgICAgICAqICAgY2FsbCB0byAkZGlnZXN0KCkgdG8gc2VlIGlmIGFueSBpdGVtcyBoYXZlIGJlZW4gYWRkZWQsIHJlbW92ZWQsIG9yIG1vdmVkLg0KICAgICAgICogLSBUaGUgYGxpc3RlbmVyYCBpcyBjYWxsZWQgd2hlbmV2ZXIgYW55dGhpbmcgd2l0aGluIHRoZSBgb2JqYCBoYXMgY2hhbmdlZC4gRXhhbXBsZXMgaW5jbHVkZQ0KICAgICAgICogICBhZGRpbmcsIHJlbW92aW5nLCBhbmQgbW92aW5nIGl0ZW1zIGJlbG9uZ2luZyB0byBhbiBvYmplY3Qgb3IgYXJyYXkuDQogICAgICAgKg0KICAgICAgICoNCiAgICAgICAqICMgRXhhbXBsZQ0KICAgICAgICogYGBganMNCiAgICAgICAgICAkc2NvcGUubmFtZXMgPSBbJ2lnb3InLCAnbWF0aWFzJywgJ21pc2tvJywgJ2phbWVzJ107DQogICAgICAgICAgJHNjb3BlLmRhdGFDb3VudCA9IDQ7DQoNCiAgICAgICAgICAkc2NvcGUuJHdhdGNoQ29sbGVjdGlvbignbmFtZXMnLCBmdW5jdGlvbihuZXdOYW1lcywgb2xkTmFtZXMpIHsNCiAgICAgICAgICAgICRzY29wZS5kYXRhQ291bnQgPSBuZXdOYW1lcy5sZW5ndGg7DQogICAgICAgICAgfSk7DQoNCiAgICAgICAgICBleHBlY3QoJHNjb3BlLmRhdGFDb3VudCkudG9FcXVhbCg0KTsNCiAgICAgICAgICAkc2NvcGUuJGRpZ2VzdCgpOw0KDQogICAgICAgICAgLy9zdGlsbCBhdCA0IC4uLiBubyBjaGFuZ2VzDQogICAgICAgICAgZXhwZWN0KCRzY29wZS5kYXRhQ291bnQpLnRvRXF1YWwoNCk7DQoNCiAgICAgICAgICAkc2NvcGUubmFtZXMucG9wKCk7DQogICAgICAgICAgJHNjb3BlLiRkaWdlc3QoKTsNCg0KICAgICAgICAgIC8vbm93IHRoZXJlJ3MgYmVlbiBhIGNoYW5nZQ0KICAgICAgICAgIGV4cGVjdCgkc2NvcGUuZGF0YUNvdW50KS50b0VxdWFsKDMpOw0KICAgICAgICogYGBgDQogICAgICAgKg0KICAgICAgICoNCiAgICAgICAqIEBwYXJhbSB7c3RyaW5nfGZ1bmN0aW9uKHNjb3BlKX0gb2JqIEV2YWx1YXRlZCBhcyB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBleHByZXNzaW9ufS4gVGhlDQogICAgICAgKiAgICBleHByZXNzaW9uIHZhbHVlIHNob3VsZCBldmFsdWF0ZSB0byBhbiBvYmplY3Qgb3IgYW4gYXJyYXkgd2hpY2ggaXMgb2JzZXJ2ZWQgb24gZWFjaA0KICAgICAgICogICAge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJGRpZ2VzdCAkZGlnZXN0fSBjeWNsZS4gQW55IHNoYWxsb3cgY2hhbmdlIHdpdGhpbiB0aGUNCiAgICAgICAqICAgIGNvbGxlY3Rpb24gd2lsbCB0cmlnZ2VyIGEgY2FsbCB0byB0aGUgYGxpc3RlbmVyYC4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0ge2Z1bmN0aW9uKG5ld0NvbGxlY3Rpb24sIG9sZENvbGxlY3Rpb24sIHNjb3BlKX0gbGlzdGVuZXIgYSBjYWxsYmFjayBmdW5jdGlvbiBjYWxsZWQNCiAgICAgICAqICAgIHdoZW4gYSBjaGFuZ2UgaXMgZGV0ZWN0ZWQuDQogICAgICAgKiAgICAtIFRoZSBgbmV3Q29sbGVjdGlvbmAgb2JqZWN0IGlzIHRoZSBuZXdseSBtb2RpZmllZCBkYXRhIG9idGFpbmVkIGZyb20gdGhlIGBvYmpgIGV4cHJlc3Npb24NCiAgICAgICAqICAgIC0gVGhlIGBvbGRDb2xsZWN0aW9uYCBvYmplY3QgaXMgYSBjb3B5IG9mIHRoZSBmb3JtZXIgY29sbGVjdGlvbiBkYXRhLg0KICAgICAgICogICAgICBEdWUgdG8gcGVyZm9ybWFuY2UgY29uc2lkZXJhdGlvbnMsIHRoZWBvbGRDb2xsZWN0aW9uYCB2YWx1ZSBpcyBjb21wdXRlZCBvbmx5IGlmIHRoZQ0KICAgICAgICogICAgICBgbGlzdGVuZXJgIGZ1bmN0aW9uIGRlY2xhcmVzIHR3byBvciBtb3JlIGFyZ3VtZW50cy4NCiAgICAgICAqICAgIC0gVGhlIGBzY29wZWAgYXJndW1lbnQgcmVmZXJzIHRvIHRoZSBjdXJyZW50IHNjb3BlLg0KICAgICAgICoNCiAgICAgICAqIEByZXR1cm5zIHtmdW5jdGlvbigpfSBSZXR1cm5zIGEgZGUtcmVnaXN0cmF0aW9uIGZ1bmN0aW9uIGZvciB0aGlzIGxpc3RlbmVyLiBXaGVuIHRoZQ0KICAgICAgICogICAgZGUtcmVnaXN0cmF0aW9uIGZ1bmN0aW9uIGlzIGV4ZWN1dGVkLCB0aGUgaW50ZXJuYWwgd2F0Y2ggb3BlcmF0aW9uIGlzIHRlcm1pbmF0ZWQuDQogICAgICAgKi8NCiAgICAgICR3YXRjaENvbGxlY3Rpb246IGZ1bmN0aW9uKG9iaiwgbGlzdGVuZXIpIHsNCiAgICAgICAgJHdhdGNoQ29sbGVjdGlvbkludGVyY2VwdG9yLiRzdGF0ZWZ1bCA9IHRydWU7DQoNCiAgICAgICAgdmFyIHNlbGYgPSB0aGlzOw0KICAgICAgICAvLyB0aGUgY3VycmVudCB2YWx1ZSwgdXBkYXRlZCBvbiBlYWNoIGRpcnR5LWNoZWNrIHJ1bg0KICAgICAgICB2YXIgbmV3VmFsdWU7DQogICAgICAgIC8vIGEgc2hhbGxvdyBjb3B5IG9mIHRoZSBuZXdWYWx1ZSBmcm9tIHRoZSBsYXN0IGRpcnR5LWNoZWNrIHJ1biwNCiAgICAgICAgLy8gdXBkYXRlZCB0byBtYXRjaCBuZXdWYWx1ZSBkdXJpbmcgZGlydHktY2hlY2sgcnVuDQogICAgICAgIHZhciBvbGRWYWx1ZTsNCiAgICAgICAgLy8gYSBzaGFsbG93IGNvcHkgb2YgdGhlIG5ld1ZhbHVlIGZyb20gd2hlbiB0aGUgbGFzdCBjaGFuZ2UgaGFwcGVuZWQNCiAgICAgICAgdmFyIHZlcnlPbGRWYWx1ZTsNCiAgICAgICAgLy8gb25seSB0cmFjayB2ZXJ5T2xkVmFsdWUgaWYgdGhlIGxpc3RlbmVyIGlzIGFza2luZyBmb3IgaXQNCiAgICAgICAgdmFyIHRyYWNrVmVyeU9sZFZhbHVlID0gKGxpc3RlbmVyLmxlbmd0aCA+IDEpOw0KICAgICAgICB2YXIgY2hhbmdlRGV0ZWN0ZWQgPSAwOw0KICAgICAgICB2YXIgY2hhbmdlRGV0ZWN0b3IgPSAkcGFyc2Uob2JqLCAkd2F0Y2hDb2xsZWN0aW9uSW50ZXJjZXB0b3IpOw0KICAgICAgICB2YXIgaW50ZXJuYWxBcnJheSA9IFtdOw0KICAgICAgICB2YXIgaW50ZXJuYWxPYmplY3QgPSB7fTsNCiAgICAgICAgdmFyIGluaXRSdW4gPSB0cnVlOw0KICAgICAgICB2YXIgb2xkTGVuZ3RoID0gMDsNCg0KICAgICAgICBmdW5jdGlvbiAkd2F0Y2hDb2xsZWN0aW9uSW50ZXJjZXB0b3IoX3ZhbHVlKSB7DQogICAgICAgICAgbmV3VmFsdWUgPSBfdmFsdWU7DQogICAgICAgICAgdmFyIG5ld0xlbmd0aCwga2V5LCBib3RoTmFOLCBuZXdJdGVtLCBvbGRJdGVtOw0KDQogICAgICAgICAgLy8gSWYgdGhlIG5ldyB2YWx1ZSBpcyB1bmRlZmluZWQsIHRoZW4gcmV0dXJuIHVuZGVmaW5lZCBhcyB0aGUgd2F0Y2ggbWF5IGJlIGEgb25lLXRpbWUgd2F0Y2gNCiAgICAgICAgICBpZiAoaXNVbmRlZmluZWQobmV3VmFsdWUpKSByZXR1cm47DQoNCiAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5ld1ZhbHVlKSkgeyAvLyBpZiBwcmltaXRpdmUNCiAgICAgICAgICAgIGlmIChvbGRWYWx1ZSAhPT0gbmV3VmFsdWUpIHsNCiAgICAgICAgICAgICAgb2xkVmFsdWUgPSBuZXdWYWx1ZTsNCiAgICAgICAgICAgICAgY2hhbmdlRGV0ZWN0ZWQrKzsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXlMaWtlKG5ld1ZhbHVlKSkgew0KICAgICAgICAgICAgaWYgKG9sZFZhbHVlICE9PSBpbnRlcm5hbEFycmF5KSB7DQogICAgICAgICAgICAgIC8vIHdlIGFyZSB0cmFuc2l0aW9uaW5nIGZyb20gc29tZXRoaW5nIHdoaWNoIHdhcyBub3QgYW4gYXJyYXkgaW50byBhcnJheS4NCiAgICAgICAgICAgICAgb2xkVmFsdWUgPSBpbnRlcm5hbEFycmF5Ow0KICAgICAgICAgICAgICBvbGRMZW5ndGggPSBvbGRWYWx1ZS5sZW5ndGggPSAwOw0KICAgICAgICAgICAgICBjaGFuZ2VEZXRlY3RlZCsrOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBuZXdMZW5ndGggPSBuZXdWYWx1ZS5sZW5ndGg7DQoNCiAgICAgICAgICAgIGlmIChvbGRMZW5ndGggIT09IG5ld0xlbmd0aCkgew0KICAgICAgICAgICAgICAvLyBpZiBsZW5ndGhzIGRvIG5vdCBtYXRjaCB3ZSBuZWVkIHRvIHRyaWdnZXIgY2hhbmdlIG5vdGlmaWNhdGlvbg0KICAgICAgICAgICAgICBjaGFuZ2VEZXRlY3RlZCsrOw0KICAgICAgICAgICAgICBvbGRWYWx1ZS5sZW5ndGggPSBvbGRMZW5ndGggPSBuZXdMZW5ndGg7DQogICAgICAgICAgICB9DQogICAgICAgICAgICAvLyBjb3B5IHRoZSBpdGVtcyB0byBvbGRWYWx1ZSBhbmQgbG9vayBmb3IgY2hhbmdlcy4NCiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmV3TGVuZ3RoOyBpKyspIHsNCiAgICAgICAgICAgICAgb2xkSXRlbSA9IG9sZFZhbHVlW2ldOw0KICAgICAgICAgICAgICBuZXdJdGVtID0gbmV3VmFsdWVbaV07DQoNCiAgICAgICAgICAgICAgYm90aE5hTiA9IChvbGRJdGVtICE9PSBvbGRJdGVtKSAmJiAobmV3SXRlbSAhPT0gbmV3SXRlbSk7DQogICAgICAgICAgICAgIGlmICghYm90aE5hTiAmJiAob2xkSXRlbSAhPT0gbmV3SXRlbSkpIHsNCiAgICAgICAgICAgICAgICBjaGFuZ2VEZXRlY3RlZCsrOw0KICAgICAgICAgICAgICAgIG9sZFZhbHVlW2ldID0gbmV3SXRlbTsNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBpZiAob2xkVmFsdWUgIT09IGludGVybmFsT2JqZWN0KSB7DQogICAgICAgICAgICAgIC8vIHdlIGFyZSB0cmFuc2l0aW9uaW5nIGZyb20gc29tZXRoaW5nIHdoaWNoIHdhcyBub3QgYW4gb2JqZWN0IGludG8gb2JqZWN0Lg0KICAgICAgICAgICAgICBvbGRWYWx1ZSA9IGludGVybmFsT2JqZWN0ID0ge307DQogICAgICAgICAgICAgIG9sZExlbmd0aCA9IDA7DQogICAgICAgICAgICAgIGNoYW5nZURldGVjdGVkKys7DQogICAgICAgICAgICB9DQogICAgICAgICAgICAvLyBjb3B5IHRoZSBpdGVtcyB0byBvbGRWYWx1ZSBhbmQgbG9vayBmb3IgY2hhbmdlcy4NCiAgICAgICAgICAgIG5ld0xlbmd0aCA9IDA7DQogICAgICAgICAgICBmb3IgKGtleSBpbiBuZXdWYWx1ZSkgew0KICAgICAgICAgICAgICBpZiAobmV3VmFsdWUuaGFzT3duUHJvcGVydHkoa2V5KSkgew0KICAgICAgICAgICAgICAgIG5ld0xlbmd0aCsrOw0KICAgICAgICAgICAgICAgIG5ld0l0ZW0gPSBuZXdWYWx1ZVtrZXldOw0KICAgICAgICAgICAgICAgIG9sZEl0ZW0gPSBvbGRWYWx1ZVtrZXldOw0KDQogICAgICAgICAgICAgICAgaWYgKGtleSBpbiBvbGRWYWx1ZSkgew0KICAgICAgICAgICAgICAgICAgYm90aE5hTiA9IChvbGRJdGVtICE9PSBvbGRJdGVtKSAmJiAobmV3SXRlbSAhPT0gbmV3SXRlbSk7DQogICAgICAgICAgICAgICAgICBpZiAoIWJvdGhOYU4gJiYgKG9sZEl0ZW0gIT09IG5ld0l0ZW0pKSB7DQogICAgICAgICAgICAgICAgICAgIGNoYW5nZURldGVjdGVkKys7DQogICAgICAgICAgICAgICAgICAgIG9sZFZhbHVlW2tleV0gPSBuZXdJdGVtOw0KICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICBvbGRMZW5ndGgrKzsNCiAgICAgICAgICAgICAgICAgIG9sZFZhbHVlW2tleV0gPSBuZXdJdGVtOw0KICAgICAgICAgICAgICAgICAgY2hhbmdlRGV0ZWN0ZWQrKzsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGlmIChvbGRMZW5ndGggPiBuZXdMZW5ndGgpIHsNCiAgICAgICAgICAgICAgLy8gd2UgdXNlZCB0byBoYXZlIG1vcmUga2V5cywgbmVlZCB0byBmaW5kIHRoZW0gYW5kIGRlc3Ryb3kgdGhlbS4NCiAgICAgICAgICAgICAgY2hhbmdlRGV0ZWN0ZWQrKzsNCiAgICAgICAgICAgICAgZm9yIChrZXkgaW4gb2xkVmFsdWUpIHsNCiAgICAgICAgICAgICAgICBpZiAoIW5ld1ZhbHVlLmhhc093blByb3BlcnR5KGtleSkpIHsNCiAgICAgICAgICAgICAgICAgIG9sZExlbmd0aC0tOw0KICAgICAgICAgICAgICAgICAgZGVsZXRlIG9sZFZhbHVlW2tleV07DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgfQ0KICAgICAgICAgIHJldHVybiBjaGFuZ2VEZXRlY3RlZDsNCiAgICAgICAgfQ0KDQogICAgICAgIGZ1bmN0aW9uICR3YXRjaENvbGxlY3Rpb25BY3Rpb24oKSB7DQogICAgICAgICAgaWYgKGluaXRSdW4pIHsNCiAgICAgICAgICAgIGluaXRSdW4gPSBmYWxzZTsNCiAgICAgICAgICAgIGxpc3RlbmVyKG5ld1ZhbHVlLCBuZXdWYWx1ZSwgc2VsZik7DQogICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGxpc3RlbmVyKG5ld1ZhbHVlLCB2ZXJ5T2xkVmFsdWUsIHNlbGYpOw0KICAgICAgICAgIH0NCg0KICAgICAgICAgIC8vIG1ha2UgYSBjb3B5IGZvciB0aGUgbmV4dCB0aW1lIGEgY29sbGVjdGlvbiBpcyBjaGFuZ2VkDQogICAgICAgICAgaWYgKHRyYWNrVmVyeU9sZFZhbHVlKSB7DQogICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5ld1ZhbHVlKSkgew0KICAgICAgICAgICAgICAvL3ByaW1pdGl2ZQ0KICAgICAgICAgICAgICB2ZXJ5T2xkVmFsdWUgPSBuZXdWYWx1ZTsNCiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheUxpa2UobmV3VmFsdWUpKSB7DQogICAgICAgICAgICAgIHZlcnlPbGRWYWx1ZSA9IG5ldyBBcnJheShuZXdWYWx1ZS5sZW5ndGgpOw0KICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5ld1ZhbHVlLmxlbmd0aDsgaSsrKSB7DQogICAgICAgICAgICAgICAgdmVyeU9sZFZhbHVlW2ldID0gbmV3VmFsdWVbaV07DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0gZWxzZSB7IC8vIGlmIG9iamVjdA0KICAgICAgICAgICAgICB2ZXJ5T2xkVmFsdWUgPSB7fTsNCiAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG5ld1ZhbHVlKSB7DQogICAgICAgICAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwobmV3VmFsdWUsIGtleSkpIHsNCiAgICAgICAgICAgICAgICAgIHZlcnlPbGRWYWx1ZVtrZXldID0gbmV3VmFsdWVba2V5XTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gdGhpcy4kd2F0Y2goY2hhbmdlRGV0ZWN0b3IsICR3YXRjaENvbGxlY3Rpb25BY3Rpb24pOw0KICAgICAgfSwNCg0KICAgICAgLyoqDQogICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgKiBAbmFtZSAkcm9vdFNjb3BlLlNjb3BlIyRkaWdlc3QNCiAgICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICAgKg0KICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgKiBQcm9jZXNzZXMgYWxsIG9mIHRoZSB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSMkd2F0Y2ggd2F0Y2hlcnN9IG9mIHRoZSBjdXJyZW50IHNjb3BlIGFuZA0KICAgICAgICogaXRzIGNoaWxkcmVuLiBCZWNhdXNlIGEge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJHdhdGNoIHdhdGNoZXJ9J3MgbGlzdGVuZXIgY2FuIGNoYW5nZQ0KICAgICAgICogdGhlIG1vZGVsLCB0aGUgYCRkaWdlc3QoKWAga2VlcHMgY2FsbGluZyB0aGUge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJHdhdGNoIHdhdGNoZXJzfQ0KICAgICAgICogdW50aWwgbm8gbW9yZSBsaXN0ZW5lcnMgYXJlIGZpcmluZy4gVGhpcyBtZWFucyB0aGF0IGl0IGlzIHBvc3NpYmxlIHRvIGdldCBpbnRvIGFuIGluZmluaXRlDQogICAgICAgKiBsb29wLiBUaGlzIGZ1bmN0aW9uIHdpbGwgdGhyb3cgYCdNYXhpbXVtIGl0ZXJhdGlvbiBsaW1pdCBleGNlZWRlZC4nYCBpZiB0aGUgbnVtYmVyIG9mDQogICAgICAgKiBpdGVyYXRpb25zIGV4Y2VlZHMgMTAuDQogICAgICAgKg0KICAgICAgICogVXN1YWxseSwgeW91IGRvbid0IGNhbGwgYCRkaWdlc3QoKWAgZGlyZWN0bHkgaW4NCiAgICAgICAqIHtAbGluayBuZy5kaXJlY3RpdmU6bmdDb250cm9sbGVyIGNvbnRyb2xsZXJzfSBvciBpbg0KICAgICAgICoge0BsaW5rIG5nLiRjb21waWxlUHJvdmlkZXIjZGlyZWN0aXZlIGRpcmVjdGl2ZXN9Lg0KICAgICAgICogSW5zdGVhZCwgeW91IHNob3VsZCBjYWxsIHtAbGluayBuZy4kcm9vdFNjb3BlLlNjb3BlIyRhcHBseSAkYXBwbHkoKX0gKHR5cGljYWxseSBmcm9tIHdpdGhpbg0KICAgICAgICogYSB7QGxpbmsgbmcuJGNvbXBpbGVQcm92aWRlciNkaXJlY3RpdmUgZGlyZWN0aXZlfSksIHdoaWNoIHdpbGwgZm9yY2UgYSBgJGRpZ2VzdCgpYC4NCiAgICAgICAqDQogICAgICAgKiBJZiB5b3Ugd2FudCB0byBiZSBub3RpZmllZCB3aGVuZXZlciBgJGRpZ2VzdCgpYCBpcyBjYWxsZWQsDQogICAgICAgKiB5b3UgY2FuIHJlZ2lzdGVyIGEgYHdhdGNoRXhwcmVzc2lvbmAgZnVuY3Rpb24gd2l0aA0KICAgICAgICoge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJHdhdGNoICR3YXRjaCgpfSB3aXRoIG5vIGBsaXN0ZW5lcmAuDQogICAgICAgKg0KICAgICAgICogSW4gdW5pdCB0ZXN0cywgeW91IG1heSBuZWVkIHRvIGNhbGwgYCRkaWdlc3QoKWAgdG8gc2ltdWxhdGUgdGhlIHNjb3BlIGxpZmUgY3ljbGUuDQogICAgICAgKg0KICAgICAgICogIyBFeGFtcGxlDQogICAgICAgKiBgYGBqcw0KICAgICAgICAgICB2YXIgc2NvcGUgPSAuLi47DQogICAgICAgICAgIHNjb3BlLm5hbWUgPSAnbWlza28nOw0KICAgICAgICAgICBzY29wZS5jb3VudGVyID0gMDsNCg0KICAgICAgICAgICBleHBlY3Qoc2NvcGUuY291bnRlcikudG9FcXVhbCgwKTsNCiAgICAgICAgICAgc2NvcGUuJHdhdGNoKCduYW1lJywgZnVuY3Rpb24obmV3VmFsdWUsIG9sZFZhbHVlKSB7DQogICAgICAgICAgICAgc2NvcGUuY291bnRlciA9IHNjb3BlLmNvdW50ZXIgKyAxOw0KICAgICAgICAgICB9KTsNCiAgICAgICAgICAgZXhwZWN0KHNjb3BlLmNvdW50ZXIpLnRvRXF1YWwoMCk7DQoNCiAgICAgICAgICAgc2NvcGUuJGRpZ2VzdCgpOw0KICAgICAgICAgICAvLyB0aGUgbGlzdGVuZXIgaXMgYWx3YXlzIGNhbGxlZCBkdXJpbmcgdGhlIGZpcnN0ICRkaWdlc3QgbG9vcCBhZnRlciBpdCB3YXMgcmVnaXN0ZXJlZA0KICAgICAgICAgICBleHBlY3Qoc2NvcGUuY291bnRlcikudG9FcXVhbCgxKTsNCg0KICAgICAgICAgICBzY29wZS4kZGlnZXN0KCk7DQogICAgICAgICAgIC8vIGJ1dCBub3cgaXQgd2lsbCBub3QgYmUgY2FsbGVkIHVubGVzcyB0aGUgdmFsdWUgY2hhbmdlcw0KICAgICAgICAgICBleHBlY3Qoc2NvcGUuY291bnRlcikudG9FcXVhbCgxKTsNCg0KICAgICAgICAgICBzY29wZS5uYW1lID0gJ2FkYW0nOw0KICAgICAgICAgICBzY29wZS4kZGlnZXN0KCk7DQogICAgICAgICAgIGV4cGVjdChzY29wZS5jb3VudGVyKS50b0VxdWFsKDIpOw0KICAgICAgICogYGBgDQogICAgICAgKg0KICAgICAgICovDQogICAgICAkZGlnZXN0OiBmdW5jdGlvbigpIHsNCiAgICAgICAgdmFyIHdhdGNoLCB2YWx1ZSwgbGFzdCwNCiAgICAgICAgICAgIHdhdGNoZXJzLA0KICAgICAgICAgICAgbGVuZ3RoLA0KICAgICAgICAgICAgZGlydHksIHR0bCA9IFRUTCwNCiAgICAgICAgICAgIG5leHQsIGN1cnJlbnQsIHRhcmdldCA9IHRoaXMsDQogICAgICAgICAgICB3YXRjaExvZyA9IFtdLA0KICAgICAgICAgICAgbG9nSWR4LCBsb2dNc2csIGFzeW5jVGFzazsNCg0KICAgICAgICBiZWdpblBoYXNlKCckZGlnZXN0Jyk7DQogICAgICAgIC8vIENoZWNrIGZvciBjaGFuZ2VzIHRvIGJyb3dzZXIgdXJsIHRoYXQgaGFwcGVuZWQgaW4gc3luYyBiZWZvcmUgdGhlIGNhbGwgdG8gJGRpZ2VzdA0KICAgICAgICAkYnJvd3Nlci4kJGNoZWNrVXJsQ2hhbmdlKCk7DQoNCiAgICAgICAgaWYgKHRoaXMgPT09ICRyb290U2NvcGUgJiYgYXBwbHlBc3luY0lkICE9PSBudWxsKSB7DQogICAgICAgICAgLy8gSWYgdGhpcyBpcyB0aGUgcm9vdCBzY29wZSwgYW5kICRhcHBseUFzeW5jIGhhcyBzY2hlZHVsZWQgYSBkZWZlcnJlZCAkYXBwbHkoKSwgdGhlbg0KICAgICAgICAgIC8vIGNhbmNlbCB0aGUgc2NoZWR1bGVkICRhcHBseSBhbmQgZmx1c2ggdGhlIHF1ZXVlIG9mIGV4cHJlc3Npb25zIHRvIGJlIGV2YWx1YXRlZC4NCiAgICAgICAgICAkYnJvd3Nlci5kZWZlci5jYW5jZWwoYXBwbHlBc3luY0lkKTsNCiAgICAgICAgICBmbHVzaEFwcGx5QXN5bmMoKTsNCiAgICAgICAgfQ0KDQogICAgICAgIGxhc3REaXJ0eVdhdGNoID0gbnVsbDsNCg0KICAgICAgICBkbyB7IC8vICJ3aGlsZSBkaXJ0eSIgbG9vcA0KICAgICAgICAgIGRpcnR5ID0gZmFsc2U7DQogICAgICAgICAgY3VycmVudCA9IHRhcmdldDsNCg0KICAgICAgICAgIHdoaWxlIChhc3luY1F1ZXVlLmxlbmd0aCkgew0KICAgICAgICAgICAgdHJ5IHsNCiAgICAgICAgICAgICAgYXN5bmNUYXNrID0gYXN5bmNRdWV1ZS5zaGlmdCgpOw0KICAgICAgICAgICAgICBhc3luY1Rhc2suc2NvcGUuJGV2YWwoYXN5bmNUYXNrLmV4cHJlc3Npb24sIGFzeW5jVGFzay5sb2NhbHMpOw0KICAgICAgICAgICAgfSBjYXRjaCAoZSkgew0KICAgICAgICAgICAgICAkZXhjZXB0aW9uSGFuZGxlcihlKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGxhc3REaXJ0eVdhdGNoID0gbnVsbDsNCiAgICAgICAgICB9DQoNCiAgICAgICAgICB0cmF2ZXJzZVNjb3Blc0xvb3A6DQogICAgICAgICAgZG8geyAvLyAidHJhdmVyc2UgdGhlIHNjb3BlcyIgbG9vcA0KICAgICAgICAgICAgaWYgKCh3YXRjaGVycyA9IGN1cnJlbnQuJCR3YXRjaGVycykpIHsNCiAgICAgICAgICAgICAgLy8gcHJvY2VzcyBvdXIgd2F0Y2hlcw0KICAgICAgICAgICAgICBsZW5ndGggPSB3YXRjaGVycy5sZW5ndGg7DQogICAgICAgICAgICAgIHdoaWxlIChsZW5ndGgtLSkgew0KICAgICAgICAgICAgICAgIHRyeSB7DQogICAgICAgICAgICAgICAgICB3YXRjaCA9IHdhdGNoZXJzW2xlbmd0aF07DQogICAgICAgICAgICAgICAgICAvLyBNb3N0IGNvbW1vbiB3YXRjaGVzIGFyZSBvbiBwcmltaXRpdmVzLCBpbiB3aGljaCBjYXNlIHdlIGNhbiBzaG9ydA0KICAgICAgICAgICAgICAgICAgLy8gY2lyY3VpdCBpdCB3aXRoID09PSBvcGVyYXRvciwgb25seSB3aGVuID09PSBmYWlscyBkbyB3ZSB1c2UgLmVxdWFscw0KICAgICAgICAgICAgICAgICAgaWYgKHdhdGNoKSB7DQogICAgICAgICAgICAgICAgICAgIGlmICgodmFsdWUgPSB3YXRjaC5nZXQoY3VycmVudCkpICE9PSAobGFzdCA9IHdhdGNoLmxhc3QpICYmDQogICAgICAgICAgICAgICAgICAgICAgICAhKHdhdGNoLmVxDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBlcXVhbHModmFsdWUsIGxhc3QpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgbGFzdCA9PT0gJ251bWJlcicNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmJiBpc05hTih2YWx1ZSkgJiYgaXNOYU4obGFzdCkpKSkgew0KICAgICAgICAgICAgICAgICAgICAgIGRpcnR5ID0gdHJ1ZTsNCiAgICAgICAgICAgICAgICAgICAgICBsYXN0RGlydHlXYXRjaCA9IHdhdGNoOw0KICAgICAgICAgICAgICAgICAgICAgIHdhdGNoLmxhc3QgPSB3YXRjaC5lcSA/IGNvcHkodmFsdWUsIG51bGwpIDogdmFsdWU7DQogICAgICAgICAgICAgICAgICAgICAgd2F0Y2guZm4odmFsdWUsICgobGFzdCA9PT0gaW5pdFdhdGNoVmFsKSA/IHZhbHVlIDogbGFzdCksIGN1cnJlbnQpOw0KICAgICAgICAgICAgICAgICAgICAgIGlmICh0dGwgPCA1KSB7DQogICAgICAgICAgICAgICAgICAgICAgICBsb2dJZHggPSA0IC0gdHRsOw0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF3YXRjaExvZ1tsb2dJZHhdKSB3YXRjaExvZ1tsb2dJZHhdID0gW107DQogICAgICAgICAgICAgICAgICAgICAgICB3YXRjaExvZ1tsb2dJZHhdLnB1c2goew0KICAgICAgICAgICAgICAgICAgICAgICAgICBtc2c6IGlzRnVuY3Rpb24od2F0Y2guZXhwKSA/ICdmbjogJyArICh3YXRjaC5leHAubmFtZSB8fCB3YXRjaC5leHAudG9TdHJpbmcoKSkgOiB3YXRjaC5leHAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1ZhbDogdmFsdWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgIG9sZFZhbDogbGFzdA0KICAgICAgICAgICAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHdhdGNoID09PSBsYXN0RGlydHlXYXRjaCkgew0KICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBtb3N0IHJlY2VudGx5IGRpcnR5IHdhdGNoZXIgaXMgbm93IGNsZWFuLCBzaG9ydCBjaXJjdWl0IHNpbmNlIHRoZSByZW1haW5pbmcgd2F0Y2hlcnMNCiAgICAgICAgICAgICAgICAgICAgICAvLyBoYXZlIGFscmVhZHkgYmVlbiB0ZXN0ZWQuDQogICAgICAgICAgICAgICAgICAgICAgZGlydHkgPSBmYWxzZTsNCiAgICAgICAgICAgICAgICAgICAgICBicmVhayB0cmF2ZXJzZVNjb3Blc0xvb3A7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7DQogICAgICAgICAgICAgICAgICAkZXhjZXB0aW9uSGFuZGxlcihlKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgLy8gSW5zYW5pdHkgV2FybmluZzogc2NvcGUgZGVwdGgtZmlyc3QgdHJhdmVyc2FsDQogICAgICAgICAgICAvLyB5ZXMsIHRoaXMgY29kZSBpcyBhIGJpdCBjcmF6eSwgYnV0IGl0IHdvcmtzIGFuZCB3ZSBoYXZlIHRlc3RzIHRvIHByb3ZlIGl0IQ0KICAgICAgICAgICAgLy8gdGhpcyBwaWVjZSBzaG91bGQgYmUga2VwdCBpbiBzeW5jIHdpdGggdGhlIHRyYXZlcnNhbCBpbiAkYnJvYWRjYXN0DQogICAgICAgICAgICBpZiAoIShuZXh0ID0gKGN1cnJlbnQuJCRjaGlsZEhlYWQgfHwNCiAgICAgICAgICAgICAgICAoY3VycmVudCAhPT0gdGFyZ2V0ICYmIGN1cnJlbnQuJCRuZXh0U2libGluZykpKSkgew0KICAgICAgICAgICAgICB3aGlsZSAoY3VycmVudCAhPT0gdGFyZ2V0ICYmICEobmV4dCA9IGN1cnJlbnQuJCRuZXh0U2libGluZykpIHsNCiAgICAgICAgICAgICAgICBjdXJyZW50ID0gY3VycmVudC4kcGFyZW50Ow0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgfSB3aGlsZSAoKGN1cnJlbnQgPSBuZXh0KSk7DQoNCiAgICAgICAgICAvLyBgYnJlYWsgdHJhdmVyc2VTY29wZXNMb29wO2AgdGFrZXMgdXMgdG8gaGVyZQ0KDQogICAgICAgICAgaWYgKChkaXJ0eSB8fCBhc3luY1F1ZXVlLmxlbmd0aCkgJiYgISh0dGwtLSkpIHsNCiAgICAgICAgICAgIGNsZWFyUGhhc2UoKTsNCiAgICAgICAgICAgIHRocm93ICRyb290U2NvcGVNaW5FcnIoJ2luZmRpZycsDQogICAgICAgICAgICAgICAgJ3swfSAkZGlnZXN0KCkgaXRlcmF0aW9ucyByZWFjaGVkLiBBYm9ydGluZyFcbicgKw0KICAgICAgICAgICAgICAgICdXYXRjaGVycyBmaXJlZCBpbiB0aGUgbGFzdCA1IGl0ZXJhdGlvbnM6IHsxfScsDQogICAgICAgICAgICAgICAgVFRMLCB3YXRjaExvZyk7DQogICAgICAgICAgfQ0KDQogICAgICAgIH0gd2hpbGUgKGRpcnR5IHx8IGFzeW5jUXVldWUubGVuZ3RoKTsNCg0KICAgICAgICBjbGVhclBoYXNlKCk7DQoNCiAgICAgICAgd2hpbGUgKHBvc3REaWdlc3RRdWV1ZS5sZW5ndGgpIHsNCiAgICAgICAgICB0cnkgew0KICAgICAgICAgICAgcG9zdERpZ2VzdFF1ZXVlLnNoaWZ0KCkoKTsNCiAgICAgICAgICB9IGNhdGNoIChlKSB7DQogICAgICAgICAgICAkZXhjZXB0aW9uSGFuZGxlcihlKTsNCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgIH0sDQoNCg0KICAgICAgLyoqDQogICAgICAgKiBAbmdkb2MgZXZlbnQNCiAgICAgICAqIEBuYW1lICRyb290U2NvcGUuU2NvcGUjJGRlc3Ryb3kNCiAgICAgICAqIEBldmVudFR5cGUgYnJvYWRjYXN0IG9uIHNjb3BlIGJlaW5nIGRlc3Ryb3llZA0KICAgICAgICoNCiAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICogQnJvYWRjYXN0ZWQgd2hlbiBhIHNjb3BlIGFuZCBpdHMgY2hpbGRyZW4gYXJlIGJlaW5nIGRlc3Ryb3llZC4NCiAgICAgICAqDQogICAgICAgKiBOb3RlIHRoYXQsIGluIEFuZ3VsYXJKUywgdGhlcmUgaXMgYWxzbyBhIGAkZGVzdHJveWAgalF1ZXJ5IGV2ZW50LCB3aGljaCBjYW4gYmUgdXNlZCB0bw0KICAgICAgICogY2xlYW4gdXAgRE9NIGJpbmRpbmdzIGJlZm9yZSBhbiBlbGVtZW50IGlzIHJlbW92ZWQgZnJvbSB0aGUgRE9NLg0KICAgICAgICovDQoNCiAgICAgIC8qKg0KICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICogQG5hbWUgJHJvb3RTY29wZS5TY29wZSMkZGVzdHJveQ0KICAgICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgICAqDQogICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAqIFJlbW92ZXMgdGhlIGN1cnJlbnQgc2NvcGUgKGFuZCBhbGwgb2YgaXRzIGNoaWxkcmVuKSBmcm9tIHRoZSBwYXJlbnQgc2NvcGUuIFJlbW92YWwgaW1wbGllcw0KICAgICAgICogdGhhdCBjYWxscyB0byB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSMkZGlnZXN0ICRkaWdlc3QoKX0gd2lsbCBubyBsb25nZXINCiAgICAgICAqIHByb3BhZ2F0ZSB0byB0aGUgY3VycmVudCBzY29wZSBhbmQgaXRzIGNoaWxkcmVuLiBSZW1vdmFsIGFsc28gaW1wbGllcyB0aGF0IHRoZSBjdXJyZW50DQogICAgICAgKiBzY29wZSBpcyBlbGlnaWJsZSBmb3IgZ2FyYmFnZSBjb2xsZWN0aW9uLg0KICAgICAgICoNCiAgICAgICAqIFRoZSBgJGRlc3Ryb3koKWAgaXMgdXN1YWxseSB1c2VkIGJ5IGRpcmVjdGl2ZXMgc3VjaCBhcw0KICAgICAgICoge0BsaW5rIG5nLmRpcmVjdGl2ZTpuZ1JlcGVhdCBuZ1JlcGVhdH0gZm9yIG1hbmFnaW5nIHRoZQ0KICAgICAgICogdW5yb2xsaW5nIG9mIHRoZSBsb29wLg0KICAgICAgICoNCiAgICAgICAqIEp1c3QgYmVmb3JlIGEgc2NvcGUgaXMgZGVzdHJveWVkLCBhIGAkZGVzdHJveWAgZXZlbnQgaXMgYnJvYWRjYXN0ZWQgb24gdGhpcyBzY29wZS4NCiAgICAgICAqIEFwcGxpY2F0aW9uIGNvZGUgY2FuIHJlZ2lzdGVyIGEgYCRkZXN0cm95YCBldmVudCBoYW5kbGVyIHRoYXQgd2lsbCBnaXZlIGl0IGEgY2hhbmNlIHRvDQogICAgICAgKiBwZXJmb3JtIGFueSBuZWNlc3NhcnkgY2xlYW51cC4NCiAgICAgICAqDQogICAgICAgKiBOb3RlIHRoYXQsIGluIEFuZ3VsYXJKUywgdGhlcmUgaXMgYWxzbyBhIGAkZGVzdHJveWAgalF1ZXJ5IGV2ZW50LCB3aGljaCBjYW4gYmUgdXNlZCB0bw0KICAgICAgICogY2xlYW4gdXAgRE9NIGJpbmRpbmdzIGJlZm9yZSBhbiBlbGVtZW50IGlzIHJlbW92ZWQgZnJvbSB0aGUgRE9NLg0KICAgICAgICovDQogICAgICAkZGVzdHJveTogZnVuY3Rpb24oKSB7DQogICAgICAgIC8vIHdlIGNhbid0IGRlc3Ryb3kgdGhlIHJvb3Qgc2NvcGUgb3IgYSBzY29wZSB0aGF0IGhhcyBiZWVuIGFscmVhZHkgZGVzdHJveWVkDQogICAgICAgIGlmICh0aGlzLiQkZGVzdHJveWVkKSByZXR1cm47DQogICAgICAgIHZhciBwYXJlbnQgPSB0aGlzLiRwYXJlbnQ7DQoNCiAgICAgICAgdGhpcy4kYnJvYWRjYXN0KCckZGVzdHJveScpOw0KICAgICAgICB0aGlzLiQkZGVzdHJveWVkID0gdHJ1ZTsNCiAgICAgICAgaWYgKHRoaXMgPT09ICRyb290U2NvcGUpIHJldHVybjsNCg0KICAgICAgICBmb3IgKHZhciBldmVudE5hbWUgaW4gdGhpcy4kJGxpc3RlbmVyQ291bnQpIHsNCiAgICAgICAgICBkZWNyZW1lbnRMaXN0ZW5lckNvdW50KHRoaXMsIHRoaXMuJCRsaXN0ZW5lckNvdW50W2V2ZW50TmFtZV0sIGV2ZW50TmFtZSk7DQogICAgICAgIH0NCg0KICAgICAgICAvLyBzZXZlciBhbGwgdGhlIHJlZmVyZW5jZXMgdG8gcGFyZW50IHNjb3BlcyAoYWZ0ZXIgdGhpcyBjbGVhbnVwLCB0aGUgY3VycmVudCBzY29wZSBzaG91bGQNCiAgICAgICAgLy8gbm90IGJlIHJldGFpbmVkIGJ5IGFueSBvZiBvdXIgcmVmZXJlbmNlcyBhbmQgc2hvdWxkIGJlIGVsaWdpYmxlIGZvciBnYXJiYWdlIGNvbGxlY3Rpb24pDQogICAgICAgIGlmIChwYXJlbnQuJCRjaGlsZEhlYWQgPT0gdGhpcykgcGFyZW50LiQkY2hpbGRIZWFkID0gdGhpcy4kJG5leHRTaWJsaW5nOw0KICAgICAgICBpZiAocGFyZW50LiQkY2hpbGRUYWlsID09IHRoaXMpIHBhcmVudC4kJGNoaWxkVGFpbCA9IHRoaXMuJCRwcmV2U2libGluZzsNCiAgICAgICAgaWYgKHRoaXMuJCRwcmV2U2libGluZykgdGhpcy4kJHByZXZTaWJsaW5nLiQkbmV4dFNpYmxpbmcgPSB0aGlzLiQkbmV4dFNpYmxpbmc7DQogICAgICAgIGlmICh0aGlzLiQkbmV4dFNpYmxpbmcpIHRoaXMuJCRuZXh0U2libGluZy4kJHByZXZTaWJsaW5nID0gdGhpcy4kJHByZXZTaWJsaW5nOw0KDQogICAgICAgIC8vIERpc2FibGUgbGlzdGVuZXJzLCB3YXRjaGVycyBhbmQgYXBwbHkvZGlnZXN0IG1ldGhvZHMNCiAgICAgICAgdGhpcy4kZGVzdHJveSA9IHRoaXMuJGRpZ2VzdCA9IHRoaXMuJGFwcGx5ID0gdGhpcy4kZXZhbEFzeW5jID0gdGhpcy4kYXBwbHlBc3luYyA9IG5vb3A7DQogICAgICAgIHRoaXMuJG9uID0gdGhpcy4kd2F0Y2ggPSB0aGlzLiR3YXRjaEdyb3VwID0gZnVuY3Rpb24oKSB7IHJldHVybiBub29wOyB9Ow0KICAgICAgICB0aGlzLiQkbGlzdGVuZXJzID0ge307DQoNCiAgICAgICAgLy8gQWxsIG9mIHRoZSBjb2RlIGJlbG93IGlzIGJvZ3VzIGNvZGUgdGhhdCB3b3JrcyBhcm91bmQgVjgncyBtZW1vcnkgbGVhayB2aWEgb3B0aW1pemVkIGNvZGUNCiAgICAgICAgLy8gYW5kIGlubGluZSBjYWNoZXMuDQogICAgICAgIC8vDQogICAgICAgIC8vIHNlZToNCiAgICAgICAgLy8gLSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MjA3MyNjMjYNCiAgICAgICAgLy8gLSBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9hbmd1bGFyLmpzL2lzc3Vlcy82Nzk0I2lzc3VlY29tbWVudC0zODY0ODkwOQ0KICAgICAgICAvLyAtIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIuanMvaXNzdWVzLzEzMTMjaXNzdWVjb21tZW50LTEwMzc4NDUxDQoNCiAgICAgICAgdGhpcy4kcGFyZW50ID0gdGhpcy4kJG5leHRTaWJsaW5nID0gdGhpcy4kJHByZXZTaWJsaW5nID0gdGhpcy4kJGNoaWxkSGVhZCA9DQogICAgICAgICAgICB0aGlzLiQkY2hpbGRUYWlsID0gdGhpcy4kcm9vdCA9IHRoaXMuJCR3YXRjaGVycyA9IG51bGw7DQogICAgICB9LA0KDQogICAgICAvKioNCiAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAqIEBuYW1lICRyb290U2NvcGUuU2NvcGUjJGV2YWwNCiAgICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICAgKg0KICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgKiBFeGVjdXRlcyB0aGUgYGV4cHJlc3Npb25gIG9uIHRoZSBjdXJyZW50IHNjb3BlIGFuZCByZXR1cm5zIHRoZSByZXN1bHQuIEFueSBleGNlcHRpb25zIGluDQogICAgICAgKiB0aGUgZXhwcmVzc2lvbiBhcmUgcHJvcGFnYXRlZCAodW5jYXVnaHQpLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIGV2YWx1YXRpbmcgQW5ndWxhcg0KICAgICAgICogZXhwcmVzc2lvbnMuDQogICAgICAgKg0KICAgICAgICogIyBFeGFtcGxlDQogICAgICAgKiBgYGBqcw0KICAgICAgICAgICB2YXIgc2NvcGUgPSBuZy4kcm9vdFNjb3BlLlNjb3BlKCk7DQogICAgICAgICAgIHNjb3BlLmEgPSAxOw0KICAgICAgICAgICBzY29wZS5iID0gMjsNCg0KICAgICAgICAgICBleHBlY3Qoc2NvcGUuJGV2YWwoJ2ErYicpKS50b0VxdWFsKDMpOw0KICAgICAgICAgICBleHBlY3Qoc2NvcGUuJGV2YWwoZnVuY3Rpb24oc2NvcGUpeyByZXR1cm4gc2NvcGUuYSArIHNjb3BlLmI7IH0pKS50b0VxdWFsKDMpOw0KICAgICAgICogYGBgDQogICAgICAgKg0KICAgICAgICogQHBhcmFtIHsoc3RyaW5nfGZ1bmN0aW9uKCkpPX0gZXhwcmVzc2lvbiBBbiBhbmd1bGFyIGV4cHJlc3Npb24gdG8gYmUgZXhlY3V0ZWQuDQogICAgICAgKg0KICAgICAgICogICAgLSBgc3RyaW5nYDogZXhlY3V0ZSB1c2luZyB0aGUgcnVsZXMgYXMgZGVmaW5lZCBpbiAge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gZXhwcmVzc2lvbn0uDQogICAgICAgKiAgICAtIGBmdW5jdGlvbihzY29wZSlgOiBleGVjdXRlIHRoZSBmdW5jdGlvbiB3aXRoIHRoZSBjdXJyZW50IGBzY29wZWAgcGFyYW1ldGVyLg0KICAgICAgICoNCiAgICAgICAqIEBwYXJhbSB7KG9iamVjdCk9fSBsb2NhbHMgTG9jYWwgdmFyaWFibGVzIG9iamVjdCwgdXNlZnVsIGZvciBvdmVycmlkaW5nIHZhbHVlcyBpbiBzY29wZS4NCiAgICAgICAqIEByZXR1cm5zIHsqfSBUaGUgcmVzdWx0IG9mIGV2YWx1YXRpbmcgdGhlIGV4cHJlc3Npb24uDQogICAgICAgKi8NCiAgICAgICRldmFsOiBmdW5jdGlvbihleHByLCBsb2NhbHMpIHsNCiAgICAgICAgcmV0dXJuICRwYXJzZShleHByKSh0aGlzLCBsb2NhbHMpOw0KICAgICAgfSwNCg0KICAgICAgLyoqDQogICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgKiBAbmFtZSAkcm9vdFNjb3BlLlNjb3BlIyRldmFsQXN5bmMNCiAgICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICAgKg0KICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgKiBFeGVjdXRlcyB0aGUgZXhwcmVzc2lvbiBvbiB0aGUgY3VycmVudCBzY29wZSBhdCBhIGxhdGVyIHBvaW50IGluIHRpbWUuDQogICAgICAgKg0KICAgICAgICogVGhlIGAkZXZhbEFzeW5jYCBtYWtlcyBubyBndWFyYW50ZWVzIGFzIHRvIHdoZW4gdGhlIGBleHByZXNzaW9uYCB3aWxsIGJlIGV4ZWN1dGVkLCBvbmx5DQogICAgICAgKiB0aGF0Og0KICAgICAgICoNCiAgICAgICAqICAgLSBpdCB3aWxsIGV4ZWN1dGUgYWZ0ZXIgdGhlIGZ1bmN0aW9uIHRoYXQgc2NoZWR1bGVkIHRoZSBldmFsdWF0aW9uIChwcmVmZXJhYmx5IGJlZm9yZSBET00NCiAgICAgICAqICAgICByZW5kZXJpbmcpLg0KICAgICAgICogICAtIGF0IGxlYXN0IG9uZSB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSMkZGlnZXN0ICRkaWdlc3QgY3ljbGV9IHdpbGwgYmUgcGVyZm9ybWVkIGFmdGVyDQogICAgICAgKiAgICAgYGV4cHJlc3Npb25gIGV4ZWN1dGlvbi4NCiAgICAgICAqDQogICAgICAgKiBBbnkgZXhjZXB0aW9ucyBmcm9tIHRoZSBleGVjdXRpb24gb2YgdGhlIGV4cHJlc3Npb24gYXJlIGZvcndhcmRlZCB0byB0aGUNCiAgICAgICAqIHtAbGluayBuZy4kZXhjZXB0aW9uSGFuZGxlciAkZXhjZXB0aW9uSGFuZGxlcn0gc2VydmljZS4NCiAgICAgICAqDQogICAgICAgKiBfX05vdGU6X18gaWYgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgb3V0c2lkZSBvZiBhIGAkZGlnZXN0YCBjeWNsZSwgYSBuZXcgYCRkaWdlc3RgIGN5Y2xlDQogICAgICAgKiB3aWxsIGJlIHNjaGVkdWxlZC4gSG93ZXZlciwgaXQgaXMgZW5jb3VyYWdlZCB0byBhbHdheXMgY2FsbCBjb2RlIHRoYXQgY2hhbmdlcyB0aGUgbW9kZWwNCiAgICAgICAqIGZyb20gd2l0aGluIGFuIGAkYXBwbHlgIGNhbGwuIFRoYXQgaW5jbHVkZXMgY29kZSBldmFsdWF0ZWQgdmlhIGAkZXZhbEFzeW5jYC4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0geyhzdHJpbmd8ZnVuY3Rpb24oKSk9fSBleHByZXNzaW9uIEFuIGFuZ3VsYXIgZXhwcmVzc2lvbiB0byBiZSBleGVjdXRlZC4NCiAgICAgICAqDQogICAgICAgKiAgICAtIGBzdHJpbmdgOiBleGVjdXRlIHVzaW5nIHRoZSBydWxlcyBhcyBkZWZpbmVkIGluIHtAbGluayBndWlkZS9leHByZXNzaW9uIGV4cHJlc3Npb259Lg0KICAgICAgICogICAgLSBgZnVuY3Rpb24oc2NvcGUpYDogZXhlY3V0ZSB0aGUgZnVuY3Rpb24gd2l0aCB0aGUgY3VycmVudCBgc2NvcGVgIHBhcmFtZXRlci4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0geyhvYmplY3QpPX0gbG9jYWxzIExvY2FsIHZhcmlhYmxlcyBvYmplY3QsIHVzZWZ1bCBmb3Igb3ZlcnJpZGluZyB2YWx1ZXMgaW4gc2NvcGUuDQogICAgICAgKi8NCiAgICAgICRldmFsQXN5bmM6IGZ1bmN0aW9uKGV4cHIsIGxvY2Fscykgew0KICAgICAgICAvLyBpZiB3ZSBhcmUgb3V0c2lkZSBvZiBhbiAkZGlnZXN0IGxvb3AgYW5kIHRoaXMgaXMgdGhlIGZpcnN0IHRpbWUgd2UgYXJlIHNjaGVkdWxpbmcgYXN5bmMNCiAgICAgICAgLy8gdGFzayBhbHNvIHNjaGVkdWxlIGFzeW5jIGF1dG8tZmx1c2gNCiAgICAgICAgaWYgKCEkcm9vdFNjb3BlLiQkcGhhc2UgJiYgIWFzeW5jUXVldWUubGVuZ3RoKSB7DQogICAgICAgICAgJGJyb3dzZXIuZGVmZXIoZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBpZiAoYXN5bmNRdWV1ZS5sZW5ndGgpIHsNCiAgICAgICAgICAgICAgJHJvb3RTY29wZS4kZGlnZXN0KCk7DQogICAgICAgICAgICB9DQogICAgICAgICAgfSk7DQogICAgICAgIH0NCg0KICAgICAgICBhc3luY1F1ZXVlLnB1c2goe3Njb3BlOiB0aGlzLCBleHByZXNzaW9uOiBleHByLCBsb2NhbHM6IGxvY2Fsc30pOw0KICAgICAgfSwNCg0KICAgICAgJCRwb3N0RGlnZXN0OiBmdW5jdGlvbihmbikgew0KICAgICAgICBwb3N0RGlnZXN0UXVldWUucHVzaChmbik7DQogICAgICB9LA0KDQogICAgICAvKioNCiAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAqIEBuYW1lICRyb290U2NvcGUuU2NvcGUjJGFwcGx5DQogICAgICAgKiBAa2luZCBmdW5jdGlvbg0KICAgICAgICoNCiAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICogYCRhcHBseSgpYCBpcyB1c2VkIHRvIGV4ZWN1dGUgYW4gZXhwcmVzc2lvbiBpbiBhbmd1bGFyIGZyb20gb3V0c2lkZSBvZiB0aGUgYW5ndWxhcg0KICAgICAgICogZnJhbWV3b3JrLiAoRm9yIGV4YW1wbGUgZnJvbSBicm93c2VyIERPTSBldmVudHMsIHNldFRpbWVvdXQsIFhIUiBvciB0aGlyZCBwYXJ0eSBsaWJyYXJpZXMpLg0KICAgICAgICogQmVjYXVzZSB3ZSBhcmUgY2FsbGluZyBpbnRvIHRoZSBhbmd1bGFyIGZyYW1ld29yayB3ZSBuZWVkIHRvIHBlcmZvcm0gcHJvcGVyIHNjb3BlIGxpZmUNCiAgICAgICAqIGN5Y2xlIG9mIHtAbGluayBuZy4kZXhjZXB0aW9uSGFuZGxlciBleGNlcHRpb24gaGFuZGxpbmd9LA0KICAgICAgICoge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJGRpZ2VzdCBleGVjdXRpbmcgd2F0Y2hlc30uDQogICAgICAgKg0KICAgICAgICogIyMgTGlmZSBjeWNsZQ0KICAgICAgICoNCiAgICAgICAqICMgUHNldWRvLUNvZGUgb2YgYCRhcHBseSgpYA0KICAgICAgICogYGBganMNCiAgICAgICAgICAgZnVuY3Rpb24gJGFwcGx5KGV4cHIpIHsNCiAgICAgICAgICAgICB0cnkgew0KICAgICAgICAgICAgICAgcmV0dXJuICRldmFsKGV4cHIpOw0KICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHsNCiAgICAgICAgICAgICAgICRleGNlcHRpb25IYW5kbGVyKGUpOw0KICAgICAgICAgICAgIH0gZmluYWxseSB7DQogICAgICAgICAgICAgICAkcm9vdC4kZGlnZXN0KCk7DQogICAgICAgICAgICAgfQ0KICAgICAgICAgICB9DQogICAgICAgKiBgYGANCiAgICAgICAqDQogICAgICAgKg0KICAgICAgICogU2NvcGUncyBgJGFwcGx5KClgIG1ldGhvZCB0cmFuc2l0aW9ucyB0aHJvdWdoIHRoZSBmb2xsb3dpbmcgc3RhZ2VzOg0KICAgICAgICoNCiAgICAgICAqIDEuIFRoZSB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBleHByZXNzaW9ufSBpcyBleGVjdXRlZCB1c2luZyB0aGUNCiAgICAgICAqICAgIHtAbGluayBuZy4kcm9vdFNjb3BlLlNjb3BlIyRldmFsICRldmFsKCl9IG1ldGhvZC4NCiAgICAgICAqIDIuIEFueSBleGNlcHRpb25zIGZyb20gdGhlIGV4ZWN1dGlvbiBvZiB0aGUgZXhwcmVzc2lvbiBhcmUgZm9yd2FyZGVkIHRvIHRoZQ0KICAgICAgICogICAge0BsaW5rIG5nLiRleGNlcHRpb25IYW5kbGVyICRleGNlcHRpb25IYW5kbGVyfSBzZXJ2aWNlLg0KICAgICAgICogMy4gVGhlIHtAbGluayBuZy4kcm9vdFNjb3BlLlNjb3BlIyR3YXRjaCB3YXRjaH0gbGlzdGVuZXJzIGFyZSBmaXJlZCBpbW1lZGlhdGVseSBhZnRlciB0aGUNCiAgICAgICAqICAgIGV4cHJlc3Npb24gd2FzIGV4ZWN1dGVkIHVzaW5nIHRoZSB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSMkZGlnZXN0ICRkaWdlc3QoKX0gbWV0aG9kLg0KICAgICAgICoNCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0geyhzdHJpbmd8ZnVuY3Rpb24oKSk9fSBleHAgQW4gYW5ndWxhciBleHByZXNzaW9uIHRvIGJlIGV4ZWN1dGVkLg0KICAgICAgICoNCiAgICAgICAqICAgIC0gYHN0cmluZ2A6IGV4ZWN1dGUgdXNpbmcgdGhlIHJ1bGVzIGFzIGRlZmluZWQgaW4ge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gZXhwcmVzc2lvbn0uDQogICAgICAgKiAgICAtIGBmdW5jdGlvbihzY29wZSlgOiBleGVjdXRlIHRoZSBmdW5jdGlvbiB3aXRoIGN1cnJlbnQgYHNjb3BlYCBwYXJhbWV0ZXIuDQogICAgICAgKg0KICAgICAgICogQHJldHVybnMgeyp9IFRoZSByZXN1bHQgb2YgZXZhbHVhdGluZyB0aGUgZXhwcmVzc2lvbi4NCiAgICAgICAqLw0KICAgICAgJGFwcGx5OiBmdW5jdGlvbihleHByKSB7DQogICAgICAgIHRyeSB7DQogICAgICAgICAgYmVnaW5QaGFzZSgnJGFwcGx5Jyk7DQogICAgICAgICAgcmV0dXJuIHRoaXMuJGV2YWwoZXhwcik7DQogICAgICAgIH0gY2F0Y2ggKGUpIHsNCiAgICAgICAgICAkZXhjZXB0aW9uSGFuZGxlcihlKTsNCiAgICAgICAgfSBmaW5hbGx5IHsNCiAgICAgICAgICBjbGVhclBoYXNlKCk7DQogICAgICAgICAgdHJ5IHsNCiAgICAgICAgICAgICRyb290U2NvcGUuJGRpZ2VzdCgpOw0KICAgICAgICAgIH0gY2F0Y2ggKGUpIHsNCiAgICAgICAgICAgICRleGNlcHRpb25IYW5kbGVyKGUpOw0KICAgICAgICAgICAgdGhyb3cgZTsNCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgIH0sDQoNCiAgICAgIC8qKg0KICAgICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAgICogQG5hbWUgJHJvb3RTY29wZS5TY29wZSMkYXBwbHlBc3luYw0KICAgICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgICAqDQogICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICAqIFNjaGVkdWxlIHRoZSBpbnZva2F0aW9uIG9mICRhcHBseSB0byBvY2N1ciBhdCBhIGxhdGVyIHRpbWUuIFRoZSBhY3R1YWwgdGltZSBkaWZmZXJlbmNlDQogICAgICAgKiB2YXJpZXMgYWNyb3NzIGJyb3dzZXJzLCBidXQgaXMgdHlwaWNhbGx5IGFyb3VuZCB+MTAgbWlsbGlzZWNvbmRzLg0KICAgICAgICoNCiAgICAgICAqIFRoaXMgY2FuIGJlIHVzZWQgdG8gcXVldWUgdXAgbXVsdGlwbGUgZXhwcmVzc2lvbnMgd2hpY2ggbmVlZCB0byBiZSBldmFsdWF0ZWQgaW4gdGhlIHNhbWUNCiAgICAgICAqIGRpZ2VzdC4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0geyhzdHJpbmd8ZnVuY3Rpb24oKSk9fSBleHAgQW4gYW5ndWxhciBleHByZXNzaW9uIHRvIGJlIGV4ZWN1dGVkLg0KICAgICAgICoNCiAgICAgICAqICAgIC0gYHN0cmluZ2A6IGV4ZWN1dGUgdXNpbmcgdGhlIHJ1bGVzIGFzIGRlZmluZWQgaW4ge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gZXhwcmVzc2lvbn0uDQogICAgICAgKiAgICAtIGBmdW5jdGlvbihzY29wZSlgOiBleGVjdXRlIHRoZSBmdW5jdGlvbiB3aXRoIGN1cnJlbnQgYHNjb3BlYCBwYXJhbWV0ZXIuDQogICAgICAgKi8NCiAgICAgICRhcHBseUFzeW5jOiBmdW5jdGlvbihleHByKSB7DQogICAgICAgIHZhciBzY29wZSA9IHRoaXM7DQogICAgICAgIGV4cHIgJiYgYXBwbHlBc3luY1F1ZXVlLnB1c2goJGFwcGx5QXN5bmNFeHByZXNzaW9uKTsNCiAgICAgICAgc2NoZWR1bGVBcHBseUFzeW5jKCk7DQoNCiAgICAgICAgZnVuY3Rpb24gJGFwcGx5QXN5bmNFeHByZXNzaW9uKCkgew0KICAgICAgICAgIHNjb3BlLiRldmFsKGV4cHIpOw0KICAgICAgICB9DQogICAgICB9LA0KDQogICAgICAvKioNCiAgICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgICAqIEBuYW1lICRyb290U2NvcGUuU2NvcGUjJG9uDQogICAgICAgKiBAa2luZCBmdW5jdGlvbg0KICAgICAgICoNCiAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICogTGlzdGVucyBvbiBldmVudHMgb2YgYSBnaXZlbiB0eXBlLiBTZWUge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJGVtaXQgJGVtaXR9IGZvcg0KICAgICAgICogZGlzY3Vzc2lvbiBvZiBldmVudCBsaWZlIGN5Y2xlLg0KICAgICAgICoNCiAgICAgICAqIFRoZSBldmVudCBsaXN0ZW5lciBmdW5jdGlvbiBmb3JtYXQgaXM6IGBmdW5jdGlvbihldmVudCwgYXJncy4uLilgLiBUaGUgYGV2ZW50YCBvYmplY3QNCiAgICAgICAqIHBhc3NlZCBpbnRvIHRoZSBsaXN0ZW5lciBoYXMgdGhlIGZvbGxvd2luZyBhdHRyaWJ1dGVzOg0KICAgICAgICoNCiAgICAgICAqICAgLSBgdGFyZ2V0U2NvcGVgIC0gYHtTY29wZX1gOiB0aGUgc2NvcGUgb24gd2hpY2ggdGhlIGV2ZW50IHdhcyBgJGVtaXRgLWVkIG9yDQogICAgICAgKiAgICAgYCRicm9hZGNhc3RgLWVkLg0KICAgICAgICogICAtIGBjdXJyZW50U2NvcGVgIC0gYHtTY29wZX1gOiB0aGUgc2NvcGUgdGhhdCBpcyBjdXJyZW50bHkgaGFuZGxpbmcgdGhlIGV2ZW50LiBPbmNlIHRoZQ0KICAgICAgICogICAgIGV2ZW50IHByb3BhZ2F0ZXMgdGhyb3VnaCB0aGUgc2NvcGUgaGllcmFyY2h5LCB0aGlzIHByb3BlcnR5IGlzIHNldCB0byBudWxsLg0KICAgICAgICogICAtIGBuYW1lYCAtIGB7c3RyaW5nfWA6IG5hbWUgb2YgdGhlIGV2ZW50Lg0KICAgICAgICogICAtIGBzdG9wUHJvcGFnYXRpb25gIC0gYHtmdW5jdGlvbj19YDogY2FsbGluZyBgc3RvcFByb3BhZ2F0aW9uYCBmdW5jdGlvbiB3aWxsIGNhbmNlbA0KICAgICAgICogICAgIGZ1cnRoZXIgZXZlbnQgcHJvcGFnYXRpb24gKGF2YWlsYWJsZSBvbmx5IGZvciBldmVudHMgdGhhdCB3ZXJlIGAkZW1pdGAtZWQpLg0KICAgICAgICogICAtIGBwcmV2ZW50RGVmYXVsdGAgLSBge2Z1bmN0aW9ufWA6IGNhbGxpbmcgYHByZXZlbnREZWZhdWx0YCBzZXRzIGBkZWZhdWx0UHJldmVudGVkYCBmbGFnDQogICAgICAgKiAgICAgdG8gdHJ1ZS4NCiAgICAgICAqICAgLSBgZGVmYXVsdFByZXZlbnRlZGAgLSBge2Jvb2xlYW59YDogdHJ1ZSBpZiBgcHJldmVudERlZmF1bHRgIHdhcyBjYWxsZWQuDQogICAgICAgKg0KICAgICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgRXZlbnQgbmFtZSB0byBsaXN0ZW4gb24uDQogICAgICAgKiBAcGFyYW0ge2Z1bmN0aW9uKGV2ZW50LCAuLi5hcmdzKX0gbGlzdGVuZXIgRnVuY3Rpb24gdG8gY2FsbCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLg0KICAgICAgICogQHJldHVybnMge2Z1bmN0aW9uKCl9IFJldHVybnMgYSBkZXJlZ2lzdHJhdGlvbiBmdW5jdGlvbiBmb3IgdGhpcyBsaXN0ZW5lci4NCiAgICAgICAqLw0KICAgICAgJG9uOiBmdW5jdGlvbihuYW1lLCBsaXN0ZW5lcikgew0KICAgICAgICB2YXIgbmFtZWRMaXN0ZW5lcnMgPSB0aGlzLiQkbGlzdGVuZXJzW25hbWVdOw0KICAgICAgICBpZiAoIW5hbWVkTGlzdGVuZXJzKSB7DQogICAgICAgICAgdGhpcy4kJGxpc3RlbmVyc1tuYW1lXSA9IG5hbWVkTGlzdGVuZXJzID0gW107DQogICAgICAgIH0NCiAgICAgICAgbmFtZWRMaXN0ZW5lcnMucHVzaChsaXN0ZW5lcik7DQoNCiAgICAgICAgdmFyIGN1cnJlbnQgPSB0aGlzOw0KICAgICAgICBkbyB7DQogICAgICAgICAgaWYgKCFjdXJyZW50LiQkbGlzdGVuZXJDb3VudFtuYW1lXSkgew0KICAgICAgICAgICAgY3VycmVudC4kJGxpc3RlbmVyQ291bnRbbmFtZV0gPSAwOw0KICAgICAgICAgIH0NCiAgICAgICAgICBjdXJyZW50LiQkbGlzdGVuZXJDb3VudFtuYW1lXSsrOw0KICAgICAgICB9IHdoaWxlICgoY3VycmVudCA9IGN1cnJlbnQuJHBhcmVudCkpOw0KDQogICAgICAgIHZhciBzZWxmID0gdGhpczsNCiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkgew0KICAgICAgICAgIHZhciBpbmRleE9mTGlzdGVuZXIgPSBuYW1lZExpc3RlbmVycy5pbmRleE9mKGxpc3RlbmVyKTsNCiAgICAgICAgICBpZiAoaW5kZXhPZkxpc3RlbmVyICE9PSAtMSkgew0KICAgICAgICAgICAgbmFtZWRMaXN0ZW5lcnNbaW5kZXhPZkxpc3RlbmVyXSA9IG51bGw7DQogICAgICAgICAgICBkZWNyZW1lbnRMaXN0ZW5lckNvdW50KHNlbGYsIDEsIG5hbWUpOw0KICAgICAgICAgIH0NCiAgICAgICAgfTsNCiAgICAgIH0sDQoNCg0KICAgICAgLyoqDQogICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgKiBAbmFtZSAkcm9vdFNjb3BlLlNjb3BlIyRlbWl0DQogICAgICAgKiBAa2luZCBmdW5jdGlvbg0KICAgICAgICoNCiAgICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAgICogRGlzcGF0Y2hlcyBhbiBldmVudCBgbmFtZWAgdXB3YXJkcyB0aHJvdWdoIHRoZSBzY29wZSBoaWVyYXJjaHkgbm90aWZ5aW5nIHRoZQ0KICAgICAgICogcmVnaXN0ZXJlZCB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSMkb259IGxpc3RlbmVycy4NCiAgICAgICAqDQogICAgICAgKiBUaGUgZXZlbnQgbGlmZSBjeWNsZSBzdGFydHMgYXQgdGhlIHNjb3BlIG9uIHdoaWNoIGAkZW1pdGAgd2FzIGNhbGxlZC4gQWxsDQogICAgICAgKiB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSMkb24gbGlzdGVuZXJzfSBsaXN0ZW5pbmcgZm9yIGBuYW1lYCBldmVudCBvbiB0aGlzIHNjb3BlIGdldA0KICAgICAgICogbm90aWZpZWQuIEFmdGVyd2FyZHMsIHRoZSBldmVudCB0cmF2ZXJzZXMgdXB3YXJkcyB0b3dhcmQgdGhlIHJvb3Qgc2NvcGUgYW5kIGNhbGxzIGFsbA0KICAgICAgICogcmVnaXN0ZXJlZCBsaXN0ZW5lcnMgYWxvbmcgdGhlIHdheS4gVGhlIGV2ZW50IHdpbGwgc3RvcCBwcm9wYWdhdGluZyBpZiBvbmUgb2YgdGhlIGxpc3RlbmVycw0KICAgICAgICogY2FuY2VscyBpdC4NCiAgICAgICAqDQogICAgICAgKiBBbnkgZXhjZXB0aW9uIGVtaXR0ZWQgZnJvbSB0aGUge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJG9uIGxpc3RlbmVyc30gd2lsbCBiZSBwYXNzZWQNCiAgICAgICAqIG9udG8gdGhlIHtAbGluayBuZy4kZXhjZXB0aW9uSGFuZGxlciAkZXhjZXB0aW9uSGFuZGxlcn0gc2VydmljZS4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBFdmVudCBuYW1lIHRvIGVtaXQuDQogICAgICAgKiBAcGFyYW0gey4uLip9IGFyZ3MgT3B0aW9uYWwgb25lIG9yIG1vcmUgYXJndW1lbnRzIHdoaWNoIHdpbGwgYmUgcGFzc2VkIG9udG8gdGhlIGV2ZW50IGxpc3RlbmVycy4NCiAgICAgICAqIEByZXR1cm4ge09iamVjdH0gRXZlbnQgb2JqZWN0IChzZWUge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJG9ufSkuDQogICAgICAgKi8NCiAgICAgICRlbWl0OiBmdW5jdGlvbihuYW1lLCBhcmdzKSB7DQogICAgICAgIHZhciBlbXB0eSA9IFtdLA0KICAgICAgICAgICAgbmFtZWRMaXN0ZW5lcnMsDQogICAgICAgICAgICBzY29wZSA9IHRoaXMsDQogICAgICAgICAgICBzdG9wUHJvcGFnYXRpb24gPSBmYWxzZSwNCiAgICAgICAgICAgIGV2ZW50ID0gew0KICAgICAgICAgICAgICBuYW1lOiBuYW1lLA0KICAgICAgICAgICAgICB0YXJnZXRTY29wZTogc2NvcGUsDQogICAgICAgICAgICAgIHN0b3BQcm9wYWdhdGlvbjogZnVuY3Rpb24oKSB7c3RvcFByb3BhZ2F0aW9uID0gdHJ1ZTt9LA0KICAgICAgICAgICAgICBwcmV2ZW50RGVmYXVsdDogZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgICAgZXZlbnQuZGVmYXVsdFByZXZlbnRlZCA9IHRydWU7DQogICAgICAgICAgICAgIH0sDQogICAgICAgICAgICAgIGRlZmF1bHRQcmV2ZW50ZWQ6IGZhbHNlDQogICAgICAgICAgICB9LA0KICAgICAgICAgICAgbGlzdGVuZXJBcmdzID0gY29uY2F0KFtldmVudF0sIGFyZ3VtZW50cywgMSksDQogICAgICAgICAgICBpLCBsZW5ndGg7DQoNCiAgICAgICAgZG8gew0KICAgICAgICAgIG5hbWVkTGlzdGVuZXJzID0gc2NvcGUuJCRsaXN0ZW5lcnNbbmFtZV0gfHwgZW1wdHk7DQogICAgICAgICAgZXZlbnQuY3VycmVudFNjb3BlID0gc2NvcGU7DQogICAgICAgICAgZm9yIChpID0gMCwgbGVuZ3RoID0gbmFtZWRMaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsNCg0KICAgICAgICAgICAgLy8gaWYgbGlzdGVuZXJzIHdlcmUgZGVyZWdpc3RlcmVkLCBkZWZyYWdtZW50IHRoZSBhcnJheQ0KICAgICAgICAgICAgaWYgKCFuYW1lZExpc3RlbmVyc1tpXSkgew0KICAgICAgICAgICAgICBuYW1lZExpc3RlbmVycy5zcGxpY2UoaSwgMSk7DQogICAgICAgICAgICAgIGktLTsNCiAgICAgICAgICAgICAgbGVuZ3RoLS07DQogICAgICAgICAgICAgIGNvbnRpbnVlOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgdHJ5IHsNCiAgICAgICAgICAgICAgLy9hbGxvdyBhbGwgbGlzdGVuZXJzIGF0dGFjaGVkIHRvIHRoZSBjdXJyZW50IHNjb3BlIHRvIHJ1bg0KICAgICAgICAgICAgICBuYW1lZExpc3RlbmVyc1tpXS5hcHBseShudWxsLCBsaXN0ZW5lckFyZ3MpOw0KICAgICAgICAgICAgfSBjYXRjaCAoZSkgew0KICAgICAgICAgICAgICAkZXhjZXB0aW9uSGFuZGxlcihlKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9DQogICAgICAgICAgLy9pZiBhbnkgbGlzdGVuZXIgb24gdGhlIGN1cnJlbnQgc2NvcGUgc3RvcHMgcHJvcGFnYXRpb24sIHByZXZlbnQgYnViYmxpbmcNCiAgICAgICAgICBpZiAoc3RvcFByb3BhZ2F0aW9uKSB7DQogICAgICAgICAgICBldmVudC5jdXJyZW50U2NvcGUgPSBudWxsOw0KICAgICAgICAgICAgcmV0dXJuIGV2ZW50Ow0KICAgICAgICAgIH0NCiAgICAgICAgICAvL3RyYXZlcnNlIHVwd2FyZHMNCiAgICAgICAgICBzY29wZSA9IHNjb3BlLiRwYXJlbnQ7DQogICAgICAgIH0gd2hpbGUgKHNjb3BlKTsNCg0KICAgICAgICBldmVudC5jdXJyZW50U2NvcGUgPSBudWxsOw0KDQogICAgICAgIHJldHVybiBldmVudDsNCiAgICAgIH0sDQoNCg0KICAgICAgLyoqDQogICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAgKiBAbmFtZSAkcm9vdFNjb3BlLlNjb3BlIyRicm9hZGNhc3QNCiAgICAgICAqIEBraW5kIGZ1bmN0aW9uDQogICAgICAgKg0KICAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAgKiBEaXNwYXRjaGVzIGFuIGV2ZW50IGBuYW1lYCBkb3dud2FyZHMgdG8gYWxsIGNoaWxkIHNjb3BlcyAoYW5kIHRoZWlyIGNoaWxkcmVuKSBub3RpZnlpbmcgdGhlDQogICAgICAgKiByZWdpc3RlcmVkIHtAbGluayBuZy4kcm9vdFNjb3BlLlNjb3BlIyRvbn0gbGlzdGVuZXJzLg0KICAgICAgICoNCiAgICAgICAqIFRoZSBldmVudCBsaWZlIGN5Y2xlIHN0YXJ0cyBhdCB0aGUgc2NvcGUgb24gd2hpY2ggYCRicm9hZGNhc3RgIHdhcyBjYWxsZWQuIEFsbA0KICAgICAgICoge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJG9uIGxpc3RlbmVyc30gbGlzdGVuaW5nIGZvciBgbmFtZWAgZXZlbnQgb24gdGhpcyBzY29wZSBnZXQNCiAgICAgICAqIG5vdGlmaWVkLiBBZnRlcndhcmRzLCB0aGUgZXZlbnQgcHJvcGFnYXRlcyB0byBhbGwgZGlyZWN0IGFuZCBpbmRpcmVjdCBzY29wZXMgb2YgdGhlIGN1cnJlbnQNCiAgICAgICAqIHNjb3BlIGFuZCBjYWxscyBhbGwgcmVnaXN0ZXJlZCBsaXN0ZW5lcnMgYWxvbmcgdGhlIHdheS4gVGhlIGV2ZW50IGNhbm5vdCBiZSBjYW5jZWxlZC4NCiAgICAgICAqDQogICAgICAgKiBBbnkgZXhjZXB0aW9uIGVtaXR0ZWQgZnJvbSB0aGUge0BsaW5rIG5nLiRyb290U2NvcGUuU2NvcGUjJG9uIGxpc3RlbmVyc30gd2lsbCBiZSBwYXNzZWQNCiAgICAgICAqIG9udG8gdGhlIHtAbGluayBuZy4kZXhjZXB0aW9uSGFuZGxlciAkZXhjZXB0aW9uSGFuZGxlcn0gc2VydmljZS4NCiAgICAgICAqDQogICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBFdmVudCBuYW1lIHRvIGJyb2FkY2FzdC4NCiAgICAgICAqIEBwYXJhbSB7Li4uKn0gYXJncyBPcHRpb25hbCBvbmUgb3IgbW9yZSBhcmd1bWVudHMgd2hpY2ggd2lsbCBiZSBwYXNzZWQgb250byB0aGUgZXZlbnQgbGlzdGVuZXJzLg0KICAgICAgICogQHJldHVybiB7T2JqZWN0fSBFdmVudCBvYmplY3QsIHNlZSB7QGxpbmsgbmcuJHJvb3RTY29wZS5TY29wZSMkb259DQogICAgICAgKi8NCiAgICAgICRicm9hZGNhc3Q6IGZ1bmN0aW9uKG5hbWUsIGFyZ3MpIHsNCiAgICAgICAgdmFyIHRhcmdldCA9IHRoaXMsDQogICAgICAgICAgICBjdXJyZW50ID0gdGFyZ2V0LA0KICAgICAgICAgICAgbmV4dCA9IHRhcmdldCwNCiAgICAgICAgICAgIGV2ZW50ID0gew0KICAgICAgICAgICAgICBuYW1lOiBuYW1lLA0KICAgICAgICAgICAgICB0YXJnZXRTY29wZTogdGFyZ2V0LA0KICAgICAgICAgICAgICBwcmV2ZW50RGVmYXVsdDogZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgICAgZXZlbnQuZGVmYXVsdFByZXZlbnRlZCA9IHRydWU7DQogICAgICAgICAgICAgIH0sDQogICAgICAgICAgICAgIGRlZmF1bHRQcmV2ZW50ZWQ6IGZhbHNlDQogICAgICAgICAgICB9Ow0KDQogICAgICAgIGlmICghdGFyZ2V0LiQkbGlzdGVuZXJDb3VudFtuYW1lXSkgcmV0dXJuIGV2ZW50Ow0KDQogICAgICAgIHZhciBsaXN0ZW5lckFyZ3MgPSBjb25jYXQoW2V2ZW50XSwgYXJndW1lbnRzLCAxKSwNCiAgICAgICAgICAgIGxpc3RlbmVycywgaSwgbGVuZ3RoOw0KDQogICAgICAgIC8vZG93biB3aGlsZSB5b3UgY2FuLCB0aGVuIHVwIGFuZCBuZXh0IHNpYmxpbmcgb3IgdXAgYW5kIG5leHQgc2libGluZyB1bnRpbCBiYWNrIGF0IHJvb3QNCiAgICAgICAgd2hpbGUgKChjdXJyZW50ID0gbmV4dCkpIHsNCiAgICAgICAgICBldmVudC5jdXJyZW50U2NvcGUgPSBjdXJyZW50Ow0KICAgICAgICAgIGxpc3RlbmVycyA9IGN1cnJlbnQuJCRsaXN0ZW5lcnNbbmFtZV0gfHwgW107DQogICAgICAgICAgZm9yIChpID0gMCwgbGVuZ3RoID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7DQogICAgICAgICAgICAvLyBpZiBsaXN0ZW5lcnMgd2VyZSBkZXJlZ2lzdGVyZWQsIGRlZnJhZ21lbnQgdGhlIGFycmF5DQogICAgICAgICAgICBpZiAoIWxpc3RlbmVyc1tpXSkgew0KICAgICAgICAgICAgICBsaXN0ZW5lcnMuc3BsaWNlKGksIDEpOw0KICAgICAgICAgICAgICBpLS07DQogICAgICAgICAgICAgIGxlbmd0aC0tOw0KICAgICAgICAgICAgICBjb250aW51ZTsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgdHJ5IHsNCiAgICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KG51bGwsIGxpc3RlbmVyQXJncyk7DQogICAgICAgICAgICB9IGNhdGNoIChlKSB7DQogICAgICAgICAgICAgICRleGNlcHRpb25IYW5kbGVyKGUpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0NCg0KICAgICAgICAgIC8vIEluc2FuaXR5IFdhcm5pbmc6IHNjb3BlIGRlcHRoLWZpcnN0IHRyYXZlcnNhbA0KICAgICAgICAgIC8vIHllcywgdGhpcyBjb2RlIGlzIGEgYml0IGNyYXp5LCBidXQgaXQgd29ya3MgYW5kIHdlIGhhdmUgdGVzdHMgdG8gcHJvdmUgaXQhDQogICAgICAgICAgLy8gdGhpcyBwaWVjZSBzaG91bGQgYmUga2VwdCBpbiBzeW5jIHdpdGggdGhlIHRyYXZlcnNhbCBpbiAkZGlnZXN0DQogICAgICAgICAgLy8gKHRob3VnaCBpdCBkaWZmZXJzIGR1ZSB0byBoYXZpbmcgdGhlIGV4dHJhIGNoZWNrIGZvciAkJGxpc3RlbmVyQ291bnQpDQogICAgICAgICAgaWYgKCEobmV4dCA9ICgoY3VycmVudC4kJGxpc3RlbmVyQ291bnRbbmFtZV0gJiYgY3VycmVudC4kJGNoaWxkSGVhZCkgfHwNCiAgICAgICAgICAgICAgKGN1cnJlbnQgIT09IHRhcmdldCAmJiBjdXJyZW50LiQkbmV4dFNpYmxpbmcpKSkpIHsNCiAgICAgICAgICAgIHdoaWxlIChjdXJyZW50ICE9PSB0YXJnZXQgJiYgIShuZXh0ID0gY3VycmVudC4kJG5leHRTaWJsaW5nKSkgew0KICAgICAgICAgICAgICBjdXJyZW50ID0gY3VycmVudC4kcGFyZW50Ow0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGV2ZW50LmN1cnJlbnRTY29wZSA9IG51bGw7DQogICAgICAgIHJldHVybiBldmVudDsNCiAgICAgIH0NCiAgICB9Ow0KDQogICAgdmFyICRyb290U2NvcGUgPSBuZXcgU2NvcGUoKTsNCg0KICAgIC8vVGhlIGludGVybmFsIHF1ZXVlcy4gRXhwb3NlIHRoZW0gb24gdGhlICRyb290U2NvcGUgZm9yIGRlYnVnZ2luZy90ZXN0aW5nIHB1cnBvc2VzLg0KICAgIHZhciBhc3luY1F1ZXVlID0gJHJvb3RTY29wZS4kJGFzeW5jUXVldWUgPSBbXTsNCiAgICB2YXIgcG9zdERpZ2VzdFF1ZXVlID0gJHJvb3RTY29wZS4kJHBvc3REaWdlc3RRdWV1ZSA9IFtdOw0KICAgIHZhciBhcHBseUFzeW5jUXVldWUgPSAkcm9vdFNjb3BlLiQkYXBwbHlBc3luY1F1ZXVlID0gW107DQoNCiAgICByZXR1cm4gJHJvb3RTY29wZTsNCg0KDQogICAgZnVuY3Rpb24gYmVnaW5QaGFzZShwaGFzZSkgew0KICAgICAgaWYgKCRyb290U2NvcGUuJCRwaGFzZSkgew0KICAgICAgICB0aHJvdyAkcm9vdFNjb3BlTWluRXJyKCdpbnByb2cnLCAnezB9IGFscmVhZHkgaW4gcHJvZ3Jlc3MnLCAkcm9vdFNjb3BlLiQkcGhhc2UpOw0KICAgICAgfQ0KDQogICAgICAkcm9vdFNjb3BlLiQkcGhhc2UgPSBwaGFzZTsNCiAgICB9DQoNCiAgICBmdW5jdGlvbiBjbGVhclBoYXNlKCkgew0KICAgICAgJHJvb3RTY29wZS4kJHBoYXNlID0gbnVsbDsNCiAgICB9DQoNCg0KICAgIGZ1bmN0aW9uIGRlY3JlbWVudExpc3RlbmVyQ291bnQoY3VycmVudCwgY291bnQsIG5hbWUpIHsNCiAgICAgIGRvIHsNCiAgICAgICAgY3VycmVudC4kJGxpc3RlbmVyQ291bnRbbmFtZV0gLT0gY291bnQ7DQoNCiAgICAgICAgaWYgKGN1cnJlbnQuJCRsaXN0ZW5lckNvdW50W25hbWVdID09PSAwKSB7DQogICAgICAgICAgZGVsZXRlIGN1cnJlbnQuJCRsaXN0ZW5lckNvdW50W25hbWVdOw0KICAgICAgICB9DQogICAgICB9IHdoaWxlICgoY3VycmVudCA9IGN1cnJlbnQuJHBhcmVudCkpOw0KICAgIH0NCg0KICAgIC8qKg0KICAgICAqIGZ1bmN0aW9uIHVzZWQgYXMgYW4gaW5pdGlhbCB2YWx1ZSBmb3Igd2F0Y2hlcnMuDQogICAgICogYmVjYXVzZSBpdCdzIHVuaXF1ZSB3ZSBjYW4gZWFzaWx5IHRlbGwgaXQgYXBhcnQgZnJvbSBvdGhlciB2YWx1ZXMNCiAgICAgKi8NCiAgICBmdW5jdGlvbiBpbml0V2F0Y2hWYWwoKSB7fQ0KDQogICAgZnVuY3Rpb24gZmx1c2hBcHBseUFzeW5jKCkgew0KICAgICAgd2hpbGUgKGFwcGx5QXN5bmNRdWV1ZS5sZW5ndGgpIHsNCiAgICAgICAgdHJ5IHsNCiAgICAgICAgICBhcHBseUFzeW5jUXVldWUuc2hpZnQoKSgpOw0KICAgICAgICB9IGNhdGNoIChlKSB7DQogICAgICAgICAgJGV4Y2VwdGlvbkhhbmRsZXIoZSk7DQogICAgICAgIH0NCiAgICAgIH0NCiAgICAgIGFwcGx5QXN5bmNJZCA9IG51bGw7DQogICAgfQ0KDQogICAgZnVuY3Rpb24gc2NoZWR1bGVBcHBseUFzeW5jKCkgew0KICAgICAgaWYgKGFwcGx5QXN5bmNJZCA9PT0gbnVsbCkgew0KICAgICAgICBhcHBseUFzeW5jSWQgPSAkYnJvd3Nlci5kZWZlcihmdW5jdGlvbigpIHsNCiAgICAgICAgICAkcm9vdFNjb3BlLiRhcHBseShmbHVzaEFwcGx5QXN5bmMpOw0KICAgICAgICB9KTsNCiAgICAgIH0NCiAgICB9DQogIH1dOw0KfQ0KDQovKioNCiAqIEBkZXNjcmlwdGlvbg0KICogUHJpdmF0ZSBzZXJ2aWNlIHRvIHNhbml0aXplIHVyaXMgZm9yIGxpbmtzIGFuZCBpbWFnZXMuIFVzZWQgYnkgJGNvbXBpbGUgYW5kICRzYW5pdGl6ZS4NCiAqLw0KZnVuY3Rpb24gJCRTYW5pdGl6ZVVyaVByb3ZpZGVyKCkgew0KICB2YXIgYUhyZWZTYW5pdGl6YXRpb25XaGl0ZWxpc3QgPSAvXlxzKihodHRwcz98ZnRwfG1haWx0b3x0ZWx8ZmlsZSk6LywNCiAgICBpbWdTcmNTYW5pdGl6YXRpb25XaGl0ZWxpc3QgPSAvXlxzKigoaHR0cHM/fGZ0cHxmaWxlfGJsb2IpOnxkYXRhOmltYWdlXC8pLzsNCg0KICAvKioNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFJldHJpZXZlcyBvciBvdmVycmlkZXMgdGhlIGRlZmF1bHQgcmVndWxhciBleHByZXNzaW9uIHRoYXQgaXMgdXNlZCBmb3Igd2hpdGVsaXN0aW5nIG9mIHNhZmUNCiAgICogdXJscyBkdXJpbmcgYVtocmVmXSBzYW5pdGl6YXRpb24uDQogICAqDQogICAqIFRoZSBzYW5pdGl6YXRpb24gaXMgYSBzZWN1cml0eSBtZWFzdXJlIGFpbWVkIGF0IHByZXZlbnQgWFNTIGF0dGFja3MgdmlhIGh0bWwgbGlua3MuDQogICAqDQogICAqIEFueSB1cmwgYWJvdXQgdG8gYmUgYXNzaWduZWQgdG8gYVtocmVmXSB2aWEgZGF0YS1iaW5kaW5nIGlzIGZpcnN0IG5vcm1hbGl6ZWQgYW5kIHR1cm5lZCBpbnRvDQogICAqIGFuIGFic29sdXRlIHVybC4gQWZ0ZXJ3YXJkcywgdGhlIHVybCBpcyBtYXRjaGVkIGFnYWluc3QgdGhlIGBhSHJlZlNhbml0aXphdGlvbldoaXRlbGlzdGANCiAgICogcmVndWxhciBleHByZXNzaW9uLiBJZiBhIG1hdGNoIGlzIGZvdW5kLCB0aGUgb3JpZ2luYWwgdXJsIGlzIHdyaXR0ZW4gaW50byB0aGUgZG9tLiBPdGhlcndpc2UsDQogICAqIHRoZSBhYnNvbHV0ZSB1cmwgaXMgcHJlZml4ZWQgd2l0aCBgJ3Vuc2FmZTonYCBzdHJpbmcgYW5kIG9ubHkgdGhlbiBpcyBpdCB3cml0dGVuIGludG8gdGhlIERPTS4NCiAgICoNCiAgICogQHBhcmFtIHtSZWdFeHA9fSByZWdleHAgTmV3IHJlZ2V4cCB0byB3aGl0ZWxpc3QgdXJscyB3aXRoLg0KICAgKiBAcmV0dXJucyB7UmVnRXhwfG5nLiRjb21waWxlUHJvdmlkZXJ9IEN1cnJlbnQgUmVnRXhwIGlmIGNhbGxlZCB3aXRob3V0IHZhbHVlIG9yIHNlbGYgZm9yDQogICAqICAgIGNoYWluaW5nIG90aGVyd2lzZS4NCiAgICovDQogIHRoaXMuYUhyZWZTYW5pdGl6YXRpb25XaGl0ZWxpc3QgPSBmdW5jdGlvbihyZWdleHApIHsNCiAgICBpZiAoaXNEZWZpbmVkKHJlZ2V4cCkpIHsNCiAgICAgIGFIcmVmU2FuaXRpemF0aW9uV2hpdGVsaXN0ID0gcmVnZXhwOw0KICAgICAgcmV0dXJuIHRoaXM7DQogICAgfQ0KICAgIHJldHVybiBhSHJlZlNhbml0aXphdGlvbldoaXRlbGlzdDsNCiAgfTsNCg0KDQogIC8qKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogUmV0cmlldmVzIG9yIG92ZXJyaWRlcyB0aGUgZGVmYXVsdCByZWd1bGFyIGV4cHJlc3Npb24gdGhhdCBpcyB1c2VkIGZvciB3aGl0ZWxpc3Rpbmcgb2Ygc2FmZQ0KICAgKiB1cmxzIGR1cmluZyBpbWdbc3JjXSBzYW5pdGl6YXRpb24uDQogICAqDQogICAqIFRoZSBzYW5pdGl6YXRpb24gaXMgYSBzZWN1cml0eSBtZWFzdXJlIGFpbWVkIGF0IHByZXZlbnQgWFNTIGF0dGFja3MgdmlhIGh0bWwgbGlua3MuDQogICAqDQogICAqIEFueSB1cmwgYWJvdXQgdG8gYmUgYXNzaWduZWQgdG8gaW1nW3NyY10gdmlhIGRhdGEtYmluZGluZyBpcyBmaXJzdCBub3JtYWxpemVkIGFuZCB0dXJuZWQgaW50bw0KICAgKiBhbiBhYnNvbHV0ZSB1cmwuIEFmdGVyd2FyZHMsIHRoZSB1cmwgaXMgbWF0Y2hlZCBhZ2FpbnN0IHRoZSBgaW1nU3JjU2FuaXRpemF0aW9uV2hpdGVsaXN0YA0KICAgKiByZWd1bGFyIGV4cHJlc3Npb24uIElmIGEgbWF0Y2ggaXMgZm91bmQsIHRoZSBvcmlnaW5hbCB1cmwgaXMgd3JpdHRlbiBpbnRvIHRoZSBkb20uIE90aGVyd2lzZSwNCiAgICogdGhlIGFic29sdXRlIHVybCBpcyBwcmVmaXhlZCB3aXRoIGAndW5zYWZlOidgIHN0cmluZyBhbmQgb25seSB0aGVuIGlzIGl0IHdyaXR0ZW4gaW50byB0aGUgRE9NLg0KICAgKg0KICAgKiBAcGFyYW0ge1JlZ0V4cD19IHJlZ2V4cCBOZXcgcmVnZXhwIHRvIHdoaXRlbGlzdCB1cmxzIHdpdGguDQogICAqIEByZXR1cm5zIHtSZWdFeHB8bmcuJGNvbXBpbGVQcm92aWRlcn0gQ3VycmVudCBSZWdFeHAgaWYgY2FsbGVkIHdpdGhvdXQgdmFsdWUgb3Igc2VsZiBmb3INCiAgICogICAgY2hhaW5pbmcgb3RoZXJ3aXNlLg0KICAgKi8NCiAgdGhpcy5pbWdTcmNTYW5pdGl6YXRpb25XaGl0ZWxpc3QgPSBmdW5jdGlvbihyZWdleHApIHsNCiAgICBpZiAoaXNEZWZpbmVkKHJlZ2V4cCkpIHsNCiAgICAgIGltZ1NyY1Nhbml0aXphdGlvbldoaXRlbGlzdCA9IHJlZ2V4cDsNCiAgICAgIHJldHVybiB0aGlzOw0KICAgIH0NCiAgICByZXR1cm4gaW1nU3JjU2FuaXRpemF0aW9uV2hpdGVsaXN0Ow0KICB9Ow0KDQogIHRoaXMuJGdldCA9IGZ1bmN0aW9uKCkgew0KICAgIHJldHVybiBmdW5jdGlvbiBzYW5pdGl6ZVVyaSh1cmksIGlzSW1hZ2UpIHsNCiAgICAgIHZhciByZWdleCA9IGlzSW1hZ2UgPyBpbWdTcmNTYW5pdGl6YXRpb25XaGl0ZWxpc3QgOiBhSHJlZlNhbml0aXphdGlvbldoaXRlbGlzdDsNCiAgICAgIHZhciBub3JtYWxpemVkVmFsOw0KICAgICAgbm9ybWFsaXplZFZhbCA9IHVybFJlc29sdmUodXJpKS5ocmVmOw0KICAgICAgaWYgKG5vcm1hbGl6ZWRWYWwgIT09ICcnICYmICFub3JtYWxpemVkVmFsLm1hdGNoKHJlZ2V4KSkgew0KICAgICAgICByZXR1cm4gJ3Vuc2FmZTonICsgbm9ybWFsaXplZFZhbDsNCiAgICAgIH0NCiAgICAgIHJldHVybiB1cmk7DQogICAgfTsNCiAgfTsNCn0NCg0KdmFyICRzY2VNaW5FcnIgPSBtaW5FcnIoJyRzY2UnKTsNCg0KdmFyIFNDRV9DT05URVhUUyA9IHsNCiAgSFRNTDogJ2h0bWwnLA0KICBDU1M6ICdjc3MnLA0KICBVUkw6ICd1cmwnLA0KICAvLyBSRVNPVVJDRV9VUkwgaXMgYSBzdWJ0eXBlIG9mIFVSTCB1c2VkIGluIGNvbnRleHRzIHdoZXJlIGEgcHJpdmlsZWdlZCByZXNvdXJjZSBpcyBzb3VyY2VkIGZyb20gYQ0KICAvLyB1cmwuICAoZS5nLiBuZy1pbmNsdWRlLCBzY3JpcHQgc3JjLCB0ZW1wbGF0ZVVybCkNCiAgUkVTT1VSQ0VfVVJMOiAncmVzb3VyY2VVcmwnLA0KICBKUzogJ2pzJw0KfTsNCg0KLy8gSGVscGVyIGZ1bmN0aW9ucyBmb2xsb3cuDQoNCmZ1bmN0aW9uIGFkanVzdE1hdGNoZXIobWF0Y2hlcikgew0KICBpZiAobWF0Y2hlciA9PT0gJ3NlbGYnKSB7DQogICAgcmV0dXJuIG1hdGNoZXI7DQogIH0gZWxzZSBpZiAoaXNTdHJpbmcobWF0Y2hlcikpIHsNCiAgICAvLyBTdHJpbmdzIG1hdGNoIGV4YWN0bHkgZXhjZXB0IGZvciAyIHdpbGRjYXJkcyAtICcqJyBhbmQgJyoqJy4NCiAgICAvLyAnKicgbWF0Y2hlcyBhbnkgY2hhcmFjdGVyIGV4Y2VwdCB0aG9zZSBmcm9tIHRoZSBzZXQgJzovLj8mJy4NCiAgICAvLyAnKionIG1hdGNoZXMgYW55IGNoYXJhY3RlciAobGlrZSAuKiBpbiBhIFJlZ0V4cCkuDQogICAgLy8gTW9yZSB0aGFuIDIgKidzIHJhaXNlcyBhbiBlcnJvciBhcyBpdCdzIGlsbCBkZWZpbmVkLg0KICAgIGlmIChtYXRjaGVyLmluZGV4T2YoJyoqKicpID4gLTEpIHsNCiAgICAgIHRocm93ICRzY2VNaW5FcnIoJ2l3Y2FyZCcsDQogICAgICAgICAgJ0lsbGVnYWwgc2VxdWVuY2UgKioqIGluIHN0cmluZyBtYXRjaGVyLiAgU3RyaW5nOiB7MH0nLCBtYXRjaGVyKTsNCiAgICB9DQogICAgbWF0Y2hlciA9IGVzY2FwZUZvclJlZ2V4cChtYXRjaGVyKS4NCiAgICAgICAgICAgICAgICAgIHJlcGxhY2UoJ1xcKlxcKicsICcuKicpLg0KICAgICAgICAgICAgICAgICAgcmVwbGFjZSgnXFwqJywgJ1teOi8uPyY7XSonKTsNCiAgICByZXR1cm4gbmV3IFJlZ0V4cCgnXicgKyBtYXRjaGVyICsgJyQnKTsNCiAgfSBlbHNlIGlmIChpc1JlZ0V4cChtYXRjaGVyKSkgew0KICAgIC8vIFRoZSBvbmx5IG90aGVyIHR5cGUgb2YgbWF0Y2hlciBhbGxvd2VkIGlzIGEgUmVnZXhwLg0KICAgIC8vIE1hdGNoIGVudGlyZSBVUkwgLyBkaXNhbGxvdyBwYXJ0aWFsIG1hdGNoZXMuDQogICAgLy8gRmxhZ3MgYXJlIHJlc2V0IChpLmUuIG5vIGdsb2JhbCwgaWdub3JlQ2FzZSBvciBtdWx0aWxpbmUpDQogICAgcmV0dXJuIG5ldyBSZWdFeHAoJ14nICsgbWF0Y2hlci5zb3VyY2UgKyAnJCcpOw0KICB9IGVsc2Ugew0KICAgIHRocm93ICRzY2VNaW5FcnIoJ2ltYXRjaGVyJywNCiAgICAgICAgJ01hdGNoZXJzIG1heSBvbmx5IGJlICJzZWxmIiwgc3RyaW5nIHBhdHRlcm5zIG9yIFJlZ0V4cCBvYmplY3RzJyk7DQogIH0NCn0NCg0KDQpmdW5jdGlvbiBhZGp1c3RNYXRjaGVycyhtYXRjaGVycykgew0KICB2YXIgYWRqdXN0ZWRNYXRjaGVycyA9IFtdOw0KICBpZiAoaXNEZWZpbmVkKG1hdGNoZXJzKSkgew0KICAgIGZvckVhY2gobWF0Y2hlcnMsIGZ1bmN0aW9uKG1hdGNoZXIpIHsNCiAgICAgIGFkanVzdGVkTWF0Y2hlcnMucHVzaChhZGp1c3RNYXRjaGVyKG1hdGNoZXIpKTsNCiAgICB9KTsNCiAgfQ0KICByZXR1cm4gYWRqdXN0ZWRNYXRjaGVyczsNCn0NCg0KDQovKioNCiAqIEBuZ2RvYyBzZXJ2aWNlDQogKiBAbmFtZSAkc2NlRGVsZWdhdGUNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKg0KICogYCRzY2VEZWxlZ2F0ZWAgaXMgYSBzZXJ2aWNlIHRoYXQgaXMgdXNlZCBieSB0aGUgYCRzY2VgIHNlcnZpY2UgdG8gcHJvdmlkZSB7QGxpbmsgbmcuJHNjZSBTdHJpY3QNCiAqIENvbnRleHR1YWwgRXNjYXBpbmcgKFNDRSl9IHNlcnZpY2VzIHRvIEFuZ3VsYXJKUy4NCiAqDQogKiBUeXBpY2FsbHksIHlvdSB3b3VsZCBjb25maWd1cmUgb3Igb3ZlcnJpZGUgdGhlIHtAbGluayBuZy4kc2NlRGVsZWdhdGUgJHNjZURlbGVnYXRlfSBpbnN0ZWFkIG9mDQogKiB0aGUgYCRzY2VgIHNlcnZpY2UgdG8gY3VzdG9taXplIHRoZSB3YXkgU3RyaWN0IENvbnRleHR1YWwgRXNjYXBpbmcgd29ya3MgaW4gQW5ndWxhckpTLiAgVGhpcyBpcw0KICogYmVjYXVzZSwgd2hpbGUgdGhlIGAkc2NlYCBwcm92aWRlcyBudW1lcm91cyBzaG9ydGhhbmQgbWV0aG9kcywgZXRjLiwgeW91IHJlYWxseSBvbmx5IG5lZWQgdG8NCiAqIG92ZXJyaWRlIDMgY29yZSBmdW5jdGlvbnMgKGB0cnVzdEFzYCwgYGdldFRydXN0ZWRgIGFuZCBgdmFsdWVPZmApIHRvIHJlcGxhY2UgdGhlIHdheSB0aGluZ3MNCiAqIHdvcmsgYmVjYXVzZSBgJHNjZWAgZGVsZWdhdGVzIHRvIGAkc2NlRGVsZWdhdGVgIGZvciB0aGVzZSBvcGVyYXRpb25zLg0KICoNCiAqIFJlZmVyIHtAbGluayBuZy4kc2NlRGVsZWdhdGVQcm92aWRlciAkc2NlRGVsZWdhdGVQcm92aWRlcn0gdG8gY29uZmlndXJlIHRoaXMgc2VydmljZS4NCiAqDQogKiBUaGUgZGVmYXVsdCBpbnN0YW5jZSBvZiBgJHNjZURlbGVnYXRlYCBzaG91bGQgd29yayBvdXQgb2YgdGhlIGJveCB3aXRoIGxpdHRsZSBwYWluLiAgV2hpbGUgeW91DQogKiBjYW4gb3ZlcnJpZGUgaXQgY29tcGxldGVseSB0byBjaGFuZ2UgdGhlIGJlaGF2aW9yIG9mIGAkc2NlYCwgdGhlIGNvbW1vbiBjYXNlIHdvdWxkDQogKiBpbnZvbHZlIGNvbmZpZ3VyaW5nIHRoZSB7QGxpbmsgbmcuJHNjZURlbGVnYXRlUHJvdmlkZXIgJHNjZURlbGVnYXRlUHJvdmlkZXJ9IGluc3RlYWQgYnkgc2V0dGluZw0KICogeW91ciBvd24gd2hpdGVsaXN0cyBhbmQgYmxhY2tsaXN0cyBmb3IgdHJ1c3RpbmcgVVJMcyB1c2VkIGZvciBsb2FkaW5nIEFuZ3VsYXJKUyByZXNvdXJjZXMgc3VjaCBhcw0KICogdGVtcGxhdGVzLiAgUmVmZXIge0BsaW5rIG5nLiRzY2VEZWxlZ2F0ZVByb3ZpZGVyI3Jlc291cmNlVXJsV2hpdGVsaXN0DQogKiAkc2NlRGVsZWdhdGVQcm92aWRlci5yZXNvdXJjZVVybFdoaXRlbGlzdH0gYW5kIHtAbGluaw0KICogbmcuJHNjZURlbGVnYXRlUHJvdmlkZXIjcmVzb3VyY2VVcmxCbGFja2xpc3QgJHNjZURlbGVnYXRlUHJvdmlkZXIucmVzb3VyY2VVcmxCbGFja2xpc3R9DQogKi8NCg0KLyoqDQogKiBAbmdkb2MgcHJvdmlkZXINCiAqIEBuYW1lICRzY2VEZWxlZ2F0ZVByb3ZpZGVyDQogKiBAZGVzY3JpcHRpb24NCiAqDQogKiBUaGUgYCRzY2VEZWxlZ2F0ZVByb3ZpZGVyYCBwcm92aWRlciBhbGxvd3MgZGV2ZWxvcGVycyB0byBjb25maWd1cmUgdGhlIHtAbGluayBuZy4kc2NlRGVsZWdhdGUNCiAqICRzY2VEZWxlZ2F0ZX0gc2VydmljZS4gIFRoaXMgYWxsb3dzIG9uZSB0byBnZXQvc2V0IHRoZSB3aGl0ZWxpc3RzIGFuZCBibGFja2xpc3RzIHVzZWQgdG8gZW5zdXJlDQogKiB0aGF0IHRoZSBVUkxzIHVzZWQgZm9yIHNvdXJjaW5nIEFuZ3VsYXIgdGVtcGxhdGVzIGFyZSBzYWZlLiAgUmVmZXIge0BsaW5rDQogKiBuZy4kc2NlRGVsZWdhdGVQcm92aWRlciNyZXNvdXJjZVVybFdoaXRlbGlzdCAkc2NlRGVsZWdhdGVQcm92aWRlci5yZXNvdXJjZVVybFdoaXRlbGlzdH0gYW5kDQogKiB7QGxpbmsgbmcuJHNjZURlbGVnYXRlUHJvdmlkZXIjcmVzb3VyY2VVcmxCbGFja2xpc3QgJHNjZURlbGVnYXRlUHJvdmlkZXIucmVzb3VyY2VVcmxCbGFja2xpc3R9DQogKg0KICogRm9yIHRoZSBnZW5lcmFsIGRldGFpbHMgYWJvdXQgdGhpcyBzZXJ2aWNlIGluIEFuZ3VsYXIsIHJlYWQgdGhlIG1haW4gcGFnZSBmb3Ige0BsaW5rIG5nLiRzY2UNCiAqIFN0cmljdCBDb250ZXh0dWFsIEVzY2FwaW5nIChTQ0UpfS4NCiAqDQogKiAqKkV4YW1wbGUqKjogIENvbnNpZGVyIHRoZSBmb2xsb3dpbmcgY2FzZS4gPGEgbmFtZT0iZXhhbXBsZSI+PC9hPg0KICoNCiAqIC0geW91ciBhcHAgaXMgaG9zdGVkIGF0IHVybCBgaHR0cDovL215YXBwLmV4YW1wbGUuY29tL2ANCiAqIC0gYnV0IHNvbWUgb2YgeW91ciB0ZW1wbGF0ZXMgYXJlIGhvc3RlZCBvbiBvdGhlciBkb21haW5zIHlvdSBjb250cm9sIHN1Y2ggYXMNCiAqICAgYGh0dHA6Ly9zcnYwMS5hc3NldHMuZXhhbXBsZS5jb20vYCzCoCBgaHR0cDovL3NydjAyLmFzc2V0cy5leGFtcGxlLmNvbS9gLCBldGMuDQogKiAtIGFuZCB5b3UgaGF2ZSBhbiBvcGVuIHJlZGlyZWN0IGF0IGBodHRwOi8vbXlhcHAuZXhhbXBsZS5jb20vY2xpY2tUaHJ1Py4uLmAuDQogKg0KICogSGVyZSBpcyB3aGF0IGEgc2VjdXJlIGNvbmZpZ3VyYXRpb24gZm9yIHRoaXMgc2NlbmFyaW8gbWlnaHQgbG9vayBsaWtlOg0KICoNCiAqIGBgYA0KICogIGFuZ3VsYXIubW9kdWxlKCdteUFwcCcsIFtdKS5jb25maWcoZnVuY3Rpb24oJHNjZURlbGVnYXRlUHJvdmlkZXIpIHsNCiAqICAgICRzY2VEZWxlZ2F0ZVByb3ZpZGVyLnJlc291cmNlVXJsV2hpdGVsaXN0KFsNCiAqICAgICAgLy8gQWxsb3cgc2FtZSBvcmlnaW4gcmVzb3VyY2UgbG9hZHMuDQogKiAgICAgICdzZWxmJywNCiAqICAgICAgLy8gQWxsb3cgbG9hZGluZyBmcm9tIG91ciBhc3NldHMgZG9tYWluLiAgTm90aWNlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gKiBhbmQgKiouDQogKiAgICAgICdodHRwOi8vc3J2Ki5hc3NldHMuZXhhbXBsZS5jb20vKionDQogKiAgICBdKTsNCiAqDQogKiAgICAvLyBUaGUgYmxhY2tsaXN0IG92ZXJyaWRlcyB0aGUgd2hpdGVsaXN0IHNvIHRoZSBvcGVuIHJlZGlyZWN0IGhlcmUgaXMgYmxvY2tlZC4NCiAqICAgICRzY2VEZWxlZ2F0ZVByb3ZpZGVyLnJlc291cmNlVXJsQmxhY2tsaXN0KFsNCiAqICAgICAgJ2h0dHA6Ly9teWFwcC5leGFtcGxlLmNvbS9jbGlja1RocnUqKicNCiAqICAgIF0pOw0KICogIH0pOw0KICogYGBgDQogKi8NCg0KZnVuY3Rpb24gJFNjZURlbGVnYXRlUHJvdmlkZXIoKSB7DQogIHRoaXMuU0NFX0NPTlRFWFRTID0gU0NFX0NPTlRFWFRTOw0KDQogIC8vIFJlc291cmNlIFVSTHMgY2FuIGFsc28gYmUgdHJ1c3RlZCBieSBwb2xpY3kuDQogIHZhciByZXNvdXJjZVVybFdoaXRlbGlzdCA9IFsnc2VsZiddLA0KICAgICAgcmVzb3VyY2VVcmxCbGFja2xpc3QgPSBbXTsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkc2NlRGVsZWdhdGVQcm92aWRlciNyZXNvdXJjZVVybFdoaXRlbGlzdA0KICAgKiBAa2luZCBmdW5jdGlvbg0KICAgKg0KICAgKiBAcGFyYW0ge0FycmF5PX0gd2hpdGVsaXN0IFdoZW4gcHJvdmlkZWQsIHJlcGxhY2VzIHRoZSByZXNvdXJjZVVybFdoaXRlbGlzdCB3aXRoIHRoZSB2YWx1ZQ0KICAgKiAgICAgcHJvdmlkZWQuICBUaGlzIG11c3QgYmUgYW4gYXJyYXkgb3IgbnVsbC4gIEEgc25hcHNob3Qgb2YgdGhpcyBhcnJheSBpcyB1c2VkIHNvIGZ1cnRoZXINCiAgICogICAgIGNoYW5nZXMgdG8gdGhlIGFycmF5IGFyZSBpZ25vcmVkLg0KICAgKg0KICAgKiAgICAgRm9sbG93IHtAbGluayBuZy4kc2NlI3Jlc291cmNlVXJsUGF0dGVybkl0ZW0gdGhpcyBsaW5rfSBmb3IgYSBkZXNjcmlwdGlvbiBvZiB0aGUgaXRlbXMNCiAgICogICAgIGFsbG93ZWQgaW4gdGhpcyBhcnJheS4NCiAgICoNCiAgICogICAgIE5vdGU6ICoqYW4gZW1wdHkgd2hpdGVsaXN0IGFycmF5IHdpbGwgYmxvY2sgYWxsIFVSTHMqKiENCiAgICoNCiAgICogQHJldHVybiB7QXJyYXl9IHRoZSBjdXJyZW50bHkgc2V0IHdoaXRlbGlzdCBhcnJheS4NCiAgICoNCiAgICogVGhlICoqZGVmYXVsdCB2YWx1ZSoqIHdoZW4gbm8gd2hpdGVsaXN0IGhhcyBiZWVuIGV4cGxpY2l0bHkgc2V0IGlzIGBbJ3NlbGYnXWAgYWxsb3dpbmcgb25seQ0KICAgKiBzYW1lIG9yaWdpbiByZXNvdXJjZSByZXF1ZXN0cy4NCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFNldHMvR2V0cyB0aGUgd2hpdGVsaXN0IG9mIHRydXN0ZWQgcmVzb3VyY2UgVVJMcy4NCiAgICovDQogIHRoaXMucmVzb3VyY2VVcmxXaGl0ZWxpc3QgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgIGlmIChhcmd1bWVudHMubGVuZ3RoKSB7DQogICAgICByZXNvdXJjZVVybFdoaXRlbGlzdCA9IGFkanVzdE1hdGNoZXJzKHZhbHVlKTsNCiAgICB9DQogICAgcmV0dXJuIHJlc291cmNlVXJsV2hpdGVsaXN0Ow0KICB9Ow0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lICRzY2VEZWxlZ2F0ZVByb3ZpZGVyI3Jlc291cmNlVXJsQmxhY2tsaXN0DQogICAqIEBraW5kIGZ1bmN0aW9uDQogICAqDQogICAqIEBwYXJhbSB7QXJyYXk9fSBibGFja2xpc3QgV2hlbiBwcm92aWRlZCwgcmVwbGFjZXMgdGhlIHJlc291cmNlVXJsQmxhY2tsaXN0IHdpdGggdGhlIHZhbHVlDQogICAqICAgICBwcm92aWRlZC4gIFRoaXMgbXVzdCBiZSBhbiBhcnJheSBvciBudWxsLiAgQSBzbmFwc2hvdCBvZiB0aGlzIGFycmF5IGlzIHVzZWQgc28gZnVydGhlcg0KICAgKiAgICAgY2hhbmdlcyB0byB0aGUgYXJyYXkgYXJlIGlnbm9yZWQuDQogICAqDQogICAqICAgICBGb2xsb3cge0BsaW5rIG5nLiRzY2UjcmVzb3VyY2VVcmxQYXR0ZXJuSXRlbSB0aGlzIGxpbmt9IGZvciBhIGRlc2NyaXB0aW9uIG9mIHRoZSBpdGVtcw0KICAgKiAgICAgYWxsb3dlZCBpbiB0aGlzIGFycmF5Lg0KICAgKg0KICAgKiAgICAgVGhlIHR5cGljYWwgdXNhZ2UgZm9yIHRoZSBibGFja2xpc3QgaXMgdG8gKipibG9jaw0KICAgKiAgICAgW29wZW4gcmVkaXJlY3RzXShodHRwOi8vY3dlLm1pdHJlLm9yZy9kYXRhL2RlZmluaXRpb25zLzYwMS5odG1sKSoqIHNlcnZlZCBieSB5b3VyIGRvbWFpbiBhcw0KICAgKiAgICAgdGhlc2Ugd291bGQgb3RoZXJ3aXNlIGJlIHRydXN0ZWQgYnV0IGFjdHVhbGx5IHJldHVybiBjb250ZW50IGZyb20gdGhlIHJlZGlyZWN0ZWQgZG9tYWluLg0KICAgKg0KICAgKiAgICAgRmluYWxseSwgKip0aGUgYmxhY2tsaXN0IG92ZXJyaWRlcyB0aGUgd2hpdGVsaXN0KiogYW5kIGhhcyB0aGUgZmluYWwgc2F5Lg0KICAgKg0KICAgKiBAcmV0dXJuIHtBcnJheX0gdGhlIGN1cnJlbnRseSBzZXQgYmxhY2tsaXN0IGFycmF5Lg0KICAgKg0KICAgKiBUaGUgKipkZWZhdWx0IHZhbHVlKiogd2hlbiBubyB3aGl0ZWxpc3QgaGFzIGJlZW4gZXhwbGljaXRseSBzZXQgaXMgdGhlIGVtcHR5IGFycmF5IChpLmUuIHRoZXJlDQogICAqIGlzIG5vIGJsYWNrbGlzdC4pDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBTZXRzL0dldHMgdGhlIGJsYWNrbGlzdCBvZiB0cnVzdGVkIHJlc291cmNlIFVSTHMuDQogICAqLw0KDQogIHRoaXMucmVzb3VyY2VVcmxCbGFja2xpc3QgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgIGlmIChhcmd1bWVudHMubGVuZ3RoKSB7DQogICAgICByZXNvdXJjZVVybEJsYWNrbGlzdCA9IGFkanVzdE1hdGNoZXJzKHZhbHVlKTsNCiAgICB9DQogICAgcmV0dXJuIHJlc291cmNlVXJsQmxhY2tsaXN0Ow0KICB9Ow0KDQogIHRoaXMuJGdldCA9IFsnJGluamVjdG9yJywgZnVuY3Rpb24oJGluamVjdG9yKSB7DQoNCiAgICB2YXIgaHRtbFNhbml0aXplciA9IGZ1bmN0aW9uIGh0bWxTYW5pdGl6ZXIoaHRtbCkgew0KICAgICAgdGhyb3cgJHNjZU1pbkVycigndW5zYWZlJywgJ0F0dGVtcHRpbmcgdG8gdXNlIGFuIHVuc2FmZSB2YWx1ZSBpbiBhIHNhZmUgY29udGV4dC4nKTsNCiAgICB9Ow0KDQogICAgaWYgKCRpbmplY3Rvci5oYXMoJyRzYW5pdGl6ZScpKSB7DQogICAgICBodG1sU2FuaXRpemVyID0gJGluamVjdG9yLmdldCgnJHNhbml0aXplJyk7DQogICAgfQ0KDQoNCiAgICBmdW5jdGlvbiBtYXRjaFVybChtYXRjaGVyLCBwYXJzZWRVcmwpIHsNCiAgICAgIGlmIChtYXRjaGVyID09PSAnc2VsZicpIHsNCiAgICAgICAgcmV0dXJuIHVybElzU2FtZU9yaWdpbihwYXJzZWRVcmwpOw0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgLy8gZGVmaW5pdGVseSBhIHJlZ2V4LiAgU2VlIGFkanVzdE1hdGNoZXJzKCkNCiAgICAgICAgcmV0dXJuICEhbWF0Y2hlci5leGVjKHBhcnNlZFVybC5ocmVmKTsNCiAgICAgIH0NCiAgICB9DQoNCiAgICBmdW5jdGlvbiBpc1Jlc291cmNlVXJsQWxsb3dlZEJ5UG9saWN5KHVybCkgew0KICAgICAgdmFyIHBhcnNlZFVybCA9IHVybFJlc29sdmUodXJsLnRvU3RyaW5nKCkpOw0KICAgICAgdmFyIGksIG4sIGFsbG93ZWQgPSBmYWxzZTsNCiAgICAgIC8vIEVuc3VyZSB0aGF0IGF0IGxlYXN0IG9uZSBpdGVtIGZyb20gdGhlIHdoaXRlbGlzdCBhbGxvd3MgdGhpcyB1cmwuDQogICAgICBmb3IgKGkgPSAwLCBuID0gcmVzb3VyY2VVcmxXaGl0ZWxpc3QubGVuZ3RoOyBpIDwgbjsgaSsrKSB7DQogICAgICAgIGlmIChtYXRjaFVybChyZXNvdXJjZVVybFdoaXRlbGlzdFtpXSwgcGFyc2VkVXJsKSkgew0KICAgICAgICAgIGFsbG93ZWQgPSB0cnVlOw0KICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQogICAgICB9DQogICAgICBpZiAoYWxsb3dlZCkgew0KICAgICAgICAvLyBFbnN1cmUgdGhhdCBubyBpdGVtIGZyb20gdGhlIGJsYWNrbGlzdCBibG9ja2VkIHRoaXMgdXJsLg0KICAgICAgICBmb3IgKGkgPSAwLCBuID0gcmVzb3VyY2VVcmxCbGFja2xpc3QubGVuZ3RoOyBpIDwgbjsgaSsrKSB7DQogICAgICAgICAgaWYgKG1hdGNoVXJsKHJlc291cmNlVXJsQmxhY2tsaXN0W2ldLCBwYXJzZWRVcmwpKSB7DQogICAgICAgICAgICBhbGxvd2VkID0gZmFsc2U7DQogICAgICAgICAgICBicmVhazsNCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgIH0NCiAgICAgIHJldHVybiBhbGxvd2VkOw0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIGdlbmVyYXRlSG9sZGVyVHlwZShCYXNlKSB7DQogICAgICB2YXIgaG9sZGVyVHlwZSA9IGZ1bmN0aW9uIFRydXN0ZWRWYWx1ZUhvbGRlclR5cGUodHJ1c3RlZFZhbHVlKSB7DQogICAgICAgIHRoaXMuJCR1bndyYXBUcnVzdGVkVmFsdWUgPSBmdW5jdGlvbigpIHsNCiAgICAgICAgICByZXR1cm4gdHJ1c3RlZFZhbHVlOw0KICAgICAgICB9Ow0KICAgICAgfTsNCiAgICAgIGlmIChCYXNlKSB7DQogICAgICAgIGhvbGRlclR5cGUucHJvdG90eXBlID0gbmV3IEJhc2UoKTsNCiAgICAgIH0NCiAgICAgIGhvbGRlclR5cGUucHJvdG90eXBlLnZhbHVlT2YgPSBmdW5jdGlvbiBzY2VWYWx1ZU9mKCkgew0KICAgICAgICByZXR1cm4gdGhpcy4kJHVud3JhcFRydXN0ZWRWYWx1ZSgpOw0KICAgICAgfTsNCiAgICAgIGhvbGRlclR5cGUucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gc2NlVG9TdHJpbmcoKSB7DQogICAgICAgIHJldHVybiB0aGlzLiQkdW53cmFwVHJ1c3RlZFZhbHVlKCkudG9TdHJpbmcoKTsNCiAgICAgIH07DQogICAgICByZXR1cm4gaG9sZGVyVHlwZTsNCiAgICB9DQoNCiAgICB2YXIgdHJ1c3RlZFZhbHVlSG9sZGVyQmFzZSA9IGdlbmVyYXRlSG9sZGVyVHlwZSgpLA0KICAgICAgICBieVR5cGUgPSB7fTsNCg0KICAgIGJ5VHlwZVtTQ0VfQ09OVEVYVFMuSFRNTF0gPSBnZW5lcmF0ZUhvbGRlclR5cGUodHJ1c3RlZFZhbHVlSG9sZGVyQmFzZSk7DQogICAgYnlUeXBlW1NDRV9DT05URVhUUy5DU1NdID0gZ2VuZXJhdGVIb2xkZXJUeXBlKHRydXN0ZWRWYWx1ZUhvbGRlckJhc2UpOw0KICAgIGJ5VHlwZVtTQ0VfQ09OVEVYVFMuVVJMXSA9IGdlbmVyYXRlSG9sZGVyVHlwZSh0cnVzdGVkVmFsdWVIb2xkZXJCYXNlKTsNCiAgICBieVR5cGVbU0NFX0NPTlRFWFRTLkpTXSA9IGdlbmVyYXRlSG9sZGVyVHlwZSh0cnVzdGVkVmFsdWVIb2xkZXJCYXNlKTsNCiAgICBieVR5cGVbU0NFX0NPTlRFWFRTLlJFU09VUkNFX1VSTF0gPSBnZW5lcmF0ZUhvbGRlclR5cGUoYnlUeXBlW1NDRV9DT05URVhUUy5VUkxdKTsNCg0KICAgIC8qKg0KICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgKiBAbmFtZSAkc2NlRGVsZWdhdGUjdHJ1c3RBcw0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogUmV0dXJucyBhbiBvYmplY3QgdGhhdCBpcyB0cnVzdGVkIGJ5IGFuZ3VsYXIgZm9yIHVzZSBpbiBzcGVjaWZpZWQgc3RyaWN0DQogICAgICogY29udGV4dHVhbCBlc2NhcGluZyBjb250ZXh0cyAoc3VjaCBhcyBuZy1iaW5kLWh0bWwsIG5nLWluY2x1ZGUsIGFueSBzcmMNCiAgICAgKiBhdHRyaWJ1dGUgaW50ZXJwb2xhdGlvbiwgYW55IGRvbSBldmVudCBiaW5kaW5nIGF0dHJpYnV0ZSBpbnRlcnBvbGF0aW9uDQogICAgICogc3VjaCBhcyBmb3Igb25jbGljaywgIGV0Yy4pIHRoYXQgdXNlcyB0aGUgcHJvdmlkZWQgdmFsdWUuDQogICAgICogU2VlIHtAbGluayBuZy4kc2NlICRzY2V9IGZvciBlbmFibGluZyBzdHJpY3QgY29udGV4dHVhbCBlc2NhcGluZy4NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIFRoZSBraW5kIG9mIGNvbnRleHQgaW4gd2hpY2ggdGhpcyB2YWx1ZSBpcyBzYWZlIGZvciB1c2UuICBlLmcuIHVybCwNCiAgICAgKiAgIHJlc291cmNlVXJsLCBodG1sLCBqcyBhbmQgY3NzLg0KICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRoYXQgdGhhdCBzaG91bGQgYmUgY29uc2lkZXJlZCB0cnVzdGVkL3NhZmUuDQogICAgICogQHJldHVybnMgeyp9IEEgdmFsdWUgdGhhdCBjYW4gYmUgdXNlZCB0byBzdGFuZCBpbiBmb3IgdGhlIHByb3ZpZGVkIGB2YWx1ZWAgaW4gcGxhY2VzDQogICAgICogd2hlcmUgQW5ndWxhciBleHBlY3RzIGEgJHNjZS50cnVzdEFzKCkgcmV0dXJuIHZhbHVlLg0KICAgICAqLw0KICAgIGZ1bmN0aW9uIHRydXN0QXModHlwZSwgdHJ1c3RlZFZhbHVlKSB7DQogICAgICB2YXIgQ29uc3RydWN0b3IgPSAoYnlUeXBlLmhhc093blByb3BlcnR5KHR5cGUpID8gYnlUeXBlW3R5cGVdIDogbnVsbCk7DQogICAgICBpZiAoIUNvbnN0cnVjdG9yKSB7DQogICAgICAgIHRocm93ICRzY2VNaW5FcnIoJ2ljb250ZXh0JywNCiAgICAgICAgICAgICdBdHRlbXB0ZWQgdG8gdHJ1c3QgYSB2YWx1ZSBpbiBpbnZhbGlkIGNvbnRleHQuIENvbnRleHQ6IHswfTsgVmFsdWU6IHsxfScsDQogICAgICAgICAgICB0eXBlLCB0cnVzdGVkVmFsdWUpOw0KICAgICAgfQ0KICAgICAgaWYgKHRydXN0ZWRWYWx1ZSA9PT0gbnVsbCB8fCB0cnVzdGVkVmFsdWUgPT09IHVuZGVmaW5lZCB8fCB0cnVzdGVkVmFsdWUgPT09ICcnKSB7DQogICAgICAgIHJldHVybiB0cnVzdGVkVmFsdWU7DQogICAgICB9DQogICAgICAvLyBBbGwgdGhlIGN1cnJlbnQgY29udGV4dHMgaW4gU0NFX0NPTlRFWFRTIGhhcHBlbiB0byBiZSBzdHJpbmdzLiAgSW4gb3JkZXIgdG8gYXZvaWQgdHJ1c3RpbmcNCiAgICAgIC8vIG11dGFibGUgb2JqZWN0cywgd2UgZW5zdXJlIGhlcmUgdGhhdCB0aGUgdmFsdWUgcGFzc2VkIGluIGlzIGFjdHVhbGx5IGEgc3RyaW5nLg0KICAgICAgaWYgKHR5cGVvZiB0cnVzdGVkVmFsdWUgIT09ICdzdHJpbmcnKSB7DQogICAgICAgIHRocm93ICRzY2VNaW5FcnIoJ2l0eXBlJywNCiAgICAgICAgICAgICdBdHRlbXB0ZWQgdG8gdHJ1c3QgYSBub24tc3RyaW5nIHZhbHVlIGluIGEgY29udGVudCByZXF1aXJpbmcgYSBzdHJpbmc6IENvbnRleHQ6IHswfScsDQogICAgICAgICAgICB0eXBlKTsNCiAgICAgIH0NCiAgICAgIHJldHVybiBuZXcgQ29uc3RydWN0b3IodHJ1c3RlZFZhbHVlKTsNCiAgICB9DQoNCiAgICAvKioNCiAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICogQG5hbWUgJHNjZURlbGVnYXRlI3ZhbHVlT2YNCiAgICAgKg0KICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAqIElmIHRoZSBwYXNzZWQgcGFyYW1ldGVyIGhhZCBiZWVuIHJldHVybmVkIGJ5IGEgcHJpb3IgY2FsbCB0byB7QGxpbmsgbmcuJHNjZURlbGVnYXRlI3RydXN0QXMNCiAgICAgKiBgJHNjZURlbGVnYXRlLnRydXN0QXNgfSwgcmV0dXJucyB0aGUgdmFsdWUgdGhhdCBoYWQgYmVlbiBwYXNzZWQgdG8ge0BsaW5rDQogICAgICogbmcuJHNjZURlbGVnYXRlI3RydXN0QXMgYCRzY2VEZWxlZ2F0ZS50cnVzdEFzYH0uDQogICAgICoNCiAgICAgKiBJZiB0aGUgcGFzc2VkIHBhcmFtZXRlciBpcyBub3QgYSB2YWx1ZSB0aGF0IGhhZCBiZWVuIHJldHVybmVkIGJ5IHtAbGluaw0KICAgICAqIG5nLiRzY2VEZWxlZ2F0ZSN0cnVzdEFzIGAkc2NlRGVsZWdhdGUudHJ1c3RBc2B9LCByZXR1cm5zIGl0IGFzLWlzLg0KICAgICAqDQogICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgcmVzdWx0IG9mIGEgcHJpb3Ige0BsaW5rIG5nLiRzY2VEZWxlZ2F0ZSN0cnVzdEFzIGAkc2NlRGVsZWdhdGUudHJ1c3RBc2B9DQogICAgICogICAgICBjYWxsIG9yIGFueXRoaW5nIGVsc2UuDQogICAgICogQHJldHVybnMgeyp9IFRoZSBgdmFsdWVgIHRoYXQgd2FzIG9yaWdpbmFsbHkgcHJvdmlkZWQgdG8ge0BsaW5rIG5nLiRzY2VEZWxlZ2F0ZSN0cnVzdEFzDQogICAgICogICAgIGAkc2NlRGVsZWdhdGUudHJ1c3RBc2B9IGlmIGB2YWx1ZWAgaXMgdGhlIHJlc3VsdCBvZiBzdWNoIGEgY2FsbC4gIE90aGVyd2lzZSwgcmV0dXJucw0KICAgICAqICAgICBgdmFsdWVgIHVuY2hhbmdlZC4NCiAgICAgKi8NCiAgICBmdW5jdGlvbiB2YWx1ZU9mKG1heWJlVHJ1c3RlZCkgew0KICAgICAgaWYgKG1heWJlVHJ1c3RlZCBpbnN0YW5jZW9mIHRydXN0ZWRWYWx1ZUhvbGRlckJhc2UpIHsNCiAgICAgICAgcmV0dXJuIG1heWJlVHJ1c3RlZC4kJHVud3JhcFRydXN0ZWRWYWx1ZSgpOw0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgcmV0dXJuIG1heWJlVHJ1c3RlZDsNCiAgICAgIH0NCiAgICB9DQoNCiAgICAvKioNCiAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICogQG5hbWUgJHNjZURlbGVnYXRlI2dldFRydXN0ZWQNCiAgICAgKg0KICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAqIFRha2VzIHRoZSByZXN1bHQgb2YgYSB7QGxpbmsgbmcuJHNjZURlbGVnYXRlI3RydXN0QXMgYCRzY2VEZWxlZ2F0ZS50cnVzdEFzYH0gY2FsbCBhbmQNCiAgICAgKiByZXR1cm5zIHRoZSBvcmlnaW5hbGx5IHN1cHBsaWVkIHZhbHVlIGlmIHRoZSBxdWVyaWVkIGNvbnRleHQgdHlwZSBpcyBhIHN1cGVydHlwZSBvZiB0aGUNCiAgICAgKiBjcmVhdGVkIHR5cGUuICBJZiB0aGlzIGNvbmRpdGlvbiBpc24ndCBzYXRpc2ZpZWQsIHRocm93cyBhbiBleGNlcHRpb24uDQogICAgICoNCiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSBUaGUga2luZCBvZiBjb250ZXh0IGluIHdoaWNoIHRoaXMgdmFsdWUgaXMgdG8gYmUgdXNlZC4NCiAgICAgKiBAcGFyYW0geyp9IG1heWJlVHJ1c3RlZCBUaGUgcmVzdWx0IG9mIGEgcHJpb3Ige0BsaW5rIG5nLiRzY2VEZWxlZ2F0ZSN0cnVzdEFzDQogICAgICogICAgIGAkc2NlRGVsZWdhdGUudHJ1c3RBc2B9IGNhbGwuDQogICAgICogQHJldHVybnMgeyp9IFRoZSB2YWx1ZSB0aGUgd2FzIG9yaWdpbmFsbHkgcHJvdmlkZWQgdG8ge0BsaW5rIG5nLiRzY2VEZWxlZ2F0ZSN0cnVzdEFzDQogICAgICogICAgIGAkc2NlRGVsZWdhdGUudHJ1c3RBc2B9IGlmIHZhbGlkIGluIHRoaXMgY29udGV4dC4gIE90aGVyd2lzZSwgdGhyb3dzIGFuIGV4Y2VwdGlvbi4NCiAgICAgKi8NCiAgICBmdW5jdGlvbiBnZXRUcnVzdGVkKHR5cGUsIG1heWJlVHJ1c3RlZCkgew0KICAgICAgaWYgKG1heWJlVHJ1c3RlZCA9PT0gbnVsbCB8fCBtYXliZVRydXN0ZWQgPT09IHVuZGVmaW5lZCB8fCBtYXliZVRydXN0ZWQgPT09ICcnKSB7DQogICAgICAgIHJldHVybiBtYXliZVRydXN0ZWQ7DQogICAgICB9DQogICAgICB2YXIgY29uc3RydWN0b3IgPSAoYnlUeXBlLmhhc093blByb3BlcnR5KHR5cGUpID8gYnlUeXBlW3R5cGVdIDogbnVsbCk7DQogICAgICBpZiAoY29uc3RydWN0b3IgJiYgbWF5YmVUcnVzdGVkIGluc3RhbmNlb2YgY29uc3RydWN0b3IpIHsNCiAgICAgICAgcmV0dXJuIG1heWJlVHJ1c3RlZC4kJHVud3JhcFRydXN0ZWRWYWx1ZSgpOw0KICAgICAgfQ0KICAgICAgLy8gSWYgd2UgZ2V0IGhlcmUsIHRoZW4gd2UgbWF5IG9ubHkgdGFrZSBvbmUgb2YgdHdvIGFjdGlvbnMuDQogICAgICAvLyAxLiBzYW5pdGl6ZSB0aGUgdmFsdWUgZm9yIHRoZSByZXF1ZXN0ZWQgdHlwZSwgb3INCiAgICAgIC8vIDIuIHRocm93IGFuIGV4Y2VwdGlvbi4NCiAgICAgIGlmICh0eXBlID09PSBTQ0VfQ09OVEVYVFMuUkVTT1VSQ0VfVVJMKSB7DQogICAgICAgIGlmIChpc1Jlc291cmNlVXJsQWxsb3dlZEJ5UG9saWN5KG1heWJlVHJ1c3RlZCkpIHsNCiAgICAgICAgICByZXR1cm4gbWF5YmVUcnVzdGVkOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIHRocm93ICRzY2VNaW5FcnIoJ2luc2VjdXJsJywNCiAgICAgICAgICAgICAgJ0Jsb2NrZWQgbG9hZGluZyByZXNvdXJjZSBmcm9tIHVybCBub3QgYWxsb3dlZCBieSAkc2NlRGVsZWdhdGUgcG9saWN5LiAgVVJMOiB7MH0nLA0KICAgICAgICAgICAgICBtYXliZVRydXN0ZWQudG9TdHJpbmcoKSk7DQogICAgICAgIH0NCiAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gU0NFX0NPTlRFWFRTLkhUTUwpIHsNCiAgICAgICAgcmV0dXJuIGh0bWxTYW5pdGl6ZXIobWF5YmVUcnVzdGVkKTsNCiAgICAgIH0NCiAgICAgIHRocm93ICRzY2VNaW5FcnIoJ3Vuc2FmZScsICdBdHRlbXB0aW5nIHRvIHVzZSBhbiB1bnNhZmUgdmFsdWUgaW4gYSBzYWZlIGNvbnRleHQuJyk7DQogICAgfQ0KDQogICAgcmV0dXJuIHsgdHJ1c3RBczogdHJ1c3RBcywNCiAgICAgICAgICAgICBnZXRUcnVzdGVkOiBnZXRUcnVzdGVkLA0KICAgICAgICAgICAgIHZhbHVlT2Y6IHZhbHVlT2YgfTsNCiAgfV07DQp9DQoNCg0KLyoqDQogKiBAbmdkb2MgcHJvdmlkZXINCiAqIEBuYW1lICRzY2VQcm92aWRlcg0KICogQGRlc2NyaXB0aW9uDQogKg0KICogVGhlICRzY2VQcm92aWRlciBwcm92aWRlciBhbGxvd3MgZGV2ZWxvcGVycyB0byBjb25maWd1cmUgdGhlIHtAbGluayBuZy4kc2NlICRzY2V9IHNlcnZpY2UuDQogKiAtICAgZW5hYmxlL2Rpc2FibGUgU3RyaWN0IENvbnRleHR1YWwgRXNjYXBpbmcgKFNDRSkgaW4gYSBtb2R1bGUNCiAqIC0gICBvdmVycmlkZSB0aGUgZGVmYXVsdCBpbXBsZW1lbnRhdGlvbiB3aXRoIGEgY3VzdG9tIGRlbGVnYXRlDQogKg0KICogUmVhZCBtb3JlIGFib3V0IHtAbGluayBuZy4kc2NlIFN0cmljdCBDb250ZXh0dWFsIEVzY2FwaW5nIChTQ0UpfS4NCiAqLw0KDQovKiBqc2hpbnQgbWF4bGVuOiBmYWxzZSovDQoNCi8qKg0KICogQG5nZG9jIHNlcnZpY2UNCiAqIEBuYW1lICRzY2UNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKg0KICogYCRzY2VgIGlzIGEgc2VydmljZSB0aGF0IHByb3ZpZGVzIFN0cmljdCBDb250ZXh0dWFsIEVzY2FwaW5nIHNlcnZpY2VzIHRvIEFuZ3VsYXJKUy4NCiAqDQogKiAjIFN0cmljdCBDb250ZXh0dWFsIEVzY2FwaW5nDQogKg0KICogU3RyaWN0IENvbnRleHR1YWwgRXNjYXBpbmcgKFNDRSkgaXMgYSBtb2RlIGluIHdoaWNoIEFuZ3VsYXJKUyByZXF1aXJlcyBiaW5kaW5ncyBpbiBjZXJ0YWluDQogKiBjb250ZXh0cyB0byByZXN1bHQgaW4gYSB2YWx1ZSB0aGF0IGlzIG1hcmtlZCBhcyBzYWZlIHRvIHVzZSBmb3IgdGhhdCBjb250ZXh0LiAgT25lIGV4YW1wbGUgb2YNCiAqIHN1Y2ggYSBjb250ZXh0IGlzIGJpbmRpbmcgYXJiaXRyYXJ5IGh0bWwgY29udHJvbGxlZCBieSB0aGUgdXNlciB2aWEgYG5nLWJpbmQtaHRtbGAuICBXZSByZWZlcg0KICogdG8gdGhlc2UgY29udGV4dHMgYXMgcHJpdmlsZWdlZCBvciBTQ0UgY29udGV4dHMuDQogKg0KICogQXMgb2YgdmVyc2lvbiAxLjIsIEFuZ3VsYXIgc2hpcHMgd2l0aCBTQ0UgZW5hYmxlZCBieSBkZWZhdWx0Lg0KICoNCiAqIE5vdGU6ICBXaGVuIGVuYWJsZWQgKHRoZSBkZWZhdWx0KSwgSUU8MTEgaW4gcXVpcmtzIG1vZGUgaXMgbm90IHN1cHBvcnRlZC4gIEluIHRoaXMgbW9kZSwgSUU8MTEgYWxsb3cNCiAqIG9uZSB0byBleGVjdXRlIGFyYml0cmFyeSBqYXZhc2NyaXB0IGJ5IHRoZSB1c2Ugb2YgdGhlIGV4cHJlc3Npb24oKSBzeW50YXguICBSZWZlcg0KICogPGh0dHA6Ly9ibG9ncy5tc2RuLmNvbS9iL2llL2FyY2hpdmUvMjAwOC8xMC8xNi9lbmRpbmctZXhwcmVzc2lvbnMuYXNweD4gdG8gbGVhcm4gbW9yZSBhYm91dCB0aGVtLg0KICogWW91IGNhbiBlbnN1cmUgeW91ciBkb2N1bWVudCBpcyBpbiBzdGFuZGFyZHMgbW9kZSBhbmQgbm90IHF1aXJrcyBtb2RlIGJ5IGFkZGluZyBgPCFkb2N0eXBlIGh0bWw+YA0KICogdG8gdGhlIHRvcCBvZiB5b3VyIEhUTUwgZG9jdW1lbnQuDQogKg0KICogU0NFIGFzc2lzdHMgaW4gd3JpdGluZyBjb2RlIGluIHdheSB0aGF0IChhKSBpcyBzZWN1cmUgYnkgZGVmYXVsdCBhbmQgKGIpIG1ha2VzIGF1ZGl0aW5nIGZvcg0KICogc2VjdXJpdHkgdnVsbmVyYWJpbGl0aWVzIHN1Y2ggYXMgWFNTLCBjbGlja2phY2tpbmcsIGV0Yy4gYSBsb3QgZWFzaWVyLg0KICoNCiAqIEhlcmUncyBhbiBleGFtcGxlIG9mIGEgYmluZGluZyBpbiBhIHByaXZpbGVnZWQgY29udGV4dDoNCiAqDQogKiBgYGANCiAqIDxpbnB1dCBuZy1tb2RlbD0idXNlckh0bWwiPg0KICogPGRpdiBuZy1iaW5kLWh0bWw9InVzZXJIdG1sIj48L2Rpdj4NCiAqIGBgYA0KICoNCiAqIE5vdGljZSB0aGF0IGBuZy1iaW5kLWh0bWxgIGlzIGJvdW5kIHRvIGB1c2VySHRtbGAgY29udHJvbGxlZCBieSB0aGUgdXNlci4gIFdpdGggU0NFDQogKiBkaXNhYmxlZCwgdGhpcyBhcHBsaWNhdGlvbiBhbGxvd3MgdGhlIHVzZXIgdG8gcmVuZGVyIGFyYml0cmFyeSBIVE1MIGludG8gdGhlIERJVi4NCiAqIEluIGEgbW9yZSByZWFsaXN0aWMgZXhhbXBsZSwgb25lIG1heSBiZSByZW5kZXJpbmcgdXNlciBjb21tZW50cywgYmxvZyBhcnRpY2xlcywgZXRjLiB2aWENCiAqIGJpbmRpbmdzLiAgKEhUTUwgaXMganVzdCBvbmUgZXhhbXBsZSBvZiBhIGNvbnRleHQgd2hlcmUgcmVuZGVyaW5nIHVzZXIgY29udHJvbGxlZCBpbnB1dCBjcmVhdGVzDQogKiBzZWN1cml0eSB2dWxuZXJhYmlsaXRpZXMuKQ0KICoNCiAqIEZvciB0aGUgY2FzZSBvZiBIVE1MLCB5b3UgbWlnaHQgdXNlIGEgbGlicmFyeSwgZWl0aGVyIG9uIHRoZSBjbGllbnQgc2lkZSwgb3Igb24gdGhlIHNlcnZlciBzaWRlLA0KICogdG8gc2FuaXRpemUgdW5zYWZlIEhUTUwgYmVmb3JlIGJpbmRpbmcgdG8gdGhlIHZhbHVlIGFuZCByZW5kZXJpbmcgaXQgaW4gdGhlIGRvY3VtZW50Lg0KICoNCiAqIEhvdyB3b3VsZCB5b3UgZW5zdXJlIHRoYXQgZXZlcnkgcGxhY2UgdGhhdCB1c2VkIHRoZXNlIHR5cGVzIG9mIGJpbmRpbmdzIHdhcyBib3VuZCB0byBhIHZhbHVlIHRoYXQNCiAqIHdhcyBzYW5pdGl6ZWQgYnkgeW91ciBsaWJyYXJ5IChvciByZXR1cm5lZCBhcyBzYWZlIGZvciByZW5kZXJpbmcgYnkgeW91ciBzZXJ2ZXI/KSAgSG93IGNhbiB5b3UNCiAqIGVuc3VyZSB0aGF0IHlvdSBkaWRuJ3QgYWNjaWRlbnRhbGx5IGRlbGV0ZSB0aGUgbGluZSB0aGF0IHNhbml0aXplZCB0aGUgdmFsdWUsIG9yIHJlbmFtZWQgc29tZQ0KICogcHJvcGVydGllcy9maWVsZHMgYW5kIGZvcmdvdCB0byB1cGRhdGUgdGhlIGJpbmRpbmcgdG8gdGhlIHNhbml0aXplZCB2YWx1ZT8NCiAqDQogKiBUbyBiZSBzZWN1cmUgYnkgZGVmYXVsdCwgeW91IHdhbnQgdG8gZW5zdXJlIHRoYXQgYW55IHN1Y2ggYmluZGluZ3MgYXJlIGRpc2FsbG93ZWQgdW5sZXNzIHlvdSBjYW4NCiAqIGRldGVybWluZSB0aGF0IHNvbWV0aGluZyBleHBsaWNpdGx5IHNheXMgaXQncyBzYWZlIHRvIHVzZSBhIHZhbHVlIGZvciBiaW5kaW5nIGluIHRoYXQNCiAqIGNvbnRleHQuICBZb3UgY2FuIHRoZW4gYXVkaXQgeW91ciBjb2RlIChhIHNpbXBsZSBncmVwIHdvdWxkIGRvKSB0byBlbnN1cmUgdGhhdCB0aGlzIGlzIG9ubHkgZG9uZQ0KICogZm9yIHRob3NlIHZhbHVlcyB0aGF0IHlvdSBjYW4gZWFzaWx5IHRlbGwgYXJlIHNhZmUgLSBiZWNhdXNlIHRoZXkgd2VyZSByZWNlaXZlZCBmcm9tIHlvdXIgc2VydmVyLA0KICogc2FuaXRpemVkIGJ5IHlvdXIgbGlicmFyeSwgZXRjLiAgWW91IGNhbiBvcmdhbml6ZSB5b3VyIGNvZGViYXNlIHRvIGhlbHAgd2l0aCB0aGlzIC0gcGVyaGFwcw0KICogYWxsb3dpbmcgb25seSB0aGUgZmlsZXMgaW4gYSBzcGVjaWZpYyBkaXJlY3RvcnkgdG8gZG8gdGhpcy4gIEVuc3VyaW5nIHRoYXQgdGhlIGludGVybmFsIEFQSQ0KICogZXhwb3NlZCBieSB0aGF0IGNvZGUgZG9lc24ndCBtYXJrdXAgYXJiaXRyYXJ5IHZhbHVlcyBhcyBzYWZlIHRoZW4gYmVjb21lcyBhIG1vcmUgbWFuYWdlYWJsZSB0YXNrLg0KICoNCiAqIEluIHRoZSBjYXNlIG9mIEFuZ3VsYXJKUycgU0NFIHNlcnZpY2UsIG9uZSB1c2VzIHtAbGluayBuZy4kc2NlI3RydXN0QXMgJHNjZS50cnVzdEFzfQ0KICogKGFuZCBzaG9ydGhhbmQgbWV0aG9kcyBzdWNoIGFzIHtAbGluayBuZy4kc2NlI3RydXN0QXNIdG1sICRzY2UudHJ1c3RBc0h0bWx9LCBldGMuKSB0bw0KICogb2J0YWluIHZhbHVlcyB0aGF0IHdpbGwgYmUgYWNjZXB0ZWQgYnkgU0NFIC8gcHJpdmlsZWdlZCBjb250ZXh0cy4NCiAqDQogKg0KICogIyMgSG93IGRvZXMgaXQgd29yaz8NCiAqDQogKiBJbiBwcml2aWxlZ2VkIGNvbnRleHRzLCBkaXJlY3RpdmVzIGFuZCBjb2RlIHdpbGwgYmluZCB0byB0aGUgcmVzdWx0IG9mIHtAbGluayBuZy4kc2NlI2dldFRydXN0ZWQNCiAqICRzY2UuZ2V0VHJ1c3RlZChjb250ZXh0LCB2YWx1ZSl9IHJhdGhlciB0aGFuIHRvIHRoZSB2YWx1ZSBkaXJlY3RseS4gIERpcmVjdGl2ZXMgdXNlIHtAbGluaw0KICogbmcuJHNjZSNwYXJzZUFzICRzY2UucGFyc2VBc30gcmF0aGVyIHRoYW4gYCRwYXJzZWAgdG8gd2F0Y2ggYXR0cmlidXRlIGJpbmRpbmdzLCB3aGljaCBwZXJmb3JtcyB0aGUNCiAqIHtAbGluayBuZy4kc2NlI2dldFRydXN0ZWQgJHNjZS5nZXRUcnVzdGVkfSBiZWhpbmQgdGhlIHNjZW5lcyBvbiBub24tY29uc3RhbnQgbGl0ZXJhbHMuDQogKg0KICogQXMgYW4gZXhhbXBsZSwge0BsaW5rIG5nLmRpcmVjdGl2ZTpuZ0JpbmRIdG1sIG5nQmluZEh0bWx9IHVzZXMge0BsaW5rDQogKiBuZy4kc2NlI3BhcnNlQXNIdG1sICRzY2UucGFyc2VBc0h0bWwoYmluZGluZyBleHByZXNzaW9uKX0uICBIZXJlJ3MgdGhlIGFjdHVhbCBjb2RlIChzbGlnaHRseQ0KICogc2ltcGxpZmllZCk6DQogKg0KICogYGBgDQogKiB2YXIgbmdCaW5kSHRtbERpcmVjdGl2ZSA9IFsnJHNjZScsIGZ1bmN0aW9uKCRzY2UpIHsNCiAqICAgcmV0dXJuIGZ1bmN0aW9uKHNjb3BlLCBlbGVtZW50LCBhdHRyKSB7DQogKiAgICAgc2NvcGUuJHdhdGNoKCRzY2UucGFyc2VBc0h0bWwoYXR0ci5uZ0JpbmRIdG1sKSwgZnVuY3Rpb24odmFsdWUpIHsNCiAqICAgICAgIGVsZW1lbnQuaHRtbCh2YWx1ZSB8fCAnJyk7DQogKiAgICAgfSk7DQogKiAgIH07DQogKiB9XTsNCiAqIGBgYA0KICoNCiAqICMjIEltcGFjdCBvbiBsb2FkaW5nIHRlbXBsYXRlcw0KICoNCiAqIFRoaXMgYXBwbGllcyBib3RoIHRvIHRoZSB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nSW5jbHVkZSBgbmctaW5jbHVkZWB9IGRpcmVjdGl2ZSBhcyB3ZWxsIGFzDQogKiBgdGVtcGxhdGVVcmxgJ3Mgc3BlY2lmaWVkIGJ5IHtAbGluayBndWlkZS9kaXJlY3RpdmUgZGlyZWN0aXZlc30uDQogKg0KICogQnkgZGVmYXVsdCwgQW5ndWxhciBvbmx5IGxvYWRzIHRlbXBsYXRlcyBmcm9tIHRoZSBzYW1lIGRvbWFpbiBhbmQgcHJvdG9jb2wgYXMgdGhlIGFwcGxpY2F0aW9uDQogKiBkb2N1bWVudC4gIFRoaXMgaXMgZG9uZSBieSBjYWxsaW5nIHtAbGluayBuZy4kc2NlI2dldFRydXN0ZWRSZXNvdXJjZVVybA0KICogJHNjZS5nZXRUcnVzdGVkUmVzb3VyY2VVcmx9IG9uIHRoZSB0ZW1wbGF0ZSBVUkwuICBUbyBsb2FkIHRlbXBsYXRlcyBmcm9tIG90aGVyIGRvbWFpbnMgYW5kL29yDQogKiBwcm90b2NvbHMsIHlvdSBtYXkgZWl0aGVyIGVpdGhlciB7QGxpbmsgbmcuJHNjZURlbGVnYXRlUHJvdmlkZXIjcmVzb3VyY2VVcmxXaGl0ZWxpc3Qgd2hpdGVsaXN0DQogKiB0aGVtfSBvciB7QGxpbmsgbmcuJHNjZSN0cnVzdEFzUmVzb3VyY2VVcmwgd3JhcCBpdH0gaW50byBhIHRydXN0ZWQgdmFsdWUuDQogKg0KICogKlBsZWFzZSBub3RlKjoNCiAqIFRoZSBicm93c2VyJ3MNCiAqIFtTYW1lIE9yaWdpbiBQb2xpY3ldKGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvYnJvd3NlcnNlYy93aWtpL1BhcnQyI1NhbWUtb3JpZ2luX3BvbGljeV9mb3JfWE1MSHR0cFJlcXVlc3QpDQogKiBhbmQgW0Nyb3NzLU9yaWdpbiBSZXNvdXJjZSBTaGFyaW5nIChDT1JTKV0oaHR0cDovL3d3dy53My5vcmcvVFIvY29ycy8pDQogKiBwb2xpY3kgYXBwbHkgaW4gYWRkaXRpb24gdG8gdGhpcyBhbmQgbWF5IGZ1cnRoZXIgcmVzdHJpY3Qgd2hldGhlciB0aGUgdGVtcGxhdGUgaXMgc3VjY2Vzc2Z1bGx5DQogKiBsb2FkZWQuICBUaGlzIG1lYW5zIHRoYXQgd2l0aG91dCB0aGUgcmlnaHQgQ09SUyBwb2xpY3ksIGxvYWRpbmcgdGVtcGxhdGVzIGZyb20gYSBkaWZmZXJlbnQgZG9tYWluDQogKiB3b24ndCB3b3JrIG9uIGFsbCBicm93c2Vycy4gIEFsc28sIGxvYWRpbmcgdGVtcGxhdGVzIGZyb20gYGZpbGU6Ly9gIFVSTCBkb2VzIG5vdCB3b3JrIG9uIHNvbWUNCiAqIGJyb3dzZXJzLg0KICoNCiAqICMjIFRoaXMgZmVlbHMgbGlrZSB0b28gbXVjaCBvdmVyaGVhZA0KICoNCiAqIEl0J3MgaW1wb3J0YW50IHRvIHJlbWVtYmVyIHRoYXQgU0NFIG9ubHkgYXBwbGllcyB0byBpbnRlcnBvbGF0aW9uIGV4cHJlc3Npb25zLg0KICoNCiAqIElmIHlvdXIgZXhwcmVzc2lvbnMgYXJlIGNvbnN0YW50IGxpdGVyYWxzLCB0aGV5J3JlIGF1dG9tYXRpY2FsbHkgdHJ1c3RlZCBhbmQgeW91IGRvbid0IG5lZWQgdG8NCiAqIGNhbGwgYCRzY2UudHJ1c3RBc2Agb24gdGhlbSAocmVtZW1iZXIgdG8gaW5jbHVkZSB0aGUgYG5nU2FuaXRpemVgIG1vZHVsZSkgKGUuZy4NCiAqIGA8ZGl2IG5nLWJpbmQtaHRtbD0iJzxiPmltcGxpY2l0bHkgdHJ1c3RlZDwvYj4nIj48L2Rpdj5gKSBqdXN0IHdvcmtzLg0KICoNCiAqIEFkZGl0aW9uYWxseSwgYGFbaHJlZl1gIGFuZCBgaW1nW3NyY11gIGF1dG9tYXRpY2FsbHkgc2FuaXRpemUgdGhlaXIgVVJMcyBhbmQgZG8gbm90IHBhc3MgdGhlbQ0KICogdGhyb3VnaCB7QGxpbmsgbmcuJHNjZSNnZXRUcnVzdGVkICRzY2UuZ2V0VHJ1c3RlZH0uICBTQ0UgZG9lc24ndCBwbGF5IGEgcm9sZSBoZXJlLg0KICoNCiAqIFRoZSBpbmNsdWRlZCB7QGxpbmsgbmcuJHNjZURlbGVnYXRlICRzY2VEZWxlZ2F0ZX0gY29tZXMgd2l0aCBzYW5lIGRlZmF1bHRzIHRvIGFsbG93IHlvdSB0byBsb2FkDQogKiB0ZW1wbGF0ZXMgaW4gYG5nLWluY2x1ZGVgIGZyb20geW91ciBhcHBsaWNhdGlvbidzIGRvbWFpbiB3aXRob3V0IGhhdmluZyB0byBldmVuIGtub3cgYWJvdXQgU0NFLg0KICogSXQgYmxvY2tzIGxvYWRpbmcgdGVtcGxhdGVzIGZyb20gb3RoZXIgZG9tYWlucyBvciBsb2FkaW5nIHRlbXBsYXRlcyBvdmVyIGh0dHAgZnJvbSBhbiBodHRwcw0KICogc2VydmVkIGRvY3VtZW50LiAgWW91IGNhbiBjaGFuZ2UgdGhlc2UgYnkgc2V0dGluZyB5b3VyIG93biBjdXN0b20ge0BsaW5rDQogKiBuZy4kc2NlRGVsZWdhdGVQcm92aWRlciNyZXNvdXJjZVVybFdoaXRlbGlzdCB3aGl0ZWxpc3RzfSBhbmQge0BsaW5rDQogKiBuZy4kc2NlRGVsZWdhdGVQcm92aWRlciNyZXNvdXJjZVVybEJsYWNrbGlzdCBibGFja2xpc3RzfSBmb3IgbWF0Y2hpbmcgc3VjaCBVUkxzLg0KICoNCiAqIFRoaXMgc2lnbmlmaWNhbnRseSByZWR1Y2VzIHRoZSBvdmVyaGVhZC4gIEl0IGlzIGZhciBlYXNpZXIgdG8gcGF5IHRoZSBzbWFsbCBvdmVyaGVhZCBhbmQgaGF2ZSBhbg0KICogYXBwbGljYXRpb24gdGhhdCdzIHNlY3VyZSBhbmQgY2FuIGJlIGF1ZGl0ZWQgdG8gdmVyaWZ5IHRoYXQgd2l0aCBtdWNoIG1vcmUgZWFzZSB0aGFuIGJvbHRpbmcNCiAqIHNlY3VyaXR5IG9udG8gYW4gYXBwbGljYXRpb24gbGF0ZXIuDQogKg0KICogPGEgbmFtZT0iY29udGV4dHMiPjwvYT4NCiAqICMjIFdoYXQgdHJ1c3RlZCBjb250ZXh0IHR5cGVzIGFyZSBzdXBwb3J0ZWQ/DQogKg0KICogfCBDb250ZXh0ICAgICAgICAgICAgIHwgTm90ZXMgICAgICAgICAgfA0KICogfC0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tfA0KICogfCBgJHNjZS5IVE1MYCAgICAgICAgIHwgRm9yIEhUTUwgdGhhdCdzIHNhZmUgdG8gc291cmNlIGludG8gdGhlIGFwcGxpY2F0aW9uLiAgVGhlIHtAbGluayBuZy5kaXJlY3RpdmU6bmdCaW5kSHRtbCBuZ0JpbmRIdG1sfSBkaXJlY3RpdmUgdXNlcyB0aGlzIGNvbnRleHQgZm9yIGJpbmRpbmdzLiBJZiBhbiB1bnNhZmUgdmFsdWUgaXMgZW5jb3VudGVyZWQgYW5kIHRoZSB7QGxpbmsgbmdTYW5pdGl6ZSAkc2FuaXRpemV9IG1vZHVsZSBpcyBwcmVzZW50IHRoaXMgd2lsbCBzYW5pdGl6ZSB0aGUgdmFsdWUgaW5zdGVhZCBvZiB0aHJvd2luZyBhbiBlcnJvci4gfA0KICogfCBgJHNjZS5DU1NgICAgICAgICAgIHwgRm9yIENTUyB0aGF0J3Mgc2FmZSB0byBzb3VyY2UgaW50byB0aGUgYXBwbGljYXRpb24uICBDdXJyZW50bHkgdW51c2VkLiAgRmVlbCBmcmVlIHRvIHVzZSBpdCBpbiB5b3VyIG93biBkaXJlY3RpdmVzLiB8DQogKiB8IGAkc2NlLlVSTGAgICAgICAgICAgfCBGb3IgVVJMcyB0aGF0IGFyZSBzYWZlIHRvIGZvbGxvdyBhcyBsaW5rcy4gIEN1cnJlbnRseSB1bnVzZWQgKGA8YSBocmVmPWAgYW5kIGA8aW1nIHNyYz1gIHNhbml0aXplIHRoZWlyIHVybHMgYW5kIGRvbid0IGNvbnN0aXR1dGUgYW4gU0NFIGNvbnRleHQuIHwNCiAqIHwgYCRzY2UuUkVTT1VSQ0VfVVJMYCB8IEZvciBVUkxzIHRoYXQgYXJlIG5vdCBvbmx5IHNhZmUgdG8gZm9sbG93IGFzIGxpbmtzLCBidXQgd2hvc2UgY29udGVudHMgYXJlIGFsc28gc2FmZSB0byBpbmNsdWRlIGluIHlvdXIgYXBwbGljYXRpb24uICBFeGFtcGxlcyBpbmNsdWRlIGBuZy1pbmNsdWRlYCwgYHNyY2AgLyBgbmdTcmNgIGJpbmRpbmdzIGZvciB0YWdzIG90aGVyIHRoYW4gYElNR2AgKGUuZy4gYElGUkFNRWAsIGBPQkpFQ1RgLCBldGMuKSAgPGJyPjxicj5Ob3RlIHRoYXQgYCRzY2UuUkVTT1VSQ0VfVVJMYCBtYWtlcyBhIHN0cm9uZ2VyIHN0YXRlbWVudCBhYm91dCB0aGUgVVJMIHRoYW4gYCRzY2UuVVJMYCBkb2VzIGFuZCB0aGVyZWZvcmUgY29udGV4dHMgcmVxdWlyaW5nIHZhbHVlcyB0cnVzdGVkIGZvciBgJHNjZS5SRVNPVVJDRV9VUkxgIGNhbiBiZSB1c2VkIGFueXdoZXJlIHRoYXQgdmFsdWVzIHRydXN0ZWQgZm9yIGAkc2NlLlVSTGAgYXJlIHJlcXVpcmVkLiB8DQogKiB8IGAkc2NlLkpTYCAgICAgICAgICAgfCBGb3IgSmF2YVNjcmlwdCB0aGF0IGlzIHNhZmUgdG8gZXhlY3V0ZSBpbiB5b3VyIGFwcGxpY2F0aW9uJ3MgY29udGV4dC4gIEN1cnJlbnRseSB1bnVzZWQuICBGZWVsIGZyZWUgdG8gdXNlIGl0IGluIHlvdXIgb3duIGRpcmVjdGl2ZXMuIHwNCiAqDQogKiAjIyBGb3JtYXQgb2YgaXRlbXMgaW4ge0BsaW5rIG5nLiRzY2VEZWxlZ2F0ZVByb3ZpZGVyI3Jlc291cmNlVXJsV2hpdGVsaXN0IHJlc291cmNlVXJsV2hpdGVsaXN0fS97QGxpbmsgbmcuJHNjZURlbGVnYXRlUHJvdmlkZXIjcmVzb3VyY2VVcmxCbGFja2xpc3QgQmxhY2tsaXN0fSA8YSBuYW1lPSJyZXNvdXJjZVVybFBhdHRlcm5JdGVtIj48L2E+DQogKg0KICogIEVhY2ggZWxlbWVudCBpbiB0aGVzZSBhcnJheXMgbXVzdCBiZSBvbmUgb2YgdGhlIGZvbGxvd2luZzoNCiAqDQogKiAgLSAqKidzZWxmJyoqDQogKiAgICAtIFRoZSBzcGVjaWFsICoqc3RyaW5nKiosIGAnc2VsZidgLCBjYW4gYmUgdXNlZCB0byBtYXRjaCBhZ2FpbnN0IGFsbCBVUkxzIG9mIHRoZSAqKnNhbWUNCiAqICAgICAgZG9tYWluKiogYXMgdGhlIGFwcGxpY2F0aW9uIGRvY3VtZW50IHVzaW5nIHRoZSAqKnNhbWUgcHJvdG9jb2wqKi4NCiAqICAtICoqU3RyaW5nKiogKGV4Y2VwdCB0aGUgc3BlY2lhbCB2YWx1ZSBgJ3NlbGYnYCkNCiAqICAgIC0gVGhlIHN0cmluZyBpcyBtYXRjaGVkIGFnYWluc3QgdGhlIGZ1bGwgKm5vcm1hbGl6ZWQgLyBhYnNvbHV0ZSBVUkwqIG9mIHRoZSByZXNvdXJjZQ0KICogICAgICBiZWluZyB0ZXN0ZWQgKHN1YnN0cmluZyBtYXRjaGVzIGFyZSBub3QgZ29vZCBlbm91Z2guKQ0KICogICAgLSBUaGVyZSBhcmUgZXhhY3RseSAqKnR3byB3aWxkY2FyZCBzZXF1ZW5jZXMqKiAtIGAqYCBhbmQgYCoqYC4gIEFsbCBvdGhlciBjaGFyYWN0ZXJzDQogKiAgICAgIG1hdGNoIHRoZW1zZWx2ZXMuDQogKiAgICAtIGAqYDogbWF0Y2hlcyB6ZXJvIG9yIG1vcmUgb2NjdXJyZW5jZXMgb2YgYW55IGNoYXJhY3RlciBvdGhlciB0aGFuIG9uZSBvZiB0aGUgZm9sbG93aW5nIDYNCiAqICAgICAgY2hhcmFjdGVyczogJ2A6YCcsICdgL2AnLCAnYC5gJywgJ2A/YCcsICdgJmAnIGFuZCAnOycuICBJdCdzIGEgdXNlZnVsIHdpbGRjYXJkIGZvciB1c2UNCiAqICAgICAgaW4gYSB3aGl0ZWxpc3QuDQogKiAgICAtIGAqKmA6IG1hdGNoZXMgemVybyBvciBtb3JlIG9jY3VycmVuY2VzIG9mICphbnkqIGNoYXJhY3Rlci4gIEFzIHN1Y2gsIGl0J3Mgbm90DQogKiAgICAgIG5vdCBhcHByb3ByaWF0ZSB0byB1c2UgaW4gZm9yIGEgc2NoZW1lLCBkb21haW4sIGV0Yy4gYXMgaXQgd291bGQgbWF0Y2ggdG9vIG11Y2guICAoZS5nLg0KICogICAgICBodHRwOi8vKiouZXhhbXBsZS5jb20vIHdvdWxkIG1hdGNoIGh0dHA6Ly9ldmlsLmNvbS8/aWdub3JlPS5leGFtcGxlLmNvbS8gYW5kIHRoYXQgbWlnaHQNCiAqICAgICAgbm90IGhhdmUgYmVlbiB0aGUgaW50ZW50aW9uLikgIEl0cyB1c2FnZSBhdCB0aGUgdmVyeSBlbmQgb2YgdGhlIHBhdGggaXMgb2suICAoZS5nLg0KICogICAgICBodHRwOi8vZm9vLmV4YW1wbGUuY29tL3RlbXBsYXRlcy8qKikuDQogKiAgLSAqKlJlZ0V4cCoqICgqc2VlIGNhdmVhdCBiZWxvdyopDQogKiAgICAtICpDYXZlYXQqOiAgV2hpbGUgcmVndWxhciBleHByZXNzaW9ucyBhcmUgcG93ZXJmdWwgYW5kIG9mZmVyIGdyZWF0IGZsZXhpYmlsaXR5LCAgdGhlaXIgc3ludGF4DQogKiAgICAgIChhbmQgYWxsIHRoZSBpbmV2aXRhYmxlIGVzY2FwaW5nKSBtYWtlcyB0aGVtICpoYXJkZXIgdG8gbWFpbnRhaW4qLiAgSXQncyBlYXN5IHRvDQogKiAgICAgIGFjY2lkZW50YWxseSBpbnRyb2R1Y2UgYSBidWcgd2hlbiBvbmUgdXBkYXRlcyBhIGNvbXBsZXggZXhwcmVzc2lvbiAoaW1obywgYWxsIHJlZ2V4ZXMgc2hvdWxkDQogKiAgICAgIGhhdmUgZ29vZCB0ZXN0IGNvdmVyYWdlLikuICBGb3IgaW5zdGFuY2UsIHRoZSB1c2Ugb2YgYC5gIGluIHRoZSByZWdleCBpcyBjb3JyZWN0IG9ubHkgaW4gYQ0KICogICAgICBzbWFsbCBudW1iZXIgb2YgY2FzZXMuICBBIGAuYCBjaGFyYWN0ZXIgaW4gdGhlIHJlZ2V4IHVzZWQgd2hlbiBtYXRjaGluZyB0aGUgc2NoZW1lIG9yIGENCiAqICAgICAgc3ViZG9tYWluIGNvdWxkIGJlIG1hdGNoZWQgYWdhaW5zdCBhIGA6YCBvciBsaXRlcmFsIGAuYCB0aGF0IHdhcyBsaWtlbHkgbm90IGludGVuZGVkLiAgIEl0DQogKiAgICAgIGlzIGhpZ2hseSByZWNvbW1lbmRlZCB0byB1c2UgdGhlIHN0cmluZyBwYXR0ZXJucyBhbmQgb25seSBmYWxsIGJhY2sgdG8gcmVndWxhciBleHByZXNzaW9ucw0KICogICAgICBpZiB0aGV5IGFzIGEgbGFzdCByZXNvcnQuDQogKiAgICAtIFRoZSByZWd1bGFyIGV4cHJlc3Npb24gbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBSZWdFeHAgKGkuZS4gbm90IGEgc3RyaW5nLikgIEl0IGlzDQogKiAgICAgIG1hdGNoZWQgYWdhaW5zdCB0aGUgKiplbnRpcmUqKiAqbm9ybWFsaXplZCAvIGFic29sdXRlIFVSTCogb2YgdGhlIHJlc291cmNlIGJlaW5nIHRlc3RlZA0KICogICAgICAoZXZlbiB3aGVuIHRoZSBSZWdFeHAgZGlkIG5vdCBoYXZlIHRoZSBgXmAgYW5kIGAkYCBjb2Rlcy4pICBJbiBhZGRpdGlvbiwgYW55IGZsYWdzDQogKiAgICAgIHByZXNlbnQgb24gdGhlIFJlZ0V4cCAoc3VjaCBhcyBtdWx0aWxpbmUsIGdsb2JhbCwgaWdub3JlQ2FzZSkgYXJlIGlnbm9yZWQuDQogKiAgICAtIElmIHlvdSBhcmUgZ2VuZXJhdGluZyB5b3VyIEphdmFTY3JpcHQgZnJvbSBzb21lIG90aGVyIHRlbXBsYXRpbmcgZW5naW5lIChub3QNCiAqICAgICAgcmVjb21tZW5kZWQsIGUuZy4gaW4gaXNzdWUgWyM0MDA2XShodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9hbmd1bGFyLmpzL2lzc3Vlcy80MDA2KSksDQogKiAgICAgIHJlbWVtYmVyIHRvIGVzY2FwZSB5b3VyIHJlZ3VsYXIgZXhwcmVzc2lvbiAoYW5kIGJlIGF3YXJlIHRoYXQgeW91IG1pZ2h0IG5lZWQgbW9yZSB0aGFuDQogKiAgICAgIG9uZSBsZXZlbCBvZiBlc2NhcGluZyBkZXBlbmRpbmcgb24geW91ciB0ZW1wbGF0aW5nIGVuZ2luZSBhbmQgdGhlIHdheSB5b3UgaW50ZXJwb2xhdGVkDQogKiAgICAgIHRoZSB2YWx1ZS4pICBEbyBtYWtlIHVzZSBvZiB5b3VyIHBsYXRmb3JtJ3MgZXNjYXBpbmcgbWVjaGFuaXNtIGFzIGl0IG1pZ2h0IGJlIGdvb2QNCiAqICAgICAgZW5vdWdoIGJlZm9yZSBjb2RpbmcgeW91ciBvd24uICBlLmcuIFJ1YnkgaGFzDQogKiAgICAgIFtSZWdleHAuZXNjYXBlKHN0cildKGh0dHA6Ly93d3cucnVieS1kb2Mub3JnL2NvcmUtMi4wLjAvUmVnZXhwLmh0bWwjbWV0aG9kLWMtZXNjYXBlKQ0KICogICAgICBhbmQgUHl0aG9uIGhhcyBbcmUuZXNjYXBlXShodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvcmUuaHRtbCNyZS5lc2NhcGUpLg0KICogICAgICBKYXZhc2NyaXB0IGxhY2tzIGEgc2ltaWxhciBidWlsdCBpbiBmdW5jdGlvbiBmb3IgZXNjYXBpbmcuICBUYWtlIGEgbG9vayBhdCBHb29nbGUNCiAqICAgICAgQ2xvc3VyZSBsaWJyYXJ5J3MgW2dvb2cuc3RyaW5nLnJlZ0V4cEVzY2FwZShzKV0oDQogKiAgICAgIGh0dHA6Ly9kb2NzLmNsb3N1cmUtbGlicmFyeS5nb29nbGVjb2RlLmNvbS9naXQvY2xvc3VyZV9nb29nX3N0cmluZ19zdHJpbmcuanMuc291cmNlLmh0bWwjbGluZTk2MikuDQogKg0KICogUmVmZXIge0BsaW5rIG5nLiRzY2VEZWxlZ2F0ZVByb3ZpZGVyICRzY2VEZWxlZ2F0ZVByb3ZpZGVyfSBmb3IgYW4gZXhhbXBsZS4NCiAqDQogKiAjIyBTaG93IG1lIGFuIGV4YW1wbGUgdXNpbmcgU0NFLg0KICoNCiAqIDxleGFtcGxlIG1vZHVsZT0ibXlTY2VBcHAiIGRlcHM9ImFuZ3VsYXItc2FuaXRpemUuanMiPg0KICogPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogKiAgIDxkaXYgbmctY29udHJvbGxlcj0iQXBwQ29udHJvbGxlciBhcyBteUN0cmwiPg0KICogICAgIDxpIG5nLWJpbmQtaHRtbD0ibXlDdHJsLmV4cGxpY2l0bHlUcnVzdGVkSHRtbCIgaWQ9ImV4cGxpY2l0bHlUcnVzdGVkSHRtbCI+PC9pPjxicj48YnI+DQogKiAgICAgPGI+VXNlciBjb21tZW50czwvYj48YnI+DQogKiAgICAgQnkgZGVmYXVsdCwgSFRNTCB0aGF0IGlzbid0IGV4cGxpY2l0bHkgdHJ1c3RlZCAoZS5nLiBBbGljZSdzIGNvbW1lbnQpIGlzIHNhbml0aXplZCB3aGVuDQogKiAgICAgJHNhbml0aXplIGlzIGF2YWlsYWJsZS4gIElmICRzYW5pdGl6ZSBpc24ndCBhdmFpbGFibGUsIHRoaXMgcmVzdWx0cyBpbiBhbiBlcnJvciBpbnN0ZWFkIG9mIGFuDQogKiAgICAgZXhwbG9pdC4NCiAqICAgICA8ZGl2IGNsYXNzPSJ3ZWxsIj4NCiAqICAgICAgIDxkaXYgbmctcmVwZWF0PSJ1c2VyQ29tbWVudCBpbiBteUN0cmwudXNlckNvbW1lbnRzIj4NCiAqICAgICAgICAgPGI+e3t1c2VyQ29tbWVudC5uYW1lfX08L2I+Og0KICogICAgICAgICA8c3BhbiBuZy1iaW5kLWh0bWw9InVzZXJDb21tZW50Lmh0bWxDb21tZW50IiBjbGFzcz0iaHRtbENvbW1lbnQiPjwvc3Bhbj4NCiAqICAgICAgICAgPGJyPg0KICogICAgICAgPC9kaXY+DQogKiAgICAgPC9kaXY+DQogKiAgIDwvZGl2Pg0KICogPC9maWxlPg0KICoNCiAqIDxmaWxlIG5hbWU9InNjcmlwdC5qcyI+DQogKiAgIGFuZ3VsYXIubW9kdWxlKCdteVNjZUFwcCcsIFsnbmdTYW5pdGl6ZSddKQ0KICogICAgIC5jb250cm9sbGVyKCdBcHBDb250cm9sbGVyJywgWyckaHR0cCcsICckdGVtcGxhdGVDYWNoZScsICckc2NlJywNCiAqICAgICAgIGZ1bmN0aW9uKCRodHRwLCAkdGVtcGxhdGVDYWNoZSwgJHNjZSkgew0KICogICAgICAgICB2YXIgc2VsZiA9IHRoaXM7DQogKiAgICAgICAgICRodHRwLmdldCgidGVzdF9kYXRhLmpzb24iLCB7Y2FjaGU6ICR0ZW1wbGF0ZUNhY2hlfSkuc3VjY2VzcyhmdW5jdGlvbih1c2VyQ29tbWVudHMpIHsNCiAqICAgICAgICAgICBzZWxmLnVzZXJDb21tZW50cyA9IHVzZXJDb21tZW50czsNCiAqICAgICAgICAgfSk7DQogKiAgICAgICAgIHNlbGYuZXhwbGljaXRseVRydXN0ZWRIdG1sID0gJHNjZS50cnVzdEFzSHRtbCgNCiAqICAgICAgICAgICAgICc8c3BhbiBvbm1vdXNlb3Zlcj0idGhpcy50ZXh0Q29udGVudD0mcXVvdDtFeHBsaWNpdGx5IHRydXN0ZWQgSFRNTCBieXBhc3NlcyAnICsNCiAqICAgICAgICAgICAgICdzYW5pdGl6YXRpb24uJnF1b3Q7Ij5Ib3ZlciBvdmVyIHRoaXMgdGV4dC48L3NwYW4+Jyk7DQogKiAgICAgICB9XSk7DQogKiA8L2ZpbGU+DQogKg0KICogPGZpbGUgbmFtZT0idGVzdF9kYXRhLmpzb24iPg0KICogWw0KICogICB7ICJuYW1lIjogIkFsaWNlIiwNCiAqICAgICAiaHRtbENvbW1lbnQiOg0KICogICAgICAgICAiPHNwYW4gb25tb3VzZW92ZXI9J3RoaXMudGV4dENvbnRlbnQ9XCJQV04zRCFcIic+SXMgPGk+YW55b25lPC9pPiByZWFkaW5nIHRoaXM/PC9zcGFuPiINCiAqICAgfSwNCiAqICAgeyAibmFtZSI6ICJCb2IiLA0KICogICAgICJodG1sQ29tbWVudCI6ICI8aT5ZZXMhPC9pPiAgQW0gSSB0aGUgb25seSBvdGhlciBvbmU/Ig0KICogICB9DQogKiBdDQogKiA8L2ZpbGU+DQogKg0KICogPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogKiAgIGRlc2NyaWJlKCdTQ0UgZG9jIGRlbW8nLCBmdW5jdGlvbigpIHsNCiAqICAgICBpdCgnc2hvdWxkIHNhbml0aXplIHVudHJ1c3RlZCB2YWx1ZXMnLCBmdW5jdGlvbigpIHsNCiAqICAgICAgIGV4cGVjdChlbGVtZW50LmFsbChieS5jc3MoJy5odG1sQ29tbWVudCcpKS5maXJzdCgpLmdldElubmVySHRtbCgpKQ0KICogICAgICAgICAgIC50b0JlKCc8c3Bhbj5JcyA8aT5hbnlvbmU8L2k+IHJlYWRpbmcgdGhpcz88L3NwYW4+Jyk7DQogKiAgICAgfSk7DQogKg0KICogICAgIGl0KCdzaG91bGQgTk9UIHNhbml0aXplIGV4cGxpY2l0bHkgdHJ1c3RlZCB2YWx1ZXMnLCBmdW5jdGlvbigpIHsNCiAqICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmlkKCdleHBsaWNpdGx5VHJ1c3RlZEh0bWwnKSkuZ2V0SW5uZXJIdG1sKCkpLnRvQmUoDQogKiAgICAgICAgICAgJzxzcGFuIG9ubW91c2VvdmVyPSJ0aGlzLnRleHRDb250ZW50PSZxdW90O0V4cGxpY2l0bHkgdHJ1c3RlZCBIVE1MIGJ5cGFzc2VzICcgKw0KICogICAgICAgICAgICdzYW5pdGl6YXRpb24uJnF1b3Q7Ij5Ib3ZlciBvdmVyIHRoaXMgdGV4dC48L3NwYW4+Jyk7DQogKiAgICAgfSk7DQogKiAgIH0pOw0KICogPC9maWxlPg0KICogPC9leGFtcGxlPg0KICoNCiAqDQogKg0KICogIyMgQ2FuIEkgZGlzYWJsZSBTQ0UgY29tcGxldGVseT8NCiAqDQogKiBZZXMsIHlvdSBjYW4uICBIb3dldmVyLCB0aGlzIGlzIHN0cm9uZ2x5IGRpc2NvdXJhZ2VkLiAgU0NFIGdpdmVzIHlvdSBhIGxvdCBvZiBzZWN1cml0eSBiZW5lZml0cw0KICogZm9yIGxpdHRsZSBjb2Rpbmcgb3ZlcmhlYWQuICBJdCB3aWxsIGJlIG11Y2ggaGFyZGVyIHRvIHRha2UgYW4gU0NFIGRpc2FibGVkIGFwcGxpY2F0aW9uIGFuZA0KICogZWl0aGVyIHNlY3VyZSBpdCBvbiB5b3VyIG93biBvciBlbmFibGUgU0NFIGF0IGEgbGF0ZXIgc3RhZ2UuICBJdCBtaWdodCBtYWtlIHNlbnNlIHRvIGRpc2FibGUgU0NFDQogKiBmb3IgY2FzZXMgd2hlcmUgeW91IGhhdmUgYSBsb3Qgb2YgZXhpc3RpbmcgY29kZSB0aGF0IHdhcyB3cml0dGVuIGJlZm9yZSBTQ0Ugd2FzIGludHJvZHVjZWQgYW5kDQogKiB5b3UncmUgbWlncmF0aW5nIHRoZW0gYSBtb2R1bGUgYXQgYSB0aW1lLg0KICoNCiAqIFRoYXQgc2FpZCwgaGVyZSdzIGhvdyB5b3UgY2FuIGNvbXBsZXRlbHkgZGlzYWJsZSBTQ0U6DQogKg0KICogYGBgDQogKiBhbmd1bGFyLm1vZHVsZSgnbXlBcHBXaXRoU2NlRGlzYWJsZWRteUFwcCcsIFtdKS5jb25maWcoZnVuY3Rpb24oJHNjZVByb3ZpZGVyKSB7DQogKiAgIC8vIENvbXBsZXRlbHkgZGlzYWJsZSBTQ0UuICBGb3IgZGVtb25zdHJhdGlvbiBwdXJwb3NlcyBvbmx5IQ0KICogICAvLyBEbyBub3QgdXNlIGluIG5ldyBwcm9qZWN0cy4NCiAqICAgJHNjZVByb3ZpZGVyLmVuYWJsZWQoZmFsc2UpOw0KICogfSk7DQogKiBgYGANCiAqDQogKi8NCi8qIGpzaGludCBtYXhsZW46IDEwMCAqLw0KDQpmdW5jdGlvbiAkU2NlUHJvdmlkZXIoKSB7DQogIHZhciBlbmFibGVkID0gdHJ1ZTsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkc2NlUHJvdmlkZXIjZW5hYmxlZA0KICAgKiBAa2luZCBmdW5jdGlvbg0KICAgKg0KICAgKiBAcGFyYW0ge2Jvb2xlYW49fSB2YWx1ZSBJZiBwcm92aWRlZCwgdGhlbiBlbmFibGVzL2Rpc2FibGVzIFNDRS4NCiAgICogQHJldHVybiB7Ym9vbGVhbn0gdHJ1ZSBpZiBTQ0UgaXMgZW5hYmxlZCwgZmFsc2Ugb3RoZXJ3aXNlLg0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogRW5hYmxlcy9kaXNhYmxlcyBTQ0UgYW5kIHJldHVybnMgdGhlIGN1cnJlbnQgdmFsdWUuDQogICAqLw0KICB0aGlzLmVuYWJsZWQgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgIGlmIChhcmd1bWVudHMubGVuZ3RoKSB7DQogICAgICBlbmFibGVkID0gISF2YWx1ZTsNCiAgICB9DQogICAgcmV0dXJuIGVuYWJsZWQ7DQogIH07DQoNCg0KICAvKiBEZXNpZ24gbm90ZXMgb24gdGhlIGRlZmF1bHQgaW1wbGVtZW50YXRpb24gZm9yIFNDRS4NCiAgICoNCiAgICogVGhlIEFQSSBjb250cmFjdCBmb3IgdGhlIFNDRSBkZWxlZ2F0ZQ0KICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQogICAqIFRoZSBTQ0UgZGVsZWdhdGUgb2JqZWN0IG11c3QgcHJvdmlkZSB0aGUgZm9sbG93aW5nIDMgbWV0aG9kczoNCiAgICoNCiAgICogLSB0cnVzdEFzKGNvbnRleHRFbnVtLCB2YWx1ZSkNCiAgICogICAgIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gdGVsbCB0aGUgU0NFIHNlcnZpY2UgdGhhdCB0aGUgcHJvdmlkZWQgdmFsdWUgaXMgT0sgdG8gdXNlIGluIHRoZQ0KICAgKiAgICAgY29udGV4dHMgc3BlY2lmaWVkIGJ5IGNvbnRleHRFbnVtLiAgSXQgbXVzdCByZXR1cm4gYW4gb2JqZWN0IHRoYXQgd2lsbCBiZSBhY2NlcHRlZCBieQ0KICAgKiAgICAgZ2V0VHJ1c3RlZCgpIGZvciBhIGNvbXBhdGlibGUgY29udGV4dEVudW0gYW5kIHJldHVybiB0aGlzIHZhbHVlLg0KICAgKg0KICAgKiAtIHZhbHVlT2YodmFsdWUpDQogICAqICAgICBGb3IgdmFsdWVzIHRoYXQgd2VyZSBub3QgcHJvZHVjZWQgYnkgdHJ1c3RBcygpLCByZXR1cm4gdGhlbSBhcyBpcy4gIEZvciB2YWx1ZXMgdGhhdCB3ZXJlDQogICAqICAgICBwcm9kdWNlZCBieSB0cnVzdEFzKCksIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyBpbnB1dCB2YWx1ZSB0byB0cnVzdEFzLiAgQmFzaWNhbGx5LCBpZg0KICAgKiAgICAgdHJ1c3RBcyBpcyB3cmFwcGluZyB0aGUgZ2l2ZW4gdmFsdWVzIGludG8gc29tZSB0eXBlLCB0aGlzIG9wZXJhdGlvbiB1bndyYXBzIGl0IHdoZW4gZ2l2ZW4NCiAgICogICAgIHN1Y2ggYSB2YWx1ZS4NCiAgICoNCiAgICogLSBnZXRUcnVzdGVkKGNvbnRleHRFbnVtLCB2YWx1ZSkNCiAgICogICAgIFRoaXMgZnVuY3Rpb24gc2hvdWxkIHJldHVybiB0aGUgYSB2YWx1ZSB0aGF0IGlzIHNhZmUgdG8gdXNlIGluIHRoZSBjb250ZXh0IHNwZWNpZmllZCBieQ0KICAgKiAgICAgY29udGV4dEVudW0gb3IgdGhyb3cgYW5kIGV4Y2VwdGlvbiBvdGhlcndpc2UuDQogICAqDQogICAqIE5PVEU6IFRoaXMgY29udHJhY3QgZGVsaWJlcmF0ZWx5IGRvZXMgTk9UIHN0YXRlIHRoYXQgdmFsdWVzIHJldHVybmVkIGJ5IHRydXN0QXMoKSBtdXN0IGJlDQogICAqIG9wYXF1ZSBvciB3cmFwcGVkIGluIHNvbWUgaG9sZGVyIG9iamVjdC4gIFRoYXQgaGFwcGVucyB0byBiZSBhbiBpbXBsZW1lbnRhdGlvbiBkZXRhaWwuICBGb3INCiAgICogaW5zdGFuY2UsIGFuIGltcGxlbWVudGF0aW9uIGNvdWxkIG1haW50YWluIGEgcmVnaXN0cnkgb2YgYWxsIHRydXN0ZWQgb2JqZWN0cyBieSBjb250ZXh0LiAgSW4NCiAgICogc3VjaCBhIGNhc2UsIHRydXN0QXMoKSB3b3VsZCByZXR1cm4gdGhlIHNhbWUgb2JqZWN0IHRoYXQgd2FzIHBhc3NlZCBpbi4gIGdldFRydXN0ZWQoKSB3b3VsZA0KICAgKiByZXR1cm4gdGhlIHNhbWUgb2JqZWN0IHBhc3NlZCBpbiBpZiBpdCB3YXMgZm91bmQgaW4gdGhlIHJlZ2lzdHJ5IHVuZGVyIGEgY29tcGF0aWJsZSBjb250ZXh0IG9yDQogICAqIHRocm93IGFuIGV4Y2VwdGlvbiBvdGhlcndpc2UuICBBbiBpbXBsZW1lbnRhdGlvbiBtaWdodCBvbmx5IHdyYXAgdmFsdWVzIHNvbWUgb2YgdGhlIHRpbWUgYmFzZWQNCiAgICogb24gc29tZSBjcml0ZXJpYS4gIGdldFRydXN0ZWQoKSBtaWdodCByZXR1cm4gYSB2YWx1ZSBhbmQgbm90IHRocm93IGFuIGV4Y2VwdGlvbiBmb3Igc3BlY2lhbA0KICAgKiBjb25zdGFudHMgb3Igb2JqZWN0cyBldmVuIGlmIG5vdCB3cmFwcGVkLiAgQWxsIHN1Y2ggaW1wbGVtZW50YXRpb25zIGZ1bGZpbGwgdGhpcyBjb250cmFjdC4NCiAgICoNCiAgICoNCiAgICogQSBub3RlIG9uIHRoZSBpbmhlcml0YW5jZSBtb2RlbCBmb3IgU0NFIGNvbnRleHRzDQogICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KICAgKiBJJ3ZlIHVzZWQgaW5oZXJpdGFuY2UgYW5kIG1hZGUgUkVTT1VSQ0VfVVJMIHdyYXBwZWQgdHlwZXMgYSBzdWJ0eXBlIG9mIFVSTCB3cmFwcGVkIHR5cGVzLiAgVGhpcw0KICAgKiBpcyBwdXJlbHkgYW4gaW1wbGVtZW50YXRpb24gZGV0YWlscy4NCiAgICoNCiAgICogVGhlIGNvbnRyYWN0IGlzIHNpbXBseSB0aGlzOg0KICAgKg0KICAgKiAgICAgZ2V0VHJ1c3RlZCgkc2NlLlJFU09VUkNFX1VSTCwgdmFsdWUpIHN1Y2NlZWRpbmcgaW1wbGllcyB0aGF0IGdldFRydXN0ZWQoJHNjZS5VUkwsIHZhbHVlKQ0KICAgKiAgICAgd2lsbCBhbHNvIHN1Y2NlZWQuDQogICAqDQogICAqIEluaGVyaXRhbmNlIGhhcHBlbnMgdG8gY2FwdHVyZSB0aGlzIGluIGEgbmF0dXJhbCB3YXkuICBJbiBzb21lIGZ1dHVyZSwgd2UNCiAgICogbWF5IG5vdCB1c2UgaW5oZXJpdGFuY2UgYW55bW9yZS4gIFRoYXQgaXMgT0sgYmVjYXVzZSBubyBjb2RlIG91dHNpZGUgb2YNCiAgICogc2NlLmpzIGFuZCBzY2VTcGVjcy5qcyB3b3VsZCBuZWVkIHRvIGJlIGF3YXJlIG9mIHRoaXMgZGV0YWlsLg0KICAgKi8NCg0KICB0aGlzLiRnZXQgPSBbJyRwYXJzZScsICckc2NlRGVsZWdhdGUnLCBmdW5jdGlvbigNCiAgICAgICAgICAgICAgICAkcGFyc2UsICAgJHNjZURlbGVnYXRlKSB7DQogICAgLy8gUHJlcmVxOiBFbnN1cmUgdGhhdCB3ZSdyZSBub3QgcnVubmluZyBpbiBJRTwxMSBxdWlya3MgbW9kZS4gIEluIHRoYXQgbW9kZSwgSUUgPCAxMSBhbGxvdw0KICAgIC8vIHRoZSAiZXhwcmVzc2lvbihqYXZhc2NyaXB0IGV4cHJlc3Npb24pIiBzeW50YXggd2hpY2ggaXMgaW5zZWN1cmUuDQogICAgaWYgKGVuYWJsZWQgJiYgbXNpZSA8IDgpIHsNCiAgICAgIHRocm93ICRzY2VNaW5FcnIoJ2llcXVpcmtzJywNCiAgICAgICAgJ1N0cmljdCBDb250ZXh0dWFsIEVzY2FwaW5nIGRvZXMgbm90IHN1cHBvcnQgSW50ZXJuZXQgRXhwbG9yZXIgdmVyc2lvbiA8IDExIGluIHF1aXJrcyAnICsNCiAgICAgICAgJ21vZGUuICBZb3UgY2FuIGZpeCB0aGlzIGJ5IGFkZGluZyB0aGUgdGV4dCA8IWRvY3R5cGUgaHRtbD4gdG8gdGhlIHRvcCBvZiB5b3VyIEhUTUwgJyArDQogICAgICAgICdkb2N1bWVudC4gIFNlZSBodHRwOi8vZG9jcy5hbmd1bGFyanMub3JnL2FwaS9uZy4kc2NlIGZvciBtb3JlIGluZm9ybWF0aW9uLicpOw0KICAgIH0NCg0KICAgIHZhciBzY2UgPSBzaGFsbG93Q29weShTQ0VfQ09OVEVYVFMpOw0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRzY2UjaXNFbmFibGVkDQogICAgICogQGtpbmQgZnVuY3Rpb24NCiAgICAgKg0KICAgICAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaWYgU0NFIGlzIGVuYWJsZWQsIGZhbHNlIG90aGVyd2lzZS4gIElmIHlvdSB3YW50IHRvIHNldCB0aGUgdmFsdWUsIHlvdQ0KICAgICAqIGhhdmUgdG8gZG8gaXQgYXQgbW9kdWxlIGNvbmZpZyB0aW1lIG9uIHtAbGluayBuZy4kc2NlUHJvdmlkZXIgJHNjZVByb3ZpZGVyfS4NCiAgICAgKg0KICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAqIFJldHVybnMgYSBib29sZWFuIGluZGljYXRpbmcgaWYgU0NFIGlzIGVuYWJsZWQuDQogICAgICovDQogICAgc2NlLmlzRW5hYmxlZCA9IGZ1bmN0aW9uKCkgew0KICAgICAgcmV0dXJuIGVuYWJsZWQ7DQogICAgfTsNCiAgICBzY2UudHJ1c3RBcyA9ICRzY2VEZWxlZ2F0ZS50cnVzdEFzOw0KICAgIHNjZS5nZXRUcnVzdGVkID0gJHNjZURlbGVnYXRlLmdldFRydXN0ZWQ7DQogICAgc2NlLnZhbHVlT2YgPSAkc2NlRGVsZWdhdGUudmFsdWVPZjsNCg0KICAgIGlmICghZW5hYmxlZCkgew0KICAgICAgc2NlLnRydXN0QXMgPSBzY2UuZ2V0VHJ1c3RlZCA9IGZ1bmN0aW9uKHR5cGUsIHZhbHVlKSB7IHJldHVybiB2YWx1ZTsgfTsNCiAgICAgIHNjZS52YWx1ZU9mID0gaWRlbnRpdHk7DQogICAgfQ0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRzY2UjcGFyc2VBcw0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogQ29udmVydHMgQW5ndWxhciB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBleHByZXNzaW9ufSBpbnRvIGEgZnVuY3Rpb24uICBUaGlzIGlzIGxpa2Uge0BsaW5rDQogICAgICogbmcuJHBhcnNlICRwYXJzZX0gYW5kIGlzIGlkZW50aWNhbCB3aGVuIHRoZSBleHByZXNzaW9uIGlzIGEgbGl0ZXJhbCBjb25zdGFudC4gIE90aGVyd2lzZSwgaXQNCiAgICAgKiB3cmFwcyB0aGUgZXhwcmVzc2lvbiBpbiBhIGNhbGwgdG8ge0BsaW5rIG5nLiRzY2UjZ2V0VHJ1c3RlZCAkc2NlLmdldFRydXN0ZWQoKnR5cGUqLA0KICAgICAqICpyZXN1bHQqKX0NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIFRoZSBraW5kIG9mIFNDRSBjb250ZXh0IGluIHdoaWNoIHRoaXMgcmVzdWx0IHdpbGwgYmUgdXNlZC4NCiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZXhwcmVzc2lvbiBTdHJpbmcgZXhwcmVzc2lvbiB0byBjb21waWxlLg0KICAgICAqIEByZXR1cm5zIHtmdW5jdGlvbihjb250ZXh0LCBsb2NhbHMpfSBhIGZ1bmN0aW9uIHdoaWNoIHJlcHJlc2VudHMgdGhlIGNvbXBpbGVkIGV4cHJlc3Npb246DQogICAgICoNCiAgICAgKiAgICAqIGBjb250ZXh0YCDigD8gYHtvYmplY3R9YCDigD8gYW4gb2JqZWN0IGFnYWluc3Qgd2hpY2ggYW55IGV4cHJlc3Npb25zIGVtYmVkZGVkIGluIHRoZSBzdHJpbmdzDQogICAgICogICAgICBhcmUgZXZhbHVhdGVkIGFnYWluc3QgKHR5cGljYWxseSBhIHNjb3BlIG9iamVjdCkuDQogICAgICogICAgKiBgbG9jYWxzYCDigD8gYHtvYmplY3Q9fWAg4oA/IGxvY2FsIHZhcmlhYmxlcyBjb250ZXh0IG9iamVjdCwgdXNlZnVsIGZvciBvdmVycmlkaW5nIHZhbHVlcyBpbg0KICAgICAqICAgICAgYGNvbnRleHRgLg0KICAgICAqLw0KICAgIHNjZS5wYXJzZUFzID0gZnVuY3Rpb24gc2NlUGFyc2VBcyh0eXBlLCBleHByKSB7DQogICAgICB2YXIgcGFyc2VkID0gJHBhcnNlKGV4cHIpOw0KICAgICAgaWYgKHBhcnNlZC5saXRlcmFsICYmIHBhcnNlZC5jb25zdGFudCkgew0KICAgICAgICByZXR1cm4gcGFyc2VkOw0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgcmV0dXJuICRwYXJzZShleHByLCBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICAgIHJldHVybiBzY2UuZ2V0VHJ1c3RlZCh0eXBlLCB2YWx1ZSk7DQogICAgICAgIH0pOw0KICAgICAgfQ0KICAgIH07DQoNCiAgICAvKioNCiAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICogQG5hbWUgJHNjZSN0cnVzdEFzDQogICAgICoNCiAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgKiBEZWxlZ2F0ZXMgdG8ge0BsaW5rIG5nLiRzY2VEZWxlZ2F0ZSN0cnVzdEFzIGAkc2NlRGVsZWdhdGUudHJ1c3RBc2B9LiAgQXMgc3VjaCwNCiAgICAgKiByZXR1cm5zIGFuIG9iamVjdCB0aGF0IGlzIHRydXN0ZWQgYnkgYW5ndWxhciBmb3IgdXNlIGluIHNwZWNpZmllZCBzdHJpY3QgY29udGV4dHVhbA0KICAgICAqIGVzY2FwaW5nIGNvbnRleHRzIChzdWNoIGFzIG5nLWJpbmQtaHRtbCwgbmctaW5jbHVkZSwgYW55IHNyYyBhdHRyaWJ1dGUNCiAgICAgKiBpbnRlcnBvbGF0aW9uLCBhbnkgZG9tIGV2ZW50IGJpbmRpbmcgYXR0cmlidXRlIGludGVycG9sYXRpb24gc3VjaCBhcyBmb3Igb25jbGljaywgIGV0Yy4pDQogICAgICogdGhhdCB1c2VzIHRoZSBwcm92aWRlZCB2YWx1ZS4gIFNlZSAqIHtAbGluayBuZy4kc2NlICRzY2V9IGZvciBlbmFibGluZyBzdHJpY3QgY29udGV4dHVhbA0KICAgICAqIGVzY2FwaW5nLg0KICAgICAqDQogICAgICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgVGhlIGtpbmQgb2YgY29udGV4dCBpbiB3aGljaCB0aGlzIHZhbHVlIGlzIHNhZmUgZm9yIHVzZS4gIGUuZy4gdXJsLA0KICAgICAqICAgcmVzb3VyY2VfdXJsLCBodG1sLCBqcyBhbmQgY3NzLg0KICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRoYXQgdGhhdCBzaG91bGQgYmUgY29uc2lkZXJlZCB0cnVzdGVkL3NhZmUuDQogICAgICogQHJldHVybnMgeyp9IEEgdmFsdWUgdGhhdCBjYW4gYmUgdXNlZCB0byBzdGFuZCBpbiBmb3IgdGhlIHByb3ZpZGVkIGB2YWx1ZWAgaW4gcGxhY2VzDQogICAgICogd2hlcmUgQW5ndWxhciBleHBlY3RzIGEgJHNjZS50cnVzdEFzKCkgcmV0dXJuIHZhbHVlLg0KICAgICAqLw0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRzY2UjdHJ1c3RBc0h0bWwNCiAgICAgKg0KICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAqIFNob3J0aGFuZCBtZXRob2QuICBgJHNjZS50cnVzdEFzSHRtbCh2YWx1ZSlgIOKGPw0KICAgICAqICAgICB7QGxpbmsgbmcuJHNjZURlbGVnYXRlI3RydXN0QXMgYCRzY2VEZWxlZ2F0ZS50cnVzdEFzKCRzY2UuSFRNTCwgdmFsdWUpYH0NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHRydXN0QXMuDQogICAgICogQHJldHVybnMgeyp9IEFuIG9iamVjdCB0aGF0IGNhbiBiZSBwYXNzZWQgdG8ge0BsaW5rIG5nLiRzY2UjZ2V0VHJ1c3RlZEh0bWwNCiAgICAgKiAgICAgJHNjZS5nZXRUcnVzdGVkSHRtbCh2YWx1ZSl9IHRvIG9idGFpbiB0aGUgb3JpZ2luYWwgdmFsdWUuICAocHJpdmlsZWdlZCBkaXJlY3RpdmVzDQogICAgICogICAgIG9ubHkgYWNjZXB0IGV4cHJlc3Npb25zIHRoYXQgYXJlIGVpdGhlciBsaXRlcmFsIGNvbnN0YW50cyBvciBhcmUgdGhlDQogICAgICogICAgIHJldHVybiB2YWx1ZSBvZiB7QGxpbmsgbmcuJHNjZSN0cnVzdEFzICRzY2UudHJ1c3RBc30uKQ0KICAgICAqLw0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRzY2UjdHJ1c3RBc1VybA0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRoYW5kIG1ldGhvZC4gIGAkc2NlLnRydXN0QXNVcmwodmFsdWUpYCDihj8NCiAgICAgKiAgICAge0BsaW5rIG5nLiRzY2VEZWxlZ2F0ZSN0cnVzdEFzIGAkc2NlRGVsZWdhdGUudHJ1c3RBcygkc2NlLlVSTCwgdmFsdWUpYH0NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHRydXN0QXMuDQogICAgICogQHJldHVybnMgeyp9IEFuIG9iamVjdCB0aGF0IGNhbiBiZSBwYXNzZWQgdG8ge0BsaW5rIG5nLiRzY2UjZ2V0VHJ1c3RlZFVybA0KICAgICAqICAgICAkc2NlLmdldFRydXN0ZWRVcmwodmFsdWUpfSB0byBvYnRhaW4gdGhlIG9yaWdpbmFsIHZhbHVlLiAgKHByaXZpbGVnZWQgZGlyZWN0aXZlcw0KICAgICAqICAgICBvbmx5IGFjY2VwdCBleHByZXNzaW9ucyB0aGF0IGFyZSBlaXRoZXIgbGl0ZXJhbCBjb25zdGFudHMgb3IgYXJlIHRoZQ0KICAgICAqICAgICByZXR1cm4gdmFsdWUgb2Yge0BsaW5rIG5nLiRzY2UjdHJ1c3RBcyAkc2NlLnRydXN0QXN9LikNCiAgICAgKi8NCg0KICAgIC8qKg0KICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgKiBAbmFtZSAkc2NlI3RydXN0QXNSZXNvdXJjZVVybA0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRoYW5kIG1ldGhvZC4gIGAkc2NlLnRydXN0QXNSZXNvdXJjZVVybCh2YWx1ZSlgIOKGPw0KICAgICAqICAgICB7QGxpbmsgbmcuJHNjZURlbGVnYXRlI3RydXN0QXMgYCRzY2VEZWxlZ2F0ZS50cnVzdEFzKCRzY2UuUkVTT1VSQ0VfVVJMLCB2YWx1ZSlgfQ0KICAgICAqDQogICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gdHJ1c3RBcy4NCiAgICAgKiBAcmV0dXJucyB7Kn0gQW4gb2JqZWN0IHRoYXQgY2FuIGJlIHBhc3NlZCB0byB7QGxpbmsgbmcuJHNjZSNnZXRUcnVzdGVkUmVzb3VyY2VVcmwNCiAgICAgKiAgICAgJHNjZS5nZXRUcnVzdGVkUmVzb3VyY2VVcmwodmFsdWUpfSB0byBvYnRhaW4gdGhlIG9yaWdpbmFsIHZhbHVlLiAgKHByaXZpbGVnZWQgZGlyZWN0aXZlcw0KICAgICAqICAgICBvbmx5IGFjY2VwdCBleHByZXNzaW9ucyB0aGF0IGFyZSBlaXRoZXIgbGl0ZXJhbCBjb25zdGFudHMgb3IgYXJlIHRoZSByZXR1cm4NCiAgICAgKiAgICAgdmFsdWUgb2Yge0BsaW5rIG5nLiRzY2UjdHJ1c3RBcyAkc2NlLnRydXN0QXN9LikNCiAgICAgKi8NCg0KICAgIC8qKg0KICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgKiBAbmFtZSAkc2NlI3RydXN0QXNKcw0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRoYW5kIG1ldGhvZC4gIGAkc2NlLnRydXN0QXNKcyh2YWx1ZSlgIOKGPw0KICAgICAqICAgICB7QGxpbmsgbmcuJHNjZURlbGVnYXRlI3RydXN0QXMgYCRzY2VEZWxlZ2F0ZS50cnVzdEFzKCRzY2UuSlMsIHZhbHVlKWB9DQogICAgICoNCiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB0cnVzdEFzLg0KICAgICAqIEByZXR1cm5zIHsqfSBBbiBvYmplY3QgdGhhdCBjYW4gYmUgcGFzc2VkIHRvIHtAbGluayBuZy4kc2NlI2dldFRydXN0ZWRKcw0KICAgICAqICAgICAkc2NlLmdldFRydXN0ZWRKcyh2YWx1ZSl9IHRvIG9idGFpbiB0aGUgb3JpZ2luYWwgdmFsdWUuICAocHJpdmlsZWdlZCBkaXJlY3RpdmVzDQogICAgICogICAgIG9ubHkgYWNjZXB0IGV4cHJlc3Npb25zIHRoYXQgYXJlIGVpdGhlciBsaXRlcmFsIGNvbnN0YW50cyBvciBhcmUgdGhlDQogICAgICogICAgIHJldHVybiB2YWx1ZSBvZiB7QGxpbmsgbmcuJHNjZSN0cnVzdEFzICRzY2UudHJ1c3RBc30uKQ0KICAgICAqLw0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRzY2UjZ2V0VHJ1c3RlZA0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogRGVsZWdhdGVzIHRvIHtAbGluayBuZy4kc2NlRGVsZWdhdGUjZ2V0VHJ1c3RlZCBgJHNjZURlbGVnYXRlLmdldFRydXN0ZWRgfS4gIEFzIHN1Y2gsDQogICAgICogdGFrZXMgdGhlIHJlc3VsdCBvZiBhIHtAbGluayBuZy4kc2NlI3RydXN0QXMgYCRzY2UudHJ1c3RBc2B9KCkgY2FsbCBhbmQgcmV0dXJucyB0aGUNCiAgICAgKiBvcmlnaW5hbGx5IHN1cHBsaWVkIHZhbHVlIGlmIHRoZSBxdWVyaWVkIGNvbnRleHQgdHlwZSBpcyBhIHN1cGVydHlwZSBvZiB0aGUgY3JlYXRlZCB0eXBlLg0KICAgICAqIElmIHRoaXMgY29uZGl0aW9uIGlzbid0IHNhdGlzZmllZCwgdGhyb3dzIGFuIGV4Y2VwdGlvbi4NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIFRoZSBraW5kIG9mIGNvbnRleHQgaW4gd2hpY2ggdGhpcyB2YWx1ZSBpcyB0byBiZSB1c2VkLg0KICAgICAqIEBwYXJhbSB7Kn0gbWF5YmVUcnVzdGVkIFRoZSByZXN1bHQgb2YgYSBwcmlvciB7QGxpbmsgbmcuJHNjZSN0cnVzdEFzIGAkc2NlLnRydXN0QXNgfQ0KICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGwuDQogICAgICogQHJldHVybnMgeyp9IFRoZSB2YWx1ZSB0aGUgd2FzIG9yaWdpbmFsbHkgcHJvdmlkZWQgdG8NCiAgICAgKiAgICAgICAgICAgICAge0BsaW5rIG5nLiRzY2UjdHJ1c3RBcyBgJHNjZS50cnVzdEFzYH0gaWYgdmFsaWQgaW4gdGhpcyBjb250ZXh0Lg0KICAgICAqICAgICAgICAgICAgICBPdGhlcndpc2UsIHRocm93cyBhbiBleGNlcHRpb24uDQogICAgICovDQoNCiAgICAvKioNCiAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICogQG5hbWUgJHNjZSNnZXRUcnVzdGVkSHRtbA0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRoYW5kIG1ldGhvZC4gIGAkc2NlLmdldFRydXN0ZWRIdG1sKHZhbHVlKWAg4oY/DQogICAgICogICAgIHtAbGluayBuZy4kc2NlRGVsZWdhdGUjZ2V0VHJ1c3RlZCBgJHNjZURlbGVnYXRlLmdldFRydXN0ZWQoJHNjZS5IVE1MLCB2YWx1ZSlgfQ0KICAgICAqDQogICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcGFzcyB0byBgJHNjZS5nZXRUcnVzdGVkYC4NCiAgICAgKiBAcmV0dXJucyB7Kn0gVGhlIHJldHVybiB2YWx1ZSBvZiBgJHNjZS5nZXRUcnVzdGVkKCRzY2UuSFRNTCwgdmFsdWUpYA0KICAgICAqLw0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRzY2UjZ2V0VHJ1c3RlZENzcw0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRoYW5kIG1ldGhvZC4gIGAkc2NlLmdldFRydXN0ZWRDc3ModmFsdWUpYCDihj8NCiAgICAgKiAgICAge0BsaW5rIG5nLiRzY2VEZWxlZ2F0ZSNnZXRUcnVzdGVkIGAkc2NlRGVsZWdhdGUuZ2V0VHJ1c3RlZCgkc2NlLkNTUywgdmFsdWUpYH0NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHBhc3MgdG8gYCRzY2UuZ2V0VHJ1c3RlZGAuDQogICAgICogQHJldHVybnMgeyp9IFRoZSByZXR1cm4gdmFsdWUgb2YgYCRzY2UuZ2V0VHJ1c3RlZCgkc2NlLkNTUywgdmFsdWUpYA0KICAgICAqLw0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRzY2UjZ2V0VHJ1c3RlZFVybA0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRoYW5kIG1ldGhvZC4gIGAkc2NlLmdldFRydXN0ZWRVcmwodmFsdWUpYCDihj8NCiAgICAgKiAgICAge0BsaW5rIG5nLiRzY2VEZWxlZ2F0ZSNnZXRUcnVzdGVkIGAkc2NlRGVsZWdhdGUuZ2V0VHJ1c3RlZCgkc2NlLlVSTCwgdmFsdWUpYH0NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHBhc3MgdG8gYCRzY2UuZ2V0VHJ1c3RlZGAuDQogICAgICogQHJldHVybnMgeyp9IFRoZSByZXR1cm4gdmFsdWUgb2YgYCRzY2UuZ2V0VHJ1c3RlZCgkc2NlLlVSTCwgdmFsdWUpYA0KICAgICAqLw0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRzY2UjZ2V0VHJ1c3RlZFJlc291cmNlVXJsDQogICAgICoNCiAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgKiBTaG9ydGhhbmQgbWV0aG9kLiAgYCRzY2UuZ2V0VHJ1c3RlZFJlc291cmNlVXJsKHZhbHVlKWAg4oY/DQogICAgICogICAgIHtAbGluayBuZy4kc2NlRGVsZWdhdGUjZ2V0VHJ1c3RlZCBgJHNjZURlbGVnYXRlLmdldFRydXN0ZWQoJHNjZS5SRVNPVVJDRV9VUkwsIHZhbHVlKWB9DQogICAgICoNCiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwYXNzIHRvIGAkc2NlRGVsZWdhdGUuZ2V0VHJ1c3RlZGAuDQogICAgICogQHJldHVybnMgeyp9IFRoZSByZXR1cm4gdmFsdWUgb2YgYCRzY2UuZ2V0VHJ1c3RlZCgkc2NlLlJFU09VUkNFX1VSTCwgdmFsdWUpYA0KICAgICAqLw0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRzY2UjZ2V0VHJ1c3RlZEpzDQogICAgICoNCiAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgKiBTaG9ydGhhbmQgbWV0aG9kLiAgYCRzY2UuZ2V0VHJ1c3RlZEpzKHZhbHVlKWAg4oY/DQogICAgICogICAgIHtAbGluayBuZy4kc2NlRGVsZWdhdGUjZ2V0VHJ1c3RlZCBgJHNjZURlbGVnYXRlLmdldFRydXN0ZWQoJHNjZS5KUywgdmFsdWUpYH0NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHBhc3MgdG8gYCRzY2UuZ2V0VHJ1c3RlZGAuDQogICAgICogQHJldHVybnMgeyp9IFRoZSByZXR1cm4gdmFsdWUgb2YgYCRzY2UuZ2V0VHJ1c3RlZCgkc2NlLkpTLCB2YWx1ZSlgDQogICAgICovDQoNCiAgICAvKioNCiAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICogQG5hbWUgJHNjZSNwYXJzZUFzSHRtbA0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRoYW5kIG1ldGhvZC4gIGAkc2NlLnBhcnNlQXNIdG1sKGV4cHJlc3Npb24gc3RyaW5nKWAg4oY/DQogICAgICogICAgIHtAbGluayBuZy4kc2NlI3BhcnNlQXMgYCRzY2UucGFyc2VBcygkc2NlLkhUTUwsIHZhbHVlKWB9DQogICAgICoNCiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZXhwcmVzc2lvbiBTdHJpbmcgZXhwcmVzc2lvbiB0byBjb21waWxlLg0KICAgICAqIEByZXR1cm5zIHtmdW5jdGlvbihjb250ZXh0LCBsb2NhbHMpfSBhIGZ1bmN0aW9uIHdoaWNoIHJlcHJlc2VudHMgdGhlIGNvbXBpbGVkIGV4cHJlc3Npb246DQogICAgICoNCiAgICAgKiAgICAqIGBjb250ZXh0YCDigD8gYHtvYmplY3R9YCDigD8gYW4gb2JqZWN0IGFnYWluc3Qgd2hpY2ggYW55IGV4cHJlc3Npb25zIGVtYmVkZGVkIGluIHRoZSBzdHJpbmdzDQogICAgICogICAgICBhcmUgZXZhbHVhdGVkIGFnYWluc3QgKHR5cGljYWxseSBhIHNjb3BlIG9iamVjdCkuDQogICAgICogICAgKiBgbG9jYWxzYCDigD8gYHtvYmplY3Q9fWAg4oA/IGxvY2FsIHZhcmlhYmxlcyBjb250ZXh0IG9iamVjdCwgdXNlZnVsIGZvciBvdmVycmlkaW5nIHZhbHVlcyBpbg0KICAgICAqICAgICAgYGNvbnRleHRgLg0KICAgICAqLw0KDQogICAgLyoqDQogICAgICogQG5nZG9jIG1ldGhvZA0KICAgICAqIEBuYW1lICRzY2UjcGFyc2VBc0Nzcw0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRoYW5kIG1ldGhvZC4gIGAkc2NlLnBhcnNlQXNDc3ModmFsdWUpYCDihj8NCiAgICAgKiAgICAge0BsaW5rIG5nLiRzY2UjcGFyc2VBcyBgJHNjZS5wYXJzZUFzKCRzY2UuQ1NTLCB2YWx1ZSlgfQ0KICAgICAqDQogICAgICogQHBhcmFtIHtzdHJpbmd9IGV4cHJlc3Npb24gU3RyaW5nIGV4cHJlc3Npb24gdG8gY29tcGlsZS4NCiAgICAgKiBAcmV0dXJucyB7ZnVuY3Rpb24oY29udGV4dCwgbG9jYWxzKX0gYSBmdW5jdGlvbiB3aGljaCByZXByZXNlbnRzIHRoZSBjb21waWxlZCBleHByZXNzaW9uOg0KICAgICAqDQogICAgICogICAgKiBgY29udGV4dGAg4oA/IGB7b2JqZWN0fWAg4oA/IGFuIG9iamVjdCBhZ2FpbnN0IHdoaWNoIGFueSBleHByZXNzaW9ucyBlbWJlZGRlZCBpbiB0aGUgc3RyaW5ncw0KICAgICAqICAgICAgYXJlIGV2YWx1YXRlZCBhZ2FpbnN0ICh0eXBpY2FsbHkgYSBzY29wZSBvYmplY3QpLg0KICAgICAqICAgICogYGxvY2Fsc2Ag4oA/IGB7b2JqZWN0PX1gIOKAPyBsb2NhbCB2YXJpYWJsZXMgY29udGV4dCBvYmplY3QsIHVzZWZ1bCBmb3Igb3ZlcnJpZGluZyB2YWx1ZXMgaW4NCiAgICAgKiAgICAgIGBjb250ZXh0YC4NCiAgICAgKi8NCg0KICAgIC8qKg0KICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgKiBAbmFtZSAkc2NlI3BhcnNlQXNVcmwNCiAgICAgKg0KICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAqIFNob3J0aGFuZCBtZXRob2QuICBgJHNjZS5wYXJzZUFzVXJsKHZhbHVlKWAg4oY/DQogICAgICogICAgIHtAbGluayBuZy4kc2NlI3BhcnNlQXMgYCRzY2UucGFyc2VBcygkc2NlLlVSTCwgdmFsdWUpYH0NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7c3RyaW5nfSBleHByZXNzaW9uIFN0cmluZyBleHByZXNzaW9uIHRvIGNvbXBpbGUuDQogICAgICogQHJldHVybnMge2Z1bmN0aW9uKGNvbnRleHQsIGxvY2Fscyl9IGEgZnVuY3Rpb24gd2hpY2ggcmVwcmVzZW50cyB0aGUgY29tcGlsZWQgZXhwcmVzc2lvbjoNCiAgICAgKg0KICAgICAqICAgICogYGNvbnRleHRgIOKAPyBge29iamVjdH1gIOKAPyBhbiBvYmplY3QgYWdhaW5zdCB3aGljaCBhbnkgZXhwcmVzc2lvbnMgZW1iZWRkZWQgaW4gdGhlIHN0cmluZ3MNCiAgICAgKiAgICAgIGFyZSBldmFsdWF0ZWQgYWdhaW5zdCAodHlwaWNhbGx5IGEgc2NvcGUgb2JqZWN0KS4NCiAgICAgKiAgICAqIGBsb2NhbHNgIOKAPyBge29iamVjdD19YCDigD8gbG9jYWwgdmFyaWFibGVzIGNvbnRleHQgb2JqZWN0LCB1c2VmdWwgZm9yIG92ZXJyaWRpbmcgdmFsdWVzIGluDQogICAgICogICAgICBgY29udGV4dGAuDQogICAgICovDQoNCiAgICAvKioNCiAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICogQG5hbWUgJHNjZSNwYXJzZUFzUmVzb3VyY2VVcmwNCiAgICAgKg0KICAgICAqIEBkZXNjcmlwdGlvbg0KICAgICAqIFNob3J0aGFuZCBtZXRob2QuICBgJHNjZS5wYXJzZUFzUmVzb3VyY2VVcmwodmFsdWUpYCDihj8NCiAgICAgKiAgICAge0BsaW5rIG5nLiRzY2UjcGFyc2VBcyBgJHNjZS5wYXJzZUFzKCRzY2UuUkVTT1VSQ0VfVVJMLCB2YWx1ZSlgfQ0KICAgICAqDQogICAgICogQHBhcmFtIHtzdHJpbmd9IGV4cHJlc3Npb24gU3RyaW5nIGV4cHJlc3Npb24gdG8gY29tcGlsZS4NCiAgICAgKiBAcmV0dXJucyB7ZnVuY3Rpb24oY29udGV4dCwgbG9jYWxzKX0gYSBmdW5jdGlvbiB3aGljaCByZXByZXNlbnRzIHRoZSBjb21waWxlZCBleHByZXNzaW9uOg0KICAgICAqDQogICAgICogICAgKiBgY29udGV4dGAg4oA/IGB7b2JqZWN0fWAg4oA/IGFuIG9iamVjdCBhZ2FpbnN0IHdoaWNoIGFueSBleHByZXNzaW9ucyBlbWJlZGRlZCBpbiB0aGUgc3RyaW5ncw0KICAgICAqICAgICAgYXJlIGV2YWx1YXRlZCBhZ2FpbnN0ICh0eXBpY2FsbHkgYSBzY29wZSBvYmplY3QpLg0KICAgICAqICAgICogYGxvY2Fsc2Ag4oA/IGB7b2JqZWN0PX1gIOKAPyBsb2NhbCB2YXJpYWJsZXMgY29udGV4dCBvYmplY3QsIHVzZWZ1bCBmb3Igb3ZlcnJpZGluZyB2YWx1ZXMgaW4NCiAgICAgKiAgICAgIGBjb250ZXh0YC4NCiAgICAgKi8NCg0KICAgIC8qKg0KICAgICAqIEBuZ2RvYyBtZXRob2QNCiAgICAgKiBAbmFtZSAkc2NlI3BhcnNlQXNKcw0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRoYW5kIG1ldGhvZC4gIGAkc2NlLnBhcnNlQXNKcyh2YWx1ZSlgIOKGPw0KICAgICAqICAgICB7QGxpbmsgbmcuJHNjZSNwYXJzZUFzIGAkc2NlLnBhcnNlQXMoJHNjZS5KUywgdmFsdWUpYH0NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7c3RyaW5nfSBleHByZXNzaW9uIFN0cmluZyBleHByZXNzaW9uIHRvIGNvbXBpbGUuDQogICAgICogQHJldHVybnMge2Z1bmN0aW9uKGNvbnRleHQsIGxvY2Fscyl9IGEgZnVuY3Rpb24gd2hpY2ggcmVwcmVzZW50cyB0aGUgY29tcGlsZWQgZXhwcmVzc2lvbjoNCiAgICAgKg0KICAgICAqICAgICogYGNvbnRleHRgIOKAPyBge29iamVjdH1gIOKAPyBhbiBvYmplY3QgYWdhaW5zdCB3aGljaCBhbnkgZXhwcmVzc2lvbnMgZW1iZWRkZWQgaW4gdGhlIHN0cmluZ3MNCiAgICAgKiAgICAgIGFyZSBldmFsdWF0ZWQgYWdhaW5zdCAodHlwaWNhbGx5IGEgc2NvcGUgb2JqZWN0KS4NCiAgICAgKiAgICAqIGBsb2NhbHNgIOKAPyBge29iamVjdD19YCDigD8gbG9jYWwgdmFyaWFibGVzIGNvbnRleHQgb2JqZWN0LCB1c2VmdWwgZm9yIG92ZXJyaWRpbmcgdmFsdWVzIGluDQogICAgICogICAgICBgY29udGV4dGAuDQogICAgICovDQoNCiAgICAvLyBTaG9ydGhhbmQgZGVsZWdhdGlvbnMuDQogICAgdmFyIHBhcnNlID0gc2NlLnBhcnNlQXMsDQogICAgICAgIGdldFRydXN0ZWQgPSBzY2UuZ2V0VHJ1c3RlZCwNCiAgICAgICAgdHJ1c3RBcyA9IHNjZS50cnVzdEFzOw0KDQogICAgZm9yRWFjaChTQ0VfQ09OVEVYVFMsIGZ1bmN0aW9uKGVudW1WYWx1ZSwgbmFtZSkgew0KICAgICAgdmFyIGxOYW1lID0gbG93ZXJjYXNlKG5hbWUpOw0KICAgICAgc2NlW2NhbWVsQ2FzZSgicGFyc2VfYXNfIiArIGxOYW1lKV0gPSBmdW5jdGlvbihleHByKSB7DQogICAgICAgIHJldHVybiBwYXJzZShlbnVtVmFsdWUsIGV4cHIpOw0KICAgICAgfTsNCiAgICAgIHNjZVtjYW1lbENhc2UoImdldF90cnVzdGVkXyIgKyBsTmFtZSldID0gZnVuY3Rpb24odmFsdWUpIHsNCiAgICAgICAgcmV0dXJuIGdldFRydXN0ZWQoZW51bVZhbHVlLCB2YWx1ZSk7DQogICAgICB9Ow0KICAgICAgc2NlW2NhbWVsQ2FzZSgidHJ1c3RfYXNfIiArIGxOYW1lKV0gPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICByZXR1cm4gdHJ1c3RBcyhlbnVtVmFsdWUsIHZhbHVlKTsNCiAgICAgIH07DQogICAgfSk7DQoNCiAgICByZXR1cm4gc2NlOw0KICB9XTsNCn0NCg0KLyoqDQogKiAhISEgVGhpcyBpcyBhbiB1bmRvY3VtZW50ZWQgInByaXZhdGUiIHNlcnZpY2UgISEhDQogKg0KICogQG5hbWUgJHNuaWZmZXINCiAqIEByZXF1aXJlcyAkd2luZG93DQogKiBAcmVxdWlyZXMgJGRvY3VtZW50DQogKg0KICogQHByb3BlcnR5IHtib29sZWFufSBoaXN0b3J5IERvZXMgdGhlIGJyb3dzZXIgc3VwcG9ydCBodG1sNSBoaXN0b3J5IGFwaSA/DQogKiBAcHJvcGVydHkge2Jvb2xlYW59IHRyYW5zaXRpb25zIERvZXMgdGhlIGJyb3dzZXIgc3VwcG9ydCBDU1MgdHJhbnNpdGlvbiBldmVudHMgPw0KICogQHByb3BlcnR5IHtib29sZWFufSBhbmltYXRpb25zIERvZXMgdGhlIGJyb3dzZXIgc3VwcG9ydCBDU1MgYW5pbWF0aW9uIGV2ZW50cyA/DQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBUaGlzIGlzIHZlcnkgc2ltcGxlIGltcGxlbWVudGF0aW9uIG9mIHRlc3RpbmcgYnJvd3NlcidzIGZlYXR1cmVzLg0KICovDQpmdW5jdGlvbiAkU25pZmZlclByb3ZpZGVyKCkgew0KICB0aGlzLiRnZXQgPSBbJyR3aW5kb3cnLCAnJGRvY3VtZW50JywgZnVuY3Rpb24oJHdpbmRvdywgJGRvY3VtZW50KSB7DQogICAgdmFyIGV2ZW50U3VwcG9ydCA9IHt9LA0KICAgICAgICBhbmRyb2lkID0NCiAgICAgICAgICBpbnQoKC9hbmRyb2lkIChcZCspLy5leGVjKGxvd2VyY2FzZSgoJHdpbmRvdy5uYXZpZ2F0b3IgfHwge30pLnVzZXJBZ2VudCkpIHx8IFtdKVsxXSksDQogICAgICAgIGJveGVlID0gL0JveGVlL2kudGVzdCgoJHdpbmRvdy5uYXZpZ2F0b3IgfHwge30pLnVzZXJBZ2VudCksDQogICAgICAgIGRvY3VtZW50ID0gJGRvY3VtZW50WzBdIHx8IHt9LA0KICAgICAgICB2ZW5kb3JQcmVmaXgsDQogICAgICAgIHZlbmRvclJlZ2V4ID0gL14oTW96fHdlYmtpdHxtcykoPz1bQS1aXSkvLA0KICAgICAgICBib2R5U3R5bGUgPSBkb2N1bWVudC5ib2R5ICYmIGRvY3VtZW50LmJvZHkuc3R5bGUsDQogICAgICAgIHRyYW5zaXRpb25zID0gZmFsc2UsDQogICAgICAgIGFuaW1hdGlvbnMgPSBmYWxzZSwNCiAgICAgICAgbWF0Y2g7DQoNCiAgICBpZiAoYm9keVN0eWxlKSB7DQogICAgICBmb3IgKHZhciBwcm9wIGluIGJvZHlTdHlsZSkgew0KICAgICAgICBpZiAobWF0Y2ggPSB2ZW5kb3JSZWdleC5leGVjKHByb3ApKSB7DQogICAgICAgICAgdmVuZG9yUHJlZml4ID0gbWF0Y2hbMF07DQogICAgICAgICAgdmVuZG9yUHJlZml4ID0gdmVuZG9yUHJlZml4LnN1YnN0cigwLCAxKS50b1VwcGVyQ2FzZSgpICsgdmVuZG9yUHJlZml4LnN1YnN0cigxKTsNCiAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KICAgICAgfQ0KDQogICAgICBpZiAoIXZlbmRvclByZWZpeCkgew0KICAgICAgICB2ZW5kb3JQcmVmaXggPSAoJ1dlYmtpdE9wYWNpdHknIGluIGJvZHlTdHlsZSkgJiYgJ3dlYmtpdCc7DQogICAgICB9DQoNCiAgICAgIHRyYW5zaXRpb25zID0gISEoKCd0cmFuc2l0aW9uJyBpbiBib2R5U3R5bGUpIHx8ICh2ZW5kb3JQcmVmaXggKyAnVHJhbnNpdGlvbicgaW4gYm9keVN0eWxlKSk7DQogICAgICBhbmltYXRpb25zICA9ICEhKCgnYW5pbWF0aW9uJyBpbiBib2R5U3R5bGUpIHx8ICh2ZW5kb3JQcmVmaXggKyAnQW5pbWF0aW9uJyBpbiBib2R5U3R5bGUpKTsNCg0KICAgICAgaWYgKGFuZHJvaWQgJiYgKCF0cmFuc2l0aW9ucyB8fCAgIWFuaW1hdGlvbnMpKSB7DQogICAgICAgIHRyYW5zaXRpb25zID0gaXNTdHJpbmcoZG9jdW1lbnQuYm9keS5zdHlsZS53ZWJraXRUcmFuc2l0aW9uKTsNCiAgICAgICAgYW5pbWF0aW9ucyA9IGlzU3RyaW5nKGRvY3VtZW50LmJvZHkuc3R5bGUud2Via2l0QW5pbWF0aW9uKTsNCiAgICAgIH0NCiAgICB9DQoNCg0KICAgIHJldHVybiB7DQogICAgICAvLyBBbmRyb2lkIGhhcyBoaXN0b3J5LnB1c2hTdGF0ZSwgYnV0IGl0IGRvZXMgbm90IHVwZGF0ZSBsb2NhdGlvbiBjb3JyZWN0bHkNCiAgICAgIC8vIHNvIGxldCdzIG5vdCB1c2UgdGhlIGhpc3RvcnkgQVBJIGF0IGFsbC4NCiAgICAgIC8vIGh0dHA6Ly9jb2RlLmdvb2dsZS5jb20vcC9hbmRyb2lkL2lzc3Vlcy9kZXRhaWw/aWQ9MTc0NzENCiAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIuanMvaXNzdWVzLzkwNA0KDQogICAgICAvLyBvbGRlciB3ZWJraXQgYnJvd3NlciAoNTMzLjkpIG9uIEJveGVlIGJveCBoYXMgZXhhY3RseSB0aGUgc2FtZSBwcm9ibGVtIGFzIEFuZHJvaWQgaGFzDQogICAgICAvLyBzbyBsZXQncyBub3QgdXNlIHRoZSBoaXN0b3J5IEFQSSBhbHNvDQogICAgICAvLyBXZSBhcmUgcHVycG9zZWZ1bGx5IHVzaW5nIGAhKGFuZHJvaWQgPCA0KWAgdG8gY292ZXIgdGhlIGNhc2Ugd2hlbiBgYW5kcm9pZGAgaXMgdW5kZWZpbmVkDQogICAgICAvLyBqc2hpbnQgLVcwMTgNCiAgICAgIGhpc3Rvcnk6ICEhKCR3aW5kb3cuaGlzdG9yeSAmJiAkd2luZG93Lmhpc3RvcnkucHVzaFN0YXRlICYmICEoYW5kcm9pZCA8IDQpICYmICFib3hlZSksDQogICAgICAvLyBqc2hpbnQgK1cwMTgNCiAgICAgIGhhc0V2ZW50OiBmdW5jdGlvbihldmVudCkgew0KICAgICAgICAvLyBJRTkgaW1wbGVtZW50cyAnaW5wdXQnIGV2ZW50IGl0J3Mgc28gZnViYXJlZCB0aGF0IHdlIHJhdGhlciBwcmV0ZW5kIHRoYXQgaXQgZG9lc24ndCBoYXZlDQogICAgICAgIC8vIGl0LiBJbiBwYXJ0aWN1bGFyIHRoZSBldmVudCBpcyBub3QgZmlyZWQgd2hlbiBiYWNrc3BhY2Ugb3IgZGVsZXRlIGtleSBhcmUgcHJlc3NlZCBvcg0KICAgICAgICAvLyB3aGVuIGN1dCBvcGVyYXRpb24gaXMgcGVyZm9ybWVkLg0KICAgICAgICAvLyBJRTEwKyBpbXBsZW1lbnRzICdpbnB1dCcgZXZlbnQgYnV0IGl0IGVycm9uZW91c2x5IGZpcmVzIHVuZGVyIHZhcmlvdXMgc2l0dWF0aW9ucywNCiAgICAgICAgLy8gZS5nLiB3aGVuIHBsYWNlaG9sZGVyIGNoYW5nZXMsIG9yIGEgZm9ybSBpcyBmb2N1c2VkLg0KICAgICAgICBpZiAoZXZlbnQgPT09ICdpbnB1dCcgJiYgbXNpZSA8PSAxMSkgcmV0dXJuIGZhbHNlOw0KDQogICAgICAgIGlmIChpc1VuZGVmaW5lZChldmVudFN1cHBvcnRbZXZlbnRdKSkgew0KICAgICAgICAgIHZhciBkaXZFbG0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsNCiAgICAgICAgICBldmVudFN1cHBvcnRbZXZlbnRdID0gJ29uJyArIGV2ZW50IGluIGRpdkVsbTsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiBldmVudFN1cHBvcnRbZXZlbnRdOw0KICAgICAgfSwNCiAgICAgIGNzcDogY3NwKCksDQogICAgICB2ZW5kb3JQcmVmaXg6IHZlbmRvclByZWZpeCwNCiAgICAgIHRyYW5zaXRpb25zOiB0cmFuc2l0aW9ucywNCiAgICAgIGFuaW1hdGlvbnM6IGFuaW1hdGlvbnMsDQogICAgICBhbmRyb2lkOiBhbmRyb2lkDQogICAgfTsNCiAgfV07DQp9DQoNCnZhciAkY29tcGlsZU1pbkVyciA9IG1pbkVycignJGNvbXBpbGUnKTsNCg0KLyoqDQogKiBAbmdkb2Mgc2VydmljZQ0KICogQG5hbWUgJHRlbXBsYXRlUmVxdWVzdA0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlIGAkdGVtcGxhdGVSZXF1ZXN0YCBzZXJ2aWNlIGRvd25sb2FkcyB0aGUgcHJvdmlkZWQgdGVtcGxhdGUgdXNpbmcgYCRodHRwYCBhbmQsIHVwb24gc3VjY2VzcywNCiAqIHN0b3JlcyB0aGUgY29udGVudHMgaW5zaWRlIG9mIGAkdGVtcGxhdGVDYWNoZWAuIElmIHRoZSBIVFRQIHJlcXVlc3QgZmFpbHMgb3IgdGhlIHJlc3BvbnNlIGRhdGENCiAqIG9mIHRoZSBIVFRQIHJlcXVlc3QgaXMgZW1wdHksIGEgYCRjb21waWxlYCBlcnJvciB3aWxsIGJlIHRocm93biAodGhlIGV4Y2VwdGlvbiBjYW4gYmUgdGh3YXJ0ZWQNCiAqIGJ5IHNldHRpbmcgdGhlIDJuZCBwYXJhbWV0ZXIgb2YgdGhlIGZ1bmN0aW9uIHRvIHRydWUpLg0KICoNCiAqIEBwYXJhbSB7c3RyaW5nfSB0cGwgVGhlIEhUVFAgcmVxdWVzdCB0ZW1wbGF0ZSBVUkwNCiAqIEBwYXJhbSB7Ym9vbGVhbj19IGlnbm9yZVJlcXVlc3RFcnJvciBXaGV0aGVyIG9yIG5vdCB0byBpZ25vcmUgdGhlIGV4Y2VwdGlvbiB3aGVuIHRoZSByZXF1ZXN0IGZhaWxzIG9yIHRoZSB0ZW1wbGF0ZSBpcyBlbXB0eQ0KICoNCiAqIEByZXR1cm4ge1Byb21pc2V9IHRoZSBIVFRQIFByb21pc2UgZm9yIHRoZSBnaXZlbi4NCiAqDQogKiBAcHJvcGVydHkge251bWJlcn0gdG90YWxQZW5kaW5nUmVxdWVzdHMgdG90YWwgYW1vdW50IG9mIHBlbmRpbmcgdGVtcGxhdGUgcmVxdWVzdHMgYmVpbmcgZG93bmxvYWRlZC4NCiAqLw0KZnVuY3Rpb24gJFRlbXBsYXRlUmVxdWVzdFByb3ZpZGVyKCkgew0KICB0aGlzLiRnZXQgPSBbJyR0ZW1wbGF0ZUNhY2hlJywgJyRodHRwJywgJyRxJywgZnVuY3Rpb24oJHRlbXBsYXRlQ2FjaGUsICRodHRwLCAkcSkgew0KICAgIGZ1bmN0aW9uIGhhbmRsZVJlcXVlc3RGbih0cGwsIGlnbm9yZVJlcXVlc3RFcnJvcikgew0KICAgICAgdmFyIHNlbGYgPSBoYW5kbGVSZXF1ZXN0Rm47DQogICAgICBzZWxmLnRvdGFsUGVuZGluZ1JlcXVlc3RzKys7DQoNCiAgICAgIHZhciB0cmFuc2Zvcm1SZXNwb25zZSA9ICRodHRwLmRlZmF1bHRzICYmICRodHRwLmRlZmF1bHRzLnRyYW5zZm9ybVJlc3BvbnNlOw0KDQogICAgICBpZiAoaXNBcnJheSh0cmFuc2Zvcm1SZXNwb25zZSkpIHsNCiAgICAgICAgdHJhbnNmb3JtUmVzcG9uc2UgPSB0cmFuc2Zvcm1SZXNwb25zZS5maWx0ZXIoZnVuY3Rpb24odHJhbnNmb3JtZXIpIHsNCiAgICAgICAgICByZXR1cm4gdHJhbnNmb3JtZXIgIT09IGRlZmF1bHRIdHRwUmVzcG9uc2VUcmFuc2Zvcm07DQogICAgICAgIH0pOw0KICAgICAgfSBlbHNlIGlmICh0cmFuc2Zvcm1SZXNwb25zZSA9PT0gZGVmYXVsdEh0dHBSZXNwb25zZVRyYW5zZm9ybSkgew0KICAgICAgICB0cmFuc2Zvcm1SZXNwb25zZSA9IG51bGw7DQogICAgICB9DQoNCiAgICAgIHZhciBodHRwT3B0aW9ucyA9IHsNCiAgICAgICAgY2FjaGU6ICR0ZW1wbGF0ZUNhY2hlLA0KICAgICAgICB0cmFuc2Zvcm1SZXNwb25zZTogdHJhbnNmb3JtUmVzcG9uc2UNCiAgICAgIH07DQoNCiAgICAgIHJldHVybiAkaHR0cC5nZXQodHBsLCBodHRwT3B0aW9ucykNCiAgICAgICAgLnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHsNCiAgICAgICAgICBzZWxmLnRvdGFsUGVuZGluZ1JlcXVlc3RzLS07DQogICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGE7DQogICAgICAgIH0sIGhhbmRsZUVycm9yKTsNCg0KICAgICAgZnVuY3Rpb24gaGFuZGxlRXJyb3IocmVzcCkgew0KICAgICAgICBzZWxmLnRvdGFsUGVuZGluZ1JlcXVlc3RzLS07DQogICAgICAgIGlmICghaWdub3JlUmVxdWVzdEVycm9yKSB7DQogICAgICAgICAgdGhyb3cgJGNvbXBpbGVNaW5FcnIoJ3RwbG9hZCcsICdGYWlsZWQgdG8gbG9hZCB0ZW1wbGF0ZTogezB9JywgdHBsKTsNCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gJHEucmVqZWN0KHJlc3ApOw0KICAgICAgfQ0KICAgIH0NCg0KICAgIGhhbmRsZVJlcXVlc3RGbi50b3RhbFBlbmRpbmdSZXF1ZXN0cyA9IDA7DQoNCiAgICByZXR1cm4gaGFuZGxlUmVxdWVzdEZuOw0KICB9XTsNCn0NCg0KZnVuY3Rpb24gJCRUZXN0YWJpbGl0eVByb3ZpZGVyKCkgew0KICB0aGlzLiRnZXQgPSBbJyRyb290U2NvcGUnLCAnJGJyb3dzZXInLCAnJGxvY2F0aW9uJywNCiAgICAgICBmdW5jdGlvbigkcm9vdFNjb3BlLCAgICRicm93c2VyLCAgICRsb2NhdGlvbikgew0KDQogICAgLyoqDQogICAgICogQG5hbWUgJHRlc3RhYmlsaXR5DQogICAgICoNCiAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgKiBUaGUgcHJpdmF0ZSAkJHRlc3RhYmlsaXR5IHNlcnZpY2UgcHJvdmlkZXMgYSBjb2xsZWN0aW9uIG9mIG1ldGhvZHMgZm9yIHVzZSB3aGVuIGRlYnVnZ2luZw0KICAgICAqIG9yIGJ5IGF1dG9tYXRlZCB0ZXN0IGFuZCBkZWJ1Z2dpbmcgdG9vbHMuDQogICAgICovDQogICAgdmFyIHRlc3RhYmlsaXR5ID0ge307DQoNCiAgICAvKioNCiAgICAgKiBAbmFtZSAkJHRlc3RhYmlsaXR5I2ZpbmRCaW5kaW5ncw0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogUmV0dXJucyBhbiBhcnJheSBvZiBlbGVtZW50cyB0aGF0IGFyZSBib3VuZCAodmlhIG5nLWJpbmQgb3Ige3t9fSkNCiAgICAgKiB0byBleHByZXNzaW9ucyBtYXRjaGluZyB0aGUgaW5wdXQuDQogICAgICoNCiAgICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgcm9vdCB0byBzZWFyY2ggZnJvbS4NCiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZXhwcmVzc2lvbiBUaGUgYmluZGluZyBleHByZXNzaW9uIHRvIG1hdGNoLg0KICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0X2V4YWN0TWF0Y2ggSWYgdHJ1ZSwgb25seSByZXR1cm5zIGV4YWN0IG1hdGNoZXMNCiAgICAgKiAgICAgZm9yIHRoZSBleHByZXNzaW9uLiBGaWx0ZXJzIGFuZCB3aGl0ZXNwYWNlIGFyZSBpZ25vcmVkLg0KICAgICAqLw0KICAgIHRlc3RhYmlsaXR5LmZpbmRCaW5kaW5ncyA9IGZ1bmN0aW9uKGVsZW1lbnQsIGV4cHJlc3Npb24sIG9wdF9leGFjdE1hdGNoKSB7DQogICAgICB2YXIgYmluZGluZ3MgPSBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ25nLWJpbmRpbmcnKTsNCiAgICAgIHZhciBtYXRjaGVzID0gW107DQogICAgICBmb3JFYWNoKGJpbmRpbmdzLCBmdW5jdGlvbihiaW5kaW5nKSB7DQogICAgICAgIHZhciBkYXRhQmluZGluZyA9IGFuZ3VsYXIuZWxlbWVudChiaW5kaW5nKS5kYXRhKCckYmluZGluZycpOw0KICAgICAgICBpZiAoZGF0YUJpbmRpbmcpIHsNCiAgICAgICAgICBmb3JFYWNoKGRhdGFCaW5kaW5nLCBmdW5jdGlvbihiaW5kaW5nTmFtZSkgew0KICAgICAgICAgICAgaWYgKG9wdF9leGFjdE1hdGNoKSB7DQogICAgICAgICAgICAgIHZhciBtYXRjaGVyID0gbmV3IFJlZ0V4cCgnKF58XFxzKScgKyBlc2NhcGVGb3JSZWdleHAoZXhwcmVzc2lvbikgKyAnKFxcc3xcXHx8JCknKTsNCiAgICAgICAgICAgICAgaWYgKG1hdGNoZXIudGVzdChiaW5kaW5nTmFtZSkpIHsNCiAgICAgICAgICAgICAgICBtYXRjaGVzLnB1c2goYmluZGluZyk7DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgIGlmIChiaW5kaW5nTmFtZS5pbmRleE9mKGV4cHJlc3Npb24pICE9IC0xKSB7DQogICAgICAgICAgICAgICAgbWF0Y2hlcy5wdXNoKGJpbmRpbmcpOw0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgfSk7DQogICAgICAgIH0NCiAgICAgIH0pOw0KICAgICAgcmV0dXJuIG1hdGNoZXM7DQogICAgfTsNCg0KICAgIC8qKg0KICAgICAqIEBuYW1lICQkdGVzdGFiaWxpdHkjZmluZE1vZGVscw0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogUmV0dXJucyBhbiBhcnJheSBvZiBlbGVtZW50cyB0aGF0IGFyZSB0d28td2F5IGZvdW5kIHZpYSBuZy1tb2RlbCB0bw0KICAgICAqIGV4cHJlc3Npb25zIG1hdGNoaW5nIHRoZSBpbnB1dC4NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCByb290IHRvIHNlYXJjaCBmcm9tLg0KICAgICAqIEBwYXJhbSB7c3RyaW5nfSBleHByZXNzaW9uIFRoZSBtb2RlbCBleHByZXNzaW9uIHRvIG1hdGNoLg0KICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0X2V4YWN0TWF0Y2ggSWYgdHJ1ZSwgb25seSByZXR1cm5zIGV4YWN0IG1hdGNoZXMNCiAgICAgKiAgICAgZm9yIHRoZSBleHByZXNzaW9uLg0KICAgICAqLw0KICAgIHRlc3RhYmlsaXR5LmZpbmRNb2RlbHMgPSBmdW5jdGlvbihlbGVtZW50LCBleHByZXNzaW9uLCBvcHRfZXhhY3RNYXRjaCkgew0KICAgICAgdmFyIHByZWZpeGVzID0gWyduZy0nLCAnZGF0YS1uZy0nLCAnbmdcXDonXTsNCiAgICAgIGZvciAodmFyIHAgPSAwOyBwIDwgcHJlZml4ZXMubGVuZ3RoOyArK3ApIHsNCiAgICAgICAgdmFyIGF0dHJpYnV0ZUVxdWFscyA9IG9wdF9leGFjdE1hdGNoID8gJz0nIDogJyo9JzsNCiAgICAgICAgdmFyIHNlbGVjdG9yID0gJ1snICsgcHJlZml4ZXNbcF0gKyAnbW9kZWwnICsgYXR0cmlidXRlRXF1YWxzICsgJyInICsgZXhwcmVzc2lvbiArICciXSc7DQogICAgICAgIHZhciBlbGVtZW50cyA9IGVsZW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7DQogICAgICAgIGlmIChlbGVtZW50cy5sZW5ndGgpIHsNCiAgICAgICAgICByZXR1cm4gZWxlbWVudHM7DQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9Ow0KDQogICAgLyoqDQogICAgICogQG5hbWUgJCR0ZXN0YWJpbGl0eSNnZXRMb2NhdGlvbg0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogU2hvcnRjdXQgZm9yIGdldHRpbmcgdGhlIGxvY2F0aW9uIGluIGEgYnJvd3NlciBhZ25vc3RpYyB3YXkuIFJldHVybnMNCiAgICAgKiAgICAgdGhlIHBhdGgsIHNlYXJjaCwgYW5kIGhhc2guIChlLmcuIC9wYXRoP2E9YiNoYXNoKQ0KICAgICAqLw0KICAgIHRlc3RhYmlsaXR5LmdldExvY2F0aW9uID0gZnVuY3Rpb24oKSB7DQogICAgICByZXR1cm4gJGxvY2F0aW9uLnVybCgpOw0KICAgIH07DQoNCiAgICAvKioNCiAgICAgKiBAbmFtZSAkJHRlc3RhYmlsaXR5I3NldExvY2F0aW9uDQogICAgICoNCiAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgKiBTaG9ydGN1dCBmb3IgbmF2aWdhdGluZyB0byBhIGxvY2F0aW9uIHdpdGhvdXQgZG9pbmcgYSBmdWxsIHBhZ2UgcmVsb2FkLg0KICAgICAqDQogICAgICogQHBhcmFtIHtzdHJpbmd9IHVybCBUaGUgbG9jYXRpb24gdXJsIChwYXRoLCBzZWFyY2ggYW5kIGhhc2gsDQogICAgICogICAgIGUuZy4gL3BhdGg/YT1iI2hhc2gpIHRvIGdvIHRvLg0KICAgICAqLw0KICAgIHRlc3RhYmlsaXR5LnNldExvY2F0aW9uID0gZnVuY3Rpb24odXJsKSB7DQogICAgICBpZiAodXJsICE9PSAkbG9jYXRpb24udXJsKCkpIHsNCiAgICAgICAgJGxvY2F0aW9uLnVybCh1cmwpOw0KICAgICAgICAkcm9vdFNjb3BlLiRkaWdlc3QoKTsNCiAgICAgIH0NCiAgICB9Ow0KDQogICAgLyoqDQogICAgICogQG5hbWUgJCR0ZXN0YWJpbGl0eSN3aGVuU3RhYmxlDQogICAgICoNCiAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgKiBDYWxscyB0aGUgY2FsbGJhY2sgd2hlbiAkdGltZW91dCBhbmQgJGh0dHAgcmVxdWVzdHMgYXJlIGNvbXBsZXRlZC4NCiAgICAgKg0KICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrDQogICAgICovDQogICAgdGVzdGFiaWxpdHkud2hlblN0YWJsZSA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7DQogICAgICAkYnJvd3Nlci5ub3RpZnlXaGVuTm9PdXRzdGFuZGluZ1JlcXVlc3RzKGNhbGxiYWNrKTsNCiAgICB9Ow0KDQogICAgcmV0dXJuIHRlc3RhYmlsaXR5Ow0KICB9XTsNCn0NCg0KZnVuY3Rpb24gJFRpbWVvdXRQcm92aWRlcigpIHsNCiAgdGhpcy4kZ2V0ID0gWyckcm9vdFNjb3BlJywgJyRicm93c2VyJywgJyRxJywgJyQkcScsICckZXhjZXB0aW9uSGFuZGxlcicsDQogICAgICAgZnVuY3Rpb24oJHJvb3RTY29wZSwgICAkYnJvd3NlciwgICAkcSwgICAkJHEsICAgJGV4Y2VwdGlvbkhhbmRsZXIpIHsNCiAgICB2YXIgZGVmZXJyZWRzID0ge307DQoNCg0KICAgICAvKioNCiAgICAgICogQG5nZG9jIHNlcnZpY2UNCiAgICAgICogQG5hbWUgJHRpbWVvdXQNCiAgICAgICoNCiAgICAgICogQGRlc2NyaXB0aW9uDQogICAgICAqIEFuZ3VsYXIncyB3cmFwcGVyIGZvciBgd2luZG93LnNldFRpbWVvdXRgLiBUaGUgYGZuYCBmdW5jdGlvbiBpcyB3cmFwcGVkIGludG8gYSB0cnkvY2F0Y2gNCiAgICAgICogYmxvY2sgYW5kIGRlbGVnYXRlcyBhbnkgZXhjZXB0aW9ucyB0bw0KICAgICAgKiB7QGxpbmsgbmcuJGV4Y2VwdGlvbkhhbmRsZXIgJGV4Y2VwdGlvbkhhbmRsZXJ9IHNlcnZpY2UuDQogICAgICAqDQogICAgICAqIFRoZSByZXR1cm4gdmFsdWUgb2YgcmVnaXN0ZXJpbmcgYSB0aW1lb3V0IGZ1bmN0aW9uIGlzIGEgcHJvbWlzZSwgd2hpY2ggd2lsbCBiZSByZXNvbHZlZCB3aGVuDQogICAgICAqIHRoZSB0aW1lb3V0IGlzIHJlYWNoZWQgYW5kIHRoZSB0aW1lb3V0IGZ1bmN0aW9uIGlzIGV4ZWN1dGVkLg0KICAgICAgKg0KICAgICAgKiBUbyBjYW5jZWwgYSB0aW1lb3V0IHJlcXVlc3QsIGNhbGwgYCR0aW1lb3V0LmNhbmNlbChwcm9taXNlKWAuDQogICAgICAqDQogICAgICAqIEluIHRlc3RzIHlvdSBjYW4gdXNlIHtAbGluayBuZ01vY2suJHRpbWVvdXQgYCR0aW1lb3V0LmZsdXNoKClgfSB0bw0KICAgICAgKiBzeW5jaHJvbm91c2x5IGZsdXNoIHRoZSBxdWV1ZSBvZiBkZWZlcnJlZCBmdW5jdGlvbnMuDQogICAgICAqDQogICAgICAqIEBwYXJhbSB7ZnVuY3Rpb24oKX0gZm4gQSBmdW5jdGlvbiwgd2hvc2UgZXhlY3V0aW9uIHNob3VsZCBiZSBkZWxheWVkLg0KICAgICAgKiBAcGFyYW0ge251bWJlcj19IFtkZWxheT0wXSBEZWxheSBpbiBtaWxsaXNlY29uZHMuDQogICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IFtpbnZva2VBcHBseT10cnVlXSBJZiBzZXQgdG8gYGZhbHNlYCBza2lwcyBtb2RlbCBkaXJ0eSBjaGVja2luZywgb3RoZXJ3aXNlDQogICAgICAqICAgd2lsbCBpbnZva2UgYGZuYCB3aXRoaW4gdGhlIHtAbGluayBuZy4kcm9vdFNjb3BlLlNjb3BlIyRhcHBseSAkYXBwbHl9IGJsb2NrLg0KICAgICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gUHJvbWlzZSB0aGF0IHdpbGwgYmUgcmVzb2x2ZWQgd2hlbiB0aGUgdGltZW91dCBpcyByZWFjaGVkLiBUaGUgdmFsdWUgdGhpcw0KICAgICAgKiAgIHByb21pc2Ugd2lsbCBiZSByZXNvbHZlZCB3aXRoIGlzIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIGBmbmAgZnVuY3Rpb24uDQogICAgICAqDQogICAgICAqLw0KICAgIGZ1bmN0aW9uIHRpbWVvdXQoZm4sIGRlbGF5LCBpbnZva2VBcHBseSkgew0KICAgICAgdmFyIHNraXBBcHBseSA9IChpc0RlZmluZWQoaW52b2tlQXBwbHkpICYmICFpbnZva2VBcHBseSksDQogICAgICAgICAgZGVmZXJyZWQgPSAoc2tpcEFwcGx5ID8gJCRxIDogJHEpLmRlZmVyKCksDQogICAgICAgICAgcHJvbWlzZSA9IGRlZmVycmVkLnByb21pc2UsDQogICAgICAgICAgdGltZW91dElkOw0KDQogICAgICB0aW1lb3V0SWQgPSAkYnJvd3Nlci5kZWZlcihmdW5jdGlvbigpIHsNCiAgICAgICAgdHJ5IHsNCiAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKGZuKCkpOw0KICAgICAgICB9IGNhdGNoIChlKSB7DQogICAgICAgICAgZGVmZXJyZWQucmVqZWN0KGUpOw0KICAgICAgICAgICRleGNlcHRpb25IYW5kbGVyKGUpOw0KICAgICAgICB9DQogICAgICAgIGZpbmFsbHkgew0KICAgICAgICAgIGRlbGV0ZSBkZWZlcnJlZHNbcHJvbWlzZS4kJHRpbWVvdXRJZF07DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoIXNraXBBcHBseSkgJHJvb3RTY29wZS4kYXBwbHkoKTsNCiAgICAgIH0sIGRlbGF5KTsNCg0KICAgICAgcHJvbWlzZS4kJHRpbWVvdXRJZCA9IHRpbWVvdXRJZDsNCiAgICAgIGRlZmVycmVkc1t0aW1lb3V0SWRdID0gZGVmZXJyZWQ7DQoNCiAgICAgIHJldHVybiBwcm9taXNlOw0KICAgIH0NCg0KDQogICAgIC8qKg0KICAgICAgKiBAbmdkb2MgbWV0aG9kDQogICAgICAqIEBuYW1lICR0aW1lb3V0I2NhbmNlbA0KICAgICAgKg0KICAgICAgKiBAZGVzY3JpcHRpb24NCiAgICAgICogQ2FuY2VscyBhIHRhc2sgYXNzb2NpYXRlZCB3aXRoIHRoZSBgcHJvbWlzZWAuIEFzIGEgcmVzdWx0IG9mIHRoaXMsIHRoZSBwcm9taXNlIHdpbGwgYmUNCiAgICAgICogcmVzb2x2ZWQgd2l0aCBhIHJlamVjdGlvbi4NCiAgICAgICoNCiAgICAgICogQHBhcmFtIHtQcm9taXNlPX0gcHJvbWlzZSBQcm9taXNlIHJldHVybmVkIGJ5IHRoZSBgJHRpbWVvdXRgIGZ1bmN0aW9uLg0KICAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHRhc2sgaGFzbid0IGV4ZWN1dGVkIHlldCBhbmQgd2FzIHN1Y2Nlc3NmdWxseQ0KICAgICAgKiAgIGNhbmNlbGVkLg0KICAgICAgKi8NCiAgICB0aW1lb3V0LmNhbmNlbCA9IGZ1bmN0aW9uKHByb21pc2UpIHsNCiAgICAgIGlmIChwcm9taXNlICYmIHByb21pc2UuJCR0aW1lb3V0SWQgaW4gZGVmZXJyZWRzKSB7DQogICAgICAgIGRlZmVycmVkc1twcm9taXNlLiQkdGltZW91dElkXS5yZWplY3QoJ2NhbmNlbGVkJyk7DQogICAgICAgIGRlbGV0ZSBkZWZlcnJlZHNbcHJvbWlzZS4kJHRpbWVvdXRJZF07DQogICAgICAgIHJldHVybiAkYnJvd3Nlci5kZWZlci5jYW5jZWwocHJvbWlzZS4kJHRpbWVvdXRJZCk7DQogICAgICB9DQogICAgICByZXR1cm4gZmFsc2U7DQogICAgfTsNCg0KICAgIHJldHVybiB0aW1lb3V0Ow0KICB9XTsNCn0NCg0KLy8gTk9URTogIFRoZSB1c2FnZSBvZiB3aW5kb3cgYW5kIGRvY3VtZW50IGluc3RlYWQgb2YgJHdpbmRvdyBhbmQgJGRvY3VtZW50IGhlcmUgaXMNCi8vIGRlbGliZXJhdGUuICBUaGlzIHNlcnZpY2UgZGVwZW5kcyBvbiB0aGUgc3BlY2lmaWMgYmVoYXZpb3Igb2YgYW5jaG9yIG5vZGVzIGNyZWF0ZWQgYnkgdGhlDQovLyBicm93c2VyIChyZXNvbHZpbmcgYW5kIHBhcnNpbmcgVVJMcykgdGhhdCBpcyB1bmxpa2VseSB0byBiZSBwcm92aWRlZCBieSBtb2NrIG9iamVjdHMgYW5kDQovLyBjYXVzZSB1cyB0byBicmVhayB0ZXN0cy4gIEluIGFkZGl0aW9uLCB3aGVuIHRoZSBicm93c2VyIHJlc29sdmVzIGEgVVJMIGZvciBYSFIsIGl0DQovLyBkb2Vzbid0IGtub3cgYWJvdXQgbW9ja2VkIGxvY2F0aW9ucyBhbmQgcmVzb2x2ZXMgVVJMcyB0byB0aGUgcmVhbCBkb2N1bWVudCAtIHdoaWNoIGlzDQovLyBleGFjdGx5IHRoZSBiZWhhdmlvciBuZWVkZWQgaGVyZS4gIFRoZXJlIGlzIGxpdHRsZSB2YWx1ZSBpcyBtb2NraW5nIHRoZXNlIG91dCBmb3IgdGhpcw0KLy8gc2VydmljZS4NCnZhciB1cmxQYXJzaW5nTm9kZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImEiKTsNCnZhciBvcmlnaW5VcmwgPSB1cmxSZXNvbHZlKHdpbmRvdy5sb2NhdGlvbi5ocmVmKTsNCg0KDQovKioNCiAqDQogKiBJbXBsZW1lbnRhdGlvbiBOb3RlcyBmb3Igbm9uLUlFIGJyb3dzZXJzDQogKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQogKiBBc3NpZ25pbmcgYSBVUkwgdG8gdGhlIGhyZWYgcHJvcGVydHkgb2YgYW4gYW5jaG9yIERPTSBub2RlLCBldmVuIG9uZSBhdHRhY2hlZCB0byB0aGUgRE9NLA0KICogcmVzdWx0cyBib3RoIGluIHRoZSBub3JtYWxpemluZyBhbmQgcGFyc2luZyBvZiB0aGUgVVJMLiAgTm9ybWFsaXppbmcgbWVhbnMgdGhhdCBhIHJlbGF0aXZlDQogKiBVUkwgd2lsbCBiZSByZXNvbHZlZCBpbnRvIGFuIGFic29sdXRlIFVSTCBpbiB0aGUgY29udGV4dCBvZiB0aGUgYXBwbGljYXRpb24gZG9jdW1lbnQuDQogKiBQYXJzaW5nIG1lYW5zIHRoYXQgdGhlIGFuY2hvciBub2RlJ3MgaG9zdCwgaG9zdG5hbWUsIHByb3RvY29sLCBwb3J0LCBwYXRobmFtZSBhbmQgcmVsYXRlZA0KICogcHJvcGVydGllcyBhcmUgYWxsIHBvcHVsYXRlZCB0byByZWZsZWN0IHRoZSBub3JtYWxpemVkIFVSTC4gIFRoaXMgYXBwcm9hY2ggaGFzIHdpZGUNCiAqIGNvbXBhdGliaWxpdHkgLSBTYWZhcmkgMSssIE1vemlsbGEgMSssIE9wZXJhIDcrLGUgZXRjLiAgU2VlDQogKiBodHRwOi8vd3d3LmFwdGFuYS5jb20vcmVmZXJlbmNlL2h0bWwvYXBpL0hUTUxBbmNob3JFbGVtZW50Lmh0bWwNCiAqDQogKiBJbXBsZW1lbnRhdGlvbiBOb3RlcyBmb3IgSUUNCiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KICogSUUgPj0gOCBhbmQgPD0gMTAgbm9ybWFsaXplcyB0aGUgVVJMIHdoZW4gYXNzaWduZWQgdG8gdGhlIGFuY2hvciBub2RlIHNpbWlsYXIgdG8gdGhlIG90aGVyDQogKiBicm93c2Vycy4gIEhvd2V2ZXIsIHRoZSBwYXJzZWQgY29tcG9uZW50cyB3aWxsIG5vdCBiZSBzZXQgaWYgdGhlIFVSTCBhc3NpZ25lZCBkaWQgbm90IHNwZWNpZnkNCiAqIHRoZW0uICAoZS5nLiBpZiB5b3UgYXNzaWduIGEuaHJlZiA9ICJmb28iLCB0aGVuIGEucHJvdG9jb2wsIGEuaG9zdCwgZXRjLiB3aWxsIGJlIGVtcHR5LikgIFdlDQogKiB3b3JrIGFyb3VuZCB0aGF0IGJ5IHBlcmZvcm1pbmcgdGhlIHBhcnNpbmcgaW4gYSAybmQgc3RlcCBieSB0YWtpbmcgYSBwcmV2aW91c2x5IG5vcm1hbGl6ZWQNCiAqIFVSTCAoZS5nLiBieSBhc3NpZ25pbmcgdG8gYS5ocmVmKSBhbmQgYXNzaWduaW5nIGl0IGEuaHJlZiBhZ2Fpbi4gIFRoaXMgY29ycmVjdGx5IHBvcHVsYXRlcyB0aGUNCiAqIHByb3BlcnRpZXMgc3VjaCBhcyBwcm90b2NvbCwgaG9zdG5hbWUsIHBvcnQsIGV0Yy4NCiAqDQogKiBJRTcgZG9lcyBub3Qgbm9ybWFsaXplIHRoZSBVUkwgd2hlbiBhc3NpZ25lZCB0byBhbiBhbmNob3Igbm9kZS4gIChBcHBhcmVudGx5LCBpdCBkb2VzLCBpZiBvbmUNCiAqIHVzZXMgdGhlIGlubmVyIEhUTUwgYXBwcm9hY2ggdG8gYXNzaWduIHRoZSBVUkwgYXMgcGFydCBvZiBhbiBIVE1MIHNuaXBwZXQgLQ0KICogaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNDcyNzI5KSAgSG93ZXZlciwgc2V0dGluZyBpbWdbc3JjXSBkb2VzIG5vcm1hbGl6ZSB0aGUgVVJMLg0KICogVW5mb3J0dW5hdGVseSwgc2V0dGluZyBpbWdbc3JjXSB0byBzb21ldGhpbmcgbGlrZSAiamF2YXNjcmlwdDpmb28iIG9uIElFIHRocm93cyBhbiBleGNlcHRpb24uDQogKiBTaW5jZSB0aGUgcHJpbWFyeSB1c2FnZSBmb3Igbm9ybWFsaXppbmcgVVJMcyBpcyB0byBzYW5pdGl6ZSBzdWNoIFVSTHMsIHdlIGNhbid0IHVzZSB0aGF0DQogKiBtZXRob2QgYW5kIElFIDwgOCBpcyB1bnN1cHBvcnRlZC4NCiAqDQogKiBSZWZlcmVuY2VzOg0KICogICBodHRwOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IVE1MQW5jaG9yRWxlbWVudA0KICogICBodHRwOi8vd3d3LmFwdGFuYS5jb20vcmVmZXJlbmNlL2h0bWwvYXBpL0hUTUxBbmNob3JFbGVtZW50Lmh0bWwNCiAqICAgaHR0cDovL3VybC5zcGVjLndoYXR3Zy5vcmcvI3VybHV0aWxzDQogKiAgIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIuanMvcHVsbC8yOTAyDQogKiAgIGh0dHA6Ly9qYW1lcy5wYWRvbHNleS5jb20vamF2YXNjcmlwdC9wYXJzaW5nLXVybHMtd2l0aC10aGUtZG9tLw0KICoNCiAqIEBraW5kIGZ1bmN0aW9uDQogKiBAcGFyYW0ge3N0cmluZ30gdXJsIFRoZSBVUkwgdG8gYmUgcGFyc2VkLg0KICogQGRlc2NyaXB0aW9uIE5vcm1hbGl6ZXMgYW5kIHBhcnNlcyBhIFVSTC4NCiAqIEByZXR1cm5zIHtvYmplY3R9IFJldHVybnMgdGhlIG5vcm1hbGl6ZWQgVVJMIGFzIGEgZGljdGlvbmFyeS4NCiAqDQogKiAgIHwgbWVtYmVyIG5hbWUgICB8IERlc2NyaXB0aW9uICAgIHwNCiAqICAgfC0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tfA0KICogICB8IGhyZWYgICAgICAgICAgfCBBIG5vcm1hbGl6ZWQgdmVyc2lvbiBvZiB0aGUgcHJvdmlkZWQgVVJMIGlmIGl0IHdhcyBub3QgYW4gYWJzb2x1dGUgVVJMIHwNCiAqICAgfCBwcm90b2NvbCAgICAgIHwgVGhlIHByb3RvY29sIGluY2x1ZGluZyB0aGUgdHJhaWxpbmcgY29sb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQogKiAgIHwgaG9zdCAgICAgICAgICB8IFRoZSBob3N0IGFuZCBwb3J0IChpZiB0aGUgcG9ydCBpcyBub24tZGVmYXVsdCkgb2YgdGhlIG5vcm1hbGl6ZWRVcmwgICAgfA0KICogICB8IHNlYXJjaCAgICAgICAgfCBUaGUgc2VhcmNoIHBhcmFtcywgbWludXMgdGhlIHF1ZXN0aW9uIG1hcmsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCiAqICAgfCBoYXNoICAgICAgICAgIHwgVGhlIGhhc2ggc3RyaW5nLCBtaW51cyB0aGUgaGFzaCBzeW1ib2wNCiAqICAgfCBob3N0bmFtZSAgICAgIHwgVGhlIGhvc3RuYW1lDQogKiAgIHwgcG9ydCAgICAgICAgICB8IFRoZSBwb3J0LCB3aXRob3V0ICI6Ig0KICogICB8IHBhdGhuYW1lICAgICAgfCBUaGUgcGF0aG5hbWUsIGJlZ2lubmluZyB3aXRoICIvIg0KICoNCiAqLw0KZnVuY3Rpb24gdXJsUmVzb2x2ZSh1cmwpIHsNCiAgdmFyIGhyZWYgPSB1cmw7DQoNCiAgaWYgKG1zaWUpIHsNCiAgICAvLyBOb3JtYWxpemUgYmVmb3JlIHBhcnNlLiAgUmVmZXIgSW1wbGVtZW50YXRpb24gTm90ZXMgb24gd2h5IHRoaXMgaXMNCiAgICAvLyBkb25lIGluIHR3byBzdGVwcyBvbiBJRS4NCiAgICB1cmxQYXJzaW5nTm9kZS5zZXRBdHRyaWJ1dGUoImhyZWYiLCBocmVmKTsNCiAgICBocmVmID0gdXJsUGFyc2luZ05vZGUuaHJlZjsNCiAgfQ0KDQogIHVybFBhcnNpbmdOb2RlLnNldEF0dHJpYnV0ZSgnaHJlZicsIGhyZWYpOw0KDQogIC8vIHVybFBhcnNpbmdOb2RlIHByb3ZpZGVzIHRoZSBVcmxVdGlscyBpbnRlcmZhY2UgLSBodHRwOi8vdXJsLnNwZWMud2hhdHdnLm9yZy8jdXJsdXRpbHMNCiAgcmV0dXJuIHsNCiAgICBocmVmOiB1cmxQYXJzaW5nTm9kZS5ocmVmLA0KICAgIHByb3RvY29sOiB1cmxQYXJzaW5nTm9kZS5wcm90b2NvbCA/IHVybFBhcnNpbmdOb2RlLnByb3RvY29sLnJlcGxhY2UoLzokLywgJycpIDogJycsDQogICAgaG9zdDogdXJsUGFyc2luZ05vZGUuaG9zdCwNCiAgICBzZWFyY2g6IHVybFBhcnNpbmdOb2RlLnNlYXJjaCA/IHVybFBhcnNpbmdOb2RlLnNlYXJjaC5yZXBsYWNlKC9eXD8vLCAnJykgOiAnJywNCiAgICBoYXNoOiB1cmxQYXJzaW5nTm9kZS5oYXNoID8gdXJsUGFyc2luZ05vZGUuaGFzaC5yZXBsYWNlKC9eIy8sICcnKSA6ICcnLA0KICAgIGhvc3RuYW1lOiB1cmxQYXJzaW5nTm9kZS5ob3N0bmFtZSwNCiAgICBwb3J0OiB1cmxQYXJzaW5nTm9kZS5wb3J0LA0KICAgIHBhdGhuYW1lOiAodXJsUGFyc2luZ05vZGUucGF0aG5hbWUuY2hhckF0KDApID09PSAnLycpDQogICAgICA/IHVybFBhcnNpbmdOb2RlLnBhdGhuYW1lDQogICAgICA6ICcvJyArIHVybFBhcnNpbmdOb2RlLnBhdGhuYW1lDQogIH07DQp9DQoNCi8qKg0KICogUGFyc2UgYSByZXF1ZXN0IFVSTCBhbmQgZGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBpcyBhIHNhbWUtb3JpZ2luIHJlcXVlc3QgYXMgdGhlIGFwcGxpY2F0aW9uIGRvY3VtZW50Lg0KICoNCiAqIEBwYXJhbSB7c3RyaW5nfG9iamVjdH0gcmVxdWVzdFVybCBUaGUgdXJsIG9mIHRoZSByZXF1ZXN0IGFzIGEgc3RyaW5nIHRoYXQgd2lsbCBiZSByZXNvbHZlZA0KICogb3IgYSBwYXJzZWQgVVJMIG9iamVjdC4NCiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSByZXF1ZXN0IGlzIGZvciB0aGUgc2FtZSBvcmlnaW4gYXMgdGhlIGFwcGxpY2F0aW9uIGRvY3VtZW50Lg0KICovDQpmdW5jdGlvbiB1cmxJc1NhbWVPcmlnaW4ocmVxdWVzdFVybCkgew0KICB2YXIgcGFyc2VkID0gKGlzU3RyaW5nKHJlcXVlc3RVcmwpKSA/IHVybFJlc29sdmUocmVxdWVzdFVybCkgOiByZXF1ZXN0VXJsOw0KICByZXR1cm4gKHBhcnNlZC5wcm90b2NvbCA9PT0gb3JpZ2luVXJsLnByb3RvY29sICYmDQogICAgICAgICAgcGFyc2VkLmhvc3QgPT09IG9yaWdpblVybC5ob3N0KTsNCn0NCg0KLyoqDQogKiBAbmdkb2Mgc2VydmljZQ0KICogQG5hbWUgJHdpbmRvdw0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogQSByZWZlcmVuY2UgdG8gdGhlIGJyb3dzZXIncyBgd2luZG93YCBvYmplY3QuIFdoaWxlIGB3aW5kb3dgDQogKiBpcyBnbG9iYWxseSBhdmFpbGFibGUgaW4gSmF2YVNjcmlwdCwgaXQgY2F1c2VzIHRlc3RhYmlsaXR5IHByb2JsZW1zLCBiZWNhdXNlDQogKiBpdCBpcyBhIGdsb2JhbCB2YXJpYWJsZS4gSW4gYW5ndWxhciB3ZSBhbHdheXMgcmVmZXIgdG8gaXQgdGhyb3VnaCB0aGUNCiAqIGAkd2luZG93YCBzZXJ2aWNlLCBzbyBpdCBtYXkgYmUgb3ZlcnJpZGRlbiwgcmVtb3ZlZCBvciBtb2NrZWQgZm9yIHRlc3RpbmcuDQogKg0KICogRXhwcmVzc2lvbnMsIGxpa2UgdGhlIG9uZSBkZWZpbmVkIGZvciB0aGUgYG5nQ2xpY2tgIGRpcmVjdGl2ZSBpbiB0aGUgZXhhbXBsZQ0KICogYmVsb3csIGFyZSBldmFsdWF0ZWQgd2l0aCByZXNwZWN0IHRvIHRoZSBjdXJyZW50IHNjb3BlLiAgVGhlcmVmb3JlLCB0aGVyZSBpcw0KICogbm8gcmlzayBvZiBpbmFkdmVydGVudGx5IGNvZGluZyBpbiBhIGRlcGVuZGVuY3kgb24gYSBnbG9iYWwgdmFsdWUgaW4gc3VjaCBhbg0KICogZXhwcmVzc2lvbi4NCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGUgbW9kdWxlPSJ3aW5kb3dFeGFtcGxlIj4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPHNjcmlwdD4NCiAgICAgICAgIGFuZ3VsYXIubW9kdWxlKCd3aW5kb3dFeGFtcGxlJywgW10pDQogICAgICAgICAgIC5jb250cm9sbGVyKCdFeGFtcGxlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgJyR3aW5kb3cnLCBmdW5jdGlvbigkc2NvcGUsICR3aW5kb3cpIHsNCiAgICAgICAgICAgICAkc2NvcGUuZ3JlZXRpbmcgPSAnSGVsbG8sIFdvcmxkISc7DQogICAgICAgICAgICAgJHNjb3BlLmRvR3JlZXRpbmcgPSBmdW5jdGlvbihncmVldGluZykgew0KICAgICAgICAgICAgICAgJHdpbmRvdy5hbGVydChncmVldGluZyk7DQogICAgICAgICAgICAgfTsNCiAgICAgICAgICAgfV0pOw0KICAgICAgIDwvc2NyaXB0Pg0KICAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICAgICAgPGlucHV0IHR5cGU9InRleHQiIG5nLW1vZGVsPSJncmVldGluZyIgLz4NCiAgICAgICAgIDxidXR0b24gbmctY2xpY2s9ImRvR3JlZXRpbmcoZ3JlZXRpbmcpIj5BTEVSVDwvYnV0dG9uPg0KICAgICAgIDwvZGl2Pg0KICAgICA8L2ZpbGU+DQogICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgaXQoJ3Nob3VsZCBkaXNwbGF5IHRoZSBncmVldGluZyBpbiB0aGUgaW5wdXQgYm94JywgZnVuY3Rpb24oKSB7DQogICAgICAgZWxlbWVudChieS5tb2RlbCgnZ3JlZXRpbmcnKSkuc2VuZEtleXMoJ0hlbGxvLCBFMkUgVGVzdHMnKTsNCiAgICAgICAvLyBJZiB3ZSBjbGljayB0aGUgYnV0dG9uIGl0IHdpbGwgYmxvY2sgdGhlIHRlc3QgcnVubmVyDQogICAgICAgLy8gZWxlbWVudCgnOmJ1dHRvbicpLmNsaWNrKCk7DQogICAgICB9KTsNCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICovDQpmdW5jdGlvbiAkV2luZG93UHJvdmlkZXIoKSB7DQogIHRoaXMuJGdldCA9IHZhbHVlRm4od2luZG93KTsNCn0NCg0KLyogZ2xvYmFsIGN1cnJlbmN5RmlsdGVyOiB0cnVlLA0KIGRhdGVGaWx0ZXI6IHRydWUsDQogZmlsdGVyRmlsdGVyOiB0cnVlLA0KIGpzb25GaWx0ZXI6IHRydWUsDQogbGltaXRUb0ZpbHRlcjogdHJ1ZSwNCiBsb3dlcmNhc2VGaWx0ZXI6IHRydWUsDQogbnVtYmVyRmlsdGVyOiB0cnVlLA0KIG9yZGVyQnlGaWx0ZXI6IHRydWUsDQogdXBwZXJjYXNlRmlsdGVyOiB0cnVlLA0KICovDQoNCi8qKg0KICogQG5nZG9jIHByb3ZpZGVyDQogKiBAbmFtZSAkZmlsdGVyUHJvdmlkZXINCiAqIEBkZXNjcmlwdGlvbg0KICoNCiAqIEZpbHRlcnMgYXJlIGp1c3QgZnVuY3Rpb25zIHdoaWNoIHRyYW5zZm9ybSBpbnB1dCB0byBhbiBvdXRwdXQuIEhvd2V2ZXIgZmlsdGVycyBuZWVkIHRvIGJlDQogKiBEZXBlbmRlbmN5IEluamVjdGVkLiBUbyBhY2hpZXZlIHRoaXMgYSBmaWx0ZXIgZGVmaW5pdGlvbiBjb25zaXN0cyBvZiBhIGZhY3RvcnkgZnVuY3Rpb24gd2hpY2ggaXMNCiAqIGFubm90YXRlZCB3aXRoIGRlcGVuZGVuY2llcyBhbmQgaXMgcmVzcG9uc2libGUgZm9yIGNyZWF0aW5nIGEgZmlsdGVyIGZ1bmN0aW9uLg0KICoNCiAqIGBgYGpzDQogKiAgIC8vIEZpbHRlciByZWdpc3RyYXRpb24NCiAqICAgZnVuY3Rpb24gTXlNb2R1bGUoJHByb3ZpZGUsICRmaWx0ZXJQcm92aWRlcikgew0KICogICAgIC8vIGNyZWF0ZSBhIHNlcnZpY2UgdG8gZGVtb25zdHJhdGUgaW5qZWN0aW9uIChub3QgYWx3YXlzIG5lZWRlZCkNCiAqICAgICAkcHJvdmlkZS52YWx1ZSgnZ3JlZXQnLCBmdW5jdGlvbihuYW1lKXsNCiAqICAgICAgIHJldHVybiAnSGVsbG8gJyArIG5hbWUgKyAnISc7DQogKiAgICAgfSk7DQogKg0KICogICAgIC8vIHJlZ2lzdGVyIGEgZmlsdGVyIGZhY3Rvcnkgd2hpY2ggdXNlcyB0aGUNCiAqICAgICAvLyBncmVldCBzZXJ2aWNlIHRvIGRlbW9uc3RyYXRlIERJLg0KICogICAgICRmaWx0ZXJQcm92aWRlci5yZWdpc3RlcignZ3JlZXQnLCBmdW5jdGlvbihncmVldCl7DQogKiAgICAgICAvLyByZXR1cm4gdGhlIGZpbHRlciBmdW5jdGlvbiB3aGljaCB1c2VzIHRoZSBncmVldCBzZXJ2aWNlDQogKiAgICAgICAvLyB0byBnZW5lcmF0ZSBzYWx1dGF0aW9uDQogKiAgICAgICByZXR1cm4gZnVuY3Rpb24odGV4dCkgew0KICogICAgICAgICAvLyBmaWx0ZXJzIG5lZWQgdG8gYmUgZm9yZ2l2aW5nIHNvIGNoZWNrIGlucHV0IHZhbGlkaXR5DQogKiAgICAgICAgIHJldHVybiB0ZXh0ICYmIGdyZWV0KHRleHQpIHx8IHRleHQ7DQogKiAgICAgICB9Ow0KICogICAgIH0pOw0KICogICB9DQogKiBgYGANCiAqDQogKiBUaGUgZmlsdGVyIGZ1bmN0aW9uIGlzIHJlZ2lzdGVyZWQgd2l0aCB0aGUgYCRpbmplY3RvcmAgdW5kZXIgdGhlIGZpbHRlciBuYW1lIHN1ZmZpeCB3aXRoDQogKiBgRmlsdGVyYC4NCiAqDQogKiBgYGBqcw0KICogICBpdCgnc2hvdWxkIGJlIHRoZSBzYW1lIGluc3RhbmNlJywgaW5qZWN0KA0KICogICAgIGZ1bmN0aW9uKCRmaWx0ZXJQcm92aWRlcikgew0KICogICAgICAgJGZpbHRlclByb3ZpZGVyLnJlZ2lzdGVyKCdyZXZlcnNlJywgZnVuY3Rpb24oKXsNCiAqICAgICAgICAgcmV0dXJuIC4uLjsNCiAqICAgICAgIH0pOw0KICogICAgIH0sDQogKiAgICAgZnVuY3Rpb24oJGZpbHRlciwgcmV2ZXJzZUZpbHRlcikgew0KICogICAgICAgZXhwZWN0KCRmaWx0ZXIoJ3JldmVyc2UnKSkudG9CZShyZXZlcnNlRmlsdGVyKTsNCiAqICAgICB9KTsNCiAqIGBgYA0KICoNCiAqDQogKiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBob3cgYW5ndWxhciBmaWx0ZXJzIHdvcmssIGFuZCBob3cgdG8gY3JlYXRlIHlvdXIgb3duIGZpbHRlcnMsIHNlZQ0KICoge0BsaW5rIGd1aWRlL2ZpbHRlciBGaWx0ZXJzfSBpbiB0aGUgQW5ndWxhciBEZXZlbG9wZXIgR3VpZGUuDQogKi8NCg0KLyoqDQogKiBAbmdkb2Mgc2VydmljZQ0KICogQG5hbWUgJGZpbHRlcg0KICogQGtpbmQgZnVuY3Rpb24NCiAqIEBkZXNjcmlwdGlvbg0KICogRmlsdGVycyBhcmUgdXNlZCBmb3IgZm9ybWF0dGluZyBkYXRhIGRpc3BsYXllZCB0byB0aGUgdXNlci4NCiAqDQogKiBUaGUgZ2VuZXJhbCBzeW50YXggaW4gdGVtcGxhdGVzIGlzIGFzIGZvbGxvd3M6DQogKg0KICogICAgICAgICB7eyBleHByZXNzaW9uIFt8IGZpbHRlcl9uYW1lWzpwYXJhbWV0ZXJfdmFsdWVdIC4uLiBdIH19DQogKg0KICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgZmlsdGVyIGZ1bmN0aW9uIHRvIHJldHJpZXZlDQogKiBAcmV0dXJuIHtGdW5jdGlvbn0gdGhlIGZpbHRlciBmdW5jdGlvbg0KICogQGV4YW1wbGUNCiAgIDxleGFtcGxlIG5hbWU9IiRmaWx0ZXIiIG1vZHVsZT0iZmlsdGVyRXhhbXBsZSI+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iTWFpbkN0cmwiPg0KICAgICAgICA8aDM+e3sgb3JpZ2luYWxUZXh0IH19PC9oMz4NCiAgICAgICAgPGgzPnt7IGZpbHRlcmVkVGV4dCB9fTwvaDM+DQogICAgICAgPC9kaXY+DQogICAgIDwvZmlsZT4NCg0KICAgICA8ZmlsZSBuYW1lPSJzY3JpcHQuanMiPg0KICAgICAgYW5ndWxhci5tb2R1bGUoJ2ZpbHRlckV4YW1wbGUnLCBbXSkNCiAgICAgIC5jb250cm9sbGVyKCdNYWluQ3RybCcsIGZ1bmN0aW9uKCRzY29wZSwgJGZpbHRlcikgew0KICAgICAgICAkc2NvcGUub3JpZ2luYWxUZXh0ID0gJ2hlbGxvJzsNCiAgICAgICAgJHNjb3BlLmZpbHRlcmVkVGV4dCA9ICRmaWx0ZXIoJ3VwcGVyY2FzZScpKCRzY29wZS5vcmlnaW5hbFRleHQpOw0KICAgICAgfSk7DQogICAgIDwvZmlsZT4NCiAgIDwvZXhhbXBsZT4NCiAgKi8NCiRGaWx0ZXJQcm92aWRlci4kaW5qZWN0ID0gWyckcHJvdmlkZSddOw0KZnVuY3Rpb24gJEZpbHRlclByb3ZpZGVyKCRwcm92aWRlKSB7DQogIHZhciBzdWZmaXggPSAnRmlsdGVyJzsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSAkZmlsdGVyUHJvdmlkZXIjcmVnaXN0ZXINCiAgICogQHBhcmFtIHtzdHJpbmd8T2JqZWN0fSBuYW1lIE5hbWUgb2YgdGhlIGZpbHRlciBmdW5jdGlvbiwgb3IgYW4gb2JqZWN0IG1hcCBvZiBmaWx0ZXJzIHdoZXJlDQogICAqICAgIHRoZSBrZXlzIGFyZSB0aGUgZmlsdGVyIG5hbWVzIGFuZCB0aGUgdmFsdWVzIGFyZSB0aGUgZmlsdGVyIGZhY3Rvcmllcy4NCiAgICogQHJldHVybnMge09iamVjdH0gUmVnaXN0ZXJlZCBmaWx0ZXIgaW5zdGFuY2UsIG9yIGlmIGEgbWFwIG9mIGZpbHRlcnMgd2FzIHByb3ZpZGVkIHRoZW4gYSBtYXANCiAgICogICAgb2YgdGhlIHJlZ2lzdGVyZWQgZmlsdGVyIGluc3RhbmNlcy4NCiAgICovDQogIGZ1bmN0aW9uIHJlZ2lzdGVyKG5hbWUsIGZhY3RvcnkpIHsNCiAgICBpZiAoaXNPYmplY3QobmFtZSkpIHsNCiAgICAgIHZhciBmaWx0ZXJzID0ge307DQogICAgICBmb3JFYWNoKG5hbWUsIGZ1bmN0aW9uKGZpbHRlciwga2V5KSB7DQogICAgICAgIGZpbHRlcnNba2V5XSA9IHJlZ2lzdGVyKGtleSwgZmlsdGVyKTsNCiAgICAgIH0pOw0KICAgICAgcmV0dXJuIGZpbHRlcnM7DQogICAgfSBlbHNlIHsNCiAgICAgIHJldHVybiAkcHJvdmlkZS5mYWN0b3J5KG5hbWUgKyBzdWZmaXgsIGZhY3RvcnkpOw0KICAgIH0NCiAgfQ0KICB0aGlzLnJlZ2lzdGVyID0gcmVnaXN0ZXI7DQoNCiAgdGhpcy4kZ2V0ID0gWyckaW5qZWN0b3InLCBmdW5jdGlvbigkaW5qZWN0b3IpIHsNCiAgICByZXR1cm4gZnVuY3Rpb24obmFtZSkgew0KICAgICAgcmV0dXJuICRpbmplY3Rvci5nZXQobmFtZSArIHN1ZmZpeCk7DQogICAgfTsNCiAgfV07DQoNCiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw0KDQogIC8qIGdsb2JhbA0KICAgIGN1cnJlbmN5RmlsdGVyOiBmYWxzZSwNCiAgICBkYXRlRmlsdGVyOiBmYWxzZSwNCiAgICBmaWx0ZXJGaWx0ZXI6IGZhbHNlLA0KICAgIGpzb25GaWx0ZXI6IGZhbHNlLA0KICAgIGxpbWl0VG9GaWx0ZXI6IGZhbHNlLA0KICAgIGxvd2VyY2FzZUZpbHRlcjogZmFsc2UsDQogICAgbnVtYmVyRmlsdGVyOiBmYWxzZSwNCiAgICBvcmRlckJ5RmlsdGVyOiBmYWxzZSwNCiAgICB1cHBlcmNhc2VGaWx0ZXI6IGZhbHNlLA0KICAqLw0KDQogIHJlZ2lzdGVyKCdjdXJyZW5jeScsIGN1cnJlbmN5RmlsdGVyKTsNCiAgcmVnaXN0ZXIoJ2RhdGUnLCBkYXRlRmlsdGVyKTsNCiAgcmVnaXN0ZXIoJ2ZpbHRlcicsIGZpbHRlckZpbHRlcik7DQogIHJlZ2lzdGVyKCdqc29uJywganNvbkZpbHRlcik7DQogIHJlZ2lzdGVyKCdsaW1pdFRvJywgbGltaXRUb0ZpbHRlcik7DQogIHJlZ2lzdGVyKCdsb3dlcmNhc2UnLCBsb3dlcmNhc2VGaWx0ZXIpOw0KICByZWdpc3RlcignbnVtYmVyJywgbnVtYmVyRmlsdGVyKTsNCiAgcmVnaXN0ZXIoJ29yZGVyQnknLCBvcmRlckJ5RmlsdGVyKTsNCiAgcmVnaXN0ZXIoJ3VwcGVyY2FzZScsIHVwcGVyY2FzZUZpbHRlcik7DQp9DQoNCi8qKg0KICogQG5nZG9jIGZpbHRlcg0KICogQG5hbWUgZmlsdGVyDQogKiBAa2luZCBmdW5jdGlvbg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogU2VsZWN0cyBhIHN1YnNldCBvZiBpdGVtcyBmcm9tIGBhcnJheWAgYW5kIHJldHVybnMgaXQgYXMgYSBuZXcgYXJyYXkuDQogKg0KICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIHNvdXJjZSBhcnJheS4NCiAqIEBwYXJhbSB7c3RyaW5nfE9iamVjdHxmdW5jdGlvbigpfSBleHByZXNzaW9uIFRoZSBwcmVkaWNhdGUgdG8gYmUgdXNlZCBmb3Igc2VsZWN0aW5nIGl0ZW1zIGZyb20NCiAqICAgYGFycmF5YC4NCiAqDQogKiAgIENhbiBiZSBvbmUgb2Y6DQogKg0KICogICAtIGBzdHJpbmdgOiBUaGUgc3RyaW5nIGlzIHVzZWQgZm9yIG1hdGNoaW5nIGFnYWluc3QgdGhlIGNvbnRlbnRzIG9mIHRoZSBgYXJyYXlgLiBBbGwgc3RyaW5ncyBvcg0KICogICAgIG9iamVjdHMgd2l0aCBzdHJpbmcgcHJvcGVydGllcyBpbiBgYXJyYXlgIHRoYXQgbWF0Y2ggdGhpcyBzdHJpbmcgd2lsbCBiZSByZXR1cm5lZC4gVGhpcyBhbHNvDQogKiAgICAgYXBwbGllcyB0byBuZXN0ZWQgb2JqZWN0IHByb3BlcnRpZXMuDQogKiAgICAgVGhlIHByZWRpY2F0ZSBjYW4gYmUgbmVnYXRlZCBieSBwcmVmaXhpbmcgdGhlIHN0cmluZyB3aXRoIGAhYC4NCiAqDQogKiAgIC0gYE9iamVjdGA6IEEgcGF0dGVybiBvYmplY3QgY2FuIGJlIHVzZWQgdG8gZmlsdGVyIHNwZWNpZmljIHByb3BlcnRpZXMgb24gb2JqZWN0cyBjb250YWluZWQNCiAqICAgICBieSBgYXJyYXlgLiBGb3IgZXhhbXBsZSBge25hbWU6Ik0iLCBwaG9uZToiMSJ9YCBwcmVkaWNhdGUgd2lsbCByZXR1cm4gYW4gYXJyYXkgb2YgaXRlbXMNCiAqICAgICB3aGljaCBoYXZlIHByb3BlcnR5IGBuYW1lYCBjb250YWluaW5nICJNIiBhbmQgcHJvcGVydHkgYHBob25lYCBjb250YWluaW5nICIxIi4gQSBzcGVjaWFsDQogKiAgICAgcHJvcGVydHkgbmFtZSBgJGAgY2FuIGJlIHVzZWQgKGFzIGluIGB7JDoidGV4dCJ9YCkgdG8gYWNjZXB0IGEgbWF0Y2ggYWdhaW5zdCBhbnkNCiAqICAgICBwcm9wZXJ0eSBvZiB0aGUgb2JqZWN0IG9yIGl0cyBuZXN0ZWQgb2JqZWN0IHByb3BlcnRpZXMuIFRoYXQncyBlcXVpdmFsZW50IHRvIHRoZSBzaW1wbGUNCiAqICAgICBzdWJzdHJpbmcgbWF0Y2ggd2l0aCBhIGBzdHJpbmdgIGFzIGRlc2NyaWJlZCBhYm92ZS4gVGhlIHByZWRpY2F0ZSBjYW4gYmUgbmVnYXRlZCBieSBwcmVmaXhpbmcNCiAqICAgICB0aGUgc3RyaW5nIHdpdGggYCFgLg0KICogICAgIEZvciBleGFtcGxlIGB7bmFtZTogIiFNIn1gIHByZWRpY2F0ZSB3aWxsIHJldHVybiBhbiBhcnJheSBvZiBpdGVtcyB3aGljaCBoYXZlIHByb3BlcnR5IGBuYW1lYA0KICogICAgIG5vdCBjb250YWluaW5nICJNIi4NCiAqDQogKiAgICAgTm90ZSB0aGF0IGEgbmFtZWQgcHJvcGVydHkgd2lsbCBtYXRjaCBwcm9wZXJ0aWVzIG9uIHRoZSBzYW1lIGxldmVsIG9ubHksIHdoaWxlIHRoZSBzcGVjaWFsDQogKiAgICAgYCRgIHByb3BlcnR5IHdpbGwgbWF0Y2ggcHJvcGVydGllcyBvbiB0aGUgc2FtZSBsZXZlbCBvciBkZWVwZXIuIEUuZy4gYW4gYXJyYXkgaXRlbSBsaWtlDQogKiAgICAgYHtuYW1lOiB7Zmlyc3Q6ICdKb2huJywgbGFzdDogJ0RvZSd9fWAgd2lsbCAqKm5vdCoqIGJlIG1hdGNoZWQgYnkgYHtuYW1lOiAnSm9obid9YCwgYnV0DQogKiAgICAgKip3aWxsKiogYmUgbWF0Y2hlZCBieSBgeyQ6ICdKb2huJ31gLg0KICoNCiAqICAgLSBgZnVuY3Rpb24odmFsdWUsIGluZGV4KWA6IEEgcHJlZGljYXRlIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIHdyaXRlIGFyYml0cmFyeSBmaWx0ZXJzLiBUaGUNCiAqICAgICBmdW5jdGlvbiBpcyBjYWxsZWQgZm9yIGVhY2ggZWxlbWVudCBvZiBgYXJyYXlgLiBUaGUgZmluYWwgcmVzdWx0IGlzIGFuIGFycmF5IG9mIHRob3NlDQogKiAgICAgZWxlbWVudHMgdGhhdCB0aGUgcHJlZGljYXRlIHJldHVybmVkIHRydWUgZm9yLg0KICoNCiAqIEBwYXJhbSB7ZnVuY3Rpb24oYWN0dWFsLCBleHBlY3RlZCl8dHJ1ZXx1bmRlZmluZWR9IGNvbXBhcmF0b3IgQ29tcGFyYXRvciB3aGljaCBpcyB1c2VkIGluDQogKiAgICAgZGV0ZXJtaW5pbmcgaWYgdGhlIGV4cGVjdGVkIHZhbHVlIChmcm9tIHRoZSBmaWx0ZXIgZXhwcmVzc2lvbikgYW5kIGFjdHVhbCB2YWx1ZSAoZnJvbQ0KICogICAgIHRoZSBvYmplY3QgaW4gdGhlIGFycmF5KSBzaG91bGQgYmUgY29uc2lkZXJlZCBhIG1hdGNoLg0KICoNCiAqICAgQ2FuIGJlIG9uZSBvZjoNCiAqDQogKiAgIC0gYGZ1bmN0aW9uKGFjdHVhbCwgZXhwZWN0ZWQpYDoNCiAqICAgICBUaGUgZnVuY3Rpb24gd2lsbCBiZSBnaXZlbiB0aGUgb2JqZWN0IHZhbHVlIGFuZCB0aGUgcHJlZGljYXRlIHZhbHVlIHRvIGNvbXBhcmUgYW5kDQogKiAgICAgc2hvdWxkIHJldHVybiB0cnVlIGlmIGJvdGggdmFsdWVzIHNob3VsZCBiZSBjb25zaWRlcmVkIGVxdWFsLg0KICoNCiAqICAgLSBgdHJ1ZWA6IEEgc2hvcnRoYW5kIGZvciBgZnVuY3Rpb24oYWN0dWFsLCBleHBlY3RlZCkgeyByZXR1cm4gYW5ndWxhci5lcXVhbHMoYWN0dWFsLCBleHBlY3RlZCl9YC4NCiAqICAgICBUaGlzIGlzIGVzc2VudGlhbGx5IHN0cmljdCBjb21wYXJpc29uIG9mIGV4cGVjdGVkIGFuZCBhY3R1YWwuDQogKg0KICogICAtIGBmYWxzZXx1bmRlZmluZWRgOiBBIHNob3J0IGhhbmQgZm9yIGEgZnVuY3Rpb24gd2hpY2ggd2lsbCBsb29rIGZvciBhIHN1YnN0cmluZyBtYXRjaCBpbiBjYXNlDQogKiAgICAgaW5zZW5zaXRpdmUgd2F5Lg0KICoNCiAqIEBleGFtcGxlDQogICA8ZXhhbXBsZT4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPGRpdiBuZy1pbml0PSJmcmllbmRzID0gW3tuYW1lOidKb2huJywgcGhvbmU6JzU1NS0xMjc2J30sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtuYW1lOidNYXJ5JywgcGhvbmU6JzgwMC1CSUctTUFSWSd9LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7bmFtZTonTWlrZScsIHBob25lOic1NTUtNDMyMSd9LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7bmFtZTonQWRhbScsIHBob25lOic1NTUtNTY3OCd9LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7bmFtZTonSnVsaWUnLCBwaG9uZTonNTU1LTg3NjUnfSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge25hbWU6J0p1bGlldHRlJywgcGhvbmU6JzU1NS01Njc4J31dIj48L2Rpdj4NCg0KICAgICAgIFNlYXJjaDogPGlucHV0IG5nLW1vZGVsPSJzZWFyY2hUZXh0Ij4NCiAgICAgICA8dGFibGUgaWQ9InNlYXJjaFRleHRSZXN1bHRzIj4NCiAgICAgICAgIDx0cj48dGg+TmFtZTwvdGg+PHRoPlBob25lPC90aD48L3RyPg0KICAgICAgICAgPHRyIG5nLXJlcGVhdD0iZnJpZW5kIGluIGZyaWVuZHMgfCBmaWx0ZXI6c2VhcmNoVGV4dCI+DQogICAgICAgICAgIDx0ZD57e2ZyaWVuZC5uYW1lfX08L3RkPg0KICAgICAgICAgICA8dGQ+e3tmcmllbmQucGhvbmV9fTwvdGQ+DQogICAgICAgICA8L3RyPg0KICAgICAgIDwvdGFibGU+DQogICAgICAgPGhyPg0KICAgICAgIEFueTogPGlucHV0IG5nLW1vZGVsPSJzZWFyY2guJCI+IDxicj4NCiAgICAgICBOYW1lIG9ubHkgPGlucHV0IG5nLW1vZGVsPSJzZWFyY2gubmFtZSI+PGJyPg0KICAgICAgIFBob25lIG9ubHkgPGlucHV0IG5nLW1vZGVsPSJzZWFyY2gucGhvbmUiPjxicj4NCiAgICAgICBFcXVhbGl0eSA8aW5wdXQgdHlwZT0iY2hlY2tib3giIG5nLW1vZGVsPSJzdHJpY3QiPjxicj4NCiAgICAgICA8dGFibGUgaWQ9InNlYXJjaE9ialJlc3VsdHMiPg0KICAgICAgICAgPHRyPjx0aD5OYW1lPC90aD48dGg+UGhvbmU8L3RoPjwvdHI+DQogICAgICAgICA8dHIgbmctcmVwZWF0PSJmcmllbmRPYmogaW4gZnJpZW5kcyB8IGZpbHRlcjpzZWFyY2g6c3RyaWN0Ij4NCiAgICAgICAgICAgPHRkPnt7ZnJpZW5kT2JqLm5hbWV9fTwvdGQ+DQogICAgICAgICAgIDx0ZD57e2ZyaWVuZE9iai5waG9uZX19PC90ZD4NCiAgICAgICAgIDwvdHI+DQogICAgICAgPC90YWJsZT4NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICB2YXIgZXhwZWN0RnJpZW5kTmFtZXMgPSBmdW5jdGlvbihleHBlY3RlZE5hbWVzLCBrZXkpIHsNCiAgICAgICAgIGVsZW1lbnQuYWxsKGJ5LnJlcGVhdGVyKGtleSArICcgaW4gZnJpZW5kcycpLmNvbHVtbihrZXkgKyAnLm5hbWUnKSkudGhlbihmdW5jdGlvbihhcnIpIHsNCiAgICAgICAgICAgYXJyLmZvckVhY2goZnVuY3Rpb24od2QsIGkpIHsNCiAgICAgICAgICAgICBleHBlY3Qod2QuZ2V0VGV4dCgpKS50b01hdGNoKGV4cGVjdGVkTmFtZXNbaV0pOw0KICAgICAgICAgICB9KTsNCiAgICAgICAgIH0pOw0KICAgICAgIH07DQoNCiAgICAgICBpdCgnc2hvdWxkIHNlYXJjaCBhY3Jvc3MgYWxsIGZpZWxkcyB3aGVuIGZpbHRlcmluZyB3aXRoIGEgc3RyaW5nJywgZnVuY3Rpb24oKSB7DQogICAgICAgICB2YXIgc2VhcmNoVGV4dCA9IGVsZW1lbnQoYnkubW9kZWwoJ3NlYXJjaFRleHQnKSk7DQogICAgICAgICBzZWFyY2hUZXh0LmNsZWFyKCk7DQogICAgICAgICBzZWFyY2hUZXh0LnNlbmRLZXlzKCdtJyk7DQogICAgICAgICBleHBlY3RGcmllbmROYW1lcyhbJ01hcnknLCAnTWlrZScsICdBZGFtJ10sICdmcmllbmQnKTsNCg0KICAgICAgICAgc2VhcmNoVGV4dC5jbGVhcigpOw0KICAgICAgICAgc2VhcmNoVGV4dC5zZW5kS2V5cygnNzYnKTsNCiAgICAgICAgIGV4cGVjdEZyaWVuZE5hbWVzKFsnSm9obicsICdKdWxpZSddLCAnZnJpZW5kJyk7DQogICAgICAgfSk7DQoNCiAgICAgICBpdCgnc2hvdWxkIHNlYXJjaCBpbiBzcGVjaWZpYyBmaWVsZHMgd2hlbiBmaWx0ZXJpbmcgd2l0aCBhIHByZWRpY2F0ZSBvYmplY3QnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgIHZhciBzZWFyY2hBbnkgPSBlbGVtZW50KGJ5Lm1vZGVsKCdzZWFyY2guJCcpKTsNCiAgICAgICAgIHNlYXJjaEFueS5jbGVhcigpOw0KICAgICAgICAgc2VhcmNoQW55LnNlbmRLZXlzKCdpJyk7DQogICAgICAgICBleHBlY3RGcmllbmROYW1lcyhbJ01hcnknLCAnTWlrZScsICdKdWxpZScsICdKdWxpZXR0ZSddLCAnZnJpZW5kT2JqJyk7DQogICAgICAgfSk7DQogICAgICAgaXQoJ3Nob3VsZCB1c2UgYSBlcXVhbCBjb21wYXJpc29uIHdoZW4gY29tcGFyYXRvciBpcyB0cnVlJywgZnVuY3Rpb24oKSB7DQogICAgICAgICB2YXIgc2VhcmNoTmFtZSA9IGVsZW1lbnQoYnkubW9kZWwoJ3NlYXJjaC5uYW1lJykpOw0KICAgICAgICAgdmFyIHN0cmljdCA9IGVsZW1lbnQoYnkubW9kZWwoJ3N0cmljdCcpKTsNCiAgICAgICAgIHNlYXJjaE5hbWUuY2xlYXIoKTsNCiAgICAgICAgIHNlYXJjaE5hbWUuc2VuZEtleXMoJ0p1bGllJyk7DQogICAgICAgICBzdHJpY3QuY2xpY2soKTsNCiAgICAgICAgIGV4cGVjdEZyaWVuZE5hbWVzKFsnSnVsaWUnXSwgJ2ZyaWVuZE9iaicpOw0KICAgICAgIH0pOw0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCmZ1bmN0aW9uIGZpbHRlckZpbHRlcigpIHsNCiAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBleHByZXNzaW9uLCBjb21wYXJhdG9yKSB7DQogICAgaWYgKCFpc0FycmF5KGFycmF5KSkgcmV0dXJuIGFycmF5Ow0KDQogICAgdmFyIHByZWRpY2F0ZUZuOw0KICAgIHZhciBtYXRjaEFnYWluc3RBbnlQcm9wOw0KDQogICAgc3dpdGNoICh0eXBlb2YgZXhwcmVzc2lvbikgew0KICAgICAgY2FzZSAnZnVuY3Rpb24nOg0KICAgICAgICBwcmVkaWNhdGVGbiA9IGV4cHJlc3Npb247DQogICAgICAgIGJyZWFrOw0KICAgICAgY2FzZSAnYm9vbGVhbic6DQogICAgICBjYXNlICdudW1iZXInOg0KICAgICAgY2FzZSAnc3RyaW5nJzoNCiAgICAgICAgbWF0Y2hBZ2FpbnN0QW55UHJvcCA9IHRydWU7DQogICAgICAgIC8vanNoaW50IC1XMDg2DQogICAgICBjYXNlICdvYmplY3QnOg0KICAgICAgICAvL2pzaGludCArVzA4Ng0KICAgICAgICBwcmVkaWNhdGVGbiA9IGNyZWF0ZVByZWRpY2F0ZUZuKGV4cHJlc3Npb24sIGNvbXBhcmF0b3IsIG1hdGNoQWdhaW5zdEFueVByb3ApOw0KICAgICAgICBicmVhazsNCiAgICAgIGRlZmF1bHQ6DQogICAgICAgIHJldHVybiBhcnJheTsNCiAgICB9DQoNCiAgICByZXR1cm4gYXJyYXkuZmlsdGVyKHByZWRpY2F0ZUZuKTsNCiAgfTsNCn0NCg0KLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYGZpbHRlckZpbHRlcmANCmZ1bmN0aW9uIGNyZWF0ZVByZWRpY2F0ZUZuKGV4cHJlc3Npb24sIGNvbXBhcmF0b3IsIG1hdGNoQWdhaW5zdEFueVByb3ApIHsNCiAgdmFyIHNob3VsZE1hdGNoUHJpbWl0aXZlcyA9IGlzT2JqZWN0KGV4cHJlc3Npb24pICYmICgnJCcgaW4gZXhwcmVzc2lvbik7DQogIHZhciBwcmVkaWNhdGVGbjsNCg0KICBpZiAoY29tcGFyYXRvciA9PT0gdHJ1ZSkgew0KICAgIGNvbXBhcmF0b3IgPSBlcXVhbHM7DQogIH0gZWxzZSBpZiAoIWlzRnVuY3Rpb24oY29tcGFyYXRvcikpIHsNCiAgICBjb21wYXJhdG9yID0gZnVuY3Rpb24oYWN0dWFsLCBleHBlY3RlZCkgew0KICAgICAgaWYgKGlzT2JqZWN0KGFjdHVhbCkgfHwgaXNPYmplY3QoZXhwZWN0ZWQpKSB7DQogICAgICAgIC8vIFByZXZlbnQgYW4gb2JqZWN0IHRvIGJlIGNvbnNpZGVyZWQgZXF1YWwgdG8gYSBzdHJpbmcgbGlrZSBgJ1tvYmplY3QnYA0KICAgICAgICByZXR1cm4gZmFsc2U7DQogICAgICB9DQoNCiAgICAgIGFjdHVhbCA9IGxvd2VyY2FzZSgnJyArIGFjdHVhbCk7DQogICAgICBleHBlY3RlZCA9IGxvd2VyY2FzZSgnJyArIGV4cGVjdGVkKTsNCiAgICAgIHJldHVybiBhY3R1YWwuaW5kZXhPZihleHBlY3RlZCkgIT09IC0xOw0KICAgIH07DQogIH0NCg0KICBwcmVkaWNhdGVGbiA9IGZ1bmN0aW9uKGl0ZW0pIHsNCiAgICBpZiAoc2hvdWxkTWF0Y2hQcmltaXRpdmVzICYmICFpc09iamVjdChpdGVtKSkgew0KICAgICAgcmV0dXJuIGRlZXBDb21wYXJlKGl0ZW0sIGV4cHJlc3Npb24uJCwgY29tcGFyYXRvciwgZmFsc2UpOw0KICAgIH0NCiAgICByZXR1cm4gZGVlcENvbXBhcmUoaXRlbSwgZXhwcmVzc2lvbiwgY29tcGFyYXRvciwgbWF0Y2hBZ2FpbnN0QW55UHJvcCk7DQogIH07DQoNCiAgcmV0dXJuIHByZWRpY2F0ZUZuOw0KfQ0KDQpmdW5jdGlvbiBkZWVwQ29tcGFyZShhY3R1YWwsIGV4cGVjdGVkLCBjb21wYXJhdG9yLCBtYXRjaEFnYWluc3RBbnlQcm9wLCBkb250TWF0Y2hXaG9sZU9iamVjdCkgew0KICB2YXIgYWN0dWFsVHlwZSA9IHR5cGVvZiBhY3R1YWw7DQogIHZhciBleHBlY3RlZFR5cGUgPSB0eXBlb2YgZXhwZWN0ZWQ7DQoNCiAgaWYgKChleHBlY3RlZFR5cGUgPT09ICdzdHJpbmcnKSAmJiAoZXhwZWN0ZWQuY2hhckF0KDApID09PSAnIScpKSB7DQogICAgcmV0dXJuICFkZWVwQ29tcGFyZShhY3R1YWwsIGV4cGVjdGVkLnN1YnN0cmluZygxKSwgY29tcGFyYXRvciwgbWF0Y2hBZ2FpbnN0QW55UHJvcCk7DQogIH0gZWxzZSBpZiAoYWN0dWFsVHlwZSA9PT0gJ2FycmF5Jykgew0KICAgIC8vIEluIGNhc2UgYGFjdHVhbGAgaXMgYW4gYXJyYXksIGNvbnNpZGVyIGl0IGEgbWF0Y2gNCiAgICAvLyBpZiBBTlkgb2YgaXQncyBpdGVtcyBtYXRjaGVzIGBleHBlY3RlZGANCiAgICByZXR1cm4gYWN0dWFsLnNvbWUoZnVuY3Rpb24oaXRlbSkgew0KICAgICAgcmV0dXJuIGRlZXBDb21wYXJlKGl0ZW0sIGV4cGVjdGVkLCBjb21wYXJhdG9yLCBtYXRjaEFnYWluc3RBbnlQcm9wKTsNCiAgICB9KTsNCiAgfQ0KDQogIHN3aXRjaCAoYWN0dWFsVHlwZSkgew0KICAgIGNhc2UgJ29iamVjdCc6DQogICAgICB2YXIga2V5Ow0KICAgICAgaWYgKG1hdGNoQWdhaW5zdEFueVByb3ApIHsNCiAgICAgICAgZm9yIChrZXkgaW4gYWN0dWFsKSB7DQogICAgICAgICAgaWYgKChrZXkuY2hhckF0KDApICE9PSAnJCcpICYmIGRlZXBDb21wYXJlKGFjdHVhbFtrZXldLCBleHBlY3RlZCwgY29tcGFyYXRvciwgdHJ1ZSkpIHsNCiAgICAgICAgICAgIHJldHVybiB0cnVlOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gZG9udE1hdGNoV2hvbGVPYmplY3QgPyBmYWxzZSA6IGRlZXBDb21wYXJlKGFjdHVhbCwgZXhwZWN0ZWQsIGNvbXBhcmF0b3IsIGZhbHNlKTsNCiAgICAgIH0gZWxzZSBpZiAoZXhwZWN0ZWRUeXBlID09PSAnb2JqZWN0Jykgew0KICAgICAgICBmb3IgKGtleSBpbiBleHBlY3RlZCkgew0KICAgICAgICAgIHZhciBleHBlY3RlZFZhbCA9IGV4cGVjdGVkW2tleV07DQogICAgICAgICAgaWYgKGlzRnVuY3Rpb24oZXhwZWN0ZWRWYWwpKSB7DQogICAgICAgICAgICBjb250aW51ZTsNCiAgICAgICAgICB9DQoNCiAgICAgICAgICB2YXIgbWF0Y2hBbnlQcm9wZXJ0eSA9IGtleSA9PT0gJyQnOw0KICAgICAgICAgIHZhciBhY3R1YWxWYWwgPSBtYXRjaEFueVByb3BlcnR5ID8gYWN0dWFsIDogYWN0dWFsW2tleV07DQogICAgICAgICAgaWYgKCFkZWVwQ29tcGFyZShhY3R1YWxWYWwsIGV4cGVjdGVkVmFsLCBjb21wYXJhdG9yLCBtYXRjaEFueVByb3BlcnR5LCBtYXRjaEFueVByb3BlcnR5KSkgew0KICAgICAgICAgICAgcmV0dXJuIGZhbHNlOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gdHJ1ZTsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIHJldHVybiBjb21wYXJhdG9yKGFjdHVhbCwgZXhwZWN0ZWQpOw0KICAgICAgfQ0KICAgICAgYnJlYWs7DQogICAgY2FzZSAnZnVuY3Rpb24nOg0KICAgICAgcmV0dXJuIGZhbHNlOw0KICAgIGRlZmF1bHQ6DQogICAgICByZXR1cm4gY29tcGFyYXRvcihhY3R1YWwsIGV4cGVjdGVkKTsNCiAgfQ0KfQ0KDQovKioNCiAqIEBuZ2RvYyBmaWx0ZXINCiAqIEBuYW1lIGN1cnJlbmN5DQogKiBAa2luZCBmdW5jdGlvbg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogRm9ybWF0cyBhIG51bWJlciBhcyBhIGN1cnJlbmN5IChpZSAkMSwyMzQuNTYpLiBXaGVuIG5vIGN1cnJlbmN5IHN5bWJvbCBpcyBwcm92aWRlZCwgZGVmYXVsdA0KICogc3ltYm9sIGZvciBjdXJyZW50IGxvY2FsZSBpcyB1c2VkLg0KICoNCiAqIEBwYXJhbSB7bnVtYmVyfSBhbW91bnQgSW5wdXQgdG8gZmlsdGVyLg0KICogQHBhcmFtIHtzdHJpbmc9fSBzeW1ib2wgQ3VycmVuY3kgc3ltYm9sIG9yIGlkZW50aWZpZXIgdG8gYmUgZGlzcGxheWVkLg0KICogQHBhcmFtIHtudW1iZXI9fSBmcmFjdGlvblNpemUgTnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHJvdW5kIHRoZSBhbW91bnQgdG8sIGRlZmF1bHRzIHRvIGRlZmF1bHQgbWF4IGZyYWN0aW9uIHNpemUgZm9yIGN1cnJlbnQgbG9jYWxlDQogKiBAcmV0dXJucyB7c3RyaW5nfSBGb3JtYXR0ZWQgbnVtYmVyLg0KICoNCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGUgbW9kdWxlPSJjdXJyZW5jeUV4YW1wbGUiPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICA8c2NyaXB0Pg0KICAgICAgICAgYW5ndWxhci5tb2R1bGUoJ2N1cnJlbmN5RXhhbXBsZScsIFtdKQ0KICAgICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICAgICRzY29wZS5hbW91bnQgPSAxMjM0LjU2Ow0KICAgICAgICAgICB9XSk7DQogICAgICAgPC9zY3JpcHQ+DQogICAgICAgPGRpdiBuZy1jb250cm9sbGVyPSJFeGFtcGxlQ29udHJvbGxlciI+DQogICAgICAgICA8aW5wdXQgdHlwZT0ibnVtYmVyIiBuZy1tb2RlbD0iYW1vdW50Ij4gPGJyPg0KICAgICAgICAgZGVmYXVsdCBjdXJyZW5jeSBzeW1ib2wgKCQpOiA8c3BhbiBpZD0iY3VycmVuY3ktZGVmYXVsdCI+e3thbW91bnQgfCBjdXJyZW5jeX19PC9zcGFuPjxicj4NCiAgICAgICAgIGN1c3RvbSBjdXJyZW5jeSBpZGVudGlmaWVyIChVU0QkKTogPHNwYW4gaWQ9ImN1cnJlbmN5LWN1c3RvbSI+e3thbW91bnQgfCBjdXJyZW5jeToiVVNEJCJ9fTwvc3Bhbj4NCiAgICAgICAgIG5vIGZyYWN0aW9ucyAoMCk6IDxzcGFuIGlkPSJjdXJyZW5jeS1uby1mcmFjdGlvbnMiPnt7YW1vdW50IHwgY3VycmVuY3k6IlVTRCQiOjB9fTwvc3Bhbj4NCiAgICAgICA8L2Rpdj4NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICBpdCgnc2hvdWxkIGluaXQgd2l0aCAxMjM0LjU2JywgZnVuY3Rpb24oKSB7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5pZCgnY3VycmVuY3ktZGVmYXVsdCcpKS5nZXRUZXh0KCkpLnRvQmUoJyQxLDIzNC41NicpOw0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuaWQoJ2N1cnJlbmN5LWN1c3RvbScpKS5nZXRUZXh0KCkpLnRvQmUoJ1VTRCQxLDIzNC41NicpOw0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuaWQoJ2N1cnJlbmN5LW5vLWZyYWN0aW9ucycpKS5nZXRUZXh0KCkpLnRvQmUoJ1VTRCQxLDIzNScpOw0KICAgICAgIH0pOw0KICAgICAgIGl0KCdzaG91bGQgdXBkYXRlJywgZnVuY3Rpb24oKSB7DQogICAgICAgICBpZiAoYnJvd3Nlci5wYXJhbXMuYnJvd3NlciA9PSAnc2FmYXJpJykgew0KICAgICAgICAgICAvLyBTYWZhcmkgZG9lcyBub3QgdW5kZXJzdGFuZCB0aGUgbWludXMga2V5LiBTZWUNCiAgICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2FuZ3VsYXIvcHJvdHJhY3Rvci9pc3N1ZXMvNDgxDQogICAgICAgICAgIHJldHVybjsNCiAgICAgICAgIH0NCiAgICAgICAgIGVsZW1lbnQoYnkubW9kZWwoJ2Ftb3VudCcpKS5jbGVhcigpOw0KICAgICAgICAgZWxlbWVudChieS5tb2RlbCgnYW1vdW50JykpLnNlbmRLZXlzKCctMTIzNCcpOw0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuaWQoJ2N1cnJlbmN5LWRlZmF1bHQnKSkuZ2V0VGV4dCgpKS50b0JlKCcoJDEsMjM0LjAwKScpOw0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuaWQoJ2N1cnJlbmN5LWN1c3RvbScpKS5nZXRUZXh0KCkpLnRvQmUoJyhVU0QkMSwyMzQuMDApJyk7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5pZCgnY3VycmVuY3ktbm8tZnJhY3Rpb25zJykpLmdldFRleHQoKSkudG9CZSgnKFVTRCQxLDIzNCknKTsNCiAgICAgICB9KTsNCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICovDQpjdXJyZW5jeUZpbHRlci4kaW5qZWN0ID0gWyckbG9jYWxlJ107DQpmdW5jdGlvbiBjdXJyZW5jeUZpbHRlcigkbG9jYWxlKSB7DQogIHZhciBmb3JtYXRzID0gJGxvY2FsZS5OVU1CRVJfRk9STUFUUzsNCiAgcmV0dXJuIGZ1bmN0aW9uKGFtb3VudCwgY3VycmVuY3lTeW1ib2wsIGZyYWN0aW9uU2l6ZSkgew0KICAgIGlmIChpc1VuZGVmaW5lZChjdXJyZW5jeVN5bWJvbCkpIHsNCiAgICAgIGN1cnJlbmN5U3ltYm9sID0gZm9ybWF0cy5DVVJSRU5DWV9TWU07DQogICAgfQ0KDQogICAgaWYgKGlzVW5kZWZpbmVkKGZyYWN0aW9uU2l6ZSkpIHsNCiAgICAgIGZyYWN0aW9uU2l6ZSA9IGZvcm1hdHMuUEFUVEVSTlNbMV0ubWF4RnJhYzsNCiAgICB9DQoNCiAgICAvLyBpZiBudWxsIG9yIHVuZGVmaW5lZCBwYXNzIGl0IHRocm91Z2gNCiAgICByZXR1cm4gKGFtb3VudCA9PSBudWxsKQ0KICAgICAgICA/IGFtb3VudA0KICAgICAgICA6IGZvcm1hdE51bWJlcihhbW91bnQsIGZvcm1hdHMuUEFUVEVSTlNbMV0sIGZvcm1hdHMuR1JPVVBfU0VQLCBmb3JtYXRzLkRFQ0lNQUxfU0VQLCBmcmFjdGlvblNpemUpLg0KICAgICAgICAgICAgcmVwbGFjZSgvXHUwMEE0L2csIGN1cnJlbmN5U3ltYm9sKTsNCiAgfTsNCn0NCg0KLyoqDQogKiBAbmdkb2MgZmlsdGVyDQogKiBAbmFtZSBudW1iZXINCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBGb3JtYXRzIGEgbnVtYmVyIGFzIHRleHQuDQogKg0KICogSWYgdGhlIGlucHV0IGlzIG5vdCBhIG51bWJlciBhbiBlbXB0eSBzdHJpbmcgaXMgcmV0dXJuZWQuDQogKg0KICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfSBudW1iZXIgTnVtYmVyIHRvIGZvcm1hdC4NCiAqIEBwYXJhbSB7KG51bWJlcnxzdHJpbmcpPX0gZnJhY3Rpb25TaXplIE51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byByb3VuZCB0aGUgbnVtYmVyIHRvLg0KICogSWYgdGhpcyBpcyBub3QgcHJvdmlkZWQgdGhlbiB0aGUgZnJhY3Rpb24gc2l6ZSBpcyBjb21wdXRlZCBmcm9tIHRoZSBjdXJyZW50IGxvY2FsZSdzIG51bWJlcg0KICogZm9ybWF0dGluZyBwYXR0ZXJuLiBJbiB0aGUgY2FzZSBvZiB0aGUgZGVmYXVsdCBsb2NhbGUsIGl0IHdpbGwgYmUgMy4NCiAqIEByZXR1cm5zIHtzdHJpbmd9IE51bWJlciByb3VuZGVkIHRvIGRlY2ltYWxQbGFjZXMgYW5kIHBsYWNlcyBhIOKAPyzigD8gYWZ0ZXIgZWFjaCB0aGlyZCBkaWdpdC4NCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGUgbW9kdWxlPSJudW1iZXJGaWx0ZXJFeGFtcGxlIj4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPHNjcmlwdD4NCiAgICAgICAgIGFuZ3VsYXIubW9kdWxlKCdudW1iZXJGaWx0ZXJFeGFtcGxlJywgW10pDQogICAgICAgICAgIC5jb250cm9sbGVyKCdFeGFtcGxlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgICAgICAgJHNjb3BlLnZhbCA9IDEyMzQuNTY3ODk7DQogICAgICAgICAgIH1dKTsNCiAgICAgICA8L3NjcmlwdD4NCiAgICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICAgIEVudGVyIG51bWJlcjogPGlucHV0IG5nLW1vZGVsPSd2YWwnPjxicj4NCiAgICAgICAgIERlZmF1bHQgZm9ybWF0dGluZzogPHNwYW4gaWQ9J251bWJlci1kZWZhdWx0Jz57e3ZhbCB8IG51bWJlcn19PC9zcGFuPjxicj4NCiAgICAgICAgIE5vIGZyYWN0aW9uczogPHNwYW4+e3t2YWwgfCBudW1iZXI6MH19PC9zcGFuPjxicj4NCiAgICAgICAgIE5lZ2F0aXZlIG51bWJlcjogPHNwYW4+e3stdmFsIHwgbnVtYmVyOjR9fTwvc3Bhbj4NCiAgICAgICA8L2Rpdj4NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICBpdCgnc2hvdWxkIGZvcm1hdCBudW1iZXJzJywgZnVuY3Rpb24oKSB7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5pZCgnbnVtYmVyLWRlZmF1bHQnKSkuZ2V0VGV4dCgpKS50b0JlKCcxLDIzNC41NjgnKTsNCiAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmJpbmRpbmcoJ3ZhbCB8IG51bWJlcjowJykpLmdldFRleHQoKSkudG9CZSgnMSwyMzUnKTsNCiAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmJpbmRpbmcoJy12YWwgfCBudW1iZXI6NCcpKS5nZXRUZXh0KCkpLnRvQmUoJy0xLDIzNC41Njc5Jyk7DQogICAgICAgfSk7DQoNCiAgICAgICBpdCgnc2hvdWxkIHVwZGF0ZScsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgZWxlbWVudChieS5tb2RlbCgndmFsJykpLmNsZWFyKCk7DQogICAgICAgICBlbGVtZW50KGJ5Lm1vZGVsKCd2YWwnKSkuc2VuZEtleXMoJzMzNzQuMzMzJyk7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5pZCgnbnVtYmVyLWRlZmF1bHQnKSkuZ2V0VGV4dCgpKS50b0JlKCczLDM3NC4zMzMnKTsNCiAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmJpbmRpbmcoJ3ZhbCB8IG51bWJlcjowJykpLmdldFRleHQoKSkudG9CZSgnMywzNzQnKTsNCiAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmJpbmRpbmcoJy12YWwgfCBudW1iZXI6NCcpKS5nZXRUZXh0KCkpLnRvQmUoJy0zLDM3NC4zMzMwJyk7DQogICAgICB9KTsNCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICovDQoNCg0KbnVtYmVyRmlsdGVyLiRpbmplY3QgPSBbJyRsb2NhbGUnXTsNCmZ1bmN0aW9uIG51bWJlckZpbHRlcigkbG9jYWxlKSB7DQogIHZhciBmb3JtYXRzID0gJGxvY2FsZS5OVU1CRVJfRk9STUFUUzsNCiAgcmV0dXJuIGZ1bmN0aW9uKG51bWJlciwgZnJhY3Rpb25TaXplKSB7DQoNCiAgICAvLyBpZiBudWxsIG9yIHVuZGVmaW5lZCBwYXNzIGl0IHRocm91Z2gNCiAgICByZXR1cm4gKG51bWJlciA9PSBudWxsKQ0KICAgICAgICA/IG51bWJlcg0KICAgICAgICA6IGZvcm1hdE51bWJlcihudW1iZXIsIGZvcm1hdHMuUEFUVEVSTlNbMF0sIGZvcm1hdHMuR1JPVVBfU0VQLCBmb3JtYXRzLkRFQ0lNQUxfU0VQLA0KICAgICAgICAgICAgICAgICAgICAgICBmcmFjdGlvblNpemUpOw0KICB9Ow0KfQ0KDQp2YXIgREVDSU1BTF9TRVAgPSAnLic7DQpmdW5jdGlvbiBmb3JtYXROdW1iZXIobnVtYmVyLCBwYXR0ZXJuLCBncm91cFNlcCwgZGVjaW1hbFNlcCwgZnJhY3Rpb25TaXplKSB7DQogIGlmICghaXNGaW5pdGUobnVtYmVyKSB8fCBpc09iamVjdChudW1iZXIpKSByZXR1cm4gJyc7DQoNCiAgdmFyIGlzTmVnYXRpdmUgPSBudW1iZXIgPCAwOw0KICBudW1iZXIgPSBNYXRoLmFicyhudW1iZXIpOw0KICB2YXIgbnVtU3RyID0gbnVtYmVyICsgJycsDQogICAgICBmb3JtYXRlZFRleHQgPSAnJywNCiAgICAgIHBhcnRzID0gW107DQoNCiAgdmFyIGhhc0V4cG9uZW50ID0gZmFsc2U7DQogIGlmIChudW1TdHIuaW5kZXhPZignZScpICE9PSAtMSkgew0KICAgIHZhciBtYXRjaCA9IG51bVN0ci5tYXRjaCgvKFtcZFwuXSspZSgtPykoXGQrKS8pOw0KICAgIGlmIChtYXRjaCAmJiBtYXRjaFsyXSA9PSAnLScgJiYgbWF0Y2hbM10gPiBmcmFjdGlvblNpemUgKyAxKSB7DQogICAgICBudW1iZXIgPSAwOw0KICAgIH0gZWxzZSB7DQogICAgICBmb3JtYXRlZFRleHQgPSBudW1TdHI7DQogICAgICBoYXNFeHBvbmVudCA9IHRydWU7DQogICAgfQ0KICB9DQoNCiAgaWYgKCFoYXNFeHBvbmVudCkgew0KICAgIHZhciBmcmFjdGlvbkxlbiA9IChudW1TdHIuc3BsaXQoREVDSU1BTF9TRVApWzFdIHx8ICcnKS5sZW5ndGg7DQoNCiAgICAvLyBkZXRlcm1pbmUgZnJhY3Rpb25TaXplIGlmIGl0IGlzIG5vdCBzcGVjaWZpZWQNCiAgICBpZiAoaXNVbmRlZmluZWQoZnJhY3Rpb25TaXplKSkgew0KICAgICAgZnJhY3Rpb25TaXplID0gTWF0aC5taW4oTWF0aC5tYXgocGF0dGVybi5taW5GcmFjLCBmcmFjdGlvbkxlbiksIHBhdHRlcm4ubWF4RnJhYyk7DQogICAgfQ0KDQogICAgLy8gc2FmZWx5IHJvdW5kIG51bWJlcnMgaW4gSlMgd2l0aG91dCBoaXR0aW5nIGltcHJlY2lzaW9ucyBvZiBmbG9hdGluZy1wb2ludCBhcml0aG1ldGljcw0KICAgIC8vIGluc3BpcmVkIGJ5Og0KICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL01hdGgvcm91bmQNCiAgICBudW1iZXIgPSArKE1hdGgucm91bmQoKyhudW1iZXIudG9TdHJpbmcoKSArICdlJyArIGZyYWN0aW9uU2l6ZSkpLnRvU3RyaW5nKCkgKyAnZScgKyAtZnJhY3Rpb25TaXplKTsNCg0KICAgIHZhciBmcmFjdGlvbiA9ICgnJyArIG51bWJlcikuc3BsaXQoREVDSU1BTF9TRVApOw0KICAgIHZhciB3aG9sZSA9IGZyYWN0aW9uWzBdOw0KICAgIGZyYWN0aW9uID0gZnJhY3Rpb25bMV0gfHwgJyc7DQoNCiAgICB2YXIgaSwgcG9zID0gMCwNCiAgICAgICAgbGdyb3VwID0gcGF0dGVybi5sZ1NpemUsDQogICAgICAgIGdyb3VwID0gcGF0dGVybi5nU2l6ZTsNCg0KICAgIGlmICh3aG9sZS5sZW5ndGggPj0gKGxncm91cCArIGdyb3VwKSkgew0KICAgICAgcG9zID0gd2hvbGUubGVuZ3RoIC0gbGdyb3VwOw0KICAgICAgZm9yIChpID0gMDsgaSA8IHBvczsgaSsrKSB7DQogICAgICAgIGlmICgocG9zIC0gaSkgJSBncm91cCA9PT0gMCAmJiBpICE9PSAwKSB7DQogICAgICAgICAgZm9ybWF0ZWRUZXh0ICs9IGdyb3VwU2VwOw0KICAgICAgICB9DQogICAgICAgIGZvcm1hdGVkVGV4dCArPSB3aG9sZS5jaGFyQXQoaSk7DQogICAgICB9DQogICAgfQ0KDQogICAgZm9yIChpID0gcG9zOyBpIDwgd2hvbGUubGVuZ3RoOyBpKyspIHsNCiAgICAgIGlmICgod2hvbGUubGVuZ3RoIC0gaSkgJSBsZ3JvdXAgPT09IDAgJiYgaSAhPT0gMCkgew0KICAgICAgICBmb3JtYXRlZFRleHQgKz0gZ3JvdXBTZXA7DQogICAgICB9DQogICAgICBmb3JtYXRlZFRleHQgKz0gd2hvbGUuY2hhckF0KGkpOw0KICAgIH0NCg0KICAgIC8vIGZvcm1hdCBmcmFjdGlvbiBwYXJ0Lg0KICAgIHdoaWxlIChmcmFjdGlvbi5sZW5ndGggPCBmcmFjdGlvblNpemUpIHsNCiAgICAgIGZyYWN0aW9uICs9ICcwJzsNCiAgICB9DQoNCiAgICBpZiAoZnJhY3Rpb25TaXplICYmIGZyYWN0aW9uU2l6ZSAhPT0gIjAiKSBmb3JtYXRlZFRleHQgKz0gZGVjaW1hbFNlcCArIGZyYWN0aW9uLnN1YnN0cigwLCBmcmFjdGlvblNpemUpOw0KICB9IGVsc2Ugew0KICAgIGlmIChmcmFjdGlvblNpemUgPiAwICYmIG51bWJlciA8IDEpIHsNCiAgICAgIGZvcm1hdGVkVGV4dCA9IG51bWJlci50b0ZpeGVkKGZyYWN0aW9uU2l6ZSk7DQogICAgICBudW1iZXIgPSBwYXJzZUZsb2F0KGZvcm1hdGVkVGV4dCk7DQogICAgfQ0KICB9DQoNCiAgaWYgKG51bWJlciA9PT0gMCkgew0KICAgIGlzTmVnYXRpdmUgPSBmYWxzZTsNCiAgfQ0KDQogIHBhcnRzLnB1c2goaXNOZWdhdGl2ZSA/IHBhdHRlcm4ubmVnUHJlIDogcGF0dGVybi5wb3NQcmUsDQogICAgICAgICAgICAgZm9ybWF0ZWRUZXh0LA0KICAgICAgICAgICAgIGlzTmVnYXRpdmUgPyBwYXR0ZXJuLm5lZ1N1ZiA6IHBhdHRlcm4ucG9zU3VmKTsNCiAgcmV0dXJuIHBhcnRzLmpvaW4oJycpOw0KfQ0KDQpmdW5jdGlvbiBwYWROdW1iZXIobnVtLCBkaWdpdHMsIHRyaW0pIHsNCiAgdmFyIG5lZyA9ICcnOw0KICBpZiAobnVtIDwgMCkgew0KICAgIG5lZyA9ICAnLSc7DQogICAgbnVtID0gLW51bTsNCiAgfQ0KICBudW0gPSAnJyArIG51bTsNCiAgd2hpbGUgKG51bS5sZW5ndGggPCBkaWdpdHMpIG51bSA9ICcwJyArIG51bTsNCiAgaWYgKHRyaW0pDQogICAgbnVtID0gbnVtLnN1YnN0cihudW0ubGVuZ3RoIC0gZGlnaXRzKTsNCiAgcmV0dXJuIG5lZyArIG51bTsNCn0NCg0KDQpmdW5jdGlvbiBkYXRlR2V0dGVyKG5hbWUsIHNpemUsIG9mZnNldCwgdHJpbSkgew0KICBvZmZzZXQgPSBvZmZzZXQgfHwgMDsNCiAgcmV0dXJuIGZ1bmN0aW9uKGRhdGUpIHsNCiAgICB2YXIgdmFsdWUgPSBkYXRlWydnZXQnICsgbmFtZV0oKTsNCiAgICBpZiAob2Zmc2V0ID4gMCB8fCB2YWx1ZSA+IC1vZmZzZXQpDQogICAgICB2YWx1ZSArPSBvZmZzZXQ7DQogICAgaWYgKHZhbHVlID09PSAwICYmIG9mZnNldCA9PSAtMTIpIHZhbHVlID0gMTI7DQogICAgcmV0dXJuIHBhZE51bWJlcih2YWx1ZSwgc2l6ZSwgdHJpbSk7DQogIH07DQp9DQoNCmZ1bmN0aW9uIGRhdGVTdHJHZXR0ZXIobmFtZSwgc2hvcnRGb3JtKSB7DQogIHJldHVybiBmdW5jdGlvbihkYXRlLCBmb3JtYXRzKSB7DQogICAgdmFyIHZhbHVlID0gZGF0ZVsnZ2V0JyArIG5hbWVdKCk7DQogICAgdmFyIGdldCA9IHVwcGVyY2FzZShzaG9ydEZvcm0gPyAoJ1NIT1JUJyArIG5hbWUpIDogbmFtZSk7DQoNCiAgICByZXR1cm4gZm9ybWF0c1tnZXRdW3ZhbHVlXTsNCiAgfTsNCn0NCg0KZnVuY3Rpb24gdGltZVpvbmVHZXR0ZXIoZGF0ZSkgew0KICB2YXIgem9uZSA9IC0xICogZGF0ZS5nZXRUaW1lem9uZU9mZnNldCgpOw0KICB2YXIgcGFkZGVkWm9uZSA9ICh6b25lID49IDApID8gIisiIDogIiI7DQoNCiAgcGFkZGVkWm9uZSArPSBwYWROdW1iZXIoTWF0aFt6b25lID4gMCA/ICdmbG9vcicgOiAnY2VpbCddKHpvbmUgLyA2MCksIDIpICsNCiAgICAgICAgICAgICAgICBwYWROdW1iZXIoTWF0aC5hYnMoem9uZSAlIDYwKSwgMik7DQoNCiAgcmV0dXJuIHBhZGRlZFpvbmU7DQp9DQoNCmZ1bmN0aW9uIGdldEZpcnN0VGh1cnNkYXlPZlllYXIoeWVhcikgew0KICAgIC8vIDAgPSBpbmRleCBvZiBKYW51YXJ5DQogICAgdmFyIGRheU9mV2Vla09uRmlyc3QgPSAobmV3IERhdGUoeWVhciwgMCwgMSkpLmdldERheSgpOw0KICAgIC8vIDQgPSBpbmRleCBvZiBUaHVyc2RheSAoKzEgdG8gYWNjb3VudCBmb3IgMXN0ID0gNSkNCiAgICAvLyAxMSA9IGluZGV4IG9mICpuZXh0KiBUaHVyc2RheSAoKzEgYWNjb3VudCBmb3IgMXN0ID0gMTIpDQogICAgcmV0dXJuIG5ldyBEYXRlKHllYXIsIDAsICgoZGF5T2ZXZWVrT25GaXJzdCA8PSA0KSA/IDUgOiAxMikgLSBkYXlPZldlZWtPbkZpcnN0KTsNCn0NCg0KZnVuY3Rpb24gZ2V0VGh1cnNkYXlUaGlzV2VlayhkYXRldGltZSkgew0KICAgIHJldHVybiBuZXcgRGF0ZShkYXRldGltZS5nZXRGdWxsWWVhcigpLCBkYXRldGltZS5nZXRNb250aCgpLA0KICAgICAgLy8gNCA9IGluZGV4IG9mIFRodXJzZGF5DQogICAgICBkYXRldGltZS5nZXREYXRlKCkgKyAoNCAtIGRhdGV0aW1lLmdldERheSgpKSk7DQp9DQoNCmZ1bmN0aW9uIHdlZWtHZXR0ZXIoc2l6ZSkgew0KICAgcmV0dXJuIGZ1bmN0aW9uKGRhdGUpIHsNCiAgICAgIHZhciBmaXJzdFRodXJzID0gZ2V0Rmlyc3RUaHVyc2RheU9mWWVhcihkYXRlLmdldEZ1bGxZZWFyKCkpLA0KICAgICAgICAgdGhpc1RodXJzID0gZ2V0VGh1cnNkYXlUaGlzV2VlayhkYXRlKTsNCg0KICAgICAgdmFyIGRpZmYgPSArdGhpc1RodXJzIC0gK2ZpcnN0VGh1cnMsDQogICAgICAgICByZXN1bHQgPSAxICsgTWF0aC5yb3VuZChkaWZmIC8gNi4wNDhlOCk7IC8vIDYuMDQ4ZTggbXMgcGVyIHdlZWsNCg0KICAgICAgcmV0dXJuIHBhZE51bWJlcihyZXN1bHQsIHNpemUpOw0KICAgfTsNCn0NCg0KZnVuY3Rpb24gYW1wbUdldHRlcihkYXRlLCBmb3JtYXRzKSB7DQogIHJldHVybiBkYXRlLmdldEhvdXJzKCkgPCAxMiA/IGZvcm1hdHMuQU1QTVNbMF0gOiBmb3JtYXRzLkFNUE1TWzFdOw0KfQ0KDQp2YXIgREFURV9GT1JNQVRTID0gew0KICB5eXl5OiBkYXRlR2V0dGVyKCdGdWxsWWVhcicsIDQpLA0KICAgIHl5OiBkYXRlR2V0dGVyKCdGdWxsWWVhcicsIDIsIDAsIHRydWUpLA0KICAgICB5OiBkYXRlR2V0dGVyKCdGdWxsWWVhcicsIDEpLA0KICBNTU1NOiBkYXRlU3RyR2V0dGVyKCdNb250aCcpLA0KICAgTU1NOiBkYXRlU3RyR2V0dGVyKCdNb250aCcsIHRydWUpLA0KICAgIE1NOiBkYXRlR2V0dGVyKCdNb250aCcsIDIsIDEpLA0KICAgICBNOiBkYXRlR2V0dGVyKCdNb250aCcsIDEsIDEpLA0KICAgIGRkOiBkYXRlR2V0dGVyKCdEYXRlJywgMiksDQogICAgIGQ6IGRhdGVHZXR0ZXIoJ0RhdGUnLCAxKSwNCiAgICBISDogZGF0ZUdldHRlcignSG91cnMnLCAyKSwNCiAgICAgSDogZGF0ZUdldHRlcignSG91cnMnLCAxKSwNCiAgICBoaDogZGF0ZUdldHRlcignSG91cnMnLCAyLCAtMTIpLA0KICAgICBoOiBkYXRlR2V0dGVyKCdIb3VycycsIDEsIC0xMiksDQogICAgbW06IGRhdGVHZXR0ZXIoJ01pbnV0ZXMnLCAyKSwNCiAgICAgbTogZGF0ZUdldHRlcignTWludXRlcycsIDEpLA0KICAgIHNzOiBkYXRlR2V0dGVyKCdTZWNvbmRzJywgMiksDQogICAgIHM6IGRhdGVHZXR0ZXIoJ1NlY29uZHMnLCAxKSwNCiAgICAgLy8gd2hpbGUgSVNPIDg2MDEgcmVxdWlyZXMgZnJhY3Rpb25zIHRvIGJlIHByZWZpeGVkIHdpdGggYC5gIG9yIGAsYA0KICAgICAvLyB3ZSBjYW4gYmUganVzdCBzYWZlbHkgcmVseSBvbiB1c2luZyBgc3NzYCBzaW5jZSB3ZSBjdXJyZW50bHkgZG9uJ3Qgc3VwcG9ydCBzaW5nbGUgb3IgdHdvIGRpZ2l0IGZyYWN0aW9ucw0KICAgc3NzOiBkYXRlR2V0dGVyKCdNaWxsaXNlY29uZHMnLCAzKSwNCiAgRUVFRTogZGF0ZVN0ckdldHRlcignRGF5JyksDQogICBFRUU6IGRhdGVTdHJHZXR0ZXIoJ0RheScsIHRydWUpLA0KICAgICBhOiBhbXBtR2V0dGVyLA0KICAgICBaOiB0aW1lWm9uZUdldHRlciwNCiAgICB3dzogd2Vla0dldHRlcigyKSwNCiAgICAgdzogd2Vla0dldHRlcigxKQ0KfTsNCg0KdmFyIERBVEVfRk9STUFUU19TUExJVCA9IC8oKD86W155TWRIaG1zYVpFdyddKyl8KD86Jyg/OlteJ118JycpKicpfCg/OkUrfHkrfE0rfGQrfEgrfGgrfG0rfHMrfGF8Wnx3KykpKC4qKS8sDQogICAgTlVNQkVSX1NUUklORyA9IC9eXC0/XGQrJC87DQoNCi8qKg0KICogQG5nZG9jIGZpbHRlcg0KICogQG5hbWUgZGF0ZQ0KICogQGtpbmQgZnVuY3Rpb24NCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqICAgRm9ybWF0cyBgZGF0ZWAgdG8gYSBzdHJpbmcgYmFzZWQgb24gdGhlIHJlcXVlc3RlZCBgZm9ybWF0YC4NCiAqDQogKiAgIGBmb3JtYXRgIHN0cmluZyBjYW4gYmUgY29tcG9zZWQgb2YgdGhlIGZvbGxvd2luZyBlbGVtZW50czoNCiAqDQogKiAgICogYCd5eXl5J2A6IDQgZGlnaXQgcmVwcmVzZW50YXRpb24gb2YgeWVhciAoZS5nLiBBRCAxID0+IDAwMDEsIEFEIDIwMTAgPT4gMjAxMCkNCiAqICAgKiBgJ3l5J2A6IDIgZGlnaXQgcmVwcmVzZW50YXRpb24gb2YgeWVhciwgcGFkZGVkICgwMC05OSkuIChlLmcuIEFEIDIwMDEgPT4gMDEsIEFEIDIwMTAgPT4gMTApDQogKiAgICogYCd5J2A6IDEgZGlnaXQgcmVwcmVzZW50YXRpb24gb2YgeWVhciwgZS5nLiAoQUQgMSA9PiAxLCBBRCAxOTkgPT4gMTk5KQ0KICogICAqIGAnTU1NTSdgOiBNb250aCBpbiB5ZWFyIChKYW51YXJ5LURlY2VtYmVyKQ0KICogICAqIGAnTU1NJ2A6IE1vbnRoIGluIHllYXIgKEphbi1EZWMpDQogKiAgICogYCdNTSdgOiBNb250aCBpbiB5ZWFyLCBwYWRkZWQgKDAxLTEyKQ0KICogICAqIGAnTSdgOiBNb250aCBpbiB5ZWFyICgxLTEyKQ0KICogICAqIGAnZGQnYDogRGF5IGluIG1vbnRoLCBwYWRkZWQgKDAxLTMxKQ0KICogICAqIGAnZCdgOiBEYXkgaW4gbW9udGggKDEtMzEpDQogKiAgICogYCdFRUVFJ2A6IERheSBpbiBXZWVrLChTdW5kYXktU2F0dXJkYXkpDQogKiAgICogYCdFRUUnYDogRGF5IGluIFdlZWssIChTdW4tU2F0KQ0KICogICAqIGAnSEgnYDogSG91ciBpbiBkYXksIHBhZGRlZCAoMDAtMjMpDQogKiAgICogYCdIJ2A6IEhvdXIgaW4gZGF5ICgwLTIzKQ0KICogICAqIGAnaGgnYDogSG91ciBpbiBBTS9QTSwgcGFkZGVkICgwMS0xMikNCiAqICAgKiBgJ2gnYDogSG91ciBpbiBBTS9QTSwgKDEtMTIpDQogKiAgICogYCdtbSdgOiBNaW51dGUgaW4gaG91ciwgcGFkZGVkICgwMC01OSkNCiAqICAgKiBgJ20nYDogTWludXRlIGluIGhvdXIgKDAtNTkpDQogKiAgICogYCdzcydgOiBTZWNvbmQgaW4gbWludXRlLCBwYWRkZWQgKDAwLTU5KQ0KICogICAqIGAncydgOiBTZWNvbmQgaW4gbWludXRlICgwLTU5KQ0KICogICAqIGAnLnNzcycgb3IgJyxzc3MnYDogTWlsbGlzZWNvbmQgaW4gc2Vjb25kLCBwYWRkZWQgKDAwMC05OTkpDQogKiAgICogYCdhJ2A6IEFNL1BNIG1hcmtlcg0KICogICAqIGAnWidgOiA0IGRpZ2l0ICgrc2lnbikgcmVwcmVzZW50YXRpb24gb2YgdGhlIHRpbWV6b25lIG9mZnNldCAoLTEyMDAtKzEyMDApDQogKiAgICogYCd3dydgOiBXZWVrIG9mIHllYXIsIHBhZGRlZCAoMDAtNTMpLiBXZWVrIDAxIGlzIHRoZSB3ZWVrIHdpdGggdGhlIGZpcnN0IFRodXJzZGF5IG9mIHRoZSB5ZWFyDQogKiAgICogYCd3J2A6IFdlZWsgb2YgeWVhciAoMC01MykuIFdlZWsgMSBpcyB0aGUgd2VlayB3aXRoIHRoZSBmaXJzdCBUaHVyc2RheSBvZiB0aGUgeWVhcg0KICoNCiAqICAgYGZvcm1hdGAgc3RyaW5nIGNhbiBhbHNvIGJlIG9uZSBvZiB0aGUgZm9sbG93aW5nIHByZWRlZmluZWQNCiAqICAge0BsaW5rIGd1aWRlL2kxOG4gbG9jYWxpemFibGUgZm9ybWF0c306DQogKg0KICogICAqIGAnbWVkaXVtJ2A6IGVxdWl2YWxlbnQgdG8gYCdNTU0gZCwgeSBoOm1tOnNzIGEnYCBmb3IgZW5fVVMgbG9jYWxlDQogKiAgICAgKGUuZy4gU2VwIDMsIDIwMTAgMTI6MDU6MDggUE0pDQogKiAgICogYCdzaG9ydCdgOiBlcXVpdmFsZW50IHRvIGAnTS9kL3l5IGg6bW0gYSdgIGZvciBlbl9VUyAgbG9jYWxlIChlLmcuIDkvMy8xMCAxMjowNSBQTSkNCiAqICAgKiBgJ2Z1bGxEYXRlJ2A6IGVxdWl2YWxlbnQgdG8gYCdFRUVFLCBNTU1NIGQsIHknYCBmb3IgZW5fVVMgIGxvY2FsZQ0KICogICAgIChlLmcuIEZyaWRheSwgU2VwdGVtYmVyIDMsIDIwMTApDQogKiAgICogYCdsb25nRGF0ZSdgOiBlcXVpdmFsZW50IHRvIGAnTU1NTSBkLCB5J2AgZm9yIGVuX1VTICBsb2NhbGUgKGUuZy4gU2VwdGVtYmVyIDMsIDIwMTApDQogKiAgICogYCdtZWRpdW1EYXRlJ2A6IGVxdWl2YWxlbnQgdG8gYCdNTU0gZCwgeSdgIGZvciBlbl9VUyAgbG9jYWxlIChlLmcuIFNlcCAzLCAyMDEwKQ0KICogICAqIGAnc2hvcnREYXRlJ2A6IGVxdWl2YWxlbnQgdG8gYCdNL2QveXknYCBmb3IgZW5fVVMgbG9jYWxlIChlLmcuIDkvMy8xMCkNCiAqICAgKiBgJ21lZGl1bVRpbWUnYDogZXF1aXZhbGVudCB0byBgJ2g6bW06c3MgYSdgIGZvciBlbl9VUyBsb2NhbGUgKGUuZy4gMTI6MDU6MDggUE0pDQogKiAgICogYCdzaG9ydFRpbWUnYDogZXF1aXZhbGVudCB0byBgJ2g6bW0gYSdgIGZvciBlbl9VUyBsb2NhbGUgKGUuZy4gMTI6MDUgUE0pDQogKg0KICogICBgZm9ybWF0YCBzdHJpbmcgY2FuIGNvbnRhaW4gbGl0ZXJhbCB2YWx1ZXMuIFRoZXNlIG5lZWQgdG8gYmUgZXNjYXBlZCBieSBzdXJyb3VuZGluZyB3aXRoIHNpbmdsZSBxdW90ZXMgKGUuZy4NCiAqICAgYCJoICdpbiB0aGUgbW9ybmluZyciYCkuIEluIG9yZGVyIHRvIG91dHB1dCBhIHNpbmdsZSBxdW90ZSwgZXNjYXBlIGl0IC0gaS5lLiwgdHdvIHNpbmdsZSBxdW90ZXMgaW4gYSBzZXF1ZW5jZQ0KICogICAoZS5nLiBgImggJ28nJ2Nsb2NrJyJgKS4NCiAqDQogKiBAcGFyYW0geyhEYXRlfG51bWJlcnxzdHJpbmcpfSBkYXRlIERhdGUgdG8gZm9ybWF0IGVpdGhlciBhcyBEYXRlIG9iamVjdCwgbWlsbGlzZWNvbmRzIChzdHJpbmcgb3INCiAqICAgIG51bWJlcikgb3IgdmFyaW91cyBJU08gODYwMSBkYXRldGltZSBzdHJpbmcgZm9ybWF0cyAoZS5nLiB5eXl5LU1NLWRkVEhIOm1tOnNzLnNzc1ogYW5kIGl0cw0KICogICAgc2hvcnRlciB2ZXJzaW9ucyBsaWtlIHl5eXktTU0tZGRUSEg6bW1aLCB5eXl5LU1NLWRkIG9yIHl5eXlNTWRkVEhIbW1zc1opLiBJZiBubyB0aW1lem9uZSBpcw0KICogICAgc3BlY2lmaWVkIGluIHRoZSBzdHJpbmcgaW5wdXQsIHRoZSB0aW1lIGlzIGNvbnNpZGVyZWQgdG8gYmUgaW4gdGhlIGxvY2FsIHRpbWV6b25lLg0KICogQHBhcmFtIHtzdHJpbmc9fSBmb3JtYXQgRm9ybWF0dGluZyBydWxlcyAoc2VlIERlc2NyaXB0aW9uKS4gSWYgbm90IHNwZWNpZmllZCwNCiAqICAgIGBtZWRpdW1EYXRlYCBpcyB1c2VkLg0KICogQHBhcmFtIHtzdHJpbmc9fSB0aW1lem9uZSBUaW1lem9uZSB0byBiZSB1c2VkIGZvciBmb3JtYXR0aW5nLiBSaWdodCBub3csIG9ubHkgYCdVVEMnYCBpcyBzdXBwb3J0ZWQuDQogKiAgICBJZiBub3Qgc3BlY2lmaWVkLCB0aGUgdGltZXpvbmUgb2YgdGhlIGJyb3dzZXIgd2lsbCBiZSB1c2VkLg0KICogQHJldHVybnMge3N0cmluZ30gRm9ybWF0dGVkIHN0cmluZyBvciB0aGUgaW5wdXQgaWYgaW5wdXQgaXMgbm90IHJlY29nbml6ZWQgYXMgZGF0ZS9taWxsaXMuDQogKg0KICogQGV4YW1wbGUNCiAgIDxleGFtcGxlPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICA8c3BhbiBuZy1ub24tYmluZGFibGU+e3sxMjg4MzIzNjIzMDA2IHwgZGF0ZTonbWVkaXVtJ319PC9zcGFuPjoNCiAgICAgICAgICAgPHNwYW4+e3sxMjg4MzIzNjIzMDA2IHwgZGF0ZTonbWVkaXVtJ319PC9zcGFuPjxicj4NCiAgICAgICA8c3BhbiBuZy1ub24tYmluZGFibGU+e3sxMjg4MzIzNjIzMDA2IHwgZGF0ZToneXl5eS1NTS1kZCBISDptbTpzcyBaJ319PC9zcGFuPjoNCiAgICAgICAgICA8c3Bhbj57ezEyODgzMjM2MjMwMDYgfCBkYXRlOid5eXl5LU1NLWRkIEhIOm1tOnNzIFonfX08L3NwYW4+PGJyPg0KICAgICAgIDxzcGFuIG5nLW5vbi1iaW5kYWJsZT57ezEyODgzMjM2MjMwMDYgfCBkYXRlOidNTS9kZC95eXl5IEAgaDptbWEnfX08L3NwYW4+Og0KICAgICAgICAgIDxzcGFuPnt7JzEyODgzMjM2MjMwMDYnIHwgZGF0ZTonTU0vZGQveXl5eSBAIGg6bW1hJ319PC9zcGFuPjxicj4NCiAgICAgICA8c3BhbiBuZy1ub24tYmluZGFibGU+e3sxMjg4MzIzNjIzMDA2IHwgZGF0ZToiTU0vZGQveXl5eSAnYXQnIGg6bW1hIn19PC9zcGFuPjoNCiAgICAgICAgICA8c3Bhbj57eycxMjg4MzIzNjIzMDA2JyB8IGRhdGU6Ik1NL2RkL3l5eXkgJ2F0JyBoOm1tYSJ9fTwvc3Bhbj48YnI+DQogICAgIDwvZmlsZT4NCiAgICAgPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogICAgICAgaXQoJ3Nob3VsZCBmb3JtYXQgZGF0ZScsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuYmluZGluZygiMTI4ODMyMzYyMzAwNiB8IGRhdGU6J21lZGl1bSciKSkuZ2V0VGV4dCgpKS4NCiAgICAgICAgICAgIHRvTWF0Y2goL09jdCAyXGQsIDIwMTAgXGR7MSwyfTpcZHsyfTpcZHsyfSAoQU18UE0pLyk7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5iaW5kaW5nKCIxMjg4MzIzNjIzMDA2IHwgZGF0ZToneXl5eS1NTS1kZCBISDptbTpzcyBaJyIpKS5nZXRUZXh0KCkpLg0KICAgICAgICAgICAgdG9NYXRjaCgvMjAxMFwtMTBcLTJcZCBcZHsyfTpcZHsyfTpcZHsyfSAoXC18XCspP1xkezR9Lyk7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5iaW5kaW5nKCInMTI4ODMyMzYyMzAwNicgfCBkYXRlOidNTS9kZC95eXl5IEAgaDptbWEnIikpLmdldFRleHQoKSkuDQogICAgICAgICAgICB0b01hdGNoKC8xMFwvMlxkXC8yMDEwIEAgXGR7MSwyfTpcZHsyfShBTXxQTSkvKTsNCiAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmJpbmRpbmcoIicxMjg4MzIzNjIzMDA2JyB8IGRhdGU6XCJNTS9kZC95eXl5ICdhdCcgaDptbWFcIiIpKS5nZXRUZXh0KCkpLg0KICAgICAgICAgICAgdG9NYXRjaCgvMTBcLzJcZFwvMjAxMCBhdCBcZHsxLDJ9OlxkezJ9KEFNfFBNKS8pOw0KICAgICAgIH0pOw0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCmRhdGVGaWx0ZXIuJGluamVjdCA9IFsnJGxvY2FsZSddOw0KZnVuY3Rpb24gZGF0ZUZpbHRlcigkbG9jYWxlKSB7DQoNCg0KICB2YXIgUl9JU084NjAxX1NUUiA9IC9eKFxkezR9KS0/KFxkXGQpLT8oXGRcZCkoPzpUKFxkXGQpKD86Oj8oXGRcZCkoPzo6PyhcZFxkKSg/OlwuKFxkKykpPyk/KT8oWnwoWystXSkoXGRcZCk6PyhcZFxkKSk/KT8kLzsNCiAgICAgICAgICAgICAgICAgICAgIC8vIDEgICAgICAgIDIgICAgICAgMyAgICAgICAgIDQgICAgICAgICAgNSAgICAgICAgICA2ICAgICAgICAgIDcgICAgICAgICAgOCAgOSAgICAgMTAgICAgICAxMQ0KICBmdW5jdGlvbiBqc29uU3RyaW5nVG9EYXRlKHN0cmluZykgew0KICAgIHZhciBtYXRjaDsNCiAgICBpZiAobWF0Y2ggPSBzdHJpbmcubWF0Y2goUl9JU084NjAxX1NUUikpIHsNCiAgICAgIHZhciBkYXRlID0gbmV3IERhdGUoMCksDQogICAgICAgICAgdHpIb3VyID0gMCwNCiAgICAgICAgICB0ek1pbiAgPSAwLA0KICAgICAgICAgIGRhdGVTZXR0ZXIgPSBtYXRjaFs4XSA/IGRhdGUuc2V0VVRDRnVsbFllYXIgOiBkYXRlLnNldEZ1bGxZZWFyLA0KICAgICAgICAgIHRpbWVTZXR0ZXIgPSBtYXRjaFs4XSA/IGRhdGUuc2V0VVRDSG91cnMgOiBkYXRlLnNldEhvdXJzOw0KDQogICAgICBpZiAobWF0Y2hbOV0pIHsNCiAgICAgICAgdHpIb3VyID0gaW50KG1hdGNoWzldICsgbWF0Y2hbMTBdKTsNCiAgICAgICAgdHpNaW4gPSBpbnQobWF0Y2hbOV0gKyBtYXRjaFsxMV0pOw0KICAgICAgfQ0KICAgICAgZGF0ZVNldHRlci5jYWxsKGRhdGUsIGludChtYXRjaFsxXSksIGludChtYXRjaFsyXSkgLSAxLCBpbnQobWF0Y2hbM10pKTsNCiAgICAgIHZhciBoID0gaW50KG1hdGNoWzRdIHx8IDApIC0gdHpIb3VyOw0KICAgICAgdmFyIG0gPSBpbnQobWF0Y2hbNV0gfHwgMCkgLSB0ek1pbjsNCiAgICAgIHZhciBzID0gaW50KG1hdGNoWzZdIHx8IDApOw0KICAgICAgdmFyIG1zID0gTWF0aC5yb3VuZChwYXJzZUZsb2F0KCcwLicgKyAobWF0Y2hbN10gfHwgMCkpICogMTAwMCk7DQogICAgICB0aW1lU2V0dGVyLmNhbGwoZGF0ZSwgaCwgbSwgcywgbXMpOw0KICAgICAgcmV0dXJuIGRhdGU7DQogICAgfQ0KICAgIHJldHVybiBzdHJpbmc7DQogIH0NCg0KDQogIHJldHVybiBmdW5jdGlvbihkYXRlLCBmb3JtYXQsIHRpbWV6b25lKSB7DQogICAgdmFyIHRleHQgPSAnJywNCiAgICAgICAgcGFydHMgPSBbXSwNCiAgICAgICAgZm4sIG1hdGNoOw0KDQogICAgZm9ybWF0ID0gZm9ybWF0IHx8ICdtZWRpdW1EYXRlJzsNCiAgICBmb3JtYXQgPSAkbG9jYWxlLkRBVEVUSU1FX0ZPUk1BVFNbZm9ybWF0XSB8fCBmb3JtYXQ7DQogICAgaWYgKGlzU3RyaW5nKGRhdGUpKSB7DQogICAgICBkYXRlID0gTlVNQkVSX1NUUklORy50ZXN0KGRhdGUpID8gaW50KGRhdGUpIDoganNvblN0cmluZ1RvRGF0ZShkYXRlKTsNCiAgICB9DQoNCiAgICBpZiAoaXNOdW1iZXIoZGF0ZSkpIHsNCiAgICAgIGRhdGUgPSBuZXcgRGF0ZShkYXRlKTsNCiAgICB9DQoNCiAgICBpZiAoIWlzRGF0ZShkYXRlKSkgew0KICAgICAgcmV0dXJuIGRhdGU7DQogICAgfQ0KDQogICAgd2hpbGUgKGZvcm1hdCkgew0KICAgICAgbWF0Y2ggPSBEQVRFX0ZPUk1BVFNfU1BMSVQuZXhlYyhmb3JtYXQpOw0KICAgICAgaWYgKG1hdGNoKSB7DQogICAgICAgIHBhcnRzID0gY29uY2F0KHBhcnRzLCBtYXRjaCwgMSk7DQogICAgICAgIGZvcm1hdCA9IHBhcnRzLnBvcCgpOw0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgcGFydHMucHVzaChmb3JtYXQpOw0KICAgICAgICBmb3JtYXQgPSBudWxsOw0KICAgICAgfQ0KICAgIH0NCg0KICAgIGlmICh0aW1lem9uZSAmJiB0aW1lem9uZSA9PT0gJ1VUQycpIHsNCiAgICAgIGRhdGUgPSBuZXcgRGF0ZShkYXRlLmdldFRpbWUoKSk7DQogICAgICBkYXRlLnNldE1pbnV0ZXMoZGF0ZS5nZXRNaW51dGVzKCkgKyBkYXRlLmdldFRpbWV6b25lT2Zmc2V0KCkpOw0KICAgIH0NCiAgICBmb3JFYWNoKHBhcnRzLCBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgZm4gPSBEQVRFX0ZPUk1BVFNbdmFsdWVdOw0KICAgICAgdGV4dCArPSBmbiA/IGZuKGRhdGUsICRsb2NhbGUuREFURVRJTUVfRk9STUFUUykNCiAgICAgICAgICAgICAgICAgOiB2YWx1ZS5yZXBsYWNlKC8oXid8JyQpL2csICcnKS5yZXBsYWNlKC8nJy9nLCAiJyIpOw0KICAgIH0pOw0KDQogICAgcmV0dXJuIHRleHQ7DQogIH07DQp9DQoNCg0KLyoqDQogKiBAbmdkb2MgZmlsdGVyDQogKiBAbmFtZSBqc29uDQogKiBAa2luZCBmdW5jdGlvbg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogICBBbGxvd3MgeW91IHRvIGNvbnZlcnQgYSBKYXZhU2NyaXB0IG9iamVjdCBpbnRvIEpTT04gc3RyaW5nLg0KICoNCiAqICAgVGhpcyBmaWx0ZXIgaXMgbW9zdGx5IHVzZWZ1bCBmb3IgZGVidWdnaW5nLiBXaGVuIHVzaW5nIHRoZSBkb3VibGUgY3VybHkge3t2YWx1ZX19IG5vdGF0aW9uDQogKiAgIHRoZSBiaW5kaW5nIGlzIGF1dG9tYXRpY2FsbHkgY29udmVydGVkIHRvIEpTT04uDQogKg0KICogQHBhcmFtIHsqfSBvYmplY3QgQW55IEphdmFTY3JpcHQgb2JqZWN0IChpbmNsdWRpbmcgYXJyYXlzIGFuZCBwcmltaXRpdmUgdHlwZXMpIHRvIGZpbHRlci4NCiAqIEBwYXJhbSB7bnVtYmVyPX0gc3BhY2luZyBUaGUgbnVtYmVyIG9mIHNwYWNlcyB0byB1c2UgcGVyIGluZGVudGF0aW9uLCBkZWZhdWx0cyB0byAyLg0KICogQHJldHVybnMge3N0cmluZ30gSlNPTiBzdHJpbmcuDQogKg0KICoNCiAqIEBleGFtcGxlDQogICA8ZXhhbXBsZT4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPHByZSBpZD0iZGVmYXVsdC1zcGFjaW5nIj57eyB7J25hbWUnOid2YWx1ZSd9IHwganNvbiB9fTwvcHJlPg0KICAgICAgIDxwcmUgaWQ9ImN1c3RvbS1zcGFjaW5nIj57eyB7J25hbWUnOid2YWx1ZSd9IHwganNvbjo0IH19PC9wcmU+DQogICAgIDwvZmlsZT4NCiAgICAgPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogICAgICAgaXQoJ3Nob3VsZCBqc29uaWZ5IGZpbHRlcmVkIG9iamVjdHMnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmlkKCdkZWZhdWx0LXNwYWNpbmcnKSkuZ2V0VGV4dCgpKS50b01hdGNoKC9ce1xuICAibmFtZSI6ID8idmFsdWUiXG59Lyk7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5pZCgnY3VzdG9tLXNwYWNpbmcnKSkuZ2V0VGV4dCgpKS50b01hdGNoKC9ce1xuICAgICJuYW1lIjogPyJ2YWx1ZSJcbn0vKTsNCiAgICAgICB9KTsNCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICoNCiAqLw0KZnVuY3Rpb24ganNvbkZpbHRlcigpIHsNCiAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCwgc3BhY2luZykgew0KICAgIGlmIChpc1VuZGVmaW5lZChzcGFjaW5nKSkgew0KICAgICAgICBzcGFjaW5nID0gMjsNCiAgICB9DQogICAgcmV0dXJuIHRvSnNvbihvYmplY3QsIHNwYWNpbmcpOw0KICB9Ow0KfQ0KDQoNCi8qKg0KICogQG5nZG9jIGZpbHRlcg0KICogQG5hbWUgbG93ZXJjYXNlDQogKiBAa2luZCBmdW5jdGlvbg0KICogQGRlc2NyaXB0aW9uDQogKiBDb252ZXJ0cyBzdHJpbmcgdG8gbG93ZXJjYXNlLg0KICogQHNlZSBhbmd1bGFyLmxvd2VyY2FzZQ0KICovDQp2YXIgbG93ZXJjYXNlRmlsdGVyID0gdmFsdWVGbihsb3dlcmNhc2UpOw0KDQoNCi8qKg0KICogQG5nZG9jIGZpbHRlcg0KICogQG5hbWUgdXBwZXJjYXNlDQogKiBAa2luZCBmdW5jdGlvbg0KICogQGRlc2NyaXB0aW9uDQogKiBDb252ZXJ0cyBzdHJpbmcgdG8gdXBwZXJjYXNlLg0KICogQHNlZSBhbmd1bGFyLnVwcGVyY2FzZQ0KICovDQp2YXIgdXBwZXJjYXNlRmlsdGVyID0gdmFsdWVGbih1cHBlcmNhc2UpOw0KDQovKioNCiAqIEBuZ2RvYyBmaWx0ZXINCiAqIEBuYW1lIGxpbWl0VG8NCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBDcmVhdGVzIGEgbmV3IGFycmF5IG9yIHN0cmluZyBjb250YWluaW5nIG9ubHkgYSBzcGVjaWZpZWQgbnVtYmVyIG9mIGVsZW1lbnRzLiBUaGUgZWxlbWVudHMNCiAqIGFyZSB0YWtlbiBmcm9tIGVpdGhlciB0aGUgYmVnaW5uaW5nIG9yIHRoZSBlbmQgb2YgdGhlIHNvdXJjZSBhcnJheSwgc3RyaW5nIG9yIG51bWJlciwgYXMgc3BlY2lmaWVkIGJ5DQogKiB0aGUgdmFsdWUgYW5kIHNpZ24gKHBvc2l0aXZlIG9yIG5lZ2F0aXZlKSBvZiBgbGltaXRgLiBJZiBhIG51bWJlciBpcyB1c2VkIGFzIGlucHV0LCBpdCBpcw0KICogY29udmVydGVkIHRvIGEgc3RyaW5nLg0KICoNCiAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfG51bWJlcn0gaW5wdXQgU291cmNlIGFycmF5LCBzdHJpbmcgb3IgbnVtYmVyIHRvIGJlIGxpbWl0ZWQuDQogKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGxpbWl0IFRoZSBsZW5ndGggb2YgdGhlIHJldHVybmVkIGFycmF5IG9yIHN0cmluZy4gSWYgdGhlIGBsaW1pdGAgbnVtYmVyDQogKiAgICAgaXMgcG9zaXRpdmUsIGBsaW1pdGAgbnVtYmVyIG9mIGl0ZW1zIGZyb20gdGhlIGJlZ2lubmluZyBvZiB0aGUgc291cmNlIGFycmF5L3N0cmluZyBhcmUgY29waWVkLg0KICogICAgIElmIHRoZSBudW1iZXIgaXMgbmVnYXRpdmUsIGBsaW1pdGAgbnVtYmVyICBvZiBpdGVtcyBmcm9tIHRoZSBlbmQgb2YgdGhlIHNvdXJjZSBhcnJheS9zdHJpbmcNCiAqICAgICBhcmUgY29waWVkLiBUaGUgYGxpbWl0YCB3aWxsIGJlIHRyaW1tZWQgaWYgaXQgZXhjZWVkcyBgYXJyYXkubGVuZ3RoYA0KICogQHJldHVybnMge0FycmF5fHN0cmluZ30gQSBuZXcgc3ViLWFycmF5IG9yIHN1YnN0cmluZyBvZiBsZW5ndGggYGxpbWl0YCBvciBsZXNzIGlmIGlucHV0IGFycmF5DQogKiAgICAgaGFkIGxlc3MgdGhhbiBgbGltaXRgIGVsZW1lbnRzLg0KICoNCiAqIEBleGFtcGxlDQogICA8ZXhhbXBsZSBtb2R1bGU9ImxpbWl0VG9FeGFtcGxlIj4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPHNjcmlwdD4NCiAgICAgICAgIGFuZ3VsYXIubW9kdWxlKCdsaW1pdFRvRXhhbXBsZScsIFtdKQ0KICAgICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICAgICRzY29wZS5udW1iZXJzID0gWzEsMiwzLDQsNSw2LDcsOCw5XTsNCiAgICAgICAgICAgICAkc2NvcGUubGV0dGVycyA9ICJhYmNkZWZnaGkiOw0KICAgICAgICAgICAgICRzY29wZS5sb25nTnVtYmVyID0gMjM0NTQzMjM0MjsNCiAgICAgICAgICAgICAkc2NvcGUubnVtTGltaXQgPSAzOw0KICAgICAgICAgICAgICRzY29wZS5sZXR0ZXJMaW1pdCA9IDM7DQogICAgICAgICAgICAgJHNjb3BlLmxvbmdOdW1iZXJMaW1pdCA9IDM7DQogICAgICAgICAgIH1dKTsNCiAgICAgICA8L3NjcmlwdD4NCiAgICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICAgIExpbWl0IHt7bnVtYmVyc319IHRvOiA8aW5wdXQgdHlwZT0ibnVtYmVyIiBzdGVwPSIxIiBuZy1tb2RlbD0ibnVtTGltaXQiPg0KICAgICAgICAgPHA+T3V0cHV0IG51bWJlcnM6IHt7IG51bWJlcnMgfCBsaW1pdFRvOm51bUxpbWl0IH19PC9wPg0KICAgICAgICAgTGltaXQge3tsZXR0ZXJzfX0gdG86IDxpbnB1dCB0eXBlPSJudW1iZXIiIHN0ZXA9IjEiIG5nLW1vZGVsPSJsZXR0ZXJMaW1pdCI+DQogICAgICAgICA8cD5PdXRwdXQgbGV0dGVyczoge3sgbGV0dGVycyB8IGxpbWl0VG86bGV0dGVyTGltaXQgfX08L3A+DQogICAgICAgICBMaW1pdCB7e2xvbmdOdW1iZXJ9fSB0bzogPGlucHV0IHR5cGU9Im51bWJlciIgc3RlcD0iMSIgbmctbW9kZWw9ImxvbmdOdW1iZXJMaW1pdCI+DQogICAgICAgICA8cD5PdXRwdXQgbG9uZyBudW1iZXI6IHt7IGxvbmdOdW1iZXIgfCBsaW1pdFRvOmxvbmdOdW1iZXJMaW1pdCB9fTwvcD4NCiAgICAgICA8L2Rpdj4NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICB2YXIgbnVtTGltaXRJbnB1dCA9IGVsZW1lbnQoYnkubW9kZWwoJ251bUxpbWl0JykpOw0KICAgICAgIHZhciBsZXR0ZXJMaW1pdElucHV0ID0gZWxlbWVudChieS5tb2RlbCgnbGV0dGVyTGltaXQnKSk7DQogICAgICAgdmFyIGxvbmdOdW1iZXJMaW1pdElucHV0ID0gZWxlbWVudChieS5tb2RlbCgnbG9uZ051bWJlckxpbWl0JykpOw0KICAgICAgIHZhciBsaW1pdGVkTnVtYmVycyA9IGVsZW1lbnQoYnkuYmluZGluZygnbnVtYmVycyB8IGxpbWl0VG86bnVtTGltaXQnKSk7DQogICAgICAgdmFyIGxpbWl0ZWRMZXR0ZXJzID0gZWxlbWVudChieS5iaW5kaW5nKCdsZXR0ZXJzIHwgbGltaXRUbzpsZXR0ZXJMaW1pdCcpKTsNCiAgICAgICB2YXIgbGltaXRlZExvbmdOdW1iZXIgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ2xvbmdOdW1iZXIgfCBsaW1pdFRvOmxvbmdOdW1iZXJMaW1pdCcpKTsNCg0KICAgICAgIGl0KCdzaG91bGQgbGltaXQgdGhlIG51bWJlciBhcnJheSB0byBmaXJzdCB0aHJlZSBpdGVtcycsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgZXhwZWN0KG51bUxpbWl0SW5wdXQuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKS50b0JlKCczJyk7DQogICAgICAgICBleHBlY3QobGV0dGVyTGltaXRJbnB1dC5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykpLnRvQmUoJzMnKTsNCiAgICAgICAgIGV4cGVjdChsb25nTnVtYmVyTGltaXRJbnB1dC5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykpLnRvQmUoJzMnKTsNCiAgICAgICAgIGV4cGVjdChsaW1pdGVkTnVtYmVycy5nZXRUZXh0KCkpLnRvRXF1YWwoJ091dHB1dCBudW1iZXJzOiBbMSwyLDNdJyk7DQogICAgICAgICBleHBlY3QobGltaXRlZExldHRlcnMuZ2V0VGV4dCgpKS50b0VxdWFsKCdPdXRwdXQgbGV0dGVyczogYWJjJyk7DQogICAgICAgICBleHBlY3QobGltaXRlZExvbmdOdW1iZXIuZ2V0VGV4dCgpKS50b0VxdWFsKCdPdXRwdXQgbG9uZyBudW1iZXI6IDIzNCcpOw0KICAgICAgIH0pOw0KDQogICAgICAgLy8gVGhlcmUgaXMgYSBidWcgaW4gc2FmYXJpIGFuZCBwcm90cmFjdG9yIHRoYXQgZG9lc24ndCBsaWtlIHRoZSBtaW51cyBrZXkNCiAgICAgICAvLyBpdCgnc2hvdWxkIHVwZGF0ZSB0aGUgb3V0cHV0IHdoZW4gLTMgaXMgZW50ZXJlZCcsIGZ1bmN0aW9uKCkgew0KICAgICAgIC8vICAgbnVtTGltaXRJbnB1dC5jbGVhcigpOw0KICAgICAgIC8vICAgbnVtTGltaXRJbnB1dC5zZW5kS2V5cygnLTMnKTsNCiAgICAgICAvLyAgIGxldHRlckxpbWl0SW5wdXQuY2xlYXIoKTsNCiAgICAgICAvLyAgIGxldHRlckxpbWl0SW5wdXQuc2VuZEtleXMoJy0zJyk7DQogICAgICAgLy8gICBsb25nTnVtYmVyTGltaXRJbnB1dC5jbGVhcigpOw0KICAgICAgIC8vICAgbG9uZ051bWJlckxpbWl0SW5wdXQuc2VuZEtleXMoJy0zJyk7DQogICAgICAgLy8gICBleHBlY3QobGltaXRlZE51bWJlcnMuZ2V0VGV4dCgpKS50b0VxdWFsKCdPdXRwdXQgbnVtYmVyczogWzcsOCw5XScpOw0KICAgICAgIC8vICAgZXhwZWN0KGxpbWl0ZWRMZXR0ZXJzLmdldFRleHQoKSkudG9FcXVhbCgnT3V0cHV0IGxldHRlcnM6IGdoaScpOw0KICAgICAgIC8vICAgZXhwZWN0KGxpbWl0ZWRMb25nTnVtYmVyLmdldFRleHQoKSkudG9FcXVhbCgnT3V0cHV0IGxvbmcgbnVtYmVyOiAzNDInKTsNCiAgICAgICAvLyB9KTsNCg0KICAgICAgIGl0KCdzaG91bGQgbm90IGV4Y2VlZCB0aGUgbWF4aW11bSBzaXplIG9mIGlucHV0IGFycmF5JywgZnVuY3Rpb24oKSB7DQogICAgICAgICBudW1MaW1pdElucHV0LmNsZWFyKCk7DQogICAgICAgICBudW1MaW1pdElucHV0LnNlbmRLZXlzKCcxMDAnKTsNCiAgICAgICAgIGxldHRlckxpbWl0SW5wdXQuY2xlYXIoKTsNCiAgICAgICAgIGxldHRlckxpbWl0SW5wdXQuc2VuZEtleXMoJzEwMCcpOw0KICAgICAgICAgbG9uZ051bWJlckxpbWl0SW5wdXQuY2xlYXIoKTsNCiAgICAgICAgIGxvbmdOdW1iZXJMaW1pdElucHV0LnNlbmRLZXlzKCcxMDAnKTsNCiAgICAgICAgIGV4cGVjdChsaW1pdGVkTnVtYmVycy5nZXRUZXh0KCkpLnRvRXF1YWwoJ091dHB1dCBudW1iZXJzOiBbMSwyLDMsNCw1LDYsNyw4LDldJyk7DQogICAgICAgICBleHBlY3QobGltaXRlZExldHRlcnMuZ2V0VGV4dCgpKS50b0VxdWFsKCdPdXRwdXQgbGV0dGVyczogYWJjZGVmZ2hpJyk7DQogICAgICAgICBleHBlY3QobGltaXRlZExvbmdOdW1iZXIuZ2V0VGV4dCgpKS50b0VxdWFsKCdPdXRwdXQgbG9uZyBudW1iZXI6IDIzNDU0MzIzNDInKTsNCiAgICAgICB9KTsNCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KKi8NCmZ1bmN0aW9uIGxpbWl0VG9GaWx0ZXIoKSB7DQogIHJldHVybiBmdW5jdGlvbihpbnB1dCwgbGltaXQpIHsNCiAgICBpZiAoaXNOdW1iZXIoaW5wdXQpKSBpbnB1dCA9IGlucHV0LnRvU3RyaW5nKCk7DQogICAgaWYgKCFpc0FycmF5KGlucHV0KSAmJiAhaXNTdHJpbmcoaW5wdXQpKSByZXR1cm4gaW5wdXQ7DQoNCiAgICBpZiAoTWF0aC5hYnMoTnVtYmVyKGxpbWl0KSkgPT09IEluZmluaXR5KSB7DQogICAgICBsaW1pdCA9IE51bWJlcihsaW1pdCk7DQogICAgfSBlbHNlIHsNCiAgICAgIGxpbWl0ID0gaW50KGxpbWl0KTsNCiAgICB9DQoNCiAgICBpZiAoaXNTdHJpbmcoaW5wdXQpKSB7DQogICAgICAvL05hTiBjaGVjayBvbiBsaW1pdA0KICAgICAgaWYgKGxpbWl0KSB7DQogICAgICAgIHJldHVybiBsaW1pdCA+PSAwID8gaW5wdXQuc2xpY2UoMCwgbGltaXQpIDogaW5wdXQuc2xpY2UobGltaXQsIGlucHV0Lmxlbmd0aCk7DQogICAgICB9IGVsc2Ugew0KICAgICAgICByZXR1cm4gIiI7DQogICAgICB9DQogICAgfQ0KDQogICAgdmFyIGksIG47DQoNCiAgICAvLyBpZiBhYnMobGltaXQpIGV4Y2VlZHMgbWF4aW11bSBsZW5ndGgsIHRyaW0gaXQNCiAgICBpZiAobGltaXQgPiBpbnB1dC5sZW5ndGgpDQogICAgICBsaW1pdCA9IGlucHV0Lmxlbmd0aDsNCiAgICBlbHNlIGlmIChsaW1pdCA8IC1pbnB1dC5sZW5ndGgpDQogICAgICBsaW1pdCA9IC1pbnB1dC5sZW5ndGg7DQoNCiAgICBpZiAobGltaXQgPiAwKSB7DQogICAgICBpID0gMDsNCiAgICAgIG4gPSBsaW1pdDsNCiAgICB9IGVsc2Ugew0KICAgICAgLy8gemVybyBhbmQgTmFOIGNoZWNrIG9uIGxpbWl0IC0gcmV0dXJuIGVtcHR5IGFycmF5DQogICAgICBpZiAoIWxpbWl0KSByZXR1cm4gW107DQoNCiAgICAgIGkgPSBpbnB1dC5sZW5ndGggKyBsaW1pdDsNCiAgICAgIG4gPSBpbnB1dC5sZW5ndGg7DQogICAgfQ0KDQogICAgcmV0dXJuIGlucHV0LnNsaWNlKGksIG4pOw0KICB9Ow0KfQ0KDQovKioNCiAqIEBuZ2RvYyBmaWx0ZXINCiAqIEBuYW1lIG9yZGVyQnkNCiAqIEBraW5kIGZ1bmN0aW9uDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBPcmRlcnMgYSBzcGVjaWZpZWQgYGFycmF5YCBieSB0aGUgYGV4cHJlc3Npb25gIHByZWRpY2F0ZS4gSXQgaXMgb3JkZXJlZCBhbHBoYWJldGljYWxseQ0KICogZm9yIHN0cmluZ3MgYW5kIG51bWVyaWNhbGx5IGZvciBudW1iZXJzLiBOb3RlOiBpZiB5b3Ugbm90aWNlIG51bWJlcnMgYXJlIG5vdCBiZWluZyBzb3J0ZWQNCiAqIGNvcnJlY3RseSwgbWFrZSBzdXJlIHRoZXkgYXJlIGFjdHVhbGx5IGJlaW5nIHNhdmVkIGFzIG51bWJlcnMgYW5kIG5vdCBzdHJpbmdzLg0KICoNCiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzb3J0Lg0KICogQHBhcmFtIHtmdW5jdGlvbigqKXxzdHJpbmd8QXJyYXkuPChmdW5jdGlvbigqKXxzdHJpbmcpPj19IGV4cHJlc3Npb24gQSBwcmVkaWNhdGUgdG8gYmUNCiAqICAgIHVzZWQgYnkgdGhlIGNvbXBhcmF0b3IgdG8gZGV0ZXJtaW5lIHRoZSBvcmRlciBvZiBlbGVtZW50cy4NCiAqDQogKiAgICBDYW4gYmUgb25lIG9mOg0KICoNCiAqICAgIC0gYGZ1bmN0aW9uYDogR2V0dGVyIGZ1bmN0aW9uLiBUaGUgcmVzdWx0IG9mIHRoaXMgZnVuY3Rpb24gd2lsbCBiZSBzb3J0ZWQgdXNpbmcgdGhlDQogKiAgICAgIGA8YCwgYD1gLCBgPmAgb3BlcmF0b3IuDQogKiAgICAtIGBzdHJpbmdgOiBBbiBBbmd1bGFyIGV4cHJlc3Npb24uIFRoZSByZXN1bHQgb2YgdGhpcyBleHByZXNzaW9uIGlzIHVzZWQgdG8gY29tcGFyZSBlbGVtZW50cw0KICogICAgICAoZm9yIGV4YW1wbGUgYG5hbWVgIHRvIHNvcnQgYnkgYSBwcm9wZXJ0eSBjYWxsZWQgYG5hbWVgIG9yIGBuYW1lLnN1YnN0cigwLCAzKWAgdG8gc29ydCBieQ0KICogICAgICAzIGZpcnN0IGNoYXJhY3RlcnMgb2YgYSBwcm9wZXJ0eSBjYWxsZWQgYG5hbWVgKS4gVGhlIHJlc3VsdCBvZiBhIGNvbnN0YW50IGV4cHJlc3Npb24NCiAqICAgICAgaXMgaW50ZXJwcmV0ZWQgYXMgYSBwcm9wZXJ0eSBuYW1lIHRvIGJlIHVzZWQgaW4gY29tcGFyaXNvbnMgKGZvciBleGFtcGxlIGAic3BlY2lhbCBuYW1lImANCiAqICAgICAgdG8gc29ydCBvYmplY3QgYnkgdGhlIHZhbHVlIG9mIHRoZWlyIGBzcGVjaWFsIG5hbWVgIHByb3BlcnR5KS4gQW4gZXhwcmVzc2lvbiBjYW4gYmUNCiAqICAgICAgb3B0aW9uYWxseSBwcmVmaXhlZCB3aXRoIGArYCBvciBgLWAgdG8gY29udHJvbCBhc2NlbmRpbmcgb3IgZGVzY2VuZGluZyBzb3J0IG9yZGVyDQogKiAgICAgIChmb3IgZXhhbXBsZSwgYCtuYW1lYCBvciBgLW5hbWVgKS4gSWYgbm8gcHJvcGVydHkgaXMgcHJvdmlkZWQsIChlLmcuIGAnKydgKSB0aGVuIHRoZSBhcnJheQ0KICogICAgICBlbGVtZW50IGl0c2VsZiBpcyB1c2VkIHRvIGNvbXBhcmUgd2hlcmUgc29ydGluZy4NCiAqICAgIC0gYEFycmF5YDogQW4gYXJyYXkgb2YgZnVuY3Rpb24gb3Igc3RyaW5nIHByZWRpY2F0ZXMuIFRoZSBmaXJzdCBwcmVkaWNhdGUgaW4gdGhlIGFycmF5DQogKiAgICAgIGlzIHVzZWQgZm9yIHNvcnRpbmcsIGJ1dCB3aGVuIHR3byBpdGVtcyBhcmUgZXF1aXZhbGVudCwgdGhlIG5leHQgcHJlZGljYXRlIGlzIHVzZWQuDQogKg0KICogICAgSWYgdGhlIHByZWRpY2F0ZSBpcyBtaXNzaW5nIG9yIGVtcHR5IHRoZW4gaXQgZGVmYXVsdHMgdG8gYCcrJ2AuDQogKg0KICogQHBhcmFtIHtib29sZWFuPX0gcmV2ZXJzZSBSZXZlcnNlIHRoZSBvcmRlciBvZiB0aGUgYXJyYXkuDQogKiBAcmV0dXJucyB7QXJyYXl9IFNvcnRlZCBjb3B5IG9mIHRoZSBzb3VyY2UgYXJyYXkuDQogKg0KICogQGV4YW1wbGUNCiAgIDxleGFtcGxlIG1vZHVsZT0ib3JkZXJCeUV4YW1wbGUiPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICA8c2NyaXB0Pg0KICAgICAgICAgYW5ndWxhci5tb2R1bGUoJ29yZGVyQnlFeGFtcGxlJywgW10pDQogICAgICAgICAgIC5jb250cm9sbGVyKCdFeGFtcGxlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgICAgICAgJHNjb3BlLmZyaWVuZHMgPQ0KICAgICAgICAgICAgICAgICBbe25hbWU6J0pvaG4nLCBwaG9uZTonNTU1LTEyMTInLCBhZ2U6MTB9LA0KICAgICAgICAgICAgICAgICAge25hbWU6J01hcnknLCBwaG9uZTonNTU1LTk4NzYnLCBhZ2U6MTl9LA0KICAgICAgICAgICAgICAgICAge25hbWU6J01pa2UnLCBwaG9uZTonNTU1LTQzMjEnLCBhZ2U6MjF9LA0KICAgICAgICAgICAgICAgICAge25hbWU6J0FkYW0nLCBwaG9uZTonNTU1LTU2NzgnLCBhZ2U6MzV9LA0KICAgICAgICAgICAgICAgICAge25hbWU6J0p1bGllJywgcGhvbmU6JzU1NS04NzY1JywgYWdlOjI5fV07DQogICAgICAgICAgICAgJHNjb3BlLnByZWRpY2F0ZSA9ICctYWdlJzsNCiAgICAgICAgICAgfV0pOw0KICAgICAgIDwvc2NyaXB0Pg0KICAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICAgICAgPHByZT5Tb3J0aW5nIHByZWRpY2F0ZSA9IHt7cHJlZGljYXRlfX07IHJldmVyc2UgPSB7e3JldmVyc2V9fTwvcHJlPg0KICAgICAgICAgPGhyLz4NCiAgICAgICAgIFsgPGEgaHJlZj0iIiBuZy1jbGljaz0icHJlZGljYXRlPScnIj51bnNvcnRlZDwvYT4gXQ0KICAgICAgICAgPHRhYmxlIGNsYXNzPSJmcmllbmQiPg0KICAgICAgICAgICA8dHI+DQogICAgICAgICAgICAgPHRoPjxhIGhyZWY9IiIgbmctY2xpY2s9InByZWRpY2F0ZSA9ICduYW1lJzsgcmV2ZXJzZT1mYWxzZSI+TmFtZTwvYT4NCiAgICAgICAgICAgICAgICAgKDxhIGhyZWY9IiIgbmctY2xpY2s9InByZWRpY2F0ZSA9ICctbmFtZSc7IHJldmVyc2U9ZmFsc2UiPl48L2E+KTwvdGg+DQogICAgICAgICAgICAgPHRoPjxhIGhyZWY9IiIgbmctY2xpY2s9InByZWRpY2F0ZSA9ICdwaG9uZSc7IHJldmVyc2U9IXJldmVyc2UiPlBob25lIE51bWJlcjwvYT48L3RoPg0KICAgICAgICAgICAgIDx0aD48YSBocmVmPSIiIG5nLWNsaWNrPSJwcmVkaWNhdGUgPSAnYWdlJzsgcmV2ZXJzZT0hcmV2ZXJzZSI+QWdlPC9hPjwvdGg+DQogICAgICAgICAgIDwvdHI+DQogICAgICAgICAgIDx0ciBuZy1yZXBlYXQ9ImZyaWVuZCBpbiBmcmllbmRzIHwgb3JkZXJCeTpwcmVkaWNhdGU6cmV2ZXJzZSI+DQogICAgICAgICAgICAgPHRkPnt7ZnJpZW5kLm5hbWV9fTwvdGQ+DQogICAgICAgICAgICAgPHRkPnt7ZnJpZW5kLnBob25lfX08L3RkPg0KICAgICAgICAgICAgIDx0ZD57e2ZyaWVuZC5hZ2V9fTwvdGQ+DQogICAgICAgICAgIDwvdHI+DQogICAgICAgICA8L3RhYmxlPg0KICAgICAgIDwvZGl2Pg0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKg0KICogSXQncyBhbHNvIHBvc3NpYmxlIHRvIGNhbGwgdGhlIG9yZGVyQnkgZmlsdGVyIG1hbnVhbGx5LCBieSBpbmplY3RpbmcgYCRmaWx0ZXJgLCByZXRyaWV2aW5nIHRoZQ0KICogZmlsdGVyIHJvdXRpbmUgd2l0aCBgJGZpbHRlcignb3JkZXJCeScpYCwgYW5kIGNhbGxpbmcgdGhlIHJldHVybmVkIGZpbHRlciByb3V0aW5lIHdpdGggdGhlDQogKiBkZXNpcmVkIHBhcmFtZXRlcnMuDQogKg0KICogRXhhbXBsZToNCiAqDQogKiBAZXhhbXBsZQ0KICA8ZXhhbXBsZSBtb2R1bGU9Im9yZGVyQnlFeGFtcGxlIj4NCiAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICAgICA8dGFibGUgY2xhc3M9ImZyaWVuZCI+DQogICAgICAgICAgPHRyPg0KICAgICAgICAgICAgPHRoPjxhIGhyZWY9IiIgbmctY2xpY2s9InJldmVyc2U9ZmFsc2U7b3JkZXIoJ25hbWUnLCBmYWxzZSkiPk5hbWU8L2E+DQogICAgICAgICAgICAgICg8YSBocmVmPSIiIG5nLWNsaWNrPSJvcmRlcignLW5hbWUnLGZhbHNlKSI+XjwvYT4pPC90aD4NCiAgICAgICAgICAgIDx0aD48YSBocmVmPSIiIG5nLWNsaWNrPSJyZXZlcnNlPSFyZXZlcnNlO29yZGVyKCdwaG9uZScsIHJldmVyc2UpIj5QaG9uZSBOdW1iZXI8L2E+PC90aD4NCiAgICAgICAgICAgIDx0aD48YSBocmVmPSIiIG5nLWNsaWNrPSJyZXZlcnNlPSFyZXZlcnNlO29yZGVyKCdhZ2UnLHJldmVyc2UpIj5BZ2U8L2E+PC90aD4NCiAgICAgICAgICA8L3RyPg0KICAgICAgICAgIDx0ciBuZy1yZXBlYXQ9ImZyaWVuZCBpbiBmcmllbmRzIj4NCiAgICAgICAgICAgIDx0ZD57e2ZyaWVuZC5uYW1lfX08L3RkPg0KICAgICAgICAgICAgPHRkPnt7ZnJpZW5kLnBob25lfX08L3RkPg0KICAgICAgICAgICAgPHRkPnt7ZnJpZW5kLmFnZX19PC90ZD4NCiAgICAgICAgICA8L3RyPg0KICAgICAgICA8L3RhYmxlPg0KICAgICAgPC9kaXY+DQogICAgPC9maWxlPg0KDQogICAgPGZpbGUgbmFtZT0ic2NyaXB0LmpzIj4NCiAgICAgIGFuZ3VsYXIubW9kdWxlKCdvcmRlckJ5RXhhbXBsZScsIFtdKQ0KICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsICckZmlsdGVyJywgZnVuY3Rpb24oJHNjb3BlLCAkZmlsdGVyKSB7DQogICAgICAgICAgdmFyIG9yZGVyQnkgPSAkZmlsdGVyKCdvcmRlckJ5Jyk7DQogICAgICAgICAgJHNjb3BlLmZyaWVuZHMgPSBbDQogICAgICAgICAgICB7IG5hbWU6ICdKb2huJywgICAgcGhvbmU6ICc1NTUtMTIxMicsICAgIGFnZTogMTAgfSwNCiAgICAgICAgICAgIHsgbmFtZTogJ01hcnknLCAgICBwaG9uZTogJzU1NS05ODc2JywgICAgYWdlOiAxOSB9LA0KICAgICAgICAgICAgeyBuYW1lOiAnTWlrZScsICAgIHBob25lOiAnNTU1LTQzMjEnLCAgICBhZ2U6IDIxIH0sDQogICAgICAgICAgICB7IG5hbWU6ICdBZGFtJywgICAgcGhvbmU6ICc1NTUtNTY3OCcsICAgIGFnZTogMzUgfSwNCiAgICAgICAgICAgIHsgbmFtZTogJ0p1bGllJywgICBwaG9uZTogJzU1NS04NzY1JywgICAgYWdlOiAyOSB9DQogICAgICAgICAgXTsNCiAgICAgICAgICAkc2NvcGUub3JkZXIgPSBmdW5jdGlvbihwcmVkaWNhdGUsIHJldmVyc2UpIHsNCiAgICAgICAgICAgICRzY29wZS5mcmllbmRzID0gb3JkZXJCeSgkc2NvcGUuZnJpZW5kcywgcHJlZGljYXRlLCByZXZlcnNlKTsNCiAgICAgICAgICB9Ow0KICAgICAgICAgICRzY29wZS5vcmRlcignLWFnZScsZmFsc2UpOw0KICAgICAgICB9XSk7DQogICAgPC9maWxlPg0KPC9leGFtcGxlPg0KICovDQpvcmRlckJ5RmlsdGVyLiRpbmplY3QgPSBbJyRwYXJzZSddOw0KZnVuY3Rpb24gb3JkZXJCeUZpbHRlcigkcGFyc2UpIHsNCiAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBzb3J0UHJlZGljYXRlLCByZXZlcnNlT3JkZXIpIHsNCiAgICBpZiAoIShpc0FycmF5TGlrZShhcnJheSkpKSByZXR1cm4gYXJyYXk7DQogICAgc29ydFByZWRpY2F0ZSA9IGlzQXJyYXkoc29ydFByZWRpY2F0ZSkgPyBzb3J0UHJlZGljYXRlIDogW3NvcnRQcmVkaWNhdGVdOw0KICAgIGlmIChzb3J0UHJlZGljYXRlLmxlbmd0aCA9PT0gMCkgeyBzb3J0UHJlZGljYXRlID0gWycrJ107IH0NCiAgICBzb3J0UHJlZGljYXRlID0gc29ydFByZWRpY2F0ZS5tYXAoZnVuY3Rpb24ocHJlZGljYXRlKSB7DQogICAgICB2YXIgZGVzY2VuZGluZyA9IGZhbHNlLCBnZXQgPSBwcmVkaWNhdGUgfHwgaWRlbnRpdHk7DQogICAgICBpZiAoaXNTdHJpbmcocHJlZGljYXRlKSkgew0KICAgICAgICBpZiAoKHByZWRpY2F0ZS5jaGFyQXQoMCkgPT0gJysnIHx8IHByZWRpY2F0ZS5jaGFyQXQoMCkgPT0gJy0nKSkgew0KICAgICAgICAgIGRlc2NlbmRpbmcgPSBwcmVkaWNhdGUuY2hhckF0KDApID09ICctJzsNCiAgICAgICAgICBwcmVkaWNhdGUgPSBwcmVkaWNhdGUuc3Vic3RyaW5nKDEpOw0KICAgICAgICB9DQogICAgICAgIGlmIChwcmVkaWNhdGUgPT09ICcnKSB7DQogICAgICAgICAgLy8gRWZmZWN0aXZlbHkgbm8gcHJlZGljYXRlIHdhcyBwYXNzZWQgc28gd2UgY29tcGFyZSBpZGVudGl0eQ0KICAgICAgICAgIHJldHVybiByZXZlcnNlQ29tcGFyYXRvcihjb21wYXJlLCBkZXNjZW5kaW5nKTsNCiAgICAgICAgfQ0KICAgICAgICBnZXQgPSAkcGFyc2UocHJlZGljYXRlKTsNCiAgICAgICAgaWYgKGdldC5jb25zdGFudCkgew0KICAgICAgICAgIHZhciBrZXkgPSBnZXQoKTsNCiAgICAgICAgICByZXR1cm4gcmV2ZXJzZUNvbXBhcmF0b3IoZnVuY3Rpb24oYSwgYikgew0KICAgICAgICAgICAgcmV0dXJuIGNvbXBhcmUoYVtrZXldLCBiW2tleV0pOw0KICAgICAgICAgIH0sIGRlc2NlbmRpbmcpOw0KICAgICAgICB9DQogICAgICB9DQogICAgICByZXR1cm4gcmV2ZXJzZUNvbXBhcmF0b3IoZnVuY3Rpb24oYSwgYikgew0KICAgICAgICByZXR1cm4gY29tcGFyZShnZXQoYSksZ2V0KGIpKTsNCiAgICAgIH0sIGRlc2NlbmRpbmcpOw0KICAgIH0pOw0KICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5KS5zb3J0KHJldmVyc2VDb21wYXJhdG9yKGNvbXBhcmF0b3IsIHJldmVyc2VPcmRlcikpOw0KDQogICAgZnVuY3Rpb24gY29tcGFyYXRvcihvMSwgbzIpIHsNCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc29ydFByZWRpY2F0ZS5sZW5ndGg7IGkrKykgew0KICAgICAgICB2YXIgY29tcCA9IHNvcnRQcmVkaWNhdGVbaV0obzEsIG8yKTsNCiAgICAgICAgaWYgKGNvbXAgIT09IDApIHJldHVybiBjb21wOw0KICAgICAgfQ0KICAgICAgcmV0dXJuIDA7DQogICAgfQ0KICAgIGZ1bmN0aW9uIHJldmVyc2VDb21wYXJhdG9yKGNvbXAsIGRlc2NlbmRpbmcpIHsNCiAgICAgIHJldHVybiBkZXNjZW5kaW5nDQogICAgICAgICAgPyBmdW5jdGlvbihhLCBiKSB7cmV0dXJuIGNvbXAoYixhKTt9DQogICAgICAgICAgOiBjb21wOw0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIGlzUHJpbWl0aXZlKHZhbHVlKSB7DQogICAgICBzd2l0Y2ggKHR5cGVvZiB2YWx1ZSkgew0KICAgICAgICBjYXNlICdudW1iZXInOiAvKiBmYWxscyB0aHJvdWdoICovDQogICAgICAgIGNhc2UgJ2Jvb2xlYW4nOiAvKiBmYWxscyB0aHJvdWdoICovDQogICAgICAgIGNhc2UgJ3N0cmluZyc6DQogICAgICAgICAgcmV0dXJuIHRydWU7DQogICAgICAgIGRlZmF1bHQ6DQogICAgICAgICAgcmV0dXJuIGZhbHNlOw0KICAgICAgfQ0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIG9iamVjdFRvU3RyaW5nKHZhbHVlKSB7DQogICAgICBpZiAodmFsdWUgPT09IG51bGwpIHJldHVybiAnbnVsbCc7DQogICAgICBpZiAodHlwZW9mIHZhbHVlLnZhbHVlT2YgPT09ICdmdW5jdGlvbicpIHsNCiAgICAgICAgdmFsdWUgPSB2YWx1ZS52YWx1ZU9mKCk7DQogICAgICAgIGlmIChpc1ByaW1pdGl2ZSh2YWx1ZSkpIHJldHVybiB2YWx1ZTsNCiAgICAgIH0NCiAgICAgIGlmICh0eXBlb2YgdmFsdWUudG9TdHJpbmcgPT09ICdmdW5jdGlvbicpIHsNCiAgICAgICAgdmFsdWUgPSB2YWx1ZS50b1N0cmluZygpOw0KICAgICAgICBpZiAoaXNQcmltaXRpdmUodmFsdWUpKSByZXR1cm4gdmFsdWU7DQogICAgICB9DQogICAgICByZXR1cm4gJyc7DQogICAgfQ0KDQogICAgZnVuY3Rpb24gY29tcGFyZSh2MSwgdjIpIHsNCiAgICAgIHZhciB0MSA9IHR5cGVvZiB2MTsNCiAgICAgIHZhciB0MiA9IHR5cGVvZiB2MjsNCiAgICAgIGlmICh0MSA9PT0gdDIgJiYgdDEgPT09ICJvYmplY3QiKSB7DQogICAgICAgIHYxID0gb2JqZWN0VG9TdHJpbmcodjEpOw0KICAgICAgICB2MiA9IG9iamVjdFRvU3RyaW5nKHYyKTsNCiAgICAgIH0NCiAgICAgIGlmICh0MSA9PT0gdDIpIHsNCiAgICAgICAgaWYgKHQxID09PSAic3RyaW5nIikgew0KICAgICAgICAgICB2MSA9IHYxLnRvTG93ZXJDYXNlKCk7DQogICAgICAgICAgIHYyID0gdjIudG9Mb3dlckNhc2UoKTsNCiAgICAgICAgfQ0KICAgICAgICBpZiAodjEgPT09IHYyKSByZXR1cm4gMDsNCiAgICAgICAgcmV0dXJuIHYxIDwgdjIgPyAtMSA6IDE7DQogICAgICB9IGVsc2Ugew0KICAgICAgICByZXR1cm4gdDEgPCB0MiA/IC0xIDogMTsNCiAgICAgIH0NCiAgICB9DQogIH07DQp9DQoNCmZ1bmN0aW9uIG5nRGlyZWN0aXZlKGRpcmVjdGl2ZSkgew0KICBpZiAoaXNGdW5jdGlvbihkaXJlY3RpdmUpKSB7DQogICAgZGlyZWN0aXZlID0gew0KICAgICAgbGluazogZGlyZWN0aXZlDQogICAgfTsNCiAgfQ0KICBkaXJlY3RpdmUucmVzdHJpY3QgPSBkaXJlY3RpdmUucmVzdHJpY3QgfHwgJ0FDJzsNCiAgcmV0dXJuIHZhbHVlRm4oZGlyZWN0aXZlKTsNCn0NCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBhDQogKiBAcmVzdHJpY3QgRQ0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogTW9kaWZpZXMgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgdGhlIGh0bWwgQSB0YWcgc28gdGhhdCB0aGUgZGVmYXVsdCBhY3Rpb24gaXMgcHJldmVudGVkIHdoZW4NCiAqIHRoZSBocmVmIGF0dHJpYnV0ZSBpcyBlbXB0eS4NCiAqDQogKiBUaGlzIGNoYW5nZSBwZXJtaXRzIHRoZSBlYXN5IGNyZWF0aW9uIG9mIGFjdGlvbiBsaW5rcyB3aXRoIHRoZSBgbmdDbGlja2AgZGlyZWN0aXZlDQogKiB3aXRob3V0IGNoYW5naW5nIHRoZSBsb2NhdGlvbiBvciBjYXVzaW5nIHBhZ2UgcmVsb2FkcywgZS5nLjoNCiAqIGA8YSBocmVmPSIiIG5nLWNsaWNrPSJsaXN0LmFkZEl0ZW0oKSI+QWRkIEl0ZW08L2E+YA0KICovDQp2YXIgaHRtbEFuY2hvckRpcmVjdGl2ZSA9IHZhbHVlRm4oew0KICByZXN0cmljdDogJ0UnLA0KICBjb21waWxlOiBmdW5jdGlvbihlbGVtZW50LCBhdHRyKSB7DQogICAgaWYgKCFhdHRyLmhyZWYgJiYgIWF0dHIueGxpbmtIcmVmICYmICFhdHRyLm5hbWUpIHsNCiAgICAgIHJldHVybiBmdW5jdGlvbihzY29wZSwgZWxlbWVudCkgew0KICAgICAgICAvLyBTVkdBRWxlbWVudCBkb2VzIG5vdCB1c2UgdGhlIGhyZWYgYXR0cmlidXRlLCBidXQgcmF0aGVyIHRoZSAneGxpbmtIcmVmJyBhdHRyaWJ1dGUuDQogICAgICAgIHZhciBocmVmID0gdG9TdHJpbmcuY2FsbChlbGVtZW50LnByb3AoJ2hyZWYnKSkgPT09ICdbb2JqZWN0IFNWR0FuaW1hdGVkU3RyaW5nXScgPw0KICAgICAgICAgICAgICAgICAgICd4bGluazpocmVmJyA6ICdocmVmJzsNCiAgICAgICAgZWxlbWVudC5vbignY2xpY2snLCBmdW5jdGlvbihldmVudCkgew0KICAgICAgICAgIC8vIGlmIHdlIGhhdmUgbm8gaHJlZiB1cmwsIHRoZW4gZG9uJ3QgbmF2aWdhdGUgYW55d2hlcmUuDQogICAgICAgICAgaWYgKCFlbGVtZW50LmF0dHIoaHJlZikpIHsNCiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7DQogICAgICAgICAgfQ0KICAgICAgICB9KTsNCiAgICAgIH07DQogICAgfQ0KICB9DQp9KTsNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0hyZWYNCiAqIEByZXN0cmljdCBBDQogKiBAcHJpb3JpdHkgOTkNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFVzaW5nIEFuZ3VsYXIgbWFya3VwIGxpa2UgYHt7aGFzaH19YCBpbiBhbiBocmVmIGF0dHJpYnV0ZSB3aWxsDQogKiBtYWtlIHRoZSBsaW5rIGdvIHRvIHRoZSB3cm9uZyBVUkwgaWYgdGhlIHVzZXIgY2xpY2tzIGl0IGJlZm9yZQ0KICogQW5ndWxhciBoYXMgYSBjaGFuY2UgdG8gcmVwbGFjZSB0aGUgYHt7aGFzaH19YCBtYXJrdXAgd2l0aCBpdHMNCiAqIHZhbHVlLiBVbnRpbCBBbmd1bGFyIHJlcGxhY2VzIHRoZSBtYXJrdXAgdGhlIGxpbmsgd2lsbCBiZSBicm9rZW4NCiAqIGFuZCB3aWxsIG1vc3QgbGlrZWx5IHJldHVybiBhIDQwNCBlcnJvci4gVGhlIGBuZ0hyZWZgIGRpcmVjdGl2ZQ0KICogc29sdmVzIHRoaXMgcHJvYmxlbS4NCiAqDQogKiBUaGUgd3Jvbmcgd2F5IHRvIHdyaXRlIGl0Og0KICogYGBgaHRtbA0KICogPGEgaHJlZj0iaHR0cDovL3d3dy5ncmF2YXRhci5jb20vYXZhdGFyL3t7aGFzaH19Ij5saW5rMTwvYT4NCiAqIGBgYA0KICoNCiAqIFRoZSBjb3JyZWN0IHdheSB0byB3cml0ZSBpdDoNCiAqIGBgYGh0bWwNCiAqIDxhIG5nLWhyZWY9Imh0dHA6Ly93d3cuZ3JhdmF0YXIuY29tL2F2YXRhci97e2hhc2h9fSI+bGluazE8L2E+DQogKiBgYGANCiAqDQogKiBAZWxlbWVudCBBDQogKiBAcGFyYW0ge3RlbXBsYXRlfSBuZ0hyZWYgYW55IHN0cmluZyB3aGljaCBjYW4gY29udGFpbiBge3t9fWAgbWFya3VwLg0KICoNCiAqIEBleGFtcGxlDQogKiBUaGlzIGV4YW1wbGUgc2hvd3MgdmFyaW91cyBjb21iaW5hdGlvbnMgb2YgYGhyZWZgLCBgbmctaHJlZmAgYW5kIGBuZy1jbGlja2AgYXR0cmlidXRlcw0KICogaW4gbGlua3MgYW5kIHRoZWlyIGRpZmZlcmVudCBiZWhhdmlvcnM6DQogICAgPGV4YW1wbGU+DQogICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICAgPGlucHV0IG5nLW1vZGVsPSJ2YWx1ZSIgLz48YnIgLz4NCiAgICAgICAgPGEgaWQ9ImxpbmstMSIgaHJlZiBuZy1jbGljaz0idmFsdWUgPSAxIj5saW5rIDE8L2E+IChsaW5rLCBkb24ndCByZWxvYWQpPGJyIC8+DQogICAgICAgIDxhIGlkPSJsaW5rLTIiIGhyZWY9IiIgbmctY2xpY2s9InZhbHVlID0gMiI+bGluayAyPC9hPiAobGluaywgZG9uJ3QgcmVsb2FkKTxiciAvPg0KICAgICAgICA8YSBpZD0ibGluay0zIiBuZy1ocmVmPSIve3snMTIzJ319Ij5saW5rIDM8L2E+IChsaW5rLCByZWxvYWQhKTxiciAvPg0KICAgICAgICA8YSBpZD0ibGluay00IiBocmVmPSIiIG5hbWU9Inh4IiBuZy1jbGljaz0idmFsdWUgPSA0Ij5hbmNob3I8L2E+IChsaW5rLCBkb24ndCByZWxvYWQpPGJyIC8+DQogICAgICAgIDxhIGlkPSJsaW5rLTUiIG5hbWU9Inh4eCIgbmctY2xpY2s9InZhbHVlID0gNSI+YW5jaG9yPC9hPiAobm8gbGluayk8YnIgLz4NCiAgICAgICAgPGEgaWQ9ImxpbmstNiIgbmctaHJlZj0ie3t2YWx1ZX19Ij5saW5rPC9hPiAobGluaywgY2hhbmdlIGxvY2F0aW9uKQ0KICAgICAgPC9maWxlPg0KICAgICAgPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogICAgICAgIGl0KCdzaG91bGQgZXhlY3V0ZSBuZy1jbGljayBidXQgbm90IHJlbG9hZCB3aGVuIGhyZWYgd2l0aG91dCB2YWx1ZScsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgIGVsZW1lbnQoYnkuaWQoJ2xpbmstMScpKS5jbGljaygpOw0KICAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5Lm1vZGVsKCd2YWx1ZScpKS5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykpLnRvRXF1YWwoJzEnKTsNCiAgICAgICAgICBleHBlY3QoZWxlbWVudChieS5pZCgnbGluay0xJykpLmdldEF0dHJpYnV0ZSgnaHJlZicpKS50b0JlKCcnKTsNCiAgICAgICAgfSk7DQoNCiAgICAgICAgaXQoJ3Nob3VsZCBleGVjdXRlIG5nLWNsaWNrIGJ1dCBub3QgcmVsb2FkIHdoZW4gaHJlZiBlbXB0eSBzdHJpbmcnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgICBlbGVtZW50KGJ5LmlkKCdsaW5rLTInKSkuY2xpY2soKTsNCiAgICAgICAgICBleHBlY3QoZWxlbWVudChieS5tb2RlbCgndmFsdWUnKSkuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKS50b0VxdWFsKCcyJyk7DQogICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuaWQoJ2xpbmstMicpKS5nZXRBdHRyaWJ1dGUoJ2hyZWYnKSkudG9CZSgnJyk7DQogICAgICAgIH0pOw0KDQogICAgICAgIGl0KCdzaG91bGQgZXhlY3V0ZSBuZy1jbGljayBhbmQgY2hhbmdlIHVybCB3aGVuIG5nLWhyZWYgc3BlY2lmaWVkJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuaWQoJ2xpbmstMycpKS5nZXRBdHRyaWJ1dGUoJ2hyZWYnKSkudG9NYXRjaCgvXC8xMjMkLyk7DQoNCiAgICAgICAgICBlbGVtZW50KGJ5LmlkKCdsaW5rLTMnKSkuY2xpY2soKTsNCg0KICAgICAgICAgIC8vIEF0IHRoaXMgcG9pbnQsIHdlIG5hdmlnYXRlIGF3YXkgZnJvbSBhbiBBbmd1bGFyIHBhZ2UsIHNvIHdlIG5lZWQNCiAgICAgICAgICAvLyB0byB1c2UgYnJvd3Nlci5kcml2ZXIgdG8gZ2V0IHRoZSBiYXNlIHdlYmRyaXZlci4NCg0KICAgICAgICAgIGJyb3dzZXIud2FpdChmdW5jdGlvbigpIHsNCiAgICAgICAgICAgIHJldHVybiBicm93c2VyLmRyaXZlci5nZXRDdXJyZW50VXJsKCkudGhlbihmdW5jdGlvbih1cmwpIHsNCiAgICAgICAgICAgICAgcmV0dXJuIHVybC5tYXRjaCgvXC8xMjMkLyk7DQogICAgICAgICAgICB9KTsNCiAgICAgICAgICB9LCA1MDAwLCAncGFnZSBzaG91bGQgbmF2aWdhdGUgdG8gLzEyMycpOw0KICAgICAgICB9KTsNCg0KICAgICAgICB4aXQoJ3Nob3VsZCBleGVjdXRlIG5nLWNsaWNrIGJ1dCBub3QgcmVsb2FkIHdoZW4gaHJlZiBlbXB0eSBzdHJpbmcgYW5kIG5hbWUgc3BlY2lmaWVkJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgZWxlbWVudChieS5pZCgnbGluay00JykpLmNsaWNrKCk7DQogICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkubW9kZWwoJ3ZhbHVlJykpLmdldEF0dHJpYnV0ZSgndmFsdWUnKSkudG9FcXVhbCgnNCcpOw0KICAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmlkKCdsaW5rLTQnKSkuZ2V0QXR0cmlidXRlKCdocmVmJykpLnRvQmUoJycpOw0KICAgICAgICB9KTsNCg0KICAgICAgICBpdCgnc2hvdWxkIGV4ZWN1dGUgbmctY2xpY2sgYnV0IG5vdCByZWxvYWQgd2hlbiBubyBocmVmIGJ1dCBuYW1lIHNwZWNpZmllZCcsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgIGVsZW1lbnQoYnkuaWQoJ2xpbmstNScpKS5jbGljaygpOw0KICAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5Lm1vZGVsKCd2YWx1ZScpKS5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykpLnRvRXF1YWwoJzUnKTsNCiAgICAgICAgICBleHBlY3QoZWxlbWVudChieS5pZCgnbGluay01JykpLmdldEF0dHJpYnV0ZSgnaHJlZicpKS50b0JlKG51bGwpOw0KICAgICAgICB9KTsNCg0KICAgICAgICBpdCgnc2hvdWxkIG9ubHkgY2hhbmdlIHVybCB3aGVuIG9ubHkgbmctaHJlZicsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgIGVsZW1lbnQoYnkubW9kZWwoJ3ZhbHVlJykpLmNsZWFyKCk7DQogICAgICAgICAgZWxlbWVudChieS5tb2RlbCgndmFsdWUnKSkuc2VuZEtleXMoJzYnKTsNCiAgICAgICAgICBleHBlY3QoZWxlbWVudChieS5pZCgnbGluay02JykpLmdldEF0dHJpYnV0ZSgnaHJlZicpKS50b01hdGNoKC9cLzYkLyk7DQoNCiAgICAgICAgICBlbGVtZW50KGJ5LmlkKCdsaW5rLTYnKSkuY2xpY2soKTsNCg0KICAgICAgICAgIC8vIEF0IHRoaXMgcG9pbnQsIHdlIG5hdmlnYXRlIGF3YXkgZnJvbSBhbiBBbmd1bGFyIHBhZ2UsIHNvIHdlIG5lZWQNCiAgICAgICAgICAvLyB0byB1c2UgYnJvd3Nlci5kcml2ZXIgdG8gZ2V0IHRoZSBiYXNlIHdlYmRyaXZlci4NCiAgICAgICAgICBicm93c2VyLndhaXQoZnVuY3Rpb24oKSB7DQogICAgICAgICAgICByZXR1cm4gYnJvd3Nlci5kcml2ZXIuZ2V0Q3VycmVudFVybCgpLnRoZW4oZnVuY3Rpb24odXJsKSB7DQogICAgICAgICAgICAgIHJldHVybiB1cmwubWF0Y2goL1wvNiQvKTsNCiAgICAgICAgICAgIH0pOw0KICAgICAgICAgIH0sIDUwMDAsICdwYWdlIHNob3VsZCBuYXZpZ2F0ZSB0byAvNicpOw0KICAgICAgICB9KTsNCiAgICAgIDwvZmlsZT4NCiAgICA8L2V4YW1wbGU+DQogKi8NCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ1NyYw0KICogQHJlc3RyaWN0IEENCiAqIEBwcmlvcml0eSA5OQ0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVXNpbmcgQW5ndWxhciBtYXJrdXAgbGlrZSBge3toYXNofX1gIGluIGEgYHNyY2AgYXR0cmlidXRlIGRvZXNuJ3QNCiAqIHdvcmsgcmlnaHQ6IFRoZSBicm93c2VyIHdpbGwgZmV0Y2ggZnJvbSB0aGUgVVJMIHdpdGggdGhlIGxpdGVyYWwNCiAqIHRleHQgYHt7aGFzaH19YCB1bnRpbCBBbmd1bGFyIHJlcGxhY2VzIHRoZSBleHByZXNzaW9uIGluc2lkZQ0KICogYHt7aGFzaH19YC4gVGhlIGBuZ1NyY2AgZGlyZWN0aXZlIHNvbHZlcyB0aGlzIHByb2JsZW0uDQogKg0KICogVGhlIGJ1Z2d5IHdheSB0byB3cml0ZSBpdDoNCiAqIGBgYGh0bWwNCiAqIDxpbWcgc3JjPSJodHRwOi8vd3d3LmdyYXZhdGFyLmNvbS9hdmF0YXIve3toYXNofX0iLz4NCiAqIGBgYA0KICoNCiAqIFRoZSBjb3JyZWN0IHdheSB0byB3cml0ZSBpdDoNCiAqIGBgYGh0bWwNCiAqIDxpbWcgbmctc3JjPSJodHRwOi8vd3d3LmdyYXZhdGFyLmNvbS9hdmF0YXIve3toYXNofX0iLz4NCiAqIGBgYA0KICoNCiAqIEBlbGVtZW50IElNRw0KICogQHBhcmFtIHt0ZW1wbGF0ZX0gbmdTcmMgYW55IHN0cmluZyB3aGljaCBjYW4gY29udGFpbiBge3t9fWAgbWFya3VwLg0KICovDQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdTcmNzZXQNCiAqIEByZXN0cmljdCBBDQogKiBAcHJpb3JpdHkgOTkNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFVzaW5nIEFuZ3VsYXIgbWFya3VwIGxpa2UgYHt7aGFzaH19YCBpbiBhIGBzcmNzZXRgIGF0dHJpYnV0ZSBkb2Vzbid0DQogKiB3b3JrIHJpZ2h0OiBUaGUgYnJvd3NlciB3aWxsIGZldGNoIGZyb20gdGhlIFVSTCB3aXRoIHRoZSBsaXRlcmFsDQogKiB0ZXh0IGB7e2hhc2h9fWAgdW50aWwgQW5ndWxhciByZXBsYWNlcyB0aGUgZXhwcmVzc2lvbiBpbnNpZGUNCiAqIGB7e2hhc2h9fWAuIFRoZSBgbmdTcmNzZXRgIGRpcmVjdGl2ZSBzb2x2ZXMgdGhpcyBwcm9ibGVtLg0KICoNCiAqIFRoZSBidWdneSB3YXkgdG8gd3JpdGUgaXQ6DQogKiBgYGBodG1sDQogKiA8aW1nIHNyY3NldD0iaHR0cDovL3d3dy5ncmF2YXRhci5jb20vYXZhdGFyL3t7aGFzaH19IDJ4Ii8+DQogKiBgYGANCiAqDQogKiBUaGUgY29ycmVjdCB3YXkgdG8gd3JpdGUgaXQ6DQogKiBgYGBodG1sDQogKiA8aW1nIG5nLXNyY3NldD0iaHR0cDovL3d3dy5ncmF2YXRhci5jb20vYXZhdGFyL3t7aGFzaH19IDJ4Ii8+DQogKiBgYGANCiAqDQogKiBAZWxlbWVudCBJTUcNCiAqIEBwYXJhbSB7dGVtcGxhdGV9IG5nU3Jjc2V0IGFueSBzdHJpbmcgd2hpY2ggY2FuIGNvbnRhaW4gYHt7fX1gIG1hcmt1cC4NCiAqLw0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nRGlzYWJsZWQNCiAqIEByZXN0cmljdCBBDQogKiBAcHJpb3JpdHkgMTAwDQogKg0KICogQGRlc2NyaXB0aW9uDQogKg0KICogV2Ugc2hvdWxkbid0IGRvIHRoaXMsIGJlY2F1c2UgaXQgd2lsbCBtYWtlIHRoZSBidXR0b24gZW5hYmxlZCBvbiBDaHJvbWUvRmlyZWZveCBidXQgbm90IG9uIElFOCBhbmQgb2xkZXIgSUVzOg0KICogYGBgaHRtbA0KICogPGRpdiBuZy1pbml0PSJzY29wZSA9IHsgaXNEaXNhYmxlZDogZmFsc2UgfSI+DQogKiAgPGJ1dHRvbiBkaXNhYmxlZD0ie3tzY29wZS5pc0Rpc2FibGVkfX0iPkRpc2FibGVkPC9idXR0b24+DQogKiA8L2Rpdj4NCiAqIGBgYA0KICoNCiAqIFRoZSBIVE1MIHNwZWNpZmljYXRpb24gZG9lcyBub3QgcmVxdWlyZSBicm93c2VycyB0byBwcmVzZXJ2ZSB0aGUgdmFsdWVzIG9mIGJvb2xlYW4gYXR0cmlidXRlcw0KICogc3VjaCBhcyBkaXNhYmxlZC4gKFRoZWlyIHByZXNlbmNlIG1lYW5zIHRydWUgYW5kIHRoZWlyIGFic2VuY2UgbWVhbnMgZmFsc2UuKQ0KICogSWYgd2UgcHV0IGFuIEFuZ3VsYXIgaW50ZXJwb2xhdGlvbiBleHByZXNzaW9uIGludG8gc3VjaCBhbiBhdHRyaWJ1dGUgdGhlbiB0aGUNCiAqIGJpbmRpbmcgaW5mb3JtYXRpb24gd291bGQgYmUgbG9zdCB3aGVuIHRoZSBicm93c2VyIHJlbW92ZXMgdGhlIGF0dHJpYnV0ZS4NCiAqIFRoZSBgbmdEaXNhYmxlZGAgZGlyZWN0aXZlIHNvbHZlcyB0aGlzIHByb2JsZW0gZm9yIHRoZSBgZGlzYWJsZWRgIGF0dHJpYnV0ZS4NCiAqIFRoaXMgY29tcGxlbWVudGFyeSBkaXJlY3RpdmUgaXMgbm90IHJlbW92ZWQgYnkgdGhlIGJyb3dzZXIgYW5kIHNvIHByb3ZpZGVzDQogKiBhIHBlcm1hbmVudCByZWxpYWJsZSBwbGFjZSB0byBzdG9yZSB0aGUgYmluZGluZyBpbmZvcm1hdGlvbi4NCiAqDQogKiBAZXhhbXBsZQ0KICAgIDxleGFtcGxlPg0KICAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgIENsaWNrIG1lIHRvIHRvZ2dsZTogPGlucHV0IHR5cGU9ImNoZWNrYm94IiBuZy1tb2RlbD0iY2hlY2tlZCI+PGJyLz4NCiAgICAgICAgPGJ1dHRvbiBuZy1tb2RlbD0iYnV0dG9uIiBuZy1kaXNhYmxlZD0iY2hlY2tlZCI+QnV0dG9uPC9idXR0b24+DQogICAgICA8L2ZpbGU+DQogICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICAgaXQoJ3Nob3VsZCB0b2dnbGUgYnV0dG9uJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuY3NzKCdidXR0b24nKSkuZ2V0QXR0cmlidXRlKCdkaXNhYmxlZCcpKS50b0JlRmFsc3koKTsNCiAgICAgICAgICBlbGVtZW50KGJ5Lm1vZGVsKCdjaGVja2VkJykpLmNsaWNrKCk7DQogICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuY3NzKCdidXR0b24nKSkuZ2V0QXR0cmlidXRlKCdkaXNhYmxlZCcpKS50b0JlVHJ1dGh5KCk7DQogICAgICAgIH0pOw0KICAgICAgPC9maWxlPg0KICAgIDwvZXhhbXBsZT4NCiAqDQogKiBAZWxlbWVudCBJTlBVVA0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ0Rpc2FibGVkIElmIHRoZSB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBleHByZXNzaW9ufSBpcyB0cnV0aHksDQogKiAgICAgdGhlbiBzcGVjaWFsIGF0dHJpYnV0ZSAiZGlzYWJsZWQiIHdpbGwgYmUgc2V0IG9uIHRoZSBlbGVtZW50DQogKi8NCg0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nQ2hlY2tlZA0KICogQHJlc3RyaWN0IEENCiAqIEBwcmlvcml0eSAxMDANCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFRoZSBIVE1MIHNwZWNpZmljYXRpb24gZG9lcyBub3QgcmVxdWlyZSBicm93c2VycyB0byBwcmVzZXJ2ZSB0aGUgdmFsdWVzIG9mIGJvb2xlYW4gYXR0cmlidXRlcw0KICogc3VjaCBhcyBjaGVja2VkLiAoVGhlaXIgcHJlc2VuY2UgbWVhbnMgdHJ1ZSBhbmQgdGhlaXIgYWJzZW5jZSBtZWFucyBmYWxzZS4pDQogKiBJZiB3ZSBwdXQgYW4gQW5ndWxhciBpbnRlcnBvbGF0aW9uIGV4cHJlc3Npb24gaW50byBzdWNoIGFuIGF0dHJpYnV0ZSB0aGVuIHRoZQ0KICogYmluZGluZyBpbmZvcm1hdGlvbiB3b3VsZCBiZSBsb3N0IHdoZW4gdGhlIGJyb3dzZXIgcmVtb3ZlcyB0aGUgYXR0cmlidXRlLg0KICogVGhlIGBuZ0NoZWNrZWRgIGRpcmVjdGl2ZSBzb2x2ZXMgdGhpcyBwcm9ibGVtIGZvciB0aGUgYGNoZWNrZWRgIGF0dHJpYnV0ZS4NCiAqIFRoaXMgY29tcGxlbWVudGFyeSBkaXJlY3RpdmUgaXMgbm90IHJlbW92ZWQgYnkgdGhlIGJyb3dzZXIgYW5kIHNvIHByb3ZpZGVzDQogKiBhIHBlcm1hbmVudCByZWxpYWJsZSBwbGFjZSB0byBzdG9yZSB0aGUgYmluZGluZyBpbmZvcm1hdGlvbi4NCiAqIEBleGFtcGxlDQogICAgPGV4YW1wbGU+DQogICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICAgQ2hlY2sgbWUgdG8gY2hlY2sgYm90aDogPGlucHV0IHR5cGU9ImNoZWNrYm94IiBuZy1tb2RlbD0ibWFzdGVyIj48YnIvPg0KICAgICAgICA8aW5wdXQgaWQ9ImNoZWNrU2xhdmUiIHR5cGU9ImNoZWNrYm94IiBuZy1jaGVja2VkPSJtYXN0ZXIiPg0KICAgICAgPC9maWxlPg0KICAgICAgPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogICAgICAgIGl0KCdzaG91bGQgY2hlY2sgYm90aCBjaGVja0JveGVzJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuaWQoJ2NoZWNrU2xhdmUnKSkuZ2V0QXR0cmlidXRlKCdjaGVja2VkJykpLnRvQmVGYWxzeSgpOw0KICAgICAgICAgIGVsZW1lbnQoYnkubW9kZWwoJ21hc3RlcicpKS5jbGljaygpOw0KICAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmlkKCdjaGVja1NsYXZlJykpLmdldEF0dHJpYnV0ZSgnY2hlY2tlZCcpKS50b0JlVHJ1dGh5KCk7DQogICAgICAgIH0pOw0KICAgICAgPC9maWxlPg0KICAgIDwvZXhhbXBsZT4NCiAqDQogKiBAZWxlbWVudCBJTlBVVA0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ0NoZWNrZWQgSWYgdGhlIHtAbGluayBndWlkZS9leHByZXNzaW9uIGV4cHJlc3Npb259IGlzIHRydXRoeSwNCiAqICAgICB0aGVuIHNwZWNpYWwgYXR0cmlidXRlICJjaGVja2VkIiB3aWxsIGJlIHNldCBvbiB0aGUgZWxlbWVudA0KICovDQoNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ1JlYWRvbmx5DQogKiBAcmVzdHJpY3QgQQ0KICogQHByaW9yaXR5IDEwMA0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlIEhUTUwgc3BlY2lmaWNhdGlvbiBkb2VzIG5vdCByZXF1aXJlIGJyb3dzZXJzIHRvIHByZXNlcnZlIHRoZSB2YWx1ZXMgb2YgYm9vbGVhbiBhdHRyaWJ1dGVzDQogKiBzdWNoIGFzIHJlYWRvbmx5LiAoVGhlaXIgcHJlc2VuY2UgbWVhbnMgdHJ1ZSBhbmQgdGhlaXIgYWJzZW5jZSBtZWFucyBmYWxzZS4pDQogKiBJZiB3ZSBwdXQgYW4gQW5ndWxhciBpbnRlcnBvbGF0aW9uIGV4cHJlc3Npb24gaW50byBzdWNoIGFuIGF0dHJpYnV0ZSB0aGVuIHRoZQ0KICogYmluZGluZyBpbmZvcm1hdGlvbiB3b3VsZCBiZSBsb3N0IHdoZW4gdGhlIGJyb3dzZXIgcmVtb3ZlcyB0aGUgYXR0cmlidXRlLg0KICogVGhlIGBuZ1JlYWRvbmx5YCBkaXJlY3RpdmUgc29sdmVzIHRoaXMgcHJvYmxlbSBmb3IgdGhlIGByZWFkb25seWAgYXR0cmlidXRlLg0KICogVGhpcyBjb21wbGVtZW50YXJ5IGRpcmVjdGl2ZSBpcyBub3QgcmVtb3ZlZCBieSB0aGUgYnJvd3NlciBhbmQgc28gcHJvdmlkZXMNCiAqIGEgcGVybWFuZW50IHJlbGlhYmxlIHBsYWNlIHRvIHN0b3JlIHRoZSBiaW5kaW5nIGluZm9ybWF0aW9uLg0KICogQGV4YW1wbGUNCiAgICA8ZXhhbXBsZT4NCiAgICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgICBDaGVjayBtZSB0byBtYWtlIHRleHQgcmVhZG9ubHk6IDxpbnB1dCB0eXBlPSJjaGVja2JveCIgbmctbW9kZWw9ImNoZWNrZWQiPjxici8+DQogICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBuZy1yZWFkb25seT0iY2hlY2tlZCIgdmFsdWU9IkknbSBBbmd1bGFyIi8+DQogICAgICA8L2ZpbGU+DQogICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICAgaXQoJ3Nob3VsZCB0b2dnbGUgcmVhZG9ubHkgYXR0cicsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmNzcygnW3R5cGU9InRleHQiXScpKS5nZXRBdHRyaWJ1dGUoJ3JlYWRvbmx5JykpLnRvQmVGYWxzeSgpOw0KICAgICAgICAgIGVsZW1lbnQoYnkubW9kZWwoJ2NoZWNrZWQnKSkuY2xpY2soKTsNCiAgICAgICAgICBleHBlY3QoZWxlbWVudChieS5jc3MoJ1t0eXBlPSJ0ZXh0Il0nKSkuZ2V0QXR0cmlidXRlKCdyZWFkb25seScpKS50b0JlVHJ1dGh5KCk7DQogICAgICAgIH0pOw0KICAgICAgPC9maWxlPg0KICAgIDwvZXhhbXBsZT4NCiAqDQogKiBAZWxlbWVudCBJTlBVVA0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ1JlYWRvbmx5IElmIHRoZSB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBleHByZXNzaW9ufSBpcyB0cnV0aHksDQogKiAgICAgdGhlbiBzcGVjaWFsIGF0dHJpYnV0ZSAicmVhZG9ubHkiIHdpbGwgYmUgc2V0IG9uIHRoZSBlbGVtZW50DQogKi8NCg0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nU2VsZWN0ZWQNCiAqIEByZXN0cmljdCBBDQogKiBAcHJpb3JpdHkgMTAwDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBUaGUgSFRNTCBzcGVjaWZpY2F0aW9uIGRvZXMgbm90IHJlcXVpcmUgYnJvd3NlcnMgdG8gcHJlc2VydmUgdGhlIHZhbHVlcyBvZiBib29sZWFuIGF0dHJpYnV0ZXMNCiAqIHN1Y2ggYXMgc2VsZWN0ZWQuIChUaGVpciBwcmVzZW5jZSBtZWFucyB0cnVlIGFuZCB0aGVpciBhYnNlbmNlIG1lYW5zIGZhbHNlLikNCiAqIElmIHdlIHB1dCBhbiBBbmd1bGFyIGludGVycG9sYXRpb24gZXhwcmVzc2lvbiBpbnRvIHN1Y2ggYW4gYXR0cmlidXRlIHRoZW4gdGhlDQogKiBiaW5kaW5nIGluZm9ybWF0aW9uIHdvdWxkIGJlIGxvc3Qgd2hlbiB0aGUgYnJvd3NlciByZW1vdmVzIHRoZSBhdHRyaWJ1dGUuDQogKiBUaGUgYG5nU2VsZWN0ZWRgIGRpcmVjdGl2ZSBzb2x2ZXMgdGhpcyBwcm9ibGVtIGZvciB0aGUgYHNlbGVjdGVkYCBhdHRyaWJ1dGUuDQogKiBUaGlzIGNvbXBsZW1lbnRhcnkgZGlyZWN0aXZlIGlzIG5vdCByZW1vdmVkIGJ5IHRoZSBicm93c2VyIGFuZCBzbyBwcm92aWRlcw0KICogYSBwZXJtYW5lbnQgcmVsaWFibGUgcGxhY2UgdG8gc3RvcmUgdGhlIGJpbmRpbmcgaW5mb3JtYXRpb24uDQogKg0KICogQGV4YW1wbGUNCiAgICA8ZXhhbXBsZT4NCiAgICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgICBDaGVjayBtZSB0byBzZWxlY3Q6IDxpbnB1dCB0eXBlPSJjaGVja2JveCIgbmctbW9kZWw9InNlbGVjdGVkIj48YnIvPg0KICAgICAgICA8c2VsZWN0Pg0KICAgICAgICAgIDxvcHRpb24+SGVsbG8hPC9vcHRpb24+DQogICAgICAgICAgPG9wdGlvbiBpZD0iZ3JlZXQiIG5nLXNlbGVjdGVkPSJzZWxlY3RlZCI+R3JlZXRpbmdzITwvb3B0aW9uPg0KICAgICAgICA8L3NlbGVjdD4NCiAgICAgIDwvZmlsZT4NCiAgICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgICBpdCgnc2hvdWxkIHNlbGVjdCBHcmVldGluZ3MhJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuaWQoJ2dyZWV0JykpLmdldEF0dHJpYnV0ZSgnc2VsZWN0ZWQnKSkudG9CZUZhbHN5KCk7DQogICAgICAgICAgZWxlbWVudChieS5tb2RlbCgnc2VsZWN0ZWQnKSkuY2xpY2soKTsNCiAgICAgICAgICBleHBlY3QoZWxlbWVudChieS5pZCgnZ3JlZXQnKSkuZ2V0QXR0cmlidXRlKCdzZWxlY3RlZCcpKS50b0JlVHJ1dGh5KCk7DQogICAgICAgIH0pOw0KICAgICAgPC9maWxlPg0KICAgIDwvZXhhbXBsZT4NCiAqDQogKiBAZWxlbWVudCBPUFRJT04NCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdTZWxlY3RlZCBJZiB0aGUge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gZXhwcmVzc2lvbn0gaXMgdHJ1dGh5LA0KICogICAgIHRoZW4gc3BlY2lhbCBhdHRyaWJ1dGUgInNlbGVjdGVkIiB3aWxsIGJlIHNldCBvbiB0aGUgZWxlbWVudA0KICovDQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdPcGVuDQogKiBAcmVzdHJpY3QgQQ0KICogQHByaW9yaXR5IDEwMA0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlIEhUTUwgc3BlY2lmaWNhdGlvbiBkb2VzIG5vdCByZXF1aXJlIGJyb3dzZXJzIHRvIHByZXNlcnZlIHRoZSB2YWx1ZXMgb2YgYm9vbGVhbiBhdHRyaWJ1dGVzDQogKiBzdWNoIGFzIG9wZW4uIChUaGVpciBwcmVzZW5jZSBtZWFucyB0cnVlIGFuZCB0aGVpciBhYnNlbmNlIG1lYW5zIGZhbHNlLikNCiAqIElmIHdlIHB1dCBhbiBBbmd1bGFyIGludGVycG9sYXRpb24gZXhwcmVzc2lvbiBpbnRvIHN1Y2ggYW4gYXR0cmlidXRlIHRoZW4gdGhlDQogKiBiaW5kaW5nIGluZm9ybWF0aW9uIHdvdWxkIGJlIGxvc3Qgd2hlbiB0aGUgYnJvd3NlciByZW1vdmVzIHRoZSBhdHRyaWJ1dGUuDQogKiBUaGUgYG5nT3BlbmAgZGlyZWN0aXZlIHNvbHZlcyB0aGlzIHByb2JsZW0gZm9yIHRoZSBgb3BlbmAgYXR0cmlidXRlLg0KICogVGhpcyBjb21wbGVtZW50YXJ5IGRpcmVjdGl2ZSBpcyBub3QgcmVtb3ZlZCBieSB0aGUgYnJvd3NlciBhbmQgc28gcHJvdmlkZXMNCiAqIGEgcGVybWFuZW50IHJlbGlhYmxlIHBsYWNlIHRvIHN0b3JlIHRoZSBiaW5kaW5nIGluZm9ybWF0aW9uLg0KICogQGV4YW1wbGUNCiAgICAgPGV4YW1wbGU+DQogICAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgICBDaGVjayBtZSBjaGVjayBtdWx0aXBsZTogPGlucHV0IHR5cGU9ImNoZWNrYm94IiBuZy1tb2RlbD0ib3BlbiI+PGJyLz4NCiAgICAgICAgIDxkZXRhaWxzIGlkPSJkZXRhaWxzIiBuZy1vcGVuPSJvcGVuIj4NCiAgICAgICAgICAgIDxzdW1tYXJ5PlNob3cvSGlkZSBtZTwvc3VtbWFyeT4NCiAgICAgICAgIDwvZGV0YWlscz4NCiAgICAgICA8L2ZpbGU+DQogICAgICAgPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogICAgICAgICBpdCgnc2hvdWxkIHRvZ2dsZSBvcGVuJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmlkKCdkZXRhaWxzJykpLmdldEF0dHJpYnV0ZSgnb3BlbicpKS50b0JlRmFsc3koKTsNCiAgICAgICAgICAgZWxlbWVudChieS5tb2RlbCgnb3BlbicpKS5jbGljaygpOw0KICAgICAgICAgICBleHBlY3QoZWxlbWVudChieS5pZCgnZGV0YWlscycpKS5nZXRBdHRyaWJ1dGUoJ29wZW4nKSkudG9CZVRydXRoeSgpOw0KICAgICAgICAgfSk7DQogICAgICAgPC9maWxlPg0KICAgICA8L2V4YW1wbGU+DQogKg0KICogQGVsZW1lbnQgREVUQUlMUw0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ09wZW4gSWYgdGhlIHtAbGluayBndWlkZS9leHByZXNzaW9uIGV4cHJlc3Npb259IGlzIHRydXRoeSwNCiAqICAgICB0aGVuIHNwZWNpYWwgYXR0cmlidXRlICJvcGVuIiB3aWxsIGJlIHNldCBvbiB0aGUgZWxlbWVudA0KICovDQoNCnZhciBuZ0F0dHJpYnV0ZUFsaWFzRGlyZWN0aXZlcyA9IHt9Ow0KDQoNCi8vIGJvb2xlYW4gYXR0cnMgYXJlIGV2YWx1YXRlZA0KZm9yRWFjaChCT09MRUFOX0FUVFIsIGZ1bmN0aW9uKHByb3BOYW1lLCBhdHRyTmFtZSkgew0KICAvLyBiaW5kaW5nIHRvIG11bHRpcGxlIGlzIG5vdCBzdXBwb3J0ZWQNCiAgaWYgKHByb3BOYW1lID09ICJtdWx0aXBsZSIpIHJldHVybjsNCg0KICB2YXIgbm9ybWFsaXplZCA9IGRpcmVjdGl2ZU5vcm1hbGl6ZSgnbmctJyArIGF0dHJOYW1lKTsNCiAgbmdBdHRyaWJ1dGVBbGlhc0RpcmVjdGl2ZXNbbm9ybWFsaXplZF0gPSBmdW5jdGlvbigpIHsNCiAgICByZXR1cm4gew0KICAgICAgcmVzdHJpY3Q6ICdBJywNCiAgICAgIHByaW9yaXR5OiAxMDAsDQogICAgICBsaW5rOiBmdW5jdGlvbihzY29wZSwgZWxlbWVudCwgYXR0cikgew0KICAgICAgICBzY29wZS4kd2F0Y2goYXR0cltub3JtYWxpemVkXSwgZnVuY3Rpb24gbmdCb29sZWFuQXR0cldhdGNoQWN0aW9uKHZhbHVlKSB7DQogICAgICAgICAgYXR0ci4kc2V0KGF0dHJOYW1lLCAhIXZhbHVlKTsNCiAgICAgICAgfSk7DQogICAgICB9DQogICAgfTsNCiAgfTsNCn0pOw0KDQovLyBhbGlhc2VkIGlucHV0IGF0dHJzIGFyZSBldmFsdWF0ZWQNCmZvckVhY2goQUxJQVNFRF9BVFRSLCBmdW5jdGlvbihodG1sQXR0ciwgbmdBdHRyKSB7DQogIG5nQXR0cmlidXRlQWxpYXNEaXJlY3RpdmVzW25nQXR0cl0gPSBmdW5jdGlvbigpIHsNCiAgICByZXR1cm4gew0KICAgICAgcHJpb3JpdHk6IDEwMCwNCiAgICAgIGxpbms6IGZ1bmN0aW9uKHNjb3BlLCBlbGVtZW50LCBhdHRyKSB7DQogICAgICAgIC8vc3BlY2lhbCBjYXNlIG5nUGF0dGVybiB3aGVuIGEgbGl0ZXJhbCByZWd1bGFyIGV4cHJlc3Npb24gdmFsdWUNCiAgICAgICAgLy9pcyB1c2VkIGFzIHRoZSBleHByZXNzaW9uICh0aGlzIHdheSB3ZSBkb24ndCBoYXZlIHRvIHdhdGNoIGFueXRoaW5nKS4NCiAgICAgICAgaWYgKG5nQXR0ciA9PT0gIm5nUGF0dGVybiIgJiYgYXR0ci5uZ1BhdHRlcm4uY2hhckF0KDApID09ICIvIikgew0KICAgICAgICAgIHZhciBtYXRjaCA9IGF0dHIubmdQYXR0ZXJuLm1hdGNoKFJFR0VYX1NUUklOR19SRUdFWFApOw0KICAgICAgICAgIGlmIChtYXRjaCkgew0KICAgICAgICAgICAgYXR0ci4kc2V0KCJuZ1BhdHRlcm4iLCBuZXcgUmVnRXhwKG1hdGNoWzFdLCBtYXRjaFsyXSkpOw0KICAgICAgICAgICAgcmV0dXJuOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIHNjb3BlLiR3YXRjaChhdHRyW25nQXR0cl0sIGZ1bmN0aW9uIG5nQXR0ckFsaWFzV2F0Y2hBY3Rpb24odmFsdWUpIHsNCiAgICAgICAgICBhdHRyLiRzZXQobmdBdHRyLCB2YWx1ZSk7DQogICAgICAgIH0pOw0KICAgICAgfQ0KICAgIH07DQogIH07DQp9KTsNCg0KLy8gbmctc3JjLCBuZy1zcmNzZXQsIG5nLWhyZWYgYXJlIGludGVycG9sYXRlZA0KZm9yRWFjaChbJ3NyYycsICdzcmNzZXQnLCAnaHJlZiddLCBmdW5jdGlvbihhdHRyTmFtZSkgew0KICB2YXIgbm9ybWFsaXplZCA9IGRpcmVjdGl2ZU5vcm1hbGl6ZSgnbmctJyArIGF0dHJOYW1lKTsNCiAgbmdBdHRyaWJ1dGVBbGlhc0RpcmVjdGl2ZXNbbm9ybWFsaXplZF0gPSBmdW5jdGlvbigpIHsNCiAgICByZXR1cm4gew0KICAgICAgcHJpb3JpdHk6IDk5LCAvLyBpdCBuZWVkcyB0byBydW4gYWZ0ZXIgdGhlIGF0dHJpYnV0ZXMgYXJlIGludGVycG9sYXRlZA0KICAgICAgbGluazogZnVuY3Rpb24oc2NvcGUsIGVsZW1lbnQsIGF0dHIpIHsNCiAgICAgICAgdmFyIHByb3BOYW1lID0gYXR0ck5hbWUsDQogICAgICAgICAgICBuYW1lID0gYXR0ck5hbWU7DQoNCiAgICAgICAgaWYgKGF0dHJOYW1lID09PSAnaHJlZicgJiYNCiAgICAgICAgICAgIHRvU3RyaW5nLmNhbGwoZWxlbWVudC5wcm9wKCdocmVmJykpID09PSAnW29iamVjdCBTVkdBbmltYXRlZFN0cmluZ10nKSB7DQogICAgICAgICAgbmFtZSA9ICd4bGlua0hyZWYnOw0KICAgICAgICAgIGF0dHIuJGF0dHJbbmFtZV0gPSAneGxpbms6aHJlZic7DQogICAgICAgICAgcHJvcE5hbWUgPSBudWxsOw0KICAgICAgICB9DQoNCiAgICAgICAgYXR0ci4kb2JzZXJ2ZShub3JtYWxpemVkLCBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICAgIGlmICghdmFsdWUpIHsNCiAgICAgICAgICAgIGlmIChhdHRyTmFtZSA9PT0gJ2hyZWYnKSB7DQogICAgICAgICAgICAgIGF0dHIuJHNldChuYW1lLCBudWxsKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIHJldHVybjsNCiAgICAgICAgICB9DQoNCiAgICAgICAgICBhdHRyLiRzZXQobmFtZSwgdmFsdWUpOw0KDQogICAgICAgICAgLy8gb24gSUUsIGlmICJuZzpzcmMiIGRpcmVjdGl2ZSBkZWNsYXJhdGlvbiBpcyB1c2VkIGFuZCAic3JjIiBhdHRyaWJ1dGUgZG9lc24ndCBleGlzdA0KICAgICAgICAgIC8vIHRoZW4gY2FsbGluZyBlbGVtZW50LnNldEF0dHJpYnV0ZSgnc3JjJywgJ2ZvbycpIGRvZXNuJ3QgZG8gYW55dGhpbmcsIHNvIHdlIG5lZWQNCiAgICAgICAgICAvLyB0byBzZXQgdGhlIHByb3BlcnR5IGFzIHdlbGwgdG8gYWNoaWV2ZSB0aGUgZGVzaXJlZCBlZmZlY3QuDQogICAgICAgICAgLy8gd2UgdXNlIGF0dHJbYXR0ck5hbWVdIHZhbHVlIHNpbmNlICRzZXQgY2FuIHNhbml0aXplIHRoZSB1cmwuDQogICAgICAgICAgaWYgKG1zaWUgJiYgcHJvcE5hbWUpIGVsZW1lbnQucHJvcChwcm9wTmFtZSwgYXR0cltuYW1lXSk7DQogICAgICAgIH0pOw0KICAgICAgfQ0KICAgIH07DQogIH07DQp9KTsNCg0KLyogZ2xvYmFsIC1udWxsRm9ybUN0cmwsIC1TVUJNSVRURURfQ0xBU1MsIGFkZFNldFZhbGlkaXR5TWV0aG9kOiB0cnVlDQogKi8NCnZhciBudWxsRm9ybUN0cmwgPSB7DQogICRhZGRDb250cm9sOiBub29wLA0KICAkJHJlbmFtZUNvbnRyb2w6IG51bGxGb3JtUmVuYW1lQ29udHJvbCwNCiAgJHJlbW92ZUNvbnRyb2w6IG5vb3AsDQogICRzZXRWYWxpZGl0eTogbm9vcCwNCiAgJHNldERpcnR5OiBub29wLA0KICAkc2V0UHJpc3RpbmU6IG5vb3AsDQogICRzZXRTdWJtaXR0ZWQ6IG5vb3ANCn0sDQpTVUJNSVRURURfQ0xBU1MgPSAnbmctc3VibWl0dGVkJzsNCg0KZnVuY3Rpb24gbnVsbEZvcm1SZW5hbWVDb250cm9sKGNvbnRyb2wsIG5hbWUpIHsNCiAgY29udHJvbC4kbmFtZSA9IG5hbWU7DQp9DQoNCi8qKg0KICogQG5nZG9jIHR5cGUNCiAqIEBuYW1lIGZvcm0uRm9ybUNvbnRyb2xsZXINCiAqDQogKiBAcHJvcGVydHkge2Jvb2xlYW59ICRwcmlzdGluZSBUcnVlIGlmIHVzZXIgaGFzIG5vdCBpbnRlcmFjdGVkIHdpdGggdGhlIGZvcm0geWV0Lg0KICogQHByb3BlcnR5IHtib29sZWFufSAkZGlydHkgVHJ1ZSBpZiB1c2VyIGhhcyBhbHJlYWR5IGludGVyYWN0ZWQgd2l0aCB0aGUgZm9ybS4NCiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gJHZhbGlkIFRydWUgaWYgYWxsIG9mIHRoZSBjb250YWluaW5nIGZvcm1zIGFuZCBjb250cm9scyBhcmUgdmFsaWQuDQogKiBAcHJvcGVydHkge2Jvb2xlYW59ICRpbnZhbGlkIFRydWUgaWYgYXQgbGVhc3Qgb25lIGNvbnRhaW5pbmcgY29udHJvbCBvciBmb3JtIGlzIGludmFsaWQuDQogKiBAcHJvcGVydHkge2Jvb2xlYW59ICRzdWJtaXR0ZWQgVHJ1ZSBpZiB1c2VyIGhhcyBzdWJtaXR0ZWQgdGhlIGZvcm0gZXZlbiBpZiBpdHMgaW52YWxpZC4NCiAqDQogKiBAcHJvcGVydHkge09iamVjdH0gJGVycm9yIElzIGFuIG9iamVjdCBoYXNoLCBjb250YWluaW5nIHJlZmVyZW5jZXMgdG8gY29udHJvbHMgb3INCiAqICBmb3JtcyB3aXRoIGZhaWxpbmcgdmFsaWRhdG9ycywgd2hlcmU6DQogKg0KICogIC0ga2V5cyBhcmUgdmFsaWRhdGlvbiB0b2tlbnMgKGVycm9yIG5hbWVzKSwNCiAqICAtIHZhbHVlcyBhcmUgYXJyYXlzIG9mIGNvbnRyb2xzIG9yIGZvcm1zIHRoYXQgaGF2ZSBhIGZhaWxpbmcgdmFsaWRhdG9yIGZvciBnaXZlbiBlcnJvciBuYW1lLg0KICoNCiAqICBCdWlsdC1pbiB2YWxpZGF0aW9uIHRva2VuczoNCiAqDQogKiAgLSBgZW1haWxgDQogKiAgLSBgbWF4YA0KICogIC0gYG1heGxlbmd0aGANCiAqICAtIGBtaW5gDQogKiAgLSBgbWlubGVuZ3RoYA0KICogIC0gYG51bWJlcmANCiAqICAtIGBwYXR0ZXJuYA0KICogIC0gYHJlcXVpcmVkYA0KICogIC0gYHVybGANCiAqICAtIGBkYXRlYA0KICogIC0gYGRhdGV0aW1lbG9jYWxgDQogKiAgLSBgdGltZWANCiAqICAtIGB3ZWVrYA0KICogIC0gYG1vbnRoYA0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogYEZvcm1Db250cm9sbGVyYCBrZWVwcyB0cmFjayBvZiBhbGwgaXRzIGNvbnRyb2xzIGFuZCBuZXN0ZWQgZm9ybXMgYXMgd2VsbCBhcyB0aGUgc3RhdGUgb2YgdGhlbSwNCiAqIHN1Y2ggYXMgYmVpbmcgdmFsaWQvaW52YWxpZCBvciBkaXJ0eS9wcmlzdGluZS4NCiAqDQogKiBFYWNoIHtAbGluayBuZy5kaXJlY3RpdmU6Zm9ybSBmb3JtfSBkaXJlY3RpdmUgY3JlYXRlcyBhbiBpbnN0YW5jZQ0KICogb2YgYEZvcm1Db250cm9sbGVyYC4NCiAqDQogKi8NCi8vYXNrcyBmb3IgJHNjb3BlIHRvIGZvb2wgdGhlIEJDIGNvbnRyb2xsZXIgbW9kdWxlDQpGb3JtQ29udHJvbGxlci4kaW5qZWN0ID0gWyckZWxlbWVudCcsICckYXR0cnMnLCAnJHNjb3BlJywgJyRhbmltYXRlJywgJyRpbnRlcnBvbGF0ZSddOw0KZnVuY3Rpb24gRm9ybUNvbnRyb2xsZXIoZWxlbWVudCwgYXR0cnMsICRzY29wZSwgJGFuaW1hdGUsICRpbnRlcnBvbGF0ZSkgew0KICB2YXIgZm9ybSA9IHRoaXMsDQogICAgICBjb250cm9scyA9IFtdOw0KDQogIHZhciBwYXJlbnRGb3JtID0gZm9ybS4kJHBhcmVudEZvcm0gPSBlbGVtZW50LnBhcmVudCgpLmNvbnRyb2xsZXIoJ2Zvcm0nKSB8fCBudWxsRm9ybUN0cmw7DQoNCiAgLy8gaW5pdCBzdGF0ZQ0KICBmb3JtLiRlcnJvciA9IHt9Ow0KICBmb3JtLiQkc3VjY2VzcyA9IHt9Ow0KICBmb3JtLiRwZW5kaW5nID0gdW5kZWZpbmVkOw0KICBmb3JtLiRuYW1lID0gJGludGVycG9sYXRlKGF0dHJzLm5hbWUgfHwgYXR0cnMubmdGb3JtIHx8ICcnKSgkc2NvcGUpOw0KICBmb3JtLiRkaXJ0eSA9IGZhbHNlOw0KICBmb3JtLiRwcmlzdGluZSA9IHRydWU7DQogIGZvcm0uJHZhbGlkID0gdHJ1ZTsNCiAgZm9ybS4kaW52YWxpZCA9IGZhbHNlOw0KICBmb3JtLiRzdWJtaXR0ZWQgPSBmYWxzZTsNCg0KICBwYXJlbnRGb3JtLiRhZGRDb250cm9sKGZvcm0pOw0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lIGZvcm0uRm9ybUNvbnRyb2xsZXIjJHJvbGxiYWNrVmlld1ZhbHVlDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBSb2xsYmFjayBhbGwgZm9ybSBjb250cm9scyBwZW5kaW5nIHVwZGF0ZXMgdG8gdGhlIGAkbW9kZWxWYWx1ZWAuDQogICAqDQogICAqIFVwZGF0ZXMgbWF5IGJlIHBlbmRpbmcgYnkgYSBkZWJvdW5jZWQgZXZlbnQgb3IgYmVjYXVzZSB0aGUgaW5wdXQgaXMgd2FpdGluZyBmb3IgYSBzb21lIGZ1dHVyZQ0KICAgKiBldmVudCBkZWZpbmVkIGluIGBuZy1tb2RlbC1vcHRpb25zYC4gVGhpcyBtZXRob2QgaXMgdHlwaWNhbGx5IG5lZWRlZCBieSB0aGUgcmVzZXQgYnV0dG9uIG9mDQogICAqIGEgZm9ybSB0aGF0IHVzZXMgYG5nLW1vZGVsLW9wdGlvbnNgIHRvIHBlbmQgdXBkYXRlcy4NCiAgICovDQogIGZvcm0uJHJvbGxiYWNrVmlld1ZhbHVlID0gZnVuY3Rpb24oKSB7DQogICAgZm9yRWFjaChjb250cm9scywgZnVuY3Rpb24oY29udHJvbCkgew0KICAgICAgY29udHJvbC4kcm9sbGJhY2tWaWV3VmFsdWUoKTsNCiAgICB9KTsNCiAgfTsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSBmb3JtLkZvcm1Db250cm9sbGVyIyRjb21taXRWaWV3VmFsdWUNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIENvbW1pdCBhbGwgZm9ybSBjb250cm9scyBwZW5kaW5nIHVwZGF0ZXMgdG8gdGhlIGAkbW9kZWxWYWx1ZWAuDQogICAqDQogICAqIFVwZGF0ZXMgbWF5IGJlIHBlbmRpbmcgYnkgYSBkZWJvdW5jZWQgZXZlbnQgb3IgYmVjYXVzZSB0aGUgaW5wdXQgaXMgd2FpdGluZyBmb3IgYSBzb21lIGZ1dHVyZQ0KICAgKiBldmVudCBkZWZpbmVkIGluIGBuZy1tb2RlbC1vcHRpb25zYC4gVGhpcyBtZXRob2QgaXMgcmFyZWx5IG5lZWRlZCBhcyBgTmdNb2RlbENvbnRyb2xsZXJgDQogICAqIHVzdWFsbHkgaGFuZGxlcyBjYWxsaW5nIHRoaXMgaW4gcmVzcG9uc2UgdG8gaW5wdXQgZXZlbnRzLg0KICAgKi8NCiAgZm9ybS4kY29tbWl0Vmlld1ZhbHVlID0gZnVuY3Rpb24oKSB7DQogICAgZm9yRWFjaChjb250cm9scywgZnVuY3Rpb24oY29udHJvbCkgew0KICAgICAgY29udHJvbC4kY29tbWl0Vmlld1ZhbHVlKCk7DQogICAgfSk7DQogIH07DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgZm9ybS5Gb3JtQ29udHJvbGxlciMkYWRkQ29udHJvbA0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogUmVnaXN0ZXIgYSBjb250cm9sIHdpdGggdGhlIGZvcm0uDQogICAqDQogICAqIElucHV0IGVsZW1lbnRzIHVzaW5nIG5nTW9kZWxDb250cm9sbGVyIGRvIHRoaXMgYXV0b21hdGljYWxseSB3aGVuIHRoZXkgYXJlIGxpbmtlZC4NCiAgICovDQogIGZvcm0uJGFkZENvbnRyb2wgPSBmdW5jdGlvbihjb250cm9sKSB7DQogICAgLy8gQnJlYWtpbmcgY2hhbmdlIC0gYmVmb3JlLCBpbnB1dHMgd2hvc2UgbmFtZSB3YXMgImhhc093blByb3BlcnR5IiB3ZXJlIHF1aWV0bHkgaWdub3JlZA0KICAgIC8vIGFuZCBub3QgYWRkZWQgdG8gdGhlIHNjb3BlLiAgTm93IHdlIHRocm93IGFuIGVycm9yLg0KICAgIGFzc2VydE5vdEhhc093blByb3BlcnR5KGNvbnRyb2wuJG5hbWUsICdpbnB1dCcpOw0KICAgIGNvbnRyb2xzLnB1c2goY29udHJvbCk7DQoNCiAgICBpZiAoY29udHJvbC4kbmFtZSkgew0KICAgICAgZm9ybVtjb250cm9sLiRuYW1lXSA9IGNvbnRyb2w7DQogICAgfQ0KICB9Ow0KDQogIC8vIFByaXZhdGUgQVBJOiByZW5hbWUgYSBmb3JtIGNvbnRyb2wNCiAgZm9ybS4kJHJlbmFtZUNvbnRyb2wgPSBmdW5jdGlvbihjb250cm9sLCBuZXdOYW1lKSB7DQogICAgdmFyIG9sZE5hbWUgPSBjb250cm9sLiRuYW1lOw0KDQogICAgaWYgKGZvcm1bb2xkTmFtZV0gPT09IGNvbnRyb2wpIHsNCiAgICAgIGRlbGV0ZSBmb3JtW29sZE5hbWVdOw0KICAgIH0NCiAgICBmb3JtW25ld05hbWVdID0gY29udHJvbDsNCiAgICBjb250cm9sLiRuYW1lID0gbmV3TmFtZTsNCiAgfTsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSBmb3JtLkZvcm1Db250cm9sbGVyIyRyZW1vdmVDb250cm9sDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBEZXJlZ2lzdGVyIGEgY29udHJvbCBmcm9tIHRoZSBmb3JtLg0KICAgKg0KICAgKiBJbnB1dCBlbGVtZW50cyB1c2luZyBuZ01vZGVsQ29udHJvbGxlciBkbyB0aGlzIGF1dG9tYXRpY2FsbHkgd2hlbiB0aGV5IGFyZSBkZXN0cm95ZWQuDQogICAqLw0KICBmb3JtLiRyZW1vdmVDb250cm9sID0gZnVuY3Rpb24oY29udHJvbCkgew0KICAgIGlmIChjb250cm9sLiRuYW1lICYmIGZvcm1bY29udHJvbC4kbmFtZV0gPT09IGNvbnRyb2wpIHsNCiAgICAgIGRlbGV0ZSBmb3JtW2NvbnRyb2wuJG5hbWVdOw0KICAgIH0NCiAgICBmb3JFYWNoKGZvcm0uJHBlbmRpbmcsIGZ1bmN0aW9uKHZhbHVlLCBuYW1lKSB7DQogICAgICBmb3JtLiRzZXRWYWxpZGl0eShuYW1lLCBudWxsLCBjb250cm9sKTsNCiAgICB9KTsNCiAgICBmb3JFYWNoKGZvcm0uJGVycm9yLCBmdW5jdGlvbih2YWx1ZSwgbmFtZSkgew0KICAgICAgZm9ybS4kc2V0VmFsaWRpdHkobmFtZSwgbnVsbCwgY29udHJvbCk7DQogICAgfSk7DQoNCiAgICBhcnJheVJlbW92ZShjb250cm9scywgY29udHJvbCk7DQogIH07DQoNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSBmb3JtLkZvcm1Db250cm9sbGVyIyRzZXRWYWxpZGl0eQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogU2V0cyB0aGUgdmFsaWRpdHkgb2YgYSBmb3JtIGNvbnRyb2wuDQogICAqDQogICAqIFRoaXMgbWV0aG9kIHdpbGwgYWxzbyBwcm9wYWdhdGUgdG8gcGFyZW50IGZvcm1zLg0KICAgKi8NCiAgYWRkU2V0VmFsaWRpdHlNZXRob2Qoew0KICAgIGN0cmw6IHRoaXMsDQogICAgJGVsZW1lbnQ6IGVsZW1lbnQsDQogICAgc2V0OiBmdW5jdGlvbihvYmplY3QsIHByb3BlcnR5LCBjb250cm9sKSB7DQogICAgICB2YXIgbGlzdCA9IG9iamVjdFtwcm9wZXJ0eV07DQogICAgICBpZiAoIWxpc3QpIHsNCiAgICAgICAgb2JqZWN0W3Byb3BlcnR5XSA9IFtjb250cm9sXTsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIHZhciBpbmRleCA9IGxpc3QuaW5kZXhPZihjb250cm9sKTsNCiAgICAgICAgaWYgKGluZGV4ID09PSAtMSkgew0KICAgICAgICAgIGxpc3QucHVzaChjb250cm9sKTsNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgIH0sDQogICAgdW5zZXQ6IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHksIGNvbnRyb2wpIHsNCiAgICAgIHZhciBsaXN0ID0gb2JqZWN0W3Byb3BlcnR5XTsNCiAgICAgIGlmICghbGlzdCkgew0KICAgICAgICByZXR1cm47DQogICAgICB9DQogICAgICBhcnJheVJlbW92ZShsaXN0LCBjb250cm9sKTsNCiAgICAgIGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkgew0KICAgICAgICBkZWxldGUgb2JqZWN0W3Byb3BlcnR5XTsNCiAgICAgIH0NCiAgICB9LA0KICAgIHBhcmVudEZvcm06IHBhcmVudEZvcm0sDQogICAgJGFuaW1hdGU6ICRhbmltYXRlDQogIH0pOw0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lIGZvcm0uRm9ybUNvbnRyb2xsZXIjJHNldERpcnR5DQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBTZXRzIHRoZSBmb3JtIHRvIGEgZGlydHkgc3RhdGUuDQogICAqDQogICAqIFRoaXMgbWV0aG9kIGNhbiBiZSBjYWxsZWQgdG8gYWRkIHRoZSAnbmctZGlydHknIGNsYXNzIGFuZCBzZXQgdGhlIGZvcm0gdG8gYSBkaXJ0eQ0KICAgKiBzdGF0ZSAobmctZGlydHkgY2xhc3MpLiBUaGlzIG1ldGhvZCB3aWxsIGFsc28gcHJvcGFnYXRlIHRvIHBhcmVudCBmb3Jtcy4NCiAgICovDQogIGZvcm0uJHNldERpcnR5ID0gZnVuY3Rpb24oKSB7DQogICAgJGFuaW1hdGUucmVtb3ZlQ2xhc3MoZWxlbWVudCwgUFJJU1RJTkVfQ0xBU1MpOw0KICAgICRhbmltYXRlLmFkZENsYXNzKGVsZW1lbnQsIERJUlRZX0NMQVNTKTsNCiAgICBmb3JtLiRkaXJ0eSA9IHRydWU7DQogICAgZm9ybS4kcHJpc3RpbmUgPSBmYWxzZTsNCiAgICBwYXJlbnRGb3JtLiRzZXREaXJ0eSgpOw0KICB9Ow0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lIGZvcm0uRm9ybUNvbnRyb2xsZXIjJHNldFByaXN0aW5lDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBTZXRzIHRoZSBmb3JtIHRvIGl0cyBwcmlzdGluZSBzdGF0ZS4NCiAgICoNCiAgICogVGhpcyBtZXRob2QgY2FuIGJlIGNhbGxlZCB0byByZW1vdmUgdGhlICduZy1kaXJ0eScgY2xhc3MgYW5kIHNldCB0aGUgZm9ybSB0byBpdHMgcHJpc3RpbmUNCiAgICogc3RhdGUgKG5nLXByaXN0aW5lIGNsYXNzKS4gVGhpcyBtZXRob2Qgd2lsbCBhbHNvIHByb3BhZ2F0ZSB0byBhbGwgdGhlIGNvbnRyb2xzIGNvbnRhaW5lZA0KICAgKiBpbiB0aGlzIGZvcm0uDQogICAqDQogICAqIFNldHRpbmcgYSBmb3JtIGJhY2sgdG8gYSBwcmlzdGluZSBzdGF0ZSBpcyBvZnRlbiB1c2VmdWwgd2hlbiB3ZSB3YW50IHRvICdyZXVzZScgYSBmb3JtIGFmdGVyDQogICAqIHNhdmluZyBvciByZXNldHRpbmcgaXQuDQogICAqLw0KICBmb3JtLiRzZXRQcmlzdGluZSA9IGZ1bmN0aW9uKCkgew0KICAgICRhbmltYXRlLnNldENsYXNzKGVsZW1lbnQsIFBSSVNUSU5FX0NMQVNTLCBESVJUWV9DTEFTUyArICcgJyArIFNVQk1JVFRFRF9DTEFTUyk7DQogICAgZm9ybS4kZGlydHkgPSBmYWxzZTsNCiAgICBmb3JtLiRwcmlzdGluZSA9IHRydWU7DQogICAgZm9ybS4kc3VibWl0dGVkID0gZmFsc2U7DQogICAgZm9yRWFjaChjb250cm9scywgZnVuY3Rpb24oY29udHJvbCkgew0KICAgICAgY29udHJvbC4kc2V0UHJpc3RpbmUoKTsNCiAgICB9KTsNCiAgfTsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSBmb3JtLkZvcm1Db250cm9sbGVyIyRzZXRVbnRvdWNoZWQNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFNldHMgdGhlIGZvcm0gdG8gaXRzIHVudG91Y2hlZCBzdGF0ZS4NCiAgICoNCiAgICogVGhpcyBtZXRob2QgY2FuIGJlIGNhbGxlZCB0byByZW1vdmUgdGhlICduZy10b3VjaGVkJyBjbGFzcyBhbmQgc2V0IHRoZSBmb3JtIGNvbnRyb2xzIHRvIHRoZWlyDQogICAqIHVudG91Y2hlZCBzdGF0ZSAobmctdW50b3VjaGVkIGNsYXNzKS4NCiAgICoNCiAgICogU2V0dGluZyBhIGZvcm0gY29udHJvbHMgYmFjayB0byB0aGVpciB1bnRvdWNoZWQgc3RhdGUgaXMgb2Z0ZW4gdXNlZnVsIHdoZW4gc2V0dGluZyB0aGUgZm9ybQ0KICAgKiBiYWNrIHRvIGl0cyBwcmlzdGluZSBzdGF0ZS4NCiAgICovDQogIGZvcm0uJHNldFVudG91Y2hlZCA9IGZ1bmN0aW9uKCkgew0KICAgIGZvckVhY2goY29udHJvbHMsIGZ1bmN0aW9uKGNvbnRyb2wpIHsNCiAgICAgIGNvbnRyb2wuJHNldFVudG91Y2hlZCgpOw0KICAgIH0pOw0KICB9Ow0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lIGZvcm0uRm9ybUNvbnRyb2xsZXIjJHNldFN1Ym1pdHRlZA0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogU2V0cyB0aGUgZm9ybSB0byBpdHMgc3VibWl0dGVkIHN0YXRlLg0KICAgKi8NCiAgZm9ybS4kc2V0U3VibWl0dGVkID0gZnVuY3Rpb24oKSB7DQogICAgJGFuaW1hdGUuYWRkQ2xhc3MoZWxlbWVudCwgU1VCTUlUVEVEX0NMQVNTKTsNCiAgICBmb3JtLiRzdWJtaXR0ZWQgPSB0cnVlOw0KICAgIHBhcmVudEZvcm0uJHNldFN1Ym1pdHRlZCgpOw0KICB9Ow0KfQ0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nRm9ybQ0KICogQHJlc3RyaWN0IEVBQw0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogTmVzdGFibGUgYWxpYXMgb2Yge0BsaW5rIG5nLmRpcmVjdGl2ZTpmb3JtIGBmb3JtYH0gZGlyZWN0aXZlLiBIVE1MDQogKiBkb2VzIG5vdCBhbGxvdyBuZXN0aW5nIG9mIGZvcm0gZWxlbWVudHMuIEl0IGlzIHVzZWZ1bCB0byBuZXN0IGZvcm1zLCBmb3IgZXhhbXBsZSBpZiB0aGUgdmFsaWRpdHkgb2YgYQ0KICogc3ViLWdyb3VwIG9mIGNvbnRyb2xzIG5lZWRzIHRvIGJlIGRldGVybWluZWQuDQogKg0KICogTm90ZTogdGhlIHB1cnBvc2Ugb2YgYG5nRm9ybWAgaXMgdG8gZ3JvdXAgY29udHJvbHMsDQogKiBidXQgbm90IHRvIGJlIGEgcmVwbGFjZW1lbnQgZm9yIHRoZSBgPGZvcm0+YCB0YWcgd2l0aCBhbGwgb2YgaXRzIGNhcGFiaWxpdGllcw0KICogKGUuZy4gcG9zdGluZyB0byB0aGUgc2VydmVyLCAuLi4pLg0KICoNCiAqIEBwYXJhbSB7c3RyaW5nPX0gbmdGb3JtfG5hbWUgTmFtZSBvZiB0aGUgZm9ybS4gSWYgc3BlY2lmaWVkLCB0aGUgZm9ybSBjb250cm9sbGVyIHdpbGwgYmUgcHVibGlzaGVkIGludG8NCiAqICAgICAgICAgICAgICAgICAgICAgICByZWxhdGVkIHNjb3BlLCB1bmRlciB0aGlzIG5hbWUuDQogKg0KICovDQoNCiAvKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIGZvcm0NCiAqIEByZXN0cmljdCBFDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBEaXJlY3RpdmUgdGhhdCBpbnN0YW50aWF0ZXMNCiAqIHtAbGluayBmb3JtLkZvcm1Db250cm9sbGVyIEZvcm1Db250cm9sbGVyfS4NCiAqDQogKiBJZiB0aGUgYG5hbWVgIGF0dHJpYnV0ZSBpcyBzcGVjaWZpZWQsIHRoZSBmb3JtIGNvbnRyb2xsZXIgaXMgcHVibGlzaGVkIG9udG8gdGhlIGN1cnJlbnQgc2NvcGUgdW5kZXINCiAqIHRoaXMgbmFtZS4NCiAqDQogKiAjIEFsaWFzOiB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nRm9ybSBgbmdGb3JtYH0NCiAqDQogKiBJbiBBbmd1bGFyIGZvcm1zIGNhbiBiZSBuZXN0ZWQuIFRoaXMgbWVhbnMgdGhhdCB0aGUgb3V0ZXIgZm9ybSBpcyB2YWxpZCB3aGVuIGFsbCBvZiB0aGUgY2hpbGQNCiAqIGZvcm1zIGFyZSB2YWxpZCBhcyB3ZWxsLiBIb3dldmVyLCBicm93c2VycyBkbyBub3QgYWxsb3cgbmVzdGluZyBvZiBgPGZvcm0+YCBlbGVtZW50cywgc28NCiAqIEFuZ3VsYXIgcHJvdmlkZXMgdGhlIHtAbGluayBuZy5kaXJlY3RpdmU6bmdGb3JtIGBuZ0Zvcm1gfSBkaXJlY3RpdmUgd2hpY2ggYmVoYXZlcyBpZGVudGljYWxseSB0bw0KICogYDxmb3JtPmAgYnV0IGNhbiBiZSBuZXN0ZWQuICBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBuZXN0ZWQgZm9ybXMsIHdoaWNoIGlzIHZlcnkgdXNlZnVsIHdoZW4NCiAqIHVzaW5nIEFuZ3VsYXIgdmFsaWRhdGlvbiBkaXJlY3RpdmVzIGluIGZvcm1zIHRoYXQgYXJlIGR5bmFtaWNhbGx5IGdlbmVyYXRlZCB1c2luZyB0aGUNCiAqIHtAbGluayBuZy5kaXJlY3RpdmU6bmdSZXBlYXQgYG5nUmVwZWF0YH0gZGlyZWN0aXZlLiBTaW5jZSB5b3UgY2Fubm90IGR5bmFtaWNhbGx5IGdlbmVyYXRlIHRoZSBgbmFtZWANCiAqIGF0dHJpYnV0ZSBvZiBpbnB1dCBlbGVtZW50cyB1c2luZyBpbnRlcnBvbGF0aW9uLCB5b3UgaGF2ZSB0byB3cmFwIGVhY2ggc2V0IG9mIHJlcGVhdGVkIGlucHV0cyBpbiBhbg0KICogYG5nRm9ybWAgZGlyZWN0aXZlIGFuZCBuZXN0IHRoZXNlIGluIGFuIG91dGVyIGBmb3JtYCBlbGVtZW50Lg0KICoNCiAqDQogKiAjIENTUyBjbGFzc2VzDQogKiAgLSBgbmctdmFsaWRgIGlzIHNldCBpZiB0aGUgZm9ybSBpcyB2YWxpZC4NCiAqICAtIGBuZy1pbnZhbGlkYCBpcyBzZXQgaWYgdGhlIGZvcm0gaXMgaW52YWxpZC4NCiAqICAtIGBuZy1wcmlzdGluZWAgaXMgc2V0IGlmIHRoZSBmb3JtIGlzIHByaXN0aW5lLg0KICogIC0gYG5nLWRpcnR5YCBpcyBzZXQgaWYgdGhlIGZvcm0gaXMgZGlydHkuDQogKiAgLSBgbmctc3VibWl0dGVkYCBpcyBzZXQgaWYgdGhlIGZvcm0gd2FzIHN1Ym1pdHRlZC4NCiAqDQogKiBLZWVwIGluIG1pbmQgdGhhdCBuZ0FuaW1hdGUgY2FuIGRldGVjdCBlYWNoIG9mIHRoZXNlIGNsYXNzZXMgd2hlbiBhZGRlZCBhbmQgcmVtb3ZlZC4NCiAqDQogKg0KICogIyBTdWJtaXR0aW5nIGEgZm9ybSBhbmQgcHJldmVudGluZyB0aGUgZGVmYXVsdCBhY3Rpb24NCiAqDQogKiBTaW5jZSB0aGUgcm9sZSBvZiBmb3JtcyBpbiBjbGllbnQtc2lkZSBBbmd1bGFyIGFwcGxpY2F0aW9ucyBpcyBkaWZmZXJlbnQgdGhhbiBpbiBjbGFzc2ljYWwNCiAqIHJvdW5kdHJpcCBhcHBzLCBpdCBpcyBkZXNpcmFibGUgZm9yIHRoZSBicm93c2VyIG5vdCB0byB0cmFuc2xhdGUgdGhlIGZvcm0gc3VibWlzc2lvbiBpbnRvIGEgZnVsbA0KICogcGFnZSByZWxvYWQgdGhhdCBzZW5kcyB0aGUgZGF0YSB0byB0aGUgc2VydmVyLiBJbnN0ZWFkIHNvbWUgamF2YXNjcmlwdCBsb2dpYyBzaG91bGQgYmUgdHJpZ2dlcmVkDQogKiB0byBoYW5kbGUgdGhlIGZvcm0gc3VibWlzc2lvbiBpbiBhbiBhcHBsaWNhdGlvbi1zcGVjaWZpYyB3YXkuDQogKg0KICogRm9yIHRoaXMgcmVhc29uLCBBbmd1bGFyIHByZXZlbnRzIHRoZSBkZWZhdWx0IGFjdGlvbiAoZm9ybSBzdWJtaXNzaW9uIHRvIHRoZSBzZXJ2ZXIpIHVubGVzcyB0aGUNCiAqIGA8Zm9ybT5gIGVsZW1lbnQgaGFzIGFuIGBhY3Rpb25gIGF0dHJpYnV0ZSBzcGVjaWZpZWQuDQogKg0KICogWW91IGNhbiB1c2Ugb25lIG9mIHRoZSBmb2xsb3dpbmcgdHdvIHdheXMgdG8gc3BlY2lmeSB3aGF0IGphdmFzY3JpcHQgbWV0aG9kIHNob3VsZCBiZSBjYWxsZWQgd2hlbg0KICogYSBmb3JtIGlzIHN1Ym1pdHRlZDoNCiAqDQogKiAtIHtAbGluayBuZy5kaXJlY3RpdmU6bmdTdWJtaXQgbmdTdWJtaXR9IGRpcmVjdGl2ZSBvbiB0aGUgZm9ybSBlbGVtZW50DQogKiAtIHtAbGluayBuZy5kaXJlY3RpdmU6bmdDbGljayBuZ0NsaWNrfSBkaXJlY3RpdmUgb24gdGhlIGZpcnN0DQogICogIGJ1dHRvbiBvciBpbnB1dCBmaWVsZCBvZiB0eXBlIHN1Ym1pdCAoaW5wdXRbdHlwZT1zdWJtaXRdKQ0KICoNCiAqIFRvIHByZXZlbnQgZG91YmxlIGV4ZWN1dGlvbiBvZiB0aGUgaGFuZGxlciwgdXNlIG9ubHkgb25lIG9mIHRoZSB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nU3VibWl0IG5nU3VibWl0fQ0KICogb3Ige0BsaW5rIG5nLmRpcmVjdGl2ZTpuZ0NsaWNrIG5nQ2xpY2t9IGRpcmVjdGl2ZXMuDQogKiBUaGlzIGlzIGJlY2F1c2Ugb2YgdGhlIGZvbGxvd2luZyBmb3JtIHN1Ym1pc3Npb24gcnVsZXMgaW4gdGhlIEhUTUwgc3BlY2lmaWNhdGlvbjoNCiAqDQogKiAtIElmIGEgZm9ybSBoYXMgb25seSBvbmUgaW5wdXQgZmllbGQgdGhlbiBoaXR0aW5nIGVudGVyIGluIHRoaXMgZmllbGQgdHJpZ2dlcnMgZm9ybSBzdWJtaXQNCiAqIChgbmdTdWJtaXRgKQ0KICogLSBpZiBhIGZvcm0gaGFzIDIrIGlucHV0IGZpZWxkcyBhbmQgbm8gYnV0dG9ucyBvciBpbnB1dFt0eXBlPXN1Ym1pdF0gdGhlbiBoaXR0aW5nIGVudGVyDQogKiBkb2Vzbid0IHRyaWdnZXIgc3VibWl0DQogKiAtIGlmIGEgZm9ybSBoYXMgb25lIG9yIG1vcmUgaW5wdXQgZmllbGRzIGFuZCBvbmUgb3IgbW9yZSBidXR0b25zIG9yIGlucHV0W3R5cGU9c3VibWl0XSB0aGVuDQogKiBoaXR0aW5nIGVudGVyIGluIGFueSBvZiB0aGUgaW5wdXQgZmllbGRzIHdpbGwgdHJpZ2dlciB0aGUgY2xpY2sgaGFuZGxlciBvbiB0aGUgKmZpcnN0KiBidXR0b24gb3INCiAqIGlucHV0W3R5cGU9c3VibWl0XSAoYG5nQ2xpY2tgKSAqYW5kKiBhIHN1Ym1pdCBoYW5kbGVyIG9uIHRoZSBlbmNsb3NpbmcgZm9ybSAoYG5nU3VibWl0YCkNCiAqDQogKiBBbnkgcGVuZGluZyBgbmdNb2RlbE9wdGlvbnNgIGNoYW5nZXMgd2lsbCB0YWtlIHBsYWNlIGltbWVkaWF0ZWx5IHdoZW4gYW4gZW5jbG9zaW5nIGZvcm0gaXMNCiAqIHN1Ym1pdHRlZC4gTm90ZSB0aGF0IGBuZ0NsaWNrYCBldmVudHMgd2lsbCBvY2N1ciBiZWZvcmUgdGhlIG1vZGVsIGlzIHVwZGF0ZWQuIFVzZSBgbmdTdWJtaXRgDQogKiB0byBoYXZlIGFjY2VzcyB0byB0aGUgdXBkYXRlZCBtb2RlbC4NCiAqDQogKiAjIyBBbmltYXRpb24gSG9va3MNCiAqDQogKiBBbmltYXRpb25zIGluIG5nRm9ybSBhcmUgdHJpZ2dlcmVkIHdoZW4gYW55IG9mIHRoZSBhc3NvY2lhdGVkIENTUyBjbGFzc2VzIGFyZSBhZGRlZCBhbmQgcmVtb3ZlZC4NCiAqIFRoZXNlIGNsYXNzZXMgYXJlOiBgLm5nLXByaXN0aW5lYCwgYC5uZy1kaXJ0eWAsIGAubmctaW52YWxpZGAgYW5kIGAubmctdmFsaWRgIGFzIHdlbGwgYXMgYW55DQogKiBvdGhlciB2YWxpZGF0aW9ucyB0aGF0IGFyZSBwZXJmb3JtZWQgd2l0aGluIHRoZSBmb3JtLiBBbmltYXRpb25zIGluIG5nRm9ybSBhcmUgc2ltaWxhciB0byBob3cNCiAqIHRoZXkgd29yayBpbiBuZ0NsYXNzIGFuZCBhbmltYXRpb25zIGNhbiBiZSBob29rZWQgaW50byB1c2luZyBDU1MgdHJhbnNpdGlvbnMsIGtleWZyYW1lcyBhcyB3ZWxsDQogKiBhcyBKUyBhbmltYXRpb25zLg0KICoNCiAqIFRoZSBmb2xsb3dpbmcgZXhhbXBsZSBzaG93cyBhIHNpbXBsZSB3YXkgdG8gdXRpbGl6ZSBDU1MgdHJhbnNpdGlvbnMgdG8gc3R5bGUgYSBmb3JtIGVsZW1lbnQNCiAqIHRoYXQgaGFzIGJlZW4gcmVuZGVyZWQgYXMgaW52YWxpZCBhZnRlciBpdCBoYXMgYmVlbiB2YWxpZGF0ZWQ6DQogKg0KICogPHByZT4NCiAqIC8vYmUgc3VyZSB0byBpbmNsdWRlIG5nQW5pbWF0ZSBhcyBhIG1vZHVsZSB0byBob29rIGludG8gbW9yZQ0KICogLy9hZHZhbmNlZCBhbmltYXRpb25zDQogKiAubXktZm9ybSB7DQogKiAgIHRyYW5zaXRpb246MC41cyBsaW5lYXIgYWxsOw0KICogICBiYWNrZ3JvdW5kOiB3aGl0ZTsNCiAqIH0NCiAqIC5teS1mb3JtLm5nLWludmFsaWQgew0KICogICBiYWNrZ3JvdW5kOiByZWQ7DQogKiAgIGNvbG9yOndoaXRlOw0KICogfQ0KICogPC9wcmU+DQogKg0KICogQGV4YW1wbGUNCiAgICA8ZXhhbXBsZSBkZXBzPSJhbmd1bGFyLWFuaW1hdGUuanMiIGFuaW1hdGlvbnM9InRydWUiIGZpeEJhc2U9InRydWUiIG1vZHVsZT0iZm9ybUV4YW1wbGUiPg0KICAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPHNjcmlwdD4NCiAgICAgICAgIGFuZ3VsYXIubW9kdWxlKCdmb3JtRXhhbXBsZScsIFtdKQ0KICAgICAgICAgICAuY29udHJvbGxlcignRm9ybUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICAgICRzY29wZS51c2VyVHlwZSA9ICdndWVzdCc7DQogICAgICAgICAgIH1dKTsNCiAgICAgICA8L3NjcmlwdD4NCiAgICAgICA8c3R5bGU+DQogICAgICAgIC5teS1mb3JtIHsNCiAgICAgICAgICAtd2Via2l0LXRyYW5zaXRpb246YWxsIGxpbmVhciAwLjVzOw0KICAgICAgICAgIHRyYW5zaXRpb246YWxsIGxpbmVhciAwLjVzOw0KICAgICAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50Ow0KICAgICAgICB9DQogICAgICAgIC5teS1mb3JtLm5nLWludmFsaWQgew0KICAgICAgICAgIGJhY2tncm91bmQ6IHJlZDsNCiAgICAgICAgfQ0KICAgICAgIDwvc3R5bGU+DQogICAgICAgPGZvcm0gbmFtZT0ibXlGb3JtIiBuZy1jb250cm9sbGVyPSJGb3JtQ29udHJvbGxlciIgY2xhc3M9Im15LWZvcm0iPg0KICAgICAgICAgdXNlclR5cGU6IDxpbnB1dCBuYW1lPSJpbnB1dCIgbmctbW9kZWw9InVzZXJUeXBlIiByZXF1aXJlZD4NCiAgICAgICAgIDxzcGFuIGNsYXNzPSJlcnJvciIgbmctc2hvdz0ibXlGb3JtLmlucHV0LiRlcnJvci5yZXF1aXJlZCI+UmVxdWlyZWQhPC9zcGFuPjxicj4NCiAgICAgICAgIDx0dD51c2VyVHlwZSA9IHt7dXNlclR5cGV9fTwvdHQ+PGJyPg0KICAgICAgICAgPHR0Pm15Rm9ybS5pbnB1dC4kdmFsaWQgPSB7e215Rm9ybS5pbnB1dC4kdmFsaWR9fTwvdHQ+PGJyPg0KICAgICAgICAgPHR0Pm15Rm9ybS5pbnB1dC4kZXJyb3IgPSB7e215Rm9ybS5pbnB1dC4kZXJyb3J9fTwvdHQ+PGJyPg0KICAgICAgICAgPHR0Pm15Rm9ybS4kdmFsaWQgPSB7e215Rm9ybS4kdmFsaWR9fTwvdHQ+PGJyPg0KICAgICAgICAgPHR0Pm15Rm9ybS4kZXJyb3IucmVxdWlyZWQgPSB7eyEhbXlGb3JtLiRlcnJvci5yZXF1aXJlZH19PC90dD48YnI+DQogICAgICAgIDwvZm9ybT4NCiAgICAgIDwvZmlsZT4NCiAgICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgICBpdCgnc2hvdWxkIGluaXRpYWxpemUgdG8gbW9kZWwnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgICB2YXIgdXNlclR5cGUgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ3VzZXJUeXBlJykpOw0KICAgICAgICAgIHZhciB2YWxpZCA9IGVsZW1lbnQoYnkuYmluZGluZygnbXlGb3JtLmlucHV0LiR2YWxpZCcpKTsNCg0KICAgICAgICAgIGV4cGVjdCh1c2VyVHlwZS5nZXRUZXh0KCkpLnRvQ29udGFpbignZ3Vlc3QnKTsNCiAgICAgICAgICBleHBlY3QodmFsaWQuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ3RydWUnKTsNCiAgICAgICAgfSk7DQoNCiAgICAgICAgaXQoJ3Nob3VsZCBiZSBpbnZhbGlkIGlmIGVtcHR5JywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgdmFyIHVzZXJUeXBlID0gZWxlbWVudChieS5iaW5kaW5nKCd1c2VyVHlwZScpKTsNCiAgICAgICAgICB2YXIgdmFsaWQgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ215Rm9ybS5pbnB1dC4kdmFsaWQnKSk7DQogICAgICAgICAgdmFyIHVzZXJJbnB1dCA9IGVsZW1lbnQoYnkubW9kZWwoJ3VzZXJUeXBlJykpOw0KDQogICAgICAgICAgdXNlcklucHV0LmNsZWFyKCk7DQogICAgICAgICAgdXNlcklucHV0LnNlbmRLZXlzKCcnKTsNCg0KICAgICAgICAgIGV4cGVjdCh1c2VyVHlwZS5nZXRUZXh0KCkpLnRvRXF1YWwoJ3VzZXJUeXBlID0nKTsNCiAgICAgICAgICBleHBlY3QodmFsaWQuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ2ZhbHNlJyk7DQogICAgICAgIH0pOw0KICAgICAgPC9maWxlPg0KICAgIDwvZXhhbXBsZT4NCiAqDQogKiBAcGFyYW0ge3N0cmluZz19IG5hbWUgTmFtZSBvZiB0aGUgZm9ybS4gSWYgc3BlY2lmaWVkLCB0aGUgZm9ybSBjb250cm9sbGVyIHdpbGwgYmUgcHVibGlzaGVkIGludG8NCiAqICAgICAgICAgICAgICAgICAgICAgICByZWxhdGVkIHNjb3BlLCB1bmRlciB0aGlzIG5hbWUuDQogKi8NCnZhciBmb3JtRGlyZWN0aXZlRmFjdG9yeSA9IGZ1bmN0aW9uKGlzTmdGb3JtKSB7DQogIHJldHVybiBbJyR0aW1lb3V0JywgZnVuY3Rpb24oJHRpbWVvdXQpIHsNCiAgICB2YXIgZm9ybURpcmVjdGl2ZSA9IHsNCiAgICAgIG5hbWU6ICdmb3JtJywNCiAgICAgIHJlc3RyaWN0OiBpc05nRm9ybSA/ICdFQUMnIDogJ0UnLA0KICAgICAgY29udHJvbGxlcjogRm9ybUNvbnRyb2xsZXIsDQogICAgICBjb21waWxlOiBmdW5jdGlvbiBuZ0Zvcm1Db21waWxlKGZvcm1FbGVtZW50KSB7DQogICAgICAgIC8vIFNldHVwIGluaXRpYWwgc3RhdGUgb2YgdGhlIGNvbnRyb2wNCiAgICAgICAgZm9ybUVsZW1lbnQuYWRkQ2xhc3MoUFJJU1RJTkVfQ0xBU1MpLmFkZENsYXNzKFZBTElEX0NMQVNTKTsNCg0KICAgICAgICByZXR1cm4gew0KICAgICAgICAgIHByZTogZnVuY3Rpb24gbmdGb3JtUHJlTGluayhzY29wZSwgZm9ybUVsZW1lbnQsIGF0dHIsIGNvbnRyb2xsZXIpIHsNCiAgICAgICAgICAgIC8vIGlmIGBhY3Rpb25gIGF0dHIgaXMgbm90IHByZXNlbnQgb24gdGhlIGZvcm0sIHByZXZlbnQgdGhlIGRlZmF1bHQgYWN0aW9uIChzdWJtaXNzaW9uKQ0KICAgICAgICAgICAgaWYgKCEoJ2FjdGlvbicgaW4gYXR0cikpIHsNCiAgICAgICAgICAgICAgLy8gd2UgY2FuJ3QgdXNlIGpxIGV2ZW50cyBiZWNhdXNlIGlmIGEgZm9ybSBpcyBkZXN0cm95ZWQgZHVyaW5nIHN1Ym1pc3Npb24gdGhlIGRlZmF1bHQNCiAgICAgICAgICAgICAgLy8gYWN0aW9uIGlzIG5vdCBwcmV2ZW50ZWQuIHNlZSAjMTIzOA0KICAgICAgICAgICAgICAvLw0KICAgICAgICAgICAgICAvLyBJRSA5IGlzIG5vdCBhZmZlY3RlZCBiZWNhdXNlIGl0IGRvZXNuJ3QgZmlyZSBhIHN1Ym1pdCBldmVudCBhbmQgdHJ5IHRvIGRvIGEgZnVsbA0KICAgICAgICAgICAgICAvLyBwYWdlIHJlbG9hZCBpZiB0aGUgZm9ybSB3YXMgZGVzdHJveWVkIGJ5IHN1Ym1pc3Npb24gb2YgdGhlIGZvcm0gdmlhIGEgY2xpY2sgaGFuZGxlcg0KICAgICAgICAgICAgICAvLyBvbiBhIGJ1dHRvbiBpbiB0aGUgZm9ybS4gTG9va3MgbGlrZSBhbiBJRTkgc3BlY2lmaWMgYnVnLg0KICAgICAgICAgICAgICB2YXIgaGFuZGxlRm9ybVN1Ym1pc3Npb24gPSBmdW5jdGlvbihldmVudCkgew0KICAgICAgICAgICAgICAgIHNjb3BlLiRhcHBseShmdW5jdGlvbigpIHsNCiAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXIuJGNvbW1pdFZpZXdWYWx1ZSgpOw0KICAgICAgICAgICAgICAgICAgY29udHJvbGxlci4kc2V0U3VibWl0dGVkKCk7DQogICAgICAgICAgICAgICAgfSk7DQoNCiAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOw0KICAgICAgICAgICAgICB9Ow0KDQogICAgICAgICAgICAgIGFkZEV2ZW50TGlzdGVuZXJGbihmb3JtRWxlbWVudFswXSwgJ3N1Ym1pdCcsIGhhbmRsZUZvcm1TdWJtaXNzaW9uKTsNCg0KICAgICAgICAgICAgICAvLyB1bnJlZ2lzdGVyIHRoZSBwcmV2ZW50RGVmYXVsdCBsaXN0ZW5lciBzbyB0aGF0IHdlIGRvbid0IG5vdCBsZWFrIG1lbW9yeSBidXQgaW4gYQ0KICAgICAgICAgICAgICAvLyB3YXkgdGhhdCB3aWxsIGFjaGlldmUgdGhlIHByZXZlbnRpb24gb2YgdGhlIGRlZmF1bHQgYWN0aW9uLg0KICAgICAgICAgICAgICBmb3JtRWxlbWVudC5vbignJGRlc3Ryb3knLCBmdW5jdGlvbigpIHsNCiAgICAgICAgICAgICAgICAkdGltZW91dChmdW5jdGlvbigpIHsNCiAgICAgICAgICAgICAgICAgIHJlbW92ZUV2ZW50TGlzdGVuZXJGbihmb3JtRWxlbWVudFswXSwgJ3N1Ym1pdCcsIGhhbmRsZUZvcm1TdWJtaXNzaW9uKTsNCiAgICAgICAgICAgICAgICB9LCAwLCBmYWxzZSk7DQogICAgICAgICAgICAgIH0pOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICB2YXIgcGFyZW50Rm9ybUN0cmwgPSBjb250cm9sbGVyLiQkcGFyZW50Rm9ybSwNCiAgICAgICAgICAgICAgICBhbGlhcyA9IGNvbnRyb2xsZXIuJG5hbWU7DQoNCiAgICAgICAgICAgIGlmIChhbGlhcykgew0KICAgICAgICAgICAgICBzZXR0ZXIoc2NvcGUsIGFsaWFzLCBjb250cm9sbGVyLCBhbGlhcyk7DQogICAgICAgICAgICAgIGF0dHIuJG9ic2VydmUoYXR0ci5uYW1lID8gJ25hbWUnIDogJ25nRm9ybScsIGZ1bmN0aW9uKG5ld1ZhbHVlKSB7DQogICAgICAgICAgICAgICAgaWYgKGFsaWFzID09PSBuZXdWYWx1ZSkgcmV0dXJuOw0KICAgICAgICAgICAgICAgIHNldHRlcihzY29wZSwgYWxpYXMsIHVuZGVmaW5lZCwgYWxpYXMpOw0KICAgICAgICAgICAgICAgIGFsaWFzID0gbmV3VmFsdWU7DQogICAgICAgICAgICAgICAgc2V0dGVyKHNjb3BlLCBhbGlhcywgY29udHJvbGxlciwgYWxpYXMpOw0KICAgICAgICAgICAgICAgIHBhcmVudEZvcm1DdHJsLiQkcmVuYW1lQ29udHJvbChjb250cm9sbGVyLCBhbGlhcyk7DQogICAgICAgICAgICAgIH0pOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgZm9ybUVsZW1lbnQub24oJyRkZXN0cm95JywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgIHBhcmVudEZvcm1DdHJsLiRyZW1vdmVDb250cm9sKGNvbnRyb2xsZXIpOw0KICAgICAgICAgICAgICBpZiAoYWxpYXMpIHsNCiAgICAgICAgICAgICAgICBzZXR0ZXIoc2NvcGUsIGFsaWFzLCB1bmRlZmluZWQsIGFsaWFzKTsNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICBleHRlbmQoY29udHJvbGxlciwgbnVsbEZvcm1DdHJsKTsgLy9zdG9wIHByb3BhZ2F0aW5nIGNoaWxkIGRlc3RydWN0aW9uIGhhbmRsZXJzIHVwd2FyZHMNCiAgICAgICAgICAgIH0pOw0KICAgICAgICAgIH0NCiAgICAgICAgfTsNCiAgICAgIH0NCiAgICB9Ow0KDQogICAgcmV0dXJuIGZvcm1EaXJlY3RpdmU7DQogIH1dOw0KfTsNCg0KdmFyIGZvcm1EaXJlY3RpdmUgPSBmb3JtRGlyZWN0aXZlRmFjdG9yeSgpOw0KdmFyIG5nRm9ybURpcmVjdGl2ZSA9IGZvcm1EaXJlY3RpdmVGYWN0b3J5KHRydWUpOw0KDQovKiBnbG9iYWwgVkFMSURfQ0xBU1M6IHRydWUsDQogIElOVkFMSURfQ0xBU1M6IHRydWUsDQogIFBSSVNUSU5FX0NMQVNTOiB0cnVlLA0KICBESVJUWV9DTEFTUzogdHJ1ZSwNCiAgVU5UT1VDSEVEX0NMQVNTOiB0cnVlLA0KICBUT1VDSEVEX0NMQVNTOiB0cnVlLA0KKi8NCg0KLy8gUmVnZXggY29kZSBpcyBvYnRhaW5lZCBmcm9tIFNPOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8zMTQzMDcwL2phdmFzY3JpcHQtcmVnZXgtaXNvLWRhdGV0aW1lI2Fuc3dlci0zMTQzMjMxDQp2YXIgSVNPX0RBVEVfUkVHRVhQID0gL1xkezR9LVswMV1cZC1bMC0zXVxkVFswLTJdXGQ6WzAtNV1cZDpbMC01XVxkXC5cZCsoWystXVswLTJdXGQ6WzAtNV1cZHxaKS87DQp2YXIgVVJMX1JFR0VYUCA9IC9eKGZ0cHxodHRwfGh0dHBzKTpcL1wvKFx3Kzp7MCwxfVx3KkApPyhcUyspKDpbMC05XSspPyhcL3xcLyhbXHcjITouPys9JiVAIVwtXC9dKSk/JC87DQp2YXIgRU1BSUxfUkVHRVhQID0gL15bYS16MC05ISMkJSYnKitcLz0/Xl9ge3x9fi4tXStAW2EtejAtOV0oW2EtejAtOS1dKlthLXowLTldKT8oXC5bYS16MC05XShbYS16MC05LV0qW2EtejAtOV0pPykqJC9pOw0KdmFyIE5VTUJFUl9SRUdFWFAgPSAvXlxzKihcLXxcKyk/KFxkK3woXGQqKFwuXGQqKSkpXHMqJC87DQp2YXIgREFURV9SRUdFWFAgPSAvXihcZHs0fSktKFxkezJ9KS0oXGR7Mn0pJC87DQp2YXIgREFURVRJTUVMT0NBTF9SRUdFWFAgPSAvXihcZHs0fSktKFxkXGQpLShcZFxkKVQoXGRcZCk6KFxkXGQpKD86OihcZFxkKShcLlxkezEsM30pPyk/JC87DQp2YXIgV0VFS19SRUdFWFAgPSAvXihcZHs0fSktVyhcZFxkKSQvOw0KdmFyIE1PTlRIX1JFR0VYUCA9IC9eKFxkezR9KS0oXGRcZCkkLzsNCnZhciBUSU1FX1JFR0VYUCA9IC9eKFxkXGQpOihcZFxkKSg/OjooXGRcZCkoXC5cZHsxLDN9KT8pPyQvOw0KdmFyIERFRkFVTFRfUkVHRVhQID0gLyhccyt8XilkZWZhdWx0KFxzK3wkKS87DQoNCnZhciAkbmdNb2RlbE1pbkVyciA9IG5ldyBtaW5FcnIoJ25nTW9kZWwnKTsNCg0KdmFyIGlucHV0VHlwZSA9IHsNCg0KICAvKioNCiAgICogQG5nZG9jIGlucHV0DQogICAqIEBuYW1lIGlucHV0W3RleHRdDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBTdGFuZGFyZCBIVE1MIHRleHQgaW5wdXQgd2l0aCBhbmd1bGFyIGRhdGEgYmluZGluZywgaW5oZXJpdGVkIGJ5IG1vc3Qgb2YgdGhlIGBpbnB1dGAgZWxlbWVudHMuDQogICAqDQogICAqDQogICAqIEBwYXJhbSB7c3RyaW5nfSBuZ01vZGVsIEFzc2lnbmFibGUgYW5ndWxhciBleHByZXNzaW9uIHRvIGRhdGEtYmluZCB0by4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSBuYW1lIFByb3BlcnR5IG5hbWUgb2YgdGhlIGZvcm0gdW5kZXIgd2hpY2ggdGhlIGNvbnRyb2wgaXMgcHVibGlzaGVkLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IHJlcXVpcmVkIEFkZHMgYHJlcXVpcmVkYCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgdmFsdWUgaXMgbm90IGVudGVyZWQuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmdSZXF1aXJlZCBBZGRzIGByZXF1aXJlZGAgYXR0cmlidXRlIGFuZCBgcmVxdWlyZWRgIHZhbGlkYXRpb24gY29uc3RyYWludCB0bw0KICAgKiAgICB0aGUgZWxlbWVudCB3aGVuIHRoZSBuZ1JlcXVpcmVkIGV4cHJlc3Npb24gZXZhbHVhdGVzIHRvIHRydWUuIFVzZSBgbmdSZXF1aXJlZGAgaW5zdGVhZCBvZg0KICAgKiAgICBgcmVxdWlyZWRgIHdoZW4geW91IHdhbnQgdG8gZGF0YS1iaW5kIHRvIHRoZSBgcmVxdWlyZWRgIGF0dHJpYnV0ZS4NCiAgICogQHBhcmFtIHtudW1iZXI9fSBuZ01pbmxlbmd0aCBTZXRzIGBtaW5sZW5ndGhgIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBpcyBzaG9ydGVyIHRoYW4NCiAgICogICAgbWlubGVuZ3RoLg0KICAgKiBAcGFyYW0ge251bWJlcj19IG5nTWF4bGVuZ3RoIFNldHMgYG1heGxlbmd0aGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGlzIGxvbmdlciB0aGFuDQogICAqICAgIG1heGxlbmd0aC4gU2V0dGluZyB0aGUgYXR0cmlidXRlIHRvIGEgbmVnYXRpdmUgb3Igbm9uLW51bWVyaWMgdmFsdWUsIGFsbG93cyB2aWV3IHZhbHVlcyBvZg0KICAgKiAgICBhbnkgbGVuZ3RoLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IHBhdHRlcm4gU2ltaWxhciB0byBgbmdQYXR0ZXJuYCBleGNlcHQgdGhhdCB0aGUgYXR0cmlidXRlIHZhbHVlIGlzIHRoZSBhY3R1YWwgc3RyaW5nDQogICAqICAgIHRoYXQgY29udGFpbnMgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbiBib2R5IHRoYXQgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gYSByZWd1bGFyIGV4cHJlc3Npb24NCiAgICogICAgYXMgaW4gdGhlIG5nUGF0dGVybiBkaXJlY3RpdmUuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmdQYXR0ZXJuIFNldHMgYHBhdHRlcm5gIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSBuZ01vZGVsIHZhbHVlIGRvZXMgbm90IG1hdGNoDQogICAqICAgIGEgUmVnRXhwIGZvdW5kIGJ5IGV2YWx1YXRpbmcgdGhlIEFuZ3VsYXIgZXhwcmVzc2lvbiBnaXZlbiBpbiB0aGUgYXR0cmlidXRlIHZhbHVlLg0KICAgKiAgICBJZiB0aGUgZXhwcmVzc2lvbiBldmFsdWF0ZXMgdG8gYSBSZWdFeHAgb2JqZWN0IHRoZW4gdGhpcyBpcyB1c2VkIGRpcmVjdGx5Lg0KICAgKiAgICBJZiB0aGUgZXhwcmVzc2lvbiBpcyBhIHN0cmluZyB0aGVuIGl0IHdpbGwgYmUgY29udmVydGVkIHRvIGEgUmVnRXhwIGFmdGVyIHdyYXBwaW5nIGl0IGluIGBeYCBhbmQgYCRgDQogICAqICAgIGNoYXJhY3RlcnMuIEZvciBpbnN0YW5jZSwgYCJhYmMiYCB3aWxsIGJlIGNvbnZlcnRlZCB0byBgbmV3IFJlZ0V4cCgnXmFiYyQnKWAuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmdDaGFuZ2UgQW5ndWxhciBleHByZXNzaW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gaW5wdXQgY2hhbmdlcyBkdWUgdG8gdXNlcg0KICAgKiAgICBpbnRlcmFjdGlvbiB3aXRoIHRoZSBpbnB1dCBlbGVtZW50Lg0KICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBbbmdUcmltPXRydWVdIElmIHNldCB0byBmYWxzZSBBbmd1bGFyIHdpbGwgbm90IGF1dG9tYXRpY2FsbHkgdHJpbSB0aGUgaW5wdXQuDQogICAqICAgIFRoaXMgcGFyYW1ldGVyIGlzIGlnbm9yZWQgZm9yIGlucHV0W3R5cGU9cGFzc3dvcmRdIGNvbnRyb2xzLCB3aGljaCB3aWxsIG5ldmVyIHRyaW0gdGhlDQogICAqICAgIGlucHV0Lg0KICAgKg0KICAgKiBAZXhhbXBsZQ0KICAgICAgPGV4YW1wbGUgbmFtZT0idGV4dC1pbnB1dC1kaXJlY3RpdmUiIG1vZHVsZT0idGV4dElucHV0RXhhbXBsZSI+DQogICAgICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgICAgPHNjcmlwdD4NCiAgICAgICAgICAgYW5ndWxhci5tb2R1bGUoJ3RleHRJbnB1dEV4YW1wbGUnLCBbXSkNCiAgICAgICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICAgICAgJHNjb3BlLnRleHQgPSAnZ3Vlc3QnOw0KICAgICAgICAgICAgICAgJHNjb3BlLndvcmQgPSAvXlxzKlx3KlxzKiQvOw0KICAgICAgICAgICAgIH1dKTsNCiAgICAgICAgIDwvc2NyaXB0Pg0KICAgICAgICAgPGZvcm0gbmFtZT0ibXlGb3JtIiBuZy1jb250cm9sbGVyPSJFeGFtcGxlQ29udHJvbGxlciI+DQogICAgICAgICAgIFNpbmdsZSB3b3JkOiA8aW5wdXQgdHlwZT0idGV4dCIgbmFtZT0iaW5wdXQiIG5nLW1vZGVsPSJ0ZXh0Ig0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5nLXBhdHRlcm49IndvcmQiIHJlcXVpcmVkIG5nLXRyaW09ImZhbHNlIj4NCiAgICAgICAgICAgPHNwYW4gY2xhc3M9ImVycm9yIiBuZy1zaG93PSJteUZvcm0uaW5wdXQuJGVycm9yLnJlcXVpcmVkIj4NCiAgICAgICAgICAgICBSZXF1aXJlZCE8L3NwYW4+DQogICAgICAgICAgIDxzcGFuIGNsYXNzPSJlcnJvciIgbmctc2hvdz0ibXlGb3JtLmlucHV0LiRlcnJvci5wYXR0ZXJuIj4NCiAgICAgICAgICAgICBTaW5nbGUgd29yZCBvbmx5ITwvc3Bhbj4NCg0KICAgICAgICAgICA8dHQ+dGV4dCA9IHt7dGV4dH19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLmlucHV0LiR2YWxpZCA9IHt7bXlGb3JtLmlucHV0LiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLmlucHV0LiRlcnJvciA9IHt7bXlGb3JtLmlucHV0LiRlcnJvcn19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLiR2YWxpZCA9IHt7bXlGb3JtLiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLiRlcnJvci5yZXF1aXJlZCA9IHt7ISFteUZvcm0uJGVycm9yLnJlcXVpcmVkfX08L3R0Pjxici8+DQogICAgICAgICAgPC9mb3JtPg0KICAgICAgICA8L2ZpbGU+DQogICAgICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgICAgIHZhciB0ZXh0ID0gZWxlbWVudChieS5iaW5kaW5nKCd0ZXh0JykpOw0KICAgICAgICAgIHZhciB2YWxpZCA9IGVsZW1lbnQoYnkuYmluZGluZygnbXlGb3JtLmlucHV0LiR2YWxpZCcpKTsNCiAgICAgICAgICB2YXIgaW5wdXQgPSBlbGVtZW50KGJ5Lm1vZGVsKCd0ZXh0JykpOw0KDQogICAgICAgICAgaXQoJ3Nob3VsZCBpbml0aWFsaXplIHRvIG1vZGVsJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBleHBlY3QodGV4dC5nZXRUZXh0KCkpLnRvQ29udGFpbignZ3Vlc3QnKTsNCiAgICAgICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbigndHJ1ZScpOw0KICAgICAgICAgIH0pOw0KDQogICAgICAgICAgaXQoJ3Nob3VsZCBiZSBpbnZhbGlkIGlmIGVtcHR5JywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBpbnB1dC5jbGVhcigpOw0KICAgICAgICAgICAgaW5wdXQuc2VuZEtleXMoJycpOw0KDQogICAgICAgICAgICBleHBlY3QodGV4dC5nZXRUZXh0KCkpLnRvRXF1YWwoJ3RleHQgPScpOw0KICAgICAgICAgICAgZXhwZWN0KHZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdmYWxzZScpOw0KICAgICAgICAgIH0pOw0KDQogICAgICAgICAgaXQoJ3Nob3VsZCBiZSBpbnZhbGlkIGlmIG11bHRpIHdvcmQnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgICAgIGlucHV0LmNsZWFyKCk7DQogICAgICAgICAgICBpbnB1dC5zZW5kS2V5cygnaGVsbG8gd29ybGQnKTsNCg0KICAgICAgICAgICAgZXhwZWN0KHZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdmYWxzZScpOw0KICAgICAgICAgIH0pOw0KICAgICAgICA8L2ZpbGU+DQogICAgICA8L2V4YW1wbGU+DQogICAqLw0KICAndGV4dCc6IHRleHRJbnB1dFR5cGUsDQoNCiAgICAvKioNCiAgICAgKiBAbmdkb2MgaW5wdXQNCiAgICAgKiBAbmFtZSBpbnB1dFtkYXRlXQ0KICAgICAqDQogICAgICogQGRlc2NyaXB0aW9uDQogICAgICogSW5wdXQgd2l0aCBkYXRlIHZhbGlkYXRpb24gYW5kIHRyYW5zZm9ybWF0aW9uLiBJbiBicm93c2VycyB0aGF0IGRvIG5vdCB5ZXQgc3VwcG9ydA0KICAgICAqIHRoZSBIVE1MNSBkYXRlIGlucHV0LCBhIHRleHQgZWxlbWVudCB3aWxsIGJlIHVzZWQuIEluIHRoYXQgY2FzZSwgdGV4dCBtdXN0IGJlIGVudGVyZWQgaW4gYSB2YWxpZCBJU08tODYwMQ0KICAgICAqIGRhdGUgZm9ybWF0ICh5eXl5LU1NLWRkKSwgZm9yIGV4YW1wbGU6IGAyMDA5LTAxLTA2YC4gU2luY2UgbWFueQ0KICAgICAqIG1vZGVybiBicm93c2VycyBkbyBub3QgeWV0IHN1cHBvcnQgdGhpcyBpbnB1dCB0eXBlLCBpdCBpcyBpbXBvcnRhbnQgdG8gcHJvdmlkZSBjdWVzIHRvIHVzZXJzIG9uIHRoZQ0KICAgICAqIGV4cGVjdGVkIGlucHV0IGZvcm1hdCB2aWEgYSBwbGFjZWhvbGRlciBvciBsYWJlbC4NCiAgICAgKg0KICAgICAqIFRoZSBtb2RlbCBtdXN0IGFsd2F5cyBiZSBhIERhdGUgb2JqZWN0LCBvdGhlcndpc2UgQW5ndWxhciB3aWxsIHRocm93IGFuIGVycm9yLg0KICAgICAqIEludmFsaWQgYERhdGVgIG9iamVjdHMgKGRhdGVzIHdob3NlIGBnZXRUaW1lKClgIGlzIGBOYU5gKSB3aWxsIGJlIHJlbmRlcmVkIGFzIGFuIGVtcHR5IHN0cmluZy4NCiAgICAgKg0KICAgICAqIFRoZSB0aW1lem9uZSB0byBiZSB1c2VkIHRvIHJlYWQvd3JpdGUgdGhlIGBEYXRlYCBpbnN0YW5jZSBpbiB0aGUgbW9kZWwgY2FuIGJlIGRlZmluZWQgdXNpbmcNCiAgICAgKiB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nTW9kZWxPcHRpb25zIG5nTW9kZWxPcHRpb25zfS4gQnkgZGVmYXVsdCwgdGhpcyBpcyB0aGUgdGltZXpvbmUgb2YgdGhlIGJyb3dzZXIuDQogICAgICoNCiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmdNb2RlbCBBc3NpZ25hYmxlIGFuZ3VsYXIgZXhwcmVzc2lvbiB0byBkYXRhLWJpbmQgdG8uDQogICAgICogQHBhcmFtIHtzdHJpbmc9fSBuYW1lIFByb3BlcnR5IG5hbWUgb2YgdGhlIGZvcm0gdW5kZXIgd2hpY2ggdGhlIGNvbnRyb2wgaXMgcHVibGlzaGVkLg0KICAgICAqIEBwYXJhbSB7c3RyaW5nPX0gbWluIFNldHMgdGhlIGBtaW5gIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBlbnRlcmVkIGlzIGxlc3MgdGhhbiBgbWluYC4gVGhpcyBtdXN0IGJlIGENCiAgICAgKiB2YWxpZCBJU08gZGF0ZSBzdHJpbmcgKHl5eXktTU0tZGQpLg0KICAgICAqIEBwYXJhbSB7c3RyaW5nPX0gbWF4IFNldHMgdGhlIGBtYXhgIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBlbnRlcmVkIGlzIGdyZWF0ZXIgdGhhbiBgbWF4YC4gVGhpcyBtdXN0IGJlDQogICAgICogYSB2YWxpZCBJU08gZGF0ZSBzdHJpbmcgKHl5eXktTU0tZGQpLg0KICAgICAqIEBwYXJhbSB7c3RyaW5nPX0gcmVxdWlyZWQgU2V0cyBgcmVxdWlyZWRgIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBpcyBub3QgZW50ZXJlZC4NCiAgICAgKiBAcGFyYW0ge3N0cmluZz19IG5nUmVxdWlyZWQgQWRkcyBgcmVxdWlyZWRgIGF0dHJpYnV0ZSBhbmQgYHJlcXVpcmVkYCB2YWxpZGF0aW9uIGNvbnN0cmFpbnQgdG8NCiAgICAgKiAgICB0aGUgZWxlbWVudCB3aGVuIHRoZSBuZ1JlcXVpcmVkIGV4cHJlc3Npb24gZXZhbHVhdGVzIHRvIHRydWUuIFVzZSBgbmdSZXF1aXJlZGAgaW5zdGVhZCBvZg0KICAgICAqICAgIGByZXF1aXJlZGAgd2hlbiB5b3Ugd2FudCB0byBkYXRhLWJpbmQgdG8gdGhlIGByZXF1aXJlZGAgYXR0cmlidXRlLg0KICAgICAqIEBwYXJhbSB7c3RyaW5nPX0gbmdDaGFuZ2UgQW5ndWxhciBleHByZXNzaW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gaW5wdXQgY2hhbmdlcyBkdWUgdG8gdXNlcg0KICAgICAqICAgIGludGVyYWN0aW9uIHdpdGggdGhlIGlucHV0IGVsZW1lbnQuDQogICAgICoNCiAgICAgKiBAZXhhbXBsZQ0KICAgICA8ZXhhbXBsZSBuYW1lPSJkYXRlLWlucHV0LWRpcmVjdGl2ZSIgbW9kdWxlPSJkYXRlSW5wdXRFeGFtcGxlIj4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPHNjcmlwdD4NCiAgICAgICAgICBhbmd1bGFyLm1vZHVsZSgnZGF0ZUlucHV0RXhhbXBsZScsIFtdKQ0KICAgICAgICAgICAgLmNvbnRyb2xsZXIoJ0RhdGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICAgICAgICAgJHNjb3BlLnZhbHVlID0gbmV3IERhdGUoMjAxMywgOSwgMjIpOw0KICAgICAgICAgICAgfV0pOw0KICAgICAgIDwvc2NyaXB0Pg0KICAgICAgIDxmb3JtIG5hbWU9Im15Rm9ybSIgbmctY29udHJvbGxlcj0iRGF0ZUNvbnRyb2xsZXIgYXMgZGF0ZUN0cmwiPg0KICAgICAgICAgIFBpY2sgYSBkYXRlIGluIDIwMTM6DQogICAgICAgICAgPGlucHV0IHR5cGU9ImRhdGUiIGlkPSJleGFtcGxlSW5wdXQiIG5hbWU9ImlucHV0IiBuZy1tb2RlbD0idmFsdWUiDQogICAgICAgICAgICAgIHBsYWNlaG9sZGVyPSJ5eXl5LU1NLWRkIiBtaW49IjIwMTMtMDEtMDEiIG1heD0iMjAxMy0xMi0zMSIgcmVxdWlyZWQgLz4NCiAgICAgICAgICA8c3BhbiBjbGFzcz0iZXJyb3IiIG5nLXNob3c9Im15Rm9ybS5pbnB1dC4kZXJyb3IucmVxdWlyZWQiPg0KICAgICAgICAgICAgICBSZXF1aXJlZCE8L3NwYW4+DQogICAgICAgICAgPHNwYW4gY2xhc3M9ImVycm9yIiBuZy1zaG93PSJteUZvcm0uaW5wdXQuJGVycm9yLmRhdGUiPg0KICAgICAgICAgICAgICBOb3QgYSB2YWxpZCBkYXRlITwvc3Bhbj4NCiAgICAgICAgICAgPHR0PnZhbHVlID0ge3t2YWx1ZSB8IGRhdGU6ICJ5eXl5LU1NLWRkIn19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLmlucHV0LiR2YWxpZCA9IHt7bXlGb3JtLmlucHV0LiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLmlucHV0LiRlcnJvciA9IHt7bXlGb3JtLmlucHV0LiRlcnJvcn19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLiR2YWxpZCA9IHt7bXlGb3JtLiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLiRlcnJvci5yZXF1aXJlZCA9IHt7ISFteUZvcm0uJGVycm9yLnJlcXVpcmVkfX08L3R0Pjxici8+DQogICAgICAgPC9mb3JtPg0KICAgICA8L2ZpbGU+DQogICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgICB2YXIgdmFsdWUgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ3ZhbHVlIHwgZGF0ZTogInl5eXktTU0tZGQiJykpOw0KICAgICAgICB2YXIgdmFsaWQgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ215Rm9ybS5pbnB1dC4kdmFsaWQnKSk7DQogICAgICAgIHZhciBpbnB1dCA9IGVsZW1lbnQoYnkubW9kZWwoJ3ZhbHVlJykpOw0KDQogICAgICAgIC8vIGN1cnJlbnRseSBwcm90cmFjdG9yL3dlYmRyaXZlciBkb2VzIG5vdCBzdXBwb3J0DQogICAgICAgIC8vIHNlbmRpbmcga2V5cyB0byBhbGwga25vd24gSFRNTDUgaW5wdXQgY29udHJvbHMNCiAgICAgICAgLy8gZm9yIHZhcmlvdXMgYnJvd3NlcnMgKHNlZSBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9wcm90cmFjdG9yL2lzc3Vlcy81NjIpLg0KICAgICAgICBmdW5jdGlvbiBzZXRJbnB1dCh2YWwpIHsNCiAgICAgICAgICAvLyBzZXQgdGhlIHZhbHVlIG9mIHRoZSBlbGVtZW50IGFuZCBmb3JjZSB2YWxpZGF0aW9uLg0KICAgICAgICAgIHZhciBzY3IgPSAidmFyIGlwdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdleGFtcGxlSW5wdXQnKTsgIiArDQogICAgICAgICAgImlwdC52YWx1ZSA9ICciICsgdmFsICsgIic7IiArDQogICAgICAgICAgImFuZ3VsYXIuZWxlbWVudChpcHQpLnNjb3BlKCkuJGFwcGx5KGZ1bmN0aW9uKHMpIHsgcy5teUZvcm1baXB0Lm5hbWVdLiRzZXRWaWV3VmFsdWUoJyIgKyB2YWwgKyAiJyk7IH0pOyI7DQogICAgICAgICAgYnJvd3Nlci5leGVjdXRlU2NyaXB0KHNjcik7DQogICAgICAgIH0NCg0KICAgICAgICBpdCgnc2hvdWxkIGluaXRpYWxpemUgdG8gbW9kZWwnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgICBleHBlY3QodmFsdWUuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJzIwMTMtMTAtMjInKTsNCiAgICAgICAgICBleHBlY3QodmFsaWQuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ215Rm9ybS5pbnB1dC4kdmFsaWQgPSB0cnVlJyk7DQogICAgICAgIH0pOw0KDQogICAgICAgIGl0KCdzaG91bGQgYmUgaW52YWxpZCBpZiBlbXB0eScsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgIHNldElucHV0KCcnKTsNCiAgICAgICAgICBleHBlY3QodmFsdWUuZ2V0VGV4dCgpKS50b0VxdWFsKCd2YWx1ZSA9Jyk7DQogICAgICAgICAgZXhwZWN0KHZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdteUZvcm0uaW5wdXQuJHZhbGlkID0gZmFsc2UnKTsNCiAgICAgICAgfSk7DQoNCiAgICAgICAgaXQoJ3Nob3VsZCBiZSBpbnZhbGlkIGlmIG92ZXIgbWF4JywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgc2V0SW5wdXQoJzIwMTUtMDEtMDEnKTsNCiAgICAgICAgICBleHBlY3QodmFsdWUuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJycpOw0KICAgICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignbXlGb3JtLmlucHV0LiR2YWxpZCA9IGZhbHNlJyk7DQogICAgICAgIH0pOw0KICAgICA8L2ZpbGU+DQogICAgIDwvZXhhbXBsZT4NCiAgICAgKi8NCiAgJ2RhdGUnOiBjcmVhdGVEYXRlSW5wdXRUeXBlKCdkYXRlJywgREFURV9SRUdFWFAsDQogICAgICAgICBjcmVhdGVEYXRlUGFyc2VyKERBVEVfUkVHRVhQLCBbJ3l5eXknLCAnTU0nLCAnZGQnXSksDQogICAgICAgICAneXl5eS1NTS1kZCcpLA0KDQogICAvKioNCiAgICAqIEBuZ2RvYyBpbnB1dA0KICAgICogQG5hbWUgaW5wdXRbZGF0ZXRpbWUtbG9jYWxdDQogICAgKg0KICAgICogQGRlc2NyaXB0aW9uDQogICAgKiBJbnB1dCB3aXRoIGRhdGV0aW1lIHZhbGlkYXRpb24gYW5kIHRyYW5zZm9ybWF0aW9uLiBJbiBicm93c2VycyB0aGF0IGRvIG5vdCB5ZXQgc3VwcG9ydA0KICAgICogdGhlIEhUTUw1IGRhdGUgaW5wdXQsIGEgdGV4dCBlbGVtZW50IHdpbGwgYmUgdXNlZC4gSW4gdGhhdCBjYXNlLCB0aGUgdGV4dCBtdXN0IGJlIGVudGVyZWQgaW4gYSB2YWxpZCBJU08tODYwMQ0KICAgICogbG9jYWwgZGF0ZXRpbWUgZm9ybWF0ICh5eXl5LU1NLWRkVEhIOm1tOnNzKSwgZm9yIGV4YW1wbGU6IGAyMDEwLTEyLTI4VDE0OjU3OjAwYC4NCiAgICAqDQogICAgKiBUaGUgbW9kZWwgbXVzdCBhbHdheXMgYmUgYSBEYXRlIG9iamVjdCwgb3RoZXJ3aXNlIEFuZ3VsYXIgd2lsbCB0aHJvdyBhbiBlcnJvci4NCiAgICAqIEludmFsaWQgYERhdGVgIG9iamVjdHMgKGRhdGVzIHdob3NlIGBnZXRUaW1lKClgIGlzIGBOYU5gKSB3aWxsIGJlIHJlbmRlcmVkIGFzIGFuIGVtcHR5IHN0cmluZy4NCiAgICAqDQogICAgKiBUaGUgdGltZXpvbmUgdG8gYmUgdXNlZCB0byByZWFkL3dyaXRlIHRoZSBgRGF0ZWAgaW5zdGFuY2UgaW4gdGhlIG1vZGVsIGNhbiBiZSBkZWZpbmVkIHVzaW5nDQogICAgKiB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nTW9kZWxPcHRpb25zIG5nTW9kZWxPcHRpb25zfS4gQnkgZGVmYXVsdCwgdGhpcyBpcyB0aGUgdGltZXpvbmUgb2YgdGhlIGJyb3dzZXIuDQogICAgKg0KICAgICogQHBhcmFtIHtzdHJpbmd9IG5nTW9kZWwgQXNzaWduYWJsZSBhbmd1bGFyIGV4cHJlc3Npb24gdG8gZGF0YS1iaW5kIHRvLg0KICAgICogQHBhcmFtIHtzdHJpbmc9fSBuYW1lIFByb3BlcnR5IG5hbWUgb2YgdGhlIGZvcm0gdW5kZXIgd2hpY2ggdGhlIGNvbnRyb2wgaXMgcHVibGlzaGVkLg0KICAgICogQHBhcmFtIHtzdHJpbmc9fSBtaW4gU2V0cyB0aGUgYG1pbmAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGVudGVyZWQgaXMgbGVzcyB0aGFuIGBtaW5gLiBUaGlzIG11c3QgYmUgYQ0KICAgICogdmFsaWQgSVNPIGRhdGV0aW1lIGZvcm1hdCAoeXl5eS1NTS1kZFRISDptbTpzcykuDQogICAgKiBAcGFyYW0ge3N0cmluZz19IG1heCBTZXRzIHRoZSBgbWF4YCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgdmFsdWUgZW50ZXJlZCBpcyBncmVhdGVyIHRoYW4gYG1heGAuIFRoaXMgbXVzdCBiZQ0KICAgICogYSB2YWxpZCBJU08gZGF0ZXRpbWUgZm9ybWF0ICh5eXl5LU1NLWRkVEhIOm1tOnNzKS4NCiAgICAqIEBwYXJhbSB7c3RyaW5nPX0gcmVxdWlyZWQgU2V0cyBgcmVxdWlyZWRgIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBpcyBub3QgZW50ZXJlZC4NCiAgICAqIEBwYXJhbSB7c3RyaW5nPX0gbmdSZXF1aXJlZCBBZGRzIGByZXF1aXJlZGAgYXR0cmlidXRlIGFuZCBgcmVxdWlyZWRgIHZhbGlkYXRpb24gY29uc3RyYWludCB0bw0KICAgICogICAgdGhlIGVsZW1lbnQgd2hlbiB0aGUgbmdSZXF1aXJlZCBleHByZXNzaW9uIGV2YWx1YXRlcyB0byB0cnVlLiBVc2UgYG5nUmVxdWlyZWRgIGluc3RlYWQgb2YNCiAgICAqICAgIGByZXF1aXJlZGAgd2hlbiB5b3Ugd2FudCB0byBkYXRhLWJpbmQgdG8gdGhlIGByZXF1aXJlZGAgYXR0cmlidXRlLg0KICAgICogQHBhcmFtIHtzdHJpbmc9fSBuZ0NoYW5nZSBBbmd1bGFyIGV4cHJlc3Npb24gdG8gYmUgZXhlY3V0ZWQgd2hlbiBpbnB1dCBjaGFuZ2VzIGR1ZSB0byB1c2VyDQogICAgKiAgICBpbnRlcmFjdGlvbiB3aXRoIHRoZSBpbnB1dCBlbGVtZW50Lg0KICAgICoNCiAgICAqIEBleGFtcGxlDQogICAgPGV4YW1wbGUgbmFtZT0iZGF0ZXRpbWVsb2NhbC1pbnB1dC1kaXJlY3RpdmUiIG1vZHVsZT0iZGF0ZUV4YW1wbGUiPg0KICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgPHNjcmlwdD4NCiAgICAgICAgYW5ndWxhci5tb2R1bGUoJ2RhdGVFeGFtcGxlJywgW10pDQogICAgICAgICAgLmNvbnRyb2xsZXIoJ0RhdGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICAgICAgICRzY29wZS52YWx1ZSA9IG5ldyBEYXRlKDIwMTAsIDExLCAyOCwgMTQsIDU3KTsNCiAgICAgICAgICB9XSk7DQogICAgICA8L3NjcmlwdD4NCiAgICAgIDxmb3JtIG5hbWU9Im15Rm9ybSIgbmctY29udHJvbGxlcj0iRGF0ZUNvbnRyb2xsZXIgYXMgZGF0ZUN0cmwiPg0KICAgICAgICBQaWNrIGEgZGF0ZSBiZXR3ZWVuIGluIDIwMTM6DQogICAgICAgIDxpbnB1dCB0eXBlPSJkYXRldGltZS1sb2NhbCIgaWQ9ImV4YW1wbGVJbnB1dCIgbmFtZT0iaW5wdXQiIG5nLW1vZGVsPSJ2YWx1ZSINCiAgICAgICAgICAgIHBsYWNlaG9sZGVyPSJ5eXl5LU1NLWRkVEhIOm1tOnNzIiBtaW49IjIwMDEtMDEtMDFUMDA6MDA6MDAiIG1heD0iMjAxMy0xMi0zMVQwMDowMDowMCIgcmVxdWlyZWQgLz4NCiAgICAgICAgPHNwYW4gY2xhc3M9ImVycm9yIiBuZy1zaG93PSJteUZvcm0uaW5wdXQuJGVycm9yLnJlcXVpcmVkIj4NCiAgICAgICAgICAgIFJlcXVpcmVkITwvc3Bhbj4NCiAgICAgICAgPHNwYW4gY2xhc3M9ImVycm9yIiBuZy1zaG93PSJteUZvcm0uaW5wdXQuJGVycm9yLmRhdGV0aW1lbG9jYWwiPg0KICAgICAgICAgICAgTm90IGEgdmFsaWQgZGF0ZSE8L3NwYW4+DQogICAgICAgIDx0dD52YWx1ZSA9IHt7dmFsdWUgfCBkYXRlOiAieXl5eS1NTS1kZFRISDptbTpzcyJ9fTwvdHQ+PGJyLz4NCiAgICAgICAgPHR0Pm15Rm9ybS5pbnB1dC4kdmFsaWQgPSB7e215Rm9ybS5pbnB1dC4kdmFsaWR9fTwvdHQ+PGJyLz4NCiAgICAgICAgPHR0Pm15Rm9ybS5pbnB1dC4kZXJyb3IgPSB7e215Rm9ybS5pbnB1dC4kZXJyb3J9fTwvdHQ+PGJyLz4NCiAgICAgICAgPHR0Pm15Rm9ybS4kdmFsaWQgPSB7e215Rm9ybS4kdmFsaWR9fTwvdHQ+PGJyLz4NCiAgICAgICAgPHR0Pm15Rm9ybS4kZXJyb3IucmVxdWlyZWQgPSB7eyEhbXlGb3JtLiRlcnJvci5yZXF1aXJlZH19PC90dD48YnIvPg0KICAgICAgPC9mb3JtPg0KICAgIDwvZmlsZT4NCiAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgIHZhciB2YWx1ZSA9IGVsZW1lbnQoYnkuYmluZGluZygndmFsdWUgfCBkYXRlOiAieXl5eS1NTS1kZFRISDptbTpzcyInKSk7DQogICAgICB2YXIgdmFsaWQgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ215Rm9ybS5pbnB1dC4kdmFsaWQnKSk7DQogICAgICB2YXIgaW5wdXQgPSBlbGVtZW50KGJ5Lm1vZGVsKCd2YWx1ZScpKTsNCg0KICAgICAgLy8gY3VycmVudGx5IHByb3RyYWN0b3Ivd2ViZHJpdmVyIGRvZXMgbm90IHN1cHBvcnQNCiAgICAgIC8vIHNlbmRpbmcga2V5cyB0byBhbGwga25vd24gSFRNTDUgaW5wdXQgY29udHJvbHMNCiAgICAgIC8vIGZvciB2YXJpb3VzIGJyb3dzZXJzIChodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9wcm90cmFjdG9yL2lzc3Vlcy81NjIpLg0KICAgICAgZnVuY3Rpb24gc2V0SW5wdXQodmFsKSB7DQogICAgICAgIC8vIHNldCB0aGUgdmFsdWUgb2YgdGhlIGVsZW1lbnQgYW5kIGZvcmNlIHZhbGlkYXRpb24uDQogICAgICAgIHZhciBzY3IgPSAidmFyIGlwdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdleGFtcGxlSW5wdXQnKTsgIiArDQogICAgICAgICJpcHQudmFsdWUgPSAnIiArIHZhbCArICInOyIgKw0KICAgICAgICAiYW5ndWxhci5lbGVtZW50KGlwdCkuc2NvcGUoKS4kYXBwbHkoZnVuY3Rpb24ocykgeyBzLm15Rm9ybVtpcHQubmFtZV0uJHNldFZpZXdWYWx1ZSgnIiArIHZhbCArICInKTsgfSk7IjsNCiAgICAgICAgYnJvd3Nlci5leGVjdXRlU2NyaXB0KHNjcik7DQogICAgICB9DQoNCiAgICAgIGl0KCdzaG91bGQgaW5pdGlhbGl6ZSB0byBtb2RlbCcsIGZ1bmN0aW9uKCkgew0KICAgICAgICBleHBlY3QodmFsdWUuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJzIwMTAtMTItMjhUMTQ6NTc6MDAnKTsNCiAgICAgICAgZXhwZWN0KHZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdteUZvcm0uaW5wdXQuJHZhbGlkID0gdHJ1ZScpOw0KICAgICAgfSk7DQoNCiAgICAgIGl0KCdzaG91bGQgYmUgaW52YWxpZCBpZiBlbXB0eScsIGZ1bmN0aW9uKCkgew0KICAgICAgICBzZXRJbnB1dCgnJyk7DQogICAgICAgIGV4cGVjdCh2YWx1ZS5nZXRUZXh0KCkpLnRvRXF1YWwoJ3ZhbHVlID0nKTsNCiAgICAgICAgZXhwZWN0KHZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdteUZvcm0uaW5wdXQuJHZhbGlkID0gZmFsc2UnKTsNCiAgICAgIH0pOw0KDQogICAgICBpdCgnc2hvdWxkIGJlIGludmFsaWQgaWYgb3ZlciBtYXgnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgc2V0SW5wdXQoJzIwMTUtMDEtMDFUMjM6NTk6MDAnKTsNCiAgICAgICAgZXhwZWN0KHZhbHVlLmdldFRleHQoKSkudG9Db250YWluKCcnKTsNCiAgICAgICAgZXhwZWN0KHZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdteUZvcm0uaW5wdXQuJHZhbGlkID0gZmFsc2UnKTsNCiAgICAgIH0pOw0KICAgIDwvZmlsZT4NCiAgICA8L2V4YW1wbGU+DQogICAgKi8NCiAgJ2RhdGV0aW1lLWxvY2FsJzogY3JlYXRlRGF0ZUlucHV0VHlwZSgnZGF0ZXRpbWVsb2NhbCcsIERBVEVUSU1FTE9DQUxfUkVHRVhQLA0KICAgICAgY3JlYXRlRGF0ZVBhcnNlcihEQVRFVElNRUxPQ0FMX1JFR0VYUCwgWyd5eXl5JywgJ01NJywgJ2RkJywgJ0hIJywgJ21tJywgJ3NzJywgJ3NzcyddKSwNCiAgICAgICd5eXl5LU1NLWRkVEhIOm1tOnNzLnNzcycpLA0KDQogIC8qKg0KICAgKiBAbmdkb2MgaW5wdXQNCiAgICogQG5hbWUgaW5wdXRbdGltZV0NCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIElucHV0IHdpdGggdGltZSB2YWxpZGF0aW9uIGFuZCB0cmFuc2Zvcm1hdGlvbi4gSW4gYnJvd3NlcnMgdGhhdCBkbyBub3QgeWV0IHN1cHBvcnQNCiAgICogdGhlIEhUTUw1IGRhdGUgaW5wdXQsIGEgdGV4dCBlbGVtZW50IHdpbGwgYmUgdXNlZC4gSW4gdGhhdCBjYXNlLCB0aGUgdGV4dCBtdXN0IGJlIGVudGVyZWQgaW4gYSB2YWxpZCBJU08tODYwMQ0KICAgKiBsb2NhbCB0aW1lIGZvcm1hdCAoSEg6bW06c3MpLCBmb3IgZXhhbXBsZTogYDE0OjU3OjAwYC4gTW9kZWwgbXVzdCBiZSBhIERhdGUgb2JqZWN0LiBUaGlzIGJpbmRpbmcgd2lsbCBhbHdheXMgb3V0cHV0IGENCiAgICogRGF0ZSBvYmplY3QgdG8gdGhlIG1vZGVsIG9mIEphbnVhcnkgMSwgMTk3MCwgb3IgbG9jYWwgZGF0ZSBgbmV3IERhdGUoMTk3MCwgMCwgMSwgSEgsIG1tLCBzcylgLg0KICAgKg0KICAgKiBUaGUgbW9kZWwgbXVzdCBhbHdheXMgYmUgYSBEYXRlIG9iamVjdCwgb3RoZXJ3aXNlIEFuZ3VsYXIgd2lsbCB0aHJvdyBhbiBlcnJvci4NCiAgICogSW52YWxpZCBgRGF0ZWAgb2JqZWN0cyAoZGF0ZXMgd2hvc2UgYGdldFRpbWUoKWAgaXMgYE5hTmApIHdpbGwgYmUgcmVuZGVyZWQgYXMgYW4gZW1wdHkgc3RyaW5nLg0KICAgKg0KICAgKiBUaGUgdGltZXpvbmUgdG8gYmUgdXNlZCB0byByZWFkL3dyaXRlIHRoZSBgRGF0ZWAgaW5zdGFuY2UgaW4gdGhlIG1vZGVsIGNhbiBiZSBkZWZpbmVkIHVzaW5nDQogICAqIHtAbGluayBuZy5kaXJlY3RpdmU6bmdNb2RlbE9wdGlvbnMgbmdNb2RlbE9wdGlvbnN9LiBCeSBkZWZhdWx0LCB0aGlzIGlzIHRoZSB0aW1lem9uZSBvZiB0aGUgYnJvd3Nlci4NCiAgICoNCiAgICogQHBhcmFtIHtzdHJpbmd9IG5nTW9kZWwgQXNzaWduYWJsZSBhbmd1bGFyIGV4cHJlc3Npb24gdG8gZGF0YS1iaW5kIHRvLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IG5hbWUgUHJvcGVydHkgbmFtZSBvZiB0aGUgZm9ybSB1bmRlciB3aGljaCB0aGUgY29udHJvbCBpcyBwdWJsaXNoZWQuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbWluIFNldHMgdGhlIGBtaW5gIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBlbnRlcmVkIGlzIGxlc3MgdGhhbiBgbWluYC4gVGhpcyBtdXN0IGJlIGENCiAgICogdmFsaWQgSVNPIHRpbWUgZm9ybWF0IChISDptbTpzcykuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbWF4IFNldHMgdGhlIGBtYXhgIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBlbnRlcmVkIGlzIGdyZWF0ZXIgdGhhbiBgbWF4YC4gVGhpcyBtdXN0IGJlIGENCiAgICogdmFsaWQgSVNPIHRpbWUgZm9ybWF0IChISDptbTpzcykuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gcmVxdWlyZWQgU2V0cyBgcmVxdWlyZWRgIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBpcyBub3QgZW50ZXJlZC4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSBuZ1JlcXVpcmVkIEFkZHMgYHJlcXVpcmVkYCBhdHRyaWJ1dGUgYW5kIGByZXF1aXJlZGAgdmFsaWRhdGlvbiBjb25zdHJhaW50IHRvDQogICAqICAgIHRoZSBlbGVtZW50IHdoZW4gdGhlIG5nUmVxdWlyZWQgZXhwcmVzc2lvbiBldmFsdWF0ZXMgdG8gdHJ1ZS4gVXNlIGBuZ1JlcXVpcmVkYCBpbnN0ZWFkIG9mDQogICAqICAgIGByZXF1aXJlZGAgd2hlbiB5b3Ugd2FudCB0byBkYXRhLWJpbmQgdG8gdGhlIGByZXF1aXJlZGAgYXR0cmlidXRlLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IG5nQ2hhbmdlIEFuZ3VsYXIgZXhwcmVzc2lvbiB0byBiZSBleGVjdXRlZCB3aGVuIGlucHV0IGNoYW5nZXMgZHVlIHRvIHVzZXINCiAgICogICAgaW50ZXJhY3Rpb24gd2l0aCB0aGUgaW5wdXQgZWxlbWVudC4NCiAgICoNCiAgICogQGV4YW1wbGUNCiAgIDxleGFtcGxlIG5hbWU9InRpbWUtaW5wdXQtZGlyZWN0aXZlIiBtb2R1bGU9InRpbWVFeGFtcGxlIj4NCiAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICA8c2NyaXB0Pg0KICAgICAgYW5ndWxhci5tb2R1bGUoJ3RpbWVFeGFtcGxlJywgW10pDQogICAgICAgIC5jb250cm9sbGVyKCdEYXRlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgICAgJHNjb3BlLnZhbHVlID0gbmV3IERhdGUoMTk3MCwgMCwgMSwgMTQsIDU3LCAwKTsNCiAgICAgICAgfV0pOw0KICAgICA8L3NjcmlwdD4NCiAgICAgPGZvcm0gbmFtZT0ibXlGb3JtIiBuZy1jb250cm9sbGVyPSJEYXRlQ29udHJvbGxlciBhcyBkYXRlQ3RybCI+DQogICAgICAgIFBpY2sgYSBiZXR3ZWVuIDhhbSBhbmQgNXBtOg0KICAgICAgICA8aW5wdXQgdHlwZT0idGltZSIgaWQ9ImV4YW1wbGVJbnB1dCIgbmFtZT0iaW5wdXQiIG5nLW1vZGVsPSJ2YWx1ZSINCiAgICAgICAgICAgIHBsYWNlaG9sZGVyPSJISDptbTpzcyIgbWluPSIwODowMDowMCIgbWF4PSIxNzowMDowMCIgcmVxdWlyZWQgLz4NCiAgICAgICAgPHNwYW4gY2xhc3M9ImVycm9yIiBuZy1zaG93PSJteUZvcm0uaW5wdXQuJGVycm9yLnJlcXVpcmVkIj4NCiAgICAgICAgICAgIFJlcXVpcmVkITwvc3Bhbj4NCiAgICAgICAgPHNwYW4gY2xhc3M9ImVycm9yIiBuZy1zaG93PSJteUZvcm0uaW5wdXQuJGVycm9yLnRpbWUiPg0KICAgICAgICAgICAgTm90IGEgdmFsaWQgZGF0ZSE8L3NwYW4+DQogICAgICAgIDx0dD52YWx1ZSA9IHt7dmFsdWUgfCBkYXRlOiAiSEg6bW06c3MifX08L3R0Pjxici8+DQogICAgICAgIDx0dD5teUZvcm0uaW5wdXQuJHZhbGlkID0ge3tteUZvcm0uaW5wdXQuJHZhbGlkfX08L3R0Pjxici8+DQogICAgICAgIDx0dD5teUZvcm0uaW5wdXQuJGVycm9yID0ge3tteUZvcm0uaW5wdXQuJGVycm9yfX08L3R0Pjxici8+DQogICAgICAgIDx0dD5teUZvcm0uJHZhbGlkID0ge3tteUZvcm0uJHZhbGlkfX08L3R0Pjxici8+DQogICAgICAgIDx0dD5teUZvcm0uJGVycm9yLnJlcXVpcmVkID0ge3shIW15Rm9ybS4kZXJyb3IucmVxdWlyZWR9fTwvdHQ+PGJyLz4NCiAgICAgPC9mb3JtPg0KICAgPC9maWxlPg0KICAgPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogICAgICB2YXIgdmFsdWUgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ3ZhbHVlIHwgZGF0ZTogIkhIOm1tOnNzIicpKTsNCiAgICAgIHZhciB2YWxpZCA9IGVsZW1lbnQoYnkuYmluZGluZygnbXlGb3JtLmlucHV0LiR2YWxpZCcpKTsNCiAgICAgIHZhciBpbnB1dCA9IGVsZW1lbnQoYnkubW9kZWwoJ3ZhbHVlJykpOw0KDQogICAgICAvLyBjdXJyZW50bHkgcHJvdHJhY3Rvci93ZWJkcml2ZXIgZG9lcyBub3Qgc3VwcG9ydA0KICAgICAgLy8gc2VuZGluZyBrZXlzIHRvIGFsbCBrbm93biBIVE1MNSBpbnB1dCBjb250cm9scw0KICAgICAgLy8gZm9yIHZhcmlvdXMgYnJvd3NlcnMgKGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL3Byb3RyYWN0b3IvaXNzdWVzLzU2MikuDQogICAgICBmdW5jdGlvbiBzZXRJbnB1dCh2YWwpIHsNCiAgICAgICAgLy8gc2V0IHRoZSB2YWx1ZSBvZiB0aGUgZWxlbWVudCBhbmQgZm9yY2UgdmFsaWRhdGlvbi4NCiAgICAgICAgdmFyIHNjciA9ICJ2YXIgaXB0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2V4YW1wbGVJbnB1dCcpOyAiICsNCiAgICAgICAgImlwdC52YWx1ZSA9ICciICsgdmFsICsgIic7IiArDQogICAgICAgICJhbmd1bGFyLmVsZW1lbnQoaXB0KS5zY29wZSgpLiRhcHBseShmdW5jdGlvbihzKSB7IHMubXlGb3JtW2lwdC5uYW1lXS4kc2V0Vmlld1ZhbHVlKCciICsgdmFsICsgIicpOyB9KTsiOw0KICAgICAgICBicm93c2VyLmV4ZWN1dGVTY3JpcHQoc2NyKTsNCiAgICAgIH0NCg0KICAgICAgaXQoJ3Nob3VsZCBpbml0aWFsaXplIHRvIG1vZGVsJywgZnVuY3Rpb24oKSB7DQogICAgICAgIGV4cGVjdCh2YWx1ZS5nZXRUZXh0KCkpLnRvQ29udGFpbignMTQ6NTc6MDAnKTsNCiAgICAgICAgZXhwZWN0KHZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdteUZvcm0uaW5wdXQuJHZhbGlkID0gdHJ1ZScpOw0KICAgICAgfSk7DQoNCiAgICAgIGl0KCdzaG91bGQgYmUgaW52YWxpZCBpZiBlbXB0eScsIGZ1bmN0aW9uKCkgew0KICAgICAgICBzZXRJbnB1dCgnJyk7DQogICAgICAgIGV4cGVjdCh2YWx1ZS5nZXRUZXh0KCkpLnRvRXF1YWwoJ3ZhbHVlID0nKTsNCiAgICAgICAgZXhwZWN0KHZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdteUZvcm0uaW5wdXQuJHZhbGlkID0gZmFsc2UnKTsNCiAgICAgIH0pOw0KDQogICAgICBpdCgnc2hvdWxkIGJlIGludmFsaWQgaWYgb3ZlciBtYXgnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgc2V0SW5wdXQoJzIzOjU5OjAwJyk7DQogICAgICAgIGV4cGVjdCh2YWx1ZS5nZXRUZXh0KCkpLnRvQ29udGFpbignJyk7DQogICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignbXlGb3JtLmlucHV0LiR2YWxpZCA9IGZhbHNlJyk7DQogICAgICB9KTsNCiAgIDwvZmlsZT4NCiAgIDwvZXhhbXBsZT4NCiAgICovDQogICd0aW1lJzogY3JlYXRlRGF0ZUlucHV0VHlwZSgndGltZScsIFRJTUVfUkVHRVhQLA0KICAgICAgY3JlYXRlRGF0ZVBhcnNlcihUSU1FX1JFR0VYUCwgWydISCcsICdtbScsICdzcycsICdzc3MnXSksDQogICAgICdISDptbTpzcy5zc3MnKSwNCg0KICAgLyoqDQogICAgKiBAbmdkb2MgaW5wdXQNCiAgICAqIEBuYW1lIGlucHV0W3dlZWtdDQogICAgKg0KICAgICogQGRlc2NyaXB0aW9uDQogICAgKiBJbnB1dCB3aXRoIHdlZWstb2YtdGhlLXllYXIgdmFsaWRhdGlvbiBhbmQgdHJhbnNmb3JtYXRpb24gdG8gRGF0ZS4gSW4gYnJvd3NlcnMgdGhhdCBkbyBub3QgeWV0IHN1cHBvcnQNCiAgICAqIHRoZSBIVE1MNSB3ZWVrIGlucHV0LCBhIHRleHQgZWxlbWVudCB3aWxsIGJlIHVzZWQuIEluIHRoYXQgY2FzZSwgdGhlIHRleHQgbXVzdCBiZSBlbnRlcmVkIGluIGEgdmFsaWQgSVNPLTg2MDENCiAgICAqIHdlZWsgZm9ybWF0ICh5eXl5LVcjIyksIGZvciBleGFtcGxlOiBgMjAxMy1XMDJgLg0KICAgICoNCiAgICAqIFRoZSBtb2RlbCBtdXN0IGFsd2F5cyBiZSBhIERhdGUgb2JqZWN0LCBvdGhlcndpc2UgQW5ndWxhciB3aWxsIHRocm93IGFuIGVycm9yLg0KICAgICogSW52YWxpZCBgRGF0ZWAgb2JqZWN0cyAoZGF0ZXMgd2hvc2UgYGdldFRpbWUoKWAgaXMgYE5hTmApIHdpbGwgYmUgcmVuZGVyZWQgYXMgYW4gZW1wdHkgc3RyaW5nLg0KICAgICoNCiAgICAqIFRoZSB0aW1lem9uZSB0byBiZSB1c2VkIHRvIHJlYWQvd3JpdGUgdGhlIGBEYXRlYCBpbnN0YW5jZSBpbiB0aGUgbW9kZWwgY2FuIGJlIGRlZmluZWQgdXNpbmcNCiAgICAqIHtAbGluayBuZy5kaXJlY3RpdmU6bmdNb2RlbE9wdGlvbnMgbmdNb2RlbE9wdGlvbnN9LiBCeSBkZWZhdWx0LCB0aGlzIGlzIHRoZSB0aW1lem9uZSBvZiB0aGUgYnJvd3Nlci4NCiAgICAqDQogICAgKiBAcGFyYW0ge3N0cmluZ30gbmdNb2RlbCBBc3NpZ25hYmxlIGFuZ3VsYXIgZXhwcmVzc2lvbiB0byBkYXRhLWJpbmQgdG8uDQogICAgKiBAcGFyYW0ge3N0cmluZz19IG5hbWUgUHJvcGVydHkgbmFtZSBvZiB0aGUgZm9ybSB1bmRlciB3aGljaCB0aGUgY29udHJvbCBpcyBwdWJsaXNoZWQuDQogICAgKiBAcGFyYW0ge3N0cmluZz19IG1pbiBTZXRzIHRoZSBgbWluYCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgdmFsdWUgZW50ZXJlZCBpcyBsZXNzIHRoYW4gYG1pbmAuIFRoaXMgbXVzdCBiZSBhDQogICAgKiB2YWxpZCBJU08gd2VlayBmb3JtYXQgKHl5eXktVyMjKS4NCiAgICAqIEBwYXJhbSB7c3RyaW5nPX0gbWF4IFNldHMgdGhlIGBtYXhgIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBlbnRlcmVkIGlzIGdyZWF0ZXIgdGhhbiBgbWF4YC4gVGhpcyBtdXN0IGJlDQogICAgKiBhIHZhbGlkIElTTyB3ZWVrIGZvcm1hdCAoeXl5eS1XIyMpLg0KICAgICogQHBhcmFtIHtzdHJpbmc9fSByZXF1aXJlZCBTZXRzIGByZXF1aXJlZGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGlzIG5vdCBlbnRlcmVkLg0KICAgICogQHBhcmFtIHtzdHJpbmc9fSBuZ1JlcXVpcmVkIEFkZHMgYHJlcXVpcmVkYCBhdHRyaWJ1dGUgYW5kIGByZXF1aXJlZGAgdmFsaWRhdGlvbiBjb25zdHJhaW50IHRvDQogICAgKiAgICB0aGUgZWxlbWVudCB3aGVuIHRoZSBuZ1JlcXVpcmVkIGV4cHJlc3Npb24gZXZhbHVhdGVzIHRvIHRydWUuIFVzZSBgbmdSZXF1aXJlZGAgaW5zdGVhZCBvZg0KICAgICogICAgYHJlcXVpcmVkYCB3aGVuIHlvdSB3YW50IHRvIGRhdGEtYmluZCB0byB0aGUgYHJlcXVpcmVkYCBhdHRyaWJ1dGUuDQogICAgKiBAcGFyYW0ge3N0cmluZz19IG5nQ2hhbmdlIEFuZ3VsYXIgZXhwcmVzc2lvbiB0byBiZSBleGVjdXRlZCB3aGVuIGlucHV0IGNoYW5nZXMgZHVlIHRvIHVzZXINCiAgICAqICAgIGludGVyYWN0aW9uIHdpdGggdGhlIGlucHV0IGVsZW1lbnQuDQogICAgKg0KICAgICogQGV4YW1wbGUNCiAgICA8ZXhhbXBsZSBuYW1lPSJ3ZWVrLWlucHV0LWRpcmVjdGl2ZSIgbW9kdWxlPSJ3ZWVrRXhhbXBsZSI+DQogICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICA8c2NyaXB0Pg0KICAgICAgYW5ndWxhci5tb2R1bGUoJ3dlZWtFeGFtcGxlJywgW10pDQogICAgICAgIC5jb250cm9sbGVyKCdEYXRlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgICAgJHNjb3BlLnZhbHVlID0gbmV3IERhdGUoMjAxMywgMCwgMyk7DQogICAgICAgIH1dKTsNCiAgICAgIDwvc2NyaXB0Pg0KICAgICAgPGZvcm0gbmFtZT0ibXlGb3JtIiBuZy1jb250cm9sbGVyPSJEYXRlQ29udHJvbGxlciBhcyBkYXRlQ3RybCI+DQogICAgICAgIFBpY2sgYSBkYXRlIGJldHdlZW4gaW4gMjAxMzoNCiAgICAgICAgPGlucHV0IGlkPSJleGFtcGxlSW5wdXQiIHR5cGU9IndlZWsiIG5hbWU9ImlucHV0IiBuZy1tb2RlbD0idmFsdWUiDQogICAgICAgICAgICBwbGFjZWhvbGRlcj0iWVlZWS1XIyMiIG1pbj0iMjAxMi1XMzIiIG1heD0iMjAxMy1XNTIiIHJlcXVpcmVkIC8+DQogICAgICAgIDxzcGFuIGNsYXNzPSJlcnJvciIgbmctc2hvdz0ibXlGb3JtLmlucHV0LiRlcnJvci5yZXF1aXJlZCI+DQogICAgICAgICAgICBSZXF1aXJlZCE8L3NwYW4+DQogICAgICAgIDxzcGFuIGNsYXNzPSJlcnJvciIgbmctc2hvdz0ibXlGb3JtLmlucHV0LiRlcnJvci53ZWVrIj4NCiAgICAgICAgICAgIE5vdCBhIHZhbGlkIGRhdGUhPC9zcGFuPg0KICAgICAgICA8dHQ+dmFsdWUgPSB7e3ZhbHVlIHwgZGF0ZTogInl5eXktV3d3In19PC90dD48YnIvPg0KICAgICAgICA8dHQ+bXlGb3JtLmlucHV0LiR2YWxpZCA9IHt7bXlGb3JtLmlucHV0LiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgICA8dHQ+bXlGb3JtLmlucHV0LiRlcnJvciA9IHt7bXlGb3JtLmlucHV0LiRlcnJvcn19PC90dD48YnIvPg0KICAgICAgICA8dHQ+bXlGb3JtLiR2YWxpZCA9IHt7bXlGb3JtLiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgICA8dHQ+bXlGb3JtLiRlcnJvci5yZXF1aXJlZCA9IHt7ISFteUZvcm0uJGVycm9yLnJlcXVpcmVkfX08L3R0Pjxici8+DQogICAgICA8L2Zvcm0+DQogICAgPC9maWxlPg0KICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgdmFyIHZhbHVlID0gZWxlbWVudChieS5iaW5kaW5nKCd2YWx1ZSB8IGRhdGU6ICJ5eXl5LVd3dyInKSk7DQogICAgICB2YXIgdmFsaWQgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ215Rm9ybS5pbnB1dC4kdmFsaWQnKSk7DQogICAgICB2YXIgaW5wdXQgPSBlbGVtZW50KGJ5Lm1vZGVsKCd2YWx1ZScpKTsNCg0KICAgICAgLy8gY3VycmVudGx5IHByb3RyYWN0b3Ivd2ViZHJpdmVyIGRvZXMgbm90IHN1cHBvcnQNCiAgICAgIC8vIHNlbmRpbmcga2V5cyB0byBhbGwga25vd24gSFRNTDUgaW5wdXQgY29udHJvbHMNCiAgICAgIC8vIGZvciB2YXJpb3VzIGJyb3dzZXJzIChodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9wcm90cmFjdG9yL2lzc3Vlcy81NjIpLg0KICAgICAgZnVuY3Rpb24gc2V0SW5wdXQodmFsKSB7DQogICAgICAgIC8vIHNldCB0aGUgdmFsdWUgb2YgdGhlIGVsZW1lbnQgYW5kIGZvcmNlIHZhbGlkYXRpb24uDQogICAgICAgIHZhciBzY3IgPSAidmFyIGlwdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdleGFtcGxlSW5wdXQnKTsgIiArDQogICAgICAgICJpcHQudmFsdWUgPSAnIiArIHZhbCArICInOyIgKw0KICAgICAgICAiYW5ndWxhci5lbGVtZW50KGlwdCkuc2NvcGUoKS4kYXBwbHkoZnVuY3Rpb24ocykgeyBzLm15Rm9ybVtpcHQubmFtZV0uJHNldFZpZXdWYWx1ZSgnIiArIHZhbCArICInKTsgfSk7IjsNCiAgICAgICAgYnJvd3Nlci5leGVjdXRlU2NyaXB0KHNjcik7DQogICAgICB9DQoNCiAgICAgIGl0KCdzaG91bGQgaW5pdGlhbGl6ZSB0byBtb2RlbCcsIGZ1bmN0aW9uKCkgew0KICAgICAgICBleHBlY3QodmFsdWUuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJzIwMTMtVzAxJyk7DQogICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignbXlGb3JtLmlucHV0LiR2YWxpZCA9IHRydWUnKTsNCiAgICAgIH0pOw0KDQogICAgICBpdCgnc2hvdWxkIGJlIGludmFsaWQgaWYgZW1wdHknLCBmdW5jdGlvbigpIHsNCiAgICAgICAgc2V0SW5wdXQoJycpOw0KICAgICAgICBleHBlY3QodmFsdWUuZ2V0VGV4dCgpKS50b0VxdWFsKCd2YWx1ZSA9Jyk7DQogICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignbXlGb3JtLmlucHV0LiR2YWxpZCA9IGZhbHNlJyk7DQogICAgICB9KTsNCg0KICAgICAgaXQoJ3Nob3VsZCBiZSBpbnZhbGlkIGlmIG92ZXIgbWF4JywgZnVuY3Rpb24oKSB7DQogICAgICAgIHNldElucHV0KCcyMDE1LVcwMScpOw0KICAgICAgICBleHBlY3QodmFsdWUuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJycpOw0KICAgICAgICBleHBlY3QodmFsaWQuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ215Rm9ybS5pbnB1dC4kdmFsaWQgPSBmYWxzZScpOw0KICAgICAgfSk7DQogICAgPC9maWxlPg0KICAgIDwvZXhhbXBsZT4NCiAgICAqLw0KICAnd2Vlayc6IGNyZWF0ZURhdGVJbnB1dFR5cGUoJ3dlZWsnLCBXRUVLX1JFR0VYUCwgd2Vla1BhcnNlciwgJ3l5eXktV3d3JyksDQoNCiAgLyoqDQogICAqIEBuZ2RvYyBpbnB1dA0KICAgKiBAbmFtZSBpbnB1dFttb250aF0NCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIElucHV0IHdpdGggbW9udGggdmFsaWRhdGlvbiBhbmQgdHJhbnNmb3JtYXRpb24uIEluIGJyb3dzZXJzIHRoYXQgZG8gbm90IHlldCBzdXBwb3J0DQogICAqIHRoZSBIVE1MNSBtb250aCBpbnB1dCwgYSB0ZXh0IGVsZW1lbnQgd2lsbCBiZSB1c2VkLiBJbiB0aGF0IGNhc2UsIHRoZSB0ZXh0IG11c3QgYmUgZW50ZXJlZCBpbiBhIHZhbGlkIElTTy04NjAxDQogICAqIG1vbnRoIGZvcm1hdCAoeXl5eS1NTSksIGZvciBleGFtcGxlOiBgMjAwOS0wMWAuDQogICAqDQogICAqIFRoZSBtb2RlbCBtdXN0IGFsd2F5cyBiZSBhIERhdGUgb2JqZWN0LCBvdGhlcndpc2UgQW5ndWxhciB3aWxsIHRocm93IGFuIGVycm9yLg0KICAgKiBJbnZhbGlkIGBEYXRlYCBvYmplY3RzIChkYXRlcyB3aG9zZSBgZ2V0VGltZSgpYCBpcyBgTmFOYCkgd2lsbCBiZSByZW5kZXJlZCBhcyBhbiBlbXB0eSBzdHJpbmcuDQogICAqIElmIHRoZSBtb2RlbCBpcyBub3Qgc2V0IHRvIHRoZSBmaXJzdCBvZiB0aGUgbW9udGgsIHRoZSBuZXh0IHZpZXcgdG8gbW9kZWwgdXBkYXRlIHdpbGwgc2V0IGl0DQogICAqIHRvIHRoZSBmaXJzdCBvZiB0aGUgbW9udGguDQogICAqDQogICAqIFRoZSB0aW1lem9uZSB0byBiZSB1c2VkIHRvIHJlYWQvd3JpdGUgdGhlIGBEYXRlYCBpbnN0YW5jZSBpbiB0aGUgbW9kZWwgY2FuIGJlIGRlZmluZWQgdXNpbmcNCiAgICoge0BsaW5rIG5nLmRpcmVjdGl2ZTpuZ01vZGVsT3B0aW9ucyBuZ01vZGVsT3B0aW9uc30uIEJ5IGRlZmF1bHQsIHRoaXMgaXMgdGhlIHRpbWV6b25lIG9mIHRoZSBicm93c2VyLg0KICAgKg0KICAgKiBAcGFyYW0ge3N0cmluZ30gbmdNb2RlbCBBc3NpZ25hYmxlIGFuZ3VsYXIgZXhwcmVzc2lvbiB0byBkYXRhLWJpbmQgdG8uDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmFtZSBQcm9wZXJ0eSBuYW1lIG9mIHRoZSBmb3JtIHVuZGVyIHdoaWNoIHRoZSBjb250cm9sIGlzIHB1Ymxpc2hlZC4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSBtaW4gU2V0cyB0aGUgYG1pbmAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGVudGVyZWQgaXMgbGVzcyB0aGFuIGBtaW5gLiBUaGlzIG11c3QgYmUNCiAgICogYSB2YWxpZCBJU08gbW9udGggZm9ybWF0ICh5eXl5LU1NKS4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSBtYXggU2V0cyB0aGUgYG1heGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGVudGVyZWQgaXMgZ3JlYXRlciB0aGFuIGBtYXhgLiBUaGlzIG11c3QNCiAgICogYmUgYSB2YWxpZCBJU08gbW9udGggZm9ybWF0ICh5eXl5LU1NKS4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSByZXF1aXJlZCBTZXRzIGByZXF1aXJlZGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGlzIG5vdCBlbnRlcmVkLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IG5nUmVxdWlyZWQgQWRkcyBgcmVxdWlyZWRgIGF0dHJpYnV0ZSBhbmQgYHJlcXVpcmVkYCB2YWxpZGF0aW9uIGNvbnN0cmFpbnQgdG8NCiAgICogICAgdGhlIGVsZW1lbnQgd2hlbiB0aGUgbmdSZXF1aXJlZCBleHByZXNzaW9uIGV2YWx1YXRlcyB0byB0cnVlLiBVc2UgYG5nUmVxdWlyZWRgIGluc3RlYWQgb2YNCiAgICogICAgYHJlcXVpcmVkYCB3aGVuIHlvdSB3YW50IHRvIGRhdGEtYmluZCB0byB0aGUgYHJlcXVpcmVkYCBhdHRyaWJ1dGUuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmdDaGFuZ2UgQW5ndWxhciBleHByZXNzaW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gaW5wdXQgY2hhbmdlcyBkdWUgdG8gdXNlcg0KICAgKiAgICBpbnRlcmFjdGlvbiB3aXRoIHRoZSBpbnB1dCBlbGVtZW50Lg0KICAgKg0KICAgKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGUgbmFtZT0ibW9udGgtaW5wdXQtZGlyZWN0aXZlIiBtb2R1bGU9Im1vbnRoRXhhbXBsZSI+DQogICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgPHNjcmlwdD4NCiAgICAgIGFuZ3VsYXIubW9kdWxlKCdtb250aEV4YW1wbGUnLCBbXSkNCiAgICAgICAgLmNvbnRyb2xsZXIoJ0RhdGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICAgICAkc2NvcGUudmFsdWUgPSBuZXcgRGF0ZSgyMDEzLCA5LCAxKTsNCiAgICAgICAgfV0pOw0KICAgICA8L3NjcmlwdD4NCiAgICAgPGZvcm0gbmFtZT0ibXlGb3JtIiBuZy1jb250cm9sbGVyPSJEYXRlQ29udHJvbGxlciBhcyBkYXRlQ3RybCI+DQogICAgICAgUGljayBhIG1vbnRoIGludCAyMDEzOg0KICAgICAgIDxpbnB1dCBpZD0iZXhhbXBsZUlucHV0IiB0eXBlPSJtb250aCIgbmFtZT0iaW5wdXQiIG5nLW1vZGVsPSJ2YWx1ZSINCiAgICAgICAgICBwbGFjZWhvbGRlcj0ieXl5eS1NTSIgbWluPSIyMDEzLTAxIiBtYXg9IjIwMTMtMTIiIHJlcXVpcmVkIC8+DQogICAgICAgPHNwYW4gY2xhc3M9ImVycm9yIiBuZy1zaG93PSJteUZvcm0uaW5wdXQuJGVycm9yLnJlcXVpcmVkIj4NCiAgICAgICAgICBSZXF1aXJlZCE8L3NwYW4+DQogICAgICAgPHNwYW4gY2xhc3M9ImVycm9yIiBuZy1zaG93PSJteUZvcm0uaW5wdXQuJGVycm9yLm1vbnRoIj4NCiAgICAgICAgICBOb3QgYSB2YWxpZCBtb250aCE8L3NwYW4+DQogICAgICAgPHR0PnZhbHVlID0ge3t2YWx1ZSB8IGRhdGU6ICJ5eXl5LU1NIn19PC90dD48YnIvPg0KICAgICAgIDx0dD5teUZvcm0uaW5wdXQuJHZhbGlkID0ge3tteUZvcm0uaW5wdXQuJHZhbGlkfX08L3R0Pjxici8+DQogICAgICAgPHR0Pm15Rm9ybS5pbnB1dC4kZXJyb3IgPSB7e215Rm9ybS5pbnB1dC4kZXJyb3J9fTwvdHQ+PGJyLz4NCiAgICAgICA8dHQ+bXlGb3JtLiR2YWxpZCA9IHt7bXlGb3JtLiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgIDx0dD5teUZvcm0uJGVycm9yLnJlcXVpcmVkID0ge3shIW15Rm9ybS4kZXJyb3IucmVxdWlyZWR9fTwvdHQ+PGJyLz4NCiAgICAgPC9mb3JtPg0KICAgPC9maWxlPg0KICAgPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogICAgICB2YXIgdmFsdWUgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ3ZhbHVlIHwgZGF0ZTogInl5eXktTU0iJykpOw0KICAgICAgdmFyIHZhbGlkID0gZWxlbWVudChieS5iaW5kaW5nKCdteUZvcm0uaW5wdXQuJHZhbGlkJykpOw0KICAgICAgdmFyIGlucHV0ID0gZWxlbWVudChieS5tb2RlbCgndmFsdWUnKSk7DQoNCiAgICAgIC8vIGN1cnJlbnRseSBwcm90cmFjdG9yL3dlYmRyaXZlciBkb2VzIG5vdCBzdXBwb3J0DQogICAgICAvLyBzZW5kaW5nIGtleXMgdG8gYWxsIGtub3duIEhUTUw1IGlucHV0IGNvbnRyb2xzDQogICAgICAvLyBmb3IgdmFyaW91cyBicm93c2VycyAoaHR0cHM6Ly9naXRodWIuY29tL2FuZ3VsYXIvcHJvdHJhY3Rvci9pc3N1ZXMvNTYyKS4NCiAgICAgIGZ1bmN0aW9uIHNldElucHV0KHZhbCkgew0KICAgICAgICAvLyBzZXQgdGhlIHZhbHVlIG9mIHRoZSBlbGVtZW50IGFuZCBmb3JjZSB2YWxpZGF0aW9uLg0KICAgICAgICB2YXIgc2NyID0gInZhciBpcHQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZXhhbXBsZUlucHV0Jyk7ICIgKw0KICAgICAgICAiaXB0LnZhbHVlID0gJyIgKyB2YWwgKyAiJzsiICsNCiAgICAgICAgImFuZ3VsYXIuZWxlbWVudChpcHQpLnNjb3BlKCkuJGFwcGx5KGZ1bmN0aW9uKHMpIHsgcy5teUZvcm1baXB0Lm5hbWVdLiRzZXRWaWV3VmFsdWUoJyIgKyB2YWwgKyAiJyk7IH0pOyI7DQogICAgICAgIGJyb3dzZXIuZXhlY3V0ZVNjcmlwdChzY3IpOw0KICAgICAgfQ0KDQogICAgICBpdCgnc2hvdWxkIGluaXRpYWxpemUgdG8gbW9kZWwnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgZXhwZWN0KHZhbHVlLmdldFRleHQoKSkudG9Db250YWluKCcyMDEzLTEwJyk7DQogICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignbXlGb3JtLmlucHV0LiR2YWxpZCA9IHRydWUnKTsNCiAgICAgIH0pOw0KDQogICAgICBpdCgnc2hvdWxkIGJlIGludmFsaWQgaWYgZW1wdHknLCBmdW5jdGlvbigpIHsNCiAgICAgICAgc2V0SW5wdXQoJycpOw0KICAgICAgICBleHBlY3QodmFsdWUuZ2V0VGV4dCgpKS50b0VxdWFsKCd2YWx1ZSA9Jyk7DQogICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignbXlGb3JtLmlucHV0LiR2YWxpZCA9IGZhbHNlJyk7DQogICAgICB9KTsNCg0KICAgICAgaXQoJ3Nob3VsZCBiZSBpbnZhbGlkIGlmIG92ZXIgbWF4JywgZnVuY3Rpb24oKSB7DQogICAgICAgIHNldElucHV0KCcyMDE1LTAxJyk7DQogICAgICAgIGV4cGVjdCh2YWx1ZS5nZXRUZXh0KCkpLnRvQ29udGFpbignJyk7DQogICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignbXlGb3JtLmlucHV0LiR2YWxpZCA9IGZhbHNlJyk7DQogICAgICB9KTsNCiAgIDwvZmlsZT4NCiAgIDwvZXhhbXBsZT4NCiAgICovDQogICdtb250aCc6IGNyZWF0ZURhdGVJbnB1dFR5cGUoJ21vbnRoJywgTU9OVEhfUkVHRVhQLA0KICAgICBjcmVhdGVEYXRlUGFyc2VyKE1PTlRIX1JFR0VYUCwgWyd5eXl5JywgJ01NJ10pLA0KICAgICAneXl5eS1NTScpLA0KDQogIC8qKg0KICAgKiBAbmdkb2MgaW5wdXQNCiAgICogQG5hbWUgaW5wdXRbbnVtYmVyXQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogVGV4dCBpbnB1dCB3aXRoIG51bWJlciB2YWxpZGF0aW9uIGFuZCB0cmFuc2Zvcm1hdGlvbi4gU2V0cyB0aGUgYG51bWJlcmAgdmFsaWRhdGlvbg0KICAgKiBlcnJvciBpZiBub3QgYSB2YWxpZCBudW1iZXIuDQogICAqDQogICAqIFRoZSBtb2RlbCBtdXN0IGFsd2F5cyBiZSBhIG51bWJlciwgb3RoZXJ3aXNlIEFuZ3VsYXIgd2lsbCB0aHJvdyBhbiBlcnJvci4NCiAgICoNCiAgICogQHBhcmFtIHtzdHJpbmd9IG5nTW9kZWwgQXNzaWduYWJsZSBhbmd1bGFyIGV4cHJlc3Npb24gdG8gZGF0YS1iaW5kIHRvLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IG5hbWUgUHJvcGVydHkgbmFtZSBvZiB0aGUgZm9ybSB1bmRlciB3aGljaCB0aGUgY29udHJvbCBpcyBwdWJsaXNoZWQuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbWluIFNldHMgdGhlIGBtaW5gIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBlbnRlcmVkIGlzIGxlc3MgdGhhbiBgbWluYC4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSBtYXggU2V0cyB0aGUgYG1heGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGVudGVyZWQgaXMgZ3JlYXRlciB0aGFuIGBtYXhgLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IHJlcXVpcmVkIFNldHMgYHJlcXVpcmVkYCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgdmFsdWUgaXMgbm90IGVudGVyZWQuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmdSZXF1aXJlZCBBZGRzIGByZXF1aXJlZGAgYXR0cmlidXRlIGFuZCBgcmVxdWlyZWRgIHZhbGlkYXRpb24gY29uc3RyYWludCB0bw0KICAgKiAgICB0aGUgZWxlbWVudCB3aGVuIHRoZSBuZ1JlcXVpcmVkIGV4cHJlc3Npb24gZXZhbHVhdGVzIHRvIHRydWUuIFVzZSBgbmdSZXF1aXJlZGAgaW5zdGVhZCBvZg0KICAgKiAgICBgcmVxdWlyZWRgIHdoZW4geW91IHdhbnQgdG8gZGF0YS1iaW5kIHRvIHRoZSBgcmVxdWlyZWRgIGF0dHJpYnV0ZS4NCiAgICogQHBhcmFtIHtudW1iZXI9fSBuZ01pbmxlbmd0aCBTZXRzIGBtaW5sZW5ndGhgIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBpcyBzaG9ydGVyIHRoYW4NCiAgICogICAgbWlubGVuZ3RoLg0KICAgKiBAcGFyYW0ge251bWJlcj19IG5nTWF4bGVuZ3RoIFNldHMgYG1heGxlbmd0aGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGlzIGxvbmdlciB0aGFuDQogICAqICAgIG1heGxlbmd0aC4gU2V0dGluZyB0aGUgYXR0cmlidXRlIHRvIGEgbmVnYXRpdmUgb3Igbm9uLW51bWVyaWMgdmFsdWUsIGFsbG93cyB2aWV3IHZhbHVlcyBvZg0KICAgKiAgICBhbnkgbGVuZ3RoLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IHBhdHRlcm4gU2ltaWxhciB0byBgbmdQYXR0ZXJuYCBleGNlcHQgdGhhdCB0aGUgYXR0cmlidXRlIHZhbHVlIGlzIHRoZSBhY3R1YWwgc3RyaW5nDQogICAqICAgIHRoYXQgY29udGFpbnMgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbiBib2R5IHRoYXQgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gYSByZWd1bGFyIGV4cHJlc3Npb24NCiAgICogICAgYXMgaW4gdGhlIG5nUGF0dGVybiBkaXJlY3RpdmUuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmdQYXR0ZXJuIFNldHMgYHBhdHRlcm5gIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSBuZ01vZGVsIHZhbHVlIGRvZXMgbm90IG1hdGNoDQogICAqICAgIGEgUmVnRXhwIGZvdW5kIGJ5IGV2YWx1YXRpbmcgdGhlIEFuZ3VsYXIgZXhwcmVzc2lvbiBnaXZlbiBpbiB0aGUgYXR0cmlidXRlIHZhbHVlLg0KICAgKiAgICBJZiB0aGUgZXhwcmVzc2lvbiBldmFsdWF0ZXMgdG8gYSBSZWdFeHAgb2JqZWN0IHRoZW4gdGhpcyBpcyB1c2VkIGRpcmVjdGx5Lg0KICAgKiAgICBJZiB0aGUgZXhwcmVzc2lvbiBpcyBhIHN0cmluZyB0aGVuIGl0IHdpbGwgYmUgY29udmVydGVkIHRvIGEgUmVnRXhwIGFmdGVyIHdyYXBwaW5nIGl0IGluIGBeYCBhbmQgYCRgDQogICAqICAgIGNoYXJhY3RlcnMuIEZvciBpbnN0YW5jZSwgYCJhYmMiYCB3aWxsIGJlIGNvbnZlcnRlZCB0byBgbmV3IFJlZ0V4cCgnXmFiYyQnKWAuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmdDaGFuZ2UgQW5ndWxhciBleHByZXNzaW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gaW5wdXQgY2hhbmdlcyBkdWUgdG8gdXNlcg0KICAgKiAgICBpbnRlcmFjdGlvbiB3aXRoIHRoZSBpbnB1dCBlbGVtZW50Lg0KICAgKg0KICAgKiBAZXhhbXBsZQ0KICAgICAgPGV4YW1wbGUgbmFtZT0ibnVtYmVyLWlucHV0LWRpcmVjdGl2ZSIgbW9kdWxlPSJudW1iZXJFeGFtcGxlIj4NCiAgICAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgICA8c2NyaXB0Pg0KICAgICAgICAgICBhbmd1bGFyLm1vZHVsZSgnbnVtYmVyRXhhbXBsZScsIFtdKQ0KICAgICAgICAgICAgIC5jb250cm9sbGVyKCdFeGFtcGxlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgICAgICAgICAkc2NvcGUudmFsdWUgPSAxMjsNCiAgICAgICAgICAgICB9XSk7DQogICAgICAgICA8L3NjcmlwdD4NCiAgICAgICAgIDxmb3JtIG5hbWU9Im15Rm9ybSIgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICAgICAgICBOdW1iZXI6IDxpbnB1dCB0eXBlPSJudW1iZXIiIG5hbWU9ImlucHV0IiBuZy1tb2RlbD0idmFsdWUiDQogICAgICAgICAgICAgICAgICAgICAgICAgIG1pbj0iMCIgbWF4PSI5OSIgcmVxdWlyZWQ+DQogICAgICAgICAgIDxzcGFuIGNsYXNzPSJlcnJvciIgbmctc2hvdz0ibXlGb3JtLmlucHV0LiRlcnJvci5yZXF1aXJlZCI+DQogICAgICAgICAgICAgUmVxdWlyZWQhPC9zcGFuPg0KICAgICAgICAgICA8c3BhbiBjbGFzcz0iZXJyb3IiIG5nLXNob3c9Im15Rm9ybS5pbnB1dC4kZXJyb3IubnVtYmVyIj4NCiAgICAgICAgICAgICBOb3QgdmFsaWQgbnVtYmVyITwvc3Bhbj4NCiAgICAgICAgICAgPHR0PnZhbHVlID0ge3t2YWx1ZX19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLmlucHV0LiR2YWxpZCA9IHt7bXlGb3JtLmlucHV0LiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLmlucHV0LiRlcnJvciA9IHt7bXlGb3JtLmlucHV0LiRlcnJvcn19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLiR2YWxpZCA9IHt7bXlGb3JtLiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLiRlcnJvci5yZXF1aXJlZCA9IHt7ISFteUZvcm0uJGVycm9yLnJlcXVpcmVkfX08L3R0Pjxici8+DQogICAgICAgICAgPC9mb3JtPg0KICAgICAgICA8L2ZpbGU+DQogICAgICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgICAgIHZhciB2YWx1ZSA9IGVsZW1lbnQoYnkuYmluZGluZygndmFsdWUnKSk7DQogICAgICAgICAgdmFyIHZhbGlkID0gZWxlbWVudChieS5iaW5kaW5nKCdteUZvcm0uaW5wdXQuJHZhbGlkJykpOw0KICAgICAgICAgIHZhciBpbnB1dCA9IGVsZW1lbnQoYnkubW9kZWwoJ3ZhbHVlJykpOw0KDQogICAgICAgICAgaXQoJ3Nob3VsZCBpbml0aWFsaXplIHRvIG1vZGVsJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBleHBlY3QodmFsdWUuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJzEyJyk7DQogICAgICAgICAgICBleHBlY3QodmFsaWQuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ3RydWUnKTsNCiAgICAgICAgICB9KTsNCg0KICAgICAgICAgIGl0KCdzaG91bGQgYmUgaW52YWxpZCBpZiBlbXB0eScsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgaW5wdXQuY2xlYXIoKTsNCiAgICAgICAgICAgIGlucHV0LnNlbmRLZXlzKCcnKTsNCiAgICAgICAgICAgIGV4cGVjdCh2YWx1ZS5nZXRUZXh0KCkpLnRvRXF1YWwoJ3ZhbHVlID0nKTsNCiAgICAgICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignZmFsc2UnKTsNCiAgICAgICAgICB9KTsNCg0KICAgICAgICAgIGl0KCdzaG91bGQgYmUgaW52YWxpZCBpZiBvdmVyIG1heCcsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgaW5wdXQuY2xlYXIoKTsNCiAgICAgICAgICAgIGlucHV0LnNlbmRLZXlzKCcxMjMnKTsNCiAgICAgICAgICAgIGV4cGVjdCh2YWx1ZS5nZXRUZXh0KCkpLnRvRXF1YWwoJ3ZhbHVlID0nKTsNCiAgICAgICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignZmFsc2UnKTsNCiAgICAgICAgICB9KTsNCiAgICAgICAgPC9maWxlPg0KICAgICAgPC9leGFtcGxlPg0KICAgKi8NCiAgJ251bWJlcic6IG51bWJlcklucHV0VHlwZSwNCg0KDQogIC8qKg0KICAgKiBAbmdkb2MgaW5wdXQNCiAgICogQG5hbWUgaW5wdXRbdXJsXQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogVGV4dCBpbnB1dCB3aXRoIFVSTCB2YWxpZGF0aW9uLiBTZXRzIHRoZSBgdXJsYCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgY29udGVudCBpcyBub3QgYQ0KICAgKiB2YWxpZCBVUkwuDQogICAqDQogICAqIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXdhcm5pbmciPg0KICAgKiAqKk5vdGU6KiogYGlucHV0W3VybF1gIHVzZXMgYSByZWdleCB0byB2YWxpZGF0ZSB1cmxzIHRoYXQgaXMgZGVyaXZlZCBmcm9tIHRoZSByZWdleA0KICAgKiB1c2VkIGluIENocm9taXVtLiBJZiB5b3UgbmVlZCBzdHJpY3RlciB2YWxpZGF0aW9uLCB5b3UgY2FuIHVzZSBgbmctcGF0dGVybmAgb3IgbW9kaWZ5DQogICAqIHRoZSBidWlsdC1pbiB2YWxpZGF0b3JzIChzZWUgdGhlIHtAbGluayBndWlkZS9mb3JtcyBGb3JtcyBndWlkZX0pDQogICAqIDwvZGl2Pg0KICAgKg0KICAgKiBAcGFyYW0ge3N0cmluZ30gbmdNb2RlbCBBc3NpZ25hYmxlIGFuZ3VsYXIgZXhwcmVzc2lvbiB0byBkYXRhLWJpbmQgdG8uDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmFtZSBQcm9wZXJ0eSBuYW1lIG9mIHRoZSBmb3JtIHVuZGVyIHdoaWNoIHRoZSBjb250cm9sIGlzIHB1Ymxpc2hlZC4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSByZXF1aXJlZCBTZXRzIGByZXF1aXJlZGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGlzIG5vdCBlbnRlcmVkLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IG5nUmVxdWlyZWQgQWRkcyBgcmVxdWlyZWRgIGF0dHJpYnV0ZSBhbmQgYHJlcXVpcmVkYCB2YWxpZGF0aW9uIGNvbnN0cmFpbnQgdG8NCiAgICogICAgdGhlIGVsZW1lbnQgd2hlbiB0aGUgbmdSZXF1aXJlZCBleHByZXNzaW9uIGV2YWx1YXRlcyB0byB0cnVlLiBVc2UgYG5nUmVxdWlyZWRgIGluc3RlYWQgb2YNCiAgICogICAgYHJlcXVpcmVkYCB3aGVuIHlvdSB3YW50IHRvIGRhdGEtYmluZCB0byB0aGUgYHJlcXVpcmVkYCBhdHRyaWJ1dGUuDQogICAqIEBwYXJhbSB7bnVtYmVyPX0gbmdNaW5sZW5ndGggU2V0cyBgbWlubGVuZ3RoYCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgdmFsdWUgaXMgc2hvcnRlciB0aGFuDQogICAqICAgIG1pbmxlbmd0aC4NCiAgICogQHBhcmFtIHtudW1iZXI9fSBuZ01heGxlbmd0aCBTZXRzIGBtYXhsZW5ndGhgIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBpcyBsb25nZXIgdGhhbg0KICAgKiAgICBtYXhsZW5ndGguIFNldHRpbmcgdGhlIGF0dHJpYnV0ZSB0byBhIG5lZ2F0aXZlIG9yIG5vbi1udW1lcmljIHZhbHVlLCBhbGxvd3MgdmlldyB2YWx1ZXMgb2YNCiAgICogICAgYW55IGxlbmd0aC4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSBwYXR0ZXJuIFNpbWlsYXIgdG8gYG5nUGF0dGVybmAgZXhjZXB0IHRoYXQgdGhlIGF0dHJpYnV0ZSB2YWx1ZSBpcyB0aGUgYWN0dWFsIHN0cmluZw0KICAgKiAgICB0aGF0IGNvbnRhaW5zIHRoZSByZWd1bGFyIGV4cHJlc3Npb24gYm9keSB0aGF0IHdpbGwgYmUgY29udmVydGVkIHRvIGEgcmVndWxhciBleHByZXNzaW9uDQogICAqICAgIGFzIGluIHRoZSBuZ1BhdHRlcm4gZGlyZWN0aXZlLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IG5nUGF0dGVybiBTZXRzIGBwYXR0ZXJuYCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgbmdNb2RlbCB2YWx1ZSBkb2VzIG5vdCBtYXRjaA0KICAgKiAgICBhIFJlZ0V4cCBmb3VuZCBieSBldmFsdWF0aW5nIHRoZSBBbmd1bGFyIGV4cHJlc3Npb24gZ2l2ZW4gaW4gdGhlIGF0dHJpYnV0ZSB2YWx1ZS4NCiAgICogICAgSWYgdGhlIGV4cHJlc3Npb24gZXZhbHVhdGVzIHRvIGEgUmVnRXhwIG9iamVjdCB0aGVuIHRoaXMgaXMgdXNlZCBkaXJlY3RseS4NCiAgICogICAgSWYgdGhlIGV4cHJlc3Npb24gaXMgYSBzdHJpbmcgdGhlbiBpdCB3aWxsIGJlIGNvbnZlcnRlZCB0byBhIFJlZ0V4cCBhZnRlciB3cmFwcGluZyBpdCBpbiBgXmAgYW5kIGAkYA0KICAgKiAgICBjaGFyYWN0ZXJzLiBGb3IgaW5zdGFuY2UsIGAiYWJjImAgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gYG5ldyBSZWdFeHAoJ15hYmMkJylgLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IG5nQ2hhbmdlIEFuZ3VsYXIgZXhwcmVzc2lvbiB0byBiZSBleGVjdXRlZCB3aGVuIGlucHV0IGNoYW5nZXMgZHVlIHRvIHVzZXINCiAgICogICAgaW50ZXJhY3Rpb24gd2l0aCB0aGUgaW5wdXQgZWxlbWVudC4NCiAgICoNCiAgICogQGV4YW1wbGUNCiAgICAgIDxleGFtcGxlIG5hbWU9InVybC1pbnB1dC1kaXJlY3RpdmUiIG1vZHVsZT0idXJsRXhhbXBsZSI+DQogICAgICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgICAgPHNjcmlwdD4NCiAgICAgICAgICAgYW5ndWxhci5tb2R1bGUoJ3VybEV4YW1wbGUnLCBbXSkNCiAgICAgICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICAgICAgJHNjb3BlLnRleHQgPSAnaHR0cDovL2dvb2dsZS5jb20nOw0KICAgICAgICAgICAgIH1dKTsNCiAgICAgICAgIDwvc2NyaXB0Pg0KICAgICAgICAgPGZvcm0gbmFtZT0ibXlGb3JtIiBuZy1jb250cm9sbGVyPSJFeGFtcGxlQ29udHJvbGxlciI+DQogICAgICAgICAgIFVSTDogPGlucHV0IHR5cGU9InVybCIgbmFtZT0iaW5wdXQiIG5nLW1vZGVsPSJ0ZXh0IiByZXF1aXJlZD4NCiAgICAgICAgICAgPHNwYW4gY2xhc3M9ImVycm9yIiBuZy1zaG93PSJteUZvcm0uaW5wdXQuJGVycm9yLnJlcXVpcmVkIj4NCiAgICAgICAgICAgICBSZXF1aXJlZCE8L3NwYW4+DQogICAgICAgICAgIDxzcGFuIGNsYXNzPSJlcnJvciIgbmctc2hvdz0ibXlGb3JtLmlucHV0LiRlcnJvci51cmwiPg0KICAgICAgICAgICAgIE5vdCB2YWxpZCB1cmwhPC9zcGFuPg0KICAgICAgICAgICA8dHQ+dGV4dCA9IHt7dGV4dH19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLmlucHV0LiR2YWxpZCA9IHt7bXlGb3JtLmlucHV0LiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLmlucHV0LiRlcnJvciA9IHt7bXlGb3JtLmlucHV0LiRlcnJvcn19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLiR2YWxpZCA9IHt7bXlGb3JtLiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgICAgICA8dHQ+bXlGb3JtLiRlcnJvci5yZXF1aXJlZCA9IHt7ISFteUZvcm0uJGVycm9yLnJlcXVpcmVkfX08L3R0Pjxici8+DQogICAgICAgICAgIDx0dD5teUZvcm0uJGVycm9yLnVybCA9IHt7ISFteUZvcm0uJGVycm9yLnVybH19PC90dD48YnIvPg0KICAgICAgICAgIDwvZm9ybT4NCiAgICAgICAgPC9maWxlPg0KICAgICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICAgICB2YXIgdGV4dCA9IGVsZW1lbnQoYnkuYmluZGluZygndGV4dCcpKTsNCiAgICAgICAgICB2YXIgdmFsaWQgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ215Rm9ybS5pbnB1dC4kdmFsaWQnKSk7DQogICAgICAgICAgdmFyIGlucHV0ID0gZWxlbWVudChieS5tb2RlbCgndGV4dCcpKTsNCg0KICAgICAgICAgIGl0KCdzaG91bGQgaW5pdGlhbGl6ZSB0byBtb2RlbCcsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgZXhwZWN0KHRleHQuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ2h0dHA6Ly9nb29nbGUuY29tJyk7DQogICAgICAgICAgICBleHBlY3QodmFsaWQuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ3RydWUnKTsNCiAgICAgICAgICB9KTsNCg0KICAgICAgICAgIGl0KCdzaG91bGQgYmUgaW52YWxpZCBpZiBlbXB0eScsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgaW5wdXQuY2xlYXIoKTsNCiAgICAgICAgICAgIGlucHV0LnNlbmRLZXlzKCcnKTsNCg0KICAgICAgICAgICAgZXhwZWN0KHRleHQuZ2V0VGV4dCgpKS50b0VxdWFsKCd0ZXh0ID0nKTsNCiAgICAgICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignZmFsc2UnKTsNCiAgICAgICAgICB9KTsNCg0KICAgICAgICAgIGl0KCdzaG91bGQgYmUgaW52YWxpZCBpZiBub3QgdXJsJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBpbnB1dC5jbGVhcigpOw0KICAgICAgICAgICAgaW5wdXQuc2VuZEtleXMoJ2JveCcpOw0KDQogICAgICAgICAgICBleHBlY3QodmFsaWQuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ2ZhbHNlJyk7DQogICAgICAgICAgfSk7DQogICAgICAgIDwvZmlsZT4NCiAgICAgIDwvZXhhbXBsZT4NCiAgICovDQogICd1cmwnOiB1cmxJbnB1dFR5cGUsDQoNCg0KICAvKioNCiAgICogQG5nZG9jIGlucHV0DQogICAqIEBuYW1lIGlucHV0W2VtYWlsXQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogVGV4dCBpbnB1dCB3aXRoIGVtYWlsIHZhbGlkYXRpb24uIFNldHMgdGhlIGBlbWFpbGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgbm90IGEgdmFsaWQgZW1haWwNCiAgICogYWRkcmVzcy4NCiAgICoNCiAgICogPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtd2FybmluZyI+DQogICAqICoqTm90ZToqKiBgaW5wdXRbZW1haWxdYCB1c2VzIGEgcmVnZXggdG8gdmFsaWRhdGUgZW1haWwgYWRkcmVzc2VzIHRoYXQgaXMgZGVyaXZlZCBmcm9tIHRoZSByZWdleA0KICAgKiB1c2VkIGluIENocm9taXVtLiBJZiB5b3UgbmVlZCBzdHJpY3RlciB2YWxpZGF0aW9uIChlLmcuIHJlcXVpcmluZyBhIHRvcC1sZXZlbCBkb21haW4pLCB5b3UgY2FuDQogICAqIHVzZSBgbmctcGF0dGVybmAgb3IgbW9kaWZ5IHRoZSBidWlsdC1pbiB2YWxpZGF0b3JzIChzZWUgdGhlIHtAbGluayBndWlkZS9mb3JtcyBGb3JtcyBndWlkZX0pDQogICAqIDwvZGl2Pg0KICAgKg0KICAgKiBAcGFyYW0ge3N0cmluZ30gbmdNb2RlbCBBc3NpZ25hYmxlIGFuZ3VsYXIgZXhwcmVzc2lvbiB0byBkYXRhLWJpbmQgdG8uDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmFtZSBQcm9wZXJ0eSBuYW1lIG9mIHRoZSBmb3JtIHVuZGVyIHdoaWNoIHRoZSBjb250cm9sIGlzIHB1Ymxpc2hlZC4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSByZXF1aXJlZCBTZXRzIGByZXF1aXJlZGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGlzIG5vdCBlbnRlcmVkLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IG5nUmVxdWlyZWQgQWRkcyBgcmVxdWlyZWRgIGF0dHJpYnV0ZSBhbmQgYHJlcXVpcmVkYCB2YWxpZGF0aW9uIGNvbnN0cmFpbnQgdG8NCiAgICogICAgdGhlIGVsZW1lbnQgd2hlbiB0aGUgbmdSZXF1aXJlZCBleHByZXNzaW9uIGV2YWx1YXRlcyB0byB0cnVlLiBVc2UgYG5nUmVxdWlyZWRgIGluc3RlYWQgb2YNCiAgICogICAgYHJlcXVpcmVkYCB3aGVuIHlvdSB3YW50IHRvIGRhdGEtYmluZCB0byB0aGUgYHJlcXVpcmVkYCBhdHRyaWJ1dGUuDQogICAqIEBwYXJhbSB7bnVtYmVyPX0gbmdNaW5sZW5ndGggU2V0cyBgbWlubGVuZ3RoYCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgdmFsdWUgaXMgc2hvcnRlciB0aGFuDQogICAqICAgIG1pbmxlbmd0aC4NCiAgICogQHBhcmFtIHtudW1iZXI9fSBuZ01heGxlbmd0aCBTZXRzIGBtYXhsZW5ndGhgIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBpcyBsb25nZXIgdGhhbg0KICAgKiAgICBtYXhsZW5ndGguIFNldHRpbmcgdGhlIGF0dHJpYnV0ZSB0byBhIG5lZ2F0aXZlIG9yIG5vbi1udW1lcmljIHZhbHVlLCBhbGxvd3MgdmlldyB2YWx1ZXMgb2YNCiAgICogICAgYW55IGxlbmd0aC4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSBwYXR0ZXJuIFNpbWlsYXIgdG8gYG5nUGF0dGVybmAgZXhjZXB0IHRoYXQgdGhlIGF0dHJpYnV0ZSB2YWx1ZSBpcyB0aGUgYWN0dWFsIHN0cmluZw0KICAgKiAgICB0aGF0IGNvbnRhaW5zIHRoZSByZWd1bGFyIGV4cHJlc3Npb24gYm9keSB0aGF0IHdpbGwgYmUgY29udmVydGVkIHRvIGEgcmVndWxhciBleHByZXNzaW9uDQogICAqICAgIGFzIGluIHRoZSBuZ1BhdHRlcm4gZGlyZWN0aXZlLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IG5nUGF0dGVybiBTZXRzIGBwYXR0ZXJuYCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgbmdNb2RlbCB2YWx1ZSBkb2VzIG5vdCBtYXRjaA0KICAgKiAgICBhIFJlZ0V4cCBmb3VuZCBieSBldmFsdWF0aW5nIHRoZSBBbmd1bGFyIGV4cHJlc3Npb24gZ2l2ZW4gaW4gdGhlIGF0dHJpYnV0ZSB2YWx1ZS4NCiAgICogICAgSWYgdGhlIGV4cHJlc3Npb24gZXZhbHVhdGVzIHRvIGEgUmVnRXhwIG9iamVjdCB0aGVuIHRoaXMgaXMgdXNlZCBkaXJlY3RseS4NCiAgICogICAgSWYgdGhlIGV4cHJlc3Npb24gaXMgYSBzdHJpbmcgdGhlbiBpdCB3aWxsIGJlIGNvbnZlcnRlZCB0byBhIFJlZ0V4cCBhZnRlciB3cmFwcGluZyBpdCBpbiBgXmAgYW5kIGAkYA0KICAgKiAgICBjaGFyYWN0ZXJzLiBGb3IgaW5zdGFuY2UsIGAiYWJjImAgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gYG5ldyBSZWdFeHAoJ15hYmMkJylgLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IG5nQ2hhbmdlIEFuZ3VsYXIgZXhwcmVzc2lvbiB0byBiZSBleGVjdXRlZCB3aGVuIGlucHV0IGNoYW5nZXMgZHVlIHRvIHVzZXINCiAgICogICAgaW50ZXJhY3Rpb24gd2l0aCB0aGUgaW5wdXQgZWxlbWVudC4NCiAgICoNCiAgICogQGV4YW1wbGUNCiAgICAgIDxleGFtcGxlIG5hbWU9ImVtYWlsLWlucHV0LWRpcmVjdGl2ZSIgbW9kdWxlPSJlbWFpbEV4YW1wbGUiPg0KICAgICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICAgIDxzY3JpcHQ+DQogICAgICAgICAgIGFuZ3VsYXIubW9kdWxlKCdlbWFpbEV4YW1wbGUnLCBbXSkNCiAgICAgICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICAgICAgJHNjb3BlLnRleHQgPSAnbWVAZXhhbXBsZS5jb20nOw0KICAgICAgICAgICAgIH1dKTsNCiAgICAgICAgIDwvc2NyaXB0Pg0KICAgICAgICAgICA8Zm9ybSBuYW1lPSJteUZvcm0iIG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICAgICAgICBFbWFpbDogPGlucHV0IHR5cGU9ImVtYWlsIiBuYW1lPSJpbnB1dCIgbmctbW9kZWw9InRleHQiIHJlcXVpcmVkPg0KICAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJlcnJvciIgbmctc2hvdz0ibXlGb3JtLmlucHV0LiRlcnJvci5yZXF1aXJlZCI+DQogICAgICAgICAgICAgICBSZXF1aXJlZCE8L3NwYW4+DQogICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImVycm9yIiBuZy1zaG93PSJteUZvcm0uaW5wdXQuJGVycm9yLmVtYWlsIj4NCiAgICAgICAgICAgICAgIE5vdCB2YWxpZCBlbWFpbCE8L3NwYW4+DQogICAgICAgICAgICAgPHR0PnRleHQgPSB7e3RleHR9fTwvdHQ+PGJyLz4NCiAgICAgICAgICAgICA8dHQ+bXlGb3JtLmlucHV0LiR2YWxpZCA9IHt7bXlGb3JtLmlucHV0LiR2YWxpZH19PC90dD48YnIvPg0KICAgICAgICAgICAgIDx0dD5teUZvcm0uaW5wdXQuJGVycm9yID0ge3tteUZvcm0uaW5wdXQuJGVycm9yfX08L3R0Pjxici8+DQogICAgICAgICAgICAgPHR0Pm15Rm9ybS4kdmFsaWQgPSB7e215Rm9ybS4kdmFsaWR9fTwvdHQ+PGJyLz4NCiAgICAgICAgICAgICA8dHQ+bXlGb3JtLiRlcnJvci5yZXF1aXJlZCA9IHt7ISFteUZvcm0uJGVycm9yLnJlcXVpcmVkfX08L3R0Pjxici8+DQogICAgICAgICAgICAgPHR0Pm15Rm9ybS4kZXJyb3IuZW1haWwgPSB7eyEhbXlGb3JtLiRlcnJvci5lbWFpbH19PC90dD48YnIvPg0KICAgICAgICAgICA8L2Zvcm0+DQogICAgICAgICA8L2ZpbGU+DQogICAgICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgICAgIHZhciB0ZXh0ID0gZWxlbWVudChieS5iaW5kaW5nKCd0ZXh0JykpOw0KICAgICAgICAgIHZhciB2YWxpZCA9IGVsZW1lbnQoYnkuYmluZGluZygnbXlGb3JtLmlucHV0LiR2YWxpZCcpKTsNCiAgICAgICAgICB2YXIgaW5wdXQgPSBlbGVtZW50KGJ5Lm1vZGVsKCd0ZXh0JykpOw0KDQogICAgICAgICAgaXQoJ3Nob3VsZCBpbml0aWFsaXplIHRvIG1vZGVsJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBleHBlY3QodGV4dC5nZXRUZXh0KCkpLnRvQ29udGFpbignbWVAZXhhbXBsZS5jb20nKTsNCiAgICAgICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbigndHJ1ZScpOw0KICAgICAgICAgIH0pOw0KDQogICAgICAgICAgaXQoJ3Nob3VsZCBiZSBpbnZhbGlkIGlmIGVtcHR5JywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBpbnB1dC5jbGVhcigpOw0KICAgICAgICAgICAgaW5wdXQuc2VuZEtleXMoJycpOw0KICAgICAgICAgICAgZXhwZWN0KHRleHQuZ2V0VGV4dCgpKS50b0VxdWFsKCd0ZXh0ID0nKTsNCiAgICAgICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignZmFsc2UnKTsNCiAgICAgICAgICB9KTsNCg0KICAgICAgICAgIGl0KCdzaG91bGQgYmUgaW52YWxpZCBpZiBub3QgZW1haWwnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgICAgIGlucHV0LmNsZWFyKCk7DQogICAgICAgICAgICBpbnB1dC5zZW5kS2V5cygneHh4Jyk7DQoNCiAgICAgICAgICAgIGV4cGVjdCh2YWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignZmFsc2UnKTsNCiAgICAgICAgICB9KTsNCiAgICAgICAgPC9maWxlPg0KICAgICAgPC9leGFtcGxlPg0KICAgKi8NCiAgJ2VtYWlsJzogZW1haWxJbnB1dFR5cGUsDQoNCg0KICAvKioNCiAgICogQG5nZG9jIGlucHV0DQogICAqIEBuYW1lIGlucHV0W3JhZGlvXQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogSFRNTCByYWRpbyBidXR0b24uDQogICAqDQogICAqIEBwYXJhbSB7c3RyaW5nfSBuZ01vZGVsIEFzc2lnbmFibGUgYW5ndWxhciBleHByZXNzaW9uIHRvIGRhdGEtYmluZCB0by4NCiAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIFRoZSB2YWx1ZSB0byB3aGljaCB0aGUgZXhwcmVzc2lvbiBzaG91bGQgYmUgc2V0IHdoZW4gc2VsZWN0ZWQuDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmFtZSBQcm9wZXJ0eSBuYW1lIG9mIHRoZSBmb3JtIHVuZGVyIHdoaWNoIHRoZSBjb250cm9sIGlzIHB1Ymxpc2hlZC4NCiAgICogQHBhcmFtIHtzdHJpbmc9fSBuZ0NoYW5nZSBBbmd1bGFyIGV4cHJlc3Npb24gdG8gYmUgZXhlY3V0ZWQgd2hlbiBpbnB1dCBjaGFuZ2VzIGR1ZSB0byB1c2VyDQogICAqICAgIGludGVyYWN0aW9uIHdpdGggdGhlIGlucHV0IGVsZW1lbnQuDQogICAqIEBwYXJhbSB7c3RyaW5nfSBuZ1ZhbHVlIEFuZ3VsYXIgZXhwcmVzc2lvbiB3aGljaCBzZXRzIHRoZSB2YWx1ZSB0byB3aGljaCB0aGUgZXhwcmVzc2lvbiBzaG91bGQNCiAgICogICAgYmUgc2V0IHdoZW4gc2VsZWN0ZWQuDQogICAqDQogICAqIEBleGFtcGxlDQogICAgICA8ZXhhbXBsZSBuYW1lPSJyYWRpby1pbnB1dC1kaXJlY3RpdmUiIG1vZHVsZT0icmFkaW9FeGFtcGxlIj4NCiAgICAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgICA8c2NyaXB0Pg0KICAgICAgICAgICBhbmd1bGFyLm1vZHVsZSgncmFkaW9FeGFtcGxlJywgW10pDQogICAgICAgICAgICAgLmNvbnRyb2xsZXIoJ0V4YW1wbGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICAgICAgICAgICRzY29wZS5jb2xvciA9ICdibHVlJzsNCiAgICAgICAgICAgICAgICRzY29wZS5zcGVjaWFsVmFsdWUgPSB7DQogICAgICAgICAgICAgICAgICJpZCI6ICIxMjM0NSIsDQogICAgICAgICAgICAgICAgICJ2YWx1ZSI6ICJncmVlbiINCiAgICAgICAgICAgICAgIH07DQogICAgICAgICAgICAgfV0pOw0KICAgICAgICAgPC9zY3JpcHQ+DQogICAgICAgICA8Zm9ybSBuYW1lPSJteUZvcm0iIG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICAgICAgPGlucHV0IHR5cGU9InJhZGlvIiBuZy1tb2RlbD0iY29sb3IiIHZhbHVlPSJyZWQiPiAgUmVkIDxici8+DQogICAgICAgICAgIDxpbnB1dCB0eXBlPSJyYWRpbyIgbmctbW9kZWw9ImNvbG9yIiBuZy12YWx1ZT0ic3BlY2lhbFZhbHVlIj4gR3JlZW4gPGJyLz4NCiAgICAgICAgICAgPGlucHV0IHR5cGU9InJhZGlvIiBuZy1tb2RlbD0iY29sb3IiIHZhbHVlPSJibHVlIj4gQmx1ZSA8YnIvPg0KICAgICAgICAgICA8dHQ+Y29sb3IgPSB7e2NvbG9yIHwganNvbn19PC90dD48YnIvPg0KICAgICAgICAgIDwvZm9ybT4NCiAgICAgICAgICBOb3RlIHRoYXQgYG5nLXZhbHVlPSJzcGVjaWFsVmFsdWUiYCBzZXRzIHJhZGlvIGl0ZW0ncyB2YWx1ZSB0byBiZSB0aGUgdmFsdWUgb2YgYCRzY29wZS5zcGVjaWFsVmFsdWVgLg0KICAgICAgICA8L2ZpbGU+DQogICAgICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgICAgIGl0KCdzaG91bGQgY2hhbmdlIHN0YXRlJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICB2YXIgY29sb3IgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ2NvbG9yJykpOw0KDQogICAgICAgICAgICBleHBlY3QoY29sb3IuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ2JsdWUnKTsNCg0KICAgICAgICAgICAgZWxlbWVudC5hbGwoYnkubW9kZWwoJ2NvbG9yJykpLmdldCgwKS5jbGljaygpOw0KDQogICAgICAgICAgICBleHBlY3QoY29sb3IuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ3JlZCcpOw0KICAgICAgICAgIH0pOw0KICAgICAgICA8L2ZpbGU+DQogICAgICA8L2V4YW1wbGU+DQogICAqLw0KICAncmFkaW8nOiByYWRpb0lucHV0VHlwZSwNCg0KDQogIC8qKg0KICAgKiBAbmdkb2MgaW5wdXQNCiAgICogQG5hbWUgaW5wdXRbY2hlY2tib3hdDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBIVE1MIGNoZWNrYm94Lg0KICAgKg0KICAgKiBAcGFyYW0ge3N0cmluZ30gbmdNb2RlbCBBc3NpZ25hYmxlIGFuZ3VsYXIgZXhwcmVzc2lvbiB0byBkYXRhLWJpbmQgdG8uDQogICAqIEBwYXJhbSB7c3RyaW5nPX0gbmFtZSBQcm9wZXJ0eSBuYW1lIG9mIHRoZSBmb3JtIHVuZGVyIHdoaWNoIHRoZSBjb250cm9sIGlzIHB1Ymxpc2hlZC4NCiAgICogQHBhcmFtIHtleHByZXNzaW9uPX0gbmdUcnVlVmFsdWUgVGhlIHZhbHVlIHRvIHdoaWNoIHRoZSBleHByZXNzaW9uIHNob3VsZCBiZSBzZXQgd2hlbiBzZWxlY3RlZC4NCiAgICogQHBhcmFtIHtleHByZXNzaW9uPX0gbmdGYWxzZVZhbHVlIFRoZSB2YWx1ZSB0byB3aGljaCB0aGUgZXhwcmVzc2lvbiBzaG91bGQgYmUgc2V0IHdoZW4gbm90IHNlbGVjdGVkLg0KICAgKiBAcGFyYW0ge3N0cmluZz19IG5nQ2hhbmdlIEFuZ3VsYXIgZXhwcmVzc2lvbiB0byBiZSBleGVjdXRlZCB3aGVuIGlucHV0IGNoYW5nZXMgZHVlIHRvIHVzZXINCiAgICogICAgaW50ZXJhY3Rpb24gd2l0aCB0aGUgaW5wdXQgZWxlbWVudC4NCiAgICoNCiAgICogQGV4YW1wbGUNCiAgICAgIDxleGFtcGxlIG5hbWU9ImNoZWNrYm94LWlucHV0LWRpcmVjdGl2ZSIgbW9kdWxlPSJjaGVja2JveEV4YW1wbGUiPg0KICAgICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICAgIDxzY3JpcHQ+DQogICAgICAgICAgIGFuZ3VsYXIubW9kdWxlKCdjaGVja2JveEV4YW1wbGUnLCBbXSkNCiAgICAgICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICAgICAgJHNjb3BlLnZhbHVlMSA9IHRydWU7DQogICAgICAgICAgICAgICAkc2NvcGUudmFsdWUyID0gJ1lFUycNCiAgICAgICAgICAgICB9XSk7DQogICAgICAgICA8L3NjcmlwdD4NCiAgICAgICAgIDxmb3JtIG5hbWU9Im15Rm9ybSIgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICAgICAgICBWYWx1ZTE6IDxpbnB1dCB0eXBlPSJjaGVja2JveCIgbmctbW9kZWw9InZhbHVlMSI+IDxici8+DQogICAgICAgICAgIFZhbHVlMjogPGlucHV0IHR5cGU9ImNoZWNrYm94IiBuZy1tb2RlbD0idmFsdWUyIg0KICAgICAgICAgICAgICAgICAgICAgICAgICBuZy10cnVlLXZhbHVlPSInWUVTJyIgbmctZmFsc2UtdmFsdWU9IidOTyciPiA8YnIvPg0KICAgICAgICAgICA8dHQ+dmFsdWUxID0ge3t2YWx1ZTF9fTwvdHQ+PGJyLz4NCiAgICAgICAgICAgPHR0PnZhbHVlMiA9IHt7dmFsdWUyfX08L3R0Pjxici8+DQogICAgICAgICAgPC9mb3JtPg0KICAgICAgICA8L2ZpbGU+DQogICAgICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgICAgIGl0KCdzaG91bGQgY2hhbmdlIHN0YXRlJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICB2YXIgdmFsdWUxID0gZWxlbWVudChieS5iaW5kaW5nKCd2YWx1ZTEnKSk7DQogICAgICAgICAgICB2YXIgdmFsdWUyID0gZWxlbWVudChieS5iaW5kaW5nKCd2YWx1ZTInKSk7DQoNCiAgICAgICAgICAgIGV4cGVjdCh2YWx1ZTEuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ3RydWUnKTsNCiAgICAgICAgICAgIGV4cGVjdCh2YWx1ZTIuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ1lFUycpOw0KDQogICAgICAgICAgICBlbGVtZW50KGJ5Lm1vZGVsKCd2YWx1ZTEnKSkuY2xpY2soKTsNCiAgICAgICAgICAgIGVsZW1lbnQoYnkubW9kZWwoJ3ZhbHVlMicpKS5jbGljaygpOw0KDQogICAgICAgICAgICBleHBlY3QodmFsdWUxLmdldFRleHQoKSkudG9Db250YWluKCdmYWxzZScpOw0KICAgICAgICAgICAgZXhwZWN0KHZhbHVlMi5nZXRUZXh0KCkpLnRvQ29udGFpbignTk8nKTsNCiAgICAgICAgICB9KTsNCiAgICAgICAgPC9maWxlPg0KICAgICAgPC9leGFtcGxlPg0KICAgKi8NCiAgJ2NoZWNrYm94JzogY2hlY2tib3hJbnB1dFR5cGUsDQoNCiAgJ2hpZGRlbic6IG5vb3AsDQogICdidXR0b24nOiBub29wLA0KICAnc3VibWl0Jzogbm9vcCwNCiAgJ3Jlc2V0Jzogbm9vcCwNCiAgJ2ZpbGUnOiBub29wDQp9Ow0KDQpmdW5jdGlvbiBzdHJpbmdCYXNlZElucHV0VHlwZShjdHJsKSB7DQogIGN0cmwuJGZvcm1hdHRlcnMucHVzaChmdW5jdGlvbih2YWx1ZSkgew0KICAgIHJldHVybiBjdHJsLiRpc0VtcHR5KHZhbHVlKSA/IHZhbHVlIDogdmFsdWUudG9TdHJpbmcoKTsNCiAgfSk7DQp9DQoNCmZ1bmN0aW9uIHRleHRJbnB1dFR5cGUoc2NvcGUsIGVsZW1lbnQsIGF0dHIsIGN0cmwsICRzbmlmZmVyLCAkYnJvd3Nlcikgew0KICBiYXNlSW5wdXRUeXBlKHNjb3BlLCBlbGVtZW50LCBhdHRyLCBjdHJsLCAkc25pZmZlciwgJGJyb3dzZXIpOw0KICBzdHJpbmdCYXNlZElucHV0VHlwZShjdHJsKTsNCn0NCg0KZnVuY3Rpb24gYmFzZUlucHV0VHlwZShzY29wZSwgZWxlbWVudCwgYXR0ciwgY3RybCwgJHNuaWZmZXIsICRicm93c2VyKSB7DQogIHZhciB0eXBlID0gbG93ZXJjYXNlKGVsZW1lbnRbMF0udHlwZSk7DQoNCiAgLy8gSW4gY29tcG9zaXRpb24gbW9kZSwgdXNlcnMgYXJlIHN0aWxsIGlucHV0aW5nIGludGVybWVkaWF0ZSB0ZXh0IGJ1ZmZlciwNCiAgLy8gaG9sZCB0aGUgbGlzdGVuZXIgdW50aWwgY29tcG9zaXRpb24gaXMgZG9uZS4NCiAgLy8gTW9yZSBhYm91dCBjb21wb3NpdGlvbiBldmVudHM6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9Db21wb3NpdGlvbkV2ZW50DQogIGlmICghJHNuaWZmZXIuYW5kcm9pZCkgew0KICAgIHZhciBjb21wb3NpbmcgPSBmYWxzZTsNCg0KICAgIGVsZW1lbnQub24oJ2NvbXBvc2l0aW9uc3RhcnQnLCBmdW5jdGlvbihkYXRhKSB7DQogICAgICBjb21wb3NpbmcgPSB0cnVlOw0KICAgIH0pOw0KDQogICAgZWxlbWVudC5vbignY29tcG9zaXRpb25lbmQnLCBmdW5jdGlvbigpIHsNCiAgICAgIGNvbXBvc2luZyA9IGZhbHNlOw0KICAgICAgbGlzdGVuZXIoKTsNCiAgICB9KTsNCiAgfQ0KDQogIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uKGV2KSB7DQogICAgaWYgKHRpbWVvdXQpIHsNCiAgICAgICRicm93c2VyLmRlZmVyLmNhbmNlbCh0aW1lb3V0KTsNCiAgICAgIHRpbWVvdXQgPSBudWxsOw0KICAgIH0NCiAgICBpZiAoY29tcG9zaW5nKSByZXR1cm47DQogICAgdmFyIHZhbHVlID0gZWxlbWVudC52YWwoKSwNCiAgICAgICAgZXZlbnQgPSBldiAmJiBldi50eXBlOw0KDQogICAgLy8gQnkgZGVmYXVsdCB3ZSB3aWxsIHRyaW0gdGhlIHZhbHVlDQogICAgLy8gSWYgdGhlIGF0dHJpYnV0ZSBuZy10cmltIGV4aXN0cyB3ZSB3aWxsIGF2b2lkIHRyaW1taW5nDQogICAgLy8gSWYgaW5wdXQgdHlwZSBpcyAncGFzc3dvcmQnLCB0aGUgdmFsdWUgaXMgbmV2ZXIgdHJpbW1lZA0KICAgIGlmICh0eXBlICE9PSAncGFzc3dvcmQnICYmICghYXR0ci5uZ1RyaW0gfHwgYXR0ci5uZ1RyaW0gIT09ICdmYWxzZScpKSB7DQogICAgICB2YWx1ZSA9IHRyaW0odmFsdWUpOw0KICAgIH0NCg0KICAgIC8vIElmIGEgY29udHJvbCBpcyBzdWZmZXJpbmcgZnJvbSBiYWQgaW5wdXQgKGR1ZSB0byBuYXRpdmUgdmFsaWRhdG9ycyksIGJyb3dzZXJzIGRpc2NhcmQgaXRzDQogICAgLy8gdmFsdWUsIHNvIGl0IG1heSBiZSBuZWNlc3NhcnkgdG8gcmV2YWxpZGF0ZSAoYnkgY2FsbGluZyAkc2V0Vmlld1ZhbHVlIGFnYWluKSBldmVuIGlmIHRoZQ0KICAgIC8vIGNvbnRyb2wncyB2YWx1ZSBpcyB0aGUgc2FtZSBlbXB0eSB2YWx1ZSB0d2ljZSBpbiBhIHJvdy4NCiAgICBpZiAoY3RybC4kdmlld1ZhbHVlICE9PSB2YWx1ZSB8fCAodmFsdWUgPT09ICcnICYmIGN0cmwuJCRoYXNOYXRpdmVWYWxpZGF0b3JzKSkgew0KICAgICAgY3RybC4kc2V0Vmlld1ZhbHVlKHZhbHVlLCBldmVudCk7DQogICAgfQ0KICB9Ow0KDQogIC8vIGlmIHRoZSBicm93c2VyIGRvZXMgc3VwcG9ydCAiaW5wdXQiIGV2ZW50LCB3ZSBhcmUgZmluZSAtIGV4Y2VwdCBvbiBJRTkgd2hpY2ggZG9lc24ndCBmaXJlIHRoZQ0KICAvLyBpbnB1dCBldmVudCBvbiBiYWNrc3BhY2UsIGRlbGV0ZSBvciBjdXQNCiAgaWYgKCRzbmlmZmVyLmhhc0V2ZW50KCdpbnB1dCcpKSB7DQogICAgZWxlbWVudC5vbignaW5wdXQnLCBsaXN0ZW5lcik7DQogIH0gZWxzZSB7DQogICAgdmFyIHRpbWVvdXQ7DQoNCiAgICB2YXIgZGVmZXJMaXN0ZW5lciA9IGZ1bmN0aW9uKGV2LCBpbnB1dCwgb3JpZ1ZhbHVlKSB7DQogICAgICBpZiAoIXRpbWVvdXQpIHsNCiAgICAgICAgdGltZW91dCA9ICRicm93c2VyLmRlZmVyKGZ1bmN0aW9uKCkgew0KICAgICAgICAgIHRpbWVvdXQgPSBudWxsOw0KICAgICAgICAgIGlmICghaW5wdXQgfHwgaW5wdXQudmFsdWUgIT09IG9yaWdWYWx1ZSkgew0KICAgICAgICAgICAgbGlzdGVuZXIoZXYpOw0KICAgICAgICAgIH0NCiAgICAgICAgfSk7DQogICAgICB9DQogICAgfTsNCg0KICAgIGVsZW1lbnQub24oJ2tleWRvd24nLCBmdW5jdGlvbihldmVudCkgew0KICAgICAgdmFyIGtleSA9IGV2ZW50LmtleUNvZGU7DQoNCiAgICAgIC8vIGlnbm9yZQ0KICAgICAgLy8gICAgY29tbWFuZCAgICAgICAgICAgIG1vZGlmaWVycyAgICAgICAgICAgICAgICAgICBhcnJvd3MNCiAgICAgIGlmIChrZXkgPT09IDkxIHx8ICgxNSA8IGtleSAmJiBrZXkgPCAxOSkgfHwgKDM3IDw9IGtleSAmJiBrZXkgPD0gNDApKSByZXR1cm47DQoNCiAgICAgIGRlZmVyTGlzdGVuZXIoZXZlbnQsIHRoaXMsIHRoaXMudmFsdWUpOw0KICAgIH0pOw0KDQogICAgLy8gaWYgdXNlciBtb2RpZmllcyBpbnB1dCB2YWx1ZSB1c2luZyBjb250ZXh0IG1lbnUgaW4gSUUsIHdlIG5lZWQgInBhc3RlIiBhbmQgImN1dCIgZXZlbnRzIHRvIGNhdGNoIGl0DQogICAgaWYgKCRzbmlmZmVyLmhhc0V2ZW50KCdwYXN0ZScpKSB7DQogICAgICBlbGVtZW50Lm9uKCdwYXN0ZSBjdXQnLCBkZWZlckxpc3RlbmVyKTsNCiAgICB9DQogIH0NCg0KICAvLyBpZiB1c2VyIHBhc3RlIGludG8gaW5wdXQgdXNpbmcgbW91c2Ugb24gb2xkZXIgYnJvd3Nlcg0KICAvLyBvciBmb3JtIGF1dG9jb21wbGV0ZSBvbiBuZXdlciBicm93c2VyLCB3ZSBuZWVkICJjaGFuZ2UiIGV2ZW50IHRvIGNhdGNoIGl0DQogIGVsZW1lbnQub24oJ2NoYW5nZScsIGxpc3RlbmVyKTsNCg0KICBjdHJsLiRyZW5kZXIgPSBmdW5jdGlvbigpIHsNCiAgICBlbGVtZW50LnZhbChjdHJsLiRpc0VtcHR5KGN0cmwuJHZpZXdWYWx1ZSkgPyAnJyA6IGN0cmwuJHZpZXdWYWx1ZSk7DQogIH07DQp9DQoNCmZ1bmN0aW9uIHdlZWtQYXJzZXIoaXNvV2VlaywgZXhpc3RpbmdEYXRlKSB7DQogIGlmIChpc0RhdGUoaXNvV2VlaykpIHsNCiAgICByZXR1cm4gaXNvV2VlazsNCiAgfQ0KDQogIGlmIChpc1N0cmluZyhpc29XZWVrKSkgew0KICAgIFdFRUtfUkVHRVhQLmxhc3RJbmRleCA9IDA7DQogICAgdmFyIHBhcnRzID0gV0VFS19SRUdFWFAuZXhlYyhpc29XZWVrKTsNCiAgICBpZiAocGFydHMpIHsNCiAgICAgIHZhciB5ZWFyID0gK3BhcnRzWzFdLA0KICAgICAgICAgIHdlZWsgPSArcGFydHNbMl0sDQogICAgICAgICAgaG91cnMgPSAwLA0KICAgICAgICAgIG1pbnV0ZXMgPSAwLA0KICAgICAgICAgIHNlY29uZHMgPSAwLA0KICAgICAgICAgIG1pbGxpc2Vjb25kcyA9IDAsDQogICAgICAgICAgZmlyc3RUaHVycyA9IGdldEZpcnN0VGh1cnNkYXlPZlllYXIoeWVhciksDQogICAgICAgICAgYWRkRGF5cyA9ICh3ZWVrIC0gMSkgKiA3Ow0KDQogICAgICBpZiAoZXhpc3RpbmdEYXRlKSB7DQogICAgICAgIGhvdXJzID0gZXhpc3RpbmdEYXRlLmdldEhvdXJzKCk7DQogICAgICAgIG1pbnV0ZXMgPSBleGlzdGluZ0RhdGUuZ2V0TWludXRlcygpOw0KICAgICAgICBzZWNvbmRzID0gZXhpc3RpbmdEYXRlLmdldFNlY29uZHMoKTsNCiAgICAgICAgbWlsbGlzZWNvbmRzID0gZXhpc3RpbmdEYXRlLmdldE1pbGxpc2Vjb25kcygpOw0KICAgICAgfQ0KDQogICAgICByZXR1cm4gbmV3IERhdGUoeWVhciwgMCwgZmlyc3RUaHVycy5nZXREYXRlKCkgKyBhZGREYXlzLCBob3VycywgbWludXRlcywgc2Vjb25kcywgbWlsbGlzZWNvbmRzKTsNCiAgICB9DQogIH0NCg0KICByZXR1cm4gTmFOOw0KfQ0KDQpmdW5jdGlvbiBjcmVhdGVEYXRlUGFyc2VyKHJlZ2V4cCwgbWFwcGluZykgew0KICByZXR1cm4gZnVuY3Rpb24oaXNvLCBkYXRlKSB7DQogICAgdmFyIHBhcnRzLCBtYXA7DQoNCiAgICBpZiAoaXNEYXRlKGlzbykpIHsNCiAgICAgIHJldHVybiBpc287DQogICAgfQ0KDQogICAgaWYgKGlzU3RyaW5nKGlzbykpIHsNCiAgICAgIC8vIFdoZW4gYSBkYXRlIGlzIEpTT04naWZpZWQgdG8gd3JhcHMgaXRzZWxmIGluc2lkZSBvZiBhbiBleHRyYQ0KICAgICAgLy8gc2V0IG9mIGRvdWJsZSBxdW90ZXMuIFRoaXMgbWFrZXMgdGhlIGRhdGUgcGFyc2luZyBjb2RlIHVuYWJsZQ0KICAgICAgLy8gdG8gbWF0Y2ggdGhlIGRhdGUgc3RyaW5nIGFuZCBwYXJzZSBpdCBhcyBhIGRhdGUuDQogICAgICBpZiAoaXNvLmNoYXJBdCgwKSA9PSAnIicgJiYgaXNvLmNoYXJBdChpc28ubGVuZ3RoIC0gMSkgPT0gJyInKSB7DQogICAgICAgIGlzbyA9IGlzby5zdWJzdHJpbmcoMSwgaXNvLmxlbmd0aCAtIDEpOw0KICAgICAgfQ0KICAgICAgaWYgKElTT19EQVRFX1JFR0VYUC50ZXN0KGlzbykpIHsNCiAgICAgICAgcmV0dXJuIG5ldyBEYXRlKGlzbyk7DQogICAgICB9DQogICAgICByZWdleHAubGFzdEluZGV4ID0gMDsNCiAgICAgIHBhcnRzID0gcmVnZXhwLmV4ZWMoaXNvKTsNCg0KICAgICAgaWYgKHBhcnRzKSB7DQogICAgICAgIHBhcnRzLnNoaWZ0KCk7DQogICAgICAgIGlmIChkYXRlKSB7DQogICAgICAgICAgbWFwID0gew0KICAgICAgICAgICAgeXl5eTogZGF0ZS5nZXRGdWxsWWVhcigpLA0KICAgICAgICAgICAgTU06IGRhdGUuZ2V0TW9udGgoKSArIDEsDQogICAgICAgICAgICBkZDogZGF0ZS5nZXREYXRlKCksDQogICAgICAgICAgICBISDogZGF0ZS5nZXRIb3VycygpLA0KICAgICAgICAgICAgbW06IGRhdGUuZ2V0TWludXRlcygpLA0KICAgICAgICAgICAgc3M6IGRhdGUuZ2V0U2Vjb25kcygpLA0KICAgICAgICAgICAgc3NzOiBkYXRlLmdldE1pbGxpc2Vjb25kcygpIC8gMTAwMA0KICAgICAgICAgIH07DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgbWFwID0geyB5eXl5OiAxOTcwLCBNTTogMSwgZGQ6IDEsIEhIOiAwLCBtbTogMCwgc3M6IDAsIHNzczogMCB9Ow0KICAgICAgICB9DQoNCiAgICAgICAgZm9yRWFjaChwYXJ0cywgZnVuY3Rpb24ocGFydCwgaW5kZXgpIHsNCiAgICAgICAgICBpZiAoaW5kZXggPCBtYXBwaW5nLmxlbmd0aCkgew0KICAgICAgICAgICAgbWFwW21hcHBpbmdbaW5kZXhdXSA9ICtwYXJ0Ow0KICAgICAgICAgIH0NCiAgICAgICAgfSk7DQogICAgICAgIHJldHVybiBuZXcgRGF0ZShtYXAueXl5eSwgbWFwLk1NIC0gMSwgbWFwLmRkLCBtYXAuSEgsIG1hcC5tbSwgbWFwLnNzIHx8IDAsIG1hcC5zc3MgKiAxMDAwIHx8IDApOw0KICAgICAgfQ0KICAgIH0NCg0KICAgIHJldHVybiBOYU47DQogIH07DQp9DQoNCmZ1bmN0aW9uIGNyZWF0ZURhdGVJbnB1dFR5cGUodHlwZSwgcmVnZXhwLCBwYXJzZURhdGUsIGZvcm1hdCkgew0KICByZXR1cm4gZnVuY3Rpb24gZHluYW1pY0RhdGVJbnB1dFR5cGUoc2NvcGUsIGVsZW1lbnQsIGF0dHIsIGN0cmwsICRzbmlmZmVyLCAkYnJvd3NlciwgJGZpbHRlcikgew0KICAgIGJhZElucHV0Q2hlY2tlcihzY29wZSwgZWxlbWVudCwgYXR0ciwgY3RybCk7DQogICAgYmFzZUlucHV0VHlwZShzY29wZSwgZWxlbWVudCwgYXR0ciwgY3RybCwgJHNuaWZmZXIsICRicm93c2VyKTsNCiAgICB2YXIgdGltZXpvbmUgPSBjdHJsICYmIGN0cmwuJG9wdGlvbnMgJiYgY3RybC4kb3B0aW9ucy50aW1lem9uZTsNCiAgICB2YXIgcHJldmlvdXNEYXRlOw0KDQogICAgY3RybC4kJHBhcnNlck5hbWUgPSB0eXBlOw0KICAgIGN0cmwuJHBhcnNlcnMucHVzaChmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgaWYgKGN0cmwuJGlzRW1wdHkodmFsdWUpKSByZXR1cm4gbnVsbDsNCiAgICAgIGlmIChyZWdleHAudGVzdCh2YWx1ZSkpIHsNCiAgICAgICAgLy8gTm90ZTogV2UgY2Fubm90IHJlYWQgY3RybC4kbW9kZWxWYWx1ZSwgYXMgdGhlcmUgbWlnaHQgYmUgYSBkaWZmZXJlbnQNCiAgICAgICAgLy8gcGFyc2VyL2Zvcm1hdHRlciBpbiB0aGUgcHJvY2Vzc2luZyBjaGFpbiBzbyB0aGF0IHRoZSBtb2RlbA0KICAgICAgICAvLyBjb250YWlucyBzb21lIGRpZmZlcmVudCBkYXRhIGZvcm1hdCENCiAgICAgICAgdmFyIHBhcnNlZERhdGUgPSBwYXJzZURhdGUodmFsdWUsIHByZXZpb3VzRGF0ZSk7DQogICAgICAgIGlmICh0aW1lem9uZSA9PT0gJ1VUQycpIHsNCiAgICAgICAgICBwYXJzZWREYXRlLnNldE1pbnV0ZXMocGFyc2VkRGF0ZS5nZXRNaW51dGVzKCkgLSBwYXJzZWREYXRlLmdldFRpbWV6b25lT2Zmc2V0KCkpOw0KICAgICAgICB9DQogICAgICAgIHJldHVybiBwYXJzZWREYXRlOw0KICAgICAgfQ0KICAgICAgcmV0dXJuIHVuZGVmaW5lZDsNCiAgICB9KTsNCg0KICAgIGN0cmwuJGZvcm1hdHRlcnMucHVzaChmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgaWYgKHZhbHVlICYmICFpc0RhdGUodmFsdWUpKSB7DQogICAgICAgIHRocm93ICRuZ01vZGVsTWluRXJyKCdkYXRlZm10JywgJ0V4cGVjdGVkIGB7MH1gIHRvIGJlIGEgZGF0ZScsIHZhbHVlKTsNCiAgICAgIH0NCiAgICAgIGlmIChpc1ZhbGlkRGF0ZSh2YWx1ZSkpIHsNCiAgICAgICAgcHJldmlvdXNEYXRlID0gdmFsdWU7DQogICAgICAgIGlmIChwcmV2aW91c0RhdGUgJiYgdGltZXpvbmUgPT09ICdVVEMnKSB7DQogICAgICAgICAgdmFyIHRpbWV6b25lT2Zmc2V0ID0gNjAwMDAgKiBwcmV2aW91c0RhdGUuZ2V0VGltZXpvbmVPZmZzZXQoKTsNCiAgICAgICAgICBwcmV2aW91c0RhdGUgPSBuZXcgRGF0ZShwcmV2aW91c0RhdGUuZ2V0VGltZSgpICsgdGltZXpvbmVPZmZzZXQpOw0KICAgICAgICB9DQogICAgICAgIHJldHVybiAkZmlsdGVyKCdkYXRlJykodmFsdWUsIGZvcm1hdCwgdGltZXpvbmUpOw0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgcHJldmlvdXNEYXRlID0gbnVsbDsNCiAgICAgICAgcmV0dXJuICcnOw0KICAgICAgfQ0KICAgIH0pOw0KDQogICAgaWYgKGlzRGVmaW5lZChhdHRyLm1pbikgfHwgYXR0ci5uZ01pbikgew0KICAgICAgdmFyIG1pblZhbDsNCiAgICAgIGN0cmwuJHZhbGlkYXRvcnMubWluID0gZnVuY3Rpb24odmFsdWUpIHsNCiAgICAgICAgcmV0dXJuICFpc1ZhbGlkRGF0ZSh2YWx1ZSkgfHwgaXNVbmRlZmluZWQobWluVmFsKSB8fCBwYXJzZURhdGUodmFsdWUpID49IG1pblZhbDsNCiAgICAgIH07DQogICAgICBhdHRyLiRvYnNlcnZlKCdtaW4nLCBmdW5jdGlvbih2YWwpIHsNCiAgICAgICAgbWluVmFsID0gcGFyc2VPYnNlcnZlZERhdGVWYWx1ZSh2YWwpOw0KICAgICAgICBjdHJsLiR2YWxpZGF0ZSgpOw0KICAgICAgfSk7DQogICAgfQ0KDQogICAgaWYgKGlzRGVmaW5lZChhdHRyLm1heCkgfHwgYXR0ci5uZ01heCkgew0KICAgICAgdmFyIG1heFZhbDsNCiAgICAgIGN0cmwuJHZhbGlkYXRvcnMubWF4ID0gZnVuY3Rpb24odmFsdWUpIHsNCiAgICAgICAgcmV0dXJuICFpc1ZhbGlkRGF0ZSh2YWx1ZSkgfHwgaXNVbmRlZmluZWQobWF4VmFsKSB8fCBwYXJzZURhdGUodmFsdWUpIDw9IG1heFZhbDsNCiAgICAgIH07DQogICAgICBhdHRyLiRvYnNlcnZlKCdtYXgnLCBmdW5jdGlvbih2YWwpIHsNCiAgICAgICAgbWF4VmFsID0gcGFyc2VPYnNlcnZlZERhdGVWYWx1ZSh2YWwpOw0KICAgICAgICBjdHJsLiR2YWxpZGF0ZSgpOw0KICAgICAgfSk7DQogICAgfQ0KDQogICAgZnVuY3Rpb24gaXNWYWxpZERhdGUodmFsdWUpIHsNCiAgICAgIC8vIEludmFsaWQgRGF0ZTogZ2V0VGltZSgpIHJldHVybnMgTmFODQogICAgICByZXR1cm4gdmFsdWUgJiYgISh2YWx1ZS5nZXRUaW1lICYmIHZhbHVlLmdldFRpbWUoKSAhPT0gdmFsdWUuZ2V0VGltZSgpKTsNCiAgICB9DQoNCiAgICBmdW5jdGlvbiBwYXJzZU9ic2VydmVkRGF0ZVZhbHVlKHZhbCkgew0KICAgICAgcmV0dXJuIGlzRGVmaW5lZCh2YWwpID8gKGlzRGF0ZSh2YWwpID8gdmFsIDogcGFyc2VEYXRlKHZhbCkpIDogdW5kZWZpbmVkOw0KICAgIH0NCiAgfTsNCn0NCg0KZnVuY3Rpb24gYmFkSW5wdXRDaGVja2VyKHNjb3BlLCBlbGVtZW50LCBhdHRyLCBjdHJsKSB7DQogIHZhciBub2RlID0gZWxlbWVudFswXTsNCiAgdmFyIG5hdGl2ZVZhbGlkYXRpb24gPSBjdHJsLiQkaGFzTmF0aXZlVmFsaWRhdG9ycyA9IGlzT2JqZWN0KG5vZGUudmFsaWRpdHkpOw0KICBpZiAobmF0aXZlVmFsaWRhdGlvbikgew0KICAgIGN0cmwuJHBhcnNlcnMucHVzaChmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgdmFyIHZhbGlkaXR5ID0gZWxlbWVudC5wcm9wKFZBTElESVRZX1NUQVRFX1BST1BFUlRZKSB8fCB7fTsNCiAgICAgIC8vIERldGVjdCBidWcgaW4gRkYzNSBmb3IgaW5wdXRbZW1haWxdIChodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMDY0NDMwKToNCiAgICAgIC8vIC0gYWxzbyBzZXRzIHZhbGlkaXR5LmJhZElucHV0IChzaG91bGQgb25seSBiZSB2YWxpZGl0eS50eXBlTWlzbWF0Y2gpLg0KICAgICAgLy8gLSBzZWUgaHR0cDovL3d3dy53aGF0d2cub3JnL3NwZWNzL3dlYi1hcHBzL2N1cnJlbnQtd29yay9tdWx0aXBhZ2UvZm9ybXMuaHRtbCNlLW1haWwtc3RhdGUtKHR5cGU9ZW1haWwpDQogICAgICAvLyAtIGNhbiBpZ25vcmUgdGhpcyBjYXNlIGFzIHdlIGNhbiBzdGlsbCByZWFkIG91dCB0aGUgZXJyb25lb3VzIGVtYWlsLi4uDQogICAgICByZXR1cm4gdmFsaWRpdHkuYmFkSW5wdXQgJiYgIXZhbGlkaXR5LnR5cGVNaXNtYXRjaCA/IHVuZGVmaW5lZCA6IHZhbHVlOw0KICAgIH0pOw0KICB9DQp9DQoNCmZ1bmN0aW9uIG51bWJlcklucHV0VHlwZShzY29wZSwgZWxlbWVudCwgYXR0ciwgY3RybCwgJHNuaWZmZXIsICRicm93c2VyKSB7DQogIGJhZElucHV0Q2hlY2tlcihzY29wZSwgZWxlbWVudCwgYXR0ciwgY3RybCk7DQogIGJhc2VJbnB1dFR5cGUoc2NvcGUsIGVsZW1lbnQsIGF0dHIsIGN0cmwsICRzbmlmZmVyLCAkYnJvd3Nlcik7DQoNCiAgY3RybC4kJHBhcnNlck5hbWUgPSAnbnVtYmVyJzsNCiAgY3RybC4kcGFyc2Vycy5wdXNoKGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgaWYgKGN0cmwuJGlzRW1wdHkodmFsdWUpKSAgICAgIHJldHVybiBudWxsOw0KICAgIGlmIChOVU1CRVJfUkVHRVhQLnRlc3QodmFsdWUpKSByZXR1cm4gcGFyc2VGbG9hdCh2YWx1ZSk7DQogICAgcmV0dXJuIHVuZGVmaW5lZDsNCiAgfSk7DQoNCiAgY3RybC4kZm9ybWF0dGVycy5wdXNoKGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgaWYgKCFjdHJsLiRpc0VtcHR5KHZhbHVlKSkgew0KICAgICAgaWYgKCFpc051bWJlcih2YWx1ZSkpIHsNCiAgICAgICAgdGhyb3cgJG5nTW9kZWxNaW5FcnIoJ251bWZtdCcsICdFeHBlY3RlZCBgezB9YCB0byBiZSBhIG51bWJlcicsIHZhbHVlKTsNCiAgICAgIH0NCiAgICAgIHZhbHVlID0gdmFsdWUudG9TdHJpbmcoKTsNCiAgICB9DQogICAgcmV0dXJuIHZhbHVlOw0KICB9KTsNCg0KICBpZiAoYXR0ci5taW4gfHwgYXR0ci5uZ01pbikgew0KICAgIHZhciBtaW5WYWw7DQogICAgY3RybC4kdmFsaWRhdG9ycy5taW4gPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgcmV0dXJuIGN0cmwuJGlzRW1wdHkodmFsdWUpIHx8IGlzVW5kZWZpbmVkKG1pblZhbCkgfHwgdmFsdWUgPj0gbWluVmFsOw0KICAgIH07DQoNCiAgICBhdHRyLiRvYnNlcnZlKCdtaW4nLCBmdW5jdGlvbih2YWwpIHsNCiAgICAgIGlmIChpc0RlZmluZWQodmFsKSAmJiAhaXNOdW1iZXIodmFsKSkgew0KICAgICAgICB2YWwgPSBwYXJzZUZsb2F0KHZhbCwgMTApOw0KICAgICAgfQ0KICAgICAgbWluVmFsID0gaXNOdW1iZXIodmFsKSAmJiAhaXNOYU4odmFsKSA/IHZhbCA6IHVuZGVmaW5lZDsNCiAgICAgIC8vIFRPRE8obWF0c2tvKTogaW1wbGVtZW50IHZhbGlkYXRlTGF0ZXIgdG8gcmVkdWNlIG51bWJlciBvZiB2YWxpZGF0aW9ucw0KICAgICAgY3RybC4kdmFsaWRhdGUoKTsNCiAgICB9KTsNCiAgfQ0KDQogIGlmIChhdHRyLm1heCB8fCBhdHRyLm5nTWF4KSB7DQogICAgdmFyIG1heFZhbDsNCiAgICBjdHJsLiR2YWxpZGF0b3JzLm1heCA9IGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgICByZXR1cm4gY3RybC4kaXNFbXB0eSh2YWx1ZSkgfHwgaXNVbmRlZmluZWQobWF4VmFsKSB8fCB2YWx1ZSA8PSBtYXhWYWw7DQogICAgfTsNCg0KICAgIGF0dHIuJG9ic2VydmUoJ21heCcsIGZ1bmN0aW9uKHZhbCkgew0KICAgICAgaWYgKGlzRGVmaW5lZCh2YWwpICYmICFpc051bWJlcih2YWwpKSB7DQogICAgICAgIHZhbCA9IHBhcnNlRmxvYXQodmFsLCAxMCk7DQogICAgICB9DQogICAgICBtYXhWYWwgPSBpc051bWJlcih2YWwpICYmICFpc05hTih2YWwpID8gdmFsIDogdW5kZWZpbmVkOw0KICAgICAgLy8gVE9ETyhtYXRza28pOiBpbXBsZW1lbnQgdmFsaWRhdGVMYXRlciB0byByZWR1Y2UgbnVtYmVyIG9mIHZhbGlkYXRpb25zDQogICAgICBjdHJsLiR2YWxpZGF0ZSgpOw0KICAgIH0pOw0KICB9DQp9DQoNCmZ1bmN0aW9uIHVybElucHV0VHlwZShzY29wZSwgZWxlbWVudCwgYXR0ciwgY3RybCwgJHNuaWZmZXIsICRicm93c2VyKSB7DQogIC8vIE5vdGU6IG5vIGJhZElucHV0Q2hlY2tlciBoZXJlIGJ5IHB1cnBvc2UgYXMgYHVybGAgaXMgb25seSBhIHZhbGlkYXRpb24NCiAgLy8gaW4gYnJvd3NlcnMsIGkuZS4gd2UgY2FuIGFsd2F5cyByZWFkIG91dCBpbnB1dC52YWx1ZSBldmVuIGlmIGl0IGlzIG5vdCB2YWxpZCENCiAgYmFzZUlucHV0VHlwZShzY29wZSwgZWxlbWVudCwgYXR0ciwgY3RybCwgJHNuaWZmZXIsICRicm93c2VyKTsNCiAgc3RyaW5nQmFzZWRJbnB1dFR5cGUoY3RybCk7DQoNCiAgY3RybC4kJHBhcnNlck5hbWUgPSAndXJsJzsNCiAgY3RybC4kdmFsaWRhdG9ycy51cmwgPSBmdW5jdGlvbihtb2RlbFZhbHVlLCB2aWV3VmFsdWUpIHsNCiAgICB2YXIgdmFsdWUgPSBtb2RlbFZhbHVlIHx8IHZpZXdWYWx1ZTsNCiAgICByZXR1cm4gY3RybC4kaXNFbXB0eSh2YWx1ZSkgfHwgVVJMX1JFR0VYUC50ZXN0KHZhbHVlKTsNCiAgfTsNCn0NCg0KZnVuY3Rpb24gZW1haWxJbnB1dFR5cGUoc2NvcGUsIGVsZW1lbnQsIGF0dHIsIGN0cmwsICRzbmlmZmVyLCAkYnJvd3Nlcikgew0KICAvLyBOb3RlOiBubyBiYWRJbnB1dENoZWNrZXIgaGVyZSBieSBwdXJwb3NlIGFzIGB1cmxgIGlzIG9ubHkgYSB2YWxpZGF0aW9uDQogIC8vIGluIGJyb3dzZXJzLCBpLmUuIHdlIGNhbiBhbHdheXMgcmVhZCBvdXQgaW5wdXQudmFsdWUgZXZlbiBpZiBpdCBpcyBub3QgdmFsaWQhDQogIGJhc2VJbnB1dFR5cGUoc2NvcGUsIGVsZW1lbnQsIGF0dHIsIGN0cmwsICRzbmlmZmVyLCAkYnJvd3Nlcik7DQogIHN0cmluZ0Jhc2VkSW5wdXRUeXBlKGN0cmwpOw0KDQogIGN0cmwuJCRwYXJzZXJOYW1lID0gJ2VtYWlsJzsNCiAgY3RybC4kdmFsaWRhdG9ycy5lbWFpbCA9IGZ1bmN0aW9uKG1vZGVsVmFsdWUsIHZpZXdWYWx1ZSkgew0KICAgIHZhciB2YWx1ZSA9IG1vZGVsVmFsdWUgfHwgdmlld1ZhbHVlOw0KICAgIHJldHVybiBjdHJsLiRpc0VtcHR5KHZhbHVlKSB8fCBFTUFJTF9SRUdFWFAudGVzdCh2YWx1ZSk7DQogIH07DQp9DQoNCmZ1bmN0aW9uIHJhZGlvSW5wdXRUeXBlKHNjb3BlLCBlbGVtZW50LCBhdHRyLCBjdHJsKSB7DQogIC8vIG1ha2UgdGhlIG5hbWUgdW5pcXVlLCBpZiBub3QgZGVmaW5lZA0KICBpZiAoaXNVbmRlZmluZWQoYXR0ci5uYW1lKSkgew0KICAgIGVsZW1lbnQuYXR0cignbmFtZScsIG5leHRVaWQoKSk7DQogIH0NCg0KICB2YXIgbGlzdGVuZXIgPSBmdW5jdGlvbihldikgew0KICAgIGlmIChlbGVtZW50WzBdLmNoZWNrZWQpIHsNCiAgICAgIGN0cmwuJHNldFZpZXdWYWx1ZShhdHRyLnZhbHVlLCBldiAmJiBldi50eXBlKTsNCiAgICB9DQogIH07DQoNCiAgZWxlbWVudC5vbignY2xpY2snLCBsaXN0ZW5lcik7DQoNCiAgY3RybC4kcmVuZGVyID0gZnVuY3Rpb24oKSB7DQogICAgdmFyIHZhbHVlID0gYXR0ci52YWx1ZTsNCiAgICBlbGVtZW50WzBdLmNoZWNrZWQgPSAodmFsdWUgPT0gY3RybC4kdmlld1ZhbHVlKTsNCiAgfTsNCg0KICBhdHRyLiRvYnNlcnZlKCd2YWx1ZScsIGN0cmwuJHJlbmRlcik7DQp9DQoNCmZ1bmN0aW9uIHBhcnNlQ29uc3RhbnRFeHByKCRwYXJzZSwgY29udGV4dCwgbmFtZSwgZXhwcmVzc2lvbiwgZmFsbGJhY2spIHsNCiAgdmFyIHBhcnNlRm47DQogIGlmIChpc0RlZmluZWQoZXhwcmVzc2lvbikpIHsNCiAgICBwYXJzZUZuID0gJHBhcnNlKGV4cHJlc3Npb24pOw0KICAgIGlmICghcGFyc2VGbi5jb25zdGFudCkgew0KICAgICAgdGhyb3cgbWluRXJyKCduZ01vZGVsJykoJ2NvbnN0ZXhwcicsICdFeHBlY3RlZCBjb25zdGFudCBleHByZXNzaW9uIGZvciBgezB9YCwgYnV0IHNhdyAnICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2B7MX1gLicsIG5hbWUsIGV4cHJlc3Npb24pOw0KICAgIH0NCiAgICByZXR1cm4gcGFyc2VGbihjb250ZXh0KTsNCiAgfQ0KICByZXR1cm4gZmFsbGJhY2s7DQp9DQoNCmZ1bmN0aW9uIGNoZWNrYm94SW5wdXRUeXBlKHNjb3BlLCBlbGVtZW50LCBhdHRyLCBjdHJsLCAkc25pZmZlciwgJGJyb3dzZXIsICRmaWx0ZXIsICRwYXJzZSkgew0KICB2YXIgdHJ1ZVZhbHVlID0gcGFyc2VDb25zdGFudEV4cHIoJHBhcnNlLCBzY29wZSwgJ25nVHJ1ZVZhbHVlJywgYXR0ci5uZ1RydWVWYWx1ZSwgdHJ1ZSk7DQogIHZhciBmYWxzZVZhbHVlID0gcGFyc2VDb25zdGFudEV4cHIoJHBhcnNlLCBzY29wZSwgJ25nRmFsc2VWYWx1ZScsIGF0dHIubmdGYWxzZVZhbHVlLCBmYWxzZSk7DQoNCiAgdmFyIGxpc3RlbmVyID0gZnVuY3Rpb24oZXYpIHsNCiAgICBjdHJsLiRzZXRWaWV3VmFsdWUoZWxlbWVudFswXS5jaGVja2VkLCBldiAmJiBldi50eXBlKTsNCiAgfTsNCg0KICBlbGVtZW50Lm9uKCdjbGljaycsIGxpc3RlbmVyKTsNCg0KICBjdHJsLiRyZW5kZXIgPSBmdW5jdGlvbigpIHsNCiAgICBlbGVtZW50WzBdLmNoZWNrZWQgPSBjdHJsLiR2aWV3VmFsdWU7DQogIH07DQoNCiAgLy8gT3ZlcnJpZGUgdGhlIHN0YW5kYXJkIGAkaXNFbXB0eWAgYmVjYXVzZSB0aGUgJHZpZXdWYWx1ZSBvZiBhbiBlbXB0eSBjaGVja2JveCBpcyBhbHdheXMgc2V0IHRvIGBmYWxzZWANCiAgLy8gVGhpcyBpcyBiZWNhdXNlIG9mIHRoZSBwYXJzZXIgYmVsb3csIHdoaWNoIGNvbXBhcmVzIHRoZSBgJG1vZGVsVmFsdWVgIHdpdGggYHRydWVWYWx1ZWAgdG8gY29udmVydA0KICAvLyBpdCB0byBhIGJvb2xlYW4uDQogIGN0cmwuJGlzRW1wdHkgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgIHJldHVybiB2YWx1ZSA9PT0gZmFsc2U7DQogIH07DQoNCiAgY3RybC4kZm9ybWF0dGVycy5wdXNoKGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgcmV0dXJuIGVxdWFscyh2YWx1ZSwgdHJ1ZVZhbHVlKTsNCiAgfSk7DQoNCiAgY3RybC4kcGFyc2Vycy5wdXNoKGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgcmV0dXJuIHZhbHVlID8gdHJ1ZVZhbHVlIDogZmFsc2VWYWx1ZTsNCiAgfSk7DQp9DQoNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSB0ZXh0YXJlYQ0KICogQHJlc3RyaWN0IEUNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIEhUTUwgdGV4dGFyZWEgZWxlbWVudCBjb250cm9sIHdpdGggYW5ndWxhciBkYXRhLWJpbmRpbmcuIFRoZSBkYXRhLWJpbmRpbmcgYW5kIHZhbGlkYXRpb24NCiAqIHByb3BlcnRpZXMgb2YgdGhpcyBlbGVtZW50IGFyZSBleGFjdGx5IHRoZSBzYW1lIGFzIHRob3NlIG9mIHRoZQ0KICoge0BsaW5rIG5nLmRpcmVjdGl2ZTppbnB1dCBpbnB1dCBlbGVtZW50fS4NCiAqDQogKiBAcGFyYW0ge3N0cmluZ30gbmdNb2RlbCBBc3NpZ25hYmxlIGFuZ3VsYXIgZXhwcmVzc2lvbiB0byBkYXRhLWJpbmQgdG8uDQogKiBAcGFyYW0ge3N0cmluZz19IG5hbWUgUHJvcGVydHkgbmFtZSBvZiB0aGUgZm9ybSB1bmRlciB3aGljaCB0aGUgY29udHJvbCBpcyBwdWJsaXNoZWQuDQogKiBAcGFyYW0ge3N0cmluZz19IHJlcXVpcmVkIFNldHMgYHJlcXVpcmVkYCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgdmFsdWUgaXMgbm90IGVudGVyZWQuDQogKiBAcGFyYW0ge3N0cmluZz19IG5nUmVxdWlyZWQgQWRkcyBgcmVxdWlyZWRgIGF0dHJpYnV0ZSBhbmQgYHJlcXVpcmVkYCB2YWxpZGF0aW9uIGNvbnN0cmFpbnQgdG8NCiAqICAgIHRoZSBlbGVtZW50IHdoZW4gdGhlIG5nUmVxdWlyZWQgZXhwcmVzc2lvbiBldmFsdWF0ZXMgdG8gdHJ1ZS4gVXNlIGBuZ1JlcXVpcmVkYCBpbnN0ZWFkIG9mDQogKiAgICBgcmVxdWlyZWRgIHdoZW4geW91IHdhbnQgdG8gZGF0YS1iaW5kIHRvIHRoZSBgcmVxdWlyZWRgIGF0dHJpYnV0ZS4NCiAqIEBwYXJhbSB7bnVtYmVyPX0gbmdNaW5sZW5ndGggU2V0cyBgbWlubGVuZ3RoYCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgdmFsdWUgaXMgc2hvcnRlciB0aGFuDQogKiAgICBtaW5sZW5ndGguDQogKiBAcGFyYW0ge251bWJlcj19IG5nTWF4bGVuZ3RoIFNldHMgYG1heGxlbmd0aGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGlzIGxvbmdlciB0aGFuDQogKiAgICBtYXhsZW5ndGguIFNldHRpbmcgdGhlIGF0dHJpYnV0ZSB0byBhIG5lZ2F0aXZlIG9yIG5vbi1udW1lcmljIHZhbHVlLCBhbGxvd3MgdmlldyB2YWx1ZXMgb2YgYW55DQogKiAgICBsZW5ndGguDQogKiBAcGFyYW0ge3N0cmluZz19IG5nUGF0dGVybiBTZXRzIGBwYXR0ZXJuYCB2YWxpZGF0aW9uIGVycm9yIGtleSBpZiB0aGUgdmFsdWUgZG9lcyBub3QgbWF0Y2ggdGhlDQogKiAgICBSZWdFeHAgcGF0dGVybiBleHByZXNzaW9uLiBFeHBlY3RlZCB2YWx1ZSBpcyBgL3JlZ2V4cC9gIGZvciBpbmxpbmUgcGF0dGVybnMgb3IgYHJlZ2V4cGAgZm9yDQogKiAgICBwYXR0ZXJucyBkZWZpbmVkIGFzIHNjb3BlIGV4cHJlc3Npb25zLg0KICogQHBhcmFtIHtzdHJpbmc9fSBuZ0NoYW5nZSBBbmd1bGFyIGV4cHJlc3Npb24gdG8gYmUgZXhlY3V0ZWQgd2hlbiBpbnB1dCBjaGFuZ2VzIGR1ZSB0byB1c2VyDQogKiAgICBpbnRlcmFjdGlvbiB3aXRoIHRoZSBpbnB1dCBlbGVtZW50Lg0KICogQHBhcmFtIHtib29sZWFuPX0gW25nVHJpbT10cnVlXSBJZiBzZXQgdG8gZmFsc2UgQW5ndWxhciB3aWxsIG5vdCBhdXRvbWF0aWNhbGx5IHRyaW0gdGhlIGlucHV0Lg0KICovDQoNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBpbnB1dA0KICogQHJlc3RyaWN0IEUNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIEhUTUwgaW5wdXQgZWxlbWVudCBjb250cm9sLiBXaGVuIHVzZWQgdG9nZXRoZXIgd2l0aCB7QGxpbmsgbmdNb2RlbCBgbmdNb2RlbGB9LCBpdCBwcm92aWRlcyBkYXRhLWJpbmRpbmcsDQogKiBpbnB1dCBzdGF0ZSBjb250cm9sLCBhbmQgdmFsaWRhdGlvbi4NCiAqIElucHV0IGNvbnRyb2wgZm9sbG93cyBIVE1MNSBpbnB1dCB0eXBlcyBhbmQgcG9seWZpbGxzIHRoZSBIVE1MNSB2YWxpZGF0aW9uIGJlaGF2aW9yIGZvciBvbGRlciBicm93c2Vycy4NCiAqDQogKiA8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4NCiAqICoqTm90ZToqKiBOb3QgZXZlcnkgZmVhdHVyZSBvZmZlcmVkIGlzIGF2YWlsYWJsZSBmb3IgYWxsIGlucHV0IHR5cGVzLg0KICogU3BlY2lmaWNhbGx5LCBkYXRhIGJpbmRpbmcgYW5kIGV2ZW50IGhhbmRsaW5nIHZpYSBgbmctbW9kZWxgIGlzIHVuc3VwcG9ydGVkIGZvciBgaW5wdXRbZmlsZV1gLg0KICogPC9kaXY+DQogKg0KICogQHBhcmFtIHtzdHJpbmd9IG5nTW9kZWwgQXNzaWduYWJsZSBhbmd1bGFyIGV4cHJlc3Npb24gdG8gZGF0YS1iaW5kIHRvLg0KICogQHBhcmFtIHtzdHJpbmc9fSBuYW1lIFByb3BlcnR5IG5hbWUgb2YgdGhlIGZvcm0gdW5kZXIgd2hpY2ggdGhlIGNvbnRyb2wgaXMgcHVibGlzaGVkLg0KICogQHBhcmFtIHtzdHJpbmc9fSByZXF1aXJlZCBTZXRzIGByZXF1aXJlZGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGlzIG5vdCBlbnRlcmVkLg0KICogQHBhcmFtIHtib29sZWFuPX0gbmdSZXF1aXJlZCBTZXRzIGByZXF1aXJlZGAgYXR0cmlidXRlIGlmIHNldCB0byB0cnVlDQogKiBAcGFyYW0ge251bWJlcj19IG5nTWlubGVuZ3RoIFNldHMgYG1pbmxlbmd0aGAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGlzIHNob3J0ZXIgdGhhbg0KICogICAgbWlubGVuZ3RoLg0KICogQHBhcmFtIHtudW1iZXI9fSBuZ01heGxlbmd0aCBTZXRzIGBtYXhsZW5ndGhgIHZhbGlkYXRpb24gZXJyb3Iga2V5IGlmIHRoZSB2YWx1ZSBpcyBsb25nZXIgdGhhbg0KICogICAgbWF4bGVuZ3RoLiBTZXR0aW5nIHRoZSBhdHRyaWJ1dGUgdG8gYSBuZWdhdGl2ZSBvciBub24tbnVtZXJpYyB2YWx1ZSwgYWxsb3dzIHZpZXcgdmFsdWVzIG9mIGFueQ0KICogICAgbGVuZ3RoLg0KICogQHBhcmFtIHtzdHJpbmc9fSBuZ1BhdHRlcm4gU2V0cyBgcGF0dGVybmAgdmFsaWRhdGlvbiBlcnJvciBrZXkgaWYgdGhlIHZhbHVlIGRvZXMgbm90IG1hdGNoIHRoZQ0KICogICAgUmVnRXhwIHBhdHRlcm4gZXhwcmVzc2lvbi4gRXhwZWN0ZWQgdmFsdWUgaXMgYC9yZWdleHAvYCBmb3IgaW5saW5lIHBhdHRlcm5zIG9yIGByZWdleHBgIGZvcg0KICogICAgcGF0dGVybnMgZGVmaW5lZCBhcyBzY29wZSBleHByZXNzaW9ucy4NCiAqIEBwYXJhbSB7c3RyaW5nPX0gbmdDaGFuZ2UgQW5ndWxhciBleHByZXNzaW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gaW5wdXQgY2hhbmdlcyBkdWUgdG8gdXNlcg0KICogICAgaW50ZXJhY3Rpb24gd2l0aCB0aGUgaW5wdXQgZWxlbWVudC4NCiAqIEBwYXJhbSB7Ym9vbGVhbj19IFtuZ1RyaW09dHJ1ZV0gSWYgc2V0IHRvIGZhbHNlIEFuZ3VsYXIgd2lsbCBub3QgYXV0b21hdGljYWxseSB0cmltIHRoZSBpbnB1dC4NCiAqICAgIFRoaXMgcGFyYW1ldGVyIGlzIGlnbm9yZWQgZm9yIGlucHV0W3R5cGU9cGFzc3dvcmRdIGNvbnRyb2xzLCB3aGljaCB3aWxsIG5ldmVyIHRyaW0gdGhlDQogKiAgICBpbnB1dC4NCiAqDQogKiBAZXhhbXBsZQ0KICAgIDxleGFtcGxlIG5hbWU9ImlucHV0LWRpcmVjdGl2ZSIgbW9kdWxlPSJpbnB1dEV4YW1wbGUiPg0KICAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPHNjcmlwdD4NCiAgICAgICAgICBhbmd1bGFyLm1vZHVsZSgnaW5wdXRFeGFtcGxlJywgW10pDQogICAgICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICAgICAkc2NvcGUudXNlciA9IHtuYW1lOiAnZ3Vlc3QnLCBsYXN0OiAndmlzaXRvcid9Ow0KICAgICAgICAgICAgfV0pOw0KICAgICAgIDwvc2NyaXB0Pg0KICAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICAgICAgPGZvcm0gbmFtZT0ibXlGb3JtIj4NCiAgICAgICAgICAgVXNlciBuYW1lOiA8aW5wdXQgdHlwZT0idGV4dCIgbmFtZT0idXNlck5hbWUiIG5nLW1vZGVsPSJ1c2VyLm5hbWUiIHJlcXVpcmVkPg0KICAgICAgICAgICA8c3BhbiBjbGFzcz0iZXJyb3IiIG5nLXNob3c9Im15Rm9ybS51c2VyTmFtZS4kZXJyb3IucmVxdWlyZWQiPg0KICAgICAgICAgICAgIFJlcXVpcmVkITwvc3Bhbj48YnI+DQogICAgICAgICAgIExhc3QgbmFtZTogPGlucHV0IHR5cGU9InRleHQiIG5hbWU9Imxhc3ROYW1lIiBuZy1tb2RlbD0idXNlci5sYXN0Ig0KICAgICAgICAgICAgIG5nLW1pbmxlbmd0aD0iMyIgbmctbWF4bGVuZ3RoPSIxMCI+DQogICAgICAgICAgIDxzcGFuIGNsYXNzPSJlcnJvciIgbmctc2hvdz0ibXlGb3JtLmxhc3ROYW1lLiRlcnJvci5taW5sZW5ndGgiPg0KICAgICAgICAgICAgIFRvbyBzaG9ydCE8L3NwYW4+DQogICAgICAgICAgIDxzcGFuIGNsYXNzPSJlcnJvciIgbmctc2hvdz0ibXlGb3JtLmxhc3ROYW1lLiRlcnJvci5tYXhsZW5ndGgiPg0KICAgICAgICAgICAgIFRvbyBsb25nITwvc3Bhbj48YnI+DQogICAgICAgICA8L2Zvcm0+DQogICAgICAgICA8aHI+DQogICAgICAgICA8dHQ+dXNlciA9IHt7dXNlcn19PC90dD48YnIvPg0KICAgICAgICAgPHR0Pm15Rm9ybS51c2VyTmFtZS4kdmFsaWQgPSB7e215Rm9ybS51c2VyTmFtZS4kdmFsaWR9fTwvdHQ+PGJyPg0KICAgICAgICAgPHR0Pm15Rm9ybS51c2VyTmFtZS4kZXJyb3IgPSB7e215Rm9ybS51c2VyTmFtZS4kZXJyb3J9fTwvdHQ+PGJyPg0KICAgICAgICAgPHR0Pm15Rm9ybS5sYXN0TmFtZS4kdmFsaWQgPSB7e215Rm9ybS5sYXN0TmFtZS4kdmFsaWR9fTwvdHQ+PGJyPg0KICAgICAgICAgPHR0Pm15Rm9ybS5sYXN0TmFtZS4kZXJyb3IgPSB7e215Rm9ybS5sYXN0TmFtZS4kZXJyb3J9fTwvdHQ+PGJyPg0KICAgICAgICAgPHR0Pm15Rm9ybS4kdmFsaWQgPSB7e215Rm9ybS4kdmFsaWR9fTwvdHQ+PGJyPg0KICAgICAgICAgPHR0Pm15Rm9ybS4kZXJyb3IucmVxdWlyZWQgPSB7eyEhbXlGb3JtLiRlcnJvci5yZXF1aXJlZH19PC90dD48YnI+DQogICAgICAgICA8dHQ+bXlGb3JtLiRlcnJvci5taW5sZW5ndGggPSB7eyEhbXlGb3JtLiRlcnJvci5taW5sZW5ndGh9fTwvdHQ+PGJyPg0KICAgICAgICAgPHR0Pm15Rm9ybS4kZXJyb3IubWF4bGVuZ3RoID0ge3shIW15Rm9ybS4kZXJyb3IubWF4bGVuZ3RofX08L3R0Pjxicj4NCiAgICAgICA8L2Rpdj4NCiAgICAgIDwvZmlsZT4NCiAgICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgICB2YXIgdXNlciA9IGVsZW1lbnQoYnkuZXhhY3RCaW5kaW5nKCd1c2VyJykpOw0KICAgICAgICB2YXIgdXNlck5hbWVWYWxpZCA9IGVsZW1lbnQoYnkuYmluZGluZygnbXlGb3JtLnVzZXJOYW1lLiR2YWxpZCcpKTsNCiAgICAgICAgdmFyIGxhc3ROYW1lVmFsaWQgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ215Rm9ybS5sYXN0TmFtZS4kdmFsaWQnKSk7DQogICAgICAgIHZhciBsYXN0TmFtZUVycm9yID0gZWxlbWVudChieS5iaW5kaW5nKCdteUZvcm0ubGFzdE5hbWUuJGVycm9yJykpOw0KICAgICAgICB2YXIgZm9ybVZhbGlkID0gZWxlbWVudChieS5iaW5kaW5nKCdteUZvcm0uJHZhbGlkJykpOw0KICAgICAgICB2YXIgdXNlck5hbWVJbnB1dCA9IGVsZW1lbnQoYnkubW9kZWwoJ3VzZXIubmFtZScpKTsNCiAgICAgICAgdmFyIHVzZXJMYXN0SW5wdXQgPSBlbGVtZW50KGJ5Lm1vZGVsKCd1c2VyLmxhc3QnKSk7DQoNCiAgICAgICAgaXQoJ3Nob3VsZCBpbml0aWFsaXplIHRvIG1vZGVsJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgZXhwZWN0KHVzZXIuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ3sibmFtZSI6Imd1ZXN0IiwibGFzdCI6InZpc2l0b3IifScpOw0KICAgICAgICAgIGV4cGVjdCh1c2VyTmFtZVZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCd0cnVlJyk7DQogICAgICAgICAgZXhwZWN0KGZvcm1WYWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbigndHJ1ZScpOw0KICAgICAgICB9KTsNCg0KICAgICAgICBpdCgnc2hvdWxkIGJlIGludmFsaWQgaWYgZW1wdHkgd2hlbiByZXF1aXJlZCcsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgIHVzZXJOYW1lSW5wdXQuY2xlYXIoKTsNCiAgICAgICAgICB1c2VyTmFtZUlucHV0LnNlbmRLZXlzKCcnKTsNCg0KICAgICAgICAgIGV4cGVjdCh1c2VyLmdldFRleHQoKSkudG9Db250YWluKCd7Imxhc3QiOiJ2aXNpdG9yIn0nKTsNCiAgICAgICAgICBleHBlY3QodXNlck5hbWVWYWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbignZmFsc2UnKTsNCiAgICAgICAgICBleHBlY3QoZm9ybVZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdmYWxzZScpOw0KICAgICAgICB9KTsNCg0KICAgICAgICBpdCgnc2hvdWxkIGJlIHZhbGlkIGlmIGVtcHR5IHdoZW4gbWluIGxlbmd0aCBpcyBzZXQnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgICB1c2VyTGFzdElucHV0LmNsZWFyKCk7DQogICAgICAgICAgdXNlckxhc3RJbnB1dC5zZW5kS2V5cygnJyk7DQoNCiAgICAgICAgICBleHBlY3QodXNlci5nZXRUZXh0KCkpLnRvQ29udGFpbigneyJuYW1lIjoiZ3Vlc3QiLCJsYXN0IjoiIn0nKTsNCiAgICAgICAgICBleHBlY3QobGFzdE5hbWVWYWxpZC5nZXRUZXh0KCkpLnRvQ29udGFpbigndHJ1ZScpOw0KICAgICAgICAgIGV4cGVjdChmb3JtVmFsaWQuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ3RydWUnKTsNCiAgICAgICAgfSk7DQoNCiAgICAgICAgaXQoJ3Nob3VsZCBiZSBpbnZhbGlkIGlmIGxlc3MgdGhhbiByZXF1aXJlZCBtaW4gbGVuZ3RoJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgdXNlckxhc3RJbnB1dC5jbGVhcigpOw0KICAgICAgICAgIHVzZXJMYXN0SW5wdXQuc2VuZEtleXMoJ3h4Jyk7DQoNCiAgICAgICAgICBleHBlY3QodXNlci5nZXRUZXh0KCkpLnRvQ29udGFpbigneyJuYW1lIjoiZ3Vlc3QifScpOw0KICAgICAgICAgIGV4cGVjdChsYXN0TmFtZVZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdmYWxzZScpOw0KICAgICAgICAgIGV4cGVjdChsYXN0TmFtZUVycm9yLmdldFRleHQoKSkudG9Db250YWluKCdtaW5sZW5ndGgnKTsNCiAgICAgICAgICBleHBlY3QoZm9ybVZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdmYWxzZScpOw0KICAgICAgICB9KTsNCg0KICAgICAgICBpdCgnc2hvdWxkIGJlIGludmFsaWQgaWYgbG9uZ2VyIHRoYW4gbWF4IGxlbmd0aCcsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgIHVzZXJMYXN0SW5wdXQuY2xlYXIoKTsNCiAgICAgICAgICB1c2VyTGFzdElucHV0LnNlbmRLZXlzKCdzb21lIHJpZGljdWxvdXNseSBsb25nIG5hbWUnKTsNCg0KICAgICAgICAgIGV4cGVjdCh1c2VyLmdldFRleHQoKSkudG9Db250YWluKCd7Im5hbWUiOiJndWVzdCJ9Jyk7DQogICAgICAgICAgZXhwZWN0KGxhc3ROYW1lVmFsaWQuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ2ZhbHNlJyk7DQogICAgICAgICAgZXhwZWN0KGxhc3ROYW1lRXJyb3IuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ21heGxlbmd0aCcpOw0KICAgICAgICAgIGV4cGVjdChmb3JtVmFsaWQuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ2ZhbHNlJyk7DQogICAgICAgIH0pOw0KICAgICAgPC9maWxlPg0KICAgIDwvZXhhbXBsZT4NCiAqLw0KdmFyIGlucHV0RGlyZWN0aXZlID0gWyckYnJvd3NlcicsICckc25pZmZlcicsICckZmlsdGVyJywgJyRwYXJzZScsDQogICAgZnVuY3Rpb24oJGJyb3dzZXIsICRzbmlmZmVyLCAkZmlsdGVyLCAkcGFyc2UpIHsNCiAgcmV0dXJuIHsNCiAgICByZXN0cmljdDogJ0UnLA0KICAgIHJlcXVpcmU6IFsnP25nTW9kZWwnXSwNCiAgICBsaW5rOiB7DQogICAgICBwcmU6IGZ1bmN0aW9uKHNjb3BlLCBlbGVtZW50LCBhdHRyLCBjdHJscykgew0KICAgICAgICBpZiAoY3RybHNbMF0pIHsNCiAgICAgICAgICAoaW5wdXRUeXBlW2xvd2VyY2FzZShhdHRyLnR5cGUpXSB8fCBpbnB1dFR5cGUudGV4dCkoc2NvcGUsIGVsZW1lbnQsIGF0dHIsIGN0cmxzWzBdLCAkc25pZmZlciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGJyb3dzZXIsICRmaWx0ZXIsICRwYXJzZSk7DQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQogIH07DQp9XTsNCg0KdmFyIFZBTElEX0NMQVNTID0gJ25nLXZhbGlkJywNCiAgICBJTlZBTElEX0NMQVNTID0gJ25nLWludmFsaWQnLA0KICAgIFBSSVNUSU5FX0NMQVNTID0gJ25nLXByaXN0aW5lJywNCiAgICBESVJUWV9DTEFTUyA9ICduZy1kaXJ0eScsDQogICAgVU5UT1VDSEVEX0NMQVNTID0gJ25nLXVudG91Y2hlZCcsDQogICAgVE9VQ0hFRF9DTEFTUyA9ICduZy10b3VjaGVkJywNCiAgICBQRU5ESU5HX0NMQVNTID0gJ25nLXBlbmRpbmcnOw0KDQovKioNCiAqIEBuZ2RvYyB0eXBlDQogKiBAbmFtZSBuZ01vZGVsLk5nTW9kZWxDb250cm9sbGVyDQogKg0KICogQHByb3BlcnR5IHtzdHJpbmd9ICR2aWV3VmFsdWUgQWN0dWFsIHN0cmluZyB2YWx1ZSBpbiB0aGUgdmlldy4NCiAqIEBwcm9wZXJ0eSB7Kn0gJG1vZGVsVmFsdWUgVGhlIHZhbHVlIGluIHRoZSBtb2RlbCB0aGF0IHRoZSBjb250cm9sIGlzIGJvdW5kIHRvLg0KICogQHByb3BlcnR5IHtBcnJheS48RnVuY3Rpb24+fSAkcGFyc2VycyBBcnJheSBvZiBmdW5jdGlvbnMgdG8gZXhlY3V0ZSwgYXMgYSBwaXBlbGluZSwgd2hlbmV2ZXINCiAgICAgICB0aGUgY29udHJvbCByZWFkcyB2YWx1ZSBmcm9tIHRoZSBET00uIFRoZSBmdW5jdGlvbnMgYXJlIGNhbGxlZCBpbiBhcnJheSBvcmRlciwgZWFjaCBwYXNzaW5nDQogICAgICAgaXRzIHJldHVybiB2YWx1ZSB0aHJvdWdoIHRvIHRoZSBuZXh0LiBUaGUgbGFzdCByZXR1cm4gdmFsdWUgaXMgZm9yd2FyZGVkIHRvIHRoZQ0KICAgICAgIHtAbGluayBuZ01vZGVsLk5nTW9kZWxDb250cm9sbGVyIyR2YWxpZGF0b3JzIGAkdmFsaWRhdG9yc2B9IGNvbGxlY3Rpb24uDQoNClBhcnNlcnMgYXJlIHVzZWQgdG8gc2FuaXRpemUgLyBjb252ZXJ0IHRoZSB7QGxpbmsgbmdNb2RlbC5OZ01vZGVsQ29udHJvbGxlciMkdmlld1ZhbHVlDQpgJHZpZXdWYWx1ZWB9Lg0KDQpSZXR1cm5pbmcgYHVuZGVmaW5lZGAgZnJvbSBhIHBhcnNlciBtZWFucyBhIHBhcnNlIGVycm9yIG9jY3VycmVkLiBJbiB0aGF0IGNhc2UsDQpubyB7QGxpbmsgbmdNb2RlbC5OZ01vZGVsQ29udHJvbGxlciMkdmFsaWRhdG9ycyBgJHZhbGlkYXRvcnNgfSB3aWxsIHJ1biBhbmQgdGhlIGBuZ01vZGVsYA0Kd2lsbCBiZSBzZXQgdG8gYHVuZGVmaW5lZGAgdW5sZXNzIHtAbGluayBuZ01vZGVsT3B0aW9ucyBgbmdNb2RlbE9wdGlvbnMuYWxsb3dJbnZhbGlkYH0NCmlzIHNldCB0byBgdHJ1ZWAuIFRoZSBwYXJzZSBlcnJvciBpcyBzdG9yZWQgaW4gYG5nTW9kZWwuJGVycm9yLnBhcnNlYC4NCg0KICoNCiAqIEBwcm9wZXJ0eSB7QXJyYXkuPEZ1bmN0aW9uPn0gJGZvcm1hdHRlcnMgQXJyYXkgb2YgZnVuY3Rpb25zIHRvIGV4ZWN1dGUsIGFzIGEgcGlwZWxpbmUsIHdoZW5ldmVyDQogICAgICAgdGhlIG1vZGVsIHZhbHVlIGNoYW5nZXMuIFRoZSBmdW5jdGlvbnMgYXJlIGNhbGxlZCBpbiByZXZlcnNlIGFycmF5IG9yZGVyLCBlYWNoIHBhc3NpbmcgdGhlIHZhbHVlIHRocm91Z2ggdG8gdGhlDQogICAgICAgbmV4dC4gVGhlIGxhc3QgcmV0dXJuIHZhbHVlIGlzIHVzZWQgYXMgdGhlIGFjdHVhbCBET00gdmFsdWUuDQogICAgICAgVXNlZCB0byBmb3JtYXQgLyBjb252ZXJ0IHZhbHVlcyBmb3IgZGlzcGxheSBpbiB0aGUgY29udHJvbC4NCiAqIGBgYGpzDQogKiBmdW5jdGlvbiBmb3JtYXR0ZXIodmFsdWUpIHsNCiAqICAgaWYgKHZhbHVlKSB7DQogKiAgICAgcmV0dXJuIHZhbHVlLnRvVXBwZXJDYXNlKCk7DQogKiAgIH0NCiAqIH0NCiAqIG5nTW9kZWwuJGZvcm1hdHRlcnMucHVzaChmb3JtYXR0ZXIpOw0KICogYGBgDQogKg0KICogQHByb3BlcnR5IHtPYmplY3QuPHN0cmluZywgZnVuY3Rpb24+fSAkdmFsaWRhdG9ycyBBIGNvbGxlY3Rpb24gb2YgdmFsaWRhdG9ycyB0aGF0IGFyZSBhcHBsaWVkDQogKiAgICAgIHdoZW5ldmVyIHRoZSBtb2RlbCB2YWx1ZSBjaGFuZ2VzLiBUaGUga2V5IHZhbHVlIHdpdGhpbiB0aGUgb2JqZWN0IHJlZmVycyB0byB0aGUgbmFtZSBvZiB0aGUNCiAqICAgICAgdmFsaWRhdG9yIHdoaWxlIHRoZSBmdW5jdGlvbiByZWZlcnMgdG8gdGhlIHZhbGlkYXRpb24gb3BlcmF0aW9uLiBUaGUgdmFsaWRhdGlvbiBvcGVyYXRpb24gaXMNCiAqICAgICAgcHJvdmlkZWQgd2l0aCB0aGUgbW9kZWwgdmFsdWUgYXMgYW4gYXJndW1lbnQgYW5kIG11c3QgcmV0dXJuIGEgdHJ1ZSBvciBmYWxzZSB2YWx1ZSBkZXBlbmRpbmcNCiAqICAgICAgb24gdGhlIHJlc3BvbnNlIG9mIHRoYXQgdmFsaWRhdGlvbi4NCiAqDQogKiBgYGBqcw0KICogbmdNb2RlbC4kdmFsaWRhdG9ycy52YWxpZENoYXJhY3RlcnMgPSBmdW5jdGlvbihtb2RlbFZhbHVlLCB2aWV3VmFsdWUpIHsNCiAqICAgdmFyIHZhbHVlID0gbW9kZWxWYWx1ZSB8fCB2aWV3VmFsdWU7DQogKiAgIHJldHVybiAvWzAtOV0rLy50ZXN0KHZhbHVlKSAmJg0KICogICAgICAgICAgL1thLXpdKy8udGVzdCh2YWx1ZSkgJiYNCiAqICAgICAgICAgIC9bQS1aXSsvLnRlc3QodmFsdWUpICYmDQogKiAgICAgICAgICAvXFcrLy50ZXN0KHZhbHVlKTsNCiAqIH07DQogKiBgYGANCiAqDQogKiBAcHJvcGVydHkge09iamVjdC48c3RyaW5nLCBmdW5jdGlvbj59ICRhc3luY1ZhbGlkYXRvcnMgQSBjb2xsZWN0aW9uIG9mIHZhbGlkYXRpb25zIHRoYXQgYXJlIGV4cGVjdGVkIHRvDQogKiAgICAgIHBlcmZvcm0gYW4gYXN5bmNocm9ub3VzIHZhbGlkYXRpb24gKGUuZy4gYSBIVFRQIHJlcXVlc3QpLiBUaGUgdmFsaWRhdGlvbiBmdW5jdGlvbiB0aGF0IGlzIHByb3ZpZGVkDQogKiAgICAgIGlzIGV4cGVjdGVkIHRvIHJldHVybiBhIHByb21pc2Ugd2hlbiBpdCBpcyBydW4gZHVyaW5nIHRoZSBtb2RlbCB2YWxpZGF0aW9uIHByb2Nlc3MuIE9uY2UgdGhlIHByb21pc2UNCiAqICAgICAgaXMgZGVsaXZlcmVkIHRoZW4gdGhlIHZhbGlkYXRpb24gc3RhdHVzIHdpbGwgYmUgc2V0IHRvIHRydWUgd2hlbiBmdWxmaWxsZWQgYW5kIGZhbHNlIHdoZW4gcmVqZWN0ZWQuDQogKiAgICAgIFdoZW4gdGhlIGFzeW5jaHJvbm91cyB2YWxpZGF0b3JzIGFyZSB0cmlnZ2VyZWQsIGVhY2ggb2YgdGhlIHZhbGlkYXRvcnMgd2lsbCBydW4gaW4gcGFyYWxsZWwgYW5kIHRoZSBtb2RlbA0KICogICAgICB2YWx1ZSB3aWxsIG9ubHkgYmUgdXBkYXRlZCBvbmNlIGFsbCB2YWxpZGF0b3JzIGhhdmUgYmVlbiBmdWxmaWxsZWQuIEFzIGxvbmcgYXMgYW4gYXN5bmNocm9ub3VzIHZhbGlkYXRvcg0KICogICAgICBpcyB1bmZ1bGZpbGxlZCwgaXRzIGtleSB3aWxsIGJlIGFkZGVkIHRvIHRoZSBjb250cm9sbGVycyBgJHBlbmRpbmdgIHByb3BlcnR5LiBBbHNvLCBhbGwgYXN5bmNocm9ub3VzIHZhbGlkYXRvcnMNCiAqICAgICAgd2lsbCBvbmx5IHJ1biBvbmNlIGFsbCBzeW5jaHJvbm91cyB2YWxpZGF0b3JzIGhhdmUgcGFzc2VkLg0KICoNCiAqIFBsZWFzZSBub3RlIHRoYXQgaWYgJGh0dHAgaXMgdXNlZCB0aGVuIGl0IGlzIGltcG9ydGFudCB0aGF0IHRoZSBzZXJ2ZXIgcmV0dXJucyBhIHN1Y2Nlc3MgSFRUUCByZXNwb25zZSBjb2RlDQogKiBpbiBvcmRlciB0byBmdWxmaWxsIHRoZSB2YWxpZGF0aW9uIGFuZCBhIHN0YXR1cyBsZXZlbCBvZiBgNHh4YCBpbiBvcmRlciB0byByZWplY3QgdGhlIHZhbGlkYXRpb24uDQogKg0KICogYGBganMNCiAqIG5nTW9kZWwuJGFzeW5jVmFsaWRhdG9ycy51bmlxdWVVc2VybmFtZSA9IGZ1bmN0aW9uKG1vZGVsVmFsdWUsIHZpZXdWYWx1ZSkgew0KICogICB2YXIgdmFsdWUgPSBtb2RlbFZhbHVlIHx8IHZpZXdWYWx1ZTsNCiAqDQogKiAgIC8vIExvb2t1cCB1c2VyIGJ5IHVzZXJuYW1lDQogKiAgIHJldHVybiAkaHR0cC5nZXQoJy9hcGkvdXNlcnMvJyArIHZhbHVlKS4NCiAqICAgICAgdGhlbihmdW5jdGlvbiByZXNvbHZlZCgpIHsNCiAqICAgICAgICAvL3VzZXJuYW1lIGV4aXN0cywgdGhpcyBtZWFucyB2YWxpZGF0aW9uIGZhaWxzDQogKiAgICAgICAgcmV0dXJuICRxLnJlamVjdCgnZXhpc3RzJyk7DQogKiAgICAgIH0sIGZ1bmN0aW9uIHJlamVjdGVkKCkgew0KICogICAgICAgIC8vdXNlcm5hbWUgZG9lcyBub3QgZXhpc3QsIHRoZXJlZm9yZSB0aGlzIHZhbGlkYXRpb24gcGFzc2VzDQogKiAgICAgICAgcmV0dXJuIHRydWU7DQogKiAgICAgIH0pOw0KICogfTsNCiAqIGBgYA0KICoNCiAqIEBwcm9wZXJ0eSB7QXJyYXkuPEZ1bmN0aW9uPn0gJHZpZXdDaGFuZ2VMaXN0ZW5lcnMgQXJyYXkgb2YgZnVuY3Rpb25zIHRvIGV4ZWN1dGUgd2hlbmV2ZXIgdGhlDQogKiAgICAgdmlldyB2YWx1ZSBoYXMgY2hhbmdlZC4gSXQgaXMgY2FsbGVkIHdpdGggbm8gYXJndW1lbnRzLCBhbmQgaXRzIHJldHVybiB2YWx1ZSBpcyBpZ25vcmVkLg0KICogICAgIFRoaXMgY2FuIGJlIHVzZWQgaW4gcGxhY2Ugb2YgYWRkaXRpb25hbCAkd2F0Y2hlcyBhZ2FpbnN0IHRoZSBtb2RlbCB2YWx1ZS4NCiAqDQogKiBAcHJvcGVydHkge09iamVjdH0gJGVycm9yIEFuIG9iamVjdCBoYXNoIHdpdGggYWxsIGZhaWxpbmcgdmFsaWRhdG9yIGlkcyBhcyBrZXlzLg0KICogQHByb3BlcnR5IHtPYmplY3R9ICRwZW5kaW5nIEFuIG9iamVjdCBoYXNoIHdpdGggYWxsIHBlbmRpbmcgdmFsaWRhdG9yIGlkcyBhcyBrZXlzLg0KICoNCiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gJHVudG91Y2hlZCBUcnVlIGlmIGNvbnRyb2wgaGFzIG5vdCBsb3N0IGZvY3VzIHlldC4NCiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gJHRvdWNoZWQgVHJ1ZSBpZiBjb250cm9sIGhhcyBsb3N0IGZvY3VzLg0KICogQHByb3BlcnR5IHtib29sZWFufSAkcHJpc3RpbmUgVHJ1ZSBpZiB1c2VyIGhhcyBub3QgaW50ZXJhY3RlZCB3aXRoIHRoZSBjb250cm9sIHlldC4NCiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gJGRpcnR5IFRydWUgaWYgdXNlciBoYXMgYWxyZWFkeSBpbnRlcmFjdGVkIHdpdGggdGhlIGNvbnRyb2wuDQogKiBAcHJvcGVydHkge2Jvb2xlYW59ICR2YWxpZCBUcnVlIGlmIHRoZXJlIGlzIG5vIGVycm9yLg0KICogQHByb3BlcnR5IHtib29sZWFufSAkaW52YWxpZCBUcnVlIGlmIGF0IGxlYXN0IG9uZSBlcnJvciBvbiB0aGUgY29udHJvbC4NCiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSAkbmFtZSBUaGUgbmFtZSBhdHRyaWJ1dGUgb2YgdGhlIGNvbnRyb2wuDQogKg0KICogQGRlc2NyaXB0aW9uDQogKg0KICogYE5nTW9kZWxDb250cm9sbGVyYCBwcm92aWRlcyBBUEkgZm9yIHRoZSB7QGxpbmsgbmdNb2RlbCBgbmdNb2RlbGB9IGRpcmVjdGl2ZS4NCiAqIFRoZSBjb250cm9sbGVyIGNvbnRhaW5zIHNlcnZpY2VzIGZvciBkYXRhLWJpbmRpbmcsIHZhbGlkYXRpb24sIENTUyB1cGRhdGVzLCBhbmQgdmFsdWUgZm9ybWF0dGluZw0KICogYW5kIHBhcnNpbmcuIEl0IHB1cnBvc2VmdWxseSBkb2VzIG5vdCBjb250YWluIGFueSBsb2dpYyB3aGljaCBkZWFscyB3aXRoIERPTSByZW5kZXJpbmcgb3INCiAqIGxpc3RlbmluZyB0byBET00gZXZlbnRzLg0KICogU3VjaCBET00gcmVsYXRlZCBsb2dpYyBzaG91bGQgYmUgcHJvdmlkZWQgYnkgb3RoZXIgZGlyZWN0aXZlcyB3aGljaCBtYWtlIHVzZSBvZg0KICogYE5nTW9kZWxDb250cm9sbGVyYCBmb3IgZGF0YS1iaW5kaW5nIHRvIGNvbnRyb2wgZWxlbWVudHMuDQogKiBBbmd1bGFyIHByb3ZpZGVzIHRoaXMgRE9NIGxvZ2ljIGZvciBtb3N0IHtAbGluayBpbnB1dCBgaW5wdXRgfSBlbGVtZW50cy4NCiAqIEF0IHRoZSBlbmQgb2YgdGhpcyBwYWdlIHlvdSBjYW4gZmluZCBhIHtAbGluayBuZ01vZGVsLk5nTW9kZWxDb250cm9sbGVyI2N1c3RvbS1jb250cm9sLWV4YW1wbGUNCiAqIGN1c3RvbSBjb250cm9sIGV4YW1wbGV9IHRoYXQgdXNlcyBgbmdNb2RlbENvbnRyb2xsZXJgIHRvIGJpbmQgdG8gYGNvbnRlbnRlZGl0YWJsZWAgZWxlbWVudHMuDQogKg0KICogQGV4YW1wbGUNCiAqICMjIyBDdXN0b20gQ29udHJvbCBFeGFtcGxlDQogKiBUaGlzIGV4YW1wbGUgc2hvd3MgaG93IHRvIHVzZSBgTmdNb2RlbENvbnRyb2xsZXJgIHdpdGggYSBjdXN0b20gY29udHJvbCB0byBhY2hpZXZlDQogKiBkYXRhLWJpbmRpbmcuIE5vdGljZSBob3cgZGlmZmVyZW50IGRpcmVjdGl2ZXMgKGBjb250ZW50ZWRpdGFibGVgLCBgbmctbW9kZWxgLCBhbmQgYHJlcXVpcmVkYCkNCiAqIGNvbGxhYm9yYXRlIHRvZ2V0aGVyIHRvIGFjaGlldmUgdGhlIGRlc2lyZWQgcmVzdWx0Lg0KICoNCiAqIE5vdGUgdGhhdCBgY29udGVudGVkaXRhYmxlYCBpcyBhbiBIVE1MNSBhdHRyaWJ1dGUsIHdoaWNoIHRlbGxzIHRoZSBicm93c2VyIHRvIGxldCB0aGUgZWxlbWVudA0KICogY29udGVudHMgYmUgZWRpdGVkIGluIHBsYWNlIGJ5IHRoZSB1c2VyLiAgVGhpcyB3aWxsIG5vdCB3b3JrIG9uIG9sZGVyIGJyb3dzZXJzLg0KICoNCiAqIFdlIGFyZSB1c2luZyB0aGUge0BsaW5rIG5nLnNlcnZpY2U6JHNjZSAkc2NlfSBzZXJ2aWNlIGhlcmUgYW5kIGluY2x1ZGUgdGhlIHtAbGluayBuZ1Nhbml0aXplICRzYW5pdGl6ZX0NCiAqIG1vZHVsZSB0byBhdXRvbWF0aWNhbGx5IHJlbW92ZSAiYmFkIiBjb250ZW50IGxpa2UgaW5saW5lIGV2ZW50IGxpc3RlbmVyIChlLmcuIGA8c3BhbiBvbmNsaWNrPSIuLi4iPmApLg0KICogSG93ZXZlciwgYXMgd2UgYXJlIHVzaW5nIGAkc2NlYCB0aGUgbW9kZWwgY2FuIHN0aWxsIGRlY2lkZSB0byBwcm92aWRlIHVuc2FmZSBjb250ZW50IGlmIGl0IG1hcmtzDQogKiB0aGF0IGNvbnRlbnQgdXNpbmcgdGhlIGAkc2NlYCBzZXJ2aWNlLg0KICoNCiAqIDxleGFtcGxlIG5hbWU9Ik5nTW9kZWxDb250cm9sbGVyIiBtb2R1bGU9ImN1c3RvbUNvbnRyb2wiIGRlcHM9ImFuZ3VsYXItc2FuaXRpemUuanMiPg0KICAgIDxmaWxlIG5hbWU9InN0eWxlLmNzcyI+DQogICAgICBbY29udGVudGVkaXRhYmxlXSB7DQogICAgICAgIGJvcmRlcjogMXB4IHNvbGlkIGJsYWNrOw0KICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsNCiAgICAgICAgbWluLWhlaWdodDogMjBweDsNCiAgICAgIH0NCg0KICAgICAgLm5nLWludmFsaWQgew0KICAgICAgICBib3JkZXI6IDFweCBzb2xpZCByZWQ7DQogICAgICB9DQoNCiAgICA8L2ZpbGU+DQogICAgPGZpbGUgbmFtZT0ic2NyaXB0LmpzIj4NCiAgICAgIGFuZ3VsYXIubW9kdWxlKCdjdXN0b21Db250cm9sJywgWyduZ1Nhbml0aXplJ10pLg0KICAgICAgICBkaXJlY3RpdmUoJ2NvbnRlbnRlZGl0YWJsZScsIFsnJHNjZScsIGZ1bmN0aW9uKCRzY2UpIHsNCiAgICAgICAgICByZXR1cm4gew0KICAgICAgICAgICAgcmVzdHJpY3Q6ICdBJywgLy8gb25seSBhY3RpdmF0ZSBvbiBlbGVtZW50IGF0dHJpYnV0ZQ0KICAgICAgICAgICAgcmVxdWlyZTogJz9uZ01vZGVsJywgLy8gZ2V0IGEgaG9sZCBvZiBOZ01vZGVsQ29udHJvbGxlcg0KICAgICAgICAgICAgbGluazogZnVuY3Rpb24oc2NvcGUsIGVsZW1lbnQsIGF0dHJzLCBuZ01vZGVsKSB7DQogICAgICAgICAgICAgIGlmICghbmdNb2RlbCkgcmV0dXJuOyAvLyBkbyBub3RoaW5nIGlmIG5vIG5nLW1vZGVsDQoNCiAgICAgICAgICAgICAgLy8gU3BlY2lmeSBob3cgVUkgc2hvdWxkIGJlIHVwZGF0ZWQNCiAgICAgICAgICAgICAgbmdNb2RlbC4kcmVuZGVyID0gZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgICAgZWxlbWVudC5odG1sKCRzY2UuZ2V0VHJ1c3RlZEh0bWwobmdNb2RlbC4kdmlld1ZhbHVlIHx8ICcnKSk7DQogICAgICAgICAgICAgIH07DQoNCiAgICAgICAgICAgICAgLy8gTGlzdGVuIGZvciBjaGFuZ2UgZXZlbnRzIHRvIGVuYWJsZSBiaW5kaW5nDQogICAgICAgICAgICAgIGVsZW1lbnQub24oJ2JsdXIga2V5dXAgY2hhbmdlJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgICAgc2NvcGUuJGV2YWxBc3luYyhyZWFkKTsNCiAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICAgIHJlYWQoKTsgLy8gaW5pdGlhbGl6ZQ0KDQogICAgICAgICAgICAgIC8vIFdyaXRlIGRhdGEgdG8gdGhlIG1vZGVsDQogICAgICAgICAgICAgIGZ1bmN0aW9uIHJlYWQoKSB7DQogICAgICAgICAgICAgICAgdmFyIGh0bWwgPSBlbGVtZW50Lmh0bWwoKTsNCiAgICAgICAgICAgICAgICAvLyBXaGVuIHdlIGNsZWFyIHRoZSBjb250ZW50IGVkaXRhYmxlIHRoZSBicm93c2VyIGxlYXZlcyBhIDxicj4gYmVoaW5kDQogICAgICAgICAgICAgICAgLy8gSWYgc3RyaXAtYnIgYXR0cmlidXRlIGlzIHByb3ZpZGVkIHRoZW4gd2Ugc3RyaXAgdGhpcyBvdXQNCiAgICAgICAgICAgICAgICBpZiAoIGF0dHJzLnN0cmlwQnIgJiYgaHRtbCA9PSAnPGJyPicgKSB7DQogICAgICAgICAgICAgICAgICBodG1sID0gJyc7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIG5nTW9kZWwuJHNldFZpZXdWYWx1ZShodG1sKTsNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH07DQogICAgICAgIH1dKTsNCiAgICA8L2ZpbGU+DQogICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICA8Zm9ybSBuYW1lPSJteUZvcm0iPg0KICAgICAgIDxkaXYgY29udGVudGVkaXRhYmxlDQogICAgICAgICAgICBuYW1lPSJteVdpZGdldCIgbmctbW9kZWw9InVzZXJDb250ZW50Ig0KICAgICAgICAgICAgc3RyaXAtYnI9InRydWUiDQogICAgICAgICAgICByZXF1aXJlZD5DaGFuZ2UgbWUhPC9kaXY+DQogICAgICAgIDxzcGFuIG5nLXNob3c9Im15Rm9ybS5teVdpZGdldC4kZXJyb3IucmVxdWlyZWQiPlJlcXVpcmVkITwvc3Bhbj4NCiAgICAgICA8aHI+DQogICAgICAgPHRleHRhcmVhIG5nLW1vZGVsPSJ1c2VyQ29udGVudCI+PC90ZXh0YXJlYT4NCiAgICAgIDwvZm9ybT4NCiAgICA8L2ZpbGU+DQogICAgPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogICAgaXQoJ3Nob3VsZCBkYXRhLWJpbmQgYW5kIGJlY29tZSBpbnZhbGlkJywgZnVuY3Rpb24oKSB7DQogICAgICBpZiAoYnJvd3Nlci5wYXJhbXMuYnJvd3NlciA9PSAnc2FmYXJpJyB8fCBicm93c2VyLnBhcmFtcy5icm93c2VyID09ICdmaXJlZm94Jykgew0KICAgICAgICAvLyBTYWZhcmlEcml2ZXIgY2FuJ3QgaGFuZGxlIGNvbnRlbnRlZGl0YWJsZQ0KICAgICAgICAvLyBhbmQgRmlyZWZveCBkcml2ZXIgY2FuJ3QgY2xlYXIgY29udGVudGVkaXRhYmxlcyB2ZXJ5IHdlbGwNCiAgICAgICAgcmV0dXJuOw0KICAgICAgfQ0KICAgICAgdmFyIGNvbnRlbnRFZGl0YWJsZSA9IGVsZW1lbnQoYnkuY3NzKCdbY29udGVudGVkaXRhYmxlXScpKTsNCiAgICAgIHZhciBjb250ZW50ID0gJ0NoYW5nZSBtZSEnOw0KDQogICAgICBleHBlY3QoY29udGVudEVkaXRhYmxlLmdldFRleHQoKSkudG9FcXVhbChjb250ZW50KTsNCg0KICAgICAgY29udGVudEVkaXRhYmxlLmNsZWFyKCk7DQogICAgICBjb250ZW50RWRpdGFibGUuc2VuZEtleXMocHJvdHJhY3Rvci5LZXkuQkFDS19TUEFDRSk7DQogICAgICBleHBlY3QoY29udGVudEVkaXRhYmxlLmdldFRleHQoKSkudG9FcXVhbCgnJyk7DQogICAgICBleHBlY3QoY29udGVudEVkaXRhYmxlLmdldEF0dHJpYnV0ZSgnY2xhc3MnKSkudG9NYXRjaCgvbmctaW52YWxpZC1yZXF1aXJlZC8pOw0KICAgIH0pOw0KICAgIDwvZmlsZT4NCiAqIDwvZXhhbXBsZT4NCiAqDQogKg0KICovDQp2YXIgTmdNb2RlbENvbnRyb2xsZXIgPSBbJyRzY29wZScsICckZXhjZXB0aW9uSGFuZGxlcicsICckYXR0cnMnLCAnJGVsZW1lbnQnLCAnJHBhcnNlJywgJyRhbmltYXRlJywgJyR0aW1lb3V0JywgJyRyb290U2NvcGUnLCAnJHEnLCAnJGludGVycG9sYXRlJywNCiAgICBmdW5jdGlvbigkc2NvcGUsICRleGNlcHRpb25IYW5kbGVyLCAkYXR0ciwgJGVsZW1lbnQsICRwYXJzZSwgJGFuaW1hdGUsICR0aW1lb3V0LCAkcm9vdFNjb3BlLCAkcSwgJGludGVycG9sYXRlKSB7DQogIHRoaXMuJHZpZXdWYWx1ZSA9IE51bWJlci5OYU47DQogIHRoaXMuJG1vZGVsVmFsdWUgPSBOdW1iZXIuTmFOOw0KICB0aGlzLiQkcmF3TW9kZWxWYWx1ZSA9IHVuZGVmaW5lZDsgLy8gc3RvcmVzIHRoZSBwYXJzZWQgbW9kZWxWYWx1ZSAvIG1vZGVsIHNldCBmcm9tIHNjb3BlIHJlZ2FyZGxlc3Mgb2YgdmFsaWRpdHkuDQogIHRoaXMuJHZhbGlkYXRvcnMgPSB7fTsNCiAgdGhpcy4kYXN5bmNWYWxpZGF0b3JzID0ge307DQogIHRoaXMuJHBhcnNlcnMgPSBbXTsNCiAgdGhpcy4kZm9ybWF0dGVycyA9IFtdOw0KICB0aGlzLiR2aWV3Q2hhbmdlTGlzdGVuZXJzID0gW107DQogIHRoaXMuJHVudG91Y2hlZCA9IHRydWU7DQogIHRoaXMuJHRvdWNoZWQgPSBmYWxzZTsNCiAgdGhpcy4kcHJpc3RpbmUgPSB0cnVlOw0KICB0aGlzLiRkaXJ0eSA9IGZhbHNlOw0KICB0aGlzLiR2YWxpZCA9IHRydWU7DQogIHRoaXMuJGludmFsaWQgPSBmYWxzZTsNCiAgdGhpcy4kZXJyb3IgPSB7fTsgLy8ga2VlcCBpbnZhbGlkIGtleXMgaGVyZQ0KICB0aGlzLiQkc3VjY2VzcyA9IHt9OyAvLyBrZWVwIHZhbGlkIGtleXMgaGVyZQ0KICB0aGlzLiRwZW5kaW5nID0gdW5kZWZpbmVkOyAvLyBrZWVwIHBlbmRpbmcga2V5cyBoZXJlDQogIHRoaXMuJG5hbWUgPSAkaW50ZXJwb2xhdGUoJGF0dHIubmFtZSB8fCAnJywgZmFsc2UpKCRzY29wZSk7DQoNCg0KICB2YXIgcGFyc2VkTmdNb2RlbCA9ICRwYXJzZSgkYXR0ci5uZ01vZGVsKSwNCiAgICAgIHBhcnNlZE5nTW9kZWxBc3NpZ24gPSBwYXJzZWROZ01vZGVsLmFzc2lnbiwNCiAgICAgIG5nTW9kZWxHZXQgPSBwYXJzZWROZ01vZGVsLA0KICAgICAgbmdNb2RlbFNldCA9IHBhcnNlZE5nTW9kZWxBc3NpZ24sDQogICAgICBwZW5kaW5nRGVib3VuY2UgPSBudWxsLA0KICAgICAgY3RybCA9IHRoaXM7DQoNCiAgdGhpcy4kJHNldE9wdGlvbnMgPSBmdW5jdGlvbihvcHRpb25zKSB7DQogICAgY3RybC4kb3B0aW9ucyA9IG9wdGlvbnM7DQogICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5nZXR0ZXJTZXR0ZXIpIHsNCiAgICAgIHZhciBpbnZva2VNb2RlbEdldHRlciA9ICRwYXJzZSgkYXR0ci5uZ01vZGVsICsgJygpJyksDQogICAgICAgICAgaW52b2tlTW9kZWxTZXR0ZXIgPSAkcGFyc2UoJGF0dHIubmdNb2RlbCArICcoJCQkcCknKTsNCg0KICAgICAgbmdNb2RlbEdldCA9IGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICB2YXIgbW9kZWxWYWx1ZSA9IHBhcnNlZE5nTW9kZWwoJHNjb3BlKTsNCiAgICAgICAgaWYgKGlzRnVuY3Rpb24obW9kZWxWYWx1ZSkpIHsNCiAgICAgICAgICBtb2RlbFZhbHVlID0gaW52b2tlTW9kZWxHZXR0ZXIoJHNjb3BlKTsNCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gbW9kZWxWYWx1ZTsNCiAgICAgIH07DQogICAgICBuZ01vZGVsU2V0ID0gZnVuY3Rpb24oJHNjb3BlLCBuZXdWYWx1ZSkgew0KICAgICAgICBpZiAoaXNGdW5jdGlvbihwYXJzZWROZ01vZGVsKCRzY29wZSkpKSB7DQogICAgICAgICAgaW52b2tlTW9kZWxTZXR0ZXIoJHNjb3BlLCB7JCQkcDogY3RybC4kbW9kZWxWYWx1ZX0pOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIHBhcnNlZE5nTW9kZWxBc3NpZ24oJHNjb3BlLCBjdHJsLiRtb2RlbFZhbHVlKTsNCiAgICAgICAgfQ0KICAgICAgfTsNCiAgICB9IGVsc2UgaWYgKCFwYXJzZWROZ01vZGVsLmFzc2lnbikgew0KICAgICAgdGhyb3cgJG5nTW9kZWxNaW5FcnIoJ25vbmFzc2lnbicsICJFeHByZXNzaW9uICd7MH0nIGlzIG5vbi1hc3NpZ25hYmxlLiBFbGVtZW50OiB7MX0iLA0KICAgICAgICAgICRhdHRyLm5nTW9kZWwsIHN0YXJ0aW5nVGFnKCRlbGVtZW50KSk7DQogICAgfQ0KICB9Ow0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lIG5nTW9kZWwuTmdNb2RlbENvbnRyb2xsZXIjJHJlbmRlcg0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogQ2FsbGVkIHdoZW4gdGhlIHZpZXcgbmVlZHMgdG8gYmUgdXBkYXRlZC4gSXQgaXMgZXhwZWN0ZWQgdGhhdCB0aGUgdXNlciBvZiB0aGUgbmctbW9kZWwNCiAgICogZGlyZWN0aXZlIHdpbGwgaW1wbGVtZW50IHRoaXMgbWV0aG9kLg0KICAgKg0KICAgKiBUaGUgYCRyZW5kZXIoKWAgbWV0aG9kIGlzIGludm9rZWQgaW4gdGhlIGZvbGxvd2luZyBzaXR1YXRpb25zOg0KICAgKg0KICAgKiAqIGAkcm9sbGJhY2tWaWV3VmFsdWUoKWAgaXMgY2FsbGVkLiAgSWYgd2UgYXJlIHJvbGxpbmcgYmFjayB0aGUgdmlldyB2YWx1ZSB0byB0aGUgbGFzdA0KICAgKiAgIGNvbW1pdHRlZCB2YWx1ZSB0aGVuIGAkcmVuZGVyKClgIGlzIGNhbGxlZCB0byB1cGRhdGUgdGhlIGlucHV0IGNvbnRyb2wuDQogICAqICogVGhlIHZhbHVlIHJlZmVyZW5jZWQgYnkgYG5nLW1vZGVsYCBpcyBjaGFuZ2VkIHByb2dyYW1tYXRpY2FsbHkgYW5kIGJvdGggdGhlIGAkbW9kZWxWYWx1ZWAgYW5kDQogICAqICAgdGhlIGAkdmlld1ZhbHVlYCBhcmUgZGlmZmVyZW50IHRvIGxhc3QgdGltZS4NCiAgICoNCiAgICogU2luY2UgYG5nLW1vZGVsYCBkb2VzIG5vdCBkbyBhIGRlZXAgd2F0Y2gsIGAkcmVuZGVyKClgIGlzIG9ubHkgaW52b2tlZCBpZiB0aGUgdmFsdWVzIG9mDQogICAqIGAkbW9kZWxWYWx1ZWAgYW5kIGAkdmlld1ZhbHVlYCBhcmUgYWN0dWFsbHkgZGlmZmVyZW50IHRvIHRoZWlyIHByZXZpb3VzIHZhbHVlLiBJZiBgJG1vZGVsVmFsdWVgDQogICAqIG9yIGAkdmlld1ZhbHVlYCBhcmUgb2JqZWN0cyAocmF0aGVyIHRoYW4gYSBzdHJpbmcgb3IgbnVtYmVyKSB0aGVuIGAkcmVuZGVyKClgIHdpbGwgbm90IGJlDQogICAqIGludm9rZWQgaWYgeW91IG9ubHkgY2hhbmdlIGEgcHJvcGVydHkgb24gdGhlIG9iamVjdHMuDQogICAqLw0KICB0aGlzLiRyZW5kZXIgPSBub29wOw0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lIG5nTW9kZWwuTmdNb2RlbENvbnRyb2xsZXIjJGlzRW1wdHkNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFRoaXMgaXMgY2FsbGVkIHdoZW4gd2UgbmVlZCB0byBkZXRlcm1pbmUgaWYgdGhlIHZhbHVlIG9mIGFuIGlucHV0IGlzIGVtcHR5Lg0KICAgKg0KICAgKiBGb3IgaW5zdGFuY2UsIHRoZSByZXF1aXJlZCBkaXJlY3RpdmUgZG9lcyB0aGlzIHRvIHdvcmsgb3V0IGlmIHRoZSBpbnB1dCBoYXMgZGF0YSBvciBub3QuDQogICAqDQogICAqIFRoZSBkZWZhdWx0IGAkaXNFbXB0eWAgZnVuY3Rpb24gY2hlY2tzIHdoZXRoZXIgdGhlIHZhbHVlIGlzIGB1bmRlZmluZWRgLCBgJydgLCBgbnVsbGAgb3IgYE5hTmAuDQogICAqDQogICAqIFlvdSBjYW4gb3ZlcnJpZGUgdGhpcyBmb3IgaW5wdXQgZGlyZWN0aXZlcyB3aG9zZSBjb25jZXB0IG9mIGJlaW5nIGVtcHR5IGlzIGRpZmZlcmVudCB0byB0aGUNCiAgICogZGVmYXVsdC4gVGhlIGBjaGVja2JveElucHV0VHlwZWAgZGlyZWN0aXZlIGRvZXMgdGhpcyBiZWNhdXNlIGluIGl0cyBjYXNlIGEgdmFsdWUgb2YgYGZhbHNlYA0KICAgKiBpbXBsaWVzIGVtcHR5Lg0KICAgKg0KICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSBvZiB0aGUgaW5wdXQgdG8gY2hlY2sgZm9yIGVtcHRpbmVzcy4NCiAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgYHZhbHVlYCBpcyAiZW1wdHkiLg0KICAgKi8NCiAgdGhpcy4kaXNFbXB0eSA9IGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgcmV0dXJuIGlzVW5kZWZpbmVkKHZhbHVlKSB8fCB2YWx1ZSA9PT0gJycgfHwgdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgIT09IHZhbHVlOw0KICB9Ow0KDQogIHZhciBwYXJlbnRGb3JtID0gJGVsZW1lbnQuaW5oZXJpdGVkRGF0YSgnJGZvcm1Db250cm9sbGVyJykgfHwgbnVsbEZvcm1DdHJsLA0KICAgICAgY3VycmVudFZhbGlkYXRpb25SdW5JZCA9IDA7DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgbmdNb2RlbC5OZ01vZGVsQ29udHJvbGxlciMkc2V0VmFsaWRpdHkNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIENoYW5nZSB0aGUgdmFsaWRpdHkgc3RhdGUsIGFuZCBub3RpZnkgdGhlIGZvcm0uDQogICAqDQogICAqIFRoaXMgbWV0aG9kIGNhbiBiZSBjYWxsZWQgd2l0aGluICRwYXJzZXJzLyRmb3JtYXR0ZXJzIG9yIGEgY3VzdG9tIHZhbGlkYXRpb24gaW1wbGVtZW50YXRpb24uDQogICAqIEhvd2V2ZXIsIGluIG1vc3QgY2FzZXMgaXQgc2hvdWxkIGJlIHN1ZmZpY2llbnQgdG8gdXNlIHRoZSBgbmdNb2RlbC4kdmFsaWRhdG9yc2AgYW5kDQogICAqIGBuZ01vZGVsLiRhc3luY1ZhbGlkYXRvcnNgIGNvbGxlY3Rpb25zIHdoaWNoIHdpbGwgY2FsbCBgJHNldFZhbGlkaXR5YCBhdXRvbWF0aWNhbGx5Lg0KICAgKg0KICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsaWRhdGlvbkVycm9yS2V5IE5hbWUgb2YgdGhlIHZhbGlkYXRvci4gVGhlIGB2YWxpZGF0aW9uRXJyb3JLZXlgIHdpbGwgYmUgYXNzaWduZWQNCiAgICogICAgICAgIHRvIGVpdGhlciBgJGVycm9yW3ZhbGlkYXRpb25FcnJvcktleV1gIG9yIGAkcGVuZGluZ1t2YWxpZGF0aW9uRXJyb3JLZXldYA0KICAgKiAgICAgICAgKGZvciB1bmZ1bGZpbGxlZCBgJGFzeW5jVmFsaWRhdG9yc2ApLCBzbyB0aGF0IGl0IGlzIGF2YWlsYWJsZSBmb3IgZGF0YS1iaW5kaW5nLg0KICAgKiAgICAgICAgVGhlIGB2YWxpZGF0aW9uRXJyb3JLZXlgIHNob3VsZCBiZSBpbiBjYW1lbENhc2UgYW5kIHdpbGwgZ2V0IGNvbnZlcnRlZCBpbnRvIGRhc2gtY2FzZQ0KICAgKiAgICAgICAgZm9yIGNsYXNzIG5hbWUuIEV4YW1wbGU6IGBteUVycm9yYCB3aWxsIHJlc3VsdCBpbiBgbmctdmFsaWQtbXktZXJyb3JgIGFuZCBgbmctaW52YWxpZC1teS1lcnJvcmANCiAgICogICAgICAgIGNsYXNzIGFuZCBjYW4gYmUgYm91bmQgdG8gYXMgIGB7e3NvbWVGb3JtLnNvbWVDb250cm9sLiRlcnJvci5teUVycm9yfX1gIC4NCiAgICogQHBhcmFtIHtib29sZWFufSBpc1ZhbGlkIFdoZXRoZXIgdGhlIGN1cnJlbnQgc3RhdGUgaXMgdmFsaWQgKHRydWUpLCBpbnZhbGlkIChmYWxzZSksIHBlbmRpbmcgKHVuZGVmaW5lZCksDQogICAqICAgICAgICAgICAgICAgICAgICAgICAgICBvciBza2lwcGVkIChudWxsKS4gUGVuZGluZyBpcyB1c2VkIGZvciB1bmZ1bGZpbGxlZCBgJGFzeW5jVmFsaWRhdG9yc2AuDQogICAqICAgICAgICAgICAgICAgICAgICAgICAgICBTa2lwcGVkIGlzIHVzZWQgYnkgQW5ndWxhciB3aGVuIHZhbGlkYXRvcnMgZG8gbm90IHJ1biBiZWNhdXNlIG9mIHBhcnNlIGVycm9ycyBhbmQNCiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIHdoZW4gYCRhc3luY1ZhbGlkYXRvcnNgIGRvIG5vdCBydW4gYmVjYXVzZSBhbnkgb2YgdGhlIGAkdmFsaWRhdG9yc2AgZmFpbGVkLg0KICAgKi8NCiAgYWRkU2V0VmFsaWRpdHlNZXRob2Qoew0KICAgIGN0cmw6IHRoaXMsDQogICAgJGVsZW1lbnQ6ICRlbGVtZW50LA0KICAgIHNldDogZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgew0KICAgICAgb2JqZWN0W3Byb3BlcnR5XSA9IHRydWU7DQogICAgfSwNCiAgICB1bnNldDogZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgew0KICAgICAgZGVsZXRlIG9iamVjdFtwcm9wZXJ0eV07DQogICAgfSwNCiAgICBwYXJlbnRGb3JtOiBwYXJlbnRGb3JtLA0KICAgICRhbmltYXRlOiAkYW5pbWF0ZQ0KICB9KTsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSBuZ01vZGVsLk5nTW9kZWxDb250cm9sbGVyIyRzZXRQcmlzdGluZQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogU2V0cyB0aGUgY29udHJvbCB0byBpdHMgcHJpc3RpbmUgc3RhdGUuDQogICAqDQogICAqIFRoaXMgbWV0aG9kIGNhbiBiZSBjYWxsZWQgdG8gcmVtb3ZlIHRoZSBgbmctZGlydHlgIGNsYXNzIGFuZCBzZXQgdGhlIGNvbnRyb2wgdG8gaXRzIHByaXN0aW5lDQogICAqIHN0YXRlIChgbmctcHJpc3RpbmVgIGNsYXNzKS4gQSBtb2RlbCBpcyBjb25zaWRlcmVkIHRvIGJlIHByaXN0aW5lIHdoZW4gdGhlIGNvbnRyb2wNCiAgICogaGFzIG5vdCBiZWVuIGNoYW5nZWQgZnJvbSB3aGVuIGZpcnN0IGNvbXBpbGVkLg0KICAgKi8NCiAgdGhpcy4kc2V0UHJpc3RpbmUgPSBmdW5jdGlvbigpIHsNCiAgICBjdHJsLiRkaXJ0eSA9IGZhbHNlOw0KICAgIGN0cmwuJHByaXN0aW5lID0gdHJ1ZTsNCiAgICAkYW5pbWF0ZS5yZW1vdmVDbGFzcygkZWxlbWVudCwgRElSVFlfQ0xBU1MpOw0KICAgICRhbmltYXRlLmFkZENsYXNzKCRlbGVtZW50LCBQUklTVElORV9DTEFTUyk7DQogIH07DQoNCiAgLyoqDQogICAqIEBuZ2RvYyBtZXRob2QNCiAgICogQG5hbWUgbmdNb2RlbC5OZ01vZGVsQ29udHJvbGxlciMkc2V0RGlydHkNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFNldHMgdGhlIGNvbnRyb2wgdG8gaXRzIGRpcnR5IHN0YXRlLg0KICAgKg0KICAgKiBUaGlzIG1ldGhvZCBjYW4gYmUgY2FsbGVkIHRvIHJlbW92ZSB0aGUgYG5nLXByaXN0aW5lYCBjbGFzcyBhbmQgc2V0IHRoZSBjb250cm9sIHRvIGl0cyBkaXJ0eQ0KICAgKiBzdGF0ZSAoYG5nLWRpcnR5YCBjbGFzcykuIEEgbW9kZWwgaXMgY29uc2lkZXJlZCB0byBiZSBkaXJ0eSB3aGVuIHRoZSBjb250cm9sIGhhcyBiZWVuIGNoYW5nZWQNCiAgICogZnJvbSB3aGVuIGZpcnN0IGNvbXBpbGVkLg0KICAgKi8NCiAgdGhpcy4kc2V0RGlydHkgPSBmdW5jdGlvbigpIHsNCiAgICBjdHJsLiRkaXJ0eSA9IHRydWU7DQogICAgY3RybC4kcHJpc3RpbmUgPSBmYWxzZTsNCiAgICAkYW5pbWF0ZS5yZW1vdmVDbGFzcygkZWxlbWVudCwgUFJJU1RJTkVfQ0xBU1MpOw0KICAgICRhbmltYXRlLmFkZENsYXNzKCRlbGVtZW50LCBESVJUWV9DTEFTUyk7DQogICAgcGFyZW50Rm9ybS4kc2V0RGlydHkoKTsNCiAgfTsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSBuZ01vZGVsLk5nTW9kZWxDb250cm9sbGVyIyRzZXRVbnRvdWNoZWQNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFNldHMgdGhlIGNvbnRyb2wgdG8gaXRzIHVudG91Y2hlZCBzdGF0ZS4NCiAgICoNCiAgICogVGhpcyBtZXRob2QgY2FuIGJlIGNhbGxlZCB0byByZW1vdmUgdGhlIGBuZy10b3VjaGVkYCBjbGFzcyBhbmQgc2V0IHRoZSBjb250cm9sIHRvIGl0cw0KICAgKiB1bnRvdWNoZWQgc3RhdGUgKGBuZy11bnRvdWNoZWRgIGNsYXNzKS4gVXBvbiBjb21waWxhdGlvbiwgYSBtb2RlbCBpcyBzZXQgYXMgdW50b3VjaGVkDQogICAqIGJ5IGRlZmF1bHQsIGhvd2V2ZXIgdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byByZXN0b3JlIHRoYXQgc3RhdGUgaWYgdGhlIG1vZGVsIGhhcw0KICAgKiBhbHJlYWR5IGJlZW4gdG91Y2hlZCBieSB0aGUgdXNlci4NCiAgICovDQogIHRoaXMuJHNldFVudG91Y2hlZCA9IGZ1bmN0aW9uKCkgew0KICAgIGN0cmwuJHRvdWNoZWQgPSBmYWxzZTsNCiAgICBjdHJsLiR1bnRvdWNoZWQgPSB0cnVlOw0KICAgICRhbmltYXRlLnNldENsYXNzKCRlbGVtZW50LCBVTlRPVUNIRURfQ0xBU1MsIFRPVUNIRURfQ0xBU1MpOw0KICB9Ow0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lIG5nTW9kZWwuTmdNb2RlbENvbnRyb2xsZXIjJHNldFRvdWNoZWQNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFNldHMgdGhlIGNvbnRyb2wgdG8gaXRzIHRvdWNoZWQgc3RhdGUuDQogICAqDQogICAqIFRoaXMgbWV0aG9kIGNhbiBiZSBjYWxsZWQgdG8gcmVtb3ZlIHRoZSBgbmctdW50b3VjaGVkYCBjbGFzcyBhbmQgc2V0IHRoZSBjb250cm9sIHRvIGl0cw0KICAgKiB0b3VjaGVkIHN0YXRlIChgbmctdG91Y2hlZGAgY2xhc3MpLiBBIG1vZGVsIGlzIGNvbnNpZGVyZWQgdG8gYmUgdG91Y2hlZCB3aGVuIHRoZSB1c2VyIGhhcw0KICAgKiBmaXJzdCBmb2N1c2VkIHRoZSBjb250cm9sIGVsZW1lbnQgYW5kIHRoZW4gc2hpZnRlZCBmb2N1cyBhd2F5IGZyb20gdGhlIGNvbnRyb2wgKGJsdXIgZXZlbnQpLg0KICAgKi8NCiAgdGhpcy4kc2V0VG91Y2hlZCA9IGZ1bmN0aW9uKCkgew0KICAgIGN0cmwuJHRvdWNoZWQgPSB0cnVlOw0KICAgIGN0cmwuJHVudG91Y2hlZCA9IGZhbHNlOw0KICAgICRhbmltYXRlLnNldENsYXNzKCRlbGVtZW50LCBUT1VDSEVEX0NMQVNTLCBVTlRPVUNIRURfQ0xBU1MpOw0KICB9Ow0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lIG5nTW9kZWwuTmdNb2RlbENvbnRyb2xsZXIjJHJvbGxiYWNrVmlld1ZhbHVlDQogICAqDQogICAqIEBkZXNjcmlwdGlvbg0KICAgKiBDYW5jZWwgYW4gdXBkYXRlIGFuZCByZXNldCB0aGUgaW5wdXQgZWxlbWVudCdzIHZhbHVlIHRvIHByZXZlbnQgYW4gdXBkYXRlIHRvIHRoZSBgJG1vZGVsVmFsdWVgLA0KICAgKiB3aGljaCBtYXkgYmUgY2F1c2VkIGJ5IGEgcGVuZGluZyBkZWJvdW5jZWQgZXZlbnQgb3IgYmVjYXVzZSB0aGUgaW5wdXQgaXMgd2FpdGluZyBmb3IgYSBzb21lDQogICAqIGZ1dHVyZSBldmVudC4NCiAgICoNCiAgICogSWYgeW91IGhhdmUgYW4gaW5wdXQgdGhhdCB1c2VzIGBuZy1tb2RlbC1vcHRpb25zYCB0byBzZXQgdXAgZGVib3VuY2VkIGV2ZW50cyBvciBldmVudHMgc3VjaA0KICAgKiBhcyBibHVyIHlvdSBjYW4gaGF2ZSBhIHNpdHVhdGlvbiB3aGVyZSB0aGVyZSBpcyBhIHBlcmlvZCB3aGVuIHRoZSBgJHZpZXdWYWx1ZWANCiAgICogaXMgb3V0IG9mIHN5bmNoIHdpdGggdGhlIG5nTW9kZWwncyBgJG1vZGVsVmFsdWVgLg0KICAgKg0KICAgKiBJbiB0aGlzIGNhc2UsIHlvdSBjYW4gcnVuIGludG8gZGlmZmljdWx0aWVzIGlmIHlvdSB0cnkgdG8gdXBkYXRlIHRoZSBuZ01vZGVsJ3MgYCRtb2RlbFZhbHVlYA0KICAgKiBwcm9ncmFtbWF0aWNhbGx5IGJlZm9yZSB0aGVzZSBkZWJvdW5jZWQvZnV0dXJlIGV2ZW50cyBoYXZlIHJlc29sdmVkL29jY3VycmVkLCBiZWNhdXNlIEFuZ3VsYXIncw0KICAgKiBkaXJ0eSBjaGVja2luZyBtZWNoYW5pc20gaXMgbm90IGFibGUgdG8gdGVsbCB3aGV0aGVyIHRoZSBtb2RlbCBoYXMgYWN0dWFsbHkgY2hhbmdlZCBvciBub3QuDQogICAqDQogICAqIFRoZSBgJHJvbGxiYWNrVmlld1ZhbHVlKClgIG1ldGhvZCBzaG91bGQgYmUgY2FsbGVkIGJlZm9yZSBwcm9ncmFtbWF0aWNhbGx5IGNoYW5naW5nIHRoZSBtb2RlbCBvZiBhbg0KICAgKiBpbnB1dCB3aGljaCBtYXkgaGF2ZSBzdWNoIGV2ZW50cyBwZW5kaW5nLiBUaGlzIGlzIGltcG9ydGFudCBpbiBvcmRlciB0byBtYWtlIHN1cmUgdGhhdCB0aGUNCiAgICogaW5wdXQgZmllbGQgd2lsbCBiZSB1cGRhdGVkIHdpdGggdGhlIG5ldyBtb2RlbCB2YWx1ZSBhbmQgYW55IHBlbmRpbmcgb3BlcmF0aW9ucyBhcmUgY2FuY2VsbGVkLg0KICAgKg0KICAgKiA8ZXhhbXBsZSBuYW1lPSJuZy1tb2RlbC1jYW5jZWwtdXBkYXRlIiBtb2R1bGU9ImNhbmNlbC11cGRhdGUtZXhhbXBsZSI+DQogICAqICAgPGZpbGUgbmFtZT0iYXBwLmpzIj4NCiAgICogICAgIGFuZ3VsYXIubW9kdWxlKCdjYW5jZWwtdXBkYXRlLWV4YW1wbGUnLCBbXSkNCiAgICoNCiAgICogICAgIC5jb250cm9sbGVyKCdDYW5jZWxVcGRhdGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICogICAgICAgJHNjb3BlLnJlc2V0V2l0aENhbmNlbCA9IGZ1bmN0aW9uKGUpIHsNCiAgICogICAgICAgICBpZiAoZS5rZXlDb2RlID09IDI3KSB7DQogICAqICAgICAgICAgICAkc2NvcGUubXlGb3JtLm15SW5wdXQxLiRyb2xsYmFja1ZpZXdWYWx1ZSgpOw0KICAgKiAgICAgICAgICAgJHNjb3BlLm15VmFsdWUgPSAnJzsNCiAgICogICAgICAgICB9DQogICAqICAgICAgIH07DQogICAqICAgICAgICRzY29wZS5yZXNldFdpdGhvdXRDYW5jZWwgPSBmdW5jdGlvbihlKSB7DQogICAqICAgICAgICAgaWYgKGUua2V5Q29kZSA9PSAyNykgew0KICAgKiAgICAgICAgICAgJHNjb3BlLm15VmFsdWUgPSAnJzsNCiAgICogICAgICAgICB9DQogICAqICAgICAgIH07DQogICAqICAgICB9XSk7DQogICAqICAgPC9maWxlPg0KICAgKiAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgKiAgICAgPGRpdiBuZy1jb250cm9sbGVyPSJDYW5jZWxVcGRhdGVDb250cm9sbGVyIj4NCiAgICogICAgICAgPHA+VHJ5IHR5cGluZyBzb21ldGhpbmcgaW4gZWFjaCBpbnB1dC4gIFNlZSB0aGF0IHRoZSBtb2RlbCBvbmx5IHVwZGF0ZXMgd2hlbiB5b3UNCiAgICogICAgICAgICAgYmx1ciBvZmYgdGhlIGlucHV0Lg0KICAgKiAgICAgICAgPC9wPg0KICAgKiAgICAgICAgPHA+Tm93IHNlZSB3aGF0IGhhcHBlbnMgaWYgeW91IHN0YXJ0IHR5cGluZyB0aGVuIHByZXNzIHRoZSBFc2NhcGUga2V5PC9wPg0KICAgKg0KICAgKiAgICAgICA8Zm9ybSBuYW1lPSJteUZvcm0iIG5nLW1vZGVsLW9wdGlvbnM9InsgdXBkYXRlT246ICdibHVyJyB9Ij4NCiAgICogICAgICAgICA8cD5XaXRoICRyb2xsYmFja1ZpZXdWYWx1ZSgpPC9wPg0KICAgKiAgICAgICAgIDxpbnB1dCBuYW1lPSJteUlucHV0MSIgbmctbW9kZWw9Im15VmFsdWUiIG5nLWtleWRvd249InJlc2V0V2l0aENhbmNlbCgkZXZlbnQpIj48YnIvPg0KICAgKiAgICAgICAgIG15VmFsdWU6ICJ7eyBteVZhbHVlIH19Ig0KICAgKg0KICAgKiAgICAgICAgIDxwPldpdGhvdXQgJHJvbGxiYWNrVmlld1ZhbHVlKCk8L3A+DQogICAqICAgICAgICAgPGlucHV0IG5hbWU9Im15SW5wdXQyIiBuZy1tb2RlbD0ibXlWYWx1ZSIgbmcta2V5ZG93bj0icmVzZXRXaXRob3V0Q2FuY2VsKCRldmVudCkiPjxici8+DQogICAqICAgICAgICAgbXlWYWx1ZTogInt7IG15VmFsdWUgfX0iDQogICAqICAgICAgIDwvZm9ybT4NCiAgICogICAgIDwvZGl2Pg0KICAgKiAgIDwvZmlsZT4NCiAgICogPC9leGFtcGxlPg0KICAgKi8NCiAgdGhpcy4kcm9sbGJhY2tWaWV3VmFsdWUgPSBmdW5jdGlvbigpIHsNCiAgICAkdGltZW91dC5jYW5jZWwocGVuZGluZ0RlYm91bmNlKTsNCiAgICBjdHJsLiR2aWV3VmFsdWUgPSBjdHJsLiQkbGFzdENvbW1pdHRlZFZpZXdWYWx1ZTsNCiAgICBjdHJsLiRyZW5kZXIoKTsNCiAgfTsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSBuZ01vZGVsLk5nTW9kZWxDb250cm9sbGVyIyR2YWxpZGF0ZQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogUnVucyBlYWNoIG9mIHRoZSByZWdpc3RlcmVkIHZhbGlkYXRvcnMgKGZpcnN0IHN5bmNocm9ub3VzIHZhbGlkYXRvcnMgYW5kIHRoZW4NCiAgICogYXN5bmNocm9ub3VzIHZhbGlkYXRvcnMpLg0KICAgKiBJZiB0aGUgdmFsaWRpdHkgY2hhbmdlcyB0byBpbnZhbGlkLCB0aGUgbW9kZWwgd2lsbCBiZSBzZXQgdG8gYHVuZGVmaW5lZGAsDQogICAqIHVubGVzcyB7QGxpbmsgbmdNb2RlbE9wdGlvbnMgYG5nTW9kZWxPcHRpb25zLmFsbG93SW52YWxpZGB9IGlzIGB0cnVlYC4NCiAgICogSWYgdGhlIHZhbGlkaXR5IGNoYW5nZXMgdG8gdmFsaWQsIGl0IHdpbGwgc2V0IHRoZSBtb2RlbCB0byB0aGUgbGFzdCBhdmFpbGFibGUgdmFsaWQNCiAgICogbW9kZWxWYWx1ZSwgaS5lLiBlaXRoZXIgdGhlIGxhc3QgcGFyc2VkIHZhbHVlIG9yIHRoZSBsYXN0IHZhbHVlIHNldCBmcm9tIHRoZSBzY29wZS4NCiAgICovDQogIHRoaXMuJHZhbGlkYXRlID0gZnVuY3Rpb24oKSB7DQogICAgLy8gaWdub3JlICR2YWxpZGF0ZSBiZWZvcmUgbW9kZWwgaXMgaW5pdGlhbGl6ZWQNCiAgICBpZiAoaXNOdW1iZXIoY3RybC4kbW9kZWxWYWx1ZSkgJiYgaXNOYU4oY3RybC4kbW9kZWxWYWx1ZSkpIHsNCiAgICAgIHJldHVybjsNCiAgICB9DQoNCiAgICB2YXIgdmlld1ZhbHVlID0gY3RybC4kJGxhc3RDb21taXR0ZWRWaWV3VmFsdWU7DQogICAgLy8gTm90ZTogd2UgdXNlIHRoZSAkJHJhd01vZGVsVmFsdWUgYXMgJG1vZGVsVmFsdWUgbWlnaHQgaGF2ZSBiZWVuDQogICAgLy8gc2V0IHRvIHVuZGVmaW5lZCBkdXJpbmcgYSB2aWV3IC0+IG1vZGVsIHVwZGF0ZSB0aGF0IGZvdW5kIHZhbGlkYXRpb24NCiAgICAvLyBlcnJvcnMuIFdlIGNhbid0IHBhcnNlIHRoZSB2aWV3IGhlcmUsIHNpbmNlIHRoYXQgY291bGQgY2hhbmdlDQogICAgLy8gdGhlIG1vZGVsIGFsdGhvdWdoIG5laXRoZXIgdmlld1ZhbHVlIG5vciB0aGUgbW9kZWwgb24gdGhlIHNjb3BlIGNoYW5nZWQNCiAgICB2YXIgbW9kZWxWYWx1ZSA9IGN0cmwuJCRyYXdNb2RlbFZhbHVlOw0KDQogICAgLy8gQ2hlY2sgaWYgdGhlIHRoZXJlJ3MgYSBwYXJzZSBlcnJvciwgc28gd2UgZG9uJ3QgdW5zZXQgaXQgYWNjaWRlbnRpYWxseQ0KICAgIHZhciBwYXJzZXJOYW1lID0gY3RybC4kJHBhcnNlck5hbWUgfHwgJ3BhcnNlJzsNCiAgICB2YXIgcGFyc2VyVmFsaWQgPSBjdHJsLiRlcnJvcltwYXJzZXJOYW1lXSA/IGZhbHNlIDogdW5kZWZpbmVkOw0KDQogICAgdmFyIHByZXZWYWxpZCA9IGN0cmwuJHZhbGlkOw0KICAgIHZhciBwcmV2TW9kZWxWYWx1ZSA9IGN0cmwuJG1vZGVsVmFsdWU7DQoNCiAgICB2YXIgYWxsb3dJbnZhbGlkID0gY3RybC4kb3B0aW9ucyAmJiBjdHJsLiRvcHRpb25zLmFsbG93SW52YWxpZDsNCg0KICAgIGN0cmwuJCRydW5WYWxpZGF0b3JzKHBhcnNlclZhbGlkLCBtb2RlbFZhbHVlLCB2aWV3VmFsdWUsIGZ1bmN0aW9uKGFsbFZhbGlkKSB7DQogICAgICAvLyBJZiB0aGVyZSB3YXMgbm8gY2hhbmdlIGluIHZhbGlkaXR5LCBkb24ndCB1cGRhdGUgdGhlIG1vZGVsDQogICAgICAvLyBUaGlzIHByZXZlbnRzIGNoYW5naW5nIGFuIGludmFsaWQgbW9kZWxWYWx1ZSB0byB1bmRlZmluZWQNCiAgICAgIGlmICghYWxsb3dJbnZhbGlkICYmIHByZXZWYWxpZCAhPT0gYWxsVmFsaWQpIHsNCiAgICAgICAgLy8gTm90ZTogRG9uJ3QgY2hlY2sgY3RybC4kdmFsaWQgaGVyZSwgYXMgd2UgY291bGQgaGF2ZQ0KICAgICAgICAvLyBleHRlcm5hbCB2YWxpZGF0b3JzIChlLmcuIGNhbGN1bGF0ZWQgb24gdGhlIHNlcnZlciksDQogICAgICAgIC8vIHRoYXQganVzdCBjYWxsICRzZXRWYWxpZGl0eSBhbmQgbmVlZCB0aGUgbW9kZWwgdmFsdWUNCiAgICAgICAgLy8gdG8gY2FsY3VsYXRlIHRoZWlyIHZhbGlkaXR5Lg0KICAgICAgICBjdHJsLiRtb2RlbFZhbHVlID0gYWxsVmFsaWQgPyBtb2RlbFZhbHVlIDogdW5kZWZpbmVkOw0KDQogICAgICAgIGlmIChjdHJsLiRtb2RlbFZhbHVlICE9PSBwcmV2TW9kZWxWYWx1ZSkgew0KICAgICAgICAgIGN0cmwuJCR3cml0ZU1vZGVsVG9TY29wZSgpOw0KICAgICAgICB9DQogICAgICB9DQogICAgfSk7DQoNCiAgfTsNCg0KICB0aGlzLiQkcnVuVmFsaWRhdG9ycyA9IGZ1bmN0aW9uKHBhcnNlVmFsaWQsIG1vZGVsVmFsdWUsIHZpZXdWYWx1ZSwgZG9uZUNhbGxiYWNrKSB7DQogICAgY3VycmVudFZhbGlkYXRpb25SdW5JZCsrOw0KICAgIHZhciBsb2NhbFZhbGlkYXRpb25SdW5JZCA9IGN1cnJlbnRWYWxpZGF0aW9uUnVuSWQ7DQoNCiAgICAvLyBjaGVjayBwYXJzZXIgZXJyb3INCiAgICBpZiAoIXByb2Nlc3NQYXJzZUVycm9ycyhwYXJzZVZhbGlkKSkgew0KICAgICAgdmFsaWRhdGlvbkRvbmUoZmFsc2UpOw0KICAgICAgcmV0dXJuOw0KICAgIH0NCiAgICBpZiAoIXByb2Nlc3NTeW5jVmFsaWRhdG9ycygpKSB7DQogICAgICB2YWxpZGF0aW9uRG9uZShmYWxzZSk7DQogICAgICByZXR1cm47DQogICAgfQ0KICAgIHByb2Nlc3NBc3luY1ZhbGlkYXRvcnMoKTsNCg0KICAgIGZ1bmN0aW9uIHByb2Nlc3NQYXJzZUVycm9ycyhwYXJzZVZhbGlkKSB7DQogICAgICB2YXIgZXJyb3JLZXkgPSBjdHJsLiQkcGFyc2VyTmFtZSB8fCAncGFyc2UnOw0KICAgICAgaWYgKHBhcnNlVmFsaWQgPT09IHVuZGVmaW5lZCkgew0KICAgICAgICBzZXRWYWxpZGl0eShlcnJvcktleSwgbnVsbCk7DQogICAgICB9IGVsc2Ugew0KICAgICAgICBzZXRWYWxpZGl0eShlcnJvcktleSwgcGFyc2VWYWxpZCk7DQogICAgICAgIGlmICghcGFyc2VWYWxpZCkgew0KICAgICAgICAgIGZvckVhY2goY3RybC4kdmFsaWRhdG9ycywgZnVuY3Rpb24odiwgbmFtZSkgew0KICAgICAgICAgICAgc2V0VmFsaWRpdHkobmFtZSwgbnVsbCk7DQogICAgICAgICAgfSk7DQogICAgICAgICAgZm9yRWFjaChjdHJsLiRhc3luY1ZhbGlkYXRvcnMsIGZ1bmN0aW9uKHYsIG5hbWUpIHsNCiAgICAgICAgICAgIHNldFZhbGlkaXR5KG5hbWUsIG51bGwpOw0KICAgICAgICAgIH0pOw0KICAgICAgICAgIHJldHVybiBmYWxzZTsNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgcmV0dXJuIHRydWU7DQogICAgfQ0KDQogICAgZnVuY3Rpb24gcHJvY2Vzc1N5bmNWYWxpZGF0b3JzKCkgew0KICAgICAgdmFyIHN5bmNWYWxpZGF0b3JzVmFsaWQgPSB0cnVlOw0KICAgICAgZm9yRWFjaChjdHJsLiR2YWxpZGF0b3JzLCBmdW5jdGlvbih2YWxpZGF0b3IsIG5hbWUpIHsNCiAgICAgICAgdmFyIHJlc3VsdCA9IHZhbGlkYXRvcihtb2RlbFZhbHVlLCB2aWV3VmFsdWUpOw0KICAgICAgICBzeW5jVmFsaWRhdG9yc1ZhbGlkID0gc3luY1ZhbGlkYXRvcnNWYWxpZCAmJiByZXN1bHQ7DQogICAgICAgIHNldFZhbGlkaXR5KG5hbWUsIHJlc3VsdCk7DQogICAgICB9KTsNCiAgICAgIGlmICghc3luY1ZhbGlkYXRvcnNWYWxpZCkgew0KICAgICAgICBmb3JFYWNoKGN0cmwuJGFzeW5jVmFsaWRhdG9ycywgZnVuY3Rpb24odiwgbmFtZSkgew0KICAgICAgICAgIHNldFZhbGlkaXR5KG5hbWUsIG51bGwpOw0KICAgICAgICB9KTsNCiAgICAgICAgcmV0dXJuIGZhbHNlOw0KICAgICAgfQ0KICAgICAgcmV0dXJuIHRydWU7DQogICAgfQ0KDQogICAgZnVuY3Rpb24gcHJvY2Vzc0FzeW5jVmFsaWRhdG9ycygpIHsNCiAgICAgIHZhciB2YWxpZGF0b3JQcm9taXNlcyA9IFtdOw0KICAgICAgdmFyIGFsbFZhbGlkID0gdHJ1ZTsNCiAgICAgIGZvckVhY2goY3RybC4kYXN5bmNWYWxpZGF0b3JzLCBmdW5jdGlvbih2YWxpZGF0b3IsIG5hbWUpIHsNCiAgICAgICAgdmFyIHByb21pc2UgPSB2YWxpZGF0b3IobW9kZWxWYWx1ZSwgdmlld1ZhbHVlKTsNCiAgICAgICAgaWYgKCFpc1Byb21pc2VMaWtlKHByb21pc2UpKSB7DQogICAgICAgICAgdGhyb3cgJG5nTW9kZWxNaW5FcnIoIiRhc3luY1ZhbGlkYXRvcnMiLA0KICAgICAgICAgICAgIkV4cGVjdGVkIGFzeW5jaHJvbm91cyB2YWxpZGF0b3IgdG8gcmV0dXJuIGEgcHJvbWlzZSBidXQgZ290ICd7MH0nIGluc3RlYWQuIiwgcHJvbWlzZSk7DQogICAgICAgIH0NCiAgICAgICAgc2V0VmFsaWRpdHkobmFtZSwgdW5kZWZpbmVkKTsNCiAgICAgICAgdmFsaWRhdG9yUHJvbWlzZXMucHVzaChwcm9taXNlLnRoZW4oZnVuY3Rpb24oKSB7DQogICAgICAgICAgc2V0VmFsaWRpdHkobmFtZSwgdHJ1ZSk7DQogICAgICAgIH0sIGZ1bmN0aW9uKGVycm9yKSB7DQogICAgICAgICAgYWxsVmFsaWQgPSBmYWxzZTsNCiAgICAgICAgICBzZXRWYWxpZGl0eShuYW1lLCBmYWxzZSk7DQogICAgICAgIH0pKTsNCiAgICAgIH0pOw0KICAgICAgaWYgKCF2YWxpZGF0b3JQcm9taXNlcy5sZW5ndGgpIHsNCiAgICAgICAgdmFsaWRhdGlvbkRvbmUodHJ1ZSk7DQogICAgICB9IGVsc2Ugew0KICAgICAgICAkcS5hbGwodmFsaWRhdG9yUHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oKSB7DQogICAgICAgICAgdmFsaWRhdGlvbkRvbmUoYWxsVmFsaWQpOw0KICAgICAgICB9LCBub29wKTsNCiAgICAgIH0NCiAgICB9DQoNCiAgICBmdW5jdGlvbiBzZXRWYWxpZGl0eShuYW1lLCBpc1ZhbGlkKSB7DQogICAgICBpZiAobG9jYWxWYWxpZGF0aW9uUnVuSWQgPT09IGN1cnJlbnRWYWxpZGF0aW9uUnVuSWQpIHsNCiAgICAgICAgY3RybC4kc2V0VmFsaWRpdHkobmFtZSwgaXNWYWxpZCk7DQogICAgICB9DQogICAgfQ0KDQogICAgZnVuY3Rpb24gdmFsaWRhdGlvbkRvbmUoYWxsVmFsaWQpIHsNCiAgICAgIGlmIChsb2NhbFZhbGlkYXRpb25SdW5JZCA9PT0gY3VycmVudFZhbGlkYXRpb25SdW5JZCkgew0KDQogICAgICAgIGRvbmVDYWxsYmFjayhhbGxWYWxpZCk7DQogICAgICB9DQogICAgfQ0KICB9Ow0KDQogIC8qKg0KICAgKiBAbmdkb2MgbWV0aG9kDQogICAqIEBuYW1lIG5nTW9kZWwuTmdNb2RlbENvbnRyb2xsZXIjJGNvbW1pdFZpZXdWYWx1ZQ0KICAgKg0KICAgKiBAZGVzY3JpcHRpb24NCiAgICogQ29tbWl0IGEgcGVuZGluZyB1cGRhdGUgdG8gdGhlIGAkbW9kZWxWYWx1ZWAuDQogICAqDQogICAqIFVwZGF0ZXMgbWF5IGJlIHBlbmRpbmcgYnkgYSBkZWJvdW5jZWQgZXZlbnQgb3IgYmVjYXVzZSB0aGUgaW5wdXQgaXMgd2FpdGluZyBmb3IgYSBzb21lIGZ1dHVyZQ0KICAgKiBldmVudCBkZWZpbmVkIGluIGBuZy1tb2RlbC1vcHRpb25zYC4gdGhpcyBtZXRob2QgaXMgcmFyZWx5IG5lZWRlZCBhcyBgTmdNb2RlbENvbnRyb2xsZXJgDQogICAqIHVzdWFsbHkgaGFuZGxlcyBjYWxsaW5nIHRoaXMgaW4gcmVzcG9uc2UgdG8gaW5wdXQgZXZlbnRzLg0KICAgKi8NCiAgdGhpcy4kY29tbWl0Vmlld1ZhbHVlID0gZnVuY3Rpb24oKSB7DQogICAgdmFyIHZpZXdWYWx1ZSA9IGN0cmwuJHZpZXdWYWx1ZTsNCg0KICAgICR0aW1lb3V0LmNhbmNlbChwZW5kaW5nRGVib3VuY2UpOw0KDQogICAgLy8gSWYgdGhlIHZpZXcgdmFsdWUgaGFzIG5vdCBjaGFuZ2VkIHRoZW4gd2Ugc2hvdWxkIGp1c3QgZXhpdCwgZXhjZXB0IGluIHRoZSBjYXNlIHdoZXJlIHRoZXJlIGlzDQogICAgLy8gYSBuYXRpdmUgdmFsaWRhdG9yIG9uIHRoZSBlbGVtZW50LiBJbiB0aGlzIGNhc2UgdGhlIHZhbGlkYXRpb24gc3RhdGUgbWF5IGhhdmUgY2hhbmdlZCBldmVuIHRob3VnaA0KICAgIC8vIHRoZSB2aWV3VmFsdWUgaGFzIHN0YXllZCBlbXB0eS4NCiAgICBpZiAoY3RybC4kJGxhc3RDb21taXR0ZWRWaWV3VmFsdWUgPT09IHZpZXdWYWx1ZSAmJiAodmlld1ZhbHVlICE9PSAnJyB8fCAhY3RybC4kJGhhc05hdGl2ZVZhbGlkYXRvcnMpKSB7DQogICAgICByZXR1cm47DQogICAgfQ0KICAgIGN0cmwuJCRsYXN0Q29tbWl0dGVkVmlld1ZhbHVlID0gdmlld1ZhbHVlOw0KDQogICAgLy8gY2hhbmdlIHRvIGRpcnR5DQogICAgaWYgKGN0cmwuJHByaXN0aW5lKSB7DQogICAgICB0aGlzLiRzZXREaXJ0eSgpOw0KICAgIH0NCiAgICB0aGlzLiQkcGFyc2VBbmRWYWxpZGF0ZSgpOw0KICB9Ow0KDQogIHRoaXMuJCRwYXJzZUFuZFZhbGlkYXRlID0gZnVuY3Rpb24oKSB7DQogICAgdmFyIHZpZXdWYWx1ZSA9IGN0cmwuJCRsYXN0Q29tbWl0dGVkVmlld1ZhbHVlOw0KICAgIHZhciBtb2RlbFZhbHVlID0gdmlld1ZhbHVlOw0KICAgIHZhciBwYXJzZXJWYWxpZCA9IGlzVW5kZWZpbmVkKG1vZGVsVmFsdWUpID8gdW5kZWZpbmVkIDogdHJ1ZTsNCg0KICAgIGlmIChwYXJzZXJWYWxpZCkgew0KICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjdHJsLiRwYXJzZXJzLmxlbmd0aDsgaSsrKSB7DQogICAgICAgIG1vZGVsVmFsdWUgPSBjdHJsLiRwYXJzZXJzW2ldKG1vZGVsVmFsdWUpOw0KICAgICAgICBpZiAoaXNVbmRlZmluZWQobW9kZWxWYWx1ZSkpIHsNCiAgICAgICAgICBwYXJzZXJWYWxpZCA9IGZhbHNlOw0KICAgICAgICAgIGJyZWFrOw0KICAgICAgICB9DQogICAgICB9DQogICAgfQ0KICAgIGlmIChpc051bWJlcihjdHJsLiRtb2RlbFZhbHVlKSAmJiBpc05hTihjdHJsLiRtb2RlbFZhbHVlKSkgew0KICAgICAgLy8gY3RybC4kbW9kZWxWYWx1ZSBoYXMgbm90IGJlZW4gdG91Y2hlZCB5ZXQuLi4NCiAgICAgIGN0cmwuJG1vZGVsVmFsdWUgPSBuZ01vZGVsR2V0KCRzY29wZSk7DQogICAgfQ0KICAgIHZhciBwcmV2TW9kZWxWYWx1ZSA9IGN0cmwuJG1vZGVsVmFsdWU7DQogICAgdmFyIGFsbG93SW52YWxpZCA9IGN0cmwuJG9wdGlvbnMgJiYgY3RybC4kb3B0aW9ucy5hbGxvd0ludmFsaWQ7DQogICAgY3RybC4kJHJhd01vZGVsVmFsdWUgPSBtb2RlbFZhbHVlOw0KDQogICAgaWYgKGFsbG93SW52YWxpZCkgew0KICAgICAgY3RybC4kbW9kZWxWYWx1ZSA9IG1vZGVsVmFsdWU7DQogICAgICB3cml0ZVRvTW9kZWxJZk5lZWRlZCgpOw0KICAgIH0NCg0KICAgIC8vIFBhc3MgdGhlICQkbGFzdENvbW1pdHRlZFZpZXdWYWx1ZSBoZXJlLCBiZWNhdXNlIHRoZSBjYWNoZWQgdmlld1ZhbHVlIG1pZ2h0IGJlIG91dCBvZiBkYXRlLg0KICAgIC8vIFRoaXMgY2FuIGhhcHBlbiBpZiBlLmcuICRzZXRWaWV3VmFsdWUgaXMgY2FsbGVkIGZyb20gaW5zaWRlIGEgcGFyc2VyDQogICAgY3RybC4kJHJ1blZhbGlkYXRvcnMocGFyc2VyVmFsaWQsIG1vZGVsVmFsdWUsIGN0cmwuJCRsYXN0Q29tbWl0dGVkVmlld1ZhbHVlLCBmdW5jdGlvbihhbGxWYWxpZCkgew0KICAgICAgaWYgKCFhbGxvd0ludmFsaWQpIHsNCiAgICAgICAgLy8gTm90ZTogRG9uJ3QgY2hlY2sgY3RybC4kdmFsaWQgaGVyZSwgYXMgd2UgY291bGQgaGF2ZQ0KICAgICAgICAvLyBleHRlcm5hbCB2YWxpZGF0b3JzIChlLmcuIGNhbGN1bGF0ZWQgb24gdGhlIHNlcnZlciksDQogICAgICAgIC8vIHRoYXQganVzdCBjYWxsICRzZXRWYWxpZGl0eSBhbmQgbmVlZCB0aGUgbW9kZWwgdmFsdWUNCiAgICAgICAgLy8gdG8gY2FsY3VsYXRlIHRoZWlyIHZhbGlkaXR5Lg0KICAgICAgICBjdHJsLiRtb2RlbFZhbHVlID0gYWxsVmFsaWQgPyBtb2RlbFZhbHVlIDogdW5kZWZpbmVkOw0KICAgICAgICB3cml0ZVRvTW9kZWxJZk5lZWRlZCgpOw0KICAgICAgfQ0KICAgIH0pOw0KDQogICAgZnVuY3Rpb24gd3JpdGVUb01vZGVsSWZOZWVkZWQoKSB7DQogICAgICBpZiAoY3RybC4kbW9kZWxWYWx1ZSAhPT0gcHJldk1vZGVsVmFsdWUpIHsNCiAgICAgICAgY3RybC4kJHdyaXRlTW9kZWxUb1Njb3BlKCk7DQogICAgICB9DQogICAgfQ0KICB9Ow0KDQogIHRoaXMuJCR3cml0ZU1vZGVsVG9TY29wZSA9IGZ1bmN0aW9uKCkgew0KICAgIG5nTW9kZWxTZXQoJHNjb3BlLCBjdHJsLiRtb2RlbFZhbHVlKTsNCiAgICBmb3JFYWNoKGN0cmwuJHZpZXdDaGFuZ2VMaXN0ZW5lcnMsIGZ1bmN0aW9uKGxpc3RlbmVyKSB7DQogICAgICB0cnkgew0KICAgICAgICBsaXN0ZW5lcigpOw0KICAgICAgfSBjYXRjaCAoZSkgew0KICAgICAgICAkZXhjZXB0aW9uSGFuZGxlcihlKTsNCiAgICAgIH0NCiAgICB9KTsNCiAgfTsNCg0KICAvKioNCiAgICogQG5nZG9jIG1ldGhvZA0KICAgKiBAbmFtZSBuZ01vZGVsLk5nTW9kZWxDb250cm9sbGVyIyRzZXRWaWV3VmFsdWUNCiAgICoNCiAgICogQGRlc2NyaXB0aW9uDQogICAqIFVwZGF0ZSB0aGUgdmlldyB2YWx1ZS4NCiAgICoNCiAgICogVGhpcyBtZXRob2Qgc2hvdWxkIGJlIGNhbGxlZCB3aGVuIGFuIGlucHV0IGRpcmVjdGl2ZSB3YW50IHRvIGNoYW5nZSB0aGUgdmlldyB2YWx1ZTsgdHlwaWNhbGx5LA0KICAgKiB0aGlzIGlzIGRvbmUgZnJvbSB3aXRoaW4gYSBET00gZXZlbnQgaGFuZGxlci4NCiAgICoNCiAgICogRm9yIGV4YW1wbGUge0BsaW5rIG5nLmRpcmVjdGl2ZTppbnB1dCBpbnB1dH0gY2FsbHMgaXQgd2hlbiB0aGUgdmFsdWUgb2YgdGhlIGlucHV0IGNoYW5nZXMgYW5kDQogICAqIHtAbGluayBuZy5kaXJlY3RpdmU6c2VsZWN0IHNlbGVjdH0gY2FsbHMgaXQgd2hlbiBhbiBvcHRpb24gaXMgc2VsZWN0ZWQuDQogICAqDQogICAqIElmIHRoZSBuZXcgYHZhbHVlYCBpcyBhbiBvYmplY3QgKHJhdGhlciB0aGFuIGEgc3RyaW5nIG9yIGEgbnVtYmVyKSwgd2Ugc2hvdWxkIG1ha2UgYSBjb3B5IG9mIHRoZQ0KICAgKiBvYmplY3QgYmVmb3JlIHBhc3NpbmcgaXQgdG8gYCRzZXRWaWV3VmFsdWVgLiAgVGhpcyBpcyBiZWNhdXNlIGBuZ01vZGVsYCBkb2VzIG5vdCBwZXJmb3JtIGEgZGVlcA0KICAgKiB3YXRjaCBvZiBvYmplY3RzLCBpdCBvbmx5IGxvb2tzIGZvciBhIGNoYW5nZSBvZiBpZGVudGl0eS4gSWYgeW91IG9ubHkgY2hhbmdlIHRoZSBwcm9wZXJ0eSBvZg0KICAgKiB0aGUgb2JqZWN0IHRoZW4gbmdNb2RlbCB3aWxsIG5vdCByZWFsaXNlIHRoYXQgdGhlIG9iamVjdCBoYXMgY2hhbmdlZCBhbmQgd2lsbCBub3QgaW52b2tlIHRoZQ0KICAgKiBgJHBhcnNlcnNgIGFuZCBgJHZhbGlkYXRvcnNgIHBpcGVsaW5lcy4NCiAgICoNCiAgICogRm9yIHRoaXMgcmVhc29uLCB5b3Ugc2hvdWxkIG5vdCBjaGFuZ2UgcHJvcGVydGllcyBvZiB0aGUgY29weSBvbmNlIGl0IGhhcyBiZWVuIHBhc3NlZCB0bw0KICAgKiBgJHNldFZpZXdWYWx1ZWAuIE90aGVyd2lzZSB5b3UgbWF5IGNhdXNlIHRoZSBtb2RlbCB2YWx1ZSBvbiB0aGUgc2NvcGUgdG8gY2hhbmdlIGluY29ycmVjdGx5Lg0KICAgKg0KICAgKiBXaGVuIHRoaXMgbWV0aG9kIGlzIGNhbGxlZCwgdGhlIG5ldyBgdmFsdWVgIHdpbGwgYmUgc3RhZ2VkIGZvciBjb21taXR0aW5nIHRocm91Z2ggdGhlIGAkcGFyc2Vyc2ANCiAgICogYW5kIGAkdmFsaWRhdG9yc2AgcGlwZWxpbmVzLiBJZiB0aGVyZSBhcmUgbm8gc3BlY2lhbCB7QGxpbmsgbmdNb2RlbE9wdGlvbnN9IHNwZWNpZmllZCB0aGVuIHRoZSBzdGFnZWQNCiAgICogdmFsdWUgc2VudCBkaXJlY3RseSBmb3IgcHJvY2Vzc2luZywgZmluYWxseSB0byBiZSBhcHBsaWVkIHRvIGAkbW9kZWxWYWx1ZWAgYW5kIHRoZW4gdGhlDQogICAqICoqZXhwcmVzc2lvbioqIHNwZWNpZmllZCBpbiB0aGUgYG5nLW1vZGVsYCBhdHRyaWJ1dGUuDQogICAqDQogICAqIExhc3RseSwgYWxsIHRoZSByZWdpc3RlcmVkIGNoYW5nZSBsaXN0ZW5lcnMsIGluIHRoZSBgJHZpZXdDaGFuZ2VMaXN0ZW5lcnNgIGxpc3QsIGFyZSBjYWxsZWQuDQogICAqDQogICAqIEluIGNhc2UgdGhlIHtAbGluayBuZy5kaXJlY3RpdmU6bmdNb2RlbE9wdGlvbnMgbmdNb2RlbE9wdGlvbnN9IGRpcmVjdGl2ZSBpcyB1c2VkIHdpdGggYHVwZGF0ZU9uYA0KICAgKiBhbmQgdGhlIGBkZWZhdWx0YCB0cmlnZ2VyIGlzIG5vdCBsaXN0ZWQsIGFsbCB0aG9zZSBhY3Rpb25zIHdpbGwgcmVtYWluIHBlbmRpbmcgdW50aWwgb25lIG9mIHRoZQ0KICAgKiBgdXBkYXRlT25gIGV2ZW50cyBpcyB0cmlnZ2VyZWQgb24gdGhlIERPTSBlbGVtZW50Lg0KICAgKiBBbGwgdGhlc2UgYWN0aW9ucyB3aWxsIGJlIGRlYm91bmNlZCBpZiB0aGUge0BsaW5rIG5nLmRpcmVjdGl2ZTpuZ01vZGVsT3B0aW9ucyBuZ01vZGVsT3B0aW9uc30NCiAgICogZGlyZWN0aXZlIGlzIHVzZWQgd2l0aCBhIGN1c3RvbSBkZWJvdW5jZSBmb3IgdGhpcyBwYXJ0aWN1bGFyIGV2ZW50Lg0KICAgKg0KICAgKiBOb3RlIHRoYXQgY2FsbGluZyB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IHRyaWdnZXIgYSBgJGRpZ2VzdGAuDQogICAqDQogICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSBWYWx1ZSBmcm9tIHRoZSB2aWV3Lg0KICAgKiBAcGFyYW0ge3N0cmluZ30gdHJpZ2dlciBFdmVudCB0aGF0IHRyaWdnZXJlZCB0aGUgdXBkYXRlLg0KICAgKi8NCiAgdGhpcy4kc2V0Vmlld1ZhbHVlID0gZnVuY3Rpb24odmFsdWUsIHRyaWdnZXIpIHsNCiAgICBjdHJsLiR2aWV3VmFsdWUgPSB2YWx1ZTsNCiAgICBpZiAoIWN0cmwuJG9wdGlvbnMgfHwgY3RybC4kb3B0aW9ucy51cGRhdGVPbkRlZmF1bHQpIHsNCiAgICAgIGN0cmwuJCRkZWJvdW5jZVZpZXdWYWx1ZUNvbW1pdCh0cmlnZ2VyKTsNCiAgICB9DQogIH07DQoNCiAgdGhpcy4kJGRlYm91bmNlVmlld1ZhbHVlQ29tbWl0ID0gZnVuY3Rpb24odHJpZ2dlcikgew0KICAgIHZhciBkZWJvdW5jZURlbGF5ID0gMCwNCiAgICAgICAgb3B0aW9ucyA9IGN0cmwuJG9wdGlvbnMsDQogICAgICAgIGRlYm91bmNlOw0KDQogICAgaWYgKG9wdGlvbnMgJiYgaXNEZWZpbmVkKG9wdGlvbnMuZGVib3VuY2UpKSB7DQogICAgICBkZWJvdW5jZSA9IG9wdGlvbnMuZGVib3VuY2U7DQogICAgICBpZiAoaXNOdW1iZXIoZGVib3VuY2UpKSB7DQogICAgICAgIGRlYm91bmNlRGVsYXkgPSBkZWJvdW5jZTsNCiAgICAgIH0gZWxzZSBpZiAoaXNOdW1iZXIoZGVib3VuY2VbdHJpZ2dlcl0pKSB7DQogICAgICAgIGRlYm91bmNlRGVsYXkgPSBkZWJvdW5jZVt0cmlnZ2VyXTsNCiAgICAgIH0gZWxzZSBpZiAoaXNOdW1iZXIoZGVib3VuY2VbJ2RlZmF1bHQnXSkpIHsNCiAgICAgICAgZGVib3VuY2VEZWxheSA9IGRlYm91bmNlWydkZWZhdWx0J107DQogICAgICB9DQogICAgfQ0KDQogICAgJHRpbWVvdXQuY2FuY2VsKHBlbmRpbmdEZWJvdW5jZSk7DQogICAgaWYgKGRlYm91bmNlRGVsYXkpIHsNCiAgICAgIHBlbmRpbmdEZWJvdW5jZSA9ICR0aW1lb3V0KGZ1bmN0aW9uKCkgew0KICAgICAgICBjdHJsLiRjb21taXRWaWV3VmFsdWUoKTsNCiAgICAgIH0sIGRlYm91bmNlRGVsYXkpOw0KICAgIH0gZWxzZSBpZiAoJHJvb3RTY29wZS4kJHBoYXNlKSB7DQogICAgICBjdHJsLiRjb21taXRWaWV3VmFsdWUoKTsNCiAgICB9IGVsc2Ugew0KICAgICAgJHNjb3BlLiRhcHBseShmdW5jdGlvbigpIHsNCiAgICAgICAgY3RybC4kY29tbWl0Vmlld1ZhbHVlKCk7DQogICAgICB9KTsNCiAgICB9DQogIH07DQoNCiAgLy8gbW9kZWwgLT4gdmFsdWUNCiAgLy8gTm90ZTogd2UgY2Fubm90IHVzZSBhIG5vcm1hbCBzY29wZS4kd2F0Y2ggYXMgd2Ugd2FudCB0byBkZXRlY3QgdGhlIGZvbGxvd2luZzoNCiAgLy8gMS4gc2NvcGUgdmFsdWUgaXMgJ2EnDQogIC8vIDIuIHVzZXIgZW50ZXJzICdiJw0KICAvLyAzLiBuZy1jaGFuZ2Uga2lja3MgaW4gYW5kIHJldmVydHMgc2NvcGUgdmFsdWUgdG8gJ2EnDQogIC8vICAgIC0+IHNjb3BlIHZhbHVlIGRpZCBub3QgY2hhbmdlIHNpbmNlIHRoZSBsYXN0IGRpZ2VzdCBhcw0KICAvLyAgICAgICBuZy1jaGFuZ2UgZXhlY3V0ZXMgaW4gYXBwbHkgcGhhc2UNCiAgLy8gNC4gdmlldyBzaG91bGQgYmUgY2hhbmdlZCBiYWNrIHRvICdhJw0KICAkc2NvcGUuJHdhdGNoKGZ1bmN0aW9uIG5nTW9kZWxXYXRjaCgpIHsNCiAgICB2YXIgbW9kZWxWYWx1ZSA9IG5nTW9kZWxHZXQoJHNjb3BlKTsNCg0KICAgIC8vIGlmIHNjb3BlIG1vZGVsIHZhbHVlIGFuZCBuZ01vZGVsIHZhbHVlIGFyZSBvdXQgb2Ygc3luYw0KICAgIC8vIFRPRE8ocGVyZik6IHdoeSBub3QgbW92ZSB0aGlzIHRvIHRoZSBhY3Rpb24gZm4/DQogICAgaWYgKG1vZGVsVmFsdWUgIT09IGN0cmwuJG1vZGVsVmFsdWUpIHsNCiAgICAgIGN0cmwuJG1vZGVsVmFsdWUgPSBjdHJsLiQkcmF3TW9kZWxWYWx1ZSA9IG1vZGVsVmFsdWU7DQoNCiAgICAgIHZhciBmb3JtYXR0ZXJzID0gY3RybC4kZm9ybWF0dGVycywNCiAgICAgICAgICBpZHggPSBmb3JtYXR0ZXJzLmxlbmd0aDsNCg0KICAgICAgdmFyIHZpZXdWYWx1ZSA9IG1vZGVsVmFsdWU7DQogICAgICB3aGlsZSAoaWR4LS0pIHsNCiAgICAgICAgdmlld1ZhbHVlID0gZm9ybWF0dGVyc1tpZHhdKHZpZXdWYWx1ZSk7DQogICAgICB9DQogICAgICBpZiAoY3RybC4kdmlld1ZhbHVlICE9PSB2aWV3VmFsdWUpIHsNCiAgICAgICAgY3RybC4kdmlld1ZhbHVlID0gY3RybC4kJGxhc3RDb21taXR0ZWRWaWV3VmFsdWUgPSB2aWV3VmFsdWU7DQogICAgICAgIGN0cmwuJHJlbmRlcigpOw0KDQogICAgICAgIGN0cmwuJCRydW5WYWxpZGF0b3JzKHVuZGVmaW5lZCwgbW9kZWxWYWx1ZSwgdmlld1ZhbHVlLCBub29wKTsNCiAgICAgIH0NCiAgICB9DQoNCiAgICByZXR1cm4gbW9kZWxWYWx1ZTsNCiAgfSk7DQp9XTsNCg0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nTW9kZWwNCiAqDQogKiBAZWxlbWVudCBpbnB1dA0KICogQHByaW9yaXR5IDENCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFRoZSBgbmdNb2RlbGAgZGlyZWN0aXZlIGJpbmRzIGFuIGBpbnB1dGAsYHNlbGVjdGAsIGB0ZXh0YXJlYWAgKG9yIGN1c3RvbSBmb3JtIGNvbnRyb2wpIHRvIGENCiAqIHByb3BlcnR5IG9uIHRoZSBzY29wZSB1c2luZyB7QGxpbmsgbmdNb2RlbC5OZ01vZGVsQ29udHJvbGxlciBOZ01vZGVsQ29udHJvbGxlcn0sDQogKiB3aGljaCBpcyBjcmVhdGVkIGFuZCBleHBvc2VkIGJ5IHRoaXMgZGlyZWN0aXZlLg0KICoNCiAqIGBuZ01vZGVsYCBpcyByZXNwb25zaWJsZSBmb3I6DQogKg0KICogLSBCaW5kaW5nIHRoZSB2aWV3IGludG8gdGhlIG1vZGVsLCB3aGljaCBvdGhlciBkaXJlY3RpdmVzIHN1Y2ggYXMgYGlucHV0YCwgYHRleHRhcmVhYCBvciBgc2VsZWN0YA0KICogICByZXF1aXJlLg0KICogLSBQcm92aWRpbmcgdmFsaWRhdGlvbiBiZWhhdmlvciAoaS5lLiByZXF1aXJlZCwgbnVtYmVyLCBlbWFpbCwgdXJsKS4NCiAqIC0gS2VlcGluZyB0aGUgc3RhdGUgb2YgdGhlIGNvbnRyb2wgKHZhbGlkL2ludmFsaWQsIGRpcnR5L3ByaXN0aW5lLCB0b3VjaGVkL3VudG91Y2hlZCwgdmFsaWRhdGlvbiBlcnJvcnMpLg0KICogLSBTZXR0aW5nIHJlbGF0ZWQgY3NzIGNsYXNzZXMgb24gdGhlIGVsZW1lbnQgKGBuZy12YWxpZGAsIGBuZy1pbnZhbGlkYCwgYG5nLWRpcnR5YCwgYG5nLXByaXN0aW5lYCwgYG5nLXRvdWNoZWRgLCBgbmctdW50b3VjaGVkYCkgaW5jbHVkaW5nIGFuaW1hdGlvbnMuDQogKiAtIFJlZ2lzdGVyaW5nIHRoZSBjb250cm9sIHdpdGggaXRzIHBhcmVudCB7QGxpbmsgbmcuZGlyZWN0aXZlOmZvcm0gZm9ybX0uDQogKg0KICogTm90ZTogYG5nTW9kZWxgIHdpbGwgdHJ5IHRvIGJpbmQgdG8gdGhlIHByb3BlcnR5IGdpdmVuIGJ5IGV2YWx1YXRpbmcgdGhlIGV4cHJlc3Npb24gb24gdGhlDQogKiBjdXJyZW50IHNjb3BlLiBJZiB0aGUgcHJvcGVydHkgZG9lc24ndCBhbHJlYWR5IGV4aXN0IG9uIHRoaXMgc2NvcGUsIGl0IHdpbGwgYmUgY3JlYXRlZA0KICogaW1wbGljaXRseSBhbmQgYWRkZWQgdG8gdGhlIHNjb3BlLg0KICoNCiAqIEZvciBiZXN0IHByYWN0aWNlcyBvbiB1c2luZyBgbmdNb2RlbGAsIHNlZToNCiAqDQogKiAgLSBbVW5kZXJzdGFuZGluZyBTY29wZXNdKGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIuanMvd2lraS9VbmRlcnN0YW5kaW5nLVNjb3BlcykNCiAqDQogKiBGb3IgYmFzaWMgZXhhbXBsZXMsIGhvdyB0byB1c2UgYG5nTW9kZWxgLCBzZWU6DQogKg0KICogIC0ge0BsaW5rIG5nLmRpcmVjdGl2ZTppbnB1dCBpbnB1dH0NCiAqICAgIC0ge0BsaW5rIGlucHV0W3RleHRdIHRleHR9DQogKiAgICAtIHtAbGluayBpbnB1dFtjaGVja2JveF0gY2hlY2tib3h9DQogKiAgICAtIHtAbGluayBpbnB1dFtyYWRpb10gcmFkaW99DQogKiAgICAtIHtAbGluayBpbnB1dFtudW1iZXJdIG51bWJlcn0NCiAqICAgIC0ge0BsaW5rIGlucHV0W2VtYWlsXSBlbWFpbH0NCiAqICAgIC0ge0BsaW5rIGlucHV0W3VybF0gdXJsfQ0KICogICAgLSB7QGxpbmsgaW5wdXRbZGF0ZV0gZGF0ZX0NCiAqICAgIC0ge0BsaW5rIGlucHV0W2RhdGV0aW1lLWxvY2FsXSBkYXRldGltZS1sb2NhbH0NCiAqICAgIC0ge0BsaW5rIGlucHV0W3RpbWVdIHRpbWV9DQogKiAgICAtIHtAbGluayBpbnB1dFttb250aF0gbW9udGh9DQogKiAgICAtIHtAbGluayBpbnB1dFt3ZWVrXSB3ZWVrfQ0KICogIC0ge0BsaW5rIG5nLmRpcmVjdGl2ZTpzZWxlY3Qgc2VsZWN0fQ0KICogIC0ge0BsaW5rIG5nLmRpcmVjdGl2ZTp0ZXh0YXJlYSB0ZXh0YXJlYX0NCiAqDQogKiAjIENTUyBjbGFzc2VzDQogKiBUaGUgZm9sbG93aW5nIENTUyBjbGFzc2VzIGFyZSBhZGRlZCBhbmQgcmVtb3ZlZCBvbiB0aGUgYXNzb2NpYXRlZCBpbnB1dC9zZWxlY3QvdGV4dGFyZWEgZWxlbWVudA0KICogZGVwZW5kaW5nIG9uIHRoZSB2YWxpZGl0eSBvZiB0aGUgbW9kZWwuDQogKg0KICogIC0gYG5nLXZhbGlkYDogdGhlIG1vZGVsIGlzIHZhbGlkDQogKiAgLSBgbmctaW52YWxpZGA6IHRoZSBtb2RlbCBpcyBpbnZhbGlkDQogKiAgLSBgbmctdmFsaWQtW2tleV1gOiBmb3IgZWFjaCB2YWxpZCBrZXkgYWRkZWQgYnkgYCRzZXRWYWxpZGl0eWANCiAqICAtIGBuZy1pbnZhbGlkLVtrZXldYDogZm9yIGVhY2ggaW52YWxpZCBrZXkgYWRkZWQgYnkgYCRzZXRWYWxpZGl0eWANCiAqICAtIGBuZy1wcmlzdGluZWA6IHRoZSBjb250cm9sIGhhc24ndCBiZWVuIGludGVyYWN0ZWQgd2l0aCB5ZXQNCiAqICAtIGBuZy1kaXJ0eWA6IHRoZSBjb250cm9sIGhhcyBiZWVuIGludGVyYWN0ZWQgd2l0aA0KICogIC0gYG5nLXRvdWNoZWRgOiB0aGUgY29udHJvbCBoYXMgYmVlbiBibHVycmVkDQogKiAgLSBgbmctdW50b3VjaGVkYDogdGhlIGNvbnRyb2wgaGFzbid0IGJlZW4gYmx1cnJlZA0KICogIC0gYG5nLXBlbmRpbmdgOiBhbnkgYCRhc3luY1ZhbGlkYXRvcnNgIGFyZSB1bmZ1bGZpbGxlZA0KICoNCiAqIEtlZXAgaW4gbWluZCB0aGF0IG5nQW5pbWF0ZSBjYW4gZGV0ZWN0IGVhY2ggb2YgdGhlc2UgY2xhc3NlcyB3aGVuIGFkZGVkIGFuZCByZW1vdmVkLg0KICoNCiAqICMjIEFuaW1hdGlvbiBIb29rcw0KICoNCiAqIEFuaW1hdGlvbnMgd2l0aGluIG1vZGVscyBhcmUgdHJpZ2dlcmVkIHdoZW4gYW55IG9mIHRoZSBhc3NvY2lhdGVkIENTUyBjbGFzc2VzIGFyZSBhZGRlZCBhbmQgcmVtb3ZlZA0KICogb24gdGhlIGlucHV0IGVsZW1lbnQgd2hpY2ggaXMgYXR0YWNoZWQgdG8gdGhlIG1vZGVsLiBUaGVzZSBjbGFzc2VzIGFyZTogYC5uZy1wcmlzdGluZWAsIGAubmctZGlydHlgLA0KICogYC5uZy1pbnZhbGlkYCBhbmQgYC5uZy12YWxpZGAgYXMgd2VsbCBhcyBhbnkgb3RoZXIgdmFsaWRhdGlvbnMgdGhhdCBhcmUgcGVyZm9ybWVkIG9uIHRoZSBtb2RlbCBpdHNlbGYuDQogKiBUaGUgYW5pbWF0aW9ucyB0aGF0IGFyZSB0cmlnZ2VyZWQgd2l0aGluIG5nTW9kZWwgYXJlIHNpbWlsYXIgdG8gaG93IHRoZXkgd29yayBpbiBuZ0NsYXNzIGFuZA0KICogYW5pbWF0aW9ucyBjYW4gYmUgaG9va2VkIGludG8gdXNpbmcgQ1NTIHRyYW5zaXRpb25zLCBrZXlmcmFtZXMgYXMgd2VsbCBhcyBKUyBhbmltYXRpb25zLg0KICoNCiAqIFRoZSBmb2xsb3dpbmcgZXhhbXBsZSBzaG93cyBhIHNpbXBsZSB3YXkgdG8gdXRpbGl6ZSBDU1MgdHJhbnNpdGlvbnMgdG8gc3R5bGUgYW4gaW5wdXQgZWxlbWVudA0KICogdGhhdCBoYXMgYmVlbiByZW5kZXJlZCBhcyBpbnZhbGlkIGFmdGVyIGl0IGhhcyBiZWVuIHZhbGlkYXRlZDoNCiAqDQogKiA8cHJlPg0KICogLy9iZSBzdXJlIHRvIGluY2x1ZGUgbmdBbmltYXRlIGFzIGEgbW9kdWxlIHRvIGhvb2sgaW50byBtb3JlDQogKiAvL2FkdmFuY2VkIGFuaW1hdGlvbnMNCiAqIC5teS1pbnB1dCB7DQogKiAgIHRyYW5zaXRpb246MC41cyBsaW5lYXIgYWxsOw0KICogICBiYWNrZ3JvdW5kOiB3aGl0ZTsNCiAqIH0NCiAqIC5teS1pbnB1dC5uZy1pbnZhbGlkIHsNCiAqICAgYmFja2dyb3VuZDogcmVkOw0KICogICBjb2xvcjp3aGl0ZTsNCiAqIH0NCiAqIDwvcHJlPg0KICoNCiAqIEBleGFtcGxlDQogKiA8ZXhhbXBsZSBkZXBzPSJhbmd1bGFyLWFuaW1hdGUuanMiIGFuaW1hdGlvbnM9InRydWUiIGZpeEJhc2U9InRydWUiIG1vZHVsZT0iaW5wdXRFeGFtcGxlIj4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPHNjcmlwdD4NCiAgICAgICAgYW5ndWxhci5tb2R1bGUoJ2lucHV0RXhhbXBsZScsIFtdKQ0KICAgICAgICAgIC5jb250cm9sbGVyKCdFeGFtcGxlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgICAgICAkc2NvcGUudmFsID0gJzEnOw0KICAgICAgICAgIH1dKTsNCiAgICAgICA8L3NjcmlwdD4NCiAgICAgICA8c3R5bGU+DQogICAgICAgICAubXktaW5wdXQgew0KICAgICAgICAgICAtd2Via2l0LXRyYW5zaXRpb246YWxsIGxpbmVhciAwLjVzOw0KICAgICAgICAgICB0cmFuc2l0aW9uOmFsbCBsaW5lYXIgMC41czsNCiAgICAgICAgICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7DQogICAgICAgICB9DQogICAgICAgICAubXktaW5wdXQubmctaW52YWxpZCB7DQogICAgICAgICAgIGNvbG9yOndoaXRlOw0KICAgICAgICAgICBiYWNrZ3JvdW5kOiByZWQ7DQogICAgICAgICB9DQogICAgICAgPC9zdHlsZT4NCiAgICAgICBVcGRhdGUgaW5wdXQgdG8gc2VlIHRyYW5zaXRpb25zIHdoZW4gdmFsaWQvaW52YWxpZC4NCiAgICAgICBJbnRlZ2VyIGlzIGEgdmFsaWQgdmFsdWUuDQogICAgICAgPGZvcm0gbmFtZT0idGVzdEZvcm0iIG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICAgIDxpbnB1dCBuZy1tb2RlbD0idmFsIiBuZy1wYXR0ZXJuPSIvXlxkKyQvIiBuYW1lPSJhbmltIiBjbGFzcz0ibXktaW5wdXQiIC8+DQogICAgICAgPC9mb3JtPg0KICAgICA8L2ZpbGU+DQogKiA8L2V4YW1wbGU+DQogKg0KICogIyMgQmluZGluZyB0byBhIGdldHRlci9zZXR0ZXINCiAqDQogKiBTb21ldGltZXMgaXQncyBoZWxwZnVsIHRvIGJpbmQgYG5nTW9kZWxgIHRvIGEgZ2V0dGVyL3NldHRlciBmdW5jdGlvbi4gIEEgZ2V0dGVyL3NldHRlciBpcyBhDQogKiBmdW5jdGlvbiB0aGF0IHJldHVybnMgYSByZXByZXNlbnRhdGlvbiBvZiB0aGUgbW9kZWwgd2hlbiBjYWxsZWQgd2l0aCB6ZXJvIGFyZ3VtZW50cywgYW5kIHNldHMNCiAqIHRoZSBpbnRlcm5hbCBzdGF0ZSBvZiBhIG1vZGVsIHdoZW4gY2FsbGVkIHdpdGggYW4gYXJndW1lbnQuIEl0J3Mgc29tZXRpbWVzIHVzZWZ1bCB0byB1c2UgdGhpcw0KICogZm9yIG1vZGVscyB0aGF0IGhhdmUgYW4gaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gdGhhdCdzIGRpZmZlcmVudCB0aGFuIHdoYXQgdGhlIG1vZGVsIGV4cG9zZXMNCiAqIHRvIHRoZSB2aWV3Lg0KICoNCiAqIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXN1Y2Nlc3MiPg0KICogKipCZXN0IFByYWN0aWNlOioqIEl0J3MgYmVzdCB0byBrZWVwIGdldHRlcnMgZmFzdCBiZWNhdXNlIEFuZ3VsYXIgaXMgbGlrZWx5IHRvIGNhbGwgdGhlbSBtb3JlDQogKiBmcmVxdWVudGx5IHRoYW4gb3RoZXIgcGFydHMgb2YgeW91ciBjb2RlLg0KICogPC9kaXY+DQogKg0KICogWW91IHVzZSB0aGlzIGJlaGF2aW9yIGJ5IGFkZGluZyBgbmctbW9kZWwtb3B0aW9ucz0ieyBnZXR0ZXJTZXR0ZXI6IHRydWUgfSJgIHRvIGFuIGVsZW1lbnQgdGhhdA0KICogaGFzIGBuZy1tb2RlbGAgYXR0YWNoZWQgdG8gaXQuIFlvdSBjYW4gYWxzbyBhZGQgYG5nLW1vZGVsLW9wdGlvbnM9InsgZ2V0dGVyU2V0dGVyOiB0cnVlIH0iYCB0bw0KICogYSBgPGZvcm0+YCwgd2hpY2ggd2lsbCBlbmFibGUgdGhpcyBiZWhhdmlvciBmb3IgYWxsIGA8aW5wdXQ+YHMgd2l0aGluIGl0LiBTZWUNCiAqIHtAbGluayBuZy5kaXJlY3RpdmU6bmdNb2RlbE9wdGlvbnMgYG5nTW9kZWxPcHRpb25zYH0gZm9yIG1vcmUuDQogKg0KICogVGhlIGZvbGxvd2luZyBleGFtcGxlIHNob3dzIGhvdyB0byB1c2UgYG5nTW9kZWxgIHdpdGggYSBnZXR0ZXIvc2V0dGVyOg0KICoNCiAqIEBleGFtcGxlDQogKiA8ZXhhbXBsZSBuYW1lPSJuZ01vZGVsLWdldHRlci1zZXR0ZXIiIG1vZHVsZT0iZ2V0dGVyU2V0dGVyRXhhbXBsZSI+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICAgICAgPGZvcm0gbmFtZT0idXNlckZvcm0iPg0KICAgICAgICAgICBOYW1lOg0KICAgICAgICAgICA8aW5wdXQgdHlwZT0idGV4dCIgbmFtZT0idXNlck5hbWUiDQogICAgICAgICAgICAgICAgICBuZy1tb2RlbD0idXNlci5uYW1lIg0KICAgICAgICAgICAgICAgICAgbmctbW9kZWwtb3B0aW9ucz0ieyBnZXR0ZXJTZXR0ZXI6IHRydWUgfSIgLz4NCiAgICAgICAgIDwvZm9ybT4NCiAgICAgICAgIDxwcmU+dXNlci5uYW1lID0gPHNwYW4gbmctYmluZD0idXNlci5uYW1lKCkiPjwvc3Bhbj48L3ByZT4NCiAgICAgICA8L2Rpdj4NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJhcHAuanMiPg0KICAgICAgIGFuZ3VsYXIubW9kdWxlKCdnZXR0ZXJTZXR0ZXJFeGFtcGxlJywgW10pDQogICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICB2YXIgX25hbWUgPSAnQnJpYW4nOw0KICAgICAgICAgICAkc2NvcGUudXNlciA9IHsNCiAgICAgICAgICAgICBuYW1lOiBmdW5jdGlvbihuZXdOYW1lKSB7DQogICAgICAgICAgICAgICBpZiAoYW5ndWxhci5pc0RlZmluZWQobmV3TmFtZSkpIHsNCiAgICAgICAgICAgICAgICAgX25hbWUgPSBuZXdOYW1lOw0KICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgcmV0dXJuIF9uYW1lOw0KICAgICAgICAgICAgIH0NCiAgICAgICAgICAgfTsNCiAgICAgICAgIH1dKTsNCiAgICAgPC9maWxlPg0KICogPC9leGFtcGxlPg0KICovDQp2YXIgbmdNb2RlbERpcmVjdGl2ZSA9IFsnJHJvb3RTY29wZScsIGZ1bmN0aW9uKCRyb290U2NvcGUpIHsNCiAgcmV0dXJuIHsNCiAgICByZXN0cmljdDogJ0EnLA0KICAgIHJlcXVpcmU6IFsnbmdNb2RlbCcsICdeP2Zvcm0nLCAnXj9uZ01vZGVsT3B0aW9ucyddLA0KICAgIGNvbnRyb2xsZXI6IE5nTW9kZWxDb250cm9sbGVyLA0KICAgIC8vIFByZWxpbmsgbmVlZHMgdG8gcnVuIGJlZm9yZSBhbnkgaW5wdXQgZGlyZWN0aXZlDQogICAgLy8gc28gdGhhdCB3ZSBjYW4gc2V0IHRoZSBOZ01vZGVsT3B0aW9ucyBpbiBOZ01vZGVsQ29udHJvbGxlcg0KICAgIC8vIGJlZm9yZSBhbnlvbmUgZWxzZSB1c2VzIGl0Lg0KICAgIHByaW9yaXR5OiAxLA0KICAgIGNvbXBpbGU6IGZ1bmN0aW9uIG5nTW9kZWxDb21waWxlKGVsZW1lbnQpIHsNCiAgICAgIC8vIFNldHVwIGluaXRpYWwgc3RhdGUgb2YgdGhlIGNvbnRyb2wNCiAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoUFJJU1RJTkVfQ0xBU1MpLmFkZENsYXNzKFVOVE9VQ0hFRF9DTEFTUykuYWRkQ2xhc3MoVkFMSURfQ0xBU1MpOw0KDQogICAgICByZXR1cm4gew0KICAgICAgICBwcmU6IGZ1bmN0aW9uIG5nTW9kZWxQcmVMaW5rKHNjb3BlLCBlbGVtZW50LCBhdHRyLCBjdHJscykgew0KICAgICAgICAgIHZhciBtb2RlbEN0cmwgPSBjdHJsc1swXSwNCiAgICAgICAgICAgICAgZm9ybUN0cmwgPSBjdHJsc1sxXSB8fCBudWxsRm9ybUN0cmw7DQoNCiAgICAgICAgICBtb2RlbEN0cmwuJCRzZXRPcHRpb25zKGN0cmxzWzJdICYmIGN0cmxzWzJdLiRvcHRpb25zKTsNCg0KICAgICAgICAgIC8vIG5vdGlmeSBvdGhlcnMsIGVzcGVjaWFsbHkgcGFyZW50IGZvcm1zDQogICAgICAgICAgZm9ybUN0cmwuJGFkZENvbnRyb2wobW9kZWxDdHJsKTsNCg0KICAgICAgICAgIGF0dHIuJG9ic2VydmUoJ25hbWUnLCBmdW5jdGlvbihuZXdWYWx1ZSkgew0KICAgICAgICAgICAgaWYgKG1vZGVsQ3RybC4kbmFtZSAhPT0gbmV3VmFsdWUpIHsNCiAgICAgICAgICAgICAgZm9ybUN0cmwuJCRyZW5hbWVDb250cm9sKG1vZGVsQ3RybCwgbmV3VmFsdWUpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0pOw0KDQogICAgICAgICAgc2NvcGUuJG9uKCckZGVzdHJveScsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgZm9ybUN0cmwuJHJlbW92ZUNvbnRyb2wobW9kZWxDdHJsKTsNCiAgICAgICAgICB9KTsNCiAgICAgICAgfSwNCiAgICAgICAgcG9zdDogZnVuY3Rpb24gbmdNb2RlbFBvc3RMaW5rKHNjb3BlLCBlbGVtZW50LCBhdHRyLCBjdHJscykgew0KICAgICAgICAgIHZhciBtb2RlbEN0cmwgPSBjdHJsc1swXTsNCiAgICAgICAgICBpZiAobW9kZWxDdHJsLiRvcHRpb25zICYmIG1vZGVsQ3RybC4kb3B0aW9ucy51cGRhdGVPbikgew0KICAgICAgICAgICAgZWxlbWVudC5vbihtb2RlbEN0cmwuJG9wdGlvbnMudXBkYXRlT24sIGZ1bmN0aW9uKGV2KSB7DQogICAgICAgICAgICAgIG1vZGVsQ3RybC4kJGRlYm91bmNlVmlld1ZhbHVlQ29tbWl0KGV2ICYmIGV2LnR5cGUpOw0KICAgICAgICAgICAgfSk7DQogICAgICAgICAgfQ0KDQogICAgICAgICAgZWxlbWVudC5vbignYmx1cicsIGZ1bmN0aW9uKGV2KSB7DQogICAgICAgICAgICBpZiAobW9kZWxDdHJsLiR0b3VjaGVkKSByZXR1cm47DQoNCiAgICAgICAgICAgIGlmICgkcm9vdFNjb3BlLiQkcGhhc2UpIHsNCiAgICAgICAgICAgICAgc2NvcGUuJGV2YWxBc3luYyhtb2RlbEN0cmwuJHNldFRvdWNoZWQpOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgc2NvcGUuJGFwcGx5KG1vZGVsQ3RybC4kc2V0VG91Y2hlZCk7DQogICAgICAgICAgICB9DQogICAgICAgICAgfSk7DQogICAgICAgIH0NCiAgICAgIH07DQogICAgfQ0KICB9Ow0KfV07DQoNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0NoYW5nZQ0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogRXZhbHVhdGUgdGhlIGdpdmVuIGV4cHJlc3Npb24gd2hlbiB0aGUgdXNlciBjaGFuZ2VzIHRoZSBpbnB1dC4NCiAqIFRoZSBleHByZXNzaW9uIGlzIGV2YWx1YXRlZCBpbW1lZGlhdGVseSwgdW5saWtlIHRoZSBKYXZhU2NyaXB0IG9uY2hhbmdlIGV2ZW50DQogKiB3aGljaCBvbmx5IHRyaWdnZXJzIGF0IHRoZSBlbmQgb2YgYSBjaGFuZ2UgKHVzdWFsbHksIHdoZW4gdGhlIHVzZXIgbGVhdmVzIHRoZQ0KICogZm9ybSBlbGVtZW50IG9yIHByZXNzZXMgdGhlIHJldHVybiBrZXkpLg0KICoNCiAqIFRoZSBgbmdDaGFuZ2VgIGV4cHJlc3Npb24gaXMgb25seSBldmFsdWF0ZWQgd2hlbiBhIGNoYW5nZSBpbiB0aGUgaW5wdXQgdmFsdWUgY2F1c2VzDQogKiBhIG5ldyB2YWx1ZSB0byBiZSBjb21taXR0ZWQgdG8gdGhlIG1vZGVsLg0KICoNCiAqIEl0IHdpbGwgbm90IGJlIGV2YWx1YXRlZDoNCiAqICogaWYgdGhlIHZhbHVlIHJldHVybmVkIGZyb20gdGhlIGAkcGFyc2Vyc2AgdHJhbnNmb3JtYXRpb24gcGlwZWxpbmUgaGFzIG5vdCBjaGFuZ2VkDQogKiAqIGlmIHRoZSBpbnB1dCBoYXMgY29udGludWVkIHRvIGJlIGludmFsaWQgc2luY2UgdGhlIG1vZGVsIHdpbGwgc3RheSBgbnVsbGANCiAqICogaWYgdGhlIG1vZGVsIGlzIGNoYW5nZWQgcHJvZ3JhbW1hdGljYWxseSBhbmQgbm90IGJ5IGEgY2hhbmdlIHRvIHRoZSBpbnB1dCB2YWx1ZQ0KICoNCiAqDQogKiBOb3RlLCB0aGlzIGRpcmVjdGl2ZSByZXF1aXJlcyBgbmdNb2RlbGAgdG8gYmUgcHJlc2VudC4NCiAqDQogKiBAZWxlbWVudCBpbnB1dA0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ0NoYW5nZSB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBFeHByZXNzaW9ufSB0byBldmFsdWF0ZSB1cG9uIGNoYW5nZQ0KICogaW4gaW5wdXQgdmFsdWUuDQogKg0KICogQGV4YW1wbGUNCiAqIDxleGFtcGxlIG5hbWU9Im5nQ2hhbmdlLWRpcmVjdGl2ZSIgbW9kdWxlPSJjaGFuZ2VFeGFtcGxlIj4NCiAqICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogKiAgICAgPHNjcmlwdD4NCiAqICAgICAgIGFuZ3VsYXIubW9kdWxlKCdjaGFuZ2VFeGFtcGxlJywgW10pDQogKiAgICAgICAgIC5jb250cm9sbGVyKCdFeGFtcGxlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogKiAgICAgICAgICAgJHNjb3BlLmNvdW50ZXIgPSAwOw0KICogICAgICAgICAgICRzY29wZS5jaGFuZ2UgPSBmdW5jdGlvbigpIHsNCiAqICAgICAgICAgICAgICRzY29wZS5jb3VudGVyKys7DQogKiAgICAgICAgICAgfTsNCiAqICAgICAgICAgfV0pOw0KICogICAgIDwvc2NyaXB0Pg0KICogICAgIDxkaXYgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICogICAgICAgPGlucHV0IHR5cGU9ImNoZWNrYm94IiBuZy1tb2RlbD0iY29uZmlybWVkIiBuZy1jaGFuZ2U9ImNoYW5nZSgpIiBpZD0ibmctY2hhbmdlLWV4YW1wbGUxIiAvPg0KICogICAgICAgPGlucHV0IHR5cGU9ImNoZWNrYm94IiBuZy1tb2RlbD0iY29uZmlybWVkIiBpZD0ibmctY2hhbmdlLWV4YW1wbGUyIiAvPg0KICogICAgICAgPGxhYmVsIGZvcj0ibmctY2hhbmdlLWV4YW1wbGUyIj5Db25maXJtZWQ8L2xhYmVsPjxiciAvPg0KICogICAgICAgPHR0PmRlYnVnID0ge3tjb25maXJtZWR9fTwvdHQ+PGJyLz4NCiAqICAgICAgIDx0dD5jb3VudGVyID0ge3tjb3VudGVyfX08L3R0Pjxici8+DQogKiAgICAgPC9kaXY+DQogKiAgIDwvZmlsZT4NCiAqICAgPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogKiAgICAgdmFyIGNvdW50ZXIgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ2NvdW50ZXInKSk7DQogKiAgICAgdmFyIGRlYnVnID0gZWxlbWVudChieS5iaW5kaW5nKCdjb25maXJtZWQnKSk7DQogKg0KICogICAgIGl0KCdzaG91bGQgZXZhbHVhdGUgdGhlIGV4cHJlc3Npb24gaWYgY2hhbmdpbmcgZnJvbSB2aWV3JywgZnVuY3Rpb24oKSB7DQogKiAgICAgICBleHBlY3QoY291bnRlci5nZXRUZXh0KCkpLnRvQ29udGFpbignMCcpOw0KICoNCiAqICAgICAgIGVsZW1lbnQoYnkuaWQoJ25nLWNoYW5nZS1leGFtcGxlMScpKS5jbGljaygpOw0KICoNCiAqICAgICAgIGV4cGVjdChjb3VudGVyLmdldFRleHQoKSkudG9Db250YWluKCcxJyk7DQogKiAgICAgICBleHBlY3QoZGVidWcuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ3RydWUnKTsNCiAqICAgICB9KTsNCiAqDQogKiAgICAgaXQoJ3Nob3VsZCBub3QgZXZhbHVhdGUgdGhlIGV4cHJlc3Npb24gaWYgY2hhbmdpbmcgZnJvbSBtb2RlbCcsIGZ1bmN0aW9uKCkgew0KICogICAgICAgZWxlbWVudChieS5pZCgnbmctY2hhbmdlLWV4YW1wbGUyJykpLmNsaWNrKCk7DQoNCiAqICAgICAgIGV4cGVjdChjb3VudGVyLmdldFRleHQoKSkudG9Db250YWluKCcwJyk7DQogKiAgICAgICBleHBlY3QoZGVidWcuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ3RydWUnKTsNCiAqICAgICB9KTsNCiAqICAgPC9maWxlPg0KICogPC9leGFtcGxlPg0KICovDQp2YXIgbmdDaGFuZ2VEaXJlY3RpdmUgPSB2YWx1ZUZuKHsNCiAgcmVzdHJpY3Q6ICdBJywNCiAgcmVxdWlyZTogJ25nTW9kZWwnLA0KICBsaW5rOiBmdW5jdGlvbihzY29wZSwgZWxlbWVudCwgYXR0ciwgY3RybCkgew0KICAgIGN0cmwuJHZpZXdDaGFuZ2VMaXN0ZW5lcnMucHVzaChmdW5jdGlvbigpIHsNCiAgICAgIHNjb3BlLiRldmFsKGF0dHIubmdDaGFuZ2UpOw0KICAgIH0pOw0KICB9DQp9KTsNCg0KDQp2YXIgcmVxdWlyZWREaXJlY3RpdmUgPSBmdW5jdGlvbigpIHsNCiAgcmV0dXJuIHsNCiAgICByZXN0cmljdDogJ0EnLA0KICAgIHJlcXVpcmU6ICc/bmdNb2RlbCcsDQogICAgbGluazogZnVuY3Rpb24oc2NvcGUsIGVsbSwgYXR0ciwgY3RybCkgew0KICAgICAgaWYgKCFjdHJsKSByZXR1cm47DQogICAgICBhdHRyLnJlcXVpcmVkID0gdHJ1ZTsgLy8gZm9yY2UgdHJ1dGh5IGluIGNhc2Ugd2UgYXJlIG9uIG5vbiBpbnB1dCBlbGVtZW50DQoNCiAgICAgIGN0cmwuJHZhbGlkYXRvcnMucmVxdWlyZWQgPSBmdW5jdGlvbihtb2RlbFZhbHVlLCB2aWV3VmFsdWUpIHsNCiAgICAgICAgcmV0dXJuICFhdHRyLnJlcXVpcmVkIHx8ICFjdHJsLiRpc0VtcHR5KHZpZXdWYWx1ZSk7DQogICAgICB9Ow0KDQogICAgICBhdHRyLiRvYnNlcnZlKCdyZXF1aXJlZCcsIGZ1bmN0aW9uKCkgew0KICAgICAgICBjdHJsLiR2YWxpZGF0ZSgpOw0KICAgICAgfSk7DQogICAgfQ0KICB9Ow0KfTsNCg0KDQp2YXIgcGF0dGVybkRpcmVjdGl2ZSA9IGZ1bmN0aW9uKCkgew0KICByZXR1cm4gew0KICAgIHJlc3RyaWN0OiAnQScsDQogICAgcmVxdWlyZTogJz9uZ01vZGVsJywNCiAgICBsaW5rOiBmdW5jdGlvbihzY29wZSwgZWxtLCBhdHRyLCBjdHJsKSB7DQogICAgICBpZiAoIWN0cmwpIHJldHVybjsNCg0KICAgICAgdmFyIHJlZ2V4cCwgcGF0dGVybkV4cCA9IGF0dHIubmdQYXR0ZXJuIHx8IGF0dHIucGF0dGVybjsNCiAgICAgIGF0dHIuJG9ic2VydmUoJ3BhdHRlcm4nLCBmdW5jdGlvbihyZWdleCkgew0KICAgICAgICBpZiAoaXNTdHJpbmcocmVnZXgpICYmIHJlZ2V4Lmxlbmd0aCA+IDApIHsNCiAgICAgICAgICByZWdleCA9IG5ldyBSZWdFeHAoJ14nICsgcmVnZXggKyAnJCcpOw0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKHJlZ2V4ICYmICFyZWdleC50ZXN0KSB7DQogICAgICAgICAgdGhyb3cgbWluRXJyKCduZ1BhdHRlcm4nKSgnbm9yZWdleHAnLA0KICAgICAgICAgICAgJ0V4cGVjdGVkIHswfSB0byBiZSBhIFJlZ0V4cCBidXQgd2FzIHsxfS4gRWxlbWVudDogezJ9JywgcGF0dGVybkV4cCwNCiAgICAgICAgICAgIHJlZ2V4LCBzdGFydGluZ1RhZyhlbG0pKTsNCiAgICAgICAgfQ0KDQogICAgICAgIHJlZ2V4cCA9IHJlZ2V4IHx8IHVuZGVmaW5lZDsNCiAgICAgICAgY3RybC4kdmFsaWRhdGUoKTsNCiAgICAgIH0pOw0KDQogICAgICBjdHJsLiR2YWxpZGF0b3JzLnBhdHRlcm4gPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICByZXR1cm4gY3RybC4kaXNFbXB0eSh2YWx1ZSkgfHwgaXNVbmRlZmluZWQocmVnZXhwKSB8fCByZWdleHAudGVzdCh2YWx1ZSk7DQogICAgICB9Ow0KICAgIH0NCiAgfTsNCn07DQoNCg0KdmFyIG1heGxlbmd0aERpcmVjdGl2ZSA9IGZ1bmN0aW9uKCkgew0KICByZXR1cm4gew0KICAgIHJlc3RyaWN0OiAnQScsDQogICAgcmVxdWlyZTogJz9uZ01vZGVsJywNCiAgICBsaW5rOiBmdW5jdGlvbihzY29wZSwgZWxtLCBhdHRyLCBjdHJsKSB7DQogICAgICBpZiAoIWN0cmwpIHJldHVybjsNCg0KICAgICAgdmFyIG1heGxlbmd0aCA9IC0xOw0KICAgICAgYXR0ci4kb2JzZXJ2ZSgnbWF4bGVuZ3RoJywgZnVuY3Rpb24odmFsdWUpIHsNCiAgICAgICAgdmFyIGludFZhbCA9IGludCh2YWx1ZSk7DQogICAgICAgIG1heGxlbmd0aCA9IGlzTmFOKGludFZhbCkgPyAtMSA6IGludFZhbDsNCiAgICAgICAgY3RybC4kdmFsaWRhdGUoKTsNCiAgICAgIH0pOw0KICAgICAgY3RybC4kdmFsaWRhdG9ycy5tYXhsZW5ndGggPSBmdW5jdGlvbihtb2RlbFZhbHVlLCB2aWV3VmFsdWUpIHsNCiAgICAgICAgcmV0dXJuIChtYXhsZW5ndGggPCAwKSB8fCBjdHJsLiRpc0VtcHR5KG1vZGVsVmFsdWUpIHx8ICh2aWV3VmFsdWUubGVuZ3RoIDw9IG1heGxlbmd0aCk7DQogICAgICB9Ow0KICAgIH0NCiAgfTsNCn07DQoNCnZhciBtaW5sZW5ndGhEaXJlY3RpdmUgPSBmdW5jdGlvbigpIHsNCiAgcmV0dXJuIHsNCiAgICByZXN0cmljdDogJ0EnLA0KICAgIHJlcXVpcmU6ICc/bmdNb2RlbCcsDQogICAgbGluazogZnVuY3Rpb24oc2NvcGUsIGVsbSwgYXR0ciwgY3RybCkgew0KICAgICAgaWYgKCFjdHJsKSByZXR1cm47DQoNCiAgICAgIHZhciBtaW5sZW5ndGggPSAwOw0KICAgICAgYXR0ci4kb2JzZXJ2ZSgnbWlubGVuZ3RoJywgZnVuY3Rpb24odmFsdWUpIHsNCiAgICAgICAgbWlubGVuZ3RoID0gaW50KHZhbHVlKSB8fCAwOw0KICAgICAgICBjdHJsLiR2YWxpZGF0ZSgpOw0KICAgICAgfSk7DQogICAgICBjdHJsLiR2YWxpZGF0b3JzLm1pbmxlbmd0aCA9IGZ1bmN0aW9uKG1vZGVsVmFsdWUsIHZpZXdWYWx1ZSkgew0KICAgICAgICByZXR1cm4gY3RybC4kaXNFbXB0eSh2aWV3VmFsdWUpIHx8IHZpZXdWYWx1ZS5sZW5ndGggPj0gbWlubGVuZ3RoOw0KICAgICAgfTsNCiAgICB9DQogIH07DQp9Ow0KDQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdMaXN0DQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBUZXh0IGlucHV0IHRoYXQgY29udmVydHMgYmV0d2VlbiBhIGRlbGltaXRlZCBzdHJpbmcgYW5kIGFuIGFycmF5IG9mIHN0cmluZ3MuIFRoZSBkZWZhdWx0DQogKiBkZWxpbWl0ZXIgaXMgYSBjb21tYSBmb2xsb3dlZCBieSBhIHNwYWNlIC0gZXF1aXZhbGVudCB0byBgbmctbGlzdD0iLCAiYC4gWW91IGNhbiBzcGVjaWZ5IGEgY3VzdG9tDQogKiBkZWxpbWl0ZXIgYXMgdGhlIHZhbHVlIG9mIHRoZSBgbmdMaXN0YCBhdHRyaWJ1dGUgLSBmb3IgZXhhbXBsZSwgYG5nLWxpc3Q9IiB8ICJgLg0KICoNCiAqIFRoZSBiZWhhdmlvdXIgb2YgdGhlIGRpcmVjdGl2ZSBpcyBhZmZlY3RlZCBieSB0aGUgdXNlIG9mIHRoZSBgbmdUcmltYCBhdHRyaWJ1dGUuDQogKiAqIElmIGBuZ1RyaW1gIGlzIHNldCB0byBgImZhbHNlImAgdGhlbiB3aGl0ZXNwYWNlIGFyb3VuZCBib3RoIHRoZSBzZXBhcmF0b3IgYW5kIGVhY2gNCiAqICAgbGlzdCBpdGVtIGlzIHJlc3BlY3RlZC4gVGhpcyBpbXBsaWVzIHRoYXQgdGhlIHVzZXIgb2YgdGhlIGRpcmVjdGl2ZSBpcyByZXNwb25zaWJsZSBmb3INCiAqICAgZGVhbGluZyB3aXRoIHdoaXRlc3BhY2UgYnV0IGFsc28gYWxsb3dzIHlvdSB0byB1c2Ugd2hpdGVzcGFjZSBhcyBhIGRlbGltaXRlciwgc3VjaCBhcyBhDQogKiAgIHRhYiBvciBuZXdsaW5lIGNoYXJhY3Rlci4NCiAqICogT3RoZXJ3aXNlIHdoaXRlc3BhY2UgYXJvdW5kIHRoZSBkZWxpbWl0ZXIgaXMgaWdub3JlZCB3aGVuIHNwbGl0dGluZyAoYWx0aG91Z2ggaXQgaXMgcmVzcGVjdGVkDQogKiAgIHdoZW4gam9pbmluZyB0aGUgbGlzdCBpdGVtcyBiYWNrIHRvZ2V0aGVyKSBhbmQgd2hpdGVzcGFjZSBhcm91bmQgZWFjaCBsaXN0IGl0ZW0gaXMgc3RyaXBwZWQNCiAqICAgYmVmb3JlIGl0IGlzIGFkZGVkIHRvIHRoZSBtb2RlbC4NCiAqDQogKiAjIyMgRXhhbXBsZSB3aXRoIFZhbGlkYXRpb24NCiAqDQogKiA8ZXhhbXBsZSBuYW1lPSJuZ0xpc3QtZGlyZWN0aXZlIiBtb2R1bGU9Imxpc3RFeGFtcGxlIj4NCiAqICAgPGZpbGUgbmFtZT0iYXBwLmpzIj4NCiAqICAgICAgYW5ndWxhci5tb2R1bGUoJ2xpc3RFeGFtcGxlJywgW10pDQogKiAgICAgICAgLmNvbnRyb2xsZXIoJ0V4YW1wbGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAqICAgICAgICAgICRzY29wZS5uYW1lcyA9IFsnbW9ycGhldXMnLCAnbmVvJywgJ3RyaW5pdHknXTsNCiAqICAgICAgICB9XSk7DQogKiAgIDwvZmlsZT4NCiAqICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogKiAgICA8Zm9ybSBuYW1lPSJteUZvcm0iIG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAqICAgICAgTGlzdDogPGlucHV0IG5hbWU9Im5hbWVzSW5wdXQiIG5nLW1vZGVsPSJuYW1lcyIgbmctbGlzdCByZXF1aXJlZD4NCiAqICAgICAgPHNwYW4gY2xhc3M9ImVycm9yIiBuZy1zaG93PSJteUZvcm0ubmFtZXNJbnB1dC4kZXJyb3IucmVxdWlyZWQiPg0KICogICAgICAgIFJlcXVpcmVkITwvc3Bhbj4NCiAqICAgICAgPGJyPg0KICogICAgICA8dHQ+bmFtZXMgPSB7e25hbWVzfX08L3R0Pjxici8+DQogKiAgICAgIDx0dD5teUZvcm0ubmFtZXNJbnB1dC4kdmFsaWQgPSB7e215Rm9ybS5uYW1lc0lucHV0LiR2YWxpZH19PC90dD48YnIvPg0KICogICAgICA8dHQ+bXlGb3JtLm5hbWVzSW5wdXQuJGVycm9yID0ge3tteUZvcm0ubmFtZXNJbnB1dC4kZXJyb3J9fTwvdHQ+PGJyLz4NCiAqICAgICAgPHR0Pm15Rm9ybS4kdmFsaWQgPSB7e215Rm9ybS4kdmFsaWR9fTwvdHQ+PGJyLz4NCiAqICAgICAgPHR0Pm15Rm9ybS4kZXJyb3IucmVxdWlyZWQgPSB7eyEhbXlGb3JtLiRlcnJvci5yZXF1aXJlZH19PC90dD48YnIvPg0KICogICAgIDwvZm9ybT4NCiAqICAgPC9maWxlPg0KICogICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAqICAgICB2YXIgbGlzdElucHV0ID0gZWxlbWVudChieS5tb2RlbCgnbmFtZXMnKSk7DQogKiAgICAgdmFyIG5hbWVzID0gZWxlbWVudChieS5leGFjdEJpbmRpbmcoJ25hbWVzJykpOw0KICogICAgIHZhciB2YWxpZCA9IGVsZW1lbnQoYnkuYmluZGluZygnbXlGb3JtLm5hbWVzSW5wdXQuJHZhbGlkJykpOw0KICogICAgIHZhciBlcnJvciA9IGVsZW1lbnQoYnkuY3NzKCdzcGFuLmVycm9yJykpOw0KICoNCiAqICAgICBpdCgnc2hvdWxkIGluaXRpYWxpemUgdG8gbW9kZWwnLCBmdW5jdGlvbigpIHsNCiAqICAgICAgIGV4cGVjdChuYW1lcy5nZXRUZXh0KCkpLnRvQ29udGFpbignWyJtb3JwaGV1cyIsIm5lbyIsInRyaW5pdHkiXScpOw0KICogICAgICAgZXhwZWN0KHZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCd0cnVlJyk7DQogKiAgICAgICBleHBlY3QoZXJyb3IuZ2V0Q3NzVmFsdWUoJ2Rpc3BsYXknKSkudG9CZSgnbm9uZScpOw0KICogICAgIH0pOw0KICoNCiAqICAgICBpdCgnc2hvdWxkIGJlIGludmFsaWQgaWYgZW1wdHknLCBmdW5jdGlvbigpIHsNCiAqICAgICAgIGxpc3RJbnB1dC5jbGVhcigpOw0KICogICAgICAgbGlzdElucHV0LnNlbmRLZXlzKCcnKTsNCiAqDQogKiAgICAgICBleHBlY3QobmFtZXMuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJycpOw0KICogICAgICAgZXhwZWN0KHZhbGlkLmdldFRleHQoKSkudG9Db250YWluKCdmYWxzZScpOw0KICogICAgICAgZXhwZWN0KGVycm9yLmdldENzc1ZhbHVlKCdkaXNwbGF5JykpLm5vdC50b0JlKCdub25lJyk7DQogKiAgICAgfSk7DQogKiAgIDwvZmlsZT4NCiAqIDwvZXhhbXBsZT4NCiAqDQogKiAjIyMgRXhhbXBsZSAtIHNwbGl0dGluZyBvbiB3aGl0ZXNwYWNlDQogKiA8ZXhhbXBsZSBuYW1lPSJuZ0xpc3QtZGlyZWN0aXZlLW5ld2xpbmVzIj4NCiAqICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogKiAgICA8dGV4dGFyZWEgbmctbW9kZWw9Imxpc3QiIG5nLWxpc3Q9IiYjMTA7IiBuZy10cmltPSJmYWxzZSI+PC90ZXh0YXJlYT4NCiAqICAgIDxwcmU+e3sgbGlzdCB8IGpzb24gfX08L3ByZT4NCiAqICAgPC9maWxlPg0KICogICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAqICAgICBpdCgic2hvdWxkIHNwbGl0IHRoZSB0ZXh0IGJ5IG5ld2xpbmVzIiwgZnVuY3Rpb24oKSB7DQogKiAgICAgICB2YXIgbGlzdElucHV0ID0gZWxlbWVudChieS5tb2RlbCgnbGlzdCcpKTsNCiAqICAgICAgIHZhciBvdXRwdXQgPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ2xpc3QgfCBqc29uJykpOw0KICogICAgICAgbGlzdElucHV0LnNlbmRLZXlzKCdhYmNcbmRlZlxuZ2hpJyk7DQogKiAgICAgICBleHBlY3Qob3V0cHV0LmdldFRleHQoKSkudG9Db250YWluKCdbXG4gICJhYmMiLFxuICAiZGVmIixcbiAgImdoaSJcbl0nKTsNCiAqICAgICB9KTsNCiAqICAgPC9maWxlPg0KICogPC9leGFtcGxlPg0KICoNCiAqIEBlbGVtZW50IGlucHV0DQogKiBAcGFyYW0ge3N0cmluZz19IG5nTGlzdCBvcHRpb25hbCBkZWxpbWl0ZXIgdGhhdCBzaG91bGQgYmUgdXNlZCB0byBzcGxpdCB0aGUgdmFsdWUuDQogKi8NCnZhciBuZ0xpc3REaXJlY3RpdmUgPSBmdW5jdGlvbigpIHsNCiAgcmV0dXJuIHsNCiAgICByZXN0cmljdDogJ0EnLA0KICAgIHByaW9yaXR5OiAxMDAsDQogICAgcmVxdWlyZTogJ25nTW9kZWwnLA0KICAgIGxpbms6IGZ1bmN0aW9uKHNjb3BlLCBlbGVtZW50LCBhdHRyLCBjdHJsKSB7DQogICAgICAvLyBXZSB3YW50IHRvIGNvbnRyb2wgd2hpdGVzcGFjZSB0cmltbWluZyBzbyB3ZSB1c2UgdGhpcyBjb252b2x1dGVkIGFwcHJvYWNoDQogICAgICAvLyB0byBhY2Nlc3MgdGhlIG5nTGlzdCBhdHRyaWJ1dGUsIHdoaWNoIGRvZXNuJ3QgcHJlLXRyaW0gdGhlIGF0dHJpYnV0ZQ0KICAgICAgdmFyIG5nTGlzdCA9IGVsZW1lbnQuYXR0cihhdHRyLiRhdHRyLm5nTGlzdCkgfHwgJywgJzsNCiAgICAgIHZhciB0cmltVmFsdWVzID0gYXR0ci5uZ1RyaW0gIT09ICdmYWxzZSc7DQogICAgICB2YXIgc2VwYXJhdG9yID0gdHJpbVZhbHVlcyA/IHRyaW0obmdMaXN0KSA6IG5nTGlzdDsNCg0KICAgICAgdmFyIHBhcnNlID0gZnVuY3Rpb24odmlld1ZhbHVlKSB7DQogICAgICAgIC8vIElmIHRoZSB2aWV3VmFsdWUgaXMgaW52YWxpZCAoc2F5IHJlcXVpcmVkIGJ1dCBlbXB0eSkgaXQgd2lsbCBiZSBgdW5kZWZpbmVkYA0KICAgICAgICBpZiAoaXNVbmRlZmluZWQodmlld1ZhbHVlKSkgcmV0dXJuOw0KDQogICAgICAgIHZhciBsaXN0ID0gW107DQoNCiAgICAgICAgaWYgKHZpZXdWYWx1ZSkgew0KICAgICAgICAgIGZvckVhY2godmlld1ZhbHVlLnNwbGl0KHNlcGFyYXRvciksIGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgICAgICAgICBpZiAodmFsdWUpIGxpc3QucHVzaCh0cmltVmFsdWVzID8gdHJpbSh2YWx1ZSkgOiB2YWx1ZSk7DQogICAgICAgICAgfSk7DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gbGlzdDsNCiAgICAgIH07DQoNCiAgICAgIGN0cmwuJHBhcnNlcnMucHVzaChwYXJzZSk7DQogICAgICBjdHJsLiRmb3JtYXR0ZXJzLnB1c2goZnVuY3Rpb24odmFsdWUpIHsNCiAgICAgICAgaWYgKGlzQXJyYXkodmFsdWUpKSB7DQogICAgICAgICAgcmV0dXJuIHZhbHVlLmpvaW4obmdMaXN0KTsNCiAgICAgICAgfQ0KDQogICAgICAgIHJldHVybiB1bmRlZmluZWQ7DQogICAgICB9KTsNCg0KICAgICAgLy8gT3ZlcnJpZGUgdGhlIHN0YW5kYXJkICRpc0VtcHR5IGJlY2F1c2UgYW4gZW1wdHkgYXJyYXkgbWVhbnMgdGhlIGlucHV0IGlzIGVtcHR5Lg0KICAgICAgY3RybC4kaXNFbXB0eSA9IGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgICAgIHJldHVybiAhdmFsdWUgfHwgIXZhbHVlLmxlbmd0aDsNCiAgICAgIH07DQogICAgfQ0KICB9Ow0KfTsNCg0KDQp2YXIgQ09OU1RBTlRfVkFMVUVfUkVHRVhQID0gL14odHJ1ZXxmYWxzZXxcZCspJC87DQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nVmFsdWUNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIEJpbmRzIHRoZSBnaXZlbiBleHByZXNzaW9uIHRvIHRoZSB2YWx1ZSBvZiBgPG9wdGlvbj5gIG9yIHtAbGluayBpbnB1dFtyYWRpb10gYGlucHV0W3JhZGlvXWB9LA0KICogc28gdGhhdCB3aGVuIHRoZSBlbGVtZW50IGlzIHNlbGVjdGVkLCB0aGUge0BsaW5rIG5nTW9kZWwgYG5nTW9kZWxgfSBvZiB0aGF0IGVsZW1lbnQgaXMgc2V0IHRvDQogKiB0aGUgYm91bmQgdmFsdWUuDQogKg0KICogYG5nVmFsdWVgIGlzIHVzZWZ1bCB3aGVuIGR5bmFtaWNhbGx5IGdlbmVyYXRpbmcgbGlzdHMgb2YgcmFkaW8gYnV0dG9ucyB1c2luZw0KICoge0BsaW5rIG5nUmVwZWF0IGBuZ1JlcGVhdGB9LCBhcyBzaG93biBiZWxvdy4NCiAqDQogKiBMaWtld2lzZSwgYG5nVmFsdWVgIGNhbiBiZSB1c2VkIHRvIGdlbmVyYXRlIGA8b3B0aW9uPmAgZWxlbWVudHMgZm9yDQogKiB0aGUge0BsaW5rIHNlbGVjdCBgc2VsZWN0YH0gZWxlbWVudC4gSW4gdGhhdCBjYXNlIGhvd2V2ZXIsIG9ubHkgc3RyaW5ncyBhcmUgc3VwcG9ydGVkDQogKiBmb3IgdGhlIGB2YWx1ZSBgYXR0cmlidXRlLCBzbyB0aGUgcmVzdWx0aW5nIGBuZ01vZGVsYCB3aWxsIGFsd2F5cyBiZSBhIHN0cmluZy4NCiAqIFN1cHBvcnQgZm9yIGBzZWxlY3RgIG1vZGVscyB3aXRoIG5vbi1zdHJpbmcgdmFsdWVzIGlzIGF2YWlsYWJsZSB2aWEgYG5nT3B0aW9uc2AuDQogKg0KICogQGVsZW1lbnQgaW5wdXQNCiAqIEBwYXJhbSB7c3RyaW5nPX0gbmdWYWx1ZSBhbmd1bGFyIGV4cHJlc3Npb24sIHdob3NlIHZhbHVlIHdpbGwgYmUgYm91bmQgdG8gdGhlIGB2YWx1ZWAgYXR0cmlidXRlDQogKiAgIG9mIHRoZSBgaW5wdXRgIGVsZW1lbnQNCiAqDQogKiBAZXhhbXBsZQ0KICAgIDxleGFtcGxlIG5hbWU9Im5nVmFsdWUtZGlyZWN0aXZlIiBtb2R1bGU9InZhbHVlRXhhbXBsZSI+DQogICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICA8c2NyaXB0Pg0KICAgICAgICAgIGFuZ3VsYXIubW9kdWxlKCd2YWx1ZUV4YW1wbGUnLCBbXSkNCiAgICAgICAgICAgIC5jb250cm9sbGVyKCdFeGFtcGxlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgICAgICAgICRzY29wZS5uYW1lcyA9IFsncGl6emEnLCAndW5pY29ybnMnLCAncm9ib3RzJ107DQogICAgICAgICAgICAgICRzY29wZS5teSA9IHsgZmF2b3JpdGU6ICd1bmljb3JucycgfTsNCiAgICAgICAgICAgIH1dKTsNCiAgICAgICA8L3NjcmlwdD4NCiAgICAgICAgPGZvcm0gbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICAgICAgIDxoMj5XaGljaCBpcyB5b3VyIGZhdm9yaXRlPzwvaDI+DQogICAgICAgICAgICA8bGFiZWwgbmctcmVwZWF0PSJuYW1lIGluIG5hbWVzIiBmb3I9Int7bmFtZX19Ij4NCiAgICAgICAgICAgICAge3tuYW1lfX0NCiAgICAgICAgICAgICAgPGlucHV0IHR5cGU9InJhZGlvIg0KICAgICAgICAgICAgICAgICAgICAgbmctbW9kZWw9Im15LmZhdm9yaXRlIg0KICAgICAgICAgICAgICAgICAgICAgbmctdmFsdWU9Im5hbWUiDQogICAgICAgICAgICAgICAgICAgICBpZD0ie3tuYW1lfX0iDQogICAgICAgICAgICAgICAgICAgICBuYW1lPSJmYXZvcml0ZSI+DQogICAgICAgICAgICA8L2xhYmVsPg0KICAgICAgICAgIDxkaXY+WW91IGNob3NlIHt7bXkuZmF2b3JpdGV9fTwvZGl2Pg0KICAgICAgICA8L2Zvcm0+DQogICAgICA8L2ZpbGU+DQogICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICAgdmFyIGZhdm9yaXRlID0gZWxlbWVudChieS5iaW5kaW5nKCdteS5mYXZvcml0ZScpKTsNCg0KICAgICAgICBpdCgnc2hvdWxkIGluaXRpYWxpemUgdG8gbW9kZWwnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgICBleHBlY3QoZmF2b3JpdGUuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJ3VuaWNvcm5zJyk7DQogICAgICAgIH0pOw0KICAgICAgICBpdCgnc2hvdWxkIGJpbmQgdGhlIHZhbHVlcyB0byB0aGUgaW5wdXRzJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgZWxlbWVudC5hbGwoYnkubW9kZWwoJ215LmZhdm9yaXRlJykpLmdldCgwKS5jbGljaygpOw0KICAgICAgICAgIGV4cGVjdChmYXZvcml0ZS5nZXRUZXh0KCkpLnRvQ29udGFpbigncGl6emEnKTsNCiAgICAgICAgfSk7DQogICAgICA8L2ZpbGU+DQogICAgPC9leGFtcGxlPg0KICovDQp2YXIgbmdWYWx1ZURpcmVjdGl2ZSA9IGZ1bmN0aW9uKCkgew0KICByZXR1cm4gew0KICAgIHJlc3RyaWN0OiAnQScsDQogICAgcHJpb3JpdHk6IDEwMCwNCiAgICBjb21waWxlOiBmdW5jdGlvbih0cGwsIHRwbEF0dHIpIHsNCiAgICAgIGlmIChDT05TVEFOVF9WQUxVRV9SRUdFWFAudGVzdCh0cGxBdHRyLm5nVmFsdWUpKSB7DQogICAgICAgIHJldHVybiBmdW5jdGlvbiBuZ1ZhbHVlQ29uc3RhbnRMaW5rKHNjb3BlLCBlbG0sIGF0dHIpIHsNCiAgICAgICAgICBhdHRyLiRzZXQoJ3ZhbHVlJywgc2NvcGUuJGV2YWwoYXR0ci5uZ1ZhbHVlKSk7DQogICAgICAgIH07DQogICAgICB9IGVsc2Ugew0KICAgICAgICByZXR1cm4gZnVuY3Rpb24gbmdWYWx1ZUxpbmsoc2NvcGUsIGVsbSwgYXR0cikgew0KICAgICAgICAgIHNjb3BlLiR3YXRjaChhdHRyLm5nVmFsdWUsIGZ1bmN0aW9uIHZhbHVlV2F0Y2hBY3Rpb24odmFsdWUpIHsNCiAgICAgICAgICAgIGF0dHIuJHNldCgndmFsdWUnLCB2YWx1ZSk7DQogICAgICAgICAgfSk7DQogICAgICAgIH07DQogICAgICB9DQogICAgfQ0KICB9Ow0KfTsNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ01vZGVsT3B0aW9ucw0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogQWxsb3dzIHR1bmluZyBob3cgbW9kZWwgdXBkYXRlcyBhcmUgZG9uZS4gVXNpbmcgYG5nTW9kZWxPcHRpb25zYCB5b3UgY2FuIHNwZWNpZnkgYSBjdXN0b20gbGlzdCBvZg0KICogZXZlbnRzIHRoYXQgd2lsbCB0cmlnZ2VyIGEgbW9kZWwgdXBkYXRlIGFuZC9vciBhIGRlYm91bmNpbmcgZGVsYXkgc28gdGhhdCB0aGUgYWN0dWFsIHVwZGF0ZSBvbmx5DQogKiB0YWtlcyBwbGFjZSB3aGVuIGEgdGltZXIgZXhwaXJlczsgdGhpcyB0aW1lciB3aWxsIGJlIHJlc2V0IGFmdGVyIGFub3RoZXIgY2hhbmdlIHRha2VzIHBsYWNlLg0KICoNCiAqIEdpdmVuIHRoZSBuYXR1cmUgb2YgYG5nTW9kZWxPcHRpb25zYCwgdGhlIHZhbHVlIGRpc3BsYXllZCBpbnNpZGUgaW5wdXQgZmllbGRzIGluIHRoZSB2aWV3IG1pZ2h0DQogKiBiZSBkaWZmZXJlbnQgdGhhbiB0aGUgdmFsdWUgaW4gdGhlIGFjdHVhbCBtb2RlbC4gVGhpcyBtZWFucyB0aGF0IGlmIHlvdSB1cGRhdGUgdGhlIG1vZGVsIHlvdQ0KICogc2hvdWxkIGFsc28gaW52b2tlIHtAbGluayBuZ01vZGVsLk5nTW9kZWxDb250cm9sbGVyIGAkcm9sbGJhY2tWaWV3VmFsdWVgfSBvbiB0aGUgcmVsZXZhbnQgaW5wdXQgZmllbGQgaW4NCiAqIG9yZGVyIHRvIG1ha2Ugc3VyZSBpdCBpcyBzeW5jaHJvbml6ZWQgd2l0aCB0aGUgbW9kZWwgYW5kIHRoYXQgYW55IGRlYm91bmNlZCBhY3Rpb24gaXMgY2FuY2VsZWQuDQogKg0KICogVGhlIGVhc2llc3Qgd2F5IHRvIHJlZmVyZW5jZSB0aGUgY29udHJvbCdzIHtAbGluayBuZ01vZGVsLk5nTW9kZWxDb250cm9sbGVyIGAkcm9sbGJhY2tWaWV3VmFsdWVgfQ0KICogbWV0aG9kIGlzIGJ5IG1ha2luZyBzdXJlIHRoZSBpbnB1dCBpcyBwbGFjZWQgaW5zaWRlIGEgZm9ybSB0aGF0IGhhcyBhIGBuYW1lYCBhdHRyaWJ1dGUuIFRoaXMgaXMNCiAqIGltcG9ydGFudCBiZWNhdXNlIGBmb3JtYCBjb250cm9sbGVycyBhcmUgcHVibGlzaGVkIHRvIHRoZSByZWxhdGVkIHNjb3BlIHVuZGVyIHRoZSBuYW1lIGluIHRoZWlyDQogKiBgbmFtZWAgYXR0cmlidXRlLg0KICoNCiAqIEFueSBwZW5kaW5nIGNoYW5nZXMgd2lsbCB0YWtlIHBsYWNlIGltbWVkaWF0ZWx5IHdoZW4gYW4gZW5jbG9zaW5nIGZvcm0gaXMgc3VibWl0dGVkIHZpYSB0aGUNCiAqIGBzdWJtaXRgIGV2ZW50LiBOb3RlIHRoYXQgYG5nQ2xpY2tgIGV2ZW50cyB3aWxsIG9jY3VyIGJlZm9yZSB0aGUgbW9kZWwgaXMgdXBkYXRlZC4gVXNlIGBuZ1N1Ym1pdGANCiAqIHRvIGhhdmUgYWNjZXNzIHRvIHRoZSB1cGRhdGVkIG1vZGVsLg0KICoNCiAqIGBuZ01vZGVsT3B0aW9uc2AgaGFzIGFuIGVmZmVjdCBvbiB0aGUgZWxlbWVudCBpdCdzIGRlY2xhcmVkIG9uIGFuZCBpdHMgZGVzY2VuZGFudHMuDQogKg0KICogQHBhcmFtIHtPYmplY3R9IG5nTW9kZWxPcHRpb25zIG9wdGlvbnMgdG8gYXBwbHkgdG8gdGhlIGN1cnJlbnQgbW9kZWwuIFZhbGlkIGtleXMgYXJlOg0KICogICAtIGB1cGRhdGVPbmA6IHN0cmluZyBzcGVjaWZ5aW5nIHdoaWNoIGV2ZW50IHNob3VsZCB0aGUgaW5wdXQgYmUgYm91bmQgdG8uIFlvdSBjYW4gc2V0IHNldmVyYWwNCiAqICAgICBldmVudHMgdXNpbmcgYW4gc3BhY2UgZGVsaW1pdGVkIGxpc3QuIFRoZXJlIGlzIGEgc3BlY2lhbCBldmVudCBjYWxsZWQgYGRlZmF1bHRgIHRoYXQNCiAqICAgICBtYXRjaGVzIHRoZSBkZWZhdWx0IGV2ZW50cyBiZWxvbmdpbmcgb2YgdGhlIGNvbnRyb2wuDQogKiAgIC0gYGRlYm91bmNlYDogaW50ZWdlciB2YWx1ZSB3aGljaCBjb250YWlucyB0aGUgZGVib3VuY2UgbW9kZWwgdXBkYXRlIHZhbHVlIGluIG1pbGxpc2Vjb25kcy4gQQ0KICogICAgIHZhbHVlIG9mIDAgdHJpZ2dlcnMgYW4gaW1tZWRpYXRlIHVwZGF0ZS4gSWYgYW4gb2JqZWN0IGlzIHN1cHBsaWVkIGluc3RlYWQsIHlvdSBjYW4gc3BlY2lmeSBhDQogKiAgICAgY3VzdG9tIHZhbHVlIGZvciBlYWNoIGV2ZW50LiBGb3IgZXhhbXBsZToNCiAqICAgICBgbmctbW9kZWwtb3B0aW9ucz0ieyB1cGRhdGVPbjogJ2RlZmF1bHQgYmx1cicsIGRlYm91bmNlOiB7J2RlZmF1bHQnOiA1MDAsICdibHVyJzogMH0gfSJgDQogKiAgIC0gYGFsbG93SW52YWxpZGA6IGJvb2xlYW4gdmFsdWUgd2hpY2ggaW5kaWNhdGVzIHRoYXQgdGhlIG1vZGVsIGNhbiBiZSBzZXQgd2l0aCB2YWx1ZXMgdGhhdCBkaWQNCiAqICAgICBub3QgdmFsaWRhdGUgY29ycmVjdGx5IGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2Ygc2V0dGluZyB0aGUgbW9kZWwgdG8gdW5kZWZpbmVkLg0KICogICAtIGBnZXR0ZXJTZXR0ZXJgOiBib29sZWFuIHZhbHVlIHdoaWNoIGRldGVybWluZXMgd2hldGhlciBvciBub3QgdG8gdHJlYXQgZnVuY3Rpb25zIGJvdW5kIHRvDQogICAgICAgYG5nTW9kZWxgIGFzIGdldHRlcnMvc2V0dGVycy4NCiAqICAgLSBgdGltZXpvbmVgOiBEZWZpbmVzIHRoZSB0aW1lem9uZSB0byBiZSB1c2VkIHRvIHJlYWQvd3JpdGUgdGhlIGBEYXRlYCBpbnN0YW5jZSBpbiB0aGUgbW9kZWwgZm9yDQogKiAgICAgYDxpbnB1dCB0eXBlPSJkYXRlIj5gLCBgPGlucHV0IHR5cGU9InRpbWUiPmAsIC4uLiAuIFJpZ2h0IG5vdywgdGhlIG9ubHkgc3VwcG9ydGVkIHZhbHVlIGlzIGAnVVRDJ2AsDQogKiAgICAgb3RoZXJ3aXNlIHRoZSBkZWZhdWx0IHRpbWV6b25lIG9mIHRoZSBicm93c2VyIHdpbGwgYmUgdXNlZC4NCiAqDQogKiBAZXhhbXBsZQ0KDQogIFRoZSBmb2xsb3dpbmcgZXhhbXBsZSBzaG93cyBob3cgdG8gb3ZlcnJpZGUgaW1tZWRpYXRlIHVwZGF0ZXMuIENoYW5nZXMgb24gdGhlIGlucHV0cyB3aXRoaW4gdGhlDQogIGZvcm0gd2lsbCB1cGRhdGUgdGhlIG1vZGVsIG9ubHkgd2hlbiB0aGUgY29udHJvbCBsb3NlcyBmb2N1cyAoYmx1ciBldmVudCkuIElmIGBlc2NhcGVgIGtleSBpcw0KICBwcmVzc2VkIHdoaWxlIHRoZSBpbnB1dCBmaWVsZCBpcyBmb2N1c2VkLCB0aGUgdmFsdWUgaXMgcmVzZXQgdG8gdGhlIHZhbHVlIGluIHRoZSBjdXJyZW50IG1vZGVsLg0KDQogIDxleGFtcGxlIG5hbWU9Im5nTW9kZWxPcHRpb25zLWRpcmVjdGl2ZS1ibHVyIiBtb2R1bGU9Im9wdGlvbnNFeGFtcGxlIj4NCiAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICAgICA8Zm9ybSBuYW1lPSJ1c2VyRm9ybSI+DQogICAgICAgICAgTmFtZToNCiAgICAgICAgICA8aW5wdXQgdHlwZT0idGV4dCIgbmFtZT0idXNlck5hbWUiDQogICAgICAgICAgICAgICAgIG5nLW1vZGVsPSJ1c2VyLm5hbWUiDQogICAgICAgICAgICAgICAgIG5nLW1vZGVsLW9wdGlvbnM9InsgdXBkYXRlT246ICdibHVyJyB9Ig0KICAgICAgICAgICAgICAgICBuZy1rZXl1cD0iY2FuY2VsKCRldmVudCkiIC8+PGJyIC8+DQoNCiAgICAgICAgICBPdGhlciBkYXRhOg0KICAgICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBuZy1tb2RlbD0idXNlci5kYXRhIiAvPjxiciAvPg0KICAgICAgICA8L2Zvcm0+DQogICAgICAgIDxwcmU+dXNlci5uYW1lID0gPHNwYW4gbmctYmluZD0idXNlci5uYW1lIj48L3NwYW4+PC9wcmU+DQogICAgICA8L2Rpdj4NCiAgICA8L2ZpbGU+DQogICAgPGZpbGUgbmFtZT0iYXBwLmpzIj4NCiAgICAgIGFuZ3VsYXIubW9kdWxlKCdvcHRpb25zRXhhbXBsZScsIFtdKQ0KICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICRzY29wZS51c2VyID0geyBuYW1lOiAnc2F5JywgZGF0YTogJycgfTsNCg0KICAgICAgICAgICRzY29wZS5jYW5jZWwgPSBmdW5jdGlvbihlKSB7DQogICAgICAgICAgICBpZiAoZS5rZXlDb2RlID09IDI3KSB7DQogICAgICAgICAgICAgICRzY29wZS51c2VyRm9ybS51c2VyTmFtZS4kcm9sbGJhY2tWaWV3VmFsdWUoKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9Ow0KICAgICAgICB9XSk7DQogICAgPC9maWxlPg0KICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgdmFyIG1vZGVsID0gZWxlbWVudChieS5iaW5kaW5nKCd1c2VyLm5hbWUnKSk7DQogICAgICB2YXIgaW5wdXQgPSBlbGVtZW50KGJ5Lm1vZGVsKCd1c2VyLm5hbWUnKSk7DQogICAgICB2YXIgb3RoZXIgPSBlbGVtZW50KGJ5Lm1vZGVsKCd1c2VyLmRhdGEnKSk7DQoNCiAgICAgIGl0KCdzaG91bGQgYWxsb3cgY3VzdG9tIGV2ZW50cycsIGZ1bmN0aW9uKCkgew0KICAgICAgICBpbnB1dC5zZW5kS2V5cygnIGhlbGxvJyk7DQogICAgICAgIGlucHV0LmNsaWNrKCk7DQogICAgICAgIGV4cGVjdChtb2RlbC5nZXRUZXh0KCkpLnRvRXF1YWwoJ3NheScpOw0KICAgICAgICBvdGhlci5jbGljaygpOw0KICAgICAgICBleHBlY3QobW9kZWwuZ2V0VGV4dCgpKS50b0VxdWFsKCdzYXkgaGVsbG8nKTsNCiAgICAgIH0pOw0KDQogICAgICBpdCgnc2hvdWxkICRyb2xsYmFja1ZpZXdWYWx1ZSB3aGVuIG1vZGVsIGNoYW5nZXMnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgaW5wdXQuc2VuZEtleXMoJyBoZWxsbycpOw0KICAgICAgICBleHBlY3QoaW5wdXQuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKS50b0VxdWFsKCdzYXkgaGVsbG8nKTsNCiAgICAgICAgaW5wdXQuc2VuZEtleXMocHJvdHJhY3Rvci5LZXkuRVNDQVBFKTsNCiAgICAgICAgZXhwZWN0KGlucHV0LmdldEF0dHJpYnV0ZSgndmFsdWUnKSkudG9FcXVhbCgnc2F5Jyk7DQogICAgICAgIG90aGVyLmNsaWNrKCk7DQogICAgICAgIGV4cGVjdChtb2RlbC5nZXRUZXh0KCkpLnRvRXF1YWwoJ3NheScpOw0KICAgICAgfSk7DQogICAgPC9maWxlPg0KICA8L2V4YW1wbGU+DQoNCiAgVGhpcyBvbmUgc2hvd3MgaG93IHRvIGRlYm91bmNlIG1vZGVsIGNoYW5nZXMuIE1vZGVsIHdpbGwgYmUgdXBkYXRlZCBvbmx5IDEgc2VjIGFmdGVyIGxhc3QgY2hhbmdlLg0KICBJZiB0aGUgYENsZWFyYCBidXR0b24gaXMgcHJlc3NlZCwgYW55IGRlYm91bmNlZCBhY3Rpb24gaXMgY2FuY2VsZWQgYW5kIHRoZSB2YWx1ZSBiZWNvbWVzIGVtcHR5Lg0KDQogIDxleGFtcGxlIG5hbWU9Im5nTW9kZWxPcHRpb25zLWRpcmVjdGl2ZS1kZWJvdW5jZSIgbW9kdWxlPSJvcHRpb25zRXhhbXBsZSI+DQogICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICAgPGZvcm0gbmFtZT0idXNlckZvcm0iPg0KICAgICAgICAgIE5hbWU6DQogICAgICAgICAgPGlucHV0IHR5cGU9InRleHQiIG5hbWU9InVzZXJOYW1lIg0KICAgICAgICAgICAgICAgICBuZy1tb2RlbD0idXNlci5uYW1lIg0KICAgICAgICAgICAgICAgICBuZy1tb2RlbC1vcHRpb25zPSJ7IGRlYm91bmNlOiAxMDAwIH0iIC8+DQogICAgICAgICAgPGJ1dHRvbiBuZy1jbGljaz0idXNlckZvcm0udXNlck5hbWUuJHJvbGxiYWNrVmlld1ZhbHVlKCk7IHVzZXIubmFtZT0nJyI+Q2xlYXI8L2J1dHRvbj48YnIgLz4NCiAgICAgICAgPC9mb3JtPg0KICAgICAgICA8cHJlPnVzZXIubmFtZSA9IDxzcGFuIG5nLWJpbmQ9InVzZXIubmFtZSI+PC9zcGFuPjwvcHJlPg0KICAgICAgPC9kaXY+DQogICAgPC9maWxlPg0KICAgIDxmaWxlIG5hbWU9ImFwcC5qcyI+DQogICAgICBhbmd1bGFyLm1vZHVsZSgnb3B0aW9uc0V4YW1wbGUnLCBbXSkNCiAgICAgICAgLmNvbnRyb2xsZXIoJ0V4YW1wbGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICAgICAkc2NvcGUudXNlciA9IHsgbmFtZTogJ3NheScgfTsNCiAgICAgICAgfV0pOw0KICAgIDwvZmlsZT4NCiAgPC9leGFtcGxlPg0KDQogIFRoaXMgb25lIHNob3dzIGhvdyB0byBiaW5kIHRvIGdldHRlci9zZXR0ZXJzOg0KDQogIDxleGFtcGxlIG5hbWU9Im5nTW9kZWxPcHRpb25zLWRpcmVjdGl2ZS1nZXR0ZXItc2V0dGVyIiBtb2R1bGU9ImdldHRlclNldHRlckV4YW1wbGUiPg0KICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgPGRpdiBuZy1jb250cm9sbGVyPSJFeGFtcGxlQ29udHJvbGxlciI+DQogICAgICAgIDxmb3JtIG5hbWU9InVzZXJGb3JtIj4NCiAgICAgICAgICBOYW1lOg0KICAgICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBuYW1lPSJ1c2VyTmFtZSINCiAgICAgICAgICAgICAgICAgbmctbW9kZWw9InVzZXIubmFtZSINCiAgICAgICAgICAgICAgICAgbmctbW9kZWwtb3B0aW9ucz0ieyBnZXR0ZXJTZXR0ZXI6IHRydWUgfSIgLz4NCiAgICAgICAgPC9mb3JtPg0KICAgICAgICA8cHJlPnVzZXIubmFtZSA9IDxzcGFuIG5nLWJpbmQ9InVzZXIubmFtZSgpIj48L3NwYW4+PC9wcmU+DQogICAgICA8L2Rpdj4NCiAgICA8L2ZpbGU+DQogICAgPGZpbGUgbmFtZT0iYXBwLmpzIj4NCiAgICAgIGFuZ3VsYXIubW9kdWxlKCdnZXR0ZXJTZXR0ZXJFeGFtcGxlJywgW10pDQogICAgICAgIC5jb250cm9sbGVyKCdFeGFtcGxlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgICAgdmFyIF9uYW1lID0gJ0JyaWFuJzsNCiAgICAgICAgICAkc2NvcGUudXNlciA9IHsNCiAgICAgICAgICAgIG5hbWU6IGZ1bmN0aW9uKG5ld05hbWUpIHsNCiAgICAgICAgICAgICAgcmV0dXJuIGFuZ3VsYXIuaXNEZWZpbmVkKG5ld05hbWUpID8gKF9uYW1lID0gbmV3TmFtZSkgOiBfbmFtZTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9Ow0KICAgICAgICB9XSk7DQogICAgPC9maWxlPg0KICA8L2V4YW1wbGU+DQogKi8NCnZhciBuZ01vZGVsT3B0aW9uc0RpcmVjdGl2ZSA9IGZ1bmN0aW9uKCkgew0KICByZXR1cm4gew0KICAgIHJlc3RyaWN0OiAnQScsDQogICAgY29udHJvbGxlcjogWyckc2NvcGUnLCAnJGF0dHJzJywgZnVuY3Rpb24oJHNjb3BlLCAkYXR0cnMpIHsNCiAgICAgIHZhciB0aGF0ID0gdGhpczsNCiAgICAgIHRoaXMuJG9wdGlvbnMgPSAkc2NvcGUuJGV2YWwoJGF0dHJzLm5nTW9kZWxPcHRpb25zKTsNCiAgICAgIC8vIEFsbG93IGFkZGluZy9vdmVycmlkaW5nIGJvdW5kIGV2ZW50cw0KICAgICAgaWYgKHRoaXMuJG9wdGlvbnMudXBkYXRlT24gIT09IHVuZGVmaW5lZCkgew0KICAgICAgICB0aGlzLiRvcHRpb25zLnVwZGF0ZU9uRGVmYXVsdCA9IGZhbHNlOw0KICAgICAgICAvLyBleHRyYWN0ICJkZWZhdWx0IiBwc2V1ZG8tZXZlbnQgZnJvbSBsaXN0IG9mIGV2ZW50cyB0aGF0IGNhbiB0cmlnZ2VyIGEgbW9kZWwgdXBkYXRlDQogICAgICAgIHRoaXMuJG9wdGlvbnMudXBkYXRlT24gPSB0cmltKHRoaXMuJG9wdGlvbnMudXBkYXRlT24ucmVwbGFjZShERUZBVUxUX1JFR0VYUCwgZnVuY3Rpb24oKSB7DQogICAgICAgICAgdGhhdC4kb3B0aW9ucy51cGRhdGVPbkRlZmF1bHQgPSB0cnVlOw0KICAgICAgICAgIHJldHVybiAnICc7DQogICAgICAgIH0pKTsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIHRoaXMuJG9wdGlvbnMudXBkYXRlT25EZWZhdWx0ID0gdHJ1ZTsNCiAgICAgIH0NCiAgICB9XQ0KICB9Ow0KfTsNCg0KLy8gaGVscGVyIG1ldGhvZHMNCmZ1bmN0aW9uIGFkZFNldFZhbGlkaXR5TWV0aG9kKGNvbnRleHQpIHsNCiAgdmFyIGN0cmwgPSBjb250ZXh0LmN0cmwsDQogICAgICAkZWxlbWVudCA9IGNvbnRleHQuJGVsZW1lbnQsDQogICAgICBjbGFzc0NhY2hlID0ge30sDQogICAgICBzZXQgPSBjb250ZXh0LnNldCwNCiAgICAgIHVuc2V0ID0gY29udGV4dC51bnNldCwNCiAgICAgIHBhcmVudEZvcm0gPSBjb250ZXh0LnBhcmVudEZvcm0sDQogICAgICAkYW5pbWF0ZSA9IGNvbnRleHQuJGFuaW1hdGU7DQoNCiAgY2xhc3NDYWNoZVtJTlZBTElEX0NMQVNTXSA9ICEoY2xhc3NDYWNoZVtWQUxJRF9DTEFTU10gPSAkZWxlbWVudC5oYXNDbGFzcyhWQUxJRF9DTEFTUykpOw0KDQogIGN0cmwuJHNldFZhbGlkaXR5ID0gc2V0VmFsaWRpdHk7DQoNCiAgZnVuY3Rpb24gc2V0VmFsaWRpdHkodmFsaWRhdGlvbkVycm9yS2V5LCBzdGF0ZSwgb3B0aW9ucykgew0KICAgIGlmIChzdGF0ZSA9PT0gdW5kZWZpbmVkKSB7DQogICAgICBjcmVhdGVBbmRTZXQoJyRwZW5kaW5nJywgdmFsaWRhdGlvbkVycm9yS2V5LCBvcHRpb25zKTsNCiAgICB9IGVsc2Ugew0KICAgICAgdW5zZXRBbmRDbGVhbnVwKCckcGVuZGluZycsIHZhbGlkYXRpb25FcnJvcktleSwgb3B0aW9ucyk7DQogICAgfQ0KICAgIGlmICghaXNCb29sZWFuKHN0YXRlKSkgew0KICAgICAgdW5zZXQoY3RybC4kZXJyb3IsIHZhbGlkYXRpb25FcnJvcktleSwgb3B0aW9ucyk7DQogICAgICB1bnNldChjdHJsLiQkc3VjY2VzcywgdmFsaWRhdGlvbkVycm9yS2V5LCBvcHRpb25zKTsNCiAgICB9IGVsc2Ugew0KICAgICAgaWYgKHN0YXRlKSB7DQogICAgICAgIHVuc2V0KGN0cmwuJGVycm9yLCB2YWxpZGF0aW9uRXJyb3JLZXksIG9wdGlvbnMpOw0KICAgICAgICBzZXQoY3RybC4kJHN1Y2Nlc3MsIHZhbGlkYXRpb25FcnJvcktleSwgb3B0aW9ucyk7DQogICAgICB9IGVsc2Ugew0KICAgICAgICBzZXQoY3RybC4kZXJyb3IsIHZhbGlkYXRpb25FcnJvcktleSwgb3B0aW9ucyk7DQogICAgICAgIHVuc2V0KGN0cmwuJCRzdWNjZXNzLCB2YWxpZGF0aW9uRXJyb3JLZXksIG9wdGlvbnMpOw0KICAgICAgfQ0KICAgIH0NCiAgICBpZiAoY3RybC4kcGVuZGluZykgew0KICAgICAgY2FjaGVkVG9nZ2xlQ2xhc3MoUEVORElOR19DTEFTUywgdHJ1ZSk7DQogICAgICBjdHJsLiR2YWxpZCA9IGN0cmwuJGludmFsaWQgPSB1bmRlZmluZWQ7DQogICAgICB0b2dnbGVWYWxpZGF0aW9uQ3NzKCcnLCBudWxsKTsNCiAgICB9IGVsc2Ugew0KICAgICAgY2FjaGVkVG9nZ2xlQ2xhc3MoUEVORElOR19DTEFTUywgZmFsc2UpOw0KICAgICAgY3RybC4kdmFsaWQgPSBpc09iamVjdEVtcHR5KGN0cmwuJGVycm9yKTsNCiAgICAgIGN0cmwuJGludmFsaWQgPSAhY3RybC4kdmFsaWQ7DQogICAgICB0b2dnbGVWYWxpZGF0aW9uQ3NzKCcnLCBjdHJsLiR2YWxpZCk7DQogICAgfQ0KDQogICAgLy8gcmUtcmVhZCB0aGUgc3RhdGUgYXMgdGhlIHNldC91bnNldCBtZXRob2RzIGNvdWxkIGhhdmUNCiAgICAvLyBjb21iaW5lZCBzdGF0ZSBpbiBjdHJsLiRlcnJvclt2YWxpZGF0aW9uRXJyb3JdICh1c2VkIGZvciBmb3JtcyksDQogICAgLy8gd2hlcmUgc2V0dGluZy91bnNldHRpbmcgb25seSBpbmNyZW1lbnRzL2RlY3JlbWVudHMgdGhlIHZhbHVlLA0KICAgIC8vIGFuZCBkb2VzIG5vdCByZXBsYWNlIGl0Lg0KICAgIHZhciBjb21iaW5lZFN0YXRlOw0KICAgIGlmIChjdHJsLiRwZW5kaW5nICYmIGN0cmwuJHBlbmRpbmdbdmFsaWRhdGlvbkVycm9yS2V5XSkgew0KICAgICAgY29tYmluZWRTdGF0ZSA9IHVuZGVmaW5lZDsNCiAgICB9IGVsc2UgaWYgKGN0cmwuJGVycm9yW3ZhbGlkYXRpb25FcnJvcktleV0pIHsNCiAgICAgIGNvbWJpbmVkU3RhdGUgPSBmYWxzZTsNCiAgICB9IGVsc2UgaWYgKGN0cmwuJCRzdWNjZXNzW3ZhbGlkYXRpb25FcnJvcktleV0pIHsNCiAgICAgIGNvbWJpbmVkU3RhdGUgPSB0cnVlOw0KICAgIH0gZWxzZSB7DQogICAgICBjb21iaW5lZFN0YXRlID0gbnVsbDsNCiAgICB9DQogICAgdG9nZ2xlVmFsaWRhdGlvbkNzcyh2YWxpZGF0aW9uRXJyb3JLZXksIGNvbWJpbmVkU3RhdGUpOw0KICAgIHBhcmVudEZvcm0uJHNldFZhbGlkaXR5KHZhbGlkYXRpb25FcnJvcktleSwgY29tYmluZWRTdGF0ZSwgY3RybCk7DQogIH0NCg0KICBmdW5jdGlvbiBjcmVhdGVBbmRTZXQobmFtZSwgdmFsdWUsIG9wdGlvbnMpIHsNCiAgICBpZiAoIWN0cmxbbmFtZV0pIHsNCiAgICAgIGN0cmxbbmFtZV0gPSB7fTsNCiAgICB9DQogICAgc2V0KGN0cmxbbmFtZV0sIHZhbHVlLCBvcHRpb25zKTsNCiAgfQ0KDQogIGZ1bmN0aW9uIHVuc2V0QW5kQ2xlYW51cChuYW1lLCB2YWx1ZSwgb3B0aW9ucykgew0KICAgIGlmIChjdHJsW25hbWVdKSB7DQogICAgICB1bnNldChjdHJsW25hbWVdLCB2YWx1ZSwgb3B0aW9ucyk7DQogICAgfQ0KICAgIGlmIChpc09iamVjdEVtcHR5KGN0cmxbbmFtZV0pKSB7DQogICAgICBjdHJsW25hbWVdID0gdW5kZWZpbmVkOw0KICAgIH0NCiAgfQ0KDQogIGZ1bmN0aW9uIGNhY2hlZFRvZ2dsZUNsYXNzKGNsYXNzTmFtZSwgc3dpdGNoVmFsdWUpIHsNCiAgICBpZiAoc3dpdGNoVmFsdWUgJiYgIWNsYXNzQ2FjaGVbY2xhc3NOYW1lXSkgew0KICAgICAgJGFuaW1hdGUuYWRkQ2xhc3MoJGVsZW1lbnQsIGNsYXNzTmFtZSk7DQogICAgICBjbGFzc0NhY2hlW2NsYXNzTmFtZV0gPSB0cnVlOw0KICAgIH0gZWxzZSBpZiAoIXN3aXRjaFZhbHVlICYmIGNsYXNzQ2FjaGVbY2xhc3NOYW1lXSkgew0KICAgICAgJGFuaW1hdGUucmVtb3ZlQ2xhc3MoJGVsZW1lbnQsIGNsYXNzTmFtZSk7DQogICAgICBjbGFzc0NhY2hlW2NsYXNzTmFtZV0gPSBmYWxzZTsNCiAgICB9DQogIH0NCg0KICBmdW5jdGlvbiB0b2dnbGVWYWxpZGF0aW9uQ3NzKHZhbGlkYXRpb25FcnJvcktleSwgaXNWYWxpZCkgew0KICAgIHZhbGlkYXRpb25FcnJvcktleSA9IHZhbGlkYXRpb25FcnJvcktleSA/ICctJyArIHNuYWtlX2Nhc2UodmFsaWRhdGlvbkVycm9yS2V5LCAnLScpIDogJyc7DQoNCiAgICBjYWNoZWRUb2dnbGVDbGFzcyhWQUxJRF9DTEFTUyArIHZhbGlkYXRpb25FcnJvcktleSwgaXNWYWxpZCA9PT0gdHJ1ZSk7DQogICAgY2FjaGVkVG9nZ2xlQ2xhc3MoSU5WQUxJRF9DTEFTUyArIHZhbGlkYXRpb25FcnJvcktleSwgaXNWYWxpZCA9PT0gZmFsc2UpOw0KICB9DQp9DQoNCmZ1bmN0aW9uIGlzT2JqZWN0RW1wdHkob2JqKSB7DQogIGlmIChvYmopIHsNCiAgICBmb3IgKHZhciBwcm9wIGluIG9iaikgew0KICAgICAgcmV0dXJuIGZhbHNlOw0KICAgIH0NCiAgfQ0KICByZXR1cm4gdHJ1ZTsNCn0NCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0JpbmQNCiAqIEByZXN0cmljdCBBQw0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlIGBuZ0JpbmRgIGF0dHJpYnV0ZSB0ZWxscyBBbmd1bGFyIHRvIHJlcGxhY2UgdGhlIHRleHQgY29udGVudCBvZiB0aGUgc3BlY2lmaWVkIEhUTUwgZWxlbWVudA0KICogd2l0aCB0aGUgdmFsdWUgb2YgYSBnaXZlbiBleHByZXNzaW9uLCBhbmQgdG8gdXBkYXRlIHRoZSB0ZXh0IGNvbnRlbnQgd2hlbiB0aGUgdmFsdWUgb2YgdGhhdA0KICogZXhwcmVzc2lvbiBjaGFuZ2VzLg0KICoNCiAqIFR5cGljYWxseSwgeW91IGRvbid0IHVzZSBgbmdCaW5kYCBkaXJlY3RseSwgYnV0IGluc3RlYWQgeW91IHVzZSB0aGUgZG91YmxlIGN1cmx5IG1hcmt1cCBsaWtlDQogKiBge3sgZXhwcmVzc2lvbiB9fWAgd2hpY2ggaXMgc2ltaWxhciBidXQgbGVzcyB2ZXJib3NlLg0KICoNCiAqIEl0IGlzIHByZWZlcmFibGUgdG8gdXNlIGBuZ0JpbmRgIGluc3RlYWQgb2YgYHt7IGV4cHJlc3Npb24gfX1gIGlmIGEgdGVtcGxhdGUgaXMgbW9tZW50YXJpbHkNCiAqIGRpc3BsYXllZCBieSB0aGUgYnJvd3NlciBpbiBpdHMgcmF3IHN0YXRlIGJlZm9yZSBBbmd1bGFyIGNvbXBpbGVzIGl0LiBTaW5jZSBgbmdCaW5kYCBpcyBhbg0KICogZWxlbWVudCBhdHRyaWJ1dGUsIGl0IG1ha2VzIHRoZSBiaW5kaW5ncyBpbnZpc2libGUgdG8gdGhlIHVzZXIgd2hpbGUgdGhlIHBhZ2UgaXMgbG9hZGluZy4NCiAqDQogKiBBbiBhbHRlcm5hdGl2ZSBzb2x1dGlvbiB0byB0aGlzIHByb2JsZW0gd291bGQgYmUgdXNpbmcgdGhlDQogKiB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nQ2xvYWsgbmdDbG9ha30gZGlyZWN0aXZlLg0KICoNCiAqDQogKiBAZWxlbWVudCBBTlkNCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdCaW5kIHtAbGluayBndWlkZS9leHByZXNzaW9uIEV4cHJlc3Npb259IHRvIGV2YWx1YXRlLg0KICoNCiAqIEBleGFtcGxlDQogKiBFbnRlciBhIG5hbWUgaW4gdGhlIExpdmUgUHJldmlldyB0ZXh0IGJveDsgdGhlIGdyZWV0aW5nIGJlbG93IHRoZSB0ZXh0IGJveCBjaGFuZ2VzIGluc3RhbnRseS4NCiAgIDxleGFtcGxlIG1vZHVsZT0iYmluZEV4YW1wbGUiPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICA8c2NyaXB0Pg0KICAgICAgICAgYW5ndWxhci5tb2R1bGUoJ2JpbmRFeGFtcGxlJywgW10pDQogICAgICAgICAgIC5jb250cm9sbGVyKCdFeGFtcGxlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgICAgICAgJHNjb3BlLm5hbWUgPSAnV2hpcmxlZCc7DQogICAgICAgICAgIH1dKTsNCiAgICAgICA8L3NjcmlwdD4NCiAgICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICAgIEVudGVyIG5hbWU6IDxpbnB1dCB0eXBlPSJ0ZXh0IiBuZy1tb2RlbD0ibmFtZSI+PGJyPg0KICAgICAgICAgSGVsbG8gPHNwYW4gbmctYmluZD0ibmFtZSI+PC9zcGFuPiENCiAgICAgICA8L2Rpdj4NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICBpdCgnc2hvdWxkIGNoZWNrIG5nLWJpbmQnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgIHZhciBuYW1lSW5wdXQgPSBlbGVtZW50KGJ5Lm1vZGVsKCduYW1lJykpOw0KDQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5iaW5kaW5nKCduYW1lJykpLmdldFRleHQoKSkudG9CZSgnV2hpcmxlZCcpOw0KICAgICAgICAgbmFtZUlucHV0LmNsZWFyKCk7DQogICAgICAgICBuYW1lSW5wdXQuc2VuZEtleXMoJ3dvcmxkJyk7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5iaW5kaW5nKCduYW1lJykpLmdldFRleHQoKSkudG9CZSgnd29ybGQnKTsNCiAgICAgICB9KTsNCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICovDQp2YXIgbmdCaW5kRGlyZWN0aXZlID0gWyckY29tcGlsZScsIGZ1bmN0aW9uKCRjb21waWxlKSB7DQogIHJldHVybiB7DQogICAgcmVzdHJpY3Q6ICdBQycsDQogICAgY29tcGlsZTogZnVuY3Rpb24gbmdCaW5kQ29tcGlsZSh0ZW1wbGF0ZUVsZW1lbnQpIHsNCiAgICAgICRjb21waWxlLiQkYWRkQmluZGluZ0NsYXNzKHRlbXBsYXRlRWxlbWVudCk7DQogICAgICByZXR1cm4gZnVuY3Rpb24gbmdCaW5kTGluayhzY29wZSwgZWxlbWVudCwgYXR0cikgew0KICAgICAgICAkY29tcGlsZS4kJGFkZEJpbmRpbmdJbmZvKGVsZW1lbnQsIGF0dHIubmdCaW5kKTsNCiAgICAgICAgZWxlbWVudCA9IGVsZW1lbnRbMF07DQogICAgICAgIHNjb3BlLiR3YXRjaChhdHRyLm5nQmluZCwgZnVuY3Rpb24gbmdCaW5kV2F0Y2hBY3Rpb24odmFsdWUpIHsNCiAgICAgICAgICBlbGVtZW50LnRleHRDb250ZW50ID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/ICcnIDogdmFsdWU7DQogICAgICAgIH0pOw0KICAgICAgfTsNCiAgICB9DQogIH07DQp9XTsNCg0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nQmluZFRlbXBsYXRlDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBUaGUgYG5nQmluZFRlbXBsYXRlYCBkaXJlY3RpdmUgc3BlY2lmaWVzIHRoYXQgdGhlIGVsZW1lbnQNCiAqIHRleHQgY29udGVudCBzaG91bGQgYmUgcmVwbGFjZWQgd2l0aCB0aGUgaW50ZXJwb2xhdGlvbiBvZiB0aGUgdGVtcGxhdGUNCiAqIGluIHRoZSBgbmdCaW5kVGVtcGxhdGVgIGF0dHJpYnV0ZS4NCiAqIFVubGlrZSBgbmdCaW5kYCwgdGhlIGBuZ0JpbmRUZW1wbGF0ZWAgY2FuIGNvbnRhaW4gbXVsdGlwbGUgYHt7YCBgfX1gDQogKiBleHByZXNzaW9ucy4gVGhpcyBkaXJlY3RpdmUgaXMgbmVlZGVkIHNpbmNlIHNvbWUgSFRNTCBlbGVtZW50cw0KICogKHN1Y2ggYXMgVElUTEUgYW5kIE9QVElPTikgY2Fubm90IGNvbnRhaW4gU1BBTiBlbGVtZW50cy4NCiAqDQogKiBAZWxlbWVudCBBTlkNCiAqIEBwYXJhbSB7c3RyaW5nfSBuZ0JpbmRUZW1wbGF0ZSB0ZW1wbGF0ZSBvZiBmb3JtDQogKiAgIDx0dD57ezwvdHQ+IDx0dD5leHByZXNzaW9uPC90dD4gPHR0Pn19PC90dD4gdG8gZXZhbC4NCiAqDQogKiBAZXhhbXBsZQ0KICogVHJ5IGl0IGhlcmU6IGVudGVyIHRleHQgaW4gdGV4dCBib3ggYW5kIHdhdGNoIHRoZSBncmVldGluZyBjaGFuZ2UuDQogICA8ZXhhbXBsZSBtb2R1bGU9ImJpbmRFeGFtcGxlIj4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPHNjcmlwdD4NCiAgICAgICAgIGFuZ3VsYXIubW9kdWxlKCdiaW5kRXhhbXBsZScsIFtdKQ0KICAgICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICAgICRzY29wZS5zYWx1dGF0aW9uID0gJ0hlbGxvJzsNCiAgICAgICAgICAgICAkc2NvcGUubmFtZSA9ICdXb3JsZCc7DQogICAgICAgICAgIH1dKTsNCiAgICAgICA8L3NjcmlwdD4NCiAgICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICAgU2FsdXRhdGlvbjogPGlucHV0IHR5cGU9InRleHQiIG5nLW1vZGVsPSJzYWx1dGF0aW9uIj48YnI+DQogICAgICAgIE5hbWU6IDxpbnB1dCB0eXBlPSJ0ZXh0IiBuZy1tb2RlbD0ibmFtZSI+PGJyPg0KICAgICAgICA8cHJlIG5nLWJpbmQtdGVtcGxhdGU9Int7c2FsdXRhdGlvbn19IHt7bmFtZX19ISI+PC9wcmU+DQogICAgICAgPC9kaXY+DQogICAgIDwvZmlsZT4NCiAgICAgPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogICAgICAgaXQoJ3Nob3VsZCBjaGVjayBuZy1iaW5kJywgZnVuY3Rpb24oKSB7DQogICAgICAgICB2YXIgc2FsdXRhdGlvbkVsZW0gPSBlbGVtZW50KGJ5LmJpbmRpbmcoJ3NhbHV0YXRpb24nKSk7DQogICAgICAgICB2YXIgc2FsdXRhdGlvbklucHV0ID0gZWxlbWVudChieS5tb2RlbCgnc2FsdXRhdGlvbicpKTsNCiAgICAgICAgIHZhciBuYW1lSW5wdXQgPSBlbGVtZW50KGJ5Lm1vZGVsKCduYW1lJykpOw0KDQogICAgICAgICBleHBlY3Qoc2FsdXRhdGlvbkVsZW0uZ2V0VGV4dCgpKS50b0JlKCdIZWxsbyBXb3JsZCEnKTsNCg0KICAgICAgICAgc2FsdXRhdGlvbklucHV0LmNsZWFyKCk7DQogICAgICAgICBzYWx1dGF0aW9uSW5wdXQuc2VuZEtleXMoJ0dyZWV0aW5ncycpOw0KICAgICAgICAgbmFtZUlucHV0LmNsZWFyKCk7DQogICAgICAgICBuYW1lSW5wdXQuc2VuZEtleXMoJ3VzZXInKTsNCg0KICAgICAgICAgZXhwZWN0KHNhbHV0YXRpb25FbGVtLmdldFRleHQoKSkudG9CZSgnR3JlZXRpbmdzIHVzZXIhJyk7DQogICAgICAgfSk7DQogICAgIDwvZmlsZT4NCiAgIDwvZXhhbXBsZT4NCiAqLw0KdmFyIG5nQmluZFRlbXBsYXRlRGlyZWN0aXZlID0gWyckaW50ZXJwb2xhdGUnLCAnJGNvbXBpbGUnLCBmdW5jdGlvbigkaW50ZXJwb2xhdGUsICRjb21waWxlKSB7DQogIHJldHVybiB7DQogICAgY29tcGlsZTogZnVuY3Rpb24gbmdCaW5kVGVtcGxhdGVDb21waWxlKHRlbXBsYXRlRWxlbWVudCkgew0KICAgICAgJGNvbXBpbGUuJCRhZGRCaW5kaW5nQ2xhc3ModGVtcGxhdGVFbGVtZW50KTsNCiAgICAgIHJldHVybiBmdW5jdGlvbiBuZ0JpbmRUZW1wbGF0ZUxpbmsoc2NvcGUsIGVsZW1lbnQsIGF0dHIpIHsNCiAgICAgICAgdmFyIGludGVycG9sYXRlRm4gPSAkaW50ZXJwb2xhdGUoZWxlbWVudC5hdHRyKGF0dHIuJGF0dHIubmdCaW5kVGVtcGxhdGUpKTsNCiAgICAgICAgJGNvbXBpbGUuJCRhZGRCaW5kaW5nSW5mbyhlbGVtZW50LCBpbnRlcnBvbGF0ZUZuLmV4cHJlc3Npb25zKTsNCiAgICAgICAgZWxlbWVudCA9IGVsZW1lbnRbMF07DQogICAgICAgIGF0dHIuJG9ic2VydmUoJ25nQmluZFRlbXBsYXRlJywgZnVuY3Rpb24odmFsdWUpIHsNCiAgICAgICAgICBlbGVtZW50LnRleHRDb250ZW50ID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/ICcnIDogdmFsdWU7DQogICAgICAgIH0pOw0KICAgICAgfTsNCiAgICB9DQogIH07DQp9XTsNCg0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nQmluZEh0bWwNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIEV2YWx1YXRlcyB0aGUgZXhwcmVzc2lvbiBhbmQgaW5zZXJ0cyB0aGUgcmVzdWx0aW5nIEhUTUwgaW50byB0aGUgZWxlbWVudCBpbiBhIHNlY3VyZSB3YXkuIEJ5IGRlZmF1bHQsDQogKiB0aGUgcmVzdWx0aW5nIEhUTUwgY29udGVudCB3aWxsIGJlIHNhbml0aXplZCB1c2luZyB0aGUge0BsaW5rIG5nU2FuaXRpemUuJHNhbml0aXplICRzYW5pdGl6ZX0gc2VydmljZS4NCiAqIFRvIHV0aWxpemUgdGhpcyBmdW5jdGlvbmFsaXR5LCBlbnN1cmUgdGhhdCBgJHNhbml0aXplYCBpcyBhdmFpbGFibGUsIGZvciBleGFtcGxlLCBieSBpbmNsdWRpbmcge0BsaW5rDQogKiBuZ1Nhbml0aXplfSBpbiB5b3VyIG1vZHVsZSdzIGRlcGVuZGVuY2llcyAobm90IGluIGNvcmUgQW5ndWxhcikuIEluIG9yZGVyIHRvIHVzZSB7QGxpbmsgbmdTYW5pdGl6ZX0NCiAqIGluIHlvdXIgbW9kdWxlJ3MgZGVwZW5kZW5jaWVzLCB5b3UgbmVlZCB0byBpbmNsdWRlICJhbmd1bGFyLXNhbml0aXplLmpzIiBpbiB5b3VyIGFwcGxpY2F0aW9uLg0KICoNCiAqIFlvdSBtYXkgYWxzbyBieXBhc3Mgc2FuaXRpemF0aW9uIGZvciB2YWx1ZXMgeW91IGtub3cgYXJlIHNhZmUuIFRvIGRvIHNvLCBiaW5kIHRvDQogKiBhbiBleHBsaWNpdGx5IHRydXN0ZWQgdmFsdWUgdmlhIHtAbGluayBuZy4kc2NlI3RydXN0QXNIdG1sICRzY2UudHJ1c3RBc0h0bWx9LiAgU2VlIHRoZSBleGFtcGxlDQogKiB1bmRlciB7QGxpbmsgbmcuJHNjZSNzaG93LW1lLWFuLWV4YW1wbGUtdXNpbmctc2NlLSBTdHJpY3QgQ29udGV4dHVhbCBFc2NhcGluZyAoU0NFKX0uDQogKg0KICogTm90ZTogSWYgYSBgJHNhbml0aXplYCBzZXJ2aWNlIGlzIHVuYXZhaWxhYmxlIGFuZCB0aGUgYm91bmQgdmFsdWUgaXNuJ3QgZXhwbGljaXRseSB0cnVzdGVkLCB5b3UNCiAqIHdpbGwgaGF2ZSBhbiBleGNlcHRpb24gKGluc3RlYWQgb2YgYW4gZXhwbG9pdC4pDQogKg0KICogQGVsZW1lbnQgQU5ZDQogKiBAcGFyYW0ge2V4cHJlc3Npb259IG5nQmluZEh0bWwge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gRXhwcmVzc2lvbn0gdG8gZXZhbHVhdGUuDQogKg0KICogQGV4YW1wbGUNCg0KICAgPGV4YW1wbGUgbW9kdWxlPSJiaW5kSHRtbEV4YW1wbGUiIGRlcHM9ImFuZ3VsYXItc2FuaXRpemUuanMiPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICAgPHAgbmctYmluZC1odG1sPSJteUhUTUwiPjwvcD4NCiAgICAgICA8L2Rpdj4NCiAgICAgPC9maWxlPg0KDQogICAgIDxmaWxlIG5hbWU9InNjcmlwdC5qcyI+DQogICAgICAgYW5ndWxhci5tb2R1bGUoJ2JpbmRIdG1sRXhhbXBsZScsIFsnbmdTYW5pdGl6ZSddKQ0KICAgICAgICAgLmNvbnRyb2xsZXIoJ0V4YW1wbGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICAgICAgJHNjb3BlLm15SFRNTCA9DQogICAgICAgICAgICAgICdJIGFtIGFuIDxjb2RlPkhUTUw8L2NvZGU+c3RyaW5nIHdpdGggJyArDQogICAgICAgICAgICAgICc8YSBocmVmPSIjIj5saW5rcyE8L2E+IGFuZCBvdGhlciA8ZW0+c3R1ZmY8L2VtPic7DQogICAgICAgICB9XSk7DQogICAgIDwvZmlsZT4NCg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICBpdCgnc2hvdWxkIGNoZWNrIG5nLWJpbmQtaHRtbCcsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuYmluZGluZygnbXlIVE1MJykpLmdldFRleHQoKSkudG9CZSgNCiAgICAgICAgICAgICAnSSBhbSBhbiBIVE1Mc3RyaW5nIHdpdGggbGlua3MhIGFuZCBvdGhlciBzdHVmZicpOw0KICAgICAgIH0pOw0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCnZhciBuZ0JpbmRIdG1sRGlyZWN0aXZlID0gWyckc2NlJywgJyRwYXJzZScsICckY29tcGlsZScsIGZ1bmN0aW9uKCRzY2UsICRwYXJzZSwgJGNvbXBpbGUpIHsNCiAgcmV0dXJuIHsNCiAgICByZXN0cmljdDogJ0EnLA0KICAgIGNvbXBpbGU6IGZ1bmN0aW9uIG5nQmluZEh0bWxDb21waWxlKHRFbGVtZW50LCB0QXR0cnMpIHsNCiAgICAgIHZhciBuZ0JpbmRIdG1sR2V0dGVyID0gJHBhcnNlKHRBdHRycy5uZ0JpbmRIdG1sKTsNCiAgICAgIHZhciBuZ0JpbmRIdG1sV2F0Y2ggPSAkcGFyc2UodEF0dHJzLm5nQmluZEh0bWwsIGZ1bmN0aW9uIGdldFN0cmluZ1ZhbHVlKHZhbHVlKSB7DQogICAgICAgIHJldHVybiAodmFsdWUgfHwgJycpLnRvU3RyaW5nKCk7DQogICAgICB9KTsNCiAgICAgICRjb21waWxlLiQkYWRkQmluZGluZ0NsYXNzKHRFbGVtZW50KTsNCg0KICAgICAgcmV0dXJuIGZ1bmN0aW9uIG5nQmluZEh0bWxMaW5rKHNjb3BlLCBlbGVtZW50LCBhdHRyKSB7DQogICAgICAgICRjb21waWxlLiQkYWRkQmluZGluZ0luZm8oZWxlbWVudCwgYXR0ci5uZ0JpbmRIdG1sKTsNCg0KICAgICAgICBzY29wZS4kd2F0Y2gobmdCaW5kSHRtbFdhdGNoLCBmdW5jdGlvbiBuZ0JpbmRIdG1sV2F0Y2hBY3Rpb24oKSB7DQogICAgICAgICAgLy8gd2UgcmUtZXZhbHVhdGUgdGhlIGV4cHIgYmVjYXVzZSB3ZSB3YW50IGEgVHJ1c3RlZFZhbHVlSG9sZGVyVHlwZQ0KICAgICAgICAgIC8vIGZvciAkc2NlLCBub3QgYSBzdHJpbmcNCiAgICAgICAgICBlbGVtZW50Lmh0bWwoJHNjZS5nZXRUcnVzdGVkSHRtbChuZ0JpbmRIdG1sR2V0dGVyKHNjb3BlKSkgfHwgJycpOw0KICAgICAgICB9KTsNCiAgICAgIH07DQogICAgfQ0KICB9Ow0KfV07DQoNCmZ1bmN0aW9uIGNsYXNzRGlyZWN0aXZlKG5hbWUsIHNlbGVjdG9yKSB7DQogIG5hbWUgPSAnbmdDbGFzcycgKyBuYW1lOw0KICByZXR1cm4gWyckYW5pbWF0ZScsIGZ1bmN0aW9uKCRhbmltYXRlKSB7DQogICAgcmV0dXJuIHsNCiAgICAgIHJlc3RyaWN0OiAnQUMnLA0KICAgICAgbGluazogZnVuY3Rpb24oc2NvcGUsIGVsZW1lbnQsIGF0dHIpIHsNCiAgICAgICAgdmFyIG9sZFZhbDsNCg0KICAgICAgICBzY29wZS4kd2F0Y2goYXR0cltuYW1lXSwgbmdDbGFzc1dhdGNoQWN0aW9uLCB0cnVlKTsNCg0KICAgICAgICBhdHRyLiRvYnNlcnZlKCdjbGFzcycsIGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgICAgICAgbmdDbGFzc1dhdGNoQWN0aW9uKHNjb3BlLiRldmFsKGF0dHJbbmFtZV0pKTsNCiAgICAgICAgfSk7DQoNCg0KICAgICAgICBpZiAobmFtZSAhPT0gJ25nQ2xhc3MnKSB7DQogICAgICAgICAgc2NvcGUuJHdhdGNoKCckaW5kZXgnLCBmdW5jdGlvbigkaW5kZXgsIG9sZCRpbmRleCkgew0KICAgICAgICAgICAgLy8ganNoaW50IGJpdHdpc2U6IGZhbHNlDQogICAgICAgICAgICB2YXIgbW9kID0gJGluZGV4ICYgMTsNCiAgICAgICAgICAgIGlmIChtb2QgIT09IChvbGQkaW5kZXggJiAxKSkgew0KICAgICAgICAgICAgICB2YXIgY2xhc3NlcyA9IGFycmF5Q2xhc3NlcyhzY29wZS4kZXZhbChhdHRyW25hbWVdKSk7DQogICAgICAgICAgICAgIG1vZCA9PT0gc2VsZWN0b3IgPw0KICAgICAgICAgICAgICAgIGFkZENsYXNzZXMoY2xhc3NlcykgOg0KICAgICAgICAgICAgICAgIHJlbW92ZUNsYXNzZXMoY2xhc3Nlcyk7DQogICAgICAgICAgICB9DQogICAgICAgICAgfSk7DQogICAgICAgIH0NCg0KICAgICAgICBmdW5jdGlvbiBhZGRDbGFzc2VzKGNsYXNzZXMpIHsNCiAgICAgICAgICB2YXIgbmV3Q2xhc3NlcyA9IGRpZ2VzdENsYXNzQ291bnRzKGNsYXNzZXMsIDEpOw0KICAgICAgICAgIGF0dHIuJGFkZENsYXNzKG5ld0NsYXNzZXMpOw0KICAgICAgICB9DQoNCiAgICAgICAgZnVuY3Rpb24gcmVtb3ZlQ2xhc3NlcyhjbGFzc2VzKSB7DQogICAgICAgICAgdmFyIG5ld0NsYXNzZXMgPSBkaWdlc3RDbGFzc0NvdW50cyhjbGFzc2VzLCAtMSk7DQogICAgICAgICAgYXR0ci4kcmVtb3ZlQ2xhc3MobmV3Q2xhc3Nlcyk7DQogICAgICAgIH0NCg0KICAgICAgICBmdW5jdGlvbiBkaWdlc3RDbGFzc0NvdW50cyhjbGFzc2VzLCBjb3VudCkgew0KICAgICAgICAgIHZhciBjbGFzc0NvdW50cyA9IGVsZW1lbnQuZGF0YSgnJGNsYXNzQ291bnRzJykgfHwge307DQogICAgICAgICAgdmFyIGNsYXNzZXNUb1VwZGF0ZSA9IFtdOw0KICAgICAgICAgIGZvckVhY2goY2xhc3NlcywgZnVuY3Rpb24oY2xhc3NOYW1lKSB7DQogICAgICAgICAgICBpZiAoY291bnQgPiAwIHx8IGNsYXNzQ291bnRzW2NsYXNzTmFtZV0pIHsNCiAgICAgICAgICAgICAgY2xhc3NDb3VudHNbY2xhc3NOYW1lXSA9IChjbGFzc0NvdW50c1tjbGFzc05hbWVdIHx8IDApICsgY291bnQ7DQogICAgICAgICAgICAgIGlmIChjbGFzc0NvdW50c1tjbGFzc05hbWVdID09PSArKGNvdW50ID4gMCkpIHsNCiAgICAgICAgICAgICAgICBjbGFzc2VzVG9VcGRhdGUucHVzaChjbGFzc05hbWUpOw0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgfSk7DQogICAgICAgICAgZWxlbWVudC5kYXRhKCckY2xhc3NDb3VudHMnLCBjbGFzc0NvdW50cyk7DQogICAgICAgICAgcmV0dXJuIGNsYXNzZXNUb1VwZGF0ZS5qb2luKCcgJyk7DQogICAgICAgIH0NCg0KICAgICAgICBmdW5jdGlvbiB1cGRhdGVDbGFzc2VzKG9sZENsYXNzZXMsIG5ld0NsYXNzZXMpIHsNCiAgICAgICAgICB2YXIgdG9BZGQgPSBhcnJheURpZmZlcmVuY2UobmV3Q2xhc3Nlcywgb2xkQ2xhc3Nlcyk7DQogICAgICAgICAgdmFyIHRvUmVtb3ZlID0gYXJyYXlEaWZmZXJlbmNlKG9sZENsYXNzZXMsIG5ld0NsYXNzZXMpOw0KICAgICAgICAgIHRvQWRkID0gZGlnZXN0Q2xhc3NDb3VudHModG9BZGQsIDEpOw0KICAgICAgICAgIHRvUmVtb3ZlID0gZGlnZXN0Q2xhc3NDb3VudHModG9SZW1vdmUsIC0xKTsNCiAgICAgICAgICBpZiAodG9BZGQgJiYgdG9BZGQubGVuZ3RoKSB7DQogICAgICAgICAgICAkYW5pbWF0ZS5hZGRDbGFzcyhlbGVtZW50LCB0b0FkZCk7DQogICAgICAgICAgfQ0KICAgICAgICAgIGlmICh0b1JlbW92ZSAmJiB0b1JlbW92ZS5sZW5ndGgpIHsNCiAgICAgICAgICAgICRhbmltYXRlLnJlbW92ZUNsYXNzKGVsZW1lbnQsIHRvUmVtb3ZlKTsNCiAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICBmdW5jdGlvbiBuZ0NsYXNzV2F0Y2hBY3Rpb24obmV3VmFsKSB7DQogICAgICAgICAgaWYgKHNlbGVjdG9yID09PSB0cnVlIHx8IHNjb3BlLiRpbmRleCAlIDIgPT09IHNlbGVjdG9yKSB7DQogICAgICAgICAgICB2YXIgbmV3Q2xhc3NlcyA9IGFycmF5Q2xhc3NlcyhuZXdWYWwgfHwgW10pOw0KICAgICAgICAgICAgaWYgKCFvbGRWYWwpIHsNCiAgICAgICAgICAgICAgYWRkQ2xhc3NlcyhuZXdDbGFzc2VzKTsNCiAgICAgICAgICAgIH0gZWxzZSBpZiAoIWVxdWFscyhuZXdWYWwsb2xkVmFsKSkgew0KICAgICAgICAgICAgICB2YXIgb2xkQ2xhc3NlcyA9IGFycmF5Q2xhc3NlcyhvbGRWYWwpOw0KICAgICAgICAgICAgICB1cGRhdGVDbGFzc2VzKG9sZENsYXNzZXMsIG5ld0NsYXNzZXMpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0NCiAgICAgICAgICBvbGRWYWwgPSBzaGFsbG93Q29weShuZXdWYWwpOw0KICAgICAgICB9DQogICAgICB9DQogICAgfTsNCg0KICAgIGZ1bmN0aW9uIGFycmF5RGlmZmVyZW5jZSh0b2tlbnMxLCB0b2tlbnMyKSB7DQogICAgICB2YXIgdmFsdWVzID0gW107DQoNCiAgICAgIG91dGVyOg0KICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0b2tlbnMxLmxlbmd0aDsgaSsrKSB7DQogICAgICAgIHZhciB0b2tlbiA9IHRva2VuczFbaV07DQogICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdG9rZW5zMi5sZW5ndGg7IGorKykgew0KICAgICAgICAgIGlmICh0b2tlbiA9PSB0b2tlbnMyW2pdKSBjb250aW51ZSBvdXRlcjsNCiAgICAgICAgfQ0KICAgICAgICB2YWx1ZXMucHVzaCh0b2tlbik7DQogICAgICB9DQogICAgICByZXR1cm4gdmFsdWVzOw0KICAgIH0NCg0KICAgIGZ1bmN0aW9uIGFycmF5Q2xhc3NlcyhjbGFzc1ZhbCkgew0KICAgICAgaWYgKGlzQXJyYXkoY2xhc3NWYWwpKSB7DQogICAgICAgIHJldHVybiBjbGFzc1ZhbDsNCiAgICAgIH0gZWxzZSBpZiAoaXNTdHJpbmcoY2xhc3NWYWwpKSB7DQogICAgICAgIHJldHVybiBjbGFzc1ZhbC5zcGxpdCgnICcpOw0KICAgICAgfSBlbHNlIGlmIChpc09iamVjdChjbGFzc1ZhbCkpIHsNCiAgICAgICAgdmFyIGNsYXNzZXMgPSBbXTsNCiAgICAgICAgZm9yRWFjaChjbGFzc1ZhbCwgZnVuY3Rpb24odiwgaykgew0KICAgICAgICAgIGlmICh2KSB7DQogICAgICAgICAgICBjbGFzc2VzID0gY2xhc3Nlcy5jb25jYXQoay5zcGxpdCgnICcpKTsNCiAgICAgICAgICB9DQogICAgICAgIH0pOw0KICAgICAgICByZXR1cm4gY2xhc3NlczsNCiAgICAgIH0NCiAgICAgIHJldHVybiBjbGFzc1ZhbDsNCiAgICB9DQogIH1dOw0KfQ0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nQ2xhc3MNCiAqIEByZXN0cmljdCBBQw0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlIGBuZ0NsYXNzYCBkaXJlY3RpdmUgYWxsb3dzIHlvdSB0byBkeW5hbWljYWxseSBzZXQgQ1NTIGNsYXNzZXMgb24gYW4gSFRNTCBlbGVtZW50IGJ5IGRhdGFiaW5kaW5nDQogKiBhbiBleHByZXNzaW9uIHRoYXQgcmVwcmVzZW50cyBhbGwgY2xhc3NlcyB0byBiZSBhZGRlZC4NCiAqDQogKiBUaGUgZGlyZWN0aXZlIG9wZXJhdGVzIGluIHRocmVlIGRpZmZlcmVudCB3YXlzLCBkZXBlbmRpbmcgb24gd2hpY2ggb2YgdGhyZWUgdHlwZXMgdGhlIGV4cHJlc3Npb24NCiAqIGV2YWx1YXRlcyB0bzoNCiAqDQogKiAxLiBJZiB0aGUgZXhwcmVzc2lvbiBldmFsdWF0ZXMgdG8gYSBzdHJpbmcsIHRoZSBzdHJpbmcgc2hvdWxkIGJlIG9uZSBvciBtb3JlIHNwYWNlLWRlbGltaXRlZCBjbGFzcw0KICogbmFtZXMuDQogKg0KICogMi4gSWYgdGhlIGV4cHJlc3Npb24gZXZhbHVhdGVzIHRvIGFuIGFycmF5LCBlYWNoIGVsZW1lbnQgb2YgdGhlIGFycmF5IHNob3VsZCBiZSBhIHN0cmluZyB0aGF0IGlzDQogKiBvbmUgb3IgbW9yZSBzcGFjZS1kZWxpbWl0ZWQgY2xhc3MgbmFtZXMuDQogKg0KICogMy4gSWYgdGhlIGV4cHJlc3Npb24gZXZhbHVhdGVzIHRvIGFuIG9iamVjdCwgdGhlbiBmb3IgZWFjaCBrZXktdmFsdWUgcGFpciBvZiB0aGUNCiAqIG9iamVjdCB3aXRoIGEgdHJ1dGh5IHZhbHVlIHRoZSBjb3JyZXNwb25kaW5nIGtleSBpcyB1c2VkIGFzIGEgY2xhc3MgbmFtZS4NCiAqDQogKiBUaGUgZGlyZWN0aXZlIHdvbid0IGFkZCBkdXBsaWNhdGUgY2xhc3NlcyBpZiBhIHBhcnRpY3VsYXIgY2xhc3Mgd2FzIGFscmVhZHkgc2V0Lg0KICoNCiAqIFdoZW4gdGhlIGV4cHJlc3Npb24gY2hhbmdlcywgdGhlIHByZXZpb3VzbHkgYWRkZWQgY2xhc3NlcyBhcmUgcmVtb3ZlZCBhbmQgb25seSB0aGVuIHRoZQ0KICogbmV3IGNsYXNzZXMgYXJlIGFkZGVkLg0KICoNCiAqIEBhbmltYXRpb25zDQogKiBhZGQgLSBoYXBwZW5zIGp1c3QgYmVmb3JlIHRoZSBjbGFzcyBpcyBhcHBsaWVkIHRvIHRoZSBlbGVtZW50DQogKiByZW1vdmUgLSBoYXBwZW5zIGp1c3QgYmVmb3JlIHRoZSBjbGFzcyBpcyByZW1vdmVkIGZyb20gdGhlIGVsZW1lbnQNCiAqDQogKiBAZWxlbWVudCBBTlkNCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdDbGFzcyB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBFeHByZXNzaW9ufSB0byBldmFsLiBUaGUgcmVzdWx0DQogKiAgIG9mIHRoZSBldmFsdWF0aW9uIGNhbiBiZSBhIHN0cmluZyByZXByZXNlbnRpbmcgc3BhY2UgZGVsaW1pdGVkIGNsYXNzDQogKiAgIG5hbWVzLCBhbiBhcnJheSwgb3IgYSBtYXAgb2YgY2xhc3MgbmFtZXMgdG8gYm9vbGVhbiB2YWx1ZXMuIEluIHRoZSBjYXNlIG9mIGEgbWFwLCB0aGUNCiAqICAgbmFtZXMgb2YgdGhlIHByb3BlcnRpZXMgd2hvc2UgdmFsdWVzIGFyZSB0cnV0aHkgd2lsbCBiZSBhZGRlZCBhcyBjc3MgY2xhc3NlcyB0byB0aGUNCiAqICAgZWxlbWVudC4NCiAqDQogKiBAZXhhbXBsZSBFeGFtcGxlIHRoYXQgZGVtb25zdHJhdGVzIGJhc2ljIGJpbmRpbmdzIHZpYSBuZ0NsYXNzIGRpcmVjdGl2ZS4NCiAgIDxleGFtcGxlPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICA8cCBuZy1jbGFzcz0ie3N0cmlrZTogZGVsZXRlZCwgYm9sZDogaW1wb3J0YW50LCByZWQ6IGVycm9yfSI+TWFwIFN5bnRheCBFeGFtcGxlPC9wPg0KICAgICAgIDxpbnB1dCB0eXBlPSJjaGVja2JveCIgbmctbW9kZWw9ImRlbGV0ZWQiPiBkZWxldGVkIChhcHBseSAic3RyaWtlIiBjbGFzcyk8YnI+DQogICAgICAgPGlucHV0IHR5cGU9ImNoZWNrYm94IiBuZy1tb2RlbD0iaW1wb3J0YW50Ij4gaW1wb3J0YW50IChhcHBseSAiYm9sZCIgY2xhc3MpPGJyPg0KICAgICAgIDxpbnB1dCB0eXBlPSJjaGVja2JveCIgbmctbW9kZWw9ImVycm9yIj4gZXJyb3IgKGFwcGx5ICJyZWQiIGNsYXNzKQ0KICAgICAgIDxocj4NCiAgICAgICA8cCBuZy1jbGFzcz0ic3R5bGUiPlVzaW5nIFN0cmluZyBTeW50YXg8L3A+DQogICAgICAgPGlucHV0IHR5cGU9InRleHQiIG5nLW1vZGVsPSJzdHlsZSIgcGxhY2Vob2xkZXI9IlR5cGU6IGJvbGQgc3RyaWtlIHJlZCI+DQogICAgICAgPGhyPg0KICAgICAgIDxwIG5nLWNsYXNzPSJbc3R5bGUxLCBzdHlsZTIsIHN0eWxlM10iPlVzaW5nIEFycmF5IFN5bnRheDwvcD4NCiAgICAgICA8aW5wdXQgbmctbW9kZWw9InN0eWxlMSIgcGxhY2Vob2xkZXI9IlR5cGU6IGJvbGQsIHN0cmlrZSBvciByZWQiPjxicj4NCiAgICAgICA8aW5wdXQgbmctbW9kZWw9InN0eWxlMiIgcGxhY2Vob2xkZXI9IlR5cGU6IGJvbGQsIHN0cmlrZSBvciByZWQiPjxicj4NCiAgICAgICA8aW5wdXQgbmctbW9kZWw9InN0eWxlMyIgcGxhY2Vob2xkZXI9IlR5cGU6IGJvbGQsIHN0cmlrZSBvciByZWQiPjxicj4NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJzdHlsZS5jc3MiPg0KICAgICAgIC5zdHJpa2Ugew0KICAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBsaW5lLXRocm91Z2g7DQogICAgICAgfQ0KICAgICAgIC5ib2xkIHsNCiAgICAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgICAgfQ0KICAgICAgIC5yZWQgew0KICAgICAgICAgICBjb2xvcjogcmVkOw0KICAgICAgIH0NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICB2YXIgcHMgPSBlbGVtZW50LmFsbChieS5jc3MoJ3AnKSk7DQoNCiAgICAgICBpdCgnc2hvdWxkIGxldCB5b3UgdG9nZ2xlIHRoZSBjbGFzcycsIGZ1bmN0aW9uKCkgew0KDQogICAgICAgICBleHBlY3QocHMuZmlyc3QoKS5nZXRBdHRyaWJ1dGUoJ2NsYXNzJykpLm5vdC50b01hdGNoKC9ib2xkLyk7DQogICAgICAgICBleHBlY3QocHMuZmlyc3QoKS5nZXRBdHRyaWJ1dGUoJ2NsYXNzJykpLm5vdC50b01hdGNoKC9yZWQvKTsNCg0KICAgICAgICAgZWxlbWVudChieS5tb2RlbCgnaW1wb3J0YW50JykpLmNsaWNrKCk7DQogICAgICAgICBleHBlY3QocHMuZmlyc3QoKS5nZXRBdHRyaWJ1dGUoJ2NsYXNzJykpLnRvTWF0Y2goL2JvbGQvKTsNCg0KICAgICAgICAgZWxlbWVudChieS5tb2RlbCgnZXJyb3InKSkuY2xpY2soKTsNCiAgICAgICAgIGV4cGVjdChwcy5maXJzdCgpLmdldEF0dHJpYnV0ZSgnY2xhc3MnKSkudG9NYXRjaCgvcmVkLyk7DQogICAgICAgfSk7DQoNCiAgICAgICBpdCgnc2hvdWxkIGxldCB5b3UgdG9nZ2xlIHN0cmluZyBleGFtcGxlJywgZnVuY3Rpb24oKSB7DQogICAgICAgICBleHBlY3QocHMuZ2V0KDEpLmdldEF0dHJpYnV0ZSgnY2xhc3MnKSkudG9CZSgnJyk7DQogICAgICAgICBlbGVtZW50KGJ5Lm1vZGVsKCdzdHlsZScpKS5jbGVhcigpOw0KICAgICAgICAgZWxlbWVudChieS5tb2RlbCgnc3R5bGUnKSkuc2VuZEtleXMoJ3JlZCcpOw0KICAgICAgICAgZXhwZWN0KHBzLmdldCgxKS5nZXRBdHRyaWJ1dGUoJ2NsYXNzJykpLnRvQmUoJ3JlZCcpOw0KICAgICAgIH0pOw0KDQogICAgICAgaXQoJ2FycmF5IGV4YW1wbGUgc2hvdWxkIGhhdmUgMyBjbGFzc2VzJywgZnVuY3Rpb24oKSB7DQogICAgICAgICBleHBlY3QocHMubGFzdCgpLmdldEF0dHJpYnV0ZSgnY2xhc3MnKSkudG9CZSgnJyk7DQogICAgICAgICBlbGVtZW50KGJ5Lm1vZGVsKCdzdHlsZTEnKSkuc2VuZEtleXMoJ2JvbGQnKTsNCiAgICAgICAgIGVsZW1lbnQoYnkubW9kZWwoJ3N0eWxlMicpKS5zZW5kS2V5cygnc3RyaWtlJyk7DQogICAgICAgICBlbGVtZW50KGJ5Lm1vZGVsKCdzdHlsZTMnKSkuc2VuZEtleXMoJ3JlZCcpOw0KICAgICAgICAgZXhwZWN0KHBzLmxhc3QoKS5nZXRBdHRyaWJ1dGUoJ2NsYXNzJykpLnRvQmUoJ2JvbGQgc3RyaWtlIHJlZCcpOw0KICAgICAgIH0pOw0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQoNCiAgICMjIEFuaW1hdGlvbnMNCg0KICAgVGhlIGV4YW1wbGUgYmVsb3cgZGVtb25zdHJhdGVzIGhvdyB0byBwZXJmb3JtIGFuaW1hdGlvbnMgdXNpbmcgbmdDbGFzcy4NCg0KICAgPGV4YW1wbGUgbW9kdWxlPSJuZ0FuaW1hdGUiIGRlcHM9ImFuZ3VsYXItYW5pbWF0ZS5qcyIgYW5pbWF0aW9ucz0idHJ1ZSI+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgPGlucHV0IGlkPSJzZXRidG4iIHR5cGU9ImJ1dHRvbiIgdmFsdWU9InNldCIgbmctY2xpY2s9Im15VmFyPSdteS1jbGFzcyciPg0KICAgICAgPGlucHV0IGlkPSJjbGVhcmJ0biIgdHlwZT0iYnV0dG9uIiB2YWx1ZT0iY2xlYXIiIG5nLWNsaWNrPSJteVZhcj0nJyI+DQogICAgICA8YnI+DQogICAgICA8c3BhbiBjbGFzcz0iYmFzZS1jbGFzcyIgbmctY2xhc3M9Im15VmFyIj5TYW1wbGUgVGV4dDwvc3Bhbj4NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJzdHlsZS5jc3MiPg0KICAgICAgIC5iYXNlLWNsYXNzIHsNCiAgICAgICAgIC13ZWJraXQtdHJhbnNpdGlvbjphbGwgY3ViaWMtYmV6aWVyKDAuMjUwLCAwLjQ2MCwgMC40NTAsIDAuOTQwKSAwLjVzOw0KICAgICAgICAgdHJhbnNpdGlvbjphbGwgY3ViaWMtYmV6aWVyKDAuMjUwLCAwLjQ2MCwgMC40NTAsIDAuOTQwKSAwLjVzOw0KICAgICAgIH0NCg0KICAgICAgIC5iYXNlLWNsYXNzLm15LWNsYXNzIHsNCiAgICAgICAgIGNvbG9yOiByZWQ7DQogICAgICAgICBmb250LXNpemU6M2VtOw0KICAgICAgIH0NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICBpdCgnc2hvdWxkIGNoZWNrIG5nLWNsYXNzJywgZnVuY3Rpb24oKSB7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5jc3MoJy5iYXNlLWNsYXNzJykpLmdldEF0dHJpYnV0ZSgnY2xhc3MnKSkubm90Lg0KICAgICAgICAgICB0b01hdGNoKC9teS1jbGFzcy8pOw0KDQogICAgICAgICBlbGVtZW50KGJ5LmlkKCdzZXRidG4nKSkuY2xpY2soKTsNCg0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuY3NzKCcuYmFzZS1jbGFzcycpKS5nZXRBdHRyaWJ1dGUoJ2NsYXNzJykpLg0KICAgICAgICAgICB0b01hdGNoKC9teS1jbGFzcy8pOw0KDQogICAgICAgICBlbGVtZW50KGJ5LmlkKCdjbGVhcmJ0bicpKS5jbGljaygpOw0KDQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5jc3MoJy5iYXNlLWNsYXNzJykpLmdldEF0dHJpYnV0ZSgnY2xhc3MnKSkubm90Lg0KICAgICAgICAgICB0b01hdGNoKC9teS1jbGFzcy8pOw0KICAgICAgIH0pOw0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQoNCg0KICAgIyMgbmdDbGFzcyBhbmQgcHJlLWV4aXN0aW5nIENTUzMgVHJhbnNpdGlvbnMvQW5pbWF0aW9ucw0KICAgVGhlIG5nQ2xhc3MgZGlyZWN0aXZlIHN0aWxsIHN1cHBvcnRzIENTUzMgVHJhbnNpdGlvbnMvQW5pbWF0aW9ucyBldmVuIGlmIHRoZXkgZG8gbm90IGZvbGxvdyB0aGUgbmdBbmltYXRlIENTUyBuYW1pbmcgc3RydWN0dXJlLg0KICAgVXBvbiBhbmltYXRpb24gbmdBbmltYXRlIHdpbGwgYXBwbHkgc3VwcGxlbWVudGFyeSBDU1MgY2xhc3NlcyB0byB0cmFjayB0aGUgc3RhcnQgYW5kIGVuZCBvZiBhbiBhbmltYXRpb24sIGJ1dCB0aGlzIHdpbGwgbm90IGhpbmRlcg0KICAgYW55IHByZS1leGlzdGluZyBDU1MgdHJhbnNpdGlvbnMgYWxyZWFkeSBvbiB0aGUgZWxlbWVudC4gVG8gZ2V0IGFuIGlkZWEgb2Ygd2hhdCBoYXBwZW5zIGR1cmluZyBhIGNsYXNzLWJhc2VkIGFuaW1hdGlvbiwgYmUgc3VyZQ0KICAgdG8gdmlldyB0aGUgc3RlcCBieSBzdGVwIGRldGFpbHMgb2Yge0BsaW5rIG5nLiRhbmltYXRlI2FkZENsYXNzICRhbmltYXRlLmFkZENsYXNzfSBhbmQNCiAgIHtAbGluayBuZy4kYW5pbWF0ZSNyZW1vdmVDbGFzcyAkYW5pbWF0ZS5yZW1vdmVDbGFzc30uDQogKi8NCnZhciBuZ0NsYXNzRGlyZWN0aXZlID0gY2xhc3NEaXJlY3RpdmUoJycsIHRydWUpOw0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nQ2xhc3NPZGQNCiAqIEByZXN0cmljdCBBQw0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlIGBuZ0NsYXNzT2RkYCBhbmQgYG5nQ2xhc3NFdmVuYCBkaXJlY3RpdmVzIHdvcmsgZXhhY3RseSBhcw0KICoge0BsaW5rIG5nLmRpcmVjdGl2ZTpuZ0NsYXNzIG5nQ2xhc3N9LCBleGNlcHQgdGhleSB3b3JrIGluDQogKiBjb25qdW5jdGlvbiB3aXRoIGBuZ1JlcGVhdGAgYW5kIHRha2UgZWZmZWN0IG9ubHkgb24gb2RkIChldmVuKSByb3dzLg0KICoNCiAqIFRoaXMgZGlyZWN0aXZlIGNhbiBiZSBhcHBsaWVkIG9ubHkgd2l0aGluIHRoZSBzY29wZSBvZiBhbg0KICoge0BsaW5rIG5nLmRpcmVjdGl2ZTpuZ1JlcGVhdCBuZ1JlcGVhdH0uDQogKg0KICogQGVsZW1lbnQgQU5ZDQogKiBAcGFyYW0ge2V4cHJlc3Npb259IG5nQ2xhc3NPZGQge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gRXhwcmVzc2lvbn0gdG8gZXZhbC4gVGhlIHJlc3VsdA0KICogICBvZiB0aGUgZXZhbHVhdGlvbiBjYW4gYmUgYSBzdHJpbmcgcmVwcmVzZW50aW5nIHNwYWNlIGRlbGltaXRlZCBjbGFzcyBuYW1lcyBvciBhbiBhcnJheS4NCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGU+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgICA8b2wgbmctaW5pdD0ibmFtZXM9WydKb2huJywgJ01hcnknLCAnQ2F0ZScsICdTdXonXSI+DQogICAgICAgICAgPGxpIG5nLXJlcGVhdD0ibmFtZSBpbiBuYW1lcyI+DQogICAgICAgICAgIDxzcGFuIG5nLWNsYXNzLW9kZD0iJ29kZCciIG5nLWNsYXNzLWV2ZW49IidldmVuJyI+DQogICAgICAgICAgICAge3tuYW1lfX0NCiAgICAgICAgICAgPC9zcGFuPg0KICAgICAgICAgIDwvbGk+DQogICAgICAgIDwvb2w+DQogICAgIDwvZmlsZT4NCiAgICAgPGZpbGUgbmFtZT0ic3R5bGUuY3NzIj4NCiAgICAgICAub2RkIHsNCiAgICAgICAgIGNvbG9yOiByZWQ7DQogICAgICAgfQ0KICAgICAgIC5ldmVuIHsNCiAgICAgICAgIGNvbG9yOiBibHVlOw0KICAgICAgIH0NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICBpdCgnc2hvdWxkIGNoZWNrIG5nLWNsYXNzLW9kZCBhbmQgbmctY2xhc3MtZXZlbicsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkucmVwZWF0ZXIoJ25hbWUgaW4gbmFtZXMnKS5yb3coMCkuY29sdW1uKCduYW1lJykpLmdldEF0dHJpYnV0ZSgnY2xhc3MnKSkuDQogICAgICAgICAgIHRvTWF0Y2goL29kZC8pOw0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkucmVwZWF0ZXIoJ25hbWUgaW4gbmFtZXMnKS5yb3coMSkuY29sdW1uKCduYW1lJykpLmdldEF0dHJpYnV0ZSgnY2xhc3MnKSkuDQogICAgICAgICAgIHRvTWF0Y2goL2V2ZW4vKTsNCiAgICAgICB9KTsNCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICovDQp2YXIgbmdDbGFzc09kZERpcmVjdGl2ZSA9IGNsYXNzRGlyZWN0aXZlKCdPZGQnLCAwKTsNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0NsYXNzRXZlbg0KICogQHJlc3RyaWN0IEFDDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBUaGUgYG5nQ2xhc3NPZGRgIGFuZCBgbmdDbGFzc0V2ZW5gIGRpcmVjdGl2ZXMgd29yayBleGFjdGx5IGFzDQogKiB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nQ2xhc3MgbmdDbGFzc30sIGV4Y2VwdCB0aGV5IHdvcmsgaW4NCiAqIGNvbmp1bmN0aW9uIHdpdGggYG5nUmVwZWF0YCBhbmQgdGFrZSBlZmZlY3Qgb25seSBvbiBvZGQgKGV2ZW4pIHJvd3MuDQogKg0KICogVGhpcyBkaXJlY3RpdmUgY2FuIGJlIGFwcGxpZWQgb25seSB3aXRoaW4gdGhlIHNjb3BlIG9mIGFuDQogKiB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nUmVwZWF0IG5nUmVwZWF0fS4NCiAqDQogKiBAZWxlbWVudCBBTlkNCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdDbGFzc0V2ZW4ge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gRXhwcmVzc2lvbn0gdG8gZXZhbC4gVGhlDQogKiAgIHJlc3VsdCBvZiB0aGUgZXZhbHVhdGlvbiBjYW4gYmUgYSBzdHJpbmcgcmVwcmVzZW50aW5nIHNwYWNlIGRlbGltaXRlZCBjbGFzcyBuYW1lcyBvciBhbiBhcnJheS4NCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGU+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgICA8b2wgbmctaW5pdD0ibmFtZXM9WydKb2huJywgJ01hcnknLCAnQ2F0ZScsICdTdXonXSI+DQogICAgICAgICAgPGxpIG5nLXJlcGVhdD0ibmFtZSBpbiBuYW1lcyI+DQogICAgICAgICAgIDxzcGFuIG5nLWNsYXNzLW9kZD0iJ29kZCciIG5nLWNsYXNzLWV2ZW49IidldmVuJyI+DQogICAgICAgICAgICAge3tuYW1lfX0gJm5ic3A7ICZuYnNwOyAmbmJzcDsNCiAgICAgICAgICAgPC9zcGFuPg0KICAgICAgICAgIDwvbGk+DQogICAgICAgIDwvb2w+DQogICAgIDwvZmlsZT4NCiAgICAgPGZpbGUgbmFtZT0ic3R5bGUuY3NzIj4NCiAgICAgICAub2RkIHsNCiAgICAgICAgIGNvbG9yOiByZWQ7DQogICAgICAgfQ0KICAgICAgIC5ldmVuIHsNCiAgICAgICAgIGNvbG9yOiBibHVlOw0KICAgICAgIH0NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICBpdCgnc2hvdWxkIGNoZWNrIG5nLWNsYXNzLW9kZCBhbmQgbmctY2xhc3MtZXZlbicsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkucmVwZWF0ZXIoJ25hbWUgaW4gbmFtZXMnKS5yb3coMCkuY29sdW1uKCduYW1lJykpLmdldEF0dHJpYnV0ZSgnY2xhc3MnKSkuDQogICAgICAgICAgIHRvTWF0Y2goL29kZC8pOw0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkucmVwZWF0ZXIoJ25hbWUgaW4gbmFtZXMnKS5yb3coMSkuY29sdW1uKCduYW1lJykpLmdldEF0dHJpYnV0ZSgnY2xhc3MnKSkuDQogICAgICAgICAgIHRvTWF0Y2goL2V2ZW4vKTsNCiAgICAgICB9KTsNCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICovDQp2YXIgbmdDbGFzc0V2ZW5EaXJlY3RpdmUgPSBjbGFzc0RpcmVjdGl2ZSgnRXZlbicsIDEpOw0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nQ2xvYWsNCiAqIEByZXN0cmljdCBBQw0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlIGBuZ0Nsb2FrYCBkaXJlY3RpdmUgaXMgdXNlZCB0byBwcmV2ZW50IHRoZSBBbmd1bGFyIGh0bWwgdGVtcGxhdGUgZnJvbSBiZWluZyBicmllZmx5DQogKiBkaXNwbGF5ZWQgYnkgdGhlIGJyb3dzZXIgaW4gaXRzIHJhdyAodW5jb21waWxlZCkgZm9ybSB3aGlsZSB5b3VyIGFwcGxpY2F0aW9uIGlzIGxvYWRpbmcuIFVzZSB0aGlzDQogKiBkaXJlY3RpdmUgdG8gYXZvaWQgdGhlIHVuZGVzaXJhYmxlIGZsaWNrZXIgZWZmZWN0IGNhdXNlZCBieSB0aGUgaHRtbCB0ZW1wbGF0ZSBkaXNwbGF5Lg0KICoNCiAqIFRoZSBkaXJlY3RpdmUgY2FuIGJlIGFwcGxpZWQgdG8gdGhlIGA8Ym9keT5gIGVsZW1lbnQsIGJ1dCB0aGUgcHJlZmVycmVkIHVzYWdlIGlzIHRvIGFwcGx5DQogKiBtdWx0aXBsZSBgbmdDbG9ha2AgZGlyZWN0aXZlcyB0byBzbWFsbCBwb3J0aW9ucyBvZiB0aGUgcGFnZSB0byBwZXJtaXQgcHJvZ3Jlc3NpdmUgcmVuZGVyaW5nDQogKiBvZiB0aGUgYnJvd3NlciB2aWV3Lg0KICoNCiAqIGBuZ0Nsb2FrYCB3b3JrcyBpbiBjb29wZXJhdGlvbiB3aXRoIHRoZSBmb2xsb3dpbmcgY3NzIHJ1bGUgZW1iZWRkZWQgd2l0aGluIGBhbmd1bGFyLmpzYCBhbmQNCiAqIGBhbmd1bGFyLm1pbi5qc2AuDQogKiBGb3IgQ1NQIG1vZGUgcGxlYXNlIGFkZCBgYW5ndWxhci1jc3AuY3NzYCB0byB5b3VyIGh0bWwgZmlsZSAoc2VlIHtAbGluayBuZy5kaXJlY3RpdmU6bmdDc3AgbmdDc3B9KS4NCiAqDQogKiBgYGBjc3MNCiAqIFtuZ1w6Y2xvYWtdLCBbbmctY2xvYWtdLCBbZGF0YS1uZy1jbG9ha10sIFt4LW5nLWNsb2FrXSwgLm5nLWNsb2FrLCAueC1uZy1jbG9hayB7DQogKiAgIGRpc3BsYXk6IG5vbmUgIWltcG9ydGFudDsNCiAqIH0NCiAqIGBgYA0KICoNCiAqIFdoZW4gdGhpcyBjc3MgcnVsZSBpcyBsb2FkZWQgYnkgdGhlIGJyb3dzZXIsIGFsbCBodG1sIGVsZW1lbnRzIChpbmNsdWRpbmcgdGhlaXIgY2hpbGRyZW4pIHRoYXQNCiAqIGFyZSB0YWdnZWQgd2l0aCB0aGUgYG5nQ2xvYWtgIGRpcmVjdGl2ZSBhcmUgaGlkZGVuLiBXaGVuIEFuZ3VsYXIgZW5jb3VudGVycyB0aGlzIGRpcmVjdGl2ZQ0KICogZHVyaW5nIHRoZSBjb21waWxhdGlvbiBvZiB0aGUgdGVtcGxhdGUgaXQgZGVsZXRlcyB0aGUgYG5nQ2xvYWtgIGVsZW1lbnQgYXR0cmlidXRlLCBtYWtpbmcNCiAqIHRoZSBjb21waWxlZCBlbGVtZW50IHZpc2libGUuDQogKg0KICogRm9yIHRoZSBiZXN0IHJlc3VsdCwgdGhlIGBhbmd1bGFyLmpzYCBzY3JpcHQgbXVzdCBiZSBsb2FkZWQgaW4gdGhlIGhlYWQgc2VjdGlvbiBvZiB0aGUgaHRtbA0KICogZG9jdW1lbnQ7IGFsdGVybmF0aXZlbHksIHRoZSBjc3MgcnVsZSBhYm92ZSBtdXN0IGJlIGluY2x1ZGVkIGluIHRoZSBleHRlcm5hbCBzdHlsZXNoZWV0IG9mIHRoZQ0KICogYXBwbGljYXRpb24uDQogKg0KICogTGVnYWN5IGJyb3dzZXJzLCBsaWtlIElFNywgZG8gbm90IHByb3ZpZGUgYXR0cmlidXRlIHNlbGVjdG9yIHN1cHBvcnQgKGFkZGVkIGluIENTUyAyLjEpIHNvIHRoZXkNCiAqIGNhbm5vdCBtYXRjaCB0aGUgYFtuZ1w6Y2xvYWtdYCBzZWxlY3Rvci4gVG8gd29yayBhcm91bmQgdGhpcyBsaW1pdGF0aW9uLCB5b3UgbXVzdCBhZGQgdGhlIGNzcw0KICogY2xhc3MgYG5nLWNsb2FrYCBpbiBhZGRpdGlvbiB0byB0aGUgYG5nQ2xvYWtgIGRpcmVjdGl2ZSBhcyBzaG93biBpbiB0aGUgZXhhbXBsZSBiZWxvdy4NCiAqDQogKiBAZWxlbWVudCBBTlkNCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGU+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgICA8ZGl2IGlkPSJ0ZW1wbGF0ZTEiIG5nLWNsb2FrPnt7ICdoZWxsbycgfX08L2Rpdj4NCiAgICAgICAgPGRpdiBpZD0idGVtcGxhdGUyIiBuZy1jbG9hayBjbGFzcz0ibmctY2xvYWsiPnt7ICdoZWxsbyBJRTcnIH19PC9kaXY+DQogICAgIDwvZmlsZT4NCiAgICAgPGZpbGUgbmFtZT0icHJvdHJhY3Rvci5qcyIgdHlwZT0icHJvdHJhY3RvciI+DQogICAgICAgaXQoJ3Nob3VsZCByZW1vdmUgdGhlIHRlbXBsYXRlIGRpcmVjdGl2ZSBhbmQgY3NzIGNsYXNzJywgZnVuY3Rpb24oKSB7DQogICAgICAgICBleHBlY3QoJCgnI3RlbXBsYXRlMScpLmdldEF0dHJpYnV0ZSgnbmctY2xvYWsnKSkuDQogICAgICAgICAgIHRvQmVOdWxsKCk7DQogICAgICAgICBleHBlY3QoJCgnI3RlbXBsYXRlMicpLmdldEF0dHJpYnV0ZSgnbmctY2xvYWsnKSkuDQogICAgICAgICAgIHRvQmVOdWxsKCk7DQogICAgICAgfSk7DQogICAgIDwvZmlsZT4NCiAgIDwvZXhhbXBsZT4NCiAqDQogKi8NCnZhciBuZ0Nsb2FrRGlyZWN0aXZlID0gbmdEaXJlY3RpdmUoew0KICBjb21waWxlOiBmdW5jdGlvbihlbGVtZW50LCBhdHRyKSB7DQogICAgYXR0ci4kc2V0KCduZ0Nsb2FrJywgdW5kZWZpbmVkKTsNCiAgICBlbGVtZW50LnJlbW92ZUNsYXNzKCduZy1jbG9haycpOw0KICB9DQp9KTsNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0NvbnRyb2xsZXINCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFRoZSBgbmdDb250cm9sbGVyYCBkaXJlY3RpdmUgYXR0YWNoZXMgYSBjb250cm9sbGVyIGNsYXNzIHRvIHRoZSB2aWV3LiBUaGlzIGlzIGEga2V5IGFzcGVjdCBvZiBob3cgYW5ndWxhcg0KICogc3VwcG9ydHMgdGhlIHByaW5jaXBsZXMgYmVoaW5kIHRoZSBNb2RlbC1WaWV3LUNvbnRyb2xsZXIgZGVzaWduIHBhdHRlcm4uDQogKg0KICogTVZDIGNvbXBvbmVudHMgaW4gYW5ndWxhcjoNCiAqDQogKiAqIE1vZGVsIOKAPyBNb2RlbHMgYXJlIHRoZSBwcm9wZXJ0aWVzIG9mIGEgc2NvcGU7IHNjb3BlcyBhcmUgYXR0YWNoZWQgdG8gdGhlIERPTSB3aGVyZSBzY29wZSBwcm9wZXJ0aWVzDQogKiAgIGFyZSBhY2Nlc3NlZCB0aHJvdWdoIGJpbmRpbmdzLg0KICogKiBWaWV3IOKAPyBUaGUgdGVtcGxhdGUgKEhUTUwgd2l0aCBkYXRhIGJpbmRpbmdzKSB0aGF0IGlzIHJlbmRlcmVkIGludG8gdGhlIFZpZXcuDQogKiAqIENvbnRyb2xsZXIg4oA/IFRoZSBgbmdDb250cm9sbGVyYCBkaXJlY3RpdmUgc3BlY2lmaWVzIGEgQ29udHJvbGxlciBjbGFzczsgdGhlIGNsYXNzIGNvbnRhaW5zIGJ1c2luZXNzDQogKiAgIGxvZ2ljIGJlaGluZCB0aGUgYXBwbGljYXRpb24gdG8gZGVjb3JhdGUgdGhlIHNjb3BlIHdpdGggZnVuY3Rpb25zIGFuZCB2YWx1ZXMNCiAqDQogKiBOb3RlIHRoYXQgeW91IGNhbiBhbHNvIGF0dGFjaCBjb250cm9sbGVycyB0byB0aGUgRE9NIGJ5IGRlY2xhcmluZyBpdCBpbiBhIHJvdXRlIGRlZmluaXRpb24NCiAqIHZpYSB0aGUge0BsaW5rIG5nUm91dGUuJHJvdXRlICRyb3V0ZX0gc2VydmljZS4gQSBjb21tb24gbWlzdGFrZSBpcyB0byBkZWNsYXJlIHRoZSBjb250cm9sbGVyDQogKiBhZ2FpbiB1c2luZyBgbmctY29udHJvbGxlcmAgaW4gdGhlIHRlbXBsYXRlIGl0c2VsZi4gIFRoaXMgd2lsbCBjYXVzZSB0aGUgY29udHJvbGxlciB0byBiZSBhdHRhY2hlZA0KICogYW5kIGV4ZWN1dGVkIHR3aWNlLg0KICoNCiAqIEBlbGVtZW50IEFOWQ0KICogQHNjb3BlDQogKiBAcHJpb3JpdHkgNTAwDQogKiBAcGFyYW0ge2V4cHJlc3Npb259IG5nQ29udHJvbGxlciBOYW1lIG9mIGEgY29uc3RydWN0b3IgZnVuY3Rpb24gcmVnaXN0ZXJlZCB3aXRoIHRoZSBjdXJyZW50DQogKiB7QGxpbmsgbmcuJGNvbnRyb2xsZXJQcm92aWRlciAkY29udHJvbGxlclByb3ZpZGVyfSBvciBhbiB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBleHByZXNzaW9ufQ0KICogdGhhdCBvbiB0aGUgY3VycmVudCBzY29wZSBldmFsdWF0ZXMgdG8gYSBjb25zdHJ1Y3RvciBmdW5jdGlvbi4NCiAqDQogKiBUaGUgY29udHJvbGxlciBpbnN0YW5jZSBjYW4gYmUgcHVibGlzaGVkIGludG8gYSBzY29wZSBwcm9wZXJ0eSBieSBzcGVjaWZ5aW5nDQogKiBgbmctY29udHJvbGxlcj0iYXMgcHJvcGVydHlOYW1lImAuDQogKg0KICogSWYgdGhlIGN1cnJlbnQgYCRjb250cm9sbGVyUHJvdmlkZXJgIGlzIGNvbmZpZ3VyZWQgdG8gdXNlIGdsb2JhbHMgKHZpYQ0KICoge0BsaW5rIG5nLiRjb250cm9sbGVyUHJvdmlkZXIjYWxsb3dHbG9iYWxzIGAkY29udHJvbGxlclByb3ZpZGVyLmFsbG93R2xvYmFscygpYCB9KSwgdGhpcyBtYXkNCiAqIGFsc28gYmUgdGhlIG5hbWUgb2YgYSBnbG9iYWxseSBhY2Nlc3NpYmxlIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIChub3QgcmVjb21tZW5kZWQpLg0KICoNCiAqIEBleGFtcGxlDQogKiBIZXJlIGlzIGEgc2ltcGxlIGZvcm0gZm9yIGVkaXRpbmcgdXNlciBjb250YWN0IGluZm9ybWF0aW9uLiBBZGRpbmcsIHJlbW92aW5nLCBjbGVhcmluZywgYW5kDQogKiBncmVldGluZyBhcmUgbWV0aG9kcyBkZWNsYXJlZCBvbiB0aGUgY29udHJvbGxlciAoc2VlIHNvdXJjZSB0YWIpLiBUaGVzZSBtZXRob2RzIGNhbg0KICogZWFzaWx5IGJlIGNhbGxlZCBmcm9tIHRoZSBhbmd1bGFyIG1hcmt1cC4gQW55IGNoYW5nZXMgdG8gdGhlIGRhdGEgYXJlIGF1dG9tYXRpY2FsbHkgcmVmbGVjdGVkDQogKiBpbiB0aGUgVmlldyB3aXRob3V0IHRoZSBuZWVkIGZvciBhIG1hbnVhbCB1cGRhdGUuDQogKg0KICogVHdvIGRpZmZlcmVudCBkZWNsYXJhdGlvbiBzdHlsZXMgYXJlIGluY2x1ZGVkIGJlbG93Og0KICoNCiAqICogb25lIGJpbmRzIG1ldGhvZHMgYW5kIHByb3BlcnRpZXMgZGlyZWN0bHkgb250byB0aGUgY29udHJvbGxlciB1c2luZyBgdGhpc2A6DQogKiBgbmctY29udHJvbGxlcj0iU2V0dGluZ3NDb250cm9sbGVyMSBhcyBzZXR0aW5ncyJgDQogKiAqIG9uZSBpbmplY3RzIGAkc2NvcGVgIGludG8gdGhlIGNvbnRyb2xsZXI6DQogKiBgbmctY29udHJvbGxlcj0iU2V0dGluZ3NDb250cm9sbGVyMiJgDQogKg0KICogVGhlIHNlY29uZCBvcHRpb24gaXMgbW9yZSBjb21tb24gaW4gdGhlIEFuZ3VsYXIgY29tbXVuaXR5LCBhbmQgaXMgZ2VuZXJhbGx5IHVzZWQgaW4gYm9pbGVycGxhdGVzDQogKiBhbmQgaW4gdGhpcyBndWlkZS4gSG93ZXZlciwgdGhlcmUgYXJlIGFkdmFudGFnZXMgdG8gYmluZGluZyBwcm9wZXJ0aWVzIGRpcmVjdGx5IHRvIHRoZSBjb250cm9sbGVyDQogKiBhbmQgYXZvaWRpbmcgc2NvcGUuDQogKg0KICogKiBVc2luZyBgY29udHJvbGxlciBhc2AgbWFrZXMgaXQgb2J2aW91cyB3aGljaCBjb250cm9sbGVyIHlvdSBhcmUgYWNjZXNzaW5nIGluIHRoZSB0ZW1wbGF0ZSB3aGVuDQogKiBtdWx0aXBsZSBjb250cm9sbGVycyBhcHBseSB0byBhbiBlbGVtZW50Lg0KICogKiBJZiB5b3UgYXJlIHdyaXRpbmcgeW91ciBjb250cm9sbGVycyBhcyBjbGFzc2VzIHlvdSBoYXZlIGVhc2llciBhY2Nlc3MgdG8gdGhlIHByb3BlcnRpZXMgYW5kDQogKiBtZXRob2RzLCB3aGljaCB3aWxsIGFwcGVhciBvbiB0aGUgc2NvcGUsIGZyb20gaW5zaWRlIHRoZSBjb250cm9sbGVyIGNvZGUuDQogKiAqIFNpbmNlIHRoZXJlIGlzIGFsd2F5cyBhIGAuYCBpbiB0aGUgYmluZGluZ3MsIHlvdSBkb24ndCBoYXZlIHRvIHdvcnJ5IGFib3V0IHByb3RvdHlwYWwNCiAqIGluaGVyaXRhbmNlIG1hc2tpbmcgcHJpbWl0aXZlcy4NCiAqDQogKiBUaGlzIGV4YW1wbGUgZGVtb25zdHJhdGVzIHRoZSBgY29udHJvbGxlciBhc2Agc3ludGF4Lg0KICoNCiAqIDxleGFtcGxlIG5hbWU9Im5nQ29udHJvbGxlckFzIiBtb2R1bGU9ImNvbnRyb2xsZXJBc0V4YW1wbGUiPg0KICogICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAqICAgIDxkaXYgaWQ9ImN0cmwtYXMtZXhtcGwiIG5nLWNvbnRyb2xsZXI9IlNldHRpbmdzQ29udHJvbGxlcjEgYXMgc2V0dGluZ3MiPg0KICogICAgICBOYW1lOiA8aW5wdXQgdHlwZT0idGV4dCIgbmctbW9kZWw9InNldHRpbmdzLm5hbWUiLz4NCiAqICAgICAgWyA8YSBocmVmPSIiIG5nLWNsaWNrPSJzZXR0aW5ncy5ncmVldCgpIj5ncmVldDwvYT4gXTxici8+DQogKiAgICAgIENvbnRhY3Q6DQogKiAgICAgIDx1bD4NCiAqICAgICAgICA8bGkgbmctcmVwZWF0PSJjb250YWN0IGluIHNldHRpbmdzLmNvbnRhY3RzIj4NCiAqICAgICAgICAgIDxzZWxlY3QgbmctbW9kZWw9ImNvbnRhY3QudHlwZSI+DQogKiAgICAgICAgICAgICA8b3B0aW9uPnBob25lPC9vcHRpb24+DQogKiAgICAgICAgICAgICA8b3B0aW9uPmVtYWlsPC9vcHRpb24+DQogKiAgICAgICAgICA8L3NlbGVjdD4NCiAqICAgICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBuZy1tb2RlbD0iY29udGFjdC52YWx1ZSIvPg0KICogICAgICAgICAgWyA8YSBocmVmPSIiIG5nLWNsaWNrPSJzZXR0aW5ncy5jbGVhckNvbnRhY3QoY29udGFjdCkiPmNsZWFyPC9hPg0KICogICAgICAgICAgfCA8YSBocmVmPSIiIG5nLWNsaWNrPSJzZXR0aW5ncy5yZW1vdmVDb250YWN0KGNvbnRhY3QpIj5YPC9hPiBdDQogKiAgICAgICAgPC9saT4NCiAqICAgICAgICA8bGk+WyA8YSBocmVmPSIiIG5nLWNsaWNrPSJzZXR0aW5ncy5hZGRDb250YWN0KCkiPmFkZDwvYT4gXTwvbGk+DQogKiAgICAgPC91bD4NCiAqICAgIDwvZGl2Pg0KICogICA8L2ZpbGU+DQogKiAgIDxmaWxlIG5hbWU9ImFwcC5qcyI+DQogKiAgICBhbmd1bGFyLm1vZHVsZSgnY29udHJvbGxlckFzRXhhbXBsZScsIFtdKQ0KICogICAgICAuY29udHJvbGxlcignU2V0dGluZ3NDb250cm9sbGVyMScsIFNldHRpbmdzQ29udHJvbGxlcjEpOw0KICoNCiAqICAgIGZ1bmN0aW9uIFNldHRpbmdzQ29udHJvbGxlcjEoKSB7DQogKiAgICAgIHRoaXMubmFtZSA9ICJKb2huIFNtaXRoIjsNCiAqICAgICAgdGhpcy5jb250YWN0cyA9IFsNCiAqICAgICAgICB7dHlwZTogJ3Bob25lJywgdmFsdWU6ICc0MDggNTU1IDEyMTInfSwNCiAqICAgICAgICB7dHlwZTogJ2VtYWlsJywgdmFsdWU6ICdqb2huLnNtaXRoQGV4YW1wbGUub3JnJ30gXTsNCiAqICAgIH0NCiAqDQogKiAgICBTZXR0aW5nc0NvbnRyb2xsZXIxLnByb3RvdHlwZS5ncmVldCA9IGZ1bmN0aW9uKCkgew0KICogICAgICBhbGVydCh0aGlzLm5hbWUpOw0KICogICAgfTsNCiAqDQogKiAgICBTZXR0aW5nc0NvbnRyb2xsZXIxLnByb3RvdHlwZS5hZGRDb250YWN0ID0gZnVuY3Rpb24oKSB7DQogKiAgICAgIHRoaXMuY29udGFjdHMucHVzaCh7dHlwZTogJ2VtYWlsJywgdmFsdWU6ICd5b3VybmFtZUBleGFtcGxlLm9yZyd9KTsNCiAqICAgIH07DQogKg0KICogICAgU2V0dGluZ3NDb250cm9sbGVyMS5wcm90b3R5cGUucmVtb3ZlQ29udGFjdCA9IGZ1bmN0aW9uKGNvbnRhY3RUb1JlbW92ZSkgew0KICogICAgIHZhciBpbmRleCA9IHRoaXMuY29udGFjdHMuaW5kZXhPZihjb250YWN0VG9SZW1vdmUpOw0KICogICAgICB0aGlzLmNvbnRhY3RzLnNwbGljZShpbmRleCwgMSk7DQogKiAgICB9Ow0KICoNCiAqICAgIFNldHRpbmdzQ29udHJvbGxlcjEucHJvdG90eXBlLmNsZWFyQ29udGFjdCA9IGZ1bmN0aW9uKGNvbnRhY3QpIHsNCiAqICAgICAgY29udGFjdC50eXBlID0gJ3Bob25lJzsNCiAqICAgICAgY29udGFjdC52YWx1ZSA9ICcnOw0KICogICAgfTsNCiAqICAgPC9maWxlPg0KICogICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAqICAgICBpdCgnc2hvdWxkIGNoZWNrIGNvbnRyb2xsZXIgYXMnLCBmdW5jdGlvbigpIHsNCiAqICAgICAgIHZhciBjb250YWluZXIgPSBlbGVtZW50KGJ5LmlkKCdjdHJsLWFzLWV4bXBsJykpOw0KICogICAgICAgICBleHBlY3QoY29udGFpbmVyLmVsZW1lbnQoYnkubW9kZWwoJ3NldHRpbmdzLm5hbWUnKSkNCiAqICAgICAgICAgICAuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKS50b0JlKCdKb2huIFNtaXRoJyk7DQogKg0KICogICAgICAgdmFyIGZpcnN0UmVwZWF0ID0NCiAqICAgICAgICAgICBjb250YWluZXIuZWxlbWVudChieS5yZXBlYXRlcignY29udGFjdCBpbiBzZXR0aW5ncy5jb250YWN0cycpLnJvdygwKSk7DQogKiAgICAgICB2YXIgc2Vjb25kUmVwZWF0ID0NCiAqICAgICAgICAgICBjb250YWluZXIuZWxlbWVudChieS5yZXBlYXRlcignY29udGFjdCBpbiBzZXR0aW5ncy5jb250YWN0cycpLnJvdygxKSk7DQogKg0KICogICAgICAgZXhwZWN0KGZpcnN0UmVwZWF0LmVsZW1lbnQoYnkubW9kZWwoJ2NvbnRhY3QudmFsdWUnKSkuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKQ0KICogICAgICAgICAgIC50b0JlKCc0MDggNTU1IDEyMTInKTsNCiAqDQogKiAgICAgICBleHBlY3Qoc2Vjb25kUmVwZWF0LmVsZW1lbnQoYnkubW9kZWwoJ2NvbnRhY3QudmFsdWUnKSkuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKQ0KICogICAgICAgICAgIC50b0JlKCdqb2huLnNtaXRoQGV4YW1wbGUub3JnJyk7DQogKg0KICogICAgICAgZmlyc3RSZXBlYXQuZWxlbWVudChieS5saW5rVGV4dCgnY2xlYXInKSkuY2xpY2soKTsNCiAqDQogKiAgICAgICBleHBlY3QoZmlyc3RSZXBlYXQuZWxlbWVudChieS5tb2RlbCgnY29udGFjdC52YWx1ZScpKS5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykpDQogKiAgICAgICAgICAgLnRvQmUoJycpOw0KICoNCiAqICAgICAgIGNvbnRhaW5lci5lbGVtZW50KGJ5LmxpbmtUZXh0KCdhZGQnKSkuY2xpY2soKTsNCiAqDQogKiAgICAgICBleHBlY3QoY29udGFpbmVyLmVsZW1lbnQoYnkucmVwZWF0ZXIoJ2NvbnRhY3QgaW4gc2V0dGluZ3MuY29udGFjdHMnKS5yb3coMikpDQogKiAgICAgICAgICAgLmVsZW1lbnQoYnkubW9kZWwoJ2NvbnRhY3QudmFsdWUnKSkNCiAqICAgICAgICAgICAuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKQ0KICogICAgICAgICAgIC50b0JlKCd5b3VybmFtZUBleGFtcGxlLm9yZycpOw0KICogICAgIH0pOw0KICogICA8L2ZpbGU+DQogKiA8L2V4YW1wbGU+DQogKg0KICogVGhpcyBleGFtcGxlIGRlbW9uc3RyYXRlcyB0aGUgImF0dGFjaCB0byBgJHNjb3BlYCIgc3R5bGUgb2YgY29udHJvbGxlci4NCiAqDQogKiA8ZXhhbXBsZSBuYW1lPSJuZ0NvbnRyb2xsZXIiIG1vZHVsZT0iY29udHJvbGxlckV4YW1wbGUiPg0KICogIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICogICA8ZGl2IGlkPSJjdHJsLWV4bXBsIiBuZy1jb250cm9sbGVyPSJTZXR0aW5nc0NvbnRyb2xsZXIyIj4NCiAqICAgICBOYW1lOiA8aW5wdXQgdHlwZT0idGV4dCIgbmctbW9kZWw9Im5hbWUiLz4NCiAqICAgICBbIDxhIGhyZWY9IiIgbmctY2xpY2s9ImdyZWV0KCkiPmdyZWV0PC9hPiBdPGJyLz4NCiAqICAgICBDb250YWN0Og0KICogICAgIDx1bD4NCiAqICAgICAgIDxsaSBuZy1yZXBlYXQ9ImNvbnRhY3QgaW4gY29udGFjdHMiPg0KICogICAgICAgICA8c2VsZWN0IG5nLW1vZGVsPSJjb250YWN0LnR5cGUiPg0KICogICAgICAgICAgICA8b3B0aW9uPnBob25lPC9vcHRpb24+DQogKiAgICAgICAgICAgIDxvcHRpb24+ZW1haWw8L29wdGlvbj4NCiAqICAgICAgICAgPC9zZWxlY3Q+DQogKiAgICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBuZy1tb2RlbD0iY29udGFjdC52YWx1ZSIvPg0KICogICAgICAgICBbIDxhIGhyZWY9IiIgbmctY2xpY2s9ImNsZWFyQ29udGFjdChjb250YWN0KSI+Y2xlYXI8L2E+DQogKiAgICAgICAgIHwgPGEgaHJlZj0iIiBuZy1jbGljaz0icmVtb3ZlQ29udGFjdChjb250YWN0KSI+WDwvYT4gXQ0KICogICAgICAgPC9saT4NCiAqICAgICAgIDxsaT5bIDxhIGhyZWY9IiIgbmctY2xpY2s9ImFkZENvbnRhY3QoKSI+YWRkPC9hPiBdPC9saT4NCiAqICAgIDwvdWw+DQogKiAgIDwvZGl2Pg0KICogIDwvZmlsZT4NCiAqICA8ZmlsZSBuYW1lPSJhcHAuanMiPg0KICogICBhbmd1bGFyLm1vZHVsZSgnY29udHJvbGxlckV4YW1wbGUnLCBbXSkNCiAqICAgICAuY29udHJvbGxlcignU2V0dGluZ3NDb250cm9sbGVyMicsIFsnJHNjb3BlJywgU2V0dGluZ3NDb250cm9sbGVyMl0pOw0KICoNCiAqICAgZnVuY3Rpb24gU2V0dGluZ3NDb250cm9sbGVyMigkc2NvcGUpIHsNCiAqICAgICAkc2NvcGUubmFtZSA9ICJKb2huIFNtaXRoIjsNCiAqICAgICAkc2NvcGUuY29udGFjdHMgPSBbDQogKiAgICAgICB7dHlwZToncGhvbmUnLCB2YWx1ZTonNDA4IDU1NSAxMjEyJ30sDQogKiAgICAgICB7dHlwZTonZW1haWwnLCB2YWx1ZTonam9obi5zbWl0aEBleGFtcGxlLm9yZyd9IF07DQogKg0KICogICAgICRzY29wZS5ncmVldCA9IGZ1bmN0aW9uKCkgew0KICogICAgICAgYWxlcnQoJHNjb3BlLm5hbWUpOw0KICogICAgIH07DQogKg0KICogICAgICRzY29wZS5hZGRDb250YWN0ID0gZnVuY3Rpb24oKSB7DQogKiAgICAgICAkc2NvcGUuY29udGFjdHMucHVzaCh7dHlwZTonZW1haWwnLCB2YWx1ZToneW91cm5hbWVAZXhhbXBsZS5vcmcnfSk7DQogKiAgICAgfTsNCiAqDQogKiAgICAgJHNjb3BlLnJlbW92ZUNvbnRhY3QgPSBmdW5jdGlvbihjb250YWN0VG9SZW1vdmUpIHsNCiAqICAgICAgIHZhciBpbmRleCA9ICRzY29wZS5jb250YWN0cy5pbmRleE9mKGNvbnRhY3RUb1JlbW92ZSk7DQogKiAgICAgICAkc2NvcGUuY29udGFjdHMuc3BsaWNlKGluZGV4LCAxKTsNCiAqICAgICB9Ow0KICoNCiAqICAgICAkc2NvcGUuY2xlYXJDb250YWN0ID0gZnVuY3Rpb24oY29udGFjdCkgew0KICogICAgICAgY29udGFjdC50eXBlID0gJ3Bob25lJzsNCiAqICAgICAgIGNvbnRhY3QudmFsdWUgPSAnJzsNCiAqICAgICB9Ow0KICogICB9DQogKiAgPC9maWxlPg0KICogIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICogICAgaXQoJ3Nob3VsZCBjaGVjayBjb250cm9sbGVyJywgZnVuY3Rpb24oKSB7DQogKiAgICAgIHZhciBjb250YWluZXIgPSBlbGVtZW50KGJ5LmlkKCdjdHJsLWV4bXBsJykpOw0KICoNCiAqICAgICAgZXhwZWN0KGNvbnRhaW5lci5lbGVtZW50KGJ5Lm1vZGVsKCduYW1lJykpDQogKiAgICAgICAgICAuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKS50b0JlKCdKb2huIFNtaXRoJyk7DQogKg0KICogICAgICB2YXIgZmlyc3RSZXBlYXQgPQ0KICogICAgICAgICAgY29udGFpbmVyLmVsZW1lbnQoYnkucmVwZWF0ZXIoJ2NvbnRhY3QgaW4gY29udGFjdHMnKS5yb3coMCkpOw0KICogICAgICB2YXIgc2Vjb25kUmVwZWF0ID0NCiAqICAgICAgICAgIGNvbnRhaW5lci5lbGVtZW50KGJ5LnJlcGVhdGVyKCdjb250YWN0IGluIGNvbnRhY3RzJykucm93KDEpKTsNCiAqDQogKiAgICAgIGV4cGVjdChmaXJzdFJlcGVhdC5lbGVtZW50KGJ5Lm1vZGVsKCdjb250YWN0LnZhbHVlJykpLmdldEF0dHJpYnV0ZSgndmFsdWUnKSkNCiAqICAgICAgICAgIC50b0JlKCc0MDggNTU1IDEyMTInKTsNCiAqICAgICAgZXhwZWN0KHNlY29uZFJlcGVhdC5lbGVtZW50KGJ5Lm1vZGVsKCdjb250YWN0LnZhbHVlJykpLmdldEF0dHJpYnV0ZSgndmFsdWUnKSkNCiAqICAgICAgICAgIC50b0JlKCdqb2huLnNtaXRoQGV4YW1wbGUub3JnJyk7DQogKg0KICogICAgICBmaXJzdFJlcGVhdC5lbGVtZW50KGJ5LmxpbmtUZXh0KCdjbGVhcicpKS5jbGljaygpOw0KICoNCiAqICAgICAgZXhwZWN0KGZpcnN0UmVwZWF0LmVsZW1lbnQoYnkubW9kZWwoJ2NvbnRhY3QudmFsdWUnKSkuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKQ0KICogICAgICAgICAgLnRvQmUoJycpOw0KICoNCiAqICAgICAgY29udGFpbmVyLmVsZW1lbnQoYnkubGlua1RleHQoJ2FkZCcpKS5jbGljaygpOw0KICoNCiAqICAgICAgZXhwZWN0KGNvbnRhaW5lci5lbGVtZW50KGJ5LnJlcGVhdGVyKCdjb250YWN0IGluIGNvbnRhY3RzJykucm93KDIpKQ0KICogICAgICAgICAgLmVsZW1lbnQoYnkubW9kZWwoJ2NvbnRhY3QudmFsdWUnKSkNCiAqICAgICAgICAgIC5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykpDQogKiAgICAgICAgICAudG9CZSgneW91cm5hbWVAZXhhbXBsZS5vcmcnKTsNCiAqICAgIH0pOw0KICogIDwvZmlsZT4NCiAqPC9leGFtcGxlPg0KDQogKi8NCnZhciBuZ0NvbnRyb2xsZXJEaXJlY3RpdmUgPSBbZnVuY3Rpb24oKSB7DQogIHJldHVybiB7DQogICAgcmVzdHJpY3Q6ICdBJywNCiAgICBzY29wZTogdHJ1ZSwNCiAgICBjb250cm9sbGVyOiAnQCcsDQogICAgcHJpb3JpdHk6IDUwMA0KICB9Ow0KfV07DQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdDc3ANCiAqDQogKiBAZWxlbWVudCBodG1sDQogKiBAZGVzY3JpcHRpb24NCiAqIEVuYWJsZXMgW0NTUCAoQ29udGVudCBTZWN1cml0eSBQb2xpY3kpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9TZWN1cml0eS9DU1ApIHN1cHBvcnQuDQogKg0KICogVGhpcyBpcyBuZWNlc3Nhcnkgd2hlbiBkZXZlbG9waW5nIHRoaW5ncyBsaWtlIEdvb2dsZSBDaHJvbWUgRXh0ZW5zaW9ucyBvciBVbml2ZXJzYWwgV2luZG93cyBBcHBzLg0KICoNCiAqIENTUCBmb3JiaWRzIGFwcHMgdG8gdXNlIGBldmFsYCBvciBgRnVuY3Rpb24oc3RyaW5nKWAgZ2VuZXJhdGVkIGZ1bmN0aW9ucyAoYW1vbmcgb3RoZXIgdGhpbmdzKS4NCiAqIEZvciBBbmd1bGFyIHRvIGJlIENTUCBjb21wYXRpYmxlIHRoZXJlIGFyZSBvbmx5IHR3byB0aGluZ3MgdGhhdCB3ZSBuZWVkIHRvIGRvIGRpZmZlcmVudGx5Og0KICoNCiAqIC0gZG9uJ3QgdXNlIGBGdW5jdGlvbmAgY29uc3RydWN0b3IgdG8gZ2VuZXJhdGUgb3B0aW1pemVkIHZhbHVlIGdldHRlcnMNCiAqIC0gZG9uJ3QgaW5qZWN0IGN1c3RvbSBzdHlsZXNoZWV0IGludG8gdGhlIGRvY3VtZW50DQogKg0KICogQW5ndWxhckpTIHVzZXMgYEZ1bmN0aW9uKHN0cmluZylgIGdlbmVyYXRlZCBmdW5jdGlvbnMgYXMgYSBzcGVlZCBvcHRpbWl6YXRpb24uIEFwcGx5aW5nIHRoZSBgbmdDc3BgDQogKiBkaXJlY3RpdmUgd2lsbCBjYXVzZSBBbmd1bGFyIHRvIHVzZSBDU1AgY29tcGF0aWJpbGl0eSBtb2RlLiBXaGVuIHRoaXMgbW9kZSBpcyBvbiBBbmd1bGFySlMgd2lsbA0KICogZXZhbHVhdGUgYWxsIGV4cHJlc3Npb25zIHVwIHRvIDMwJSBzbG93ZXIgdGhhbiBpbiBub24tQ1NQIG1vZGUsIGJ1dCBubyBzZWN1cml0eSB2aW9sYXRpb25zIHdpbGwNCiAqIGJlIHJhaXNlZC4NCiAqDQogKiBDU1AgZm9yYmlkcyBKYXZhU2NyaXB0IHRvIGlubGluZSBzdHlsZXNoZWV0IHJ1bGVzLiBJbiBub24gQ1NQIG1vZGUgQW5ndWxhciBhdXRvbWF0aWNhbGx5DQogKiBpbmNsdWRlcyBzb21lIENTUyBydWxlcyAoZS5nLiB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nQ2xvYWsgbmdDbG9ha30pLg0KICogVG8gbWFrZSB0aG9zZSBkaXJlY3RpdmVzIHdvcmsgaW4gQ1NQIG1vZGUsIGluY2x1ZGUgdGhlIGBhbmd1bGFyLWNzcC5jc3NgIG1hbnVhbGx5Lg0KICoNCiAqIEFuZ3VsYXIgdHJpZXMgdG8gYXV0b2RldGVjdCBpZiBDU1AgaXMgYWN0aXZlIGFuZCBhdXRvbWF0aWNhbGx5IHR1cm4gb24gdGhlIENTUC1zYWZlIG1vZGUuIFRoaXMNCiAqIGF1dG9kZXRlY3Rpb24gaG93ZXZlciB0cmlnZ2VycyBhIENTUCBlcnJvciB0byBiZSBsb2dnZWQgaW4gdGhlIGNvbnNvbGU6DQogKg0KICogYGBgDQogKiBSZWZ1c2VkIHRvIGV2YWx1YXRlIGEgc3RyaW5nIGFzIEphdmFTY3JpcHQgYmVjYXVzZSAndW5zYWZlLWV2YWwnIGlzIG5vdCBhbiBhbGxvd2VkIHNvdXJjZSBvZg0KICogc2NyaXB0IGluIHRoZSBmb2xsb3dpbmcgQ29udGVudCBTZWN1cml0eSBQb2xpY3kgZGlyZWN0aXZlOiAiZGVmYXVsdC1zcmMgJ3NlbGYnIi4gTm90ZSB0aGF0DQogKiAnc2NyaXB0LXNyYycgd2FzIG5vdCBleHBsaWNpdGx5IHNldCwgc28gJ2RlZmF1bHQtc3JjJyBpcyB1c2VkIGFzIGEgZmFsbGJhY2suDQogKiBgYGANCiAqDQogKiBUaGlzIGVycm9yIGlzIGhhcm1sZXNzIGJ1dCBhbm5veWluZy4gVG8gcHJldmVudCB0aGUgZXJyb3IgZnJvbSBzaG93aW5nIHVwLCBwdXQgdGhlIGBuZ0NzcGANCiAqIGRpcmVjdGl2ZSBvbiB0aGUgcm9vdCBlbGVtZW50IG9mIHRoZSBhcHBsaWNhdGlvbiBvciBvbiB0aGUgYGFuZ3VsYXIuanNgIHNjcmlwdCB0YWcsIHdoaWNoZXZlcg0KICogYXBwZWFycyBmaXJzdCBpbiB0aGUgaHRtbCBkb2N1bWVudC4NCiAqDQogKiAqTm90ZTogVGhpcyBkaXJlY3RpdmUgaXMgb25seSBhdmFpbGFibGUgaW4gdGhlIGBuZy1jc3BgIGFuZCBgZGF0YS1uZy1jc3BgIGF0dHJpYnV0ZSBmb3JtLioNCiAqDQogKiBAZXhhbXBsZQ0KICogVGhpcyBleGFtcGxlIHNob3dzIGhvdyB0byBhcHBseSB0aGUgYG5nQ3NwYCBkaXJlY3RpdmUgdG8gdGhlIGBodG1sYCB0YWcuDQogICBgYGBodG1sDQogICAgIDwhZG9jdHlwZSBodG1sPg0KICAgICA8aHRtbCBuZy1hcHAgbmctY3NwPg0KICAgICAuLi4NCiAgICAgLi4uDQogICAgIDwvaHRtbD4NCiAgIGBgYA0KICAqIEBleGFtcGxlDQogICAgICAvLyBOb3RlOiB0aGUgc3VmZml4IGAuY3NwYCBpbiB0aGUgZXhhbXBsZSBuYW1lIHRyaWdnZXJzDQogICAgICAvLyBjc3AgbW9kZSBpbiBvdXIgaHR0cCBzZXJ2ZXIhDQogICAgICA8ZXhhbXBsZSBuYW1lPSJleGFtcGxlLmNzcCIgbW9kdWxlPSJjc3BFeGFtcGxlIiBuZy1jc3A9InRydWUiPg0KICAgICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9Ik1haW5Db250cm9sbGVyIGFzIGN0cmwiPg0KICAgICAgICAgICAgPGRpdj4NCiAgICAgICAgICAgICAgPGJ1dHRvbiBuZy1jbGljaz0iY3RybC5pbmMoKSIgaWQ9ImluYyI+SW5jcmVtZW50PC9idXR0b24+DQogICAgICAgICAgICAgIDxzcGFuIGlkPSJjb3VudGVyIj4NCiAgICAgICAgICAgICAgICB7e2N0cmwuY291bnRlcn19DQogICAgICAgICAgICAgIDwvc3Bhbj4NCiAgICAgICAgICAgIDwvZGl2Pg0KDQogICAgICAgICAgICA8ZGl2Pg0KICAgICAgICAgICAgICA8YnV0dG9uIG5nLWNsaWNrPSJjdHJsLmV2aWwoKSIgaWQ9ImV2aWwiPkV2aWw8L2J1dHRvbj4NCiAgICAgICAgICAgICAgPHNwYW4gaWQ9ImV2aWxFcnJvciI+DQogICAgICAgICAgICAgICAge3tjdHJsLmV2aWxFcnJvcn19DQogICAgICAgICAgICAgIDwvc3Bhbj4NCiAgICAgICAgICAgIDwvZGl2Pg0KICAgICAgICAgIDwvZGl2Pg0KICAgICAgICA8L2ZpbGU+DQogICAgICAgIDxmaWxlIG5hbWU9InNjcmlwdC5qcyI+DQogICAgICAgICAgIGFuZ3VsYXIubW9kdWxlKCdjc3BFeGFtcGxlJywgW10pDQogICAgICAgICAgICAgLmNvbnRyb2xsZXIoJ01haW5Db250cm9sbGVyJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgICAgdGhpcy5jb3VudGVyID0gMDsNCiAgICAgICAgICAgICAgICB0aGlzLmluYyA9IGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgICAgICAgdGhpcy5jb3VudGVyKys7DQogICAgICAgICAgICAgICAgfTsNCiAgICAgICAgICAgICAgICB0aGlzLmV2aWwgPSBmdW5jdGlvbigpIHsNCiAgICAgICAgICAgICAgICAgIC8vIGpzaGludCBldmlsOnRydWUNCiAgICAgICAgICAgICAgICAgIHRyeSB7DQogICAgICAgICAgICAgICAgICAgIGV2YWwoJzErMicpOw0KICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkgew0KICAgICAgICAgICAgICAgICAgICB0aGlzLmV2aWxFcnJvciA9IGUubWVzc2FnZTsNCiAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9Ow0KICAgICAgICAgICAgICB9KTsNCiAgICAgICAgPC9maWxlPg0KICAgICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICAgICB2YXIgdXRpbCwgd2ViZHJpdmVyOw0KDQogICAgICAgICAgdmFyIGluY0J0biA9IGVsZW1lbnQoYnkuaWQoJ2luYycpKTsNCiAgICAgICAgICB2YXIgY291bnRlciA9IGVsZW1lbnQoYnkuaWQoJ2NvdW50ZXInKSk7DQogICAgICAgICAgdmFyIGV2aWxCdG4gPSBlbGVtZW50KGJ5LmlkKCdldmlsJykpOw0KICAgICAgICAgIHZhciBldmlsRXJyb3IgPSBlbGVtZW50KGJ5LmlkKCdldmlsRXJyb3InKSk7DQoNCiAgICAgICAgICBmdW5jdGlvbiBnZXRBbmRDbGVhclNldmVyZUVycm9ycygpIHsNCiAgICAgICAgICAgIHJldHVybiBicm93c2VyLm1hbmFnZSgpLmxvZ3MoKS5nZXQoJ2Jyb3dzZXInKS50aGVuKGZ1bmN0aW9uKGJyb3dzZXJMb2cpIHsNCiAgICAgICAgICAgICAgcmV0dXJuIGJyb3dzZXJMb2cuZmlsdGVyKGZ1bmN0aW9uKGxvZ0VudHJ5KSB7DQogICAgICAgICAgICAgICAgcmV0dXJuIGxvZ0VudHJ5LmxldmVsLnZhbHVlID4gd2ViZHJpdmVyLmxvZ2dpbmcuTGV2ZWwuV0FSTklORy52YWx1ZTsNCiAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICB9KTsNCiAgICAgICAgICB9DQoNCiAgICAgICAgICBmdW5jdGlvbiBjbGVhckVycm9ycygpIHsNCiAgICAgICAgICAgIGdldEFuZENsZWFyU2V2ZXJlRXJyb3JzKCk7DQogICAgICAgICAgfQ0KDQogICAgICAgICAgZnVuY3Rpb24gZXhwZWN0Tm9FcnJvcnMoKSB7DQogICAgICAgICAgICBnZXRBbmRDbGVhclNldmVyZUVycm9ycygpLnRoZW4oZnVuY3Rpb24oZmlsdGVyZWRMb2cpIHsNCiAgICAgICAgICAgICAgZXhwZWN0KGZpbHRlcmVkTG9nLmxlbmd0aCkudG9FcXVhbCgwKTsNCiAgICAgICAgICAgICAgaWYgKGZpbHRlcmVkTG9nLmxlbmd0aCkgew0KICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdicm93c2VyIGNvbnNvbGUgZXJyb3JzOiAnICsgdXRpbC5pbnNwZWN0KGZpbHRlcmVkTG9nKSk7DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0pOw0KICAgICAgICAgIH0NCg0KICAgICAgICAgIGZ1bmN0aW9uIGV4cGVjdEVycm9yKHJlZ2V4KSB7DQogICAgICAgICAgICBnZXRBbmRDbGVhclNldmVyZUVycm9ycygpLnRoZW4oZnVuY3Rpb24oZmlsdGVyZWRMb2cpIHsNCiAgICAgICAgICAgICAgdmFyIGZvdW5kID0gZmFsc2U7DQogICAgICAgICAgICAgIGZpbHRlcmVkTG9nLmZvckVhY2goZnVuY3Rpb24obG9nKSB7DQogICAgICAgICAgICAgICAgaWYgKGxvZy5tZXNzYWdlLm1hdGNoKHJlZ2V4KSkgew0KICAgICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICAgIGlmICghZm91bmQpIHsNCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGVjdGVkIGFuIGVycm9yIHRoYXQgbWF0Y2hlcyAnICsgcmVnZXgpOw0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9KTsNCiAgICAgICAgICB9DQoNCiAgICAgICAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgdXRpbCA9IHJlcXVpcmUoJ3V0aWwnKTsNCiAgICAgICAgICAgIHdlYmRyaXZlciA9IHJlcXVpcmUoJ3Byb3RyYWN0b3Ivbm9kZV9tb2R1bGVzL3NlbGVuaXVtLXdlYmRyaXZlcicpOw0KICAgICAgICAgIH0pOw0KDQogICAgICAgICAgLy8gRm9yIG5vdywgd2Ugb25seSB0ZXN0IG9uIENocm9tZSwNCiAgICAgICAgICAvLyBhcyBTYWZhcmkgZG9lcyBub3QgbG9hZCB0aGUgcGFnZSB3aXRoIFByb3RyYWN0b3IncyBpbmplY3RlZCBzY3JpcHRzLA0KICAgICAgICAgIC8vIGFuZCBGaXJlZm94IHdlYmRyaXZlciBhbHdheXMgZGlzYWJsZXMgY29udGVudCBzZWN1cml0eSBwb2xpY3kgKCM2MzU4KQ0KICAgICAgICAgIGlmIChicm93c2VyLnBhcmFtcy5icm93c2VyICE9PSAnY2hyb21lJykgew0KICAgICAgICAgICAgcmV0dXJuOw0KICAgICAgICAgIH0NCg0KICAgICAgICAgIGl0KCdzaG91bGQgbm90IHJlcG9ydCBlcnJvcnMgd2hlbiB0aGUgcGFnZSBpcyBsb2FkZWQnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgICAgIC8vIGNsZWFyIGVycm9ycyBzbyB3ZSBhcmUgbm90IGRlcGVuZGVudCBvbiBwcmV2aW91cyB0ZXN0cw0KICAgICAgICAgICAgY2xlYXJFcnJvcnMoKTsNCiAgICAgICAgICAgIC8vIE5lZWQgdG8gcmVsb2FkIHRoZSBwYWdlIGFzIHRoZSBwYWdlIGlzIGFscmVhZHkgbG9hZGVkIHdoZW4NCiAgICAgICAgICAgIC8vIHdlIGNvbWUgaGVyZQ0KICAgICAgICAgICAgYnJvd3Nlci5kcml2ZXIuZ2V0Q3VycmVudFVybCgpLnRoZW4oZnVuY3Rpb24odXJsKSB7DQogICAgICAgICAgICAgIGJyb3dzZXIuZ2V0KHVybCk7DQogICAgICAgICAgICB9KTsNCiAgICAgICAgICAgIGV4cGVjdE5vRXJyb3JzKCk7DQogICAgICAgICAgfSk7DQoNCiAgICAgICAgICBpdCgnc2hvdWxkIGV2YWx1YXRlIGV4cHJlc3Npb25zJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBleHBlY3QoY291bnRlci5nZXRUZXh0KCkpLnRvRXF1YWwoJzAnKTsNCiAgICAgICAgICAgIGluY0J0bi5jbGljaygpOw0KICAgICAgICAgICAgZXhwZWN0KGNvdW50ZXIuZ2V0VGV4dCgpKS50b0VxdWFsKCcxJyk7DQogICAgICAgICAgICBleHBlY3ROb0Vycm9ycygpOw0KICAgICAgICAgIH0pOw0KDQogICAgICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBhbmQgcmVwb3J0IGFuIGVycm9yIHdoZW4gdXNpbmcgImV2YWwiJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBldmlsQnRuLmNsaWNrKCk7DQogICAgICAgICAgICBleHBlY3QoZXZpbEVycm9yLmdldFRleHQoKSkudG9NYXRjaCgvQ29udGVudCBTZWN1cml0eSBQb2xpY3kvKTsNCiAgICAgICAgICAgIGV4cGVjdEVycm9yKC9Db250ZW50IFNlY3VyaXR5IFBvbGljeS8pOw0KICAgICAgICAgIH0pOw0KICAgICAgICA8L2ZpbGU+DQogICAgICA8L2V4YW1wbGU+DQogICovDQoNCi8vIG5nQ3NwIGlzIG5vdCBpbXBsZW1lbnRlZCBhcyBhIHByb3BlciBkaXJlY3RpdmUgYW55IG1vcmUsIGJlY2F1c2Ugd2UgbmVlZCBpdCBiZSBwcm9jZXNzZWQgd2hpbGUgd2UNCi8vIGJvb3RzdHJhcCB0aGUgc3lzdGVtIChiZWZvcmUgJHBhcnNlIGlzIGluc3RhbnRpYXRlZCksIGZvciB0aGlzIHJlYXNvbiB3ZSBqdXN0IGhhdmUNCi8vIHRoZSBjc3AuaXNBY3RpdmUoKSBmbiB0aGF0IGxvb2tzIGZvciBuZy1jc3AgYXR0cmlidXRlIGFueXdoZXJlIGluIHRoZSBjdXJyZW50IGRvYw0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nQ2xpY2sNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFRoZSBuZ0NsaWNrIGRpcmVjdGl2ZSBhbGxvd3MgeW91IHRvIHNwZWNpZnkgY3VzdG9tIGJlaGF2aW9yIHdoZW4NCiAqIGFuIGVsZW1lbnQgaXMgY2xpY2tlZC4NCiAqDQogKiBAZWxlbWVudCBBTlkNCiAqIEBwcmlvcml0eSAwDQogKiBAcGFyYW0ge2V4cHJlc3Npb259IG5nQ2xpY2sge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gRXhwcmVzc2lvbn0gdG8gZXZhbHVhdGUgdXBvbg0KICogY2xpY2suICh7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiMtZXZlbnQtIEV2ZW50IG9iamVjdCBpcyBhdmFpbGFibGUgYXMgYCRldmVudGB9KQ0KICoNCiAqIEBleGFtcGxlDQogICA8ZXhhbXBsZT4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICA8YnV0dG9uIG5nLWNsaWNrPSJjb3VudCA9IGNvdW50ICsgMSIgbmctaW5pdD0iY291bnQ9MCI+DQogICAgICAgIEluY3JlbWVudA0KICAgICAgPC9idXR0b24+DQogICAgICA8c3Bhbj4NCiAgICAgICAgY291bnQ6IHt7Y291bnR9fQ0KICAgICAgPC9zcGFuPg0KICAgICA8L2ZpbGU+DQogICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgIGl0KCdzaG91bGQgY2hlY2sgbmctY2xpY2snLCBmdW5jdGlvbigpIHsNCiAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmJpbmRpbmcoJ2NvdW50JykpLmdldFRleHQoKSkudG9NYXRjaCgnMCcpOw0KICAgICAgICAgZWxlbWVudChieS5jc3MoJ2J1dHRvbicpKS5jbGljaygpOw0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuYmluZGluZygnY291bnQnKSkuZ2V0VGV4dCgpKS50b01hdGNoKCcxJyk7DQogICAgICAgfSk7DQogICAgIDwvZmlsZT4NCiAgIDwvZXhhbXBsZT4NCiAqLw0KLyoNCiAqIEEgY29sbGVjdGlvbiBvZiBkaXJlY3RpdmVzIHRoYXQgYWxsb3dzIGNyZWF0aW9uIG9mIGN1c3RvbSBldmVudCBoYW5kbGVycyB0aGF0IGFyZSBkZWZpbmVkIGFzDQogKiBhbmd1bGFyIGV4cHJlc3Npb25zIGFuZCBhcmUgY29tcGlsZWQgYW5kIGV4ZWN1dGVkIHdpdGhpbiB0aGUgY3VycmVudCBzY29wZS4NCiAqLw0KdmFyIG5nRXZlbnREaXJlY3RpdmVzID0ge307DQoNCi8vIEZvciBldmVudHMgdGhhdCBtaWdodCBmaXJlIHN5bmNocm9ub3VzbHkgZHVyaW5nIERPTSBtYW5pcHVsYXRpb24NCi8vIHdlIG5lZWQgdG8gZXhlY3V0ZSB0aGVpciBldmVudCBoYW5kbGVycyBhc3luY2hyb25vdXNseSB1c2luZyAkZXZhbEFzeW5jLA0KLy8gc28gdGhhdCB0aGV5IGFyZSBub3QgZXhlY3V0ZWQgaW4gYW4gaW5jb25zaXN0ZW50IHN0YXRlLg0KdmFyIGZvcmNlQXN5bmNFdmVudHMgPSB7DQogICdibHVyJzogdHJ1ZSwNCiAgJ2ZvY3VzJzogdHJ1ZQ0KfTsNCmZvckVhY2goDQogICdjbGljayBkYmxjbGljayBtb3VzZWRvd24gbW91c2V1cCBtb3VzZW92ZXIgbW91c2VvdXQgbW91c2Vtb3ZlIG1vdXNlZW50ZXIgbW91c2VsZWF2ZSBrZXlkb3duIGtleXVwIGtleXByZXNzIHN1Ym1pdCBmb2N1cyBibHVyIGNvcHkgY3V0IHBhc3RlJy5zcGxpdCgnICcpLA0KICBmdW5jdGlvbihldmVudE5hbWUpIHsNCiAgICB2YXIgZGlyZWN0aXZlTmFtZSA9IGRpcmVjdGl2ZU5vcm1hbGl6ZSgnbmctJyArIGV2ZW50TmFtZSk7DQogICAgbmdFdmVudERpcmVjdGl2ZXNbZGlyZWN0aXZlTmFtZV0gPSBbJyRwYXJzZScsICckcm9vdFNjb3BlJywgZnVuY3Rpb24oJHBhcnNlLCAkcm9vdFNjb3BlKSB7DQogICAgICByZXR1cm4gew0KICAgICAgICByZXN0cmljdDogJ0EnLA0KICAgICAgICBjb21waWxlOiBmdW5jdGlvbigkZWxlbWVudCwgYXR0cikgew0KICAgICAgICAgIC8vIFdlIGV4cG9zZSB0aGUgcG93ZXJmdWwgJGV2ZW50IG9iamVjdCBvbiB0aGUgc2NvcGUgdGhhdCBwcm92aWRlcyBhY2Nlc3MgdG8gdGhlIFdpbmRvdywNCiAgICAgICAgICAvLyBldGMuIHRoYXQgaXNuJ3QgcHJvdGVjdGVkIGJ5IHRoZSBmYXN0IHBhdGhzIGluICRwYXJzZS4gIFdlIGV4cGxpY2l0bHkgcmVxdWVzdCBiZXR0ZXINCiAgICAgICAgICAvLyBjaGVja3MgYXQgdGhlIGNvc3Qgb2Ygc3BlZWQgc2luY2UgZXZlbnQgaGFuZGxlciBleHByZXNzaW9ucyBhcmUgbm90IGV4ZWN1dGVkIGFzDQogICAgICAgICAgLy8gZnJlcXVlbnRseSBhcyByZWd1bGFyIGNoYW5nZSBkZXRlY3Rpb24uDQogICAgICAgICAgdmFyIGZuID0gJHBhcnNlKGF0dHJbZGlyZWN0aXZlTmFtZV0sIC8qIGludGVyY2VwdG9yRm4gKi8gbnVsbCwgLyogZXhwZW5zaXZlQ2hlY2tzICovIHRydWUpOw0KICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBuZ0V2ZW50SGFuZGxlcihzY29wZSwgZWxlbWVudCkgew0KICAgICAgICAgICAgZWxlbWVudC5vbihldmVudE5hbWUsIGZ1bmN0aW9uKGV2ZW50KSB7DQogICAgICAgICAgICAgIHZhciBjYWxsYmFjayA9IGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgICAgIGZuKHNjb3BlLCB7JGV2ZW50OmV2ZW50fSk7DQogICAgICAgICAgICAgIH07DQogICAgICAgICAgICAgIGlmIChmb3JjZUFzeW5jRXZlbnRzW2V2ZW50TmFtZV0gJiYgJHJvb3RTY29wZS4kJHBoYXNlKSB7DQogICAgICAgICAgICAgICAgc2NvcGUuJGV2YWxBc3luYyhjYWxsYmFjayk7DQogICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgc2NvcGUuJGFwcGx5KGNhbGxiYWNrKTsNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfSk7DQogICAgICAgICAgfTsNCiAgICAgICAgfQ0KICAgICAgfTsNCiAgICB9XTsNCiAgfQ0KKTsNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0RibGNsaWNrDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBUaGUgYG5nRGJsY2xpY2tgIGRpcmVjdGl2ZSBhbGxvd3MgeW91IHRvIHNwZWNpZnkgY3VzdG9tIGJlaGF2aW9yIG9uIGEgZGJsY2xpY2sgZXZlbnQuDQogKg0KICogQGVsZW1lbnQgQU5ZDQogKiBAcHJpb3JpdHkgMA0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ0RibGNsaWNrIHtAbGluayBndWlkZS9leHByZXNzaW9uIEV4cHJlc3Npb259IHRvIGV2YWx1YXRlIHVwb24NCiAqIGEgZGJsY2xpY2suIChUaGUgRXZlbnQgb2JqZWN0IGlzIGF2YWlsYWJsZSBhcyBgJGV2ZW50YCkNCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGU+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgPGJ1dHRvbiBuZy1kYmxjbGljaz0iY291bnQgPSBjb3VudCArIDEiIG5nLWluaXQ9ImNvdW50PTAiPg0KICAgICAgICBJbmNyZW1lbnQgKG9uIGRvdWJsZSBjbGljaykNCiAgICAgIDwvYnV0dG9uPg0KICAgICAgY291bnQ6IHt7Y291bnR9fQ0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCg0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nTW91c2Vkb3duDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBUaGUgbmdNb3VzZWRvd24gZGlyZWN0aXZlIGFsbG93cyB5b3UgdG8gc3BlY2lmeSBjdXN0b20gYmVoYXZpb3Igb24gbW91c2Vkb3duIGV2ZW50Lg0KICoNCiAqIEBlbGVtZW50IEFOWQ0KICogQHByaW9yaXR5IDANCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdNb3VzZWRvd24ge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gRXhwcmVzc2lvbn0gdG8gZXZhbHVhdGUgdXBvbg0KICogbW91c2Vkb3duLiAoe0BsaW5rIGd1aWRlL2V4cHJlc3Npb24jLWV2ZW50LSBFdmVudCBvYmplY3QgaXMgYXZhaWxhYmxlIGFzIGAkZXZlbnRgfSkNCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGU+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgPGJ1dHRvbiBuZy1tb3VzZWRvd249ImNvdW50ID0gY291bnQgKyAxIiBuZy1pbml0PSJjb3VudD0wIj4NCiAgICAgICAgSW5jcmVtZW50IChvbiBtb3VzZSBkb3duKQ0KICAgICAgPC9idXR0b24+DQogICAgICBjb3VudDoge3tjb3VudH19DQogICAgIDwvZmlsZT4NCiAgIDwvZXhhbXBsZT4NCiAqLw0KDQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdNb3VzZXVwDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBTcGVjaWZ5IGN1c3RvbSBiZWhhdmlvciBvbiBtb3VzZXVwIGV2ZW50Lg0KICoNCiAqIEBlbGVtZW50IEFOWQ0KICogQHByaW9yaXR5IDANCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdNb3VzZXVwIHtAbGluayBndWlkZS9leHByZXNzaW9uIEV4cHJlc3Npb259IHRvIGV2YWx1YXRlIHVwb24NCiAqIG1vdXNldXAuICh7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiMtZXZlbnQtIEV2ZW50IG9iamVjdCBpcyBhdmFpbGFibGUgYXMgYCRldmVudGB9KQ0KICoNCiAqIEBleGFtcGxlDQogICA8ZXhhbXBsZT4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICA8YnV0dG9uIG5nLW1vdXNldXA9ImNvdW50ID0gY291bnQgKyAxIiBuZy1pbml0PSJjb3VudD0wIj4NCiAgICAgICAgSW5jcmVtZW50IChvbiBtb3VzZSB1cCkNCiAgICAgIDwvYnV0dG9uPg0KICAgICAgY291bnQ6IHt7Y291bnR9fQ0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ01vdXNlb3Zlcg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogU3BlY2lmeSBjdXN0b20gYmVoYXZpb3Igb24gbW91c2VvdmVyIGV2ZW50Lg0KICoNCiAqIEBlbGVtZW50IEFOWQ0KICogQHByaW9yaXR5IDANCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdNb3VzZW92ZXIge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gRXhwcmVzc2lvbn0gdG8gZXZhbHVhdGUgdXBvbg0KICogbW91c2VvdmVyLiAoe0BsaW5rIGd1aWRlL2V4cHJlc3Npb24jLWV2ZW50LSBFdmVudCBvYmplY3QgaXMgYXZhaWxhYmxlIGFzIGAkZXZlbnRgfSkNCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGU+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgPGJ1dHRvbiBuZy1tb3VzZW92ZXI9ImNvdW50ID0gY291bnQgKyAxIiBuZy1pbml0PSJjb3VudD0wIj4NCiAgICAgICAgSW5jcmVtZW50ICh3aGVuIG1vdXNlIGlzIG92ZXIpDQogICAgICA8L2J1dHRvbj4NCiAgICAgIGNvdW50OiB7e2NvdW50fX0NCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICovDQoNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ01vdXNlZW50ZXINCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFNwZWNpZnkgY3VzdG9tIGJlaGF2aW9yIG9uIG1vdXNlZW50ZXIgZXZlbnQuDQogKg0KICogQGVsZW1lbnQgQU5ZDQogKiBAcHJpb3JpdHkgMA0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ01vdXNlZW50ZXIge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gRXhwcmVzc2lvbn0gdG8gZXZhbHVhdGUgdXBvbg0KICogbW91c2VlbnRlci4gKHtAbGluayBndWlkZS9leHByZXNzaW9uIy1ldmVudC0gRXZlbnQgb2JqZWN0IGlzIGF2YWlsYWJsZSBhcyBgJGV2ZW50YH0pDQogKg0KICogQGV4YW1wbGUNCiAgIDxleGFtcGxlPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgIDxidXR0b24gbmctbW91c2VlbnRlcj0iY291bnQgPSBjb3VudCArIDEiIG5nLWluaXQ9ImNvdW50PTAiPg0KICAgICAgICBJbmNyZW1lbnQgKHdoZW4gbW91c2UgZW50ZXJzKQ0KICAgICAgPC9idXR0b24+DQogICAgICBjb3VudDoge3tjb3VudH19DQogICAgIDwvZmlsZT4NCiAgIDwvZXhhbXBsZT4NCiAqLw0KDQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdNb3VzZWxlYXZlDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBTcGVjaWZ5IGN1c3RvbSBiZWhhdmlvciBvbiBtb3VzZWxlYXZlIGV2ZW50Lg0KICoNCiAqIEBlbGVtZW50IEFOWQ0KICogQHByaW9yaXR5IDANCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdNb3VzZWxlYXZlIHtAbGluayBndWlkZS9leHByZXNzaW9uIEV4cHJlc3Npb259IHRvIGV2YWx1YXRlIHVwb24NCiAqIG1vdXNlbGVhdmUuICh7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiMtZXZlbnQtIEV2ZW50IG9iamVjdCBpcyBhdmFpbGFibGUgYXMgYCRldmVudGB9KQ0KICoNCiAqIEBleGFtcGxlDQogICA8ZXhhbXBsZT4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICA8YnV0dG9uIG5nLW1vdXNlbGVhdmU9ImNvdW50ID0gY291bnQgKyAxIiBuZy1pbml0PSJjb3VudD0wIj4NCiAgICAgICAgSW5jcmVtZW50ICh3aGVuIG1vdXNlIGxlYXZlcykNCiAgICAgIDwvYnV0dG9uPg0KICAgICAgY291bnQ6IHt7Y291bnR9fQ0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCg0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nTW91c2Vtb3ZlDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBTcGVjaWZ5IGN1c3RvbSBiZWhhdmlvciBvbiBtb3VzZW1vdmUgZXZlbnQuDQogKg0KICogQGVsZW1lbnQgQU5ZDQogKiBAcHJpb3JpdHkgMA0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ01vdXNlbW92ZSB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBFeHByZXNzaW9ufSB0byBldmFsdWF0ZSB1cG9uDQogKiBtb3VzZW1vdmUuICh7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiMtZXZlbnQtIEV2ZW50IG9iamVjdCBpcyBhdmFpbGFibGUgYXMgYCRldmVudGB9KQ0KICoNCiAqIEBleGFtcGxlDQogICA8ZXhhbXBsZT4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICA8YnV0dG9uIG5nLW1vdXNlbW92ZT0iY291bnQgPSBjb3VudCArIDEiIG5nLWluaXQ9ImNvdW50PTAiPg0KICAgICAgICBJbmNyZW1lbnQgKHdoZW4gbW91c2UgbW92ZXMpDQogICAgICA8L2J1dHRvbj4NCiAgICAgIGNvdW50OiB7e2NvdW50fX0NCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICovDQoNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0tleWRvd24NCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFNwZWNpZnkgY3VzdG9tIGJlaGF2aW9yIG9uIGtleWRvd24gZXZlbnQuDQogKg0KICogQGVsZW1lbnQgQU5ZDQogKiBAcHJpb3JpdHkgMA0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ0tleWRvd24ge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gRXhwcmVzc2lvbn0gdG8gZXZhbHVhdGUgdXBvbg0KICoga2V5ZG93bi4gKEV2ZW50IG9iamVjdCBpcyBhdmFpbGFibGUgYXMgYCRldmVudGAgYW5kIGNhbiBiZSBpbnRlcnJvZ2F0ZWQgZm9yIGtleUNvZGUsIGFsdEtleSwgZXRjLikNCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGU+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgPGlucHV0IG5nLWtleWRvd249ImNvdW50ID0gY291bnQgKyAxIiBuZy1pbml0PSJjb3VudD0wIj4NCiAgICAgIGtleSBkb3duIGNvdW50OiB7e2NvdW50fX0NCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICovDQoNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0tleXVwDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBTcGVjaWZ5IGN1c3RvbSBiZWhhdmlvciBvbiBrZXl1cCBldmVudC4NCiAqDQogKiBAZWxlbWVudCBBTlkNCiAqIEBwcmlvcml0eSAwDQogKiBAcGFyYW0ge2V4cHJlc3Npb259IG5nS2V5dXAge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gRXhwcmVzc2lvbn0gdG8gZXZhbHVhdGUgdXBvbg0KICoga2V5dXAuIChFdmVudCBvYmplY3QgaXMgYXZhaWxhYmxlIGFzIGAkZXZlbnRgIGFuZCBjYW4gYmUgaW50ZXJyb2dhdGVkIGZvciBrZXlDb2RlLCBhbHRLZXksIGV0Yy4pDQogKg0KICogQGV4YW1wbGUNCiAgIDxleGFtcGxlPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICA8cD5UeXBpbmcgaW4gdGhlIGlucHV0IGJveCBiZWxvdyB1cGRhdGVzIHRoZSBrZXkgY291bnQ8L3A+DQogICAgICAgPGlucHV0IG5nLWtleXVwPSJjb3VudCA9IGNvdW50ICsgMSIgbmctaW5pdD0iY291bnQ9MCI+IGtleSB1cCBjb3VudDoge3tjb3VudH19DQoNCiAgICAgICA8cD5UeXBpbmcgaW4gdGhlIGlucHV0IGJveCBiZWxvdyB1cGRhdGVzIHRoZSBrZXljb2RlPC9wPg0KICAgICAgIDxpbnB1dCBuZy1rZXl1cD0iZXZlbnQ9JGV2ZW50Ij4NCiAgICAgICA8cD5ldmVudCBrZXlDb2RlOiB7eyBldmVudC5rZXlDb2RlIH19PC9wPg0KICAgICAgIDxwPmV2ZW50IGFsdEtleToge3sgZXZlbnQuYWx0S2V5IH19PC9wPg0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCg0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nS2V5cHJlc3MNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFNwZWNpZnkgY3VzdG9tIGJlaGF2aW9yIG9uIGtleXByZXNzIGV2ZW50Lg0KICoNCiAqIEBlbGVtZW50IEFOWQ0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ0tleXByZXNzIHtAbGluayBndWlkZS9leHByZXNzaW9uIEV4cHJlc3Npb259IHRvIGV2YWx1YXRlIHVwb24NCiAqIGtleXByZXNzLiAoe0BsaW5rIGd1aWRlL2V4cHJlc3Npb24jLWV2ZW50LSBFdmVudCBvYmplY3QgaXMgYXZhaWxhYmxlIGFzIGAkZXZlbnRgfQ0KICogYW5kIGNhbiBiZSBpbnRlcnJvZ2F0ZWQgZm9yIGtleUNvZGUsIGFsdEtleSwgZXRjLikNCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGU+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgPGlucHV0IG5nLWtleXByZXNzPSJjb3VudCA9IGNvdW50ICsgMSIgbmctaW5pdD0iY291bnQ9MCI+DQogICAgICBrZXkgcHJlc3MgY291bnQ6IHt7Y291bnR9fQ0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCg0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nU3VibWl0DQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBFbmFibGVzIGJpbmRpbmcgYW5ndWxhciBleHByZXNzaW9ucyB0byBvbnN1Ym1pdCBldmVudHMuDQogKg0KICogQWRkaXRpb25hbGx5IGl0IHByZXZlbnRzIHRoZSBkZWZhdWx0IGFjdGlvbiAod2hpY2ggZm9yIGZvcm0gbWVhbnMgc2VuZGluZyB0aGUgcmVxdWVzdCB0byB0aGUNCiAqIHNlcnZlciBhbmQgcmVsb2FkaW5nIHRoZSBjdXJyZW50IHBhZ2UpLCBidXQgb25seSBpZiB0aGUgZm9ybSBkb2VzIG5vdCBjb250YWluIGBhY3Rpb25gLA0KICogYGRhdGEtYWN0aW9uYCwgb3IgYHgtYWN0aW9uYCBhdHRyaWJ1dGVzLg0KICoNCiAqIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXdhcm5pbmciPg0KICogKipXYXJuaW5nOioqIEJlIGNhcmVmdWwgbm90IHRvIGNhdXNlICJkb3VibGUtc3VibWlzc2lvbiIgYnkgdXNpbmcgYm90aCB0aGUgYG5nQ2xpY2tgIGFuZA0KICogYG5nU3VibWl0YCBoYW5kbGVycyB0b2dldGhlci4gU2VlIHRoZQ0KICoge0BsaW5rIGZvcm0jc3VibWl0dGluZy1hLWZvcm0tYW5kLXByZXZlbnRpbmctdGhlLWRlZmF1bHQtYWN0aW9uIGBmb3JtYCBkaXJlY3RpdmUgZG9jdW1lbnRhdGlvbn0NCiAqIGZvciBhIGRldGFpbGVkIGRpc2N1c3Npb24gb2Ygd2hlbiBgbmdTdWJtaXRgIG1heSBiZSB0cmlnZ2VyZWQuDQogKiA8L2Rpdj4NCiAqDQogKiBAZWxlbWVudCBmb3JtDQogKiBAcHJpb3JpdHkgMA0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ1N1Ym1pdCB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBFeHByZXNzaW9ufSB0byBldmFsLg0KICogKHtAbGluayBndWlkZS9leHByZXNzaW9uIy1ldmVudC0gRXZlbnQgb2JqZWN0IGlzIGF2YWlsYWJsZSBhcyBgJGV2ZW50YH0pDQogKg0KICogQGV4YW1wbGUNCiAgIDxleGFtcGxlIG1vZHVsZT0ic3VibWl0RXhhbXBsZSI+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgPHNjcmlwdD4NCiAgICAgICAgYW5ndWxhci5tb2R1bGUoJ3N1Ym1pdEV4YW1wbGUnLCBbXSkNCiAgICAgICAgICAuY29udHJvbGxlcignRXhhbXBsZUNvbnRyb2xsZXInLCBbJyRzY29wZScsIGZ1bmN0aW9uKCRzY29wZSkgew0KICAgICAgICAgICAgJHNjb3BlLmxpc3QgPSBbXTsNCiAgICAgICAgICAgICRzY29wZS50ZXh0ID0gJ2hlbGxvJzsNCiAgICAgICAgICAgICRzY29wZS5zdWJtaXQgPSBmdW5jdGlvbigpIHsNCiAgICAgICAgICAgICAgaWYgKCRzY29wZS50ZXh0KSB7DQogICAgICAgICAgICAgICAgJHNjb3BlLmxpc3QucHVzaCh0aGlzLnRleHQpOw0KICAgICAgICAgICAgICAgICRzY29wZS50ZXh0ID0gJyc7DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH07DQogICAgICAgICAgfV0pOw0KICAgICAgPC9zY3JpcHQ+DQogICAgICA8Zm9ybSBuZy1zdWJtaXQ9InN1Ym1pdCgpIiBuZy1jb250cm9sbGVyPSJFeGFtcGxlQ29udHJvbGxlciI+DQogICAgICAgIEVudGVyIHRleHQgYW5kIGhpdCBlbnRlcjoNCiAgICAgICAgPGlucHV0IHR5cGU9InRleHQiIG5nLW1vZGVsPSJ0ZXh0IiBuYW1lPSJ0ZXh0IiAvPg0KICAgICAgICA8aW5wdXQgdHlwZT0ic3VibWl0IiBpZD0ic3VibWl0IiB2YWx1ZT0iU3VibWl0IiAvPg0KICAgICAgICA8cHJlPmxpc3Q9e3tsaXN0fX08L3ByZT4NCiAgICAgIDwvZm9ybT4NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICBpdCgnc2hvdWxkIGNoZWNrIG5nLXN1Ym1pdCcsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuYmluZGluZygnbGlzdCcpKS5nZXRUZXh0KCkpLnRvQmUoJ2xpc3Q9W10nKTsNCiAgICAgICAgIGVsZW1lbnQoYnkuY3NzKCcjc3VibWl0JykpLmNsaWNrKCk7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5iaW5kaW5nKCdsaXN0JykpLmdldFRleHQoKSkudG9Db250YWluKCdoZWxsbycpOw0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkubW9kZWwoJ3RleHQnKSkuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKS50b0JlKCcnKTsNCiAgICAgICB9KTsNCiAgICAgICBpdCgnc2hvdWxkIGlnbm9yZSBlbXB0eSBzdHJpbmdzJywgZnVuY3Rpb24oKSB7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5iaW5kaW5nKCdsaXN0JykpLmdldFRleHQoKSkudG9CZSgnbGlzdD1bXScpOw0KICAgICAgICAgZWxlbWVudChieS5jc3MoJyNzdWJtaXQnKSkuY2xpY2soKTsNCiAgICAgICAgIGVsZW1lbnQoYnkuY3NzKCcjc3VibWl0JykpLmNsaWNrKCk7DQogICAgICAgICBleHBlY3QoZWxlbWVudChieS5iaW5kaW5nKCdsaXN0JykpLmdldFRleHQoKSkudG9Db250YWluKCdoZWxsbycpOw0KICAgICAgICB9KTsNCiAgICAgPC9maWxlPg0KICAgPC9leGFtcGxlPg0KICovDQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdGb2N1cw0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogU3BlY2lmeSBjdXN0b20gYmVoYXZpb3Igb24gZm9jdXMgZXZlbnQuDQogKg0KICogTm90ZTogQXMgdGhlIGBmb2N1c2AgZXZlbnQgaXMgZXhlY3V0ZWQgc3luY2hyb25vdXNseSB3aGVuIGNhbGxpbmcgYGlucHV0LmZvY3VzKClgDQogKiBBbmd1bGFySlMgZXhlY3V0ZXMgdGhlIGV4cHJlc3Npb24gdXNpbmcgYHNjb3BlLiRldmFsQXN5bmNgIGlmIHRoZSBldmVudCBpcyBmaXJlZA0KICogZHVyaW5nIGFuIGAkYXBwbHlgIHRvIGVuc3VyZSBhIGNvbnNpc3RlbnQgc3RhdGUuDQogKg0KICogQGVsZW1lbnQgd2luZG93LCBpbnB1dCwgc2VsZWN0LCB0ZXh0YXJlYSwgYQ0KICogQHByaW9yaXR5IDANCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdGb2N1cyB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBFeHByZXNzaW9ufSB0byBldmFsdWF0ZSB1cG9uDQogKiBmb2N1cy4gKHtAbGluayBndWlkZS9leHByZXNzaW9uIy1ldmVudC0gRXZlbnQgb2JqZWN0IGlzIGF2YWlsYWJsZSBhcyBgJGV2ZW50YH0pDQogKg0KICogQGV4YW1wbGUNCiAqIFNlZSB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nQ2xpY2sgbmdDbGlja30NCiAqLw0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nQmx1cg0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogU3BlY2lmeSBjdXN0b20gYmVoYXZpb3Igb24gYmx1ciBldmVudC4NCiAqDQogKiBBIFtibHVyIGV2ZW50XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9FdmVudHMvYmx1cikgZmlyZXMgd2hlbg0KICogYW4gZWxlbWVudCBoYXMgbG9zdCBmb2N1cy4NCiAqDQogKiBOb3RlOiBBcyB0aGUgYGJsdXJgIGV2ZW50IGlzIGV4ZWN1dGVkIHN5bmNocm9ub3VzbHkgYWxzbyBkdXJpbmcgRE9NIG1hbmlwdWxhdGlvbnMNCiAqIChlLmcuIHJlbW92aW5nIGEgZm9jdXNzZWQgaW5wdXQpLA0KICogQW5ndWxhckpTIGV4ZWN1dGVzIHRoZSBleHByZXNzaW9uIHVzaW5nIGBzY29wZS4kZXZhbEFzeW5jYCBpZiB0aGUgZXZlbnQgaXMgZmlyZWQNCiAqIGR1cmluZyBhbiBgJGFwcGx5YCB0byBlbnN1cmUgYSBjb25zaXN0ZW50IHN0YXRlLg0KICoNCiAqIEBlbGVtZW50IHdpbmRvdywgaW5wdXQsIHNlbGVjdCwgdGV4dGFyZWEsIGENCiAqIEBwcmlvcml0eSAwDQogKiBAcGFyYW0ge2V4cHJlc3Npb259IG5nQmx1ciB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBFeHByZXNzaW9ufSB0byBldmFsdWF0ZSB1cG9uDQogKiBibHVyLiAoe0BsaW5rIGd1aWRlL2V4cHJlc3Npb24jLWV2ZW50LSBFdmVudCBvYmplY3QgaXMgYXZhaWxhYmxlIGFzIGAkZXZlbnRgfSkNCiAqDQogKiBAZXhhbXBsZQ0KICogU2VlIHtAbGluayBuZy5kaXJlY3RpdmU6bmdDbGljayBuZ0NsaWNrfQ0KICovDQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdDb3B5DQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBTcGVjaWZ5IGN1c3RvbSBiZWhhdmlvciBvbiBjb3B5IGV2ZW50Lg0KICoNCiAqIEBlbGVtZW50IHdpbmRvdywgaW5wdXQsIHNlbGVjdCwgdGV4dGFyZWEsIGENCiAqIEBwcmlvcml0eSAwDQogKiBAcGFyYW0ge2V4cHJlc3Npb259IG5nQ29weSB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBFeHByZXNzaW9ufSB0byBldmFsdWF0ZSB1cG9uDQogKiBjb3B5LiAoe0BsaW5rIGd1aWRlL2V4cHJlc3Npb24jLWV2ZW50LSBFdmVudCBvYmplY3QgaXMgYXZhaWxhYmxlIGFzIGAkZXZlbnRgfSkNCiAqDQogKiBAZXhhbXBsZQ0KICAgPGV4YW1wbGU+DQogICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgPGlucHV0IG5nLWNvcHk9ImNvcGllZD10cnVlIiBuZy1pbml0PSJjb3BpZWQ9ZmFsc2U7IHZhbHVlPSdjb3B5IG1lJyIgbmctbW9kZWw9InZhbHVlIj4NCiAgICAgIGNvcGllZDoge3tjb3BpZWR9fQ0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0N1dA0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogU3BlY2lmeSBjdXN0b20gYmVoYXZpb3Igb24gY3V0IGV2ZW50Lg0KICoNCiAqIEBlbGVtZW50IHdpbmRvdywgaW5wdXQsIHNlbGVjdCwgdGV4dGFyZWEsIGENCiAqIEBwcmlvcml0eSAwDQogKiBAcGFyYW0ge2V4cHJlc3Npb259IG5nQ3V0IHtAbGluayBndWlkZS9leHByZXNzaW9uIEV4cHJlc3Npb259IHRvIGV2YWx1YXRlIHVwb24NCiAqIGN1dC4gKHtAbGluayBndWlkZS9leHByZXNzaW9uIy1ldmVudC0gRXZlbnQgb2JqZWN0IGlzIGF2YWlsYWJsZSBhcyBgJGV2ZW50YH0pDQogKg0KICogQGV4YW1wbGUNCiAgIDxleGFtcGxlPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgIDxpbnB1dCBuZy1jdXQ9ImN1dD10cnVlIiBuZy1pbml0PSJjdXQ9ZmFsc2U7IHZhbHVlPSdjdXQgbWUnIiBuZy1tb2RlbD0idmFsdWUiPg0KICAgICAgY3V0OiB7e2N1dH19DQogICAgIDwvZmlsZT4NCiAgIDwvZXhhbXBsZT4NCiAqLw0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nUGFzdGUNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFNwZWNpZnkgY3VzdG9tIGJlaGF2aW9yIG9uIHBhc3RlIGV2ZW50Lg0KICoNCiAqIEBlbGVtZW50IHdpbmRvdywgaW5wdXQsIHNlbGVjdCwgdGV4dGFyZWEsIGENCiAqIEBwcmlvcml0eSAwDQogKiBAcGFyYW0ge2V4cHJlc3Npb259IG5nUGFzdGUge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gRXhwcmVzc2lvbn0gdG8gZXZhbHVhdGUgdXBvbg0KICogcGFzdGUuICh7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiMtZXZlbnQtIEV2ZW50IG9iamVjdCBpcyBhdmFpbGFibGUgYXMgYCRldmVudGB9KQ0KICoNCiAqIEBleGFtcGxlDQogICA8ZXhhbXBsZT4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICA8aW5wdXQgbmctcGFzdGU9InBhc3RlPXRydWUiIG5nLWluaXQ9InBhc3RlPWZhbHNlIiBwbGFjZWhvbGRlcj0ncGFzdGUgaGVyZSc+DQogICAgICBwYXN0ZWQ6IHt7cGFzdGV9fQ0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0lmDQogKiBAcmVzdHJpY3QgQQ0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlIGBuZ0lmYCBkaXJlY3RpdmUgcmVtb3ZlcyBvciByZWNyZWF0ZXMgYSBwb3J0aW9uIG9mIHRoZSBET00gdHJlZSBiYXNlZCBvbiBhbg0KICoge2V4cHJlc3Npb259LiBJZiB0aGUgZXhwcmVzc2lvbiBhc3NpZ25lZCB0byBgbmdJZmAgZXZhbHVhdGVzIHRvIGEgZmFsc2UNCiAqIHZhbHVlIHRoZW4gdGhlIGVsZW1lbnQgaXMgcmVtb3ZlZCBmcm9tIHRoZSBET00sIG90aGVyd2lzZSBhIGNsb25lIG9mIHRoZQ0KICogZWxlbWVudCBpcyByZWluc2VydGVkIGludG8gdGhlIERPTS4NCiAqDQogKiBgbmdJZmAgZGlmZmVycyBmcm9tIGBuZ1Nob3dgIGFuZCBgbmdIaWRlYCBpbiB0aGF0IGBuZ0lmYCBjb21wbGV0ZWx5IHJlbW92ZXMgYW5kIHJlY3JlYXRlcyB0aGUNCiAqIGVsZW1lbnQgaW4gdGhlIERPTSByYXRoZXIgdGhhbiBjaGFuZ2luZyBpdHMgdmlzaWJpbGl0eSB2aWEgdGhlIGBkaXNwbGF5YCBjc3MgcHJvcGVydHkuICBBIGNvbW1vbg0KICogY2FzZSB3aGVuIHRoaXMgZGlmZmVyZW5jZSBpcyBzaWduaWZpY2FudCBpcyB3aGVuIHVzaW5nIGNzcyBzZWxlY3RvcnMgdGhhdCByZWx5IG9uIGFuIGVsZW1lbnQncw0KICogcG9zaXRpb24gd2l0aGluIHRoZSBET00sIHN1Y2ggYXMgdGhlIGA6Zmlyc3QtY2hpbGRgIG9yIGA6bGFzdC1jaGlsZGAgcHNldWRvLWNsYXNzZXMuDQogKg0KICogTm90ZSB0aGF0IHdoZW4gYW4gZWxlbWVudCBpcyByZW1vdmVkIHVzaW5nIGBuZ0lmYCBpdHMgc2NvcGUgaXMgZGVzdHJveWVkIGFuZCBhIG5ldyBzY29wZQ0KICogaXMgY3JlYXRlZCB3aGVuIHRoZSBlbGVtZW50IGlzIHJlc3RvcmVkLiAgVGhlIHNjb3BlIGNyZWF0ZWQgd2l0aGluIGBuZ0lmYCBpbmhlcml0cyBmcm9tDQogKiBpdHMgcGFyZW50IHNjb3BlIHVzaW5nDQogKiBbcHJvdG90eXBhbCBpbmhlcml0YW5jZV0oaHR0cHM6Ly9naXRodWIuY29tL2FuZ3VsYXIvYW5ndWxhci5qcy93aWtpL1VuZGVyc3RhbmRpbmctU2NvcGVzI2phdmFzY3JpcHQtcHJvdG90eXBhbC1pbmhlcml0YW5jZSkuDQogKiBBbiBpbXBvcnRhbnQgaW1wbGljYXRpb24gb2YgdGhpcyBpcyBpZiBgbmdNb2RlbGAgaXMgdXNlZCB3aXRoaW4gYG5nSWZgIHRvIGJpbmQgdG8NCiAqIGEgamF2YXNjcmlwdCBwcmltaXRpdmUgZGVmaW5lZCBpbiB0aGUgcGFyZW50IHNjb3BlLiBJbiB0aGlzIGNhc2UgYW55IG1vZGlmaWNhdGlvbnMgbWFkZSB0byB0aGUNCiAqIHZhcmlhYmxlIHdpdGhpbiB0aGUgY2hpbGQgc2NvcGUgd2lsbCBvdmVycmlkZSAoaGlkZSkgdGhlIHZhbHVlIGluIHRoZSBwYXJlbnQgc2NvcGUuDQogKg0KICogQWxzbywgYG5nSWZgIHJlY3JlYXRlcyBlbGVtZW50cyB1c2luZyB0aGVpciBjb21waWxlZCBzdGF0ZS4gQW4gZXhhbXBsZSBvZiB0aGlzIGJlaGF2aW9yDQogKiBpcyBpZiBhbiBlbGVtZW50J3MgY2xhc3MgYXR0cmlidXRlIGlzIGRpcmVjdGx5IG1vZGlmaWVkIGFmdGVyIGl0J3MgY29tcGlsZWQsIHVzaW5nIHNvbWV0aGluZyBsaWtlDQogKiBqUXVlcnkncyBgLmFkZENsYXNzKClgIG1ldGhvZCwgYW5kIHRoZSBlbGVtZW50IGlzIGxhdGVyIHJlbW92ZWQuIFdoZW4gYG5nSWZgIHJlY3JlYXRlcyB0aGUgZWxlbWVudA0KICogdGhlIGFkZGVkIGNsYXNzIHdpbGwgYmUgbG9zdCBiZWNhdXNlIHRoZSBvcmlnaW5hbCBjb21waWxlZCBzdGF0ZSBpcyB1c2VkIHRvIHJlZ2VuZXJhdGUgdGhlIGVsZW1lbnQuDQogKg0KICogQWRkaXRpb25hbGx5LCB5b3UgY2FuIHByb3ZpZGUgYW5pbWF0aW9ucyB2aWEgdGhlIGBuZ0FuaW1hdGVgIG1vZHVsZSB0byBhbmltYXRlIHRoZSBgZW50ZXJgDQogKiBhbmQgYGxlYXZlYCBlZmZlY3RzLg0KICoNCiAqIEBhbmltYXRpb25zDQogKiBlbnRlciAtIGhhcHBlbnMganVzdCBhZnRlciB0aGUgYG5nSWZgIGNvbnRlbnRzIGNoYW5nZSBhbmQgYSBuZXcgRE9NIGVsZW1lbnQgaXMgY3JlYXRlZCBhbmQgaW5qZWN0ZWQgaW50byB0aGUgYG5nSWZgIGNvbnRhaW5lcg0KICogbGVhdmUgLSBoYXBwZW5zIGp1c3QgYmVmb3JlIHRoZSBgbmdJZmAgY29udGVudHMgYXJlIHJlbW92ZWQgZnJvbSB0aGUgRE9NDQogKg0KICogQGVsZW1lbnQgQU5ZDQogKiBAc2NvcGUNCiAqIEBwcmlvcml0eSA2MDANCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdJZiBJZiB0aGUge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gZXhwcmVzc2lvbn0gaXMgZmFsc3kgdGhlbg0KICogICAgIHRoZSBlbGVtZW50IGlzIHJlbW92ZWQgZnJvbSB0aGUgRE9NIHRyZWUuIElmIGl0IGlzIHRydXRoeSBhIGNvcHkgb2YgdGhlIGNvbXBpbGVkDQogKiAgICAgZWxlbWVudCBpcyBhZGRlZCB0byB0aGUgRE9NIHRyZWUuDQogKg0KICogQGV4YW1wbGUNCiAgPGV4YW1wbGUgbW9kdWxlPSJuZ0FuaW1hdGUiIGRlcHM9ImFuZ3VsYXItYW5pbWF0ZS5qcyIgYW5pbWF0aW9ucz0idHJ1ZSI+DQogICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICBDbGljayBtZTogPGlucHV0IHR5cGU9ImNoZWNrYm94IiBuZy1tb2RlbD0iY2hlY2tlZCIgbmctaW5pdD0iY2hlY2tlZD10cnVlIiAvPjxici8+DQogICAgICBTaG93IHdoZW4gY2hlY2tlZDoNCiAgICAgIDxzcGFuIG5nLWlmPSJjaGVja2VkIiBjbGFzcz0iYW5pbWF0ZS1pZiI+DQogICAgICAgIFRoaXMgaXMgcmVtb3ZlZCB3aGVuIHRoZSBjaGVja2JveCBpcyB1bmNoZWNrZWQuDQogICAgICA8L3NwYW4+DQogICAgPC9maWxlPg0KICAgIDxmaWxlIG5hbWU9ImFuaW1hdGlvbnMuY3NzIj4NCiAgICAgIC5hbmltYXRlLWlmIHsNCiAgICAgICAgYmFja2dyb3VuZDp3aGl0ZTsNCiAgICAgICAgYm9yZGVyOjFweCBzb2xpZCBibGFjazsNCiAgICAgICAgcGFkZGluZzoxMHB4Ow0KICAgICAgfQ0KDQogICAgICAuYW5pbWF0ZS1pZi5uZy1lbnRlciwgLmFuaW1hdGUtaWYubmctbGVhdmUgew0KICAgICAgICAtd2Via2l0LXRyYW5zaXRpb246YWxsIGN1YmljLWJlemllcigwLjI1MCwgMC40NjAsIDAuNDUwLCAwLjk0MCkgMC41czsNCiAgICAgICAgdHJhbnNpdGlvbjphbGwgY3ViaWMtYmV6aWVyKDAuMjUwLCAwLjQ2MCwgMC40NTAsIDAuOTQwKSAwLjVzOw0KICAgICAgfQ0KDQogICAgICAuYW5pbWF0ZS1pZi5uZy1lbnRlciwNCiAgICAgIC5hbmltYXRlLWlmLm5nLWxlYXZlLm5nLWxlYXZlLWFjdGl2ZSB7DQogICAgICAgIG9wYWNpdHk6MDsNCiAgICAgIH0NCg0KICAgICAgLmFuaW1hdGUtaWYubmctbGVhdmUsDQogICAgICAuYW5pbWF0ZS1pZi5uZy1lbnRlci5uZy1lbnRlci1hY3RpdmUgew0KICAgICAgICBvcGFjaXR5OjE7DQogICAgICB9DQogICAgPC9maWxlPg0KICA8L2V4YW1wbGU+DQogKi8NCnZhciBuZ0lmRGlyZWN0aXZlID0gWyckYW5pbWF0ZScsIGZ1bmN0aW9uKCRhbmltYXRlKSB7DQogIHJldHVybiB7DQogICAgbXVsdGlFbGVtZW50OiB0cnVlLA0KICAgIHRyYW5zY2x1ZGU6ICdlbGVtZW50JywNCiAgICBwcmlvcml0eTogNjAwLA0KICAgIHRlcm1pbmFsOiB0cnVlLA0KICAgIHJlc3RyaWN0OiAnQScsDQogICAgJCR0bGI6IHRydWUsDQogICAgbGluazogZnVuY3Rpb24oJHNjb3BlLCAkZWxlbWVudCwgJGF0dHIsIGN0cmwsICR0cmFuc2NsdWRlKSB7DQogICAgICAgIHZhciBibG9jaywgY2hpbGRTY29wZSwgcHJldmlvdXNFbGVtZW50czsNCiAgICAgICAgJHNjb3BlLiR3YXRjaCgkYXR0ci5uZ0lmLCBmdW5jdGlvbiBuZ0lmV2F0Y2hBY3Rpb24odmFsdWUpIHsNCg0KICAgICAgICAgIGlmICh2YWx1ZSkgew0KICAgICAgICAgICAgaWYgKCFjaGlsZFNjb3BlKSB7DQogICAgICAgICAgICAgICR0cmFuc2NsdWRlKGZ1bmN0aW9uKGNsb25lLCBuZXdTY29wZSkgew0KICAgICAgICAgICAgICAgIGNoaWxkU2NvcGUgPSBuZXdTY29wZTsNCiAgICAgICAgICAgICAgICBjbG9uZVtjbG9uZS5sZW5ndGgrK10gPSBkb2N1bWVudC5jcmVhdGVDb21tZW50KCcgZW5kIG5nSWY6ICcgKyAkYXR0ci5uZ0lmICsgJyAnKTsNCiAgICAgICAgICAgICAgICAvLyBOb3RlOiBXZSBvbmx5IG5lZWQgdGhlIGZpcnN0L2xhc3Qgbm9kZSBvZiB0aGUgY2xvbmVkIG5vZGVzLg0KICAgICAgICAgICAgICAgIC8vIEhvd2V2ZXIsIHdlIG5lZWQgdG8ga2VlcCB0aGUgcmVmZXJlbmNlIHRvIHRoZSBqcWxpdGUgd3JhcHBlciBhcyBpdCBtaWdodCBiZSBjaGFuZ2VkIGxhdGVyDQogICAgICAgICAgICAgICAgLy8gYnkgYSBkaXJlY3RpdmUgd2l0aCB0ZW1wbGF0ZVVybCB3aGVuIGl0cyB0ZW1wbGF0ZSBhcnJpdmVzLg0KICAgICAgICAgICAgICAgIGJsb2NrID0gew0KICAgICAgICAgICAgICAgICAgY2xvbmU6IGNsb25lDQogICAgICAgICAgICAgICAgfTsNCiAgICAgICAgICAgICAgICAkYW5pbWF0ZS5lbnRlcihjbG9uZSwgJGVsZW1lbnQucGFyZW50KCksICRlbGVtZW50KTsNCiAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGlmIChwcmV2aW91c0VsZW1lbnRzKSB7DQogICAgICAgICAgICAgIHByZXZpb3VzRWxlbWVudHMucmVtb3ZlKCk7DQogICAgICAgICAgICAgIHByZXZpb3VzRWxlbWVudHMgPSBudWxsOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaWYgKGNoaWxkU2NvcGUpIHsNCiAgICAgICAgICAgICAgY2hpbGRTY29wZS4kZGVzdHJveSgpOw0KICAgICAgICAgICAgICBjaGlsZFNjb3BlID0gbnVsbDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGlmIChibG9jaykgew0KICAgICAgICAgICAgICBwcmV2aW91c0VsZW1lbnRzID0gZ2V0QmxvY2tOb2RlcyhibG9jay5jbG9uZSk7DQogICAgICAgICAgICAgICRhbmltYXRlLmxlYXZlKHByZXZpb3VzRWxlbWVudHMpLnRoZW4oZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgICAgcHJldmlvdXNFbGVtZW50cyA9IG51bGw7DQogICAgICAgICAgICAgIH0pOw0KICAgICAgICAgICAgICBibG9jayA9IG51bGw7DQogICAgICAgICAgICB9DQogICAgICAgICAgfQ0KICAgICAgICB9KTsNCiAgICB9DQogIH07DQp9XTsNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0luY2x1ZGUNCiAqIEByZXN0cmljdCBFQ0ENCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIEZldGNoZXMsIGNvbXBpbGVzIGFuZCBpbmNsdWRlcyBhbiBleHRlcm5hbCBIVE1MIGZyYWdtZW50Lg0KICoNCiAqIEJ5IGRlZmF1bHQsIHRoZSB0ZW1wbGF0ZSBVUkwgaXMgcmVzdHJpY3RlZCB0byB0aGUgc2FtZSBkb21haW4gYW5kIHByb3RvY29sIGFzIHRoZQ0KICogYXBwbGljYXRpb24gZG9jdW1lbnQuIFRoaXMgaXMgZG9uZSBieSBjYWxsaW5nIHtAbGluayAkc2NlI2dldFRydXN0ZWRSZXNvdXJjZVVybA0KICogJHNjZS5nZXRUcnVzdGVkUmVzb3VyY2VVcmx9IG9uIGl0LiBUbyBsb2FkIHRlbXBsYXRlcyBmcm9tIG90aGVyIGRvbWFpbnMgb3IgcHJvdG9jb2xzDQogKiB5b3UgbWF5IGVpdGhlciB7QGxpbmsgbmcuJHNjZURlbGVnYXRlUHJvdmlkZXIjcmVzb3VyY2VVcmxXaGl0ZWxpc3Qgd2hpdGVsaXN0IHRoZW19IG9yDQogKiB7QGxpbmsgJHNjZSN0cnVzdEFzUmVzb3VyY2VVcmwgd3JhcCB0aGVtfSBhcyB0cnVzdGVkIHZhbHVlcy4gUmVmZXIgdG8gQW5ndWxhcidzIHtAbGluaw0KICogbmcuJHNjZSBTdHJpY3QgQ29udGV4dHVhbCBFc2NhcGluZ30uDQogKg0KICogSW4gYWRkaXRpb24sIHRoZSBicm93c2VyJ3MNCiAqIFtTYW1lIE9yaWdpbiBQb2xpY3ldKGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvYnJvd3NlcnNlYy93aWtpL1BhcnQyI1NhbWUtb3JpZ2luX3BvbGljeV9mb3JfWE1MSHR0cFJlcXVlc3QpDQogKiBhbmQgW0Nyb3NzLU9yaWdpbiBSZXNvdXJjZSBTaGFyaW5nIChDT1JTKV0oaHR0cDovL3d3dy53My5vcmcvVFIvY29ycy8pDQogKiBwb2xpY3kgbWF5IGZ1cnRoZXIgcmVzdHJpY3Qgd2hldGhlciB0aGUgdGVtcGxhdGUgaXMgc3VjY2Vzc2Z1bGx5IGxvYWRlZC4NCiAqIEZvciBleGFtcGxlLCBgbmdJbmNsdWRlYCB3b24ndCB3b3JrIGZvciBjcm9zcy1kb21haW4gcmVxdWVzdHMgb24gYWxsIGJyb3dzZXJzIGFuZCBmb3IgYGZpbGU6Ly9gDQogKiBhY2Nlc3Mgb24gc29tZSBicm93c2Vycy4NCiAqDQogKiBAYW5pbWF0aW9ucw0KICogZW50ZXIgLSBhbmltYXRpb24gaXMgdXNlZCB0byBicmluZyBuZXcgY29udGVudCBpbnRvIHRoZSBicm93c2VyLg0KICogbGVhdmUgLSBhbmltYXRpb24gaXMgdXNlZCB0byBhbmltYXRlIGV4aXN0aW5nIGNvbnRlbnQgYXdheS4NCiAqDQogKiBUaGUgZW50ZXIgYW5kIGxlYXZlIGFuaW1hdGlvbiBvY2N1ciBjb25jdXJyZW50bHkuDQogKg0KICogQHNjb3BlDQogKiBAcHJpb3JpdHkgNDAwDQogKg0KICogQHBhcmFtIHtzdHJpbmd9IG5nSW5jbHVkZXxzcmMgYW5ndWxhciBleHByZXNzaW9uIGV2YWx1YXRpbmcgdG8gVVJMLiBJZiB0aGUgc291cmNlIGlzIGEgc3RyaW5nIGNvbnN0YW50LA0KICogICAgICAgICAgICAgICAgIG1ha2Ugc3VyZSB5b3Ugd3JhcCBpdCBpbiAqKnNpbmdsZSoqIHF1b3RlcywgZS5nLiBgc3JjPSInbXlQYXJ0aWFsVGVtcGxhdGUuaHRtbCciYC4NCiAqIEBwYXJhbSB7c3RyaW5nPX0gb25sb2FkIEV4cHJlc3Npb24gdG8gZXZhbHVhdGUgd2hlbiBhIG5ldyBwYXJ0aWFsIGlzIGxvYWRlZC4NCiAqDQogKiBAcGFyYW0ge3N0cmluZz19IGF1dG9zY3JvbGwgV2hldGhlciBgbmdJbmNsdWRlYCBzaG91bGQgY2FsbCB7QGxpbmsgbmcuJGFuY2hvclNjcm9sbA0KICogICAgICAgICAgICAgICAgICAkYW5jaG9yU2Nyb2xsfSB0byBzY3JvbGwgdGhlIHZpZXdwb3J0IGFmdGVyIHRoZSBjb250ZW50IGlzIGxvYWRlZC4NCiAqDQogKiAgICAgICAgICAgICAgICAgIC0gSWYgdGhlIGF0dHJpYnV0ZSBpcyBub3Qgc2V0LCBkaXNhYmxlIHNjcm9sbGluZy4NCiAqICAgICAgICAgICAgICAgICAgLSBJZiB0aGUgYXR0cmlidXRlIGlzIHNldCB3aXRob3V0IHZhbHVlLCBlbmFibGUgc2Nyb2xsaW5nLg0KICogICAgICAgICAgICAgICAgICAtIE90aGVyd2lzZSBlbmFibGUgc2Nyb2xsaW5nIG9ubHkgaWYgdGhlIGV4cHJlc3Npb24gZXZhbHVhdGVzIHRvIHRydXRoeSB2YWx1ZS4NCiAqDQogKiBAZXhhbXBsZQ0KICA8ZXhhbXBsZSBtb2R1bGU9ImluY2x1ZGVFeGFtcGxlIiBkZXBzPSJhbmd1bGFyLWFuaW1hdGUuanMiIGFuaW1hdGlvbnM9InRydWUiPg0KICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICA8c2VsZWN0IG5nLW1vZGVsPSJ0ZW1wbGF0ZSIgbmctb3B0aW9ucz0idC5uYW1lIGZvciB0IGluIHRlbXBsYXRlcyI+DQogICAgICAgIDxvcHRpb24gdmFsdWU9IiI+KGJsYW5rKTwvb3B0aW9uPg0KICAgICAgIDwvc2VsZWN0Pg0KICAgICAgIHVybCBvZiB0aGUgdGVtcGxhdGU6IDx0dD57e3RlbXBsYXRlLnVybH19PC90dD4NCiAgICAgICA8aHIvPg0KICAgICAgIDxkaXYgY2xhc3M9InNsaWRlLWFuaW1hdGUtY29udGFpbmVyIj4NCiAgICAgICAgIDxkaXYgY2xhc3M9InNsaWRlLWFuaW1hdGUiIG5nLWluY2x1ZGU9InRlbXBsYXRlLnVybCI+PC9kaXY+DQogICAgICAgPC9kaXY+DQogICAgIDwvZGl2Pg0KICAgIDwvZmlsZT4NCiAgICA8ZmlsZSBuYW1lPSJzY3JpcHQuanMiPg0KICAgICAgYW5ndWxhci5tb2R1bGUoJ2luY2x1ZGVFeGFtcGxlJywgWyduZ0FuaW1hdGUnXSkNCiAgICAgICAgLmNvbnRyb2xsZXIoJ0V4YW1wbGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICAgICAkc2NvcGUudGVtcGxhdGVzID0NCiAgICAgICAgICAgIFsgeyBuYW1lOiAndGVtcGxhdGUxLmh0bWwnLCB1cmw6ICd0ZW1wbGF0ZTEuaHRtbCd9LA0KICAgICAgICAgICAgICB7IG5hbWU6ICd0ZW1wbGF0ZTIuaHRtbCcsIHVybDogJ3RlbXBsYXRlMi5odG1sJ30gXTsNCiAgICAgICAgICAkc2NvcGUudGVtcGxhdGUgPSAkc2NvcGUudGVtcGxhdGVzWzBdOw0KICAgICAgICB9XSk7DQogICAgIDwvZmlsZT4NCiAgICA8ZmlsZSBuYW1lPSJ0ZW1wbGF0ZTEuaHRtbCI+DQogICAgICBDb250ZW50IG9mIHRlbXBsYXRlMS5odG1sDQogICAgPC9maWxlPg0KICAgIDxmaWxlIG5hbWU9InRlbXBsYXRlMi5odG1sIj4NCiAgICAgIENvbnRlbnQgb2YgdGVtcGxhdGUyLmh0bWwNCiAgICA8L2ZpbGU+DQogICAgPGZpbGUgbmFtZT0iYW5pbWF0aW9ucy5jc3MiPg0KICAgICAgLnNsaWRlLWFuaW1hdGUtY29udGFpbmVyIHsNCiAgICAgICAgcG9zaXRpb246cmVsYXRpdmU7DQogICAgICAgIGJhY2tncm91bmQ6d2hpdGU7DQogICAgICAgIGJvcmRlcjoxcHggc29saWQgYmxhY2s7DQogICAgICAgIGhlaWdodDo0MHB4Ow0KICAgICAgICBvdmVyZmxvdzpoaWRkZW47DQogICAgICB9DQoNCiAgICAgIC5zbGlkZS1hbmltYXRlIHsNCiAgICAgICAgcGFkZGluZzoxMHB4Ow0KICAgICAgfQ0KDQogICAgICAuc2xpZGUtYW5pbWF0ZS5uZy1lbnRlciwgLnNsaWRlLWFuaW1hdGUubmctbGVhdmUgew0KICAgICAgICAtd2Via2l0LXRyYW5zaXRpb246YWxsIGN1YmljLWJlemllcigwLjI1MCwgMC40NjAsIDAuNDUwLCAwLjk0MCkgMC41czsNCiAgICAgICAgdHJhbnNpdGlvbjphbGwgY3ViaWMtYmV6aWVyKDAuMjUwLCAwLjQ2MCwgMC40NTAsIDAuOTQwKSAwLjVzOw0KDQogICAgICAgIHBvc2l0aW9uOmFic29sdXRlOw0KICAgICAgICB0b3A6MDsNCiAgICAgICAgbGVmdDowOw0KICAgICAgICByaWdodDowOw0KICAgICAgICBib3R0b206MDsNCiAgICAgICAgZGlzcGxheTpibG9jazsNCiAgICAgICAgcGFkZGluZzoxMHB4Ow0KICAgICAgfQ0KDQogICAgICAuc2xpZGUtYW5pbWF0ZS5uZy1lbnRlciB7DQogICAgICAgIHRvcDotNTBweDsNCiAgICAgIH0NCiAgICAgIC5zbGlkZS1hbmltYXRlLm5nLWVudGVyLm5nLWVudGVyLWFjdGl2ZSB7DQogICAgICAgIHRvcDowOw0KICAgICAgfQ0KDQogICAgICAuc2xpZGUtYW5pbWF0ZS5uZy1sZWF2ZSB7DQogICAgICAgIHRvcDowOw0KICAgICAgfQ0KICAgICAgLnNsaWRlLWFuaW1hdGUubmctbGVhdmUubmctbGVhdmUtYWN0aXZlIHsNCiAgICAgICAgdG9wOjUwcHg7DQogICAgICB9DQogICAgPC9maWxlPg0KICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgdmFyIHRlbXBsYXRlU2VsZWN0ID0gZWxlbWVudChieS5tb2RlbCgndGVtcGxhdGUnKSk7DQogICAgICB2YXIgaW5jbHVkZUVsZW0gPSBlbGVtZW50KGJ5LmNzcygnW25nLWluY2x1ZGVdJykpOw0KDQogICAgICBpdCgnc2hvdWxkIGxvYWQgdGVtcGxhdGUxLmh0bWwnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgZXhwZWN0KGluY2x1ZGVFbGVtLmdldFRleHQoKSkudG9NYXRjaCgvQ29udGVudCBvZiB0ZW1wbGF0ZTEuaHRtbC8pOw0KICAgICAgfSk7DQoNCiAgICAgIGl0KCdzaG91bGQgbG9hZCB0ZW1wbGF0ZTIuaHRtbCcsIGZ1bmN0aW9uKCkgew0KICAgICAgICBpZiAoYnJvd3Nlci5wYXJhbXMuYnJvd3NlciA9PSAnZmlyZWZveCcpIHsNCiAgICAgICAgICAvLyBGaXJlZm94IGNhbid0IGhhbmRsZSB1c2luZyBzZWxlY3RzDQogICAgICAgICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL3Byb3RyYWN0b3IvaXNzdWVzLzQ4MA0KICAgICAgICAgIHJldHVybjsNCiAgICAgICAgfQ0KICAgICAgICB0ZW1wbGF0ZVNlbGVjdC5jbGljaygpOw0KICAgICAgICB0ZW1wbGF0ZVNlbGVjdC5hbGwoYnkuY3NzKCdvcHRpb24nKSkuZ2V0KDIpLmNsaWNrKCk7DQogICAgICAgIGV4cGVjdChpbmNsdWRlRWxlbS5nZXRUZXh0KCkpLnRvTWF0Y2goL0NvbnRlbnQgb2YgdGVtcGxhdGUyLmh0bWwvKTsNCiAgICAgIH0pOw0KDQogICAgICBpdCgnc2hvdWxkIGNoYW5nZSB0byBibGFuaycsIGZ1bmN0aW9uKCkgew0KICAgICAgICBpZiAoYnJvd3Nlci5wYXJhbXMuYnJvd3NlciA9PSAnZmlyZWZveCcpIHsNCiAgICAgICAgICAvLyBGaXJlZm94IGNhbid0IGhhbmRsZSB1c2luZyBzZWxlY3RzDQogICAgICAgICAgcmV0dXJuOw0KICAgICAgICB9DQogICAgICAgIHRlbXBsYXRlU2VsZWN0LmNsaWNrKCk7DQogICAgICAgIHRlbXBsYXRlU2VsZWN0LmFsbChieS5jc3MoJ29wdGlvbicpKS5nZXQoMCkuY2xpY2soKTsNCiAgICAgICAgZXhwZWN0KGluY2x1ZGVFbGVtLmlzUHJlc2VudCgpKS50b0JlKGZhbHNlKTsNCiAgICAgIH0pOw0KICAgIDwvZmlsZT4NCiAgPC9leGFtcGxlPg0KICovDQoNCg0KLyoqDQogKiBAbmdkb2MgZXZlbnQNCiAqIEBuYW1lIG5nSW5jbHVkZSMkaW5jbHVkZUNvbnRlbnRSZXF1ZXN0ZWQNCiAqIEBldmVudFR5cGUgZW1pdCBvbiB0aGUgc2NvcGUgbmdJbmNsdWRlIHdhcyBkZWNsYXJlZCBpbg0KICogQGRlc2NyaXB0aW9uDQogKiBFbWl0dGVkIGV2ZXJ5IHRpbWUgdGhlIG5nSW5jbHVkZSBjb250ZW50IGlzIHJlcXVlc3RlZC4NCiAqDQogKiBAcGFyYW0ge09iamVjdH0gYW5ndWxhckV2ZW50IFN5bnRoZXRpYyBldmVudCBvYmplY3QuDQogKiBAcGFyYW0ge1N0cmluZ30gc3JjIFVSTCBvZiBjb250ZW50IHRvIGxvYWQuDQogKi8NCg0KDQovKioNCiAqIEBuZ2RvYyBldmVudA0KICogQG5hbWUgbmdJbmNsdWRlIyRpbmNsdWRlQ29udGVudExvYWRlZA0KICogQGV2ZW50VHlwZSBlbWl0IG9uIHRoZSBjdXJyZW50IG5nSW5jbHVkZSBzY29wZQ0KICogQGRlc2NyaXB0aW9uDQogKiBFbWl0dGVkIGV2ZXJ5IHRpbWUgdGhlIG5nSW5jbHVkZSBjb250ZW50IGlzIHJlbG9hZGVkLg0KICoNCiAqIEBwYXJhbSB7T2JqZWN0fSBhbmd1bGFyRXZlbnQgU3ludGhldGljIGV2ZW50IG9iamVjdC4NCiAqIEBwYXJhbSB7U3RyaW5nfSBzcmMgVVJMIG9mIGNvbnRlbnQgdG8gbG9hZC4NCiAqLw0KDQoNCi8qKg0KICogQG5nZG9jIGV2ZW50DQogKiBAbmFtZSBuZ0luY2x1ZGUjJGluY2x1ZGVDb250ZW50RXJyb3INCiAqIEBldmVudFR5cGUgZW1pdCBvbiB0aGUgc2NvcGUgbmdJbmNsdWRlIHdhcyBkZWNsYXJlZCBpbg0KICogQGRlc2NyaXB0aW9uDQogKiBFbWl0dGVkIHdoZW4gYSB0ZW1wbGF0ZSBIVFRQIHJlcXVlc3QgeWllbGRzIGFuIGVycm9ub3VzIHJlc3BvbnNlIChzdGF0dXMgPCAyMDAgfHwgc3RhdHVzID4gMjk5KQ0KICoNCiAqIEBwYXJhbSB7T2JqZWN0fSBhbmd1bGFyRXZlbnQgU3ludGhldGljIGV2ZW50IG9iamVjdC4NCiAqIEBwYXJhbSB7U3RyaW5nfSBzcmMgVVJMIG9mIGNvbnRlbnQgdG8gbG9hZC4NCiAqLw0KdmFyIG5nSW5jbHVkZURpcmVjdGl2ZSA9IFsnJHRlbXBsYXRlUmVxdWVzdCcsICckYW5jaG9yU2Nyb2xsJywgJyRhbmltYXRlJywgJyRzY2UnLA0KICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oJHRlbXBsYXRlUmVxdWVzdCwgICAkYW5jaG9yU2Nyb2xsLCAgICRhbmltYXRlLCAgICRzY2UpIHsNCiAgcmV0dXJuIHsNCiAgICByZXN0cmljdDogJ0VDQScsDQogICAgcHJpb3JpdHk6IDQwMCwNCiAgICB0ZXJtaW5hbDogdHJ1ZSwNCiAgICB0cmFuc2NsdWRlOiAnZWxlbWVudCcsDQogICAgY29udHJvbGxlcjogYW5ndWxhci5ub29wLA0KICAgIGNvbXBpbGU6IGZ1bmN0aW9uKGVsZW1lbnQsIGF0dHIpIHsNCiAgICAgIHZhciBzcmNFeHAgPSBhdHRyLm5nSW5jbHVkZSB8fCBhdHRyLnNyYywNCiAgICAgICAgICBvbmxvYWRFeHAgPSBhdHRyLm9ubG9hZCB8fCAnJywNCiAgICAgICAgICBhdXRvU2Nyb2xsRXhwID0gYXR0ci5hdXRvc2Nyb2xsOw0KDQogICAgICByZXR1cm4gZnVuY3Rpb24oc2NvcGUsICRlbGVtZW50LCAkYXR0ciwgY3RybCwgJHRyYW5zY2x1ZGUpIHsNCiAgICAgICAgdmFyIGNoYW5nZUNvdW50ZXIgPSAwLA0KICAgICAgICAgICAgY3VycmVudFNjb3BlLA0KICAgICAgICAgICAgcHJldmlvdXNFbGVtZW50LA0KICAgICAgICAgICAgY3VycmVudEVsZW1lbnQ7DQoNCiAgICAgICAgdmFyIGNsZWFudXBMYXN0SW5jbHVkZUNvbnRlbnQgPSBmdW5jdGlvbigpIHsNCiAgICAgICAgICBpZiAocHJldmlvdXNFbGVtZW50KSB7DQogICAgICAgICAgICBwcmV2aW91c0VsZW1lbnQucmVtb3ZlKCk7DQogICAgICAgICAgICBwcmV2aW91c0VsZW1lbnQgPSBudWxsOw0KICAgICAgICAgIH0NCiAgICAgICAgICBpZiAoY3VycmVudFNjb3BlKSB7DQogICAgICAgICAgICBjdXJyZW50U2NvcGUuJGRlc3Ryb3koKTsNCiAgICAgICAgICAgIGN1cnJlbnRTY29wZSA9IG51bGw7DQogICAgICAgICAgfQ0KICAgICAgICAgIGlmIChjdXJyZW50RWxlbWVudCkgew0KICAgICAgICAgICAgJGFuaW1hdGUubGVhdmUoY3VycmVudEVsZW1lbnQpLnRoZW4oZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgIHByZXZpb3VzRWxlbWVudCA9IG51bGw7DQogICAgICAgICAgICB9KTsNCiAgICAgICAgICAgIHByZXZpb3VzRWxlbWVudCA9IGN1cnJlbnRFbGVtZW50Ow0KICAgICAgICAgICAgY3VycmVudEVsZW1lbnQgPSBudWxsOw0KICAgICAgICAgIH0NCiAgICAgICAgfTsNCg0KICAgICAgICBzY29wZS4kd2F0Y2goJHNjZS5wYXJzZUFzUmVzb3VyY2VVcmwoc3JjRXhwKSwgZnVuY3Rpb24gbmdJbmNsdWRlV2F0Y2hBY3Rpb24oc3JjKSB7DQogICAgICAgICAgdmFyIGFmdGVyQW5pbWF0aW9uID0gZnVuY3Rpb24oKSB7DQogICAgICAgICAgICBpZiAoaXNEZWZpbmVkKGF1dG9TY3JvbGxFeHApICYmICghYXV0b1Njcm9sbEV4cCB8fCBzY29wZS4kZXZhbChhdXRvU2Nyb2xsRXhwKSkpIHsNCiAgICAgICAgICAgICAgJGFuY2hvclNjcm9sbCgpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH07DQogICAgICAgICAgdmFyIHRoaXNDaGFuZ2VJZCA9ICsrY2hhbmdlQ291bnRlcjsNCg0KICAgICAgICAgIGlmIChzcmMpIHsNCiAgICAgICAgICAgIC8vc2V0IHRoZSAybmQgcGFyYW0gdG8gdHJ1ZSB0byBpZ25vcmUgdGhlIHRlbXBsYXRlIHJlcXVlc3QgZXJyb3Igc28gdGhhdCB0aGUgaW5uZXINCiAgICAgICAgICAgIC8vY29udGVudHMgYW5kIHNjb3BlIGNhbiBiZSBjbGVhbmVkIHVwLg0KICAgICAgICAgICAgJHRlbXBsYXRlUmVxdWVzdChzcmMsIHRydWUpLnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHsNCiAgICAgICAgICAgICAgaWYgKHRoaXNDaGFuZ2VJZCAhPT0gY2hhbmdlQ291bnRlcikgcmV0dXJuOw0KICAgICAgICAgICAgICB2YXIgbmV3U2NvcGUgPSBzY29wZS4kbmV3KCk7DQogICAgICAgICAgICAgIGN0cmwudGVtcGxhdGUgPSByZXNwb25zZTsNCg0KICAgICAgICAgICAgICAvLyBOb3RlOiBUaGlzIHdpbGwgYWxzbyBsaW5rIGFsbCBjaGlsZHJlbiBvZiBuZy1pbmNsdWRlIHRoYXQgd2VyZSBjb250YWluZWQgaW4gdGhlIG9yaWdpbmFsDQogICAgICAgICAgICAgIC8vIGh0bWwuIElmIHRoYXQgY29udGVudCBjb250YWlucyBjb250cm9sbGVycywgLi4uIHRoZXkgY291bGQgcG9sbHV0ZS9jaGFuZ2UgdGhlIHNjb3BlLg0KICAgICAgICAgICAgICAvLyBIb3dldmVyLCB1c2luZyBuZy1pbmNsdWRlIG9uIGFuIGVsZW1lbnQgd2l0aCBhZGRpdGlvbmFsIGNvbnRlbnQgZG9lcyBub3QgbWFrZSBzZW5zZS4uLg0KICAgICAgICAgICAgICAvLyBOb3RlOiBXZSBjYW4ndCByZW1vdmUgdGhlbSBpbiB0aGUgY2xvbmVBdHRjaEZuIG9mICR0cmFuc2NsdWRlIGFzIHRoYXQNCiAgICAgICAgICAgICAgLy8gZnVuY3Rpb24gaXMgY2FsbGVkIGJlZm9yZSBsaW5raW5nIHRoZSBjb250ZW50LCB3aGljaCB3b3VsZCBhcHBseSBjaGlsZA0KICAgICAgICAgICAgICAvLyBkaXJlY3RpdmVzIHRvIG5vbiBleGlzdGluZyBlbGVtZW50cy4NCiAgICAgICAgICAgICAgdmFyIGNsb25lID0gJHRyYW5zY2x1ZGUobmV3U2NvcGUsIGZ1bmN0aW9uKGNsb25lKSB7DQogICAgICAgICAgICAgICAgY2xlYW51cExhc3RJbmNsdWRlQ29udGVudCgpOw0KICAgICAgICAgICAgICAgICRhbmltYXRlLmVudGVyKGNsb25lLCBudWxsLCAkZWxlbWVudCkudGhlbihhZnRlckFuaW1hdGlvbik7DQogICAgICAgICAgICAgIH0pOw0KDQogICAgICAgICAgICAgIGN1cnJlbnRTY29wZSA9IG5ld1Njb3BlOw0KICAgICAgICAgICAgICBjdXJyZW50RWxlbWVudCA9IGNsb25lOw0KDQogICAgICAgICAgICAgIGN1cnJlbnRTY29wZS4kZW1pdCgnJGluY2x1ZGVDb250ZW50TG9hZGVkJywgc3JjKTsNCiAgICAgICAgICAgICAgc2NvcGUuJGV2YWwob25sb2FkRXhwKTsNCiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgICBpZiAodGhpc0NoYW5nZUlkID09PSBjaGFuZ2VDb3VudGVyKSB7DQogICAgICAgICAgICAgICAgY2xlYW51cExhc3RJbmNsdWRlQ29udGVudCgpOw0KICAgICAgICAgICAgICAgIHNjb3BlLiRlbWl0KCckaW5jbHVkZUNvbnRlbnRFcnJvcicsIHNyYyk7DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0pOw0KICAgICAgICAgICAgc2NvcGUuJGVtaXQoJyRpbmNsdWRlQ29udGVudFJlcXVlc3RlZCcsIHNyYyk7DQogICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGNsZWFudXBMYXN0SW5jbHVkZUNvbnRlbnQoKTsNCiAgICAgICAgICAgIGN0cmwudGVtcGxhdGUgPSBudWxsOw0KICAgICAgICAgIH0NCiAgICAgICAgfSk7DQogICAgICB9Ow0KICAgIH0NCiAgfTsNCn1dOw0KDQovLyBUaGlzIGRpcmVjdGl2ZSBpcyBjYWxsZWQgZHVyaW5nIHRoZSAkdHJhbnNjbHVkZSBjYWxsIG9mIHRoZSBmaXJzdCBgbmdJbmNsdWRlYCBkaXJlY3RpdmUuDQovLyBJdCB3aWxsIHJlcGxhY2UgYW5kIGNvbXBpbGUgdGhlIGNvbnRlbnQgb2YgdGhlIGVsZW1lbnQgd2l0aCB0aGUgbG9hZGVkIHRlbXBsYXRlLg0KLy8gV2UgbmVlZCB0aGlzIGRpcmVjdGl2ZSBzbyB0aGF0IHRoZSBlbGVtZW50IGNvbnRlbnQgaXMgYWxyZWFkeSBmaWxsZWQgd2hlbg0KLy8gdGhlIGxpbmsgZnVuY3Rpb24gb2YgYW5vdGhlciBkaXJlY3RpdmUgb24gdGhlIHNhbWUgZWxlbWVudCBhcyBuZ0luY2x1ZGUNCi8vIGlzIGNhbGxlZC4NCnZhciBuZ0luY2x1ZGVGaWxsQ29udGVudERpcmVjdGl2ZSA9IFsnJGNvbXBpbGUnLA0KICBmdW5jdGlvbigkY29tcGlsZSkgew0KICAgIHJldHVybiB7DQogICAgICByZXN0cmljdDogJ0VDQScsDQogICAgICBwcmlvcml0eTogLTQwMCwNCiAgICAgIHJlcXVpcmU6ICduZ0luY2x1ZGUnLA0KICAgICAgbGluazogZnVuY3Rpb24oc2NvcGUsICRlbGVtZW50LCAkYXR0ciwgY3RybCkgew0KICAgICAgICBpZiAoL1NWRy8udGVzdCgkZWxlbWVudFswXS50b1N0cmluZygpKSkgew0KICAgICAgICAgIC8vIFdlYktpdDogaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTEzNTY5OCAtLS0gU1ZHIGVsZW1lbnRzIGRvIG5vdA0KICAgICAgICAgIC8vIHN1cHBvcnQgaW5uZXJIVE1MLCBzbyBkZXRlY3QgdGhpcyBoZXJlIGFuZCB0cnkgdG8gZ2VuZXJhdGUgdGhlIGNvbnRlbnRzDQogICAgICAgICAgLy8gc3BlY2lhbGx5Lg0KICAgICAgICAgICRlbGVtZW50LmVtcHR5KCk7DQogICAgICAgICAgJGNvbXBpbGUoanFMaXRlQnVpbGRGcmFnbWVudChjdHJsLnRlbXBsYXRlLCBkb2N1bWVudCkuY2hpbGROb2Rlcykoc2NvcGUsDQogICAgICAgICAgICAgIGZ1bmN0aW9uIG5hbWVzcGFjZUFkYXB0ZWRDbG9uZShjbG9uZSkgew0KICAgICAgICAgICAgJGVsZW1lbnQuYXBwZW5kKGNsb25lKTsNCiAgICAgICAgICB9LCB7ZnV0dXJlUGFyZW50RWxlbWVudDogJGVsZW1lbnR9KTsNCiAgICAgICAgICByZXR1cm47DQogICAgICAgIH0NCg0KICAgICAgICAkZWxlbWVudC5odG1sKGN0cmwudGVtcGxhdGUpOw0KICAgICAgICAkY29tcGlsZSgkZWxlbWVudC5jb250ZW50cygpKShzY29wZSk7DQogICAgICB9DQogICAgfTsNCiAgfV07DQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdJbml0DQogKiBAcmVzdHJpY3QgQUMNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFRoZSBgbmdJbml0YCBkaXJlY3RpdmUgYWxsb3dzIHlvdSB0byBldmFsdWF0ZSBhbiBleHByZXNzaW9uIGluIHRoZQ0KICogY3VycmVudCBzY29wZS4NCiAqDQogKiA8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1lcnJvciI+DQogKiBUaGUgb25seSBhcHByb3ByaWF0ZSB1c2Ugb2YgYG5nSW5pdGAgaXMgZm9yIGFsaWFzaW5nIHNwZWNpYWwgcHJvcGVydGllcyBvZg0KICoge0BsaW5rIG5nLmRpcmVjdGl2ZTpuZ1JlcGVhdCBgbmdSZXBlYXRgfSwgYXMgc2VlbiBpbiB0aGUgZGVtbyBiZWxvdy4gQmVzaWRlcyB0aGlzIGNhc2UsIHlvdQ0KICogc2hvdWxkIHVzZSB7QGxpbmsgZ3VpZGUvY29udHJvbGxlciBjb250cm9sbGVyc30gcmF0aGVyIHRoYW4gYG5nSW5pdGANCiAqIHRvIGluaXRpYWxpemUgdmFsdWVzIG9uIGEgc2NvcGUuDQogKiA8L2Rpdj4NCiAqIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXdhcm5pbmciPg0KICogKipOb3RlKio6IElmIHlvdSBoYXZlIGFzc2lnbm1lbnQgaW4gYG5nSW5pdGAgYWxvbmcgd2l0aCB7QGxpbmsgbmcuJGZpbHRlciBgJGZpbHRlcmB9LCBtYWtlDQogKiBzdXJlIHlvdSBoYXZlIHBhcmVudGhlc2lzIGZvciBjb3JyZWN0IHByZWNlZGVuY2U6DQogKiA8cHJlIGNsYXNzPSJwcmV0dHlwcmludCI+DQogKiAgIDxkaXYgbmctaW5pdD0idGVzdDEgPSAoZGF0YSB8IG9yZGVyQnk6J25hbWUnKSI+PC9kaXY+DQogKiA8L3ByZT4NCiAqIDwvZGl2Pg0KICoNCiAqIEBwcmlvcml0eSA0NTANCiAqDQogKiBAZWxlbWVudCBBTlkNCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdJbml0IHtAbGluayBndWlkZS9leHByZXNzaW9uIEV4cHJlc3Npb259IHRvIGV2YWwuDQogKg0KICogQGV4YW1wbGUNCiAgIDxleGFtcGxlIG1vZHVsZT0iaW5pdEV4YW1wbGUiPg0KICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgIDxzY3JpcHQ+DQogICAgIGFuZ3VsYXIubW9kdWxlKCdpbml0RXhhbXBsZScsIFtdKQ0KICAgICAgIC5jb250cm9sbGVyKCdFeGFtcGxlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgICAkc2NvcGUubGlzdCA9IFtbJ2EnLCAnYiddLCBbJ2MnLCAnZCddXTsNCiAgICAgICB9XSk7DQogICA8L3NjcmlwdD4NCiAgIDxkaXYgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICA8ZGl2IG5nLXJlcGVhdD0iaW5uZXJMaXN0IGluIGxpc3QiIG5nLWluaXQ9Im91dGVySW5kZXggPSAkaW5kZXgiPg0KICAgICAgIDxkaXYgbmctcmVwZWF0PSJ2YWx1ZSBpbiBpbm5lckxpc3QiIG5nLWluaXQ9ImlubmVySW5kZXggPSAkaW5kZXgiPg0KICAgICAgICAgIDxzcGFuIGNsYXNzPSJleGFtcGxlLWluaXQiPmxpc3RbIHt7b3V0ZXJJbmRleH19IF1bIHt7aW5uZXJJbmRleH19IF0gPSB7e3ZhbHVlfX07PC9zcGFuPg0KICAgICAgIDwvZGl2Pg0KICAgICA8L2Rpdj4NCiAgIDwvZGl2Pg0KICAgICA8L2ZpbGU+DQogICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgIGl0KCdzaG91bGQgYWxpYXMgaW5kZXggcG9zaXRpb25zJywgZnVuY3Rpb24oKSB7DQogICAgICAgICB2YXIgZWxlbWVudHMgPSBlbGVtZW50LmFsbChieS5jc3MoJy5leGFtcGxlLWluaXQnKSk7DQogICAgICAgICBleHBlY3QoZWxlbWVudHMuZ2V0KDApLmdldFRleHQoKSkudG9CZSgnbGlzdFsgMCBdWyAwIF0gPSBhOycpOw0KICAgICAgICAgZXhwZWN0KGVsZW1lbnRzLmdldCgxKS5nZXRUZXh0KCkpLnRvQmUoJ2xpc3RbIDAgXVsgMSBdID0gYjsnKTsNCiAgICAgICAgIGV4cGVjdChlbGVtZW50cy5nZXQoMikuZ2V0VGV4dCgpKS50b0JlKCdsaXN0WyAxIF1bIDAgXSA9IGM7Jyk7DQogICAgICAgICBleHBlY3QoZWxlbWVudHMuZ2V0KDMpLmdldFRleHQoKSkudG9CZSgnbGlzdFsgMSBdWyAxIF0gPSBkOycpOw0KICAgICAgIH0pOw0KICAgICA8L2ZpbGU+DQogICA8L2V4YW1wbGU+DQogKi8NCnZhciBuZ0luaXREaXJlY3RpdmUgPSBuZ0RpcmVjdGl2ZSh7DQogIHByaW9yaXR5OiA0NTAsDQogIGNvbXBpbGU6IGZ1bmN0aW9uKCkgew0KICAgIHJldHVybiB7DQogICAgICBwcmU6IGZ1bmN0aW9uKHNjb3BlLCBlbGVtZW50LCBhdHRycykgew0KICAgICAgICBzY29wZS4kZXZhbChhdHRycy5uZ0luaXQpOw0KICAgICAgfQ0KICAgIH07DQogIH0NCn0pOw0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nTm9uQmluZGFibGUNCiAqIEByZXN0cmljdCBBQw0KICogQHByaW9yaXR5IDEwMDANCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFRoZSBgbmdOb25CaW5kYWJsZWAgZGlyZWN0aXZlIHRlbGxzIEFuZ3VsYXIgbm90IHRvIGNvbXBpbGUgb3IgYmluZCB0aGUgY29udGVudHMgb2YgdGhlIGN1cnJlbnQNCiAqIERPTSBlbGVtZW50LiBUaGlzIGlzIHVzZWZ1bCBpZiB0aGUgZWxlbWVudCBjb250YWlucyB3aGF0IGFwcGVhcnMgdG8gYmUgQW5ndWxhciBkaXJlY3RpdmVzIGFuZA0KICogYmluZGluZ3MgYnV0IHdoaWNoIHNob3VsZCBiZSBpZ25vcmVkIGJ5IEFuZ3VsYXIuIFRoaXMgY291bGQgYmUgdGhlIGNhc2UgaWYgeW91IGhhdmUgYSBzaXRlIHRoYXQNCiAqIGRpc3BsYXlzIHNuaXBwZXRzIG9mIGNvZGUsIGZvciBpbnN0YW5jZS4NCiAqDQogKiBAZWxlbWVudCBBTlkNCiAqDQogKiBAZXhhbXBsZQ0KICogSW4gdGhpcyBleGFtcGxlIHRoZXJlIGFyZSB0d28gbG9jYXRpb25zIHdoZXJlIGEgc2ltcGxlIGludGVycG9sYXRpb24gYmluZGluZyAoYHt7fX1gKSBpcyBwcmVzZW50LA0KICogYnV0IHRoZSBvbmUgd3JhcHBlZCBpbiBgbmdOb25CaW5kYWJsZWAgaXMgbGVmdCBhbG9uZS4NCiAqDQogKiBAZXhhbXBsZQ0KICAgIDxleGFtcGxlPg0KICAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgIDxkaXY+Tm9ybWFsOiB7ezEgKyAyfX08L2Rpdj4NCiAgICAgICAgPGRpdiBuZy1ub24tYmluZGFibGU+SWdub3JlZDoge3sxICsgMn19PC9kaXY+DQogICAgICA8L2ZpbGU+DQogICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICBpdCgnc2hvdWxkIGNoZWNrIG5nLW5vbi1iaW5kYWJsZScsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuYmluZGluZygnMSArIDInKSkuZ2V0VGV4dCgpKS50b0NvbnRhaW4oJzMnKTsNCiAgICAgICAgIGV4cGVjdChlbGVtZW50LmFsbChieS5jc3MoJ2RpdicpKS5sYXN0KCkuZ2V0VGV4dCgpKS50b01hdGNoKC8xIFwrIDIvKTsNCiAgICAgICB9KTsNCiAgICAgIDwvZmlsZT4NCiAgICA8L2V4YW1wbGU+DQogKi8NCnZhciBuZ05vbkJpbmRhYmxlRGlyZWN0aXZlID0gbmdEaXJlY3RpdmUoeyB0ZXJtaW5hbDogdHJ1ZSwgcHJpb3JpdHk6IDEwMDAgfSk7DQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdQbHVyYWxpemUNCiAqIEByZXN0cmljdCBFQQ0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogYG5nUGx1cmFsaXplYCBpcyBhIGRpcmVjdGl2ZSB0aGF0IGRpc3BsYXlzIG1lc3NhZ2VzIGFjY29yZGluZyB0byBlbi1VUyBsb2NhbGl6YXRpb24gcnVsZXMuDQogKiBUaGVzZSBydWxlcyBhcmUgYnVuZGxlZCB3aXRoIGFuZ3VsYXIuanMsIGJ1dCBjYW4gYmUgb3ZlcnJpZGRlbg0KICogKHNlZSB7QGxpbmsgZ3VpZGUvaTE4biBBbmd1bGFyIGkxOG59IGRldiBndWlkZSkuIFlvdSBjb25maWd1cmUgbmdQbHVyYWxpemUgZGlyZWN0aXZlDQogKiBieSBzcGVjaWZ5aW5nIHRoZSBtYXBwaW5ncyBiZXR3ZWVuDQogKiBbcGx1cmFsIGNhdGVnb3JpZXNdKGh0dHA6Ly91bmljb2RlLm9yZy9yZXBvcy9jbGRyLXRtcC90cnVuay9kaWZmL3N1cHBsZW1lbnRhbC9sYW5ndWFnZV9wbHVyYWxfcnVsZXMuaHRtbCkNCiAqIGFuZCB0aGUgc3RyaW5ncyB0byBiZSBkaXNwbGF5ZWQuDQogKg0KICogIyBQbHVyYWwgY2F0ZWdvcmllcyBhbmQgZXhwbGljaXQgbnVtYmVyIHJ1bGVzDQogKiBUaGVyZSBhcmUgdHdvDQogKiBbcGx1cmFsIGNhdGVnb3JpZXNdKGh0dHA6Ly91bmljb2RlLm9yZy9yZXBvcy9jbGRyLXRtcC90cnVuay9kaWZmL3N1cHBsZW1lbnRhbC9sYW5ndWFnZV9wbHVyYWxfcnVsZXMuaHRtbCkNCiAqIGluIEFuZ3VsYXIncyBkZWZhdWx0IGVuLVVTIGxvY2FsZTogIm9uZSIgYW5kICJvdGhlciIuDQogKg0KICogV2hpbGUgYSBwbHVyYWwgY2F0ZWdvcnkgbWF5IG1hdGNoIG1hbnkgbnVtYmVycyAoZm9yIGV4YW1wbGUsIGluIGVuLVVTIGxvY2FsZSwgIm90aGVyIiBjYW4gbWF0Y2gNCiAqIGFueSBudW1iZXIgdGhhdCBpcyBub3QgMSksIGFuIGV4cGxpY2l0IG51bWJlciBydWxlIGNhbiBvbmx5IG1hdGNoIG9uZSBudW1iZXIuIEZvciBleGFtcGxlLCB0aGUNCiAqIGV4cGxpY2l0IG51bWJlciBydWxlIGZvciAiMyIgbWF0Y2hlcyB0aGUgbnVtYmVyIDMuIFRoZXJlIGFyZSBleGFtcGxlcyBvZiBwbHVyYWwgY2F0ZWdvcmllcw0KICogYW5kIGV4cGxpY2l0IG51bWJlciBydWxlcyB0aHJvdWdob3V0IHRoZSByZXN0IG9mIHRoaXMgZG9jdW1lbnRhdGlvbi4NCiAqDQogKiAjIENvbmZpZ3VyaW5nIG5nUGx1cmFsaXplDQogKiBZb3UgY29uZmlndXJlIG5nUGx1cmFsaXplIGJ5IHByb3ZpZGluZyAyIGF0dHJpYnV0ZXM6IGBjb3VudGAgYW5kIGB3aGVuYC4NCiAqIFlvdSBjYW4gYWxzbyBwcm92aWRlIGFuIG9wdGlvbmFsIGF0dHJpYnV0ZSwgYG9mZnNldGAuDQogKg0KICogVGhlIHZhbHVlIG9mIHRoZSBgY291bnRgIGF0dHJpYnV0ZSBjYW4gYmUgZWl0aGVyIGEgc3RyaW5nIG9yIGFuIHtAbGluayBndWlkZS9leHByZXNzaW9uDQogKiBBbmd1bGFyIGV4cHJlc3Npb259OyB0aGVzZSBhcmUgZXZhbHVhdGVkIG9uIHRoZSBjdXJyZW50IHNjb3BlIGZvciBpdHMgYm91bmQgdmFsdWUuDQogKg0KICogVGhlIGB3aGVuYCBhdHRyaWJ1dGUgc3BlY2lmaWVzIHRoZSBtYXBwaW5ncyBiZXR3ZWVuIHBsdXJhbCBjYXRlZ29yaWVzIGFuZCB0aGUgYWN0dWFsDQogKiBzdHJpbmcgdG8gYmUgZGlzcGxheWVkLiBUaGUgdmFsdWUgb2YgdGhlIGF0dHJpYnV0ZSBzaG91bGQgYmUgYSBKU09OIG9iamVjdC4NCiAqDQogKiBUaGUgZm9sbG93aW5nIGV4YW1wbGUgc2hvd3MgaG93IHRvIGNvbmZpZ3VyZSBuZ1BsdXJhbGl6ZToNCiAqDQogKiBgYGBodG1sDQogKiA8bmctcGx1cmFsaXplIGNvdW50PSJwZXJzb25Db3VudCINCiAgICAgICAgICAgICAgICAgd2hlbj0ieycwJzogJ05vYm9keSBpcyB2aWV3aW5nLicsDQogKiAgICAgICAgICAgICAgICAgICAgICAnb25lJzogJzEgcGVyc29uIGlzIHZpZXdpbmcuJywNCiAqICAgICAgICAgICAgICAgICAgICAgICdvdGhlcic6ICd7fSBwZW9wbGUgYXJlIHZpZXdpbmcuJ30iPg0KICogPC9uZy1wbHVyYWxpemU+DQogKmBgYA0KICoNCiAqIEluIHRoZSBleGFtcGxlLCBgIjA6IE5vYm9keSBpcyB2aWV3aW5nLiJgIGlzIGFuIGV4cGxpY2l0IG51bWJlciBydWxlLiBJZiB5b3UgZGlkIG5vdA0KICogc3BlY2lmeSB0aGlzIHJ1bGUsIDAgd291bGQgYmUgbWF0Y2hlZCB0byB0aGUgIm90aGVyIiBjYXRlZ29yeSBhbmQgIjAgcGVvcGxlIGFyZSB2aWV3aW5nIg0KICogd291bGQgYmUgc2hvd24gaW5zdGVhZCBvZiAiTm9ib2R5IGlzIHZpZXdpbmciLiBZb3UgY2FuIHNwZWNpZnkgYW4gZXhwbGljaXQgbnVtYmVyIHJ1bGUgZm9yDQogKiBvdGhlciBudW1iZXJzLCBmb3IgZXhhbXBsZSAxMiwgc28gdGhhdCBpbnN0ZWFkIG9mIHNob3dpbmcgIjEyIHBlb3BsZSBhcmUgdmlld2luZyIsIHlvdSBjYW4NCiAqIHNob3cgImEgZG96ZW4gcGVvcGxlIGFyZSB2aWV3aW5nIi4NCiAqDQogKiBZb3UgY2FuIHVzZSBhIHNldCBvZiBjbG9zZWQgYnJhY2VzIChge31gKSBhcyBhIHBsYWNlaG9sZGVyIGZvciB0aGUgbnVtYmVyIHRoYXQgeW91IHdhbnQgc3Vic3RpdHV0ZWQNCiAqIGludG8gcGx1cmFsaXplZCBzdHJpbmdzLiBJbiB0aGUgcHJldmlvdXMgZXhhbXBsZSwgQW5ndWxhciB3aWxsIHJlcGxhY2UgYHt9YCB3aXRoDQogKiA8c3BhbiBuZy1ub24tYmluZGFibGU+YHt7cGVyc29uQ291bnR9fWA8L3NwYW4+LiBUaGUgY2xvc2VkIGJyYWNlcyBge31gIGlzIGEgcGxhY2Vob2xkZXINCiAqIGZvciA8c3BhbiBuZy1ub24tYmluZGFibGU+e3tudW1iZXJFeHByZXNzaW9ufX08L3NwYW4+Lg0KICoNCiAqICMgQ29uZmlndXJpbmcgbmdQbHVyYWxpemUgd2l0aCBvZmZzZXQNCiAqIFRoZSBgb2Zmc2V0YCBhdHRyaWJ1dGUgYWxsb3dzIGZ1cnRoZXIgY3VzdG9taXphdGlvbiBvZiBwbHVyYWxpemVkIHRleHQsIHdoaWNoIGNhbiByZXN1bHQgaW4NCiAqIGEgYmV0dGVyIHVzZXIgZXhwZXJpZW5jZS4gRm9yIGV4YW1wbGUsIGluc3RlYWQgb2YgdGhlIG1lc3NhZ2UgIjQgcGVvcGxlIGFyZSB2aWV3aW5nIHRoaXMgZG9jdW1lbnQiLA0KICogeW91IG1pZ2h0IGRpc3BsYXkgIkpvaG4sIEthdGUgYW5kIDIgb3RoZXJzIGFyZSB2aWV3aW5nIHRoaXMgZG9jdW1lbnQiLg0KICogVGhlIG9mZnNldCBhdHRyaWJ1dGUgYWxsb3dzIHlvdSB0byBvZmZzZXQgYSBudW1iZXIgYnkgYW55IGRlc2lyZWQgdmFsdWUuDQogKiBMZXQncyB0YWtlIGEgbG9vayBhdCBhbiBleGFtcGxlOg0KICoNCiAqIGBgYGh0bWwNCiAqIDxuZy1wbHVyYWxpemUgY291bnQ9InBlcnNvbkNvdW50IiBvZmZzZXQ9Mg0KICogICAgICAgICAgICAgICB3aGVuPSJ7JzAnOiAnTm9ib2R5IGlzIHZpZXdpbmcuJywNCiAqICAgICAgICAgICAgICAgICAgICAgICcxJzogJ3t7cGVyc29uMX19IGlzIHZpZXdpbmcuJywNCiAqICAgICAgICAgICAgICAgICAgICAgICcyJzogJ3t7cGVyc29uMX19IGFuZCB7e3BlcnNvbjJ9fSBhcmUgdmlld2luZy4nLA0KICogICAgICAgICAgICAgICAgICAgICAgJ29uZSc6ICd7e3BlcnNvbjF9fSwge3twZXJzb24yfX0gYW5kIG9uZSBvdGhlciBwZXJzb24gYXJlIHZpZXdpbmcuJywNCiAqICAgICAgICAgICAgICAgICAgICAgICdvdGhlcic6ICd7e3BlcnNvbjF9fSwge3twZXJzb24yfX0gYW5kIHt9IG90aGVyIHBlb3BsZSBhcmUgdmlld2luZy4nfSI+DQogKiA8L25nLXBsdXJhbGl6ZT4NCiAqIGBgYA0KICoNCiAqIE5vdGljZSB0aGF0IHdlIGFyZSBzdGlsbCB1c2luZyB0d28gcGx1cmFsIGNhdGVnb3JpZXMob25lLCBvdGhlciksIGJ1dCB3ZSBhZGRlZA0KICogdGhyZWUgZXhwbGljaXQgbnVtYmVyIHJ1bGVzIDAsIDEgYW5kIDIuDQogKiBXaGVuIG9uZSBwZXJzb24sIHBlcmhhcHMgSm9obiwgdmlld3MgdGhlIGRvY3VtZW50LCAiSm9obiBpcyB2aWV3aW5nIiB3aWxsIGJlIHNob3duLg0KICogV2hlbiB0aHJlZSBwZW9wbGUgdmlldyB0aGUgZG9jdW1lbnQsIG5vIGV4cGxpY2l0IG51bWJlciBydWxlIGlzIGZvdW5kLCBzbw0KICogYW4gb2Zmc2V0IG9mIDIgaXMgdGFrZW4gb2ZmIDMsIGFuZCBBbmd1bGFyIHVzZXMgMSB0byBkZWNpZGUgdGhlIHBsdXJhbCBjYXRlZ29yeS4NCiAqIEluIHRoaXMgY2FzZSwgcGx1cmFsIGNhdGVnb3J5ICdvbmUnIGlzIG1hdGNoZWQgYW5kICJKb2huLCBNYXJ5IGFuZCBvbmUgb3RoZXIgcGVyc29uIGFyZSB2aWV3aW5nIg0KICogaXMgc2hvd24uDQogKg0KICogTm90ZSB0aGF0IHdoZW4geW91IHNwZWNpZnkgb2Zmc2V0cywgeW91IG11c3QgcHJvdmlkZSBleHBsaWNpdCBudW1iZXIgcnVsZXMgZm9yDQogKiBudW1iZXJzIGZyb20gMCB1cCB0byBhbmQgaW5jbHVkaW5nIHRoZSBvZmZzZXQuIElmIHlvdSB1c2UgYW4gb2Zmc2V0IG9mIDMsIGZvciBleGFtcGxlLA0KICogeW91IG11c3QgcHJvdmlkZSBleHBsaWNpdCBudW1iZXIgcnVsZXMgZm9yIDAsIDEsIDIgYW5kIDMuIFlvdSBtdXN0IGFsc28gcHJvdmlkZSBwbHVyYWwgc3RyaW5ncyBmb3INCiAqIHBsdXJhbCBjYXRlZ29yaWVzICJvbmUiIGFuZCAib3RoZXIiLg0KICoNCiAqIEBwYXJhbSB7c3RyaW5nfGV4cHJlc3Npb259IGNvdW50IFRoZSB2YXJpYWJsZSB0byBiZSBib3VuZCB0by4NCiAqIEBwYXJhbSB7c3RyaW5nfSB3aGVuIFRoZSBtYXBwaW5nIGJldHdlZW4gcGx1cmFsIGNhdGVnb3J5IHRvIGl0cyBjb3JyZXNwb25kaW5nIHN0cmluZ3MuDQogKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gZGVkdWN0IGZyb20gdGhlIHRvdGFsIG51bWJlci4NCiAqDQogKiBAZXhhbXBsZQ0KICAgIDxleGFtcGxlIG1vZHVsZT0icGx1cmFsaXplRXhhbXBsZSI+DQogICAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgICAgPHNjcmlwdD4NCiAgICAgICAgICBhbmd1bGFyLm1vZHVsZSgncGx1cmFsaXplRXhhbXBsZScsIFtdKQ0KICAgICAgICAgICAgLmNvbnRyb2xsZXIoJ0V4YW1wbGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICAgICAgICAgJHNjb3BlLnBlcnNvbjEgPSAnSWdvcic7DQogICAgICAgICAgICAgICRzY29wZS5wZXJzb24yID0gJ01pc2tvJzsNCiAgICAgICAgICAgICAgJHNjb3BlLnBlcnNvbkNvdW50ID0gMTsNCiAgICAgICAgICAgIH1dKTsNCiAgICAgICAgPC9zY3JpcHQ+DQogICAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICAgICAgIFBlcnNvbiAxOjxpbnB1dCB0eXBlPSJ0ZXh0IiBuZy1tb2RlbD0icGVyc29uMSIgdmFsdWU9Iklnb3IiIC8+PGJyLz4NCiAgICAgICAgICBQZXJzb24gMjo8aW5wdXQgdHlwZT0idGV4dCIgbmctbW9kZWw9InBlcnNvbjIiIHZhbHVlPSJNaXNrbyIgLz48YnIvPg0KICAgICAgICAgIE51bWJlciBvZiBQZW9wbGU6PGlucHV0IHR5cGU9InRleHQiIG5nLW1vZGVsPSJwZXJzb25Db3VudCIgdmFsdWU9IjEiIC8+PGJyLz4NCg0KICAgICAgICAgIDwhLS0tIEV4YW1wbGUgd2l0aCBzaW1wbGUgcGx1cmFsaXphdGlvbiBydWxlcyBmb3IgZW4gbG9jYWxlIC0tLT4NCiAgICAgICAgICBXaXRob3V0IE9mZnNldDoNCiAgICAgICAgICA8bmctcGx1cmFsaXplIGNvdW50PSJwZXJzb25Db3VudCINCiAgICAgICAgICAgICAgICAgICAgICAgIHdoZW49InsnMCc6ICdOb2JvZHkgaXMgdmlld2luZy4nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdvbmUnOiAnMSBwZXJzb24gaXMgdmlld2luZy4nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdvdGhlcic6ICd7fSBwZW9wbGUgYXJlIHZpZXdpbmcuJ30iPg0KICAgICAgICAgIDwvbmctcGx1cmFsaXplPjxicj4NCg0KICAgICAgICAgIDwhLS0tIEV4YW1wbGUgd2l0aCBvZmZzZXQgLS0tPg0KICAgICAgICAgIFdpdGggT2Zmc2V0KDIpOg0KICAgICAgICAgIDxuZy1wbHVyYWxpemUgY291bnQ9InBlcnNvbkNvdW50IiBvZmZzZXQ9Mg0KICAgICAgICAgICAgICAgICAgICAgICAgd2hlbj0ieycwJzogJ05vYm9keSBpcyB2aWV3aW5nLicsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJzEnOiAne3twZXJzb24xfX0gaXMgdmlld2luZy4nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcyJzogJ3t7cGVyc29uMX19IGFuZCB7e3BlcnNvbjJ9fSBhcmUgdmlld2luZy4nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdvbmUnOiAne3twZXJzb24xfX0sIHt7cGVyc29uMn19IGFuZCBvbmUgb3RoZXIgcGVyc29uIGFyZSB2aWV3aW5nLicsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ290aGVyJzogJ3t7cGVyc29uMX19LCB7e3BlcnNvbjJ9fSBhbmQge30gb3RoZXIgcGVvcGxlIGFyZSB2aWV3aW5nLid9Ij4NCiAgICAgICAgICA8L25nLXBsdXJhbGl6ZT4NCiAgICAgICAgPC9kaXY+DQogICAgICA8L2ZpbGU+DQogICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICAgaXQoJ3Nob3VsZCBzaG93IGNvcnJlY3QgcGx1cmFsaXplZCBzdHJpbmcnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgICB2YXIgd2l0aG91dE9mZnNldCA9IGVsZW1lbnQuYWxsKGJ5LmNzcygnbmctcGx1cmFsaXplJykpLmdldCgwKTsNCiAgICAgICAgICB2YXIgd2l0aE9mZnNldCA9IGVsZW1lbnQuYWxsKGJ5LmNzcygnbmctcGx1cmFsaXplJykpLmdldCgxKTsNCiAgICAgICAgICB2YXIgY291bnRJbnB1dCA9IGVsZW1lbnQoYnkubW9kZWwoJ3BlcnNvbkNvdW50JykpOw0KDQogICAgICAgICAgZXhwZWN0KHdpdGhvdXRPZmZzZXQuZ2V0VGV4dCgpKS50b0VxdWFsKCcxIHBlcnNvbiBpcyB2aWV3aW5nLicpOw0KICAgICAgICAgIGV4cGVjdCh3aXRoT2Zmc2V0LmdldFRleHQoKSkudG9FcXVhbCgnSWdvciBpcyB2aWV3aW5nLicpOw0KDQogICAgICAgICAgY291bnRJbnB1dC5jbGVhcigpOw0KICAgICAgICAgIGNvdW50SW5wdXQuc2VuZEtleXMoJzAnKTsNCg0KICAgICAgICAgIGV4cGVjdCh3aXRob3V0T2Zmc2V0LmdldFRleHQoKSkudG9FcXVhbCgnTm9ib2R5IGlzIHZpZXdpbmcuJyk7DQogICAgICAgICAgZXhwZWN0KHdpdGhPZmZzZXQuZ2V0VGV4dCgpKS50b0VxdWFsKCdOb2JvZHkgaXMgdmlld2luZy4nKTsNCg0KICAgICAgICAgIGNvdW50SW5wdXQuY2xlYXIoKTsNCiAgICAgICAgICBjb3VudElucHV0LnNlbmRLZXlzKCcyJyk7DQoNCiAgICAgICAgICBleHBlY3Qod2l0aG91dE9mZnNldC5nZXRUZXh0KCkpLnRvRXF1YWwoJzIgcGVvcGxlIGFyZSB2aWV3aW5nLicpOw0KICAgICAgICAgIGV4cGVjdCh3aXRoT2Zmc2V0LmdldFRleHQoKSkudG9FcXVhbCgnSWdvciBhbmQgTWlza28gYXJlIHZpZXdpbmcuJyk7DQoNCiAgICAgICAgICBjb3VudElucHV0LmNsZWFyKCk7DQogICAgICAgICAgY291bnRJbnB1dC5zZW5kS2V5cygnMycpOw0KDQogICAgICAgICAgZXhwZWN0KHdpdGhvdXRPZmZzZXQuZ2V0VGV4dCgpKS50b0VxdWFsKCczIHBlb3BsZSBhcmUgdmlld2luZy4nKTsNCiAgICAgICAgICBleHBlY3Qod2l0aE9mZnNldC5nZXRUZXh0KCkpLnRvRXF1YWwoJ0lnb3IsIE1pc2tvIGFuZCBvbmUgb3RoZXIgcGVyc29uIGFyZSB2aWV3aW5nLicpOw0KDQogICAgICAgICAgY291bnRJbnB1dC5jbGVhcigpOw0KICAgICAgICAgIGNvdW50SW5wdXQuc2VuZEtleXMoJzQnKTsNCg0KICAgICAgICAgIGV4cGVjdCh3aXRob3V0T2Zmc2V0LmdldFRleHQoKSkudG9FcXVhbCgnNCBwZW9wbGUgYXJlIHZpZXdpbmcuJyk7DQogICAgICAgICAgZXhwZWN0KHdpdGhPZmZzZXQuZ2V0VGV4dCgpKS50b0VxdWFsKCdJZ29yLCBNaXNrbyBhbmQgMiBvdGhlciBwZW9wbGUgYXJlIHZpZXdpbmcuJyk7DQogICAgICAgIH0pOw0KICAgICAgICBpdCgnc2hvdWxkIHNob3cgZGF0YS1ib3VuZCBuYW1lcycsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgIHZhciB3aXRoT2Zmc2V0ID0gZWxlbWVudC5hbGwoYnkuY3NzKCduZy1wbHVyYWxpemUnKSkuZ2V0KDEpOw0KICAgICAgICAgIHZhciBwZXJzb25Db3VudCA9IGVsZW1lbnQoYnkubW9kZWwoJ3BlcnNvbkNvdW50JykpOw0KICAgICAgICAgIHZhciBwZXJzb24xID0gZWxlbWVudChieS5tb2RlbCgncGVyc29uMScpKTsNCiAgICAgICAgICB2YXIgcGVyc29uMiA9IGVsZW1lbnQoYnkubW9kZWwoJ3BlcnNvbjInKSk7DQogICAgICAgICAgcGVyc29uQ291bnQuY2xlYXIoKTsNCiAgICAgICAgICBwZXJzb25Db3VudC5zZW5kS2V5cygnNCcpOw0KICAgICAgICAgIHBlcnNvbjEuY2xlYXIoKTsNCiAgICAgICAgICBwZXJzb24xLnNlbmRLZXlzKCdEaScpOw0KICAgICAgICAgIHBlcnNvbjIuY2xlYXIoKTsNCiAgICAgICAgICBwZXJzb24yLnNlbmRLZXlzKCdWb2p0YScpOw0KICAgICAgICAgIGV4cGVjdCh3aXRoT2Zmc2V0LmdldFRleHQoKSkudG9FcXVhbCgnRGksIFZvanRhIGFuZCAyIG90aGVyIHBlb3BsZSBhcmUgdmlld2luZy4nKTsNCiAgICAgICAgfSk7DQogICAgICA8L2ZpbGU+DQogICAgPC9leGFtcGxlPg0KICovDQp2YXIgbmdQbHVyYWxpemVEaXJlY3RpdmUgPSBbJyRsb2NhbGUnLCAnJGludGVycG9sYXRlJywgZnVuY3Rpb24oJGxvY2FsZSwgJGludGVycG9sYXRlKSB7DQogIHZhciBCUkFDRSA9IC97fS9nLA0KICAgICAgSVNfV0hFTiA9IC9ed2hlbihNaW51cyk/KC4rKSQvOw0KDQogIHJldHVybiB7DQogICAgcmVzdHJpY3Q6ICdFQScsDQogICAgbGluazogZnVuY3Rpb24oc2NvcGUsIGVsZW1lbnQsIGF0dHIpIHsNCiAgICAgIHZhciBudW1iZXJFeHAgPSBhdHRyLmNvdW50LA0KICAgICAgICAgIHdoZW5FeHAgPSBhdHRyLiRhdHRyLndoZW4gJiYgZWxlbWVudC5hdHRyKGF0dHIuJGF0dHIud2hlbiksIC8vIHdlIGhhdmUge3t9fSBpbiBhdHRycw0KICAgICAgICAgIG9mZnNldCA9IGF0dHIub2Zmc2V0IHx8IDAsDQogICAgICAgICAgd2hlbnMgPSBzY29wZS4kZXZhbCh3aGVuRXhwKSB8fCB7fSwNCiAgICAgICAgICB3aGVuc0V4cEZucyA9IHt9LA0KICAgICAgICAgIHN0YXJ0U3ltYm9sID0gJGludGVycG9sYXRlLnN0YXJ0U3ltYm9sKCksDQogICAgICAgICAgZW5kU3ltYm9sID0gJGludGVycG9sYXRlLmVuZFN5bWJvbCgpLA0KICAgICAgICAgIGJyYWNlUmVwbGFjZW1lbnQgPSBzdGFydFN5bWJvbCArIG51bWJlckV4cCArICctJyArIG9mZnNldCArIGVuZFN5bWJvbCwNCiAgICAgICAgICB3YXRjaFJlbW92ZXIgPSBhbmd1bGFyLm5vb3AsDQogICAgICAgICAgbGFzdENvdW50Ow0KDQogICAgICBmb3JFYWNoKGF0dHIsIGZ1bmN0aW9uKGV4cHJlc3Npb24sIGF0dHJpYnV0ZU5hbWUpIHsNCiAgICAgICAgdmFyIHRtcE1hdGNoID0gSVNfV0hFTi5leGVjKGF0dHJpYnV0ZU5hbWUpOw0KICAgICAgICBpZiAodG1wTWF0Y2gpIHsNCiAgICAgICAgICB2YXIgd2hlbktleSA9ICh0bXBNYXRjaFsxXSA/ICctJyA6ICcnKSArIGxvd2VyY2FzZSh0bXBNYXRjaFsyXSk7DQogICAgICAgICAgd2hlbnNbd2hlbktleV0gPSBlbGVtZW50LmF0dHIoYXR0ci4kYXR0clthdHRyaWJ1dGVOYW1lXSk7DQogICAgICAgIH0NCiAgICAgIH0pOw0KICAgICAgZm9yRWFjaCh3aGVucywgZnVuY3Rpb24oZXhwcmVzc2lvbiwga2V5KSB7DQogICAgICAgIHdoZW5zRXhwRm5zW2tleV0gPSAkaW50ZXJwb2xhdGUoZXhwcmVzc2lvbi5yZXBsYWNlKEJSQUNFLCBicmFjZVJlcGxhY2VtZW50KSk7DQoNCiAgICAgIH0pOw0KDQogICAgICBzY29wZS4kd2F0Y2gobnVtYmVyRXhwLCBmdW5jdGlvbiBuZ1BsdXJhbGl6ZVdhdGNoQWN0aW9uKG5ld1ZhbCkgew0KICAgICAgICB2YXIgY291bnQgPSBwYXJzZUZsb2F0KG5ld1ZhbCk7DQogICAgICAgIHZhciBjb3VudElzTmFOID0gaXNOYU4oY291bnQpOw0KDQogICAgICAgIGlmICghY291bnRJc05hTiAmJiAhKGNvdW50IGluIHdoZW5zKSkgew0KICAgICAgICAgIC8vIElmIGFuIGV4cGxpY2l0IG51bWJlciBydWxlIHN1Y2ggYXMgMSwgMiwgMy4uLiBpcyBkZWZpbmVkLCBqdXN0IHVzZSBpdC4NCiAgICAgICAgICAvLyBPdGhlcndpc2UsIGNoZWNrIGl0IGFnYWluc3QgcGx1cmFsaXphdGlvbiBydWxlcyBpbiAkbG9jYWxlIHNlcnZpY2UuDQogICAgICAgICAgY291bnQgPSAkbG9jYWxlLnBsdXJhbENhdChjb3VudCAtIG9mZnNldCk7DQogICAgICAgIH0NCg0KICAgICAgICAvLyBJZiBib3RoIGBjb3VudGAgYW5kIGBsYXN0Q291bnRgIGFyZSBOYU4sIHdlIGRvbid0IG5lZWQgdG8gcmUtcmVnaXN0ZXIgYSB3YXRjaC4NCiAgICAgICAgLy8gSW4gSlMgYE5hTiAhPT0gTmFOYCwgc28gd2UgaGF2ZSB0byBleGxpY2l0bHkgY2hlY2suDQogICAgICAgIGlmICgoY291bnQgIT09IGxhc3RDb3VudCkgJiYgIShjb3VudElzTmFOICYmIGlzTmFOKGxhc3RDb3VudCkpKSB7DQogICAgICAgICAgd2F0Y2hSZW1vdmVyKCk7DQogICAgICAgICAgd2F0Y2hSZW1vdmVyID0gc2NvcGUuJHdhdGNoKHdoZW5zRXhwRm5zW2NvdW50XSwgdXBkYXRlRWxlbWVudFRleHQpOw0KICAgICAgICAgIGxhc3RDb3VudCA9IGNvdW50Ow0KICAgICAgICB9DQogICAgICB9KTsNCg0KICAgICAgZnVuY3Rpb24gdXBkYXRlRWxlbWVudFRleHQobmV3VGV4dCkgew0KICAgICAgICBlbGVtZW50LnRleHQobmV3VGV4dCB8fCAnJyk7DQogICAgICB9DQogICAgfQ0KICB9Ow0KfV07DQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdSZXBlYXQNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFRoZSBgbmdSZXBlYXRgIGRpcmVjdGl2ZSBpbnN0YW50aWF0ZXMgYSB0ZW1wbGF0ZSBvbmNlIHBlciBpdGVtIGZyb20gYSBjb2xsZWN0aW9uLiBFYWNoIHRlbXBsYXRlDQogKiBpbnN0YW5jZSBnZXRzIGl0cyBvd24gc2NvcGUsIHdoZXJlIHRoZSBnaXZlbiBsb29wIHZhcmlhYmxlIGlzIHNldCB0byB0aGUgY3VycmVudCBjb2xsZWN0aW9uIGl0ZW0sDQogKiBhbmQgYCRpbmRleGAgaXMgc2V0IHRvIHRoZSBpdGVtIGluZGV4IG9yIGtleS4NCiAqDQogKiBTcGVjaWFsIHByb3BlcnRpZXMgYXJlIGV4cG9zZWQgb24gdGhlIGxvY2FsIHNjb3BlIG9mIGVhY2ggdGVtcGxhdGUgaW5zdGFuY2UsIGluY2x1ZGluZzoNCiAqDQogKiB8IFZhcmlhYmxlICB8IFR5cGUgICAgICAgICAgICB8IERldGFpbHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQogKiB8LS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18DQogKiB8IGAkaW5kZXhgICB8IHtAdHlwZSBudW1iZXJ9ICB8IGl0ZXJhdG9yIG9mZnNldCBvZiB0aGUgcmVwZWF0ZWQgZWxlbWVudCAoMC4ubGVuZ3RoLTEpICAgICAgICAgICAgICAgICAgICAgICB8DQogKiB8IGAkZmlyc3RgICB8IHtAdHlwZSBib29sZWFufSB8IHRydWUgaWYgdGhlIHJlcGVhdGVkIGVsZW1lbnQgaXMgZmlyc3QgaW4gdGhlIGl0ZXJhdG9yLiAgICAgICAgICAgICAgICAgICAgICB8DQogKiB8IGAkbWlkZGxlYCB8IHtAdHlwZSBib29sZWFufSB8IHRydWUgaWYgdGhlIHJlcGVhdGVkIGVsZW1lbnQgaXMgYmV0d2VlbiB0aGUgZmlyc3QgYW5kIGxhc3QgaW4gdGhlIGl0ZXJhdG9yLiB8DQogKiB8IGAkbGFzdGAgICB8IHtAdHlwZSBib29sZWFufSB8IHRydWUgaWYgdGhlIHJlcGVhdGVkIGVsZW1lbnQgaXMgbGFzdCBpbiB0aGUgaXRlcmF0b3IuICAgICAgICAgICAgICAgICAgICAgICB8DQogKiB8IGAkZXZlbmAgICB8IHtAdHlwZSBib29sZWFufSB8IHRydWUgaWYgdGhlIGl0ZXJhdG9yIHBvc2l0aW9uIGAkaW5kZXhgIGlzIGV2ZW4gKG90aGVyd2lzZSBmYWxzZSkuICAgICAgICAgICB8DQogKiB8IGAkb2RkYCAgICB8IHtAdHlwZSBib29sZWFufSB8IHRydWUgaWYgdGhlIGl0ZXJhdG9yIHBvc2l0aW9uIGAkaW5kZXhgIGlzIG9kZCAob3RoZXJ3aXNlIGZhbHNlKS4gICAgICAgICAgICB8DQogKg0KICogQ3JlYXRpbmcgYWxpYXNlcyBmb3IgdGhlc2UgcHJvcGVydGllcyBpcyBwb3NzaWJsZSB3aXRoIHtAbGluayBuZy5kaXJlY3RpdmU6bmdJbml0IGBuZ0luaXRgfS4NCiAqIFRoaXMgbWF5IGJlIHVzZWZ1bCB3aGVuLCBmb3IgaW5zdGFuY2UsIG5lc3RpbmcgbmdSZXBlYXRzLg0KICoNCiAqICMgU3BlY2lhbCByZXBlYXQgc3RhcnQgYW5kIGVuZCBwb2ludHMNCiAqIFRvIHJlcGVhdCBhIHNlcmllcyBvZiBlbGVtZW50cyBpbnN0ZWFkIG9mIGp1c3Qgb25lIHBhcmVudCBlbGVtZW50LCBuZ1JlcGVhdCAoYXMgd2VsbCBhcyBvdGhlciBuZyBkaXJlY3RpdmVzKSBzdXBwb3J0cyBleHRlbmRpbmcNCiAqIHRoZSByYW5nZSBvZiB0aGUgcmVwZWF0ZXIgYnkgZGVmaW5pbmcgZXhwbGljaXQgc3RhcnQgYW5kIGVuZCBwb2ludHMgYnkgdXNpbmcgKipuZy1yZXBlYXQtc3RhcnQqKiBhbmQgKipuZy1yZXBlYXQtZW5kKiogcmVzcGVjdGl2ZWx5Lg0KICogVGhlICoqbmctcmVwZWF0LXN0YXJ0KiogZGlyZWN0aXZlIHdvcmtzIHRoZSBzYW1lIGFzICoqbmctcmVwZWF0KiosIGJ1dCB3aWxsIHJlcGVhdCBhbGwgdGhlIEhUTUwgY29kZSAoaW5jbHVkaW5nIHRoZSB0YWcgaXQncyBkZWZpbmVkIG9uKQ0KICogdXAgdG8gYW5kIGluY2x1ZGluZyB0aGUgZW5kaW5nIEhUTUwgdGFnIHdoZXJlICoqbmctcmVwZWF0LWVuZCoqIGlzIHBsYWNlZC4NCiAqDQogKiBUaGUgZXhhbXBsZSBiZWxvdyBtYWtlcyB1c2Ugb2YgdGhpcyBmZWF0dXJlOg0KICogYGBgaHRtbA0KICogICA8aGVhZGVyIG5nLXJlcGVhdC1zdGFydD0iaXRlbSBpbiBpdGVtcyI+DQogKiAgICAgSGVhZGVyIHt7IGl0ZW0gfX0NCiAqICAgPC9oZWFkZXI+DQogKiAgIDxkaXYgY2xhc3M9ImJvZHkiPg0KICogICAgIEJvZHkge3sgaXRlbSB9fQ0KICogICA8L2Rpdj4NCiAqICAgPGZvb3RlciBuZy1yZXBlYXQtZW5kPg0KICogICAgIEZvb3RlciB7eyBpdGVtIH19DQogKiAgIDwvZm9vdGVyPg0KICogYGBgDQogKg0KICogQW5kIHdpdGggYW4gaW5wdXQgb2Yge0B0eXBlIFsnQScsJ0InXX0gZm9yIHRoZSBpdGVtcyB2YXJpYWJsZSBpbiB0aGUgZXhhbXBsZSBhYm92ZSwgdGhlIG91dHB1dCB3aWxsIGV2YWx1YXRlIHRvOg0KICogYGBgaHRtbA0KICogICA8aGVhZGVyPg0KICogICAgIEhlYWRlciBBDQogKiAgIDwvaGVhZGVyPg0KICogICA8ZGl2IGNsYXNzPSJib2R5Ij4NCiAqICAgICBCb2R5IEENCiAqICAgPC9kaXY+DQogKiAgIDxmb290ZXI+DQogKiAgICAgRm9vdGVyIEENCiAqICAgPC9mb290ZXI+DQogKiAgIDxoZWFkZXI+DQogKiAgICAgSGVhZGVyIEINCiAqICAgPC9oZWFkZXI+DQogKiAgIDxkaXYgY2xhc3M9ImJvZHkiPg0KICogICAgIEJvZHkgQg0KICogICA8L2Rpdj4NCiAqICAgPGZvb3Rlcj4NCiAqICAgICBGb290ZXIgQg0KICogICA8L2Zvb3Rlcj4NCiAqIGBgYA0KICoNCiAqIFRoZSBjdXN0b20gc3RhcnQgYW5kIGVuZCBwb2ludHMgZm9yIG5nUmVwZWF0IGFsc28gc3VwcG9ydCBhbGwgb3RoZXIgSFRNTCBkaXJlY3RpdmUgc3ludGF4IGZsYXZvcnMgcHJvdmlkZWQgaW4gQW5ndWxhckpTIChzdWNoDQogKiBhcyAqKmRhdGEtbmctcmVwZWF0LXN0YXJ0KiosICoqeC1uZy1yZXBlYXQtc3RhcnQqKiBhbmQgKipuZzpyZXBlYXQtc3RhcnQqKikuDQogKg0KICogQGFuaW1hdGlvbnMNCiAqICoqLmVudGVyKiogLSB3aGVuIGEgbmV3IGl0ZW0gaXMgYWRkZWQgdG8gdGhlIGxpc3Qgb3Igd2hlbiBhbiBpdGVtIGlzIHJldmVhbGVkIGFmdGVyIGEgZmlsdGVyDQogKg0KICogKioubGVhdmUqKiAtIHdoZW4gYW4gaXRlbSBpcyByZW1vdmVkIGZyb20gdGhlIGxpc3Qgb3Igd2hlbiBhbiBpdGVtIGlzIGZpbHRlcmVkIG91dA0KICoNCiAqICoqLm1vdmUqKiAtIHdoZW4gYW4gYWRqYWNlbnQgaXRlbSBpcyBmaWx0ZXJlZCBvdXQgY2F1c2luZyBhIHJlb3JkZXIgb3Igd2hlbiB0aGUgaXRlbSBjb250ZW50cyBhcmUgcmVvcmRlcmVkDQogKg0KICogQGVsZW1lbnQgQU5ZDQogKiBAc2NvcGUNCiAqIEBwcmlvcml0eSAxMDAwDQogKiBAcGFyYW0ge3JlcGVhdF9leHByZXNzaW9ufSBuZ1JlcGVhdCBUaGUgZXhwcmVzc2lvbiBpbmRpY2F0aW5nIGhvdyB0byBlbnVtZXJhdGUgYSBjb2xsZWN0aW9uLiBUaGVzZQ0KICogICBmb3JtYXRzIGFyZSBjdXJyZW50bHkgc3VwcG9ydGVkOg0KICoNCiAqICAgKiBgdmFyaWFibGUgaW4gZXhwcmVzc2lvbmAg4oA/IHdoZXJlIHZhcmlhYmxlIGlzIHRoZSB1c2VyIGRlZmluZWQgbG9vcCB2YXJpYWJsZSBhbmQgYGV4cHJlc3Npb25gDQogKiAgICAgaXMgYSBzY29wZSBleHByZXNzaW9uIGdpdmluZyB0aGUgY29sbGVjdGlvbiB0byBlbnVtZXJhdGUuDQogKg0KICogICAgIEZvciBleGFtcGxlOiBgYWxidW0gaW4gYXJ0aXN0LmFsYnVtc2AuDQogKg0KICogICAqIGAoa2V5LCB2YWx1ZSkgaW4gZXhwcmVzc2lvbmAg4oA/IHdoZXJlIGBrZXlgIGFuZCBgdmFsdWVgIGNhbiBiZSBhbnkgdXNlciBkZWZpbmVkIGlkZW50aWZpZXJzLA0KICogICAgIGFuZCBgZXhwcmVzc2lvbmAgaXMgdGhlIHNjb3BlIGV4cHJlc3Npb24gZ2l2aW5nIHRoZSBjb2xsZWN0aW9uIHRvIGVudW1lcmF0ZS4NCiAqDQogKiAgICAgRm9yIGV4YW1wbGU6IGAobmFtZSwgYWdlKSBpbiB7J2FkYW0nOjEwLCAnYW1hbGllJzoxMn1gLg0KICoNCiAqICAgKiBgdmFyaWFibGUgaW4gZXhwcmVzc2lvbiB0cmFjayBieSB0cmFja2luZ19leHByZXNzaW9uYCDigD8gWW91IGNhbiBhbHNvIHByb3ZpZGUgYW4gb3B0aW9uYWwgdHJhY2tpbmcgZnVuY3Rpb24NCiAqICAgICB3aGljaCBjYW4gYmUgdXNlZCB0byBhc3NvY2lhdGUgdGhlIG9iamVjdHMgaW4gdGhlIGNvbGxlY3Rpb24gd2l0aCB0aGUgRE9NIGVsZW1lbnRzLiBJZiBubyB0cmFja2luZyBmdW5jdGlvbg0KICogICAgIGlzIHNwZWNpZmllZCB0aGUgbmctcmVwZWF0IGFzc29jaWF0ZXMgZWxlbWVudHMgYnkgaWRlbnRpdHkgaW4gdGhlIGNvbGxlY3Rpb24uIEl0IGlzIGFuIGVycm9yIHRvIGhhdmUNCiAqICAgICBtb3JlIHRoYW4gb25lIHRyYWNraW5nIGZ1bmN0aW9uIHRvIHJlc29sdmUgdG8gdGhlIHNhbWUga2V5LiAoVGhpcyB3b3VsZCBtZWFuIHRoYXQgdHdvIGRpc3RpbmN0IG9iamVjdHMgYXJlDQogKiAgICAgbWFwcGVkIHRvIHRoZSBzYW1lIERPTSBlbGVtZW50LCB3aGljaCBpcyBub3QgcG9zc2libGUuKSAgRmlsdGVycyBzaG91bGQgYmUgYXBwbGllZCB0byB0aGUgZXhwcmVzc2lvbiwNCiAqICAgICBiZWZvcmUgc3BlY2lmeWluZyBhIHRyYWNraW5nIGV4cHJlc3Npb24uDQogKg0KICogICAgIEZvciBleGFtcGxlOiBgaXRlbSBpbiBpdGVtc2AgaXMgZXF1aXZhbGVudCB0byBgaXRlbSBpbiBpdGVtcyB0cmFjayBieSAkaWQoaXRlbSlgLiBUaGlzIGltcGxpZXMgdGhhdCB0aGUgRE9NIGVsZW1lbnRzDQogKiAgICAgd2lsbCBiZSBhc3NvY2lhdGVkIGJ5IGl0ZW0gaWRlbnRpdHkgaW4gdGhlIGFycmF5Lg0KICoNCiAqICAgICBGb3IgZXhhbXBsZTogYGl0ZW0gaW4gaXRlbXMgdHJhY2sgYnkgJGlkKGl0ZW0pYC4gQSBidWlsdCBpbiBgJGlkKClgIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGFzc2lnbiBhIHVuaXF1ZQ0KICogICAgIGAkJGhhc2hLZXlgIHByb3BlcnR5IHRvIGVhY2ggaXRlbSBpbiB0aGUgYXJyYXkuIFRoaXMgcHJvcGVydHkgaXMgdGhlbiB1c2VkIGFzIGEga2V5IHRvIGFzc29jaWF0ZWQgRE9NIGVsZW1lbnRzDQogKiAgICAgd2l0aCB0aGUgY29ycmVzcG9uZGluZyBpdGVtIGluIHRoZSBhcnJheSBieSBpZGVudGl0eS4gTW92aW5nIHRoZSBzYW1lIG9iamVjdCBpbiBhcnJheSB3b3VsZCBtb3ZlIHRoZSBET00NCiAqICAgICBlbGVtZW50IGluIHRoZSBzYW1lIHdheSBpbiB0aGUgRE9NLg0KICoNCiAqICAgICBGb3IgZXhhbXBsZTogYGl0ZW0gaW4gaXRlbXMgdHJhY2sgYnkgaXRlbS5pZGAgaXMgYSB0eXBpY2FsIHBhdHRlcm4gd2hlbiB0aGUgaXRlbXMgY29tZSBmcm9tIHRoZSBkYXRhYmFzZS4gSW4gdGhpcw0KICogICAgIGNhc2UgdGhlIG9iamVjdCBpZGVudGl0eSBkb2VzIG5vdCBtYXR0ZXIuIFR3byBvYmplY3RzIGFyZSBjb25zaWRlcmVkIGVxdWl2YWxlbnQgYXMgbG9uZyBhcyB0aGVpciBgaWRgDQogKiAgICAgcHJvcGVydHkgaXMgc2FtZS4NCiAqDQogKiAgICAgRm9yIGV4YW1wbGU6IGBpdGVtIGluIGl0ZW1zIHwgZmlsdGVyOnNlYXJjaFRleHQgdHJhY2sgYnkgaXRlbS5pZGAgaXMgYSBwYXR0ZXJuIHRoYXQgbWlnaHQgYmUgdXNlZCB0byBhcHBseSBhIGZpbHRlcg0KICogICAgIHRvIGl0ZW1zIGluIGNvbmp1bmN0aW9uIHdpdGggYSB0cmFja2luZyBleHByZXNzaW9uLg0KICoNCiAqICAgKiBgdmFyaWFibGUgaW4gZXhwcmVzc2lvbiBhcyBhbGlhc19leHByZXNzaW9uYCDigD8gWW91IGNhbiBhbHNvIHByb3ZpZGUgYW4gb3B0aW9uYWwgYWxpYXMgZXhwcmVzc2lvbiB3aGljaCB3aWxsIHRoZW4gc3RvcmUgdGhlDQogKiAgICAgaW50ZXJtZWRpYXRlIHJlc3VsdHMgb2YgdGhlIHJlcGVhdGVyIGFmdGVyIHRoZSBmaWx0ZXJzIGhhdmUgYmVlbiBhcHBsaWVkLiBUeXBpY2FsbHkgdGhpcyBpcyB1c2VkIHRvIHJlbmRlciBhIHNwZWNpYWwgbWVzc2FnZQ0KICogICAgIHdoZW4gYSBmaWx0ZXIgaXMgYWN0aXZlIG9uIHRoZSByZXBlYXRlciwgYnV0IHRoZSBmaWx0ZXJlZCByZXN1bHQgc2V0IGlzIGVtcHR5Lg0KICoNCiAqICAgICBGb3IgZXhhbXBsZTogYGl0ZW0gaW4gaXRlbXMgfCBmaWx0ZXI6eCBhcyByZXN1bHRzYCB3aWxsIHN0b3JlIHRoZSBmcmFnbWVudCBvZiB0aGUgcmVwZWF0ZWQgaXRlbXMgYXMgYHJlc3VsdHNgLCBidXQgb25seSBhZnRlcg0KICogICAgIHRoZSBpdGVtcyBoYXZlIGJlZW4gcHJvY2Vzc2VkIHRocm91Z2ggdGhlIGZpbHRlci4NCiAqDQogKiBAZXhhbXBsZQ0KICogVGhpcyBleGFtcGxlIGluaXRpYWxpemVzIHRoZSBzY29wZSB0byBhIGxpc3Qgb2YgbmFtZXMgYW5kDQogKiB0aGVuIHVzZXMgYG5nUmVwZWF0YCB0byBkaXNwbGF5IGV2ZXJ5IHBlcnNvbjoNCiAgPGV4YW1wbGUgbW9kdWxlPSJuZ0FuaW1hdGUiIGRlcHM9ImFuZ3VsYXItYW5pbWF0ZS5qcyIgYW5pbWF0aW9ucz0idHJ1ZSI+DQogICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICA8ZGl2IG5nLWluaXQ9ImZyaWVuZHMgPSBbDQogICAgICAgIHtuYW1lOidKb2huJywgYWdlOjI1LCBnZW5kZXI6J2JveSd9LA0KICAgICAgICB7bmFtZTonSmVzc2llJywgYWdlOjMwLCBnZW5kZXI6J2dpcmwnfSwNCiAgICAgICAge25hbWU6J0pvaGFubmEnLCBhZ2U6MjgsIGdlbmRlcjonZ2lybCd9LA0KICAgICAgICB7bmFtZTonSm95JywgYWdlOjE1LCBnZW5kZXI6J2dpcmwnfSwNCiAgICAgICAge25hbWU6J01hcnknLCBhZ2U6MjgsIGdlbmRlcjonZ2lybCd9LA0KICAgICAgICB7bmFtZTonUGV0ZXInLCBhZ2U6OTUsIGdlbmRlcjonYm95J30sDQogICAgICAgIHtuYW1lOidTZWJhc3RpYW4nLCBhZ2U6NTAsIGdlbmRlcjonYm95J30sDQogICAgICAgIHtuYW1lOidFcmlrYScsIGFnZToyNywgZ2VuZGVyOidnaXJsJ30sDQogICAgICAgIHtuYW1lOidQYXRyaWNrJywgYWdlOjQwLCBnZW5kZXI6J2JveSd9LA0KICAgICAgICB7bmFtZTonU2FtYW50aGEnLCBhZ2U6NjAsIGdlbmRlcjonZ2lybCd9DQogICAgICBdIj4NCiAgICAgICAgSSBoYXZlIHt7ZnJpZW5kcy5sZW5ndGh9fSBmcmllbmRzLiBUaGV5IGFyZToNCiAgICAgICAgPGlucHV0IHR5cGU9InNlYXJjaCIgbmctbW9kZWw9InEiIHBsYWNlaG9sZGVyPSJmaWx0ZXIgZnJpZW5kcy4uLiIgLz4NCiAgICAgICAgPHVsIGNsYXNzPSJleGFtcGxlLWFuaW1hdGUtY29udGFpbmVyIj4NCiAgICAgICAgICA8bGkgY2xhc3M9ImFuaW1hdGUtcmVwZWF0IiBuZy1yZXBlYXQ9ImZyaWVuZCBpbiBmcmllbmRzIHwgZmlsdGVyOnEgYXMgcmVzdWx0cyI+DQogICAgICAgICAgICBbe3skaW5kZXggKyAxfX1dIHt7ZnJpZW5kLm5hbWV9fSB3aG8gaXMge3tmcmllbmQuYWdlfX0geWVhcnMgb2xkLg0KICAgICAgICAgIDwvbGk+DQogICAgICAgICAgPGxpIGNsYXNzPSJhbmltYXRlLXJlcGVhdCIgbmctaWY9InJlc3VsdHMubGVuZ3RoID09IDAiPg0KICAgICAgICAgICAgPHN0cm9uZz5ObyByZXN1bHRzIGZvdW5kLi4uPC9zdHJvbmc+DQogICAgICAgICAgPC9saT4NCiAgICAgICAgPC91bD4NCiAgICAgIDwvZGl2Pg0KICAgIDwvZmlsZT4NCiAgICA8ZmlsZSBuYW1lPSJhbmltYXRpb25zLmNzcyI+DQogICAgICAuZXhhbXBsZS1hbmltYXRlLWNvbnRhaW5lciB7DQogICAgICAgIGJhY2tncm91bmQ6d2hpdGU7DQogICAgICAgIGJvcmRlcjoxcHggc29saWQgYmxhY2s7DQogICAgICAgIGxpc3Qtc3R5bGU6bm9uZTsNCiAgICAgICAgbWFyZ2luOjA7DQogICAgICAgIHBhZGRpbmc6MCAxMHB4Ow0KICAgICAgfQ0KDQogICAgICAuYW5pbWF0ZS1yZXBlYXQgew0KICAgICAgICBsaW5lLWhlaWdodDo0MHB4Ow0KICAgICAgICBsaXN0LXN0eWxlOm5vbmU7DQogICAgICAgIGJveC1zaXppbmc6Ym9yZGVyLWJveDsNCiAgICAgIH0NCg0KICAgICAgLmFuaW1hdGUtcmVwZWF0Lm5nLW1vdmUsDQogICAgICAuYW5pbWF0ZS1yZXBlYXQubmctZW50ZXIsDQogICAgICAuYW5pbWF0ZS1yZXBlYXQubmctbGVhdmUgew0KICAgICAgICAtd2Via2l0LXRyYW5zaXRpb246YWxsIGxpbmVhciAwLjVzOw0KICAgICAgICB0cmFuc2l0aW9uOmFsbCBsaW5lYXIgMC41czsNCiAgICAgIH0NCg0KICAgICAgLmFuaW1hdGUtcmVwZWF0Lm5nLWxlYXZlLm5nLWxlYXZlLWFjdGl2ZSwNCiAgICAgIC5hbmltYXRlLXJlcGVhdC5uZy1tb3ZlLA0KICAgICAgLmFuaW1hdGUtcmVwZWF0Lm5nLWVudGVyIHsNCiAgICAgICAgb3BhY2l0eTowOw0KICAgICAgICBtYXgtaGVpZ2h0OjA7DQogICAgICB9DQoNCiAgICAgIC5hbmltYXRlLXJlcGVhdC5uZy1sZWF2ZSwNCiAgICAgIC5hbmltYXRlLXJlcGVhdC5uZy1tb3ZlLm5nLW1vdmUtYWN0aXZlLA0KICAgICAgLmFuaW1hdGUtcmVwZWF0Lm5nLWVudGVyLm5nLWVudGVyLWFjdGl2ZSB7DQogICAgICAgIG9wYWNpdHk6MTsNCiAgICAgICAgbWF4LWhlaWdodDo0MHB4Ow0KICAgICAgfQ0KICAgIDwvZmlsZT4NCiAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgIHZhciBmcmllbmRzID0gZWxlbWVudC5hbGwoYnkucmVwZWF0ZXIoJ2ZyaWVuZCBpbiBmcmllbmRzJykpOw0KDQogICAgICBpdCgnc2hvdWxkIHJlbmRlciBpbml0aWFsIGRhdGEgc2V0JywgZnVuY3Rpb24oKSB7DQogICAgICAgIGV4cGVjdChmcmllbmRzLmNvdW50KCkpLnRvQmUoMTApOw0KICAgICAgICBleHBlY3QoZnJpZW5kcy5nZXQoMCkuZ2V0VGV4dCgpKS50b0VxdWFsKCdbMV0gSm9obiB3aG8gaXMgMjUgeWVhcnMgb2xkLicpOw0KICAgICAgICBleHBlY3QoZnJpZW5kcy5nZXQoMSkuZ2V0VGV4dCgpKS50b0VxdWFsKCdbMl0gSmVzc2llIHdobyBpcyAzMCB5ZWFycyBvbGQuJyk7DQogICAgICAgIGV4cGVjdChmcmllbmRzLmxhc3QoKS5nZXRUZXh0KCkpLnRvRXF1YWwoJ1sxMF0gU2FtYW50aGEgd2hvIGlzIDYwIHllYXJzIG9sZC4nKTsNCiAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuYmluZGluZygnZnJpZW5kcy5sZW5ndGgnKSkuZ2V0VGV4dCgpKQ0KICAgICAgICAgICAgLnRvTWF0Y2goIkkgaGF2ZSAxMCBmcmllbmRzLiBUaGV5IGFyZToiKTsNCiAgICAgIH0pOw0KDQogICAgICAgaXQoJ3Nob3VsZCB1cGRhdGUgcmVwZWF0ZXIgd2hlbiBmaWx0ZXIgcHJlZGljYXRlIGNoYW5nZXMnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgIGV4cGVjdChmcmllbmRzLmNvdW50KCkpLnRvQmUoMTApOw0KDQogICAgICAgICBlbGVtZW50KGJ5Lm1vZGVsKCdxJykpLnNlbmRLZXlzKCdtYScpOw0KDQogICAgICAgICBleHBlY3QoZnJpZW5kcy5jb3VudCgpKS50b0JlKDIpOw0KICAgICAgICAgZXhwZWN0KGZyaWVuZHMuZ2V0KDApLmdldFRleHQoKSkudG9FcXVhbCgnWzFdIE1hcnkgd2hvIGlzIDI4IHllYXJzIG9sZC4nKTsNCiAgICAgICAgIGV4cGVjdChmcmllbmRzLmxhc3QoKS5nZXRUZXh0KCkpLnRvRXF1YWwoJ1syXSBTYW1hbnRoYSB3aG8gaXMgNjAgeWVhcnMgb2xkLicpOw0KICAgICAgIH0pOw0KICAgICAgPC9maWxlPg0KICAgIDwvZXhhbXBsZT4NCiAqLw0KdmFyIG5nUmVwZWF0RGlyZWN0aXZlID0gWyckcGFyc2UnLCAnJGFuaW1hdGUnLCBmdW5jdGlvbigkcGFyc2UsICRhbmltYXRlKSB7DQogIHZhciBOR19SRU1PVkVEID0gJyQkTkdfUkVNT1ZFRCc7DQogIHZhciBuZ1JlcGVhdE1pbkVyciA9IG1pbkVycignbmdSZXBlYXQnKTsNCg0KICB2YXIgdXBkYXRlU2NvcGUgPSBmdW5jdGlvbihzY29wZSwgaW5kZXgsIHZhbHVlSWRlbnRpZmllciwgdmFsdWUsIGtleUlkZW50aWZpZXIsIGtleSwgYXJyYXlMZW5ndGgpIHsNCiAgICAvLyBUT0RPKHBlcmYpOiBnZW5lcmF0ZSBzZXR0ZXJzIHRvIHNoYXZlIG9mZiB+NDBtcyBvciAxLTEuNSUNCiAgICBzY29wZVt2YWx1ZUlkZW50aWZpZXJdID0gdmFsdWU7DQogICAgaWYgKGtleUlkZW50aWZpZXIpIHNjb3BlW2tleUlkZW50aWZpZXJdID0ga2V5Ow0KICAgIHNjb3BlLiRpbmRleCA9IGluZGV4Ow0KICAgIHNjb3BlLiRmaXJzdCA9IChpbmRleCA9PT0gMCk7DQogICAgc2NvcGUuJGxhc3QgPSAoaW5kZXggPT09IChhcnJheUxlbmd0aCAtIDEpKTsNCiAgICBzY29wZS4kbWlkZGxlID0gIShzY29wZS4kZmlyc3QgfHwgc2NvcGUuJGxhc3QpOw0KICAgIC8vIGpzaGludCBiaXR3aXNlOiBmYWxzZQ0KICAgIHNjb3BlLiRvZGQgPSAhKHNjb3BlLiRldmVuID0gKGluZGV4JjEpID09PSAwKTsNCiAgICAvLyBqc2hpbnQgYml0d2lzZTogdHJ1ZQ0KICB9Ow0KDQogIHZhciBnZXRCbG9ja1N0YXJ0ID0gZnVuY3Rpb24oYmxvY2spIHsNCiAgICByZXR1cm4gYmxvY2suY2xvbmVbMF07DQogIH07DQoNCiAgdmFyIGdldEJsb2NrRW5kID0gZnVuY3Rpb24oYmxvY2spIHsNCiAgICByZXR1cm4gYmxvY2suY2xvbmVbYmxvY2suY2xvbmUubGVuZ3RoIC0gMV07DQogIH07DQoNCg0KICByZXR1cm4gew0KICAgIHJlc3RyaWN0OiAnQScsDQogICAgbXVsdGlFbGVtZW50OiB0cnVlLA0KICAgIHRyYW5zY2x1ZGU6ICdlbGVtZW50JywNCiAgICBwcmlvcml0eTogMTAwMCwNCiAgICB0ZXJtaW5hbDogdHJ1ZSwNCiAgICAkJHRsYjogdHJ1ZSwNCiAgICBjb21waWxlOiBmdW5jdGlvbiBuZ1JlcGVhdENvbXBpbGUoJGVsZW1lbnQsICRhdHRyKSB7DQogICAgICB2YXIgZXhwcmVzc2lvbiA9ICRhdHRyLm5nUmVwZWF0Ow0KICAgICAgdmFyIG5nUmVwZWF0RW5kQ29tbWVudCA9IGRvY3VtZW50LmNyZWF0ZUNvbW1lbnQoJyBlbmQgbmdSZXBlYXQ6ICcgKyBleHByZXNzaW9uICsgJyAnKTsNCg0KICAgICAgdmFyIG1hdGNoID0gZXhwcmVzc2lvbi5tYXRjaCgvXlxzKihbXHNcU10rPylccytpblxzKyhbXHNcU10rPykoPzpccythc1xzKyhbXHNcU10rPykpPyg/OlxzK3RyYWNrXHMrYnlccysoW1xzXFNdKz8pKT9ccyokLyk7DQoNCiAgICAgIGlmICghbWF0Y2gpIHsNCiAgICAgICAgdGhyb3cgbmdSZXBlYXRNaW5FcnIoJ2lleHAnLCAiRXhwZWN0ZWQgZXhwcmVzc2lvbiBpbiBmb3JtIG9mICdfaXRlbV8gaW4gX2NvbGxlY3Rpb25fWyB0cmFjayBieSBfaWRfXScgYnV0IGdvdCAnezB9Jy4iLA0KICAgICAgICAgICAgZXhwcmVzc2lvbik7DQogICAgICB9DQoNCiAgICAgIHZhciBsaHMgPSBtYXRjaFsxXTsNCiAgICAgIHZhciByaHMgPSBtYXRjaFsyXTsNCiAgICAgIHZhciBhbGlhc0FzID0gbWF0Y2hbM107DQogICAgICB2YXIgdHJhY2tCeUV4cCA9IG1hdGNoWzRdOw0KDQogICAgICBtYXRjaCA9IGxocy5tYXRjaCgvXig/OihccypbXCRcd10rKXxcKFxzKihbXCRcd10rKVxzKixccyooW1wkXHddKylccypcKSkkLyk7DQoNCiAgICAgIGlmICghbWF0Y2gpIHsNCiAgICAgICAgdGhyb3cgbmdSZXBlYXRNaW5FcnIoJ2lpZGV4cCcsICInX2l0ZW1fJyBpbiAnX2l0ZW1fIGluIF9jb2xsZWN0aW9uXycgc2hvdWxkIGJlIGFuIGlkZW50aWZpZXIgb3IgJyhfa2V5XywgX3ZhbHVlXyknIGV4cHJlc3Npb24sIGJ1dCBnb3QgJ3swfScuIiwNCiAgICAgICAgICAgIGxocyk7DQogICAgICB9DQogICAgICB2YXIgdmFsdWVJZGVudGlmaWVyID0gbWF0Y2hbM10gfHwgbWF0Y2hbMV07DQogICAgICB2YXIga2V5SWRlbnRpZmllciA9IG1hdGNoWzJdOw0KDQogICAgICBpZiAoYWxpYXNBcyAmJiAoIS9eWyRhLXpBLVpfXVskYS16QS1aMC05X10qJC8udGVzdChhbGlhc0FzKSB8fA0KICAgICAgICAgIC9eKG51bGx8dW5kZWZpbmVkfHRoaXN8XCRpbmRleHxcJGZpcnN0fFwkbWlkZGxlfFwkbGFzdHxcJGV2ZW58XCRvZGR8XCRwYXJlbnQpJC8udGVzdChhbGlhc0FzKSkpIHsNCiAgICAgICAgdGhyb3cgbmdSZXBlYXRNaW5FcnIoJ2JhZGlkZW50JywgImFsaWFzICd7MH0nIGlzIGludmFsaWQgLS0tIG11c3QgYmUgYSB2YWxpZCBKUyBpZGVudGlmaWVyIHdoaWNoIGlzIG5vdCBhIHJlc2VydmVkIG5hbWUuIiwNCiAgICAgICAgICBhbGlhc0FzKTsNCiAgICAgIH0NCg0KICAgICAgdmFyIHRyYWNrQnlFeHBHZXR0ZXIsIHRyYWNrQnlJZEV4cEZuLCB0cmFja0J5SWRBcnJheUZuLCB0cmFja0J5SWRPYmpGbjsNCiAgICAgIHZhciBoYXNoRm5Mb2NhbHMgPSB7JGlkOiBoYXNoS2V5fTsNCg0KICAgICAgaWYgKHRyYWNrQnlFeHApIHsNCiAgICAgICAgdHJhY2tCeUV4cEdldHRlciA9ICRwYXJzZSh0cmFja0J5RXhwKTsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIHRyYWNrQnlJZEFycmF5Rm4gPSBmdW5jdGlvbihrZXksIHZhbHVlKSB7DQogICAgICAgICAgcmV0dXJuIGhhc2hLZXkodmFsdWUpOw0KICAgICAgICB9Ow0KICAgICAgICB0cmFja0J5SWRPYmpGbiA9IGZ1bmN0aW9uKGtleSkgew0KICAgICAgICAgIHJldHVybiBrZXk7DQogICAgICAgIH07DQogICAgICB9DQoNCiAgICAgIHJldHVybiBmdW5jdGlvbiBuZ1JlcGVhdExpbmsoJHNjb3BlLCAkZWxlbWVudCwgJGF0dHIsIGN0cmwsICR0cmFuc2NsdWRlKSB7DQoNCiAgICAgICAgaWYgKHRyYWNrQnlFeHBHZXR0ZXIpIHsNCiAgICAgICAgICB0cmFja0J5SWRFeHBGbiA9IGZ1bmN0aW9uKGtleSwgdmFsdWUsIGluZGV4KSB7DQogICAgICAgICAgICAvLyBhc3NpZ24ga2V5LCB2YWx1ZSwgYW5kICRpbmRleCB0byB0aGUgbG9jYWxzIHNvIHRoYXQgdGhleSBjYW4gYmUgdXNlZCBpbiBoYXNoIGZ1bmN0aW9ucw0KICAgICAgICAgICAgaWYgKGtleUlkZW50aWZpZXIpIGhhc2hGbkxvY2Fsc1trZXlJZGVudGlmaWVyXSA9IGtleTsNCiAgICAgICAgICAgIGhhc2hGbkxvY2Fsc1t2YWx1ZUlkZW50aWZpZXJdID0gdmFsdWU7DQogICAgICAgICAgICBoYXNoRm5Mb2NhbHMuJGluZGV4ID0gaW5kZXg7DQogICAgICAgICAgICByZXR1cm4gdHJhY2tCeUV4cEdldHRlcigkc2NvcGUsIGhhc2hGbkxvY2Fscyk7DQogICAgICAgICAgfTsNCiAgICAgICAgfQ0KDQogICAgICAgIC8vIFN0b3JlIGEgbGlzdCBvZiBlbGVtZW50cyBmcm9tIHByZXZpb3VzIHJ1bi4gVGhpcyBpcyBhIGhhc2ggd2hlcmUga2V5IGlzIHRoZSBpdGVtIGZyb20gdGhlDQogICAgICAgIC8vIGl0ZXJhdG9yLCBhbmQgdGhlIHZhbHVlIGlzIG9iamVjdHMgd2l0aCBmb2xsb3dpbmcgcHJvcGVydGllcy4NCiAgICAgICAgLy8gICAtIHNjb3BlOiBib3VuZCBzY29wZQ0KICAgICAgICAvLyAgIC0gZWxlbWVudDogcHJldmlvdXMgZWxlbWVudC4NCiAgICAgICAgLy8gICAtIGluZGV4OiBwb3NpdGlvbg0KICAgICAgICAvLw0KICAgICAgICAvLyBXZSBhcmUgdXNpbmcgbm8tcHJvdG8gb2JqZWN0IHNvIHRoYXQgd2UgZG9uJ3QgbmVlZCB0byBndWFyZCBhZ2FpbnN0IGluaGVyaXRlZCBwcm9wcyB2aWENCiAgICAgICAgLy8gaGFzT3duUHJvcGVydHkuDQogICAgICAgIHZhciBsYXN0QmxvY2tNYXAgPSBjcmVhdGVNYXAoKTsNCg0KICAgICAgICAvL3dhdGNoIHByb3BzDQogICAgICAgICRzY29wZS4kd2F0Y2hDb2xsZWN0aW9uKHJocywgZnVuY3Rpb24gbmdSZXBlYXRBY3Rpb24oY29sbGVjdGlvbikgew0KICAgICAgICAgIHZhciBpbmRleCwgbGVuZ3RoLA0KICAgICAgICAgICAgICBwcmV2aW91c05vZGUgPSAkZWxlbWVudFswXSwgICAgIC8vIG5vZGUgdGhhdCBjbG9uZWQgbm9kZXMgc2hvdWxkIGJlIGluc2VydGVkIGFmdGVyDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5pdGlhbGl6ZWQgdG8gdGhlIGNvbW1lbnQgbm9kZSBhbmNob3INCiAgICAgICAgICAgICAgbmV4dE5vZGUsDQogICAgICAgICAgICAgIC8vIFNhbWUgYXMgbGFzdEJsb2NrTWFwIGJ1dCBpdCBoYXMgdGhlIGN1cnJlbnQgc3RhdGUuIEl0IHdpbGwgYmVjb21lIHRoZQ0KICAgICAgICAgICAgICAvLyBsYXN0QmxvY2tNYXAgb24gdGhlIG5leHQgaXRlcmF0aW9uLg0KICAgICAgICAgICAgICBuZXh0QmxvY2tNYXAgPSBjcmVhdGVNYXAoKSwNCiAgICAgICAgICAgICAgY29sbGVjdGlvbkxlbmd0aCwNCiAgICAgICAgICAgICAga2V5LCB2YWx1ZSwgLy8ga2V5L3ZhbHVlIG9mIGl0ZXJhdGlvbg0KICAgICAgICAgICAgICB0cmFja0J5SWQsDQogICAgICAgICAgICAgIHRyYWNrQnlJZEZuLA0KICAgICAgICAgICAgICBjb2xsZWN0aW9uS2V5cywNCiAgICAgICAgICAgICAgYmxvY2ssICAgICAgIC8vIGxhc3Qgb2JqZWN0IGluZm9ybWF0aW9uIHtzY29wZSwgZWxlbWVudCwgaWR9DQogICAgICAgICAgICAgIG5leHRCbG9ja09yZGVyLA0KICAgICAgICAgICAgICBlbGVtZW50c1RvUmVtb3ZlOw0KDQogICAgICAgICAgaWYgKGFsaWFzQXMpIHsNCiAgICAgICAgICAgICRzY29wZVthbGlhc0FzXSA9IGNvbGxlY3Rpb247DQogICAgICAgICAgfQ0KDQogICAgICAgICAgaWYgKGlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pKSB7DQogICAgICAgICAgICBjb2xsZWN0aW9uS2V5cyA9IGNvbGxlY3Rpb247DQogICAgICAgICAgICB0cmFja0J5SWRGbiA9IHRyYWNrQnlJZEV4cEZuIHx8IHRyYWNrQnlJZEFycmF5Rm47DQogICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIHRyYWNrQnlJZEZuID0gdHJhY2tCeUlkRXhwRm4gfHwgdHJhY2tCeUlkT2JqRm47DQogICAgICAgICAgICAvLyBpZiBvYmplY3QsIGV4dHJhY3Qga2V5cywgc29ydCB0aGVtIGFuZCB1c2UgdG8gZGV0ZXJtaW5lIG9yZGVyIG9mIGl0ZXJhdGlvbiBvdmVyIG9iaiBwcm9wcw0KICAgICAgICAgICAgY29sbGVjdGlvbktleXMgPSBbXTsNCiAgICAgICAgICAgIGZvciAodmFyIGl0ZW1LZXkgaW4gY29sbGVjdGlvbikgew0KICAgICAgICAgICAgICBpZiAoY29sbGVjdGlvbi5oYXNPd25Qcm9wZXJ0eShpdGVtS2V5KSAmJiBpdGVtS2V5LmNoYXJBdCgwKSAhPSAnJCcpIHsNCiAgICAgICAgICAgICAgICBjb2xsZWN0aW9uS2V5cy5wdXNoKGl0ZW1LZXkpOw0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgICBjb2xsZWN0aW9uS2V5cy5zb3J0KCk7DQogICAgICAgICAgfQ0KDQogICAgICAgICAgY29sbGVjdGlvbkxlbmd0aCA9IGNvbGxlY3Rpb25LZXlzLmxlbmd0aDsNCiAgICAgICAgICBuZXh0QmxvY2tPcmRlciA9IG5ldyBBcnJheShjb2xsZWN0aW9uTGVuZ3RoKTsNCg0KICAgICAgICAgIC8vIGxvY2F0ZSBleGlzdGluZyBpdGVtcw0KICAgICAgICAgIGZvciAoaW5kZXggPSAwOyBpbmRleCA8IGNvbGxlY3Rpb25MZW5ndGg7IGluZGV4KyspIHsNCiAgICAgICAgICAgIGtleSA9IChjb2xsZWN0aW9uID09PSBjb2xsZWN0aW9uS2V5cykgPyBpbmRleCA6IGNvbGxlY3Rpb25LZXlzW2luZGV4XTsNCiAgICAgICAgICAgIHZhbHVlID0gY29sbGVjdGlvbltrZXldOw0KICAgICAgICAgICAgdHJhY2tCeUlkID0gdHJhY2tCeUlkRm4oa2V5LCB2YWx1ZSwgaW5kZXgpOw0KICAgICAgICAgICAgaWYgKGxhc3RCbG9ja01hcFt0cmFja0J5SWRdKSB7DQogICAgICAgICAgICAgIC8vIGZvdW5kIHByZXZpb3VzbHkgc2VlbiBibG9jaw0KICAgICAgICAgICAgICBibG9jayA9IGxhc3RCbG9ja01hcFt0cmFja0J5SWRdOw0KICAgICAgICAgICAgICBkZWxldGUgbGFzdEJsb2NrTWFwW3RyYWNrQnlJZF07DQogICAgICAgICAgICAgIG5leHRCbG9ja01hcFt0cmFja0J5SWRdID0gYmxvY2s7DQogICAgICAgICAgICAgIG5leHRCbG9ja09yZGVyW2luZGV4XSA9IGJsb2NrOw0KICAgICAgICAgICAgfSBlbHNlIGlmIChuZXh0QmxvY2tNYXBbdHJhY2tCeUlkXSkgew0KICAgICAgICAgICAgICAvLyBpZiBjb2xsaXNpb24gZGV0ZWN0ZWQuIHJlc3RvcmUgbGFzdEJsb2NrTWFwIGFuZCB0aHJvdyBhbiBlcnJvcg0KICAgICAgICAgICAgICBmb3JFYWNoKG5leHRCbG9ja09yZGVyLCBmdW5jdGlvbihibG9jaykgew0KICAgICAgICAgICAgICAgIGlmIChibG9jayAmJiBibG9jay5zY29wZSkgbGFzdEJsb2NrTWFwW2Jsb2NrLmlkXSA9IGJsb2NrOw0KICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICAgICAgdGhyb3cgbmdSZXBlYXRNaW5FcnIoJ2R1cGVzJywNCiAgICAgICAgICAgICAgICAgICJEdXBsaWNhdGVzIGluIGEgcmVwZWF0ZXIgYXJlIG5vdCBhbGxvd2VkLiBVc2UgJ3RyYWNrIGJ5JyBleHByZXNzaW9uIHRvIHNwZWNpZnkgdW5pcXVlIGtleXMuIFJlcGVhdGVyOiB7MH0sIER1cGxpY2F0ZSBrZXk6IHsxfSwgRHVwbGljYXRlIHZhbHVlOiB7Mn0iLA0KICAgICAgICAgICAgICAgICAgZXhwcmVzc2lvbiwgdHJhY2tCeUlkLCB2YWx1ZSk7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAvLyBuZXcgbmV2ZXIgYmVmb3JlIHNlZW4gYmxvY2sNCiAgICAgICAgICAgICAgbmV4dEJsb2NrT3JkZXJbaW5kZXhdID0ge2lkOiB0cmFja0J5SWQsIHNjb3BlOiB1bmRlZmluZWQsIGNsb25lOiB1bmRlZmluZWR9Ow0KICAgICAgICAgICAgICBuZXh0QmxvY2tNYXBbdHJhY2tCeUlkXSA9IHRydWU7DQogICAgICAgICAgICB9DQogICAgICAgICAgfQ0KDQogICAgICAgICAgLy8gcmVtb3ZlIGxlZnRvdmVyIGl0ZW1zDQogICAgICAgICAgZm9yICh2YXIgYmxvY2tLZXkgaW4gbGFzdEJsb2NrTWFwKSB7DQogICAgICAgICAgICBibG9jayA9IGxhc3RCbG9ja01hcFtibG9ja0tleV07DQogICAgICAgICAgICBlbGVtZW50c1RvUmVtb3ZlID0gZ2V0QmxvY2tOb2RlcyhibG9jay5jbG9uZSk7DQogICAgICAgICAgICAkYW5pbWF0ZS5sZWF2ZShlbGVtZW50c1RvUmVtb3ZlKTsNCiAgICAgICAgICAgIGlmIChlbGVtZW50c1RvUmVtb3ZlWzBdLnBhcmVudE5vZGUpIHsNCiAgICAgICAgICAgICAgLy8gaWYgdGhlIGVsZW1lbnQgd2FzIG5vdCByZW1vdmVkIHlldCBiZWNhdXNlIG9mIHBlbmRpbmcgYW5pbWF0aW9uLCBtYXJrIGl0IGFzIGRlbGV0ZWQNCiAgICAgICAgICAgICAgLy8gc28gdGhhdCB3ZSBjYW4gaWdub3JlIGl0IGxhdGVyDQogICAgICAgICAgICAgIGZvciAoaW5kZXggPSAwLCBsZW5ndGggPSBlbGVtZW50c1RvUmVtb3ZlLmxlbmd0aDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHsNCiAgICAgICAgICAgICAgICBlbGVtZW50c1RvUmVtb3ZlW2luZGV4XVtOR19SRU1PVkVEXSA9IHRydWU7DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGJsb2NrLnNjb3BlLiRkZXN0cm95KCk7DQogICAgICAgICAgfQ0KDQogICAgICAgICAgLy8gd2UgYXJlIG5vdCB1c2luZyBmb3JFYWNoIGZvciBwZXJmIHJlYXNvbnMgKHRyeWluZyB0byBhdm9pZCAjY2FsbCkNCiAgICAgICAgICBmb3IgKGluZGV4ID0gMDsgaW5kZXggPCBjb2xsZWN0aW9uTGVuZ3RoOyBpbmRleCsrKSB7DQogICAgICAgICAgICBrZXkgPSAoY29sbGVjdGlvbiA9PT0gY29sbGVjdGlvbktleXMpID8gaW5kZXggOiBjb2xsZWN0aW9uS2V5c1tpbmRleF07DQogICAgICAgICAgICB2YWx1ZSA9IGNvbGxlY3Rpb25ba2V5XTsNCiAgICAgICAgICAgIGJsb2NrID0gbmV4dEJsb2NrT3JkZXJbaW5kZXhdOw0KDQogICAgICAgICAgICBpZiAoYmxvY2suc2NvcGUpIHsNCiAgICAgICAgICAgICAgLy8gaWYgd2UgaGF2ZSBhbHJlYWR5IHNlZW4gdGhpcyBvYmplY3QsIHRoZW4gd2UgbmVlZCB0byByZXVzZSB0aGUNCiAgICAgICAgICAgICAgLy8gYXNzb2NpYXRlZCBzY29wZS9lbGVtZW50DQoNCiAgICAgICAgICAgICAgbmV4dE5vZGUgPSBwcmV2aW91c05vZGU7DQoNCiAgICAgICAgICAgICAgLy8gc2tpcCBub2RlcyB0aGF0IGFyZSBhbHJlYWR5IHBlbmRpbmcgcmVtb3ZhbCB2aWEgbGVhdmUgYW5pbWF0aW9uDQogICAgICAgICAgICAgIGRvIHsNCiAgICAgICAgICAgICAgICBuZXh0Tm9kZSA9IG5leHROb2RlLm5leHRTaWJsaW5nOw0KICAgICAgICAgICAgICB9IHdoaWxlIChuZXh0Tm9kZSAmJiBuZXh0Tm9kZVtOR19SRU1PVkVEXSk7DQoNCiAgICAgICAgICAgICAgaWYgKGdldEJsb2NrU3RhcnQoYmxvY2spICE9IG5leHROb2RlKSB7DQogICAgICAgICAgICAgICAgLy8gZXhpc3RpbmcgaXRlbSB3aGljaCBnb3QgbW92ZWQNCiAgICAgICAgICAgICAgICAkYW5pbWF0ZS5tb3ZlKGdldEJsb2NrTm9kZXMoYmxvY2suY2xvbmUpLCBudWxsLCBqcUxpdGUocHJldmlvdXNOb2RlKSk7DQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgcHJldmlvdXNOb2RlID0gZ2V0QmxvY2tFbmQoYmxvY2spOw0KICAgICAgICAgICAgICB1cGRhdGVTY29wZShibG9jay5zY29wZSwgaW5kZXgsIHZhbHVlSWRlbnRpZmllciwgdmFsdWUsIGtleUlkZW50aWZpZXIsIGtleSwgY29sbGVjdGlvbkxlbmd0aCk7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAvLyBuZXcgaXRlbSB3aGljaCB3ZSBkb24ndCBrbm93IGFib3V0DQogICAgICAgICAgICAgICR0cmFuc2NsdWRlKGZ1bmN0aW9uIG5nUmVwZWF0VHJhbnNjbHVkZShjbG9uZSwgc2NvcGUpIHsNCiAgICAgICAgICAgICAgICBibG9jay5zY29wZSA9IHNjb3BlOw0KICAgICAgICAgICAgICAgIC8vIGh0dHA6Ly9qc3BlcmYuY29tL2Nsb25lLXZzLWNyZWF0ZWNvbW1lbnQNCiAgICAgICAgICAgICAgICB2YXIgZW5kTm9kZSA9IG5nUmVwZWF0RW5kQ29tbWVudC5jbG9uZU5vZGUoZmFsc2UpOw0KICAgICAgICAgICAgICAgIGNsb25lW2Nsb25lLmxlbmd0aCsrXSA9IGVuZE5vZGU7DQoNCiAgICAgICAgICAgICAgICAvLyBUT0RPKHBlcmYpOiBzdXBwb3J0IG5ha2VkIHByZXZpb3VzTm9kZSBpbiBgZW50ZXJgIHRvIGF2b2lkIGNyZWF0aW9uIG9mIGpxTGl0ZSB3cmFwcGVyPw0KICAgICAgICAgICAgICAgICRhbmltYXRlLmVudGVyKGNsb25lLCBudWxsLCBqcUxpdGUocHJldmlvdXNOb2RlKSk7DQogICAgICAgICAgICAgICAgcHJldmlvdXNOb2RlID0gZW5kTm9kZTsNCiAgICAgICAgICAgICAgICAvLyBOb3RlOiBXZSBvbmx5IG5lZWQgdGhlIGZpcnN0L2xhc3Qgbm9kZSBvZiB0aGUgY2xvbmVkIG5vZGVzLg0KICAgICAgICAgICAgICAgIC8vIEhvd2V2ZXIsIHdlIG5lZWQgdG8ga2VlcCB0aGUgcmVmZXJlbmNlIHRvIHRoZSBqcWxpdGUgd3JhcHBlciBhcyBpdCBtaWdodCBiZSBjaGFuZ2VkIGxhdGVyDQogICAgICAgICAgICAgICAgLy8gYnkgYSBkaXJlY3RpdmUgd2l0aCB0ZW1wbGF0ZVVybCB3aGVuIGl0cyB0ZW1wbGF0ZSBhcnJpdmVzLg0KICAgICAgICAgICAgICAgIGJsb2NrLmNsb25lID0gY2xvbmU7DQogICAgICAgICAgICAgICAgbmV4dEJsb2NrTWFwW2Jsb2NrLmlkXSA9IGJsb2NrOw0KICAgICAgICAgICAgICAgIHVwZGF0ZVNjb3BlKGJsb2NrLnNjb3BlLCBpbmRleCwgdmFsdWVJZGVudGlmaWVyLCB2YWx1ZSwga2V5SWRlbnRpZmllciwga2V5LCBjb2xsZWN0aW9uTGVuZ3RoKTsNCiAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgfQ0KICAgICAgICAgIGxhc3RCbG9ja01hcCA9IG5leHRCbG9ja01hcDsNCiAgICAgICAgfSk7DQogICAgICB9Ow0KICAgIH0NCiAgfTsNCn1dOw0KDQp2YXIgTkdfSElERV9DTEFTUyA9ICduZy1oaWRlJzsNCnZhciBOR19ISURFX0lOX1BST0dSRVNTX0NMQVNTID0gJ25nLWhpZGUtYW5pbWF0ZSc7DQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nU2hvdw0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlIGBuZ1Nob3dgIGRpcmVjdGl2ZSBzaG93cyBvciBoaWRlcyB0aGUgZ2l2ZW4gSFRNTCBlbGVtZW50IGJhc2VkIG9uIHRoZSBleHByZXNzaW9uDQogKiBwcm92aWRlZCB0byB0aGUgYG5nU2hvd2AgYXR0cmlidXRlLiBUaGUgZWxlbWVudCBpcyBzaG93biBvciBoaWRkZW4gYnkgcmVtb3Zpbmcgb3IgYWRkaW5nDQogKiB0aGUgYC5uZy1oaWRlYCBDU1MgY2xhc3Mgb250byB0aGUgZWxlbWVudC4gVGhlIGAubmctaGlkZWAgQ1NTIGNsYXNzIGlzIHByZWRlZmluZWQNCiAqIGluIEFuZ3VsYXJKUyBhbmQgc2V0cyB0aGUgZGlzcGxheSBzdHlsZSB0byBub25lICh1c2luZyBhbiAhaW1wb3J0YW50IGZsYWcpLg0KICogRm9yIENTUCBtb2RlIHBsZWFzZSBhZGQgYGFuZ3VsYXItY3NwLmNzc2AgdG8geW91ciBodG1sIGZpbGUgKHNlZSB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nQ3NwIG5nQ3NwfSkuDQogKg0KICogYGBgaHRtbA0KICogPCEtLSB3aGVuICRzY29wZS5teVZhbHVlIGlzIHRydXRoeSAoZWxlbWVudCBpcyB2aXNpYmxlKSAtLT4NCiAqIDxkaXYgbmctc2hvdz0ibXlWYWx1ZSI+PC9kaXY+DQogKg0KICogPCEtLSB3aGVuICRzY29wZS5teVZhbHVlIGlzIGZhbHN5IChlbGVtZW50IGlzIGhpZGRlbikgLS0+DQogKiA8ZGl2IG5nLXNob3c9Im15VmFsdWUiIGNsYXNzPSJuZy1oaWRlIj48L2Rpdj4NCiAqIGBgYA0KICoNCiAqIFdoZW4gdGhlIGBuZ1Nob3dgIGV4cHJlc3Npb24gZXZhbHVhdGVzIHRvIGEgZmFsc3kgdmFsdWUgdGhlbiB0aGUgYC5uZy1oaWRlYCBDU1MgY2xhc3MgaXMgYWRkZWQgdG8gdGhlIGNsYXNzDQogKiBhdHRyaWJ1dGUgb24gdGhlIGVsZW1lbnQgY2F1c2luZyBpdCB0byBiZWNvbWUgaGlkZGVuLiBXaGVuIHRydXRoeSwgdGhlIGAubmctaGlkZWAgQ1NTIGNsYXNzIGlzIHJlbW92ZWQNCiAqIGZyb20gdGhlIGVsZW1lbnQgY2F1c2luZyB0aGUgZWxlbWVudCBub3QgdG8gYXBwZWFyIGhpZGRlbi4NCiAqDQogKiAjIyBXaHkgaXMgIWltcG9ydGFudCB1c2VkPw0KICoNCiAqIFlvdSBtYXkgYmUgd29uZGVyaW5nIHdoeSAhaW1wb3J0YW50IGlzIHVzZWQgZm9yIHRoZSBgLm5nLWhpZGVgIENTUyBjbGFzcy4gVGhpcyBpcyBiZWNhdXNlIHRoZSBgLm5nLWhpZGVgIHNlbGVjdG9yDQogKiBjYW4gYmUgZWFzaWx5IG92ZXJyaWRkZW4gYnkgaGVhdmllciBzZWxlY3RvcnMuIEZvciBleGFtcGxlLCBzb21ldGhpbmcgYXMgc2ltcGxlDQogKiBhcyBjaGFuZ2luZyB0aGUgZGlzcGxheSBzdHlsZSBvbiBhIEhUTUwgbGlzdCBpdGVtIHdvdWxkIG1ha2UgaGlkZGVuIGVsZW1lbnRzIGFwcGVhciB2aXNpYmxlLg0KICogVGhpcyBhbHNvIGJlY29tZXMgYSBiaWdnZXIgaXNzdWUgd2hlbiBkZWFsaW5nIHdpdGggQ1NTIGZyYW1ld29ya3MuDQogKg0KICogQnkgdXNpbmcgIWltcG9ydGFudCwgdGhlIHNob3cgYW5kIGhpZGUgYmVoYXZpb3Igd2lsbCB3b3JrIGFzIGV4cGVjdGVkIGRlc3BpdGUgYW55IGNsYXNoIGJldHdlZW4gQ1NTIHNlbGVjdG9yDQogKiBzcGVjaWZpY2l0eSAod2hlbiAhaW1wb3J0YW50IGlzbid0IHVzZWQgd2l0aCBhbnkgY29uZmxpY3Rpbmcgc3R5bGVzKS4gSWYgYSBkZXZlbG9wZXIgY2hvb3NlcyB0byBvdmVycmlkZSB0aGUNCiAqIHN0eWxpbmcgdG8gY2hhbmdlIGhvdyB0byBoaWRlIGFuIGVsZW1lbnQgdGhlbiBpdCBpcyBqdXN0IGEgbWF0dGVyIG9mIHVzaW5nICFpbXBvcnRhbnQgaW4gdGhlaXIgb3duIENTUyBjb2RlLg0KICoNCiAqICMjIyBPdmVycmlkaW5nIGAubmctaGlkZWANCiAqDQogKiBCeSBkZWZhdWx0LCB0aGUgYC5uZy1oaWRlYCBjbGFzcyB3aWxsIHN0eWxlIHRoZSBlbGVtZW50IHdpdGggYGRpc3BsYXk6IG5vbmUhaW1wb3J0YW50YC4gSWYgeW91IHdpc2ggdG8gY2hhbmdlDQogKiB0aGUgaGlkZSBiZWhhdmlvciB3aXRoIG5nU2hvdy9uZ0hpZGUgdGhlbiB0aGlzIGNhbiBiZSBhY2hpZXZlZCBieSByZXN0YXRpbmcgdGhlIHN0eWxlcyBmb3IgdGhlIGAubmctaGlkZWANCiAqIGNsYXNzIGluIENTUzoNCiAqDQogKiBgYGBjc3MNCiAqIC5uZy1oaWRlIHsNCiAqICAgLyYjNDI7IHRoaXMgaXMganVzdCBhbm90aGVyIGZvcm0gb2YgaGlkaW5nIGFuIGVsZW1lbnQgJiM0MjsvDQogKiAgIGRpc3BsYXk6IGJsb2NrIWltcG9ydGFudDsNCiAqICAgcG9zaXRpb246IGFic29sdXRlOw0KICogICB0b3A6IC05OTk5cHg7DQogKiAgIGxlZnQ6IC05OTk5cHg7DQogKiB9DQogKiBgYGANCiAqDQogKiBCeSBkZWZhdWx0IHlvdSBkb24ndCBuZWVkIHRvIG92ZXJyaWRlIGluIENTUyBhbnl0aGluZyBhbmQgdGhlIGFuaW1hdGlvbnMgd2lsbCB3b3JrIGFyb3VuZCB0aGUgZGlzcGxheSBzdHlsZS4NCiAqDQogKiAjIyBBIG5vdGUgYWJvdXQgYW5pbWF0aW9ucyB3aXRoIGBuZ1Nob3dgDQogKg0KICogQW5pbWF0aW9ucyBpbiBuZ1Nob3cvbmdIaWRlIHdvcmsgd2l0aCB0aGUgc2hvdyBhbmQgaGlkZSBldmVudHMgdGhhdCBhcmUgdHJpZ2dlcmVkIHdoZW4gdGhlIGRpcmVjdGl2ZSBleHByZXNzaW9uDQogKiBpcyB0cnVlIGFuZCBmYWxzZS4gVGhpcyBzeXN0ZW0gd29ya3MgbGlrZSB0aGUgYW5pbWF0aW9uIHN5c3RlbSBwcmVzZW50IHdpdGggbmdDbGFzcyBleGNlcHQgdGhhdA0KICogeW91IG11c3QgYWxzbyBpbmNsdWRlIHRoZSAhaW1wb3J0YW50IGZsYWcgdG8gb3ZlcnJpZGUgdGhlIGRpc3BsYXkgcHJvcGVydHkNCiAqIHNvIHRoYXQgeW91IGNhbiBwZXJmb3JtIGFuIGFuaW1hdGlvbiB3aGVuIHRoZSBlbGVtZW50IGlzIGhpZGRlbiBkdXJpbmcgdGhlIHRpbWUgb2YgdGhlIGFuaW1hdGlvbi4NCiAqDQogKiBgYGBjc3MNCiAqIC8vDQogKiAvL2Egd29ya2luZyBleGFtcGxlIGNhbiBiZSBmb3VuZCBhdCB0aGUgYm90dG9tIG9mIHRoaXMgcGFnZQ0KICogLy8NCiAqIC5teS1lbGVtZW50Lm5nLWhpZGUtYWRkLCAubXktZWxlbWVudC5uZy1oaWRlLXJlbW92ZSB7DQogKiAgIC8mIzQyOyB0aGlzIGlzIHJlcXVpcmVkIGFzIG9mIDEuM3ggdG8gcHJvcGVybHkNCiAqICAgICAgYXBwbHkgYWxsIHN0eWxpbmcgaW4gYSBzaG93L2hpZGUgYW5pbWF0aW9uICYjNDI7Lw0KICogICB0cmFuc2l0aW9uOiAwcyBsaW5lYXIgYWxsOw0KICogfQ0KICoNCiAqIC5teS1lbGVtZW50Lm5nLWhpZGUtYWRkLWFjdGl2ZSwNCiAqIC5teS1lbGVtZW50Lm5nLWhpZGUtcmVtb3ZlLWFjdGl2ZSB7DQogKiAgIC8mIzQyOyB0aGUgdHJhbnNpdGlvbiBpcyBkZWZpbmVkIGluIHRoZSBhY3RpdmUgY2xhc3MgJiM0MjsvDQogKiAgIHRyYW5zaXRpb246IDFzIGxpbmVhciBhbGw7DQogKiB9DQogKg0KICogLm15LWVsZW1lbnQubmctaGlkZS1hZGQgeyAuLi4gfQ0KICogLm15LWVsZW1lbnQubmctaGlkZS1hZGQubmctaGlkZS1hZGQtYWN0aXZlIHsgLi4uIH0NCiAqIC5teS1lbGVtZW50Lm5nLWhpZGUtcmVtb3ZlIHsgLi4uIH0NCiAqIC5teS1lbGVtZW50Lm5nLWhpZGUtcmVtb3ZlLm5nLWhpZGUtcmVtb3ZlLWFjdGl2ZSB7IC4uLiB9DQogKiBgYGANCiAqDQogKiBLZWVwIGluIG1pbmQgdGhhdCwgYXMgb2YgQW5ndWxhckpTIHZlcnNpb24gMS4zLjAtYmV0YS4xMSwgdGhlcmUgaXMgbm8gbmVlZCB0byBjaGFuZ2UgdGhlIGRpc3BsYXkNCiAqIHByb3BlcnR5IHRvIGJsb2NrIGR1cmluZyBhbmltYXRpb24gc3RhdGVzLS1uZ0FuaW1hdGUgd2lsbCBoYW5kbGUgdGhlIHN0eWxlIHRvZ2dsaW5nIGF1dG9tYXRpY2FsbHkgZm9yIHlvdS4NCiAqDQogKiBAYW5pbWF0aW9ucw0KICogYWRkQ2xhc3M6IGAubmctaGlkZWAgLSBoYXBwZW5zIGFmdGVyIHRoZSBgbmdTaG93YCBleHByZXNzaW9uIGV2YWx1YXRlcyB0byBhIHRydXRoeSB2YWx1ZSBhbmQgdGhlIGp1c3QgYmVmb3JlIGNvbnRlbnRzIGFyZSBzZXQgdG8gdmlzaWJsZQ0KICogcmVtb3ZlQ2xhc3M6IGAubmctaGlkZWAgLSBoYXBwZW5zIGFmdGVyIHRoZSBgbmdTaG93YCBleHByZXNzaW9uIGV2YWx1YXRlcyB0byBhIG5vbiB0cnV0aHkgdmFsdWUgYW5kIGp1c3QgYmVmb3JlIHRoZSBjb250ZW50cyBhcmUgc2V0IHRvIGhpZGRlbg0KICoNCiAqIEBlbGVtZW50IEFOWQ0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ1Nob3cgSWYgdGhlIHtAbGluayBndWlkZS9leHByZXNzaW9uIGV4cHJlc3Npb259IGlzIHRydXRoeQ0KICogICAgIHRoZW4gdGhlIGVsZW1lbnQgaXMgc2hvd24gb3IgaGlkZGVuIHJlc3BlY3RpdmVseS4NCiAqDQogKiBAZXhhbXBsZQ0KICA8ZXhhbXBsZSBtb2R1bGU9Im5nQW5pbWF0ZSIgZGVwcz0iYW5ndWxhci1hbmltYXRlLmpzIiBhbmltYXRpb25zPSJ0cnVlIj4NCiAgICA8ZmlsZSBuYW1lPSJpbmRleC5odG1sIj4NCiAgICAgIENsaWNrIG1lOiA8aW5wdXQgdHlwZT0iY2hlY2tib3giIG5nLW1vZGVsPSJjaGVja2VkIj48YnIvPg0KICAgICAgPGRpdj4NCiAgICAgICAgU2hvdzoNCiAgICAgICAgPGRpdiBjbGFzcz0iY2hlY2stZWxlbWVudCBhbmltYXRlLXNob3ciIG5nLXNob3c9ImNoZWNrZWQiPg0KICAgICAgICAgIDxzcGFuIGNsYXNzPSJnbHlwaGljb24gZ2x5cGhpY29uLXRodW1icy11cCI+PC9zcGFuPiBJIHNob3cgdXAgd2hlbiB5b3VyIGNoZWNrYm94IGlzIGNoZWNrZWQuDQogICAgICAgIDwvZGl2Pg0KICAgICAgPC9kaXY+DQogICAgICA8ZGl2Pg0KICAgICAgICBIaWRlOg0KICAgICAgICA8ZGl2IGNsYXNzPSJjaGVjay1lbGVtZW50IGFuaW1hdGUtc2hvdyIgbmctaGlkZT0iY2hlY2tlZCI+DQogICAgICAgICAgPHNwYW4gY2xhc3M9ImdseXBoaWNvbiBnbHlwaGljb24tdGh1bWJzLWRvd24iPjwvc3Bhbj4gSSBoaWRlIHdoZW4geW91ciBjaGVja2JveCBpcyBjaGVja2VkLg0KICAgICAgICA8L2Rpdj4NCiAgICAgIDwvZGl2Pg0KICAgIDwvZmlsZT4NCiAgICA8ZmlsZSBuYW1lPSJnbHlwaGljb25zLmNzcyI+DQogICAgICBAaW1wb3J0IHVybCguLi8uLi9jb21wb25lbnRzL2Jvb3RzdHJhcC0zLjEuMS9jc3MvYm9vdHN0cmFwLmNzcyk7DQogICAgPC9maWxlPg0KICAgIDxmaWxlIG5hbWU9ImFuaW1hdGlvbnMuY3NzIj4NCiAgICAgIC5hbmltYXRlLXNob3cgew0KICAgICAgICBsaW5lLWhlaWdodDogMjBweDsNCiAgICAgICAgb3BhY2l0eTogMTsNCiAgICAgICAgcGFkZGluZzogMTBweDsNCiAgICAgICAgYm9yZGVyOiAxcHggc29saWQgYmxhY2s7DQogICAgICAgIGJhY2tncm91bmQ6IHdoaXRlOw0KICAgICAgfQ0KDQogICAgICAuYW5pbWF0ZS1zaG93Lm5nLWhpZGUtYWRkLm5nLWhpZGUtYWRkLWFjdGl2ZSwNCiAgICAgIC5hbmltYXRlLXNob3cubmctaGlkZS1yZW1vdmUubmctaGlkZS1yZW1vdmUtYWN0aXZlIHsNCiAgICAgICAgLXdlYmtpdC10cmFuc2l0aW9uOiBhbGwgbGluZWFyIDAuNXM7DQogICAgICAgIHRyYW5zaXRpb246IGFsbCBsaW5lYXIgMC41czsNCiAgICAgIH0NCg0KICAgICAgLmFuaW1hdGUtc2hvdy5uZy1oaWRlIHsNCiAgICAgICAgbGluZS1oZWlnaHQ6IDA7DQogICAgICAgIG9wYWNpdHk6IDA7DQogICAgICAgIHBhZGRpbmc6IDAgMTBweDsNCiAgICAgIH0NCg0KICAgICAgLmNoZWNrLWVsZW1lbnQgew0KICAgICAgICBwYWRkaW5nOiAxMHB4Ow0KICAgICAgICBib3JkZXI6IDFweCBzb2xpZCBibGFjazsNCiAgICAgICAgYmFja2dyb3VuZDogd2hpdGU7DQogICAgICB9DQogICAgPC9maWxlPg0KICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgdmFyIHRodW1ic1VwID0gZWxlbWVudChieS5jc3MoJ3NwYW4uZ2x5cGhpY29uLXRodW1icy11cCcpKTsNCiAgICAgIHZhciB0aHVtYnNEb3duID0gZWxlbWVudChieS5jc3MoJ3NwYW4uZ2x5cGhpY29uLXRodW1icy1kb3duJykpOw0KDQogICAgICBpdCgnc2hvdWxkIGNoZWNrIG5nLXNob3cgLyBuZy1oaWRlJywgZnVuY3Rpb24oKSB7DQogICAgICAgIGV4cGVjdCh0aHVtYnNVcC5pc0Rpc3BsYXllZCgpKS50b0JlRmFsc3koKTsNCiAgICAgICAgZXhwZWN0KHRodW1ic0Rvd24uaXNEaXNwbGF5ZWQoKSkudG9CZVRydXRoeSgpOw0KDQogICAgICAgIGVsZW1lbnQoYnkubW9kZWwoJ2NoZWNrZWQnKSkuY2xpY2soKTsNCg0KICAgICAgICBleHBlY3QodGh1bWJzVXAuaXNEaXNwbGF5ZWQoKSkudG9CZVRydXRoeSgpOw0KICAgICAgICBleHBlY3QodGh1bWJzRG93bi5pc0Rpc3BsYXllZCgpKS50b0JlRmFsc3koKTsNCiAgICAgIH0pOw0KICAgIDwvZmlsZT4NCiAgPC9leGFtcGxlPg0KICovDQp2YXIgbmdTaG93RGlyZWN0aXZlID0gWyckYW5pbWF0ZScsIGZ1bmN0aW9uKCRhbmltYXRlKSB7DQogIHJldHVybiB7DQogICAgcmVzdHJpY3Q6ICdBJywNCiAgICBtdWx0aUVsZW1lbnQ6IHRydWUsDQogICAgbGluazogZnVuY3Rpb24oc2NvcGUsIGVsZW1lbnQsIGF0dHIpIHsNCiAgICAgIHNjb3BlLiR3YXRjaChhdHRyLm5nU2hvdywgZnVuY3Rpb24gbmdTaG93V2F0Y2hBY3Rpb24odmFsdWUpIHsNCiAgICAgICAgLy8gd2UncmUgYWRkaW5nIGEgdGVtcG9yYXJ5LCBhbmltYXRpb24tc3BlY2lmaWMgY2xhc3MgZm9yIG5nLWhpZGUgc2luY2UgdGhpcyB3YXkNCiAgICAgICAgLy8gd2UgY2FuIGNvbnRyb2wgd2hlbiB0aGUgZWxlbWVudCBpcyBhY3R1YWxseSBkaXNwbGF5ZWQgb24gc2NyZWVuIHdpdGhvdXQgaGF2aW5nDQogICAgICAgIC8vIHRvIGhhdmUgYSBnbG9iYWwvZ3JlZWR5IENTUyBzZWxlY3RvciB0aGF0IGJyZWFrcyB3aGVuIG90aGVyIGFuaW1hdGlvbnMgYXJlIHJ1bi4NCiAgICAgICAgLy8gUmVhZDogaHR0cHM6Ly9naXRodWIuY29tL2FuZ3VsYXIvYW5ndWxhci5qcy9pc3N1ZXMvOTEwMyNpc3N1ZWNvbW1lbnQtNTgzMzU4NDUNCiAgICAgICAgJGFuaW1hdGVbdmFsdWUgPyAncmVtb3ZlQ2xhc3MnIDogJ2FkZENsYXNzJ10oZWxlbWVudCwgTkdfSElERV9DTEFTUywgew0KICAgICAgICAgIHRlbXBDbGFzc2VzOiBOR19ISURFX0lOX1BST0dSRVNTX0NMQVNTDQogICAgICAgIH0pOw0KICAgICAgfSk7DQogICAgfQ0KICB9Ow0KfV07DQoNCg0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBuZ0hpZGUNCiAqDQogKiBAZGVzY3JpcHRpb24NCiAqIFRoZSBgbmdIaWRlYCBkaXJlY3RpdmUgc2hvd3Mgb3IgaGlkZXMgdGhlIGdpdmVuIEhUTUwgZWxlbWVudCBiYXNlZCBvbiB0aGUgZXhwcmVzc2lvbg0KICogcHJvdmlkZWQgdG8gdGhlIGBuZ0hpZGVgIGF0dHJpYnV0ZS4gVGhlIGVsZW1lbnQgaXMgc2hvd24gb3IgaGlkZGVuIGJ5IHJlbW92aW5nIG9yIGFkZGluZw0KICogdGhlIGBuZy1oaWRlYCBDU1MgY2xhc3Mgb250byB0aGUgZWxlbWVudC4gVGhlIGAubmctaGlkZWAgQ1NTIGNsYXNzIGlzIHByZWRlZmluZWQNCiAqIGluIEFuZ3VsYXJKUyBhbmQgc2V0cyB0aGUgZGlzcGxheSBzdHlsZSB0byBub25lICh1c2luZyBhbiAhaW1wb3J0YW50IGZsYWcpLg0KICogRm9yIENTUCBtb2RlIHBsZWFzZSBhZGQgYGFuZ3VsYXItY3NwLmNzc2AgdG8geW91ciBodG1sIGZpbGUgKHNlZSB7QGxpbmsgbmcuZGlyZWN0aXZlOm5nQ3NwIG5nQ3NwfSkuDQogKg0KICogYGBgaHRtbA0KICogPCEtLSB3aGVuICRzY29wZS5teVZhbHVlIGlzIHRydXRoeSAoZWxlbWVudCBpcyBoaWRkZW4pIC0tPg0KICogPGRpdiBuZy1oaWRlPSJteVZhbHVlIiBjbGFzcz0ibmctaGlkZSI+PC9kaXY+DQogKg0KICogPCEtLSB3aGVuICRzY29wZS5teVZhbHVlIGlzIGZhbHN5IChlbGVtZW50IGlzIHZpc2libGUpIC0tPg0KICogPGRpdiBuZy1oaWRlPSJteVZhbHVlIj48L2Rpdj4NCiAqIGBgYA0KICoNCiAqIFdoZW4gdGhlIGBuZ0hpZGVgIGV4cHJlc3Npb24gZXZhbHVhdGVzIHRvIGEgdHJ1dGh5IHZhbHVlIHRoZW4gdGhlIGAubmctaGlkZWAgQ1NTIGNsYXNzIGlzIGFkZGVkIHRvIHRoZSBjbGFzcw0KICogYXR0cmlidXRlIG9uIHRoZSBlbGVtZW50IGNhdXNpbmcgaXQgdG8gYmVjb21lIGhpZGRlbi4gV2hlbiBmYWxzeSwgdGhlIGAubmctaGlkZWAgQ1NTIGNsYXNzIGlzIHJlbW92ZWQNCiAqIGZyb20gdGhlIGVsZW1lbnQgY2F1c2luZyB0aGUgZWxlbWVudCBub3QgdG8gYXBwZWFyIGhpZGRlbi4NCiAqDQogKiAjIyBXaHkgaXMgIWltcG9ydGFudCB1c2VkPw0KICoNCiAqIFlvdSBtYXkgYmUgd29uZGVyaW5nIHdoeSAhaW1wb3J0YW50IGlzIHVzZWQgZm9yIHRoZSBgLm5nLWhpZGVgIENTUyBjbGFzcy4gVGhpcyBpcyBiZWNhdXNlIHRoZSBgLm5nLWhpZGVgIHNlbGVjdG9yDQogKiBjYW4gYmUgZWFzaWx5IG92ZXJyaWRkZW4gYnkgaGVhdmllciBzZWxlY3RvcnMuIEZvciBleGFtcGxlLCBzb21ldGhpbmcgYXMgc2ltcGxlDQogKiBhcyBjaGFuZ2luZyB0aGUgZGlzcGxheSBzdHlsZSBvbiBhIEhUTUwgbGlzdCBpdGVtIHdvdWxkIG1ha2UgaGlkZGVuIGVsZW1lbnRzIGFwcGVhciB2aXNpYmxlLg0KICogVGhpcyBhbHNvIGJlY29tZXMgYSBiaWdnZXIgaXNzdWUgd2hlbiBkZWFsaW5nIHdpdGggQ1NTIGZyYW1ld29ya3MuDQogKg0KICogQnkgdXNpbmcgIWltcG9ydGFudCwgdGhlIHNob3cgYW5kIGhpZGUgYmVoYXZpb3Igd2lsbCB3b3JrIGFzIGV4cGVjdGVkIGRlc3BpdGUgYW55IGNsYXNoIGJldHdlZW4gQ1NTIHNlbGVjdG9yDQogKiBzcGVjaWZpY2l0eSAod2hlbiAhaW1wb3J0YW50IGlzbid0IHVzZWQgd2l0aCBhbnkgY29uZmxpY3Rpbmcgc3R5bGVzKS4gSWYgYSBkZXZlbG9wZXIgY2hvb3NlcyB0byBvdmVycmlkZSB0aGUNCiAqIHN0eWxpbmcgdG8gY2hhbmdlIGhvdyB0byBoaWRlIGFuIGVsZW1lbnQgdGhlbiBpdCBpcyBqdXN0IGEgbWF0dGVyIG9mIHVzaW5nICFpbXBvcnRhbnQgaW4gdGhlaXIgb3duIENTUyBjb2RlLg0KICoNCiAqICMjIyBPdmVycmlkaW5nIGAubmctaGlkZWANCiAqDQogKiBCeSBkZWZhdWx0LCB0aGUgYC5uZy1oaWRlYCBjbGFzcyB3aWxsIHN0eWxlIHRoZSBlbGVtZW50IHdpdGggYGRpc3BsYXk6IG5vbmUhaW1wb3J0YW50YC4gSWYgeW91IHdpc2ggdG8gY2hhbmdlDQogKiB0aGUgaGlkZSBiZWhhdmlvciB3aXRoIG5nU2hvdy9uZ0hpZGUgdGhlbiB0aGlzIGNhbiBiZSBhY2hpZXZlZCBieSByZXN0YXRpbmcgdGhlIHN0eWxlcyBmb3IgdGhlIGAubmctaGlkZWANCiAqIGNsYXNzIGluIENTUzoNCiAqDQogKiBgYGBjc3MNCiAqIC5uZy1oaWRlIHsNCiAqICAgLyYjNDI7IHRoaXMgaXMganVzdCBhbm90aGVyIGZvcm0gb2YgaGlkaW5nIGFuIGVsZW1lbnQgJiM0MjsvDQogKiAgIGRpc3BsYXk6IGJsb2NrIWltcG9ydGFudDsNCiAqICAgcG9zaXRpb246IGFic29sdXRlOw0KICogICB0b3A6IC05OTk5cHg7DQogKiAgIGxlZnQ6IC05OTk5cHg7DQogKiB9DQogKiBgYGANCiAqDQogKiBCeSBkZWZhdWx0IHlvdSBkb24ndCBuZWVkIHRvIG92ZXJyaWRlIGluIENTUyBhbnl0aGluZyBhbmQgdGhlIGFuaW1hdGlvbnMgd2lsbCB3b3JrIGFyb3VuZCB0aGUgZGlzcGxheSBzdHlsZS4NCiAqDQogKiAjIyBBIG5vdGUgYWJvdXQgYW5pbWF0aW9ucyB3aXRoIGBuZ0hpZGVgDQogKg0KICogQW5pbWF0aW9ucyBpbiBuZ1Nob3cvbmdIaWRlIHdvcmsgd2l0aCB0aGUgc2hvdyBhbmQgaGlkZSBldmVudHMgdGhhdCBhcmUgdHJpZ2dlcmVkIHdoZW4gdGhlIGRpcmVjdGl2ZSBleHByZXNzaW9uDQogKiBpcyB0cnVlIGFuZCBmYWxzZS4gVGhpcyBzeXN0ZW0gd29ya3MgbGlrZSB0aGUgYW5pbWF0aW9uIHN5c3RlbSBwcmVzZW50IHdpdGggbmdDbGFzcywgZXhjZXB0IHRoYXQgdGhlIGAubmctaGlkZWANCiAqIENTUyBjbGFzcyBpcyBhZGRlZCBhbmQgcmVtb3ZlZCBmb3IgeW91IGluc3RlYWQgb2YgeW91ciBvd24gQ1NTIGNsYXNzLg0KICoNCiAqIGBgYGNzcw0KICogLy8NCiAqIC8vYSB3b3JraW5nIGV4YW1wbGUgY2FuIGJlIGZvdW5kIGF0IHRoZSBib3R0b20gb2YgdGhpcyBwYWdlDQogKiAvLw0KICogLm15LWVsZW1lbnQubmctaGlkZS1hZGQsIC5teS1lbGVtZW50Lm5nLWhpZGUtcmVtb3ZlIHsNCiAqICAgdHJhbnNpdGlvbjogMC41cyBsaW5lYXIgYWxsOw0KICogfQ0KICoNCiAqIC5teS1lbGVtZW50Lm5nLWhpZGUtYWRkIHsgLi4uIH0NCiAqIC5teS1lbGVtZW50Lm5nLWhpZGUtYWRkLm5nLWhpZGUtYWRkLWFjdGl2ZSB7IC4uLiB9DQogKiAubXktZWxlbWVudC5uZy1oaWRlLXJlbW92ZSB7IC4uLiB9DQogKiAubXktZWxlbWVudC5uZy1oaWRlLXJlbW92ZS5uZy1oaWRlLXJlbW92ZS1hY3RpdmUgeyAuLi4gfQ0KICogYGBgDQogKg0KICogS2VlcCBpbiBtaW5kIHRoYXQsIGFzIG9mIEFuZ3VsYXJKUyB2ZXJzaW9uIDEuMy4wLWJldGEuMTEsIHRoZXJlIGlzIG5vIG5lZWQgdG8gY2hhbmdlIHRoZSBkaXNwbGF5DQogKiBwcm9wZXJ0eSB0byBibG9jayBkdXJpbmcgYW5pbWF0aW9uIHN0YXRlcy0tbmdBbmltYXRlIHdpbGwgaGFuZGxlIHRoZSBzdHlsZSB0b2dnbGluZyBhdXRvbWF0aWNhbGx5IGZvciB5b3UuDQogKg0KICogQGFuaW1hdGlvbnMNCiAqIHJlbW92ZUNsYXNzOiBgLm5nLWhpZGVgIC0gaGFwcGVucyBhZnRlciB0aGUgYG5nSGlkZWAgZXhwcmVzc2lvbiBldmFsdWF0ZXMgdG8gYSB0cnV0aHkgdmFsdWUgYW5kIGp1c3QgYmVmb3JlIHRoZSBjb250ZW50cyBhcmUgc2V0IHRvIGhpZGRlbg0KICogYWRkQ2xhc3M6IGAubmctaGlkZWAgLSBoYXBwZW5zIGFmdGVyIHRoZSBgbmdIaWRlYCBleHByZXNzaW9uIGV2YWx1YXRlcyB0byBhIG5vbiB0cnV0aHkgdmFsdWUgYW5kIGp1c3QgYmVmb3JlIHRoZSBjb250ZW50cyBhcmUgc2V0IHRvIHZpc2libGUNCiAqDQogKiBAZWxlbWVudCBBTlkNCiAqIEBwYXJhbSB7ZXhwcmVzc2lvbn0gbmdIaWRlIElmIHRoZSB7QGxpbmsgZ3VpZGUvZXhwcmVzc2lvbiBleHByZXNzaW9ufSBpcyB0cnV0aHkgdGhlbg0KICogICAgIHRoZSBlbGVtZW50IGlzIHNob3duIG9yIGhpZGRlbiByZXNwZWN0aXZlbHkuDQogKg0KICogQGV4YW1wbGUNCiAgPGV4YW1wbGUgbW9kdWxlPSJuZ0FuaW1hdGUiIGRlcHM9ImFuZ3VsYXItYW5pbWF0ZS5qcyIgYW5pbWF0aW9ucz0idHJ1ZSI+DQogICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICBDbGljayBtZTogPGlucHV0IHR5cGU9ImNoZWNrYm94IiBuZy1tb2RlbD0iY2hlY2tlZCI+PGJyLz4NCiAgICAgIDxkaXY+DQogICAgICAgIFNob3c6DQogICAgICAgIDxkaXYgY2xhc3M9ImNoZWNrLWVsZW1lbnQgYW5pbWF0ZS1oaWRlIiBuZy1zaG93PSJjaGVja2VkIj4NCiAgICAgICAgICA8c3BhbiBjbGFzcz0iZ2x5cGhpY29uIGdseXBoaWNvbi10aHVtYnMtdXAiPjwvc3Bhbj4gSSBzaG93IHVwIHdoZW4geW91ciBjaGVja2JveCBpcyBjaGVja2VkLg0KICAgICAgICA8L2Rpdj4NCiAgICAgIDwvZGl2Pg0KICAgICAgPGRpdj4NCiAgICAgICAgSGlkZToNCiAgICAgICAgPGRpdiBjbGFzcz0iY2hlY2stZWxlbWVudCBhbmltYXRlLWhpZGUiIG5nLWhpZGU9ImNoZWNrZWQiPg0KICAgICAgICAgIDxzcGFuIGNsYXNzPSJnbHlwaGljb24gZ2x5cGhpY29uLXRodW1icy1kb3duIj48L3NwYW4+IEkgaGlkZSB3aGVuIHlvdXIgY2hlY2tib3ggaXMgY2hlY2tlZC4NCiAgICAgICAgPC9kaXY+DQogICAgICA8L2Rpdj4NCiAgICA8L2ZpbGU+DQogICAgPGZpbGUgbmFtZT0iZ2x5cGhpY29ucy5jc3MiPg0KICAgICAgQGltcG9ydCB1cmwoLi4vLi4vY29tcG9uZW50cy9ib290c3RyYXAtMy4xLjEvY3NzL2Jvb3RzdHJhcC5jc3MpOw0KICAgIDwvZmlsZT4NCiAgICA8ZmlsZSBuYW1lPSJhbmltYXRpb25zLmNzcyI+DQogICAgICAuYW5pbWF0ZS1oaWRlIHsNCiAgICAgICAgLXdlYmtpdC10cmFuc2l0aW9uOiBhbGwgbGluZWFyIDAuNXM7DQogICAgICAgIHRyYW5zaXRpb246IGFsbCBsaW5lYXIgMC41czsNCiAgICAgICAgbGluZS1oZWlnaHQ6IDIwcHg7DQogICAgICAgIG9wYWNpdHk6IDE7DQogICAgICAgIHBhZGRpbmc6IDEwcHg7DQogICAgICAgIGJvcmRlcjogMXB4IHNvbGlkIGJsYWNrOw0KICAgICAgICBiYWNrZ3JvdW5kOiB3aGl0ZTsNCiAgICAgIH0NCg0KICAgICAgLmFuaW1hdGUtaGlkZS5uZy1oaWRlIHsNCiAgICAgICAgbGluZS1oZWlnaHQ6IDA7DQogICAgICAgIG9wYWNpdHk6IDA7DQogICAgICAgIHBhZGRpbmc6IDAgMTBweDsNCiAgICAgIH0NCg0KICAgICAgLmNoZWNrLWVsZW1lbnQgew0KICAgICAgICBwYWRkaW5nOiAxMHB4Ow0KICAgICAgICBib3JkZXI6IDFweCBzb2xpZCBibGFjazsNCiAgICAgICAgYmFja2dyb3VuZDogd2hpdGU7DQogICAgICB9DQogICAgPC9maWxlPg0KICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgdmFyIHRodW1ic1VwID0gZWxlbWVudChieS5jc3MoJ3NwYW4uZ2x5cGhpY29uLXRodW1icy11cCcpKTsNCiAgICAgIHZhciB0aHVtYnNEb3duID0gZWxlbWVudChieS5jc3MoJ3NwYW4uZ2x5cGhpY29uLXRodW1icy1kb3duJykpOw0KDQogICAgICBpdCgnc2hvdWxkIGNoZWNrIG5nLXNob3cgLyBuZy1oaWRlJywgZnVuY3Rpb24oKSB7DQogICAgICAgIGV4cGVjdCh0aHVtYnNVcC5pc0Rpc3BsYXllZCgpKS50b0JlRmFsc3koKTsNCiAgICAgICAgZXhwZWN0KHRodW1ic0Rvd24uaXNEaXNwbGF5ZWQoKSkudG9CZVRydXRoeSgpOw0KDQogICAgICAgIGVsZW1lbnQoYnkubW9kZWwoJ2NoZWNrZWQnKSkuY2xpY2soKTsNCg0KICAgICAgICBleHBlY3QodGh1bWJzVXAuaXNEaXNwbGF5ZWQoKSkudG9CZVRydXRoeSgpOw0KICAgICAgICBleHBlY3QodGh1bWJzRG93bi5pc0Rpc3BsYXllZCgpKS50b0JlRmFsc3koKTsNCiAgICAgIH0pOw0KICAgIDwvZmlsZT4NCiAgPC9leGFtcGxlPg0KICovDQp2YXIgbmdIaWRlRGlyZWN0aXZlID0gWyckYW5pbWF0ZScsIGZ1bmN0aW9uKCRhbmltYXRlKSB7DQogIHJldHVybiB7DQogICAgcmVzdHJpY3Q6ICdBJywNCiAgICBtdWx0aUVsZW1lbnQ6IHRydWUsDQogICAgbGluazogZnVuY3Rpb24oc2NvcGUsIGVsZW1lbnQsIGF0dHIpIHsNCiAgICAgIHNjb3BlLiR3YXRjaChhdHRyLm5nSGlkZSwgZnVuY3Rpb24gbmdIaWRlV2F0Y2hBY3Rpb24odmFsdWUpIHsNCiAgICAgICAgLy8gVGhlIGNvbW1lbnQgaW5zaWRlIG9mIHRoZSBuZ1Nob3dEaXJlY3RpdmUgZXhwbGFpbnMgd2h5IHdlIGFkZCBhbmQNCiAgICAgICAgLy8gcmVtb3ZlIGEgdGVtcG9yYXJ5IGNsYXNzIGZvciB0aGUgc2hvdy9oaWRlIGFuaW1hdGlvbg0KICAgICAgICAkYW5pbWF0ZVt2YWx1ZSA/ICdhZGRDbGFzcycgOiAncmVtb3ZlQ2xhc3MnXShlbGVtZW50LE5HX0hJREVfQ0xBU1MsIHsNCiAgICAgICAgICB0ZW1wQ2xhc3NlczogTkdfSElERV9JTl9QUk9HUkVTU19DTEFTUw0KICAgICAgICB9KTsNCiAgICAgIH0pOw0KICAgIH0NCiAgfTsNCn1dOw0KDQovKioNCiAqIEBuZ2RvYyBkaXJlY3RpdmUNCiAqIEBuYW1lIG5nU3R5bGUNCiAqIEByZXN0cmljdCBBQw0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlIGBuZ1N0eWxlYCBkaXJlY3RpdmUgYWxsb3dzIHlvdSB0byBzZXQgQ1NTIHN0eWxlIG9uIGFuIEhUTUwgZWxlbWVudCBjb25kaXRpb25hbGx5Lg0KICoNCiAqIEBlbGVtZW50IEFOWQ0KICogQHBhcmFtIHtleHByZXNzaW9ufSBuZ1N0eWxlDQogKg0KICoge0BsaW5rIGd1aWRlL2V4cHJlc3Npb24gRXhwcmVzc2lvbn0gd2hpY2ggZXZhbHMgdG8gYW4NCiAqIG9iamVjdCB3aG9zZSBrZXlzIGFyZSBDU1Mgc3R5bGUgbmFtZXMgYW5kIHZhbHVlcyBhcmUgY29ycmVzcG9uZGluZyB2YWx1ZXMgZm9yIHRob3NlIENTUw0KICoga2V5cy4NCiAqDQogKiBTaW5jZSBzb21lIENTUyBzdHlsZSBuYW1lcyBhcmUgbm90IHZhbGlkIGtleXMgZm9yIGFuIG9iamVjdCwgdGhleSBtdXN0IGJlIHF1b3RlZC4NCiAqIFNlZSB0aGUgJ2JhY2tncm91bmQtY29sb3InIHN0eWxlIGluIHRoZSBleGFtcGxlIGJlbG93Lg0KICoNCiAqIEBleGFtcGxlDQogICA8ZXhhbXBsZT4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgIDxpbnB1dCB0eXBlPSJidXR0b24iIHZhbHVlPSJzZXQgY29sb3IiIG5nLWNsaWNrPSJteVN0eWxlPXtjb2xvcjoncmVkJ30iPg0KICAgICAgICA8aW5wdXQgdHlwZT0iYnV0dG9uIiB2YWx1ZT0ic2V0IGJhY2tncm91bmQiIG5nLWNsaWNrPSJteVN0eWxlPXsnYmFja2dyb3VuZC1jb2xvcic6J2JsdWUnfSI+DQogICAgICAgIDxpbnB1dCB0eXBlPSJidXR0b24iIHZhbHVlPSJjbGVhciIgbmctY2xpY2s9Im15U3R5bGU9e30iPg0KICAgICAgICA8YnIvPg0KICAgICAgICA8c3BhbiBuZy1zdHlsZT0ibXlTdHlsZSI+U2FtcGxlIFRleHQ8L3NwYW4+DQogICAgICAgIDxwcmU+bXlTdHlsZT17e215U3R5bGV9fTwvcHJlPg0KICAgICA8L2ZpbGU+DQogICAgIDxmaWxlIG5hbWU9InN0eWxlLmNzcyI+DQogICAgICAgc3BhbiB7DQogICAgICAgICBjb2xvcjogYmxhY2s7DQogICAgICAgfQ0KICAgICA8L2ZpbGU+DQogICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgIHZhciBjb2xvclNwYW4gPSBlbGVtZW50KGJ5LmNzcygnc3BhbicpKTsNCg0KICAgICAgIGl0KCdzaG91bGQgY2hlY2sgbmctc3R5bGUnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgIGV4cGVjdChjb2xvclNwYW4uZ2V0Q3NzVmFsdWUoJ2NvbG9yJykpLnRvQmUoJ3JnYmEoMCwgMCwgMCwgMSknKTsNCiAgICAgICAgIGVsZW1lbnQoYnkuY3NzKCdpbnB1dFt2YWx1ZT1cJ3NldCBjb2xvclwnXScpKS5jbGljaygpOw0KICAgICAgICAgZXhwZWN0KGNvbG9yU3Bhbi5nZXRDc3NWYWx1ZSgnY29sb3InKSkudG9CZSgncmdiYSgyNTUsIDAsIDAsIDEpJyk7DQogICAgICAgICBlbGVtZW50KGJ5LmNzcygnaW5wdXRbdmFsdWU9Y2xlYXJdJykpLmNsaWNrKCk7DQogICAgICAgICBleHBlY3QoY29sb3JTcGFuLmdldENzc1ZhbHVlKCdjb2xvcicpKS50b0JlKCdyZ2JhKDAsIDAsIDAsIDEpJyk7DQogICAgICAgfSk7DQogICAgIDwvZmlsZT4NCiAgIDwvZXhhbXBsZT4NCiAqLw0KdmFyIG5nU3R5bGVEaXJlY3RpdmUgPSBuZ0RpcmVjdGl2ZShmdW5jdGlvbihzY29wZSwgZWxlbWVudCwgYXR0cikgew0KICBzY29wZS4kd2F0Y2goYXR0ci5uZ1N0eWxlLCBmdW5jdGlvbiBuZ1N0eWxlV2F0Y2hBY3Rpb24obmV3U3R5bGVzLCBvbGRTdHlsZXMpIHsNCiAgICBpZiAob2xkU3R5bGVzICYmIChuZXdTdHlsZXMgIT09IG9sZFN0eWxlcykpIHsNCiAgICAgIGZvckVhY2gob2xkU3R5bGVzLCBmdW5jdGlvbih2YWwsIHN0eWxlKSB7IGVsZW1lbnQuY3NzKHN0eWxlLCAnJyk7fSk7DQogICAgfQ0KICAgIGlmIChuZXdTdHlsZXMpIGVsZW1lbnQuY3NzKG5ld1N0eWxlcyk7DQogIH0sIHRydWUpOw0KfSk7DQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdTd2l0Y2gNCiAqIEByZXN0cmljdCBFQQ0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogVGhlIGBuZ1N3aXRjaGAgZGlyZWN0aXZlIGlzIHVzZWQgdG8gY29uZGl0aW9uYWxseSBzd2FwIERPTSBzdHJ1Y3R1cmUgb24geW91ciB0ZW1wbGF0ZSBiYXNlZCBvbiBhIHNjb3BlIGV4cHJlc3Npb24uDQogKiBFbGVtZW50cyB3aXRoaW4gYG5nU3dpdGNoYCBidXQgd2l0aG91dCBgbmdTd2l0Y2hXaGVuYCBvciBgbmdTd2l0Y2hEZWZhdWx0YCBkaXJlY3RpdmVzIHdpbGwgYmUgcHJlc2VydmVkIGF0IHRoZSBsb2NhdGlvbg0KICogYXMgc3BlY2lmaWVkIGluIHRoZSB0ZW1wbGF0ZS4NCiAqDQogKiBUaGUgZGlyZWN0aXZlIGl0c2VsZiB3b3JrcyBzaW1pbGFyIHRvIG5nSW5jbHVkZSwgaG93ZXZlciwgaW5zdGVhZCBvZiBkb3dubG9hZGluZyB0ZW1wbGF0ZSBjb2RlIChvciBsb2FkaW5nIGl0DQogKiBmcm9tIHRoZSB0ZW1wbGF0ZSBjYWNoZSksIGBuZ1N3aXRjaGAgc2ltcGx5IGNob29zZXMgb25lIG9mIHRoZSBuZXN0ZWQgZWxlbWVudHMgYW5kIG1ha2VzIGl0IHZpc2libGUgYmFzZWQgb24gd2hpY2ggZWxlbWVudA0KICogbWF0Y2hlcyB0aGUgdmFsdWUgb2J0YWluZWQgZnJvbSB0aGUgZXZhbHVhdGVkIGV4cHJlc3Npb24uIEluIG90aGVyIHdvcmRzLCB5b3UgZGVmaW5lIGEgY29udGFpbmVyIGVsZW1lbnQNCiAqICh3aGVyZSB5b3UgcGxhY2UgdGhlIGRpcmVjdGl2ZSksIHBsYWNlIGFuIGV4cHJlc3Npb24gb24gdGhlICoqYG9uPSIuLi4iYCBhdHRyaWJ1dGUqKg0KICogKG9yIHRoZSAqKmBuZy1zd2l0Y2g9Ii4uLiJgIGF0dHJpYnV0ZSoqKSwgZGVmaW5lIGFueSBpbm5lciBlbGVtZW50cyBpbnNpZGUgb2YgdGhlIGRpcmVjdGl2ZSBhbmQgcGxhY2UNCiAqIGEgd2hlbiBhdHRyaWJ1dGUgcGVyIGVsZW1lbnQuIFRoZSB3aGVuIGF0dHJpYnV0ZSBpcyB1c2VkIHRvIGluZm9ybSBuZ1N3aXRjaCB3aGljaCBlbGVtZW50IHRvIGRpc3BsYXkgd2hlbiB0aGUgb24NCiAqIGV4cHJlc3Npb24gaXMgZXZhbHVhdGVkLiBJZiBhIG1hdGNoaW5nIGV4cHJlc3Npb24gaXMgbm90IGZvdW5kIHZpYSBhIHdoZW4gYXR0cmlidXRlIHRoZW4gYW4gZWxlbWVudCB3aXRoIHRoZSBkZWZhdWx0DQogKiBhdHRyaWJ1dGUgaXMgZGlzcGxheWVkLg0KICoNCiAqIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWluZm8iPg0KICogQmUgYXdhcmUgdGhhdCB0aGUgYXR0cmlidXRlIHZhbHVlcyB0byBtYXRjaCBhZ2FpbnN0IGNhbm5vdCBiZSBleHByZXNzaW9ucy4gVGhleSBhcmUgaW50ZXJwcmV0ZWQNCiAqIGFzIGxpdGVyYWwgc3RyaW5nIHZhbHVlcyB0byBtYXRjaCBhZ2FpbnN0Lg0KICogRm9yIGV4YW1wbGUsICoqYG5nLXN3aXRjaC13aGVuPSJzb21lVmFsImAqKiB3aWxsIG1hdGNoIGFnYWluc3QgdGhlIHN0cmluZyBgInNvbWVWYWwiYCBub3QgYWdhaW5zdCB0aGUNCiAqIHZhbHVlIG9mIHRoZSBleHByZXNzaW9uIGAkc2NvcGUuc29tZVZhbGAuDQogKiA8L2Rpdj4NCg0KICogQGFuaW1hdGlvbnMNCiAqIGVudGVyIC0gaGFwcGVucyBhZnRlciB0aGUgbmdTd2l0Y2ggY29udGVudHMgY2hhbmdlIGFuZCB0aGUgbWF0Y2hlZCBjaGlsZCBlbGVtZW50IGlzIHBsYWNlZCBpbnNpZGUgdGhlIGNvbnRhaW5lcg0KICogbGVhdmUgLSBoYXBwZW5zIGp1c3QgYWZ0ZXIgdGhlIG5nU3dpdGNoIGNvbnRlbnRzIGNoYW5nZSBhbmQganVzdCBiZWZvcmUgdGhlIGZvcm1lciBjb250ZW50cyBhcmUgcmVtb3ZlZCBmcm9tIHRoZSBET00NCiAqDQogKiBAdXNhZ2UNCiAqDQogKiBgYGANCiAqIDxBTlkgbmctc3dpdGNoPSJleHByZXNzaW9uIj4NCiAqICAgPEFOWSBuZy1zd2l0Y2gtd2hlbj0ibWF0Y2hWYWx1ZTEiPi4uLjwvQU5ZPg0KICogICA8QU5ZIG5nLXN3aXRjaC13aGVuPSJtYXRjaFZhbHVlMiI+Li4uPC9BTlk+DQogKiAgIDxBTlkgbmctc3dpdGNoLWRlZmF1bHQ+Li4uPC9BTlk+DQogKiA8L0FOWT4NCiAqIGBgYA0KICoNCiAqDQogKiBAc2NvcGUNCiAqIEBwcmlvcml0eSAxMjAwDQogKiBAcGFyYW0geyp9IG5nU3dpdGNofG9uIGV4cHJlc3Npb24gdG8gbWF0Y2ggYWdhaW5zdCA8dHQ+bmctc3dpdGNoLXdoZW48L3R0Pi4NCiAqIE9uIGNoaWxkIGVsZW1lbnRzIGFkZDoNCiAqDQogKiAqIGBuZ1N3aXRjaFdoZW5gOiB0aGUgY2FzZSBzdGF0ZW1lbnQgdG8gbWF0Y2ggYWdhaW5zdC4gSWYgbWF0Y2ggdGhlbiB0aGlzDQogKiAgIGNhc2Ugd2lsbCBiZSBkaXNwbGF5ZWQuIElmIHRoZSBzYW1lIG1hdGNoIGFwcGVhcnMgbXVsdGlwbGUgdGltZXMsIGFsbCB0aGUNCiAqICAgZWxlbWVudHMgd2lsbCBiZSBkaXNwbGF5ZWQuDQogKiAqIGBuZ1N3aXRjaERlZmF1bHRgOiB0aGUgZGVmYXVsdCBjYXNlIHdoZW4gbm8gb3RoZXIgY2FzZSBtYXRjaC4gSWYgdGhlcmUNCiAqICAgYXJlIG11bHRpcGxlIGRlZmF1bHQgY2FzZXMsIGFsbCBvZiB0aGVtIHdpbGwgYmUgZGlzcGxheWVkIHdoZW4gbm8gb3RoZXINCiAqICAgY2FzZSBtYXRjaC4NCiAqDQogKg0KICogQGV4YW1wbGUNCiAgPGV4YW1wbGUgbW9kdWxlPSJzd2l0Y2hFeGFtcGxlIiBkZXBzPSJhbmd1bGFyLWFuaW1hdGUuanMiIGFuaW1hdGlvbnM9InRydWUiPg0KICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgPGRpdiBuZy1jb250cm9sbGVyPSJFeGFtcGxlQ29udHJvbGxlciI+DQogICAgICAgIDxzZWxlY3QgbmctbW9kZWw9InNlbGVjdGlvbiIgbmctb3B0aW9ucz0iaXRlbSBmb3IgaXRlbSBpbiBpdGVtcyI+DQogICAgICAgIDwvc2VsZWN0Pg0KICAgICAgICA8dHQ+c2VsZWN0aW9uPXt7c2VsZWN0aW9ufX08L3R0Pg0KICAgICAgICA8aHIvPg0KICAgICAgICA8ZGl2IGNsYXNzPSJhbmltYXRlLXN3aXRjaC1jb250YWluZXIiDQogICAgICAgICAgbmctc3dpdGNoIG9uPSJzZWxlY3Rpb24iPg0KICAgICAgICAgICAgPGRpdiBjbGFzcz0iYW5pbWF0ZS1zd2l0Y2giIG5nLXN3aXRjaC13aGVuPSJzZXR0aW5ncyI+U2V0dGluZ3MgRGl2PC9kaXY+DQogICAgICAgICAgICA8ZGl2IGNsYXNzPSJhbmltYXRlLXN3aXRjaCIgbmctc3dpdGNoLXdoZW49ImhvbWUiPkhvbWUgU3BhbjwvZGl2Pg0KICAgICAgICAgICAgPGRpdiBjbGFzcz0iYW5pbWF0ZS1zd2l0Y2giIG5nLXN3aXRjaC1kZWZhdWx0PmRlZmF1bHQ8L2Rpdj4NCiAgICAgICAgPC9kaXY+DQogICAgICA8L2Rpdj4NCiAgICA8L2ZpbGU+DQogICAgPGZpbGUgbmFtZT0ic2NyaXB0LmpzIj4NCiAgICAgIGFuZ3VsYXIubW9kdWxlKCdzd2l0Y2hFeGFtcGxlJywgWyduZ0FuaW1hdGUnXSkNCiAgICAgICAgLmNvbnRyb2xsZXIoJ0V4YW1wbGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICAgICAkc2NvcGUuaXRlbXMgPSBbJ3NldHRpbmdzJywgJ2hvbWUnLCAnb3RoZXInXTsNCiAgICAgICAgICAkc2NvcGUuc2VsZWN0aW9uID0gJHNjb3BlLml0ZW1zWzBdOw0KICAgICAgICB9XSk7DQogICAgPC9maWxlPg0KICAgIDxmaWxlIG5hbWU9ImFuaW1hdGlvbnMuY3NzIj4NCiAgICAgIC5hbmltYXRlLXN3aXRjaC1jb250YWluZXIgew0KICAgICAgICBwb3NpdGlvbjpyZWxhdGl2ZTsNCiAgICAgICAgYmFja2dyb3VuZDp3aGl0ZTsNCiAgICAgICAgYm9yZGVyOjFweCBzb2xpZCBibGFjazsNCiAgICAgICAgaGVpZ2h0OjQwcHg7DQogICAgICAgIG92ZXJmbG93OmhpZGRlbjsNCiAgICAgIH0NCg0KICAgICAgLmFuaW1hdGUtc3dpdGNoIHsNCiAgICAgICAgcGFkZGluZzoxMHB4Ow0KICAgICAgfQ0KDQogICAgICAuYW5pbWF0ZS1zd2l0Y2gubmctYW5pbWF0ZSB7DQogICAgICAgIC13ZWJraXQtdHJhbnNpdGlvbjphbGwgY3ViaWMtYmV6aWVyKDAuMjUwLCAwLjQ2MCwgMC40NTAsIDAuOTQwKSAwLjVzOw0KICAgICAgICB0cmFuc2l0aW9uOmFsbCBjdWJpYy1iZXppZXIoMC4yNTAsIDAuNDYwLCAwLjQ1MCwgMC45NDApIDAuNXM7DQoNCiAgICAgICAgcG9zaXRpb246YWJzb2x1dGU7DQogICAgICAgIHRvcDowOw0KICAgICAgICBsZWZ0OjA7DQogICAgICAgIHJpZ2h0OjA7DQogICAgICAgIGJvdHRvbTowOw0KICAgICAgfQ0KDQogICAgICAuYW5pbWF0ZS1zd2l0Y2gubmctbGVhdmUubmctbGVhdmUtYWN0aXZlLA0KICAgICAgLmFuaW1hdGUtc3dpdGNoLm5nLWVudGVyIHsNCiAgICAgICAgdG9wOi01MHB4Ow0KICAgICAgfQ0KICAgICAgLmFuaW1hdGUtc3dpdGNoLm5nLWxlYXZlLA0KICAgICAgLmFuaW1hdGUtc3dpdGNoLm5nLWVudGVyLm5nLWVudGVyLWFjdGl2ZSB7DQogICAgICAgIHRvcDowOw0KICAgICAgfQ0KICAgIDwvZmlsZT4NCiAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgIHZhciBzd2l0Y2hFbGVtID0gZWxlbWVudChieS5jc3MoJ1tuZy1zd2l0Y2hdJykpOw0KICAgICAgdmFyIHNlbGVjdCA9IGVsZW1lbnQoYnkubW9kZWwoJ3NlbGVjdGlvbicpKTsNCg0KICAgICAgaXQoJ3Nob3VsZCBzdGFydCBpbiBzZXR0aW5ncycsIGZ1bmN0aW9uKCkgew0KICAgICAgICBleHBlY3Qoc3dpdGNoRWxlbS5nZXRUZXh0KCkpLnRvTWF0Y2goL1NldHRpbmdzIERpdi8pOw0KICAgICAgfSk7DQogICAgICBpdCgnc2hvdWxkIGNoYW5nZSB0byBob21lJywgZnVuY3Rpb24oKSB7DQogICAgICAgIHNlbGVjdC5hbGwoYnkuY3NzKCdvcHRpb24nKSkuZ2V0KDEpLmNsaWNrKCk7DQogICAgICAgIGV4cGVjdChzd2l0Y2hFbGVtLmdldFRleHQoKSkudG9NYXRjaCgvSG9tZSBTcGFuLyk7DQogICAgICB9KTsNCiAgICAgIGl0KCdzaG91bGQgc2VsZWN0IGRlZmF1bHQnLCBmdW5jdGlvbigpIHsNCiAgICAgICAgc2VsZWN0LmFsbChieS5jc3MoJ29wdGlvbicpKS5nZXQoMikuY2xpY2soKTsNCiAgICAgICAgZXhwZWN0KHN3aXRjaEVsZW0uZ2V0VGV4dCgpKS50b01hdGNoKC9kZWZhdWx0Lyk7DQogICAgICB9KTsNCiAgICA8L2ZpbGU+DQogIDwvZXhhbXBsZT4NCiAqLw0KdmFyIG5nU3dpdGNoRGlyZWN0aXZlID0gWyckYW5pbWF0ZScsIGZ1bmN0aW9uKCRhbmltYXRlKSB7DQogIHJldHVybiB7DQogICAgcmVzdHJpY3Q6ICdFQScsDQogICAgcmVxdWlyZTogJ25nU3dpdGNoJywNCg0KICAgIC8vIGFza3MgZm9yICRzY29wZSB0byBmb29sIHRoZSBCQyBjb250cm9sbGVyIG1vZHVsZQ0KICAgIGNvbnRyb2xsZXI6IFsnJHNjb3BlJywgZnVuY3Rpb24gbmdTd2l0Y2hDb250cm9sbGVyKCkgew0KICAgICB0aGlzLmNhc2VzID0ge307DQogICAgfV0sDQogICAgbGluazogZnVuY3Rpb24oc2NvcGUsIGVsZW1lbnQsIGF0dHIsIG5nU3dpdGNoQ29udHJvbGxlcikgew0KICAgICAgdmFyIHdhdGNoRXhwciA9IGF0dHIubmdTd2l0Y2ggfHwgYXR0ci5vbiwNCiAgICAgICAgICBzZWxlY3RlZFRyYW5zY2x1ZGVzID0gW10sDQogICAgICAgICAgc2VsZWN0ZWRFbGVtZW50cyA9IFtdLA0KICAgICAgICAgIHByZXZpb3VzTGVhdmVBbmltYXRpb25zID0gW10sDQogICAgICAgICAgc2VsZWN0ZWRTY29wZXMgPSBbXTsNCg0KICAgICAgdmFyIHNwbGljZUZhY3RvcnkgPSBmdW5jdGlvbihhcnJheSwgaW5kZXgpIHsNCiAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7IGFycmF5LnNwbGljZShpbmRleCwgMSk7IH07DQogICAgICB9Ow0KDQogICAgICBzY29wZS4kd2F0Y2god2F0Y2hFeHByLCBmdW5jdGlvbiBuZ1N3aXRjaFdhdGNoQWN0aW9uKHZhbHVlKSB7DQogICAgICAgIHZhciBpLCBpaTsNCiAgICAgICAgZm9yIChpID0gMCwgaWkgPSBwcmV2aW91c0xlYXZlQW5pbWF0aW9ucy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7DQogICAgICAgICAgJGFuaW1hdGUuY2FuY2VsKHByZXZpb3VzTGVhdmVBbmltYXRpb25zW2ldKTsNCiAgICAgICAgfQ0KICAgICAgICBwcmV2aW91c0xlYXZlQW5pbWF0aW9ucy5sZW5ndGggPSAwOw0KDQogICAgICAgIGZvciAoaSA9IDAsIGlpID0gc2VsZWN0ZWRTY29wZXMubGVuZ3RoOyBpIDwgaWk7ICsraSkgew0KICAgICAgICAgIHZhciBzZWxlY3RlZCA9IGdldEJsb2NrTm9kZXMoc2VsZWN0ZWRFbGVtZW50c1tpXS5jbG9uZSk7DQogICAgICAgICAgc2VsZWN0ZWRTY29wZXNbaV0uJGRlc3Ryb3koKTsNCiAgICAgICAgICB2YXIgcHJvbWlzZSA9IHByZXZpb3VzTGVhdmVBbmltYXRpb25zW2ldID0gJGFuaW1hdGUubGVhdmUoc2VsZWN0ZWQpOw0KICAgICAgICAgIHByb21pc2UudGhlbihzcGxpY2VGYWN0b3J5KHByZXZpb3VzTGVhdmVBbmltYXRpb25zLCBpKSk7DQogICAgICAgIH0NCg0KICAgICAgICBzZWxlY3RlZEVsZW1lbnRzLmxlbmd0aCA9IDA7DQogICAgICAgIHNlbGVjdGVkU2NvcGVzLmxlbmd0aCA9IDA7DQoNCiAgICAgICAgaWYgKChzZWxlY3RlZFRyYW5zY2x1ZGVzID0gbmdTd2l0Y2hDb250cm9sbGVyLmNhc2VzWychJyArIHZhbHVlXSB8fCBuZ1N3aXRjaENvbnRyb2xsZXIuY2FzZXNbJz8nXSkpIHsNCiAgICAgICAgICBmb3JFYWNoKHNlbGVjdGVkVHJhbnNjbHVkZXMsIGZ1bmN0aW9uKHNlbGVjdGVkVHJhbnNjbHVkZSkgew0KICAgICAgICAgICAgc2VsZWN0ZWRUcmFuc2NsdWRlLnRyYW5zY2x1ZGUoZnVuY3Rpb24oY2FzZUVsZW1lbnQsIHNlbGVjdGVkU2NvcGUpIHsNCiAgICAgICAgICAgICAgc2VsZWN0ZWRTY29wZXMucHVzaChzZWxlY3RlZFNjb3BlKTsNCiAgICAgICAgICAgICAgdmFyIGFuY2hvciA9IHNlbGVjdGVkVHJhbnNjbHVkZS5lbGVtZW50Ow0KICAgICAgICAgICAgICBjYXNlRWxlbWVudFtjYXNlRWxlbWVudC5sZW5ndGgrK10gPSBkb2N1bWVudC5jcmVhdGVDb21tZW50KCcgZW5kIG5nU3dpdGNoV2hlbjogJyk7DQogICAgICAgICAgICAgIHZhciBibG9jayA9IHsgY2xvbmU6IGNhc2VFbGVtZW50IH07DQoNCiAgICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50cy5wdXNoKGJsb2NrKTsNCiAgICAgICAgICAgICAgJGFuaW1hdGUuZW50ZXIoY2FzZUVsZW1lbnQsIGFuY2hvci5wYXJlbnQoKSwgYW5jaG9yKTsNCiAgICAgICAgICAgIH0pOw0KICAgICAgICAgIH0pOw0KICAgICAgICB9DQogICAgICB9KTsNCiAgICB9DQogIH07DQp9XTsNCg0KdmFyIG5nU3dpdGNoV2hlbkRpcmVjdGl2ZSA9IG5nRGlyZWN0aXZlKHsNCiAgdHJhbnNjbHVkZTogJ2VsZW1lbnQnLA0KICBwcmlvcml0eTogMTIwMCwNCiAgcmVxdWlyZTogJ15uZ1N3aXRjaCcsDQogIG11bHRpRWxlbWVudDogdHJ1ZSwNCiAgbGluazogZnVuY3Rpb24oc2NvcGUsIGVsZW1lbnQsIGF0dHJzLCBjdHJsLCAkdHJhbnNjbHVkZSkgew0KICAgIGN0cmwuY2FzZXNbJyEnICsgYXR0cnMubmdTd2l0Y2hXaGVuXSA9IChjdHJsLmNhc2VzWychJyArIGF0dHJzLm5nU3dpdGNoV2hlbl0gfHwgW10pOw0KICAgIGN0cmwuY2FzZXNbJyEnICsgYXR0cnMubmdTd2l0Y2hXaGVuXS5wdXNoKHsgdHJhbnNjbHVkZTogJHRyYW5zY2x1ZGUsIGVsZW1lbnQ6IGVsZW1lbnQgfSk7DQogIH0NCn0pOw0KDQp2YXIgbmdTd2l0Y2hEZWZhdWx0RGlyZWN0aXZlID0gbmdEaXJlY3RpdmUoew0KICB0cmFuc2NsdWRlOiAnZWxlbWVudCcsDQogIHByaW9yaXR5OiAxMjAwLA0KICByZXF1aXJlOiAnXm5nU3dpdGNoJywNCiAgbXVsdGlFbGVtZW50OiB0cnVlLA0KICBsaW5rOiBmdW5jdGlvbihzY29wZSwgZWxlbWVudCwgYXR0ciwgY3RybCwgJHRyYW5zY2x1ZGUpIHsNCiAgICBjdHJsLmNhc2VzWyc/J10gPSAoY3RybC5jYXNlc1snPyddIHx8IFtdKTsNCiAgICBjdHJsLmNhc2VzWyc/J10ucHVzaCh7IHRyYW5zY2x1ZGU6ICR0cmFuc2NsdWRlLCBlbGVtZW50OiBlbGVtZW50IH0pOw0KICAgfQ0KfSk7DQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgbmdUcmFuc2NsdWRlDQogKiBAcmVzdHJpY3QgRUFDDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBEaXJlY3RpdmUgdGhhdCBtYXJrcyB0aGUgaW5zZXJ0aW9uIHBvaW50IGZvciB0aGUgdHJhbnNjbHVkZWQgRE9NIG9mIHRoZSBuZWFyZXN0IHBhcmVudCBkaXJlY3RpdmUgdGhhdCB1c2VzIHRyYW5zY2x1c2lvbi4NCiAqDQogKiBBbnkgZXhpc3RpbmcgY29udGVudCBvZiB0aGUgZWxlbWVudCB0aGF0IHRoaXMgZGlyZWN0aXZlIGlzIHBsYWNlZCBvbiB3aWxsIGJlIHJlbW92ZWQgYmVmb3JlIHRoZSB0cmFuc2NsdWRlZCBjb250ZW50IGlzIGluc2VydGVkLg0KICoNCiAqIEBlbGVtZW50IEFOWQ0KICoNCiAqIEBleGFtcGxlDQogICA8ZXhhbXBsZSBtb2R1bGU9InRyYW5zY2x1ZGVFeGFtcGxlIj4NCiAgICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICAgPHNjcmlwdD4NCiAgICAgICAgIGFuZ3VsYXIubW9kdWxlKCd0cmFuc2NsdWRlRXhhbXBsZScsIFtdKQ0KICAgICAgICAgIC5kaXJlY3RpdmUoJ3BhbmUnLCBmdW5jdGlvbigpew0KICAgICAgICAgICAgIHJldHVybiB7DQogICAgICAgICAgICAgICByZXN0cmljdDogJ0UnLA0KICAgICAgICAgICAgICAgdHJhbnNjbHVkZTogdHJ1ZSwNCiAgICAgICAgICAgICAgIHNjb3BlOiB7IHRpdGxlOidAJyB9LA0KICAgICAgICAgICAgICAgdGVtcGxhdGU6ICc8ZGl2IHN0eWxlPSJib3JkZXI6IDFweCBzb2xpZCBibGFjazsiPicgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgJzxkaXYgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6IGdyYXkiPnt7dGl0bGV9fTwvZGl2PicgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgJzxuZy10cmFuc2NsdWRlPjwvbmctdHJhbnNjbHVkZT4nICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAnPC9kaXY+Jw0KICAgICAgICAgICAgIH07DQogICAgICAgICB9KQ0KICAgICAgICAgLmNvbnRyb2xsZXIoJ0V4YW1wbGVDb250cm9sbGVyJywgWyckc2NvcGUnLCBmdW5jdGlvbigkc2NvcGUpIHsNCiAgICAgICAgICAgJHNjb3BlLnRpdGxlID0gJ0xvcmVtIElwc3VtJzsNCiAgICAgICAgICAgJHNjb3BlLnRleHQgPSAnTmVxdWUgcG9ycm8gcXVpc3F1YW0gZXN0IHF1aSBkb2xvcmVtIGlwc3VtIHF1aWEgZG9sb3IuLi4nOw0KICAgICAgICAgfV0pOw0KICAgICAgIDwvc2NyaXB0Pg0KICAgICAgIDxkaXYgbmctY29udHJvbGxlcj0iRXhhbXBsZUNvbnRyb2xsZXIiPg0KICAgICAgICAgPGlucHV0IG5nLW1vZGVsPSJ0aXRsZSI+IDxici8+DQogICAgICAgICA8dGV4dGFyZWEgbmctbW9kZWw9InRleHQiPjwvdGV4dGFyZWE+IDxici8+DQogICAgICAgICA8cGFuZSB0aXRsZT0ie3t0aXRsZX19Ij57e3RleHR9fTwvcGFuZT4NCiAgICAgICA8L2Rpdj4NCiAgICAgPC9maWxlPg0KICAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgICAgaXQoJ3Nob3VsZCBoYXZlIHRyYW5zY2x1ZGVkJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgdmFyIHRpdGxlRWxlbWVudCA9IGVsZW1lbnQoYnkubW9kZWwoJ3RpdGxlJykpOw0KICAgICAgICAgIHRpdGxlRWxlbWVudC5jbGVhcigpOw0KICAgICAgICAgIHRpdGxlRWxlbWVudC5zZW5kS2V5cygnVElUTEUnKTsNCiAgICAgICAgICB2YXIgdGV4dEVsZW1lbnQgPSBlbGVtZW50KGJ5Lm1vZGVsKCd0ZXh0JykpOw0KICAgICAgICAgIHRleHRFbGVtZW50LmNsZWFyKCk7DQogICAgICAgICAgdGV4dEVsZW1lbnQuc2VuZEtleXMoJ1RFWFQnKTsNCiAgICAgICAgICBleHBlY3QoZWxlbWVudChieS5iaW5kaW5nKCd0aXRsZScpKS5nZXRUZXh0KCkpLnRvRXF1YWwoJ1RJVExFJyk7DQogICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuYmluZGluZygndGV4dCcpKS5nZXRUZXh0KCkpLnRvRXF1YWwoJ1RFWFQnKTsNCiAgICAgICAgfSk7DQogICAgIDwvZmlsZT4NCiAgIDwvZXhhbXBsZT4NCiAqDQogKi8NCnZhciBuZ1RyYW5zY2x1ZGVEaXJlY3RpdmUgPSBuZ0RpcmVjdGl2ZSh7DQogIHJlc3RyaWN0OiAnRUFDJywNCiAgbGluazogZnVuY3Rpb24oJHNjb3BlLCAkZWxlbWVudCwgJGF0dHJzLCBjb250cm9sbGVyLCAkdHJhbnNjbHVkZSkgew0KICAgIGlmICghJHRyYW5zY2x1ZGUpIHsNCiAgICAgIHRocm93IG1pbkVycignbmdUcmFuc2NsdWRlJykoJ29ycGhhbicsDQogICAgICAgJ0lsbGVnYWwgdXNlIG9mIG5nVHJhbnNjbHVkZSBkaXJlY3RpdmUgaW4gdGhlIHRlbXBsYXRlISAnICsNCiAgICAgICAnTm8gcGFyZW50IGRpcmVjdGl2ZSB0aGF0IHJlcXVpcmVzIGEgdHJhbnNjbHVzaW9uIGZvdW5kLiAnICsNCiAgICAgICAnRWxlbWVudDogezB9JywNCiAgICAgICBzdGFydGluZ1RhZygkZWxlbWVudCkpOw0KICAgIH0NCg0KICAgICR0cmFuc2NsdWRlKGZ1bmN0aW9uKGNsb25lKSB7DQogICAgICAkZWxlbWVudC5lbXB0eSgpOw0KICAgICAgJGVsZW1lbnQuYXBwZW5kKGNsb25lKTsNCiAgICB9KTsNCiAgfQ0KfSk7DQoNCi8qKg0KICogQG5nZG9jIGRpcmVjdGl2ZQ0KICogQG5hbWUgc2NyaXB0DQogKiBAcmVzdHJpY3QgRQ0KICoNCiAqIEBkZXNjcmlwdGlvbg0KICogTG9hZCB0aGUgY29udGVudCBvZiBhIGA8c2NyaXB0PmAgZWxlbWVudCBpbnRvIHtAbGluayBuZy4kdGVtcGxhdGVDYWNoZSBgJHRlbXBsYXRlQ2FjaGVgfSwgc28gdGhhdCB0aGUNCiAqIHRlbXBsYXRlIGNhbiBiZSB1c2VkIGJ5IHtAbGluayBuZy5kaXJlY3RpdmU6bmdJbmNsdWRlIGBuZ0luY2x1ZGVgfSwNCiAqIHtAbGluayBuZ1JvdXRlLmRpcmVjdGl2ZTpuZ1ZpZXcgYG5nVmlld2B9LCBvciB7QGxpbmsgZ3VpZGUvZGlyZWN0aXZlIGRpcmVjdGl2ZXN9LiBUaGUgdHlwZSBvZiB0aGUNCiAqIGA8c2NyaXB0PmAgZWxlbWVudCBtdXN0IGJlIHNwZWNpZmllZCBhcyBgdGV4dC9uZy10ZW1wbGF0ZWAsIGFuZCBhIGNhY2hlIG5hbWUgZm9yIHRoZSB0ZW1wbGF0ZSBtdXN0IGJlDQogKiBhc3NpZ25lZCB0aHJvdWdoIHRoZSBlbGVtZW50J3MgYGlkYCwgd2hpY2ggY2FuIHRoZW4gYmUgdXNlZCBhcyBhIGRpcmVjdGl2ZSdzIGB0ZW1wbGF0ZVVybGAuDQogKg0KICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgTXVzdCBiZSBzZXQgdG8gYCd0ZXh0L25nLXRlbXBsYXRlJ2AuDQogKiBAcGFyYW0ge3N0cmluZ30gaWQgQ2FjaGUgbmFtZSBvZiB0aGUgdGVtcGxhdGUuDQogKg0KICogQGV4YW1wbGUNCiAgPGV4YW1wbGU+DQogICAgPGZpbGUgbmFtZT0iaW5kZXguaHRtbCI+DQogICAgICA8c2NyaXB0IHR5cGU9InRleHQvbmctdGVtcGxhdGUiIGlkPSIvdHBsLmh0bWwiPg0KICAgICAgICBDb250ZW50IG9mIHRoZSB0ZW1wbGF0ZS4NCiAgICAgIDwvc2NyaXB0Pg0KDQogICAgICA8YSBuZy1jbGljaz0iY3VycmVudFRwbD0nL3RwbC5odG1sJyIgaWQ9InRwbC1saW5rIj5Mb2FkIGlubGluZWQgdGVtcGxhdGU8L2E+DQogICAgICA8ZGl2IGlkPSJ0cGwtY29udGVudCIgbmctaW5jbHVkZSBzcmM9ImN1cnJlbnRUcGwiPjwvZGl2Pg0KICAgIDwvZmlsZT4NCiAgICA8ZmlsZSBuYW1lPSJwcm90cmFjdG9yLmpzIiB0eXBlPSJwcm90cmFjdG9yIj4NCiAgICAgIGl0KCdzaG91bGQgbG9hZCB0ZW1wbGF0ZSBkZWZpbmVkIGluc2lkZSBzY3JpcHQgdGFnJywgZnVuY3Rpb24oKSB7DQogICAgICAgIGVsZW1lbnQoYnkuY3NzKCcjdHBsLWxpbmsnKSkuY2xpY2soKTsNCiAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuY3NzKCcjdHBsLWNvbnRlbnQnKSkuZ2V0VGV4dCgpKS50b01hdGNoKC9Db250ZW50IG9mIHRoZSB0ZW1wbGF0ZS8pOw0KICAgICAgfSk7DQogICAgPC9maWxlPg0KICA8L2V4YW1wbGU+DQogKi8NCnZhciBzY3JpcHREaXJlY3RpdmUgPSBbJyR0ZW1wbGF0ZUNhY2hlJywgZnVuY3Rpb24oJHRlbXBsYXRlQ2FjaGUpIHsNCiAgcmV0dXJuIHsNCiAgICByZXN0cmljdDogJ0UnLA0KICAgIHRlcm1pbmFsOiB0cnVlLA0KICAgIGNvbXBpbGU6IGZ1bmN0aW9uKGVsZW1lbnQsIGF0dHIpIHsNCiAgICAgIGlmIChhdHRyLnR5cGUgPT0gJ3RleHQvbmctdGVtcGxhdGUnKSB7DQogICAgICAgIHZhciB0ZW1wbGF0ZVVybCA9IGF0dHIuaWQsDQogICAgICAgICAgICB0ZXh0ID0gZWxlbWVudFswXS50ZXh0Ow0KDQogICAgICAgICR0ZW1wbGF0ZUNhY2hlLnB1dCh0ZW1wbGF0ZVVybCwgdGV4dCk7DQogICAgICB9DQogICAgfQ0KICB9Ow0KfV07DQoNCnZhciBuZ09wdGlvbnNNaW5FcnIgPSBtaW5FcnIoJ25nT3B0aW9ucycpOw0KLyoqDQogKiBAbmdkb2MgZGlyZWN0aXZlDQogKiBAbmFtZSBzZWxlY3QNCiAqIEByZXN0cmljdCBFDQogKg0KICogQGRlc2NyaXB0aW9uDQogKiBIVE1MIGBTRUxFQ1RgIGVsZW1lbnQgd2l0aCBhbmd1bGFyIGRhdGEtYmluZGluZy4NCiAqDQogKiAjIGBuZ09wdGlvbnNgDQogKg0KICogVGhlIGBuZ09wdGlvbnNgIGF0dHJpYnV0ZSBjYW4gYmUgdXNlZCB0byBkeW5hbWljYWxseSBnZW5lcmF0ZSBhIGxpc3Qgb2YgYDxvcHRpb24+YA0KICogZWxlbWVudHMgZm9yIHRoZSBgPHNlbGVjdD5gIGVsZW1lbnQgdXNpbmcgdGhlIGFycmF5IG9yIG9iamVjdCBvYnRhaW5lZCBieSBldmFsdWF0aW5nIHRoZQ0KICogYG5nT3B0aW9uc2AgY29tcHJlaGVuc2lvbiBleHByZXNzaW9uLg0KICoNCiAqIEluIG1hbnkgY2FzZXMsIGBuZ1JlcGVhdGAgY2FuIGJlIHVzZWQgb24gYDxvcHRpb24+YCBlbGVtZW50cyBpbnN0ZWFkIG9mIGBuZ09wdGlvbnNgIHRvIGFjaGlldmUgYQ0KICogc2ltaWxhciByZXN1bHQuIEhvd2V2ZXIsIGBuZ09wdGlvbnNgIHByb3ZpZGVzIHNvbWUgYmVuZWZpdHMgc3VjaCBhcyByZWR1Y2luZyBtZW1vcnkgYW5kDQogKiBpbmNyZWFzaW5nIHNwZWVkIGJ5IG5vdCBjcmVhdGluZyBhIG5ldyBzY29wZSBmb3IgZWFjaCByZXBlYXRlZCBpbnN0YW5jZSwgYXMgd2VsbCBhcyBwcm92aWRpbmcNCiAqIG1vcmUgZmxleGliaWxpdHkgaW4gaG93IHRoZSBgPHNlbGVjdD5gJ3MgbW9kZWwgaXMgYXNzaWduZWQgdmlhIHRoZSBgc2VsZWN0YCAqKmBhc2AqKiBwYXJ0IG9mIHRoZQ0KICogY29tcHJlaGVuc2lvbiBleHByZXNzaW9uLiBgbmdPcHRpb25zYCBzaG91bGQgYmUgdXNlZCB3aGVuIHRoZSBgPHNlbGVjdD5gIG1vZGVsIG5lZWRzIHRvIGJlIGJvdW5kDQogKiAgdG8gYSBub24tc3RyaW5nIHZhbHVlLiBUaGlzIGlzIGJlY2F1c2UgYW4gb3B0aW9uIGVsZW1lbnQgY2FuIG9ubHkgYmUgYm91bmQgdG8gc3RyaW5nIHZhbHVlcyBhdA0KICogcHJlc2VudC4NCiAqDQogKiBXaGVuIGFuIGl0ZW0gaW4gdGhlIGA8c2VsZWN0PmAgbWVudSBpcyBzZWxlY3RlZCwgdGhlIGFycmF5IGVsZW1lbnQgb3Igb2JqZWN0IHByb3BlcnR5DQogKiByZXByZXNlbnRlZCBieSB0aGUgc2VsZWN0ZWQgb3B0aW9uIHdpbGwgYmUgYm91bmQgdG8gdGhlIG1vZGVsIGlkZW50aWZpZWQgYnkgdGhlIGBuZ01vZGVsYA0KICogZGlyZWN0aXZlLg0KICoNCiAqIE9wdGlvbmFsbHksIGEgc2luZ2xlIGhhcmQtY29kZWQgYDxvcHRpb24+YCBlbGVtZW50LCB3aXRoIHRoZSB2YWx1ZSBzZXQgdG8gYW4gZW1wdHkgc3RyaW5nLCBjYW4NCiAqIGJlIG5lc3RlZCBpbnRvIHRoZSBgPHNlbGVjdD5gIGVsZW1lbnQuIFRoaXMgZWxlbWVudCB3aWxsIHRoZW4gcmVwcmVzZW50IHRoZSBgbnVsbGAgb3IgIm5vdCBzZWxlY3RlZCINCiAqIG9wdGlvbi4gU2VlIGV4YW1wbGUgYmVsb3cgZm9yIGRlbW9uc3RyYXRpb24uDQogKg0KICogPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtd2FybmluZyI+DQogKiAqKk5vdGU6KiogYG5nTW9kZWxgIGNvbXBhcmVzIGJ5IHJlZmVyZW5jZSwgbm90IHZhbHVlLiBUaGlzIGlzIGltcG9ydGFudCB3aGVuIGJpbmRpbmcgdG8gYW4NCiAqIGFycmF5IG9mIG9iamVjdHMuIFNlZSBhbiBleGFtcGxlIFtpbiB0aGlzIGpzZmlkZGxlXShodHRwOi8vanNmaWRkbGUubmV0L3FXelRiLykuDQogKiA8L2Rpdj4NCiAqDQogKiAjIyBgc2VsZWN0YCAqKmBhc2AqKg0KICoNCiAqIFVzaW5nIGBzZWxlY3RgICoqYGFzYCoqIHdpbGwgYmluZCB0aGUgcmVzdWx0IG9mIHRoZSBgc2VsZWN0YCBleHByZXNzaW9uIHRvIHRoZSBtb2RlbCwgYnV0DQogKiB0aGUgdmFsdWUgb2YgdGhlIGA8c2VsZWN0PmAgYW5kIGA8b3B0aW9uPmAgaHRtbCBlbGVtZW50cyB3aWxsIGJlIGVpdGhlciB0aGUgaW5kZXggKGZvciBhcnJheSBkYXRhIHNvdXJjZXMpDQogKiBvciBwcm9wZXJ0eSBuYW1lIChmb3Igb2JqZWN0IGRhdGEgc291cmNlcykgb2YgdGhlIHZhbHVlIHdpdGhpbiB0aGUgY29sbGVjdGlvbi4gSWYgYSAqKmB0cmFjayBieWAqKiBleHByZXNzaW9uDQogKiBpcyB1c2VkLCB0aGUgcmVzdWx0IG9mIHRoYXQgZXhwcmVzc2lvbiB3aWxsIGJlIHNldCBhcyB0aGUgdmFsdWUgb2YgdGhlIGBvcHRpb25gIGFuZCBgc2VsZWN0YCBlbGVtZW50cy4NCiAqDQogKg0KICogIyMjIGBzZWxlY3RgICoqYGFzYCoqIGFuZCAqKmB0cmFjayBieWAqKg0KICoNCiAqIDxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXdhcm5pbmciPg0KICogRG8gbm90IHVzZSBgc2VsZWN0YCAqKmBhc2AqKiBhbmQgKipgdHJhY2sgYnlgKiogaW4gdGhlIHNhbWUgZXhwcmVzc2lvbi4gVGhleSBhcmUgbm90IGRlc2lnbmVkIHRvIHdvcmsgdG9nZXRoZXIuDQogKiA8L2Rpdj4NCiAqDQogKiBDb25zaWRlciB0aGUgZm9sbG93aW5nIGV4YW1wbGU6DQogKg0KICogYGBgaHRtbA0KICogPHNlbGVjdCBuZy1vcHRpb25zPSJpdGVtLnN1Ykl0ZW0gYXMgaXRlbS5sYWJlbCBmb3IgaXRlbSBpbiB2YWx1ZXMgdHJhY2sgYnkgaXRlbS5pZCIgbmctbW9kZWw9InNlbGVjdGVkIj4NCiAqIGBgYA0KICoNCiAqIGBgYGpzDQogKiAkc2NvcGUudmFsdWVzID0gW3sNCiAqICAgaWQ6IDEsDQogKiAgIGxhYmVsOiAnYUxhYmVsJywNCiAqICAgc3ViSXRlbTogeyBuYW1lOiAnYVN1Ykl0ZW0nIH0NCiAqIH0sIHsNCiAqICAgaWQ6IDIsDQogKiAgIGxhYmVsOiAnYkxhYmVsJywNCiAqICAgc3ViSXRlbTogeyBuYW1lOiAnYlN1Ykl0ZW0nIH0NCiAqIH1dOw0KICoNCiAqICRzY29wZS5zZWxlY3RlZCA9IHsgbmFtZTogJ2FTdWJJdGVtJyB9Ow0KICogYGBgDQogKg0KICogV2l0aCB0aGUgcHVycG9zZSBvZiBwcmVzZXJ2aW5nIHRoZSBzZWxlY3Rpb24sIHRoZSAqKmB0cmFjayBieWAqKiBleHByZXNzaW9uIGlzIGFsd2F5cyBhcHBsaWVkIHRvIHRoZSBlbGVtZW50DQogKiBvZiB0aGUgZGF0YSBzb3VyY2UgKHRvIGBpdGVtYCBpbiB0aGlzIGV4YW1wbGUpLiBUbyBjYWxjdWxhdGUgd2hldGhlciBhbiBlbGVtZW50IGlzIHNlbGVjdGVkLCB3ZSBkbyB0aGUNCiAqIGZvbGxvd2luZzoNCiAqDQogKiAxLiBBcHBseSAqKmB0cmFjayBieWAqKiB0byB0aGUgZWxlbWVudHMgaW4gdGhlIGFycmF5LiBJbiB0aGUgZXhhbXBsZTogYFsxLCAyXWANCiAqIDIuIEFwcGx5ICoqYHRyYWNrIGJ5YCoqIHRvIHRoZSBhbHJlYWR5IHNlbGVjdGVkIHZhbHVlIGluIGBuZ01vZGVsYC4NCiAqICAgIEluIHRoZSBleGFtcGxlOiB0aGlzIGlzIG5vdCBwb3NzaWJsZSBhcyAqKmB0cmFjayBieWAqKiByZWZlcnMgdG8gYGl0ZW0uaWRgLCBidXQgdGhlIHNlbGVjdGVkDQogKiAgICB2YWx1ZSBmcm9tIGBuZ01vZGVsYCBpcyBge25hbWU6ICdhU3ViSXRlbSd9YCwgc28gdGhlICoqYHRyYWNrIGJ5YCoqIGV4cHJlc3Npb24gaXMgYXBwbGllZCB0bw0KICogICAgYSB3cm9uZyBvYmplY3QsIHRoZSBzZWxlY3RlZCBlbGVtZW50IGNhbid0IGJlIGZvdW5kLCBgPHNlbGVjdD5gIGlzIGFsd2F5cyByZXNldCB0byB0aGUgIm5vdA0KICogICAgc2VsZWN0ZWQiIG9wdGlvbi4NCiAqDQogKg0KICogQHBhcmFtIHtzdHJpbmd9IG5nTW9kZWwgQXNzaWduYWJsZSBhbmd1bGFyIGV4cHJlc3Npb24gdG8gZGF0YS1iaW5kIHRvLg0KICogQHBhcmFtIHtzdHJpbmc9fSBuYW1lIFByb3BlcnR5IG5hbWUgb2YgdGhlIGZvcm0gdW5kZXIgd2hpY2ggdGhlIGNvbnRyb2wgaXMgcHVibGlzaGVkLg0KICogQHBhcmFtIHtzdHJpbmc9fSByZXF1aXJlZCBUaGUgY29udHJvbCBpcyBjb25zaWRlcmVkIHZhbGlkIG9ubHkgaWYgdmFsdWUgaXMgZW50ZXJlZC4NCiAqIEBwYXJhbSB7c3RyaW5nPX0gbmdSZXF1aXJlZCBBZGRzIGByZXF1aXJlZGAgYXR0cmlidXRlIGFuZCBgcmVxdWlyZWRgIHZhbGlkYXRpb24gY29uc3RyYWludCB0bw0KICogICAgdGhlIGVsZW1lbnQgd2hlbiB0aGUgbmdSZXF1aXJlZCBleHByZXNzaW9uIGV2YWx1YXRlcyB0byB0cnVlLiBVc2UgYG5nUmVxdWlyZWRgIGluc3RlYWQgb2YNCiAqICAgIGByZXF1aXJlZGAgd2hlbiB5b3Ugd2FudCB0byBkYXRhLWJpbmQgdG8gdGhlIGByZXF1aXJlZGAgYXR0cmlidXRlLg0KICogQHBhcmFtIHtjb21wcmVoZW5zaW9uX2V4cHJlc3Npb249fSBuZ09wdGlvbnMgaW4gb25lIG9mIHRoZSBmb2xsb3dpbmcgZm9ybXM6DQogKg0KICogICAqIGZvciBhcnJheSBkYXRhIHNvdXJjZXM6DQogKiAgICAgKiBgbGFiZWxgICoqYGZvcmAqKiBgdmFsdWVgICoqYGluYCoqIGBhcnJheWANCiAqICAgICAqIGBzZWxlY3RgICoqYGFzYCoqIGBsYWJlbGAgKipgZm9yYCoqIGB2YWx1ZWAgKipgaW5gKiogYGFycmF5YA0KICogICAgICogYGxhYmVsYCAqKmBncm91cCBieWAqKiBgZ3JvdXBgICoqYGZvcmAqKiBgdmFsdWVgICoqYGluYCoqIGBhcnJheWANCiAqICAgICAqIGBsYWJlbGAgKipgZ3JvdXAgYnlgKiogYGdyb3VwYCAqKmBmb3JgKiogYHZhbHVlYCAqKmBpbmAqKiBgYXJyYXlgICoqYHRyYWNrIGJ5YCoqIGB0cmFja2V4cHJgDQogKiAgICAgKiBgbGFiZWxgICoqYGZvcmAqKiBgdmFsdWVgICoqYGluYCoqIGBhcnJheWAgfCBvcmRlckJ5OmBvcmRlcmV4cHJgICoqYHRyYWNrIGJ5YCoqIGB0cmFja2V4cHJgDQogKiAgICAgICAgKGZvciBpbmNsdWRpbmcgYSBmaWx0ZXIgd2l0aCBgdHJhY2sgYnlgKQ0KICogICAqIGZvciBvYmplY3QgZGF0YSBzb3VyY2VzOg0KICogICAgICogYGxhYmVsYCAqKmBmb3IgKGAqKmBrZXlgICoqYCxgKiogYHZhbHVlYCoqYCkgaW5gKiogYG9iamVjdGANCiAqICAgICAqIGBzZWxlY3RgICoqYGFzYCoqIGBsYWJlbGAgKipgZm9yIChgKipga2V5YCAqKmAsYCoqIGB2YWx1ZWAqKmApIGluYCoqIGBvYmplY3RgDQogKiAgICAgKiBgbGFiZWxgICoqYGdyb3VwIGJ5YCoqIGBncm91cGAgKipgZm9yIChgKipga2V5YCoqYCxgKiogYHZhbHVlYCoqYCkgaW5gKiogYG9iamVjdGANCiAqICAgICAqIGBzZWxlY3RgICoqYGFzYCoqIGBsYWJlbGAgKipgZ3JvdXAgYnlgKiogYGdyb3VwYA0KICogICAgICAgICAqKmBmb3JgIGAoYCoqYGtleWAqKmAsYCoqIGB2YWx1ZWAqKmApIGluYCoqIGBvYmplY3RgDQogKg0KICogV2hlcmU6DQogKg0KICogICAqIGBhcnJheWAgLyBgb2JqZWN0YDogYW4gZXhwcmVzc2lvbiB3aGljaCBldmFsdWF0ZXMgdG8gYW4gYXJyYXkgLyBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLg0KICogICAqIGB2YWx1ZWA6IGxvY2FsIHZhcmlhYmxlIHdoaWNoIHdpbGwgcmVmZXIgdG8gZWFjaCBpdGVtIGluIHRoZSBgYXJyYXlgIG9yIGVhY2ggcHJvcGVydHkgdmFsdWUNCiAqICAgICAgb2YgYG9iamVjdGAgZHVyaW5nIGl0ZXJhdGlvbi4NCiAqICAgKiBga2V5YDogbG9jYWwgdmFyaWFibGUgd2hpY2ggd2lsbCByZWZlciB0byBhIHByb3BlcnR5IG5hbWUgaW4gYG9iamVjdGAgZHVyaW5nIGl0ZXJhdGlvbi4NCiAqICAgKiBgbGFiZWxgOiBUaGUgcmVzdWx0IG9mIHRoaXMgZXhwcmVzc2lvbiB3aWxsIGJlIHRoZSBsYWJlbCBmb3IgYDxvcHRpb24+YCBlbGVtZW50LiBUaGUNCiAqICAgICBgZXhwcmVzc2lvbmAgd2lsbCBtb3N0IGxpa2VseSByZWZlciB0byB0aGUgYHZhbHVlYCB2YXJpYWJsZSAoZS5nLiBgdmFsdWUucHJvcGVydHlOYW1lYCkuDQogKiAgICogYHNlbGVjdGA6IFRoZSByZXN1bHQgb2YgdGhpcyBleHByZXNzaW9uIHdpbGwgYmUgYm91bmQgdG8gdGhlIG1vZGVsIG9mIHRoZSBwYXJlbnQgYDxzZWxlY3Q+YA0KICogICAgICBlbGVtZW50LiBJZiBub3Qgc3BlY2lmaWVkLCBgc2VsZWN0YCBleHByZXNzaW9uIHdpbGwgZGVmYXVsdCB0byBgdmFsdWVgLg0KICogICAqIGBncm91cGA6IFRoZSByZXN1bHQgb2YgdGhpcyBleHByZXNzaW9uIHdpbGwgYmUgdXNlZCB0byBncm91cCBvcHRpb25zIHVzaW5nIHRoZSBgPG9wdGdyb3VwPmANCiAqICAgICAgRE9NIGVsZW1lbnQuDQogKiAgICogYHRyYWNrZXhwcmA6IFVzZWQgd2hlbiB3b3JraW5nIHdpdGggYW4gYXJyYXkgb2Ygb2JqZWN0cy4gVGhlIHJlc3VsdCBvZiB0aGlzIGV4cHJlc3Npb24gd2lsbCBiZQ0KICogICAgICB1c2VkIHRvIGlkZW50aWZ5IHRoZSBvYmplY3RzIGluIHRoZSBhcnJheS4gVGhlIGB0cmFja2V4cHJgIHdpbGwgbW9zdCBsaWtlbHkgcmVmZXIgdG8gdGhlDQogKiAgICAgYHZhbHVlYCB2YXJpYWJsZSAoZS5nLiBgdmFsdWUucHJvcGVydHlOYW1lYCkuIFdpdGggdGhpcyB0aGUgc2VsZWN0aW9uIGlzIHByZXNlcnZlZA0KICogICAgICBldmVuIHdoZW4gdGhlIG9wdGlvbnMgYXJlIHJlY3JlYXRlZCAoZS5nLiByZWxvYWRlZCBmcm9tIHRoZSBzZXJ2ZXIpLg0KICoNCiAqIEBleGFtcGxlDQogICAgPGV4YW1wbGUgbW9kdWxlPSJzZWxlY3RFeGFtcGxlIj4NCiAgICAgIDxmaWxlIG5hbWU9ImluZGV4Lmh0bWwiPg0KICAgICAgICA8c2NyaXB0Pg0KICAgICAgICBhbmd1bGFyLm1vZHVsZSgnc2VsZWN0RXhhbXBsZScsIFtdKQ0KICAgICAgICAgIC5jb250cm9sbGVyKCdFeGFtcGxlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgZnVuY3Rpb24oJHNjb3BlKSB7DQogICAgICAgICAgICAkc2NvcGUuY29sb3JzID0gWw0KICAgICAgICAgICAgICB7bmFtZTonYmxhY2snLCBzaGFkZTonZGFyayd9LA0KICAgICAgICAgICAgICB7bmFtZTond2hpdGUnLCBzaGFkZTonbGlnaHQnfSwNCiAgICAgICAgICAgICAge25hbWU6J3JlZCcsIHNoYWRlOidkYXJrJ30sDQogICAgICAgICAgICAgIHtuYW1lOidibHVlJywgc2hhZGU6J2RhcmsnfSwNCiAgICAgICAgICAgICAge25hbWU6J3llbGxvdycsIHNoYWRlOidsaWdodCd9DQogICAgICAgICAgICBdOw0KICAgICAgICAgICAgJHNjb3BlLm15Q29sb3IgPSAkc2NvcGUuY29sb3JzWzJdOyAvLyByZWQNCiAgICAgICAgICB9XSk7DQogICAgICAgIDwvc2NyaXB0Pg0KICAgICAgICA8ZGl2IG5nLWNvbnRyb2xsZXI9IkV4YW1wbGVDb250cm9sbGVyIj4NCiAgICAgICAgICA8dWw+DQogICAgICAgICAgICA8bGkgbmctcmVwZWF0PSJjb2xvciBpbiBjb2xvcnMiPg0KICAgICAgICAgICAgICBOYW1lOiA8aW5wdXQgbmctbW9kZWw9ImNvbG9yLm5hbWUiPg0KICAgICAgICAgICAgICBbPGEgaHJlZiBuZy1jbGljaz0iY29sb3JzLnNwbGljZSgkaW5kZXgsIDEpIj5YPC9hPl0NCiAgICAgICAgICAgIDwvbGk+DQogICAgICAgICAgICA8bGk+DQogICAgICAgICAgICAgIFs8YSBocmVmIG5nLWNsaWNrPSJjb2xvcnMucHVzaCh7fSkiPmFkZDwvYT5dDQogICAgICAgICAgICA8L2xpPg0KICAgICAgICAgIDwvdWw+DQogICAgICAgICAgPGhyLz4NCiAgICAgICAgICBDb2xvciAobnVsbCBub3QgYWxsb3dlZCk6DQogICAgICAgICAgPHNlbGVjdCBuZy1tb2RlbD0ibXlDb2xvciIgbmctb3B0aW9ucz0iY29sb3IubmFtZSBmb3IgY29sb3IgaW4gY29sb3JzIj48L3NlbGVjdD48YnI+DQoNCiAgICAgICAgICBDb2xvciAobnVsbCBhbGxvd2VkKToNCiAgICAgICAgICA8c3BhbiAgY2xhc3M9Im51bGxhYmxlIj4NCiAgICAgICAgICAgIDxzZWxlY3QgbmctbW9kZWw9Im15Q29sb3IiIG5nLW9wdGlvbnM9ImNvbG9yLm5hbWUgZm9yIGNvbG9yIGluIGNvbG9ycyI+DQogICAgICAgICAgICAgIDxvcHRpb24gdmFsdWU9IiI+LS0gY2hvb3NlIGNvbG9yIC0tPC9vcHRpb24+DQogICAgICAgICAgICA8L3NlbGVjdD4NCiAgICAgICAgICA8L3NwYW4+PGJyLz4NCg0KICAgICAgICAgIENvbG9yIGdyb3VwZWQgYnkgc2hhZGU6DQogICAgICAgICAgPHNlbGVjdCBuZy1tb2RlbD0ibXlDb2xvciIgbmctb3B0aW9ucz0iY29sb3IubmFtZSBncm91cCBieSBjb2xvci5zaGFkZSBmb3IgY29sb3IgaW4gY29sb3JzIj4NCiAgICAgICAgICA8L3NlbGVjdD48YnIvPg0KDQoNCiAgICAgICAgICBTZWxlY3QgPGEgaHJlZiBuZy1jbGljaz0ibXlDb2xvciA9IHsgbmFtZTonbm90IGluIGxpc3QnLCBzaGFkZTogJ290aGVyJyB9Ij5ib2d1czwvYT4uPGJyPg0KICAgICAgICAgIDxoci8+DQogICAgICAgICAgQ3VycmVudGx5IHNlbGVjdGVkOiB7eyB7c2VsZWN0ZWRfY29sb3I6bXlDb2xvcn0gfX0NCiAgICAgICAgICA8ZGl2IHN0eWxlPSJib3JkZXI6c29saWQgMXB4IGJsYWNrOyBoZWlnaHQ6MjBweCINCiAgICAgICAgICAgICAgIG5nLXN0eWxlPSJ7J2JhY2tncm91bmQtY29sb3InOm15Q29sb3IubmFtZX0iPg0KICAgICAgICAgIDwvZGl2Pg0KICAgICAgICA8L2Rpdj4NCiAgICAgIDwvZmlsZT4NCiAgICAgIDxmaWxlIG5hbWU9InByb3RyYWN0b3IuanMiIHR5cGU9InByb3RyYWN0b3IiPg0KICAgICAgICAgaXQoJ3Nob3VsZCBjaGVjayBuZy1vcHRpb25zJywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgIGV4cGVjdChlbGVtZW50KGJ5LmJpbmRpbmcoJ3tzZWxlY3RlZF9jb2xvcjpteUNvbG9yfScpKS5nZXRUZXh0KCkpLnRvTWF0Y2goJ3JlZCcpOw0KICAgICAgICAgICBlbGVtZW50LmFsbChieS5tb2RlbCgnbXlDb2xvcicpKS5maXJzdCgpLmNsaWNrKCk7DQogICAgICAgICAgIGVsZW1lbnQuYWxsKGJ5LmNzcygnc2VsZWN0W25nLW1vZGVsPSJteUNvbG9yIl0gb3B0aW9uJykpLmZpcnN0KCkuY2xpY2soKTsNCiAgICAgICAgICAgZXhwZWN0KGVsZW1lbnQoYnkuYmluZGluZygne3NlbGVjdGVkX2NvbG9yOm15Q29sb3J9JykpLmdldFRleHQoKSkudG9NYXRjaCgnYmxhY2snKTsNCiAgICAgICAgICAgZWxlbWVudChieS5jc3MoJy5udWxsYWJsZSBzZWxlY3RbbmctbW9kZWw9Im15Q29sb3IiXScpKS5jbGljaygpOw0KICAgICAgICAgICBlbGVtZW50LmFsbChieS5jc3MoJy5udWxsYWJsZSBzZWxlY3RbbmctbW9kZWw9Im15Q29sb3IiXSBvcHRpb24nKSkuZmlyc3QoKS5jbGljaygpOw0KICAgICAgICAgICBleHBlY3QoZWxlbWVudChieS5iaW5kaW5nKCd7c2VsZWN0ZWRfY29sb3I6bXlDb2xvcn0nKSkuZ2V0VGV4dCgpKS50b01hdGNoKCdudWxsJyk7DQogICAgICAgICB9KTsNCiAgICAgIDwvZmlsZT4NCiAgICA8L2V4YW1wbGU+DQogKi8NCg0KdmFyIG5nT3B0aW9uc0RpcmVjdGl2ZSA9IHZhbHVlRm4oew0KICByZXN0cmljdDogJ0EnLA0KICB0ZXJtaW5hbDogdHJ1ZQ0KfSk7DQoNCi8vIGpzaGludCBtYXhsZW46IGZhbHNlDQp2YXIgc2VsZWN0RGlyZWN0aXZlID0gWyckY29tcGlsZScsICckcGFyc2UnLCBmdW5jdGlvbigkY29tcGlsZSwgICAkcGFyc2UpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAvLzAwMDAxMTExMTExMTExMDAwMDAwMDAwMDAyMjIyMjIyMjIyMDAwMDAwMDAwMDAwMDAwMDAwMDAwMzMzMzMzMzMzMzAwMDAwMDAwMDAwMDAwNDQ0NDQ0NDQ0NDQ0NDQ0MDAwMDAwMDAwNTU1NTU1NTU1NTU1NTU1MDAwMDAwMDY2NjY2NjY2NjY2NjY2NjAwMDAwMDAwMDAwMDAwMDc3Nzc3Nzc3NzcwMDAwMDAwMDAwMDAwMDAwMDAwODg4ODg4ODg4OA0KICB2YXIgTkdfT1BUSU9OU19SRUdFWFAgPSAvXlxzKihbXHNcU10rPykoPzpccythc1xzKyhbXHNcU10rPykpPyg/OlxzK2dyb3VwXHMrYnlccysoW1xzXFNdKz8pKT9ccytmb3JccysoPzooW1wkXHddW1wkXHddKil8KD86XChccyooW1wkXHddW1wkXHddKilccyosXHMqKFtcJFx3XVtcJFx3XSopXHMqXCkpKVxzK2luXHMrKFtcc1xTXSs/KSg/OlxzK3RyYWNrXHMrYnlccysoW1xzXFNdKz8pKT8kLywNCiAgICAgIG51bGxNb2RlbEN0cmwgPSB7JHNldFZpZXdWYWx1ZTogbm9vcH07DQovLyBqc2hpbnQgbWF4bGVuOiAxMDANCg0KICByZXR1cm4gew0KICAgIHJlc3RyaWN0OiAnRScsDQogICAgcmVxdWlyZTogWydzZWxlY3QnLCAnP25nTW9kZWwnXSwNCiAgICBjb250cm9sbGVyOiBbJyRlbGVtZW50JywgJyRzY29wZScsICckYXR0cnMnLCBmdW5jdGlvbigkZWxlbWVudCwgJHNjb3BlLCAkYXR0cnMpIHsNCiAgICAgIHZhciBzZWxmID0gdGhpcywNCiAgICAgICAgICBvcHRpb25zTWFwID0ge30sDQogICAgICAgICAgbmdNb2RlbEN0cmwgPSBudWxsTW9kZWxDdHJsLA0KICAgICAgICAgIG51bGxPcHRpb24sDQogICAgICAgICAgdW5rbm93bk9wdGlvbjsNCg0KDQogICAgICBzZWxmLmRhdGFib3VuZCA9ICRhdHRycy5uZ01vZGVsOw0KDQoNCiAgICAgIHNlbGYuaW5pdCA9IGZ1bmN0aW9uKG5nTW9kZWxDdHJsXywgbnVsbE9wdGlvbl8sIHVua25vd25PcHRpb25fKSB7DQogICAgICAgIG5nTW9kZWxDdHJsID0gbmdNb2RlbEN0cmxfOw0KICAgICAgICBudWxsT3B0aW9uID0gbnVsbE9wdGlvbl87DQogICAgICAgIHVua25vd25PcHRpb24gPSB1bmtub3duT3B0aW9uXzsNCiAgICAgIH07DQoNCg0KICAgICAgc2VsZi5hZGRPcHRpb24gPSBmdW5jdGlvbih2YWx1ZSwgZWxlbWVudCkgew0KICAgICAgICBhc3NlcnROb3RIYXNPd25Qcm9wZXJ0eSh2YWx1ZSwgJyJvcHRpb24gdmFsdWUiJyk7DQogICAgICAgIG9wdGlvbnNNYXBbdmFsdWVdID0gdHJ1ZTsNCg0KICAgICAgICBpZiAobmdNb2RlbEN0cmwuJHZpZXdWYWx1ZSA9PSB2YWx1ZSkgew0KICAgICAgICAgICRlbGVtZW50LnZhbCh2YWx1ZSk7DQogICAgICAgICAgaWYgKHVua25vd25PcHRpb24ucGFyZW50KCkpIHVua25vd25PcHRpb24ucmVtb3ZlKCk7DQogICAgICAgIH0NCiAgICAgICAgLy8gV29ya2Fyb3VuZCBmb3IgaHR0cHM6Ly9jb2RlLmdvb2dsZS5jb20vcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTM4MTQ1OQ0KICAgICAgICAvLyBBZGRpbmcgYW4gPG9wdGlvbiBzZWxlY3RlZD0ic2VsZWN0ZWQiPiBlbGVtZW50IHRvIGEgPHNlbGVjdCByZXF1aXJlZD0icmVxdWlyZWQiPiBzaG91bGQNCiAgICAgICAgLy8gYXV0b21hdGljYWxseSBzZWxlY3QgdGhlIG5ldyBlbGVtZW50DQogICAgICAgIGlmIChlbGVtZW50ICYmIGVsZW1lbnRbMF0uaGFzQXR0cmlidXRlKCdzZWxlY3RlZCcpKSB7DQogICAgICAgICAgZWxlbWVudFswXS5zZWxlY3RlZCA9IHRydWU7DQogICAgICAgIH0NCiAgICAgIH07DQoNCg0KICAgICAgc2VsZi5yZW1vdmVPcHRpb24gPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICBpZiAodGhpcy5oYXNPcHRpb24odmFsdWUpKSB7DQogICAgICAgICAgZGVsZXRlIG9wdGlvbnNNYXBbdmFsdWVdOw0KICAgICAgICAgIGlmIChuZ01vZGVsQ3RybC4kdmlld1ZhbHVlID09PSB2YWx1ZSkgew0KICAgICAgICAgICAgdGhpcy5yZW5kZXJVbmtub3duT3B0aW9uKHZhbHVlKTsNCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgIH07DQoNCg0KICAgICAgc2VsZi5yZW5kZXJVbmtub3duT3B0aW9uID0gZnVuY3Rpb24odmFsKSB7DQogICAgICAgIHZhciB1bmtub3duVmFsID0gJz8gJyArIGhhc2hLZXkodmFsKSArICcgPyc7DQogICAgICAgIHVua25vd25PcHRpb24udmFsKHVua25vd25WYWwpOw0KICAgICAgICAkZWxlbWVudC5wcmVwZW5kKHVua25vd25PcHRpb24pOw0KICAgICAgICAkZWxlbWVudC52YWwodW5rbm93blZhbCk7DQogICAgICAgIHVua25vd25PcHRpb24ucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTsgLy8gbmVlZGVkIGZvciBJRQ0KICAgICAgfTsNCg0KDQogICAgICBzZWxmLmhhc09wdGlvbiA9IGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgICAgIHJldHVybiBvcHRpb25zTWFwLmhhc093blByb3BlcnR5KHZhbHVlKTsNCiAgICAgIH07DQoNCiAgICAgICRzY29wZS4kb24oJyRkZXN0cm95JywgZnVuY3Rpb24oKSB7DQogICAgICAgIC8vIGRpc2FibGUgdW5rbm93biBvcHRpb24gc28gdGhhdCB3ZSBkb24ndCBkbyB3b3JrIHdoZW4gdGhlIHdob2xlIHNlbGVjdCBpcyBiZWluZyBkZXN0cm95ZWQNCiAgICAgICAgc2VsZi5yZW5kZXJVbmtub3duT3B0aW9uID0gbm9vcDsNCiAgICAgIH0pOw0KICAgIH1dLA0KDQogICAgbGluazogZnVuY3Rpb24oc2NvcGUsIGVsZW1lbnQsIGF0dHIsIGN0cmxzKSB7DQogICAgICAvLyBpZiBuZ01vZGVsIGlzIG5vdCBkZWZpbmVkLCB3ZSBkb24ndCBuZWVkIHRvIGRvIGFueXRoaW5nDQogICAgICBpZiAoIWN0cmxzWzFdKSByZXR1cm47DQoNCiAgICAgIHZhciBzZWxlY3RDdHJsID0gY3RybHNbMF0sDQogICAgICAgICAgbmdNb2RlbEN0cmwgPSBjdHJsc1sxXSwNCiAgICAgICAgICBtdWx0aXBsZSA9IGF0dHIubXVsdGlwbGUsDQogICAgICAgICAgb3B0aW9uc0V4cCA9IGF0dHIubmdPcHRpb25zLA0KICAgICAgICAgIG51bGxPcHRpb24gPSBmYWxzZSwgLy8gaWYgZmFsc2UsIHVzZXIgd2lsbCBub3QgYmUgYWJsZSB0byBzZWxlY3QgaXQgKHVzZWQgYnkgbmdPcHRpb25zKQ0KICAgICAgICAgIGVtcHR5T3B0aW9uLA0KICAgICAgICAgIHJlbmRlclNjaGVkdWxlZCA9IGZhbHNlLA0KICAgICAgICAgIC8vIHdlIGNhbid0IGp1c3QganFMaXRlKCc8b3B0aW9uPicpIHNpbmNlIGpxTGl0ZSBpcyBub3Qgc21hcnQgZW5vdWdoDQogICAgICAgICAgLy8gdG8gY3JlYXRlIGl0IGluIDxzZWxlY3Q+IGFuZCBJRSBiYXJmcyBvdGhlcndpc2UuDQogICAgICAgICAgb3B0aW9uVGVtcGxhdGUgPSBqcUxpdGUoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnb3B0aW9uJykpLA0KICAgICAgICAgIG9wdEdyb3VwVGVtcGxhdGUgPWpxTGl0ZShkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdvcHRncm91cCcpKSwNCiAgICAgICAgICB1bmtub3duT3B0aW9uID0gb3B0aW9uVGVtcGxhdGUuY2xvbmUoKTsNCg0KICAgICAgLy8gZmluZCAibnVsbCIgb3B0aW9uDQogICAgICBmb3IgKHZhciBpID0gMCwgY2hpbGRyZW4gPSBlbGVtZW50LmNoaWxkcmVuKCksIGlpID0gY2hpbGRyZW4ubGVuZ3RoOyBpIDwgaWk7IGkrKykgew0KICAgICAgICBpZiAoY2hpbGRyZW5baV0udmFsdWUgPT09ICcnKSB7DQogICAgICAgICAgZW1wdHlPcHRpb24gPSBudWxsT3B0aW9uID0gY2hpbGRyZW4uZXEoaSk7DQogICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCiAgICAgIH0NCg0KICAgICAgc2VsZWN0Q3RybC5pbml0KG5nTW9kZWxDdHJsLCBudWxsT3B0aW9uLCB1bmtub3duT3B0aW9uKTsNCg0KICAgICAgLy8gcmVxdWlyZWQgdmFsaWRhdG9yDQogICAgICBpZiAobXVsdGlwbGUpIHsNCiAgICAgICAgbmdNb2RlbEN0cmwuJGlzRW1wdHkgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgICAgICAgIHJldHVybiAhdmFsdWUgfHwgdmFsdWUubGVuZ3RoID09PSAwOw0KICAgICAgICB9Ow0KICAgICAgfQ0KDQogICAgICBpZiAob3B0aW9uc0V4cCkgc2V0dXBBc09wdGlvbnMoc2NvcGUsIGVsZW1lbnQsIG5nTW9kZWxDdHJsKTsNCiAgICAgIGVsc2UgaWYgKG11bHRpcGxlKSBzZXR1cEFzTXVsdGlwbGUoc2NvcGUsIGVsZW1lbnQsIG5nTW9kZWxDdHJsKTsNCiAgICAgIGVsc2Ugc2V0dXBBc1NpbmdsZShzY29wZSwgZWxlbWVudCwgbmdNb2RlbEN0cmwsIHNlbGVjdEN0cmwpOw0KDQoNCiAgICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCg0KDQoNCiAgICAgIGZ1bmN0aW9uIHNldHVwQXNTaW5nbGUoc2NvcGUsIHNlbGVjdEVsZW1lbnQsIG5nTW9kZWxDdHJsLCBzZWxlY3RDdHJsKSB7DQogICAgICAgIG5nTW9kZWxDdHJsLiRyZW5kZXIgPSBmdW5jdGlvbigpIHsNCiAgICAgICAgICB2YXIgdmlld1ZhbHVlID0gbmdNb2RlbEN0cmwuJHZpZXdWYWx1ZTsNCg0KICAgICAgICAgIGlmIChzZWxlY3RDdHJsLmhhc09wdGlvbih2aWV3VmFsdWUpKSB7DQogICAgICAgICAgICBpZiAodW5rbm93bk9wdGlvbi5wYXJlbnQoKSkgdW5rbm93bk9wdGlvbi5yZW1vdmUoKTsNCiAgICAgICAgICAgIHNlbGVjdEVsZW1lbnQudmFsKHZpZXdWYWx1ZSk7DQogICAgICAgICAgICBpZiAodmlld1ZhbHVlID09PSAnJykgZW1wdHlPcHRpb24ucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTsgLy8gdG8gbWFrZSBJRTkgaGFwcHkNCiAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgaWYgKGlzVW5kZWZpbmVkKHZpZXdWYWx1ZSkgJiYgZW1wdHlPcHRpb24pIHsNCiAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC52YWwoJycpOw0KICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgc2VsZWN0Q3RybC5yZW5kZXJVbmtub3duT3B0aW9uKHZpZXdWYWx1ZSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgfQ0KICAgICAgICB9Ow0KDQogICAgICAgIHNlbGVjdEVsZW1lbnQub24oJ2NoYW5nZScsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgIHNjb3BlLiRhcHBseShmdW5jdGlvbigpIHsNCiAgICAgICAgICAgIGlmICh1bmtub3duT3B0aW9uLnBhcmVudCgpKSB1bmtub3duT3B0aW9uLnJlbW92ZSgpOw0KICAgICAgICAgICAgbmdNb2RlbEN0cmwuJHNldFZpZXdWYWx1ZShzZWxlY3RFbGVtZW50LnZhbCgpKTsNCiAgICAgICAgICB9KTsNCiAgICAgICAgfSk7DQogICAgICB9DQoNCiAgICAgIGZ1bmN0aW9uIHNldHVwQXNNdWx0aXBsZShzY29wZSwgc2VsZWN0RWxlbWVudCwgY3RybCkgew0KICAgICAgICB2YXIgbGFzdFZpZXc7DQogICAgICAgIGN0cmwuJHJlbmRlciA9IGZ1bmN0aW9uKCkgew0KICAgICAgICAgIHZhciBpdGVtcyA9IG5ldyBIYXNoTWFwKGN0cmwuJHZpZXdWYWx1ZSk7DQogICAgICAgICAgZm9yRWFjaChzZWxlY3RFbGVtZW50LmZpbmQoJ29wdGlvbicpLCBmdW5jdGlvbihvcHRpb24pIHsNCiAgICAgICAgICAgIG9wdGlvbi5zZWxlY3RlZCA9IGlzRGVmaW5lZChpdGVtcy5nZXQob3B0aW9uLnZhbHVlKSk7DQogICAgICAgICAgfSk7DQogICAgICAgIH07DQoNCiAgICAgICAgLy8gd2UgaGF2ZSB0byBkbyBpdCBvbiBlYWNoIHdhdGNoIHNpbmNlIG5nTW9kZWwgd2F0Y2hlcyByZWZlcmVuY2UsIGJ1dA0KICAgICAgICAvLyB3ZSBuZWVkIHRvIHdvcmsgb2YgYW4gYXJyYXksIHNvIHdlIG5lZWQgdG8gc2VlIGlmIGFueXRoaW5nIHdhcyBpbnNlcnRlZC9yZW1vdmVkDQogICAgICAgIHNjb3BlLiR3YXRjaChmdW5jdGlvbiBzZWxlY3RNdWx0aXBsZVdhdGNoKCkgew0KICAgICAgICAgIGlmICghZXF1YWxzKGxhc3RWaWV3LCBjdHJsLiR2aWV3VmFsdWUpKSB7DQogICAgICAgICAgICBsYXN0VmlldyA9IHNoYWxsb3dDb3B5KGN0cmwuJHZpZXdWYWx1ZSk7DQogICAgICAgICAgICBjdHJsLiRyZW5kZXIoKTsNCiAgICAgICAgICB9DQogICAgICAgIH0pOw0KDQogICAgICAgIHNlbGVjdEVsZW1lbnQub24oJ2NoYW5nZScsIGZ1bmN0aW9uKCkgew0KICAgICAgICAgIHNjb3BlLiRhcHBseShmdW5jdGlvbigpIHsNCiAgICAgICAgICAgIHZhciBhcnJheSA9IFtdOw0KICAgICAgICAgICAgZm9yRWFjaChzZWxlY3RFbGVtZW50LmZpbmQoJ29wdGlvbicpLCBmdW5jdGlvbihvcHRpb24pIHsNCiAgICAgICAgICAgICAgaWYgKG9wdGlvbi5zZWxlY3RlZCkgew0KICAgICAgICAgICAgICAgIGFycmF5LnB1c2gob3B0aW9uLnZhbHVlKTsNCiAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfSk7DQogICAgICAgICAgICBjdHJsLiRzZXRWaWV3VmFsdWUoYXJyYXkpOw0KICAgICAgICAgIH0pOw0KICAgICAgICB9KTsNCiAgICAgIH0NCg0KICAgICAgZnVuY3Rpb24gc2V0dXBBc09wdGlvbnMoc2NvcGUsIHNlbGVjdEVsZW1lbnQsIGN0cmwpIHsNCiAgICAgICAgdmFyIG1hdGNoOw0KDQogICAgICAgIGlmICghKG1hdGNoID0gb3B0aW9uc0V4cC5tYXRjaChOR19PUFRJT05TX1JFR0VYUCkpKSB7DQogICAgICAgICAgdGhyb3cgbmdPcHRpb25zTWluRXJyKCdpZXhwJywNCiAgICAgICAgICAgICJFeHBlY3RlZCBleHByZXNzaW9uIGluIGZvcm0gb2YgIiArDQogICAgICAgICAgICAiJ19zZWxlY3RfIChhcyBfbGFiZWxfKT8gZm9yIChfa2V5XywpP192YWx1ZV8gaW4gX2NvbGxlY3Rpb25fJyIgKw0KICAgICAgICAgICAgIiBidXQgZ290ICd7MH0nLiBFbGVtZW50OiB7MX0iLA0KICAgICAgICAgICAgb3B0aW9uc0V4cCwgc3RhcnRpbmdUYWcoc2VsZWN0RWxlbWVudCkpOw0KICAgICAgICB9DQoNCiAgICAgICAgdmFyIGRpc3BsYXlGbiA9ICRwYXJzZShtYXRjaFsyXSB8fCBtYXRjaFsxXSksDQogICAgICAgICAgICB2YWx1ZU5hbWUgPSBtYXRjaFs0XSB8fCBtYXRjaFs2XSwNCiAgICAgICAgICAgIHNlbGVjdEFzID0gLyBhcyAvLnRlc3QobWF0Y2hbMF0pICYmIG1hdGNoWzFdLA0KICAgICAgICAgICAgc2VsZWN0QXNGbiA9IHNlbGVjdEFzID8gJHBhcnNlKHNlbGVjdEFzKSA6IG51bGwsDQogICAgICAgICAgICBrZXlOYW1lID0gbWF0Y2hbNV0sDQogICAgICAgICAgICBncm91cEJ5Rm4gPSAkcGFyc2UobWF0Y2hbM10gfHwgJycpLA0KICAgICAgICAgICAgdmFsdWVGbiA9ICRwYXJzZShtYXRjaFsyXSA/IG1hdGNoWzFdIDogdmFsdWVOYW1lKSwNCiAgICAgICAgICAgIHZhbHVlc0ZuID0gJHBhcnNlKG1hdGNoWzddKSwNCiAgICAgICAgICAgIHRyYWNrID0gbWF0Y2hbOF0sDQogICAgICAgICAgICB0cmFja0ZuID0gdHJhY2sgPyAkcGFyc2UobWF0Y2hbOF0pIDogbnVsbCwNCiAgICAgICAgICAgIHRyYWNrS2V5c0NhY2hlID0ge30sDQogICAgICAgICAgICAvLyBUaGlzIGlzIGFuIGFycmF5IG9mIGFycmF5IG9mIGV4aXN0aW5nIG9wdGlvbiBncm91cHMgaW4gRE9NLg0KICAgICAgICAgICAgLy8gV2UgdHJ5IHRvIHJldXNlIHRoZXNlIGlmIHBvc3NpYmxlDQogICAgICAgICAgICAvLyAtIG9wdGlvbkdyb3Vwc0NhY2hlWzBdIGlzIHRoZSBvcHRpb25zIHdpdGggbm8gb3B0aW9uIGdyb3VwDQogICAgICAgICAgICAvLyAtIG9wdGlvbkdyb3Vwc0NhY2hlWz9dWzBdIGlzIHRoZSBwYXJlbnQ6IGVpdGhlciB0aGUgU0VMRUNUIG9yIE9QVEdST1VQIGVsZW1lbnQNCiAgICAgICAgICAgIG9wdGlvbkdyb3Vwc0NhY2hlID0gW1t7ZWxlbWVudDogc2VsZWN0RWxlbWVudCwgbGFiZWw6Jyd9XV0sDQogICAgICAgICAgICAvL3JlLXVzYWJsZSBvYmplY3QgdG8gcmVwcmVzZW50IG9wdGlvbidzIGxvY2Fscw0KICAgICAgICAgICAgbG9jYWxzID0ge307DQoNCiAgICAgICAgaWYgKG51bGxPcHRpb24pIHsNCiAgICAgICAgICAvLyBjb21waWxlIHRoZSBlbGVtZW50IHNpbmNlIHRoZXJlIG1pZ2h0IGJlIGJpbmRpbmdzIGluIGl0DQogICAgICAgICAgJGNvbXBpbGUobnVsbE9wdGlvbikoc2NvcGUpOw0KDQogICAgICAgICAgLy8gcmVtb3ZlIHRoZSBjbGFzcywgd2hpY2ggaXMgYWRkZWQgYXV0b21hdGljYWxseSBiZWNhdXNlIHdlIHJlY29tcGlsZSB0aGUgZWxlbWVudCBhbmQgaXQNCiAgICAgICAgICAvLyBiZWNvbWVzIHRoZSBjb21waWxhdGlvbiByb290DQogICAgICAgICAgbnVsbE9wdGlvbi5yZW1vdmVDbGFzcygnbmctc2NvcGUnKTsNCg0KICAgICAgICAgIC8vIHdlIG5lZWQgdG8gcmVtb3ZlIGl0IGJlZm9yZSBjYWxsaW5nIHNlbGVjdEVsZW1lbnQuZW1wdHkoKSBiZWNhdXNlIG90aGVyd2lzZSBJRSB3aWxsDQogICAgICAgICAgLy8gcmVtb3ZlIHRoZSBsYWJlbCBmcm9tIHRoZSBlbGVtZW50LiB3dGY/DQogICAgICAgICAgbnVsbE9wdGlvbi5yZW1vdmUoKTsNCiAgICAgICAgfQ0KDQogICAgICAgIC8vIGNsZWFyIGNvbnRlbnRzLCB3ZSdsbCBhZGQgd2hhdCdzIG5lZWRlZCBiYXNlZCBvbiB0aGUgbW9kZWwNCiAgICAgICAgc2VsZWN0RWxlbWVudC5lbXB0eSgpOw0KDQogICAgICAgIHNlbGVjdEVsZW1lbnQub24oJ2NoYW5nZScsIHNlbGVjdGlvbkNoYW5nZWQpOw0KDQogICAgICAgIGN0cmwuJHJlbmRlciA9IHJlbmRlcjsNCg0KICAgICAgICBzY29wZS4kd2F0Y2hDb2xsZWN0aW9uKHZhbHVlc0ZuLCBzY2hlZHVsZVJlbmRlcmluZyk7DQogICAgICAgIHNjb3BlLiR3YXRjaENvbGxlY3Rpb24oZ2V0TGFiZWxzLCBzY2hlZHVsZVJlbmRlcmluZyk7DQoNCiAgICAgICAgaWYgKG11bHRpcGxlKSB7DQogICAgICAgICAgc2NvcGUuJHdhdGNoQ29sbGVjdGlvbihmdW5jdGlvbigpIHsgcmV0dXJuIGN0cmwuJG1vZGVsVmFsdWU7IH0sIHNjaGVkdWxlUmVuZGVyaW5nKTsNCiAgICAgICAgfQ0KDQogICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvLw0KDQogICAgICAgIGZ1bmN0aW9uIGNhbGxFeHByZXNzaW9uKGV4cHJGbiwga2V5LCB2YWx1ZSkgew0KICAgICAgICAgIGxvY2Fsc1t2YWx1ZU5hbWVdID0gdmFsdWU7DQogICAgICAgICAgaWYgKGtleU5hbWUpIGxvY2Fsc1trZXlOYW1lXSA9IGtleTsNCiAgICAgICAgICByZXR1cm4gZXhwckZuKHNjb3BlLCBsb2NhbHMpOw0KICAgICAgICB9DQoNCiAgICAgICAgZnVuY3Rpb24gc2VsZWN0aW9uQ2hhbmdlZCgpIHsNCiAgICAgICAgICBzY29wZS4kYXBwbHkoZnVuY3Rpb24oKSB7DQogICAgICAgICAgICB2YXIgY29sbGVjdGlvbiA9IHZhbHVlc0ZuKHNjb3BlKSB8fCBbXTsNCiAgICAgICAgICAgIHZhciB2aWV3VmFsdWU7DQogICAgICAgICAgICBpZiAobXVsdGlwbGUpIHsNCiAgICAgICAgICAgICAgdmlld1ZhbHVlID0gW107DQogICAgICAgICAgICAgIGZvckVhY2goc2VsZWN0RWxlbWVudC52YWwoKSwgZnVuY3Rpb24oc2VsZWN0ZWRLZXkpIHsNCiAgICAgICAgICAgICAgICAgIHNlbGVjdGVkS2V5ID0gdHJhY2tGbiA/IHRyYWNrS2V5c0NhY2hlW3NlbGVjdGVkS2V5XSA6IHNlbGVjdGVkS2V5Ow0KICAgICAgICAgICAgICAgIHZpZXdWYWx1ZS5wdXNoKGdldFZpZXdWYWx1ZShzZWxlY3RlZEtleSwgY29sbGVjdGlvbltzZWxlY3RlZEtleV0pKTsNCiAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICB2YXIgc2VsZWN0ZWRLZXkgPSB0cmFja0ZuID8gdHJhY2tLZXlzQ2FjaGVbc2VsZWN0RWxlbWVudC52YWwoKV0gOiBzZWxlY3RFbGVtZW50LnZhbCgpOw0KICAgICAgICAgICAgICB2aWV3VmFsdWUgPSBnZXRWaWV3VmFsdWUoc2VsZWN0ZWRLZXksIGNvbGxlY3Rpb25bc2VsZWN0ZWRLZXldKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGN0cmwuJHNldFZpZXdWYWx1ZSh2aWV3VmFsdWUpOw0KICAgICAgICAgICAgcmVuZGVyKCk7DQogICAgICAgICAgfSk7DQogICAgICAgIH0NCg0KICAgICAgICBmdW5jdGlvbiBnZXRWaWV3VmFsdWUoa2V5LCB2YWx1ZSkgew0KICAgICAgICAgIGlmIChrZXkgPT09ICc/Jykgew0KICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDsNCiAgICAgICAgICB9IGVsc2UgaWYgKGtleSA9PT0gJycpIHsNCiAgICAgICAgICAgIHJldHVybiBudWxsOw0KICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICB2YXIgdmlld1ZhbHVlRm4gPSBzZWxlY3RBc0ZuID8gc2VsZWN0QXNGbiA6IHZhbHVlRm47DQogICAgICAgICAgICByZXR1cm4gY2FsbEV4cHJlc3Npb24odmlld1ZhbHVlRm4sIGtleSwgdmFsdWUpOw0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGZ1bmN0aW9uIGdldExhYmVscygpIHsNCiAgICAgICAgICB2YXIgdmFsdWVzID0gdmFsdWVzRm4oc2NvcGUpOw0KICAgICAgICAgIHZhciB0b0Rpc3BsYXk7DQogICAgICAgICAgaWYgKHZhbHVlcyAmJiBpc0FycmF5KHZhbHVlcykpIHsNCiAgICAgICAgICAgIHRvRGlzcGxheSA9IG5ldyBBcnJheSh2YWx1ZXMubGVuZ3RoKTsNCiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHZhbHVlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7DQogICAgICAgICAgICAgIHRvRGlzcGxheVtpXSA9IGNhbGxFeHByZXNzaW9uKGRpc3BsYXlGbiwgaSwgdmFsdWVzW2ldKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIHJldHVybiB0b0Rpc3BsYXk7DQogICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZXMpIHsNCiAgICAgICAgICAgIC8vIFRPRE86IEFkZCBhIHRlc3QgZm9yIHRoaXMgY2FzZQ0KICAgICAgICAgICAgdG9EaXNwbGF5ID0ge307DQogICAgICAgICAgICBmb3IgKHZhciBwcm9wIGluIHZhbHVlcykgew0KICAgICAgICAgICAgICBpZiAodmFsdWVzLmhhc093blByb3BlcnR5KHByb3ApKSB7DQogICAgICAgICAgICAgICAgdG9EaXNwbGF5W3Byb3BdID0gY2FsbEV4cHJlc3Npb24oZGlzcGxheUZuLCBwcm9wLCB2YWx1ZXNbcHJvcF0pOw0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgfQ0KICAgICAgICAgIHJldHVybiB0b0Rpc3BsYXk7DQogICAgICAgIH0NCg0KICAgICAgICBmdW5jdGlvbiBjcmVhdGVJc1NlbGVjdGVkRm4odmlld1ZhbHVlKSB7DQogICAgICAgICAgdmFyIHNlbGVjdGVkU2V0Ow0KICAgICAgICAgIGlmIChtdWx0aXBsZSkgew0KICAgICAgICAgICAgaWYgKHRyYWNrRm4gJiYgaXNBcnJheSh2aWV3VmFsdWUpKSB7DQoNCiAgICAgICAgICAgICAgc2VsZWN0ZWRTZXQgPSBuZXcgSGFzaE1hcChbXSk7DQogICAgICAgICAgICAgIGZvciAodmFyIHRyYWNrSW5kZXggPSAwOyB0cmFja0luZGV4IDwgdmlld1ZhbHVlLmxlbmd0aDsgdHJhY2tJbmRleCsrKSB7DQogICAgICAgICAgICAgICAgLy8gdHJhY2tpbmcgYnkga2V5DQogICAgICAgICAgICAgICAgc2VsZWN0ZWRTZXQucHV0KGNhbGxFeHByZXNzaW9uKHRyYWNrRm4sIG51bGwsIHZpZXdWYWx1ZVt0cmFja0luZGV4XSksIHRydWUpOw0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICBzZWxlY3RlZFNldCA9IG5ldyBIYXNoTWFwKHZpZXdWYWx1ZSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgfSBlbHNlIGlmICh0cmFja0ZuKSB7DQogICAgICAgICAgICB2aWV3VmFsdWUgPSBjYWxsRXhwcmVzc2lvbih0cmFja0ZuLCBudWxsLCB2aWV3VmFsdWUpOw0KICAgICAgICAgIH0NCg0KICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBpc1NlbGVjdGVkKGtleSwgdmFsdWUpIHsNCiAgICAgICAgICAgIHZhciBjb21wYXJlVmFsdWVGbjsNCiAgICAgICAgICAgIGlmICh0cmFja0ZuKSB7DQogICAgICAgICAgICAgIGNvbXBhcmVWYWx1ZUZuID0gdHJhY2tGbjsNCiAgICAgICAgICAgIH0gZWxzZSBpZiAoc2VsZWN0QXNGbikgew0KICAgICAgICAgICAgICBjb21wYXJlVmFsdWVGbiA9IHNlbGVjdEFzRm47DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICBjb21wYXJlVmFsdWVGbiA9IHZhbHVlRm47DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmIChtdWx0aXBsZSkgew0KICAgICAgICAgICAgICByZXR1cm4gaXNEZWZpbmVkKHNlbGVjdGVkU2V0LnJlbW92ZShjYWxsRXhwcmVzc2lvbihjb21wYXJlVmFsdWVGbiwga2V5LCB2YWx1ZSkpKTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgIHJldHVybiB2aWV3VmFsdWUgPT09IGNhbGxFeHByZXNzaW9uKGNvbXBhcmVWYWx1ZUZuLCBrZXksIHZhbHVlKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9Ow0KICAgICAgICB9DQoNCiAgICAgICAgZnVuY3Rpb24gc2NoZWR1bGVSZW5kZXJpbmcoKSB7DQogICAgICAgICAgaWYgKCFyZW5kZXJTY2hlZHVsZWQpIHsNCiAgICAgICAgICAgIHNjb3BlLiQkcG9zdERpZ2VzdChyZW5kZXIpOw0KICAgICAgICAgICAgcmVuZGVyU2NoZWR1bGVkID0gdHJ1ZTsNCiAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICAvKioNCiAgICAgICAgICogQSBuZXcgbGFiZWxNYXAgaXMgY3JlYXRlZCB3aXRoIGVhY2ggcmVuZGVyLg0KICAgICAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBmb3IgZWFjaCBleGlzdGluZyBvcHRpb24gd2l0aCBhZGRlZD1mYWxzZSwNCiAgICAgICAgICogYW5kIGVhY2ggbmV3IG9wdGlvbiB3aXRoIGFkZGVkPXRydWUuDQogICAgICAgICAqIC0gTGFiZWxzIHRoYXQgYXJlIHBhc3NlZCB0byB0aGlzIG1ldGhvZCB0d2ljZSwNCiAgICAgICAgICogKG9uY2Ugd2l0aCBhZGRlZD10cnVlIGFuZCBvbmNlIHdpdGggYWRkZWQ9ZmFsc2UpIHdpbGwgZW5kIHVwIHdpdGggYSB2YWx1ZSBvZiAwLCBhbmQNCiAgICAgICAgICogd2lsbCBjYXVzZSBubyBjaGFuZ2UgdG8gaGFwcGVuIHRvIHRoZSBjb3JyZXNwb25kaW5nIG9wdGlvbi4NCiAgICAgICAgICogLSBMYWJlbHMgdGhhdCBhcmUgcGFzc2VkIHRvIHRoaXMgbWV0aG9kIG9ubHkgb25jZSB3aXRoIGFkZGVkPWZhbHNlIHdpbGwgZW5kIHVwIHdpdGggYQ0KICAgICAgICAgKiB2YWx1ZSBvZiAtMSBhbmQgd2lsbCBldmVudHVhbGx5IGJlIHBhc3NlZCB0byBzZWxlY3RDdHJsLnJlbW92ZU9wdGlvbigpDQogICAgICAgICAqIC0gTGFiZWxzIHRoYXQgYXJlIHBhc3NlZCB0byB0aGlzIG1ldGhvZCBvbmx5IG9uY2Ugd2l0aCBhZGRlZD10cnVlIHdpbGwgZW5kIHVwIHdpdGggYQ0KICAgICAgICAgKiB2YWx1ZSBvZiAxIGFuZCB3aWxsIGV2ZW50dWFsbHkgYmUgcGFzc2VkIHRvIHNlbGVjdEN0cmwuYWRkT3B0aW9uKCkNCiAgICAgICAgKi8NCiAgICAgICAgZnVuY3Rpb24gdXBkYXRlTGFiZWxNYXAobGFiZWxNYXAsIGxhYmVsLCBhZGRlZCkgew0KICAgICAgICAgIGxhYmVsTWFwW2xhYmVsXSA9IGxhYmVsTWFwW2xhYmVsXSB8fCAwOw0KICAgICAgICAgIGxhYmVsTWFwW2xhYmVsXSArPSAoYWRkZWQgPyAxIDogLTEpOw0KICAgICAgICB9DQoNCiAgICAgICAgZnVuY3Rpb24gcmVuZGVyKCkgew0KICAgICAgICAgIHJlbmRlclNjaGVkdWxlZCA9IGZhbHNlOw0KDQogICAgICAgICAgLy8gVGVtcG9yYXJ5IGxvY2F0aW9uIGZvciB0aGUgb3B0aW9uIGdyb3VwcyBiZWZvcmUgd2UgcmVuZGVyIHRoZW0NCiAgICAgICAgICB2YXIgb3B0aW9uR3JvdXBzID0geycnOltdfSwNCiAgICAgICAgICAgICAgb3B0aW9uR3JvdXBOYW1lcyA9IFsnJ10sDQogICAgICAgICAgICAgIG9wdGlvbkdyb3VwTmFtZSwNCiAgICAgICAgICAgICAgb3B0aW9uR3JvdXAsDQogICAgICAgICAgICAgIG9wdGlvbiwNCiAgICAgICAgICAgICAgZXhpc3RpbmdQYXJlbnQsIGV4aXN0aW5nT3B0aW9ucywgZXhpc3RpbmdPcHRpb24sDQogICAgICAgICAgICAgIHZpZXdWYWx1ZSA9IGN0cmwuJHZpZXdWYWx1ZSwNCiAgICAgICAgICAgICAgdmFsdWVzID0gdmFsdWVzRm4oc2NvcGUpIHx8IFtdLA0KICAgICAgICAgICAgICBrZXlzID0ga2V5TmFtZSA/IHNvcnRlZEtleXModmFsdWVzKSA6IHZhbHVlcywNCiAgICAgICAgICAgICAga2V5LA0KICAgICAgICAgICAgICB2YWx1ZSwNCiAgICAgICAgICAgICAgZ3JvdXBMZW5ndGgsIGxlbmd0aCwNCiAgICAgICAgICAgICAgZ3JvdXBJbmRleCwgaW5kZXgsDQogICAgICAgICAgICAgIGxhYmVsTWFwID0ge30sDQogICAgICAgICAgICAgIHNlbGVjdGVkLA0KICAgICAgICAgICAgICBpc1NlbGVjdGVkID0gY3JlYXRlSXNTZWxlY3RlZEZuKHZpZXdWYWx1ZSksDQogICAgICAgICAgICAgIGFueVNlbGVjdGVkID0gZmFsc2UsDQogICAgICAgICAgICAgIGxhc3RFbGVtZW50LA0KICAgICAgICAgICAgICBlbGVtZW50LA0KICAgICAgICAgICAgICBsYWJlbCwNCiAgICAgICAgICAgICAgb3B0aW9uSWQ7DQoNCiAgICAgICAgICB0cmFja0tleXNDYWNoZSA9IHt9Ow0KDQogICAgICAgICAgLy8gV2Ugbm93IGJ1aWxkIHVwIHRoZSBsaXN0IG9mIG9wdGlvbnMgd2UgbmVlZCAod2UgbWVyZ2UgbGF0ZXIpDQogICAgICAgICAgZm9yIChpbmRleCA9IDA7IGxlbmd0aCA9IGtleXMubGVuZ3RoLCBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykgew0KICAgICAgICAgICAga2V5ID0gaW5kZXg7DQogICAgICAgICAgICBpZiAoa2V5TmFtZSkgew0KICAgICAgICAgICAgICBrZXkgPSBrZXlzW2luZGV4XTsNCiAgICAgICAgICAgICAgaWYgKGtleS5jaGFyQXQoMCkgPT09ICckJykgY29udGludWU7DQogICAgICAgICAgICB9DQogICAgICAgICAgICB2YWx1ZSA9IHZhbHVlc1trZXldOw0KDQogICAgICAgICAgICBvcHRpb25Hcm91cE5hbWUgPSBjYWxsRXhwcmVzc2lvbihncm91cEJ5Rm4sIGtleSwgdmFsdWUpIHx8ICcnOw0KICAgICAgICAgICAgaWYgKCEob3B0aW9uR3JvdXAgPSBvcHRpb25Hcm91cHNbb3B0aW9uR3JvdXBOYW1lXSkpIHsNCiAgICAgICAgICAgICAgb3B0aW9uR3JvdXAgPSBvcHRpb25Hcm91cHNbb3B0aW9uR3JvdXBOYW1lXSA9IFtdOw0KICAgICAgICAgICAgICBvcHRpb25Hcm91cE5hbWVzLnB1c2gob3B0aW9uR3JvdXBOYW1lKTsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgc2VsZWN0ZWQgPSBpc1NlbGVjdGVkKGtleSwgdmFsdWUpOw0KICAgICAgICAgICAgYW55U2VsZWN0ZWQgPSBhbnlTZWxlY3RlZCB8fCBzZWxlY3RlZDsNCg0KICAgICAgICAgICAgbGFiZWwgPSBjYWxsRXhwcmVzc2lvbihkaXNwbGF5Rm4sIGtleSwgdmFsdWUpOyAvLyB3aGF0IHdpbGwgYmUgc2VlbiBieSB0aGUgdXNlcg0KDQogICAgICAgICAgICAvLyBkb2luZyBkaXNwbGF5Rm4oc2NvcGUsIGxvY2FscykgfHwgJycgb3ZlcndyaXRlcyB6ZXJvIHZhbHVlcw0KICAgICAgICAgICAgbGFiZWwgPSBpc0RlZmluZWQobGFiZWwpID8gbGFiZWwgOiAnJzsNCiAgICAgICAgICAgIG9wdGlvbklkID0gdHJhY2tGbiA/IHRyYWNrRm4oc2NvcGUsIGxvY2FscykgOiAoa2V5TmFtZSA/IGtleXNbaW5kZXhdIDogaW5kZXgpOw0KICAgICAgICAgICAgaWYgKHRyYWNrRm4pIHsNCiAgICAgICAgICAgICAgdHJhY2tLZXlzQ2FjaGVbb3B0aW9uSWRdID0ga2V5Ow0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBvcHRpb25Hcm91cC5wdXNoKHsNCiAgICAgICAgICAgICAgLy8gZWl0aGVyIHRoZSBpbmRleCBpbnRvIGFycmF5IG9yIGtleSBmcm9tIG9iamVjdA0KICAgICAgICAgICAgICBpZDogb3B0aW9uSWQsDQogICAgICAgICAgICAgIGxhYmVsOiBsYWJlbCwNCiAgICAgICAgICAgICAgc2VsZWN0ZWQ6IHNlbGVjdGVkICAgICAgICAgICAgICAgICAgIC8vIGRldGVybWluZSBpZiB3ZSBzaG91bGQgYmUgc2VsZWN0ZWQNCiAgICAgICAgICAgIH0pOw0KICAgICAgICAgIH0NCiAgICAgICAgICBpZiAoIW11bHRpcGxlKSB7DQogICAgICAgICAgICBpZiAobnVsbE9wdGlvbiB8fCB2aWV3VmFsdWUgPT09IG51bGwpIHsNCiAgICAgICAgICAgICAgLy8gaW5zZXJ0IG51bGwgb3B0aW9uIGlmIHdlIGhhdmUgYSBwbGFjZWhvbGRlciwgb3IgdGhlIG1vZGVsIGlzIG51bGwNCiAgICAgICAgICAgICAgb3B0aW9uR3JvdXBzWycnXS51bnNoaWZ0KHtpZDonJywgbGFiZWw6JycsIHNlbGVjdGVkOiFhbnlTZWxlY3RlZH0pOw0KICAgICAgICAgICAgfSBlbHNlIGlmICghYW55U2VsZWN0ZWQpIHsNCiAgICAgICAgICAgICAgLy8gb3B0aW9uIGNvdWxkIG5vdCBiZSBmb3VuZCwgd2UgaGF2ZSB0byBpbnNlcnQgdGhlIHVuZGVmaW5lZCBpdGVtDQogICAgICAgICAgICAgIG9wdGlvbkdyb3Vwc1snJ10udW5zaGlmdCh7aWQ6Jz8nLCBsYWJlbDonJywgc2VsZWN0ZWQ6dHJ1ZX0pOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0NCg0KICAgICAgICAgIC8vIE5vdyB3ZSBuZWVkIHRvIHVwZGF0ZSB0aGUgbGlzdCBvZiBET00gbm9kZXMgdG8gbWF0Y2ggdGhlIG9wdGlvbkdyb3VwcyB3ZSBjb21wdXRlZCBhYm92ZQ0KICAgICAgICAgIGZvciAoZ3JvdXBJbmRleCA9IDAsIGdyb3VwTGVuZ3RoID0gb3B0aW9uR3JvdXBOYW1lcy5sZW5ndGg7DQogICAgICAgICAgICAgICBncm91cEluZGV4IDwgZ3JvdXBMZW5ndGg7DQogICAgICAgICAgICAgICBncm91cEluZGV4KyspIHsNCiAgICAgICAgICAgIC8vIGN1cnJlbnQgb3B0aW9uIGdyb3VwIG5hbWUgb3IgJycgaWYgbm8gZ3JvdXANCiAgICAgICAgICAgIG9wdGlvbkdyb3VwTmFtZSA9IG9wdGlvbkdyb3VwTmFtZXNbZ3JvdXBJbmRleF07DQoNCiAgICAgICAgICAgIC8vIGxpc3Qgb2Ygb3B0aW9ucyBmb3IgdGhhdCBncm91cC4gKGZpcnN0IGl0ZW0gaGFzIHRoZSBwYXJlbnQpDQogICAgICAgICAgICBvcHRpb25Hcm91cCA9IG9wdGlvbkdyb3Vwc1tvcHRpb25Hcm91cE5hbWVdOw0KDQogICAgICAgICAgICBpZiAob3B0aW9uR3JvdXBzQ2FjaGUubGVuZ3RoIDw9IGdyb3VwSW5kZXgpIHsNCiAgICAgICAgICAgICAgLy8gd2UgbmVlZCB0byBncm93IHRoZSBvcHRpb25Hcm91cHMNCiAgICAgICAgICAgICAgZXhpc3RpbmdQYXJlbnQgPSB7DQogICAgICAgICAgICAgICAgZWxlbWVudDogb3B0R3JvdXBUZW1wbGF0ZS5jbG9uZSgpLmF0dHIoJ2xhYmVsJywgb3B0aW9uR3JvdXBOYW1lKSwNCiAgICAgICAgICAgICAgICBsYWJlbDogb3B0aW9uR3JvdXAubGFiZWwNCiAgICAgICAgICAgICAgfTsNCiAgICAgICAgICAgICAgZXhpc3RpbmdPcHRpb25zID0gW2V4aXN0aW5nUGFyZW50XTsNCiAgICAgICAgICAgICAgb3B0aW9uR3JvdXBzQ2FjaGUucHVzaChleGlzdGluZ09wdGlvbnMpOw0KICAgICAgICAgICAgICBzZWxlY3RFbGVtZW50LmFwcGVuZChleGlzdGluZ1BhcmVudC5lbGVtZW50KTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgIGV4aXN0aW5nT3B0aW9ucyA9IG9wdGlvbkdyb3Vwc0NhY2hlW2dyb3VwSW5kZXhdOw0KICAgICAgICAgICAgICBleGlzdGluZ1BhcmVudCA9IGV4aXN0aW5nT3B0aW9uc1swXTsgIC8vIGVpdGhlciBTRUxFQ1QgKG5vIGdyb3VwKSBvciBPUFRHUk9VUCBlbGVtZW50DQoNCiAgICAgICAgICAgICAgLy8gdXBkYXRlIHRoZSBPUFRHUk9VUCBsYWJlbCBpZiBub3QgdGhlIHNhbWUuDQogICAgICAgICAgICAgIGlmIChleGlzdGluZ1BhcmVudC5sYWJlbCAhPSBvcHRpb25Hcm91cE5hbWUpIHsNCiAgICAgICAgICAgICAgICBleGlzdGluZ1BhcmVudC5lbGVtZW50LmF0dHIoJ2xhYmVsJywgZXhpc3RpbmdQYXJlbnQubGFiZWwgPSBvcHRpb25Hcm91cE5hbWUpOw0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGxhc3RFbGVtZW50ID0gbnVsbDsgIC8vIHN0YXJ0IGF0IHRoZSBiZWdpbm5pbmcNCiAgICAgICAgICAgIGZvciAoaW5kZXggPSAwLCBsZW5ndGggPSBvcHRpb25Hcm91cC5sZW5ndGg7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7DQogICAgICAgICAgICAgIG9wdGlvbiA9IG9wdGlvbkdyb3VwW2luZGV4XTsNCiAgICAgICAgICAgICAgaWYgKChleGlzdGluZ09wdGlvbiA9IGV4aXN0aW5nT3B0aW9uc1tpbmRleCArIDFdKSkgew0KICAgICAgICAgICAgICAgIC8vIHJldXNlIGVsZW1lbnRzDQogICAgICAgICAgICAgICAgbGFzdEVsZW1lbnQgPSBleGlzdGluZ09wdGlvbi5lbGVtZW50Ow0KICAgICAgICAgICAgICAgIGlmIChleGlzdGluZ09wdGlvbi5sYWJlbCAhPT0gb3B0aW9uLmxhYmVsKSB7DQogICAgICAgICAgICAgICAgICB1cGRhdGVMYWJlbE1hcChsYWJlbE1hcCwgZXhpc3RpbmdPcHRpb24ubGFiZWwsIGZhbHNlKTsNCiAgICAgICAgICAgICAgICAgIHVwZGF0ZUxhYmVsTWFwKGxhYmVsTWFwLCBvcHRpb24ubGFiZWwsIHRydWUpOw0KICAgICAgICAgICAgICAgICAgbGFzdEVsZW1lbnQudGV4dChleGlzdGluZ09wdGlvbi5sYWJlbCA9IG9wdGlvbi5sYWJlbCk7DQogICAgICAgICAgICAgICAgICBsYXN0RWxlbWVudC5wcm9wKCdsYWJlbCcsIGV4aXN0aW5nT3B0aW9uLmxhYmVsKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgaWYgKGV4aXN0aW5nT3B0aW9uLmlkICE9PSBvcHRpb24uaWQpIHsNCiAgICAgICAgICAgICAgICAgIGxhc3RFbGVtZW50LnZhbChleGlzdGluZ09wdGlvbi5pZCA9IG9wdGlvbi5pZCk7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIC8vIGxhc3RFbGVtZW50LnByb3AoJ3NlbGVjdGVkJykgcHJvdmlkZWQgYnkgalF1ZXJ5IGhhcyBzaWRlLWVmZmVjdHMNCiAgICAgICAgICAgICAgICBpZiAobGFzdEVsZW1lbnRbMF0uc2VsZWN0ZWQgIT09IG9wdGlvbi5zZWxlY3RlZCkgew0KICAgICAgICAgICAgICAgICAgbGFzdEVsZW1lbnQucHJvcCgnc2VsZWN0ZWQnLCAoZXhpc3RpbmdPcHRpb24uc2VsZWN0ZWQgPSBvcHRpb24uc2VsZWN0ZWQpKTsNCiAgICAgICAgICAgICAgICAgIGlmIChtc2llKSB7DQogICAgICAgICAgICAgICAgICAgIC8vIFNlZSAjNzY5Mg0KICAgICAgICAgICAgICAgICAgICAvLyBUaGUgc2VsZWN0ZWQgaXRlbSB3b3VsZG4ndCB2aXN1YWxseSB1cGRhdGUgb24gSUUgd2l0aG91dCB0aGlzLg0KICAgICAgICAgICAgICAgICAgICAvLyBUZXN0ZWQgb24gV2luNzogSUU5LCBJRTEwIGFuZCBJRTExLiBGdXR1cmUgSUVzIHNob3VsZCBiZSB0ZXN0ZWQgYXMgd2VsbA0KICAgICAgICAgICAgICAgICAgICBsYXN0RWxlbWVudC5wcm9wKCdzZWxlY3RlZCcsIGV4aXN0aW5nT3B0aW9uLnNlbGVjdGVkKTsNCiAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgLy8gZ3JvdyBlbGVtZW50cw0KDQogICAgICAgICAgICAgICAgLy8gaWYgaXQncyBhIG51bGwgb3B0aW9uDQogICAgICAgICAgICAgICAgaWYgKG9wdGlvbi5pZCA9PT0gJycgJiYgbnVsbE9wdGlvbikgew0KICAgICAgICAgICAgICAgICAgLy8gcHV0IGJhY2sgdGhlIHByZS1jb21waWxlZCBlbGVtZW50DQogICAgICAgICAgICAgICAgICBlbGVtZW50ID0gbnVsbE9wdGlvbjsNCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgLy8galF1ZXJ5KHYxLjQuMikgQnVnOiBXZSBzaG91bGQgYmUgYWJsZSB0byBjaGFpbiB0aGUgbWV0aG9kIGNhbGxzLCBidXQNCiAgICAgICAgICAgICAgICAgIC8vIGluIHRoaXMgdmVyc2lvbiBvZiBqUXVlcnkgb24gc29tZSBicm93c2VyIHRoZSAudGV4dCgpIHJldHVybnMgYSBzdHJpbmcNCiAgICAgICAgICAgICAgICAgIC8vIHJhdGhlciB0aGVuIHRoZSBlbGVtZW50Lg0KICAgICAgICAgICAgICAgICAgKGVsZW1lbnQgPSBvcHRpb25UZW1wbGF0ZS5jbG9uZSgpKQ0KICAgICAgICAgICAgICAgICAgICAgIC52YWwob3B0aW9uLmlkKQ0KICAgICAgICAgICAgICAgICAgICAgIC5wcm9wKCdzZWxlY3RlZCcsIG9wdGlvbi5zZWxlY3RlZCkNCiAgICAgICAgICAgICAgICAgICAgICAuYXR0cignc2VsZWN0ZWQnLCBvcHRpb24uc2VsZWN0ZWQpDQogICAgICAgICAgICAgICAgICAgICAgLnByb3AoJ2xhYmVsJywgb3B0aW9uLmxhYmVsKQ0KICAgICAgICAgICAgICAgICAgICAgIC50ZXh0KG9wdGlvbi5sYWJlbCk7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgZXhpc3RpbmdPcHRpb25zLnB1c2goZXhpc3RpbmdPcHRpb24gPSB7DQogICAgICAgICAgICAgICAgICAgIGVsZW1lbnQ6IGVsZW1lbnQsDQogICAgICAgICAgICAgICAgICAgIGxhYmVsOiBvcHRpb24ubGFiZWwsDQogICAgICAgICAgICAgICAgICAgIGlkOiBvcHRpb24uaWQsDQogICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkOiBvcHRpb24uc2VsZWN0ZWQNCiAgICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICAgICAgICB1cGRhdGVMYWJlbE1hcChsYWJlbE1hcCwgb3B0aW9uLmxhYmVsLCB0cnVlKTsNCiAgICAgICAgICAgICAgICBpZiAobGFzdEVsZW1lbnQpIHsNCiAgICAgICAgICAgICAgICAgIGxhc3RFbGVtZW50LmFmdGVyKGVsZW1lbnQpOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICBleGlzdGluZ1BhcmVudC5lbGVtZW50LmFwcGVuZChlbGVtZW50KTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgbGFzdEVsZW1lbnQgPSBlbGVtZW50Ow0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgICAvLyByZW1vdmUgYW55IGV4Y2Vzc2l2ZSBPUFRJT05zIGluIGEgZ3JvdXANCiAgICAgICAgICAgIGluZGV4Kys7IC8vIGluY3JlbWVudCBzaW5jZSB0aGUgZXhpc3RpbmdPcHRpb25zWzBdIGlzIHBhcmVudCBlbGVtZW50IG5vdCBPUFRJT04NCiAgICAgICAgICAgIHdoaWxlIChleGlzdGluZ09wdGlvbnMubGVuZ3RoID4gaW5kZXgpIHsNCiAgICAgICAgICAgICAgb3B0aW9uID0gZXhpc3RpbmdPcHRpb25zLnBvcCgpOw0KICAgICAgICAgICAgICB1cGRhdGVMYWJlbE1hcChsYWJlbE1hcCwgb3B0aW9uLmxhYmVsLCBmYWxzZSk7DQogICAgICAgICAgICAgIG9wdGlvbi5lbGVtZW50LnJlbW92ZSgpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0NCiAgICAgICAgICAvLyByZW1vdmUgYW55IGV4Y2Vzc2l2ZSBPUFRHUk9VUHMgZnJvbSBzZWxlY3QNCiAgICAgICAgICB3aGlsZSAob3B0aW9uR3JvdXBzQ2FjaGUubGVuZ3RoID4gZ3JvdXBJbmRleCkgew0KICAgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB0aGUgbGFiZWxzIGluIHRoZSBvcHRpb24gZ3JvdXANCiAgICAgICAgICAgIG9wdGlvbkdyb3VwID0gb3B0aW9uR3JvdXBzQ2FjaGUucG9wKCk7DQogICAgICAgICAgICBmb3IgKGluZGV4ID0gMTsgaW5kZXggPCBvcHRpb25Hcm91cC5sZW5ndGg7ICsraW5kZXgpIHsNCiAgICAgICAgICAgICAgdXBkYXRlTGFiZWxNYXAobGFiZWxNYXAsIG9wdGlvbkdyb3VwW2luZGV4XS5sYWJlbCwgZmFsc2UpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgb3B0aW9uR3JvdXBbMF0uZWxlbWVudC5yZW1vdmUoKTsNCiAgICAgICAgICB9DQogICAgICAgICAgZm9yRWFjaChsYWJlbE1hcCwgZnVuY3Rpb24oY291bnQsIGxhYmVsKSB7DQogICAgICAgICAgICBpZiAoY291bnQgPiAwKSB7DQogICAgICAgICAgICAgIHNlbGVjdEN0cmwuYWRkT3B0aW9uKGxhYmVsKTsNCiAgICAgICAgICAgIH0gZWxzZSBpZiAoY291bnQgPCAwKSB7DQogICAgICAgICAgICAgIHNlbGVjdEN0cmwucmVtb3ZlT3B0aW9uKGxhYmVsKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9KTsNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgIH0NCiAgfTsNCn1dOw0KDQp2YXIgb3B0aW9uRGlyZWN0aXZlID0gWyckaW50ZXJwb2xhdGUnLCBmdW5jdGlvbigkaW50ZXJwb2xhdGUpIHsNCiAgdmFyIG51bGxTZWxlY3RDdHJsID0gew0KICAgIGFkZE9wdGlvbjogbm9vcCwNCiAgICByZW1vdmVPcHRpb246IG5vb3ANCiAgfTsNCg0KICByZXR1cm4gew0KICAgIHJlc3RyaWN0OiAnRScsDQogICAgcHJpb3JpdHk6IDEwMCwNCiAgICBjb21waWxlOiBmdW5jdGlvbihlbGVtZW50LCBhdHRyKSB7DQogICAgICBpZiAoaXNVbmRlZmluZWQoYXR0ci52YWx1ZSkpIHsNCiAgICAgICAgdmFyIGludGVycG9sYXRlRm4gPSAkaW50ZXJwb2xhdGUoZWxlbWVudC50ZXh0KCksIHRydWUpOw0KICAgICAgICBpZiAoIWludGVycG9sYXRlRm4pIHsNCiAgICAgICAgICBhdHRyLiRzZXQoJ3ZhbHVlJywgZWxlbWVudC50ZXh0KCkpOw0KICAgICAgICB9DQogICAgICB9DQoNCiAgICAgIHJldHVybiBmdW5jdGlvbihzY29wZSwgZWxlbWVudCwgYXR0cikgew0KICAgICAgICB2YXIgc2VsZWN0Q3RybE5hbWUgPSAnJHNlbGVjdENvbnRyb2xsZXInLA0KICAgICAgICAgICAgcGFyZW50ID0gZWxlbWVudC5wYXJlbnQoKSwNCiAgICAgICAgICAgIHNlbGVjdEN0cmwgPSBwYXJlbnQuZGF0YShzZWxlY3RDdHJsTmFtZSkgfHwNCiAgICAgICAgICAgICAgcGFyZW50LnBhcmVudCgpLmRhdGEoc2VsZWN0Q3RybE5hbWUpOyAvLyBpbiBjYXNlIHdlIGFyZSBpbiBvcHRncm91cA0KDQogICAgICAgIGlmICghc2VsZWN0Q3RybCB8fCAhc2VsZWN0Q3RybC5kYXRhYm91bmQpIHsNCiAgICAgICAgICBzZWxlY3RDdHJsID0gbnVsbFNlbGVjdEN0cmw7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoaW50ZXJwb2xhdGVGbikgew0KICAgICAgICAgIHNjb3BlLiR3YXRjaChpbnRlcnBvbGF0ZUZuLCBmdW5jdGlvbiBpbnRlcnBvbGF0ZVdhdGNoQWN0aW9uKG5ld1ZhbCwgb2xkVmFsKSB7DQogICAgICAgICAgICBhdHRyLiRzZXQoJ3ZhbHVlJywgbmV3VmFsKTsNCiAgICAgICAgICAgIGlmIChvbGRWYWwgIT09IG5ld1ZhbCkgew0KICAgICAgICAgICAgICBzZWxlY3RDdHJsLnJlbW92ZU9wdGlvbihvbGRWYWwpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgc2VsZWN0Q3RybC5hZGRPcHRpb24obmV3VmFsLCBlbGVtZW50KTsNCiAgICAgICAgICB9KTsNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBzZWxlY3RDdHJsLmFkZE9wdGlvbihhdHRyLnZhbHVlLCBlbGVtZW50KTsNCiAgICAgICAgfQ0KDQogICAgICAgIGVsZW1lbnQub24oJyRkZXN0cm95JywgZnVuY3Rpb24oKSB7DQogICAgICAgICAgc2VsZWN0Q3RybC5yZW1vdmVPcHRpb24oYXR0ci52YWx1ZSk7DQogICAgICAgIH0pOw0KICAgICAgfTsNCiAgICB9DQogIH07DQp9XTsNCg0KdmFyIHN0eWxlRGlyZWN0aXZlID0gdmFsdWVGbih7DQogIHJlc3RyaWN0OiAnRScsDQogIHRlcm1pbmFsOiBmYWxzZQ0KfSk7DQoNCiAgaWYgKHdpbmRvdy5hbmd1bGFyLmJvb3RzdHJhcCkgew0KICAgIC8vQW5ndWxhckpTIGlzIGFscmVhZHkgbG9hZGVkLCBzbyB3ZSBjYW4gcmV0dXJuIGhlcmUuLi4NCiAgICBjb25zb2xlLmxvZygnV0FSTklORzogVHJpZWQgdG8gbG9hZCBhbmd1bGFyIG1vcmUgdGhhbiBvbmNlLicpOw0KICAgIHJldHVybjsNCiAgfQ0KDQogIC8vdHJ5IHRvIGJpbmQgdG8ganF1ZXJ5IG5vdyBzbyB0aGF0IG9uZSBjYW4gd3JpdGUganFMaXRlKGRvY3VtZW50KS5yZWFkeSgpDQogIC8vYnV0IHdlIHdpbGwgcmViaW5kIG9uIGJvb3RzdHJhcCBhZ2Fpbi4NCiAgYmluZEpRdWVyeSgpOw0KDQogIHB1Ymxpc2hFeHRlcm5hbEFQSShhbmd1bGFyKTsNCg0KICBqcUxpdGUoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkgew0KICAgIGFuZ3VsYXJJbml0KGRvY3VtZW50LCBib290c3RyYXApOw0KICB9KTsNCg0KfSkod2luZG93LCBkb2N1bWVudCk7DQoNCiF3aW5kb3cuYW5ndWxhci4kJGNzcCgpICYmIHdpbmRvdy5hbmd1bGFyLmVsZW1lbnQoZG9jdW1lbnQpLmZpbmQoJ2hlYWQnKS5wcmVwZW5kKCc8c3R5bGUgdHlwZT0idGV4dC9jc3MiPkBjaGFyc2V0ICJVVEYtOCI7W25nXFw6Y2xvYWtdLFtuZy1jbG9ha10sW2RhdGEtbmctY2xvYWtdLFt4LW5nLWNsb2FrXSwubmctY2xvYWssLngtbmctY2xvYWssLm5nLWhpZGU6bm90KC5uZy1oaWRlLWFuaW1hdGUpe2Rpc3BsYXk6bm9uZSAhaW1wb3J0YW50O31uZ1xcOmZvcm17ZGlzcGxheTpibG9jazt9PC9zdHlsZT4nKTsNCg==