Private/Discovery.ps1
|
function Get-DotNetProductType { param( [Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $DisplayName ) if ([string]::IsNullOrWhiteSpace($DisplayName)) { return $null } if ($DisplayName.IndexOf('.NET Core SDK', [StringComparison]::OrdinalIgnoreCase) -ge 0 -or $DisplayName.IndexOf('Microsoft .NET SDK', [StringComparison]::OrdinalIgnoreCase) -ge 0) { return 'Sdk' } if ($DisplayName.IndexOf('ASP.NET', [StringComparison]::OrdinalIgnoreCase) -ge 0 -and ($DisplayName.IndexOf('Runtime', [StringComparison]::OrdinalIgnoreCase) -ge 0 -or $DisplayName.IndexOf('Shared Framework', [StringComparison]::OrdinalIgnoreCase) -ge 0)) { return 'AspNetCoreRuntime' } if ($DisplayName.IndexOf('Windows Desktop Runtime', [StringComparison]::OrdinalIgnoreCase) -ge 0 -or $DisplayName.IndexOf( 'Dotnet Shared Framework for Windows Desktop', [StringComparison]::OrdinalIgnoreCase ) -ge 0) { return 'WindowsDesktopRuntime' } if ($DisplayName.IndexOf('.NET Core Runtime', [StringComparison]::OrdinalIgnoreCase) -ge 0 -or $DisplayName.IndexOf('Microsoft .NET Runtime', [StringComparison]::OrdinalIgnoreCase) -ge 0) { return 'Runtime' } return $null } function Get-DotNetVersionFromDisplayName { param( [Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $DisplayName ) if ([string]::IsNullOrWhiteSpace($DisplayName)) { return $null } if ($DisplayName -match '(?i)(?<core>\d+\.\d+\.\d+)\s+(?<label>preview|alpha|rc)\s*(?<number>\d+(?:\.\d+)*)') { return '{0}-{1}.{2}' -f $Matches.core, $Matches.label.ToLowerInvariant(), $Matches.number } if ($DisplayName -match '(?<version>\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)') { return $Matches.version } return $null } function Get-DotNetBundleIdentity { param( [Parameter(Mandatory = $true)] [string] $DisplayName, [AllowEmptyString()] [string] $BundleCachePath, [AllowEmptyString()] [string] $UninstallString ) $productType = Get-DotNetProductType -DisplayName $DisplayName if ($null -eq $productType) { return $null } $version = $null $architecture = $null $identityText = "$BundleCachePath`n$UninstallString" if ($identityText -match '(?i)(?:dotnet-sdk|dotnet-runtime|aspnetcore-runtime|windowsdesktop-runtime)-(?<version>\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)-win-(?<architecture>x64|x86|arm64)\.exe') { $version = $Matches.version $architecture = $Matches.architecture.ToLowerInvariant() } elseif ($identityText -match '(?i)dotnet-(?:dev-)?win-(?<architecture>x64|x86)\.(?<version>\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)\.exe') { $version = $Matches.version $architecture = $Matches.architecture.ToLowerInvariant() } if ([string]::IsNullOrWhiteSpace($version)) { $version = Get-DotNetVersionFromDisplayName -DisplayName $DisplayName } if ([string]::IsNullOrWhiteSpace($architecture) -and $DisplayName -match '(?i)\((?<architecture>x64|x86|arm64)\)') { $architecture = $Matches.architecture.ToLowerInvariant() } if ([string]::IsNullOrWhiteSpace($version) -or [string]::IsNullOrWhiteSpace($architecture)) { return $null } [pscustomobject] @{ ProductType = $productType Version = $version Architecture = $architecture Rid = "win-$architecture" } } function Get-DotNetBundleInventory { $registryHive = [Microsoft.Win32.RegistryHive]::LocalMachine # Official .NET Burn bundles register in the 32-bit Add/Remove Programs view. $registryView = [Microsoft.Win32.RegistryView]::Registry32 $uninstallPath = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall' $bundles = New-Object System.Collections.Generic.List[object] $baseKey = $null $uninstallKey = $null try { $baseKey = [Microsoft.Win32.RegistryKey]::OpenBaseKey($registryHive, $registryView) $uninstallKey = $baseKey.OpenSubKey($uninstallPath) if ($null -eq $uninstallKey) { return @() } foreach ($subkeyName in $uninstallKey.GetSubKeyNames()) { $bundleKey = $uninstallKey.OpenSubKey($subkeyName) if ($null -eq $bundleKey) { continue } try { $displayName = [string] $bundleKey.GetValue('DisplayName') $displayVersion = [string] $bundleKey.GetValue('DisplayVersion') $bundleVersion = [string] $bundleKey.GetValue('BundleVersion') $publisher = [string] $bundleKey.GetValue('Publisher') $uninstallString = [string] $bundleKey.GetValue('UninstallString') $quietUninstallString = [string] $bundleKey.GetValue('QuietUninstallString') $bundleCachePath = [string] $bundleKey.GetValue('BundleCachePath') $productType = Get-DotNetProductType -DisplayName $displayName $isVisualStudioOwned = $displayName.IndexOf('Visual Studio', [StringComparison]::OrdinalIgnoreCase) -ge 0 -or $displayName.IndexOf('VS 2015', [StringComparison]::OrdinalIgnoreCase) -ge 0 -or $displayName.IndexOf('Local Feed', [StringComparison]::OrdinalIgnoreCase) -ge 0 $isExeBundle = $uninstallString.IndexOf('.exe', [StringComparison]::OrdinalIgnoreCase) -ge 0 -and $uninstallString.IndexOf('msiexec', [StringComparison]::OrdinalIgnoreCase) -lt 0 if ($null -eq $productType -or -not $isExeBundle -or $publisher -cne 'Microsoft Corporation' -or [string]::IsNullOrWhiteSpace($displayVersion) -or [string]::IsNullOrWhiteSpace($bundleVersion)) { continue } $identity = Get-DotNetBundleIdentity -DisplayName $displayName ` -BundleCachePath $bundleCachePath -UninstallString $uninstallString if ($null -eq $identity) { Write-Warning "Ignoring .NET bundle '$displayName' because its version or architecture could not be determined." continue } try { $versionInfo = New-SdkVersionInfo -Text $identity.Version } catch { Write-Warning "Ignoring .NET bundle '$displayName' because version '$($identity.Version)' is invalid." continue } $bundleProviderKey = [string] $bundleKey.GetValue('BundleProviderKey') if ([string]::IsNullOrWhiteSpace($bundleProviderKey)) { $bundleProviderKey = $subkeyName } $bundles.Add([pscustomobject] @{ PSTypeName = 'DotNetSteward.Installation' ProductType = $identity.ProductType Version = $versionInfo.Text VersionInfo = $versionInfo Architecture = $identity.Architecture Rid = $identity.Rid InstallerKind = 'Bundle' ManagementSource = if ($isVisualStudioOwned) { 'VisualStudio' } else { 'Standalone' } ManagedByVisualStudio = $isVisualStudioOwned Owners = @($displayName) IsUpdateable = -not $isVisualStudioOwned IsUninstallable = -not $isVisualStudioOwned DisplayName = $displayName DisplayVersion = $displayVersion BundleVersion = $bundleVersion BundleId = $bundleProviderKey BundleUpgradeCode = @($bundleKey.GetValue('BundleUpgradeCode')) BundleCachePath = $bundleCachePath UninstallString = $uninstallString QuietUninstallString = $quietUninstallString RegistryView = [string] $registryView RegistrySubkey = "$uninstallPath\$subkeyName" }) } finally { $bundleKey.Dispose() } } } finally { if ($null -ne $uninstallKey) { $uninstallKey.Dispose() } if ($null -ne $baseKey) { $baseKey.Dispose() } } return $bundles.ToArray() } function Get-DotNetSdkBundleInventory { return @( Get-DotNetInstallationInventory | Where-Object { $_.ProductType -eq 'Sdk' -and $_.InstallerKind -eq 'Bundle' -and $_.IsUpdateable } ) } function Get-DotNetDependencyMap { $dependencyPath = 'SOFTWARE\Classes\Installer\Dependencies' $byProductCode = @{} foreach ($registryView in @( [Microsoft.Win32.RegistryView]::Registry32, [Microsoft.Win32.RegistryView]::Registry64 )) { $baseKey = [Microsoft.Win32.RegistryKey]::OpenBaseKey( [Microsoft.Win32.RegistryHive]::LocalMachine, $registryView ) $dependenciesKey = $baseKey.OpenSubKey($dependencyPath) try { if ($null -eq $dependenciesKey) { continue } foreach ($providerName in $dependenciesKey.GetSubKeyNames()) { $providerKey = $dependenciesKey.OpenSubKey($providerName) if ($null -eq $providerKey) { continue } try { $productCode = [string] $providerKey.GetValue($null) if ($productCode -notmatch '^\{[0-9A-Fa-f-]{36}\}$') { continue } $dependentsKey = $providerKey.OpenSubKey('Dependents') try { $dependents = if ($null -ne $dependentsKey) { @($dependentsKey.GetSubKeyNames()) } else { @() } } finally { if ($null -ne $dependentsKey) { $dependentsKey.Dispose() } } $mapKey = $productCode.ToUpperInvariant() if (-not $byProductCode.ContainsKey($mapKey)) { $byProductCode[$mapKey] = [pscustomobject] @{ ProviderKeys = New-Object System.Collections.Generic.List[string] Dependents = New-Object System.Collections.Generic.List[string] } } if (-not $byProductCode[$mapKey].ProviderKeys.Contains($providerName)) { $byProductCode[$mapKey].ProviderKeys.Add($providerName) } foreach ($dependent in $dependents) { if (-not $byProductCode[$mapKey].Dependents.Contains($dependent)) { $byProductCode[$mapKey].Dependents.Add($dependent) } } } finally { $providerKey.Dispose() } } } finally { if ($null -ne $dependenciesKey) { $dependenciesKey.Dispose() } $baseKey.Dispose() } } return $byProductCode } function Get-DotNetInstallRoot { param( [Parameter(Mandatory = $true)] [ValidateSet('x64', 'x86', 'arm64')] [string] $Architecture ) $setupPath = "SOFTWARE\dotnet\Setup\InstalledVersions\$Architecture" foreach ($registryView in @( [Microsoft.Win32.RegistryView]::Registry64, [Microsoft.Win32.RegistryView]::Registry32 )) { $baseKey = [Microsoft.Win32.RegistryKey]::OpenBaseKey( [Microsoft.Win32.RegistryHive]::LocalMachine, $registryView ) $setupKey = $baseKey.OpenSubKey($setupPath) try { if ($null -ne $setupKey) { $installLocation = [string] $setupKey.GetValue('InstallLocation') if (-not [string]::IsNullOrWhiteSpace($installLocation)) { return $installLocation } } } finally { if ($null -ne $setupKey) { $setupKey.Dispose() } $baseKey.Dispose() } } return $null } function Resolve-DotNetPayloadVersion { param( [Parameter(Mandatory = $true)] [ValidateSet('Sdk', 'Runtime', 'AspNetCoreRuntime', 'WindowsDesktopRuntime')] [string] $ProductType, [Parameter(Mandatory = $true)] [object] $VersionInfo, [Parameter(Mandatory = $true)] [ValidateSet('x64', 'x86', 'arm64')] [string] $Architecture, [AllowEmptyCollection()] [object[]] $OwnerBundles = @() ) if ($VersionInfo.IsStable) { return $VersionInfo } $installRoot = Get-DotNetInstallRoot -Architecture $Architecture if ([string]::IsNullOrWhiteSpace($installRoot)) { return $VersionInfo } if ($ProductType -eq 'Sdk') { $frameworkPath = Join-Path $installRoot 'sdk' } else { $frameworkName = switch ($ProductType) { 'Runtime' { 'Microsoft.NETCore.App' } 'AspNetCoreRuntime' { 'Microsoft.AspNetCore.App' } 'WindowsDesktopRuntime' { 'Microsoft.WindowsDesktop.App' } } $frameworkPath = Join-Path (Join-Path $installRoot 'shared') $frameworkName } if (-not (Test-Path -LiteralPath $frameworkPath -PathType Container)) { return $VersionInfo } $matches = New-Object System.Collections.Generic.List[object] foreach ($directory in Get-ChildItem -LiteralPath $frameworkPath -Directory -ErrorAction Stop) { if ($directory.Name -ne $VersionInfo.Text -and -not $directory.Name.StartsWith("$($VersionInfo.Text).", [StringComparison]::OrdinalIgnoreCase)) { continue } try { $matches.Add([pscustomobject] @{ VersionInfo = New-SdkVersionInfo -Text $directory.Name }) } catch { continue } } if ($matches.Count -eq 0) { return $VersionInfo } foreach ($ownerBundle in $OwnerBundles) { if ($ownerBundle.ProductType -eq $ProductType -and ($ownerBundle.VersionInfo.Text -eq $VersionInfo.Text -or $ownerBundle.VersionInfo.Text.StartsWith( "$($VersionInfo.Text).", [StringComparison]::OrdinalIgnoreCase ))) { return $ownerBundle.VersionInfo } if ($ownerBundle.VersionInfo.Major -eq $VersionInfo.Major -and $ownerBundle.VersionInfo.Minor -eq $VersionInfo.Minor -and -not [string]::IsNullOrWhiteSpace($ownerBundle.VersionInfo.Prerelease)) { $ownerMatch = @($matches | Where-Object { $_.VersionInfo.Prerelease -ceq $ownerBundle.VersionInfo.Prerelease }) if ($ownerMatch.Count -eq 1) { return $ownerMatch[0].VersionInfo } } } if ($matches.Count -eq 1) { return $matches[0].VersionInfo } return $VersionInfo } function Get-DotNetPayloadInventory { param( [Parameter(Mandatory = $true)] [AllowEmptyCollection()] [object[]] $Bundles ) $uninstallPath = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall' $visualStudioDependent = 'VS.{AEF703B8-D2CC-4343-915C-F54A30B90937}' $dependencyMap = Get-DotNetDependencyMap $bundleById = @{} foreach ($bundle in $Bundles) { $bundleById[$bundle.BundleId.ToUpperInvariant()] = $bundle } $payloads = New-Object System.Collections.Generic.List[object] foreach ($registryView in @( [Microsoft.Win32.RegistryView]::Registry32, [Microsoft.Win32.RegistryView]::Registry64 )) { $baseKey = [Microsoft.Win32.RegistryKey]::OpenBaseKey( [Microsoft.Win32.RegistryHive]::LocalMachine, $registryView ) $uninstallKey = $baseKey.OpenSubKey($uninstallPath) try { if ($null -eq $uninstallKey) { continue } foreach ($subkeyName in $uninstallKey.GetSubKeyNames()) { $productKey = $uninstallKey.OpenSubKey($subkeyName) if ($null -eq $productKey) { continue } try { $displayName = [string] $productKey.GetValue('DisplayName') $publisher = [string] $productKey.GetValue('Publisher') $uninstallString = [string] $productKey.GetValue('UninstallString') $productType = Get-DotNetProductType -DisplayName $displayName if ($null -eq $productType -or $publisher -cne 'Microsoft Corporation' -or $uninstallString.IndexOf('msiexec', [StringComparison]::OrdinalIgnoreCase) -lt 0) { continue } $version = Get-DotNetVersionFromDisplayName -DisplayName $displayName if ([string]::IsNullOrWhiteSpace($version) -or $displayName -notmatch '(?i)\((?<architecture>x64|x86|arm64)\)') { continue } $architecture = $Matches.architecture.ToLowerInvariant() $productCode = $subkeyName.ToUpperInvariant() $providerKeys = @() $dependentIds = @() if ($dependencyMap.ContainsKey($productCode)) { $providerKeys = $dependencyMap[$productCode].ProviderKeys.ToArray() $dependentIds = $dependencyMap[$productCode].Dependents.ToArray() } $managedByVisualStudio = $false $owners = New-Object System.Collections.Generic.List[string] $ownerBundles = New-Object System.Collections.Generic.List[object] foreach ($dependentId in $dependentIds) { if ($dependentId -eq $visualStudioDependent) { $managedByVisualStudio = $true if (-not $owners.Contains('Visual Studio')) { $owners.Add('Visual Studio') } continue } $dependentKey = $dependentId.ToUpperInvariant() if ($bundleById.ContainsKey($dependentKey)) { $ownerBundle = $bundleById[$dependentKey] $ownerName = $ownerBundle.DisplayName if (-not $ownerBundles.Contains($ownerBundle)) { $ownerBundles.Add($ownerBundle) } } else { $ownerName = $dependentId } if (-not $owners.Contains($ownerName)) { $owners.Add($ownerName) } } try { $versionInfo = New-SdkVersionInfo -Text $version } catch { Write-Warning "Ignoring .NET payload '$displayName' because version '$version' is invalid." continue } try { $versionInfo = Resolve-DotNetPayloadVersion -ProductType $productType ` -VersionInfo $versionInfo -Architecture $architecture ` -OwnerBundles $ownerBundles.ToArray() } catch { Write-Warning "Could not refine the prerelease version for .NET payload '$displayName'; using '$version'. $($_.Exception.Message)" } $managementSource = if ($managedByVisualStudio) { 'VisualStudio' } elseif ($owners.Count -gt 0) { 'SharedInstaller' } else { 'WindowsInstaller' } $payloads.Add([pscustomobject] @{ PSTypeName = 'DotNetSteward.Installation' ProductType = $productType Version = $versionInfo.Text VersionInfo = $versionInfo Architecture = $architecture Rid = "win-$architecture" InstallerKind = 'Payload' ManagementSource = $managementSource ManagedByVisualStudio = $managedByVisualStudio Owners = $owners.ToArray() IsUpdateable = $false IsUninstallable = $false DisplayName = $displayName DisplayVersion = [string] $productKey.GetValue('DisplayVersion') ProductCode = $subkeyName DependencyProviderKeys = $providerKeys RegistryView = [string] $registryView RegistrySubkey = "$uninstallPath\$subkeyName" }) } finally { $productKey.Dispose() } } } finally { if ($null -ne $uninstallKey) { $uninstallKey.Dispose() } $baseKey.Dispose() } } return $payloads.ToArray() } function Get-DotNetInstallationInventory { $bundles = @(Get-DotNetBundleInventory) $payloads = @(Get-DotNetPayloadInventory -Bundles $bundles) $payloadsByIdentity = @{} foreach ($payload in $payloads) { $identity = "$($payload.ProductType)|$($payload.Version)|$($payload.Architecture)" if (-not $payloadsByIdentity.ContainsKey($identity)) { $payloadsByIdentity[$identity] = New-Object System.Collections.Generic.List[object] } $payloadsByIdentity[$identity].Add($payload) } $installations = New-Object System.Collections.Generic.List[object] foreach ($bundle in $bundles) { $identity = "$($bundle.ProductType)|$($bundle.Version)|$($bundle.Architecture)" if ($payloadsByIdentity.ContainsKey($identity)) { foreach ($payload in $payloadsByIdentity[$identity]) { if ($payload.ManagedByVisualStudio) { $bundle.ManagedByVisualStudio = $true $bundle.ManagementSource = 'StandaloneAndVisualStudio' $bundle.IsUpdateable = $false $bundle.IsUninstallable = $false } $bundle.Owners = @($bundle.Owners + $payload.Owners | Sort-Object -Unique) } $payloadsByIdentity.Remove($identity) } $installations.Add($bundle) } foreach ($remainingPayloads in $payloadsByIdentity.Values) { foreach ($payload in $remainingPayloads) { $installations.Add($payload) } } return $installations.ToArray() } function Sort-DotNetInstallations { param( [Parameter(Mandatory = $true)] [AllowEmptyCollection()] [object[]] $Installations ) $sorted = New-Object System.Collections.Generic.List[object] foreach ($installation in $Installations) { $insertAt = $sorted.Count for ($index = 0; $index -lt $sorted.Count; $index++) { $comparison = [string]::CompareOrdinal( [string] $installation.ProductType, [string] $sorted[$index].ProductType ) if ($comparison -eq 0) { $comparison = [string]::CompareOrdinal( [string] $installation.Architecture, [string] $sorted[$index].Architecture ) } if ($comparison -eq 0) { $comparison = Compare-SdkVersion -Left $installation.VersionInfo ` -Right $sorted[$index].VersionInfo } if ($comparison -lt 0) { $insertAt = $index break } } $sorted.Insert($insertAt, $installation) } return $sorted.ToArray() } # SIG # Begin signature block # MII9JwYJKoZIhvcNAQcCoII9GDCCPRQCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDSyyPg9T3BVSZz # U8gEDlplm4kK4VC2ruyO+bxIb9JoWqCCIewwggXMMIIDtKADAgECAhBUmNLR1FsZ # 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+Fq8UiuZzGCGpEwghqNAgEBMHEwWjELMAkGA1UEBhMC # VVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjErMCkGA1UEAxMiTWlj # cm9zb2Z0IElEIFZlcmlmaWVkIENTIEVPQyBDQSAwNAITMwAIK9mfcYvDu5GkOwAA # AAgr2TANBglghkgBZQMEAgEFAKBeMBAGCisGAQQBgjcCAQwxAjAAMBkGCSqGSIb3 # DQEJAzEMBgorBgEEAYI3AgEEMC8GCSqGSIb3DQEJBDEiBCD2W1SahzW4jHjwxubd # SrxkJLM/H4ulHsXAJM01vS5lfjANBgkqhkiG9w0BAQEFAASCAYA7Zui3no3C76w5 # pQor6DV44OigjC63byZnjZtZX9FInBFwZ4a3Q0cPcAmRd7Y+DuUFq6FY4DDEFwfD # G9+66Nqi+x5/dVDvhxajBseiYJfdAnhH7EgUXagOLuJlYHteQz7zHCE6PbQmc3Ma # iFJMwlI1Fdr7+kuzQH0+Tfxc6x8+jgVciGSthkpoz+N88Mp7BiUDNFUjto+pYTwC # Hefwz36ekF1qJAQMKYw3j276OTX80sJz6Zrjzy4mCDUmE9e4f3a1yAiIpo4MeoO0 # yw9AZZnmkOYVVgEu2GcN4WtfNJfTORNXfLl3x2v/DqaUc59d+Gdta7djEFpu7V5T # xHFWPXFUvoe5ZgpEcULC7wOHijkG4kDtUOW8GJbmWemi+CH93+Rttgr6HdIQZQrE # OUTZh3dC4OgEXG0RhTjyXz0c0ouxBlLT/fjeP0TsocHEBswviKNaif0FyAvcCP6P # qI634UjUCTU22L8AZrLHo6cuZDJ6gVBvFe9llTeA6Xaxmy/S0LihghgRMIIYDQYK # KwYBBAGCNwMDATGCF/0wghf5BgkqhkiG9w0BBwKgghfqMIIX5gIBAzEPMA0GCWCG # SAFlAwQCAQUAMIIBYgYLKoZIhvcNAQkQAQSgggFRBIIBTTCCAUkCAQEGCisGAQQB # hFkKAwEwMTANBglghkgBZQMEAgEFAAQgNqMnElIj0Ezxs3u1VvW9Nw/OrOawmVUo # FLXCHkMZhxMCBmrI9B12EBgTMjAyNjEwMTMyMzQ5NDIuNjU1WjAEgAIB9KCB4aSB # 3jCB2zELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UE # CxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVs # ZCBUU1MgRVNOOjdBMDAtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVi # 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 # f6ADAgECAhMzAAAAXcY5eE9AfTP9AAAAAABdMA0GCSqGSIb3DQEBDAUAMGExCzAJ # BgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNV # BAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwMB4X # DTI2MDkxNzE4NTcyMVoXDTI3MDkxNDE4NTcyMVowgdsxCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNh # IE9wZXJhdGlvbnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo3QTAwLTA1RTAt # RDk0NzE1MDMGA1UEAxMsTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBTdGFtcGlu # ZyBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCd96jc # 8RQPiazqg7HGevnT7FexggLz24QaPYwyNeHCyaTfUhE3u7t2JFbFSvU99WplRBLC # knQ2UHg2nkialDbCKjsxsAS7sZP1/DZWUYkF1qcbzuA0opGv3WKlTpH4dLa+yYZI # CRfW4qD8sC5S21n0cyTghk+3aPI/9SxTE0HwwSwNv7WNU4NKSwMZnK03YiYXzlRt # nziwAbOQjBqkeNWMsg5wjTud+6en/ymxgP6XgbpNNX5Aj0rIEqkcaD3jnEXkGO7y # Ojtq48+ce8xKPaHMZ+dkrDwWU+qYB6m5cKVlG+m+2oc8vN7puAwtEjL1H9IbJv9P # vvbeL0Jq8XlXEzXVEQG8Fw1C1fVC9nfNaow+mT27iwqCdpxVWsHpXb7PWCXk+JoR # tDqT/uyKL3Sbtu7KnWeE/G1Vq6ne6nbm+zSQA5o4k86fMbi5kKwHQ0fz4QQ0BYIM # /o/PEudWZsonB3J0JFbRDyov5LIh0lcysrHzlzgxM2vSGaeOZq1FY/yUyKPp50hh # Y8vEhbHl0k5ifhpUSYXkZ4UChlErHM9DDWN9RCcQDvEnT6iWkds99BvGLyTYE4tK # VDMdHm8Brarhf5fso+BdX89Eg5gmdS4pKqaTRLLYsSR8Gt9n2/fmqm/lBgUfwNYa # 9KEaCVmwG4kwhdUsjJPWyIQnz19iYCwwzf2MzQIDAQABo4IByzCCAccwHQYDVR0O # BBYEFEPbCl2ZTvB+Hlbt/eWoaMh/Wue5MB8GA1UdIwQYMBaAFGtpKDo1L0hjQM97 # 2K9J6T7ZPdshMGwGA1UdHwRlMGMwYaBfoF2GW2h0dHA6Ly93d3cubWljcm9zb2Z0 # LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFB1YmxpYyUyMFJTQSUyMFRpbWVz # dGFtcGluZyUyMENBJTIwMjAyMC5jcmwweQYIKwYBBQUHAQEEbTBrMGkGCCsGAQUF # BzAChl1odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jv # c29mdCUyMFB1YmxpYyUyMFJTQSUyMFRpbWVzdGFtcGluZyUyMENBJTIwMjAyMC5j # cnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8B # Af8EBAMCB4AwZgYDVR0gBF8wXTBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcC # ARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRv # cnkuaHRtMAgGBmeBDAEEAjANBgkqhkiG9w0BAQwFAAOCAgEAQshE8CnDLtduJOHh # aG1DqAp8l4oLX+kclQ1f4Iy+92BXwV6DujiloDib+kKzT683EH8tJAutLONmAmuG # lFoBNOLaKHaNpRyfXYprF9r4GNUczKx8hiMZj0aEiVplHWb6w9qS2J6ml/ysjP+V # fz5bHujOBoURidTTvpHq0JsXdXE7n8HJtStccwgyhw21Bnt5C0dzATbCCi2gbObP # S5TaAmIvuda+Xh9q0JRy05YEJg4f3StO91Q43T5W0AGlqz+aFe6tDKkFVZshM+Kt # 1weISoB7YpxQcwJ5rMGxS+Ed8ixDQrEd4g8AOlgmRVE0zEEKKCEOiK2wctBfvj/h # wiTzEo+joJDl5jUBQi5ZjoOJdDgWaNU6D6AgQyJ4PI5CK6SYxN0xzpgreRgf9dvL # GRJQrOzoavweSQFmJTezIuR7cJp168p2j+EVdI9m4tZa9XmGOjdp3zHg+Dehai4f # 28/7CausPNUpr+mcdFhGQKJz6UkoIxz7ggVzzD2DlIKShT6ficLGDAI7ryo/Jpyz # U4bGVWrfjB/DB0IgsxHty0zm+gJ8/qvsbrtfg9R9dbkMnCjpkd53XOuhGPiMhrFn # kv0g2e5L1xVqV3Cv41gibmeTmxAAnMGnu7pRu/IZu1Zdg823HYm+/xE1hNPM+poV # onZjOZpg62zkBsO/JEfa82HJk0oxggdDMIIHPwIBATB4MGExCzAJBgNVBAYTAlVT # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jv # c29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwAhMzAAAAXcY5eE9A # fTP9AAAAAABdMA0GCWCGSAFlAwQCAQUAoIIEnDARBgsqhkiG9w0BCRACDzECBQAw # GgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNjEw # MTMyMzQ5NDJaMC8GCSqGSIb3DQEJBDEiBCAeZWbhK5r4p2fZdyCsSkGzTFgCBenh # rFvuKW+dOn9ivDCBuQYLKoZIhvcNAQkQAi8xgakwgaYwgaMwgaAEIC01ZEtv6fPu # QmKhZadGormGhQBDXm/cy+sXvdzEAkpdMHwwZaRjMGExCzAJBgNVBAYTAlVTMR4w # HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29m # dCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwAhMzAAAAXcY5eE9AfTP9 # AAAAAABdMIIDXgYLKoZIhvcNAQkQAhIxggNNMIIDSaGCA0UwggNBMIICKQIBATCC # AQmhgeGkgd4wgdsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw # DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x # JTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNVBAsT # Hm5TaGllbGQgVFNTIEVTTjo3QTAwLTA1RTAtRDk0NzE1MDMGA1UEAxMsTWljcm9z # b2Z0IFB1YmxpYyBSU0EgVGltZSBTdGFtcGluZyBBdXRob3JpdHmiIwoBATAHBgUr # DgMCGgMVAL2nurW1sYDPB2jAbA8RxJrMlpD1oGcwZaRjMGExCzAJBgNVBAYTAlVT # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jv # c29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwMA0GCSqGSIb3DQEB # CwUAAgUA7ni4mTAiGA8yMDI2MTAxMzE0MDMwNVoYDzIwMjYxMDE0MTQwMzA1WjB0 # MDoGCisGAQQBhFkKBAExLDAqMAoCBQDueLiZAgEAMAcCAQACAg3oMAcCAQACAhJH # MAoCBQDuegoZAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAI # AgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBAFyWZuFUYZ7E # 4aFu/PTMUtrXTvLSfWHchDErn/micM90OpeWBFTsjGxDJcDwNWsIWMmAAn+YowjE # +2PNb+uVwytOb3ALJlPrBh/aizKsMUjmKcg8PEQ+znIb/pQbp7kdqC0PWE1ltEv6 # LetYzFgRCp6vam8zzuAR4IDlNObZ20jFUra1sIve+aeGQh9CKu1HJ0Zp9cU/YIFj # nTMhBcGWxwuRQBPwS3wZ0W+9E0ZVjYxwnnuAfszmwEapszL31c+7exsWabK5CuLQ # UiTtoZ9Yi9pd70UwuZDeK1VaPsjnAENv54tjBh6RFcOFgquLMeQ4jkM2M6Ff397o # iR8xzUB9m28wDQYJKoZIhvcNAQEBBQAEggIANhxaqBLMQ1Tv3Za2LiabXAQ6OwUh # 2uFXhlKxi6dv0yaCa86BlN1hTxrfFpxr4e2ufAEA6uqjg3boEdQ5CnQbOlLlmoKZ # LtG09oYocPEWYLYg8tG7iFRt63lRXvPec5UG2WTl5Fz7S2Tjek9q/+SLnWEKcE6/ # Qe/vmyB3bz+tL8695oRGmWdYfwgWwj4NAnP5oVcjeOmKP1Yzyv5Sty2RP2+xJnIm # jKUbTHNYuihs7Bj/4efAlXCTltvp8fZEJ2SF49bysYPFV3ThQCzGL6hauf+NCGjL # V0YSNxLO5rMSbVYkelwm860umOyQKxIFC2eEP9cROMjMQVaMIc7shGK9sUkoHkXR # tOyPoZdBk53jaP/7jdJCEsiH6AM8gtf80k0EIERCP0BsqZg5jrjtexK2VSmCQ6p1 # q7l8frCwMukvlbBjv8Up7HGpIqHlY25YI0zk+9L/UAl9Bsx+jXLFjqfLBt+jmd9D # yC5HoCnQDAwzpPviePq7ZIEAT9Zs6egKSni/PU1MJNkV98g51xEfFcUTDYJNeHMi # +jTyOo7HJN2lkt2LLNdUehqhIZ3S0Pkdgf8nbICnfraKorYYxHyj1/G8oaJhFW+L # TCTCnBGLfJz2LC+su3C+JkUHnx4WgYgd+9tLubhnRxD4rN/YNZMOV/zFME7uNtH0 # c+LuUvWgQIAEHK0= # SIG # End signature block |