AppVentiX.psm1

<#
    .SYNOPSIS
        This PowerShell module, named AppVentiX, provides functions for managing AppVentiX application deployment.
 
    .NOTES
        Module : AppVentiX
        Author : John Billekens
        Copyright: (c) John Billekens Consultancy & AppVentiX
#>

#Unblock files
Get-ChildItem -Path $PSScriptRoot | Unblock-File

# Get public and private function definition files.
$Public = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction Ignore )
$Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction Ignore )

# Dot source the files
foreach ($import in @($Public + $Private)) {
    try {
        . $import.fullname
    } catch {
        Write-Error -Message "Failed to import function $($import.fullname): $_"
    }
}

# Set alias for Export-AppVentiXPublishingTaskReport
New-Alias -Name Export-AppVentiXPublishing -Value Export-AppVentiXPublishingTaskReport -Force

# Set alias for Export-AppVentiXSeamlessApplicationsReport
New-Alias -Name Export-AppVentiXSeamlessApplications -Value Export-AppVentiXSeamlessApplicationsReport -Force

# Set alias for Get-AppVentiXContentStorePackage (renamed from Get-AppVentiXContentSharePackages: singular
# noun for PSScriptAnalyzer, "ContentStore" matching the ConfigShare->ConfigStore naming convention)
New-Alias -Name Get-AppVentiXContentSharePackages -Value Get-AppVentiXContentStorePackage -Force

$ModuleName = $($MyInvocation.MyCommand.Name) -replace '\.psm1$', ''
$AppDataPath = [System.IO.Path]::Combine($env:APPDATA, $ModuleName)
$Script:AppVentiXConfigFilePath = [System.IO.Path]::Combine($AppDataPath, "$ModuleName.json")
$Script:AppVentiXModuleConfig = $null
$Script:AppVentiXSQLManagementConnection = $null
Update-AppVentiXConfigSettings

#Set module specific variables
# Layout-independent variables. The layout-dependent file path keys (PublishingTasksFilename,
# MachineGroupsFilename, LicenseFilename, etc.) are populated from the layout map below and are
# refreshed whenever the Configuration Store changes (see Set-AppVentiXLayout).
$AppVentiX = [ordered]@{
    CentralViewSettingsFilename = "${Env:PROGRAMDATA}\AppVentiX-CentralView\Settings.xml"
    AgentVersion                = "Unknown"
    ConfigShare                 = $Script:AppVentiXModuleConfig.AppVentiX.ConfigShare
    # The store the currently applied layout was detected for, see Sync-AppVentiXLayout.
    LayoutConfigShare           = $null
    # Identity of the Central View site the store came from, empty when the store was set by path.
    # Set-AppVentiXConfigShare always clears these and Set-AppVentiXSite sets them right after, so
    # they cannot describe a different store than the one in ConfigShare.
    SiteName                    = $null
    SiteGuid                    = $null
    # Bounds every reachability probe of the Configuration Store. An unreachable file server makes a
    # plain Test-Path block for the full SMB timeout, which would stall Import-Module.
    ConfigShareProbeTimeout     = 5
    LicenseValid                = $false
    PublishingExeFilepath       = "C:\Program Files\AppVentiX\AppVentiX Agent\AppVentiX Wrapper.exe"
    ADCache                     = @{}
    ADDomainCache               = @{}
    ManifestCache               = @{}
    PackagePathCache            = @{}
    MachineGroupCache           = @{}
    AgentMSILocations           = @(
        '#ConfigStore#\Agent\AppVentiX Agent.msi',
        'C:\Program Files\AppVentiX\AppVentiX Central View\Agent\AppVentiX Agent.msi'
    )
}

# Seed the layout-dependent keys with the default (v2) layout. The actual layout is detected and
# (re)applied once the Configuration Store path is known, both here on import and in
# Set-AppVentiXConfigShare.
$defaultLayoutMap = Get-AppVentiXLayoutMap -Layout 'v2'
foreach ($key in $defaultLayoutMap.Keys) {
    $AppVentiX[$key] = $defaultLayoutMap[$key]
}

New-Variable -Name AppVentiX -Value $AppVentiX -Scope Script -Force
$Script:PSDefaultParameterValues['*-AdsiAD*:Port'] = 389
$Script:PSDefaultParameterValues['*-AdsiAD*:Server'] = $Env:USERDNSDOMAIN
$Script:PSDefaultParameterValues['*-AdsiAD*:Credential'] = [System.Management.Automation.PSCredential]::Empty

# Debug logging state (controlled by Enable-/Disable-AppVentiXDebugLogging).
# Off by default. When enabled, crucial steps are written as JSONL to AppVentiX-PS-Debug.jsonl
# in $Script:AppVentiXDebugLogPath. State is module-scoped (not a fragile global variable).
$Script:AppVentiXDebugLogEnabled = $false
$Script:AppVentiXDebugLogPath = $null
$Script:AppVentiXDebugLogLastTimestamp = $null

Add-Type -Assembly System.IO.Compression.FileSystem

# DPAPI encrypts the cached Azure Blob sign-in token at rest; the assembly differs by edition.
if ($PSVersionTable.PSEdition -ne 'Core') {
    Add-Type -AssemblyName System.Security
} else {
    Add-Type -AssemblyName System.Security.Cryptography.ProtectedData
}

# Configuration Store credentials live in the module session only, the current user context is used
# when none are set. Set by Connect-AppVentiXConfigShare.
$Script:AppVentiXConfigShareCredential = $null

# Central View sites are read from local files only, so this costs nothing on a machine without
# Central View. Everything that touches the store itself runs after the credentials are applied.
$centralViewSites = @()
$centralViewSettingsFolder = Split-Path -Path $Script:AppVentiX.CentralViewSettingsFilename -Parent
if (Test-Path -Path $centralViewSettingsFolder -PathType Container) {
    try {
        $centralViewSites = @(Get-AppVentiXSite)
    } catch {
        Write-Warning "Could not read the AppVentiX Central View sites: $($_.Exception.Message)"
    }
} else {
    Write-Verbose "AppVentiX Central View is not installed on this machine, no sites to detect."
}

# Store selection: environment variables, then the store saved by Set-AppVentiXConfigShare, then the
# default Central View site.
$resolvedStore = Resolve-AppVentiXConfigShare -SavedConfigShare $Script:AppVentiXModuleConfig.AppVentiX.ConfigShare -Site $centralViewSites
$Script:AppVentiX.ConfigShare = $resolvedStore.ConfigShare
$Script:AppVentiX.SiteName = $resolvedStore.SiteName
$Script:AppVentiX.SiteGuid = $resolvedStore.SiteGuid
Write-Verbose "Configuration Store '$($resolvedStore.ConfigShare)' selected from '$($resolvedStore.Source)'."

