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

# Set alias for Connect-AppVentiXAzure (renamed from Connect-AppVentiXAzureBlobStore: the sign-in also covers Entra ID group lookups)
New-Alias -Name Connect-AppVentiXAzureBlobStore -Value Connect-AppVentiXAzure -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-AppVentiXAzureAccessToken) {
        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-AppVentiXAzure -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
# MII5zAYJKoZIhvcNAQcCoII5vTCCObkCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBYIho9oW6Q9tSx
# jenBJZHkxYwcCpJif2TFID0sMkPs06CCIfAwggXMMIIDtKADAgECAhBUmNLR1FsZ
# 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
# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggalMIIEjaADAgECAhMzAAfe3swl
# E6VpSNHVAAAAB97eMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ
# RCBWZXJpZmllZCBDUyBFT0MgQ0EgMDQwHhcNMjYxMDA3MTc0NzU4WhcNMjYxMDEw
# MTc0NzU4WjBoMQswCQYDVQQGEwJOTDEWMBQGA1UECBMNTm9vcmQtSG9sbGFuZDEP
# MA0GA1UEBxMGSGVpbG9vMRcwFQYDVQQKEw5BcHBWZW50aVggQi5WLjEXMBUGA1UE
# AxMOQXBwVmVudGlYIEIuVi4wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIB
# gQCH4MN0MJY3PV2IJj1lggIPJa7SCcf+/7EX0DgKPo81x0t3hZtHoHHyG4498t+Z
# A/8X1pRwQA9t9IFR0XzVma1LDn/U0DVgVGJzNCKXbM/gvSYdGdVz6B2clk1ZGVbs
# HIqGKZLFeLIstSTlcbJ90hwwppmt5lIixODy7l+7o4SmgYHZ3HttFW5emQuNhnlO
# qIRFCeexRDvOX7fNgIGL8FzEwX72c59S3d7ZkPhWgbpkBP6vh0uGoFxE/evYk7/S
# FCFa3A1eTr3eW7TP+LInJFhVAAUELX3TgQSeCuRwnDJdN3e2nqYOKSB+tUyY0iPA
# 7ZuOmAYPPea+haQMIv47ka7zjMrQIYF3WcYyS5SVkmSrK6hFih7TWn8y2A3a8Twf
# 9ptYOBon5ThRPmXvidc85SMK0ZzAOn52VyNVufyoTmkBk4fdBP8eMSTzpuoHyM+d
# lbGQvM7TrUHGFLfIxvX8I2q8hyYmW3F/QxrU3ceg+BHzJ+SANMHuYO73c2tIlQWL
# ShsCAwEAAaOCAdQwggHQMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMDsG
# A1UdJQQ0MDIGCisGAQQBgjdhAQAGCCsGAQUFBwMDBhorBgEEAYI3YaL8yC6uh9F6
# gZ2lyVCBwcKCJzAdBgNVHQ4EFgQUqHnLRgR/WaIs69C093zde4HIsKwwHwYDVR0j
# BBgwFoAUmvFUd3UMhxY3RqCs3nn59H/BeOkwZwYDVR0fBGAwXjBcoFqgWIZWaHR0
# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSUQl
# MjBWZXJpZmllZCUyMENTJTIwRU9DJTIwQ0ElMjAwNC5jcmwwdAYIKwYBBQUHAQEE
# aDBmMGQGCCsGAQUFBzAChlhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz
# L2NlcnRzL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUyMEVPQyUyMENB
# JTIwMDQuY3J0MFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0w
# DQYJKoZIhvcNAQEMBQADggIBADVITG0Ap1LmVCSnbzZMm1PFDY/0yN7nmdHF5u8E
# WS7ZUPjfwjvNb0DZf764lFQVMMzXX5eNnJCzib1jGYhSKPSGSiYTqUgb/nU/vug3
# tJrbUQ3rxRgJBaqedIX1Tw5zfYf+ZAa4Bb96DTuudk43sFTG6xJeYWEQfk/8Ihsw
# QEUQE6ThYx227aTfG7wiqP+KIE3haHTw5sVuTcp25beIZswbFsllG/rqFKd4+ems
# mUJDwywxgOBUy8xLvCXFFWJAi+269BWox1PCzg+fPqba7yvwYxPNuXM8iWAFM0Fy
# ZlpV/S97QQhe3uqw+66UL7yukVRIqAb+G5fSkERqiA74Jhi99puLNIvczrLqi2zF
# Cf6mW0AIWsARqW6CC4hEA3ImfT8oYWPq11CRQlrk2IQ6WkArqYJvpSw964cf/dIc
# r/QlJOICv9BaXo9EzbvgEqoVbdlcgBpJY+a0Hz8uV3L7svWJID7ECllFyuzjGVmf
# j1olx5XjKGRK819k/EMr02l9Wfzkm4ekAe56/5RXiFIMdzJ6f7H5a01y6y8s80nH
# DuLrgnkTm936K/KWK2/CkAltjhKVHOkZ95Q4kURvmZtTInX9uS2IihezuRsSgYpO
# urTE48L+FAavyMUVgbB8MJaWW95bxHn9jx7IdJAiaPwPgGolZR6tsw3C8aWos0nM
# AXSdMIIGpTCCBI2gAwIBAgITMwAH3t7MJROlaUjR1QAAAAfe3jANBgkqhkiG9w0B
# AQwFADBaMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSswKQYDVQQDEyJNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ1MgRU9DIENBIDA0
# MB4XDTI2MTAwNzE3NDc1OFoXDTI2MTAxMDE3NDc1OFowaDELMAkGA1UEBhMCTkwx
# FjAUBgNVBAgTDU5vb3JkLUhvbGxhbmQxDzANBgNVBAcTBkhlaWxvbzEXMBUGA1UE
# ChMOQXBwVmVudGlYIEIuVi4xFzAVBgNVBAMTDkFwcFZlbnRpWCBCLlYuMIIBojAN
# BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAh+DDdDCWNz1diCY9ZYICDyWu0gnH
# /v+xF9A4Cj6PNcdLd4WbR6Bx8huOPfLfmQP/F9aUcEAPbfSBUdF81ZmtSw5/1NA1
# YFRiczQil2zP4L0mHRnVc+gdnJZNWRlW7ByKhimSxXiyLLUk5XGyfdIcMKaZreZS
# IsTg8u5fu6OEpoGB2dx7bRVuXpkLjYZ5TqiERQnnsUQ7zl+3zYCBi/BcxMF+9nOf
# Ut3e2ZD4VoG6ZAT+r4dLhqBcRP3r2JO/0hQhWtwNXk693lu0z/iyJyRYVQAFBC19
# 04EEngrkcJwyXTd3tp6mDikgfrVMmNIjwO2bjpgGDz3mvoWkDCL+O5Gu84zK0CGB
# d1nGMkuUlZJkqyuoRYoe01p/MtgN2vE8H/abWDgaJ+U4UT5l74nXPOUjCtGcwDp+
# dlcjVbn8qE5pAZOH3QT/HjEk86bqB8jPnZWxkLzO061BxhS3yMb1/CNqvIcmJltx
# f0Ma1N3HoPgR8yfkgDTB7mDu93NrSJUFi0obAgMBAAGjggHUMIIB0DAMBgNVHRMB
# Af8EAjAAMA4GA1UdDwEB/wQEAwIHgDA7BgNVHSUENDAyBgorBgEEAYI3YQEABggr
# BgEFBQcDAwYaKwYBBAGCN2Gi/MgurofReoGdpclQgcHCgicwHQYDVR0OBBYEFKh5
# y0YEf1miLOvQtPd83XuByLCsMB8GA1UdIwQYMBaAFJrxVHd1DIcWN0agrN55+fR/
# wXjpMGcGA1UdHwRgMF4wXKBaoFiGVmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
# a2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUyMEVPQyUy
# MENBJTIwMDQuY3JsMHQGCCsGAQUFBwEBBGgwZjBkBggrBgEFBQcwAoZYaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBJRCUy
# MFZlcmlmaWVkJTIwQ1MlMjBFT0MlMjBDQSUyMDA0LmNydDBUBgNVHSAETTBLMEkG
# BFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br
# aW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMA0GCSqGSIb3DQEBDAUAA4ICAQA1SExt
# AKdS5lQkp282TJtTxQ2P9Mje55nRxebvBFku2VD438I7zW9A2X++uJRUFTDM11+X
# jZyQs4m9YxmIUij0hkomE6lIG/51P77oN7Sa21EN68UYCQWqnnSF9U8Oc32H/mQG
# uAW/eg07rnZON7BUxusSXmFhEH5P/CIbMEBFEBOk4WMdtu2k3xu8Iqj/iiBN4Wh0
# 8ObFbk3KduW3iGbMGxbJZRv66hSnePnprJlCQ8MsMYDgVMvMS7wlxRViQIvtuvQV
# qMdTws4Pnz6m2u8r8GMTzblzPIlgBTNBcmZaVf0ve0EIXt7qsPuulC+8rpFUSKgG
# /huX0pBEaogO+CYYvfabizSL3M6y6otsxQn+pltACFrAEalugguIRANyJn0/KGFj
# 6tdQkUJa5NiEOlpAK6mCb6UsPeuHH/3SHK/0JSTiAr/QWl6PRM274BKqFW3ZXIAa
# SWPmtB8/Lldy+7L1iSA+xApZRcrs4xlZn49aJceV4yhkSvNfZPxDK9NpfVn85JuH
# pAHuev+UV4hSDHcyen+x+WtNcusvLPNJxw7i64J5E5vd+ivylitvwpAJbY4SlRzp
# GfeUOJFEb5mbUyJ1/bktiIoXs7kbEoGKTrq0xOPC/hQGr8jFFYGwfDCWllveW8R5
# /Y8eyHSQImj8D4BqJWUerbMNwvGlqLNJzAF0nTCCBygwggUQoAMCAQICEzMAAAAX
# J0UJC4uHr8YAAAAAABcwDQYJKoZIhvcNAQEMBQAwYzELMAkGA1UEBhMCVVMxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE0MDIGA1UEAxMrTWljcm9zb2Z0
# IElEIFZlcmlmaWVkIENvZGUgU2lnbmluZyBQQ0EgMjAyMTAeFw0yNjAzMjYxODEx
# MzFaFw0zMTAzMjYxODExMzFaMFoxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJRCBWZXJpZmll
# ZCBDUyBFT0MgQ0EgMDQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCC
# x2T+Aw9mKgGVzJ+Tq0PMn49G3itIsYpbx7ClLSRHFe1RELdPcZ1sIqWOhsSfy6yy
# qEapClGH9Je9FXA1cQgZvvpQbkg+QInVLr/0EPrVBCwrM96lbRI2PxNeCwXG9Lsy
# W2hG6KQgintDmNCBo4zpDIr377plVdSliZm6UB7rHwmvBnR02QT6tnrqWq2ihzB6
# lRJVTEzuh0OafzIMeMnYM0+x+ve5EOLHdfiq+HXiMf9Jb7YLHtYgyHIiJA7bTWLq
# FSLGaTh7ZlbxbsLXA91OOroEpv7OjzFuu3tkpC9FflA4Dp2Euq4+qPmxUqfGp+TX
# 0gLRJp9NJOzzILjcTD3rkFFFbxUv1xyg6avivFDLtoKBhM2Td138umE1pNOacanu
# SYtPHIeQHmB6haFi64avLBLwTTAm/Rbit860cFXR72wq+5Qh4hSmezHqKXERWPpV
# Be+APrJ4Iqc+aPeMmIkoCWZQO22HnLNFUFSXjiwyIbgvlH/LIAJEqTafTzxDZgKh
# lLU7zr6gwsq3WNpcYQI6NuxWnwh3VVDDyF7onQqKs5Ll7bleVN0Y8VvqgE45ppyB
# bvwqN/Run5fMCCRz3aYMY0kZhKO92eP7t4zHqZ5bQMAgZ0tE2Pz/jb0wiykUF/Pc
# oOqqk3vVLiRDYst6vd3GEMNzMpUUvQcvBG46+COIbwIDAQABo4IB3DCCAdgwDgYD
# VR0PAQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBSa8VR3dQyH
# FjdGoKzeefn0f8F46TBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYz
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnku
# aHRtMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMBIGA1UdEwEB/wQIMAYBAf8C
# AQAwHwYDVR0jBBgwFoAU2UEpsA8PY2zvadf1zSmepEhqMOYwcAYDVR0fBGkwZzBl
# oGOgYYZfaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9z
# b2Z0JTIwSUQlMjBWZXJpZmllZCUyMENvZGUlMjBTaWduaW5nJTIwUENBJTIwMjAy
# MS5jcmwwfQYIKwYBBQUHAQEEcTBvMG0GCCsGAQUFBzAChmFodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIwVmVyaWZp
# ZWQlMjBDb2RlJTIwU2lnbmluZyUyMFBDQSUyMDIwMjEuY3J0MA0GCSqGSIb3DQEB
# DAUAA4ICAQCQdVoZ/U0m38l2iKaZFlsxavptpoOLyaR1a9ZK2TSF1kOnFJhMDse6
# KkCgsveoiEjXTVc6Xt86IKHn76Nk5qZB0BXv2iMRQ2giAJmYvZcmstoZqfB2M3Kd
# 5wnJhUJOtF/b6HsqSelY6nhrF06zor1lDmDQixBZcLB9zR1+RKQso1jekNxYuUk+
# HaN3k1S57qk0O//YbkwU0mELCW04N5vICMZx5T5c7Nq/7uLvbVhCdD7f2bZpA4U7
# vOkB1ooB4AaER3pjoJ0Mad5LFyi6Na9p9Zu/hrLeOjU5FItS5YxsqvlfXxAThJ17
# 6CmkYstKRmytSHZ7JhKRfV6e9Zftk/ODb/CK4pGVAVqsOf4337bQGrOHHCQ3IvN9
# gmnUuDh8JdvbheoWPHxIN1GB5sUiY584tXN7xdD8LCSsRqJvQ8e7a3gZWTgViugR
# s1QWq+N0G9Nje6JHlN1CjJehge+H5PGktJja+juGEr0P+ukSkcL6qaZxFQTh3SDI
# 71lvW++3bl/Ezd6SO8N9Udw+reoyvRHCyTiSsplZQSBTVJdPmo3qCpGuyHFtPo5C
# Bn3/FPTiqJd3M9BHoqKd0G9Kmg6fGcAvFwnLNXA2kov727wRljL3ypfqL7iAT/Yn
# pxul6RwHRlcOf9dDGg1RRvr92NP/CWVXIb68geR2rvU/NsfmtjF1wDCCB54wggWG
# 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+tHD6n58vhavFIrmcxghcyMIIXLgIBATBxMFoxCzAJBgNV
# BAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMT
# Ik1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBFT0MgQ0EgMDQCEzMAB97ezCUTpWlI
# 0dUAAAAH3t4wDQYJYIZIAWUDBAIBBQCgXjAQBgorBgEEAYI3AgEMMQIwADAZBgkq
# hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAvBgkqhkiG9w0BCQQxIgQgy9WkDeJXAmt3
# pAfZSLdu81rWkKGG+Heal2+AMvy8VNgwDQYJKoZIhvcNAQEBBQAEggGAba7HM3zH
# L1tDSmo6pjEI4CbcOjVUwbtqQrsBV+UmgBAIiSDUVbI2NElN/NZmlWhwmIKxckVF
# U0hiZ2OmSFw4KLPFlZurb+LKfJVe6BBSERSBJHYOL+Z6eWuZHmDWBK+XD7GyU5e6
# 7OLoWEgsh8j/7rcAib405x6fXJ4S1AKmY/n/EdYgUUTGpx1A/KG+eqSnhz7wrSxC
# AY4cb0eqyA27fzhIjhUVdgovNwdGfHkrkmgIKNxE/VnpL63srh9H/wi3/oIp36xb
# 5zAkJVMI8vXUXnZrkk2YSjXMdj4IkuvBnq4G1hTHKEGc87qVfRZGZP/ttGGUJuEY
# vdHicotb8gqtOhhpXAunZhKdLmKjM5F1S2ozhTi+Q/Fqtm548A5a+QX8oIHw/TzN
# 4u5eElnB0lSLCpfWkOsZCrTyzoEw2S9Ke38SwNDJ9QOYogV2CS8bRL3AccEEXF2X
# yO/+1Jbc26ZC4T8e8BLt7UCcNNQXbEnJt/5gz5u6e2F1TtfupNRc0hCwoYIUsjCC
# FK4GCisGAQQBgjcDAwExghSeMIIUmgYJKoZIhvcNAQcCoIIUizCCFIcCAQMxDzAN
# BglghkgBZQMEAgEFADCCAWoGCyqGSIb3DQEJEAEEoIIBWQSCAVUwggFRAgEBBgor
# BgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEIMPiOHW8d+XAcLxg3h0Ts1MJEt5N
# sTs9QEZSbyzcohumAgZqwGCVnjwYEzIwMjYxMDA4MTk1MDM0Ljc2NVowBIACAfSg
# gemkgeYwgeMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD
# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTAr
# BgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUG
# A1UECxMeblNoaWVsZCBUU1MgRVNOOjQ5MUEtMDVFMC1EOTQ3MTUwMwYDVQQDEyxN
# aWNyb3NvZnQgUHVibGljIFJTQSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eaCCDykw
# ggeCMIIFaqADAgECAhMzAAAABeXPD/9mLsmHAAAAAAAFMA0GCSqGSIb3DQEBDAUA
# MHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# SDBGBgNVBAMTP01pY3Jvc29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBD
# ZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAyMDAeFw0yMDExMTkyMDMyMzFaFw0zNTEx
# MTkyMDQyMzFaMGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
# cG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFt
# cGluZyBDQSAyMDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnnzn
# UmP94MWfBX1jtQYioxwe1+eXM9ETBb1lRkd3kcFdcG9/sqtDlwxKoVIcaqDb+omF
# io5DHC4RBcbyQHjXCwMk/l3TOYtgoBjxnG/eViS4sOx8y4gSq8Zg49REAf5huXhI
# kQRKe3Qxs8Sgp02KHAznEa/Ssah8nWo5hJM1xznkRsFPu6rfDHeZeG1Wa1wISvlk
# pOQooTULFm809Z0ZYlQ8Lp7i5F9YciFlyAKwn6yjN/kR4fkquUWfGmMopNq/B8U/
# pdoZkZZQbxNlqJOiBGgCWpx69uKqKhTPVi3gVErnc/qi+dR8A2MiAz0kN0nh7SqI
# NGbmw5OIRC0EsZ31WF3Uxp3GgZwetEKxLms73KG/Z+MkeuaVDQQheangOEMGJ4pQ
# ZH55ngI0Tdy1bi69INBV5Kn2HVJo9XxRYR/JPGAaM6xGl57Ei95HUw9NV/uC3yFj
# rhc087qLJQawSC3xzY/EXzsT4I7sDbxOmM2rl4uKK6eEpurRduOQ2hTkmG1hSuWY
# BunFGNv21Kt4N20AKmbeuSnGnsBCd2cjRKG79+TX+sTehawOoxfeOO/jR7wo3liw
# kGdzPJYHgnJ54UxbckF914AqHOiEV7xTnD1a69w/UTxwjEugpIPMIIE67SFZ2PMo
# 27xjlLAHWW3l1CEAFjLNHd3EQ79PUr8FUXetXr0CAwEAAaOCAhswggIXMA4GA1Ud
# DwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQUa2koOjUvSGNA
# z3vYr0npPtk92yEwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0
# dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0
# bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMA
# QTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFMh+0mqFKhvKGZgEByfPUBBP
# aKiiMIGEBgNVHR8EfTB7MHmgd6B1hnNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v
# cGtpb3BzL2NybC9NaWNyb3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUy
# MFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3JsMIGUBggr
# BgEFBQcBAQSBhzCBhDCBgQYIKwYBBQUHMAKGdWh0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmlj
# YXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNy
# dDANBgkqhkiG9w0BAQwFAAOCAgEAX4h2x35ttVoVdedMeGj6TuHYRJklFaW4sTQ5
# r+k77iB79cSLNe+GzRjv4pVjJviceW6AF6ycWoEYR0LYhaa0ozJLU5Yi+LCmcrdo
# vkl53DNt4EXs87KDogYb9eGEndSpZ5ZM74LNvVzY0/nPISHz0Xva71QjD4h+8z2X
# MOZzY7YQ0Psw+etyNZ1CesufU211rLslLKsO8F2aBs2cIo1k+aHOhrw9xw6JCWON
# NboZ497mwYW5EfN0W3zL5s3ad4Xtm7yFM7Ujrhc0aqy3xL7D5FR2J7x9cLWMq7eb
# 0oYioXhqV2tgFqbKHeDick+P8tHYIFovIP7YG4ZkJWag1H91KlELGWi3SLv10o4K
# Gag42pswjybTi4toQcC/irAodDW8HNtX+cbz0sMptFJK+KObAnDFHEsukxD+7jFf
# EV9Hh/+CSxKRsmnuiovCWIOb+H7DRon9TlxydiFhvu88o0w35JkNbJxTk4MhF/Kg
# aXn0GxdH8elEa2Imq45gaa8D+mTm8LWVydt4ytxYP/bqjN49D9NZ81coE6aQWm88
# TwIf4R4YZbOpMKN0CyejaPNN41LGXHeCUMYmBx3PkP8ADHD1J2Cr/6tjuOOCztfp
# +o9Nc+ZoIAkpUcA/X2gSMkgHAPUvIdtoSAHEUKiBhI6JQivRepyvWcl+JYbYbBh7
# pmgAXVswggefMIIFh6ADAgECAhMzAAAAWvYNZ4yF7d0IAAAAAABaMA0GCSqGSIb3
# DQEBDAUAMGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
# YXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGlu
# ZyBDQSAyMDIwMB4XDTI2MDEwODE4NTkwM1oXDTI3MDEwNzE4NTkwM1owgeMxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jv
# c29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVs
# ZCBUU1MgRVNOOjQ5MUEtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVi
# bGljIFJTQSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEB
# BQADggIPADCCAgoCggIBAO/0O0eWjgUb9rnHcQLRdfWPN4H+91a3YnlaP46E1m4u
# D+JKx6csWMStX79fxLJUAqHJqQWE19UlNMhS9jEB32dAJ4yuWsHyUuM+dphjDz4E
# 5jl4gYGZEmaOrKvNt+KqlFayyg/oTg3BlLRu4aBq8668A5qlHcfsuh6DdSqFID1i
# xJFZzHrZFG1iGBG7U1Bn2ONLDo7jbwX5rMcPduTAUw/c7M3WhSxQBuZpQiz8RQGK
# IqCKfIxgQkKdzpCpU0SWQOE/DgTXbz3c15KMRCdkGlL2zb+lnuSV4sseQm3qflZi
# ZckLyn2xJI8ZXDkq+Ig+b/rsPPIfI8di228WvK1j67JXpyeVCaSUO9ErzlLnTrnj
# QkeXVQIp73xuVBVrmvoTf/v4a7MnrmuKSyIXc5vJUHEGB345+O8omFt1w8b+Xg9D
# 9PKIRqDPEv7HRk0C+Yvxu8FvHJvSocSIZK+v/FmKFOipYnpP76yAmJNnyheucShO
# gk8QiU53USn/+AyMb7xW905gZnyNqb29HeVdQ175pDHJGEz8Cx5wiHeVliGz5hAB
# ucFDylR9z3LSTmB6+3ZuIxeG9BZS46P6ANPkuVuD5m8wgc7GLLzg73CsDF09ukt8
# Uf8dTcMBX3ro+7/k9M6Xt8WPG7IL9v/4DvyMY03tkb9Y9Ri6HWavXRPYRCUePspP
# AgMBAAGjggHLMIIBxzAdBgNVHQ4EFgQUjmOyQ6twMcP1ZbRytJxI4fnXmcIwHwYD
# VR0jBBgwFoAUa2koOjUvSGNAz3vYr0npPtk92yEwbAYDVR0fBGUwYzBhoF+gXYZb
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIw
# UHVibGljJTIwUlNBJTIwVGltZXN0YW1waW5nJTIwQ0ElMjAyMDIwLmNybDB5Bggr
# BgEFBQcBAQRtMGswaQYIKwYBBQUHMAKGXWh0dHA6Ly93d3cubWljcm9zb2Z0LmNv
# bS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwUHVibGljJTIwUlNBJTIwVGltZXN0
# YW1waW5nJTIwQ0ElMjAyMDIwLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQM
# MAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDBmBgNVHSAEXzBdMFEGDCsGAQQB
# gjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v
# cGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wCAYGZ4EMAQQCMA0GCSqGSIb3DQEB
# DAUAA4ICAQCAlM8r+t3hIb2h1lDTAx+iYkQlxFuU7QONeyIFIBZ29xvGl8pehKxE
# rDzIniOpIX/eluUAwQKoaI0zwuKAdR0mrSHXCniMoLNko5W+5r7sXNamKX7QMV3B
# fGOX3gi9qVfxyUe7AHXbqQ8KBQHNYCnNFtQQHgARrlYhtyAKol5ctM0CAc/y3oY7
# bTMsVJvnA5u7DVWPeXoST2KEMDeLBvJYq0IJZ6yMpDOWLZ4UP82bksyShIB/Xdaw
# irIGLdseudryRxVMk313mAcjGRb59+Ittt6otVvYQWqH+PGrTUzEcez8aQuO3umo
# NZjKuFoX5VsPP/gSZse+orhG3zfZk9IDyE3DfUFrhvkv6H0tijK1D0uIGhwMBWSm
# 9ktQ6oeU+aurZFx3MI+LODnHsbRFZAy11uMvwKq+ZNC1Se4tIM1u9piWAhnTPoh6
# mULKikHOVhHaO953tkzDCtjsse5GUKOx9yg9nqHKWMgnODp62/uPPzC/yDEISrXC
# cU7UB7tATr3zWNEdtM4d009iXWI6dV/SdcIIX44rpoLyCLw+nXjxp+fY/dygLO7U
# dSQaVaUFVj3K2nVyuujPspt5Lunc5FvuYPqmi/z8kASmmwbiF+W0P0UTWFaC84MW
# fU2h6MDg5s0oxmdNFK76jXr3wZfdSoV7FCKfq5GdeGoy5UwDQwMC0DGCA9QwggPQ
# AgEBMHgwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5n
# IENBIDIwMjACEzMAAABa9g1njIXt3QgAAAAAAFowDQYJYIZIAWUDBAIBBQCgggEt
# MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgYrzG
# pUgrfKtvcpZUnO8/502iWcPYAA5/NdkuiPZsUKIwgd0GCyqGSIb3DQEJEAIvMYHN
# MIHKMIHHMIGgBCBiuWRAi+p96PRsBt3TwW3jNozgPQS+Qco1CVm/NaU0QzB8MGWk
# YzBhMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
# MTIwMAYDVQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0Eg
# MjAyMAITMwAAAFr2DWeMhe3dCAAAAAAAWjAiBCBM/NJHAE0n+pq9rL8aeBV+XZjP
# 3FuRuXwRDZE+kszIZjANBgkqhkiG9w0BAQsFAASCAgDKMnO/MVnhM4V0jjWMKNCK
# lK0dMaPvsWCYDcpuur5m12jIeD9EeJDXYpfy98eU4EV3HZ7X2RqVVfxT2GzAmux5
# qswWOoHx+YVY55VLDzTjCnifMljbpng/NYKr8D31hNmZqHNBqC2mJotGY//4iklP
# uniWaU/G6bu5JaJllFOiiz6HZO4QMZTihWwytS4BZIbTsb1K5473o7HWGyouwDBp
# lLm5HD0h0IU6gZx/ArR7VaRcVoc1BVGiE9cW9FZ0s9+L6/1GnLy6vGEo/+fwv1tQ
# 4Jj68m+jt9y23JKocZr6E5kbebcNE6fZgzw1zgjWGYud3At90/E6FvdVGgVUvquS
# sIccuPVm29AvhGERV8tQKM9K5raMDfFwk2wSyJZm+qDomAlqqHzLuD20distOZSy
# 90clXBm/4ABKAUyBffpK5zsQ2yiZ4FijCUm4IMVMXOYKJXXC1n3LE/ui/HefwcKV
# U0aLT0/geoFpVdYvsFw1eCb5cugOzMf9IL1QpTCsfc350YiS5OJuzPNtsFBkom9/
# ilvhox1EZx50YCLD9/RPXK8tmJaQZDsOlu7Nr87rSrE16HZY0SUxWPelCuDxge/Z
# 2UoAT+l9CgbDmiBp9NWr0LNlCREBJp7lRJmLX7bikJGy6HzaT76NADwf+MhLa7Sp
# qePicFocU9F8DeEKw6c3sA==
# SIG # End signature block