public/Invoke-ScriptUpdateCheck.ps1

function Invoke-ScriptUpdateCheck {
    <#
    .SYNOPSIS
        Checks for a new version of the script and optionally performs an update.
 
    .DESCRIPTION
        This function connects to a GitHub repository to check for new script versions based on a
        specified file. It supports signed scripts via GitHub Releases, dependency checking,
        update throttling, and multiple update channels.
 
    .PARAMETER CurrentVersion
        The version of the currently running script.
 
    .PARAMETER AutoUpdate
        A switch to automatically download and apply an available update.
 
    .PARAMETER UpdateChannel
        The update channel to check ('stable' or 'dev').
 
    .PARAMETER Rollback
        A switch to initiate a rollback to the most recent backup file.
 
    .PARAMETER NoUpdateCheck
        A switch to bypass the update check.
 
    .PARAMETER CheckIntervalHours
        The number of hours to wait before checking for an update again.
 
    .NOTES
        Function Name : Invoke-ScriptUpdateCheck
        Version : v2025.817.1705
        Author : John Billekens Consultancy
 
    .LINK
        https://blog.j81.nl
#>

    [CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'Github')]
    [OutputType([boolean])]
    param(

        [Parameter(Mandatory = $true, ParameterSetName = 'Github')]
        [string]$CurrentVersion,

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [switch]$AutoUpdate,

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [ValidateSet('stable', 'dev')]
        [string]$UpdateChannel = 'stable',

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [switch]$Rollback,

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [switch]$NoUpdateCheck,

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [Alias('ShowDevInfo')]
        [Switch]$ShowDevInfoIfNewerVersion = $false,

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [int]$CheckIntervalHours = 24,

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [String]$GithubRepo = $Global:GithubRepo,

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [String]$GithubOwner = $Global:GithubOwner,

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [ValidateNotNullOrEmpty()]
        [string]$GistId = $Global:GistId,

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [ValidateNotNullOrEmpty()]
        [String]$GistFilename = 'versioninfo.json',

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [Switch]$ForceCheckUpdate,

        [Parameter(Mandatory = $false, ParameterSetName = 'Github')]
        [Switch]$Silent
    )

    #region --- SETUP VARIABLES ---
    $script:Silent = $Silent.IsPresent
    $Result = @{
        Version         = ""
        Success         = $false
        Upgraded        = $false
        RestartRequired = $false
        NewVersion      = ""
        ReleaseNotes    = New-Object System.Collections.Generic.List[string]
        Messages        = New-Object System.Collections.Generic.List[string]
    }
    $SourceName = ""
    if ($PSCmdlet.ParameterSetName -eq 'Github') {
        $SourceName = "GitHub"
        if ([String]::IsNullOrEmpty($GithubOwner)) {
            Write-Error -Message "GitHub owner not specified. Please set the `$GithubOwner variable."
            $Result.Success = $false
            $Result.Messages.Add("GitHub owner not specified. Please set the `$GithubOwner variable.")
            return ([PSCustomObject]$Result)
        }
        if ([String]::IsNullOrEmpty($GithubRepo)) {
            Write-Error -Message "GitHub repository not specified. Please set the `$GithubRepo variable."
            $Result.Success = $false
            $Result.Messages.Add("GitHub repository not specified. Please set the `$GithubRepo variable.")
            return ([PSCustomObject]$Result)
        }
        if ([String]::IsNullOrEmpty($GistId)) {
            Write-Error -Message "Gist ID not specified. Please set the `$GistId variable."
            $Result.Success = $false
            $Result.Messages.Add("Gist ID not specified. Please set the `$GistId variable.")
            return ([PSCustomObject]$Result)
        }
        $jsonUrl = "https://gist.githubusercontent.com/$($GithubOwner)/$($GistId)/raw/$($GistFilename)"
        Write-Verbose -Message "Using Github URL: $($jsonUrl)"
    }

    # Script determines its own context
    $PSCallStack = Get-PSCallStack
    if ($PSCallStack.Count -eq 0) {
        Write-Error -Message "No call stack found. This function must be called from a script or function."
        $Result.Success = $false
        $Result.Messages.Add("No call stack found. This function must be called from a script or function.")
        return ([PSCustomObject]$Result)
    }
    $SourceScriptName = $PSCallStack[0].InvocationInfo.ScriptName
    $pattern = '(?<=\.ps1\s).*?$'
    if ($PSCallStack[-1].InvocationInfo.MyCommand -match $pattern) {
        $SourceParameters = $matches[0]
    } else {
        $SourceParameters = $null
    }
    if (-not $SourceScriptName) {
        Write-Error -Message "No script name found in call stack. This function must be called from a script."
        $Result.Success = $false
        $Result.Messages.Add("No script name found in call stack. This function must be called from a script.")
        return ([PSCustomObject]$Result)
    }
    $scriptFullName = Split-Path -Path $SourceScriptName -Leaf
    Write-Verbose -Message "Script full name: $($scriptFullName)"
    $scriptPath = $SourceScriptName
    Write-Verbose -Message "Script path: $($scriptPath)"
    $scriptRoot = Split-Path -Path $scriptPath -Parent
    Write-Verbose -Message "Script root: $($scriptRoot)"
    Write-Verbose -Message "Source parameters: $($SourceParameters | Out-String)"
    #endregion

    #region --- INITIAL CHECKS & MODES (Rollback/NoCheck) ---
    if ($NoUpdateCheck) {
        Write-Verbose -Message "Update check explicitly skipped."
        $Result.Success = $true
        $Result.Messages.Add("No update check performed, as requested.")
        return ([PSCustomObject]$Result)
    }

    if ($Rollback) {
        Write-Verbose -Message "Rollback mode activated."
        $Result.Messages.Add("Rollback mode activated. Attempting to roll back to the last backup.")
        $backupFile = Get-ChildItem -Path $scriptRoot -Filter "$($scriptFullName -replace '\.ps1$', '*.bak')" | Sort-Object -Property LastWriteTime -Descending | Select-Object -First 1
        if (-not $backupFile) {
            Write-Error -Message "No backup file (.bak) found to roll back to."
            $Result.Success = $false
            $Result.Messages.Add("No backup file found for rollback.")
            return ([PSCustomObject]$Result)
        }
        if ($PSCmdlet.ShouldProcess($scriptFullName, "Rollback to version from '$($backupFile.Name)'")) {
            $brokenScriptPath = "$($scriptPath).broken_$(Get-Date -Format 'yyyyMMddHHmmss')"
            Rename-Item -Path $scriptPath -NewName $brokenScriptPath -Force | Out-Null
            Rename-Item -Path $backupFile.FullName -NewName $scriptFullName -Force | Out-Null
            Write-InformationColored "Rollback successful. Please start the script again." -ForegroundColor Green
            $Result.Success = $true
            $Result.RestartRequired = $true
            $Result.Messages.Add("Rollback successful, restart the script to apply changes.")
            return ([PSCustomObject]$Result)
        }
    }
    #endregion

    #region --- THROTTLING ---
    Write-Verbose -Message "Checking if update check is throttled..."
    $lastCheckFile = Join-Path -Path $env:TEMP -ChildPath "$($scriptFullName)_lastupdatecheck.txt"
    if ((Test-Path -Path $lastCheckFile) -and $CheckIntervalHours -gt 0) {
        Write-Verbose -Message "Last update check file found at $($lastCheckFile)."
        try {
            if ($ForceCheckUpdate) {
                Write-Verbose -Message "Forced update check, ignoring last check time."
                $Result.Messages.Add("Forced update check initiated.")
            } elseif ((Get-Date) -lt ([datetime]::FromFileTimeUtc($(Get-Content -Path $lastCheckFile))).AddHours($CheckIntervalHours)) {
                Write-Verbose -Message "Update check skipped; last check was recent."
                $Result.Success = $true
                $Result.Messages.Add("Update check skipped; last check was within the throttling period of $($CheckIntervalHours) hours.")
                return ([PSCustomObject]$Result)
            }
        } catch {
            Write-Warning -Message "Could not parse last update check time. Checking now."
        }
    }
    #endregion

    #region --- FETCH UPDATE INFO ---
    Write-Verbose -Message "Checking for updates... (Channel: $($UpdateChannel))"
    try {
        $versionInfo = Invoke-RestMethod -Uri $jsonUrl -ErrorAction Stop
        Write-Verbose -Message "Retrieved version information from $($jsonUrl)"
        Set-Content -Path $lastCheckFile -Value ((Get-Date).ToFileTimeUtc())
    } catch {
        Write-Warning -Message "Could not retrieve update information from Gist. Continuing with current version."
        $Result.Success = $true
        $Result.Messages.Add("Could not retrieve update information from Gist. Continuing with current version.")
        return ([PSCustomObject]$Result)
    }

    $channelData = $versionInfo.channels.$UpdateChannel
    $latestVersionString = $channelData.version
    $currentVersionObj = [System.Version]$CurrentVersion
    $latestVersionObj = [System.Version]$latestVersionString
    $versionDetails = $versionInfo.changelog.$latestVersionString
    $requiredCertificateSubject = $versionDetails.CertificateSubject
    #endregion

    #region --- VERSION & DEPENDENCY CHECK ---
    if ($channelData.forceUpdateBelowVersion -and ($currentVersionObj -lt [System.Version]$channelData.forceUpdateBelowVersion)) {
        Write-Error -Message "CRITICAL: Your script version ($($CurrentVersion)) is outdated. Update to $($latestVersionString) is required. Please run with '-AutoUpdate'."
        $Result.Success = $false
        $Result.Messages.Add("CRITICAL: Your script version ($($CurrentVersion)) is outdated. Update to $($latestVersionString) is required. Please run with '-AutoUpdate'.")
        return ([PSCustomObject]$Result)
    }

    if ($latestVersionObj -le $currentVersionObj) {
        Write-Verbose -Message "Your script is up-to-date (Latest Version: $($latestVersionString), Script Version: $($CurrentVersion))."
        $Result.Success = $true
        $Result.Messages.Add("Your script is up-to-date (Latest Version: $($latestVersionString), Script Version: $($CurrentVersion)).")
        return ([PSCustomObject]$Result)
    }

    Write-InformationColored "`r`nA new version ($($latestVersionString)) is available for the '$($UpdateChannel)' channel!" -ForegroundColor Yellow
    $Result.Messages.Add("A new version ($($latestVersionString)) is available for the '$($UpdateChannel)' channel!")

    if ($versionDetails.notes -or $versionDetails.notes.Count -gt 0) {
        Write-InformationColored -Message "`r`nRelease Notes for version $($latestVersionString):" -ForegroundColor Cyan
        $Result.Messages.Add("Release Notes for version $($latestVersionString):")
        $versionDetails.notes | ForEach-Object { Write-InformationColored -Message " => $_"; $Result.Messages.Add(" => $_") }
    }
    if (($ShowDevInfoIfNewerVersion -or $channelData.showDevInfo) -and [version]$versionInfo.channels.dev.version -gt $latestVersionObj) {
        Write-InformationColored -Message "`r`nIMPORTANT: A newer development version ($($versionInfo.channels.dev.version)) is available in the 'dev' channel." -ForegroundColor Yellow
        Write-InformationColored -Message "Consider switching to the 'dev' channel for the latest features and fixes." -ForegroundColor Yellow
        $Result.Messages.Add("IMPORTANT: A newer development version ($($versionInfo.channels.dev.version)) is available in the 'dev' channel. Consider switching to the 'dev' channel for the latest features and fixes.")
        if ($versionInfo.changelog.$($versionInfo.channels.dev.version).notes -or $versionInfo.changelog.$($versionInfo.channels.dev.version).notes.Count -gt 0) {
            Write-InformationColored -Message "`r`nDevelopment Release Notes for version $($versionInfo.channels.dev.version):" -ForegroundColor Cyan
            $Result.Messages.Add("Development Release Notes for version $($versionInfo.channels.dev.version):")
            $versionInfo.changelog.$($versionInfo.channels.dev.version).notes | ForEach-Object { Write-InformationColored -Message " => $_"; $Result.Messages.Add(" => $_") }
        }
    }
    #endregion

    #region --- UPDATE EXECUTION ---
    if (-not $AutoUpdate) {
        Write-InformationColored -Message "Run with '-AutoUpdate' to install."
        $Result.Success = $true
        $Result.Messages.Add("Run with '-AutoUpdate' to install.")
        return ([PSCustomObject]$Result)
    }
    if (-not $PSCmdlet.ShouldProcess($scriptPath, "Update to version $($latestVersionString)")) {
        Write-InformationColored -Message "Update cancelled by user." -ForegroundColor Yellow
        $Result.Success = $true
        $Result.Messages.Add("Update cancelled by user.")
        return ([PSCustomObject]$Result)
    }

    try {
        $releaseApiUrl = "https://api.github.com/repos/$($GithubOwner)/$($GithubRepo)/releases/tags/$($latestVersionString)"
        Write-Verbose -Message "Getting release information from $($releaseApiUrl)"
        try {
            $releaseInfo = Invoke-RestMethod -Uri $releaseApiUrl -ErrorAction Stop
            Write-InformationColored -Message "Successfully retrieved release information from $SourceName." -ForegroundColor Green
            $Result.Messages.Add("Successfully retrieved release information from $SourceName.")
        } catch {
            if ($_.ErrorDetails.Message -and ($ErrorDetails = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue)) {
                if ($ErrorDetails.status -eq 404) {
                    Write-InformationColored -Message "Failed to retrieve release information from $SourceName. [$($ErrorDetails.status)] $($ErrorDetails.message), trying again with alternative option..."
                    $Result.Messages.Add("Failed to retrieve release information from $SourceName. [$($ErrorDetails.status)] $($ErrorDetails.message), trying again with alternative option...")
                    $releaseApiUrl = "https://api.github.com/repos/$($GithubOwner)/$($GithubRepo)/releases/tags/v$($latestVersionString)"
                    Write-Verbose -Message "Retrying with URL: $($releaseApiUrl)"
                    try {
                        $releaseInfo = Invoke-RestMethod -Uri $releaseApiUrl -ErrorAction Stop
                        Write-InformationColored -Message "Successfully retrieved release information from $SourceName." -ForegroundColor Green
                        $Result.Messages.Add("Successfully retrieved release information from $SourceName.")
                    } catch {
                        if ($_.ErrorDetails.Message -and ($ErrorDetails = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue)) {
                            Write-Error -Message "Failed to retrieve release information from $SourceName. [$($ErrorDetails.status)] $($ErrorDetails.message)"
                            $Result.Messages.Add("Failed to retrieve release information from $SourceName. [$($ErrorDetails.status)] $($ErrorDetails.message)")
                            $Result.Success = $false
                            return ([PSCustomObject]$Result)
                        } else {
                            Write-Error -Message "Failed to retrieve release information from $SourceName. Error: $($_.Exception.Message)"
                            $Result.Messages.Add("Failed to retrieve release information from $SourceName. Error: $($_.Exception.Message)")
                            $Result.Success = $false
                            return ([PSCustomObject]$Result)
                        }
                    }
                } else {
                    Write-Error -Message "Failed to retrieve release information from $SourceName. [$($ErrorDetails.status)] $($ErrorDetails.message)"
                    $Result.Messages.Add("Failed to retrieve release information from $SourceName. [$($ErrorDetails.status)] $($ErrorDetails.message)")
                    $Result.Success = $false
                    return ([PSCustomObject]$Result)
                }
            }
        }
        Write-Verbose -Message "Release information retrieved successfully."
        $downloadUrl = ($releaseInfo.assets | Where-Object { $_.name -ieq $scriptFullName }).browser_download_url
        if (-not $downloadUrl) {
            Write-Error -Message "Could not find asset '$($scriptFullName)' in release '$($latestVersionString)'."
            $Result.Messages.Add("Could not find asset '$($scriptFullName)' in release '$($latestVersionString)'.")
            $Result.Success = $false
            return ([PSCustomObject]$Result)
        }

        $tempPath = Join-Path -Path $env:TEMP -ChildPath $scriptFullName
        Write-Verbose -Message "Downloading update from $($downloadUrl)..."
        Invoke-WebRequest -Uri $downloadUrl -OutFile $tempPath -ErrorAction Stop
        if (-not [String]::IsNullOrEmpty($requiredCertificateSubject)) {
            Write-Verbose -Message "Verifying Authenticode signature..."
            $signature = Get-AuthenticodeSignature -FilePath $tempPath
            if ($signature.Status -ne 'Valid') { throw "Signature check failed! Status: $($signature.Status)." }

            # The function uses the $requiredCertificateSubject variable from the parent script scope
            if ($signature.SignerCertificate.Subject -ne $requiredCertificateSubject) {
                Write-Error -Message "Certificate subject mismatch! Expected '$($requiredCertificateSubject)', but got '$($signature.SignerCertificate.Subject)'."
                $Result.Messages.Add("Certificate subject mismatch! Expected '$($requiredCertificateSubject)', but got '$($signature.SignerCertificate.Subject)'.")
                $Result.Success = $false
                return ([PSCustomObject]$Result)
            }
            Write-Verbose -Message "Signature valid and matches expected subject."
            Write-InformationColored "Signature verified successfully." -ForegroundColor Green
            $Result.Messages.Add("Script Signature verified successfully.")
        } else {
            Write-Verbose -Message "No certificate subject specified for signature verification. Skipping signature check."
            Write-InformationColored "No certificate subject specified for signature verification. Skipping signature check." -ForegroundColor Yellow
            $Result.Messages.Add("No certificate subject specified for signature verification. Skipping signature check.")
        }
        Write-Verbose -Message "Update downloaded successfully to $($tempPath). Unblocking file..."
        Unblock-File -Path $tempPath

        $count = 1
        $backupPath = "$($scriptPath -replace '\.ps1$', "_v$($CurrentVersion).bak")"
        while ($true) {
            Write-Verbose -Message "Checking for existing backup file..."
            if (-not (Test-Path -Path $backupPath)) {
                Write-Verbose -Message "No existing backup file found. Proceeding with backup creation."
                break
            }
            Write-Verbose -Message "Backup file already exists at $($backupPath). Incrementing backup count."
            $backupPath = "$($scriptPath -replace '\.ps1$', "_v$($CurrentVersion)_$($count).bak")"
            $count++
        }
        try {
            Write-Verbose -Message "Creating backup of current script at $($backupPath)"
            Rename-Item -Path $scriptPath -NewName $backupPath -Force -ErrorAction Stop
            $Result.Messages.Add("Backup created successfully at $($backupPath).")
        } catch {
            Write-Warning -Message "Failed to create backup of current script. Exiting update process."
            Write-Error -Message "Backup creation failed: $($_.Exception.Message)"
            $Result.Messages.Add("Backup creation failed: $($_.Exception.Message)")
            $Result.Success = $false
            return ([PSCustomObject]$Result)
        }
        Write-Verbose -Message "Moving new script to $($scriptPath)"
        Move-Item -Path $tempPath -Destination $scriptPath -Force -ErrorAction Stop
        Write-InformationColored "Script successfully updated to version $($latestVersionString)." -ForegroundColor Green
        $Result.Success = $true
        $Result.Upgraded = $true
        $Result.Version = $latestVersionString
        $Result.Messages.Add("Script successfully updated to version $($latestVersionString).")
    } catch {
        Write-Error -Message "Update failed: $($_.Exception.Message)"
        $Result.Messages.Add("Update failed: $($_.Exception.Message)")
        if (Test-Path -Path $backupPath) {
            Move-Item -Path $backupPath -Destination $scriptPath -Force
            Write-InformationColored "Restored previous version." -ForegroundColor Green
            $Result.Messages.Add("Restored previous version from backup.")
        }
        $Result.Success = $false
        return ([PSCustomObject]$Result)
    }
    return ([PSCustomObject]$Result)
}

