Ly8gZnVuY3Rpb25zIGluIHRoaXMgbW9kZXVsZSBhcmUgdXNlZCBmb3IgdmVyaWZ5aW5nIHRoYXQgYSBzdHVkZW50IGlzIHdobyB0aGV5IAovLyBzYXkgdGhleSBhcmUKCmZ1bmN0aW9uIHNldF9zaGFyZWRfb3JfcHJpdmF0ZShzaGFyZWRfb3JfcHJpdmF0ZSl7CiAgICAvL3JlYWRzIG9yIHdyaXRlcyB0byBsb2NhbCBzdG9yYWdlIHdoZXRoZXIgdGhpcyBjb21wdXRlciBpcyBzaGFyZWQgb3IgcHJpdmF0ZQogICAgQm9va1N0b3JhZ2UuaXNQcml2YXRlQ29tcHV0ZXIoc2hhcmVkX29yX3ByaXZhdGU9PT0icHJpdmF0ZSIpCiAgICBjb25zdCBsb2NhdGlvbiA9IHNoYXJlZF9vcl9wcml2YXRlPT09InByaXZhdGUiID8gQXV0b1N0b3JhZ2UuU1RPUkFHRV9UWVBFLkxPQ0FMIDogQXV0b1N0b3JhZ2UuU1RPUkFHRV9UWVBFLlNFU1NJT04KICAgIEJvb2tTdG9yYWdlLnVwZGF0ZVN0b3JhZ2VUeXBlKGxvY2F0aW9uKQogICAgc2hvd19zaGFyZWRfcHJpdmF0ZV9kZXRhaWxzKCkKICAKfQoKZnVuY3Rpb24gc2hvd19zaGFyZWRfcHJpdmF0ZV9kZXRhaWxzKCl7CiAgICAvLyBzaG93IG9yIGhpZGUgdGhlIGRldGFpbHMgb2YgZWFjaCBhdXRoZW50aWNhdGlvbiBtZXRob2QgYXBwcm9wcmlhdGVseQogICAgaWYoQm9va1N0b3JhZ2UuaXNQcml2YXRlQ29tcHV0ZXIoKSl7CiAgICAgICAgZm9yKGNvbnN0IGVsZW0gb2YgZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgic2hhcmVkLWNvbXB1dGVyIikpewogICAgICAgICAgICBlbGVtLnN0eWxlLmRpc3BsYXk9Im5vbmUiCiAgICAgICAgfQogICAgICAgIGZvcihjb25zdCBlbGVtIG9mIGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoInByaXZhdGUtY29tcHV0ZXIiKSl7CiAgICAgICAgICAgIGVsZW0uc3R5bGUuZGlzcGxheT0iIgogICAgICAgIH0KICAgIH1lbHNlewogICAgICAgIGZvcihjb25zdCBlbGVtIG9mIGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoInNoYXJlZC1jb21wdXRlciIpKXsKICAgICAgICAgICAgZWxlbS5zdHlsZS5kaXNwbGF5PSIiCiAgICAgICAgfQogICAgICAgIGZvcihjb25zdCBlbGVtIG9mIGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoInByaXZhdGUtY29tcHV0ZXIiKSl7CiAgICAgICAgICAgIGVsZW0uc3R5bGUuZGlzcGxheT0ibm9uZSIKICAgICAgICB9CiAgICB9CiAgICAgIAp9Cgphc3luYyBmdW5jdGlvbiBjaG9vc2VfY29uZmlndXJhdGlvbihldnQpIHsKICAvL2NvbnNvbGUubG9nKCJldnQiLGV2dCkKCgogIC8vIGNhbiBiZSBjYWxsZWQgYnkgcGFzc2luZyBpbiB0aGUgY2hlY2tib3ggdG8gb3BlcmF0ZSBvbiwgb3IgYnkgY2xpY2tpbmcgdGhlIGNoZWNrYm94CiAgbGV0IGNoZWNrYm94PWV2dAogIGlmKGV2dC50YXJnZXQpewogICAgLy8gaXQgbG9va3MgYXMgdGhvdWdoIHdlIGFyZSBjbGlja2luZyBvbiB0aGUgY2hlY2tib3gKICAgIGNoZWNrYm94ID0gZXZ0LnRhcmdldAogIH0KCiAgY29uc3QgY29uZmlnX2lkID0gY2hlY2tib3guaWQKCiAgLy8gc2V0IHRoZSBkYlR5cGUgdG8gdGhlIGlkIG9mIGh0ZSBib3gganVzdCBjaGVja2VkCiAgbGV0IGNoYW5nZT1mYWxzZQogIGxldCByZXNwb25zZT1udWxsCiAgc3dpdGNoIChjb25maWdfaWQpIHsKICAgIGNhc2UgImJvb2siOgogICAgICBjaGFuZ2U9dHJ1ZQogICAgICBicmVhawogICAgY2FzZSAic3FsaXRlIjoKICAgICAgY2hhbmdlPXRydWUKICAgICAgYnJlYWsKICAgIGNhc2UgImRhdGF3b3JsZCI6CiAgICAgIC8vY29uc29sZS5sb2coInNldHRpbmcgZHcgdG9rZW4iKQogICAgICBjaGVja2JveC5pbm5lckhUTUw9ImhvdXJnbGFzc19lbXB0eSIKICAgICAgY2hlY2tib3guY2xhc3NMaXN0LmFkZCgiYmxpbmsiKQogICAgICBpZighZXZ0LmN0cmxLZXkpey8vb25seSB0cnlpbmcgdG8gY2hlY2sgZXhpc3RpbmcgY29uZmlnIGlzIGN0cmwgaXMgbm90IGRvd24gd2hlbiBjbGlja2VkCiAgICAgICAgcmVzcG9uc2U9Z2V0X2Zyb21fYm9va19zdG9yYWdlKCJkd1Rva2VuIikKICAgICAgICBpZiAocmVzcG9uc2UpewogICAgICAgICAgcmVzcG9uc2UgPSBhd2FpdCBjaGVja19kd19jb25uZWN0aW9uKHJlc3BvbnNlKQogICAgICAgICAgaWYocmVzcG9uc2Uuc3RhdHVzIT09InN1Y2Nlc3MiKXsKICAgICAgICAgICAgcmVzcG9uc2U9bnVsbAogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYocmVzcG9uc2UpeyAgCiAgICAgICAgY2hhbmdlPXRydWUKICAgICAgfWVsc2V7ICAKICAgICAgICAvLyBlaXRoZXIgdGhlcmUgaXMgbm8gZHdUb2tlbiBvciBpdCBkaWQgbm90IHdvcmsKICAgICAgICByZXNwb25zZSA9IGF3YWl0IGdldF9kd190b2tlbigpCiAgICAgICAgaWYocmVzcG9uc2UpewogICAgICAgICAgQm9va1N0b3JhZ2UuZHdUb2tlbihyZXNwb25zZSkKICAgICAgICAgIGNoYW5nZT10cnVlCiAgICAgICAgfQogICAgICB9CiAgICAgIGNoZWNrYm94LmNsYXNzTGlzdC5yZW1vdmUoImJsaW5rIikKICAgICAgYnJlYWsKICAgIGNhc2UgIm9yYWNsZSI6CiAgICAgIGNoZWNrYm94LmlubmVySFRNTD0iaG91cmdsYXNzX2VtcHR5IgogICAgICBjaGVja2JveC5jbGFzc0xpc3QuYWRkKCJibGluayIpCiAgICAgIC8vIGNoZWNrIHRvIHNlZSBpZiB3ZSBjYW4gcnVuIGFuIG9yYWNsZSBxdWVyeQogICAgICAKICAgICAgbGV0IHN1Y2Nlc2Z1bGx5RXhlY3V0ZWRRdWVyeT1mYWxzZQogICAgICBpZighZXZ0LmN0cmxLZXkpey8vb25seSB0cnlpbmcgdG8gY2hlY2sgZXhpc3RpbmcgY29uZmlnIGlzIGN0cmwgaXMgbm90IGRvd24gd2hlbiBjbGlja2VkCgogICAgICAgIGxldCBlbmRwb2ludCA9IEJvb2tTdG9yYWdlLmxvZ2luVHlwZSgpPT09ImdhcyIgPyBnZXRfZ2FzX2VuZHBvaW50KCkgOiBudWxsCiAgICAgICAgLy8gaXQncyBva2F5IHRvIGF0dGVtcHQgdGhlIHF1ZXJ5IGlmIHdlIGhhdmUgYW4gZW5kcG9pbnQgT1Igd2UgdGhlIGxvZ2ludHlwZSBpcyBwYWlkCgogICAgICAgIGlmKGVuZHBvaW50IHx8IEJvb2tTdG9yYWdlLmxvZ2luVHlwZSgpPT09InBhaWQiKXsKICAgICAgICAgIHRyeXsKICAgICAgICAgICAgICByZXNwb25zZSA9IGF3YWl0IHJ1bl9kYl9xdWVyeSh7Y29ubmVjdGlvbjoic3FsX2Jvb2tfY29ubmVjdGlvbiIsIGVuZ2luZToib3JhY2xlIixlbmRwb2ludDplbmRwb2ludCwgcXVlcnk6InNlbGVjdCBjb3VudCgqKSBhcyBvbmUgZnJvbSBjYW52YXMubXVzZXVtIn0pICAKICAgICAgICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZSkKICAgICAgICAgICAgICBpZiAocmVzcG9uc2U/Lml0ZW1zWzBdPy5yZXN1bHRTZXQ/Lml0ZW1zWzBdPy5vbmUpIHsKICAgICAgICAgICAgICAgIHN1Y2Nlc2Z1bGx5RXhlY3V0ZWRRdWVyeSA9IHRydWUKICAgICAgICAgICAgICB9ZWxzZXsKICAgICAgICAgICAgICAgIHN1Y2Nlc2Z1bGx5RXhlY3V0ZWRRdWVyeSA9IGZhbHNlCiAgICAgICAgICAgICAgfQogICAgICAgICAgfWNhdGNoKGUpewogICAgICAgICAgICBzdWNjZXNmdWxseUV4ZWN1dGVkUXVlcnkgPSBmYWxzZQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBpZihzdWNjZXNmdWxseUV4ZWN1dGVkUXVlcnkpewogICAgICAgIC8vIHdlIHN1Y2Nlc2Z1bGx5IGV4ZWN1dGVkIGFuIG9yYWNsZSBxdWVyeQogICAgICAgIGNoYW5nZT10cnVlCiAgICAgIH1lbHNlewogICAgICAgIHJlc3BvbnNlID0gYXdhaXQgZ2V0X29yYWNsZV9jb25maWd1cmF0aW9uKCkKICAgICAgICBjb25zb2xlLmxvZygicmVzcG9uc2UgZnJvbSBnZXR0aW5nIG9yYWNsZSIsIHJlc3BvbnNlKQogICAgICAgIGlmKHJlc3BvbnNlPT0iY29ubmVjdGVkIil7CiAgICAgICAgICBjaGFuZ2U9dHJ1ZQogICAgICAgIH0KICAgICAgfQogICAgICBjaGVja2JveC5jbGFzc0xpc3QucmVtb3ZlKCJibGluayIpCiAgICAgIGJyZWFrCiAgfQogIGNoZWNrYm94LmNsYXNzTGlzdC5yZW1vdmUoImJsaW5rIikKICBjaGVja2JveC5pbm5lckhUTUw9ImNoZWNrX2JveF9vdXRsaW5lX2JsYW5rIgogIGlmKGNoYW5nZSl7CiAgICBCb29rU3RvcmFnZS5kYlR5cGUoY29uZmlnX2lkKQogICAgc2V0X2Jvb2tfbGFiZWwoKQogICAgZm9yIChib3ggb2YgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgiLiIgKyBjaGVja2JveC5kYXRhc2V0LnNldCkpIHsKICAgICAgYm94LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJzcGFuIilbMF0uaW5uZXJIVE1MID0gImNoZWNrX2JveF9vdXRsaW5lX2JsYW5rIgogICAgICBib3gubmV4dEVsZW1lbnRTaWJsaW5nLnN0eWxlLmRpc3BsYXkgPSAibm9uZSIKICAgIH0KICAgIGNoZWNrYm94LmlubmVySFRNTCA9ICJjaGVja19ib3giCiAgICB0YWcoImNvbmZpZy0iICsgY29uZmlnX2lkKS5zdHlsZS5kaXNwbGF5ID0gIiIKICAgIGNvbmZpZ3VyZV9ib29rKCkKICB9Cn0KCgphc3luYyBmdW5jdGlvbiBjaG9vc2VfYWlfbWV0aG9kKGV2dCkgewogIC8vIGV4ZWN1dGVkIHdoZW4gdGhlIHVzZXJzIGNsaWNrcyB0aGUgYW4gQUkgb3B0aW9uIGNoZWNrYm94IG9uIHRoZSBjb25naWd1cmF0aW9uIHBhZ2UKICBjb25zdCBjaGVja2JveD1ldnQudGFyZ2V0CiAgaWYoY2hlY2tib3guaW5uZXJIVE1MPT09ImNoZWNrX2JveCIpe3JldHVybn0KICBCb29rU3RvcmFnZS5haVR5cGUoY2hlY2tib3guaWQpCgogIGZvciAoYm94IG9mIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoIi4iICsgY2hlY2tib3guZGF0YXNldC5zZXQpKSB7CiAgICBib3guZ2V0RWxlbWVudHNCeVRhZ05hbWUoInNwYW4iKVswXS5pbm5lckhUTUwgPSAiY2hlY2tfYm94X291dGxpbmVfYmxhbmsiCiAgICBib3gubmV4dEVsZW1lbnRTaWJsaW5nLnN0eWxlLmRpc3BsYXkgPSAibm9uZSIKICB9CgogIGNoZWNrYm94LmlubmVySFRNTCA9ICJjaGVja19ib3giCiAgY29uZmlndXJlX2Jvb2soKQp9CgoKCgphc3luYyBmdW5jdGlvbiBjaG9vc2VfbG9naW5fbWV0aG9kKGV2dCkgewogIC8vY29uc29sZS5sb2coImNhbGxpbmcgY2hvb3NlIGxvZ2luIG1ldGhvZCIpOwoKICAvLyBjYW4gYmUgY2FsbGVkIGJ5IHBhc3NpbmcgaW4gdGhlIGNoZWNrYm94IHRvIG9wZXJhdGUgb24sIG9yIGJ5IGNsaWNraW5nIHRoZSBjaGVja2JveAogIGxldCBjaGVja2JveD1ldnQKICBpZihldnQudGFyZ2V0KXsKICAgIC8vIGl0IGxvb2tzIGFzIHRob3VnaCB3ZSBhcmUgY2xpY2tpbmcgb24gdGhlIGNoZWNrYm94CiAgICBjaGVja2JveCA9IGV2dC50YXJnZXQKICB9CiAgICBjb25zdCBsb2dpbl9pZCA9IGNoZWNrYm94LmlkCiAgCiAgICBsZXQgY2hhbmdlID0gZmFsc2UKICAgIGxldCBhdXRoX21lc3NhZ2U9IllvdSBhcmUgbm93IGNvbmZpZ3VyZWQgdG8gbm90IHJlcXVpcmUgYSBwYXNzd29yZCB3aGVuIHdvcmtpbmcgb24gdGhpcyBjb21wdXRlci4iCiAgICBsZXQgbmV3X3BhY2thZ2UKCiAgICBjaGVja2JveC5pbm5lckhUTUw9ImhvdXJnbGFzc19lbXB0eSIKICAgIGNoZWNrYm94LmNsYXNzTGlzdC5hZGQoImJsaW5rIikKCiAgICBsb2dpbl9pZCA9PT0gImxvZ2luLXBhaWQiID8gZmlyZWJhc2UuYXV0aC5zaWduT3V0KGZpcmViYXNlLmF1dGguZ2V0QXV0aCgpKSA6IG51bGwKCiAgICBzd2l0Y2ggKGxvZ2luX2lkKSB7CiAgICAgIGNhc2UgImxvZ2luLW5vbmUiOgogICAgICAgIHNldF9sb2dpbl90eXBlKCkKICAgICAgICBjaGFuZ2U9dHJ1ZQogICAgICAgIG1lc3NhZ2UoewogICAgICAgICAgbWVzc2FnZTphdXRoX21lc3NhZ2UsCiAgICAgICAgICB0aXRsZToiQXV0aGVudGljYXRpb24gTWV0aG9kIENoYW5nZWQiLAogICAgICAgICAgc2Vjb25kczo4LAogICAgICAgICAgc2hvdzp0cnVlCiAgICAgICAgfSkKICAgICAgICBpZihCb29rU3RvcmFnZS5kYlR5cGUoKT09PSJvcmFjbGUiKXsKICAgICAgICAgICAgLy8gT3JhY2xlIG5vdCBhbGxvd2VkIHdpdGggdGhpcyBsb2dpbiB0eXBlCiAgICAgICAgICAgIHN3dGljaF9kYigib3JhY2xlIiwic3FsaXRlIikKICAgICAgICB9CiAgICAgICAgYnJlYWsKICAgICAgY2FzZSAibG9naW4tbG9jYWwiOgogICAgICAgIGF1dGhfbWVzc2FnZT0iWW91IGFyZSBub3cgbG9nZ2VkIGluIHRvIHRoaXMgY29tcHV0ZXIuICBJZiB5b3UgY2xvc2UgeW91ciBicm93c2VyLCB5b3Ugd2lsbCBuZWVkIHRvIHN1cHBseSB5b3VyIHBhc3N3b3JkIGFnYWluIHRvIGFjY2VzcyB5b3VyIHNhdmVkIHNldHRpbmdzLiIKICAgICAgICBuZXdfcGFja2FnZSA9IGF3YWl0IHNldF9sb2NhbF9wYXNzd29yZCgpCiAgICAgICAgaWYobmV3X3BhY2thZ2UucGFzc3dvcmQpewogICAgICAgICAgLy8gd2UgaGF2ZSBhIG5ldyBsb2NhbCBwYXNzd29yZC4gIFVzZSBpdCB0byBlbmNyeXB0IHZhbHVlcyBpbiBib29rU3RvcmFnZQogICAgICAgICAgc2V0X2xvZ2luX3R5cGUobmV3X3BhY2thZ2UucGFzc3dvcmQpCiAgICAgICAgICBCb29rU3RvcmFnZS5sb2NhbENhbmFyeShuY3J5cHQoImxvZ2dlZCBpbiIsQm9va1N0b3JhZ2UudG9rZW4oKSkpCiAgICAgICAgICBjaGFuZ2U9dHJ1ZQogICAgICAgICAgbWVzc2FnZSh7CiAgICAgICAgICAgIG1lc3NhZ2U6YXV0aF9tZXNzYWdlICwKICAgICAgICAgICAgdGl0bGU6IkF1dGhlbnRpY2F0aW9uIE1ldGhvZCBDaGFuZ2VkIiwKICAgICAgICAgICAgc2Vjb25kczo4LAogICAgICAgICAgICBzaG93OnRydWUKICAgICAgICAgIH0pCiAgICAgICAgICBpZihCb29rU3RvcmFnZS5kYlR5cGUoKT09PSJvcmFjbGUiKXsKICAgICAgICAgICAgLy8gT3JhY2xlIG5vdCBhbGxvd2VkIHdpdGggdGhpcyBsb2dpbiB0eXBlCiAgICAgICAgICAgIHN3dGljaF9kYigib3JhY2xlIiwic3FsaXRlIikKICAgICAgICB9CiAgCiAgICAgICAgfQogICAgICAgIGJyZWFrCiAgICAgIGNhc2UgImxvZ2luLWdhcyI6CiAgICAgICAgLy9jb25zb2xlLmxvZygiZ2V0dGluZyBkZXBsb3ltZW50IGlkIixCb29rU3RvcmFnZS5kZXBsb3ltZW50SWQoKSkKICAgICAgICAvLyBmaXJzdCBjaGVjayB0byBzZWUgaWYgd2UgaGF2ZSBhIHZhbGlkIHRva2VuCiAgICAgICAgaWYoIWV2dC5jdHJsS2V5KXsvL29ubHkgdHJ5aW5nIHRvIGNoZWNrIGV4aXN0aW5nIGNvbmZpZyBpcyBjdHJsIGlzIG5vdCBkb3duIHdoZW4gY2xpY2tlZAogICAgICAgICAgYXV0aF9tZXNzYWdlPSJZb3UgYXJlIG5vdyBsb2dnZWQgaW4gdXNpbmcgeW91ciBvd24gYXV0aGVudGljYXRpb24gc2VydmVyLiAgSWYgeW91IGNsb3NlIHlvdXIgYnJvd3NlciwgeW91IHdpbGwgbmVlZCB0byBzdXBwbHkgeW91ciBwYXNzd29yZCBhZ2FpbiB0byBhY2Nlc3MgeW91ciBzYXZlZCBzZXR0aW5ncy4iCiAgICAgICAgICBpZihnZXRfZnJvbV9ib29rX3N0b3JhZ2UoImRlcGxveW1lbnRJZCIpICYmIGdldF9mcm9tX2Jvb2tfc3RvcmFnZSgiZ2FzVG9rZW4iKSl7CiAgICAgICAgICAgICAgLy8gd2UgYWhhdmUgYSB0b2tlbiBhbmQgZGVwbG95bWVudCBpdCwgbGV0cyBzZWUgaWYgaXQgaXMgdmFsaWQgZmlzdC4uLgogICAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7CiAgICAgICAgICAgICAgICAgIG1vZGU6ICJjb25uZWN0IgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHNlcnZlcl9wb3N0KHBheWxvYWQsIGdldF9nYXNfZW5kcG9pbnQoKSkKICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSAiY29ubmVjdGVkIikgewogICAgICAgICAgICAgICAgICAvLyB3ZSBoYXZlIGNvbm5lY3RlZCBhbmQgd2UgYXJlIGRvbmUKICAgICAgICAgICAgICAgICAgY2hhbmdlPXRydWUKICAgICAgICAgICAgICAgICAgc2V0X2xvZ2luX3R5cGUodXVpZCgpKQogICAgICAgICAgICAgICAgICBnYXNfdG9fYm9va19zdG9yYWdlKHJlc3BvbnNlLGdldF9mcm9tX2Jvb2tfc3RvcmFnZSgiZGVwbG95bWVudElkIikpCiAgICAgICAgICAgICAgICAgIG1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTphdXRoX21lc3NhZ2UsCiAgICAgICAgICAgICAgICAgICAgICB0aXRsZToiQXV0aGVudGljYXRpb24gTWV0aG9kIENoYW5nZWQiLAogICAgICAgICAgICAgICAgICAgICAgc2Vjb25kczo4LAogICAgICAgICAgICAgICAgICAgICAgc2hvdzp0cnVlCiAgICAgICAgICAgICAgICAgIH0pCiAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9ICAgICAgICAKICAgICAgICAvLyBzZXQgYSBuZXcgcGFzc3dvcmQgaWYgbmVjZXNzYXJ5CiAgICAgICAgbmV3X3BhY2thZ2UgPSBhd2FpdCBzZXRfZ2FzX3Bhc3N3b3JkKCkKICAgICAgICBpZihuZXdfcGFja2FnZSAmJiBuZXdfcGFja2FnZS5zdGF0dXMgJiYgbmV3X3BhY2thZ2Uuc3RhdHVzPT09InN1Y2Nlc3MiKXsKICAgICAgICAgICAgQm9va1N0b3JhZ2UuZGVwbG95bWVudElkKG5ld19wYWNrYWdlLmRlcGxveW1lbnRfaWQpCiAgICAgICAgICAgIC8vIHdlIGhhdmUgYSBuZXcgaW5mb3JtYXRpb24gZm9yIGdhcyBhdXRoZW50aWNhdGlvbi4gIFVzZSBpdCB0byBlbmNyeXB0IHZhbHVlcyBpbiBib29rU3RvcmFnZQogICAgICAgICAgICBjaGFuZ2U9dHJ1ZQogICAgICAgICAgICBzZXRfbG9naW5fdHlwZShuZXdfcGFja2FnZS5wYXNzd29yZCkKICAgICAgICAgICAgQm9va1N0b3JhZ2UubG9jYWxDYW5hcnlCb29rU3RyYWdlPUJvb2tTdG9yYWdlLnRva2VuICAvLyB1c2VkIHRvIGhvbGQgdGhlIGxvY2FsLWxvZ2luIHRva2VuIHNvIHdlIGNhbiByZWNhbGwgaXQgCiAgICAgICAgICAgIG1lc3NhZ2UoewogICAgICAgICAgICBtZXNzYWdlOmF1dGhfbWVzc2FnZSwKICAgICAgICAgICAgdGl0bGU6IkF1dGhlbnRpY2F0aW9uIE1ldGhvZCBDaGFuZ2VkIiwKICAgICAgICAgICAgc2Vjb25kczo4LAogICAgICAgICAgICBzaG93OnRydWUKICAgICAgICAgICAgfSkKICAgIAogICAgICAgIH0KICAgICAgICAKICAgICAgICBicmVhayAgCiAgICAgIGNhc2UgImxvZ2luLXBhaWQiOgogICAgICAgIC8vY29uc29sZS5sb2coImZpcmViYXNlLWxvZ2luIikKICAgICAgICBjaGFuZ2UgPSB0cnVlIC8vIHJlbmRlcnMgdGhlIGNoZWNrIGJveAogICAgICAgIC8vIHdpbmRvdy5wYWlkU2VjdGlvbigpCiAgICAgICAgcGFpZFVzZXJJbmZvKCkKICAgICAgICBicmVhawogICAgfQogICAgY2hlY2tib3guY2xhc3NMaXN0LnJlbW92ZSgiYmxpbmsiKQogICAgY2hlY2tib3guaW5uZXJIVE1MPSJjaGVja19ib3hfb3V0bGluZV9ibGFuayIKCiAgICBpZihjaGFuZ2UpewogICAgICBCb29rU3RvcmFnZS5sb2dpblR5cGUobG9naW5faWQuc3BsaXQoIi0iKVsxXSkKICAgICAgLy8gY2xlYXIgb3RoZXIgY2hlY2ttYXJrcyAKICAgICAgZm9yIChib3ggb2YgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgiLiIgKyBjaGVja2JveC5kYXRhc2V0LnNldCkpIHsKICAgICAgICBib3guZ2V0RWxlbWVudHNCeVRhZ05hbWUoInNwYW4iKVswXS5pbm5lckhUTUwgPSAiY2hlY2tfYm94X291dGxpbmVfYmxhbmsiCiAgICAgICAgYm94Lm5leHRFbGVtZW50U2libGluZy5zdHlsZS5kaXNwbGF5ID0gIm5vbmUiCiAgICAgIH0KICAgICAgLy8gY2hlY2sgdGhlIGNvcnJlY3Qgb25lIAogICAgICBjaGVja2JveC5pbm5lckhUTUwgPSAiY2hlY2tfYm94IgogICAgICB0YWcoImNvbmZpZy0iICsgbG9naW5faWQpLnN0eWxlLmRpc3BsYXkgPSAiYmxvY2siCiAgICAgIAoKICAgICAgLy9kZWJ1Z2dlcgogICAgICBzZXRfYm9va19sYWJlbCgpICAKICAgICAgY29uZmlndXJlX2Jvb2soKSAgCiAgICB9CiAgICBmdW5jdGlvbiBzd3RpY2hfZGIoZnJvbV9kYix0b19kYil7CiAgICAgICAgLy8gY2hhbmdlcyBib29rc3Ryb2FnZSBkYnR5cGUgYW5kIHRoZSBjaGVja2JveC4gIGRvZXMgbm8gdmVyaWZpY2F0aW9uCiAgICAgICAgQm9va1N0b3JhZ2UuZGJUeXBlKHRvX2RiKQogICAgICAgIHRhZyhmcm9tX2RiKS5pbm5lckhUTUw9ImNoZWNrX2JveF9vdXRsaW5lX2JsYW5rIgogICAgICAgIHRhZyh0b19kYikuaW5uZXJIVE1MPSJjaGVja19ib3giCiAgICB9CiAgCiAgfQoKYXN5bmMgZnVuY3Rpb24gYWJhbmRvbl9tYWNoaW5lKCl7CiAgICAKICAgIGNvbnN0IGJ1dHRvbl9sYWJlbD0iWWVzLCBjbGVhciBhbGwgZGF0YS4iCiAgICBjb25zdCBidXR0b24gPSBhd2FpdCB1aV9tZXNzYWdlX2JveCgKICAgICAgICAiVGhpcyB3aWxsIGNsZWFyIGFsbCBkYXRhIGZyb20gdGhpcyBtYWNoaW5lLCByZXNldHRpbmcgaXQgYXMgaWYgbm8gb25lIGhhcyB1c2VkIHRoaXMgYm9vayBoZXJlLiAgQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIGNsZWFyIHRoZSBkYXRhPyAiLAogICAgICAgICJBcmUgeW91IHN1cmU/IiwKICAgICAgICBbYnV0dG9uX2xhYmVsLCAiT29wcywgZG9uJ3QgY2xlYXIgbXkgZGF0YS4iXQogICAgKQogICAgCiAgICBpZihidXR0b249PT1idXR0b25fbGFiZWwpewogICAgICAgIGxvY2FsU3RvcmFnZS5jbGVhcigpCiAgICAgICAgc2Vzc2lvblN0b3JhZ2UuY2xlYXIoKQogICAgICAgIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKQogICAgfQp9CgpmdW5jdGlvbiBzZXRfbG9naW5fdHlwZShwYXNzd29yZD0iU2FtdWVsIERhdmllcyIpewogICAgQm9va1N0b3JhZ2UuY2hhbmdlRW5jcnlwdGlvbktleShwYXNzd29yZCkKICAgIGlmKEJvb2tTdG9yYWdlLmlzUHJpdmF0ZUNvbXB1dGVyKCkpewogICAgICAgIEJvb2tTdG9yYWdlLnVwZGF0ZVN0b3JhZ2VUeXBlKEF1dG9TdG9yYWdlLlNUT1JBR0VfVFlQRS5MT0NBTCkKICAgIH1lbHNlewogICAgICAgIEJvb2tTdG9yYWdlLnVwZGF0ZVN0b3JhZ2VUeXBlKEF1dG9TdG9yYWdlLlNUT1JBR0VfVFlQRS5TRVNTSU9OKQogICAgfSAgCn0KCiAgCgphc3luYyBmdW5jdGlvbiBsb2dpbl9sb2NhbCgpewogICAgLy8gYWxsb3dzIHRoZSB1c2VyIHRvIHN1cHBseSB0aGUgcGFzc3dvcmQgZm9yIGEgbG9jYWwgbG9naW4gYW5kIHZlcmlmaWVzIGlmIGl0IGlzIGNvcnJlY3QKICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgbmV3IFByb21pc2UoCiAgICAgIChyZXNvbHZlLCByZWplY3QpPT57CiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQodWlfbW9kYWwoIkxvZ2luIHRvIHRoaXMgQ29tcHV0ZXIiLGxvZ2luX2xvY2FsX2Zvcm0ocmVzb2x2ZSkscmVzb2x2ZSkpCiAgICAgICAgdGFnKCJwd2QiKS5mb2N1cygpCiAgICAgIH0KICAgICkKICAgIHJldHVybiB2YWx1ZQogIAogICAgLy8gY3VycmVudGx5IG9ubHkgdXNlZCBoZXJlLCBidXQgY291bGQgYmUgdXNlZCBlbHNld2hlcmUuICB0aGVuIHdlIHdpbGwgbW92ZSBpdCBvdXQgb2YgdGhpcyBmbgogICAgZnVuY3Rpb24gbG9naW5fbG9jYWxfZm9ybShyZXNvbHZlID0gKCkgPT4geyB9LCByZWplY3QgPSAoKSA9PiB7IH0pIHsKICAgICAgY29uc3QgZm9ybSA9IHVpX2Zvcm0oImF1dGgtY29udGFpbmVyIHVpLWlubGluZS1ibG9jayIpCiAgICAgIAogICAgICBjb25zdCBwYXNzd29yZF9ibG9jayA9IHVpX2lucHV0X3Bhc3N3b3JkX3JldmVhbCgidWktaW5wdXQgdWktZnVsbC13aWR0aCIpCiAgICAgIGNvbnN0IHBhc3N3b3JkX2lucHV0ID0gcGFzc3dvcmRfYmxvY2suZ2V0RWxlbWVudHNCeVRhZ05hbWUoImlucHV0IilbMF0KICAgICAgcGFzc3dvcmRfaW5wdXQuaWQ9InB3ZCIKICAgICAgY29uc3QgZXJyb3JfbWVzc2FnZSA9IHVpX2RpdigidWktYmctY2xlYXIgZXJyb3ItbWVzc2FnZSAiKQogICAgICBjb25zdCBzdWJtaXQgPSB1aV9idG4oImxvZ2luIikKICAgICAgc3VibWl0LmNsYXNzTGlzdC5hZGQoIm10MyIpCiAgICAgIHN1Ym1pdC5vbmNsaWNrID0gKGUpID0+IHsKICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKQogICAgICAgICAgCiAgICAgICAgICBpZihwYXNzd29yZF9pbnB1dC52YWx1ZS5sZW5ndGg9PT0wKXsKICAgICAgICAgICAgZXJyb3JfbWVzc2FnZS5yZXBsYWNlQ2hpbGRyZW4odWlfc3BhbigiIiwgIlBhc3N3b3JkIGlzIHJlcXVpcmVkLiIpKQogICAgICAgICAgfWVsc2UgaWYoISBCb29rU3RvcmFnZS5sb2dpbihwYXNzd29yZF9pbnB1dC52YWx1ZSkpewogICAgICAgICAgICBlcnJvcl9tZXNzYWdlLnJlcGxhY2VDaGlsZHJlbih1aV9zcGFuKCIiLCAiVGhlIHBhc3N3b3JkIGluIGluY29ycmVjdC4iKSkKICAgICAgICAgIH1lbHNlewogICAgICAgICAgICAvLyBwYXNzZWQgYWxsIGNoZWNrcwogICAgICAgICAgICAvL3N1Ym1pdC5yZXBsYWNlQ2hpbGRyZW4odWlfbG9hZGluZygpKQogICAgICAgICAgICBzdWJtaXQuZGlzYWJsZWQgPSB0cnVlCgogICAgICAgICAgICBlcnJvcl9tZXNzYWdlLnJlcGxhY2VDaGlsZHJlbigpCiAgICAgICAgICAgIHRhZygib3ZlcmxheSIpLnJlbW92ZSgpCiAgICAgICAgICAgIHJlc29sdmUoInN1Y2Nlc3MiKQogIAogICAgICAgICAgfQogICAgICB9CiAgCiAgICAgIGNvbnN0IHN3aXRjaF9idG4gPSB1aV9idG4oIlN3aXRjaCB0byBObyBBdXRoZW50aWNhdGlvbiIpCiAgICAgIHN3aXRjaF9idG4uY2xhc3NMaXN0LmFkZCgibXQzIikKICAgICAgc3dpdGNoX2J0bi5vbmNsaWNrID0gKGUpID0+IHsKICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKQogICAgICAgICAgc2V0X2xvZ2luX3R5cGUoKQogICAgICAgICAgdGFnKCJvdmVybGF5IikucmVtb3ZlKCkKICAgICAgICAgIHJlc29sdmUoIm5vIGxvZ2luIikKICAgICAgfQogIAogICAgICBjb25zdCBvcj11aV9oMigiIiwiT1IiKQogICAgICBvci5zdHlsZS50ZXh0QWxpZ249ImNlbnRlciIKICAgICAgZm9ybS5hcHBlbmQoCiAgICAgICAgICB1aV9wKCIiLCJUaGlzIGJvb2sgaXMgY29uZmlndXJlZCBmb3IgTG9jYWwgTG9naW4uIFBsZWFzZSBzdXBwbHkgdGhlIHBhc3N3b3JkIHlvdSBjaG9zZSBwcmV2aW91c2x5IHRvIGFjY2VzcyB5b3VyIHNhdmVkIHNldHRpbmdzIikgICwKICAgICAgICAgIHVpX2xhYmVsKCIiLCAiUGFzc3dvcmQiKSwgdWlfYnIoKSwgcGFzc3dvcmRfYmxvY2ssIHVpX2JyKCksCiAgICAgICAgICBzdWJtaXQsCiAgICAgICAgICBlcnJvcl9tZXNzYWdlLAogICAgICAgICAgb3IsCiAgICAgICAgICB1aV9wKCIiLCdTd2l0Y2ggdG8gIk5vIGF1dGhlbnRpY2F0aW9uIiB0byBzdGFydCBmcm9tIHNjcmF0Y2guICBUaGlzIHdpbGwgY2xlYXIgYW55IHNhdmVkIHNldHRpbmdzIHlvdSBoYXZlLicpICAsCiAgICAgICAgICBzd2l0Y2hfYnRuCiAgICAgICkKICAgICAgcmV0dXJuIGZvcm0KICAgIH0KICB9CiAgCgogIAogIGFzeW5jIGZ1bmN0aW9uIGxvZ2luX2dhcygpewogICAgLy8gYWxsb3dzIHRoZSB1c2VyIHRvIHN1cHBseSB0aGUgcGFzc3dvcmQgZm9yIGEgbG9jYWwgbG9naW4gYW5kIHZlcmlmaWVzIGlmIGl0IGlzIGNvcnJlY3QKICAgIAogICAgLy8gZmlyc3QsIGNoZWNrIHRvIHNlZSBpZiB3ZSBhcmUgYWxyZWFkeSBsb2dnZWQgaW4KICAgIGlmKGdldF9mcm9tX2Jvb2tfc3RvcmFnZSgiZGVwbG95bWVudElkIikgJiYgZ2V0X2Zyb21fYm9va19zdG9yYWdlKCJnYXNUb2tlbiIpKXsKICAgICAgICAvLyB3ZSBhaGF2ZSBhIHRva2VuIGFuZCBkZXBsb3ltZW50IGl0LCBsZXRzIHNlZSBpZiBpdCBpcyB2YWxpZCBmaXN0Li4uCiAgICAgICAgY29uc3QgcGF5bG9hZCA9IHsKICAgICAgICAgICAgbW9kZTogImNvbm5lY3QiCiAgICAgICAgfQogICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgc2VydmVyX3Bvc3QocGF5bG9hZCkKICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSAiY29ubmVjdGVkIikgewoKICAgICAgICAgICAgc2V0X2xvZ2luX3R5cGUodXVpZCgpKS8vIGdlbmVyYXRlIGEgcGFzc3dvcmQgZm9yIHVzZSB3aXRoIGVuY3J5cHRpb24uICBJIGRvZXMgbm90IG5lZWQgdG8gYmUga25vd2FibGUgYmVjYXVzZSB0aGlzIGxvZ2luIHRpbWUgaXMgdmVyaWZpZWQgYXQgZ29vZ2xlIHNlcnZlcgogICAgICAgICAgICBnYXNfdG9fYm9va19zdG9yYWdlKHJlc3BvbnNlLCBnZXRfZnJvbV9ib29rX3N0b3JhZ2UoImRlcGxveW1lbnRJZCIpKQogICAgICAgICAgICBtZXNzYWdlKHsKICAgICAgICAgICAgICAgIG1lc3NhZ2U6IllvdSBhcmUgbm93IGxvZ2dlZCBpbiB1c2luZyB5b3VyIG93biBhdXRoZW50aWNhdGlvbiBzZXJ2ZXIuIiwKICAgICAgICAgICAgICAgIHRpdGxlOiJBdXRoZW50aWNhdGlvbiBNZXRob2QgQ2hhbmdlZCIsCiAgICAgICAgICAgICAgICBzZWNvbmRzOjgsCiAgICAgICAgICAgICAgICBzaG93OnRydWUKICAgICAgICAgICAgfSkKICAgICAgICAgICAgcmV0dXJuIHtzdGF0dXM6InN1Y2Nlc3MifQogICAgICAgIH0KICAgIH0KCiAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IG5ldyBQcm9taXNlKAogICAgICAocmVzb2x2ZSwgcmVqZWN0KT0+ewogICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kKHVpX21vZGFsKCJMb2dpbiB0byB5b3VyIEF1dGhlbnRpY2F0aW9uIFNlcnZlciIsbG9naW5fZ2FzX2Zvcm0ocmVzb2x2ZSkscmVzb2x2ZSkpCiAgICAgICAgdGFnKCJkZXBsLWlkIikuZm9jdXMoKQogICAgICB9CiAgICApCiAgICByZXR1cm4gdmFsdWUKICAKICAgIC8vIGN1cnJlbnRseSBvbmx5IHVzZWQgaGVyZSwgYnV0IGNvdWxkIGJlIHVzZWQgZWxzZXdoZXJlLiAgdGhlbiB3ZSB3aWxsIG1vdmUgaXQgb3V0IG9mIHRoaXMgZm4KICAgIGZ1bmN0aW9uIGxvZ2luX2dhc19mb3JtKHJlc29sdmUgPSAoKSA9PiB7IH0sIHJlamVjdCA9ICgpID0+IHsgfSkgewogICAgICBjb25zdCBmb3JtID0gdWlfZm9ybSgiYXV0aC1jb250YWluZXIgdWktaW5saW5lLWJsb2NrIikKICAKICAgICAgY29uc3Qgc3dpdGNoX2J0biA9IHVpX2J0bigiU3dpdGNoIHRvIE5vIEF1dGhlbnRpY2F0aW9uIikKICAgICAgc3dpdGNoX2J0bi5jbGFzc0xpc3QuYWRkKCJtdDMiKQogICAgICBzd2l0Y2hfYnRuLm9uY2xpY2sgPSAoZSkgPT4gewogICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpCiAgICAgICAgICBzZXRfbG9naW5fdHlwZSgibm9uZSIpCiAgICAgICAgICB0YWcoIm92ZXJsYXkiKS5yZW1vdmUoKQogICAgICAgICAgcmVzb2x2ZSgibm8gbG9naW4iKQogICAgICB9CiAgCiAgICAgIGNvbnN0IG9yPXVpX2gyKCIiLCJPUiIpCiAgICAgIG9yLnN0eWxlLnRleHRBbGlnbj0iY2VudGVyIgogICAgICBmb3JtLmFwcGVuZCgKICAgICAgICAgIGdhc19hdXRoZW50aWNhdGlvbl9ibG9jayhyZXNvbHZlKSwKICAgICAgICAgIG9yLAogICAgICAgICAgdWlfcCgiIiwnU3dpdGNoIHRvICJObyBhdXRoZW50aWNhdGlvbiIgdG8gc3RhcnQgZnJvbSBzY3JhdGNoLiAgVGhpcyB3aWxsIGNsZWFyIGFueSBzYXZlZCBzZXR0aW5ncyB0aGF0IG1heSBiZSBzdG9yZWQgb24gdGhpcyBtYWNoaW5lLiAgWW91IGNhbiBhbHdheXMgbG9nIGluIHRvIHlvdXIgYXV0aGVudGljYXRpb24gc2VydmVyIGxhdGVyIHRvIGFjY2VzcyB0aGUgd29yayBhbmQgc2V0dGluZ3Mgc2F2ZWQgdGhlcmUuJykgICwKICAgICAgICAgIHN3aXRjaF9idG4KICAgICAgKQogICAgICByZXR1cm4gZm9ybQogICAgfQogICAgCiAgCiAgfQoKCiAgCiAgYXN5bmMgZnVuY3Rpb24gc2V0X2xvY2FsX3Bhc3N3b3JkKCl7CiAgLy8gc2V0cyB0aGUgcGFzc3dvcmQgZm9yIGEgbG9jYWwgbG9naW4KICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgbmV3IFByb21pc2UoCiAgICAgIChyZXNvbHZlLCByZWplY3QpPT57CiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQodWlfbW9kYWwoIlNldCBMb2NhbCBQYXNzd29yZCIsc2V0X2xvY2FsX3Bhc3N3b3JkX2Zvcm0ocmVzb2x2ZSkscmVzb2x2ZSkpCiAgICAgICAgdGFnKCJwd2QiKS5mb2N1cygpCiAgICAgIH0KICAgICkKICAgIHJldHVybiB2YWx1ZQogIAogICAgLy8gY3VycmVudGx5IG9ubHkgdXNlZCBoZXJlLCBidXQgY291bGQgYmUgdXNlZCBlbHNld2hlcmUuICB0aGVuIHdlIHdpbGwgbW92ZSBpdCBvdXQgb2YgdGhpcyBmbgogICAgZnVuY3Rpb24gc2V0X2xvY2FsX3Bhc3N3b3JkX2Zvcm0ocmVzb2x2ZSA9ICgpID0+IHsgfSwgcmVqZWN0ID0gKCkgPT4geyB9KSB7CiAgICAgIGNvbnN0IGZvcm0gPSB1aV9mb3JtKCJhdXRoLWNvbnRhaW5lciB1aS1pbmxpbmUtYmxvY2siKQogICAgICBjb25zdCBwYXNzd29yZF9ibG9jayA9IHVpX2lucHV0X3Bhc3N3b3JkX3JldmVhbCgidWktaW5wdXQgdWktZnVsbC13aWR0aCIpCiAgICAgIGNvbnN0IHBhc3N3b3JkX2lucHV0ID0gcGFzc3dvcmRfYmxvY2suZ2V0RWxlbWVudHNCeVRhZ05hbWUoImlucHV0IilbMF0KICAgICAgcGFzc3dvcmRfaW5wdXQuaWQ9InB3ZCIKICAgICAgY29uc3Qgc3VibWl0ID0gdWlfYnRuKCJTZXQgUGFzc3dvcmQiKQogICAgICBjb25zdCBlcnJvcl9tZXNzYWdlID0gdWlfZGl2KCJ1aS1iZy1jbGVhciBlcnJvci1tZXNzYWdlICIpCiAgICAgIHN1Ym1pdC5jbGFzc0xpc3QuYWRkKCJtdDMiKQogICAgICBzdWJtaXQub25jbGljayA9IChlKSA9PiB7CiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCkKICAgICAgICAgIAogICAgICAgICAgaWYocGFzc3dvcmRfaW5wdXQudmFsdWUubGVuZ3RoPT09MCl7CiAgICAgICAgICAgIGVycm9yX21lc3NhZ2UucmVwbGFjZUNoaWxkcmVuKHVpX3NwYW4oIiIsICJQYXNzd29yZCBpcyByZXF1aXJlZC4iKSkKICAgICAgICAgIH1lbHNlewogICAgICAgICAgICAvLyBwYXNzZWQgYWxsIGNoZWNrcwogICAgICAgICAgICAvL3N1Ym1pdC5yZXBsYWNlQ2hpbGRyZW4odWlfbG9hZGluZygpKQogICAgICAgICAgICBzdWJtaXQuZGlzYWJsZWQgPSB0cnVlCiAgICAgICAgICAgIGVycm9yX21lc3NhZ2UucmVwbGFjZUNoaWxkcmVuKCkKICAgICAgICAgICAgdGFnKCJvdmVybGF5IikucmVtb3ZlKCkKICAgICAgICAgICAgcmVzb2x2ZSh7cGFzc3dvcmQ6cGFzc3dvcmRfaW5wdXQudmFsdWV9KQogICAgICAgICAgfQogICAgICB9CiAgICAgIGZvcm0uYXBwZW5kKAogICAgICAgICAgdWlfcCgiIiwiQ2hvb3NlIGEgcGFzc3dvcmQgdGhhdCB5b3Ugd2lsbCB1c2UgdG8gYXV0aGVudGljYXRlIG9uIHRoaXMgY29tcHV0ZXIuICAgV2UnbGwgdXNlIGl0IHRvIGVuY3J5cHQgeW91ciBzZXR0aW5ncyBhbmQgd29yayBzbyBldmVuIGlmIHNvbWVvbmUgZ2V0cyBhaG9sZCBvZiB0aGlzIGNvbXB1dGVyLCB0aGV5IHdvbnQgYmUgYWJsZSB0byByZWFkIHlvdXIgZGF0YS4iKSwKICAgICAgICAgIHVpX2xhYmVsKCIiLCAiUGFzc3dvcmQiKSwgdWlfYnIoKSwgcGFzc3dvcmRfYmxvY2ssIHVpX2JyKCksCiAgICAgICAgICBzdWJtaXQsCiAgICAgICAgICBlcnJvcl9tZXNzYWdlLAogICAgICApCiAgICAgIHJldHVybiBmb3JtCiAgICB9CiAgICAKICAKICB9CiAgCiAgCiAgCiAgCiAgYXN5bmMgZnVuY3Rpb24gc2V0X2dhc19wYXNzd29yZCgpewogICAgLy8gc2V0cyB0aGUgcGFzc3dvcmQgZm9yIGEgbG9jYWwgbG9naW4KICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCBuZXcgUHJvbWlzZSgKICAgICAgICAocmVzb2x2ZSwgcmVqZWN0KT0+ewogICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQodWlfbW9kYWwoIkNvbm5lY3QgdG8geW91ciBBdXRoZW50aWNhdGlvbiBTZXJ2ZXIiLHNldF9nYXNfcGFzc3dvcmRfZm9ybShyZXNvbHZlKSxyZXNvbHZlKSkKICAgICAgICAgIHRhZygiZGVwbC1pZCIpLmZvY3VzKCkKICAgICAgICB9CiAgICAgICkKICAgICAgcmV0dXJuIHZhbHVlCiAgICAKICAgICAgLy8gY3VycmVudGx5IG9ubHkgdXNlZCBoZXJlLCBidXQgY291bGQgYmUgdXNlZCBlbHNld2hlcmUuICB0aGVuIHdlIHdpbGwgbW92ZSBpdCBvdXQgb2YgdGhpcyBmbgogICAgICBmdW5jdGlvbiBzZXRfZ2FzX3Bhc3N3b3JkX2Zvcm0ocmVzb2x2ZSA9ICgpID0+IHsgfSwgcmVqZWN0ID0gKCkgPT4geyB9KSB7CiAgICAgICAgY29uc3QgZm9ybSA9IHVpX2Zvcm0oImF1dGgtY29udGFpbmVyIHVpLWlubGluZS1ibG9jayIpCiAgICAgICAgZm9ybS5hcHBlbmQoCiAgICAgICAgICAgIGdhc19hdXRoZW50aWNhdGlvbl9ibG9jayhyZXNvbHZlKQogICAgICAgICkKICAgICAgICByZXR1cm4gZm9ybQogICAgICB9CiAgICAgIAogICAgCiAgICB9CiAgICAKICAgIApmdW5jdGlvbiBnYXNfYXV0aGVudGljYXRpb25fYmxvY2socmVzb2x2ZSl7CiAgIAogICAgY29uc3QgZGVwbG95bWVudF9pZF9pbnB1dCA9IHVpX2lucHV0KCJ1aS1pbnB1dCB1aS1mdWxsLXdpZHRoIikKICAgIGRlcGxveW1lbnRfaWRfaW5wdXQuaWQ9ImRlcGwtaWQiCgogICAgY29uc3QgcGFzc3dvcmRfYmxvY2sgPSB1aV9pbnB1dF9wYXNzd29yZF9yZXZlYWwoInVpLWlucHV0IHVpLWZ1bGwtd2lkdGgiKQogICAgY29uc3QgcGFzc3dvcmRfaW5wdXQgPSBwYXNzd29yZF9ibG9jay5nZXRFbGVtZW50c0J5VGFnTmFtZSgiaW5wdXQiKVswXQogICAgY29uc3QgcGFzc3dvcmRfZGl2PXVpX2RpdigiIiwgdWlfbGFiZWwoIiIsICJQYXNzd29yZCIpLCB1aV9icigpLCBwYXNzd29yZF9ibG9jaykKICAgIHBhc3N3b3JkX2Rpdi5zdHlsZS5kaXNwbGF5PSJub25lIgoKICAgIGNvbnN0IHJlc2V0X2NvZGVfaW5wdXQgPSB1aV9pbnB1dCgidWktaW5wdXQgdWktZnVsbC13aWR0aCIpCiAgICBjb25zdCByZXNldF9kaXY9dWlfZGl2KCIiLCB1aV9sYWJlbCgiIiwgIlBhc3N3b3JkIFJlc2V0IENvZGUiKSwgdWlfYnIoKSwgcmVzZXRfY29kZV9pbnB1dCkKICAgIHJlc2V0X2Rpdi5zdHlsZS5kaXNwbGF5PSJub25lIgoKICAgIGNvbnN0IHJlc2V0ID0gdWlfYnRuKCJSZXNldCBQYXNzd29yZCIpICAgICAgIAogICAgcmVzZXQuc3R5bGUuZGlzcGxheT0ibm9uZSIKICAgIGNvbnN0IHJlc2V0X21lc3NhZ2UgPSB1aV9kaXYoInVpLWJnLWNsZWFyIikKCiAgICByZXNldC5jbGFzc0xpc3QuYWRkKCJtdDMiKQogICAgcmVzZXQub25jbGljayA9IGFzeW5jIChlKSA9PiB7CiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpCiAgICAgICAgcmVzZXQuZGlzYWJsZWQgPSB0cnVlCiAgICAgICAgY29uc3QgcGF5bG9hZCA9IHsKICAgICAgICAgICAgbW9kZTogInJlcXVlc3QtcmVzZXQiLAogICAgICAgICAgfQogICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBzZXJ2ZXJfcG9zdChwYXlsb2FkLGdldF9nYXNfZW5kcG9pbnQoZGVwbG95bWVudF9pZF9pbnB1dC52YWx1ZSkpCiAgICAgICAgICByZXNldC5kaXNhYmxlZCA9IGZhbHNlCiAgICAgICAgICAvL2NvbnNvbGUubG9nKCJyZXNwb25zZSIsIHJlc3BvbnNlKQogICAgICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gInN1Y2Nlc3MiKSB7CiAgICAgICAgICAgIHJlc2V0X21lc3NhZ2UucmVwbGFjZUNoaWxkcmVuKHVpX3NwYW4oIiIsICdBIHJlc2V0IGNvZGUgaGFzIGJlZW4gc2VudCB0byB0aGUgZW1haWwgYWRkcmVzcyBhdHRhY2hlZCB0byB0aGUgZGVwbG95bWVudCBpZCB5b3UgZW50ZXJlZC4gRW50ZXIgdGhlIGNvZGUgaW4gdGhlICJSZXNldCBDb2RlIiBmaWVsZCBhYm92ZSBhbmQgZW50ZXIgdGhlIHBhc3N3b3JkIHlvdSB3YW50IHRvIHVzZS4nKSkKICAgICAgICAgICAgcmVzZXRfZGl2LnN0eWxlLmRpc3BsYXk9ImJsb2NrIgogICAgICAgICAgICAvLyBtZXNzYWdlKHsKICAgICAgICAgICAgLy8gICBtZXNzYWdlOiBgQSByZXNldCBjb2RlIGhhcyBiZWVuIHNlbnQgdG8gdGhlIGVtYWlsIGFkZHJlc3MgYXR0YWNoZWQgdG8gdGhlIGRlcGxveW1lbnQgaWQgeW91IGVudGVyZC4gRW50ZXIgdGhlIGNvZGUgaW4gdGhlICJSZXNldCBDb2RlIiBmaWVsZCBiZWxvdyBhbmQgY2hvb3NlIGEgbmV3IHBhc3N3b3JkLiAgWW91IGNhbiBhbHNvIGNoYW5nZSB0aGUgdXNlcm5hbWUgaWYgeW91IGxpa2UuYCwKICAgICAgICAgICAgLy8gICB0aXRsZTogIlBhc3N3b3JkIiwKICAgICAgICAgICAgLy8gICBzZWNvbmRzOiA4LAogICAgICAgICAgICAvLyAgIHNob3c6IHRydWUKICAgICAgICAgICAgLy8gfSkKICAgICAgICAgICAgLy8gdGFnKCJyZXNldC1jb2RlIikuc3R5bGUuZGlzcGxheSA9IG51bGwKICAgICAgICAgICAgLy8gdGFnKCJyZXNldC1idXR0b24iKS5zdHlsZS5kaXNwbGF5ID0gIm5vbmUiCiAgICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gImZhaWx1cmUiKSB7CiAgICAgICAgICAgIG1lc3NhZ2UoewogICAgICAgICAgICAgIG1lc3NhZ2U6IHJlc3BvbnNlLm1lc3NhZ2UsCiAgICAgICAgICAgICAgdGl0bGU6ICJSZXNldCBSZXF1ZXN0IEZhaWxlZCIsCiAgICAgICAgICAgICAgc2Vjb25kczogOCwKICAgICAgICAgICAgICBraW5kOiAiZXJyb3IiLAogICAgICAgICAgICAgIHNob3c6IHRydWUKICAgICAgICAgICAgfSkKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG1lc3NhZ2UoewogICAgICAgICAgICAgIG1lc3NhZ2U6IHJlc3VsdCwKICAgICAgICAgICAgICB0aXRsZTogIlVuZXhwZWN0ZWQgRXJyb3IiLAogICAgICAgICAgICAgIHNlY29uZHM6IDgsCiAgICAgICAgICAgICAga2luZDogImVycm9yIiwKICAgICAgICAgICAgICBzaG93OiB0cnVlCiAgICAgICAgICAgIH0pCiAgICAgICAgICB9CiAgICAgIAoKICAgIH0KCiAgICBjb25zdCBzdWJtaXQgPSB1aV9idG4oIkNvbm5lY3QiKSAgICAgICAKICAgIGNvbnN0IGVycm9yX21lc3NhZ2UgPSB1aV9kaXYoInVpLWJnLWNsZWFyIGVycm9yLW1lc3NhZ2UgIikKICAgIHN1Ym1pdC5jbGFzc0xpc3QuYWRkKCJtdDMiKQogICAgc3VibWl0Lm9uY2xpY2sgPSBhc3luYyAoZSkgPT4gewogICAgICAgIGUucHJldmVudERlZmF1bHQoKQogICAgICAgIAogICAgICAgIGlmKGUudGFyZ2V0LmlubmVySFRNTD09PSJDb25uZWN0IiB8fCBlLnRhcmdldC5pbm5lckhUTUw9PT0iTG9naW4iKXsKICAgICAgICAgICAgLy8gaW5pdGlhbCBjb25uZWN0aW9uIHRvIHNlZSBpZiB0aGUgc2VydmVyIHJlc3BvbmRpbmcgICAgCiAgICAgICAgICAgIGlmKGRlcGxveW1lbnRfaWRfaW5wdXQudmFsdWUubGVuZ3RoPT09MCl7CiAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlLnJlcGxhY2VDaGlsZHJlbih1aV9zcGFuKCIiLCAiRGVwbG95bWVudCBJRCBpcyByZXF1aXJlZC4iKSkKICAgICAgICAgICAgfWVsc2UgaWYoZS50YXJnZXQuaW5uZXJIVE1MPT09IkxvZ2luIiAmJiBwYXNzd29yZF9pbnB1dC52YWx1ZS5sZW5ndGg9PT0wKXsKICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UucmVwbGFjZUNoaWxkcmVuKHVpX3NwYW4oIiIsICJQYXNzd29yZCBpcyByZXF1aXJlZC4iKSkKICAgICAgICAgICAgfWVsc2V7CiAgICAgICAgICAgICAgICAvLyBwYXNzZWQgYWxsIGNoZWNrcwogICAgICAgICAgICAgICAgLy9zdWJtaXQucmVwbGFjZUNoaWxkcmVuKHVpX2xvYWRpbmcoKSkKICAgICAgICAgICAgICAgIHN1Ym1pdC5kaXNhYmxlZCA9IHRydWUKICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UucmVwbGFjZUNoaWxkcmVuKCkKICAgICAgICAgICAgICAgIHJlc2V0LnN0eWxlLmRpc3BsYXk9Im5vbmUiCgogICAgICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHsKICAgICAgICAgICAgICAgICAgICBtb2RlOiAiY29ubmVjdCIKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZihwYXNzd29yZF9pbnB1dC52YWx1ZSl7CiAgICAgICAgICAgICAgICAgICAgcGF5bG9hZC5wYXNzd29yZD1wYXNzd29yZF9pbnB1dC52YWx1ZQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBpZiAocmVzZXRfY29kZV9pbnB1dC52YWx1ZSkgewogICAgICAgICAgICAgICAgICAgIHBheWxvYWQucmVzZXRUb2tlbiA9IHJlc2V0X2NvZGVfaW5wdXQudmFsdWUKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZyZWxheVNlcnZlclBvc3QocGF5bG9hZCxnZXRfZ2FzX2VuZHBvaW50KGRlcGxveW1lbnRfaWRfaW5wdXQudmFsdWUpKQogICAgICAgICAgICAgICAgICBzdWJtaXQuZGlzYWJsZWQgPSBmYWxzZQogICAgICAgICAgICAgICAgICBpZihyZXNwb25zZS5zdGF0dXM9PT0iZXJyb3IiKXsKICAgICAgICAgICAgICAgICAgICAvLyB0aGUgc2VydmVyIHdhcyBjb250YWN0ZWQgYnV0IGJlY2F1c2Ugd2UgaGF2ZSBub3Qgc2VudCBhIHBhc3N3b3JkLCB3ZSBjb3VsZCBub3QgeWV0IGxvZ2luCiAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZS5yZXBsYWNlQ2hpbGRyZW4odWlfc3BhbigiIiwgIlVuYWJsZSB0byBjb250YWN0IHNlcnZlciB1c2luZyB0aGUgRGVwbG95bWVudCBJRCBnaXZlbi4gIFBsZWFzZSB2ZXJpZnkgYW5kIHRyeSBhZ2Fpbi4iKSkKICAgICAgICAgICAgICAgICAgfWVsc2UgaWYocmVzcG9uc2Uuc3RhdHVzPT09ImFsaXZlIil7CiAgICAgICAgICAgICAgICAgICAgQm9va1N0b3JhZ2UuZGVwbG95bWVudElkKGRlcGxveW1lbnRfaWRfaW5wdXQudmFsdWUpCiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHNlcnZlciB3YXMgY29udGFjdGVkIGJ1dCBiZWNhdXNlIHdlIGhhdmUgbm90IHNlbnQgYSBwYXNzd29yZCwgd2UgY291bGQgbm90IHlldCBsb2dpbgogICAgICAgICAgICAgICAgICAgIHN1Ym1pdC5pbm5lckhUTUw9IkxvZ2luIgogICAgICAgICAgICAgICAgICAgIHBhc3N3b3JkX2Rpdi5zdHlsZS5kaXNwbGF5PSJibG9jayIKICAgICAgICAgICAgICAgICAgfWVsc2UgaWYocmVzcG9uc2Uuc3RhdHVzPT09ImludmFsaWQtcGFzc3dvcmQiKXsKICAgICAgICAgICAgICAgICAgICBCb29rU3RvcmFnZS5kZXBsb3ltZW50SWQoZGVwbG95bWVudF9pZF9pbnB1dC52YWx1ZSkKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICBpZihzdWJtaXQuaW5uZXJIVE1MPT09IkxvZ2luIil7CiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UucmVwbGFjZUNoaWxkcmVuKHVpX3NwYW4oIiIsICJJbnZhbGlkIFBhc3N3b3JkLiAgVHJ5IGFnYWluIG9yIHVzZSB0aGUgYnV0dG9uIGJlbG93IHRvIGNoYW5nZSB5b3VyIHBhc3N3b3JkLiIpKQogICAgICAgICAgICAgICAgICAgICAgICByZXNldC5zdHlsZS5kaXNwbGF5PSIiCiAgICAgICAgICAgICAgICAgICAgfWVsc2V7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1Ym1pdC5pbm5lckhUTUw9IkxvZ2luIgogICAgICAgICAgICAgICAgICAgICAgICBwYXNzd29yZF9kaXYuc3R5bGUuZGlzcGxheT0iYmxvY2siCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICB9ZWxzZSBpZihyZXNwb25zZS5zdGF0dXM9PT0iY29ubmVjdGVkIil7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBleGlzdGluZyB0b2tlbiB3YXMgdmFsaWQsIHNvIHdlIGFyZSBjb25uZWN0ZWQKICAgICAgICAgICAgICAgICAgICAgICAgdGFnKCJvdmVybGF5IikucmVtb3ZlKCkKICAgICAgICAgICAgICAgICAgICAgICAgZ2FzX3RvX2Jvb2tfc3RvcmFnZShyZXNwb25zZSwgZGVwbG95bWVudF9pZF9pbnB1dC52YWx1ZSkKICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh7c3RhdHVzOiJzdWNjZXNzIiwgZGVwbG95bWVudF9pZDpkZXBsb3ltZW50X2lkX2lucHV0LnZhbHVlfSkgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgfWVsc2V7CgogICAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICB9CiAgICAgICAgfWVsc2UgaWYoZS50YXJnZXQuaW5uZXJIVE1MPT09ImxvZ2luIil7CgogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gdWlfZGl2KCIiLAogICAgICAgIHVpX3AoIiIsJ0VudGVyIHRoZSAiRGVwbG95bWVudCBJRCIgdGhhdCB5b3UgY29waWVkIHdoZW4geW91IHNldCB1cCB5b3VyIGF1dGhlbnRpY2F0aW9uIHNlcnZlciBvbiBHb29nbGUgQXBwcyBTY3JpcHQuJyksCiAgICAgICAgdWlfbGFiZWwoIiIsICJEZXBsb3ltZW50IElEIiksIHVpX2JyKCksIGRlcGxveW1lbnRfaWRfaW5wdXQsIHVpX2JyKCksCiAgICAgICAgcGFzc3dvcmRfZGl2LAogICAgICAgIHJlc2V0X2RpdiwKICAgICAgICBzdWJtaXQsCiAgICAgICAgZXJyb3JfbWVzc2FnZSwKICAgICAgICByZXNldCwKICAgICAgICByZXNldF9tZXNzYWdlLAogICAgKQoKCn0gICAgCiAgICAKICAKICAKZnVuY3Rpb24gcGFzdGVfc2V0dGluZ3NfaW1wb3J0KCl7CiAgICAvLyBpbXBvcnRzIHN0ZGVudCBkYXRhIHRvIGEgYSB0ZXh0Ym94IGZvciBjb3B5IGFuZCBwYXN0aW5nCiAgCiAgbGV0IGRhdGE9dGFnKCJjb3B5LXBhc3RlIikudmFsdWUKCiAgdHJ5ewogICAgZGF0YT1KU09OLnBhcnNlKGRhdGEpCiAgfWNhdGNoKGUpewogICAgbWVzc2FnZSh7CiAgICAgIG1lc3NhZ2U6ICJUaGVyZSBpcyBhbiBlcnJvciBpbiB0aGUgaW1wb3J0IGRhdGEuIiwKICAgICAgdGl0bGU6ICJJbXBvcnQgRXJyb3IiLAogICAgICBzZWNvbmRzOiA4LAogICAgICBraW5kOiAiZXJyb3IiLAogICAgICBzaG93OiB0cnVlCiAgICB9KQogICAgcmV0dXJuCiAgfQogIC8vY29uc29sZS5sb2coImRhdGEiLCBkYXRhKQoKICAvL2NvbnNvbGUubG9nKCJnZXRfYm9va19kYl90eXBlKCkiLGdldF9ib29rX2RiX3R5cGUoKSkKICBvYmplY3RfdG9fYm9va3N0b3JhZ2UoZGF0YSkKICAvL2NvbnNvbGUubG9nKCJnZXRfYm9va19kYl90eXBlIHRhZyIsdGFnKGdldF9ib29rX2RiX3R5cGUoKSkpCgogIC8vIHJ1biB0aGUgc2FtZSBjb2RlIHRoYXQgZ2V0cyBydW4gd2hlbiB0aGUgc2V0dGluZ3MgcGFnZSBsb2FkcwogIGNob29zZV9jb25maWd1cmF0aW9uKHRhZyhnZXRfYm9va19kYl90eXBlKCkpKQogIGNob29zZV9sb2dpbl9tZXRob2QodGFnKCJsb2dpbi0iK0Jvb2tTdG9yYWdlLmxvZ2luVHlwZSgpKSkKICBmaWxsX3NlcnZlcl9jb25maWd1cmF0aW9uKCkgIAoKICBtZXNzYWdlKHsKICAgIG1lc3NhZ2U6ICJZb3VyIGluZm9ybWF0aW9uIGhhcyBiZWVuIHJlc3RvcmVkIiwKICAgIHRpdGxlOiAiSW1wb3J0IFN1Y2NlZWRlZCIsCiAgICBzZWNvbmRzOiA0LAogICAgc2hvdzogdHJ1ZQogIH0pCiAgCgoKfQoKZnVuY3Rpb24gcGFzdGVfc2V0dGluZ3NfZXhwb3J0KCl7CiAgY29uc3QgZGF0YT1ib29rc3RvcmFnZV90b19vYmplY3QoKQogIC8vY29uc29sZS5sb2coZGF0YSkKCiAgdGFnKCJjb3B5LXBhc3RlIikudmFsdWU9SlNPTi5zdHJpbmdpZnkoZGF0YSxudWxsLDIpCgogIG1lc3NhZ2UoewogICAgbWVzc2FnZTogIllvdXIgaW5mb3JtYXRpb24gY2FuIG5vdyBiZSBjb3BpZWQgb3IgZWRpdGVkLiIsCiAgICB0aXRsZTogIkV4cG9ydCBTdWNjZXNzZnVsIiwKICAgIHNlY29uZHM6IDgsCiAgICBzaG93OiB0cnVlCiAgfSkKCn0KCgpmdW5jdGlvbiBleHBvcnRfc3R1ZGVudF9kYXRhKCl7CiAgICAvLyBleHBvcnRzIHN0ZGVudCBkYXRhIHRvIGEgZmlsZSB0byBiZSBpbXBvcnRlZCB3aXRoIGltcG9ydF9zdHVkZW50X2RhdGUKICAgIGNvbnN0IHBhc3N3b3JkPXRhZygiaW1wb3J0LWV4cG9ydC1wYXNzd29yZCIpLnZhbHVlCiAgCiAgCiAgICBjb25zdCBkYXRhPWJvb2tzdG9yYWdlX3RvX29iamVjdCgpCiAgCiAgICBjb25zdCBkYXRhX2ZpbGU9KAogICAgICBwYXNzd29yZCA/IAogICAgICBuY3J5cHQoSlNPTi5zdHJpbmdpZnkoZGF0YSkscGFzc3dvcmQpCiAgICAgIDogCiAgICAgIEpTT04uc3RyaW5naWZ5KGRhdGEsbnVsbCwyKQogICAgKQogIAogICAgLy9jb25zb2xlLmxvZyhkYXRhX2ZpbGUpCiAgCiAgICBkb3dubG9hZF90ZXh0X2ZpbGUoZGF0YV9maWxlLCAic3FsLWJvb2stc2V0dGluZ3MuanNvbiIpCiAgICBtZXNzYWdlKHsKICAgICAgbWVzc2FnZTogIllvdXIgaW5mb3JtYXRpb24gZmlsZSBoYXMgYmVlbiBleHBvcnRlZC4iLAogICAgICB0aXRsZTogIkZpbGUgRG93bmxvYWRlZCIsCiAgICAgIHNlY29uZHM6IDgsCiAgICAgIHNob3c6IHRydWUKICAgIH0pCn0KCgpmdW5jdGlvbiBpbXBvcnRfc3R1ZGVudF9kYXRhKHJhd19kYXRhKXsKICAgIC8vIGltcG9ydHMgYSBmaWxlIHRoYXQgd2FzIGV4cG9ydGVkIHdpdGggZXhwb3J0X3N0ZHVlbnRfZGF0YQogICAgLy9jb25zb2xlLmxvZygiYXQgaW1wb3J0IHN0ZHVldG4gZGF0YSIpCiAgCiAgICBsZXQgZGF0YQogICAgdHJ5ey8vIHRyeSB0byBpbXBvcnQgd2l0aCBvdXQgcGFzc3dvcmQsIGp1c3QgaW4gY2FzZS4uLgogICAgICBkYXRhPUpTT04ucGFyc2UocmF3X2RhdGEpIAogICAgfSBjYXRjaChlKXsKICAgICAgLy8gY291bGQgbm90IGRlY3J5cHQgd2l0aGhvdXQgUFcsIHRyeSB3aXRoCiAgICAgIGRhdGE9ZGNyeXB0KHJhd19kYXRhLHRhZygiaW1wb3J0LWV4cG9ydC1wYXNzd29yZCIpLnZhbHVlKQogICAgICAKICAgICAgaWYoZGF0YT09PSJmYWlsZWQiKXsgIAogICAgICAgIG1lc3NhZ2UoewogICAgICAgICAgbWVzc2FnZTogIlRoZSBwYXNzd29yZCB5b3UgcHJvdmlkZWQgaXMgbm90IGNvcnJlY3QuICBQbGVhc2UgdHJ5IGFnYWluLiIsCiAgICAgICAgICB0aXRsZTogIkZpbGUgTm90IEltcG9ydGVkIiwKICAgICAgICAgIHNlY29uZHM6IDgsCiAgICAgICAgICBraW5kOiAiZXJyb3IiLAogICAgICAgICAgc2hvdzogdHJ1ZQogICAgICAgIH0pCiAgICAgICAgcmV0dXJuCiAgICAgIH0gICAgCiAgICB9CgogICAgb2JqZWN0X3RvX2Jvb2tzdG9yYWdlKGRhdGEpCgogIAogICAgLy8gcnVuIHRoZSBzYW1lIGNvZGUgdGhhdCBnZXRzIHJ1biB3aGVuIHRoZSBzZXR0aW5ncyBwYWdlIGxvYWRzCiAgICBjaG9vc2VfY29uZmlndXJhdGlvbih0YWcoZ2V0X2Jvb2tfZGJfdHlwZSgpKSkKICAgIGNob29zZV9sb2dpbl9tZXRob2QodGFnKCJsb2dpbi0iK0Jvb2tTdG9yYWdlLmxvZ2luVHlwZSgpKSkKICAgIGZpbGxfc2VydmVyX2NvbmZpZ3VyYXRpb24oKSAgCiAgCiAgICBtZXNzYWdlKHsKICAgICAgbWVzc2FnZTogIllvdXIgaW5mb3JtYXRpb24gaGFzIGJlZW4gcmVzdG9yZWQiLAogICAgICB0aXRsZTogIkZpbGUgSW1wb3J0ZWQiLAogICAgICBzZWNvbmRzOiA4LAogICAgICBzaG93OiB0cnVlCiAgICB9KQogIH0KCiAgZnVuY3Rpb24gZmlsbF9zZXJ2ZXJfY29uZmlndXJhdGlvbigpIHsKICAgIC8vIGNvbXB1dGVyIHNoYXJlZCBvciBwcml2YXRlCiAgICAKICAgIGlmKEJvb2tTdG9yYWdlLmlzUHJpdmF0ZUNvbXB1dGVyKCkpewogICAgICB0YWcoInByaXZhdGVfY29tcHV0ZXIiKS5jaGVja2VkPXRydWUKICAgIH1lbHNlewogICAgICB0YWcoInNoYXJlZF9jb21wdXRlciIpLmNoZWNrZWQ9dHJ1ZQogICAgfQogICAgCiAgICAKICAKICAgIC8vIHByZWZpbGwgdGhlIHNlcnZlciBjb25maWd1cmF0aW9uIHdpdGggd2hhdGV2ZXIgaXMga25vd24gYWJvdXQgaXQKICAgIC8vY29uc29sZS5sb2coInVybCIsIHVybCkKICAgIGNvbnN0IHVybF9wYXJhbXMgPSBnZXRfcGFyYW1zKCkKICAgIC8vY29uc29sZS5sb2coInVybF9wYXJhbXMiLCB1cmxfcGFyYW1zKQogICAgaWYgKHVybF9wYXJhbXMuZGF0YSkgewogICAgICAvLyBhIGRhdGEgYmxvY2sgaGFzIGJlZW4gc2VudCBpbiBsaW5rLCB0aGVzZSB0YWtlIHByZWNlZGVuY2UKICAgICAgZGF0YSA9IEpTT04ucGFyc2UoYXRvYih1cmxfcGFyYW1zLmRhdGEpKQogICAgICAvL2NvbnNvbGUubG9nKCJkYXRhIiwgZGF0YSkKICAgICAgdGFnKCJnYXMtdXNlcm5hbWUiKS52YWx1ZSA9IGRhdGEuZ2FzVXNlcm5hbWUKICAKICAgICAgaWYoZGF0YS5kZXBsb3ltZW50SWQpewogICAgICAgIHRhZygiZGVwbG95bWVudC1pZCIpLnZhbHVlID0gZGF0YS5kZXBsb3ltZW50SWQKICAgICAgICBCb29rU3RvcmFnZS5kZXBsb3ltZW50SWQ9ZGF0YS5kZXBsb3ltZW50SWQKICAgICAgfQogICAgfQogIAogICAgZGF0YV9mcm9tX2Jvb2tfc3RvcmFnZV90b19lbGVtZW50KGRvY3VtZW50LmJvZHkpICAKICAKICAKICB9CiAgCiAgCmZ1bmN0aW9uIGRhdGFfZnJvbV9ib29rX3N0b3JhZ2VfdG9fZWxlbWVudChlbGVtZW50PWRvY3VtZW50LmJvZHkpewogICAgLy8gbG9va3MgYXQgYWxsIGlucHV0IHRhZ3MgaW4gZWxlbWVudCBhbmQgdXNlcyB0aGllciBpZHMgdG8gdHJ5IHRvIHB1bGwgZGF0YSBmcm9tIGJvb2tTdG9yYWdlCiAgICBmb3IgKGNvbnN0IFt2YXJfbmFtZSxpZF0gb2YgT2JqZWN0LmVudHJpZXMoZ2V0X2lkX21hcF9mcm9tX2VsZW1lbnQoZWxlbWVudCkpKXsKICAgICAgdHJ5ewogICAgICAgIHRhZyhpZCkudmFsdWU9Qm9va1N0b3JhZ2VbdmFyX25hbWVdKCkKICAgICAgfWNhdGNoKGUpewogICAgICAgIC8vY29uc29sZS5lcnJvcihlKQogICAgICAgIC8vIG9uIGVycm9yLCBpZ25vcmUuICBJdCBtZWFucyB0aGVyZSBpcyBubyBtYXRjaGluZyB2YWx1ZSBpbiBib29rU3RvcmFnZQogICAgICB9CiAgICB9CiAgfQogIAogIGZ1bmN0aW9uIGluaXRfdXNlcl9wcm9maWxlKCl7CiAgICAvLyBzZXRzIHVwIHRoZSB1c2VyLXByb2ZpbGUgcGFnZSB3aGVuIGl0IGlzIGxvYWRlZAogICAgdGFnKGdldF9mcm9tX2Jvb2tfc3RvcmFnZSgiYWlUeXBlIiwgImdwdCIpKS5pbm5lckhUTUw9ImNoZWNrX2JveCIKICAgIHRhZyhnZXRfZnJvbV9ib29rX3N0b3JhZ2UoImRiVHlwZSIsICJzcWxpdGUiKSkuaW5uZXJIVE1MPSJjaGVja19ib3giCiAgICBzaG93X3NoYXJlZF9wcml2YXRlX2RldGFpbHMoKSAgIAogIAogICAgLy8gY2hlY2sgdGhlIGN1cnJlbnQgYXV0aGVudGljYXRpb24gbWV0aG9kCiAgICBjb25zdCBlbGVtID0gdGFnKCJsb2dpbi0iK0Jvb2tTdG9yYWdlLmxvZ2luVHlwZSgpKQogICAgZWxlbS5pbm5lckhUTUw9ImNoZWNrX2JveCIKICAgIGVsZW0ucGFyZW50Tm9kZS5uZXh0RWxlbWVudFNpYmxpbmcuc3R5bGUuZGlzcGxheT0iYmxvY2siCgogICAgLy8gc3BlYWNpYWwgdGhpbmdzIHdlIGRvIGZvciBlYWNoIGxvZ2luIHR5cGUKICAgIGlmIChCb29rU3RvcmFnZS5sb2dpblR5cGUoKSA9PT0gInBhaWQiKSB7CiAgICAgIC8vY29uc29sZS5sb2coInBhaWQiKTsKICAgICAgcGFpZFVzZXJJbmZvKCkgLy8gdGhpcyByZW5kZXJzIHRoZSBVSSBmb3IgdGhpcyBzZWN0aW9uCiAgICB9ZWxzZXsKICAgICAgLy8gZGVmYXVsdCBoYW5kbGluZwogICAgfQoKICAgIGZpbGxfc2VydmVyX2NvbmZpZ3VyYXRpb24oKQogICAgdGFnKCd1cGxvYWRJbnB1dCcpLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIGZ1bmN0aW9uKCkgewogICAgICAgICAgICBjb25zdCBmcj1uZXcgRmlsZVJlYWRlcigpOwogICAgICAgICAgICBmci5vbmxvYWQ9ZnVuY3Rpb24oKXtpbXBvcnRfc3R1ZGVudF9kYXRhKGZyLnJlc3VsdCl9CiAgICAgICAgICAgIGZyLnJlYWRBc1RleHQodGhpcy5maWxlc1swXSk7CiAgICB9KQogIH0KCmZ1bmN0aW9uIHNhdmVfc3R1ZGVudF9kYXRhKCl7CiAgLy8gc2F2ZXMgdGhlIHN0ZHVlbnQgZGF0YQogIGNvbnN0IHByb21pc2VzID0gW10KICBmb3IoY29uc3QgW2tleSx2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoZ2V0X2RhdGFfZnJvbV9lbGVtZW50KHRhZygic3R1ZGVudC1kYXRhIikpKSl7CiAgICAgIC8vIHNldCB2YWx1ZSBpbiBib29rIHN0b3JhZ2UKICAgICAgcHJvbWlzZXMucHVzaChCb29rU3RvcmFnZVtrZXldKHZhbHVlKSkKICB9CgogIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpPT57CiAgICBtZXNzYWdlKHsKICAgICAgbWVzc2FnZTogIlN1Y2Nlc3NmdWxseSBzYXZlZCB5b3VyIHVzZXIgaW5mb3JtYXRpb24uIiwKICAgICAgdGl0bGU6ICJVc2VyIEluZm9ybWF0aW9uIFNhdmVkIiwKICAgICAgc2Vjb25kczogOCwKICAgICAgc2hvdzogdHJ1ZQogICAgfSkKICB9KS5jYXRjaChlcnI9PnsKICAgIG1lc3NhZ2UoewogICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSwKICAgICAgdGl0bGU6ICJQcm9ibGVtIFNhdmluZyB2YWx1ZSB0byBzZXJ2ZXIiLAogICAgICBraW5kOiAiZXJyb3IiLAogICAgICBzaG93OiB0cnVlCiAgfSkKICB9KQp9CgoKYXN5bmMgZnVuY3Rpb24gZ2V0X2R3X3Rva2VuKCl7CiAgLy8gYW4gYXdhaXRhYmxlIGRpYWxvZyBib3gKICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgbmV3IFByb21pc2UoCiAgICAgIChyZXNvbHZlLCByZWplY3QpPT57CiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQodWlfbW9kYWwoIlJlYWQvV3JpdGUgVG9rZW4iLGdldF9kd190b2tlbl9mb3JtKHJlc29sdmUpLHJlc29sdmUpKQogICAgICAgIHRhZygidG9rZW4taW5wdXQiKS5mb2N1cygpCiAgICAgIH0KICAgICkKICAgIHJldHVybiB2YWx1ZQogIAogICAgLy8gY3VycmVudGx5IG9ubHkgdXNlZCBoZXJlLCBidXQgY291bGQgYmUgdXNlZCBlbHNld2hlcmUuICB0aGVuIHdlIHdpbGwgbW92ZSBpdCBvdXQgb2YgdGhpcyBmbgogICAgZnVuY3Rpb24gZ2V0X2R3X3Rva2VuX2Zvcm0ocmVzb2x2ZSA9ICgpID0+IHsgfSwgcmVqZWN0ID0gKCkgPT4geyB9KSB7CiAgICAgIGNvbnN0IGZvcm0gPSB1aV9mb3JtKCJhdXRoLWNvbnRhaW5lciB1aS1pbmxpbmUtYmxvY2siKQogICAgICBjb25zdCB0b2tlbl9pbnB1dCA9IHVpX2lucHV0KCJ1aS1pbnB1dCB1aS1mdWxsLXdpZHRoIG1iMiIpCiAgICAgIHRva2VuX2lucHV0LmlkPSJ0b2tlbi1pbnB1dCIKICAgICAgdG9rZW5faW5wdXQudmFsdWU9Z2V0X2Zyb21fYm9va19zdG9yYWdlKCJkd1Rva2VuIikKICAgICAgY29uc3QgYnV0dG9uX2xhYmVsPSJTYXZlIgogICAgICBjb25zdCBzdWJtaXQgPSB1aV9idG4oYnV0dG9uX2xhYmVsKQogICAgICBjb25zdCBlcnJvcl9tZXNzYWdlID0gdWlfZGl2KCJ1aS1iZy1jbGVhciBlcnJvci1tZXNzYWdlICIpCiAgICAgIGNvbnN0IG1lc3NhZ2U9dWlfcCgpCiAgICAgIG1lc3NhZ2UuaW5uZXJIVE1MPSdUaGUgZGF0YS53b3JsZCA8YSBocmVmPSJodHRwczovL2RhdGEud29ybGQvc2V0dGluZ3MvYWR2YW5jZWQiIHRhcmdldD0iYmxhbmsiPlJlYWQvV3JpdGUgdG9rZW48L2E+IGF1dGhvcml6ZXMgdGhpcyBzaXRlIHRvIGludGVyYWN0IHdpdGggZGF0YS53b3JsZCBvbiB5b3VyIGJlaGFsZiBzbyB5b3UgY2FuIGV4ZWN1dGUgcXVlcmllcyBhbmQgc2VlIHlvdXIgcmVzdWx0cy4nCiAgICAgIHN1Ym1pdC5vbmNsaWNrID0gYXN5bmMgKGUpID0+IHsKICAgICAgICBlcnJvcl9tZXNzYWdlLnJlcGxhY2VDaGlsZHJlbigpCiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpCgogICAgICAgIGlmKHRva2VuX2lucHV0LnZhbHVlLmxlbmd0aD09PTApewogICAgICAgICAgZXJyb3JfbWVzc2FnZS5yZXBsYWNlQ2hpbGRyZW4odWlfc3BhbigiIiwgIlRoZSB0b2tlbiBpcyByZXF1aXJlZC4iKSkKICAgICAgICB9ZWxzZXsKICAgICAgICAgIHN1Ym1pdC5yZXBsYWNlQ2hpbGRyZW4odWlfbG9hZGluZygpKQogICAgICAgICAgc3VibWl0LmRpc2FibGVkID0gdHJ1ZQogICAgICAgICAgY29uc3QgcmVzdWx0PWF3YWl0IGNoZWNrX2R3X2Nvbm5lY3Rpb24odG9rZW5faW5wdXQudmFsdWUpCiAgICAgICAgICBpZihyZXN1bHQuc3RhdHVzPT09InN1Y2Nlc3MiKXsKICAgICAgICAgICAgZXJyb3JfbWVzc2FnZS5yZXBsYWNlQ2hpbGRyZW4oKQogICAgICAgICAgICB0YWcoIm92ZXJsYXkiKS5yZW1vdmUoKQogICAgICAgICAgICByZXNvbHZlKHRva2VuX2lucHV0LnZhbHVlKQogICAgICAgICAgfWVsc2V7CiAgICAgICAgICAgIGVycm9yX21lc3NhZ2UucmVwbGFjZUNoaWxkcmVuKHVpX3NwYW4oIiIsIHJlc3VsdC5tZXNzYWdlKSkKICAgICAgICAgICAgc3VibWl0LnJlcGxhY2VDaGlsZHJlbihidXR0b25fbGFiZWwpCiAgICAgICAgICAgIHN1Ym1pdC5kaXNhYmxlZCA9IGZhbHNlCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGZvcm0uYXBwZW5kKAogICAgICAgIG1lc3NhZ2UsCiAgICAgICAgdWlfbGFiZWwoIiIsICJkYXRhLndvcmxkIFJlYWQvV3JpdGUgVG9rZW4iKSwgdWlfYnIoKSwKICAgICAgICB0b2tlbl9pbnB1dCwKICAgICAgICBzdWJtaXQsCiAgICAgICAgZXJyb3JfbWVzc2FnZQogICAgICApCiAgICAgIHJldHVybiBmb3JtCiAgICB9CiAgCiAgfQoKYXN5bmMgZnVuY3Rpb24gZ2V0X29yYWNsZV9jb25maWd1cmF0aW9uKCl7CiAgLy8gYW4gYXdhaXRhYmxlIGRpYWxvZyBib3gKICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgbmV3IFByb21pc2UoCiAgICAgIChyZXNvbHZlLCByZWplY3QpPT57CiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQodWlfbW9kYWwoIk9yYWNsZSBBdXRvbm9tb3VzIERhdGFiYXNlIixnZXRfb3JhY2xlX2NvbmZpZ3VyYXRpb25fZm9ybShyZXNvbHZlKSxyZXNvbHZlKSkKICAgICAgICB0YWcoInVybC1pbnB1dCIpLmZvY3VzKCkKICAgICAgfQogICAgKQogICAgcmV0dXJuIHZhbHVlCiAgCiAgICAvLyBjdXJyZW50bHkgb25seSB1c2VkIGhlcmUsIGJ1dCBjb3VsZCBiZSB1c2VkIGVsc2V3aGVyZS4gIHRoZW4gd2Ugd2lsbCBtb3ZlIGl0IG91dCBvZiB0aGlzIGZuCiAgICBmdW5jdGlvbiBnZXRfb3JhY2xlX2NvbmZpZ3VyYXRpb25fZm9ybShyZXNvbHZlID0gKCkgPT4geyB9LCByZWplY3QgPSAoKSA9PiB7IH0pIHsKICAgICAgY29uc3QgZm9ybSA9IHVpX2Zvcm0oImF1dGgtY29udGFpbmVyIHVpLWlubGluZS1ibG9jayIpCiAgICAgIGNvbnN0IHVybF9pbnB1dCA9IHVpX2lucHV0KCJ1aS1pbnB1dCB1aS1mdWxsLXdpZHRoIG1iMiIpCiAgICAgIHVybF9pbnB1dC5pZD0idXJsLWlucHV0IgogICAgICB1cmxfaW5wdXQudmFsdWU9Z2V0X2Zyb21fYm9va19zdG9yYWdlKCJvcmFjbGVVUkwiKQogICAgICBsZXQgYnV0dG9uX2xhYmVsCiAgICAgIGNvbnN0IGVycm9yX21lc3NhZ2UgPSB1aV9kaXYoInVpLWJnLWNsZWFyIGVycm9yLW1lc3NhZ2UiKQogICAgICBjb25zdCBtZXNzYWdlPXVpX3AoIm10MCIpCgogICAgICBjb25zdCB1c2VybmFtZV9pbnB1dCA9IHVpX2lucHV0KCJ1aS1pbnB1dCB1aS1mdWxsLXdpZHRoIG1iMiIpCiAgICAgIHVzZXJuYW1lX2lucHV0LmlkPSJ1c2VybmFtZS1pbnB1dCIKICAgICAgdXNlcm5hbWVfaW5wdXQudmFsdWU9IkFETUlOIgoKCiAgICAgIGNvbnN0IHBhc3N3b3JkX2Jsb2NrID0gdWlfaW5wdXRfcGFzc3dvcmRfcmV2ZWFsKCJ1aS1pbnB1dCB1aS1mdWxsLXdpZHRoIikKICAgICAgY29uc3QgcGFzc3dvcmRfaW5wdXQgPSBwYXNzd29yZF9ibG9jay5nZXRFbGVtZW50c0J5VGFnTmFtZSgiaW5wdXQiKVswXQogICAgICBwYXNzd29yZF9pbnB1dC5pZD0ib3JhY2xlLWFkbWluLXB3ZCIKCiAgICAgIGNvbnN0IHNjcmlwdF9tZXNzYWdlICA9ICAgdWlfZGl2KCJzY3JpcHQtbWVzc2FnZSIpCiAgICAgIHNjcmlwdF9tZXNzYWdlLmlkPSJzY3JpcHQtbWVzc2FnZSIKICAgICAgc2NyaXB0X21lc3NhZ2Uuc3R5bGUuZGlzcGxheT0ibm9uZSIKICAgICAgCiAgICAgIGNvbnN0IGF1dGhfYmxvY2sgPSAgdWlfZGl2KCIiLAogICAgICAgIHVpX2xhYmVsKCIiLCAiQWRtaW5pc3RyYXRvciBVc2VybmFtZSIpLCB1aV9icigpLHVzZXJuYW1lX2lucHV0LAogICAgICAgIHVpX2xhYmVsKCIiLCAiQWRtaW5pc3RyYXRvciBQYXNzd29yZCIpLCB1aV9icigpLHBhc3N3b3JkX2Jsb2NrLAogICAgICApCgogICAgICBjb25zdCB1cmxfYmxvY2sgPSB1aV9kaXYoIiIsdWlfbGFiZWwoIiIsICJPcmFjbGUgQ29ubmVjdGlvbiBVUkwiKSwgdWlfYnIoKSx1cmxfaW5wdXQpCgogICAgICBjb25zdCBjb25uZWN0aW9uX2Jsb2NrPXVpX2RpdigiIix1cmxfYmxvY2ssYXV0aF9ibG9jayxzY3JpcHRfbWVzc2FnZSkKCiAgICAgIGlmKGdldF9mcm9tX2Jvb2tfc3RvcmFnZSgibG9naW5UeXBlIik9PT0nZ2FzJyB8fCBnZXRfZnJvbV9ib29rX3N0b3JhZ2UoImxvZ2luVHlwZSIpPT09J3BhaWQnKXsKICAgICAgICAvL2xvZ2luIHR5cGUgYWxsb3dzIG9yYWNsZQogICAgICAgIG1lc3NhZ2UuaW5uZXJIVE1MPSdQcm92aWRlIHRoZSB0aGUgY29ubmVjdGlvbiBVUkwgZm9yIGFueSB1c2VyIG9uIHlvdXIgT3JhY2xlIEF1dG9ub21vdXMgRGF0YWJhc2UuICBZb3UgbWF5IG5lZWQgdG8gZm9sbG93IHRoZSA8YSB0YXJnZXQ9Il9ibGFuayIgaHJlZj0iaHR0cHM6Ly9nb29nLmxlLmNvbSI+aW5zdHJ1Y3Rpb25zIHRvIGNvbmZpZ3VyZSB5b3VyIE9yYWNsZSBBdXRvbm9tb3VzIERhdGFiYXNlPC9hPiB0byB3b3JrIHdpdGggdGhpcyBib29rLicKICAgICAgICBidXR0b25fbGFiZWw9IkluaXRpYXRlIENvbm5lY3Rpb24iCiAgICAgIH1lbHNlewogICAgICAgIC8vbG9naW4gdHlwZSBkb2VzIG5vdCBhbGxvdyBvcmFjbGUKICAgICAgICBtZXNzYWdlLmlubmVySFRNTD0nVG8gdXNlIHlvdXIgT3JhY2xlIEF1dG9ub21vdXMgRGF0YWJhc2UsIHlvdSBtdXN0IGNvbmZpZ3VyZSB0aGlzIGJvb2sgdG8gYXV0aGVudGljYXRlIHdpdGggZWl0aGVyICJZb3VyIE93biBBdXRoZW50aWNhdGlvbiBTZXJ2ZXIiIG9yIHdpdGggIlRoaXMgQm9va1wncyBBdXRoZW50aWNhdGlvbiBTZXJ2ZXIiLicKICAgICAgICBidXR0b25fbGFiZWw9Ik9LIgogICAgICAgIGNvbm5lY3Rpb25fYmxvY2suc3R5bGUuZGlzcGxheT0ibm9uZSIKICAgICAgfSAKCiAgICAgIGNvbnN0IHN1Ym1pdCA9IHVpX2J0bihidXR0b25fbGFiZWwpCiAgICAgIHN1Ym1pdC5zdHlsZS5tYXJnaW5Ub3A9IjFyZW0iCgogICAgICBzdWJtaXQub25jbGljayA9IGFzeW5jIChlKSA9PiB7CiAgICAgICAgLy9jb25zb2xlLmxvZygiY2xpY2tlZCIsIGUpCiAgICAgICAgZXJyb3JfbWVzc2FnZS5yZXBsYWNlQ2hpbGRyZW4oKQogICAgICAgIGUucHJldmVudERlZmF1bHQoKQoKICAgICAgICBzd2l0Y2goZS50YXJnZXQuaW5uZXJIVE1MKXsKICAgICAgICAgICAgY2FzZSAiT0siOgogICAgICAgICAgICAgICAgdGFnKCJvdmVybGF5IikucmVtb3ZlKCkKICAgICAgICAgICAgICAgIHJlc29sdmUobnVsbCkKICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgY2FzZSAiQ2xvc2UiOgogICAgICAgICAgICAgICAgaWYoc3VibWl0LmRhdGFzZXQucmVzdWx0PT09ImVycm9yIil7CiAgICAgICAgICAgICAgICAgICAgdGFnKCJvdmVybGF5IikucmVtb3ZlKCkKICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG51bGwpCiAgICAgICAgICAgICAgICB9ZWxzZXsKICAgICAgICAgICAgICAgICAgICB0YWcoIm92ZXJsYXkiKS5yZW1vdmUoKQogICAgICAgICAgICAgICAgICAgIHJlc29sdmUoImNvbm5lY3RlZCIpCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXR1cm4KICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgIGNhc2UgIkNvbmZpZ3VyZSBEYXRhc2V0cyI6CgogICAgICAgICAgICAgICAgaWYodXNlcm5hbWVfaW5wdXQudmFsdWUubGVuZ3RoPT09MCB8fCBwYXNzd29yZF9pbnB1dC52YWx1ZS5sZW5ndGg9PT0wKXsKICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlLnJlcGxhY2VDaGlsZHJlbih1aV9zcGFuKCIiLCAiVGhlIHVzZXJuYW1lIGFuZCBwYXNzd29yZCBhcmUgYm90aCByZXF1aXJlZC4iKSkKICAgICAgICAgICAgICAgIH1lbHNlewogICAgICAgICAgICAgICAgICAgIC8vIHdlIGhhdmUgYSB1c2VybmFtZSBhbmQgcGFzc3dvcmQsIGxldCdzIGNoZWNrIGlmIHRoZSBhcmUgdmFsaWQKICAgICAgICAgICAgICAgICAgICBzdWJtaXQucmVwbGFjZUNoaWxkcmVuKHVpX2xvYWRpbmcoKSkKICAgICAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNoZWNrX29yYWNsZV9jb25uZWN0aW9uKHVybF9pbnB1dC52YWx1ZSx1c2VybmFtZV9pbnB1dC52YWx1ZSxwYXNzd29yZF9pbnB1dC52YWx1ZSkKICAgICAgICAgICAgICAgICAgICAvL3Jlc3BvbnNlLmNvZGU9MTAgICAgCiAgICAgICAgICAgICAgICAgICAgc3dpdGNoKHJlc3BvbnNlLmNvZGUpewogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDM6IC8vQ3JlZGVudGlhbHMgc3VwcGxpZWQgYXJlIHVuYXV0aG9yaXplZCBhcyBzZXJ2ZXIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9rLCB3ZSBoYXZlIGF1dGhlbnRpY2F0ZWQgd2l0aCB0aGUgYWRtaW4gdXNlcm5hbWUgYW5kIHBhc3NvcmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybF9ibG9jay5zdHlsZS5kaXNwbGF5PSJub25lIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0aF9ibG9jay5zdHlsZS5kaXNwbGF5PSJibG9jayIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Ym1pdC5pbm5lckhUTUw9IkNvbmZpZ3VyZSBEYXRhc2V0cyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UucmVwbGFjZUNoaWxkcmVuKHVpX3NwYW4oIiIsICJUaGUgdXNlcm5hbWUgYW5kIHBhc3dvcmQgeW91IHN1cHBsaWVkIGFyZSB1bmFibGUgdG8gY29ubmVjdC4gIFBsZWFzZSBjaGVjayB0aGVtIGFuZCB0cnkgYWdhaW4uIikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDEwOiAvL2dvb2QgY3JlZGVudGlhbHMsIG5vdCBjb25maWd1cmVkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvaywgd2UgaGF2ZSBhdXRoZW50aWNhdGVkIHdpdGggdGhlIGFkbWluIHVzZXJuYW1lIGFuZCBwYXNzb3JkLCB0aW1lIHRvIGJ1bGlkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmxfYmxvY2suc3R5bGUuZGlzcGxheT0ibm9uZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dGhfYmxvY2suc3R5bGUuZGlzcGxheT0ibm9uZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcmlwdF9tZXNzYWdlLnN0eWxlLmRpc3BsYXk9ImJsb2NrIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VibWl0LnN0eWxlLmRpc3BsYXk9Im5vbmUiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJtaXQuZGF0YXNldC5yZXN1bHQgPSAgYXdhaXQgY29uZmlndXJlX2Jvb2tfZGIodXNlcm5hbWVfaW5wdXQudmFsdWUsIHBhc3N3b3JkX2lucHV0LnZhbHVlLCB1cmxfaW5wdXQudmFsdWUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJtaXQuc3R5bGUuZGlzcGxheT0iIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VibWl0LmlubmVySFRNTD0iQ2xvc2UiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OiAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKHJlc3BvbnNlLm1lc3NhZ2UpewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UucmVwbGFjZUNoaWxkcmVuKHVpX3NwYW4oIiIsIHJlc3BvbnNlLm1lc3NhZ2UpKSAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ZWxzZXsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZS5yZXBsYWNlQ2hpbGRyZW4odWlfc3BhbigiIiwgIlNvbWV0aGluZyB2ZXJ5IHVuZXhwZWN0ZWQgaGFwcGVuZWQuIikpICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9ICAgIAogICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgY2FzZSAiSW5pdGlhdGUgQ29ubmVjdGlvbiI6CiAgICAgICAgICAgICAgLy9kZWJ1Z2dlcgogICAgICAgICAgICAgICAgaWYodXJsX2lucHV0LnZhbHVlLmxlbmd0aD09PTApewogICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UucmVwbGFjZUNoaWxkcmVuKHVpX3NwYW4oIiIsICJUaGUgY29ubmVjdGlvbiBVUkwgaXMgcmVxdWlyZWQuIikpCiAgICAgICAgICAgICAgICB9ZWxzZXsKICAgICAgICAgICAgICAgICAgICAvLyB0cnkgdG8gdGFsayB0byB0aGUgc2VydmVyIGF0IHRoZSB1cmwKICAgICAgICAgICAgICAgICAgICBzdWJtaXQucmVwbGFjZUNoaWxkcmVuKHVpX2xvYWRpbmcoKSkKICAgICAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNoZWNrX29yYWNsZV9jb25uZWN0aW9uKHVybF9pbnB1dC52YWx1ZSx1c2VybmFtZV9pbnB1dC52YWx1ZSxwYXNzd29yZF9pbnB1dC52YWx1ZSkKICAgICAgICAgICAgICAgICAgICAvL3Jlc3BvbnNlLmNvZGU9MTAKICAgICAgICAgICAgICAgICAgICBzd2l0Y2gocmVzcG9uc2UuY29kZSl7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTA6IC8vY29ubmVjdGVkIGJ1dCBubyBkYXRxYWJhc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW5uZXJIVE1MID0gIlN1Y2Nlc3NmdWxseSBjb25uZWN0ZWQgdG8geW91ciBzZXJ2ZXIsIHlheSEgSXQgbG9va3MgYXMgdGhvdWdoIHdlIG5lZWQgdG8gY29uZmlndXJlIHRoaXMgYm9vaydzIGRhdGEgb24geW91ciBzZXJ2ZXIuICBQcm92aWRlIHRoZSBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIGJlbG93LiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybF9ibG9jay5zdHlsZS5kaXNwbGF5PSJub25lIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0aF9ibG9jay5zdHlsZS5kaXNwbGF5PSJibG9jayIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Ym1pdC5pbm5lckhUTUw9IkNvbmZpZ3VyZSBEYXRhc2V0cyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjA6IC8vZnVsbHkgY29uZmlndXJlZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnKCJvdmVybGF5IikucmVtb3ZlKCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoImNvbm5lY3RlZCIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OiAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygicmVzcG9uc2UiLHJlc3BvbnNlKSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Ym1pdC5pbm5lckhUTUw9IkluaXRpYXRlIENvbm5lY3Rpb24iCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihyZXNwb25zZS5tZXNzYWdlKXsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlLnJlcGxhY2VDaGlsZHJlbih1aV9zcGFuKCIiLCByZXNwb25zZS5tZXNzYWdlKSkgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfWVsc2V7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UucmVwbGFjZUNoaWxkcmVuKHVpX3NwYW4oIiIsICJTb21ldGhpbmcgdmVyeSB1bmV4cGVjdGVkIGhhcHBlbmVkLiIpKSAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIC8vIGlmKHJlc3BvbnNlLnN0YXR1cz0ic3VjY2VzcyIpewogICAgICAgICAgICAgICAgICAgIC8vICAgICAvL2NvbnNvbGUubG9nKCJvcmFjbGUgcmVzcG9uZGVkIikKICAgICAgICAgICAgICAgICAgICAvLyB9ZWxzZXsKICAgICAgICAgICAgICAgICAgICAvLyAgICAgLy9jb25zb2xlLmxvZygib3JhY2xlIGZhaWxlZCIpCiAgICAgICAgICAgICAgICAgICAgLy8gfQoKICAgICAgICAgICAgICAgICAgICAvLyBzdWJtaXQucmVwbGFjZUNoaWxkcmVuKHVpX2xvYWRpbmcoKSkKICAgICAgICAgICAgICAgICAgICAvLyBzdWJtaXQuZGlzYWJsZWQgPSB0cnVlCiAgICAgICAgICAgICAgICAgICAgLy8gY29uc3QgcmVzdWx0PWF3YWl0IGNoZWNrX2R3X2Nvbm5lY3Rpb24odXJsX2lucHV0LnZhbHVlKQogICAgICAgICAgICAgICAgICAgIC8vIGlmKHJlc3VsdC5zdGF0dXM9PT0ic3VjY2VzcyIpewogICAgICAgICAgICAgICAgICAgIC8vICAgICBlcnJvcl9tZXNzYWdlLnJlcGxhY2VDaGlsZHJlbigpCiAgICAgICAgICAgICAgICAgICAgLy8gICAgIHRhZygib3ZlcmxheSIpLnJlbW92ZSgpCiAgICAgICAgICAgICAgICAgICAgLy8gICAgIHJlc29sdmUodXJsX2lucHV0LnZhbHVlKQogICAgICAgICAgICAgICAgICAgIC8vIH1lbHNlewogICAgICAgICAgICAgICAgICAgIC8vICAgICBlcnJvcl9tZXNzYWdlLnJlcGxhY2VDaGlsZHJlbih1aV9zcGFuKCIiLCByZXN1bHQubWVzc2FnZSkpCiAgICAgICAgICAgICAgICAgICAgLy8gICAgIHN1Ym1pdC5yZXBsYWNlQ2hpbGRyZW4oYnV0dG9uX2xhYmVsKQogICAgICAgICAgICAgICAgICAgIC8vICAgICBzdWJtaXQuZGlzYWJsZWQgPSBmYWxzZQogICAgICAgICAgICAgICAgICAgIC8vIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCJidXR0b24gTGFiZWwgbm90IHJlY29nbml6ZWQiKSAgICAKICAgICAgICAgICAgICAgIHJlc29sdmUobnVsbCkKICAgICAgICAgICAgICAgIHJldHVybiAgICAgICAgICAgICAgICAKICAgICAgICB9CgogICAgICB9CiAgICAgIGZvcm0uYXBwZW5kKAogICAgICAgIG1lc3NhZ2UsCiAgICAgICAgY29ubmVjdGlvbl9ibG9jaywKICAgICAgICBzdWJtaXQsCiAgICAgICAgZXJyb3JfbWVzc2FnZQogICAgICApCiAgICAgIHJldHVybiBmb3JtCiAgICB9CiAgCiAgfQoKICBhc3luYyBmdW5jdGlvbiBjaGVja19vcmFjbGVfY29ubmVjdGlvbih1cmwsIHVzZXJuYW1lLCBwYXNzd29yZCl7CiAgICAvLyBhY2NlcHRzIGEgdG9rZW4gYW5kIGNoZWNrcyB0byBzZWUgaWYgd2UgY2FuIGNvbm5lY3QgdG8gZGF0YS53b3JsZAogICAgY29uc3QgcGF5bG9hZCA9IHsKICAgICAgICBtb2RlOiAiY2hlY2stb3JhY2xlLWNvbm5lY3Rpb24iLAogICAgICAgIHVybDogdXJsCiAgICB9CiAgICBpZih1c2VybmFtZSl7cGF5bG9hZC51c2VybmFtZT11c2VybmFtZX0KICAgIGlmKHBhc3N3b3JkKXtwYXlsb2FkLnBhc3N3b3JkPXBhc3N3b3JkfQogICAgY29uc29sZS5sb2coImNoZWNrX29yYWNsZV9jb25uZWN0aW9uIixwYXlsb2FkKQogICAgcmV0dXJuIGF3YWl0IHNlcnZlcl9wb3N0KHBheWxvYWQpCiAgfQoKICBhc3luYyBmdW5jdGlvbiBjaGVja19kd19jb25uZWN0aW9uKHRva2VuKXsKICAgIC8vIGFjY2VwdHMgYSB0b2tlbiBhbmQgY2hlY2tzIHRvIHNlZSBpZiB3ZSBjYW4gY29ubmVjdCB0byBkYXRhLndvcmxkCiAgICBjb25zdCB1cmwgPSBgaHR0cHM6Ly9hcGkuZGF0YS53b3JsZC92MC9zcWwvaHVkc29udS9odWRzb251YAogICAgY29uc3Qgb3B0aW9ucyA9IHsKICAgICAgaGVhZGVyczogewogICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsCiAgICAgICAgJ0F1dGhvcml6YXRpb24nOiAnQmVhcmVyICcgKyB0b2tlbiwKICAgICAgfSwKICAgICAgJ21ldGhvZCc6ICdQT1NUJywKICAgICAgJ2JvZHknOiBKU09OLnN0cmluZ2lmeSh7CiAgICAgICAgInF1ZXJ5IjogInNlbGVjdCAqIGZyb20gYXBwcm92YWwiLAogICAgICAgICJpbmNsdWRlVGFibGVTY2hlbWEiOiB0cnVlLAogICAgICAgICJxdWVyeVJ1blRva2VuIjogdXVpZCgpCiAgICAgIH0pCiAgICB9CiAgICBsZXQgcmVzcG9uc2UKICAgIHRyeSB7CiAgICAgIHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsLCBvcHRpb25zKQogICAgfSBjYXRjaCAoZSkgewogICAgICA7Y29uc29sZS5sb2coImh0dHAgZXJyb3IiLCBlLm1lc3NhZ2UpCiAgICAgIHJldHVybiB7c3RhdHVzOiJmYWlsdXJlIiwgbWVzc2FnZTplLm1lc3NhZ2V9CiAgICB9CiAgICB0cnl7CiAgICAgIGlmKHJlc3BvbnNlLnN0YXR1cz09PTIwMCl7CiAgICAgICAgLy8gT0stLWV2ZXJ5dGhpbmcgaXMgdmFsaWQKICAgICAgICByZXR1cm4ge3N0YXR1czoic3VjY2VzcyIsIG1lc3NhZ2U6IkNvbm5lY3Rpb24gc3VjY2Vzc2Z1bC4ifQogICAgICB9ZWxzZSBpZihyZXNwb25zZS5zdGF0dXM9PT00MDEpewogICAgICAgIC8vIHVuYXV0aG9yaXplZAogICAgICAgIHJldHVybiB7c3RhdHVzOiJmYWlsdXJlIiwgbWVzc2FnZToiVGhlIFJlYWQvV3JpdGUgdG9rZW4gd2FzIHJlamVjdGVkIGJ5IGRhdGEud29ybGQuICBQbGVhc2UgY2hlY2sgaXQgYW5kIHRyeSBhZ2Fpbi4ifQogICAgICB9ZWxzZSBpZihyZXNwb25zZS5zdGF0dXM9PT00MDQpewogICAgICAgIHJldHVybiB7c3RhdHVzOiJmYWlsdXJlIiwgbWVzc2FnZToiQ29udGFjdGVkIGRhdGEud29ybGQsIGJ1dCBjb3VsZCBub3QgZmluZCB0aGUgdmVyaWZpY2F0aW9uIHByb2plY3QuICBUaGlzIGlzIHVuZXhwZWN0ZWQuIn0KICAgICAgfQogICAgfWNhdGNoKGUpeyAgCiAgICAgIHJldHVybiB7c3RhdHVzOiJmYWlsdXJlIiwgbWVzc2FnZToiVW5leHBlY3RlZCBlcnJvcjogIiArIGUubWVzc2FnZX0KICAgIH0KICB9Cgpjb25zdCBwYWlkVXNlckluZm8gPSAoKCkgPT4gewogIGNvbnN0IHsKICAgIGdldEF1dGgsCiAgICBvbkF1dGhTdGF0ZUNoYW5nZWQsCiAgICBzaWduT3V0LAogIH0gPSBmaXJlYmFzZS5hdXRoCiAgY29uc3QgeyBnZXRGdW5jdGlvbnMsIGh0dHBzQ2FsbGFibGVGcm9tVVJMIH0gPSBmaXJlYmFzZS5mdW5jdGlvbnMKCiAgY29uc3QgYXV0aCA9IGdldEF1dGgoKTsKCiAgY29uc3QgbG9hZGluZyA9IHVpX2RpdigiY2VudGVyIiwKICAgIHVpX2xvYWRpbmcoIiIpCiAgKQoKICBmdW5jdGlvbiBwcm9maWxlKHVzZXIpIHsKICAgIHJldHVybiB1aV9kaXYoImNlbnRlciIsCiAgICAgIHVpX2RpdigidXNlci1pbmZvIiwKICAgICAgICB1aV9kaXYoInVzZXItaWNvbiIsIHVzZXIuZW1haWxbMF0udG9VcHBlckNhc2UoKSksCiAgICAgICAgdWlfZGl2KCJ1c2VyLWVtYWlsIiwgdXNlci5lbWFpbCksCiAgICAgICAgc2lnbk91dFVJKGF1dGgpLAogICAgICApLAogICAgKQogIH0KCiAgZnVuY3Rpb24gc2lnbk91dFVJKGZpcmViYXNlQXV0aCkgewogICAgY29uc3Qgc2lnbk91dEJ0biA9IHVpX2J0bl9lcnJvcigiU2lnbiBPdXQiKQogICAgc2lnbk91dEJ0bi5vbmNsaWNrID0gYXN5bmMgKCkgPT4gYXdhaXQgc2lnbk91dChmaXJlYmFzZUF1dGgpCiAgICByZXR1cm4gc2lnbk91dEJ0bgogIH0KCiAgLyoqCiAgICogVGhpcyBtZXRob2QgbXVzdCBiZSBjYWxsZWQgb25jZSB0aGUgdXNlciBoYXMgYmVlbiBhdXRoZW50aWNhdGVkCiAgICogQHJldHVybnMgYSB1cmwgc3RyaW5nIHRoYXQgY2FuIGJlIHVzZWQgdG8gbG9nIGluIHRoZSB1c2VyIHRvIHRoaWVyIHN0cmlwZSBhY2NvdW50IG9yIGFuIAogICAqIGVtcHR5IHN0cmluZyBpZiB0aGVyZSB3YXMgYW4gZXJyb3IgaW4gdGhlIGJhY2tlbmQuCiAgICovCiAgYXN5bmMgZnVuY3Rpb24gZ2V0U3RyaXBlUG9ydGFsTGluaygpIHsKICAgIHRyeSB7CiAgICAgIGNvbnN0IGZ1bmN0aW9ucyA9IGdldEZ1bmN0aW9ucygpCiAgICAgIGNvbnN0IGNyZWF0ZVBvcnRhbExpbmsgPSBodHRwc0NhbGxhYmxlRnJvbVVSTCgKICAgICAgICBmdW5jdGlvbnMsCiAgICAgICAgImh0dHBzOi8vdXMtd2VzdDMtcHJpbWUtbWljcm9uLTM3NDIxNS5jbG91ZGZ1bmN0aW9ucy5uZXQvZXh0LWZpcmVzdG9yZS1zdHJpcGUtcGF5bWVudHMtY3JlYXRlUG9ydGFsTGluayIKICAgICAgKTsKICAgICAgY29uc3QgeyBkYXRhIH0gPSBhd2FpdCBjcmVhdGVQb3J0YWxMaW5rKHsKICAgICAgICByZXR1cm5Vcmw6IHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4sCiAgICAgIH0pCiAgICAgIHJldHVybiBkYXRhLnVybAogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgcmV0dXJuICIiCiAgICB9CiAgfQoKCiAgYXN5bmMgZnVuY3Rpb24gcHJvZHVjdEFuZFByaWNlRGF0YSgpIHsKICAgIGNvbnN0IHByb2R1Y3RzID0gW10KICAgIGNvbnN0IHF1ZXJ5U25hcHNob3QgPSBhd2FpdCBnZXREb2NzKGNvbGxlY3Rpb24oZGIsICJwcm9kdWN0cyIpKTsKICAgIHF1ZXJ5U25hcHNob3QuZm9yRWFjaChhc3luYyAocHJvZHVjdERvYykgPT4gewogICAgICBjb25zdCBwcm9kdWN0X2RhdGEgPSBwcm9kdWN0RG9jLmRhdGEoKQogICAgICBpZiAocHJvZHVjdF9kYXRhLmFjdGl2ZSkgewogICAgICAgIHByb2R1Y3RzLnB1c2goewogICAgICAgICAgZG9jSUQ6IHByb2R1Y3REb2MuaWQsCiAgICAgICAgICAuLi5wcm9kdWN0X2RhdGEKICAgICAgICB9KQogICAgICB9CiAgICB9KQogICAgY29uc3QgcHJpY2VzX3NuYXBzaG90X3Byb21pc2UgPSBbXQogICAgZm9yIChjb25zdCBwcm9kdWN0IG9mIHByb2R1Y3RzKSB7CiAgICAgIHByaWNlc19zbmFwc2hvdF9wcm9taXNlLnB1c2goZ2V0RG9jcyhjb2xsZWN0aW9uKGRiLCAicHJvZHVjdHMiLCBwcm9kdWN0LmRvY0lELCAicHJpY2VzIikpKQogICAgfQogICAgY29uc3QgcHJvZHVjdF9hbmRfcHJpY2UgPSBbXQogICAgY29uc3Qgc25hcHNob3RzID0gYXdhaXQgUHJvbWlzZS5hbGwocHJpY2VzX3NuYXBzaG90X3Byb21pc2UpCiAgICBmb3IgKGNvbnN0IHByaWNlU25hcHNob3Qgb2Ygc25hcHNob3RzKSB7CiAgICAgIHByaWNlU25hcHNob3QuZm9yRWFjaChwcmljZURvYyA9PiB7CiAgICAgICAgY29uc3QgcHJpY2UgPSBwcmljZURvYy5kYXRhKCkKICAgICAgICBwcm9kdWN0X2FuZF9wcmljZS5wdXNoKHsKICAgICAgICAgIHByb2R1Y3Q6IHByb2R1Y3RzLmZpbmQoeCA9PiB4LmRvY0lEID09PSBwcmljZS5wcm9kdWN0KSwKICAgICAgICAgIHByaWNlOiBwcmljZSwKICAgICAgICAgIHByb2R1Y3RJRDogcHJpY2UucHJvZHVjdCwKICAgICAgICAgIHByaWNlSUQ6IHByaWNlRG9jLmlkLAogICAgICAgIH0pCiAgICAgIH0pCiAgICB9CiAgICByZXR1cm4gcHJvZHVjdF9hbmRfcHJpY2UKICB9CgogIGZ1bmN0aW9uIG1hbmFnZVB1cmNoYXNlQ2FyZChwcm9kdWN0X2RhdGEsIGRlc2NyaXB0aW9uLCBmZWF0dXJlcywgc3RyaXBlTGluaykgewogICAgY29uc3QgYnV5X2J0biA9IHVpX2J0bl9pbmZvKCJMb2FkaW5nIikKICAgIGJ1eV9idG4ucmVwbGFjZUNoaWxkcmVuKCJNYW5hZ2UiKQogICAgYnV5X2J0bi5vbmNsaWNrID0gKCkgPT4gd2luZG93LmxvY2F0aW9uLmFzc2lnbihzdHJpcGVMaW5rKQogICAgY29uc3QgaGVhZCA9IHVpX2NhcmRfaGVhZChwcm9kdWN0X2RhdGEubmFtZSwgdWlfZmlyc3RfbGV0dGVyX3VwcGVyX2Nhc2UocHJvZHVjdF9kYXRhLmRlc2NyaXB0aW9uKSkKICAgIGNvbnN0IGNhcmQgPSB1aV9jYXJkKGhlYWQsIGRlc2NyaXB0aW9uLCBidXlfYnRuLCBmZWF0dXJlcykKICAgIHJldHVybiBjYXJkCiAgfQoKICAvKioKICAgKiBnZXRzIHRoZSB1c2VycyBwdXJjaGFzZWQgcHJvZHVjdHMuIElmIHRoZSB1c2VyIGRpZCBub3QgYnV5IGFueXRoaW5nLCBvcgogICAqIHRoZSB1c2VyIGlzIG5vdCBzaWduZWQgaW4sIHRoZW4gdGhpcyBtZXRob2Qgd2lsbCByZXR1cm4gbnVsbC4gCiAgICogQHJldHVybnMKICAgKi8KICBhc3luYyBmdW5jdGlvbiBnZXRQdXJjaGFzZWRQcm9kdWN0cyh1c2VyKSB7CiAgICBpZiAoIXVzZXIpIHsgcmV0dXJuIFtdIH0KICAgIGNvbnN0IHVzZXJzU3Vic1NuYXBzaG90ID0gYXdhaXQgZ2V0RG9jcyhjb2xsZWN0aW9uKGRiLCAiY3VzdG9tZXJzIiwgdXNlci51aWQsICJzdWJzY3JpcHRpb25zIikpCiAgICBjb25zdCBzdWJzID0gW10KICAgIHVzZXJzU3Vic1NuYXBzaG90LmZvckVhY2goeCA9PiB4ID0gc3Vicy5wdXNoKHguZGF0YSgpKSkKICAgIHJldHVybiBzdWJzLm1hcCh4ID0+ICh7IC4uLngsIHByb2R1Y3RJRDogeC5pdGVtc1swXS5wbGFuLnByb2R1Y3QgfSkpCiAgfQoKICBhc3luYyBmdW5jdGlvbiBjaGVja291dF9wcm9kdWN0KHByaWNlX2lkLCBwcmljZV90eXBlLCB1c2VyKSB7CiAgICBpZiAoIXVzZXIpIHsKICAgICAgdXNlciA9IGF3YWl0IGdldFVzZXIoKQogICAgfQogICAgY29uc3QgY2hlY2tvdXRQYXlsb2FkID0gewogICAgICBwcmljZTogcHJpY2VfaWQsCiAgICAgIHN1Y2Nlc3NfdXJsOiB3aW5kb3cubG9jYXRpb24ub3JpZ2luLAogICAgICBjYW5jZWxfdXJsOiB3aW5kb3cubG9jYXRpb24ub3JpZ2luLAogICAgfQogICAgaWYgKHByaWNlX3R5cGUgPT09ICJvbmVfdGltZSIpIHsgY2hlY2tvdXRQYXlsb2FkLm1vZGUgPSAicGF5bWVudCIgfQoKICAgIGNvbnN0IGNoZWNrb3V0X3Nlc3Npb25fcmVmID0gY29sbGVjdGlvbihkYiwgImN1c3RvbWVycyIsIHVzZXIudWlkLCAiY2hlY2tvdXRfc2Vzc2lvbnMiKTsKICAgIGNvbnN0IHJlZiA9IGF3YWl0IGFkZERvYyhjaGVja291dF9zZXNzaW9uX3JlZiwgY2hlY2tvdXRQYXlsb2FkKQogICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHsKICAgICAgb25TbmFwc2hvdChyZWYsIChzbmFwKSA9PiB7CiAgICAgICAgY29uc3QgeyBlcnJvciwgdXJsIH0gPSBzbmFwLmRhdGEoKTsKICAgICAgICBpZiAoZXJyb3IpIHsKICAgICAgICAgIHJlc29sdmUoKQogICAgICAgICAgYWxlcnQoYEFuIGVycm9yIG9jY3VyZWQ6ICR7ZXJyb3IubWVzc2FnZX1gKTsKICAgICAgICB9CiAgICAgICAgaWYgKHVybCkgewogICAgICAgICAgLy8gV2UgaGF2ZSBhIFN0cmlwZSBDaGVja291dCBVUkwsIGxldCdzIHJlZGlyZWN0LgogICAgICAgICAgcmVzb2x2ZSgpCiAgICAgICAgICB3aW5kb3cubG9jYXRpb24uYXNzaWduKHVybCk7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0pCgoKCiAgfQoKICBmdW5jdGlvbiBtYXJrUHJvZHVjdHNBc1B1cmNoYXNlZChwcm9kdWN0c19hbmRfcHJpY2VzLCBwdXJjaGFzZWRfcHJvZHVjdHMpIHsKICAgIHJldHVybiBwcm9kdWN0c19hbmRfcHJpY2VzLm1hcChwcm9kdWN0X2FuZF9wcmljZSA9PiB7CiAgICAgIGNvbnN0IHB1cmNoYXNlZF9wcm9kdWN0ID0gcHVyY2hhc2VkX3Byb2R1Y3RzLmZpbmQocHVyY2hhc2VkX3Byb2R1Y3QgPT4gcHVyY2hhc2VkX3Byb2R1Y3QucHJvZHVjdElEID09PSBwcm9kdWN0X2FuZF9wcmljZS5wcm9kdWN0SUQpCiAgICAgIGlmIChwdXJjaGFzZWRfcHJvZHVjdCkgewogICAgICAgIHJldHVybiB7IC4uLnByb2R1Y3RfYW5kX3ByaWNlLCBwdXJjaGFzZWQ6IHRydWUsIH0KICAgICAgfQogICAgICByZXR1cm4gcHJvZHVjdF9hbmRfcHJpY2UKICAgIH0pCiAgfQoKICBmdW5jdGlvbiB1aVByb2R1Y3RzV2l0aFByaWNlcyhwcm9kdWN0X2FuZF9wcmljZSwgc3RyaXBlX2xpbmssIHVzZXIpIHsKICAgIGNvbnN0IGdyaWQgPSB1aV9ncmlkKCkKICAgIGZvciAoY29uc3QgeyBwcm9kdWN0LCBwcmljZSwgcHJpY2VJRCwgcHVyY2hhc2VkIH0gb2YgcHJvZHVjdF9hbmRfcHJpY2UpIHsKICAgICAgY29uc3QgZG9sbGFyX2Ftb3VudCA9IHByaWNlLnVuaXRfYW1vdW50IC8gMTAwCiAgICAgIGNvbnN0IHByb2R1Y3RfZmVhdHVyZXMgPSBPYmplY3QuZW50cmllcyhwcm9kdWN0Lm1ldGFkYXRhKQogICAgICAgIC5maWx0ZXIoKChba2V5XSkgPT4ga2V5Lm1hdGNoKC9mZWF0dXJlX1xkKy8pKSkKICAgICAgICAuc29ydCgoYSwgYikgPT4gYVswXSA+IGJbMF0pCiAgICAgICAgLm1hcCgoW18sIHZhbHVlXSkgPT4gdWlfZmlyc3RfbGV0dGVyX3VwcGVyX2Nhc2UodmFsdWUpKQoKICAgICAgbGV0IHByaWNlX2RpdgogICAgICBpZiAocHJpY2UudHlwZSA9PT0gIm9uZV90aW1lIikgewogICAgICAgIHByaWNlX2RpdiA9IHVpX2RpdigiY2VudGVyIHByaWNlLXRhZyIsICIkIiwgZG9sbGFyX2Ftb3VudCkKICAgICAgfSBlbHNlIHsKICAgICAgICBwcmljZV9kaXYgPSB1aV9kaXYoImNlbnRlciBwcmljZS10YWciLCAiJCIsIGRvbGxhcl9hbW91bnQsICIgLyAiLCBwcmljZS5pbnRlcnZhbCkKICAgICAgfQoKICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSB1aV9jYXJkX2JvZHlfaXRlbSgiIiwgcHJpY2VfZGl2LCB1aV9icigpKQogICAgICBjb25zdCBmZWF0dXJlcyA9IHVpX2RpdigiIiwgdWlfdWwoImNhcmQtdWwtcGFkZGluZyIsIC4uLnByb2R1Y3RfZmVhdHVyZXMubWFwKHggPT4gdWlfbGkoIiIsIHgpKSkpCgogICAgICBpZiAocHVyY2hhc2VkKSB7CiAgICAgICAgZ3JpZC5hcHBlbmQodWlfZ3JpZF9pdGVtKG1hbmFnZVB1cmNoYXNlQ2FyZChwcm9kdWN0LCBkZXNjcmlwdGlvbiwgZmVhdHVyZXMsIHN0cmlwZV9saW5rKSkpCiAgICAgIH0gZWxzZSB7CgogICAgICAgIGNvbnN0IGJ1eV9idG4gPSB1aV9idG4oIkJ1eSBOb3ciKQogICAgICAgIGJ1eV9idG4ub25jbGljayA9IGFzeW5jICgpID0+IHsKICAgICAgICAgIGJ1eV9idG4uZGlzYWJsZWQgPSB0cnVlCiAgICAgICAgICBidXlfYnRuLmlubmVyVGV4dCA9ICJIZWFkaW5nIHRvIGNoZWNrb3V0Li4uIgogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgYXdhaXQgY2hlY2tvdXRfcHJvZHVjdChwcmljZUlELCBwcmljZS50eXBlLCB1c2VyKQogICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgaWYgKGVycm9yID09PSAidXNlciBhYm9ydCIpIHsKICAgICAgICAgICAgICAvLyB0aGUgdXNlciBzaW1wbHkgcXVpdC4gU28gd2UgZG9udCBoYXZlIHRvIGRvIGFueXRoaW5nLgogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpCiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIGJ1eV9idG4uaW5uZXJUZXh0ID0gIkJ1eSBOb3ciCiAgICAgICAgICAgIGJ1eV9idG4uZGlzYWJsZWQgPSBmYWxzZQogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgY29uc3QgaGVhZCA9IHVpX2NhcmRfaGVhZChwcm9kdWN0Lm5hbWUsIHVpX2ZpcnN0X2xldHRlcl91cHBlcl9jYXNlKHByb2R1Y3QuZGVzY3JpcHRpb24pKQogICAgICAgIGNvbnN0IGNhcmQgPSB1aV9jYXJkKGhlYWQsIGRlc2NyaXB0aW9uLCBidXlfYnRuLCBmZWF0dXJlcykKICAgICAgICBncmlkLmFwcGVuZCh1aV9ncmlkX2l0ZW0oY2FyZCkpCiAgICAgIH0KICAgIH0KICAgIHJldHVybiBncmlkCiAgfQoKICByZXR1cm4gYXN5bmMgKCkgPT4gewogICAgY29uc3Qgcm9vdF9ub2RlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInVzZXItcHJvZmlsZS1hc2QiKQogICAgcm9vdF9ub2RlLnJlcGxhY2VDaGlsZHJlbihsb2FkaW5nKQogICAgY29uc3QgcHJvZHVjdF9hbmRfcHJpY2UgPSBhd2FpdCBwcm9kdWN0QW5kUHJpY2VEYXRhKCkKICAgIGF3YWl0IG5ldyBQcm9taXNlKCgpID0+IHsKICAgICAgb25BdXRoU3RhdGVDaGFuZ2VkKGF1dGgsIGFzeW5jICh1c2VyKSA9PiB7CiAgICAgICAgbGV0IHBfYV9wID0gcHJvZHVjdF9hbmRfcHJpY2UKICAgICAgICBsZXQgc3RyaXBlX2xpbmsgPSAiIgogICAgICAgIGlmICh1c2VyKSB7CiAgICAgICAgICBsZXQgcHVyY2hhc2VkX3Byb2R1Y3RzCiAgICAgICAgICBbcHVyY2hhc2VkX3Byb2R1Y3RzLCBzdHJpcGVfbGlua10gPSBhd2FpdCBQcm9taXNlLmFsbChbZ2V0UHVyY2hhc2VkUHJvZHVjdHModXNlciksIGdldFN0cmlwZVBvcnRhbExpbmsoKV0pCiAgICAgICAgICBwX2FfcCA9IG1hcmtQcm9kdWN0c0FzUHVyY2hhc2VkKHBfYV9wLCBwdXJjaGFzZWRfcHJvZHVjdHMpCiAgICAgICAgICByb290X25vZGUucmVwbGFjZUNoaWxkcmVuKHByb2ZpbGUodXNlcikpCiAgICAgICAgfWVsc2V7CiAgICAgICAgICByb290X25vZGUucmVwbGFjZUNoaWxkcmVuKCkKICAgICAgICB9CgogICAgICAgIGNvbnN0IHNpZ25JbkJ1dHRvbiA9IHVpX2J1dHRvbigidWktYnV0dG9uLWxpbmsiLCAiSGF2ZSBhbiBhY2NvdW50PyBTaWduIGluIikKICAgICAgICBzaWduSW5CdXR0b24ub25jbGljayA9IGdldFVzZXIKCiAgICAgICAgcm9vdF9ub2RlLmFwcGVuZCgKICAgICAgICAgIHVpUHJvZHVjdHNXaXRoUHJpY2VzKHBfYV9wLCBzdHJpcGVfbGluaywgdXNlciksCiAgICAgICAgICB1aV9kaXYoImNlbnRlciIsCiAgICAgICAgICAgIHVzZXIgPyAiIiA6IHNpZ25JbkJ1dHRvbiwKICAgICAgICAgICksCiAgICAgICAgKQogICAgICB9KQogICAgfSkKICB9Cn0pKCk=
person
navigate_before Table of Contents expand_more navigate_next
Loading Page hourglass_empty