Universal.psm1

Import-Module "$PSScriptRoot\UniversalDashboard.MaterialUI.psm1" -ErrorAction SilentlyContinue

if (-not $IsCoreCLR) {
    [PowerShellUniversal.Cmdlets.AssemblyResolver]::Bind()
}

$TAType = [psobject].Assembly.GetType('System.Management.Automation.TypeAccelerators')
$TAtype::Add('File', 'PowerShellUniversal.PSUFile')
$TAtype::Add('Documentation', 'PowerShellUniversal.DocumentationAttribute')
$TAtype::Add('Component', 'PowerShellUniversal.ComponentAttribute')

function Start-PSUServer {
    [CmdletBinding(DefaultParameterSetName = "Service")]
    param(
        [Parameter(ParameterSetName = 'Path')]
        [string]$ExecutablePath,
        [Parameter(ParameterSetName = 'Path')]
        [string]$ListenAddress,
        [Parameter(ParameterSetName = 'Path')]
        [int]$Port,
        [Parameter(ParameterSetName = 'Path')]
        [ScriptBlock]$Configuration
    )

    if ($MyInvocation.BoundParameters.Count -eq 0)
    {
        Start-Service 'PowerShellUniversal'
        return
    }

    if ([UniversalAutomation.RemoteCommand]::Configuration) {
        & $Configuration
        return
    }

    if (-not $PSBoundParameters.ContainsKey("ExecutablePath")) {
        $ExecutablePath = "Universal.Server"
        if ($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows) {
            $ExecutablePath = "Universal.Server.exe"
        }
    }

    $Command = Get-Command $ExecutablePath -ErrorAction SilentlyContinue
    if ($null -eq $Command) {
        $ExecutablePath = Join-Path $PSScriptRoot $ExecutablePath
        $Command = Get-Command $ExecutablePath -ErrorAction SilentlyContinue
        if ($null -eq $Command) {
            throw 'Unable to locate the Universal Server executable. You can use Install-PSUServer the server for your platform. Use the -AddToPath parameter to add the installation directory the the PATH.'
        }
    }

    if ($PSVersionTable.PSEdition -ne 'Desktop' -and -not $IsWindows) {
        try {
            chmod +x $ExecutablePath
        }
        catch {
            Write-Warning "Failed to set executable flag. You may have to run 'chmod +x' yourself on $ExecutablePath. $_"
        }
    }

    if ($ListenAddress) {
        $Env:Kestrel__Endpoints__HTTP__Url = $ListenAddress
    }
    elseif ($PSBoundParameters.ContainsKey("Port")) {
        $Env:Kestrel__Endpoints__HTTP__Url = "http://*:$port"
    }

    if ($Configuration) {
        $scriptName = (Get-PSCallStack | Select-Object -Last 1).ScriptName
        if (-not $scriptName) {
            $scriptName = (Get-PSCallStack | Select-Object -Last 1 -Skip 1).ScriptName
        }
        $Env:Data__ConfigurationScript = $scriptName
    }

    $Process = Start-Process -FilePath $ExecutablePath -PassThru

    $Process
}

