Skip to content

Instantly share code, notes, and snippets.

@mickert
Last active March 4, 2026 23:19
Show Gist options
  • Select an option

  • Save mickert/c502202ca7dd1a56e14b48e53faa411c to your computer and use it in GitHub Desktop.

Select an option

Save mickert/c502202ca7dd1a56e14b48e53faa411c to your computer and use it in GitHub Desktop.
PowerShell script to install, update, downgrade, or uninstall smartmontools on Windows with GitHub API discovery, silent install, MD5 validation, JSON output, and optional cleanup. (c) 2026 Michel Sijmons - https://mickert.dev - License: Apache 2.0

PowerShell License Status Windows

A robust PowerShell script to install, update, downgrade, or uninstall smartmontools on Windows systems.
Supports GitHub API release discovery, silent installation, MD5 validation, downgrade logic, JSON output, and optional cleanup.

Download URL: https://gists.mickert.dev/c502202ca7dd1a56e14b48e53faa411c#file-zyntriops-smartmontoolsinstaller-ps1 Latest README: https://gists.mickert.dev/c502202ca7dd1a56e14b48e53faa411c#file-readme-md


⚡ Quick Start

Install or update to the latest version

.\ZyntriOps-SmartmontoolsInstaller.ps1 -Verbose

Install a specific version

.\ZyntriOps-SmartmontoolsInstaller.ps1 -TargetVersion 7.4 -Verbose

Downgrade (automatic uninstall → install)

.\ZyntriOps-SmartmontoolsInstaller.ps1 -TargetVersion 7.4 -Verbose

Uninstall smartmontools

.\ZyntriOps-SmartmontoolsInstaller.ps1 -Uninstall -Verbose

JSON output for RMM/CI/CD

.\ZyntriOps-SmartmontoolsInstaller.ps1 -Json

Cleanup temporary files

.\ZyntriOps-SmartmontoolsInstaller.ps1 -Cleanup -Verbose

✨ Features

  • GitHub API asset discovery
    Automatically locates the correct installer for any version (including future 7.5.x, 7.6, etc.).

  • Install / Update / Downgrade / Uninstall
    Full lifecycle support with silent installation.

  • Downgrade detection
    Automatically uninstalls the current version before installing an older one.

  • MD5 integrity validation
    Verifies installer integrity using upstream smartmontools checksums.

  • Mark-of-the-Web removal
    Prevents SmartScreen warnings and execution blocks.

  • JSON output
    Ideal for automation platforms, monitoring systems, and CI/CD pipelines.

  • Service restart support
    Optionally restarts a Windows service after install, downgrade, or uninstall.

  • Cleanup mode
    Removes installer, checksum, and stdout/stderr logs after successful execution.

  • Verbose, timestamped logging
    Logs are written to:

    C:\ProgramData\ZyntriOps\Logs\Installer\SmartmontoolsInstaller.log
    
  • WhatIf / Confirm support
    Fully integrated with PowerShell’s ShouldProcess model.


🧠 How It Works

The script performs the following steps:

  1. Detects any existing smartmontools installation via registry, where.exe, and default paths.
  2. Retrieves release metadata from the GitHub API.
  3. Determines the correct installer asset for the requested version.
  4. Downloads the installer and MD5 checksum.
  5. Validates integrity using MD5.
  6. Removes Mark-of-the-Web from the installer.
  7. Executes a silent installation (/S).
  8. Optionally restarts a service.
  9. Optionally cleans up temporary files.
  10. Outputs structured JSON when requested.

🚀 Usage Examples

Install with verbose logging

.\ZyntriOps-SmartmontoolsInstaller.ps1 -Verbose

Downgrade + JSON + Cleanup

.\ZyntriOps-SmartmontoolsInstaller.ps1 -TargetVersion 7.4 -Json -Cleanup

Uninstall + service restart

.\ZyntriOps-SmartmontoolsInstaller.ps1 -Uninstall -RestartServiceName "DiskMonitor"

WhatIf dry-run

.\ZyntriOps-SmartmontoolsInstaller.ps1 -WhatIf

📊 JSON Output Example

{
  "Status": "Installed",
  "OldVersion": "7.5",
  "NewVersion": "7.4",
  "DesiredVersion": "7.4",
  "LatestVersion": "7.5",
  "Downgrade": true,
  "ServiceRestarted": "",
  "ServiceRestartOK": false,
  "InstallerExitCode": 0,
  "RebootRequired": false,
  "CleanupRequested": true,
  "CleanupOK": true
}

🛠️ Requirements

  • Windows 10/11 or Windows Server 2016+
  • PowerShell 5.1 or PowerShell 7+
  • Administrator privileges
  • Internet access (GitHub API + downloads)

📁 File Locations

File Location
Installer $env:TEMP\smartmontools-setup.exe
MD5 checksum $env:TEMP\smartmontools-setup.exe.md5
Stdout/stderr logs $env:TEMP\smartmontools-stdout.log
Script log C:\ProgramData\ZyntriOps\Logs\Installer\SmartmontoolsInstaller.log

🧪 Test Matrix Summary

Scenario Result
Install latest
Install specific version
Downgrade
Upgrade
Uninstall
Cleanup
JSON output
WhatIf
Verbose logging
GitHub API discovery

📜 License (Apache 2.0)

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.

📝 Notes

  • MD5 is used because smartmontools publishes MD5 checksums only.
  • Downgrade logic is fully automatic and safe.
  • Logging is audit-friendly and suitable for production environments.
  • Cleanup is intentionally skipped on failure to preserve artifacts for debugging.

👋 Hey visitor - Michel here

If any of my tools, gists, or guides helped you out - saved you time or money, solved a headache, or taught you something useful - I’d love it if you:

Explore my work (Gists + GitHub projects) and maybe drop a ⭐ or follow https://gists.mickert.dev/https://github.mickert.dev/

Support my work on Ko-fi https://support.mickert.dev/https://ko-fi.com/michelsprojects

Your support helps me create more tools like this.

Kind regards,
Michel Sijmons
https://mickert.dev

