Private/ReleaseMetadata.ps1
|
function Get-ReleaseIndex { Write-Host 'Checking Microsoft .NET release metadata...' $index = Invoke-RestMethod -Uri $script:ReleaseIndexUri -Method Get -Headers @{ Accept = 'application/json' 'User-Agent' = 'DotNetSteward' } $indexProperty = $index.PSObject.Properties['releases-index'] if ($null -eq $indexProperty -or @($indexProperty.Value).Count -eq 0) { throw "Microsoft's release index did not contain any release channels." } return @($indexProperty.Value) } function Get-ChannelIndexEntry { param( [Parameter(Mandatory = $true)] [object[]] $ReleaseIndex, [Parameter(Mandatory = $true)] [string] $Channel ) foreach ($entry in $ReleaseIndex) { $channelProperty = $entry.PSObject.Properties['channel-version'] if ($null -ne $channelProperty -and [string] $channelProperty.Value -eq $Channel) { return $entry } } return $null } function Get-ReleasesUri { param( [Parameter(Mandatory = $true)] [object] $ChannelEntry ) foreach ($propertyName in @('releases.json', 'patch-releases-info-uri')) { $property = $ChannelEntry.PSObject.Properties[$propertyName] if ($null -ne $property -and -not [string]::IsNullOrWhiteSpace([string] $property.Value)) { $uri = [uri] $property.Value if (-not $uri.IsAbsoluteUri -or $uri.Scheme -ne 'https') { throw "Release metadata URI '$uri' is not an absolute HTTPS URI." } return $uri.AbsoluteUri } } $channel = [string] $ChannelEntry.PSObject.Properties['channel-version'].Value throw "The release-index entry for .NET $channel did not provide a releases metadata URI." } function Get-ChannelReleaseMetadata { param( [Parameter(Mandatory = $true)] [object] $ChannelEntry, [AllowNull()] [hashtable] $Cache ) $channel = [string] $ChannelEntry.PSObject.Properties['channel-version'].Value $releasesUri = Get-ReleasesUri -ChannelEntry $ChannelEntry if ($null -ne $Cache -and $Cache.ContainsKey($releasesUri)) { return $Cache[$releasesUri] } Write-Host " Reading .NET $channel releases..." $metadata = Invoke-RestMethod -Uri $releasesUri -Method Get -Headers @{ Accept = 'application/json' 'User-Agent' = 'DotNetSteward' } $releasesProperty = $metadata.PSObject.Properties['releases'] if ($null -eq $releasesProperty) { throw "Release metadata for .NET $channel did not contain a releases collection." } if ($null -ne $Cache) { $Cache[$releasesUri] = $metadata } return $metadata } function Get-ChannelSdkInstallers { param( [Parameter(Mandatory = $true)] [object] $ChannelEntry, [Parameter(Mandatory = $true)] [string] $Rid, [AllowNull()] [hashtable] $MetadataCache ) $metadata = Get-ChannelReleaseMetadata -ChannelEntry $ChannelEntry ` -Cache $MetadataCache $releasesProperty = $metadata.PSObject.Properties['releases'] $installerNames = @( "dotnet-sdk-$Rid.exe" "dotnet-dev-$Rid.exe" ) $byVersion = @{} foreach ($release in @($releasesProperty.Value)) { $sdkObjects = New-Object System.Collections.Generic.List[object] $sdksProperty = $release.PSObject.Properties['sdks'] if ($null -ne $sdksProperty) { foreach ($sdkValue in @($sdksProperty.Value)) { if ($null -ne $sdkValue) { $sdkObjects.Add($sdkValue) } } } $sdkProperty = $release.PSObject.Properties['sdk'] if ($null -ne $sdkProperty -and $null -ne $sdkProperty.Value) { $sdkObjects.Add($sdkProperty.Value) } foreach ($sdk in $sdkObjects) { $versionProperty = $sdk.PSObject.Properties['version'] $filesProperty = $sdk.PSObject.Properties['files'] if ($null -eq $versionProperty -or $null -eq $filesProperty) { continue } try { $versionInfo = New-SdkVersionInfo -Text ([string] $versionProperty.Value) } catch { continue } $matchingFiles = @($filesProperty.Value | Where-Object { $ridProperty = $_.PSObject.Properties['rid'] $nameProperty = $_.PSObject.Properties['name'] $null -ne $ridProperty -and $null -ne $nameProperty -and [string] $ridProperty.Value -eq $Rid -and $installerNames -contains [string] $nameProperty.Value }) if ($matchingFiles.Count -eq 0) { continue } if ($matchingFiles.Count -gt 1) { throw "Release metadata contains multiple $Rid EXE installers for SDK $($versionInfo.Text)." } $file = $matchingFiles[0] $urlProperty = $file.PSObject.Properties['url'] $hashProperty = $file.PSObject.Properties['hash'] if ($null -eq $urlProperty -or $null -eq $hashProperty -or [string]::IsNullOrWhiteSpace([string] $hashProperty.Value)) { Write-Verbose "Skipping SDK $($versionInfo.Text) because its Windows installer metadata does not include a hash." continue } $url = [uri] ([string] $urlProperty.Value) $hash = ([string] $hashProperty.Value).ToUpperInvariant() if (-not $url.IsAbsoluteUri -or $url.Scheme -ne 'https') { throw "Installer URI '$url' for SDK $($versionInfo.Text) is not an absolute HTTPS URI." } if ($hash -notmatch '^(?:[0-9A-F]{64}|[0-9A-F]{128})$') { throw "Release metadata for SDK $($versionInfo.Text) has an invalid SHA-256 or SHA-512 hash." } $installer = [pscustomobject] @{ Version = $versionInfo.Text VersionInfo = $versionInfo Rid = $Rid Url = $url.AbsoluteUri Hash = $hash HashAlgorithm = if ($hash.Length -eq 128) { 'SHA512' } else { 'SHA256' } } if ($byVersion.ContainsKey($versionInfo.Text)) { $existing = $byVersion[$versionInfo.Text] if ($existing.Url -ne $installer.Url -or $existing.Hash -ne $installer.Hash) { throw "Release metadata contains conflicting installers for SDK $($versionInfo.Text)." } } else { $byVersion[$versionInfo.Text] = $installer } } } return @($byVersion.Values) } function Get-DotNetProductLabel { param( [Parameter(Mandatory = $true)] [ValidateSet('Sdk', 'Runtime', 'AspNetCoreRuntime', 'WindowsDesktopRuntime')] [string] $ProductType ) switch ($ProductType) { 'Sdk' { return '.NET SDK' } 'Runtime' { return '.NET Runtime' } 'AspNetCoreRuntime' { return 'ASP.NET Core Runtime' } 'WindowsDesktopRuntime' { return '.NET Windows Desktop Runtime' } } } function Get-ChannelRuntimeInstallers { param( [Parameter(Mandatory = $true)] [object] $ChannelEntry, [Parameter(Mandatory = $true)] [string] $Rid, [Parameter(Mandatory = $true)] [ValidateSet('Runtime', 'AspNetCoreRuntime', 'WindowsDesktopRuntime')] [string] $ProductType, [AllowNull()] [hashtable] $MetadataCache ) $componentPropertyName = switch ($ProductType) { 'Runtime' { 'runtime' } 'AspNetCoreRuntime' { 'aspnetcore-runtime' } 'WindowsDesktopRuntime' { 'windowsdesktop' } } $installerNames = switch ($ProductType) { 'Runtime' { @( "dotnet-runtime-$Rid.exe" "dotnet-$Rid.exe" ) } 'AspNetCoreRuntime' { @("aspnetcore-runtime-$Rid.exe") } 'WindowsDesktopRuntime' { @("windowsdesktop-runtime-$Rid.exe") } } $productLabel = Get-DotNetProductLabel -ProductType $ProductType $channel = [string] $ChannelEntry.PSObject.Properties['channel-version'].Value $metadata = Get-ChannelReleaseMetadata -ChannelEntry $ChannelEntry ` -Cache $MetadataCache $releasesProperty = $metadata.PSObject.Properties['releases'] $byVersion = @{} foreach ($release in @($releasesProperty.Value)) { $componentProperty = $release.PSObject.Properties[$componentPropertyName] if ($null -eq $componentProperty -or $null -eq $componentProperty.Value) { continue } $component = $componentProperty.Value $versionProperty = $component.PSObject.Properties['version'] $filesProperty = $component.PSObject.Properties['files'] if ($null -eq $versionProperty -or $null -eq $filesProperty) { continue } try { $versionInfo = New-SdkVersionInfo -Text ([string] $versionProperty.Value) } catch { continue } $matchingFiles = @($filesProperty.Value | Where-Object { $ridProperty = $_.PSObject.Properties['rid'] $nameProperty = $_.PSObject.Properties['name'] $null -ne $ridProperty -and $null -ne $nameProperty -and [string] $ridProperty.Value -eq $Rid -and $installerNames -contains [string] $nameProperty.Value }) if ($matchingFiles.Count -eq 0) { continue } if ($matchingFiles.Count -gt 1) { throw "Release metadata contains multiple $Rid EXE installers for $productLabel $($versionInfo.Text)." } $file = $matchingFiles[0] $urlProperty = $file.PSObject.Properties['url'] $hashProperty = $file.PSObject.Properties['hash'] if ($null -eq $urlProperty -or $null -eq $hashProperty -or [string]::IsNullOrWhiteSpace([string] $hashProperty.Value)) { Write-Verbose "Skipping $productLabel $($versionInfo.Text) because its Windows installer metadata does not include a hash." continue } $url = [uri] ([string] $urlProperty.Value) $hash = ([string] $hashProperty.Value).ToUpperInvariant() if (-not $url.IsAbsoluteUri -or $url.Scheme -ne 'https') { throw "Installer URI '$url' for $productLabel $($versionInfo.Text) is not an absolute HTTPS URI." } if ($hash -notmatch '^(?:[0-9A-F]{64}|[0-9A-F]{128})$') { throw "Release metadata for $productLabel $($versionInfo.Text) has an invalid SHA-256 or SHA-512 hash." } $installer = [pscustomobject] @{ ProductType = $ProductType ProductLabel = $productLabel Version = $versionInfo.Text VersionInfo = $versionInfo Rid = $Rid Url = $url.AbsoluteUri Hash = $hash HashAlgorithm = if ($hash.Length -eq 128) { 'SHA512' } else { 'SHA256' } } if ($byVersion.ContainsKey($versionInfo.Text)) { $existing = $byVersion[$versionInfo.Text] if ($existing.Url -ne $installer.Url -or $existing.Hash -ne $installer.Hash) { throw "Release metadata contains conflicting installers for $productLabel $($versionInfo.Text)." } } else { $byVersion[$versionInfo.Text] = $installer } } return @($byVersion.Values) } function Get-SupportPhase { param( [Parameter(Mandatory = $true)] [object] $ChannelEntry ) $property = $ChannelEntry.PSObject.Properties['support-phase'] if ($null -eq $property) { return 'unknown' } return [string] $property.Value } function Get-ReleaseType { param( [Parameter(Mandatory = $true)] [object] $ChannelEntry ) $property = $ChannelEntry.PSObject.Properties['release-type'] if ($null -eq $property -or [string]::IsNullOrWhiteSpace([string] $property.Value)) { return 'unknown' } return [string] $property.Value } function Get-ChannelSdkVersions { param( [Parameter(Mandatory = $true)] [object] $ChannelEntry, [Parameter(Mandatory = $true)] [hashtable] $MetadataCache ) $metadata = Get-ChannelReleaseMetadata -ChannelEntry $ChannelEntry -Cache $MetadataCache foreach ($release in @($metadata.releases)) { foreach ($propertyName in @('sdk', 'sdks')) { $property = $release.PSObject.Properties[$propertyName] if ($null -eq $property) { continue } foreach ($sdk in @($property.Value)) { if ($null -ne $sdk) { New-SdkVersionInfo -Text ([string] $sdk.version) } } } } } function Get-InstallationSupportInfo { param( [Parameter(Mandatory = $true)] [object] $Installation, [Parameter(Mandatory = $true)] [object[]] $ReleaseIndex, [Parameter(Mandatory = $true)] [hashtable] $MetadataCache ) $version = $Installation.VersionInfo $channelEntry = Get-ChannelIndexEntry -ReleaseIndex $ReleaseIndex -Channel $version.Channel if ($Installation.ProductType -eq 'Sdk') { $possibleChannels = @( if ($null -ne $channelEntry) { $channelEntry } foreach ($entry in $ReleaseIndex) { $latestSdkProperty = $entry.PSObject.Properties['latest-sdk'] if ($null -ne $latestSdkProperty -and $entry -ne $channelEntry) { $latestSdk = New-SdkVersionInfo -Text ([string] $latestSdkProperty.Value) if ($latestSdk.Channel -eq $version.Channel) { $entry } } } ) # Early SDK versions can belong to a different runtime/catalog channel. if ($possibleChannels.Count -gt 1 -or $null -eq $channelEntry) { $channelEntry = $null foreach ($entry in $possibleChannels) { $versions = @(Get-ChannelSdkVersions -ChannelEntry $entry -MetadataCache $MetadataCache) if (@($versions | Where-Object Text -eq $version.Text).Count -gt 0) { $channelEntry = $entry break } } } } if ($null -eq $channelEntry) { throw "No official release channel was found for $($Installation.ProductType) $($version.Text)." } $channel = [string] $channelEntry.'channel-version' $phase = Get-SupportPhase -ChannelEntry $channelEntry if ($phase -notin @('active', 'maintenance', 'eol', 'preview', 'go-live')) { throw "Release metadata for .NET $channel has an unknown support phase '$phase'." } $endOfSupportDate = $null $endOfSupportProperty = $channelEntry.PSObject.Properties['eol-date'] if ($null -ne $endOfSupportProperty -and -not [string]::IsNullOrWhiteSpace([string] $endOfSupportProperty.Value)) { $endOfSupportDate = [datetime]::ParseExact( [string] $endOfSupportProperty.Value, 'yyyy-MM-dd', [Globalization.CultureInfo]::InvariantCulture ) } $latestPatch = $null if ($phase -eq 'eol' -or ($null -ne $endOfSupportDate -and $endOfSupportDate -lt [datetime]::Today)) { $status = ".NET $channel is out of support." } elseif ($phase -eq 'maintenance') { $status = ".NET $channel is going out of support soon." } else { if ($Installation.ProductType -eq 'Sdk') { $latestSdk = New-SdkVersionInfo -Text ([string] $channelEntry.'latest-sdk') if ($latestSdk.FeatureBandKey -eq $version.FeatureBandKey) { $latestPatch = $latestSdk } else { $versions = @(Get-ChannelSdkVersions -ChannelEntry $channelEntry -MetadataCache $MetadataCache) foreach ($candidate in $versions) { if ($candidate.FeatureBandKey -eq $version.FeatureBandKey -and ($null -eq $latestPatch -or (Compare-SdkVersion -Left $candidate -Right $latestPatch) -gt 0)) { $latestPatch = $candidate } } } } else { $latestPatch = New-SdkVersionInfo -Text ([string] $channelEntry.'latest-runtime') } if ($null -eq $latestPatch) { throw "No official patch release was found for $($Installation.ProductType) $($version.Text)." } if ((Compare-SdkVersion -Left $latestPatch -Right $version) -gt 0) { $status = "Patch $($latestPatch.Text) is available." } else { $status = 'Up to date.' } } return @{ SupportStatus = $status SupportPhase = $phase Channel = $channel EndOfSupportDate = $endOfSupportDate LatestPatchVersion = if ($null -ne $latestPatch) { $latestPatch.Text } else { $null } } } function Add-InstallationSupportStatus { param( [Parameter(Mandatory = $true)] [AllowEmptyCollection()] [object[]] $Installations, [switch] $SkipSupportCheck ) foreach ($installation in $Installations) { $installation | Add-Member -NotePropertyMembers @{ SupportStatus = if ($SkipSupportCheck) { 'Not checked' } else { 'Unknown' } SupportPhase = 'unknown' Channel = $null EndOfSupportDate = $null LatestPatchVersion = $null } -Force } if ($SkipSupportCheck -or $Installations.Count -eq 0) { return } $originalSecurityProtocol = [Net.ServicePointManager]::SecurityProtocol try { [Net.ServicePointManager]::SecurityProtocol = $originalSecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 try { $releaseIndex = @(Get-ReleaseIndex) } catch { Write-Warning "Could not check .NET support status: $($_.Exception.Message) Local inventory is still available; support status is Unknown." return } $metadataCache = @{} $statusCache = @{} foreach ($installation in $Installations) { $key = "$($installation.ProductType)|$($installation.Version)" if (-not $statusCache.ContainsKey($key)) { try { $statusCache[$key] = Get-InstallationSupportInfo -Installation $installation ` -ReleaseIndex $releaseIndex -MetadataCache $metadataCache } catch { $statusCache[$key] = $null Write-Warning "Could not check support status for $($installation.ProductType) $($installation.Version): $($_.Exception.Message) Support status is Unknown." } } if ($null -ne $statusCache[$key]) { $installation | Add-Member -NotePropertyMembers $statusCache[$key] -Force } } } finally { [Net.ServicePointManager]::SecurityProtocol = $originalSecurityProtocol } } # SIG # Begin signature block # MII9KgYJKoZIhvcNAQcCoII9GzCCPRcCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB0Isin6P926MYv # hmHgbmBCIOtxDwgfMkCzvajQw4UkaKCCIewwggXMMIIDtKADAgECAhBUmNLR1FsZ # 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 # 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggajMIIEi6ADAgECAhMzAAgr2Z9x # i8O7kaQ7AAAACCvZMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ # RCBWZXJpZmllZCBDUyBFT0MgQ0EgMDQwHhcNMjYxMDEyMDYyMjUxWhcNMjYxMDE1 # MDYyMjUxWjBnMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjERMA8G # A1UEBxMISXNzYXF1YWgxFzAVBgNVBAoTDkRhbWlhbiBFZHdhcmRzMRcwFQYDVQQD # Ew5EYW1pYW4gRWR3YXJkczCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB # AIomJ3JmdXDfPb8TVKcrN5Y31yAowbFp5k4YkCdSKhMWDwW6XDnESb3/RCAd1qze # WoysMqJFCUpXsEosbCOLgGk43Xfcd+Gisik1Gh1LI3fuTUO7rUY+qASVFGcMGfaG # cpHur3a9ozx4XvKfz+wAWOjlRWfAQ8L/LDAgGq95N7QNu60AtK04AzQ3h60jjFWc # IEjqA0ow7Po/4Ck627qOO8Ypi7r4tyBXT/5YduFcoSoFXnmw3LOamy1tD55micXo # +6wkiXlHPpP/q+0/v11l7srgX23fHUzjYK4K+NGftC0KCF/OEOuCVS8+htao4xMH # MQDJiiTDDtx2yVRTDlwTde9BOn5CHMFY6K7f62L8aIJD9RqMfy0wSUf5QgLjxnat # zaeObQiIIwy3LIjuHqUyB4ARTCK1iLAbS1rYs7bFiXZYqsnZUJzI6Tt5nBn2S5bN # ij1mkCsj7khlrjJ1lCHD16cYiGeAz1bbM+HPqjX/7np+BIf79B+fVXp/jnrUe0yA # 9QIDAQABo4IB0zCCAc8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwOgYD # VR0lBDMwMQYKKwYBBAGCN2EBAAYIKwYBBQUHAwMGGSsGAQQBgjdh8PiHLKGwwBPl # htEVg5ShoiEwHQYDVR0OBBYEFO695zvjoAP+VYZjonSFbhHTvX5UMB8GA1UdIwQY # MBaAFJrxVHd1DIcWN0agrN55+fR/wXjpMGcGA1UdHwRgMF4wXKBaoFiGVmh0dHA6 # Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIw # VmVyaWZpZWQlMjBDUyUyMEVPQyUyMENBJTIwMDQuY3JsMHQGCCsGAQUFBwEBBGgw # ZjBkBggrBgEFBQcwAoZYaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j # ZXJ0cy9NaWNyb3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ1MlMjBFT0MlMjBDQSUy # MDA0LmNydDBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMA0G # CSqGSIb3DQEBDAUAA4ICAQAe7jGXSeClV2q/CGYfsh5QN4FXvDeuvJ5+gaxekkck # o/tCXLqRgyj4u2J7tWB0eAMsxwiFeIAxeG5BKAMZVw4k5xwIziQ8xFc73Frbb0iw # EQoIFpoOFq9nh0rdhok7xfYw0DpXIQEFi49wnorMdofEwHQhUF/U7eXwyC9acDTK # f4Ks4o8wZ7t6R/O+mKikIU9pkWzx33jjIU/tbMieg/9yS4L4GD3bN3jNtYu+JLw2 # 5eTOtvMp5lkoLC7ESfX9UR7EzV5YLIhleaw0yBwQAOwsGl22gpesoydw4loQM92/ # 8gqlIu96o5bgew60dY5SpV1YnAFzM9wnNCB3gG1I9BtqQ9BeQHN3eA/QhwC8TbYJ # uuCX58uvfrOpctQ+mN3FzhTd0xN16RgbdNUWNh23Es1A2ztpVRWz22tOvYCMEeOo # kOAEIxuIt9WIXg8mPT7Wmitg6HYyygQmxCysAVlm5jXc6l+CAKRHgb5lpIJOQjWI # czMDOSV9aSsvwTJc6qF/2aG797G5uyGjHb5qQgx7QDbciqnvuW8JfYT4bl/4vS2b # TlA3kSHTDVusbMEa8ddvnr4xtNjyCYzy52uHxUcwt7rE0H7o/W8tDANQ0PkWwihf # CJnpooi1GLvVAGz09LDQHqTJ12ROwLp0DGJmhGclR4B4c5lcx4CnZ+F9zBZVpQfb # ADCCBqMwggSLoAMCAQICEzMACCvZn3GLw7uRpDsAAAAIK9kwDQYJKoZIhvcNAQEM # BQAwWjELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjErMCkGA1UEAxMiTWljcm9zb2Z0IElEIFZlcmlmaWVkIENTIEVPQyBDQSAwNDAe # Fw0yNjEwMTIwNjIyNTFaFw0yNjEwMTUwNjIyNTFaMGcxCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMREwDwYDVQQHEwhJc3NhcXVhaDEXMBUGA1UEChMO # RGFtaWFuIEVkd2FyZHMxFzAVBgNVBAMTDkRhbWlhbiBFZHdhcmRzMIIBojANBgkq # hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAiiYncmZ1cN89vxNUpys3ljfXICjBsWnm # ThiQJ1IqExYPBbpcOcRJvf9EIB3WrN5ajKwyokUJSlewSixsI4uAaTjdd9x34aKy # KTUaHUsjd+5NQ7utRj6oBJUUZwwZ9oZyke6vdr2jPHhe8p/P7ABY6OVFZ8BDwv8s # MCAar3k3tA27rQC0rTgDNDeHrSOMVZwgSOoDSjDs+j/gKTrbuo47ximLuvi3IFdP # /lh24VyhKgVeebDcs5qbLW0PnmaJxej7rCSJeUc+k/+r7T+/XWXuyuBfbd8dTONg # rgr40Z+0LQoIX84Q64JVLz6G1qjjEwcxAMmKJMMO3HbJVFMOXBN170E6fkIcwVjo # rt/rYvxogkP1Gox/LTBJR/lCAuPGdq3Np45tCIgjDLcsiO4epTIHgBFMIrWIsBtL # WtiztsWJdliqydlQnMjpO3mcGfZLls2KPWaQKyPuSGWuMnWUIcPXpxiIZ4DPVtsz # 4c+qNf/uen4Eh/v0H59Ven+OetR7TID1AgMBAAGjggHTMIIBzzAMBgNVHRMBAf8E # AjAAMA4GA1UdDwEB/wQEAwIHgDA6BgNVHSUEMzAxBgorBgEEAYI3YQEABggrBgEF # BQcDAwYZKwYBBAGCN2Hw+IcsobDAE+WG0RWDlKGiITAdBgNVHQ4EFgQU7r3nO+Og # A/5VhmOidIVuEdO9flQwHwYDVR0jBBgwFoAUmvFUd3UMhxY3RqCs3nn59H/BeOkw # ZwYDVR0fBGAwXjBcoFqgWIZWaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w # cy9jcmwvTWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENTJTIwRU9DJTIwQ0El # MjAwNC5jcmwwdAYIKwYBBQUHAQEEaDBmMGQGCCsGAQUFBzAChlhodHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIwVmVy # aWZpZWQlMjBDUyUyMEVPQyUyMENBJTIwMDQuY3J0MFQGA1UdIARNMEswSQYEVR0g # ADBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz # L0RvY3MvUmVwb3NpdG9yeS5odG0wDQYJKoZIhvcNAQEMBQADggIBAB7uMZdJ4KVX # ar8IZh+yHlA3gVe8N668nn6BrF6SRySj+0JcupGDKPi7Ynu1YHR4AyzHCIV4gDF4 # bkEoAxlXDiTnHAjOJDzEVzvcWttvSLARCggWmg4Wr2eHSt2GiTvF9jDQOlchAQWL # j3Ceisx2h8TAdCFQX9Tt5fDIL1pwNMp/gqzijzBnu3pH876YqKQhT2mRbPHfeOMh # T+1syJ6D/3JLgvgYPds3eM21i74kvDbl5M628ynmWSgsLsRJ9f1RHsTNXlgsiGV5 # rDTIHBAA7CwaXbaCl6yjJ3DiWhAz3b/yCqUi73qjluB7DrR1jlKlXVicAXMz3Cc0 # IHeAbUj0G2pD0F5Ac3d4D9CHALxNtgm64Jfny69+s6ly1D6Y3cXOFN3TE3XpGBt0 # 1RY2HbcSzUDbO2lVFbPba069gIwR46iQ4AQjG4i31YheDyY9PtaaK2DodjLKBCbE # LKwBWWbmNdzqX4IApEeBvmWkgk5CNYhzMwM5JX1pKy/BMlzqoX/Zobv3sbm7IaMd # vmpCDHtANtyKqe+5bwl9hPhuX/i9LZtOUDeRIdMNW6xswRrx12+evjG02PIJjPLn # a4fFRzC3usTQfuj9by0MA1DQ+RbCKF8ImemiiLUYu9UAbPT0sNAepMnXZE7AunQM # YmaEZyVHgHhzmVzHgKdn4X3MFlWlB9sAMIIHKDCCBRCgAwIBAgITMwAAABcnRQkL # i4evxgAAAAAAFzANBgkqhkiG9w0BAQwFADBjMQswCQYDVQQGEwJVUzEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTQwMgYDVQQDEytNaWNyb3NvZnQgSUQg # VmVyaWZpZWQgQ29kZSBTaWduaW5nIFBDQSAyMDIxMB4XDTI2MDMyNjE4MTEzMVoX # DTMxMDMyNjE4MTEzMVowWjELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjErMCkGA1UEAxMiTWljcm9zb2Z0IElEIFZlcmlmaWVkIENT # IEVPQyBDQSAwNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAILHZP4D # D2YqAZXMn5OrQ8yfj0beK0ixilvHsKUtJEcV7VEQt09xnWwipY6GxJ/LrLKoRqkK # UYf0l70VcDVxCBm++lBuSD5AidUuv/QQ+tUELCsz3qVtEjY/E14LBcb0uzJbaEbo # pCCKe0OY0IGjjOkMivfvumVV1KWJmbpQHusfCa8GdHTZBPq2euparaKHMHqVElVM # TO6HQ5p/Mgx4ydgzT7H697kQ4sd1+Kr4deIx/0lvtgse1iDIciIkDttNYuoVIsZp # OHtmVvFuwtcD3U46ugSm/s6PMW67e2SkL0V+UDgOnYS6rj6o+bFSp8an5NfSAtEm # n00k7PMguNxMPeuQUUVvFS/XHKDpq+K8UMu2goGEzZN3Xfy6YTWk05pxqe5Ji08c # h5AeYHqFoWLrhq8sEvBNMCb9FuK3zrRwVdHvbCr7lCHiFKZ7MeopcRFY+lUF74A+ # sngipz5o94yYiSgJZlA7bYecs0VQVJeOLDIhuC+Uf8sgAkSpNp9PPENmAqGUtTvO # vqDCyrdY2lxhAjo27FafCHdVUMPIXuidCoqzkuXtuV5U3RjxW+qATjmmnIFu/Co3 # 9G6fl8wIJHPdpgxjSRmEo73Z4/u3jMepnltAwCBnS0TY/P+NvTCLKRQX89yg6qqT # e9UuJENiy3q93cYQw3MylRS9By8Ebjr4I4hvAgMBAAGjggHcMIIB2DAOBgNVHQ8B # Af8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFJrxVHd1DIcWN0ag # rN55+fR/wXjpMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRw # Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0w # GQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwEgYDVR0TAQH/BAgwBgEB/wIBADAf # BgNVHSMEGDAWgBTZQSmwDw9jbO9p1/XNKZ6kSGow5jBwBgNVHR8EaTBnMGWgY6Bh # hl9odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQl # MjBJRCUyMFZlcmlmaWVkJTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDIxLmNy # bDB9BggrBgEFBQcBAQRxMG8wbQYIKwYBBQUHMAKGYWh0dHA6Ly93d3cubWljcm9z # b2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUy # MENvZGUlMjBTaWduaW5nJTIwUENBJTIwMjAyMS5jcnQwDQYJKoZIhvcNAQEMBQAD # ggIBAJB1Whn9TSbfyXaIppkWWzFq+m2mg4vJpHVr1krZNIXWQ6cUmEwOx7oqQKCy # 96iISNdNVzpe3zogoefvo2TmpkHQFe/aIxFDaCIAmZi9lyay2hmp8HYzcp3nCcmF # Qk60X9voeypJ6VjqeGsXTrOivWUOYNCLEFlwsH3NHX5EpCyjWN6Q3Fi5ST4do3eT # VLnuqTQ7/9huTBTSYQsJbTg3m8gIxnHlPlzs2r/u4u9tWEJ0Pt/ZtmkDhTu86QHW # igHgBoRHemOgnQxp3ksXKLo1r2n1m7+Gst46NTkUi1LljGyq+V9fEBOEnXvoKaRi # y0pGbK1IdnsmEpF9Xp71l+2T84Nv8IrikZUBWqw5/jffttAas4ccJDci832CadS4 # OHwl29uF6hY8fEg3UYHmxSJjnzi1c3vF0PwsJKxGom9Dx7treBlZOBWK6BGzVBar # 43Qb02N7okeU3UKMl6GB74fk8aS0mNr6O4YSvQ/66RKRwvqppnEVBOHdIMjvWW9b # 77duX8TN3pI7w31R3D6t6jK9EcLJOJKymVlBIFNUl0+ajeoKka7IcW0+jkIGff8U # 9OKol3cz0Eeiop3Qb0qaDp8ZwC8XCcs1cDaSi/vbvBGWMvfKl+ovuIBP9ienG6Xp # HAdGVw5/10MaDVFG+v3Y0/8JZVchvryB5Hau9T82x+a2MXXAMIIHnjCCBYagAwIB # AgITMwAAAAeHozSje6WOHAAAAAAABzANBgkqhkiG9w0BAQwFADB3MQswCQYDVQQG # EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMUgwRgYDVQQDEz9N # aWNyb3NvZnQgSWRlbnRpdHkgVmVyaWZpY2F0aW9uIFJvb3QgQ2VydGlmaWNhdGUg # QXV0aG9yaXR5IDIwMjAwHhcNMjEwNDAxMjAwNTIwWhcNMzYwNDAxMjAxNTIwWjBj # MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTQw # MgYDVQQDEytNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ29kZSBTaWduaW5nIFBDQSAy # MDIxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsvDArxmIKOLdVHpM # SWxpCFUJtFL/ekr4weslKPdnF3cpTeuV8veqtmKVgok2rO0D05BpyvUDCg1wdsoE # tuxACEGcgHfjPF/nZsOkg7c0mV8hpMT/GvB4uhDvWXMIeQPsDgCzUGzTvoi76YDp # xDOxhgf8JuXWJzBDoLrmtThX01CE1TCCvH2sZD/+Hz3RDwl2MsvDSdX5rJDYVuR3 # bjaj2QfzZFmwfccTKqMAHlrz4B7ac8g9zyxlTpkTuJGtFnLBGasoOnn5NyYlf0xF # 9/bjVRo4Gzg2Yc7KR7yhTVNiuTGH5h4eB9ajm1OCShIyhrKqgOkc4smz6obxO+Hx # KeJ9bYmPf6KLXVNLz8UaeARo0BatvJ82sLr2gqlFBdj1sYfqOf00Qm/3B4XGFPDK # /H04kteZEZsBRc3VT2d/iVd7OTLpSH9yCORV3oIZQB/Qr4nD4YT/lWkhVtw2v2s0 # TnRJubL/hFMIQa86rcaGMhNsJrhysLNNMeBhiMezU1s5zpusf54qlYu2v5sZ5zL0 # KvBDLHtL8F9gn6jOy3v7Jm0bbBHjrW5yQW7S36ALAt03QDpwW1JG1Hxu/FUXJbBO # 2AwwVG4Fre+ZQ5Od8ouwt59FpBxVOBGfN4vN2m3fZx1gqn52GvaiBz6ozorgIEjn # +PhUXILhAV5Q/ZgCJ0u2+ldFGjcCAwEAAaOCAjUwggIxMA4GA1UdDwEB/wQEAwIB # hjAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU2UEpsA8PY2zvadf1zSmepEhq # MOYwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTAZBgkrBgEE # AYI3FAIEDB4KAFMAdQBiAEMAQTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaA # FMh+0mqFKhvKGZgEByfPUBBPaKiiMIGEBgNVHR8EfTB7MHmgd6B1hnNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBJZGVudGl0 # eSUyMFZlcmlmaWNhdGlvbiUyMFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0 # eSUyMDIwMjAuY3JsMIHDBggrBgEFBQcBAQSBtjCBszCBgQYIKwYBBQUHMAKGdWh0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIw # SWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUlMjBB # dXRob3JpdHklMjAyMDIwLmNydDAtBggrBgEFBQcwAYYhaHR0cDovL29uZW9jc3Au # bWljcm9zb2Z0LmNvbS9vY3NwMA0GCSqGSIb3DQEBDAUAA4ICAQB/JSqe/tSr6t1m # CttXI0y6XmyQ41uGWzl9xw+WYhvOL47BV09Dgfnm/tU4ieeZ7NAR5bguorTCNr58 # HOcA1tcsHQqt0wJsdClsu8bpQD9e/al+lUgTUJEV80Xhco7xdgRrehbyhUf4pkeA # hBEjABvIUpD2LKPho5Z4DPCT5/0TlK02nlPwUbv9URREhVYCtsDM+31OFU3fDV8B # mQXv5hT2RurVsJHZgP4y26dJDVF+3pcbtvh7R6NEDuYHYihfmE2HdQRq5jRvLE1E # b59PYwISFCX2DaLZ+zpU4bX0I16ntKq4poGOFaaKtjIA1vRElItaOKcwtc04CBrX # SfyL2Op6mvNIxTk4OaswIkTXbFL81ZKGD+24uMCwo/pLNhn7VHLfnxlMVzHQVL+b # Ha9KhTyzwdG/L6uderJQn0cGpLQMStUuNDArxW2wF16QGZ1NtBWgKA8Kqv48M8Hf # FqNifN6+zt6J0GwzvU8g0rYGgTZR8zDEIJfeZxwWDHpSxB5FJ1VVU1LIAtB7o9PX # bjXzGifaIMYTzU4YKt4vMNwwBmetQDHhdAtTPplOXrnI9SI6HeTtjDD3iUN/7ygb # ahmYOHk7VB7fwT4ze+ErCbMh6gHV1UuXPiLciloNxH6K4aMfZN1oLVk6YFeIJEok # uPgNPa6EnTiOL60cPqfny+Fq8UiuZzGCGpQwghqQAgEBMHEwWjELMAkGA1UEBhMC # VVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjErMCkGA1UEAxMiTWlj # cm9zb2Z0IElEIFZlcmlmaWVkIENTIEVPQyBDQSAwNAITMwAIK9mfcYvDu5GkOwAA # AAgr2TANBglghkgBZQMEAgEFAKBeMBAGCisGAQQBgjcCAQwxAjAAMBkGCSqGSIb3 # DQEJAzEMBgorBgEEAYI3AgEEMC8GCSqGSIb3DQEJBDEiBCBHJjbpgh0Zao6+HJWX # oKLnqsGzhLEk1v4dBDG7lYFnczANBgkqhkiG9w0BAQEFAASCAYBB8G6Lk9lE9Qal # t6nqiTy3CvHTP/DhVcXEqSwMTTc6FYs3u/I5LxdBylN5wkAkTphcv2SEK5sTF7e2 # kYEsquHdhi7HB0xQNFS95l9j1vnLjdhVK8VDSr2IaLmGwtE2aJcjWYAyfh6/5o6J # KoKlo/Y2ombM2ZAah5yqgEosk04phO6w1h6WSLrdMH/paqRA++7YA5QcDLNcIq+t # KsJrwhEV2009SYGvZOMzoN2bz6NHK2wTcBnQemQ5JIlWWMt4pezjXaOb7jKsaAJw # 1OvJoBbEn4ZiND4GhwEJPmxxjKbf9HDHgA4Q8bYCqWnFrb8JMly6kAtqYLPJtQ+B # J/0bTkfQWnmYnoqaLYhjVQV4EyJowBxUA0g4vvxuyAuVAt/ADTZ1+uLrxS/sjYcq # kT4TddRiNtGM/gWBZJO33usVbEmUDyx83AsBkowGxblfowKad/zbMi0/s0JNJu17 # MB+tuDI5Fhh9WuNqu9k9Br2Spz95axoYunS0rJy/XBVE791fPbShghgUMIIYEAYK # KwYBBAGCNwMDATGCGAAwghf8BgkqhkiG9w0BBwKgghftMIIX6QIBAzEPMA0GCWCG # SAFlAwQCAQUAMIIBYgYLKoZIhvcNAQkQAQSgggFRBIIBTTCCAUkCAQEGCisGAQQB # hFkKAwEwMTANBglghkgBZQMEAgEFAAQg5kI/NB0OkONiSxH5/GWfJdkDIAao7ln2 # h93It2a6PTUCBmrI5fdjJxgTMjAyNjEwMTMyMjEyMDYuOTc0WjAEgAIB9KCB4aSB # 3jCB2zELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UE # CxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVs # ZCBUU1MgRVNOOkE1MDAtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVi # bGljIFJTQSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eaCCDyEwggeCMIIFaqADAgEC # AhMzAAAABeXPD/9mLsmHAAAAAAAFMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYT # AlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01p # Y3Jvc29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBB # dXRob3JpdHkgMjAyMDAeFw0yMDExMTkyMDMyMzFaFw0zNTExMTkyMDQyMzFaMGEx # CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAw # BgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIw # MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnnznUmP94MWfBX1jtQYi # oxwe1+eXM9ETBb1lRkd3kcFdcG9/sqtDlwxKoVIcaqDb+omFio5DHC4RBcbyQHjX # CwMk/l3TOYtgoBjxnG/eViS4sOx8y4gSq8Zg49REAf5huXhIkQRKe3Qxs8Sgp02K # HAznEa/Ssah8nWo5hJM1xznkRsFPu6rfDHeZeG1Wa1wISvlkpOQooTULFm809Z0Z # YlQ8Lp7i5F9YciFlyAKwn6yjN/kR4fkquUWfGmMopNq/B8U/pdoZkZZQbxNlqJOi # BGgCWpx69uKqKhTPVi3gVErnc/qi+dR8A2MiAz0kN0nh7SqINGbmw5OIRC0EsZ31 # WF3Uxp3GgZwetEKxLms73KG/Z+MkeuaVDQQheangOEMGJ4pQZH55ngI0Tdy1bi69 # INBV5Kn2HVJo9XxRYR/JPGAaM6xGl57Ei95HUw9NV/uC3yFjrhc087qLJQawSC3x # zY/EXzsT4I7sDbxOmM2rl4uKK6eEpurRduOQ2hTkmG1hSuWYBunFGNv21Kt4N20A # KmbeuSnGnsBCd2cjRKG79+TX+sTehawOoxfeOO/jR7wo3liwkGdzPJYHgnJ54Uxb # ckF914AqHOiEV7xTnD1a69w/UTxwjEugpIPMIIE67SFZ2PMo27xjlLAHWW3l1CEA # FjLNHd3EQ79PUr8FUXetXr0CAwEAAaOCAhswggIXMA4GA1UdDwEB/wQEAwIBhjAQ # BgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQUa2koOjUvSGNAz3vYr0npPtk92yEw # VAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWlj # cm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAK # BggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAPBgNVHRMBAf8E # BTADAQH/MB8GA1UdIwQYMBaAFMh+0mqFKhvKGZgEByfPUBBPaKiiMIGEBgNVHR8E # fTB7MHmgd6B1hnNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9N # aWNyb3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUyMFJvb3QlMjBDZXJ0 # aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3JsMIGUBggrBgEFBQcBAQSBhzCB # hDCBgQYIKwYBBQUHMAKGdWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv # Y2VydHMvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290 # JTIwQ2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNydDANBgkqhkiG9w0B # AQwFAAOCAgEAX4h2x35ttVoVdedMeGj6TuHYRJklFaW4sTQ5r+k77iB79cSLNe+G # zRjv4pVjJviceW6AF6ycWoEYR0LYhaa0ozJLU5Yi+LCmcrdovkl53DNt4EXs87KD # ogYb9eGEndSpZ5ZM74LNvVzY0/nPISHz0Xva71QjD4h+8z2XMOZzY7YQ0Psw+ety # NZ1CesufU211rLslLKsO8F2aBs2cIo1k+aHOhrw9xw6JCWONNboZ497mwYW5EfN0 # W3zL5s3ad4Xtm7yFM7Ujrhc0aqy3xL7D5FR2J7x9cLWMq7eb0oYioXhqV2tgFqbK # HeDick+P8tHYIFovIP7YG4ZkJWag1H91KlELGWi3SLv10o4KGag42pswjybTi4to # QcC/irAodDW8HNtX+cbz0sMptFJK+KObAnDFHEsukxD+7jFfEV9Hh/+CSxKRsmnu # iovCWIOb+H7DRon9TlxydiFhvu88o0w35JkNbJxTk4MhF/KgaXn0GxdH8elEa2Im # q45gaa8D+mTm8LWVydt4ytxYP/bqjN49D9NZ81coE6aQWm88TwIf4R4YZbOpMKN0 # CyejaPNN41LGXHeCUMYmBx3PkP8ADHD1J2Cr/6tjuOOCztfp+o9Nc+ZoIAkpUcA/ # X2gSMkgHAPUvIdtoSAHEUKiBhI6JQivRepyvWcl+JYbYbBh7pmgAXVswggeXMIIF # f6ADAgECAhMzAAAAYHIGJIpKBbjZAAAAAABgMA0GCSqGSIb3DQEBDAUAMGExCzAJ # BgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNV # BAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwMB4X # DTI2MDkxNzE4NTcyN1oXDTI3MDkxNDE4NTcyN1owgdsxCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNh # IE9wZXJhdGlvbnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjpBNTAwLTA1RTAt # RDk0NzE1MDMGA1UEAxMsTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBTdGFtcGlu # ZyBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCaE2NL # wFPHivpDfMeASpyJR/YkExXCIhEJXza+XHOY1hGkA6ao2ad71PwUkWBnp707PqB7 # OFEH4XwXj1KLqcH76xP65J0WzFdOUXyufOYEF5+L9niiFkra3EJXSc1wzDuEgJO8 # QSo2ArhmWlyFdWvxyFj7FQsrJFRqs1cYjvJpuC+I9amZgH5b8ageWd9Xot3lqdg3 # IfhRI5NJVVAD/Uilf70bg7vS52a97Sc1dMwdpmq1y25Pv6ItqWnoAPZRaSDRT+jO # 8vVlU8Zjdciqmg/hEg5TZIn5D2/wgDd5l4g20AicErzwL7sAW9/J2qu7o++A7JnC # bvvwkCat8EID4WM5jh/J9qKDWUlzXX/2xH4vrsFsteuPGZubow2DGMn3ov0uPJVU # pFbjkxsTChZ9inGRJns3lXP3Tz9ri2iDJdiqGmNybNR3BhB9e8pJdkwQXnFQYp5/ # N+FZx845ERvqd9QoxNc0ggoRA9RWtKnTjAp/2pA7WyToq2gQ/XhkTWEjYHyQsCmk # b/8JYoPMoxQJNQ3LPxMZ5L8zBnyxPlq3ifwZhOPfUtO9rj1g1OKEkAsFJmJzJGfu # LwTc1AbkuGVTpFOco0YJWcx0gr9QVfFOVZhBAXew3cXNGlJebmTUM9qOI5Cor38Y # MQUWc4KijuiQsKGqfpUekuS4i1BA8G49scji3wIDAQABo4IByzCCAccwHQYDVR0O # BBYEFIhUKHRhUAQ7Ewm4gt6So7de2mpiMB8GA1UdIwQYMBaAFGtpKDo1L0hjQM97 # 2K9J6T7ZPdshMGwGA1UdHwRlMGMwYaBfoF2GW2h0dHA6Ly93d3cubWljcm9zb2Z0 # LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFB1YmxpYyUyMFJTQSUyMFRpbWVz # dGFtcGluZyUyMENBJTIwMjAyMC5jcmwweQYIKwYBBQUHAQEEbTBrMGkGCCsGAQUF # BzAChl1odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jv # c29mdCUyMFB1YmxpYyUyMFJTQSUyMFRpbWVzdGFtcGluZyUyMENBJTIwMjAyMC5j # cnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8B # Af8EBAMCB4AwZgYDVR0gBF8wXTBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcC # ARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRv # cnkuaHRtMAgGBmeBDAEEAjANBgkqhkiG9w0BAQwFAAOCAgEAV4vmfykFNJc9GbTl # 2Jxub4K5oulwAz+QKHvLEpujstjXFiHDnIhr96U5YuOmFVa58aCecRcGqrja4YM8 # 4DMVEUe4GXDyHbsLGW6ixMxzGzwSuz2uBBvs2Cccc259zOavuXOft2QhOcvBijiX # XbFuSSPZXALUvR5i1uEkSOypuBedo4fUCs49v+vGpe2dqsS4O9mIEzBs2XsuRBeV # OYNKOHwCcXlXw4Ka8B5LPsMwbfMO3GYVt/NXQGx4lZPPVmInNNe84JUaHSwILSb7 # FUHGmf58TySy2QohU7wPgxmsC32uhAVgf8Aqjd2dOOurzxS4DvqqlFpmGvT7N/aI # XSAoAcGAZg82c9nvcgdBEkxCJ9IKr8yhZBrfw7ex9pwNHa+DG8Nn6N+jstAVeD4I # KAfaHPodl+F8PxKdN72YBgdj9ExoeFH36MnSqVu8WMdoQEXeKwCpaimxMlZUMw8T # LjuHA4h+QDIv1zj9xwiXNLScUdErGE3ng5fU39s3BnHBtIcuhftj5VJ1YR+n/Cud # tSh8jkrKFqB7iBk4xle3fdzHFUUYGtOSqk27E2sBha/22Ex91IRC8ZV6UCAvJ50y # NCRX97xQP+Vrs3nx1Z3Nw2VcVt81F78WHOx/hKtbUiWXIW5cjYaxnJdjUoeEKcAa # Tyni13gki4MhW2rpGgFeECXSABYxggdGMIIHQgIBATB4MGExCzAJBgNVBAYTAlVT # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jv # c29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwAhMzAAAAYHIGJIpK # BbjZAAAAAABgMA0GCWCGSAFlAwQCAQUAoIIEnzARBgsqhkiG9w0BCRACDzECBQAw # GgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNjEw # MTMyMjEyMDZaMC8GCSqGSIb3DQEJBDEiBCAI2fN3igv7DW5M8GnLQvmhFGNPOhKK # /ZG1tfIAGaDOITCBuQYLKoZIhvcNAQkQAi8xgakwgaYwgaMwgaAEIDfLjLnwvS54 # utKqPKxmcYlH7Orna0xc019MpXpStgKzMHwwZaRjMGExCzAJBgNVBAYTAlVTMR4w # HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29m # dCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwAhMzAAAAYHIGJIpKBbjZ # AAAAAABgMIIDYQYLKoZIhvcNAQkQAhIxggNQMIIDTKGCA0gwggNEMIICLAIBATCC # AQmhgeGkgd4wgdsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw # DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x # JTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNVBAsT # Hm5TaGllbGQgVFNTIEVTTjpBNTAwLTA1RTAtRDk0NzE1MDMGA1UEAxMsTWljcm9z # b2Z0IFB1YmxpYyBSU0EgVGltZSBTdGFtcGluZyBBdXRob3JpdHmiIwoBATAHBgUr # DgMCGgMVAJe/M8jCvUlk8+ItY60JUWKjdUI3oGcwZaRjMGExCzAJBgNVBAYTAlVT # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jv # c29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwMA0GCSqGSIb3DQEB # CwUAAgUA7niqczAiGA8yMDI2MTAxMzEzMDI0M1oYDzIwMjYxMDE0MTMwMjQzWjB3 # MD0GCisGAQQBhFkKBAExLzAtMAoCBQDueKpzAgEAMAoCAQACAhnKAgH/MAcCAQAC # AhKOMAoCBQDuefvzAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKg # CjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBAIG3oNJB # iSEx2hSLcM/f900dfFan97u3GjkbGNtOsGKAp+2WODaMaRHuNS6pKPl27ZfQSWKt # 5ml0wyD4GlPI23d1NrvTT2fe8gtsCc64xd36D9UHR0CIelf7jSVfccMUs28x42l9 # YWxX0jNFASXWS3OS/mtY98cxzidIN0uvDdGpIk856ohPdSTtL75/u9GYAE2P6kQH # vyvAS9jdIDhMB6xgeeRBkww56WPRfJnsyRBZ8BkdPBPa+RLvU8aQupdlzAu97TSp # mRfEiqeQ+SMzuKQWWxJxr3hGzx9RMhR401/4B9ysryP5AhBFs3vm+yeF5RzKCSNm # PU34c2UBvhx5b7UwDQYJKoZIhvcNAQEBBQAEggIAT9L5SVnPSaz/OPOQnOXR1WgK # gn9G6ipjQCtlcgURPMhcQybsLQKv+9re0ZOHs5TpPUP37qGW4DZ2SNmP9bS3WWHc # +K/YI2Ezprmz8fiVpn8vTIbJBucEztdC53jJohrkqsGvlkd+/QJfvLFNeB5L0BV3 # yDBmJu9WFj+NqkknJI6hC4Am5ockGkyMJEvav8GVvS2Ugbj31hsoSb9fGQrSLW4k # PhVWomlcO+x15YwastkLjJzIQ2BYU5juH2IxdYGSDDVxqXrPE5xUstGja441me0k # tISImUt0NYvNMW51ZqcjZ0rO2cgChg1skYi5h8Sw9oeJ1BdxkSUtvkqZN0CC9lw8 # UwchK8Uy+nSLx9CCbAscYpp4f3y6ahe+82IeiNwCFV9jvq9OXjE00CD/4SWO2mKD # mWA/l9CkjuWbDUCPKWyaaANUtxTgsOaNO/EYdaW5TmkpY0v/Wr8K4mRvypwHw547 # vRSlx8xfZd3BVoqSkPgGQ48KCvj+ddbKVdqN0WY6HaCO5DMTlvXk5k1kHiI++8xT # 0iHM0psZvEwXfcE9HZ5tlxqE2C2o5HYY0s8Ey6MZcFgl+utgKEg849OuRAhB7oiF # eOH0L28T8fzg8fAUdCHfkSFb5i1oSUEaSgaVsGUgHglh7w2r4cLDEexetFS/dfYR # xq/FA1yi5vXnASZI3B4= # SIG # End signature block |