Private/RESTHelpers.ps1

<#
SAMPLE CODE NOTICE
 
THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
#>


<#
.SYNOPSIS
    Import this module to get functions to help handling REST calls.
     
.DESCRIPTION
    This script can be imported to enable cmdlets to deal with HTTP connection and JSON messages.
 
.NOTES
    Copyright © 2025 Microsoft. All rights reserved.
#>


<#
.SYNOPSIS
    Create new HttpRequestMessage object and set Json content and authorization header
#>


function New-JsonRequestMessage
{
    param(
        [Parameter(Mandatory=$true)]
        [string] $Uri,
        [Parameter(Mandatory=$true)]
        [System.Security.SecureString] $AccessToken,
        [Parameter(Mandatory=$false)]
        [string] $Content,
        [Parameter(Mandatory=$false)]
        [System.Net.Http.HttpMethod] $HttpMethod = [System.Net.Http.HttpMethod]::Post
    )

    Write-Verbose "Creating request for URI: $Uri"
    $request = New-Object -TypeName System.Net.Http.HttpRequestMessage -ArgumentList @($HttpMethod, $Uri)
    if ($Content)
    {
        $request.Content = New-Object -TypeName System.Net.Http.StringContent -ArgumentList @($Content, [System.Text.Encoding]::UTF8, "application/json")
    }
    $request.Headers.Authorization = "Bearer $(ConvertFrom-SecureStringInternal $AccessToken)"

    return $request
}

function New-EnvironmentRouteRequest
{
    param(
        [Parameter(Mandatory)]
        [string] $EnvironmentId,
        [Parameter(Mandatory)]
        [string] $Path,
        [Parameter(Mandatory)]
        [string] $Query,
        [Parameter(Mandatory)]
        [PPEndpoint] $Endpoint,
        [Parameter(Mandatory=$true)]
        [System.Security.SecureString] $AccessToken,
        [Parameter(Mandatory=$false)]
        [string] $Content,
        [Parameter(Mandatory=$false)]
        [System.Net.Http.HttpMethod] $HttpMethod = [System.Net.Http.HttpMethod]::Post
    )

    $hostName = Get-EnvironmentRouteHostName -Endpoint $Endpoint -EnvironmentId $EnvironmentId
    $uriBuilder = [System.UriBuilder]::new()
    $uriBuilder.Scheme = "https"
    $uriBuilder.Host = $hostName
    $uriBuilder.Path = $Path
    $uriBuilder.Query = $Query

    $request = New-JsonRequestMessage -Uri $uriBuilder.Uri.ToString() -AccessToken $AccessToken -Content $Content -HttpMethod $HttpMethod
    return $request
}

function New-HomeTenantRouteRequest
{
    param(
        [Parameter(Mandatory)]
        [string] $TenantId,
        [Parameter(Mandatory)]
        [string] $Path,
        [Parameter(Mandatory)]
        [string] $Query,
        [Parameter(Mandatory)]
        [PPEndpoint] $Endpoint,
        [Parameter(Mandatory=$true)]
        [System.Security.SecureString] $AccessToken,
        [Parameter(Mandatory=$false)]
        [string] $Content,
        [Parameter(Mandatory=$false)]
        [System.Net.Http.HttpMethod] $HttpMethod = [System.Net.Http.HttpMethod]::Post
    )

    $hostName = Get-TenantRouteHostName -Endpoint $Endpoint -TenantId $TenantId
    $uriBuilder = [System.UriBuilder]::new()
    $uriBuilder.Scheme = "https"
    $uriBuilder.Host = $hostName
    $uriBuilder.Path = $Path
    $uriBuilder.Query = $Query

    $request = New-JsonRequestMessage -Uri $uriBuilder.Uri.ToString() -AccessToken $AccessToken -Content $Content -HttpMethod $HttpMethod
    $request.Headers.Host = $hostName
    return $request
}

<#
.SYNOPSIS
    Gets a singleton HttpClient object or creates a new one and clears Default Request Headers
#>