# Credentials from the environment overrule the current user context, and have to be applied before
# anything probes the store, otherwise layout detection and the license check run unauthenticated.
if ($Env:AppVentiXConfigShareUsername -and $Env:AppVentiXConfigSharePassword) {
    try {
        $Script:AppVentiXConfigShareCredential = New-Object System.Management.Automation.PSCredential($Env:AppVentiXConfigShareUsername, (ConvertTo-SecureString $Env:AppVentiXConfigSharePassword -AsPlainText -Force))
    } catch {
        Write-Warning "Could not build the Configuration Store credential from `$Env:AppVentiXConfigShareUsername and `$Env:AppVentiXConfigSharePassword: $($_.Exception.Message)"
    }
}
if ($Script:AppVentiXConfigShareCredential -and -not [String]::IsNullOrEmpty($Script:AppVentiX.ConfigShare)) {
    $null = Connect-AppVentiXConfigShare -ConfigShare $Script:AppVentiX.ConfigShare -Credential $Script:AppVentiXConfigShareCredential
}

try {
    $ADParam = @{
        AuthenticateConfigShare = $false
    }
    if ($Env:AppVentiXADDomainUsername -and $Env:AppVentiXADDomainPassword) {
        try {
            $ADParam.Credential = New-Object System.Management.Automation.PSCredential($Env:AppVentiXADDomainUsername, (ConvertTo-SecureString $Env:AppVentiXADDomainPassword -AsPlainText -Force))
            $ADParam.AuthenticateConfigShare = $true
        } catch {
            Write-Warning "Failed to convert Active Directory credential from environment variables. Please ensure that AppVentiXADDomainUsername and AppVentiXADDomainPassword are set correctly or run 'Set-AppVentiXADCredential -Credential (Get-Credential) -AuthenticateConfigShare' first if you need to authenticate to the ConfigShare or 'Set-AppVentiXADCredential -Credential (Get-Credential) -Server your.domain.controller' if you need to authenticate to Active Directory."
            $ADParam.Credential = [System.Management.Automation.PSCredential]::Empty
        }
    }
    if ($Env:AppVentiXADDomainServer) {
        $ADParam.Server = $Env:AppVentiXADDomainServer
    }
    if ($Env:AppVentiXADDomainPort) {
        $ADParam.Port = $Env:AppVentiXADDomainPort
    }
    if ($null -ne $ADParam.Credential -and $ADParam.Credential -ne [System.Management.Automation.PSCredential]::Empty -and $ADParam.Server) {
        try {
            Set-AppVentiXADCredential @ADParam -ErrorAction Stop
        } catch {
            Write-Warning "Failed to authenticate to Active Directory with provided credentials. Please run 'Set-AppVentiXADCredential -Credential (Get-Credential) -AuthenticateConfigShare' first if you need to authenticate to the ConfigShare or 'Set-AppVentiXADCredential -Credential (Get-Credential) -Server your.domain.controller' if you need to authenticate to Active Directory."
        }
    }
} catch {
    Write-Warning "Could not apply the Active Directory credentials from the environment variables: $($_.Exception.Message)"
}

