PCEtLQogICAgCiAgICBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lIG9yIG1vcmUKICAgIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUgZGlzdHJpYnV0ZWQgd2l0aAogICAgdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIHJlZ2FyZGluZyBjb3B5cmlnaHQgb3duZXJzaGlwLgogICAgVGhlIEFTRiBsaWNlbnNlcyB0aGlzIGZpbGUgdG8gWW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAKICAgICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoCiAgICB0aGUgTGljZW5zZS4gIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAogICAgCiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKICAgIAogICAgVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQogICAgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKICAgIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgogICAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAogICAgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCgotLT4KPGh0bWw+CjxoZWFkPgo8dGl0bGU+U2VydmljZU1peCA0IENYRi1PU0dpIEV4YW1wbGU8L3RpdGxlPgo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+CnZhciB1cmxUb09wZW4gPSAiaHR0cDovL2xvY2FsaG9zdDo4MTgxL2N4Zi9Tb2FwQ29udGV4dC9Tb2FwUG9ydCI7IC8vZGVmYXVsdCBVUkwgdG8gb3BlbgoKZnVuY3Rpb24gZ2V0SFRUUE9iamVjdCgpIHsKICB2YXIgeG1saHR0cCA9IGZhbHNlOwoKICAvKiBDb21waWxhdGlvbiBjb25kaXRpb25uZWxsZSBkJ0lFICovCiAgLyogQ2hlY2sgaWYgd2UgYXJlIHVzaW5nIElFICovCiAgLypAY2Nfb24KICBAaWYgKEBfanNjcmlwdF92ZXJzaW9uID49IDUpCiAgICAgdHJ5IHsKICAgICAgICB4bWxodHRwID0gbmV3IEFjdGl2ZVhPYmplY3QoIk1zeG1sMi5YTUxIVFRQIik7CiAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIHRyeSB7CiAgICAgICAgICAgeG1saHR0cCA9IG5ldyBBY3RpdmVYT2JqZWN0KCJNaWNyb3NvZnQuWE1MSFRUUCIpOwogICAgICAgIH0gY2F0Y2ggKEUpIHsKICAgICAgICAgICB4bWxodHRwID0gZmFsc2U7CiAgICAgICAgfQogICAgIH0KICBAZWxzZQogICAgIHhtbGh0dHAgPSBmYWxzZTsKICBAZW5kIEAqLwoKICAvKiBvbiBlc3NhaWUgZGUgY3LpZXIgbCdvYmpldCBzaSBjZSBuJ2VzdCBwYXMgZOlq4CBmYWl0ICovCiAgLyogQ3JlYXRlIHRoZSB4bWxodHRwIG9iamVjdCBpZiBpdCBpcyBub3QgeWV0IGRlZmluZWQgKi8KICBpZiAoIXhtbGh0dHAgJiYgdHlwZW9mIFhNTEh0dHBSZXF1ZXN0ICE9ICd1bmRlZmluZWQnKSB7CiAgICAgdHJ5IHsKICAgICAgICB4bWxodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7CiAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIHhtbGh0dHAgPSBmYWxzZTsKICAgICB9CiAgfQoKICBpZiAoeG1saHR0cCkgewogICAgIC8qIG9uIGTpZmluaXQgY2UgcXVpIGRvaXQgc2UgcGFzc2VyIHF1YW5kIGxhIHBhZ2Ugculwb25kcmEgKi8KICAgICAvKiBEZWZpbmUgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGZvciB0aGUgcmVzcG9uc2UgKi8KICAgICB4bWxodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZT1mdW5jdGlvbigpIHsKICAgICAgICBpZiAoeG1saHR0cC5yZWFkeVN0YXRlID09IDQpIHsgLyogNCA6IOl0YXQgImNvbXBsZXRlIiAqLwogICAgICAgICAgIHZhciByZXNwb25zZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJyZXNwb25zZSIpOwogICAgICAgICAgIHZhciByZXNwb25zZVN0YXR1cyA9ICIiOwogICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICByZXNwb25zZVN0YXR1cyA9IHhtbGh0dHAuc3RhdHVzICsgIiI7CiAgICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAgcmVzcG9uc2VTdGF0dXMgPSAiRVJST1IgV0hJTEUgUkVUUklFVklORyBTVEFUVVM7IE1BWUJFIFVOQUJMRSBUTyBDT05ORUNULiI7CiAgICAgICAgICAgfQogICAgICAgICAgIHJlc3BvbnNlLnZhbHVlID0gIlNUQVRVUzogIiArIHJlc3BvbnNlU3RhdHVzICsgIlxuIiArIHhtbGh0dHAucmVzcG9uc2VUZXh0OwogICAgICAgIH0KICAgICB9CiAgfQogIHJldHVybiB4bWxodHRwOwp9CgpmdW5jdGlvbiBzZW5kKCkgewogIGlmICgoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInVybFRvT3BlbiIpLnZhbHVlICE9IHVybFRvT3BlbikgJiYgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ1cmxUb09wZW4iKS52YWx1ZSAhPSAiIikpIHsKICAgIC8vIHVzZSB1c2VyIGVudHJ5IGlmIGl0IGlzIG5vdCB0aGUgZW1wdHkgc3RyaW5nCiAgICB1cmxUb09wZW4gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidXJsVG9PcGVuIikudmFsdWU7CiAgfSAgCiAgdmFyIHhtbGh0dHAgPSBnZXRIVFRQT2JqZWN0KCk7CiAgaWYgKCF4bWxodHRwKSB7CiAgICBhbGVydCgnY291bmQgbm90IGNyZWF0ZSBYTUxIdHRwUmVxdWVzdCBvYmplY3QnKTsKICAgIHJldHVybjsKICB9CiAgdmFyIHJlcXVlc3QgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgicmVxdWVzdCIpOwogIHZhciByZXNwb25zZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJyZXNwb25zZSIpOwogIHRyeSB7CiAgICBuZXRzY2FwZS5zZWN1cml0eS5Qcml2aWxlZ2VNYW5hZ2VyLmVuYWJsZVByaXZpbGVnZSgiVW5pdmVyc2FsQnJvd3NlclJlYWQgVW5pdmVyc2FsQnJvd3NlcldyaXRlIik7CiAgfSBjYXRjaCAoZSkgewogIH0KICB0cnkgewogICAgeG1saHR0cC5vcGVuKCJQT1NUIiwgdXJsVG9PcGVuLCB0cnVlKTsKICB9IGNhdGNoIChlKSB7CiAgICBhbGVydCgnZXJyb3Igb3BlbmluZycpOwogIH0KICB4bWxodHRwLnNlbmQocmVxdWVzdC52YWx1ZSk7Cn0KCjwvc2NyaXB0Pgo8L2hlYWQ+Cgo8Ym9keT4KCjxoMT5TZXJ2aWNlTWl4IDQgQ1hGIFdTLUFkZHJlc3NpbmcgRXhhbXBsZTwvaDE+Cgo8cD5XZWxjb21lIHRvIHRoZSBDWEYgV1MtQWRkcmVzc2luZyBleGFtcGxlIGZvciBTZXJ2aWNlTWl4IDQ8L3A+Cgo8cD5QZXJmb3JtIGEgUE9TVCBpbnRvIHRoZSBIVFRQIGJpbmRpbmcuIFRoaXMgcmVxdWlyZXMgSmF2YVNjcmlwdC48L3A+IAo8cD5UYXJnZXQ6IDxpbnB1dCB0eXBlPSJ0ZXh0IiBzaXplPSI1MCIgaWQ9InVybFRvT3BlbiIgdmFsdWU9IiI+PHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ1cmxUb09wZW4iKS52YWx1ZSA9IHVybFRvT3Blbjs8L3NjcmlwdD4uPC9wPgogIAo8dGFibGU+CiAgPHRyPgogICAgPHRkPgogIDx0ZXh0YXJlYSBpZD0icmVxdWVzdCIgc3R5bGU9IndpZHRoOjYwMHB4O2hlaWdodDo0MDBweCI+PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHNvYXA6RW52ZWxvcGUgeG1sbnM6c29hcD0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvc29hcC9lbnZlbG9wZS8iPgogICA8c29hcDpIZWFkZXI+CiAgICAgIDxNZXNzYWdlSUQgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDUvMDgvYWRkcmVzc2luZyI+dXJuOnV1aWQ6MTBmYjJlZTYtNDNkYi00ZDg4LWEzZTUtNjMxNmYxNzYzNjY5PC9NZXNzYWdlSUQ+CiAgICAgIDxUbyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwNS8wOC9hZGRyZXNzaW5nIj5odHRwOi8vbG9jYWxob3N0OjkwMDEvU29hcENvbnRleHQvU29hcFBvcnQ8L1RvPgogICAgICA8UmVwbHlUbyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwNS8wOC9hZGRyZXNzaW5nIj4KICAgICAgICAgPEFkZHJlc3M+aHR0cDovL3d3dy53My5vcmcvMjAwNS8wOC9hZGRyZXNzaW5nL2Fub255bW91czwvQWRkcmVzcz4KICAgICAgPC9SZXBseVRvPgogICAgICA8RmF1bHRUbyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwNS8wOC9hZGRyZXNzaW5nIj4KICAgICAgICAgPEFkZHJlc3M+aHR0cDovL3d3dy53My5vcmcvMjAwNS8wOC9hZGRyZXNzaW5nL2Fub255bW91PC9BZGRyZXNzPgogICAgICA8L0ZhdWx0VG8+CiAgICAgIDxBY3Rpb24geG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDUvMDgvYWRkcmVzc2luZyI+aHR0cDovL2FwYWNoZS5vcmcvaGVsbG9fd29ybGRfc29hcF9odHRwL0dyZWV0ZXIvc2F5SGlSZXF1ZXN0PC9BY3Rpb24+CiAgIDwvc29hcDpIZWFkZXI+CiAgIDxzb2FwOkJvZHk+CiAgICAgIDxzYXlIaSB4bWxucz0iaHR0cDovL2FwYWNoZS5vcmcvaGVsbG9fd29ybGRfc29hcF9odHRwL3R5cGVzIi8+CiAgIDwvc29hcDpCb2R5Pgo8L3NvYXA6RW52ZWxvcGU+CgogIDwvdGV4dGFyZWE+CiAgICA8L3RkPgogICAgPHRkPgogIDx0ZXh0YXJlYSBpZD0icmVzcG9uc2UiIHN0eWxlPSJ3aWR0aDo2MDBweDtoZWlnaHQ6NDAwcHgiPgogIDwvdGV4dGFyZWE+CiAgICA8L3RkPgogIDwvdHI+CiAgPHRyPgogICAgPHRkIGNvbHNwYW49Mj4KICA8aW5wdXQgdHlwZT0iYnV0dG9uIiB2YWx1ZT0iU2VuZCIgb25DbGljaz0ic2VuZCgpOyIvPgogICAgPC90ZD4KICA8L3RyPgo8L3RhYmxlPgo8L2JvZHk+CjwvaHRtbD4K