private/Test-MachineSatisfiesDependency.ps1
|
function Test-MachineSatisfiesDependency { [CmdletBinding()] [OutputType('System.Int32')] Param ( [ValidateNotNullOrEmpty()] [System.Xml.XmlElement]$Dependency, [Parameter( Mandatory = $true )] [string]$PackagePath, [int]$DebugIndent = 0, [switch]$FailInboxDrivers ) # 0 SUCCESS, Dependency is met # -1 FAILRE, Dependency is not met # -2 Unknown dependency kind - status uncertain switch ($Dependency.SchemaInfo.Name) { '_Bios' { Write-Debug "$('- ' * $DebugIndent)[ Got: $($CachedHardwareTable._Bios)]" foreach ($entry in $Dependency.Level) { if ($CachedHardwareTable._Bios -like "$entry*") { return 0 } } return -1 } '_Coreq' { $DependencyPackage = $AllPackagesDependenciesInfo[$Dependency.name] if ($DependencyPackage) { if ($DependencyPackage.IsInstalled) { Write-Debug "$('- ' * $DebugIndent)[ Got: $($Dependency.name) $($DependencyPackage.Version), Expected: $($Dependency.Version) ]" return (Test-VersionPattern -LenovoString $Dependency.Version -SystemString $DependencyPackage.Version) } else { Write-Debug "$('- ' * $DebugIndent)[ $($Dependency.name) is not installed yet, Expected: $($Dependency.Version) ]" } } else { Write-Debug "$('- ' * $DebugIndent)[ $($Dependency.name) is not in the repository, Expected: $($Dependency.Version) ]" } return -1 } '_CPUAddressWidth' { Write-Debug "$('- ' * $DebugIndent)[ Got: $($CachedHardwareTable._CPUAddressWidth), Expected: $($dependency.AddressWidth) ]" if ($CachedHardwareTable._CPUAddressWidth -like "$($Dependency.AddressWidth)*") { return 0 } else { return -1 } } '_Driver' { [array]$SupportedDriverNodes = 'HardwareID', 'Version', 'Date', 'File' [array]$DriverChildNodes = $Dependency.ChildNodes.SchemaInfo.Name if (-not (Compare-Array $DriverChildNodes -in $SupportedDriverNodes)) { Write-Debug "$('- ' * $DebugIndent)_Driver node contained unknown element - skipping checks" return -2 } if ($DriverChildNodes -contains 'HardwareID') { [System.Collections.Generic.List[object]]$DevicesMatchedExact = [System.Collections.Generic.List[object]]::new() [System.Collections.Generic.List[object]]$DevicesMatchedWildcard = [System.Collections.Generic.List[object]]::new() [System.Collections.Generic.List[object]]$DevicesToTest = [System.Collections.Generic.List[object]]::new() :NextDevice foreach ($DeviceInMachine in $CachedHardwareTable._PnPID) { [bool]$DeviceHwIdWildcardMatched = $false foreach ($HardwareInMachine in $DeviceInMachine.HardwareID) { # A _Driver node can have multiple 'HardwareID' child nodes, e.g. https://download.lenovo.com/pccbbs/mobiles/r1kwq15w_2_.xml foreach ($HardwareID in $Dependency.HardwareID.'#cdata-section') { # Matching with wildcards may have been a mistake, some HardwareIDs just contain a * (star). # Try exact equal matches first and fall back to wildcard only when needed. I want to see how often that happens. if ($HardwareInMachine -eq "$HardwareID") { Write-Debug "$('- ' * $DebugIndent)Matched device '$HardwareInMachine' with required '$HardwareID' (EXACT)" $DevicesMatchedExact.Add($DeviceInMachine) continue NextDevice } # Lenovo HardwareIDs can contain wildcards (*) so we have to compare with "-like" if ($HardwareInMachine -like "*$HardwareID*") { Write-Debug "$('- ' * $DebugIndent)Matched device '$HardwareInMachine' with required '$HardwareID' (WILDCARD)" $DeviceHwIdWildcardMatched = $true } } } # To preserve the old behavior whilst fully testing the new, do add devices that were only matched via wildcards if ($DeviceHwIdWildcardMatched) { Write-Debug "$('- ' * $DebugIndent)Adding device - HardwareIDs matched only when using wildcards" $DevicesMatchedWildcard.Add($DeviceInMachine) } } Write-Debug "$('- ' * $DebugIndent)Matched devices: $($DevicesMatchedExact.Count) exact, $($DevicesMatchedWildcard.Count) wildcard" $DevicesToTest = if ($DevicesMatchedExact) { $DevicesMatchedExact } else { $DevicesMatchedWildcard } if ($DevicesToTest.Count -ge 1) { $TestResults = [System.Collections.Generic.List[bool]]::new() foreach ($Device in $DevicesToTest) { Write-Debug "$('- ' * $DebugIndent)Testing $($Device.DeviceId)" # First, check if there is a driver installed for the device at all before proceeding (issue#24) if ($Device.Problem -eq 'CM_PROB_FAILED_INSTALL') { [string]$HexDeviceProblemStatus = '0x{0:X8}' -f (Get-PnpDeviceProperty -InputObject $Device -KeyName 'DEVPKEY_Device_ProblemStatus').Data Write-Debug "$('- ' * $DebugIndent)Device '$($Device.InstanceId)' does not have any driver (ProblemStatus: $HexDeviceProblemStatus)" return -1 } if ($FailInboxDrivers) { # This approach of identifying 'inbox' drivers seems to produce the most matching SeverityOverride results. # Some alternatives tested were DEVPKEY_Device_GenericDriverInstalled and Get-AuthenticodeSignature .IsOSBinary property. [bool]$DriverIsInbox = ( (Get-PnpDeviceProperty -InputObject $Device -KeyName 'DEVPKEY_Device_DriverProvider').Data -eq 'Microsoft' -and (Get-PnpDeviceProperty -InputObject $Device -KeyName 'DEVPKEY_Device_DriverInfPath').Data -notmatch '^oem\d+\.inf$' ) if ($DriverIsInbox) { Write-Debug "$('- ' * $DebugIndent)Failed because device is using an inbox driver" return -1 } } $icmParams = @{ 'InputObject' = $Device 'MethodName' = 'GetDeviceProperties' 'Arguments' = @{'devicePropertyKeys' = @('DEVPKEY_Device_DriverVersion')} 'Verbose' = $false 'ErrorAction' = 'SilentlyContinue' } $DriverVersionObject = Invoke-CimMethod @icmParams | Select-Object -ExpandProperty deviceProperties if (-not $DriverVersionObject) { # Fall back to the much slower Get-PnpDeviceProperty cmdlet in cases where GetDeviceProperties fails (e.g. disconnected "phantom" devices) $DriverVersionObject = Get-PnpDeviceProperty -InputObject $Device -KeyName 'DEVPKEY_Device_DriverVersion' } $DriverVersion = $DriverVersionObject.Data $icmParams = @{ 'InputObject' = $Device 'MethodName' = 'GetDeviceProperties' 'Arguments' = @{'devicePropertyKeys' = @('DEVPKEY_Device_DriverDate')} 'Verbose' = $false 'ErrorAction' = 'SilentlyContinue' } $DriverDateObject = Invoke-CimMethod @icmParams | Select-Object -ExpandProperty deviceProperties if (-not $DriverDateObject) { # Fall back to the much slower Get-PnpDeviceProperty cmdlet in cases where GetDeviceProperties fails (e.g. disconnected "phantom" devices) $DriverDateObject = Get-PnpDeviceProperty -InputObject $Device -KeyName 'DEVPKEY_Device_DriverDate' } $DriverDate = $DriverDateObject.Data # Documentation for this: https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifier-score--windows-vista-and-later- # To be clear, this is a 'pretty good / best effort' approach, but it can detect false positives or miss generic drivers. # AFAIK it is not possible to detect with 100% certainty that a driver is generic/inbox and even if - it's not always a problem. # So this information should only be used for informaing the user or as an aid in making non-critical decisions, # do not rely on this detection/boolean to be accurate! [UInt32]$DriverRank = (Get-PnpDeviceProperty -InputObject $Device -KeyName 'DEVPKEY_Device_DriverRank').Data [byte]$DriverMatchTypeScore = $DriverRank -shr 12 -band 0xF Write-Debug "$('- ' * $DebugIndent)Device '$($Device.Name)' DriverRank is 0x$('{0:X8}' -f $DriverRank)" if ($DriverMatchTypeScore -ge 2) { Write-Verbose "Device '$($Device.Name)' may currently be using a generic or inbox driver" } if ($DriverChildNodes -contains 'Date') { Write-Debug "$('- ' * $DebugIndent)Trying to match driver based on Date" $LenovoDate = [DateTime]::new(0) [bool]$LenovoDateIsValid = [DateTime]::TryParseExact( $Dependency.Date, 'yyyy-MM-dd', [CultureInfo]::InvariantCulture, [System.Globalization.DateTimeStyles]::AdjustToUniversal -bor [System.Globalization.DateTimeStyles]::AssumeUniversal, [ref]$LenovoDate ) if ($LenovoDateIsValid) { if ($DriverDate) { # WMI and therefore CIM stores datetime values in a DMTF string format. # When these are converted to DateTime objects, they are always converted to the local timezone, aka an offset # is "artificially" added. For driver dates, this can lead to GitHub#33 where the offset is enough to change the date, # which leads to false driver results. We have to remove the offset by converting the DateTime of Kind 'Local' back to UTC. # See GitHub#33 and https://docs.microsoft.com/en-us/dotnet/api/system.management.managementdatetimeconverter.todatetime?view=netframework-4.8#remarks $DriverDate = $DriverDate.ToUniversalTime().Date Write-Debug "$('- ' * $DebugIndent)[Got: $DriverDate, Expected: $LenovoDate]" if ($DriverDate -ge $LenovoDate) { Write-Debug "$('- ' * $DebugIndent)Passed DriverDate test" $TestResults.Add($true) } else { Write-Debug "$('- ' * $DebugIndent)Failed DriverDate test" $TestResults.Add($false) } } else { Write-Verbose "Device '$($Device.InstanceId)' does not report its driver date" } } else { Write-Verbose "Got unsupported date format from Lenovo: '$($Dependency.Date)' (expected yyyy-MM-dd)" } } if ($DriverChildNodes -contains 'Version') { Write-Debug "$('- ' * $DebugIndent)Trying to match driver based on Version" # Not all drivers tell us their versions via the OS API. I think later I can try to parse the INIs as an alternative, but it would get tricky if ($DriverVersion) { Write-Debug "$('- ' * $DebugIndent)[Got: $DriverVersion, Expected: $($Dependency.Version)]" if ((Test-VersionPattern -LenovoString $Dependency.Version -SystemString $DriverVersion) -eq 0) { Write-Debug "$('- ' * $DebugIndent)Passed DriverVersion test" $TestResults.Add($true) } else { Write-Debug "$('- ' * $DebugIndent)Failed DriverVersion test" $TestResults.Add($false) } } else { Write-Verbose "Device '$($Device.InstanceId)' does not report its driver version" } } } # If all HardwareID-tests were successful, return SUCCESS #Changed to take account of the Thinkpad monitor file that was appearing as already installed but was not. if (-not ($TestResults -contains $false)) { return 0 #SUCCESS } #if ($TestResults -contains $true) { #return 0 # } # If one or more HardwareID-tests were completed but failed (e.g. Date) continue in case there are further tests like FileVersion } } if (Compare-Array @('File', 'Version') -in $DriverChildNodes) { # This may not be 100% yet as Lenovo sometimes uses some non-system environment variables in their file paths [string]$Path = Resolve-CmdVariable -String $Dependency.File -ExtraVariables @{'WINDOWS' = $env:SystemRoot} if (Test-Path -LiteralPath $Path -PathType Leaf) { $filProductVersion = (Get-Item -LiteralPath $Path).VersionInfo.ProductVersion $FileVersionCompare = Test-VersionPattern -LenovoString $Dependency.Version -SystemString $filProductVersion if ($FileVersionCompare -eq -2) { Write-Debug "$('- ' * $DebugIndent)Got unsupported with ProductVersion, trying comparison with FileVersion" $filFileVersion = (Get-Item -LiteralPath $Path).VersionInfo.FileVersion return (Test-VersionPattern -LenovoString $Dependency.Version -SystemString $filFileVersion) } else { return $FileVersionCompare } } else { Write-Debug "$('- ' * $DebugIndent)The file '$Path' was not found." return -1 } } # If we have not hit a success condition before the end, return with failure return -1 } '_EmbeddedControllerVersion' { if ($CachedHardwareTable._EmbeddedControllerVersion) { if ($CachedHardwareTable._EmbeddedControllerVersion -eq '255.255') { Write-Warning "This computers EC firmware is not upgradable but is being used to evaluate a package" } return (Test-VersionPattern -LenovoString $Dependency.Version -SystemString $CachedHardwareTable._EmbeddedControllerVersion) } return -1 } '_ExternalDetection' { $externalDetection = Invoke-PackageCommand -Command $Dependency.'#text' -Path $PackagePath -RuntimeLimit $script:LnvUpdateConfiguration.MaxExternalDetectionRuntime if ($externalDetection.Err) { Write-Debug "$('- ' * $DebugIndent)[ External process did not run properly: $($externalDetection.Err) ]" return -1 } else { Write-Debug "$('- ' * $DebugIndent)[ Got ExitCode: $($externalDetection.Info.ExitCode), Expected: $($Dependency.rc) ]" if ($externalDetection.Info.ExitCode -in ($Dependency.rc -split ',')) { return 0 } else { return -1 } } } '_FileExists' { # This may not be 100% yet as Lenovo sometimes uses some non-system environment variables in their file paths [string]$Path = Resolve-CmdVariable -String $Dependency.'#text' -ExtraVariables @{'WINDOWS' = $env:SystemRoot} if (Test-Path -LiteralPath $Path -PathType Leaf) { return 0 } else { return -1 } } '_FileVersion' { # This may not be 100% yet as Lenovo sometimes uses some non-system environment variables in their file paths [string]$Path = Resolve-CmdVariable -String $Dependency.File -ExtraVariables @{'WINDOWS' = $env:SystemRoot} if (Test-Path -LiteralPath $Path -PathType Leaf) { $filProductVersion = (Get-Item -LiteralPath $Path).VersionInfo.ProductVersion $FileVersionCompare = Test-VersionPattern -LenovoString $Dependency.Version -SystemString $filProductVersion if ($FileVersionCompare -eq -2) { Write-Debug "$('- ' * $DebugIndent)Got unsupported with ProductVersion, trying comparison with FileVersion" $filFileVersion = (Get-Item -LiteralPath $Path).VersionInfo.FileVersion return (Test-VersionPattern -LenovoString $Dependency.Version -SystemString $filFileVersion) } else { return $FileVersionCompare } } else { Write-Debug "$('- ' * $DebugIndent)The file '$Path' was not found." return -1 } } '_Firmware' { # https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/query-version-and-status-ps1-script?view=windows-11 # Dependency.Version can also have a hex2dec attribute (True/False) and depending on whether it exists PowerShell deserializes # the XML differently (.Version can be string or XmlElement). Using SelectNode is consistent. [string]$LenovoVersion = $Dependency.SelectSingleNode('Version').'#text' [bool]$LenovoVersionIsHex = $Dependency.SelectSingleNode('Version').GetAttribute('hex2dec') -eq 'True' foreach ($PnpDevice in $CachedHardwareTable._PnPID) { foreach ($entry in $Dependency.HardwareIDs) { # Only exact HardwareID matches will be found (no wildcards) if ($entry.'#cdata-section' -in $PnpDevice.HardwareID) { [string]$PnpDeviceFirmwareRev = $PnpDevice.HardwareID[0].Substring($PnpDevice.HardwareID[0].IndexOf('&REV_') + 5) Write-Debug "$('- ' * $DebugIndent)[ Got: ${PnpDeviceFirmwareRev}, Expected: ${LenovoVersion} (IsHex: ${LenovoVersionIsHex}) ]" if ($LenovoVersionIsHex) { # If hex2dec is explicitly set to True only interpret the LenovoVersion as hexadecimal. # This is important because any decimal-looking number can also be interpreted in hex but has a very different value there. return (Test-VersionPattern -LenovoString $LenovoVersion -SystemString $PnpDeviceFirmwareRev -SystemStringFormat Hex -LenovoStringFormat Hex) } else { # Some packages, like https://download.lenovo.com/pccbbs/mobiles/n2wrg16w_v2_2_.xml, use hexadecimal versions but set hex2dec=False. # We leave LenovoStringFormat set to the default 'Auto' to try and support that case as best as possible with fallback logic return (Test-VersionPattern -LenovoString $LenovoVersion -SystemString $PnpDeviceFirmwareRev -SystemStringFormat Hex) } } } } return -1 # HardwareID not in system - fail } '_OS' { foreach ($entry in $Dependency.OS) { if ("$entry" -like "WIN$($CachedHardwareTable._OS)*") { return 0 } } return -1 } '_OSLang' { if ($Dependency.Lang -eq [CultureInfo]::CurrentUICulture.ThreeLetterWindowsLanguageName) { return 0 } else { return -1 } } '_PnPID' { foreach ($HardwareID in $CachedHardwareTable._PnPID.HardwareID) { if ($HardwareID -like "*$($Dependency.'#cdata-section')*") { return 0 } } return -1 } '_RegistryKey' { if ($Dependency.Key) { if (Test-Path -LiteralPath ('Microsoft.PowerShell.Core\Registry::{0}' -f $Dependency.Key) -PathType Container) { return 0 } } return -1 } '_RegistryKeyValue' { if ($Dependency.Version -and $Dependency.KeyValue -or $Dependency.Version -and $Dependency.type -ne 'REG_SZ') { return -2 } if (Test-Path -LiteralPath ('Microsoft.PowerShell.Core\Registry::{0}' -f $Dependency.Key) -PathType Container) { try { $regValue = Get-ItemPropertyValue -LiteralPath ('Microsoft.PowerShell.Core\Registry::{0}' -f $Dependency.Key) -Name $Dependency.KeyName -ErrorAction Stop } catch { return -1 } [string]$DependencyVersion = if ($Dependency.KeyValue) { $Dependency.KeyValue } elseif ($Dependency.Version) { $Dependency.Version } else { Write-Verbose "Could not get LenovoString from _RegistryKeyValue dependency node" return -2 } return (Test-VersionPattern -LenovoString $DependencyVersion -SystemString $regValue) } else { return -1 } } '_WindowsBuildVersion' { # A _WindowsBuildVersion test can specify multiple Build Versions, see issue #42 [array]$TestResults = foreach ($DependencyVersion in $Dependency.Version) { Write-Debug "$('- ' * $DebugIndent)[ Got: $($CachedHardwareTable._WindowsBuildVersion), Expected: $DependencyVersion ]" Test-VersionPattern -LenovoString $DependencyVersion -SystemString $CachedHardwareTable._WindowsBuildVersion } # If we had a clear success match, return success overall. # If we had no clear successes, but an unsupported case, return # -2 for unsupported so the calling function can evaluate that. # Otherwise return -1 to indicate failure (no matches). if ($TestResults -contains 0) { return 0 } elseif ($TestResults -contains -2) { return -2 } else { return -1 } } default { Write-Verbose "Unsupported dependency encountered: $_" return -2 } } return -2 } # SIG # Begin signature block # MIItugYJKoZIhvcNAQcCoIItqzCCLacCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUhNRsVR4vf5BCy1o52B6JeyYR # AACggibcMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIFkDCCA3ig # AwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG # EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl # cnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMw # ODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UE # ChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYD # VQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEppz1Y # q3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lX # FllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxe # TsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbu # yntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I # 9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/CNdaSaTC5qmg # Z92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtmmnTK3kse # 5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKy # Ebe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwh # HbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/ # Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwID # AQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4E # FgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQADggIBALth2X2p # bL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY # ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdN # Oj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4 # i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJ # EVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9NcCOGDErcgdLM # MpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N0XWs0Mr7QbhD # parTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb/UdK # Dd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP # 0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLS # oCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9T # dSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+MIIGsDCCBJigAwIBAgIQCK1AsmDS # nEyfXs2pvZOu2TANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UE # ChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYD # VQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjEwNDI5MDAwMDAwWhcN # MzYwNDI4MjM1OTU5WjBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs # IEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5n # IFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A # MIICCgKCAgEA1bQvQtAorXi3XdU5WRuxiEL1M4zrPYGXcMW7xIUmMJ+kjmjYXPXr # NCQH4UtP03hD9BfXHtr50tVnGlJPDqFX/IiZwZHMgQM+TXAkZLON4gh9NH1MgFcS # a0OamfLFOx/y78tHWhOmTLMBICXzENOLsvsI8IrgnQnAZaf6mIBJNYc9URnokCF4 # RS6hnyzhGMIazMXuk0lwQjKP+8bqHPNlaJGiTUyCEUhSaN4QvRRXXegYE2XFf7JP # hSxIpFaENdb5LpyqABXRN/4aBpTCfMjqGzLmysL0p6MDDnSlrzm2q2AS4+jWufcx # 4dyt5Big2MEjR0ezoQ9uo6ttmAaDG7dqZy3SvUQakhCBj7A7CdfHmzJawv9qYFSL # ScGT7eG0XOBv6yb5jNWy+TgQ5urOkfW+0/tvk2E0XLyTRSiDNipmKF+wc86LJiUG # soPUXPYVGUztYuBeM/Lo6OwKp7ADK5GyNnm+960IHnWmZcy740hQ83eRGv7bUKJG # yGFYmPV8AhY8gyitOYbs1LcNU9D4R+Z1MI3sMJN2FKZbS110YU0/EpF23r9Yy3IQ # KUHw1cVtJnZoEUETWJrcJisB9IlNWdt4z4FKPkBHX8mBUHOFECMhWWCKZFTBzCEa # 6DgZfGYczXg4RTCZT/9jT0y7qg0IU0F8WD1Hs/q27IwyCQLMbDwMVhECAwEAAaOC # AVkwggFVMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFGg34Ou2O/hfEYb7 # /mF7CIhl9E5CMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1Ud # DwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzB3BggrBgEFBQcBAQRrMGkw # JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcw # AoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJv # b3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQu # Y29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwHAYDVR0gBBUwEzAHBgVngQwB # AzAIBgZngQwBBAEwDQYJKoZIhvcNAQEMBQADggIBADojRD2NCHbuj7w6mdNW4AIa # pfhINPMstuZ0ZveUcrEAyq9sMCcTEp6QRJ9L/Z6jfCbVN7w6XUhtldU/SfQnuxaB # RVD9nL22heB2fjdxyyL3WqqQz/WTauPrINHVUHmImoqKwba9oUgYftzYgBoRGRjN # YZmBVvbJ43bnxOQbX0P4PpT/djk9ntSZz0rdKOtfJqGVWEjVGv7XJz/9kNF2ht0c # sGBc8w2o7uCJob054ThO2m67Np375SFTWsPK6Wrxoj7bQ7gzyE84FJKZ9d3OVG3Z # XQIUH0AzfAPilbLCIXVzUstG2MQ0HKKlS43Nb3Y3LIU/Gs4m6Ri+kAewQ3+ViCCC # cPDMyu/9KTVcH4k4Vfc3iosJocsL6TEa/y4ZXDlx4b6cpwoG1iZnt5LmTl/eeqxJ # zy6kdJKt2zyknIYf48FWGysj/4+16oh7cGvmoLr9Oj9FpsToFpFSi0HASIRLlk2r # REDjjfAVKM7t8RhWByovEMQMCGQ8M4+uKIw8y4+ICw2/O/TOHnuO77Xry7fwdxPm # 5yg/rBKupS8ibEH5glwVZsxsDsrFhsP2JjMMB0ug0wcCampAMEhLNKhRILutG4UI # 4lkNbcoFUCvqShyepf2gpx8GdOfy1lKQ/a+FSCH5Vzu0nAPthkX0tGFuv2jiJmCG # 6sivqf6UHedjGzqGVnhOMIIGtDCCBJygAwIBAgIQDcesVwX/IZkuQEMiDDpJhjAN # BgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQg # SW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2Vy # dCBUcnVzdGVkIFJvb3QgRzQwHhcNMjUwNTA3MDAwMDAwWhcNMzgwMTE0MjM1OTU5 # WjBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNV # BAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hB # MjU2IDIwMjUgQ0ExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtHgx # 0wqYQXK+PEbAHKx126NGaHS0URedTa2NDZS1mZaDLFTtQ2oRjzUXMmxCqvkbsDpz # 4aH+qbxeLho8I6jY3xL1IusLopuW2qftJYJaDNs1+JH7Z+QdSKWM06qchUP+AbdJ # gMQB3h2DZ0Mal5kYp77jYMVQXSZH++0trj6Ao+xh/AS7sQRuQL37QXbDhAktVJMQ # bzIBHYJBYgzWIjk8eDrYhXDEpKk7RdoX0M980EpLtlrNyHw0Xm+nt5pnYJU3Gmq6 # bNMI1I7Gb5IBZK4ivbVCiZv7PNBYqHEpNVWC2ZQ8BbfnFRQVESYOszFI2Wv82wnJ # RfN20VRS3hpLgIR4hjzL0hpoYGk81coWJ+KdPvMvaB0WkE/2qHxJ0ucS638ZxqU1 # 4lDnki7CcoKCz6eum5A19WZQHkqUJfdkDjHkccpL6uoG8pbF0LJAQQZxst7VvwDD # jAmSFTUms+wV/FbWBqi7fTJnjq3hj0XbQcd8hjj/q8d6ylgxCZSKi17yVp2NL+cn # T6Toy+rN+nM8M7LnLqCrO2JP3oW//1sfuZDKiDEb1AQ8es9Xr/u6bDTnYCTKIsDq # 1BtmXUqEG1NqzJKS4kOmxkYp2WyODi7vQTCBZtVFJfVZ3j7OgWmnhFr4yUozZtqg # PrHRVHhGNKlYzyjlroPxul+bgIspzOwbtmsgY1MCAwEAAaOCAV0wggFZMBIGA1Ud # EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFO9vU0rp5AZ8esrikFb2L9RJ7MtOMB8G # A1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjAT # BgNVHSUEDDAKBggrBgEFBQcDCDB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGG # GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2Nh # Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYD # VR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0 # VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9 # bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQAXzvsWgBz+Bz0RdnEwvb4LyLU0pn/N0IfF # iBowf0/Dm1wGc/Do7oVMY2mhXZXjDNJQa8j00DNqhCT3t+s8G0iP5kvN2n7Jd2E4 # /iEIUBO41P5F448rSYJ59Ib61eoalhnd6ywFLerycvZTAz40y8S4F3/a+Z1jEMK/ # DMm/axFSgoR8n6c3nuZB9BfBwAQYK9FHaoq2e26MHvVY9gCDA/JYsq7pGdogP8HR # trYfctSLANEBfHU16r3J05qX3kId+ZOczgj5kjatVB+NdADVZKON/gnZruMvNYY2 # o1f4MXRJDMdTSlOLh0HCn2cQLwQCqjFbqrXuvTPSegOOzr4EWj7PtspIHBldNE2K # 9i697cvaiIo2p61Ed2p8xMJb82Yosn0z4y25xUbI7GIN/TpVfHIqQ6Ku/qjTY6hc # 3hsXMrS+U0yy+GWqAXam4ToWd2UQ1KYT70kZjE4YtL8Pbzg0c1ugMZyZZd/BdHLi # Ru7hAWE6bTEm4XYRkA6Tl4KSFLFk43esaUeqGkH/wyW4N7OigizwJWeukcyIPbAv # jSabnf7+Pu0VrFgoiovRDiyx3zEdmcif/sYQsfch28bZeUz2rtY/9TCA6TD8dC3J # E3rYkrhLULy7Dc90G6e8BlqmyIjlgp2+VqsS9/wQD7yFylIz0scmbKvFoW2jNrbM # 1pD2T7m3XDCCBu0wggTVoAMCAQICEAhP3DNPfkVO28MPj/mSGDUwDQYJKoZIhvcN # AQELBQAwaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEw # PwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IFRpbWVTdGFtcGluZyBSU0E0MDk2 # IFNIQTI1NiAyMDI1IENBMTAeFw0yNjA4MDUwMDAwMDBaFw0zNzExMDQyMzU5NTla # MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UE # AxMyRGlnaUNlcnQgU0hBMjU2IFJTQTQwOTYgVGltZXN0YW1wIFJlc3BvbmRlciAy # MDI2IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2e6byyf7NSvjU # m0xls/04xjD4fAkOkbnGQi7+Wpx81iYxfzViaxSIctuH3KSl5YEYpMuFgGsA31N2 # D9ATMbfZdw5uaAhuWevQKhDdZIB4NnqcfpfpWQXJiQnDdAElETC+bhSEvNLGbA8D # twUpFMQ4yyYQSPqomT92osQAv6hBi47ATZS6JfVWe6XxhF4jJZ3iSAuf2Cros1cz # RSmWRHqMv9AfGZvp8ygYElhudpQjtcPpwoOl6QrZJUyV3iINvN4cO05prGV0fkjG # 426xDr2d3z9lcSIHkdvGPdGUrXdxfVbgOUVcp2/8ISEzwKPW++Wa+E2ujI91EZtu # kGWDJ/xZ27k3oHKEXBRGfRTqjOU+jE3ba/5++JSE/7oNHnjs5mekExYN96LV/mxU # bCKJb8pBNY4r3uD7hEmk/M81XhVgwDA7aMzYC3LZBg9WY5BMmbSay5ecmtJuXaB/ # 0nKWmQmVZeqTVDgsmzHP5MQuhAJkiWNuC9MmCg9TZHXbJ2/yLVSov9p16UDTLtT0 # +aa1vN71fHeu1qMLlLNB3WOB/ADCxr3S/1hxI92Z6jKgEED/btwIvbfuXkNNhg8M # tDg43c4tMZae9FvqMOt/9PvmAxF9TNIsIFB8G6yb36ZJZGUL8N/pL971DyLXcK6H # M5PYnH5X+eVtczhCgHCVQCF6XDAlPQIDAQABo4IBlTCCAZEwDAYDVR0TAQH/BAIw # ADAdBgNVHQ4EFgQUFMljijAu1Er7bpTz5uNAfvXszeIwHwYDVR0jBBgwFoAU729T # SunkBnx6yuKQVvYv1Ensy04wDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoG # CCsGAQUFBwMIMIGVBggrBgEFBQcBAQSBiDCBhTAkBggrBgEFBQcwAYYYaHR0cDov # L29jc3AuZGlnaWNlcnQuY29tMF0GCCsGAQUFBzAChlFodHRwOi8vY2FjZXJ0cy5k # aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2 # U0hBMjU2MjAyNUNBMS5jcnQwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL2NybDMu # ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0VGltZVN0YW1waW5nUlNBNDA5 # NlNIQTI1NjIwMjVDQTEuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG # /WwHATANBgkqhkiG9w0BAQsFAAOCAgEAjcU6YR6dUgrfmawJgH59KECxa9Ji8sEi # 2g10CBDaMiqsaxWyW5cwlT/6ZF5sFznazqVsoC85U9dqLOYqQwst+UQQoNlDHgKR # La3xoc+OReFreFhnTXSG0Vrd2E2CZqUfm+5a+He1MJ/h+tNLuA+0Zzhn/Fo+FDYA # HWZHx4R79ZsfRFYe9UiXpXBDf6DkUo183Y38NYmR/XfDYf7YZ+oR9t3flbDwK+hg # GMs0gNNp1w9Z2CyOyI5or/sSwomAuNQ0hWC9xoU4stD8aWsD7RkcmgVRs6vlIk3z # PKQ+ylcheWkMlj+CoVRlFE55pv0ZWCaFt04lwP/rdGHE9qEVQZtyRE42ox7oNgC/ # r+Y4bSlZ3dw9K2x1xLtu6PkPKeLBFjzKigwfqm3Hm+k/+lnME8F5kPZTgiy2HLEH # klpryqs6QHnPXrRNeIzkAMyylnRN8P0wmirS0WkU+ywpEWFZ4QNg+9xS43tTuW9x # 0eXh7NDc1P/sV+zWxHXKH8tFt1ncHdVzqrZaYPyYMLSn2TOXajveJW1L3joiQSPs # WRGxkbDDW15jERFE4LvjnGu2O9zD1nLJSMdlYZEikl4w2w+q4IN/R+TIe0H4ngCI # 1moJCTbevGH4punIxM1Uoi0nmX3ZK+XbRT01uowE5ViXWHng0RgsmrX/EdYUo80r # 3TfMlkD0/YMwggdWMIIFPqADAgECAhAFfARoFtaNDha0m0G6FxiVMA0GCSqGSIb3 # DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFB # MD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5 # NiBTSEEzODQgMjAyMSBDQTEwHhcNMjYwNTE0MDAwMDAwWhcNMjcwNjE3MjM1OTU5 # WjBeMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExFDASBgNV # BAcTC01vcnJpc3ZpbGxlMQ8wDQYDVQQKEwZMZW5vdm8xDzANBgNVBAMTBkxlbm92 # bzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALVacqHydjmqo6bF2tHw # cETPkOZLgPv1tJeIerpLcfmxLoX40GsUiY5l96B13bcfKjKBJQvHsj5D08RfGnif # K+sGsAX8xCgaYNLxq0COKn51GgLLMNgzlE4rR/8mUMuWK2fKXs24dmn7teE2+e+2 # dz/GfHXgrAIPvIr4PN+dZAFeoj6/wfpLLHZXtQLxKVmtDFc7gQZkM6Z8o0HrH2eX # 2MVNQwbZZWvSQhqRN66/LMcXxbLP8SAb6nKRCExflbI5i+MpEq+xOdiJxkP5dC5s # rQ31JGLDdhbuAcUJEdXATzgP1pT9is3uWZm3fro71Kvfa0XLwBZWR2ut8sQ6KUhd # 0Nsmd5c0f2PiD2uTd9mDWHQ34bu9mDunZaeWZrIlUP9MJ8TMM82ao/4tjFNK5m3T # hZUbCGwoepenXq8yjbKMKqHHvcoJY0SmkAIlUzWoRBbRC+uN0TwcR048sZDPo+ZC # gdONLPrjnsIU+NxuhfDMnj4UYbkRbtvnJ+U0O4Eu+ajRS87Li+jN2jHrABvAUXtP # J7DkkxTTfaspzlfxueoqVKcGLnu4PUAthKg3g4hleGgeo7s+krEDAzyvdBnY+b8U # dRH/BCxDr7G5ys/bCMPEzcUFT5LrrVBHO6N2U65iYkamzEo4okrrCNFDJPZC1G/p # NleTeiIadSPTT0tJGPK+nDo1AgMBAAGjggIDMIIB/zAfBgNVHSMEGDAWgBRoN+Dr # tjv4XxGG+/5hewiIZfROQjAdBgNVHQ4EFgQU7R8eucYUNncCkcWYWfCltSt/mxYw # PgYDVR0gBDcwNTAzBgZngQwBBAEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5k # aWdpY2VydC5jb20vQ1BTMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEF # BQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRwOi8vY3JsMy5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIx # Q0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0 # VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcmwwgZQG # CCsGAQUFBwEBBIGHMIGEMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy # dC5jb20wXAYIKwYBBQUHMAKGUGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEu # Y3J0MAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggIBAC0PiOF1B8Qdp2pcfb3P # 6MuzaeTUw77bfMSCcnwY8xFtkyRRp9H6X4ZaSTdAQge3d6NG7OcHnGQ3FKraZqT3 # ugjNEXvH1MXr8SNgFb7t7TyKDK0RmRK9idsycLJfRsmbj0FSTL12jqrzyHrQqkTq # KaDqYfIVan7VxP2On8gq3/OT368z1YJbRgfu/rNpXoYpXTKSfxaIXNE7rEiUwu+T # vi8wgfLqC/a7ujC8vbYRWgaHHsz3bjFVN/h1p78adds2GdxPzYFoS12+JKq2cKGe # Ma5Hbr2YQfHsbpQlzZglB3mGCci+uhN5YGaHleo3Ohd0BHci32RFOA1xdD8fS9TD # pGRMGLKF9z5WTmiGZVR4x54Qwtf4clbA5V0P9d4ppmLZJKdeaHd/JKONVJ9nYV1H # NA52CgvgRWpUc+jxnPL5A3J9qIvUXp98ZQifEyHBFX2VqWTdu9MldzklRo/eAT1k # MUVheRAcd32yLDiFvn7lp2nasJs8Hh+6bUxfHKbKBrNrw7CmcTDzFK119BkykWS0 # vL7xsbCEbavLIhW/ZqEjWA9k/v2FS2wbBQ9YOC8F3magnslxWlZWsym3Dxdm0Hr1 # WKHbnFcBscMiBQ+fhLDAqIG8tPPnNhc7QhOOlxQlbfEDh8QmQbUo2H9hJJEGiHJS # VwuAKbcWembFyAgLV02ASxS7MYIGSDCCBkQCAQEwfTBpMQswCQYDVQQGEwJVUzEX # MBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0 # ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAFfARo # FtaNDha0m0G6FxiVMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgACh # AoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAM # BgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBTAiSt8/dgFQ3w1vNgrhKZpBXJS # qzANBgkqhkiG9w0BAQEFAASCAgBqx+Nk7ZU3aND2140UOfajQS/aMYvTdahV8Qhz # ZwbcW1EBRj2IK+qfnLVYVltFx/dvLfCt3xyXIascAVgxIiEZ5J9O/hL1xXUHYlyx # 5aiMov44lbM3v3gcSSQzTSH3v+rZPg6l7RrmpkeS7XREaRidrhby2Lu+LdiHhOk3 # 3RmDyUJ7fDeEWEaXzp3GLvme7RhOVhWJZJt2Iy45geGKADzzsDmtD+Ii2U5KTK92 # 6yZbQtYChxBxlNVG8CNHZBMzGmjX94Rqof4dhFrAsR2UzX5HZ6xJ12JDysDpcT5n # 5NKIRCucJEqtN2eMckcThvFY3vkD6oR1B6W4Ac+0phW1j4dz4SBwCwMBG0dLK7/C # FMveDBdbMokHSr3w3B/sr3+LeYeDFRDYJf8brEKYoMiNIfIRsiOk1mtskx/Aw1O1 # 4P58g3+4WMIuTzIWxsRvf8sKFjs0XZccBEL3pC9FUq6aKyrJHPRtYdxQGUyB9dUo # tMejZzTpPJZ5qYyWBWqdp7wXO+gI0AV9lZcMUoJsLiCm7D7Tgm59BWg0VmUoTQts # OtFM6J4hKPAeTPKhnV7hHOENjEoT0kejDCdsZsvuY1zb91+IGWbpElEq+DwYZtH1 # HsqwfUPfBrV2AkOY2w0ZmRTTu7kCIlS7RjZggidjexgNVnlXABMk8ec5sv/AVu+W # dihtU6GCAyYwggMiBgkqhkiG9w0BCQYxggMTMIIDDwIBATB9MGkxCzAJBgNVBAYT # AlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQg # VHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTEC # EAhP3DNPfkVO28MPj/mSGDUwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMx # CwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNjA5MjQxODEzMzlaMC8GCSqG # SIb3DQEJBDEiBCAidHXuyx7fLdUSk0Pu7HAFaSuusXewm5JrrF/71nPbKDANBgkq # hkiG9w0BAQEFAASCAgBWFGY+/xH/ko/vo69ZH6U6rHxU/8RBFNmR0WJnSPZzaXR9 # xMTz/CQc+jEuvH42uNwGfX8a9hETFjZhHhHdXYgpqtiE5HmMjs0uEVdMrJNz+9qz # Egp8bRPrGarM8ldgSQGjRillDTh7Y6U/HhkVvZUWqtuYeSjJAWcPXqgpgEQq6KJ7 # Ez2RNjhrf9ce6wgHZgzFSOGdFSJbln5R4KhvDf2EtbKvWXW38TOyQoQdm0g9hOBm # U9plzWSJYWZdRi5Azpb5ahxelYvKwR3SrgzdDMgUnHfjxhwhmUelUXPmvPih816W # EH9O93yRJ9At+2zoGLocI//pnKkNb0D27zjQRQO1AfEHTDKuw4ZxSOkUX7pAajuo # eFIZ7jTBOmaQyBEcjqHlQNC0WvXvgdFJl5XaIRfsDAZhULapsxwzG1KpPkE6UpKN # WdJ2/qKSw9c9625mdlYuzADtpLtPfscjZu2ngz2oWWCVXrmKmyOf/xhybD5AaCyT # f1JsTMVGRVtuX9dOI7izjrrDWQEbLZ4ZdftftMjnP2bR6JQGH5Kn2gFWKKJciDLJ # WJy2B1tGhbWxGiAuuQeg6DRSdnly44R2MyOZtdJk76x715zep4rKQi7hopHEOXfY # LB1fpz5idIQJD8jBI1yZbnKkQJ450IBy7zjxvvi3Hu2i+OBw6hm3GLpWsETpSg== # SIG # End signature block |