LyoNCiAgR29vZ2xlIEhUTUw1IHNsaWRlcyB0ZW1wbGF0ZQ0KDQogIEF1dGhvcnM6IEx1a2UgTWFo6SAoY29kZSkNCiAgICAgICAgICAgTWFyY2luIFdpY2hhcnkgKGNvZGUgYW5kIGRlc2lnbikNCg0KICAgICAgICAgICBEb21pbmljIE1henpvbmkgKGJyb3dzZXIgY29tcGF0aWJpbGl0eSkNCiAgICAgICAgICAgQ2hhcmxlcyBDaGVuIChDaHJvbWVWb3ggc3VwcG9ydCkNCiAgICAgICAgICAgSm9obiBBcnRob3JuZSAoRWNsaXBzZSB0ZW1wbGF0ZSkNCg0KICBVUkw6IGh0dHA6Ly9jb2RlLmdvb2dsZS5jb20vcC9odG1sNXNsaWRlcy8NCiovDQoNCnZhciBQRVJNQU5FTlRfVVJMX1BSRUZJWCA9ICdodHRwOi8vZWNsaXBzZS5vcmcvZWNsaXBzZS9wcmVzZW50YXRpb24vaHRtbC8nOw0KDQp2YXIgU0xJREVfQ0xBU1NFUyA9IFsnZmFyLXBhc3QnLCAncGFzdCcsICdjdXJyZW50JywgJ25leHQnLCAnZmFyLW5leHQnXTsNCg0KdmFyIFBNX1RPVUNIX1NFTlNJVElWSVRZID0gMTU7DQoNCnZhciBjdXJTbGlkZTsNCg0KLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLw0KLyogY2xhc3NMaXN0IHBvbHlmaWxsIGJ5IEVsaSBHcmV5IA0KICogKGh0dHA6Ly9wdXJsLmVsaWdyZXkuY29tL2dpdGh1Yi9jbGFzc0xpc3QuanMvYmxvYi9tYXN0ZXIvY2xhc3NMaXN0LmpzKSAqLw0KDQppZiAodHlwZW9mIGRvY3VtZW50ICE9PSAidW5kZWZpbmVkIiAmJiAhKCJjbGFzc0xpc3QiIGluIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImEiKSkpIHsNCg0KKGZ1bmN0aW9uICh2aWV3KSB7DQoNCnZhcg0KICAgIGNsYXNzTGlzdFByb3AgPSAiY2xhc3NMaXN0Ig0KICAsIHByb3RvUHJvcCA9ICJwcm90b3R5cGUiDQogICwgZWxlbUN0clByb3RvID0gKHZpZXcuSFRNTEVsZW1lbnQgfHwgdmlldy5FbGVtZW50KVtwcm90b1Byb3BdDQogICwgb2JqQ3RyID0gT2JqZWN0DQogICAgc3RyVHJpbSA9IFN0cmluZ1twcm90b1Byb3BdLnRyaW0gfHwgZnVuY3Rpb24gKCkgew0KICAgIHJldHVybiB0aGlzLnJlcGxhY2UoL15ccyt8XHMrJC9nLCAiIik7DQogIH0NCiAgLCBhcnJJbmRleE9mID0gQXJyYXlbcHJvdG9Qcm9wXS5pbmRleE9mIHx8IGZ1bmN0aW9uIChpdGVtKSB7DQogICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IHRoaXMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHsNCiAgICAgIGlmIChpIGluIHRoaXMgJiYgdGhpc1tpXSA9PT0gaXRlbSkgew0KICAgICAgICByZXR1cm4gaTsNCiAgICAgIH0NCiAgICB9DQogICAgcmV0dXJuIC0xOw0KICB9DQogIC8vIFZlbmRvcnM6IHBsZWFzZSBhbGxvdyBjb250ZW50IGNvZGUgdG8gaW5zdGFudGlhdGUgRE9NRXhjZXB0aW9ucw0KICAsIERPTUV4ID0gZnVuY3Rpb24gKHR5cGUsIG1lc3NhZ2UpIHsNCiAgICB0aGlzLm5hbWUgPSB0eXBlOw0KICAgIHRoaXMuY29kZSA9IERPTUV4Y2VwdGlvblt0eXBlXTsNCiAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlOw0KICB9DQogICwgY2hlY2tUb2tlbkFuZEdldEluZGV4ID0gZnVuY3Rpb24gKGNsYXNzTGlzdCwgdG9rZW4pIHsNCiAgICBpZiAodG9rZW4gPT09ICIiKSB7DQogICAgICB0aHJvdyBuZXcgRE9NRXgoDQogICAgICAgICAgIlNZTlRBWF9FUlIiDQogICAgICAgICwgIkFuIGludmFsaWQgb3IgaWxsZWdhbCBzdHJpbmcgd2FzIHNwZWNpZmllZCINCiAgICAgICk7DQogICAgfQ0KICAgIGlmICgvXHMvLnRlc3QodG9rZW4pKSB7DQogICAgICB0aHJvdyBuZXcgRE9NRXgoDQogICAgICAgICAgIklOVkFMSURfQ0hBUkFDVEVSX0VSUiINCiAgICAgICAgLCAiU3RyaW5nIGNvbnRhaW5zIGFuIGludmFsaWQgY2hhcmFjdGVyIg0KICAgICAgKTsNCiAgICB9DQogICAgcmV0dXJuIGFyckluZGV4T2YuY2FsbChjbGFzc0xpc3QsIHRva2VuKTsNCiAgfQ0KICAsIENsYXNzTGlzdCA9IGZ1bmN0aW9uIChlbGVtKSB7DQogICAgdmFyDQogICAgICAgIHRyaW1tZWRDbGFzc2VzID0gc3RyVHJpbS5jYWxsKGVsZW0uY2xhc3NOYW1lKQ0KICAgICAgLCBjbGFzc2VzID0gdHJpbW1lZENsYXNzZXMgPyB0cmltbWVkQ2xhc3Nlcy5zcGxpdCgvXHMrLykgOiBbXQ0KICAgIDsNCiAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gY2xhc3Nlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykgew0KICAgICAgdGhpcy5wdXNoKGNsYXNzZXNbaV0pOw0KICAgIH0NCiAgICB0aGlzLl91cGRhdGVDbGFzc05hbWUgPSBmdW5jdGlvbiAoKSB7DQogICAgICBlbGVtLmNsYXNzTmFtZSA9IHRoaXMudG9TdHJpbmcoKTsNCiAgICB9Ow0KICB9DQogICwgY2xhc3NMaXN0UHJvdG8gPSBDbGFzc0xpc3RbcHJvdG9Qcm9wXSA9IFtdDQogICwgY2xhc3NMaXN0R2V0dGVyID0gZnVuY3Rpb24gKCkgew0KICAgIHJldHVybiBuZXcgQ2xhc3NMaXN0KHRoaXMpOw0KICB9DQo7DQovLyBNb3N0IERPTUV4Y2VwdGlvbiBpbXBsZW1lbnRhdGlvbnMgZG9uJ3QgYWxsb3cgY2FsbGluZyBET01FeGNlcHRpb24ncyB0b1N0cmluZygpDQovLyBvbiBub24tRE9NRXhjZXB0aW9ucy4gRXJyb3IncyB0b1N0cmluZygpIGlzIHN1ZmZpY2llbnQgaGVyZS4NCkRPTUV4W3Byb3RvUHJvcF0gPSBFcnJvcltwcm90b1Byb3BdOw0KY2xhc3NMaXN0UHJvdG8uaXRlbSA9IGZ1bmN0aW9uIChpKSB7DQogIHJldHVybiB0aGlzW2ldIHx8IG51bGw7DQp9Ow0KY2xhc3NMaXN0UHJvdG8uY29udGFpbnMgPSBmdW5jdGlvbiAodG9rZW4pIHsNCiAgdG9rZW4gKz0gIiI7DQogIHJldHVybiBjaGVja1Rva2VuQW5kR2V0SW5kZXgodGhpcywgdG9rZW4pICE9PSAtMTsNCn07DQpjbGFzc0xpc3RQcm90by5hZGQgPSBmdW5jdGlvbiAodG9rZW4pIHsNCiAgdG9rZW4gKz0gIiI7DQogIGlmIChjaGVja1Rva2VuQW5kR2V0SW5kZXgodGhpcywgdG9rZW4pID09PSAtMSkgew0KICAgIHRoaXMucHVzaCh0b2tlbik7DQogICAgdGhpcy5fdXBkYXRlQ2xhc3NOYW1lKCk7DQogIH0NCn07DQpjbGFzc0xpc3RQcm90by5yZW1vdmUgPSBmdW5jdGlvbiAodG9rZW4pIHsNCiAgdG9rZW4gKz0gIiI7DQogIHZhciBpbmRleCA9IGNoZWNrVG9rZW5BbmRHZXRJbmRleCh0aGlzLCB0b2tlbik7DQogIGlmIChpbmRleCAhPT0gLTEpIHsNCiAgICB0aGlzLnNwbGljZShpbmRleCwgMSk7DQogICAgdGhpcy5fdXBkYXRlQ2xhc3NOYW1lKCk7DQogIH0NCn07DQpjbGFzc0xpc3RQcm90by50b2dnbGUgPSBmdW5jdGlvbiAodG9rZW4pIHsNCiAgdG9rZW4gKz0gIiI7DQogIGlmIChjaGVja1Rva2VuQW5kR2V0SW5kZXgodGhpcywgdG9rZW4pID09PSAtMSkgew0KICAgIHRoaXMuYWRkKHRva2VuKTsNCiAgfSBlbHNlIHsNCiAgICB0aGlzLnJlbW92ZSh0b2tlbik7DQogIH0NCn07DQpjbGFzc0xpc3RQcm90by50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHsNCiAgcmV0dXJuIHRoaXMuam9pbigiICIpOw0KfTsNCg0KaWYgKG9iakN0ci5kZWZpbmVQcm9wZXJ0eSkgew0KICB2YXIgY2xhc3NMaXN0UHJvcERlc2MgPSB7DQogICAgICBnZXQ6IGNsYXNzTGlzdEdldHRlcg0KICAgICwgZW51bWVyYWJsZTogdHJ1ZQ0KICAgICwgY29uZmlndXJhYmxlOiB0cnVlDQogIH07DQogIHRyeSB7DQogICAgb2JqQ3RyLmRlZmluZVByb3BlcnR5KGVsZW1DdHJQcm90bywgY2xhc3NMaXN0UHJvcCwgY2xhc3NMaXN0UHJvcERlc2MpOw0KICB9IGNhdGNoIChleCkgeyAvLyBJRSA4IGRvZXNuJ3Qgc3VwcG9ydCBlbnVtZXJhYmxlOnRydWUNCiAgICBpZiAoZXgubnVtYmVyID09PSAtMHg3RkY1RUM1NCkgew0KICAgICAgY2xhc3NMaXN0UHJvcERlc2MuZW51bWVyYWJsZSA9IGZhbHNlOw0KICAgICAgb2JqQ3RyLmRlZmluZVByb3BlcnR5KGVsZW1DdHJQcm90bywgY2xhc3NMaXN0UHJvcCwgY2xhc3NMaXN0UHJvcERlc2MpOw0KICAgIH0NCiAgfQ0KfSBlbHNlIGlmIChvYmpDdHJbcHJvdG9Qcm9wXS5fX2RlZmluZUdldHRlcl9fKSB7DQogIGVsZW1DdHJQcm90by5fX2RlZmluZUdldHRlcl9fKGNsYXNzTGlzdFByb3AsIGNsYXNzTGlzdEdldHRlcik7DQp9DQoNCn0oc2VsZikpOw0KDQp9DQovKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovDQoNCi8qIFNsaWRlIG1vdmVtZW50ICovDQoNCmZ1bmN0aW9uIGdldFNsaWRlRWwobm8pIHsNCiAgaWYgKChubyA8IDApIHx8IChubyA+PSBzbGlkZUVscy5sZW5ndGgpKSB7IA0KICAgIHJldHVybiBudWxsOw0KICB9IGVsc2Ugew0KICAgIHJldHVybiBzbGlkZUVsc1tub107DQogIH0NCn07DQoNCmZ1bmN0aW9uIHVwZGF0ZVNsaWRlQ2xhc3Moc2xpZGVObywgY2xhc3NOYW1lKSB7DQogIHZhciBlbCA9IGdldFNsaWRlRWwoc2xpZGVObyk7DQogIA0KICBpZiAoIWVsKSB7DQogICAgcmV0dXJuOw0KICB9DQogIA0KICBpZiAoY2xhc3NOYW1lKSB7DQogICAgZWwuY2xhc3NMaXN0LmFkZChjbGFzc05hbWUpOw0KICB9DQogICAgDQogIGZvciAodmFyIGkgaW4gU0xJREVfQ0xBU1NFUykgew0KICAgIGlmIChjbGFzc05hbWUgIT0gU0xJREVfQ0xBU1NFU1tpXSkgew0KICAgICAgZWwuY2xhc3NMaXN0LnJlbW92ZShTTElERV9DTEFTU0VTW2ldKTsNCiAgICB9DQogIH0NCn07DQoNCmZ1bmN0aW9uIHVwZGF0ZVNsaWRlcygpIHsNCiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzbGlkZUVscy5sZW5ndGg7IGkrKykgew0KICAgIHN3aXRjaCAoaSkgew0KICAgICAgY2FzZSBjdXJTbGlkZSAtIDI6DQogICAgICAgIHVwZGF0ZVNsaWRlQ2xhc3MoaSwgJ2Zhci1wYXN0Jyk7DQogICAgICAgIGJyZWFrOw0KICAgICAgY2FzZSBjdXJTbGlkZSAtIDE6DQogICAgICAgIHVwZGF0ZVNsaWRlQ2xhc3MoaSwgJ3Bhc3QnKTsNCiAgICAgICAgYnJlYWs7DQogICAgICBjYXNlIGN1clNsaWRlOiANCiAgICAgICAgdXBkYXRlU2xpZGVDbGFzcyhpLCAnY3VycmVudCcpOw0KICAgICAgICBicmVhazsNCiAgICAgIGNhc2UgY3VyU2xpZGUgKyAxOg0KICAgICAgICB1cGRhdGVTbGlkZUNsYXNzKGksICduZXh0Jyk7ICAgICAgDQogICAgICAgIGJyZWFrOw0KICAgICAgY2FzZSBjdXJTbGlkZSArIDI6DQogICAgICAgIHVwZGF0ZVNsaWRlQ2xhc3MoaSwgJ2Zhci1uZXh0Jyk7ICAgICAgDQogICAgICAgIGJyZWFrOw0KICAgICAgZGVmYXVsdDoNCiAgICAgICAgdXBkYXRlU2xpZGVDbGFzcyhpKTsNCiAgICAgICAgYnJlYWs7DQogICAgfQ0KICB9DQoNCiAgdHJpZ2dlckxlYXZlRXZlbnQoY3VyU2xpZGUgLSAxKTsNCiAgdHJpZ2dlckVudGVyRXZlbnQoY3VyU2xpZGUpOw0KDQogIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCkgew0KICAgIC8vIEhpZGUgYWZ0ZXIgdGhlIHNsaWRlDQogICAgZGlzYWJsZVNsaWRlRnJhbWVzKGN1clNsaWRlIC0gMik7DQogIH0sIDMwMSk7DQoNCiAgZW5hYmxlU2xpZGVGcmFtZXMoY3VyU2xpZGUgLSAxKTsNCiAgZW5hYmxlU2xpZGVGcmFtZXMoY3VyU2xpZGUgKyAyKTsNCiAgDQogIGlmIChpc0Nocm9tZVZveEFjdGl2ZSgpKSB7DQogICAgc3BlYWtBbmRTeW5jVG9Ob2RlKHNsaWRlRWxzW2N1clNsaWRlXSk7DQogIH0gIA0KDQogIHVwZGF0ZUhhc2goKTsNCn07DQoNCmZ1bmN0aW9uIGJ1aWxkTmV4dEl0ZW0oKSB7DQogIHZhciB0b0J1aWxkICA9IHNsaWRlRWxzW2N1clNsaWRlXS5xdWVyeVNlbGVjdG9yQWxsKCcudG8tYnVpbGQnKTsNCg0KICBpZiAoIXRvQnVpbGQubGVuZ3RoKSB7DQogICAgcmV0dXJuIGZhbHNlOw0KICB9DQoNCiAgdG9CdWlsZFswXS5jbGFzc0xpc3QucmVtb3ZlKCd0by1idWlsZCcsICcnKTsNCg0KICBpZiAoaXNDaHJvbWVWb3hBY3RpdmUoKSkgew0KICAgIHNwZWFrQW5kU3luY1RvTm9kZSh0b0J1aWxkWzBdKTsNCiAgfQ0KDQogIHJldHVybiB0cnVlOw0KfTsNCg0KZnVuY3Rpb24gcHJldlNsaWRlKCkgew0KICBpZiAoY3VyU2xpZGUgPiAwKSB7DQogICAgY3VyU2xpZGUtLTsNCg0KICAgIHVwZGF0ZVNsaWRlcygpOw0KICB9DQp9Ow0KDQpmdW5jdGlvbiBuZXh0U2xpZGUoKSB7DQogIGlmIChidWlsZE5leHRJdGVtKCkpIHsNCiAgICByZXR1cm47DQogIH0NCg0KICBpZiAoY3VyU2xpZGUgPCBzbGlkZUVscy5sZW5ndGggLSAxKSB7DQogICAgY3VyU2xpZGUrKzsNCg0KICAgIHVwZGF0ZVNsaWRlcygpOw0KICB9DQp9Ow0KDQovKiBTbGlkZSBldmVudHMgKi8NCg0KZnVuY3Rpb24gdHJpZ2dlckVudGVyRXZlbnQobm8pIHsNCiAgdmFyIGVsID0gZ2V0U2xpZGVFbChubyk7DQogIGlmICghZWwpIHsNCiAgICByZXR1cm47DQogIH0NCg0KICB2YXIgb25FbnRlciA9IGVsLmdldEF0dHJpYnV0ZSgnb25zbGlkZWVudGVyJyk7DQogIGlmIChvbkVudGVyKSB7DQogICAgbmV3IEZ1bmN0aW9uKG9uRW50ZXIpLmNhbGwoZWwpOw0KICB9DQoNCiAgdmFyIGV2dCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdFdmVudCcpOw0KICBldnQuaW5pdEV2ZW50KCdzbGlkZWVudGVyJywgdHJ1ZSwgdHJ1ZSk7DQogIGV2dC5zbGlkZU51bWJlciA9IG5vICsgMTsgLy8gTWFrZSBpdCByZWFkYWJsZQ0KDQogIGVsLmRpc3BhdGNoRXZlbnQoZXZ0KTsNCn07DQoNCmZ1bmN0aW9uIHRyaWdnZXJMZWF2ZUV2ZW50KG5vKSB7DQogIHZhciBlbCA9IGdldFNsaWRlRWwobm8pOw0KICBpZiAoIWVsKSB7DQogICAgcmV0dXJuOw0KICB9DQoNCiAgdmFyIG9uTGVhdmUgPSBlbC5nZXRBdHRyaWJ1dGUoJ29uc2xpZGVsZWF2ZScpOw0KICBpZiAob25MZWF2ZSkgew0KICAgIG5ldyBGdW5jdGlvbihvbkxlYXZlKS5jYWxsKGVsKTsNCiAgfQ0KDQogIHZhciBldnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnRXZlbnQnKTsNCiAgZXZ0LmluaXRFdmVudCgnc2xpZGVsZWF2ZScsIHRydWUsIHRydWUpOw0KICBldnQuc2xpZGVOdW1iZXIgPSBubyArIDE7IC8vIE1ha2UgaXQgcmVhZGFibGUNCiAgDQogIGVsLmRpc3BhdGNoRXZlbnQoZXZ0KTsNCn07DQoNCi8qIFRvdWNoIGV2ZW50cyAqLw0KDQpmdW5jdGlvbiBoYW5kbGVUb3VjaFN0YXJ0KGV2ZW50KSB7DQogIGlmIChldmVudC50b3VjaGVzLmxlbmd0aCA9PSAxKSB7DQogICAgdG91Y2hEWCA9IDA7DQogICAgdG91Y2hEWSA9IDA7DQoNCiAgICB0b3VjaFN0YXJ0WCA9IGV2ZW50LnRvdWNoZXNbMF0ucGFnZVg7DQogICAgdG91Y2hTdGFydFkgPSBldmVudC50b3VjaGVzWzBdLnBhZ2VZOw0KDQogICAgZG9jdW1lbnQuYm9keS5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBoYW5kbGVUb3VjaE1vdmUsIHRydWUpOw0KICAgIGRvY3VtZW50LmJvZHkuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBoYW5kbGVUb3VjaEVuZCwgdHJ1ZSk7DQogIH0NCn07DQoNCmZ1bmN0aW9uIGhhbmRsZVRvdWNoTW92ZShldmVudCkgew0KICBpZiAoZXZlbnQudG91Y2hlcy5sZW5ndGggPiAxKSB7DQogICAgY2FuY2VsVG91Y2goKTsNCiAgfSBlbHNlIHsNCiAgICB0b3VjaERYID0gZXZlbnQudG91Y2hlc1swXS5wYWdlWCAtIHRvdWNoU3RhcnRYOw0KICAgIHRvdWNoRFkgPSBldmVudC50b3VjaGVzWzBdLnBhZ2VZIC0gdG91Y2hTdGFydFk7DQogIH0NCn07DQoNCmZ1bmN0aW9uIGhhbmRsZVRvdWNoRW5kKGV2ZW50KSB7DQogIHZhciBkeCA9IE1hdGguYWJzKHRvdWNoRFgpOw0KICB2YXIgZHkgPSBNYXRoLmFicyh0b3VjaERZKTsNCg0KICBpZiAoKGR4ID4gUE1fVE9VQ0hfU0VOU0lUSVZJVFkpICYmIChkeSA8IChkeCAqIDIgLyAzKSkpIHsNCiAgICBpZiAodG91Y2hEWCA+IDApIHsNCiAgICAgIHByZXZTbGlkZSgpOw0KICAgIH0gZWxzZSB7DQogICAgICBuZXh0U2xpZGUoKTsNCiAgICB9DQogIH0NCiAgDQogIGNhbmNlbFRvdWNoKCk7DQp9Ow0KDQpmdW5jdGlvbiBjYW5jZWxUb3VjaCgpIHsNCiAgZG9jdW1lbnQuYm9keS5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBoYW5kbGVUb3VjaE1vdmUsIHRydWUpOw0KICBkb2N1bWVudC5ib2R5LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgaGFuZGxlVG91Y2hFbmQsIHRydWUpOyAgDQp9Ow0KDQovKiBQcmVsb2FkaW5nIGZyYW1lcyAqLw0KDQpmdW5jdGlvbiBkaXNhYmxlU2xpZGVGcmFtZXMobm8pIHsNCiAgdmFyIGVsID0gZ2V0U2xpZGVFbChubyk7DQogIGlmICghZWwpIHsNCiAgICByZXR1cm47DQogIH0NCg0KICB2YXIgZnJhbWVzID0gZWwuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2lmcmFtZScpOw0KICBmb3IgKHZhciBpID0gMCwgZnJhbWU7IGZyYW1lID0gZnJhbWVzW2ldOyBpKyspIHsNCiAgICBkaXNhYmxlRnJhbWUoZnJhbWUpOw0KICB9DQp9Ow0KDQpmdW5jdGlvbiBlbmFibGVTbGlkZUZyYW1lcyhubykgew0KICB2YXIgZWwgPSBnZXRTbGlkZUVsKG5vKTsNCiAgaWYgKCFlbCkgew0KICAgIHJldHVybjsNCiAgfQ0KDQogIHZhciBmcmFtZXMgPSBlbC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaWZyYW1lJyk7DQogIGZvciAodmFyIGkgPSAwLCBmcmFtZTsgZnJhbWUgPSBmcmFtZXNbaV07IGkrKykgew0KICAgIGVuYWJsZUZyYW1lKGZyYW1lKTsNCiAgfQ0KfTsNCg0KZnVuY3Rpb24gZGlzYWJsZUZyYW1lKGZyYW1lKSB7DQogIGZyYW1lLnNyYyA9ICdhYm91dDpibGFuayc7DQp9Ow0KDQpmdW5jdGlvbiBlbmFibGVGcmFtZShmcmFtZSkgew0KICB2YXIgc3JjID0gZnJhbWUuX3NyYzsNCg0KICBpZiAoZnJhbWUuc3JjICE9IHNyYyAmJiBzcmMgIT0gJ2Fib3V0OmJsYW5rJykgew0KICAgIGZyYW1lLnNyYyA9IHNyYzsNCiAgfQ0KfTsNCg0KZnVuY3Rpb24gc2V0dXBGcmFtZXMoKSB7DQogIHZhciBmcmFtZXMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdpZnJhbWUnKTsNCiAgZm9yICh2YXIgaSA9IDAsIGZyYW1lOyBmcmFtZSA9IGZyYW1lc1tpXTsgaSsrKSB7DQogICAgZnJhbWUuX3NyYyA9IGZyYW1lLnNyYzsNCiAgICBkaXNhYmxlRnJhbWUoZnJhbWUpOw0KICB9DQogIA0KICBlbmFibGVTbGlkZUZyYW1lcyhjdXJTbGlkZSk7DQogIGVuYWJsZVNsaWRlRnJhbWVzKGN1clNsaWRlICsgMSk7DQogIGVuYWJsZVNsaWRlRnJhbWVzKGN1clNsaWRlICsgMik7ICANCn07DQoNCmZ1bmN0aW9uIHNldHVwSW50ZXJhY3Rpb24oKSB7DQogIC8qIENsaWNraW5nIGFuZCB0YXBwaW5nICovDQogIA0KICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsNCiAgZWwuY2xhc3NOYW1lID0gJ3NsaWRlLWFyZWEnOw0KICBlbC5pZCA9ICdwcmV2LXNsaWRlLWFyZWEnOyAgDQogIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgcHJldlNsaWRlLCBmYWxzZSk7DQogIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3NlY3Rpb24uc2xpZGVzJykuYXBwZW5kQ2hpbGQoZWwpOw0KDQogIHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOw0KICBlbC5jbGFzc05hbWUgPSAnc2xpZGUtYXJlYSc7DQogIGVsLmlkID0gJ25leHQtc2xpZGUtYXJlYSc7ICANCiAgZWwuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBuZXh0U2xpZGUsIGZhbHNlKTsNCiAgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcignc2VjdGlvbi5zbGlkZXMnKS5hcHBlbmRDaGlsZChlbCk7ICANCiAgDQogIC8qIFN3aXBpbmcgKi8NCiAgDQogIGRvY3VtZW50LmJvZHkuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIGhhbmRsZVRvdWNoU3RhcnQsIGZhbHNlKTsNCn0NCg0KLyogQ2hyb21lVm94IHN1cHBvcnQgKi8NCg0KZnVuY3Rpb24gaXNDaHJvbWVWb3hBY3RpdmUoKSB7DQogIGlmICh0eXBlb2YoY3ZveCkgPT0gJ3VuZGVmaW5lZCcpIHsNCiAgICByZXR1cm4gZmFsc2U7DQogIH0gZWxzZSB7DQogICAgcmV0dXJuIHRydWU7DQogIH0NCn07DQoNCmZ1bmN0aW9uIHNwZWFrQW5kU3luY1RvTm9kZShub2RlKSB7DQogIGlmICghaXNDaHJvbWVWb3hBY3RpdmUoKSkgew0KICAgIHJldHVybjsNCiAgfQ0KICANCiAgY3ZveC5DaHJvbWVWb3gubmF2aWdhdGlvbk1hbmFnZXIuc3dpdGNoVG9TdHJhdGVneSgNCiAgICAgIGN2b3guQ2hyb21lVm94TmF2aWdhdGlvbk1hbmFnZXIuU1RSQVRFR0lFUy5MSU5FQVJET00sIDAsIHRydWUpOyAgDQogIGN2b3guQ2hyb21lVm94Lm5hdmlnYXRpb25NYW5hZ2VyLnN5bmNUb05vZGUobm9kZSk7DQogIGN2b3guQ2hyb21lVm94VXNlckNvbW1hbmRzLmZpbmlzaE5hdkNvbW1hbmQoJycpOw0KICB2YXIgdGFyZ2V0ID0gbm9kZTsNCiAgd2hpbGUgKHRhcmdldC5maXJzdENoaWxkKSB7DQogICAgdGFyZ2V0ID0gdGFyZ2V0LmZpcnN0Q2hpbGQ7DQogIH0NCiAgY3ZveC5DaHJvbWVWb3gubmF2aWdhdGlvbk1hbmFnZXIuc3luY1RvTm9kZSh0YXJnZXQpOw0KfTsNCg0KZnVuY3Rpb24gc3BlYWtOZXh0SXRlbSgpIHsNCiAgaWYgKCFpc0Nocm9tZVZveEFjdGl2ZSgpKSB7DQogICAgcmV0dXJuOw0KICB9DQogIA0KICBjdm94LkNocm9tZVZveC5uYXZpZ2F0aW9uTWFuYWdlci5zd2l0Y2hUb1N0cmF0ZWd5KA0KICAgICAgY3ZveC5DaHJvbWVWb3hOYXZpZ2F0aW9uTWFuYWdlci5TVFJBVEVHSUVTLkxJTkVBUkRPTSwgMCwgdHJ1ZSk7DQogIGN2b3guQ2hyb21lVm94Lm5hdmlnYXRpb25NYW5hZ2VyLm5leHQodHJ1ZSk7DQogIGlmICghY3ZveC5Eb21VdGlsLmlzRGVzY2VuZGFudE9mTm9kZSgNCiAgICAgIGN2b3guQ2hyb21lVm94Lm5hdmlnYXRpb25NYW5hZ2VyLmdldEN1cnJlbnROb2RlKCksIHNsaWRlRWxzW2N1clNsaWRlXSkpew0KICAgIHZhciB0YXJnZXQgPSBzbGlkZUVsc1tjdXJTbGlkZV07DQogICAgd2hpbGUgKHRhcmdldC5maXJzdENoaWxkKSB7DQogICAgICB0YXJnZXQgPSB0YXJnZXQuZmlyc3RDaGlsZDsNCiAgICB9DQogICAgY3ZveC5DaHJvbWVWb3gubmF2aWdhdGlvbk1hbmFnZXIuc3luY1RvTm9kZSh0YXJnZXQpOw0KICAgIGN2b3guQ2hyb21lVm94Lm5hdmlnYXRpb25NYW5hZ2VyLm5leHQodHJ1ZSk7DQogIH0NCiAgY3ZveC5DaHJvbWVWb3hVc2VyQ29tbWFuZHMuZmluaXNoTmF2Q29tbWFuZCgnJyk7DQp9Ow0KDQpmdW5jdGlvbiBzcGVha1ByZXZJdGVtKCkgew0KICBpZiAoIWlzQ2hyb21lVm94QWN0aXZlKCkpIHsNCiAgICByZXR1cm47DQogIH0NCiAgDQogIGN2b3guQ2hyb21lVm94Lm5hdmlnYXRpb25NYW5hZ2VyLnN3aXRjaFRvU3RyYXRlZ3koDQogICAgICBjdm94LkNocm9tZVZveE5hdmlnYXRpb25NYW5hZ2VyLlNUUkFURUdJRVMuTElORUFSRE9NLCAwLCB0cnVlKTsNCiAgY3ZveC5DaHJvbWVWb3gubmF2aWdhdGlvbk1hbmFnZXIucHJldmlvdXModHJ1ZSk7DQogIGlmICghY3ZveC5Eb21VdGlsLmlzRGVzY2VuZGFudE9mTm9kZSgNCiAgICAgIGN2b3guQ2hyb21lVm94Lm5hdmlnYXRpb25NYW5hZ2VyLmdldEN1cnJlbnROb2RlKCksIHNsaWRlRWxzW2N1clNsaWRlXSkpew0KICAgIHZhciB0YXJnZXQgPSBzbGlkZUVsc1tjdXJTbGlkZV07DQogICAgd2hpbGUgKHRhcmdldC5sYXN0Q2hpbGQpew0KICAgICAgdGFyZ2V0ID0gdGFyZ2V0Lmxhc3RDaGlsZDsNCiAgICB9DQogICAgY3ZveC5DaHJvbWVWb3gubmF2aWdhdGlvbk1hbmFnZXIuc3luY1RvTm9kZSh0YXJnZXQpOw0KICAgIGN2b3guQ2hyb21lVm94Lm5hdmlnYXRpb25NYW5hZ2VyLnByZXZpb3VzKHRydWUpOw0KICB9DQogIGN2b3guQ2hyb21lVm94VXNlckNvbW1hbmRzLmZpbmlzaE5hdkNvbW1hbmQoJycpOw0KfTsNCg0KLyogSGFzaCBmdW5jdGlvbnMgKi8NCg0KZnVuY3Rpb24gZ2V0Q3VyU2xpZGVGcm9tSGFzaCgpIHsNCiAgdmFyIHNsaWRlTm8gPSBwYXJzZUludChsb2NhdGlvbi5oYXNoLnN1YnN0cigxKSk7DQoNCiAgaWYgKHNsaWRlTm8pIHsNCiAgICBjdXJTbGlkZSA9IHNsaWRlTm8gLSAxOw0KICB9IGVsc2Ugew0KICAgIGN1clNsaWRlID0gMDsNCiAgfQ0KfTsNCg0KZnVuY3Rpb24gdXBkYXRlSGFzaCgpIHsNCiAgbG9jYXRpb24ucmVwbGFjZSgnIycgKyAoY3VyU2xpZGUgKyAxKSk7DQp9Ow0KDQovKiBFdmVudCBsaXN0ZW5lcnMgKi8NCg0KZnVuY3Rpb24gaGFuZGxlQm9keUtleURvd24oZXZlbnQpIHsNCiAgc3dpdGNoIChldmVudC5rZXlDb2RlKSB7DQogICAgY2FzZSAzOTogLy8gcmlnaHQgYXJyb3cNCiAgICBjYXNlIDEzOiAvLyBFbnRlcg0KICAgIGNhc2UgMzI6IC8vIHNwYWNlDQogICAgY2FzZSAzNDogLy8gUGdEbg0KICAgICAgbmV4dFNsaWRlKCk7DQogICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOw0KICAgICAgYnJlYWs7DQoNCiAgICBjYXNlIDM3OiAvLyBsZWZ0IGFycm93DQogICAgY2FzZSA4OiAvLyBCYWNrc3BhY2UNCiAgICBjYXNlIDMzOiAvLyBQZ1VwDQogICAgICBwcmV2U2xpZGUoKTsNCiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7DQogICAgICBicmVhazsNCg0KICAgIGNhc2UgNDA6IC8vIGRvd24gYXJyb3cNCiAgICAgIGlmIChpc0Nocm9tZVZveEFjdGl2ZSgpKSB7DQogICAgICAgIHNwZWFrTmV4dEl0ZW0oKTsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIG5leHRTbGlkZSgpOw0KICAgICAgfQ0KICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsNCiAgICAgIGJyZWFrOw0KDQogICAgY2FzZSAzODogLy8gdXAgYXJyb3cNCiAgICAgIGlmIChpc0Nocm9tZVZveEFjdGl2ZSgpKSB7DQogICAgICAgIHNwZWFrUHJldkl0ZW0oKTsNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIHByZXZTbGlkZSgpOw0KICAgICAgfQ0KICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsNCiAgICAgIGJyZWFrOw0KICB9DQp9Ow0KDQpmdW5jdGlvbiBhZGRFdmVudExpc3RlbmVycygpIHsNCiAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGhhbmRsZUJvZHlLZXlEb3duLCBmYWxzZSk7ICANCn07DQoNCi8qIEluaXRpYWxpemF0aW9uICovDQoNCmZ1bmN0aW9uIGFkZFByZXR0aWZ5KCkgew0KICB2YXIgZWxzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgncHJlJyk7DQogIGZvciAodmFyIGkgPSAwLCBlbDsgZWwgPSBlbHNbaV07IGkrKykgew0KICAgIGlmICghZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdub3ByZXR0eXByaW50JykpIHsNCiAgICAgIGVsLmNsYXNzTGlzdC5hZGQoJ3ByZXR0eXByaW50Jyk7DQogICAgfQ0KICB9DQogIA0KICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTsNCiAgZWwudHlwZSA9ICd0ZXh0L2phdmFzY3JpcHQnOw0KICBlbC5zcmMgPSBQRVJNQU5FTlRfVVJMX1BSRUZJWCArICdwcmV0dGlmeS5qcyc7DQogIGVsLm9ubG9hZCA9IGZ1bmN0aW9uKCkgew0KICAgIHByZXR0eVByaW50KCk7DQogIH0NCiAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChlbCk7DQp9Ow0KDQpmdW5jdGlvbiBhZGRGb250U3R5bGUoKSB7DQogIHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpbmsnKTsNCiAgZWwucmVsID0gJ3N0eWxlc2hlZXQnOw0KICBlbC50eXBlID0gJ3RleHQvY3NzJzsNCiAgZWwuaHJlZiA9ICdodHRwOi8vZm9udHMuZ29vZ2xlYXBpcy5jb20vY3NzP2ZhbWlseT0nICsNCiAgICAgICAgICAgICdPcGVuK1NhbnM6cmVndWxhcixzZW1pYm9sZCxpdGFsaWMsaXRhbGljc2VtaWJvbGR8RHJvaWQrU2FucytNb25vJzsNCg0KICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGVsKTsNCn07DQoNCmZ1bmN0aW9uIGFkZEdlbmVyYWxTdHlsZSgpIHsNCiAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGluaycpOw0KICBlbC5yZWwgPSAnc3R5bGVzaGVldCc7DQogIGVsLnR5cGUgPSAndGV4dC9jc3MnOw0KICBlbC5ocmVmID0gUEVSTUFORU5UX1VSTF9QUkVGSVggKyAnc3R5bGVzLmNzcyc7DQogIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZWwpOw0KICANCiAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbWV0YScpOw0KICBlbC5uYW1lID0gJ3ZpZXdwb3J0JzsNCiAgZWwuY29udGVudCA9ICd3aWR0aD0xMTAwLGhlaWdodD03NTAnOw0KICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdoZWFkJykuYXBwZW5kQ2hpbGQoZWwpOw0KICANCiAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbWV0YScpOw0KICBlbC5uYW1lID0gJ2FwcGxlLW1vYmlsZS13ZWItYXBwLWNhcGFibGUnOw0KICBlbC5jb250ZW50ID0gJ3llcyc7DQogIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2hlYWQnKS5hcHBlbmRDaGlsZChlbCk7DQp9Ow0KDQpmdW5jdGlvbiBtYWtlQnVpbGRMaXN0cygpIHsNCiAgZm9yICh2YXIgaSA9IGN1clNsaWRlLCBzbGlkZTsgc2xpZGUgPSBzbGlkZUVsc1tpXTsgaSsrKSB7DQogICAgdmFyIGl0ZW1zID0gc2xpZGUucXVlcnlTZWxlY3RvckFsbCgnLmJ1aWxkID4gKicpOw0KICAgIGZvciAodmFyIGogPSAwLCBpdGVtOyBpdGVtID0gaXRlbXNbal07IGorKykgew0KICAgICAgaWYgKGl0ZW0uY2xhc3NMaXN0KSB7DQogICAgICAgIGl0ZW0uY2xhc3NMaXN0LmFkZCgndG8tYnVpbGQnKTsNCiAgICAgIH0NCiAgICB9DQogIH0NCn07DQoNCmZ1bmN0aW9uIGhhbmRsZURvbUxvYWRlZCgpIHsNCiAgc2xpZGVFbHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdzZWN0aW9uLnNsaWRlcyA+IGFydGljbGUnKTsNCg0KICBzZXR1cEZyYW1lcygpOw0KDQogIGFkZEZvbnRTdHlsZSgpOw0KICBhZGRHZW5lcmFsU3R5bGUoKTsNCiAgYWRkUHJldHRpZnkoKTsNCiAgYWRkRXZlbnRMaXN0ZW5lcnMoKTsNCg0KICB1cGRhdGVTbGlkZXMoKTsNCg0KICBzZXR1cEludGVyYWN0aW9uKCk7DQogIG1ha2VCdWlsZExpc3RzKCk7DQoNCiAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuYWRkKCdsb2FkZWQnKTsNCn07DQoNCmZ1bmN0aW9uIGluaXRpYWxpemUoKSB7DQogIGdldEN1clNsaWRlRnJvbUhhc2goKTsNCg0KICBpZiAod2luZG93WydfREVCVUcnXSkgew0KICAgIFBFUk1BTkVOVF9VUkxfUFJFRklYID0gJy4uLyc7DQogIH0NCg0KICBpZiAod2luZG93WydfRENMJ10pIHsNCiAgICBoYW5kbGVEb21Mb2FkZWQoKTsNCiAgfSBlbHNlIHsNCiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgaGFuZGxlRG9tTG9hZGVkLCBmYWxzZSk7DQogIH0NCn0NCg0KLy8gSWYgP2RlYnVnIGV4aXN0cyB0aGVuIGxvYWQgdGhlIHNjcmlwdCByZWxhdGl2ZSBpbnN0ZWFkIG9mIGFic29sdXRlDQppZiAoIXdpbmRvd1snX0RFQlVHJ10gJiYgZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCc/ZGVidWcnKSAhPT0gLTEpIHsNCiAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZ1bmN0aW9uKCkgew0KICAgIC8vIEF2b2lkIG1pc3NpbmcgdGhlIERvbUNvbnRlbnRMb2FkZWQgZXZlbnQNCiAgICB3aW5kb3dbJ19EQ0wnXSA9IHRydWUNCiAgfSwgZmFsc2UpOw0KDQogIHdpbmRvd1snX0RFQlVHJ10gPSB0cnVlOw0KICB2YXIgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7DQogIHNjcmlwdC50eXBlID0gJ3RleHQvamF2YXNjcmlwdCc7DQogIHNjcmlwdC5zcmMgPSAnLi4vc2xpZGVzLmpzJzsNCiAgdmFyIHMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnc2NyaXB0JylbMF07DQogIHMucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoc2NyaXB0LCBzKTsNCg0KICAvLyBSZW1vdmUgdGhpcyBzY3JpcHQNCiAgcy5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHMpOw0KfSBlbHNlIHsNCiAgaW5pdGlhbGl6ZSgpOw0KfQ0K