Obs/bin/ObsDep/content/Powershell/Roles/Common/Servicing/Scripts/Install-Update.psm1
<###################################################
# # # Copyright (c) Microsoft. All rights reserved. # # # ##################################################> # TODO: Use Common functions for session re-use # TODO: Clean up trace execution to full sentences. # FUTURE: Implement MSPs - postponed # FUTURE: Allow computer arrays rather than just one at a time # FUTURE: Use other mechanisms in Test-UpdateRebootRequested similar to MSFT_xPendingReboot from DSC $Script:UpdateRebootRequestedPath = Join-Path $env:SystemDrive UpdateRebootRequest.xml <# .Synopsis Updates a running computer. .Description Runs PowerShell scripts and KB .MSUs from the source path, without rebooting it. Requires CredSSP enabled from this computer to each of the targets. Does not reboot targets, caller can use Test-UpdateRebootRequired to determine status and reboot it if necessary. It is assumed that additional orchestration with existing roles is necessary, so it is not safe to do this "all in one" similar to Cluster Aware Updating. For scripts: Scripts will be invoked directly from the source location, allowing the script to know and reference additional materials relative to the script location. Default execution policy of the computer will be respected unless BypassExecutionPolicy is set. This allows the source directory to be remote to the computer, yet not require signing for test scenarios. .Link Test-UpdateRebootRequested #> function Install-Update { [CmdletBinding()] Param ( # Computer name to update [Parameter(Mandatory=$true)] [string] $ComputerName, # Explicit Credential for CredSSP [Parameter(Mandatory=$true)] [PSCredential] [System.Management.Automation.Credential()] $Credential, # Source for updates [Parameter(Mandatory=$true)] [string] $SourcePath, # Optional Scratch directory for update installation [string] $ScratchDirectory = $null, # Bypass default execution policy [switch] $BypassExecutionPolicy ) $ErrorActionPreference = "Stop" Install-UpdateScript -ComputerName $ComputerName -Credential $Credential -SourcePath (Join-Path $SourcePath "Script") -BypassExecutionPolicy:$BypassExecutionPolicy Install-UpdateKB -ComputerName $ComputerName -Credential $Credential -SourcePath $SourcePath -ScratchDirectory $ScratchDirectory } <# .Synopsis Indicates whether a computer needs a reboot to complete updating .Description Timestamp in file indicates when reboot was last requested, Test-UpdateRebootRequested will compare this timestamp to the actual time of last reboot. This function does not check other side effect locations of other software install or update processes. Update scripts, in particular, may need a reboot without marking the other locations so this mechanism provides a definitive marking. Future implementations may check the other locations, such as those checked by the DSC resource MSFT_xPendingReboot. .Link Install-Update .Link Set-UpdateRebootRequested #> function Test-UpdateRebootRequested { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [string] $ComputerName, [Parameter(Mandatory=$true)] [PSCredential] [System.Management.Automation.Credential()] $Credential ) $ErrorActionPreference = "Stop" $result = Invoke-Command -ComputerName $ComputerName -Credential $Credential -ScriptBlock { if (!(Test-Path $using:UpdateRebootRequestedPath)) { return $false } $request = [DateTime]::MaxValue try { # incoming time is in UTC ticks [DateTime] $request = Import-Clixml -Path $using:UpdateRebootRequestedPath } catch { Write-Warning "Invalid incoming UpdateRebootRequestedPath time, assuming reboot required" } $os = Get-CimInstance -Class Win32_OperatingSystem [DateTime] $lastBoot = $os.LastBootUpTime.ToUniversalTime() if ($lastBoot -lt $request) { return $true } else { Remove-Item -Path $using:UpdateRebootRequestedPath return $false } } return $result } <# .Synopsis Marks a computer to indicate a reboot is needed to complete updating .Description Timestamp in file indicates when reboot was last requested, Test-UpdateRebootRequested will compare this timestamp to the actual time of last reboot. Scripts can mark local machine request with the following snippet: $UpdateRebootRequestedPath = Join-Path $env:SystemDrive UpdateRebootRequest.xml [DateTime]::UtcNow.Ticks | Export-Clixml -Path $Script:UpdateRebootRequestedPath .Link Test-UpdateRebootRequested #> function Set-UpdateRebootRequested { [CmdletBinding(SupportsShouldProcess=$true)] Param ( [Parameter(Mandatory=$true)] [string] $ComputerName, [Parameter(Mandatory=$true)] [PSCredential] [System.Management.Automation.Credential()] $Credential ) $ErrorActionPreference = "Stop" Trace-Execution "Setting UpdateRebootRequest on $ComputerName" # Using UTC and Ticks to avoid format and timezone change issues if ($PSCmdlet.ShouldProcess($ComputerName)) { Invoke-Command -ComputerName $ComputerName -Credential $Credential -ScriptBlock { [DateTime]::UtcNow.Ticks | Export-Clixml -Path $using:UpdateRebootRequestedPath } } } <# .Synopsis Internal function to apply cabs for KBs to a computer .Link Install-Update #> function Install-UpdateKB { Param ( # Computer name to update [Parameter(Mandatory=$true)] [string] $ComputerName, # Explicit Credential for CredSSP [Parameter(Mandatory=$true)] [PSCredential] [System.Management.Automation.Credential()] $Credential, # Source for updates. [Parameter(Mandatory=$true)] [string] $SourcePath, # Optional Scratch directory for update installation [string] $ScratchDirectory = $null, # Install KBs sequentially - test hook [switch] $Sequential ) Install-UpdateKBSubFolder -ComputerName $ComputerName -Credential $Credential -SourcePath (Join-Path $SourcePath "SSU") -ScratchDirectory $ScratchDirectory -Sequential:$Sequential Install-UpdateKBSubFolder -ComputerName $ComputerName -Credential $Credential -SourcePath (Join-Path $SourcePath "LCU") -ScratchDirectory $ScratchDirectory -Sequential:$Sequential } <# .Synopsis Internal function to apply cabs for KBs to a computer #> function Install-UpdateKBSubFolder { Param ( # Computer name to update [Parameter(Mandatory=$true)] [string] $ComputerName, # Explicit Credential for CredSSP [Parameter(Mandatory=$true)] [PSCredential] [System.Management.Automation.Credential()] $Credential, # Source for updates. [Parameter(Mandatory=$true)] [string] $SourcePath, # Optional Scratch directory for update installation [string] $ScratchDirectory = $null, # Install KBs sequentially - test hook [switch] $Sequential ) $ErrorActionPreference = "Stop" $stopWatch = New-Object Diagnostics.Stopwatch $stopWatch.Start() Trace-Execution "$([DateTime]::Now): Starting Install-UpdateKB" Trace-Execution ($PSBoundParameters | Out-String) Trace-Execution "invoking to $computername" [ScriptBlock] $block = { Write-Verbose "At $env:COMPUTERNAME, using $using:SourcePath" if (!(Test-Path $using:SourcePath)) { Write-Warning "$using:SourcePath not reachable" return } if (!(Get-ChildItem -Path $using:SourcePath -Filter "*.cab")) { Write-Warning "There is no KB existing in $using:SourcePath" return } Write-Verbose "Tested sourcepath" $stopWatch = New-Object Diagnostics.Stopwatch $stopWatch.Start() Write-Verbose "$([DateTime]::Now): Starting Add-WindowsPackage" $PackageArgs = @{ Online = $true NoRestart = $true PackagePath = $using:SourcePath Verbose=$true } if ($using:ScratchDirectory) { Write-Verbose "Installing updates using ScratchDirectory '$($using:ScratchDirectory)'" New-Item -ItemType Directory -Path $using:ScratchDirectory -Force try { $result = Add-WindowsPackage @PackageArgs -ScratchDirectory $using:ScratchDirectory } finally { Remove-Item -Force -Recurse -Path $using:ScratchDirectory -ErrorAction Ignore } } else { $result = Add-WindowsPackage @PackageArgs } $stopWatch.Stop() Write-Verbose "$([DateTime]::Now), Elapsed: $($stopWatch.Elapsed), Restart Needed $($result.RestartNeeded)" return $result } $result = $null if (!$Sequential) { # ISSUE: This a long running job, potentially affected by network glitches # or service fabric failovers. # Consider potentially converting to a scheduled task type approach. # Even creating PS Jobs as in Common\Helpers\Invoke-JobCommon wouldn't # necessarily re-connect if the PS session goes away. Need to verify # underlying DISM behavior when this disconnects abruptly. try { $result = Invoke-Command -Credential $Credential -Authentication Credssp -ComputerName $ComputerName -ScriptBlock $block if ($result.RestartNeeded) { Set-UpdateRebootRequested -ComputerName $ComputerName -Credential $Credential } } catch { # Due to throw, unable to determine if batch application required reboot. Assume yes. Set-UpdateRebootRequested -ComputerName $ComputerName -Credential $Credential if ($_.Exception -imatch "0x800f081e") { Trace-Warning "Skipping not applicable update $($package.PackageName) from $($cab.Name), HRESULT 0x$('{0:X8}' -f $_.Exception.HResult)" } else { throw $_.Exception } } } else # Sequential install of updates { # build install state list $targetPackages = Invoke-Command -Credential $Credential -ComputerName $ComputerName -ScriptBlock { Get-WindowsPackage -Online -Verbose } $installStates = @{} foreach ($package in $targetPackages) { $installStates[$package.PackageName] = $package } $originalSourcePath = $SourcePath $cabs = Get-ChildItemLocalOrUnc -Path $originalSourcePath -Include "*.cab" -ComputerName $ComputerName -Credential $Credential $rebootRequested = $false $thrownException = @() try { foreach ($cab in $cabs) { $package = Invoke-Command -Credential $Credential -ComputerName $ComputerName -Authentication Credssp -ScriptBlock { return Get-WindowsPackage -Online -PackagePath $using:cab } $remotePackage = $installStates[$package.PackageName] Trace-Execution "$cab, Target package state: $($remotePackage.PackageState), $($package.PackageName)" if ((!$remotePackage) -or ($remotePackage.PackageState -ne "Installed")) { $SourcePath = $cab.FullName try { $result = Invoke-Command -Credential $Credential -Authentication Credssp -ComputerName $ComputerName -ScriptBlock $block if ($result.RestartNeeded) { $rebootRequested = $true } } catch { if ($_.Exception -imatch "0x800f081e") { Trace-Warning "Skipping not applicable update $($package.PackageName) from $($cab.Name), HRESULT 0x$('{0:X8}' -f $_.Exception.HResult)" } else { # Something unexpected happened. Continue applying other updates, # but assume reboot is probably required. $rebootRequested = $true $thrownException += $_ } } } else { Trace-Execution "Skipping $cab, $($package.InstallTime), $($package.PackageName)" } } } finally { if ($rebootRequested) { Set-UpdateRebootRequested -ComputerName $ComputerName -Credential $Credential } } if ($thrownException) { Trace-Warning "Re-throwing aggregated exceptions from sequential update installs" throw $thrownException } } $stopWatch.Stop() Trace-Execution "$([DateTime]::Now): Ending Install-UpdateKB, Elapsed: $($stopWatch.Elapsed), $ComputerName" return $result } <# .Synopsis Internal function to apply update scripts to computer. .Link Install-Update #> function Install-UpdateScript { Param ( # Computer name to update [Parameter(Mandatory=$true)] [string] $ComputerName, # Explicit Credential for CredSSP [Parameter(Mandatory=$true)] [PSCredential] [System.Management.Automation.Credential()] $Credential, # Source for updates [Parameter(Mandatory=$true)] [string] $SourcePath, # Allow unsigned PowerShell scripts [switch] $BypassExecutionPolicy ) $ErrorActionPreference = "Stop" $scripts = Get-ChildItemLocalOrUnc -Path $SourcePath -Include "*.ps1" -ComputerName $ComputerName -Credential $Credential foreach ($script in $scripts) { # Execute scripts on computers, respecting the signing requirements for remote scripts unless a bypass is set. Trace-Execution "Invoking $script at $ComputerName, BypassExecutionPolicy: $BypassExecutionPolicy" Invoke-Command -Verbose -Credential $Credential -Authentication Credssp -ComputerName $ComputerName -ScriptBlock { if ($using:BypassExecutionPolicy) { Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass } & $using:script } | Out-Null } } <# .Synopsis Internal function to validate KBs were installed successfully to a computer. #> function Test-UpdateKB { Param ( # Computer name to validate [Parameter(Mandatory=$true)] [string] $ComputerName, # Explicit Credential for CredSSP [Parameter(Mandatory=$true)] [PSCredential] $Credential, # Source for updates. [Parameter(Mandatory=$true)] [string] $SourcePath ) $ErrorActionPreference = "Stop" Trace-Execution "$([DateTime]::Now): Starting Test-UpdateKB" Trace-Execution "Testing state of Windows Update installation on $ComputerName." $cabs = @() $cabPaths = @((Join-Path $SourcePath "SSU"), (Join-Path $SourcePath "LCU")) $cabs = Get-ChildItemLocalOrUnc -Path $cabPaths -Include "*.cab" -ComputerName $ComputerName -Credential $Credential $notInstalledKBs = @() foreach ($cab in $cabs) { try { $package = Invoke-Command -Credential $Credential -ComputerName $ComputerName -Authentication Credssp -ScriptBlock { return Get-WindowsPackage -Online -PackagePath $using:cab } if ($package -and ($package.PackageState -ieq "Installed" -or $package.PackageState -ieq "Superseded")) { Trace-Execution "$cab was installed successfully on $ComputerName." } else { Trace-Warning "$cab was not installed on $ComputerName." $notInstalledKBs += $cab } } catch { Trace-Warning "$cab was not installed on $ComputerName." $notInstalledKBs += $cab } } if ($notInstalledKBs.Count -ge 1) { Trace-Error "The following KBs were not installed on $ComputerName : $notInstalledKBs." } Trace-Execution "$([DateTime]::Now): Test-UpdateKB completed successfully on $ComputerName." } <# .Synopsis Pre-processes a directory containing to extract the underlying cabs. .Description This is typically a pre-packaging step not performed on a running stamp. Caller is assumed to have access to Source and Destination, without requiring credentials. #> function Copy-ContentToStagingFolder { [CmdletBinding()] Param ( # Folder containing raw MSUs downloaded from Microsoft Catalog [Parameter(Mandatory=$true)] [string] $Source, # Output directory for flat folder of .CAB files suitable for DISM Add-WindowsPackage [Parameter(Mandatory=$true)] [string] $Destination, # Source is a WSUS Export [switch] $WSUSExport = $false, # Delete all existing content in the staging folder [switch] $PurgeExisting ) $ErrorActionPreference = "Stop" # Imports Import-Module (Join-Path $PSScriptRoot "Modules\Get-FreeDriveLetter.psm1") $stopWatch = New-Object Diagnostics.Stopwatch $stopWatch.Start() Trace-Execution "$([DateTime]::Now): Starting Copy-ContentToStagingFolder from $Source to $Destination, Purge: $PurgeExisting" # Find all MSUs, expand, copy the .CAB to a single folder if (!(Test-Path $Source)) { Trace-Error "$Source not accessible as source for MSUs" } $DestinationDrive = $null $SourceDrive = $null # MSU folder and file names can be very long and will exceed .NET limits in # a reasonably named share. Persistent PS drives will act as shortened # path names. # PSDrives, even though declared persistent, will only remain # mapped for the duration of their scope. No finally clean-up needed. $SourceDrive = New-PSDrive -Scope Local -Persist -Name (Get-FreeDriveLetter) -Root $Source -Description "Source for MSUs" -PSProvider FileSystem $Source = "$SourceDrive`:" $DestinationDrive = New-PSDrive -Scope Local -Persist -Name (Get-FreeDriveLetter) -Root $Destination -Description "Destination for extracted cabinets" -PSProvider FileSystem $Destination = "$DestinationDrive`:" if ($PurgeExisting) { Remove-Item (Join-Path $Destination *) -Include "*.cab" } if ($WSUSExport) { Copy-WSUSContentToStagingFolder -Source $Source -Destination $Destination } else { Copy-MSUContentToStagingFolder -Source $Source -Destination $Destination } $stopWatch.Stop() Trace-Execution "Ending Copy-ContentCabsToStagingFolder $([DateTime]::Now), Elapsed: $($stopWatch.Elapsed)" } function Copy-FileViaRoboCopy { [Diagnostics.CodeAnalysis.SuppressMessage("PSAvoidGlobalVars", "global:LASTEXITCODE", Scope="Function")] Param ( [Parameter(Mandatory=$true)] [string] $Source, [Parameter(Mandatory=$true)] [string] $Destination, [Parameter(Mandatory=$true)] [string] $Name ) # Robocopy can handle the long file names robocopy /R:5 /W:5 /NP /NJH /NJS /NDL /NFL $cab.DirectoryName $Destination $cab.Name $result = $LASTEXITCODE switch ($result) { 0 { # No file copied, okay in a merging (non-Purge) scenario if ($PurgeExisting) { Trace-Error "No file copied, but -Purge was specified" $global:LASTEXITCODE = 1 } } 1 { # Expected result $global:LASTEXITCODE = 0 } default { Trace-Error "RoboCopy returned unexpected LastExitCode: $result" } } } function Copy-MSUContentToStagingFolder { Param ( # Folder containing raw Content [Parameter(Mandatory=$true)] [string] $Source, # Output directory for flat folder of .CAB files suitable for DISM Add-WindowsPackage [Parameter(Mandatory=$true)] [string] $Destination ) # Extracted files are assumed not to hit long file name issues $extractTemp = Join-Path $env:TEMP "UpdateContentExpansion" $packages = Get-ChildItem -Recurse -Path $Source -Include "*.msu" foreach ($msu in $Packages) { if (Test-Path $extractTemp) { Remove-Item $extractTemp -Recurse -Force } New-Item -ItemType Directory $extractTemp | Out-Null try { #Expand.exe can handle the long file names. # Note that a non-compressed file will "expand" with no error - it's just a straight file copy. expand.exe -F:* $msu $extractTemp | Out-Null $result = $LastExitCode if (0 -ne $result) { Trace-Error "Expand.exe returned unexpected non-zero result: $result" } $cab = Get-ChildItem "$extractTemp\*" -Include "*.cab" -Exclude "WSUSSCAN.cab" if ($cab -and $cab.Count -eq 1) { Trace-Execution "Writing $($cab.Name) from $msu" Copy-FileViaRoboCopy $cab.DirectoryName $Destination $cab.Name } else { Trace-Error "Unexpected cabinet state found in $msu" } } finally { Remove-Item $extractTemp -Recurse -Force } } } function Copy-WSUSContentToStagingFolder { Param ( # Folder containing raw Content [Parameter(Mandatory=$true)] [string] $Source, # Output directory for flat folder of .CAB files suitable for DISM Add-WindowsPackage [Parameter(Mandatory=$true)] [string] $Destination ) # Extracted files are assumed not to hit long file name issues $extractTemp = Join-Path $env:TEMP "UpdateContentExpansion" $packages = Get-ChildItem -Recurse -Path $Source -Include "*.cab" if ($PurgeExisting) { Remove-Item (Join-Path $Destination *) -Include "*.cab" } foreach ($cab in $packages) { if (Test-Path $extractTemp) { Remove-Item $extractTemp -Recurse -Force } New-Item -ItemType Directory $extractTemp | Out-Null try { $keyFile = "update.cat" # Expand.exe can handle the long file names. # Note that a non-compressed file will "expand" with no error - it's just a straight file copy. expand.exe -F:$keyFile $cab $extractTemp | Out-Null $result = $LastExitCode if (0 -ne $result) { Trace-Error "Expand.exe returned unexpected non-zero result: $result" } $manifest = Get-ChildItem "$extractTemp\*" -Include $keyFile if ($manifest) { Trace-Execution "Staging $($cab.Name) from $Source" Copy-FileViaRoboCopy $cab.DirectoryName $Destination $cab.Name } else { Trace-Execution "Skipping non MSU package $($cab.Name)" } } finally { Remove-Item $extractTemp -Recurse -Force } } } # Test if the specified path is a UNC path. function Test-IsUncPath { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [string] $Path ) Trace-Execution "Testing if $Path is a UNC path." if ($Path.Contains(":")) { return $false } else { return $true } } # If the path is a UNC path we can directly find the files from this path. However if this is a local CSV path # used for host update, we have to do the file search in a remote session to the node being updated. function Get-ChildItemLocalOrUnc { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] $Path, [Parameter(Mandatory=$true)] $Include, [Parameter(Mandatory=$true)] $ComputerName, [Parameter(Mandatory=$true)] $Credential ) if (Test-IsUncPath -Path $Path) { return Get-ChildItem -Path (Join-Path $Path *) -Include $Include } else { return (Invoke-Command -Credential $Credential -ComputerName $ComputerName -ScriptBlock { if (-not (Test-Path $using:Path)) { return $null } else { Get-ChildItem -Path (Join-Path $using:Path *) -Include $using:Include } }) } } # Public Export-ModuleMember -Function Set-UpdateRebootRequested Export-ModuleMember -Function Test-UpdateRebootRequested Export-ModuleMember -Function Install-Update Export-ModuleMember -Function Copy-ContentToStagingFolder # Internal Export-ModuleMember -Function Install-UpdateScript Export-ModuleMember -Function Install-UpdateKB Export-ModuleMember -Function Install-UpdateCIPolicy Export-ModuleMember -Function Test-UpdateKB Export-ModuleMember -Function Test-IsUncPath Export-ModuleMember -Function Get-ChildItemLocalOrUnc # SIG # Begin signature block # MIInvwYJKoZIhvcNAQcCoIInsDCCJ6wCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCQWPm5eXrjpV6a # gTr+wnhmXDhod7yhkgVFRcICxlMuGKCCDXYwggX0MIID3KADAgECAhMzAAADrzBA # DkyjTQVBAAAAAAOvMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjMxMTE2MTkwOTAwWhcNMjQxMTE0MTkwOTAwWjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDOS8s1ra6f0YGtg0OhEaQa/t3Q+q1MEHhWJhqQVuO5amYXQpy8MDPNoJYk+FWA # hePP5LxwcSge5aen+f5Q6WNPd6EDxGzotvVpNi5ve0H97S3F7C/axDfKxyNh21MG # 0W8Sb0vxi/vorcLHOL9i+t2D6yvvDzLlEefUCbQV/zGCBjXGlYJcUj6RAzXyeNAN # xSpKXAGd7Fh+ocGHPPphcD9LQTOJgG7Y7aYztHqBLJiQQ4eAgZNU4ac6+8LnEGAL # go1ydC5BJEuJQjYKbNTy959HrKSu7LO3Ws0w8jw6pYdC1IMpdTkk2puTgY2PDNzB # tLM4evG7FYer3WX+8t1UMYNTAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQURxxxNPIEPGSO8kqz+bgCAQWGXsEw # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzUwMTgyNjAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAISxFt/zR2frTFPB45Yd # mhZpB2nNJoOoi+qlgcTlnO4QwlYN1w/vYwbDy/oFJolD5r6FMJd0RGcgEM8q9TgQ # 2OC7gQEmhweVJ7yuKJlQBH7P7Pg5RiqgV3cSonJ+OM4kFHbP3gPLiyzssSQdRuPY # 1mIWoGg9i7Y4ZC8ST7WhpSyc0pns2XsUe1XsIjaUcGu7zd7gg97eCUiLRdVklPmp # XobH9CEAWakRUGNICYN2AgjhRTC4j3KJfqMkU04R6Toyh4/Toswm1uoDcGr5laYn # TfcX3u5WnJqJLhuPe8Uj9kGAOcyo0O1mNwDa+LhFEzB6CB32+wfJMumfr6degvLT # e8x55urQLeTjimBQgS49BSUkhFN7ois3cZyNpnrMca5AZaC7pLI72vuqSsSlLalG # OcZmPHZGYJqZ0BacN274OZ80Q8B11iNokns9Od348bMb5Z4fihxaBWebl8kWEi2O # PvQImOAeq3nt7UWJBzJYLAGEpfasaA3ZQgIcEXdD+uwo6ymMzDY6UamFOfYqYWXk # ntxDGu7ngD2ugKUuccYKJJRiiz+LAUcj90BVcSHRLQop9N8zoALr/1sJuwPrVAtx # HNEgSW+AKBqIxYWM4Ev32l6agSUAezLMbq5f3d8x9qzT031jMDT+sUAoCw0M5wVt # CUQcqINPuYjbS1WgJyZIiEkBMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 # IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg # Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC # CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03 # a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr # rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg # OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy # 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9 # sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh # dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k # A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB # w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn # Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90 # lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w # ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o # ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD # VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa # BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny # bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG # AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t # L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV # HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG # AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl # AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb # C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l # hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6 # I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0 # wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 # STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam # ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa # J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah # XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA # 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt # Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr # /Xmfwb1tbWrJUnMTDXpQzTGCGZ8wghmbAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAAOvMEAOTKNNBUEAAAAAA68wDQYJYIZIAWUDBAIB # BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIHpSCoUokvw7evTjCvUhHcpg # IAuouFozI5lRHzOUQOivMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB # BQAEggEABW+acw7qy5z6LXiBzMDvp2AgHYgaHI5dZfQjZxKJ3KLxapr9O9d0VSmn # uj0EBNqdvm7dN58HYnezMNQ6XR1Y746j5+nYNPWhZ2Htn5FuCghRjitlS8azWwyx # 6jJ1DUoBZHHdb/cKtAmOdf7DYHberzRf7luJyW+jBI32nB72498HmC53WQyr+N+t # Q0gPO/wAZW3CbCqxrQTxXbhSh9Cl9Evjrsj2fs0UuLnmm5CHolFAkRdvYd6pLKaD # qfdqaNg0xd5q0C+z1cCL+tpy0dhNW14TiE/kUJBOmXadTv5XPDKxar89vCxEY3Ie # YJZ2j1GkMTF70kVr7V5OGvkHsRWBE6GCFykwghclBgorBgEEAYI3AwMBMYIXFTCC # FxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsq # hkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl # AwQCAQUABCD1ouSanN1geIyFNMo7JTVRsdoSKgrDkSB9LSqjUXHEOgIGZjOt3LDC # GBMyMDI0MDUxNjE4NDQzNi44NzdaMASAAgH0oIHYpIHVMIHSMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl # bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO # OkZDNDEtNEJENC1EMjIwMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT # ZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAHimZmV8dzjIOsAAQAAAeIwDQYJ # KoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjMx # MDEyMTkwNzI1WhcNMjUwMTEwMTkwNzI1WjCB0jELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl # cmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpGQzQxLTRC # RDQtRDIyMDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCC # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALVjtZhV+kFmb8cKQpg2mzis # DlRI978Gb2amGvbAmCd04JVGeTe/QGzM8KbQrMDol7DC7jS03JkcrPsWi9WpVwsI # ckRQ8AkX1idBG9HhyCspAavfuvz55khl7brPQx7H99UJbsE3wMmpmJasPWpgF05z # ZlvpWQDULDcIYyl5lXI4HVZ5N6MSxWO8zwWr4r9xkMmUXs7ICxDJr5a39SSePAJR # IyznaIc0WzZ6MFcTRzLLNyPBE4KrVv1LFd96FNxAzwnetSePg88EmRezr2T3HTFE # lneJXyQYd6YQ7eCIc7yllWoY03CEg9ghorp9qUKcBUfFcS4XElf3GSERnlzJsK7s # /ZGPU4daHT2jWGoYha2QCOmkgjOmBFCqQFFwFmsPrZj4eQszYxq4c4HqPnUu4hT4 # aqpvUZ3qIOXbdyU42pNL93cn0rPTTleOUsOQbgvlRdthFCBepxfb6nbsp3fcZaPB # fTbtXVa8nLQuMCBqyfsebuqnbwj+lHQfqKpivpyd7KCWACoj78XUwYqy1HyYnStT # me4T9vK6u2O/KThfROeJHiSg44ymFj+34IcFEhPogaKvNNsTVm4QbqphCyknrwBy # qorBCLH6bllRtJMJwmu7GRdTQsIx2HMKqphEtpSm1z3ufASdPrgPhsQIRFkHZGui # hL1Jjj4Lu3CbAmha0lOrAgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQURIQOEdq+7Qds # lptJiCRNpXgJ2gUwHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYD # VR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j # cmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwG # CCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIw # MjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD # CDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBAORURDGrVRTbnulf # sg2cTsyyh7YXvhVU7NZMkITAQYsFEPVgvSviCylr5ap3ka76Yz0t/6lxuczI6w7t # Xq8n4WxUUgcj5wAhnNorhnD8ljYqbck37fggYK3+wEwLhP1PGC5tvXK0xYomU1nU # +lXOy9ZRnShI/HZdFrw2srgtsbWow9OMuADS5lg7okrXa2daCOGnxuaD1IO+65E7 # qv2O0W0sGj7AWdOjNdpexPrspL2KEcOMeJVmkk/O0ganhFzzHAnWjtNWneU11WQ6 # Bxv8OpN1fY9wzQoiycgvOOJM93od55EGeXxfF8bofLVlUE3zIikoSed+8s61NDP+ # x9RMya2mwK/Ys1xdvDlZTHndIKssfmu3vu/a+BFf2uIoycVTvBQpv/drRJD68eo4 # 01mkCRFkmy/+BmQlRrx2rapqAu5k0Nev+iUdBUKmX/iOaKZ75vuQg7hCiBA5xIm5 # ZIXDSlX47wwFar3/BgTwntMq9ra6QRAeS/o/uYWkmvqvE8Aq38QmKgTiBnWSS/uV # PcaHEyArnyFh5G+qeCGmL44MfEnFEhxc3saPmXhe6MhSgCIGJUZDA7336nQD8fn4 # y6534Lel+LuT5F5bFt0mLwd+H5GxGzObZmm/c3pEWtHv1ug7dS/Dfrcd1sn2E4gk # 4W1L1jdRBbK9xwkMmwY+CHZeMSvBMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJ # mQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh # dGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1 # WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEB # BQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjK # NVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhg # fWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJp # rx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/d # vI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka9 # 7aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKR # Hh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9itu # qBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyO # ArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItb # oKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6 # bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6t # AgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQW # BBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacb # UzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYz # aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnku # aHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIA # QwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2 # VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwu # bWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEw # LTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93 # d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYt # MjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/q # XBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6 # U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVt # I1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis # 9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTp # kbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0 # sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138e # W0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJ # sWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7 # Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0 # dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQ # tB1VM1izoXBm8qGCAtQwggI9AgEBMIIBAKGB2KSB1TCB0jELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxh # bmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpG # QzQxLTRCRDQtRDIyMDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy # dmljZaIjCgEBMAcGBSsOAwIaAxUAFpuZafp0bnpJdIhfiB1d8pTohm+ggYMwgYCk # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF # AOnwn2IwIhgPMjAyNDA1MTYyMzA2MTBaGA8yMDI0MDUxNzIzMDYxMFowdDA6Bgor # BgEEAYRZCgQBMSwwKjAKAgUA6fCfYgIBADAHAgEAAgIYmzAHAgEAAgITVDAKAgUA # 6fHw4gIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAID # B6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAISJNra7Ggw4B/8Tn4yp # x+hXDg8/G8srkcJl7vwzRVbuS6W9fR0YCSMS6fkjFayeozoQe5FrKcY1U7cZw3XC # UhSsQGfYXh1matPvCIPXbjvnphAuKz0TdujD/q+eE6Gqa++ey0goT0AYhcfDRwvx # gxxBejaOpgYnpl40jU7s7YN9MYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt # U3RhbXAgUENBIDIwMTACEzMAAAHimZmV8dzjIOsAAQAAAeIwDQYJYIZIAWUDBAIB # BQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQx # IgQg2iZM/6/LdcwJxW8T3CfmvA01KU2LT7raBTFGTH6yW+0wgfoGCyqGSIb3DQEJ # EAIvMYHqMIHnMIHkMIG9BCAriSpKEP0muMbBUETODoL4d5LU6I/bjucIZkOJCI9/ # /zCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw # DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x # JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB4pmZ # lfHc4yDrAAEAAAHiMCIEILplb72oW4+73iQROSoFPO5HtCiiSLulx8XotCt2EMse # MA0GCSqGSIb3DQEBCwUABIICAJzzdNnXkjwWzRao8kHDWii9frYF+VMi2sEz35RN # Gj4HUubt8MxYFjxVfWhaHFb1IuVs1v/WIHw8O24D+WpMHo78UkirkWAllNq2VBe2 # 36L+xUm3iIpVE/3nsmQKYusL5dVy2dNkgLS5UOSgzNPKHXB6iRozB2a6qrHojwd2 # dzt3AQd8Npfx1+YClSNb+kMwrcWY5ss3bo6N1/1B2SMZ660e020yss/vySqW5TjI # topz6hRErXqX+tjErAK45Y6zTh4LkrzKP5SuqvA5ue5aPxHbkISouUlizDcopPny # Hub2/kfCR+oSQ5AyCLjTH9o9xFUGBYioogjvIltdoNRvuAlEAS7Zs/pQS52/KXVF # +5Zsa+LcaQ5akXVXo+yfZZ7oqzteNH/h0b5i6VjYYTIe6RhHD08xpFSPDEI9egv+ # PYQZ6ukvXyqgiZt5Cx9qDSy21+SakAGmSIAmRly/uGxmTlBzhvdRzLioyLTl3JOj # IIExiOgZBDVam+3Mb2UlcsmfJWEVt1ZeLUEG6g0deJLV1zfWIKRnLGeCcnV8mEKc # RnT7Il60veL7gYIfLnB+81fyjBgpwXbLt/qRSf4goxD0ezEpgHNS0UmyU5OBdmfR # hzy6jzAi6YZ7EEQhkQ62JyKKfqWatm1Gm5Eu47aSyTjGQp1wrvNuVdl3A6iD5eh9 # VnNB # SIG # End signature block |