<#PSScriptInfo
.VERSION 1.3.1
.GUID 8f3c9c3c-4b9d-4c1e-9c4a-2f1f0e8b7a11
.AUTHOR Michel Sijmons (ZyntriOps)
.COMPANYNAME ZyntriOps
.COPYRIGHT Copyright (c) 2026 Michel Sijmons - https://mickert.dev
.LICENSEURI http://www.apache.org/licenses/LICENSE-2.0
.PROJECTURI https://zyntriops.com/tools/smartmontools-installer
.ICONURI https://zyntriops.com/tools/smartmontools-installer/icon.png
.TAGS smartmontools;installer;zyntriops;monitoring;storage;automation
.RELEASENOTES
- Added GitHub API asset discovery (future-proof for 7.5.1+, 7.6, etc.)
- Added uninstall /S enforcement
- Improved logging, cleanup, fail-fast behavior, and installer output capture
- Added JSON output for automation systems
- Added downgrade support with automatic uninstall
- Added MOTW removal and MD5 validation
#>
<#
.SYNOPSIS
Installs, updates, downgrades, or uninstalls smartmontools on Windows systems.
.DESCRIPTION
ZyntriOps-SmartmontoolsInstaller.ps1
This script installs, updates, downgrades, or uninstalls smartmontools on Windows systems.
It retrieves release metadata directly from the GitHub API, discovers the correct
installer asset for the requested version, downloads the installer and its MD5
checksum, validates file integrity, removes Mark-of-the-Web (MOTW), and performs
a fully silent installation.
If a specific version is requested via -TargetVersion, the script will install that version.
If the requested version is lower than the installed version, the script will uninstall the
current version before installing the target. If the requested version equals the installed
version, no action is taken unless -Force is specified.
When -Uninstall is specified, the script will only uninstall smartmontools (if installed).
If -RestartServiceName is provided, the specified service will be restarted after install,
downgrade, or uninstall. This is useful for services that probe for smartmontools on startup.
When -Cleanup is used, temporary files (installer, checksum, stdout/stderr logs)
are removed after a successful operation. Cleanup is skipped on failure to
preserve artifacts for debugging and auditing.
Existing installations are detected through registry keys, where.exe, and default installation
paths.
The script supports JSON output for RMM/CI/CD systems and writes operational logs
to ProgramData with timestamped entries.
This script is licensed under the Apache License, Version 2.0.
See the LICENSE section in this script.
DISCLAIMER:
This script is provided "as-is" without any warranties or guarantees.
Use at your own risk. The author assumes no liability for any damages,
data loss, misconfiguration, or operational impact resulting from the
use of this script. Always test in a controlled environment before
deploying to production.
(c) 2026 Michel Sijmons - https://mickert.dev
.PARAMETER TargetVersion
Optional. Installs a specific smartmontools version instead of the latest.
If the target version is lower than the installed version, the script will
uninstall the current version before installing the requested version.
If the target version equals the installed version, no action is taken
unless -Force is specified.
.PARAMETER Uninstall
Uninstalls smartmontools if it is installed. No installation or update
will be performed when this switch is used. If smartmontools is not
installed, the script exits gracefully. If -RestartServiceName is
specified, the service will be restarted after uninstall (or attempted
uninstall).
.PARAMETER RestartServiceName
Optional. Restarts the specified Windows service after installation,
downgrade, or uninstallation completes. This is useful for services
that probe for smartmontools on startup or require a refresh after
changes.
.PARAMETER Force
Forces installation even if the installed version appears up-to-date or
matches the requested TargetVersion.
.PARAMETER Json
Outputs structured JSON for RMM/CI/CD pipelines.
.PARAMETER Cleanup
Removes downloaded temporary files (installer, checksum, and captured
stdout/stderr logs) from $env:TEMP after a successful installation,
update, downgrade, or uninstall. This option is disabled by default
to preserve artifacts for debugging and auditing.
.PARAMETER Verbose
Enables detailed logging output. This script uses Write-Verbose extensively
to provide timestamped operational logs. Use -Verbose to display them.
.PARAMETER WhatIf
Shows what actions would be performed without making any changes. Applies to
installation, downgrade, uninstall, cleanup, and service restart operations.
.PARAMETER Confirm
Prompts for confirmation before executing actions. Applies to installation,
downgrade, uninstall, cleanup, and service restart operations.
.PARAMETER Debug
Enables debug output. Useful for troubleshooting script behavior.
.EXAMPLE
PS> .\ZyntriOps-SmartmontoolsInstaller.ps1 -Verbose
.EXAMPLE
PS> .\ZyntriOps-SmartmontoolsInstaller.ps1 -TargetVersion 7.4
.EXAMPLE
PS> .\ZyntriOps-SmartmontoolsInstaller.ps1 -Uninstall -RestartServiceName "DiskMonitor"
.EXAMPLE
PS> .\ZyntriOps-SmartmontoolsInstaller.ps1 -Json | ConvertFrom-Json
.NOTES
Author : Michel Sijmons (ZyntriOps) - https://mickert.dev
License : Apache License 2.0
Version : 1.3.1
This script must be run with administrative privileges.
Internet access is required to retrieve release metadata and download installers.
Temporary files are stored in $env:TEMP and removed only when -Cleanup is used.
Logs are written to: $env:ProgramData\ZyntriOps\Logs\Installer\SmartmontoolsInstaller.log
.LINK
https://gists.mickert.dev/c502202ca7dd1a56e14b48e53faa411c#file-zyntriops-smartmontoolsinstaller-ps1
#>
# =====================================================================
# NOTICE
# =====================================================================
# This script is part of the ZyntriOps Toolkit.
# Developed by Michel Sijmons.
# Copyright (c) 2026 Michel Sijmons and licensed under the
# Apache License, Version 2.0. See License section below.
#
# For more information, visit: https://zyntriops.com
# =====================================================================
# DISCLAIMER & LICENSE
# =====================================================================
# 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.
#
# DISCLAIMER:
# This script is provided "as-is" without any warranties or guarantees.
# Use at your own risk. The author assumes no liability for any damages,
# data loss, misconfiguration, or operational impact resulting from the
# use of this script. Always test in a controlled environment before
# deploying to production.
# =====================================================================
# COPYRIGHT
# =====================================================================
# Copyright (c) 2026 Michel Sijmons
# All rights reserved.
[CmdletBinding(SupportsShouldProcess = $true)]
param(
[string]$TargetVersion,
[string]$RestartServiceName,
[switch]$Force,
[switch]$Json,
[switch]$Uninstall,
[switch]$Cleanup
)
# =====================================================================
# GLOBALS
# =====================================================================
$script:ModuleName = "ZyntriOps.SmartmontoolsInstaller"
$script:ScriptVersion = "1.3.1"
$script:VerboseLoggingEnabled = $false
$script:LogFile = $null
# Initialize log file
try {
$logRoot = Join-Path $env:ProgramData "ZyntriOps\Logs\Installer"
if (-not (Test-Path $logRoot)) {
New-Item -ItemType Directory -Path $logRoot -Force | Out-Null
}
$script:LogFile = Join-Path $logRoot "SmartmontoolsInstaller.log"
}
catch {
$script:LogFile = $null
}
if ($PSBoundParameters.ContainsKey('Verbose')) {
$script:VerboseLoggingEnabled = $true
}
# =====================================================================
# LOGGING
# =====================================================================
function Write-ZOLog {
param(
[Parameter(Mandatory = $true)][string]$Message,
[ValidateSet("INFO","WARN","ERROR","DEBUG")][string]$Level = "INFO"
)
$timestamp = Get-Date -Format o
$line = "[$timestamp] [$Level] $Message"
if ($script:LogFile) {
try { Add-Content -LiteralPath $script:LogFile -Value $line } catch {}
}
switch ($Level) {
"ERROR" {
Write-Error $line
Write-Verbose $line
}
"DEBUG" {
if ($script:VerboseLoggingEnabled) { Write-Verbose $line }
}
default {
Write-Verbose $line
}
}
}
# =====================================================================
# NETWORK
# =====================================================================
function Invoke-ZOWebRequest {
[CmdletBinding()]
[OutputType([bool])]
param(
[string]$Url,
[string]$OutFile
)
Write-ZOLog "Downloading: $Url" "INFO"
try {
Invoke-WebRequest -Uri $Url -OutFile $OutFile -UseBasicParsing -TimeoutSec 60
return $true
}
catch {
Write-ZOLog "Download failed: $($_.Exception.Message)" "ERROR"
return $false
}
}
# =====================================================================
# DETECTION
# =====================================================================
function Get-ZOSmartmontoolsInstallInfo {
[CmdletBinding()]
[OutputType([PSCustomObject])]
param()
$paths = @(
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools"
)
foreach ($p in $paths) {
if (Test-Path $p) {
$key = Get-ItemProperty $p
return [PSCustomObject]@{
DisplayVersion = $key.DisplayVersion
InstallLocation = $key.InstallLocation
UninstallString = $key.UninstallString
}
}
}
return $null
}
function Get-ZOSmartctlPath {
[CmdletBinding()]
[OutputType([string])]
param()
$info = Get-ZOSmartmontoolsInstallInfo
if ($info -and $info.InstallLocation) {
$candidate = Join-Path $info.InstallLocation "bin\smartctl.exe"
if (Test-Path $candidate) { return $candidate }
}
$where = & where.exe smartctl 2>$null
if ($where -and (Test-Path $where)) { return $where }
$default = "C:\Program Files\smartmontools\bin\smartctl.exe"
if (Test-Path $default) { return $default }
return $null
}
function Get-ZOSmartmontoolsInstalledVersion {
[CmdletBinding()]
[OutputType([string])]
param()
$smartctl = Get-ZOSmartctlPath
if (-not $smartctl) { return $null }
try {
$output = & $smartctl --version 2>$null
if (-not $output) { return $null }
$line = $output | Select-Object -First 1
if ($line -match "smartctl\s+([\d\.]+)") {
return $Matches[1]
}
}
catch {
Write-ZOLog "Failed to query smartctl version: $($_.Exception.Message)" "WARN"
}
return $null
}
# =====================================================================
# UNINSTALL (with /S enforcement)
# =====================================================================
function Uninstall-ZOSmartmontools {
[CmdletBinding(SupportsShouldProcess = $true)]
[OutputType([bool])]
param()
$info = Get-ZOSmartmontoolsInstallInfo
if (-not $info -or -not $info.UninstallString) {
Write-ZOLog "No uninstall information found; skipping uninstall." "WARN"
return $true
}
$uninstallCmd = $info.UninstallString.Trim()
# Ensure /S is present
if ($uninstallCmd -notmatch "/S\b") {
Write-ZOLog "Adding /S to uninstall parameters." "INFO"
$uninstallCmd = "$uninstallCmd /S"
}
Write-ZOLog "Final uninstall command: $uninstallCmd" "DEBUG"
if ($PSCmdlet.ShouldProcess("smartmontools", "Uninstall")) {
try {
$arguments = "/c `"$uninstallCmd`""
$proc = Start-Process -FilePath "cmd.exe" -ArgumentList $arguments -Wait -PassThru
if ($proc.ExitCode -ne 0) {
Write-ZOLog "Uninstall returned exit code $($proc.ExitCode)" "ERROR"
return $false
}
Write-ZOLog "Uninstall completed successfully." "INFO"
return $true
}
catch {
Write-ZOLog "Uninstall failed: $($_.Exception.Message)" "ERROR"
return $false
}
}
return $true
}
# =====================================================================
# GITHUB RELEASE DISCOVERY (future-proof)
# =====================================================================
function Get-ZOSmartmontoolsDownloadUrls {
[CmdletBinding()]
[OutputType([PSCustomObject])]
param(
[Parameter(Mandatory = $true)]
[string]$Version
)
# Convert version to tag format: 7.5.1 → RELEASE_7_5_1
$tag = "RELEASE_" + ($Version -replace "\.", "_")
$api = "https://api.github.com/repos/smartmontools/smartmontools/releases/tags/$tag"
Write-ZOLog "Querying GitHub for release tag $tag" "INFO"
try {
$release = Invoke-RestMethod -Uri $api -Headers @{ "User-Agent" = "ZyntriOps" }
}
catch {
throw "Failed to retrieve release metadata for ${Version}: $($_.Exception.Message)"
}
# Find installer and MD5 assets
$installer = $release.assets | Where-Object { $_.name -match "win32-setup\.exe$" }
$md5 = $release.assets | Where-Object { $_.name -match "win32-setup\.exe\.md5$" }
if (-not $installer) { throw "Could not locate installer asset for version $Version" }
if (-not $md5) { throw "Could not locate MD5 asset for version $Version" }
return [PSCustomObject]@{
Installer = $installer.browser_download_url
Md5 = $md5.browser_download_url
}
}
# =====================================================================
# SERVICE RESTART
# =====================================================================
function Restart-ZOService {
[CmdletBinding(SupportsShouldProcess = $true)]
[OutputType([bool])]
param([string]$Name)
Write-ZOLog "Requested restart of service '$Name'." "INFO"
try {
Get-Service -Name $Name -ErrorAction Stop | Out-Null
}
catch {
Write-ZOLog "Service '$Name' not found: $($_.Exception.Message)" "ERROR"
return $false
}
if ($PSCmdlet.ShouldProcess("Service $Name", "Restart")) {
try {
Restart-Service -Name $Name -Force -ErrorAction Stop
Write-ZOLog "Service '$Name' restarted successfully." "INFO"
return $true
}
catch {
Write-ZOLog "Failed to restart service '$Name': $($_.Exception.Message)" "ERROR"
return $false
}
}
return $false
}
# =====================================================================
# CLEANUP
# =====================================================================
function Remove-ZOTempFile {
[CmdletBinding(SupportsShouldProcess = $true)]
[OutputType([bool])]
param([string]$Path)
if (-not (Test-Path $Path)) {
Write-ZOLog "Temporary file not found: $Path" "WARN"
return $true
}
if ($PSCmdlet.ShouldProcess($Path, "Remove temporary file")) {
try {
Remove-Item -Path $Path -Force -ErrorAction Stop
Write-ZOLog "Removed temporary file: $Path" "INFO"
return $true
}
catch {
Write-ZOLog "Failed to remove temporary file '$Path': $($_.Exception.Message)" "ERROR"
return $false
}
}
return $true
}
# =====================================================================
# MAIN LOGIC — INITIALIZATION
# =====================================================================
Write-ZOLog "Starting $script:ModuleName v$script:ScriptVersion" "INFO"
$installedRaw = Get-ZOSmartmontoolsInstalledVersion
$installedVer = $null
if ($installedRaw) {
try { $installedVer = [version]$installedRaw } catch {}
}
# Determine latest version
try {
$latestApi = "https://api.github.com/repos/smartmontools/smartmontools/releases/latest"
$latestJson = Invoke-RestMethod -Uri $latestApi -Headers @{ "User-Agent" = "ZyntriOps" }
$latestRaw = ($latestJson.tag_name -replace "RELEASE_", "") -replace "_", "."
$latestVer = [version]$latestRaw
}
catch {
Write-ZOLog "GitHub API unavailable, falling back to 7.5" "WARN"
$latestRaw = "7.5"
$latestVer = [version]"7.5"
}
Write-ZOLog "Installed version: $installedRaw" "INFO"
Write-ZOLog "Latest version : $latestRaw" "INFO"
$installerPath = Join-Path $env:TEMP "smartmontools-setup.exe"
$md5Path = Join-Path $env:TEMP "smartmontools-setup.exe.md5"
$stdoutPath = Join-Path $env:TEMP "smartmontools-stdout.log"
$stderrPath = Join-Path $env:TEMP "smartmontools-stderr.log"
$cleanupOK = $false
$serviceRestarted = $false
$rebootRequired = $false
$installerExitCode = 0
# =====================================================================
# UNINSTALL MODE
# =====================================================================
if ($Uninstall) {
Write-ZOLog "Uninstall mode requested." "INFO"
$info = Get-ZOSmartmontoolsInstallInfo
if (-not $info) {
Write-ZOLog "smartmontools is not installed. Nothing to uninstall." "WARN"
if ($RestartServiceName) {
$serviceRestarted = Restart-ZOService -Name $RestartServiceName
if (-not $serviceRestarted) {
if ($Json) {
[PSCustomObject]@{
Status = "NotInstalled"
Action = "Uninstall"
ServiceRestarted = $RestartServiceName
ServiceRestartOK = $serviceRestarted
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 1
}
}
if ($Cleanup) {
$cleanupOK = (
(Remove-ZOTempFile -Path $installerPath) -and
(Remove-ZOTempFile -Path $md5Path) -and
(Remove-ZOTempFile -Path $stdoutPath) -and
(Remove-ZOTempFile -Path $stderrPath)
)
}
if ($Json) {
[PSCustomObject]@{
Status = "NotInstalled"
Action = "Uninstall"
ServiceRestarted = $RestartServiceName
ServiceRestartOK = $serviceRestarted
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 0
}
$uninstallOK = Uninstall-ZOSmartmontools
if (-not $uninstallOK) {
if ($Json) {
[PSCustomObject]@{
Status = "UninstallFailed"
OldVersion = $installedRaw
ServiceRestarted = $RestartServiceName
ServiceRestartOK = $false
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 1
}
if ($RestartServiceName) {
$serviceRestarted = Restart-ZOService -Name $RestartServiceName
if (-not $serviceRestarted) {
if ($Json) {
[PSCustomObject]@{
Status = "Uninstalled"
OldVersion = $installedRaw
ServiceRestarted = $RestartServiceName
ServiceRestartOK = $serviceRestarted
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 1
}
}
if ($Cleanup) {
$cleanupOK = (
(Remove-ZOTempFile -Path $installerPath) -and
(Remove-ZOTempFile -Path $md5Path) -and
(Remove-ZOTempFile -Path $stdoutPath) -and
(Remove-ZOTempFile -Path $stderrPath)
)
}
if ($Json) {
[PSCustomObject]@{
Status = "Uninstalled"
OldVersion = $installedRaw
ServiceRestarted = $RestartServiceName
ServiceRestartOK = $serviceRestarted
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 0
}
# =====================================================================
# INSTALL / UPDATE / DOWNGRADE
# =====================================================================
# Determine desired version
if ($TargetVersion) {
try {
$desiredVer = [version]$TargetVersion
$desiredRaw = $TargetVersion
}
catch {
Write-ZOLog "TargetVersion '$TargetVersion' is not a valid version." "ERROR"
if ($Json) {
[PSCustomObject]@{
Status = "InvalidTargetVersion"
TargetVersion = $TargetVersion
} | ConvertTo-Json -Depth 5
}
exit 1
}
Write-ZOLog "Target version : $desiredRaw" "INFO"
}
else {
$desiredVer = $latestVer
$desiredRaw = $latestRaw
Write-ZOLog "No TargetVersion specified; using latest: $desiredRaw" "INFO"
}
# No action needed
if ($installedVer -and $desiredVer -eq $installedVer -and -not $Force) {
Write-ZOLog "Installed version already matches desired version ($desiredRaw). No action required." "INFO"
if ($Json) {
[PSCustomObject]@{
Status = "UpToDate"
InstalledVersion = $installedRaw
DesiredVersion = $desiredRaw
LatestVersion = $latestRaw
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 0
}
# Downgrade detection
$downgrade = $false
if ($installedVer -and $desiredVer -lt $installedVer) {
$downgrade = $true
Write-ZOLog "Requested version ($desiredRaw) is lower than installed version ($installedRaw). Downgrade will uninstall first." "WARN"
}
# Resolve download URLs via GitHub API
try {
$urls = Get-ZOSmartmontoolsDownloadUrls -Version $desiredRaw
}
catch {
Write-ZOLog "Failed to resolve download URLs for version '$desiredRaw': $($_.Exception.Message)" "ERROR"
if ($Json) {
[PSCustomObject]@{
Status = "UrlResolutionFailed"
DesiredVersion = $desiredRaw
LatestVersion = $latestRaw
} | ConvertTo-Json -Depth 5
}
exit 1
}
# Downgrade uninstall
if ($downgrade) {
$uninstallOK = Uninstall-ZOSmartmontools
if (-not $uninstallOK) {
if ($Json) {
[PSCustomObject]@{
Status = "DowngradeUninstallFailed"
OldVersion = $installedRaw
DesiredVersion = $desiredRaw
LatestVersion = $latestRaw
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 1
}
}
# Download installer
if (-not (Invoke-ZOWebRequest -Url $urls.Installer -OutFile $installerPath)) {
if ($Json) {
[PSCustomObject]@{
Status = "InstallerDownloadFailed"
DesiredVersion = $desiredRaw
LatestVersion = $latestRaw
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 1
}
# Download MD5
if (-not (Invoke-ZOWebRequest -Url $urls.Md5 -OutFile $md5Path)) {
if ($Json) {
[PSCustomObject]@{
Status = "Md5DownloadFailed"
DesiredVersion = $desiredRaw
LatestVersion = $latestRaw
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 1
}
# Remove MOTW
try {
Unblock-File -Path $installerPath
Write-ZOLog "Removed Mark-of-the-Web from installer." "INFO"
}
catch {
Write-ZOLog "Failed to remove MOTW: $($_.Exception.Message)" "WARN"
}
# MD5 validation
try {
$expected = (Get-Content $md5Path).Split(" ")[0].Trim()
$actual = (Get-FileHash -Path $installerPath -Algorithm MD5).Hash.ToLower()
if ($expected -ne $actual) {
Write-ZOLog "MD5 checksum mismatch. Expected: $expected, Actual: $actual. Aborting." "ERROR"
if ($Json) {
[PSCustomObject]@{
Status = "Md5Mismatch"
DesiredVersion = $desiredRaw
LatestVersion = $latestRaw
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 1
}
Write-ZOLog "MD5 checksum validated successfully." "INFO"
}
catch {
Write-ZOLog "MD5 validation failed: $($_.Exception.Message)" "ERROR"
if ($Json) {
[PSCustomObject]@{
Status = "Md5ValidationFailed"
DesiredVersion = $desiredRaw
LatestVersion = $latestRaw
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 1
}
# Run installer
if ($PSCmdlet.ShouldProcess("smartmontools $desiredRaw", "Install/Update")) {
Write-ZOLog "Running silent installer for version $desiredRaw..." "INFO"
try {
$proc = Start-Process -FilePath $installerPath `
-ArgumentList "/S" `
-Wait `
-PassThru `
-RedirectStandardOutput $stdoutPath `
-RedirectStandardError $stderrPath
$installerExitCode = $proc.ExitCode
if (Test-Path $stdoutPath) {
Get-Content $stdoutPath | ForEach-Object { Write-ZOLog $_ "INFO" }
}
if (Test-Path $stderrPath) {
Get-Content $stderrPath | ForEach-Object { Write-ZOLog $_ "ERROR" }
}
if ($installerExitCode -ne 0 -and $installerExitCode -ne 3010) {
Write-ZOLog "Installer returned exit code $installerExitCode" "ERROR"
if ($Json) {
[PSCustomObject]@{
Status = "InstallFailed"
OldVersion = $installedRaw
DesiredVersion = $desiredRaw
LatestVersion = $latestRaw
InstallerExitCode = $installerExitCode
RebootRequired = $false
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit $installerExitCode
}
if ($installerExitCode -eq 3010) {
Write-ZOLog "Installer indicates reboot required (3010)." "WARN"
$rebootRequired = $true
}
Write-ZOLog "Installation completed successfully." "INFO"
}
catch {
Write-ZOLog "Installer execution failed: $($_.Exception.Message)" "ERROR"
if ($Json) {
[PSCustomObject]@{
Status = "InstallerExecutionFailed"
OldVersion = $installedRaw
DesiredVersion = $desiredRaw
LatestVersion = $latestRaw
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 1
}
}
# Query new version
$newRaw = Get-ZOSmartmontoolsInstalledVersion
Write-ZOLog "New installed version: $newRaw" "INFO"
# Restart service if requested
if ($RestartServiceName) {
$serviceRestarted = Restart-ZOService -Name $RestartServiceName
if (-not $serviceRestarted) {
if ($Json) {
[PSCustomObject]@{
Status = "Installed"
OldVersion = $installedRaw
NewVersion = $newRaw
DesiredVersion = $desiredRaw
LatestVersion = $latestRaw
Downgrade = $downgrade
ServiceRestarted = $RestartServiceName
ServiceRestartOK = $serviceRestarted
InstallerExitCode = $installerExitCode
RebootRequired = $rebootRequired
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
exit 1
}
}
# Cleanup
if ($Cleanup) {
$cleanupOK = (
(Remove-ZOTempFile -Path $installerPath) -and
(Remove-ZOTempFile -Path $md5Path) -and
(Remove-ZOTempFile -Path $stdoutPath) -and
(Remove-ZOTempFile -Path $stderrPath)
)
}
# JSON output
if ($Json) {
[PSCustomObject]@{
Status = "Installed"
OldVersion = $installedRaw
NewVersion = $newRaw
DesiredVersion = $desiredRaw
LatestVersion = $latestRaw
Downgrade = $downgrade
ServiceRestarted = $RestartServiceName
ServiceRestartOK = $serviceRestarted
InstallerExitCode = $installerExitCode
RebootRequired = $rebootRequired
CleanupRequested = $Cleanup.IsPresent
CleanupOK = $cleanupOK
} | ConvertTo-Json -Depth 5
}
# Exit code propagation
if ($installerExitCode -ne 0 -and $installerExitCode -ne 3010) {
exit $installerExitCode
}
exit 0
# ZyntriOps Action1 PowerShell Wrapper
# Copyright (c) 2026 Michel Sijmons
# Licensed under Apache License 2.0
# Wrapper generator download: https://gists.mickert.dev/d76e6a710a6cafb5b631049f6aa917e4
#
# wrapped original script: ZyntriOps-SmartmontoolsInstaller1.3.1.ps1
# Read Action1-injected variables
$TargetVersion = ${TargetVersion}
$RestartServiceName = ${RestartServiceName}
$Force = ${Force}
$Json = ${Json}
$Uninstall = ${Uninstall}
$Cleanup = ${Cleanup}
# Normalize boolean-like values
if ($TargetVersion -eq '1') { $TargetVersion = $true } elseif ($TargetVersion -eq '0') { $TargetVersion = $false }
if ($RestartServiceName -eq '1') { $RestartServiceName = $true } elseif ($RestartServiceName -eq '0') { $RestartServiceName = $false }
if ($Force -eq '1') { $Force = $true } elseif ($Force -eq '0') { $Force = $false }
if ($Json -eq '1') { $Json = $true } elseif ($Json -eq '0') { $Json = $false }
if ($Uninstall -eq '1') { $Uninstall = $true } elseif ($Uninstall -eq '0') { $Uninstall = $false }
if ($Cleanup -eq '1') { $Cleanup = $true } elseif ($Cleanup -eq '0') { $Cleanup = $false }
# Build callArgs hashtable
$callArgs = @{}
if ($TargetVersion -ne '' -and $TargetVersion -ne $null) { $callArgs['TargetVersion'] = $TargetVersion }
if ($RestartServiceName -ne '' -and $RestartServiceName -ne $null) { $callArgs['RestartServiceName'] = $RestartServiceName }
if ($Force -ne '' -and $Force -ne $null) { $callArgs['Force'] = $Force }
if ($Json -ne '' -and $Json -ne $null) { $callArgs['Json'] = $Json }
if ($Uninstall -ne '' -and $Uninstall -ne $null) { $callArgs['Uninstall'] = $Uninstall }
if ($Cleanup -ne '' -and $Cleanup -ne $null) { $callArgs['Cleanup'] = $Cleanup }
# Log execution
$jsonArgs = ($callArgs | ConvertTo-Json -Compress)
Write-Host "ZyntriOps Action1 PowerShell Wrapper"
Write-Host "Licensed under Apache License 2.0"
Write-Host "Copyright (c) 2026 Michel Sijmons"
Write-Host "Wrapper generator download: https://gists.mickert.dev/d76e6a710a6cafb5b631049f6aa917e4"
Write-Host ""
$ts = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ss.fffffffK")
Write-Host "[$ts] Executing wrapped script 'ZyntriOps-SmartmontoolsInstaller1.3.1.ps1' with arguments: $jsonArgs"
# Decode original script
$scriptPath = "$env:TEMP\Action1WrappedScript.ps1"
$base64 = "PCNQU1NjcmlwdEluZm8NCi5WRVJTSU9OIDEuMy4xDQouR1VJRCA4ZjNjOWMzYy00YjlkLTRjMWUtOWM0YS0yZjFmMGU4YjdhMTENCi5BVVRIT1IgTWljaGVsIFNpam1vbnMgKFp5bnRyaU9wcykNCi5DT01QQU5ZTkFNRSBaeW50cmlPcHMNCi5DT1BZUklHSFQgQ29weXJpZ2h0IChjKSAyMDI2IE1pY2hlbCBTaWptb25zIC0gaHR0cHM6Ly9taWNrZXJ0LmRldg0KLkxJQ0VOU0VVUkkgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wDQouUFJPSkVDVFVSSSBodHRwczovL3p5bnRyaW9wcy5jb20vdG9vbHMvc21hcnRtb250b29scy1pbnN0YWxsZXINCi5JQ09OVVJJIGh0dHBzOi8venludHJpb3BzLmNvbS90b29scy9zbWFydG1vbnRvb2xzLWluc3RhbGxlci9pY29uLnBuZw0KLlRBR1Mgc21hcnRtb250b29scztpbnN0YWxsZXI7enludHJpb3BzO21vbml0b3Jpbmc7c3RvcmFnZTthdXRvbWF0aW9uDQouUkVMRUFTRU5PVEVTDQotIEFkZGVkIEdpdEh1YiBBUEkgYXNzZXQgZGlzY292ZXJ5IChmdXR1cmUtcHJvb2YgZm9yIDcuNS4xKywgNy42LCBldGMuKQ0KLSBBZGRlZCB1bmluc3RhbGwgL1MgZW5mb3JjZW1lbnQNCi0gSW1wcm92ZWQgbG9nZ2luZywgY2xlYW51cCwgZmFpbC1mYXN0IGJlaGF2aW9yLCBhbmQgaW5zdGFsbGVyIG91dHB1dCBjYXB0dXJlDQotIEFkZGVkIEpTT04gb3V0cHV0IGZvciBhdXRvbWF0aW9uIHN5c3RlbXMNCi0gQWRkZWQgZG93bmdyYWRlIHN1cHBvcnQgd2l0aCBhdXRvbWF0aWMgdW5pbnN0YWxsDQotIEFkZGVkIE1PVFcgcmVtb3ZhbCBhbmQgTUQ1IHZhbGlkYXRpb24NCiM+DQoNCjwjDQouU1lOT1BTSVMNCiAgICBJbnN0YWxscywgdXBkYXRlcywgZG93bmdyYWRlcywgb3IgdW5pbnN0YWxscyBzbWFydG1vbnRvb2xzIG9uIFdpbmRvd3Mgc3lzdGVtcy4NCg0KLkRFU0NSSVBUSU9ODQogICAgWnludHJpT3BzLVNtYXJ0bW9udG9vbHNJbnN0YWxsZXIucHMxDQogICAgVGhpcyBzY3JpcHQgaW5zdGFsbHMsIHVwZGF0ZXMsIGRvd25ncmFkZXMsIG9yIHVuaW5zdGFsbHMgc21hcnRtb250b29scyBvbiBXaW5kb3dzIHN5c3RlbXMuDQogICAgSXQgcmV0cmlldmVzIHJlbGVhc2UgbWV0YWRhdGEgZGlyZWN0bHkgZnJvbSB0aGUgR2l0SHViIEFQSSwgZGlzY292ZXJzIHRoZSBjb3JyZWN0DQogICAgaW5zdGFsbGVyIGFzc2V0IGZvciB0aGUgcmVxdWVzdGVkIHZlcnNpb24sIGRvd25sb2FkcyB0aGUgaW5zdGFsbGVyIGFuZCBpdHMgTUQ1DQogICAgY2hlY2tzdW0sIHZhbGlkYXRlcyBmaWxlIGludGVncml0eSwgcmVtb3ZlcyBNYXJrLW9mLXRoZS1XZWIgKE1PVFcpLCBhbmQgcGVyZm9ybXMNCiAgICBhIGZ1bGx5IHNpbGVudCBpbnN0YWxsYXRpb24uDQoNCiAgICBJZiBhIHNwZWNpZmljIHZlcnNpb24gaXMgcmVxdWVzdGVkIHZpYSAtVGFyZ2V0VmVyc2lvbiwgdGhlIHNjcmlwdCB3aWxsIGluc3RhbGwgdGhhdCB2ZXJzaW9uLg0KICAgIElmIHRoZSByZXF1ZXN0ZWQgdmVyc2lvbiBpcyBsb3dlciB0aGFuIHRoZSBpbnN0YWxsZWQgdmVyc2lvbiwgdGhlIHNjcmlwdCB3aWxsIHVuaW5zdGFsbCB0aGUNCiAgICBjdXJyZW50IHZlcnNpb24gYmVmb3JlIGluc3RhbGxpbmcgdGhlIHRhcmdldC4gSWYgdGhlIHJlcXVlc3RlZCB2ZXJzaW9uIGVxdWFscyB0aGUgaW5zdGFsbGVkDQogICAgdmVyc2lvbiwgbm8gYWN0aW9uIGlzIHRha2VuIHVubGVzcyAtRm9yY2UgaXMgc3BlY2lmaWVkLg0KDQogICAgV2hlbiAtVW5pbnN0YWxsIGlzIHNwZWNpZmllZCwgdGhlIHNjcmlwdCB3aWxsIG9ubHkgdW5pbnN0YWxsIHNtYXJ0bW9udG9vbHMgKGlmIGluc3RhbGxlZCkuDQogICAgSWYgLVJlc3RhcnRTZXJ2aWNlTmFtZSBpcyBwcm92aWRlZCwgdGhlIHNwZWNpZmllZCBzZXJ2aWNlIHdpbGwgYmUgcmVzdGFydGVkIGFmdGVyIGluc3RhbGwsDQogICAgZG93bmdyYWRlLCBvciB1bmluc3RhbGwuIFRoaXMgaXMgdXNlZnVsIGZvciBzZXJ2aWNlcyB0aGF0IHByb2JlIGZvciBzbWFydG1vbnRvb2xzIG9uIHN0YXJ0dXAuDQoNCiAgICBXaGVuIC1DbGVhbnVwIGlzIHVzZWQsIHRlbXBvcmFyeSBmaWxlcyAoaW5zdGFsbGVyLCBjaGVja3N1bSwgc3Rkb3V0L3N0ZGVyciBsb2dzKQ0KICAgIGFyZSByZW1vdmVkIGFmdGVyIGEgc3VjY2Vzc2Z1bCBvcGVyYXRpb24uIENsZWFudXAgaXMgc2tpcHBlZCBvbiBmYWlsdXJlIHRvDQogICAgcHJlc2VydmUgYXJ0aWZhY3RzIGZvciBkZWJ1Z2dpbmcgYW5kIGF1ZGl0aW5nLg0KDQogICAgRXhpc3RpbmcgaW5zdGFsbGF0aW9ucyBhcmUgZGV0ZWN0ZWQgdGhyb3VnaCByZWdpc3RyeSBrZXlzLCB3aGVyZS5leGUsIGFuZCBkZWZhdWx0IGluc3RhbGxhdGlvbg0KICAgIHBhdGhzLg0KICAgIA0KICAgIFRoZSBzY3JpcHQgc3VwcG9ydHMgSlNPTiBvdXRwdXQgZm9yIFJNTS9DSS9DRCBzeXN0ZW1zIGFuZCB3cml0ZXMgb3BlcmF0aW9uYWwgbG9ncw0KICAgIHRvIFByb2dyYW1EYXRhIHdpdGggdGltZXN0YW1wZWQgZW50cmllcy4NCg0KICAgIFRoaXMgc2NyaXB0IGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAuDQogICAgU2VlIHRoZSBMSUNFTlNFIHNlY3Rpb24gaW4gdGhpcyBzY3JpcHQuDQoNCiAgICBESVNDTEFJTUVSOg0KICAgIFRoaXMgc2NyaXB0IGlzIHByb3ZpZGVkICJhcy1pcyIgd2l0aG91dCBhbnkgd2FycmFudGllcyBvciBndWFyYW50ZWVzLg0KICAgIFVzZSBhdCB5b3VyIG93biByaXNrLiBUaGUgYXV0aG9yIGFzc3VtZXMgbm8gbGlhYmlsaXR5IGZvciBhbnkgZGFtYWdlcywNCiAgICBkYXRhIGxvc3MsIG1pc2NvbmZpZ3VyYXRpb24sIG9yIG9wZXJhdGlvbmFsIGltcGFjdCByZXN1bHRpbmcgZnJvbSB0aGUNCiAgICB1c2Ugb2YgdGhpcyBzY3JpcHQuIEFsd2F5cyB0ZXN0IGluIGEgY29udHJvbGxlZCBlbnZpcm9ubWVudCBiZWZvcmUNCiAgICBkZXBsb3lpbmcgdG8gcHJvZHVjdGlvbi4NCg0KICAgIChjKSAyMDI2IE1pY2hlbCBTaWptb25zIC0gaHR0cHM6Ly9taWNrZXJ0LmRldg0KDQouUEFSQU1FVEVSIFRhcmdldFZlcnNpb24NCiAgICBPcHRpb25hbC4gSW5zdGFsbHMgYSBzcGVjaWZpYyBzbWFydG1vbnRvb2xzIHZlcnNpb24gaW5zdGVhZCBvZiB0aGUgbGF0ZXN0Lg0KICAgIElmIHRoZSB0YXJnZXQgdmVyc2lvbiBpcyBsb3dlciB0aGFuIHRoZSBpbnN0YWxsZWQgdmVyc2lvbiwgdGhlIHNjcmlwdCB3aWxsDQogICAgdW5pbnN0YWxsIHRoZSBjdXJyZW50IHZlcnNpb24gYmVmb3JlIGluc3RhbGxpbmcgdGhlIHJlcXVlc3RlZCB2ZXJzaW9uLg0KICAgIElmIHRoZSB0YXJnZXQgdmVyc2lvbiBlcXVhbHMgdGhlIGluc3RhbGxlZCB2ZXJzaW9uLCBubyBhY3Rpb24gaXMgdGFrZW4NCiAgICB1bmxlc3MgLUZvcmNlIGlzIHNwZWNpZmllZC4NCg0KLlBBUkFNRVRFUiBVbmluc3RhbGwNCiAgICBVbmluc3RhbGxzIHNtYXJ0bW9udG9vbHMgaWYgaXQgaXMgaW5zdGFsbGVkLiBObyBpbnN0YWxsYXRpb24gb3IgdXBkYXRlDQogICAgd2lsbCBiZSBwZXJmb3JtZWQgd2hlbiB0aGlzIHN3aXRjaCBpcyB1c2VkLiBJZiBzbWFydG1vbnRvb2xzIGlzIG5vdA0KICAgIGluc3RhbGxlZCwgdGhlIHNjcmlwdCBleGl0cyBncmFjZWZ1bGx5LiBJZiAtUmVzdGFydFNlcnZpY2VOYW1lIGlzDQogICAgc3BlY2lmaWVkLCB0aGUgc2VydmljZSB3aWxsIGJlIHJlc3RhcnRlZCBhZnRlciB1bmluc3RhbGwgKG9yIGF0dGVtcHRlZA0KICAgIHVuaW5zdGFsbCkuDQoNCi5QQVJBTUVURVIgUmVzdGFydFNlcnZpY2VOYW1lDQogICAgT3B0aW9uYWwuIFJlc3RhcnRzIHRoZSBzcGVjaWZpZWQgV2luZG93cyBzZXJ2aWNlIGFmdGVyIGluc3RhbGxhdGlvbiwNCiAgICBkb3duZ3JhZGUsIG9yIHVuaW5zdGFsbGF0aW9uIGNvbXBsZXRlcy4gVGhpcyBpcyB1c2VmdWwgZm9yIHNlcnZpY2VzDQogICAgdGhhdCBwcm9iZSBmb3Igc21hcnRtb250b29scyBvbiBzdGFydHVwIG9yIHJlcXVpcmUgYSByZWZyZXNoIGFmdGVyDQogICAgY2hhbmdlcy4NCg0KLlBBUkFNRVRFUiBGb3JjZQ0KICAgIEZvcmNlcyBpbnN0YWxsYXRpb24gZXZlbiBpZiB0aGUgaW5zdGFsbGVkIHZlcnNpb24gYXBwZWFycyB1cC10by1kYXRlIG9yDQogICAgbWF0Y2hlcyB0aGUgcmVxdWVzdGVkIFRhcmdldFZlcnNpb24uDQoNCi5QQVJBTUVURVIgSnNvbg0KICAgIE91dHB1dHMgc3RydWN0dXJlZCBKU09OIGZvciBSTU0vQ0kvQ0QgcGlwZWxpbmVzLg0KDQouUEFSQU1FVEVSIENsZWFudXANCiAgICBSZW1vdmVzIGRvd25sb2FkZWQgdGVtcG9yYXJ5IGZpbGVzIChpbnN0YWxsZXIsIGNoZWNrc3VtLCBhbmQgY2FwdHVyZWQNCiAgICBzdGRvdXQvc3RkZXJyIGxvZ3MpIGZyb20gJGVudjpURU1QIGFmdGVyIGEgc3VjY2Vzc2Z1bCBpbnN0YWxsYXRpb24sDQogICAgdXBkYXRlLCBkb3duZ3JhZGUsIG9yIHVuaW5zdGFsbC4gVGhpcyBvcHRpb24gaXMgZGlzYWJsZWQgYnkgZGVmYXVsdA0KICAgIHRvIHByZXNlcnZlIGFydGlmYWN0cyBmb3IgZGVidWdnaW5nIGFuZCBhdWRpdGluZy4NCg0KLlBBUkFNRVRFUiBWZXJib3NlDQogICAgRW5hYmxlcyBkZXRhaWxlZCBsb2dnaW5nIG91dHB1dC4gVGhpcyBzY3JpcHQgdXNlcyBXcml0ZS1WZXJib3NlIGV4dGVuc2l2ZWx5DQogICAgdG8gcHJvdmlkZSB0aW1lc3RhbXBlZCBvcGVyYXRpb25hbCBsb2dzLiBVc2UgLVZlcmJvc2UgdG8gZGlzcGxheSB0aGVtLg0KDQouUEFSQU1FVEVSIFdoYXRJZg0KICAgIFNob3dzIHdoYXQgYWN0aW9ucyB3b3VsZCBiZSBwZXJmb3JtZWQgd2l0aG91dCBtYWtpbmcgYW55IGNoYW5nZXMuIEFwcGxpZXMgdG8NCiAgICBpbnN0YWxsYXRpb24sIGRvd25ncmFkZSwgdW5pbnN0YWxsLCBjbGVhbnVwLCBhbmQgc2VydmljZSByZXN0YXJ0IG9wZXJhdGlvbnMuDQoNCi5QQVJBTUVURVIgQ29uZmlybQ0KICAgIFByb21wdHMgZm9yIGNvbmZpcm1hdGlvbiBiZWZvcmUgZXhlY3V0aW5nIGFjdGlvbnMuIEFwcGxpZXMgdG8gaW5zdGFsbGF0aW9uLA0KICAgIGRvd25ncmFkZSwgdW5pbnN0YWxsLCBjbGVhbnVwLCBhbmQgc2VydmljZSByZXN0YXJ0IG9wZXJhdGlvbnMuDQoNCi5QQVJBTUVURVIgRGVidWcNCiAgICBFbmFibGVzIGRlYnVnIG91dHB1dC4gVXNlZnVsIGZvciB0cm91Ymxlc2hvb3Rpbmcgc2NyaXB0IGJlaGF2aW9yLg0KDQouRVhBTVBMRQ0KICAgIFBTPiAuXFp5bnRyaU9wcy1TbWFydG1vbnRvb2xzSW5zdGFsbGVyLnBzMSAtVmVyYm9zZQ0KDQouRVhBTVBMRQ0KICAgIFBTPiAuXFp5bnRyaU9wcy1TbWFydG1vbnRvb2xzSW5zdGFsbGVyLnBzMSAtVGFyZ2V0VmVyc2lvbiA3LjQNCg0KLkVYQU1QTEUNCiAgICBQUz4gLlxaeW50cmlPcHMtU21hcnRtb250b29sc0luc3RhbGxlci5wczEgLVVuaW5zdGFsbCAtUmVzdGFydFNlcnZpY2VOYW1lICJEaXNrTW9uaXRvciINCg0KLkVYQU1QTEUNCiAgICBQUz4gLlxaeW50cmlPcHMtU21hcnRtb250b29sc0luc3RhbGxlci5wczEgLUpzb24gfCBDb252ZXJ0RnJvbS1Kc29uDQoNCi5OT1RFUw0KICAgIEF1dGhvciAgIDogTWljaGVsIFNpam1vbnMgKFp5bnRyaU9wcykgLSBodHRwczovL21pY2tlcnQuZGV2DQogICAgTGljZW5zZSAgOiBBcGFjaGUgTGljZW5zZSAyLjANCiAgICBWZXJzaW9uICA6IDEuMy4xDQoNCiAgICBUaGlzIHNjcmlwdCBtdXN0IGJlIHJ1biB3aXRoIGFkbWluaXN0cmF0aXZlIHByaXZpbGVnZXMuDQogICAgSW50ZXJuZXQgYWNjZXNzIGlzIHJlcXVpcmVkIHRvIHJldHJpZXZlIHJlbGVhc2UgbWV0YWRhdGEgYW5kIGRvd25sb2FkIGluc3RhbGxlcnMuDQogICAgVGVtcG9yYXJ5IGZpbGVzIGFyZSBzdG9yZWQgaW4gJGVudjpURU1QIGFuZCByZW1vdmVkIG9ubHkgd2hlbiAtQ2xlYW51cCBpcyB1c2VkLg0KICAgIExvZ3MgYXJlIHdyaXR0ZW4gdG86ICRlbnY6UHJvZ3JhbURhdGFcWnludHJpT3BzXExvZ3NcSW5zdGFsbGVyXFNtYXJ0bW9udG9vbHNJbnN0YWxsZXIubG9nDQoNCi5MSU5LDQogICAgaHR0cHM6Ly9naXN0cy5taWNrZXJ0LmRldi9jNTAyMjAyY2E3ZGQxYTU2ZTE0YjQ4ZTUzZmFhNDExYyNmaWxlLXp5bnRyaW9wcy1zbWFydG1vbnRvb2xzaW5zdGFsbGVyLXBzMQ0KDQojPg0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBOT1RJQ0UNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIFRoaXMgc2NyaXB0IGlzIHBhcnQgb2YgdGhlIFp5bnRyaU9wcyBUb29sa2l0Lg0KIyBEZXZlbG9wZWQgYnkgTWljaGVsIFNpam1vbnMuDQojIENvcHlyaWdodCAoYykgMjAyNiBNaWNoZWwgU2lqbW9ucyBhbmQgbGljZW5zZWQgdW5kZXIgdGhlDQojIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMC4gU2VlIExpY2Vuc2Ugc2VjdGlvbiBiZWxvdy4NCiMNCiMgRm9yIG1vcmUgaW5mb3JtYXRpb24sIHZpc2l0OiBodHRwczovL3p5bnRyaW9wcy5jb20NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgRElTQ0xBSU1FUiAmIExJQ0VOU0UNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOw0KIyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuDQojIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdDoNCiMNCiMgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMA0KIw0KIyBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlDQojIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJUyIgQkFTSVMsDQojIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLg0KIyBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kDQojIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLg0KIw0KIyBESVNDTEFJTUVSOg0KIyBUaGlzIHNjcmlwdCBpcyBwcm92aWRlZCAiYXMtaXMiIHdpdGhvdXQgYW55IHdhcnJhbnRpZXMgb3IgZ3VhcmFudGVlcy4NCiMgVXNlIGF0IHlvdXIgb3duIHJpc2suIFRoZSBhdXRob3IgYXNzdW1lcyBubyBsaWFiaWxpdHkgZm9yIGFueSBkYW1hZ2VzLA0KIyBkYXRhIGxvc3MsIG1pc2NvbmZpZ3VyYXRpb24sIG9yIG9wZXJhdGlvbmFsIGltcGFjdCByZXN1bHRpbmcgZnJvbSB0aGUNCiMgdXNlIG9mIHRoaXMgc2NyaXB0LiBBbHdheXMgdGVzdCBpbiBhIGNvbnRyb2xsZWQgZW52aXJvbm1lbnQgYmVmb3JlDQojIGRlcGxveWluZyB0byBwcm9kdWN0aW9uLg0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBDT1BZUklHSFQNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIENvcHlyaWdodCAoYykgMjAyNiBNaWNoZWwgU2lqbW9ucw0KIyBBbGwgcmlnaHRzIHJlc2VydmVkLg0KDQpbQ21kbGV0QmluZGluZyhTdXBwb3J0c1Nob3VsZFByb2Nlc3MgPSAkdHJ1ZSldDQpwYXJhbSgNCiAgICBbc3RyaW5nXSRUYXJnZXRWZXJzaW9uLA0KICAgIFtzdHJpbmddJFJlc3RhcnRTZXJ2aWNlTmFtZSwNCiAgICBbc3dpdGNoXSRGb3JjZSwNCiAgICBbc3dpdGNoXSRKc29uLA0KICAgIFtzd2l0Y2hdJFVuaW5zdGFsbCwNCiAgICBbc3dpdGNoXSRDbGVhbnVwDQopDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEdMT0JBTFMNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQokc2NyaXB0Ok1vZHVsZU5hbWUgICAgPSAiWnludHJpT3BzLlNtYXJ0bW9udG9vbHNJbnN0YWxsZXIiDQokc2NyaXB0OlNjcmlwdFZlcnNpb24gPSAiMS4zLjEiDQokc2NyaXB0OlZlcmJvc2VMb2dnaW5nRW5hYmxlZCA9ICRmYWxzZQ0KJHNjcmlwdDpMb2dGaWxlID0gJG51bGwNCg0KIyBJbml0aWFsaXplIGxvZyBmaWxlDQp0cnkgew0KICAgICRsb2dSb290ID0gSm9pbi1QYXRoICRlbnY6UHJvZ3JhbURhdGEgIlp5bnRyaU9wc1xMb2dzXEluc3RhbGxlciINCiAgICBpZiAoLW5vdCAoVGVzdC1QYXRoICRsb2dSb290KSkgew0KICAgICAgICBOZXctSXRlbSAtSXRlbVR5cGUgRGlyZWN0b3J5IC1QYXRoICRsb2dSb290IC1Gb3JjZSB8IE91dC1OdWxsDQogICAgfQ0KICAgICRzY3JpcHQ6TG9nRmlsZSA9IEpvaW4tUGF0aCAkbG9nUm9vdCAiU21hcnRtb250b29sc0luc3RhbGxlci5sb2ciDQp9DQpjYXRjaCB7DQogICAgJHNjcmlwdDpMb2dGaWxlID0gJG51bGwNCn0NCg0KaWYgKCRQU0JvdW5kUGFyYW1ldGVycy5Db250YWluc0tleSgnVmVyYm9zZScpKSB7DQogICAgJHNjcmlwdDpWZXJib3NlTG9nZ2luZ0VuYWJsZWQgPSAkdHJ1ZQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBMT0dHSU5HDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KZnVuY3Rpb24gV3JpdGUtWk9Mb2cgew0KICAgIHBhcmFtKA0KICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV1bc3RyaW5nXSRNZXNzYWdlLA0KICAgICAgICBbVmFsaWRhdGVTZXQoIklORk8iLCJXQVJOIiwiRVJST1IiLCJERUJVRyIpXVtzdHJpbmddJExldmVsID0gIklORk8iDQogICAgKQ0KDQogICAgJHRpbWVzdGFtcCA9IEdldC1EYXRlIC1Gb3JtYXQgbw0KICAgICRsaW5lID0gIlskdGltZXN0YW1wXSBbJExldmVsXSAkTWVzc2FnZSINCg0KICAgIGlmICgkc2NyaXB0OkxvZ0ZpbGUpIHsNCiAgICAgICAgdHJ5IHsgQWRkLUNvbnRlbnQgLUxpdGVyYWxQYXRoICRzY3JpcHQ6TG9nRmlsZSAtVmFsdWUgJGxpbmUgfSBjYXRjaCB7fQ0KICAgIH0NCg0KICAgIHN3aXRjaCAoJExldmVsKSB7DQogICAgICAgICJFUlJPUiIgew0KICAgICAgICAgICAgV3JpdGUtRXJyb3IgJGxpbmUNCiAgICAgICAgICAgIFdyaXRlLVZlcmJvc2UgJGxpbmUNCiAgICAgICAgfQ0KICAgICAgICAiREVCVUciIHsNCiAgICAgICAgICAgIGlmICgkc2NyaXB0OlZlcmJvc2VMb2dnaW5nRW5hYmxlZCkgeyBXcml0ZS1WZXJib3NlICRsaW5lIH0NCiAgICAgICAgfQ0KICAgICAgICBkZWZhdWx0IHsNCiAgICAgICAgICAgIFdyaXRlLVZlcmJvc2UgJGxpbmUNCiAgICAgICAgfQ0KICAgIH0NCn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgTkVUV09SSw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCmZ1bmN0aW9uIEludm9rZS1aT1dlYlJlcXVlc3Qgew0KICAgIFtDbWRsZXRCaW5kaW5nKCldDQogICAgW091dHB1dFR5cGUoW2Jvb2xdKV0NCiAgICBwYXJhbSgNCiAgICAgICAgW3N0cmluZ10kVXJsLA0KICAgICAgICBbc3RyaW5nXSRPdXRGaWxlDQogICAgKQ0KDQogICAgV3JpdGUtWk9Mb2cgIkRvd25sb2FkaW5nOiAkVXJsIiAiSU5GTyINCg0KICAgIHRyeSB7DQogICAgICAgIEludm9rZS1XZWJSZXF1ZXN0IC1VcmkgJFVybCAtT3V0RmlsZSAkT3V0RmlsZSAtVXNlQmFzaWNQYXJzaW5nIC1UaW1lb3V0U2VjIDYwDQogICAgICAgIHJldHVybiAkdHJ1ZQ0KICAgIH0NCiAgICBjYXRjaCB7DQogICAgICAgIFdyaXRlLVpPTG9nICJEb3dubG9hZCBmYWlsZWQ6ICQoJF8uRXhjZXB0aW9uLk1lc3NhZ2UpIiAiRVJST1IiDQogICAgICAgIHJldHVybiAkZmFsc2UNCiAgICB9DQp9DQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIERFVEVDVElPTg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCmZ1bmN0aW9uIEdldC1aT1NtYXJ0bW9udG9vbHNJbnN0YWxsSW5mbyB7DQogICAgW0NtZGxldEJpbmRpbmcoKV0NCiAgICBbT3V0cHV0VHlwZShbUFNDdXN0b21PYmplY3RdKV0NCiAgICBwYXJhbSgpDQoNCiAgICAkcGF0aHMgPSBAKA0KICAgICAgICAiSEtMTTpcU09GVFdBUkVcV09XNjQzMk5vZGVcTWljcm9zb2Z0XFdpbmRvd3NcQ3VycmVudFZlcnNpb25cVW5pbnN0YWxsXHNtYXJ0bW9udG9vbHMiLA0KICAgICAgICAiSEtMTTpcU09GVFdBUkVcTWljcm9zb2Z0XFdpbmRvd3NcQ3VycmVudFZlcnNpb25cVW5pbnN0YWxsXHNtYXJ0bW9udG9vbHMiDQogICAgKQ0KDQogICAgZm9yZWFjaCAoJHAgaW4gJHBhdGhzKSB7DQogICAgICAgIGlmIChUZXN0LVBhdGggJHApIHsNCiAgICAgICAgICAgICRrZXkgPSBHZXQtSXRlbVByb3BlcnR5ICRwDQogICAgICAgICAgICByZXR1cm4gW1BTQ3VzdG9tT2JqZWN0XUB7DQogICAgICAgICAgICAgICAgRGlzcGxheVZlcnNpb24gID0gJGtleS5EaXNwbGF5VmVyc2lvbg0KICAgICAgICAgICAgICAgIEluc3RhbGxMb2NhdGlvbiA9ICRrZXkuSW5zdGFsbExvY2F0aW9uDQogICAgICAgICAgICAgICAgVW5pbnN0YWxsU3RyaW5nID0gJGtleS5Vbmluc3RhbGxTdHJpbmcNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIH0NCg0KICAgIHJldHVybiAkbnVsbA0KfQ0KDQpmdW5jdGlvbiBHZXQtWk9TbWFydGN0bFBhdGggew0KICAgIFtDbWRsZXRCaW5kaW5nKCldDQogICAgW091dHB1dFR5cGUoW3N0cmluZ10pXQ0KICAgIHBhcmFtKCkNCg0KICAgICRpbmZvID0gR2V0LVpPU21hcnRtb250b29sc0luc3RhbGxJbmZvDQogICAgaWYgKCRpbmZvIC1hbmQgJGluZm8uSW5zdGFsbExvY2F0aW9uKSB7DQogICAgICAgICRjYW5kaWRhdGUgPSBKb2luLVBhdGggJGluZm8uSW5zdGFsbExvY2F0aW9uICJiaW5cc21hcnRjdGwuZXhlIg0KICAgICAgICBpZiAoVGVzdC1QYXRoICRjYW5kaWRhdGUpIHsgcmV0dXJuICRjYW5kaWRhdGUgfQ0KICAgIH0NCg0KICAgICR3aGVyZSA9ICYgd2hlcmUuZXhlIHNtYXJ0Y3RsIDI+JG51bGwNCiAgICBpZiAoJHdoZXJlIC1hbmQgKFRlc3QtUGF0aCAkd2hlcmUpKSB7IHJldHVybiAkd2hlcmUgfQ0KDQogICAgJGRlZmF1bHQgPSAiQzpcUHJvZ3JhbSBGaWxlc1xzbWFydG1vbnRvb2xzXGJpblxzbWFydGN0bC5leGUiDQogICAgaWYgKFRlc3QtUGF0aCAkZGVmYXVsdCkgeyByZXR1cm4gJGRlZmF1bHQgfQ0KDQogICAgcmV0dXJuICRudWxsDQp9DQoNCmZ1bmN0aW9uIEdldC1aT1NtYXJ0bW9udG9vbHNJbnN0YWxsZWRWZXJzaW9uIHsNCiAgICBbQ21kbGV0QmluZGluZygpXQ0KICAgIFtPdXRwdXRUeXBlKFtzdHJpbmddKV0NCiAgICBwYXJhbSgpDQoNCiAgICAkc21hcnRjdGwgPSBHZXQtWk9TbWFydGN0bFBhdGgNCiAgICBpZiAoLW5vdCAkc21hcnRjdGwpIHsgcmV0dXJuICRudWxsIH0NCg0KICAgIHRyeSB7DQogICAgICAgICRvdXRwdXQgPSAmICRzbWFydGN0bCAtLXZlcnNpb24gMj4kbnVsbA0KICAgICAgICBpZiAoLW5vdCAkb3V0cHV0KSB7IHJldHVybiAkbnVsbCB9DQoNCiAgICAgICAgJGxpbmUgPSAkb3V0cHV0IHwgU2VsZWN0LU9iamVjdCAtRmlyc3QgMQ0KICAgICAgICBpZiAoJGxpbmUgLW1hdGNoICJzbWFydGN0bFxzKyhbXGRcLl0rKSIpIHsNCiAgICAgICAgICAgIHJldHVybiAkTWF0Y2hlc1sxXQ0KICAgICAgICB9DQogICAgfQ0KICAgIGNhdGNoIHsNCiAgICAgICAgV3JpdGUtWk9Mb2cgIkZhaWxlZCB0byBxdWVyeSBzbWFydGN0bCB2ZXJzaW9uOiAkKCRfLkV4Y2VwdGlvbi5NZXNzYWdlKSIgIldBUk4iDQogICAgfQ0KDQogICAgcmV0dXJuICRudWxsDQp9DQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIFVOSU5TVEFMTCAod2l0aCAvUyBlbmZvcmNlbWVudCkNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpmdW5jdGlvbiBVbmluc3RhbGwtWk9TbWFydG1vbnRvb2xzIHsNCiAgICBbQ21kbGV0QmluZGluZyhTdXBwb3J0c1Nob3VsZFByb2Nlc3MgPSAkdHJ1ZSldDQogICAgW091dHB1dFR5cGUoW2Jvb2xdKV0NCiAgICBwYXJhbSgpDQoNCiAgICAkaW5mbyA9IEdldC1aT1NtYXJ0bW9udG9vbHNJbnN0YWxsSW5mbw0KICAgIGlmICgtbm90ICRpbmZvIC1vciAtbm90ICRpbmZvLlVuaW5zdGFsbFN0cmluZykgew0KICAgICAgICBXcml0ZS1aT0xvZyAiTm8gdW5pbnN0YWxsIGluZm9ybWF0aW9uIGZvdW5kOyBza2lwcGluZyB1bmluc3RhbGwuIiAiV0FSTiINCiAgICAgICAgcmV0dXJuICR0cnVlDQogICAgfQ0KDQogICAgJHVuaW5zdGFsbENtZCA9ICRpbmZvLlVuaW5zdGFsbFN0cmluZy5UcmltKCkNCg0KICAgICMgRW5zdXJlIC9TIGlzIHByZXNlbnQNCiAgICBpZiAoJHVuaW5zdGFsbENtZCAtbm90bWF0Y2ggIi9TXGIiKSB7DQogICAgICAgIFdyaXRlLVpPTG9nICJBZGRpbmcgL1MgdG8gdW5pbnN0YWxsIHBhcmFtZXRlcnMuIiAiSU5GTyINCiAgICAgICAgJHVuaW5zdGFsbENtZCA9ICIkdW5pbnN0YWxsQ21kIC9TIg0KICAgIH0NCg0KICAgIFdyaXRlLVpPTG9nICJGaW5hbCB1bmluc3RhbGwgY29tbWFuZDogJHVuaW5zdGFsbENtZCIgIkRFQlVHIg0KDQogICAgaWYgKCRQU0NtZGxldC5TaG91bGRQcm9jZXNzKCJzbWFydG1vbnRvb2xzIiwgIlVuaW5zdGFsbCIpKSB7DQogICAgICAgIHRyeSB7DQogICAgICAgICAgICAkYXJndW1lbnRzID0gIi9jIGAiJHVuaW5zdGFsbENtZGAiIg0KICAgICAgICAgICAgJHByb2MgPSBTdGFydC1Qcm9jZXNzIC1GaWxlUGF0aCAiY21kLmV4ZSIgLUFyZ3VtZW50TGlzdCAkYXJndW1lbnRzIC1XYWl0IC1QYXNzVGhydQ0KDQogICAgICAgICAgICBpZiAoJHByb2MuRXhpdENvZGUgLW5lIDApIHsNCiAgICAgICAgICAgICAgICBXcml0ZS1aT0xvZyAiVW5pbnN0YWxsIHJldHVybmVkIGV4aXQgY29kZSAkKCRwcm9jLkV4aXRDb2RlKSIgIkVSUk9SIg0KICAgICAgICAgICAgICAgIHJldHVybiAkZmFsc2UNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgV3JpdGUtWk9Mb2cgIlVuaW5zdGFsbCBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5LiIgIklORk8iDQogICAgICAgICAgICByZXR1cm4gJHRydWUNCiAgICAgICAgfQ0KICAgICAgICBjYXRjaCB7DQogICAgICAgICAgICBXcml0ZS1aT0xvZyAiVW5pbnN0YWxsIGZhaWxlZDogJCgkXy5FeGNlcHRpb24uTWVzc2FnZSkiICJFUlJPUiINCiAgICAgICAgICAgIHJldHVybiAkZmFsc2UNCiAgICAgICAgfQ0KICAgIH0NCg0KICAgIHJldHVybiAkdHJ1ZQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBHSVRIVUIgUkVMRUFTRSBESVNDT1ZFUlkgKGZ1dHVyZS1wcm9vZikNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpmdW5jdGlvbiBHZXQtWk9TbWFydG1vbnRvb2xzRG93bmxvYWRVcmxzIHsNCiAgICBbQ21kbGV0QmluZGluZygpXQ0KICAgIFtPdXRwdXRUeXBlKFtQU0N1c3RvbU9iamVjdF0pXQ0KICAgIHBhcmFtKA0KICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeSA9ICR0cnVlKV0NCiAgICAgICAgW3N0cmluZ10kVmVyc2lvbg0KICAgICkNCg0KICAgICMgQ29udmVydCB2ZXJzaW9uIHRvIHRhZyBmb3JtYXQ6IDcuNS4xIOKGkiBSRUxFQVNFXzdfNV8xDQogICAgJHRhZyA9ICJSRUxFQVNFXyIgKyAoJFZlcnNpb24gLXJlcGxhY2UgIlwuIiwgIl8iKQ0KDQogICAgJGFwaSA9ICJodHRwczovL2FwaS5naXRodWIuY29tL3JlcG9zL3NtYXJ0bW9udG9vbHMvc21hcnRtb250b29scy9yZWxlYXNlcy90YWdzLyR0YWciDQogICAgV3JpdGUtWk9Mb2cgIlF1ZXJ5aW5nIEdpdEh1YiBmb3IgcmVsZWFzZSB0YWcgJHRhZyIgIklORk8iDQoNCiAgICB0cnkgew0KICAgICAgICAkcmVsZWFzZSA9IEludm9rZS1SZXN0TWV0aG9kIC1VcmkgJGFwaSAtSGVhZGVycyBAeyAiVXNlci1BZ2VudCIgPSAiWnludHJpT3BzIiB9DQogICAgfQ0KICAgIGNhdGNoIHsNCiAgICAgICAgdGhyb3cgIkZhaWxlZCB0byByZXRyaWV2ZSByZWxlYXNlIG1ldGFkYXRhIGZvciAke1ZlcnNpb259OiAkKCRfLkV4Y2VwdGlvbi5NZXNzYWdlKSINCiAgICB9DQoNCiAgICAjIEZpbmQgaW5zdGFsbGVyIGFuZCBNRDUgYXNzZXRzDQogICAgJGluc3RhbGxlciA9ICRyZWxlYXNlLmFzc2V0cyB8IFdoZXJlLU9iamVjdCB7ICRfLm5hbWUgLW1hdGNoICJ3aW4zMi1zZXR1cFwuZXhlJCIgfQ0KICAgICRtZDUgICAgICAgPSAkcmVsZWFzZS5hc3NldHMgfCBXaGVyZS1PYmplY3QgeyAkXy5uYW1lIC1tYXRjaCAid2luMzItc2V0dXBcLmV4ZVwubWQ1JCIgfQ0KDQogICAgaWYgKC1ub3QgJGluc3RhbGxlcikgeyB0aHJvdyAiQ291bGQgbm90IGxvY2F0ZSBpbnN0YWxsZXIgYXNzZXQgZm9yIHZlcnNpb24gJFZlcnNpb24iIH0NCiAgICBpZiAoLW5vdCAkbWQ1KSAgICAgICB7IHRocm93ICJDb3VsZCBub3QgbG9jYXRlIE1ENSBhc3NldCBmb3IgdmVyc2lvbiAkVmVyc2lvbiIgfQ0KDQogICAgcmV0dXJuIFtQU0N1c3RvbU9iamVjdF1Aew0KICAgICAgICBJbnN0YWxsZXIgPSAkaW5zdGFsbGVyLmJyb3dzZXJfZG93bmxvYWRfdXJsDQogICAgICAgIE1kNSAgICAgICA9ICRtZDUuYnJvd3Nlcl9kb3dubG9hZF91cmwNCiAgICB9DQp9DQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIFNFUlZJQ0UgUkVTVEFSVA0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCmZ1bmN0aW9uIFJlc3RhcnQtWk9TZXJ2aWNlIHsNCiAgICBbQ21kbGV0QmluZGluZyhTdXBwb3J0c1Nob3VsZFByb2Nlc3MgPSAkdHJ1ZSldDQogICAgW091dHB1dFR5cGUoW2Jvb2xdKV0NCiAgICBwYXJhbShbc3RyaW5nXSROYW1lKQ0KDQogICAgV3JpdGUtWk9Mb2cgIlJlcXVlc3RlZCByZXN0YXJ0IG9mIHNlcnZpY2UgJyROYW1lJy4iICJJTkZPIg0KDQogICAgdHJ5IHsNCiAgICAgICAgR2V0LVNlcnZpY2UgLU5hbWUgJE5hbWUgLUVycm9yQWN0aW9uIFN0b3AgfCBPdXQtTnVsbA0KICAgIH0NCiAgICBjYXRjaCB7DQogICAgICAgIFdyaXRlLVpPTG9nICJTZXJ2aWNlICckTmFtZScgbm90IGZvdW5kOiAkKCRfLkV4Y2VwdGlvbi5NZXNzYWdlKSIgIkVSUk9SIg0KICAgICAgICByZXR1cm4gJGZhbHNlDQogICAgfQ0KDQogICAgaWYgKCRQU0NtZGxldC5TaG91bGRQcm9jZXNzKCJTZXJ2aWNlICROYW1lIiwgIlJlc3RhcnQiKSkgew0KICAgICAgICB0cnkgew0KICAgICAgICAgICAgUmVzdGFydC1TZXJ2aWNlIC1OYW1lICROYW1lIC1Gb3JjZSAtRXJyb3JBY3Rpb24gU3RvcA0KICAgICAgICAgICAgV3JpdGUtWk9Mb2cgIlNlcnZpY2UgJyROYW1lJyByZXN0YXJ0ZWQgc3VjY2Vzc2Z1bGx5LiIgIklORk8iDQogICAgICAgICAgICByZXR1cm4gJHRydWUNCiAgICAgICAgfQ0KICAgICAgICBjYXRjaCB7DQogICAgICAgICAgICBXcml0ZS1aT0xvZyAiRmFpbGVkIHRvIHJlc3RhcnQgc2VydmljZSAnJE5hbWUnOiAkKCRfLkV4Y2VwdGlvbi5NZXNzYWdlKSIgIkVSUk9SIg0KICAgICAgICAgICAgcmV0dXJuICRmYWxzZQ0KICAgICAgICB9DQogICAgfQ0KDQogICAgcmV0dXJuICRmYWxzZQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBDTEVBTlVQDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KZnVuY3Rpb24gUmVtb3ZlLVpPVGVtcEZpbGUgew0KICAgIFtDbWRsZXRCaW5kaW5nKFN1cHBvcnRzU2hvdWxkUHJvY2VzcyA9ICR0cnVlKV0NCiAgICBbT3V0cHV0VHlwZShbYm9vbF0pXQ0KICAgIHBhcmFtKFtzdHJpbmddJFBhdGgpDQoNCiAgICBpZiAoLW5vdCAoVGVzdC1QYXRoICRQYXRoKSkgew0KICAgICAgICBXcml0ZS1aT0xvZyAiVGVtcG9yYXJ5IGZpbGUgbm90IGZvdW5kOiAkUGF0aCIgIldBUk4iDQogICAgICAgIHJldHVybiAkdHJ1ZQ0KICAgIH0NCg0KICAgIGlmICgkUFNDbWRsZXQuU2hvdWxkUHJvY2VzcygkUGF0aCwgIlJlbW92ZSB0ZW1wb3JhcnkgZmlsZSIpKSB7DQogICAgICAgIHRyeSB7DQogICAgICAgICAgICBSZW1vdmUtSXRlbSAtUGF0aCAkUGF0aCAtRm9yY2UgLUVycm9yQWN0aW9uIFN0b3ANCiAgICAgICAgICAgIFdyaXRlLVpPTG9nICJSZW1vdmVkIHRlbXBvcmFyeSBmaWxlOiAkUGF0aCIgIklORk8iDQogICAgICAgICAgICByZXR1cm4gJHRydWUNCiAgICAgICAgfQ0KICAgICAgICBjYXRjaCB7DQogICAgICAgICAgICBXcml0ZS1aT0xvZyAiRmFpbGVkIHRvIHJlbW92ZSB0ZW1wb3JhcnkgZmlsZSAnJFBhdGgnOiAkKCRfLkV4Y2VwdGlvbi5NZXNzYWdlKSIgIkVSUk9SIg0KICAgICAgICAgICAgcmV0dXJuICRmYWxzZQ0KICAgICAgICB9DQogICAgfQ0KDQogICAgcmV0dXJuICR0cnVlDQp9DQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIE1BSU4gTE9HSUMg4oCUIElOSVRJQUxJWkFUSU9ODQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KV3JpdGUtWk9Mb2cgIlN0YXJ0aW5nICRzY3JpcHQ6TW9kdWxlTmFtZSB2JHNjcmlwdDpTY3JpcHRWZXJzaW9uIiAiSU5GTyINCg0KJGluc3RhbGxlZFJhdyA9IEdldC1aT1NtYXJ0bW9udG9vbHNJbnN0YWxsZWRWZXJzaW9uDQokaW5zdGFsbGVkVmVyID0gJG51bGwNCmlmICgkaW5zdGFsbGVkUmF3KSB7DQogICAgdHJ5IHsgJGluc3RhbGxlZFZlciA9IFt2ZXJzaW9uXSRpbnN0YWxsZWRSYXcgfSBjYXRjaCB7fQ0KfQ0KDQojIERldGVybWluZSBsYXRlc3QgdmVyc2lvbg0KdHJ5IHsNCiAgICAkbGF0ZXN0QXBpID0gImh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vcmVwb3Mvc21hcnRtb250b29scy9zbWFydG1vbnRvb2xzL3JlbGVhc2VzL2xhdGVzdCINCiAgICAkbGF0ZXN0SnNvbiA9IEludm9rZS1SZXN0TWV0aG9kIC1VcmkgJGxhdGVzdEFwaSAtSGVhZGVycyBAeyAiVXNlci1BZ2VudCIgPSAiWnludHJpT3BzIiB9DQogICAgJGxhdGVzdFJhdyA9ICgkbGF0ZXN0SnNvbi50YWdfbmFtZSAtcmVwbGFjZSAiUkVMRUFTRV8iLCAiIikgLXJlcGxhY2UgIl8iLCAiLiINCiAgICAkbGF0ZXN0VmVyID0gW3ZlcnNpb25dJGxhdGVzdFJhdw0KfQ0KY2F0Y2ggew0KICAgIFdyaXRlLVpPTG9nICJHaXRIdWIgQVBJIHVuYXZhaWxhYmxlLCBmYWxsaW5nIGJhY2sgdG8gNy41IiAiV0FSTiINCiAgICAkbGF0ZXN0UmF3ID0gIjcuNSINCiAgICAkbGF0ZXN0VmVyID0gW3ZlcnNpb25dIjcuNSINCn0NCg0KV3JpdGUtWk9Mb2cgIkluc3RhbGxlZCB2ZXJzaW9uOiAkaW5zdGFsbGVkUmF3IiAiSU5GTyINCldyaXRlLVpPTG9nICJMYXRlc3QgdmVyc2lvbiAgIDogJGxhdGVzdFJhdyIgIklORk8iDQoNCiRpbnN0YWxsZXJQYXRoID0gSm9pbi1QYXRoICRlbnY6VEVNUCAic21hcnRtb250b29scy1zZXR1cC5leGUiDQokbWQ1UGF0aCAgICAgICA9IEpvaW4tUGF0aCAkZW52OlRFTVAgInNtYXJ0bW9udG9vbHMtc2V0dXAuZXhlLm1kNSINCiRzdGRvdXRQYXRoICAgID0gSm9pbi1QYXRoICRlbnY6VEVNUCAic21hcnRtb250b29scy1zdGRvdXQubG9nIg0KJHN0ZGVyclBhdGggICAgPSBKb2luLVBhdGggJGVudjpURU1QICJzbWFydG1vbnRvb2xzLXN0ZGVyci5sb2ciDQoNCiRjbGVhbnVwT0sgPSAkZmFsc2UNCiRzZXJ2aWNlUmVzdGFydGVkID0gJGZhbHNlDQokcmVib290UmVxdWlyZWQgPSAkZmFsc2UNCiRpbnN0YWxsZXJFeGl0Q29kZSA9IDANCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgVU5JTlNUQUxMIE1PREUNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQppZiAoJFVuaW5zdGFsbCkgew0KICAgIFdyaXRlLVpPTG9nICJVbmluc3RhbGwgbW9kZSByZXF1ZXN0ZWQuIiAiSU5GTyINCg0KICAgICRpbmZvID0gR2V0LVpPU21hcnRtb250b29sc0luc3RhbGxJbmZvDQoNCiAgICBpZiAoLW5vdCAkaW5mbykgew0KICAgICAgICBXcml0ZS1aT0xvZyAic21hcnRtb250b29scyBpcyBub3QgaW5zdGFsbGVkLiBOb3RoaW5nIHRvIHVuaW5zdGFsbC4iICJXQVJOIg0KDQogICAgICAgIGlmICgkUmVzdGFydFNlcnZpY2VOYW1lKSB7DQogICAgICAgICAgICAkc2VydmljZVJlc3RhcnRlZCA9IFJlc3RhcnQtWk9TZXJ2aWNlIC1OYW1lICRSZXN0YXJ0U2VydmljZU5hbWUNCiAgICAgICAgICAgIGlmICgtbm90ICRzZXJ2aWNlUmVzdGFydGVkKSB7DQogICAgICAgICAgICAgICAgaWYgKCRKc29uKSB7DQogICAgICAgICAgICAgICAgICAgIFtQU0N1c3RvbU9iamVjdF1Aew0KICAgICAgICAgICAgICAgICAgICAgICAgU3RhdHVzICAgICAgICAgICA9ICJOb3RJbnN0YWxsZWQiDQogICAgICAgICAgICAgICAgICAgICAgICBBY3Rpb24gICAgICAgICAgID0gIlVuaW5zdGFsbCINCiAgICAgICAgICAgICAgICAgICAgICAgIFNlcnZpY2VSZXN0YXJ0ZWQgPSAkUmVzdGFydFNlcnZpY2VOYW1lDQogICAgICAgICAgICAgICAgICAgICAgICBTZXJ2aWNlUmVzdGFydE9LID0gJHNlcnZpY2VSZXN0YXJ0ZWQNCiAgICAgICAgICAgICAgICAgICAgICAgIENsZWFudXBSZXF1ZXN0ZWQgPSAkQ2xlYW51cC5Jc1ByZXNlbnQNCiAgICAgICAgICAgICAgICAgICAgICAgIENsZWFudXBPSyAgICAgICAgPSAkY2xlYW51cE9LDQogICAgICAgICAgICAgICAgICAgIH0gfCBDb252ZXJ0VG8tSnNvbiAtRGVwdGggNQ0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBleGl0IDENCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGlmICgkQ2xlYW51cCkgew0KICAgICAgICAgICAgJGNsZWFudXBPSyA9ICgNCiAgICAgICAgICAgICAgICAoUmVtb3ZlLVpPVGVtcEZpbGUgLVBhdGggJGluc3RhbGxlclBhdGgpIC1hbmQNCiAgICAgICAgICAgICAgICAoUmVtb3ZlLVpPVGVtcEZpbGUgLVBhdGggJG1kNVBhdGgpIC1hbmQNCiAgICAgICAgICAgICAgICAoUmVtb3ZlLVpPVGVtcEZpbGUgLVBhdGggJHN0ZG91dFBhdGgpIC1hbmQNCiAgICAgICAgICAgICAgICAoUmVtb3ZlLVpPVGVtcEZpbGUgLVBhdGggJHN0ZGVyclBhdGgpDQogICAgICAgICAgICApDQogICAgICAgIH0NCg0KICAgICAgICBpZiAoJEpzb24pIHsNCiAgICAgICAgICAgIFtQU0N1c3RvbU9iamVjdF1Aew0KICAgICAgICAgICAgICAgIFN0YXR1cyAgICAgICAgICAgPSAiTm90SW5zdGFsbGVkIg0KICAgICAgICAgICAgICAgIEFjdGlvbiAgICAgICAgICAgPSAiVW5pbnN0YWxsIg0KICAgICAgICAgICAgICAgIFNlcnZpY2VSZXN0YXJ0ZWQgPSAkUmVzdGFydFNlcnZpY2VOYW1lDQogICAgICAgICAgICAgICAgU2VydmljZVJlc3RhcnRPSyA9ICRzZXJ2aWNlUmVzdGFydGVkDQogICAgICAgICAgICAgICAgQ2xlYW51cFJlcXVlc3RlZCA9ICRDbGVhbnVwLklzUHJlc2VudA0KICAgICAgICAgICAgICAgIENsZWFudXBPSyAgICAgICAgPSAkY2xlYW51cE9LDQogICAgICAgICAgICB9IHwgQ29udmVydFRvLUpzb24gLURlcHRoIDUNCiAgICAgICAgfQ0KICAgICAgICBleGl0IDANCiAgICB9DQoNCiAgICAkdW5pbnN0YWxsT0sgPSBVbmluc3RhbGwtWk9TbWFydG1vbnRvb2xzDQogICAgaWYgKC1ub3QgJHVuaW5zdGFsbE9LKSB7DQogICAgICAgIGlmICgkSnNvbikgew0KICAgICAgICAgICAgW1BTQ3VzdG9tT2JqZWN0XUB7DQogICAgICAgICAgICAgICAgU3RhdHVzICAgICAgICAgICA9ICJVbmluc3RhbGxGYWlsZWQiDQogICAgICAgICAgICAgICAgT2xkVmVyc2lvbiAgICAgICA9ICRpbnN0YWxsZWRSYXcNCiAgICAgICAgICAgICAgICBTZXJ2aWNlUmVzdGFydGVkID0gJFJlc3RhcnRTZXJ2aWNlTmFtZQ0KICAgICAgICAgICAgICAgIFNlcnZpY2VSZXN0YXJ0T0sgPSAkZmFsc2UNCiAgICAgICAgICAgICAgICBDbGVhbnVwUmVxdWVzdGVkID0gJENsZWFudXAuSXNQcmVzZW50DQogICAgICAgICAgICAgICAgQ2xlYW51cE9LICAgICAgICA9ICRjbGVhbnVwT0sNCiAgICAgICAgICAgIH0gfCBDb252ZXJ0VG8tSnNvbiAtRGVwdGggNQ0KICAgICAgICB9DQogICAgICAgIGV4aXQgMQ0KICAgIH0NCg0KICAgIGlmICgkUmVzdGFydFNlcnZpY2VOYW1lKSB7DQogICAgICAgICRzZXJ2aWNlUmVzdGFydGVkID0gUmVzdGFydC1aT1NlcnZpY2UgLU5hbWUgJFJlc3RhcnRTZXJ2aWNlTmFtZQ0KICAgICAgICBpZiAoLW5vdCAkc2VydmljZVJlc3RhcnRlZCkgew0KICAgICAgICAgICAgaWYgKCRKc29uKSB7DQogICAgICAgICAgICAgICAgW1BTQ3VzdG9tT2JqZWN0XUB7DQogICAgICAgICAgICAgICAgICAgIFN0YXR1cyAgICAgICAgICAgPSAiVW5pbnN0YWxsZWQiDQogICAgICAgICAgICAgICAgICAgIE9sZFZlcnNpb24gICAgICAgPSAkaW5zdGFsbGVkUmF3DQogICAgICAgICAgICAgICAgICAgIFNlcnZpY2VSZXN0YXJ0ZWQgPSAkUmVzdGFydFNlcnZpY2VOYW1lDQogICAgICAgICAgICAgICAgICAgIFNlcnZpY2VSZXN0YXJ0T0sgPSAkc2VydmljZVJlc3RhcnRlZA0KICAgICAgICAgICAgICAgICAgICBDbGVhbnVwUmVxdWVzdGVkID0gJENsZWFudXAuSXNQcmVzZW50DQogICAgICAgICAgICAgICAgICAgIENsZWFudXBPSyAgICAgICAgPSAkY2xlYW51cE9LDQogICAgICAgICAgICAgICAgfSB8IENvbnZlcnRUby1Kc29uIC1EZXB0aCA1DQogICAgICAgICAgICB9DQogICAgICAgICAgICBleGl0IDENCiAgICAgICAgfQ0KICAgIH0NCg0KICAgIGlmICgkQ2xlYW51cCkgew0KICAgICAgICAkY2xlYW51cE9LID0gKA0KICAgICAgICAgICAgKFJlbW92ZS1aT1RlbXBGaWxlIC1QYXRoICRpbnN0YWxsZXJQYXRoKSAtYW5kDQogICAgICAgICAgICAoUmVtb3ZlLVpPVGVtcEZpbGUgLVBhdGggJG1kNVBhdGgpIC1hbmQNCiAgICAgICAgICAgIChSZW1vdmUtWk9UZW1wRmlsZSAtUGF0aCAkc3Rkb3V0UGF0aCkgLWFuZA0KICAgICAgICAgICAgKFJlbW92ZS1aT1RlbXBGaWxlIC1QYXRoICRzdGRlcnJQYXRoKQ0KICAgICAgICApDQogICAgfQ0KDQogICAgaWYgKCRKc29uKSB7DQogICAgICAgIFtQU0N1c3RvbU9iamVjdF1Aew0KICAgICAgICAgICAgU3RhdHVzICAgICAgICAgICA9ICJVbmluc3RhbGxlZCINCiAgICAgICAgICAgIE9sZFZlcnNpb24gICAgICAgPSAkaW5zdGFsbGVkUmF3DQogICAgICAgICAgICBTZXJ2aWNlUmVzdGFydGVkID0gJFJlc3RhcnRTZXJ2aWNlTmFtZQ0KICAgICAgICAgICAgU2VydmljZVJlc3RhcnRPSyA9ICRzZXJ2aWNlUmVzdGFydGVkDQogICAgICAgICAgICBDbGVhbnVwUmVxdWVzdGVkID0gJENsZWFudXAuSXNQcmVzZW50DQogICAgICAgICAgICBDbGVhbnVwT0sgICAgICAgID0gJGNsZWFudXBPSw0KICAgICAgICB9IHwgQ29udmVydFRvLUpzb24gLURlcHRoIDUNCiAgICB9DQogICAgZXhpdCAwDQp9DQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIElOU1RBTEwgLyBVUERBVEUgLyBET1dOR1JBREUNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgRGV0ZXJtaW5lIGRlc2lyZWQgdmVyc2lvbg0KaWYgKCRUYXJnZXRWZXJzaW9uKSB7DQogICAgdHJ5IHsNCiAgICAgICAgJGRlc2lyZWRWZXIgPSBbdmVyc2lvbl0kVGFyZ2V0VmVyc2lvbg0KICAgICAgICAkZGVzaXJlZFJhdyA9ICRUYXJnZXRWZXJzaW9uDQogICAgfQ0KICAgIGNhdGNoIHsNCiAgICAgICAgV3JpdGUtWk9Mb2cgIlRhcmdldFZlcnNpb24gJyRUYXJnZXRWZXJzaW9uJyBpcyBub3QgYSB2YWxpZCB2ZXJzaW9uLiIgIkVSUk9SIg0KICAgICAgICBpZiAoJEpzb24pIHsNCiAgICAgICAgICAgIFtQU0N1c3RvbU9iamVjdF1Aew0KICAgICAgICAgICAgICAgIFN0YXR1cyAgICAgICAgID0gIkludmFsaWRUYXJnZXRWZXJzaW9uIg0KICAgICAgICAgICAgICAgIFRhcmdldFZlcnNpb24gID0gJFRhcmdldFZlcnNpb24NCiAgICAgICAgICAgIH0gfCBDb252ZXJ0VG8tSnNvbiAtRGVwdGggNQ0KICAgICAgICB9DQogICAgICAgIGV4aXQgMQ0KICAgIH0NCiAgICBXcml0ZS1aT0xvZyAiVGFyZ2V0IHZlcnNpb24gICA6ICRkZXNpcmVkUmF3IiAiSU5GTyINCn0NCmVsc2Ugew0KICAgICRkZXNpcmVkVmVyID0gJGxhdGVzdFZlcg0KICAgICRkZXNpcmVkUmF3ID0gJGxhdGVzdFJhdw0KICAgIFdyaXRlLVpPTG9nICJObyBUYXJnZXRWZXJzaW9uIHNwZWNpZmllZDsgdXNpbmcgbGF0ZXN0OiAkZGVzaXJlZFJhdyIgIklORk8iDQp9DQoNCiMgTm8gYWN0aW9uIG5lZWRlZA0KaWYgKCRpbnN0YWxsZWRWZXIgLWFuZCAkZGVzaXJlZFZlciAtZXEgJGluc3RhbGxlZFZlciAtYW5kIC1ub3QgJEZvcmNlKSB7DQogICAgV3JpdGUtWk9Mb2cgIkluc3RhbGxlZCB2ZXJzaW9uIGFscmVhZHkgbWF0Y2hlcyBkZXNpcmVkIHZlcnNpb24gKCRkZXNpcmVkUmF3KS4gTm8gYWN0aW9uIHJlcXVpcmVkLiIgIklORk8iDQogICAgaWYgKCRKc29uKSB7DQogICAgICAgIFtQU0N1c3RvbU9iamVjdF1Aew0KICAgICAgICAgICAgU3RhdHVzICAgICAgICAgICA9ICJVcFRvRGF0ZSINCiAgICAgICAgICAgIEluc3RhbGxlZFZlcnNpb24gPSAkaW5zdGFsbGVkUmF3DQogICAgICAgICAgICBEZXNpcmVkVmVyc2lvbiAgID0gJGRlc2lyZWRSYXcNCiAgICAgICAgICAgIExhdGVzdFZlcnNpb24gICAgPSAkbGF0ZXN0UmF3DQogICAgICAgICAgICBDbGVhbnVwUmVxdWVzdGVkID0gJENsZWFudXAuSXNQcmVzZW50DQogICAgICAgICAgICBDbGVhbnVwT0sgICAgICAgID0gJGNsZWFudXBPSw0KICAgICAgICB9IHwgQ29udmVydFRvLUpzb24gLURlcHRoIDUNCiAgICB9DQogICAgZXhpdCAwDQp9DQoNCiMgRG93bmdyYWRlIGRldGVjdGlvbg0KJGRvd25ncmFkZSA9ICRmYWxzZQ0KaWYgKCRpbnN0YWxsZWRWZXIgLWFuZCAkZGVzaXJlZFZlciAtbHQgJGluc3RhbGxlZFZlcikgew0KICAgICRkb3duZ3JhZGUgPSAkdHJ1ZQ0KICAgIFdyaXRlLVpPTG9nICJSZXF1ZXN0ZWQgdmVyc2lvbiAoJGRlc2lyZWRSYXcpIGlzIGxvd2VyIHRoYW4gaW5zdGFsbGVkIHZlcnNpb24gKCRpbnN0YWxsZWRSYXcpLiBEb3duZ3JhZGUgd2lsbCB1bmluc3RhbGwgZmlyc3QuIiAiV0FSTiINCn0NCg0KIyBSZXNvbHZlIGRvd25sb2FkIFVSTHMgdmlhIEdpdEh1YiBBUEkNCnRyeSB7DQogICAgJHVybHMgPSBHZXQtWk9TbWFydG1vbnRvb2xzRG93bmxvYWRVcmxzIC1WZXJzaW9uICRkZXNpcmVkUmF3DQp9DQpjYXRjaCB7DQogICAgV3JpdGUtWk9Mb2cgIkZhaWxlZCB0byByZXNvbHZlIGRvd25sb2FkIFVSTHMgZm9yIHZlcnNpb24gJyRkZXNpcmVkUmF3JzogJCgkXy5FeGNlcHRpb24uTWVzc2FnZSkiICJFUlJPUiINCiAgICBpZiAoJEpzb24pIHsNCiAgICAgICAgW1BTQ3VzdG9tT2JqZWN0XUB7DQogICAgICAgICAgICBTdGF0dXMgICAgICAgICA9ICJVcmxSZXNvbHV0aW9uRmFpbGVkIg0KICAgICAgICAgICAgRGVzaXJlZFZlcnNpb24gPSAkZGVzaXJlZFJhdw0KICAgICAgICAgICAgTGF0ZXN0VmVyc2lvbiAgPSAkbGF0ZXN0UmF3DQogICAgICAgIH0gfCBDb252ZXJ0VG8tSnNvbiAtRGVwdGggNQ0KICAgIH0NCiAgICBleGl0IDENCn0NCg0KIyBEb3duZ3JhZGUgdW5pbnN0YWxsDQppZiAoJGRvd25ncmFkZSkgew0KICAgICR1bmluc3RhbGxPSyA9IFVuaW5zdGFsbC1aT1NtYXJ0bW9udG9vbHMNCiAgICBpZiAoLW5vdCAkdW5pbnN0YWxsT0spIHsNCiAgICAgICAgaWYgKCRKc29uKSB7DQogICAgICAgICAgICBbUFNDdXN0b21PYmplY3RdQHsNCiAgICAgICAgICAgICAgICBTdGF0dXMgICAgICAgICAgID0gIkRvd25ncmFkZVVuaW5zdGFsbEZhaWxlZCINCiAgICAgICAgICAgICAgICBPbGRWZXJzaW9uICAgICAgID0gJGluc3RhbGxlZFJhdw0KICAgICAgICAgICAgICAgIERlc2lyZWRWZXJzaW9uICAgPSAkZGVzaXJlZFJhdw0KICAgICAgICAgICAgICAgIExhdGVzdFZlcnNpb24gICAgPSAkbGF0ZXN0UmF3DQogICAgICAgICAgICAgICAgQ2xlYW51cFJlcXVlc3RlZCA9ICRDbGVhbnVwLklzUHJlc2VudA0KICAgICAgICAgICAgICAgIENsZWFudXBPSyAgICAgICAgPSAkY2xlYW51cE9LDQogICAgICAgICAgICB9IHwgQ29udmVydFRvLUpzb24gLURlcHRoIDUNCiAgICAgICAgfQ0KICAgICAgICBleGl0IDENCiAgICB9DQp9DQoNCiMgRG93bmxvYWQgaW5zdGFsbGVyDQppZiAoLW5vdCAoSW52b2tlLVpPV2ViUmVxdWVzdCAtVXJsICR1cmxzLkluc3RhbGxlciAtT3V0RmlsZSAkaW5zdGFsbGVyUGF0aCkpIHsNCiAgICBpZiAoJEpzb24pIHsNCiAgICAgICAgW1BTQ3VzdG9tT2JqZWN0XUB7DQogICAgICAgICAgICBTdGF0dXMgICAgICAgICAgID0gIkluc3RhbGxlckRvd25sb2FkRmFpbGVkIg0KICAgICAgICAgICAgRGVzaXJlZFZlcnNpb24gICA9ICRkZXNpcmVkUmF3DQogICAgICAgICAgICBMYXRlc3RWZXJzaW9uICAgID0gJGxhdGVzdFJhdw0KICAgICAgICAgICAgQ2xlYW51cFJlcXVlc3RlZCA9ICRDbGVhbnVwLklzUHJlc2VudA0KICAgICAgICAgICAgQ2xlYW51cE9LICAgICAgICA9ICRjbGVhbnVwT0sNCiAgICAgICAgfSB8IENvbnZlcnRUby1Kc29uIC1EZXB0aCA1DQogICAgfQ0KICAgIGV4aXQgMQ0KfQ0KDQojIERvd25sb2FkIE1ENQ0KaWYgKC1ub3QgKEludm9rZS1aT1dlYlJlcXVlc3QgLVVybCAkdXJscy5NZDUgLU91dEZpbGUgJG1kNVBhdGgpKSB7DQogICAgaWYgKCRKc29uKSB7DQogICAgICAgIFtQU0N1c3RvbU9iamVjdF1Aew0KICAgICAgICAgICAgU3RhdHVzICAgICAgICAgICA9ICJNZDVEb3dubG9hZEZhaWxlZCINCiAgICAgICAgICAgIERlc2lyZWRWZXJzaW9uICAgPSAkZGVzaXJlZFJhdw0KICAgICAgICAgICAgTGF0ZXN0VmVyc2lvbiAgICA9ICRsYXRlc3RSYXcNCiAgICAgICAgICAgIENsZWFudXBSZXF1ZXN0ZWQgPSAkQ2xlYW51cC5Jc1ByZXNlbnQNCiAgICAgICAgICAgIENsZWFudXBPSyAgICAgICAgPSAkY2xlYW51cE9LDQogICAgICAgIH0gfCBDb252ZXJ0VG8tSnNvbiAtRGVwdGggNQ0KICAgIH0NCiAgICBleGl0IDENCn0NCg0KIyBSZW1vdmUgTU9UVw0KdHJ5IHsNCiAgICBVbmJsb2NrLUZpbGUgLVBhdGggJGluc3RhbGxlclBhdGgNCiAgICBXcml0ZS1aT0xvZyAiUmVtb3ZlZCBNYXJrLW9mLXRoZS1XZWIgZnJvbSBpbnN0YWxsZXIuIiAiSU5GTyINCn0NCmNhdGNoIHsNCiAgICBXcml0ZS1aT0xvZyAiRmFpbGVkIHRvIHJlbW92ZSBNT1RXOiAkKCRfLkV4Y2VwdGlvbi5NZXNzYWdlKSIgIldBUk4iDQp9DQoNCiMgTUQ1IHZhbGlkYXRpb24NCnRyeSB7DQogICAgJGV4cGVjdGVkID0gKEdldC1Db250ZW50ICRtZDVQYXRoKS5TcGxpdCgiICIpWzBdLlRyaW0oKQ0KICAgICRhY3R1YWwgICA9IChHZXQtRmlsZUhhc2ggLVBhdGggJGluc3RhbGxlclBhdGggLUFsZ29yaXRobSBNRDUpLkhhc2guVG9Mb3dlcigpDQoNCiAgICBpZiAoJGV4cGVjdGVkIC1uZSAkYWN0dWFsKSB7DQogICAgICAgIFdyaXRlLVpPTG9nICJNRDUgY2hlY2tzdW0gbWlzbWF0Y2guIEV4cGVjdGVkOiAkZXhwZWN0ZWQsIEFjdHVhbDogJGFjdHVhbC4gQWJvcnRpbmcuIiAiRVJST1IiDQogICAgICAgIGlmICgkSnNvbikgew0KICAgICAgICAgICAgW1BTQ3VzdG9tT2JqZWN0XUB7DQogICAgICAgICAgICAgICAgU3RhdHVzICAgICAgICAgICA9ICJNZDVNaXNtYXRjaCINCiAgICAgICAgICAgICAgICBEZXNpcmVkVmVyc2lvbiAgID0gJGRlc2lyZWRSYXcNCiAgICAgICAgICAgICAgICBMYXRlc3RWZXJzaW9uICAgID0gJGxhdGVzdFJhdw0KICAgICAgICAgICAgICAgIENsZWFudXBSZXF1ZXN0ZWQgPSAkQ2xlYW51cC5Jc1ByZXNlbnQNCiAgICAgICAgICAgICAgICBDbGVhbnVwT0sgICAgICAgID0gJGNsZWFudXBPSw0KICAgICAgICAgICAgfSB8IENvbnZlcnRUby1Kc29uIC1EZXB0aCA1DQogICAgICAgIH0NCiAgICAgICAgZXhpdCAxDQogICAgfQ0KDQogICAgV3JpdGUtWk9Mb2cgIk1ENSBjaGVja3N1bSB2YWxpZGF0ZWQgc3VjY2Vzc2Z1bGx5LiIgIklORk8iDQp9DQpjYXRjaCB7DQogICAgV3JpdGUtWk9Mb2cgIk1ENSB2YWxpZGF0aW9uIGZhaWxlZDogJCgkXy5FeGNlcHRpb24uTWVzc2FnZSkiICJFUlJPUiINCiAgICBpZiAoJEpzb24pIHsNCiAgICAgICAgW1BTQ3VzdG9tT2JqZWN0XUB7DQogICAgICAgICAgICBTdGF0dXMgICAgICAgICAgID0gIk1kNVZhbGlkYXRpb25GYWlsZWQiDQogICAgICAgICAgICBEZXNpcmVkVmVyc2lvbiAgID0gJGRlc2lyZWRSYXcNCiAgICAgICAgICAgIExhdGVzdFZlcnNpb24gICAgPSAkbGF0ZXN0UmF3DQogICAgICAgICAgICBDbGVhbnVwUmVxdWVzdGVkID0gJENsZWFudXAuSXNQcmVzZW50DQogICAgICAgICAgICBDbGVhbnVwT0sgICAgICAgID0gJGNsZWFudXBPSw0KICAgICAgICB9IHwgQ29udmVydFRvLUpzb24gLURlcHRoIDUNCiAgICB9DQogICAgZXhpdCAxDQp9DQoNCiMgUnVuIGluc3RhbGxlcg0KaWYgKCRQU0NtZGxldC5TaG91bGRQcm9jZXNzKCJzbWFydG1vbnRvb2xzICRkZXNpcmVkUmF3IiwgIkluc3RhbGwvVXBkYXRlIikpIHsNCiAgICBXcml0ZS1aT0xvZyAiUnVubmluZyBzaWxlbnQgaW5zdGFsbGVyIGZvciB2ZXJzaW9uICRkZXNpcmVkUmF3Li4uIiAiSU5GTyINCg0KICAgIHRyeSB7DQogICAgICAgICRwcm9jID0gU3RhcnQtUHJvY2VzcyAtRmlsZVBhdGggJGluc3RhbGxlclBhdGggYA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLUFyZ3VtZW50TGlzdCAiL1MiIGANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC1XYWl0IGANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC1QYXNzVGhydSBgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtUmVkaXJlY3RTdGFuZGFyZE91dHB1dCAkc3Rkb3V0UGF0aCBgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtUmVkaXJlY3RTdGFuZGFyZEVycm9yICAkc3RkZXJyUGF0aA0KDQogICAgICAgICRpbnN0YWxsZXJFeGl0Q29kZSA9ICRwcm9jLkV4aXRDb2RlDQoNCiAgICAgICAgaWYgKFRlc3QtUGF0aCAkc3Rkb3V0UGF0aCkgew0KICAgICAgICAgICAgR2V0LUNvbnRlbnQgJHN0ZG91dFBhdGggfCBGb3JFYWNoLU9iamVjdCB7IFdyaXRlLVpPTG9nICRfICJJTkZPIiB9DQogICAgICAgIH0NCiAgICAgICAgaWYgKFRlc3QtUGF0aCAkc3RkZXJyUGF0aCkgew0KICAgICAgICAgICAgR2V0LUNvbnRlbnQgJHN0ZGVyclBhdGggfCBGb3JFYWNoLU9iamVjdCB7IFdyaXRlLVpPTG9nICRfICJFUlJPUiIgfQ0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKCRpbnN0YWxsZXJFeGl0Q29kZSAtbmUgMCAtYW5kICRpbnN0YWxsZXJFeGl0Q29kZSAtbmUgMzAxMCkgew0KICAgICAgICAgICAgV3JpdGUtWk9Mb2cgIkluc3RhbGxlciByZXR1cm5lZCBleGl0IGNvZGUgJGluc3RhbGxlckV4aXRDb2RlIiAiRVJST1IiDQogICAgICAgICAgICBpZiAoJEpzb24pIHsNCiAgICAgICAgICAgICAgICBbUFNDdXN0b21PYmplY3RdQHsNCiAgICAgICAgICAgICAgICAgICAgU3RhdHVzICAgICAgICAgICAgPSAiSW5zdGFsbEZhaWxlZCINCiAgICAgICAgICAgICAgICAgICAgT2xkVmVyc2lvbiAgICAgICAgPSAkaW5zdGFsbGVkUmF3DQogICAgICAgICAgICAgICAgICAgIERlc2lyZWRWZXJzaW9uICAgID0gJGRlc2lyZWRSYXcNCiAgICAgICAgICAgICAgICAgICAgTGF0ZXN0VmVyc2lvbiAgICAgPSAkbGF0ZXN0UmF3DQogICAgICAgICAgICAgICAgICAgIEluc3RhbGxlckV4aXRDb2RlID0gJGluc3RhbGxlckV4aXRDb2RlDQogICAgICAgICAgICAgICAgICAgIFJlYm9vdFJlcXVpcmVkICAgID0gJGZhbHNlDQogICAgICAgICAgICAgICAgICAgIENsZWFudXBSZXF1ZXN0ZWQgID0gJENsZWFudXAuSXNQcmVzZW50DQogICAgICAgICAgICAgICAgICAgIENsZWFudXBPSyAgICAgICAgID0gJGNsZWFudXBPSw0KICAgICAgICAgICAgICAgIH0gfCBDb252ZXJ0VG8tSnNvbiAtRGVwdGggNQ0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgZXhpdCAkaW5zdGFsbGVyRXhpdENvZGUNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICgkaW5zdGFsbGVyRXhpdENvZGUgLWVxIDMwMTApIHsNCiAgICAgICAgICAgIFdyaXRlLVpPTG9nICJJbnN0YWxsZXIgaW5kaWNhdGVzIHJlYm9vdCByZXF1aXJlZCAoMzAxMCkuIiAiV0FSTiINCiAgICAgICAgICAgICRyZWJvb3RSZXF1aXJlZCA9ICR0cnVlDQogICAgICAgIH0NCg0KICAgICAgICBXcml0ZS1aT0xvZyAiSW5zdGFsbGF0aW9uIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHkuIiAiSU5GTyINCiAgICB9DQogICAgY2F0Y2ggew0KICAgICAgICBXcml0ZS1aT0xvZyAiSW5zdGFsbGVyIGV4ZWN1dGlvbiBmYWlsZWQ6ICQoJF8uRXhjZXB0aW9uLk1lc3NhZ2UpIiAiRVJST1IiDQogICAgICAgIGlmICgkSnNvbikgew0KICAgICAgICAgICAgW1BTQ3VzdG9tT2JqZWN0XUB7DQogICAgICAgICAgICAgICAgU3RhdHVzICAgICAgICAgICA9ICJJbnN0YWxsZXJFeGVjdXRpb25GYWlsZWQiDQogICAgICAgICAgICAgICAgT2xkVmVyc2lvbiAgICAgICA9ICRpbnN0YWxsZWRSYXcNCiAgICAgICAgICAgICAgICBEZXNpcmVkVmVyc2lvbiAgID0gJGRlc2lyZWRSYXcNCiAgICAgICAgICAgICAgICBMYXRlc3RWZXJzaW9uICAgID0gJGxhdGVzdFJhdw0KICAgICAgICAgICAgICAgIENsZWFudXBSZXF1ZXN0ZWQgPSAkQ2xlYW51cC5Jc1ByZXNlbnQNCiAgICAgICAgICAgICAgICBDbGVhbnVwT0sgICAgICAgID0gJGNsZWFudXBPSw0KICAgICAgICAgICAgfSB8IENvbnZlcnRUby1Kc29uIC1EZXB0aCA1DQogICAgICAgIH0NCiAgICAgICAgZXhpdCAxDQogICAgfQ0KfQ0KDQojIFF1ZXJ5IG5ldyB2ZXJzaW9uDQokbmV3UmF3ID0gR2V0LVpPU21hcnRtb250b29sc0luc3RhbGxlZFZlcnNpb24NCldyaXRlLVpPTG9nICJOZXcgaW5zdGFsbGVkIHZlcnNpb246ICRuZXdSYXciICJJTkZPIg0KDQojIFJlc3RhcnQgc2VydmljZSBpZiByZXF1ZXN0ZWQNCmlmICgkUmVzdGFydFNlcnZpY2VOYW1lKSB7DQogICAgJHNlcnZpY2VSZXN0YXJ0ZWQgPSBSZXN0YXJ0LVpPU2VydmljZSAtTmFtZSAkUmVzdGFydFNlcnZpY2VOYW1lDQogICAgaWYgKC1ub3QgJHNlcnZpY2VSZXN0YXJ0ZWQpIHsNCiAgICAgICAgaWYgKCRKc29uKSB7DQogICAgICAgICAgICBbUFNDdXN0b21PYmplY3RdQHsNCiAgICAgICAgICAgICAgICBTdGF0dXMgICAgICAgICAgICA9ICJJbnN0YWxsZWQiDQogICAgICAgICAgICAgICAgT2xkVmVyc2lvbiAgICAgICAgPSAkaW5zdGFsbGVkUmF3DQogICAgICAgICAgICAgICAgTmV3VmVyc2lvbiAgICAgICAgPSAkbmV3UmF3DQogICAgICAgICAgICAgICAgRGVzaXJlZFZlcnNpb24gICAgPSAkZGVzaXJlZFJhdw0KICAgICAgICAgICAgICAgIExhdGVzdFZlcnNpb24gICAgID0gJGxhdGVzdFJhdw0KICAgICAgICAgICAgICAgIERvd25ncmFkZSAgICAgICAgID0gJGRvd25ncmFkZQ0KICAgICAgICAgICAgICAgIFNlcnZpY2VSZXN0YXJ0ZWQgID0gJFJlc3RhcnRTZXJ2aWNlTmFtZQ0KICAgICAgICAgICAgICAgIFNlcnZpY2VSZXN0YXJ0T0sgID0gJHNlcnZpY2VSZXN0YXJ0ZWQNCiAgICAgICAgICAgICAgICBJbnN0YWxsZXJFeGl0Q29kZSA9ICRpbnN0YWxsZXJFeGl0Q29kZQ0KICAgICAgICAgICAgICAgIFJlYm9vdFJlcXVpcmVkICAgID0gJHJlYm9vdFJlcXVpcmVkDQogICAgICAgICAgICAgICAgQ2xlYW51cFJlcXVlc3RlZCAgPSAkQ2xlYW51cC5Jc1ByZXNlbnQNCiAgICAgICAgICAgICAgICBDbGVhbnVwT0sgICAgICAgICA9ICRjbGVhbnVwT0sNCiAgICAgICAgICAgIH0gfCBDb252ZXJ0VG8tSnNvbiAtRGVwdGggNQ0KICAgICAgICB9DQogICAgICAgIGV4aXQgMQ0KICAgIH0NCn0NCg0KIyBDbGVhbnVwDQppZiAoJENsZWFudXApIHsNCiAgICAkY2xlYW51cE9LID0gKA0KICAgICAgICAoUmVtb3ZlLVpPVGVtcEZpbGUgLVBhdGggJGluc3RhbGxlclBhdGgpIC1hbmQNCiAgICAgICAgKFJlbW92ZS1aT1RlbXBGaWxlIC1QYXRoICRtZDVQYXRoKSAtYW5kDQogICAgICAgIChSZW1vdmUtWk9UZW1wRmlsZSAtUGF0aCAkc3Rkb3V0UGF0aCkgLWFuZA0KICAgICAgICAoUmVtb3ZlLVpPVGVtcEZpbGUgLVBhdGggJHN0ZGVyclBhdGgpDQogICAgKQ0KfQ0KDQojIEpTT04gb3V0cHV0DQppZiAoJEpzb24pIHsNCiAgICBbUFNDdXN0b21PYmplY3RdQHsNCiAgICAgICAgU3RhdHVzICAgICAgICAgICAgPSAiSW5zdGFsbGVkIg0KICAgICAgICBPbGRWZXJzaW9uICAgICAgICA9ICRpbnN0YWxsZWRSYXcNCiAgICAgICAgTmV3VmVyc2lvbiAgICAgICAgPSAkbmV3UmF3DQogICAgICAgIERlc2lyZWRWZXJzaW9uICAgID0gJGRlc2lyZWRSYXcNCiAgICAgICAgTGF0ZXN0VmVyc2lvbiAgICAgPSAkbGF0ZXN0UmF3DQogICAgICAgIERvd25ncmFkZSAgICAgICAgID0gJGRvd25ncmFkZQ0KICAgICAgICBTZXJ2aWNlUmVzdGFydGVkICA9ICRSZXN0YXJ0U2VydmljZU5hbWUNCiAgICAgICAgU2VydmljZVJlc3RhcnRPSyAgPSAkc2VydmljZVJlc3RhcnRlZA0KICAgICAgICBJbnN0YWxsZXJFeGl0Q29kZSA9ICRpbnN0YWxsZXJFeGl0Q29kZQ0KICAgICAgICBSZWJvb3RSZXF1aXJlZCAgICA9ICRyZWJvb3RSZXF1aXJlZA0KICAgICAgICBDbGVhbnVwUmVxdWVzdGVkICA9ICRDbGVhbnVwLklzUHJlc2VudA0KICAgICAgICBDbGVhbnVwT0sgICAgICAgICA9ICRjbGVhbnVwT0sNCiAgICB9IHwgQ29udmVydFRvLUpzb24gLURlcHRoIDUNCn0NCg0KIyBFeGl0IGNvZGUgcHJvcGFnYXRpb24NCmlmICgkaW5zdGFsbGVyRXhpdENvZGUgLW5lIDAgLWFuZCAkaW5zdGFsbGVyRXhpdENvZGUgLW5lIDMwMTApIHsNCiAgICBleGl0ICRpbnN0YWxsZXJFeGl0Q29kZQ0KfQ0KDQpleGl0IDA="
[IO.File]::WriteAllBytes($scriptPath, [Convert]::FromBase64String($base64))
# Execute original script
& $scriptPath @callArgs
exit $LASTEXITCODE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment