From 30b9bed2fc907ca8686b14fe95de5ee70ba561d9 Mon Sep 17 00:00:00 2001 From: Georgy Okrokvertskhov Date: Sat, 10 Aug 2013 00:22:58 -0700 Subject: [PATCH] Added base64 encryption of the script files. Now script files are stored separately from templates in the ./scripts/ directory. test_windows_agent.py updated. Formatting in windows_agent.py fixed. Tracing and error capturing added to Set-LocalUserPassword. Function Set-LocalUserPassword removed as it is implemented by workflow means. Scripts now stored in one common folder. Scripts updated from murano-deployment. Templates updated to reflect new script names. Workflow template can reference multiple script files. These script files will be concatinated and encrypted with base64. Change-Id: Icb3532d2fb724bbb711c06086cb906bde22a380f Fixed flake8 reported issues. Change-Id: Icb3532d2fb724bbb711c06086cb906bde22a380f Fixed test failure after reformatting. Change-Id: Icb3532d2fb724bbb711c06086cb906bde22a380f Fixed issues with test. Revert back path selection for scripts folder. It is reasonable to have an ability to use own folder for custom workflows so script path is relative to template location. Change-Id: Icb3532d2fb724bbb711c06086cb906bde22a380f --- data/templates/agent/AskDnsIp.template | 2 +- data/templates/agent/CreatePrimaryDC.template | 23 +- .../agent/CreateSecondaryDC.template | 9 +- data/templates/agent/DeployWebApp.template | 11 +- data/templates/agent/InstallIIS.template | 10 +- .../agent/InstallMsSqlServer.template | 16 +- data/templates/agent/JoinDomain.template | 15 +- data/templates/agent/LeaveDomain.template | 2 +- data/templates/agent/SetPassword.template | 9 +- .../ConfigureEnvironmentForAOAG.template | 9 +- .../SqlServerCluster/FailoverCluster.template | 13 +- .../FailoverClusterPrerequisites.template | 14 +- .../InitializeAOAGPrimaryReplica.template | 18 +- .../InitializeAOAGSecondaryReplica.template | 18 +- .../InitializeAlwaysOn.template | 18 +- .../InstallSqlServerForAOAG.template | 14 +- .../agent/scripts/CopyPrerequisites.ps1 | 50 + data/templates/agent/scripts/DeployWebApp.ps1 | 148 ++ .../agent/scripts/Export-Function.ps1 | 61 + .../agent/scripts/Failover-Cluster.ps1 | 239 +++ .../scripts/Get-DnsListeningIpAddress.ps1 | 7 + .../agent/scripts/ImportCoreFunctions.ps1 | 65 + .../Install-RolePrimaryDomainController.ps1 | 43 + .../Install-RoleSecondaryDomainController.ps1 | 69 + .../agent/scripts/Install-SQLServer.ps1 | 84 + data/templates/agent/scripts/InstallIIS.ps1 | 72 + data/templates/agent/scripts/Join-Domain.ps1 | 65 + .../scripts/New-SqlServerSystemAccount.ps1 | 64 + data/templates/agent/scripts/OptionParser.ps1 | 280 ++++ .../agent/scripts/SQLServerForAOAG.ps1 | 538 +++++++ .../agent/scripts/SQLServerInstaller.ps1 | 1373 +++++++++++++++++ .../agent/scripts/SQLServerOptionParsers.ps1 | 367 +++++ .../agent/scripts/SetLocalUserPassword.ps1 | 37 + .../agent/scripts/Start-PowerShellProcess.ps1 | 151 ++ .../agent/scripts/Update-ServiceConfig.ps1 | 60 + muranoconductor/commands/windows_agent.py | 21 +- tests/conductor/test_windows_agent.py | 63 + 37 files changed, 3940 insertions(+), 118 deletions(-) create mode 100644 data/templates/agent/scripts/CopyPrerequisites.ps1 create mode 100644 data/templates/agent/scripts/DeployWebApp.ps1 create mode 100644 data/templates/agent/scripts/Export-Function.ps1 create mode 100644 data/templates/agent/scripts/Failover-Cluster.ps1 create mode 100644 data/templates/agent/scripts/Get-DnsListeningIpAddress.ps1 create mode 100644 data/templates/agent/scripts/ImportCoreFunctions.ps1 create mode 100644 data/templates/agent/scripts/Install-RolePrimaryDomainController.ps1 create mode 100644 data/templates/agent/scripts/Install-RoleSecondaryDomainController.ps1 create mode 100644 data/templates/agent/scripts/Install-SQLServer.ps1 create mode 100644 data/templates/agent/scripts/InstallIIS.ps1 create mode 100644 data/templates/agent/scripts/Join-Domain.ps1 create mode 100644 data/templates/agent/scripts/New-SqlServerSystemAccount.ps1 create mode 100644 data/templates/agent/scripts/OptionParser.ps1 create mode 100644 data/templates/agent/scripts/SQLServerForAOAG.ps1 create mode 100644 data/templates/agent/scripts/SQLServerInstaller.ps1 create mode 100644 data/templates/agent/scripts/SQLServerOptionParsers.ps1 create mode 100644 data/templates/agent/scripts/SetLocalUserPassword.ps1 create mode 100644 data/templates/agent/scripts/Start-PowerShellProcess.ps1 create mode 100644 data/templates/agent/scripts/Update-ServiceConfig.ps1 create mode 100644 tests/conductor/test_windows_agent.py diff --git a/data/templates/agent/AskDnsIp.template b/data/templates/agent/AskDnsIp.template index a9f6ee3..6d6bd40 100644 --- a/data/templates/agent/AskDnsIp.template +++ b/data/templates/agent/AskDnsIp.template @@ -1,6 +1,6 @@ { "Scripts": [ - "ZnVuY3Rpb24gR2V0LURuc0xpc3RlbmluZ0lwQWRkcmVzcyB7DQogICAgSW1wb3J0LU1vZHVsZSBEbnNTZXJ2ZXINCiAgICAoR2V0LUROU1NlcnZlciAtQ29tcHV0ZXJOYW1lIGxvY2FsaG9zdCkuU2VydmVyU2V0dGluZy5MaXN0ZW5pbmdJcEFkZHJlc3MgfA0KICAgICAgICBXaGVyZS1PYmplY3QgeyAkXyAtbWF0Y2ggIlxkezEsM31cLlxkezEsM31cLlxkezEsM31cLlxkezEsM30iIH0NCn0NCg==" + "Get-DnsListeningIpAddress.ps1" ], "Commands": [ { diff --git a/data/templates/agent/CreatePrimaryDC.template b/data/templates/agent/CreatePrimaryDC.template index f3b6867..92151e9 100644 --- a/data/templates/agent/CreatePrimaryDC.template +++ b/data/templates/agent/CreatePrimaryDC.template @@ -1,21 +1,16 @@ { "Scripts": [ - "RnVuY3Rpb24gU2V0LUxvY2FsVXNlclBhc3N3b3JkIHsKICAgIHBhcmFtICgKICAgICAgICBbU3RyaW5nXSAkVXNlck5hbWUsCiAgICAgICAgW1N0cmluZ10gJFBhc3N3b3JkLAogICAgICAgIFtTd2l0Y2hdICRGb3JjZQogICAgKQogICAgCiAgICB0cmFwIHsgU3RvcC1FeGVjdXRpb24gJF8gfQogICAgCiAgICBpZiAoKEdldC1XbWlPYmplY3QgV2luMzJfVXNlckFjY291bnQgLUZpbHRlciAiTG9jYWxBY2NvdW50ID0gJ1RydWUnIEFORCBOYW1lPSckVXNlck5hbWUnIikgLWVxICRudWxsKSB7CiAgICAgICAgdGhyb3cgIlVuYWJsZSB0byBmaW5kIGxvY2FsIHVzZXIgYWNjb3VudCAnJFVzZXJOYW1lJyIKICAgIH0KICAgIAogICAgaWYgKCRGb3JjZSkgewogICAgICAgIFdyaXRlLUxvZyAiQ2hhbmdpbmcgcGFzc3dvcmQgZm9yIHVzZXIgJyRVc2VyTmFtZScgdG8gJyoqKioqJyIgIyA6KQogICAgICAgIChbQURTSV0gIldpbk5UOi8vLi8kVXNlck5hbWUiKS5TZXRQYXNzd29yZCgkUGFzc3dvcmQpCiAgICB9CiAgICBlbHNlIHsKICAgICAgICBXcml0ZS1Mb2dXYXJuaW5nICJZb3UgYXJlIHRyeWluZyB0byBjaGFuZ2UgcGFzc3dvcmQgZm9yIHVzZXIgJyRVc2VyTmFtZScuIFRvIGRvIHRoaXMgcGxlYXNlIHJ1biB0aGUgY29tbWFuZCBhZ2FpbiB3aXRoIC1Gb3JjZSBwYXJhbWV0ZXIuIgogICAgICAgICRVc2VyQWNjb3VudAogICAgfQp9CgoKCkZ1bmN0aW9uIEluc3RhbGwtUm9sZVByaW1hcnlEb21haW5Db250cm9sbGVyCnsKPCMKLlNZTk9QU0lTCkNvbmZpZ3VyZSBub2RlJ3MgbmV0d29yayBhZGFwdGVycy4KQ3JlYXRlIGZpcnN0IGRvbWFpbiBjb250cm9sbGVyIGluIHRoZSBmb3Jlc3QuCgouRVhBTVBMRQpQUz4gSW5zdGFsbC1Sb2xlUHJpbWFyeURvbWFpbkNvbnRyb2xsZXIgLURvbWFpbk5hbWUgYWNtZS5sb2NhbCAtU2FmZU1vZGVQYXNzd29yZCAiUEBzc3cwcmQiCgpJbnN0YWxsIEROUyBhbmQgQUREUywgY3JlYXRlIGZvcmVzdCBhbmQgZG9tYWluICdhY21lLmxvY2FsJy4KU2V0IERDIHJlY292ZXJ5IG1vZGUgcGFzc3dvcmQgdG8gJ1BAc3N3MHJkJy4KIz4KCQoJcGFyYW0KCSgKCQlbU3RyaW5nXQoJCSMgTmV3IGRvbWFpbiBuYW1lLgoJCSREb21haW5OYW1lLAoJCQoJCVtTdHJpbmddCgkJIyBEb21haW4gY29udHJvbGxlciByZWNvdmVyeSBtb2RlIHBhc3N3b3JkLgoJCSRTYWZlTW9kZVBhc3N3b3JkCgkpCgoJdHJhcCB7IFN0b3AtRXhlY3V0aW9uICRfIH0KCiAgICAgICAgIyBBZGQgcmVxdWlyZWQgd2luZG93cyBmZWF0dXJlcwoJQWRkLVdpbmRvd3NGZWF0dXJlV3JhcHBlciBgCgkJLU5hbWUgIkROUyIsIkFELURvbWFpbi1TZXJ2aWNlcyIsIlJTQVQtREZTLU1nbXQtQ29uIiBgCgkJLUluY2x1ZGVNYW5hZ2VtZW50VG9vbHMgYAogICAgICAgIC1Ob3RpZnlSZXN0YXJ0CgoKCVdyaXRlLUxvZyAiQ3JlYXRpbmcgZmlyc3QgZG9tYWluIGNvbnRyb2xsZXIgLi4uIgoJCQoJJFNNQVAgPSBDb252ZXJ0VG8tU2VjdXJlU3RyaW5nIC1TdHJpbmcgJFNhZmVNb2RlUGFzc3dvcmQgLUFzUGxhaW5UZXh0IC1Gb3JjZQoJCQoJSW5zdGFsbC1BRERTRm9yZXN0IGAKCQktRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgCgkJLVNhZmVNb2RlQWRtaW5pc3RyYXRvclBhc3N3b3JkICRTTUFQIGAKCQktRG9tYWluTW9kZSBEZWZhdWx0IGAKCQktRm9yZXN0TW9kZSBEZWZhdWx0IGAKCQktTm9SZWJvb3RPbkNvbXBsZXRpb24gYAoJCS1Gb3JjZSBgCgkJLUVycm9yQWN0aW9uIFN0b3AgfCBPdXQtTnVsbAoKCVdyaXRlLUxvZyAiV2FpdGluZyBmb3IgcmVib290IC4uLiIJCQojCVN0b3AtRXhlY3V0aW9uIC1FeGl0Q29kZSAzMDEwIC1FeGl0U3RyaW5nICJDb21wdXRlciBtdXN0IGJlIHJlc3RhcnRlZCB0byBmaW5pc2ggZG9tYWluIGNvbnRyb2xsZXIgcHJvbW90aW9uLiIKIwlXcml0ZS1Mb2cgIlJlc3RhcmluZyBjb21wdXRlciAuLi4iCiMJUmVzdGFydC1Db21wdXRlciAtRm9yY2UKfQo=" + "ImportCoreFunctions.ps1", + "Install-RolePrimaryDomainController.ps1" ], "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, - { - "Name": "Install-RolePrimaryDomainController", - "Arguments": { - "DomainName": "$domain", - "SafeModePassword": "$recoveryPassword" - } - } + { + "Name": "Install-RolePrimaryDomainController", + "Arguments": { + "DomainName": "$domain", + "SafeModePassword": "$recoveryPassword" + } + } ], "RebootOnCompletion": 1 } \ No newline at end of file diff --git a/data/templates/agent/CreateSecondaryDC.template b/data/templates/agent/CreateSecondaryDC.template index a5ad7f4..6b492f2 100644 --- a/data/templates/agent/CreateSecondaryDC.template +++ b/data/templates/agent/CreateSecondaryDC.template @@ -1,14 +1,9 @@ { "Scripts": [ - "RnVuY3Rpb24gSW5zdGFsbC1Sb2xlU2Vjb25kYXJ5RG9tYWluQ29udHJvbGxlcg0Kew0KPCMNCi5TWU5PUFNJUw0KSW5zdGFsbCBhZGRpdGlvbmFsIChzZWNvbmRhcnkpIGRvbWFpbiBjb250cm9sbGVyLg0KDQojPg0KCXBhcmFtDQoJKA0KCQlbU3RyaW5nXQ0KCQkjIERvbWFpbiBuYW1lIHRvIGpvaW4gdG8uDQoJCSREb21haW5OYW1lLA0KCQkNCgkJW1N0cmluZ10NCgkJIyBEb21haW4gdXNlciB3aG8gaXMgYWxsb3dlZCB0byBqb2luIGNvbXB1dGVyIHRvIGRvbWFpbi4NCgkJJFVzZXJOYW1lLA0KCQkNCgkJW1N0cmluZ10NCgkJIyBVc2VyJ3MgcGFzc3dvcmQuDQoJCSRQYXNzd29yZCwNCgkJDQoJCVtTdHJpbmddDQoJCSMgRG9tYWluIGNvbnRyb2xsZXIgcmVjb3ZlcnkgbW9kZSBwYXNzd29yZC4NCgkJJFNhZmVNb2RlUGFzc3dvcmQNCgkpDQoNCgl0cmFwIHsgU3RvcC1FeGVjdXRpb24gJF8gfQ0KCQ0KCSRDcmVkZW50aWFsID0gTmV3LUNyZWRlbnRpYWwgLVVzZXJOYW1lICIkRG9tYWluTmFtZVwkVXNlck5hbWUiIC1QYXNzd29yZCAkUGFzc3dvcmQNCgkJDQoJIyBBZGQgcmVxdWlyZWQgd2luZG93cyBmZWF0dXJlcw0KCUFkZC1XaW5kb3dzRmVhdHVyZVdyYXBwZXIgYA0KCQktTmFtZSAiRE5TIiwiQUQtRG9tYWluLVNlcnZpY2VzIiwiUlNBVC1ERlMtTWdtdC1Db24iIGANCgkJLUluY2x1ZGVNYW5hZ2VtZW50VG9vbHMgYA0KICAgICAgICAgICAgICAgIC1Ob3RpZnlSZXN0YXJ0DQoJCQ0KCQ0KICAgICAgICBXcml0ZS1Mb2cgIkFkZGluZyBzZWNvbmRhcnkgZG9tYWluIGNvbnRyb2xsZXIgLi4uIg0KICAgIA0KCSRTTUFQID0gQ29udmVydFRvLVNlY3VyZVN0cmluZyAtU3RyaW5nICRTYWZlTW9kZVBhc3N3b3JkIC1Bc1BsYWluVGV4dCAtRm9yY2UNCg0KCUluc3RhbGwtQUREU0RvbWFpbkNvbnRyb2xsZXIgYA0KCQktRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgDQoJCS1TYWZlTW9kZUFkbWluaXN0cmF0b3JQYXNzd29yZCAkU01BUCBgDQoJCS1DcmVkZW50aWFsICRDcmVkZW50aWFsIGANCgkJLU5vUmVib290T25Db21wbGV0aW9uIGANCgkJLUZvcmNlIGANCgkJLUVycm9yQWN0aW9uIFN0b3AgfCBPdXQtTnVsbA0KDQoJV3JpdGUtTG9nICJXYWl0aW5nIGZvciByZXN0YXJ0IC4uLiINCiMJU3RvcC1FeGVjdXRpb24gLUV4aXRDb2RlIDMwMTAgLUV4aXRTdHJpbmcgIkNvbXB1dGVyIG11c3QgYmUgcmVzdGFydGVkIHRvIGZpbmlzaCBkb21haW4gY29udHJvbGxlciBwcm9tb3Rpb24uIg0KIwlXcml0ZS1Mb2cgIlJlc3RhcnRpbmcgY29tcHV0ZXIgLi4uIg0KIwlSZXN0YXJ0LUNvbXB1dGVyIC1Gb3JjZQ0KfQ0K" + "ImportCoreFunctions.ps1", + "Install-RoleSecondaryDomainController.ps1" ], "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, { "Name": "Install-RoleSecondaryDomainController", "Arguments": { diff --git a/data/templates/agent/DeployWebApp.template b/data/templates/agent/DeployWebApp.template index c8d3552..16ead07 100644 --- a/data/templates/agent/DeployWebApp.template +++ b/data/templates/agent/DeployWebApp.template @@ -1,14 +1,9 @@ { "Scripts": [ - "DQpmdW5jdGlvbiBSZWdpc3Rlci1XZWJBcHAgew0KPCMNCi5MSU5LUw0KDQpodHRwOi8vd3d3Lmlpcy5uZXQvbGVhcm4vbWFuYWdlL3Bvd2Vyc2hlbGwvcG93ZXJzaGVsbC1zbmFwLWluLWNyZWF0aW5nLXdlYi1zaXRlcy13ZWItYXBwbGljYXRpb25zLXZpcnR1YWwtZGlyZWN0b3JpZXMtYW5kLWFwcGxpY2F0aW9uLXBvb2xzDQojPg0KCXBhcmFtICgNCgkJW1N0cmluZ10gJFNvdXJjZSwNCgkJW1N0cmluZ10gJFBhdGggPSAiQzpcaW5ldHB1Ylx3d3dyb290IiwNCgkJW1N0cmluZ10gJE5hbWUgPSAiIiwNCgkJW1N0cmluZ10gJFVzZXJuYW1lID0gIiIsDQoJCVtTdHJpbmddICRQYXNzd29yZCA9ICIiDQoJKQ0KDQoJSW1wb3J0LU1vZHVsZSBXZWJBZG1pbmlzdHJhdGlvbg0KCQ0KCWlmICgkTmFtZSAtZXEgIiIpIHsNCgkJJE5hbWUgPSBAKFtJTy5QYXRoXTo6R2V0RGlyZWN0b3J5TmFtZSgkU291cmNlKSAtc3BsaXQgJ1xcJylbLTFdDQoJCWlmICgkTmFtZSAtZXEgInd3d3Jvb3QiKSB7DQoJCQl0aHJvdygiQXBwbGljYXRpb24gcG9vbCBuYW1lIGNvdWxkbid0IGJlICd3d3dyb290Jy4iKQ0KCQl9DQoJfQ0KCWVsc2Ugew0KCQkkUGF0aCA9IFtJTy5QYXRoXTo6Q29tYmluZSgkUGF0aCwgJE5hbWUpDQoJfQ0KDQoJQ29weS1JdGVtIC1QYXRoICRTb3VyY2UgLURlc3RpbmF0aW9uICRQYXRoIC1SZWN1cnNlIC1Gb3JjZQ0KCQ0KDQoJIyBDcmVhdGUgbmV3IGFwcGxpY2F0aW9uIHBvb2wNCiAgICAkQXBwUG9vbCA9IE5ldy1XZWJBcHBQb29sIC1OYW1lICROYW1lIC1Gb3JjZQ0KICAgICMkQXBwUG9vbCA9IEdldC1JdGVtICJJSVM6XEFwcFBvb2xzXCROYW1lIg0KICAgICRBcHBQb29sLm1hbmFnZWRSdW50aW1lVmVyc2lvbiA9ICd2NC4wJw0KICAgICRBcHBQb29sLm1hbmFnZWRQaXBlbGluZU1vZGUgPSAnQ2xhc3NpYycNCiAgICAkQXBwUG9vbC5wcm9jZXNzTW9kZWwubG9hZFVzZXJQcm9maWxlID0gJHRydWUNCiAgICAkQXBwUG9vbC5wcm9jZXNzTW9kZWwubG9nb25UeXBlID0gJ0xvZ29uQmF0Y2gnDQogICAgDQoJI1NldCBJZGVudGl0eSB0eXBlDQoJaWYgKCRVc2VybmFtZSAtZXEgIiIpIHsNCgkJJEFwcFBvb2wucHJvY2Vzc01vZGVsLmlkZW50aXR5VHlwZSA9ICdBcHBsaWNhdGlvblBvb2xJZGVudGl0eScNCgl9DQoJZWxzZSB7DQoJICAgICRBcHBQb29sLnByb2Nlc3NNb2RlbC5pZGVudGl0eVR5cGUgPSAnU3BlY2lmaWNVc2VyJw0KCSAgICAkQXBwUG9vbC5wcm9jZXNzTW9kZWwudXNlck5hbWUgPSAkVXNlcm5hbWUNCgkgICAgJEFwcFBvb2wucHJvY2Vzc01vZGVsLnBhc3N3b3JkID0gJFBhc3N3b3JkDQoJICAgICRBcHBQb29sIHwgU2V0LUl0ZW0NCgl9DQoNCg0KICAgICMgQ3JlYXRlIFdlYnNpdGUNCiAgICAkV2ViU2l0ZSA9IE5ldy1XZWJTaXRlIC1OYW1lICROYW1lIC1Qb3J0IDgwIC1Ib3N0SGVhZGVyICROYW1lIC1QaHlzaWNhbFBhdGggJFBhdGggLUZvcmNlDQogICAgIyRXZWJTaXRlID0gR2V0LUl0ZW0gIklJUzpcU2l0ZXNcJE5hbWUiDQogICAgDQoJIyBTZXQgdGhlIEFwcGxpY2F0aW9uIFBvb2wNCiAgICBTZXQtSXRlbVByb3BlcnR5ICJJSVM6XFNpdGVzXCROYW1lIiAnQXBwbGljYXRpb25Qb29sJyAkTmFtZQ0KICAgIA0KCSNUdXJuIG9uIERpcmVjdG9yeSBCcm93c2luZw0KICAgICNTZXQtV2ViQ29uZmlndXJhdGlvblByb3BlcnR5IC1GaWx0ZXIgJy9zeXN0ZW0ud2ViU2VydmVyL2RpcmVjdG9yeUJyb3dzZScgLU5hbWUgJ2VuYWJsZWQnIC1WYWx1ZSAkdHJ1ZSAtUFNQYXRoICJJSVM6XFNpdGVzXCROYW1lIg0KICAgIA0KCSMgVXBkYXRlIEF1dGhlbnRpY2F0aW9uDQogICAgI1NldC1XZWJDb25maWd1cmF0aW9uUHJvcGVydHkgLUZpbHRlciAnL3N5c3RlbS5XZWJTZXJ2ZXIvc2VjdXJpdHkvYXV0aGVudGljYXRpb24vQW5vbnltb3VzQXV0aGVudGljYXRpb24nIC1OYW1lICdlbmFibGVkJyAtVmFsdWUgJHRydWUgLUxvY2F0aW9uICRuYW1lDQogICAgI1NldC1XZWJDb25maWd1cmF0aW9uUHJvcGVydHkgLUZpbHRlciAnL3N5c3RlbS5XZWJTZXJ2ZXIvc2VjdXJpdHkvYXV0aGVudGljYXRpb24vd2luZG93c0F1dGhlbnRpY2F0aW9uJyAtTmFtZSAnZW5hYmxlZCcgLVZhbHVlICRmYWxzZSAtTG9jYXRpb24gJE5hbWUNCiAgICAjU2V0LVdlYkNvbmZpZ3VyYXRpb25Qcm9wZXJ0eSAtRmlsdGVyICcvc3lzdGVtLldlYlNlcnZlci9zZWN1cml0eS9hdXRoZW50aWNhdGlvbi9iYXNpY0F1dGhlbnRpY2F0aW9uJyAtTmFtZSAnZW5hYmxlZCcgLVZhbHVlICRmYWxzZSAtTG9jYXRpb24gJE5hbWUNCgkNCgkkV2ViU2l0ZS5TdGFydCgpDQoNCglBZGQtQ29udGVudCAtUGF0aCAiQzpcV2luZG93c1xTeXN0ZW0zMlxEcml2ZXJzXGV0Y1xob3N0cyIgLVZhbHVlICIxMjcuMC4wLjEgICAkTmFtZSINCn0NCg0KDQpmdW5jdGlvbiBEZXBsb3ktV2ViQXBwRnJvbUdpdCB7DQoJcGFyYW0gKA0KCQlbU3RyaW5nXSAkVVJMLA0KCQlbU3RyaW5nXSAkVGVtcFBhdGggPSBbSU8uUGF0aF06OkNvbWJpbmUoW0lPLlBhdGhdOjpHZXRUZW1wUGF0aCgpLCBbSU8uUGF0aF06OkdldFJhbmRvbUZpbGVOYW1lKCkpLA0KCQlbU3RyaW5nXSAkT3V0cHV0UGF0aCA9IFtJTy5QYXRoXTo6Q29tYmluZShbSU8uUGF0aF06OkdldFRlbXBQYXRoKCksIFtJTy5QYXRoXTo6R2V0UmFuZG9tRmlsZU5hbWUoKSkNCgkpDQoJV3JpdGUtTG9nICJUZW1wUGF0aCA9ICckVGVtcFBhdGgnIg0KCVdyaXRlLUxvZyAiT3V0cHV0UGF0aCA9ICckT3V0cHV0UGF0aCciDQoJDQoJDQoJIyBGZXRjaCB3ZWIgYXBwbGljYXRpb24NCgkjLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KCVdyaXRlLUxvZyAiRmV0Y2hpbmcgc291cmNlcyBmcm9tIEdpdCAuLi4iDQoJDQoJJG51bGwgPSBOZXctSXRlbSAtUGF0aCAkVGVtcFBhdGggLUl0ZW1UeXBlIENvbnRhaW5lcg0KCUV4ZWMgLUZpbGVQYXRoICdnaXQuZXhlJyAtQXJndW1lbnRMaXN0IEAoJ2Nsb25lJywgJFVSTCkgLVdvcmtpbmdEaXIgJFRlbXBQYXRoIC1SZWRpcmVjdFN0cmVhbXMNCgkNCgkkUGF0aCA9IEAoR2V0LUNoaWxkSXRlbSAkVGVtcFBhdGgpWzBdLkZ1bGxOYW1lDQoJIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCgkNCgkNCgkjIEJ1aWxkIHdlYiBhcHBsaWNhdGlvbg0KCSMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoJV3JpdGUtTG9nICJCdWlsZGluZyBzb3VyY2VzIC4uLiINCgkNCgkkbXNidWlsZCA9ICJDOlxXaW5kb3dzXE1pY3Jvc29mdC5ORVRcRnJhbWV3b3JrNjRcdjQuMC4zMDMxOVxNU0J1aWxkLmV4ZSINCgkNCgkkbnVsbCA9IE5ldy1JdGVtIC1QYXRoICRPdXRwdXRQYXRoIC1JdGVtVHlwZSBDb250YWluZXINCgkNCgkkU2xuRmlsZXMgPSBAKEdldC1DaGlsZEl0ZW0gLVBhdGggJFBhdGggLUZpbHRlciAqLnNsbiAtUmVjdXJzZSkNCg0KICAgICMgU3RhcnQgbmV3IHByb2Nlc3NzIHdpdGggYWRkaXRpb25hbCBlbnYgdmFyaWFibGVzOg0KCSMqIFZpc3VhbFN0dWRpb1ZlcnNpb24gPSAiMTAuMCINCgkjKiBFbmFibGVOdUdldFBhY2thZ2VSZXN0b3JlICA9ICJ0cnVlIg0KCUV4ZWMgLUZpbGVQYXRoICRtc2J1aWxkIGANCgkJLUFyZ3VtZW50TGlzdCBAKCRTbG5GaWxlc1swXS5GdWxsTmFtZSwgIi9wOk91dHB1dFBhdGg9JE91dHB1dFBhdGgiKSBgDQoJCS1FbnZpcm9ubWVudCBAeydWaXN1YWxTdHVkaW9WZXJzaW9uJyA9ICcxMC4wJzsgJ0VuYWJsZU51R2V0UGFja2FnZVJlc3RvcmUnID0gJ3RydWUnfSBgDQoJCS1SZWRpcmVjdFN0cmVhbXMNCgkNCgkkQXBwRm9sZGVyID0gQChHZXQtQ2hpbGRJdGVtIChbSU8uUGF0aF06OkNvbWJpbmUoJE91dHB1dFBhdGgsICdfUHVibGlzaGVkV2Vic2l0ZXMnKSkpWzBdDQoJIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCgkNCgkNCgkjIEluc3RhbGwgd2ViIGFwcGxpY2F0aW9uDQoJIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KCVJlZ2lzdGVyLVdlYkFwcCAtU291cmNlICRBcHBGb2xkZXIuRnVsbE5hbWUgLU5hbWUgJEFwcEZvbGRlci5OYW1lDQoJIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KfQ0K" + "ImportCoreFunctions.ps1", + "DeployWebApp.ps1" ], "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, { "Name": "Deploy-WebAppFromGit", "Arguments": { @@ -17,4 +12,4 @@ } ], "RebootOnCompletion": 0 -} +} \ No newline at end of file diff --git a/data/templates/agent/InstallIIS.template b/data/templates/agent/InstallIIS.template index 90f1048..6389f3b 100644 --- a/data/templates/agent/InstallIIS.template +++ b/data/templates/agent/InstallIIS.template @@ -1,14 +1,10 @@ { "Scripts": [ - "ZnVuY3Rpb24gQ29weS1QcmVyZXF1aXNpdGVzIHsNCglwYXJhbSAoDQoJCVtTdHJpbmddICRQYXRoID0gJycsDQoJCVtTdHJpbmddICREZXN0aW5hdGlvbiA9ICcnDQoJKQ0KDQoJV3JpdGUtTG9nICItLT4gQ29weS1QcmVyZXF1aXNpdGVzIg0KDQogICAgaWYgKCREZXN0aW5hdGlvbiAtZXEgJycpIHsNCiAgICAgICAgdGhyb3coIkNvcHktUHJlcmVxdWlzaXRlczogRGVzdGluYXRpb24gcGF0aCBub3Qgc3BlY2lmaWVkISIpDQogICAgfQ0KDQogICAgaWYgKCRQYXRoIC1lcSAnJykgew0KICAgICAgICAkUGF0aCA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpDQogICAgICAgIGlmICgkUGF0aCAtZXEgJG51bGwpIHsNCiAgICAgICAgICAgIHRocm93KCJDb3B5LVByZXJlcXVpc2l0ZXM6IFVuYWJsZSB0byBkZXRlcm1pbmUgc291cmNlIHBhdGggZm9yIHByZXJlcXVpc2l0ZXMuIikNCiAgICAgICAgfQ0KICAgIH0NCg0KCVdyaXRlLUxvZyAiQ3JlYXRpbmcgbmV3IFBTRHJpdmUgLi4uIg0KCU5ldy1QU0RyaXZlIC1OYW1lICdQJyAtUFNQcm92aWRlciAnRmlsZVN5c3RlbScgLVJvb3QgJFBhdGggfCBPdXQtTnVsbA0KCVdyaXRlLUxvZyAiQ3JlYXRpbmcgZGVzdGluYXRpb24gZm9sZGVyIC4uLiINCglOZXctSXRlbSAtUGF0aCAkRGVzdGluYXRpb24gLUl0ZW1UeXBlIENvbnRhaW5lciAtRm9yY2UgfCBPdXQtTnVsbA0KCVdyaXRlLUxvZyAiQ29weWluZyBpdGVtcyAuLi4iDQoJQ29weS1JdGVtIC1QYXRoICdQOlxQcmVyZXF1aXNpdGVzXElJUycgLURlc3RpbmF0aW9uICREZXN0aW5hdGlvbiAtUmVjdXJzZSAtRm9yY2UgfCBPdXQtTnVsbA0KCVdyaXRlLUxvZyAiUmVtb3ZpbmcgUFNEcml2ZSAuLi4iDQoJUmVtb3ZlLVBTRHJpdmUgLU5hbWUgJ1AnIC1QU1Byb3ZpZGVyICdGaWxlU3lzdGVtJyAtRm9yY2UgfCBPdXQtTnVsbA0KCQ0KCVdyaXRlLUxvZyAiPC0tIENvcHktUHJlcmVxdWlzaXRlcyINCn0NCg0KDQoNCmZ1bmN0aW9uIEluc3RhbGwtV2ViU2VydmVyIHsNCglwYXJhbSAoDQoJCVtTdHJpbmddICRQcmVyZXF1aXNpdGVzUGF0aA0KCSkNCgkNCglXcml0ZS1Mb2cgIi0tPiBJbnN0YWxsLVdlYlNlcnZlciINCg0KCSRGZWF0dXJlTGlzdCA9IEAoDQoJCSdXZWItU2VydmVyJywNCgkJJ1dlYi1OZXQtRXh0NDUnLA0KCQknV2ViLUFTUCcsDQoJCSdXZWItQXNwLU5ldDQ1JywNCgkJJ1dlYi1JU0FQSS1FeHQnLA0KCQknV2ViLUlTQVBJLUZpbHRlcicsDQoJCSdXZWItSW5jbHVkZXMnDQoJKQ0KCQ0KCSRQcmVyZXF1aXNpdGVzTGlzdCA9IEAoDQoJCSdBc3BOZXRNdmM0U2V0dXAuZXhlJywNCgkJJ1dlYkFwcGxpY2F0aW9ucy5leGUnDQoJKQ0KICAgIA0KCSRQcmVyZXF1aXNpdGVzUGF0aCA9IFtJTy5QYXRoXTo6Q29tYmluZSgkUHJlcmVxdWlzaXRlc1BhdGgsICdJSVMnKQ0KICAgIA0KCVdyaXRlLUxvZyAiVmFsaWRhdGluZyBwcmVyZXF1aXNpdGVzIGJhc2VkIG9uIHRoZSBsaXN0IC4uLiINCglmb3JlYWNoICgkRmlsZU5hbWUgaW4gJFByZXJlcXVpc2l0ZXNMaXN0KSB7DQoJCSRGaWxlUGF0aCA9IFtJTy5QYXRoXTo6Q29tYmluZSgkUHJlcmVxdWlzaXRlc1BhdGgsICRGaWxlTmFtZSkNCgkJaWYgKC1ub3QgKFRlc3QtUGF0aCAtUGF0aCAkRmlsZVBhdGggLVBhdGhUeXBlIExlYWYpKSB7DQoJCQl0aHJvdygiUHJlcmVxdWlzaXRlIGZpbGUgbm90IGZvdW5kOiAnJEZpbGVQYXRoJyIpDQoJCX0NCgl9DQoJDQoJSW1wb3J0LU1vZHVsZSBTZXJ2ZXJNYW5hZ2VyDQoJDQoJV3JpdGUtTG9nICJJbnN0YWxsaW5nIFdlYiBTZXJ2ZXIgLi4uIg0KCUluc3RhbGwtV2luZG93c0ZlYXR1cmUgJEZlYXR1cmVMaXN0IC1JbmNsdWRlTWFuYWdlbWVudFRvb2xzDQoJDQoJV3JpdGUtTG9nICJJbnN0YWxsaW5nIEFzcE5ldE12cDQgLi4uIg0KCSRFeGVjID0gRXhlYyAtRmlsZVBhdGggJChbSU8uUGF0aF06OkNvbWJpbmUoJFByZXJlcXVpc2l0ZXNQYXRoLCAnQXNwTmV0TXZjNFNldHVwLmV4ZScpKSAtQXJndW1lbnRMaXN0ICcvcScgLVBhc3NUaHJ1DQoJaWYgKCRFeGVjLkV4aXRDb2RlIC1uZSAwKSB7DQoJCXRocm93KCJJbnN0YWxsYXRpb24gb2YgJ0FzcE5ldE12YzRTZXR1cC5leGUnIGZhaWxlZC4gUHJvY2VzcyBleGl0IGNvZGUgJyQoJEV4ZWMuRXhpdENvZGUpJyIpDQoJfQ0KCQ0KCSMgRXh0cmFjdCBXZWJBcHBsaWNhdGlvbnMgZm9sZGVyIHdpdGggKi50YXJnZXQgZmlsZXMgdG8NCgkjICAgQzpcUHJvZ3JhbSBGaWxlcyAoeDg2KVxNU0J1aWxkXE1pY3Jvc29mdFxWaXN1YWxTdHVkaW9cdjEwLjANCglXcml0ZS1Mb2cgIkluc3RhbGxpbmcgV2ViQXBwbGljYXRpb24gdGFyZ2V0cyAuLi4iDQoJJFdlYkFwcGxpY2F0aW9uc1RhcmdldHNSb290ID0gJ0M6XFByb2dyYW0gRmlsZXMgKHg4NilcTVNCdWlsZFxNaWNyb3NvZnRcVmlzdWFsU3R1ZGlvXHYxMC4wJw0KCSRudWxsID0gTmV3LUl0ZW0gLVBhdGggJFdlYkFwcGxpY2F0aW9uc1RhcmdldHNSb290IC1JdGVtVHlwZSBDb250YWluZXINCgkkRXhlYyA9IEV4ZWMgLUZpbGVQYXRoICQoW0lPLlBhdGhdOjpDb21iaW5lKCRQcmVyZXF1aXNpdGVzUGF0aCwgJ1dlYkFwcGxpY2F0aW9ucy5leGUnKSkgLUFyZ3VtZW50TGlzdCBAKCItb2AiJFdlYkFwcGxpY2F0aW9uc1RhcmdldHNSb290YCIiLCAnLXknKSAtUGFzc1RocnUNCglpZiAoJEV4ZWMuRXhpdENvZGUgLW5lIDApIHsNCgkJdGhyb3coIkluc3RhbGxhdGlvbiBvZiAnV2ViQXBwbGljYXRpb25zLmV4ZScgZmFpbGVkLiBQcm9jZXNzIGV4aXQgY29kZSAnJCgkRXhlYy5FeGl0Q29kZSknIikNCgl9DQoNCglXcml0ZS1Mb2cgIjwtLSBJbnN0YWxsLVdlYlNlcnZlciINCn0NCg0K" + "ImportCoreFunctions.ps1", + "CopyPrerequisites.ps1", + "InstallIIS.ps1" ], "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, { "Name": "Copy-Prerequisites", "Arguments": { diff --git a/data/templates/agent/InstallMsSqlServer.template b/data/templates/agent/InstallMsSqlServer.template index ceb10dd..8a75996 100644 --- a/data/templates/agent/InstallMsSqlServer.template +++ b/data/templates/agent/InstallMsSqlServer.template @@ -1,4 +1,11 @@ { + "Scripts": [ + "ImportCoreFunctions.ps1", + "OptionParser.ps1", + "SQLServerOptionParsers.ps1", + "SQLServerInstaller.ps1", + "Install-SQLServer.ps1" + ], "Commands": [ { "Name": "Install-SQLServer", @@ -8,12 +15,5 @@ } } ], - "RebootOnCompletion": 0, - "Scripts": [ - "SW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zIC1Gb3JjZQ==", - "IyRFcnJvckFjdGlvblByZWZlcmVuY2UgPSAnU3RvcCcKCmZ1bmN0aW9uIE5ldy1PcHRpb24gKFtzdHJpbmddJE5hbWUsIFtzd2l0Y2hdJFN3aXRjaCwgW3N3aXRjaF0kQm9vbGVhbiwgW3N3aXRjaF0kU3RyaW5nLCBbc3dpdGNoXSRMaXN0LCAkQ29uc3RyYWludHM9JG51bGwpIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgT3B0aW9uIG9iamVjdAoKICAgIC5ERVNDUklQVElPTgogICAgT3B0aW9uIG9iamVjdCBpcyBhIHZpcnR1YWwgb2JqZWN0IHJlcHJlc3RudGluZyB0eXBlZCBjb21tYW5kIGxpbmUgb3B0aW9uLiBUaGVzZSBvYmplY3RzIGVuY2Fwc3VsYXRlIGVzY2FwaW5nIGFuZAogICAgdmFsaWRhdGlvbiBtYXR0ZXJzLgoKICAgIE9uZSBhbmQgb25seSBvbmUgb2YgdGhlIHN3aXRjaGVzICdTd2l0Y2gnLCAnQm9vbGVhbicsICdTdHJpbmcnIG9yICdMaXN0JyBzaG91bGQgYmUgcHJvdmlkZWQuCgogICAgLlBBUkFNRVRFUiBOYW1lCiAgICBPcHRpb24gbmFtZSBhcyBpdCBhcHBlYXJzIGluIHRoZSBjb21tYW5kIGxpbmUuCgogICAgLlBBUkFNRVRFUiBTd2l0Y2gKICAgIFVzZSB0aGlzIHN3aXRjaCB0byBjcmVhdGUgdmFsdWVsZXNzIG9wdGlvbiAoYSBzd2l0Y2gpLgoKICAgIC5QQVJBTUVURVIgQm9vbGVhbgogICAgVXNlIHRoaXMgc3dpdGNoIHRvIGNyZWF0ZSBib29sZWFuIG9wdGlvbi4gSXRzIHZhbHVlIGlzIGFsd2F5cyBjb252ZXJ0ZWQgdG8gIjEiIG9yICIwIgoKICAgIC5QQVJBTUVURVIgU3RyaW5nCiAgICBVc2UgdGhpcyBzd2l0Y2ggdG8gY3JlYXRlIHN0cmluZyBvcHRpb24uIEl0cyB2YWx1ZSB3aWxsIGJlIHByb3Blcmx5IHF1b3RlZCBpZiBuZWNlc3NhcnkuCgogICAgLlBBUkFNRVRFUiBMaXN0CiAgICBVc2UgdGhpcyBzd2l0Y2ggdG8gY3JlYXRlIG9wdGlvbiB3aXRoIGxpc3QgdmFsdWUuIFZhbHVlcyB3aWxsIGJlIHB1dCBpbnRvIGNvbW1hbmQgbGluZSB1c2luZyB2YWxpZCB2YWx1ZSBkZWxlbWl0ZXIgKGEgY29tbWEpCgogICAgLlBBUkFNRVRFUiBDb25zdHJhaW50cwogICAgV2hlbiB0aGlzIHBhcmFtZXRlciBpcyBzcGVjaWZpZWQsIG9wdGlvbiB2YWx1ZXMgYXJlIGxpbWl0ZWQgdG8gb3B0aW9ucyBmcm9tIHRoYXQgbGlzdC4KCiAgICAjPgoKICAgICRPcHRpb24gPSBOZXctT2JqZWN0IC1UeXBlTmFtZSBQU09iamVjdAoKICAgICMgRmllbGRzCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgVHlwZSAtdmFsdWUgJG51bGwKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIE5vdGVQcm9wZXJ0eSBOYW1lIC12YWx1ZSAkbnVsbAogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IEFsbG93ZWRWYWx1ZXMgLXZhbHVlICRudWxsCgogICAgIyBJbml0CgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIF9faW5pdF9fIHsKICAgICAgICBwYXJhbShbc3RyaW5nXSROYW1lLCAkU3dpdGNoLCAkQm9vbGVhbiwgJFN0cmluZywgJExpc3QpCgogICAgICAgICR0aGlzLk5hbWUgPSAkTmFtZQogICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICMgV2l0aCByZXNwZWN0IGZvciBvdXIgZGV2ZWxvcGVycyB3ZSBkbyBub3QgY2hlY2sgZm9yIGRvdWJsZSB0eXBlIHNlbGVjdGVkCiAgICAgICAgaWYgKCRTd2l0Y2gpIHsKICAgICAgICAgICAgQXVnbWVudE9wdGlvblN3aXRjaCgkdGhpcykKICAgICAgICB9IGVsc2VpZiAoJEJvb2xlYW4pIHsKICAgICAgICAgICAgQXVnbWVudE9wdGlvbkJvb2xlYW4oJHRoaXMpCiAgICAgICAgfSBlbHNlaWYgKCRTdHJpbmcpIHsKICAgICAgICAgICAgQXVnbWVudE9wdGlvblN0cmluZygkdGhpcykKICAgICAgICB9IGVsc2VpZiAoJExpc3QpIHsKICAgICAgICAgICAgQXVnbWVudE9wdGlvbkxpc3QoJHRoaXMpCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGhyb3cgIlN3aXRjaCwgQm9vbGVhbiwgU3RyaW5nIG9yIExpc3Qgb3B0aW9uIHR5cGUgbXVzdCBiZSBwcm92aWRlZCBmb3Igb3B0aW9uICckTmFtZSciCiAgICAgICAgfQogICAgfQoKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIFNjcmlwdE1ldGhvZCBfX3Bvc3RfaW5pdF9fIHsKICAgICAgICBwYXJhbSgkQ29uc3RyYWludHM9JG51bGwpCiAgICAgICAgaWYgKCRDb25zdHJhaW50cyAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJHRoaXMuQWxsb3dlZFZhbHVlcyA9IEAoKQogICAgICAgICAgICAkdGhpcy5BbGxvd2VkVmFsdWVzID0gJHRoaXMuQWxsb3dlZFZhbHVlcyArICRDb25zdHJhaW50cwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICRDb25zdHJhaW50cyA9ICRudWxsCiAgICAgICAgfQogICAgfQoKICAgICMgTWV0aG9kcwoKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIC1Gb3JjZSBTY3JpcHRNZXRob2QgVmFsaWRhdGUgewogICAgICAgIGlmICgkdGhpcy5BbGxvd2VkVmFsdWVzIC1uZSAkbnVsbCkgewogICAgICAgICAgICBpZiAoLW5vdCgkdGhpcy5BbGxvd2VkVmFsdWVzIC1jb250YWlucyAkdGhpcy5WYWx1ZSkpIHsKICAgICAgICAgICAgICAgICRDdHMgPSAkdGhpcy5BbGxvd2VkVmFsdWVzIC1qb2luICcsJwogICAgICAgICAgICAgICAgdGhyb3cgIk9wdGlvbiAnJCgkdGhpcy5OYW1lKScgbWF5IGhhdmUgdmFsdWVzICgkQ3RzKSBidXQgbm90ICckKCR0aGlzLlZhbHVlKSciCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBUb1N0cmluZyB7CiAgICAgICAgcmV0dXJuICIvJCgkdGhpcy5OYW1lKSIKICAgIH0KCiAgICAjIGludm9rZSBjb25zdHJ1Y3RvcgoKICAgICRPcHRpb24uX19pbml0X18oJE5hbWUsICRTd2l0Y2gsICRCb29sZWFuLCAkU3RyaW5nLCAkTGlzdCkKICAgICRPcHRpb24uX19wb3N0X2luaXRfXygkQ29uc3RyYWludHMpCgogICAgcmV0dXJuICRPcHRpb24KfQoKZnVuY3Rpb24gQXVnbWVudE9wdGlvblN3aXRjaCgkT3B0aW9uKSB7Cn0KCmZ1bmN0aW9uIEF1Z21lbnRPcHRpb25Cb29sZWFuKCRPcHRpb24pIHsKICAgICMgRmllbGRzCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgVmFsdWUgLXZhbHVlICRmYWxzZQoKICAgICMgTWV0aG9kcwoKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIC1Gb3JjZSBTY3JpcHRNZXRob2QgVG9TdHJpbmcgewogICAgICAgIGlmICgkdGhpcy5WYWx1ZSkgewogICAgICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpPTEiCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuICIvJCgkdGhpcy5OYW1lKT0wIgogICAgICAgIH0KICAgIH0KfQoKZnVuY3Rpb24gQXVnbWVudE9wdGlvblN0cmluZygkT3B0aW9uKSB7CiAgICAjIEZpZWxkcwogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IFZhbHVlIC12YWx1ZSAiIgoKICAgICMgTWV0aG9kcwoKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIC1Gb3JjZSBTY3JpcHRNZXRob2QgVG9TdHJpbmcgewogICAgICAgICR2ID0gIiQoJHRoaXMuVmFsdWUpIgogICAgICAgIGlmICgkdiAtbWF0Y2ggJy4qIC4qJykgewogICAgICAgICAgICAjIFRPRE86IEVzY2FwZSBkb3VibGUgcXVvdGUgY2hhcmFjdGVycyBpZiBwb3NzaWJsZQogICAgICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpPWAiJHZgIiIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpPSR2IgogICAgICAgIH0KICAgIH0KfQoKZnVuY3Rpb24gQXVnbWVudE9wdGlvbkxpc3QoJE9wdGlvbikgewogICAgIyBGaWVsZHMKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIE5vdGVQcm9wZXJ0eSBWYWx1ZSAtdmFsdWUgQCgpCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBWYWxpZGF0ZSB7CiAgICAgICAgaWYgKCR0aGlzLkFsbG93ZWRWYWx1ZXMgLW5lICRudWxsKSB7CiAgICAgICAgICAgIGZvcmVhY2ggKCRWIGluICR0aGlzLlZhbHVlKSB7CiAgICAgICAgICAgICAgICBpZiAoLW5vdCgkdGhpcy5BbGxvd2VkVmFsdWVzIC1jb250YWlucyAkVikpIHsKICAgICAgICAgICAgICAgICAgICAkQ3RzID0gJHRoaXMuQWxsb3dlZFZhbHVlcyAtam9pbiAnLCcKICAgICAgICAgICAgICAgICAgICB0aHJvdyAiT3B0aW9uICckKCR0aGlzLk5hbWUpJyBtYXkgaGF2ZSB2YWx1ZXMgKCRDdHMpIGJ1dCBub3QgJyRWJyIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciAtRm9yY2UgU2NyaXB0TWV0aG9kIFRvU3RyaW5nIHsKICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpPSQoJHRoaXMuVmFsdWUgLWpvaW4gJywnKSIKICAgIH0KfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlcigpIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgT3B0aW9uUGFyc2VyIG9iamVjdC4KCiAgICAuREVTQ1JJUFRJT04KICAgIE9wdGlvblBhcnNlciBvYmplY3QgbGV2ZXJhZ2VzIE9wdGlvbiBvYmplY3RzIGNhcGFiaWxpdGllcyBhbmQgYnVpbGRzIHZhbGlkIGNvbW1hbmQgbGluZSB1c2luZyBzcGVjaWZpZWQgb3B0aW9ucy4KICAgIEFuIGFwcGxpY2F0aW9uIG1heSBhbHNvIGJlIGludm9rZWQgd2l0aCBPcHRpb25QYXJzZXIuCgogICAgIz4KCiAgICAkT3B0aW9uUGFyc2VyID0gTmV3LU9iamVjdCAtVHlwZU5hbWUgUFNPYmplY3QKCiAgICAjIEZpZWxkcwogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IE9wdGlvbnMgLXZhbHVlIEB7fQogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IERlZmF1bHRzIC12YWx1ZSBAe30KICAgICRPcHRpb25QYXJzZXIgfCBBZGQtTWVtYmVyIE5vdGVQcm9wZXJ0eSBSZXF1aXJlZE9wdGlvbnMgLXZhbHVlIEAoKQoKICAgICMgTWV0aG9kcwoKICAgICRPcHRpb25QYXJzZXIgfCBBZGQtTWVtYmVyIFNjcmlwdE1ldGhvZCBBZGRPcHRpb24gewogICAgICAgIDwjCiAgICAgICAgLlNZTk9QU0lTCiAgICAgICAgQWRkcyBzdXBwb3J0ZWQgb3B0aW9uIGludG8gT3B0aW9uUGFyc2VyLgogICAgICAgIAogICAgICAgIC5ERVNDUklQVElPTgogICAgICAgIE9wdGlvblBhcnNlciBkb2VzIG5vdCBhbGxvdyB1c2luZyB1bnJlY29nbml6ZWQgb3B0aW9ucy4gVXNlIHRoaXMgbWV0aG9kIHRvIGZpbGwgT3B0aW9uUGFyc2VyIHdpdGggcmVjb2duaXplZCBvcHRpb25zCgogICAgICAgIC5QQVJBTUVURVIgT3B0aW9uCiAgICAgICAgT3B0aW9uIG9iamVjdAoKICAgICAgICAuUEFSQU1FVEVSIFJlcXVpcmVkCiAgICAgICAgUmVxdWlyZWQgb3B0aW9uIHN3aXRjaAoKICAgICAgICAuUEFSQU1FVEVSIERlZmF1bHQKICAgICAgICBPcHRpb24gZGVmYXVsdCB2YWx1ZQogICAgICAgICM+CiAgICAgICAgcGFyYW0oJE9wdGlvbiwgW2Jvb2xdJFJlcXVpcmVkPSRmYWxzZSwgJERlZmF1bHQ9JG51bGwpCiAgICAgICAgJHRoaXMuT3B0aW9ucy5BZGQoJE9wdGlvbi5OYW1lLCAkT3B0aW9uKQogICAgICAgIGlmICgkUmVxdWlyZWQpIHsKICAgICAgICAgICAgJHRoaXMuUmVxdWlyZWRPcHRpb25zID0gJHRoaXMuUmVxdWlyZWRPcHRpb25zICsgJE9wdGlvbi5OYW1lCiAgICAgICAgICAgIGlmICgkT3B0aW9uIHwgR2V0LU1lbWJlciAiVmFsdWUiKSB7CiAgICAgICAgICAgICAgICBpZiAoJERlZmF1bHQpIHsKICAgICAgICAgICAgICAgICAgICAkdGhpcy5EZWZhdWx0cy5BZGQoJE9wdGlvbi5OYW1lLCAkRGVmYXVsdCkKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICR0aGlzLkRlZmF1bHRzLkFkZCgkT3B0aW9uLk5hbWUsICRudWxsKQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgICRPcHRpb25QYXJzZXIgfCBBZGQtTWVtYmVyIFNjcmlwdE1ldGhvZCBQYXJzZSB7CiAgICAgICAgPCMKICAgICAgICAuU1lOT1BTSVMKICAgICAgICBQYXJzZXMgc3VwcGxpZWQgb3B0aW9ucyBhbmQgcmV0dXJucyBjb21tYW5kIGxpbmUgcGFyYW1ldGVycyBhcnJheS4KICAgICAgICAKICAgICAgICAuREVTQ1JJUFRJT04KICAgICAgICBUaGlzIG1ldGhvZCB2ZXJpZmllcyB0aGF0IG9ubHkgc3VwcG9ydGVkIG9wdGlvbnMgYXJlIHByb3ZpZGVkLCBhbGwgbWFuZGF0b3J5IG9wdGlvbnMgYXJlIGluIHBsYWNlLCAKICAgICAgICBhbGwgb3B0aW9uIG1lZXQgY29uc3RyYWludHMgaWYgYW55LiBVbnNwZWNpZmllZCBvcHRpb25zIHdpdGggZGVmYXVsdCB2YWx1ZXMgYXJlIGFkZGVkIHRvIGNvbW1hbmQgbGluZS4KICAgICAgICBTbywgbWFuZGF0b3J5IG9wdGlvbiB3aXRoIGRlZmF1bHQgdmFsdWUgbmV2ZXIgY2F1c2VzIGV4Y2VwdGlvbi4KCiAgICAgICAgLlBBUkFNRVRFUiBPcHRpb25zCiAgICAgICAgQSBoYXNoIG1hcCBvZiBvcHRpb25zIHRvIHBhcnNlLiBPcHRpb24gbmFtZXMgc2hvdWxkIGJlIG1hcHBlZCB0byBjb3JyZXNwb25kaW5nIHZhbHVlcy4KICAgICAgICAjPgogICAgICAgIHBhcmFtKFtoYXNodGFibGVdJE9wdGlvbnMpCgogICAgICAgICRDb21tYW5kTGluZSA9IEAoKQogICAgICAgIGZvcmVhY2ggKCRSZXF1aXJlZE9wdGlvbk5hbWUgaW4gJHRoaXMuUmVxdWlyZWRPcHRpb25zKSB7CiAgICAgICAgICAgIGlmICgtbm90ICRPcHRpb25zLkNvbnRhaW5zS2V5KCRSZXF1aXJlZE9wdGlvbk5hbWUpKSB7CiAgICAgICAgICAgICAgICAkRGVmYXVsdCA9ICR0aGlzLkRlZmF1bHRzLkdldF9JdGVtKCRSZXF1aXJlZE9wdGlvbk5hbWUpCiAgICAgICAgICAgICAgICBpZiAoJHRoaXMuRGVmYXVsdHMuQ29udGFpbnNLZXkoJFJlcXVpcmVkT3B0aW9uTmFtZSkpIHsKICAgICAgICAgICAgICAgICAgICAkT3B0aW9ucy5BZGQoJFJlcXVpcmVkT3B0aW9uTmFtZSwgJHRoaXMuRGVmYXVsdHMuR2V0X0l0ZW0oJFJlcXVpcmVkT3B0aW9uTmFtZSkpCiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIHRocm93ICJSZXF1aXJlZCBvcHRpb24gJyRSZXF1aXJlZE9wdGlvbk5hbWUnIGlzIG1pc3NpbmciCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGZvcmVhY2ggKCRPcHRpb25OYW1lIGluICQoJE9wdGlvbnMua2V5cykpIHsKICAgICAgICAgICAgJE9wdGlvbiA9ICR0aGlzLk9wdGlvbnMuR2V0X0l0ZW0oJE9wdGlvbk5hbWUpCiAgICAgICAgICAgIGlmICgkT3B0aW9uIC1lcSAkbnVsbCkgewogICAgICAgICAgICAgICAgdGhyb3cgIk9wdGlvbiAnJE9wdGlvbk5hbWUnIGlzIG5vdCBhbGxvd2VkIgogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICgkT3B0aW9uIHwgR2V0LU1lbWJlciAiVmFsdWUiKSB7CiAgICAgICAgICAgICAgICAkT3B0aW9uLlZhbHVlID0gJE9wdGlvbnMuR2V0X0l0ZW0oJE9wdGlvbk5hbWUpCiAgICAgICAgICAgIH0KICAgICAgICAgICAgJE9wdGlvbi5WYWxpZGF0ZSgpCiAgICAgICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICRPcHRpb24uVG9TdHJpbmcoKQogICAgICAgIH0KICAgICAgICByZXR1cm4gJENvbW1hbmRMaW5lCiAgICB9CgogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIEV4ZWN1dGVCaW5hcnkgewogICAgICAgIHBhcmFtKCRCaW5hcnksIFtoYXNodGFibGVdJE9wdGlvbnMgPSBAe30sICRDb21tYW5kTGluZVN1ZmZpeCA9IEAoKSkKICAgICAgICA8IwogICAgICAgIC5TWU5PUFNJUwogICAgICAgIEV4ZWN1dGVzIGJpbmFyeSB3aXRoIGEgY29tbWFuZCBsaW5lIGNvbnN0cnVjdGVkIGZyb20gcHJvdmlkZWQgb3B0aW9ucy4gQW4gYXJiaXRyYXJ5IHN1ZmZpeCBtYXkgYmUgCiAgICAgICAgYXBwZW5kZWQgdG8gdGhlIGNvbW1hbmQgbGluZS4KICAgICAgICAKICAgICAgICAuREVTQ1JJUFRJT04KICAgICAgICBUaGlzIG1ldGhvZCB1c2VzIE9wdGlvblBhcnNlci5QYXJzZSBtZXRob2QgdG8gY29uc3RydWN0IGNvbW1hbmQgbGluZS4gSWYgdGhlcmUgYSBjb21tYW5kIGxpbmUgc3VmZml4IAogICAgICAgIHdhcyBzdXBwbGllZCwgaXQgaXMgYXBwZW5kZWQgdG8gdGhlIGVuZCBvZiBjb21tYW5kIGxpbmUuIE5vcm1hbGx5IGNvbW1hbmQgbGluZSBzdWZmaXggc2hvdWxkIGNvbnRhaW4KICAgICAgICBsZWFkaW5nIHNwYWNlIGNoYXJhY3Rlci4KCiAgICAgICAgTWV0aG9kIHdhaXRzIGZvciBleGVjdXRhYmxlIHByb2Nlc3MgdG8gY29tcGxldGUgYW5kIHJldHVybnMgaXRzIGV4aXQgY29kZS4KCiAgICAgICAgLlBBUkFNRVRFUiBCaW5hcnkKICAgICAgICBGdWxsIG9yIHJlbGF0aXZlIHBhdGggdG8gdGhlIGV4ZWN1dGFibGUgdG8gcnVuLgoKICAgICAgICAuUEFSQU1FVEVSIE9wdGlvbnMKICAgICAgICBBIGhhc2ggbWFwIG9mIG9wdGlvbnMgdG8gcGFzcyB0byB0aGUgZXhlY3V0YWJsZS4KCiAgICAgICAgLlBBUkFNRVRFUiBDb21tYW5kTGluZVN1ZmZpeAogICAgICAgIEFyYml0cmFyeSBjb21tYW5kIGxpbmUgc3VmZml4LiBOb3JtYWxseSBpdCBzaG91ZCBoYXZlIGxlYWRpbmcgc3BhY2UgY2hhcmFjdGVyLgogICAgICAgICM+CgogICAgICAgICRCaW5hcnkgPSBHZXQtSXRlbSAkQmluYXJ5CiAgICAgICAgJENvbW1hbmRMaW5lID0gJHRoaXMuUGFyc2UoJE9wdGlvbnMpCiAgICAgICAgaWYgKCRDb21tYW5kTGluZVN1ZmZpeCkgewogICAgICAgICAgICAkQ29tbWFuZExpbmUgPSAkQ29tbWFuZExpbmUgKyAkQ29tbWFuZExpbmVTdWZmaXgKICAgICAgICB9CgogICAgICAgIFdyaXRlLUxvZyAiRXhlY3V0aW5nOiAkKCRCaW5hcnkuRnVsbE5hbWUpICQoJENvbW1hbmRMaW5lIC1qb2luICcgJykiCiAgICAgICAgJHByb2Nlc3MgPSBbU3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3NdOjpTdGFydCgkQmluYXJ5LCAkQ29tbWFuZExpbmUpCiAgICAgICAgJHByb2Nlc3MuV2FpdEZvckV4aXQoKQogICAgICAgICRwcm9jZXNzLlJlZnJlc2goKQogICAgICAgIHJldHVybiAkcHJvY2Vzcy5FeGl0Q29kZQogICAgfQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCiNFeHBvcnQtTW9kdWxlTWVtYmVyIC1GdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyCiNFeHBvcnQtTW9kdWxlTWVtYmVyIC1GdW5jdGlvbiBOZXctT3B0aW9u", - "I0ltcG9ydC1Nb2R1bGUgT3B0aW9uUGFyc2VyCgojJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICdTdG9wJwoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckluc3RhbGwgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBhbiBvcHRpb24gcGFyc2VyIGZvciBNUyBTUUwgU2VydmVyIDIwMTIgc2V0dXAgIklOU1RBTEwiIGFjdGlvbi4KCiAgICAuREVTQ1JJUFRJT04KICAgIFVzZSB0aGlzIGNtZGxldCB0byBjcmVhdGUgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJJTlNUQUxMIiBhY3Rpb24uCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkSXNQYXJ0T2ZEb21haW4gPSAoR2V0LVdtaU9iamVjdCBXaW4zMl9Db21wdXRlclN5c3RlbSkuUGFydE9mRG9tYWluCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIklOU1RBTEwiKSwgJHRydWUsICJJTlNUQUxMIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJQUNDRVBUU1FMU0VSVkVSTElDRU5TRVRFUk1TIiAtU3dpdGNoKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5VIiAtU3dpdGNoKSkKICAgICMkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlVwZGF0ZVNvdXJjZSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVSUk9SUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTCIsIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJEUSIsIkFTIiwiUlMiLCJEUUMiLCJJUyIsIk1EUyIsIlRvb2xzIiwiQkMiLCJCT0wiLCJCSURTIiwiQ29ubiIsIlNTTVMiLCJBRFZfU1NNUyIsIkRSRVBMQVlfQ1RMUiIsIkRSRVBMQVlfQ0xUIiwiU05BQ19TREsiLCJTREsiLCJMb2NhbERCIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJPTEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiU1BJX0FTX0V4aXN0aW5nRmFybSIsICJTUElfQVNfTmV3RmFybSIsICJBbGxGZWF0dXJlc19XaXRoRGVmYXVsdHMiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRFdPV0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlBJRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlVJTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJOb3JtYWwiLCAiQXV0b0FkdmFuY2UiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FNUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTQkFDS1VQRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU0NPTExBVElPTiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQVNDT05GSUdESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTREFUQURJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQVNMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU0VSVkVSTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNVUxUSURJTUVOU0lPTkFMIiwgIlBPV0VSUElWT1QiLCAiVEFCVUxBUiIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKCiAgICAjJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXCRFTlY6VVNFUk5BTUUiKQogICAgaWYgKCRJc1BhcnRPZkRvbWFpbikgewogICAgICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFbnY6VVNFUkRPTUFJTlxBZG1pbmlzdHJhdG9yIikKICAgIH0KICAgIGVsc2UgewogICAgICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFbnY6Q09NUFVURVJOQU1FXEFkbWluaXN0cmF0b3IiKQogICAgfQoKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1RFTVBESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTUFJPVklERVJNU09MQVAiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGQVJNQUNDT1VOVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkFSTVBBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJQQVNTUEhSQVNFIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGQVJNQURNSU5JUE9SVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQlJPV1NFUlNWQ1NUQVJUVVBUWVBFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5BQkxFUkFOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNRTERBVEFESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNBUFdEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTRUNVUklUWU1PREUiIC1TdHJpbmcgLUNvbnN0cmFpbnJzICgiU1FMIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTEJBQ0tVUERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMQ09MTEFUSU9OIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBRERDVVJSRU5UVVNFUkFTU1FMQURNSU4iIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgCiAgICAjJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6VVNFUkRPTUFJTlwkRU5WOlVTRVJOQU1FIikKICAgIGlmICgkSXNQYXJ0T2ZEb21haW4pIHsKICAgICAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXEFkbWluaXN0cmF0b3IiKQogICAgfQogICAgZWxzZSB7CiAgICAgICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6Q09NUFVURVJOQU1FXEFkbWluaXN0cmF0b3IiKQogICAgfQogICAgCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVEVNUERCRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxURU1QREJMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFVTRVJEQkRJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVVNFUkRCTE9HRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGSUxFU1RSRUFNTEVWRUwiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiMCIsICIxIiwgIjIiLCAiMyIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGSUxFU1RSRUFNU0hBUkVOQU1FIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGVFNWQ0FDQ09VTlQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZUU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklTU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSVNTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSVNTVkNTdGFydHVwVHlwZSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIk5QRU5BQkxFRCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlRDUEVOQUJMRUQiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU0lOU1RBTExNT0RFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIlNoYXJlUG9pbnRGaWxlc09ubHlNb2RlIiwgIkRlZmF1bHROYXRpdmVNb2RlIiwgIkZpbGVzT25seU1vZGUiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNBQ0NPVU5UIiAtU3RyaW5nKSwgJHRydWUsICJOVCBBVVRIT1JJVFlcTmV0d29yayBTZXJ2aWNlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ1N0YXJ0dXBUeXBlIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclByZXBhcmVJbWFnZSB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgTm90ZSB0aGF0IGZvciBpbnN0YWxsZXIgdmVyc2lvbiBvZiBNUyBTUUwgU2VydmVyIHByaW9yIHRvIDIwMTIgU1AxIEN1bXVsYXRpdmUgVXBkYXRlIDIgb25seSB0aGUKICAgIGZvbGxvd2luZyBmZWF0dXJlcyBhcmUgc3VwcG9ydGVkOiBTUUxFbmdpbmUsIFJlcGxpY2F0aW9uLCBGdWxsVGV4dCwgUlMKCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUNUSU9OIiAtU3RyaW5nIC1Db25zdHJhaW50cyAiUHJlcGFyZUltYWdlIiksICR0cnVlLCAiUHJlcGFyZUltYWdlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJQUNDRVBUU1FMU0VSVkVSTElDRU5TRVRFUk1TIiAtU3dpdGNoKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5VIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJVcGRhdGVFbmFibGVkIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJVcGRhdGVTb3VyY2UiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkNPTkZJR1VSQVRJT05GSUxFIiAtU3RyaW5nKSkKIyAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJSUyIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGRUFUVVJFUyIgLUxpc3QgLUNvbnN0cmFpbnRzICgiU1FMIiwiU1FMRW5naW5lIiwiUmVwbGljYXRpb24iLCJGdWxsVGV4dCIsIkRRIiwiQVMiLCJSUyIsIkRRQyIsIklTIiwiTURTIiwiVG9vbHMiLCJCQyIsIkJPTCIsIkJJRFMiLCJDb25uIiwiU1NNUyIsIkFEVl9TU01TIiwiRFJFUExBWV9DVExSIiwiRFJFUExBWV9DTFQiLCJTTkFDX1NESyIsIlNESyIsIkxvY2FsREIiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklORElDQVRFUFJPR1JFU1MiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTExTSEFSRURESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJTlNUQU5DRUlEIiAtU3RyaW5nKSwgJHRydWUsICJNU1NRTFNFUlZFUiIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJQcmVwYXJlSW1hZ2VTUDFVMiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgVGhpcyBjbWRsZXQgc2hvdWxkIGJlIHVzZWQgb25seSBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIFNQMSBDaW1pbGF0aXZlIFVwZGF0ZSAyIG9yIGxhdGVyLgoKICAgIE5vdGUgdGhhdCBmb3IgaW5zdGFsbGVyIHZlcnNpb24gb2YgTVMgU1FMIFNlcnZlciBwcmlvciB0byAyMDEyIFNQMSBDaW1pbGF0aXZlIFVwZGF0ZSAyIG9ubHkgdGhlCiAgICBmb2xsb3dpbmcgZmVhdHVyZXMgYXJlIHN1cHBvcnRlZDogU1FMRW5naW5lLCBSZXBsaWNhdGlvbiwgRnVsbFRleHQsIFJTCgogICAgQWxsIGRvY3VtZW50ZWQgb3B0aW9uIGFyZSBzdXBwb3J0ZWQuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yIGRldGFpbHM6CiAgICBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAogICAgIz4KICAgICRPcHRpb25QYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VyCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIlByZXBhcmVJbWFnZSIpLCAkdHJ1ZSwgIlByZXBhcmVJbWFnZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSUFDQ0VQVFNRTFNFUlZFUkxJQ0VOU0VURVJNUyIgLVN3aXRjaCksICR0cnVlKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlU291cmNlIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJDT05GSUdVUkFUSU9ORklMRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTCIsIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJEUSIsIkFTIiwiUlMiLCJEUUMiLCJJUyIsIk1EUyIsIlRvb2xzIiwiQkMiLCJCT0wiLCJCSURTIiwiQ29ubiIsIlNTTVMiLCJBRFZfU1NNUyIsIlNOQUNfU0RLIiwiU0RLIiwiTG9jYWxEQiIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJISURFQ09OU09MRSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk1TU1FMU0VSVkVSIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRUyIgLVN3aXRjaCkpCgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckNvbXBsZXRlSW1hZ2UgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBhbiBvcHRpb24gcGFyc2VyIGZvciBNUyBTUUwgU2VydmVyIDIwMTIgc2V0dXAgIkNvbXBsZXRlSW1hZ2UiIGFjdGlvbi4KCiAgICAuREVTQ1JJUFRJT04KICAgIFVzZSB0aGlzIGNtZGxldCB0byBjcmVhdGUgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJDb21wbGV0ZUltYWdlIiBhY3Rpb24uCgogICAgTm90ZSB0aGF0IElOU1RBTkNFSUQgcGFyYW1ldGVyIHZhbHVlIE1VU1QgYmUgdGhlIHNhbWUgYXMgc3BlY2lmaWVkIG9uICJQcmVwYXJlSW1hZ2UiIHBoYXNlLgoKICAgIEFsbCBkb2N1bWVudGVkIG9wdGlvbiBhcmUgc3VwcG9ydGVkLiBTZWUgdGhlIGZvbGxvd2luZyBsaW5rIGZvciBkZXRhaWxzOgogICAgaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTQ0MjU5LmFzcHgKICAgICM+CiAgICAkT3B0aW9uUGFyc2VyID0gTmV3LU9wdGlvblBhcnNlcgoKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBQ1RJT04iIC1TdHJpbmcgLUNvbnN0cmFpbnRzICJDb21wbGV0ZUltYWdlIiksICR0cnVlLCAiQ29tcGxldGVJbWFnZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSUFDQ0VQVFNRTFNFUlZFUkxJQ0VOU0VURVJNUyIgLVN3aXRjaCksICR0cnVlKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVSUk9SUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VJRCIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlBJRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTVJFUE9SVElORyIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkhJREVDT05TT0xFIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNBQ0NPVU5UIiAtU3RyaW5nKSwgJHRydWUsICJOVCBBVVRIT1JJVFlcTmV0d29yayBTZXJ2aWNlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUdUU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJCUk9XU0VSU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFTkFCTEVSQU5VIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJTlNUQUxMU1FMREFUQURJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU0FQV0QiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNFQ1VSSVRZTU9ERSIgLVN0cmluZyAtQ29uc3RyYWlucnMgKCJTUUwiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMQkFDS1VQRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxDT0xMQVRJT04iIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6VVNFUkRPTUFJTlwkRU5WOlVTRVJOQU1FIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxURU1QREJESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFRFTVBEQkxPR0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVVNFUkRCRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxVU0VSREJMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZJTEVTVFJFQU1MRVZFTCIgLVN0cmluZyAtQ29uc3RyYWludHMgKCIwIiwgIjEiLCAiMiIsICIzIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZJTEVTVFJFQU1TSEFSRU5BTUUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZUU1ZDQUNDT1VOVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRlRTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiTlBFTkFCTEVEIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVENQRU5BQkxFRCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTSU5TVEFMTE1PREUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiU2hhcmVQb2ludEZpbGVzT25seU1vZGUiLCAiRGVmYXVsdE5hdGl2ZU1vZGUiLCAiRmlsZXNPbmx5TW9kZSIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDU3RhcnR1cFR5cGUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKCiAgICByZXR1cm4gJE9wdGlvblBhcnNlcgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyQ29tcGxldGVJbWFnZVNQMVUyIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJDb21wbGV0ZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiQ29tcGxldGVJbWFnZSIgYWN0aW9uLgoKICAgIFRoaXMgY21kbGV0IHNob3VsZCBiZSB1c2VkIG9ubHkgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBTUDEgQ2ltaWxhdGl2ZSBVcGRhdGUgMiBvciBsYXRlci4KCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUNUSU9OIiAtU3RyaW5nIC1Db25zdHJhaW50cyAiQ29tcGxldGVJbWFnZSIpLCAkdHJ1ZSwgIkNvbXBsZXRlSW1hZ2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklBQ0NFUFRTUUxTRVJWRVJMSUNFTlNFVEVSTVMiIC1Td2l0Y2gpLCAkdHJ1ZSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFTlUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkNPTkZJR1VSQVRJT05GSUxFIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFUlJPUlJFUE9SVElORyIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklORElDQVRFUFJPR1JFU1MiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUElEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FNUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkJST1dTRVJTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOQUJMRVJBTlUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTExTUUxEQVRBRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTQVBXRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU0VDVVJJVFlNT0RFIiAtU3RyaW5nIC1Db25zdHJhaW5ycyAoIlNRTCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxCQUNLVVBESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTENPTExBVElPTiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1NUQVJUVVBUWVBFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXCRFTlY6VVNFUk5BTUUiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFRFTVBEQkRJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVEVNUERCTE9HRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxVU0VSREJESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFVTRVJEQkxPR0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRklMRVNUUkVBTUxFVkVMIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIjAiLCAiMSIsICIyIiwgIjMiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRklMRVNUUkVBTVNIQVJFTkFNRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRlRTVkNBQ0NPVU5UIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJOUEVOQUJMRUQiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJUQ1BFTkFCTEVEIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNJTlNUQUxMTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJTaGFyZVBvaW50RmlsZXNPbmx5TW9kZSIsICJEZWZhdWx0TmF0aXZlTW9kZSIsICJGaWxlc09ubHlNb2RlIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNTdGFydHVwVHlwZSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJVcGdyYWRlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckVkaXRpb25VcGdyYWRlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclJlcGFpciB7CiAgICAjIFRvRG86IEltcGxlbWVudAogICAgdGhyb3cgIk5vdCB5ZXQgaW1wbGVtZW50ZWQiCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJSZWJ1aWxkZGF0YWJhc2UgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyVW5pbnN0YWxsIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJJTlNUQUxMIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiSU5TVEFMTCIgYWN0aW9uLgogICAgQWxsIGRvY3VtZW50ZWQgb3B0aW9uIGFyZSBzdXBwb3J0ZWQuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yIGRldGFpbHM6CiAgICBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAogICAgIz4KICAgICRPcHRpb25QYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VyCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIlVOSU5TVEFMTCIpLCAkdHJ1ZSwgIlVOSU5TVEFMTCIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZFQVRVUkVTIiAtTGlzdCAtQ29uc3RyYWludHMgKCJTUUwiLCJTUUxFbmdpbmUiLCJSZXBsaWNhdGlvbiIsIkZ1bGxUZXh0IiwiRFEiLCJBUyIsIlJTIiwiRFFDIiwiSVMiLCJNRFMiLCJUb29scyIsIkJDIiwiQk9MIiwiQklEUyIsIkNvbm4iLCJTU01TIiwiQURWX1NTTVMiLCJEUkVQTEFZX0NUTFIiLCJEUkVQTEFZX0NMVCIsIlNOQUNfU0RLIiwiU0RLIiwiTG9jYWxEQiIpKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VOQU1FIiAtU3RyaW5nKSwgJHRydWUsICJNU1NRTFNFUlZFUiIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJJbnN0YWxsRmFpbG92ZXJDbHVzdGVyIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclByZXBhcmVGYWlsb3ZlckNsdXN0ZXIgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyQ29tcGxldGVGYWlsb3ZlckNsdXN0ZXIgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyVXBncmFkZSB7CiAgICAjIFRvRG86IEltcGxlbWVudAogICAgdGhyb3cgIk5vdCB5ZXQgaW1wbGVtZW50ZWQiCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJBZGROb2RlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclJlbW92ZU5vZGUgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgojRXhwb3J0LU1vZHVsZU1lbWJlciAtRnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckluc3RhbGwKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJQcmVwYXJlSW1hZ2UKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJQcmVwYXJlSW1hZ2VTUDFVMgojRXhwb3J0LU1vZHVsZU1lbWJlciAtRnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckNvbXBsZXRlSW1hZ2UKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJDb21wbGV0ZUltYWdlU1AxVTIKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJVcGdyYWRlCiNFeHBvcnQtTW9kdWxlTWVtYmVyIC1GdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyRWRpdGlvblVwZ3JhZGUKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJSZXBhaXIKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJSZWJ1aWxkZGF0YWJhc2UKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJVbmluc3RhbGwKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJJbnN0YWxsRmFpbG92ZXJDbHVzdGVyCiNFeHBvcnQtTW9kdWxlTWVtYmVyIC1GdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyUHJlcGFyZUZhaWxvdmVyQ2x1c3RlcgojRXhwb3J0LU1vZHVsZU1lbWJlciAtRnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckNvbXBsZXRlRmFpbG92ZXJDbHVzdGVyCiNFeHBvcnQtTW9kdWxlTWVtYmVyIC1GdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyVXBncmFkZQojRXhwb3J0LU1vZHVsZU1lbWJlciAtRnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckFkZE5vZGUKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJSZW1vdmVOb2RlCg==", - "SW1wb3J0LU1vZHVsZSBOZXRTZWN1cml0eQoKI0ltcG9ydC1Nb2R1bGUgT3B0aW9uUGFyc2VyCiNJbXBvcnQtTW9kdWxlIFNRTFNlcnZlck9wdGlvblBhcnNlcnMKCiMkRXJyb3JBY3Rpb25QcmVmZXJlbmNlID0gJ1N0b3AnCgpmdW5jdGlvbiBUZXN0LUtleShbc3RyaW5nXSRwYXRoLCBbc3RyaW5nXSRrZXkpCnsKICAgIGlmKCEoVGVzdC1QYXRoICRwYXRoKSkgeyByZXR1cm4gJGZhbHNlIH0KICAgIGlmICgoR2V0LUl0ZW1Qcm9wZXJ0eSAkcGF0aCkuJGtleSAtZXEgJG51bGwpIHsgcmV0dXJuICRmYWxzZSB9CiAgICByZXR1cm4gJHRydWUKfQoKZnVuY3Rpb24gUmVzb2x2ZS1TUUxTZXJ2ZXJQcmVyZXF1aXNpdGVzIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluc3RhbGxzIE1TIFNRTCBTZXJ2ZXIgcHJlcmVxdWlzaXRlcyAoLk5ldCBGcmFtZXdvcmsgMy41KQoKICAgIC5ERVNDUklQVElPTgogICAgSW5zdGFsbHMgTVMgU1FMIFNlcnZlciBwcmVyZXF1aXNpdGVzICguTmV0IEZyYW1ld29yayAzLjUpCgogICAgIz4KICAgIGlmICgtbm90IChUZXN0LUtleSAiSEtMTTpcU29mdHdhcmVcTWljcm9zb2Z0XE5FVCBGcmFtZXdvcmsgU2V0dXBcTkRQXHYzLjUiICJJbnN0YWxsIikpIHsKICAgICAgICBJbXBvcnQtTW9kdWxlIFNlcnZlck1hbmFnZXIKICAgICAgICBXcml0ZS1Ib3N0ICIuTmV0IEZyYW1ld29yayAzLjUgbm90IGZvdW5kLiBJbnN0YWxsaW5nIGl0IHVzaW5nIFNlcnZlciBNYW5hZ2VyLi4uIgogICAgICAgICRGZWF0dXJlID0gR2V0LVdpbmRvd3NGZWF0dXJlIE5FVC1GcmFtZXdvcmsKICAgICAgICBpZiAoJEZlYXR1cmUgLWVxICRudWxsKSB7CiAgICAgICAgICAgICMgV2UgYXJlIHByb2JhYmx5IG9uIFdpbmRvd3MgU2VydmVyIDIwMTIKICAgICAgICAgICAgJEZlYXR1cmUgPSBHZXQtV2luZG93c0ZlYXR1cmUgTkVULUZyYW1ld29yay1Db3JlCiAgICAgICAgfQogICAgICAgIGlmICgtbm90ICRGZWF0dXJlKSB7CiAgICAgICAgICAgIHRocm93ICIuTmV0IGZyYW1ld29yayAzLjUgZmVhdHVyZSB3YXMgbm90IGZvdW5kLiIKICAgICAgICB9CiAgICAgICAgaWYgKC1ub3QgJEZlYXR1cmUuRGlzcGxheU5hbWUgLW1hdGNoICIzLjUiKSB7CiAgICAgICAgICAgIExvZy1XYXJuaW5nICIuTmV0IGZyYW1ld29yayAzLjUgaXMgcmVxdWlyZWQsIGJ1dCAkKCRGZWF0dXJlLkRpc3BsYXlOYW1lKSBpcyBhdmFpbGFibGUgYXMgV2luZG93cyBmZWF0dXJlLiBQcm9jZWVkaW5nIHdpdGggaW5zdGFsbGF0aW9uIgogICAgICAgIH0KICAgICAgICBbdm9pZF0oQWRkLVdpbmRvd3NGZWF0dXJlICRGZWF0dXJlKQogICAgfQp9CgpmdW5jdGlvbiBOZXctU1FMU2VydmVyIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluc3RhbmNlLiBSZXR1cm5zICR0cnVlIGlmIGEgcmVib290IGlzIHJlcXVpcmVkIGFmdGVyIHRoZSBpbnN0YWxsYXRpb24sIAogICAgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCBhbmQgdGhyb3dzIGFuIGV4Y2VwdGlvbiBpbiBjYXNlIGlmIGluc3RhbGxhdGlvbiBmYWlscy4KCiAgICAuREVTQ1JJUFRJT04KICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluc3RhbmNlIGluIHVuYXR0ZW5kZWQgbW9kZS4KCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBFeHRyYUZlYXR1cmVzCiAgICBMaXN0IG9mIGZlYXR1cmVzIHRvIGJlIGluc3RhbGxlZCBpbiBhZGRpdGlvbiB0byBkZWZhdWx0ICJTUUxFbmdpbmUiLCAiQ29ubiIsICJTU01TIiwgIkFEVl9TU01TIi4KICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kU2V0dXBSb290LAogICAgICAgIFthcnJheV0kRXh0cmFGZWF0dXJlcyA9IEAoKSwKICAgICAgICBbSGFzaHRhYmxlXSRFeHRyYU9wdGlvbnMgPSBAe30KICAgICkKCiAgICAkU2V0dXBEaXIgPSBHZXQtSXRlbSAkU2V0dXBSb290CiAgICAkU2V0dXBFeGUgPSAkU2V0dXBEaXIuR2V0RmlsZXMoInNldHVwLmV4ZSIpWzBdCgogICAgUmVzb2x2ZS1TUUxTZXJ2ZXJQcmVyZXF1aXNpdGVzCgogICAgJHBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXJJbnN0YWxsCiAgICAkRXhpdENvZGUgPSAkcGFyc2VyLkV4ZWN1dGVCaW5hcnkoJFNldHVwRXhlLkZ1bGxOYW1lLCBAeyJRIiA9ICRudWxsOyAiRkVBVFVSRVMiID0gQCgiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIpICsgJEV4dHJhRmVhdHVyZXN9ICsgJEV4dHJhT3B0aW9ucykKCiAgICBpZiAoJEV4aXRDb2RlIC1lcSAzMDEwKSB7CiAgICAgICAgcmV0dXJuICR0cnVlCiAgICB9CgogICAgaWYgKCRFeGl0Q29kZSAtbmUgMCkgewogICAgICAgIHRocm93ICJJbnN0YWxsYXRpb24gZXhlY3V0YWJsZSBleGl0ZWQgd2l0aCBjb2RlICQoInswOlg4fSIgLWYgJEV4aXRDb2RlKSAoRGVjaW1hbDogJEV4aXRDb2RlKSIKICAgIH0KCiAgICByZXR1cm4gJGZhbHNlCn0KCmZ1bmN0aW9uIE5ldy1TUUxTZXJ2ZXJGb3JBT0FHIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluc3RhbmNlIHdpdGggYWxsIG5lZWRlZCBmZWF0dXJlcyB0byBzZXQgdXAgQWx3YXlzT24gQXZhaWxhYmlsaXR5IEdyb3VwLgogICAgUmV0dXJucyAkdHJ1ZSBpZiBhIHJlYm9vdCBpcyByZXF1aXJlZCBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLCAkZmFsc2UgaWYgYSByZWJvb3QgaXMgbm90IHJlcXVpcmVkIAogICAgYW5kIHRocm93cyBhbiBleGNlcHRpb24gaW4gY2FzZSBpZiBpbnN0YWxsYXRpb24gZmFpbHMuCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSBpbiB1bmF0dGVuZGVkIG1vZGUuIEFsbCBmZWF0dXJlcyBmb3IgQWx3YXlzT24gQXZhaWxhYmlsaXR5IEdyb3VwcyBhcmUKICAgIGluc3RhbGxlZC4KCiAgICBBbGwgYXZhaWxhYmlsaXR5IGdyb3VwIG1lbWJlcnMgbXVzdCBiZSBpbnN0YWxsZWQgd2l0aCB0aGUgc2FtZSBTUUxTdmNVc3JEb21hbiwgU1FMU3ZjVXNyTmFtZSBhbmQgU1FMU3ZjVXNyUGFzc3dvcmQgcGFyYW1ldGVycy4KICAgIFVzZXIgbXVzdCBiZSBhIGRvbWFpbiB1c2VyIHNpbmNlIGl0IHdpbGwgYmUgdXNlZCBmb3Igbm9kZXMgaW50ZXJjb25uZWN0aW9uLgoKICAgIC5QQVJBTUVURVIgU2V0dXBSb290CiAgICBNUyBTUUwgU2VydmVyIGluc3RhbGxhdGlvbiBmaWxlcyByb290IGRpcmVjdG9yeS4gTm9ybWFsbHkgaXQgaXMganVzdCBEVkQgZHJpdmUgbmFtZS4KCiAgICAuUEFSQU1FVEVSIFNRTFN2Y1VzckRvbWFpbgogICAgTVMgU1FMIFNlcnZlciB1c2VyIGFjY291bnQgZG9tYWluIG5hbWUuCgogICAgLlBBUkFNRVRFUiBTUUxTdmNVc3JOYW1lCiAgICBNUyBTUUwgU2VydmVyIHVzZXIgYWNjb3VudCBuYW1lLgoKICAgIC5QQVJBTUVURVIgU1FMU3ZjVXNyUGFzc3dvcmQKICAgIE1TIFNRTCBTZXJ2ZXIgdXNlciBhY2NvdW50IHBhc3N3b3JkLgoKICAgIC5QQVJBTUVURVIgRXh0cmFGZWF0dXJlcwogICAgTGlzdCBvZiBmZWF0dXJlcyB0byBiZSByZW1vdmVkIGJlc2lkZXMgIlNRTEVuZ2luZSIsICJDb25uIiwgIlNTTVMiLCAiQURWX1NTTVMiLCAiRFJFUExBWV9DVExSIiwgIkRSRVBMQVlfQ0xUIi4KICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kU2V0dXBSb290LAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNRTFN2Y1VzckRvbWFpbiwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTUUxTdmNVc3JOYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNRTFN2Y1VzclBhc3N3b3JkLAogICAgICAgIFthcnJheV0kRXh0cmFGZWF0dXJlcyA9IEAoKQogICAgKQoKICAgICRTZXR1cERpciA9IEdldC1JdGVtICRTZXR1cFJvb3QKICAgICRTZXR1cEV4ZSA9ICRTZXR1cERpci5HZXRGaWxlcygic2V0dXAuZXhlIilbMF0KCiAgICAkU1FMVXNlciA9ICIkU1FMU3ZjVXNyRG9tYWluXCRTUUxTdmNVc3JOYW1lIgogICAgJGRvbWFpbiA9IE5ldy1PYmplY3QgU3lzdGVtLkRpcmVjdG9yeVNlcnZpY2VzLkRpcmVjdG9yeUVudHJ5KCJMREFQOi8vJFNRTFN2Y1VzckRvbWFpbiIsICRTUUxTdmNVc3JOYW1lLCAkU1FMU3ZjVXNyUGFzc3dvcmQpCgogICAgaWYgKCRkb21haW4ubmFtZSAtZXEgJG51bGwpIHsKICAgICAgICB0aHJvdyAiQ3JlZGVudGlhbHMgdmFsaWRhdGlvbiBmYWlsZWQgZm9yIHVzZXIgJFNRTFVzZXIuIENoZWNrIGRvbWFpbiwgbG9naW4gbmFtZSBhbmQgcGFzc3dvcmQuIgogICAgfQoKICAgIFJlc29sdmUtU1FMU2VydmVyUHJlcmVxdWlzaXRlcwoKICAgICRwYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VySW5zdGFsbAogICAgJEV4aXRDb2RlID0gJHBhcnNlci5FeGVjdXRlQmluYXJ5KCRTZXR1cEV4ZS5GdWxsTmFtZSwgQHsiUVMiID0gJG51bGw7ICJGRUFUVVJFUyIgPSBAKCJTUUxFbmdpbmUiLCAiQ29ubiIsICJTU01TIiwgIkFEVl9TU01TIiwgIkRSRVBMQVlfQ1RMUiIsICJEUkVQTEFZX0NMVCIpICsgJEV4dHJhRmVhdHVyZXM7CiAgICAgICAgIkFHVFNWQ0FDQ09VTlQiID0gJFNRTFVzZXI7ICJBR1RTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7ICJBU1NWQ0FDQ09VTlQiID0gJFNRTFVzZXI7ICJBU1NWQ1BBU1NXT1JEIiA9ICRTUUxTdmNVc3JQYXNzd29yZDsgIkFTU1lTQURNSU5BQ0NPVU5UUyIgPSAkU1FMVVNlcjsKICAgICAgICAiU1FMU1ZDQUNDT1VOVCIgPSAkU1FMVXNlcjsgIlNRTFNWQ1BBU1NXT1JEIiA9ICRTUUxTdmNVc3JQYXNzd29yZDsgIlNRTFNZU0FETUlOQUNDT1VOVFMiID0gJFNRTFVzZXI7ICJJU1NWQ0FDQ09VTlQiID0gJFNRTFVzZXI7ICJJU1NWQ1BBU1NXT1JEIiA9ICRTUUxTdmNVc3JQYXNzd29yZDsgCiAgICAgICAgIlJTU1ZDQUNDT1VOVCIgPSAkU1FMVXNlcjsgIlJTU1ZDUEFTU1dPUkQiID0gJFNRTFN2Y1VzclBhc3N3b3JkfSkKCiAgICBpZiAoJEV4aXRDb2RlIC1lcSAzMDEwKSB7CiAgICAgICAgcmV0dXJuICR0cnVlCiAgICB9CgogICAgaWYgKCRFeGl0Q29kZSAtbmUgMCkgewogICAgICAgIHRocm93ICJJbnN0YWxsYXRpb24gZXhlY3V0YWJsZSBleGl0ZWQgd2l0aCBjb2RlICQoInswOlg4fSIgLWYgJEV4aXRDb2RlKSAoRGVjaW1hbDogJEV4aXRDb2RlKSIKICAgIH0KCiAgICByZXR1cm4gJGZhbHNlCn0KCmZ1bmN0aW9uIFJlbW92ZS1TUUxTZXJ2ZXIgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgVW5pbnN0YWxscyBNUyBTUUwgU2VydmVyIGluc3RhbmNlIGluc3RhbGxlZCB3aXRoIE5ldy1TUUxTZXJ2ZXIgY21kbGV0CgogICAgLkRFU0NSSVBUSU9OCiAgICBVbmluc3RhbGxzIE1TIFNRTCBTZXJ2ZXIgaW5zdGFuY2UgaW5zdGFsbGVkIHdpdGggTmV3LVNRTFNlcnZlciBjbWRsZXQgaW4gdW5hdHRlbmRlZCBtb2RlCgogICAgLlBBUkFNRVRFUiBTZXR1cFJvb3QKICAgIE1TIFNRTCBTZXJ2ZXIgaW5zdGFsbGF0aW9uIGZpbGVzIHJvb3QgZGlyZWN0b3J5LiBOb3JtYWxseSBpdCBpcyBqdXN0IERWRCBkcml2ZSBuYW1lLgoKICAgIC5QQVJBTUVURVIgRXh0cmFGZWF0dXJlcwogICAgTGlzdCBvZiBmZWF0dXJlcyB0byBiZSByZW1vdmVkIGJlc2lkZXMgIlNRTEVuZ2luZSIsICJDb25uIiwgIlNTTVMiLCAiQURWX1NTTVMiLgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTZXR1cFJvb3QsCiAgICAgICAgW2FycmF5XSRFeHRyYUZlYXR1cmVzID0gQCgpCiAgICApCgogICAgJFNldHVwRGlyID0gR2V0LUl0ZW0gJFNldHVwUm9vdAogICAgJFNldHVwRXhlID0gJFNldHVwRGlyLkdldEZpbGVzKCJzZXR1cC5leGUiKVswXQoKICAgICRwYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VyVW5pbnN0YWxsCiAgICAkRXhpdENvZGUgPSAkcGFyc2VyLkV4ZWN1dGVCaW5hcnkoJFNldHVwRXhlLkZ1bGxOYW1lLCBAeyJRIiA9ICRudWxsOyAiRkVBVFVSRVMiID0gQCgiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIpICsgJEV4dHJhRmVhdHVyZXN9KQoKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICB0aHJvdyAiSW5zdGFsbGF0aW9uIGV4ZWN1dGFibGUgZXhpdGVkIHdpdGggY29kZSAkKCJ7MDpYOH0iIC1mICRFeGl0Q29kZSkiCiAgICB9Cn0KCmZ1bmN0aW9uIEluc3RhbGwtU1FMU2VydmVyRm9yU3lzUHJlcCB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbiBzeXNwcmVwIG1vZGUuCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbiBzeXNwcmVwIG1vZGUuIFJldHVybnMgJHRydWUgaWYgYSByZWJvb3QgaXMgcmVxdWlyZWQgYWZ0ZXIgdGhlIGluc3RhbGxhdGlvbiwgCiAgICAkZmFsc2UgaWYgYSByZWJvb3QgaXMgbm90IHJlcXVpcmVkIGFuZCB0aHJvd3MgYW4gZXhjZXB0aW9uIGluIGNhc2UgaWYgaW5zdGFsbGF0aW9uIGZhaWxzLgoKICAgIFNldHVwIG11c3QgYmUgY29tcGxldGVkIGFmdGVyIGJvb3RpbmcgcmVhcm1lZCBtYWNoaW5lIGJ5IHVzaW5nIENvbXBsZXRlLVNRTFNlcnZlciBjbWRsZXQKCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBFeHRyYUZlYXR1cmVzCiAgICBMaXN0IG9mIGZlYXR1cmVzIHRvIGJlIGluc3RhbGxlZCBpbiBhZGRpdGlvbiB0byBkZWZhdWx0ICJTUUxFbmdpbmUiLiBOb3RlIHRoYXQgcHJpb3IgdG8KICAgIFNRTCBTZXJ2ZXIgdmVyc2lvbiAyMDEyIFNlcnZpY2UgUGFjayAxIEN1bXVsYXRpdmUgVXBkYXRlIDIgKEphbnVhcnkgMjAxMykgb25seSAiUmVwbGljYXRpb24iLCAKICAgICJGdWxsVGV4dCIgYW5kICJSUyIgbWF5IGJlIGluc3RhbGxlZCBpbiBhZGRpdGlvbiB0byAiU1FMRW5naW5lIi4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IKICAgIGRldGlhbHM6IGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CgogICAgIz4KfQoKZnVuY3Rpb24gSW5zdGFsbC1TUUxTZXJ2ZXJGb3JTeXNQcmVwIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluIHN5c3ByZXAgbW9kZS4KCiAgICAuREVTQ1JJUFRJT04KICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluIHN5c3ByZXAgbW9kZS4gUmV0dXJucyAkdHJ1ZSBpZiBhIHJlYm9vdCBpcyByZXF1aXJlZCBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLCAKICAgICRmYWxzZSBpZiBhIHJlYm9vdCBpcyBub3QgcmVxdWlyZWQgYW5kIHRocm93cyBhbiBleGNlcHRpb24gaW4gY2FzZSBpZiBpbnN0YWxsYXRpb24gZmFpbHMuCgogICAgU2V0dXAgbXVzdCBiZSBjb21wbGV0ZWQgYWZ0ZXIgYm9vdGluZyByZWFybWVkIG1hY2hpbmUgYnkgdXNpbmcgQ29tcGxldGUtU1FMU2VydmVyIGNtZGxldAoKICAgIC5QQVJBTUVURVIgU2V0dXBSb290CiAgICBNUyBTUUwgU2VydmVyIGluc3RhbGxhdGlvbiBmaWxlcyByb290IGRpcmVjdG9yeS4gTm9ybWFsbHkgaXQgaXMganVzdCBEVkQgZHJpdmUgbmFtZS4KCiAgICAuUEFSQU1FVEVSIEV4dHJhRmVhdHVyZXMKICAgIExpc3Qgb2YgZmVhdHVyZXMgdG8gYmUgaW5zdGFsbGVkIGluIGFkZGl0aW9uIHRvIGRlZmF1bHQgIlNRTEVuZ2luZSIuIE5vdGUgdGhhdCBwcmlvciB0bwogICAgU1FMIFNlcnZlciB2ZXJzaW9uIDIwMTIgU2VydmljZSBQYWNrIDEgQ3VtdWxhdGl2ZSBVcGRhdGUgMiAoSmFudWFyeSAyMDEzKSBvbmx5ICJSZXBsaWNhdGlvbiIsIAogICAgIkZ1bGxUZXh0IiBhbmQgIlJTIiBtYXkgYmUgaW5zdGFsbGVkIGluIGFkZGl0aW9uIHRvICJTUUxFbmdpbmUiLiBTZWUgdGhlIGZvbGxvd2luZyBsaW5rIGZvcgogICAgZGV0aWFsczogaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTQ0MjU5LmFzcHgKCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCkKICAgICkKCiAgICAkU2V0dXBEaXIgPSBHZXQtSXRlbSAkU2V0dXBSb290CiAgICAkU2V0dXBFeGUgPSAkU2V0dXBEaXIuR2V0RmlsZXMoInNldHVwLmV4ZSIpWzBdCgogICAgUmVzb2x2ZS1TUUxTZXJ2ZXJQcmVyZXF1aXNpdGVzCgogICAgJHBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXJQcmVwYXJlSW1hZ2UKICAgICRFeGl0Q29kZSA9ICRwYXJzZXIuRXhlY3V0ZUJpbmFyeSgkU2V0dXBFeGUuRnVsbE5hbWUsIEB7IlFTIiA9ICRudWxsOyAiRkVBVFVSRVMiID0gQCgiU1FMRW5naW5lIikgKyAkRXh0cmFGZWF0dXJlcyB9KQoKICAgIGlmICgkRXhpdENvZGUgLWVxIDMwMTApIHsKICAgICAgICByZXR1cm4gJHRydWUKICAgIH0KCiAgICBpZiAoJEV4aXRDb2RlIC1uZSAwKSB7CiAgICAgICAgdGhyb3cgIkluc3RhbGxhdGlvbiBleGVjdXRhYmxlIGV4aXRlZCB3aXRoIGNvZGUgJCgiezA6WDh9IiAtZiAkRXhpdENvZGUpIChEZWNpbWFsOiAkRXhpdENvZGUpIgogICAgfQoKICAgIHJldHVybiAkZmFsc2UKfQoKZnVuY3Rpb24gQ29tcGxldGUtU1FMU2VydmVyQWZ0ZXJTeXNQcmVwIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbXBsZXRlcyBwcmV2aW91c2x5IHByZXBhcmVkIHdpdGggIkluc3RhbGwtU1FMU2VydmVyRm9yU3lzUHJlcCIgTVMgU1FMIFNlcnZlciBhZnRlciB0aGUgc3lzdGVtIHdhcyByZWFybWVkLgoKICAgIC5ERVNDUklQVElPTgogICAgQ29tcGxldGVzIHByZXZpb3VzbHkgcHJlcGFyZWQgd2l0aCAiSW5zdGFsbC1TUUxTZXJ2ZXJGb3JTeXNQcmVwIiBNUyBTUUwgU2VydmVyIGFmdGVyIHRoZSBzeXN0ZW0gd2FzIHJlYXJtZWQuCiAgICBSZXR1cm5zICR0cnVlIGlmIGEgcmVib290IGlzIHJlcXVpcmVkIGFmdGVyIHRoZSBpbnN0YWxsYXRpb24sICRmYWxzZSBpZiBhIHJlYm9vdCBpcyBub3QgcmVxdWlyZWQgYW5kIHRocm93cyAKICAgIGFuIGV4Y2VwdGlvbiBpbiBjYXNlIGlmIGluc3RhbGxhdGlvbiBmYWlscy4KCiAgICBTZXR1cCBtdXN0IGJlIGNvbXBsZXRlZCBhZnRlciBib290aW5nIHJlYXJtZWQgbWFjaGluZSBieSB1c2luZyBDb21wbGV0ZS1TUUxTZXJ2ZXIgY21kbGV0CgogICAgLlBBUkFNRVRFUiBTZXR1cFJvb3QKICAgIE1TIFNRTCBTZXJ2ZXIgaW5zdGFsbGF0aW9uIGZpbGVzIHJvb3QgZGlyZWN0b3J5LiBOb3JtYWxseSBpdCBpcyBqdXN0IERWRCBkcml2ZSBuYW1lLgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTZXR1cFJvb3QKICAgICkKCiAgICAkU2V0dXBEaXIgPSBHZXQtSXRlbSAkU2V0dXBSb290CiAgICAkU2V0dXBFeGUgPSAkU2V0dXBEaXIuR2V0RmlsZXMoInNldHVwLmV4ZSIpWzBdCgogICAgJHBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXJDb21wbGV0ZUltYWdlCiAgICAkRXhpdENvZGUgPSAkcGFyc2VyLkV4ZWN1dGVCaW5hcnkoJFNldHVwRXhlLkZ1bGxOYW1lLCBAeyJRUyIgPSAkbnVsbH0pCgogICAgaWYgKCRFeGl0Q29kZSAtZXEgMzAxMCkgewogICAgICAgIHJldHVybiAkdHJ1ZQogICAgfQoKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICB0aHJvdyAiSW5zdGFsbGF0aW9uIGV4ZWN1dGFibGUgZXhpdGVkIHdpdGggY29kZSAkKCJ7MDpYOH0iIC1mICRFeGl0Q29kZSkgKERlY2ltYWw6ICRFeGl0Q29kZSkiCiAgICB9CgogICAgcmV0dXJuICRmYWxzZQp9CgpmdW5jdGlvbiBDb252ZXJ0VG8tU1FMU3RyaW5nIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbnZlcnRzIGFyZ3VtZW50IHRvIGEgdmFsaWQgU1FMIHN0cmluZyBpbiBxdW90ZXMKCiAgICAuREVTQ1JJUFRJT04KICAgIENvbnZlcnRzIGFyZ3VtZW50IHRvIGEgdmFsaWQgU1FMIHN0cmluZyBpbiBxdW90ZXMuIFRoZSBzdHJpbmcgbWF5IGNvbnRhaW4gYW55IGNoYXJhY3RlcnMuCiAgICBTZWUgaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTc5ODk5LmFzcHgKCiAgICAuUEFSQU1FVEVSIFMKICAgIFN0cmluZyB0byBjb252ZXJ0CiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSwgVmFsdWVGcm9tUGlwZWxpbmUgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kUwogICAgKQogICAgCiAgICByZXR1cm4gIickKCRTIC1yZXBsYWNlICInIiwgIicnIiknIgp9CgpmdW5jdGlvbiBDb252ZXJ0VG8tU1FMTmFtZSB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDb252ZXJ0cyBhcmd1bWVudCB0byBhIHZhbGlkIFNRTCBuYW1lIGluIGJyYWNrZXRzCgogICAgLkRFU0NSSVBUSU9OCiAgICBDb252ZXJ0cyBhcmd1bWVudCB0byBhIHZhbGlkIFNRTCBuYW1lIGluIGJyYWNrZXRzLiBUaGUgc3RyaW5nIG1heSBjb250YWluIGFueSBjaGFyYWN0ZXJzLgogICAgU2VlIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE3NTg3NC5hc3B4CgogICAgLlBBUkFNRVRFUiBTCiAgICBTdHJpbmcgdG8gY29udmVydAogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUsIFZhbHVlRnJvbVBpcGVsaW5lID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFMKICAgICkKICAgIHJldHVybiAiWyQoJFMgLXJlcGxhY2UgIl0iLCAiXV0iKV0iCn0KCmZ1bmN0aW9uIEludm9rZS1TUUxUZXh0IHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEludm9rZXMgU1FMIHRleHQKCiAgICAuREVTQ1JJUFRJT04KICAgIEludm9rZXMgU1FMIHRleHQuIFJldHVybnMgcmF3IFNRTCBzZXJ2ZXIgb3V0cHV0LgoKICAgIC5QQVJBTUVURVIgU1FMCiAgICBTUUwgVGV4dAoKICAgIC5QQVJBTUVURVIgVXNlcgogICAgU1FMIFNlcnZlciB1c2VyIG5hbWUKCiAgICAuUEFSQU1FVEVSIFBhc3N3b3JkCiAgICBTUUwgU2VydmVyIHVzZXIgcGFzc3dvcmQKICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTUUwsCiAgICAgICAgW3N0cmluZ10kVXNlciA9ICRudWxsLAogICAgICAgIFtzdHJpbmddJFBhc3N3b3JkID0gJG51bGwKICAgICkKCiAgICAjV3JpdGUtV2FybmluZyAiJFNRTGBuIgogICAgI3JldHVybgoKICAgICRCaW5hcnkgPSBHZXQtQ29tbWFuZCAic3FsY21kLmV4ZSIKCiAgICAkdGVtcEZpbGUgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCiAgICAkdGVtcEZpbGUgPSBHZXQtSXRlbSAkdGVtcEZpbGUKICAgIFNldC1Db250ZW50IC1QYXRoICR0ZW1wRmlsZSAtVmFsdWUgJFNRTAoKICAgICRDb21tYW5kTGluZSA9IEAoJy1oJywgJy0xJywgJy1iJywgJy1pJywgImAiJCgkdGVtcEZpbGUuRnVsbE5hbWUpYCIiKQogICAgaWYgKCgkVXNlciAtbmUgJG51bGwpIC1hbmQgKCRVc2VyIC1uZSAnJykpIHsKICAgICAgICAkQ29tbWFuZExpbmUgPSAkQ29tbWFuZExpbmUgKyAnLVUnCiAgICAgICAgJENvbW1hbmRMaW5lID0gJENvbW1hbmRMaW5lICsgJFVzZXIKICAgICAgICAkQ29tbWFuZExpbmUgPSAkQ29tbWFuZExpbmUgKyAnLVAnCiAgICAgICAgJENvbW1hbmRMaW5lID0gJENvbW1hbmRMaW5lICsgJFBhc3N3b3JkCiAgICB9CgogICAgV3JpdGUtRGVidWcgIkV4ZWN1dGluZzogYG4kU1FMYG4iCiAgICBbc3RyaW5nXSRvdXRwdXQgPSAmJEJpbmFyeSAkQ29tbWFuZExpbmUKCiAgICAkRXhpdENvZGUgPSAkTGFzdEV4aXRDb2RlCiAgICBpZiAoJEV4aXRDb2RlIC1uZSAwKSB7CiAgICAgICAgV3JpdGUtV2FybmluZyAkb3V0cHV0CiAgICAgICAgdGhyb3cgIlNRTENNRC5FWEUgcmV0dXJuZWQgd2l0aCBleGl0IGNvZGUgJEV4aXRDb2RlIHdoaWxlIHJ1bm5pbmcgJEJpbmFyeSAkQ29tbWFuZExpbmUiCiAgICB9CiAgIAogICAgUmVtb3ZlLUl0ZW0gJHRlbXBGaWxlCgogICAgcmV0dXJuICRvdXRwdXQKfQoKZnVuY3Rpb24gTmV3LVNRTFVzZXIgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgSW52b2tlcyBTUUwgdGV4dAoKICAgIC5ERVNDUklQVElPTgogICAgSW52b2tlcyBTUUwgdGV4dAoKICAgIC5QQVJBTUVURVIgU1FMCiAgICBTUUwgVGV4dAoKICAgIC5QQVJBTUVURVIgVXNlcgogICAgU1FMIFNlcnZlciB1c2VyIG5hbWUKCiAgICAuUEFSQU1FVEVSIFBhc3N3b3JkCiAgICBTUUwgU2VydmVyIHVzZXIgcGFzc3dvcmQKICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTUUwsCiAgICAgICAgW3N0cmluZ10kVXNlciA9ICRudWxsLAogICAgICAgIFtzdHJpbmddJFBhc3N3b3JkID0gJG51bGwKICAgICkKfQoKZnVuY3Rpb24gTmV3LVBhc3N3b3JkIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgcmFuZG9tIHBhc3N3b3JkIG9mIHRoZSBzcGVjaWZpZWQgbGVuZ3RoCgogICAgLkRFU0NSSVBUSU9OCiAgICBQYXNzd29yZCBjb250YWlucyByYW5kb20gY2hhcmFjdGVycyBhLXosIEEtWiwgbnVtYmVycyBhbmQgc3BlY2lhbCBjaGFyYWN0ZXJzLgogICAgVGhlcmUgaXMgbm8gZ3VhcmFudGVlIHRoYXQgYWxsIHRoZSB0eXBlcyBvZiBzeW1ib2xzIHdpbGwgYmUgcHJlc2VudCBpbiB0aGUgcGFzc3dvcmQuCgogICAgLlBBUkFNRVRFUiBMZW5ndGgKICAgIERlc2lyZWQgbGVuZ3RoIG9mIHRoZSBwYXNzd29yZC4KCiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW2ludF0kTGVuZ3RoPTYKICAgICkKCiAgICAkUmVzdWx0ID0gIiIKICAgICRhbHBoYSA9ICJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OSFAIyQlXiYqKCknYCJgYF8rW11ce318OzosLi88Pj9+IgogICAgd2hpbGUgKCRMZW5ndGggLWd0IDApIHsKICAgICAgICAkeCA9IEdldC1SYW5kb20gJGFscGhhLkxlbmd0aAogICAgICAgICRjID0gJGFscGhhWyR4XQogICAgICAgICRSZXN1bHQgPSAiJFJlc3VsdCRjIgogICAgICAgICRMZW5ndGggPSAkTGVuZ3RoIC0gMQogICAgfQogICAgcmV0dXJuICRSZXN1bHQKfQoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1NaXJyb3JpbmdFbmRwb2ludCB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIG1pcnJvcmluZyBlbmRwb2ludC4KCiAgICAuREVTQ1JJUFRJT04KICAgIE1hc3RlciBrZXkgaXMgY3JlYXRlZCBpZiBuZWNlc3NhcnkuIEhvc3QgY2VydGlmaWNhdGUgaXMgY3JlYXRlZCB3aGVuIG5lY2Vzc2FyeSBlaXRoZXIgKG5vcm1hbGx5IG9uIGZpcnN0IGVuZHBvaW50IGNyZWF0aW9uKS4KCiAgICBFbmRwb2ludCBhbmQgY2VydGlmaWNhdGUgYXJlIHJlY3JlYXRlZCBpbiBjYXNlIGlmIG1hc3RlciBrZXkgZGlkIG5vdCBleGlzdGVkIChzaG91bGQgbm90IG5vcm1hbGx5IGhhcHBlbikuCgogICAgRW5kcG9pbnQgaXMgcmVjcmVhdGVkIGluIGNhc2UgaWYgY2VydGlmaWNhdGUgZGlkIG5vdCBleGlzdGVkIChzaG91bGQgbm90IGhhcHBlbiB1bmxlc3MgdGhlIGVuZHBvaW50IHdhcyBjcmVhdGVkIG1hbnVhbGx5KS4KCiAgICBNaXJyb3JpbmcgZW5kcG9pbnQgaXMgY3JlYXRlZCB1bmxlc3Mgb25lIGFscmVhZHkgZXhpc3RzLiBUaGUgZW5kcG9pbnQgaXMgY3JlYXRlZCB3aXRoIHRoZSBzcGVjaWZpZWQgbmFtZS4gV2hlbiB0aGUgZW5kcG9pbnQKICAgIGFscmVhZHkgZXhpc3RzIGlzIGlzIHVuY2hhbmdlZC4KCiAgICBFbmRwb2ludCBwb3J0IGlzIHNlbGVjdGVkIGF1dG9tYXRpY2FsbHkgYXMgNDAyMiBvciBhcyBmaXJzdCBhdmFpbGFibGUgcG9ydCBhZnRlciA0MDIyIGluIGNhc2UgaWYgNDAyMiBpcyBhbHJlYWR5IGxpc3RlbmluZy4KICAgIElmIHRoZXJlIGlzIG5vIGZpcmV3YWxsIHJ1bGUgd2l0aCBuYW1lICdEYXRhYmFzZU1pcnJvcmluZy1UQ1Ate3BvcnRudW1iZXJ9JywgYWxsb3dpbmcgcnVsZSBpcyBjcmVhdGVkLgoKICAgIENlcnRpZmljYXRlIGlzIHN0b3JlZCBpbiB0aGUgc3BlY2lmaWVkIGZpbGUuCgogICAgUmV0dXJucyBlbmRwb2ludCBsaXN0ZW5pbmcgcG9ydC4KCiAgICAuUEFSQU1FVEVSIEVuY3J5cHRpb25QYXNzd29yZAogICAgRW5jcnlwdGlvbiBwYXNzd29yZCB1c2VkIHRvIGNyZWF0ZSBjZXJ0aWZpY2F0ZS4KCiAgICAuUEFSQU1FVEVSIENlcnRpZmljYXRlRmlsZU5hbWUKICAgIENlcnRpZmljYXRlIHRhcmdldCBmaWxlIG5hbWUuIEZpbGUgTVVTVCBOT1QgZXhpc3QuCgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRFbmNyeXB0aW9uUGFzc3dvcmQsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kQ2VydGlmaWNhdGVGaWxlTmFtZQogICAgKQoKICAgICRFbmRwb2ludE5hbWUgPSAnTWlycm9yaW5nRW5kcG9pbnQnCgogICAgJEZvbGRlciA9IEdldC1JdGVtICRXb3JrRGlyCgogICAgJEggPSAkRW52OkNPTVBVVEVSTkFNRSAtcmVwbGFjZSAnW15BLVphLXowLTlfXScsICdfJwoKICAgICRQb3J0ID0gR2V0LU5leHRGcmVlUG9ydCA0MDIyCgogICAgJENyZWF0ZU1hc3RlcktleSA9ICJVU0UgbWFzdGVyOwoKICAgICAgICAgICAgICAgICAgICAgICAgSUYgTk9UIEVYSVNUUyhzZWxlY3QgKiBmcm9tIHN5cy5zeW1tZXRyaWNfa2V5cyB3aGVyZSBuYW1lID0gJyMjTVNfRGF0YWJhc2VNYXN0ZXJLZXkjIycpCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUkVBVEUgTUFTVEVSIEtFWSBFTkNSWVBUSU9OIEJZIFBBU1NXT1JEID0gJChDb252ZXJ0VG8tU1FMU3RyaW5nICRFbmNyeXB0aW9uUGFzc3dvcmQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgSUYgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLmNlcnRpZmljYXRlcyB3aGVyZSBuYW1lID0gJyR7SH1fY2VydCcpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERST1AgQ0VSVElGSUNBVEUgJHtIfV9jZXJ0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIElGIEVYSVNUUyhTRUxFQ1QgKiBGUk9NIHN5cy5lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBERUNMQVJFIGBAbmFtZSBWQVJDSEFSKDI1NSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTRUxFQ1QgVE9QIDEgYEBuYW1lID0gbmFtZSBGUk9NIHN5cy5lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVhFQyAoJ0RST1AgRU5EUE9JTlQgWycgKyBgQG5hbWUgKyAnXScpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgRU5ECiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICBJRiBOT1QgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLmNlcnRpZmljYXRlcyB3aGVyZSBuYW1lID0gJyR7SH1fY2VydCcpCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUkVBVEUgQ0VSVElGSUNBVEUgJHtIfV9jZXJ0IFdJVEggU1VCSkVDVCA9ICcke0h9IGVuZHBvaW50IGNlcnRpZmljYXRlJzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIElGIEVYSVNUUyhTRUxFQ1QgKiBGUk9NIHN5cy5lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBERUNMQVJFIGBAbmFtZSBWQVJDSEFSKDI1NSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTRUxFQ1QgVE9QIDEgYEBuYW1lID0gbmFtZSBGUk9NIHN5cy5lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRVhFQyAoJ0RST1AgRU5EUE9JTlQgWycgKyBgQG5hbWUgKyAnXScpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgRU5ECiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICBCQUNLVVAgQ0VSVElGSUNBVEUgJHtIfV9jZXJ0IFRPIEZJTEUgPSAkKENvbnZlcnRUby1TUUxTdHJpbmcgIiRDZXJ0aWZpY2F0ZUZpbGVOYW1lIik7CiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICBERUNMQVJFIGBAcG9ydCBpbnQKICAgICAgICAgICAgICAgICAgICAgICAgSUYgRVhJU1RTKFNFTEVDVCAqIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycpCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTRUxFQ1QgYEBwb3J0ID0gcG9ydCBGUk9NIHN5cy50Y3BfZW5kcG9pbnRzIFdIRVJFIHR5cGVfZGVzYz0nREFUQUJBU0VfTUlSUk9SSU5HJwogICAgICAgICAgICAgICAgICAgICAgICBFTkQgRUxTRQogICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1JFQVRFIEVORFBPSU5UICQoQ29udmVydFRvLVNRTE5hbWUgJEVuZHBvaW50TmFtZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTVEFURSA9IFNUQVJURUQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBUyBUQ1AgKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMSVNURU5FUl9QT1JUID0gJFBvcnQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBMSVNURU5FUl9JUCA9IEFMTAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRk9SIERBVEFCQVNFX01JUlJPUklORyAoIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBVVRIRU5USUNBVElPTiA9IENFUlRJRklDQVRFICR7SH1fY2VydAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIEVOQ1JZUFRJT04gPSBSRVFVSVJFRCBBTEdPUklUSE0gQUVTCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgUk9MRSA9IEFMTAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTRUxFQ1QgYEBwb3J0ID0gJFBvcnQKICAgICAgICAgICAgICAgICAgICAgICAgRU5ECgogICAgICAgICAgICAgICAgICAgICAgICBTRUxFQ1QgJ3BvcnQ6KCcgKyBDT05WRVJUKFZBUkNIQVIsIGBAcG9ydCkgKyAnKScgYXMgcG9ydAogICAgICAgICAgICAgICAgICAgICAgICBHTwoKICAgICAgICAgICAgICAgICAgICAgICAgIgoKICAgICRyYXdkYXRhID0gSW52b2tlLVNRTFRleHQgLVNRTCAkQ3JlYXRlTWFzdGVyS2V5CiAgICBbaW50XSRQb3J0ID0gJHJhd2RhdGEgLXJlcGxhY2UgJy4qcG9ydDpcKChbXildKilcKS4qJywgJyQxJwoKICAgICMgT3BlbiBwb3J0IGluIFdpbmRvd3MgRmlyZXdhbGwKCiAgICAkUG9ydE9wZW4gPSAkZmFsc2UKICAgICRSdWxlTmFtZSA9ICJEYXRhYmFzZU1pcnJvcmluZy1UQ1AtJFBvcnQiCiAgICBHZXQtTmV0RmlyZXdhbGxSdWxlIHwgRm9yZWFjaC1PYmplY3QgewogICAgICAgIGlmICgkXy5OYW1lIC1lcSAkUnVsZU5hbWUpIHsKICAgICAgICAgICAgJFBvcnRPcGVuID0gJHRydWUKICAgICAgICB9CiAgICB9CiAgICBpZiAoLW5vdCAkUG9ydE9wZW4pIHsKICAgICAgICAkRGlzcGxheU5hbWUgPSAiTVMgU1FMIERhdGFiYXNlIE1pcnJvcmluZyBFbmRwb2ludCBhdCBUQ1AgcG9ydCAkUG9ydCIKICAgICAgICBOZXctTmV0RmlyZXdhbGxSdWxlIC1OYW1lICRSdWxlTmFtZSAtRGlzcGxheU5hbWUgJERpc3BsYXlOYW1lIC1EZXNjcmlwdGlvbiAkRGlzcGxheU5hbWUgLVByb3RvY29sIFRDUCAtTG9jYWxQb3J0ICRQb3J0IC1FbmFibGVkIFRydWUgLVByb2ZpbGUgQW55IC1BY3Rpb24gQWxsb3cKICAgIH0KICAgICAKICAgIHJldHVybiAkUG9ydAp9CgpmdW5jdGlvbiBDb21wbGV0ZS1NaXJyb3JpbmdFbmRwb2ludCB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDb21wbGV0ZXMgbWlycm9yaW5nIGVuZHBvaW50CgogICAgLkRFU0NSSVBUSU9OCiAgICBBbGxvd3MgaW5ib3VuZCBjb25uZWN0aW9ucyBmcm9tIHJlbW90ZSBob3N0CiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZUhvc3ROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZVdvcmtEaXIsCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdExvZ2luLAogICAgICAgIFtTdHJpbmddJFJlbW90ZUhvc3RVc2VyLAogICAgICAgIFtTdHJpbmddJFJlbW90ZUhvc3RQYXNzd29yZAogICAgKQoKICAgICRGb2xkZXIgPSBHZXQtSXRlbSAkUmVtb3RlV29ya0RpcgogICAgJFJlbW90ZVdvcmtEaXIgPSAkRm9sZGVyLkZ1bGxOYW1lCgogICAgJEggPSAkUmVtb3RlSG9zdE5hbWUgLXJlcGxhY2UgJ1teQS1aYS16MC05X10nLCAnXycKCiAgICBpZiAoLW5vdCAkUmVtb3RlSG9zdExvZ2luKSB7CiAgICAgICAgJFJlbW90ZUhvc3RMb2dpbiA9ICIke0h9X2xvZ2luIgogICAgfQogICAgaWYgKC1ub3QgJFJlbW90ZUhvc3RVc2VyKSB7CiAgICAgICAgJFJlbW90ZUhvc3RVc2VyID0gIiR7SH1fdXNlciIKICAgIH0KICAgIGlmICgtbm90ICRSZW1vdGVIb3N0UGFzc3dvcmQpIHsKICAgICAgICAkUmVtb3RlSG9zdFBhc3N3b3JkID0gIiQoTmV3LVBhc3N3b3JkIDEwKWFBIzMiCiAgICB9CgogICAgJFNRTCA9ICAgICAgICAgICAgICJVU0UgbWFzdGVyOwoKICAgICAgICAgICAgICAgICAgICAgICAgSUYgTk9UIEVYSVNUUyhzZWxlY3QgKiBmcm9tIHN5cy5zcWxfbG9naW5zIHdoZXJlIG5hbWU9JChDb252ZXJ0VG8tU1FMU3RyaW5nICRSZW1vdGVIb3N0TG9naW4pKQogICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1JFQVRFIExPR0lOICQoQ29udmVydFRvLVNRTE5hbWUgJFJlbW90ZUhvc3RMb2dpbikgV0lUSCBQQVNTV09SRCA9ICQoQ29udmVydFRvLVNRTFN0cmluZyAkUmVtb3RlSG9zdFBhc3N3b3JkKTsKICAgICAgICAgICAgICAgICAgICAgICAgRU5ECiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICBJRiBOT1QgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLnN5c3VzZXJzIHdoZXJlIG5hbWU9JChDb252ZXJ0VG8tU1FMU3RyaW5nICRSZW1vdGVIb3N0VXNlcikpCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUkVBVEUgVVNFUiAkKENvbnZlcnRUby1TUUxOYW1lICRSZW1vdGVIb3N0VXNlcikgRk9SIExPR0lOICQoQ29udmVydFRvLVNRTE5hbWUgJFJlbW90ZUhvc3RMb2dpbik7CiAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBHTwoKICAgICAgICAgICAgICAgICAgICAgICAgSUYgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLmNlcnRpZmljYXRlcyB3aGVyZSBuYW1lPScke0h9X3JlbW90ZV9jZXJ0JykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIERST1AgQ0VSVElGSUNBVEUgJHtIfV9yZW1vdGVfY2VydAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBDRVJUSUZJQ0FURSAke0h9X3JlbW90ZV9jZXJ0IEFVVEhPUklaQVRJT04gJChDb252ZXJ0VG8tU1FMTmFtZSAkUmVtb3RlSG9zdFVzZXIpIEZST00gRklMRSA9ICQoQ29udmVydFRvLVNRTFN0cmluZyAiJFJlbW90ZVdvcmtEaXJcY2VydGlmaWNhdGUuY2VyIik7CiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICBERUNMQVJFIGBAbmFtZSBWQVJDSEFSKDI1NSkKICAgICAgICAgICAgICAgICAgICAgICAgU0VMRUNUIFRPUCAxIGBAbmFtZSA9IG5hbWUgRlJPTSBzeXMuZW5kcG9pbnRzIFdIRVJFIHR5cGVfZGVzYz0nREFUQUJBU0VfTUlSUk9SSU5HJwogICAgICAgICAgICAgICAgICAgICAgICBTRUxFQ1QgJ25hbWU6KCcgKyBgQG5hbWUgKyAnKScgYXMgbmFtZQogICAgICAgICAgICAgICAgICAgICAgICAiCgogICAgJHJhd2RhdGEgPSBJbnZva2UtU1FMVGV4dCAtU1FMICRTUUwKICAgICRFbmRwb2ludE5hbWUgPSAkcmF3ZGF0YSAtcmVwbGFjZSAnLipuYW1lOlwoKFteKV0qKVwpLionLCAnJDEnCiAgICAkU1FMID0gICAgICAgICAgICAgIkdSQU5UIENPTk5FQ1QgT04gRU5EUE9JTlQ6OiQoQ29udmVydFRvLVNRTE5hbWUgJEVuZHBvaW50TmFtZSkgVE8gJChDb252ZXJ0VG8tU1FMTmFtZSAkUmVtb3RlSG9zdExvZ2luKSIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRTUUwpCn0KCmZ1bmN0aW9uIENvbXBsZXRlLVNRTE1pcnJvciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDb21wbGV0ZXMgY3JlYXRpb24gb2YgbWlycm9yZWQgU1FMIGRhdGFiYXNlCgogICAgLkRFU0NSSVBUSU9OCiAgICBUaGlzIGNtZGxldCBzaG91bGQgYmUgZmlyc3QgZXhlY3V0ZWQgb24gbWlycm9yIHNlcnZlciBhbmQgdGhlbiBvbiBwcmluY2lwYWwgc2VydmVyLgogICAgT3RoZXJ3aXNlIGl0IHdpbGwgZmFpbCAoaG93ZXZlciBpdCBtYXkgYmUgZXhlY3V0ZWQgYWdhaW4gd2l0aCBubyBoYXJtKS4KICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW0ludF0kUmVtb3RlUG9ydCwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSREYXRhYmFzZU5hbWUKICAgICkKCiAgICAkVXJsID0gIlRDUDovLyR7UmVtb3RlSG9zdE5hbWV9OiR7UmVtb3RlUG9ydH0iCiAgICAkQWx0ZXJEYiA9ICJBTFRFUiBEQVRBQkFTRSAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIFNFVCBQQVJUTkVSID0gJChDb252ZXJ0VG8tU1FMU3RyaW5nICRVcmwpOwogICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQWx0ZXJEYikKfQoKZnVuY3Rpb24gTmV3LVNRTERhdGFiYXNlIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgZW1wdHkgU1FMIGRhdGFiYXNlCgogICAgLkRFU0NSSVBUSU9OCiAgICBDcmVhdGVzIGVtcHR5IFNRTCBkYXRhYmFzZSB3aXRoIGRlZmF1bHQgc2V0dGluZ3MuIEZhaWxzIGluIGNhc2UgaXMgdGhlIGRhdGFiYXNlIGFscmVhZHkgZXhpc3RzLgoKICAgIC5QQVJBTUVURVIgRGF0YUJhc2VOYW1lCiAgICBEYXRhYmFzZSBuYW1lLgoKICAgIC5QQVJBTUVURVIgbWRmRmlsZQogICAgTmFtZSBvZiB0aGUgTURGIChkYXRhKSBmaWxlLiBJZiBub3Qgc3BlY2lmaWVkLCB0aGUgZm9sbG93aW5nIHZhbHVlIGlzIHVzZWQ6CiAgICAiQzpcUHJvZ3JhbSBGaWxlc1xNaWNyb3NvZnQgU1FMIFNlcnZlclxNU1NRTDExLk1TU1FMU0VSVkVSXE1TU1FMXERBVEFce0RhdGFCYXNlUGF0aE5hbWV9Lm1kZiIKICAgIFdoZXJlIHtEYXRhQmFzZVBhdGhOYW1lfSBpcyBkYXRhYmFzZSBuYW1lIHdpdGggYWxsIGJ1dCBBLVosIGEteiwgMC05IGNoYXJhY3RlcnMKICAgIHJlcGxhY2VkIGJ5IHVuZGVyc2NvcmUuCgogICAgLlBBUkFNRVRFUiBEYXRhQmFzZU5hbWUKICAgIE5hbWUgb2YgdGhlIExERiAodHJhbnNhY3Rpb24gbG9nKSBmaWxlLiBJZiBub3Qgc3BlY2lmaWVkLCB0aGUgZm9sbG93aW5nIHZhbHVlIGlzIHVzZWQ6CiAgICAiQzpcUHJvZ3JhbSBGaWxlc1xNaWNyb3NvZnQgU1FMIFNlcnZlclxNU1NRTDExLk1TU1FMU0VSVkVSXE1TU1FMXERBVEFce0RhdGFCYXNlUGF0aE5hbWV9X2xvZy5tZGYiCiAgICBXaGVyZSB7RGF0YUJhc2VQYXRoTmFtZX0gaXMgZGF0YWJhc2UgbmFtZSB3aXRoIGFsbCBidXQgQS1aLCBhLXosIDAtOSBjaGFyYWN0ZXJzCiAgICByZXBsYWNlZCBieSB1bmRlcnNjb3JlLgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSREYXRhQmFzZU5hbWUsCiAgICAgICAgW1N0cmluZ10kbWRmRmlsZT0kbnVsbCwKICAgICAgICBbU3RyaW5nXSRsZGZGaWxlPSRudWxsCiAgICApCgogICAgJERhdGFCYXNlUGF0aE5hbWUgPSAkRGF0YUJhc2VOYW1lIC1yZXBsYWNlICdbXjAtOWEtekEtWl0nLCAnXycKICAgIGlmICgtbm90ICRtZGZGaWxlKSB7CiAgICAgICAgJG1kZkZpbGUgPSAiQzpcUHJvZ3JhbSBGaWxlc1xNaWNyb3NvZnQgU1FMIFNlcnZlclxNU1NRTDExLk1TU1FMU0VSVkVSXE1TU1FMXERBVEFcJHtEYXRhQmFzZVBhdGhOYW1lfS5tZGYiCiAgICB9CiAgICBpZiAoLW5vdCAkbGRmRmlsZSkgewogICAgICAgICRsZGZGaWxlID0gIkM6XFByb2dyYW0gRmlsZXNcTWljcm9zb2Z0IFNRTCBTZXJ2ZXJcTVNTUUwxMS5NU1NRTFNFUlZFUlxNU1NRTFxEQVRBXCR7RGF0YUJhc2VQYXRoTmFtZX1fbG9nLmxkZiIKICAgIH0KCiAgICAkTmV3RGF0YWJhc2UgPSAiCiAgICAgICAgQ1JFQVRFIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkKICAgICAgICAgICAgICAgIENPTlRBSU5NRU5UID0gTk9ORQogICAgICAgICAgICAgICAgT04gIFBSSU1BUlkgCiAgICAgICAgICAgICggTkFNRSA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgJERhdGFCYXNlTmFtZSksIEZJTEVOQU1FID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAkbWRmRmlsZSkgLCBTSVpFID0gNDA5NktCICwgRklMRUdST1dUSCA9IDEwMjRLQiApCiAgICAgICAgICAgICAgICBMT0cgT04gCiAgICAgICAgICAgICggTkFNRSA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiR7RGF0YUJhc2VOYW1lfV9sb2ciKSwgRklMRU5BTUUgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICRsZGZGaWxlKSAsIFNJWkUgPSAxMDI0S0IgLCBGSUxFR1JPV1RIID0gMTAlKQogICAgICAgIEdPCiAgICAgICAgVVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkKICAgICAgICBHTwogICAgICAgIElGIE5PVCBFWElTVFMgKFNFTEVDVCBuYW1lIEZST00gc3lzLmZpbGVncm91cHMgV0hFUkUgaXNfZGVmYXVsdD0xIEFORCBuYW1lID0gTidQUklNQVJZJykgQUxURVIgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBNT0RJRlkgRklMRUdST1VQIFtQUklNQVJZXSBERUZBVUxUCiAgICAgICAgR08iCgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJE5ld0RhdGFiYXNlKQp9CgpmdW5jdGlvbiBJbml0aWFsaXplLVNRTE1pcnJvcmluZ1ByaW5jaXBhbFN0ZXAxIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIFByZXBhcmVzIHByaW5jaXBhbCBTUUwgU2VydmVyIGZvciBkYXRhYmFzZSBtaXJyb3JpbmcgKFN0YWdlIDEpCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbml0aWFsaXplcyBtaXJyb3JpbmcgZW5kcG9pbnQgKHRoaXMgaXMgYWJzb2x1dGVseSBzeW1tZXRyaWMgc3RlcCB0byB0aGUgbWlycm9yIGluaXQpLiBJbiBhZGRpdGlvbiB0byB0aGF0IGl0IGNyZWF0ZXMKICAgIGEgZGF0YWJhc2UgYW5kIHN0b3JlcyBiYWNrdXBzIG9mIGl0IGFuZCBpdHMgdHJhbnNhY3Rpb24gbG9nIGluIHRoZSBzYW1lIGRpcmVjdG9yeSBhcyB0aGUgZW5kcG9pbnQgY2VydGlmaWNhdGUuCgogICAgQSBmaXJld2FsbCBydWxlIGlzIGNyZWF0ZWQgZm9yIGVuZHBvaW50IGlmIG5lY2Vzc2FyeS4KCiAgICAuUEFSQU1FVEVSIFdvcmtEaXIKICAgIFdvcmtpbmQgZGlyZWN0b3J5LiBUaGlzIGRpcmVjdG9yeSBzaG91bGQgYmUgdHJhbmZlcnJlZCB0byB0aGUgbWlycm9yIHNlcnZlciBhZnRlciB0aGlzCiAgICBzdGVwIGlzIGV4ZWN1dGVkLgoKICAgIC5QQVJBTUVURVIgRGF0YWJhc2VOYW1lCiAgICBNaXJyb3JlZCBkYXRhYmFzZSBuYW1lLiBUaGlzIG5hbWUgTVVTVCBiZSB1c2UgYXQgbWlycm9yIHNlcnZlciBlaXRoZXIuCiAgICAKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kV29ya0RpciwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSREYXRhQmFzZU5hbWUKICAgICkKCiAgICBbU3RyaW5nXSRFbmNyeXB0aW9uUGFzc3dvcmQgPSAiJChOZXctUGFzc3dvcmQgMTApYUEjMyIKCiAgICBpZiAoLW5vdCAoVGVzdC1QYXRoICRXb3JrRGlyKSkgewogICAgICAgIFt2b2lkXShOZXctSXRlbSAtVHlwZSBEaXJlY3RvcnkgJFdvcmtEaXIpCiAgICB9CiAgICAkV29ya0RpciA9IChHZXQtSXRlbSAkV29ya0RpcikuRnVsbE5hbWUKICAgIGlmICgoR2V0LUNoaWxkSXRlbSAtUGF0aCAkV29ya0RpcikuTGVuZ3RoIC1ndCAwKSB7CiAgICAgICAgdGhyb3cgIldvcmtpbmcgZGlyZWN0b3J5ICRXb3JrRGlyIGlzIG5vdCBlbXB0eSIKICAgIH0KCiAgICAkRW5kcG9pbnRQb3J0ID0gSW5pdGlhbGl6ZS1NaXJyb3JpbmdFbmRwb2ludCAkRW5jcnlwdGlvblBhc3N3b3JkICIkV29ya0RpclxjZXJ0aWZpY2F0ZS5jZXIiCiAgICAkRW5kcG9pbnRQb3J0IHwgU2V0LUNvbnRlbnQgIiRXb3JrRGlyXGVuZHBvaW50LXBvcnQudHh0IgogICAgTmV3LVNRTERhdGFiYXNlICREYXRhQmFzZU5hbWUKCiAgICAkQmFja3VwRGIgPSAiQkFDS1VQIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgVE8gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXFNvdXJjZS5iYWsiKSBXSVRIIE5PRk9STUFULCBJTklULCBOQU1FID0gTidGdWxsIERhdGFiYXNlIEJhY2t1cCcsIFNLSVAsIE5PUkVXSU5ELCBOT1VOTE9BRCwgU1RBVFMgPSAxMAogICAgICAgICAgICAgICAgIEdPIgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJEJhY2t1cERiKQogICAgJEJhY2t1cExvZyA9ICJCQUNLVVAgTE9HICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgVE8gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXFNvdXJjZV9sb2cuYmFrIikgV0lUSCBOT0ZPUk1BVCwgSU5JVCwgIE5BTUUgPSBOJ1RyYW5zYWN0aW9uIExvZyAgQmFja3VwJywgU0tJUCwgTk9SRVdJTkQsIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgIEdPIgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJEJhY2t1cExvZykKfQoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1TUUxNaXJyb3JpbmdQcmluY2lwYWxTdGVwMiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBQcmVwYXJlcyBwcmluY2lwYWwgU1FMIFNlcnZlciBmb3IgZGF0YWJhc2UgbWlycm9yaW5nIChTdGFnZSAyKQoKICAgIC5ERVNDUklQVElPTgogICAgSW1wb3J0cyByZW1vdGUgc2VydmVyIGNlcnRpZmljYXRlIGFuZCBncmFudHMgaXQgd2l0aCBhY2Nlc3MgdG8gdGhlIG1pcnJvcmluZyBlbmRwb2ludC4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZUhvc3ROYW1lCiAgICBSZW1vdGUgKG1pcnJvcikgaG9zdCBuYW1lLiBGUUROIGlzIHByZWZlcnJlZCwgYnV0IE5ldEJJT1MgbmFtZXMgYW5kIElQIGFkZHJlc3NlcyBhcmUgYWxzbyBhY2NlcHRlZC4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZVdvcmtEaXIKICAgIFBhdGggdG8gYSBjb3B5IG9mIHdvcmtkaXIgb2J0YWluZWQgZnJvbSBtaXJyb3IgbWFjaGluZSBjcmVhdGVkIG9uIFN0YWdlIDEuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZUhvc3ROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZVdvcmtEaXIKICAgICkKCiAgICBpZiAoLW5vdCAoVGVzdC1QYXRoICRSZW1vdGVXb3JrRGlyKSkgewogICAgICAgIHRocm93ICJSZW1vdGUgd29yayBkaXIgJyRSZW1vdGVXb3JrRGlyJyB3YXMgbm90IGZvdW5kIgogICAgfQogICAgJFJlbW90ZVdvcmtEaXIgPSAoR2V0LUl0ZW0gJFJlbW90ZVdvcmtEaXIpLkZ1bGxOYW1lCgogICAgQ29tcGxldGUtTWlycm9yaW5nRW5kcG9pbnQgJFJlbW90ZUhvc3ROYW1lICRSZW1vdGVXb3JrRGlyCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nUHJpbmNpcGFsU3RlcDMgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgcHJpbmNpcGFsIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMykKCiAgICAuREVTQ1JJUFRJT04KICAgIENvbXBsZXRlcyBtaXJyb3IgY3JlYXRpb24uIFRoaXMgc3RlcCBtdXN0IGJlIGdsb2JhbGx5IHRoZSBsYXN0IG9uZSBpbiBtaXJyb3IgY3JlYXRpb24gc2VxdWVuY2UuCgogICAgTm90ZSB0aGF0IHRoZSByZW1vdGUgaG9zdCBjZXJ0aWZpY2F0ZSBpcyB2YWxpZCBmcm9tIHRoZSB0aW1lIGl0IGlzIGNyZWF0ZWQgdGhlcmUuIFNvCiAgICB0aGlzIHN0ZXAgd2lsbCBmYWlsIGlmIHRoZXJlIGlzIG5vdGljYWJsZSBkaWZmZXJlbnQgaW4gdGltZSBsb2NhbCBhbmQgcmVtb3RlIG1hY2hpbmVzLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlSG9zdE5hbWUKICAgIFJlbW90ZSAocHJpbmNpcGFsKSBob3N0IG5hbWUuIEZRRE4gaXMgcHJlZmVycmVkLCBidXQgTmV0QklPUyBuYW1lcyBhbmQgSVAgYWRkcmVzc2VzIGFyZSBhbHNvIGFjY2VwdGVkLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlV29ya0RpcgogICAgUGF0aCB0byBhIGNvcHkgb2Ygd29ya2RpciBvYnRhaW5lZCBmcm9tIHByaW5jaXBhbCBtYWNoaW5lIGNyZWF0ZWQgb24gU3RhZ2UgMS4KCiAgICAuUEFSQU1FVEVSIERhdGFiYXNlTmFtZQogICAgTWlycm9yZWQgZGF0YWJhc2UgbmFtZS4gVGhpcyBuYW1lIE1VU1QgbWF0Y2ggcHJpbmNpcGFsIGRhdGFiYXNlIG5hbWUgYW5kIG5hbWUgcHJvdmlkZWQgb24gc3RlcCAxLgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFiYXNlTmFtZQogICAgKQoKICAgIFtpbnRdJHBvcnQgPSBHZXQtQ29udGVudCAiJHtSZW1vdGVXb3JrRGlyfVxlbmRwb2ludC1wb3J0LnR4dCIKICAgIENvbXBsZXRlLVNRTE1pcnJvciAkUmVtb3RlSG9zdE5hbWUgJHBvcnQgJERhdGFiYXNlTmFtZQp9CgpmdW5jdGlvbiBJbml0aWFsaXplLVNRTE1pcnJvcmluZ01pcnJvclN0ZXAxIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIFByZXBhcmVzIG1pcnJvciBTUUwgU2VydmVyIGZvciBkYXRhYmFzZSBtaXJyb3JpbmcgKFN0YWdlMSkKCiAgICAuREVTQ1JJUFRJT04KICAgIEluaXRpYWxpemVzIG1pcnJvcmluZyBlbmRwb2ludCBmb3IgbWlycm9yIHNlcnZlci4gU3RvcmVzIG1pcnJvcmluZyBlbmRwb2ludCBjZXJ0aWZpY2F0ZSBpbiBXb3JrZGlyLgoKICAgIC5QQVJBTUVURVIgV29ya0RpcgogICAgV29ya2luZCBkaXJlY3RvcnkuIFRoaXMgZGlyZWN0b3J5IHNob3VsZCBiZSB0cmFuZmVycmVkIHRvIHRoZSBwcmluY2lwYWwgc2VydmVyIGFmdGVyIHRoaXMKICAgIHN0ZXAgaXMgZXhlY3V0ZWQuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWUKICAgIE1pcnJvcmVkIGRhdGFiYXNlIG5hbWUuIFRoaXMgbmFtZSBNVVNUIG1hdGNoIHByaW5jaXBhbCBkYXRhYmFzZSBuYW1lLgoKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kV29ya0RpciwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSREYXRhYmFzZU5hbWUKICAgICkKCiAgICBbU3RyaW5nXSRFbmNyeXB0aW9uUGFzc3dvcmQgPSAiJChOZXctUGFzc3dvcmQgMTApYUEjMyIKCiAgICBpZiAoLW5vdCAoVGVzdC1QYXRoICRXb3JrRGlyKSkgewogICAgICAgIFt2b2lkXShOZXctSXRlbSAtVHlwZSBEaXJlY3RvcnkgJFdvcmtEaXIpCiAgICB9CiAgICAkV29ya0RpciA9IChHZXQtSXRlbSAkV29ya0RpcikuRnVsbE5hbWUKCiAgICAkRW5kcG9pbnRQb3J0ID0gSW5pdGlhbGl6ZS1NaXJyb3JpbmdFbmRwb2ludCAkRW5jcnlwdGlvblBhc3N3b3JkICIkV29ya0RpclxjZXJ0aWZpY2F0ZS5jZXIiCiAgICAkRW5kcG9pbnRQb3J0IHwgU2V0LUNvbnRlbnQgIiRXb3JrRGlyXGVuZHBvaW50LXBvcnQudHh0Igp9CgpmdW5jdGlvbiBJbml0aWFsaXplLVNRTE1pcnJvcmluZ01pcnJvclN0ZXAyIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIFByZXBhcmVzIG1pcnJvciBTUUwgU2VydmVyIGZvciBkYXRhYmFzZSBtaXJyb3JpbmcgKFN0YWdlIDIpCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbXBvcnRzIHJlbW90ZSBzZXJ2ZXIgY2VydGlmaWNhdGUgYW5kIGdyYW50cyBpdCB3aXRoIGFjY2VzcyB0byB0aGUgbWlycm9yaW5nIGVuZHBvaW50LgogICAgUmVzdG9yZXMgZGF0YWJhc2Ugb2J0YWluZWQgZnJvbSBwcmluY2lwYWwgYW5kIGxlYXZlcyBpdCBpbiAnUmVzdG9yaW5nJyBzdGF0ZS4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZUhvc3ROYW1lCiAgICBSZW1vdGUgKHByaW5jaXBhbCkgaG9zdCBuYW1lLiBGUUROIGlzIHByZWZlcnJlZCwgYnV0IE5ldEJJT1MgbmFtZXMgYW5kIElQIGFkZHJlc3NlcyBhcmUgYWxzbyBhY2NlcHRlZC4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZVdvcmtEaXIKICAgIFBhdGggdG8gYSBjb3B5IG9mIHdvcmtkaXIgb2J0YWluZWQgZnJvbSBwcmluY2lwYWwgbWFjaGluZSBjcmVhdGVkIG9uIFN0YWdlIDEuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWUKICAgIE1pcnJvcmVkIGRhdGFiYXNlIG5hbWUuIFRoaXMgbmFtZSBNVVNUIG1hdGNoIHByaW5jaXBhbCBkYXRhYmFzZSBuYW1lLgoKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpciwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSREYXRhQmFzZU5hbWUKICAgICkKCiAgICBpZiAoLW5vdCAoVGVzdC1QYXRoICRSZW1vdGVXb3JrRGlyKSkgewogICAgICAgIHRocm93ICJSZW1vdGUgd29yayBkaXIgJyRSZW1vdGVXb3JrRGlyJyB3YXMgbm90IGZvdW5kIgogICAgfQogICAgJFJlbW90ZVdvcmtEaXIgPSAoR2V0LUl0ZW0gJFJlbW90ZVdvcmtEaXIpLkZ1bGxOYW1lCgogICAgQ29tcGxldGUtTWlycm9yaW5nRW5kcG9pbnQgJFJlbW90ZUhvc3ROYW1lICRSZW1vdGVXb3JrRGlyCgogICAgJFJlc3RvcmVEYiA9ICJSRVNUT1JFIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgRlJPTSBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFJlbW90ZVdvcmtEaXJcU291cmNlLmJhayIpIFdJVEggRklMRSA9IDEsIE5PUkVDT1ZFUlksIE5PVU5MT0FELCBSRVBMQUNFLCBTVEFUUyA9IDUKICAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkUmVzdG9yZURiKQogICAgJFJlc3RvcmVMb2cgPSAiUkVTVE9SRSBMT0cgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBGUk9NIERJU0sgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICIkUmVtb3RlV29ya0RpclxTb3VyY2VfbG9nLmJhayIpIFdJVEggRklMRSA9IDEsIE5PUkVDT1ZFUlksIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgICBHTyIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRSZXN0b3JlTG9nKQp9CgpmdW5jdGlvbiBJbml0aWFsaXplLVNRTE1pcnJvcmluZ01pcnJvclN0ZXAzIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIFByZXBhcmVzIG1pcnJvciBTUUwgU2VydmVyIGZvciBkYXRhYmFzZSBtaXJyb3JpbmcgKFN0YWdlIDMpCgogICAgLkRFU0NSSVBUSU9OCiAgICBDb21wbGV0ZXMgbWlycm9yIGNyZWF0aW9uLiBUaGlzIHN0ZXAgbXVzdCBiZSBleGVjdXRlZCBzdHJpY3RseSBiZWZvcmUgc3ltbWV0cmljIHN0ZXAgb24gdGhlIHByaW5jaXBhbC4KCiAgICBOb3RlIHRoYXQgdGhlIHJlbW90ZSBob3N0IGNlcnRpZmljYXRlIGlzIHZhbGlkIGZyb20gdGhlIHRpbWUgaXQgaXMgY3JlYXRlZCB0aGVyZS4gU28KICAgIHRoaXMgc3RlcCB3aWxsIGZhaWwgaWYgdGhlcmUgaXMgbm90aWNhYmxlIGRpZmZlcmVudCBpbiB0aW1lIGxvY2FsIGFuZCByZW1vdGUgbWFjaGluZXMuCgogICAgLlBBUkFNRVRFUiBSZW1vdGVIb3N0TmFtZQogICAgUmVtb3RlIChwcmluY2lwYWwpIGhvc3QgbmFtZS4gRlFETiBpcyBwcmVmZXJyZWQsIGJ1dCBOZXRCSU9TIG5hbWVzIGFuZCBJUCBhZGRyZXNzZXMgYXJlIGFsc28gYWNjZXB0ZWQuCgogICAgLlBBUkFNRVRFUiBSZW1vdGVXb3JrRGlyCiAgICBQYXRoIHRvIGEgY29weSBvZiB3b3JrZGlyIG9idGFpbmVkIGZyb20gcHJpbmNpcGFsIG1hY2hpbmUgY3JlYXRlZCBvbiBTdGFnZSAxLgoKICAgIC5QQVJBTUVURVIgRGF0YWJhc2VOYW1lCiAgICBNaXJyb3JlZCBkYXRhYmFzZSBuYW1lLiBUaGlzIG5hbWUgTVVTVCBtYXRjaCBwcmluY2lwYWwgZGF0YWJhc2UgbmFtZS4KCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZUhvc3ROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZVdvcmtEaXIsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kRGF0YWJhc2VOYW1lCiAgICApCgogICAgW2ludF0kcG9ydCA9IEdldC1Db250ZW50ICIke1JlbW90ZVdvcmtEaXJ9XGVuZHBvaW50LXBvcnQudHh0IgogICAgQ29tcGxldGUtU1FMTWlycm9yICRSZW1vdGVIb3N0TmFtZSAkcG9ydCAkRGF0YWJhc2VOYW1lCn0KCmZ1bmN0aW9uIEdldC1OZXh0RnJlZVBvcnQgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUmV0dXJucyBzcGVjaWZpZWQgZGVzaXJlZCBwb3J0IG9yIGNsb3Nlc3QgbmV4dCBvbmUgdW5vY2N1cGllZC4KCiAgICAuUEFSQU1FVEVSIFBvcnQKICAgIERlc2lyZWQgcG9ydCBudW1iZXIuCgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbaW50XSRQb3J0CiAgICApCiAgICAkT3BlblBvcnRzID0gbmV0c3RhdCAtYW9uIHwgc2VsZWN0LXN0cmluZyAnTElTVEVOSU5HJyB8IEZvcmVhY2gtT2JqZWN0IHsgKCgkXyAtcmVwbGFjZSAnXlxzKicsICcnIC1zcGxpdCAnXHMrJylbMV0gLXNwbGl0ICcuKjonKVsxXSB9IHwgU29ydC1PYmplY3QgfCBHZXQtVW5pcXVlCiAgICB3aGlsZSAoJE9wZW5Qb3J0cy5Db250YWlucygke1BvcnR9KSkgewogICAgICAgICRQb3J0ID0gJFBvcnQgKyAxCiAgICB9CiAgICByZXR1cm4gJFBvcnQKfQoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BbHdheXNPbiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbml0aWFsaXplcyBBbHdheXNPbiBjbHVzdGVyaW5nIG9uIGxvY2FsIFNRTCBzZXJ2ZXIgYW5kIGNyZWF0ZXMgQWx3YXlzT24gZW5kcG9pbnQgbGlzdGVuZXIuIFJldHVybnMgQWx3YXlzT24gZW5kcG9pbnQgcG9ydCBudW1iZXIuCgogICAgLkRFU0NSSVBUSU9OCiAgICBFbmFibGVzIEFsd2F5c09uIGNsdXN0ZXJpbmcgb24gbG9jYWwgU1FMIHNlcnZlci4gQ3JlYXRlcyBBbHdheXNPbiBUQ1AgZW5kcG9pbnQgb24gcG9ydCA1MDIyIG9yIGdyZWF0ZXIgaWYgdGhlIG9uZSBpcyBvY2N1cGllZC4gICAKICAgICM+CgogICAgaWYgKCEoVGVzdC1QYXRoIFNRTFNFUlZFUjpcKSkgewogICAgICAgIEltcG9ydC1Nb2R1bGUgc3FscHMKICAgIH0KICAgICRNYWNoaW5lTmFtZSA9IChHZXQtQ2hpbGRJdGVtIFNRTFNFUlZFUjpcU1FMKVswXS5QU0NoaWxkTmFtZQogICAgJEluc3RhbmNlTmFtZSA9IChHZXQtQ2hpbGRJdGVtIFNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZSkuUFNDaGlsZE5hbWUKICAgICRBbHdheXNPbkVuYWJsZWQgPSAoKEdldC1JdGVtIFNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lKSB8IHNlbGVjdCBJc0hhZHJFbmFibGVkKS5Jc0hhZHJFbmFibGVkCiAgICBpZiAoLW5vdCAkQWx3YXlzT25FbmFibGVkKSB7CiAgICAgICAgRW5hYmxlLVNxbEFsd2F5c09uIC1QYXRoICJTUUxTRVJWRVI6XFNRTFwkTWFjaGluZU5hbWVcJEluc3RhbmNlTmFtZSIgLUZvcmNlCiAgICB9CiAgICAkSW5zdGFuY2UgPSBHZXQtSXRlbSBTUUxTRVJWRVI6XFNRTFwkTWFjaGluZU5hbWVcJEluc3RhbmNlTmFtZQogICAgJGVuZHBvaW50ID0gJEluc3RhbmNlLkVuZHBvaW50c1siQWx3YXlzT25FbmRwb2ludCJdCiAgICBpZiAoLW5vdCAkZW5kcG9pbnQpIHsKICAgICAgICAkUG9ydCA9IEdldC1OZXh0RnJlZVBvcnQgNTAyMgogICAgICAgICRlbmRwb2ludCA9IE5ldy1TcWxIYWRyRW5kcG9pbnQgQWx3YXlzT25FbmRwb2ludCAtUG9ydCAkUG9ydCAtUGF0aCBTUUxTRVJWRVI6XFNRTFwkTWFjaGluZU5hbWVcJEluc3RhbmNlTmFtZQogICAgfSBlbHNlIHsKICAgICAgICAkUG9ydCA9ICRlbmRwb2ludC5Qcm90b2NvbC5UY3AuTGlzdGVuZXJQb3J0CiAgICB9IAogICAgaWYgKCRlbmRwb2ludC5FbmRwb2ludFN0YXRlIC1uZSAiU3RhcnRlZCIpIHsKICAgICAgICAkZW5kcG9pbnQuU3RhcnQoKQogICAgfSAgICAKICAgIHJldHVybiAkUG9ydAp9CgpmdW5jdGlvbiBOZXctQWx3YXlzT25BdmFpbGFiaWxpdHlHcm91cCB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIG5ldyBBbHdheXNPbiBhdmFpbGFiaWxpdHkgZ3JvdXAgb24gcHJpbWFyeSByZXBsaWNhLgoKICAgIC5ERVNDUklQVElPTgogICAgQ3JlYXRlcyBuZXcgQWx3YXlzT24gYXZhaWxhYmlsaXR5IGdyb3VwIG9uIHByaW1hcnkgcmVwbGljYS4KCiAgICAuUEFSQU1FVEVSIFdvcmtEaXIKICAgIFdvcmtpbmQgZGlyZWN0b3J5LiBUaGlzIGRpcmVjdG9yeSBzaG91bGQgYmUgdHJhbmZlcnJlZCB0byB0aGUgcmVwbGljYSBzZXJ2ZXIocykgYWZ0ZXIgdGhpcwogICAgc3RlcCBpcyBleGVjdXRlZC4KCiAgICAuUEFSQU1FVEVSIE5hbWUKICAgIEF2YWlsYWJpbGl0eSBncm91cCBuYW1lLgoKICAgIC5QQVJBTUVURVIgRGF0YWJhc2VOYW1lcwogICAgUmVwbGljYSBkYXRhYmFzZShzKSBuYW1lcy4KCiAgICAuUEFSQU1FVEVSIFJlcGxpY2FEZWZzCiAgICBBcnJheSBvZiByZXBsaWNhIGRlZmluaXRpb24uIEVhY2ggZGVmaW5pdGlvbiBpcyBhIGhhc2ggdGFibGUgd2l0aCByZXBsaWNhLXNwZWNpZmljIHZhbHVlcy4KICAgIAogICAgTWFuZGF0b3J5IHJlcGxpY2EgZGVmaW5pdGlvbiB2YWx1ZXMgYXJlOgoKICAgICAgICAqIFtTdHJpbmddIFNFUlZFUl9JTlNUQU5DRSAgIC0gUmVwbGljYSBzZXJ2ZXIgaW5zdGFuY2UgbmFtZQogICAgICAgICogW1N0cmluZ10gRU5EUE9JTlRfVVJMICAgICAgLSBSZXBsaWNhIHNlcnZlciBlbmRwb2ludCBVUkwuIE5vcm1hbGx5IGl0IGlzIFRDUDovL2Z1bGx5LnF1YWxpZmllZC5kb21haW4ubmFtZTo1MDIyIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQb3J0IG51bWJlciBzaG91bGQgYmUgb2J0YWluZWQgd2l0aCBJbml0aWFsaXplLUFsd2F5c09uIGF0IHRoZSByZXBsaWNhIHNlcnZlcgogICAgICAgICogW1N0cmluZ10gQVZBSUxBQklMSVRZX01PREUgLSBSZXBsaWNhIGF2YWlsYWJpbGl0eSBtb2RlLiBDYW4gYmUgIlNZTkNIUk9OT1VTX0NPTU1JVCIgb3IgIkFTWU5DSFJPTk9VU19DT01NSVQiIG9ubHkuCiAgICAgICAgKiBbU3RyaW5nXSBGQUlMT1ZFUl9NT0RFICAgICAtIFJlcGxpY2EgYXZhaWxhYmlsaXR5IG1vZGUuIENhbiBiZSAiTUFOVUFMIiBvciAiQVVUT01BVElDIiBvbmx5LgoKICAgIE9wdGlvbmFsIHJlcGxpY2EgZGVmaW5pdGlvbiB2YWx1ZXMgYXJlOgoKICAgICAgICAqIFtJbnRlZ2VyXSBCQUNLVVBfUFJJT1JJVFkgICAgICAgICAgLSBCYWNrdXAgcHJpb3JpdHkKICAgICAgICAqIFtJbnRlZ2VyXSBTRVNTSU9OX1RJTUVPVVQgICAgICAgICAgLSBTZXNzaW9uIHRpbWVvdXQKICAgICAgICAqIFtTdHJpbmddICBQX0FMTE9XX0NPTk5FQ1RJT05TICAgICAgLSBBbGxvd2VkIGNvbm5lY3Rpb24gdHlwZXMgZm9yICJQcmltYXJ5IiByZXBsaWNhIG1vZGUuIENhbiBiZSAiUkVBRF9XUklURSIgb3IgIkFMTCIgb25seS4KICAgICAgICAqIFtBcnJheV0gICBQX1JFQURfT05MWV9ST1VUSU5HX0xJU1QgLSBMaXN0IG9mIHJlcGxpY2FzIHByb3ZpcmluZyByZWFkb25seSBhY2Nlc3Mgd2hlbiB0aGlzIG9uZSBpcyBwcmltYXJ5LgogICAgICAgICogW1N0cmluZ10gIFNfQUxMT1dfQ09OTkVDVElPTlMgICAgICAtIEFsbG93ZWQgY29ubmVjdGlvbiB0eXBlcyBmb3IgIlNlY29uZGFyeSIgcmVwbGljYSBtb2RlLiBDYW4gYmUgb25lIG9mICJOTyIsICJSRUFEX09OTFkiLCAiQUxMIi4KICAgICAgICAqIFtTdHJpbmddICBTX1JFQURfT05MWV9ST1VUSU5HX1VSTCAgLSBSZXBsaWNhIHJlYWQtb25seSByZXF1ZXN0cyBsaXN0ZW5lciBVUkwuIE5vcm1hbGx5IGRlZmF1bHQgc2VydmVyIGxpc3RlbmVyIGF0IHBvcnQgMTQzMyBpcyB1c2VkLgoKICAgIC5QQVJBTUVURVIgUHJlZmVyZW5jZXMKICAgIEhhc2ggdGFibGUgb2YgZ2VuZXJhbCBhdmFpbGFiaWxpdHkgZ3JvdXAgcHJlZmVyZW5jZXMuIEFsbCB0aGUga2V5cyBhcmUgb3B0aW9uYWwuIFN1cHBvcnRlZCBlbnRyeSBrZXlzIGFyZToKCiAgICAgICAgKiBbU3RyaW5nXSAgQVVUT01BVEVEX0JBQ0tVUF9QUkVGRVJFTkNFIC0gQXV0b21hdGVkIGJhY2t1cCBwcmVmZXJlbmNlLiBDYW4gYmUgIlBSSU1BUlkiLCAiU0VDT05EQVJZX09OTFkiLCAiU0VDT05EQVJZIiBvciAiTk9ORSIuCiAgICAgICAgKiBbU3RyaW5nXSAgRkFJTFVSRV9DT05ESVRJT05fTEVWRUwgICAgIC0gRmFpbHVyZSBjb25kaXRpb24gbGV2ZWwuIENhbiBiZSAiMSIsICIyIiwgIjMiLCAiNCIgb3IgIjUiLgogICAgICAgICogW0ludGVnZXJdIEhFQUxUSF9DSEVDS19USU1FT1VUICAgICAgICAtIFJlcGxpY2EgaGVhbHRoIGNoZWNrIHRpbWVvdXQuCgogICAgLlBBUkFNRVRFUiBMaXN0ZW5lckRlZgogICAgSGFzaCB0YWJsZSBjb250YWluaW5nIGF2YWlsYWJpbGl0eSBncm91cCBsaXN0ZW5lciBjb25maWd1cmF0aW9uLgoKICAgIE1hbmRhdG9yeSBsaXN0ZW5lciBjb25maWd1cmF0aW9uIHZhbHVlcyBhcmU6CgogICAgICAgIFtTdHJpbmddIE5BTUUgLSBMaXN0ZW5lciBuYW1lLgoKICAgIE9wdGlvbmFsIGxpc3RlbmVyIGNvbmZpZ3VyYXRpb24gdmFsdWVzIGFyZToKICAgIAogICAgICAgIFtTdHJpbmddIFBPUlQgLSBMaXN0ZW5lciBwb3J0IG51bWJlci4gSW50ZWdlciB2YWx1ZSBtYXkgYmUgc3VmZml4ZWQgYnkgYSAiKyIgc3ltb2wgKHN1Y2ggYXMgIjUwMjIrIikgd2hpY2ggYWxsb3dzIHRoZSByb3V0aW5lIHRvCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdCBuZXh0IGZyZWUgcG9ydCB3aXRoIG51bWJlciBncmVhdGVyIG9yIGVxdWFsIHRvIHRoZSBzcGVjaWZpZWQgdmFsdWUuCiAgICAgICAgW1N0cmluZ10gREhDUCAtIERIQ1AgbGlzdGVuZXIgYWRkcmVzcyBjb25maWd1cmF0aW9uIGZsYWcuIFdoZW4gYW55IHZhbHVlIHNwZWNpZmllZCwgREhDUCBpcyB1c2VkIHRvIGNvbmZpZ3VyZSBsaXN0ZW5lcgogICAgICAgICAgICAgICAgICAgICAgICAodGhpcyBpcyBhbHNvIHRoZSBkZWZhdWx0IGJlaGF2aW9yKS4gQWxzbywgYSBzcGVjaWZpYyBpbnRlcmZhY2UgZm9yIERIQ1AgbWF5IGJlIHNwZWNpZmllZCBhcyBJUF9BRERSRVNTL01BU0sKICAgICAgICAgICAgICAgICAgICAgICAgKGxpa2UgIjE5Mi4xNjguMS4wLzI1NS4yNTUuMjU1LjAiKSBhcyBhIHZhbHVlIG9mIHRoZSBwYXJhbWV0ZXIuCiAgICAgICAgW0FycmF5XSBTVEFUSUMgLSBTdGF0aWMgSVAgYWRkcmVzc2VzIHRvIGxpc3Rlbi4gSVAgYWRkcmVzc2VzIG1heSBiZSBJUHY0IGFkZHJlc3NlcyBpbiB0aGUgIklQX0FERFJFU1MvTUFTSyIgZm9ybSBvciBJUHY2CiAgICAgICAgICAgICAgICAgICAgICAgIGFkZHJlc3NlcyBpbiBzdGFuZGFyZCBJUHY2IG5vdGF0aW9uLgoKICAgIFNlZSBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvZmY4NzgzOTkuYXNweCBwYWdlIGZvciBtb3JlIGRldGFpbHMgcmVnYXJkaW5nIGFsbCB0aGUgc3VwcG9ydGVkIG9wdGlvbnMuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFdvcmtEaXIsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kTmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbQXJyYXldJERhdGFiYXNlTmFtZXMsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW0FycmF5XSRSZXBsaWNhRGVmcywKICAgICAgICBbcGFyYW1ldGVyXQogICAgICAgIFtIYXNodGFibGVdJFByZWZlcmVuY2VzLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtIYXNodGFibGVdJExpc3RlbmVyRGVmCiAgICApCgogICAgaWYgKC1ub3QgKFRlc3QtUGF0aCAkV29ya0RpcikpIHsKICAgICAgICBbdm9pZF0oTmV3LUl0ZW0gLVR5cGUgRGlyZWN0b3J5ICRXb3JrRGlyKQogICAgfQogICAgJFdvcmtEaXIgPSAoR2V0LUl0ZW0gJFdvcmtEaXIpLkZ1bGxOYW1lCiAgICBpZiAoKEdldC1DaGlsZEl0ZW0gLVBhdGggJFdvcmtEaXIpLkxlbmd0aCAtZ3QgMCkgewogICAgICAgIHRocm93ICJXb3JraW5nIGRpcmVjdG9yeSAkV29ya0RpciBpcyBub3QgZW1wdHkiCiAgICB9CgogICAgJFF1b3RlZERCTmFtZXMgPSAoJERhdGFiYXNlTmFtZXMgfCBGb3JFYWNoLU9iamVjdCB7IENvbnZlcnRUby1TUUxOYW1lICRfIH0pIC1qb2luICIsICIKCiAgICBpZiAoJFByZWZlcmVuY2VzIC1lcSAkbnVsbCkgewogICAgICAgICRQcmVmZXJlbmNlcyA9IEAoKQogICAgfQogICAgJFByZWZzID0gQCgpCiAgICBmb3JlYWNoKCRQcmVmIGluICRQcmVmZXJlbmNlcykgewogICAgICAgIGlmICgkUHJlZi5LZXkgLWVxICRudWxsKSB7CiAgICAgICAgICAgIENvbnRpbnVlCiAgICAgICAgfQogICAgICAgIGlmICgkUHJlZi5LZXkgLWVxICJBVVRPTUFURURfQkFDS1VQX1BSRUZFUkVOQ0UiKSB7CiAgICAgICAgICAgICRQcmVmcyA9ICRQcmVmcyArIChWYWxpZGF0ZS1PcHRpb24gJFByZWYuS2V5LCAkUHJlZi5WYWx1ZSwgQCgiUFJJTUFSWSIsICJTRUNPTkRBUllfT05MWSIsICJTRUNPTkRBUlkiLCAiTk9ORSIpIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgJFByZWYuS2V5KQogICAgICAgIH0gZWxzZWlmICgkUHJlZi5LZXkgLWVxICJGQUlMVVJFX0NPTkRJVElPTl9MRVZFTCIpIHsKICAgICAgICAgICAgJFByZWZzID0gJFByZWZzICsgKFZhbGlkYXRlLU9wdGlvbiAkUHJlZi5LZXksICRQcmVmLlZhbHVlLCBAKCIxIiwgIjIiLCAiMyIsICI0IiwgIjUiKSB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICRQcmVmLktleSkKICAgICAgICB9IGVsc2VpZiAoJFByZWYuS2V5IC1lcSAiSEVBTFRIX0NIRUNLX1RJTUVPVVQiKSB7CiAgICAgICAgICAgICRQcmVmcyA9ICRQcmVmcyArIChWYWxpZGF0ZS1JbnRPcHRpb24gJFByZWYuS2V5LCAkUHJlZi5WYWx1ZSB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICRQcmVmLktleSkKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aHJvdyAiVW5leHBlY3RlZCBwZWZlcmVuY2VzIG9wdGlvbjogJyQoJFByZWYuS2V5KSciCiAgICAgICAgfQogICAgfQoKICAgICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSA9IEAoKQogICAgZm9yICgkaSA9IDA7ICRpIC1sdCAkUmVwbGljYURlZnMuTGVuZ3RoOyAkaSsrKSB7CiAgICAgICAgJFJEZWYgPSAkUmVwbGljYURlZnNbJGldCiAgICAgICAgaWYgKCRSRGVmLkdldFR5cGUoKS5OYW1lIC1uZSAiSGFzaHRhYmxlIikgewogICAgICAgICAgICB0aHJvdyAiQWxsIGVsZW1lbnRzIG9mIFJlcGxpY2FEZWZzIGFycmF5IHNob3VsZCBiZSBIYXNodGFibGVzIgogICAgICAgIH0KCiAgICAgICAgJFJlcGxpY2FPcHRzID0gQCgpCgogICAgICAgICMgTWFuZGF0b3J5IG9wdGlvbnMKICAgICAgICAkUmVwbGljYU5hbWUgPSBWYWxpZGF0ZS1EZWZpbmVkT3B0aW9uICJTRVJWRVJfSU5TVEFOQ0UiICRSRGVmWyJTRVJWRVJfSU5TVEFOQ0UiXQogICAgICAgICRSZXBsaWNhT3B0cyA9ICRSZXBsaWNhT3B0cyArIChWYWxpZGF0ZS1EZWZpbmVkT3B0aW9uICJFTkRQT0lOVF9VUkwiICRSRGVmWyJFTkRQT0lOVF9VUkwiXSB8IENvbnZlcnRUby1TUUxTdHJpbmcgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiRU5EUE9JTlRfVVJMIikKICAgICAgICAkUmVwbGljYU9wdHMgPSAkUmVwbGljYU9wdHMgKyAoVmFsaWRhdGUtT3B0aW9uICJBVkFJTEFCSUxJVFlfTU9ERSIgJFJEZWZbIkFWQUlMQUJJTElUWV9NT0RFIl0gQCgiU1lOQ0hST05PVVNfQ09NTUlUIiwgIkFTWU5DSFJPTk9VU19DT01NSVQiKSB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJBVkFJTEFCSUxJVFlfTU9ERSIpCiAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLU9wdGlvbiAiRkFJTE9WRVJfTU9ERSIgJFJEZWZbIkZBSUxPVkVSX01PREUiXSBAKCJBVVRPTUFUSUMiLCAiTUFOVUFMIikgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiRkFJTE9WRVJfTU9ERSIpCgogICAgICAgICMgT3B0aW9uYWwgb3B0aW9ucwogICAgICAgIGlmICgkUkRlZlsiQkFDS1VQX1BSSU9SSVRZIl0gLW5lICRudWxsKSB7CiAgICAgICAgICAgICRSZXBsaWNhT3B0cyA9ICRSZXBsaWNhT3B0cyArIChWYWxpZGF0ZS1JbnRPcHRpb24gIkJBQ0tVUF9QUklPUklUWSIgJFJEZWZbIkJBQ0tVUF9QUklPUklUWSJdIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIkJBQ0tVUF9QUklPUklUWSIpCiAgICAgICAgfQogICAgICAgIGlmICgkUkRlZlsiU0VTU0lPTl9USU1FT1VUIl0gLW5lICRudWxsKSB7CiAgICAgICAgICAgICRSZXBsaWNhT3B0cyA9ICRSZXBsaWNhT3B0cyArIChWYWxpZGF0ZS1JbnRPcHRpb24gIlNFU1NJT05fVElNRU9VVCIgJFJEZWZbIlNFU1NJT05fVElNRU9VVCJdIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIlNFU1NJT05fVElNRU9VVCIpCiAgICAgICAgfQoKICAgICAgICAkU2Vjb25kYXJ5Um9sZSA9IEAoKQogICAgICAgIGlmICgkUkRlZlsiU19BTExPV19DT05ORUNUSU9OUyJdIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkU2Vjb25kYXJ5Um9sZSA9ICRTZWNvbmRhcnlSb2xlICsgKFZhbGlkYXRlLU9wdGlvbiAiU19BTExPV19DT05ORUNUSU9OUyIgJFJEZWZbIlNfQUxMT1dfQ09OTkVDVElPTlMiXSBAKCJOTyIsICJSRUFEX09OTFkiLCAiQUxMIikgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFJEZWZbIlNfUkVBRF9PTkxZX1JPVVRJTkdfVVJMIl0gLW5lICRudWxsKSB7CiAgICAgICAgICAgICRTZWNvbmRhcnlSb2xlID0gJFNlY29uZGFyeVJvbGUgKyAoJFJEZWZbIlNfUkVBRF9PTkxZX1JPVVRJTkdfVVJMIl0gfCBDb252ZXJ0VG8tU1FMU3RyaW5nIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIkFMTE9XX0NPTk5FQ1RJT05TIikKICAgICAgICB9CiAgICAgICAgaWYgKCRTZWNvbmRhcnlSb2xlLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICAgICAkUmVwbGljYU9wdHMgPSAkUmVwbGljYU9wdHMgKyAoIiggJCgkU2Vjb25kYXJ5Um9sZSAtam9pbiAnLCAnKSApIiB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJTRUNPTkRBUllfUk9MRSIpCiAgICAgICAgfQoKICAgICAgICAkUHJpbWFyeVJvbGUgPSBAKCkKICAgICAgICBpZiAoJFJEZWZbIlBfQUxMT1dfQ09OTkVDVElPTlMiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFByaW1hcnlSb2xlID0gJFByaW1hcnlSb2xlICsgKFZhbGlkYXRlLU9wdGlvbiAiUF9BTExPV19DT05ORUNUSU9OUyIgJFJEZWZbIlBfQUxMT1dfQ09OTkVDVElPTlMiXSBAKCJSRUFEX1dSSVRFIiwgIkFMTCIpIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIkFMTE9XX0NPTk5FQ1RJT05TIikKICAgICAgICB9CiAgICAgICAgaWYgKCRSRGVmWyJQX1JFQURfT05MWV9ST1VUSU5HX0xJU1QiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFByaW1hcnlSb2xlID0gJFByaW1hcnlSb2xlICsgKCgoJFJEZWZbIlBfUkVBRF9PTkxZX1JPVVRJTkdfTElTVCJdIHwgRm9yRWFjaC1PYmplY3QgeyBDb252ZXJ0VG8tU1FMU3RyaW5nICRfIH0pIC1qb2luICcsICcpIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIkFMTE9XX0NPTk5FQ1RJT05TIikKICAgICAgICB9CiAgICAgICAgaWYgKCRQcmltYXJ5Um9sZS5MZW5ndGggLWd0IDApIHsKICAgICAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKCIoICQoJFByaW1hcnlSb2xlIC1qb2luICcsICcpICkiIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIlBSSU1BUllfUk9MRSIpCiAgICAgICAgfQoKICAgICAgICAkUmVwbGljYURlZmluaXRpb25zQXJyYXkgPSAkUmVwbGljYURlZmluaXRpb25zQXJyYXkgKwogICAgICAgICAgICAjICBUQ1A6Ly9icmF2by5tdXJhbm8ubG9jYWw6NTAyMgogICAgICAgICAgICAiTiQoQ29udmVydFRvLVNRTFN0cmluZyAkUmVwbGljYU5hbWUpIFdJVEggKCQoJFJlcGxpY2FPcHRzIC1qb2luICcsICcpKSIKICAgIH0KICAgICRSZXBsaWNhRGVmaW5pdGlvbnMgPSAkUmVwbGljYURlZmluaXRpb25zQXJyYXkgLWpvaW4gIixgcmBuICAgICAgICAiOwoKICAgIGlmICgkTGlzdGVuZXJEZWZbIkRIQ1AiXSAtbmUgJG51bGwpIHsKICAgICAgICBpZiAoJExpc3RlbmVyRGVmWyJESENQIl0ubWF0Y2hlcygiXGQrXGQrXGQrXGQrL1xkK1xkK1xkK1xkKyIpKSB7CiAgICAgICAgICAgICgkSXBBZGRyLCAkTWFzaykgPSAkTGlzdGVuZXJEZWZbIkRIQ1AiXSAtc3BsaXQgIi8iCiAgICAgICAgICAgICRMaXN0ZW5lckFkZHIgPSAiREhDUCBPTiAoICRJcEFkZHIsICRNYXNrICkiCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICJESENQIgogICAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgICAgW2FycmF5XSRJUEFkZHJlc3NlcyA9ICRMaXN0ZW5lckRlZlsiU1RBVElDIl0KICAgICAgICBpZiAoKCRJUEFkZHJlc3NlcyAtZXEgJG51bGwpIC1vciAoJElQQWRkcmVzc2VzLkNvdW50IC1lcSAwKSkgewogICAgICAgICAgICAkTGlzdGVuZXJBZGRyID0gIkRIQ1AiCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgJENvbnZlcnRlZE9wdHMgPSBAKCkKICAgICAgICAgICAgZm9yZWFjaCAoJElwT3B0aW9uIGluICRJUEFkZHJlc3NlcykgewogICAgICAgICAgICAgICAgIyBJUHY0CiAgICAgICAgICAgICAgICBpZiAoJElwT3B0aW9uIC1tYXRjaCAiXGQrXGQrXGQrXGQrL1xkK1xkK1xkK1xkKyIpIHsKICAgICAgICAgICAgICAgICAgICAoJElwQWRkciwgJE1hc2spID0gJElwT3B0aW9uIC1zcGxpdCAiLyIKICAgICAgICAgICAgICAgICAgICAkQ29udmVydGVkT3B0cyA9ICRDb252ZXJ0ZWRPcHRzICsgIiggJChDb252ZXJ0VG8tU1FMU3RyaW5nICRJcEFkZHIpLCAkKENvbnZlcnRUby1TUUxTdHJpbmcgJE1hc2spICkiCiAgICAgICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICMgSVB2NgogICAgICAgICAgICAgICAgaWYgKCRJcE9wdGlvbiAtbWF0Y2ggIl4oKCg/PSg/Pi4qPzo6KSg/IS4qOjopKSkoOjopPyhbMC05QS1GXXsxLDR9Ojo/KXswLDV9fChbMC05QS1GXXsxLDR9Oil7Nn0pKFwyKFswLTlBLUZdezEsNH0oOjo/fCQpKXswLDJ9fCgoMjVbMC01XXwoMlswLTRdfDFcZHxbMS05XSk/XGQpKFwufCQpKXs0fXxbMC05QS1GXXsxLDR9OlswLTlBLUZdezEsNH0pKD88IVteOl06fFwuKVx6IikgewogICAgICAgICAgICAgICAgICAgICRDb252ZXJ0ZWRPcHRzID0gJENvbnZlcnRlZE9wdHMgKyAiKCAkKENvbnZlcnRUby1TUUxTdHJpbmcgJElwT3B0aW9uKSApIgogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB0aHJvdyAiTWFsZm9ybWVkIElQdjQvSVB2NiBhZGRyZXNzOiAkSXBPcHRpb24iCiAgICAgICAgICAgIH0KICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICJJUCAoICQoJENvbnZlcnRlZE9wdHMgLWpvaW4gJywgJykgKSIKICAgICAgICB9CiAgICB9CiAgICBpZiAoKCRMaXN0ZW5lckRlZlsiTkFNRSJdIC1lcSAkbnVsbCkgLW9yICgkTGlzdGVuZXJEZWZbIk5BTUUiXSAtbWF0Y2ggIl5ccyokIikpIHsKICAgICAgICB0aHJvdyAiTGlzdGVuZXIgbmFtZSBpcyByZXF1aXJlZCIKICAgIH0KICAgIGlmICgtbm90ICgkTGlzdGVuZXJEZWZbIk5BTUUiXSAtbWF0Y2ggIl5bQS1aYS16MC05XC5fXC1dKyQiKSkgewogICAgICAgIHRocm93ICJJbGxlZ2FsIGxpc3RlbmVyIG5hbWUuIEl0IGNhbiBjb250YWluIG9ubHkgYWxwaGFudW1lcmljIGNoYXJhY3RlcnMsIGRhc2hlcyAoLSksIGFuZCBoeXBoZW5zIChfKSwgaW4gYW55IG9yZGVyLiIKICAgIH0KICAgICRQb3J0ID0gJG51bGwKICAgIGlmICgkTGlzdGVuZXJEZWZbIlBPUlQiXSAtbmUgJG51bGwpIHsKICAgICAgICBpZiAoJExpc3RlbmVyRGVmWyJQT1JUIl0gLW1hdGNoICJcZCtcKyIpIHsKICAgICAgICAgICAgJFN0YXJ0aW5nUG9ydCA9ICRMaXN0ZW5lckRlZlsiUE9SVCJdIC1yZXBsYWNlICJcKyIsICIiCiAgICAgICAgICAgICRQb3J0ID0gR2V0LU5leHRGcmVlUG9ydCAkU3RhcnRpbmdQb3J0CiAgICAgICAgICAgICRMaXN0ZW5lckFkZHIgPSAkTGlzdGVuZXJBZGRyICsgIiwgUE9SVCA9ICRQb3J0IgogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmICgkTGlzdGVuZXJEZWZbIlBPUlQiXSAtbWF0Y2ggIlxkKyIpIHsKICAgICAgICAgICAgICAgICRMaXN0ZW5lckFkZHIgPSAkTGlzdGVuZXJBZGRyICsgIiwgUE9SVCA9ICQoJExpc3RlbmVyRGVmWyJQT1JUIl0pIgogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgdGhyb3cgIkludmFsaWQgcG9ydCB2YWx1ZTogJCgkTGlzdGVuZXJEZWZbIlBPUlQiXSkiCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICAkTGlzdGVuZXIgPSAiTElTVEVORVIgJyQoJExpc3RlbmVyRGVmWyJOQU1FIl0pJyAoIFdJVEggJExpc3RlbmVyQWRkciApIgoKICAgICROYW1lIHwgT3V0LUZpbGUgIiRXb3JrRGlyXGF2Z3JvdXAubmFtZSIKICAgIAogICAgZm9yICgkaSA9IDA7ICRpIC1sdCAkRGF0YWJhc2VOYW1lcy5MZW5ndGg7ICRpKyspIHsKICAgICAgICAkRGF0YUJhc2VOYW1lID0gJERhdGFiYXNlTmFtZXNbJGldCiAgICAgICAgJERhdGFCYXNlTmFtZSB8IE91dC1GaWxlICIkV29ya0RpclxkYiRpLm5hbWUiCiAgICAgICAgTmV3LVNRTERhdGFiYXNlICREYXRhQmFzZU5hbWUKICAgICAgICAkQmFja3VwRGIgPSAiQkFDS1VQIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgVE8gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXGRiJGkuYmFrIikgV0lUSCBOT0ZPUk1BVCwgSU5JVCwgTkFNRSA9IE4nRnVsbCBEYXRhYmFzZSBCYWNrdXAnLCBTS0lQLCBOT1JFV0lORCwgTk9VTkxPQUQsIFNUQVRTID0gMTAKICAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJEJhY2t1cERiKQogICAgICAgICRCYWNrdXBMb2cgPSAiQkFDS1VQIExPRyAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIFRPIERJU0sgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICIkV29ya0RpclxkYiR7aX0ubG9nLmJhayIpIFdJVEggTk9GT1JNQVQsIElOSVQsICBOQU1FID0gTidUcmFuc2FjdGlvbiBMb2cgIEJhY2t1cCcsIFNLSVAsIE5PUkVXSU5ELCBOT1VOTE9BRCwgU1RBVFMgPSAxMAogICAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJEJhY2t1cExvZykKICAgIH0KICAgICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSA9IEAoKQogICAgaWYgKCRQcmVmcy5MZW5ndGggLWd0IDApIHsKICAgICAgICAkUHJlZnNMaW5lID0gIldJVEggKCAkKCRQcmVmcyAtam9pbiAnLCAnKSApIgogICAgfSBlbHNlIHsKICAgICAgICAkUHJlZnNMaW5lID0gIiIKICAgIH0KICAgICRTUUwgPSAiQ1JFQVRFIEFWQUlMQUJJTElUWSBHUk9VUCAkKENvbnZlcnRUby1TUUxOYW1lICROYW1lKSAkUHJlZnNMaW5lCiAgICAgICAgICAgICAgICBGT1IgREFUQUJBU0UgJFF1b3RlZERCTmFtZXMKICAgICAgICAgICAgICAgIFJFUExJQ0EgT05gcmBuICAgICAgICAkUmVwbGljYURlZmluaXRpb25zCiAgICAgICAgICAgICAgICAkTGlzdGVuZXI7CiAgICAiCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkU1FMKQogICAgcmV0dXJuICRQb3J0Cn0KCmZ1bmN0aW9uIE5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwUmVwbGljYSB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIEFsd2F5c09uIGF2YWlsYWJpbGl0eSBncm91cCBzZWNvbmRhcnkgcmVwbGljYQoKICAgIC5ERVNDUklQVElPTgogICAgQ3JlYXRlcyBBbHdheXNPbiBhdmFpbGFiaWxpdHkgZ3JvdXAgc2Vjb25kYXJ5IHJlcGxpY2EgYmFzZWQgb24gaW5mb3JtYXRpb24gcHJvdmlkZWQgdG8gYW5kIGJ5IE5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwLgoKICAgIC5QQVJBTUVURVIgV29ya0RpcgogICAgV29ya2luZyBkaXJlY3Rvcnkgd2hpY2ggd2FzIHRyYW5zZmVycmVkIGZyb20gdGhlIHByaW1hcnkgcmVwbGljYS4KICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRXb3JrRGlyCiAgICApCiAgICBpZiAoLW5vdCAoVGVzdC1QYXRoICRXb3JrRGlyKSkgewogICAgICAgIHRocm93ICJXb3JrIGRpciAnJFdvcmtEaXInIG5vdCBmb3VuZCIKICAgIH0KICAgICRXb3JrRGlyT2JqID0gR2V0LUl0ZW0gLVBhdGggJFdvcmtEaXIKICAgICRXb3JrRGlyID0gJFdvcmtEaXJPYmouRnVsbE5hbWUKICAgICRHcm91cE5hbWUgPSBHZXQtQ29udGVudCAkV29ya0Rpck9iai5HZXRGaWxlcygiYXZncm91cC5uYW1lIikuRnVsbE5hbWUKCiAgICAkSm9pbkdyb3VwID0gIkFMVEVSIEFWQUlMQUJJTElUWSBHUk9VUCAkKENvbnZlcnRUby1TUUxOYW1lICRHcm91cE5hbWUpIEpPSU4KICAgICAgICAgICAgICAgICAgIEdPIgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJEpvaW5Hcm91cCkKCiAgICBmb3IgKCRpID0gMDsgOyAkaSsrKSB7CiAgICAgICAgJEZpbGUgPSAkV29ya0Rpck9iai5HZXRGaWxlcygiZGIkaS5uYW1lIikKICAgICAgICBpZiAoLW5vdCAkRmlsZSkgewogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgJERhdGFCYXNlTmFtZSA9IEdldC1Db250ZW50ICRXb3JrRGlyT2JqLkdldEZpbGVzKCJkYiRpLm5hbWUiKS5GdWxsTmFtZQogICAgICAgICRSZXN0b3JlRGIgPSAiUkVTVE9SRSBEQVRBQkFTRSAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIEZST00gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXGRiJGkuYmFrIikgV0lUSCBGSUxFID0gMSwgTk9SRUNPVkVSWSwgTk9VTkxPQUQsIFJFUExBQ0UsIFNUQVRTID0gNQogICAgICAgICAgICAgICAgICAgIEdPIgogICAgICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRSZXN0b3JlRGIpCiAgICAgICAgJFJlc3RvcmVMb2cgPSAiUkVTVE9SRSBMT0cgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBGUk9NIERJU0sgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICIkV29ya0RpclxkYiRpLmxvZy5iYWsiKSBXSVRIIEZJTEUgPSAxLCBOT1JFQ09WRVJZLCBOT1VOTE9BRCwgU1RBVFMgPSAxMAogICAgICAgICAgICAgICAgICAgIEdPIgogICAgICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRSZXN0b3JlTG9nKQogICAgICAgICRBbHRlckRCID0gIkFMVEVSIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgU0VUIEhBRFIgQVZBSUxBQklMSVRZIEdST1VQID0gJChDb252ZXJ0VG8tU1FMTmFtZSAkR3JvdXBOYW1lKQogICAgICAgICAgICAgICAgICAgIEdPIgogICAgICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRBbHRlckRCKQogICAgfQp9CgpmdW5jdGlvbiBOZXctUmVwbGljYU9wdGlvbiB7CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUsIFZhbHVlRnJvbVBpcGVsaW5lID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFZhbHVlCiAgICApCiAgICByZXR1cm4gIiROYW1lID0gJFZhbHVlIgp9CgpmdW5jdGlvbiBWYWxpZGF0ZS1PcHRpb24gewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ2hlY2tzIHRoYXQgdGhlIHZhbHVlIGlzIG9uZSBvZiBhbGxvd2VkIHZhbHVlcwoKICAgIC5ERVNDUklQVElPTgogICAgQ2hlY2tzIHRoYXQgdGhlIHZhbHVlIGlzIG9uZSBvZiBhbGxvd2VkIHZhbHVlcyBvciB0aHJvd3MgZXhjZXB0aW9uIG90aGVyd2lzZS4gUmV0dXJucyBwcm92aWRlZCB2YWx1ZS4KCiAgICAuUEFSQU1FVEVSIE5hbWUKICAgIE9wdGlvbiBuYW1lLiBVc2VkIG9ubHkgZm9yIGVycm9yIG1lc3NhZ2UuCgogICAgLlBBUkFNRVRFUiBWYWx1ZQogICAgT3B0aW9uIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgQWxsb3dlZAogICAgTGlzdCBvZiBhbGxvd2VkIG9wdGlvbiB2YWx1cy4KICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSROYW1lLAogICAgICAgIFtTdHJpbmddJFZhbHVlLAogICAgICAgIFtBcnJheV0kQWxsb3dlZAogICAgKQogICAgaWYgKCgkVmFsdWUgLWVxICRudWxsKSAtb3IgKCRWYWx1ZSAtZXEgIiIpKSB7CiAgICAgICAgdGhyb3cgIk5vIHZhbHVlIHdhcyBwcm92aWRlZCBmb3IgJE5hbWUiCiAgICB9CiAgICBmb3JlYWNoICgkViBpbiAkQWxsb3dlZCkgewogICAgICAgIGlmICgkViAtZXEgJFZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiAkVmFsdWUKICAgICAgICB9CiAgICB9CiAgICB0aHJvdyAiUHJvdmlkZWQgdmFsdWUgJyRWYWx1ZScgZm9yICROYW1lIGlzIG5vdCBvbmUgb2YgJCgkQWxsb3dlZCAtam9pbiAnLCAnKSIKfQoKZnVuY3Rpb24gVmFsaWRhdGUtSW50T3B0aW9uIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENoZWNrcyB0aGF0IHRoZSB2YWx1ZSBpcyBpbnRlZ2VyCgogICAgLkRFU0NSSVBUSU9OCiAgICBDaGVja3MgdGhhdCB0aGUgdmFsdWUgaXMgaW50ZWdlci4gUmV0dXJucyBwcm92aWRlZCB2YWx1ZS4KCiAgICAuUEFSQU1FVEVSIE5hbWUKICAgIE9wdGlvbiBuYW1lLiBVc2VkIG9ubHkgZm9yIGVycm9yIG1lc3NhZ2UuCgogICAgLlBBUkFNRVRFUiBWYWx1ZQogICAgT3B0aW9uIHZhbHVlLgogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcl0KICAgICAgICBbU3RyaW5nXSRWYWx1ZQogICAgKQogICAgaWYgKCgkVmFsdWUgLWVxICRudWxsKSAtb3IgKCRWYWx1ZSAtZXEgIiIpKSB7CiAgICAgICAgdGhyb3cgIk5vIHZhbHVlIHdhcyBwcm92aWRlZCBmb3IgJE5hbWUiCiAgICB9CiAgICBpZiAoLW5vdCAoIiRWYWx1ZSIgLW1hdGNoICJeWystXT9cZCskIikpIHsKICAgICAgICB0aHJvdyAiUHJvdmlkZWQgdmFsdWUgJyRWYWx1ZScgZm9yICROYW1lIGlzIG5vdCBhIG51bWJlciIKICAgIH0KICAgIHJldHVybiAkVmFsdWUKfQoKZnVuY3Rpb24gVmFsaWRhdGUtRGVmaW5lZE9wdGlvbiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDaGVja3MgdGhhdCB0aGUgdmFsdWUgaXMgbm90IG51bGwKCiAgICAuREVTQ1JJUFRJT04KICAgIENoZWNrcyB0aGF0IHRoZSB2YWx1ZSBpcyBub3QgbnVsbC4gUmV0dXJucyBwcm92aWRlZCB2YWx1ZS4KCiAgICAuUEFSQU1FVEVSIE5hbWUKICAgIE9wdGlvbiBuYW1lLiBVc2VkIG9ubHkgZm9yIGVycm9yIG1lc3NhZ2UuCgogICAgLlBBUkFNRVRFUiBWYWx1ZQogICAgT3B0aW9uIHZhbHVlLgogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkZmFsc2UpXQogICAgICAgIFtTdHJpbmddJFZhbHVlCiAgICApCiAgICBpZiAoKCRWYWx1ZSAtZXEgJG51bGwpIC1vciAoJFZhbHVlIC1lcSAiIikpIHsKICAgICAgICB0aHJvdyAiTm8gdmFsdWUgd2FzIHByb3ZpZGVkIGZvciAkTmFtZSIKICAgIH0KICAgIHJldHVybiAkVmFsdWUKfQoKCiNFeHBvcnQtTW9kdWxlTWVtYmVyIC1GdW5jdGlvbiBOZXctU1FMU2VydmVyCiNFeHBvcnQtTW9kdWxlTWVtYmVyIC1GdW5jdGlvbiBOZXctU1FMU2VydmVyRm9yQU9BRwojRXhwb3J0LU1vZHVsZU1lbWJlciAtRnVuY3Rpb24gUmVtb3ZlLVNRTFNlcnZlcgojRXhwb3J0LU1vZHVsZU1lbWJlciAtRnVuY3Rpb24gSW52b2tlLVNRTFRleHQKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIEluaXRpYWxpemUtTWlycm9yaW5nRW5kcG9pbnQKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nUHJpbmNpcGFsU3RlcDEKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDEKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nUHJpbmNpcGFsU3RlcDIKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDIKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nUHJpbmNpcGFsU3RlcDMKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDMKI0V4cG9ydC1Nb2R1bGVNZW1iZXIgLUZ1bmN0aW9uIEluc3RhbGwtU1FMU2VydmVyRm9yU3lzUHJlcAojRXhwb3J0LU1vZHVsZU1lbWJlciAtRnVuY3Rpb24gQ29tcGxldGUtU1FMU2VydmVyQWZ0ZXJTeXNQcmVwCiNFeHBvcnQtTW9kdWxlTWVtYmVyIC1GdW5jdGlvbiBJbml0aWFsaXplLUFsd2F5c09uCiNFeHBvcnQtTW9kdWxlTWVtYmVyIC1GdW5jdGlvbiBOZXctQWx3YXlzT25BdmFpbGFiaWxpdHlHcm91cAojRXhwb3J0LU1vZHVsZU1lbWJlciAtRnVuY3Rpb24gTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXBSZXBsaWNhCg==", - "RnVuY3Rpb24gQ29udmVydFRvLUJvb2xlYW4gewogICAgcGFyYW0gKAogICAgICAgICRJbnB1dE9iamVjdCwKICAgICAgICBbQm9vbGVhbl0gJERlZmF1bHQgPSAkZmFsc2UKICAgICkKICAgIHRyeSB7CiAgICAgICAgW1N5c3RlbS5Db252ZXJ0XTo6VG9Cb29sZWFuKCRJbnB1dE9iamVjdCkKICAgIH0KICAgIGNhdGNoIHsKICAgICAgICAkRGVmYXVsdAogICAgfQp9CgpGdW5jdGlvbiBTaG93LUVudmlyb25tZW50IHsKICAgIGZvcmVhY2ggKCRpdGVtIGluIChHZXQtQ2hpbGRJdGVtIEVudjopKSB7CiAgICAgICAgV3JpdGUtTG9nICgiJ3swfScgLS0+ICd7MX0nIiAtZiAkaXRlbS5OYW1lLCAkaXRlbS5WYWx1ZSkKICAgIH0KfQoKRnVuY3Rpb24gSW5zdGFsbC1TcWxTZXJ2ZXIgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJywKICAgICAgICBbU3RyaW5nXSAkU0FQYXNzd29yZCA9ICcnLAogICAgICAgIFtTdHJpbmddICRNdXJhbm9GaWxlU2hhcmUgPSAnJywKICAgICAgICBbU3dpdGNoXSAkTWl4ZWRNb2RlQXV0aCA9ICRmYWxzZSwKICAgICAgICBbU3dpdGNoXSAkVXBkYXRlRW5hYmxlZCA9ICRmYWxzZQogICAgKQogICAgCiAgICBpZiAoJFNldHVwUm9vdCAtZXEgJycpIHsKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgJFNldHVwUm9vdCA9IFtJTy5QYXRoXTo6Q29tYmluZSgkTXVyYW5vRmlsZVNoYXJlLCAnUHJlcmVxdWlzaXRlc1xTUUwgU2VydmVyXDIwMTInKQogICAgfQogICAgCiAgICAjJE1peGVkTW9kZUF1dGhTd2l0Y2ggPSBDb252ZXJ0VG8tQm9vbGVhbiAkTWl4ZWRNb2RlQXV0aAoKICAgICRFeHRyYU9wdGlvbnMgPSBAe30KICAgIAogICAgaWYgKCRNaXhlZE1vZGVBdXRoIC1lcSAkdHJ1ZSkgewogICAgICAgICRFeHRyYU9wdGlvbnMgKz0gQHsnU0VDVVJJVFlNT0RFJyA9ICdTUUwnfQogICAgICAgIGlmICgkU0FQYXNzd29yZCAtZXEgJycpIHsKICAgICAgICAgICAgdGhyb3coIlNBUGFzc3dvcmQgbXVzdCBiZSBzZXQgd2hlbiBNaXhlZE1vZGVBdXRoIGlzIHJlcXVpc3RlZCEiKQogICAgICAgIH0KICAgIH0KICAgIAogICAgaWYgKCRTQVBhc3N3b3JkIC1uZSAnJykgewogICAgICAgICRFeHRyYU9wdGlvbnMgKz0gQHsnU0FQV0QnID0gJFNBUGFzc3dvcmR9CiAgICB9CgogICAgaWYgKC1ub3QgJFVwZGF0ZUVuYWJsZWQpIHsKICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJGZhbHNlfQogICAgfQoKICAgIFNob3ctRW52aXJvbm1lbnQKCiAgICBOZXctU3FsU2VydmVyIC1TZXR1cFJvb3QgJFNldHVwUm9vdCAtRXh0cmFPcHRpb25zICRFeHRyYU9wdGlvbnMKfQo=" - ] + "RebootOnCompletion": 0 } \ No newline at end of file diff --git a/data/templates/agent/JoinDomain.template b/data/templates/agent/JoinDomain.template index f2e7a24..3d8cbef 100644 --- a/data/templates/agent/JoinDomain.template +++ b/data/templates/agent/JoinDomain.template @@ -1,11 +1,9 @@ { + "Scripts": [ + "ImportCoreFunctions.ps1", + "Join-Domain.ps1" + ], "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, { "Name": "Set-NetworkAdapterConfiguration", "Arguments": { @@ -23,8 +21,5 @@ } } ], - "RebootOnCompletion": 1, - "Scripts": [ - "RnVuY3Rpb24gSm9pbi1Eb21haW4gewo8IwouU1lOT1BTSVMKRXhlY3V0ZXMgIkpvaW4gZG9tYWluIiBhY3Rpb24uCgpSZXF1aXJlcyAnQ29yZUZ1bmN0aW9ucycgbW9kdWxlLgojPgoJcGFyYW0gKAoJCVtTdHJpbmddICREb21haW5OYW1lID0gJycsCgkJW1N0cmluZ10gJFVzZXJOYW1lID0gJycsCgkJW1N0cmluZ10gJFBhc3N3b3JkID0gJycsCgkJW1N0cmluZ10gJE9VUGF0aCA9ICcnLAogICAgICAgIFtTd2l0Y2hdICRBbGxvd1Jlc3RhcnQKCSkKCQoJaWYgKCRVc2VyTmFtZSAtZXEgJycpIHsKCQkkVXNlck5hbWUgPSAnQWRtaW5pc3RyYXRvcicKCX0KCgkkQ3JlZGVudGlhbCA9IE5ldy1DcmVkZW50aWFsIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJFVzZXJOYW1lIiAtUGFzc3dvcmQgJFBhc3N3b3JkCgoJaWYgKFRlc3QtQ29tcHV0ZXJOYW1lIC1Eb21haW5OYW1lICREb21haW5OYW1lKSB7CiAgICAgICAgV3JpdGUtTG9nV2FybmluZyAiQ29tcHV0ZXIgYWxyZWFkeSBqb2luZWQgdG8gZG9tYWluICckRG9tYWluTmFtZSciCgl9CgllbHNlIHsKCQlXcml0ZS1Mb2cgIkpvaW5pbmcgY29tcHV0ZXIgdG8gZG9tYWluICckRG9tYWluTmFtZScgLi4uIgoJCQoJCWlmICgkT1VQYXRoIC1lcSAnJykgewoJCQlBZGQtQ29tcHV0ZXIgLURvbWFpbk5hbWUgJERvbWFpbk5hbWUgLUNyZWRlbnRpYWwgJENyZWRlbnRpYWwgLUZvcmNlIC1FcnJvckFjdGlvbiBTdG9wCgkJfQoJCWVsc2UgewoJCQlBZGQtQ29tcHV0ZXIgLURvbWFpbk5hbWUgJERvbWFpbk5hbWUgLUNyZWRlbnRpYWwgJENyZWRlbnRpYWwgLU9VUGF0aCAkT1VQYXRoIC1Gb3JjZSAtRXJyb3JBY3Rpb24gU3RvcAoJCX0KCQkKICAgICAgICBpZiAoJEFsbG93UmVzdGFydCkgewogICAgICAgICAgICBXcml0ZS1Mb2cgIlJlc3RhcnRpbmcgY29tcHV0ZXIgLi4uIgogICAgICAgICAgICBSZXN0YXJ0LUNvbXB1dGVyIC1Gb3JjZQogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgV3JpdGUtTG9nICJQbGVhc2UgcmVzdGFydCB0aGUgY29tcHV0ZXIgbm93LiIKICAgICAgICB9Cgl9Cn0K" - ] + "RebootOnCompletion": 1 } \ No newline at end of file diff --git a/data/templates/agent/LeaveDomain.template b/data/templates/agent/LeaveDomain.template index c4e95d6..262ac0b 100644 --- a/data/templates/agent/LeaveDomain.template +++ b/data/templates/agent/LeaveDomain.template @@ -1,5 +1,5 @@ { + "Scripts": [], "Commands": [], "RebootOnCompletion": 0, - "Scripts": [] } \ No newline at end of file diff --git a/data/templates/agent/SetPassword.template b/data/templates/agent/SetPassword.template index 1cc9dcc..02f7482 100644 --- a/data/templates/agent/SetPassword.template +++ b/data/templates/agent/SetPassword.template @@ -1,14 +1,9 @@ { "Scripts": [ - "RnVuY3Rpb24gU2V0LUxvY2FsVXNlclBhc3N3b3JkIHsNCiAgICBwYXJhbSAoDQogICAgICAgIFtTdHJpbmddICRVc2VyTmFtZSwNCiAgICAgICAgW1N0cmluZ10gJFBhc3N3b3JkLA0KICAgICAgICBbU3dpdGNoXSAkRm9yY2UNCiAgICApDQogICAgDQogICAgdHJhcCB7IFN0b3AtRXhlY3V0aW9uICRfIH0NCiAgICANCiAgICBpZiAoKEdldC1XbWlPYmplY3QgV2luMzJfVXNlckFjY291bnQgLUZpbHRlciAiTG9jYWxBY2NvdW50ID0gJ1RydWUnIEFORCBOYW1lPSckVXNlck5hbWUnIikgLWVxICRudWxsKSB7DQogICAgICAgIHRocm93ICJVbmFibGUgdG8gZmluZCBsb2NhbCB1c2VyIGFjY291bnQgJyRVc2VyTmFtZSciDQogICAgfQ0KICAgIA0KICAgIGlmICgkRm9yY2UpIHsNCiAgICAgICAgV3JpdGUtTG9nICJDaGFuZ2luZyBwYXNzd29yZCBmb3IgdXNlciAnJFVzZXJOYW1lJyB0byAnKioqKionIiAjIDopDQogICAgICAgIChbQURTSV0gIldpbk5UOi8vLi8kVXNlck5hbWUiKS5TZXRQYXNzd29yZCgkUGFzc3dvcmQpDQogICAgfQ0KICAgIGVsc2Ugew0KICAgICAgICBXcml0ZS1Mb2dXYXJuaW5nICJZb3UgYXJlIHRyeWluZyB0byBjaGFuZ2UgcGFzc3dvcmQgZm9yIHVzZXIgJyRVc2VyTmFtZScuIFRvIGRvIHRoaXMgcGxlYXNlIHJ1biB0aGUgY29tbWFuZCBhZ2FpbiB3aXRoIC1Gb3JjZSBwYXJhbWV0ZXIuIg0KICAgICAgICAkVXNlckFjY291bnQNCiAgICB9DQp9DQoNCg0KDQpGdW5jdGlvbiBJbnN0YWxsLVJvbGVQcmltYXJ5RG9tYWluQ29udHJvbGxlcg0Kew0KPCMNCi5TWU5PUFNJUw0KQ29uZmlndXJlIG5vZGUncyBuZXR3b3JrIGFkYXB0ZXJzLg0KQ3JlYXRlIGZpcnN0IGRvbWFpbiBjb250cm9sbGVyIGluIHRoZSBmb3Jlc3QuDQoNCi5FWEFNUExFDQpQUz4gSW5zdGFsbC1Sb2xlUHJpbWFyeURvbWFpbkNvbnRyb2xsZXIgLURvbWFpbk5hbWUgYWNtZS5sb2NhbCAtU2FmZU1vZGVQYXNzd29yZCAiUEBzc3cwcmQiDQoNCkluc3RhbGwgRE5TIGFuZCBBRERTLCBjcmVhdGUgZm9yZXN0IGFuZCBkb21haW4gJ2FjbWUubG9jYWwnLg0KU2V0IERDIHJlY292ZXJ5IG1vZGUgcGFzc3dvcmQgdG8gJ1BAc3N3MHJkJy4NCiM+DQoJDQoJcGFyYW0NCgkoDQoJCVtTdHJpbmddDQoJCSMgTmV3IGRvbWFpbiBuYW1lLg0KCQkkRG9tYWluTmFtZSwNCgkJDQoJCVtTdHJpbmddDQoJCSMgRG9tYWluIGNvbnRyb2xsZXIgcmVjb3ZlcnkgbW9kZSBwYXNzd29yZC4NCgkJJFNhZmVNb2RlUGFzc3dvcmQNCgkpDQoNCgl0cmFwIHsgU3RvcC1FeGVjdXRpb24gJF8gfQ0KDQogICAgICAgICMgQWRkIHJlcXVpcmVkIHdpbmRvd3MgZmVhdHVyZXMNCglBZGQtV2luZG93c0ZlYXR1cmVXcmFwcGVyIGANCgkJLU5hbWUgIkROUyIsIkFELURvbWFpbi1TZXJ2aWNlcyIsIlJTQVQtREZTLU1nbXQtQ29uIiBgDQoJCS1JbmNsdWRlTWFuYWdlbWVudFRvb2xzIGANCiAgICAgICAgLU5vdGlmeVJlc3RhcnQNCg0KDQoJV3JpdGUtTG9nICJDcmVhdGluZyBmaXJzdCBkb21haW4gY29udHJvbGxlciAuLi4iDQoJCQ0KCSRTTUFQID0gQ29udmVydFRvLVNlY3VyZVN0cmluZyAtU3RyaW5nICRTYWZlTW9kZVBhc3N3b3JkIC1Bc1BsYWluVGV4dCAtRm9yY2UNCgkJDQoJSW5zdGFsbC1BRERTRm9yZXN0IGANCgkJLURvbWFpbk5hbWUgJERvbWFpbk5hbWUgYA0KCQktU2FmZU1vZGVBZG1pbmlzdHJhdG9yUGFzc3dvcmQgJFNNQVAgYA0KCQktRG9tYWluTW9kZSBEZWZhdWx0IGANCgkJLUZvcmVzdE1vZGUgRGVmYXVsdCBgDQoJCS1Ob1JlYm9vdE9uQ29tcGxldGlvbiBgDQoJCS1Gb3JjZSBgDQoJCS1FcnJvckFjdGlvbiBTdG9wIHwgT3V0LU51bGwNCg0KCVdyaXRlLUhvc3QgIldhaXRpbmcgZm9yIHJlYm9vdCAuLi4iCQkNCiMJU3RvcC1FeGVjdXRpb24gLUV4aXRDb2RlIDMwMTAgLUV4aXRTdHJpbmcgIkNvbXB1dGVyIG11c3QgYmUgcmVzdGFydGVkIHRvIGZpbmlzaCBkb21haW4gY29udHJvbGxlciBwcm9tb3Rpb24uIg0KIwlXcml0ZS1Mb2cgIlJlc3RhcmluZyBjb21wdXRlciAuLi4iDQojCVJlc3RhcnQtQ29tcHV0ZXIgLUZvcmNlDQp9DQo=" + "ImportCoreFunctions.ps1", + "Set-LocalUserPasswordPassword.ps1" ], "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, { "Name": "Set-LocalUserPassword", "Arguments": { diff --git a/data/templates/agent/SqlServerCluster/ConfigureEnvironmentForAOAG.template b/data/templates/agent/SqlServerCluster/ConfigureEnvironmentForAOAG.template index d1c7e32..df12ddf 100644 --- a/data/templates/agent/SqlServerCluster/ConfigureEnvironmentForAOAG.template +++ b/data/templates/agent/SqlServerCluster/ConfigureEnvironmentForAOAG.template @@ -1,4 +1,8 @@ { + "Scripts": [ + "ImportCoreFunctions.ps1", + "SQLServerForAOAG.ps1" + ], "Commands": [ { "Name": "Enable-TrustedHosts", @@ -10,10 +14,5 @@ "PrimaryNode": "$primaryNode" } } - ], - "Scripts": [ - "SW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zIC1Gb3JjZQoKCmZ1bmN0aW9uIFNob3ctSW52b2NhdGlvbkluZm8gewogICAgcGFyYW0gKAogICAgICAgICRJbnZvY2F0aW9uLAogICAgICAgIFtTd2l0Y2hdICRFbmQKICAgICkKCiAgICBpZiAoJEVuZCkgewogICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L2Z1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICB9CiAgICBlbHNlIHsKICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPGZ1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjxwYXJhbT4iCiAgICAgICAgZm9yZWFjaCAoJFBhcmFtZXRlciBpbiAkSW52b2NhdGlvbi5NeUNvbW1hbmQuUGFyYW1ldGVycykgewogICAgICAgICAgICBmb3JlYWNoICgkS2V5IGluICRQYXJhbWV0ZXIuS2V5cykgewogICAgICAgICAgICAgICAgJFR5cGUgPSAkUGFyYW1ldGVyWyRLZXldLlBhcmFtZXRlclR5cGUuRnVsbE5hbWUKICAgICAgICAgICAgICAgIGZvcmVhY2ggKCRWYWx1ZSBpbiAkSW52b2NhdGlvbi5Cb3VuZFBhcmFtZXRlcnNbJEtleV0pIHsKICAgICAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiWyRUeXBlXSAkS2V5ID0gJyRWYWx1ZSciCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjwvcGFyYW0+IgogICAgfQp9CgoKJFRyYXBIYW5kbGVyID0gewogICAgV3JpdGUtTG9nRXJyb3IgQCgiPGV4Y2VwdGlvbj4iLCAkXykgLUVudGlyZU9iamVjdAogICAgV3JpdGUtTG9nRXJyb3IgIjwvZXhjZXB0aW9uPiIKICAgIGJyZWFrCn0KCgp0cmFwIHsKICAgICYkVHJhcEhhbmRsZXIKfQoKJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICdTdG9wJwoKCjwjCiMgVXNhZ2UgZXhhbXBsZSBmb3IgU2hvdy1JbnZvY2F0aW9uSW5mbwoKZnVuY3Rpb24gTXlGdW5jdGlvbiB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJFZhbHVlMSwKICAgICAgICBbU3RyaW5nXSAkVmFsdWUyLAogICAgICAgIFtJbnRdICRJbnQxCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KICAgICAgICAjIE1haW4gY29kZSBoZXJlCiAgICB9Cn0KIz4K", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlclBvd2VyU2hlbGxNb2R1bGUgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJwogICAgKQogICAgYmVnaW4gewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbgogICAgfQogICAgZW5kIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24gLUVuZAogICAgfQogICAgcHJvY2VzcyB7CiAgICAgICAgdHJhcCB7CiAgICAgICAgICAgICYkVHJhcEhhbmRsZXIKICAgICAgICB9CgogICAgICAgIGlmICgoR2V0LU1vZHVsZSBTUUxQUyAtTGlzdEF2YWlsYWJsZSkgLW5lICRudWxsKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiTW9kdWxlIFNRTFNQIGFscmVhZHkgaW5zdGFsbGVkLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcVG9vbHMnKQogICAgICAgIH0KICAgICAgICAKICAgICAgICAkRmlsZUxpc3QgPSBAKAogICAgICAgICAgICAnU1FMU3lzQ2xyVHlwZXMubXNpJywKICAgICAgICAgICAgJ1NoYXJlZE1hbmFnZW1lbnRPYmplY3RzLm1zaScsCiAgICAgICAgICAgICdQb3dlclNoZWxsVG9vbHMubXNpJwogICAgICAgICkKCiAgICAgICAgZm9yZWFjaCAoJE1zaUZpbGUgaW4gJEZpbGVMaXN0KSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVHJ5aW5nIHRvIGluc3RhbGwgJyRNc2lGaWxlJyAuLi4iCiAgICAgICAgICAgICRNc2lQYXRoID0gSm9pbi1QYXRoICRTZXR1cFJvb3QgJE1zaUZpbGUKICAgICAgICAgICAgaWYgKFtJTy5GaWxlXTo6RXhpc3RzKCRNc2lQYXRoKSkgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJTdGFydGluZyBtc2lleGUgLi4uIgogICAgICAgICAgICAgICAgJFJlc3VsdCA9IEV4ZWMgLUZpbGVQYXRoICJtc2lleGVjLmV4ZSIgLUFyZ3VtZW50TGlzdCBAKCcvaScsICJgIiRNc2lQYXRoYCIiLCAnL3F1aWV0JykgLVBhc3NUaHJ1CiAgICAgICAgICAgICAgICBpZiAoJFJlc3VsdC5FeGl0Q29kZSAtbmUgMCkgewogICAgICAgICAgICAgICAgICAgIHRocm93ICgiSW5zdGFsbGF0aW9uIG9mIE1TSSBwYWNrYWdlICckTXNpUGF0aCcgZmFpbGVkIHdpdGggZXJyb3IgY29kZSAnJCgkUmVzdWx0LkV4aXRDb2RlKSciKQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJGaWxlICckTXNpUGF0aCcgbm90IGZvdW5kLiIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQoKCgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgUGF0aCB0byBmb2xkZXIgd2hlcmUgbXNpIGZpbGVzIGZvciBhZGRpdGlvbmFsIFNRTCBmZWF0dXJlcyBhcmUgbG9jYXRlZAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJywKCiAgICAgICAgIyBQYXRoIHRvIGZvbGRlciB3aGVyZSBtc2kgZmlsZXMgZm9yIGFkZGl0aW9uYWwgU1FMUFMgbW9kdWxlIGFyZSBsb2NhdGVkCiAgICAgICAgW1N0cmluZ10gJFNxbHBzU2V0dXBSb290ID0gJycsCgogICAgICAgIFtTdHJpbmddICRNdXJhbm9GaWxlU2hhcmUgPSAnJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIERvbWFpbiBuYW1lCiAgICAgICAgW1N0cmluZ10gJFNRTFNlcnZpY2VVc2VyRG9tYWluID0gJ2ZjLWFjbWUubG9jYWwnLAoKICAgICAgICAjIChSRVFVSVJFRCkgVXNlciBuYW1lIGZvciB0aGUgYWNjb3VudCB3aGljaCB3aWxsIGJlIHVzZWQgYnkgU1FMIHNlcnZpY2UKICAgICAgICBbU3RyaW5nXSAkU1FMU2VydmljZVVzZXJOYW1lID0gJ0FkbWluaXN0cmF0b3InLAoKICAgICAgICAjIChSRVFVSVJFRCkgUGFzc3dvcmQgZm9yIHRoYXQgdXNlcgogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlclBhc3N3b3JkID0gJ1BAc3N3MHJkJywKCiAgICAgICAgW1N3aXRjaF0gJFVwZGF0ZUVuYWJsZWQKICAgICkKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcMjAxMicpCiAgICAgICAgfQoKICAgICAgICAkRXh0cmFPcHRpb25zID0gQHt9CgogICAgICAgIGlmICgkVXBkYXRlRW5hYmxlZCkgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJHRydWV9CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJGZhbHNlfQogICAgICAgIH0KCiAgICAgICAgTmV3LVNRTFNlcnZlckZvckFPQUcgYAogICAgICAgICAgICAtU2V0dXBSb290ICRTZXR1cFJvb3QgYAogICAgICAgICAgICAtU1FMU3ZjVXNyRG9tYWluICRTUUxTZXJ2aWNlVXNlckRvbWFpbiBgCiAgICAgICAgICAgIC1TUUxTdmNVc3JOYW1lICRTUUxTZXJ2aWNlVXNlck5hbWUgYAogICAgICAgICAgICAtU1FMU3ZjVXNyUGFzc3dvcmQgJFNRTFNlcnZpY2VVc2VyUGFzc3dvcmQgYAogICAgICAgICAgICAtRXh0cmFPcHRpb25zICRFeHRyYU9wdGlvbnMKICAgIH0KfQoKCgpmdW5jdGlvbiBJbml0aWFsaXplLUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXAgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnRQYXNzd29yZCwKICAgICAgICBbU3RyaW5nXSAkU3FsU2VydmljZUFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICRQcmltYXJ5Tm9kZSwKICAgICAgICBbU3RyaW5nXSAkU2hhcmVOYW1lID0gJ1NoYXJlZFdvcmtEaXInCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgJFNoYXJlTmV0d29ya1BhdGggPSAnXFwnICsgJFByaW1hcnlOb2RlICsgJ1wnICsgJFNoYXJlTmFtZQoKICAgICAgICAkRG9tYWluQWRtaW5BY2NvdW50Q3JlZHMgPSBOZXctQ3JlZGVudGlhbCBgCiAgICAgICAgICAgIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJERvbWFpbkFkbWluQWNjb3VudE5hbWUiIGAKICAgICAgICAgICAgLVBhc3N3b3JkICIkRG9tYWluQWRtaW5BY2NvdW50UGFzc3dvcmQiCgogICAgICAgICRGdW5jdGlvbnNGaWxlID0gRXhwb3J0LUZ1bmN0aW9uICdHZXQtTmV4dEZyZWVQb3J0JywgJ0luaXRpYWxpemUtQWx3YXlzT24nCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICBgJF8KICAgIGV4aXQgMQp9CgpJbXBvcnQtTW9kdWxlIENvcmVGdW5jdGlvbnMKCldyaXRlLUxvZyAiSW1wb3J0aW5nIGZ1bmN0aW9ucyBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ0luaXRpYWxpemUtQWx3YXlzT24nIC4uLiIKYCRYbWxGaWxlID0gW0lPLlBhdGhdOjpDb21iaW5lKCIkU2hhcmVOZXR3b3JrUGF0aCIsICJgJChgJEVudjpDb21wdXRlck5hbWUpLnhtbCIpCldyaXRlLUxvZyAiT3V0cHV0IFhNTCBmaWxlIGlzICdgJFhtbEZpbGUnIgpJbml0aWFsaXplLUFsd2F5c09uIHwgRXhwb3J0LUNsaVhtbCAtUGF0aCBgJFhtbEZpbGUKIkAgLUNyZWRlbnRpYWwgJERvbWFpbkFkbWluQWNjb3VudENyZWRzIC1Ob0Jhc2U2NAogICAgfQp9CgoKZnVuY3Rpb24gTmV3LVNoYXJlZEZvbGRlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKQogICAgICAgIFtTdHJpbmddICRTaGFyZVBhdGggPSBbSU8uUGF0aF06OkNvbWJpbmUoJEVudjpTeXN0ZW1Ecml2ZSArICdcJywgJ1NoYXJlZFdvcmtEaXInKSwKCiAgICAgICAgIyAoT1BUSU9OQUwpCiAgICAgICAgW1N0cmluZ10gJFNoYXJlTmFtZSA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlID0gJyAnCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBzY3JpcHQgcnVucyBvbiBwcmltYXJ5IG5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZyBzY3JpcHQuIgogICAgICAgICAgICByZXR1cm4KICAgICAgICB9CgogICAgICAgIGlmICgkU2hhcmVOYW1lIC1lcSAnJykgewogICAgICAgICAgICAkU2hhcmVOYW1lID0gW0lPLlBhdGhdOjpHZXRGaWxlTmFtZVdpdGhvdXRFeHRlbnNpb24oJFNoYXJlUGF0aCkKICAgICAgICB9CgogICAgICAgIFdyaXRlLUxvZ0RlYnVnICJTaGFyZVBhdGggPSAnJFNoYXJlUGF0aCciCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIlNoYXJlTmFtZSA9ICckU2hhcmVOYW1lJyIKCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgc2hhcmUgJyRTaGFyZU5hbWUnIgogICAgICAgICAgICAkbnVsbCA9IEdldC1TbWJTaGFyZSAtTmFtZSAkU2hhcmVOYW1lIC1FcnJvckFjdGlvbiAnU3RvcCcKICAgICAgICAgICAgJG51bGwgPSBSZW1vdmUtU21iU2hhcmUgLU5hbWUgJFNoYXJlTmFtZSAtRm9yY2UKICAgICAgICAgICAgd3JpdGUtTG9nICJTaGFyZSAnJFNoYXJlTmFtZScgcmVtb3ZlZC4iCiAgICAgICAgfQogICAgICAgIGNhdGNoIHsKICAgICAgICAgICAgV3JpdGUtTG9nV2FybmluZyAiU2hhcmUgJyRTaGFyZU5hbWUnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgZm9sZGVyICckU2hhcmVQYXRoIgogICAgICAgICAgICAkbnVsbCA9IEdldC1JdGVtIC1QYXRoICRTaGFyZVBhdGggLUVycm9yQWN0aW9uICdTdG9wJwogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICRTaGFyZVBhdGggLVJlY3Vyc2UgLUZvcmNlCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRm9sZGVyICckU2hhcmVQYXRoJyByZW1vdmVkLiIKICAgICAgICB9CiAgICAgICAgY2F0Y2ggewogICAgICAgICAgICBXcml0ZS1Mb2dXYXJuaW5nICJGb2xkZXIgJyRTaGFyZVBhdGgnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgJG51bGwgPSBOZXctSXRlbSAtUGF0aCAkU2hhcmVQYXRoIC1JdGVtVHlwZSBDb250YWluZXIgLUZvcmNlCiAgICAgICAgICAgICAgICAKICAgICAgICAkbnVsbCA9IE5ldy1TbWJTaGFyZSAtUGF0aCAkU2hhcmVQYXRoIGAKICAgICAgICAgICAgLU5hbWUgJFNoYXJlTmFtZSBgCiAgICAgICAgICAgIC1GdWxsQWNjZXNzICJFdmVyeW9uZSIgYAogICAgICAgICAgICAtRGVzY3JpcHRpb24gIlNoYXJlZCBmb2xkZXIgZm9yIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cCBzZXR1cC4iCgogICAgICAgIHJldHVybiAnXFwnICsgJEVudjpDb21wdXRlck5hbWUgKyAnXCcgKyAkU2hhcmVOYW1lCiAgICB9Cn0KCgoKZnVuY3Rpb24gTmV3LURhdGFiYXNlRm9yQU9BRyB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJERhdGFiYXNlTmFtZSwKICAgICAgICBbU3RyaW5nXSAkRG9tYWluTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlck5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJQYXNzd29yZAogICAgKQoKICAgICRDcmVkcyA9IE5ldy1DcmVkZW50aWFsIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJFVzZXJOYW1lIiAtUGFzc3dvcmQgIiRVc2VyUGFzc3dvcmQiCgogICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gJ0ludm9rZS1TUUxUZXh0JywgJ0NvbnZlcnRUby1TUUxOYW1lJywgJ0NvbnZlcnRUby1TUUxTdHJpbmcnLCAnTmV3LVNRTERhdGFiYXNlJwoKICAgIFN0YXJ0LVBvd2VyU2hlbGxQcm9jZXNzIEAiCnRyYXAgewogICAgYCRfCiAgICBleGl0IDEKfQoKSW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zCgpXcml0ZS1Mb2cgIkltcG9ydGluZyBmdW5jdGlvbnMgZnJvbSBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1TUUxEYXRhYmFzZScgLi4uIgpOZXctU1FMRGF0YWJhc2UgJERhdGFiYXNlTmFtZQoiQCAtQ3JlZGVudGlhbCAkQ3JlZHMgLU5vQmFzZTY0Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHUHJpbWFyeVJlcGxpY2EgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKSBOYW1lIG9mIHRoZSBuZXcgQXZhaWxhYmlsaXR5IEdyb3VwLiBJZiBub3Qgc3BlY2lmaWVkIHRoZW4gZGVmYXVsdCBuYW1lIHdpbGwgYmUgdXNlZC4KICAgICAgICBbU3RyaW5nXSAkR3JvdXBOYW1lID0gJ011cmFub0FHJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICROb2RlTGlzdCwKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGUgbmFtZSB0aGF0IHdpbGwgYmUgcHJpbWFyeSBmb3Igc2VsZWN0ZWQgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nXSAkUHJpbWFyeU5vZGUsCgogICAgICAgICMgKFJFUVVJUkVEKSBEYXRhYmFzZSBsaXN0IHRoYXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICREYXRhYmFzZUxpc3QsCgogICAgICAgICMgKFJFUVVJUkVEKSBMaXN0ZW5lciBuYW1lIHRoYXQgd2lsbCBiZSB1c2VkIGJ5IGNsaWVudHMgdG8gY29ubmVjdCB0byBkYXRhYmFzZXMgaW4gdGhhdCBBRwogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyTmFtZSA9ICdNdXJhbm9BR19MaXN0ZW5lcicsCgogICAgICAgICMgKFJFUVVJUkVEKSBJUCBhZGRyZXNzIG9mIHRoZSBsaXN0ZW5lcgogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVySVAsCgogICAgICAgIFtTdHJpbmddICRMaXN0ZW5lcklQTWFzayA9ICcyNTUuMjU1LjI1NS4wJywKCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyUG9ydCA9ICc1MDIzJywKCiAgICAgICAgIyBTeW5jIE1vZGUgTm9kZSBMaXN0CiAgICAgICAgW1N0cmluZ1tdXSAkU3luY01vZGVOb2RlTGlzdCwKCiAgICAgICAgW1N0cmluZ10gJFNoYXJlZFdvcmtEaXIgPSAnU2hhcmVkV29ya0RpcicsCgogICAgICAgIFtTdHJpbmddICRDbGlYbWxGaWxlID0gJycsCgogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlclBhc3N3b3JkCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJQcmltYXJ5IG5vZGU6ICckKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkpJyIKICAgICAgICBXcml0ZS1Mb2cgIkN1cnJlbnQgbm9kZTogJyQoKCRFbnY6Q29tcHV0ZXJOYW1lKS5Ub0xvd2VyKCkpJyIKCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICQoJEVudjpDb21wdXRlck5hbWUpLlRvTG93ZXIoKSkgewogICAgICAgICAgICBXcml0ZS1Mb2cgIlRoaXMgZnVuY3Rpb24gd29ya3Mgb24gUHJpbWFyeU5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZy4iCiAgICAgICAgICAgIHJldHVybgogICAgICAgIH0KCiAgICAgICAgaWYgKCRDbGlYbWxGaWxlIC1lcSAnJykgewogICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ID0gQCgpCiAgICAgICAgICAgIGZvcmVhY2ggKCROb2RlIGluICROb2RlTGlzdCkgewogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAkTm9kZUVuZHBvaW50UG9ydCA9IEltcG9ydC1DbGlYbWwgLVBhdGggIlxcJFByaW1hcnlOb2RlXFNoYXJlZFdvcmtEaXJcJE5vZGUueG1sIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2F0Y2ggewogICAgICAgICAgICAgICAgICAgIFdyaXRlLUxvZyAiVXNpbmcgZGVmYXVsdCBlbmRwb2ludCBwb3J0IDUwMjIiCiAgICAgICAgICAgICAgICAgICAgJE5vZGVFbmRwb2ludFBvcnQgPSA1MDIyCiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uID0gQHsKICAgICAgICAgICAgICAgICAgICAiU0VSVkVSX0lOU1RBTkNFIiA9ICIkTm9kZSI7CiAgICAgICAgICAgICAgICAgICAgIkVORFBPSU5UX1VSTCIgPSAiVENQOi8vJHtOb2RlfToke05vZGVFbmRwb2ludFBvcnR9IjsKICAgICAgICAgICAgICAgICAgICAiQVZBSUxBQklMSVRZX01PREUiID0gIkFTWU5DSFJPTk9VU19DT01NSVQiOwogICAgICAgICAgICAgICAgICAgICJGQUlMT1ZFUl9NT0RFIj0iTUFOVUFMIjsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZiAoJFN5bmNNb2RlTm9kZUxpc3QgLWNvbnRhaW5zICROb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBpbiBTeW5jTW9kZU5vZGVMaXN0IgogICAgICAgICAgICAgICAgICAgICRSZXBsaWNhRGVmaW5pdGlvblsnQVZBSUxBQklMSVRZX01PREUnXSA9ICJTWU5DSFJPTk9VU19DT01NSVQiCiAgICAgICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uWydGQUlMT1ZFUl9NT0RFJ10gPSAiQVVUT01BVElDIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBOT1QgaW4gU3luY01vZGVOb2RlTGlzdCIKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ICs9IEAoJFJlcGxpY2FEZWZpbml0aW9uKQogICAgICAgICAgICB9CgogICAgICAgICAgICAkUHJlZmVyZW5jZXMgPSBAe30KCiAgICAgICAgICAgICRMaXN0ZW5lckRlZmluaXRpb24gPSBAewogICAgICAgICAgICAgICAgIk5BTUUiPSRMaXN0ZW5lck5hbWU7CiAgICAgICAgICAgICAgICAiUE9SVCIgPSAiJExpc3RlbmVyUG9ydCI7CiAgICAgICAgICAgICAgICAiU1RBVElDIiA9ICIkTGlzdGVuZXJJUC8kTGlzdGVuZXJJUE1hc2siCiAgICAgICAgICAgIH0KCiAgICAgICAgICAgICRQYXJhbWV0ZXJzID0gQHsKICAgICAgICAgICAgICAgICdXb3JrRGlyJyA9ICJcXCRQcmltYXJ5Tm9kZVwkU2hhcmVkV29ya0RpciI7CiAgICAgICAgICAgICAgICAnTmFtZScgPSAkR3JvdXBOYW1lOwogICAgICAgICAgICAgICAgJ0RhdGFiYXNlTmFtZXMnID0gJERhdGFiYXNlTGlzdDsKICAgICAgICAgICAgICAgICdSZXBsaWNhRGVmcycgPSAkUmVwbGljYURlZmluaXRpb25MaXN0OwogICAgICAgICAgICAgICAgJ1ByZWZlcmVuY2VzJyA9ICRQcmVmZXJlbmNlczsKICAgICAgICAgICAgICAgICdMaXN0ZW5lckRlZicgPSAkTGlzdGVuZXJEZWZpbml0aW9uOwogICAgICAgICAgICB9CgogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICJcXCRQcmltYXJ5Tm9kZVxTaGFyZWRXb3JrRGlyXCoiIC1Gb3JjZQoKICAgICAgICAgICAgJENsaVhtbEZpbGUgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiQ2xpWG1sIGZpbGU6ICckQ2xpWG1sRmlsZSciCgogICAgICAgICAgICAkbnVsbCA9IEV4cG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUgLUlucHV0T2JqZWN0ICRQYXJhbWV0ZXJzIC1EZXB0aCAxMAoKICAgICAgICAgICAgJG51bGwgPSBJbml0aWFsaXplLUFPQUdQcmltYXJ5UmVwbGljYSBgCiAgICAgICAgICAgICAgICAtQ2xpWG1sRmlsZSAkQ2xpWG1sRmlsZSBgCiAgICAgICAgICAgICAgICAtRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgCiAgICAgICAgICAgICAgICAtVXNlck5hbWUgJFVzZXJOYW1lIGAKICAgICAgICAgICAgICAgIC1Vc2VyUGFzc3dvcmQgJFVzZXJQYXNzd29yZCBgCiAgICAgICAgICAgICAgICAtUHJpbWFyeU5vZGUgJFByaW1hcnlOb2RlCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiSW5uZXIgJ0luaXRpYWxpemUtQU9BR1ByaW1hcnlSZXBsaWNhJyBjYWxsIGNvbXBsZXRlZC4iCiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAgICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gLUFsbAoKICAgICAgICAgICAgJG51bGwgPSBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyBAIgp0cmFwIHsKICAgIGAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJJbXBvcnRpbmcgQ2xpWG1sIHBhcmFtZXRlcnMgZmlsZSAuLi4iCmAkUGFyYW1ldGVycyA9IEltcG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwIGBgCiAgICAtV29ya0RpciBgJFBhcmFtZXRlcnNbJ1dvcmtEaXInXSBgYAogICAgLU5hbWUgYCRQYXJhbWV0ZXJzWydOYW1lJ10gYGAKICAgIC1EYXRhYmFzZU5hbWVzIGAkUGFyYW1ldGVyc1snRGF0YWJhc2VOYW1lcyddIGBgCiAgICAtUmVwbGljYURlZnMgYCRQYXJhbWV0ZXJzWydSZXBsaWNhRGVmcyddIGBgCiAgICAtUHJlZmVyZW5jZXMgYCRQYXJhbWV0ZXJzWydQcmVmZXJlbmNlcyddIGBgCiAgICAtTGlzdGVuZXJEZWYgYCRQYXJhbWV0ZXJzWydMaXN0ZW5lckRlZiddCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgICAgICB9CiAgICB9Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHU2Vjb25kYXJ5UmVwbGljYSB7CiAgICBwYXJhbSAoCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmdbXV0gJE5vZGVMaXN0LAoKICAgICAgICAjIChSRVFVSVJFRCkgTm9kZSBuYW1lIHRoYXQgd2lsbCBiZSBwcmltYXJ5IGZvciBzZWxlY3RlZCBBdmFpbGFiaWxpdHkgR3JvdXAKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlLAoKICAgICAgICBbU3RyaW5nXSAkU2hhcmVkV29ya0RpciA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJERvbWFpbk5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJOYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyUGFzc3dvcmQKICAgICkgCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLWVxICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBmdW5jdGlvbiB3b3JrcyBvbiBhbnkgU2Vjb25kYXJ5Tm9kZSBvbmx5LiIKICAgICAgICAgICAgV3JpdGUtTG9nICJFeGl0aW5nLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAkRnVuY3Rpb25zRmlsZSA9IEV4cG9ydC1GdW5jdGlvbiAtQWxsCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJTdGFydGluZyAnTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXBSZXBsaWNhJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwUmVwbGljYSAtV29ya0RpciAiXFwkUHJpbWFyeU5vZGVcJFNoYXJlZFdvcmtEaXIiCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgIH0KfQoKCgpmdW5jdGlvbiBEaXNhYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb2ZmCiAgICB9Cn0KCgoKZnVuY3Rpb24gRW5hYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb24KICAgIH0KfQoKCgpmdW5jdGlvbiBFbmFibGUtVHJ1c3RlZEhvc3RzIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBTZXQtSXRlbSBXU01hbjpcbG9jYWxob3N0XENsaWVudFxUcnVzdGVkSG9zdHMgLVZhbHVlICcqJyAtRm9yY2UKICAgIH0KfQo=", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgoKCmZ1bmN0aW9uIE5ldy1TcWxTZXJ2ZXJTeXN0ZW1BY2NvdW50IHsKICAgIHBhcmFtICgKICAgICAgICAjIChSRVFVSVJFRCkgRG9tYWluIE5hbWUKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJERvbWFpbk5hbWUsCgogICAgICAgICMgKFJFUVVJUkVEKSBVc2VyIG5hbWUgd2hvIGhhcyBwZXJtaXNzaW9ucyB0byBjcmVhdGUgYW5kIG1vZGlmeSB1c2VyUGFzc3dvcmQKICAgICAgICAjIFVzdWFsbHkgdGhpcyBpcyB0aGUgZG9tYWluIGFkbWluaXN0cmF0b3IgJyRkb21haW5OYW1lXEFkbWluaXN0cmF0b3InIGFjY291bnQKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJFVzZXJOYW1lLAoKICAgICAgICAjIChSRVFVSVJFRCkgUGFzc3dvcmQgZm9yIHRoYXQgdXNlcgogICAgICAgIFtQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nXSAkVXNlclBhc3N3b3JkLAoKICAgICAgICAjIChSRVFVSVJFRCkgVXNlciBuYW1lIGZvciBhIG5ldyBhY2NvdW50IHRoYXQgd2lsbCBiZSB1c2VkIHRvIHJ1biBTUUwgU2VydmVyCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlck5hbWUsCgogICAgICAgICMgKFJFUVVJUkVEKSBQYXNzd29yZCBmb3IgdGhhdCB1c2VyCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlclBhc3N3b3JkLAoKICAgICAgICBbU3RyaW5nXSAkUHJpbWFyeU5vZGUgPSAnICcKICAgICkKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBpZiAoJFByaW1hcnlOb2RlLlRvTG93ZXIoKSAtbmUgKCRFbnY6Q29tcHV0ZXJOYW1lKS5Ub0xvd2VyKCkpIHsKICAgICAgICAgICAgV3JpdGUtTG9nICJUSGlzIGZ1bmN0aW9uIHJ1bnMgb24gQU9BRyBwcmltYXJ5IG5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZy4iCiAgICAgICAgICAgIHJldHVybgogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJJbnN0YWxsaW5nICdSU0FULUFELVBvd2VyU2hlbGwnIC4uLiAiCiAgICAgICAgQWRkLVdpbmRvd3NGZWF0dXJlIFJTQVQtQUQtUG93ZXJTaGVsbAoKICAgICAgICBJbXBvcnQtTW9kdWxlIEFjdGl2ZURpcmVjdG9yeQoKICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICBXcml0ZS1Mb2cgIkFkZGluZyBuZXcgdXNlciAuLi4iCiAgICAgICAgJG51bGwgPSBOZXctQURVc2VyIGAKICAgICAgICAgICAgLU5hbWUgJFNRTFNlcnZpY2VVc2VyTmFtZSBgCiAgICAgICAgICAgIC1BY2NvdW50UGFzc3dvcmQgJChDb252ZXJ0VG8tU2VjdXJlU3RyaW5nIC1TdHJpbmcgJFNRTFNlcnZpY2VVc2VyUGFzc3dvcmQgLUFzUGxhaW5UZXh0IC1Gb3JjZSkgYAogICAgICAgICAgICAtQ3JlZGVudGlhbCAkQ3JlZHMgYAogICAgICAgICAgICAtRXJyb3JBY3Rpb24gJ1N0b3AnCiAgICB9Cn0K" ] } \ No newline at end of file diff --git a/data/templates/agent/SqlServerCluster/FailoverCluster.template b/data/templates/agent/SqlServerCluster/FailoverCluster.template index 1c84bcf..b30c9ac 100644 --- a/data/templates/agent/SqlServerCluster/FailoverCluster.template +++ b/data/templates/agent/SqlServerCluster/FailoverCluster.template @@ -1,4 +1,9 @@ { + "Scripts": [ + "ImportCoreFunctions.ps1", + "Start-PowerShellProcess.ps1", + "Failover-Cluster.ps1" + ], "Commands": [ { "Name": "New-FailoverCluster", @@ -22,11 +27,5 @@ } } ], - "RebootOnCompletion": 0, - "Scripts": [ - "SW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zIC1Gb3JjZQoKCmZ1bmN0aW9uIFNob3ctSW52b2NhdGlvbkluZm8gewogICAgcGFyYW0gKAogICAgICAgICRJbnZvY2F0aW9uLAogICAgICAgIFtTd2l0Y2hdICRFbmQKICAgICkKCiAgICBpZiAoJEVuZCkgewogICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L2Z1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICB9CiAgICBlbHNlIHsKICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPGZ1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjxwYXJhbT4iCiAgICAgICAgZm9yZWFjaCAoJFBhcmFtZXRlciBpbiAkSW52b2NhdGlvbi5NeUNvbW1hbmQuUGFyYW1ldGVycykgewogICAgICAgICAgICBmb3JlYWNoICgkS2V5IGluICRQYXJhbWV0ZXIuS2V5cykgewogICAgICAgICAgICAgICAgJFR5cGUgPSAkUGFyYW1ldGVyWyRLZXldLlBhcmFtZXRlclR5cGUuRnVsbE5hbWUKICAgICAgICAgICAgICAgIGZvcmVhY2ggKCRWYWx1ZSBpbiAkSW52b2NhdGlvbi5Cb3VuZFBhcmFtZXRlcnNbJEtleV0pIHsKICAgICAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiWyRUeXBlXSAkS2V5ID0gJyRWYWx1ZSciCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjwvcGFyYW0+IgogICAgfQp9CgoKJFRyYXBIYW5kbGVyID0gewogICAgV3JpdGUtTG9nRXJyb3IgQCgiPGV4Y2VwdGlvbj4iLCAkXykgLUVudGlyZU9iamVjdAogICAgV3JpdGUtTG9nRXJyb3IgIjwvZXhjZXB0aW9uPiIKICAgIGJyZWFrCn0KCgp0cmFwIHsKICAgICYkVHJhcEhhbmRsZXIKfQoKJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICdTdG9wJwoKCjwjCiMgVXNhZ2UgZXhhbXBsZSBmb3IgU2hvdy1JbnZvY2F0aW9uSW5mbwoKZnVuY3Rpb24gTXlGdW5jdGlvbiB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJFZhbHVlMSwKICAgICAgICBbU3RyaW5nXSAkVmFsdWUyLAogICAgICAgIFtJbnRdICRJbnQxCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KICAgICAgICAjIE1haW4gY29kZSBoZXJlCiAgICB9Cn0KIz4K", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgoKCmZ1bmN0aW9uIE5ldy1TcWxTZXJ2ZXJTeXN0ZW1BY2NvdW50IHsKICAgIHBhcmFtICgKICAgICAgICAjIChSRVFVSVJFRCkgRG9tYWluIE5hbWUKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJERvbWFpbk5hbWUsCgogICAgICAgICMgKFJFUVVJUkVEKSBVc2VyIG5hbWUgd2hvIGhhcyBwZXJtaXNzaW9ucyB0byBjcmVhdGUgYW5kIG1vZGlmeSB1c2VyUGFzc3dvcmQKICAgICAgICAjIFVzdWFsbHkgdGhpcyBpcyB0aGUgZG9tYWluIGFkbWluaXN0cmF0b3IgJyRkb21haW5OYW1lXEFkbWluaXN0cmF0b3InIGFjY291bnQKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJFVzZXJOYW1lLAoKICAgICAgICAjIChSRVFVSVJFRCkgUGFzc3dvcmQgZm9yIHRoYXQgdXNlcgogICAgICAgIFtQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nXSAkVXNlclBhc3N3b3JkLAoKICAgICAgICAjIChSRVFVSVJFRCkgVXNlciBuYW1lIGZvciBhIG5ldyBhY2NvdW50IHRoYXQgd2lsbCBiZSB1c2VkIHRvIHJ1biBTUUwgU2VydmVyCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlck5hbWUsCgogICAgICAgICMgKFJFUVVJUkVEKSBQYXNzd29yZCBmb3IgdGhhdCB1c2VyCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlclBhc3N3b3JkLAoKICAgICAgICBbU3RyaW5nXSAkUHJpbWFyeU5vZGUgPSAnICcKICAgICkKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBpZiAoJFByaW1hcnlOb2RlLlRvTG93ZXIoKSAtbmUgKCRFbnY6Q29tcHV0ZXJOYW1lKS5Ub0xvd2VyKCkpIHsKICAgICAgICAgICAgV3JpdGUtTG9nICJUSGlzIGZ1bmN0aW9uIHJ1bnMgb24gQU9BRyBwcmltYXJ5IG5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZy4iCiAgICAgICAgICAgIHJldHVybgogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJJbnN0YWxsaW5nICdSU0FULUFELVBvd2VyU2hlbGwnIC4uLiAiCiAgICAgICAgQWRkLVdpbmRvd3NGZWF0dXJlIFJTQVQtQUQtUG93ZXJTaGVsbAoKICAgICAgICBJbXBvcnQtTW9kdWxlIEFjdGl2ZURpcmVjdG9yeQoKICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICBXcml0ZS1Mb2cgIkFkZGluZyBuZXcgdXNlciAuLi4iCiAgICAgICAgJG51bGwgPSBOZXctQURVc2VyIGAKICAgICAgICAgICAgLU5hbWUgJFNRTFNlcnZpY2VVc2VyTmFtZSBgCiAgICAgICAgICAgIC1BY2NvdW50UGFzc3dvcmQgJChDb252ZXJ0VG8tU2VjdXJlU3RyaW5nIC1TdHJpbmcgJFNRTFNlcnZpY2VVc2VyUGFzc3dvcmQgLUFzUGxhaW5UZXh0IC1Gb3JjZSkgYAogICAgICAgICAgICAtQ3JlZGVudGlhbCAkQ3JlZHMgYAogICAgICAgICAgICAtRXJyb3JBY3Rpb24gJ1N0b3AnCiAgICB9Cn0K", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgoKCmZ1bmN0aW9uIFNlbGVjdC1DbGlYbWxCbG9jayB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJFBhdGgsCiAgICAgICAgW1N0cmluZ10gJE91dEZpbGUgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCiAgICApCgogICAgJFRhZ0ZvdW5kID0gJGZhbHNlCiAgICBHZXQtQ29udGVudCAkUGF0aCB8CiAgICAgICAgRm9yRWFjaC1PYmplY3QgewogICAgICAgICAgICBpZiAoJF8gLWVxICcjPCBDTElYTUwnKSB7CiAgICAgICAgICAgICAgICAkVGFnRm91bmQgPSAkdHJ1ZQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICgkVGFnRm91bmQpIHsKICAgICAgICAgICAgICAgIEFkZC1Db250ZW50IC1QYXRoICRPdXRGaWxlIC1WYWx1ZSAkXwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgJE91dEZpbGUKfQoKCgpmdW5jdGlvbiBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJENvbW1hbmQsCiAgICAgICAgJENyZWRlbnRpYWwgPSAkbnVsbCwKICAgICAgICBbU3dpdGNoXSAkSWdub3JlU3RkRXJyLAogICAgICAgIFtTd2l0Y2hdICROb0Jhc2U2NAogICAgKQogICAgYmVnaW4gewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbgogICAgfQogICAgZW5kIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24gLUVuZAogICAgfQogICAgcHJvY2VzcyB7CiAgICAgICAgdHJhcCB7CiAgICAgICAgICAgICYkVHJhcEhhbmRsZXIKICAgICAgICB9CgogICAgICAgICRTdGRPdXQgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCiAgICAgICAgJFN0ZEVyciA9IFtJTy5QYXRoXTo6R2V0VGVtcEZpbGVOYW1lKCkKCiAgICAgICAgJEFyZ3VtZW50TGlzdCA9IEAoJy1PdXRwdXRGb3JtYXQnLCAnWE1MJykKCiAgICAgICAgaWYgKCROb0Jhc2U2NCkgewogICAgICAgICAgICAkVG1wU2NyaXB0ID0gW0lPLlBhdGhdOjpHZXRUZW1wRmlsZU5hbWUoKQogICAgICAgICAgICBSZW5hbWUtSXRlbSAtUGF0aCAiJFRtcFNjcmlwdCIgLU5ld05hbWUgIiRUbXBTY3JpcHQucHMxIiAtRm9yY2UKICAgICAgICAgICAgJFRtcFNjcmlwdCA9ICIkVG1wU2NyaXB0LnBzMSIKCiAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICRUbXBTY3JpcHQKCiAgICAgICAgICAgICRDb21tYW5kIHwgT3V0LUZpbGUgJFRtcFNjcmlwdAoKICAgICAgICAgICAgJEFyZ3VtZW50TGlzdCArPSBAKCctRmlsZScsICIkVG1wU2NyaXB0IikKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICRCeXRlcyA9IFtUZXh0LkVuY29kaW5nXTo6VW5pY29kZS5HZXRCeXRlcygkQ29tbWFuZCkKICAgICAgICAgICAgJEVuY29kZWRDb21tYW5kID0gW0NvbnZlcnRdOjpUb0Jhc2U2NFN0cmluZygkQnl0ZXMpCiAgICAgICAgICAgIAogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAkRW5jb2RlZENvbW1hbmQKCiAgICAgICAgICAgICRBcmd1bWVudExpc3QgKz0gQCgnLUVuY29kZWRDb21tYW5kJywgJEVuY29kZWRDb21tYW5kKQogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nRGVidWcgJEFyZ3VtZW50TGlzdAoKICAgICAgICBXcml0ZS1Mb2cgIlN0YXJ0aW5nIGV4dGVybmFsIFBvd2VyU2hlbGwgcHJvY2VzcyAuLi4iCgogICAgICAgIGlmICgkQ3JlZGVudGlhbCAtZXEgJG51bGwpIHsKICAgICAgICAgICAgJFByb2Nlc3MgPSBTdGFydC1Qcm9jZXNzIC1GaWxlUGF0aCAncG93ZXJzaGVsbC5leGUnIGAKICAgICAgICAgICAgICAgIC1Bcmd1bWVudExpc3QgQCgkQXJndW1lbnRMaXN0KSBgCiAgICAgICAgICAgICAgICAtUmVkaXJlY3RTdGFuZGFyZE91dHB1dCAkU3RkT3V0IGAKICAgICAgICAgICAgICAgIC1SZWRpcmVjdFN0YW5kYXJkRXJyb3IgJFN0ZEVyciBgCiAgICAgICAgICAgICAgICAtTm9OZXdXaW5kb3cgYAogICAgICAgICAgICAgICAgLVdhaXQgYAogICAgICAgICAgICAgICAgLVBhc3NUaHJ1CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkUHJvY2VzcyA9IFN0YXJ0LVByb2Nlc3MgLUZpbGVQYXRoICdwb3dlcnNoZWxsLmV4ZScgYAogICAgICAgICAgICAgICAgLUFyZ3VtZW50TGlzdCBAKCRBcmd1bWVudExpc3QpIGAKICAgICAgICAgICAgICAgIC1SZWRpcmVjdFN0YW5kYXJkT3V0cHV0ICRTdGRPdXQgYAogICAgICAgICAgICAgICAgLVJlZGlyZWN0U3RhbmRhcmRFcnJvciAkU3RkRXJyIGAKICAgICAgICAgICAgICAgIC1DcmVkZW50aWFsICRDcmVkZW50aWFsIGAKICAgICAgICAgICAgICAgIC1Ob05ld1dpbmRvdyBgCiAgICAgICAgICAgICAgICAtV2FpdCBgCiAgICAgICAgICAgICAgICAtUGFzc1RocnUKICAgICAgICB9CgogICAgICAgIFdyaXRlLUxvZyAiRXh0ZXJuYWwgUG93ZXJTaGVsbCBwcm9jZXNzIGV4aXRlZCB3aXRoIGV4aXQgY29kZSAnJCgkUHJvY2Vzcy5FeGl0Q29kZSknLiIKCiAgICAgICAgI2lmICgkQXJndW1lbnRMaXN0IC1jb250YWlucyAnLUZpbGUnKSB7CiAgICAgICAgIyAgICBSZW1vdmUtSXRlbSAtUGF0aCAkVG1wU2NyaXB0IC1Gb3JjZQogICAgICAgICN9CgogICAgICAgICRFcnJvckFjdGlvblByZWZlcmVuY2VTYXZlZCA9ICRFcnJvckFjdGlvblByZWZlcmVuY2UKICAgICAgICAkRXJyb3JBY3Rpb25QcmVmZXJlbmNlID0gJ1NpbGVudGx5Q29udGludWUnCgogICAgICAgIFdyaXRlLUxvZ0RlYnVnICJTdGRPdXQgZmlsZSBpcyAnJFN0ZE91dCciCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIlN0ZEVyciBmaWxlIGlzICckU3RkRXJyJyIKCiAgICAgICAgaWYgKChHZXQtSXRlbSAkU3RkT3V0KS5MZW5ndGggLWd0IDApIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICJMb2FkaW5nIFN0ZE91dCBmcm9tICckU3RkT3V0JyIKICAgICAgICAgICAgICAgICRUbXBGaWxlID0gU2VsZWN0LUNsaVhtbEJsb2NrICRTdGRPdXQKICAgICAgICAgICAgICAgICRTdGRPdXRPYmplY3QgPSBJbXBvcnQtQ2xpeG1sICRUbXBGaWxlCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPFN0ZE91dD4iCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAoJFN0ZE91dE9iamVjdCkKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L1N0ZE91dD4iCiAgICAgICAgICAgICAgICAkU3RkT3V0T2JqZWN0CiAgICAgICAgICAgICAgICAjUmVtb3ZlLUl0ZW0gLVBhdGggJFRtcEZpbGUgLUZvcmNlCiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2F0Y2ggewogICAgICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIkFuIGVycm9yIG9jY3VyZWQgd2hpbGUgbG9hZGluZyBTdGRPdXQgZnJvbSAnJFRtcEZpbGUnIgogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBpZiAoKEdldC1JdGVtICRTdGRFcnIpLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIkxvYWRpbmcgU3RkRXJyIC4uLiIKICAgICAgICAgICAgICAgICRUbXBGaWxlID0gU2VsZWN0LUNsaVhtbEJsb2NrICRTdGRFcnIKICAgICAgICAgICAgICAgICRTdGRFcnJPYmplY3QgPSBJbXBvcnQtQ2xpeG1sICRUbXBGaWxlCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPFN0ZEVycj4iCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAoJFN0ZEVyck9iamVjdCkKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L1N0ZEVycj4iCiAgICAgICAgICAgICAgICBpZiAoLW5vdCAkSWdub3JlU3RkRXJyKSB7CiAgICAgICAgICAgICAgICAgICAgJFN0ZEVyck9iamVjdAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgI1JlbW92ZS1JdGVtIC1QYXRoICRUbXBGaWxlIC1Gb3JjZQogICAgICAgICAgICB9CiAgICAgICAgICAgIGNhdGNoIHsKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICJBbiBlcnJvciBvY2N1cmVkIHdoaWxlIGxvYWRpbmcgU3RkRXJyIGZyb20gJyRUbXBGaWxlJyIKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICRFcnJvckFjdGlvblByZWZlcmVuY2VTYXZlZAoKICAgICAgICBpZiAoJFByb2Nlc3MuRXhpdENvZGUgLW5lIDApIHsKICAgICAgICAgICAgdGhyb3coIkV4dGVybmFsIFBvd2VyU2hlbGwgcHJvY2VzcyBleGl0ZWQgd2l0aCBjb2RlICckKCRQcm9jZXNzLkV4aXRDb2RlKSciKQogICAgICAgIH0KCiAgICAgICAgI1JlbW92ZS1JdGVtICRTdGRPdXQgLUZvcmNlCiAgICAgICAgI1JlbW92ZS1JdGVtICRTdGRFcnIgLUZvcmNlCiAgICB9Cn0K", - "PCMNCi5ERVNDUklQVElPTg0KDQojIyBGYWlsb3ZlciBDbHVzdGVyIElucHV0IERhdGEgKGZyb20gdGhlIFVJKQ0KDQoqIERvbWFpbiBNZW1iZXJzaGlwDQogICAgLSBbU3RyaW5nXSAvIFtTZWxlY3QgYm94XSAkRG9tYWluTmFtZSAtIERvbWFpbiBuYW1lDQoqIERvbWFpbiBVc2VyIENyZWRlbnRpYWxzDQogICAgLSBbU3RyaW5nXSAkVXNlck5hbWUgLSBVc2VybmFtZQ0KICAgIC0gW1Bhc3N3b3JkIHN0cmluZ10gJFVzZXJQYXNzd29yZCAtIFVzZXIgcGFzc3dvcmQNCiogU2hhcmVkIEZvbGRlciBJbmZvcm1hdGlvbg0KICAgIC0gW1N0cmluZ10gJFNoYXJlU2VydmVyIC0gU2VydmVyIHdoaWNoIHdpbGwgaG9zdCB0aGUgZm9sZGVyDQogICAgLSBbU3RyaW5nXSAkU2hhcmVOYW1lIC0gU2hhcmUgbmFtZQ0KICAgIC0gW1N0cmluZ10gJFNoYXJlUGF0aCAtIFNoYXJlZCBmb2xkZXIgaW50ZXJuYWwgcGF0aA0KKiBGYWlsb3ZlciBDbHVzdGVyIE1lbWJlcnMNCiAgICAtIFtTdHJpbmddICRDbHVzdGVyTmFtZSAtIENsdXN0ZXIgbmFtZQ0KICAgIC0gW1N0cmluZ10gJENsdXN0ZXJJUCAtIFN0YXRpYyBJUCBhZGRyZXNzIHRoYXQgd2lsbCBiZSBhc3NpZ25lZCB0byB0aGUgY2x1c3Rlcg0KICAgIC0gW1N0cmluZ1tdXSAkQ2x1c3Rlck5vZGVzIC0gTGlzdCBvZiBub2RlIG5hbWVzDQoNCg0KDQojIyBGYWlsb3ZlciBDbHVzdGVyIGNyZWF0aW9uIHdvcmtmbG93DQoNCiogQ3JlYXRlIEFEIGRvbWFpbg0KKiBKb2luIGFsbCB0aGUgVk1zIHRvIHRoYXQgZG9tYWluDQoqIFByZXBhcmUgbm9kZXMNCiAgICAtIEluc3RhbGwgRmFpbG92ZXIgQ2x1c3RlciBwcmVyZXF1aXNpdGVzIG9uIGFsbCBGQyBub2Rlcw0KKiBDcmVhdGUgZmFpbG92ZXIgY2x1c3Rlcg0KICAgIC0gQ3JlYXRlIG5ldyBjbHVzdGVyDQogICAgLSBBZGQgbWVtYmVycw0KKiBDb25mdWd1cmUgRkMgcXVvcnVtDQogICAgLSBDcmVhdGUgbmV3IGZvbGRlciB0aGF0IHdpbGwgYmUgc2hhcmVkDQogICAgLSBTaGFyZSB0aGF0IGZvbGRlciB3aXRoIGFwcHJvcHJpYXRlIHBlcm1pc3Npb25zDQogICAgLSBDb25maWd1cmUgcXVvcnVtIG1vZGUNCg0KDQoNCiMjIEhlbHBmdWwgU21iU2hhcmUqIEZ1bmN0aW9ucw0KDQoqIE5ldy1TbWJTaGFyZQ0KKiBHcmFudC1TbWJTaGFyZUFjY2Vzcw0KDQojPg0KDQp0cmFwIHsNCiAgICAmJFRyYXBIYW5kbGVyDQp9DQoNCg0KDQpmdW5jdGlvbiBJbnN0YWxsLUZhaWxvdmVyQ2x1c3RlclByZXJlcXVpc2l0ZXMgew0KICAgICNJbXBvcnQtTW9kdWxlIEZhaWxvdmVyQ2x1c3RlcnMNCg0KICAgIEFkZC1XaW5kb3dzRmVhdHVyZSBGYWlsb3Zlci1DbHVzdGVyaW5nLCBSU0FULUNsdXN0ZXJpbmctUG93ZXJTaGVsbA0KfQ0KDQoNCg0KZnVuY3Rpb24gTmV3LUZhaWxvdmVyQ2x1c3RlclNoYXJlZEZvbGRlciB7DQoJcGFyYW0gKA0KICAgICAgICBbU3RyaW5nXSAkQ2x1c3Rlck5hbWUsDQogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLA0KICAgICAgICBbU3RyaW5nXSAkU2hhcmVTZXJ2ZXIsDQoJCVtTdHJpbmddICRTaGFyZVBhdGggPSAkKCRFbnY6U3lzdGVtRHJpdmUgKyAnXEZDU2hhcmUnKSwNCgkJW1N0cmluZ10gJFNoYXJlTmFtZSA9ICdGQ1NoYXJlJywNCiAgICAgICAgW1N0cmluZ10gJFVzZXJOYW1lLA0KICAgICAgICBbU3RyaW5nXSAkVXNlclBhc3N3b3JkLA0KICAgICAgICAkQ3JlZGVudGlhbCA9ICRudWxsDQoJKQ0KICAgIGJlZ2luIHsNCiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uDQogICAgfQ0KICAgIGVuZCB7DQogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kDQogICAgfQ0KICAgIHByb2Nlc3Mgew0KICAgICAgICB0cmFwIHsNCiAgICAgICAgICAgICYkVHJhcEhhbmRsZXINCiAgICAgICAgfQ0KDQogICAgICAgIFdyaXRlLUxvZyAiLS0+IE5ldy1GYWlsb3ZlckNsdXN0ZXJTaGFyZWRGb2xkZXIiDQoNCiAgICAgICAgV3JpdGUtTG9nICJDcmVhdGluZyBzaGFyZWQgZm9sZGVyIGZvciBGYWlsb3ZlciBDbHVzdGVyIC4uLiINCiAgICAgICAgDQogICAgICAgIGlmICgkQ3JlZGVudGlhbCAtZXEgJG51bGwpIHsNCiAgICAgICAgICAgICRDcmVkZW50aWFsID0gTmV3LUNyZWRlbnRpYWwgLVVzZXJOYW1lICIkRG9tYWluTmFtZVwkVXNlck5hbWUiIC1QYXNzd29yZCAiJFVzZXJQYXNzd29yZCINCiAgICAgICAgfQ0KDQogICAgICAgIGlmICgoVGVzdC1Db25uZWN0aW9uIC1Db21wdXRlck5hbWUgJFNoYXJlU2VydmVyIC1Db3VudCAxIC1RdWlldCkgLWVxICRmYWxzZSkgew0KICAgICAgICAgICAgdGhyb3coIlNlcnZlciAnJFNoYXJlU2VydmVyJyBpcyB1bnJlYWNoYWJsZSB2aWEgSUNNUC4iKQ0KICAgICAgICB9DQoNCiAgICAgICAgJFNlc3Npb24gPSBOZXctUFNTZXNzaW9uIC1Db21wdXRlck5hbWUgJFNoYXJlU2VydmVyIC1DcmVkZW50aWFsICRDcmVkZW50aWFsDQoNCiAgICAgICAgV3JpdGUtTG9nICJDcmVhdGluZyBmb2xkZXIgb24gJyRTaGFyZVNlcnZlcicgLi4uIg0KICAgICAgICBJbnZva2UtQ29tbWFuZCAtU2Vzc2lvbiAkU2Vzc2lvbiAtU2NyaXB0QmxvY2sgew0KICAgICAgICAgICAgICAgIHBhcmFtICgNCiAgICAgICAgICAgICAgICAgICAgW1N0cmluZ10gJFNoYXJlUGF0aCwNCiAgICAgICAgICAgICAgICAgICAgW1N0cmluZ10gJFNoYXJlTmFtZSwNCiAgICAgICAgICAgICAgICAgICAgW1N0cmluZ10gJENsdXN0ZXJBY2NvdW50DQogICAgICAgICAgICAgICAgKQ0KDQogICAgICAgICAgICAgICAgUmVtb3ZlLVNtYlNoYXJlIC1OYW1lICRTaGFyZU5hbWUgLUZvcmNlIC1FcnJvckFjdGlvbiAnU2lsZW50bHlDb250aW51ZScNCiAgICAgICAgICAgICAgICBSZW1vdmUtSXRlbSAtUGF0aCAkU2hhcmVQYXRoIC1Gb3JjZSAtRXJyb3JBY3Rpb24gJ1NpbGVudGx5Q29udGludWUnDQoNCiAgICAgICAgICAgICAgICBOZXctSXRlbSAtUGF0aCAkU2hhcmVQYXRoIC1JdGVtVHlwZSBDb250YWluZXIgLUZvcmNlDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgTmV3LVNtYlNoYXJlIC1QYXRoICRTaGFyZVBhdGggYA0KICAgICAgICAgICAgICAgICAgICAtTmFtZSAkU2hhcmVOYW1lIGANCiAgICAgICAgICAgICAgICAgICAgLUZ1bGxBY2Nlc3MgIiRDbHVzdGVyQWNjb3VudCIsICdFdmVyeW9uZScgYA0KICAgICAgICAgICAgICAgICAgICAtRGVzY3JpcHRpb24gIlNoYXJlZCBmb2xkZXIgZm9yIEZhaWxvdmVyIENsdXN0ZXIuIg0KDQogICAgICAgICAgICB9IC1Bcmd1bWVudExpc3QgJFNoYXJlUGF0aCwgJFNoYXJlTmFtZSwgIiREb21haW5OYW1lXCRDbHVzdGVyTmFtZWAkIg0KDQogICAgICAgIFdyaXRlLUxvZyAiQ29uZmd1cmluZyBGYWlsb3ZlciBDbHVzdGVyIHRvIHVzZSBzaGFyZWQgZm9sZGVyIGFzIHFvdXJ1bSByZXNvdXJzZSAuLi4iDQoNCiAgICAgICAgJG51bGwgPSBTZXQtQ2x1c3RlclF1b3J1bSAtTm9kZUFuZEZpbGVTaGFyZU1ham9yaXR5ICJcXCRTaGFyZVNlcnZlclwkU2hhcmVOYW1lIg0KDQogICAgICAgIFdyaXRlLUxvZyAiPC0tIE5ldy1GYWlsb3ZlckNsdXN0ZXJTaGFyZWRGb2xkZXIiDQogICAgfQ0KfQ0KDQoNCg0KZnVuY3Rpb24gTmV3LUZhaWxvdmVyQ2x1c3RlciB7DQoJcGFyYW0gKA0KICAgICAgICBbU3RyaW5nXSAkQ2x1c3Rlck5hbWUsDQogICAgICAgIFtTdHJpbmddICRTdGF0aWNBZGRyZXNzLA0KICAgICAgICBbU3RyaW5nW11dICRDbHVzdGVyTm9kZXMsDQogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLA0KICAgICAgICBbU3RyaW5nXSAkVXNlck5hbWUsDQogICAgICAgIFtTdHJpbmddICRVc2VyUGFzc3dvcmQsDQogICAgICAgICRDcmVkZW50aWFsDQogICAgKQ0KICAgIGJlZ2luIHsNCiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uDQogICAgfQ0KICAgIGVuZCB7DQogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kDQogICAgfQ0KICAgIHByb2Nlc3Mgew0KICAgICAgICB0cmFwIHsNCiAgICAgICAgICAgICYkVHJhcEhhbmRsZXINCiAgICAgICAgfQ0KDQogICAgICAgIFdyaXRlLUxvZyAiQ2x1c3Rlck5vZGVzOiAkKCRDbHVzdGVyTm9kZXMgLWpvaW4gJywgJykiDQoNCiAgICAgICAgaWYgKCRDcmVkZW50aWFsIC1lcSAkbnVsbCkgew0KICAgICAgICAgICAgJENyZWRlbnRpYWwgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIg0KICAgICAgICB9DQoNCiAgICAgICAgSW1wb3J0LU1vZHVsZSBGYWlsb3ZlckNsdXN0ZXJzDQoNCiAgICAJaWYgKChHZXQtQ2x1c3RlciAkQ2x1c3Rlck5hbWUgLUVycm9yQWN0aW9uIFNpbGVudGx5Q29udGludWUpIC1lcSAkbnVsbCkgew0KICAgICAgICAgICAgV3JpdGUtTG9nICJDcmVhdGluZyBuZXcgY2x1c3RlciAnJENsdXN0ZXJOYW1lJyAuLi4iDQogICAgICAgICAgICBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyAtQ29tbWFuZCBAIg0KSW1wb3J0LU1vZHVsZSBGYWlsb3ZlckNsdXN0ZXJzDQpOZXctQ2x1c3RlciAtTmFtZSAnJENsdXN0ZXJOYW1lJyAtU3RhdGljQWRkcmVzcyAnJFN0YXRpY0FkZHJlc3MnDQoiQCAtQ3JlZGVudGlhbCAkQ3JlZGVudGlhbCAtTm9CYXNlNjQNCiAgICAgICAgICAgIFN0YXJ0LVNsZWVwIC1TZWNvbmRzIDE1DQogICAgICAgIH0NCiAgICAgICAgZWxzZSB7DQogICAgICAgICAgICBXcml0ZS1Mb2cgIkNsdXN0ZXIgJyRDbHVzdGVyTmFtZScgYWxyZWFkeSBleGlzdHMuIg0KICAgICAgICB9DQoNCiAgICAgICAgZm9yZWFjaCAoJE5vZGUgaW4gJENsdXN0ZXJOb2Rlcykgew0KICAgICAgICAgICAgV3JpdGUtTG9nICJBZGRpbmcgbm9kZSAnJE5vZGUnIHRvIHRoZSBjbHVzdGVyICckQ2x1c3Rlck5hbWUnIC4uLiINCiAgICAgICAgICAgIGlmICgoR2V0LUNsdXN0ZXJOb2RlICROb2RlIC1FcnJvckFjdGlvbiBTaWxlbnRseUNvbnRpbnVlKSAtZXEgJG51bGwpIHsNCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2cgIkFkZGluZyBub2RlIC4uLiINCiAgICAgICAgICAgICAgICBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyAtQ29tbWFuZCBAIg0KSW1wb3J0LU1vZHVsZSBGYWlsb3ZlckNsdXN0ZXJzDQpBZGQtQ2x1c3Rlck5vZGUgLUNsdXN0ZXIgJyRDbHVzdGVyTmFtZScgLU5hbWUgJyROb2RlJw0KIkAgLUNyZWRlbnRpYWwgJENyZWRlbnRpYWwgLU5vQmFzZTY0DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2cgIk5vZGUgJyROb2RlJyBhbHJlYWR5IGEgcGFydCBvZiB0aGUgY2x1c3RlciAnJENsdXN0ZXJOYW1lJy4iDQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICB9DQp9DQoNCg0KDQo8Iw0KDQojIEV4YW1wbGUNCg0KJERvbWFpbk5hbWUgPSAnZmMtYWNtZS5sb2NhbCcNCiREb21haW5Vc2VyID0gJ0FkbWluaXN0cmF0b3InDQokRG9tYWluUGFzc3dvcmQgPSAnUEBzc3cwcmQnDQoNCiRDbHVzdGVyTmFtZSA9ICdmYy10ZXN0Jw0KJENsdXN0ZXJJUCA9ICcxMC4yMDAuMC42MCcNCiRDbHVzdGVyTm9kZXMgPSBAKCdmYy1ub2RlLTAxJywnZmMtbm9kZS0wMicsJ2ZjLW5vZGUtMDMnKQ0KDQokU2hhcmVTZXJ2ZXIgPSAnZmMtZGMtMDEnDQokU2hhcmVOYW1lID0gJ0ZDU2hhcmUnDQoNCiRTaGFyZVBhdGggPSAiQzpcJFNoYXJlTmFtZSINCg0KDQoNCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucyAtRm9yY2UNCg0KJENyZWRzID0gTmV3LUNyZWRlbnRpYWwgYA0KICAgIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJERvbWFpblVzZXIiIGANCiAgICAtUGFzc3dvcmQgIiREb21haW5QYXNzd29yZCINCg0KTmV3LUZhaWxvdmVyQ2x1c3RlciBgDQogICAgLUNsdXN0ZXJOYW1lICRDbHVzdGVyTmFtZSBgDQogICAgLVN0YXRpY0FkZHJlc3MgJENsdXN0ZXJJUCBgDQogICAgLUNsdXN0ZXJOb2RlcyAkQ2x1c3Rlck5vZGVzIGANCiAgICAtQ3JlZGVudGlhbCAkQ3JlZHMNCg0KTmV3LUZhaWxvdmVyQ2x1c3RlclNoYXJlZEZvbGRlciBgDQogICAgLUNsdXN0ZXJOYW1lICRDbHVzdGVyTmFtZSBgDQogICAgLURvbWFpbk5hbWUgJERvbWFpbk5hbWUgYA0KICAgIC1TaGFyZVNlcnZlciAkU2hhcmVTZXJ2ZXIgYA0KICAgIC1TaGFyZVBhdGggIiRTaGFyZVBhdGgiIGANCiAgICAtU2hhcmVOYW1lICIkU2hhcmVOYW1lIiBgDQogICAgLUNyZWRlbnRpYWwgJENyZWRzDQoNCiM+DQo=" - ] + "RebootOnCompletion": 0 } \ No newline at end of file diff --git a/data/templates/agent/SqlServerCluster/FailoverClusterPrerequisites.template b/data/templates/agent/SqlServerCluster/FailoverClusterPrerequisites.template index b9e7590..e439f54 100644 --- a/data/templates/agent/SqlServerCluster/FailoverClusterPrerequisites.template +++ b/data/templates/agent/SqlServerCluster/FailoverClusterPrerequisites.template @@ -1,4 +1,10 @@ { + "Scripts": [ + "ImportCoreFunctions.ps1", + "Update-ServiceConfig.ps1", + "SQLServerForAOAG.ps1", + "Failover-Cluster.ps1" + ], "Commands": [ { "Name": "Install-FailoverClusterPrerequisites", @@ -18,11 +24,5 @@ } } ], - "RebootOnCompletion": 1, - "Scripts": [ - "SW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zIC1Gb3JjZQoKCmZ1bmN0aW9uIFNob3ctSW52b2NhdGlvbkluZm8gewogICAgcGFyYW0gKAogICAgICAgICRJbnZvY2F0aW9uLAogICAgICAgIFtTd2l0Y2hdICRFbmQKICAgICkKCiAgICBpZiAoJEVuZCkgewogICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L2Z1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICB9CiAgICBlbHNlIHsKICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPGZ1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjxwYXJhbT4iCiAgICAgICAgZm9yZWFjaCAoJFBhcmFtZXRlciBpbiAkSW52b2NhdGlvbi5NeUNvbW1hbmQuUGFyYW1ldGVycykgewogICAgICAgICAgICBmb3JlYWNoICgkS2V5IGluICRQYXJhbWV0ZXIuS2V5cykgewogICAgICAgICAgICAgICAgJFR5cGUgPSAkUGFyYW1ldGVyWyRLZXldLlBhcmFtZXRlclR5cGUuRnVsbE5hbWUKICAgICAgICAgICAgICAgIGZvcmVhY2ggKCRWYWx1ZSBpbiAkSW52b2NhdGlvbi5Cb3VuZFBhcmFtZXRlcnNbJEtleV0pIHsKICAgICAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiWyRUeXBlXSAkS2V5ID0gJyRWYWx1ZSciCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjwvcGFyYW0+IgogICAgfQp9CgoKJFRyYXBIYW5kbGVyID0gewogICAgV3JpdGUtTG9nRXJyb3IgQCgiPGV4Y2VwdGlvbj4iLCAkXykgLUVudGlyZU9iamVjdAogICAgV3JpdGUtTG9nRXJyb3IgIjwvZXhjZXB0aW9uPiIKICAgIGJyZWFrCn0KCgp0cmFwIHsKICAgICYkVHJhcEhhbmRsZXIKfQoKJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICdTdG9wJwoKCjwjCiMgVXNhZ2UgZXhhbXBsZSBmb3IgU2hvdy1JbnZvY2F0aW9uSW5mbwoKZnVuY3Rpb24gTXlGdW5jdGlvbiB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJFZhbHVlMSwKICAgICAgICBbU3RyaW5nXSAkVmFsdWUyLAogICAgICAgIFtJbnRdICRJbnQxCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KICAgICAgICAjIE1haW4gY29kZSBoZXJlCiAgICB9Cn0KIz4K", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgoKCmZ1bmN0aW9uIFVwZGF0ZS1TZXJ2aWNlQ29uZmlnIHsKICAgIHBhcmFtICgKICAgICAgICBbU3RyaW5nXSAkTmFtZSwKICAgICAgICBbU3RyaW5nXSAkUnVuQXNVc2VyID0gJycsCiAgICAgICAgW1N0cmluZ10gJERvbWFpbk5hbWUgPSAnLicsCiAgICAgICAgW1N0cmluZ10gJFBhc3N3b3JkID0gJycsCiAgICAgICAgW1N3aXRjaF0gJFJ1bkFzTG9jYWxTZXJ2aWNlCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgJEFyZ3VtZW50TGlzdCA9IEAoJ2NvbmZpZycsICJgIiROYW1lYCIiKQoKICAgICAgICBpZiAoJFJ1bkFzTG9jYWxTZXJ2aWNlKSB7CiAgICAgICAgICAgICRBcmd1bWVudExpc3QgKz0gQCgib2JqPSIsICJgIk5UIEFVVEhPUklUWVxMb2NhbFNlcnZpY2VgIiIpCiAgICAgICAgfQogICAgICAgIGVsc2VpZiAoJFJ1bkFzVXNlciAtbmUgJycpIHsKICAgICAgICAgICAgJEFyZ3VtZW50TGlzdCArPSBAKCJvYmo9IiwgImAiJERvbWFpbk5hbWVcJFJ1bkFzVXNlcmAiIiwgInBhc3N3b3JkPSIsICJgIiRQYXNzd29yZGAiIikKICAgICAgICB9CgogICAgICAgICRQcm9jZXNzID0gRXhlYyAnc2MuZXhlJyAkQXJndW1lbnRMaXN0IC1QYXNzVGhydSAtUmVkaXJlY3RTdHJlYW1zCgogICAgICAgIGlmICgkUHJvY2Vzcy5FeGl0Q29kZSAtbmUgMCkgewogICAgICAgICAgICB0aHJvdyAiQ29tbWFuZCAnc2MuZXhlJyByZXR1cm5lZCBleGl0IGNvZGUgJyQoJFByb2Nlc3MuRXhpdENvZGUpJyIKICAgICAgICB9CgogICAgICAgICROdFJpZ2h0cyA9ICJDOlxNdXJhbm9cVG9vbHNcbnRyaWdodHMuZXhlIgoKICAgICAgICBpZiAoLW5vdCAoW0lPLkZpbGVdOjpFeGlzdHMoJE50UmlnaHRzKSkpIHsKICAgICAgICAgICAgdGhyb3cgIkZpbGUgJyROdFJpZ2h0cycgbm90IGZvdW5kLiIKICAgICAgICB9CgogICAgICAgICRQcm9jZXNzID0gRXhlYyAkTnRSaWdodHMgQCgnLXUnLCAiJERvbWFpbk5hbWVcJFJ1bkFzVXNlciIsICcrcicsICdTZVNlcnZpY2VMb2dvblJpZ2h0JykgLVJlZGlyZWN0U3RyZWFtcyAtUGFzc1RocnUKCiAgICAgICAgaWYgKCRQcm9jZXNzLkV4aXRDb2RlIC1uZSAwKSB7CiAgICAgICAgICAgIHRocm93ICJDb21tYW5kICckTnRSaWdodHMnIHJldHVybmVkIGV4aXQgY29kZSAnJCgkUHJvY2Vzcy5FeGl0Q29kZSknIgogICAgICAgIH0KCiAgICAgICAgJFByb2Nlc3MgPSBFeGVjICROdFJpZ2h0cyBAKCctdScsICIkRG9tYWluTmFtZVwkUnVuQXNVc2VyIiwgJytyJywgJ1NlQmF0Y2hMb2dvblJpZ2h0JykgLVJlZGlyZWN0U3RyZWFtcyAtUGFzc1RocnUKCiAgICAgICAgaWYgKCRQcm9jZXNzLkV4aXRDb2RlIC1uZSAwKSB7CiAgICAgICAgICAgIHRocm93ICJDb21tYW5kICckTnRSaWdodHMnIHJldHVybmVkIGV4aXQgY29kZSAnJCgkUHJvY2Vzcy5FeGl0Q29kZSknIgogICAgICAgIH0KICAgIH0KfQo=", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlclBvd2VyU2hlbGxNb2R1bGUgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJwogICAgKQogICAgYmVnaW4gewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbgogICAgfQogICAgZW5kIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24gLUVuZAogICAgfQogICAgcHJvY2VzcyB7CiAgICAgICAgdHJhcCB7CiAgICAgICAgICAgICYkVHJhcEhhbmRsZXIKICAgICAgICB9CgogICAgICAgIGlmICgoR2V0LU1vZHVsZSBTUUxQUyAtTGlzdEF2YWlsYWJsZSkgLW5lICRudWxsKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiTW9kdWxlIFNRTFNQIGFscmVhZHkgaW5zdGFsbGVkLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcVG9vbHMnKQogICAgICAgIH0KICAgICAgICAKICAgICAgICAkRmlsZUxpc3QgPSBAKAogICAgICAgICAgICAnU1FMU3lzQ2xyVHlwZXMubXNpJywKICAgICAgICAgICAgJ1NoYXJlZE1hbmFnZW1lbnRPYmplY3RzLm1zaScsCiAgICAgICAgICAgICdQb3dlclNoZWxsVG9vbHMubXNpJwogICAgICAgICkKCiAgICAgICAgZm9yZWFjaCAoJE1zaUZpbGUgaW4gJEZpbGVMaXN0KSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVHJ5aW5nIHRvIGluc3RhbGwgJyRNc2lGaWxlJyAuLi4iCiAgICAgICAgICAgICRNc2lQYXRoID0gSm9pbi1QYXRoICRTZXR1cFJvb3QgJE1zaUZpbGUKICAgICAgICAgICAgaWYgKFtJTy5GaWxlXTo6RXhpc3RzKCRNc2lQYXRoKSkgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJTdGFydGluZyBtc2lleGUgLi4uIgogICAgICAgICAgICAgICAgJFJlc3VsdCA9IEV4ZWMgLUZpbGVQYXRoICJtc2lleGVjLmV4ZSIgLUFyZ3VtZW50TGlzdCBAKCcvaScsICJgIiRNc2lQYXRoYCIiLCAnL3F1aWV0JykgLVBhc3NUaHJ1CiAgICAgICAgICAgICAgICBpZiAoJFJlc3VsdC5FeGl0Q29kZSAtbmUgMCkgewogICAgICAgICAgICAgICAgICAgIHRocm93ICgiSW5zdGFsbGF0aW9uIG9mIE1TSSBwYWNrYWdlICckTXNpUGF0aCcgZmFpbGVkIHdpdGggZXJyb3IgY29kZSAnJCgkUmVzdWx0LkV4aXRDb2RlKSciKQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJGaWxlICckTXNpUGF0aCcgbm90IGZvdW5kLiIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQoKCgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgUGF0aCB0byBmb2xkZXIgd2hlcmUgbXNpIGZpbGVzIGZvciBhZGRpdGlvbmFsIFNRTCBmZWF0dXJlcyBhcmUgbG9jYXRlZAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJywKCiAgICAgICAgIyBQYXRoIHRvIGZvbGRlciB3aGVyZSBtc2kgZmlsZXMgZm9yIGFkZGl0aW9uYWwgU1FMUFMgbW9kdWxlIGFyZSBsb2NhdGVkCiAgICAgICAgW1N0cmluZ10gJFNxbHBzU2V0dXBSb290ID0gJycsCgogICAgICAgIFtTdHJpbmddICRNdXJhbm9GaWxlU2hhcmUgPSAnJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIERvbWFpbiBuYW1lCiAgICAgICAgW1N0cmluZ10gJFNRTFNlcnZpY2VVc2VyRG9tYWluID0gJ2ZjLWFjbWUubG9jYWwnLAoKICAgICAgICAjIChSRVFVSVJFRCkgVXNlciBuYW1lIGZvciB0aGUgYWNjb3VudCB3aGljaCB3aWxsIGJlIHVzZWQgYnkgU1FMIHNlcnZpY2UKICAgICAgICBbU3RyaW5nXSAkU1FMU2VydmljZVVzZXJOYW1lID0gJ0FkbWluaXN0cmF0b3InLAoKICAgICAgICAjIChSRVFVSVJFRCkgUGFzc3dvcmQgZm9yIHRoYXQgdXNlcgogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlclBhc3N3b3JkID0gJ1BAc3N3MHJkJywKCiAgICAgICAgW1N3aXRjaF0gJFVwZGF0ZUVuYWJsZWQKICAgICkKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcMjAxMicpCiAgICAgICAgfQoKICAgICAgICAkRXh0cmFPcHRpb25zID0gQHt9CgogICAgICAgIGlmICgkVXBkYXRlRW5hYmxlZCkgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJHRydWV9CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJGZhbHNlfQogICAgICAgIH0KCiAgICAgICAgTmV3LVNRTFNlcnZlckZvckFPQUcgYAogICAgICAgICAgICAtU2V0dXBSb290ICRTZXR1cFJvb3QgYAogICAgICAgICAgICAtU1FMU3ZjVXNyRG9tYWluICRTUUxTZXJ2aWNlVXNlckRvbWFpbiBgCiAgICAgICAgICAgIC1TUUxTdmNVc3JOYW1lICRTUUxTZXJ2aWNlVXNlck5hbWUgYAogICAgICAgICAgICAtU1FMU3ZjVXNyUGFzc3dvcmQgJFNRTFNlcnZpY2VVc2VyUGFzc3dvcmQgYAogICAgICAgICAgICAtRXh0cmFPcHRpb25zICRFeHRyYU9wdGlvbnMKICAgIH0KfQoKCgpmdW5jdGlvbiBJbml0aWFsaXplLUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXAgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnRQYXNzd29yZCwKICAgICAgICBbU3RyaW5nXSAkU3FsU2VydmljZUFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICRQcmltYXJ5Tm9kZSwKICAgICAgICBbU3RyaW5nXSAkU2hhcmVOYW1lID0gJ1NoYXJlZFdvcmtEaXInCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgJFNoYXJlTmV0d29ya1BhdGggPSAnXFwnICsgJFByaW1hcnlOb2RlICsgJ1wnICsgJFNoYXJlTmFtZQoKICAgICAgICAkRG9tYWluQWRtaW5BY2NvdW50Q3JlZHMgPSBOZXctQ3JlZGVudGlhbCBgCiAgICAgICAgICAgIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJERvbWFpbkFkbWluQWNjb3VudE5hbWUiIGAKICAgICAgICAgICAgLVBhc3N3b3JkICIkRG9tYWluQWRtaW5BY2NvdW50UGFzc3dvcmQiCgogICAgICAgICRGdW5jdGlvbnNGaWxlID0gRXhwb3J0LUZ1bmN0aW9uICdHZXQtTmV4dEZyZWVQb3J0JywgJ0luaXRpYWxpemUtQWx3YXlzT24nCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICBgJF8KICAgIGV4aXQgMQp9CgpJbXBvcnQtTW9kdWxlIENvcmVGdW5jdGlvbnMKCldyaXRlLUxvZyAiSW1wb3J0aW5nIGZ1bmN0aW9ucyBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ0luaXRpYWxpemUtQWx3YXlzT24nIC4uLiIKYCRYbWxGaWxlID0gW0lPLlBhdGhdOjpDb21iaW5lKCIkU2hhcmVOZXR3b3JrUGF0aCIsICJgJChgJEVudjpDb21wdXRlck5hbWUpLnhtbCIpCldyaXRlLUxvZyAiT3V0cHV0IFhNTCBmaWxlIGlzICdgJFhtbEZpbGUnIgpJbml0aWFsaXplLUFsd2F5c09uIHwgRXhwb3J0LUNsaVhtbCAtUGF0aCBgJFhtbEZpbGUKIkAgLUNyZWRlbnRpYWwgJERvbWFpbkFkbWluQWNjb3VudENyZWRzIC1Ob0Jhc2U2NAogICAgfQp9CgoKZnVuY3Rpb24gTmV3LVNoYXJlZEZvbGRlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKQogICAgICAgIFtTdHJpbmddICRTaGFyZVBhdGggPSBbSU8uUGF0aF06OkNvbWJpbmUoJEVudjpTeXN0ZW1Ecml2ZSArICdcJywgJ1NoYXJlZFdvcmtEaXInKSwKCiAgICAgICAgIyAoT1BUSU9OQUwpCiAgICAgICAgW1N0cmluZ10gJFNoYXJlTmFtZSA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlID0gJyAnCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBzY3JpcHQgcnVucyBvbiBwcmltYXJ5IG5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZyBzY3JpcHQuIgogICAgICAgICAgICByZXR1cm4KICAgICAgICB9CgogICAgICAgIGlmICgkU2hhcmVOYW1lIC1lcSAnJykgewogICAgICAgICAgICAkU2hhcmVOYW1lID0gW0lPLlBhdGhdOjpHZXRGaWxlTmFtZVdpdGhvdXRFeHRlbnNpb24oJFNoYXJlUGF0aCkKICAgICAgICB9CgogICAgICAgIFdyaXRlLUxvZ0RlYnVnICJTaGFyZVBhdGggPSAnJFNoYXJlUGF0aCciCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIlNoYXJlTmFtZSA9ICckU2hhcmVOYW1lJyIKCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgc2hhcmUgJyRTaGFyZU5hbWUnIgogICAgICAgICAgICAkbnVsbCA9IEdldC1TbWJTaGFyZSAtTmFtZSAkU2hhcmVOYW1lIC1FcnJvckFjdGlvbiAnU3RvcCcKICAgICAgICAgICAgJG51bGwgPSBSZW1vdmUtU21iU2hhcmUgLU5hbWUgJFNoYXJlTmFtZSAtRm9yY2UKICAgICAgICAgICAgd3JpdGUtTG9nICJTaGFyZSAnJFNoYXJlTmFtZScgcmVtb3ZlZC4iCiAgICAgICAgfQogICAgICAgIGNhdGNoIHsKICAgICAgICAgICAgV3JpdGUtTG9nV2FybmluZyAiU2hhcmUgJyRTaGFyZU5hbWUnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgZm9sZGVyICckU2hhcmVQYXRoIgogICAgICAgICAgICAkbnVsbCA9IEdldC1JdGVtIC1QYXRoICRTaGFyZVBhdGggLUVycm9yQWN0aW9uICdTdG9wJwogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICRTaGFyZVBhdGggLVJlY3Vyc2UgLUZvcmNlCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRm9sZGVyICckU2hhcmVQYXRoJyByZW1vdmVkLiIKICAgICAgICB9CiAgICAgICAgY2F0Y2ggewogICAgICAgICAgICBXcml0ZS1Mb2dXYXJuaW5nICJGb2xkZXIgJyRTaGFyZVBhdGgnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgJG51bGwgPSBOZXctSXRlbSAtUGF0aCAkU2hhcmVQYXRoIC1JdGVtVHlwZSBDb250YWluZXIgLUZvcmNlCiAgICAgICAgICAgICAgICAKICAgICAgICAkbnVsbCA9IE5ldy1TbWJTaGFyZSAtUGF0aCAkU2hhcmVQYXRoIGAKICAgICAgICAgICAgLU5hbWUgJFNoYXJlTmFtZSBgCiAgICAgICAgICAgIC1GdWxsQWNjZXNzICJFdmVyeW9uZSIgYAogICAgICAgICAgICAtRGVzY3JpcHRpb24gIlNoYXJlZCBmb2xkZXIgZm9yIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cCBzZXR1cC4iCgogICAgICAgIHJldHVybiAnXFwnICsgJEVudjpDb21wdXRlck5hbWUgKyAnXCcgKyAkU2hhcmVOYW1lCiAgICB9Cn0KCgoKZnVuY3Rpb24gTmV3LURhdGFiYXNlRm9yQU9BRyB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJERhdGFiYXNlTmFtZSwKICAgICAgICBbU3RyaW5nXSAkRG9tYWluTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlck5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJQYXNzd29yZAogICAgKQoKICAgICRDcmVkcyA9IE5ldy1DcmVkZW50aWFsIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJFVzZXJOYW1lIiAtUGFzc3dvcmQgIiRVc2VyUGFzc3dvcmQiCgogICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gJ0ludm9rZS1TUUxUZXh0JywgJ0NvbnZlcnRUby1TUUxOYW1lJywgJ0NvbnZlcnRUby1TUUxTdHJpbmcnLCAnTmV3LVNRTERhdGFiYXNlJwoKICAgIFN0YXJ0LVBvd2VyU2hlbGxQcm9jZXNzIEAiCnRyYXAgewogICAgYCRfCiAgICBleGl0IDEKfQoKSW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zCgpXcml0ZS1Mb2cgIkltcG9ydGluZyBmdW5jdGlvbnMgZnJvbSBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1TUUxEYXRhYmFzZScgLi4uIgpOZXctU1FMRGF0YWJhc2UgJERhdGFiYXNlTmFtZQoiQCAtQ3JlZGVudGlhbCAkQ3JlZHMgLU5vQmFzZTY0Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHUHJpbWFyeVJlcGxpY2EgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKSBOYW1lIG9mIHRoZSBuZXcgQXZhaWxhYmlsaXR5IEdyb3VwLiBJZiBub3Qgc3BlY2lmaWVkIHRoZW4gZGVmYXVsdCBuYW1lIHdpbGwgYmUgdXNlZC4KICAgICAgICBbU3RyaW5nXSAkR3JvdXBOYW1lID0gJ011cmFub0FHJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICROb2RlTGlzdCwKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGUgbmFtZSB0aGF0IHdpbGwgYmUgcHJpbWFyeSBmb3Igc2VsZWN0ZWQgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nXSAkUHJpbWFyeU5vZGUsCgogICAgICAgICMgKFJFUVVJUkVEKSBEYXRhYmFzZSBsaXN0IHRoYXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICREYXRhYmFzZUxpc3QsCgogICAgICAgICMgKFJFUVVJUkVEKSBMaXN0ZW5lciBuYW1lIHRoYXQgd2lsbCBiZSB1c2VkIGJ5IGNsaWVudHMgdG8gY29ubmVjdCB0byBkYXRhYmFzZXMgaW4gdGhhdCBBRwogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyTmFtZSA9ICdNdXJhbm9BR19MaXN0ZW5lcicsCgogICAgICAgICMgKFJFUVVJUkVEKSBJUCBhZGRyZXNzIG9mIHRoZSBsaXN0ZW5lcgogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVySVAsCgogICAgICAgIFtTdHJpbmddICRMaXN0ZW5lcklQTWFzayA9ICcyNTUuMjU1LjI1NS4wJywKCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyUG9ydCA9ICc1MDIzJywKCiAgICAgICAgIyBTeW5jIE1vZGUgTm9kZSBMaXN0CiAgICAgICAgW1N0cmluZ1tdXSAkU3luY01vZGVOb2RlTGlzdCwKCiAgICAgICAgW1N0cmluZ10gJFNoYXJlZFdvcmtEaXIgPSAnU2hhcmVkV29ya0RpcicsCgogICAgICAgIFtTdHJpbmddICRDbGlYbWxGaWxlID0gJycsCgogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlclBhc3N3b3JkCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJQcmltYXJ5IG5vZGU6ICckKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkpJyIKICAgICAgICBXcml0ZS1Mb2cgIkN1cnJlbnQgbm9kZTogJyQoKCRFbnY6Q29tcHV0ZXJOYW1lKS5Ub0xvd2VyKCkpJyIKCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICQoJEVudjpDb21wdXRlck5hbWUpLlRvTG93ZXIoKSkgewogICAgICAgICAgICBXcml0ZS1Mb2cgIlRoaXMgZnVuY3Rpb24gd29ya3Mgb24gUHJpbWFyeU5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZy4iCiAgICAgICAgICAgIHJldHVybgogICAgICAgIH0KCiAgICAgICAgaWYgKCRDbGlYbWxGaWxlIC1lcSAnJykgewogICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ID0gQCgpCiAgICAgICAgICAgIGZvcmVhY2ggKCROb2RlIGluICROb2RlTGlzdCkgewogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAkTm9kZUVuZHBvaW50UG9ydCA9IEltcG9ydC1DbGlYbWwgLVBhdGggIlxcJFByaW1hcnlOb2RlXFNoYXJlZFdvcmtEaXJcJE5vZGUueG1sIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2F0Y2ggewogICAgICAgICAgICAgICAgICAgIFdyaXRlLUxvZyAiVXNpbmcgZGVmYXVsdCBlbmRwb2ludCBwb3J0IDUwMjIiCiAgICAgICAgICAgICAgICAgICAgJE5vZGVFbmRwb2ludFBvcnQgPSA1MDIyCiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uID0gQHsKICAgICAgICAgICAgICAgICAgICAiU0VSVkVSX0lOU1RBTkNFIiA9ICIkTm9kZSI7CiAgICAgICAgICAgICAgICAgICAgIkVORFBPSU5UX1VSTCIgPSAiVENQOi8vJHtOb2RlfToke05vZGVFbmRwb2ludFBvcnR9IjsKICAgICAgICAgICAgICAgICAgICAiQVZBSUxBQklMSVRZX01PREUiID0gIkFTWU5DSFJPTk9VU19DT01NSVQiOwogICAgICAgICAgICAgICAgICAgICJGQUlMT1ZFUl9NT0RFIj0iTUFOVUFMIjsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZiAoJFN5bmNNb2RlTm9kZUxpc3QgLWNvbnRhaW5zICROb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBpbiBTeW5jTW9kZU5vZGVMaXN0IgogICAgICAgICAgICAgICAgICAgICRSZXBsaWNhRGVmaW5pdGlvblsnQVZBSUxBQklMSVRZX01PREUnXSA9ICJTWU5DSFJPTk9VU19DT01NSVQiCiAgICAgICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uWydGQUlMT1ZFUl9NT0RFJ10gPSAiQVVUT01BVElDIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBOT1QgaW4gU3luY01vZGVOb2RlTGlzdCIKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ICs9IEAoJFJlcGxpY2FEZWZpbml0aW9uKQogICAgICAgICAgICB9CgogICAgICAgICAgICAkUHJlZmVyZW5jZXMgPSBAe30KCiAgICAgICAgICAgICRMaXN0ZW5lckRlZmluaXRpb24gPSBAewogICAgICAgICAgICAgICAgIk5BTUUiPSRMaXN0ZW5lck5hbWU7CiAgICAgICAgICAgICAgICAiUE9SVCIgPSAiJExpc3RlbmVyUG9ydCI7CiAgICAgICAgICAgICAgICAiU1RBVElDIiA9ICIkTGlzdGVuZXJJUC8kTGlzdGVuZXJJUE1hc2siCiAgICAgICAgICAgIH0KCiAgICAgICAgICAgICRQYXJhbWV0ZXJzID0gQHsKICAgICAgICAgICAgICAgICdXb3JrRGlyJyA9ICJcXCRQcmltYXJ5Tm9kZVwkU2hhcmVkV29ya0RpciI7CiAgICAgICAgICAgICAgICAnTmFtZScgPSAkR3JvdXBOYW1lOwogICAgICAgICAgICAgICAgJ0RhdGFiYXNlTmFtZXMnID0gJERhdGFiYXNlTGlzdDsKICAgICAgICAgICAgICAgICdSZXBsaWNhRGVmcycgPSAkUmVwbGljYURlZmluaXRpb25MaXN0OwogICAgICAgICAgICAgICAgJ1ByZWZlcmVuY2VzJyA9ICRQcmVmZXJlbmNlczsKICAgICAgICAgICAgICAgICdMaXN0ZW5lckRlZicgPSAkTGlzdGVuZXJEZWZpbml0aW9uOwogICAgICAgICAgICB9CgogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICJcXCRQcmltYXJ5Tm9kZVxTaGFyZWRXb3JrRGlyXCoiIC1Gb3JjZQoKICAgICAgICAgICAgJENsaVhtbEZpbGUgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiQ2xpWG1sIGZpbGU6ICckQ2xpWG1sRmlsZSciCgogICAgICAgICAgICAkbnVsbCA9IEV4cG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUgLUlucHV0T2JqZWN0ICRQYXJhbWV0ZXJzIC1EZXB0aCAxMAoKICAgICAgICAgICAgJG51bGwgPSBJbml0aWFsaXplLUFPQUdQcmltYXJ5UmVwbGljYSBgCiAgICAgICAgICAgICAgICAtQ2xpWG1sRmlsZSAkQ2xpWG1sRmlsZSBgCiAgICAgICAgICAgICAgICAtRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgCiAgICAgICAgICAgICAgICAtVXNlck5hbWUgJFVzZXJOYW1lIGAKICAgICAgICAgICAgICAgIC1Vc2VyUGFzc3dvcmQgJFVzZXJQYXNzd29yZCBgCiAgICAgICAgICAgICAgICAtUHJpbWFyeU5vZGUgJFByaW1hcnlOb2RlCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiSW5uZXIgJ0luaXRpYWxpemUtQU9BR1ByaW1hcnlSZXBsaWNhJyBjYWxsIGNvbXBsZXRlZC4iCiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAgICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gLUFsbAoKICAgICAgICAgICAgJG51bGwgPSBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyBAIgp0cmFwIHsKICAgIGAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJJbXBvcnRpbmcgQ2xpWG1sIHBhcmFtZXRlcnMgZmlsZSAuLi4iCmAkUGFyYW1ldGVycyA9IEltcG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwIGBgCiAgICAtV29ya0RpciBgJFBhcmFtZXRlcnNbJ1dvcmtEaXInXSBgYAogICAgLU5hbWUgYCRQYXJhbWV0ZXJzWydOYW1lJ10gYGAKICAgIC1EYXRhYmFzZU5hbWVzIGAkUGFyYW1ldGVyc1snRGF0YWJhc2VOYW1lcyddIGBgCiAgICAtUmVwbGljYURlZnMgYCRQYXJhbWV0ZXJzWydSZXBsaWNhRGVmcyddIGBgCiAgICAtUHJlZmVyZW5jZXMgYCRQYXJhbWV0ZXJzWydQcmVmZXJlbmNlcyddIGBgCiAgICAtTGlzdGVuZXJEZWYgYCRQYXJhbWV0ZXJzWydMaXN0ZW5lckRlZiddCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgICAgICB9CiAgICB9Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHU2Vjb25kYXJ5UmVwbGljYSB7CiAgICBwYXJhbSAoCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmdbXV0gJE5vZGVMaXN0LAoKICAgICAgICAjIChSRVFVSVJFRCkgTm9kZSBuYW1lIHRoYXQgd2lsbCBiZSBwcmltYXJ5IGZvciBzZWxlY3RlZCBBdmFpbGFiaWxpdHkgR3JvdXAKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlLAoKICAgICAgICBbU3RyaW5nXSAkU2hhcmVkV29ya0RpciA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJERvbWFpbk5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJOYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyUGFzc3dvcmQKICAgICkgCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLWVxICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBmdW5jdGlvbiB3b3JrcyBvbiBhbnkgU2Vjb25kYXJ5Tm9kZSBvbmx5LiIKICAgICAgICAgICAgV3JpdGUtTG9nICJFeGl0aW5nLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAkRnVuY3Rpb25zRmlsZSA9IEV4cG9ydC1GdW5jdGlvbiAtQWxsCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJTdGFydGluZyAnTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXBSZXBsaWNhJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwUmVwbGljYSAtV29ya0RpciAiXFwkUHJpbWFyeU5vZGVcJFNoYXJlZFdvcmtEaXIiCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgIH0KfQoKCgpmdW5jdGlvbiBEaXNhYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb2ZmCiAgICB9Cn0KCgoKZnVuY3Rpb24gRW5hYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb24KICAgIH0KfQoKCgpmdW5jdGlvbiBFbmFibGUtVHJ1c3RlZEhvc3RzIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBTZXQtSXRlbSBXU01hbjpcbG9jYWxob3N0XENsaWVudFxUcnVzdGVkSG9zdHMgLVZhbHVlICcqJyAtRm9yY2UKICAgIH0KfQo=", - "PCMNCi5ERVNDUklQVElPTg0KDQojIyBGYWlsb3ZlciBDbHVzdGVyIElucHV0IERhdGEgKGZyb20gdGhlIFVJKQ0KDQoqIERvbWFpbiBNZW1iZXJzaGlwDQogICAgLSBbU3RyaW5nXSAvIFtTZWxlY3QgYm94XSAkRG9tYWluTmFtZSAtIERvbWFpbiBuYW1lDQoqIERvbWFpbiBVc2VyIENyZWRlbnRpYWxzDQogICAgLSBbU3RyaW5nXSAkVXNlck5hbWUgLSBVc2VybmFtZQ0KICAgIC0gW1Bhc3N3b3JkIHN0cmluZ10gJFVzZXJQYXNzd29yZCAtIFVzZXIgcGFzc3dvcmQNCiogU2hhcmVkIEZvbGRlciBJbmZvcm1hdGlvbg0KICAgIC0gW1N0cmluZ10gJFNoYXJlU2VydmVyIC0gU2VydmVyIHdoaWNoIHdpbGwgaG9zdCB0aGUgZm9sZGVyDQogICAgLSBbU3RyaW5nXSAkU2hhcmVOYW1lIC0gU2hhcmUgbmFtZQ0KICAgIC0gW1N0cmluZ10gJFNoYXJlUGF0aCAtIFNoYXJlZCBmb2xkZXIgaW50ZXJuYWwgcGF0aA0KKiBGYWlsb3ZlciBDbHVzdGVyIE1lbWJlcnMNCiAgICAtIFtTdHJpbmddICRDbHVzdGVyTmFtZSAtIENsdXN0ZXIgbmFtZQ0KICAgIC0gW1N0cmluZ10gJENsdXN0ZXJJUCAtIFN0YXRpYyBJUCBhZGRyZXNzIHRoYXQgd2lsbCBiZSBhc3NpZ25lZCB0byB0aGUgY2x1c3Rlcg0KICAgIC0gW1N0cmluZ1tdXSAkQ2x1c3Rlck5vZGVzIC0gTGlzdCBvZiBub2RlIG5hbWVzDQoNCg0KDQojIyBGYWlsb3ZlciBDbHVzdGVyIGNyZWF0aW9uIHdvcmtmbG93DQoNCiogQ3JlYXRlIEFEIGRvbWFpbg0KKiBKb2luIGFsbCB0aGUgVk1zIHRvIHRoYXQgZG9tYWluDQoqIFByZXBhcmUgbm9kZXMNCiAgICAtIEluc3RhbGwgRmFpbG92ZXIgQ2x1c3RlciBwcmVyZXF1aXNpdGVzIG9uIGFsbCBGQyBub2Rlcw0KKiBDcmVhdGUgZmFpbG92ZXIgY2x1c3Rlcg0KICAgIC0gQ3JlYXRlIG5ldyBjbHVzdGVyDQogICAgLSBBZGQgbWVtYmVycw0KKiBDb25mdWd1cmUgRkMgcXVvcnVtDQogICAgLSBDcmVhdGUgbmV3IGZvbGRlciB0aGF0IHdpbGwgYmUgc2hhcmVkDQogICAgLSBTaGFyZSB0aGF0IGZvbGRlciB3aXRoIGFwcHJvcHJpYXRlIHBlcm1pc3Npb25zDQogICAgLSBDb25maWd1cmUgcXVvcnVtIG1vZGUNCg0KDQoNCiMjIEhlbHBmdWwgU21iU2hhcmUqIEZ1bmN0aW9ucw0KDQoqIE5ldy1TbWJTaGFyZQ0KKiBHcmFudC1TbWJTaGFyZUFjY2Vzcw0KDQojPg0KDQp0cmFwIHsNCiAgICAmJFRyYXBIYW5kbGVyDQp9DQoNCg0KDQpmdW5jdGlvbiBJbnN0YWxsLUZhaWxvdmVyQ2x1c3RlclByZXJlcXVpc2l0ZXMgew0KICAgICNJbXBvcnQtTW9kdWxlIEZhaWxvdmVyQ2x1c3RlcnMNCg0KICAgIEFkZC1XaW5kb3dzRmVhdHVyZSBGYWlsb3Zlci1DbHVzdGVyaW5nLCBSU0FULUNsdXN0ZXJpbmctUG93ZXJTaGVsbA0KfQ0KDQoNCg0KZnVuY3Rpb24gTmV3LUZhaWxvdmVyQ2x1c3RlclNoYXJlZEZvbGRlciB7DQoJcGFyYW0gKA0KICAgICAgICBbU3RyaW5nXSAkQ2x1c3Rlck5hbWUsDQogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLA0KICAgICAgICBbU3RyaW5nXSAkU2hhcmVTZXJ2ZXIsDQoJCVtTdHJpbmddICRTaGFyZVBhdGggPSAkKCRFbnY6U3lzdGVtRHJpdmUgKyAnXEZDU2hhcmUnKSwNCgkJW1N0cmluZ10gJFNoYXJlTmFtZSA9ICdGQ1NoYXJlJywNCiAgICAgICAgW1N0cmluZ10gJFVzZXJOYW1lLA0KICAgICAgICBbU3RyaW5nXSAkVXNlclBhc3N3b3JkLA0KICAgICAgICAkQ3JlZGVudGlhbCA9ICRudWxsDQoJKQ0KICAgIGJlZ2luIHsNCiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uDQogICAgfQ0KICAgIGVuZCB7DQogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kDQogICAgfQ0KICAgIHByb2Nlc3Mgew0KICAgICAgICB0cmFwIHsNCiAgICAgICAgICAgICYkVHJhcEhhbmRsZXINCiAgICAgICAgfQ0KDQogICAgICAgIFdyaXRlLUxvZyAiLS0+IE5ldy1GYWlsb3ZlckNsdXN0ZXJTaGFyZWRGb2xkZXIiDQoNCiAgICAgICAgV3JpdGUtTG9nICJDcmVhdGluZyBzaGFyZWQgZm9sZGVyIGZvciBGYWlsb3ZlciBDbHVzdGVyIC4uLiINCiAgICAgICAgDQogICAgICAgIGlmICgkQ3JlZGVudGlhbCAtZXEgJG51bGwpIHsNCiAgICAgICAgICAgICRDcmVkZW50aWFsID0gTmV3LUNyZWRlbnRpYWwgLVVzZXJOYW1lICIkRG9tYWluTmFtZVwkVXNlck5hbWUiIC1QYXNzd29yZCAiJFVzZXJQYXNzd29yZCINCiAgICAgICAgfQ0KDQogICAgICAgIGlmICgoVGVzdC1Db25uZWN0aW9uIC1Db21wdXRlck5hbWUgJFNoYXJlU2VydmVyIC1Db3VudCAxIC1RdWlldCkgLWVxICRmYWxzZSkgew0KICAgICAgICAgICAgdGhyb3coIlNlcnZlciAnJFNoYXJlU2VydmVyJyBpcyB1bnJlYWNoYWJsZSB2aWEgSUNNUC4iKQ0KICAgICAgICB9DQoNCiAgICAgICAgJFNlc3Npb24gPSBOZXctUFNTZXNzaW9uIC1Db21wdXRlck5hbWUgJFNoYXJlU2VydmVyIC1DcmVkZW50aWFsICRDcmVkZW50aWFsDQoNCiAgICAgICAgV3JpdGUtTG9nICJDcmVhdGluZyBmb2xkZXIgb24gJyRTaGFyZVNlcnZlcicgLi4uIg0KICAgICAgICBJbnZva2UtQ29tbWFuZCAtU2Vzc2lvbiAkU2Vzc2lvbiAtU2NyaXB0QmxvY2sgew0KICAgICAgICAgICAgICAgIHBhcmFtICgNCiAgICAgICAgICAgICAgICAgICAgW1N0cmluZ10gJFNoYXJlUGF0aCwNCiAgICAgICAgICAgICAgICAgICAgW1N0cmluZ10gJFNoYXJlTmFtZSwNCiAgICAgICAgICAgICAgICAgICAgW1N0cmluZ10gJENsdXN0ZXJBY2NvdW50DQogICAgICAgICAgICAgICAgKQ0KDQogICAgICAgICAgICAgICAgUmVtb3ZlLVNtYlNoYXJlIC1OYW1lICRTaGFyZU5hbWUgLUZvcmNlIC1FcnJvckFjdGlvbiAnU2lsZW50bHlDb250aW51ZScNCiAgICAgICAgICAgICAgICBSZW1vdmUtSXRlbSAtUGF0aCAkU2hhcmVQYXRoIC1Gb3JjZSAtRXJyb3JBY3Rpb24gJ1NpbGVudGx5Q29udGludWUnDQoNCiAgICAgICAgICAgICAgICBOZXctSXRlbSAtUGF0aCAkU2hhcmVQYXRoIC1JdGVtVHlwZSBDb250YWluZXIgLUZvcmNlDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgTmV3LVNtYlNoYXJlIC1QYXRoICRTaGFyZVBhdGggYA0KICAgICAgICAgICAgICAgICAgICAtTmFtZSAkU2hhcmVOYW1lIGANCiAgICAgICAgICAgICAgICAgICAgLUZ1bGxBY2Nlc3MgIiRDbHVzdGVyQWNjb3VudCIsICdFdmVyeW9uZScgYA0KICAgICAgICAgICAgICAgICAgICAtRGVzY3JpcHRpb24gIlNoYXJlZCBmb2xkZXIgZm9yIEZhaWxvdmVyIENsdXN0ZXIuIg0KDQogICAgICAgICAgICB9IC1Bcmd1bWVudExpc3QgJFNoYXJlUGF0aCwgJFNoYXJlTmFtZSwgIiREb21haW5OYW1lXCRDbHVzdGVyTmFtZWAkIg0KDQogICAgICAgIFdyaXRlLUxvZyAiQ29uZmd1cmluZyBGYWlsb3ZlciBDbHVzdGVyIHRvIHVzZSBzaGFyZWQgZm9sZGVyIGFzIHFvdXJ1bSByZXNvdXJzZSAuLi4iDQoNCiAgICAgICAgJG51bGwgPSBTZXQtQ2x1c3RlclF1b3J1bSAtTm9kZUFuZEZpbGVTaGFyZU1ham9yaXR5ICJcXCRTaGFyZVNlcnZlclwkU2hhcmVOYW1lIg0KDQogICAgICAgIFdyaXRlLUxvZyAiPC0tIE5ldy1GYWlsb3ZlckNsdXN0ZXJTaGFyZWRGb2xkZXIiDQogICAgfQ0KfQ0KDQoNCg0KZnVuY3Rpb24gTmV3LUZhaWxvdmVyQ2x1c3RlciB7DQoJcGFyYW0gKA0KICAgICAgICBbU3RyaW5nXSAkQ2x1c3Rlck5hbWUsDQogICAgICAgIFtTdHJpbmddICRTdGF0aWNBZGRyZXNzLA0KICAgICAgICBbU3RyaW5nW11dICRDbHVzdGVyTm9kZXMsDQogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLA0KICAgICAgICBbU3RyaW5nXSAkVXNlck5hbWUsDQogICAgICAgIFtTdHJpbmddICRVc2VyUGFzc3dvcmQsDQogICAgICAgICRDcmVkZW50aWFsDQogICAgKQ0KICAgIGJlZ2luIHsNCiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uDQogICAgfQ0KICAgIGVuZCB7DQogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kDQogICAgfQ0KICAgIHByb2Nlc3Mgew0KICAgICAgICB0cmFwIHsNCiAgICAgICAgICAgICYkVHJhcEhhbmRsZXINCiAgICAgICAgfQ0KDQogICAgICAgIFdyaXRlLUxvZyAiQ2x1c3Rlck5vZGVzOiAkKCRDbHVzdGVyTm9kZXMgLWpvaW4gJywgJykiDQoNCiAgICAgICAgaWYgKCRDcmVkZW50aWFsIC1lcSAkbnVsbCkgew0KICAgICAgICAgICAgJENyZWRlbnRpYWwgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIg0KICAgICAgICB9DQoNCiAgICAgICAgSW1wb3J0LU1vZHVsZSBGYWlsb3ZlckNsdXN0ZXJzDQoNCiAgICAJaWYgKChHZXQtQ2x1c3RlciAkQ2x1c3Rlck5hbWUgLUVycm9yQWN0aW9uIFNpbGVudGx5Q29udGludWUpIC1lcSAkbnVsbCkgew0KICAgICAgICAgICAgV3JpdGUtTG9nICJDcmVhdGluZyBuZXcgY2x1c3RlciAnJENsdXN0ZXJOYW1lJyAuLi4iDQogICAgICAgICAgICBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyAtQ29tbWFuZCBAIg0KSW1wb3J0LU1vZHVsZSBGYWlsb3ZlckNsdXN0ZXJzDQpOZXctQ2x1c3RlciAtTmFtZSAnJENsdXN0ZXJOYW1lJyAtU3RhdGljQWRkcmVzcyAnJFN0YXRpY0FkZHJlc3MnDQoiQCAtQ3JlZGVudGlhbCAkQ3JlZGVudGlhbCAtTm9CYXNlNjQNCiAgICAgICAgICAgIFN0YXJ0LVNsZWVwIC1TZWNvbmRzIDE1DQogICAgICAgIH0NCiAgICAgICAgZWxzZSB7DQogICAgICAgICAgICBXcml0ZS1Mb2cgIkNsdXN0ZXIgJyRDbHVzdGVyTmFtZScgYWxyZWFkeSBleGlzdHMuIg0KICAgICAgICB9DQoNCiAgICAgICAgZm9yZWFjaCAoJE5vZGUgaW4gJENsdXN0ZXJOb2Rlcykgew0KICAgICAgICAgICAgV3JpdGUtTG9nICJBZGRpbmcgbm9kZSAnJE5vZGUnIHRvIHRoZSBjbHVzdGVyICckQ2x1c3Rlck5hbWUnIC4uLiINCiAgICAgICAgICAgIGlmICgoR2V0LUNsdXN0ZXJOb2RlICROb2RlIC1FcnJvckFjdGlvbiBTaWxlbnRseUNvbnRpbnVlKSAtZXEgJG51bGwpIHsNCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2cgIkFkZGluZyBub2RlIC4uLiINCiAgICAgICAgICAgICAgICBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyAtQ29tbWFuZCBAIg0KSW1wb3J0LU1vZHVsZSBGYWlsb3ZlckNsdXN0ZXJzDQpBZGQtQ2x1c3Rlck5vZGUgLUNsdXN0ZXIgJyRDbHVzdGVyTmFtZScgLU5hbWUgJyROb2RlJw0KIkAgLUNyZWRlbnRpYWwgJENyZWRlbnRpYWwgLU5vQmFzZTY0DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2cgIk5vZGUgJyROb2RlJyBhbHJlYWR5IGEgcGFydCBvZiB0aGUgY2x1c3RlciAnJENsdXN0ZXJOYW1lJy4iDQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICB9DQp9DQoNCg0KDQo8Iw0KDQojIEV4YW1wbGUNCg0KJERvbWFpbk5hbWUgPSAnZmMtYWNtZS5sb2NhbCcNCiREb21haW5Vc2VyID0gJ0FkbWluaXN0cmF0b3InDQokRG9tYWluUGFzc3dvcmQgPSAnUEBzc3cwcmQnDQoNCiRDbHVzdGVyTmFtZSA9ICdmYy10ZXN0Jw0KJENsdXN0ZXJJUCA9ICcxMC4yMDAuMC42MCcNCiRDbHVzdGVyTm9kZXMgPSBAKCdmYy1ub2RlLTAxJywnZmMtbm9kZS0wMicsJ2ZjLW5vZGUtMDMnKQ0KDQokU2hhcmVTZXJ2ZXIgPSAnZmMtZGMtMDEnDQokU2hhcmVOYW1lID0gJ0ZDU2hhcmUnDQoNCiRTaGFyZVBhdGggPSAiQzpcJFNoYXJlTmFtZSINCg0KDQoNCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucyAtRm9yY2UNCg0KJENyZWRzID0gTmV3LUNyZWRlbnRpYWwgYA0KICAgIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJERvbWFpblVzZXIiIGANCiAgICAtUGFzc3dvcmQgIiREb21haW5QYXNzd29yZCINCg0KTmV3LUZhaWxvdmVyQ2x1c3RlciBgDQogICAgLUNsdXN0ZXJOYW1lICRDbHVzdGVyTmFtZSBgDQogICAgLVN0YXRpY0FkZHJlc3MgJENsdXN0ZXJJUCBgDQogICAgLUNsdXN0ZXJOb2RlcyAkQ2x1c3Rlck5vZGVzIGANCiAgICAtQ3JlZGVudGlhbCAkQ3JlZHMNCg0KTmV3LUZhaWxvdmVyQ2x1c3RlclNoYXJlZEZvbGRlciBgDQogICAgLUNsdXN0ZXJOYW1lICRDbHVzdGVyTmFtZSBgDQogICAgLURvbWFpbk5hbWUgJERvbWFpbk5hbWUgYA0KICAgIC1TaGFyZVNlcnZlciAkU2hhcmVTZXJ2ZXIgYA0KICAgIC1TaGFyZVBhdGggIiRTaGFyZVBhdGgiIGANCiAgICAtU2hhcmVOYW1lICIkU2hhcmVOYW1lIiBgDQogICAgLUNyZWRlbnRpYWwgJENyZWRzDQoNCiM+DQo=" - ] + "RebootOnCompletion": 1 } \ No newline at end of file diff --git a/data/templates/agent/SqlServerCluster/InitializeAOAGPrimaryReplica.template b/data/templates/agent/SqlServerCluster/InitializeAOAGPrimaryReplica.template index 270e320..54ca203 100644 --- a/data/templates/agent/SqlServerCluster/InitializeAOAGPrimaryReplica.template +++ b/data/templates/agent/SqlServerCluster/InitializeAOAGPrimaryReplica.template @@ -1,4 +1,13 @@ { + "Scripts": [ + "ImportCoreFunctions.ps1", + "OptionParser.ps1", + "SQLServerOptionParsers.ps1", + "SQLServerInsatller.ps1", + "Export-Function.ps1", + "Start-PowerShellProcess.ps1", + "SQLServerForAOAG.ps1" + ], "Commands": [ { "Name": "Initialize-AOAGPrimaryReplica", @@ -15,14 +24,5 @@ "DatabaseList": "$databaseList" } } - ], - "Scripts": [ - "SW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zIC1Gb3JjZQoKCmZ1bmN0aW9uIFNob3ctSW52b2NhdGlvbkluZm8gewogICAgcGFyYW0gKAogICAgICAgICRJbnZvY2F0aW9uLAogICAgICAgIFtTd2l0Y2hdICRFbmQKICAgICkKCiAgICBpZiAoJEVuZCkgewogICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L2Z1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICB9CiAgICBlbHNlIHsKICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPGZ1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjxwYXJhbT4iCiAgICAgICAgZm9yZWFjaCAoJFBhcmFtZXRlciBpbiAkSW52b2NhdGlvbi5NeUNvbW1hbmQuUGFyYW1ldGVycykgewogICAgICAgICAgICBmb3JlYWNoICgkS2V5IGluICRQYXJhbWV0ZXIuS2V5cykgewogICAgICAgICAgICAgICAgJFR5cGUgPSAkUGFyYW1ldGVyWyRLZXldLlBhcmFtZXRlclR5cGUuRnVsbE5hbWUKICAgICAgICAgICAgICAgIGZvcmVhY2ggKCRWYWx1ZSBpbiAkSW52b2NhdGlvbi5Cb3VuZFBhcmFtZXRlcnNbJEtleV0pIHsKICAgICAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiWyRUeXBlXSAkS2V5ID0gJyRWYWx1ZSciCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjwvcGFyYW0+IgogICAgfQp9CgoKJFRyYXBIYW5kbGVyID0gewogICAgV3JpdGUtTG9nRXJyb3IgQCgiPGV4Y2VwdGlvbj4iLCAkXykgLUVudGlyZU9iamVjdAogICAgV3JpdGUtTG9nRXJyb3IgIjwvZXhjZXB0aW9uPiIKICAgIGJyZWFrCn0KCgp0cmFwIHsKICAgICYkVHJhcEhhbmRsZXIKfQoKJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICdTdG9wJwoKCjwjCiMgVXNhZ2UgZXhhbXBsZSBmb3IgU2hvdy1JbnZvY2F0aW9uSW5mbwoKZnVuY3Rpb24gTXlGdW5jdGlvbiB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJFZhbHVlMSwKICAgICAgICBbU3RyaW5nXSAkVmFsdWUyLAogICAgICAgIFtJbnRdICRJbnQxCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KICAgICAgICAjIE1haW4gY29kZSBoZXJlCiAgICB9Cn0KIz4K", - "ZnVuY3Rpb24gTmV3LU9wdGlvbiAoW3N0cmluZ10kTmFtZSwgW3N3aXRjaF0kU3dpdGNoLCBbc3dpdGNoXSRCb29sZWFuLCBbc3dpdGNoXSRTdHJpbmcsIFtzd2l0Y2hdJExpc3QsICRDb25zdHJhaW50cz0kbnVsbCkgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBPcHRpb24gb2JqZWN0CgogICAgLkRFU0NSSVBUSU9OCiAgICBPcHRpb24gb2JqZWN0IGlzIGEgdmlydHVhbCBvYmplY3QgcmVwcmVzdG50aW5nIHR5cGVkIGNvbW1hbmQgbGluZSBvcHRpb24uIFRoZXNlIG9iamVjdHMgZW5jYXBzdWxhdGUgZXNjYXBpbmcgYW5kCiAgICB2YWxpZGF0aW9uIG1hdHRlcnMuCgogICAgT25lIGFuZCBvbmx5IG9uZSBvZiB0aGUgc3dpdGNoZXMgJ1N3aXRjaCcsICdCb29sZWFuJywgJ1N0cmluZycgb3IgJ0xpc3QnIHNob3VsZCBiZSBwcm92aWRlZC4KCiAgICAuUEFSQU1FVEVSIE5hbWUKICAgIE9wdGlvbiBuYW1lIGFzIGl0IGFwcGVhcnMgaW4gdGhlIGNvbW1hbmQgbGluZS4KCiAgICAuUEFSQU1FVEVSIFN3aXRjaAogICAgVXNlIHRoaXMgc3dpdGNoIHRvIGNyZWF0ZSB2YWx1ZWxlc3Mgb3B0aW9uIChhIHN3aXRjaCkuCgogICAgLlBBUkFNRVRFUiBCb29sZWFuCiAgICBVc2UgdGhpcyBzd2l0Y2ggdG8gY3JlYXRlIGJvb2xlYW4gb3B0aW9uLiBJdHMgdmFsdWUgaXMgYWx3YXlzIGNvbnZlcnRlZCB0byAiMSIgb3IgIjAiCgogICAgLlBBUkFNRVRFUiBTdHJpbmcKICAgIFVzZSB0aGlzIHN3aXRjaCB0byBjcmVhdGUgc3RyaW5nIG9wdGlvbi4gSXRzIHZhbHVlIHdpbGwgYmUgcHJvcGVybHkgcXVvdGVkIGlmIG5lY2Vzc2FyeS4KCiAgICAuUEFSQU1FVEVSIExpc3QKICAgIFVzZSB0aGlzIHN3aXRjaCB0byBjcmVhdGUgb3B0aW9uIHdpdGggbGlzdCB2YWx1ZS4gVmFsdWVzIHdpbGwgYmUgcHV0IGludG8gY29tbWFuZCBsaW5lIHVzaW5nIHZhbGlkIHZhbHVlIGRlbGVtaXRlciAoYSBjb21tYSkKCiAgICAuUEFSQU1FVEVSIENvbnN0cmFpbnRzCiAgICBXaGVuIHRoaXMgcGFyYW1ldGVyIGlzIHNwZWNpZmllZCwgb3B0aW9uIHZhbHVlcyBhcmUgbGltaXRlZCB0byBvcHRpb25zIGZyb20gdGhhdCBsaXN0LgoKICAgICM+CgogICAgJE9wdGlvbiA9IE5ldy1PYmplY3QgLVR5cGVOYW1lIFBTT2JqZWN0CgogICAgIyBGaWVsZHMKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIE5vdGVQcm9wZXJ0eSBUeXBlIC12YWx1ZSAkbnVsbAogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IE5hbWUgLXZhbHVlICRudWxsCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgQWxsb3dlZFZhbHVlcyAtdmFsdWUgJG51bGwKCiAgICAjIEluaXQKCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBTY3JpcHRNZXRob2QgX19pbml0X18gewogICAgICAgIHBhcmFtKFtzdHJpbmddJE5hbWUsICRTd2l0Y2gsICRCb29sZWFuLCAkU3RyaW5nLCAkTGlzdCkKCiAgICAgICAgJHRoaXMuTmFtZSA9ICROYW1lCiAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgIyBXaXRoIHJlc3BlY3QgZm9yIG91ciBkZXZlbG9wZXJzIHdlIGRvIG5vdCBjaGVjayBmb3IgZG91YmxlIHR5cGUgc2VsZWN0ZWQKICAgICAgICBpZiAoJFN3aXRjaCkgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uU3dpdGNoKCR0aGlzKQogICAgICAgIH0gZWxzZWlmICgkQm9vbGVhbikgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uQm9vbGVhbigkdGhpcykKICAgICAgICB9IGVsc2VpZiAoJFN0cmluZykgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uU3RyaW5nKCR0aGlzKQogICAgICAgIH0gZWxzZWlmICgkTGlzdCkgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uTGlzdCgkdGhpcykKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aHJvdyAiU3dpdGNoLCBCb29sZWFuLCBTdHJpbmcgb3IgTGlzdCBvcHRpb24gdHlwZSBtdXN0IGJlIHByb3ZpZGVkIGZvciBvcHRpb24gJyROYW1lJyIKICAgICAgICB9CiAgICB9CgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIF9fcG9zdF9pbml0X18gewogICAgICAgIHBhcmFtKCRDb25zdHJhaW50cz0kbnVsbCkKICAgICAgICBpZiAoJENvbnN0cmFpbnRzIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkdGhpcy5BbGxvd2VkVmFsdWVzID0gQCgpCiAgICAgICAgICAgICR0aGlzLkFsbG93ZWRWYWx1ZXMgPSAkdGhpcy5BbGxvd2VkVmFsdWVzICsgJENvbnN0cmFpbnRzCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgJENvbnN0cmFpbnRzID0gJG51bGwKICAgICAgICB9CiAgICB9CgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBWYWxpZGF0ZSB7CiAgICAgICAgaWYgKCR0aGlzLkFsbG93ZWRWYWx1ZXMgLW5lICRudWxsKSB7CiAgICAgICAgICAgIGlmICgtbm90KCR0aGlzLkFsbG93ZWRWYWx1ZXMgLWNvbnRhaW5zICR0aGlzLlZhbHVlKSkgewogICAgICAgICAgICAgICAgJEN0cyA9ICR0aGlzLkFsbG93ZWRWYWx1ZXMgLWpvaW4gJywnCiAgICAgICAgICAgICAgICB0aHJvdyAiT3B0aW9uICckKCR0aGlzLk5hbWUpJyBtYXkgaGF2ZSB2YWx1ZXMgKCRDdHMpIGJ1dCBub3QgJyQoJHRoaXMuVmFsdWUpJyIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciAtRm9yY2UgU2NyaXB0TWV0aG9kIFRvU3RyaW5nIHsKICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpIgogICAgfQoKICAgICMgaW52b2tlIGNvbnN0cnVjdG9yCgogICAgJE9wdGlvbi5fX2luaXRfXygkTmFtZSwgJFN3aXRjaCwgJEJvb2xlYW4sICRTdHJpbmcsICRMaXN0KQogICAgJE9wdGlvbi5fX3Bvc3RfaW5pdF9fKCRDb25zdHJhaW50cykKCiAgICByZXR1cm4gJE9wdGlvbgp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uU3dpdGNoKCRPcHRpb24pIHsKfQoKZnVuY3Rpb24gQXVnbWVudE9wdGlvbkJvb2xlYW4oJE9wdGlvbikgewogICAgIyBGaWVsZHMKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIE5vdGVQcm9wZXJ0eSBWYWx1ZSAtdmFsdWUgJGZhbHNlCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBUb1N0cmluZyB7CiAgICAgICAgaWYgKCR0aGlzLlZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9MSIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpPTAiCiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uU3RyaW5nKCRPcHRpb24pIHsKICAgICMgRmllbGRzCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgVmFsdWUgLXZhbHVlICIiCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBUb1N0cmluZyB7CiAgICAgICAgJHYgPSAiJCgkdGhpcy5WYWx1ZSkiCiAgICAgICAgaWYgKCR2IC1tYXRjaCAnLiogLionKSB7CiAgICAgICAgICAgICMgVE9ETzogRXNjYXBlIGRvdWJsZSBxdW90ZSBjaGFyYWN0ZXJzIGlmIHBvc3NpYmxlCiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9YCIkdmAiIgogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9JHYiCiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uTGlzdCgkT3B0aW9uKSB7CiAgICAjIEZpZWxkcwogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IFZhbHVlIC12YWx1ZSBAKCkKCiAgICAjIE1ldGhvZHMKCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciAtRm9yY2UgU2NyaXB0TWV0aG9kIFZhbGlkYXRlIHsKICAgICAgICBpZiAoJHRoaXMuQWxsb3dlZFZhbHVlcyAtbmUgJG51bGwpIHsKICAgICAgICAgICAgZm9yZWFjaCAoJFYgaW4gJHRoaXMuVmFsdWUpIHsKICAgICAgICAgICAgICAgIGlmICgtbm90KCR0aGlzLkFsbG93ZWRWYWx1ZXMgLWNvbnRhaW5zICRWKSkgewogICAgICAgICAgICAgICAgICAgICRDdHMgPSAkdGhpcy5BbGxvd2VkVmFsdWVzIC1qb2luICcsJwogICAgICAgICAgICAgICAgICAgIHRocm93ICJPcHRpb24gJyQoJHRoaXMuTmFtZSknIG1heSBoYXZlIHZhbHVlcyAoJEN0cykgYnV0IG5vdCAnJFYnIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIC1Gb3JjZSBTY3JpcHRNZXRob2QgVG9TdHJpbmcgewogICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9JCgkdGhpcy5WYWx1ZSAtam9pbiAnLCcpIgogICAgfQp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyKCkgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBPcHRpb25QYXJzZXIgb2JqZWN0LgoKICAgIC5ERVNDUklQVElPTgogICAgT3B0aW9uUGFyc2VyIG9iamVjdCBsZXZlcmFnZXMgT3B0aW9uIG9iamVjdHMgY2FwYWJpbGl0aWVzIGFuZCBidWlsZHMgdmFsaWQgY29tbWFuZCBsaW5lIHVzaW5nIHNwZWNpZmllZCBvcHRpb25zLgogICAgQW4gYXBwbGljYXRpb24gbWF5IGFsc28gYmUgaW52b2tlZCB3aXRoIE9wdGlvblBhcnNlci4KCiAgICAjPgoKICAgICRPcHRpb25QYXJzZXIgPSBOZXctT2JqZWN0IC1UeXBlTmFtZSBQU09iamVjdAoKICAgICMgRmllbGRzCiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgT3B0aW9ucyAtdmFsdWUgQHt9CiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgRGVmYXVsdHMgLXZhbHVlIEB7fQogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IFJlcXVpcmVkT3B0aW9ucyAtdmFsdWUgQCgpCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIEFkZE9wdGlvbiB7CiAgICAgICAgPCMKICAgICAgICAuU1lOT1BTSVMKICAgICAgICBBZGRzIHN1cHBvcnRlZCBvcHRpb24gaW50byBPcHRpb25QYXJzZXIuCiAgICAgICAgCiAgICAgICAgLkRFU0NSSVBUSU9OCiAgICAgICAgT3B0aW9uUGFyc2VyIGRvZXMgbm90IGFsbG93IHVzaW5nIHVucmVjb2duaXplZCBvcHRpb25zLiBVc2UgdGhpcyBtZXRob2QgdG8gZmlsbCBPcHRpb25QYXJzZXIgd2l0aCByZWNvZ25pemVkIG9wdGlvbnMKCiAgICAgICAgLlBBUkFNRVRFUiBPcHRpb24KICAgICAgICBPcHRpb24gb2JqZWN0CgogICAgICAgIC5QQVJBTUVURVIgUmVxdWlyZWQKICAgICAgICBSZXF1aXJlZCBvcHRpb24gc3dpdGNoCgogICAgICAgIC5QQVJBTUVURVIgRGVmYXVsdAogICAgICAgIE9wdGlvbiBkZWZhdWx0IHZhbHVlCiAgICAgICAgIz4KICAgICAgICBwYXJhbSgkT3B0aW9uLCBbYm9vbF0kUmVxdWlyZWQ9JGZhbHNlLCAkRGVmYXVsdD0kbnVsbCkKICAgICAgICAkdGhpcy5PcHRpb25zLkFkZCgkT3B0aW9uLk5hbWUsICRPcHRpb24pCiAgICAgICAgaWYgKCRSZXF1aXJlZCkgewogICAgICAgICAgICAkdGhpcy5SZXF1aXJlZE9wdGlvbnMgPSAkdGhpcy5SZXF1aXJlZE9wdGlvbnMgKyAkT3B0aW9uLk5hbWUKICAgICAgICAgICAgaWYgKCRPcHRpb24gfCBHZXQtTWVtYmVyICJWYWx1ZSIpIHsKICAgICAgICAgICAgICAgIGlmICgkRGVmYXVsdCkgewogICAgICAgICAgICAgICAgICAgICR0aGlzLkRlZmF1bHRzLkFkZCgkT3B0aW9uLk5hbWUsICREZWZhdWx0KQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgJHRoaXMuRGVmYXVsdHMuQWRkKCRPcHRpb24uTmFtZSwgJG51bGwpCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIFBhcnNlIHsKICAgICAgICA8IwogICAgICAgIC5TWU5PUFNJUwogICAgICAgIFBhcnNlcyBzdXBwbGllZCBvcHRpb25zIGFuZCByZXR1cm5zIGNvbW1hbmQgbGluZSBwYXJhbWV0ZXJzIGFycmF5LgogICAgICAgIAogICAgICAgIC5ERVNDUklQVElPTgogICAgICAgIFRoaXMgbWV0aG9kIHZlcmlmaWVzIHRoYXQgb25seSBzdXBwb3J0ZWQgb3B0aW9ucyBhcmUgcHJvdmlkZWQsIGFsbCBtYW5kYXRvcnkgb3B0aW9ucyBhcmUgaW4gcGxhY2UsIAogICAgICAgIGFsbCBvcHRpb24gbWVldCBjb25zdHJhaW50cyBpZiBhbnkuIFVuc3BlY2lmaWVkIG9wdGlvbnMgd2l0aCBkZWZhdWx0IHZhbHVlcyBhcmUgYWRkZWQgdG8gY29tbWFuZCBsaW5lLgogICAgICAgIFNvLCBtYW5kYXRvcnkgb3B0aW9uIHdpdGggZGVmYXVsdCB2YWx1ZSBuZXZlciBjYXVzZXMgZXhjZXB0aW9uLgoKICAgICAgICAuUEFSQU1FVEVSIE9wdGlvbnMKICAgICAgICBBIGhhc2ggbWFwIG9mIG9wdGlvbnMgdG8gcGFyc2UuIE9wdGlvbiBuYW1lcyBzaG91bGQgYmUgbWFwcGVkIHRvIGNvcnJlc3BvbmRpbmcgdmFsdWVzLgogICAgICAgICM+CiAgICAgICAgcGFyYW0oW2hhc2h0YWJsZV0kT3B0aW9ucykKCiAgICAgICAgJENvbW1hbmRMaW5lID0gQCgpCiAgICAgICAgZm9yZWFjaCAoJFJlcXVpcmVkT3B0aW9uTmFtZSBpbiAkdGhpcy5SZXF1aXJlZE9wdGlvbnMpIHsKICAgICAgICAgICAgaWYgKC1ub3QgJE9wdGlvbnMuQ29udGFpbnNLZXkoJFJlcXVpcmVkT3B0aW9uTmFtZSkpIHsKICAgICAgICAgICAgICAgICREZWZhdWx0ID0gJHRoaXMuRGVmYXVsdHMuR2V0X0l0ZW0oJFJlcXVpcmVkT3B0aW9uTmFtZSkKICAgICAgICAgICAgICAgIGlmICgkdGhpcy5EZWZhdWx0cy5Db250YWluc0tleSgkUmVxdWlyZWRPcHRpb25OYW1lKSkgewogICAgICAgICAgICAgICAgICAgICRPcHRpb25zLkFkZCgkUmVxdWlyZWRPcHRpb25OYW1lLCAkdGhpcy5EZWZhdWx0cy5HZXRfSXRlbSgkUmVxdWlyZWRPcHRpb25OYW1lKSkKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgIlJlcXVpcmVkIG9wdGlvbiAnJFJlcXVpcmVkT3B0aW9uTmFtZScgaXMgbWlzc2luZyIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZm9yZWFjaCAoJE9wdGlvbk5hbWUgaW4gJCgkT3B0aW9ucy5rZXlzKSkgewogICAgICAgICAgICAkT3B0aW9uID0gJHRoaXMuT3B0aW9ucy5HZXRfSXRlbSgkT3B0aW9uTmFtZSkKICAgICAgICAgICAgaWYgKCRPcHRpb24gLWVxICRudWxsKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAiT3B0aW9uICckT3B0aW9uTmFtZScgaXMgbm90IGFsbG93ZWQiCiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCRPcHRpb24gfCBHZXQtTWVtYmVyICJWYWx1ZSIpIHsKICAgICAgICAgICAgICAgICRPcHRpb24uVmFsdWUgPSAkT3B0aW9ucy5HZXRfSXRlbSgkT3B0aW9uTmFtZSkKICAgICAgICAgICAgfQogICAgICAgICAgICAkT3B0aW9uLlZhbGlkYXRlKCkKICAgICAgICAgICAgJENvbW1hbmRMaW5lID0gJENvbW1hbmRMaW5lICsgJE9wdGlvbi5Ub1N0cmluZygpCiAgICAgICAgfQogICAgICAgIHJldHVybiAkQ29tbWFuZExpbmUKICAgIH0KCiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBTY3JpcHRNZXRob2QgRXhlY3V0ZUJpbmFyeSB7CiAgICAgICAgcGFyYW0oJEJpbmFyeSwgW2hhc2h0YWJsZV0kT3B0aW9ucyA9IEB7fSwgJENvbW1hbmRMaW5lU3VmZml4ID0gQCgpKQogICAgICAgIDwjCiAgICAgICAgLlNZTk9QU0lTCiAgICAgICAgRXhlY3V0ZXMgYmluYXJ5IHdpdGggYSBjb21tYW5kIGxpbmUgY29uc3RydWN0ZWQgZnJvbSBwcm92aWRlZCBvcHRpb25zLiBBbiBhcmJpdHJhcnkgc3VmZml4IG1heSBiZSAKICAgICAgICBhcHBlbmRlZCB0byB0aGUgY29tbWFuZCBsaW5lLgogICAgICAgIAogICAgICAgIC5ERVNDUklQVElPTgogICAgICAgIFRoaXMgbWV0aG9kIHVzZXMgT3B0aW9uUGFyc2VyLlBhcnNlIG1ldGhvZCB0byBjb25zdHJ1Y3QgY29tbWFuZCBsaW5lLiBJZiB0aGVyZSBhIGNvbW1hbmQgbGluZSBzdWZmaXggCiAgICAgICAgd2FzIHN1cHBsaWVkLCBpdCBpcyBhcHBlbmRlZCB0byB0aGUgZW5kIG9mIGNvbW1hbmQgbGluZS4gTm9ybWFsbHkgY29tbWFuZCBsaW5lIHN1ZmZpeCBzaG91bGQgY29udGFpbgogICAgICAgIGxlYWRpbmcgc3BhY2UgY2hhcmFjdGVyLgoKICAgICAgICBNZXRob2Qgd2FpdHMgZm9yIGV4ZWN1dGFibGUgcHJvY2VzcyB0byBjb21wbGV0ZSBhbmQgcmV0dXJucyBpdHMgZXhpdCBjb2RlLgoKICAgICAgICAuUEFSQU1FVEVSIEJpbmFyeQogICAgICAgIEZ1bGwgb3IgcmVsYXRpdmUgcGF0aCB0byB0aGUgZXhlY3V0YWJsZSB0byBydW4uCgogICAgICAgIC5QQVJBTUVURVIgT3B0aW9ucwogICAgICAgIEEgaGFzaCBtYXAgb2Ygb3B0aW9ucyB0byBwYXNzIHRvIHRoZSBleGVjdXRhYmxlLgoKICAgICAgICAuUEFSQU1FVEVSIENvbW1hbmRMaW5lU3VmZml4CiAgICAgICAgQXJiaXRyYXJ5IGNvbW1hbmQgbGluZSBzdWZmaXguIE5vcm1hbGx5IGl0IHNob3VkIGhhdmUgbGVhZGluZyBzcGFjZSBjaGFyYWN0ZXIuCiAgICAgICAgIz4KCiAgICAgICAgJEJpbmFyeSA9IEdldC1JdGVtICRCaW5hcnkKICAgICAgICAkQ29tbWFuZExpbmUgPSAkdGhpcy5QYXJzZSgkT3B0aW9ucykKICAgICAgICBpZiAoJENvbW1hbmRMaW5lU3VmZml4KSB7CiAgICAgICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICRDb21tYW5kTGluZVN1ZmZpeAogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJFeGVjdXRpbmc6ICQoJEJpbmFyeS5GdWxsTmFtZSkgJCgkQ29tbWFuZExpbmUgLWpvaW4gJyAnKSIKICAgICAgICAkcHJvY2VzcyA9IFtTeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2Vzc106OlN0YXJ0KCRCaW5hcnksICRDb21tYW5kTGluZSkKICAgICAgICAkcHJvY2Vzcy5XYWl0Rm9yRXhpdCgpCiAgICAgICAgJHByb2Nlc3MuUmVmcmVzaCgpCiAgICAgICAgcmV0dXJuICRwcm9jZXNzLkV4aXRDb2RlCiAgICB9CgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQo=", - "ZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckluc3RhbGwgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBhbiBvcHRpb24gcGFyc2VyIGZvciBNUyBTUUwgU2VydmVyIDIwMTIgc2V0dXAgIklOU1RBTEwiIGFjdGlvbi4KCiAgICAuREVTQ1JJUFRJT04KICAgIFVzZSB0aGlzIGNtZGxldCB0byBjcmVhdGUgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJJTlNUQUxMIiBhY3Rpb24uCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkSXNQYXJ0T2ZEb21haW4gPSAoR2V0LVdtaU9iamVjdCBXaW4zMl9Db21wdXRlclN5c3RlbSkuUGFydE9mRG9tYWluCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIklOU1RBTEwiKSwgJHRydWUsICJJTlNUQUxMIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJQUNDRVBUU1FMU0VSVkVSTElDRU5TRVRFUk1TIiAtU3dpdGNoKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5VIiAtU3dpdGNoKSkKICAgICMkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlVwZGF0ZVNvdXJjZSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVSUk9SUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTCIsIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJEUSIsIkFTIiwiUlMiLCJEUUMiLCJJUyIsIk1EUyIsIlRvb2xzIiwiQkMiLCJCT0wiLCJCSURTIiwiQ29ubiIsIlNTTVMiLCJBRFZfU1NNUyIsIkRSRVBMQVlfQ1RMUiIsIkRSRVBMQVlfQ0xUIiwiU05BQ19TREsiLCJTREsiLCJMb2NhbERCIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJPTEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiU1BJX0FTX0V4aXN0aW5nRmFybSIsICJTUElfQVNfTmV3RmFybSIsICJBbGxGZWF0dXJlc19XaXRoRGVmYXVsdHMiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRFdPV0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlBJRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlVJTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJOb3JtYWwiLCAiQXV0b0FkdmFuY2UiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FNUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTQkFDS1VQRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU0NPTExBVElPTiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQVNDT05GSUdESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTREFUQURJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQVNMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU0VSVkVSTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNVUxUSURJTUVOU0lPTkFMIiwgIlBPV0VSUElWT1QiLCAiVEFCVUxBUiIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKCiAgICAjJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXCRFTlY6VVNFUk5BTUUiKQogICAgaWYgKCRJc1BhcnRPZkRvbWFpbikgewogICAgICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFbnY6VVNFUkRPTUFJTlxBZG1pbmlzdHJhdG9yIikKICAgIH0KICAgIGVsc2UgewogICAgICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFbnY6Q09NUFVURVJOQU1FXEFkbWluaXN0cmF0b3IiKQogICAgfQoKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1RFTVBESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTUFJPVklERVJNU09MQVAiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGQVJNQUNDT1VOVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkFSTVBBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJQQVNTUEhSQVNFIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGQVJNQURNSU5JUE9SVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQlJPV1NFUlNWQ1NUQVJUVVBUWVBFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5BQkxFUkFOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNRTERBVEFESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNBUFdEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTRUNVUklUWU1PREUiIC1TdHJpbmcgLUNvbnN0cmFpbnJzICgiU1FMIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTEJBQ0tVUERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMQ09MTEFUSU9OIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBRERDVVJSRU5UVVNFUkFTU1FMQURNSU4iIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgCiAgICAjJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6VVNFUkRPTUFJTlwkRU5WOlVTRVJOQU1FIikKICAgIGlmICgkSXNQYXJ0T2ZEb21haW4pIHsKICAgICAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXEFkbWluaXN0cmF0b3IiKQogICAgfQogICAgZWxzZSB7CiAgICAgICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6Q09NUFVURVJOQU1FXEFkbWluaXN0cmF0b3IiKQogICAgfQogICAgCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVEVNUERCRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxURU1QREJMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFVTRVJEQkRJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVVNFUkRCTE9HRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGSUxFU1RSRUFNTEVWRUwiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiMCIsICIxIiwgIjIiLCAiMyIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGSUxFU1RSRUFNU0hBUkVOQU1FIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGVFNWQ0FDQ09VTlQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZUU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklTU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSVNTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSVNTVkNTdGFydHVwVHlwZSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIk5QRU5BQkxFRCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlRDUEVOQUJMRUQiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU0lOU1RBTExNT0RFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIlNoYXJlUG9pbnRGaWxlc09ubHlNb2RlIiwgIkRlZmF1bHROYXRpdmVNb2RlIiwgIkZpbGVzT25seU1vZGUiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNBQ0NPVU5UIiAtU3RyaW5nKSwgJHRydWUsICJOVCBBVVRIT1JJVFlcTmV0d29yayBTZXJ2aWNlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ1N0YXJ0dXBUeXBlIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclByZXBhcmVJbWFnZSB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgTm90ZSB0aGF0IGZvciBpbnN0YWxsZXIgdmVyc2lvbiBvZiBNUyBTUUwgU2VydmVyIHByaW9yIHRvIDIwMTIgU1AxIEN1bXVsYXRpdmUgVXBkYXRlIDIgb25seSB0aGUKICAgIGZvbGxvd2luZyBmZWF0dXJlcyBhcmUgc3VwcG9ydGVkOiBTUUxFbmdpbmUsIFJlcGxpY2F0aW9uLCBGdWxsVGV4dCwgUlMKCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUNUSU9OIiAtU3RyaW5nIC1Db25zdHJhaW50cyAiUHJlcGFyZUltYWdlIiksICR0cnVlLCAiUHJlcGFyZUltYWdlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJQUNDRVBUU1FMU0VSVkVSTElDRU5TRVRFUk1TIiAtU3dpdGNoKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5VIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJVcGRhdGVFbmFibGVkIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJVcGRhdGVTb3VyY2UiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkNPTkZJR1VSQVRJT05GSUxFIiAtU3RyaW5nKSkKIyAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJSUyIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGRUFUVVJFUyIgLUxpc3QgLUNvbnN0cmFpbnRzICgiU1FMIiwiU1FMRW5naW5lIiwiUmVwbGljYXRpb24iLCJGdWxsVGV4dCIsIkRRIiwiQVMiLCJSUyIsIkRRQyIsIklTIiwiTURTIiwiVG9vbHMiLCJCQyIsIkJPTCIsIkJJRFMiLCJDb25uIiwiU1NNUyIsIkFEVl9TU01TIiwiRFJFUExBWV9DVExSIiwiRFJFUExBWV9DTFQiLCJTTkFDX1NESyIsIlNESyIsIkxvY2FsREIiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklORElDQVRFUFJPR1JFU1MiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTExTSEFSRURESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJTlNUQU5DRUlEIiAtU3RyaW5nKSwgJHRydWUsICJNU1NRTFNFUlZFUiIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJQcmVwYXJlSW1hZ2VTUDFVMiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgVGhpcyBjbWRsZXQgc2hvdWxkIGJlIHVzZWQgb25seSBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIFNQMSBDaW1pbGF0aXZlIFVwZGF0ZSAyIG9yIGxhdGVyLgoKICAgIE5vdGUgdGhhdCBmb3IgaW5zdGFsbGVyIHZlcnNpb24gb2YgTVMgU1FMIFNlcnZlciBwcmlvciB0byAyMDEyIFNQMSBDaW1pbGF0aXZlIFVwZGF0ZSAyIG9ubHkgdGhlCiAgICBmb2xsb3dpbmcgZmVhdHVyZXMgYXJlIHN1cHBvcnRlZDogU1FMRW5naW5lLCBSZXBsaWNhdGlvbiwgRnVsbFRleHQsIFJTCgogICAgQWxsIGRvY3VtZW50ZWQgb3B0aW9uIGFyZSBzdXBwb3J0ZWQuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yIGRldGFpbHM6CiAgICBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAogICAgIz4KICAgICRPcHRpb25QYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VyCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIlByZXBhcmVJbWFnZSIpLCAkdHJ1ZSwgIlByZXBhcmVJbWFnZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSUFDQ0VQVFNRTFNFUlZFUkxJQ0VOU0VURVJNUyIgLVN3aXRjaCksICR0cnVlKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlU291cmNlIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJDT05GSUdVUkFUSU9ORklMRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTCIsIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJEUSIsIkFTIiwiUlMiLCJEUUMiLCJJUyIsIk1EUyIsIlRvb2xzIiwiQkMiLCJCT0wiLCJCSURTIiwiQ29ubiIsIlNTTVMiLCJBRFZfU1NNUyIsIlNOQUNfU0RLIiwiU0RLIiwiTG9jYWxEQiIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJISURFQ09OU09MRSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk1TU1FMU0VSVkVSIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRUyIgLVN3aXRjaCkpCgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckNvbXBsZXRlSW1hZ2UgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBhbiBvcHRpb24gcGFyc2VyIGZvciBNUyBTUUwgU2VydmVyIDIwMTIgc2V0dXAgIkNvbXBsZXRlSW1hZ2UiIGFjdGlvbi4KCiAgICAuREVTQ1JJUFRJT04KICAgIFVzZSB0aGlzIGNtZGxldCB0byBjcmVhdGUgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJDb21wbGV0ZUltYWdlIiBhY3Rpb24uCgogICAgTm90ZSB0aGF0IElOU1RBTkNFSUQgcGFyYW1ldGVyIHZhbHVlIE1VU1QgYmUgdGhlIHNhbWUgYXMgc3BlY2lmaWVkIG9uICJQcmVwYXJlSW1hZ2UiIHBoYXNlLgoKICAgIEFsbCBkb2N1bWVudGVkIG9wdGlvbiBhcmUgc3VwcG9ydGVkLiBTZWUgdGhlIGZvbGxvd2luZyBsaW5rIGZvciBkZXRhaWxzOgogICAgaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTQ0MjU5LmFzcHgKICAgICM+CiAgICAkT3B0aW9uUGFyc2VyID0gTmV3LU9wdGlvblBhcnNlcgoKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBQ1RJT04iIC1TdHJpbmcgLUNvbnN0cmFpbnRzICJDb21wbGV0ZUltYWdlIiksICR0cnVlLCAiQ29tcGxldGVJbWFnZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSUFDQ0VQVFNRTFNFUlZFUkxJQ0VOU0VURVJNUyIgLVN3aXRjaCksICR0cnVlKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVSUk9SUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VJRCIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlBJRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTVJFUE9SVElORyIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkhJREVDT05TT0xFIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNBQ0NPVU5UIiAtU3RyaW5nKSwgJHRydWUsICJOVCBBVVRIT1JJVFlcTmV0d29yayBTZXJ2aWNlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUdUU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJCUk9XU0VSU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFTkFCTEVSQU5VIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJTlNUQUxMU1FMREFUQURJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU0FQV0QiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNFQ1VSSVRZTU9ERSIgLVN0cmluZyAtQ29uc3RyYWlucnMgKCJTUUwiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMQkFDS1VQRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxDT0xMQVRJT04iIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6VVNFUkRPTUFJTlwkRU5WOlVTRVJOQU1FIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxURU1QREJESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFRFTVBEQkxPR0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVVNFUkRCRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxVU0VSREJMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZJTEVTVFJFQU1MRVZFTCIgLVN0cmluZyAtQ29uc3RyYWludHMgKCIwIiwgIjEiLCAiMiIsICIzIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZJTEVTVFJFQU1TSEFSRU5BTUUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZUU1ZDQUNDT1VOVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRlRTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiTlBFTkFCTEVEIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVENQRU5BQkxFRCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTSU5TVEFMTE1PREUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiU2hhcmVQb2ludEZpbGVzT25seU1vZGUiLCAiRGVmYXVsdE5hdGl2ZU1vZGUiLCAiRmlsZXNPbmx5TW9kZSIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDU3RhcnR1cFR5cGUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKCiAgICByZXR1cm4gJE9wdGlvblBhcnNlcgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyQ29tcGxldGVJbWFnZVNQMVUyIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJDb21wbGV0ZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiQ29tcGxldGVJbWFnZSIgYWN0aW9uLgoKICAgIFRoaXMgY21kbGV0IHNob3VsZCBiZSB1c2VkIG9ubHkgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBTUDEgQ2ltaWxhdGl2ZSBVcGRhdGUgMiBvciBsYXRlci4KCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUNUSU9OIiAtU3RyaW5nIC1Db25zdHJhaW50cyAiQ29tcGxldGVJbWFnZSIpLCAkdHJ1ZSwgIkNvbXBsZXRlSW1hZ2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklBQ0NFUFRTUUxTRVJWRVJMSUNFTlNFVEVSTVMiIC1Td2l0Y2gpLCAkdHJ1ZSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFTlUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkNPTkZJR1VSQVRJT05GSUxFIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFUlJPUlJFUE9SVElORyIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklORElDQVRFUFJPR1JFU1MiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUElEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FNUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkJST1dTRVJTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOQUJMRVJBTlUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTExTUUxEQVRBRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTQVBXRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU0VDVVJJVFlNT0RFIiAtU3RyaW5nIC1Db25zdHJhaW5ycyAoIlNRTCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxCQUNLVVBESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTENPTExBVElPTiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1NUQVJUVVBUWVBFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXCRFTlY6VVNFUk5BTUUiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFRFTVBEQkRJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVEVNUERCTE9HRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxVU0VSREJESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFVTRVJEQkxPR0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRklMRVNUUkVBTUxFVkVMIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIjAiLCAiMSIsICIyIiwgIjMiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRklMRVNUUkVBTVNIQVJFTkFNRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRlRTVkNBQ0NPVU5UIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJOUEVOQUJMRUQiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJUQ1BFTkFCTEVEIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNJTlNUQUxMTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJTaGFyZVBvaW50RmlsZXNPbmx5TW9kZSIsICJEZWZhdWx0TmF0aXZlTW9kZSIsICJGaWxlc09ubHlNb2RlIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNTdGFydHVwVHlwZSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJVcGdyYWRlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckVkaXRpb25VcGdyYWRlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclJlcGFpciB7CiAgICAjIFRvRG86IEltcGxlbWVudAogICAgdGhyb3cgIk5vdCB5ZXQgaW1wbGVtZW50ZWQiCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJSZWJ1aWxkZGF0YWJhc2UgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyVW5pbnN0YWxsIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJJTlNUQUxMIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiSU5TVEFMTCIgYWN0aW9uLgogICAgQWxsIGRvY3VtZW50ZWQgb3B0aW9uIGFyZSBzdXBwb3J0ZWQuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yIGRldGFpbHM6CiAgICBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAogICAgIz4KICAgICRPcHRpb25QYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VyCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIlVOSU5TVEFMTCIpLCAkdHJ1ZSwgIlVOSU5TVEFMTCIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZFQVRVUkVTIiAtTGlzdCAtQ29uc3RyYWludHMgKCJTUUwiLCJTUUxFbmdpbmUiLCJSZXBsaWNhdGlvbiIsIkZ1bGxUZXh0IiwiRFEiLCJBUyIsIlJTIiwiRFFDIiwiSVMiLCJNRFMiLCJUb29scyIsIkJDIiwiQk9MIiwiQklEUyIsIkNvbm4iLCJTU01TIiwiQURWX1NTTVMiLCJEUkVQTEFZX0NUTFIiLCJEUkVQTEFZX0NMVCIsIlNOQUNfU0RLIiwiU0RLIiwiTG9jYWxEQiIpKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VOQU1FIiAtU3RyaW5nKSwgJHRydWUsICJNU1NRTFNFUlZFUiIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJJbnN0YWxsRmFpbG92ZXJDbHVzdGVyIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclByZXBhcmVGYWlsb3ZlckNsdXN0ZXIgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyQ29tcGxldGVGYWlsb3ZlckNsdXN0ZXIgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyVXBncmFkZSB7CiAgICAjIFRvRG86IEltcGxlbWVudAogICAgdGhyb3cgIk5vdCB5ZXQgaW1wbGVtZW50ZWQiCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJBZGROb2RlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclJlbW92ZU5vZGUgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9Cg==", - "SW1wb3J0LU1vZHVsZSBOZXRTZWN1cml0eQoKZnVuY3Rpb24gVGVzdC1LZXkoW3N0cmluZ10kcGF0aCwgW3N0cmluZ10ka2V5KSB7CiAgICBpZighKFRlc3QtUGF0aCAkcGF0aCkpIHsgcmV0dXJuICRmYWxzZSB9CiAgICBpZiAoKEdldC1JdGVtUHJvcGVydHkgJHBhdGgpLiRrZXkgLWVxICRudWxsKSB7IHJldHVybiAkZmFsc2UgfQogICAgcmV0dXJuICR0cnVlCn0KCmZ1bmN0aW9uIFJlc29sdmUtU1FMU2VydmVyUHJlcmVxdWlzaXRlcyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBNUyBTUUwgU2VydmVyIHByZXJlcXVpc2l0ZXMgKC5OZXQgRnJhbWV3b3JrIDMuNSkKCiAgICAuREVTQ1JJUFRJT04KICAgIEluc3RhbGxzIE1TIFNRTCBTZXJ2ZXIgcHJlcmVxdWlzaXRlcyAoLk5ldCBGcmFtZXdvcmsgMy41KQoKICAgICM+CiAgICBpZiAoLW5vdCAoVGVzdC1LZXkgIkhLTE06XFNvZnR3YXJlXE1pY3Jvc29mdFxORVQgRnJhbWV3b3JrIFNldHVwXE5EUFx2My41IiAiSW5zdGFsbCIpKSB7CiAgICAgICAgSW1wb3J0LU1vZHVsZSBTZXJ2ZXJNYW5hZ2VyCiAgICAgICAgV3JpdGUtSG9zdCAiLk5ldCBGcmFtZXdvcmsgMy41IG5vdCBmb3VuZC4gSW5zdGFsbGluZyBpdCB1c2luZyBTZXJ2ZXIgTWFuYWdlci4uLiIKICAgICAgICAkRmVhdHVyZSA9IEdldC1XaW5kb3dzRmVhdHVyZSBORVQtRnJhbWV3b3JrCiAgICAgICAgaWYgKCRGZWF0dXJlIC1lcSAkbnVsbCkgewogICAgICAgICAgICAjIFdlIGFyZSBwcm9iYWJseSBvbiBXaW5kb3dzIFNlcnZlciAyMDEyCiAgICAgICAgICAgICRGZWF0dXJlID0gR2V0LVdpbmRvd3NGZWF0dXJlIE5FVC1GcmFtZXdvcmstQ29yZQogICAgICAgIH0KICAgICAgICBpZiAoLW5vdCAkRmVhdHVyZSkgewogICAgICAgICAgICB0aHJvdyAiLk5ldCBmcmFtZXdvcmsgMy41IGZlYXR1cmUgd2FzIG5vdCBmb3VuZC4iCiAgICAgICAgfQogICAgICAgIGlmICgtbm90ICRGZWF0dXJlLkRpc3BsYXlOYW1lIC1tYXRjaCAiMy41IikgewogICAgICAgICAgICBMb2ctV2FybmluZyAiLk5ldCBmcmFtZXdvcmsgMy41IGlzIHJlcXVpcmVkLCBidXQgJCgkRmVhdHVyZS5EaXNwbGF5TmFtZSkgaXMgYXZhaWxhYmxlIGFzIFdpbmRvd3MgZmVhdHVyZS4gUHJvY2VlZGluZyB3aXRoIGluc3RhbGxhdGlvbiIKICAgICAgICB9CiAgICAgICAgW3ZvaWRdKEFkZC1XaW5kb3dzRmVhdHVyZSAkRmVhdHVyZSkKICAgIH0KfQoKZnVuY3Rpb24gTmV3LVNRTFNlcnZlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZS4gUmV0dXJucyAkdHJ1ZSBpZiBhIHJlYm9vdCBpcyByZXF1aXJlZCBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLCAKICAgICRmYWxzZSBpZiBhIHJlYm9vdCBpcyBub3QgcmVxdWlyZWQgYW5kIHRocm93cyBhbiBleGNlcHRpb24gaW4gY2FzZSBpZiBpbnN0YWxsYXRpb24gZmFpbHMuCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSBpbiB1bmF0dGVuZGVkIG1vZGUuCgogICAgLlBBUkFNRVRFUiBTZXR1cFJvb3QKICAgIE1TIFNRTCBTZXJ2ZXIgaW5zdGFsbGF0aW9uIGZpbGVzIHJvb3QgZGlyZWN0b3J5LiBOb3JtYWxseSBpdCBpcyBqdXN0IERWRCBkcml2ZSBuYW1lLgoKICAgIC5QQVJBTUVURVIgRXh0cmFGZWF0dXJlcwogICAgTGlzdCBvZiBmZWF0dXJlcyB0byBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gZGVmYXVsdCAiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCksCiAgICAgICAgW0hhc2h0YWJsZV0kRXh0cmFPcHRpb25zID0gQHt9CiAgICApCgogICAgJFNldHVwRGlyID0gR2V0LUl0ZW0gJFNldHVwUm9vdAogICAgJFNldHVwRXhlID0gJFNldHVwRGlyLkdldEZpbGVzKCJzZXR1cC5leGUiKVswXQoKICAgIFJlc29sdmUtU1FMU2VydmVyUHJlcmVxdWlzaXRlcwoKICAgICRwYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VySW5zdGFsbAogICAgJEV4aXRDb2RlID0gJHBhcnNlci5FeGVjdXRlQmluYXJ5KCRTZXR1cEV4ZS5GdWxsTmFtZSwgQHsiUSIgPSAkbnVsbDsgIkZFQVRVUkVTIiA9IEAoIlNRTEVuZ2luZSIsICJDb25uIiwgIlNTTVMiLCAiQURWX1NTTVMiKSArICRFeHRyYUZlYXR1cmVzfSArICRFeHRyYU9wdGlvbnMpCgogICAgaWYgKCRFeGl0Q29kZSAtZXEgMzAxMCkgewogICAgICAgIHJldHVybiAkdHJ1ZQogICAgfQoKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICB0aHJvdyAiSW5zdGFsbGF0aW9uIGV4ZWN1dGFibGUgZXhpdGVkIHdpdGggY29kZSAkKCJ7MDpYOH0iIC1mICRFeGl0Q29kZSkgKERlY2ltYWw6ICRFeGl0Q29kZSkiCiAgICB9CgogICAgcmV0dXJuICRmYWxzZQp9CgpmdW5jdGlvbiBOZXctU1FMU2VydmVyRm9yQU9BRyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSB3aXRoIGFsbCBuZWVkZWQgZmVhdHVyZXMgdG8gc2V0IHVwIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cC4KICAgIFJldHVybnMgJHRydWUgaWYgYSByZWJvb3QgaXMgcmVxdWlyZWQgYWZ0ZXIgdGhlIGluc3RhbGxhdGlvbiwgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCAKICAgIGFuZCB0aHJvd3MgYW4gZXhjZXB0aW9uIGluIGNhc2UgaWYgaW5zdGFsbGF0aW9uIGZhaWxzLgoKICAgIC5ERVNDUklQVElPTgogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW5zdGFuY2UgaW4gdW5hdHRlbmRlZCBtb2RlLiBBbGwgZmVhdHVyZXMgZm9yIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cHMgYXJlCiAgICBpbnN0YWxsZWQuCgogICAgQWxsIGF2YWlsYWJpbGl0eSBncm91cCBtZW1iZXJzIG11c3QgYmUgaW5zdGFsbGVkIHdpdGggdGhlIHNhbWUgU1FMU3ZjVXNyRG9tYW4sIFNRTFN2Y1Vzck5hbWUgYW5kIFNRTFN2Y1VzclBhc3N3b3JkIHBhcmFtZXRlcnMuCiAgICBVc2VyIG11c3QgYmUgYSBkb21haW4gdXNlciBzaW5jZSBpdCB3aWxsIGJlIHVzZWQgZm9yIG5vZGVzIGludGVyY29ubmVjdGlvbi4KCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBTUUxTdmNVc3JEb21haW4KICAgIE1TIFNRTCBTZXJ2ZXIgdXNlciBhY2NvdW50IGRvbWFpbiBuYW1lLgoKICAgIC5QQVJBTUVURVIgU1FMU3ZjVXNyTmFtZQogICAgTVMgU1FMIFNlcnZlciB1c2VyIGFjY291bnQgbmFtZS4KCiAgICAuUEFSQU1FVEVSIFNRTFN2Y1VzclBhc3N3b3JkCiAgICBNUyBTUUwgU2VydmVyIHVzZXIgYWNjb3VudCBwYXNzd29yZC4KCiAgICAuUEFSQU1FVEVSIEV4dHJhRmVhdHVyZXMKICAgIExpc3Qgb2YgZmVhdHVyZXMgdG8gYmUgcmVtb3ZlZCBiZXNpZGVzICJTUUxFbmdpbmUiLCAiQ29ubiIsICJTU01TIiwgIkFEVl9TU01TIiwgIkRSRVBMQVlfQ1RMUiIsICJEUkVQTEFZX0NMVCIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTUUxTdmNVc3JEb21haW4sCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kU1FMU3ZjVXNyTmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTUUxTdmNVc3JQYXNzd29yZCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCksCiAgICAgICAgW0hhc2h0YWJsZV0kRXh0cmFPcHRpb25zID0gQHt9CiAgICApCgogICAgJFNldHVwRGlyID0gR2V0LUl0ZW0gJFNldHVwUm9vdAogICAgJFNldHVwRXhlID0gJFNldHVwRGlyLkdldEZpbGVzKCJzZXR1cC5leGUiKVswXQoKICAgICRTUUxVc2VyID0gIiRTUUxTdmNVc3JEb21haW5cJFNRTFN2Y1Vzck5hbWUiCiAgICAkZG9tYWluID0gTmV3LU9iamVjdCBTeXN0ZW0uRGlyZWN0b3J5U2VydmljZXMuRGlyZWN0b3J5RW50cnkoIkxEQVA6Ly8kU1FMU3ZjVXNyRG9tYWluIiwgJFNRTFN2Y1Vzck5hbWUsICRTUUxTdmNVc3JQYXNzd29yZCkKCiAgICBpZiAoJGRvbWFpbi5uYW1lIC1lcSAkbnVsbCkgewogICAgICAgIHRocm93ICJDcmVkZW50aWFscyB2YWxpZGF0aW9uIGZhaWxlZCBmb3IgdXNlciAkU1FMVXNlci4gQ2hlY2sgZG9tYWluLCBsb2dpbiBuYW1lIGFuZCBwYXNzd29yZC4iCiAgICB9CgogICAgUmVzb2x2ZS1TUUxTZXJ2ZXJQcmVyZXF1aXNpdGVzCgogICAgJHBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXJJbnN0YWxsCiAgICAkRXhpdENvZGUgPSAkcGFyc2VyLkV4ZWN1dGVCaW5hcnkoJFNldHVwRXhlLkZ1bGxOYW1lLCBAeyJRIiA9ICRudWxsOyAiRkVBVFVSRVMiID0gQCgiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIsICJEUkVQTEFZX0NUTFIiLCAiRFJFUExBWV9DTFQiKSArICRFeHRyYUZlYXR1cmVzOwogICAgICAgICJBR1RTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiQUdUU1ZDUEFTU1dPUkQiID0gJFNRTFN2Y1VzclBhc3N3b3JkOyAiQVNTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiQVNTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7ICJBU1NZU0FETUlOQUNDT1VOVFMiID0gJFNRTFVTZXI7CiAgICAgICAgIlNRTFNWQ0FDQ09VTlQiID0gJFNRTFVzZXI7ICJTUUxTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7ICJTUUxTWVNBRE1JTkFDQ09VTlRTIiA9ICRTUUxVc2VyOyAiSVNTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiSVNTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7IAogICAgICAgICJSU1NWQ0FDQ09VTlQiID0gJFNRTFVzZXI7ICJSU1NWQ1BBU1NXT1JEIiA9ICRTUUxTdmNVc3JQYXNzd29yZH0gKyAkRXh0cmFPcHRpb25zKQoKICAgIGlmICgkRXhpdENvZGUgLWVxIDMwMTApIHsKICAgICAgICByZXR1cm4gJHRydWUKICAgIH0KCiAgICBpZiAoJEV4aXRDb2RlIC1uZSAwKSB7CiAgICAgICAgdGhyb3cgIkluc3RhbGxhdGlvbiBleGVjdXRhYmxlIGV4aXRlZCB3aXRoIGNvZGUgJCgiezA6WDh9IiAtZiAkRXhpdENvZGUpIChEZWNpbWFsOiAkRXhpdENvZGUpIgogICAgfQoKICAgIHJldHVybiAkZmFsc2UKfQoKZnVuY3Rpb24gUmVtb3ZlLVNRTFNlcnZlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBVbmluc3RhbGxzIE1TIFNRTCBTZXJ2ZXIgaW5zdGFuY2UgaW5zdGFsbGVkIHdpdGggTmV3LVNRTFNlcnZlciBjbWRsZXQKCiAgICAuREVTQ1JJUFRJT04KICAgIFVuaW5zdGFsbHMgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSBpbnN0YWxsZWQgd2l0aCBOZXctU1FMU2VydmVyIGNtZGxldCBpbiB1bmF0dGVuZGVkIG1vZGUKCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBFeHRyYUZlYXR1cmVzCiAgICBMaXN0IG9mIGZlYXR1cmVzIHRvIGJlIHJlbW92ZWQgYmVzaWRlcyAiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCkKICAgICkKCiAgICAkU2V0dXBEaXIgPSBHZXQtSXRlbSAkU2V0dXBSb290CiAgICAkU2V0dXBFeGUgPSAkU2V0dXBEaXIuR2V0RmlsZXMoInNldHVwLmV4ZSIpWzBdCgogICAgJHBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXJVbmluc3RhbGwKICAgICRFeGl0Q29kZSA9ICRwYXJzZXIuRXhlY3V0ZUJpbmFyeSgkU2V0dXBFeGUuRnVsbE5hbWUsIEB7IlEiID0gJG51bGw7ICJGRUFUVVJFUyIgPSBAKCJTUUxFbmdpbmUiLCAiQ29ubiIsICJTU01TIiwgIkFEVl9TU01TIikgKyAkRXh0cmFGZWF0dXJlc30pCgogICAgaWYgKCRFeGl0Q29kZSAtbmUgMCkgewogICAgICAgIHRocm93ICJJbnN0YWxsYXRpb24gZXhlY3V0YWJsZSBleGl0ZWQgd2l0aCBjb2RlICQoInswOlg4fSIgLWYgJEV4aXRDb2RlKSIKICAgIH0KfQoKZnVuY3Rpb24gSW5zdGFsbC1TUUxTZXJ2ZXJGb3JTeXNQcmVwIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluIHN5c3ByZXAgbW9kZS4KCiAgICAuREVTQ1JJUFRJT04KICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluIHN5c3ByZXAgbW9kZS4gUmV0dXJucyAkdHJ1ZSBpZiBhIHJlYm9vdCBpcyByZXF1aXJlZCBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLCAKICAgICRmYWxzZSBpZiBhIHJlYm9vdCBpcyBub3QgcmVxdWlyZWQgYW5kIHRocm93cyBhbiBleGNlcHRpb24gaW4gY2FzZSBpZiBpbnN0YWxsYXRpb24gZmFpbHMuCgogICAgU2V0dXAgbXVzdCBiZSBjb21wbGV0ZWQgYWZ0ZXIgYm9vdGluZyByZWFybWVkIG1hY2hpbmUgYnkgdXNpbmcgQ29tcGxldGUtU1FMU2VydmVyIGNtZGxldAoKICAgIC5QQVJBTUVURVIgU2V0dXBSb290CiAgICBNUyBTUUwgU2VydmVyIGluc3RhbGxhdGlvbiBmaWxlcyByb290IGRpcmVjdG9yeS4gTm9ybWFsbHkgaXQgaXMganVzdCBEVkQgZHJpdmUgbmFtZS4KCiAgICAuUEFSQU1FVEVSIEV4dHJhRmVhdHVyZXMKICAgIExpc3Qgb2YgZmVhdHVyZXMgdG8gYmUgaW5zdGFsbGVkIGluIGFkZGl0aW9uIHRvIGRlZmF1bHQgIlNRTEVuZ2luZSIuIE5vdGUgdGhhdCBwcmlvciB0bwogICAgU1FMIFNlcnZlciB2ZXJzaW9uIDIwMTIgU2VydmljZSBQYWNrIDEgQ3VtdWxhdGl2ZSBVcGRhdGUgMiAoSmFudWFyeSAyMDEzKSBvbmx5ICJSZXBsaWNhdGlvbiIsIAogICAgIkZ1bGxUZXh0IiBhbmQgIlJTIiBtYXkgYmUgaW5zdGFsbGVkIGluIGFkZGl0aW9uIHRvICJTUUxFbmdpbmUiLiBTZWUgdGhlIGZvbGxvd2luZyBsaW5rIGZvcgogICAgZGV0aWFsczogaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTQ0MjU5LmFzcHgKCiAgICAjPgp9CgpmdW5jdGlvbiBJbnN0YWxsLVNRTFNlcnZlckZvclN5c1ByZXAgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW4gc3lzcHJlcCBtb2RlLgoKICAgIC5ERVNDUklQVElPTgogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW4gc3lzcHJlcCBtb2RlLiBSZXR1cm5zICR0cnVlIGlmIGEgcmVib290IGlzIHJlcXVpcmVkIGFmdGVyIHRoZSBpbnN0YWxsYXRpb24sIAogICAgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCBhbmQgdGhyb3dzIGFuIGV4Y2VwdGlvbiBpbiBjYXNlIGlmIGluc3RhbGxhdGlvbiBmYWlscy4KCiAgICBTZXR1cCBtdXN0IGJlIGNvbXBsZXRlZCBhZnRlciBib290aW5nIHJlYXJtZWQgbWFjaGluZSBieSB1c2luZyBDb21wbGV0ZS1TUUxTZXJ2ZXIgY21kbGV0CgogICAgLlBBUkFNRVRFUiBTZXR1cFJvb3QKICAgIE1TIFNRTCBTZXJ2ZXIgaW5zdGFsbGF0aW9uIGZpbGVzIHJvb3QgZGlyZWN0b3J5LiBOb3JtYWxseSBpdCBpcyBqdXN0IERWRCBkcml2ZSBuYW1lLgoKICAgIC5QQVJBTUVURVIgRXh0cmFGZWF0dXJlcwogICAgTGlzdCBvZiBmZWF0dXJlcyB0byBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gZGVmYXVsdCAiU1FMRW5naW5lIi4gTm90ZSB0aGF0IHByaW9yIHRvCiAgICBTUUwgU2VydmVyIHZlcnNpb24gMjAxMiBTZXJ2aWNlIFBhY2sgMSBDdW11bGF0aXZlIFVwZGF0ZSAyIChKYW51YXJ5IDIwMTMpIG9ubHkgIlJlcGxpY2F0aW9uIiwgCiAgICAiRnVsbFRleHQiIGFuZCAiUlMiIG1heSBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gIlNRTEVuZ2luZSIuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yCiAgICBkZXRpYWxzOiBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAoKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kU2V0dXBSb290LAogICAgICAgIFthcnJheV0kRXh0cmFGZWF0dXJlcyA9IEAoKQogICAgKQoKICAgICRTZXR1cERpciA9IEdldC1JdGVtICRTZXR1cFJvb3QKICAgICRTZXR1cEV4ZSA9ICRTZXR1cERpci5HZXRGaWxlcygic2V0dXAuZXhlIilbMF0KCiAgICBSZXNvbHZlLVNRTFNlcnZlclByZXJlcXVpc2l0ZXMKCiAgICAkcGFyc2VyID0gTmV3LU9wdGlvblBhcnNlclByZXBhcmVJbWFnZQogICAgJEV4aXRDb2RlID0gJHBhcnNlci5FeGVjdXRlQmluYXJ5KCRTZXR1cEV4ZS5GdWxsTmFtZSwgQHsiUVMiID0gJG51bGw7ICJGRUFUVVJFUyIgPSBAKCJTUUxFbmdpbmUiKSArICRFeHRyYUZlYXR1cmVzIH0pCgogICAgaWYgKCRFeGl0Q29kZSAtZXEgMzAxMCkgewogICAgICAgIHJldHVybiAkdHJ1ZQogICAgfQoKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICB0aHJvdyAiSW5zdGFsbGF0aW9uIGV4ZWN1dGFibGUgZXhpdGVkIHdpdGggY29kZSAkKCJ7MDpYOH0iIC1mICRFeGl0Q29kZSkgKERlY2ltYWw6ICRFeGl0Q29kZSkiCiAgICB9CgogICAgcmV0dXJuICRmYWxzZQp9CgpmdW5jdGlvbiBDb21wbGV0ZS1TUUxTZXJ2ZXJBZnRlclN5c1ByZXAgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ29tcGxldGVzIHByZXZpb3VzbHkgcHJlcGFyZWQgd2l0aCAiSW5zdGFsbC1TUUxTZXJ2ZXJGb3JTeXNQcmVwIiBNUyBTUUwgU2VydmVyIGFmdGVyIHRoZSBzeXN0ZW0gd2FzIHJlYXJtZWQuCgogICAgLkRFU0NSSVBUSU9OCiAgICBDb21wbGV0ZXMgcHJldmlvdXNseSBwcmVwYXJlZCB3aXRoICJJbnN0YWxsLVNRTFNlcnZlckZvclN5c1ByZXAiIE1TIFNRTCBTZXJ2ZXIgYWZ0ZXIgdGhlIHN5c3RlbSB3YXMgcmVhcm1lZC4KICAgIFJldHVybnMgJHRydWUgaWYgYSByZWJvb3QgaXMgcmVxdWlyZWQgYWZ0ZXIgdGhlIGluc3RhbGxhdGlvbiwgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCBhbmQgdGhyb3dzIAogICAgYW4gZXhjZXB0aW9uIGluIGNhc2UgaWYgaW5zdGFsbGF0aW9uIGZhaWxzLgoKICAgIFNldHVwIG11c3QgYmUgY29tcGxldGVkIGFmdGVyIGJvb3RpbmcgcmVhcm1lZCBtYWNoaW5lIGJ5IHVzaW5nIENvbXBsZXRlLVNRTFNlcnZlciBjbWRsZXQKCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdAogICAgKQoKICAgICRTZXR1cERpciA9IEdldC1JdGVtICRTZXR1cFJvb3QKICAgICRTZXR1cEV4ZSA9ICRTZXR1cERpci5HZXRGaWxlcygic2V0dXAuZXhlIilbMF0KCiAgICAkcGFyc2VyID0gTmV3LU9wdGlvblBhcnNlckNvbXBsZXRlSW1hZ2UKICAgICRFeGl0Q29kZSA9ICRwYXJzZXIuRXhlY3V0ZUJpbmFyeSgkU2V0dXBFeGUuRnVsbE5hbWUsIEB7IlFTIiA9ICRudWxsfSkKCiAgICBpZiAoJEV4aXRDb2RlIC1lcSAzMDEwKSB7CiAgICAgICAgcmV0dXJuICR0cnVlCiAgICB9CgogICAgaWYgKCRFeGl0Q29kZSAtbmUgMCkgewogICAgICAgIHRocm93ICJJbnN0YWxsYXRpb24gZXhlY3V0YWJsZSBleGl0ZWQgd2l0aCBjb2RlICQoInswOlg4fSIgLWYgJEV4aXRDb2RlKSAoRGVjaW1hbDogJEV4aXRDb2RlKSIKICAgIH0KCiAgICByZXR1cm4gJGZhbHNlCn0KCmZ1bmN0aW9uIENvbnZlcnRUby1TUUxTdHJpbmcgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ29udmVydHMgYXJndW1lbnQgdG8gYSB2YWxpZCBTUUwgc3RyaW5nIGluIHF1b3RlcwoKICAgIC5ERVNDUklQVElPTgogICAgQ29udmVydHMgYXJndW1lbnQgdG8gYSB2YWxpZCBTUUwgc3RyaW5nIGluIHF1b3Rlcy4gVGhlIHN0cmluZyBtYXkgY29udGFpbiBhbnkgY2hhcmFjdGVycy4KICAgIFNlZSBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNzk4OTkuYXNweAoKICAgIC5QQVJBTUVURVIgUwogICAgU3RyaW5nIHRvIGNvbnZlcnQKICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlLCBWYWx1ZUZyb21QaXBlbGluZSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTCiAgICApCiAgICAKICAgIHJldHVybiAiJyQoJFMgLXJlcGxhY2UgIiciLCAiJyciKSciCn0KCmZ1bmN0aW9uIENvbnZlcnRUby1TUUxOYW1lIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbnZlcnRzIGFyZ3VtZW50IHRvIGEgdmFsaWQgU1FMIG5hbWUgaW4gYnJhY2tldHMKCiAgICAuREVTQ1JJUFRJT04KICAgIENvbnZlcnRzIGFyZ3VtZW50IHRvIGEgdmFsaWQgU1FMIG5hbWUgaW4gYnJhY2tldHMuIFRoZSBzdHJpbmcgbWF5IGNvbnRhaW4gYW55IGNoYXJhY3RlcnMuCiAgICBTZWUgaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTc1ODc0LmFzcHgKCiAgICAuUEFSQU1FVEVSIFMKICAgIFN0cmluZyB0byBjb252ZXJ0CiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSwgVmFsdWVGcm9tUGlwZWxpbmUgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kUwogICAgKQogICAgcmV0dXJuICJbJCgkUyAtcmVwbGFjZSAiXSIsICJdXSIpXSIKfQoKZnVuY3Rpb24gSW52b2tlLVNRTFRleHQgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgSW52b2tlcyBTUUwgdGV4dAoKICAgIC5ERVNDUklQVElPTgogICAgSW52b2tlcyBTUUwgdGV4dC4gUmV0dXJucyByYXcgU1FMIHNlcnZlciBvdXRwdXQuCgogICAgLlBBUkFNRVRFUiBTUUwKICAgIFNRTCBUZXh0CgogICAgLlBBUkFNRVRFUiBVc2VyCiAgICBTUUwgU2VydmVyIHVzZXIgbmFtZQoKICAgIC5QQVJBTUVURVIgUGFzc3dvcmQKICAgIFNRTCBTZXJ2ZXIgdXNlciBwYXNzd29yZAogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNRTCwKICAgICAgICBbc3RyaW5nXSRVc2VyID0gJG51bGwsCiAgICAgICAgW3N0cmluZ10kUGFzc3dvcmQgPSAkbnVsbAogICAgKQoKICAgICNXcml0ZS1XYXJuaW5nICIkU1FMYG4iCiAgICAjcmV0dXJuCgogICAgJEJpbmFyeSA9IEdldC1Db21tYW5kICJzcWxjbWQuZXhlIgoKICAgICR0ZW1wRmlsZSA9IFtJTy5QYXRoXTo6R2V0VGVtcEZpbGVOYW1lKCkKICAgICR0ZW1wRmlsZSA9IEdldC1JdGVtICR0ZW1wRmlsZQogICAgU2V0LUNvbnRlbnQgLVBhdGggJHRlbXBGaWxlIC1WYWx1ZSAkU1FMCgogICAgJENvbW1hbmRMaW5lID0gQCgnLWgnLCAnLTEnLCAnLWInLCAnLWknLCAiYCIkKCR0ZW1wRmlsZS5GdWxsTmFtZSlgIiIpCiAgICBpZiAoKCRVc2VyIC1uZSAkbnVsbCkgLWFuZCAoJFVzZXIgLW5lICcnKSkgewogICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICctVScKICAgICAgICAkQ29tbWFuZExpbmUgPSAkQ29tbWFuZExpbmUgKyAkVXNlcgogICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICctUCcKICAgICAgICAkQ29tbWFuZExpbmUgPSAkQ29tbWFuZExpbmUgKyAkUGFzc3dvcmQKICAgIH0KCiAgICBXcml0ZS1EZWJ1ZyAiRXhlY3V0aW5nOiBgbiRTUUxgbiIKICAgIFtzdHJpbmddJG91dHB1dCA9ICYkQmluYXJ5ICRDb21tYW5kTGluZQoKICAgICRFeGl0Q29kZSA9ICRMYXN0RXhpdENvZGUKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICBXcml0ZS1XYXJuaW5nICRvdXRwdXQKICAgICAgICB0aHJvdyAiU1FMQ01ELkVYRSByZXR1cm5lZCB3aXRoIGV4aXQgY29kZSAkRXhpdENvZGUgd2hpbGUgcnVubmluZyAkQmluYXJ5ICRDb21tYW5kTGluZSIKICAgIH0KICAgCiAgICBSZW1vdmUtSXRlbSAkdGVtcEZpbGUKCiAgICByZXR1cm4gJG91dHB1dAp9CgpmdW5jdGlvbiBOZXctU1FMVXNlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnZva2VzIFNRTCB0ZXh0CgogICAgLkRFU0NSSVBUSU9OCiAgICBJbnZva2VzIFNRTCB0ZXh0CgogICAgLlBBUkFNRVRFUiBTUUwKICAgIFNRTCBUZXh0CgogICAgLlBBUkFNRVRFUiBVc2VyCiAgICBTUUwgU2VydmVyIHVzZXIgbmFtZQoKICAgIC5QQVJBTUVURVIgUGFzc3dvcmQKICAgIFNRTCBTZXJ2ZXIgdXNlciBwYXNzd29yZAogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNRTCwKICAgICAgICBbc3RyaW5nXSRVc2VyID0gJG51bGwsCiAgICAgICAgW3N0cmluZ10kUGFzc3dvcmQgPSAkbnVsbAogICAgKQp9CgpmdW5jdGlvbiBOZXctUGFzc3dvcmQgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyByYW5kb20gcGFzc3dvcmQgb2YgdGhlIHNwZWNpZmllZCBsZW5ndGgKCiAgICAuREVTQ1JJUFRJT04KICAgIFBhc3N3b3JkIGNvbnRhaW5zIHJhbmRvbSBjaGFyYWN0ZXJzIGEteiwgQS1aLCBudW1iZXJzIGFuZCBzcGVjaWFsIGNoYXJhY3RlcnMuCiAgICBUaGVyZSBpcyBubyBndWFyYW50ZWUgdGhhdCBhbGwgdGhlIHR5cGVzIG9mIHN5bWJvbHMgd2lsbCBiZSBwcmVzZW50IGluIHRoZSBwYXNzd29yZC4KCiAgICAuUEFSQU1FVEVSIExlbmd0aAogICAgRGVzaXJlZCBsZW5ndGggb2YgdGhlIHBhc3N3b3JkLgoKICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbaW50XSRMZW5ndGg9NgogICAgKQoKICAgICRSZXN1bHQgPSAiIgogICAgJGFscGhhID0gImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5IUAjJCVeJiooKSdgImBgXytbXVx7fXw7OiwuLzw+P34iCiAgICB3aGlsZSAoJExlbmd0aCAtZ3QgMCkgewogICAgICAgICR4ID0gR2V0LVJhbmRvbSAkYWxwaGEuTGVuZ3RoCiAgICAgICAgJGMgPSAkYWxwaGFbJHhdCiAgICAgICAgJFJlc3VsdCA9ICIkUmVzdWx0JGMiCiAgICAgICAgJExlbmd0aCA9ICRMZW5ndGggLSAxCiAgICB9CiAgICByZXR1cm4gJFJlc3VsdAp9CgpmdW5jdGlvbiBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50IHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgbWlycm9yaW5nIGVuZHBvaW50LgoKICAgIC5ERVNDUklQVElPTgogICAgTWFzdGVyIGtleSBpcyBjcmVhdGVkIGlmIG5lY2Vzc2FyeS4gSG9zdCBjZXJ0aWZpY2F0ZSBpcyBjcmVhdGVkIHdoZW4gbmVjZXNzYXJ5IGVpdGhlciAobm9ybWFsbHkgb24gZmlyc3QgZW5kcG9pbnQgY3JlYXRpb24pLgoKICAgIEVuZHBvaW50IGFuZCBjZXJ0aWZpY2F0ZSBhcmUgcmVjcmVhdGVkIGluIGNhc2UgaWYgbWFzdGVyIGtleSBkaWQgbm90IGV4aXN0ZWQgKHNob3VsZCBub3Qgbm9ybWFsbHkgaGFwcGVuKS4KCiAgICBFbmRwb2ludCBpcyByZWNyZWF0ZWQgaW4gY2FzZSBpZiBjZXJ0aWZpY2F0ZSBkaWQgbm90IGV4aXN0ZWQgKHNob3VsZCBub3QgaGFwcGVuIHVubGVzcyB0aGUgZW5kcG9pbnQgd2FzIGNyZWF0ZWQgbWFudWFsbHkpLgoKICAgIE1pcnJvcmluZyBlbmRwb2ludCBpcyBjcmVhdGVkIHVubGVzcyBvbmUgYWxyZWFkeSBleGlzdHMuIFRoZSBlbmRwb2ludCBpcyBjcmVhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBuYW1lLiBXaGVuIHRoZSBlbmRwb2ludAogICAgYWxyZWFkeSBleGlzdHMgaXMgaXMgdW5jaGFuZ2VkLgoKICAgIEVuZHBvaW50IHBvcnQgaXMgc2VsZWN0ZWQgYXV0b21hdGljYWxseSBhcyA0MDIyIG9yIGFzIGZpcnN0IGF2YWlsYWJsZSBwb3J0IGFmdGVyIDQwMjIgaW4gY2FzZSBpZiA0MDIyIGlzIGFscmVhZHkgbGlzdGVuaW5nLgogICAgSWYgdGhlcmUgaXMgbm8gZmlyZXdhbGwgcnVsZSB3aXRoIG5hbWUgJ0RhdGFiYXNlTWlycm9yaW5nLVRDUC17cG9ydG51bWJlcn0nLCBhbGxvd2luZyBydWxlIGlzIGNyZWF0ZWQuCgogICAgQ2VydGlmaWNhdGUgaXMgc3RvcmVkIGluIHRoZSBzcGVjaWZpZWQgZmlsZS4KCiAgICBSZXR1cm5zIGVuZHBvaW50IGxpc3RlbmluZyBwb3J0LgoKICAgIC5QQVJBTUVURVIgRW5jcnlwdGlvblBhc3N3b3JkCiAgICBFbmNyeXB0aW9uIHBhc3N3b3JkIHVzZWQgdG8gY3JlYXRlIGNlcnRpZmljYXRlLgoKICAgIC5QQVJBTUVURVIgQ2VydGlmaWNhdGVGaWxlTmFtZQogICAgQ2VydGlmaWNhdGUgdGFyZ2V0IGZpbGUgbmFtZS4gRmlsZSBNVVNUIE5PVCBleGlzdC4KCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRDZXJ0aWZpY2F0ZUZpbGVOYW1lCiAgICApCgogICAgJEVuZHBvaW50TmFtZSA9ICdNaXJyb3JpbmdFbmRwb2ludCcKCiAgICAkRm9sZGVyID0gR2V0LUl0ZW0gJFdvcmtEaXIKCiAgICAkSCA9ICRFbnY6Q09NUFVURVJOQU1FIC1yZXBsYWNlICdbXkEtWmEtejAtOV9dJywgJ18nCgogICAgJFBvcnQgPSBHZXQtTmV4dEZyZWVQb3J0IDQwMjIKCiAgICAkQ3JlYXRlTWFzdGVyS2V5ID0gIlVTRSBtYXN0ZXI7CgogICAgICAgICAgICAgICAgICAgICAgICBJRiBOT1QgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLnN5bW1ldHJpY19rZXlzIHdoZXJlIG5hbWUgPSAnIyNNU19EYXRhYmFzZU1hc3RlcktleSMjJykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBNQVNURVIgS0VZIEVOQ1JZUFRJT04gQlkgUEFTU1dPUkQgPSAkKENvbnZlcnRUby1TUUxTdHJpbmcgJEVuY3J5cHRpb25QYXNzd29yZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWUgPSAnJHtIfV9jZXJ0JykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRFJPUCBDRVJUSUZJQ0FURSAke0h9X2NlcnQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICAgICAgSUYgRVhJU1RTKFNFTEVDVCAqIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBUT1AgMSBgQG5hbWUgPSBuYW1lIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFWEVDICgnRFJPUCBFTkRQT0lOVCBbJyArIGBAbmFtZSArICddJykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIElGIE5PVCBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWUgPSAnJHtIfV9jZXJ0JykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBDRVJUSUZJQ0FURSAke0h9X2NlcnQgV0lUSCBTVUJKRUNUID0gJyR7SH0gZW5kcG9pbnQgY2VydGlmaWNhdGUnOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgSUYgRVhJU1RTKFNFTEVDVCAqIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBUT1AgMSBgQG5hbWUgPSBuYW1lIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFWEVDICgnRFJPUCBFTkRQT0lOVCBbJyArIGBAbmFtZSArICddJykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIEJBQ0tVUCBDRVJUSUZJQ0FURSAke0h9X2NlcnQgVE8gRklMRSA9ICQoQ29udmVydFRvLVNRTFN0cmluZyAiJENlcnRpZmljYXRlRmlsZU5hbWUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBwb3J0IGludAogICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoU0VMRUNUICogRlJPTSBzeXMuZW5kcG9pbnRzIFdIRVJFIHR5cGVfZGVzYz0nREFUQUJBU0VfTUlSUk9SSU5HJykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBgQHBvcnQgPSBwb3J0IEZST00gc3lzLnRjcF9lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnCiAgICAgICAgICAgICAgICAgICAgICAgIEVORCBFTFNFCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUkVBVEUgRU5EUE9JTlQgJChDb252ZXJ0VG8tU1FMTmFtZSAkRW5kcG9pbnROYW1lKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNUQVRFID0gU1RBUlRFRAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFTIFRDUCAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExJU1RFTkVSX1BPUlQgPSAkUG9ydAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIExJU1RFTkVSX0lQID0gQUxMCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGT1IgREFUQUJBU0VfTUlSUk9SSU5HICggCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFVVEhFTlRJQ0FUSU9OID0gQ0VSVElGSUNBVEUgJHtIfV9jZXJ0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgRU5DUllQVElPTiA9IFJFUVVJUkVEIEFMR09SSVRITSBBRVMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBST0xFID0gQUxMCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBgQHBvcnQgPSAkUG9ydAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKCiAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCAncG9ydDooJyArIENPTlZFUlQoVkFSQ0hBUiwgYEBwb3J0KSArICcpJyBhcyBwb3J0CiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICAiCgogICAgJHJhd2RhdGEgPSBJbnZva2UtU1FMVGV4dCAtU1FMICRDcmVhdGVNYXN0ZXJLZXkKICAgIFtpbnRdJFBvcnQgPSAkcmF3ZGF0YSAtcmVwbGFjZSAnLipwb3J0OlwoKFteKV0qKVwpLionLCAnJDEnCgogICAgIyBPcGVuIHBvcnQgaW4gV2luZG93cyBGaXJld2FsbAoKICAgICRQb3J0T3BlbiA9ICRmYWxzZQogICAgJFJ1bGVOYW1lID0gIkRhdGFiYXNlTWlycm9yaW5nLVRDUC0kUG9ydCIKICAgIEdldC1OZXRGaXJld2FsbFJ1bGUgfCBGb3JlYWNoLU9iamVjdCB7CiAgICAgICAgaWYgKCRfLk5hbWUgLWVxICRSdWxlTmFtZSkgewogICAgICAgICAgICAkUG9ydE9wZW4gPSAkdHJ1ZQogICAgICAgIH0KICAgIH0KICAgIGlmICgtbm90ICRQb3J0T3BlbikgewogICAgICAgICREaXNwbGF5TmFtZSA9ICJNUyBTUUwgRGF0YWJhc2UgTWlycm9yaW5nIEVuZHBvaW50IGF0IFRDUCBwb3J0ICRQb3J0IgogICAgICAgIE5ldy1OZXRGaXJld2FsbFJ1bGUgLU5hbWUgJFJ1bGVOYW1lIC1EaXNwbGF5TmFtZSAkRGlzcGxheU5hbWUgLURlc2NyaXB0aW9uICREaXNwbGF5TmFtZSAtUHJvdG9jb2wgVENQIC1Mb2NhbFBvcnQgJFBvcnQgLUVuYWJsZWQgVHJ1ZSAtUHJvZmlsZSBBbnkgLUFjdGlvbiBBbGxvdwogICAgfQogICAgIAogICAgcmV0dXJuICRQb3J0Cn0KCmZ1bmN0aW9uIENvbXBsZXRlLU1pcnJvcmluZ0VuZHBvaW50IHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbXBsZXRlcyBtaXJyb3JpbmcgZW5kcG9pbnQKCiAgICAuREVTQ1JJUFRJT04KICAgIEFsbG93cyBpbmJvdW5kIGNvbm5lY3Rpb25zIGZyb20gcmVtb3RlIGhvc3QKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpciwKICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TG9naW4sCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdFVzZXIsCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdFBhc3N3b3JkCiAgICApCgogICAgJEZvbGRlciA9IEdldC1JdGVtICRSZW1vdGVXb3JrRGlyCiAgICAkUmVtb3RlV29ya0RpciA9ICRGb2xkZXIuRnVsbE5hbWUKCiAgICAkSCA9ICRSZW1vdGVIb3N0TmFtZSAtcmVwbGFjZSAnW15BLVphLXowLTlfXScsICdfJwoKICAgIGlmICgtbm90ICRSZW1vdGVIb3N0TG9naW4pIHsKICAgICAgICAkUmVtb3RlSG9zdExvZ2luID0gIiR7SH1fbG9naW4iCiAgICB9CiAgICBpZiAoLW5vdCAkUmVtb3RlSG9zdFVzZXIpIHsKICAgICAgICAkUmVtb3RlSG9zdFVzZXIgPSAiJHtIfV91c2VyIgogICAgfQogICAgaWYgKC1ub3QgJFJlbW90ZUhvc3RQYXNzd29yZCkgewogICAgICAgICRSZW1vdGVIb3N0UGFzc3dvcmQgPSAiJChOZXctUGFzc3dvcmQgMTApYUEjMyIKICAgIH0KCiAgICAkU1FMID0gICAgICAgICAgICAgIlVTRSBtYXN0ZXI7CgogICAgICAgICAgICAgICAgICAgICAgICBJRiBOT1QgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLnNxbF9sb2dpbnMgd2hlcmUgbmFtZT0kKENvbnZlcnRUby1TUUxTdHJpbmcgJFJlbW90ZUhvc3RMb2dpbikpCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUkVBVEUgTE9HSU4gJChDb252ZXJ0VG8tU1FMTmFtZSAkUmVtb3RlSG9zdExvZ2luKSBXSVRIIFBBU1NXT1JEID0gJChDb252ZXJ0VG8tU1FMU3RyaW5nICRSZW1vdGVIb3N0UGFzc3dvcmQpOwogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIElGIE5PVCBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuc3lzdXNlcnMgd2hlcmUgbmFtZT0kKENvbnZlcnRUby1TUUxTdHJpbmcgJFJlbW90ZUhvc3RVc2VyKSkKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBVU0VSICQoQ29udmVydFRvLVNRTE5hbWUgJFJlbW90ZUhvc3RVc2VyKSBGT1IgTE9HSU4gJChDb252ZXJ0VG8tU1FMTmFtZSAkUmVtb3RlSG9zdExvZ2luKTsKICAgICAgICAgICAgICAgICAgICAgICAgRU5ECiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWU9JyR7SH1fcmVtb3RlX2NlcnQnKQogICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgRFJPUCBDRVJUSUZJQ0FURSAke0h9X3JlbW90ZV9jZXJ0CiAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBHTwoKICAgICAgICAgICAgICAgICAgICAgICAgQ1JFQVRFIENFUlRJRklDQVRFICR7SH1fcmVtb3RlX2NlcnQgQVVUSE9SSVpBVElPTiAkKENvbnZlcnRUby1TUUxOYW1lICRSZW1vdGVIb3N0VXNlcikgRlJPTSBGSUxFID0gJChDb252ZXJ0VG8tU1FMU3RyaW5nICIkUmVtb3RlV29ya0RpclxjZXJ0aWZpY2F0ZS5jZXIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICBTRUxFQ1QgVE9QIDEgYEBuYW1lID0gbmFtZSBGUk9NIHN5cy5lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnCiAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCAnbmFtZTooJyArIGBAbmFtZSArICcpJyBhcyBuYW1lCiAgICAgICAgICAgICAgICAgICAgICAgICIKCiAgICAkcmF3ZGF0YSA9IEludm9rZS1TUUxUZXh0IC1TUUwgJFNRTAogICAgJEVuZHBvaW50TmFtZSA9ICRyYXdkYXRhIC1yZXBsYWNlICcuKm5hbWU6XCgoW14pXSopXCkuKicsICckMScKICAgICRTUUwgPSAgICAgICAgICAgICAiR1JBTlQgQ09OTkVDVCBPTiBFTkRQT0lOVDo6JChDb252ZXJ0VG8tU1FMTmFtZSAkRW5kcG9pbnROYW1lKSBUTyAkKENvbnZlcnRUby1TUUxOYW1lICRSZW1vdGVIb3N0TG9naW4pIgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFNRTCkKfQoKZnVuY3Rpb24gQ29tcGxldGUtU1FMTWlycm9yIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbXBsZXRlcyBjcmVhdGlvbiBvZiBtaXJyb3JlZCBTUUwgZGF0YWJhc2UKCiAgICAuREVTQ1JJUFRJT04KICAgIFRoaXMgY21kbGV0IHNob3VsZCBiZSBmaXJzdCBleGVjdXRlZCBvbiBtaXJyb3Igc2VydmVyIGFuZCB0aGVuIG9uIHByaW5jaXBhbCBzZXJ2ZXIuCiAgICBPdGhlcndpc2UgaXQgd2lsbCBmYWlsIChob3dldmVyIGl0IG1heSBiZSBleGVjdXRlZCBhZ2FpbiB3aXRoIG5vIGhhcm0pLgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbSW50XSRSZW1vdGVQb3J0LAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFiYXNlTmFtZQogICAgKQoKICAgICRVcmwgPSAiVENQOi8vJHtSZW1vdGVIb3N0TmFtZX06JHtSZW1vdGVQb3J0fSIKICAgICRBbHRlckRiID0gIkFMVEVSIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgU0VUIFBBUlRORVIgPSAkKENvbnZlcnRUby1TUUxTdHJpbmcgJFVybCk7CiAgICAgICAgICAgICAgICBHTyIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRBbHRlckRiKQp9CgpmdW5jdGlvbiBOZXctU1FMRGF0YWJhc2UgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBlbXB0eSBTUUwgZGF0YWJhc2UKCiAgICAuREVTQ1JJUFRJT04KICAgIENyZWF0ZXMgZW1wdHkgU1FMIGRhdGFiYXNlIHdpdGggZGVmYXVsdCBzZXR0aW5ncy4gRmFpbHMgaW4gY2FzZSBpcyB0aGUgZGF0YWJhc2UgYWxyZWFkeSBleGlzdHMuCgogICAgLlBBUkFNRVRFUiBEYXRhQmFzZU5hbWUKICAgIERhdGFiYXNlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBtZGZGaWxlCiAgICBOYW1lIG9mIHRoZSBNREYgKGRhdGEpIGZpbGUuIElmIG5vdCBzcGVjaWZpZWQsIHRoZSBmb2xsb3dpbmcgdmFsdWUgaXMgdXNlZDoKICAgICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVx7RGF0YUJhc2VQYXRoTmFtZX0ubWRmIgogICAgV2hlcmUge0RhdGFCYXNlUGF0aE5hbWV9IGlzIGRhdGFiYXNlIG5hbWUgd2l0aCBhbGwgYnV0IEEtWiwgYS16LCAwLTkgY2hhcmFjdGVycwogICAgcmVwbGFjZWQgYnkgdW5kZXJzY29yZS4KCiAgICAuUEFSQU1FVEVSIERhdGFCYXNlTmFtZQogICAgTmFtZSBvZiB0aGUgTERGICh0cmFuc2FjdGlvbiBsb2cpIGZpbGUuIElmIG5vdCBzcGVjaWZpZWQsIHRoZSBmb2xsb3dpbmcgdmFsdWUgaXMgdXNlZDoKICAgICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVx7RGF0YUJhc2VQYXRoTmFtZX1fbG9nLm1kZiIKICAgIFdoZXJlIHtEYXRhQmFzZVBhdGhOYW1lfSBpcyBkYXRhYmFzZSBuYW1lIHdpdGggYWxsIGJ1dCBBLVosIGEteiwgMC05IGNoYXJhY3RlcnMKICAgIHJlcGxhY2VkIGJ5IHVuZGVyc2NvcmUuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZSwKICAgICAgICBbU3RyaW5nXSRtZGZGaWxlPSRudWxsLAogICAgICAgIFtTdHJpbmddJGxkZkZpbGU9JG51bGwKICAgICkKCiAgICAkRGF0YUJhc2VQYXRoTmFtZSA9ICREYXRhQmFzZU5hbWUgLXJlcGxhY2UgJ1teMC05YS16QS1aXScsICdfJwogICAgaWYgKC1ub3QgJG1kZkZpbGUpIHsKICAgICAgICAkbWRmRmlsZSA9ICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVwke0RhdGFCYXNlUGF0aE5hbWV9Lm1kZiIKICAgIH0KICAgIGlmICgtbm90ICRsZGZGaWxlKSB7CiAgICAgICAgJGxkZkZpbGUgPSAiQzpcUHJvZ3JhbSBGaWxlc1xNaWNyb3NvZnQgU1FMIFNlcnZlclxNU1NRTDExLk1TU1FMU0VSVkVSXE1TU1FMXERBVEFcJHtEYXRhQmFzZVBhdGhOYW1lfV9sb2cubGRmIgogICAgfQoKICAgICROZXdEYXRhYmFzZSA9ICIKICAgICAgICBDUkVBVEUgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKQogICAgICAgICAgICAgICAgQ09OVEFJTk1FTlQgPSBOT05FCiAgICAgICAgICAgICAgICBPTiAgUFJJTUFSWSAKICAgICAgICAgICAgKCBOQU1FID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAkRGF0YUJhc2VOYW1lKSwgRklMRU5BTUUgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICRtZGZGaWxlKSAsIFNJWkUgPSA0MDk2S0IgLCBGSUxFR1JPV1RIID0gMTAyNEtCICkKICAgICAgICAgICAgICAgIExPRyBPTiAKICAgICAgICAgICAgKCBOQU1FID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJHtEYXRhQmFzZU5hbWV9X2xvZyIpLCBGSUxFTkFNRSA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgJGxkZkZpbGUpICwgU0laRSA9IDEwMjRLQiAsIEZJTEVHUk9XVEggPSAxMCUpCiAgICAgICAgR08KICAgICAgICBVU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKQogICAgICAgIEdPCiAgICAgICAgSUYgTk9UIEVYSVNUUyAoU0VMRUNUIG5hbWUgRlJPTSBzeXMuZmlsZWdyb3VwcyBXSEVSRSBpc19kZWZhdWx0PTEgQU5EIG5hbWUgPSBOJ1BSSU1BUlknKSBBTFRFUiBEQVRBQkFTRSAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIE1PRElGWSBGSUxFR1JPVVAgW1BSSU1BUlldIERFRkFVTFQKICAgICAgICBHTyIKCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkTmV3RGF0YWJhc2UpCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nUHJpbmNpcGFsU3RlcDEgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgcHJpbmNpcGFsIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMSkKCiAgICAuREVTQ1JJUFRJT04KICAgIEluaXRpYWxpemVzIG1pcnJvcmluZyBlbmRwb2ludCAodGhpcyBpcyBhYnNvbHV0ZWx5IHN5bW1ldHJpYyBzdGVwIHRvIHRoZSBtaXJyb3IgaW5pdCkuIEluIGFkZGl0aW9uIHRvIHRoYXQgaXQgY3JlYXRlcwogICAgYSBkYXRhYmFzZSBhbmQgc3RvcmVzIGJhY2t1cHMgb2YgaXQgYW5kIGl0cyB0cmFuc2FjdGlvbiBsb2cgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIHRoZSBlbmRwb2ludCBjZXJ0aWZpY2F0ZS4KCiAgICBBIGZpcmV3YWxsIHJ1bGUgaXMgY3JlYXRlZCBmb3IgZW5kcG9pbnQgaWYgbmVjZXNzYXJ5LgoKICAgIC5QQVJBTUVURVIgV29ya0RpcgogICAgV29ya2luZCBkaXJlY3RvcnkuIFRoaXMgZGlyZWN0b3J5IHNob3VsZCBiZSB0cmFuZmVycmVkIHRvIHRoZSBtaXJyb3Igc2VydmVyIGFmdGVyIHRoaXMKICAgIHN0ZXAgaXMgZXhlY3V0ZWQuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWUKICAgIE1pcnJvcmVkIGRhdGFiYXNlIG5hbWUuIFRoaXMgbmFtZSBNVVNUIGJlIHVzZSBhdCBtaXJyb3Igc2VydmVyIGVpdGhlci4KICAgIAogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZQogICAgKQoKICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCA9ICIkKE5ldy1QYXNzd29yZCAxMClhQSMzIgoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgW3ZvaWRdKE5ldy1JdGVtIC1UeXBlIERpcmVjdG9yeSAkV29ya0RpcikKICAgIH0KICAgICRXb3JrRGlyID0gKEdldC1JdGVtICRXb3JrRGlyKS5GdWxsTmFtZQogICAgaWYgKChHZXQtQ2hpbGRJdGVtIC1QYXRoICRXb3JrRGlyKS5MZW5ndGggLWd0IDApIHsKICAgICAgICB0aHJvdyAiV29ya2luZyBkaXJlY3RvcnkgJFdvcmtEaXIgaXMgbm90IGVtcHR5IgogICAgfQoKICAgICRFbmRwb2ludFBvcnQgPSBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50ICRFbmNyeXB0aW9uUGFzc3dvcmQgIiRXb3JrRGlyXGNlcnRpZmljYXRlLmNlciIKICAgICRFbmRwb2ludFBvcnQgfCBTZXQtQ29udGVudCAiJFdvcmtEaXJcZW5kcG9pbnQtcG9ydC50eHQiCiAgICBOZXctU1FMRGF0YWJhc2UgJERhdGFCYXNlTmFtZQoKICAgICRCYWNrdXBEYiA9ICJCQUNLVVAgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcU291cmNlLmJhayIpIFdJVEggTk9GT1JNQVQsIElOSVQsIE5BTUUgPSBOJ0Z1bGwgRGF0YWJhc2UgQmFja3VwJywgU0tJUCwgTk9SRVdJTkQsIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwRGIpCiAgICAkQmFja3VwTG9nID0gIkJBQ0tVUCBMT0cgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcU291cmNlX2xvZy5iYWsiKSBXSVRIIE5PRk9STUFULCBJTklULCAgTkFNRSA9IE4nVHJhbnNhY3Rpb24gTG9nICBCYWNrdXAnLCBTS0lQLCBOT1JFV0lORCwgTk9VTkxPQUQsIFNUQVRTID0gMTAKICAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwTG9nKQp9CgpmdW5jdGlvbiBJbml0aWFsaXplLVNRTE1pcnJvcmluZ1ByaW5jaXBhbFN0ZXAyIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIFByZXBhcmVzIHByaW5jaXBhbCBTUUwgU2VydmVyIGZvciBkYXRhYmFzZSBtaXJyb3JpbmcgKFN0YWdlIDIpCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbXBvcnRzIHJlbW90ZSBzZXJ2ZXIgY2VydGlmaWNhdGUgYW5kIGdyYW50cyBpdCB3aXRoIGFjY2VzcyB0byB0aGUgbWlycm9yaW5nIGVuZHBvaW50LgoKICAgIC5QQVJBTUVURVIgUmVtb3RlSG9zdE5hbWUKICAgIFJlbW90ZSAobWlycm9yKSBob3N0IG5hbWUuIEZRRE4gaXMgcHJlZmVycmVkLCBidXQgTmV0QklPUyBuYW1lcyBhbmQgSVAgYWRkcmVzc2VzIGFyZSBhbHNvIGFjY2VwdGVkLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlV29ya0RpcgogICAgUGF0aCB0byBhIGNvcHkgb2Ygd29ya2RpciBvYnRhaW5lZCBmcm9tIG1pcnJvciBtYWNoaW5lIGNyZWF0ZWQgb24gU3RhZ2UgMS4KICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpcgogICAgKQoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFJlbW90ZVdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIlJlbW90ZSB3b3JrIGRpciAnJFJlbW90ZVdvcmtEaXInIHdhcyBub3QgZm91bmQiCiAgICB9CiAgICAkUmVtb3RlV29ya0RpciA9IChHZXQtSXRlbSAkUmVtb3RlV29ya0RpcikuRnVsbE5hbWUKCiAgICBDb21wbGV0ZS1NaXJyb3JpbmdFbmRwb2ludCAkUmVtb3RlSG9zdE5hbWUgJFJlbW90ZVdvcmtEaXIKfQoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1TUUxNaXJyb3JpbmdQcmluY2lwYWxTdGVwMyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBQcmVwYXJlcyBwcmluY2lwYWwgU1FMIFNlcnZlciBmb3IgZGF0YWJhc2UgbWlycm9yaW5nIChTdGFnZSAzKQoKICAgIC5ERVNDUklQVElPTgogICAgQ29tcGxldGVzIG1pcnJvciBjcmVhdGlvbi4gVGhpcyBzdGVwIG11c3QgYmUgZ2xvYmFsbHkgdGhlIGxhc3Qgb25lIGluIG1pcnJvciBjcmVhdGlvbiBzZXF1ZW5jZS4KCiAgICBOb3RlIHRoYXQgdGhlIHJlbW90ZSBob3N0IGNlcnRpZmljYXRlIGlzIHZhbGlkIGZyb20gdGhlIHRpbWUgaXQgaXMgY3JlYXRlZCB0aGVyZS4gU28KICAgIHRoaXMgc3RlcCB3aWxsIGZhaWwgaWYgdGhlcmUgaXMgbm90aWNhYmxlIGRpZmZlcmVudCBpbiB0aW1lIGxvY2FsIGFuZCByZW1vdGUgbWFjaGluZXMuCgogICAgLlBBUkFNRVRFUiBSZW1vdGVIb3N0TmFtZQogICAgUmVtb3RlIChwcmluY2lwYWwpIGhvc3QgbmFtZS4gRlFETiBpcyBwcmVmZXJyZWQsIGJ1dCBOZXRCSU9TIG5hbWVzIGFuZCBJUCBhZGRyZXNzZXMgYXJlIGFsc28gYWNjZXB0ZWQuCgogICAgLlBBUkFNRVRFUiBSZW1vdGVXb3JrRGlyCiAgICBQYXRoIHRvIGEgY29weSBvZiB3b3JrZGlyIG9idGFpbmVkIGZyb20gcHJpbmNpcGFsIG1hY2hpbmUgY3JlYXRlZCBvbiBTdGFnZSAxLgoKICAgIC5QQVJBTUVURVIgRGF0YWJhc2VOYW1lCiAgICBNaXJyb3JlZCBkYXRhYmFzZSBuYW1lLiBUaGlzIG5hbWUgTVVTVCBtYXRjaCBwcmluY2lwYWwgZGF0YWJhc2UgbmFtZSBhbmQgbmFtZSBwcm92aWRlZCBvbiBzdGVwIDEuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZUhvc3ROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZVdvcmtEaXIsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kRGF0YWJhc2VOYW1lCiAgICApCgogICAgW2ludF0kcG9ydCA9IEdldC1Db250ZW50ICIke1JlbW90ZVdvcmtEaXJ9XGVuZHBvaW50LXBvcnQudHh0IgogICAgQ29tcGxldGUtU1FMTWlycm9yICRSZW1vdGVIb3N0TmFtZSAkcG9ydCAkRGF0YWJhc2VOYW1lCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDEgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UxKQoKICAgIC5ERVNDUklQVElPTgogICAgSW5pdGlhbGl6ZXMgbWlycm9yaW5nIGVuZHBvaW50IGZvciBtaXJyb3Igc2VydmVyLiBTdG9yZXMgbWlycm9yaW5nIGVuZHBvaW50IGNlcnRpZmljYXRlIGluIFdvcmtkaXIuCgogICAgLlBBUkFNRVRFUiBXb3JrRGlyCiAgICBXb3JraW5kIGRpcmVjdG9yeS4gVGhpcyBkaXJlY3Rvcnkgc2hvdWxkIGJlIHRyYW5mZXJyZWQgdG8gdGhlIHByaW5jaXBhbCBzZXJ2ZXIgYWZ0ZXIgdGhpcwogICAgc3RlcCBpcyBleGVjdXRlZC4KCiAgICAuUEFSQU1FVEVSIERhdGFiYXNlTmFtZQogICAgTWlycm9yZWQgZGF0YWJhc2UgbmFtZS4gVGhpcyBuYW1lIE1VU1QgbWF0Y2ggcHJpbmNpcGFsIGRhdGFiYXNlIG5hbWUuCgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFiYXNlTmFtZQogICAgKQoKICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCA9ICIkKE5ldy1QYXNzd29yZCAxMClhQSMzIgoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgW3ZvaWRdKE5ldy1JdGVtIC1UeXBlIERpcmVjdG9yeSAkV29ya0RpcikKICAgIH0KICAgICRXb3JrRGlyID0gKEdldC1JdGVtICRXb3JrRGlyKS5GdWxsTmFtZQoKICAgICRFbmRwb2ludFBvcnQgPSBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50ICRFbmNyeXB0aW9uUGFzc3dvcmQgIiRXb3JrRGlyXGNlcnRpZmljYXRlLmNlciIKICAgICRFbmRwb2ludFBvcnQgfCBTZXQtQ29udGVudCAiJFdvcmtEaXJcZW5kcG9pbnQtcG9ydC50eHQiCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDIgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMikKCiAgICAuREVTQ1JJUFRJT04KICAgIEltcG9ydHMgcmVtb3RlIHNlcnZlciBjZXJ0aWZpY2F0ZSBhbmQgZ3JhbnRzIGl0IHdpdGggYWNjZXNzIHRvIHRoZSBtaXJyb3JpbmcgZW5kcG9pbnQuCiAgICBSZXN0b3JlcyBkYXRhYmFzZSBvYnRhaW5lZCBmcm9tIHByaW5jaXBhbCBhbmQgbGVhdmVzIGl0IGluICdSZXN0b3JpbmcnIHN0YXRlLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlSG9zdE5hbWUKICAgIFJlbW90ZSAocHJpbmNpcGFsKSBob3N0IG5hbWUuIEZRRE4gaXMgcHJlZmVycmVkLCBidXQgTmV0QklPUyBuYW1lcyBhbmQgSVAgYWRkcmVzc2VzIGFyZSBhbHNvIGFjY2VwdGVkLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlV29ya0RpcgogICAgUGF0aCB0byBhIGNvcHkgb2Ygd29ya2RpciBvYnRhaW5lZCBmcm9tIHByaW5jaXBhbCBtYWNoaW5lIGNyZWF0ZWQgb24gU3RhZ2UgMS4KCiAgICAuUEFSQU1FVEVSIERhdGFiYXNlTmFtZQogICAgTWlycm9yZWQgZGF0YWJhc2UgbmFtZS4gVGhpcyBuYW1lIE1VU1QgbWF0Y2ggcHJpbmNpcGFsIGRhdGFiYXNlIG5hbWUuCgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZQogICAgKQoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFJlbW90ZVdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIlJlbW90ZSB3b3JrIGRpciAnJFJlbW90ZVdvcmtEaXInIHdhcyBub3QgZm91bmQiCiAgICB9CiAgICAkUmVtb3RlV29ya0RpciA9IChHZXQtSXRlbSAkUmVtb3RlV29ya0RpcikuRnVsbE5hbWUKCiAgICBDb21wbGV0ZS1NaXJyb3JpbmdFbmRwb2ludCAkUmVtb3RlSG9zdE5hbWUgJFJlbW90ZVdvcmtEaXIKCiAgICAkUmVzdG9yZURiID0gIlJFU1RPUkUgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBGUk9NIERJU0sgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICIkUmVtb3RlV29ya0RpclxTb3VyY2UuYmFrIikgV0lUSCBGSUxFID0gMSwgTk9SRUNPVkVSWSwgTk9VTkxPQUQsIFJFUExBQ0UsIFNUQVRTID0gNQogICAgICAgICAgICAgICAgICBHTyIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRSZXN0b3JlRGIpCiAgICAkUmVzdG9yZUxvZyA9ICJSRVNUT1JFIExPRyAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIEZST00gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRSZW1vdGVXb3JrRGlyXFNvdXJjZV9sb2cuYmFrIikgV0lUSCBGSUxFID0gMSwgTk9SRUNPVkVSWSwgTk9VTkxPQUQsIFNUQVRTID0gMTAKICAgICAgICAgICAgICAgICAgIEdPIgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVMb2cpCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDMgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMykKCiAgICAuREVTQ1JJUFRJT04KICAgIENvbXBsZXRlcyBtaXJyb3IgY3JlYXRpb24uIFRoaXMgc3RlcCBtdXN0IGJlIGV4ZWN1dGVkIHN0cmljdGx5IGJlZm9yZSBzeW1tZXRyaWMgc3RlcCBvbiB0aGUgcHJpbmNpcGFsLgoKICAgIE5vdGUgdGhhdCB0aGUgcmVtb3RlIGhvc3QgY2VydGlmaWNhdGUgaXMgdmFsaWQgZnJvbSB0aGUgdGltZSBpdCBpcyBjcmVhdGVkIHRoZXJlLiBTbwogICAgdGhpcyBzdGVwIHdpbGwgZmFpbCBpZiB0aGVyZSBpcyBub3RpY2FibGUgZGlmZmVyZW50IGluIHRpbWUgbG9jYWwgYW5kIHJlbW90ZSBtYWNoaW5lcy4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZUhvc3ROYW1lCiAgICBSZW1vdGUgKHByaW5jaXBhbCkgaG9zdCBuYW1lLiBGUUROIGlzIHByZWZlcnJlZCwgYnV0IE5ldEJJT1MgbmFtZXMgYW5kIElQIGFkZHJlc3NlcyBhcmUgYWxzbyBhY2NlcHRlZC4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZVdvcmtEaXIKICAgIFBhdGggdG8gYSBjb3B5IG9mIHdvcmtkaXIgb2J0YWluZWQgZnJvbSBwcmluY2lwYWwgbWFjaGluZSBjcmVhdGVkIG9uIFN0YWdlIDEuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWUKICAgIE1pcnJvcmVkIGRhdGFiYXNlIG5hbWUuIFRoaXMgbmFtZSBNVVNUIG1hdGNoIHByaW5jaXBhbCBkYXRhYmFzZSBuYW1lLgoKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpciwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSREYXRhYmFzZU5hbWUKICAgICkKCiAgICBbaW50XSRwb3J0ID0gR2V0LUNvbnRlbnQgIiR7UmVtb3RlV29ya0Rpcn1cZW5kcG9pbnQtcG9ydC50eHQiCiAgICBDb21wbGV0ZS1TUUxNaXJyb3IgJFJlbW90ZUhvc3ROYW1lICRwb3J0ICREYXRhYmFzZU5hbWUKfQoKZnVuY3Rpb24gR2V0LU5leHRGcmVlUG9ydCB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBSZXR1cm5zIHNwZWNpZmllZCBkZXNpcmVkIHBvcnQgb3IgY2xvc2VzdCBuZXh0IG9uZSB1bm9jY3VwaWVkLgoKICAgIC5QQVJBTUVURVIgUG9ydAogICAgRGVzaXJlZCBwb3J0IG51bWJlci4KCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtpbnRdJFBvcnQKICAgICkKICAgICRPcGVuUG9ydHMgPSBuZXRzdGF0IC1hb24gfCBzZWxlY3Qtc3RyaW5nICdMSVNURU5JTkcnIHwgRm9yZWFjaC1PYmplY3QgeyAoKCRfIC1yZXBsYWNlICdeXHMqJywgJycgLXNwbGl0ICdccysnKVsxXSAtc3BsaXQgJy4qOicpWzFdIH0gfCBTb3J0LU9iamVjdCB8IEdldC1VbmlxdWUKICAgIHdoaWxlICgkT3BlblBvcnRzLkNvbnRhaW5zKCR7UG9ydH0pKSB7CiAgICAgICAgJFBvcnQgPSAkUG9ydCArIDEKICAgIH0KICAgIHJldHVybiAkUG9ydAp9CgpmdW5jdGlvbiBJbml0aWFsaXplLUFsd2F5c09uIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluaXRpYWxpemVzIEFsd2F5c09uIGNsdXN0ZXJpbmcgb24gbG9jYWwgU1FMIHNlcnZlciBhbmQgY3JlYXRlcyBBbHdheXNPbiBlbmRwb2ludCBsaXN0ZW5lci4gUmV0dXJucyBBbHdheXNPbiBlbmRwb2ludCBwb3J0IG51bWJlci4KCiAgICAuREVTQ1JJUFRJT04KICAgIEVuYWJsZXMgQWx3YXlzT24gY2x1c3RlcmluZyBvbiBsb2NhbCBTUUwgc2VydmVyLiBDcmVhdGVzIEFsd2F5c09uIFRDUCBlbmRwb2ludCBvbiBwb3J0IDUwMjIgb3IgZ3JlYXRlciBpZiB0aGUgb25lIGlzIG9jY3VwaWVkLiAgIAogICAgIz4KCiAgICBpZiAoIShUZXN0LVBhdGggU1FMU0VSVkVSOlwpKSB7CiAgICAgICAgSW1wb3J0LU1vZHVsZSBzcWxwcwogICAgfQogICAgJE1hY2hpbmVOYW1lID0gKEdldC1DaGlsZEl0ZW0gU1FMU0VSVkVSOlxTUUwpWzBdLlBTQ2hpbGROYW1lCiAgICAkSW5zdGFuY2VOYW1lID0gKEdldC1DaGlsZEl0ZW0gU1FMU0VSVkVSOlxTUUxcJE1hY2hpbmVOYW1lKS5QU0NoaWxkTmFtZQogICAgJEFsd2F5c09uRW5hYmxlZCA9ICgoR2V0LUl0ZW0gU1FMU0VSVkVSOlxTUUxcJE1hY2hpbmVOYW1lXCRJbnN0YW5jZU5hbWUpIHwgc2VsZWN0IElzSGFkckVuYWJsZWQpLklzSGFkckVuYWJsZWQKICAgIGlmICgtbm90ICRBbHdheXNPbkVuYWJsZWQpIHsKICAgICAgICBFbmFibGUtU3FsQWx3YXlzT24gLVBhdGggIlNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lIiAtRm9yY2UKICAgIH0KICAgICRJbnN0YW5jZSA9IEdldC1JdGVtIFNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lCiAgICAkZW5kcG9pbnQgPSAkSW5zdGFuY2UuRW5kcG9pbnRzWyJBbHdheXNPbkVuZHBvaW50Il0KICAgIGlmICgtbm90ICRlbmRwb2ludCkgewogICAgICAgICRQb3J0ID0gR2V0LU5leHRGcmVlUG9ydCA1MDIyCiAgICAgICAgJGVuZHBvaW50ID0gTmV3LVNxbEhhZHJFbmRwb2ludCBBbHdheXNPbkVuZHBvaW50IC1Qb3J0ICRQb3J0IC1QYXRoIFNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lCiAgICB9IGVsc2UgewogICAgICAgICRQb3J0ID0gJGVuZHBvaW50LlByb3RvY29sLlRjcC5MaXN0ZW5lclBvcnQKICAgIH0gCiAgICBpZiAoJGVuZHBvaW50LkVuZHBvaW50U3RhdGUgLW5lICJTdGFydGVkIikgewogICAgICAgICRlbmRwb2ludC5TdGFydCgpCiAgICB9ICAgIAogICAgcmV0dXJuICRQb3J0Cn0KCmZ1bmN0aW9uIE5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgbmV3IEFsd2F5c09uIGF2YWlsYWJpbGl0eSBncm91cCBvbiBwcmltYXJ5IHJlcGxpY2EuCgogICAgLkRFU0NSSVBUSU9OCiAgICBDcmVhdGVzIG5ldyBBbHdheXNPbiBhdmFpbGFiaWxpdHkgZ3JvdXAgb24gcHJpbWFyeSByZXBsaWNhLgoKICAgIC5QQVJBTUVURVIgV29ya0RpcgogICAgV29ya2luZCBkaXJlY3RvcnkuIFRoaXMgZGlyZWN0b3J5IHNob3VsZCBiZSB0cmFuZmVycmVkIHRvIHRoZSByZXBsaWNhIHNlcnZlcihzKSBhZnRlciB0aGlzCiAgICBzdGVwIGlzIGV4ZWN1dGVkLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgQXZhaWxhYmlsaXR5IGdyb3VwIG5hbWUuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWVzCiAgICBSZXBsaWNhIGRhdGFiYXNlKHMpIG5hbWVzLgoKICAgIC5QQVJBTUVURVIgUmVwbGljYURlZnMKICAgIEFycmF5IG9mIHJlcGxpY2EgZGVmaW5pdGlvbi4gRWFjaCBkZWZpbml0aW9uIGlzIGEgaGFzaCB0YWJsZSB3aXRoIHJlcGxpY2Etc3BlY2lmaWMgdmFsdWVzLgogICAgCiAgICBNYW5kYXRvcnkgcmVwbGljYSBkZWZpbml0aW9uIHZhbHVlcyBhcmU6CgogICAgICAgICogW1N0cmluZ10gU0VSVkVSX0lOU1RBTkNFICAgLSBSZXBsaWNhIHNlcnZlciBpbnN0YW5jZSBuYW1lCiAgICAgICAgKiBbU3RyaW5nXSBFTkRQT0lOVF9VUkwgICAgICAtIFJlcGxpY2Egc2VydmVyIGVuZHBvaW50IFVSTC4gTm9ybWFsbHkgaXQgaXMgVENQOi8vZnVsbHkucXVhbGlmaWVkLmRvbWFpbi5uYW1lOjUwMjIgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBvcnQgbnVtYmVyIHNob3VsZCBiZSBvYnRhaW5lZCB3aXRoIEluaXRpYWxpemUtQWx3YXlzT24gYXQgdGhlIHJlcGxpY2Egc2VydmVyCiAgICAgICAgKiBbU3RyaW5nXSBBVkFJTEFCSUxJVFlfTU9ERSAtIFJlcGxpY2EgYXZhaWxhYmlsaXR5IG1vZGUuIENhbiBiZSAiU1lOQ0hST05PVVNfQ09NTUlUIiBvciAiQVNZTkNIUk9OT1VTX0NPTU1JVCIgb25seS4KICAgICAgICAqIFtTdHJpbmddIEZBSUxPVkVSX01PREUgICAgIC0gUmVwbGljYSBhdmFpbGFiaWxpdHkgbW9kZS4gQ2FuIGJlICJNQU5VQUwiIG9yICJBVVRPTUFUSUMiIG9ubHkuCgogICAgT3B0aW9uYWwgcmVwbGljYSBkZWZpbml0aW9uIHZhbHVlcyBhcmU6CgogICAgICAgICogW0ludGVnZXJdIEJBQ0tVUF9QUklPUklUWSAgICAgICAgICAtIEJhY2t1cCBwcmlvcml0eQogICAgICAgICogW0ludGVnZXJdIFNFU1NJT05fVElNRU9VVCAgICAgICAgICAtIFNlc3Npb24gdGltZW91dAogICAgICAgICogW1N0cmluZ10gIFBfQUxMT1dfQ09OTkVDVElPTlMgICAgICAtIEFsbG93ZWQgY29ubmVjdGlvbiB0eXBlcyBmb3IgIlByaW1hcnkiIHJlcGxpY2EgbW9kZS4gQ2FuIGJlICJSRUFEX1dSSVRFIiBvciAiQUxMIiBvbmx5LgogICAgICAgICogW0FycmF5XSAgIFBfUkVBRF9PTkxZX1JPVVRJTkdfTElTVCAtIExpc3Qgb2YgcmVwbGljYXMgcHJvdmlyaW5nIHJlYWRvbmx5IGFjY2VzcyB3aGVuIHRoaXMgb25lIGlzIHByaW1hcnkuCiAgICAgICAgKiBbU3RyaW5nXSAgU19BTExPV19DT05ORUNUSU9OUyAgICAgIC0gQWxsb3dlZCBjb25uZWN0aW9uIHR5cGVzIGZvciAiU2Vjb25kYXJ5IiByZXBsaWNhIG1vZGUuIENhbiBiZSBvbmUgb2YgIk5PIiwgIlJFQURfT05MWSIsICJBTEwiLgogICAgICAgICogW1N0cmluZ10gIFNfUkVBRF9PTkxZX1JPVVRJTkdfVVJMICAtIFJlcGxpY2EgcmVhZC1vbmx5IHJlcXVlc3RzIGxpc3RlbmVyIFVSTC4gTm9ybWFsbHkgZGVmYXVsdCBzZXJ2ZXIgbGlzdGVuZXIgYXQgcG9ydCAxNDMzIGlzIHVzZWQuCgogICAgLlBBUkFNRVRFUiBQcmVmZXJlbmNlcwogICAgSGFzaCB0YWJsZSBvZiBnZW5lcmFsIGF2YWlsYWJpbGl0eSBncm91cCBwcmVmZXJlbmNlcy4gQWxsIHRoZSBrZXlzIGFyZSBvcHRpb25hbC4gU3VwcG9ydGVkIGVudHJ5IGtleXMgYXJlOgoKICAgICAgICAqIFtTdHJpbmddICBBVVRPTUFURURfQkFDS1VQX1BSRUZFUkVOQ0UgLSBBdXRvbWF0ZWQgYmFja3VwIHByZWZlcmVuY2UuIENhbiBiZSAiUFJJTUFSWSIsICJTRUNPTkRBUllfT05MWSIsICJTRUNPTkRBUlkiIG9yICJOT05FIi4KICAgICAgICAqIFtTdHJpbmddICBGQUlMVVJFX0NPTkRJVElPTl9MRVZFTCAgICAgLSBGYWlsdXJlIGNvbmRpdGlvbiBsZXZlbC4gQ2FuIGJlICIxIiwgIjIiLCAiMyIsICI0IiBvciAiNSIuCiAgICAgICAgKiBbSW50ZWdlcl0gSEVBTFRIX0NIRUNLX1RJTUVPVVQgICAgICAgIC0gUmVwbGljYSBoZWFsdGggY2hlY2sgdGltZW91dC4KCiAgICAuUEFSQU1FVEVSIExpc3RlbmVyRGVmCiAgICBIYXNoIHRhYmxlIGNvbnRhaW5pbmcgYXZhaWxhYmlsaXR5IGdyb3VwIGxpc3RlbmVyIGNvbmZpZ3VyYXRpb24uCgogICAgTWFuZGF0b3J5IGxpc3RlbmVyIGNvbmZpZ3VyYXRpb24gdmFsdWVzIGFyZToKCiAgICAgICAgW1N0cmluZ10gTkFNRSAtIExpc3RlbmVyIG5hbWUuCgogICAgT3B0aW9uYWwgbGlzdGVuZXIgY29uZmlndXJhdGlvbiB2YWx1ZXMgYXJlOgogICAgCiAgICAgICAgW1N0cmluZ10gUE9SVCAtIExpc3RlbmVyIHBvcnQgbnVtYmVyLiBJbnRlZ2VyIHZhbHVlIG1heSBiZSBzdWZmaXhlZCBieSBhICIrIiBzeW1vbCAoc3VjaCBhcyAiNTAyMisiKSB3aGljaCBhbGxvd3MgdGhlIHJvdXRpbmUgdG8KICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0IG5leHQgZnJlZSBwb3J0IHdpdGggbnVtYmVyIGdyZWF0ZXIgb3IgZXF1YWwgdG8gdGhlIHNwZWNpZmllZCB2YWx1ZS4KICAgICAgICBbU3RyaW5nXSBESENQIC0gREhDUCBsaXN0ZW5lciBhZGRyZXNzIGNvbmZpZ3VyYXRpb24gZmxhZy4gV2hlbiBhbnkgdmFsdWUgc3BlY2lmaWVkLCBESENQIGlzIHVzZWQgdG8gY29uZmlndXJlIGxpc3RlbmVyCiAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzIGlzIGFsc28gdGhlIGRlZmF1bHQgYmVoYXZpb3IpLiBBbHNvLCBhIHNwZWNpZmljIGludGVyZmFjZSBmb3IgREhDUCBtYXkgYmUgc3BlY2lmaWVkIGFzIElQX0FERFJFU1MvTUFTSwogICAgICAgICAgICAgICAgICAgICAgICAobGlrZSAiMTkyLjE2OC4xLjAvMjU1LjI1NS4yNTUuMCIpIGFzIGEgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci4KICAgICAgICBbQXJyYXldIFNUQVRJQyAtIFN0YXRpYyBJUCBhZGRyZXNzZXMgdG8gbGlzdGVuLiBJUCBhZGRyZXNzZXMgbWF5IGJlIElQdjQgYWRkcmVzc2VzIGluIHRoZSAiSVBfQUREUkVTUy9NQVNLIiBmb3JtIG9yIElQdjYKICAgICAgICAgICAgICAgICAgICAgICAgYWRkcmVzc2VzIGluIHN0YW5kYXJkIElQdjYgbm90YXRpb24uCgogICAgU2VlIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9mZjg3ODM5OS5hc3B4IHBhZ2UgZm9yIG1vcmUgZGV0YWlscyByZWdhcmRpbmcgYWxsIHRoZSBzdXBwb3J0ZWQgb3B0aW9ucy4KICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kV29ya0RpciwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtBcnJheV0kRGF0YWJhc2VOYW1lcywKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbQXJyYXldJFJlcGxpY2FEZWZzLAogICAgICAgIFtwYXJhbWV0ZXJdCiAgICAgICAgW0hhc2h0YWJsZV0kUHJlZmVyZW5jZXMsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW0hhc2h0YWJsZV0kTGlzdGVuZXJEZWYKICAgICkKCiAgICBpZiAoLW5vdCAoVGVzdC1QYXRoICRXb3JrRGlyKSkgewogICAgICAgIFt2b2lkXShOZXctSXRlbSAtVHlwZSBEaXJlY3RvcnkgJFdvcmtEaXIpCiAgICB9CiAgICAkV29ya0RpciA9IChHZXQtSXRlbSAkV29ya0RpcikuRnVsbE5hbWUKICAgIGlmICgoR2V0LUNoaWxkSXRlbSAtUGF0aCAkV29ya0RpcikuTGVuZ3RoIC1ndCAwKSB7CiAgICAgICAgdGhyb3cgIldvcmtpbmcgZGlyZWN0b3J5ICRXb3JrRGlyIGlzIG5vdCBlbXB0eSIKICAgIH0KCiAgICAkUXVvdGVkREJOYW1lcyA9ICgkRGF0YWJhc2VOYW1lcyB8IEZvckVhY2gtT2JqZWN0IHsgQ29udmVydFRvLVNRTE5hbWUgJF8gfSkgLWpvaW4gIiwgIgoKICAgIGlmICgkUHJlZmVyZW5jZXMgLWVxICRudWxsKSB7CiAgICAgICAgJFByZWZlcmVuY2VzID0gQCgpCiAgICB9CiAgICAkUHJlZnMgPSBAKCkKICAgIGZvcmVhY2goJFByZWYgaW4gJFByZWZlcmVuY2VzKSB7CiAgICAgICAgaWYgKCRQcmVmLktleSAtZXEgJG51bGwpIHsKICAgICAgICAgICAgQ29udGludWUKICAgICAgICB9CiAgICAgICAgaWYgKCRQcmVmLktleSAtZXEgIkFVVE9NQVRFRF9CQUNLVVBfUFJFRkVSRU5DRSIpIHsKICAgICAgICAgICAgJFByZWZzID0gJFByZWZzICsgKFZhbGlkYXRlLU9wdGlvbiAkUHJlZi5LZXksICRQcmVmLlZhbHVlLCBAKCJQUklNQVJZIiwgIlNFQ09OREFSWV9PTkxZIiwgIlNFQ09OREFSWSIsICJOT05FIikgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAkUHJlZi5LZXkpCiAgICAgICAgfSBlbHNlaWYgKCRQcmVmLktleSAtZXEgIkZBSUxVUkVfQ09ORElUSU9OX0xFVkVMIikgewogICAgICAgICAgICAkUHJlZnMgPSAkUHJlZnMgKyAoVmFsaWRhdGUtT3B0aW9uICRQcmVmLktleSwgJFByZWYuVmFsdWUsIEAoIjEiLCAiMiIsICIzIiwgIjQiLCAiNSIpIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgJFByZWYuS2V5KQogICAgICAgIH0gZWxzZWlmICgkUHJlZi5LZXkgLWVxICJIRUFMVEhfQ0hFQ0tfVElNRU9VVCIpIHsKICAgICAgICAgICAgJFByZWZzID0gJFByZWZzICsgKFZhbGlkYXRlLUludE9wdGlvbiAkUHJlZi5LZXksICRQcmVmLlZhbHVlIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgJFByZWYuS2V5KQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRocm93ICJVbmV4cGVjdGVkIHBlZmVyZW5jZXMgb3B0aW9uOiAnJCgkUHJlZi5LZXkpJyIKICAgICAgICB9CiAgICB9CgogICAgJFJlcGxpY2FEZWZpbml0aW9uc0FycmF5ID0gQCgpCiAgICBmb3IgKCRpID0gMDsgJGkgLWx0ICRSZXBsaWNhRGVmcy5MZW5ndGg7ICRpKyspIHsKICAgICAgICAkUkRlZiA9ICRSZXBsaWNhRGVmc1skaV0KICAgICAgICBpZiAoJFJEZWYuR2V0VHlwZSgpLk5hbWUgLW5lICJIYXNodGFibGUiKSB7CiAgICAgICAgICAgIHRocm93ICJBbGwgZWxlbWVudHMgb2YgUmVwbGljYURlZnMgYXJyYXkgc2hvdWxkIGJlIEhhc2h0YWJsZXMiCiAgICAgICAgfQoKICAgICAgICAkUmVwbGljYU9wdHMgPSBAKCkKCiAgICAgICAgIyBNYW5kYXRvcnkgb3B0aW9ucwogICAgICAgICRSZXBsaWNhTmFtZSA9IFZhbGlkYXRlLURlZmluZWRPcHRpb24gIlNFUlZFUl9JTlNUQU5DRSIgJFJEZWZbIlNFUlZFUl9JTlNUQU5DRSJdCiAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLURlZmluZWRPcHRpb24gIkVORFBPSU5UX1VSTCIgJFJEZWZbIkVORFBPSU5UX1VSTCJdIHwgQ29udmVydFRvLVNRTFN0cmluZyB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJFTkRQT0lOVF9VUkwiKQogICAgICAgICRSZXBsaWNhT3B0cyA9ICRSZXBsaWNhT3B0cyArIChWYWxpZGF0ZS1PcHRpb24gIkFWQUlMQUJJTElUWV9NT0RFIiAkUkRlZlsiQVZBSUxBQklMSVRZX01PREUiXSBAKCJTWU5DSFJPTk9VU19DT01NSVQiLCAiQVNZTkNIUk9OT1VTX0NPTU1JVCIpIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIkFWQUlMQUJJTElUWV9NT0RFIikKICAgICAgICAkUmVwbGljYU9wdHMgPSAkUmVwbGljYU9wdHMgKyAoVmFsaWRhdGUtT3B0aW9uICJGQUlMT1ZFUl9NT0RFIiAkUkRlZlsiRkFJTE9WRVJfTU9ERSJdIEAoIkFVVE9NQVRJQyIsICJNQU5VQUwiKSB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJGQUlMT1ZFUl9NT0RFIikKCiAgICAgICAgIyBPcHRpb25hbCBvcHRpb25zCiAgICAgICAgaWYgKCRSRGVmWyJCQUNLVVBfUFJJT1JJVFkiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLUludE9wdGlvbiAiQkFDS1VQX1BSSU9SSVRZIiAkUkRlZlsiQkFDS1VQX1BSSU9SSVRZIl0gfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQkFDS1VQX1BSSU9SSVRZIikKICAgICAgICB9CiAgICAgICAgaWYgKCRSRGVmWyJTRVNTSU9OX1RJTUVPVVQiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLUludE9wdGlvbiAiU0VTU0lPTl9USU1FT1VUIiAkUkRlZlsiU0VTU0lPTl9USU1FT1VUIl0gfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiU0VTU0lPTl9USU1FT1VUIikKICAgICAgICB9CgogICAgICAgICRTZWNvbmRhcnlSb2xlID0gQCgpCiAgICAgICAgaWYgKCRSRGVmWyJTX0FMTE9XX0NPTk5FQ1RJT05TIl0gLW5lICRudWxsKSB7CiAgICAgICAgICAgICRTZWNvbmRhcnlSb2xlID0gJFNlY29uZGFyeVJvbGUgKyAoVmFsaWRhdGUtT3B0aW9uICJTX0FMTE9XX0NPTk5FQ1RJT05TIiAkUkRlZlsiU19BTExPV19DT05ORUNUSU9OUyJdIEAoIk5PIiwgIlJFQURfT05MWSIsICJBTEwiKSB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJBTExPV19DT05ORUNUSU9OUyIpCiAgICAgICAgfQogICAgICAgIGlmICgkUkRlZlsiU19SRUFEX09OTFlfUk9VVElOR19VUkwiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFNlY29uZGFyeVJvbGUgPSAkU2Vjb25kYXJ5Um9sZSArICgkUkRlZlsiU19SRUFEX09OTFlfUk9VVElOR19VUkwiXSB8IENvbnZlcnRUby1TUUxTdHJpbmcgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFNlY29uZGFyeVJvbGUuTGVuZ3RoIC1ndCAwKSB7CiAgICAgICAgICAgICRSZXBsaWNhT3B0cyA9ICRSZXBsaWNhT3B0cyArICgiKCAkKCRTZWNvbmRhcnlSb2xlIC1qb2luICcsICcpICkiIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIlNFQ09OREFSWV9ST0xFIikKICAgICAgICB9CgogICAgICAgICRQcmltYXJ5Um9sZSA9IEAoKQogICAgICAgIGlmICgkUkRlZlsiUF9BTExPV19DT05ORUNUSU9OUyJdIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkUHJpbWFyeVJvbGUgPSAkUHJpbWFyeVJvbGUgKyAoVmFsaWRhdGUtT3B0aW9uICJQX0FMTE9XX0NPTk5FQ1RJT05TIiAkUkRlZlsiUF9BTExPV19DT05ORUNUSU9OUyJdIEAoIlJFQURfV1JJVEUiLCAiQUxMIikgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFJEZWZbIlBfUkVBRF9PTkxZX1JPVVRJTkdfTElTVCJdIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkUHJpbWFyeVJvbGUgPSAkUHJpbWFyeVJvbGUgKyAoKCgkUkRlZlsiUF9SRUFEX09OTFlfUk9VVElOR19MSVNUIl0gfCBGb3JFYWNoLU9iamVjdCB7IENvbnZlcnRUby1TUUxTdHJpbmcgJF8gfSkgLWpvaW4gJywgJykgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFByaW1hcnlSb2xlLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICAgICAkUmVwbGljYU9wdHMgPSAkUmVwbGljYU9wdHMgKyAoIiggJCgkUHJpbWFyeVJvbGUgLWpvaW4gJywgJykgKSIgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiUFJJTUFSWV9ST0xFIikKICAgICAgICB9CgogICAgICAgICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSA9ICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSArCiAgICAgICAgICAgICMgIFRDUDovL2JyYXZvLm11cmFuby5sb2NhbDo1MDIyCiAgICAgICAgICAgICJOJChDb252ZXJ0VG8tU1FMU3RyaW5nICRSZXBsaWNhTmFtZSkgV0lUSCAoJCgkUmVwbGljYU9wdHMgLWpvaW4gJywgJykpIgogICAgfQogICAgJFJlcGxpY2FEZWZpbml0aW9ucyA9ICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSAtam9pbiAiLGByYG4gICAgICAgICI7CgogICAgaWYgKCRMaXN0ZW5lckRlZlsiREhDUCJdIC1uZSAkbnVsbCkgewogICAgICAgIGlmICgkTGlzdGVuZXJEZWZbIkRIQ1AiXS5tYXRjaGVzKCJcZCtcLlxkK1wuXGQrXC5cZCsvXGQrXC5cZCtcLlxkK1wuXGQrIikpIHsKICAgICAgICAgICAgKCRJcEFkZHIsICRNYXNrKSA9ICRMaXN0ZW5lckRlZlsiREhDUCJdIC1zcGxpdCAiLyIKICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICJESENQIE9OICggJElwQWRkciwgJE1hc2sgKSIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAkTGlzdGVuZXJBZGRyID0gIkRIQ1AiCiAgICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgICBbYXJyYXldJElQQWRkcmVzc2VzID0gJExpc3RlbmVyRGVmWyJTVEFUSUMiXQogICAgICAgIGlmICgoJElQQWRkcmVzc2VzIC1lcSAkbnVsbCkgLW9yICgkSVBBZGRyZXNzZXMuQ291bnQgLWVxIDApKSB7CiAgICAgICAgICAgICRMaXN0ZW5lckFkZHIgPSAiREhDUCIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAkQ29udmVydGVkT3B0cyA9IEAoKQogICAgICAgICAgICBmb3JlYWNoICgkSXBPcHRpb24gaW4gJElQQWRkcmVzc2VzKSB7CiAgICAgICAgICAgICAgICAjIElQdjQKICAgICAgICAgICAgICAgIGlmICgkSXBPcHRpb24gLW1hdGNoICJcZCtcLlxkK1wuXGQrXC5cZCsvXGQrXC5cZCtcLlxkK1wuXGQrIikgewogICAgICAgICAgICAgICAgICAgICgkSXBBZGRyLCAkTWFzaykgPSAkSXBPcHRpb24gLXNwbGl0ICIvIgogICAgICAgICAgICAgICAgICAgICRDb252ZXJ0ZWRPcHRzID0gJENvbnZlcnRlZE9wdHMgKyAiKCAkKENvbnZlcnRUby1TUUxTdHJpbmcgJElwQWRkciksICQoQ29udmVydFRvLVNRTFN0cmluZyAkTWFzaykgKSIKICAgICAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgIyBJUHY2CiAgICAgICAgICAgICAgICBpZiAoJElwT3B0aW9uIC1tYXRjaCAiXigoKD89KD8+Lio/OjopKD8hLio6OikpKSg6Oik/KFswLTlBLUZdezEsNH06Oj8pezAsNX18KFswLTlBLUZdezEsNH06KXs2fSkoXDIoWzAtOUEtRl17MSw0fSg6Oj98JCkpezAsMn18KCgyNVswLTVdfCgyWzAtNF18MVxkfFsxLTldKT9cZCkoXC58JCkpezR9fFswLTlBLUZdezEsNH06WzAtOUEtRl17MSw0fSkoPzwhW146XTp8XC4pXHoiKSB7CiAgICAgICAgICAgICAgICAgICAgJENvbnZlcnRlZE9wdHMgPSAkQ29udmVydGVkT3B0cyArICIoICQoQ29udmVydFRvLVNRTFN0cmluZyAkSXBPcHRpb24pICkiCiAgICAgICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRocm93ICJNYWxmb3JtZWQgSVB2NC9JUHY2IGFkZHJlc3M6ICRJcE9wdGlvbiIKICAgICAgICAgICAgfQogICAgICAgICAgICAkTGlzdGVuZXJBZGRyID0gIklQICggJCgkQ29udmVydGVkT3B0cyAtam9pbiAnLCAnKSApIgogICAgICAgIH0KICAgIH0KICAgIGlmICgoJExpc3RlbmVyRGVmWyJOQU1FIl0gLWVxICRudWxsKSAtb3IgKCRMaXN0ZW5lckRlZlsiTkFNRSJdIC1tYXRjaCAiXlxzKiQiKSkgewogICAgICAgIHRocm93ICJMaXN0ZW5lciBuYW1lIGlzIHJlcXVpcmVkIgogICAgfQogICAgaWYgKC1ub3QgKCRMaXN0ZW5lckRlZlsiTkFNRSJdIC1tYXRjaCAiXltBLVphLXowLTlcLl9cLV0rJCIpKSB7CiAgICAgICAgdGhyb3cgIklsbGVnYWwgbGlzdGVuZXIgbmFtZS4gSXQgY2FuIGNvbnRhaW4gb25seSBhbHBoYW51bWVyaWMgY2hhcmFjdGVycywgZGFzaGVzICgtKSwgYW5kIGh5cGhlbnMgKF8pLCBpbiBhbnkgb3JkZXIuIgogICAgfQogICAgJFBvcnQgPSAkbnVsbAogICAgaWYgKCRMaXN0ZW5lckRlZlsiUE9SVCJdIC1uZSAkbnVsbCkgewogICAgICAgIGlmICgkTGlzdGVuZXJEZWZbIlBPUlQiXSAtbWF0Y2ggIlxkK1wrIikgewogICAgICAgICAgICAkU3RhcnRpbmdQb3J0ID0gJExpc3RlbmVyRGVmWyJQT1JUIl0gLXJlcGxhY2UgIlwrIiwgIiIKICAgICAgICAgICAgJFBvcnQgPSBHZXQtTmV4dEZyZWVQb3J0ICRTdGFydGluZ1BvcnQKICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICRMaXN0ZW5lckFkZHIgKyAiLCBQT1JUID0gJFBvcnQiCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKCRMaXN0ZW5lckRlZlsiUE9SVCJdIC1tYXRjaCAiXGQrIikgewogICAgICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICRMaXN0ZW5lckFkZHIgKyAiLCBQT1JUID0gJCgkTGlzdGVuZXJEZWZbIlBPUlQiXSkiCiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyAiSW52YWxpZCBwb3J0IHZhbHVlOiAkKCRMaXN0ZW5lckRlZlsiUE9SVCJdKSIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgICRMaXN0ZW5lciA9ICJMSVNURU5FUiAnJCgkTGlzdGVuZXJEZWZbIk5BTUUiXSknICggV0lUSCAkTGlzdGVuZXJBZGRyICkiCgogICAgJE5hbWUgfCBPdXQtRmlsZSAiJFdvcmtEaXJcYXZncm91cC5uYW1lIgogICAgCiAgICBmb3IgKCRpID0gMDsgJGkgLWx0ICREYXRhYmFzZU5hbWVzLkxlbmd0aDsgJGkrKykgewogICAgICAgICREYXRhQmFzZU5hbWUgPSAkRGF0YWJhc2VOYW1lc1skaV0KICAgICAgICAkRGF0YUJhc2VOYW1lIHwgT3V0LUZpbGUgIiRXb3JrRGlyXGRiJGkubmFtZSIKICAgICAgICBOZXctU1FMRGF0YWJhc2UgJERhdGFCYXNlTmFtZQogICAgICAgICRCYWNrdXBEYiA9ICJCQUNLVVAgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcZGIkaS5iYWsiKSBXSVRIIE5PRk9STUFULCBJTklULCBOQU1FID0gTidGdWxsIERhdGFiYXNlIEJhY2t1cCcsIFNLSVAsIE5PUkVXSU5ELCBOT1VOTE9BRCwgU1RBVFMgPSAxMAogICAgICAgICAgICAgICAgICAgICBHTyIKICAgICAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwRGIpCiAgICAgICAgJEJhY2t1cExvZyA9ICJCQUNLVVAgTE9HICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgVE8gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXGRiJHtpfS5sb2cuYmFrIikgV0lUSCBOT0ZPUk1BVCwgSU5JVCwgIE5BTUUgPSBOJ1RyYW5zYWN0aW9uIExvZyAgQmFja3VwJywgU0tJUCwgTk9SRVdJTkQsIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgICAgICBHTyIKICAgICAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwTG9nKQogICAgfQogICAgJFJlcGxpY2FEZWZpbml0aW9uc0FycmF5ID0gQCgpCiAgICBpZiAoJFByZWZzLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICRQcmVmc0xpbmUgPSAiV0lUSCAoICQoJFByZWZzIC1qb2luICcsICcpICkiCiAgICB9IGVsc2UgewogICAgICAgICRQcmVmc0xpbmUgPSAiIgogICAgfQogICAgJFNRTCA9ICJDUkVBVEUgQVZBSUxBQklMSVRZIEdST1VQICQoQ29udmVydFRvLVNRTE5hbWUgJE5hbWUpICRQcmVmc0xpbmUKICAgICAgICAgICAgICAgIEZPUiBEQVRBQkFTRSAkUXVvdGVkREJOYW1lcwogICAgICAgICAgICAgICAgUkVQTElDQSBPTmByYG4gICAgICAgICRSZXBsaWNhRGVmaW5pdGlvbnMKICAgICAgICAgICAgICAgICRMaXN0ZW5lcjsKICAgICIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRTUUwpCiAgICByZXR1cm4gJFBvcnQKfQoKZnVuY3Rpb24gTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXBSZXBsaWNhIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgQWx3YXlzT24gYXZhaWxhYmlsaXR5IGdyb3VwIHNlY29uZGFyeSByZXBsaWNhCgogICAgLkRFU0NSSVBUSU9OCiAgICBDcmVhdGVzIEFsd2F5c09uIGF2YWlsYWJpbGl0eSBncm91cCBzZWNvbmRhcnkgcmVwbGljYSBiYXNlZCBvbiBpbmZvcm1hdGlvbiBwcm92aWRlZCB0byBhbmQgYnkgTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXAuCgogICAgLlBBUkFNRVRFUiBXb3JrRGlyCiAgICBXb3JraW5nIGRpcmVjdG9yeSB3aGljaCB3YXMgdHJhbnNmZXJyZWQgZnJvbSB0aGUgcHJpbWFyeSByZXBsaWNhLgogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFdvcmtEaXIKICAgICkKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIldvcmsgZGlyICckV29ya0Rpcicgbm90IGZvdW5kIgogICAgfQogICAgJFdvcmtEaXJPYmogPSBHZXQtSXRlbSAtUGF0aCAkV29ya0RpcgogICAgJFdvcmtEaXIgPSAkV29ya0Rpck9iai5GdWxsTmFtZQogICAgJEdyb3VwTmFtZSA9IEdldC1Db250ZW50ICRXb3JrRGlyT2JqLkdldEZpbGVzKCJhdmdyb3VwLm5hbWUiKS5GdWxsTmFtZQoKICAgICRKb2luR3JvdXAgPSAiQUxURVIgQVZBSUxBQklMSVRZIEdST1VQICQoQ29udmVydFRvLVNRTE5hbWUgJEdyb3VwTmFtZSkgSk9JTgogICAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkSm9pbkdyb3VwKQoKICAgIGZvciAoJGkgPSAwOyA7ICRpKyspIHsKICAgICAgICAkRmlsZSA9ICRXb3JrRGlyT2JqLkdldEZpbGVzKCJkYiRpLm5hbWUiKQogICAgICAgIGlmICgtbm90ICRGaWxlKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICAkRGF0YUJhc2VOYW1lID0gR2V0LUNvbnRlbnQgJFdvcmtEaXJPYmouR2V0RmlsZXMoImRiJGkubmFtZSIpLkZ1bGxOYW1lCiAgICAgICAgJFJlc3RvcmVEYiA9ICJSRVNUT1JFIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgRlJPTSBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcZGIkaS5iYWsiKSBXSVRIIEZJTEUgPSAxLCBOT1JFQ09WRVJZLCBOT1VOTE9BRCwgUkVQTEFDRSwgU1RBVFMgPSA1CiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVEYikKICAgICAgICAkUmVzdG9yZUxvZyA9ICJSRVNUT1JFIExPRyAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIEZST00gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXGRiJGkubG9nLmJhayIpIFdJVEggRklMRSA9IDEsIE5PUkVDT1ZFUlksIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVMb2cpCiAgICAgICAgJEFsdGVyREIgPSAiQUxURVIgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBTRVQgSEFEUiBBVkFJTEFCSUxJVFkgR1JPVVAgPSAkKENvbnZlcnRUby1TUUxOYW1lICRHcm91cE5hbWUpCiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJEFsdGVyREIpCiAgICB9Cn0KCmZ1bmN0aW9uIE5ldy1SZXBsaWNhT3B0aW9uIHsKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSwgVmFsdWVGcm9tUGlwZWxpbmUgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kVmFsdWUKICAgICkKICAgIHJldHVybiAiJE5hbWUgPSAkVmFsdWUiCn0KCmZ1bmN0aW9uIFZhbGlkYXRlLU9wdGlvbiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDaGVja3MgdGhhdCB0aGUgdmFsdWUgaXMgb25lIG9mIGFsbG93ZWQgdmFsdWVzCgogICAgLkRFU0NSSVBUSU9OCiAgICBDaGVja3MgdGhhdCB0aGUgdmFsdWUgaXMgb25lIG9mIGFsbG93ZWQgdmFsdWVzIG9yIHRocm93cyBleGNlcHRpb24gb3RoZXJ3aXNlLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCgogICAgLlBBUkFNRVRFUiBBbGxvd2VkCiAgICBMaXN0IG9mIGFsbG93ZWQgb3B0aW9uIHZhbHVzLgogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJE5hbWUsCiAgICAgICAgW1N0cmluZ10kVmFsdWUsCiAgICAgICAgW0FycmF5XSRBbGxvd2VkCiAgICApCiAgICBpZiAoKCRWYWx1ZSAtZXEgJG51bGwpIC1vciAoJFZhbHVlIC1lcSAiIikpIHsKICAgICAgICB0aHJvdyAiTm8gdmFsdWUgd2FzIHByb3ZpZGVkIGZvciAkTmFtZSIKICAgIH0KICAgIGZvcmVhY2ggKCRWIGluICRBbGxvd2VkKSB7CiAgICAgICAgaWYgKCRWIC1lcSAkVmFsdWUpIHsKICAgICAgICAgICAgcmV0dXJuICRWYWx1ZQogICAgICAgIH0KICAgIH0KICAgIHRocm93ICJQcm92aWRlZCB2YWx1ZSAnJFZhbHVlJyBmb3IgJE5hbWUgaXMgbm90IG9uZSBvZiAkKCRBbGxvd2VkIC1qb2luICcsICcpIgp9CgpmdW5jdGlvbiBWYWxpZGF0ZS1JbnRPcHRpb24gewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ2hlY2tzIHRoYXQgdGhlIHZhbHVlIGlzIGludGVnZXIKCiAgICAuREVTQ1JJUFRJT04KICAgIENoZWNrcyB0aGF0IHRoZSB2YWx1ZSBpcyBpbnRlZ2VyLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kTmFtZSwKICAgICAgICBbcGFyYW1ldGVyXQogICAgICAgIFtTdHJpbmddJFZhbHVlCiAgICApCiAgICBpZiAoKCRWYWx1ZSAtZXEgJG51bGwpIC1vciAoJFZhbHVlIC1lcSAiIikpIHsKICAgICAgICB0aHJvdyAiTm8gdmFsdWUgd2FzIHByb3ZpZGVkIGZvciAkTmFtZSIKICAgIH0KICAgIGlmICgtbm90ICgiJFZhbHVlIiAtbWF0Y2ggIl5bKy1dP1xkKyQiKSkgewogICAgICAgIHRocm93ICJQcm92aWRlZCB2YWx1ZSAnJFZhbHVlJyBmb3IgJE5hbWUgaXMgbm90IGEgbnVtYmVyIgogICAgfQogICAgcmV0dXJuICRWYWx1ZQp9CgpmdW5jdGlvbiBWYWxpZGF0ZS1EZWZpbmVkT3B0aW9uIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENoZWNrcyB0aGF0IHRoZSB2YWx1ZSBpcyBub3QgbnVsbAoKICAgIC5ERVNDUklQVElPTgogICAgQ2hlY2tzIHRoYXQgdGhlIHZhbHVlIGlzIG5vdCBudWxsLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kTmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICRmYWxzZSldCiAgICAgICAgW1N0cmluZ10kVmFsdWUKICAgICkKICAgIGlmICgoJFZhbHVlIC1lcSAkbnVsbCkgLW9yICgkVmFsdWUgLWVxICIiKSkgewogICAgICAgIHRocm93ICJObyB2YWx1ZSB3YXMgcHJvdmlkZWQgZm9yICROYW1lIgogICAgfQogICAgcmV0dXJuICRWYWx1ZQp9CgoKCg==", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlclBvd2VyU2hlbGxNb2R1bGUgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJwogICAgKQogICAgYmVnaW4gewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbgogICAgfQogICAgZW5kIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24gLUVuZAogICAgfQogICAgcHJvY2VzcyB7CiAgICAgICAgdHJhcCB7CiAgICAgICAgICAgICYkVHJhcEhhbmRsZXIKICAgICAgICB9CgogICAgICAgIGlmICgoR2V0LU1vZHVsZSBTUUxQUyAtTGlzdEF2YWlsYWJsZSkgLW5lICRudWxsKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiTW9kdWxlIFNRTFNQIGFscmVhZHkgaW5zdGFsbGVkLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcVG9vbHMnKQogICAgICAgIH0KICAgICAgICAKICAgICAgICAkRmlsZUxpc3QgPSBAKAogICAgICAgICAgICAnU1FMU3lzQ2xyVHlwZXMubXNpJywKICAgICAgICAgICAgJ1NoYXJlZE1hbmFnZW1lbnRPYmplY3RzLm1zaScsCiAgICAgICAgICAgICdQb3dlclNoZWxsVG9vbHMubXNpJwogICAgICAgICkKCiAgICAgICAgZm9yZWFjaCAoJE1zaUZpbGUgaW4gJEZpbGVMaXN0KSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVHJ5aW5nIHRvIGluc3RhbGwgJyRNc2lGaWxlJyAuLi4iCiAgICAgICAgICAgICRNc2lQYXRoID0gSm9pbi1QYXRoICRTZXR1cFJvb3QgJE1zaUZpbGUKICAgICAgICAgICAgaWYgKFtJTy5GaWxlXTo6RXhpc3RzKCRNc2lQYXRoKSkgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJTdGFydGluZyBtc2lleGUgLi4uIgogICAgICAgICAgICAgICAgJFJlc3VsdCA9IEV4ZWMgLUZpbGVQYXRoICJtc2lleGVjLmV4ZSIgLUFyZ3VtZW50TGlzdCBAKCcvaScsICJgIiRNc2lQYXRoYCIiLCAnL3F1aWV0JykgLVBhc3NUaHJ1CiAgICAgICAgICAgICAgICBpZiAoJFJlc3VsdC5FeGl0Q29kZSAtbmUgMCkgewogICAgICAgICAgICAgICAgICAgIHRocm93ICgiSW5zdGFsbGF0aW9uIG9mIE1TSSBwYWNrYWdlICckTXNpUGF0aCcgZmFpbGVkIHdpdGggZXJyb3IgY29kZSAnJCgkUmVzdWx0LkV4aXRDb2RlKSciKQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJGaWxlICckTXNpUGF0aCcgbm90IGZvdW5kLiIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQoKCgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgUGF0aCB0byBmb2xkZXIgd2hlcmUgbXNpIGZpbGVzIGZvciBhZGRpdGlvbmFsIFNRTCBmZWF0dXJlcyBhcmUgbG9jYXRlZAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJywKCiAgICAgICAgIyBQYXRoIHRvIGZvbGRlciB3aGVyZSBtc2kgZmlsZXMgZm9yIGFkZGl0aW9uYWwgU1FMUFMgbW9kdWxlIGFyZSBsb2NhdGVkCiAgICAgICAgW1N0cmluZ10gJFNxbHBzU2V0dXBSb290ID0gJycsCgogICAgICAgIFtTdHJpbmddICRNdXJhbm9GaWxlU2hhcmUgPSAnJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIERvbWFpbiBuYW1lCiAgICAgICAgW1N0cmluZ10gJFNRTFNlcnZpY2VVc2VyRG9tYWluID0gJ2ZjLWFjbWUubG9jYWwnLAoKICAgICAgICAjIChSRVFVSVJFRCkgVXNlciBuYW1lIGZvciB0aGUgYWNjb3VudCB3aGljaCB3aWxsIGJlIHVzZWQgYnkgU1FMIHNlcnZpY2UKICAgICAgICBbU3RyaW5nXSAkU1FMU2VydmljZVVzZXJOYW1lID0gJ0FkbWluaXN0cmF0b3InLAoKICAgICAgICAjIChSRVFVSVJFRCkgUGFzc3dvcmQgZm9yIHRoYXQgdXNlcgogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlclBhc3N3b3JkID0gJ1BAc3N3MHJkJywKCiAgICAgICAgW1N3aXRjaF0gJFVwZGF0ZUVuYWJsZWQKICAgICkKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcMjAxMicpCiAgICAgICAgfQoKICAgICAgICAkRXh0cmFPcHRpb25zID0gQHt9CgogICAgICAgIGlmICgkVXBkYXRlRW5hYmxlZCkgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJHRydWV9CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJGZhbHNlfQogICAgICAgIH0KCiAgICAgICAgTmV3LVNRTFNlcnZlckZvckFPQUcgYAogICAgICAgICAgICAtU2V0dXBSb290ICRTZXR1cFJvb3QgYAogICAgICAgICAgICAtU1FMU3ZjVXNyRG9tYWluICRTUUxTZXJ2aWNlVXNlckRvbWFpbiBgCiAgICAgICAgICAgIC1TUUxTdmNVc3JOYW1lICRTUUxTZXJ2aWNlVXNlck5hbWUgYAogICAgICAgICAgICAtU1FMU3ZjVXNyUGFzc3dvcmQgJFNRTFNlcnZpY2VVc2VyUGFzc3dvcmQgYAogICAgICAgICAgICAtRXh0cmFPcHRpb25zICRFeHRyYU9wdGlvbnMKICAgIH0KfQoKCgpmdW5jdGlvbiBJbml0aWFsaXplLUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXAgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnRQYXNzd29yZCwKICAgICAgICBbU3RyaW5nXSAkU3FsU2VydmljZUFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICRQcmltYXJ5Tm9kZSwKICAgICAgICBbU3RyaW5nXSAkU2hhcmVOYW1lID0gJ1NoYXJlZFdvcmtEaXInCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgJFNoYXJlTmV0d29ya1BhdGggPSAnXFwnICsgJFByaW1hcnlOb2RlICsgJ1wnICsgJFNoYXJlTmFtZQoKICAgICAgICAkRG9tYWluQWRtaW5BY2NvdW50Q3JlZHMgPSBOZXctQ3JlZGVudGlhbCBgCiAgICAgICAgICAgIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJERvbWFpbkFkbWluQWNjb3VudE5hbWUiIGAKICAgICAgICAgICAgLVBhc3N3b3JkICIkRG9tYWluQWRtaW5BY2NvdW50UGFzc3dvcmQiCgogICAgICAgICRGdW5jdGlvbnNGaWxlID0gRXhwb3J0LUZ1bmN0aW9uICdHZXQtTmV4dEZyZWVQb3J0JywgJ0luaXRpYWxpemUtQWx3YXlzT24nCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICBgJF8KICAgIGV4aXQgMQp9CgpJbXBvcnQtTW9kdWxlIENvcmVGdW5jdGlvbnMKCldyaXRlLUxvZyAiSW1wb3J0aW5nIGZ1bmN0aW9ucyBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ0luaXRpYWxpemUtQWx3YXlzT24nIC4uLiIKYCRYbWxGaWxlID0gW0lPLlBhdGhdOjpDb21iaW5lKCIkU2hhcmVOZXR3b3JrUGF0aCIsICJgJChgJEVudjpDb21wdXRlck5hbWUpLnhtbCIpCldyaXRlLUxvZyAiT3V0cHV0IFhNTCBmaWxlIGlzICdgJFhtbEZpbGUnIgpJbml0aWFsaXplLUFsd2F5c09uIHwgRXhwb3J0LUNsaVhtbCAtUGF0aCBgJFhtbEZpbGUKIkAgLUNyZWRlbnRpYWwgJERvbWFpbkFkbWluQWNjb3VudENyZWRzIC1Ob0Jhc2U2NAogICAgfQp9CgoKZnVuY3Rpb24gTmV3LVNoYXJlZEZvbGRlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKQogICAgICAgIFtTdHJpbmddICRTaGFyZVBhdGggPSBbSU8uUGF0aF06OkNvbWJpbmUoJEVudjpTeXN0ZW1Ecml2ZSArICdcJywgJ1NoYXJlZFdvcmtEaXInKSwKCiAgICAgICAgIyAoT1BUSU9OQUwpCiAgICAgICAgW1N0cmluZ10gJFNoYXJlTmFtZSA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlID0gJyAnCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBzY3JpcHQgcnVucyBvbiBwcmltYXJ5IG5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZyBzY3JpcHQuIgogICAgICAgICAgICByZXR1cm4KICAgICAgICB9CgogICAgICAgIGlmICgkU2hhcmVOYW1lIC1lcSAnJykgewogICAgICAgICAgICAkU2hhcmVOYW1lID0gW0lPLlBhdGhdOjpHZXRGaWxlTmFtZVdpdGhvdXRFeHRlbnNpb24oJFNoYXJlUGF0aCkKICAgICAgICB9CgogICAgICAgIFdyaXRlLUxvZ0RlYnVnICJTaGFyZVBhdGggPSAnJFNoYXJlUGF0aCciCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIlNoYXJlTmFtZSA9ICckU2hhcmVOYW1lJyIKCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgc2hhcmUgJyRTaGFyZU5hbWUnIgogICAgICAgICAgICAkbnVsbCA9IEdldC1TbWJTaGFyZSAtTmFtZSAkU2hhcmVOYW1lIC1FcnJvckFjdGlvbiAnU3RvcCcKICAgICAgICAgICAgJG51bGwgPSBSZW1vdmUtU21iU2hhcmUgLU5hbWUgJFNoYXJlTmFtZSAtRm9yY2UKICAgICAgICAgICAgd3JpdGUtTG9nICJTaGFyZSAnJFNoYXJlTmFtZScgcmVtb3ZlZC4iCiAgICAgICAgfQogICAgICAgIGNhdGNoIHsKICAgICAgICAgICAgV3JpdGUtTG9nV2FybmluZyAiU2hhcmUgJyRTaGFyZU5hbWUnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgZm9sZGVyICckU2hhcmVQYXRoIgogICAgICAgICAgICAkbnVsbCA9IEdldC1JdGVtIC1QYXRoICRTaGFyZVBhdGggLUVycm9yQWN0aW9uICdTdG9wJwogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICRTaGFyZVBhdGggLVJlY3Vyc2UgLUZvcmNlCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRm9sZGVyICckU2hhcmVQYXRoJyByZW1vdmVkLiIKICAgICAgICB9CiAgICAgICAgY2F0Y2ggewogICAgICAgICAgICBXcml0ZS1Mb2dXYXJuaW5nICJGb2xkZXIgJyRTaGFyZVBhdGgnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgJG51bGwgPSBOZXctSXRlbSAtUGF0aCAkU2hhcmVQYXRoIC1JdGVtVHlwZSBDb250YWluZXIgLUZvcmNlCiAgICAgICAgICAgICAgICAKICAgICAgICAkbnVsbCA9IE5ldy1TbWJTaGFyZSAtUGF0aCAkU2hhcmVQYXRoIGAKICAgICAgICAgICAgLU5hbWUgJFNoYXJlTmFtZSBgCiAgICAgICAgICAgIC1GdWxsQWNjZXNzICJFdmVyeW9uZSIgYAogICAgICAgICAgICAtRGVzY3JpcHRpb24gIlNoYXJlZCBmb2xkZXIgZm9yIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cCBzZXR1cC4iCgogICAgICAgIHJldHVybiAnXFwnICsgJEVudjpDb21wdXRlck5hbWUgKyAnXCcgKyAkU2hhcmVOYW1lCiAgICB9Cn0KCgoKZnVuY3Rpb24gTmV3LURhdGFiYXNlRm9yQU9BRyB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJERhdGFiYXNlTmFtZSwKICAgICAgICBbU3RyaW5nXSAkRG9tYWluTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlck5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJQYXNzd29yZAogICAgKQoKICAgICRDcmVkcyA9IE5ldy1DcmVkZW50aWFsIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJFVzZXJOYW1lIiAtUGFzc3dvcmQgIiRVc2VyUGFzc3dvcmQiCgogICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gJ0ludm9rZS1TUUxUZXh0JywgJ0NvbnZlcnRUby1TUUxOYW1lJywgJ0NvbnZlcnRUby1TUUxTdHJpbmcnLCAnTmV3LVNRTERhdGFiYXNlJwoKICAgIFN0YXJ0LVBvd2VyU2hlbGxQcm9jZXNzIEAiCnRyYXAgewogICAgYCRfCiAgICBleGl0IDEKfQoKSW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zCgpXcml0ZS1Mb2cgIkltcG9ydGluZyBmdW5jdGlvbnMgZnJvbSBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1TUUxEYXRhYmFzZScgLi4uIgpOZXctU1FMRGF0YWJhc2UgJERhdGFiYXNlTmFtZQoiQCAtQ3JlZGVudGlhbCAkQ3JlZHMgLU5vQmFzZTY0Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHUHJpbWFyeVJlcGxpY2EgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKSBOYW1lIG9mIHRoZSBuZXcgQXZhaWxhYmlsaXR5IEdyb3VwLiBJZiBub3Qgc3BlY2lmaWVkIHRoZW4gZGVmYXVsdCBuYW1lIHdpbGwgYmUgdXNlZC4KICAgICAgICBbU3RyaW5nXSAkR3JvdXBOYW1lID0gJ011cmFub0FHJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICROb2RlTGlzdCwKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGUgbmFtZSB0aGF0IHdpbGwgYmUgcHJpbWFyeSBmb3Igc2VsZWN0ZWQgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nXSAkUHJpbWFyeU5vZGUsCgogICAgICAgICMgKFJFUVVJUkVEKSBEYXRhYmFzZSBsaXN0IHRoYXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICREYXRhYmFzZUxpc3QsCgogICAgICAgICMgKFJFUVVJUkVEKSBMaXN0ZW5lciBuYW1lIHRoYXQgd2lsbCBiZSB1c2VkIGJ5IGNsaWVudHMgdG8gY29ubmVjdCB0byBkYXRhYmFzZXMgaW4gdGhhdCBBRwogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyTmFtZSA9ICdNdXJhbm9BR19MaXN0ZW5lcicsCgogICAgICAgICMgKFJFUVVJUkVEKSBJUCBhZGRyZXNzIG9mIHRoZSBsaXN0ZW5lcgogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVySVAsCgogICAgICAgIFtTdHJpbmddICRMaXN0ZW5lcklQTWFzayA9ICcyNTUuMjU1LjI1NS4wJywKCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyUG9ydCA9ICc1MDIzJywKCiAgICAgICAgIyBTeW5jIE1vZGUgTm9kZSBMaXN0CiAgICAgICAgW1N0cmluZ1tdXSAkU3luY01vZGVOb2RlTGlzdCwKCiAgICAgICAgW1N0cmluZ10gJFNoYXJlZFdvcmtEaXIgPSAnU2hhcmVkV29ya0RpcicsCgogICAgICAgIFtTdHJpbmddICRDbGlYbWxGaWxlID0gJycsCgogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlclBhc3N3b3JkCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJQcmltYXJ5IG5vZGU6ICckKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkpJyIKICAgICAgICBXcml0ZS1Mb2cgIkN1cnJlbnQgbm9kZTogJyQoKCRFbnY6Q29tcHV0ZXJOYW1lKS5Ub0xvd2VyKCkpJyIKCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICQoJEVudjpDb21wdXRlck5hbWUpLlRvTG93ZXIoKSkgewogICAgICAgICAgICBXcml0ZS1Mb2cgIlRoaXMgZnVuY3Rpb24gd29ya3Mgb24gUHJpbWFyeU5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZy4iCiAgICAgICAgICAgIHJldHVybgogICAgICAgIH0KCiAgICAgICAgaWYgKCRDbGlYbWxGaWxlIC1lcSAnJykgewogICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ID0gQCgpCiAgICAgICAgICAgIGZvcmVhY2ggKCROb2RlIGluICROb2RlTGlzdCkgewogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAkTm9kZUVuZHBvaW50UG9ydCA9IEltcG9ydC1DbGlYbWwgLVBhdGggIlxcJFByaW1hcnlOb2RlXFNoYXJlZFdvcmtEaXJcJE5vZGUueG1sIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2F0Y2ggewogICAgICAgICAgICAgICAgICAgIFdyaXRlLUxvZyAiVXNpbmcgZGVmYXVsdCBlbmRwb2ludCBwb3J0IDUwMjIiCiAgICAgICAgICAgICAgICAgICAgJE5vZGVFbmRwb2ludFBvcnQgPSA1MDIyCiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uID0gQHsKICAgICAgICAgICAgICAgICAgICAiU0VSVkVSX0lOU1RBTkNFIiA9ICIkTm9kZSI7CiAgICAgICAgICAgICAgICAgICAgIkVORFBPSU5UX1VSTCIgPSAiVENQOi8vJHtOb2RlfToke05vZGVFbmRwb2ludFBvcnR9IjsKICAgICAgICAgICAgICAgICAgICAiQVZBSUxBQklMSVRZX01PREUiID0gIkFTWU5DSFJPTk9VU19DT01NSVQiOwogICAgICAgICAgICAgICAgICAgICJGQUlMT1ZFUl9NT0RFIj0iTUFOVUFMIjsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZiAoJFN5bmNNb2RlTm9kZUxpc3QgLWNvbnRhaW5zICROb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBpbiBTeW5jTW9kZU5vZGVMaXN0IgogICAgICAgICAgICAgICAgICAgICRSZXBsaWNhRGVmaW5pdGlvblsnQVZBSUxBQklMSVRZX01PREUnXSA9ICJTWU5DSFJPTk9VU19DT01NSVQiCiAgICAgICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uWydGQUlMT1ZFUl9NT0RFJ10gPSAiQVVUT01BVElDIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBOT1QgaW4gU3luY01vZGVOb2RlTGlzdCIKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ICs9IEAoJFJlcGxpY2FEZWZpbml0aW9uKQogICAgICAgICAgICB9CgogICAgICAgICAgICAkUHJlZmVyZW5jZXMgPSBAe30KCiAgICAgICAgICAgICRMaXN0ZW5lckRlZmluaXRpb24gPSBAewogICAgICAgICAgICAgICAgIk5BTUUiPSRMaXN0ZW5lck5hbWU7CiAgICAgICAgICAgICAgICAiUE9SVCIgPSAiJExpc3RlbmVyUG9ydCI7CiAgICAgICAgICAgICAgICAiU1RBVElDIiA9ICIkTGlzdGVuZXJJUC8kTGlzdGVuZXJJUE1hc2siCiAgICAgICAgICAgIH0KCiAgICAgICAgICAgICRQYXJhbWV0ZXJzID0gQHsKICAgICAgICAgICAgICAgICdXb3JrRGlyJyA9ICJcXCRQcmltYXJ5Tm9kZVwkU2hhcmVkV29ya0RpciI7CiAgICAgICAgICAgICAgICAnTmFtZScgPSAkR3JvdXBOYW1lOwogICAgICAgICAgICAgICAgJ0RhdGFiYXNlTmFtZXMnID0gJERhdGFiYXNlTGlzdDsKICAgICAgICAgICAgICAgICdSZXBsaWNhRGVmcycgPSAkUmVwbGljYURlZmluaXRpb25MaXN0OwogICAgICAgICAgICAgICAgJ1ByZWZlcmVuY2VzJyA9ICRQcmVmZXJlbmNlczsKICAgICAgICAgICAgICAgICdMaXN0ZW5lckRlZicgPSAkTGlzdGVuZXJEZWZpbml0aW9uOwogICAgICAgICAgICB9CgogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICJcXCRQcmltYXJ5Tm9kZVxTaGFyZWRXb3JrRGlyXCoiIC1Gb3JjZQoKICAgICAgICAgICAgJENsaVhtbEZpbGUgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiQ2xpWG1sIGZpbGU6ICckQ2xpWG1sRmlsZSciCgogICAgICAgICAgICAkbnVsbCA9IEV4cG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUgLUlucHV0T2JqZWN0ICRQYXJhbWV0ZXJzIC1EZXB0aCAxMAoKICAgICAgICAgICAgJG51bGwgPSBJbml0aWFsaXplLUFPQUdQcmltYXJ5UmVwbGljYSBgCiAgICAgICAgICAgICAgICAtQ2xpWG1sRmlsZSAkQ2xpWG1sRmlsZSBgCiAgICAgICAgICAgICAgICAtRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgCiAgICAgICAgICAgICAgICAtVXNlck5hbWUgJFVzZXJOYW1lIGAKICAgICAgICAgICAgICAgIC1Vc2VyUGFzc3dvcmQgJFVzZXJQYXNzd29yZCBgCiAgICAgICAgICAgICAgICAtUHJpbWFyeU5vZGUgJFByaW1hcnlOb2RlCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiSW5uZXIgJ0luaXRpYWxpemUtQU9BR1ByaW1hcnlSZXBsaWNhJyBjYWxsIGNvbXBsZXRlZC4iCiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAgICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gLUFsbAoKICAgICAgICAgICAgJG51bGwgPSBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyBAIgp0cmFwIHsKICAgIGAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJJbXBvcnRpbmcgQ2xpWG1sIHBhcmFtZXRlcnMgZmlsZSAuLi4iCmAkUGFyYW1ldGVycyA9IEltcG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwIGBgCiAgICAtV29ya0RpciBgJFBhcmFtZXRlcnNbJ1dvcmtEaXInXSBgYAogICAgLU5hbWUgYCRQYXJhbWV0ZXJzWydOYW1lJ10gYGAKICAgIC1EYXRhYmFzZU5hbWVzIGAkUGFyYW1ldGVyc1snRGF0YWJhc2VOYW1lcyddIGBgCiAgICAtUmVwbGljYURlZnMgYCRQYXJhbWV0ZXJzWydSZXBsaWNhRGVmcyddIGBgCiAgICAtUHJlZmVyZW5jZXMgYCRQYXJhbWV0ZXJzWydQcmVmZXJlbmNlcyddIGBgCiAgICAtTGlzdGVuZXJEZWYgYCRQYXJhbWV0ZXJzWydMaXN0ZW5lckRlZiddCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgICAgICB9CiAgICB9Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHU2Vjb25kYXJ5UmVwbGljYSB7CiAgICBwYXJhbSAoCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmdbXV0gJE5vZGVMaXN0LAoKICAgICAgICAjIChSRVFVSVJFRCkgTm9kZSBuYW1lIHRoYXQgd2lsbCBiZSBwcmltYXJ5IGZvciBzZWxlY3RlZCBBdmFpbGFiaWxpdHkgR3JvdXAKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlLAoKICAgICAgICBbU3RyaW5nXSAkU2hhcmVkV29ya0RpciA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJERvbWFpbk5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJOYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyUGFzc3dvcmQKICAgICkgCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLWVxICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBmdW5jdGlvbiB3b3JrcyBvbiBhbnkgU2Vjb25kYXJ5Tm9kZSBvbmx5LiIKICAgICAgICAgICAgV3JpdGUtTG9nICJFeGl0aW5nLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAkRnVuY3Rpb25zRmlsZSA9IEV4cG9ydC1GdW5jdGlvbiAtQWxsCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJTdGFydGluZyAnTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXBSZXBsaWNhJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwUmVwbGljYSAtV29ya0RpciAiXFwkUHJpbWFyeU5vZGVcJFNoYXJlZFdvcmtEaXIiCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgIH0KfQoKCgpmdW5jdGlvbiBEaXNhYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb2ZmCiAgICB9Cn0KCgoKZnVuY3Rpb24gRW5hYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb24KICAgIH0KfQoKCgpmdW5jdGlvbiBFbmFibGUtVHJ1c3RlZEhvc3RzIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBTZXQtSXRlbSBXU01hbjpcbG9jYWxob3N0XENsaWVudFxUcnVzdGVkSG9zdHMgLVZhbHVlICcqJyAtRm9yY2UKICAgIH0KfQo=", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgpmdW5jdGlvbiBFeHBvcnQtRnVuY3Rpb24gewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmdbXV0gJE5hbWUsCgogICAgICAgIFtQYXJhbWV0ZXIoVmFsdWVGcm9tUGlwZWxpbmU9JHRydWUpXQogICAgICAgIFtTdHJpbmddICRQYXRoID0gW0lPLlBhdGhdOjpHZXRUZW1wRmlsZU5hbWUoKSwKCiAgICAgICAgW1N3aXRjaF0gJEFsbAogICAgKQoKICAgIGlmIChbSU8uUGF0aF06OkdldEV4dGVuc2lvbigkUGF0aCkgLW5lICdwczEnKSB7CiAgICAgICAgJG51bGwgPSBSZW5hbWUtSXRlbSAtUGF0aCAkUGF0aCAtTmV3TmFtZSAiJFBhdGgucHMxIiAtRm9yY2UKICAgICAgICAkUGF0aCA9ICIkUGF0aC5wczEiCiAgICB9CgogICAgJFN5c3RlbUZ1bmN0aW9ucyA9IEAoCiAgICAgICAgJ0E6JywgJ0I6JywgJ0M6JywgJ0Q6JywgJ0U6JywgJ0Y6JywgJ0c6JywgJ0g6JywgJ0k6JywgJ0o6JywKICAgICAgICAnSzonLCAnTDonLCAnTTonLCAnTjonLCAnTzonLCAnUDonLCAnUTonLCAnUjonLCAnUzonLCAnVDonLAogICAgICAgICdVOicsICdWOicsICdXOicsICdYOicsICdZOicsICdaOicsCiAgICAgICAgJ2NkLi4nLCAnY2RcJywgJ2hlbHAnLCAnbWtkaXInLCAnbW9yZScsICdvc3MnLCAncHJvbXB0JywKICAgICAgICAnQ2xlYXItSG9zdCcsICdHZXQtVmVyYicsICdQYXVzZScsICdUYWJFeHBhbnNpb24yJwogICAgKQoKICAgIGlmICgkQWxsKSB7CiAgICAgICAgR2V0LUNoaWxkSXRlbSBGdW5jdGlvbjogfAogICAgICAgICAgICBXaGVyZS1PYmplY3QgeyRfLk1vZHVsZU5hbWUgLWVxICcnfSB8CiAgICAgICAgICAgIFdoZXJlLU9iamVjdCB7JFN5c3RlbUZ1bmN0aW9ucyAtbm90Y29udGFpbnMgJF8uTmFtZX0gfAogICAgICAgICAgICBGb3JFYWNoLU9iamVjdCB7CiAgICAgICAgICAgICAgICBBZGQtQ29udGVudCAtUGF0aCAkUGF0aCAtVmFsdWUgQCIKCgpmdW5jdGlvbiAkKCRfLk5hbWUpIHsKJCgkXy5TY3JpcHRCbG9jaykKfQoKIkAKICAgICAgICAgICAgfQogICAgfQogICAgZWxzZSB7CiAgICAgICAgZm9yZWFjaCAoJEZ1bmN0aW9uTmFtZSBpbiAkTmFtZSkgewogICAgICAgICAgICAkRnVuY3Rpb25PYmplY3QgPSBHZXQtQ2hpbGRJdGVtICJGdW5jdGlvbjpcJEZ1bmN0aW9uTmFtZSIKICAgICAgICAgICAgaWYgKCRGdW5jdGlvbk9iamVjdCAtbmUgJG51bGwpIHsKICAgICAgICAgICAgICAgIEFkZC1Db250ZW50IC1QYXRoICRQYXRoIC1WYWx1ZSBAIgoKCmZ1bmN0aW9uICRGdW5jdGlvbk5hbWUgewokKCRGdW5jdGlvbk9iamVjdC5TY3JpcHRCbG9jaykKfQoKIkAKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gJFBhdGgKfQo=", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgoKCmZ1bmN0aW9uIFNlbGVjdC1DbGlYbWxCbG9jayB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJFBhdGgsCiAgICAgICAgW1N0cmluZ10gJE91dEZpbGUgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCiAgICApCgogICAgJFRhZ0ZvdW5kID0gJGZhbHNlCiAgICBHZXQtQ29udGVudCAkUGF0aCB8CiAgICAgICAgRm9yRWFjaC1PYmplY3QgewogICAgICAgICAgICBpZiAoJF8gLWVxICcjPCBDTElYTUwnKSB7CiAgICAgICAgICAgICAgICAkVGFnRm91bmQgPSAkdHJ1ZQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICgkVGFnRm91bmQpIHsKICAgICAgICAgICAgICAgIEFkZC1Db250ZW50IC1QYXRoICRPdXRGaWxlIC1WYWx1ZSAkXwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgJE91dEZpbGUKfQoKCgpmdW5jdGlvbiBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJENvbW1hbmQsCiAgICAgICAgJENyZWRlbnRpYWwgPSAkbnVsbCwKICAgICAgICBbU3dpdGNoXSAkSWdub3JlU3RkRXJyLAogICAgICAgIFtTd2l0Y2hdICROb0Jhc2U2NAogICAgKQogICAgYmVnaW4gewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbgogICAgfQogICAgZW5kIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24gLUVuZAogICAgfQogICAgcHJvY2VzcyB7CiAgICAgICAgdHJhcCB7CiAgICAgICAgICAgICYkVHJhcEhhbmRsZXIKICAgICAgICB9CgogICAgICAgICRTdGRPdXQgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCiAgICAgICAgJFN0ZEVyciA9IFtJTy5QYXRoXTo6R2V0VGVtcEZpbGVOYW1lKCkKCiAgICAgICAgJEFyZ3VtZW50TGlzdCA9IEAoJy1PdXRwdXRGb3JtYXQnLCAnWE1MJykKCiAgICAgICAgaWYgKCROb0Jhc2U2NCkgewogICAgICAgICAgICAkVG1wU2NyaXB0ID0gW0lPLlBhdGhdOjpHZXRUZW1wRmlsZU5hbWUoKQogICAgICAgICAgICBSZW5hbWUtSXRlbSAtUGF0aCAiJFRtcFNjcmlwdCIgLU5ld05hbWUgIiRUbXBTY3JpcHQucHMxIiAtRm9yY2UKICAgICAgICAgICAgJFRtcFNjcmlwdCA9ICIkVG1wU2NyaXB0LnBzMSIKCiAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICRUbXBTY3JpcHQKCiAgICAgICAgICAgICRDb21tYW5kIHwgT3V0LUZpbGUgJFRtcFNjcmlwdAoKICAgICAgICAgICAgJEFyZ3VtZW50TGlzdCArPSBAKCctRmlsZScsICIkVG1wU2NyaXB0IikKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICRCeXRlcyA9IFtUZXh0LkVuY29kaW5nXTo6VW5pY29kZS5HZXRCeXRlcygkQ29tbWFuZCkKICAgICAgICAgICAgJEVuY29kZWRDb21tYW5kID0gW0NvbnZlcnRdOjpUb0Jhc2U2NFN0cmluZygkQnl0ZXMpCiAgICAgICAgICAgIAogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAkRW5jb2RlZENvbW1hbmQKCiAgICAgICAgICAgICRBcmd1bWVudExpc3QgKz0gQCgnLUVuY29kZWRDb21tYW5kJywgJEVuY29kZWRDb21tYW5kKQogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nRGVidWcgJEFyZ3VtZW50TGlzdAoKICAgICAgICBXcml0ZS1Mb2cgIlN0YXJ0aW5nIGV4dGVybmFsIFBvd2VyU2hlbGwgcHJvY2VzcyAuLi4iCgogICAgICAgIGlmICgkQ3JlZGVudGlhbCAtZXEgJG51bGwpIHsKICAgICAgICAgICAgJFByb2Nlc3MgPSBTdGFydC1Qcm9jZXNzIC1GaWxlUGF0aCAncG93ZXJzaGVsbC5leGUnIGAKICAgICAgICAgICAgICAgIC1Bcmd1bWVudExpc3QgQCgkQXJndW1lbnRMaXN0KSBgCiAgICAgICAgICAgICAgICAtUmVkaXJlY3RTdGFuZGFyZE91dHB1dCAkU3RkT3V0IGAKICAgICAgICAgICAgICAgIC1SZWRpcmVjdFN0YW5kYXJkRXJyb3IgJFN0ZEVyciBgCiAgICAgICAgICAgICAgICAtTm9OZXdXaW5kb3cgYAogICAgICAgICAgICAgICAgLVdhaXQgYAogICAgICAgICAgICAgICAgLVBhc3NUaHJ1CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkUHJvY2VzcyA9IFN0YXJ0LVByb2Nlc3MgLUZpbGVQYXRoICdwb3dlcnNoZWxsLmV4ZScgYAogICAgICAgICAgICAgICAgLUFyZ3VtZW50TGlzdCBAKCRBcmd1bWVudExpc3QpIGAKICAgICAgICAgICAgICAgIC1SZWRpcmVjdFN0YW5kYXJkT3V0cHV0ICRTdGRPdXQgYAogICAgICAgICAgICAgICAgLVJlZGlyZWN0U3RhbmRhcmRFcnJvciAkU3RkRXJyIGAKICAgICAgICAgICAgICAgIC1DcmVkZW50aWFsICRDcmVkZW50aWFsIGAKICAgICAgICAgICAgICAgIC1Ob05ld1dpbmRvdyBgCiAgICAgICAgICAgICAgICAtV2FpdCBgCiAgICAgICAgICAgICAgICAtUGFzc1RocnUKICAgICAgICB9CgogICAgICAgIFdyaXRlLUxvZyAiRXh0ZXJuYWwgUG93ZXJTaGVsbCBwcm9jZXNzIGV4aXRlZCB3aXRoIGV4aXQgY29kZSAnJCgkUHJvY2Vzcy5FeGl0Q29kZSknLiIKCiAgICAgICAgI2lmICgkQXJndW1lbnRMaXN0IC1jb250YWlucyAnLUZpbGUnKSB7CiAgICAgICAgIyAgICBSZW1vdmUtSXRlbSAtUGF0aCAkVG1wU2NyaXB0IC1Gb3JjZQogICAgICAgICN9CgogICAgICAgICRFcnJvckFjdGlvblByZWZlcmVuY2VTYXZlZCA9ICRFcnJvckFjdGlvblByZWZlcmVuY2UKICAgICAgICAkRXJyb3JBY3Rpb25QcmVmZXJlbmNlID0gJ1NpbGVudGx5Q29udGludWUnCgogICAgICAgIFdyaXRlLUxvZ0RlYnVnICJTdGRPdXQgZmlsZSBpcyAnJFN0ZE91dCciCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIlN0ZEVyciBmaWxlIGlzICckU3RkRXJyJyIKCiAgICAgICAgaWYgKChHZXQtSXRlbSAkU3RkT3V0KS5MZW5ndGggLWd0IDApIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICJMb2FkaW5nIFN0ZE91dCBmcm9tICckU3RkT3V0JyIKICAgICAgICAgICAgICAgICRUbXBGaWxlID0gU2VsZWN0LUNsaVhtbEJsb2NrICRTdGRPdXQKICAgICAgICAgICAgICAgICRTdGRPdXRPYmplY3QgPSBJbXBvcnQtQ2xpeG1sICRUbXBGaWxlCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPFN0ZE91dD4iCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAoJFN0ZE91dE9iamVjdCkKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L1N0ZE91dD4iCiAgICAgICAgICAgICAgICAkU3RkT3V0T2JqZWN0CiAgICAgICAgICAgICAgICAjUmVtb3ZlLUl0ZW0gLVBhdGggJFRtcEZpbGUgLUZvcmNlCiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2F0Y2ggewogICAgICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIkFuIGVycm9yIG9jY3VyZWQgd2hpbGUgbG9hZGluZyBTdGRPdXQgZnJvbSAnJFRtcEZpbGUnIgogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBpZiAoKEdldC1JdGVtICRTdGRFcnIpLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIkxvYWRpbmcgU3RkRXJyIC4uLiIKICAgICAgICAgICAgICAgICRUbXBGaWxlID0gU2VsZWN0LUNsaVhtbEJsb2NrICRTdGRFcnIKICAgICAgICAgICAgICAgICRTdGRFcnJPYmplY3QgPSBJbXBvcnQtQ2xpeG1sICRUbXBGaWxlCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPFN0ZEVycj4iCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAoJFN0ZEVyck9iamVjdCkKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L1N0ZEVycj4iCiAgICAgICAgICAgICAgICBpZiAoLW5vdCAkSWdub3JlU3RkRXJyKSB7CiAgICAgICAgICAgICAgICAgICAgJFN0ZEVyck9iamVjdAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgI1JlbW92ZS1JdGVtIC1QYXRoICRUbXBGaWxlIC1Gb3JjZQogICAgICAgICAgICB9CiAgICAgICAgICAgIGNhdGNoIHsKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICJBbiBlcnJvciBvY2N1cmVkIHdoaWxlIGxvYWRpbmcgU3RkRXJyIGZyb20gJyRUbXBGaWxlJyIKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICRFcnJvckFjdGlvblByZWZlcmVuY2VTYXZlZAoKICAgICAgICBpZiAoJFByb2Nlc3MuRXhpdENvZGUgLW5lIDApIHsKICAgICAgICAgICAgdGhyb3coIkV4dGVybmFsIFBvd2VyU2hlbGwgcHJvY2VzcyBleGl0ZWQgd2l0aCBjb2RlICckKCRQcm9jZXNzLkV4aXRDb2RlKSciKQogICAgICAgIH0KCiAgICAgICAgI1JlbW92ZS1JdGVtICRTdGRPdXQgLUZvcmNlCiAgICAgICAgI1JlbW92ZS1JdGVtICRTdGRFcnIgLUZvcmNlCiAgICB9Cn0K" ] } \ No newline at end of file diff --git a/data/templates/agent/SqlServerCluster/InitializeAOAGSecondaryReplica.template b/data/templates/agent/SqlServerCluster/InitializeAOAGSecondaryReplica.template index b9bde6a..1af2865 100644 --- a/data/templates/agent/SqlServerCluster/InitializeAOAGSecondaryReplica.template +++ b/data/templates/agent/SqlServerCluster/InitializeAOAGSecondaryReplica.template @@ -1,4 +1,13 @@ { + "Scripts": [ + "ImportCoreFunctions.ps1", + "OptionParser.ps1", + "SQLServerOptionParsers.ps1", + "SQLServerInstall.ps1", + "Export-Function.ps1", + "Start-PowerShellProcess.ps1", + "SQLServerForAOAG.ps1" + ], "Commands": [ { "Name": "Initialize-AOAGSecondaryReplica", @@ -10,14 +19,5 @@ "DomainName": "$domainName" } } - ], - "Scripts": [ - "SW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zIC1Gb3JjZQoKCmZ1bmN0aW9uIFNob3ctSW52b2NhdGlvbkluZm8gewogICAgcGFyYW0gKAogICAgICAgICRJbnZvY2F0aW9uLAogICAgICAgIFtTd2l0Y2hdICRFbmQKICAgICkKCiAgICBpZiAoJEVuZCkgewogICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L2Z1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICB9CiAgICBlbHNlIHsKICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPGZ1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjxwYXJhbT4iCiAgICAgICAgZm9yZWFjaCAoJFBhcmFtZXRlciBpbiAkSW52b2NhdGlvbi5NeUNvbW1hbmQuUGFyYW1ldGVycykgewogICAgICAgICAgICBmb3JlYWNoICgkS2V5IGluICRQYXJhbWV0ZXIuS2V5cykgewogICAgICAgICAgICAgICAgJFR5cGUgPSAkUGFyYW1ldGVyWyRLZXldLlBhcmFtZXRlclR5cGUuRnVsbE5hbWUKICAgICAgICAgICAgICAgIGZvcmVhY2ggKCRWYWx1ZSBpbiAkSW52b2NhdGlvbi5Cb3VuZFBhcmFtZXRlcnNbJEtleV0pIHsKICAgICAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiWyRUeXBlXSAkS2V5ID0gJyRWYWx1ZSciCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjwvcGFyYW0+IgogICAgfQp9CgoKJFRyYXBIYW5kbGVyID0gewogICAgV3JpdGUtTG9nRXJyb3IgQCgiPGV4Y2VwdGlvbj4iLCAkXykgLUVudGlyZU9iamVjdAogICAgV3JpdGUtTG9nRXJyb3IgIjwvZXhjZXB0aW9uPiIKICAgIGJyZWFrCn0KCgp0cmFwIHsKICAgICYkVHJhcEhhbmRsZXIKfQoKJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICdTdG9wJwoKCjwjCiMgVXNhZ2UgZXhhbXBsZSBmb3IgU2hvdy1JbnZvY2F0aW9uSW5mbwoKZnVuY3Rpb24gTXlGdW5jdGlvbiB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJFZhbHVlMSwKICAgICAgICBbU3RyaW5nXSAkVmFsdWUyLAogICAgICAgIFtJbnRdICRJbnQxCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KICAgICAgICAjIE1haW4gY29kZSBoZXJlCiAgICB9Cn0KIz4K", - "ZnVuY3Rpb24gTmV3LU9wdGlvbiAoW3N0cmluZ10kTmFtZSwgW3N3aXRjaF0kU3dpdGNoLCBbc3dpdGNoXSRCb29sZWFuLCBbc3dpdGNoXSRTdHJpbmcsIFtzd2l0Y2hdJExpc3QsICRDb25zdHJhaW50cz0kbnVsbCkgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBPcHRpb24gb2JqZWN0CgogICAgLkRFU0NSSVBUSU9OCiAgICBPcHRpb24gb2JqZWN0IGlzIGEgdmlydHVhbCBvYmplY3QgcmVwcmVzdG50aW5nIHR5cGVkIGNvbW1hbmQgbGluZSBvcHRpb24uIFRoZXNlIG9iamVjdHMgZW5jYXBzdWxhdGUgZXNjYXBpbmcgYW5kCiAgICB2YWxpZGF0aW9uIG1hdHRlcnMuCgogICAgT25lIGFuZCBvbmx5IG9uZSBvZiB0aGUgc3dpdGNoZXMgJ1N3aXRjaCcsICdCb29sZWFuJywgJ1N0cmluZycgb3IgJ0xpc3QnIHNob3VsZCBiZSBwcm92aWRlZC4KCiAgICAuUEFSQU1FVEVSIE5hbWUKICAgIE9wdGlvbiBuYW1lIGFzIGl0IGFwcGVhcnMgaW4gdGhlIGNvbW1hbmQgbGluZS4KCiAgICAuUEFSQU1FVEVSIFN3aXRjaAogICAgVXNlIHRoaXMgc3dpdGNoIHRvIGNyZWF0ZSB2YWx1ZWxlc3Mgb3B0aW9uIChhIHN3aXRjaCkuCgogICAgLlBBUkFNRVRFUiBCb29sZWFuCiAgICBVc2UgdGhpcyBzd2l0Y2ggdG8gY3JlYXRlIGJvb2xlYW4gb3B0aW9uLiBJdHMgdmFsdWUgaXMgYWx3YXlzIGNvbnZlcnRlZCB0byAiMSIgb3IgIjAiCgogICAgLlBBUkFNRVRFUiBTdHJpbmcKICAgIFVzZSB0aGlzIHN3aXRjaCB0byBjcmVhdGUgc3RyaW5nIG9wdGlvbi4gSXRzIHZhbHVlIHdpbGwgYmUgcHJvcGVybHkgcXVvdGVkIGlmIG5lY2Vzc2FyeS4KCiAgICAuUEFSQU1FVEVSIExpc3QKICAgIFVzZSB0aGlzIHN3aXRjaCB0byBjcmVhdGUgb3B0aW9uIHdpdGggbGlzdCB2YWx1ZS4gVmFsdWVzIHdpbGwgYmUgcHV0IGludG8gY29tbWFuZCBsaW5lIHVzaW5nIHZhbGlkIHZhbHVlIGRlbGVtaXRlciAoYSBjb21tYSkKCiAgICAuUEFSQU1FVEVSIENvbnN0cmFpbnRzCiAgICBXaGVuIHRoaXMgcGFyYW1ldGVyIGlzIHNwZWNpZmllZCwgb3B0aW9uIHZhbHVlcyBhcmUgbGltaXRlZCB0byBvcHRpb25zIGZyb20gdGhhdCBsaXN0LgoKICAgICM+CgogICAgJE9wdGlvbiA9IE5ldy1PYmplY3QgLVR5cGVOYW1lIFBTT2JqZWN0CgogICAgIyBGaWVsZHMKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIE5vdGVQcm9wZXJ0eSBUeXBlIC12YWx1ZSAkbnVsbAogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IE5hbWUgLXZhbHVlICRudWxsCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgQWxsb3dlZFZhbHVlcyAtdmFsdWUgJG51bGwKCiAgICAjIEluaXQKCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBTY3JpcHRNZXRob2QgX19pbml0X18gewogICAgICAgIHBhcmFtKFtzdHJpbmddJE5hbWUsICRTd2l0Y2gsICRCb29sZWFuLCAkU3RyaW5nLCAkTGlzdCkKCiAgICAgICAgJHRoaXMuTmFtZSA9ICROYW1lCiAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgIyBXaXRoIHJlc3BlY3QgZm9yIG91ciBkZXZlbG9wZXJzIHdlIGRvIG5vdCBjaGVjayBmb3IgZG91YmxlIHR5cGUgc2VsZWN0ZWQKICAgICAgICBpZiAoJFN3aXRjaCkgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uU3dpdGNoKCR0aGlzKQogICAgICAgIH0gZWxzZWlmICgkQm9vbGVhbikgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uQm9vbGVhbigkdGhpcykKICAgICAgICB9IGVsc2VpZiAoJFN0cmluZykgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uU3RyaW5nKCR0aGlzKQogICAgICAgIH0gZWxzZWlmICgkTGlzdCkgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uTGlzdCgkdGhpcykKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aHJvdyAiU3dpdGNoLCBCb29sZWFuLCBTdHJpbmcgb3IgTGlzdCBvcHRpb24gdHlwZSBtdXN0IGJlIHByb3ZpZGVkIGZvciBvcHRpb24gJyROYW1lJyIKICAgICAgICB9CiAgICB9CgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIF9fcG9zdF9pbml0X18gewogICAgICAgIHBhcmFtKCRDb25zdHJhaW50cz0kbnVsbCkKICAgICAgICBpZiAoJENvbnN0cmFpbnRzIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkdGhpcy5BbGxvd2VkVmFsdWVzID0gQCgpCiAgICAgICAgICAgICR0aGlzLkFsbG93ZWRWYWx1ZXMgPSAkdGhpcy5BbGxvd2VkVmFsdWVzICsgJENvbnN0cmFpbnRzCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgJENvbnN0cmFpbnRzID0gJG51bGwKICAgICAgICB9CiAgICB9CgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBWYWxpZGF0ZSB7CiAgICAgICAgaWYgKCR0aGlzLkFsbG93ZWRWYWx1ZXMgLW5lICRudWxsKSB7CiAgICAgICAgICAgIGlmICgtbm90KCR0aGlzLkFsbG93ZWRWYWx1ZXMgLWNvbnRhaW5zICR0aGlzLlZhbHVlKSkgewogICAgICAgICAgICAgICAgJEN0cyA9ICR0aGlzLkFsbG93ZWRWYWx1ZXMgLWpvaW4gJywnCiAgICAgICAgICAgICAgICB0aHJvdyAiT3B0aW9uICckKCR0aGlzLk5hbWUpJyBtYXkgaGF2ZSB2YWx1ZXMgKCRDdHMpIGJ1dCBub3QgJyQoJHRoaXMuVmFsdWUpJyIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciAtRm9yY2UgU2NyaXB0TWV0aG9kIFRvU3RyaW5nIHsKICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpIgogICAgfQoKICAgICMgaW52b2tlIGNvbnN0cnVjdG9yCgogICAgJE9wdGlvbi5fX2luaXRfXygkTmFtZSwgJFN3aXRjaCwgJEJvb2xlYW4sICRTdHJpbmcsICRMaXN0KQogICAgJE9wdGlvbi5fX3Bvc3RfaW5pdF9fKCRDb25zdHJhaW50cykKCiAgICByZXR1cm4gJE9wdGlvbgp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uU3dpdGNoKCRPcHRpb24pIHsKfQoKZnVuY3Rpb24gQXVnbWVudE9wdGlvbkJvb2xlYW4oJE9wdGlvbikgewogICAgIyBGaWVsZHMKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIE5vdGVQcm9wZXJ0eSBWYWx1ZSAtdmFsdWUgJGZhbHNlCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBUb1N0cmluZyB7CiAgICAgICAgaWYgKCR0aGlzLlZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9MSIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpPTAiCiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uU3RyaW5nKCRPcHRpb24pIHsKICAgICMgRmllbGRzCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgVmFsdWUgLXZhbHVlICIiCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBUb1N0cmluZyB7CiAgICAgICAgJHYgPSAiJCgkdGhpcy5WYWx1ZSkiCiAgICAgICAgaWYgKCR2IC1tYXRjaCAnLiogLionKSB7CiAgICAgICAgICAgICMgVE9ETzogRXNjYXBlIGRvdWJsZSBxdW90ZSBjaGFyYWN0ZXJzIGlmIHBvc3NpYmxlCiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9YCIkdmAiIgogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9JHYiCiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uTGlzdCgkT3B0aW9uKSB7CiAgICAjIEZpZWxkcwogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IFZhbHVlIC12YWx1ZSBAKCkKCiAgICAjIE1ldGhvZHMKCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciAtRm9yY2UgU2NyaXB0TWV0aG9kIFZhbGlkYXRlIHsKICAgICAgICBpZiAoJHRoaXMuQWxsb3dlZFZhbHVlcyAtbmUgJG51bGwpIHsKICAgICAgICAgICAgZm9yZWFjaCAoJFYgaW4gJHRoaXMuVmFsdWUpIHsKICAgICAgICAgICAgICAgIGlmICgtbm90KCR0aGlzLkFsbG93ZWRWYWx1ZXMgLWNvbnRhaW5zICRWKSkgewogICAgICAgICAgICAgICAgICAgICRDdHMgPSAkdGhpcy5BbGxvd2VkVmFsdWVzIC1qb2luICcsJwogICAgICAgICAgICAgICAgICAgIHRocm93ICJPcHRpb24gJyQoJHRoaXMuTmFtZSknIG1heSBoYXZlIHZhbHVlcyAoJEN0cykgYnV0IG5vdCAnJFYnIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIC1Gb3JjZSBTY3JpcHRNZXRob2QgVG9TdHJpbmcgewogICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9JCgkdGhpcy5WYWx1ZSAtam9pbiAnLCcpIgogICAgfQp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyKCkgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBPcHRpb25QYXJzZXIgb2JqZWN0LgoKICAgIC5ERVNDUklQVElPTgogICAgT3B0aW9uUGFyc2VyIG9iamVjdCBsZXZlcmFnZXMgT3B0aW9uIG9iamVjdHMgY2FwYWJpbGl0aWVzIGFuZCBidWlsZHMgdmFsaWQgY29tbWFuZCBsaW5lIHVzaW5nIHNwZWNpZmllZCBvcHRpb25zLgogICAgQW4gYXBwbGljYXRpb24gbWF5IGFsc28gYmUgaW52b2tlZCB3aXRoIE9wdGlvblBhcnNlci4KCiAgICAjPgoKICAgICRPcHRpb25QYXJzZXIgPSBOZXctT2JqZWN0IC1UeXBlTmFtZSBQU09iamVjdAoKICAgICMgRmllbGRzCiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgT3B0aW9ucyAtdmFsdWUgQHt9CiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgRGVmYXVsdHMgLXZhbHVlIEB7fQogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IFJlcXVpcmVkT3B0aW9ucyAtdmFsdWUgQCgpCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIEFkZE9wdGlvbiB7CiAgICAgICAgPCMKICAgICAgICAuU1lOT1BTSVMKICAgICAgICBBZGRzIHN1cHBvcnRlZCBvcHRpb24gaW50byBPcHRpb25QYXJzZXIuCiAgICAgICAgCiAgICAgICAgLkRFU0NSSVBUSU9OCiAgICAgICAgT3B0aW9uUGFyc2VyIGRvZXMgbm90IGFsbG93IHVzaW5nIHVucmVjb2duaXplZCBvcHRpb25zLiBVc2UgdGhpcyBtZXRob2QgdG8gZmlsbCBPcHRpb25QYXJzZXIgd2l0aCByZWNvZ25pemVkIG9wdGlvbnMKCiAgICAgICAgLlBBUkFNRVRFUiBPcHRpb24KICAgICAgICBPcHRpb24gb2JqZWN0CgogICAgICAgIC5QQVJBTUVURVIgUmVxdWlyZWQKICAgICAgICBSZXF1aXJlZCBvcHRpb24gc3dpdGNoCgogICAgICAgIC5QQVJBTUVURVIgRGVmYXVsdAogICAgICAgIE9wdGlvbiBkZWZhdWx0IHZhbHVlCiAgICAgICAgIz4KICAgICAgICBwYXJhbSgkT3B0aW9uLCBbYm9vbF0kUmVxdWlyZWQ9JGZhbHNlLCAkRGVmYXVsdD0kbnVsbCkKICAgICAgICAkdGhpcy5PcHRpb25zLkFkZCgkT3B0aW9uLk5hbWUsICRPcHRpb24pCiAgICAgICAgaWYgKCRSZXF1aXJlZCkgewogICAgICAgICAgICAkdGhpcy5SZXF1aXJlZE9wdGlvbnMgPSAkdGhpcy5SZXF1aXJlZE9wdGlvbnMgKyAkT3B0aW9uLk5hbWUKICAgICAgICAgICAgaWYgKCRPcHRpb24gfCBHZXQtTWVtYmVyICJWYWx1ZSIpIHsKICAgICAgICAgICAgICAgIGlmICgkRGVmYXVsdCkgewogICAgICAgICAgICAgICAgICAgICR0aGlzLkRlZmF1bHRzLkFkZCgkT3B0aW9uLk5hbWUsICREZWZhdWx0KQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgJHRoaXMuRGVmYXVsdHMuQWRkKCRPcHRpb24uTmFtZSwgJG51bGwpCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIFBhcnNlIHsKICAgICAgICA8IwogICAgICAgIC5TWU5PUFNJUwogICAgICAgIFBhcnNlcyBzdXBwbGllZCBvcHRpb25zIGFuZCByZXR1cm5zIGNvbW1hbmQgbGluZSBwYXJhbWV0ZXJzIGFycmF5LgogICAgICAgIAogICAgICAgIC5ERVNDUklQVElPTgogICAgICAgIFRoaXMgbWV0aG9kIHZlcmlmaWVzIHRoYXQgb25seSBzdXBwb3J0ZWQgb3B0aW9ucyBhcmUgcHJvdmlkZWQsIGFsbCBtYW5kYXRvcnkgb3B0aW9ucyBhcmUgaW4gcGxhY2UsIAogICAgICAgIGFsbCBvcHRpb24gbWVldCBjb25zdHJhaW50cyBpZiBhbnkuIFVuc3BlY2lmaWVkIG9wdGlvbnMgd2l0aCBkZWZhdWx0IHZhbHVlcyBhcmUgYWRkZWQgdG8gY29tbWFuZCBsaW5lLgogICAgICAgIFNvLCBtYW5kYXRvcnkgb3B0aW9uIHdpdGggZGVmYXVsdCB2YWx1ZSBuZXZlciBjYXVzZXMgZXhjZXB0aW9uLgoKICAgICAgICAuUEFSQU1FVEVSIE9wdGlvbnMKICAgICAgICBBIGhhc2ggbWFwIG9mIG9wdGlvbnMgdG8gcGFyc2UuIE9wdGlvbiBuYW1lcyBzaG91bGQgYmUgbWFwcGVkIHRvIGNvcnJlc3BvbmRpbmcgdmFsdWVzLgogICAgICAgICM+CiAgICAgICAgcGFyYW0oW2hhc2h0YWJsZV0kT3B0aW9ucykKCiAgICAgICAgJENvbW1hbmRMaW5lID0gQCgpCiAgICAgICAgZm9yZWFjaCAoJFJlcXVpcmVkT3B0aW9uTmFtZSBpbiAkdGhpcy5SZXF1aXJlZE9wdGlvbnMpIHsKICAgICAgICAgICAgaWYgKC1ub3QgJE9wdGlvbnMuQ29udGFpbnNLZXkoJFJlcXVpcmVkT3B0aW9uTmFtZSkpIHsKICAgICAgICAgICAgICAgICREZWZhdWx0ID0gJHRoaXMuRGVmYXVsdHMuR2V0X0l0ZW0oJFJlcXVpcmVkT3B0aW9uTmFtZSkKICAgICAgICAgICAgICAgIGlmICgkdGhpcy5EZWZhdWx0cy5Db250YWluc0tleSgkUmVxdWlyZWRPcHRpb25OYW1lKSkgewogICAgICAgICAgICAgICAgICAgICRPcHRpb25zLkFkZCgkUmVxdWlyZWRPcHRpb25OYW1lLCAkdGhpcy5EZWZhdWx0cy5HZXRfSXRlbSgkUmVxdWlyZWRPcHRpb25OYW1lKSkKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgIlJlcXVpcmVkIG9wdGlvbiAnJFJlcXVpcmVkT3B0aW9uTmFtZScgaXMgbWlzc2luZyIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZm9yZWFjaCAoJE9wdGlvbk5hbWUgaW4gJCgkT3B0aW9ucy5rZXlzKSkgewogICAgICAgICAgICAkT3B0aW9uID0gJHRoaXMuT3B0aW9ucy5HZXRfSXRlbSgkT3B0aW9uTmFtZSkKICAgICAgICAgICAgaWYgKCRPcHRpb24gLWVxICRudWxsKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAiT3B0aW9uICckT3B0aW9uTmFtZScgaXMgbm90IGFsbG93ZWQiCiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCRPcHRpb24gfCBHZXQtTWVtYmVyICJWYWx1ZSIpIHsKICAgICAgICAgICAgICAgICRPcHRpb24uVmFsdWUgPSAkT3B0aW9ucy5HZXRfSXRlbSgkT3B0aW9uTmFtZSkKICAgICAgICAgICAgfQogICAgICAgICAgICAkT3B0aW9uLlZhbGlkYXRlKCkKICAgICAgICAgICAgJENvbW1hbmRMaW5lID0gJENvbW1hbmRMaW5lICsgJE9wdGlvbi5Ub1N0cmluZygpCiAgICAgICAgfQogICAgICAgIHJldHVybiAkQ29tbWFuZExpbmUKICAgIH0KCiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBTY3JpcHRNZXRob2QgRXhlY3V0ZUJpbmFyeSB7CiAgICAgICAgcGFyYW0oJEJpbmFyeSwgW2hhc2h0YWJsZV0kT3B0aW9ucyA9IEB7fSwgJENvbW1hbmRMaW5lU3VmZml4ID0gQCgpKQogICAgICAgIDwjCiAgICAgICAgLlNZTk9QU0lTCiAgICAgICAgRXhlY3V0ZXMgYmluYXJ5IHdpdGggYSBjb21tYW5kIGxpbmUgY29uc3RydWN0ZWQgZnJvbSBwcm92aWRlZCBvcHRpb25zLiBBbiBhcmJpdHJhcnkgc3VmZml4IG1heSBiZSAKICAgICAgICBhcHBlbmRlZCB0byB0aGUgY29tbWFuZCBsaW5lLgogICAgICAgIAogICAgICAgIC5ERVNDUklQVElPTgogICAgICAgIFRoaXMgbWV0aG9kIHVzZXMgT3B0aW9uUGFyc2VyLlBhcnNlIG1ldGhvZCB0byBjb25zdHJ1Y3QgY29tbWFuZCBsaW5lLiBJZiB0aGVyZSBhIGNvbW1hbmQgbGluZSBzdWZmaXggCiAgICAgICAgd2FzIHN1cHBsaWVkLCBpdCBpcyBhcHBlbmRlZCB0byB0aGUgZW5kIG9mIGNvbW1hbmQgbGluZS4gTm9ybWFsbHkgY29tbWFuZCBsaW5lIHN1ZmZpeCBzaG91bGQgY29udGFpbgogICAgICAgIGxlYWRpbmcgc3BhY2UgY2hhcmFjdGVyLgoKICAgICAgICBNZXRob2Qgd2FpdHMgZm9yIGV4ZWN1dGFibGUgcHJvY2VzcyB0byBjb21wbGV0ZSBhbmQgcmV0dXJucyBpdHMgZXhpdCBjb2RlLgoKICAgICAgICAuUEFSQU1FVEVSIEJpbmFyeQogICAgICAgIEZ1bGwgb3IgcmVsYXRpdmUgcGF0aCB0byB0aGUgZXhlY3V0YWJsZSB0byBydW4uCgogICAgICAgIC5QQVJBTUVURVIgT3B0aW9ucwogICAgICAgIEEgaGFzaCBtYXAgb2Ygb3B0aW9ucyB0byBwYXNzIHRvIHRoZSBleGVjdXRhYmxlLgoKICAgICAgICAuUEFSQU1FVEVSIENvbW1hbmRMaW5lU3VmZml4CiAgICAgICAgQXJiaXRyYXJ5IGNvbW1hbmQgbGluZSBzdWZmaXguIE5vcm1hbGx5IGl0IHNob3VkIGhhdmUgbGVhZGluZyBzcGFjZSBjaGFyYWN0ZXIuCiAgICAgICAgIz4KCiAgICAgICAgJEJpbmFyeSA9IEdldC1JdGVtICRCaW5hcnkKICAgICAgICAkQ29tbWFuZExpbmUgPSAkdGhpcy5QYXJzZSgkT3B0aW9ucykKICAgICAgICBpZiAoJENvbW1hbmRMaW5lU3VmZml4KSB7CiAgICAgICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICRDb21tYW5kTGluZVN1ZmZpeAogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJFeGVjdXRpbmc6ICQoJEJpbmFyeS5GdWxsTmFtZSkgJCgkQ29tbWFuZExpbmUgLWpvaW4gJyAnKSIKICAgICAgICAkcHJvY2VzcyA9IFtTeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2Vzc106OlN0YXJ0KCRCaW5hcnksICRDb21tYW5kTGluZSkKICAgICAgICAkcHJvY2Vzcy5XYWl0Rm9yRXhpdCgpCiAgICAgICAgJHByb2Nlc3MuUmVmcmVzaCgpCiAgICAgICAgcmV0dXJuICRwcm9jZXNzLkV4aXRDb2RlCiAgICB9CgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQo=", - "ZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckluc3RhbGwgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBhbiBvcHRpb24gcGFyc2VyIGZvciBNUyBTUUwgU2VydmVyIDIwMTIgc2V0dXAgIklOU1RBTEwiIGFjdGlvbi4KCiAgICAuREVTQ1JJUFRJT04KICAgIFVzZSB0aGlzIGNtZGxldCB0byBjcmVhdGUgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJJTlNUQUxMIiBhY3Rpb24uCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkSXNQYXJ0T2ZEb21haW4gPSAoR2V0LVdtaU9iamVjdCBXaW4zMl9Db21wdXRlclN5c3RlbSkuUGFydE9mRG9tYWluCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIklOU1RBTEwiKSwgJHRydWUsICJJTlNUQUxMIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJQUNDRVBUU1FMU0VSVkVSTElDRU5TRVRFUk1TIiAtU3dpdGNoKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5VIiAtU3dpdGNoKSkKICAgICMkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlVwZGF0ZVNvdXJjZSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVSUk9SUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTCIsIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJEUSIsIkFTIiwiUlMiLCJEUUMiLCJJUyIsIk1EUyIsIlRvb2xzIiwiQkMiLCJCT0wiLCJCSURTIiwiQ29ubiIsIlNTTVMiLCJBRFZfU1NNUyIsIkRSRVBMQVlfQ1RMUiIsIkRSRVBMQVlfQ0xUIiwiU05BQ19TREsiLCJTREsiLCJMb2NhbERCIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJPTEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiU1BJX0FTX0V4aXN0aW5nRmFybSIsICJTUElfQVNfTmV3RmFybSIsICJBbGxGZWF0dXJlc19XaXRoRGVmYXVsdHMiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRFdPV0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlBJRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlVJTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJOb3JtYWwiLCAiQXV0b0FkdmFuY2UiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FNUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTQkFDS1VQRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU0NPTExBVElPTiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQVNDT05GSUdESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTREFUQURJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQVNMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU0VSVkVSTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNVUxUSURJTUVOU0lPTkFMIiwgIlBPV0VSUElWT1QiLCAiVEFCVUxBUiIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKCiAgICAjJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXCRFTlY6VVNFUk5BTUUiKQogICAgaWYgKCRJc1BhcnRPZkRvbWFpbikgewogICAgICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFbnY6VVNFUkRPTUFJTlxBZG1pbmlzdHJhdG9yIikKICAgIH0KICAgIGVsc2UgewogICAgICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFbnY6Q09NUFVURVJOQU1FXEFkbWluaXN0cmF0b3IiKQogICAgfQoKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1RFTVBESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTUFJPVklERVJNU09MQVAiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGQVJNQUNDT1VOVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkFSTVBBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJQQVNTUEhSQVNFIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGQVJNQURNSU5JUE9SVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQlJPV1NFUlNWQ1NUQVJUVVBUWVBFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5BQkxFUkFOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNRTERBVEFESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNBUFdEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTRUNVUklUWU1PREUiIC1TdHJpbmcgLUNvbnN0cmFpbnJzICgiU1FMIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTEJBQ0tVUERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMQ09MTEFUSU9OIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBRERDVVJSRU5UVVNFUkFTU1FMQURNSU4iIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgCiAgICAjJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6VVNFUkRPTUFJTlwkRU5WOlVTRVJOQU1FIikKICAgIGlmICgkSXNQYXJ0T2ZEb21haW4pIHsKICAgICAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXEFkbWluaXN0cmF0b3IiKQogICAgfQogICAgZWxzZSB7CiAgICAgICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6Q09NUFVURVJOQU1FXEFkbWluaXN0cmF0b3IiKQogICAgfQogICAgCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVEVNUERCRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxURU1QREJMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFVTRVJEQkRJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVVNFUkRCTE9HRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGSUxFU1RSRUFNTEVWRUwiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiMCIsICIxIiwgIjIiLCAiMyIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGSUxFU1RSRUFNU0hBUkVOQU1FIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGVFNWQ0FDQ09VTlQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZUU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklTU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSVNTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSVNTVkNTdGFydHVwVHlwZSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIk5QRU5BQkxFRCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlRDUEVOQUJMRUQiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU0lOU1RBTExNT0RFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIlNoYXJlUG9pbnRGaWxlc09ubHlNb2RlIiwgIkRlZmF1bHROYXRpdmVNb2RlIiwgIkZpbGVzT25seU1vZGUiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNBQ0NPVU5UIiAtU3RyaW5nKSwgJHRydWUsICJOVCBBVVRIT1JJVFlcTmV0d29yayBTZXJ2aWNlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ1N0YXJ0dXBUeXBlIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclByZXBhcmVJbWFnZSB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgTm90ZSB0aGF0IGZvciBpbnN0YWxsZXIgdmVyc2lvbiBvZiBNUyBTUUwgU2VydmVyIHByaW9yIHRvIDIwMTIgU1AxIEN1bXVsYXRpdmUgVXBkYXRlIDIgb25seSB0aGUKICAgIGZvbGxvd2luZyBmZWF0dXJlcyBhcmUgc3VwcG9ydGVkOiBTUUxFbmdpbmUsIFJlcGxpY2F0aW9uLCBGdWxsVGV4dCwgUlMKCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUNUSU9OIiAtU3RyaW5nIC1Db25zdHJhaW50cyAiUHJlcGFyZUltYWdlIiksICR0cnVlLCAiUHJlcGFyZUltYWdlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJQUNDRVBUU1FMU0VSVkVSTElDRU5TRVRFUk1TIiAtU3dpdGNoKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5VIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJVcGRhdGVFbmFibGVkIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJVcGRhdGVTb3VyY2UiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkNPTkZJR1VSQVRJT05GSUxFIiAtU3RyaW5nKSkKIyAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJSUyIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGRUFUVVJFUyIgLUxpc3QgLUNvbnN0cmFpbnRzICgiU1FMIiwiU1FMRW5naW5lIiwiUmVwbGljYXRpb24iLCJGdWxsVGV4dCIsIkRRIiwiQVMiLCJSUyIsIkRRQyIsIklTIiwiTURTIiwiVG9vbHMiLCJCQyIsIkJPTCIsIkJJRFMiLCJDb25uIiwiU1NNUyIsIkFEVl9TU01TIiwiRFJFUExBWV9DVExSIiwiRFJFUExBWV9DTFQiLCJTTkFDX1NESyIsIlNESyIsIkxvY2FsREIiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklORElDQVRFUFJPR1JFU1MiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTExTSEFSRURESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJTlNUQU5DRUlEIiAtU3RyaW5nKSwgJHRydWUsICJNU1NRTFNFUlZFUiIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJQcmVwYXJlSW1hZ2VTUDFVMiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgVGhpcyBjbWRsZXQgc2hvdWxkIGJlIHVzZWQgb25seSBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIFNQMSBDaW1pbGF0aXZlIFVwZGF0ZSAyIG9yIGxhdGVyLgoKICAgIE5vdGUgdGhhdCBmb3IgaW5zdGFsbGVyIHZlcnNpb24gb2YgTVMgU1FMIFNlcnZlciBwcmlvciB0byAyMDEyIFNQMSBDaW1pbGF0aXZlIFVwZGF0ZSAyIG9ubHkgdGhlCiAgICBmb2xsb3dpbmcgZmVhdHVyZXMgYXJlIHN1cHBvcnRlZDogU1FMRW5naW5lLCBSZXBsaWNhdGlvbiwgRnVsbFRleHQsIFJTCgogICAgQWxsIGRvY3VtZW50ZWQgb3B0aW9uIGFyZSBzdXBwb3J0ZWQuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yIGRldGFpbHM6CiAgICBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAogICAgIz4KICAgICRPcHRpb25QYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VyCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIlByZXBhcmVJbWFnZSIpLCAkdHJ1ZSwgIlByZXBhcmVJbWFnZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSUFDQ0VQVFNRTFNFUlZFUkxJQ0VOU0VURVJNUyIgLVN3aXRjaCksICR0cnVlKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlU291cmNlIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJDT05GSUdVUkFUSU9ORklMRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTCIsIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJEUSIsIkFTIiwiUlMiLCJEUUMiLCJJUyIsIk1EUyIsIlRvb2xzIiwiQkMiLCJCT0wiLCJCSURTIiwiQ29ubiIsIlNTTVMiLCJBRFZfU1NNUyIsIlNOQUNfU0RLIiwiU0RLIiwiTG9jYWxEQiIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJISURFQ09OU09MRSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk1TU1FMU0VSVkVSIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRUyIgLVN3aXRjaCkpCgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckNvbXBsZXRlSW1hZ2UgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBhbiBvcHRpb24gcGFyc2VyIGZvciBNUyBTUUwgU2VydmVyIDIwMTIgc2V0dXAgIkNvbXBsZXRlSW1hZ2UiIGFjdGlvbi4KCiAgICAuREVTQ1JJUFRJT04KICAgIFVzZSB0aGlzIGNtZGxldCB0byBjcmVhdGUgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJDb21wbGV0ZUltYWdlIiBhY3Rpb24uCgogICAgTm90ZSB0aGF0IElOU1RBTkNFSUQgcGFyYW1ldGVyIHZhbHVlIE1VU1QgYmUgdGhlIHNhbWUgYXMgc3BlY2lmaWVkIG9uICJQcmVwYXJlSW1hZ2UiIHBoYXNlLgoKICAgIEFsbCBkb2N1bWVudGVkIG9wdGlvbiBhcmUgc3VwcG9ydGVkLiBTZWUgdGhlIGZvbGxvd2luZyBsaW5rIGZvciBkZXRhaWxzOgogICAgaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTQ0MjU5LmFzcHgKICAgICM+CiAgICAkT3B0aW9uUGFyc2VyID0gTmV3LU9wdGlvblBhcnNlcgoKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBQ1RJT04iIC1TdHJpbmcgLUNvbnN0cmFpbnRzICJDb21wbGV0ZUltYWdlIiksICR0cnVlLCAiQ29tcGxldGVJbWFnZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSUFDQ0VQVFNRTFNFUlZFUkxJQ0VOU0VURVJNUyIgLVN3aXRjaCksICR0cnVlKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVSUk9SUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VJRCIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlBJRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTVJFUE9SVElORyIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkhJREVDT05TT0xFIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNBQ0NPVU5UIiAtU3RyaW5nKSwgJHRydWUsICJOVCBBVVRIT1JJVFlcTmV0d29yayBTZXJ2aWNlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUdUU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJCUk9XU0VSU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFTkFCTEVSQU5VIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJTlNUQUxMU1FMREFUQURJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU0FQV0QiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNFQ1VSSVRZTU9ERSIgLVN0cmluZyAtQ29uc3RyYWlucnMgKCJTUUwiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMQkFDS1VQRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxDT0xMQVRJT04iIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6VVNFUkRPTUFJTlwkRU5WOlVTRVJOQU1FIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxURU1QREJESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFRFTVBEQkxPR0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVVNFUkRCRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxVU0VSREJMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZJTEVTVFJFQU1MRVZFTCIgLVN0cmluZyAtQ29uc3RyYWludHMgKCIwIiwgIjEiLCAiMiIsICIzIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZJTEVTVFJFQU1TSEFSRU5BTUUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZUU1ZDQUNDT1VOVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRlRTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiTlBFTkFCTEVEIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVENQRU5BQkxFRCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTSU5TVEFMTE1PREUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiU2hhcmVQb2ludEZpbGVzT25seU1vZGUiLCAiRGVmYXVsdE5hdGl2ZU1vZGUiLCAiRmlsZXNPbmx5TW9kZSIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDU3RhcnR1cFR5cGUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKCiAgICByZXR1cm4gJE9wdGlvblBhcnNlcgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyQ29tcGxldGVJbWFnZVNQMVUyIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJDb21wbGV0ZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiQ29tcGxldGVJbWFnZSIgYWN0aW9uLgoKICAgIFRoaXMgY21kbGV0IHNob3VsZCBiZSB1c2VkIG9ubHkgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBTUDEgQ2ltaWxhdGl2ZSBVcGRhdGUgMiBvciBsYXRlci4KCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUNUSU9OIiAtU3RyaW5nIC1Db25zdHJhaW50cyAiQ29tcGxldGVJbWFnZSIpLCAkdHJ1ZSwgIkNvbXBsZXRlSW1hZ2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklBQ0NFUFRTUUxTRVJWRVJMSUNFTlNFVEVSTVMiIC1Td2l0Y2gpLCAkdHJ1ZSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFTlUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkNPTkZJR1VSQVRJT05GSUxFIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFUlJPUlJFUE9SVElORyIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklORElDQVRFUFJPR1JFU1MiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUElEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FNUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkJST1dTRVJTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOQUJMRVJBTlUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTExTUUxEQVRBRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTQVBXRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU0VDVVJJVFlNT0RFIiAtU3RyaW5nIC1Db25zdHJhaW5ycyAoIlNRTCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxCQUNLVVBESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTENPTExBVElPTiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1NUQVJUVVBUWVBFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXCRFTlY6VVNFUk5BTUUiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFRFTVBEQkRJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVEVNUERCTE9HRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxVU0VSREJESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFVTRVJEQkxPR0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRklMRVNUUkVBTUxFVkVMIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIjAiLCAiMSIsICIyIiwgIjMiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRklMRVNUUkVBTVNIQVJFTkFNRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRlRTVkNBQ0NPVU5UIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJOUEVOQUJMRUQiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJUQ1BFTkFCTEVEIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNJTlNUQUxMTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJTaGFyZVBvaW50RmlsZXNPbmx5TW9kZSIsICJEZWZhdWx0TmF0aXZlTW9kZSIsICJGaWxlc09ubHlNb2RlIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNTdGFydHVwVHlwZSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJVcGdyYWRlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckVkaXRpb25VcGdyYWRlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclJlcGFpciB7CiAgICAjIFRvRG86IEltcGxlbWVudAogICAgdGhyb3cgIk5vdCB5ZXQgaW1wbGVtZW50ZWQiCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJSZWJ1aWxkZGF0YWJhc2UgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyVW5pbnN0YWxsIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJJTlNUQUxMIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiSU5TVEFMTCIgYWN0aW9uLgogICAgQWxsIGRvY3VtZW50ZWQgb3B0aW9uIGFyZSBzdXBwb3J0ZWQuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yIGRldGFpbHM6CiAgICBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAogICAgIz4KICAgICRPcHRpb25QYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VyCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIlVOSU5TVEFMTCIpLCAkdHJ1ZSwgIlVOSU5TVEFMTCIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZFQVRVUkVTIiAtTGlzdCAtQ29uc3RyYWludHMgKCJTUUwiLCJTUUxFbmdpbmUiLCJSZXBsaWNhdGlvbiIsIkZ1bGxUZXh0IiwiRFEiLCJBUyIsIlJTIiwiRFFDIiwiSVMiLCJNRFMiLCJUb29scyIsIkJDIiwiQk9MIiwiQklEUyIsIkNvbm4iLCJTU01TIiwiQURWX1NTTVMiLCJEUkVQTEFZX0NUTFIiLCJEUkVQTEFZX0NMVCIsIlNOQUNfU0RLIiwiU0RLIiwiTG9jYWxEQiIpKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VOQU1FIiAtU3RyaW5nKSwgJHRydWUsICJNU1NRTFNFUlZFUiIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJJbnN0YWxsRmFpbG92ZXJDbHVzdGVyIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclByZXBhcmVGYWlsb3ZlckNsdXN0ZXIgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyQ29tcGxldGVGYWlsb3ZlckNsdXN0ZXIgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyVXBncmFkZSB7CiAgICAjIFRvRG86IEltcGxlbWVudAogICAgdGhyb3cgIk5vdCB5ZXQgaW1wbGVtZW50ZWQiCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJBZGROb2RlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclJlbW92ZU5vZGUgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9Cg==", - "SW1wb3J0LU1vZHVsZSBOZXRTZWN1cml0eQoKZnVuY3Rpb24gVGVzdC1LZXkoW3N0cmluZ10kcGF0aCwgW3N0cmluZ10ka2V5KSB7CiAgICBpZighKFRlc3QtUGF0aCAkcGF0aCkpIHsgcmV0dXJuICRmYWxzZSB9CiAgICBpZiAoKEdldC1JdGVtUHJvcGVydHkgJHBhdGgpLiRrZXkgLWVxICRudWxsKSB7IHJldHVybiAkZmFsc2UgfQogICAgcmV0dXJuICR0cnVlCn0KCmZ1bmN0aW9uIFJlc29sdmUtU1FMU2VydmVyUHJlcmVxdWlzaXRlcyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBNUyBTUUwgU2VydmVyIHByZXJlcXVpc2l0ZXMgKC5OZXQgRnJhbWV3b3JrIDMuNSkKCiAgICAuREVTQ1JJUFRJT04KICAgIEluc3RhbGxzIE1TIFNRTCBTZXJ2ZXIgcHJlcmVxdWlzaXRlcyAoLk5ldCBGcmFtZXdvcmsgMy41KQoKICAgICM+CiAgICBpZiAoLW5vdCAoVGVzdC1LZXkgIkhLTE06XFNvZnR3YXJlXE1pY3Jvc29mdFxORVQgRnJhbWV3b3JrIFNldHVwXE5EUFx2My41IiAiSW5zdGFsbCIpKSB7CiAgICAgICAgSW1wb3J0LU1vZHVsZSBTZXJ2ZXJNYW5hZ2VyCiAgICAgICAgV3JpdGUtSG9zdCAiLk5ldCBGcmFtZXdvcmsgMy41IG5vdCBmb3VuZC4gSW5zdGFsbGluZyBpdCB1c2luZyBTZXJ2ZXIgTWFuYWdlci4uLiIKICAgICAgICAkRmVhdHVyZSA9IEdldC1XaW5kb3dzRmVhdHVyZSBORVQtRnJhbWV3b3JrCiAgICAgICAgaWYgKCRGZWF0dXJlIC1lcSAkbnVsbCkgewogICAgICAgICAgICAjIFdlIGFyZSBwcm9iYWJseSBvbiBXaW5kb3dzIFNlcnZlciAyMDEyCiAgICAgICAgICAgICRGZWF0dXJlID0gR2V0LVdpbmRvd3NGZWF0dXJlIE5FVC1GcmFtZXdvcmstQ29yZQogICAgICAgIH0KICAgICAgICBpZiAoLW5vdCAkRmVhdHVyZSkgewogICAgICAgICAgICB0aHJvdyAiLk5ldCBmcmFtZXdvcmsgMy41IGZlYXR1cmUgd2FzIG5vdCBmb3VuZC4iCiAgICAgICAgfQogICAgICAgIGlmICgtbm90ICRGZWF0dXJlLkRpc3BsYXlOYW1lIC1tYXRjaCAiMy41IikgewogICAgICAgICAgICBMb2ctV2FybmluZyAiLk5ldCBmcmFtZXdvcmsgMy41IGlzIHJlcXVpcmVkLCBidXQgJCgkRmVhdHVyZS5EaXNwbGF5TmFtZSkgaXMgYXZhaWxhYmxlIGFzIFdpbmRvd3MgZmVhdHVyZS4gUHJvY2VlZGluZyB3aXRoIGluc3RhbGxhdGlvbiIKICAgICAgICB9CiAgICAgICAgW3ZvaWRdKEFkZC1XaW5kb3dzRmVhdHVyZSAkRmVhdHVyZSkKICAgIH0KfQoKZnVuY3Rpb24gTmV3LVNRTFNlcnZlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZS4gUmV0dXJucyAkdHJ1ZSBpZiBhIHJlYm9vdCBpcyByZXF1aXJlZCBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLCAKICAgICRmYWxzZSBpZiBhIHJlYm9vdCBpcyBub3QgcmVxdWlyZWQgYW5kIHRocm93cyBhbiBleGNlcHRpb24gaW4gY2FzZSBpZiBpbnN0YWxsYXRpb24gZmFpbHMuCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSBpbiB1bmF0dGVuZGVkIG1vZGUuCgogICAgLlBBUkFNRVRFUiBTZXR1cFJvb3QKICAgIE1TIFNRTCBTZXJ2ZXIgaW5zdGFsbGF0aW9uIGZpbGVzIHJvb3QgZGlyZWN0b3J5LiBOb3JtYWxseSBpdCBpcyBqdXN0IERWRCBkcml2ZSBuYW1lLgoKICAgIC5QQVJBTUVURVIgRXh0cmFGZWF0dXJlcwogICAgTGlzdCBvZiBmZWF0dXJlcyB0byBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gZGVmYXVsdCAiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCksCiAgICAgICAgW0hhc2h0YWJsZV0kRXh0cmFPcHRpb25zID0gQHt9CiAgICApCgogICAgJFNldHVwRGlyID0gR2V0LUl0ZW0gJFNldHVwUm9vdAogICAgJFNldHVwRXhlID0gJFNldHVwRGlyLkdldEZpbGVzKCJzZXR1cC5leGUiKVswXQoKICAgIFJlc29sdmUtU1FMU2VydmVyUHJlcmVxdWlzaXRlcwoKICAgICRwYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VySW5zdGFsbAogICAgJEV4aXRDb2RlID0gJHBhcnNlci5FeGVjdXRlQmluYXJ5KCRTZXR1cEV4ZS5GdWxsTmFtZSwgQHsiUSIgPSAkbnVsbDsgIkZFQVRVUkVTIiA9IEAoIlNRTEVuZ2luZSIsICJDb25uIiwgIlNTTVMiLCAiQURWX1NTTVMiKSArICRFeHRyYUZlYXR1cmVzfSArICRFeHRyYU9wdGlvbnMpCgogICAgaWYgKCRFeGl0Q29kZSAtZXEgMzAxMCkgewogICAgICAgIHJldHVybiAkdHJ1ZQogICAgfQoKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICB0aHJvdyAiSW5zdGFsbGF0aW9uIGV4ZWN1dGFibGUgZXhpdGVkIHdpdGggY29kZSAkKCJ7MDpYOH0iIC1mICRFeGl0Q29kZSkgKERlY2ltYWw6ICRFeGl0Q29kZSkiCiAgICB9CgogICAgcmV0dXJuICRmYWxzZQp9CgpmdW5jdGlvbiBOZXctU1FMU2VydmVyRm9yQU9BRyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSB3aXRoIGFsbCBuZWVkZWQgZmVhdHVyZXMgdG8gc2V0IHVwIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cC4KICAgIFJldHVybnMgJHRydWUgaWYgYSByZWJvb3QgaXMgcmVxdWlyZWQgYWZ0ZXIgdGhlIGluc3RhbGxhdGlvbiwgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCAKICAgIGFuZCB0aHJvd3MgYW4gZXhjZXB0aW9uIGluIGNhc2UgaWYgaW5zdGFsbGF0aW9uIGZhaWxzLgoKICAgIC5ERVNDUklQVElPTgogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW5zdGFuY2UgaW4gdW5hdHRlbmRlZCBtb2RlLiBBbGwgZmVhdHVyZXMgZm9yIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cHMgYXJlCiAgICBpbnN0YWxsZWQuCgogICAgQWxsIGF2YWlsYWJpbGl0eSBncm91cCBtZW1iZXJzIG11c3QgYmUgaW5zdGFsbGVkIHdpdGggdGhlIHNhbWUgU1FMU3ZjVXNyRG9tYW4sIFNRTFN2Y1Vzck5hbWUgYW5kIFNRTFN2Y1VzclBhc3N3b3JkIHBhcmFtZXRlcnMuCiAgICBVc2VyIG11c3QgYmUgYSBkb21haW4gdXNlciBzaW5jZSBpdCB3aWxsIGJlIHVzZWQgZm9yIG5vZGVzIGludGVyY29ubmVjdGlvbi4KCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBTUUxTdmNVc3JEb21haW4KICAgIE1TIFNRTCBTZXJ2ZXIgdXNlciBhY2NvdW50IGRvbWFpbiBuYW1lLgoKICAgIC5QQVJBTUVURVIgU1FMU3ZjVXNyTmFtZQogICAgTVMgU1FMIFNlcnZlciB1c2VyIGFjY291bnQgbmFtZS4KCiAgICAuUEFSQU1FVEVSIFNRTFN2Y1VzclBhc3N3b3JkCiAgICBNUyBTUUwgU2VydmVyIHVzZXIgYWNjb3VudCBwYXNzd29yZC4KCiAgICAuUEFSQU1FVEVSIEV4dHJhRmVhdHVyZXMKICAgIExpc3Qgb2YgZmVhdHVyZXMgdG8gYmUgcmVtb3ZlZCBiZXNpZGVzICJTUUxFbmdpbmUiLCAiQ29ubiIsICJTU01TIiwgIkFEVl9TU01TIiwgIkRSRVBMQVlfQ1RMUiIsICJEUkVQTEFZX0NMVCIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTUUxTdmNVc3JEb21haW4sCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kU1FMU3ZjVXNyTmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTUUxTdmNVc3JQYXNzd29yZCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCksCiAgICAgICAgW0hhc2h0YWJsZV0kRXh0cmFPcHRpb25zID0gQHt9CiAgICApCgogICAgJFNldHVwRGlyID0gR2V0LUl0ZW0gJFNldHVwUm9vdAogICAgJFNldHVwRXhlID0gJFNldHVwRGlyLkdldEZpbGVzKCJzZXR1cC5leGUiKVswXQoKICAgICRTUUxVc2VyID0gIiRTUUxTdmNVc3JEb21haW5cJFNRTFN2Y1Vzck5hbWUiCiAgICAkZG9tYWluID0gTmV3LU9iamVjdCBTeXN0ZW0uRGlyZWN0b3J5U2VydmljZXMuRGlyZWN0b3J5RW50cnkoIkxEQVA6Ly8kU1FMU3ZjVXNyRG9tYWluIiwgJFNRTFN2Y1Vzck5hbWUsICRTUUxTdmNVc3JQYXNzd29yZCkKCiAgICBpZiAoJGRvbWFpbi5uYW1lIC1lcSAkbnVsbCkgewogICAgICAgIHRocm93ICJDcmVkZW50aWFscyB2YWxpZGF0aW9uIGZhaWxlZCBmb3IgdXNlciAkU1FMVXNlci4gQ2hlY2sgZG9tYWluLCBsb2dpbiBuYW1lIGFuZCBwYXNzd29yZC4iCiAgICB9CgogICAgUmVzb2x2ZS1TUUxTZXJ2ZXJQcmVyZXF1aXNpdGVzCgogICAgJHBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXJJbnN0YWxsCiAgICAkRXhpdENvZGUgPSAkcGFyc2VyLkV4ZWN1dGVCaW5hcnkoJFNldHVwRXhlLkZ1bGxOYW1lLCBAeyJRIiA9ICRudWxsOyAiRkVBVFVSRVMiID0gQCgiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIsICJEUkVQTEFZX0NUTFIiLCAiRFJFUExBWV9DTFQiKSArICRFeHRyYUZlYXR1cmVzOwogICAgICAgICJBR1RTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiQUdUU1ZDUEFTU1dPUkQiID0gJFNRTFN2Y1VzclBhc3N3b3JkOyAiQVNTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiQVNTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7ICJBU1NZU0FETUlOQUNDT1VOVFMiID0gJFNRTFVTZXI7CiAgICAgICAgIlNRTFNWQ0FDQ09VTlQiID0gJFNRTFVzZXI7ICJTUUxTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7ICJTUUxTWVNBRE1JTkFDQ09VTlRTIiA9ICRTUUxVc2VyOyAiSVNTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiSVNTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7IAogICAgICAgICJSU1NWQ0FDQ09VTlQiID0gJFNRTFVzZXI7ICJSU1NWQ1BBU1NXT1JEIiA9ICRTUUxTdmNVc3JQYXNzd29yZH0gKyAkRXh0cmFPcHRpb25zKQoKICAgIGlmICgkRXhpdENvZGUgLWVxIDMwMTApIHsKICAgICAgICByZXR1cm4gJHRydWUKICAgIH0KCiAgICBpZiAoJEV4aXRDb2RlIC1uZSAwKSB7CiAgICAgICAgdGhyb3cgIkluc3RhbGxhdGlvbiBleGVjdXRhYmxlIGV4aXRlZCB3aXRoIGNvZGUgJCgiezA6WDh9IiAtZiAkRXhpdENvZGUpIChEZWNpbWFsOiAkRXhpdENvZGUpIgogICAgfQoKICAgIHJldHVybiAkZmFsc2UKfQoKZnVuY3Rpb24gUmVtb3ZlLVNRTFNlcnZlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBVbmluc3RhbGxzIE1TIFNRTCBTZXJ2ZXIgaW5zdGFuY2UgaW5zdGFsbGVkIHdpdGggTmV3LVNRTFNlcnZlciBjbWRsZXQKCiAgICAuREVTQ1JJUFRJT04KICAgIFVuaW5zdGFsbHMgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSBpbnN0YWxsZWQgd2l0aCBOZXctU1FMU2VydmVyIGNtZGxldCBpbiB1bmF0dGVuZGVkIG1vZGUKCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBFeHRyYUZlYXR1cmVzCiAgICBMaXN0IG9mIGZlYXR1cmVzIHRvIGJlIHJlbW92ZWQgYmVzaWRlcyAiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCkKICAgICkKCiAgICAkU2V0dXBEaXIgPSBHZXQtSXRlbSAkU2V0dXBSb290CiAgICAkU2V0dXBFeGUgPSAkU2V0dXBEaXIuR2V0RmlsZXMoInNldHVwLmV4ZSIpWzBdCgogICAgJHBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXJVbmluc3RhbGwKICAgICRFeGl0Q29kZSA9ICRwYXJzZXIuRXhlY3V0ZUJpbmFyeSgkU2V0dXBFeGUuRnVsbE5hbWUsIEB7IlEiID0gJG51bGw7ICJGRUFUVVJFUyIgPSBAKCJTUUxFbmdpbmUiLCAiQ29ubiIsICJTU01TIiwgIkFEVl9TU01TIikgKyAkRXh0cmFGZWF0dXJlc30pCgogICAgaWYgKCRFeGl0Q29kZSAtbmUgMCkgewogICAgICAgIHRocm93ICJJbnN0YWxsYXRpb24gZXhlY3V0YWJsZSBleGl0ZWQgd2l0aCBjb2RlICQoInswOlg4fSIgLWYgJEV4aXRDb2RlKSIKICAgIH0KfQoKZnVuY3Rpb24gSW5zdGFsbC1TUUxTZXJ2ZXJGb3JTeXNQcmVwIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluIHN5c3ByZXAgbW9kZS4KCiAgICAuREVTQ1JJUFRJT04KICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluIHN5c3ByZXAgbW9kZS4gUmV0dXJucyAkdHJ1ZSBpZiBhIHJlYm9vdCBpcyByZXF1aXJlZCBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLCAKICAgICRmYWxzZSBpZiBhIHJlYm9vdCBpcyBub3QgcmVxdWlyZWQgYW5kIHRocm93cyBhbiBleGNlcHRpb24gaW4gY2FzZSBpZiBpbnN0YWxsYXRpb24gZmFpbHMuCgogICAgU2V0dXAgbXVzdCBiZSBjb21wbGV0ZWQgYWZ0ZXIgYm9vdGluZyByZWFybWVkIG1hY2hpbmUgYnkgdXNpbmcgQ29tcGxldGUtU1FMU2VydmVyIGNtZGxldAoKICAgIC5QQVJBTUVURVIgU2V0dXBSb290CiAgICBNUyBTUUwgU2VydmVyIGluc3RhbGxhdGlvbiBmaWxlcyByb290IGRpcmVjdG9yeS4gTm9ybWFsbHkgaXQgaXMganVzdCBEVkQgZHJpdmUgbmFtZS4KCiAgICAuUEFSQU1FVEVSIEV4dHJhRmVhdHVyZXMKICAgIExpc3Qgb2YgZmVhdHVyZXMgdG8gYmUgaW5zdGFsbGVkIGluIGFkZGl0aW9uIHRvIGRlZmF1bHQgIlNRTEVuZ2luZSIuIE5vdGUgdGhhdCBwcmlvciB0bwogICAgU1FMIFNlcnZlciB2ZXJzaW9uIDIwMTIgU2VydmljZSBQYWNrIDEgQ3VtdWxhdGl2ZSBVcGRhdGUgMiAoSmFudWFyeSAyMDEzKSBvbmx5ICJSZXBsaWNhdGlvbiIsIAogICAgIkZ1bGxUZXh0IiBhbmQgIlJTIiBtYXkgYmUgaW5zdGFsbGVkIGluIGFkZGl0aW9uIHRvICJTUUxFbmdpbmUiLiBTZWUgdGhlIGZvbGxvd2luZyBsaW5rIGZvcgogICAgZGV0aWFsczogaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTQ0MjU5LmFzcHgKCiAgICAjPgp9CgpmdW5jdGlvbiBJbnN0YWxsLVNRTFNlcnZlckZvclN5c1ByZXAgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW4gc3lzcHJlcCBtb2RlLgoKICAgIC5ERVNDUklQVElPTgogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW4gc3lzcHJlcCBtb2RlLiBSZXR1cm5zICR0cnVlIGlmIGEgcmVib290IGlzIHJlcXVpcmVkIGFmdGVyIHRoZSBpbnN0YWxsYXRpb24sIAogICAgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCBhbmQgdGhyb3dzIGFuIGV4Y2VwdGlvbiBpbiBjYXNlIGlmIGluc3RhbGxhdGlvbiBmYWlscy4KCiAgICBTZXR1cCBtdXN0IGJlIGNvbXBsZXRlZCBhZnRlciBib290aW5nIHJlYXJtZWQgbWFjaGluZSBieSB1c2luZyBDb21wbGV0ZS1TUUxTZXJ2ZXIgY21kbGV0CgogICAgLlBBUkFNRVRFUiBTZXR1cFJvb3QKICAgIE1TIFNRTCBTZXJ2ZXIgaW5zdGFsbGF0aW9uIGZpbGVzIHJvb3QgZGlyZWN0b3J5LiBOb3JtYWxseSBpdCBpcyBqdXN0IERWRCBkcml2ZSBuYW1lLgoKICAgIC5QQVJBTUVURVIgRXh0cmFGZWF0dXJlcwogICAgTGlzdCBvZiBmZWF0dXJlcyB0byBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gZGVmYXVsdCAiU1FMRW5naW5lIi4gTm90ZSB0aGF0IHByaW9yIHRvCiAgICBTUUwgU2VydmVyIHZlcnNpb24gMjAxMiBTZXJ2aWNlIFBhY2sgMSBDdW11bGF0aXZlIFVwZGF0ZSAyIChKYW51YXJ5IDIwMTMpIG9ubHkgIlJlcGxpY2F0aW9uIiwgCiAgICAiRnVsbFRleHQiIGFuZCAiUlMiIG1heSBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gIlNRTEVuZ2luZSIuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yCiAgICBkZXRpYWxzOiBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAoKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kU2V0dXBSb290LAogICAgICAgIFthcnJheV0kRXh0cmFGZWF0dXJlcyA9IEAoKQogICAgKQoKICAgICRTZXR1cERpciA9IEdldC1JdGVtICRTZXR1cFJvb3QKICAgICRTZXR1cEV4ZSA9ICRTZXR1cERpci5HZXRGaWxlcygic2V0dXAuZXhlIilbMF0KCiAgICBSZXNvbHZlLVNRTFNlcnZlclByZXJlcXVpc2l0ZXMKCiAgICAkcGFyc2VyID0gTmV3LU9wdGlvblBhcnNlclByZXBhcmVJbWFnZQogICAgJEV4aXRDb2RlID0gJHBhcnNlci5FeGVjdXRlQmluYXJ5KCRTZXR1cEV4ZS5GdWxsTmFtZSwgQHsiUVMiID0gJG51bGw7ICJGRUFUVVJFUyIgPSBAKCJTUUxFbmdpbmUiKSArICRFeHRyYUZlYXR1cmVzIH0pCgogICAgaWYgKCRFeGl0Q29kZSAtZXEgMzAxMCkgewogICAgICAgIHJldHVybiAkdHJ1ZQogICAgfQoKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICB0aHJvdyAiSW5zdGFsbGF0aW9uIGV4ZWN1dGFibGUgZXhpdGVkIHdpdGggY29kZSAkKCJ7MDpYOH0iIC1mICRFeGl0Q29kZSkgKERlY2ltYWw6ICRFeGl0Q29kZSkiCiAgICB9CgogICAgcmV0dXJuICRmYWxzZQp9CgpmdW5jdGlvbiBDb21wbGV0ZS1TUUxTZXJ2ZXJBZnRlclN5c1ByZXAgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ29tcGxldGVzIHByZXZpb3VzbHkgcHJlcGFyZWQgd2l0aCAiSW5zdGFsbC1TUUxTZXJ2ZXJGb3JTeXNQcmVwIiBNUyBTUUwgU2VydmVyIGFmdGVyIHRoZSBzeXN0ZW0gd2FzIHJlYXJtZWQuCgogICAgLkRFU0NSSVBUSU9OCiAgICBDb21wbGV0ZXMgcHJldmlvdXNseSBwcmVwYXJlZCB3aXRoICJJbnN0YWxsLVNRTFNlcnZlckZvclN5c1ByZXAiIE1TIFNRTCBTZXJ2ZXIgYWZ0ZXIgdGhlIHN5c3RlbSB3YXMgcmVhcm1lZC4KICAgIFJldHVybnMgJHRydWUgaWYgYSByZWJvb3QgaXMgcmVxdWlyZWQgYWZ0ZXIgdGhlIGluc3RhbGxhdGlvbiwgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCBhbmQgdGhyb3dzIAogICAgYW4gZXhjZXB0aW9uIGluIGNhc2UgaWYgaW5zdGFsbGF0aW9uIGZhaWxzLgoKICAgIFNldHVwIG11c3QgYmUgY29tcGxldGVkIGFmdGVyIGJvb3RpbmcgcmVhcm1lZCBtYWNoaW5lIGJ5IHVzaW5nIENvbXBsZXRlLVNRTFNlcnZlciBjbWRsZXQKCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdAogICAgKQoKICAgICRTZXR1cERpciA9IEdldC1JdGVtICRTZXR1cFJvb3QKICAgICRTZXR1cEV4ZSA9ICRTZXR1cERpci5HZXRGaWxlcygic2V0dXAuZXhlIilbMF0KCiAgICAkcGFyc2VyID0gTmV3LU9wdGlvblBhcnNlckNvbXBsZXRlSW1hZ2UKICAgICRFeGl0Q29kZSA9ICRwYXJzZXIuRXhlY3V0ZUJpbmFyeSgkU2V0dXBFeGUuRnVsbE5hbWUsIEB7IlFTIiA9ICRudWxsfSkKCiAgICBpZiAoJEV4aXRDb2RlIC1lcSAzMDEwKSB7CiAgICAgICAgcmV0dXJuICR0cnVlCiAgICB9CgogICAgaWYgKCRFeGl0Q29kZSAtbmUgMCkgewogICAgICAgIHRocm93ICJJbnN0YWxsYXRpb24gZXhlY3V0YWJsZSBleGl0ZWQgd2l0aCBjb2RlICQoInswOlg4fSIgLWYgJEV4aXRDb2RlKSAoRGVjaW1hbDogJEV4aXRDb2RlKSIKICAgIH0KCiAgICByZXR1cm4gJGZhbHNlCn0KCmZ1bmN0aW9uIENvbnZlcnRUby1TUUxTdHJpbmcgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ29udmVydHMgYXJndW1lbnQgdG8gYSB2YWxpZCBTUUwgc3RyaW5nIGluIHF1b3RlcwoKICAgIC5ERVNDUklQVElPTgogICAgQ29udmVydHMgYXJndW1lbnQgdG8gYSB2YWxpZCBTUUwgc3RyaW5nIGluIHF1b3Rlcy4gVGhlIHN0cmluZyBtYXkgY29udGFpbiBhbnkgY2hhcmFjdGVycy4KICAgIFNlZSBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNzk4OTkuYXNweAoKICAgIC5QQVJBTUVURVIgUwogICAgU3RyaW5nIHRvIGNvbnZlcnQKICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlLCBWYWx1ZUZyb21QaXBlbGluZSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTCiAgICApCiAgICAKICAgIHJldHVybiAiJyQoJFMgLXJlcGxhY2UgIiciLCAiJyciKSciCn0KCmZ1bmN0aW9uIENvbnZlcnRUby1TUUxOYW1lIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbnZlcnRzIGFyZ3VtZW50IHRvIGEgdmFsaWQgU1FMIG5hbWUgaW4gYnJhY2tldHMKCiAgICAuREVTQ1JJUFRJT04KICAgIENvbnZlcnRzIGFyZ3VtZW50IHRvIGEgdmFsaWQgU1FMIG5hbWUgaW4gYnJhY2tldHMuIFRoZSBzdHJpbmcgbWF5IGNvbnRhaW4gYW55IGNoYXJhY3RlcnMuCiAgICBTZWUgaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTc1ODc0LmFzcHgKCiAgICAuUEFSQU1FVEVSIFMKICAgIFN0cmluZyB0byBjb252ZXJ0CiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSwgVmFsdWVGcm9tUGlwZWxpbmUgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kUwogICAgKQogICAgcmV0dXJuICJbJCgkUyAtcmVwbGFjZSAiXSIsICJdXSIpXSIKfQoKZnVuY3Rpb24gSW52b2tlLVNRTFRleHQgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgSW52b2tlcyBTUUwgdGV4dAoKICAgIC5ERVNDUklQVElPTgogICAgSW52b2tlcyBTUUwgdGV4dC4gUmV0dXJucyByYXcgU1FMIHNlcnZlciBvdXRwdXQuCgogICAgLlBBUkFNRVRFUiBTUUwKICAgIFNRTCBUZXh0CgogICAgLlBBUkFNRVRFUiBVc2VyCiAgICBTUUwgU2VydmVyIHVzZXIgbmFtZQoKICAgIC5QQVJBTUVURVIgUGFzc3dvcmQKICAgIFNRTCBTZXJ2ZXIgdXNlciBwYXNzd29yZAogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNRTCwKICAgICAgICBbc3RyaW5nXSRVc2VyID0gJG51bGwsCiAgICAgICAgW3N0cmluZ10kUGFzc3dvcmQgPSAkbnVsbAogICAgKQoKICAgICNXcml0ZS1XYXJuaW5nICIkU1FMYG4iCiAgICAjcmV0dXJuCgogICAgJEJpbmFyeSA9IEdldC1Db21tYW5kICJzcWxjbWQuZXhlIgoKICAgICR0ZW1wRmlsZSA9IFtJTy5QYXRoXTo6R2V0VGVtcEZpbGVOYW1lKCkKICAgICR0ZW1wRmlsZSA9IEdldC1JdGVtICR0ZW1wRmlsZQogICAgU2V0LUNvbnRlbnQgLVBhdGggJHRlbXBGaWxlIC1WYWx1ZSAkU1FMCgogICAgJENvbW1hbmRMaW5lID0gQCgnLWgnLCAnLTEnLCAnLWInLCAnLWknLCAiYCIkKCR0ZW1wRmlsZS5GdWxsTmFtZSlgIiIpCiAgICBpZiAoKCRVc2VyIC1uZSAkbnVsbCkgLWFuZCAoJFVzZXIgLW5lICcnKSkgewogICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICctVScKICAgICAgICAkQ29tbWFuZExpbmUgPSAkQ29tbWFuZExpbmUgKyAkVXNlcgogICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICctUCcKICAgICAgICAkQ29tbWFuZExpbmUgPSAkQ29tbWFuZExpbmUgKyAkUGFzc3dvcmQKICAgIH0KCiAgICBXcml0ZS1EZWJ1ZyAiRXhlY3V0aW5nOiBgbiRTUUxgbiIKICAgIFtzdHJpbmddJG91dHB1dCA9ICYkQmluYXJ5ICRDb21tYW5kTGluZQoKICAgICRFeGl0Q29kZSA9ICRMYXN0RXhpdENvZGUKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICBXcml0ZS1XYXJuaW5nICRvdXRwdXQKICAgICAgICB0aHJvdyAiU1FMQ01ELkVYRSByZXR1cm5lZCB3aXRoIGV4aXQgY29kZSAkRXhpdENvZGUgd2hpbGUgcnVubmluZyAkQmluYXJ5ICRDb21tYW5kTGluZSIKICAgIH0KICAgCiAgICBSZW1vdmUtSXRlbSAkdGVtcEZpbGUKCiAgICByZXR1cm4gJG91dHB1dAp9CgpmdW5jdGlvbiBOZXctU1FMVXNlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnZva2VzIFNRTCB0ZXh0CgogICAgLkRFU0NSSVBUSU9OCiAgICBJbnZva2VzIFNRTCB0ZXh0CgogICAgLlBBUkFNRVRFUiBTUUwKICAgIFNRTCBUZXh0CgogICAgLlBBUkFNRVRFUiBVc2VyCiAgICBTUUwgU2VydmVyIHVzZXIgbmFtZQoKICAgIC5QQVJBTUVURVIgUGFzc3dvcmQKICAgIFNRTCBTZXJ2ZXIgdXNlciBwYXNzd29yZAogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNRTCwKICAgICAgICBbc3RyaW5nXSRVc2VyID0gJG51bGwsCiAgICAgICAgW3N0cmluZ10kUGFzc3dvcmQgPSAkbnVsbAogICAgKQp9CgpmdW5jdGlvbiBOZXctUGFzc3dvcmQgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyByYW5kb20gcGFzc3dvcmQgb2YgdGhlIHNwZWNpZmllZCBsZW5ndGgKCiAgICAuREVTQ1JJUFRJT04KICAgIFBhc3N3b3JkIGNvbnRhaW5zIHJhbmRvbSBjaGFyYWN0ZXJzIGEteiwgQS1aLCBudW1iZXJzIGFuZCBzcGVjaWFsIGNoYXJhY3RlcnMuCiAgICBUaGVyZSBpcyBubyBndWFyYW50ZWUgdGhhdCBhbGwgdGhlIHR5cGVzIG9mIHN5bWJvbHMgd2lsbCBiZSBwcmVzZW50IGluIHRoZSBwYXNzd29yZC4KCiAgICAuUEFSQU1FVEVSIExlbmd0aAogICAgRGVzaXJlZCBsZW5ndGggb2YgdGhlIHBhc3N3b3JkLgoKICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbaW50XSRMZW5ndGg9NgogICAgKQoKICAgICRSZXN1bHQgPSAiIgogICAgJGFscGhhID0gImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5IUAjJCVeJiooKSdgImBgXytbXVx7fXw7OiwuLzw+P34iCiAgICB3aGlsZSAoJExlbmd0aCAtZ3QgMCkgewogICAgICAgICR4ID0gR2V0LVJhbmRvbSAkYWxwaGEuTGVuZ3RoCiAgICAgICAgJGMgPSAkYWxwaGFbJHhdCiAgICAgICAgJFJlc3VsdCA9ICIkUmVzdWx0JGMiCiAgICAgICAgJExlbmd0aCA9ICRMZW5ndGggLSAxCiAgICB9CiAgICByZXR1cm4gJFJlc3VsdAp9CgpmdW5jdGlvbiBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50IHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgbWlycm9yaW5nIGVuZHBvaW50LgoKICAgIC5ERVNDUklQVElPTgogICAgTWFzdGVyIGtleSBpcyBjcmVhdGVkIGlmIG5lY2Vzc2FyeS4gSG9zdCBjZXJ0aWZpY2F0ZSBpcyBjcmVhdGVkIHdoZW4gbmVjZXNzYXJ5IGVpdGhlciAobm9ybWFsbHkgb24gZmlyc3QgZW5kcG9pbnQgY3JlYXRpb24pLgoKICAgIEVuZHBvaW50IGFuZCBjZXJ0aWZpY2F0ZSBhcmUgcmVjcmVhdGVkIGluIGNhc2UgaWYgbWFzdGVyIGtleSBkaWQgbm90IGV4aXN0ZWQgKHNob3VsZCBub3Qgbm9ybWFsbHkgaGFwcGVuKS4KCiAgICBFbmRwb2ludCBpcyByZWNyZWF0ZWQgaW4gY2FzZSBpZiBjZXJ0aWZpY2F0ZSBkaWQgbm90IGV4aXN0ZWQgKHNob3VsZCBub3QgaGFwcGVuIHVubGVzcyB0aGUgZW5kcG9pbnQgd2FzIGNyZWF0ZWQgbWFudWFsbHkpLgoKICAgIE1pcnJvcmluZyBlbmRwb2ludCBpcyBjcmVhdGVkIHVubGVzcyBvbmUgYWxyZWFkeSBleGlzdHMuIFRoZSBlbmRwb2ludCBpcyBjcmVhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBuYW1lLiBXaGVuIHRoZSBlbmRwb2ludAogICAgYWxyZWFkeSBleGlzdHMgaXMgaXMgdW5jaGFuZ2VkLgoKICAgIEVuZHBvaW50IHBvcnQgaXMgc2VsZWN0ZWQgYXV0b21hdGljYWxseSBhcyA0MDIyIG9yIGFzIGZpcnN0IGF2YWlsYWJsZSBwb3J0IGFmdGVyIDQwMjIgaW4gY2FzZSBpZiA0MDIyIGlzIGFscmVhZHkgbGlzdGVuaW5nLgogICAgSWYgdGhlcmUgaXMgbm8gZmlyZXdhbGwgcnVsZSB3aXRoIG5hbWUgJ0RhdGFiYXNlTWlycm9yaW5nLVRDUC17cG9ydG51bWJlcn0nLCBhbGxvd2luZyBydWxlIGlzIGNyZWF0ZWQuCgogICAgQ2VydGlmaWNhdGUgaXMgc3RvcmVkIGluIHRoZSBzcGVjaWZpZWQgZmlsZS4KCiAgICBSZXR1cm5zIGVuZHBvaW50IGxpc3RlbmluZyBwb3J0LgoKICAgIC5QQVJBTUVURVIgRW5jcnlwdGlvblBhc3N3b3JkCiAgICBFbmNyeXB0aW9uIHBhc3N3b3JkIHVzZWQgdG8gY3JlYXRlIGNlcnRpZmljYXRlLgoKICAgIC5QQVJBTUVURVIgQ2VydGlmaWNhdGVGaWxlTmFtZQogICAgQ2VydGlmaWNhdGUgdGFyZ2V0IGZpbGUgbmFtZS4gRmlsZSBNVVNUIE5PVCBleGlzdC4KCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRDZXJ0aWZpY2F0ZUZpbGVOYW1lCiAgICApCgogICAgJEVuZHBvaW50TmFtZSA9ICdNaXJyb3JpbmdFbmRwb2ludCcKCiAgICAkRm9sZGVyID0gR2V0LUl0ZW0gJFdvcmtEaXIKCiAgICAkSCA9ICRFbnY6Q09NUFVURVJOQU1FIC1yZXBsYWNlICdbXkEtWmEtejAtOV9dJywgJ18nCgogICAgJFBvcnQgPSBHZXQtTmV4dEZyZWVQb3J0IDQwMjIKCiAgICAkQ3JlYXRlTWFzdGVyS2V5ID0gIlVTRSBtYXN0ZXI7CgogICAgICAgICAgICAgICAgICAgICAgICBJRiBOT1QgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLnN5bW1ldHJpY19rZXlzIHdoZXJlIG5hbWUgPSAnIyNNU19EYXRhYmFzZU1hc3RlcktleSMjJykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBNQVNURVIgS0VZIEVOQ1JZUFRJT04gQlkgUEFTU1dPUkQgPSAkKENvbnZlcnRUby1TUUxTdHJpbmcgJEVuY3J5cHRpb25QYXNzd29yZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWUgPSAnJHtIfV9jZXJ0JykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRFJPUCBDRVJUSUZJQ0FURSAke0h9X2NlcnQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICAgICAgSUYgRVhJU1RTKFNFTEVDVCAqIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBUT1AgMSBgQG5hbWUgPSBuYW1lIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFWEVDICgnRFJPUCBFTkRQT0lOVCBbJyArIGBAbmFtZSArICddJykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIElGIE5PVCBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWUgPSAnJHtIfV9jZXJ0JykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBDRVJUSUZJQ0FURSAke0h9X2NlcnQgV0lUSCBTVUJKRUNUID0gJyR7SH0gZW5kcG9pbnQgY2VydGlmaWNhdGUnOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgSUYgRVhJU1RTKFNFTEVDVCAqIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBUT1AgMSBgQG5hbWUgPSBuYW1lIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFWEVDICgnRFJPUCBFTkRQT0lOVCBbJyArIGBAbmFtZSArICddJykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIEJBQ0tVUCBDRVJUSUZJQ0FURSAke0h9X2NlcnQgVE8gRklMRSA9ICQoQ29udmVydFRvLVNRTFN0cmluZyAiJENlcnRpZmljYXRlRmlsZU5hbWUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBwb3J0IGludAogICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoU0VMRUNUICogRlJPTSBzeXMuZW5kcG9pbnRzIFdIRVJFIHR5cGVfZGVzYz0nREFUQUJBU0VfTUlSUk9SSU5HJykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBgQHBvcnQgPSBwb3J0IEZST00gc3lzLnRjcF9lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnCiAgICAgICAgICAgICAgICAgICAgICAgIEVORCBFTFNFCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUkVBVEUgRU5EUE9JTlQgJChDb252ZXJ0VG8tU1FMTmFtZSAkRW5kcG9pbnROYW1lKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNUQVRFID0gU1RBUlRFRAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFTIFRDUCAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExJU1RFTkVSX1BPUlQgPSAkUG9ydAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIExJU1RFTkVSX0lQID0gQUxMCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGT1IgREFUQUJBU0VfTUlSUk9SSU5HICggCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFVVEhFTlRJQ0FUSU9OID0gQ0VSVElGSUNBVEUgJHtIfV9jZXJ0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgRU5DUllQVElPTiA9IFJFUVVJUkVEIEFMR09SSVRITSBBRVMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBST0xFID0gQUxMCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBgQHBvcnQgPSAkUG9ydAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKCiAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCAncG9ydDooJyArIENPTlZFUlQoVkFSQ0hBUiwgYEBwb3J0KSArICcpJyBhcyBwb3J0CiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICAiCgogICAgJHJhd2RhdGEgPSBJbnZva2UtU1FMVGV4dCAtU1FMICRDcmVhdGVNYXN0ZXJLZXkKICAgIFtpbnRdJFBvcnQgPSAkcmF3ZGF0YSAtcmVwbGFjZSAnLipwb3J0OlwoKFteKV0qKVwpLionLCAnJDEnCgogICAgIyBPcGVuIHBvcnQgaW4gV2luZG93cyBGaXJld2FsbAoKICAgICRQb3J0T3BlbiA9ICRmYWxzZQogICAgJFJ1bGVOYW1lID0gIkRhdGFiYXNlTWlycm9yaW5nLVRDUC0kUG9ydCIKICAgIEdldC1OZXRGaXJld2FsbFJ1bGUgfCBGb3JlYWNoLU9iamVjdCB7CiAgICAgICAgaWYgKCRfLk5hbWUgLWVxICRSdWxlTmFtZSkgewogICAgICAgICAgICAkUG9ydE9wZW4gPSAkdHJ1ZQogICAgICAgIH0KICAgIH0KICAgIGlmICgtbm90ICRQb3J0T3BlbikgewogICAgICAgICREaXNwbGF5TmFtZSA9ICJNUyBTUUwgRGF0YWJhc2UgTWlycm9yaW5nIEVuZHBvaW50IGF0IFRDUCBwb3J0ICRQb3J0IgogICAgICAgIE5ldy1OZXRGaXJld2FsbFJ1bGUgLU5hbWUgJFJ1bGVOYW1lIC1EaXNwbGF5TmFtZSAkRGlzcGxheU5hbWUgLURlc2NyaXB0aW9uICREaXNwbGF5TmFtZSAtUHJvdG9jb2wgVENQIC1Mb2NhbFBvcnQgJFBvcnQgLUVuYWJsZWQgVHJ1ZSAtUHJvZmlsZSBBbnkgLUFjdGlvbiBBbGxvdwogICAgfQogICAgIAogICAgcmV0dXJuICRQb3J0Cn0KCmZ1bmN0aW9uIENvbXBsZXRlLU1pcnJvcmluZ0VuZHBvaW50IHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbXBsZXRlcyBtaXJyb3JpbmcgZW5kcG9pbnQKCiAgICAuREVTQ1JJUFRJT04KICAgIEFsbG93cyBpbmJvdW5kIGNvbm5lY3Rpb25zIGZyb20gcmVtb3RlIGhvc3QKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpciwKICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TG9naW4sCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdFVzZXIsCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdFBhc3N3b3JkCiAgICApCgogICAgJEZvbGRlciA9IEdldC1JdGVtICRSZW1vdGVXb3JrRGlyCiAgICAkUmVtb3RlV29ya0RpciA9ICRGb2xkZXIuRnVsbE5hbWUKCiAgICAkSCA9ICRSZW1vdGVIb3N0TmFtZSAtcmVwbGFjZSAnW15BLVphLXowLTlfXScsICdfJwoKICAgIGlmICgtbm90ICRSZW1vdGVIb3N0TG9naW4pIHsKICAgICAgICAkUmVtb3RlSG9zdExvZ2luID0gIiR7SH1fbG9naW4iCiAgICB9CiAgICBpZiAoLW5vdCAkUmVtb3RlSG9zdFVzZXIpIHsKICAgICAgICAkUmVtb3RlSG9zdFVzZXIgPSAiJHtIfV91c2VyIgogICAgfQogICAgaWYgKC1ub3QgJFJlbW90ZUhvc3RQYXNzd29yZCkgewogICAgICAgICRSZW1vdGVIb3N0UGFzc3dvcmQgPSAiJChOZXctUGFzc3dvcmQgMTApYUEjMyIKICAgIH0KCiAgICAkU1FMID0gICAgICAgICAgICAgIlVTRSBtYXN0ZXI7CgogICAgICAgICAgICAgICAgICAgICAgICBJRiBOT1QgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLnNxbF9sb2dpbnMgd2hlcmUgbmFtZT0kKENvbnZlcnRUby1TUUxTdHJpbmcgJFJlbW90ZUhvc3RMb2dpbikpCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUkVBVEUgTE9HSU4gJChDb252ZXJ0VG8tU1FMTmFtZSAkUmVtb3RlSG9zdExvZ2luKSBXSVRIIFBBU1NXT1JEID0gJChDb252ZXJ0VG8tU1FMU3RyaW5nICRSZW1vdGVIb3N0UGFzc3dvcmQpOwogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIElGIE5PVCBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuc3lzdXNlcnMgd2hlcmUgbmFtZT0kKENvbnZlcnRUby1TUUxTdHJpbmcgJFJlbW90ZUhvc3RVc2VyKSkKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBVU0VSICQoQ29udmVydFRvLVNRTE5hbWUgJFJlbW90ZUhvc3RVc2VyKSBGT1IgTE9HSU4gJChDb252ZXJ0VG8tU1FMTmFtZSAkUmVtb3RlSG9zdExvZ2luKTsKICAgICAgICAgICAgICAgICAgICAgICAgRU5ECiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWU9JyR7SH1fcmVtb3RlX2NlcnQnKQogICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgRFJPUCBDRVJUSUZJQ0FURSAke0h9X3JlbW90ZV9jZXJ0CiAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBHTwoKICAgICAgICAgICAgICAgICAgICAgICAgQ1JFQVRFIENFUlRJRklDQVRFICR7SH1fcmVtb3RlX2NlcnQgQVVUSE9SSVpBVElPTiAkKENvbnZlcnRUby1TUUxOYW1lICRSZW1vdGVIb3N0VXNlcikgRlJPTSBGSUxFID0gJChDb252ZXJ0VG8tU1FMU3RyaW5nICIkUmVtb3RlV29ya0RpclxjZXJ0aWZpY2F0ZS5jZXIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICBTRUxFQ1QgVE9QIDEgYEBuYW1lID0gbmFtZSBGUk9NIHN5cy5lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnCiAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCAnbmFtZTooJyArIGBAbmFtZSArICcpJyBhcyBuYW1lCiAgICAgICAgICAgICAgICAgICAgICAgICIKCiAgICAkcmF3ZGF0YSA9IEludm9rZS1TUUxUZXh0IC1TUUwgJFNRTAogICAgJEVuZHBvaW50TmFtZSA9ICRyYXdkYXRhIC1yZXBsYWNlICcuKm5hbWU6XCgoW14pXSopXCkuKicsICckMScKICAgICRTUUwgPSAgICAgICAgICAgICAiR1JBTlQgQ09OTkVDVCBPTiBFTkRQT0lOVDo6JChDb252ZXJ0VG8tU1FMTmFtZSAkRW5kcG9pbnROYW1lKSBUTyAkKENvbnZlcnRUby1TUUxOYW1lICRSZW1vdGVIb3N0TG9naW4pIgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFNRTCkKfQoKZnVuY3Rpb24gQ29tcGxldGUtU1FMTWlycm9yIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbXBsZXRlcyBjcmVhdGlvbiBvZiBtaXJyb3JlZCBTUUwgZGF0YWJhc2UKCiAgICAuREVTQ1JJUFRJT04KICAgIFRoaXMgY21kbGV0IHNob3VsZCBiZSBmaXJzdCBleGVjdXRlZCBvbiBtaXJyb3Igc2VydmVyIGFuZCB0aGVuIG9uIHByaW5jaXBhbCBzZXJ2ZXIuCiAgICBPdGhlcndpc2UgaXQgd2lsbCBmYWlsIChob3dldmVyIGl0IG1heSBiZSBleGVjdXRlZCBhZ2FpbiB3aXRoIG5vIGhhcm0pLgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbSW50XSRSZW1vdGVQb3J0LAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFiYXNlTmFtZQogICAgKQoKICAgICRVcmwgPSAiVENQOi8vJHtSZW1vdGVIb3N0TmFtZX06JHtSZW1vdGVQb3J0fSIKICAgICRBbHRlckRiID0gIkFMVEVSIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgU0VUIFBBUlRORVIgPSAkKENvbnZlcnRUby1TUUxTdHJpbmcgJFVybCk7CiAgICAgICAgICAgICAgICBHTyIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRBbHRlckRiKQp9CgpmdW5jdGlvbiBOZXctU1FMRGF0YWJhc2UgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBlbXB0eSBTUUwgZGF0YWJhc2UKCiAgICAuREVTQ1JJUFRJT04KICAgIENyZWF0ZXMgZW1wdHkgU1FMIGRhdGFiYXNlIHdpdGggZGVmYXVsdCBzZXR0aW5ncy4gRmFpbHMgaW4gY2FzZSBpcyB0aGUgZGF0YWJhc2UgYWxyZWFkeSBleGlzdHMuCgogICAgLlBBUkFNRVRFUiBEYXRhQmFzZU5hbWUKICAgIERhdGFiYXNlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBtZGZGaWxlCiAgICBOYW1lIG9mIHRoZSBNREYgKGRhdGEpIGZpbGUuIElmIG5vdCBzcGVjaWZpZWQsIHRoZSBmb2xsb3dpbmcgdmFsdWUgaXMgdXNlZDoKICAgICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVx7RGF0YUJhc2VQYXRoTmFtZX0ubWRmIgogICAgV2hlcmUge0RhdGFCYXNlUGF0aE5hbWV9IGlzIGRhdGFiYXNlIG5hbWUgd2l0aCBhbGwgYnV0IEEtWiwgYS16LCAwLTkgY2hhcmFjdGVycwogICAgcmVwbGFjZWQgYnkgdW5kZXJzY29yZS4KCiAgICAuUEFSQU1FVEVSIERhdGFCYXNlTmFtZQogICAgTmFtZSBvZiB0aGUgTERGICh0cmFuc2FjdGlvbiBsb2cpIGZpbGUuIElmIG5vdCBzcGVjaWZpZWQsIHRoZSBmb2xsb3dpbmcgdmFsdWUgaXMgdXNlZDoKICAgICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVx7RGF0YUJhc2VQYXRoTmFtZX1fbG9nLm1kZiIKICAgIFdoZXJlIHtEYXRhQmFzZVBhdGhOYW1lfSBpcyBkYXRhYmFzZSBuYW1lIHdpdGggYWxsIGJ1dCBBLVosIGEteiwgMC05IGNoYXJhY3RlcnMKICAgIHJlcGxhY2VkIGJ5IHVuZGVyc2NvcmUuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZSwKICAgICAgICBbU3RyaW5nXSRtZGZGaWxlPSRudWxsLAogICAgICAgIFtTdHJpbmddJGxkZkZpbGU9JG51bGwKICAgICkKCiAgICAkRGF0YUJhc2VQYXRoTmFtZSA9ICREYXRhQmFzZU5hbWUgLXJlcGxhY2UgJ1teMC05YS16QS1aXScsICdfJwogICAgaWYgKC1ub3QgJG1kZkZpbGUpIHsKICAgICAgICAkbWRmRmlsZSA9ICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVwke0RhdGFCYXNlUGF0aE5hbWV9Lm1kZiIKICAgIH0KICAgIGlmICgtbm90ICRsZGZGaWxlKSB7CiAgICAgICAgJGxkZkZpbGUgPSAiQzpcUHJvZ3JhbSBGaWxlc1xNaWNyb3NvZnQgU1FMIFNlcnZlclxNU1NRTDExLk1TU1FMU0VSVkVSXE1TU1FMXERBVEFcJHtEYXRhQmFzZVBhdGhOYW1lfV9sb2cubGRmIgogICAgfQoKICAgICROZXdEYXRhYmFzZSA9ICIKICAgICAgICBDUkVBVEUgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKQogICAgICAgICAgICAgICAgQ09OVEFJTk1FTlQgPSBOT05FCiAgICAgICAgICAgICAgICBPTiAgUFJJTUFSWSAKICAgICAgICAgICAgKCBOQU1FID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAkRGF0YUJhc2VOYW1lKSwgRklMRU5BTUUgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICRtZGZGaWxlKSAsIFNJWkUgPSA0MDk2S0IgLCBGSUxFR1JPV1RIID0gMTAyNEtCICkKICAgICAgICAgICAgICAgIExPRyBPTiAKICAgICAgICAgICAgKCBOQU1FID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJHtEYXRhQmFzZU5hbWV9X2xvZyIpLCBGSUxFTkFNRSA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgJGxkZkZpbGUpICwgU0laRSA9IDEwMjRLQiAsIEZJTEVHUk9XVEggPSAxMCUpCiAgICAgICAgR08KICAgICAgICBVU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKQogICAgICAgIEdPCiAgICAgICAgSUYgTk9UIEVYSVNUUyAoU0VMRUNUIG5hbWUgRlJPTSBzeXMuZmlsZWdyb3VwcyBXSEVSRSBpc19kZWZhdWx0PTEgQU5EIG5hbWUgPSBOJ1BSSU1BUlknKSBBTFRFUiBEQVRBQkFTRSAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIE1PRElGWSBGSUxFR1JPVVAgW1BSSU1BUlldIERFRkFVTFQKICAgICAgICBHTyIKCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkTmV3RGF0YWJhc2UpCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nUHJpbmNpcGFsU3RlcDEgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgcHJpbmNpcGFsIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMSkKCiAgICAuREVTQ1JJUFRJT04KICAgIEluaXRpYWxpemVzIG1pcnJvcmluZyBlbmRwb2ludCAodGhpcyBpcyBhYnNvbHV0ZWx5IHN5bW1ldHJpYyBzdGVwIHRvIHRoZSBtaXJyb3IgaW5pdCkuIEluIGFkZGl0aW9uIHRvIHRoYXQgaXQgY3JlYXRlcwogICAgYSBkYXRhYmFzZSBhbmQgc3RvcmVzIGJhY2t1cHMgb2YgaXQgYW5kIGl0cyB0cmFuc2FjdGlvbiBsb2cgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIHRoZSBlbmRwb2ludCBjZXJ0aWZpY2F0ZS4KCiAgICBBIGZpcmV3YWxsIHJ1bGUgaXMgY3JlYXRlZCBmb3IgZW5kcG9pbnQgaWYgbmVjZXNzYXJ5LgoKICAgIC5QQVJBTUVURVIgV29ya0RpcgogICAgV29ya2luZCBkaXJlY3RvcnkuIFRoaXMgZGlyZWN0b3J5IHNob3VsZCBiZSB0cmFuZmVycmVkIHRvIHRoZSBtaXJyb3Igc2VydmVyIGFmdGVyIHRoaXMKICAgIHN0ZXAgaXMgZXhlY3V0ZWQuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWUKICAgIE1pcnJvcmVkIGRhdGFiYXNlIG5hbWUuIFRoaXMgbmFtZSBNVVNUIGJlIHVzZSBhdCBtaXJyb3Igc2VydmVyIGVpdGhlci4KICAgIAogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZQogICAgKQoKICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCA9ICIkKE5ldy1QYXNzd29yZCAxMClhQSMzIgoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgW3ZvaWRdKE5ldy1JdGVtIC1UeXBlIERpcmVjdG9yeSAkV29ya0RpcikKICAgIH0KICAgICRXb3JrRGlyID0gKEdldC1JdGVtICRXb3JrRGlyKS5GdWxsTmFtZQogICAgaWYgKChHZXQtQ2hpbGRJdGVtIC1QYXRoICRXb3JrRGlyKS5MZW5ndGggLWd0IDApIHsKICAgICAgICB0aHJvdyAiV29ya2luZyBkaXJlY3RvcnkgJFdvcmtEaXIgaXMgbm90IGVtcHR5IgogICAgfQoKICAgICRFbmRwb2ludFBvcnQgPSBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50ICRFbmNyeXB0aW9uUGFzc3dvcmQgIiRXb3JrRGlyXGNlcnRpZmljYXRlLmNlciIKICAgICRFbmRwb2ludFBvcnQgfCBTZXQtQ29udGVudCAiJFdvcmtEaXJcZW5kcG9pbnQtcG9ydC50eHQiCiAgICBOZXctU1FMRGF0YWJhc2UgJERhdGFCYXNlTmFtZQoKICAgICRCYWNrdXBEYiA9ICJCQUNLVVAgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcU291cmNlLmJhayIpIFdJVEggTk9GT1JNQVQsIElOSVQsIE5BTUUgPSBOJ0Z1bGwgRGF0YWJhc2UgQmFja3VwJywgU0tJUCwgTk9SRVdJTkQsIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwRGIpCiAgICAkQmFja3VwTG9nID0gIkJBQ0tVUCBMT0cgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcU291cmNlX2xvZy5iYWsiKSBXSVRIIE5PRk9STUFULCBJTklULCAgTkFNRSA9IE4nVHJhbnNhY3Rpb24gTG9nICBCYWNrdXAnLCBTS0lQLCBOT1JFV0lORCwgTk9VTkxPQUQsIFNUQVRTID0gMTAKICAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwTG9nKQp9CgpmdW5jdGlvbiBJbml0aWFsaXplLVNRTE1pcnJvcmluZ1ByaW5jaXBhbFN0ZXAyIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIFByZXBhcmVzIHByaW5jaXBhbCBTUUwgU2VydmVyIGZvciBkYXRhYmFzZSBtaXJyb3JpbmcgKFN0YWdlIDIpCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbXBvcnRzIHJlbW90ZSBzZXJ2ZXIgY2VydGlmaWNhdGUgYW5kIGdyYW50cyBpdCB3aXRoIGFjY2VzcyB0byB0aGUgbWlycm9yaW5nIGVuZHBvaW50LgoKICAgIC5QQVJBTUVURVIgUmVtb3RlSG9zdE5hbWUKICAgIFJlbW90ZSAobWlycm9yKSBob3N0IG5hbWUuIEZRRE4gaXMgcHJlZmVycmVkLCBidXQgTmV0QklPUyBuYW1lcyBhbmQgSVAgYWRkcmVzc2VzIGFyZSBhbHNvIGFjY2VwdGVkLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlV29ya0RpcgogICAgUGF0aCB0byBhIGNvcHkgb2Ygd29ya2RpciBvYnRhaW5lZCBmcm9tIG1pcnJvciBtYWNoaW5lIGNyZWF0ZWQgb24gU3RhZ2UgMS4KICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpcgogICAgKQoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFJlbW90ZVdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIlJlbW90ZSB3b3JrIGRpciAnJFJlbW90ZVdvcmtEaXInIHdhcyBub3QgZm91bmQiCiAgICB9CiAgICAkUmVtb3RlV29ya0RpciA9IChHZXQtSXRlbSAkUmVtb3RlV29ya0RpcikuRnVsbE5hbWUKCiAgICBDb21wbGV0ZS1NaXJyb3JpbmdFbmRwb2ludCAkUmVtb3RlSG9zdE5hbWUgJFJlbW90ZVdvcmtEaXIKfQoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1TUUxNaXJyb3JpbmdQcmluY2lwYWxTdGVwMyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBQcmVwYXJlcyBwcmluY2lwYWwgU1FMIFNlcnZlciBmb3IgZGF0YWJhc2UgbWlycm9yaW5nIChTdGFnZSAzKQoKICAgIC5ERVNDUklQVElPTgogICAgQ29tcGxldGVzIG1pcnJvciBjcmVhdGlvbi4gVGhpcyBzdGVwIG11c3QgYmUgZ2xvYmFsbHkgdGhlIGxhc3Qgb25lIGluIG1pcnJvciBjcmVhdGlvbiBzZXF1ZW5jZS4KCiAgICBOb3RlIHRoYXQgdGhlIHJlbW90ZSBob3N0IGNlcnRpZmljYXRlIGlzIHZhbGlkIGZyb20gdGhlIHRpbWUgaXQgaXMgY3JlYXRlZCB0aGVyZS4gU28KICAgIHRoaXMgc3RlcCB3aWxsIGZhaWwgaWYgdGhlcmUgaXMgbm90aWNhYmxlIGRpZmZlcmVudCBpbiB0aW1lIGxvY2FsIGFuZCByZW1vdGUgbWFjaGluZXMuCgogICAgLlBBUkFNRVRFUiBSZW1vdGVIb3N0TmFtZQogICAgUmVtb3RlIChwcmluY2lwYWwpIGhvc3QgbmFtZS4gRlFETiBpcyBwcmVmZXJyZWQsIGJ1dCBOZXRCSU9TIG5hbWVzIGFuZCBJUCBhZGRyZXNzZXMgYXJlIGFsc28gYWNjZXB0ZWQuCgogICAgLlBBUkFNRVRFUiBSZW1vdGVXb3JrRGlyCiAgICBQYXRoIHRvIGEgY29weSBvZiB3b3JrZGlyIG9idGFpbmVkIGZyb20gcHJpbmNpcGFsIG1hY2hpbmUgY3JlYXRlZCBvbiBTdGFnZSAxLgoKICAgIC5QQVJBTUVURVIgRGF0YWJhc2VOYW1lCiAgICBNaXJyb3JlZCBkYXRhYmFzZSBuYW1lLiBUaGlzIG5hbWUgTVVTVCBtYXRjaCBwcmluY2lwYWwgZGF0YWJhc2UgbmFtZSBhbmQgbmFtZSBwcm92aWRlZCBvbiBzdGVwIDEuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZUhvc3ROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZVdvcmtEaXIsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kRGF0YWJhc2VOYW1lCiAgICApCgogICAgW2ludF0kcG9ydCA9IEdldC1Db250ZW50ICIke1JlbW90ZVdvcmtEaXJ9XGVuZHBvaW50LXBvcnQudHh0IgogICAgQ29tcGxldGUtU1FMTWlycm9yICRSZW1vdGVIb3N0TmFtZSAkcG9ydCAkRGF0YWJhc2VOYW1lCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDEgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UxKQoKICAgIC5ERVNDUklQVElPTgogICAgSW5pdGlhbGl6ZXMgbWlycm9yaW5nIGVuZHBvaW50IGZvciBtaXJyb3Igc2VydmVyLiBTdG9yZXMgbWlycm9yaW5nIGVuZHBvaW50IGNlcnRpZmljYXRlIGluIFdvcmtkaXIuCgogICAgLlBBUkFNRVRFUiBXb3JrRGlyCiAgICBXb3JraW5kIGRpcmVjdG9yeS4gVGhpcyBkaXJlY3Rvcnkgc2hvdWxkIGJlIHRyYW5mZXJyZWQgdG8gdGhlIHByaW5jaXBhbCBzZXJ2ZXIgYWZ0ZXIgdGhpcwogICAgc3RlcCBpcyBleGVjdXRlZC4KCiAgICAuUEFSQU1FVEVSIERhdGFiYXNlTmFtZQogICAgTWlycm9yZWQgZGF0YWJhc2UgbmFtZS4gVGhpcyBuYW1lIE1VU1QgbWF0Y2ggcHJpbmNpcGFsIGRhdGFiYXNlIG5hbWUuCgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFiYXNlTmFtZQogICAgKQoKICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCA9ICIkKE5ldy1QYXNzd29yZCAxMClhQSMzIgoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgW3ZvaWRdKE5ldy1JdGVtIC1UeXBlIERpcmVjdG9yeSAkV29ya0RpcikKICAgIH0KICAgICRXb3JrRGlyID0gKEdldC1JdGVtICRXb3JrRGlyKS5GdWxsTmFtZQoKICAgICRFbmRwb2ludFBvcnQgPSBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50ICRFbmNyeXB0aW9uUGFzc3dvcmQgIiRXb3JrRGlyXGNlcnRpZmljYXRlLmNlciIKICAgICRFbmRwb2ludFBvcnQgfCBTZXQtQ29udGVudCAiJFdvcmtEaXJcZW5kcG9pbnQtcG9ydC50eHQiCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDIgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMikKCiAgICAuREVTQ1JJUFRJT04KICAgIEltcG9ydHMgcmVtb3RlIHNlcnZlciBjZXJ0aWZpY2F0ZSBhbmQgZ3JhbnRzIGl0IHdpdGggYWNjZXNzIHRvIHRoZSBtaXJyb3JpbmcgZW5kcG9pbnQuCiAgICBSZXN0b3JlcyBkYXRhYmFzZSBvYnRhaW5lZCBmcm9tIHByaW5jaXBhbCBhbmQgbGVhdmVzIGl0IGluICdSZXN0b3JpbmcnIHN0YXRlLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlSG9zdE5hbWUKICAgIFJlbW90ZSAocHJpbmNpcGFsKSBob3N0IG5hbWUuIEZRRE4gaXMgcHJlZmVycmVkLCBidXQgTmV0QklPUyBuYW1lcyBhbmQgSVAgYWRkcmVzc2VzIGFyZSBhbHNvIGFjY2VwdGVkLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlV29ya0RpcgogICAgUGF0aCB0byBhIGNvcHkgb2Ygd29ya2RpciBvYnRhaW5lZCBmcm9tIHByaW5jaXBhbCBtYWNoaW5lIGNyZWF0ZWQgb24gU3RhZ2UgMS4KCiAgICAuUEFSQU1FVEVSIERhdGFiYXNlTmFtZQogICAgTWlycm9yZWQgZGF0YWJhc2UgbmFtZS4gVGhpcyBuYW1lIE1VU1QgbWF0Y2ggcHJpbmNpcGFsIGRhdGFiYXNlIG5hbWUuCgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZQogICAgKQoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFJlbW90ZVdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIlJlbW90ZSB3b3JrIGRpciAnJFJlbW90ZVdvcmtEaXInIHdhcyBub3QgZm91bmQiCiAgICB9CiAgICAkUmVtb3RlV29ya0RpciA9IChHZXQtSXRlbSAkUmVtb3RlV29ya0RpcikuRnVsbE5hbWUKCiAgICBDb21wbGV0ZS1NaXJyb3JpbmdFbmRwb2ludCAkUmVtb3RlSG9zdE5hbWUgJFJlbW90ZVdvcmtEaXIKCiAgICAkUmVzdG9yZURiID0gIlJFU1RPUkUgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBGUk9NIERJU0sgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICIkUmVtb3RlV29ya0RpclxTb3VyY2UuYmFrIikgV0lUSCBGSUxFID0gMSwgTk9SRUNPVkVSWSwgTk9VTkxPQUQsIFJFUExBQ0UsIFNUQVRTID0gNQogICAgICAgICAgICAgICAgICBHTyIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRSZXN0b3JlRGIpCiAgICAkUmVzdG9yZUxvZyA9ICJSRVNUT1JFIExPRyAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIEZST00gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRSZW1vdGVXb3JrRGlyXFNvdXJjZV9sb2cuYmFrIikgV0lUSCBGSUxFID0gMSwgTk9SRUNPVkVSWSwgTk9VTkxPQUQsIFNUQVRTID0gMTAKICAgICAgICAgICAgICAgICAgIEdPIgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVMb2cpCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDMgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMykKCiAgICAuREVTQ1JJUFRJT04KICAgIENvbXBsZXRlcyBtaXJyb3IgY3JlYXRpb24uIFRoaXMgc3RlcCBtdXN0IGJlIGV4ZWN1dGVkIHN0cmljdGx5IGJlZm9yZSBzeW1tZXRyaWMgc3RlcCBvbiB0aGUgcHJpbmNpcGFsLgoKICAgIE5vdGUgdGhhdCB0aGUgcmVtb3RlIGhvc3QgY2VydGlmaWNhdGUgaXMgdmFsaWQgZnJvbSB0aGUgdGltZSBpdCBpcyBjcmVhdGVkIHRoZXJlLiBTbwogICAgdGhpcyBzdGVwIHdpbGwgZmFpbCBpZiB0aGVyZSBpcyBub3RpY2FibGUgZGlmZmVyZW50IGluIHRpbWUgbG9jYWwgYW5kIHJlbW90ZSBtYWNoaW5lcy4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZUhvc3ROYW1lCiAgICBSZW1vdGUgKHByaW5jaXBhbCkgaG9zdCBuYW1lLiBGUUROIGlzIHByZWZlcnJlZCwgYnV0IE5ldEJJT1MgbmFtZXMgYW5kIElQIGFkZHJlc3NlcyBhcmUgYWxzbyBhY2NlcHRlZC4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZVdvcmtEaXIKICAgIFBhdGggdG8gYSBjb3B5IG9mIHdvcmtkaXIgb2J0YWluZWQgZnJvbSBwcmluY2lwYWwgbWFjaGluZSBjcmVhdGVkIG9uIFN0YWdlIDEuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWUKICAgIE1pcnJvcmVkIGRhdGFiYXNlIG5hbWUuIFRoaXMgbmFtZSBNVVNUIG1hdGNoIHByaW5jaXBhbCBkYXRhYmFzZSBuYW1lLgoKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpciwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSREYXRhYmFzZU5hbWUKICAgICkKCiAgICBbaW50XSRwb3J0ID0gR2V0LUNvbnRlbnQgIiR7UmVtb3RlV29ya0Rpcn1cZW5kcG9pbnQtcG9ydC50eHQiCiAgICBDb21wbGV0ZS1TUUxNaXJyb3IgJFJlbW90ZUhvc3ROYW1lICRwb3J0ICREYXRhYmFzZU5hbWUKfQoKZnVuY3Rpb24gR2V0LU5leHRGcmVlUG9ydCB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBSZXR1cm5zIHNwZWNpZmllZCBkZXNpcmVkIHBvcnQgb3IgY2xvc2VzdCBuZXh0IG9uZSB1bm9jY3VwaWVkLgoKICAgIC5QQVJBTUVURVIgUG9ydAogICAgRGVzaXJlZCBwb3J0IG51bWJlci4KCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtpbnRdJFBvcnQKICAgICkKICAgICRPcGVuUG9ydHMgPSBuZXRzdGF0IC1hb24gfCBzZWxlY3Qtc3RyaW5nICdMSVNURU5JTkcnIHwgRm9yZWFjaC1PYmplY3QgeyAoKCRfIC1yZXBsYWNlICdeXHMqJywgJycgLXNwbGl0ICdccysnKVsxXSAtc3BsaXQgJy4qOicpWzFdIH0gfCBTb3J0LU9iamVjdCB8IEdldC1VbmlxdWUKICAgIHdoaWxlICgkT3BlblBvcnRzLkNvbnRhaW5zKCR7UG9ydH0pKSB7CiAgICAgICAgJFBvcnQgPSAkUG9ydCArIDEKICAgIH0KICAgIHJldHVybiAkUG9ydAp9CgpmdW5jdGlvbiBJbml0aWFsaXplLUFsd2F5c09uIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluaXRpYWxpemVzIEFsd2F5c09uIGNsdXN0ZXJpbmcgb24gbG9jYWwgU1FMIHNlcnZlciBhbmQgY3JlYXRlcyBBbHdheXNPbiBlbmRwb2ludCBsaXN0ZW5lci4gUmV0dXJucyBBbHdheXNPbiBlbmRwb2ludCBwb3J0IG51bWJlci4KCiAgICAuREVTQ1JJUFRJT04KICAgIEVuYWJsZXMgQWx3YXlzT24gY2x1c3RlcmluZyBvbiBsb2NhbCBTUUwgc2VydmVyLiBDcmVhdGVzIEFsd2F5c09uIFRDUCBlbmRwb2ludCBvbiBwb3J0IDUwMjIgb3IgZ3JlYXRlciBpZiB0aGUgb25lIGlzIG9jY3VwaWVkLiAgIAogICAgIz4KCiAgICBpZiAoIShUZXN0LVBhdGggU1FMU0VSVkVSOlwpKSB7CiAgICAgICAgSW1wb3J0LU1vZHVsZSBzcWxwcwogICAgfQogICAgJE1hY2hpbmVOYW1lID0gKEdldC1DaGlsZEl0ZW0gU1FMU0VSVkVSOlxTUUwpWzBdLlBTQ2hpbGROYW1lCiAgICAkSW5zdGFuY2VOYW1lID0gKEdldC1DaGlsZEl0ZW0gU1FMU0VSVkVSOlxTUUxcJE1hY2hpbmVOYW1lKS5QU0NoaWxkTmFtZQogICAgJEFsd2F5c09uRW5hYmxlZCA9ICgoR2V0LUl0ZW0gU1FMU0VSVkVSOlxTUUxcJE1hY2hpbmVOYW1lXCRJbnN0YW5jZU5hbWUpIHwgc2VsZWN0IElzSGFkckVuYWJsZWQpLklzSGFkckVuYWJsZWQKICAgIGlmICgtbm90ICRBbHdheXNPbkVuYWJsZWQpIHsKICAgICAgICBFbmFibGUtU3FsQWx3YXlzT24gLVBhdGggIlNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lIiAtRm9yY2UKICAgIH0KICAgICRJbnN0YW5jZSA9IEdldC1JdGVtIFNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lCiAgICAkZW5kcG9pbnQgPSAkSW5zdGFuY2UuRW5kcG9pbnRzWyJBbHdheXNPbkVuZHBvaW50Il0KICAgIGlmICgtbm90ICRlbmRwb2ludCkgewogICAgICAgICRQb3J0ID0gR2V0LU5leHRGcmVlUG9ydCA1MDIyCiAgICAgICAgJGVuZHBvaW50ID0gTmV3LVNxbEhhZHJFbmRwb2ludCBBbHdheXNPbkVuZHBvaW50IC1Qb3J0ICRQb3J0IC1QYXRoIFNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lCiAgICB9IGVsc2UgewogICAgICAgICRQb3J0ID0gJGVuZHBvaW50LlByb3RvY29sLlRjcC5MaXN0ZW5lclBvcnQKICAgIH0gCiAgICBpZiAoJGVuZHBvaW50LkVuZHBvaW50U3RhdGUgLW5lICJTdGFydGVkIikgewogICAgICAgICRlbmRwb2ludC5TdGFydCgpCiAgICB9ICAgIAogICAgcmV0dXJuICRQb3J0Cn0KCmZ1bmN0aW9uIE5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgbmV3IEFsd2F5c09uIGF2YWlsYWJpbGl0eSBncm91cCBvbiBwcmltYXJ5IHJlcGxpY2EuCgogICAgLkRFU0NSSVBUSU9OCiAgICBDcmVhdGVzIG5ldyBBbHdheXNPbiBhdmFpbGFiaWxpdHkgZ3JvdXAgb24gcHJpbWFyeSByZXBsaWNhLgoKICAgIC5QQVJBTUVURVIgV29ya0RpcgogICAgV29ya2luZCBkaXJlY3RvcnkuIFRoaXMgZGlyZWN0b3J5IHNob3VsZCBiZSB0cmFuZmVycmVkIHRvIHRoZSByZXBsaWNhIHNlcnZlcihzKSBhZnRlciB0aGlzCiAgICBzdGVwIGlzIGV4ZWN1dGVkLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgQXZhaWxhYmlsaXR5IGdyb3VwIG5hbWUuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWVzCiAgICBSZXBsaWNhIGRhdGFiYXNlKHMpIG5hbWVzLgoKICAgIC5QQVJBTUVURVIgUmVwbGljYURlZnMKICAgIEFycmF5IG9mIHJlcGxpY2EgZGVmaW5pdGlvbi4gRWFjaCBkZWZpbml0aW9uIGlzIGEgaGFzaCB0YWJsZSB3aXRoIHJlcGxpY2Etc3BlY2lmaWMgdmFsdWVzLgogICAgCiAgICBNYW5kYXRvcnkgcmVwbGljYSBkZWZpbml0aW9uIHZhbHVlcyBhcmU6CgogICAgICAgICogW1N0cmluZ10gU0VSVkVSX0lOU1RBTkNFICAgLSBSZXBsaWNhIHNlcnZlciBpbnN0YW5jZSBuYW1lCiAgICAgICAgKiBbU3RyaW5nXSBFTkRQT0lOVF9VUkwgICAgICAtIFJlcGxpY2Egc2VydmVyIGVuZHBvaW50IFVSTC4gTm9ybWFsbHkgaXQgaXMgVENQOi8vZnVsbHkucXVhbGlmaWVkLmRvbWFpbi5uYW1lOjUwMjIgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBvcnQgbnVtYmVyIHNob3VsZCBiZSBvYnRhaW5lZCB3aXRoIEluaXRpYWxpemUtQWx3YXlzT24gYXQgdGhlIHJlcGxpY2Egc2VydmVyCiAgICAgICAgKiBbU3RyaW5nXSBBVkFJTEFCSUxJVFlfTU9ERSAtIFJlcGxpY2EgYXZhaWxhYmlsaXR5IG1vZGUuIENhbiBiZSAiU1lOQ0hST05PVVNfQ09NTUlUIiBvciAiQVNZTkNIUk9OT1VTX0NPTU1JVCIgb25seS4KICAgICAgICAqIFtTdHJpbmddIEZBSUxPVkVSX01PREUgICAgIC0gUmVwbGljYSBhdmFpbGFiaWxpdHkgbW9kZS4gQ2FuIGJlICJNQU5VQUwiIG9yICJBVVRPTUFUSUMiIG9ubHkuCgogICAgT3B0aW9uYWwgcmVwbGljYSBkZWZpbml0aW9uIHZhbHVlcyBhcmU6CgogICAgICAgICogW0ludGVnZXJdIEJBQ0tVUF9QUklPUklUWSAgICAgICAgICAtIEJhY2t1cCBwcmlvcml0eQogICAgICAgICogW0ludGVnZXJdIFNFU1NJT05fVElNRU9VVCAgICAgICAgICAtIFNlc3Npb24gdGltZW91dAogICAgICAgICogW1N0cmluZ10gIFBfQUxMT1dfQ09OTkVDVElPTlMgICAgICAtIEFsbG93ZWQgY29ubmVjdGlvbiB0eXBlcyBmb3IgIlByaW1hcnkiIHJlcGxpY2EgbW9kZS4gQ2FuIGJlICJSRUFEX1dSSVRFIiBvciAiQUxMIiBvbmx5LgogICAgICAgICogW0FycmF5XSAgIFBfUkVBRF9PTkxZX1JPVVRJTkdfTElTVCAtIExpc3Qgb2YgcmVwbGljYXMgcHJvdmlyaW5nIHJlYWRvbmx5IGFjY2VzcyB3aGVuIHRoaXMgb25lIGlzIHByaW1hcnkuCiAgICAgICAgKiBbU3RyaW5nXSAgU19BTExPV19DT05ORUNUSU9OUyAgICAgIC0gQWxsb3dlZCBjb25uZWN0aW9uIHR5cGVzIGZvciAiU2Vjb25kYXJ5IiByZXBsaWNhIG1vZGUuIENhbiBiZSBvbmUgb2YgIk5PIiwgIlJFQURfT05MWSIsICJBTEwiLgogICAgICAgICogW1N0cmluZ10gIFNfUkVBRF9PTkxZX1JPVVRJTkdfVVJMICAtIFJlcGxpY2EgcmVhZC1vbmx5IHJlcXVlc3RzIGxpc3RlbmVyIFVSTC4gTm9ybWFsbHkgZGVmYXVsdCBzZXJ2ZXIgbGlzdGVuZXIgYXQgcG9ydCAxNDMzIGlzIHVzZWQuCgogICAgLlBBUkFNRVRFUiBQcmVmZXJlbmNlcwogICAgSGFzaCB0YWJsZSBvZiBnZW5lcmFsIGF2YWlsYWJpbGl0eSBncm91cCBwcmVmZXJlbmNlcy4gQWxsIHRoZSBrZXlzIGFyZSBvcHRpb25hbC4gU3VwcG9ydGVkIGVudHJ5IGtleXMgYXJlOgoKICAgICAgICAqIFtTdHJpbmddICBBVVRPTUFURURfQkFDS1VQX1BSRUZFUkVOQ0UgLSBBdXRvbWF0ZWQgYmFja3VwIHByZWZlcmVuY2UuIENhbiBiZSAiUFJJTUFSWSIsICJTRUNPTkRBUllfT05MWSIsICJTRUNPTkRBUlkiIG9yICJOT05FIi4KICAgICAgICAqIFtTdHJpbmddICBGQUlMVVJFX0NPTkRJVElPTl9MRVZFTCAgICAgLSBGYWlsdXJlIGNvbmRpdGlvbiBsZXZlbC4gQ2FuIGJlICIxIiwgIjIiLCAiMyIsICI0IiBvciAiNSIuCiAgICAgICAgKiBbSW50ZWdlcl0gSEVBTFRIX0NIRUNLX1RJTUVPVVQgICAgICAgIC0gUmVwbGljYSBoZWFsdGggY2hlY2sgdGltZW91dC4KCiAgICAuUEFSQU1FVEVSIExpc3RlbmVyRGVmCiAgICBIYXNoIHRhYmxlIGNvbnRhaW5pbmcgYXZhaWxhYmlsaXR5IGdyb3VwIGxpc3RlbmVyIGNvbmZpZ3VyYXRpb24uCgogICAgTWFuZGF0b3J5IGxpc3RlbmVyIGNvbmZpZ3VyYXRpb24gdmFsdWVzIGFyZToKCiAgICAgICAgW1N0cmluZ10gTkFNRSAtIExpc3RlbmVyIG5hbWUuCgogICAgT3B0aW9uYWwgbGlzdGVuZXIgY29uZmlndXJhdGlvbiB2YWx1ZXMgYXJlOgogICAgCiAgICAgICAgW1N0cmluZ10gUE9SVCAtIExpc3RlbmVyIHBvcnQgbnVtYmVyLiBJbnRlZ2VyIHZhbHVlIG1heSBiZSBzdWZmaXhlZCBieSBhICIrIiBzeW1vbCAoc3VjaCBhcyAiNTAyMisiKSB3aGljaCBhbGxvd3MgdGhlIHJvdXRpbmUgdG8KICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0IG5leHQgZnJlZSBwb3J0IHdpdGggbnVtYmVyIGdyZWF0ZXIgb3IgZXF1YWwgdG8gdGhlIHNwZWNpZmllZCB2YWx1ZS4KICAgICAgICBbU3RyaW5nXSBESENQIC0gREhDUCBsaXN0ZW5lciBhZGRyZXNzIGNvbmZpZ3VyYXRpb24gZmxhZy4gV2hlbiBhbnkgdmFsdWUgc3BlY2lmaWVkLCBESENQIGlzIHVzZWQgdG8gY29uZmlndXJlIGxpc3RlbmVyCiAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzIGlzIGFsc28gdGhlIGRlZmF1bHQgYmVoYXZpb3IpLiBBbHNvLCBhIHNwZWNpZmljIGludGVyZmFjZSBmb3IgREhDUCBtYXkgYmUgc3BlY2lmaWVkIGFzIElQX0FERFJFU1MvTUFTSwogICAgICAgICAgICAgICAgICAgICAgICAobGlrZSAiMTkyLjE2OC4xLjAvMjU1LjI1NS4yNTUuMCIpIGFzIGEgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci4KICAgICAgICBbQXJyYXldIFNUQVRJQyAtIFN0YXRpYyBJUCBhZGRyZXNzZXMgdG8gbGlzdGVuLiBJUCBhZGRyZXNzZXMgbWF5IGJlIElQdjQgYWRkcmVzc2VzIGluIHRoZSAiSVBfQUREUkVTUy9NQVNLIiBmb3JtIG9yIElQdjYKICAgICAgICAgICAgICAgICAgICAgICAgYWRkcmVzc2VzIGluIHN0YW5kYXJkIElQdjYgbm90YXRpb24uCgogICAgU2VlIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9mZjg3ODM5OS5hc3B4IHBhZ2UgZm9yIG1vcmUgZGV0YWlscyByZWdhcmRpbmcgYWxsIHRoZSBzdXBwb3J0ZWQgb3B0aW9ucy4KICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kV29ya0RpciwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtBcnJheV0kRGF0YWJhc2VOYW1lcywKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbQXJyYXldJFJlcGxpY2FEZWZzLAogICAgICAgIFtwYXJhbWV0ZXJdCiAgICAgICAgW0hhc2h0YWJsZV0kUHJlZmVyZW5jZXMsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW0hhc2h0YWJsZV0kTGlzdGVuZXJEZWYKICAgICkKCiAgICBpZiAoLW5vdCAoVGVzdC1QYXRoICRXb3JrRGlyKSkgewogICAgICAgIFt2b2lkXShOZXctSXRlbSAtVHlwZSBEaXJlY3RvcnkgJFdvcmtEaXIpCiAgICB9CiAgICAkV29ya0RpciA9IChHZXQtSXRlbSAkV29ya0RpcikuRnVsbE5hbWUKICAgIGlmICgoR2V0LUNoaWxkSXRlbSAtUGF0aCAkV29ya0RpcikuTGVuZ3RoIC1ndCAwKSB7CiAgICAgICAgdGhyb3cgIldvcmtpbmcgZGlyZWN0b3J5ICRXb3JrRGlyIGlzIG5vdCBlbXB0eSIKICAgIH0KCiAgICAkUXVvdGVkREJOYW1lcyA9ICgkRGF0YWJhc2VOYW1lcyB8IEZvckVhY2gtT2JqZWN0IHsgQ29udmVydFRvLVNRTE5hbWUgJF8gfSkgLWpvaW4gIiwgIgoKICAgIGlmICgkUHJlZmVyZW5jZXMgLWVxICRudWxsKSB7CiAgICAgICAgJFByZWZlcmVuY2VzID0gQCgpCiAgICB9CiAgICAkUHJlZnMgPSBAKCkKICAgIGZvcmVhY2goJFByZWYgaW4gJFByZWZlcmVuY2VzKSB7CiAgICAgICAgaWYgKCRQcmVmLktleSAtZXEgJG51bGwpIHsKICAgICAgICAgICAgQ29udGludWUKICAgICAgICB9CiAgICAgICAgaWYgKCRQcmVmLktleSAtZXEgIkFVVE9NQVRFRF9CQUNLVVBfUFJFRkVSRU5DRSIpIHsKICAgICAgICAgICAgJFByZWZzID0gJFByZWZzICsgKFZhbGlkYXRlLU9wdGlvbiAkUHJlZi5LZXksICRQcmVmLlZhbHVlLCBAKCJQUklNQVJZIiwgIlNFQ09OREFSWV9PTkxZIiwgIlNFQ09OREFSWSIsICJOT05FIikgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAkUHJlZi5LZXkpCiAgICAgICAgfSBlbHNlaWYgKCRQcmVmLktleSAtZXEgIkZBSUxVUkVfQ09ORElUSU9OX0xFVkVMIikgewogICAgICAgICAgICAkUHJlZnMgPSAkUHJlZnMgKyAoVmFsaWRhdGUtT3B0aW9uICRQcmVmLktleSwgJFByZWYuVmFsdWUsIEAoIjEiLCAiMiIsICIzIiwgIjQiLCAiNSIpIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgJFByZWYuS2V5KQogICAgICAgIH0gZWxzZWlmICgkUHJlZi5LZXkgLWVxICJIRUFMVEhfQ0hFQ0tfVElNRU9VVCIpIHsKICAgICAgICAgICAgJFByZWZzID0gJFByZWZzICsgKFZhbGlkYXRlLUludE9wdGlvbiAkUHJlZi5LZXksICRQcmVmLlZhbHVlIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgJFByZWYuS2V5KQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRocm93ICJVbmV4cGVjdGVkIHBlZmVyZW5jZXMgb3B0aW9uOiAnJCgkUHJlZi5LZXkpJyIKICAgICAgICB9CiAgICB9CgogICAgJFJlcGxpY2FEZWZpbml0aW9uc0FycmF5ID0gQCgpCiAgICBmb3IgKCRpID0gMDsgJGkgLWx0ICRSZXBsaWNhRGVmcy5MZW5ndGg7ICRpKyspIHsKICAgICAgICAkUkRlZiA9ICRSZXBsaWNhRGVmc1skaV0KICAgICAgICBpZiAoJFJEZWYuR2V0VHlwZSgpLk5hbWUgLW5lICJIYXNodGFibGUiKSB7CiAgICAgICAgICAgIHRocm93ICJBbGwgZWxlbWVudHMgb2YgUmVwbGljYURlZnMgYXJyYXkgc2hvdWxkIGJlIEhhc2h0YWJsZXMiCiAgICAgICAgfQoKICAgICAgICAkUmVwbGljYU9wdHMgPSBAKCkKCiAgICAgICAgIyBNYW5kYXRvcnkgb3B0aW9ucwogICAgICAgICRSZXBsaWNhTmFtZSA9IFZhbGlkYXRlLURlZmluZWRPcHRpb24gIlNFUlZFUl9JTlNUQU5DRSIgJFJEZWZbIlNFUlZFUl9JTlNUQU5DRSJdCiAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLURlZmluZWRPcHRpb24gIkVORFBPSU5UX1VSTCIgJFJEZWZbIkVORFBPSU5UX1VSTCJdIHwgQ29udmVydFRvLVNRTFN0cmluZyB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJFTkRQT0lOVF9VUkwiKQogICAgICAgICRSZXBsaWNhT3B0cyA9ICRSZXBsaWNhT3B0cyArIChWYWxpZGF0ZS1PcHRpb24gIkFWQUlMQUJJTElUWV9NT0RFIiAkUkRlZlsiQVZBSUxBQklMSVRZX01PREUiXSBAKCJTWU5DSFJPTk9VU19DT01NSVQiLCAiQVNZTkNIUk9OT1VTX0NPTU1JVCIpIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIkFWQUlMQUJJTElUWV9NT0RFIikKICAgICAgICAkUmVwbGljYU9wdHMgPSAkUmVwbGljYU9wdHMgKyAoVmFsaWRhdGUtT3B0aW9uICJGQUlMT1ZFUl9NT0RFIiAkUkRlZlsiRkFJTE9WRVJfTU9ERSJdIEAoIkFVVE9NQVRJQyIsICJNQU5VQUwiKSB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJGQUlMT1ZFUl9NT0RFIikKCiAgICAgICAgIyBPcHRpb25hbCBvcHRpb25zCiAgICAgICAgaWYgKCRSRGVmWyJCQUNLVVBfUFJJT1JJVFkiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLUludE9wdGlvbiAiQkFDS1VQX1BSSU9SSVRZIiAkUkRlZlsiQkFDS1VQX1BSSU9SSVRZIl0gfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQkFDS1VQX1BSSU9SSVRZIikKICAgICAgICB9CiAgICAgICAgaWYgKCRSRGVmWyJTRVNTSU9OX1RJTUVPVVQiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLUludE9wdGlvbiAiU0VTU0lPTl9USU1FT1VUIiAkUkRlZlsiU0VTU0lPTl9USU1FT1VUIl0gfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiU0VTU0lPTl9USU1FT1VUIikKICAgICAgICB9CgogICAgICAgICRTZWNvbmRhcnlSb2xlID0gQCgpCiAgICAgICAgaWYgKCRSRGVmWyJTX0FMTE9XX0NPTk5FQ1RJT05TIl0gLW5lICRudWxsKSB7CiAgICAgICAgICAgICRTZWNvbmRhcnlSb2xlID0gJFNlY29uZGFyeVJvbGUgKyAoVmFsaWRhdGUtT3B0aW9uICJTX0FMTE9XX0NPTk5FQ1RJT05TIiAkUkRlZlsiU19BTExPV19DT05ORUNUSU9OUyJdIEAoIk5PIiwgIlJFQURfT05MWSIsICJBTEwiKSB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJBTExPV19DT05ORUNUSU9OUyIpCiAgICAgICAgfQogICAgICAgIGlmICgkUkRlZlsiU19SRUFEX09OTFlfUk9VVElOR19VUkwiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFNlY29uZGFyeVJvbGUgPSAkU2Vjb25kYXJ5Um9sZSArICgkUkRlZlsiU19SRUFEX09OTFlfUk9VVElOR19VUkwiXSB8IENvbnZlcnRUby1TUUxTdHJpbmcgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFNlY29uZGFyeVJvbGUuTGVuZ3RoIC1ndCAwKSB7CiAgICAgICAgICAgICRSZXBsaWNhT3B0cyA9ICRSZXBsaWNhT3B0cyArICgiKCAkKCRTZWNvbmRhcnlSb2xlIC1qb2luICcsICcpICkiIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIlNFQ09OREFSWV9ST0xFIikKICAgICAgICB9CgogICAgICAgICRQcmltYXJ5Um9sZSA9IEAoKQogICAgICAgIGlmICgkUkRlZlsiUF9BTExPV19DT05ORUNUSU9OUyJdIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkUHJpbWFyeVJvbGUgPSAkUHJpbWFyeVJvbGUgKyAoVmFsaWRhdGUtT3B0aW9uICJQX0FMTE9XX0NPTk5FQ1RJT05TIiAkUkRlZlsiUF9BTExPV19DT05ORUNUSU9OUyJdIEAoIlJFQURfV1JJVEUiLCAiQUxMIikgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFJEZWZbIlBfUkVBRF9PTkxZX1JPVVRJTkdfTElTVCJdIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkUHJpbWFyeVJvbGUgPSAkUHJpbWFyeVJvbGUgKyAoKCgkUkRlZlsiUF9SRUFEX09OTFlfUk9VVElOR19MSVNUIl0gfCBGb3JFYWNoLU9iamVjdCB7IENvbnZlcnRUby1TUUxTdHJpbmcgJF8gfSkgLWpvaW4gJywgJykgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFByaW1hcnlSb2xlLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICAgICAkUmVwbGljYU9wdHMgPSAkUmVwbGljYU9wdHMgKyAoIiggJCgkUHJpbWFyeVJvbGUgLWpvaW4gJywgJykgKSIgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiUFJJTUFSWV9ST0xFIikKICAgICAgICB9CgogICAgICAgICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSA9ICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSArCiAgICAgICAgICAgICMgIFRDUDovL2JyYXZvLm11cmFuby5sb2NhbDo1MDIyCiAgICAgICAgICAgICJOJChDb252ZXJ0VG8tU1FMU3RyaW5nICRSZXBsaWNhTmFtZSkgV0lUSCAoJCgkUmVwbGljYU9wdHMgLWpvaW4gJywgJykpIgogICAgfQogICAgJFJlcGxpY2FEZWZpbml0aW9ucyA9ICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSAtam9pbiAiLGByYG4gICAgICAgICI7CgogICAgaWYgKCRMaXN0ZW5lckRlZlsiREhDUCJdIC1uZSAkbnVsbCkgewogICAgICAgIGlmICgkTGlzdGVuZXJEZWZbIkRIQ1AiXS5tYXRjaGVzKCJcZCtcLlxkK1wuXGQrXC5cZCsvXGQrXC5cZCtcLlxkK1wuXGQrIikpIHsKICAgICAgICAgICAgKCRJcEFkZHIsICRNYXNrKSA9ICRMaXN0ZW5lckRlZlsiREhDUCJdIC1zcGxpdCAiLyIKICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICJESENQIE9OICggJElwQWRkciwgJE1hc2sgKSIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAkTGlzdGVuZXJBZGRyID0gIkRIQ1AiCiAgICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgICBbYXJyYXldJElQQWRkcmVzc2VzID0gJExpc3RlbmVyRGVmWyJTVEFUSUMiXQogICAgICAgIGlmICgoJElQQWRkcmVzc2VzIC1lcSAkbnVsbCkgLW9yICgkSVBBZGRyZXNzZXMuQ291bnQgLWVxIDApKSB7CiAgICAgICAgICAgICRMaXN0ZW5lckFkZHIgPSAiREhDUCIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAkQ29udmVydGVkT3B0cyA9IEAoKQogICAgICAgICAgICBmb3JlYWNoICgkSXBPcHRpb24gaW4gJElQQWRkcmVzc2VzKSB7CiAgICAgICAgICAgICAgICAjIElQdjQKICAgICAgICAgICAgICAgIGlmICgkSXBPcHRpb24gLW1hdGNoICJcZCtcLlxkK1wuXGQrXC5cZCsvXGQrXC5cZCtcLlxkK1wuXGQrIikgewogICAgICAgICAgICAgICAgICAgICgkSXBBZGRyLCAkTWFzaykgPSAkSXBPcHRpb24gLXNwbGl0ICIvIgogICAgICAgICAgICAgICAgICAgICRDb252ZXJ0ZWRPcHRzID0gJENvbnZlcnRlZE9wdHMgKyAiKCAkKENvbnZlcnRUby1TUUxTdHJpbmcgJElwQWRkciksICQoQ29udmVydFRvLVNRTFN0cmluZyAkTWFzaykgKSIKICAgICAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgIyBJUHY2CiAgICAgICAgICAgICAgICBpZiAoJElwT3B0aW9uIC1tYXRjaCAiXigoKD89KD8+Lio/OjopKD8hLio6OikpKSg6Oik/KFswLTlBLUZdezEsNH06Oj8pezAsNX18KFswLTlBLUZdezEsNH06KXs2fSkoXDIoWzAtOUEtRl17MSw0fSg6Oj98JCkpezAsMn18KCgyNVswLTVdfCgyWzAtNF18MVxkfFsxLTldKT9cZCkoXC58JCkpezR9fFswLTlBLUZdezEsNH06WzAtOUEtRl17MSw0fSkoPzwhW146XTp8XC4pXHoiKSB7CiAgICAgICAgICAgICAgICAgICAgJENvbnZlcnRlZE9wdHMgPSAkQ29udmVydGVkT3B0cyArICIoICQoQ29udmVydFRvLVNRTFN0cmluZyAkSXBPcHRpb24pICkiCiAgICAgICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRocm93ICJNYWxmb3JtZWQgSVB2NC9JUHY2IGFkZHJlc3M6ICRJcE9wdGlvbiIKICAgICAgICAgICAgfQogICAgICAgICAgICAkTGlzdGVuZXJBZGRyID0gIklQICggJCgkQ29udmVydGVkT3B0cyAtam9pbiAnLCAnKSApIgogICAgICAgIH0KICAgIH0KICAgIGlmICgoJExpc3RlbmVyRGVmWyJOQU1FIl0gLWVxICRudWxsKSAtb3IgKCRMaXN0ZW5lckRlZlsiTkFNRSJdIC1tYXRjaCAiXlxzKiQiKSkgewogICAgICAgIHRocm93ICJMaXN0ZW5lciBuYW1lIGlzIHJlcXVpcmVkIgogICAgfQogICAgaWYgKC1ub3QgKCRMaXN0ZW5lckRlZlsiTkFNRSJdIC1tYXRjaCAiXltBLVphLXowLTlcLl9cLV0rJCIpKSB7CiAgICAgICAgdGhyb3cgIklsbGVnYWwgbGlzdGVuZXIgbmFtZS4gSXQgY2FuIGNvbnRhaW4gb25seSBhbHBoYW51bWVyaWMgY2hhcmFjdGVycywgZGFzaGVzICgtKSwgYW5kIGh5cGhlbnMgKF8pLCBpbiBhbnkgb3JkZXIuIgogICAgfQogICAgJFBvcnQgPSAkbnVsbAogICAgaWYgKCRMaXN0ZW5lckRlZlsiUE9SVCJdIC1uZSAkbnVsbCkgewogICAgICAgIGlmICgkTGlzdGVuZXJEZWZbIlBPUlQiXSAtbWF0Y2ggIlxkK1wrIikgewogICAgICAgICAgICAkU3RhcnRpbmdQb3J0ID0gJExpc3RlbmVyRGVmWyJQT1JUIl0gLXJlcGxhY2UgIlwrIiwgIiIKICAgICAgICAgICAgJFBvcnQgPSBHZXQtTmV4dEZyZWVQb3J0ICRTdGFydGluZ1BvcnQKICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICRMaXN0ZW5lckFkZHIgKyAiLCBQT1JUID0gJFBvcnQiCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKCRMaXN0ZW5lckRlZlsiUE9SVCJdIC1tYXRjaCAiXGQrIikgewogICAgICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICRMaXN0ZW5lckFkZHIgKyAiLCBQT1JUID0gJCgkTGlzdGVuZXJEZWZbIlBPUlQiXSkiCiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyAiSW52YWxpZCBwb3J0IHZhbHVlOiAkKCRMaXN0ZW5lckRlZlsiUE9SVCJdKSIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgICRMaXN0ZW5lciA9ICJMSVNURU5FUiAnJCgkTGlzdGVuZXJEZWZbIk5BTUUiXSknICggV0lUSCAkTGlzdGVuZXJBZGRyICkiCgogICAgJE5hbWUgfCBPdXQtRmlsZSAiJFdvcmtEaXJcYXZncm91cC5uYW1lIgogICAgCiAgICBmb3IgKCRpID0gMDsgJGkgLWx0ICREYXRhYmFzZU5hbWVzLkxlbmd0aDsgJGkrKykgewogICAgICAgICREYXRhQmFzZU5hbWUgPSAkRGF0YWJhc2VOYW1lc1skaV0KICAgICAgICAkRGF0YUJhc2VOYW1lIHwgT3V0LUZpbGUgIiRXb3JrRGlyXGRiJGkubmFtZSIKICAgICAgICBOZXctU1FMRGF0YWJhc2UgJERhdGFCYXNlTmFtZQogICAgICAgICRCYWNrdXBEYiA9ICJCQUNLVVAgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcZGIkaS5iYWsiKSBXSVRIIE5PRk9STUFULCBJTklULCBOQU1FID0gTidGdWxsIERhdGFiYXNlIEJhY2t1cCcsIFNLSVAsIE5PUkVXSU5ELCBOT1VOTE9BRCwgU1RBVFMgPSAxMAogICAgICAgICAgICAgICAgICAgICBHTyIKICAgICAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwRGIpCiAgICAgICAgJEJhY2t1cExvZyA9ICJCQUNLVVAgTE9HICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgVE8gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXGRiJHtpfS5sb2cuYmFrIikgV0lUSCBOT0ZPUk1BVCwgSU5JVCwgIE5BTUUgPSBOJ1RyYW5zYWN0aW9uIExvZyAgQmFja3VwJywgU0tJUCwgTk9SRVdJTkQsIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgICAgICBHTyIKICAgICAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwTG9nKQogICAgfQogICAgJFJlcGxpY2FEZWZpbml0aW9uc0FycmF5ID0gQCgpCiAgICBpZiAoJFByZWZzLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICRQcmVmc0xpbmUgPSAiV0lUSCAoICQoJFByZWZzIC1qb2luICcsICcpICkiCiAgICB9IGVsc2UgewogICAgICAgICRQcmVmc0xpbmUgPSAiIgogICAgfQogICAgJFNRTCA9ICJDUkVBVEUgQVZBSUxBQklMSVRZIEdST1VQICQoQ29udmVydFRvLVNRTE5hbWUgJE5hbWUpICRQcmVmc0xpbmUKICAgICAgICAgICAgICAgIEZPUiBEQVRBQkFTRSAkUXVvdGVkREJOYW1lcwogICAgICAgICAgICAgICAgUkVQTElDQSBPTmByYG4gICAgICAgICRSZXBsaWNhRGVmaW5pdGlvbnMKICAgICAgICAgICAgICAgICRMaXN0ZW5lcjsKICAgICIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRTUUwpCiAgICByZXR1cm4gJFBvcnQKfQoKZnVuY3Rpb24gTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXBSZXBsaWNhIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgQWx3YXlzT24gYXZhaWxhYmlsaXR5IGdyb3VwIHNlY29uZGFyeSByZXBsaWNhCgogICAgLkRFU0NSSVBUSU9OCiAgICBDcmVhdGVzIEFsd2F5c09uIGF2YWlsYWJpbGl0eSBncm91cCBzZWNvbmRhcnkgcmVwbGljYSBiYXNlZCBvbiBpbmZvcm1hdGlvbiBwcm92aWRlZCB0byBhbmQgYnkgTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXAuCgogICAgLlBBUkFNRVRFUiBXb3JrRGlyCiAgICBXb3JraW5nIGRpcmVjdG9yeSB3aGljaCB3YXMgdHJhbnNmZXJyZWQgZnJvbSB0aGUgcHJpbWFyeSByZXBsaWNhLgogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFdvcmtEaXIKICAgICkKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIldvcmsgZGlyICckV29ya0Rpcicgbm90IGZvdW5kIgogICAgfQogICAgJFdvcmtEaXJPYmogPSBHZXQtSXRlbSAtUGF0aCAkV29ya0RpcgogICAgJFdvcmtEaXIgPSAkV29ya0Rpck9iai5GdWxsTmFtZQogICAgJEdyb3VwTmFtZSA9IEdldC1Db250ZW50ICRXb3JrRGlyT2JqLkdldEZpbGVzKCJhdmdyb3VwLm5hbWUiKS5GdWxsTmFtZQoKICAgICRKb2luR3JvdXAgPSAiQUxURVIgQVZBSUxBQklMSVRZIEdST1VQICQoQ29udmVydFRvLVNRTE5hbWUgJEdyb3VwTmFtZSkgSk9JTgogICAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkSm9pbkdyb3VwKQoKICAgIGZvciAoJGkgPSAwOyA7ICRpKyspIHsKICAgICAgICAkRmlsZSA9ICRXb3JrRGlyT2JqLkdldEZpbGVzKCJkYiRpLm5hbWUiKQogICAgICAgIGlmICgtbm90ICRGaWxlKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICAkRGF0YUJhc2VOYW1lID0gR2V0LUNvbnRlbnQgJFdvcmtEaXJPYmouR2V0RmlsZXMoImRiJGkubmFtZSIpLkZ1bGxOYW1lCiAgICAgICAgJFJlc3RvcmVEYiA9ICJSRVNUT1JFIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgRlJPTSBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcZGIkaS5iYWsiKSBXSVRIIEZJTEUgPSAxLCBOT1JFQ09WRVJZLCBOT1VOTE9BRCwgUkVQTEFDRSwgU1RBVFMgPSA1CiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVEYikKICAgICAgICAkUmVzdG9yZUxvZyA9ICJSRVNUT1JFIExPRyAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIEZST00gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXGRiJGkubG9nLmJhayIpIFdJVEggRklMRSA9IDEsIE5PUkVDT1ZFUlksIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVMb2cpCiAgICAgICAgJEFsdGVyREIgPSAiQUxURVIgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBTRVQgSEFEUiBBVkFJTEFCSUxJVFkgR1JPVVAgPSAkKENvbnZlcnRUby1TUUxOYW1lICRHcm91cE5hbWUpCiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJEFsdGVyREIpCiAgICB9Cn0KCmZ1bmN0aW9uIE5ldy1SZXBsaWNhT3B0aW9uIHsKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSwgVmFsdWVGcm9tUGlwZWxpbmUgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kVmFsdWUKICAgICkKICAgIHJldHVybiAiJE5hbWUgPSAkVmFsdWUiCn0KCmZ1bmN0aW9uIFZhbGlkYXRlLU9wdGlvbiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDaGVja3MgdGhhdCB0aGUgdmFsdWUgaXMgb25lIG9mIGFsbG93ZWQgdmFsdWVzCgogICAgLkRFU0NSSVBUSU9OCiAgICBDaGVja3MgdGhhdCB0aGUgdmFsdWUgaXMgb25lIG9mIGFsbG93ZWQgdmFsdWVzIG9yIHRocm93cyBleGNlcHRpb24gb3RoZXJ3aXNlLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCgogICAgLlBBUkFNRVRFUiBBbGxvd2VkCiAgICBMaXN0IG9mIGFsbG93ZWQgb3B0aW9uIHZhbHVzLgogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJE5hbWUsCiAgICAgICAgW1N0cmluZ10kVmFsdWUsCiAgICAgICAgW0FycmF5XSRBbGxvd2VkCiAgICApCiAgICBpZiAoKCRWYWx1ZSAtZXEgJG51bGwpIC1vciAoJFZhbHVlIC1lcSAiIikpIHsKICAgICAgICB0aHJvdyAiTm8gdmFsdWUgd2FzIHByb3ZpZGVkIGZvciAkTmFtZSIKICAgIH0KICAgIGZvcmVhY2ggKCRWIGluICRBbGxvd2VkKSB7CiAgICAgICAgaWYgKCRWIC1lcSAkVmFsdWUpIHsKICAgICAgICAgICAgcmV0dXJuICRWYWx1ZQogICAgICAgIH0KICAgIH0KICAgIHRocm93ICJQcm92aWRlZCB2YWx1ZSAnJFZhbHVlJyBmb3IgJE5hbWUgaXMgbm90IG9uZSBvZiAkKCRBbGxvd2VkIC1qb2luICcsICcpIgp9CgpmdW5jdGlvbiBWYWxpZGF0ZS1JbnRPcHRpb24gewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ2hlY2tzIHRoYXQgdGhlIHZhbHVlIGlzIGludGVnZXIKCiAgICAuREVTQ1JJUFRJT04KICAgIENoZWNrcyB0aGF0IHRoZSB2YWx1ZSBpcyBpbnRlZ2VyLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kTmFtZSwKICAgICAgICBbcGFyYW1ldGVyXQogICAgICAgIFtTdHJpbmddJFZhbHVlCiAgICApCiAgICBpZiAoKCRWYWx1ZSAtZXEgJG51bGwpIC1vciAoJFZhbHVlIC1lcSAiIikpIHsKICAgICAgICB0aHJvdyAiTm8gdmFsdWUgd2FzIHByb3ZpZGVkIGZvciAkTmFtZSIKICAgIH0KICAgIGlmICgtbm90ICgiJFZhbHVlIiAtbWF0Y2ggIl5bKy1dP1xkKyQiKSkgewogICAgICAgIHRocm93ICJQcm92aWRlZCB2YWx1ZSAnJFZhbHVlJyBmb3IgJE5hbWUgaXMgbm90IGEgbnVtYmVyIgogICAgfQogICAgcmV0dXJuICRWYWx1ZQp9CgpmdW5jdGlvbiBWYWxpZGF0ZS1EZWZpbmVkT3B0aW9uIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENoZWNrcyB0aGF0IHRoZSB2YWx1ZSBpcyBub3QgbnVsbAoKICAgIC5ERVNDUklQVElPTgogICAgQ2hlY2tzIHRoYXQgdGhlIHZhbHVlIGlzIG5vdCBudWxsLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kTmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICRmYWxzZSldCiAgICAgICAgW1N0cmluZ10kVmFsdWUKICAgICkKICAgIGlmICgoJFZhbHVlIC1lcSAkbnVsbCkgLW9yICgkVmFsdWUgLWVxICIiKSkgewogICAgICAgIHRocm93ICJObyB2YWx1ZSB3YXMgcHJvdmlkZWQgZm9yICROYW1lIgogICAgfQogICAgcmV0dXJuICRWYWx1ZQp9CgoKCg==", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlclBvd2VyU2hlbGxNb2R1bGUgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJwogICAgKQogICAgYmVnaW4gewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbgogICAgfQogICAgZW5kIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24gLUVuZAogICAgfQogICAgcHJvY2VzcyB7CiAgICAgICAgdHJhcCB7CiAgICAgICAgICAgICYkVHJhcEhhbmRsZXIKICAgICAgICB9CgogICAgICAgIGlmICgoR2V0LU1vZHVsZSBTUUxQUyAtTGlzdEF2YWlsYWJsZSkgLW5lICRudWxsKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiTW9kdWxlIFNRTFNQIGFscmVhZHkgaW5zdGFsbGVkLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcVG9vbHMnKQogICAgICAgIH0KICAgICAgICAKICAgICAgICAkRmlsZUxpc3QgPSBAKAogICAgICAgICAgICAnU1FMU3lzQ2xyVHlwZXMubXNpJywKICAgICAgICAgICAgJ1NoYXJlZE1hbmFnZW1lbnRPYmplY3RzLm1zaScsCiAgICAgICAgICAgICdQb3dlclNoZWxsVG9vbHMubXNpJwogICAgICAgICkKCiAgICAgICAgZm9yZWFjaCAoJE1zaUZpbGUgaW4gJEZpbGVMaXN0KSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVHJ5aW5nIHRvIGluc3RhbGwgJyRNc2lGaWxlJyAuLi4iCiAgICAgICAgICAgICRNc2lQYXRoID0gSm9pbi1QYXRoICRTZXR1cFJvb3QgJE1zaUZpbGUKICAgICAgICAgICAgaWYgKFtJTy5GaWxlXTo6RXhpc3RzKCRNc2lQYXRoKSkgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJTdGFydGluZyBtc2lleGUgLi4uIgogICAgICAgICAgICAgICAgJFJlc3VsdCA9IEV4ZWMgLUZpbGVQYXRoICJtc2lleGVjLmV4ZSIgLUFyZ3VtZW50TGlzdCBAKCcvaScsICJgIiRNc2lQYXRoYCIiLCAnL3F1aWV0JykgLVBhc3NUaHJ1CiAgICAgICAgICAgICAgICBpZiAoJFJlc3VsdC5FeGl0Q29kZSAtbmUgMCkgewogICAgICAgICAgICAgICAgICAgIHRocm93ICgiSW5zdGFsbGF0aW9uIG9mIE1TSSBwYWNrYWdlICckTXNpUGF0aCcgZmFpbGVkIHdpdGggZXJyb3IgY29kZSAnJCgkUmVzdWx0LkV4aXRDb2RlKSciKQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJGaWxlICckTXNpUGF0aCcgbm90IGZvdW5kLiIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQoKCgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgUGF0aCB0byBmb2xkZXIgd2hlcmUgbXNpIGZpbGVzIGZvciBhZGRpdGlvbmFsIFNRTCBmZWF0dXJlcyBhcmUgbG9jYXRlZAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJywKCiAgICAgICAgIyBQYXRoIHRvIGZvbGRlciB3aGVyZSBtc2kgZmlsZXMgZm9yIGFkZGl0aW9uYWwgU1FMUFMgbW9kdWxlIGFyZSBsb2NhdGVkCiAgICAgICAgW1N0cmluZ10gJFNxbHBzU2V0dXBSb290ID0gJycsCgogICAgICAgIFtTdHJpbmddICRNdXJhbm9GaWxlU2hhcmUgPSAnJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIERvbWFpbiBuYW1lCiAgICAgICAgW1N0cmluZ10gJFNRTFNlcnZpY2VVc2VyRG9tYWluID0gJ2ZjLWFjbWUubG9jYWwnLAoKICAgICAgICAjIChSRVFVSVJFRCkgVXNlciBuYW1lIGZvciB0aGUgYWNjb3VudCB3aGljaCB3aWxsIGJlIHVzZWQgYnkgU1FMIHNlcnZpY2UKICAgICAgICBbU3RyaW5nXSAkU1FMU2VydmljZVVzZXJOYW1lID0gJ0FkbWluaXN0cmF0b3InLAoKICAgICAgICAjIChSRVFVSVJFRCkgUGFzc3dvcmQgZm9yIHRoYXQgdXNlcgogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlclBhc3N3b3JkID0gJ1BAc3N3MHJkJywKCiAgICAgICAgW1N3aXRjaF0gJFVwZGF0ZUVuYWJsZWQKICAgICkKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcMjAxMicpCiAgICAgICAgfQoKICAgICAgICAkRXh0cmFPcHRpb25zID0gQHt9CgogICAgICAgIGlmICgkVXBkYXRlRW5hYmxlZCkgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJHRydWV9CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJGZhbHNlfQogICAgICAgIH0KCiAgICAgICAgTmV3LVNRTFNlcnZlckZvckFPQUcgYAogICAgICAgICAgICAtU2V0dXBSb290ICRTZXR1cFJvb3QgYAogICAgICAgICAgICAtU1FMU3ZjVXNyRG9tYWluICRTUUxTZXJ2aWNlVXNlckRvbWFpbiBgCiAgICAgICAgICAgIC1TUUxTdmNVc3JOYW1lICRTUUxTZXJ2aWNlVXNlck5hbWUgYAogICAgICAgICAgICAtU1FMU3ZjVXNyUGFzc3dvcmQgJFNRTFNlcnZpY2VVc2VyUGFzc3dvcmQgYAogICAgICAgICAgICAtRXh0cmFPcHRpb25zICRFeHRyYU9wdGlvbnMKICAgIH0KfQoKCgpmdW5jdGlvbiBJbml0aWFsaXplLUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXAgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnRQYXNzd29yZCwKICAgICAgICBbU3RyaW5nXSAkU3FsU2VydmljZUFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICRQcmltYXJ5Tm9kZSwKICAgICAgICBbU3RyaW5nXSAkU2hhcmVOYW1lID0gJ1NoYXJlZFdvcmtEaXInCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgJFNoYXJlTmV0d29ya1BhdGggPSAnXFwnICsgJFByaW1hcnlOb2RlICsgJ1wnICsgJFNoYXJlTmFtZQoKICAgICAgICAkRG9tYWluQWRtaW5BY2NvdW50Q3JlZHMgPSBOZXctQ3JlZGVudGlhbCBgCiAgICAgICAgICAgIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJERvbWFpbkFkbWluQWNjb3VudE5hbWUiIGAKICAgICAgICAgICAgLVBhc3N3b3JkICIkRG9tYWluQWRtaW5BY2NvdW50UGFzc3dvcmQiCgogICAgICAgICRGdW5jdGlvbnNGaWxlID0gRXhwb3J0LUZ1bmN0aW9uICdHZXQtTmV4dEZyZWVQb3J0JywgJ0luaXRpYWxpemUtQWx3YXlzT24nCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICBgJF8KICAgIGV4aXQgMQp9CgpJbXBvcnQtTW9kdWxlIENvcmVGdW5jdGlvbnMKCldyaXRlLUxvZyAiSW1wb3J0aW5nIGZ1bmN0aW9ucyBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ0luaXRpYWxpemUtQWx3YXlzT24nIC4uLiIKYCRYbWxGaWxlID0gW0lPLlBhdGhdOjpDb21iaW5lKCIkU2hhcmVOZXR3b3JrUGF0aCIsICJgJChgJEVudjpDb21wdXRlck5hbWUpLnhtbCIpCldyaXRlLUxvZyAiT3V0cHV0IFhNTCBmaWxlIGlzICdgJFhtbEZpbGUnIgpJbml0aWFsaXplLUFsd2F5c09uIHwgRXhwb3J0LUNsaVhtbCAtUGF0aCBgJFhtbEZpbGUKIkAgLUNyZWRlbnRpYWwgJERvbWFpbkFkbWluQWNjb3VudENyZWRzIC1Ob0Jhc2U2NAogICAgfQp9CgoKZnVuY3Rpb24gTmV3LVNoYXJlZEZvbGRlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKQogICAgICAgIFtTdHJpbmddICRTaGFyZVBhdGggPSBbSU8uUGF0aF06OkNvbWJpbmUoJEVudjpTeXN0ZW1Ecml2ZSArICdcJywgJ1NoYXJlZFdvcmtEaXInKSwKCiAgICAgICAgIyAoT1BUSU9OQUwpCiAgICAgICAgW1N0cmluZ10gJFNoYXJlTmFtZSA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlID0gJyAnCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBzY3JpcHQgcnVucyBvbiBwcmltYXJ5IG5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZyBzY3JpcHQuIgogICAgICAgICAgICByZXR1cm4KICAgICAgICB9CgogICAgICAgIGlmICgkU2hhcmVOYW1lIC1lcSAnJykgewogICAgICAgICAgICAkU2hhcmVOYW1lID0gW0lPLlBhdGhdOjpHZXRGaWxlTmFtZVdpdGhvdXRFeHRlbnNpb24oJFNoYXJlUGF0aCkKICAgICAgICB9CgogICAgICAgIFdyaXRlLUxvZ0RlYnVnICJTaGFyZVBhdGggPSAnJFNoYXJlUGF0aCciCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIlNoYXJlTmFtZSA9ICckU2hhcmVOYW1lJyIKCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgc2hhcmUgJyRTaGFyZU5hbWUnIgogICAgICAgICAgICAkbnVsbCA9IEdldC1TbWJTaGFyZSAtTmFtZSAkU2hhcmVOYW1lIC1FcnJvckFjdGlvbiAnU3RvcCcKICAgICAgICAgICAgJG51bGwgPSBSZW1vdmUtU21iU2hhcmUgLU5hbWUgJFNoYXJlTmFtZSAtRm9yY2UKICAgICAgICAgICAgd3JpdGUtTG9nICJTaGFyZSAnJFNoYXJlTmFtZScgcmVtb3ZlZC4iCiAgICAgICAgfQogICAgICAgIGNhdGNoIHsKICAgICAgICAgICAgV3JpdGUtTG9nV2FybmluZyAiU2hhcmUgJyRTaGFyZU5hbWUnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgZm9sZGVyICckU2hhcmVQYXRoIgogICAgICAgICAgICAkbnVsbCA9IEdldC1JdGVtIC1QYXRoICRTaGFyZVBhdGggLUVycm9yQWN0aW9uICdTdG9wJwogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICRTaGFyZVBhdGggLVJlY3Vyc2UgLUZvcmNlCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRm9sZGVyICckU2hhcmVQYXRoJyByZW1vdmVkLiIKICAgICAgICB9CiAgICAgICAgY2F0Y2ggewogICAgICAgICAgICBXcml0ZS1Mb2dXYXJuaW5nICJGb2xkZXIgJyRTaGFyZVBhdGgnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgJG51bGwgPSBOZXctSXRlbSAtUGF0aCAkU2hhcmVQYXRoIC1JdGVtVHlwZSBDb250YWluZXIgLUZvcmNlCiAgICAgICAgICAgICAgICAKICAgICAgICAkbnVsbCA9IE5ldy1TbWJTaGFyZSAtUGF0aCAkU2hhcmVQYXRoIGAKICAgICAgICAgICAgLU5hbWUgJFNoYXJlTmFtZSBgCiAgICAgICAgICAgIC1GdWxsQWNjZXNzICJFdmVyeW9uZSIgYAogICAgICAgICAgICAtRGVzY3JpcHRpb24gIlNoYXJlZCBmb2xkZXIgZm9yIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cCBzZXR1cC4iCgogICAgICAgIHJldHVybiAnXFwnICsgJEVudjpDb21wdXRlck5hbWUgKyAnXCcgKyAkU2hhcmVOYW1lCiAgICB9Cn0KCgoKZnVuY3Rpb24gTmV3LURhdGFiYXNlRm9yQU9BRyB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJERhdGFiYXNlTmFtZSwKICAgICAgICBbU3RyaW5nXSAkRG9tYWluTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlck5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJQYXNzd29yZAogICAgKQoKICAgICRDcmVkcyA9IE5ldy1DcmVkZW50aWFsIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJFVzZXJOYW1lIiAtUGFzc3dvcmQgIiRVc2VyUGFzc3dvcmQiCgogICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gJ0ludm9rZS1TUUxUZXh0JywgJ0NvbnZlcnRUby1TUUxOYW1lJywgJ0NvbnZlcnRUby1TUUxTdHJpbmcnLCAnTmV3LVNRTERhdGFiYXNlJwoKICAgIFN0YXJ0LVBvd2VyU2hlbGxQcm9jZXNzIEAiCnRyYXAgewogICAgYCRfCiAgICBleGl0IDEKfQoKSW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zCgpXcml0ZS1Mb2cgIkltcG9ydGluZyBmdW5jdGlvbnMgZnJvbSBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1TUUxEYXRhYmFzZScgLi4uIgpOZXctU1FMRGF0YWJhc2UgJERhdGFiYXNlTmFtZQoiQCAtQ3JlZGVudGlhbCAkQ3JlZHMgLU5vQmFzZTY0Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHUHJpbWFyeVJlcGxpY2EgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKSBOYW1lIG9mIHRoZSBuZXcgQXZhaWxhYmlsaXR5IEdyb3VwLiBJZiBub3Qgc3BlY2lmaWVkIHRoZW4gZGVmYXVsdCBuYW1lIHdpbGwgYmUgdXNlZC4KICAgICAgICBbU3RyaW5nXSAkR3JvdXBOYW1lID0gJ011cmFub0FHJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICROb2RlTGlzdCwKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGUgbmFtZSB0aGF0IHdpbGwgYmUgcHJpbWFyeSBmb3Igc2VsZWN0ZWQgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nXSAkUHJpbWFyeU5vZGUsCgogICAgICAgICMgKFJFUVVJUkVEKSBEYXRhYmFzZSBsaXN0IHRoYXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICREYXRhYmFzZUxpc3QsCgogICAgICAgICMgKFJFUVVJUkVEKSBMaXN0ZW5lciBuYW1lIHRoYXQgd2lsbCBiZSB1c2VkIGJ5IGNsaWVudHMgdG8gY29ubmVjdCB0byBkYXRhYmFzZXMgaW4gdGhhdCBBRwogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyTmFtZSA9ICdNdXJhbm9BR19MaXN0ZW5lcicsCgogICAgICAgICMgKFJFUVVJUkVEKSBJUCBhZGRyZXNzIG9mIHRoZSBsaXN0ZW5lcgogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVySVAsCgogICAgICAgIFtTdHJpbmddICRMaXN0ZW5lcklQTWFzayA9ICcyNTUuMjU1LjI1NS4wJywKCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyUG9ydCA9ICc1MDIzJywKCiAgICAgICAgIyBTeW5jIE1vZGUgTm9kZSBMaXN0CiAgICAgICAgW1N0cmluZ1tdXSAkU3luY01vZGVOb2RlTGlzdCwKCiAgICAgICAgW1N0cmluZ10gJFNoYXJlZFdvcmtEaXIgPSAnU2hhcmVkV29ya0RpcicsCgogICAgICAgIFtTdHJpbmddICRDbGlYbWxGaWxlID0gJycsCgogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlclBhc3N3b3JkCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJQcmltYXJ5IG5vZGU6ICckKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkpJyIKICAgICAgICBXcml0ZS1Mb2cgIkN1cnJlbnQgbm9kZTogJyQoKCRFbnY6Q29tcHV0ZXJOYW1lKS5Ub0xvd2VyKCkpJyIKCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICQoJEVudjpDb21wdXRlck5hbWUpLlRvTG93ZXIoKSkgewogICAgICAgICAgICBXcml0ZS1Mb2cgIlRoaXMgZnVuY3Rpb24gd29ya3Mgb24gUHJpbWFyeU5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZy4iCiAgICAgICAgICAgIHJldHVybgogICAgICAgIH0KCiAgICAgICAgaWYgKCRDbGlYbWxGaWxlIC1lcSAnJykgewogICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ID0gQCgpCiAgICAgICAgICAgIGZvcmVhY2ggKCROb2RlIGluICROb2RlTGlzdCkgewogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAkTm9kZUVuZHBvaW50UG9ydCA9IEltcG9ydC1DbGlYbWwgLVBhdGggIlxcJFByaW1hcnlOb2RlXFNoYXJlZFdvcmtEaXJcJE5vZGUueG1sIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2F0Y2ggewogICAgICAgICAgICAgICAgICAgIFdyaXRlLUxvZyAiVXNpbmcgZGVmYXVsdCBlbmRwb2ludCBwb3J0IDUwMjIiCiAgICAgICAgICAgICAgICAgICAgJE5vZGVFbmRwb2ludFBvcnQgPSA1MDIyCiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uID0gQHsKICAgICAgICAgICAgICAgICAgICAiU0VSVkVSX0lOU1RBTkNFIiA9ICIkTm9kZSI7CiAgICAgICAgICAgICAgICAgICAgIkVORFBPSU5UX1VSTCIgPSAiVENQOi8vJHtOb2RlfToke05vZGVFbmRwb2ludFBvcnR9IjsKICAgICAgICAgICAgICAgICAgICAiQVZBSUxBQklMSVRZX01PREUiID0gIkFTWU5DSFJPTk9VU19DT01NSVQiOwogICAgICAgICAgICAgICAgICAgICJGQUlMT1ZFUl9NT0RFIj0iTUFOVUFMIjsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZiAoJFN5bmNNb2RlTm9kZUxpc3QgLWNvbnRhaW5zICROb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBpbiBTeW5jTW9kZU5vZGVMaXN0IgogICAgICAgICAgICAgICAgICAgICRSZXBsaWNhRGVmaW5pdGlvblsnQVZBSUxBQklMSVRZX01PREUnXSA9ICJTWU5DSFJPTk9VU19DT01NSVQiCiAgICAgICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uWydGQUlMT1ZFUl9NT0RFJ10gPSAiQVVUT01BVElDIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBOT1QgaW4gU3luY01vZGVOb2RlTGlzdCIKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ICs9IEAoJFJlcGxpY2FEZWZpbml0aW9uKQogICAgICAgICAgICB9CgogICAgICAgICAgICAkUHJlZmVyZW5jZXMgPSBAe30KCiAgICAgICAgICAgICRMaXN0ZW5lckRlZmluaXRpb24gPSBAewogICAgICAgICAgICAgICAgIk5BTUUiPSRMaXN0ZW5lck5hbWU7CiAgICAgICAgICAgICAgICAiUE9SVCIgPSAiJExpc3RlbmVyUG9ydCI7CiAgICAgICAgICAgICAgICAiU1RBVElDIiA9ICIkTGlzdGVuZXJJUC8kTGlzdGVuZXJJUE1hc2siCiAgICAgICAgICAgIH0KCiAgICAgICAgICAgICRQYXJhbWV0ZXJzID0gQHsKICAgICAgICAgICAgICAgICdXb3JrRGlyJyA9ICJcXCRQcmltYXJ5Tm9kZVwkU2hhcmVkV29ya0RpciI7CiAgICAgICAgICAgICAgICAnTmFtZScgPSAkR3JvdXBOYW1lOwogICAgICAgICAgICAgICAgJ0RhdGFiYXNlTmFtZXMnID0gJERhdGFiYXNlTGlzdDsKICAgICAgICAgICAgICAgICdSZXBsaWNhRGVmcycgPSAkUmVwbGljYURlZmluaXRpb25MaXN0OwogICAgICAgICAgICAgICAgJ1ByZWZlcmVuY2VzJyA9ICRQcmVmZXJlbmNlczsKICAgICAgICAgICAgICAgICdMaXN0ZW5lckRlZicgPSAkTGlzdGVuZXJEZWZpbml0aW9uOwogICAgICAgICAgICB9CgogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICJcXCRQcmltYXJ5Tm9kZVxTaGFyZWRXb3JrRGlyXCoiIC1Gb3JjZQoKICAgICAgICAgICAgJENsaVhtbEZpbGUgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiQ2xpWG1sIGZpbGU6ICckQ2xpWG1sRmlsZSciCgogICAgICAgICAgICAkbnVsbCA9IEV4cG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUgLUlucHV0T2JqZWN0ICRQYXJhbWV0ZXJzIC1EZXB0aCAxMAoKICAgICAgICAgICAgJG51bGwgPSBJbml0aWFsaXplLUFPQUdQcmltYXJ5UmVwbGljYSBgCiAgICAgICAgICAgICAgICAtQ2xpWG1sRmlsZSAkQ2xpWG1sRmlsZSBgCiAgICAgICAgICAgICAgICAtRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgCiAgICAgICAgICAgICAgICAtVXNlck5hbWUgJFVzZXJOYW1lIGAKICAgICAgICAgICAgICAgIC1Vc2VyUGFzc3dvcmQgJFVzZXJQYXNzd29yZCBgCiAgICAgICAgICAgICAgICAtUHJpbWFyeU5vZGUgJFByaW1hcnlOb2RlCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiSW5uZXIgJ0luaXRpYWxpemUtQU9BR1ByaW1hcnlSZXBsaWNhJyBjYWxsIGNvbXBsZXRlZC4iCiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAgICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gLUFsbAoKICAgICAgICAgICAgJG51bGwgPSBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyBAIgp0cmFwIHsKICAgIGAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJJbXBvcnRpbmcgQ2xpWG1sIHBhcmFtZXRlcnMgZmlsZSAuLi4iCmAkUGFyYW1ldGVycyA9IEltcG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwIGBgCiAgICAtV29ya0RpciBgJFBhcmFtZXRlcnNbJ1dvcmtEaXInXSBgYAogICAgLU5hbWUgYCRQYXJhbWV0ZXJzWydOYW1lJ10gYGAKICAgIC1EYXRhYmFzZU5hbWVzIGAkUGFyYW1ldGVyc1snRGF0YWJhc2VOYW1lcyddIGBgCiAgICAtUmVwbGljYURlZnMgYCRQYXJhbWV0ZXJzWydSZXBsaWNhRGVmcyddIGBgCiAgICAtUHJlZmVyZW5jZXMgYCRQYXJhbWV0ZXJzWydQcmVmZXJlbmNlcyddIGBgCiAgICAtTGlzdGVuZXJEZWYgYCRQYXJhbWV0ZXJzWydMaXN0ZW5lckRlZiddCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgICAgICB9CiAgICB9Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHU2Vjb25kYXJ5UmVwbGljYSB7CiAgICBwYXJhbSAoCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmdbXV0gJE5vZGVMaXN0LAoKICAgICAgICAjIChSRVFVSVJFRCkgTm9kZSBuYW1lIHRoYXQgd2lsbCBiZSBwcmltYXJ5IGZvciBzZWxlY3RlZCBBdmFpbGFiaWxpdHkgR3JvdXAKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlLAoKICAgICAgICBbU3RyaW5nXSAkU2hhcmVkV29ya0RpciA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJERvbWFpbk5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJOYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyUGFzc3dvcmQKICAgICkgCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLWVxICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBmdW5jdGlvbiB3b3JrcyBvbiBhbnkgU2Vjb25kYXJ5Tm9kZSBvbmx5LiIKICAgICAgICAgICAgV3JpdGUtTG9nICJFeGl0aW5nLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAkRnVuY3Rpb25zRmlsZSA9IEV4cG9ydC1GdW5jdGlvbiAtQWxsCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJTdGFydGluZyAnTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXBSZXBsaWNhJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwUmVwbGljYSAtV29ya0RpciAiXFwkUHJpbWFyeU5vZGVcJFNoYXJlZFdvcmtEaXIiCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgIH0KfQoKCgpmdW5jdGlvbiBEaXNhYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb2ZmCiAgICB9Cn0KCgoKZnVuY3Rpb24gRW5hYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb24KICAgIH0KfQoKCgpmdW5jdGlvbiBFbmFibGUtVHJ1c3RlZEhvc3RzIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBTZXQtSXRlbSBXU01hbjpcbG9jYWxob3N0XENsaWVudFxUcnVzdGVkSG9zdHMgLVZhbHVlICcqJyAtRm9yY2UKICAgIH0KfQo=", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgpmdW5jdGlvbiBFeHBvcnQtRnVuY3Rpb24gewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmdbXV0gJE5hbWUsCgogICAgICAgIFtQYXJhbWV0ZXIoVmFsdWVGcm9tUGlwZWxpbmU9JHRydWUpXQogICAgICAgIFtTdHJpbmddICRQYXRoID0gW0lPLlBhdGhdOjpHZXRUZW1wRmlsZU5hbWUoKSwKCiAgICAgICAgW1N3aXRjaF0gJEFsbAogICAgKQoKICAgIGlmIChbSU8uUGF0aF06OkdldEV4dGVuc2lvbigkUGF0aCkgLW5lICdwczEnKSB7CiAgICAgICAgJG51bGwgPSBSZW5hbWUtSXRlbSAtUGF0aCAkUGF0aCAtTmV3TmFtZSAiJFBhdGgucHMxIiAtRm9yY2UKICAgICAgICAkUGF0aCA9ICIkUGF0aC5wczEiCiAgICB9CgogICAgJFN5c3RlbUZ1bmN0aW9ucyA9IEAoCiAgICAgICAgJ0E6JywgJ0I6JywgJ0M6JywgJ0Q6JywgJ0U6JywgJ0Y6JywgJ0c6JywgJ0g6JywgJ0k6JywgJ0o6JywKICAgICAgICAnSzonLCAnTDonLCAnTTonLCAnTjonLCAnTzonLCAnUDonLCAnUTonLCAnUjonLCAnUzonLCAnVDonLAogICAgICAgICdVOicsICdWOicsICdXOicsICdYOicsICdZOicsICdaOicsCiAgICAgICAgJ2NkLi4nLCAnY2RcJywgJ2hlbHAnLCAnbWtkaXInLCAnbW9yZScsICdvc3MnLCAncHJvbXB0JywKICAgICAgICAnQ2xlYXItSG9zdCcsICdHZXQtVmVyYicsICdQYXVzZScsICdUYWJFeHBhbnNpb24yJwogICAgKQoKICAgIGlmICgkQWxsKSB7CiAgICAgICAgR2V0LUNoaWxkSXRlbSBGdW5jdGlvbjogfAogICAgICAgICAgICBXaGVyZS1PYmplY3QgeyRfLk1vZHVsZU5hbWUgLWVxICcnfSB8CiAgICAgICAgICAgIFdoZXJlLU9iamVjdCB7JFN5c3RlbUZ1bmN0aW9ucyAtbm90Y29udGFpbnMgJF8uTmFtZX0gfAogICAgICAgICAgICBGb3JFYWNoLU9iamVjdCB7CiAgICAgICAgICAgICAgICBBZGQtQ29udGVudCAtUGF0aCAkUGF0aCAtVmFsdWUgQCIKCgpmdW5jdGlvbiAkKCRfLk5hbWUpIHsKJCgkXy5TY3JpcHRCbG9jaykKfQoKIkAKICAgICAgICAgICAgfQogICAgfQogICAgZWxzZSB7CiAgICAgICAgZm9yZWFjaCAoJEZ1bmN0aW9uTmFtZSBpbiAkTmFtZSkgewogICAgICAgICAgICAkRnVuY3Rpb25PYmplY3QgPSBHZXQtQ2hpbGRJdGVtICJGdW5jdGlvbjpcJEZ1bmN0aW9uTmFtZSIKICAgICAgICAgICAgaWYgKCRGdW5jdGlvbk9iamVjdCAtbmUgJG51bGwpIHsKICAgICAgICAgICAgICAgIEFkZC1Db250ZW50IC1QYXRoICRQYXRoIC1WYWx1ZSBAIgoKCmZ1bmN0aW9uICRGdW5jdGlvbk5hbWUgewokKCRGdW5jdGlvbk9iamVjdC5TY3JpcHRCbG9jaykKfQoKIkAKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gJFBhdGgKfQo=", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgoKCmZ1bmN0aW9uIFNlbGVjdC1DbGlYbWxCbG9jayB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJFBhdGgsCiAgICAgICAgW1N0cmluZ10gJE91dEZpbGUgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCiAgICApCgogICAgJFRhZ0ZvdW5kID0gJGZhbHNlCiAgICBHZXQtQ29udGVudCAkUGF0aCB8CiAgICAgICAgRm9yRWFjaC1PYmplY3QgewogICAgICAgICAgICBpZiAoJF8gLWVxICcjPCBDTElYTUwnKSB7CiAgICAgICAgICAgICAgICAkVGFnRm91bmQgPSAkdHJ1ZQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICgkVGFnRm91bmQpIHsKICAgICAgICAgICAgICAgIEFkZC1Db250ZW50IC1QYXRoICRPdXRGaWxlIC1WYWx1ZSAkXwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgJE91dEZpbGUKfQoKCgpmdW5jdGlvbiBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJENvbW1hbmQsCiAgICAgICAgJENyZWRlbnRpYWwgPSAkbnVsbCwKICAgICAgICBbU3dpdGNoXSAkSWdub3JlU3RkRXJyLAogICAgICAgIFtTd2l0Y2hdICROb0Jhc2U2NAogICAgKQogICAgYmVnaW4gewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbgogICAgfQogICAgZW5kIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24gLUVuZAogICAgfQogICAgcHJvY2VzcyB7CiAgICAgICAgdHJhcCB7CiAgICAgICAgICAgICYkVHJhcEhhbmRsZXIKICAgICAgICB9CgogICAgICAgICRTdGRPdXQgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCiAgICAgICAgJFN0ZEVyciA9IFtJTy5QYXRoXTo6R2V0VGVtcEZpbGVOYW1lKCkKCiAgICAgICAgJEFyZ3VtZW50TGlzdCA9IEAoJy1PdXRwdXRGb3JtYXQnLCAnWE1MJykKCiAgICAgICAgaWYgKCROb0Jhc2U2NCkgewogICAgICAgICAgICAkVG1wU2NyaXB0ID0gW0lPLlBhdGhdOjpHZXRUZW1wRmlsZU5hbWUoKQogICAgICAgICAgICBSZW5hbWUtSXRlbSAtUGF0aCAiJFRtcFNjcmlwdCIgLU5ld05hbWUgIiRUbXBTY3JpcHQucHMxIiAtRm9yY2UKICAgICAgICAgICAgJFRtcFNjcmlwdCA9ICIkVG1wU2NyaXB0LnBzMSIKCiAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICRUbXBTY3JpcHQKCiAgICAgICAgICAgICRDb21tYW5kIHwgT3V0LUZpbGUgJFRtcFNjcmlwdAoKICAgICAgICAgICAgJEFyZ3VtZW50TGlzdCArPSBAKCctRmlsZScsICIkVG1wU2NyaXB0IikKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICRCeXRlcyA9IFtUZXh0LkVuY29kaW5nXTo6VW5pY29kZS5HZXRCeXRlcygkQ29tbWFuZCkKICAgICAgICAgICAgJEVuY29kZWRDb21tYW5kID0gW0NvbnZlcnRdOjpUb0Jhc2U2NFN0cmluZygkQnl0ZXMpCiAgICAgICAgICAgIAogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAkRW5jb2RlZENvbW1hbmQKCiAgICAgICAgICAgICRBcmd1bWVudExpc3QgKz0gQCgnLUVuY29kZWRDb21tYW5kJywgJEVuY29kZWRDb21tYW5kKQogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nRGVidWcgJEFyZ3VtZW50TGlzdAoKICAgICAgICBXcml0ZS1Mb2cgIlN0YXJ0aW5nIGV4dGVybmFsIFBvd2VyU2hlbGwgcHJvY2VzcyAuLi4iCgogICAgICAgIGlmICgkQ3JlZGVudGlhbCAtZXEgJG51bGwpIHsKICAgICAgICAgICAgJFByb2Nlc3MgPSBTdGFydC1Qcm9jZXNzIC1GaWxlUGF0aCAncG93ZXJzaGVsbC5leGUnIGAKICAgICAgICAgICAgICAgIC1Bcmd1bWVudExpc3QgQCgkQXJndW1lbnRMaXN0KSBgCiAgICAgICAgICAgICAgICAtUmVkaXJlY3RTdGFuZGFyZE91dHB1dCAkU3RkT3V0IGAKICAgICAgICAgICAgICAgIC1SZWRpcmVjdFN0YW5kYXJkRXJyb3IgJFN0ZEVyciBgCiAgICAgICAgICAgICAgICAtTm9OZXdXaW5kb3cgYAogICAgICAgICAgICAgICAgLVdhaXQgYAogICAgICAgICAgICAgICAgLVBhc3NUaHJ1CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkUHJvY2VzcyA9IFN0YXJ0LVByb2Nlc3MgLUZpbGVQYXRoICdwb3dlcnNoZWxsLmV4ZScgYAogICAgICAgICAgICAgICAgLUFyZ3VtZW50TGlzdCBAKCRBcmd1bWVudExpc3QpIGAKICAgICAgICAgICAgICAgIC1SZWRpcmVjdFN0YW5kYXJkT3V0cHV0ICRTdGRPdXQgYAogICAgICAgICAgICAgICAgLVJlZGlyZWN0U3RhbmRhcmRFcnJvciAkU3RkRXJyIGAKICAgICAgICAgICAgICAgIC1DcmVkZW50aWFsICRDcmVkZW50aWFsIGAKICAgICAgICAgICAgICAgIC1Ob05ld1dpbmRvdyBgCiAgICAgICAgICAgICAgICAtV2FpdCBgCiAgICAgICAgICAgICAgICAtUGFzc1RocnUKICAgICAgICB9CgogICAgICAgIFdyaXRlLUxvZyAiRXh0ZXJuYWwgUG93ZXJTaGVsbCBwcm9jZXNzIGV4aXRlZCB3aXRoIGV4aXQgY29kZSAnJCgkUHJvY2Vzcy5FeGl0Q29kZSknLiIKCiAgICAgICAgI2lmICgkQXJndW1lbnRMaXN0IC1jb250YWlucyAnLUZpbGUnKSB7CiAgICAgICAgIyAgICBSZW1vdmUtSXRlbSAtUGF0aCAkVG1wU2NyaXB0IC1Gb3JjZQogICAgICAgICN9CgogICAgICAgICRFcnJvckFjdGlvblByZWZlcmVuY2VTYXZlZCA9ICRFcnJvckFjdGlvblByZWZlcmVuY2UKICAgICAgICAkRXJyb3JBY3Rpb25QcmVmZXJlbmNlID0gJ1NpbGVudGx5Q29udGludWUnCgogICAgICAgIFdyaXRlLUxvZ0RlYnVnICJTdGRPdXQgZmlsZSBpcyAnJFN0ZE91dCciCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIlN0ZEVyciBmaWxlIGlzICckU3RkRXJyJyIKCiAgICAgICAgaWYgKChHZXQtSXRlbSAkU3RkT3V0KS5MZW5ndGggLWd0IDApIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICJMb2FkaW5nIFN0ZE91dCBmcm9tICckU3RkT3V0JyIKICAgICAgICAgICAgICAgICRUbXBGaWxlID0gU2VsZWN0LUNsaVhtbEJsb2NrICRTdGRPdXQKICAgICAgICAgICAgICAgICRTdGRPdXRPYmplY3QgPSBJbXBvcnQtQ2xpeG1sICRUbXBGaWxlCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPFN0ZE91dD4iCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAoJFN0ZE91dE9iamVjdCkKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L1N0ZE91dD4iCiAgICAgICAgICAgICAgICAkU3RkT3V0T2JqZWN0CiAgICAgICAgICAgICAgICAjUmVtb3ZlLUl0ZW0gLVBhdGggJFRtcEZpbGUgLUZvcmNlCiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2F0Y2ggewogICAgICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIkFuIGVycm9yIG9jY3VyZWQgd2hpbGUgbG9hZGluZyBTdGRPdXQgZnJvbSAnJFRtcEZpbGUnIgogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBpZiAoKEdldC1JdGVtICRTdGRFcnIpLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIkxvYWRpbmcgU3RkRXJyIC4uLiIKICAgICAgICAgICAgICAgICRUbXBGaWxlID0gU2VsZWN0LUNsaVhtbEJsb2NrICRTdGRFcnIKICAgICAgICAgICAgICAgICRTdGRFcnJPYmplY3QgPSBJbXBvcnQtQ2xpeG1sICRUbXBGaWxlCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPFN0ZEVycj4iCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAoJFN0ZEVyck9iamVjdCkKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L1N0ZEVycj4iCiAgICAgICAgICAgICAgICBpZiAoLW5vdCAkSWdub3JlU3RkRXJyKSB7CiAgICAgICAgICAgICAgICAgICAgJFN0ZEVyck9iamVjdAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgI1JlbW92ZS1JdGVtIC1QYXRoICRUbXBGaWxlIC1Gb3JjZQogICAgICAgICAgICB9CiAgICAgICAgICAgIGNhdGNoIHsKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICJBbiBlcnJvciBvY2N1cmVkIHdoaWxlIGxvYWRpbmcgU3RkRXJyIGZyb20gJyRUbXBGaWxlJyIKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICRFcnJvckFjdGlvblByZWZlcmVuY2VTYXZlZAoKICAgICAgICBpZiAoJFByb2Nlc3MuRXhpdENvZGUgLW5lIDApIHsKICAgICAgICAgICAgdGhyb3coIkV4dGVybmFsIFBvd2VyU2hlbGwgcHJvY2VzcyBleGl0ZWQgd2l0aCBjb2RlICckKCRQcm9jZXNzLkV4aXRDb2RlKSciKQogICAgICAgIH0KCiAgICAgICAgI1JlbW92ZS1JdGVtICRTdGRPdXQgLUZvcmNlCiAgICAgICAgI1JlbW92ZS1JdGVtICRTdGRFcnIgLUZvcmNlCiAgICB9Cn0K" ] } \ No newline at end of file diff --git a/data/templates/agent/SqlServerCluster/InitializeAlwaysOn.template b/data/templates/agent/SqlServerCluster/InitializeAlwaysOn.template index b888a45..01fdb49 100644 --- a/data/templates/agent/SqlServerCluster/InitializeAlwaysOn.template +++ b/data/templates/agent/SqlServerCluster/InitializeAlwaysOn.template @@ -1,4 +1,13 @@ { + "Scripts": [ + "ImportCoreFunctions.ps1", + "OptionParser.ps1", + "SQLServerOptionParsers.ps1", + "SQLServerInstaller.ps1", + "Export-Function.ps1", + "Start-PowerShellProcess.ps1", + "SQLServerForAOAG.ps1" + ], "Commands": [ { "Name": "Initialize-AlwaysOnAvailabilityGroup", @@ -10,14 +19,5 @@ "DomainName": "$domainName" } } - ], - "Scripts": [ - "SW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zIC1Gb3JjZQoKCmZ1bmN0aW9uIFNob3ctSW52b2NhdGlvbkluZm8gewogICAgcGFyYW0gKAogICAgICAgICRJbnZvY2F0aW9uLAogICAgICAgIFtTd2l0Y2hdICRFbmQKICAgICkKCiAgICBpZiAoJEVuZCkgewogICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L2Z1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICB9CiAgICBlbHNlIHsKICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPGZ1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjxwYXJhbT4iCiAgICAgICAgZm9yZWFjaCAoJFBhcmFtZXRlciBpbiAkSW52b2NhdGlvbi5NeUNvbW1hbmQuUGFyYW1ldGVycykgewogICAgICAgICAgICBmb3JlYWNoICgkS2V5IGluICRQYXJhbWV0ZXIuS2V5cykgewogICAgICAgICAgICAgICAgJFR5cGUgPSAkUGFyYW1ldGVyWyRLZXldLlBhcmFtZXRlclR5cGUuRnVsbE5hbWUKICAgICAgICAgICAgICAgIGZvcmVhY2ggKCRWYWx1ZSBpbiAkSW52b2NhdGlvbi5Cb3VuZFBhcmFtZXRlcnNbJEtleV0pIHsKICAgICAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiWyRUeXBlXSAkS2V5ID0gJyRWYWx1ZSciCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjwvcGFyYW0+IgogICAgfQp9CgoKJFRyYXBIYW5kbGVyID0gewogICAgV3JpdGUtTG9nRXJyb3IgQCgiPGV4Y2VwdGlvbj4iLCAkXykgLUVudGlyZU9iamVjdAogICAgV3JpdGUtTG9nRXJyb3IgIjwvZXhjZXB0aW9uPiIKICAgIGJyZWFrCn0KCgp0cmFwIHsKICAgICYkVHJhcEhhbmRsZXIKfQoKJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICdTdG9wJwoKCjwjCiMgVXNhZ2UgZXhhbXBsZSBmb3IgU2hvdy1JbnZvY2F0aW9uSW5mbwoKZnVuY3Rpb24gTXlGdW5jdGlvbiB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJFZhbHVlMSwKICAgICAgICBbU3RyaW5nXSAkVmFsdWUyLAogICAgICAgIFtJbnRdICRJbnQxCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KICAgICAgICAjIE1haW4gY29kZSBoZXJlCiAgICB9Cn0KIz4K", - "ZnVuY3Rpb24gTmV3LU9wdGlvbiAoW3N0cmluZ10kTmFtZSwgW3N3aXRjaF0kU3dpdGNoLCBbc3dpdGNoXSRCb29sZWFuLCBbc3dpdGNoXSRTdHJpbmcsIFtzd2l0Y2hdJExpc3QsICRDb25zdHJhaW50cz0kbnVsbCkgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBPcHRpb24gb2JqZWN0CgogICAgLkRFU0NSSVBUSU9OCiAgICBPcHRpb24gb2JqZWN0IGlzIGEgdmlydHVhbCBvYmplY3QgcmVwcmVzdG50aW5nIHR5cGVkIGNvbW1hbmQgbGluZSBvcHRpb24uIFRoZXNlIG9iamVjdHMgZW5jYXBzdWxhdGUgZXNjYXBpbmcgYW5kCiAgICB2YWxpZGF0aW9uIG1hdHRlcnMuCgogICAgT25lIGFuZCBvbmx5IG9uZSBvZiB0aGUgc3dpdGNoZXMgJ1N3aXRjaCcsICdCb29sZWFuJywgJ1N0cmluZycgb3IgJ0xpc3QnIHNob3VsZCBiZSBwcm92aWRlZC4KCiAgICAuUEFSQU1FVEVSIE5hbWUKICAgIE9wdGlvbiBuYW1lIGFzIGl0IGFwcGVhcnMgaW4gdGhlIGNvbW1hbmQgbGluZS4KCiAgICAuUEFSQU1FVEVSIFN3aXRjaAogICAgVXNlIHRoaXMgc3dpdGNoIHRvIGNyZWF0ZSB2YWx1ZWxlc3Mgb3B0aW9uIChhIHN3aXRjaCkuCgogICAgLlBBUkFNRVRFUiBCb29sZWFuCiAgICBVc2UgdGhpcyBzd2l0Y2ggdG8gY3JlYXRlIGJvb2xlYW4gb3B0aW9uLiBJdHMgdmFsdWUgaXMgYWx3YXlzIGNvbnZlcnRlZCB0byAiMSIgb3IgIjAiCgogICAgLlBBUkFNRVRFUiBTdHJpbmcKICAgIFVzZSB0aGlzIHN3aXRjaCB0byBjcmVhdGUgc3RyaW5nIG9wdGlvbi4gSXRzIHZhbHVlIHdpbGwgYmUgcHJvcGVybHkgcXVvdGVkIGlmIG5lY2Vzc2FyeS4KCiAgICAuUEFSQU1FVEVSIExpc3QKICAgIFVzZSB0aGlzIHN3aXRjaCB0byBjcmVhdGUgb3B0aW9uIHdpdGggbGlzdCB2YWx1ZS4gVmFsdWVzIHdpbGwgYmUgcHV0IGludG8gY29tbWFuZCBsaW5lIHVzaW5nIHZhbGlkIHZhbHVlIGRlbGVtaXRlciAoYSBjb21tYSkKCiAgICAuUEFSQU1FVEVSIENvbnN0cmFpbnRzCiAgICBXaGVuIHRoaXMgcGFyYW1ldGVyIGlzIHNwZWNpZmllZCwgb3B0aW9uIHZhbHVlcyBhcmUgbGltaXRlZCB0byBvcHRpb25zIGZyb20gdGhhdCBsaXN0LgoKICAgICM+CgogICAgJE9wdGlvbiA9IE5ldy1PYmplY3QgLVR5cGVOYW1lIFBTT2JqZWN0CgogICAgIyBGaWVsZHMKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIE5vdGVQcm9wZXJ0eSBUeXBlIC12YWx1ZSAkbnVsbAogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IE5hbWUgLXZhbHVlICRudWxsCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgQWxsb3dlZFZhbHVlcyAtdmFsdWUgJG51bGwKCiAgICAjIEluaXQKCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBTY3JpcHRNZXRob2QgX19pbml0X18gewogICAgICAgIHBhcmFtKFtzdHJpbmddJE5hbWUsICRTd2l0Y2gsICRCb29sZWFuLCAkU3RyaW5nLCAkTGlzdCkKCiAgICAgICAgJHRoaXMuTmFtZSA9ICROYW1lCiAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgIyBXaXRoIHJlc3BlY3QgZm9yIG91ciBkZXZlbG9wZXJzIHdlIGRvIG5vdCBjaGVjayBmb3IgZG91YmxlIHR5cGUgc2VsZWN0ZWQKICAgICAgICBpZiAoJFN3aXRjaCkgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uU3dpdGNoKCR0aGlzKQogICAgICAgIH0gZWxzZWlmICgkQm9vbGVhbikgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uQm9vbGVhbigkdGhpcykKICAgICAgICB9IGVsc2VpZiAoJFN0cmluZykgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uU3RyaW5nKCR0aGlzKQogICAgICAgIH0gZWxzZWlmICgkTGlzdCkgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uTGlzdCgkdGhpcykKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aHJvdyAiU3dpdGNoLCBCb29sZWFuLCBTdHJpbmcgb3IgTGlzdCBvcHRpb24gdHlwZSBtdXN0IGJlIHByb3ZpZGVkIGZvciBvcHRpb24gJyROYW1lJyIKICAgICAgICB9CiAgICB9CgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIF9fcG9zdF9pbml0X18gewogICAgICAgIHBhcmFtKCRDb25zdHJhaW50cz0kbnVsbCkKICAgICAgICBpZiAoJENvbnN0cmFpbnRzIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkdGhpcy5BbGxvd2VkVmFsdWVzID0gQCgpCiAgICAgICAgICAgICR0aGlzLkFsbG93ZWRWYWx1ZXMgPSAkdGhpcy5BbGxvd2VkVmFsdWVzICsgJENvbnN0cmFpbnRzCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgJENvbnN0cmFpbnRzID0gJG51bGwKICAgICAgICB9CiAgICB9CgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBWYWxpZGF0ZSB7CiAgICAgICAgaWYgKCR0aGlzLkFsbG93ZWRWYWx1ZXMgLW5lICRudWxsKSB7CiAgICAgICAgICAgIGlmICgtbm90KCR0aGlzLkFsbG93ZWRWYWx1ZXMgLWNvbnRhaW5zICR0aGlzLlZhbHVlKSkgewogICAgICAgICAgICAgICAgJEN0cyA9ICR0aGlzLkFsbG93ZWRWYWx1ZXMgLWpvaW4gJywnCiAgICAgICAgICAgICAgICB0aHJvdyAiT3B0aW9uICckKCR0aGlzLk5hbWUpJyBtYXkgaGF2ZSB2YWx1ZXMgKCRDdHMpIGJ1dCBub3QgJyQoJHRoaXMuVmFsdWUpJyIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciAtRm9yY2UgU2NyaXB0TWV0aG9kIFRvU3RyaW5nIHsKICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpIgogICAgfQoKICAgICMgaW52b2tlIGNvbnN0cnVjdG9yCgogICAgJE9wdGlvbi5fX2luaXRfXygkTmFtZSwgJFN3aXRjaCwgJEJvb2xlYW4sICRTdHJpbmcsICRMaXN0KQogICAgJE9wdGlvbi5fX3Bvc3RfaW5pdF9fKCRDb25zdHJhaW50cykKCiAgICByZXR1cm4gJE9wdGlvbgp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uU3dpdGNoKCRPcHRpb24pIHsKfQoKZnVuY3Rpb24gQXVnbWVudE9wdGlvbkJvb2xlYW4oJE9wdGlvbikgewogICAgIyBGaWVsZHMKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIE5vdGVQcm9wZXJ0eSBWYWx1ZSAtdmFsdWUgJGZhbHNlCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBUb1N0cmluZyB7CiAgICAgICAgaWYgKCR0aGlzLlZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9MSIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpPTAiCiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uU3RyaW5nKCRPcHRpb24pIHsKICAgICMgRmllbGRzCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgVmFsdWUgLXZhbHVlICIiCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBUb1N0cmluZyB7CiAgICAgICAgJHYgPSAiJCgkdGhpcy5WYWx1ZSkiCiAgICAgICAgaWYgKCR2IC1tYXRjaCAnLiogLionKSB7CiAgICAgICAgICAgICMgVE9ETzogRXNjYXBlIGRvdWJsZSBxdW90ZSBjaGFyYWN0ZXJzIGlmIHBvc3NpYmxlCiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9YCIkdmAiIgogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9JHYiCiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uTGlzdCgkT3B0aW9uKSB7CiAgICAjIEZpZWxkcwogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IFZhbHVlIC12YWx1ZSBAKCkKCiAgICAjIE1ldGhvZHMKCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciAtRm9yY2UgU2NyaXB0TWV0aG9kIFZhbGlkYXRlIHsKICAgICAgICBpZiAoJHRoaXMuQWxsb3dlZFZhbHVlcyAtbmUgJG51bGwpIHsKICAgICAgICAgICAgZm9yZWFjaCAoJFYgaW4gJHRoaXMuVmFsdWUpIHsKICAgICAgICAgICAgICAgIGlmICgtbm90KCR0aGlzLkFsbG93ZWRWYWx1ZXMgLWNvbnRhaW5zICRWKSkgewogICAgICAgICAgICAgICAgICAgICRDdHMgPSAkdGhpcy5BbGxvd2VkVmFsdWVzIC1qb2luICcsJwogICAgICAgICAgICAgICAgICAgIHRocm93ICJPcHRpb24gJyQoJHRoaXMuTmFtZSknIG1heSBoYXZlIHZhbHVlcyAoJEN0cykgYnV0IG5vdCAnJFYnIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIC1Gb3JjZSBTY3JpcHRNZXRob2QgVG9TdHJpbmcgewogICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9JCgkdGhpcy5WYWx1ZSAtam9pbiAnLCcpIgogICAgfQp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyKCkgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBPcHRpb25QYXJzZXIgb2JqZWN0LgoKICAgIC5ERVNDUklQVElPTgogICAgT3B0aW9uUGFyc2VyIG9iamVjdCBsZXZlcmFnZXMgT3B0aW9uIG9iamVjdHMgY2FwYWJpbGl0aWVzIGFuZCBidWlsZHMgdmFsaWQgY29tbWFuZCBsaW5lIHVzaW5nIHNwZWNpZmllZCBvcHRpb25zLgogICAgQW4gYXBwbGljYXRpb24gbWF5IGFsc28gYmUgaW52b2tlZCB3aXRoIE9wdGlvblBhcnNlci4KCiAgICAjPgoKICAgICRPcHRpb25QYXJzZXIgPSBOZXctT2JqZWN0IC1UeXBlTmFtZSBQU09iamVjdAoKICAgICMgRmllbGRzCiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgT3B0aW9ucyAtdmFsdWUgQHt9CiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgRGVmYXVsdHMgLXZhbHVlIEB7fQogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IFJlcXVpcmVkT3B0aW9ucyAtdmFsdWUgQCgpCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIEFkZE9wdGlvbiB7CiAgICAgICAgPCMKICAgICAgICAuU1lOT1BTSVMKICAgICAgICBBZGRzIHN1cHBvcnRlZCBvcHRpb24gaW50byBPcHRpb25QYXJzZXIuCiAgICAgICAgCiAgICAgICAgLkRFU0NSSVBUSU9OCiAgICAgICAgT3B0aW9uUGFyc2VyIGRvZXMgbm90IGFsbG93IHVzaW5nIHVucmVjb2duaXplZCBvcHRpb25zLiBVc2UgdGhpcyBtZXRob2QgdG8gZmlsbCBPcHRpb25QYXJzZXIgd2l0aCByZWNvZ25pemVkIG9wdGlvbnMKCiAgICAgICAgLlBBUkFNRVRFUiBPcHRpb24KICAgICAgICBPcHRpb24gb2JqZWN0CgogICAgICAgIC5QQVJBTUVURVIgUmVxdWlyZWQKICAgICAgICBSZXF1aXJlZCBvcHRpb24gc3dpdGNoCgogICAgICAgIC5QQVJBTUVURVIgRGVmYXVsdAogICAgICAgIE9wdGlvbiBkZWZhdWx0IHZhbHVlCiAgICAgICAgIz4KICAgICAgICBwYXJhbSgkT3B0aW9uLCBbYm9vbF0kUmVxdWlyZWQ9JGZhbHNlLCAkRGVmYXVsdD0kbnVsbCkKICAgICAgICAkdGhpcy5PcHRpb25zLkFkZCgkT3B0aW9uLk5hbWUsICRPcHRpb24pCiAgICAgICAgaWYgKCRSZXF1aXJlZCkgewogICAgICAgICAgICAkdGhpcy5SZXF1aXJlZE9wdGlvbnMgPSAkdGhpcy5SZXF1aXJlZE9wdGlvbnMgKyAkT3B0aW9uLk5hbWUKICAgICAgICAgICAgaWYgKCRPcHRpb24gfCBHZXQtTWVtYmVyICJWYWx1ZSIpIHsKICAgICAgICAgICAgICAgIGlmICgkRGVmYXVsdCkgewogICAgICAgICAgICAgICAgICAgICR0aGlzLkRlZmF1bHRzLkFkZCgkT3B0aW9uLk5hbWUsICREZWZhdWx0KQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgJHRoaXMuRGVmYXVsdHMuQWRkKCRPcHRpb24uTmFtZSwgJG51bGwpCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIFBhcnNlIHsKICAgICAgICA8IwogICAgICAgIC5TWU5PUFNJUwogICAgICAgIFBhcnNlcyBzdXBwbGllZCBvcHRpb25zIGFuZCByZXR1cm5zIGNvbW1hbmQgbGluZSBwYXJhbWV0ZXJzIGFycmF5LgogICAgICAgIAogICAgICAgIC5ERVNDUklQVElPTgogICAgICAgIFRoaXMgbWV0aG9kIHZlcmlmaWVzIHRoYXQgb25seSBzdXBwb3J0ZWQgb3B0aW9ucyBhcmUgcHJvdmlkZWQsIGFsbCBtYW5kYXRvcnkgb3B0aW9ucyBhcmUgaW4gcGxhY2UsIAogICAgICAgIGFsbCBvcHRpb24gbWVldCBjb25zdHJhaW50cyBpZiBhbnkuIFVuc3BlY2lmaWVkIG9wdGlvbnMgd2l0aCBkZWZhdWx0IHZhbHVlcyBhcmUgYWRkZWQgdG8gY29tbWFuZCBsaW5lLgogICAgICAgIFNvLCBtYW5kYXRvcnkgb3B0aW9uIHdpdGggZGVmYXVsdCB2YWx1ZSBuZXZlciBjYXVzZXMgZXhjZXB0aW9uLgoKICAgICAgICAuUEFSQU1FVEVSIE9wdGlvbnMKICAgICAgICBBIGhhc2ggbWFwIG9mIG9wdGlvbnMgdG8gcGFyc2UuIE9wdGlvbiBuYW1lcyBzaG91bGQgYmUgbWFwcGVkIHRvIGNvcnJlc3BvbmRpbmcgdmFsdWVzLgogICAgICAgICM+CiAgICAgICAgcGFyYW0oW2hhc2h0YWJsZV0kT3B0aW9ucykKCiAgICAgICAgJENvbW1hbmRMaW5lID0gQCgpCiAgICAgICAgZm9yZWFjaCAoJFJlcXVpcmVkT3B0aW9uTmFtZSBpbiAkdGhpcy5SZXF1aXJlZE9wdGlvbnMpIHsKICAgICAgICAgICAgaWYgKC1ub3QgJE9wdGlvbnMuQ29udGFpbnNLZXkoJFJlcXVpcmVkT3B0aW9uTmFtZSkpIHsKICAgICAgICAgICAgICAgICREZWZhdWx0ID0gJHRoaXMuRGVmYXVsdHMuR2V0X0l0ZW0oJFJlcXVpcmVkT3B0aW9uTmFtZSkKICAgICAgICAgICAgICAgIGlmICgkdGhpcy5EZWZhdWx0cy5Db250YWluc0tleSgkUmVxdWlyZWRPcHRpb25OYW1lKSkgewogICAgICAgICAgICAgICAgICAgICRPcHRpb25zLkFkZCgkUmVxdWlyZWRPcHRpb25OYW1lLCAkdGhpcy5EZWZhdWx0cy5HZXRfSXRlbSgkUmVxdWlyZWRPcHRpb25OYW1lKSkKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgIlJlcXVpcmVkIG9wdGlvbiAnJFJlcXVpcmVkT3B0aW9uTmFtZScgaXMgbWlzc2luZyIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZm9yZWFjaCAoJE9wdGlvbk5hbWUgaW4gJCgkT3B0aW9ucy5rZXlzKSkgewogICAgICAgICAgICAkT3B0aW9uID0gJHRoaXMuT3B0aW9ucy5HZXRfSXRlbSgkT3B0aW9uTmFtZSkKICAgICAgICAgICAgaWYgKCRPcHRpb24gLWVxICRudWxsKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAiT3B0aW9uICckT3B0aW9uTmFtZScgaXMgbm90IGFsbG93ZWQiCiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCRPcHRpb24gfCBHZXQtTWVtYmVyICJWYWx1ZSIpIHsKICAgICAgICAgICAgICAgICRPcHRpb24uVmFsdWUgPSAkT3B0aW9ucy5HZXRfSXRlbSgkT3B0aW9uTmFtZSkKICAgICAgICAgICAgfQogICAgICAgICAgICAkT3B0aW9uLlZhbGlkYXRlKCkKICAgICAgICAgICAgJENvbW1hbmRMaW5lID0gJENvbW1hbmRMaW5lICsgJE9wdGlvbi5Ub1N0cmluZygpCiAgICAgICAgfQogICAgICAgIHJldHVybiAkQ29tbWFuZExpbmUKICAgIH0KCiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBTY3JpcHRNZXRob2QgRXhlY3V0ZUJpbmFyeSB7CiAgICAgICAgcGFyYW0oJEJpbmFyeSwgW2hhc2h0YWJsZV0kT3B0aW9ucyA9IEB7fSwgJENvbW1hbmRMaW5lU3VmZml4ID0gQCgpKQogICAgICAgIDwjCiAgICAgICAgLlNZTk9QU0lTCiAgICAgICAgRXhlY3V0ZXMgYmluYXJ5IHdpdGggYSBjb21tYW5kIGxpbmUgY29uc3RydWN0ZWQgZnJvbSBwcm92aWRlZCBvcHRpb25zLiBBbiBhcmJpdHJhcnkgc3VmZml4IG1heSBiZSAKICAgICAgICBhcHBlbmRlZCB0byB0aGUgY29tbWFuZCBsaW5lLgogICAgICAgIAogICAgICAgIC5ERVNDUklQVElPTgogICAgICAgIFRoaXMgbWV0aG9kIHVzZXMgT3B0aW9uUGFyc2VyLlBhcnNlIG1ldGhvZCB0byBjb25zdHJ1Y3QgY29tbWFuZCBsaW5lLiBJZiB0aGVyZSBhIGNvbW1hbmQgbGluZSBzdWZmaXggCiAgICAgICAgd2FzIHN1cHBsaWVkLCBpdCBpcyBhcHBlbmRlZCB0byB0aGUgZW5kIG9mIGNvbW1hbmQgbGluZS4gTm9ybWFsbHkgY29tbWFuZCBsaW5lIHN1ZmZpeCBzaG91bGQgY29udGFpbgogICAgICAgIGxlYWRpbmcgc3BhY2UgY2hhcmFjdGVyLgoKICAgICAgICBNZXRob2Qgd2FpdHMgZm9yIGV4ZWN1dGFibGUgcHJvY2VzcyB0byBjb21wbGV0ZSBhbmQgcmV0dXJucyBpdHMgZXhpdCBjb2RlLgoKICAgICAgICAuUEFSQU1FVEVSIEJpbmFyeQogICAgICAgIEZ1bGwgb3IgcmVsYXRpdmUgcGF0aCB0byB0aGUgZXhlY3V0YWJsZSB0byBydW4uCgogICAgICAgIC5QQVJBTUVURVIgT3B0aW9ucwogICAgICAgIEEgaGFzaCBtYXAgb2Ygb3B0aW9ucyB0byBwYXNzIHRvIHRoZSBleGVjdXRhYmxlLgoKICAgICAgICAuUEFSQU1FVEVSIENvbW1hbmRMaW5lU3VmZml4CiAgICAgICAgQXJiaXRyYXJ5IGNvbW1hbmQgbGluZSBzdWZmaXguIE5vcm1hbGx5IGl0IHNob3VkIGhhdmUgbGVhZGluZyBzcGFjZSBjaGFyYWN0ZXIuCiAgICAgICAgIz4KCiAgICAgICAgJEJpbmFyeSA9IEdldC1JdGVtICRCaW5hcnkKICAgICAgICAkQ29tbWFuZExpbmUgPSAkdGhpcy5QYXJzZSgkT3B0aW9ucykKICAgICAgICBpZiAoJENvbW1hbmRMaW5lU3VmZml4KSB7CiAgICAgICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICRDb21tYW5kTGluZVN1ZmZpeAogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJFeGVjdXRpbmc6ICQoJEJpbmFyeS5GdWxsTmFtZSkgJCgkQ29tbWFuZExpbmUgLWpvaW4gJyAnKSIKICAgICAgICAkcHJvY2VzcyA9IFtTeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2Vzc106OlN0YXJ0KCRCaW5hcnksICRDb21tYW5kTGluZSkKICAgICAgICAkcHJvY2Vzcy5XYWl0Rm9yRXhpdCgpCiAgICAgICAgJHByb2Nlc3MuUmVmcmVzaCgpCiAgICAgICAgcmV0dXJuICRwcm9jZXNzLkV4aXRDb2RlCiAgICB9CgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQo=", - "ZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckluc3RhbGwgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBhbiBvcHRpb24gcGFyc2VyIGZvciBNUyBTUUwgU2VydmVyIDIwMTIgc2V0dXAgIklOU1RBTEwiIGFjdGlvbi4KCiAgICAuREVTQ1JJUFRJT04KICAgIFVzZSB0aGlzIGNtZGxldCB0byBjcmVhdGUgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJJTlNUQUxMIiBhY3Rpb24uCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkSXNQYXJ0T2ZEb21haW4gPSAoR2V0LVdtaU9iamVjdCBXaW4zMl9Db21wdXRlclN5c3RlbSkuUGFydE9mRG9tYWluCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIklOU1RBTEwiKSwgJHRydWUsICJJTlNUQUxMIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJQUNDRVBUU1FMU0VSVkVSTElDRU5TRVRFUk1TIiAtU3dpdGNoKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5VIiAtU3dpdGNoKSkKICAgICMkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlVwZGF0ZVNvdXJjZSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVSUk9SUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTCIsIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJEUSIsIkFTIiwiUlMiLCJEUUMiLCJJUyIsIk1EUyIsIlRvb2xzIiwiQkMiLCJCT0wiLCJCSURTIiwiQ29ubiIsIlNTTVMiLCJBRFZfU1NNUyIsIkRSRVBMQVlfQ1RMUiIsIkRSRVBMQVlfQ0xUIiwiU05BQ19TREsiLCJTREsiLCJMb2NhbERCIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJPTEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiU1BJX0FTX0V4aXN0aW5nRmFybSIsICJTUElfQVNfTmV3RmFybSIsICJBbGxGZWF0dXJlc19XaXRoRGVmYXVsdHMiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRFdPV0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlBJRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlVJTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJOb3JtYWwiLCAiQXV0b0FkdmFuY2UiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FNUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTQkFDS1VQRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU0NPTExBVElPTiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQVNDT05GSUdESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTREFUQURJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQVNMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU0VSVkVSTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNVUxUSURJTUVOU0lPTkFMIiwgIlBPV0VSUElWT1QiLCAiVEFCVUxBUiIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKCiAgICAjJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXCRFTlY6VVNFUk5BTUUiKQogICAgaWYgKCRJc1BhcnRPZkRvbWFpbikgewogICAgICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFbnY6VVNFUkRPTUFJTlxBZG1pbmlzdHJhdG9yIikKICAgIH0KICAgIGVsc2UgewogICAgICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFbnY6Q09NUFVURVJOQU1FXEFkbWluaXN0cmF0b3IiKQogICAgfQoKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1RFTVBESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTUFJPVklERVJNU09MQVAiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGQVJNQUNDT1VOVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkFSTVBBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJQQVNTUEhSQVNFIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGQVJNQURNSU5JUE9SVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQlJPV1NFUlNWQ1NUQVJUVVBUWVBFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5BQkxFUkFOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNRTERBVEFESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNBUFdEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTRUNVUklUWU1PREUiIC1TdHJpbmcgLUNvbnN0cmFpbnJzICgiU1FMIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTEJBQ0tVUERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMQ09MTEFUSU9OIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBRERDVVJSRU5UVVNFUkFTU1FMQURNSU4iIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgCiAgICAjJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6VVNFUkRPTUFJTlwkRU5WOlVTRVJOQU1FIikKICAgIGlmICgkSXNQYXJ0T2ZEb21haW4pIHsKICAgICAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXEFkbWluaXN0cmF0b3IiKQogICAgfQogICAgZWxzZSB7CiAgICAgICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6Q09NUFVURVJOQU1FXEFkbWluaXN0cmF0b3IiKQogICAgfQogICAgCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVEVNUERCRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxURU1QREJMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFVTRVJEQkRJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVVNFUkRCTE9HRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGSUxFU1RSRUFNTEVWRUwiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiMCIsICIxIiwgIjIiLCAiMyIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGSUxFU1RSRUFNU0hBUkVOQU1FIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGVFNWQ0FDQ09VTlQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZUU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklTU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSVNTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSVNTVkNTdGFydHVwVHlwZSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIk5QRU5BQkxFRCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlRDUEVOQUJMRUQiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU0lOU1RBTExNT0RFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIlNoYXJlUG9pbnRGaWxlc09ubHlNb2RlIiwgIkRlZmF1bHROYXRpdmVNb2RlIiwgIkZpbGVzT25seU1vZGUiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNBQ0NPVU5UIiAtU3RyaW5nKSwgJHRydWUsICJOVCBBVVRIT1JJVFlcTmV0d29yayBTZXJ2aWNlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ1N0YXJ0dXBUeXBlIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclByZXBhcmVJbWFnZSB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgTm90ZSB0aGF0IGZvciBpbnN0YWxsZXIgdmVyc2lvbiBvZiBNUyBTUUwgU2VydmVyIHByaW9yIHRvIDIwMTIgU1AxIEN1bXVsYXRpdmUgVXBkYXRlIDIgb25seSB0aGUKICAgIGZvbGxvd2luZyBmZWF0dXJlcyBhcmUgc3VwcG9ydGVkOiBTUUxFbmdpbmUsIFJlcGxpY2F0aW9uLCBGdWxsVGV4dCwgUlMKCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUNUSU9OIiAtU3RyaW5nIC1Db25zdHJhaW50cyAiUHJlcGFyZUltYWdlIiksICR0cnVlLCAiUHJlcGFyZUltYWdlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJQUNDRVBUU1FMU0VSVkVSTElDRU5TRVRFUk1TIiAtU3dpdGNoKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5VIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJVcGRhdGVFbmFibGVkIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJVcGRhdGVTb3VyY2UiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkNPTkZJR1VSQVRJT05GSUxFIiAtU3RyaW5nKSkKIyAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJSUyIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGRUFUVVJFUyIgLUxpc3QgLUNvbnN0cmFpbnRzICgiU1FMIiwiU1FMRW5naW5lIiwiUmVwbGljYXRpb24iLCJGdWxsVGV4dCIsIkRRIiwiQVMiLCJSUyIsIkRRQyIsIklTIiwiTURTIiwiVG9vbHMiLCJCQyIsIkJPTCIsIkJJRFMiLCJDb25uIiwiU1NNUyIsIkFEVl9TU01TIiwiRFJFUExBWV9DVExSIiwiRFJFUExBWV9DTFQiLCJTTkFDX1NESyIsIlNESyIsIkxvY2FsREIiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklORElDQVRFUFJPR1JFU1MiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTExTSEFSRURESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJTlNUQU5DRUlEIiAtU3RyaW5nKSwgJHRydWUsICJNU1NRTFNFUlZFUiIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJQcmVwYXJlSW1hZ2VTUDFVMiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgVGhpcyBjbWRsZXQgc2hvdWxkIGJlIHVzZWQgb25seSBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIFNQMSBDaW1pbGF0aXZlIFVwZGF0ZSAyIG9yIGxhdGVyLgoKICAgIE5vdGUgdGhhdCBmb3IgaW5zdGFsbGVyIHZlcnNpb24gb2YgTVMgU1FMIFNlcnZlciBwcmlvciB0byAyMDEyIFNQMSBDaW1pbGF0aXZlIFVwZGF0ZSAyIG9ubHkgdGhlCiAgICBmb2xsb3dpbmcgZmVhdHVyZXMgYXJlIHN1cHBvcnRlZDogU1FMRW5naW5lLCBSZXBsaWNhdGlvbiwgRnVsbFRleHQsIFJTCgogICAgQWxsIGRvY3VtZW50ZWQgb3B0aW9uIGFyZSBzdXBwb3J0ZWQuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yIGRldGFpbHM6CiAgICBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAogICAgIz4KICAgICRPcHRpb25QYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VyCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIlByZXBhcmVJbWFnZSIpLCAkdHJ1ZSwgIlByZXBhcmVJbWFnZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSUFDQ0VQVFNRTFNFUlZFUkxJQ0VOU0VURVJNUyIgLVN3aXRjaCksICR0cnVlKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlU291cmNlIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJDT05GSUdVUkFUSU9ORklMRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTCIsIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJEUSIsIkFTIiwiUlMiLCJEUUMiLCJJUyIsIk1EUyIsIlRvb2xzIiwiQkMiLCJCT0wiLCJCSURTIiwiQ29ubiIsIlNTTVMiLCJBRFZfU1NNUyIsIlNOQUNfU0RLIiwiU0RLIiwiTG9jYWxEQiIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJISURFQ09OU09MRSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk1TU1FMU0VSVkVSIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRUyIgLVN3aXRjaCkpCgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckNvbXBsZXRlSW1hZ2UgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBhbiBvcHRpb24gcGFyc2VyIGZvciBNUyBTUUwgU2VydmVyIDIwMTIgc2V0dXAgIkNvbXBsZXRlSW1hZ2UiIGFjdGlvbi4KCiAgICAuREVTQ1JJUFRJT04KICAgIFVzZSB0aGlzIGNtZGxldCB0byBjcmVhdGUgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJDb21wbGV0ZUltYWdlIiBhY3Rpb24uCgogICAgTm90ZSB0aGF0IElOU1RBTkNFSUQgcGFyYW1ldGVyIHZhbHVlIE1VU1QgYmUgdGhlIHNhbWUgYXMgc3BlY2lmaWVkIG9uICJQcmVwYXJlSW1hZ2UiIHBoYXNlLgoKICAgIEFsbCBkb2N1bWVudGVkIG9wdGlvbiBhcmUgc3VwcG9ydGVkLiBTZWUgdGhlIGZvbGxvd2luZyBsaW5rIGZvciBkZXRhaWxzOgogICAgaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTQ0MjU5LmFzcHgKICAgICM+CiAgICAkT3B0aW9uUGFyc2VyID0gTmV3LU9wdGlvblBhcnNlcgoKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBQ1RJT04iIC1TdHJpbmcgLUNvbnN0cmFpbnRzICJDb21wbGV0ZUltYWdlIiksICR0cnVlLCAiQ29tcGxldGVJbWFnZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSUFDQ0VQVFNRTFNFUlZFUkxJQ0VOU0VURVJNUyIgLVN3aXRjaCksICR0cnVlKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVSUk9SUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VJRCIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlBJRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTVJFUE9SVElORyIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkhJREVDT05TT0xFIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNBQ0NPVU5UIiAtU3RyaW5nKSwgJHRydWUsICJOVCBBVVRIT1JJVFlcTmV0d29yayBTZXJ2aWNlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUdUU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJCUk9XU0VSU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFTkFCTEVSQU5VIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJTlNUQUxMU1FMREFUQURJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU0FQV0QiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNFQ1VSSVRZTU9ERSIgLVN0cmluZyAtQ29uc3RyYWlucnMgKCJTUUwiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMQkFDS1VQRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxDT0xMQVRJT04iIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6VVNFUkRPTUFJTlwkRU5WOlVTRVJOQU1FIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxURU1QREJESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFRFTVBEQkxPR0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVVNFUkRCRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxVU0VSREJMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZJTEVTVFJFQU1MRVZFTCIgLVN0cmluZyAtQ29uc3RyYWludHMgKCIwIiwgIjEiLCAiMiIsICIzIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZJTEVTVFJFQU1TSEFSRU5BTUUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZUU1ZDQUNDT1VOVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRlRTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiTlBFTkFCTEVEIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVENQRU5BQkxFRCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTSU5TVEFMTE1PREUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiU2hhcmVQb2ludEZpbGVzT25seU1vZGUiLCAiRGVmYXVsdE5hdGl2ZU1vZGUiLCAiRmlsZXNPbmx5TW9kZSIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDU3RhcnR1cFR5cGUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKCiAgICByZXR1cm4gJE9wdGlvblBhcnNlcgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyQ29tcGxldGVJbWFnZVNQMVUyIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJDb21wbGV0ZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiQ29tcGxldGVJbWFnZSIgYWN0aW9uLgoKICAgIFRoaXMgY21kbGV0IHNob3VsZCBiZSB1c2VkIG9ubHkgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBTUDEgQ2ltaWxhdGl2ZSBVcGRhdGUgMiBvciBsYXRlci4KCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUNUSU9OIiAtU3RyaW5nIC1Db25zdHJhaW50cyAiQ29tcGxldGVJbWFnZSIpLCAkdHJ1ZSwgIkNvbXBsZXRlSW1hZ2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklBQ0NFUFRTUUxTRVJWRVJMSUNFTlNFVEVSTVMiIC1Td2l0Y2gpLCAkdHJ1ZSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFTlUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkNPTkZJR1VSQVRJT05GSUxFIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFUlJPUlJFUE9SVElORyIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklORElDQVRFUFJPR1JFU1MiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUElEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FNUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkJST1dTRVJTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOQUJMRVJBTlUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTExTUUxEQVRBRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTQVBXRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU0VDVVJJVFlNT0RFIiAtU3RyaW5nIC1Db25zdHJhaW5ycyAoIlNRTCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxCQUNLVVBESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTENPTExBVElPTiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1NUQVJUVVBUWVBFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXCRFTlY6VVNFUk5BTUUiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFRFTVBEQkRJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVEVNUERCTE9HRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxVU0VSREJESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFVTRVJEQkxPR0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRklMRVNUUkVBTUxFVkVMIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIjAiLCAiMSIsICIyIiwgIjMiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRklMRVNUUkVBTVNIQVJFTkFNRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRlRTVkNBQ0NPVU5UIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJOUEVOQUJMRUQiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJUQ1BFTkFCTEVEIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNJTlNUQUxMTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJTaGFyZVBvaW50RmlsZXNPbmx5TW9kZSIsICJEZWZhdWx0TmF0aXZlTW9kZSIsICJGaWxlc09ubHlNb2RlIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNTdGFydHVwVHlwZSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJVcGdyYWRlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckVkaXRpb25VcGdyYWRlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclJlcGFpciB7CiAgICAjIFRvRG86IEltcGxlbWVudAogICAgdGhyb3cgIk5vdCB5ZXQgaW1wbGVtZW50ZWQiCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJSZWJ1aWxkZGF0YWJhc2UgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyVW5pbnN0YWxsIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJJTlNUQUxMIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiSU5TVEFMTCIgYWN0aW9uLgogICAgQWxsIGRvY3VtZW50ZWQgb3B0aW9uIGFyZSBzdXBwb3J0ZWQuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yIGRldGFpbHM6CiAgICBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAogICAgIz4KICAgICRPcHRpb25QYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VyCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIlVOSU5TVEFMTCIpLCAkdHJ1ZSwgIlVOSU5TVEFMTCIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZFQVRVUkVTIiAtTGlzdCAtQ29uc3RyYWludHMgKCJTUUwiLCJTUUxFbmdpbmUiLCJSZXBsaWNhdGlvbiIsIkZ1bGxUZXh0IiwiRFEiLCJBUyIsIlJTIiwiRFFDIiwiSVMiLCJNRFMiLCJUb29scyIsIkJDIiwiQk9MIiwiQklEUyIsIkNvbm4iLCJTU01TIiwiQURWX1NTTVMiLCJEUkVQTEFZX0NUTFIiLCJEUkVQTEFZX0NMVCIsIlNOQUNfU0RLIiwiU0RLIiwiTG9jYWxEQiIpKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VOQU1FIiAtU3RyaW5nKSwgJHRydWUsICJNU1NRTFNFUlZFUiIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJJbnN0YWxsRmFpbG92ZXJDbHVzdGVyIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclByZXBhcmVGYWlsb3ZlckNsdXN0ZXIgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyQ29tcGxldGVGYWlsb3ZlckNsdXN0ZXIgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyVXBncmFkZSB7CiAgICAjIFRvRG86IEltcGxlbWVudAogICAgdGhyb3cgIk5vdCB5ZXQgaW1wbGVtZW50ZWQiCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJBZGROb2RlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclJlbW92ZU5vZGUgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9Cg==", - "SW1wb3J0LU1vZHVsZSBOZXRTZWN1cml0eQoKZnVuY3Rpb24gVGVzdC1LZXkoW3N0cmluZ10kcGF0aCwgW3N0cmluZ10ka2V5KSB7CiAgICBpZighKFRlc3QtUGF0aCAkcGF0aCkpIHsgcmV0dXJuICRmYWxzZSB9CiAgICBpZiAoKEdldC1JdGVtUHJvcGVydHkgJHBhdGgpLiRrZXkgLWVxICRudWxsKSB7IHJldHVybiAkZmFsc2UgfQogICAgcmV0dXJuICR0cnVlCn0KCmZ1bmN0aW9uIFJlc29sdmUtU1FMU2VydmVyUHJlcmVxdWlzaXRlcyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBNUyBTUUwgU2VydmVyIHByZXJlcXVpc2l0ZXMgKC5OZXQgRnJhbWV3b3JrIDMuNSkKCiAgICAuREVTQ1JJUFRJT04KICAgIEluc3RhbGxzIE1TIFNRTCBTZXJ2ZXIgcHJlcmVxdWlzaXRlcyAoLk5ldCBGcmFtZXdvcmsgMy41KQoKICAgICM+CiAgICBpZiAoLW5vdCAoVGVzdC1LZXkgIkhLTE06XFNvZnR3YXJlXE1pY3Jvc29mdFxORVQgRnJhbWV3b3JrIFNldHVwXE5EUFx2My41IiAiSW5zdGFsbCIpKSB7CiAgICAgICAgSW1wb3J0LU1vZHVsZSBTZXJ2ZXJNYW5hZ2VyCiAgICAgICAgV3JpdGUtSG9zdCAiLk5ldCBGcmFtZXdvcmsgMy41IG5vdCBmb3VuZC4gSW5zdGFsbGluZyBpdCB1c2luZyBTZXJ2ZXIgTWFuYWdlci4uLiIKICAgICAgICAkRmVhdHVyZSA9IEdldC1XaW5kb3dzRmVhdHVyZSBORVQtRnJhbWV3b3JrCiAgICAgICAgaWYgKCRGZWF0dXJlIC1lcSAkbnVsbCkgewogICAgICAgICAgICAjIFdlIGFyZSBwcm9iYWJseSBvbiBXaW5kb3dzIFNlcnZlciAyMDEyCiAgICAgICAgICAgICRGZWF0dXJlID0gR2V0LVdpbmRvd3NGZWF0dXJlIE5FVC1GcmFtZXdvcmstQ29yZQogICAgICAgIH0KICAgICAgICBpZiAoLW5vdCAkRmVhdHVyZSkgewogICAgICAgICAgICB0aHJvdyAiLk5ldCBmcmFtZXdvcmsgMy41IGZlYXR1cmUgd2FzIG5vdCBmb3VuZC4iCiAgICAgICAgfQogICAgICAgIGlmICgtbm90ICRGZWF0dXJlLkRpc3BsYXlOYW1lIC1tYXRjaCAiMy41IikgewogICAgICAgICAgICBMb2ctV2FybmluZyAiLk5ldCBmcmFtZXdvcmsgMy41IGlzIHJlcXVpcmVkLCBidXQgJCgkRmVhdHVyZS5EaXNwbGF5TmFtZSkgaXMgYXZhaWxhYmxlIGFzIFdpbmRvd3MgZmVhdHVyZS4gUHJvY2VlZGluZyB3aXRoIGluc3RhbGxhdGlvbiIKICAgICAgICB9CiAgICAgICAgW3ZvaWRdKEFkZC1XaW5kb3dzRmVhdHVyZSAkRmVhdHVyZSkKICAgIH0KfQoKZnVuY3Rpb24gTmV3LVNRTFNlcnZlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZS4gUmV0dXJucyAkdHJ1ZSBpZiBhIHJlYm9vdCBpcyByZXF1aXJlZCBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLCAKICAgICRmYWxzZSBpZiBhIHJlYm9vdCBpcyBub3QgcmVxdWlyZWQgYW5kIHRocm93cyBhbiBleGNlcHRpb24gaW4gY2FzZSBpZiBpbnN0YWxsYXRpb24gZmFpbHMuCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSBpbiB1bmF0dGVuZGVkIG1vZGUuCgogICAgLlBBUkFNRVRFUiBTZXR1cFJvb3QKICAgIE1TIFNRTCBTZXJ2ZXIgaW5zdGFsbGF0aW9uIGZpbGVzIHJvb3QgZGlyZWN0b3J5LiBOb3JtYWxseSBpdCBpcyBqdXN0IERWRCBkcml2ZSBuYW1lLgoKICAgIC5QQVJBTUVURVIgRXh0cmFGZWF0dXJlcwogICAgTGlzdCBvZiBmZWF0dXJlcyB0byBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gZGVmYXVsdCAiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCksCiAgICAgICAgW0hhc2h0YWJsZV0kRXh0cmFPcHRpb25zID0gQHt9CiAgICApCgogICAgJFNldHVwRGlyID0gR2V0LUl0ZW0gJFNldHVwUm9vdAogICAgJFNldHVwRXhlID0gJFNldHVwRGlyLkdldEZpbGVzKCJzZXR1cC5leGUiKVswXQoKICAgIFJlc29sdmUtU1FMU2VydmVyUHJlcmVxdWlzaXRlcwoKICAgICRwYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VySW5zdGFsbAogICAgJEV4aXRDb2RlID0gJHBhcnNlci5FeGVjdXRlQmluYXJ5KCRTZXR1cEV4ZS5GdWxsTmFtZSwgQHsiUSIgPSAkbnVsbDsgIkZFQVRVUkVTIiA9IEAoIlNRTEVuZ2luZSIsICJDb25uIiwgIlNTTVMiLCAiQURWX1NTTVMiKSArICRFeHRyYUZlYXR1cmVzfSArICRFeHRyYU9wdGlvbnMpCgogICAgaWYgKCRFeGl0Q29kZSAtZXEgMzAxMCkgewogICAgICAgIHJldHVybiAkdHJ1ZQogICAgfQoKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICB0aHJvdyAiSW5zdGFsbGF0aW9uIGV4ZWN1dGFibGUgZXhpdGVkIHdpdGggY29kZSAkKCJ7MDpYOH0iIC1mICRFeGl0Q29kZSkgKERlY2ltYWw6ICRFeGl0Q29kZSkiCiAgICB9CgogICAgcmV0dXJuICRmYWxzZQp9CgpmdW5jdGlvbiBOZXctU1FMU2VydmVyRm9yQU9BRyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSB3aXRoIGFsbCBuZWVkZWQgZmVhdHVyZXMgdG8gc2V0IHVwIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cC4KICAgIFJldHVybnMgJHRydWUgaWYgYSByZWJvb3QgaXMgcmVxdWlyZWQgYWZ0ZXIgdGhlIGluc3RhbGxhdGlvbiwgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCAKICAgIGFuZCB0aHJvd3MgYW4gZXhjZXB0aW9uIGluIGNhc2UgaWYgaW5zdGFsbGF0aW9uIGZhaWxzLgoKICAgIC5ERVNDUklQVElPTgogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW5zdGFuY2UgaW4gdW5hdHRlbmRlZCBtb2RlLiBBbGwgZmVhdHVyZXMgZm9yIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cHMgYXJlCiAgICBpbnN0YWxsZWQuCgogICAgQWxsIGF2YWlsYWJpbGl0eSBncm91cCBtZW1iZXJzIG11c3QgYmUgaW5zdGFsbGVkIHdpdGggdGhlIHNhbWUgU1FMU3ZjVXNyRG9tYW4sIFNRTFN2Y1Vzck5hbWUgYW5kIFNRTFN2Y1VzclBhc3N3b3JkIHBhcmFtZXRlcnMuCiAgICBVc2VyIG11c3QgYmUgYSBkb21haW4gdXNlciBzaW5jZSBpdCB3aWxsIGJlIHVzZWQgZm9yIG5vZGVzIGludGVyY29ubmVjdGlvbi4KCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBTUUxTdmNVc3JEb21haW4KICAgIE1TIFNRTCBTZXJ2ZXIgdXNlciBhY2NvdW50IGRvbWFpbiBuYW1lLgoKICAgIC5QQVJBTUVURVIgU1FMU3ZjVXNyTmFtZQogICAgTVMgU1FMIFNlcnZlciB1c2VyIGFjY291bnQgbmFtZS4KCiAgICAuUEFSQU1FVEVSIFNRTFN2Y1VzclBhc3N3b3JkCiAgICBNUyBTUUwgU2VydmVyIHVzZXIgYWNjb3VudCBwYXNzd29yZC4KCiAgICAuUEFSQU1FVEVSIEV4dHJhRmVhdHVyZXMKICAgIExpc3Qgb2YgZmVhdHVyZXMgdG8gYmUgcmVtb3ZlZCBiZXNpZGVzICJTUUxFbmdpbmUiLCAiQ29ubiIsICJTU01TIiwgIkFEVl9TU01TIiwgIkRSRVBMQVlfQ1RMUiIsICJEUkVQTEFZX0NMVCIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTUUxTdmNVc3JEb21haW4sCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kU1FMU3ZjVXNyTmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTUUxTdmNVc3JQYXNzd29yZCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCksCiAgICAgICAgW0hhc2h0YWJsZV0kRXh0cmFPcHRpb25zID0gQHt9CiAgICApCgogICAgJFNldHVwRGlyID0gR2V0LUl0ZW0gJFNldHVwUm9vdAogICAgJFNldHVwRXhlID0gJFNldHVwRGlyLkdldEZpbGVzKCJzZXR1cC5leGUiKVswXQoKICAgICRTUUxVc2VyID0gIiRTUUxTdmNVc3JEb21haW5cJFNRTFN2Y1Vzck5hbWUiCiAgICAkZG9tYWluID0gTmV3LU9iamVjdCBTeXN0ZW0uRGlyZWN0b3J5U2VydmljZXMuRGlyZWN0b3J5RW50cnkoIkxEQVA6Ly8kU1FMU3ZjVXNyRG9tYWluIiwgJFNRTFN2Y1Vzck5hbWUsICRTUUxTdmNVc3JQYXNzd29yZCkKCiAgICBpZiAoJGRvbWFpbi5uYW1lIC1lcSAkbnVsbCkgewogICAgICAgIHRocm93ICJDcmVkZW50aWFscyB2YWxpZGF0aW9uIGZhaWxlZCBmb3IgdXNlciAkU1FMVXNlci4gQ2hlY2sgZG9tYWluLCBsb2dpbiBuYW1lIGFuZCBwYXNzd29yZC4iCiAgICB9CgogICAgUmVzb2x2ZS1TUUxTZXJ2ZXJQcmVyZXF1aXNpdGVzCgogICAgJHBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXJJbnN0YWxsCiAgICAkRXhpdENvZGUgPSAkcGFyc2VyLkV4ZWN1dGVCaW5hcnkoJFNldHVwRXhlLkZ1bGxOYW1lLCBAeyJRIiA9ICRudWxsOyAiRkVBVFVSRVMiID0gQCgiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIsICJEUkVQTEFZX0NUTFIiLCAiRFJFUExBWV9DTFQiKSArICRFeHRyYUZlYXR1cmVzOwogICAgICAgICJBR1RTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiQUdUU1ZDUEFTU1dPUkQiID0gJFNRTFN2Y1VzclBhc3N3b3JkOyAiQVNTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiQVNTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7ICJBU1NZU0FETUlOQUNDT1VOVFMiID0gJFNRTFVTZXI7CiAgICAgICAgIlNRTFNWQ0FDQ09VTlQiID0gJFNRTFVzZXI7ICJTUUxTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7ICJTUUxTWVNBRE1JTkFDQ09VTlRTIiA9ICRTUUxVc2VyOyAiSVNTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiSVNTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7IAogICAgICAgICJSU1NWQ0FDQ09VTlQiID0gJFNRTFVzZXI7ICJSU1NWQ1BBU1NXT1JEIiA9ICRTUUxTdmNVc3JQYXNzd29yZH0gKyAkRXh0cmFPcHRpb25zKQoKICAgIGlmICgkRXhpdENvZGUgLWVxIDMwMTApIHsKICAgICAgICByZXR1cm4gJHRydWUKICAgIH0KCiAgICBpZiAoJEV4aXRDb2RlIC1uZSAwKSB7CiAgICAgICAgdGhyb3cgIkluc3RhbGxhdGlvbiBleGVjdXRhYmxlIGV4aXRlZCB3aXRoIGNvZGUgJCgiezA6WDh9IiAtZiAkRXhpdENvZGUpIChEZWNpbWFsOiAkRXhpdENvZGUpIgogICAgfQoKICAgIHJldHVybiAkZmFsc2UKfQoKZnVuY3Rpb24gUmVtb3ZlLVNRTFNlcnZlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBVbmluc3RhbGxzIE1TIFNRTCBTZXJ2ZXIgaW5zdGFuY2UgaW5zdGFsbGVkIHdpdGggTmV3LVNRTFNlcnZlciBjbWRsZXQKCiAgICAuREVTQ1JJUFRJT04KICAgIFVuaW5zdGFsbHMgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSBpbnN0YWxsZWQgd2l0aCBOZXctU1FMU2VydmVyIGNtZGxldCBpbiB1bmF0dGVuZGVkIG1vZGUKCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBFeHRyYUZlYXR1cmVzCiAgICBMaXN0IG9mIGZlYXR1cmVzIHRvIGJlIHJlbW92ZWQgYmVzaWRlcyAiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCkKICAgICkKCiAgICAkU2V0dXBEaXIgPSBHZXQtSXRlbSAkU2V0dXBSb290CiAgICAkU2V0dXBFeGUgPSAkU2V0dXBEaXIuR2V0RmlsZXMoInNldHVwLmV4ZSIpWzBdCgogICAgJHBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXJVbmluc3RhbGwKICAgICRFeGl0Q29kZSA9ICRwYXJzZXIuRXhlY3V0ZUJpbmFyeSgkU2V0dXBFeGUuRnVsbE5hbWUsIEB7IlEiID0gJG51bGw7ICJGRUFUVVJFUyIgPSBAKCJTUUxFbmdpbmUiLCAiQ29ubiIsICJTU01TIiwgIkFEVl9TU01TIikgKyAkRXh0cmFGZWF0dXJlc30pCgogICAgaWYgKCRFeGl0Q29kZSAtbmUgMCkgewogICAgICAgIHRocm93ICJJbnN0YWxsYXRpb24gZXhlY3V0YWJsZSBleGl0ZWQgd2l0aCBjb2RlICQoInswOlg4fSIgLWYgJEV4aXRDb2RlKSIKICAgIH0KfQoKZnVuY3Rpb24gSW5zdGFsbC1TUUxTZXJ2ZXJGb3JTeXNQcmVwIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluIHN5c3ByZXAgbW9kZS4KCiAgICAuREVTQ1JJUFRJT04KICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluIHN5c3ByZXAgbW9kZS4gUmV0dXJucyAkdHJ1ZSBpZiBhIHJlYm9vdCBpcyByZXF1aXJlZCBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLCAKICAgICRmYWxzZSBpZiBhIHJlYm9vdCBpcyBub3QgcmVxdWlyZWQgYW5kIHRocm93cyBhbiBleGNlcHRpb24gaW4gY2FzZSBpZiBpbnN0YWxsYXRpb24gZmFpbHMuCgogICAgU2V0dXAgbXVzdCBiZSBjb21wbGV0ZWQgYWZ0ZXIgYm9vdGluZyByZWFybWVkIG1hY2hpbmUgYnkgdXNpbmcgQ29tcGxldGUtU1FMU2VydmVyIGNtZGxldAoKICAgIC5QQVJBTUVURVIgU2V0dXBSb290CiAgICBNUyBTUUwgU2VydmVyIGluc3RhbGxhdGlvbiBmaWxlcyByb290IGRpcmVjdG9yeS4gTm9ybWFsbHkgaXQgaXMganVzdCBEVkQgZHJpdmUgbmFtZS4KCiAgICAuUEFSQU1FVEVSIEV4dHJhRmVhdHVyZXMKICAgIExpc3Qgb2YgZmVhdHVyZXMgdG8gYmUgaW5zdGFsbGVkIGluIGFkZGl0aW9uIHRvIGRlZmF1bHQgIlNRTEVuZ2luZSIuIE5vdGUgdGhhdCBwcmlvciB0bwogICAgU1FMIFNlcnZlciB2ZXJzaW9uIDIwMTIgU2VydmljZSBQYWNrIDEgQ3VtdWxhdGl2ZSBVcGRhdGUgMiAoSmFudWFyeSAyMDEzKSBvbmx5ICJSZXBsaWNhdGlvbiIsIAogICAgIkZ1bGxUZXh0IiBhbmQgIlJTIiBtYXkgYmUgaW5zdGFsbGVkIGluIGFkZGl0aW9uIHRvICJTUUxFbmdpbmUiLiBTZWUgdGhlIGZvbGxvd2luZyBsaW5rIGZvcgogICAgZGV0aWFsczogaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTQ0MjU5LmFzcHgKCiAgICAjPgp9CgpmdW5jdGlvbiBJbnN0YWxsLVNRTFNlcnZlckZvclN5c1ByZXAgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW4gc3lzcHJlcCBtb2RlLgoKICAgIC5ERVNDUklQVElPTgogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW4gc3lzcHJlcCBtb2RlLiBSZXR1cm5zICR0cnVlIGlmIGEgcmVib290IGlzIHJlcXVpcmVkIGFmdGVyIHRoZSBpbnN0YWxsYXRpb24sIAogICAgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCBhbmQgdGhyb3dzIGFuIGV4Y2VwdGlvbiBpbiBjYXNlIGlmIGluc3RhbGxhdGlvbiBmYWlscy4KCiAgICBTZXR1cCBtdXN0IGJlIGNvbXBsZXRlZCBhZnRlciBib290aW5nIHJlYXJtZWQgbWFjaGluZSBieSB1c2luZyBDb21wbGV0ZS1TUUxTZXJ2ZXIgY21kbGV0CgogICAgLlBBUkFNRVRFUiBTZXR1cFJvb3QKICAgIE1TIFNRTCBTZXJ2ZXIgaW5zdGFsbGF0aW9uIGZpbGVzIHJvb3QgZGlyZWN0b3J5LiBOb3JtYWxseSBpdCBpcyBqdXN0IERWRCBkcml2ZSBuYW1lLgoKICAgIC5QQVJBTUVURVIgRXh0cmFGZWF0dXJlcwogICAgTGlzdCBvZiBmZWF0dXJlcyB0byBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gZGVmYXVsdCAiU1FMRW5naW5lIi4gTm90ZSB0aGF0IHByaW9yIHRvCiAgICBTUUwgU2VydmVyIHZlcnNpb24gMjAxMiBTZXJ2aWNlIFBhY2sgMSBDdW11bGF0aXZlIFVwZGF0ZSAyIChKYW51YXJ5IDIwMTMpIG9ubHkgIlJlcGxpY2F0aW9uIiwgCiAgICAiRnVsbFRleHQiIGFuZCAiUlMiIG1heSBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gIlNRTEVuZ2luZSIuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yCiAgICBkZXRpYWxzOiBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAoKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kU2V0dXBSb290LAogICAgICAgIFthcnJheV0kRXh0cmFGZWF0dXJlcyA9IEAoKQogICAgKQoKICAgICRTZXR1cERpciA9IEdldC1JdGVtICRTZXR1cFJvb3QKICAgICRTZXR1cEV4ZSA9ICRTZXR1cERpci5HZXRGaWxlcygic2V0dXAuZXhlIilbMF0KCiAgICBSZXNvbHZlLVNRTFNlcnZlclByZXJlcXVpc2l0ZXMKCiAgICAkcGFyc2VyID0gTmV3LU9wdGlvblBhcnNlclByZXBhcmVJbWFnZQogICAgJEV4aXRDb2RlID0gJHBhcnNlci5FeGVjdXRlQmluYXJ5KCRTZXR1cEV4ZS5GdWxsTmFtZSwgQHsiUVMiID0gJG51bGw7ICJGRUFUVVJFUyIgPSBAKCJTUUxFbmdpbmUiKSArICRFeHRyYUZlYXR1cmVzIH0pCgogICAgaWYgKCRFeGl0Q29kZSAtZXEgMzAxMCkgewogICAgICAgIHJldHVybiAkdHJ1ZQogICAgfQoKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICB0aHJvdyAiSW5zdGFsbGF0aW9uIGV4ZWN1dGFibGUgZXhpdGVkIHdpdGggY29kZSAkKCJ7MDpYOH0iIC1mICRFeGl0Q29kZSkgKERlY2ltYWw6ICRFeGl0Q29kZSkiCiAgICB9CgogICAgcmV0dXJuICRmYWxzZQp9CgpmdW5jdGlvbiBDb21wbGV0ZS1TUUxTZXJ2ZXJBZnRlclN5c1ByZXAgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ29tcGxldGVzIHByZXZpb3VzbHkgcHJlcGFyZWQgd2l0aCAiSW5zdGFsbC1TUUxTZXJ2ZXJGb3JTeXNQcmVwIiBNUyBTUUwgU2VydmVyIGFmdGVyIHRoZSBzeXN0ZW0gd2FzIHJlYXJtZWQuCgogICAgLkRFU0NSSVBUSU9OCiAgICBDb21wbGV0ZXMgcHJldmlvdXNseSBwcmVwYXJlZCB3aXRoICJJbnN0YWxsLVNRTFNlcnZlckZvclN5c1ByZXAiIE1TIFNRTCBTZXJ2ZXIgYWZ0ZXIgdGhlIHN5c3RlbSB3YXMgcmVhcm1lZC4KICAgIFJldHVybnMgJHRydWUgaWYgYSByZWJvb3QgaXMgcmVxdWlyZWQgYWZ0ZXIgdGhlIGluc3RhbGxhdGlvbiwgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCBhbmQgdGhyb3dzIAogICAgYW4gZXhjZXB0aW9uIGluIGNhc2UgaWYgaW5zdGFsbGF0aW9uIGZhaWxzLgoKICAgIFNldHVwIG11c3QgYmUgY29tcGxldGVkIGFmdGVyIGJvb3RpbmcgcmVhcm1lZCBtYWNoaW5lIGJ5IHVzaW5nIENvbXBsZXRlLVNRTFNlcnZlciBjbWRsZXQKCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdAogICAgKQoKICAgICRTZXR1cERpciA9IEdldC1JdGVtICRTZXR1cFJvb3QKICAgICRTZXR1cEV4ZSA9ICRTZXR1cERpci5HZXRGaWxlcygic2V0dXAuZXhlIilbMF0KCiAgICAkcGFyc2VyID0gTmV3LU9wdGlvblBhcnNlckNvbXBsZXRlSW1hZ2UKICAgICRFeGl0Q29kZSA9ICRwYXJzZXIuRXhlY3V0ZUJpbmFyeSgkU2V0dXBFeGUuRnVsbE5hbWUsIEB7IlFTIiA9ICRudWxsfSkKCiAgICBpZiAoJEV4aXRDb2RlIC1lcSAzMDEwKSB7CiAgICAgICAgcmV0dXJuICR0cnVlCiAgICB9CgogICAgaWYgKCRFeGl0Q29kZSAtbmUgMCkgewogICAgICAgIHRocm93ICJJbnN0YWxsYXRpb24gZXhlY3V0YWJsZSBleGl0ZWQgd2l0aCBjb2RlICQoInswOlg4fSIgLWYgJEV4aXRDb2RlKSAoRGVjaW1hbDogJEV4aXRDb2RlKSIKICAgIH0KCiAgICByZXR1cm4gJGZhbHNlCn0KCmZ1bmN0aW9uIENvbnZlcnRUby1TUUxTdHJpbmcgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ29udmVydHMgYXJndW1lbnQgdG8gYSB2YWxpZCBTUUwgc3RyaW5nIGluIHF1b3RlcwoKICAgIC5ERVNDUklQVElPTgogICAgQ29udmVydHMgYXJndW1lbnQgdG8gYSB2YWxpZCBTUUwgc3RyaW5nIGluIHF1b3Rlcy4gVGhlIHN0cmluZyBtYXkgY29udGFpbiBhbnkgY2hhcmFjdGVycy4KICAgIFNlZSBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNzk4OTkuYXNweAoKICAgIC5QQVJBTUVURVIgUwogICAgU3RyaW5nIHRvIGNvbnZlcnQKICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlLCBWYWx1ZUZyb21QaXBlbGluZSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTCiAgICApCiAgICAKICAgIHJldHVybiAiJyQoJFMgLXJlcGxhY2UgIiciLCAiJyciKSciCn0KCmZ1bmN0aW9uIENvbnZlcnRUby1TUUxOYW1lIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbnZlcnRzIGFyZ3VtZW50IHRvIGEgdmFsaWQgU1FMIG5hbWUgaW4gYnJhY2tldHMKCiAgICAuREVTQ1JJUFRJT04KICAgIENvbnZlcnRzIGFyZ3VtZW50IHRvIGEgdmFsaWQgU1FMIG5hbWUgaW4gYnJhY2tldHMuIFRoZSBzdHJpbmcgbWF5IGNvbnRhaW4gYW55IGNoYXJhY3RlcnMuCiAgICBTZWUgaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTc1ODc0LmFzcHgKCiAgICAuUEFSQU1FVEVSIFMKICAgIFN0cmluZyB0byBjb252ZXJ0CiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSwgVmFsdWVGcm9tUGlwZWxpbmUgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kUwogICAgKQogICAgcmV0dXJuICJbJCgkUyAtcmVwbGFjZSAiXSIsICJdXSIpXSIKfQoKZnVuY3Rpb24gSW52b2tlLVNRTFRleHQgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgSW52b2tlcyBTUUwgdGV4dAoKICAgIC5ERVNDUklQVElPTgogICAgSW52b2tlcyBTUUwgdGV4dC4gUmV0dXJucyByYXcgU1FMIHNlcnZlciBvdXRwdXQuCgogICAgLlBBUkFNRVRFUiBTUUwKICAgIFNRTCBUZXh0CgogICAgLlBBUkFNRVRFUiBVc2VyCiAgICBTUUwgU2VydmVyIHVzZXIgbmFtZQoKICAgIC5QQVJBTUVURVIgUGFzc3dvcmQKICAgIFNRTCBTZXJ2ZXIgdXNlciBwYXNzd29yZAogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNRTCwKICAgICAgICBbc3RyaW5nXSRVc2VyID0gJG51bGwsCiAgICAgICAgW3N0cmluZ10kUGFzc3dvcmQgPSAkbnVsbAogICAgKQoKICAgICNXcml0ZS1XYXJuaW5nICIkU1FMYG4iCiAgICAjcmV0dXJuCgogICAgJEJpbmFyeSA9IEdldC1Db21tYW5kICJzcWxjbWQuZXhlIgoKICAgICR0ZW1wRmlsZSA9IFtJTy5QYXRoXTo6R2V0VGVtcEZpbGVOYW1lKCkKICAgICR0ZW1wRmlsZSA9IEdldC1JdGVtICR0ZW1wRmlsZQogICAgU2V0LUNvbnRlbnQgLVBhdGggJHRlbXBGaWxlIC1WYWx1ZSAkU1FMCgogICAgJENvbW1hbmRMaW5lID0gQCgnLWgnLCAnLTEnLCAnLWInLCAnLWknLCAiYCIkKCR0ZW1wRmlsZS5GdWxsTmFtZSlgIiIpCiAgICBpZiAoKCRVc2VyIC1uZSAkbnVsbCkgLWFuZCAoJFVzZXIgLW5lICcnKSkgewogICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICctVScKICAgICAgICAkQ29tbWFuZExpbmUgPSAkQ29tbWFuZExpbmUgKyAkVXNlcgogICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICctUCcKICAgICAgICAkQ29tbWFuZExpbmUgPSAkQ29tbWFuZExpbmUgKyAkUGFzc3dvcmQKICAgIH0KCiAgICBXcml0ZS1EZWJ1ZyAiRXhlY3V0aW5nOiBgbiRTUUxgbiIKICAgIFtzdHJpbmddJG91dHB1dCA9ICYkQmluYXJ5ICRDb21tYW5kTGluZQoKICAgICRFeGl0Q29kZSA9ICRMYXN0RXhpdENvZGUKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICBXcml0ZS1XYXJuaW5nICRvdXRwdXQKICAgICAgICB0aHJvdyAiU1FMQ01ELkVYRSByZXR1cm5lZCB3aXRoIGV4aXQgY29kZSAkRXhpdENvZGUgd2hpbGUgcnVubmluZyAkQmluYXJ5ICRDb21tYW5kTGluZSIKICAgIH0KICAgCiAgICBSZW1vdmUtSXRlbSAkdGVtcEZpbGUKCiAgICByZXR1cm4gJG91dHB1dAp9CgpmdW5jdGlvbiBOZXctU1FMVXNlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnZva2VzIFNRTCB0ZXh0CgogICAgLkRFU0NSSVBUSU9OCiAgICBJbnZva2VzIFNRTCB0ZXh0CgogICAgLlBBUkFNRVRFUiBTUUwKICAgIFNRTCBUZXh0CgogICAgLlBBUkFNRVRFUiBVc2VyCiAgICBTUUwgU2VydmVyIHVzZXIgbmFtZQoKICAgIC5QQVJBTUVURVIgUGFzc3dvcmQKICAgIFNRTCBTZXJ2ZXIgdXNlciBwYXNzd29yZAogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNRTCwKICAgICAgICBbc3RyaW5nXSRVc2VyID0gJG51bGwsCiAgICAgICAgW3N0cmluZ10kUGFzc3dvcmQgPSAkbnVsbAogICAgKQp9CgpmdW5jdGlvbiBOZXctUGFzc3dvcmQgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyByYW5kb20gcGFzc3dvcmQgb2YgdGhlIHNwZWNpZmllZCBsZW5ndGgKCiAgICAuREVTQ1JJUFRJT04KICAgIFBhc3N3b3JkIGNvbnRhaW5zIHJhbmRvbSBjaGFyYWN0ZXJzIGEteiwgQS1aLCBudW1iZXJzIGFuZCBzcGVjaWFsIGNoYXJhY3RlcnMuCiAgICBUaGVyZSBpcyBubyBndWFyYW50ZWUgdGhhdCBhbGwgdGhlIHR5cGVzIG9mIHN5bWJvbHMgd2lsbCBiZSBwcmVzZW50IGluIHRoZSBwYXNzd29yZC4KCiAgICAuUEFSQU1FVEVSIExlbmd0aAogICAgRGVzaXJlZCBsZW5ndGggb2YgdGhlIHBhc3N3b3JkLgoKICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbaW50XSRMZW5ndGg9NgogICAgKQoKICAgICRSZXN1bHQgPSAiIgogICAgJGFscGhhID0gImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5IUAjJCVeJiooKSdgImBgXytbXVx7fXw7OiwuLzw+P34iCiAgICB3aGlsZSAoJExlbmd0aCAtZ3QgMCkgewogICAgICAgICR4ID0gR2V0LVJhbmRvbSAkYWxwaGEuTGVuZ3RoCiAgICAgICAgJGMgPSAkYWxwaGFbJHhdCiAgICAgICAgJFJlc3VsdCA9ICIkUmVzdWx0JGMiCiAgICAgICAgJExlbmd0aCA9ICRMZW5ndGggLSAxCiAgICB9CiAgICByZXR1cm4gJFJlc3VsdAp9CgpmdW5jdGlvbiBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50IHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgbWlycm9yaW5nIGVuZHBvaW50LgoKICAgIC5ERVNDUklQVElPTgogICAgTWFzdGVyIGtleSBpcyBjcmVhdGVkIGlmIG5lY2Vzc2FyeS4gSG9zdCBjZXJ0aWZpY2F0ZSBpcyBjcmVhdGVkIHdoZW4gbmVjZXNzYXJ5IGVpdGhlciAobm9ybWFsbHkgb24gZmlyc3QgZW5kcG9pbnQgY3JlYXRpb24pLgoKICAgIEVuZHBvaW50IGFuZCBjZXJ0aWZpY2F0ZSBhcmUgcmVjcmVhdGVkIGluIGNhc2UgaWYgbWFzdGVyIGtleSBkaWQgbm90IGV4aXN0ZWQgKHNob3VsZCBub3Qgbm9ybWFsbHkgaGFwcGVuKS4KCiAgICBFbmRwb2ludCBpcyByZWNyZWF0ZWQgaW4gY2FzZSBpZiBjZXJ0aWZpY2F0ZSBkaWQgbm90IGV4aXN0ZWQgKHNob3VsZCBub3QgaGFwcGVuIHVubGVzcyB0aGUgZW5kcG9pbnQgd2FzIGNyZWF0ZWQgbWFudWFsbHkpLgoKICAgIE1pcnJvcmluZyBlbmRwb2ludCBpcyBjcmVhdGVkIHVubGVzcyBvbmUgYWxyZWFkeSBleGlzdHMuIFRoZSBlbmRwb2ludCBpcyBjcmVhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBuYW1lLiBXaGVuIHRoZSBlbmRwb2ludAogICAgYWxyZWFkeSBleGlzdHMgaXMgaXMgdW5jaGFuZ2VkLgoKICAgIEVuZHBvaW50IHBvcnQgaXMgc2VsZWN0ZWQgYXV0b21hdGljYWxseSBhcyA0MDIyIG9yIGFzIGZpcnN0IGF2YWlsYWJsZSBwb3J0IGFmdGVyIDQwMjIgaW4gY2FzZSBpZiA0MDIyIGlzIGFscmVhZHkgbGlzdGVuaW5nLgogICAgSWYgdGhlcmUgaXMgbm8gZmlyZXdhbGwgcnVsZSB3aXRoIG5hbWUgJ0RhdGFiYXNlTWlycm9yaW5nLVRDUC17cG9ydG51bWJlcn0nLCBhbGxvd2luZyBydWxlIGlzIGNyZWF0ZWQuCgogICAgQ2VydGlmaWNhdGUgaXMgc3RvcmVkIGluIHRoZSBzcGVjaWZpZWQgZmlsZS4KCiAgICBSZXR1cm5zIGVuZHBvaW50IGxpc3RlbmluZyBwb3J0LgoKICAgIC5QQVJBTUVURVIgRW5jcnlwdGlvblBhc3N3b3JkCiAgICBFbmNyeXB0aW9uIHBhc3N3b3JkIHVzZWQgdG8gY3JlYXRlIGNlcnRpZmljYXRlLgoKICAgIC5QQVJBTUVURVIgQ2VydGlmaWNhdGVGaWxlTmFtZQogICAgQ2VydGlmaWNhdGUgdGFyZ2V0IGZpbGUgbmFtZS4gRmlsZSBNVVNUIE5PVCBleGlzdC4KCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRDZXJ0aWZpY2F0ZUZpbGVOYW1lCiAgICApCgogICAgJEVuZHBvaW50TmFtZSA9ICdNaXJyb3JpbmdFbmRwb2ludCcKCiAgICAkRm9sZGVyID0gR2V0LUl0ZW0gJFdvcmtEaXIKCiAgICAkSCA9ICRFbnY6Q09NUFVURVJOQU1FIC1yZXBsYWNlICdbXkEtWmEtejAtOV9dJywgJ18nCgogICAgJFBvcnQgPSBHZXQtTmV4dEZyZWVQb3J0IDQwMjIKCiAgICAkQ3JlYXRlTWFzdGVyS2V5ID0gIlVTRSBtYXN0ZXI7CgogICAgICAgICAgICAgICAgICAgICAgICBJRiBOT1QgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLnN5bW1ldHJpY19rZXlzIHdoZXJlIG5hbWUgPSAnIyNNU19EYXRhYmFzZU1hc3RlcktleSMjJykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBNQVNURVIgS0VZIEVOQ1JZUFRJT04gQlkgUEFTU1dPUkQgPSAkKENvbnZlcnRUby1TUUxTdHJpbmcgJEVuY3J5cHRpb25QYXNzd29yZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWUgPSAnJHtIfV9jZXJ0JykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRFJPUCBDRVJUSUZJQ0FURSAke0h9X2NlcnQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICAgICAgSUYgRVhJU1RTKFNFTEVDVCAqIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBUT1AgMSBgQG5hbWUgPSBuYW1lIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFWEVDICgnRFJPUCBFTkRQT0lOVCBbJyArIGBAbmFtZSArICddJykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIElGIE5PVCBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWUgPSAnJHtIfV9jZXJ0JykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBDRVJUSUZJQ0FURSAke0h9X2NlcnQgV0lUSCBTVUJKRUNUID0gJyR7SH0gZW5kcG9pbnQgY2VydGlmaWNhdGUnOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgSUYgRVhJU1RTKFNFTEVDVCAqIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBUT1AgMSBgQG5hbWUgPSBuYW1lIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFWEVDICgnRFJPUCBFTkRQT0lOVCBbJyArIGBAbmFtZSArICddJykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIEJBQ0tVUCBDRVJUSUZJQ0FURSAke0h9X2NlcnQgVE8gRklMRSA9ICQoQ29udmVydFRvLVNRTFN0cmluZyAiJENlcnRpZmljYXRlRmlsZU5hbWUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBwb3J0IGludAogICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoU0VMRUNUICogRlJPTSBzeXMuZW5kcG9pbnRzIFdIRVJFIHR5cGVfZGVzYz0nREFUQUJBU0VfTUlSUk9SSU5HJykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBgQHBvcnQgPSBwb3J0IEZST00gc3lzLnRjcF9lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnCiAgICAgICAgICAgICAgICAgICAgICAgIEVORCBFTFNFCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUkVBVEUgRU5EUE9JTlQgJChDb252ZXJ0VG8tU1FMTmFtZSAkRW5kcG9pbnROYW1lKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNUQVRFID0gU1RBUlRFRAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFTIFRDUCAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExJU1RFTkVSX1BPUlQgPSAkUG9ydAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIExJU1RFTkVSX0lQID0gQUxMCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGT1IgREFUQUJBU0VfTUlSUk9SSU5HICggCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFVVEhFTlRJQ0FUSU9OID0gQ0VSVElGSUNBVEUgJHtIfV9jZXJ0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgRU5DUllQVElPTiA9IFJFUVVJUkVEIEFMR09SSVRITSBBRVMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBST0xFID0gQUxMCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBgQHBvcnQgPSAkUG9ydAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKCiAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCAncG9ydDooJyArIENPTlZFUlQoVkFSQ0hBUiwgYEBwb3J0KSArICcpJyBhcyBwb3J0CiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICAiCgogICAgJHJhd2RhdGEgPSBJbnZva2UtU1FMVGV4dCAtU1FMICRDcmVhdGVNYXN0ZXJLZXkKICAgIFtpbnRdJFBvcnQgPSAkcmF3ZGF0YSAtcmVwbGFjZSAnLipwb3J0OlwoKFteKV0qKVwpLionLCAnJDEnCgogICAgIyBPcGVuIHBvcnQgaW4gV2luZG93cyBGaXJld2FsbAoKICAgICRQb3J0T3BlbiA9ICRmYWxzZQogICAgJFJ1bGVOYW1lID0gIkRhdGFiYXNlTWlycm9yaW5nLVRDUC0kUG9ydCIKICAgIEdldC1OZXRGaXJld2FsbFJ1bGUgfCBGb3JlYWNoLU9iamVjdCB7CiAgICAgICAgaWYgKCRfLk5hbWUgLWVxICRSdWxlTmFtZSkgewogICAgICAgICAgICAkUG9ydE9wZW4gPSAkdHJ1ZQogICAgICAgIH0KICAgIH0KICAgIGlmICgtbm90ICRQb3J0T3BlbikgewogICAgICAgICREaXNwbGF5TmFtZSA9ICJNUyBTUUwgRGF0YWJhc2UgTWlycm9yaW5nIEVuZHBvaW50IGF0IFRDUCBwb3J0ICRQb3J0IgogICAgICAgIE5ldy1OZXRGaXJld2FsbFJ1bGUgLU5hbWUgJFJ1bGVOYW1lIC1EaXNwbGF5TmFtZSAkRGlzcGxheU5hbWUgLURlc2NyaXB0aW9uICREaXNwbGF5TmFtZSAtUHJvdG9jb2wgVENQIC1Mb2NhbFBvcnQgJFBvcnQgLUVuYWJsZWQgVHJ1ZSAtUHJvZmlsZSBBbnkgLUFjdGlvbiBBbGxvdwogICAgfQogICAgIAogICAgcmV0dXJuICRQb3J0Cn0KCmZ1bmN0aW9uIENvbXBsZXRlLU1pcnJvcmluZ0VuZHBvaW50IHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbXBsZXRlcyBtaXJyb3JpbmcgZW5kcG9pbnQKCiAgICAuREVTQ1JJUFRJT04KICAgIEFsbG93cyBpbmJvdW5kIGNvbm5lY3Rpb25zIGZyb20gcmVtb3RlIGhvc3QKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpciwKICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TG9naW4sCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdFVzZXIsCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdFBhc3N3b3JkCiAgICApCgogICAgJEZvbGRlciA9IEdldC1JdGVtICRSZW1vdGVXb3JrRGlyCiAgICAkUmVtb3RlV29ya0RpciA9ICRGb2xkZXIuRnVsbE5hbWUKCiAgICAkSCA9ICRSZW1vdGVIb3N0TmFtZSAtcmVwbGFjZSAnW15BLVphLXowLTlfXScsICdfJwoKICAgIGlmICgtbm90ICRSZW1vdGVIb3N0TG9naW4pIHsKICAgICAgICAkUmVtb3RlSG9zdExvZ2luID0gIiR7SH1fbG9naW4iCiAgICB9CiAgICBpZiAoLW5vdCAkUmVtb3RlSG9zdFVzZXIpIHsKICAgICAgICAkUmVtb3RlSG9zdFVzZXIgPSAiJHtIfV91c2VyIgogICAgfQogICAgaWYgKC1ub3QgJFJlbW90ZUhvc3RQYXNzd29yZCkgewogICAgICAgICRSZW1vdGVIb3N0UGFzc3dvcmQgPSAiJChOZXctUGFzc3dvcmQgMTApYUEjMyIKICAgIH0KCiAgICAkU1FMID0gICAgICAgICAgICAgIlVTRSBtYXN0ZXI7CgogICAgICAgICAgICAgICAgICAgICAgICBJRiBOT1QgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLnNxbF9sb2dpbnMgd2hlcmUgbmFtZT0kKENvbnZlcnRUby1TUUxTdHJpbmcgJFJlbW90ZUhvc3RMb2dpbikpCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUkVBVEUgTE9HSU4gJChDb252ZXJ0VG8tU1FMTmFtZSAkUmVtb3RlSG9zdExvZ2luKSBXSVRIIFBBU1NXT1JEID0gJChDb252ZXJ0VG8tU1FMU3RyaW5nICRSZW1vdGVIb3N0UGFzc3dvcmQpOwogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIElGIE5PVCBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuc3lzdXNlcnMgd2hlcmUgbmFtZT0kKENvbnZlcnRUby1TUUxTdHJpbmcgJFJlbW90ZUhvc3RVc2VyKSkKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBVU0VSICQoQ29udmVydFRvLVNRTE5hbWUgJFJlbW90ZUhvc3RVc2VyKSBGT1IgTE9HSU4gJChDb252ZXJ0VG8tU1FMTmFtZSAkUmVtb3RlSG9zdExvZ2luKTsKICAgICAgICAgICAgICAgICAgICAgICAgRU5ECiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWU9JyR7SH1fcmVtb3RlX2NlcnQnKQogICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgRFJPUCBDRVJUSUZJQ0FURSAke0h9X3JlbW90ZV9jZXJ0CiAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBHTwoKICAgICAgICAgICAgICAgICAgICAgICAgQ1JFQVRFIENFUlRJRklDQVRFICR7SH1fcmVtb3RlX2NlcnQgQVVUSE9SSVpBVElPTiAkKENvbnZlcnRUby1TUUxOYW1lICRSZW1vdGVIb3N0VXNlcikgRlJPTSBGSUxFID0gJChDb252ZXJ0VG8tU1FMU3RyaW5nICIkUmVtb3RlV29ya0RpclxjZXJ0aWZpY2F0ZS5jZXIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICBTRUxFQ1QgVE9QIDEgYEBuYW1lID0gbmFtZSBGUk9NIHN5cy5lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnCiAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCAnbmFtZTooJyArIGBAbmFtZSArICcpJyBhcyBuYW1lCiAgICAgICAgICAgICAgICAgICAgICAgICIKCiAgICAkcmF3ZGF0YSA9IEludm9rZS1TUUxUZXh0IC1TUUwgJFNRTAogICAgJEVuZHBvaW50TmFtZSA9ICRyYXdkYXRhIC1yZXBsYWNlICcuKm5hbWU6XCgoW14pXSopXCkuKicsICckMScKICAgICRTUUwgPSAgICAgICAgICAgICAiR1JBTlQgQ09OTkVDVCBPTiBFTkRQT0lOVDo6JChDb252ZXJ0VG8tU1FMTmFtZSAkRW5kcG9pbnROYW1lKSBUTyAkKENvbnZlcnRUby1TUUxOYW1lICRSZW1vdGVIb3N0TG9naW4pIgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFNRTCkKfQoKZnVuY3Rpb24gQ29tcGxldGUtU1FMTWlycm9yIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbXBsZXRlcyBjcmVhdGlvbiBvZiBtaXJyb3JlZCBTUUwgZGF0YWJhc2UKCiAgICAuREVTQ1JJUFRJT04KICAgIFRoaXMgY21kbGV0IHNob3VsZCBiZSBmaXJzdCBleGVjdXRlZCBvbiBtaXJyb3Igc2VydmVyIGFuZCB0aGVuIG9uIHByaW5jaXBhbCBzZXJ2ZXIuCiAgICBPdGhlcndpc2UgaXQgd2lsbCBmYWlsIChob3dldmVyIGl0IG1heSBiZSBleGVjdXRlZCBhZ2FpbiB3aXRoIG5vIGhhcm0pLgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbSW50XSRSZW1vdGVQb3J0LAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFiYXNlTmFtZQogICAgKQoKICAgICRVcmwgPSAiVENQOi8vJHtSZW1vdGVIb3N0TmFtZX06JHtSZW1vdGVQb3J0fSIKICAgICRBbHRlckRiID0gIkFMVEVSIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgU0VUIFBBUlRORVIgPSAkKENvbnZlcnRUby1TUUxTdHJpbmcgJFVybCk7CiAgICAgICAgICAgICAgICBHTyIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRBbHRlckRiKQp9CgpmdW5jdGlvbiBOZXctU1FMRGF0YWJhc2UgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBlbXB0eSBTUUwgZGF0YWJhc2UKCiAgICAuREVTQ1JJUFRJT04KICAgIENyZWF0ZXMgZW1wdHkgU1FMIGRhdGFiYXNlIHdpdGggZGVmYXVsdCBzZXR0aW5ncy4gRmFpbHMgaW4gY2FzZSBpcyB0aGUgZGF0YWJhc2UgYWxyZWFkeSBleGlzdHMuCgogICAgLlBBUkFNRVRFUiBEYXRhQmFzZU5hbWUKICAgIERhdGFiYXNlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBtZGZGaWxlCiAgICBOYW1lIG9mIHRoZSBNREYgKGRhdGEpIGZpbGUuIElmIG5vdCBzcGVjaWZpZWQsIHRoZSBmb2xsb3dpbmcgdmFsdWUgaXMgdXNlZDoKICAgICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVx7RGF0YUJhc2VQYXRoTmFtZX0ubWRmIgogICAgV2hlcmUge0RhdGFCYXNlUGF0aE5hbWV9IGlzIGRhdGFiYXNlIG5hbWUgd2l0aCBhbGwgYnV0IEEtWiwgYS16LCAwLTkgY2hhcmFjdGVycwogICAgcmVwbGFjZWQgYnkgdW5kZXJzY29yZS4KCiAgICAuUEFSQU1FVEVSIERhdGFCYXNlTmFtZQogICAgTmFtZSBvZiB0aGUgTERGICh0cmFuc2FjdGlvbiBsb2cpIGZpbGUuIElmIG5vdCBzcGVjaWZpZWQsIHRoZSBmb2xsb3dpbmcgdmFsdWUgaXMgdXNlZDoKICAgICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVx7RGF0YUJhc2VQYXRoTmFtZX1fbG9nLm1kZiIKICAgIFdoZXJlIHtEYXRhQmFzZVBhdGhOYW1lfSBpcyBkYXRhYmFzZSBuYW1lIHdpdGggYWxsIGJ1dCBBLVosIGEteiwgMC05IGNoYXJhY3RlcnMKICAgIHJlcGxhY2VkIGJ5IHVuZGVyc2NvcmUuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZSwKICAgICAgICBbU3RyaW5nXSRtZGZGaWxlPSRudWxsLAogICAgICAgIFtTdHJpbmddJGxkZkZpbGU9JG51bGwKICAgICkKCiAgICAkRGF0YUJhc2VQYXRoTmFtZSA9ICREYXRhQmFzZU5hbWUgLXJlcGxhY2UgJ1teMC05YS16QS1aXScsICdfJwogICAgaWYgKC1ub3QgJG1kZkZpbGUpIHsKICAgICAgICAkbWRmRmlsZSA9ICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVwke0RhdGFCYXNlUGF0aE5hbWV9Lm1kZiIKICAgIH0KICAgIGlmICgtbm90ICRsZGZGaWxlKSB7CiAgICAgICAgJGxkZkZpbGUgPSAiQzpcUHJvZ3JhbSBGaWxlc1xNaWNyb3NvZnQgU1FMIFNlcnZlclxNU1NRTDExLk1TU1FMU0VSVkVSXE1TU1FMXERBVEFcJHtEYXRhQmFzZVBhdGhOYW1lfV9sb2cubGRmIgogICAgfQoKICAgICROZXdEYXRhYmFzZSA9ICIKICAgICAgICBDUkVBVEUgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKQogICAgICAgICAgICAgICAgQ09OVEFJTk1FTlQgPSBOT05FCiAgICAgICAgICAgICAgICBPTiAgUFJJTUFSWSAKICAgICAgICAgICAgKCBOQU1FID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAkRGF0YUJhc2VOYW1lKSwgRklMRU5BTUUgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICRtZGZGaWxlKSAsIFNJWkUgPSA0MDk2S0IgLCBGSUxFR1JPV1RIID0gMTAyNEtCICkKICAgICAgICAgICAgICAgIExPRyBPTiAKICAgICAgICAgICAgKCBOQU1FID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJHtEYXRhQmFzZU5hbWV9X2xvZyIpLCBGSUxFTkFNRSA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgJGxkZkZpbGUpICwgU0laRSA9IDEwMjRLQiAsIEZJTEVHUk9XVEggPSAxMCUpCiAgICAgICAgR08KICAgICAgICBVU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKQogICAgICAgIEdPCiAgICAgICAgSUYgTk9UIEVYSVNUUyAoU0VMRUNUIG5hbWUgRlJPTSBzeXMuZmlsZWdyb3VwcyBXSEVSRSBpc19kZWZhdWx0PTEgQU5EIG5hbWUgPSBOJ1BSSU1BUlknKSBBTFRFUiBEQVRBQkFTRSAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIE1PRElGWSBGSUxFR1JPVVAgW1BSSU1BUlldIERFRkFVTFQKICAgICAgICBHTyIKCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkTmV3RGF0YWJhc2UpCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nUHJpbmNpcGFsU3RlcDEgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgcHJpbmNpcGFsIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMSkKCiAgICAuREVTQ1JJUFRJT04KICAgIEluaXRpYWxpemVzIG1pcnJvcmluZyBlbmRwb2ludCAodGhpcyBpcyBhYnNvbHV0ZWx5IHN5bW1ldHJpYyBzdGVwIHRvIHRoZSBtaXJyb3IgaW5pdCkuIEluIGFkZGl0aW9uIHRvIHRoYXQgaXQgY3JlYXRlcwogICAgYSBkYXRhYmFzZSBhbmQgc3RvcmVzIGJhY2t1cHMgb2YgaXQgYW5kIGl0cyB0cmFuc2FjdGlvbiBsb2cgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIHRoZSBlbmRwb2ludCBjZXJ0aWZpY2F0ZS4KCiAgICBBIGZpcmV3YWxsIHJ1bGUgaXMgY3JlYXRlZCBmb3IgZW5kcG9pbnQgaWYgbmVjZXNzYXJ5LgoKICAgIC5QQVJBTUVURVIgV29ya0RpcgogICAgV29ya2luZCBkaXJlY3RvcnkuIFRoaXMgZGlyZWN0b3J5IHNob3VsZCBiZSB0cmFuZmVycmVkIHRvIHRoZSBtaXJyb3Igc2VydmVyIGFmdGVyIHRoaXMKICAgIHN0ZXAgaXMgZXhlY3V0ZWQuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWUKICAgIE1pcnJvcmVkIGRhdGFiYXNlIG5hbWUuIFRoaXMgbmFtZSBNVVNUIGJlIHVzZSBhdCBtaXJyb3Igc2VydmVyIGVpdGhlci4KICAgIAogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZQogICAgKQoKICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCA9ICIkKE5ldy1QYXNzd29yZCAxMClhQSMzIgoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgW3ZvaWRdKE5ldy1JdGVtIC1UeXBlIERpcmVjdG9yeSAkV29ya0RpcikKICAgIH0KICAgICRXb3JrRGlyID0gKEdldC1JdGVtICRXb3JrRGlyKS5GdWxsTmFtZQogICAgaWYgKChHZXQtQ2hpbGRJdGVtIC1QYXRoICRXb3JrRGlyKS5MZW5ndGggLWd0IDApIHsKICAgICAgICB0aHJvdyAiV29ya2luZyBkaXJlY3RvcnkgJFdvcmtEaXIgaXMgbm90IGVtcHR5IgogICAgfQoKICAgICRFbmRwb2ludFBvcnQgPSBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50ICRFbmNyeXB0aW9uUGFzc3dvcmQgIiRXb3JrRGlyXGNlcnRpZmljYXRlLmNlciIKICAgICRFbmRwb2ludFBvcnQgfCBTZXQtQ29udGVudCAiJFdvcmtEaXJcZW5kcG9pbnQtcG9ydC50eHQiCiAgICBOZXctU1FMRGF0YWJhc2UgJERhdGFCYXNlTmFtZQoKICAgICRCYWNrdXBEYiA9ICJCQUNLVVAgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcU291cmNlLmJhayIpIFdJVEggTk9GT1JNQVQsIElOSVQsIE5BTUUgPSBOJ0Z1bGwgRGF0YWJhc2UgQmFja3VwJywgU0tJUCwgTk9SRVdJTkQsIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwRGIpCiAgICAkQmFja3VwTG9nID0gIkJBQ0tVUCBMT0cgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcU291cmNlX2xvZy5iYWsiKSBXSVRIIE5PRk9STUFULCBJTklULCAgTkFNRSA9IE4nVHJhbnNhY3Rpb24gTG9nICBCYWNrdXAnLCBTS0lQLCBOT1JFV0lORCwgTk9VTkxPQUQsIFNUQVRTID0gMTAKICAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwTG9nKQp9CgpmdW5jdGlvbiBJbml0aWFsaXplLVNRTE1pcnJvcmluZ1ByaW5jaXBhbFN0ZXAyIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIFByZXBhcmVzIHByaW5jaXBhbCBTUUwgU2VydmVyIGZvciBkYXRhYmFzZSBtaXJyb3JpbmcgKFN0YWdlIDIpCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbXBvcnRzIHJlbW90ZSBzZXJ2ZXIgY2VydGlmaWNhdGUgYW5kIGdyYW50cyBpdCB3aXRoIGFjY2VzcyB0byB0aGUgbWlycm9yaW5nIGVuZHBvaW50LgoKICAgIC5QQVJBTUVURVIgUmVtb3RlSG9zdE5hbWUKICAgIFJlbW90ZSAobWlycm9yKSBob3N0IG5hbWUuIEZRRE4gaXMgcHJlZmVycmVkLCBidXQgTmV0QklPUyBuYW1lcyBhbmQgSVAgYWRkcmVzc2VzIGFyZSBhbHNvIGFjY2VwdGVkLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlV29ya0RpcgogICAgUGF0aCB0byBhIGNvcHkgb2Ygd29ya2RpciBvYnRhaW5lZCBmcm9tIG1pcnJvciBtYWNoaW5lIGNyZWF0ZWQgb24gU3RhZ2UgMS4KICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpcgogICAgKQoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFJlbW90ZVdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIlJlbW90ZSB3b3JrIGRpciAnJFJlbW90ZVdvcmtEaXInIHdhcyBub3QgZm91bmQiCiAgICB9CiAgICAkUmVtb3RlV29ya0RpciA9IChHZXQtSXRlbSAkUmVtb3RlV29ya0RpcikuRnVsbE5hbWUKCiAgICBDb21wbGV0ZS1NaXJyb3JpbmdFbmRwb2ludCAkUmVtb3RlSG9zdE5hbWUgJFJlbW90ZVdvcmtEaXIKfQoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1TUUxNaXJyb3JpbmdQcmluY2lwYWxTdGVwMyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBQcmVwYXJlcyBwcmluY2lwYWwgU1FMIFNlcnZlciBmb3IgZGF0YWJhc2UgbWlycm9yaW5nIChTdGFnZSAzKQoKICAgIC5ERVNDUklQVElPTgogICAgQ29tcGxldGVzIG1pcnJvciBjcmVhdGlvbi4gVGhpcyBzdGVwIG11c3QgYmUgZ2xvYmFsbHkgdGhlIGxhc3Qgb25lIGluIG1pcnJvciBjcmVhdGlvbiBzZXF1ZW5jZS4KCiAgICBOb3RlIHRoYXQgdGhlIHJlbW90ZSBob3N0IGNlcnRpZmljYXRlIGlzIHZhbGlkIGZyb20gdGhlIHRpbWUgaXQgaXMgY3JlYXRlZCB0aGVyZS4gU28KICAgIHRoaXMgc3RlcCB3aWxsIGZhaWwgaWYgdGhlcmUgaXMgbm90aWNhYmxlIGRpZmZlcmVudCBpbiB0aW1lIGxvY2FsIGFuZCByZW1vdGUgbWFjaGluZXMuCgogICAgLlBBUkFNRVRFUiBSZW1vdGVIb3N0TmFtZQogICAgUmVtb3RlIChwcmluY2lwYWwpIGhvc3QgbmFtZS4gRlFETiBpcyBwcmVmZXJyZWQsIGJ1dCBOZXRCSU9TIG5hbWVzIGFuZCBJUCBhZGRyZXNzZXMgYXJlIGFsc28gYWNjZXB0ZWQuCgogICAgLlBBUkFNRVRFUiBSZW1vdGVXb3JrRGlyCiAgICBQYXRoIHRvIGEgY29weSBvZiB3b3JrZGlyIG9idGFpbmVkIGZyb20gcHJpbmNpcGFsIG1hY2hpbmUgY3JlYXRlZCBvbiBTdGFnZSAxLgoKICAgIC5QQVJBTUVURVIgRGF0YWJhc2VOYW1lCiAgICBNaXJyb3JlZCBkYXRhYmFzZSBuYW1lLiBUaGlzIG5hbWUgTVVTVCBtYXRjaCBwcmluY2lwYWwgZGF0YWJhc2UgbmFtZSBhbmQgbmFtZSBwcm92aWRlZCBvbiBzdGVwIDEuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZUhvc3ROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZVdvcmtEaXIsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kRGF0YWJhc2VOYW1lCiAgICApCgogICAgW2ludF0kcG9ydCA9IEdldC1Db250ZW50ICIke1JlbW90ZVdvcmtEaXJ9XGVuZHBvaW50LXBvcnQudHh0IgogICAgQ29tcGxldGUtU1FMTWlycm9yICRSZW1vdGVIb3N0TmFtZSAkcG9ydCAkRGF0YWJhc2VOYW1lCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDEgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UxKQoKICAgIC5ERVNDUklQVElPTgogICAgSW5pdGlhbGl6ZXMgbWlycm9yaW5nIGVuZHBvaW50IGZvciBtaXJyb3Igc2VydmVyLiBTdG9yZXMgbWlycm9yaW5nIGVuZHBvaW50IGNlcnRpZmljYXRlIGluIFdvcmtkaXIuCgogICAgLlBBUkFNRVRFUiBXb3JrRGlyCiAgICBXb3JraW5kIGRpcmVjdG9yeS4gVGhpcyBkaXJlY3Rvcnkgc2hvdWxkIGJlIHRyYW5mZXJyZWQgdG8gdGhlIHByaW5jaXBhbCBzZXJ2ZXIgYWZ0ZXIgdGhpcwogICAgc3RlcCBpcyBleGVjdXRlZC4KCiAgICAuUEFSQU1FVEVSIERhdGFiYXNlTmFtZQogICAgTWlycm9yZWQgZGF0YWJhc2UgbmFtZS4gVGhpcyBuYW1lIE1VU1QgbWF0Y2ggcHJpbmNpcGFsIGRhdGFiYXNlIG5hbWUuCgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFiYXNlTmFtZQogICAgKQoKICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCA9ICIkKE5ldy1QYXNzd29yZCAxMClhQSMzIgoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgW3ZvaWRdKE5ldy1JdGVtIC1UeXBlIERpcmVjdG9yeSAkV29ya0RpcikKICAgIH0KICAgICRXb3JrRGlyID0gKEdldC1JdGVtICRXb3JrRGlyKS5GdWxsTmFtZQoKICAgICRFbmRwb2ludFBvcnQgPSBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50ICRFbmNyeXB0aW9uUGFzc3dvcmQgIiRXb3JrRGlyXGNlcnRpZmljYXRlLmNlciIKICAgICRFbmRwb2ludFBvcnQgfCBTZXQtQ29udGVudCAiJFdvcmtEaXJcZW5kcG9pbnQtcG9ydC50eHQiCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDIgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMikKCiAgICAuREVTQ1JJUFRJT04KICAgIEltcG9ydHMgcmVtb3RlIHNlcnZlciBjZXJ0aWZpY2F0ZSBhbmQgZ3JhbnRzIGl0IHdpdGggYWNjZXNzIHRvIHRoZSBtaXJyb3JpbmcgZW5kcG9pbnQuCiAgICBSZXN0b3JlcyBkYXRhYmFzZSBvYnRhaW5lZCBmcm9tIHByaW5jaXBhbCBhbmQgbGVhdmVzIGl0IGluICdSZXN0b3JpbmcnIHN0YXRlLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlSG9zdE5hbWUKICAgIFJlbW90ZSAocHJpbmNpcGFsKSBob3N0IG5hbWUuIEZRRE4gaXMgcHJlZmVycmVkLCBidXQgTmV0QklPUyBuYW1lcyBhbmQgSVAgYWRkcmVzc2VzIGFyZSBhbHNvIGFjY2VwdGVkLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlV29ya0RpcgogICAgUGF0aCB0byBhIGNvcHkgb2Ygd29ya2RpciBvYnRhaW5lZCBmcm9tIHByaW5jaXBhbCBtYWNoaW5lIGNyZWF0ZWQgb24gU3RhZ2UgMS4KCiAgICAuUEFSQU1FVEVSIERhdGFiYXNlTmFtZQogICAgTWlycm9yZWQgZGF0YWJhc2UgbmFtZS4gVGhpcyBuYW1lIE1VU1QgbWF0Y2ggcHJpbmNpcGFsIGRhdGFiYXNlIG5hbWUuCgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZQogICAgKQoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFJlbW90ZVdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIlJlbW90ZSB3b3JrIGRpciAnJFJlbW90ZVdvcmtEaXInIHdhcyBub3QgZm91bmQiCiAgICB9CiAgICAkUmVtb3RlV29ya0RpciA9IChHZXQtSXRlbSAkUmVtb3RlV29ya0RpcikuRnVsbE5hbWUKCiAgICBDb21wbGV0ZS1NaXJyb3JpbmdFbmRwb2ludCAkUmVtb3RlSG9zdE5hbWUgJFJlbW90ZVdvcmtEaXIKCiAgICAkUmVzdG9yZURiID0gIlJFU1RPUkUgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBGUk9NIERJU0sgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICIkUmVtb3RlV29ya0RpclxTb3VyY2UuYmFrIikgV0lUSCBGSUxFID0gMSwgTk9SRUNPVkVSWSwgTk9VTkxPQUQsIFJFUExBQ0UsIFNUQVRTID0gNQogICAgICAgICAgICAgICAgICBHTyIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRSZXN0b3JlRGIpCiAgICAkUmVzdG9yZUxvZyA9ICJSRVNUT1JFIExPRyAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIEZST00gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRSZW1vdGVXb3JrRGlyXFNvdXJjZV9sb2cuYmFrIikgV0lUSCBGSUxFID0gMSwgTk9SRUNPVkVSWSwgTk9VTkxPQUQsIFNUQVRTID0gMTAKICAgICAgICAgICAgICAgICAgIEdPIgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVMb2cpCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDMgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMykKCiAgICAuREVTQ1JJUFRJT04KICAgIENvbXBsZXRlcyBtaXJyb3IgY3JlYXRpb24uIFRoaXMgc3RlcCBtdXN0IGJlIGV4ZWN1dGVkIHN0cmljdGx5IGJlZm9yZSBzeW1tZXRyaWMgc3RlcCBvbiB0aGUgcHJpbmNpcGFsLgoKICAgIE5vdGUgdGhhdCB0aGUgcmVtb3RlIGhvc3QgY2VydGlmaWNhdGUgaXMgdmFsaWQgZnJvbSB0aGUgdGltZSBpdCBpcyBjcmVhdGVkIHRoZXJlLiBTbwogICAgdGhpcyBzdGVwIHdpbGwgZmFpbCBpZiB0aGVyZSBpcyBub3RpY2FibGUgZGlmZmVyZW50IGluIHRpbWUgbG9jYWwgYW5kIHJlbW90ZSBtYWNoaW5lcy4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZUhvc3ROYW1lCiAgICBSZW1vdGUgKHByaW5jaXBhbCkgaG9zdCBuYW1lLiBGUUROIGlzIHByZWZlcnJlZCwgYnV0IE5ldEJJT1MgbmFtZXMgYW5kIElQIGFkZHJlc3NlcyBhcmUgYWxzbyBhY2NlcHRlZC4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZVdvcmtEaXIKICAgIFBhdGggdG8gYSBjb3B5IG9mIHdvcmtkaXIgb2J0YWluZWQgZnJvbSBwcmluY2lwYWwgbWFjaGluZSBjcmVhdGVkIG9uIFN0YWdlIDEuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWUKICAgIE1pcnJvcmVkIGRhdGFiYXNlIG5hbWUuIFRoaXMgbmFtZSBNVVNUIG1hdGNoIHByaW5jaXBhbCBkYXRhYmFzZSBuYW1lLgoKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpciwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSREYXRhYmFzZU5hbWUKICAgICkKCiAgICBbaW50XSRwb3J0ID0gR2V0LUNvbnRlbnQgIiR7UmVtb3RlV29ya0Rpcn1cZW5kcG9pbnQtcG9ydC50eHQiCiAgICBDb21wbGV0ZS1TUUxNaXJyb3IgJFJlbW90ZUhvc3ROYW1lICRwb3J0ICREYXRhYmFzZU5hbWUKfQoKZnVuY3Rpb24gR2V0LU5leHRGcmVlUG9ydCB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBSZXR1cm5zIHNwZWNpZmllZCBkZXNpcmVkIHBvcnQgb3IgY2xvc2VzdCBuZXh0IG9uZSB1bm9jY3VwaWVkLgoKICAgIC5QQVJBTUVURVIgUG9ydAogICAgRGVzaXJlZCBwb3J0IG51bWJlci4KCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtpbnRdJFBvcnQKICAgICkKICAgICRPcGVuUG9ydHMgPSBuZXRzdGF0IC1hb24gfCBzZWxlY3Qtc3RyaW5nICdMSVNURU5JTkcnIHwgRm9yZWFjaC1PYmplY3QgeyAoKCRfIC1yZXBsYWNlICdeXHMqJywgJycgLXNwbGl0ICdccysnKVsxXSAtc3BsaXQgJy4qOicpWzFdIH0gfCBTb3J0LU9iamVjdCB8IEdldC1VbmlxdWUKICAgIHdoaWxlICgkT3BlblBvcnRzLkNvbnRhaW5zKCR7UG9ydH0pKSB7CiAgICAgICAgJFBvcnQgPSAkUG9ydCArIDEKICAgIH0KICAgIHJldHVybiAkUG9ydAp9CgpmdW5jdGlvbiBJbml0aWFsaXplLUFsd2F5c09uIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluaXRpYWxpemVzIEFsd2F5c09uIGNsdXN0ZXJpbmcgb24gbG9jYWwgU1FMIHNlcnZlciBhbmQgY3JlYXRlcyBBbHdheXNPbiBlbmRwb2ludCBsaXN0ZW5lci4gUmV0dXJucyBBbHdheXNPbiBlbmRwb2ludCBwb3J0IG51bWJlci4KCiAgICAuREVTQ1JJUFRJT04KICAgIEVuYWJsZXMgQWx3YXlzT24gY2x1c3RlcmluZyBvbiBsb2NhbCBTUUwgc2VydmVyLiBDcmVhdGVzIEFsd2F5c09uIFRDUCBlbmRwb2ludCBvbiBwb3J0IDUwMjIgb3IgZ3JlYXRlciBpZiB0aGUgb25lIGlzIG9jY3VwaWVkLiAgIAogICAgIz4KCiAgICBpZiAoIShUZXN0LVBhdGggU1FMU0VSVkVSOlwpKSB7CiAgICAgICAgSW1wb3J0LU1vZHVsZSBzcWxwcwogICAgfQogICAgJE1hY2hpbmVOYW1lID0gKEdldC1DaGlsZEl0ZW0gU1FMU0VSVkVSOlxTUUwpWzBdLlBTQ2hpbGROYW1lCiAgICAkSW5zdGFuY2VOYW1lID0gKEdldC1DaGlsZEl0ZW0gU1FMU0VSVkVSOlxTUUxcJE1hY2hpbmVOYW1lKS5QU0NoaWxkTmFtZQogICAgJEFsd2F5c09uRW5hYmxlZCA9ICgoR2V0LUl0ZW0gU1FMU0VSVkVSOlxTUUxcJE1hY2hpbmVOYW1lXCRJbnN0YW5jZU5hbWUpIHwgc2VsZWN0IElzSGFkckVuYWJsZWQpLklzSGFkckVuYWJsZWQKICAgIGlmICgtbm90ICRBbHdheXNPbkVuYWJsZWQpIHsKICAgICAgICBFbmFibGUtU3FsQWx3YXlzT24gLVBhdGggIlNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lIiAtRm9yY2UKICAgIH0KICAgICRJbnN0YW5jZSA9IEdldC1JdGVtIFNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lCiAgICAkZW5kcG9pbnQgPSAkSW5zdGFuY2UuRW5kcG9pbnRzWyJBbHdheXNPbkVuZHBvaW50Il0KICAgIGlmICgtbm90ICRlbmRwb2ludCkgewogICAgICAgICRQb3J0ID0gR2V0LU5leHRGcmVlUG9ydCA1MDIyCiAgICAgICAgJGVuZHBvaW50ID0gTmV3LVNxbEhhZHJFbmRwb2ludCBBbHdheXNPbkVuZHBvaW50IC1Qb3J0ICRQb3J0IC1QYXRoIFNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lCiAgICB9IGVsc2UgewogICAgICAgICRQb3J0ID0gJGVuZHBvaW50LlByb3RvY29sLlRjcC5MaXN0ZW5lclBvcnQKICAgIH0gCiAgICBpZiAoJGVuZHBvaW50LkVuZHBvaW50U3RhdGUgLW5lICJTdGFydGVkIikgewogICAgICAgICRlbmRwb2ludC5TdGFydCgpCiAgICB9ICAgIAogICAgcmV0dXJuICRQb3J0Cn0KCmZ1bmN0aW9uIE5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgbmV3IEFsd2F5c09uIGF2YWlsYWJpbGl0eSBncm91cCBvbiBwcmltYXJ5IHJlcGxpY2EuCgogICAgLkRFU0NSSVBUSU9OCiAgICBDcmVhdGVzIG5ldyBBbHdheXNPbiBhdmFpbGFiaWxpdHkgZ3JvdXAgb24gcHJpbWFyeSByZXBsaWNhLgoKICAgIC5QQVJBTUVURVIgV29ya0RpcgogICAgV29ya2luZCBkaXJlY3RvcnkuIFRoaXMgZGlyZWN0b3J5IHNob3VsZCBiZSB0cmFuZmVycmVkIHRvIHRoZSByZXBsaWNhIHNlcnZlcihzKSBhZnRlciB0aGlzCiAgICBzdGVwIGlzIGV4ZWN1dGVkLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgQXZhaWxhYmlsaXR5IGdyb3VwIG5hbWUuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWVzCiAgICBSZXBsaWNhIGRhdGFiYXNlKHMpIG5hbWVzLgoKICAgIC5QQVJBTUVURVIgUmVwbGljYURlZnMKICAgIEFycmF5IG9mIHJlcGxpY2EgZGVmaW5pdGlvbi4gRWFjaCBkZWZpbml0aW9uIGlzIGEgaGFzaCB0YWJsZSB3aXRoIHJlcGxpY2Etc3BlY2lmaWMgdmFsdWVzLgogICAgCiAgICBNYW5kYXRvcnkgcmVwbGljYSBkZWZpbml0aW9uIHZhbHVlcyBhcmU6CgogICAgICAgICogW1N0cmluZ10gU0VSVkVSX0lOU1RBTkNFICAgLSBSZXBsaWNhIHNlcnZlciBpbnN0YW5jZSBuYW1lCiAgICAgICAgKiBbU3RyaW5nXSBFTkRQT0lOVF9VUkwgICAgICAtIFJlcGxpY2Egc2VydmVyIGVuZHBvaW50IFVSTC4gTm9ybWFsbHkgaXQgaXMgVENQOi8vZnVsbHkucXVhbGlmaWVkLmRvbWFpbi5uYW1lOjUwMjIgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBvcnQgbnVtYmVyIHNob3VsZCBiZSBvYnRhaW5lZCB3aXRoIEluaXRpYWxpemUtQWx3YXlzT24gYXQgdGhlIHJlcGxpY2Egc2VydmVyCiAgICAgICAgKiBbU3RyaW5nXSBBVkFJTEFCSUxJVFlfTU9ERSAtIFJlcGxpY2EgYXZhaWxhYmlsaXR5IG1vZGUuIENhbiBiZSAiU1lOQ0hST05PVVNfQ09NTUlUIiBvciAiQVNZTkNIUk9OT1VTX0NPTU1JVCIgb25seS4KICAgICAgICAqIFtTdHJpbmddIEZBSUxPVkVSX01PREUgICAgIC0gUmVwbGljYSBhdmFpbGFiaWxpdHkgbW9kZS4gQ2FuIGJlICJNQU5VQUwiIG9yICJBVVRPTUFUSUMiIG9ubHkuCgogICAgT3B0aW9uYWwgcmVwbGljYSBkZWZpbml0aW9uIHZhbHVlcyBhcmU6CgogICAgICAgICogW0ludGVnZXJdIEJBQ0tVUF9QUklPUklUWSAgICAgICAgICAtIEJhY2t1cCBwcmlvcml0eQogICAgICAgICogW0ludGVnZXJdIFNFU1NJT05fVElNRU9VVCAgICAgICAgICAtIFNlc3Npb24gdGltZW91dAogICAgICAgICogW1N0cmluZ10gIFBfQUxMT1dfQ09OTkVDVElPTlMgICAgICAtIEFsbG93ZWQgY29ubmVjdGlvbiB0eXBlcyBmb3IgIlByaW1hcnkiIHJlcGxpY2EgbW9kZS4gQ2FuIGJlICJSRUFEX1dSSVRFIiBvciAiQUxMIiBvbmx5LgogICAgICAgICogW0FycmF5XSAgIFBfUkVBRF9PTkxZX1JPVVRJTkdfTElTVCAtIExpc3Qgb2YgcmVwbGljYXMgcHJvdmlyaW5nIHJlYWRvbmx5IGFjY2VzcyB3aGVuIHRoaXMgb25lIGlzIHByaW1hcnkuCiAgICAgICAgKiBbU3RyaW5nXSAgU19BTExPV19DT05ORUNUSU9OUyAgICAgIC0gQWxsb3dlZCBjb25uZWN0aW9uIHR5cGVzIGZvciAiU2Vjb25kYXJ5IiByZXBsaWNhIG1vZGUuIENhbiBiZSBvbmUgb2YgIk5PIiwgIlJFQURfT05MWSIsICJBTEwiLgogICAgICAgICogW1N0cmluZ10gIFNfUkVBRF9PTkxZX1JPVVRJTkdfVVJMICAtIFJlcGxpY2EgcmVhZC1vbmx5IHJlcXVlc3RzIGxpc3RlbmVyIFVSTC4gTm9ybWFsbHkgZGVmYXVsdCBzZXJ2ZXIgbGlzdGVuZXIgYXQgcG9ydCAxNDMzIGlzIHVzZWQuCgogICAgLlBBUkFNRVRFUiBQcmVmZXJlbmNlcwogICAgSGFzaCB0YWJsZSBvZiBnZW5lcmFsIGF2YWlsYWJpbGl0eSBncm91cCBwcmVmZXJlbmNlcy4gQWxsIHRoZSBrZXlzIGFyZSBvcHRpb25hbC4gU3VwcG9ydGVkIGVudHJ5IGtleXMgYXJlOgoKICAgICAgICAqIFtTdHJpbmddICBBVVRPTUFURURfQkFDS1VQX1BSRUZFUkVOQ0UgLSBBdXRvbWF0ZWQgYmFja3VwIHByZWZlcmVuY2UuIENhbiBiZSAiUFJJTUFSWSIsICJTRUNPTkRBUllfT05MWSIsICJTRUNPTkRBUlkiIG9yICJOT05FIi4KICAgICAgICAqIFtTdHJpbmddICBGQUlMVVJFX0NPTkRJVElPTl9MRVZFTCAgICAgLSBGYWlsdXJlIGNvbmRpdGlvbiBsZXZlbC4gQ2FuIGJlICIxIiwgIjIiLCAiMyIsICI0IiBvciAiNSIuCiAgICAgICAgKiBbSW50ZWdlcl0gSEVBTFRIX0NIRUNLX1RJTUVPVVQgICAgICAgIC0gUmVwbGljYSBoZWFsdGggY2hlY2sgdGltZW91dC4KCiAgICAuUEFSQU1FVEVSIExpc3RlbmVyRGVmCiAgICBIYXNoIHRhYmxlIGNvbnRhaW5pbmcgYXZhaWxhYmlsaXR5IGdyb3VwIGxpc3RlbmVyIGNvbmZpZ3VyYXRpb24uCgogICAgTWFuZGF0b3J5IGxpc3RlbmVyIGNvbmZpZ3VyYXRpb24gdmFsdWVzIGFyZToKCiAgICAgICAgW1N0cmluZ10gTkFNRSAtIExpc3RlbmVyIG5hbWUuCgogICAgT3B0aW9uYWwgbGlzdGVuZXIgY29uZmlndXJhdGlvbiB2YWx1ZXMgYXJlOgogICAgCiAgICAgICAgW1N0cmluZ10gUE9SVCAtIExpc3RlbmVyIHBvcnQgbnVtYmVyLiBJbnRlZ2VyIHZhbHVlIG1heSBiZSBzdWZmaXhlZCBieSBhICIrIiBzeW1vbCAoc3VjaCBhcyAiNTAyMisiKSB3aGljaCBhbGxvd3MgdGhlIHJvdXRpbmUgdG8KICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0IG5leHQgZnJlZSBwb3J0IHdpdGggbnVtYmVyIGdyZWF0ZXIgb3IgZXF1YWwgdG8gdGhlIHNwZWNpZmllZCB2YWx1ZS4KICAgICAgICBbU3RyaW5nXSBESENQIC0gREhDUCBsaXN0ZW5lciBhZGRyZXNzIGNvbmZpZ3VyYXRpb24gZmxhZy4gV2hlbiBhbnkgdmFsdWUgc3BlY2lmaWVkLCBESENQIGlzIHVzZWQgdG8gY29uZmlndXJlIGxpc3RlbmVyCiAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzIGlzIGFsc28gdGhlIGRlZmF1bHQgYmVoYXZpb3IpLiBBbHNvLCBhIHNwZWNpZmljIGludGVyZmFjZSBmb3IgREhDUCBtYXkgYmUgc3BlY2lmaWVkIGFzIElQX0FERFJFU1MvTUFTSwogICAgICAgICAgICAgICAgICAgICAgICAobGlrZSAiMTkyLjE2OC4xLjAvMjU1LjI1NS4yNTUuMCIpIGFzIGEgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci4KICAgICAgICBbQXJyYXldIFNUQVRJQyAtIFN0YXRpYyBJUCBhZGRyZXNzZXMgdG8gbGlzdGVuLiBJUCBhZGRyZXNzZXMgbWF5IGJlIElQdjQgYWRkcmVzc2VzIGluIHRoZSAiSVBfQUREUkVTUy9NQVNLIiBmb3JtIG9yIElQdjYKICAgICAgICAgICAgICAgICAgICAgICAgYWRkcmVzc2VzIGluIHN0YW5kYXJkIElQdjYgbm90YXRpb24uCgogICAgU2VlIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9mZjg3ODM5OS5hc3B4IHBhZ2UgZm9yIG1vcmUgZGV0YWlscyByZWdhcmRpbmcgYWxsIHRoZSBzdXBwb3J0ZWQgb3B0aW9ucy4KICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kV29ya0RpciwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtBcnJheV0kRGF0YWJhc2VOYW1lcywKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbQXJyYXldJFJlcGxpY2FEZWZzLAogICAgICAgIFtwYXJhbWV0ZXJdCiAgICAgICAgW0hhc2h0YWJsZV0kUHJlZmVyZW5jZXMsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW0hhc2h0YWJsZV0kTGlzdGVuZXJEZWYKICAgICkKCiAgICBpZiAoLW5vdCAoVGVzdC1QYXRoICRXb3JrRGlyKSkgewogICAgICAgIFt2b2lkXShOZXctSXRlbSAtVHlwZSBEaXJlY3RvcnkgJFdvcmtEaXIpCiAgICB9CiAgICAkV29ya0RpciA9IChHZXQtSXRlbSAkV29ya0RpcikuRnVsbE5hbWUKICAgIGlmICgoR2V0LUNoaWxkSXRlbSAtUGF0aCAkV29ya0RpcikuTGVuZ3RoIC1ndCAwKSB7CiAgICAgICAgdGhyb3cgIldvcmtpbmcgZGlyZWN0b3J5ICRXb3JrRGlyIGlzIG5vdCBlbXB0eSIKICAgIH0KCiAgICAkUXVvdGVkREJOYW1lcyA9ICgkRGF0YWJhc2VOYW1lcyB8IEZvckVhY2gtT2JqZWN0IHsgQ29udmVydFRvLVNRTE5hbWUgJF8gfSkgLWpvaW4gIiwgIgoKICAgIGlmICgkUHJlZmVyZW5jZXMgLWVxICRudWxsKSB7CiAgICAgICAgJFByZWZlcmVuY2VzID0gQCgpCiAgICB9CiAgICAkUHJlZnMgPSBAKCkKICAgIGZvcmVhY2goJFByZWYgaW4gJFByZWZlcmVuY2VzKSB7CiAgICAgICAgaWYgKCRQcmVmLktleSAtZXEgJG51bGwpIHsKICAgICAgICAgICAgQ29udGludWUKICAgICAgICB9CiAgICAgICAgaWYgKCRQcmVmLktleSAtZXEgIkFVVE9NQVRFRF9CQUNLVVBfUFJFRkVSRU5DRSIpIHsKICAgICAgICAgICAgJFByZWZzID0gJFByZWZzICsgKFZhbGlkYXRlLU9wdGlvbiAkUHJlZi5LZXksICRQcmVmLlZhbHVlLCBAKCJQUklNQVJZIiwgIlNFQ09OREFSWV9PTkxZIiwgIlNFQ09OREFSWSIsICJOT05FIikgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAkUHJlZi5LZXkpCiAgICAgICAgfSBlbHNlaWYgKCRQcmVmLktleSAtZXEgIkZBSUxVUkVfQ09ORElUSU9OX0xFVkVMIikgewogICAgICAgICAgICAkUHJlZnMgPSAkUHJlZnMgKyAoVmFsaWRhdGUtT3B0aW9uICRQcmVmLktleSwgJFByZWYuVmFsdWUsIEAoIjEiLCAiMiIsICIzIiwgIjQiLCAiNSIpIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgJFByZWYuS2V5KQogICAgICAgIH0gZWxzZWlmICgkUHJlZi5LZXkgLWVxICJIRUFMVEhfQ0hFQ0tfVElNRU9VVCIpIHsKICAgICAgICAgICAgJFByZWZzID0gJFByZWZzICsgKFZhbGlkYXRlLUludE9wdGlvbiAkUHJlZi5LZXksICRQcmVmLlZhbHVlIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgJFByZWYuS2V5KQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRocm93ICJVbmV4cGVjdGVkIHBlZmVyZW5jZXMgb3B0aW9uOiAnJCgkUHJlZi5LZXkpJyIKICAgICAgICB9CiAgICB9CgogICAgJFJlcGxpY2FEZWZpbml0aW9uc0FycmF5ID0gQCgpCiAgICBmb3IgKCRpID0gMDsgJGkgLWx0ICRSZXBsaWNhRGVmcy5MZW5ndGg7ICRpKyspIHsKICAgICAgICAkUkRlZiA9ICRSZXBsaWNhRGVmc1skaV0KICAgICAgICBpZiAoJFJEZWYuR2V0VHlwZSgpLk5hbWUgLW5lICJIYXNodGFibGUiKSB7CiAgICAgICAgICAgIHRocm93ICJBbGwgZWxlbWVudHMgb2YgUmVwbGljYURlZnMgYXJyYXkgc2hvdWxkIGJlIEhhc2h0YWJsZXMiCiAgICAgICAgfQoKICAgICAgICAkUmVwbGljYU9wdHMgPSBAKCkKCiAgICAgICAgIyBNYW5kYXRvcnkgb3B0aW9ucwogICAgICAgICRSZXBsaWNhTmFtZSA9IFZhbGlkYXRlLURlZmluZWRPcHRpb24gIlNFUlZFUl9JTlNUQU5DRSIgJFJEZWZbIlNFUlZFUl9JTlNUQU5DRSJdCiAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLURlZmluZWRPcHRpb24gIkVORFBPSU5UX1VSTCIgJFJEZWZbIkVORFBPSU5UX1VSTCJdIHwgQ29udmVydFRvLVNRTFN0cmluZyB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJFTkRQT0lOVF9VUkwiKQogICAgICAgICRSZXBsaWNhT3B0cyA9ICRSZXBsaWNhT3B0cyArIChWYWxpZGF0ZS1PcHRpb24gIkFWQUlMQUJJTElUWV9NT0RFIiAkUkRlZlsiQVZBSUxBQklMSVRZX01PREUiXSBAKCJTWU5DSFJPTk9VU19DT01NSVQiLCAiQVNZTkNIUk9OT1VTX0NPTU1JVCIpIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIkFWQUlMQUJJTElUWV9NT0RFIikKICAgICAgICAkUmVwbGljYU9wdHMgPSAkUmVwbGljYU9wdHMgKyAoVmFsaWRhdGUtT3B0aW9uICJGQUlMT1ZFUl9NT0RFIiAkUkRlZlsiRkFJTE9WRVJfTU9ERSJdIEAoIkFVVE9NQVRJQyIsICJNQU5VQUwiKSB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJGQUlMT1ZFUl9NT0RFIikKCiAgICAgICAgIyBPcHRpb25hbCBvcHRpb25zCiAgICAgICAgaWYgKCRSRGVmWyJCQUNLVVBfUFJJT1JJVFkiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLUludE9wdGlvbiAiQkFDS1VQX1BSSU9SSVRZIiAkUkRlZlsiQkFDS1VQX1BSSU9SSVRZIl0gfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQkFDS1VQX1BSSU9SSVRZIikKICAgICAgICB9CiAgICAgICAgaWYgKCRSRGVmWyJTRVNTSU9OX1RJTUVPVVQiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLUludE9wdGlvbiAiU0VTU0lPTl9USU1FT1VUIiAkUkRlZlsiU0VTU0lPTl9USU1FT1VUIl0gfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiU0VTU0lPTl9USU1FT1VUIikKICAgICAgICB9CgogICAgICAgICRTZWNvbmRhcnlSb2xlID0gQCgpCiAgICAgICAgaWYgKCRSRGVmWyJTX0FMTE9XX0NPTk5FQ1RJT05TIl0gLW5lICRudWxsKSB7CiAgICAgICAgICAgICRTZWNvbmRhcnlSb2xlID0gJFNlY29uZGFyeVJvbGUgKyAoVmFsaWRhdGUtT3B0aW9uICJTX0FMTE9XX0NPTk5FQ1RJT05TIiAkUkRlZlsiU19BTExPV19DT05ORUNUSU9OUyJdIEAoIk5PIiwgIlJFQURfT05MWSIsICJBTEwiKSB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJBTExPV19DT05ORUNUSU9OUyIpCiAgICAgICAgfQogICAgICAgIGlmICgkUkRlZlsiU19SRUFEX09OTFlfUk9VVElOR19VUkwiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFNlY29uZGFyeVJvbGUgPSAkU2Vjb25kYXJ5Um9sZSArICgkUkRlZlsiU19SRUFEX09OTFlfUk9VVElOR19VUkwiXSB8IENvbnZlcnRUby1TUUxTdHJpbmcgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFNlY29uZGFyeVJvbGUuTGVuZ3RoIC1ndCAwKSB7CiAgICAgICAgICAgICRSZXBsaWNhT3B0cyA9ICRSZXBsaWNhT3B0cyArICgiKCAkKCRTZWNvbmRhcnlSb2xlIC1qb2luICcsICcpICkiIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIlNFQ09OREFSWV9ST0xFIikKICAgICAgICB9CgogICAgICAgICRQcmltYXJ5Um9sZSA9IEAoKQogICAgICAgIGlmICgkUkRlZlsiUF9BTExPV19DT05ORUNUSU9OUyJdIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkUHJpbWFyeVJvbGUgPSAkUHJpbWFyeVJvbGUgKyAoVmFsaWRhdGUtT3B0aW9uICJQX0FMTE9XX0NPTk5FQ1RJT05TIiAkUkRlZlsiUF9BTExPV19DT05ORUNUSU9OUyJdIEAoIlJFQURfV1JJVEUiLCAiQUxMIikgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFJEZWZbIlBfUkVBRF9PTkxZX1JPVVRJTkdfTElTVCJdIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkUHJpbWFyeVJvbGUgPSAkUHJpbWFyeVJvbGUgKyAoKCgkUkRlZlsiUF9SRUFEX09OTFlfUk9VVElOR19MSVNUIl0gfCBGb3JFYWNoLU9iamVjdCB7IENvbnZlcnRUby1TUUxTdHJpbmcgJF8gfSkgLWpvaW4gJywgJykgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFByaW1hcnlSb2xlLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICAgICAkUmVwbGljYU9wdHMgPSAkUmVwbGljYU9wdHMgKyAoIiggJCgkUHJpbWFyeVJvbGUgLWpvaW4gJywgJykgKSIgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiUFJJTUFSWV9ST0xFIikKICAgICAgICB9CgogICAgICAgICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSA9ICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSArCiAgICAgICAgICAgICMgIFRDUDovL2JyYXZvLm11cmFuby5sb2NhbDo1MDIyCiAgICAgICAgICAgICJOJChDb252ZXJ0VG8tU1FMU3RyaW5nICRSZXBsaWNhTmFtZSkgV0lUSCAoJCgkUmVwbGljYU9wdHMgLWpvaW4gJywgJykpIgogICAgfQogICAgJFJlcGxpY2FEZWZpbml0aW9ucyA9ICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSAtam9pbiAiLGByYG4gICAgICAgICI7CgogICAgaWYgKCRMaXN0ZW5lckRlZlsiREhDUCJdIC1uZSAkbnVsbCkgewogICAgICAgIGlmICgkTGlzdGVuZXJEZWZbIkRIQ1AiXS5tYXRjaGVzKCJcZCtcLlxkK1wuXGQrXC5cZCsvXGQrXC5cZCtcLlxkK1wuXGQrIikpIHsKICAgICAgICAgICAgKCRJcEFkZHIsICRNYXNrKSA9ICRMaXN0ZW5lckRlZlsiREhDUCJdIC1zcGxpdCAiLyIKICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICJESENQIE9OICggJElwQWRkciwgJE1hc2sgKSIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAkTGlzdGVuZXJBZGRyID0gIkRIQ1AiCiAgICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgICBbYXJyYXldJElQQWRkcmVzc2VzID0gJExpc3RlbmVyRGVmWyJTVEFUSUMiXQogICAgICAgIGlmICgoJElQQWRkcmVzc2VzIC1lcSAkbnVsbCkgLW9yICgkSVBBZGRyZXNzZXMuQ291bnQgLWVxIDApKSB7CiAgICAgICAgICAgICRMaXN0ZW5lckFkZHIgPSAiREhDUCIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAkQ29udmVydGVkT3B0cyA9IEAoKQogICAgICAgICAgICBmb3JlYWNoICgkSXBPcHRpb24gaW4gJElQQWRkcmVzc2VzKSB7CiAgICAgICAgICAgICAgICAjIElQdjQKICAgICAgICAgICAgICAgIGlmICgkSXBPcHRpb24gLW1hdGNoICJcZCtcLlxkK1wuXGQrXC5cZCsvXGQrXC5cZCtcLlxkK1wuXGQrIikgewogICAgICAgICAgICAgICAgICAgICgkSXBBZGRyLCAkTWFzaykgPSAkSXBPcHRpb24gLXNwbGl0ICIvIgogICAgICAgICAgICAgICAgICAgICRDb252ZXJ0ZWRPcHRzID0gJENvbnZlcnRlZE9wdHMgKyAiKCAkKENvbnZlcnRUby1TUUxTdHJpbmcgJElwQWRkciksICQoQ29udmVydFRvLVNRTFN0cmluZyAkTWFzaykgKSIKICAgICAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgIyBJUHY2CiAgICAgICAgICAgICAgICBpZiAoJElwT3B0aW9uIC1tYXRjaCAiXigoKD89KD8+Lio/OjopKD8hLio6OikpKSg6Oik/KFswLTlBLUZdezEsNH06Oj8pezAsNX18KFswLTlBLUZdezEsNH06KXs2fSkoXDIoWzAtOUEtRl17MSw0fSg6Oj98JCkpezAsMn18KCgyNVswLTVdfCgyWzAtNF18MVxkfFsxLTldKT9cZCkoXC58JCkpezR9fFswLTlBLUZdezEsNH06WzAtOUEtRl17MSw0fSkoPzwhW146XTp8XC4pXHoiKSB7CiAgICAgICAgICAgICAgICAgICAgJENvbnZlcnRlZE9wdHMgPSAkQ29udmVydGVkT3B0cyArICIoICQoQ29udmVydFRvLVNRTFN0cmluZyAkSXBPcHRpb24pICkiCiAgICAgICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRocm93ICJNYWxmb3JtZWQgSVB2NC9JUHY2IGFkZHJlc3M6ICRJcE9wdGlvbiIKICAgICAgICAgICAgfQogICAgICAgICAgICAkTGlzdGVuZXJBZGRyID0gIklQICggJCgkQ29udmVydGVkT3B0cyAtam9pbiAnLCAnKSApIgogICAgICAgIH0KICAgIH0KICAgIGlmICgoJExpc3RlbmVyRGVmWyJOQU1FIl0gLWVxICRudWxsKSAtb3IgKCRMaXN0ZW5lckRlZlsiTkFNRSJdIC1tYXRjaCAiXlxzKiQiKSkgewogICAgICAgIHRocm93ICJMaXN0ZW5lciBuYW1lIGlzIHJlcXVpcmVkIgogICAgfQogICAgaWYgKC1ub3QgKCRMaXN0ZW5lckRlZlsiTkFNRSJdIC1tYXRjaCAiXltBLVphLXowLTlcLl9cLV0rJCIpKSB7CiAgICAgICAgdGhyb3cgIklsbGVnYWwgbGlzdGVuZXIgbmFtZS4gSXQgY2FuIGNvbnRhaW4gb25seSBhbHBoYW51bWVyaWMgY2hhcmFjdGVycywgZGFzaGVzICgtKSwgYW5kIGh5cGhlbnMgKF8pLCBpbiBhbnkgb3JkZXIuIgogICAgfQogICAgJFBvcnQgPSAkbnVsbAogICAgaWYgKCRMaXN0ZW5lckRlZlsiUE9SVCJdIC1uZSAkbnVsbCkgewogICAgICAgIGlmICgkTGlzdGVuZXJEZWZbIlBPUlQiXSAtbWF0Y2ggIlxkK1wrIikgewogICAgICAgICAgICAkU3RhcnRpbmdQb3J0ID0gJExpc3RlbmVyRGVmWyJQT1JUIl0gLXJlcGxhY2UgIlwrIiwgIiIKICAgICAgICAgICAgJFBvcnQgPSBHZXQtTmV4dEZyZWVQb3J0ICRTdGFydGluZ1BvcnQKICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICRMaXN0ZW5lckFkZHIgKyAiLCBQT1JUID0gJFBvcnQiCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKCRMaXN0ZW5lckRlZlsiUE9SVCJdIC1tYXRjaCAiXGQrIikgewogICAgICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICRMaXN0ZW5lckFkZHIgKyAiLCBQT1JUID0gJCgkTGlzdGVuZXJEZWZbIlBPUlQiXSkiCiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyAiSW52YWxpZCBwb3J0IHZhbHVlOiAkKCRMaXN0ZW5lckRlZlsiUE9SVCJdKSIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgICRMaXN0ZW5lciA9ICJMSVNURU5FUiAnJCgkTGlzdGVuZXJEZWZbIk5BTUUiXSknICggV0lUSCAkTGlzdGVuZXJBZGRyICkiCgogICAgJE5hbWUgfCBPdXQtRmlsZSAiJFdvcmtEaXJcYXZncm91cC5uYW1lIgogICAgCiAgICBmb3IgKCRpID0gMDsgJGkgLWx0ICREYXRhYmFzZU5hbWVzLkxlbmd0aDsgJGkrKykgewogICAgICAgICREYXRhQmFzZU5hbWUgPSAkRGF0YWJhc2VOYW1lc1skaV0KICAgICAgICAkRGF0YUJhc2VOYW1lIHwgT3V0LUZpbGUgIiRXb3JrRGlyXGRiJGkubmFtZSIKICAgICAgICBOZXctU1FMRGF0YWJhc2UgJERhdGFCYXNlTmFtZQogICAgICAgICRCYWNrdXBEYiA9ICJCQUNLVVAgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcZGIkaS5iYWsiKSBXSVRIIE5PRk9STUFULCBJTklULCBOQU1FID0gTidGdWxsIERhdGFiYXNlIEJhY2t1cCcsIFNLSVAsIE5PUkVXSU5ELCBOT1VOTE9BRCwgU1RBVFMgPSAxMAogICAgICAgICAgICAgICAgICAgICBHTyIKICAgICAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwRGIpCiAgICAgICAgJEJhY2t1cExvZyA9ICJCQUNLVVAgTE9HICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgVE8gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXGRiJHtpfS5sb2cuYmFrIikgV0lUSCBOT0ZPUk1BVCwgSU5JVCwgIE5BTUUgPSBOJ1RyYW5zYWN0aW9uIExvZyAgQmFja3VwJywgU0tJUCwgTk9SRVdJTkQsIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgICAgICBHTyIKICAgICAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwTG9nKQogICAgfQogICAgJFJlcGxpY2FEZWZpbml0aW9uc0FycmF5ID0gQCgpCiAgICBpZiAoJFByZWZzLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICRQcmVmc0xpbmUgPSAiV0lUSCAoICQoJFByZWZzIC1qb2luICcsICcpICkiCiAgICB9IGVsc2UgewogICAgICAgICRQcmVmc0xpbmUgPSAiIgogICAgfQogICAgJFNRTCA9ICJDUkVBVEUgQVZBSUxBQklMSVRZIEdST1VQICQoQ29udmVydFRvLVNRTE5hbWUgJE5hbWUpICRQcmVmc0xpbmUKICAgICAgICAgICAgICAgIEZPUiBEQVRBQkFTRSAkUXVvdGVkREJOYW1lcwogICAgICAgICAgICAgICAgUkVQTElDQSBPTmByYG4gICAgICAgICRSZXBsaWNhRGVmaW5pdGlvbnMKICAgICAgICAgICAgICAgICRMaXN0ZW5lcjsKICAgICIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRTUUwpCiAgICByZXR1cm4gJFBvcnQKfQoKZnVuY3Rpb24gTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXBSZXBsaWNhIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgQWx3YXlzT24gYXZhaWxhYmlsaXR5IGdyb3VwIHNlY29uZGFyeSByZXBsaWNhCgogICAgLkRFU0NSSVBUSU9OCiAgICBDcmVhdGVzIEFsd2F5c09uIGF2YWlsYWJpbGl0eSBncm91cCBzZWNvbmRhcnkgcmVwbGljYSBiYXNlZCBvbiBpbmZvcm1hdGlvbiBwcm92aWRlZCB0byBhbmQgYnkgTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXAuCgogICAgLlBBUkFNRVRFUiBXb3JrRGlyCiAgICBXb3JraW5nIGRpcmVjdG9yeSB3aGljaCB3YXMgdHJhbnNmZXJyZWQgZnJvbSB0aGUgcHJpbWFyeSByZXBsaWNhLgogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFdvcmtEaXIKICAgICkKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIldvcmsgZGlyICckV29ya0Rpcicgbm90IGZvdW5kIgogICAgfQogICAgJFdvcmtEaXJPYmogPSBHZXQtSXRlbSAtUGF0aCAkV29ya0RpcgogICAgJFdvcmtEaXIgPSAkV29ya0Rpck9iai5GdWxsTmFtZQogICAgJEdyb3VwTmFtZSA9IEdldC1Db250ZW50ICRXb3JrRGlyT2JqLkdldEZpbGVzKCJhdmdyb3VwLm5hbWUiKS5GdWxsTmFtZQoKICAgICRKb2luR3JvdXAgPSAiQUxURVIgQVZBSUxBQklMSVRZIEdST1VQICQoQ29udmVydFRvLVNRTE5hbWUgJEdyb3VwTmFtZSkgSk9JTgogICAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkSm9pbkdyb3VwKQoKICAgIGZvciAoJGkgPSAwOyA7ICRpKyspIHsKICAgICAgICAkRmlsZSA9ICRXb3JrRGlyT2JqLkdldEZpbGVzKCJkYiRpLm5hbWUiKQogICAgICAgIGlmICgtbm90ICRGaWxlKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICAkRGF0YUJhc2VOYW1lID0gR2V0LUNvbnRlbnQgJFdvcmtEaXJPYmouR2V0RmlsZXMoImRiJGkubmFtZSIpLkZ1bGxOYW1lCiAgICAgICAgJFJlc3RvcmVEYiA9ICJSRVNUT1JFIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgRlJPTSBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcZGIkaS5iYWsiKSBXSVRIIEZJTEUgPSAxLCBOT1JFQ09WRVJZLCBOT1VOTE9BRCwgUkVQTEFDRSwgU1RBVFMgPSA1CiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVEYikKICAgICAgICAkUmVzdG9yZUxvZyA9ICJSRVNUT1JFIExPRyAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIEZST00gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXGRiJGkubG9nLmJhayIpIFdJVEggRklMRSA9IDEsIE5PUkVDT1ZFUlksIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVMb2cpCiAgICAgICAgJEFsdGVyREIgPSAiQUxURVIgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBTRVQgSEFEUiBBVkFJTEFCSUxJVFkgR1JPVVAgPSAkKENvbnZlcnRUby1TUUxOYW1lICRHcm91cE5hbWUpCiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJEFsdGVyREIpCiAgICB9Cn0KCmZ1bmN0aW9uIE5ldy1SZXBsaWNhT3B0aW9uIHsKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSwgVmFsdWVGcm9tUGlwZWxpbmUgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kVmFsdWUKICAgICkKICAgIHJldHVybiAiJE5hbWUgPSAkVmFsdWUiCn0KCmZ1bmN0aW9uIFZhbGlkYXRlLU9wdGlvbiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDaGVja3MgdGhhdCB0aGUgdmFsdWUgaXMgb25lIG9mIGFsbG93ZWQgdmFsdWVzCgogICAgLkRFU0NSSVBUSU9OCiAgICBDaGVja3MgdGhhdCB0aGUgdmFsdWUgaXMgb25lIG9mIGFsbG93ZWQgdmFsdWVzIG9yIHRocm93cyBleGNlcHRpb24gb3RoZXJ3aXNlLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCgogICAgLlBBUkFNRVRFUiBBbGxvd2VkCiAgICBMaXN0IG9mIGFsbG93ZWQgb3B0aW9uIHZhbHVzLgogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJE5hbWUsCiAgICAgICAgW1N0cmluZ10kVmFsdWUsCiAgICAgICAgW0FycmF5XSRBbGxvd2VkCiAgICApCiAgICBpZiAoKCRWYWx1ZSAtZXEgJG51bGwpIC1vciAoJFZhbHVlIC1lcSAiIikpIHsKICAgICAgICB0aHJvdyAiTm8gdmFsdWUgd2FzIHByb3ZpZGVkIGZvciAkTmFtZSIKICAgIH0KICAgIGZvcmVhY2ggKCRWIGluICRBbGxvd2VkKSB7CiAgICAgICAgaWYgKCRWIC1lcSAkVmFsdWUpIHsKICAgICAgICAgICAgcmV0dXJuICRWYWx1ZQogICAgICAgIH0KICAgIH0KICAgIHRocm93ICJQcm92aWRlZCB2YWx1ZSAnJFZhbHVlJyBmb3IgJE5hbWUgaXMgbm90IG9uZSBvZiAkKCRBbGxvd2VkIC1qb2luICcsICcpIgp9CgpmdW5jdGlvbiBWYWxpZGF0ZS1JbnRPcHRpb24gewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ2hlY2tzIHRoYXQgdGhlIHZhbHVlIGlzIGludGVnZXIKCiAgICAuREVTQ1JJUFRJT04KICAgIENoZWNrcyB0aGF0IHRoZSB2YWx1ZSBpcyBpbnRlZ2VyLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kTmFtZSwKICAgICAgICBbcGFyYW1ldGVyXQogICAgICAgIFtTdHJpbmddJFZhbHVlCiAgICApCiAgICBpZiAoKCRWYWx1ZSAtZXEgJG51bGwpIC1vciAoJFZhbHVlIC1lcSAiIikpIHsKICAgICAgICB0aHJvdyAiTm8gdmFsdWUgd2FzIHByb3ZpZGVkIGZvciAkTmFtZSIKICAgIH0KICAgIGlmICgtbm90ICgiJFZhbHVlIiAtbWF0Y2ggIl5bKy1dP1xkKyQiKSkgewogICAgICAgIHRocm93ICJQcm92aWRlZCB2YWx1ZSAnJFZhbHVlJyBmb3IgJE5hbWUgaXMgbm90IGEgbnVtYmVyIgogICAgfQogICAgcmV0dXJuICRWYWx1ZQp9CgpmdW5jdGlvbiBWYWxpZGF0ZS1EZWZpbmVkT3B0aW9uIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENoZWNrcyB0aGF0IHRoZSB2YWx1ZSBpcyBub3QgbnVsbAoKICAgIC5ERVNDUklQVElPTgogICAgQ2hlY2tzIHRoYXQgdGhlIHZhbHVlIGlzIG5vdCBudWxsLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kTmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICRmYWxzZSldCiAgICAgICAgW1N0cmluZ10kVmFsdWUKICAgICkKICAgIGlmICgoJFZhbHVlIC1lcSAkbnVsbCkgLW9yICgkVmFsdWUgLWVxICIiKSkgewogICAgICAgIHRocm93ICJObyB2YWx1ZSB3YXMgcHJvdmlkZWQgZm9yICROYW1lIgogICAgfQogICAgcmV0dXJuICRWYWx1ZQp9CgoKCg==", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgpmdW5jdGlvbiBFeHBvcnQtRnVuY3Rpb24gewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmdbXV0gJE5hbWUsCgogICAgICAgIFtQYXJhbWV0ZXIoVmFsdWVGcm9tUGlwZWxpbmU9JHRydWUpXQogICAgICAgIFtTdHJpbmddICRQYXRoID0gW0lPLlBhdGhdOjpHZXRUZW1wRmlsZU5hbWUoKSwKCiAgICAgICAgW1N3aXRjaF0gJEFsbAogICAgKQoKICAgIGlmIChbSU8uUGF0aF06OkdldEV4dGVuc2lvbigkUGF0aCkgLW5lICdwczEnKSB7CiAgICAgICAgJG51bGwgPSBSZW5hbWUtSXRlbSAtUGF0aCAkUGF0aCAtTmV3TmFtZSAiJFBhdGgucHMxIiAtRm9yY2UKICAgICAgICAkUGF0aCA9ICIkUGF0aC5wczEiCiAgICB9CgogICAgJFN5c3RlbUZ1bmN0aW9ucyA9IEAoCiAgICAgICAgJ0E6JywgJ0I6JywgJ0M6JywgJ0Q6JywgJ0U6JywgJ0Y6JywgJ0c6JywgJ0g6JywgJ0k6JywgJ0o6JywKICAgICAgICAnSzonLCAnTDonLCAnTTonLCAnTjonLCAnTzonLCAnUDonLCAnUTonLCAnUjonLCAnUzonLCAnVDonLAogICAgICAgICdVOicsICdWOicsICdXOicsICdYOicsICdZOicsICdaOicsCiAgICAgICAgJ2NkLi4nLCAnY2RcJywgJ2hlbHAnLCAnbWtkaXInLCAnbW9yZScsICdvc3MnLCAncHJvbXB0JywKICAgICAgICAnQ2xlYXItSG9zdCcsICdHZXQtVmVyYicsICdQYXVzZScsICdUYWJFeHBhbnNpb24yJwogICAgKQoKICAgIGlmICgkQWxsKSB7CiAgICAgICAgR2V0LUNoaWxkSXRlbSBGdW5jdGlvbjogfAogICAgICAgICAgICBXaGVyZS1PYmplY3QgeyRfLk1vZHVsZU5hbWUgLWVxICcnfSB8CiAgICAgICAgICAgIFdoZXJlLU9iamVjdCB7JFN5c3RlbUZ1bmN0aW9ucyAtbm90Y29udGFpbnMgJF8uTmFtZX0gfAogICAgICAgICAgICBGb3JFYWNoLU9iamVjdCB7CiAgICAgICAgICAgICAgICBBZGQtQ29udGVudCAtUGF0aCAkUGF0aCAtVmFsdWUgQCIKCgpmdW5jdGlvbiAkKCRfLk5hbWUpIHsKJCgkXy5TY3JpcHRCbG9jaykKfQoKIkAKICAgICAgICAgICAgfQogICAgfQogICAgZWxzZSB7CiAgICAgICAgZm9yZWFjaCAoJEZ1bmN0aW9uTmFtZSBpbiAkTmFtZSkgewogICAgICAgICAgICAkRnVuY3Rpb25PYmplY3QgPSBHZXQtQ2hpbGRJdGVtICJGdW5jdGlvbjpcJEZ1bmN0aW9uTmFtZSIKICAgICAgICAgICAgaWYgKCRGdW5jdGlvbk9iamVjdCAtbmUgJG51bGwpIHsKICAgICAgICAgICAgICAgIEFkZC1Db250ZW50IC1QYXRoICRQYXRoIC1WYWx1ZSBAIgoKCmZ1bmN0aW9uICRGdW5jdGlvbk5hbWUgewokKCRGdW5jdGlvbk9iamVjdC5TY3JpcHRCbG9jaykKfQoKIkAKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gJFBhdGgKfQo=", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgoKCmZ1bmN0aW9uIFNlbGVjdC1DbGlYbWxCbG9jayB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJFBhdGgsCiAgICAgICAgW1N0cmluZ10gJE91dEZpbGUgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCiAgICApCgogICAgJFRhZ0ZvdW5kID0gJGZhbHNlCiAgICBHZXQtQ29udGVudCAkUGF0aCB8CiAgICAgICAgRm9yRWFjaC1PYmplY3QgewogICAgICAgICAgICBpZiAoJF8gLWVxICcjPCBDTElYTUwnKSB7CiAgICAgICAgICAgICAgICAkVGFnRm91bmQgPSAkdHJ1ZQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICgkVGFnRm91bmQpIHsKICAgICAgICAgICAgICAgIEFkZC1Db250ZW50IC1QYXRoICRPdXRGaWxlIC1WYWx1ZSAkXwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgJE91dEZpbGUKfQoKCgpmdW5jdGlvbiBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJENvbW1hbmQsCiAgICAgICAgJENyZWRlbnRpYWwgPSAkbnVsbCwKICAgICAgICBbU3dpdGNoXSAkSWdub3JlU3RkRXJyLAogICAgICAgIFtTd2l0Y2hdICROb0Jhc2U2NAogICAgKQogICAgYmVnaW4gewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbgogICAgfQogICAgZW5kIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24gLUVuZAogICAgfQogICAgcHJvY2VzcyB7CiAgICAgICAgdHJhcCB7CiAgICAgICAgICAgICYkVHJhcEhhbmRsZXIKICAgICAgICB9CgogICAgICAgICRTdGRPdXQgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCiAgICAgICAgJFN0ZEVyciA9IFtJTy5QYXRoXTo6R2V0VGVtcEZpbGVOYW1lKCkKCiAgICAgICAgJEFyZ3VtZW50TGlzdCA9IEAoJy1PdXRwdXRGb3JtYXQnLCAnWE1MJykKCiAgICAgICAgaWYgKCROb0Jhc2U2NCkgewogICAgICAgICAgICAkVG1wU2NyaXB0ID0gW0lPLlBhdGhdOjpHZXRUZW1wRmlsZU5hbWUoKQogICAgICAgICAgICBSZW5hbWUtSXRlbSAtUGF0aCAiJFRtcFNjcmlwdCIgLU5ld05hbWUgIiRUbXBTY3JpcHQucHMxIiAtRm9yY2UKICAgICAgICAgICAgJFRtcFNjcmlwdCA9ICIkVG1wU2NyaXB0LnBzMSIKCiAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICRUbXBTY3JpcHQKCiAgICAgICAgICAgICRDb21tYW5kIHwgT3V0LUZpbGUgJFRtcFNjcmlwdAoKICAgICAgICAgICAgJEFyZ3VtZW50TGlzdCArPSBAKCctRmlsZScsICIkVG1wU2NyaXB0IikKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICRCeXRlcyA9IFtUZXh0LkVuY29kaW5nXTo6VW5pY29kZS5HZXRCeXRlcygkQ29tbWFuZCkKICAgICAgICAgICAgJEVuY29kZWRDb21tYW5kID0gW0NvbnZlcnRdOjpUb0Jhc2U2NFN0cmluZygkQnl0ZXMpCiAgICAgICAgICAgIAogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAkRW5jb2RlZENvbW1hbmQKCiAgICAgICAgICAgICRBcmd1bWVudExpc3QgKz0gQCgnLUVuY29kZWRDb21tYW5kJywgJEVuY29kZWRDb21tYW5kKQogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nRGVidWcgJEFyZ3VtZW50TGlzdAoKICAgICAgICBXcml0ZS1Mb2cgIlN0YXJ0aW5nIGV4dGVybmFsIFBvd2VyU2hlbGwgcHJvY2VzcyAuLi4iCgogICAgICAgIGlmICgkQ3JlZGVudGlhbCAtZXEgJG51bGwpIHsKICAgICAgICAgICAgJFByb2Nlc3MgPSBTdGFydC1Qcm9jZXNzIC1GaWxlUGF0aCAncG93ZXJzaGVsbC5leGUnIGAKICAgICAgICAgICAgICAgIC1Bcmd1bWVudExpc3QgQCgkQXJndW1lbnRMaXN0KSBgCiAgICAgICAgICAgICAgICAtUmVkaXJlY3RTdGFuZGFyZE91dHB1dCAkU3RkT3V0IGAKICAgICAgICAgICAgICAgIC1SZWRpcmVjdFN0YW5kYXJkRXJyb3IgJFN0ZEVyciBgCiAgICAgICAgICAgICAgICAtTm9OZXdXaW5kb3cgYAogICAgICAgICAgICAgICAgLVdhaXQgYAogICAgICAgICAgICAgICAgLVBhc3NUaHJ1CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkUHJvY2VzcyA9IFN0YXJ0LVByb2Nlc3MgLUZpbGVQYXRoICdwb3dlcnNoZWxsLmV4ZScgYAogICAgICAgICAgICAgICAgLUFyZ3VtZW50TGlzdCBAKCRBcmd1bWVudExpc3QpIGAKICAgICAgICAgICAgICAgIC1SZWRpcmVjdFN0YW5kYXJkT3V0cHV0ICRTdGRPdXQgYAogICAgICAgICAgICAgICAgLVJlZGlyZWN0U3RhbmRhcmRFcnJvciAkU3RkRXJyIGAKICAgICAgICAgICAgICAgIC1DcmVkZW50aWFsICRDcmVkZW50aWFsIGAKICAgICAgICAgICAgICAgIC1Ob05ld1dpbmRvdyBgCiAgICAgICAgICAgICAgICAtV2FpdCBgCiAgICAgICAgICAgICAgICAtUGFzc1RocnUKICAgICAgICB9CgogICAgICAgIFdyaXRlLUxvZyAiRXh0ZXJuYWwgUG93ZXJTaGVsbCBwcm9jZXNzIGV4aXRlZCB3aXRoIGV4aXQgY29kZSAnJCgkUHJvY2Vzcy5FeGl0Q29kZSknLiIKCiAgICAgICAgI2lmICgkQXJndW1lbnRMaXN0IC1jb250YWlucyAnLUZpbGUnKSB7CiAgICAgICAgIyAgICBSZW1vdmUtSXRlbSAtUGF0aCAkVG1wU2NyaXB0IC1Gb3JjZQogICAgICAgICN9CgogICAgICAgICRFcnJvckFjdGlvblByZWZlcmVuY2VTYXZlZCA9ICRFcnJvckFjdGlvblByZWZlcmVuY2UKICAgICAgICAkRXJyb3JBY3Rpb25QcmVmZXJlbmNlID0gJ1NpbGVudGx5Q29udGludWUnCgogICAgICAgIFdyaXRlLUxvZ0RlYnVnICJTdGRPdXQgZmlsZSBpcyAnJFN0ZE91dCciCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIlN0ZEVyciBmaWxlIGlzICckU3RkRXJyJyIKCiAgICAgICAgaWYgKChHZXQtSXRlbSAkU3RkT3V0KS5MZW5ndGggLWd0IDApIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICJMb2FkaW5nIFN0ZE91dCBmcm9tICckU3RkT3V0JyIKICAgICAgICAgICAgICAgICRUbXBGaWxlID0gU2VsZWN0LUNsaVhtbEJsb2NrICRTdGRPdXQKICAgICAgICAgICAgICAgICRTdGRPdXRPYmplY3QgPSBJbXBvcnQtQ2xpeG1sICRUbXBGaWxlCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPFN0ZE91dD4iCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAoJFN0ZE91dE9iamVjdCkKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L1N0ZE91dD4iCiAgICAgICAgICAgICAgICAkU3RkT3V0T2JqZWN0CiAgICAgICAgICAgICAgICAjUmVtb3ZlLUl0ZW0gLVBhdGggJFRtcEZpbGUgLUZvcmNlCiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2F0Y2ggewogICAgICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIkFuIGVycm9yIG9jY3VyZWQgd2hpbGUgbG9hZGluZyBTdGRPdXQgZnJvbSAnJFRtcEZpbGUnIgogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBpZiAoKEdldC1JdGVtICRTdGRFcnIpLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIkxvYWRpbmcgU3RkRXJyIC4uLiIKICAgICAgICAgICAgICAgICRUbXBGaWxlID0gU2VsZWN0LUNsaVhtbEJsb2NrICRTdGRFcnIKICAgICAgICAgICAgICAgICRTdGRFcnJPYmplY3QgPSBJbXBvcnQtQ2xpeG1sICRUbXBGaWxlCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPFN0ZEVycj4iCiAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAoJFN0ZEVyck9iamVjdCkKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L1N0ZEVycj4iCiAgICAgICAgICAgICAgICBpZiAoLW5vdCAkSWdub3JlU3RkRXJyKSB7CiAgICAgICAgICAgICAgICAgICAgJFN0ZEVyck9iamVjdAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgI1JlbW92ZS1JdGVtIC1QYXRoICRUbXBGaWxlIC1Gb3JjZQogICAgICAgICAgICB9CiAgICAgICAgICAgIGNhdGNoIHsKICAgICAgICAgICAgICAgIFdyaXRlLUxvZ0RlYnVnICJBbiBlcnJvciBvY2N1cmVkIHdoaWxlIGxvYWRpbmcgU3RkRXJyIGZyb20gJyRUbXBGaWxlJyIKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICRFcnJvckFjdGlvblByZWZlcmVuY2VTYXZlZAoKICAgICAgICBpZiAoJFByb2Nlc3MuRXhpdENvZGUgLW5lIDApIHsKICAgICAgICAgICAgdGhyb3coIkV4dGVybmFsIFBvd2VyU2hlbGwgcHJvY2VzcyBleGl0ZWQgd2l0aCBjb2RlICckKCRQcm9jZXNzLkV4aXRDb2RlKSciKQogICAgICAgIH0KCiAgICAgICAgI1JlbW92ZS1JdGVtICRTdGRPdXQgLUZvcmNlCiAgICAgICAgI1JlbW92ZS1JdGVtICRTdGRFcnIgLUZvcmNlCiAgICB9Cn0K", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlclBvd2VyU2hlbGxNb2R1bGUgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJwogICAgKQogICAgYmVnaW4gewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbgogICAgfQogICAgZW5kIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24gLUVuZAogICAgfQogICAgcHJvY2VzcyB7CiAgICAgICAgdHJhcCB7CiAgICAgICAgICAgICYkVHJhcEhhbmRsZXIKICAgICAgICB9CgogICAgICAgIGlmICgoR2V0LU1vZHVsZSBTUUxQUyAtTGlzdEF2YWlsYWJsZSkgLW5lICRudWxsKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiTW9kdWxlIFNRTFNQIGFscmVhZHkgaW5zdGFsbGVkLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcVG9vbHMnKQogICAgICAgIH0KICAgICAgICAKICAgICAgICAkRmlsZUxpc3QgPSBAKAogICAgICAgICAgICAnU1FMU3lzQ2xyVHlwZXMubXNpJywKICAgICAgICAgICAgJ1NoYXJlZE1hbmFnZW1lbnRPYmplY3RzLm1zaScsCiAgICAgICAgICAgICdQb3dlclNoZWxsVG9vbHMubXNpJwogICAgICAgICkKCiAgICAgICAgZm9yZWFjaCAoJE1zaUZpbGUgaW4gJEZpbGVMaXN0KSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVHJ5aW5nIHRvIGluc3RhbGwgJyRNc2lGaWxlJyAuLi4iCiAgICAgICAgICAgICRNc2lQYXRoID0gSm9pbi1QYXRoICRTZXR1cFJvb3QgJE1zaUZpbGUKICAgICAgICAgICAgaWYgKFtJTy5GaWxlXTo6RXhpc3RzKCRNc2lQYXRoKSkgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJTdGFydGluZyBtc2lleGUgLi4uIgogICAgICAgICAgICAgICAgJFJlc3VsdCA9IEV4ZWMgLUZpbGVQYXRoICJtc2lleGVjLmV4ZSIgLUFyZ3VtZW50TGlzdCBAKCcvaScsICJgIiRNc2lQYXRoYCIiLCAnL3F1aWV0JykgLVBhc3NUaHJ1CiAgICAgICAgICAgICAgICBpZiAoJFJlc3VsdC5FeGl0Q29kZSAtbmUgMCkgewogICAgICAgICAgICAgICAgICAgIHRocm93ICgiSW5zdGFsbGF0aW9uIG9mIE1TSSBwYWNrYWdlICckTXNpUGF0aCcgZmFpbGVkIHdpdGggZXJyb3IgY29kZSAnJCgkUmVzdWx0LkV4aXRDb2RlKSciKQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJGaWxlICckTXNpUGF0aCcgbm90IGZvdW5kLiIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQoKCgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgUGF0aCB0byBmb2xkZXIgd2hlcmUgbXNpIGZpbGVzIGZvciBhZGRpdGlvbmFsIFNRTCBmZWF0dXJlcyBhcmUgbG9jYXRlZAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJywKCiAgICAgICAgIyBQYXRoIHRvIGZvbGRlciB3aGVyZSBtc2kgZmlsZXMgZm9yIGFkZGl0aW9uYWwgU1FMUFMgbW9kdWxlIGFyZSBsb2NhdGVkCiAgICAgICAgW1N0cmluZ10gJFNxbHBzU2V0dXBSb290ID0gJycsCgogICAgICAgIFtTdHJpbmddICRNdXJhbm9GaWxlU2hhcmUgPSAnJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIERvbWFpbiBuYW1lCiAgICAgICAgW1N0cmluZ10gJFNRTFNlcnZpY2VVc2VyRG9tYWluID0gJ2ZjLWFjbWUubG9jYWwnLAoKICAgICAgICAjIChSRVFVSVJFRCkgVXNlciBuYW1lIGZvciB0aGUgYWNjb3VudCB3aGljaCB3aWxsIGJlIHVzZWQgYnkgU1FMIHNlcnZpY2UKICAgICAgICBbU3RyaW5nXSAkU1FMU2VydmljZVVzZXJOYW1lID0gJ0FkbWluaXN0cmF0b3InLAoKICAgICAgICAjIChSRVFVSVJFRCkgUGFzc3dvcmQgZm9yIHRoYXQgdXNlcgogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlclBhc3N3b3JkID0gJ1BAc3N3MHJkJywKCiAgICAgICAgW1N3aXRjaF0gJFVwZGF0ZUVuYWJsZWQKICAgICkKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcMjAxMicpCiAgICAgICAgfQoKICAgICAgICAkRXh0cmFPcHRpb25zID0gQHt9CgogICAgICAgIGlmICgkVXBkYXRlRW5hYmxlZCkgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJHRydWV9CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJGZhbHNlfQogICAgICAgIH0KCiAgICAgICAgTmV3LVNRTFNlcnZlckZvckFPQUcgYAogICAgICAgICAgICAtU2V0dXBSb290ICRTZXR1cFJvb3QgYAogICAgICAgICAgICAtU1FMU3ZjVXNyRG9tYWluICRTUUxTZXJ2aWNlVXNlckRvbWFpbiBgCiAgICAgICAgICAgIC1TUUxTdmNVc3JOYW1lICRTUUxTZXJ2aWNlVXNlck5hbWUgYAogICAgICAgICAgICAtU1FMU3ZjVXNyUGFzc3dvcmQgJFNRTFNlcnZpY2VVc2VyUGFzc3dvcmQgYAogICAgICAgICAgICAtRXh0cmFPcHRpb25zICRFeHRyYU9wdGlvbnMKICAgIH0KfQoKCgpmdW5jdGlvbiBJbml0aWFsaXplLUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXAgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnRQYXNzd29yZCwKICAgICAgICBbU3RyaW5nXSAkU3FsU2VydmljZUFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICRQcmltYXJ5Tm9kZSwKICAgICAgICBbU3RyaW5nXSAkU2hhcmVOYW1lID0gJ1NoYXJlZFdvcmtEaXInCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgJFNoYXJlTmV0d29ya1BhdGggPSAnXFwnICsgJFByaW1hcnlOb2RlICsgJ1wnICsgJFNoYXJlTmFtZQoKICAgICAgICAkRG9tYWluQWRtaW5BY2NvdW50Q3JlZHMgPSBOZXctQ3JlZGVudGlhbCBgCiAgICAgICAgICAgIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJERvbWFpbkFkbWluQWNjb3VudE5hbWUiIGAKICAgICAgICAgICAgLVBhc3N3b3JkICIkRG9tYWluQWRtaW5BY2NvdW50UGFzc3dvcmQiCgogICAgICAgICRGdW5jdGlvbnNGaWxlID0gRXhwb3J0LUZ1bmN0aW9uICdHZXQtTmV4dEZyZWVQb3J0JywgJ0luaXRpYWxpemUtQWx3YXlzT24nCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICBgJF8KICAgIGV4aXQgMQp9CgpJbXBvcnQtTW9kdWxlIENvcmVGdW5jdGlvbnMKCldyaXRlLUxvZyAiSW1wb3J0aW5nIGZ1bmN0aW9ucyBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ0luaXRpYWxpemUtQWx3YXlzT24nIC4uLiIKYCRYbWxGaWxlID0gW0lPLlBhdGhdOjpDb21iaW5lKCIkU2hhcmVOZXR3b3JrUGF0aCIsICJgJChgJEVudjpDb21wdXRlck5hbWUpLnhtbCIpCldyaXRlLUxvZyAiT3V0cHV0IFhNTCBmaWxlIGlzICdgJFhtbEZpbGUnIgpJbml0aWFsaXplLUFsd2F5c09uIHwgRXhwb3J0LUNsaVhtbCAtUGF0aCBgJFhtbEZpbGUKIkAgLUNyZWRlbnRpYWwgJERvbWFpbkFkbWluQWNjb3VudENyZWRzIC1Ob0Jhc2U2NAogICAgfQp9CgoKZnVuY3Rpb24gTmV3LVNoYXJlZEZvbGRlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKQogICAgICAgIFtTdHJpbmddICRTaGFyZVBhdGggPSBbSU8uUGF0aF06OkNvbWJpbmUoJEVudjpTeXN0ZW1Ecml2ZSArICdcJywgJ1NoYXJlZFdvcmtEaXInKSwKCiAgICAgICAgIyAoT1BUSU9OQUwpCiAgICAgICAgW1N0cmluZ10gJFNoYXJlTmFtZSA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlID0gJyAnCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBzY3JpcHQgcnVucyBvbiBwcmltYXJ5IG5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZyBzY3JpcHQuIgogICAgICAgICAgICByZXR1cm4KICAgICAgICB9CgogICAgICAgIGlmICgkU2hhcmVOYW1lIC1lcSAnJykgewogICAgICAgICAgICAkU2hhcmVOYW1lID0gW0lPLlBhdGhdOjpHZXRGaWxlTmFtZVdpdGhvdXRFeHRlbnNpb24oJFNoYXJlUGF0aCkKICAgICAgICB9CgogICAgICAgIFdyaXRlLUxvZ0RlYnVnICJTaGFyZVBhdGggPSAnJFNoYXJlUGF0aCciCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIlNoYXJlTmFtZSA9ICckU2hhcmVOYW1lJyIKCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgc2hhcmUgJyRTaGFyZU5hbWUnIgogICAgICAgICAgICAkbnVsbCA9IEdldC1TbWJTaGFyZSAtTmFtZSAkU2hhcmVOYW1lIC1FcnJvckFjdGlvbiAnU3RvcCcKICAgICAgICAgICAgJG51bGwgPSBSZW1vdmUtU21iU2hhcmUgLU5hbWUgJFNoYXJlTmFtZSAtRm9yY2UKICAgICAgICAgICAgd3JpdGUtTG9nICJTaGFyZSAnJFNoYXJlTmFtZScgcmVtb3ZlZC4iCiAgICAgICAgfQogICAgICAgIGNhdGNoIHsKICAgICAgICAgICAgV3JpdGUtTG9nV2FybmluZyAiU2hhcmUgJyRTaGFyZU5hbWUnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgZm9sZGVyICckU2hhcmVQYXRoIgogICAgICAgICAgICAkbnVsbCA9IEdldC1JdGVtIC1QYXRoICRTaGFyZVBhdGggLUVycm9yQWN0aW9uICdTdG9wJwogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICRTaGFyZVBhdGggLVJlY3Vyc2UgLUZvcmNlCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRm9sZGVyICckU2hhcmVQYXRoJyByZW1vdmVkLiIKICAgICAgICB9CiAgICAgICAgY2F0Y2ggewogICAgICAgICAgICBXcml0ZS1Mb2dXYXJuaW5nICJGb2xkZXIgJyRTaGFyZVBhdGgnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgJG51bGwgPSBOZXctSXRlbSAtUGF0aCAkU2hhcmVQYXRoIC1JdGVtVHlwZSBDb250YWluZXIgLUZvcmNlCiAgICAgICAgICAgICAgICAKICAgICAgICAkbnVsbCA9IE5ldy1TbWJTaGFyZSAtUGF0aCAkU2hhcmVQYXRoIGAKICAgICAgICAgICAgLU5hbWUgJFNoYXJlTmFtZSBgCiAgICAgICAgICAgIC1GdWxsQWNjZXNzICJFdmVyeW9uZSIgYAogICAgICAgICAgICAtRGVzY3JpcHRpb24gIlNoYXJlZCBmb2xkZXIgZm9yIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cCBzZXR1cC4iCgogICAgICAgIHJldHVybiAnXFwnICsgJEVudjpDb21wdXRlck5hbWUgKyAnXCcgKyAkU2hhcmVOYW1lCiAgICB9Cn0KCgoKZnVuY3Rpb24gTmV3LURhdGFiYXNlRm9yQU9BRyB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJERhdGFiYXNlTmFtZSwKICAgICAgICBbU3RyaW5nXSAkRG9tYWluTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlck5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJQYXNzd29yZAogICAgKQoKICAgICRDcmVkcyA9IE5ldy1DcmVkZW50aWFsIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJFVzZXJOYW1lIiAtUGFzc3dvcmQgIiRVc2VyUGFzc3dvcmQiCgogICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gJ0ludm9rZS1TUUxUZXh0JywgJ0NvbnZlcnRUby1TUUxOYW1lJywgJ0NvbnZlcnRUby1TUUxTdHJpbmcnLCAnTmV3LVNRTERhdGFiYXNlJwoKICAgIFN0YXJ0LVBvd2VyU2hlbGxQcm9jZXNzIEAiCnRyYXAgewogICAgYCRfCiAgICBleGl0IDEKfQoKSW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zCgpXcml0ZS1Mb2cgIkltcG9ydGluZyBmdW5jdGlvbnMgZnJvbSBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1TUUxEYXRhYmFzZScgLi4uIgpOZXctU1FMRGF0YWJhc2UgJERhdGFiYXNlTmFtZQoiQCAtQ3JlZGVudGlhbCAkQ3JlZHMgLU5vQmFzZTY0Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHUHJpbWFyeVJlcGxpY2EgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKSBOYW1lIG9mIHRoZSBuZXcgQXZhaWxhYmlsaXR5IEdyb3VwLiBJZiBub3Qgc3BlY2lmaWVkIHRoZW4gZGVmYXVsdCBuYW1lIHdpbGwgYmUgdXNlZC4KICAgICAgICBbU3RyaW5nXSAkR3JvdXBOYW1lID0gJ011cmFub0FHJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICROb2RlTGlzdCwKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGUgbmFtZSB0aGF0IHdpbGwgYmUgcHJpbWFyeSBmb3Igc2VsZWN0ZWQgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nXSAkUHJpbWFyeU5vZGUsCgogICAgICAgICMgKFJFUVVJUkVEKSBEYXRhYmFzZSBsaXN0IHRoYXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICREYXRhYmFzZUxpc3QsCgogICAgICAgICMgKFJFUVVJUkVEKSBMaXN0ZW5lciBuYW1lIHRoYXQgd2lsbCBiZSB1c2VkIGJ5IGNsaWVudHMgdG8gY29ubmVjdCB0byBkYXRhYmFzZXMgaW4gdGhhdCBBRwogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyTmFtZSA9ICdNdXJhbm9BR19MaXN0ZW5lcicsCgogICAgICAgICMgKFJFUVVJUkVEKSBJUCBhZGRyZXNzIG9mIHRoZSBsaXN0ZW5lcgogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVySVAsCgogICAgICAgIFtTdHJpbmddICRMaXN0ZW5lcklQTWFzayA9ICcyNTUuMjU1LjI1NS4wJywKCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyUG9ydCA9ICc1MDIzJywKCiAgICAgICAgIyBTeW5jIE1vZGUgTm9kZSBMaXN0CiAgICAgICAgW1N0cmluZ1tdXSAkU3luY01vZGVOb2RlTGlzdCwKCiAgICAgICAgW1N0cmluZ10gJFNoYXJlZFdvcmtEaXIgPSAnU2hhcmVkV29ya0RpcicsCgogICAgICAgIFtTdHJpbmddICRDbGlYbWxGaWxlID0gJycsCgogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlclBhc3N3b3JkCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJQcmltYXJ5IG5vZGU6ICckKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkpJyIKICAgICAgICBXcml0ZS1Mb2cgIkN1cnJlbnQgbm9kZTogJyQoKCRFbnY6Q29tcHV0ZXJOYW1lKS5Ub0xvd2VyKCkpJyIKCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICQoJEVudjpDb21wdXRlck5hbWUpLlRvTG93ZXIoKSkgewogICAgICAgICAgICBXcml0ZS1Mb2cgIlRoaXMgZnVuY3Rpb24gd29ya3Mgb24gUHJpbWFyeU5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZy4iCiAgICAgICAgICAgIHJldHVybgogICAgICAgIH0KCiAgICAgICAgaWYgKCRDbGlYbWxGaWxlIC1lcSAnJykgewogICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ID0gQCgpCiAgICAgICAgICAgIGZvcmVhY2ggKCROb2RlIGluICROb2RlTGlzdCkgewogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAkTm9kZUVuZHBvaW50UG9ydCA9IEltcG9ydC1DbGlYbWwgLVBhdGggIlxcJFByaW1hcnlOb2RlXFNoYXJlZFdvcmtEaXJcJE5vZGUueG1sIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2F0Y2ggewogICAgICAgICAgICAgICAgICAgIFdyaXRlLUxvZyAiVXNpbmcgZGVmYXVsdCBlbmRwb2ludCBwb3J0IDUwMjIiCiAgICAgICAgICAgICAgICAgICAgJE5vZGVFbmRwb2ludFBvcnQgPSA1MDIyCiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uID0gQHsKICAgICAgICAgICAgICAgICAgICAiU0VSVkVSX0lOU1RBTkNFIiA9ICIkTm9kZSI7CiAgICAgICAgICAgICAgICAgICAgIkVORFBPSU5UX1VSTCIgPSAiVENQOi8vJHtOb2RlfToke05vZGVFbmRwb2ludFBvcnR9IjsKICAgICAgICAgICAgICAgICAgICAiQVZBSUxBQklMSVRZX01PREUiID0gIkFTWU5DSFJPTk9VU19DT01NSVQiOwogICAgICAgICAgICAgICAgICAgICJGQUlMT1ZFUl9NT0RFIj0iTUFOVUFMIjsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZiAoJFN5bmNNb2RlTm9kZUxpc3QgLWNvbnRhaW5zICROb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBpbiBTeW5jTW9kZU5vZGVMaXN0IgogICAgICAgICAgICAgICAgICAgICRSZXBsaWNhRGVmaW5pdGlvblsnQVZBSUxBQklMSVRZX01PREUnXSA9ICJTWU5DSFJPTk9VU19DT01NSVQiCiAgICAgICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uWydGQUlMT1ZFUl9NT0RFJ10gPSAiQVVUT01BVElDIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBOT1QgaW4gU3luY01vZGVOb2RlTGlzdCIKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ICs9IEAoJFJlcGxpY2FEZWZpbml0aW9uKQogICAgICAgICAgICB9CgogICAgICAgICAgICAkUHJlZmVyZW5jZXMgPSBAe30KCiAgICAgICAgICAgICRMaXN0ZW5lckRlZmluaXRpb24gPSBAewogICAgICAgICAgICAgICAgIk5BTUUiPSRMaXN0ZW5lck5hbWU7CiAgICAgICAgICAgICAgICAiUE9SVCIgPSAiJExpc3RlbmVyUG9ydCI7CiAgICAgICAgICAgICAgICAiU1RBVElDIiA9ICIkTGlzdGVuZXJJUC8kTGlzdGVuZXJJUE1hc2siCiAgICAgICAgICAgIH0KCiAgICAgICAgICAgICRQYXJhbWV0ZXJzID0gQHsKICAgICAgICAgICAgICAgICdXb3JrRGlyJyA9ICJcXCRQcmltYXJ5Tm9kZVwkU2hhcmVkV29ya0RpciI7CiAgICAgICAgICAgICAgICAnTmFtZScgPSAkR3JvdXBOYW1lOwogICAgICAgICAgICAgICAgJ0RhdGFiYXNlTmFtZXMnID0gJERhdGFiYXNlTGlzdDsKICAgICAgICAgICAgICAgICdSZXBsaWNhRGVmcycgPSAkUmVwbGljYURlZmluaXRpb25MaXN0OwogICAgICAgICAgICAgICAgJ1ByZWZlcmVuY2VzJyA9ICRQcmVmZXJlbmNlczsKICAgICAgICAgICAgICAgICdMaXN0ZW5lckRlZicgPSAkTGlzdGVuZXJEZWZpbml0aW9uOwogICAgICAgICAgICB9CgogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICJcXCRQcmltYXJ5Tm9kZVxTaGFyZWRXb3JrRGlyXCoiIC1Gb3JjZQoKICAgICAgICAgICAgJENsaVhtbEZpbGUgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiQ2xpWG1sIGZpbGU6ICckQ2xpWG1sRmlsZSciCgogICAgICAgICAgICAkbnVsbCA9IEV4cG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUgLUlucHV0T2JqZWN0ICRQYXJhbWV0ZXJzIC1EZXB0aCAxMAoKICAgICAgICAgICAgJG51bGwgPSBJbml0aWFsaXplLUFPQUdQcmltYXJ5UmVwbGljYSBgCiAgICAgICAgICAgICAgICAtQ2xpWG1sRmlsZSAkQ2xpWG1sRmlsZSBgCiAgICAgICAgICAgICAgICAtRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgCiAgICAgICAgICAgICAgICAtVXNlck5hbWUgJFVzZXJOYW1lIGAKICAgICAgICAgICAgICAgIC1Vc2VyUGFzc3dvcmQgJFVzZXJQYXNzd29yZCBgCiAgICAgICAgICAgICAgICAtUHJpbWFyeU5vZGUgJFByaW1hcnlOb2RlCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiSW5uZXIgJ0luaXRpYWxpemUtQU9BR1ByaW1hcnlSZXBsaWNhJyBjYWxsIGNvbXBsZXRlZC4iCiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAgICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gLUFsbAoKICAgICAgICAgICAgJG51bGwgPSBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyBAIgp0cmFwIHsKICAgIGAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJJbXBvcnRpbmcgQ2xpWG1sIHBhcmFtZXRlcnMgZmlsZSAuLi4iCmAkUGFyYW1ldGVycyA9IEltcG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwIGBgCiAgICAtV29ya0RpciBgJFBhcmFtZXRlcnNbJ1dvcmtEaXInXSBgYAogICAgLU5hbWUgYCRQYXJhbWV0ZXJzWydOYW1lJ10gYGAKICAgIC1EYXRhYmFzZU5hbWVzIGAkUGFyYW1ldGVyc1snRGF0YWJhc2VOYW1lcyddIGBgCiAgICAtUmVwbGljYURlZnMgYCRQYXJhbWV0ZXJzWydSZXBsaWNhRGVmcyddIGBgCiAgICAtUHJlZmVyZW5jZXMgYCRQYXJhbWV0ZXJzWydQcmVmZXJlbmNlcyddIGBgCiAgICAtTGlzdGVuZXJEZWYgYCRQYXJhbWV0ZXJzWydMaXN0ZW5lckRlZiddCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgICAgICB9CiAgICB9Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHU2Vjb25kYXJ5UmVwbGljYSB7CiAgICBwYXJhbSAoCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmdbXV0gJE5vZGVMaXN0LAoKICAgICAgICAjIChSRVFVSVJFRCkgTm9kZSBuYW1lIHRoYXQgd2lsbCBiZSBwcmltYXJ5IGZvciBzZWxlY3RlZCBBdmFpbGFiaWxpdHkgR3JvdXAKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlLAoKICAgICAgICBbU3RyaW5nXSAkU2hhcmVkV29ya0RpciA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJERvbWFpbk5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJOYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyUGFzc3dvcmQKICAgICkgCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLWVxICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBmdW5jdGlvbiB3b3JrcyBvbiBhbnkgU2Vjb25kYXJ5Tm9kZSBvbmx5LiIKICAgICAgICAgICAgV3JpdGUtTG9nICJFeGl0aW5nLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAkRnVuY3Rpb25zRmlsZSA9IEV4cG9ydC1GdW5jdGlvbiAtQWxsCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJTdGFydGluZyAnTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXBSZXBsaWNhJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwUmVwbGljYSAtV29ya0RpciAiXFwkUHJpbWFyeU5vZGVcJFNoYXJlZFdvcmtEaXIiCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgIH0KfQoKCgpmdW5jdGlvbiBEaXNhYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb2ZmCiAgICB9Cn0KCgoKZnVuY3Rpb24gRW5hYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb24KICAgIH0KfQoKCgpmdW5jdGlvbiBFbmFibGUtVHJ1c3RlZEhvc3RzIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBTZXQtSXRlbSBXU01hbjpcbG9jYWxob3N0XENsaWVudFxUcnVzdGVkSG9zdHMgLVZhbHVlICcqJyAtRm9yY2UKICAgIH0KfQo=" ] } \ No newline at end of file diff --git a/data/templates/agent/SqlServerCluster/InstallSqlServerForAOAG.template b/data/templates/agent/SqlServerCluster/InstallSqlServerForAOAG.template index 7db0da2..658c50d 100644 --- a/data/templates/agent/SqlServerCluster/InstallSqlServerForAOAG.template +++ b/data/templates/agent/SqlServerCluster/InstallSqlServerForAOAG.template @@ -1,4 +1,11 @@ { + "Scripts": [ + "ImportCoreFunctions.ps1", + "OptionParser.ps1", + "SQLServerOptionParsers.ps1", + "SQLServerInstaller.ps1", + "SQLServerForAOAG.ps1" + ], "Commands": [ { "Name": "Disable-Firewall", @@ -16,12 +23,5 @@ "Name": "Install-SqlServerPowerShellModule", "Arguments": {} } - ], - "Scripts": [ - "SW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zIC1Gb3JjZQoKCmZ1bmN0aW9uIFNob3ctSW52b2NhdGlvbkluZm8gewogICAgcGFyYW0gKAogICAgICAgICRJbnZvY2F0aW9uLAogICAgICAgIFtTd2l0Y2hdICRFbmQKICAgICkKCiAgICBpZiAoJEVuZCkgewogICAgICAgIFdyaXRlLUxvZ0RlYnVnICI8L2Z1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICB9CiAgICBlbHNlIHsKICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiPGZ1bmN0aW9uIG5hbWU9JyQoJEludm9jYXRpb24uTXlDb21tYW5kLk5hbWUpJz4iCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjxwYXJhbT4iCiAgICAgICAgZm9yZWFjaCAoJFBhcmFtZXRlciBpbiAkSW52b2NhdGlvbi5NeUNvbW1hbmQuUGFyYW1ldGVycykgewogICAgICAgICAgICBmb3JlYWNoICgkS2V5IGluICRQYXJhbWV0ZXIuS2V5cykgewogICAgICAgICAgICAgICAgJFR5cGUgPSAkUGFyYW1ldGVyWyRLZXldLlBhcmFtZXRlclR5cGUuRnVsbE5hbWUKICAgICAgICAgICAgICAgIGZvcmVhY2ggKCRWYWx1ZSBpbiAkSW52b2NhdGlvbi5Cb3VuZFBhcmFtZXRlcnNbJEtleV0pIHsKICAgICAgICAgICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiWyRUeXBlXSAkS2V5ID0gJyRWYWx1ZSciCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgV3JpdGUtTG9nRGVidWcgIjwvcGFyYW0+IgogICAgfQp9CgoKJFRyYXBIYW5kbGVyID0gewogICAgV3JpdGUtTG9nRXJyb3IgQCgiPGV4Y2VwdGlvbj4iLCAkXykgLUVudGlyZU9iamVjdAogICAgV3JpdGUtTG9nRXJyb3IgIjwvZXhjZXB0aW9uPiIKICAgIGJyZWFrCn0KCgp0cmFwIHsKICAgICYkVHJhcEhhbmRsZXIKfQoKJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICdTdG9wJwoKCjwjCiMgVXNhZ2UgZXhhbXBsZSBmb3IgU2hvdy1JbnZvY2F0aW9uSW5mbwoKZnVuY3Rpb24gTXlGdW5jdGlvbiB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJFZhbHVlMSwKICAgICAgICBbU3RyaW5nXSAkVmFsdWUyLAogICAgICAgIFtJbnRdICRJbnQxCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KICAgICAgICAjIE1haW4gY29kZSBoZXJlCiAgICB9Cn0KIz4K", - "ZnVuY3Rpb24gTmV3LU9wdGlvbiAoW3N0cmluZ10kTmFtZSwgW3N3aXRjaF0kU3dpdGNoLCBbc3dpdGNoXSRCb29sZWFuLCBbc3dpdGNoXSRTdHJpbmcsIFtzd2l0Y2hdJExpc3QsICRDb25zdHJhaW50cz0kbnVsbCkgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBPcHRpb24gb2JqZWN0CgogICAgLkRFU0NSSVBUSU9OCiAgICBPcHRpb24gb2JqZWN0IGlzIGEgdmlydHVhbCBvYmplY3QgcmVwcmVzdG50aW5nIHR5cGVkIGNvbW1hbmQgbGluZSBvcHRpb24uIFRoZXNlIG9iamVjdHMgZW5jYXBzdWxhdGUgZXNjYXBpbmcgYW5kCiAgICB2YWxpZGF0aW9uIG1hdHRlcnMuCgogICAgT25lIGFuZCBvbmx5IG9uZSBvZiB0aGUgc3dpdGNoZXMgJ1N3aXRjaCcsICdCb29sZWFuJywgJ1N0cmluZycgb3IgJ0xpc3QnIHNob3VsZCBiZSBwcm92aWRlZC4KCiAgICAuUEFSQU1FVEVSIE5hbWUKICAgIE9wdGlvbiBuYW1lIGFzIGl0IGFwcGVhcnMgaW4gdGhlIGNvbW1hbmQgbGluZS4KCiAgICAuUEFSQU1FVEVSIFN3aXRjaAogICAgVXNlIHRoaXMgc3dpdGNoIHRvIGNyZWF0ZSB2YWx1ZWxlc3Mgb3B0aW9uIChhIHN3aXRjaCkuCgogICAgLlBBUkFNRVRFUiBCb29sZWFuCiAgICBVc2UgdGhpcyBzd2l0Y2ggdG8gY3JlYXRlIGJvb2xlYW4gb3B0aW9uLiBJdHMgdmFsdWUgaXMgYWx3YXlzIGNvbnZlcnRlZCB0byAiMSIgb3IgIjAiCgogICAgLlBBUkFNRVRFUiBTdHJpbmcKICAgIFVzZSB0aGlzIHN3aXRjaCB0byBjcmVhdGUgc3RyaW5nIG9wdGlvbi4gSXRzIHZhbHVlIHdpbGwgYmUgcHJvcGVybHkgcXVvdGVkIGlmIG5lY2Vzc2FyeS4KCiAgICAuUEFSQU1FVEVSIExpc3QKICAgIFVzZSB0aGlzIHN3aXRjaCB0byBjcmVhdGUgb3B0aW9uIHdpdGggbGlzdCB2YWx1ZS4gVmFsdWVzIHdpbGwgYmUgcHV0IGludG8gY29tbWFuZCBsaW5lIHVzaW5nIHZhbGlkIHZhbHVlIGRlbGVtaXRlciAoYSBjb21tYSkKCiAgICAuUEFSQU1FVEVSIENvbnN0cmFpbnRzCiAgICBXaGVuIHRoaXMgcGFyYW1ldGVyIGlzIHNwZWNpZmllZCwgb3B0aW9uIHZhbHVlcyBhcmUgbGltaXRlZCB0byBvcHRpb25zIGZyb20gdGhhdCBsaXN0LgoKICAgICM+CgogICAgJE9wdGlvbiA9IE5ldy1PYmplY3QgLVR5cGVOYW1lIFBTT2JqZWN0CgogICAgIyBGaWVsZHMKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIE5vdGVQcm9wZXJ0eSBUeXBlIC12YWx1ZSAkbnVsbAogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IE5hbWUgLXZhbHVlICRudWxsCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgQWxsb3dlZFZhbHVlcyAtdmFsdWUgJG51bGwKCiAgICAjIEluaXQKCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBTY3JpcHRNZXRob2QgX19pbml0X18gewogICAgICAgIHBhcmFtKFtzdHJpbmddJE5hbWUsICRTd2l0Y2gsICRCb29sZWFuLCAkU3RyaW5nLCAkTGlzdCkKCiAgICAgICAgJHRoaXMuTmFtZSA9ICROYW1lCiAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgIyBXaXRoIHJlc3BlY3QgZm9yIG91ciBkZXZlbG9wZXJzIHdlIGRvIG5vdCBjaGVjayBmb3IgZG91YmxlIHR5cGUgc2VsZWN0ZWQKICAgICAgICBpZiAoJFN3aXRjaCkgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uU3dpdGNoKCR0aGlzKQogICAgICAgIH0gZWxzZWlmICgkQm9vbGVhbikgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uQm9vbGVhbigkdGhpcykKICAgICAgICB9IGVsc2VpZiAoJFN0cmluZykgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uU3RyaW5nKCR0aGlzKQogICAgICAgIH0gZWxzZWlmICgkTGlzdCkgewogICAgICAgICAgICBBdWdtZW50T3B0aW9uTGlzdCgkdGhpcykKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aHJvdyAiU3dpdGNoLCBCb29sZWFuLCBTdHJpbmcgb3IgTGlzdCBvcHRpb24gdHlwZSBtdXN0IGJlIHByb3ZpZGVkIGZvciBvcHRpb24gJyROYW1lJyIKICAgICAgICB9CiAgICB9CgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIF9fcG9zdF9pbml0X18gewogICAgICAgIHBhcmFtKCRDb25zdHJhaW50cz0kbnVsbCkKICAgICAgICBpZiAoJENvbnN0cmFpbnRzIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkdGhpcy5BbGxvd2VkVmFsdWVzID0gQCgpCiAgICAgICAgICAgICR0aGlzLkFsbG93ZWRWYWx1ZXMgPSAkdGhpcy5BbGxvd2VkVmFsdWVzICsgJENvbnN0cmFpbnRzCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgJENvbnN0cmFpbnRzID0gJG51bGwKICAgICAgICB9CiAgICB9CgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBWYWxpZGF0ZSB7CiAgICAgICAgaWYgKCR0aGlzLkFsbG93ZWRWYWx1ZXMgLW5lICRudWxsKSB7CiAgICAgICAgICAgIGlmICgtbm90KCR0aGlzLkFsbG93ZWRWYWx1ZXMgLWNvbnRhaW5zICR0aGlzLlZhbHVlKSkgewogICAgICAgICAgICAgICAgJEN0cyA9ICR0aGlzLkFsbG93ZWRWYWx1ZXMgLWpvaW4gJywnCiAgICAgICAgICAgICAgICB0aHJvdyAiT3B0aW9uICckKCR0aGlzLk5hbWUpJyBtYXkgaGF2ZSB2YWx1ZXMgKCRDdHMpIGJ1dCBub3QgJyQoJHRoaXMuVmFsdWUpJyIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciAtRm9yY2UgU2NyaXB0TWV0aG9kIFRvU3RyaW5nIHsKICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpIgogICAgfQoKICAgICMgaW52b2tlIGNvbnN0cnVjdG9yCgogICAgJE9wdGlvbi5fX2luaXRfXygkTmFtZSwgJFN3aXRjaCwgJEJvb2xlYW4sICRTdHJpbmcsICRMaXN0KQogICAgJE9wdGlvbi5fX3Bvc3RfaW5pdF9fKCRDb25zdHJhaW50cykKCiAgICByZXR1cm4gJE9wdGlvbgp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uU3dpdGNoKCRPcHRpb24pIHsKfQoKZnVuY3Rpb24gQXVnbWVudE9wdGlvbkJvb2xlYW4oJE9wdGlvbikgewogICAgIyBGaWVsZHMKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIE5vdGVQcm9wZXJ0eSBWYWx1ZSAtdmFsdWUgJGZhbHNlCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBUb1N0cmluZyB7CiAgICAgICAgaWYgKCR0aGlzLlZhbHVlKSB7CiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9MSIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gIi8kKCR0aGlzLk5hbWUpPTAiCiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uU3RyaW5nKCRPcHRpb24pIHsKICAgICMgRmllbGRzCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgVmFsdWUgLXZhbHVlICIiCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgLUZvcmNlIFNjcmlwdE1ldGhvZCBUb1N0cmluZyB7CiAgICAgICAgJHYgPSAiJCgkdGhpcy5WYWx1ZSkiCiAgICAgICAgaWYgKCR2IC1tYXRjaCAnLiogLionKSB7CiAgICAgICAgICAgICMgVE9ETzogRXNjYXBlIGRvdWJsZSBxdW90ZSBjaGFyYWN0ZXJzIGlmIHBvc3NpYmxlCiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9YCIkdmAiIgogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9JHYiCiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBBdWdtZW50T3B0aW9uTGlzdCgkT3B0aW9uKSB7CiAgICAjIEZpZWxkcwogICAgJE9wdGlvbiB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IFZhbHVlIC12YWx1ZSBAKCkKCiAgICAjIE1ldGhvZHMKCiAgICAkT3B0aW9uIHwgQWRkLU1lbWJlciAtRm9yY2UgU2NyaXB0TWV0aG9kIFZhbGlkYXRlIHsKICAgICAgICBpZiAoJHRoaXMuQWxsb3dlZFZhbHVlcyAtbmUgJG51bGwpIHsKICAgICAgICAgICAgZm9yZWFjaCAoJFYgaW4gJHRoaXMuVmFsdWUpIHsKICAgICAgICAgICAgICAgIGlmICgtbm90KCR0aGlzLkFsbG93ZWRWYWx1ZXMgLWNvbnRhaW5zICRWKSkgewogICAgICAgICAgICAgICAgICAgICRDdHMgPSAkdGhpcy5BbGxvd2VkVmFsdWVzIC1qb2luICcsJwogICAgICAgICAgICAgICAgICAgIHRocm93ICJPcHRpb24gJyQoJHRoaXMuTmFtZSknIG1heSBoYXZlIHZhbHVlcyAoJEN0cykgYnV0IG5vdCAnJFYnIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgICRPcHRpb24gfCBBZGQtTWVtYmVyIC1Gb3JjZSBTY3JpcHRNZXRob2QgVG9TdHJpbmcgewogICAgICAgIHJldHVybiAiLyQoJHRoaXMuTmFtZSk9JCgkdGhpcy5WYWx1ZSAtam9pbiAnLCcpIgogICAgfQp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyKCkgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBPcHRpb25QYXJzZXIgb2JqZWN0LgoKICAgIC5ERVNDUklQVElPTgogICAgT3B0aW9uUGFyc2VyIG9iamVjdCBsZXZlcmFnZXMgT3B0aW9uIG9iamVjdHMgY2FwYWJpbGl0aWVzIGFuZCBidWlsZHMgdmFsaWQgY29tbWFuZCBsaW5lIHVzaW5nIHNwZWNpZmllZCBvcHRpb25zLgogICAgQW4gYXBwbGljYXRpb24gbWF5IGFsc28gYmUgaW52b2tlZCB3aXRoIE9wdGlvblBhcnNlci4KCiAgICAjPgoKICAgICRPcHRpb25QYXJzZXIgPSBOZXctT2JqZWN0IC1UeXBlTmFtZSBQU09iamVjdAoKICAgICMgRmllbGRzCiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgT3B0aW9ucyAtdmFsdWUgQHt9CiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBOb3RlUHJvcGVydHkgRGVmYXVsdHMgLXZhbHVlIEB7fQogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgTm90ZVByb3BlcnR5IFJlcXVpcmVkT3B0aW9ucyAtdmFsdWUgQCgpCgogICAgIyBNZXRob2RzCgogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIEFkZE9wdGlvbiB7CiAgICAgICAgPCMKICAgICAgICAuU1lOT1BTSVMKICAgICAgICBBZGRzIHN1cHBvcnRlZCBvcHRpb24gaW50byBPcHRpb25QYXJzZXIuCiAgICAgICAgCiAgICAgICAgLkRFU0NSSVBUSU9OCiAgICAgICAgT3B0aW9uUGFyc2VyIGRvZXMgbm90IGFsbG93IHVzaW5nIHVucmVjb2duaXplZCBvcHRpb25zLiBVc2UgdGhpcyBtZXRob2QgdG8gZmlsbCBPcHRpb25QYXJzZXIgd2l0aCByZWNvZ25pemVkIG9wdGlvbnMKCiAgICAgICAgLlBBUkFNRVRFUiBPcHRpb24KICAgICAgICBPcHRpb24gb2JqZWN0CgogICAgICAgIC5QQVJBTUVURVIgUmVxdWlyZWQKICAgICAgICBSZXF1aXJlZCBvcHRpb24gc3dpdGNoCgogICAgICAgIC5QQVJBTUVURVIgRGVmYXVsdAogICAgICAgIE9wdGlvbiBkZWZhdWx0IHZhbHVlCiAgICAgICAgIz4KICAgICAgICBwYXJhbSgkT3B0aW9uLCBbYm9vbF0kUmVxdWlyZWQ9JGZhbHNlLCAkRGVmYXVsdD0kbnVsbCkKICAgICAgICAkdGhpcy5PcHRpb25zLkFkZCgkT3B0aW9uLk5hbWUsICRPcHRpb24pCiAgICAgICAgaWYgKCRSZXF1aXJlZCkgewogICAgICAgICAgICAkdGhpcy5SZXF1aXJlZE9wdGlvbnMgPSAkdGhpcy5SZXF1aXJlZE9wdGlvbnMgKyAkT3B0aW9uLk5hbWUKICAgICAgICAgICAgaWYgKCRPcHRpb24gfCBHZXQtTWVtYmVyICJWYWx1ZSIpIHsKICAgICAgICAgICAgICAgIGlmICgkRGVmYXVsdCkgewogICAgICAgICAgICAgICAgICAgICR0aGlzLkRlZmF1bHRzLkFkZCgkT3B0aW9uLk5hbWUsICREZWZhdWx0KQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgJHRoaXMuRGVmYXVsdHMuQWRkKCRPcHRpb24uTmFtZSwgJG51bGwpCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgJE9wdGlvblBhcnNlciB8IEFkZC1NZW1iZXIgU2NyaXB0TWV0aG9kIFBhcnNlIHsKICAgICAgICA8IwogICAgICAgIC5TWU5PUFNJUwogICAgICAgIFBhcnNlcyBzdXBwbGllZCBvcHRpb25zIGFuZCByZXR1cm5zIGNvbW1hbmQgbGluZSBwYXJhbWV0ZXJzIGFycmF5LgogICAgICAgIAogICAgICAgIC5ERVNDUklQVElPTgogICAgICAgIFRoaXMgbWV0aG9kIHZlcmlmaWVzIHRoYXQgb25seSBzdXBwb3J0ZWQgb3B0aW9ucyBhcmUgcHJvdmlkZWQsIGFsbCBtYW5kYXRvcnkgb3B0aW9ucyBhcmUgaW4gcGxhY2UsIAogICAgICAgIGFsbCBvcHRpb24gbWVldCBjb25zdHJhaW50cyBpZiBhbnkuIFVuc3BlY2lmaWVkIG9wdGlvbnMgd2l0aCBkZWZhdWx0IHZhbHVlcyBhcmUgYWRkZWQgdG8gY29tbWFuZCBsaW5lLgogICAgICAgIFNvLCBtYW5kYXRvcnkgb3B0aW9uIHdpdGggZGVmYXVsdCB2YWx1ZSBuZXZlciBjYXVzZXMgZXhjZXB0aW9uLgoKICAgICAgICAuUEFSQU1FVEVSIE9wdGlvbnMKICAgICAgICBBIGhhc2ggbWFwIG9mIG9wdGlvbnMgdG8gcGFyc2UuIE9wdGlvbiBuYW1lcyBzaG91bGQgYmUgbWFwcGVkIHRvIGNvcnJlc3BvbmRpbmcgdmFsdWVzLgogICAgICAgICM+CiAgICAgICAgcGFyYW0oW2hhc2h0YWJsZV0kT3B0aW9ucykKCiAgICAgICAgJENvbW1hbmRMaW5lID0gQCgpCiAgICAgICAgZm9yZWFjaCAoJFJlcXVpcmVkT3B0aW9uTmFtZSBpbiAkdGhpcy5SZXF1aXJlZE9wdGlvbnMpIHsKICAgICAgICAgICAgaWYgKC1ub3QgJE9wdGlvbnMuQ29udGFpbnNLZXkoJFJlcXVpcmVkT3B0aW9uTmFtZSkpIHsKICAgICAgICAgICAgICAgICREZWZhdWx0ID0gJHRoaXMuRGVmYXVsdHMuR2V0X0l0ZW0oJFJlcXVpcmVkT3B0aW9uTmFtZSkKICAgICAgICAgICAgICAgIGlmICgkdGhpcy5EZWZhdWx0cy5Db250YWluc0tleSgkUmVxdWlyZWRPcHRpb25OYW1lKSkgewogICAgICAgICAgICAgICAgICAgICRPcHRpb25zLkFkZCgkUmVxdWlyZWRPcHRpb25OYW1lLCAkdGhpcy5EZWZhdWx0cy5HZXRfSXRlbSgkUmVxdWlyZWRPcHRpb25OYW1lKSkKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgIlJlcXVpcmVkIG9wdGlvbiAnJFJlcXVpcmVkT3B0aW9uTmFtZScgaXMgbWlzc2luZyIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZm9yZWFjaCAoJE9wdGlvbk5hbWUgaW4gJCgkT3B0aW9ucy5rZXlzKSkgewogICAgICAgICAgICAkT3B0aW9uID0gJHRoaXMuT3B0aW9ucy5HZXRfSXRlbSgkT3B0aW9uTmFtZSkKICAgICAgICAgICAgaWYgKCRPcHRpb24gLWVxICRudWxsKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAiT3B0aW9uICckT3B0aW9uTmFtZScgaXMgbm90IGFsbG93ZWQiCiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCRPcHRpb24gfCBHZXQtTWVtYmVyICJWYWx1ZSIpIHsKICAgICAgICAgICAgICAgICRPcHRpb24uVmFsdWUgPSAkT3B0aW9ucy5HZXRfSXRlbSgkT3B0aW9uTmFtZSkKICAgICAgICAgICAgfQogICAgICAgICAgICAkT3B0aW9uLlZhbGlkYXRlKCkKICAgICAgICAgICAgJENvbW1hbmRMaW5lID0gJENvbW1hbmRMaW5lICsgJE9wdGlvbi5Ub1N0cmluZygpCiAgICAgICAgfQogICAgICAgIHJldHVybiAkQ29tbWFuZExpbmUKICAgIH0KCiAgICAkT3B0aW9uUGFyc2VyIHwgQWRkLU1lbWJlciBTY3JpcHRNZXRob2QgRXhlY3V0ZUJpbmFyeSB7CiAgICAgICAgcGFyYW0oJEJpbmFyeSwgW2hhc2h0YWJsZV0kT3B0aW9ucyA9IEB7fSwgJENvbW1hbmRMaW5lU3VmZml4ID0gQCgpKQogICAgICAgIDwjCiAgICAgICAgLlNZTk9QU0lTCiAgICAgICAgRXhlY3V0ZXMgYmluYXJ5IHdpdGggYSBjb21tYW5kIGxpbmUgY29uc3RydWN0ZWQgZnJvbSBwcm92aWRlZCBvcHRpb25zLiBBbiBhcmJpdHJhcnkgc3VmZml4IG1heSBiZSAKICAgICAgICBhcHBlbmRlZCB0byB0aGUgY29tbWFuZCBsaW5lLgogICAgICAgIAogICAgICAgIC5ERVNDUklQVElPTgogICAgICAgIFRoaXMgbWV0aG9kIHVzZXMgT3B0aW9uUGFyc2VyLlBhcnNlIG1ldGhvZCB0byBjb25zdHJ1Y3QgY29tbWFuZCBsaW5lLiBJZiB0aGVyZSBhIGNvbW1hbmQgbGluZSBzdWZmaXggCiAgICAgICAgd2FzIHN1cHBsaWVkLCBpdCBpcyBhcHBlbmRlZCB0byB0aGUgZW5kIG9mIGNvbW1hbmQgbGluZS4gTm9ybWFsbHkgY29tbWFuZCBsaW5lIHN1ZmZpeCBzaG91bGQgY29udGFpbgogICAgICAgIGxlYWRpbmcgc3BhY2UgY2hhcmFjdGVyLgoKICAgICAgICBNZXRob2Qgd2FpdHMgZm9yIGV4ZWN1dGFibGUgcHJvY2VzcyB0byBjb21wbGV0ZSBhbmQgcmV0dXJucyBpdHMgZXhpdCBjb2RlLgoKICAgICAgICAuUEFSQU1FVEVSIEJpbmFyeQogICAgICAgIEZ1bGwgb3IgcmVsYXRpdmUgcGF0aCB0byB0aGUgZXhlY3V0YWJsZSB0byBydW4uCgogICAgICAgIC5QQVJBTUVURVIgT3B0aW9ucwogICAgICAgIEEgaGFzaCBtYXAgb2Ygb3B0aW9ucyB0byBwYXNzIHRvIHRoZSBleGVjdXRhYmxlLgoKICAgICAgICAuUEFSQU1FVEVSIENvbW1hbmRMaW5lU3VmZml4CiAgICAgICAgQXJiaXRyYXJ5IGNvbW1hbmQgbGluZSBzdWZmaXguIE5vcm1hbGx5IGl0IHNob3VkIGhhdmUgbGVhZGluZyBzcGFjZSBjaGFyYWN0ZXIuCiAgICAgICAgIz4KCiAgICAgICAgJEJpbmFyeSA9IEdldC1JdGVtICRCaW5hcnkKICAgICAgICAkQ29tbWFuZExpbmUgPSAkdGhpcy5QYXJzZSgkT3B0aW9ucykKICAgICAgICBpZiAoJENvbW1hbmRMaW5lU3VmZml4KSB7CiAgICAgICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICRDb21tYW5kTGluZVN1ZmZpeAogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJFeGVjdXRpbmc6ICQoJEJpbmFyeS5GdWxsTmFtZSkgJCgkQ29tbWFuZExpbmUgLWpvaW4gJyAnKSIKICAgICAgICAkcHJvY2VzcyA9IFtTeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2Vzc106OlN0YXJ0KCRCaW5hcnksICRDb21tYW5kTGluZSkKICAgICAgICAkcHJvY2Vzcy5XYWl0Rm9yRXhpdCgpCiAgICAgICAgJHByb2Nlc3MuUmVmcmVzaCgpCiAgICAgICAgcmV0dXJuICRwcm9jZXNzLkV4aXRDb2RlCiAgICB9CgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQo=", - "ZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckluc3RhbGwgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBhbiBvcHRpb24gcGFyc2VyIGZvciBNUyBTUUwgU2VydmVyIDIwMTIgc2V0dXAgIklOU1RBTEwiIGFjdGlvbi4KCiAgICAuREVTQ1JJUFRJT04KICAgIFVzZSB0aGlzIGNtZGxldCB0byBjcmVhdGUgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJJTlNUQUxMIiBhY3Rpb24uCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkSXNQYXJ0T2ZEb21haW4gPSAoR2V0LVdtaU9iamVjdCBXaW4zMl9Db21wdXRlclN5c3RlbSkuUGFydE9mRG9tYWluCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIklOU1RBTEwiKSwgJHRydWUsICJJTlNUQUxMIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJQUNDRVBUU1FMU0VSVkVSTElDRU5TRVRFUk1TIiAtU3dpdGNoKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5VIiAtU3dpdGNoKSkKICAgICMkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlVwZGF0ZVNvdXJjZSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVSUk9SUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTCIsIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJEUSIsIkFTIiwiUlMiLCJEUUMiLCJJUyIsIk1EUyIsIlRvb2xzIiwiQkMiLCJCT0wiLCJCSURTIiwiQ29ubiIsIlNTTVMiLCJBRFZfU1NNUyIsIkRSRVBMQVlfQ1RMUiIsIkRSRVBMQVlfQ0xUIiwiU05BQ19TREsiLCJTREsiLCJMb2NhbERCIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJPTEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiU1BJX0FTX0V4aXN0aW5nRmFybSIsICJTUElfQVNfTmV3RmFybSIsICJBbGxGZWF0dXJlc19XaXRoRGVmYXVsdHMiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRFdPV0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlBJRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlVJTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJOb3JtYWwiLCAiQXV0b0FkdmFuY2UiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FNUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTQkFDS1VQRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU0NPTExBVElPTiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQVNDT05GSUdESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTREFUQURJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQVNMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU0VSVkVSTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNVUxUSURJTUVOU0lPTkFMIiwgIlBPV0VSUElWT1QiLCAiVEFCVUxBUiIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKCiAgICAjJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXCRFTlY6VVNFUk5BTUUiKQogICAgaWYgKCRJc1BhcnRPZkRvbWFpbikgewogICAgICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFbnY6VVNFUkRPTUFJTlxBZG1pbmlzdHJhdG9yIikKICAgIH0KICAgIGVsc2UgewogICAgICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1NZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFbnY6Q09NUFVURVJOQU1FXEFkbWluaXN0cmF0b3IiKQogICAgfQoKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBU1RFTVBESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFTUFJPVklERVJNU09MQVAiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGQVJNQUNDT1VOVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkFSTVBBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJQQVNTUEhSQVNFIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGQVJNQURNSU5JUE9SVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQlJPV1NFUlNWQ1NUQVJUVVBUWVBFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5BQkxFUkFOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNRTERBVEFESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNBUFdEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTRUNVUklUWU1PREUiIC1TdHJpbmcgLUNvbnN0cmFpbnJzICgiU1FMIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTEJBQ0tVUERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMQ09MTEFUSU9OIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBRERDVVJSRU5UVVNFUkFTU1FMQURNSU4iIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgCiAgICAjJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6VVNFUkRPTUFJTlwkRU5WOlVTRVJOQU1FIikKICAgIGlmICgkSXNQYXJ0T2ZEb21haW4pIHsKICAgICAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXEFkbWluaXN0cmF0b3IiKQogICAgfQogICAgZWxzZSB7CiAgICAgICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6Q09NUFVURVJOQU1FXEFkbWluaXN0cmF0b3IiKQogICAgfQogICAgCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVEVNUERCRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxURU1QREJMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFVTRVJEQkRJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVVNFUkRCTE9HRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGSUxFU1RSRUFNTEVWRUwiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiMCIsICIxIiwgIjIiLCAiMyIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGSUxFU1RSRUFNU0hBUkVOQU1FIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGVFNWQ0FDQ09VTlQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZUU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklTU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSVNTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSVNTVkNTdGFydHVwVHlwZSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIk5QRU5BQkxFRCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlRDUEVOQUJMRUQiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU0lOU1RBTExNT0RFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIlNoYXJlUG9pbnRGaWxlc09ubHlNb2RlIiwgIkRlZmF1bHROYXRpdmVNb2RlIiwgIkZpbGVzT25seU1vZGUiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNBQ0NPVU5UIiAtU3RyaW5nKSwgJHRydWUsICJOVCBBVVRIT1JJVFlcTmV0d29yayBTZXJ2aWNlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ1N0YXJ0dXBUeXBlIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclByZXBhcmVJbWFnZSB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgTm90ZSB0aGF0IGZvciBpbnN0YWxsZXIgdmVyc2lvbiBvZiBNUyBTUUwgU2VydmVyIHByaW9yIHRvIDIwMTIgU1AxIEN1bXVsYXRpdmUgVXBkYXRlIDIgb25seSB0aGUKICAgIGZvbGxvd2luZyBmZWF0dXJlcyBhcmUgc3VwcG9ydGVkOiBTUUxFbmdpbmUsIFJlcGxpY2F0aW9uLCBGdWxsVGV4dCwgUlMKCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUNUSU9OIiAtU3RyaW5nIC1Db25zdHJhaW50cyAiUHJlcGFyZUltYWdlIiksICR0cnVlLCAiUHJlcGFyZUltYWdlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJQUNDRVBUU1FMU0VSVkVSTElDRU5TRVRFUk1TIiAtU3dpdGNoKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRU5VIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJVcGRhdGVFbmFibGVkIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJVcGRhdGVTb3VyY2UiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkNPTkZJR1VSQVRJT05GSUxFIiAtU3RyaW5nKSkKIyAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJSUyIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGRUFUVVJFUyIgLUxpc3QgLUNvbnN0cmFpbnRzICgiU1FMIiwiU1FMRW5naW5lIiwiUmVwbGljYXRpb24iLCJGdWxsVGV4dCIsIkRRIiwiQVMiLCJSUyIsIkRRQyIsIklTIiwiTURTIiwiVG9vbHMiLCJCQyIsIkJPTCIsIkJJRFMiLCJDb25uIiwiU1NNUyIsIkFEVl9TU01TIiwiRFJFUExBWV9DVExSIiwiRFJFUExBWV9DTFQiLCJTTkFDX1NESyIsIlNESyIsIkxvY2FsREIiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklORElDQVRFUFJPR1JFU1MiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTExTSEFSRURESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJTlNUQU5DRUlEIiAtU3RyaW5nKSwgJHRydWUsICJNU1NRTFNFUlZFUiIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJQcmVwYXJlSW1hZ2VTUDFVMiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDcmVhdGVzIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiUHJlcGFyZUltYWdlIiBhY3Rpb24uCgogICAgVGhpcyBjbWRsZXQgc2hvdWxkIGJlIHVzZWQgb25seSBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIFNQMSBDaW1pbGF0aXZlIFVwZGF0ZSAyIG9yIGxhdGVyLgoKICAgIE5vdGUgdGhhdCBmb3IgaW5zdGFsbGVyIHZlcnNpb24gb2YgTVMgU1FMIFNlcnZlciBwcmlvciB0byAyMDEyIFNQMSBDaW1pbGF0aXZlIFVwZGF0ZSAyIG9ubHkgdGhlCiAgICBmb2xsb3dpbmcgZmVhdHVyZXMgYXJlIHN1cHBvcnRlZDogU1FMRW5naW5lLCBSZXBsaWNhdGlvbiwgRnVsbFRleHQsIFJTCgogICAgQWxsIGRvY3VtZW50ZWQgb3B0aW9uIGFyZSBzdXBwb3J0ZWQuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yIGRldGFpbHM6CiAgICBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAogICAgIz4KICAgICRPcHRpb25QYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VyCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIlByZXBhcmVJbWFnZSIpLCAkdHJ1ZSwgIlByZXBhcmVJbWFnZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSUFDQ0VQVFNRTFNFUlZFUkxJQ0VOU0VURVJNUyIgLVN3aXRjaCksICR0cnVlKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlRW5hYmxlZCIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVXBkYXRlU291cmNlIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJDT05GSUdVUkFUSU9ORklMRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRkVBVFVSRVMiIC1MaXN0IC1Db25zdHJhaW50cyAoIlNRTCIsIlNRTEVuZ2luZSIsIlJlcGxpY2F0aW9uIiwiRnVsbFRleHQiLCJEUSIsIkFTIiwiUlMiLCJEUUMiLCJJUyIsIk1EUyIsIlRvb2xzIiwiQkMiLCJCT0wiLCJCSURTIiwiQ29ubiIsIlNTTVMiLCJBRFZfU1NNUyIsIlNOQUNfU0RLIiwiU0RLIiwiTG9jYWxEQiIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJISURFQ09OU09MRSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFMTFNIQVJFRERJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk1TU1FMU0VSVkVSIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRUyIgLVN3aXRjaCkpCgogICAgcmV0dXJuICRPcHRpb25QYXJzZXIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckNvbXBsZXRlSW1hZ2UgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBhbiBvcHRpb24gcGFyc2VyIGZvciBNUyBTUUwgU2VydmVyIDIwMTIgc2V0dXAgIkNvbXBsZXRlSW1hZ2UiIGFjdGlvbi4KCiAgICAuREVTQ1JJUFRJT04KICAgIFVzZSB0aGlzIGNtZGxldCB0byBjcmVhdGUgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJDb21wbGV0ZUltYWdlIiBhY3Rpb24uCgogICAgTm90ZSB0aGF0IElOU1RBTkNFSUQgcGFyYW1ldGVyIHZhbHVlIE1VU1QgYmUgdGhlIHNhbWUgYXMgc3BlY2lmaWVkIG9uICJQcmVwYXJlSW1hZ2UiIHBoYXNlLgoKICAgIEFsbCBkb2N1bWVudGVkIG9wdGlvbiBhcmUgc3VwcG9ydGVkLiBTZWUgdGhlIGZvbGxvd2luZyBsaW5rIGZvciBkZXRhaWxzOgogICAgaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTQ0MjU5LmFzcHgKICAgICM+CiAgICAkT3B0aW9uUGFyc2VyID0gTmV3LU9wdGlvblBhcnNlcgoKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBQ1RJT04iIC1TdHJpbmcgLUNvbnN0cmFpbnRzICJDb21wbGV0ZUltYWdlIiksICR0cnVlLCAiQ29tcGxldGVJbWFnZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSUFDQ0VQVFNRTFNFUlZFUkxJQ0VOU0VURVJNUyIgLVN3aXRjaCksICR0cnVlKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOVSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVSUk9SUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VJRCIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZyksICR0cnVlLCAiTVNTUUxTRVJWRVIiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlBJRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUVMiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTVJFUE9SVElORyIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkhJREVDT05TT0xFIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNBQ0NPVU5UIiAtU3RyaW5nKSwgJHRydWUsICJOVCBBVVRIT1JJVFlcTmV0d29yayBTZXJ2aWNlIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUdUU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJCUk9XU0VSU1ZDU1RBUlRVUFRZUEUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFTkFCTEVSQU5VIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJJTlNUQUxMU1FMREFUQURJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU0FQV0QiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNFQ1VSSVRZTU9ERSIgLVN0cmluZyAtQ29uc3RyYWlucnMgKCJTUUwiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMQkFDS1VQRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxDT0xMQVRJT04iIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNZU0FETUlOQUNDT1VOVFMiIC1TdHJpbmcpLCAkdHJ1ZSwgIiRFTlY6VVNFUkRPTUFJTlwkRU5WOlVTRVJOQU1FIikKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxURU1QREJESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFRFTVBEQkxPR0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVVNFUkRCRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxVU0VSREJMT0dESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZJTEVTVFJFQU1MRVZFTCIgLVN0cmluZyAtQ29uc3RyYWludHMgKCIwIiwgIjEiLCAiMiIsICIzIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZJTEVTVFJFQU1TSEFSRU5BTUUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZUU1ZDQUNDT1VOVCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRlRTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiTlBFTkFCTEVEIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiVENQRU5BQkxFRCIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTSU5TVEFMTE1PREUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiU2hhcmVQb2ludEZpbGVzT25seU1vZGUiLCAiRGVmYXVsdE5hdGl2ZU1vZGUiLCAiRmlsZXNPbmx5TW9kZSIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJSU1NWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDU3RhcnR1cFR5cGUiIC1TdHJpbmcgLUNvbnN0cmFpbnRzICgiTWFudWFsIiwgIkF1dG9tYXRpYyIsICJEaXNhYmxlZCIpKSkKCiAgICByZXR1cm4gJE9wdGlvblBhcnNlcgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyQ29tcGxldGVJbWFnZVNQMVUyIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJDb21wbGV0ZUltYWdlIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiQ29tcGxldGVJbWFnZSIgYWN0aW9uLgoKICAgIFRoaXMgY21kbGV0IHNob3VsZCBiZSB1c2VkIG9ubHkgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBTUDEgQ2ltaWxhdGl2ZSBVcGRhdGUgMiBvciBsYXRlci4KCiAgICBBbGwgZG9jdW1lbnRlZCBvcHRpb24gYXJlIHN1cHBvcnRlZC4gU2VlIHRoZSBmb2xsb3dpbmcgbGluayBmb3IgZGV0YWlsczoKICAgIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczE0NDI1OS5hc3B4CiAgICAjPgogICAgJE9wdGlvblBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXIKCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQUNUSU9OIiAtU3RyaW5nIC1Db25zdHJhaW50cyAiQ29tcGxldGVJbWFnZSIpLCAkdHJ1ZSwgIkNvbXBsZXRlSW1hZ2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklBQ0NFUFRTUUxTRVJWRVJMSUNFTlNFVEVSTVMiIC1Td2l0Y2gpLCAkdHJ1ZSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFTlUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkNPTkZJR1VSQVRJT05GSUxFIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJFUlJPUlJFUE9SVElORyIgLUJvb2xlYW4pKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklORElDQVRFUFJPR1JFU1MiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFSUQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTkNFTkFNRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUElEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRIiAtU3dpdGNoKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJRUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FNUkVQT1JUSU5HIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ0FDQ09VTlQiIC1TdHJpbmcpLCAkdHJ1ZSwgIk5UIEFVVEhPUklUWVxOZXR3b3JrIFNlcnZpY2UiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFHVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJBR1RTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkJST1dTRVJTVkNTVEFSVFVQVFlQRSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkVOQUJMRVJBTlUiIC1Td2l0Y2gpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIklOU1RBTExTUUxEQVRBRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTQVBXRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU0VDVVJJVFlNT0RFIiAtU3RyaW5nIC1Db25zdHJhaW5ycyAoIlNRTCIpKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxCQUNLVVBESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTENPTExBVElPTiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1ZDUEFTU1dPUkQiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFNWQ1NUQVJUVVBUWVBFIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIk1hbnVhbCIsICJBdXRvbWF0aWMiLCAiRGlzYWJsZWQiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMU1lTQURNSU5BQ0NPVU5UUyIgLVN0cmluZyksICR0cnVlLCAiJEVOVjpVU0VSRE9NQUlOXCRFTlY6VVNFUk5BTUUiKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFRFTVBEQkRJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiU1FMVEVNUERCTE9HRElSIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJTUUxVU0VSREJESVIiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlNRTFVTRVJEQkxPR0RJUiIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRklMRVNUUkVBTUxFVkVMIiAtU3RyaW5nIC1Db25zdHJhaW50cyAoIjAiLCAiMSIsICIyIiwgIjMiKSkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRklMRVNUUkVBTVNIQVJFTkFNRSIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiRlRTVkNBQ0NPVU5UIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJGVFNWQ1BBU1NXT1JEIiAtU3RyaW5nKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJOUEVOQUJMRUQiIC1Cb29sZWFuKSkKICAgICRPcHRpb25QYXJzZXIuQWRkT3B0aW9uKChOZXctT3B0aW9uICJUQ1BFTkFCTEVEIiAtQm9vbGVhbikpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNJTlNUQUxMTU9ERSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJTaGFyZVBvaW50RmlsZXNPbmx5TW9kZSIsICJEZWZhdWx0TmF0aXZlTW9kZSIsICJGaWxlc09ubHlNb2RlIikpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIlJTU1ZDQUNDT1VOVCIgLVN0cmluZyksICR0cnVlLCAiTlQgQVVUSE9SSVRZXE5ldHdvcmsgU2VydmljZSIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNQQVNTV09SRCIgLVN0cmluZykpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUlNTVkNTdGFydHVwVHlwZSIgLVN0cmluZyAtQ29uc3RyYWludHMgKCJNYW51YWwiLCAiQXV0b21hdGljIiwgIkRpc2FibGVkIikpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJVcGdyYWRlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlckVkaXRpb25VcGdyYWRlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclJlcGFpciB7CiAgICAjIFRvRG86IEltcGxlbWVudAogICAgdGhyb3cgIk5vdCB5ZXQgaW1wbGVtZW50ZWQiCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJSZWJ1aWxkZGF0YWJhc2UgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyVW5pbnN0YWxsIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgYW4gb3B0aW9uIHBhcnNlciBmb3IgTVMgU1FMIFNlcnZlciAyMDEyIHNldHVwICJJTlNUQUxMIiBhY3Rpb24uCgogICAgLkRFU0NSSVBUSU9OCiAgICBVc2UgdGhpcyBjbWRsZXQgdG8gY3JlYXRlIGFuIG9wdGlvbiBwYXJzZXIgZm9yIE1TIFNRTCBTZXJ2ZXIgMjAxMiBzZXR1cCAiSU5TVEFMTCIgYWN0aW9uLgogICAgQWxsIGRvY3VtZW50ZWQgb3B0aW9uIGFyZSBzdXBwb3J0ZWQuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yIGRldGFpbHM6CiAgICBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAogICAgIz4KICAgICRPcHRpb25QYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VyCgogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkFDVElPTiIgLVN0cmluZyAtQ29uc3RyYWludHMgIlVOSU5TVEFMTCIpLCAkdHJ1ZSwgIlVOSU5TVEFMTCIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiQ09ORklHVVJBVElPTkZJTEUiIC1TdHJpbmcpKQogICAgJE9wdGlvblBhcnNlci5BZGRPcHRpb24oKE5ldy1PcHRpb24gIkZFQVRVUkVTIiAtTGlzdCAtQ29uc3RyYWludHMgKCJTUUwiLCJTUUxFbmdpbmUiLCJSZXBsaWNhdGlvbiIsIkZ1bGxUZXh0IiwiRFEiLCJBUyIsIlJTIiwiRFFDIiwiSVMiLCJNRFMiLCJUb29scyIsIkJDIiwiQk9MIiwiQklEUyIsIkNvbm4iLCJTU01TIiwiQURWX1NTTVMiLCJEUkVQTEFZX0NUTFIiLCJEUkVQTEFZX0NMVCIsIlNOQUNfU0RLIiwiU0RLIiwiTG9jYWxEQiIpKSwgJHRydWUpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5ESUNBVEVQUk9HUkVTUyIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSU5TVEFOQ0VOQU1FIiAtU3RyaW5nKSwgJHRydWUsICJNU1NRTFNFUlZFUiIpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiUSIgLVN3aXRjaCkpCiAgICAkT3B0aW9uUGFyc2VyLkFkZE9wdGlvbigoTmV3LU9wdGlvbiAiSElERUNPTlNPTEUiIC1Td2l0Y2gpKQoKICAgIHJldHVybiAkT3B0aW9uUGFyc2VyCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJJbnN0YWxsRmFpbG92ZXJDbHVzdGVyIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclByZXBhcmVGYWlsb3ZlckNsdXN0ZXIgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyQ29tcGxldGVGYWlsb3ZlckNsdXN0ZXIgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9CgpmdW5jdGlvbiBOZXctT3B0aW9uUGFyc2VyVXBncmFkZSB7CiAgICAjIFRvRG86IEltcGxlbWVudAogICAgdGhyb3cgIk5vdCB5ZXQgaW1wbGVtZW50ZWQiCn0KCmZ1bmN0aW9uIE5ldy1PcHRpb25QYXJzZXJBZGROb2RlIHsKICAgICMgVG9EbzogSW1wbGVtZW50CiAgICB0aHJvdyAiTm90IHlldCBpbXBsZW1lbnRlZCIKfQoKZnVuY3Rpb24gTmV3LU9wdGlvblBhcnNlclJlbW92ZU5vZGUgewogICAgIyBUb0RvOiBJbXBsZW1lbnQKICAgIHRocm93ICJOb3QgeWV0IGltcGxlbWVudGVkIgp9Cg==", - "SW1wb3J0LU1vZHVsZSBOZXRTZWN1cml0eQoKZnVuY3Rpb24gVGVzdC1LZXkoW3N0cmluZ10kcGF0aCwgW3N0cmluZ10ka2V5KSB7CiAgICBpZighKFRlc3QtUGF0aCAkcGF0aCkpIHsgcmV0dXJuICRmYWxzZSB9CiAgICBpZiAoKEdldC1JdGVtUHJvcGVydHkgJHBhdGgpLiRrZXkgLWVxICRudWxsKSB7IHJldHVybiAkZmFsc2UgfQogICAgcmV0dXJuICR0cnVlCn0KCmZ1bmN0aW9uIFJlc29sdmUtU1FMU2VydmVyUHJlcmVxdWlzaXRlcyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBNUyBTUUwgU2VydmVyIHByZXJlcXVpc2l0ZXMgKC5OZXQgRnJhbWV3b3JrIDMuNSkKCiAgICAuREVTQ1JJUFRJT04KICAgIEluc3RhbGxzIE1TIFNRTCBTZXJ2ZXIgcHJlcmVxdWlzaXRlcyAoLk5ldCBGcmFtZXdvcmsgMy41KQoKICAgICM+CiAgICBpZiAoLW5vdCAoVGVzdC1LZXkgIkhLTE06XFNvZnR3YXJlXE1pY3Jvc29mdFxORVQgRnJhbWV3b3JrIFNldHVwXE5EUFx2My41IiAiSW5zdGFsbCIpKSB7CiAgICAgICAgSW1wb3J0LU1vZHVsZSBTZXJ2ZXJNYW5hZ2VyCiAgICAgICAgV3JpdGUtSG9zdCAiLk5ldCBGcmFtZXdvcmsgMy41IG5vdCBmb3VuZC4gSW5zdGFsbGluZyBpdCB1c2luZyBTZXJ2ZXIgTWFuYWdlci4uLiIKICAgICAgICAkRmVhdHVyZSA9IEdldC1XaW5kb3dzRmVhdHVyZSBORVQtRnJhbWV3b3JrCiAgICAgICAgaWYgKCRGZWF0dXJlIC1lcSAkbnVsbCkgewogICAgICAgICAgICAjIFdlIGFyZSBwcm9iYWJseSBvbiBXaW5kb3dzIFNlcnZlciAyMDEyCiAgICAgICAgICAgICRGZWF0dXJlID0gR2V0LVdpbmRvd3NGZWF0dXJlIE5FVC1GcmFtZXdvcmstQ29yZQogICAgICAgIH0KICAgICAgICBpZiAoLW5vdCAkRmVhdHVyZSkgewogICAgICAgICAgICB0aHJvdyAiLk5ldCBmcmFtZXdvcmsgMy41IGZlYXR1cmUgd2FzIG5vdCBmb3VuZC4iCiAgICAgICAgfQogICAgICAgIGlmICgtbm90ICRGZWF0dXJlLkRpc3BsYXlOYW1lIC1tYXRjaCAiMy41IikgewogICAgICAgICAgICBMb2ctV2FybmluZyAiLk5ldCBmcmFtZXdvcmsgMy41IGlzIHJlcXVpcmVkLCBidXQgJCgkRmVhdHVyZS5EaXNwbGF5TmFtZSkgaXMgYXZhaWxhYmxlIGFzIFdpbmRvd3MgZmVhdHVyZS4gUHJvY2VlZGluZyB3aXRoIGluc3RhbGxhdGlvbiIKICAgICAgICB9CiAgICAgICAgW3ZvaWRdKEFkZC1XaW5kb3dzRmVhdHVyZSAkRmVhdHVyZSkKICAgIH0KfQoKZnVuY3Rpb24gTmV3LVNRTFNlcnZlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZS4gUmV0dXJucyAkdHJ1ZSBpZiBhIHJlYm9vdCBpcyByZXF1aXJlZCBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLCAKICAgICRmYWxzZSBpZiBhIHJlYm9vdCBpcyBub3QgcmVxdWlyZWQgYW5kIHRocm93cyBhbiBleGNlcHRpb24gaW4gY2FzZSBpZiBpbnN0YWxsYXRpb24gZmFpbHMuCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSBpbiB1bmF0dGVuZGVkIG1vZGUuCgogICAgLlBBUkFNRVRFUiBTZXR1cFJvb3QKICAgIE1TIFNRTCBTZXJ2ZXIgaW5zdGFsbGF0aW9uIGZpbGVzIHJvb3QgZGlyZWN0b3J5LiBOb3JtYWxseSBpdCBpcyBqdXN0IERWRCBkcml2ZSBuYW1lLgoKICAgIC5QQVJBTUVURVIgRXh0cmFGZWF0dXJlcwogICAgTGlzdCBvZiBmZWF0dXJlcyB0byBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gZGVmYXVsdCAiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCksCiAgICAgICAgW0hhc2h0YWJsZV0kRXh0cmFPcHRpb25zID0gQHt9CiAgICApCgogICAgJFNldHVwRGlyID0gR2V0LUl0ZW0gJFNldHVwUm9vdAogICAgJFNldHVwRXhlID0gJFNldHVwRGlyLkdldEZpbGVzKCJzZXR1cC5leGUiKVswXQoKICAgIFJlc29sdmUtU1FMU2VydmVyUHJlcmVxdWlzaXRlcwoKICAgICRwYXJzZXIgPSBOZXctT3B0aW9uUGFyc2VySW5zdGFsbAogICAgJEV4aXRDb2RlID0gJHBhcnNlci5FeGVjdXRlQmluYXJ5KCRTZXR1cEV4ZS5GdWxsTmFtZSwgQHsiUSIgPSAkbnVsbDsgIkZFQVRVUkVTIiA9IEAoIlNRTEVuZ2luZSIsICJDb25uIiwgIlNTTVMiLCAiQURWX1NTTVMiKSArICRFeHRyYUZlYXR1cmVzfSArICRFeHRyYU9wdGlvbnMpCgogICAgaWYgKCRFeGl0Q29kZSAtZXEgMzAxMCkgewogICAgICAgIHJldHVybiAkdHJ1ZQogICAgfQoKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICB0aHJvdyAiSW5zdGFsbGF0aW9uIGV4ZWN1dGFibGUgZXhpdGVkIHdpdGggY29kZSAkKCJ7MDpYOH0iIC1mICRFeGl0Q29kZSkgKERlY2ltYWw6ICRFeGl0Q29kZSkiCiAgICB9CgogICAgcmV0dXJuICRmYWxzZQp9CgpmdW5jdGlvbiBOZXctU1FMU2VydmVyRm9yQU9BRyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnN0YWxscyBuZXcgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSB3aXRoIGFsbCBuZWVkZWQgZmVhdHVyZXMgdG8gc2V0IHVwIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cC4KICAgIFJldHVybnMgJHRydWUgaWYgYSByZWJvb3QgaXMgcmVxdWlyZWQgYWZ0ZXIgdGhlIGluc3RhbGxhdGlvbiwgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCAKICAgIGFuZCB0aHJvd3MgYW4gZXhjZXB0aW9uIGluIGNhc2UgaWYgaW5zdGFsbGF0aW9uIGZhaWxzLgoKICAgIC5ERVNDUklQVElPTgogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW5zdGFuY2UgaW4gdW5hdHRlbmRlZCBtb2RlLiBBbGwgZmVhdHVyZXMgZm9yIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cHMgYXJlCiAgICBpbnN0YWxsZWQuCgogICAgQWxsIGF2YWlsYWJpbGl0eSBncm91cCBtZW1iZXJzIG11c3QgYmUgaW5zdGFsbGVkIHdpdGggdGhlIHNhbWUgU1FMU3ZjVXNyRG9tYW4sIFNRTFN2Y1Vzck5hbWUgYW5kIFNRTFN2Y1VzclBhc3N3b3JkIHBhcmFtZXRlcnMuCiAgICBVc2VyIG11c3QgYmUgYSBkb21haW4gdXNlciBzaW5jZSBpdCB3aWxsIGJlIHVzZWQgZm9yIG5vZGVzIGludGVyY29ubmVjdGlvbi4KCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBTUUxTdmNVc3JEb21haW4KICAgIE1TIFNRTCBTZXJ2ZXIgdXNlciBhY2NvdW50IGRvbWFpbiBuYW1lLgoKICAgIC5QQVJBTUVURVIgU1FMU3ZjVXNyTmFtZQogICAgTVMgU1FMIFNlcnZlciB1c2VyIGFjY291bnQgbmFtZS4KCiAgICAuUEFSQU1FVEVSIFNRTFN2Y1VzclBhc3N3b3JkCiAgICBNUyBTUUwgU2VydmVyIHVzZXIgYWNjb3VudCBwYXNzd29yZC4KCiAgICAuUEFSQU1FVEVSIEV4dHJhRmVhdHVyZXMKICAgIExpc3Qgb2YgZmVhdHVyZXMgdG8gYmUgcmVtb3ZlZCBiZXNpZGVzICJTUUxFbmdpbmUiLCAiQ29ubiIsICJTU01TIiwgIkFEVl9TU01TIiwgIkRSRVBMQVlfQ1RMUiIsICJEUkVQTEFZX0NMVCIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTUUxTdmNVc3JEb21haW4sCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kU1FMU3ZjVXNyTmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTUUxTdmNVc3JQYXNzd29yZCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCksCiAgICAgICAgW0hhc2h0YWJsZV0kRXh0cmFPcHRpb25zID0gQHt9CiAgICApCgogICAgJFNldHVwRGlyID0gR2V0LUl0ZW0gJFNldHVwUm9vdAogICAgJFNldHVwRXhlID0gJFNldHVwRGlyLkdldEZpbGVzKCJzZXR1cC5leGUiKVswXQoKICAgICRTUUxVc2VyID0gIiRTUUxTdmNVc3JEb21haW5cJFNRTFN2Y1Vzck5hbWUiCiAgICAkZG9tYWluID0gTmV3LU9iamVjdCBTeXN0ZW0uRGlyZWN0b3J5U2VydmljZXMuRGlyZWN0b3J5RW50cnkoIkxEQVA6Ly8kU1FMU3ZjVXNyRG9tYWluIiwgJFNRTFN2Y1Vzck5hbWUsICRTUUxTdmNVc3JQYXNzd29yZCkKCiAgICBpZiAoJGRvbWFpbi5uYW1lIC1lcSAkbnVsbCkgewogICAgICAgIHRocm93ICJDcmVkZW50aWFscyB2YWxpZGF0aW9uIGZhaWxlZCBmb3IgdXNlciAkU1FMVXNlci4gQ2hlY2sgZG9tYWluLCBsb2dpbiBuYW1lIGFuZCBwYXNzd29yZC4iCiAgICB9CgogICAgUmVzb2x2ZS1TUUxTZXJ2ZXJQcmVyZXF1aXNpdGVzCgogICAgJHBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXJJbnN0YWxsCiAgICAkRXhpdENvZGUgPSAkcGFyc2VyLkV4ZWN1dGVCaW5hcnkoJFNldHVwRXhlLkZ1bGxOYW1lLCBAeyJRIiA9ICRudWxsOyAiRkVBVFVSRVMiID0gQCgiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIsICJEUkVQTEFZX0NUTFIiLCAiRFJFUExBWV9DTFQiKSArICRFeHRyYUZlYXR1cmVzOwogICAgICAgICJBR1RTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiQUdUU1ZDUEFTU1dPUkQiID0gJFNRTFN2Y1VzclBhc3N3b3JkOyAiQVNTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiQVNTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7ICJBU1NZU0FETUlOQUNDT1VOVFMiID0gJFNRTFVTZXI7CiAgICAgICAgIlNRTFNWQ0FDQ09VTlQiID0gJFNRTFVzZXI7ICJTUUxTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7ICJTUUxTWVNBRE1JTkFDQ09VTlRTIiA9ICRTUUxVc2VyOyAiSVNTVkNBQ0NPVU5UIiA9ICRTUUxVc2VyOyAiSVNTVkNQQVNTV09SRCIgPSAkU1FMU3ZjVXNyUGFzc3dvcmQ7IAogICAgICAgICJSU1NWQ0FDQ09VTlQiID0gJFNRTFVzZXI7ICJSU1NWQ1BBU1NXT1JEIiA9ICRTUUxTdmNVc3JQYXNzd29yZH0gKyAkRXh0cmFPcHRpb25zKQoKICAgIGlmICgkRXhpdENvZGUgLWVxIDMwMTApIHsKICAgICAgICByZXR1cm4gJHRydWUKICAgIH0KCiAgICBpZiAoJEV4aXRDb2RlIC1uZSAwKSB7CiAgICAgICAgdGhyb3cgIkluc3RhbGxhdGlvbiBleGVjdXRhYmxlIGV4aXRlZCB3aXRoIGNvZGUgJCgiezA6WDh9IiAtZiAkRXhpdENvZGUpIChEZWNpbWFsOiAkRXhpdENvZGUpIgogICAgfQoKICAgIHJldHVybiAkZmFsc2UKfQoKZnVuY3Rpb24gUmVtb3ZlLVNRTFNlcnZlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBVbmluc3RhbGxzIE1TIFNRTCBTZXJ2ZXIgaW5zdGFuY2UgaW5zdGFsbGVkIHdpdGggTmV3LVNRTFNlcnZlciBjbWRsZXQKCiAgICAuREVTQ1JJUFRJT04KICAgIFVuaW5zdGFsbHMgTVMgU1FMIFNlcnZlciBpbnN0YW5jZSBpbnN0YWxsZWQgd2l0aCBOZXctU1FMU2VydmVyIGNtZGxldCBpbiB1bmF0dGVuZGVkIG1vZGUKCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBFeHRyYUZlYXR1cmVzCiAgICBMaXN0IG9mIGZlYXR1cmVzIHRvIGJlIHJlbW92ZWQgYmVzaWRlcyAiU1FMRW5naW5lIiwgIkNvbm4iLCAiU1NNUyIsICJBRFZfU1NNUyIuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdCwKICAgICAgICBbYXJyYXldJEV4dHJhRmVhdHVyZXMgPSBAKCkKICAgICkKCiAgICAkU2V0dXBEaXIgPSBHZXQtSXRlbSAkU2V0dXBSb290CiAgICAkU2V0dXBFeGUgPSAkU2V0dXBEaXIuR2V0RmlsZXMoInNldHVwLmV4ZSIpWzBdCgogICAgJHBhcnNlciA9IE5ldy1PcHRpb25QYXJzZXJVbmluc3RhbGwKICAgICRFeGl0Q29kZSA9ICRwYXJzZXIuRXhlY3V0ZUJpbmFyeSgkU2V0dXBFeGUuRnVsbE5hbWUsIEB7IlEiID0gJG51bGw7ICJGRUFUVVJFUyIgPSBAKCJTUUxFbmdpbmUiLCAiQ29ubiIsICJTU01TIiwgIkFEVl9TU01TIikgKyAkRXh0cmFGZWF0dXJlc30pCgogICAgaWYgKCRFeGl0Q29kZSAtbmUgMCkgewogICAgICAgIHRocm93ICJJbnN0YWxsYXRpb24gZXhlY3V0YWJsZSBleGl0ZWQgd2l0aCBjb2RlICQoInswOlg4fSIgLWYgJEV4aXRDb2RlKSIKICAgIH0KfQoKZnVuY3Rpb24gSW5zdGFsbC1TUUxTZXJ2ZXJGb3JTeXNQcmVwIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluIHN5c3ByZXAgbW9kZS4KCiAgICAuREVTQ1JJUFRJT04KICAgIEluc3RhbGxzIG5ldyBNUyBTUUwgU2VydmVyIGluIHN5c3ByZXAgbW9kZS4gUmV0dXJucyAkdHJ1ZSBpZiBhIHJlYm9vdCBpcyByZXF1aXJlZCBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLCAKICAgICRmYWxzZSBpZiBhIHJlYm9vdCBpcyBub3QgcmVxdWlyZWQgYW5kIHRocm93cyBhbiBleGNlcHRpb24gaW4gY2FzZSBpZiBpbnN0YWxsYXRpb24gZmFpbHMuCgogICAgU2V0dXAgbXVzdCBiZSBjb21wbGV0ZWQgYWZ0ZXIgYm9vdGluZyByZWFybWVkIG1hY2hpbmUgYnkgdXNpbmcgQ29tcGxldGUtU1FMU2VydmVyIGNtZGxldAoKICAgIC5QQVJBTUVURVIgU2V0dXBSb290CiAgICBNUyBTUUwgU2VydmVyIGluc3RhbGxhdGlvbiBmaWxlcyByb290IGRpcmVjdG9yeS4gTm9ybWFsbHkgaXQgaXMganVzdCBEVkQgZHJpdmUgbmFtZS4KCiAgICAuUEFSQU1FVEVSIEV4dHJhRmVhdHVyZXMKICAgIExpc3Qgb2YgZmVhdHVyZXMgdG8gYmUgaW5zdGFsbGVkIGluIGFkZGl0aW9uIHRvIGRlZmF1bHQgIlNRTEVuZ2luZSIuIE5vdGUgdGhhdCBwcmlvciB0bwogICAgU1FMIFNlcnZlciB2ZXJzaW9uIDIwMTIgU2VydmljZSBQYWNrIDEgQ3VtdWxhdGl2ZSBVcGRhdGUgMiAoSmFudWFyeSAyMDEzKSBvbmx5ICJSZXBsaWNhdGlvbiIsIAogICAgIkZ1bGxUZXh0IiBhbmQgIlJTIiBtYXkgYmUgaW5zdGFsbGVkIGluIGFkZGl0aW9uIHRvICJTUUxFbmdpbmUiLiBTZWUgdGhlIGZvbGxvd2luZyBsaW5rIGZvcgogICAgZGV0aWFsczogaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTQ0MjU5LmFzcHgKCiAgICAjPgp9CgpmdW5jdGlvbiBJbnN0YWxsLVNRTFNlcnZlckZvclN5c1ByZXAgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW4gc3lzcHJlcCBtb2RlLgoKICAgIC5ERVNDUklQVElPTgogICAgSW5zdGFsbHMgbmV3IE1TIFNRTCBTZXJ2ZXIgaW4gc3lzcHJlcCBtb2RlLiBSZXR1cm5zICR0cnVlIGlmIGEgcmVib290IGlzIHJlcXVpcmVkIGFmdGVyIHRoZSBpbnN0YWxsYXRpb24sIAogICAgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCBhbmQgdGhyb3dzIGFuIGV4Y2VwdGlvbiBpbiBjYXNlIGlmIGluc3RhbGxhdGlvbiBmYWlscy4KCiAgICBTZXR1cCBtdXN0IGJlIGNvbXBsZXRlZCBhZnRlciBib290aW5nIHJlYXJtZWQgbWFjaGluZSBieSB1c2luZyBDb21wbGV0ZS1TUUxTZXJ2ZXIgY21kbGV0CgogICAgLlBBUkFNRVRFUiBTZXR1cFJvb3QKICAgIE1TIFNRTCBTZXJ2ZXIgaW5zdGFsbGF0aW9uIGZpbGVzIHJvb3QgZGlyZWN0b3J5LiBOb3JtYWxseSBpdCBpcyBqdXN0IERWRCBkcml2ZSBuYW1lLgoKICAgIC5QQVJBTUVURVIgRXh0cmFGZWF0dXJlcwogICAgTGlzdCBvZiBmZWF0dXJlcyB0byBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gZGVmYXVsdCAiU1FMRW5naW5lIi4gTm90ZSB0aGF0IHByaW9yIHRvCiAgICBTUUwgU2VydmVyIHZlcnNpb24gMjAxMiBTZXJ2aWNlIFBhY2sgMSBDdW11bGF0aXZlIFVwZGF0ZSAyIChKYW51YXJ5IDIwMTMpIG9ubHkgIlJlcGxpY2F0aW9uIiwgCiAgICAiRnVsbFRleHQiIGFuZCAiUlMiIG1heSBiZSBpbnN0YWxsZWQgaW4gYWRkaXRpb24gdG8gIlNRTEVuZ2luZSIuIFNlZSB0aGUgZm9sbG93aW5nIGxpbmsgZm9yCiAgICBkZXRpYWxzOiBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNDQyNTkuYXNweAoKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kU2V0dXBSb290LAogICAgICAgIFthcnJheV0kRXh0cmFGZWF0dXJlcyA9IEAoKQogICAgKQoKICAgICRTZXR1cERpciA9IEdldC1JdGVtICRTZXR1cFJvb3QKICAgICRTZXR1cEV4ZSA9ICRTZXR1cERpci5HZXRGaWxlcygic2V0dXAuZXhlIilbMF0KCiAgICBSZXNvbHZlLVNRTFNlcnZlclByZXJlcXVpc2l0ZXMKCiAgICAkcGFyc2VyID0gTmV3LU9wdGlvblBhcnNlclByZXBhcmVJbWFnZQogICAgJEV4aXRDb2RlID0gJHBhcnNlci5FeGVjdXRlQmluYXJ5KCRTZXR1cEV4ZS5GdWxsTmFtZSwgQHsiUVMiID0gJG51bGw7ICJGRUFUVVJFUyIgPSBAKCJTUUxFbmdpbmUiKSArICRFeHRyYUZlYXR1cmVzIH0pCgogICAgaWYgKCRFeGl0Q29kZSAtZXEgMzAxMCkgewogICAgICAgIHJldHVybiAkdHJ1ZQogICAgfQoKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICB0aHJvdyAiSW5zdGFsbGF0aW9uIGV4ZWN1dGFibGUgZXhpdGVkIHdpdGggY29kZSAkKCJ7MDpYOH0iIC1mICRFeGl0Q29kZSkgKERlY2ltYWw6ICRFeGl0Q29kZSkiCiAgICB9CgogICAgcmV0dXJuICRmYWxzZQp9CgpmdW5jdGlvbiBDb21wbGV0ZS1TUUxTZXJ2ZXJBZnRlclN5c1ByZXAgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ29tcGxldGVzIHByZXZpb3VzbHkgcHJlcGFyZWQgd2l0aCAiSW5zdGFsbC1TUUxTZXJ2ZXJGb3JTeXNQcmVwIiBNUyBTUUwgU2VydmVyIGFmdGVyIHRoZSBzeXN0ZW0gd2FzIHJlYXJtZWQuCgogICAgLkRFU0NSSVBUSU9OCiAgICBDb21wbGV0ZXMgcHJldmlvdXNseSBwcmVwYXJlZCB3aXRoICJJbnN0YWxsLVNRTFNlcnZlckZvclN5c1ByZXAiIE1TIFNRTCBTZXJ2ZXIgYWZ0ZXIgdGhlIHN5c3RlbSB3YXMgcmVhcm1lZC4KICAgIFJldHVybnMgJHRydWUgaWYgYSByZWJvb3QgaXMgcmVxdWlyZWQgYWZ0ZXIgdGhlIGluc3RhbGxhdGlvbiwgJGZhbHNlIGlmIGEgcmVib290IGlzIG5vdCByZXF1aXJlZCBhbmQgdGhyb3dzIAogICAgYW4gZXhjZXB0aW9uIGluIGNhc2UgaWYgaW5zdGFsbGF0aW9uIGZhaWxzLgoKICAgIFNldHVwIG11c3QgYmUgY29tcGxldGVkIGFmdGVyIGJvb3RpbmcgcmVhcm1lZCBtYWNoaW5lIGJ5IHVzaW5nIENvbXBsZXRlLVNRTFNlcnZlciBjbWRsZXQKCiAgICAuUEFSQU1FVEVSIFNldHVwUm9vdAogICAgTVMgU1FMIFNlcnZlciBpbnN0YWxsYXRpb24gZmlsZXMgcm9vdCBkaXJlY3RvcnkuIE5vcm1hbGx5IGl0IGlzIGp1c3QgRFZEIGRyaXZlIG5hbWUuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNldHVwUm9vdAogICAgKQoKICAgICRTZXR1cERpciA9IEdldC1JdGVtICRTZXR1cFJvb3QKICAgICRTZXR1cEV4ZSA9ICRTZXR1cERpci5HZXRGaWxlcygic2V0dXAuZXhlIilbMF0KCiAgICAkcGFyc2VyID0gTmV3LU9wdGlvblBhcnNlckNvbXBsZXRlSW1hZ2UKICAgICRFeGl0Q29kZSA9ICRwYXJzZXIuRXhlY3V0ZUJpbmFyeSgkU2V0dXBFeGUuRnVsbE5hbWUsIEB7IlFTIiA9ICRudWxsfSkKCiAgICBpZiAoJEV4aXRDb2RlIC1lcSAzMDEwKSB7CiAgICAgICAgcmV0dXJuICR0cnVlCiAgICB9CgogICAgaWYgKCRFeGl0Q29kZSAtbmUgMCkgewogICAgICAgIHRocm93ICJJbnN0YWxsYXRpb24gZXhlY3V0YWJsZSBleGl0ZWQgd2l0aCBjb2RlICQoInswOlg4fSIgLWYgJEV4aXRDb2RlKSAoRGVjaW1hbDogJEV4aXRDb2RlKSIKICAgIH0KCiAgICByZXR1cm4gJGZhbHNlCn0KCmZ1bmN0aW9uIENvbnZlcnRUby1TUUxTdHJpbmcgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ29udmVydHMgYXJndW1lbnQgdG8gYSB2YWxpZCBTUUwgc3RyaW5nIGluIHF1b3RlcwoKICAgIC5ERVNDUklQVElPTgogICAgQ29udmVydHMgYXJndW1lbnQgdG8gYSB2YWxpZCBTUUwgc3RyaW5nIGluIHF1b3Rlcy4gVGhlIHN0cmluZyBtYXkgY29udGFpbiBhbnkgY2hhcmFjdGVycy4KICAgIFNlZSBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvbXMxNzk4OTkuYXNweAoKICAgIC5QQVJBTUVURVIgUwogICAgU3RyaW5nIHRvIGNvbnZlcnQKICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlLCBWYWx1ZUZyb21QaXBlbGluZSA9ICR0cnVlKV0KICAgICAgICBbc3RyaW5nXSRTCiAgICApCiAgICAKICAgIHJldHVybiAiJyQoJFMgLXJlcGxhY2UgIiciLCAiJyciKSciCn0KCmZ1bmN0aW9uIENvbnZlcnRUby1TUUxOYW1lIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbnZlcnRzIGFyZ3VtZW50IHRvIGEgdmFsaWQgU1FMIG5hbWUgaW4gYnJhY2tldHMKCiAgICAuREVTQ1JJUFRJT04KICAgIENvbnZlcnRzIGFyZ3VtZW50IHRvIGEgdmFsaWQgU1FMIG5hbWUgaW4gYnJhY2tldHMuIFRoZSBzdHJpbmcgbWF5IGNvbnRhaW4gYW55IGNoYXJhY3RlcnMuCiAgICBTZWUgaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zMTc1ODc0LmFzcHgKCiAgICAuUEFSQU1FVEVSIFMKICAgIFN0cmluZyB0byBjb252ZXJ0CiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSwgVmFsdWVGcm9tUGlwZWxpbmUgPSAkdHJ1ZSldCiAgICAgICAgW3N0cmluZ10kUwogICAgKQogICAgcmV0dXJuICJbJCgkUyAtcmVwbGFjZSAiXSIsICJdXSIpXSIKfQoKZnVuY3Rpb24gSW52b2tlLVNRTFRleHQgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgSW52b2tlcyBTUUwgdGV4dAoKICAgIC5ERVNDUklQVElPTgogICAgSW52b2tlcyBTUUwgdGV4dC4gUmV0dXJucyByYXcgU1FMIHNlcnZlciBvdXRwdXQuCgogICAgLlBBUkFNRVRFUiBTUUwKICAgIFNRTCBUZXh0CgogICAgLlBBUkFNRVRFUiBVc2VyCiAgICBTUUwgU2VydmVyIHVzZXIgbmFtZQoKICAgIC5QQVJBTUVURVIgUGFzc3dvcmQKICAgIFNRTCBTZXJ2ZXIgdXNlciBwYXNzd29yZAogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNRTCwKICAgICAgICBbc3RyaW5nXSRVc2VyID0gJG51bGwsCiAgICAgICAgW3N0cmluZ10kUGFzc3dvcmQgPSAkbnVsbAogICAgKQoKICAgICNXcml0ZS1XYXJuaW5nICIkU1FMYG4iCiAgICAjcmV0dXJuCgogICAgJEJpbmFyeSA9IEdldC1Db21tYW5kICJzcWxjbWQuZXhlIgoKICAgICR0ZW1wRmlsZSA9IFtJTy5QYXRoXTo6R2V0VGVtcEZpbGVOYW1lKCkKICAgICR0ZW1wRmlsZSA9IEdldC1JdGVtICR0ZW1wRmlsZQogICAgU2V0LUNvbnRlbnQgLVBhdGggJHRlbXBGaWxlIC1WYWx1ZSAkU1FMCgogICAgJENvbW1hbmRMaW5lID0gQCgnLWgnLCAnLTEnLCAnLWInLCAnLWknLCAiYCIkKCR0ZW1wRmlsZS5GdWxsTmFtZSlgIiIpCiAgICBpZiAoKCRVc2VyIC1uZSAkbnVsbCkgLWFuZCAoJFVzZXIgLW5lICcnKSkgewogICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICctVScKICAgICAgICAkQ29tbWFuZExpbmUgPSAkQ29tbWFuZExpbmUgKyAkVXNlcgogICAgICAgICRDb21tYW5kTGluZSA9ICRDb21tYW5kTGluZSArICctUCcKICAgICAgICAkQ29tbWFuZExpbmUgPSAkQ29tbWFuZExpbmUgKyAkUGFzc3dvcmQKICAgIH0KCiAgICBXcml0ZS1EZWJ1ZyAiRXhlY3V0aW5nOiBgbiRTUUxgbiIKICAgIFtzdHJpbmddJG91dHB1dCA9ICYkQmluYXJ5ICRDb21tYW5kTGluZQoKICAgICRFeGl0Q29kZSA9ICRMYXN0RXhpdENvZGUKICAgIGlmICgkRXhpdENvZGUgLW5lIDApIHsKICAgICAgICBXcml0ZS1XYXJuaW5nICRvdXRwdXQKICAgICAgICB0aHJvdyAiU1FMQ01ELkVYRSByZXR1cm5lZCB3aXRoIGV4aXQgY29kZSAkRXhpdENvZGUgd2hpbGUgcnVubmluZyAkQmluYXJ5ICRDb21tYW5kTGluZSIKICAgIH0KICAgCiAgICBSZW1vdmUtSXRlbSAkdGVtcEZpbGUKCiAgICByZXR1cm4gJG91dHB1dAp9CgpmdW5jdGlvbiBOZXctU1FMVXNlciB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBJbnZva2VzIFNRTCB0ZXh0CgogICAgLkRFU0NSSVBUSU9OCiAgICBJbnZva2VzIFNRTCB0ZXh0CgogICAgLlBBUkFNRVRFUiBTUUwKICAgIFNRTCBUZXh0CgogICAgLlBBUkFNRVRFUiBVc2VyCiAgICBTUUwgU2VydmVyIHVzZXIgbmFtZQoKICAgIC5QQVJBTUVURVIgUGFzc3dvcmQKICAgIFNRTCBTZXJ2ZXIgdXNlciBwYXNzd29yZAogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtzdHJpbmddJFNRTCwKICAgICAgICBbc3RyaW5nXSRVc2VyID0gJG51bGwsCiAgICAgICAgW3N0cmluZ10kUGFzc3dvcmQgPSAkbnVsbAogICAgKQp9CgpmdW5jdGlvbiBOZXctUGFzc3dvcmQgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyByYW5kb20gcGFzc3dvcmQgb2YgdGhlIHNwZWNpZmllZCBsZW5ndGgKCiAgICAuREVTQ1JJUFRJT04KICAgIFBhc3N3b3JkIGNvbnRhaW5zIHJhbmRvbSBjaGFyYWN0ZXJzIGEteiwgQS1aLCBudW1iZXJzIGFuZCBzcGVjaWFsIGNoYXJhY3RlcnMuCiAgICBUaGVyZSBpcyBubyBndWFyYW50ZWUgdGhhdCBhbGwgdGhlIHR5cGVzIG9mIHN5bWJvbHMgd2lsbCBiZSBwcmVzZW50IGluIHRoZSBwYXNzd29yZC4KCiAgICAuUEFSQU1FVEVSIExlbmd0aAogICAgRGVzaXJlZCBsZW5ndGggb2YgdGhlIHBhc3N3b3JkLgoKICAgICM+CiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbaW50XSRMZW5ndGg9NgogICAgKQoKICAgICRSZXN1bHQgPSAiIgogICAgJGFscGhhID0gImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5IUAjJCVeJiooKSdgImBgXytbXVx7fXw7OiwuLzw+P34iCiAgICB3aGlsZSAoJExlbmd0aCAtZ3QgMCkgewogICAgICAgICR4ID0gR2V0LVJhbmRvbSAkYWxwaGEuTGVuZ3RoCiAgICAgICAgJGMgPSAkYWxwaGFbJHhdCiAgICAgICAgJFJlc3VsdCA9ICIkUmVzdWx0JGMiCiAgICAgICAgJExlbmd0aCA9ICRMZW5ndGggLSAxCiAgICB9CiAgICByZXR1cm4gJFJlc3VsdAp9CgpmdW5jdGlvbiBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50IHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgbWlycm9yaW5nIGVuZHBvaW50LgoKICAgIC5ERVNDUklQVElPTgogICAgTWFzdGVyIGtleSBpcyBjcmVhdGVkIGlmIG5lY2Vzc2FyeS4gSG9zdCBjZXJ0aWZpY2F0ZSBpcyBjcmVhdGVkIHdoZW4gbmVjZXNzYXJ5IGVpdGhlciAobm9ybWFsbHkgb24gZmlyc3QgZW5kcG9pbnQgY3JlYXRpb24pLgoKICAgIEVuZHBvaW50IGFuZCBjZXJ0aWZpY2F0ZSBhcmUgcmVjcmVhdGVkIGluIGNhc2UgaWYgbWFzdGVyIGtleSBkaWQgbm90IGV4aXN0ZWQgKHNob3VsZCBub3Qgbm9ybWFsbHkgaGFwcGVuKS4KCiAgICBFbmRwb2ludCBpcyByZWNyZWF0ZWQgaW4gY2FzZSBpZiBjZXJ0aWZpY2F0ZSBkaWQgbm90IGV4aXN0ZWQgKHNob3VsZCBub3QgaGFwcGVuIHVubGVzcyB0aGUgZW5kcG9pbnQgd2FzIGNyZWF0ZWQgbWFudWFsbHkpLgoKICAgIE1pcnJvcmluZyBlbmRwb2ludCBpcyBjcmVhdGVkIHVubGVzcyBvbmUgYWxyZWFkeSBleGlzdHMuIFRoZSBlbmRwb2ludCBpcyBjcmVhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBuYW1lLiBXaGVuIHRoZSBlbmRwb2ludAogICAgYWxyZWFkeSBleGlzdHMgaXMgaXMgdW5jaGFuZ2VkLgoKICAgIEVuZHBvaW50IHBvcnQgaXMgc2VsZWN0ZWQgYXV0b21hdGljYWxseSBhcyA0MDIyIG9yIGFzIGZpcnN0IGF2YWlsYWJsZSBwb3J0IGFmdGVyIDQwMjIgaW4gY2FzZSBpZiA0MDIyIGlzIGFscmVhZHkgbGlzdGVuaW5nLgogICAgSWYgdGhlcmUgaXMgbm8gZmlyZXdhbGwgcnVsZSB3aXRoIG5hbWUgJ0RhdGFiYXNlTWlycm9yaW5nLVRDUC17cG9ydG51bWJlcn0nLCBhbGxvd2luZyBydWxlIGlzIGNyZWF0ZWQuCgogICAgQ2VydGlmaWNhdGUgaXMgc3RvcmVkIGluIHRoZSBzcGVjaWZpZWQgZmlsZS4KCiAgICBSZXR1cm5zIGVuZHBvaW50IGxpc3RlbmluZyBwb3J0LgoKICAgIC5QQVJBTUVURVIgRW5jcnlwdGlvblBhc3N3b3JkCiAgICBFbmNyeXB0aW9uIHBhc3N3b3JkIHVzZWQgdG8gY3JlYXRlIGNlcnRpZmljYXRlLgoKICAgIC5QQVJBTUVURVIgQ2VydGlmaWNhdGVGaWxlTmFtZQogICAgQ2VydGlmaWNhdGUgdGFyZ2V0IGZpbGUgbmFtZS4gRmlsZSBNVVNUIE5PVCBleGlzdC4KCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRDZXJ0aWZpY2F0ZUZpbGVOYW1lCiAgICApCgogICAgJEVuZHBvaW50TmFtZSA9ICdNaXJyb3JpbmdFbmRwb2ludCcKCiAgICAkRm9sZGVyID0gR2V0LUl0ZW0gJFdvcmtEaXIKCiAgICAkSCA9ICRFbnY6Q09NUFVURVJOQU1FIC1yZXBsYWNlICdbXkEtWmEtejAtOV9dJywgJ18nCgogICAgJFBvcnQgPSBHZXQtTmV4dEZyZWVQb3J0IDQwMjIKCiAgICAkQ3JlYXRlTWFzdGVyS2V5ID0gIlVTRSBtYXN0ZXI7CgogICAgICAgICAgICAgICAgICAgICAgICBJRiBOT1QgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLnN5bW1ldHJpY19rZXlzIHdoZXJlIG5hbWUgPSAnIyNNU19EYXRhYmFzZU1hc3RlcktleSMjJykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBNQVNURVIgS0VZIEVOQ1JZUFRJT04gQlkgUEFTU1dPUkQgPSAkKENvbnZlcnRUby1TUUxTdHJpbmcgJEVuY3J5cHRpb25QYXNzd29yZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWUgPSAnJHtIfV9jZXJ0JykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRFJPUCBDRVJUSUZJQ0FURSAke0h9X2NlcnQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICAgICAgSUYgRVhJU1RTKFNFTEVDVCAqIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBUT1AgMSBgQG5hbWUgPSBuYW1lIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFWEVDICgnRFJPUCBFTkRQT0lOVCBbJyArIGBAbmFtZSArICddJykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIElGIE5PVCBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWUgPSAnJHtIfV9jZXJ0JykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBDRVJUSUZJQ0FURSAke0h9X2NlcnQgV0lUSCBTVUJKRUNUID0gJyR7SH0gZW5kcG9pbnQgY2VydGlmaWNhdGUnOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgSUYgRVhJU1RTKFNFTEVDVCAqIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBUT1AgMSBgQG5hbWUgPSBuYW1lIEZST00gc3lzLmVuZHBvaW50cyBXSEVSRSB0eXBlX2Rlc2M9J0RBVEFCQVNFX01JUlJPUklORycKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFWEVDICgnRFJPUCBFTkRQT0lOVCBbJyArIGBAbmFtZSArICddJykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIEJBQ0tVUCBDRVJUSUZJQ0FURSAke0h9X2NlcnQgVE8gRklMRSA9ICQoQ29udmVydFRvLVNRTFN0cmluZyAiJENlcnRpZmljYXRlRmlsZU5hbWUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBwb3J0IGludAogICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoU0VMRUNUICogRlJPTSBzeXMuZW5kcG9pbnRzIFdIRVJFIHR5cGVfZGVzYz0nREFUQUJBU0VfTUlSUk9SSU5HJykKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBgQHBvcnQgPSBwb3J0IEZST00gc3lzLnRjcF9lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnCiAgICAgICAgICAgICAgICAgICAgICAgIEVORCBFTFNFCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUkVBVEUgRU5EUE9JTlQgJChDb252ZXJ0VG8tU1FMTmFtZSAkRW5kcG9pbnROYW1lKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNUQVRFID0gU1RBUlRFRAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFTIFRDUCAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExJU1RFTkVSX1BPUlQgPSAkUG9ydAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIExJU1RFTkVSX0lQID0gQUxMCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGT1IgREFUQUJBU0VfTUlSUk9SSU5HICggCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFVVEhFTlRJQ0FUSU9OID0gQ0VSVElGSUNBVEUgJHtIfV9jZXJ0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgRU5DUllQVElPTiA9IFJFUVVJUkVEIEFMR09SSVRITSBBRVMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBST0xFID0gQUxMCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCBgQHBvcnQgPSAkUG9ydAogICAgICAgICAgICAgICAgICAgICAgICBFTkQKCiAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCAncG9ydDooJyArIENPTlZFUlQoVkFSQ0hBUiwgYEBwb3J0KSArICcpJyBhcyBwb3J0CiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICAiCgogICAgJHJhd2RhdGEgPSBJbnZva2UtU1FMVGV4dCAtU1FMICRDcmVhdGVNYXN0ZXJLZXkKICAgIFtpbnRdJFBvcnQgPSAkcmF3ZGF0YSAtcmVwbGFjZSAnLipwb3J0OlwoKFteKV0qKVwpLionLCAnJDEnCgogICAgIyBPcGVuIHBvcnQgaW4gV2luZG93cyBGaXJld2FsbAoKICAgICRQb3J0T3BlbiA9ICRmYWxzZQogICAgJFJ1bGVOYW1lID0gIkRhdGFiYXNlTWlycm9yaW5nLVRDUC0kUG9ydCIKICAgIEdldC1OZXRGaXJld2FsbFJ1bGUgfCBGb3JlYWNoLU9iamVjdCB7CiAgICAgICAgaWYgKCRfLk5hbWUgLWVxICRSdWxlTmFtZSkgewogICAgICAgICAgICAkUG9ydE9wZW4gPSAkdHJ1ZQogICAgICAgIH0KICAgIH0KICAgIGlmICgtbm90ICRQb3J0T3BlbikgewogICAgICAgICREaXNwbGF5TmFtZSA9ICJNUyBTUUwgRGF0YWJhc2UgTWlycm9yaW5nIEVuZHBvaW50IGF0IFRDUCBwb3J0ICRQb3J0IgogICAgICAgIE5ldy1OZXRGaXJld2FsbFJ1bGUgLU5hbWUgJFJ1bGVOYW1lIC1EaXNwbGF5TmFtZSAkRGlzcGxheU5hbWUgLURlc2NyaXB0aW9uICREaXNwbGF5TmFtZSAtUHJvdG9jb2wgVENQIC1Mb2NhbFBvcnQgJFBvcnQgLUVuYWJsZWQgVHJ1ZSAtUHJvZmlsZSBBbnkgLUFjdGlvbiBBbGxvdwogICAgfQogICAgIAogICAgcmV0dXJuICRQb3J0Cn0KCmZ1bmN0aW9uIENvbXBsZXRlLU1pcnJvcmluZ0VuZHBvaW50IHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbXBsZXRlcyBtaXJyb3JpbmcgZW5kcG9pbnQKCiAgICAuREVTQ1JJUFRJT04KICAgIEFsbG93cyBpbmJvdW5kIGNvbm5lY3Rpb25zIGZyb20gcmVtb3RlIGhvc3QKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpciwKICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TG9naW4sCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdFVzZXIsCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdFBhc3N3b3JkCiAgICApCgogICAgJEZvbGRlciA9IEdldC1JdGVtICRSZW1vdGVXb3JrRGlyCiAgICAkUmVtb3RlV29ya0RpciA9ICRGb2xkZXIuRnVsbE5hbWUKCiAgICAkSCA9ICRSZW1vdGVIb3N0TmFtZSAtcmVwbGFjZSAnW15BLVphLXowLTlfXScsICdfJwoKICAgIGlmICgtbm90ICRSZW1vdGVIb3N0TG9naW4pIHsKICAgICAgICAkUmVtb3RlSG9zdExvZ2luID0gIiR7SH1fbG9naW4iCiAgICB9CiAgICBpZiAoLW5vdCAkUmVtb3RlSG9zdFVzZXIpIHsKICAgICAgICAkUmVtb3RlSG9zdFVzZXIgPSAiJHtIfV91c2VyIgogICAgfQogICAgaWYgKC1ub3QgJFJlbW90ZUhvc3RQYXNzd29yZCkgewogICAgICAgICRSZW1vdGVIb3N0UGFzc3dvcmQgPSAiJChOZXctUGFzc3dvcmQgMTApYUEjMyIKICAgIH0KCiAgICAkU1FMID0gICAgICAgICAgICAgIlVTRSBtYXN0ZXI7CgogICAgICAgICAgICAgICAgICAgICAgICBJRiBOT1QgRVhJU1RTKHNlbGVjdCAqIGZyb20gc3lzLnNxbF9sb2dpbnMgd2hlcmUgbmFtZT0kKENvbnZlcnRUby1TUUxTdHJpbmcgJFJlbW90ZUhvc3RMb2dpbikpCiAgICAgICAgICAgICAgICAgICAgICAgIEJFR0lOCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUkVBVEUgTE9HSU4gJChDb252ZXJ0VG8tU1FMTmFtZSAkUmVtb3RlSG9zdExvZ2luKSBXSVRIIFBBU1NXT1JEID0gJChDb252ZXJ0VG8tU1FMU3RyaW5nICRSZW1vdGVIb3N0UGFzc3dvcmQpOwogICAgICAgICAgICAgICAgICAgICAgICBFTkQKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIElGIE5PVCBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuc3lzdXNlcnMgd2hlcmUgbmFtZT0kKENvbnZlcnRUby1TUUxTdHJpbmcgJFJlbW90ZUhvc3RVc2VyKSkKICAgICAgICAgICAgICAgICAgICAgICAgQkVHSU4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIENSRUFURSBVU0VSICQoQ29udmVydFRvLVNRTE5hbWUgJFJlbW90ZUhvc3RVc2VyKSBGT1IgTE9HSU4gJChDb252ZXJ0VG8tU1FMTmFtZSAkUmVtb3RlSG9zdExvZ2luKTsKICAgICAgICAgICAgICAgICAgICAgICAgRU5ECiAgICAgICAgICAgICAgICAgICAgICAgIEdPCgogICAgICAgICAgICAgICAgICAgICAgICBJRiBFWElTVFMoc2VsZWN0ICogZnJvbSBzeXMuY2VydGlmaWNhdGVzIHdoZXJlIG5hbWU9JyR7SH1fcmVtb3RlX2NlcnQnKQogICAgICAgICAgICAgICAgICAgICAgICBCRUdJTgogICAgICAgICAgICAgICAgICAgICAgICAgICAgRFJPUCBDRVJUSUZJQ0FURSAke0h9X3JlbW90ZV9jZXJ0CiAgICAgICAgICAgICAgICAgICAgICAgIEVORAogICAgICAgICAgICAgICAgICAgICAgICBHTwoKICAgICAgICAgICAgICAgICAgICAgICAgQ1JFQVRFIENFUlRJRklDQVRFICR7SH1fcmVtb3RlX2NlcnQgQVVUSE9SSVpBVElPTiAkKENvbnZlcnRUby1TUUxOYW1lICRSZW1vdGVIb3N0VXNlcikgRlJPTSBGSUxFID0gJChDb252ZXJ0VG8tU1FMU3RyaW5nICIkUmVtb3RlV29ya0RpclxjZXJ0aWZpY2F0ZS5jZXIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgR08KCiAgICAgICAgICAgICAgICAgICAgICAgIERFQ0xBUkUgYEBuYW1lIFZBUkNIQVIoMjU1KQogICAgICAgICAgICAgICAgICAgICAgICBTRUxFQ1QgVE9QIDEgYEBuYW1lID0gbmFtZSBGUk9NIHN5cy5lbmRwb2ludHMgV0hFUkUgdHlwZV9kZXNjPSdEQVRBQkFTRV9NSVJST1JJTkcnCiAgICAgICAgICAgICAgICAgICAgICAgIFNFTEVDVCAnbmFtZTooJyArIGBAbmFtZSArICcpJyBhcyBuYW1lCiAgICAgICAgICAgICAgICAgICAgICAgICIKCiAgICAkcmF3ZGF0YSA9IEludm9rZS1TUUxUZXh0IC1TUUwgJFNRTAogICAgJEVuZHBvaW50TmFtZSA9ICRyYXdkYXRhIC1yZXBsYWNlICcuKm5hbWU6XCgoW14pXSopXCkuKicsICckMScKICAgICRTUUwgPSAgICAgICAgICAgICAiR1JBTlQgQ09OTkVDVCBPTiBFTkRQT0lOVDo6JChDb252ZXJ0VG8tU1FMTmFtZSAkRW5kcG9pbnROYW1lKSBUTyAkKENvbnZlcnRUby1TUUxOYW1lICRSZW1vdGVIb3N0TG9naW4pIgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFNRTCkKfQoKZnVuY3Rpb24gQ29tcGxldGUtU1FMTWlycm9yIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENvbXBsZXRlcyBjcmVhdGlvbiBvZiBtaXJyb3JlZCBTUUwgZGF0YWJhc2UKCiAgICAuREVTQ1JJUFRJT04KICAgIFRoaXMgY21kbGV0IHNob3VsZCBiZSBmaXJzdCBleGVjdXRlZCBvbiBtaXJyb3Igc2VydmVyIGFuZCB0aGVuIG9uIHByaW5jaXBhbCBzZXJ2ZXIuCiAgICBPdGhlcndpc2UgaXQgd2lsbCBmYWlsIChob3dldmVyIGl0IG1heSBiZSBleGVjdXRlZCBhZ2FpbiB3aXRoIG5vIGhhcm0pLgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbSW50XSRSZW1vdGVQb3J0LAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFiYXNlTmFtZQogICAgKQoKICAgICRVcmwgPSAiVENQOi8vJHtSZW1vdGVIb3N0TmFtZX06JHtSZW1vdGVQb3J0fSIKICAgICRBbHRlckRiID0gIkFMVEVSIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgU0VUIFBBUlRORVIgPSAkKENvbnZlcnRUby1TUUxTdHJpbmcgJFVybCk7CiAgICAgICAgICAgICAgICBHTyIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRBbHRlckRiKQp9CgpmdW5jdGlvbiBOZXctU1FMRGF0YWJhc2UgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ3JlYXRlcyBlbXB0eSBTUUwgZGF0YWJhc2UKCiAgICAuREVTQ1JJUFRJT04KICAgIENyZWF0ZXMgZW1wdHkgU1FMIGRhdGFiYXNlIHdpdGggZGVmYXVsdCBzZXR0aW5ncy4gRmFpbHMgaW4gY2FzZSBpcyB0aGUgZGF0YWJhc2UgYWxyZWFkeSBleGlzdHMuCgogICAgLlBBUkFNRVRFUiBEYXRhQmFzZU5hbWUKICAgIERhdGFiYXNlIG5hbWUuCgogICAgLlBBUkFNRVRFUiBtZGZGaWxlCiAgICBOYW1lIG9mIHRoZSBNREYgKGRhdGEpIGZpbGUuIElmIG5vdCBzcGVjaWZpZWQsIHRoZSBmb2xsb3dpbmcgdmFsdWUgaXMgdXNlZDoKICAgICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVx7RGF0YUJhc2VQYXRoTmFtZX0ubWRmIgogICAgV2hlcmUge0RhdGFCYXNlUGF0aE5hbWV9IGlzIGRhdGFiYXNlIG5hbWUgd2l0aCBhbGwgYnV0IEEtWiwgYS16LCAwLTkgY2hhcmFjdGVycwogICAgcmVwbGFjZWQgYnkgdW5kZXJzY29yZS4KCiAgICAuUEFSQU1FVEVSIERhdGFCYXNlTmFtZQogICAgTmFtZSBvZiB0aGUgTERGICh0cmFuc2FjdGlvbiBsb2cpIGZpbGUuIElmIG5vdCBzcGVjaWZpZWQsIHRoZSBmb2xsb3dpbmcgdmFsdWUgaXMgdXNlZDoKICAgICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVx7RGF0YUJhc2VQYXRoTmFtZX1fbG9nLm1kZiIKICAgIFdoZXJlIHtEYXRhQmFzZVBhdGhOYW1lfSBpcyBkYXRhYmFzZSBuYW1lIHdpdGggYWxsIGJ1dCBBLVosIGEteiwgMC05IGNoYXJhY3RlcnMKICAgIHJlcGxhY2VkIGJ5IHVuZGVyc2NvcmUuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZSwKICAgICAgICBbU3RyaW5nXSRtZGZGaWxlPSRudWxsLAogICAgICAgIFtTdHJpbmddJGxkZkZpbGU9JG51bGwKICAgICkKCiAgICAkRGF0YUJhc2VQYXRoTmFtZSA9ICREYXRhQmFzZU5hbWUgLXJlcGxhY2UgJ1teMC05YS16QS1aXScsICdfJwogICAgaWYgKC1ub3QgJG1kZkZpbGUpIHsKICAgICAgICAkbWRmRmlsZSA9ICJDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdCBTUUwgU2VydmVyXE1TU1FMMTEuTVNTUUxTRVJWRVJcTVNTUUxcREFUQVwke0RhdGFCYXNlUGF0aE5hbWV9Lm1kZiIKICAgIH0KICAgIGlmICgtbm90ICRsZGZGaWxlKSB7CiAgICAgICAgJGxkZkZpbGUgPSAiQzpcUHJvZ3JhbSBGaWxlc1xNaWNyb3NvZnQgU1FMIFNlcnZlclxNU1NRTDExLk1TU1FMU0VSVkVSXE1TU1FMXERBVEFcJHtEYXRhQmFzZVBhdGhOYW1lfV9sb2cubGRmIgogICAgfQoKICAgICROZXdEYXRhYmFzZSA9ICIKICAgICAgICBDUkVBVEUgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKQogICAgICAgICAgICAgICAgQ09OVEFJTk1FTlQgPSBOT05FCiAgICAgICAgICAgICAgICBPTiAgUFJJTUFSWSAKICAgICAgICAgICAgKCBOQU1FID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAkRGF0YUJhc2VOYW1lKSwgRklMRU5BTUUgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICRtZGZGaWxlKSAsIFNJWkUgPSA0MDk2S0IgLCBGSUxFR1JPV1RIID0gMTAyNEtCICkKICAgICAgICAgICAgICAgIExPRyBPTiAKICAgICAgICAgICAgKCBOQU1FID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJHtEYXRhQmFzZU5hbWV9X2xvZyIpLCBGSUxFTkFNRSA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgJGxkZkZpbGUpICwgU0laRSA9IDEwMjRLQiAsIEZJTEVHUk9XVEggPSAxMCUpCiAgICAgICAgR08KICAgICAgICBVU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKQogICAgICAgIEdPCiAgICAgICAgSUYgTk9UIEVYSVNUUyAoU0VMRUNUIG5hbWUgRlJPTSBzeXMuZmlsZWdyb3VwcyBXSEVSRSBpc19kZWZhdWx0PTEgQU5EIG5hbWUgPSBOJ1BSSU1BUlknKSBBTFRFUiBEQVRBQkFTRSAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIE1PRElGWSBGSUxFR1JPVVAgW1BSSU1BUlldIERFRkFVTFQKICAgICAgICBHTyIKCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkTmV3RGF0YWJhc2UpCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nUHJpbmNpcGFsU3RlcDEgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgcHJpbmNpcGFsIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMSkKCiAgICAuREVTQ1JJUFRJT04KICAgIEluaXRpYWxpemVzIG1pcnJvcmluZyBlbmRwb2ludCAodGhpcyBpcyBhYnNvbHV0ZWx5IHN5bW1ldHJpYyBzdGVwIHRvIHRoZSBtaXJyb3IgaW5pdCkuIEluIGFkZGl0aW9uIHRvIHRoYXQgaXQgY3JlYXRlcwogICAgYSBkYXRhYmFzZSBhbmQgc3RvcmVzIGJhY2t1cHMgb2YgaXQgYW5kIGl0cyB0cmFuc2FjdGlvbiBsb2cgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIHRoZSBlbmRwb2ludCBjZXJ0aWZpY2F0ZS4KCiAgICBBIGZpcmV3YWxsIHJ1bGUgaXMgY3JlYXRlZCBmb3IgZW5kcG9pbnQgaWYgbmVjZXNzYXJ5LgoKICAgIC5QQVJBTUVURVIgV29ya0RpcgogICAgV29ya2luZCBkaXJlY3RvcnkuIFRoaXMgZGlyZWN0b3J5IHNob3VsZCBiZSB0cmFuZmVycmVkIHRvIHRoZSBtaXJyb3Igc2VydmVyIGFmdGVyIHRoaXMKICAgIHN0ZXAgaXMgZXhlY3V0ZWQuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWUKICAgIE1pcnJvcmVkIGRhdGFiYXNlIG5hbWUuIFRoaXMgbmFtZSBNVVNUIGJlIHVzZSBhdCBtaXJyb3Igc2VydmVyIGVpdGhlci4KICAgIAogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZQogICAgKQoKICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCA9ICIkKE5ldy1QYXNzd29yZCAxMClhQSMzIgoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgW3ZvaWRdKE5ldy1JdGVtIC1UeXBlIERpcmVjdG9yeSAkV29ya0RpcikKICAgIH0KICAgICRXb3JrRGlyID0gKEdldC1JdGVtICRXb3JrRGlyKS5GdWxsTmFtZQogICAgaWYgKChHZXQtQ2hpbGRJdGVtIC1QYXRoICRXb3JrRGlyKS5MZW5ndGggLWd0IDApIHsKICAgICAgICB0aHJvdyAiV29ya2luZyBkaXJlY3RvcnkgJFdvcmtEaXIgaXMgbm90IGVtcHR5IgogICAgfQoKICAgICRFbmRwb2ludFBvcnQgPSBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50ICRFbmNyeXB0aW9uUGFzc3dvcmQgIiRXb3JrRGlyXGNlcnRpZmljYXRlLmNlciIKICAgICRFbmRwb2ludFBvcnQgfCBTZXQtQ29udGVudCAiJFdvcmtEaXJcZW5kcG9pbnQtcG9ydC50eHQiCiAgICBOZXctU1FMRGF0YWJhc2UgJERhdGFCYXNlTmFtZQoKICAgICRCYWNrdXBEYiA9ICJCQUNLVVAgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcU291cmNlLmJhayIpIFdJVEggTk9GT1JNQVQsIElOSVQsIE5BTUUgPSBOJ0Z1bGwgRGF0YWJhc2UgQmFja3VwJywgU0tJUCwgTk9SRVdJTkQsIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwRGIpCiAgICAkQmFja3VwTG9nID0gIkJBQ0tVUCBMT0cgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcU291cmNlX2xvZy5iYWsiKSBXSVRIIE5PRk9STUFULCBJTklULCAgTkFNRSA9IE4nVHJhbnNhY3Rpb24gTG9nICBCYWNrdXAnLCBTS0lQLCBOT1JFV0lORCwgTk9VTkxPQUQsIFNUQVRTID0gMTAKICAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwTG9nKQp9CgpmdW5jdGlvbiBJbml0aWFsaXplLVNRTE1pcnJvcmluZ1ByaW5jaXBhbFN0ZXAyIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIFByZXBhcmVzIHByaW5jaXBhbCBTUUwgU2VydmVyIGZvciBkYXRhYmFzZSBtaXJyb3JpbmcgKFN0YWdlIDIpCgogICAgLkRFU0NSSVBUSU9OCiAgICBJbXBvcnRzIHJlbW90ZSBzZXJ2ZXIgY2VydGlmaWNhdGUgYW5kIGdyYW50cyBpdCB3aXRoIGFjY2VzcyB0byB0aGUgbWlycm9yaW5nIGVuZHBvaW50LgoKICAgIC5QQVJBTUVURVIgUmVtb3RlSG9zdE5hbWUKICAgIFJlbW90ZSAobWlycm9yKSBob3N0IG5hbWUuIEZRRE4gaXMgcHJlZmVycmVkLCBidXQgTmV0QklPUyBuYW1lcyBhbmQgSVAgYWRkcmVzc2VzIGFyZSBhbHNvIGFjY2VwdGVkLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlV29ya0RpcgogICAgUGF0aCB0byBhIGNvcHkgb2Ygd29ya2RpciBvYnRhaW5lZCBmcm9tIG1pcnJvciBtYWNoaW5lIGNyZWF0ZWQgb24gU3RhZ2UgMS4KICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpcgogICAgKQoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFJlbW90ZVdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIlJlbW90ZSB3b3JrIGRpciAnJFJlbW90ZVdvcmtEaXInIHdhcyBub3QgZm91bmQiCiAgICB9CiAgICAkUmVtb3RlV29ya0RpciA9IChHZXQtSXRlbSAkUmVtb3RlV29ya0RpcikuRnVsbE5hbWUKCiAgICBDb21wbGV0ZS1NaXJyb3JpbmdFbmRwb2ludCAkUmVtb3RlSG9zdE5hbWUgJFJlbW90ZVdvcmtEaXIKfQoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1TUUxNaXJyb3JpbmdQcmluY2lwYWxTdGVwMyB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBQcmVwYXJlcyBwcmluY2lwYWwgU1FMIFNlcnZlciBmb3IgZGF0YWJhc2UgbWlycm9yaW5nIChTdGFnZSAzKQoKICAgIC5ERVNDUklQVElPTgogICAgQ29tcGxldGVzIG1pcnJvciBjcmVhdGlvbi4gVGhpcyBzdGVwIG11c3QgYmUgZ2xvYmFsbHkgdGhlIGxhc3Qgb25lIGluIG1pcnJvciBjcmVhdGlvbiBzZXF1ZW5jZS4KCiAgICBOb3RlIHRoYXQgdGhlIHJlbW90ZSBob3N0IGNlcnRpZmljYXRlIGlzIHZhbGlkIGZyb20gdGhlIHRpbWUgaXQgaXMgY3JlYXRlZCB0aGVyZS4gU28KICAgIHRoaXMgc3RlcCB3aWxsIGZhaWwgaWYgdGhlcmUgaXMgbm90aWNhYmxlIGRpZmZlcmVudCBpbiB0aW1lIGxvY2FsIGFuZCByZW1vdGUgbWFjaGluZXMuCgogICAgLlBBUkFNRVRFUiBSZW1vdGVIb3N0TmFtZQogICAgUmVtb3RlIChwcmluY2lwYWwpIGhvc3QgbmFtZS4gRlFETiBpcyBwcmVmZXJyZWQsIGJ1dCBOZXRCSU9TIG5hbWVzIGFuZCBJUCBhZGRyZXNzZXMgYXJlIGFsc28gYWNjZXB0ZWQuCgogICAgLlBBUkFNRVRFUiBSZW1vdGVXb3JrRGlyCiAgICBQYXRoIHRvIGEgY29weSBvZiB3b3JrZGlyIG9idGFpbmVkIGZyb20gcHJpbmNpcGFsIG1hY2hpbmUgY3JlYXRlZCBvbiBTdGFnZSAxLgoKICAgIC5QQVJBTUVURVIgRGF0YWJhc2VOYW1lCiAgICBNaXJyb3JlZCBkYXRhYmFzZSBuYW1lLiBUaGlzIG5hbWUgTVVTVCBtYXRjaCBwcmluY2lwYWwgZGF0YWJhc2UgbmFtZSBhbmQgbmFtZSBwcm92aWRlZCBvbiBzdGVwIDEuCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZUhvc3ROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFJlbW90ZVdvcmtEaXIsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kRGF0YWJhc2VOYW1lCiAgICApCgogICAgW2ludF0kcG9ydCA9IEdldC1Db250ZW50ICIke1JlbW90ZVdvcmtEaXJ9XGVuZHBvaW50LXBvcnQudHh0IgogICAgQ29tcGxldGUtU1FMTWlycm9yICRSZW1vdGVIb3N0TmFtZSAkcG9ydCAkRGF0YWJhc2VOYW1lCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDEgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UxKQoKICAgIC5ERVNDUklQVElPTgogICAgSW5pdGlhbGl6ZXMgbWlycm9yaW5nIGVuZHBvaW50IGZvciBtaXJyb3Igc2VydmVyLiBTdG9yZXMgbWlycm9yaW5nIGVuZHBvaW50IGNlcnRpZmljYXRlIGluIFdvcmtkaXIuCgogICAgLlBBUkFNRVRFUiBXb3JrRGlyCiAgICBXb3JraW5kIGRpcmVjdG9yeS4gVGhpcyBkaXJlY3Rvcnkgc2hvdWxkIGJlIHRyYW5mZXJyZWQgdG8gdGhlIHByaW5jaXBhbCBzZXJ2ZXIgYWZ0ZXIgdGhpcwogICAgc3RlcCBpcyBleGVjdXRlZC4KCiAgICAuUEFSQU1FVEVSIERhdGFiYXNlTmFtZQogICAgTWlycm9yZWQgZGF0YWJhc2UgbmFtZS4gVGhpcyBuYW1lIE1VU1QgbWF0Y2ggcHJpbmNpcGFsIGRhdGFiYXNlIG5hbWUuCgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFiYXNlTmFtZQogICAgKQoKICAgIFtTdHJpbmddJEVuY3J5cHRpb25QYXNzd29yZCA9ICIkKE5ldy1QYXNzd29yZCAxMClhQSMzIgoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgW3ZvaWRdKE5ldy1JdGVtIC1UeXBlIERpcmVjdG9yeSAkV29ya0RpcikKICAgIH0KICAgICRXb3JrRGlyID0gKEdldC1JdGVtICRXb3JrRGlyKS5GdWxsTmFtZQoKICAgICRFbmRwb2ludFBvcnQgPSBJbml0aWFsaXplLU1pcnJvcmluZ0VuZHBvaW50ICRFbmNyeXB0aW9uUGFzc3dvcmQgIiRXb3JrRGlyXGNlcnRpZmljYXRlLmNlciIKICAgICRFbmRwb2ludFBvcnQgfCBTZXQtQ29udGVudCAiJFdvcmtEaXJcZW5kcG9pbnQtcG9ydC50eHQiCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDIgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMikKCiAgICAuREVTQ1JJUFRJT04KICAgIEltcG9ydHMgcmVtb3RlIHNlcnZlciBjZXJ0aWZpY2F0ZSBhbmQgZ3JhbnRzIGl0IHdpdGggYWNjZXNzIHRvIHRoZSBtaXJyb3JpbmcgZW5kcG9pbnQuCiAgICBSZXN0b3JlcyBkYXRhYmFzZSBvYnRhaW5lZCBmcm9tIHByaW5jaXBhbCBhbmQgbGVhdmVzIGl0IGluICdSZXN0b3JpbmcnIHN0YXRlLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlSG9zdE5hbWUKICAgIFJlbW90ZSAocHJpbmNpcGFsKSBob3N0IG5hbWUuIEZRRE4gaXMgcHJlZmVycmVkLCBidXQgTmV0QklPUyBuYW1lcyBhbmQgSVAgYWRkcmVzc2VzIGFyZSBhbHNvIGFjY2VwdGVkLgoKICAgIC5QQVJBTUVURVIgUmVtb3RlV29ya0RpcgogICAgUGF0aCB0byBhIGNvcHkgb2Ygd29ya2RpciBvYnRhaW5lZCBmcm9tIHByaW5jaXBhbCBtYWNoaW5lIGNyZWF0ZWQgb24gU3RhZ2UgMS4KCiAgICAuUEFSQU1FVEVSIERhdGFiYXNlTmFtZQogICAgTWlycm9yZWQgZGF0YWJhc2UgbmFtZS4gVGhpcyBuYW1lIE1VU1QgbWF0Y2ggcHJpbmNpcGFsIGRhdGFiYXNlIG5hbWUuCgogICAgIz4KCiAgICBwYXJhbSgKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVIb3N0TmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSRSZW1vdGVXb3JrRGlyLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJERhdGFCYXNlTmFtZQogICAgKQoKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFJlbW90ZVdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIlJlbW90ZSB3b3JrIGRpciAnJFJlbW90ZVdvcmtEaXInIHdhcyBub3QgZm91bmQiCiAgICB9CiAgICAkUmVtb3RlV29ya0RpciA9IChHZXQtSXRlbSAkUmVtb3RlV29ya0RpcikuRnVsbE5hbWUKCiAgICBDb21wbGV0ZS1NaXJyb3JpbmdFbmRwb2ludCAkUmVtb3RlSG9zdE5hbWUgJFJlbW90ZVdvcmtEaXIKCiAgICAkUmVzdG9yZURiID0gIlJFU1RPUkUgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBGUk9NIERJU0sgPSBOJChDb252ZXJ0VG8tU1FMU3RyaW5nICIkUmVtb3RlV29ya0RpclxTb3VyY2UuYmFrIikgV0lUSCBGSUxFID0gMSwgTk9SRUNPVkVSWSwgTk9VTkxPQUQsIFJFUExBQ0UsIFNUQVRTID0gNQogICAgICAgICAgICAgICAgICBHTyIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRSZXN0b3JlRGIpCiAgICAkUmVzdG9yZUxvZyA9ICJSRVNUT1JFIExPRyAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIEZST00gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRSZW1vdGVXb3JrRGlyXFNvdXJjZV9sb2cuYmFrIikgV0lUSCBGSUxFID0gMSwgTk9SRUNPVkVSWSwgTk9VTkxPQUQsIFNUQVRTID0gMTAKICAgICAgICAgICAgICAgICAgIEdPIgogICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVMb2cpCn0KCmZ1bmN0aW9uIEluaXRpYWxpemUtU1FMTWlycm9yaW5nTWlycm9yU3RlcDMgewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgUHJlcGFyZXMgbWlycm9yIFNRTCBTZXJ2ZXIgZm9yIGRhdGFiYXNlIG1pcnJvcmluZyAoU3RhZ2UgMykKCiAgICAuREVTQ1JJUFRJT04KICAgIENvbXBsZXRlcyBtaXJyb3IgY3JlYXRpb24uIFRoaXMgc3RlcCBtdXN0IGJlIGV4ZWN1dGVkIHN0cmljdGx5IGJlZm9yZSBzeW1tZXRyaWMgc3RlcCBvbiB0aGUgcHJpbmNpcGFsLgoKICAgIE5vdGUgdGhhdCB0aGUgcmVtb3RlIGhvc3QgY2VydGlmaWNhdGUgaXMgdmFsaWQgZnJvbSB0aGUgdGltZSBpdCBpcyBjcmVhdGVkIHRoZXJlLiBTbwogICAgdGhpcyBzdGVwIHdpbGwgZmFpbCBpZiB0aGVyZSBpcyBub3RpY2FibGUgZGlmZmVyZW50IGluIHRpbWUgbG9jYWwgYW5kIHJlbW90ZSBtYWNoaW5lcy4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZUhvc3ROYW1lCiAgICBSZW1vdGUgKHByaW5jaXBhbCkgaG9zdCBuYW1lLiBGUUROIGlzIHByZWZlcnJlZCwgYnV0IE5ldEJJT1MgbmFtZXMgYW5kIElQIGFkZHJlc3NlcyBhcmUgYWxzbyBhY2NlcHRlZC4KCiAgICAuUEFSQU1FVEVSIFJlbW90ZVdvcmtEaXIKICAgIFBhdGggdG8gYSBjb3B5IG9mIHdvcmtkaXIgb2J0YWluZWQgZnJvbSBwcmluY2lwYWwgbWFjaGluZSBjcmVhdGVkIG9uIFN0YWdlIDEuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWUKICAgIE1pcnJvcmVkIGRhdGFiYXNlIG5hbWUuIFRoaXMgbmFtZSBNVVNUIG1hdGNoIHByaW5jaXBhbCBkYXRhYmFzZSBuYW1lLgoKICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlSG9zdE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kUmVtb3RlV29ya0RpciwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSREYXRhYmFzZU5hbWUKICAgICkKCiAgICBbaW50XSRwb3J0ID0gR2V0LUNvbnRlbnQgIiR7UmVtb3RlV29ya0Rpcn1cZW5kcG9pbnQtcG9ydC50eHQiCiAgICBDb21wbGV0ZS1TUUxNaXJyb3IgJFJlbW90ZUhvc3ROYW1lICRwb3J0ICREYXRhYmFzZU5hbWUKfQoKZnVuY3Rpb24gR2V0LU5leHRGcmVlUG9ydCB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBSZXR1cm5zIHNwZWNpZmllZCBkZXNpcmVkIHBvcnQgb3IgY2xvc2VzdCBuZXh0IG9uZSB1bm9jY3VwaWVkLgoKICAgIC5QQVJBTUVURVIgUG9ydAogICAgRGVzaXJlZCBwb3J0IG51bWJlci4KCiAgICAjPgoKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtpbnRdJFBvcnQKICAgICkKICAgICRPcGVuUG9ydHMgPSBuZXRzdGF0IC1hb24gfCBzZWxlY3Qtc3RyaW5nICdMSVNURU5JTkcnIHwgRm9yZWFjaC1PYmplY3QgeyAoKCRfIC1yZXBsYWNlICdeXHMqJywgJycgLXNwbGl0ICdccysnKVsxXSAtc3BsaXQgJy4qOicpWzFdIH0gfCBTb3J0LU9iamVjdCB8IEdldC1VbmlxdWUKICAgIHdoaWxlICgkT3BlblBvcnRzLkNvbnRhaW5zKCR7UG9ydH0pKSB7CiAgICAgICAgJFBvcnQgPSAkUG9ydCArIDEKICAgIH0KICAgIHJldHVybiAkUG9ydAp9CgpmdW5jdGlvbiBJbml0aWFsaXplLUFsd2F5c09uIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIEluaXRpYWxpemVzIEFsd2F5c09uIGNsdXN0ZXJpbmcgb24gbG9jYWwgU1FMIHNlcnZlciBhbmQgY3JlYXRlcyBBbHdheXNPbiBlbmRwb2ludCBsaXN0ZW5lci4gUmV0dXJucyBBbHdheXNPbiBlbmRwb2ludCBwb3J0IG51bWJlci4KCiAgICAuREVTQ1JJUFRJT04KICAgIEVuYWJsZXMgQWx3YXlzT24gY2x1c3RlcmluZyBvbiBsb2NhbCBTUUwgc2VydmVyLiBDcmVhdGVzIEFsd2F5c09uIFRDUCBlbmRwb2ludCBvbiBwb3J0IDUwMjIgb3IgZ3JlYXRlciBpZiB0aGUgb25lIGlzIG9jY3VwaWVkLiAgIAogICAgIz4KCiAgICBpZiAoIShUZXN0LVBhdGggU1FMU0VSVkVSOlwpKSB7CiAgICAgICAgSW1wb3J0LU1vZHVsZSBzcWxwcwogICAgfQogICAgJE1hY2hpbmVOYW1lID0gKEdldC1DaGlsZEl0ZW0gU1FMU0VSVkVSOlxTUUwpWzBdLlBTQ2hpbGROYW1lCiAgICAkSW5zdGFuY2VOYW1lID0gKEdldC1DaGlsZEl0ZW0gU1FMU0VSVkVSOlxTUUxcJE1hY2hpbmVOYW1lKS5QU0NoaWxkTmFtZQogICAgJEFsd2F5c09uRW5hYmxlZCA9ICgoR2V0LUl0ZW0gU1FMU0VSVkVSOlxTUUxcJE1hY2hpbmVOYW1lXCRJbnN0YW5jZU5hbWUpIHwgc2VsZWN0IElzSGFkckVuYWJsZWQpLklzSGFkckVuYWJsZWQKICAgIGlmICgtbm90ICRBbHdheXNPbkVuYWJsZWQpIHsKICAgICAgICBFbmFibGUtU3FsQWx3YXlzT24gLVBhdGggIlNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lIiAtRm9yY2UKICAgIH0KICAgICRJbnN0YW5jZSA9IEdldC1JdGVtIFNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lCiAgICAkZW5kcG9pbnQgPSAkSW5zdGFuY2UuRW5kcG9pbnRzWyJBbHdheXNPbkVuZHBvaW50Il0KICAgIGlmICgtbm90ICRlbmRwb2ludCkgewogICAgICAgICRQb3J0ID0gR2V0LU5leHRGcmVlUG9ydCA1MDIyCiAgICAgICAgJGVuZHBvaW50ID0gTmV3LVNxbEhhZHJFbmRwb2ludCBBbHdheXNPbkVuZHBvaW50IC1Qb3J0ICRQb3J0IC1QYXRoIFNRTFNFUlZFUjpcU1FMXCRNYWNoaW5lTmFtZVwkSW5zdGFuY2VOYW1lCiAgICB9IGVsc2UgewogICAgICAgICRQb3J0ID0gJGVuZHBvaW50LlByb3RvY29sLlRjcC5MaXN0ZW5lclBvcnQKICAgIH0gCiAgICBpZiAoJGVuZHBvaW50LkVuZHBvaW50U3RhdGUgLW5lICJTdGFydGVkIikgewogICAgICAgICRlbmRwb2ludC5TdGFydCgpCiAgICB9ICAgIAogICAgcmV0dXJuICRQb3J0Cn0KCmZ1bmN0aW9uIE5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgbmV3IEFsd2F5c09uIGF2YWlsYWJpbGl0eSBncm91cCBvbiBwcmltYXJ5IHJlcGxpY2EuCgogICAgLkRFU0NSSVBUSU9OCiAgICBDcmVhdGVzIG5ldyBBbHdheXNPbiBhdmFpbGFiaWxpdHkgZ3JvdXAgb24gcHJpbWFyeSByZXBsaWNhLgoKICAgIC5QQVJBTUVURVIgV29ya0RpcgogICAgV29ya2luZCBkaXJlY3RvcnkuIFRoaXMgZGlyZWN0b3J5IHNob3VsZCBiZSB0cmFuZmVycmVkIHRvIHRoZSByZXBsaWNhIHNlcnZlcihzKSBhZnRlciB0aGlzCiAgICBzdGVwIGlzIGV4ZWN1dGVkLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgQXZhaWxhYmlsaXR5IGdyb3VwIG5hbWUuCgogICAgLlBBUkFNRVRFUiBEYXRhYmFzZU5hbWVzCiAgICBSZXBsaWNhIGRhdGFiYXNlKHMpIG5hbWVzLgoKICAgIC5QQVJBTUVURVIgUmVwbGljYURlZnMKICAgIEFycmF5IG9mIHJlcGxpY2EgZGVmaW5pdGlvbi4gRWFjaCBkZWZpbml0aW9uIGlzIGEgaGFzaCB0YWJsZSB3aXRoIHJlcGxpY2Etc3BlY2lmaWMgdmFsdWVzLgogICAgCiAgICBNYW5kYXRvcnkgcmVwbGljYSBkZWZpbml0aW9uIHZhbHVlcyBhcmU6CgogICAgICAgICogW1N0cmluZ10gU0VSVkVSX0lOU1RBTkNFICAgLSBSZXBsaWNhIHNlcnZlciBpbnN0YW5jZSBuYW1lCiAgICAgICAgKiBbU3RyaW5nXSBFTkRQT0lOVF9VUkwgICAgICAtIFJlcGxpY2Egc2VydmVyIGVuZHBvaW50IFVSTC4gTm9ybWFsbHkgaXQgaXMgVENQOi8vZnVsbHkucXVhbGlmaWVkLmRvbWFpbi5uYW1lOjUwMjIgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBvcnQgbnVtYmVyIHNob3VsZCBiZSBvYnRhaW5lZCB3aXRoIEluaXRpYWxpemUtQWx3YXlzT24gYXQgdGhlIHJlcGxpY2Egc2VydmVyCiAgICAgICAgKiBbU3RyaW5nXSBBVkFJTEFCSUxJVFlfTU9ERSAtIFJlcGxpY2EgYXZhaWxhYmlsaXR5IG1vZGUuIENhbiBiZSAiU1lOQ0hST05PVVNfQ09NTUlUIiBvciAiQVNZTkNIUk9OT1VTX0NPTU1JVCIgb25seS4KICAgICAgICAqIFtTdHJpbmddIEZBSUxPVkVSX01PREUgICAgIC0gUmVwbGljYSBhdmFpbGFiaWxpdHkgbW9kZS4gQ2FuIGJlICJNQU5VQUwiIG9yICJBVVRPTUFUSUMiIG9ubHkuCgogICAgT3B0aW9uYWwgcmVwbGljYSBkZWZpbml0aW9uIHZhbHVlcyBhcmU6CgogICAgICAgICogW0ludGVnZXJdIEJBQ0tVUF9QUklPUklUWSAgICAgICAgICAtIEJhY2t1cCBwcmlvcml0eQogICAgICAgICogW0ludGVnZXJdIFNFU1NJT05fVElNRU9VVCAgICAgICAgICAtIFNlc3Npb24gdGltZW91dAogICAgICAgICogW1N0cmluZ10gIFBfQUxMT1dfQ09OTkVDVElPTlMgICAgICAtIEFsbG93ZWQgY29ubmVjdGlvbiB0eXBlcyBmb3IgIlByaW1hcnkiIHJlcGxpY2EgbW9kZS4gQ2FuIGJlICJSRUFEX1dSSVRFIiBvciAiQUxMIiBvbmx5LgogICAgICAgICogW0FycmF5XSAgIFBfUkVBRF9PTkxZX1JPVVRJTkdfTElTVCAtIExpc3Qgb2YgcmVwbGljYXMgcHJvdmlyaW5nIHJlYWRvbmx5IGFjY2VzcyB3aGVuIHRoaXMgb25lIGlzIHByaW1hcnkuCiAgICAgICAgKiBbU3RyaW5nXSAgU19BTExPV19DT05ORUNUSU9OUyAgICAgIC0gQWxsb3dlZCBjb25uZWN0aW9uIHR5cGVzIGZvciAiU2Vjb25kYXJ5IiByZXBsaWNhIG1vZGUuIENhbiBiZSBvbmUgb2YgIk5PIiwgIlJFQURfT05MWSIsICJBTEwiLgogICAgICAgICogW1N0cmluZ10gIFNfUkVBRF9PTkxZX1JPVVRJTkdfVVJMICAtIFJlcGxpY2EgcmVhZC1vbmx5IHJlcXVlc3RzIGxpc3RlbmVyIFVSTC4gTm9ybWFsbHkgZGVmYXVsdCBzZXJ2ZXIgbGlzdGVuZXIgYXQgcG9ydCAxNDMzIGlzIHVzZWQuCgogICAgLlBBUkFNRVRFUiBQcmVmZXJlbmNlcwogICAgSGFzaCB0YWJsZSBvZiBnZW5lcmFsIGF2YWlsYWJpbGl0eSBncm91cCBwcmVmZXJlbmNlcy4gQWxsIHRoZSBrZXlzIGFyZSBvcHRpb25hbC4gU3VwcG9ydGVkIGVudHJ5IGtleXMgYXJlOgoKICAgICAgICAqIFtTdHJpbmddICBBVVRPTUFURURfQkFDS1VQX1BSRUZFUkVOQ0UgLSBBdXRvbWF0ZWQgYmFja3VwIHByZWZlcmVuY2UuIENhbiBiZSAiUFJJTUFSWSIsICJTRUNPTkRBUllfT05MWSIsICJTRUNPTkRBUlkiIG9yICJOT05FIi4KICAgICAgICAqIFtTdHJpbmddICBGQUlMVVJFX0NPTkRJVElPTl9MRVZFTCAgICAgLSBGYWlsdXJlIGNvbmRpdGlvbiBsZXZlbC4gQ2FuIGJlICIxIiwgIjIiLCAiMyIsICI0IiBvciAiNSIuCiAgICAgICAgKiBbSW50ZWdlcl0gSEVBTFRIX0NIRUNLX1RJTUVPVVQgICAgICAgIC0gUmVwbGljYSBoZWFsdGggY2hlY2sgdGltZW91dC4KCiAgICAuUEFSQU1FVEVSIExpc3RlbmVyRGVmCiAgICBIYXNoIHRhYmxlIGNvbnRhaW5pbmcgYXZhaWxhYmlsaXR5IGdyb3VwIGxpc3RlbmVyIGNvbmZpZ3VyYXRpb24uCgogICAgTWFuZGF0b3J5IGxpc3RlbmVyIGNvbmZpZ3VyYXRpb24gdmFsdWVzIGFyZToKCiAgICAgICAgW1N0cmluZ10gTkFNRSAtIExpc3RlbmVyIG5hbWUuCgogICAgT3B0aW9uYWwgbGlzdGVuZXIgY29uZmlndXJhdGlvbiB2YWx1ZXMgYXJlOgogICAgCiAgICAgICAgW1N0cmluZ10gUE9SVCAtIExpc3RlbmVyIHBvcnQgbnVtYmVyLiBJbnRlZ2VyIHZhbHVlIG1heSBiZSBzdWZmaXhlZCBieSBhICIrIiBzeW1vbCAoc3VjaCBhcyAiNTAyMisiKSB3aGljaCBhbGxvd3MgdGhlIHJvdXRpbmUgdG8KICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0IG5leHQgZnJlZSBwb3J0IHdpdGggbnVtYmVyIGdyZWF0ZXIgb3IgZXF1YWwgdG8gdGhlIHNwZWNpZmllZCB2YWx1ZS4KICAgICAgICBbU3RyaW5nXSBESENQIC0gREhDUCBsaXN0ZW5lciBhZGRyZXNzIGNvbmZpZ3VyYXRpb24gZmxhZy4gV2hlbiBhbnkgdmFsdWUgc3BlY2lmaWVkLCBESENQIGlzIHVzZWQgdG8gY29uZmlndXJlIGxpc3RlbmVyCiAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzIGlzIGFsc28gdGhlIGRlZmF1bHQgYmVoYXZpb3IpLiBBbHNvLCBhIHNwZWNpZmljIGludGVyZmFjZSBmb3IgREhDUCBtYXkgYmUgc3BlY2lmaWVkIGFzIElQX0FERFJFU1MvTUFTSwogICAgICAgICAgICAgICAgICAgICAgICAobGlrZSAiMTkyLjE2OC4xLjAvMjU1LjI1NS4yNTUuMCIpIGFzIGEgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci4KICAgICAgICBbQXJyYXldIFNUQVRJQyAtIFN0YXRpYyBJUCBhZGRyZXNzZXMgdG8gbGlzdGVuLiBJUCBhZGRyZXNzZXMgbWF5IGJlIElQdjQgYWRkcmVzc2VzIGluIHRoZSAiSVBfQUREUkVTUy9NQVNLIiBmb3JtIG9yIElQdjYKICAgICAgICAgICAgICAgICAgICAgICAgYWRkcmVzc2VzIGluIHN0YW5kYXJkIElQdjYgbm90YXRpb24uCgogICAgU2VlIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9mZjg3ODM5OS5hc3B4IHBhZ2UgZm9yIG1vcmUgZGV0YWlscyByZWdhcmRpbmcgYWxsIHRoZSBzdXBwb3J0ZWQgb3B0aW9ucy4KICAgICM+CgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kV29ya0RpciwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbU3RyaW5nXSROYW1lLAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtBcnJheV0kRGF0YWJhc2VOYW1lcywKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0KICAgICAgICBbQXJyYXldJFJlcGxpY2FEZWZzLAogICAgICAgIFtwYXJhbWV0ZXJdCiAgICAgICAgW0hhc2h0YWJsZV0kUHJlZmVyZW5jZXMsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW0hhc2h0YWJsZV0kTGlzdGVuZXJEZWYKICAgICkKCiAgICBpZiAoLW5vdCAoVGVzdC1QYXRoICRXb3JrRGlyKSkgewogICAgICAgIFt2b2lkXShOZXctSXRlbSAtVHlwZSBEaXJlY3RvcnkgJFdvcmtEaXIpCiAgICB9CiAgICAkV29ya0RpciA9IChHZXQtSXRlbSAkV29ya0RpcikuRnVsbE5hbWUKICAgIGlmICgoR2V0LUNoaWxkSXRlbSAtUGF0aCAkV29ya0RpcikuTGVuZ3RoIC1ndCAwKSB7CiAgICAgICAgdGhyb3cgIldvcmtpbmcgZGlyZWN0b3J5ICRXb3JrRGlyIGlzIG5vdCBlbXB0eSIKICAgIH0KCiAgICAkUXVvdGVkREJOYW1lcyA9ICgkRGF0YWJhc2VOYW1lcyB8IEZvckVhY2gtT2JqZWN0IHsgQ29udmVydFRvLVNRTE5hbWUgJF8gfSkgLWpvaW4gIiwgIgoKICAgIGlmICgkUHJlZmVyZW5jZXMgLWVxICRudWxsKSB7CiAgICAgICAgJFByZWZlcmVuY2VzID0gQCgpCiAgICB9CiAgICAkUHJlZnMgPSBAKCkKICAgIGZvcmVhY2goJFByZWYgaW4gJFByZWZlcmVuY2VzKSB7CiAgICAgICAgaWYgKCRQcmVmLktleSAtZXEgJG51bGwpIHsKICAgICAgICAgICAgQ29udGludWUKICAgICAgICB9CiAgICAgICAgaWYgKCRQcmVmLktleSAtZXEgIkFVVE9NQVRFRF9CQUNLVVBfUFJFRkVSRU5DRSIpIHsKICAgICAgICAgICAgJFByZWZzID0gJFByZWZzICsgKFZhbGlkYXRlLU9wdGlvbiAkUHJlZi5LZXksICRQcmVmLlZhbHVlLCBAKCJQUklNQVJZIiwgIlNFQ09OREFSWV9PTkxZIiwgIlNFQ09OREFSWSIsICJOT05FIikgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAkUHJlZi5LZXkpCiAgICAgICAgfSBlbHNlaWYgKCRQcmVmLktleSAtZXEgIkZBSUxVUkVfQ09ORElUSU9OX0xFVkVMIikgewogICAgICAgICAgICAkUHJlZnMgPSAkUHJlZnMgKyAoVmFsaWRhdGUtT3B0aW9uICRQcmVmLktleSwgJFByZWYuVmFsdWUsIEAoIjEiLCAiMiIsICIzIiwgIjQiLCAiNSIpIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgJFByZWYuS2V5KQogICAgICAgIH0gZWxzZWlmICgkUHJlZi5LZXkgLWVxICJIRUFMVEhfQ0hFQ0tfVElNRU9VVCIpIHsKICAgICAgICAgICAgJFByZWZzID0gJFByZWZzICsgKFZhbGlkYXRlLUludE9wdGlvbiAkUHJlZi5LZXksICRQcmVmLlZhbHVlIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgJFByZWYuS2V5KQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRocm93ICJVbmV4cGVjdGVkIHBlZmVyZW5jZXMgb3B0aW9uOiAnJCgkUHJlZi5LZXkpJyIKICAgICAgICB9CiAgICB9CgogICAgJFJlcGxpY2FEZWZpbml0aW9uc0FycmF5ID0gQCgpCiAgICBmb3IgKCRpID0gMDsgJGkgLWx0ICRSZXBsaWNhRGVmcy5MZW5ndGg7ICRpKyspIHsKICAgICAgICAkUkRlZiA9ICRSZXBsaWNhRGVmc1skaV0KICAgICAgICBpZiAoJFJEZWYuR2V0VHlwZSgpLk5hbWUgLW5lICJIYXNodGFibGUiKSB7CiAgICAgICAgICAgIHRocm93ICJBbGwgZWxlbWVudHMgb2YgUmVwbGljYURlZnMgYXJyYXkgc2hvdWxkIGJlIEhhc2h0YWJsZXMiCiAgICAgICAgfQoKICAgICAgICAkUmVwbGljYU9wdHMgPSBAKCkKCiAgICAgICAgIyBNYW5kYXRvcnkgb3B0aW9ucwogICAgICAgICRSZXBsaWNhTmFtZSA9IFZhbGlkYXRlLURlZmluZWRPcHRpb24gIlNFUlZFUl9JTlNUQU5DRSIgJFJEZWZbIlNFUlZFUl9JTlNUQU5DRSJdCiAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLURlZmluZWRPcHRpb24gIkVORFBPSU5UX1VSTCIgJFJEZWZbIkVORFBPSU5UX1VSTCJdIHwgQ29udmVydFRvLVNRTFN0cmluZyB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJFTkRQT0lOVF9VUkwiKQogICAgICAgICRSZXBsaWNhT3B0cyA9ICRSZXBsaWNhT3B0cyArIChWYWxpZGF0ZS1PcHRpb24gIkFWQUlMQUJJTElUWV9NT0RFIiAkUkRlZlsiQVZBSUxBQklMSVRZX01PREUiXSBAKCJTWU5DSFJPTk9VU19DT01NSVQiLCAiQVNZTkNIUk9OT1VTX0NPTU1JVCIpIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIkFWQUlMQUJJTElUWV9NT0RFIikKICAgICAgICAkUmVwbGljYU9wdHMgPSAkUmVwbGljYU9wdHMgKyAoVmFsaWRhdGUtT3B0aW9uICJGQUlMT1ZFUl9NT0RFIiAkUkRlZlsiRkFJTE9WRVJfTU9ERSJdIEAoIkFVVE9NQVRJQyIsICJNQU5VQUwiKSB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJGQUlMT1ZFUl9NT0RFIikKCiAgICAgICAgIyBPcHRpb25hbCBvcHRpb25zCiAgICAgICAgaWYgKCRSRGVmWyJCQUNLVVBfUFJJT1JJVFkiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLUludE9wdGlvbiAiQkFDS1VQX1BSSU9SSVRZIiAkUkRlZlsiQkFDS1VQX1BSSU9SSVRZIl0gfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQkFDS1VQX1BSSU9SSVRZIikKICAgICAgICB9CiAgICAgICAgaWYgKCRSRGVmWyJTRVNTSU9OX1RJTUVPVVQiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFJlcGxpY2FPcHRzID0gJFJlcGxpY2FPcHRzICsgKFZhbGlkYXRlLUludE9wdGlvbiAiU0VTU0lPTl9USU1FT1VUIiAkUkRlZlsiU0VTU0lPTl9USU1FT1VUIl0gfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiU0VTU0lPTl9USU1FT1VUIikKICAgICAgICB9CgogICAgICAgICRTZWNvbmRhcnlSb2xlID0gQCgpCiAgICAgICAgaWYgKCRSRGVmWyJTX0FMTE9XX0NPTk5FQ1RJT05TIl0gLW5lICRudWxsKSB7CiAgICAgICAgICAgICRTZWNvbmRhcnlSb2xlID0gJFNlY29uZGFyeVJvbGUgKyAoVmFsaWRhdGUtT3B0aW9uICJTX0FMTE9XX0NPTk5FQ1RJT05TIiAkUkRlZlsiU19BTExPV19DT05ORUNUSU9OUyJdIEAoIk5PIiwgIlJFQURfT05MWSIsICJBTEwiKSB8IE5ldy1SZXBsaWNhT3B0aW9uIC1OYW1lICJBTExPV19DT05ORUNUSU9OUyIpCiAgICAgICAgfQogICAgICAgIGlmICgkUkRlZlsiU19SRUFEX09OTFlfUk9VVElOR19VUkwiXSAtbmUgJG51bGwpIHsKICAgICAgICAgICAgJFNlY29uZGFyeVJvbGUgPSAkU2Vjb25kYXJ5Um9sZSArICgkUkRlZlsiU19SRUFEX09OTFlfUk9VVElOR19VUkwiXSB8IENvbnZlcnRUby1TUUxTdHJpbmcgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFNlY29uZGFyeVJvbGUuTGVuZ3RoIC1ndCAwKSB7CiAgICAgICAgICAgICRSZXBsaWNhT3B0cyA9ICRSZXBsaWNhT3B0cyArICgiKCAkKCRTZWNvbmRhcnlSb2xlIC1qb2luICcsICcpICkiIHwgTmV3LVJlcGxpY2FPcHRpb24gLU5hbWUgIlNFQ09OREFSWV9ST0xFIikKICAgICAgICB9CgogICAgICAgICRQcmltYXJ5Um9sZSA9IEAoKQogICAgICAgIGlmICgkUkRlZlsiUF9BTExPV19DT05ORUNUSU9OUyJdIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkUHJpbWFyeVJvbGUgPSAkUHJpbWFyeVJvbGUgKyAoVmFsaWRhdGUtT3B0aW9uICJQX0FMTE9XX0NPTk5FQ1RJT05TIiAkUkRlZlsiUF9BTExPV19DT05ORUNUSU9OUyJdIEAoIlJFQURfV1JJVEUiLCAiQUxMIikgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFJEZWZbIlBfUkVBRF9PTkxZX1JPVVRJTkdfTElTVCJdIC1uZSAkbnVsbCkgewogICAgICAgICAgICAkUHJpbWFyeVJvbGUgPSAkUHJpbWFyeVJvbGUgKyAoKCgkUkRlZlsiUF9SRUFEX09OTFlfUk9VVElOR19MSVNUIl0gfCBGb3JFYWNoLU9iamVjdCB7IENvbnZlcnRUby1TUUxTdHJpbmcgJF8gfSkgLWpvaW4gJywgJykgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiQUxMT1dfQ09OTkVDVElPTlMiKQogICAgICAgIH0KICAgICAgICBpZiAoJFByaW1hcnlSb2xlLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICAgICAkUmVwbGljYU9wdHMgPSAkUmVwbGljYU9wdHMgKyAoIiggJCgkUHJpbWFyeVJvbGUgLWpvaW4gJywgJykgKSIgfCBOZXctUmVwbGljYU9wdGlvbiAtTmFtZSAiUFJJTUFSWV9ST0xFIikKICAgICAgICB9CgogICAgICAgICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSA9ICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSArCiAgICAgICAgICAgICMgIFRDUDovL2JyYXZvLm11cmFuby5sb2NhbDo1MDIyCiAgICAgICAgICAgICJOJChDb252ZXJ0VG8tU1FMU3RyaW5nICRSZXBsaWNhTmFtZSkgV0lUSCAoJCgkUmVwbGljYU9wdHMgLWpvaW4gJywgJykpIgogICAgfQogICAgJFJlcGxpY2FEZWZpbml0aW9ucyA9ICRSZXBsaWNhRGVmaW5pdGlvbnNBcnJheSAtam9pbiAiLGByYG4gICAgICAgICI7CgogICAgaWYgKCRMaXN0ZW5lckRlZlsiREhDUCJdIC1uZSAkbnVsbCkgewogICAgICAgIGlmICgkTGlzdGVuZXJEZWZbIkRIQ1AiXS5tYXRjaGVzKCJcZCtcLlxkK1wuXGQrXC5cZCsvXGQrXC5cZCtcLlxkK1wuXGQrIikpIHsKICAgICAgICAgICAgKCRJcEFkZHIsICRNYXNrKSA9ICRMaXN0ZW5lckRlZlsiREhDUCJdIC1zcGxpdCAiLyIKICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICJESENQIE9OICggJElwQWRkciwgJE1hc2sgKSIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAkTGlzdGVuZXJBZGRyID0gIkRIQ1AiCiAgICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgICBbYXJyYXldJElQQWRkcmVzc2VzID0gJExpc3RlbmVyRGVmWyJTVEFUSUMiXQogICAgICAgIGlmICgoJElQQWRkcmVzc2VzIC1lcSAkbnVsbCkgLW9yICgkSVBBZGRyZXNzZXMuQ291bnQgLWVxIDApKSB7CiAgICAgICAgICAgICRMaXN0ZW5lckFkZHIgPSAiREhDUCIKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAkQ29udmVydGVkT3B0cyA9IEAoKQogICAgICAgICAgICBmb3JlYWNoICgkSXBPcHRpb24gaW4gJElQQWRkcmVzc2VzKSB7CiAgICAgICAgICAgICAgICAjIElQdjQKICAgICAgICAgICAgICAgIGlmICgkSXBPcHRpb24gLW1hdGNoICJcZCtcLlxkK1wuXGQrXC5cZCsvXGQrXC5cZCtcLlxkK1wuXGQrIikgewogICAgICAgICAgICAgICAgICAgICgkSXBBZGRyLCAkTWFzaykgPSAkSXBPcHRpb24gLXNwbGl0ICIvIgogICAgICAgICAgICAgICAgICAgICRDb252ZXJ0ZWRPcHRzID0gJENvbnZlcnRlZE9wdHMgKyAiKCAkKENvbnZlcnRUby1TUUxTdHJpbmcgJElwQWRkciksICQoQ29udmVydFRvLVNRTFN0cmluZyAkTWFzaykgKSIKICAgICAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgIyBJUHY2CiAgICAgICAgICAgICAgICBpZiAoJElwT3B0aW9uIC1tYXRjaCAiXigoKD89KD8+Lio/OjopKD8hLio6OikpKSg6Oik/KFswLTlBLUZdezEsNH06Oj8pezAsNX18KFswLTlBLUZdezEsNH06KXs2fSkoXDIoWzAtOUEtRl17MSw0fSg6Oj98JCkpezAsMn18KCgyNVswLTVdfCgyWzAtNF18MVxkfFsxLTldKT9cZCkoXC58JCkpezR9fFswLTlBLUZdezEsNH06WzAtOUEtRl17MSw0fSkoPzwhW146XTp8XC4pXHoiKSB7CiAgICAgICAgICAgICAgICAgICAgJENvbnZlcnRlZE9wdHMgPSAkQ29udmVydGVkT3B0cyArICIoICQoQ29udmVydFRvLVNRTFN0cmluZyAkSXBPcHRpb24pICkiCiAgICAgICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRocm93ICJNYWxmb3JtZWQgSVB2NC9JUHY2IGFkZHJlc3M6ICRJcE9wdGlvbiIKICAgICAgICAgICAgfQogICAgICAgICAgICAkTGlzdGVuZXJBZGRyID0gIklQICggJCgkQ29udmVydGVkT3B0cyAtam9pbiAnLCAnKSApIgogICAgICAgIH0KICAgIH0KICAgIGlmICgoJExpc3RlbmVyRGVmWyJOQU1FIl0gLWVxICRudWxsKSAtb3IgKCRMaXN0ZW5lckRlZlsiTkFNRSJdIC1tYXRjaCAiXlxzKiQiKSkgewogICAgICAgIHRocm93ICJMaXN0ZW5lciBuYW1lIGlzIHJlcXVpcmVkIgogICAgfQogICAgaWYgKC1ub3QgKCRMaXN0ZW5lckRlZlsiTkFNRSJdIC1tYXRjaCAiXltBLVphLXowLTlcLl9cLV0rJCIpKSB7CiAgICAgICAgdGhyb3cgIklsbGVnYWwgbGlzdGVuZXIgbmFtZS4gSXQgY2FuIGNvbnRhaW4gb25seSBhbHBoYW51bWVyaWMgY2hhcmFjdGVycywgZGFzaGVzICgtKSwgYW5kIGh5cGhlbnMgKF8pLCBpbiBhbnkgb3JkZXIuIgogICAgfQogICAgJFBvcnQgPSAkbnVsbAogICAgaWYgKCRMaXN0ZW5lckRlZlsiUE9SVCJdIC1uZSAkbnVsbCkgewogICAgICAgIGlmICgkTGlzdGVuZXJEZWZbIlBPUlQiXSAtbWF0Y2ggIlxkK1wrIikgewogICAgICAgICAgICAkU3RhcnRpbmdQb3J0ID0gJExpc3RlbmVyRGVmWyJQT1JUIl0gLXJlcGxhY2UgIlwrIiwgIiIKICAgICAgICAgICAgJFBvcnQgPSBHZXQtTmV4dEZyZWVQb3J0ICRTdGFydGluZ1BvcnQKICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICRMaXN0ZW5lckFkZHIgKyAiLCBQT1JUID0gJFBvcnQiCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKCRMaXN0ZW5lckRlZlsiUE9SVCJdIC1tYXRjaCAiXGQrIikgewogICAgICAgICAgICAgICAgJExpc3RlbmVyQWRkciA9ICRMaXN0ZW5lckFkZHIgKyAiLCBQT1JUID0gJCgkTGlzdGVuZXJEZWZbIlBPUlQiXSkiCiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyAiSW52YWxpZCBwb3J0IHZhbHVlOiAkKCRMaXN0ZW5lckRlZlsiUE9SVCJdKSIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgICRMaXN0ZW5lciA9ICJMSVNURU5FUiAnJCgkTGlzdGVuZXJEZWZbIk5BTUUiXSknICggV0lUSCAkTGlzdGVuZXJBZGRyICkiCgogICAgJE5hbWUgfCBPdXQtRmlsZSAiJFdvcmtEaXJcYXZncm91cC5uYW1lIgogICAgCiAgICBmb3IgKCRpID0gMDsgJGkgLWx0ICREYXRhYmFzZU5hbWVzLkxlbmd0aDsgJGkrKykgewogICAgICAgICREYXRhQmFzZU5hbWUgPSAkRGF0YWJhc2VOYW1lc1skaV0KICAgICAgICAkRGF0YUJhc2VOYW1lIHwgT3V0LUZpbGUgIiRXb3JrRGlyXGRiJGkubmFtZSIKICAgICAgICBOZXctU1FMRGF0YWJhc2UgJERhdGFCYXNlTmFtZQogICAgICAgICRCYWNrdXBEYiA9ICJCQUNLVVAgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBUTyBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcZGIkaS5iYWsiKSBXSVRIIE5PRk9STUFULCBJTklULCBOQU1FID0gTidGdWxsIERhdGFiYXNlIEJhY2t1cCcsIFNLSVAsIE5PUkVXSU5ELCBOT1VOTE9BRCwgU1RBVFMgPSAxMAogICAgICAgICAgICAgICAgICAgICBHTyIKICAgICAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwRGIpCiAgICAgICAgJEJhY2t1cExvZyA9ICJCQUNLVVAgTE9HICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgVE8gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXGRiJHtpfS5sb2cuYmFrIikgV0lUSCBOT0ZPUk1BVCwgSU5JVCwgIE5BTUUgPSBOJ1RyYW5zYWN0aW9uIExvZyAgQmFja3VwJywgU0tJUCwgTk9SRVdJTkQsIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgICAgICBHTyIKICAgICAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkQmFja3VwTG9nKQogICAgfQogICAgJFJlcGxpY2FEZWZpbml0aW9uc0FycmF5ID0gQCgpCiAgICBpZiAoJFByZWZzLkxlbmd0aCAtZ3QgMCkgewogICAgICAgICRQcmVmc0xpbmUgPSAiV0lUSCAoICQoJFByZWZzIC1qb2luICcsICcpICkiCiAgICB9IGVsc2UgewogICAgICAgICRQcmVmc0xpbmUgPSAiIgogICAgfQogICAgJFNRTCA9ICJDUkVBVEUgQVZBSUxBQklMSVRZIEdST1VQICQoQ29udmVydFRvLVNRTE5hbWUgJE5hbWUpICRQcmVmc0xpbmUKICAgICAgICAgICAgICAgIEZPUiBEQVRBQkFTRSAkUXVvdGVkREJOYW1lcwogICAgICAgICAgICAgICAgUkVQTElDQSBPTmByYG4gICAgICAgICRSZXBsaWNhRGVmaW5pdGlvbnMKICAgICAgICAgICAgICAgICRMaXN0ZW5lcjsKICAgICIKICAgIFt2b2lkXShJbnZva2UtU1FMVGV4dCAtU1FMICRTUUwpCiAgICByZXR1cm4gJFBvcnQKfQoKZnVuY3Rpb24gTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXBSZXBsaWNhIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENyZWF0ZXMgQWx3YXlzT24gYXZhaWxhYmlsaXR5IGdyb3VwIHNlY29uZGFyeSByZXBsaWNhCgogICAgLkRFU0NSSVBUSU9OCiAgICBDcmVhdGVzIEFsd2F5c09uIGF2YWlsYWJpbGl0eSBncm91cCBzZWNvbmRhcnkgcmVwbGljYSBiYXNlZCBvbiBpbmZvcm1hdGlvbiBwcm92aWRlZCB0byBhbmQgYnkgTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXAuCgogICAgLlBBUkFNRVRFUiBXb3JrRGlyCiAgICBXb3JraW5nIGRpcmVjdG9yeSB3aGljaCB3YXMgdHJhbnNmZXJyZWQgZnJvbSB0aGUgcHJpbWFyeSByZXBsaWNhLgogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJFdvcmtEaXIKICAgICkKICAgIGlmICgtbm90IChUZXN0LVBhdGggJFdvcmtEaXIpKSB7CiAgICAgICAgdGhyb3cgIldvcmsgZGlyICckV29ya0Rpcicgbm90IGZvdW5kIgogICAgfQogICAgJFdvcmtEaXJPYmogPSBHZXQtSXRlbSAtUGF0aCAkV29ya0RpcgogICAgJFdvcmtEaXIgPSAkV29ya0Rpck9iai5GdWxsTmFtZQogICAgJEdyb3VwTmFtZSA9IEdldC1Db250ZW50ICRXb3JrRGlyT2JqLkdldEZpbGVzKCJhdmdyb3VwLm5hbWUiKS5GdWxsTmFtZQoKICAgICRKb2luR3JvdXAgPSAiQUxURVIgQVZBSUxBQklMSVRZIEdST1VQICQoQ29udmVydFRvLVNRTE5hbWUgJEdyb3VwTmFtZSkgSk9JTgogICAgICAgICAgICAgICAgICAgR08iCiAgICBbdm9pZF0oSW52b2tlLVNRTFRleHQgLVNRTCAkSm9pbkdyb3VwKQoKICAgIGZvciAoJGkgPSAwOyA7ICRpKyspIHsKICAgICAgICAkRmlsZSA9ICRXb3JrRGlyT2JqLkdldEZpbGVzKCJkYiRpLm5hbWUiKQogICAgICAgIGlmICgtbm90ICRGaWxlKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICAkRGF0YUJhc2VOYW1lID0gR2V0LUNvbnRlbnQgJFdvcmtEaXJPYmouR2V0RmlsZXMoImRiJGkubmFtZSIpLkZ1bGxOYW1lCiAgICAgICAgJFJlc3RvcmVEYiA9ICJSRVNUT1JFIERBVEFCQVNFICQoQ29udmVydFRvLVNRTE5hbWUgJERhdGFCYXNlTmFtZSkgRlJPTSBESVNLID0gTiQoQ29udmVydFRvLVNRTFN0cmluZyAiJFdvcmtEaXJcZGIkaS5iYWsiKSBXSVRIIEZJTEUgPSAxLCBOT1JFQ09WRVJZLCBOT1VOTE9BRCwgUkVQTEFDRSwgU1RBVFMgPSA1CiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVEYikKICAgICAgICAkUmVzdG9yZUxvZyA9ICJSRVNUT1JFIExPRyAkKENvbnZlcnRUby1TUUxOYW1lICREYXRhQmFzZU5hbWUpIEZST00gRElTSyA9IE4kKENvbnZlcnRUby1TUUxTdHJpbmcgIiRXb3JrRGlyXGRiJGkubG9nLmJhayIpIFdJVEggRklMRSA9IDEsIE5PUkVDT1ZFUlksIE5PVU5MT0FELCBTVEFUUyA9IDEwCiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJFJlc3RvcmVMb2cpCiAgICAgICAgJEFsdGVyREIgPSAiQUxURVIgREFUQUJBU0UgJChDb252ZXJ0VG8tU1FMTmFtZSAkRGF0YUJhc2VOYW1lKSBTRVQgSEFEUiBBVkFJTEFCSUxJVFkgR1JPVVAgPSAkKENvbnZlcnRUby1TUUxOYW1lICRHcm91cE5hbWUpCiAgICAgICAgICAgICAgICAgICAgR08iCiAgICAgICAgW3ZvaWRdKEludm9rZS1TUUxUZXh0IC1TUUwgJEFsdGVyREIpCiAgICB9Cn0KCmZ1bmN0aW9uIE5ldy1SZXBsaWNhT3B0aW9uIHsKICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJE5hbWUsCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSwgVmFsdWVGcm9tUGlwZWxpbmUgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kVmFsdWUKICAgICkKICAgIHJldHVybiAiJE5hbWUgPSAkVmFsdWUiCn0KCmZ1bmN0aW9uIFZhbGlkYXRlLU9wdGlvbiB7CiAgICA8IwogICAgLlNZTk9QU0lTCiAgICBDaGVja3MgdGhhdCB0aGUgdmFsdWUgaXMgb25lIG9mIGFsbG93ZWQgdmFsdWVzCgogICAgLkRFU0NSSVBUSU9OCiAgICBDaGVja3MgdGhhdCB0aGUgdmFsdWUgaXMgb25lIG9mIGFsbG93ZWQgdmFsdWVzIG9yIHRocm93cyBleGNlcHRpb24gb3RoZXJ3aXNlLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCgogICAgLlBBUkFNRVRFUiBBbGxvd2VkCiAgICBMaXN0IG9mIGFsbG93ZWQgb3B0aW9uIHZhbHVzLgogICAgIz4KICAgIHBhcmFtKAogICAgICAgIFtwYXJhbWV0ZXIoTWFuZGF0b3J5ID0gJHRydWUpXQogICAgICAgIFtTdHJpbmddJE5hbWUsCiAgICAgICAgW1N0cmluZ10kVmFsdWUsCiAgICAgICAgW0FycmF5XSRBbGxvd2VkCiAgICApCiAgICBpZiAoKCRWYWx1ZSAtZXEgJG51bGwpIC1vciAoJFZhbHVlIC1lcSAiIikpIHsKICAgICAgICB0aHJvdyAiTm8gdmFsdWUgd2FzIHByb3ZpZGVkIGZvciAkTmFtZSIKICAgIH0KICAgIGZvcmVhY2ggKCRWIGluICRBbGxvd2VkKSB7CiAgICAgICAgaWYgKCRWIC1lcSAkVmFsdWUpIHsKICAgICAgICAgICAgcmV0dXJuICRWYWx1ZQogICAgICAgIH0KICAgIH0KICAgIHRocm93ICJQcm92aWRlZCB2YWx1ZSAnJFZhbHVlJyBmb3IgJE5hbWUgaXMgbm90IG9uZSBvZiAkKCRBbGxvd2VkIC1qb2luICcsICcpIgp9CgpmdW5jdGlvbiBWYWxpZGF0ZS1JbnRPcHRpb24gewogICAgPCMKICAgIC5TWU5PUFNJUwogICAgQ2hlY2tzIHRoYXQgdGhlIHZhbHVlIGlzIGludGVnZXIKCiAgICAuREVTQ1JJUFRJT04KICAgIENoZWNrcyB0aGF0IHRoZSB2YWx1ZSBpcyBpbnRlZ2VyLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kTmFtZSwKICAgICAgICBbcGFyYW1ldGVyXQogICAgICAgIFtTdHJpbmddJFZhbHVlCiAgICApCiAgICBpZiAoKCRWYWx1ZSAtZXEgJG51bGwpIC1vciAoJFZhbHVlIC1lcSAiIikpIHsKICAgICAgICB0aHJvdyAiTm8gdmFsdWUgd2FzIHByb3ZpZGVkIGZvciAkTmFtZSIKICAgIH0KICAgIGlmICgtbm90ICgiJFZhbHVlIiAtbWF0Y2ggIl5bKy1dP1xkKyQiKSkgewogICAgICAgIHRocm93ICJQcm92aWRlZCB2YWx1ZSAnJFZhbHVlJyBmb3IgJE5hbWUgaXMgbm90IGEgbnVtYmVyIgogICAgfQogICAgcmV0dXJuICRWYWx1ZQp9CgpmdW5jdGlvbiBWYWxpZGF0ZS1EZWZpbmVkT3B0aW9uIHsKICAgIDwjCiAgICAuU1lOT1BTSVMKICAgIENoZWNrcyB0aGF0IHRoZSB2YWx1ZSBpcyBub3QgbnVsbAoKICAgIC5ERVNDUklQVElPTgogICAgQ2hlY2tzIHRoYXQgdGhlIHZhbHVlIGlzIG5vdCBudWxsLiBSZXR1cm5zIHByb3ZpZGVkIHZhbHVlLgoKICAgIC5QQVJBTUVURVIgTmFtZQogICAgT3B0aW9uIG5hbWUuIFVzZWQgb25seSBmb3IgZXJyb3IgbWVzc2FnZS4KCiAgICAuUEFSQU1FVEVSIFZhbHVlCiAgICBPcHRpb24gdmFsdWUuCiAgICAjPgogICAgcGFyYW0oCiAgICAgICAgW3BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgICAgICAgW1N0cmluZ10kTmFtZSwKICAgICAgICBbcGFyYW1ldGVyKE1hbmRhdG9yeSA9ICRmYWxzZSldCiAgICAgICAgW1N0cmluZ10kVmFsdWUKICAgICkKICAgIGlmICgoJFZhbHVlIC1lcSAkbnVsbCkgLW9yICgkVmFsdWUgLWVxICIiKSkgewogICAgICAgIHRocm93ICJObyB2YWx1ZSB3YXMgcHJvdmlkZWQgZm9yICROYW1lIgogICAgfQogICAgcmV0dXJuICRWYWx1ZQp9CgoKCg==", - "CnRyYXAgewogICAgJiRUcmFwSGFuZGxlcgp9CgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlclBvd2VyU2hlbGxNb2R1bGUgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJwogICAgKQogICAgYmVnaW4gewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbgogICAgfQogICAgZW5kIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24gLUVuZAogICAgfQogICAgcHJvY2VzcyB7CiAgICAgICAgdHJhcCB7CiAgICAgICAgICAgICYkVHJhcEhhbmRsZXIKICAgICAgICB9CgogICAgICAgIGlmICgoR2V0LU1vZHVsZSBTUUxQUyAtTGlzdEF2YWlsYWJsZSkgLW5lICRudWxsKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiTW9kdWxlIFNRTFNQIGFscmVhZHkgaW5zdGFsbGVkLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcVG9vbHMnKQogICAgICAgIH0KICAgICAgICAKICAgICAgICAkRmlsZUxpc3QgPSBAKAogICAgICAgICAgICAnU1FMU3lzQ2xyVHlwZXMubXNpJywKICAgICAgICAgICAgJ1NoYXJlZE1hbmFnZW1lbnRPYmplY3RzLm1zaScsCiAgICAgICAgICAgICdQb3dlclNoZWxsVG9vbHMubXNpJwogICAgICAgICkKCiAgICAgICAgZm9yZWFjaCAoJE1zaUZpbGUgaW4gJEZpbGVMaXN0KSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVHJ5aW5nIHRvIGluc3RhbGwgJyRNc2lGaWxlJyAuLi4iCiAgICAgICAgICAgICRNc2lQYXRoID0gSm9pbi1QYXRoICRTZXR1cFJvb3QgJE1zaUZpbGUKICAgICAgICAgICAgaWYgKFtJTy5GaWxlXTo6RXhpc3RzKCRNc2lQYXRoKSkgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJTdGFydGluZyBtc2lleGUgLi4uIgogICAgICAgICAgICAgICAgJFJlc3VsdCA9IEV4ZWMgLUZpbGVQYXRoICJtc2lleGVjLmV4ZSIgLUFyZ3VtZW50TGlzdCBAKCcvaScsICJgIiRNc2lQYXRoYCIiLCAnL3F1aWV0JykgLVBhc3NUaHJ1CiAgICAgICAgICAgICAgICBpZiAoJFJlc3VsdC5FeGl0Q29kZSAtbmUgMCkgewogICAgICAgICAgICAgICAgICAgIHRocm93ICgiSW5zdGFsbGF0aW9uIG9mIE1TSSBwYWNrYWdlICckTXNpUGF0aCcgZmFpbGVkIHdpdGggZXJyb3IgY29kZSAnJCgkUmVzdWx0LkV4aXRDb2RlKSciKQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgV3JpdGUtTG9nICJGaWxlICckTXNpUGF0aCcgbm90IGZvdW5kLiIKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQoKCgpmdW5jdGlvbiBJbnN0YWxsLVNxbFNlcnZlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgUGF0aCB0byBmb2xkZXIgd2hlcmUgbXNpIGZpbGVzIGZvciBhZGRpdGlvbmFsIFNRTCBmZWF0dXJlcyBhcmUgbG9jYXRlZAogICAgICAgIFtTdHJpbmddICRTZXR1cFJvb3QgPSAnJywKCiAgICAgICAgIyBQYXRoIHRvIGZvbGRlciB3aGVyZSBtc2kgZmlsZXMgZm9yIGFkZGl0aW9uYWwgU1FMUFMgbW9kdWxlIGFyZSBsb2NhdGVkCiAgICAgICAgW1N0cmluZ10gJFNxbHBzU2V0dXBSb290ID0gJycsCgogICAgICAgIFtTdHJpbmddICRNdXJhbm9GaWxlU2hhcmUgPSAnJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIERvbWFpbiBuYW1lCiAgICAgICAgW1N0cmluZ10gJFNRTFNlcnZpY2VVc2VyRG9tYWluID0gJ2ZjLWFjbWUubG9jYWwnLAoKICAgICAgICAjIChSRVFVSVJFRCkgVXNlciBuYW1lIGZvciB0aGUgYWNjb3VudCB3aGljaCB3aWxsIGJlIHVzZWQgYnkgU1FMIHNlcnZpY2UKICAgICAgICBbU3RyaW5nXSAkU1FMU2VydmljZVVzZXJOYW1lID0gJ0FkbWluaXN0cmF0b3InLAoKICAgICAgICAjIChSRVFVSVJFRCkgUGFzc3dvcmQgZm9yIHRoYXQgdXNlcgogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlclBhc3N3b3JkID0gJ1BAc3N3MHJkJywKCiAgICAgICAgW1N3aXRjaF0gJFVwZGF0ZUVuYWJsZWQKICAgICkKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBpZiAoJE11cmFub0ZpbGVTaGFyZSAtZXEgJycpIHsKICAgICAgICAgICAgJE11cmFub0ZpbGVTaGFyZSA9IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ011cmFub0ZpbGVTaGFyZScpCiAgICAgICAgICAgIGlmICgkTXVyYW5vRmlsZVNoYXJlIC1lcSAnJykgewogICAgICAgICAgICAgICAgdGhyb3coIlVuYWJsZSB0byBmaW5kIE11cmFub0ZpbGVTaGFyZSBwYXRoLiIpCiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICgkU2V0dXBSb290IC1lcSAnJykgewogICAgICAgICAgICAkU2V0dXBSb290ID0gW0lPLlBhdGhdOjpDb21iaW5lKCRNdXJhbm9GaWxlU2hhcmUsICdQcmVyZXF1aXNpdGVzXFNRTCBTZXJ2ZXJcMjAxMicpCiAgICAgICAgfQoKICAgICAgICAkRXh0cmFPcHRpb25zID0gQHt9CgogICAgICAgIGlmICgkVXBkYXRlRW5hYmxlZCkgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJHRydWV9CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkRXh0cmFPcHRpb25zICs9IEB7J1VwZGF0ZUVuYWJsZWQnID0gJGZhbHNlfQogICAgICAgIH0KCiAgICAgICAgTmV3LVNRTFNlcnZlckZvckFPQUcgYAogICAgICAgICAgICAtU2V0dXBSb290ICRTZXR1cFJvb3QgYAogICAgICAgICAgICAtU1FMU3ZjVXNyRG9tYWluICRTUUxTZXJ2aWNlVXNlckRvbWFpbiBgCiAgICAgICAgICAgIC1TUUxTdmNVc3JOYW1lICRTUUxTZXJ2aWNlVXNlck5hbWUgYAogICAgICAgICAgICAtU1FMU3ZjVXNyUGFzc3dvcmQgJFNRTFNlcnZpY2VVc2VyUGFzc3dvcmQgYAogICAgICAgICAgICAtRXh0cmFPcHRpb25zICRFeHRyYU9wdGlvbnMKICAgIH0KfQoKCgpmdW5jdGlvbiBJbml0aWFsaXplLUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXAgewogICAgcGFyYW0gKAogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICREb21haW5BZG1pbkFjY291bnRQYXNzd29yZCwKICAgICAgICBbU3RyaW5nXSAkU3FsU2VydmljZUFjY291bnROYW1lLAogICAgICAgIFtTdHJpbmddICRQcmltYXJ5Tm9kZSwKICAgICAgICBbU3RyaW5nXSAkU2hhcmVOYW1lID0gJ1NoYXJlZFdvcmtEaXInCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgJFNoYXJlTmV0d29ya1BhdGggPSAnXFwnICsgJFByaW1hcnlOb2RlICsgJ1wnICsgJFNoYXJlTmFtZQoKICAgICAgICAkRG9tYWluQWRtaW5BY2NvdW50Q3JlZHMgPSBOZXctQ3JlZGVudGlhbCBgCiAgICAgICAgICAgIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJERvbWFpbkFkbWluQWNjb3VudE5hbWUiIGAKICAgICAgICAgICAgLVBhc3N3b3JkICIkRG9tYWluQWRtaW5BY2NvdW50UGFzc3dvcmQiCgogICAgICAgICRGdW5jdGlvbnNGaWxlID0gRXhwb3J0LUZ1bmN0aW9uICdHZXQtTmV4dEZyZWVQb3J0JywgJ0luaXRpYWxpemUtQWx3YXlzT24nCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICBgJF8KICAgIGV4aXQgMQp9CgpJbXBvcnQtTW9kdWxlIENvcmVGdW5jdGlvbnMKCldyaXRlLUxvZyAiSW1wb3J0aW5nIGZ1bmN0aW9ucyBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ0luaXRpYWxpemUtQWx3YXlzT24nIC4uLiIKYCRYbWxGaWxlID0gW0lPLlBhdGhdOjpDb21iaW5lKCIkU2hhcmVOZXR3b3JrUGF0aCIsICJgJChgJEVudjpDb21wdXRlck5hbWUpLnhtbCIpCldyaXRlLUxvZyAiT3V0cHV0IFhNTCBmaWxlIGlzICdgJFhtbEZpbGUnIgpJbml0aWFsaXplLUFsd2F5c09uIHwgRXhwb3J0LUNsaVhtbCAtUGF0aCBgJFhtbEZpbGUKIkAgLUNyZWRlbnRpYWwgJERvbWFpbkFkbWluQWNjb3VudENyZWRzIC1Ob0Jhc2U2NAogICAgfQp9CgoKZnVuY3Rpb24gTmV3LVNoYXJlZEZvbGRlckZvckFPQUcgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKQogICAgICAgIFtTdHJpbmddICRTaGFyZVBhdGggPSBbSU8uUGF0aF06OkNvbWJpbmUoJEVudjpTeXN0ZW1Ecml2ZSArICdcJywgJ1NoYXJlZFdvcmtEaXInKSwKCiAgICAgICAgIyAoT1BUSU9OQUwpCiAgICAgICAgW1N0cmluZ10gJFNoYXJlTmFtZSA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlID0gJyAnCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBzY3JpcHQgcnVucyBvbiBwcmltYXJ5IG5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZyBzY3JpcHQuIgogICAgICAgICAgICByZXR1cm4KICAgICAgICB9CgogICAgICAgIGlmICgkU2hhcmVOYW1lIC1lcSAnJykgewogICAgICAgICAgICAkU2hhcmVOYW1lID0gW0lPLlBhdGhdOjpHZXRGaWxlTmFtZVdpdGhvdXRFeHRlbnNpb24oJFNoYXJlUGF0aCkKICAgICAgICB9CgogICAgICAgIFdyaXRlLUxvZ0RlYnVnICJTaGFyZVBhdGggPSAnJFNoYXJlUGF0aCciCiAgICAgICAgV3JpdGUtTG9nRGVidWcgIlNoYXJlTmFtZSA9ICckU2hhcmVOYW1lJyIKCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgc2hhcmUgJyRTaGFyZU5hbWUnIgogICAgICAgICAgICAkbnVsbCA9IEdldC1TbWJTaGFyZSAtTmFtZSAkU2hhcmVOYW1lIC1FcnJvckFjdGlvbiAnU3RvcCcKICAgICAgICAgICAgJG51bGwgPSBSZW1vdmUtU21iU2hhcmUgLU5hbWUgJFNoYXJlTmFtZSAtRm9yY2UKICAgICAgICAgICAgd3JpdGUtTG9nICJTaGFyZSAnJFNoYXJlTmFtZScgcmVtb3ZlZC4iCiAgICAgICAgfQogICAgICAgIGNhdGNoIHsKICAgICAgICAgICAgV3JpdGUtTG9nV2FybmluZyAiU2hhcmUgJyRTaGFyZU5hbWUnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgV3JpdGUtTG9nRGVidWcgIlRyeWluZyB0byByZW1vdmUgZm9sZGVyICckU2hhcmVQYXRoIgogICAgICAgICAgICAkbnVsbCA9IEdldC1JdGVtIC1QYXRoICRTaGFyZVBhdGggLUVycm9yQWN0aW9uICdTdG9wJwogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICRTaGFyZVBhdGggLVJlY3Vyc2UgLUZvcmNlCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRm9sZGVyICckU2hhcmVQYXRoJyByZW1vdmVkLiIKICAgICAgICB9CiAgICAgICAgY2F0Y2ggewogICAgICAgICAgICBXcml0ZS1Mb2dXYXJuaW5nICJGb2xkZXIgJyRTaGFyZVBhdGgnIG5vdCBleGlzdHMgb3IgY2Fubm90IGJlIGRlbGV0ZWQuIgogICAgICAgIH0KCiAgICAgICAgJG51bGwgPSBOZXctSXRlbSAtUGF0aCAkU2hhcmVQYXRoIC1JdGVtVHlwZSBDb250YWluZXIgLUZvcmNlCiAgICAgICAgICAgICAgICAKICAgICAgICAkbnVsbCA9IE5ldy1TbWJTaGFyZSAtUGF0aCAkU2hhcmVQYXRoIGAKICAgICAgICAgICAgLU5hbWUgJFNoYXJlTmFtZSBgCiAgICAgICAgICAgIC1GdWxsQWNjZXNzICJFdmVyeW9uZSIgYAogICAgICAgICAgICAtRGVzY3JpcHRpb24gIlNoYXJlZCBmb2xkZXIgZm9yIEFsd2F5c09uIEF2YWlsYWJpbGl0eSBHcm91cCBzZXR1cC4iCgogICAgICAgIHJldHVybiAnXFwnICsgJEVudjpDb21wdXRlck5hbWUgKyAnXCcgKyAkU2hhcmVOYW1lCiAgICB9Cn0KCgoKZnVuY3Rpb24gTmV3LURhdGFiYXNlRm9yQU9BRyB7CiAgICBwYXJhbSAoCiAgICAgICAgW1N0cmluZ10gJERhdGFiYXNlTmFtZSwKICAgICAgICBbU3RyaW5nXSAkRG9tYWluTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlck5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJQYXNzd29yZAogICAgKQoKICAgICRDcmVkcyA9IE5ldy1DcmVkZW50aWFsIC1Vc2VyTmFtZSAiJERvbWFpbk5hbWVcJFVzZXJOYW1lIiAtUGFzc3dvcmQgIiRVc2VyUGFzc3dvcmQiCgogICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gJ0ludm9rZS1TUUxUZXh0JywgJ0NvbnZlcnRUby1TUUxOYW1lJywgJ0NvbnZlcnRUby1TUUxTdHJpbmcnLCAnTmV3LVNRTERhdGFiYXNlJwoKICAgIFN0YXJ0LVBvd2VyU2hlbGxQcm9jZXNzIEAiCnRyYXAgewogICAgYCRfCiAgICBleGl0IDEKfQoKSW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zCgpXcml0ZS1Mb2cgIkltcG9ydGluZyBmdW5jdGlvbnMgZnJvbSBmaWxlICckRnVuY3Rpb25zRmlsZScgLi4uIgouICIkRnVuY3Rpb25zRmlsZSIKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1TUUxEYXRhYmFzZScgLi4uIgpOZXctU1FMRGF0YWJhc2UgJERhdGFiYXNlTmFtZQoiQCAtQ3JlZGVudGlhbCAkQ3JlZHMgLU5vQmFzZTY0Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHUHJpbWFyeVJlcGxpY2EgewogICAgcGFyYW0gKAogICAgICAgICMgKE9QVElPTkFMKSBOYW1lIG9mIHRoZSBuZXcgQXZhaWxhYmlsaXR5IEdyb3VwLiBJZiBub3Qgc3BlY2lmaWVkIHRoZW4gZGVmYXVsdCBuYW1lIHdpbGwgYmUgdXNlZC4KICAgICAgICBbU3RyaW5nXSAkR3JvdXBOYW1lID0gJ011cmFub0FHJywKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICROb2RlTGlzdCwKCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGUgbmFtZSB0aGF0IHdpbGwgYmUgcHJpbWFyeSBmb3Igc2VsZWN0ZWQgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nXSAkUHJpbWFyeU5vZGUsCgogICAgICAgICMgKFJFUVVJUkVEKSBEYXRhYmFzZSBsaXN0IHRoYXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgQXZhaWxhYmlsaXR5IEdyb3VwCiAgICAgICAgI1tQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nW11dICREYXRhYmFzZUxpc3QsCgogICAgICAgICMgKFJFUVVJUkVEKSBMaXN0ZW5lciBuYW1lIHRoYXQgd2lsbCBiZSB1c2VkIGJ5IGNsaWVudHMgdG8gY29ubmVjdCB0byBkYXRhYmFzZXMgaW4gdGhhdCBBRwogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyTmFtZSA9ICdNdXJhbm9BR19MaXN0ZW5lcicsCgogICAgICAgICMgKFJFUVVJUkVEKSBJUCBhZGRyZXNzIG9mIHRoZSBsaXN0ZW5lcgogICAgICAgICNbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVySVAsCgogICAgICAgIFtTdHJpbmddICRMaXN0ZW5lcklQTWFzayA9ICcyNTUuMjU1LjI1NS4wJywKCiAgICAgICAgW1N0cmluZ10gJExpc3RlbmVyUG9ydCA9ICc1MDIzJywKCiAgICAgICAgIyBTeW5jIE1vZGUgTm9kZSBMaXN0CiAgICAgICAgW1N0cmluZ1tdXSAkU3luY01vZGVOb2RlTGlzdCwKCiAgICAgICAgW1N0cmluZ10gJFNoYXJlZFdvcmtEaXIgPSAnU2hhcmVkV29ya0RpcicsCgogICAgICAgIFtTdHJpbmddICRDbGlYbWxGaWxlID0gJycsCgogICAgICAgIFtTdHJpbmddICREb21haW5OYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyTmFtZSwKICAgICAgICBbU3RyaW5nXSAkVXNlclBhc3N3b3JkCiAgICApCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgV3JpdGUtTG9nICJQcmltYXJ5IG5vZGU6ICckKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkpJyIKICAgICAgICBXcml0ZS1Mb2cgIkN1cnJlbnQgbm9kZTogJyQoKCRFbnY6Q29tcHV0ZXJOYW1lKS5Ub0xvd2VyKCkpJyIKCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLW5lICQoJEVudjpDb21wdXRlck5hbWUpLlRvTG93ZXIoKSkgewogICAgICAgICAgICBXcml0ZS1Mb2cgIlRoaXMgZnVuY3Rpb24gd29ya3Mgb24gUHJpbWFyeU5vZGUgb25seS4iCiAgICAgICAgICAgIFdyaXRlLUxvZyAiRXhpdGluZy4iCiAgICAgICAgICAgIHJldHVybgogICAgICAgIH0KCiAgICAgICAgaWYgKCRDbGlYbWxGaWxlIC1lcSAnJykgewogICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ID0gQCgpCiAgICAgICAgICAgIGZvcmVhY2ggKCROb2RlIGluICROb2RlTGlzdCkgewogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAkTm9kZUVuZHBvaW50UG9ydCA9IEltcG9ydC1DbGlYbWwgLVBhdGggIlxcJFByaW1hcnlOb2RlXFNoYXJlZFdvcmtEaXJcJE5vZGUueG1sIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2F0Y2ggewogICAgICAgICAgICAgICAgICAgIFdyaXRlLUxvZyAiVXNpbmcgZGVmYXVsdCBlbmRwb2ludCBwb3J0IDUwMjIiCiAgICAgICAgICAgICAgICAgICAgJE5vZGVFbmRwb2ludFBvcnQgPSA1MDIyCiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uID0gQHsKICAgICAgICAgICAgICAgICAgICAiU0VSVkVSX0lOU1RBTkNFIiA9ICIkTm9kZSI7CiAgICAgICAgICAgICAgICAgICAgIkVORFBPSU5UX1VSTCIgPSAiVENQOi8vJHtOb2RlfToke05vZGVFbmRwb2ludFBvcnR9IjsKICAgICAgICAgICAgICAgICAgICAiQVZBSUxBQklMSVRZX01PREUiID0gIkFTWU5DSFJPTk9VU19DT01NSVQiOwogICAgICAgICAgICAgICAgICAgICJGQUlMT1ZFUl9NT0RFIj0iTUFOVUFMIjsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZiAoJFN5bmNNb2RlTm9kZUxpc3QgLWNvbnRhaW5zICROb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBpbiBTeW5jTW9kZU5vZGVMaXN0IgogICAgICAgICAgICAgICAgICAgICRSZXBsaWNhRGVmaW5pdGlvblsnQVZBSUxBQklMSVRZX01PREUnXSA9ICJTWU5DSFJPTk9VU19DT01NSVQiCiAgICAgICAgICAgICAgICAgICAgJFJlcGxpY2FEZWZpbml0aW9uWydGQUlMT1ZFUl9NT0RFJ10gPSAiQVVUT01BVElDIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgV3JpdGUtTG9nICIkTm9kZSBpcyBOT1QgaW4gU3luY01vZGVOb2RlTGlzdCIKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAkUmVwbGljYURlZmluaXRpb25MaXN0ICs9IEAoJFJlcGxpY2FEZWZpbml0aW9uKQogICAgICAgICAgICB9CgogICAgICAgICAgICAkUHJlZmVyZW5jZXMgPSBAe30KCiAgICAgICAgICAgICRMaXN0ZW5lckRlZmluaXRpb24gPSBAewogICAgICAgICAgICAgICAgIk5BTUUiPSRMaXN0ZW5lck5hbWU7CiAgICAgICAgICAgICAgICAiUE9SVCIgPSAiJExpc3RlbmVyUG9ydCI7CiAgICAgICAgICAgICAgICAiU1RBVElDIiA9ICIkTGlzdGVuZXJJUC8kTGlzdGVuZXJJUE1hc2siCiAgICAgICAgICAgIH0KCiAgICAgICAgICAgICRQYXJhbWV0ZXJzID0gQHsKICAgICAgICAgICAgICAgICdXb3JrRGlyJyA9ICJcXCRQcmltYXJ5Tm9kZVwkU2hhcmVkV29ya0RpciI7CiAgICAgICAgICAgICAgICAnTmFtZScgPSAkR3JvdXBOYW1lOwogICAgICAgICAgICAgICAgJ0RhdGFiYXNlTmFtZXMnID0gJERhdGFiYXNlTGlzdDsKICAgICAgICAgICAgICAgICdSZXBsaWNhRGVmcycgPSAkUmVwbGljYURlZmluaXRpb25MaXN0OwogICAgICAgICAgICAgICAgJ1ByZWZlcmVuY2VzJyA9ICRQcmVmZXJlbmNlczsKICAgICAgICAgICAgICAgICdMaXN0ZW5lckRlZicgPSAkTGlzdGVuZXJEZWZpbml0aW9uOwogICAgICAgICAgICB9CgogICAgICAgICAgICAkbnVsbCA9IFJlbW92ZS1JdGVtIC1QYXRoICJcXCRQcmltYXJ5Tm9kZVxTaGFyZWRXb3JrRGlyXCoiIC1Gb3JjZQoKICAgICAgICAgICAgJENsaVhtbEZpbGUgPSBbSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiQ2xpWG1sIGZpbGU6ICckQ2xpWG1sRmlsZSciCgogICAgICAgICAgICAkbnVsbCA9IEV4cG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUgLUlucHV0T2JqZWN0ICRQYXJhbWV0ZXJzIC1EZXB0aCAxMAoKICAgICAgICAgICAgJG51bGwgPSBJbml0aWFsaXplLUFPQUdQcmltYXJ5UmVwbGljYSBgCiAgICAgICAgICAgICAgICAtQ2xpWG1sRmlsZSAkQ2xpWG1sRmlsZSBgCiAgICAgICAgICAgICAgICAtRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgCiAgICAgICAgICAgICAgICAtVXNlck5hbWUgJFVzZXJOYW1lIGAKICAgICAgICAgICAgICAgIC1Vc2VyUGFzc3dvcmQgJFVzZXJQYXNzd29yZCBgCiAgICAgICAgICAgICAgICAtUHJpbWFyeU5vZGUgJFByaW1hcnlOb2RlCgogICAgICAgICAgICBXcml0ZS1Mb2dEZWJ1ZyAiSW5uZXIgJ0luaXRpYWxpemUtQU9BR1ByaW1hcnlSZXBsaWNhJyBjYWxsIGNvbXBsZXRlZC4iCiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAgICAgJEZ1bmN0aW9uc0ZpbGUgPSBFeHBvcnQtRnVuY3Rpb24gLUFsbAoKICAgICAgICAgICAgJG51bGwgPSBTdGFydC1Qb3dlclNoZWxsUHJvY2VzcyBAIgp0cmFwIHsKICAgIGAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJJbXBvcnRpbmcgQ2xpWG1sIHBhcmFtZXRlcnMgZmlsZSAuLi4iCmAkUGFyYW1ldGVycyA9IEltcG9ydC1DbGlYbWwgLVBhdGggJENsaVhtbEZpbGUKCldyaXRlLUxvZyAiU3RhcnRpbmcgJ05ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwIGBgCiAgICAtV29ya0RpciBgJFBhcmFtZXRlcnNbJ1dvcmtEaXInXSBgYAogICAgLU5hbWUgYCRQYXJhbWV0ZXJzWydOYW1lJ10gYGAKICAgIC1EYXRhYmFzZU5hbWVzIGAkUGFyYW1ldGVyc1snRGF0YWJhc2VOYW1lcyddIGBgCiAgICAtUmVwbGljYURlZnMgYCRQYXJhbWV0ZXJzWydSZXBsaWNhRGVmcyddIGBgCiAgICAtUHJlZmVyZW5jZXMgYCRQYXJhbWV0ZXJzWydQcmVmZXJlbmNlcyddIGBgCiAgICAtTGlzdGVuZXJEZWYgYCRQYXJhbWV0ZXJzWydMaXN0ZW5lckRlZiddCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgICAgICB9CiAgICB9Cn0KCgoKZnVuY3Rpb24gSW5pdGlhbGl6ZS1BT0FHU2Vjb25kYXJ5UmVwbGljYSB7CiAgICBwYXJhbSAoCiAgICAgICAgIyAoUkVRVUlSRUQpIE5vZGVzIHRoYXQgd2lsbCBiZSBjb25maWd1cmVkIGFzIHJlcGxpY2EgcGFydG5lcnMuCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmdbXV0gJE5vZGVMaXN0LAoKICAgICAgICAjIChSRVFVSVJFRCkgTm9kZSBuYW1lIHRoYXQgd2lsbCBiZSBwcmltYXJ5IGZvciBzZWxlY3RlZCBBdmFpbGFiaWxpdHkgR3JvdXAKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJFByaW1hcnlOb2RlLAoKICAgICAgICBbU3RyaW5nXSAkU2hhcmVkV29ya0RpciA9ICdTaGFyZWRXb3JrRGlyJywKCiAgICAgICAgW1N0cmluZ10gJERvbWFpbk5hbWUsCiAgICAgICAgW1N0cmluZ10gJFVzZXJOYW1lLAogICAgICAgIFtTdHJpbmddICRVc2VyUGFzc3dvcmQKICAgICkgCiAgICBiZWdpbiB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uCiAgICB9CiAgICBlbmQgewogICAgICAgIFNob3ctSW52b2NhdGlvbkluZm8gJE15SW52b2NhdGlvbiAtRW5kCiAgICB9CiAgICBwcm9jZXNzIHsKICAgICAgICB0cmFwIHsKICAgICAgICAgICAgJiRUcmFwSGFuZGxlcgogICAgICAgIH0KCiAgICAgICAgaWYgKCRQcmltYXJ5Tm9kZS5Ub0xvd2VyKCkgLWVxICgkRW52OkNvbXB1dGVyTmFtZSkuVG9Mb3dlcigpKSB7CiAgICAgICAgICAgIFdyaXRlLUxvZyAiVGhpcyBmdW5jdGlvbiB3b3JrcyBvbiBhbnkgU2Vjb25kYXJ5Tm9kZSBvbmx5LiIKICAgICAgICAgICAgV3JpdGUtTG9nICJFeGl0aW5nLiIKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQoKICAgICAgICAkQ3JlZHMgPSBOZXctQ3JlZGVudGlhbCAtVXNlck5hbWUgIiREb21haW5OYW1lXCRVc2VyTmFtZSIgLVBhc3N3b3JkICIkVXNlclBhc3N3b3JkIgoKICAgICAgICAkRnVuY3Rpb25zRmlsZSA9IEV4cG9ydC1GdW5jdGlvbiAtQWxsCgogICAgICAgICRudWxsID0gU3RhcnQtUG93ZXJTaGVsbFByb2Nlc3MgQCIKdHJhcCB7CiAgICAkXwogICAgZXhpdCAxCn0KCkltcG9ydC1Nb2R1bGUgQ29yZUZ1bmN0aW9ucwoKV3JpdGUtTG9nICJJbXBvcnRpbmcgZnVuY3Rpb25zIGZyb20gJyRGdW5jdGlvbnNGaWxlJyAuLi4iCi4gIiRGdW5jdGlvbnNGaWxlIgoKV3JpdGUtTG9nICJTdGFydGluZyAnTmV3LUFsd2F5c09uQXZhaWxhYmlsaXR5R3JvdXBSZXBsaWNhJyAuLi4iCk5ldy1BbHdheXNPbkF2YWlsYWJpbGl0eUdyb3VwUmVwbGljYSAtV29ya0RpciAiXFwkUHJpbWFyeU5vZGVcJFNoYXJlZFdvcmtEaXIiCiJAIC1DcmVkZW50aWFsICRDcmVkcyAtTm9CYXNlNjQKICAgIH0KfQoKCgpmdW5jdGlvbiBEaXNhYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb2ZmCiAgICB9Cn0KCgoKZnVuY3Rpb24gRW5hYmxlLUZpcmV3YWxsIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBuZXRzaCBhZHZmaXJld2FsbCBzZXQgYWxscHJvZmlsZXMgc3RhdGUgb24KICAgIH0KfQoKCgpmdW5jdGlvbiBFbmFibGUtVHJ1c3RlZEhvc3RzIHsKICAgIGJlZ2luIHsKICAgICAgICBTaG93LUludm9jYXRpb25JbmZvICRNeUludm9jYXRpb24KICAgIH0KICAgIGVuZCB7CiAgICAgICAgU2hvdy1JbnZvY2F0aW9uSW5mbyAkTXlJbnZvY2F0aW9uIC1FbmQKICAgIH0KICAgIHByb2Nlc3MgewogICAgICAgIHRyYXAgewogICAgICAgICAgICAmJFRyYXBIYW5kbGVyCiAgICAgICAgfQoKICAgICAgICBTZXQtSXRlbSBXU01hbjpcbG9jYWxob3N0XENsaWVudFxUcnVzdGVkSG9zdHMgLVZhbHVlICcqJyAtRm9yY2UKICAgIH0KfQo=" ] } \ No newline at end of file diff --git a/data/templates/agent/scripts/CopyPrerequisites.ps1 b/data/templates/agent/scripts/CopyPrerequisites.ps1 new file mode 100644 index 0000000..5e939c4 --- /dev/null +++ b/data/templates/agent/scripts/CopyPrerequisites.ps1 @@ -0,0 +1,50 @@ + +trap { + &$TrapHandler +} + + +Function Copy-Prerequisites { + param ( + [String] $Path = '', + [String] $Destination = '' + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + Write-Log "--> Copy-Prerequisites" + + if ($Destination -eq '') { + throw("Copy-Prerequisites: Destination path not specified!") + } + + if ($Path -eq '') { + $Path = [Environment]::GetEnvironmentVariable('MuranoFileShare') + if ($Path -eq $null) { + throw("Copy-Prerequisites: Unable to determine source path for prerequisites.") + } + } + + Write-Log "Creating new PSDrive ..." + New-PSDrive -Name 'P' -PSProvider 'FileSystem' -Root $Path | Out-Null + + Write-Log "Creating destination folder ..." + New-Item -Path $Destination -ItemType Container -Force | Out-Null + + Write-Log "Copying items ..." + Copy-Item -Path 'P:\Prerequisites\IIS' -Destination $Destination -Recurse -Force | Out-Null + + Write-Log "Removing PSDrive ..." + Remove-PSDrive -Name 'P' -PSProvider 'FileSystem' -Force | Out-Null + + Write-Log "<-- Copy-Prerequisites" + } +} diff --git a/data/templates/agent/scripts/DeployWebApp.ps1 b/data/templates/agent/scripts/DeployWebApp.ps1 new file mode 100644 index 0000000..8c4ca69 --- /dev/null +++ b/data/templates/agent/scripts/DeployWebApp.ps1 @@ -0,0 +1,148 @@ + +trap { + &$TrapHandler +} + + +Function Register-WebApp { +<# +.LINKS + +http://www.iis.net/learn/manage/powershell/powershell-snap-in-creating-web-sites-web-applications-virtual-directories-and-application-pools +#> + param ( + [String] $Source, + [String] $Path = "C:\inetpub\wwwroot", + [String] $Name = "", + [String] $Username = "", + [String] $Password = "" + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + Import-Module WebAdministration + + if ($Name -eq "") { + $Name = @([IO.Path]::GetDirectoryName($Source) -split '\\')[-1] + if ($Name -eq "wwwroot") { + throw("Application pool name couldn't be 'wwwroot'.") + } + } + else { + $Path = [IO.Path]::Combine($Path, $Name) + } + + Copy-Item -Path $Source -Destination $Path -Recurse -Force + + + # Create new application pool + $AppPool = New-WebAppPool -Name $Name -Force + #$AppPool = Get-Item "IIS:\AppPools\$Name" + $AppPool.managedRuntimeVersion = 'v4.0' + $AppPool.managedPipelineMode = 'Classic' + $AppPool.processModel.loadUserProfile = $true + $AppPool.processModel.logonType = 'LogonBatch' + + #Set Identity type + if ($Username -eq "") { + $AppPool.processModel.identityType = 'ApplicationPoolIdentity' + } + else { + $AppPool.processModel.identityType = 'SpecificUser' + $AppPool.processModel.userName = $Username + $AppPool.processModel.password = $Password + $AppPool | Set-Item + } + + + # Create Website + $WebSite = New-WebSite -Name $Name -Port 80 -HostHeader $Name -PhysicalPath $Path -Force + #$WebSite = Get-Item "IIS:\Sites\$Name" + + # Set the Application Pool + Set-ItemProperty "IIS:\Sites\$Name" 'ApplicationPool' $Name + + #Turn on Directory Browsing + #Set-WebConfigurationProperty -Filter '/system.webServer/directoryBrowse' -Name 'enabled' -Value $true -PSPath "IIS:\Sites\$Name" + + # Update Authentication + #Set-WebConfigurationProperty -Filter '/system.WebServer/security/authentication/AnonymousAuthentication' -Name 'enabled' -Value $true -Location $name + #Set-WebConfigurationProperty -Filter '/system.WebServer/security/authentication/windowsAuthentication' -Name 'enabled' -Value $false -Location $Name + #Set-WebConfigurationProperty -Filter '/system.WebServer/security/authentication/basicAuthentication' -Name 'enabled' -Value $false -Location $Name + + $WebSite.Start() + + Add-Content -Path "C:\Windows\System32\Drivers\etc\hosts" -Value "127.0.0.1 $Name" + } +} + + + +Function Deploy-WebAppFromGit { + param ( + [String] $URL, + [String] $TempPath = [IO.Path]::Combine([IO.Path]::GetTempPath(), [IO.Path]::GetRandomFileName()), + [String] $OutputPath = [IO.Path]::Combine([IO.Path]::GetTempPath(), [IO.Path]::GetRandomFileName()) + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + Write-Log "TempPath = '$TempPath'" + Write-Log "OutputPath = '$OutputPath'" + + + # Fetch web application + #---------------------- + Write-Log "Fetching sources from Git ..." + + $null = New-Item -Path $TempPath -ItemType Container + Exec -FilePath 'git.exe' -ArgumentList @('clone', $URL) -WorkingDir $TempPath -RedirectStreams + + $Path = @(Get-ChildItem $TempPath)[0].FullName + #---------------------- + + + # Build web application + #---------------------- + Write-Log "Building sources ..." + + $msbuild = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe" + + $null = New-Item -Path $OutputPath -ItemType Container + + $SlnFiles = @(Get-ChildItem -Path $Path -Filter *.sln -Recurse) + + # Start new processs with additional env variables: + #* VisualStudioVersion = "10.0" + #* EnableNuGetPackageRestore = "true" + Exec -FilePath $msbuild ` + -ArgumentList @($SlnFiles[0].FullName, "/p:OutputPath=$OutputPath") ` + -Environment @{'VisualStudioVersion' = '10.0'; 'EnableNuGetPackageRestore' = 'true'} ` + -RedirectStreams + + $AppFolder = @(Get-ChildItem ([IO.Path]::Combine($OutputPath, '_PublishedWebsites')))[0] + #---------------------- + + + # Install web application + #------------------------ + Register-WebApp -Source $AppFolder.FullName -Name $AppFolder.Name + #------------------------ + } +} diff --git a/data/templates/agent/scripts/Export-Function.ps1 b/data/templates/agent/scripts/Export-Function.ps1 new file mode 100644 index 0000000..8cd1b57 --- /dev/null +++ b/data/templates/agent/scripts/Export-Function.ps1 @@ -0,0 +1,61 @@ + +trap { + &$TrapHandler +} + +function Export-Function { + param ( + [String[]] $Name, + + [Parameter(ValueFromPipeline=$true)] + [String] $Path = [IO.Path]::GetTempFileName(), + + [Switch] $All + ) + + if ([IO.Path]::GetExtension($Path) -ne 'ps1') { + $null = Rename-Item -Path $Path -NewName "$Path.ps1" -Force + $Path = "$Path.ps1" + } + + $SystemFunctions = @( + 'A:', 'B:', 'C:', 'D:', 'E:', 'F:', 'G:', 'H:', 'I:', 'J:', + 'K:', 'L:', 'M:', 'N:', 'O:', 'P:', 'Q:', 'R:', 'S:', 'T:', + 'U:', 'V:', 'W:', 'X:', 'Y:', 'Z:', + 'cd..', 'cd\', 'help', 'mkdir', 'more', 'oss', 'prompt', + 'Clear-Host', 'Get-Verb', 'Pause', 'TabExpansion2' + ) + + if ($All) { + Get-ChildItem Function: | + Where-Object {$_.ModuleName -eq ''} | + Where-Object {$SystemFunctions -notcontains $_.Name} | + ForEach-Object { + Add-Content -Path $Path -Value @" + + +function $($_.Name) { +$($_.ScriptBlock) +} + +"@ + } + } + else { + foreach ($FunctionName in $Name) { + $FunctionObject = Get-ChildItem "Function:\$FunctionName" + if ($FunctionObject -ne $null) { + Add-Content -Path $Path -Value @" + + +function $FunctionName { +$($FunctionObject.ScriptBlock) +} + +"@ + } + } + } + + return $Path +} diff --git a/data/templates/agent/scripts/Failover-Cluster.ps1 b/data/templates/agent/scripts/Failover-Cluster.ps1 new file mode 100644 index 0000000..e444ac2 --- /dev/null +++ b/data/templates/agent/scripts/Failover-Cluster.ps1 @@ -0,0 +1,239 @@ +<# +.DESCRIPTION + +## Failover Cluster Input Data (from the UI) + +* Domain Membership + - [String] / [Select box] $DomainName - Domain name +* Domain User Credentials + - [String] $UserName - Username + - [Password string] $UserPassword - User password +* Shared Folder Information + - [String] $ShareServer - Server which will host the folder + - [String] $ShareName - Share name + - [String] $SharePath - Shared folder internal path +* Failover Cluster Members + - [String] $ClusterName - Cluster name + - [String] $ClusterIP - Static IP address that will be assigned to the cluster + - [String[]] $ClusterNodes - List of node names + + + +## Failover Cluster creation workflow + +* Create AD domain +* Join all the VMs to that domain +* Prepare nodes + - Install Failover Cluster prerequisites on all FC nodes +* Create failover cluster + - Create new cluster + - Add members +* Confugure FC quorum + - Create new folder that will be shared + - Share that folder with appropriate permissions + - Configure quorum mode + + + +## Helpful SmbShare* Functions + +* New-SmbShare +* Grant-SmbShareAccess + +#> + +trap { + &$TrapHandler +} + + + +function Install-FailoverClusterPrerequisites { + #Import-Module FailoverClusters + + #Add-WindowsFeature Failover-Clustering, RSAT-Clustering-PowerShell +} + + + +function New-FailoverClusterSharedFolder { + param ( + [String] $ClusterName, + [String] $DomainName, + [String] $ShareServer, + [String] $SharePath = $($Env:SystemDrive + '\FCShare'), + [String] $ShareName = 'FCShare', + [String] $UserName, + [String] $UserPassword, + $Credential = $null + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + Write-Log "--> New-FailoverClusterSharedFolder" + + Write-Log "Creating shared folder for Failover Cluster ..." + + if ($Credential -eq $null) { + $Credential = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword" + } + + if ((Test-Connection -ComputerName $ShareServer -Count 1 -Quiet) -eq $false) { + throw("Server '$ShareServer' is unreachable via ICMP.") + } + + $Session = New-PSSession -ComputerName $ShareServer -Credential $Credential + + Write-Log "Creating folder on '$ShareServer' ..." + Invoke-Command -Session $Session -ScriptBlock { + param ( + [String] $SharePath, + [String] $ShareName, + [String] $ClusterAccount + ) + + Remove-SmbShare -Name $ShareName -Force -ErrorAction 'SilentlyContinue' + Remove-Item -Path $SharePath -Force -ErrorAction 'SilentlyContinue' + + New-Item -Path $SharePath -ItemType Container -Force + + New-SmbShare -Path $SharePath ` + -Name $ShareName ` + -FullAccess "$ClusterAccount", 'Everyone' ` + -Description "Shared folder for Failover Cluster." + + } -ArgumentList $SharePath, $ShareName, "$DomainName\$ClusterName`$" + + Write-Log "Confguring Failover Cluster to use shared folder as qourum resourse ..." + + $null = Set-ClusterQuorum -NodeAndFileShareMajority "\\$ShareServer\$ShareName" + + Write-Log "<-- New-FailoverClusterSharedFolder" + } +} + + + +function New-FailoverCluster { + param ( + [String] $ClusterName, + [String] $StaticAddress, + [String[]] $ClusterNodes, + [String] $DomainName, + [String] $UserName, + [String] $UserPassword, + $Credential + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + Write-Log "ClusterNodes: $($ClusterNodes -join ', ')" + + if ($Credential -eq $null) { + $Credential = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword" + } + + foreach ($Node in $ClusterNodes) { + Write-LogDebug "Installing Failover Cluster modules on '$Node' ..." + $null = Invoke-Command ` + -ComputerName $Node ` + -Credential $Credential ` + -ScriptBlock { + Add-WindowsFeature Failover-Clustering, RSAT-Clustering-PowerShell + } + } + + Import-Module FailoverClusters + + if ((Get-Cluster $ClusterName -ErrorAction SilentlyContinue) -eq $null) { + Write-Log "Creating new cluster '$ClusterName' ..." +<# + Start-PowerShellProcess -Command @" +Import-Module FailoverClusters +New-Cluster -Name '$ClusterName' -StaticAddress '$StaticAddress' +"@ -Credential $Credential -NoBase64 +#> + New-Cluster -Name "$ClusterName" -StaticAddress "$StaticAddress" + Start-Sleep -Seconds 30 + } + else { + Write-Log "Cluster '$ClusterName' already exists." + } + + foreach ($Node in $ClusterNodes) { + Write-Log "Adding node '$Node' to the cluster '$ClusterName' ..." + if ((Get-ClusterNode $Node -ErrorAction SilentlyContinue) -eq $null) { + Write-Log "Adding node ..." +<# + Start-PowerShellProcess -Command @" +Import-Module FailoverClusters +Add-ClusterNode -Cluster '$ClusterName' -Name '$Node' +"@ -Credential $Credential -NoBase64 +#> + Add-ClusterNode -Cluster "$ClusterName" -Name "$Node" + } + else { + Write-Log "Node '$Node' already a part of the cluster '$ClusterName'." + } + } + } +} + + + +<# + +# Example + +$DomainName = 'fc-acme.local' +$DomainUser = 'Administrator' +$DomainPassword = 'P@ssw0rd' + +$ClusterName = 'fc-test' +$ClusterIP = '10.200.0.60' +$ClusterNodes = @('fc-node-01','fc-node-02','fc-node-03') + +$ShareServer = 'fc-dc-01' +$ShareName = 'FCShare' + +$SharePath = "C:\$ShareName" + + + +Import-Module CoreFunctions -Force + +$Creds = New-Credential ` + -UserName "$DomainName\$DomainUser" ` + -Password "$DomainPassword" + +New-FailoverCluster ` + -ClusterName $ClusterName ` + -StaticAddress $ClusterIP ` + -ClusterNodes $ClusterNodes ` + -Credential $Creds + +New-FailoverClusterSharedFolder ` + -ClusterName $ClusterName ` + -DomainName $DomainName ` + -ShareServer $ShareServer ` + -SharePath "$SharePath" ` + -ShareName "$ShareName" ` + -Credential $Creds + +#> diff --git a/data/templates/agent/scripts/Get-DnsListeningIpAddress.ps1 b/data/templates/agent/scripts/Get-DnsListeningIpAddress.ps1 new file mode 100644 index 0000000..1db0b85 --- /dev/null +++ b/data/templates/agent/scripts/Get-DnsListeningIpAddress.ps1 @@ -0,0 +1,7 @@ + +function Get-DnsListeningIpAddress { + Import-Module DnsServer + + (Get-DNSServer -ComputerName localhost).ServerSetting.ListeningIpAddress | + Where-Object { $_ -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" } +} diff --git a/data/templates/agent/scripts/ImportCoreFunctions.ps1 b/data/templates/agent/scripts/ImportCoreFunctions.ps1 new file mode 100644 index 0000000..33ee499 --- /dev/null +++ b/data/templates/agent/scripts/ImportCoreFunctions.ps1 @@ -0,0 +1,65 @@ +Import-Module CoreFunctions -Force + + +function Show-InvocationInfo { + param ( + $Invocation, + [Switch] $End + ) + + if ($End) { + Write-LogDebug "" + } + else { + Write-LogDebug "" + Write-LogDebug "" + foreach ($Parameter in $Invocation.MyCommand.Parameters) { + foreach ($Key in $Parameter.Keys) { + $Type = $Parameter[$Key].ParameterType.FullName + foreach ($Value in $Invocation.BoundParameters[$Key]) { + Write-LogDebug "[$Type] $Key = '$Value'" + } + } + } + Write-LogDebug "" + } +} + + +$TrapHandler = { + Write-LogError @("", $_) -EntireObject + Write-LogError "" + break +} + + +trap { + &$TrapHandler +} + +$ErrorActionPreference = 'Stop' + + +<# +# Usage example for Show-InvocationInfo + +function MyFunction { + param ( + [String] $Value1, + [String] $Value2, + [Int] $Int1 + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + # Main code here + } +} +#> diff --git a/data/templates/agent/scripts/Install-RolePrimaryDomainController.ps1 b/data/templates/agent/scripts/Install-RolePrimaryDomainController.ps1 new file mode 100644 index 0000000..e8f1e5a --- /dev/null +++ b/data/templates/agent/scripts/Install-RolePrimaryDomainController.ps1 @@ -0,0 +1,43 @@ + +trap { + &$TrapHandler +} + + +Function Install-RolePrimaryDomainController { + param ( + [String] $DomainName, + [String] $SafeModePassword + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + Add-WindowsFeatureWrapper ` + -Name "DNS","AD-Domain-Services","RSAT-DFS-Mgmt-Con" ` + -IncludeManagementTools ` + -NotifyRestart + + Write-Log "Creating first domain controller ..." + + $SMAP = ConvertTo-SecureString -String $SafeModePassword -AsPlainText -Force + + $null = Install-ADDSForest ` + -DomainName $DomainName ` + -SafeModeAdministratorPassword $SMAP ` + -DomainMode Default ` + -ForestMode Default ` + -NoRebootOnCompletion ` + -Force + + Write-Log "Waiting 60 seconds for reboot ..." + Start-Sleep -Seconds 60 + } +} diff --git a/data/templates/agent/scripts/Install-RoleSecondaryDomainController.ps1 b/data/templates/agent/scripts/Install-RoleSecondaryDomainController.ps1 new file mode 100644 index 0000000..47e5980 --- /dev/null +++ b/data/templates/agent/scripts/Install-RoleSecondaryDomainController.ps1 @@ -0,0 +1,69 @@ + +trap { + &$TrapHandler +} + + +Function Install-RoleSecondaryDomainController +{ +<# +.SYNOPSIS +Install additional (secondary) domain controller. + +#> + param + ( + [String] + # Domain name to join to. + $DomainName, + + [String] + # Domain user who is allowed to join computer to domain. + $UserName, + + [String] + # User's password. + $Password, + + [String] + # Domain controller recovery mode password. + $SafeModePassword + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + $Credential = New-Credential -UserName "$DomainName\$UserName" -Password $Password + + # Add required windows features + Add-WindowsFeatureWrapper ` + -Name "DNS","AD-Domain-Services","RSAT-DFS-Mgmt-Con" ` + -IncludeManagementTools ` + -NotifyRestart + + + Write-Log "Adding secondary domain controller ..." + + $SMAP = ConvertTo-SecureString -String $SafeModePassword -AsPlainText -Force + + Install-ADDSDomainController ` + -DomainName $DomainName ` + -SafeModeAdministratorPassword $SMAP ` + -Credential $Credential ` + -NoRebootOnCompletion ` + -Force ` + -ErrorAction Stop | Out-Null + + Write-Log "Waiting for restart ..." + # Stop-Execution -ExitCode 3010 -ExitString "Computer must be restarted to finish domain controller promotion." + # Write-Log "Restarting computer ..." + # Restart-Computer -Force + } +} diff --git a/data/templates/agent/scripts/Install-SQLServer.ps1 b/data/templates/agent/scripts/Install-SQLServer.ps1 new file mode 100644 index 0000000..61fb566 --- /dev/null +++ b/data/templates/agent/scripts/Install-SQLServer.ps1 @@ -0,0 +1,84 @@ + +trap { + &$TrapHandler +} + + + +Function ConvertTo-Boolean { + param ( + $InputObject, + [Boolean] $Default = $false + ) + try { + [System.Convert]::ToBoolean($InputObject) + } + catch { + $Default + } +} + + + +Function Show-Environment { + foreach ($item in (Get-ChildItem Env:)) { + Write-Log ("'{0}' --> '{1}'" -f $item.Name, $item.Value) + } +} + + + +Function Install-SqlServer { + param ( + [String] $SetupRoot = '', + [String] $SAPassword = '', + [String] $MuranoFileShare = '', + [Switch] $MixedModeAuth = $false, + [Switch] $UpdateEnabled = $false + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + if ($SetupRoot -eq '') { + if ($MuranoFileShare -eq '') { + $MuranoFileShare = [Environment]::GetEnvironmentVariable('MuranoFileShare') + if ($MuranoFileShare -eq '') { + throw("Unable to find MuranoFileShare path.") + } + } + + $SetupRoot = [IO.Path]::Combine($MuranoFileShare, 'Prerequisites\SQL Server\2012') + } + + #$MixedModeAuthSwitch = ConvertTo-Boolean $MixedModeAuth + + $ExtraOptions = @{} + + if ($MixedModeAuth -eq $true) { + $ExtraOptions += @{'SECURITYMODE' = 'SQL'} + if ($SAPassword -eq '') { + throw("SAPassword must be set when MixedModeAuth is requisted!") + } + } + + if ($SAPassword -ne '') { + $ExtraOptions += @{'SAPWD' = $SAPassword} + } + + if (-not $UpdateEnabled) { + $ExtraOptions += @{'UpdateEnabled' = $false} + } + + Show-Environment + + New-SqlServer -SetupRoot $SetupRoot -ExtraOptions $ExtraOptions + } +} diff --git a/data/templates/agent/scripts/InstallIIS.ps1 b/data/templates/agent/scripts/InstallIIS.ps1 new file mode 100644 index 0000000..57e7dc4 --- /dev/null +++ b/data/templates/agent/scripts/InstallIIS.ps1 @@ -0,0 +1,72 @@ + +trap { + &$TrapHandler +} + + +Function Install-WebServer { + param ( + [String] $PrerequisitesPath + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + Write-Log "--> Install-WebServer" + + $FeatureList = @( + 'Web-Server', + 'Web-Net-Ext45', + 'Web-ASP', + 'Web-Asp-Net45', + 'Web-ISAPI-Ext', + 'Web-ISAPI-Filter', + 'Web-Includes' + ) + + $PrerequisitesList = @( + 'AspNetMvc4Setup.exe', + 'WebApplications.exe' + ) + + $PrerequisitesPath = [IO.Path]::Combine($PrerequisitesPath, 'IIS') + + Write-Log "Validating prerequisites based on the list ..." + foreach ($FileName in $PrerequisitesList) { + $FilePath = [IO.Path]::Combine($PrerequisitesPath, $FileName) + if (-not (Test-Path -Path $FilePath -PathType Leaf)) { + throw("Prerequisite file not found: '$FilePath'") + } + } + + Import-Module ServerManager + + Write-Log "Installing Web Server ..." + Install-WindowsFeature $FeatureList -IncludeManagementTools + + Write-Log "Installing AspNetMvp4 ..." + $Exec = Exec -FilePath $([IO.Path]::Combine($PrerequisitesPath, 'AspNetMvc4Setup.exe')) -ArgumentList '/q' -PassThru + if ($Exec.ExitCode -ne 0) { + throw("Installation of 'AspNetMvc4Setup.exe' failed. Process exit code '$($Exec.ExitCode)'") + } + + # Extract WebApplications folder with *.target files to + # C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0 + Write-Log "Installing WebApplication targets ..." + $WebApplicationsTargetsRoot = 'C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0' + $null = New-Item -Path $WebApplicationsTargetsRoot -ItemType Container + $Exec = Exec -FilePath $([IO.Path]::Combine($PrerequisitesPath, 'WebApplications.exe')) -ArgumentList @("-o`"$WebApplicationsTargetsRoot`"", '-y') -PassThru + if ($Exec.ExitCode -ne 0) { + throw("Installation of 'WebApplications.exe' failed. Process exit code '$($Exec.ExitCode)'") + } + + Write-Log "<-- Install-WebServer" + } +} diff --git a/data/templates/agent/scripts/Join-Domain.ps1 b/data/templates/agent/scripts/Join-Domain.ps1 new file mode 100644 index 0000000..025555d --- /dev/null +++ b/data/templates/agent/scripts/Join-Domain.ps1 @@ -0,0 +1,65 @@ + +trap { + &$TrapHandler +} + + +Function Join-Domain { +<# +.SYNOPSIS +Executes "Join domain" action. + +Requires 'CoreFunctions' module. +#> + param ( + [String] $DomainName = '', + [String] $UserName = '', + [String] $Password = '', + [String] $OUPath = '', + [Switch] $AllowRestart + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + if ($UserName -eq '') { + $UserName = 'Administrator' + } + + $Credential = New-Credential -UserName "$DomainName\$UserName" -Password $Password + + + if (Test-ComputerName -DomainName $DomainName -ErrorAction 'SilentlyContinue') { + Write-LogWarning "Computer already joined to domain '$DomainName'" + } + else { + Write-Log "Joining computer to domain '$DomainName' ..." + + if ($OUPath -eq '') { + Add-Computer -DomainName $DomainName -Credential $Credential -Force + } + else { + Add-Computer -DomainName $DomainName -Credential $Credential -OUPath $OUPath -Force + } + + Write-Log "Waiting 30 seconds to restart ..." + Start-Sleep -Seconds 30 + <# + if ($AllowRestart) { + Write-Log "Restarting computer ..." + Restart-Computer -Force + } + else { + Write-Log "Please restart the computer now." + } + #> + } + } +} diff --git a/data/templates/agent/scripts/New-SqlServerSystemAccount.ps1 b/data/templates/agent/scripts/New-SqlServerSystemAccount.ps1 new file mode 100644 index 0000000..a3b306b --- /dev/null +++ b/data/templates/agent/scripts/New-SqlServerSystemAccount.ps1 @@ -0,0 +1,64 @@ + +trap { + &$TrapHandler +} + + + +function New-SqlServerSystemAccount { + param ( + # (REQUIRED) Domain Name + [Parameter(Mandatory=$true)] + [String] $DomainName, + + # (REQUIRED) User name who has permissions to create and modify userPassword + # Usually this is the domain administrator '$domainName\Administrator' account + [Parameter(Mandatory=$true)] + [String] $UserName, + + # (REQUIRED) Password for that user + [Parameter(Mandatory=$true)] + [String] $UserPassword, + + # (REQUIRED) User name for a new account that will be used to run SQL Server + [Parameter(Mandatory=$true)] + [String] $SQLServiceUserName, + + # (REQUIRED) Password for that user + [Parameter(Mandatory=$true)] + [String] $SQLServiceUserPassword, + + [String] $PrimaryNode = ' ' + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + if ($PrimaryNode.ToLower() -ne ($Env:ComputerName).ToLower()) { + Write-Log "THis function runs on AOAG primary node only." + Write-Log "Exiting." + return + } + + Write-Log "Installing 'RSAT-AD-PowerShell' ... " + Add-WindowsFeature RSAT-AD-PowerShell + + Import-Module ActiveDirectory + + $Creds = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword" + + Write-Log "Adding new user ..." + $null = New-ADUser ` + -Name $SQLServiceUserName ` + -AccountPassword $(ConvertTo-SecureString -String $SQLServiceUserPassword -AsPlainText -Force) ` + -Credential $Creds ` + -ErrorAction 'Stop' + } +} diff --git a/data/templates/agent/scripts/OptionParser.ps1 b/data/templates/agent/scripts/OptionParser.ps1 new file mode 100644 index 0000000..664c4af --- /dev/null +++ b/data/templates/agent/scripts/OptionParser.ps1 @@ -0,0 +1,280 @@ +function New-Option ([string]$Name, [switch]$Switch, [switch]$Boolean, [switch]$String, [switch]$List, $Constraints=$null) { + <# + .SYNOPSIS + Creates Option object + + .DESCRIPTION + Option object is a virtual object represtnting typed command line option. These objects encapsulate escaping and + validation matters. + + One and only one of the switches 'Switch', 'Boolean', 'String' or 'List' should be provided. + + .PARAMETER Name + Option name as it appears in the command line. + + .PARAMETER Switch + Use this switch to create valueless option (a switch). + + .PARAMETER Boolean + Use this switch to create boolean option. Its value is always converted to "1" or "0" + + .PARAMETER String + Use this switch to create string option. Its value will be properly quoted if necessary. + + .PARAMETER List + Use this switch to create option with list value. Values will be put into command line using valid value delemiter (a comma) + + .PARAMETER Constraints + When this parameter is specified, option values are limited to options from that list. + + #> + + $Option = New-Object -TypeName PSObject + + # Fields + $Option | Add-Member NoteProperty Type -value $null + $Option | Add-Member NoteProperty Name -value $null + $Option | Add-Member NoteProperty AllowedValues -value $null + + # Init + + $Option | Add-Member ScriptMethod __init__ { + param([string]$Name, $Switch, $Boolean, $String, $List) + + $this.Name = $Name + + # With respect for our developers we do not check for double type selected + if ($Switch) { + AugmentOptionSwitch($this) + } elseif ($Boolean) { + AugmentOptionBoolean($this) + } elseif ($String) { + AugmentOptionString($this) + } elseif ($List) { + AugmentOptionList($this) + } else { + throw "Switch, Boolean, String or List option type must be provided for option '$Name'" + } + } + + $Option | Add-Member ScriptMethod __post_init__ { + param($Constraints=$null) + if ($Constraints -ne $null) { + $this.AllowedValues = @() + $this.AllowedValues = $this.AllowedValues + $Constraints + } else { + $Constraints = $null + } + } + + # Methods + + $Option | Add-Member -Force ScriptMethod Validate { + if ($this.AllowedValues -ne $null) { + if (-not($this.AllowedValues -contains $this.Value)) { + $Cts = $this.AllowedValues -join ',' + throw "Option '$($this.Name)' may have values ($Cts) but not '$($this.Value)'" + } + } + } + + $Option | Add-Member -Force ScriptMethod ToString { + return "/$($this.Name)" + } + + # invoke constructor + + $Option.__init__($Name, $Switch, $Boolean, $String, $List) + $Option.__post_init__($Constraints) + + return $Option +} + +function AugmentOptionSwitch($Option) { +} + +function AugmentOptionBoolean($Option) { + # Fields + $Option | Add-Member NoteProperty Value -value $false + + # Methods + + $Option | Add-Member -Force ScriptMethod ToString { + if ($this.Value) { + return "/$($this.Name)=1" + } else { + return "/$($this.Name)=0" + } + } +} + +function AugmentOptionString($Option) { + # Fields + $Option | Add-Member NoteProperty Value -value "" + + # Methods + + $Option | Add-Member -Force ScriptMethod ToString { + $v = "$($this.Value)" + if ($v -match '.* .*') { + # TODO: Escape double quote characters if possible + return "/$($this.Name)=`"$v`"" + } else { + return "/$($this.Name)=$v" + } + } +} + +function AugmentOptionList($Option) { + # Fields + $Option | Add-Member NoteProperty Value -value @() + + # Methods + + $Option | Add-Member -Force ScriptMethod Validate { + if ($this.AllowedValues -ne $null) { + foreach ($V in $this.Value) { + if (-not($this.AllowedValues -contains $V)) { + $Cts = $this.AllowedValues -join ',' + throw "Option '$($this.Name)' may have values ($Cts) but not '$V'" + } + } + } + } + + $Option | Add-Member -Force ScriptMethod ToString { + return "/$($this.Name)=$($this.Value -join ',')" + } +} + +function New-OptionParser() { + <# + .SYNOPSIS + Creates OptionParser object. + + .DESCRIPTION + OptionParser object leverages Option objects capabilities and builds valid command line using specified options. + An application may also be invoked with OptionParser. + + #> + + $OptionParser = New-Object -TypeName PSObject + + # Fields + $OptionParser | Add-Member NoteProperty Options -value @{} + $OptionParser | Add-Member NoteProperty Defaults -value @{} + $OptionParser | Add-Member NoteProperty RequiredOptions -value @() + + # Methods + + $OptionParser | Add-Member ScriptMethod AddOption { + <# + .SYNOPSIS + Adds supported option into OptionParser. + + .DESCRIPTION + OptionParser does not allow using unrecognized options. Use this method to fill OptionParser with recognized options + + .PARAMETER Option + Option object + + .PARAMETER Required + Required option switch + + .PARAMETER Default + Option default value + #> + param($Option, [bool]$Required=$false, $Default=$null) + $this.Options.Add($Option.Name, $Option) + if ($Required) { + $this.RequiredOptions = $this.RequiredOptions + $Option.Name + if ($Option | Get-Member "Value") { + if ($Default) { + $this.Defaults.Add($Option.Name, $Default) + } + } else { + $this.Defaults.Add($Option.Name, $null) + } + } + } + + $OptionParser | Add-Member ScriptMethod Parse { + <# + .SYNOPSIS + Parses supplied options and returns command line parameters array. + + .DESCRIPTION + This method verifies that only supported options are provided, all mandatory options are in place, + all option meet constraints if any. Unspecified options with default values are added to command line. + So, mandatory option with default value never causes exception. + + .PARAMETER Options + A hash map of options to parse. Option names should be mapped to corresponding values. + #> + param([hashtable]$Options) + + $CommandLine = @() + foreach ($RequiredOptionName in $this.RequiredOptions) { + if (-not $Options.ContainsKey($RequiredOptionName)) { + $Default = $this.Defaults.Get_Item($RequiredOptionName) + if ($this.Defaults.ContainsKey($RequiredOptionName)) { + $Options.Add($RequiredOptionName, $this.Defaults.Get_Item($RequiredOptionName)) + } else { + throw "Required option '$RequiredOptionName' is missing" + } + } + } + + foreach ($OptionName in $($Options.keys)) { + $Option = $this.Options.Get_Item($OptionName) + if ($Option -eq $null) { + throw "Option '$OptionName' is not allowed" + } + if ($Option | Get-Member "Value") { + $Option.Value = $Options.Get_Item($OptionName) + } + $Option.Validate() + $CommandLine = $CommandLine + $Option.ToString() + } + return $CommandLine + } + + $OptionParser | Add-Member ScriptMethod ExecuteBinary { + param($Binary, [hashtable]$Options = @{}, $CommandLineSuffix = @()) + <# + .SYNOPSIS + Executes binary with a command line constructed from provided options. An arbitrary suffix may be + appended to the command line. + + .DESCRIPTION + This method uses OptionParser.Parse method to construct command line. If there a command line suffix + was supplied, it is appended to the end of command line. Normally command line suffix should contain + leading space character. + + Method waits for executable process to complete and returns its exit code. + + .PARAMETER Binary + Full or relative path to the executable to run. + + .PARAMETER Options + A hash map of options to pass to the executable. + + .PARAMETER CommandLineSuffix + Arbitrary command line suffix. Normally it shoud have leading space character. + #> + + $Binary = Get-Item $Binary + $CommandLine = $this.Parse($Options) + if ($CommandLineSuffix) { + $CommandLine = $CommandLine + $CommandLineSuffix + } + + Write-Log "Executing: $($Binary.FullName) $($CommandLine -join ' ')" + $process = [System.Diagnostics.Process]::Start($Binary, $CommandLine) + $process.WaitForExit() + $process.Refresh() + return $process.ExitCode + } + + return $OptionParser +} diff --git a/data/templates/agent/scripts/SQLServerForAOAG.ps1 b/data/templates/agent/scripts/SQLServerForAOAG.ps1 new file mode 100644 index 0000000..ae40b73 --- /dev/null +++ b/data/templates/agent/scripts/SQLServerForAOAG.ps1 @@ -0,0 +1,538 @@ + +trap { + &$TrapHandler +} + +function Install-SqlServerPowerShellModule { + param ( + [String] $SetupRoot = '' + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + if ((Get-Module SQLPS -ListAvailable) -ne $null) { + Write-Log "Module SQLSP already installed." + return + } + + if ($MuranoFileShare -eq '') { + $MuranoFileShare = [String]([Environment]::GetEnvironmentVariable('MuranoFileShare')) + if ($MuranoFileShare -eq '') { + throw "Unable to find MuranoFileShare path." + } + } + Write-LogDebug "MuranoFileShare = '$MuranoFileShare'" + + if ($SetupRoot -eq '') { + $SetupRoot = [IO.Path]::Combine("$MuranoFileShare", 'Prerequisites\SQL Server\Tools') + } + Write-LogDebug "SetupRoot = '$SetupRoot'" + + $FileList = @( + 'SQLSysClrTypes.msi', + 'SharedManagementObjects.msi', + 'PowerShellTools.msi' + ) + + foreach ($MsiFile in $FileList) { + Write-Log "Trying to install '$MsiFile' ..." + $MsiPath = Join-Path $SetupRoot $MsiFile + if ([IO.File]::Exists($MsiPath)) { + Write-Log "Starting msiexe ..." + $Result = Exec -FilePath "msiexec.exe" -ArgumentList @('/i', "`"$MsiPath`"", '/quiet') -PassThru + if ($Result.ExitCode -ne 0) { + throw "Installation of MSI package '$MsiPath' failed with error code '$($Result.ExitCode)'" + } + } + else { + Write-Log "File '$MsiPath' not found." + } + } + } +} + + + +function Install-SqlServerForAOAG { + param ( + # Path to folder where msi files for additional SQL features are located + [String] $SetupRoot = '', + + # Path to folder where msi files for additional SQLPS module are located + [String] $SqlpsSetupRoot = '', + + [String] $MuranoFileShare = '', + + # (REQUIRED) Domain name + [String] $SQLServiceUserDomain = 'fc-acme.local', + + # (REQUIRED) User name for the account which will be used by SQL service + [String] $SQLServiceUserName = 'Administrator', + + # (REQUIRED) Password for that user + [String] $SQLServiceUserPassword = 'P@ssw0rd', + + [Switch] $UpdateEnabled + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + if ($MuranoFileShare -eq '') { + $MuranoFileShare = [String]([Environment]::GetEnvironmentVariable('MuranoFileShare')) + if ($MuranoFileShare -eq '') { + throw "Unable to find MuranoFileShare path." + } + } + Write-LogDebug "MuranoFileShare = '$MuranoFileShare'" + + if ($SetupRoot -eq '') { + $SetupRoot = [IO.Path]::Combine("$MuranoFileShare", 'Prerequisites\SQL Server\2012') + } + Write-LogDebug "SetupRoot = '$SetupRoot'" + + $ExtraOptions = @{} + + if ($UpdateEnabled) { + $ExtraOptions += @{'UpdateEnabled' = $true} + } + else { + $ExtraOptions += @{'UpdateEnabled' = $false} + } + + $null = New-SQLServerForAOAG ` + -SetupRoot $SetupRoot ` + -SQLSvcUsrDomain $SQLServiceUserDomain ` + -SQLSvcUsrName $SQLServiceUserName ` + -SQLSvcUsrPassword $SQLServiceUserPassword ` + -ExtraOptions $ExtraOptions + } +} + + + +function Initialize-AlwaysOnAvailabilityGroup { + param ( + [String] $DomainName, + [String] $DomainAdminAccountName, + [String] $DomainAdminAccountPassword, + [String] $SqlServiceAccountName, + [String] $PrimaryNode, + [String] $ShareName = 'SharedWorkDir' + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + $ShareNetworkPath = '\\' + $PrimaryNode + '\' + $ShareName + + $DomainAdminAccountCreds = New-Credential ` + -UserName "$DomainName\$DomainAdminAccountName" ` + -Password "$DomainAdminAccountPassword" + + $FunctionsFile = Export-Function 'Get-NextFreePort', 'Initialize-AlwaysOn' + + $null = Start-PowerShellProcess @" +trap { + `$_ + exit 1 +} + +Import-Module CoreFunctions + +Write-Log "Importing functions file '$FunctionsFile' ..." +. "$FunctionsFile" + +Write-Log "Starting 'Initialize-AlwaysOn' ..." +`$XmlFile = [IO.Path]::Combine("$ShareNetworkPath", "`$(`$Env:ComputerName).xml") +Write-Log "Output XML file is '`$XmlFile'" +Initialize-AlwaysOn | Export-CliXml -Path `$XmlFile +"@ -Credential $DomainAdminAccountCreds -NoBase64 + } +} + + +function New-SharedFolderForAOAG { + param ( + # (OPTIONAL) + [String] $SharePath = [IO.Path]::Combine($Env:SystemDrive + '\', 'SharedWorkDir'), + + # (OPTIONAL) + [String] $ShareName = 'SharedWorkDir', + + [String] $PrimaryNode = ' ' + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + if ($PrimaryNode.ToLower() -ne ($Env:ComputerName).ToLower()) { + Write-Log "This script runs on primary node only." + Write-Log "Exiting script." + return + } + + if ($ShareName -eq '') { + $ShareName = [IO.Path]::GetFileNameWithoutExtension($SharePath) + } + + Write-LogDebug "SharePath = '$SharePath'" + Write-LogDebug "ShareName = '$ShareName'" + + try { + Write-LogDebug "Trying to remove share '$ShareName'" + $null = Get-SmbShare -Name $ShareName -ErrorAction 'Stop' + $null = Remove-SmbShare -Name $ShareName -Force + write-Log "Share '$ShareName' removed." + } + catch { + Write-LogWarning "Share '$ShareName' not exists or cannot be deleted." + } + + try { + Write-LogDebug "Trying to remove folder '$SharePath" + $null = Get-Item -Path $SharePath -ErrorAction 'Stop' + $null = Remove-Item -Path $SharePath -Recurse -Force + Write-Log "Folder '$SharePath' removed." + } + catch { + Write-LogWarning "Folder '$SharePath' not exists or cannot be deleted." + } + + $null = New-Item -Path $SharePath -ItemType Container -Force + + $null = New-SmbShare -Path $SharePath ` + -Name $ShareName ` + -FullAccess "Everyone" ` + -Description "Shared folder for AlwaysOn Availability Group setup." + + return '\\' + $Env:ComputerName + '\' + $ShareName + } +} + + + +function New-DatabaseForAOAG { + param ( + [String] $DatabaseName, + [String] $DomainName, + [String] $UserName, + [String] $UserPassword + ) + + $Creds = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword" + + $FunctionsFile = Export-Function 'Invoke-SQLText', 'ConvertTo-SQLName', 'ConvertTo-SQLString', 'New-SQLDatabase' + + Start-PowerShellProcess @" +trap { + `$_ + exit 1 +} + +Import-Module CoreFunctions + +Write-Log "Importing functions from file '$FunctionsFile' ..." +. "$FunctionsFile" + +Write-Log "Starting 'New-SQLDatabase' ..." +New-SQLDatabase $DatabaseName +"@ -Credential $Creds -NoBase64 +} + + + +function Initialize-AOAGPrimaryReplica { + param ( + # (OPTIONAL) Name of the new Availability Group. If not specified then default name will be used. + [String] $GroupName = 'MuranoAG', + + # (REQUIRED) Nodes that will be configured as replica partners. + #[Parameter(Mandatory=$true)] + [String[]] $NodeList, + + # (REQUIRED) Node name that will be primary for selected Availability Group + #[Parameter(Mandatory=$true)] + [String] $PrimaryNode, + + # (REQUIRED) Database list that will be added to the Availability Group + #[Parameter(Mandatory=$true)] + [String[]] $DatabaseList, + + # (REQUIRED) Listener name that will be used by clients to connect to databases in that AG + #[Parameter(Mandatory=$true)] + [String] $ListenerName = 'MuranoAG_Listener', + + # (REQUIRED) IP address of the listener + #[Parameter(Mandatory=$true)] + [String] $ListenerIP, + + [String] $ListenerIPMask = '255.255.255.0', + + [String] $ListenerPort = '5023', + + # Sync Mode Node List + [String[]] $SyncModeNodeList, + + [String] $SharedWorkDir = 'SharedWorkDir', + + [String] $CliXmlFile = '', + + [String] $DomainName, + [String] $UserName, + [String] $UserPassword + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + Write-Log "Primary node: '$($PrimaryNode.ToLower())'" + Write-Log "Current node: '$(($Env:ComputerName).ToLower())'" + + if ($PrimaryNode.ToLower() -ne $($Env:ComputerName).ToLower()) { + Write-Log "This function works on PrimaryNode only." + Write-Log "Exiting." + return + } + + if ($CliXmlFile -eq '') { + $ReplicaDefinitionList = @() + foreach ($Node in $NodeList) { + try { + $NodeEndpointPort = Import-CliXml -Path "\\$PrimaryNode\SharedWorkDir\$Node.xml" + } + catch { + Write-Log "Using default endpoint port 5022" + $NodeEndpointPort = 5022 + } + + $ReplicaDefinition = @{ + "SERVER_INSTANCE" = "$Node"; + "ENDPOINT_URL" = "TCP://${Node}:${NodeEndpointPort}"; + "AVAILABILITY_MODE" = "ASYNCHRONOUS_COMMIT"; + "FAILOVER_MODE"="MANUAL"; + } + + if ($SyncModeNodeList -contains $Node) { + Write-Log "$Node is in SyncModeNodeList" + $ReplicaDefinition['AVAILABILITY_MODE'] = "SYNCHRONOUS_COMMIT" + $ReplicaDefinition['FAILOVER_MODE'] = "AUTOMATIC" + } + else { + Write-Log "$Node is NOT in SyncModeNodeList" + } + + $ReplicaDefinitionList += @($ReplicaDefinition) + } + + $Preferences = @{} + + $ListenerDefinition = @{ + "NAME"=$ListenerName; + "PORT" = "$ListenerPort"; + "STATIC" = "$ListenerIP/$ListenerIPMask" + } + + $Parameters = @{ + 'WorkDir' = "\\$PrimaryNode\$SharedWorkDir"; + 'Name' = $GroupName; + 'DatabaseNames' = $DatabaseList; + 'ReplicaDefs' = $ReplicaDefinitionList; + 'Preferences' = $Preferences; + 'ListenerDef' = $ListenerDefinition; + } + + $null = Remove-Item -Path "\\$PrimaryNode\SharedWorkDir\*" -Force + + $CliXmlFile = [IO.Path]::GetTempFileName() + + Write-LogDebug "CliXml file: '$CliXmlFile'" + + $null = Export-CliXml -Path $CliXmlFile -InputObject $Parameters -Depth 10 + + $null = Initialize-AOAGPrimaryReplica ` + -CliXmlFile $CliXmlFile ` + -DomainName $DomainName ` + -UserName $UserName ` + -UserPassword $UserPassword ` + -PrimaryNode $PrimaryNode + + Write-LogDebug "Inner 'Initialize-AOAGPrimaryReplica' call completed." + } + else { + $Creds = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword" + + $FunctionsFile = Export-Function -All + + $null = Start-PowerShellProcess @" +trap { + `$_ + exit 1 +} + +Import-Module CoreFunctions + +Write-Log "Importing functions from '$FunctionsFile' ..." +. "$FunctionsFile" + +Write-Log "Importing CliXml parameters file ..." +`$Parameters = Import-CliXml -Path $CliXmlFile + +Write-Log "Starting 'New-AlwaysOnAvailabilityGroup' ..." +New-AlwaysOnAvailabilityGroup `` + -WorkDir `$Parameters['WorkDir'] `` + -Name `$Parameters['Name'] `` + -DatabaseNames `$Parameters['DatabaseNames'] `` + -ReplicaDefs `$Parameters['ReplicaDefs'] `` + -Preferences `$Parameters['Preferences'] `` + -ListenerDef `$Parameters['ListenerDef'] +"@ -Credential $Creds -NoBase64 + } + } +} + + + +function Initialize-AOAGSecondaryReplica { + param ( + # (REQUIRED) Nodes that will be configured as replica partners. + [Parameter(Mandatory=$true)] + [String[]] $NodeList, + + # (REQUIRED) Node name that will be primary for selected Availability Group + [Parameter(Mandatory=$true)] + [String] $PrimaryNode, + + [String] $SharedWorkDir = 'SharedWorkDir', + + [String] $DomainName, + [String] $UserName, + [String] $UserPassword + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + if ($PrimaryNode.ToLower() -eq ($Env:ComputerName).ToLower()) { + Write-Log "This function works on any SecondaryNode only." + Write-Log "Exiting." + return + } + + $Creds = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword" + + $FunctionsFile = Export-Function -All + + $null = Start-PowerShellProcess @" +trap { + $_ + exit 1 +} + +Import-Module CoreFunctions + +Write-Log "Importing functions from '$FunctionsFile' ..." +. "$FunctionsFile" + +Write-Log "Starting 'New-AlwaysOnAvailabilityGroupReplica' ..." +New-AlwaysOnAvailabilityGroupReplica -WorkDir "\\$PrimaryNode\$SharedWorkDir" +"@ -Credential $Creds -NoBase64 + } +} + + + +function Disable-Firewall { + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + netsh advfirewall set allprofiles state off + } +} + + + +function Enable-Firewall { + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + netsh advfirewall set allprofiles state on + } +} + + + +function Enable-TrustedHosts { + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' -Force + } +} diff --git a/data/templates/agent/scripts/SQLServerInstaller.ps1 b/data/templates/agent/scripts/SQLServerInstaller.ps1 new file mode 100644 index 0000000..5a4001f --- /dev/null +++ b/data/templates/agent/scripts/SQLServerInstaller.ps1 @@ -0,0 +1,1373 @@ +Import-Module NetSecurity + +function Test-Key([string]$path, [string]$key) { + if(!(Test-Path $path)) { return $false } + if ((Get-ItemProperty $path).$key -eq $null) { return $false } + return $true +} + +function Resolve-SQLServerPrerequisites { + <# + .SYNOPSIS + Installs MS SQL Server prerequisites (.Net Framework 3.5) + + .DESCRIPTION + Installs MS SQL Server prerequisites (.Net Framework 3.5) + + #> + if (-not (Test-Key "HKLM:\Software\Microsoft\NET Framework Setup\NDP\v3.5" "Install")) { + Import-Module ServerManager + Write-Host ".Net Framework 3.5 not found. Installing it using Server Manager..." + $Feature = Get-WindowsFeature NET-Framework + if ($Feature -eq $null) { + # We are probably on Windows Server 2012 + $Feature = Get-WindowsFeature NET-Framework-Core + } + if (-not $Feature) { + throw ".Net framework 3.5 feature was not found." + } + if (-not $Feature.DisplayName -match "3.5") { + Log-Warning ".Net framework 3.5 is required, but $($Feature.DisplayName) is available as Windows feature. Proceeding with installation" + } + [void](Add-WindowsFeature $Feature) + } +} + +function New-SQLServer { + <# + .SYNOPSIS + Installs new MS SQL Server instance. Returns $true if a reboot is required after the installation, + $false if a reboot is not required and throws an exception in case if installation fails. + + .DESCRIPTION + Installs new MS SQL Server instance in unattended mode. + + .PARAMETER SetupRoot + MS SQL Server installation files root directory. Normally it is just DVD drive name. + + .PARAMETER ExtraFeatures + List of features to be installed in addition to default "SQLEngine", "Conn", "SSMS", "ADV_SSMS". + #> + + param( + [parameter(Mandatory = $true)] + [string]$SetupRoot, + [array]$ExtraFeatures = @(), + [Hashtable]$ExtraOptions = @{} + ) + + $SetupDir = Get-Item $SetupRoot + $SetupExe = $SetupDir.GetFiles("setup.exe")[0] + + Resolve-SQLServerPrerequisites + + $parser = New-OptionParserInstall + $ExitCode = $parser.ExecuteBinary($SetupExe.FullName, @{"Q" = $null; "FEATURES" = @("SQLEngine", "Conn", "SSMS", "ADV_SSMS") + $ExtraFeatures} + $ExtraOptions) + + if ($ExitCode -eq 3010) { + return $true + } + + if ($ExitCode -ne 0) { + throw "Installation executable exited with code $("{0:X8}" -f $ExitCode) (Decimal: $ExitCode)" + } + + return $false +} + +function New-SQLServerForAOAG { + <# + .SYNOPSIS + Installs new MS SQL Server instance with all needed features to set up AlwaysOn Availability Group. + Returns $true if a reboot is required after the installation, $false if a reboot is not required + and throws an exception in case if installation fails. + + .DESCRIPTION + Installs new MS SQL Server instance in unattended mode. All features for AlwaysOn Availability Groups are + installed. + + All availability group members must be installed with the same SQLSvcUsrDoman, SQLSvcUsrName and SQLSvcUsrPassword parameters. + User must be a domain user since it will be used for nodes interconnection. + + .PARAMETER SetupRoot + MS SQL Server installation files root directory. Normally it is just DVD drive name. + + .PARAMETER SQLSvcUsrDomain + MS SQL Server user account domain name. + + .PARAMETER SQLSvcUsrName + MS SQL Server user account name. + + .PARAMETER SQLSvcUsrPassword + MS SQL Server user account password. + + .PARAMETER ExtraFeatures + List of features to be removed besides "SQLEngine", "Conn", "SSMS", "ADV_SSMS", "DREPLAY_CTLR", "DREPLAY_CLT". + #> + + param( + [parameter(Mandatory = $true)] + [string]$SetupRoot, + [parameter(Mandatory = $true)] + [string]$SQLSvcUsrDomain, + [parameter(Mandatory = $true)] + [string]$SQLSvcUsrName, + [parameter(Mandatory = $true)] + [string]$SQLSvcUsrPassword, + [array]$ExtraFeatures = @(), + [Hashtable]$ExtraOptions = @{} + ) + + $SetupDir = Get-Item $SetupRoot + $SetupExe = $SetupDir.GetFiles("setup.exe")[0] + + $SQLUser = "$SQLSvcUsrDomain\$SQLSvcUsrName" + $domain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$SQLSvcUsrDomain", $SQLSvcUsrName, $SQLSvcUsrPassword) + + if ($domain.name -eq $null) { + throw "Credentials validation failed for user $SQLUser. Check domain, login name and password." + } + + Resolve-SQLServerPrerequisites + + $parser = New-OptionParserInstall + $ExitCode = $parser.ExecuteBinary($SetupExe.FullName, @{"Q" = $null; "FEATURES" = @("SQLEngine", "Conn", "SSMS", "ADV_SSMS", "DREPLAY_CTLR", "DREPLAY_CLT") + $ExtraFeatures; + "AGTSVCACCOUNT" = $SQLUser; "AGTSVCPASSWORD" = $SQLSvcUsrPassword; "ASSVCACCOUNT" = $SQLUser; "ASSVCPASSWORD" = $SQLSvcUsrPassword; "ASSYSADMINACCOUNTS" = $SQLUSer; + "SQLSVCACCOUNT" = $SQLUser; "SQLSVCPASSWORD" = $SQLSvcUsrPassword; "SQLSYSADMINACCOUNTS" = $SQLUser; "ISSVCACCOUNT" = $SQLUser; "ISSVCPASSWORD" = $SQLSvcUsrPassword; + "RSSVCACCOUNT" = $SQLUser; "RSSVCPASSWORD" = $SQLSvcUsrPassword} + $ExtraOptions) + + if ($ExitCode -eq 3010) { + return $true + } + + if ($ExitCode -ne 0) { + throw "Installation executable exited with code $("{0:X8}" -f $ExitCode) (Decimal: $ExitCode)" + } + + return $false +} + +function Remove-SQLServer { + <# + .SYNOPSIS + Uninstalls MS SQL Server instance installed with New-SQLServer cmdlet + + .DESCRIPTION + Uninstalls MS SQL Server instance installed with New-SQLServer cmdlet in unattended mode + + .PARAMETER SetupRoot + MS SQL Server installation files root directory. Normally it is just DVD drive name. + + .PARAMETER ExtraFeatures + List of features to be removed besides "SQLEngine", "Conn", "SSMS", "ADV_SSMS". + #> + + param( + [parameter(Mandatory = $true)] + [string]$SetupRoot, + [array]$ExtraFeatures = @() + ) + + $SetupDir = Get-Item $SetupRoot + $SetupExe = $SetupDir.GetFiles("setup.exe")[0] + + $parser = New-OptionParserUninstall + $ExitCode = $parser.ExecuteBinary($SetupExe.FullName, @{"Q" = $null; "FEATURES" = @("SQLEngine", "Conn", "SSMS", "ADV_SSMS") + $ExtraFeatures}) + + if ($ExitCode -ne 0) { + throw "Installation executable exited with code $("{0:X8}" -f $ExitCode)" + } +} + +function Install-SQLServerForSysPrep { + <# + .SYNOPSIS + Installs new MS SQL Server in sysprep mode. + + .DESCRIPTION + Installs new MS SQL Server in sysprep mode. Returns $true if a reboot is required after the installation, + $false if a reboot is not required and throws an exception in case if installation fails. + + Setup must be completed after booting rearmed machine by using Complete-SQLServer cmdlet + + .PARAMETER SetupRoot + MS SQL Server installation files root directory. Normally it is just DVD drive name. + + .PARAMETER ExtraFeatures + List of features to be installed in addition to default "SQLEngine". Note that prior to + SQL Server version 2012 Service Pack 1 Cumulative Update 2 (January 2013) only "Replication", + "FullText" and "RS" may be installed in addition to "SQLEngine". See the following link for + detials: http://msdn.microsoft.com/en-us/library/ms144259.aspx + + #> +} + +function Install-SQLServerForSysPrep { + <# + .SYNOPSIS + Installs new MS SQL Server in sysprep mode. + + .DESCRIPTION + Installs new MS SQL Server in sysprep mode. Returns $true if a reboot is required after the installation, + $false if a reboot is not required and throws an exception in case if installation fails. + + Setup must be completed after booting rearmed machine by using Complete-SQLServer cmdlet + + .PARAMETER SetupRoot + MS SQL Server installation files root directory. Normally it is just DVD drive name. + + .PARAMETER ExtraFeatures + List of features to be installed in addition to default "SQLEngine". Note that prior to + SQL Server version 2012 Service Pack 1 Cumulative Update 2 (January 2013) only "Replication", + "FullText" and "RS" may be installed in addition to "SQLEngine". See the following link for + detials: http://msdn.microsoft.com/en-us/library/ms144259.aspx + + #> + + param( + [parameter(Mandatory = $true)] + [string]$SetupRoot, + [array]$ExtraFeatures = @() + ) + + $SetupDir = Get-Item $SetupRoot + $SetupExe = $SetupDir.GetFiles("setup.exe")[0] + + Resolve-SQLServerPrerequisites + + $parser = New-OptionParserPrepareImage + $ExitCode = $parser.ExecuteBinary($SetupExe.FullName, @{"QS" = $null; "FEATURES" = @("SQLEngine") + $ExtraFeatures }) + + if ($ExitCode -eq 3010) { + return $true + } + + if ($ExitCode -ne 0) { + throw "Installation executable exited with code $("{0:X8}" -f $ExitCode) (Decimal: $ExitCode)" + } + + return $false +} + +function Complete-SQLServerAfterSysPrep { + <# + .SYNOPSIS + Completes previously prepared with "Install-SQLServerForSysPrep" MS SQL Server after the system was rearmed. + + .DESCRIPTION + Completes previously prepared with "Install-SQLServerForSysPrep" MS SQL Server after the system was rearmed. + Returns $true if a reboot is required after the installation, $false if a reboot is not required and throws + an exception in case if installation fails. + + Setup must be completed after booting rearmed machine by using Complete-SQLServer cmdlet + + .PARAMETER SetupRoot + MS SQL Server installation files root directory. Normally it is just DVD drive name. + #> + + param( + [parameter(Mandatory = $true)] + [string]$SetupRoot + ) + + $SetupDir = Get-Item $SetupRoot + $SetupExe = $SetupDir.GetFiles("setup.exe")[0] + + $parser = New-OptionParserCompleteImage + $ExitCode = $parser.ExecuteBinary($SetupExe.FullName, @{"QS" = $null}) + + if ($ExitCode -eq 3010) { + return $true + } + + if ($ExitCode -ne 0) { + throw "Installation executable exited with code $("{0:X8}" -f $ExitCode) (Decimal: $ExitCode)" + } + + return $false +} + +function ConvertTo-SQLString { + <# + .SYNOPSIS + Converts argument to a valid SQL string in quotes + + .DESCRIPTION + Converts argument to a valid SQL string in quotes. The string may contain any characters. + See http://msdn.microsoft.com/en-us/library/ms179899.aspx + + .PARAMETER S + String to convert + #> + param( + [parameter(Mandatory = $true, ValueFromPipeline = $true)] + [string]$S + ) + + return "'$($S -replace "'", "''")'" +} + +function ConvertTo-SQLName { + <# + .SYNOPSIS + Converts argument to a valid SQL name in brackets + + .DESCRIPTION + Converts argument to a valid SQL name in brackets. The string may contain any characters. + See http://msdn.microsoft.com/en-us/library/ms175874.aspx + + .PARAMETER S + String to convert + #> + param( + [parameter(Mandatory = $true, ValueFromPipeline = $true)] + [string]$S + ) + return "[$($S -replace "]", "]]")]" +} + +function Invoke-SQLText { + <# + .SYNOPSIS + Invokes SQL text + + .DESCRIPTION + Invokes SQL text. Returns raw SQL server output. + + .PARAMETER SQL + SQL Text + + .PARAMETER User + SQL Server user name + + .PARAMETER Password + SQL Server user password + #> + param( + [parameter(Mandatory = $true)] + [string]$SQL, + [string]$User = $null, + [string]$Password = $null + ) + + #Write-Warning "$SQL`n" + #return + + $Binary = Get-Command "sqlcmd.exe" + + $tempFile = [IO.Path]::GetTempFileName() + $tempFile = Get-Item $tempFile + Set-Content -Path $tempFile -Value $SQL + + $CommandLine = @('-h', '-1', '-b', '-i', "`"$($tempFile.FullName)`"") + if (($User -ne $null) -and ($User -ne '')) { + $CommandLine = $CommandLine + '-U' + $CommandLine = $CommandLine + $User + $CommandLine = $CommandLine + '-P' + $CommandLine = $CommandLine + $Password + } + + Write-Debug "Executing: `n$SQL`n" + [string]$output = &$Binary $CommandLine + + $ExitCode = $LastExitCode + if ($ExitCode -ne 0) { + Write-Warning $output + throw "SQLCMD.EXE returned with exit code $ExitCode while running $Binary $CommandLine" + } + + Remove-Item $tempFile + + return $output +} + +function New-SQLUser { + <# + .SYNOPSIS + Invokes SQL text + + .DESCRIPTION + Invokes SQL text + + .PARAMETER SQL + SQL Text + + .PARAMETER User + SQL Server user name + + .PARAMETER Password + SQL Server user password + #> + param( + [parameter(Mandatory = $true)] + [string]$SQL, + [string]$User = $null, + [string]$Password = $null + ) +} + +function New-Password { + <# + .SYNOPSIS + Creates random password of the specified length + + .DESCRIPTION + Password contains random characters a-z, A-Z, numbers and special characters. + There is no guarantee that all the types of symbols will be present in the password. + + .PARAMETER Length + Desired length of the password. + + #> + param( + [parameter(Mandatory = $true)] + [int]$Length=6 + ) + + $Result = "" + $alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()'`"``_+[]\{}|;:,./<>?~" + while ($Length -gt 0) { + $x = Get-Random $alpha.Length + $c = $alpha[$x] + $Result = "$Result$c" + $Length = $Length - 1 + } + return $Result +} + +function Initialize-MirroringEndpoint { + <# + .SYNOPSIS + Creates mirroring endpoint. + + .DESCRIPTION + Master key is created if necessary. Host certificate is created when necessary either (normally on first endpoint creation). + + Endpoint and certificate are recreated in case if master key did not existed (should not normally happen). + + Endpoint is recreated in case if certificate did not existed (should not happen unless the endpoint was created manually). + + Mirroring endpoint is created unless one already exists. The endpoint is created with the specified name. When the endpoint + already exists is is unchanged. + + Endpoint port is selected automatically as 4022 or as first available port after 4022 in case if 4022 is already listening. + If there is no firewall rule with name 'DatabaseMirroring-TCP-{portnumber}', allowing rule is created. + + Certificate is stored in the specified file. + + Returns endpoint listening port. + + .PARAMETER EncryptionPassword + Encryption password used to create certificate. + + .PARAMETER CertificateFileName + Certificate target file name. File MUST NOT exist. + + #> + + param( + [parameter(Mandatory = $true)] + [String]$EncryptionPassword, + [parameter(Mandatory = $true)] + [String]$CertificateFileName + ) + + $EndpointName = 'MirroringEndpoint' + + $Folder = Get-Item $WorkDir + + $H = $Env:COMPUTERNAME -replace '[^A-Za-z0-9_]', '_' + + $Port = Get-NextFreePort 4022 + + $CreateMasterKey = "USE master; + + IF NOT EXISTS(select * from sys.symmetric_keys where name = '##MS_DatabaseMasterKey##') + BEGIN + CREATE MASTER KEY ENCRYPTION BY PASSWORD = $(ConvertTo-SQLString $EncryptionPassword); + IF EXISTS(select * from sys.certificates where name = '${H}_cert') + BEGIN + DROP CERTIFICATE ${H}_cert + END + IF EXISTS(SELECT * FROM sys.endpoints WHERE type_desc='DATABASE_MIRRORING') + BEGIN + DECLARE `@name VARCHAR(255) + SELECT TOP 1 `@name = name FROM sys.endpoints WHERE type_desc='DATABASE_MIRRORING' + EXEC ('DROP ENDPOINT [' + `@name + ']') + END + END + GO + + IF NOT EXISTS(select * from sys.certificates where name = '${H}_cert') + BEGIN + CREATE CERTIFICATE ${H}_cert WITH SUBJECT = '${H} endpoint certificate'; + IF EXISTS(SELECT * FROM sys.endpoints WHERE type_desc='DATABASE_MIRRORING') + BEGIN + DECLARE `@name VARCHAR(255) + SELECT TOP 1 `@name = name FROM sys.endpoints WHERE type_desc='DATABASE_MIRRORING' + EXEC ('DROP ENDPOINT [' + `@name + ']') + END + END + GO + + BACKUP CERTIFICATE ${H}_cert TO FILE = $(ConvertTo-SQLString "$CertificateFileName"); + GO + + DECLARE `@port int + IF EXISTS(SELECT * FROM sys.endpoints WHERE type_desc='DATABASE_MIRRORING') + BEGIN + SELECT `@port = port FROM sys.tcp_endpoints WHERE type_desc='DATABASE_MIRRORING' + END ELSE + BEGIN + CREATE ENDPOINT $(ConvertTo-SQLName $EndpointName) + STATE = STARTED + AS TCP ( + LISTENER_PORT = $Port + , LISTENER_IP = ALL + ) + FOR DATABASE_MIRRORING ( + AUTHENTICATION = CERTIFICATE ${H}_cert + , ENCRYPTION = REQUIRED ALGORITHM AES + , ROLE = ALL + ); + SELECT `@port = $Port + END + + SELECT 'port:(' + CONVERT(VARCHAR, `@port) + ')' as port + GO + + " + + $rawdata = Invoke-SQLText -SQL $CreateMasterKey + [int]$Port = $rawdata -replace '.*port:\(([^)]*)\).*', '$1' + + # Open port in Windows Firewall + + $PortOpen = $false + $RuleName = "DatabaseMirroring-TCP-$Port" + Get-NetFirewallRule | Foreach-Object { + if ($_.Name -eq $RuleName) { + $PortOpen = $true + } + } + if (-not $PortOpen) { + $DisplayName = "MS SQL Database Mirroring Endpoint at TCP port $Port" + New-NetFirewallRule -Name $RuleName -DisplayName $DisplayName -Description $DisplayName -Protocol TCP -LocalPort $Port -Enabled True -Profile Any -Action Allow + } + + return $Port +} + +function Complete-MirroringEndpoint { + <# + .SYNOPSIS + Completes mirroring endpoint + + .DESCRIPTION + Allows inbound connections from remote host + #> + + param( + [parameter(Mandatory = $true)] + [String]$RemoteHostName, + [parameter(Mandatory = $true)] + [String]$RemoteWorkDir, + [String]$RemoteHostLogin, + [String]$RemoteHostUser, + [String]$RemoteHostPassword + ) + + $Folder = Get-Item $RemoteWorkDir + $RemoteWorkDir = $Folder.FullName + + $H = $RemoteHostName -replace '[^A-Za-z0-9_]', '_' + + if (-not $RemoteHostLogin) { + $RemoteHostLogin = "${H}_login" + } + if (-not $RemoteHostUser) { + $RemoteHostUser = "${H}_user" + } + if (-not $RemoteHostPassword) { + $RemoteHostPassword = "$(New-Password 10)aA#3" + } + + $SQL = "USE master; + + IF NOT EXISTS(select * from sys.sql_logins where name=$(ConvertTo-SQLString $RemoteHostLogin)) + BEGIN + CREATE LOGIN $(ConvertTo-SQLName $RemoteHostLogin) WITH PASSWORD = $(ConvertTo-SQLString $RemoteHostPassword); + END + GO + + IF NOT EXISTS(select * from sys.sysusers where name=$(ConvertTo-SQLString $RemoteHostUser)) + BEGIN + CREATE USER $(ConvertTo-SQLName $RemoteHostUser) FOR LOGIN $(ConvertTo-SQLName $RemoteHostLogin); + END + GO + + IF EXISTS(select * from sys.certificates where name='${H}_remote_cert') + BEGIN + DROP CERTIFICATE ${H}_remote_cert + END + GO + + CREATE CERTIFICATE ${H}_remote_cert AUTHORIZATION $(ConvertTo-SQLName $RemoteHostUser) FROM FILE = $(ConvertTo-SQLString "$RemoteWorkDir\certificate.cer"); + GO + + DECLARE `@name VARCHAR(255) + SELECT TOP 1 `@name = name FROM sys.endpoints WHERE type_desc='DATABASE_MIRRORING' + SELECT 'name:(' + `@name + ')' as name + " + + $rawdata = Invoke-SQLText -SQL $SQL + $EndpointName = $rawdata -replace '.*name:\(([^)]*)\).*', '$1' + $SQL = "GRANT CONNECT ON ENDPOINT::$(ConvertTo-SQLName $EndpointName) TO $(ConvertTo-SQLName $RemoteHostLogin)" + [void](Invoke-SQLText -SQL $SQL) +} + +function Complete-SQLMirror { + <# + .SYNOPSIS + Completes creation of mirrored SQL database + + .DESCRIPTION + This cmdlet should be first executed on mirror server and then on principal server. + Otherwise it will fail (however it may be executed again with no harm). + #> + + param( + [parameter(Mandatory = $true)] + [String]$RemoteHostName, + [parameter(Mandatory = $true)] + [Int]$RemotePort, + [parameter(Mandatory = $true)] + [String]$DatabaseName + ) + + $Url = "TCP://${RemoteHostName}:${RemotePort}" + $AlterDb = "ALTER DATABASE $(ConvertTo-SQLName $DataBaseName) SET PARTNER = $(ConvertTo-SQLString $Url); + GO" + [void](Invoke-SQLText -SQL $AlterDb) +} + +function New-SQLDatabase { + <# + .SYNOPSIS + Creates empty SQL database + + .DESCRIPTION + Creates empty SQL database with default settings. Fails in case is the database already exists. + + .PARAMETER DataBaseName + Database name. + + .PARAMETER mdfFile + Name of the MDF (data) file. If not specified, the following value is used: + "C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\{DataBasePathName}.mdf" + Where {DataBasePathName} is database name with all but A-Z, a-z, 0-9 characters + replaced by underscore. + + .PARAMETER DataBaseName + Name of the LDF (transaction log) file. If not specified, the following value is used: + "C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\{DataBasePathName}_log.mdf" + Where {DataBasePathName} is database name with all but A-Z, a-z, 0-9 characters + replaced by underscore. + #> + + param( + [parameter(Mandatory = $true)] + [String]$DataBaseName, + [String]$mdfFile=$null, + [String]$ldfFile=$null + ) + + $DataBasePathName = $DataBaseName -replace '[^0-9a-zA-Z]', '_' + if (-not $mdfFile) { + $mdfFile = "C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\${DataBasePathName}.mdf" + } + if (-not $ldfFile) { + $ldfFile = "C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\${DataBasePathName}_log.ldf" + } + + $NewDatabase = " + CREATE DATABASE $(ConvertTo-SQLName $DataBaseName) + CONTAINMENT = NONE + ON PRIMARY + ( NAME = N$(ConvertTo-SQLString $DataBaseName), FILENAME = N$(ConvertTo-SQLString $mdfFile) , SIZE = 4096KB , FILEGROWTH = 1024KB ) + LOG ON + ( NAME = N$(ConvertTo-SQLString "${DataBaseName}_log"), FILENAME = N$(ConvertTo-SQLString $ldfFile) , SIZE = 1024KB , FILEGROWTH = 10%) + GO + USE $(ConvertTo-SQLName $DataBaseName) + GO + IF NOT EXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'PRIMARY') ALTER DATABASE $(ConvertTo-SQLName $DataBaseName) MODIFY FILEGROUP [PRIMARY] DEFAULT + GO" + + [void](Invoke-SQLText -SQL $NewDatabase) +} + +function Initialize-SQLMirroringPrincipalStep1 { + <# + .SYNOPSIS + Prepares principal SQL Server for database mirroring (Stage 1) + + .DESCRIPTION + Initializes mirroring endpoint (this is absolutely symmetric step to the mirror init). In addition to that it creates + a database and stores backups of it and its transaction log in the same directory as the endpoint certificate. + + A firewall rule is created for endpoint if necessary. + + .PARAMETER WorkDir + Workind directory. This directory should be tranferred to the mirror server after this + step is executed. + + .PARAMETER DatabaseName + Mirrored database name. This name MUST be use at mirror server either. + + #> + + param( + [parameter(Mandatory = $true)] + [String]$WorkDir, + [parameter(Mandatory = $true)] + [String]$DataBaseName + ) + + [String]$EncryptionPassword = "$(New-Password 10)aA#3" + + if (-not (Test-Path $WorkDir)) { + [void](New-Item -Type Directory $WorkDir) + } + $WorkDir = (Get-Item $WorkDir).FullName + if ((Get-ChildItem -Path $WorkDir).Length -gt 0) { + throw "Working directory $WorkDir is not empty" + } + + $EndpointPort = Initialize-MirroringEndpoint $EncryptionPassword "$WorkDir\certificate.cer" + $EndpointPort | Set-Content "$WorkDir\endpoint-port.txt" + New-SQLDatabase $DataBaseName + + $BackupDb = "BACKUP DATABASE $(ConvertTo-SQLName $DataBaseName) TO DISK = N$(ConvertTo-SQLString "$WorkDir\Source.bak") WITH NOFORMAT, INIT, NAME = N'Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10 + GO" + [void](Invoke-SQLText -SQL $BackupDb) + $BackupLog = "BACKUP LOG $(ConvertTo-SQLName $DataBaseName) TO DISK = N$(ConvertTo-SQLString "$WorkDir\Source_log.bak") WITH NOFORMAT, INIT, NAME = N'Transaction Log Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10 + GO" + [void](Invoke-SQLText -SQL $BackupLog) +} + +function Initialize-SQLMirroringPrincipalStep2 { + <# + .SYNOPSIS + Prepares principal SQL Server for database mirroring (Stage 2) + + .DESCRIPTION + Imports remote server certificate and grants it with access to the mirroring endpoint. + + .PARAMETER RemoteHostName + Remote (mirror) host name. FQDN is preferred, but NetBIOS names and IP addresses are also accepted. + + .PARAMETER RemoteWorkDir + Path to a copy of workdir obtained from mirror machine created on Stage 1. + #> + + param( + [parameter(Mandatory = $true)] + [String]$RemoteHostName, + [parameter(Mandatory = $true)] + [String]$RemoteWorkDir + ) + + if (-not (Test-Path $RemoteWorkDir)) { + throw "Remote work dir '$RemoteWorkDir' was not found" + } + $RemoteWorkDir = (Get-Item $RemoteWorkDir).FullName + + Complete-MirroringEndpoint $RemoteHostName $RemoteWorkDir +} + +function Initialize-SQLMirroringPrincipalStep3 { + <# + .SYNOPSIS + Prepares principal SQL Server for database mirroring (Stage 3) + + .DESCRIPTION + Completes mirror creation. This step must be globally the last one in mirror creation sequence. + + Note that the remote host certificate is valid from the time it is created there. So + this step will fail if there is noticable different in time local and remote machines. + + .PARAMETER RemoteHostName + Remote (principal) host name. FQDN is preferred, but NetBIOS names and IP addresses are also accepted. + + .PARAMETER RemoteWorkDir + Path to a copy of workdir obtained from principal machine created on Stage 1. + + .PARAMETER DatabaseName + Mirrored database name. This name MUST match principal database name and name provided on step 1. + #> + + param( + [parameter(Mandatory = $true)] + [String]$RemoteHostName, + [parameter(Mandatory = $true)] + [String]$RemoteWorkDir, + [parameter(Mandatory = $true)] + [String]$DatabaseName + ) + + [int]$port = Get-Content "${RemoteWorkDir}\endpoint-port.txt" + Complete-SQLMirror $RemoteHostName $port $DatabaseName +} + +function Initialize-SQLMirroringMirrorStep1 { + <# + .SYNOPSIS + Prepares mirror SQL Server for database mirroring (Stage1) + + .DESCRIPTION + Initializes mirroring endpoint for mirror server. Stores mirroring endpoint certificate in Workdir. + + .PARAMETER WorkDir + Workind directory. This directory should be tranferred to the principal server after this + step is executed. + + .PARAMETER DatabaseName + Mirrored database name. This name MUST match principal database name. + + #> + + param( + [parameter(Mandatory = $true)] + [String]$WorkDir, + [parameter(Mandatory = $true)] + [String]$DatabaseName + ) + + [String]$EncryptionPassword = "$(New-Password 10)aA#3" + + if (-not (Test-Path $WorkDir)) { + [void](New-Item -Type Directory $WorkDir) + } + $WorkDir = (Get-Item $WorkDir).FullName + + $EndpointPort = Initialize-MirroringEndpoint $EncryptionPassword "$WorkDir\certificate.cer" + $EndpointPort | Set-Content "$WorkDir\endpoint-port.txt" +} + +function Initialize-SQLMirroringMirrorStep2 { + <# + .SYNOPSIS + Prepares mirror SQL Server for database mirroring (Stage 2) + + .DESCRIPTION + Imports remote server certificate and grants it with access to the mirroring endpoint. + Restores database obtained from principal and leaves it in 'Restoring' state. + + .PARAMETER RemoteHostName + Remote (principal) host name. FQDN is preferred, but NetBIOS names and IP addresses are also accepted. + + .PARAMETER RemoteWorkDir + Path to a copy of workdir obtained from principal machine created on Stage 1. + + .PARAMETER DatabaseName + Mirrored database name. This name MUST match principal database name. + + #> + + param( + [parameter(Mandatory = $true)] + [String]$RemoteHostName, + [parameter(Mandatory = $true)] + [String]$RemoteWorkDir, + [parameter(Mandatory = $true)] + [String]$DataBaseName + ) + + if (-not (Test-Path $RemoteWorkDir)) { + throw "Remote work dir '$RemoteWorkDir' was not found" + } + $RemoteWorkDir = (Get-Item $RemoteWorkDir).FullName + + Complete-MirroringEndpoint $RemoteHostName $RemoteWorkDir + + $RestoreDb = "RESTORE DATABASE $(ConvertTo-SQLName $DataBaseName) FROM DISK = N$(ConvertTo-SQLString "$RemoteWorkDir\Source.bak") WITH FILE = 1, NORECOVERY, NOUNLOAD, REPLACE, STATS = 5 + GO" + [void](Invoke-SQLText -SQL $RestoreDb) + $RestoreLog = "RESTORE LOG $(ConvertTo-SQLName $DataBaseName) FROM DISK = N$(ConvertTo-SQLString "$RemoteWorkDir\Source_log.bak") WITH FILE = 1, NORECOVERY, NOUNLOAD, STATS = 10 + GO" + [void](Invoke-SQLText -SQL $RestoreLog) +} + +function Initialize-SQLMirroringMirrorStep3 { + <# + .SYNOPSIS + Prepares mirror SQL Server for database mirroring (Stage 3) + + .DESCRIPTION + Completes mirror creation. This step must be executed strictly before symmetric step on the principal. + + Note that the remote host certificate is valid from the time it is created there. So + this step will fail if there is noticable different in time local and remote machines. + + .PARAMETER RemoteHostName + Remote (principal) host name. FQDN is preferred, but NetBIOS names and IP addresses are also accepted. + + .PARAMETER RemoteWorkDir + Path to a copy of workdir obtained from principal machine created on Stage 1. + + .PARAMETER DatabaseName + Mirrored database name. This name MUST match principal database name. + + #> + + param( + [parameter(Mandatory = $true)] + [String]$RemoteHostName, + [parameter(Mandatory = $true)] + [String]$RemoteWorkDir, + [parameter(Mandatory = $true)] + [String]$DatabaseName + ) + + [int]$port = Get-Content "${RemoteWorkDir}\endpoint-port.txt" + Complete-SQLMirror $RemoteHostName $port $DatabaseName +} + +function Get-NextFreePort { + <# + .SYNOPSIS + Returns specified desired port or closest next one unoccupied. + + .PARAMETER Port + Desired port number. + + #> + + param( + [parameter(Mandatory = $true)] + [int]$Port + ) + $OpenPorts = netstat -aon | select-string 'LISTENING' | Foreach-Object { (($_ -replace '^\s*', '' -split '\s+')[1] -split '.*:')[1] } | Sort-Object | Get-Unique + while ($OpenPorts.Contains(${Port})) { + $Port = $Port + 1 + } + return $Port +} + +function Initialize-AlwaysOn { + <# + .SYNOPSIS + Initializes AlwaysOn clustering on local SQL server and creates AlwaysOn endpoint listener. Returns AlwaysOn endpoint port number. + + .DESCRIPTION + Enables AlwaysOn clustering on local SQL server. Creates AlwaysOn TCP endpoint on port 5022 or greater if the one is occupied. + #> + + if (!(Test-Path SQLSERVER:\)) { + Import-Module sqlps + } + $MachineName = (Get-ChildItem SQLSERVER:\SQL)[0].PSChildName + $InstanceName = (Get-ChildItem SQLSERVER:\SQL\$MachineName).PSChildName + $AlwaysOnEnabled = ((Get-Item SQLSERVER:\SQL\$MachineName\$InstanceName) | select IsHadrEnabled).IsHadrEnabled + if (-not $AlwaysOnEnabled) { + Enable-SqlAlwaysOn -Path "SQLSERVER:\SQL\$MachineName\$InstanceName" -Force + } + $Instance = Get-Item SQLSERVER:\SQL\$MachineName\$InstanceName + $endpoint = $Instance.Endpoints["AlwaysOnEndpoint"] + if (-not $endpoint) { + $Port = Get-NextFreePort 5022 + $endpoint = New-SqlHadrEndpoint AlwaysOnEndpoint -Port $Port -Path SQLSERVER:\SQL\$MachineName\$InstanceName + } else { + $Port = $endpoint.Protocol.Tcp.ListenerPort + } + if ($endpoint.EndpointState -ne "Started") { + $endpoint.Start() + } + return $Port +} + +function New-AlwaysOnAvailabilityGroup { + <# + .SYNOPSIS + Creates new AlwaysOn availability group on primary replica. + + .DESCRIPTION + Creates new AlwaysOn availability group on primary replica. + + .PARAMETER WorkDir + Workind directory. This directory should be tranferred to the replica server(s) after this + step is executed. + + .PARAMETER Name + Availability group name. + + .PARAMETER DatabaseNames + Replica database(s) names. + + .PARAMETER ReplicaDefs + Array of replica definition. Each definition is a hash table with replica-specific values. + + Mandatory replica definition values are: + + * [String] SERVER_INSTANCE - Replica server instance name + * [String] ENDPOINT_URL - Replica server endpoint URL. Normally it is TCP://fully.qualified.domain.name:5022 + Port number should be obtained with Initialize-AlwaysOn at the replica server + * [String] AVAILABILITY_MODE - Replica availability mode. Can be "SYNCHRONOUS_COMMIT" or "ASYNCHRONOUS_COMMIT" only. + * [String] FAILOVER_MODE - Replica availability mode. Can be "MANUAL" or "AUTOMATIC" only. + + Optional replica definition values are: + + * [Integer] BACKUP_PRIORITY - Backup priority + * [Integer] SESSION_TIMEOUT - Session timeout + * [String] P_ALLOW_CONNECTIONS - Allowed connection types for "Primary" replica mode. Can be "READ_WRITE" or "ALL" only. + * [Array] P_READ_ONLY_ROUTING_LIST - List of replicas proviring readonly access when this one is primary. + * [String] S_ALLOW_CONNECTIONS - Allowed connection types for "Secondary" replica mode. Can be one of "NO", "READ_ONLY", "ALL". + * [String] S_READ_ONLY_ROUTING_URL - Replica read-only requests listener URL. Normally default server listener at port 1433 is used. + + .PARAMETER Preferences + Hash table of general availability group preferences. All the keys are optional. Supported entry keys are: + + * [String] AUTOMATED_BACKUP_PREFERENCE - Automated backup preference. Can be "PRIMARY", "SECONDARY_ONLY", "SECONDARY" or "NONE". + * [String] FAILURE_CONDITION_LEVEL - Failure condition level. Can be "1", "2", "3", "4" or "5". + * [Integer] HEALTH_CHECK_TIMEOUT - Replica health check timeout. + + .PARAMETER ListenerDef + Hash table containing availability group listener configuration. + + Mandatory listener configuration values are: + + [String] NAME - Listener name. + + Optional listener configuration values are: + + [String] PORT - Listener port number. Integer value may be suffixed by a "+" symol (such as "5022+") which allows the routine to + select next free port with number greater or equal to the specified value. + [String] DHCP - DHCP listener address configuration flag. When any value specified, DHCP is used to configure listener + (this is also the default behavior). Also, a specific interface for DHCP may be specified as IP_ADDRESS/MASK + (like "192.168.1.0/255.255.255.0") as a value of the parameter. + [Array] STATIC - Static IP addresses to listen. IP addresses may be IPv4 addresses in the "IP_ADDRESS/MASK" form or IPv6 + addresses in standard IPv6 notation. + + See http://msdn.microsoft.com/en-us/library/ff878399.aspx page for more details regarding all the supported options. + #> + + param( + [parameter(Mandatory = $true)] + [String]$WorkDir, + [parameter(Mandatory = $true)] + [String]$Name, + [parameter(Mandatory = $true)] + [Array]$DatabaseNames, + [parameter(Mandatory = $true)] + [Array]$ReplicaDefs, + [parameter] + [Hashtable]$Preferences, + [parameter(Mandatory = $true)] + [Hashtable]$ListenerDef + ) + + if (-not (Test-Path $WorkDir)) { + [void](New-Item -Type Directory $WorkDir) + } + $WorkDir = (Get-Item $WorkDir).FullName + if ((Get-ChildItem -Path $WorkDir).Length -gt 0) { + throw "Working directory $WorkDir is not empty" + } + + $QuotedDBNames = ($DatabaseNames | ForEach-Object { ConvertTo-SQLName $_ }) -join ", " + + if ($Preferences -eq $null) { + $Preferences = @() + } + $Prefs = @() + foreach($Pref in $Preferences) { + if ($Pref.Key -eq $null) { + Continue + } + if ($Pref.Key -eq "AUTOMATED_BACKUP_PREFERENCE") { + $Prefs = $Prefs + (Validate-Option $Pref.Key, $Pref.Value, @("PRIMARY", "SECONDARY_ONLY", "SECONDARY", "NONE") | New-ReplicaOption -Name $Pref.Key) + } elseif ($Pref.Key -eq "FAILURE_CONDITION_LEVEL") { + $Prefs = $Prefs + (Validate-Option $Pref.Key, $Pref.Value, @("1", "2", "3", "4", "5") | New-ReplicaOption -Name $Pref.Key) + } elseif ($Pref.Key -eq "HEALTH_CHECK_TIMEOUT") { + $Prefs = $Prefs + (Validate-IntOption $Pref.Key, $Pref.Value | New-ReplicaOption -Name $Pref.Key) + } else { + throw "Unexpected peferences option: '$($Pref.Key)'" + } + } + + $ReplicaDefinitionsArray = @() + for ($i = 0; $i -lt $ReplicaDefs.Length; $i++) { + $RDef = $ReplicaDefs[$i] + if ($RDef.GetType().Name -ne "Hashtable") { + throw "All elements of ReplicaDefs array should be Hashtables" + } + + $ReplicaOpts = @() + + # Mandatory options + $ReplicaName = Validate-DefinedOption "SERVER_INSTANCE" $RDef["SERVER_INSTANCE"] + $ReplicaOpts = $ReplicaOpts + (Validate-DefinedOption "ENDPOINT_URL" $RDef["ENDPOINT_URL"] | ConvertTo-SQLString | New-ReplicaOption -Name "ENDPOINT_URL") + $ReplicaOpts = $ReplicaOpts + (Validate-Option "AVAILABILITY_MODE" $RDef["AVAILABILITY_MODE"] @("SYNCHRONOUS_COMMIT", "ASYNCHRONOUS_COMMIT") | New-ReplicaOption -Name "AVAILABILITY_MODE") + $ReplicaOpts = $ReplicaOpts + (Validate-Option "FAILOVER_MODE" $RDef["FAILOVER_MODE"] @("AUTOMATIC", "MANUAL") | New-ReplicaOption -Name "FAILOVER_MODE") + + # Optional options + if ($RDef["BACKUP_PRIORITY"] -ne $null) { + $ReplicaOpts = $ReplicaOpts + (Validate-IntOption "BACKUP_PRIORITY" $RDef["BACKUP_PRIORITY"] | New-ReplicaOption -Name "BACKUP_PRIORITY") + } + if ($RDef["SESSION_TIMEOUT"] -ne $null) { + $ReplicaOpts = $ReplicaOpts + (Validate-IntOption "SESSION_TIMEOUT" $RDef["SESSION_TIMEOUT"] | New-ReplicaOption -Name "SESSION_TIMEOUT") + } + + $SecondaryRole = @() + if ($RDef["S_ALLOW_CONNECTIONS"] -ne $null) { + $SecondaryRole = $SecondaryRole + (Validate-Option "S_ALLOW_CONNECTIONS" $RDef["S_ALLOW_CONNECTIONS"] @("NO", "READ_ONLY", "ALL") | New-ReplicaOption -Name "ALLOW_CONNECTIONS") + } + if ($RDef["S_READ_ONLY_ROUTING_URL"] -ne $null) { + $SecondaryRole = $SecondaryRole + ($RDef["S_READ_ONLY_ROUTING_URL"] | ConvertTo-SQLString | New-ReplicaOption -Name "ALLOW_CONNECTIONS") + } + if ($SecondaryRole.Length -gt 0) { + $ReplicaOpts = $ReplicaOpts + ("( $($SecondaryRole -join ', ') )" | New-ReplicaOption -Name "SECONDARY_ROLE") + } + + $PrimaryRole = @() + if ($RDef["P_ALLOW_CONNECTIONS"] -ne $null) { + $PrimaryRole = $PrimaryRole + (Validate-Option "P_ALLOW_CONNECTIONS" $RDef["P_ALLOW_CONNECTIONS"] @("READ_WRITE", "ALL") | New-ReplicaOption -Name "ALLOW_CONNECTIONS") + } + if ($RDef["P_READ_ONLY_ROUTING_LIST"] -ne $null) { + $PrimaryRole = $PrimaryRole + ((($RDef["P_READ_ONLY_ROUTING_LIST"] | ForEach-Object { ConvertTo-SQLString $_ }) -join ', ') | New-ReplicaOption -Name "ALLOW_CONNECTIONS") + } + if ($PrimaryRole.Length -gt 0) { + $ReplicaOpts = $ReplicaOpts + ("( $($PrimaryRole -join ', ') )" | New-ReplicaOption -Name "PRIMARY_ROLE") + } + + $ReplicaDefinitionsArray = $ReplicaDefinitionsArray + + # TCP://bravo.murano.local:5022 + "N$(ConvertTo-SQLString $ReplicaName) WITH ($($ReplicaOpts -join ', '))" + } + $ReplicaDefinitions = $ReplicaDefinitionsArray -join ",`r`n "; + + if ($ListenerDef["DHCP"] -ne $null) { + if ($ListenerDef["DHCP"].matches("\d+\.\d+\.\d+\.\d+/\d+\.\d+\.\d+\.\d+")) { + ($IpAddr, $Mask) = $ListenerDef["DHCP"] -split "/" + $ListenerAddr = "DHCP ON ( $IpAddr, $Mask )" + } else { + $ListenerAddr = "DHCP" + } + } else { + [array]$IPAddresses = $ListenerDef["STATIC"] + if (($IPAddresses -eq $null) -or ($IPAddresses.Count -eq 0)) { + $ListenerAddr = "DHCP" + } else { + $ConvertedOpts = @() + foreach ($IpOption in $IPAddresses) { + # IPv4 + if ($IpOption -match "\d+\.\d+\.\d+\.\d+/\d+\.\d+\.\d+\.\d+") { + ($IpAddr, $Mask) = $IpOption -split "/" + $ConvertedOpts = $ConvertedOpts + "( $(ConvertTo-SQLString $IpAddr), $(ConvertTo-SQLString $Mask) )" + continue + } + # IPv6 + if ($IpOption -match "^(((?=(?>.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0,5}|([0-9A-F]{1,4}:){6})(\2([0-9A-F]{1,4}(::?|$)){0,2}|((25[0-5]|(2[0-4]|1\d|[1-9])?\d)(\.|$)){4}|[0-9A-F]{1,4}:[0-9A-F]{1,4})(? + param( + [parameter(Mandatory = $true)] + [String]$WorkDir + ) + if (-not (Test-Path $WorkDir)) { + throw "Work dir '$WorkDir' not found" + } + $WorkDirObj = Get-Item -Path $WorkDir + $WorkDir = $WorkDirObj.FullName + $GroupName = Get-Content $WorkDirObj.GetFiles("avgroup.name").FullName + + $JoinGroup = "ALTER AVAILABILITY GROUP $(ConvertTo-SQLName $GroupName) JOIN + GO" + [void](Invoke-SQLText -SQL $JoinGroup) + + for ($i = 0; ; $i++) { + $File = $WorkDirObj.GetFiles("db$i.name") + if (-not $File) { + break; + } + $DataBaseName = Get-Content $WorkDirObj.GetFiles("db$i.name").FullName + $RestoreDb = "RESTORE DATABASE $(ConvertTo-SQLName $DataBaseName) FROM DISK = N$(ConvertTo-SQLString "$WorkDir\db$i.bak") WITH FILE = 1, NORECOVERY, NOUNLOAD, REPLACE, STATS = 5 + GO" + [void](Invoke-SQLText -SQL $RestoreDb) + $RestoreLog = "RESTORE LOG $(ConvertTo-SQLName $DataBaseName) FROM DISK = N$(ConvertTo-SQLString "$WorkDir\db$i.log.bak") WITH FILE = 1, NORECOVERY, NOUNLOAD, STATS = 10 + GO" + [void](Invoke-SQLText -SQL $RestoreLog) + $AlterDB = "ALTER DATABASE $(ConvertTo-SQLName $DataBaseName) SET HADR AVAILABILITY GROUP = $(ConvertTo-SQLName $GroupName) + GO" + [void](Invoke-SQLText -SQL $AlterDB) + } +} + +function New-ReplicaOption { + param( + [parameter(Mandatory = $true)] + [String]$Name, + [parameter(Mandatory = $true, ValueFromPipeline = $true)] + [String]$Value + ) + return "$Name = $Value" +} + +function Validate-Option { + <# + .SYNOPSIS + Checks that the value is one of allowed values + + .DESCRIPTION + Checks that the value is one of allowed values or throws exception otherwise. Returns provided value. + + .PARAMETER Name + Option name. Used only for error message. + + .PARAMETER Value + Option value. + + .PARAMETER Allowed + List of allowed option valus. + #> + param( + [parameter(Mandatory = $true)] + [String]$Name, + [String]$Value, + [Array]$Allowed + ) + if (($Value -eq $null) -or ($Value -eq "")) { + throw "No value was provided for $Name" + } + foreach ($V in $Allowed) { + if ($V -eq $Value) { + return $Value + } + } + throw "Provided value '$Value' for $Name is not one of $($Allowed -join ', ')" +} + +function Validate-IntOption { + <# + .SYNOPSIS + Checks that the value is integer + + .DESCRIPTION + Checks that the value is integer. Returns provided value. + + .PARAMETER Name + Option name. Used only for error message. + + .PARAMETER Value + Option value. + #> + param( + [parameter(Mandatory = $true)] + [String]$Name, + [parameter] + [String]$Value + ) + if (($Value -eq $null) -or ($Value -eq "")) { + throw "No value was provided for $Name" + } + if (-not ("$Value" -match "^[+-]?\d+$")) { + throw "Provided value '$Value' for $Name is not a number" + } + return $Value +} + +function Validate-DefinedOption { + <# + .SYNOPSIS + Checks that the value is not null + + .DESCRIPTION + Checks that the value is not null. Returns provided value. + + .PARAMETER Name + Option name. Used only for error message. + + .PARAMETER Value + Option value. + #> + param( + [parameter(Mandatory = $true)] + [String]$Name, + [parameter(Mandatory = $false)] + [String]$Value + ) + if (($Value -eq $null) -or ($Value -eq "")) { + throw "No value was provided for $Name" + } + return $Value +} + + + diff --git a/data/templates/agent/scripts/SQLServerOptionParsers.ps1 b/data/templates/agent/scripts/SQLServerOptionParsers.ps1 new file mode 100644 index 0000000..1624853 --- /dev/null +++ b/data/templates/agent/scripts/SQLServerOptionParsers.ps1 @@ -0,0 +1,367 @@ +function New-OptionParserInstall { + <# + .SYNOPSIS + Creates an option parser for MS SQL Server 2012 setup "INSTALL" action. + + .DESCRIPTION + Use this cmdlet to create an option parser for MS SQL Server 2012 setup "INSTALL" action. + All documented option are supported. See the following link for details: + http://msdn.microsoft.com/en-us/library/ms144259.aspx + #> + $OptionParser = New-OptionParser + + $IsPartOfDomain = (Get-WmiObject Win32_ComputerSystem).PartOfDomain + + $OptionParser.AddOption((New-Option "ACTION" -String -Constraints "INSTALL"), $true, "INSTALL") + $OptionParser.AddOption((New-Option "IACCEPTSQLSERVERLICENSETERMS" -Switch), $true) + $OptionParser.AddOption((New-Option "ENU" -Switch)) + #$OptionParser.AddOption((New-Option "UpdateEnabled" -Switch)) + $OptionParser.AddOption((New-Option "UpdateEnabled" -Boolean)) + $OptionParser.AddOption((New-Option "UpdateSource" -String)) + $OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String)) + $OptionParser.AddOption((New-Option "ERRORREPORTING" -Boolean)) + $OptionParser.AddOption((New-Option "FEATURES" -List -Constraints ("SQL","SQLEngine","Replication","FullText","DQ","AS","RS","DQC","IS","MDS","Tools","BC","BOL","BIDS","Conn","SSMS","ADV_SSMS","DREPLAY_CTLR","DREPLAY_CLT","SNAC_SDK","SDK","LocalDB"))) + $OptionParser.AddOption((New-Option "ROLE" -String -Constraints ("SPI_AS_ExistingFarm", "SPI_AS_NewFarm", "AllFeatures_WithDefaults"))) + $OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch)) + $OptionParser.AddOption((New-Option "INSTALLSHAREDDIR" -String)) + $OptionParser.AddOption((New-Option "INSTALLSHAREDWOWDIR" -String)) + $OptionParser.AddOption((New-Option "INSTANCEDIR" -String)) + $OptionParser.AddOption((New-Option "INSTANCEID" -String)) + $OptionParser.AddOption((New-Option "INSTANCENAME" -String), $true, "MSSQLSERVER") + $OptionParser.AddOption((New-Option "PID" -String)) + $OptionParser.AddOption((New-Option "Q" -Switch)) + $OptionParser.AddOption((New-Option "QS" -Switch)) + $OptionParser.AddOption((New-Option "UIMODE" -String -Constraints ("Normal", "AutoAdvance"))) + $OptionParser.AddOption((New-Option "SQMREPORTING" -Boolean)) + $OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch)) + $OptionParser.AddOption((New-Option "AGTSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service") + $OptionParser.AddOption((New-Option "AGTSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "AGTSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled"))) + $OptionParser.AddOption((New-Option "ASBACKUPDIR" -String)) + $OptionParser.AddOption((New-Option "ASCOLLATION" -String)) + $OptionParser.AddOption((New-Option "ASCONFIGDIR" -String)) + $OptionParser.AddOption((New-Option "ASDATADIR" -String)) + $OptionParser.AddOption((New-Option "ASLOGDIR" -String)) + $OptionParser.AddOption((New-Option "ASSERVERMODE" -String -Constraints ("MULTIDIMENSIONAL", "POWERPIVOT", "TABULAR"))) + $OptionParser.AddOption((New-Option "ASSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service") + $OptionParser.AddOption((New-Option "ASSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "ASSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled"))) + + #$OptionParser.AddOption((New-Option "ASSYSADMINACCOUNTS" -String), $true, "$ENV:USERDOMAIN\$ENV:USERNAME") + if ($IsPartOfDomain) { + $OptionParser.AddOption((New-Option "ASSYSADMINACCOUNTS" -String), $true, "$Env:USERDOMAIN\Administrator") + } + else { + $OptionParser.AddOption((New-Option "ASSYSADMINACCOUNTS" -String), $true, "$Env:COMPUTERNAME\Administrator") + } + + $OptionParser.AddOption((New-Option "ASTEMPDIR" -String)) + $OptionParser.AddOption((New-Option "ASPROVIDERMSOLAP" -Boolean)) + $OptionParser.AddOption((New-Option "FARMACCOUNT" -String)) + $OptionParser.AddOption((New-Option "FARMPASSWORD" -String)) + $OptionParser.AddOption((New-Option "PASSPHRASE" -String)) + $OptionParser.AddOption((New-Option "FARMADMINIPORT" -String)) + $OptionParser.AddOption((New-Option "BROWSERSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled"))) + $OptionParser.AddOption((New-Option "ENABLERANU" -Switch)) + $OptionParser.AddOption((New-Option "INSTALLSQLDATADIR" -String)) + $OptionParser.AddOption((New-Option "SAPWD" -String)) + $OptionParser.AddOption((New-Option "SECURITYMODE" -String -Constrainrs ("SQL"))) + $OptionParser.AddOption((New-Option "SQLBACKUPDIR" -String)) + $OptionParser.AddOption((New-Option "SQLCOLLATION" -String)) + $OptionParser.AddOption((New-Option "ADDCURRENTUSERASSQLADMIN" -Switch)) + $OptionParser.AddOption((New-Option "SQLSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service") + $OptionParser.AddOption((New-Option "SQLSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "SQLSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled"))) + + #$OptionParser.AddOption((New-Option "SQLSYSADMINACCOUNTS" -String), $true, "$ENV:USERDOMAIN\$ENV:USERNAME") + if ($IsPartOfDomain) { + $OptionParser.AddOption((New-Option "SQLSYSADMINACCOUNTS" -String), $true, "$ENV:USERDOMAIN\Administrator") + } + else { + $OptionParser.AddOption((New-Option "SQLSYSADMINACCOUNTS" -String), $true, "$ENV:COMPUTERNAME\Administrator") + } + + $OptionParser.AddOption((New-Option "SQLTEMPDBDIR" -String)) + $OptionParser.AddOption((New-Option "SQLTEMPDBLOGDIR" -String)) + $OptionParser.AddOption((New-Option "SQLUSERDBDIR" -String)) + $OptionParser.AddOption((New-Option "SQLUSERDBLOGDIR" -String)) + $OptionParser.AddOption((New-Option "FILESTREAMLEVEL" -String -Constraints ("0", "1", "2", "3"))) + $OptionParser.AddOption((New-Option "FILESTREAMSHARENAME" -String)) + $OptionParser.AddOption((New-Option "FTSVCACCOUNT" -String)) + $OptionParser.AddOption((New-Option "FTSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "ISSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service") + $OptionParser.AddOption((New-Option "ISSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "ISSVCStartupType" -String -Constraints ("Manual", "Automatic", "Disabled"))) + $OptionParser.AddOption((New-Option "NPENABLED" -Boolean)) + $OptionParser.AddOption((New-Option "TCPENABLED" -Boolean)) + $OptionParser.AddOption((New-Option "RSINSTALLMODE" -String -Constraints ("SharePointFilesOnlyMode", "DefaultNativeMode", "FilesOnlyMode"))) + $OptionParser.AddOption((New-Option "RSSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service") + $OptionParser.AddOption((New-Option "RSSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "RSSVCStartupType" -String -Constraints ("Manual", "Automatic", "Disabled"))) + + return $OptionParser +} + +function New-OptionParserPrepareImage { + <# + .SYNOPSIS + Creates an option parser for MS SQL Server 2012 setup "PrepareImage" action. + + .DESCRIPTION + Use this cmdlet to create an option parser for MS SQL Server 2012 setup "PrepareImage" action. + + Note that for installer version of MS SQL Server prior to 2012 SP1 Cumulative Update 2 only the + following features are supported: SQLEngine, Replication, FullText, RS + + All documented option are supported. See the following link for details: + http://msdn.microsoft.com/en-us/library/ms144259.aspx + #> + $OptionParser = New-OptionParser + + $OptionParser.AddOption((New-Option "ACTION" -String -Constraints "PrepareImage"), $true, "PrepareImage") + $OptionParser.AddOption((New-Option "IACCEPTSQLSERVERLICENSETERMS" -Switch), $true) + $OptionParser.AddOption((New-Option "ENU" -Switch)) + $OptionParser.AddOption((New-Option "UpdateEnabled" -Switch)) + $OptionParser.AddOption((New-Option "UpdateSource" -String)) + $OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String)) +# $OptionParser.AddOption((New-Option "FEATURES" -List -Constraints ("SQLEngine","Replication","FullText","RS"))) + $OptionParser.AddOption((New-Option "FEATURES" -List -Constraints ("SQL","SQLEngine","Replication","FullText","DQ","AS","RS","DQC","IS","MDS","Tools","BC","BOL","BIDS","Conn","SSMS","ADV_SSMS","DREPLAY_CTLR","DREPLAY_CLT","SNAC_SDK","SDK","LocalDB"))) + $OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch)) + $OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch)) + $OptionParser.AddOption((New-Option "INSTALLSHAREDDIR" -String)) + $OptionParser.AddOption((New-Option "INSTANCEDIR" -String)) + $OptionParser.AddOption((New-Option "INSTANCEID" -String), $true, "MSSQLSERVER") + $OptionParser.AddOption((New-Option "Q" -Switch)) + $OptionParser.AddOption((New-Option "QS" -Switch)) + + return $OptionParser +} + +function New-OptionParserPrepareImageSP1U2 { + <# + .SYNOPSIS + Creates an option parser for MS SQL Server 2012 setup "PrepareImage" action. + + .DESCRIPTION + Use this cmdlet to create an option parser for MS SQL Server 2012 setup "PrepareImage" action. + + This cmdlet should be used only for MS SQL Server 2012 SP1 Cimilative Update 2 or later. + + Note that for installer version of MS SQL Server prior to 2012 SP1 Cimilative Update 2 only the + following features are supported: SQLEngine, Replication, FullText, RS + + All documented option are supported. See the following link for details: + http://msdn.microsoft.com/en-us/library/ms144259.aspx + #> + $OptionParser = New-OptionParser + + $OptionParser.AddOption((New-Option "ACTION" -String -Constraints "PrepareImage"), $true, "PrepareImage") + $OptionParser.AddOption((New-Option "IACCEPTSQLSERVERLICENSETERMS" -Switch), $true) + $OptionParser.AddOption((New-Option "ENU" -Switch)) + $OptionParser.AddOption((New-Option "UpdateEnabled" -Switch)) + $OptionParser.AddOption((New-Option "UpdateSource" -String)) + $OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String)) + $OptionParser.AddOption((New-Option "FEATURES" -List -Constraints ("SQL","SQLEngine","Replication","FullText","DQ","AS","RS","DQC","IS","MDS","Tools","BC","BOL","BIDS","Conn","SSMS","ADV_SSMS","SNAC_SDK","SDK","LocalDB"))) + $OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch)) + $OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch)) + $OptionParser.AddOption((New-Option "INSTALLSHAREDDIR" -String)) + $OptionParser.AddOption((New-Option "INSTANCEDIR" -String)) + $OptionParser.AddOption((New-Option "INSTANCEID" -String), $true, "MSSQLSERVER") + $OptionParser.AddOption((New-Option "Q" -Switch)) + $OptionParser.AddOption((New-Option "QS" -Switch)) + + return $OptionParser +} + +function New-OptionParserCompleteImage { + <# + .SYNOPSIS + Creates an option parser for MS SQL Server 2012 setup "CompleteImage" action. + + .DESCRIPTION + Use this cmdlet to create an option parser for MS SQL Server 2012 setup "CompleteImage" action. + + Note that INSTANCEID parameter value MUST be the same as specified on "PrepareImage" phase. + + All documented option are supported. See the following link for details: + http://msdn.microsoft.com/en-us/library/ms144259.aspx + #> + $OptionParser = New-OptionParser + + $OptionParser.AddOption((New-Option "ACTION" -String -Constraints "CompleteImage"), $true, "CompleteImage") + $OptionParser.AddOption((New-Option "IACCEPTSQLSERVERLICENSETERMS" -Switch), $true) + $OptionParser.AddOption((New-Option "ENU" -Switch)) + $OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String)) + $OptionParser.AddOption((New-Option "ERRORREPORTING" -Boolean)) + $OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch)) + $OptionParser.AddOption((New-Option "INSTANCEID" -String), $true, "MSSQLSERVER") + $OptionParser.AddOption((New-Option "INSTANCENAME" -String), $true, "MSSQLSERVER") + $OptionParser.AddOption((New-Option "PID" -String)) + $OptionParser.AddOption((New-Option "Q" -Switch)) + $OptionParser.AddOption((New-Option "QS" -Switch)) + $OptionParser.AddOption((New-Option "SQMREPORTING" -Boolean)) + $OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch)) + $OptionParser.AddOption((New-Option "AGTSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service") + $OptionParser.AddOption((New-Option "AGTSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "AGTSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled"))) + $OptionParser.AddOption((New-Option "BROWSERSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled"))) + $OptionParser.AddOption((New-Option "ENABLERANU" -Switch)) + $OptionParser.AddOption((New-Option "INSTALLSQLDATADIR" -String)) + $OptionParser.AddOption((New-Option "SAPWD" -String)) + $OptionParser.AddOption((New-Option "SECURITYMODE" -String -Constrainrs ("SQL"))) + $OptionParser.AddOption((New-Option "SQLBACKUPDIR" -String)) + $OptionParser.AddOption((New-Option "SQLCOLLATION" -String)) + $OptionParser.AddOption((New-Option "SQLSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service") + $OptionParser.AddOption((New-Option "SQLSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "SQLSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled"))) + $OptionParser.AddOption((New-Option "SQLSYSADMINACCOUNTS" -String), $true, "$ENV:USERDOMAIN\$ENV:USERNAME") + $OptionParser.AddOption((New-Option "SQLTEMPDBDIR" -String)) + $OptionParser.AddOption((New-Option "SQLTEMPDBLOGDIR" -String)) + $OptionParser.AddOption((New-Option "SQLUSERDBDIR" -String)) + $OptionParser.AddOption((New-Option "SQLUSERDBLOGDIR" -String)) + $OptionParser.AddOption((New-Option "FILESTREAMLEVEL" -String -Constraints ("0", "1", "2", "3"))) + $OptionParser.AddOption((New-Option "FILESTREAMSHARENAME" -String)) + $OptionParser.AddOption((New-Option "FTSVCACCOUNT" -String)) + $OptionParser.AddOption((New-Option "FTSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "NPENABLED" -Boolean)) + $OptionParser.AddOption((New-Option "TCPENABLED" -Boolean)) + $OptionParser.AddOption((New-Option "RSINSTALLMODE" -String -Constraints ("SharePointFilesOnlyMode", "DefaultNativeMode", "FilesOnlyMode"))) + $OptionParser.AddOption((New-Option "RSSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service") + $OptionParser.AddOption((New-Option "RSSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "RSSVCStartupType" -String -Constraints ("Manual", "Automatic", "Disabled"))) + + return $OptionParser +} + +function New-OptionParserCompleteImageSP1U2 { + <# + .SYNOPSIS + Creates an option parser for MS SQL Server 2012 setup "CompleteImage" action. + + .DESCRIPTION + Use this cmdlet to create an option parser for MS SQL Server 2012 setup "CompleteImage" action. + + This cmdlet should be used only for MS SQL Server 2012 SP1 Cimilative Update 2 or later. + + All documented option are supported. See the following link for details: + http://msdn.microsoft.com/en-us/library/ms144259.aspx + #> + $OptionParser = New-OptionParser + + $OptionParser.AddOption((New-Option "ACTION" -String -Constraints "CompleteImage"), $true, "CompleteImage") + $OptionParser.AddOption((New-Option "IACCEPTSQLSERVERLICENSETERMS" -Switch), $true) + $OptionParser.AddOption((New-Option "ENU" -Switch)) + $OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String)) + $OptionParser.AddOption((New-Option "ERRORREPORTING" -Boolean)) + $OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch)) + $OptionParser.AddOption((New-Option "INSTANCEID" -String)) + $OptionParser.AddOption((New-Option "INSTANCENAME" -String)) + $OptionParser.AddOption((New-Option "PID" -String)) + $OptionParser.AddOption((New-Option "Q" -Switch)) + $OptionParser.AddOption((New-Option "QS" -Switch)) + $OptionParser.AddOption((New-Option "SQMREPORTING" -Boolean)) + $OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch)) + $OptionParser.AddOption((New-Option "AGTSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service") + $OptionParser.AddOption((New-Option "AGTSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "AGTSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled"))) + $OptionParser.AddOption((New-Option "BROWSERSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled"))) + $OptionParser.AddOption((New-Option "ENABLERANU" -Switch)) + $OptionParser.AddOption((New-Option "INSTALLSQLDATADIR" -String)) + $OptionParser.AddOption((New-Option "SAPWD" -String)) + $OptionParser.AddOption((New-Option "SECURITYMODE" -String -Constrainrs ("SQL"))) + $OptionParser.AddOption((New-Option "SQLBACKUPDIR" -String)) + $OptionParser.AddOption((New-Option "SQLCOLLATION" -String)) + $OptionParser.AddOption((New-Option "SQLSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service") + $OptionParser.AddOption((New-Option "SQLSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "SQLSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled"))) + $OptionParser.AddOption((New-Option "SQLSYSADMINACCOUNTS" -String), $true, "$ENV:USERDOMAIN\$ENV:USERNAME") + $OptionParser.AddOption((New-Option "SQLTEMPDBDIR" -String)) + $OptionParser.AddOption((New-Option "SQLTEMPDBLOGDIR" -String)) + $OptionParser.AddOption((New-Option "SQLUSERDBDIR" -String)) + $OptionParser.AddOption((New-Option "SQLUSERDBLOGDIR" -String)) + $OptionParser.AddOption((New-Option "FILESTREAMLEVEL" -String -Constraints ("0", "1", "2", "3"))) + $OptionParser.AddOption((New-Option "FILESTREAMSHARENAME" -String)) + $OptionParser.AddOption((New-Option "FTSVCACCOUNT" -String)) + $OptionParser.AddOption((New-Option "FTSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "NPENABLED" -Boolean)) + $OptionParser.AddOption((New-Option "TCPENABLED" -Boolean)) + $OptionParser.AddOption((New-Option "RSINSTALLMODE" -String -Constraints ("SharePointFilesOnlyMode", "DefaultNativeMode", "FilesOnlyMode"))) + $OptionParser.AddOption((New-Option "RSSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service") + $OptionParser.AddOption((New-Option "RSSVCPASSWORD" -String)) + $OptionParser.AddOption((New-Option "RSSVCStartupType" -String -Constraints ("Manual", "Automatic", "Disabled"))) + + return $OptionParser +} + +function New-OptionParserUpgrade { + # ToDo: Implement + throw "Not yet implemented" +} + +function New-OptionParserEditionUpgrade { + # ToDo: Implement + throw "Not yet implemented" +} + +function New-OptionParserRepair { + # ToDo: Implement + throw "Not yet implemented" +} + +function New-OptionParserRebuilddatabase { + # ToDo: Implement + throw "Not yet implemented" +} + +function New-OptionParserUninstall { + <# + .SYNOPSIS + Creates an option parser for MS SQL Server 2012 setup "INSTALL" action. + + .DESCRIPTION + Use this cmdlet to create an option parser for MS SQL Server 2012 setup "INSTALL" action. + All documented option are supported. See the following link for details: + http://msdn.microsoft.com/en-us/library/ms144259.aspx + #> + $OptionParser = New-OptionParser + + $OptionParser.AddOption((New-Option "ACTION" -String -Constraints "UNINSTALL"), $true, "UNINSTALL") + $OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String)) + $OptionParser.AddOption((New-Option "FEATURES" -List -Constraints ("SQL","SQLEngine","Replication","FullText","DQ","AS","RS","DQC","IS","MDS","Tools","BC","BOL","BIDS","Conn","SSMS","ADV_SSMS","DREPLAY_CTLR","DREPLAY_CLT","SNAC_SDK","SDK","LocalDB")), $true) + $OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch)) + $OptionParser.AddOption((New-Option "INSTANCENAME" -String), $true, "MSSQLSERVER") + $OptionParser.AddOption((New-Option "Q" -Switch)) + $OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch)) + + return $OptionParser +} + +function New-OptionParserInstallFailoverCluster { + # ToDo: Implement + throw "Not yet implemented" +} + +function New-OptionParserPrepareFailoverCluster { + # ToDo: Implement + throw "Not yet implemented" +} + +function New-OptionParserCompleteFailoverCluster { + # ToDo: Implement + throw "Not yet implemented" +} + +function New-OptionParserUpgrade { + # ToDo: Implement + throw "Not yet implemented" +} + +function New-OptionParserAddNode { + # ToDo: Implement + throw "Not yet implemented" +} + +function New-OptionParserRemoveNode { + # ToDo: Implement + throw "Not yet implemented" +} diff --git a/data/templates/agent/scripts/SetLocalUserPassword.ps1 b/data/templates/agent/scripts/SetLocalUserPassword.ps1 new file mode 100644 index 0000000..8708a0f --- /dev/null +++ b/data/templates/agent/scripts/SetLocalUserPassword.ps1 @@ -0,0 +1,37 @@ + +trap { + &$TrapHandler +} + + +Function Set-LocalUserPassword { + param ( + [String] $UserName, + [String] $Password, + [Switch] $Force + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + if ((Get-WmiObject Win32_UserAccount -Filter "LocalAccount = 'True' AND Name='$UserName'") -eq $null) { + throw "Unable to find local user account '$UserName'" + } + + if ($Force) { + Write-Log "Changing password for user '$UserName' to '*****'" # :) + $null = ([ADSI] "WinNT://./$UserName").SetPassword($Password) + } + else { + Write-LogWarning "You are trying to change password for user '$UserName'. To do this please run the command again with -Force parameter." + } + } +} + diff --git a/data/templates/agent/scripts/Start-PowerShellProcess.ps1 b/data/templates/agent/scripts/Start-PowerShellProcess.ps1 new file mode 100644 index 0000000..779908d --- /dev/null +++ b/data/templates/agent/scripts/Start-PowerShellProcess.ps1 @@ -0,0 +1,151 @@ + +trap { + &$TrapHandler +} + + + +function Select-CliXmlBlock { + param ( + [String] $Path, + [String] $OutFile = [IO.Path]::GetTempFileName() + ) + + $TagFound = $false + Get-Content $Path | + ForEach-Object { + if ($_ -eq '#< CLIXML') { + $TagFound = $true + } + if ($TagFound) { + Add-Content -Path $OutFile -Value $_ + } + } + $OutFile +} + + + +function Start-PowerShellProcess { + param ( + [String] $Command, + $Credential = $null, + [Switch] $IgnoreStdErr, + [Switch] $NoBase64 + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + $StdOut = [IO.Path]::GetTempFileName() + $StdErr = [IO.Path]::GetTempFileName() + + $ArgumentList = @('-OutputFormat', 'XML') + + if ($NoBase64) { + $TmpScript = [IO.Path]::GetTempFileName() + Rename-Item -Path "$TmpScript" -NewName "$TmpScript.ps1" -Force + $TmpScript = "$TmpScript.ps1" + + Write-LogDebug $TmpScript + + $Command | Out-File $TmpScript + + $ArgumentList += @('-File', "$TmpScript") + } + else { + $Bytes = [Text.Encoding]::Unicode.GetBytes($Command) + $EncodedCommand = [Convert]::ToBase64String($Bytes) + + Write-LogDebug $EncodedCommand + + $ArgumentList += @('-EncodedCommand', $EncodedCommand) + } + + Write-LogDebug $ArgumentList + + Write-Log "Starting external PowerShell process ..." + + if ($Credential -eq $null) { + $Process = Start-Process -FilePath 'powershell.exe' ` + -ArgumentList @($ArgumentList) ` + -RedirectStandardOutput $StdOut ` + -RedirectStandardError $StdErr ` + -NoNewWindow ` + -Wait ` + -PassThru + } + else { + $Process = Start-Process -FilePath 'powershell.exe' ` + -ArgumentList @($ArgumentList) ` + -RedirectStandardOutput $StdOut ` + -RedirectStandardError $StdErr ` + -Credential $Credential ` + -NoNewWindow ` + -Wait ` + -PassThru + } + + Write-Log "External PowerShell process exited with exit code '$($Process.ExitCode)'." + + #if ($ArgumentList -contains '-File') { + # Remove-Item -Path $TmpScript -Force + #} + + $ErrorActionPreferenceSaved = $ErrorActionPreference + $ErrorActionPreference = 'SilentlyContinue' + + Write-LogDebug "StdOut file is '$StdOut'" + Write-LogDebug "StdErr file is '$StdErr'" + + if ((Get-Item $StdOut).Length -gt 0) { + try { + Write-LogDebug "Loading StdOut from '$StdOut'" + $TmpFile = Select-CliXmlBlock $StdOut + $StdOutObject = Import-Clixml $TmpFile + Write-LogDebug "" + Write-LogDebug ($StdOutObject) + Write-LogDebug "" + $StdOutObject + #Remove-Item -Path $TmpFile -Force + } + catch { + Write-LogDebug "An error occured while loading StdOut from '$TmpFile'" + } + } + + if ((Get-Item $StdErr).Length -gt 0) { + try { + Write-LogDebug "Loading StdErr ..." + $TmpFile = Select-CliXmlBlock $StdErr + $StdErrObject = Import-Clixml $TmpFile + Write-LogDebug "" + Write-LogDebug ($StdErrObject) + Write-LogDebug "" + if (-not $IgnoreStdErr) { + $StdErrObject + } + #Remove-Item -Path $TmpFile -Force + } + catch { + Write-LogDebug "An error occured while loading StdErr from '$TmpFile'" + } + } + + $ErrorActionPreference = $ErrorActionPreferenceSaved + + if ($Process.ExitCode -ne 0) { + throw("External PowerShell process exited with code '$($Process.ExitCode)'") + } + + #Remove-Item $StdOut -Force + #Remove-Item $StdErr -Force + } +} diff --git a/data/templates/agent/scripts/Update-ServiceConfig.ps1 b/data/templates/agent/scripts/Update-ServiceConfig.ps1 new file mode 100644 index 0000000..791713d --- /dev/null +++ b/data/templates/agent/scripts/Update-ServiceConfig.ps1 @@ -0,0 +1,60 @@ + +trap { + &$TrapHandler +} + + + +function Update-ServiceConfig { + param ( + [String] $Name, + [String] $RunAsUser = '', + [String] $DomainName = '.', + [String] $Password = '', + [Switch] $RunAsLocalService + ) + begin { + Show-InvocationInfo $MyInvocation + } + end { + Show-InvocationInfo $MyInvocation -End + } + process { + trap { + &$TrapHandler + } + + $ArgumentList = @('config', "`"$Name`"") + + if ($RunAsLocalService) { + $ArgumentList += @("obj=", "`"NT AUTHORITY\LocalService`"") + } + elseif ($RunAsUser -ne '') { + $ArgumentList += @("obj=", "`"$DomainName\$RunAsUser`"", "password=", "`"$Password`"") + } + + $Process = Exec 'sc.exe' $ArgumentList -PassThru -RedirectStreams + + if ($Process.ExitCode -ne 0) { + throw "Command 'sc.exe' returned exit code '$($Process.ExitCode)'" + } + + $NtRights = "C:\Murano\Tools\ntrights.exe" + + if (-not ([IO.File]::Exists($NtRights))) { + throw "File '$NtRights' not found." + } + + $Process = Exec $NtRights @('-u', "$DomainName\$RunAsUser", '+r', 'SeServiceLogonRight') -RedirectStreams -PassThru + + if ($Process.ExitCode -ne 0) { + throw "Command '$NtRights' returned exit code '$($Process.ExitCode)'" + } + + $Process = Exec $NtRights @('-u', "$DomainName\$RunAsUser", '+r', 'SeBatchLogonRight') -RedirectStreams -PassThru + + if ($Process.ExitCode -ne 0) { + throw "Command '$NtRights' returned exit code '$($Process.ExitCode)'" + } + } +} diff --git a/muranoconductor/commands/windows_agent.py b/muranoconductor/commands/windows_agent.py index f112b8c..870e845 100644 --- a/muranoconductor/commands/windows_agent.py +++ b/muranoconductor/commands/windows_agent.py @@ -1,5 +1,6 @@ import json import uuid +import os from muranoconductor.openstack.common import log as logging from muranocommon.messaging import Message @@ -20,11 +21,14 @@ class WindowsAgentExecutor(CommandBase): def execute(self, template, mappings, unit, service, callback, timeout=None): - with open('data/templates/agent/%s.template' % template) as t_file: + template_path = 'data/templates/agent/%s.template' % template + with open(template_path) as t_file: template_data = t_file.read() + json_template = json.loads(template_data) + json_template = self.encode_scripts(json_template, template_path) template_data = muranoconductor.helpers.transform_json( - json.loads(template_data), mappings) + json_template, mappings) msg_id = str(uuid.uuid4()).lower() queue = ('%s-%s-%s' % (self._stack, service, unit)).lower() @@ -42,6 +46,19 @@ class WindowsAgentExecutor(CommandBase): log.info('Sending RMQ message {0} to {1} with id {2}'.format( template_data, queue, msg_id)) + def encode_scripts(self, json_data, template_path): + scripts_folder = ''.join([os.path.dirname(template_path), "/scripts/"]) + script_files = json_data.get("Scripts", []) + scripts = [] + for script in script_files: + script_path = os.path.join(scripts_folder, script) + log.debug('Loading script "{0}"'.format(script_path)) + with open(script_path) as script_file: + script_data = script_file.read() + scripts.append(script_data.encode('base64')) + json_data["Scripts"] = scripts + return json_data + def has_pending_commands(self): return len(self._pending_list) > 0 diff --git a/tests/conductor/test_windows_agent.py b/tests/conductor/test_windows_agent.py new file mode 100644 index 0000000..73cb9f4 --- /dev/null +++ b/tests/conductor/test_windows_agent.py @@ -0,0 +1,63 @@ +# Copyright (c) 2013 Mirantis Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import mock +import mockfs +import json + +from muranoconductor.commands.windows_agent import WindowsAgentExecutor + + +class TestWindowsAgent(unittest.TestCase): + def setUp(self): + self.mfs = mockfs.replace_builtins() + self.template = { + "Scripts": [ + "Get-DnsListeningIpAddress.ps1", + "Join-Domain.ps1" + ], + "Commands": [ + { + "Name": "Get-DnsListeningIpAddress", + "Arguments": {} + }], + "RebootOnCompletion": 0 + } + + self.mfs.add_entries({ + './data/templates/agent/test.template': + json.dumps(self.template), + './data/templates/agent/scripts/Get-DnsListeningIpAddress.ps1': + 'function GetDNSip(){\ntest\n}\n', + './data/templates/agent/scripts/Join-Domain.ps1': + 'function JoinDomain(){\ntest\n}\n', + }) + self.template_path = './data/templates/agent/test.template' + + def test_script_encode(self): + stack = mock.MagicMock() + rmqclient = mock.MagicMock() + reporter = mock.MagicMock() + rmqclient.declare = mock.Mock() + + executor = WindowsAgentExecutor(stack, rmqclient, reporter) + result = executor.encode_scripts(self.template, self.template_path) + encoded = [ + 'ZnVuY3Rpb24gR2V0RE5TaXAoKXsKdGVzdAp9Cg==\n', + 'ZnVuY3Rpb24gSm9pbkRvbWFpbigpewp0ZXN0Cn0K\n' + ] + self.assertEqual(result['Scripts'], encoded, + 'Encoded script is incorrect')