# Everything below touches the Configuration Store, so the store is probed first and that probe is
# bounded by $Script:AppVentiX.ConfigShareProbeTimeout.
if ([String]::IsNullOrEmpty($($Script:AppVentiX.ConfigShare))) {
    Write-Warning "No Configuration Store is configured. Please run 'Set-AppVentiXConfigShare -ConfigShare `"\\path.to\ConfigStore`"' (add '-Credential (Get-Credential)' when the store needs explicit credentials), set the `$Env:AppVentiXConfigShare environment variable before importing the module, or define the '-ConfigShare `"\\path.to\ConfigStore`"' parameter for each function."
} elseif ((Get-AppVentiXStoreBackendType -ConfigShare $Script:AppVentiX.ConfigShare) -eq 'AzureBlob') {
    # Apply the layout first so BackendType and the container/blob map are in module state.
    try {
        $detectedLayout = Set-AppVentiXLayout -ConfigShare $Script:AppVentiX.ConfigShare
        Write-Verbose "AppVentiX Configuration Store layout detected on import: '$detectedLayout'"
    } catch {
        Write-Warning "Could not detect the Configuration Store layout: $($_.Exception.Message)"
    }
    # Silent token check only, never an interactive prompt, so this can't stall Import-Module.
    if (Get-AppVentiXAzureBlobAccessToken) {
        try {
            if (Test-AppVentiXIsLicensed -ConfigShare $Script:AppVentiX.ConfigShare -ErrorAction Stop) {
                Write-AppVentiXLogEntry -Feature "UserAccess" -Action "Import-Module" -Details "AppVentiX module imported and connected to Configuration Store `"$($Script:AppVentiX.ConfigShare)`""
            } else {
                Write-Warning "AppVentiX is (possibly) not licensed for the Configuration Store `"$($Script:AppVentiX.ConfigShare)`"."
            }
        } catch {
            Write-Warning "Could not validate the AppVentiX license: $($_.Exception.Message)"
        }
        try {
            $Script:AppVentiX.AgentVersion = Get-AppVentiXVersion -ConfigShare $Script:AppVentiX.ConfigShare
        } catch {
            Write-Verbose "Failed to detect AppVentiX Agent version."
        }
    } else {
        Write-Warning "No cached Azure sign-in was found for the Configuration Store `"$($Script:AppVentiX.ConfigShare)`". Please run 'Connect-AppVentiXAzureBlobStore -ConfigShare `"$($Script:AppVentiX.ConfigShare)`"' to sign in."
    }
} elseif (-not (Test-AppVentiXPathAvailable -Path $Script:AppVentiX.ConfigShare -TimeoutSeconds $Script:AppVentiX.ConfigShareProbeTimeout)) {
    if ($resolvedStore.ShareAuthenticationmode -ieq 'Specified' -and $null -eq $Script:AppVentiXConfigShareCredential) {
        # Not every Central View settings file carries a SiteName, so only name the site when it has one.
        $siteLabel = if ([String]::IsNullOrEmpty($resolvedStore.SiteName)) { "The AppVentiX Central View site" } else { "The AppVentiX Central View site '$($resolvedStore.SiteName)'" }
        Write-Warning "$siteLabel accesses its Configuration Store `"$($Script:AppVentiX.ConfigShare)`" with specified credentials, but none were supplied. Please run 'Set-AppVentiXConfigShare -ConfigShare `"$($Script:AppVentiX.ConfigShare)`" -Credential (Get-Credential)', or set the `$Env:AppVentiXConfigShareUsername and `$Env:AppVentiXConfigSharePassword environment variables before importing the module."
    } else {
        Write-Warning "Could not reach the Configuration Store `"$($Script:AppVentiX.ConfigShare)`" within $($Script:AppVentiX.ConfigShareProbeTimeout) seconds. Please check the path, and if the store needs explicit credentials run 'Set-AppVentiXConfigShare -ConfigShare `"$($Script:AppVentiX.ConfigShare)`" -Credential (Get-Credential)'."
    }
} else {
    try {
        # Detect the Configuration Store layout (v1/v2) and apply the matching relative file paths.
        $detectedLayout = Set-AppVentiXLayout -ConfigShare $Script:AppVentiX.ConfigShare
        Write-Verbose "AppVentiX Configuration Store layout detected on import: '$detectedLayout'"
    } catch {
        Write-Warning "Could not detect the Configuration Store layout: $($_.Exception.Message)"
    }
    try {
        if (Test-AppVentiXIsLicensed -ConfigShare $Script:AppVentiX.ConfigShare -ErrorAction Stop) {
            Write-AppVentiXLogEntry -Feature "UserAccess" -Action "Import-Module" -Details "AppVentiX module imported and connected to Configuration Store `"$($Script:AppVentiX.ConfigShare)`""
        } else {
            Write-Warning "AppVentiX is (possibly) not licensed for the Configuration Store `"$($Script:AppVentiX.ConfigShare)`"."
        }
    } catch {
        Write-Warning "Could not validate the AppVentiX license: $($_.Exception.Message)"
    }
    try {
        $Script:AppVentiX.AgentVersion = Get-AppVentiXVersion -ConfigShare $Script:AppVentiX.ConfigShare
    } catch {
        Write-Verbose "Failed to detect AppVentiX Agent version."
    }
}
if ($Script:AppVentiX.LicenseValid -eq $true) {
    $sites = @(Get-AppVentiXSite | Where-Object {$_.Configurationshare -ieq "$($Script:AppVentiX.ConfigShare)"} | Select-Object -ExpandProperty SiteName)
    if ($sites.count -eq 1){
        $siteText = " [Site: $($sites[0])]"
    } else {
        $siteText = " [Site: Unknown]"
    }
    Write-Information -MessageData "`r`nConnected to Configuration Store: `"$($Script:AppVentiX.ConfigShare)`"$siteText`r`n" -InformationAction Continue
}

# SIG # Begin signature block
# MII5ywYJKoZIhvcNAQcCoII5vDCCObgCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCSiWEXIC2MUjqK
# QPEj95mlOQ7EUD/icA3oxBn++eIsLqCCIfAwggXMMIIDtKADAgECAhBUmNLR1FsZ
# lUgTecgRwIeZMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVu
# dGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAy
# MDAeFw0yMDA0MTYxODM2MTZaFw00NTA0MTYxODQ0NDBaMHcxCzAJBgNVBAYTAlVT
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jv
# c29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo
# b3JpdHkgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALORKgeD
# Bmf9np3gx8C3pOZCBH8Ppttf+9Va10Wg+3cL8IDzpm1aTXlT2KCGhFdFIMeiVPvH
# or+Kx24186IVxC9O40qFlkkN/76Z2BT2vCcH7kKbK/ULkgbk/WkTZaiRcvKYhOuD
# PQ7k13ESSCHLDe32R0m3m/nJxxe2hE//uKya13NnSYXjhr03QNAlhtTetcJtYmrV
# qXi8LW9J+eVsFBT9FMfTZRY33stuvF4pjf1imxUs1gXmuYkyM6Nix9fWUmcIxC70
# ViueC4fM7Ke0pqrrBc0ZV6U6CwQnHJFnni1iLS8evtrAIMsEGcoz+4m+mOJyoHI1
# vnnhnINv5G0Xb5DzPQCGdTiO0OBJmrvb0/gwytVXiGhNctO/bX9x2P29Da6SZEi3
# W295JrXNm5UhhNHvDzI9e1eM80UHTHzgXhgONXaLbZ7LNnSrBfjgc10yVpRnlyUK
# xjU9lJfnwUSLgP3B+PR0GeUw9gb7IVc+BhyLaxWGJ0l7gpPKWeh1R+g/OPTHU3mg
# trTiXFHvvV84wRPmeAyVWi7FQFkozA8kwOy6CXcjmTimthzax7ogttc32H83rwjj
# O3HbbnMbfZlysOSGM1l0tRYAe1BtxoYT2v3EOYI9JACaYNq6lMAFUSw0rFCZE4e7
# swWAsk0wAly4JoNdtGNz764jlU9gKL431VulAgMBAAGjVDBSMA4GA1UdDwEB/wQE
# AwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIftJqhSobyhmYBAcnz1AQ
# T2ioojAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQwFAAOCAgEAr2rd5hnn
# LZRDGU7L6VCVZKUDkQKL4jaAOxWiUsIWGbZqWl10QzD0m/9gdAmxIR6QFm3FJI9c
# Zohj9E/MffISTEAQiwGf2qnIrvKVG8+dBetJPnSgaFvlVixlHIJ+U9pW2UYXeZJF
# xBA2CFIpF8svpvJ+1Gkkih6PsHMNzBxKq7Kq7aeRYwFkIqgyuH4yKLNncy2RtNwx
# AQv3Rwqm8ddK7VZgxCwIo3tAsLx0J1KH1r6I3TeKiW5niB31yV2g/rarOoDXGpc8
# FzYiQR6sTdWD5jw4vU8w6VSp07YEwzJ2YbuwGMUrGLPAgNW3lbBeUU0i/OxYqujY
# lLSlLu2S3ucYfCFX3VVj979tzR/SpncocMfiWzpbCNJbTsgAlrPhgzavhgplXHT2
# 6ux6anSg8Evu75SjrFDyh+3XOjCDyft9V77l4/hByuVkrrOj7FjshZrM77nq81YY
# uVxzmq/FdxeDWds3GhhyVKVB0rYjdaNDmuV3fJZ5t0GNv+zcgKCf0Xd1WF81E+Al
# GmcLfc4l+gcK5GEh2NQc5QfGNpn0ltDGFf5Ozdeui53bFv0ExpK91IjmqaOqu/dk
# ODtfzAzQNb50GQOmxapMomE2gj4d8yu8l13bS3g7LfU772Aj6PXsCyM2la+YZr9T
# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggalMIIEjaADAgECAhMzAAbxHabe
# pFDFgGHZAAAABvEdMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ
# RCBWZXJpZmllZCBDUyBBT0MgQ0EgMDMwHhcNMjYwOTIyMTYzNDE3WhcNMjYwOTI1
# MTYzNDE3WjBoMQswCQYDVQQGEwJOTDEWMBQGA1UECBMNTm9vcmQtSG9sbGFuZDEP
# MA0GA1UEBxMGSGVpbG9vMRcwFQYDVQQKEw5BcHBWZW50aVggQi5WLjEXMBUGA1UE
# AxMOQXBwVmVudGlYIEIuVi4wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIB
# gQCKHxMyJ3ev7MjDoA0e7avtmEtdvA5DmkkP0U8++26F6Gxi7ckEdKw+UVK5AN1G
# 19oMlmi4edOdPIzeI1bwXQ609WDn6rxM1oGHkSo5+jvjr93hWxm+e1ZxRBRfG/VB
# pLZca32lTzI2c+ruEbBhLG4pjLTGwR3weiibHY+tkG+UGzWZt/6pCiAymQK+4F3/
# oDTxmdlOLSIXbuy6gul+jK4zMlqsl0bAYjJUJfRF599R655OY7uyYTg/AoEyDA6o
# MarYhaJqItrDUW/t0/2cJIOdFIWzDG3uCI5W2H1CgeoAO8R8w3DzXOhduwpycF0n
# lRhZuvZKrbL6NlVAFCmd6ga72TYxvFO/laAg6HbvG3KDl4DnsY1dU2UkUb8K3p5w
# 1A8N/n2pOSqL+qXzMmKQ2qYg5m+78QhBPU3SB3wVf71idbJpesrraAAUTz4Y1GoX
# 97ZsvQlVApceXkMfNbphVEJVcjothZOzhSyVM7muvnbir1j4BOhDlPcqcS2sXKvV
# DfkCAwEAAaOCAdQwggHQMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMDsG
# A1UdJQQ0MDIGCisGAQQBgjdhAQAGCCsGAQUFBwMDBhorBgEEAYI3YaL8yC6uh9F6
# gZ2lyVCBwcKCJzAdBgNVHQ4EFgQUGRQ8WX/GdDskB0leROkR25M/JqQwHwYDVR0j
# BBgwFoAUpEMMf3ZapYXnPo0oDwwXokVpcMYwZwYDVR0fBGAwXjBcoFqgWIZWaHR0
# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSUQl
# MjBWZXJpZmllZCUyMENTJTIwQU9DJTIwQ0ElMjAwMy5jcmwwdAYIKwYBBQUHAQEE
# aDBmMGQGCCsGAQUFBzAChlhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz
# L2NlcnRzL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUyMEFPQyUyMENB
# JTIwMDMuY3J0MFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0w
# DQYJKoZIhvcNAQEMBQADggIBAJp+n/ro+nj0idI78wJh1JjI4O/0kdkubxUT1H2c
# aahqzNSBnUrFboYgaexusANXzb0iop2vQgDMWcvfoJqJ8K5TtOHMZda+81Cpa+Gl
# JNJ5m6elK3FGqTBOrnYp1h1A4in5S6Po5KE/pwciiBg00Zx6W2FjzXKsvbOsmy+Q
# oR2C4oShB2Ydu96+SmK5niz7/RRl/WoNVbRihHUduyHwjPVyiu2LSaDAKn5plzj7
# hzngzhqAzOnyxEhOtx3oWmYylXCaUWVroG0JFFGZ9IvlPBwHAzlqCsbn96drBEUD
# wjJ45E/C9sDLAhIcIMXMWeXYosI4u1qNCMAEcjTwZs5js2QGOYqRlXaVoGtU/QAv
# /O2HnZK+a62vNDXD/4gU3vULrqHzO+qRcCGmEYZPIlsyVRXZMb+6GYkug8OxABs4
# yqE0oBVG7C7VCd3Uhcan4O5D8xW7cbwGoeXJG7fvXOHEN9lEuWt5jtWg9YgrU88I
# fWrPMQRVLNCGOmPD+nm608IueiorIxHfpic3fFzFXZDEwWBesn8ISIjG7bLmxm82
# +5ZKfUlanQcekjqmRvHeQ3P1A8TjaULHRnJruIj6tFTK18ej1dWWIb6X9QTAZj/w
# dj0/nQKr8iqtAhULbx30T4ZbDyqSHLmnvagGFmDb8xUV7AJ+siksCBc5m6ptgxkj
# 00ZTMIIGpTCCBI2gAwIBAgITMwAG8R2m3qRQxYBh2QAAAAbxHTANBgkqhkiG9w0B
# AQwFADBaMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSswKQYDVQQDEyJNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ1MgQU9DIENBIDAz
# MB4XDTI2MDkyMjE2MzQxN1oXDTI2MDkyNTE2MzQxN1owaDELMAkGA1UEBhMCTkwx
# FjAUBgNVBAgTDU5vb3JkLUhvbGxhbmQxDzANBgNVBAcTBkhlaWxvbzEXMBUGA1UE
# ChMOQXBwVmVudGlYIEIuVi4xFzAVBgNVBAMTDkFwcFZlbnRpWCBCLlYuMIIBojAN
# BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAih8TMid3r+zIw6ANHu2r7ZhLXbwO
# Q5pJD9FPPvtuhehsYu3JBHSsPlFSuQDdRtfaDJZouHnTnTyM3iNW8F0OtPVg5+q8
# TNaBh5EqOfo746/d4VsZvntWcUQUXxv1QaS2XGt9pU8yNnPq7hGwYSxuKYy0xsEd
# 8Hoomx2PrZBvlBs1mbf+qQogMpkCvuBd/6A08ZnZTi0iF27suoLpfoyuMzJarJdG
# wGIyVCX0ReffUeueTmO7smE4PwKBMgwOqDGq2IWiaiLaw1Fv7dP9nCSDnRSFswxt
# 7giOVth9QoHqADvEfMNw81zoXbsKcnBdJ5UYWbr2Sq2y+jZVQBQpneoGu9k2MbxT
# v5WgIOh27xtyg5eA57GNXVNlJFG/Ct6ecNQPDf59qTkqi/ql8zJikNqmIOZvu/EI
# QT1N0gd8FX+9YnWyaXrK62gAFE8+GNRqF/e2bL0JVQKXHl5DHzW6YVRCVXI6LYWT
# s4UslTO5rr524q9Y+AToQ5T3KnEtrFyr1Q35AgMBAAGjggHUMIIB0DAMBgNVHRMB
# Af8EAjAAMA4GA1UdDwEB/wQEAwIHgDA7BgNVHSUENDAyBgorBgEEAYI3YQEABggr
# BgEFBQcDAwYaKwYBBAGCN2Gi/MgurofReoGdpclQgcHCgicwHQYDVR0OBBYEFBkU
# PFl/xnQ7JAdJXkTpEduTPyakMB8GA1UdIwQYMBaAFKRDDH92WqWF5z6NKA8MF6JF
# aXDGMGcGA1UdHwRgMF4wXKBaoFiGVmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
# a2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUyMEFPQyUy
# MENBJTIwMDMuY3JsMHQGCCsGAQUFBwEBBGgwZjBkBggrBgEFBQcwAoZYaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBJRCUy
# MFZlcmlmaWVkJTIwQ1MlMjBBT0MlMjBDQSUyMDAzLmNydDBUBgNVHSAETTBLMEkG
# BFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br
# aW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMA0GCSqGSIb3DQEBDAUAA4ICAQCafp/6
# 6Pp49InSO/MCYdSYyODv9JHZLm8VE9R9nGmoaszUgZ1KxW6GIGnsbrADV829IqKd
# r0IAzFnL36CaifCuU7ThzGXWvvNQqWvhpSTSeZunpStxRqkwTq52KdYdQOIp+Uuj
# 6OShP6cHIogYNNGcelthY81yrL2zrJsvkKEdguKEoQdmHbvevkpiuZ4s+/0UZf1q
# DVW0YoR1Hbsh8Iz1corti0mgwCp+aZc4+4c54M4agMzp8sRITrcd6FpmMpVwmlFl
# a6BtCRRRmfSL5TwcBwM5agrG5/enawRFA8IyeORPwvbAywISHCDFzFnl2KLCOLta
# jQjABHI08GbOY7NkBjmKkZV2laBrVP0AL/zth52SvmutrzQ1w/+IFN71C66h8zvq
# kXAhphGGTyJbMlUV2TG/uhmJLoPDsQAbOMqhNKAVRuwu1Qnd1IXGp+DuQ/MVu3G8
# BqHlyRu371zhxDfZRLlreY7VoPWIK1PPCH1qzzEEVSzQhjpjw/p5utPCLnoqKyMR
# 36YnN3xcxV2QxMFgXrJ/CEiIxu2y5sZvNvuWSn1JWp0HHpI6pkbx3kNz9QPE42lC
# x0Zya7iI+rRUytfHo9XVliG+l/UEwGY/8HY9P50Cq/IqrQIVC28d9E+GWw8qkhy5
# p72oBhZg2/MVFewCfrIpLAgXOZuqbYMZI9NGUzCCBygwggUQoAMCAQICEzMAAAAY
# DeuRVamKAJgAAAAAABgwDQYJKoZIhvcNAQEMBQAwYzELMAkGA1UEBhMCVVMxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE0MDIGA1UEAxMrTWljcm9zb2Z0
# IElEIFZlcmlmaWVkIENvZGUgU2lnbmluZyBQQ0EgMjAyMTAeFw0yNjAzMjYxODEx
# MzJaFw0zMTAzMjYxODExMzJaMFoxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJRCBWZXJpZmll
# ZCBDUyBBT0MgQ0EgMDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDI
# gNpgNFaiif2VWeWP5I6PnFXxJ/lB37fJR55GCvR7GLZBMkBijbiKVwgpBI3xM5nf
# 484znH/qncJ+OCq6y3jgnQW+R8Zd7U+7LjlrmcskalzSQ0ghMxEpnBW8/HHs2V8Z
# JzQk6HP+SDsbvsL7LdlH/eO2l4mknhDBwr0Z/Q966TvEth5b8kCxj1vqiV4YNthL
# GRqZR9u2fK/yBMWu83p6O4uo2Edg++gEew5IL7vnnnKFqmSh/R9vPJy3WF1YcZew
# AUx8sXZNUnx3ZhVg59l2LpitPiwzE6FMqIsqaEvVe3MzuFd2a/uWDZH6VbDyUiRK
# 78mIg1DQYA9zDEyyBFcNI+nxVSzglvL6u7PRuNqgcV3sf6ELxw89ysQM/Z4R1hRF
# WXRpyOWKKAKtfBHTk0UnNiPcxmLMMYs8jeUjOidfVPjTIry/UVwnwxdlkK85cZfB
# EMYZ/DBNOwdomP459Y1n8izKkbhsa+p4lw+cQVxATBFx9ggR79HhryT7HDmpPLvk
# JvBZ4wW4CW32UT2SMyDe28nIOU3m+hfHlVeKcLBQcym5VoRDjIcCVI7uqgGW2PNM
# E0cfei8zCwCy6HCsssJWFS7eg/YbFhnATJcyWfMrkNuAbMfMN8Npg8crS6jVVowy
# D0GG5zdgi+uQVcSK/638mA1xEYK3pnIoQgO09uuDBwIDAQABo4IB3DCCAdgwDgYD
# VR0PAQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBSkQwx/dlql
# hec+jSgPDBeiRWlwxjBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYz
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnku
# aHRtMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMBIGA1UdEwEB/wQIMAYBAf8C
# AQAwHwYDVR0jBBgwFoAU2UEpsA8PY2zvadf1zSmepEhqMOYwcAYDVR0fBGkwZzBl
# oGOgYYZfaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9z
# b2Z0JTIwSUQlMjBWZXJpZmllZCUyMENvZGUlMjBTaWduaW5nJTIwUENBJTIwMjAy
# MS5jcmwwfQYIKwYBBQUHAQEEcTBvMG0GCCsGAQUFBzAChmFodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIwVmVyaWZp
# ZWQlMjBDb2RlJTIwU2lnbmluZyUyMFBDQSUyMDIwMjEuY3J0MA0GCSqGSIb3DQEB
# DAUAA4ICAQBxxyBW+X6mhdRiSwD9PMMWcGUAnx5/QUwnNvZdFGEX+4DRDIr9WCh4
# C87wHtw+lg1D3uzK10DstPX0LFLBFAC3vWMYX4ImXwoLhoR0xlN8mUdorJ3bgnpC
# JWuI1531Z1rCwPuUrSkBxfOIGDk3p2ECb3Ho/xHi5PRSR/OUrWuQHwXiaXMTuXu3
# IRLezwVkZpFmNwYRD57R9Nx2F/yM7tzOY0Hh0hGCaYEK38/6FrS0SXadXWyDUCfn
# 5XOGACRjUCnHx+JQUG0f4SHD+iblpAI0gl+ZHnVmdXXxHTZeTa0CYCIhFxKP2922
# s0g6zLmeiV13LWUmtt/UF7TrWXpMi2/0UNniaDoH7rnPGRV5xVX8uXy4sZii4asw
# zqPM7Y7+mzcranqZ8EjZk5gjLhQ3A2sZaprlOu8CaRmyfcIiVH7zVfgAvm81MWXF
# ziAf7my7QOvnyEFPGddq8MSfPtfRyw/Uq3uH6KpoaJNIfPYH6fceZSi53Rat1A9g
# rExq3ROjhhSpTcchuBItAMNVPxoKNbUm+iR/X3XkL+9WQginjyHe+hXLclY8vAGX
# FD1p40PqMIpAYsmEJBFKW9df4//1N5oQDr/FY9IBJl/oSS979i5rtT7NZz9KvYra
# CPRBGs0QCy+sWvgQa0coM70QJVLeVwmSxUO/0od0w9Qry7bSLrxGoDCCB54wggWG
# oAMCAQICEzMAAAAHh6M0o3uljhwAAAAAAAcwDQYJKoZIhvcNAQEMBQAwdzELMAkG
# A1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjFIMEYGA1UE
# AxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNhdGlvbiBSb290IENlcnRpZmlj
# YXRlIEF1dGhvcml0eSAyMDIwMB4XDTIxMDQwMTIwMDUyMFoXDTM2MDQwMTIwMTUy
# MFowYzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjE0MDIGA1UEAxMrTWljcm9zb2Z0IElEIFZlcmlmaWVkIENvZGUgU2lnbmluZyBQ
# Q0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALLwwK8ZiCji
# 3VR6TElsaQhVCbRS/3pK+MHrJSj3Zxd3KU3rlfL3qrZilYKJNqztA9OQacr1AwoN
# cHbKBLbsQAhBnIB34zxf52bDpIO3NJlfIaTE/xrweLoQ71lzCHkD7A4As1Bs076I
# u+mA6cQzsYYH/Cbl1icwQ6C65rU4V9NQhNUwgrx9rGQ//h890Q8JdjLLw0nV+ayQ
# 2Fbkd242o9kH82RZsH3HEyqjAB5a8+Ae2nPIPc8sZU6ZE7iRrRZywRmrKDp5+Tcm
# JX9MRff241UaOBs4NmHOyke8oU1TYrkxh+YeHgfWo5tTgkoSMoayqoDpHOLJs+qG
# 8Tvh8SnifW2Jj3+ii11TS8/FGngEaNAWrbyfNrC69oKpRQXY9bGH6jn9NEJv9weF
# xhTwyvx9OJLXmRGbAUXN1U9nf4lXezky6Uh/cgjkVd6CGUAf0K+Jw+GE/5VpIVbc
# Nr9rNE50Sbmy/4RTCEGvOq3GhjITbCa4crCzTTHgYYjHs1NbOc6brH+eKpWLtr+b
# Gecy9CrwQyx7S/BfYJ+ozst7+yZtG2wR461uckFu0t+gCwLdN0A6cFtSRtR8bvxV
# FyWwTtgMMFRuBa3vmUOTnfKLsLefRaQcVTgRnzeLzdpt32cdYKp+dhr2ogc+qM6K
# 4CBI5/j4VFyC4QFeUP2YAidLtvpXRRo3AgMBAAGjggI1MIICMTAOBgNVHQ8BAf8E
# BAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNlBKbAPD2Ns72nX9c0p
# nqRIajDmMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wGQYJ
# KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME
# GDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYDVR0fBH0wezB5oHegdYZzaHR0
# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSWRl
# bnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUlMjBBdXRo
# b3JpdHklMjAyMDIwLmNybDCBwwYIKwYBBQUHAQEEgbYwgbMwgYEGCCsGAQUFBzAC
# hnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29m
# dCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRpZmljYXRl
# JTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwLQYIKwYBBQUHMAGGIWh0dHA6Ly9vbmVv
# Y3NwLm1pY3Jvc29mdC5jb20vb2NzcDANBgkqhkiG9w0BAQwFAAOCAgEAfyUqnv7U
# q+rdZgrbVyNMul5skONbhls5fccPlmIbzi+OwVdPQ4H55v7VOInnmezQEeW4LqK0
# wja+fBznANbXLB0KrdMCbHQpbLvG6UA/Xv2pfpVIE1CRFfNF4XKO8XYEa3oW8oVH
# +KZHgIQRIwAbyFKQ9iyj4aOWeAzwk+f9E5StNp5T8FG7/VEURIVWArbAzPt9ThVN
# 3w1fAZkF7+YU9kbq1bCR2YD+MtunSQ1Rft6XG7b4e0ejRA7mB2IoX5hNh3UEauY0
# byxNRG+fT2MCEhQl9g2i2fs6VOG19CNep7SquKaBjhWmirYyANb0RJSLWjinMLXN
# OAga10n8i9jqeprzSMU5ODmrMCJE12xS/NWShg/tuLjAsKP6SzYZ+1Ry358ZTFcx
# 0FS/mx2vSoU8s8HRvy+rnXqyUJ9HBqS0DErVLjQwK8VtsBdekBmdTbQVoCgPCqr+
# PDPB3xajYnzevs7eidBsM71PINK2BoE2UfMwxCCX3mccFgx6UsQeRSdVVVNSyALQ
# e6PT12418xon2iDGE81OGCreLzDcMAZnrUAx4XQLUz6ZTl65yPUiOh3k7Yww94lD
# f+8oG2oZmDh5O1Qe38E+M3vhKwmzIeoB1dVLlz4i3IpaDcR+iuGjH2TdaC1ZOmBX
# iCRKJLj4DT2uhJ04ji+tHD6n58vhavFIrmcxghcxMIIXLQIBATBxMFoxCzAJBgNV
# BAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMT
# Ik1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBBT0MgQ0EgMDMCEzMABvEdpt6kUMWA
# YdkAAAAG8R0wDQYJYIZIAWUDBAIBBQCgXjAQBgorBgEEAYI3AgEMMQIwADAZBgkq
# hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAvBgkqhkiG9w0BCQQxIgQgE2xbrBHivYvJ
# xvIad0Urjt3dMJMiZYL8a9Zf+ImnPpUwDQYJKoZIhvcNAQEBBQAEggGAHZiQM7d+
# Z9LfHjTDVa3wFnRUxwyewXpIA7nIa0NQnnSxJE4XU1ObB26OmuWstpiKGjMWIpcV
# vyaUOVt9IjH33Y9fUfH/PZWuOIeGj1vyTW70FbKtwCR4WfCtuEm7ZK7UVtj0THhV
# HpqgfEh+zEqdWBtQQQZPw35zgHwEVHBzEjqBCZuYu4usr2GtoDGqYQLTt7JCVcDR
# YTeZy87OlDwnvUYzUezusThiUew9I25ra+Bu3/xArRN1kJknT/zwNpuAF/LZaoBu
# mmWVj7UsB3MfeN9n2rxpMUsd18SIPqSwioHuq5yzGuDGgW1ES1wG5Blv9ghOCPnb
# 6+QZ7DyYfbtuFpJEf0X2hgoUGDILFT0PHmrKo73Jcf6TDYoar93Y9ARh/69hCzcA
# BvJhjjV5vOssngsPtasla2Hk3zrgc0fVxwUIpSuaVinpfXM2IKDOM06bS34FJben
# wZbBPGkeSgSjEt+Pzn/GcjSC6ywW+mTNy7NC277Iq07TfqGgJ452pM5doYIUsTCC
# FK0GCisGAQQBgjcDAwExghSdMIIUmQYJKoZIhvcNAQcCoIIUijCCFIYCAQMxDzAN
# BglghkgBZQMEAgEFADCCAWkGCyqGSIb3DQEJEAEEoIIBWASCAVQwggFQAgEBBgor
# BgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEILi6LSwtfQ039cNaAaS/sCkZlAjg
# ggUIaSr7cFp2SW1zAgZqNTDnrZ0YEjIwMjYwOTIzMTk1NDA1LjUxWjAEgAIB9KCB
# 6aSB5jCB4zELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV
# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsG
# A1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMScwJQYD
# VQQLEx5uU2hpZWxkIFRTUyBFU046NDkxQS0wNUUwLUQ5NDcxNTAzBgNVBAMTLE1p
# Y3Jvc29mdCBQdWJsaWMgUlNBIFRpbWUgU3RhbXBpbmcgQXV0aG9yaXR5oIIPKTCC
# B4IwggVqoAMCAQICEzMAAAAF5c8P/2YuyYcAAAAAAAUwDQYJKoZIhvcNAQEMBQAw
# dzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjFI
# MEYGA1UEAxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNhdGlvbiBSb290IENl
# cnRpZmljYXRlIEF1dGhvcml0eSAyMDIwMB4XDTIwMTExOTIwMzIzMVoXDTM1MTEx
# OTIwNDIzMVowYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1w
# aW5nIENBIDIwMjAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCefOdS
# Y/3gxZ8FfWO1BiKjHB7X55cz0RMFvWVGR3eRwV1wb3+yq0OXDEqhUhxqoNv6iYWK
# jkMcLhEFxvJAeNcLAyT+XdM5i2CgGPGcb95WJLiw7HzLiBKrxmDj1EQB/mG5eEiR
# BEp7dDGzxKCnTYocDOcRr9KxqHydajmEkzXHOeRGwU+7qt8Md5l4bVZrXAhK+WSk
# 5CihNQsWbzT1nRliVDwunuLkX1hyIWXIArCfrKM3+RHh+Sq5RZ8aYyik2r8HxT+l
# 2hmRllBvE2Wok6IEaAJanHr24qoqFM9WLeBUSudz+qL51HwDYyIDPSQ3SeHtKog0
# ZubDk4hELQSxnfVYXdTGncaBnB60QrEuazvcob9n4yR65pUNBCF5qeA4QwYnilBk
# fnmeAjRN3LVuLr0g0FXkqfYdUmj1fFFhH8k8YBozrEaXnsSL3kdTD01X+4LfIWOu
# FzTzuoslBrBILfHNj8RfOxPgjuwNvE6YzauXi4orp4Sm6tF245DaFOSYbWFK5ZgG
# 6cUY2/bUq3g3bQAqZt65KcaewEJ3ZyNEobv35Nf6xN6FrA6jF9447+NHvCjeWLCQ
# Z3M8lgeCcnnhTFtyQX3XgCoc6IRXvFOcPVrr3D9RPHCMS6Ckg8wggTrtIVnY8yjb
# vGOUsAdZbeXUIQAWMs0d3cRDv09SvwVRd61evQIDAQABo4ICGzCCAhcwDgYDVR0P
# AQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRraSg6NS9IY0DP
# e9ivSek+2T3bITBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYzaHR0
# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRt
# MBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBB
# MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUyH7SaoUqG8oZmAQHJ89QEE9o
# qKIwgYQGA1UdHwR9MHsweaB3oHWGc2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
# a2lvcHMvY3JsL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIw
# Um9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcmwwgZQGCCsG
# AQUFBwEBBIGHMIGEMIGBBggrBgEFBQcwAoZ1aHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNh
# dGlvbiUyMFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3J0
# MA0GCSqGSIb3DQEBDAUAA4ICAQBfiHbHfm21WhV150x4aPpO4dhEmSUVpbixNDmv
# 6TvuIHv1xIs174bNGO/ilWMm+Jx5boAXrJxagRhHQtiFprSjMktTliL4sKZyt2i+
# SXncM23gRezzsoOiBhv14YSd1Klnlkzvgs29XNjT+c8hIfPRe9rvVCMPiH7zPZcw
# 5nNjthDQ+zD563I1nUJ6y59TbXWsuyUsqw7wXZoGzZwijWT5oc6GvD3HDokJY401
# uhnj3ubBhbkR83RbfMvmzdp3he2bvIUztSOuFzRqrLfEvsPkVHYnvH1wtYyrt5vS
# hiKheGpXa2AWpsod4OJyT4/y0dggWi8g/tgbhmQlZqDUf3UqUQsZaLdIu/XSjgoZ
# qDjamzCPJtOLi2hBwL+KsCh0Nbwc21f5xvPSwym0Ukr4o5sCcMUcSy6TEP7uMV8R
# X0eH/4JLEpGyae6Ki8JYg5v4fsNGif1OXHJ2IWG+7zyjTDfkmQ1snFOTgyEX8qBp
# efQbF0fx6URrYiarjmBprwP6ZObwtZXJ23jK3Fg/9uqM3j0P01nzVygTppBabzxP
# Ah/hHhhls6kwo3QLJ6No803jUsZcd4JQxiYHHc+Q/wAMcPUnYKv/q2O444LO1+n6
# j01z5mggCSlRwD9faBIySAcA9S8h22hIAcRQqIGEjolCK9F6nK9ZyX4lhthsGHum
# aABdWzCCB58wggWHoAMCAQICEzMAAABa9g1njIXt3QgAAAAAAFowDQYJKoZIhvcN
# AQEMBQAwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5n
# IENBIDIwMjAwHhcNMjYwMTA4MTg1OTAzWhcNMjcwMTA3MTg1OTAzWjCB4zELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9z
# b2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMScwJQYDVQQLEx5uU2hpZWxk
# IFRTUyBFU046NDkxQS0wNUUwLUQ5NDcxNTAzBgNVBAMTLE1pY3Jvc29mdCBQdWJs
# aWMgUlNBIFRpbWUgU3RhbXBpbmcgQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF
# AAOCAg8AMIICCgKCAgEA7/Q7R5aOBRv2ucdxAtF19Y83gf73VrdieVo/joTWbi4P
# 4krHpyxYxK1fv1/EslQCocmpBYTX1SU0yFL2MQHfZ0AnjK5awfJS4z52mGMPPgTm
# OXiBgZkSZo6sq8234qqUVrLKD+hODcGUtG7hoGrzrrwDmqUdx+y6HoN1KoUgPWLE
# kVnMetkUbWIYEbtTUGfY40sOjuNvBfmsxw925MBTD9zszdaFLFAG5mlCLPxFAYoi
# oIp8jGBCQp3OkKlTRJZA4T8OBNdvPdzXkoxEJ2QaUvbNv6We5JXiyx5Cbep+VmJl
# yQvKfbEkjxlcOSr4iD5v+uw88h8jx2Lbbxa8rWPrslenJ5UJpJQ70SvOUudOueNC
# R5dVAinvfG5UFWua+hN/+/hrsyeua4pLIhdzm8lQcQYHfjn47yiYW3XDxv5eD0P0
# 8ohGoM8S/sdGTQL5i/G7wW8cm9KhxIhkr6/8WYoU6Kliek/vrICYk2fKF65xKE6C
# TxCJTndRKf/4DIxvvFb3TmBmfI2pvb0d5V1DXvmkMckYTPwLHnCId5WWIbPmEAG5
# wUPKVH3PctJOYHr7dm4jF4b0FlLjo/oA0+S5W4PmbzCBzsYsvODvcKwMXT26S3xR
# /x1NwwFfeuj7v+T0zpe3xY8bsgv2//gO/IxjTe2Rv1j1GLodZq9dE9hEJR4+yk8C
# AwEAAaOCAcswggHHMB0GA1UdDgQWBBSOY7JDq3Axw/VltHK0nEjh+deZwjAfBgNV
# HSMEGDAWgBRraSg6NS9IY0DPe9ivSek+2T3bITBsBgNVHR8EZTBjMGGgX6Bdhlto
# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBQ
# dWJsaWMlMjBSU0ElMjBUaW1lc3RhbXBpbmclMjBDQSUyMDIwMjAuY3JsMHkGCCsG
# AQUFBwEBBG0wazBpBggrBgEFBQcwAoZdaHR0cDovL3d3dy5taWNyb3NvZnQuY29t
# L3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBQdWJsaWMlMjBSU0ElMjBUaW1lc3Rh
# bXBpbmclMjBDQSUyMDIwMjAuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAww
# CgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQDAgeAMGYGA1UdIARfMF0wUQYMKwYBBAGC
# N0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
# a2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTAIBgZngQwBBAIwDQYJKoZIhvcNAQEM
# BQADggIBAICUzyv63eEhvaHWUNMDH6JiRCXEW5TtA417IgUgFnb3G8aXyl6ErESs
# PMieI6khf96W5QDBAqhojTPC4oB1HSatIdcKeIygs2Sjlb7mvuxc1qYpftAxXcF8
# Y5feCL2pV/HJR7sAddupDwoFAc1gKc0W1BAeABGuViG3IAqiXly0zQIBz/Lehjtt
# MyxUm+cDm7sNVY95ehJPYoQwN4sG8lirQglnrIykM5YtnhQ/zZuSzJKEgH9d1rCK
# sgYt2x652vJHFUyTfXeYByMZFvn34i223qi1W9hBaof48atNTMRx7PxpC47e6ag1
# mMq4WhflWw8/+BJmx76iuEbfN9mT0gPITcN9QWuG+S/ofS2KMrUPS4gaHAwFZKb2
# S1Dqh5T5q6tkXHcwj4s4OcextEVkDLXW4y/Aqr5k0LVJ7i0gzW72mJYCGdM+iHqZ
# QsqKQc5WEdo73ne2TMMK2Oyx7kZQo7H3KD2eocpYyCc4Onrb+48/ML/IMQhKtcJx
# TtQHu0BOvfNY0R20zh3TT2JdYjp1X9J1wghfjiumgvIIvD6dePGn59j93KAs7tR1
# JBpVpQVWPcradXK66M+ym3ku6dzkW+5g+qaL/PyQBKabBuIX5bQ/RRNYVoLzgxZ9
# TaHowODmzSjGZ00UrvqNevfBl91KhXsUIp+rkZ14ajLlTANDAwLQMYID1DCCA9AC
# AQEweDBhMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcg
# Q0EgMjAyMAITMwAAAFr2DWeMhe3dCAAAAAAAWjANBglghkgBZQMEAgEFAKCCAS0w
# GgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCDdA2YU
# 0S5IoamqVZXzVdOvl/dTm7ZHWxijHQfaYyrBdjCB3QYLKoZIhvcNAQkQAi8xgc0w
# gcowgccwgaAEIGK5ZECL6n3o9GwG3dPBbeM2jOA9BL5ByjUJWb81pTRDMHwwZaRj
# MGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# MjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAy
# MDIwAhMzAAAAWvYNZ4yF7d0IAAAAAABaMCIEILSSMkzr8frHIPVX1zWHka2v9qPR
# JKQBWYiXS2Q0MflBMA0GCSqGSIb3DQEBCwUABIICACmOjyVejoa3uAX3NQQuh7uS
# p2sJzPG1avI2yhDQFDu/WZ6XubQwCZ/HJJBjeyWBL2ymZBQttEFr6LtbtLlqpPi4
# ZPVq0comSALhbgk4uI6R9E16ZyUWodQZYaCtBXn+Wo9MrD3hlcJANhr1uC92919/
# FrqU1CtAMvhzSkx2551F7HWqg2/IZDgOoGSi07dQwWOmln/LLsdqtTK/hjyyLwGT
# ZZ13tIlO/ILqTrwnVZ55yUdvWS6+6h5QKvdfeKBuItObJBWLPtWEHPRFTYfZMzzN
# c2fnEM+HtarNcWr2ZvcBQP1EbWNuwS/ZUwzIm9TUymLVPM+ILJoTJ6ToRkaHsuYt
# tNgcrmo1loGKrv7NJHvjaEz9QSf/bDQnICmi0FgCuiP7bx/LJQ84GPgTvQtBDDkz
# RvcObGlzgN4WdG+GQYvLd3GmYyT2rvdUIuD9q0Lpx7Na6t32PUSwoRn0vNn1AC8/
# IWRgQ8taf8kI3kMDyNFohdR1rFwcB7tu4E9V6QtKk6UEsa6MxNX9pTbnS1tTnhHz
# LUGc4gAc/LscrOptoTHxChWhnDltbZrMLYEPhzNgqmYnoJt9L5rzv+YBgRImqVL8
# MSv1Xi8Do6TcK7bcQOzwaBdtZ32Nxf7PK+D0hw4BKpVIfWygfxni1/zT9bc+zga4
# NZNJXpKd+6Ry3unE3pXp
# SIG # End signature block