function Install-PSUServer {
    <#
    .SYNOPSIS
    Install the PowerShell Universal server.
     
    .DESCRIPTION
    Install the PowerShell Universal server. This is a convenience function that will install the server for your platform. On Windows, it will install the
    server as a Windows service. On Linux, it will install the server as a systemd service. On Mac, it will install the server as a launchd service.
     
    .PARAMETER Path
    The path to store the PowerShell Universal binaries. If not specified, the default installation path will be used.
     
    .PARAMETER AddToPath
    Whether to add the path to the PATH environment variable.
     
    .PARAMETER Version
    The version of PowerShell Universal to install.
     
    .PARAMETER LatestVersion
    Install the most recent version.
     
    .EXAMPLE
    Install-PSUServer
    #>

    [CmdletBinding(DefaultParameterSetName = "Version")]
    param(
        [Parameter()]
        [string]$Path,
        [Parameter(ParameterSetName = "Version")]
        [string]$Version,
        [Parameter(ParameterSetName = "Latest")]
        [Switch]$LatestVersion,
        [Parameter()]
        [string]$IISWebsite,
        [Parameter()]
        [string]$IISAppPool = "PowerShellUniversal",
        [Parameter()]
        [int]$IISPort
    )
    
    if ([string]::IsNullOrEmpty($Version))
    {
        # This module is either named Universal or Devolutions.PowerShellUniversal so use the version from the module if not specified.
        $Version = $PSCmdlet.MyInvocation.MyCommand.Module.Version
        Write-Verbose "Version not specified. Using version $Version from the Universal module."
    }

    if ($IISWebsite -and ($IsLinux -or $IsMacOS)) {
        throw "IISWebsite is only supported on Windows."
    }

    if ($IISWebsite) {
        Import-Module WebAdministration -ErrorAction Stop
    }

    if ($platform -eq 'win-x64' -and -not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
        throw 'You must be an administrator to install the Universal Server. Please run the command as an administrator.'
    }

    $platform = "win-x64";
    $folder = 'CommonApplicationData'
    if ($PSVersionTable.PSEdition -eq 'Core') {
        if ($IsLinux) {
            $platform = "linux-x64"
        }
        elseif ($IsMacOS) {
            $folder = 'ApplicationData'
            $platform = "osx-x64"
        }
    }

    if (-not $Path -and -not $IISWebsite) {
        $ProgramData = [System.Environment]::GetFolderPath($folder)
        $Path = [System.IO.Path]::Combine($ProgramData, "PowerShellUniversal", "Server")
    }

    if (-not $Path -and $IISWebsite) {
        $Path = "C:\inetpub\wwwroot\PowerShellUniversal"
        New-Item $Path -ItemType Directory | Out-Null
    }

    # Determine whether this is a Devolutions-era version (major year >= 2026)
    $parsedVersion = [Version]::new(0, 0)
    [void][Version]::TryParse($Version, [ref]$parsedVersion)
    $isDevolutionsVersion = $parsedVersion.Major -gt 2000

    if ($LatestVersion) {
        if ($isDevolutionsVersion) {
            Write-Verbose "Fetching latest version from Devolutions product info."
            $productInfo = (Invoke-WebRequest 'https://devolutions.net/productinfo.json' -UseBasicParsing).Content | ConvertFrom-Json
            $Version = $productInfo.PowerShellUniversal.Current.Version
            Write-Verbose "Latest Devolutions version: $Version"
            # Re-evaluate after fetching the latest version
            [void][Version]::TryParse($Version, [ref]$parsedVersion)
            $isDevolutionsVersion = $parsedVersion.Major -gt 2000
        } else {
            $Version = (Invoke-WebRequest 'https://imsreleases.blob.core.windows.net/universal/production/v5-version.txt' -UseBasicParsing).Content
        }
    }

    Write-Verbose "Downloading version $Version"

    if ($isDevolutionsVersion) {
        # The Devolutions CDN uses a 4-octet version (e.g. 2026.1.2.0).
        # If the supplied version has only 3 parts, append .0.
        $cdnVersion = $Version
        if (($Version -split '\.').Count -eq 3) {
            $cdnVersion = "$Version.0"
        }

        if (($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows) -and -not $IISWebsite) {
            $Temp = [System.IO.Path]::GetTempPath()
            $Msi = (Join-Path $Temp "Devolutions.PowerShellUniversal.$cdnVersion.msi")
            Remove-Item $Msi -Force -ErrorAction SilentlyContinue
            $msiUrl = "https://cdn.devolutions.net/download/Devolutions.PowerShellUniversal.$cdnVersion.msi"
            Write-Verbose "Downloading MSI from $msiUrl"
            Invoke-WebRequest $msiUrl -UseBasicParsing -OutFile $Msi
            Write-Verbose "Download complete. Installing from MSI."
            Start-Process msiexec.exe -ArgumentList "/i `"$Msi`" /quiet /qn /norestart" -Wait
        } else {
            Write-Verbose "Installing server to $Path"
            $Temp = [System.IO.Path]::GetTempPath()
            $Zip = (Join-Path $Temp "Universal.$cdnVersion.$platform.zip")
            Remove-Item $Zip -Force -ErrorAction SilentlyContinue
            $zipUrl = "https://cdn.devolutions.net/download/Universal.$platform.$cdnVersion.zip"
            Write-Verbose "Downloading ZIP from $zipUrl"
            Invoke-WebRequest $zipUrl -UseBasicParsing -OutFile $Zip
            Write-Verbose "Download complete. Unzipping to $Path"
            Expand-Archive -Path $Zip -DestinationPath $Path -Force
            Remove-Item $Zip -Force
        }
    } elseif (($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows) -and -not $IISWebsite) {
        $Temp = [System.IO.Path]::GetTempPath()
        $Msi = (Join-Path $Temp "Universal.$Version.$platform.msi")
        Remove-Item $Msi -Force -ErrorAction SilentlyContinue
        Invoke-WebRequest "https://imsreleases.blob.core.windows.net/universal/production/$Version/PowerShellUniversal.$Version.msi" -UseBasicParsing -OutFile $Msi
        Write-Verbose "Download complete. Installing from MSI."
        Start-Process msiexec.exe -ArgumentList "/i `"$Msi`" /quiet /qn /norestart" -Wait
    } else {
        Write-Verbose "Installing server to $Path"
        $Temp = [System.IO.Path]::GetTempPath()
        $Zip = (Join-Path $Temp "Universal.$Version.$platform.zip")
        Remove-Item $Zip -Force -ErrorAction SilentlyContinue
        Invoke-WebRequest "https://imsreleases.blob.core.windows.net/universal/production/$Version/Universal.$platform.$Version.zip" -UseBasicParsing -OutFile $Zip
        Write-Verbose "Download complete. Unzipping to $Path"
        Expand-Archive -Path $Zip -DestinationPath $Path -Force
        Remove-Item $Zip -Force
    }

    if ($IISWebsite) {
        New-WebAppPool -Name $IISAppPool | Out-Null
        New-Website -Name $IISWebsite -Port $IISPort -PhysicalPath $Path -ApplicationPool $IISAppPool | Out-Null
        Start-Website -Name $IISWebsite
    }

    if ($IsMacOS -or $IsLinux) {
        $ServerPath = Join-Path $Path "Universal.Server"
        /bin/chmod +x $ServerPath
    }

    if ($IsLinux) {
        Write-Verbose "Creating and starting PowerShellUniversal service"
        touch /etc/systemd/system/PowerShellUniversal.service
        chmod 664 /etc/systemd/system/PowerShellUniversal.service
        "[Unit]
        Description=PowerShell Universal
         
        [Service]
        ExecStart=$Path/Universal.Server
         
        [Install]
        WantedBy=multi-user.target"
 | Out-File /etc/systemd/system/PowerShellUniversal.service

        systemctl daemon-reload
        systemctl start PowerShellUniversal
        systemctl enable PowerShellUniversal
    }

    if ($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows) {
    }
    else {
        Write-Verbose "Adding $Path to `$PATH variable"
        $PathSeparator = ":"
        $envPath = [Environment]::GetEnvironmentVariable('PATH')
        $newpath = $envPath + $PathSeparator + $Path
        [Environment]::SetEnvironmentVariable("PATH", $newpath)
    }

    $Env:PATH += $PathSeparator + $Path

}

function Update-PSUServer {
    <#
    .SYNOPSIS
    Update the PowerShell Universal server.
     
    .DESCRIPTION
    Update the PowerShell Universal server. This is a convenience function that will update the server for your platform.
     
    .PARAMETER Path
    The path for the PowerShell Universal binaries. If not specified, the path will attempt to be resolved.
     
    .PARAMETER Version
    The version to upgrade to.
     
    .PARAMETER LatestVersion
    Upgrade to the latest version.
     
    .EXAMPLE
    Update-PSUServer
    #>

    [CmdletBinding(DefaultParameterSetName = "Version")]
    param(
        [Parameter()]
        [string]$Path,
        [Parameter(ParameterSetName = "Version")]
        [string]$Version,
        [Parameter(ParameterSetName = "Latest")]
        [Switch]$LatestVersion,
        [Parameter()]
        [string]$IISWebsite
    )
    
    if ([string]::IsNullOrEmpty($Version))
    {
        # This module is either named Universal or Devolutions.PowerShellUniversal so use the version from the module if not specified.
        $Version = $PSCmdlet.MyInvocation.MyCommand.Module.Version
        Write-Verbose "Version not specified. Using version $Version from the Universal module."
    }

    $platform = "win-x64";
    if ($PSVersionTable.PSEdition -eq 'Core') {
        if ($IsLinux) {
            $platform = "linux-x64"
        }
        elseif ($IsMacOS) {
            $platform = "osx-x64"
        }
    }

    if ($platform -eq 'win-x64' -and -not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
        throw 'You must be an administrator to update the Universal Server. Please run the command as an administrator.'
    }

    if ($IISWebsite -and ($IsLinux -or $IsMacOS)) {
        throw "IISWebsite is only supported on Windows."
    }

    if ($IISWebsite) {
        Import-Module WebAdministration -ErrorAction Stop
    }

    if (-not $Path -and -not $IISWebsite) {
        if ($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows) {
            $ServerPath = Get-Command "Universal.Server.exe" -ErrorAction SilentlyContinue
        }
        else {
            $ServerPath = Get-Command "Universal.Server" -ErrorAction SilentlyContinue
        }

        if (-not $ServerPath) {
            throw "Unable to locate existing PowerShell Universal installation. Use the -Path parameter to specify the folder of the previous installation."
        }

        $Path = [System.IO.Path]::GetDirectoryName($ServerPath.Source)
    }

    if (-not $Path -and $IISWebsite) {
        $Path = (Get-Website -Name $IISWebsite).PhysicalPath
    }

    # Determine whether this is a Devolutions-era version (major year >= 2026)
    $parsedVersion = [Version]::new(0, 0)
    [void][Version]::TryParse($Version, [ref]$parsedVersion)
    $isDevolutionsVersion = $parsedVersion.Major -gt 2000

    if ($LatestVersion) {
        if ($isDevolutionsVersion) {
            Write-Verbose "Fetching latest version from Devolutions product info."
            $productInfo = (Invoke-WebRequest 'https://devolutions.net/productinfo.json' -UseBasicParsing).Content | ConvertFrom-Json
            $Version = $productInfo.PowerShellUniversal.Current.Version
            Write-Verbose "Latest Devolutions version: $Version"
            # Re-evaluate after fetching the latest version
            [void][Version]::TryParse($Version, [ref]$parsedVersion)
            $isDevolutionsVersion = $parsedVersion.Major -gt 2000
        } else {
            $Version = (Invoke-WebRequest 'https://imsreleases.blob.core.windows.net/universal/production/v5-version.txt' -UseBasicParsing).Content
        }
    }

    Write-Verbose "Downloading version $Version"

    if ($isDevolutionsVersion) {
        # The Devolutions CDN uses a 4-octet version (e.g. 2026.1.2.0).
        # If the supplied version has only 3 parts, append .0.
        $cdnVersion = $Version
        if (($Version -split '\.').Count -eq 3) {
            $cdnVersion = "$Version.0"
        }

        if (($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows) -and -not $IISWebsite) {
            $Temp = [System.IO.Path]::GetTempPath()
            $Msi = (Join-Path $Temp "Devolutions.PowerShellUniversal.$cdnVersion.msi")
            Remove-Item $Msi -Force -ErrorAction SilentlyContinue
            $msiUrl = "https://cdn.devolutions.net/download/Devolutions.PowerShellUniversal.$cdnVersion.msi"
            Write-Verbose "Downloading MSI from $msiUrl"
            Invoke-WebRequest $msiUrl -UseBasicParsing -OutFile $Msi
            Write-Verbose "Download complete. Installing from MSI."
            Start-Process msiexec.exe -ArgumentList "/i `"$Msi`" /quiet /qn /norestart" -Wait
        } else {
            Write-Verbose "Upgrading server installed at $Path"

            $Temp = [System.IO.Path]::GetTempPath()
            $Zip = (Join-Path $Temp "Universal.$cdnVersion.$platform.zip")
            Remove-Item $Zip -Force -ErrorAction SilentlyContinue

            if ($IISWebsite) {
                $AppPool = (Get-Website -Name $IISWebsite).ApplicationPool
                Stop-Website -Name $IISWebsite
                Stop-WebAppPool -Name $AppPool
            }

            if ($IsLinux) {
                Write-Verbose "Stopped PowerShellUniversal service"
                systemctl stop PowerShellUniversal
                systemctl disable PowerShellUniversal
            }

            Remove-Item $Path -Force -Recurse
            $zipUrl = "https://cdn.devolutions.net/download/Universal.$platform.$cdnVersion.zip"
            Write-Verbose "Downloading ZIP from $zipUrl"
            Invoke-WebRequest $zipUrl -UseBasicParsing -OutFile $Zip

            Write-Verbose "Download complete. Extracting to $Path"

            Expand-Archive -Path $Zip -DestinationPath $Path -Force
            Remove-Item $Zip -Force

            if ($IISWebsite) {
                Get-ChildItem $Path -Recurse | Unblock-File
                Start-Website -Name $IISWebsite
            }

            if ($IsMacOS -or $IsLinux) {
                $ServerPath = Join-Path $Path "Universal.Server"
                /bin/chmod +x $ServerPath
            }

            if ($IsLinux) {
                Write-Verbose "Started PowerShellUniversal service"
                systemctl start PowerShellUniversal
                systemctl enable PowerShellUniversal
            }
        }
    } elseif (($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows) -and -not $IISWebsite) {
        $Temp = [System.IO.Path]::GetTempPath()
        $Msi = (Join-Path $Temp "Universal.$Version.$platform.msi")
        Remove-Item $Msi -Force -ErrorAction SilentlyContinue
        Invoke-WebRequest "https://imsreleases.blob.core.windows.net/universal/production/$Version/PowerShellUniversal.$Version.msi" -UseBasicParsing -OutFile $Msi
        Write-Verbose "Download complete. Installing from MSI."
        Start-Process msiexec.exe -ArgumentList "/i `"$Msi`" /quiet /qn /norestart" -Wait
    } else {
        Write-Verbose "Upgrading server installed at $Path"

        $Temp = [System.IO.Path]::GetTempPath()
        $Zip = (Join-Path $Temp "Universal.$Version.$platform.zip")
        Remove-Item $Zip -Force -ErrorAction SilentlyContinue

        if ($IISWebsite) {
            $AppPool = (Get-Website -Name $IISWebsite).ApplicationPool
            Stop-Website -Name $IISWebsite
            Stop-WebAppPool -Name $AppPool
        }

        if ($IsLinux) {
            Write-Verbose "Stopped PowerShellUniversal service"
            systemctl stop PowerShellUniversal
            systemctl disable PowerShellUniversal
        }

        Remove-Item $Path -Force -Recurse
        Invoke-WebRequest "https://imsreleases.blob.core.windows.net/universal/production/$Version/Universal.$platform.$Version.zip" -UseBasicParsing -OutFile $Zip

        Write-Verbose "Download complete. Extracting to $Path"

        Expand-Archive -Path $Zip -DestinationPath $Path -Force
        Remove-Item $Zip -Force

        if ($IISWebsite) {
            Get-ChildItem $Path -Recurse | Unblock-File
            Start-Website -Name $IISWebsite
        }

        if ($IsMacOS -or $IsLinux) {
            $ServerPath = Join-Path $Path "Universal.Server"
            /bin/chmod +x $ServerPath
        }

        if ($IsLinux) {
            Write-Verbose "Started PowerShellUniversal service"
            systemctl start PowerShellUniversal
            systemctl enable PowerShellUniversal
        }
    }
}

function Uninstall-PSUServer {
    <#
    .SYNOPSIS
    Removes the PowerShell Universal server.
     
    .DESCRIPTION
    Removes the PowerShell Universal server. This is a convenience function that will remove the server for your platform.
     
    .PARAMETER Path
    The path to the PowerShell Universal binaries. If not specified, the path will attempt to be resolved.
     
    .EXAMPLE
    Remove-PSUServer
    #>

    [Alias("Remove-PSUServer")]
    [CmdletBinding(DefaultParameterSetName = "Version")]
    param(
        [Parameter()]
        [string]$Path,
        [Parameter()]
        [string]$IISWebsite
    )

    if (($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows) -and -not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
        throw 'You must be an administrator to remove the Universal Server. Please run the command as an administrator.'
    }

    if ($IISWebsite -and ($IsLinux -or $IsMacOS)) {
        throw "IISWebsite is only supported on Windows."
    }

    if ($IISWebsite) {
        Import-Module WebAdministration -ErrorAction Stop
    }

    if (($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows) -and -not $IISWebsite)
    {
        Write-Verbose "Locating local package with Win32_Product"
        $Package = Get-CimInstance win32_product  -Filter "Name like 'PowerShell Universal%'" | Select-Object -First 1
        if ($Package)
        {
            Write-Verbose "Removing via msiexec."
            Start-Process msiexec.exe -ArgumentList "/x $( $Package.LocalPackage ) /quiet /qn /norestart" -Wait
        } else {
            throw "Unable to locate PowerShell Universal installation."
        }
    }
    else
    {
        if (-not $Path -and -not $IISWebsite) {
            $ServerPath = Get-Command "Universal.Server" -ErrorAction SilentlyContinue

            if (-not $ServerPath) {
                throw "Unable to locate existing PowerShell Universal installation. Use the -Path parameter to specify the folder of the previous installation."
            }

            $Path = [System.IO.Path]::GetDirectoryName($ServerPath.Source)
        }

        if ($IISWebsite) {
            $Path = (Get-Website -Name $IISWebsite).PhysicalPath
            $AppPool = (Get-Website -Name $IISWebsite).ApplicationPool
            Stop-Website -Name $IISWebsite
            Remove-Website -Name $IISWebsite
            Remove-WebAppPool $AppPool

            Write-Verbose "Removing application files"
            Remove-Item $Path -Force -Recurse
        }

        if ($IsLinux) {
            Write-Verbose "Stopped PowerShellUniversal service"
            systemctl stop PowerShellUniversal
            systemctl disable PowerShellUniversal
            Remove-Item /etc/systemd/system/PowerShellUniversal.service -Force
            systemctl daemon-reload

            Write-Verbose "Removing application files"
            Remove-Item $Path -Force -Recurse
        }
    }
}
# SIG # Begin signature block
# MIIvWgYJKoZIhvcNAQcCoIIvSzCCL0cCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBToNl0fjapWzmO
# pulhe94uVvXeDCjMdQdCtpcVScVP4aCCFBcwggVyMIIDWqADAgECAhB2U/6sdUZI
# k/Xl10pIOk74MA0GCSqGSIb3DQEBDAUAMFMxCzAJBgNVBAYTAkJFMRkwFwYDVQQK
# ExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQDEyBHbG9iYWxTaWduIENvZGUgU2ln
# bmluZyBSb290IFI0NTAeFw0yMDAzMTgwMDAwMDBaFw00NTAzMTgwMDAwMDBaMFMx
# CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQD
# EyBHbG9iYWxTaWduIENvZGUgU2lnbmluZyBSb290IFI0NTCCAiIwDQYJKoZIhvcN
# AQEBBQADggIPADCCAgoCggIBALYtxTDdeuirkD0DcrA6S5kWYbLl/6VnHTcc5X7s
# k4OqhPWjQ5uYRYq4Y1ddmwCIBCXp+GiSS4LYS8lKA/Oof2qPimEnvaFE0P31PyLC
# o0+RjbMFsiiCkV37WYgFC5cGwpj4LKczJO5QOkHM8KCwex1N0qhYOJbp3/kbkbuL
# ECzSx0Mdogl0oYCve+YzCgxZa4689Ktal3t/rlX7hPCA/oRM1+K6vcR1oW+9YRB0
# RLKYB+J0q/9o3GwmPukf5eAEh60w0wyNA3xVuBZwXCR4ICXrZ2eIq7pONJhrcBHe
# OMrUvqHAnOHfHgIB2DvhZ0OEts/8dLcvhKO/ugk3PWdssUVcGWGrQYP1rB3rdw1G
# R3POv72Vle2dK4gQ/vpY6KdX4bPPqFrpByWbEsSegHI9k9yMlN87ROYmgPzSwwPw
# jAzSRdYu54+YnuYE7kJuZ35CFnFi5wT5YMZkobacgSFOK8ZtaJSGxpl0c2cxepHy
# 1Ix5bnymu35Gb03FhRIrz5oiRAiohTfOB2FXBhcSJMDEMXOhmDVXR34QOkXZLaRR
# kJipoAc3xGUaqhxrFnf3p5fsPxkwmW8x++pAsufSxPrJ0PBQdnRZ+o1tFzK++Ol+
# A/Tnh3Wa1EqRLIUDEwIrQoDyiWo2z8hMoM6e+MuNrRan097VmxinxpI68YJj8S4O
# JGTfAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0G
# A1UdDgQWBBQfAL9GgAr8eDm3pbRD2VZQu86WOzANBgkqhkiG9w0BAQwFAAOCAgEA
# Xiu6dJc0RF92SChAhJPuAW7pobPWgCXme+S8CZE9D/x2rdfUMCC7j2DQkdYc8pzv
# eBorlDICwSSWUlIC0PPR/PKbOW6Z4R+OQ0F9mh5byV2ahPwm5ofzdHImraQb2T07
# alKgPAkeLx57szO0Rcf3rLGvk2Ctdq64shV464Nq6//bRqsk5e4C+pAfWcAvXda3
# XaRcELdyU/hBTsz6eBolSsr+hWJDYcO0N6qB0vTWOg+9jVl+MEfeK2vnIVAzX9Rn
# m9S4Z588J5kD/4VDjnMSyiDN6GHVsWbcF9Y5bQ/bzyM3oYKJThxrP9agzaoHnT5C
# JqrXDO76R78aUn7RdYHTyYpiF21PiKAhoCY+r23ZYjAf6Zgorm6N1Y5McmaTgI0q
# 41XHYGeQQlZcIlEPs9xOOe5N3dkdeBBUO27Ql28DtR6yI3PGErKaZND8lYUkqP/f
# obDckUCu3wkzq7ndkrfxzJF0O2nrZ5cbkL/nx6BvcbtXv7ePWu16QGoWzYCELS/h
# AtQklEOzFfwMKxv9cW/8y7x1Fzpeg9LJsy8b1ZyNf1T+fn7kVqOHp53hWVKUQY9t
# W76GlZr/GnbdQNJRSnC0HzNjI3c/7CceWeQIh+00gkoPP/6gHcH1Z3NFhnj0qinp
# J4fGGdvGExTDOUmHTaCX4GUT9Z13Vunas1jHOvLAzYIwggboMIIE0KADAgECAhB3
# vQ4Ft1kLth1HYVMeP3XtMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAkJFMRkw
# FwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQDEyBHbG9iYWxTaWduIENv
# ZGUgU2lnbmluZyBSb290IFI0NTAeFw0yMDA3MjgwMDAwMDBaFw0zMDA3MjgwMDAw
# MDBaMFwxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTIw
# MAYDVQQDEylHbG9iYWxTaWduIEdDQyBSNDUgRVYgQ29kZVNpZ25pbmcgQ0EgMjAy
# MDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMsg75ceuQEyQ6BbqYoj
# /SBerjgSi8os1P9B2BpV1BlTt/2jF+d6OVzA984Ro/ml7QH6tbqT76+T3PjisxlM
# g7BKRFAEeIQQaqTWlpCOgfh8qy+1o1cz0lh7lA5tD6WRJiqzg09ysYp7ZJLQ8LRV
# X5YLEeWatSyyEc8lG31RK5gfSaNf+BOeNbgDAtqkEy+FSu/EL3AOwdTMMxLsvUCV
# 0xHK5s2zBZzIU+tS13hMUQGSgt4T8weOdLqEgJ/SpBUO6K/r94n233Hw0b6nskEz
# IHXMsdXtHQcZxOsmd/KrbReTSam35sOQnMa47MzJe5pexcUkk2NvfhCLYc+YVaMk
# oog28vmfvpMusgafJsAMAVYS4bKKnw4e3JiLLs/a4ok0ph8moKiueG3soYgVPMLq
# 7rfYrWGlr3A2onmO3A1zwPHkLKuU7FgGOTZI1jta6CLOdA6vLPEV2tG0leis1Ult
# 5a/dm2tjIF2OfjuyQ9hiOpTlzbSYszcZJBJyc6sEsAnchebUIgTvQCodLm3HadNu
# twFsDeCXpxbmJouI9wNEhl9iZ0y1pzeoVdwDNoxuz202JvEOj7A9ccDhMqeC5LYy
# AjIwfLWTyCH9PIjmaWP47nXJi8Kr77o6/elev7YR8b7wPcoyPm593g9+m5XEEofn
# GrhO7izB36Fl6CSDySrC/blTAgMBAAGjggGtMIIBqTAOBgNVHQ8BAf8EBAMCAYYw
# EwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4E
# FgQUJZ3Q/FkJhmPF7POxEztXHAOSNhEwHwYDVR0jBBgwFoAUHwC/RoAK/Hg5t6W0
# Q9lWULvOljswgZMGCCsGAQUFBwEBBIGGMIGDMDkGCCsGAQUFBzABhi1odHRwOi8v
# b2NzcC5nbG9iYWxzaWduLmNvbS9jb2Rlc2lnbmluZ3Jvb3RyNDUwRgYIKwYBBQUH
# MAKGOmh0dHA6Ly9zZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L2NvZGVzaWdu
# aW5ncm9vdHI0NS5jcnQwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL2NybC5nbG9i
# YWxzaWduLmNvbS9jb2Rlc2lnbmluZ3Jvb3RyNDUuY3JsMFUGA1UdIAROMEwwQQYJ
# KwYBBAGgMgECMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24u
# Y29tL3JlcG9zaXRvcnkvMAcGBWeBDAEDMA0GCSqGSIb3DQEBCwUAA4ICAQAldaAJ
# yTm6t6E5iS8Yn6vW6x1L6JR8DQdomxyd73G2F2prAk+zP4ZFh8xlm0zjWAYCImbV
# YQLFY4/UovG2XiULd5bpzXFAM4gp7O7zom28TbU+BkvJczPKCBQtPUzosLp1pnQt
# pFg6bBNJ+KUVChSWhbFqaDQlQq+WVvQQ+iR98StywRbha+vmqZjHPlr00Bid/XSX
# hndGKj0jfShziq7vKxuav2xTpxSePIdxwF6OyPvTKpIz6ldNXgdeysEYrIEtGiH6
# bs+XYXvfcXo6ymP31TBENzL+u0OF3Lr8psozGSt3bdvLBfB+X3Uuora/Nao2Y8nO
# ZNm9/Lws80lWAMgSK8YnuzevV+/Ezx4pxPTiLc4qYc9X7fUKQOL1GNYe6ZAvytOH
# X5OKSBoRHeU3hZ8uZmKaXoFOlaxVV0PcU4slfjxhD4oLuvU/pteO9wRWXiG7n9dq
# cYC/lt5yA9jYIivzJxZPOOhRQAyuku++PX33gMZMNleElaeEFUgwDlInCI2Oor0i
# xxnJpsoOqHo222q6YV8RJJWk4o5o7hmpSZle0LQ0vdb5QMcQlzFSOTUpEYck08T7
# qWPLd0jV+mL8JOAEek7Q5G7ezp44UCb0IXFl1wkl1MkHAHq4x/N36MXU4lXQ0x72
# f1LiSY25EXIMiEQmM2YBRN/kMw4h3mKJSAfa9TCCB7EwggWZoAMCAQICDHPTwzYD
# /4u0QiTyXjANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQ
# R2xvYmFsU2lnbiBudi1zYTEyMDAGA1UEAxMpR2xvYmFsU2lnbiBHQ0MgUjQ1IEVW
# IENvZGVTaWduaW5nIENBIDIwMjAwHhcNMjMxMDMwMTc1MTE4WhcNMjYxMDMwMTc1
# MTE4WjCB8TEdMBsGA1UEDwwUUHJpdmF0ZSBPcmdhbml6YXRpb24xEzARBgNVBAUT
# CjExNjI1NDQ2ODkxEzARBgsrBgEEAYI3PAIBAxMCQ0ExFzAVBgsrBgEEAYI3PAIB
# AhMGUXVlYmVjMQswCQYDVQQGEwJDQTEPMA0GA1UECBMGUXVlYmVjMRIwEAYDVQQH
# EwlMYXZhbHRyaWUxGDAWBgNVBAoTD0Rldm9sdXRpb25zIEluYzEYMBYGA1UEAxMP
# RGV2b2x1dGlvbnMgSW5jMScwJQYJKoZIhvcNAQkBFhhzZWN1cml0eUBkZXZvbHV0
# aW9ucy5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCfDk6c1eCL
# 9rTvq1D1lq1GmU08ZKyYQJQ7Eb/mRFpRXqpOFiySnf8BysYbZ4y4MnIl7M2Wjc5n
# 1JcXR9BPWmkJLnI7rFTwpq/O5xKUwW20/EYyOuF7TasRq6olljm73dcLjrt5z/a2
# u2gO+vMS8LVY6UXKAGZGIigMoPS92f2MkkKmdEmA5dpwbALUfvH9sy0qknUfQY6d
# slpI8PbjTCx9GY5xqCTMtBQcWB5sBn/I0YAlp5yuOn+2ga4vUcucAZTVseoRI/Js
# n5KWWb0iM9wrbv+DOCzcAtBF+Yj2Kp8wHRWfMCumu4YuYcwTY3hbIuNRoUi8j4nL
# ptjGaz7R3UfAr4b/rH4Vg8/l9ufP61Z7bpSkZbIlnh3Gjy9UJCjw5wguQucnllSb
# NNg5ZBd7v3DRUKwKvzF9TYoOERwGdeY8uS4fnSYP7XuGF9b+coZ/D5guGaebiJJE
# odRJkGdiP5P+6jLO43dzgmB4hmWbuF5wofRYXd1ihFOf4aBH2qzHnFkDvp5zeclM
# lgoLuxJVb4mU36Z84KnJuT7fPThK9RbNEoqPPzd1BYcCcRmVaLCYHw+6AgmVXm3b
# gCsv4zM/DqkycfPX11sBXedYdTJ4tihtFo1eRqfQsXEivN+XYwUIJ/EdfHUmaHU+
# 7eYhgSPVynPm9Fq1mAAC3KqH+6RtIpEmpQIDAQABo4IB2zCCAdcwDgYDVR0PAQH/
# BAQDAgeAMIGfBggrBgEFBQcBAQSBkjCBjzBMBggrBgEFBQcwAoZAaHR0cDovL3Nl
# Y3VyZS5nbG9iYWxzaWduLmNvbS9jYWNlcnQvZ3NnY2NyNDVldmNvZGVzaWduY2Ey
# MDIwLmNydDA/BggrBgEFBQcwAYYzaHR0cDovL29jc3AuZ2xvYmFsc2lnbi5jb20v
# Z3NnY2NyNDVldmNvZGVzaWduY2EyMDIwMFUGA1UdIAROMEwwQQYJKwYBBAGgMgEC
# MDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9z
# aXRvcnkvMAcGBWeBDAEDMAkGA1UdEwQCMAAwRwYDVR0fBEAwPjA8oDqgOIY2aHR0
# cDovL2NybC5nbG9iYWxzaWduLmNvbS9nc2djY3I0NWV2Y29kZXNpZ25jYTIwMjAu
# Y3JsMCMGA1UdEQQcMBqBGHNlY3VyaXR5QGRldm9sdXRpb25zLm5ldDATBgNVHSUE
# DDAKBggrBgEFBQcDAzAfBgNVHSMEGDAWgBQlndD8WQmGY8Xs87ETO1ccA5I2ETAd
# BgNVHQ4EFgQU+cpn+IPqWRnE5rHeI+bO8b/X89owDQYJKoZIhvcNAQELBQADggIB
# ABr7ukUZYHuRYKb0JdoVh9Lwngn45m/BBg90jTL5CF6ZP4xYB2kaKN366sfAbvmK
# ThbgfcIvN26NjS1/cFXad5af6s5OzGUic+mAFZOhbpX81GedsAnxl1D4BKJs2+iW
# h/eK2vba/K3J5V2Z7S7YFgHqF0vlmDtNxnBQ8jsI30zrbcuYJowft8WLjfW4hr0S
# dAIk2F4X1CTGhtJVMuPcxyUuvrmknp1g2y99jc5eXA6qp0CiUbFC1R3C1kpZYT4s
# xiu86B3kbY6JqTO2f08tjvpih36UeFCC/ByZBzb1D8FFIaKiErjlDHVMIBCY1XrE
# EDEJpIyMRyobXsIuisyn4TpK8JqRb0C0opDzvE8BlKvqlqmHfafbOUXFH5gz/F9a
# iJAMfHyh4ddUg9nFcF+YKWKp8hpdaIW+5ptlsC2LSS5tztMUXRisUf/zCTeLQ2MA
# Xc7Vl0sc8ZD9Uqb9wm+tmK3ZGvnDKCikwE8YU+y96ogFUybGcEWXUYk3QvuXKeS0
# 9/v6QOwbgY3o5EkrNQyPUugI2HsyWtmLhTdDM/Pnj+O2NDNkPXvGiss2b0O8yUMV
# kh9C0HG4WS3L/ExoM1keN1Yd54FaFhk1zQv3KQaC7MJU8uZrmrIJLPNdEPGKiFfI
# 8CLIV/04jAIrR+A4SDaCpDTz+XDZF7kP42KGybJiSD1qMYIamTCCGpUCAQEwbDBc
# MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEyMDAGA1UE
# AxMpR2xvYmFsU2lnbiBHQ0MgUjQ1IEVWIENvZGVTaWduaW5nIENBIDIwMjACDHPT
# wzYD/4u0QiTyXjANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKAC
# gAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsx
# DjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCAONa4Aees+EhIjTRqRcVDN
# jjh+sPTvBpa9RZiVvxrTxTANBgkqhkiG9w0BAQEFAASCAgASXUtIB1FhwmxqgH5U
# /GIKuQJJ4DLZQwXDEK144/yNyK1cjAYnIVUaILmrZiIQPrpOIfZ77IkzgJgdyZri
# bzWxKSikt/BZegNYvk1GmCht2mWmODtPU1+fon0JxC/37uBk0E3TokPVo9OXaoPG
# 6RJNfBMB3PbZ1yAOw3g976ddhTIY6JNXen+7ypgsYWgPe/0FvnadBkjBtXVme7Tl
# CohCz5FxD5KnbBbKQSUxW35R4iLK9cO/HycDDs4jnwgohdDsdl7dbXHICcuxKT5K
# I3vOY1qQe1ENh2YPZPaK/s6mlpRJL0bOFcoP1GtbsGzlyLutMXPhwvM7TLuT2k4S
# L6xa6+EJa4GbIg7WmgEE9QQkd1jyze36ASemtk2C7gZAW8ko0VeM8Rd6sU+X0qJy
# Su4c9E/gFlrDDm5DT3itX89+HPGSJlwzGFbOPrvKZKuWZN48byiPpXp8njONNJlw
# RcI7RfFRb9eLjAl0BWiNt6JGoMCdK90cAwfKj2Qzc64uUTMGVDRBMBgDpnRNvB6c
# b65tuscU+YH0AR5ckGYxNGw9AFKuk7B2+8kbj+iny1u2bmO1MbZzUMfDTYjtNQWm
# 4uczPGHvqcf5fT3Z/7RW0nM/nWABg7QN7bCiaOHtEbxnCkAvyn134va4kF1SvoPn
# 4tVSw0VRF10BE7/8rz9kny4PE6GCF3cwghdzBgorBgEEAYI3AwMBMYIXYzCCF18G
# CSqGSIb3DQEHAqCCF1AwghdMAgEDMQ8wDQYJYIZIAWUDBAIBBQAweAYLKoZIhvcN
# AQkQAQSgaQRnMGUCAQEGCWCGSAGG/WwHATAxMA0GCWCGSAFlAwQCAQUABCBgpDJ+
# gggAGpA+l0ebWYub/AMI3Wuylndo6BFZafWtVAIRAIwGIu+hJWd+XJoQPEd2RhsY
# DzIwMjYwMjI3MTQwNDI5WqCCEzowggbtMIIE1aADAgECAhAKgO8YS43xBYLRxHan
# lXRoMA0GCSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdp
# Q2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3Rh
# bXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTEwHhcNMjUwNjA0MDAwMDAwWhcN
# MzYwOTAzMjM1OTU5WjBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs
# IEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFNIQTI1NiBSU0E0MDk2IFRpbWVzdGFt
# cCBSZXNwb25kZXIgMjAyNSAxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
# AgEA0EasLRLGntDqrmBWsytXum9R/4ZwCgHfyjfMGUIwYzKomd8U1nH7C8Dr0cVM
# F3BsfAFI54um8+dnxk36+jx0Tb+k+87H9WPxNyFPJIDZHhAqlUPt281mHrBbZHqR
# K71Em3/hCGC5KyyneqiZ7syvFXJ9A72wzHpkBaMUNg7MOLxI6E9RaUueHTQKWXym
# OtRwJXcrcTTPPT2V1D/+cFllESviH8YjoPFvZSjKs3SKO1QNUdFd2adw44wDcKgH
# +JRJE5Qg0NP3yiSyi5MxgU6cehGHr7zou1znOM8odbkqoK+lJ25LCHBSai25CFyD
# 23DZgPfDrJJJK77epTwMP6eKA0kWa3osAe8fcpK40uhktzUd/Yk0xUvhDU6lvJuk
# x7jphx40DQt82yepyekl4i0r8OEps/FNO4ahfvAk12hE5FVs9HVVWcO5J4dVmVzi
# x4A77p3awLbr89A90/nWGjXMGn7FQhmSlIUDy9Z2hSgctaepZTd0ILIUbWuhKuAe
# NIeWrzHKYueMJtItnj2Q+aTyLLKLM0MheP/9w6CtjuuVHJOVoIJ/DtpJRE7Ce7vM
# RHoRon4CWIvuiNN1Lk9Y+xZ66lazs2kKFSTnnkrT3pXWETTJkhd76CIDBbTRofOs
# NyEhzZtCGmnQigpFHti58CSmvEyJcAlDVcKacJ+A9/z7eacCAwEAAaOCAZUwggGR
# MAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFOQ7/PIx7f391/ORcWMZUEPPYYzoMB8G
# A1UdIwQYMBaAFO9vU0rp5AZ8esrikFb2L9RJ7MtOMA4GA1UdDwEB/wQEAwIHgDAW
# BgNVHSUBAf8EDDAKBggrBgEFBQcDCDCBlQYIKwYBBQUHAQEEgYgwgYUwJAYIKwYB
# BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBdBggrBgEFBQcwAoZRaHR0
# cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0VGltZVN0
# YW1waW5nUlNBNDA5NlNIQTI1NjIwMjVDQTEuY3J0MF8GA1UdHwRYMFYwVKBSoFCG
# Tmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFRpbWVT
# dGFtcGluZ1JTQTQwOTZTSEEyNTYyMDI1Q0ExLmNybDAgBgNVHSAEGTAXMAgGBmeB
# DAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIBAGUqrfEcJwS5rmBB
# 7NEIRJ5jQHIh+OT2Ik/bNYulCrVvhREafBYF0RkP2AGr181o2YWPoSHz9iZEN/FP
# sLSTwVQWo2H62yGBvg7ouCODwrx6ULj6hYKqdT8wv2UV+Kbz/3ImZlJ7YXwBD9R0
# oU62PtgxOao872bOySCILdBghQ/ZLcdC8cbUUO75ZSpbh1oipOhcUT8lD8QAGB9l
# ctZTTOJM3pHfKBAEcxQFoHlt2s9sXoxFizTeHihsQyfFg5fxUFEp7W42fNBVN4ue
# LaceRf9Cq9ec1v5iQMWTFQa0xNqItH3CPFTG7aEQJmmrJTV3Qhtfparz+BW60OiM
# EgV5GWoBy4RVPRwqxv7Mk0Sy4QHs7v9y69NBqycz0BZwhB9WOfOu/CIJnzkQTwtS
# SpGGhLdjnQ4eBpjtP+XB3pQCtv4E5UCSDag6+iX8MmB10nfldPF9SVD7weCC3yXZ
# i/uuhqdwkgVxuiMFzGVFwYbQsiGnoa9F5AaAyBjFBtXVLcKtapnMG3VH3EmAp/js
# J3FVF3+d1SVDTmjFjLbNFZUWMXuZyvgLfgyPehwJVxwC+UpX2MSey2ueIu9THFVk
# T+um1vshETaWyQo8gmBto/m3acaP9QsuLj3FNwFlTxq25+T4QwX9xa6ILs84ZPvm
# povq90K8eWyG2N01c4IhSOxqt81nMIIGtDCCBJygAwIBAgIQDcesVwX/IZkuQEMi
# DDpJhjANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln
# aUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhE
# aWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjUwNTA3MDAwMDAwWhcNMzgwMTE0
# MjM1OTU5WjBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4x
# QTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQw
# OTYgU0hBMjU2IDIwMjUgQ0ExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
# AgEAtHgx0wqYQXK+PEbAHKx126NGaHS0URedTa2NDZS1mZaDLFTtQ2oRjzUXMmxC
# qvkbsDpz4aH+qbxeLho8I6jY3xL1IusLopuW2qftJYJaDNs1+JH7Z+QdSKWM06qc
# hUP+AbdJgMQB3h2DZ0Mal5kYp77jYMVQXSZH++0trj6Ao+xh/AS7sQRuQL37QXbD
# hAktVJMQbzIBHYJBYgzWIjk8eDrYhXDEpKk7RdoX0M980EpLtlrNyHw0Xm+nt5pn
# YJU3Gmq6bNMI1I7Gb5IBZK4ivbVCiZv7PNBYqHEpNVWC2ZQ8BbfnFRQVESYOszFI
# 2Wv82wnJRfN20VRS3hpLgIR4hjzL0hpoYGk81coWJ+KdPvMvaB0WkE/2qHxJ0ucS
# 638ZxqU14lDnki7CcoKCz6eum5A19WZQHkqUJfdkDjHkccpL6uoG8pbF0LJAQQZx
# st7VvwDDjAmSFTUms+wV/FbWBqi7fTJnjq3hj0XbQcd8hjj/q8d6ylgxCZSKi17y
# Vp2NL+cnT6Toy+rN+nM8M7LnLqCrO2JP3oW//1sfuZDKiDEb1AQ8es9Xr/u6bDTn
# YCTKIsDq1BtmXUqEG1NqzJKS4kOmxkYp2WyODi7vQTCBZtVFJfVZ3j7OgWmnhFr4
# yUozZtqgPrHRVHhGNKlYzyjlroPxul+bgIspzOwbtmsgY1MCAwEAAaOCAV0wggFZ
# MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFO9vU0rp5AZ8esrikFb2L9RJ
# 7MtOMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1UdDwEB/wQE
# AwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB3BggrBgEFBQcBAQRrMGkwJAYIKwYB
# BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0
# cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5j
# cnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0Rp
# Z2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJ
# YIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQAXzvsWgBz+Bz0RdnEwvb4LyLU0
# pn/N0IfFiBowf0/Dm1wGc/Do7oVMY2mhXZXjDNJQa8j00DNqhCT3t+s8G0iP5kvN
# 2n7Jd2E4/iEIUBO41P5F448rSYJ59Ib61eoalhnd6ywFLerycvZTAz40y8S4F3/a
# +Z1jEMK/DMm/axFSgoR8n6c3nuZB9BfBwAQYK9FHaoq2e26MHvVY9gCDA/JYsq7p
# GdogP8HRtrYfctSLANEBfHU16r3J05qX3kId+ZOczgj5kjatVB+NdADVZKON/gnZ
# ruMvNYY2o1f4MXRJDMdTSlOLh0HCn2cQLwQCqjFbqrXuvTPSegOOzr4EWj7PtspI
# HBldNE2K9i697cvaiIo2p61Ed2p8xMJb82Yosn0z4y25xUbI7GIN/TpVfHIqQ6Ku
# /qjTY6hc3hsXMrS+U0yy+GWqAXam4ToWd2UQ1KYT70kZjE4YtL8Pbzg0c1ugMZyZ
# Zd/BdHLiRu7hAWE6bTEm4XYRkA6Tl4KSFLFk43esaUeqGkH/wyW4N7OigizwJWeu
# kcyIPbAvjSabnf7+Pu0VrFgoiovRDiyx3zEdmcif/sYQsfch28bZeUz2rtY/9TCA
# 6TD8dC3JE3rYkrhLULy7Dc90G6e8BlqmyIjlgp2+VqsS9/wQD7yFylIz0scmbKvF
# oW2jNrbM1pD2T7m3XDCCBY0wggR1oAMCAQICEA6bGI750C3n79tQ4ghAGFowDQYJ
# KoZIhvcNAQEMBQAwZTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IElu
# YzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQg
# QXNzdXJlZCBJRCBSb290IENBMB4XDTIyMDgwMTAwMDAwMFoXDTMxMTEwOTIzNTk1
# OVowYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UE
# CxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBS
# b290IEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAv+aQc2jeu+Rd
# SjwwIjBpM+zCpyUuySE98orYWcLhKac9WKt2ms2uexuEDcQwH/MbpDgW61bGl20d
# q7J58soR0uRf1gU8Ug9SH8aeFaV+vp+pVxZZVXKvaJNwwrK6dZlqczKU0RBEEC7f
# gvMHhOZ0O21x4i0MG+4g1ckgHWMpLc7sXk7Ik/ghYZs06wXGXuxbGrzryc/NrDRA
# X7F6Zu53yEioZldXn1RYjgwrt0+nMNlW7sp7XeOtyU9e5TXnMcvak17cjo+A2raR
# mECQecN4x7axxLVqGDgDEI3Y1DekLgV9iPWCPhCRcKtVgkEy19sEcypukQF8IUzU
# vK4bA3VdeGbZOjFEmjNAvwjXWkmkwuapoGfdpCe8oU85tRFYF/ckXEaPZPfBaYh2
# mHY9WV1CdoeJl2l6SPDgohIbZpp0yt5LHucOY67m1O+SkjqePdwA5EUlibaaRBkr
# fsCUtNJhbesz2cXfSwQAzH0clcOP9yGyshG3u3/y1YxwLEFgqrFjGESVGnZifvaA
# sPvoZKYz0YkH4b235kOkGLimdwHhD5QMIR2yVCkliWzlDlJRR3S+Jqy2QXXeeqxf
# jT/JvNNBERJb5RBQ6zHFynIWIgnffEx1P2PsIV/EIFFrb7GrhotPwtZFX50g/KEe
# xcCPorF+CiaZ9eRpL5gdLfXZqbId5RsCAwEAAaOCATowggE2MA8GA1UdEwEB/wQF
# MAMBAf8wHQYDVR0OBBYEFOzX44LScV1kTN8uZz/nupiuHA9PMB8GA1UdIwQYMBaA
# FEXroq/0ksuCMS1Ri6enIZ3zbcgPMA4GA1UdDwEB/wQEAwIBhjB5BggrBgEFBQcB
# AQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggr
# BgEFBQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNz
# dXJlZElEUm9vdENBLmNydDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vY3JsMy5k
# aWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMBEGA1UdIAQK
# MAgwBgYEVR0gADANBgkqhkiG9w0BAQwFAAOCAQEAcKC/Q1xV5zhfoKN0Gz22Ftf3
# v1cHvZqsoYcs7IVeqRq7IviHGmlUIu2kiHdtvRoU9BNKei8ttzjv9P+Aufih9/Jy
# 3iS8UgPITtAq3votVs/59PesMHqai7Je1M/RQ0SbQyHrlnKhSLSZy51PpwYDE3cn
# RNTnf+hZqPC/Lwum6fI0POz3A8eHqNJMQBk1RmppVLC4oVaO7KTVPeix3P0c2PR3
# WlxUjG/voVA9/HYJaISfb8rbII01YBwCA8sgsKxYoA5AY8WYIsGyWfVVa88nq2x2
# zm8jLfR+cWojayL/ErhULSd+2DrZ8LaHlv1b0VysGMNNn3O3AamfV6peKOK5lDGC
# A3wwggN4AgEBMH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
# bmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IFRpbWVTdGFtcGluZyBS
# U0E0MDk2IFNIQTI1NiAyMDI1IENBMQIQCoDvGEuN8QWC0cR2p5V0aDANBglghkgB
# ZQMEAgEFAKCB0TAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcN
# AQkFMQ8XDTI2MDIyNzE0MDQyOVowKwYLKoZIhvcNAQkQAgwxHDAaMBgwFgQU3WIw
# rIYKLTBr2jixaHlSMAf7QX4wLwYJKoZIhvcNAQkEMSIEIGQBeXyKTqXP7pMQbgpx
# nVtPb7vZk3KtpWOJ42URSg+7MDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEIEqgP6Is
# 11yExVyTj4KOZ2ucrsqzP+NtJpqjNPFGEQozMA0GCSqGSIb3DQEBAQUABIICAAw2
# hQoBFL+qI81FxmDdBefAE2+WzX0CYLNaoSa7mrVKZT+WTzSO26ArVpzVUsostzSk
# +CvjefvScZ/nJlYxHnsEKRzTxw/T166FFp+2+4CFeeWe1N/WigXiGf/v0TId7vn3
# idUoGOhoLfJk7a39nVQtOQpy3YLBoHtzcM7REa1/1V7/UvP2jTXACidO/1elZ1ne
# 3cJ3/kAjpcRFdJcSPcmY5AIqQ0PgR8uT3sb3YNFvipPQx9M/UiXaFjvLhqLjR2pW
# iJziUOV7JetszwRdKKYzeKpDgNmybsdxY8MgAdeZngZUrXAQMf/IBNbBlGAFKAAt
# B8nc7MdwPuwPR3rBGsLD6vKo6yxQ3fDpYYRolJ0CYPLIJ+umVrlaTuyHTTzA/gzC
# GoSWNWwCXo52/ydsRDpAEsnBavLmPi1dP0cAPqb1f9We8fss76lrFITJr1/GwMkh
# PiYyLC0/0FLMsqpHDw1r7jVl3Kgzz8Zc5rynXiHc3Zi3mhw0L9g3+Q5SKoSo7PXl
# vDBaCanGxFCj08bbph0m1hvY7H2T1cOOZc0rnjdKErSSyEwb/0G4kIIxcZ2ATLg+
# kp6gYsdCBmyy6rnZD9Poof/QiP2imo316G6ZTf7vYQ1Q+cqBLP7DMc0Zi5NKH+0B
# 0TkVL1atCKI/KKylxjMM8EGH4nVN8ybWV5agK6HK
# SIG # End signature block