# Copyright 2019-2022 ActiveState Software Inc. All rights reserved. <# .EXAMPLE install.ps1 -b branchToInstall #> Set-StrictMode -Off # URL to fetch update infos from. $script:BASEINFOURL = "https://platform.activestate.com/sv/state-update/api/v1/info" # URL to fetch installer archive from $script:BASEFILEURL = "https://state-tool.s3.amazonaws.com/update/state" # The name of the remove archive to download $script:ARCHIVENAME = "state-installer.zip" # Name of the installer executable to ultimately use $script:INSTALLERNAME = "state-install\\state-installer.exe" # Channel the installer will target $script:CHANNEL = "release" # The version to install (autodetermined to be the latest if left unspecified) $script:VERSION = "" $script:SESSION_TOKEN_VERIFY = -join ("{", "TOKEN", "}") $script:SESSION_TOKEN = "316148410.1693229451_pdli01" $script:SESSION_TOKEN_VALUE = "" if ("$SESSION_TOKEN" -ne "$SESSION_TOKEN_VERIFY") { $script:SESSION_TOKEN_VALUE = $script:SESSION_TOKEN } function getopt([string] $opt, [string] $default, [string[]] $arr) { for ($i = 0; $i -le $arr.Length; $i++) { $arg = $arr[$i] if ($arg -eq $opt -and $arr.Length -ge ($i + 2)) { return $arr[$i + 1] } } return $default } # Collect all instances of a flag (for flags that can appear multiple times) function getopt_all([string] $opt, [string[]] $arr) { $result = @() for ($i = 0; $i -lt $arr.Length; $i++) { $arg = $arr[$i] if ($arg -eq $opt -and ($i + 1) -lt $arr.Length) { $value = $arr[$i + 1] if ($value -and -not $value.StartsWith("-")) { $result += $opt $result += $value } } } return $result } $script:CHANNEL = getopt "-b" $script:CHANNEL $args $script:VERSION = getopt "-v" $script:VERSION $args $script:CONFIG_SET_ARGS = getopt_all "--config-set" $args function download([string] $url, [string] $out) { [int]$Retrycount = "0" do { try { $downloader = New-Object System.Net.WebClient if ($out -eq "") { return $downloader.DownloadString($url) } else { return $downloader.DownloadFile($url, $out) } } catch { if ($Retrycount -gt 5) { $exception = $_.Exception $errorMessage = "" if ($exception -is [System.Management.Automation.MethodInvocationException] -and $exception.InnerException -is [System.Net.WebException]) { $webException = [System.Net.WebException]$exception.InnerException $response = $webException.Response if ($response -ne $null) { $responseStream = $response.GetResponseStream() $reader = New-Object System.IO.StreamReader($responseStream) $responseBody = $reader.ReadToEnd() $reader.Close() $responseStream.Close() try { $errorMessage = (ConvertFrom-Json $responseBody).message } catch { $errorMessage = $responseBody } } else { $errorMessage = $webException.Message } } else { $errorMessage = $exception.Message } Write-Error "Could not download after 5 retries. Received error: $errorMessage" throw $exception } else { Write-Host "Could not download, retrying..." $Retrycount = $Retrycount + 1 } } } While ($true) } function tempDir() { $parent = [System.IO.Path]::GetTempPath() [string]$name = [System.Guid]::NewGuid() New-Item -ItemType Directory -Path (Join-Path $parent $name) } function progress([string] $msg) { Write-Host "• $msg..." -NoNewline } function progress_done() { $greenCheck = @{ Object = [Char]8730 ForegroundColor = 'Green' NoNewLine = $true } Write-Host @greenCheck Write-Host ' Done' -ForegroundColor Green } function progress_fail() { Write-Host 'x Failed' -ForegroundColor Red } function error([string] $msg) { Write-Host $msg -ForegroundColor Red } function setShellOverride { # Walk up the process tree to find cmd.exe # If we encounter it we set the shell override $currentPid = $PID while ($currentPid -ne 0) { $process = Get-CimInstance Win32_Process | Where-Object { $_.ProcessId -eq $currentPid } if (!$process) { break } if ($process.Name -eq "cmd" -or $process.Name -eq "cmd.exe") { [System.Environment]::SetEnvironmentVariable("ACTIVESTATE_CLI_SHELL_OVERRIDE", $process.Name, "Process") break } $currentPid = $process.ParentProcessId } } $version = $script:VERSION if (!$version) { # If the user did not specify a version, formulate a query to fetch the JSON info of the latest # version, including where it is. $jsonURL = "$script:BASEINFOURL/?channel=$script:CHANNEL&platform=windows&source=install" } elseif (!($version | Select-String -Pattern "-SHA" -SimpleMatch)) { # If the user specified a partial version (i.e. no SHA), formulate a query to fetch the JSON # info of that version's latest SHA, including where it is. $versionNoSHA = $version $version = "" $jsonURL = "$script:BASEINFOURL/?channel=$script:CHANNEL&platform=windows&source=install&target-version=$versionNoSHA" } else { # If the user specified a full version with SHA, formulate a query to fetch the JSON info of # that version. $versionNoSHA = $version -replace "-SHA.*", "" $jsonURL = "$script:BASEINFOURL/?channel=$script:CHANNEL&platform=windows&source=install&target-version=$versionNoSHA" } # Fetch version info. try { $infoJson = ConvertFrom-Json -InputObject (download $jsonURL) } catch [System.Exception] { } if (!$infoJson) { if (!$version) { Write-Error "Unable to retrieve the latest version number" } else { Write-Error "Could not download a State Tool Installer for the given command line arguments" } Write-Error $_.Exception.Message exit 1 } # Extract checksum. $checksum = $infoJson.Sha256 if (!$version) { # If the user specified no version or a partial version we need to use the json URL to get the # actual installer URL. $version = $infoJson.Version $relUrl = $infoJson.Path } else { # If the user specified a full version, construct the installer URL. if ($version -ne $infoJson.Version) { Write-Error "Unknown version: $version" exit 1 } $relUrl = "$script:CHANNEL/$versionNoSHA/windows-amd64/state-windows-amd64-$version.zip" } # Fetch the requested or latest version. progress "Preparing Installer for State Tool Package Manager version $version" $zipURL = "$script:BASEFILEURL/$relUrl" $tmpParentPath = tempDir $zipPath = Join-Path $tmpParentPath $script:ARCHIVENAME $exePath = Join-Path $tmpParentPath $script:INSTALLERNAME try { download $zipURL $zipPath } catch [System.Exception] { progress_fail Write-Error "Could not download $zipURL to $zipPath." Write-Error $_.Exception.Message exit 1 } # Verify checksum. $hash = (Get-FileHash -Path $zipPath -Algorithm SHA256).Hash if ($hash -ne $checksum) { Write-Warning "SHA256 sum did not match:" Write-Warning "Expected: $checksum" Write-Warning "Received: $hash" Write-Warning "Aborting installation" exit 1 } # Extract it. try { Expand-Archive -ErrorAction Stop -LiteralPath $zipPath -DestinationPath $tmpParentPath } catch { progress_fail Write-Error $_.Exception.Message exit 1 } progress_done Write-Host "" $OutputEncoding = [System.Console]::OutputEncoding = [System.Console]::InputEncoding = [System.Text.Encoding]::UTF8 $PSDefaultParameterValues['*:Encoding'] = 'utf8' [System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 # Run the installer. $env:ACTIVESTATE_SESSION_TOKEN = $script:SESSION_TOKEN_VALUE setShellOverride # Build installer arguments by reconstructing the command line properly $cmdArgs = @() # Add non-config-set arguments first for ($i = 0; $i -lt $args.Length; $i++) { if ($args[$i] -eq "--config-set" -and ($i + 1) -lt $args.Length) { # Skip the --config-set flag and its value, we'll add them back from our processed array $i++ # Skip the value too } else { $cmdArgs += $args[$i] } } # Add the processed config-set arguments (pass through without comma splitting - let Go handle it) if ($script:CONFIG_SET_ARGS -and $script:CONFIG_SET_ARGS.Length -gt 0) { $cmdArgs += $script:CONFIG_SET_ARGS } # Add the source installer flag $cmdArgs += "--source-installer=install.ps1" # Execute with the properly constructed arguments & $exePath @cmdArgs $success = $? if (Test-Path env:ACTIVESTATE_SESSION_TOKEN) { Remove-Item Env:\ACTIVESTATE_SESSION_TOKEN } if ( !$success ) { exit 1 } # SIG # Begin signature block # MIIi/gYJKoZIhvcNAQcCoIIi7zCCIusCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBLCnVkjLQrvNzD # O170MxUzlzcP7n6uBvWIkX8pVET5qaCCBlswggZXMIIEv6ADAgECAhARwXFMm4li # uuLk+UpCCdQOMA0GCSqGSIb3DQEBDAUAMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQK # Ew9TZWN0aWdvIExpbWl0ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUg # U2lnbmluZyBDQSBSMzYwHhcNMjUwNjAyMDAwMDAwWhcNMjgwNjAxMjM1OTU5WjBu # MQswCQYDVQQGEwJDQTEZMBcGA1UECAwQQnJpdGlzaCBDb2x1bWJpYTEhMB8GA1UE # CgwYQWN0aXZlU3RhdGUgU29mdHdhcmUgSW5jMSEwHwYDVQQDDBhBY3RpdmVTdGF0 # ZSBTb2Z0d2FyZSBJbmMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCu # ZxBAy/JV6Iyo21ZrP4Ta8oqZlSkOahdWEQiNsEL+obckTuIFTv2u1kSAtwvPMNKG # hfEm9kvyAtLLT1Ayup6XB8koI9TVSwHfDnTBph5Y8DiPAue1Nf38KO6fIf9c/x0Z # ZTbYvYXLNY4Rs+QAtDd+Eqygt4k1ZNQDCBRSp8Iz6sJksPeB1vyse8I1go8bytjW # hkG/jvPATsBAeaXD+in1yVl+9vEKam2PWIZvmHtjvgcflBfVLSRkGn1rYulW9EEI # AoLJzKdDXKD1i/IT8aGVfWcg7PfnFtj8NYpDCePcjggmyZyKu7eGPVzJMT9Nnisa # JFksgaeRlMocK76xWVOHDApGNd3uju4bqzWP/3OXk7tK0ST69uefNFsGw8RwcUaw # XRfMa91SkXur3l2UQOF7k0IMkVSOErBaU523JxkwdEH+7+0ExGyw7763cDLtCgMv # azSRk4txiLOWqx4kooaknynRG+8YoRWZ6WCm3zJvLn/SuGkKKdjrM9MZW9dud+5Q # 8+n+uE14uK+ur9fc170BBmColEN1k9MRg1XqmOJl3bpEGONEHAwocdirV324uVlF # SFF4w/yK7O00DyMc4IeXNdHB9PjLj2fg+rJ1v8VLVYoXW2+4kfwXsxGoJZDfQRzM # edj86bNXahGu4O0/eoOztC7lahaPfPWQ7qJFPuQnEwIDAQABo4IBiTCCAYUwHwYD # VR0jBBgwFoAUDyrLIIcouOxvSK4rVKYpqhekzQwwHQYDVR0OBBYEFGs9v+sH94bC # unz7iDCZ+6pSAURRMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMGA1Ud # JQQMMAoGCCsGAQUFBwMDMEoGA1UdIARDMEEwNQYMKwYBBAGyMQECAQMCMCUwIwYI # KwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMAgGBmeBDAEEATBJBgNV # HR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJs # aWNDb2RlU2lnbmluZ0NBUjM2LmNybDB5BggrBgEFBQcBAQRtMGswRAYIKwYBBQUH # MAKGOGh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWdu # aW5nQ0FSMzYuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNv # bTANBgkqhkiG9w0BAQwFAAOCAYEAPHvJ97QLuaNwEs9/nP7+BIuJ69ys5SUBIOhY # Q7apVEw2e3LX2zRTURS3kZ7kOPO49FS+EeYAuj0Cp8epwlqK33CCgzm1WO+vNMED # xw6Lw2bO/4LlhqzGVH90L41GTffeIxtt9xqGnvaVuXnH6e5/zHtB+uhDvvHgg/NE # zmn0L6sE5ujxm5fpp3VSzaCRv5RzjmZyO56m1P2fvY9fTt+jR89PwjidQSa5llmw # nbju2NW/7c2VFoXHbm7X90NLlWpCXcvezzHh7OQBAf3lHPVkDtCBn/QPx8ZVAGrZ # 5KosA/7kpkaqkVJolK026fUgKEMa2XS9txnLjinj136m3aUEzAaoZeeI3YfL1ok4 # RNuLkeEeT3wcRPKIctscx4gF59MT4HT1/gketw/7yRsChspCu9pCnvdM7Uvici+9 # w5m+v/TUCRJOMc1IMIVuFZN843MPxVs0gjb+c8Ztt8OljSCDpAsDSUXIXUjkHCdx # xjJ1jsvmXbCC01UcTIoS/FmJbJH8MYIb+TCCG/UCAQEwaDBUMQswCQYDVQQGEwJH # QjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1 # YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2AhARwXFMm4liuuLk+UpCCdQOMA0GCWCG # SAFlAwQCAQUAoIGIMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCSqGSIb3 # DQEJBTEPFw0yNTA5MTgxODA0MTVaMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3 # AgEVMC8GCSqGSIb3DQEJBDEiBCDMf7mz297QXZJhTerqBf3KTV6kJ37Li4ThvB+c # 6kZs/jANBgkqhkiG9w0BAQEFAASCAgAXdm+uejtmlH6BBAzwjZUhEPttMuDgMqAc # uYEUYtND9QbrljSHnhaX45R5fH8THL4OOrSFW1EeiHq9Scf3qTWGTF2g36Tg1XLZ # B3YOKK6SSF1HoNsg9dodmHrfJjKY7f6FgdH4bwxk/pQ8qdEqzpOcd8IzXXGRX7ha # F5H7Ctw7M+X28VLeHCKmNFS5rn0rTA9rZzeJBEUq6aYYPIzC3PczGJiOYRn46bry # 4975HE1xLDW+3xwEkMlNAdWaKEkm4gs6ROzAw7Onhsgt9yDqaJT1ycdWREnqgMV6 # ZymAWZOnk+KhuvpdlD3uQ2gpwjytuFru8TZZhDTqzy9TRgK2h7Siiv0vVwGhbtAO # f5wBi3bDfFcRtDhiiN8qkrGOP5Y5HA87q112YVbqe1qJ2BJUjcrChUiJkvtI1JMY # IqYZ3Pu0rnFtSuCuUk4Cpg2ty1kRsRfOtxtbw1bjGazUF/fz4U1eFY5wp1mQwzSd # JtNf1iT/vi1fWitah4i/cpW48Xtow9WJDGO1wIc8/iM0UB2xVHgdNySxSMlTeopy # hBfDSp0IW9gNfe8Y+2jAkTKpbAyVBxk1xMcd1g0LOLHQ0UUlp1v6jLesYfoyG3TC # NsbfItsiSrHQyG+8uAA4GYY7dFEGB7m5zeLzZmajpqmPgbnnHJgbDw8rYXs2J3O/ # fMGPl+3tXKGCGNcwghjTBgorBgEEAYI3AwMBMYIYwzCCGL8GCSqGSIb3DQEHAqCC # GLAwghisAgEDMQ8wDQYJYIZIAWUDBAICBQAwgfcGCyqGSIb3DQEJEAEEoIHnBIHk # MIHhAgEBBgorBgEEAbIxAgEBMDEwDQYJYIZIAWUDBAIBBQAEIPu4cETQpq0AWeCz # eZ4IRq3jLWqpEEVvlsiV0c6QUvZDAhRW95ZL4JZK/rw7Gt6YlVCu9EhkvBgPMjAy # NTA5MTgxODA0MTZaoHakdDByMQswCQYDVQQGEwJHQjEXMBUGA1UECBMOV2VzdCBZ # b3Jrc2hpcmUxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEwMC4GA1UEAxMnU2Vj # dGlnbyBQdWJsaWMgVGltZSBTdGFtcGluZyBTaWduZXIgUjM2oIITBDCCBmIwggTK # oAMCAQICEQCkKTtuHt3XpzQIh616TrckMA0GCSqGSIb3DQEBDAUAMFUxCzAJBgNV # BAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxLDAqBgNVBAMTI1NlY3Rp # Z28gUHVibGljIFRpbWUgU3RhbXBpbmcgQ0EgUjM2MB4XDTI1MDMyNzAwMDAwMFoX # DTM2MDMyMTIzNTk1OVowcjELMAkGA1UEBhMCR0IxFzAVBgNVBAgTDldlc3QgWW9y # a3NoaXJlMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxMDAuBgNVBAMTJ1NlY3Rp # Z28gUHVibGljIFRpbWUgU3RhbXBpbmcgU2lnbmVyIFIzNjCCAiIwDQYJKoZIhvcN # AQEBBQADggIPADCCAgoCggIBANOElfRupFN48j0QS3gSBzzclIFTZ2Gsn7BjsmBF # 659/kpA2Ey7NXK3MP6JdrMBNU8wdmkf+SSIyjX++UAYWtg3Y/uDRDyg8RxHeHRJ+ # 0U1jHEyH5uPdk1ttiPC3x/gOxIc9P7Gn3OgW7DQc4x07exZ4DX4XyaGDq5LoEmk/ # BdCM1IelVMKB3WA6YpZ/XYdJ9JueOXeQObSQ/dohQCGyh0FhmwkDWKZaqQBWrBwZ # ++zqlt+z/QYTgEnZo6dyIo2IhXXANFkCHutL8765NBxvolXMFWY8/reTnFxk3Maj # gM5NX6wzWdWsPJxYRhLxtJLSUJJ5yWRNw+NBqH1ezvFs4GgJ2ZqFJ+Dwqbx9+rw+ # F2gBdgo4j7CVomP49sS7CbqsdybbiOGpB9DJhs5QVMpYV73TVV3IwLiBHBECrTgU # fZVOMF0KSEq2zk/LsfvehswavE3W4aBXJmGjgWSpcDz+6TqeTM8f1DIcgQPdz0IY # gnT3yFTgiDbFGOFNt6eCidxdR6j9x+kpcN5RwApy4pRhE10YOV/xafBvKpRuWPjO # PWRBlKdm53kS2aMh08spx7xSEqXn4QQldCnUWRz3Lki+TgBlpwYwJUbR77DAayNw # AANE7taBrz2v+MnnogMrvvct0iwvfIA1W8kp155Lo44SIfqGmrbJP6Mn+Udr3MR2 # oWozAgMBAAGjggGOMIIBijAfBgNVHSMEGDAWgBRfWO1MMXqiYUKNUoC6s2GXGaIy # mzAdBgNVHQ4EFgQUiGGMoSo3ZIEoYKGbMdCM/SwCzk8wDgYDVR0PAQH/BAQDAgbA # MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwSgYDVR0gBEMw # QTA1BgwrBgEEAbIxAQIBAwgwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdv # LmNvbS9DUFMwCAYGZ4EMAQQCMEoGA1UdHwRDMEEwP6A9oDuGOWh0dHA6Ly9jcmwu # c2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY1RpbWVTdGFtcGluZ0NBUjM2LmNybDB6 # BggrBgEFBQcBAQRuMGwwRQYIKwYBBQUHMAKGOWh0dHA6Ly9jcnQuc2VjdGlnby5j # b20vU2VjdGlnb1B1YmxpY1RpbWVTdGFtcGluZ0NBUjM2LmNydDAjBggrBgEFBQcw # AYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggGBAAKB # PqSGclEh+WWpLj1SiuHlm8xLE0SThI2yLuq+75s11y6SceBchpnKpxWaGtXc8dya # 1Aq3RuW//y3wMThsvT4fSba2AoSWlR67rA4fTYGMIhgzocsids0ct/pHaocLVJSw # nTYxY2pE0hPoZAvRebctbsTqENmZHyOVjOFlwN2R3DRweFeNs4uyZN5LRJ5EnVYl # cTOq3bl1tI5poru9WaQRWQ4eynXp7Pj0Fz4DKr86HYECRJMWiDjeV0QqAcQMFsIj # JtrYTw7mU81qf4FBc4u4swphLeKRNyn9DDrd3HIMJ+CpdhSHEGleeZ5I79YDg3B3 # A/fmVY2GaMik1Vm+FajEMv4/EN2mmHf4zkOuhYZNzVm4NrWJeY4UAriLBOeVYODd # A1GxFr1ycbcUEGlUecc4RCPgYySs4d00NNuicR4a9n7idJlevAJbha/arIYMEuUq # TeRRbWkhJwMKmb9yEvppRudKyu1t6l21sIuIZqcpVH8oLWCxHS0LpDRF9Y4jijCC # BhQwggP8oAMCAQICEHojrtpTaZYPkcg+XPTH4z8wDQYJKoZIhvcNAQEMBQAwVzEL # MAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEuMCwGA1UEAxMl # U2VjdGlnbyBQdWJsaWMgVGltZSBTdGFtcGluZyBSb290IFI0NjAeFw0yMTAzMjIw # MDAwMDBaFw0zNjAzMjEyMzU5NTlaMFUxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9T # ZWN0aWdvIExpbWl0ZWQxLDAqBgNVBAMTI1NlY3RpZ28gUHVibGljIFRpbWUgU3Rh # bXBpbmcgQ0EgUjM2MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAzZjY # Q0GrboIr7PYzfiY05ImM0+8iEoBUPu8mr4wOgYPjoiIz5vzf7d5wu8GFK1JWN5hc # iN9rdqOhbdxLcSVwnOTJmUGfAMQm4eXOls3iQwfapEFWuOsYmBKXPNSpwZAFoLGl # 5y1EaGGc5LByM8wjcbSF52/Z42YaJRsPXY545E3QAPN2mxDh0OLozhiGgYT1xtjX # VfEzYBVmfQaI5QL35cTTAjsJAp85R+KAsOfuL9Z7LFnjdcuPkZWjssMETFIueH69 # rxbFOUD64G+rUo7xFIdRAuDNvWBsv0iGDPGaR2nZlY24tz5fISYk1sPY4gir99aX # AGnoo0vX3Okew4MsiyBn5ZnUDMKzUcQrpVavGacrIkmDYu/bcOUR1mVBIZ0X7P4b # Kf38JF7Mp7tY3LFF/h7hvBS2tgTYXlD7TnIMPrxyXCfB5yQq3FFoXRXM3/DvqQ4s # hoVWF/mwwz9xoRku05iphp22fTfjKRIVpm4gFT24JKspEpM8mFa9eTgKWWCvAgMB # AAGjggFcMIIBWDAfBgNVHSMEGDAWgBT2d2rdP/0BE/8WoWyCAi/QCj0UJTAdBgNV # HQ4EFgQUX1jtTDF6omFCjVKAurNhlxmiMpswDgYDVR0PAQH/BAQDAgGGMBIGA1Ud # EwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwEQYDVR0gBAowCDAG # BgRVHSAAMEwGA1UdHwRFMEMwQaA/oD2GO2h0dHA6Ly9jcmwuc2VjdGlnby5jb20v # U2VjdGlnb1B1YmxpY1RpbWVTdGFtcGluZ1Jvb3RSNDYuY3JsMHwGCCsGAQUFBwEB # BHAwbjBHBggrBgEFBQcwAoY7aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdv # UHVibGljVGltZVN0YW1waW5nUm9vdFI0Ni5wN2MwIwYIKwYBBQUHMAGGF2h0dHA6 # Ly9vY3NwLnNlY3RpZ28uY29tMA0GCSqGSIb3DQEBDAUAA4ICAQAS13sgrQ41WAye # gR0lWP1MLWd0r8diJiH2VVRpxqFGhnZbaF+IQ7JATGceTWOS+kgnMAzGYRzpm8jI # cjlSQ8JtcqymKhgx1s6cFZBSfvfeoyigF8iCGlH+SVSo3HHr98NepjSFJTU5KSRK # K+3nVSWYkSVQgJlgGh3MPcz9IWN4I/n1qfDGzqHCPWZ+/Mb5vVyhgaeqxLPbBIqv # 6cM74Nvyo1xNsllECJJrOvsrJQkajVz4xJwZ8blAdX5umzwFfk7K/0K3fpjgiXpq # NOpXaJ+KSRW0HdE0FSDC7+ZKJJSJx78mn+rwEyT+A3z7Ss0gT5CpTrcmhUwIw9jb # vnYuYRKxFVWjKklW3z83epDVzoWJttxFpujdrNmRwh1YZVIB2guAAjEQoF42H0BA # 7WBCueHVMDyV1e4nM9K4As7PVSNvQ8LI1WRaTuGSFUd9y8F8jw22BZC6mJoB40d7 # SlZIYfaildlgpgbgtu6SDsek2L8qomG57Yp5qTqof0DwJ4Q4HsShvRl/59T4IJBo # vRwmqWafH0cIPEX7cEttS5+tXrgRtMjjTOp6A9l0D6xcKZtxnLqiTH9KPCy6xZEi # 0UDcMTww5Fl4VvoGbMG2oonuX3f1tsoHLaO/Fwkj3xVr3lDkmeUqivebQTvGkx5h # GuJaSVQ+x60xJ/Y29RBr8Tm9XJ59AjCCBoIwggRqoAMCAQICEDbCsL18Gzrno7Pd # NsvJdWgwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpO # ZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVT # RVJUUlVTVCBOZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmlj # YXRpb24gQXV0aG9yaXR5MB4XDTIxMDMyMjAwMDAwMFoXDTM4MDExODIzNTk1OVow # VzELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEuMCwGA1UE # AxMlU2VjdGlnbyBQdWJsaWMgVGltZSBTdGFtcGluZyBSb290IFI0NjCCAiIwDQYJ # KoZIhvcNAQEBBQADggIPADCCAgoCggIBAIid2LlFZ50d3ei5JoGaVFTAfEkFm8xa # FQ/ZlBBEtEFAgXcUmanU5HYsyAhTXiDQkiUvpVdYqZ1uYoZEMgtHES1l1Cc6HaqZ # zEbOOp6YiTx63ywTon434aXVydmhx7Dx4IBrAou7hNGsKioIBPy5GMN7KmgYmuu4 # f92sKKjbxqohUSfjk1mJlAjthgF7Hjx4vvyVDQGsd5KarLW5d73E3ThobSkob2SL # 48LpUR/O627pDchxll+bTSv1gASn/hp6IuHJorEu6EopoB1CNFp/+HpTXeNARXUm # dRMKbnXWflq+/g36NJXB35ZvxQw6zid61qmrlD/IbKJA6COw/8lFSPQwBP1ityZd # wuCysCKZ9ZjczMqbUcLFyq6KdOpuzVDR3ZUwxDKL1wCAxgL2Mpz7eZbrb/JWXiOc # NzDpQsmwGQ6Stw8tTCqPumhLRPb7YkzM8/6NnWH3T9ClmcGSF22LEyJYNWCHrQqY # ubNeKolzqUbCqhSqmr/UdUeb49zYHr7ALL8bAJyPDmubNqMtuaobKASBqP84uhqc # RY/pjnYd+V5/dcu9ieERjiRKKsxCG1t6tG9oj7liwPddXEcYGOUiWLm742st50jG # wTzxbMpepmOP1mLnJskvZaN5e45NuzAHteORlsSuDt5t4BBRCJL+5EZnnw0ezntk # 9R8QJyAkL6/bAgMBAAGjggEWMIIBEjAfBgNVHSMEGDAWgBRTeb9aqitKz1SA4dib # wJ3ysgNmyzAdBgNVHQ4EFgQU9ndq3T/9ARP/FqFsggIv0Ao9FCUwDgYDVR0PAQH/ # BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wEwYDVR0lBAwwCgYIKwYBBQUHAwgwEQYD # VR0gBAowCDAGBgRVHSAAMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNl # cnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNy # bDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0 # cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggIBAA6+ZUHtaES45aHF1BGH5Lc7JYzr # ftrIF5Ht2PFDxKKFOct/awAEWgHQMVHol9ZLSyd/pYMbaC0IZ+XBW9xhdkkmUV/K # bUOiL7g98M/yzRyqUOZ1/IY7Ay0YbMniIibJrPcgFp73WDnRDKtVutShPSZQZAdt # FwXnuiWl8eFARK3PmLqEm9UsVX+55DbVIz33Mbhba0HUTEYv3yJ1fwKGxPBsP/Mg # TECimh7eXomvMm0/GPxX2uhwCcs/YLxDnBdVVlxvDjHjO1cuwbOpkiJGHmLXXVNb # sdXUC2xBrq9fLrfe8IBsA4hopwsCj8hTuwKXJlSTrZcPRVSccP5i9U28gZ7OMzoJ # GlxZ5384OKm0r568Mo9TYrqzKeKZgFo0fj2/0iHbj55hc20jfxvK3mQi+H7xpbzx # ZOFGm/yVQkpo+ffv5gdhp+hv1GDsvJOtJinJmgGbBFZIThbqI+MHvAmMmkfb3fTx # mSkop2mSJL1Y2x/955S29Gu0gSJIkc3z30vU/iXrMpWx2tS7UVfVP+5tKuzGtgkP # 7d/doqDrLF1u6Ci3TpjAZdeLLlRQZm867eVeXED58LXd1Dk6UvaAhvmWYXoiLz4J # A5gPBcz7J311uahxCweNxE+xxxR3kT0WKzASo5G/PyDez6NHdIUKBeE3jDPs2ACc # 6CkJ1Sji4PKWVT0/MYIEkjCCBI4CAQEwajBVMQswCQYDVQQGEwJHQjEYMBYGA1UE # ChMPU2VjdGlnbyBMaW1pdGVkMSwwKgYDVQQDEyNTZWN0aWdvIFB1YmxpYyBUaW1l # IFN0YW1waW5nIENBIFIzNgIRAKQpO24e3denNAiHrXpOtyQwDQYJYIZIAWUDBAIC # BQCgggH5MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUx # DxcNMjUwOTE4MTgwNDE2WjA/BgkqhkiG9w0BCQQxMgQwN+D74P+3gzw5GkUypoUX # 4r/ni2EUs9GfLqPsDA+E9gdYkihsaAs/G4W0hebStF8JMIIBegYLKoZIhvcNAQkQ # AgwxggFpMIIBZTCCAWEwFgQUOMkUgRBEtNxmPpPUdEuBQYaptbEwgYcEFMauVOR4 # hvF8PVUSSIxpw0p6+cLdMG8wW6RZMFcxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9T # ZWN0aWdvIExpbWl0ZWQxLjAsBgNVBAMTJVNlY3RpZ28gUHVibGljIFRpbWUgU3Rh # bXBpbmcgUm9vdCBSNDYCEHojrtpTaZYPkcg+XPTH4z8wgbwEFIU9Yy2TgoJhfNCQ # NcSR3pLBQtrHMIGjMIGOpIGLMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3 # IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VS # VFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0 # aW9uIEF1dGhvcml0eQIQNsKwvXwbOuejs902y8l1aDANBgkqhkiG9w0BAQEFAASC # AgCsFghQ1DYm504kmQnXAe2/tME38jYJOpgtI6jjws/xeEtWzDJu1LmKWz3ZQ/xb # wP2+C6OVBnYlJJGf3WXi0X1Go2NhkFtfA1ak8840IWDla5wPixpff3dRLhV/iqTT # 7f/MsnFivhAKPeYKt+bxpqqeIK/ocF6FJgPKf8g0sTERrgc6KibnhQNiDE7T8hWs # t6TdEYT2RXBebCC5bkQ70hU8VvC8GfB+rE8G6xkrFLXCUhhAnzjofscDGHOLu8ZC # z1ez5U0qV2avioNRv6/8mBjSL/OQ9Njq1c29JrpRlJX8eBQvMZY5euV4phdzbKpw # MsZF8dNoJd057RaBndU00PjbYFmxm5l3VuZXVozSTqsqrox2taLEByJM2h2q88nk # KICuRv3XjhqR4tSGR0kWqEGThte9oLU26F4PR10KnINS5UZ6Xm325QTquSYfWb7j # qpMnYf8gieZ2MzaKOBgfp/RkpeqTGqTrm7zhWVK231wEBZr4vkmeqfs/mUycL96q # H0tuw4Mbcz0qmsstO3mUsOxJ4H6QfWg/GBrPRTv+q0jCPA9a2JBfX4CSmfI0loVF # ibgQJyRYTuXii2ndJuoASq/3wvMgfuOFe9kctHuy7ii8cuL4ftPzIG82HaTAxWfY # g9MYdeZrbvIx5/pqOfXisTTFV93xKTpH3F0KB9lbP2gyhg== # SIG # End signature block