function Get-HttpClient
{
    if($null -eq $script:httpClient)
    {
        [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls13 -bor [System.Net.SecurityProtocolType]::Tls12

        $script:httpClient = New-Object -TypeName System.Net.Http.HttpClient
        $script:httpClient.DefaultRequestHeaders.Clear()

        $moduleName = "Microsoft.PowerPlatform.EnterprisePolicies"
        $moduleVersion = Get-ModuleVersion
        $osPlatform = [System.Environment]::OSVersion.Platform

        $script:httpClient.DefaultRequestHeaders.UserAgent.Add([System.Net.Http.Headers.ProductInfoHeaderValue]::new($moduleName, $moduleVersion))
        $script:httpClient.DefaultRequestHeaders.Add("x-ms-useragent", "$moduleName/$moduleVersion ($osPlatform)")
    }

    return $script:httpClient
}

<#
.SYNOPSIS
    Given an async Task, await and return its result
#>

function Get-AsyncResult
{
    param(
        [Parameter(Mandatory=$true)]
        $task
    )

    try
    {
        $result = $task.GetAwaiter().GetResult()
    }
    catch
    {
        if ($_.Exception.InnerException)
        {
            # Two levels into inner exceptions have network connection problem messages
            if ($_.Exception.InnerException.InnerException)
            {
                throw $_.Exception.InnerException.InnerException.Message
            }
            else
            {
                throw $_.Exception.InnerException.Message   
            }
        }
        else
        {
            throw $_.Exception.Message
        }
    }

    return $result
}

function Get-EnvironmentRouteHostName {
    param (
        [Parameter(Mandatory)]
        [string] $EnvironmentId,
        [Parameter(Mandatory)]
        [PPEndpoint] $Endpoint
    )

    $baseUri = Get-APIResourceUrl -Endpoint $Endpoint
    # Separate the scheme from the base URI
    $baseUri = $baseUri.Replace("https://", "").Trim('/')
    $EnvironmentId = $EnvironmentId.Replace("-", "")
    if(Test-IsSingleCharEndpoint -Endpoint $Endpoint) {
        $shortEnvId = $EnvironmentId.Substring($EnvironmentId.Length - 1, 1)
        $remainingEnvId = $EnvironmentId.Substring(0, $EnvironmentId.Length - 1)
    }
    else {
        $shortEnvId = $EnvironmentId.Substring($EnvironmentId.Length - 2, 2)
        $remainingEnvId = $EnvironmentId.Substring(0, $EnvironmentId.Length - 2)
    }
    return "$remainingEnvId.$shortEnvId.environment.$baseUri"
}

function Get-TenantRouteHostName {
    param (
        [Parameter(Mandatory)]
        [string] $TenantId,
        [Parameter(Mandatory)]
        [PPEndpoint] $Endpoint
    )

    $baseUri = Get-APIResourceUrl -Endpoint $Endpoint
    # Separate the scheme from the base URI
    $baseUri = $baseUri.Replace("https://", "").Trim('/')
    $TenantId = $TenantId.Replace("-", "")
    if(Test-IsSingleCharEndpoint -Endpoint $Endpoint) {
        $shortTenantId = $TenantId.Substring($TenantId.Length - 1, 1)
        $remainingTenantId = $TenantId.Substring(0, $TenantId.Length - 1)
    }
    else {
        $shortTenantId = $TenantId.Substring($TenantId.Length - 2, 2)
        $remainingTenantId = $TenantId.Substring(0, $TenantId.Length - 2)
    }
    return "il-$remainingTenantId.$shortTenantId.tenant.$baseUri"
}

function Get-PPEndpointUrl {
    param (
        [Parameter(Mandatory)]
        [PPEndpoint] $Endpoint
    )

    switch ($Endpoint) {
        ([PPEndpoint]::tip1) { return "https://tip1.api.bap.microsoft.com/" }
        ([PPEndpoint]::tip2) { return "https://tip2.api.bap.microsoft.com/" }
        ([PPEndpoint]::prod) { return "https://api.bap.microsoft.com/" }
        ([PPEndpoint]::usgovhigh) { return "https://high.api.bap.microsoft.us/" }
        ([PPEndpoint]::dod) { return "https://api.bap.appsplatform.us/" }
        ([PPEndpoint]::china) { return "https://api.bap.partner.microsoftonline.cn/" }
        Default { throw "Unsupported PP endpoint: $Endpoint" }
    }
}

function Get-PPResourceUrl {
    param (
        [Parameter(Mandatory)]
        [PPEndpoint] $Endpoint
    )

    switch ($Endpoint) {
        ([PPEndpoint]::tip1) { return "https://service.powerapps.com/" }
        ([PPEndpoint]::tip2) { return "https://service.powerapps.com/" }
        ([PPEndpoint]::prod) { return "https://service.powerapps.com/" }
        ([PPEndpoint]::usgovhigh) { return "https://high.service.powerapps.us/" }
        ([PPEndpoint]::dod) { return "https://service.apps.appsplatform.us/" }
        ([PPEndpoint]::china) { return "https://service.powerapps.cn/" }
        Default { throw "Unsupported PP endpoint: $Endpoint" }
    }
}


function Get-APIResourceUrl {
    param (
        [Parameter(Mandatory)]
        [PPEndpoint] $Endpoint
    )

    switch ($Endpoint) {
        ([PPEndpoint]::tip1) { return "https://api.preprod.powerplatform.com/" }
        ([PPEndpoint]::tip2) { return "https://api.test.powerplatform.com/" }
        ([PPEndpoint]::prod) { return "https://api.powerplatform.com/" }
        ([PPEndpoint]::usgovhigh) { return "https://api.high.powerplatform.microsoft.us/" }
        ([PPEndpoint]::dod) { return "https://api.appsplatform.us/" }
        ([PPEndpoint]::china) { return "https://api.powerplatform.partner.microsoftonline.cn/" }
        Default { throw "Unsupported PP endpoint: $Endpoint" }
    }
}

function Send-Request {
    <#
    .SYNOPSIS
    Sends an HTTP request once and throws on a non-success status code.
 
    .DESCRIPTION
    Wraps the common request boilerplate: get the singleton HttpClient, send the request,
    extract the x-ms-correlation-id header, and verbose-log the result. On a non-success
    status code, throws an exception that includes the status code, correlation ID, and
    response body. Does not retry — use Send-RequestWithRetries for that.
    #>

    param (
        [Parameter(Mandatory)]
        $Request
    )

    $client = Get-HttpClient
    $result = Get-AsyncResult -Task $client.SendAsync($Request)
    $correlationId = $result.Headers.GetValues("x-ms-correlation-id") | Select-Object -First 1

    if (-not $result.IsSuccessStatusCode) {
        $contentString = Get-AsyncResult -Task $result.Content.ReadAsStringAsync()
        throw "$(Get-LogDate): Request failed: $($contentString.Trim(".")). Status code: $($result.StatusCode). Correlation ID: $correlationId."
    }

    Write-Verbose "$(Get-LogDate): API Call returned $($result.StatusCode). Correlation ID: $correlationId"
    return $result
}

function Send-RequestWithRetries {
    param (
        [Parameter(Mandatory)]
        [int] $MaxRetries,
        [Parameter(Mandatory)]
        [int] $DelaySeconds,
        [Parameter(Mandatory)]
        [scriptblock] $RequestFactory
    )

    $client = Get-HttpClient
    $attempt = 0
    $retryAfterFound = $false
    while ($attempt -lt $MaxRetries) {
        try {
            $sleepSeconds = $DelaySeconds
            $result = Get-AsyncResult -Task $client.SendAsync((& $RequestFactory))

            if(Test-Result -Result $result) {
                return $result
            }
            
            # Check for 503 Service Unavailable or 429 Too Many Requests with Retry-After header
            if ($result.StatusCode -eq 503 -or $result.StatusCode -eq 429) {
                if ($result.Headers.Contains("Retry-After")) {
                    $retryAfterFound = $true
                    $retryAfterValue = $result.Headers.GetValues("Retry-After") | Select-Object -First 1
                    # Retry-After can be either seconds (integer) or HTTP date
                    if ($retryAfterValue -match '^\d+$') {
                        $sleepSeconds = [int]$retryAfterValue
                    } else {
                        try {
                            $retryAfterDate = [DateTime]::Parse($retryAfterValue)
                            if ($retryAfterDate.Kind -ne [System.DateTimeKind]::Utc) {
                                $retryAfterDate = $retryAfterDate.ToUniversalTime()
                            }
                            $sleepSeconds = [Math]::Max(1, [int]($retryAfterDate - [DateTime]::UtcNow).TotalSeconds)
                        } catch {
                            Write-Verbose "Could not parse Retry-After header value: $retryAfterValue. Using default delay."
                            $sleepSeconds = $DelaySeconds
                        }
                    }
                    Write-Host "The service is working on the request and has requested a retry. Waiting for $sleepSeconds seconds as indicated by the Retry-After header..." -ForegroundColor Yellow
                }
            }
            elseif(($result.StatusCode -eq 502 -or $result.StatusCode -eq 503) -and $retryAfterFound) {
                # If we previously saw a Retry-After header, extend the wait time as the gateway might not have the route configured yet.
                $sleepSeconds = 60
                Write-Host "The gateway has not updated the route information yet. Waiting for $sleepSeconds seconds before retrying..." -ForegroundColor Yellow
            }
            $attempt++
        }
        catch {
            $attempt++
            Write-Verbose "Exception on attempt $attempt : $($_.Exception.Message)"
            if($attempt -ge $MaxRetries) {
                throw "Request failed after $MaxRetries attempts. Last error: $($_.Exception.Message)"
            }
        }

        if ($attempt -ge $MaxRetries) {
            Write-Host "Request failed after $MaxRetries attempts." -ForegroundColor Red
            Assert-Result -Result $result
        }
        Write-Verbose "Request failed on attempt $attempt. Retrying in $sleepSeconds seconds..."
        Start-Sleep -Seconds $sleepSeconds
    }
}

function Test-Result {
    param (
        [Parameter(Mandatory)]
        $Result
    )

    $correlationId = $Result.Headers.GetValues("x-ms-correlation-id") | Select-Object -First 1
    if (-not($Result.IsSuccessStatusCode))
    {
        $contentString = Get-AsyncResult -Task $Result.Content.ReadAsStringAsync()
        if ($contentString)
        {
            $errorMessage = $contentString.Trim('.')
            Write-Verbose "$(Get-LogDate): API Call returned $($Result.StatusCode): $($errorMessage). Correlation ID: $correlationId"
            return $false
        }
        else
        {
            Write-Verbose "$(Get-LogDate): API Call returned $($Result.StatusCode): $($Result.ReasonPhrase). Correlation ID: $correlationId"
            return $false
        }
    }
    Write-Verbose "$(Get-LogDate): API Call returned $($Result.StatusCode). Correlation ID: $correlationId"
    return $true
}

function Assert-Result {
    param (
        [Parameter(Mandatory)]
        $Result
    )

    if (-not($Result.IsSuccessStatusCode))
    {
        $contentString = Get-AsyncResult -Task $Result.Content.ReadAsStringAsync()
        if ($contentString)
        {
            $errorMessage = $contentString.Trim('.')
            Write-Verbose "$(Get-LogDate): API Call returned $($Result.StatusCode): $($errorMessage). Correlation ID: $($($Result.Headers.GetValues("x-ms-correlation-id") | Select-Object -First 1))"
            throw "$(Get-LogDate): API Call returned $($Result.StatusCode): $($errorMessage). Correlation ID: $($($Result.Headers.GetValues("x-ms-correlation-id") | Select-Object -First 1))"
        }
        else
        {
            Write-Verbose "$(Get-LogDate): API Call returned $($Result.StatusCode): $($Result.ReasonPhrase). Correlation ID: $($($Result.Headers.GetValues("x-ms-correlation-id") | Select-Object -First 1))"
            throw "$(Get-LogDate): API Call returned $($Result.StatusCode): $($Result.ReasonPhrase). Correlation ID: $($($Result.Headers.GetValues("x-ms-correlation-id") | Select-Object -First 1))"
        }
    }
}

function ConvertFrom-JsonToClass {
    param (
        [string]$Json,
        [Type]$ClassType
    )

    $data = $Json | ConvertFrom-Json

    # Handle array types directly
    if ($ClassType.IsArray) {
        $elementType = $ClassType.GetElementType()
        $itemList = @()
        foreach ($item in $data) {
            $itemJson = $item | ConvertTo-Json -Depth 10
            $itemList += ConvertFrom-JsonToClass -Json $itemJson -ClassType $elementType
        }
        return ,$itemList  
    }
    
    # Handle primitive types and strings
    if ($ClassType.IsPrimitive -or $ClassType -eq [string]) {
        return ($data -as $ClassType)
    }
    # Handle common value types explicitly
    if ($ClassType -eq [DateTime]) {
        return [DateTime]::Parse($data)
    }
    if ($ClassType.FullName -eq 'System.Guid') {
        return [Guid]::Parse($data)
    }
    if ($ClassType.FullName -eq 'System.Decimal') {
        return [Decimal]::Parse($data)
    }
    
    if ($null -eq $data) {
        return $null
    }
    # Handle complex types
    $instance = [Activator]::CreateInstance($ClassType)

    foreach ($property in $ClassType.GetProperties()) {
        $name = $property.Name
        $type = Get-UnderlyingType $property.PropertyType
        if ($data.PSObject.Properties -and $data.PSObject.Properties[$name]) {
            if ($type -eq [hashtable] -or $type.FullName -eq 'System.Collections.Hashtable') {
                $instance.$name = ConvertTo-Hashtable $data.$name
            }
            elseif ($type.IsClass -and $type -ne [string]) {
                $nestedJson = $data.$name | ConvertTo-Json -Depth 10
                $instance.$name = ConvertFrom-JsonToClass -Json $nestedJson -ClassType $type
            }
            elseif ($type.IsEnum){
                $instance.$name = [System.Enum]::Parse($type, $data.$name)
            }
            else {
                $instance.$name = $data.$name
            }
        }
    }

    return $instance
}

function Get-UnderlyingType([type]$t) {
    if ($t.IsGenericType -and $t.GetGenericTypeDefinition().FullName -eq 'System.Nullable`1') {
        return $t.GetGenericArguments()[0]
    }
    return $t
}

function ConvertTo-Hashtable($obj) {
    if ($obj -is [hashtable]) {
        return $obj
    }
    $hash = @{}
    foreach ($property in $obj.PSObject.Properties) {
        $hash[$property.Name] = $property.Value
    }
    return $hash
}

 function Test-IsSingleCharEndpoint {
     param (
         [Parameter(Mandatory)]
         [PPEndpoint] $Endpoint
     )
     return $Endpoint -in @(
         [PPEndpoint]::tip1,
         [PPEndpoint]::tip2,
         [PPEndpoint]::usgovhigh,
         [PPEndpoint]::dod
     )
 }

# SIG # Begin signature block
# MIInbgYJKoZIhvcNAQcCoIInXzCCJ1sCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAWOv1sAjPVU4si
# WcoQ8MapOdyTG2HYTbfihmkjR4QX/KCCDMkwggYEMIID7KADAgECAhMzAAACHPrN
# xZvoL37EAAAAAAIcMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBD
# b2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwNDE2MTg1OTQxWhcNMjcwNDE1MTg1
# OTQxWjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYD
# VQQDExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IB
# DwAwggEKAoIBAQDVsZfgOKmM31HPfoWOoNEiw0SlCiIxUMC0I9NMWbucKOw/e9lP
# oAoehQVu6SG65V4EPzrYsnBnFPNoi4/HoOdjhz1qkrEt4I6tEcxXU6oOeY9zGveC
# /3iBeuhLYxM3M/PkcUoebF+Nednm8OkdSPoDu8imViHPQq/8CQUu0WRR4rE+dMRf
# rpVqfmNi2qWCX94T4MsepijGVkwE//tJg0ryAiYdHT34LSnlG/RSBZmQRGWZ5g8j
# qnKjRParSqMft1gvjuUTVgtWNZfgcLFSK5Wa0myrq8OPcgTGGsRgun+tnSS+IxDT
# xVsAPH1OzvPjwomguByhUe/OcvUN0D5Wmp7xAgMBAAGjggGqMIIBpjAOBgNVHQ8B
# Af8EBAMCB4AwHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0O
# BBYEFNoH7a2YDjOSwpkp6DHcmUS7J+0yMFQGA1UdEQRNMEukSTBHMS0wKwYDVQQL
# EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxFjAUBgNVBAUT
# DTIzMDAxMis1MDc1NjkwHwYDVR0jBBgwFoAUf1k/VCHarU/vBeXmo9ctBpQSCDEw
# YAYDVR0fBFkwVzBVoFOgUYZPaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w
# cy9jcmwvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNy
# bDBtBggrBgEFBQcBAQRhMF8wXQYIKwYBBQUHMAKGUWh0dHA6Ly93d3cubWljcm9z
# b2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmcl
# MjBQQ0ElMjAyMDI0LmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IC
# AQAUnEqhaRXe0T3hIJjvdQErEkrA/7bByjn6t5IArODkkRjzkYwtKMc2yYj2quaN
# rLutWw2YZcngKPy1b71YyDJQTy4NDRwaSh9Tw5thrk3NmcPrAHia5vtcBJ1CgtKK
# 7mQbIcQ22d/N3813ayCDDFewu1+jsZmX+r/aTEqaOM4TVxVtRSkuCy8nAXKuChOK
# Li/zA4XuH8iEYqIsj2YoNaeSxVmeGiERXpKdo3dDmYi0kO5w2D8VS4c3+9h6gElY
# BaAAg/dYErBg27qT3vv0zRDJhJufvCNylA8S7/+8H5E/PV5cng6na9VV/w9OV3qu
# uND6zdGa2EX38Glp50F9AIQk3p2xXmcvorDeM4XJ7UlWYBi6g80J1SSOQnInCYFE
# msfUNn3+1AaTJKSJL83quKArTac2pKhu0Yzzzrzo6HrsRiQKzpnRBb1/dMa6P3hz
# 75XbMRBctNsFhZC07WCmjExdLg2eHW5uV0TY8D5+6wozJf7vF3+WHkYPO85Z+BC6
# U4FkNbYNycZ9cE4j1tXRdyDCfml6c0HWPHjNVDObrv9lKt3qUqFpX38VCqVCyNOO
# 1UcXfQiVjJw32U2WUKZjt/neJKHEBsm9kFsLuWzkQ53+qcaSaytmsCnk2gOglrlD
# 5d3kKyvvAw+rzm0lT8K38P6PLxfZQHhu4W8dV7Av8N2ZmDCCBr0wggSloAMCAQIC
# EzMAAAA5O7Y3Gb8GHWcAAAAAADkwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBS
# b290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDExMB4XDTI0MDgwODIwNTQxOFoX
# DTM2MDMyMjIyMTMwNFowVzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQ
# Q0EgMjAyNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANgBnB7jOMeq
# lRYHNa265v4IY9fH8TKhemHfPINe1gpLaV3dhg324WwH06LcHbpnsBukCDNitryo
# 0dtS/EW6I/yEL/bLSY8hKpbfQuWusBPr9qazYcDxCW/qnjb5JsI1s8bNOg3bVATv
# QVL4tcf03aTycsz8QeCdM0l/yHRObJ9QqazM1r6VPEOJ7LL+uEEb73w6QCuhs89a
# 1uv1zerOYMnsneRRwCbpyW11IcggU0cRKDDq1pjVJzIbIF6+oiXXbReOsgeI8zu1
# FyQfK0fVkaya8SmVHQ/tOf23mZ4W9k0Ri22QW9p3UgSC5OUDktKxxcCmGL6tXLfO
# GSWHIIV4YrTJTT6PNty5REojHJuZHArkF9VnHTERWoTjAzfI3kP+5b4alUdhgAZ7
# ttOu1bVnXfHaqPYl2rPs20ji03LOVWsh/radgE17es5hL+t6lV0eVHrVhsssROWJ
# uz2MXMCt7iw7lFPG9LXKGjsmonn2gotGdHIuEg5JnJMJVmixd5LRlkmgYRZKzhxS
# CwyoGIq0PhaA7Y+VPct5pCHkijcIIDm0nlkK+0KyepolcqGm0T/GYQRMhHJlGOOm
# VQop36wUVUYklUy++vDWeEgEo4s7hxN6mIbf2MSIQ/iIfMZgJxC69oukMUXCrOC3
# SkE/xIkgpfl22MM1itkZ35nNXkMolU1lAgMBAAGjggFOMIIBSjAOBgNVHQ8BAf8E
# BAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFH9ZP1Qh2q1P7wXl5qPX
# LQaUEggxMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMB
# Af8wHwYDVR0jBBgwFoAUci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0fBFMwUTBP
# oE2gS4ZJaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv
# TWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRSMFAw
# TgYIKwYBBQUHMAKGQmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMv
# TWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNydDANBgkqhkiG9w0BAQwFAAOC
# AgEAFJQfOChP7onn6fLIMKrSlN1WYKwDFgAddymOUO3FrM8d7B/W/iQ6DxXsDn7D
# 5W4wMwYeLystcEqfkjz4NURRgazyMu5yRzQh4LqjA4tStTcJh1opExo7nn5PuPBY
# nbu0+THSuVHTe0VTTPVhily/piFrDo3axQ9P4C+Ol5yet+2gTfekICS5xS+cYfSI
# vgn0JksVBVMYVI5QFu/qhnLhsEFEUzG8fvv0hjgkO+lkpV9ty6GkN4vdnd7ya6Q6
# aR9y34aiM1qmxaxBi6OUnyNl6fkuun/diTFnYDLTppOkr/mg5WSfCiDVMNCxtj4w
# PKC5OmHm1DQIt/MNokbbH3UGsFP1QbzsLocuSqLCvH09Io3fDPTmscR9Y75G4qX7
# RTX8AdBPo0I6OEojf39zuFZt0qOHm65YWQE69cZM2ueE1MB05dNNgHK9gTE7zKvK
# /fg8B2qjW88MT/WF5V5uvZGtqa9FSL2RazArA+rDPuf6JGYz4HpgMZHB4S6szWSK
# YBv0VisCzfxgeU+dquXW9bd0auYlOB58DPcOYKdc3Se94g+xL4pcEhbB54JOgAkw
# YTu/9dLeH2pDqeJZAABVDWRQCaXfO5LgyKwKCLYXpigrZYCjUSBcr+Ve8PFWMhVT
# Ql0v4q8J/AUmQN5W4n101cY2L4A7GTQG1h32HHAvfQESWP0xghn7MIIZ9wIBATBu
# MFcxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# KDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMjQCEzMAAAIc
# +s3Fm+gvfsQAAAAAAhwwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwG
# CisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZI
# hvcNAQkEMSIEINSoxKHtAmgv6TMmj5aFwjjclIv+flI8DyjeN5S6NvbiMEIGCisG
# AQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAEggEAMQKIF/cMBXYOz+ln/Fa5
# Mx9woO9EQq52EGjxwPUvW4CpEnDHeeLz87Qrlf1bqMCeRrZq8nBYDG0gpLrChqO/
# vO4zS41+j+wFNZ+39LEnipAmxFe/lUKEDDDH9YkXEZRUcvskhg9LGrO5j9IMDM5N
# GEM5kaqkRoVR76VM5n9/Ot0lPW2fgj6PvZdpfsIk65g3caOy7PEGyr/VqjLKgu8g
# C1y5fdrdR2o1HBA6bZUlPeaD/CTGgmthgs2cfGd2V3SvDWkhqwhnbWMLe0I7nodk
# j9FcvrRqDpyHKkCjMzyF3LzFnNct1yJJo2lxUf2HQuojoYdIMz4J3ehA4Q8euhIz
# DKGCF60wghepBgorBgEEAYI3AwMBMYIXmTCCF5UGCSqGSIb3DQEHAqCCF4YwgheC
# AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFFMIIB
# QQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCAfVye9SYMDLZDtGeDM
# nY75XnMLgXbHDGGo5JcIOCwcgwIGaev5Qh5tGBMyMDI2MDUxMzE4NTk1NC41MjVa
# MASAAgH0oIHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0
# ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo0MzFBLTA1RTAtRDk0NzElMCMG
# A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCEfswggcoMIIFEKAD
# AgECAhMzAAACHUvAkoc4hX45AAEAAAIdMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m
# dCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI1MDgxNDE4NDgzM1oXDTI2MTExMzE4
# NDgzM1owgdMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD
# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTAr
# BgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUG
# A1UECxMeblNoaWVsZCBUU1MgRVNOOjQzMUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxN
# aWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOC
# Ag8AMIICCgKCAgEAorSgaAA8oOl4ph574zw29egUN8DDepRHLX8FM1zHNJmXG6Kr
# SqUKwzcKafopuYdPTETTCvb9aJfESuAU0iGNUFI/D6R0kvdfpe2oPX+E3sbTQvGi
# 4JPH5qdIYUaJ45V/4bqe8eNvbWzpC+ZKjH193DeiI1XAI918JoQmBhlEXo/Ton17
# 21luZJgincsf5LjMY3jX84WyXUSX3dsS7h/7xVI+w1yjg7pa+0y3o/me2Tsv6UJU
# dSTQap5ORGSfCnclnP1z3IiiWIWr3Vo7aIPWsgJzq3m5GxpxUHCQk8qzUhk50y/u
# B+LGE3WIK2C77iy9iFsSfSLUnyMEzGRDW9mXHT4PH7Ozz6CHqQEiNvwcHqlvlCh1
# pHQh1NXQSAqOoVBs5mi6easf6yxWTfe5DrR79503r8pU6VqC2Y9XMRU4wH9QbYXY
# sIUZ33Jmndy22W1LBDAbxBPQHCBlncGDU3BgdhVUVLe80mggFO98FdkWho67w4kP
# dCTRkvdvkY8PrQYE/nQjHXCa0g7LcMttZb6ejMHfQ+tUWXv6+nZ4Ynkr2OkaxclF
# Cw4RIYNMWD26AWbQj/WEdzga18fKtw66L5gzXPza6jFBfPJeKE3H8QAuwpirmH4m
# s+5nUjNNQOmNgqJn0U1+3Yn7ClswD79YN0r3fdbYBMDApBZJpNlK7q7HXRsCAwEA
# AaOCAUkwggFFMB0GA1UdDgQWBBSEWfBxNEamZtXm8gl92Yq80jfxXTAfBgNVHSME
# GDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1l
# LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsG
# AQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p
# Y3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMB
# Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDAN
# BgkqhkiG9w0BAQsFAAOCAgEAkdweB4yxvLspLKq0D+miyD4Q0EcxVFpNZuJxiR54
# gWRkeTDDuymNeB03JhlsBpbwSYJ5uZSgDBCvwHED2VL8lJpFlOprJzxsXWC2NTfA
# +O+PO5Fk5jw6LHh6jeBADDEdQAx3Hqi7Zm0JwvQ93z5f6dtxkm29WqOcHYXRXfAQ
# wy1hSrLXyfeblqR66jpP/9n0fCkWU4ggsUjQpQ2Ngj1DV09J4Y3y7p9Nd81+Xs6q
# Yo++7RKm8qiB/5NDeigOLjlAeFgiEXIRUJW+mJyqpQw+OORlaqcFjR8Hu0G+/7bM
# dek68YX+kPpDBk7Ue+I/xgiYJ1xcDRBn/vczLtN72+RIlD4UgXYLuBSCk//pDEPX
# 5z39Cr+rkc6E4Y28FPk4BhloAyvp628P4xfElQY8TcxraUbZShypocE6ny95D1K1
# BkltZmrHVKCxmglnuOlM15NKIrXFlXCzdqpCtIwQ417wNAVF/QDPvzzbumPdTi6f
# b0tLbScYobV6zvbBsMsKEME4Tj1b9oIXC8dybJq4nbboEXYpRwi1QAbpSNrn+PxG
# W9uf1q63FnMJu4gm3Oh63njW/iVf723quzyHrSijWMgY0HiRiHQi0Jyu0h8MdhRU
# p7mxbmLQckPiOFwAlIaUN/k725y/aLWpkRU6fqmLlEOyH5WpyLd23AYy9r8v+Qob
# a6swggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEB
# CwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD
# VQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAe
# Fw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0
# YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5OGm
# TOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/XE/H
# ZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1hlDc
# wUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7M62A
# W36MEBydUv626GIl3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3KNi1w
# jjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy1cCG
# MFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF803RKJ
# 1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQcNIIP
# 8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahhaYQFz
# ymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkLiWHz
# NgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV2xo3
# xwgVGD94q0W29R6HXtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIGCSsG
# AQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUpzxD/
# LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBTMFEG
# DCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29m
# dC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYB
# BQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8G
# A1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQw
# VgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9j
# cmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUF
# BwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br
# aS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcNAQEL
# BQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1OdfC
# cTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYAA7AF
# vonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbzaN9l
# 9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6LGYnn
# 8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy87JGA0j3mSj5m
# O0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0SCyx
# TkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxkoJLo4
# S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFmPWn9
# y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC4822rpM
# +Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7vzhw
# RNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIDVjCCAj4C
# AQEwggEBoYHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0
# ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo0MzFBLTA1RTAtRDk0NzElMCMG
# A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIa
# AxUAuoO+BKbfXzqyfi9GLEdWHkCLeT+ggYMwgYCkfjB8MQswCQYDVQQGEwJVUzET
# MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV
# TWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T
# dGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsFAAIFAO2u2jEwIhgPMjAyNjA1MTMx
# MTA4MzNaGA8yMDI2MDUxNDExMDgzM1owdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA
# 7a7aMQIBADAHAgEAAgIKITAHAgEAAgISfjAKAgUA7bArsQIBADA2BgorBgEEAYRZ
# CgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0G
# CSqGSIb3DQEBCwUAA4IBAQCevEvzyGenmKW9YcgQyq954HcMZp7RLWTrTdrBqcLi
# lqcUx36Q8dQqa+kG5N0yEVyXVkR1g3Fab25BCApomKCvdgvXoOFFsxkRd4SjJFYs
# hggrqY6ySBI3QXXajBUShVJuu6mowqSe7mRooWiLAvxIfWyCWJQGm/ZqJHgB9fQI
# 7goKXfF8CufqhdRJS1qWI6nslx/wQ3jy2mrOo/2rpXH2ZTPnb9HDYZ+vJs6dJRkL
# SLW5QyzGvyrmdCAFn+aMjktZ67hJPqEUHh0z9ixOXANp8JOA2gGnLZ1vKl87ZvtE
# NNHC1Gw9yagi3fr4zkFoUcXRHehkncz/j35A3RBQ7/BsMYIEDTCCBAkCAQEwgZMw
# fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd
# TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIdS8CShziFfjkAAQAA
# Ah0wDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRAB
# BDAvBgkqhkiG9w0BCQQxIgQgZU5JQDnau2CEz5w32igIWLmG6129xUbr624xwW0x
# F/owgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCCxtpXMXEiLJzrqM77ep4rT
# NwrMOj6gpWN9hZvpj5QFUTCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD
# QSAyMDEwAhMzAAACHUvAkoc4hX45AAEAAAIdMCIEIHCymnRLTfZO3WrrYoMhE2Y3
# x9/9Obg+79XAIV89VZOQMA0GCSqGSIb3DQEBCwUABIICAAua170hpyhuYTdxT7H3
# JnptC8Eid4IiSkxl9wNilcNZBxWr7nlMGAz9rbUwtkjw3kbdYIY+8Npw/E5oDN2F
# HSksBZtlVBdw0gCrqP9e8SNZlFLf8igoQdFgUf7hnBGshh2DhKhhmfEAnio6t++/
# bcEBCcFHQKpxIWees8n1shjbbQcBbM2g5IWPzXtTwz71mRCBvbO3g8QiUWDD0Uuc
# OmcrJZERTTznu2oUY8eiBQsXrzWt3q/5cNwY/+lCtTKhVUZxss6FC3NpzOJK6jce
# 0x17TncAGLyuwSCLJxnx7+AFRclQzb0BxOzxRqNjJzwtuW+Rt9Q7du7pkOyx5mn0
# 1U3pB+tmzPnD8lEE53s0IPE2klADUlmPdmEbWpz58kb2AvxjJIoUuCXfZIQT1BlL
# +gYhOEQN3JoX8beLKAwx2rESE6WafWuTpWUXNO7Sa9qGrzjpA/zbnEWlSdbXa+gK
# ag4tXkxMvezRyMh+EIkD2H9rX+imJ6jVQiyU3UHR9f1xcOTQN3jKgUmnooLqjup2
# WlmqXTR+iIqEBajLkYuJ9+k/gkhDYcc4zRtPBrLBaY0FfqJQ8lWdUqExH6cHUiWN
# 7SkZL6KmUAqWq3n1iqkleMPrd46GVczZoAS/r34LjGImhtuZfyyHdVyoztwQR1a5
# shH5rtk3zqKU7Lr83q6iM21W
# SIG # End signature block