# SIG # Begin signature block
# MIImdwYJKoZIhvcNAQcCoIImaDCCJmQCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBoMN/VYY7lk8W7
# 9eqFWBeBCGAGSE6YnxLFufC3qoIcoKCCIAowggYUMIID/KADAgECAhB6I67aU2mW
# D5HIPlz0x+M/MA0GCSqGSIb3DQEBDAUAMFcxCzAJBgNVBAYTAkdCMRgwFgYDVQQK
# Ew9TZWN0aWdvIExpbWl0ZWQxLjAsBgNVBAMTJVNlY3RpZ28gUHVibGljIFRpbWUg
# U3RhbXBpbmcgUm9vdCBSNDYwHhcNMjEwMzIyMDAwMDAwWhcNMzYwMzIxMjM1OTU5
# WjBVMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSwwKgYD
# VQQDEyNTZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIENBIFIzNjCCAaIwDQYJ
# KoZIhvcNAQEBBQADggGPADCCAYoCggGBAM2Y2ENBq26CK+z2M34mNOSJjNPvIhKA
# VD7vJq+MDoGD46IiM+b83+3ecLvBhStSVjeYXIjfa3ajoW3cS3ElcJzkyZlBnwDE
# JuHlzpbN4kMH2qRBVrjrGJgSlzzUqcGQBaCxpectRGhhnOSwcjPMI3G0hedv2eNm
# GiUbD12OeORN0ADzdpsQ4dDi6M4YhoGE9cbY11XxM2AVZn0GiOUC9+XE0wI7CQKf
# OUfigLDn7i/WeyxZ43XLj5GVo7LDBExSLnh+va8WxTlA+uBvq1KO8RSHUQLgzb1g
# bL9Ihgzxmkdp2ZWNuLc+XyEmJNbD2OIIq/fWlwBp6KNL19zpHsODLIsgZ+WZ1AzC
# s1HEK6VWrxmnKyJJg2Lv23DlEdZlQSGdF+z+Gyn9/CRezKe7WNyxRf4e4bwUtrYE
# 2F5Q+05yDD68clwnweckKtxRaF0VzN/w76kOLIaFVhf5sMM/caEZLtOYqYadtn03
# 4ykSFaZuIBU9uCSrKRKTPJhWvXk4CllgrwIDAQABo4IBXDCCAVgwHwYDVR0jBBgw
# FoAU9ndq3T/9ARP/FqFsggIv0Ao9FCUwHQYDVR0OBBYEFF9Y7UwxeqJhQo1SgLqz
# YZcZojKbMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMBMGA1Ud
# JQQMMAoGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0gADBMBgNVHR8ERTBDMEGg
# P6A9hjtodHRwOi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNUaW1lU3Rh
# bXBpbmdSb290UjQ2LmNybDB8BggrBgEFBQcBAQRwMG4wRwYIKwYBBQUHMAKGO2h0
# dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY1RpbWVTdGFtcGluZ1Jv
# b3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAN
# BgkqhkiG9w0BAQwFAAOCAgEAEtd7IK0ONVgMnoEdJVj9TC1ndK/HYiYh9lVUacah
# RoZ2W2hfiEOyQExnHk1jkvpIJzAMxmEc6ZvIyHI5UkPCbXKspioYMdbOnBWQUn73
# 3qMooBfIghpR/klUqNxx6/fDXqY0hSU1OSkkSivt51UlmJElUICZYBodzD3M/SFj
# eCP59anwxs6hwj1mfvzG+b1coYGnqsSz2wSKr+nDO+Db8qNcTbJZRAiSazr7KyUJ
# Go1c+MScGfG5QHV+bps8BX5Oyv9Ct36Y4Il6ajTqV2ifikkVtB3RNBUgwu/mSiSU
# ice/Jp/q8BMk/gN8+0rNIE+QqU63JoVMCMPY2752LmESsRVVoypJVt8/N3qQ1c6F
# ibbcRabo3azZkcIdWGVSAdoLgAIxEKBeNh9AQO1gQrnh1TA8ldXuJzPSuALOz1Uj
# b0PCyNVkWk7hkhVHfcvBfI8NtgWQupiaAeNHe0pWSGH2opXZYKYG4Lbukg7HpNi/
# KqJhue2Keak6qH9A8CeEOB7Eob0Zf+fU+CCQaL0cJqlmnx9HCDxF+3BLbUufrV64
# EbTI40zqegPZdA+sXCmbcZy6okx/SjwsusWRItFA3DE8MORZeFb6BmzBtqKJ7l93
# 9bbKBy2jvxcJI98Va95Q5JnlKor3m0E7xpMeYRriWklUPsetMSf2NvUQa/E5vVye
# fQIwggZFMIIELaADAgECAhAIMk+dt9qRb2Pk8qM8Xl1RMA0GCSqGSIb3DQEBCwUA
# MFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMu
# QS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBDQTAeFw0yNDA0
# MDQxNDA0MjRaFw0yNzA0MDQxNDA0MjNaMGsxCzAJBgNVBAYTAk5MMRIwEAYDVQQH
# DAlTY2hpam5kZWwxIzAhBgNVBAoMGkpvaG4gQmlsbGVrZW5zIENvbnN1bHRhbmN5
# MSMwIQYDVQQDDBpKb2huIEJpbGxla2VucyBDb25zdWx0YW5jeTCCAaIwDQYJKoZI
# hvcNAQEBBQADggGPADCCAYoCggGBAMslntDbSQwHZXwFhmibivbnd0Qfn6sqe/6f
# os3pKzKxEsR907RkDMet2x6RRg3eJkiIr3TFPwqBooyXXgK3zxxpyhGOcuIqyM9J
# 28DVf4kUyZHsjGO/8HFjrr3K1hABNUszP0o7H3o6J31eqV1UmCXYhQlNoW9FOmRC
# 1amlquBmh7w4EKYEytqdmdOBavAD5Xq4vLPxNP6kyA+B2YTtk/xM27TghtbwFGKn
# u9Vwnm7dFcpLxans4ONt2OxDQOMA5NwgcUv/YTpjhq9qoz6ivG55NRJGNvUXsM3w
# 2o7dR6Xh4MuEGrTSrOWGg2A5EcLH1XqQtkF5cZnAPM8W/9HUp8ggornWnFVQ9/6M
# ga+ermy5wy5XrmQpN+x3u6tit7xlHk1Hc+4XY4a4ie3BPXG2PhJhmZAn4ebNSBwN
# Hh8z7WTT9X9OFERepGSytZVeEP7hgyptSLcuhpwWeR4QdBb7dV++4p3PsAUQVHFp
# wkSbrRTv4EiJ0Lcz9P1HPGFoHiFAQQIDAQABo4IBeDCCAXQwDAYDVR0TAQH/BAIw
# ADA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY2NzY2EyMDIxLmNybC5jZXJ0dW0u
# cGwvY2NzY2EyMDIxLmNybDBzBggrBgEFBQcBAQRnMGUwLAYIKwYBBQUHMAGGIGh0
# dHA6Ly9jY3NjYTIwMjEub2NzcC1jZXJ0dW0uY29tMDUGCCsGAQUFBzAChilodHRw
# Oi8vcmVwb3NpdG9yeS5jZXJ0dW0ucGwvY2NzY2EyMDIxLmNlcjAfBgNVHSMEGDAW
# gBTddF1MANt7n6B0yrFu9zzAMsBwzTAdBgNVHQ4EFgQUO6KtBpOBgmrlANVAnyiQ
# C6W6lJwwSwYDVR0gBEQwQjAIBgZngQwBBAEwNgYLKoRoAYb2dwIFAQQwJzAlBggr
# BgEFBQcCARYZaHR0cHM6Ly93d3cuY2VydHVtLnBsL0NQUzATBgNVHSUEDDAKBggr
# BgEFBQcDAzAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBAEQsN8wg
# PMdWVkwHPPTN+jKpdns5AKVFjcn00psf2NGVVgWWNQBIQc9lEuTBWb54IK6Ga3hx
# QRZfnPNo5HGl73YLmFgdFQrFzZ1lnaMdIcyh8LTWv6+XNWfoyCM9wCp4zMIDPOs8
# LKSMQqA/wRgqiACWnOS4a6fyd5GUIAm4CuaptpFYr90l4Dn/wAdXOdY32UhgzmSu
# xpUbhD8gVJUaBNVmQaRqeU8y49MxiVrUKJXde1BCrtR9awXbqembc7Nqvmi60tYK
# lD27hlpKtj6eGPjkht0hHEsgzU0Fxw7ZJghYG2wXfpF2ziN893ak9Mi/1dmCNmor
# GOnybKYfT6ff6YTCDDNkod4egcMZdOSv+/Qv+HAeIgEvrxE9QsGlzTwbRtbm6gwY
# YcVBs/SsVUdBn/TSB35MMxRhHE5iC3aUTkDbceo/XP3uFhVL4g2JZHpFfCSu2TQr
# rzRn2sn07jfMvzeHArCOJgBW1gPqR3WrJ4hUxL06Rbg1gs9tU5HGGz9KNQMfQFQ7
# 0Wz7UIhezGcFcRfkIfSkMmQYYpsc7rfzj+z0ThfDVzzJr2dMOFsMlfj1T6l22GBq
# 9XQx0A4lcc5Fl9pRxbOuHHWFqIBD/BCEhwniOCySzqENd2N+oz8znKooSISStnkN
# aYXt6xblJF2dx9Dn89FK7d1IquNxOwt0tI5dMIIGYjCCBMqgAwIBAgIRAKQpO24e
# 3denNAiHrXpOtyQwDQYJKoZIhvcNAQEMBQAwVTELMAkGA1UEBhMCR0IxGDAWBgNV
# BAoTD1NlY3RpZ28gTGltaXRlZDEsMCoGA1UEAxMjU2VjdGlnbyBQdWJsaWMgVGlt
# ZSBTdGFtcGluZyBDQSBSMzYwHhcNMjUwMzI3MDAwMDAwWhcNMzYwMzIxMjM1OTU5
# WjByMQswCQYDVQQGEwJHQjEXMBUGA1UECBMOV2VzdCBZb3Jrc2hpcmUxGDAWBgNV
# BAoTD1NlY3RpZ28gTGltaXRlZDEwMC4GA1UEAxMnU2VjdGlnbyBQdWJsaWMgVGlt
# ZSBTdGFtcGluZyBTaWduZXIgUjM2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
# CgKCAgEA04SV9G6kU3jyPRBLeBIHPNyUgVNnYayfsGOyYEXrn3+SkDYTLs1crcw/
# ol2swE1TzB2aR/5JIjKNf75QBha2Ddj+4NEPKDxHEd4dEn7RTWMcTIfm492TW22I
# 8LfH+A7Ehz0/safc6BbsNBzjHTt7FngNfhfJoYOrkugSaT8F0IzUh6VUwoHdYDpi
# ln9dh0n0m545d5A5tJD92iFAIbKHQWGbCQNYplqpAFasHBn77OqW37P9BhOASdmj
# p3IijYiFdcA0WQIe60vzvrk0HG+iVcwVZjz+t5OcXGTcxqOAzk1frDNZ1aw8nFhG
# EvG0ktJQknnJZE3D40GofV7O8WzgaAnZmoUn4PCpvH36vD4XaAF2CjiPsJWiY/j2
# xLsJuqx3JtuI4akH0MmGzlBUylhXvdNVXcjAuIEcEQKtOBR9lU4wXQpISrbOT8ux
# +96GzBq8TdbhoFcmYaOBZKlwPP7pOp5Mzx/UMhyBA93PQhiCdPfIVOCINsUY4U23
# p4KJ3F1HqP3H6Slw3lHACnLilGETXRg5X/Fp8G8qlG5Y+M49ZEGUp2bneRLZoyHT
# yynHvFISpefhBCV0KdRZHPcuSL5OAGWnBjAlRtHvsMBrI3AAA0Tu1oGvPa/4yeei
# Ayu+9y3SLC98gDVbySnXnkujjhIh+oaatsk/oyf5R2vcxHahajMCAwEAAaOCAY4w
# ggGKMB8GA1UdIwQYMBaAFF9Y7UwxeqJhQo1SgLqzYZcZojKbMB0GA1UdDgQWBBSI
# YYyhKjdkgShgoZsx0Iz9LALOTzAOBgNVHQ8BAf8EBAMCBsAwDAYDVR0TAQH/BAIw
# ADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDBKBgNVHSAEQzBBMDUGDCsGAQQBsjEB
# AgEDCDAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28uY29tL0NQUzAIBgZn
# gQwBBAIwSgYDVR0fBEMwQTA/oD2gO4Y5aHR0cDovL2NybC5zZWN0aWdvLmNvbS9T
# ZWN0aWdvUHVibGljVGltZVN0YW1waW5nQ0FSMzYuY3JsMHoGCCsGAQUFBwEBBG4w
# bDBFBggrBgEFBQcwAoY5aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVi
# bGljVGltZVN0YW1waW5nQ0FSMzYuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2Nz
# cC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAYEAAoE+pIZyUSH5ZakuPVKK
# 4eWbzEsTRJOEjbIu6r7vmzXXLpJx4FyGmcqnFZoa1dzx3JrUCrdG5b//LfAxOGy9
# Ph9JtrYChJaVHrusDh9NgYwiGDOhyyJ2zRy3+kdqhwtUlLCdNjFjakTSE+hkC9F5
# ty1uxOoQ2ZkfI5WM4WXA3ZHcNHB4V42zi7Jk3ktEnkSdViVxM6rduXW0jmmiu71Z
# pBFZDh7Kdens+PQXPgMqvzodgQJEkxaION5XRCoBxAwWwiMm2thPDuZTzWp/gUFz
# i7izCmEt4pE3Kf0MOt3ccgwn4Kl2FIcQaV55nkjv1gODcHcD9+ZVjYZoyKTVWb4V
# qMQy/j8Q3aaYd/jOQ66Fhk3NWbg2tYl5jhQCuIsE55Vg4N0DUbEWvXJxtxQQaVR5
# xzhEI+BjJKzh3TQ026JxHhr2fuJ0mV68AluFr9qshgwS5SpN5FFtaSEnAwqZv3IS
# +mlG50rK7W3qXbWwi4hmpylUfygtYLEdLQukNEX1jiOKMIIGgjCCBGqgAwIBAgIQ
# NsKwvXwbOuejs902y8l1aDANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UEBhMCVVMx
# EzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYD
# VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBS
# U0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMjEwMzIyMDAwMDAwWhcNMzgw
# MTE4MjM1OTU5WjBXMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1p
# dGVkMS4wLAYDVQQDEyVTZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIFJvb3Qg
# UjQ2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAiJ3YuUVnnR3d6Lkm
# gZpUVMB8SQWbzFoVD9mUEES0QUCBdxSZqdTkdizICFNeINCSJS+lV1ipnW5ihkQy
# C0cRLWXUJzodqpnMRs46npiJPHrfLBOifjfhpdXJ2aHHsPHggGsCi7uE0awqKggE
# /LkYw3sqaBia67h/3awoqNvGqiFRJ+OTWYmUCO2GAXsePHi+/JUNAax3kpqstbl3
# vcTdOGhtKShvZIvjwulRH87rbukNyHGWX5tNK/WABKf+Gnoi4cmisS7oSimgHUI0
# Wn/4elNd40BFdSZ1EwpuddZ+Wr7+Dfo0lcHflm/FDDrOJ3rWqauUP8hsokDoI7D/
# yUVI9DAE/WK3Jl3C4LKwIpn1mNzMyptRwsXKrop06m7NUNHdlTDEMovXAIDGAvYy
# nPt5lutv8lZeI5w3MOlCybAZDpK3Dy1MKo+6aEtE9vtiTMzz/o2dYfdP0KWZwZIX
# bYsTIlg1YIetCpi5s14qiXOpRsKqFKqav9R1R5vj3NgevsAsvxsAnI8Oa5s2oy25
# qhsoBIGo/zi6GpxFj+mOdh35Xn91y72J4RGOJEoqzEIbW3q0b2iPuWLA911cRxgY
# 5SJYubvjay3nSMbBPPFsyl6mY4/WYucmyS9lo3l7jk27MAe145GWxK4O3m3gEFEI
# kv7kRmefDR7Oe2T1HxAnICQvr9sCAwEAAaOCARYwggESMB8GA1UdIwQYMBaAFFN5
# v1qqK0rPVIDh2JvAnfKyA2bLMB0GA1UdDgQWBBT2d2rdP/0BE/8WoWyCAi/QCj0U
# JTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zATBgNVHSUEDDAKBggr
# BgEFBQcDCDARBgNVHSAECjAIMAYGBFUdIAAwUAYDVR0fBEkwRzBFoEOgQYY/aHR0
# cDovL2NybC51c2VydHJ1c3QuY29tL1VTRVJUcnVzdFJTQUNlcnRpZmljYXRpb25B
# dXRob3JpdHkuY3JsMDUGCCsGAQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0cDov
# L29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEADr5lQe1oRLjl
# ocXUEYfktzsljOt+2sgXke3Y8UPEooU5y39rAARaAdAxUeiX1ktLJ3+lgxtoLQhn
# 5cFb3GF2SSZRX8ptQ6IvuD3wz/LNHKpQ5nX8hjsDLRhsyeIiJsms9yAWnvdYOdEM
# q1W61KE9JlBkB20XBee6JaXx4UBErc+YuoSb1SxVf7nkNtUjPfcxuFtrQdRMRi/f
# InV/AobE8Gw/8yBMQKKaHt5eia8ybT8Y/Ffa6HAJyz9gvEOcF1VWXG8OMeM7Vy7B
# s6mSIkYeYtddU1ux1dQLbEGur18ut97wgGwDiGinCwKPyFO7ApcmVJOtlw9FVJxw
# /mL1TbyBns4zOgkaXFnnfzg4qbSvnrwyj1NiurMp4pmAWjR+Pb/SIduPnmFzbSN/
# G8reZCL4fvGlvPFk4Uab/JVCSmj59+/mB2Gn6G/UYOy8k60mKcmaAZsEVkhOFuoj
# 4we8CYyaR9vd9PGZKSinaZIkvVjbH/3nlLb0a7SBIkiRzfPfS9T+JesylbHa1LtR
# V9U/7m0q7Ma2CQ/t392ioOssXW7oKLdOmMBl14suVFBmbzrt5V5cQPnwtd3UOTpS
# 9oCG+ZZheiIvPgkDmA8FzPsnfXW5qHELB43ET7HHFHeRPRYrMBKjkb8/IN7Po0d0
# hQoF4TeMM+zYAJzoKQnVKOLg8pZVPT8wgga5MIIEoaADAgECAhEAmaOACiZVO2Wr
# 3G6EprPqOTANBgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwxIjAgBgNVBAoT
# GVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0
# aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0
# d29yayBDQSAyMB4XDTIxMDUxOTA1MzIxOFoXDTM2MDUxODA1MzIxOFowVjELMAkG
# A1UEBhMCUEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMgUy5BLjEkMCIG
# A1UEAxMbQ2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBMIICIjANBgkqhkiG9w0B
# AQEFAAOCAg8AMIICCgKCAgEAnSPPBDAjO8FGLOczcz5jXXp1ur5cTbq96y34vuTm
# flN4mSAfgLKTvggv24/rWiVGzGxT9YEASVMw1Aj8ewTS4IndU8s7VS5+djSoMcbv
# IKck6+hI1shsylP4JyLvmxwLHtSworV9wmjhNd627h27a8RdrT1PH9ud0IF+njvM
# k2xqbNTIPsnWtw3E7DmDoUmDQiYi/ucJ42fcHqBkbbxYDB7SYOouu9Tj1yHIohzu
# C8KNqfcYf7Z4/iZgkBJ+UFNDcc6zokZ2uJIxWgPWXMEmhu1gMXgv8aGUsRdaCtVD
# 2bSlbfsq7BiqljjaCun+RJgTgFRCtsuAEw0pG9+FA+yQN9n/kZtMLK+Wo837Q4QO
# ZgYqVWQ4x6cM7/G0yswg1ElLlJj6NYKLw9EcBXE7TF3HybZtYvj9lDV2nT8mFSkc
# SkAExzd4prHwYjUXTeZIlVXqj+eaYqoMTpMrfh5MCAOIG5knN4Q/JHuurfTI5XDY
# O962WZayx7ACFf5ydJpoEowSP07YaBiQ8nXpDkNrUA9g7qf/rCkKbWpQ5boufUnq
# 1UiYPIAHlezf4muJqxqIns/kqld6JVX8cixbd6PzkDpwZo4SlADaCi2JSplKShBS
# ND36E/ENVv8urPS0yOnpG4tIoBGxVCARPCg1BnyMJ4rBJAcOSnAWd18Jx5n858JS
# qPECAwEAAaOCAVUwggFRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFN10XUwA
# 23ufoHTKsW73PMAywHDNMB8GA1UdIwQYMBaAFLahVDkCw6A/joq8+tT4HKbROg79
# MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzAwBgNVHR8EKTAn
# MCWgI6Ahhh9odHRwOi8vY3JsLmNlcnR1bS5wbC9jdG5jYTIuY3JsMGwGCCsGAQUF
# BwEBBGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3AtY2VydHVtLmNv
# bTAyBggrBgEFBQcwAoYmaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL2N0bmNh
# Mi5jZXIwOQYDVR0gBDIwMDAuBgRVHSAAMCYwJAYIKwYBBQUHAgEWGGh0dHA6Ly93
# d3cuY2VydHVtLnBsL0NQUzANBgkqhkiG9w0BAQwFAAOCAgEAdYhYD+WPUCiaU58Q
# 7EP89DttyZqGYn2XRDhJkL6P+/T0IPZyxfxiXumYlARMgwRzLRUStJl490L94C9L
# GF3vjzzH8Jq3iR74BRlkO18J3zIdmCKQa5LyZ48IfICJTZVJeChDUyuQy6rGDxLU
# UAsO0eqeLNhLVsgw6/zOfImNlARKn1FP7o0fTbj8ipNGxHBIutiRsWrhWM2f8pXd
# d3x2mbJCKKtl2s42g9KUJHEIiLni9ByoqIUul4GblLQigO0ugh7bWRLDm0CdY9rN
# LqyA3ahe8WlxVWkxyrQLjH8ItI17RdySaYayX3PhRSC4Am1/7mATwZWwSD+B7eMc
# ZNhpn8zJ+6MTyE6YoEBSRVrs0zFFIHUR08Wk0ikSf+lIe5Iv6RY3/bFAEloMU+vU
# BfSouCReZwSLo8WdrDlPXtR0gicDnytO7eZ5827NS2x7gCBibESYkOh1/w1tVxTp
# V2Na3PR7nxYVlPu1JPoRZCbH86gc96UTvuWiOruWmyOEMLOGGniR+x+zPF/2DaGg
# K2W1eEJfo2qyrBNPvF7wuAyQfiFXLwvWHamoYtPZo0LHuH8X3n9C+xN4YaNjt2yw
# zOr+tKyEVAotnyU9vyEVOaIYMk3IeBrmFnn0gbKeTTyYeEEUz/Qwt4HOUBCrW602
# NCmvO1nm+/80nLy5r0AZvCQxaQ4xggXDMIIFvwIBATBqMFYxCzAJBgNVBAYTAlBM
# MSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0Nl
# cnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBDQQIQCDJPnbfakW9j5PKjPF5dUTANBglg
# hkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3
# DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEV
# MC8GCSqGSIb3DQEJBDEiBCBr70R7KS80JjVtojjQhX7VJ8n3sYjHYzqiKFxnM7eG
# 0jANBgkqhkiG9w0BAQEFAASCAYA6MQ0hnBTcCCVyWvEWqFswGR45ru94W8eWiIJ1
# cBNVo/YW2NnwlhNaKEGUkObXuTbQaLjUoZ1ZiFOL+P7qJNt1JYJ0CHR4fLSFZtJq
# +NMNoy11+IoBIfcSO4seqH5PtQBQ3ClKB2wBGLPQknWbCHSGkc+TxVE8yWz8jKoq
# Ehrr+L/XpisH2JjgyP2UD6j7q4j93b9u1NRik++5tClTrBV3VoNfr6KH6VTqpFMn
# QGIb4msuCfenLE0f5nuJdefHMeFOSkRJNLRGGqxkRRL9qBGFcHuzs+rmkenQIURW
# qlsUujK/9vSXkIwOZycmAgHQhGO8x9hCANWdn0lORNjaoegtwt5m5S9PZKOhWxMv
# Q07QkfvhuHKkjzn8gMv3Np+EyPaN6PmgluR1bqKM0ZDxTGDXtZRDYFtCZ0C4sN6M
# celxWal0cmnzfx0o6/8L/H49oIAuBm88zCwYNxeZlzNDImHnkr1JWhOSfClhEaMR
# 5vS/5buy70c+jsXYokM9g85yLuWhggMjMIIDHwYJKoZIhvcNAQkGMYIDEDCCAwwC
# AQEwajBVMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSww
# KgYDVQQDEyNTZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIENBIFIzNgIRAKQp
# O24e3denNAiHrXpOtyQwDQYJYIZIAWUDBAICBQCgeTAYBgkqhkiG9w0BCQMxCwYJ
# KoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNjAzMTEwODUxMjRaMD8GCSqGSIb3
# DQEJBDEyBDBF4CSXJwtwK4EcoNPxwwVMjvza6DDnp2iMnberyoVowYp/x1cfbqmH
# jWpKqRS+6gEwDQYJKoZIhvcNAQEBBQAEggIAZWLtZ49eqn4oEjU55610DM+sb9lf
# HCB0yunMn7I5g1ZofNT7XwbgylEJar9vPfDJYzqRnXVdFnXBLNCznxMZ8gfCc9jE
# soMAGb2+LkBN7E/ny/W66YCzv0YLE0Xf12DJV1sbu/BWV01nraaZVh3P0JSL0QE9
# zFEWnMiMENHVydvWItQYc+RGPCjLSIoHZRU6d14kGExe7wLLxe7x6cWVSoH3jQbC
# ruPnzjrYLx/4BRCwOLPagqDUogmTjh5SdPgrP/usAcmqYCxMbvfmBdnvlSt+sqAc
# RFn2YyEg8v7jO3qf3KPKAh6AvGIto3a516ZHpkQChBxTyN/whj60hkh8xK7ui+QV
# yWQv9lVXNY/9cO07Tm6WGGsL6FwXZyq29EwfvPtPcb81wxjWOg8TUi/zgwSN28/5
# GKCG7FdmjSpDzCOprtMRQLrIBENh/6jm33ZufuXzXg6EEJUHSwDlxB8JkWd+Fkrj
# QSSAH/Y8iOCu1ZPZenCPPMljLwb1PsyruzD7vVlXsZWeB5iMk2XcxnD7u0oXBHUo
# mv7yuu2FQDnAOY9SF4bOUUx+k9yeDe5fQZ8DQzfPO1JSE1fAw4MGbxHV7PZjTyOQ
# uN9jlBcG/wqJTCqa2qddD4IuS1VvKZZqE9DGx+sO73CfT/B0T0jLKUGpOrABI2r3
# 3ji6cFiR5YfietU=
# SIG # End signature block