Execution.psm1
function Set-ScriptArgs { [CmdletBinding()] param( [Parameter()] [System.Collections.Generic.Dictionary`2[System.String, System.Object]] $BoundParameters, [Parameter()] [System.Collections.Generic.List`1[System.Object]] $UnboundArguments ) $global:PSCommandPath = $MyInvocation.PSCommandPath Log trace "global:PSCommandPath: '$global:PSCommandPath'" $argumentList = [System.Collections.ArrayList]@() $parameters = (Get-Command $global:PSCommandPath).Parameters Log trace 'Parse bound parameters...' foreach ($key in $BoundParameters.Keys) { $type = $parameters.Values | Where-Object { $_.Name -eq $key } | Select-Object -ExpandProperty ParameterType Log trace "Parametertype: '$($type.FullName)'" switch ($type) { ([System.Management.Automation.SwitchParameter]) { $value = '$true' } ([System.Boolean]) { try { $boolValue = [System.Convert]::ToBoolean($BoundParameters[$key]) } catch { $boolValue = $false } $value = if ($boolValue) { '$true' } else { '$false' } } default { $value = $BoundParameters[$key] } } Log trace "-$key`:$value" $argumentList.Add("-$key`:$value") > $null } Log trace 'Parse bound parameters... Done.' Log trace 'Parse unbound arguments...' foreach ($arg in $UnboundArguments) { Log trace "$arg" $argumentList.Add($arg) > $null } Log trace 'Parse unbound arguments... Done.' $global:ScriptArgs = $argumentList Log trace "global:ScriptArgs: '$global:ScriptArgs'" } function Invoke-SelfElevation() { # Self-elevate the script if required if ($PSVersionTable.Platform -eq 'unix') { if ((id -u) -ne 0) { Log trace 'Try self elevation on Unix platform...' $executionInfo = Get-ExecutionInfo & sudo $executionInfo.Executable @($executionInfo.ArgumentList) exit 0 } } else { if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'administrator')) { if ([int] (Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) { Log trace 'Try self elevation on Windows platform...' $executionInfo = Get-ExecutionInfo $hashAndFile = Get-HashAndFile -Executable $executionInfo.Executable -Arguments $executionInfo.Arguments Log trace "Write mutex file with hash to '$($hashAndFile.File)'" New-Item -Path $hashAndFile.File -ItemType File -Force > $null Log trace "Start-Process -FilePath $($executionInfo.Executable) -ArgumentList $($executionInfo.Arguments) -WorkingDirectory $PSScriptRoot -Verb runas" Start-Process -FilePath $executionInfo.Executable -ArgumentList $executionInfo.Arguments -WorkingDirectory $PSScriptRoot -Verb runas exit 0 } } } } function Exit-WithAndWaitOnExplorer([int] $ExitCode) { if ($PSVersionTable.Platform -ne 'unix') { $executionInfo = Get-ExecutionInfo $hashAndFile = Get-HashAndFile -Executable $executionInfo.Executable -Arguments $executionInfo.Arguments Log trace "Check if mutex file exists '$($hashAndFile.FileName)'..." $mutexFileExists = Test-Path -Path $hashAndFile.File if ($mutexFileExists) { Log trace "Mutex file exists '$($hashAndFile.File)'" Remove-Item -Path $hashAndFile.File -Force > $null } if ((Get-ScriptIsCalledFromUI) -or $mutexFileExists) { Log info 'Press any key to continue . . . ' $HOST.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') > $null $HOST.UI.RawUI.FlushInputBuffer() } } exit $ExitCode } function Get-ScriptIsCalledFromUI() { # Check distance from current process to 'explorer.exe' to # determine if the user start the script in explorer or UI. # If the hierarchy is like this above, then we can determine # that the user executed the script from 'explorer.exe' UI. # # 1) pwsh.exe|powershell.exe # 2) -> cmd.exe # 3) -> explorer.exe $calledFromUI = $false $processNames = [System.Collections.ArrayList]@() $currentProcessId = $PID $indent = 2 Log trace 'ProcessHierarchy:' while ($true) { $currentProcess = Get-CimInstance Win32_Process -Filter "ProcessId = $currentProcessId" $currentProcessName = $currentProcess.Name if (-not $currentProcessId -or -not $currentProcessName) { # We are on the top -> break break } Log trace "$(''.PadLeft($indent))$currentProcessName -> $currentProcessId" $processNames.Add($currentProcessName) > $null $indent += 2 $currentProcessId = $currentProcess.ParentProcessId } $expectedProcessNames = @('(pwsh.exe)|(powershell.exe)', 'cmd.exe', 'explorer.exe') if ($processNames.Count -ge $expectedProcessNames.Count) { $indent = 2 Log trace 'Check ProcessHierarchy:' for ($i = 0; $i -lt $expectedProcessNames.Count; $i++) { if ($processNames[$i] -imatch $expectedProcessNames[$i]) { $calledFromUI = $true Log trace "$(''.PadLeft($indent))$($processNames[$i]) -> $($expectedProcessNames[$i]) -> OK" } else { $calledFromUI = $false Log trace "$(''.PadLeft($indent))$($processNames[$i]) -> $($expectedProcessNames[$i]) -> FAIL" break } $indent += 2 } } return $calledFromUI } function Get-ExecutionInfo() { $executable = Get-Process -Id $PID | Select-Object -ExpandProperty MainModule | Select-Object -ExpandProperty FileName $argumentList = @('-NoProfile', '-ExecutionPolicy', 'Unrestricted', '-Command', "`"& `"$global:PSCommandPath`" $global:ScriptArgs`"") $arguments = "$argumentList" Log trace "executable: $executable" Log trace "argumentList: $argumentList" Log trace "arguments: $arguments" $executionInfo = [pscustomobject][ordered]@{ Executable = $executable ArgumentList = $argumentList Arguments = $arguments } return $executionInfo } function Get-HashAndFile([string] $Executable, [string] $Arguments) { Log trace "Get-HashAndFile -> `$Executable: '$Executable' | `$Arguments: '$Arguments'" $value = "$Executable $Arguments".ToLowerInvariant() $fileName = "psec-$(Get-Checksum -Value $value)" $file = (Join-Path $env:TEMP $fileName) $object = [pscustomobject][ordered]@{ FileName = $fileName File = $file } return $object } function Set-PSScriptID() { Log trace 'Set-PSScriptID' $callStack = Get-PSCallStack $callerInvocation = $callStack[1].InvocationInfo $commandPath = $callStack[0].InvocationInfo.PSCommandPath Log trace " commandPath: '$commandPath'" $argumentList = [System.Collections.ArrayList]@() $parameters = (Get-Command $commandPath).Parameters Log trace ' Parse bound parameters...' foreach ($key in $callerInvocation.BoundParameters.Keys) { $type = $parameters.Values | Where-Object { $_.Name -eq $key } | Select-Object -ExpandProperty ParameterType Log trace " Parametertype: '$($type.FullName)'" switch ($type) { ([System.Management.Automation.SwitchParameter]) { $value = '$true' } ([System.Boolean]) { try { $boolValue = [System.Convert]::ToBoolean($callerInvocation.BoundParameters[$key]) } catch { $boolValue = $false } $value = if ($boolValue) { '$true' } else { '$false' } } default { $value = $callerInvocation.BoundParameters[$key] } } Log trace " -$key`:$value" $argumentList.Add("-$key`:$value") > $null } Log trace ' Parse unbound arguments...' foreach ($arg in $callerInvocation.UnboundArguments) { Log trace "$arg" $argumentList.Add($arg) > $null } # Construct command and arguments $executable = Get-Process -Id $PID | Select-Object -ExpandProperty MainModule | Select-Object -ExpandProperty FileName # Normalize executable $executable = "`"$(Get-CanonicalPath $executable)`"" Log trace " executable: '$executable'" $argumentList = @('-NoProfile', '-ExecutionPolicy', 'Unrestricted', '-Command', "`"& `"`"`"$commandPath`"`"`" $argumentList`"") Log trace " argumentList: '$argumentList'" $fileHash = Get-FileHashFromCommand $executable $argumentList $scriptID = [guid]::NewGuid().Guid.Replace('-', '') Log trace " Set PSScriptInfos for scriptID: '$scriptID'" $global:PSScriptInfos[$scriptID] = [pscustomobject][ordered]@{ Executable = $executable ScriptPath = $commandPath ArgumentList = $argumentList } $global:PSScriptInfos[$scriptID] | Add-Member -MemberType ScriptProperty -Name 'Arguments' -Value { "$($this.ArgumentList)" } $global:PSScriptInfos[$scriptID] | Add-Member -MemberType NoteProperty -Name 'FileHash' -Value $fileHash Log trace " Executable: '$($global:PSScriptInfos[$scriptID].Executable)'" Log trace " ScriptPath: '$($global:PSScriptInfos[$scriptID].ScriptPath)'" Log trace " ArgumentList: '$($global:PSScriptInfos[$scriptID].ArgumentList)'" Log trace " Arguments: '$($global:PSScriptInfos[$scriptID].Arguments)'" Log trace " FileHash: '$($global:PSScriptInfos[$scriptID].FileHash)'" Set-Variable -Name 'PSScriptID' -Value $scriptID -Scope ($callStack.Count - 2) } function Get-CanonicalPath([string] $Path) { if (-not (Test-Path -Path $Path -PathType Any)) { return $Path } $dir = [System.IO.DirectoryInfo]::new($Path) if ($null -ne $dir.Parent) { return Join-Path (Get-CanonicalPath -Path $dir.Parent.FullName) ($dir.Parent.GetFileSystemInfos($dir.Name)[0].Name) } else { return $dir.Name.ToUpperInvariant() } } function Restart-SelfElevated() { Log trace 'Restart-SelfElevated' $scriptID = Get-Variable -Name 'PSScriptID' -ValueOnly -Scope ((Get-PSCallStack).Count - 2) Log trace " -> `$scriptID: '$scriptID'" # Self-elevate the script if required if ($PSVersionTable.Platform -eq 'unix') { if ((id -u) -ne 0) { Log trace ' Try self elevation on Unix platform...' Log trace " Get PSScriptInfos for scriptID: '$scriptID'" $scriptInfo = $global:PSScriptInfos[$scriptID] & sudo $scriptInfo.Executable @($scriptInfo.ArgumentList) exit 0 } } else { if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'administrator')) { if ([int] (Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) { Log trace ' Try self elevation on Windows platform...' Log trace " Get PSScriptInfos for scriptID: '$scriptID'" $scriptInfo = $global:PSScriptInfos[$scriptID] Log trace " Write mutex file -> '$($scriptInfo.FileHash.File)'" New-Item -Path $scriptInfo.FileHash.File -ItemType File -Force > $null Log trace " -> Start-Process -FilePath $($scriptInfo.Executable) -ArgumentList $($scriptInfo.Arguments) -WorkingDirectory $PSScriptRoot -Verb runas" Start-Process -FilePath $scriptInfo.Executable -ArgumentList $scriptInfo.Arguments -WorkingDirectory $PSScriptRoot -Verb runas exit 0 } } } } function Exit-AndWaitOnUI([int] $ExitCode) { Log trace 'Exit-AndWaitOnUI' Log trace " -> `$ExitCode: '$ExitCode'" $scriptID = Get-Variable -Name 'PSScriptID' -ValueOnly -Scope ((Get-PSCallStack).Count - 2) Log trace " -> `$scriptID: '$scriptID'" if ($PSVersionTable.Platform -ne 'unix') { Log trace " Get PSScriptInfos for scriptID: '$scriptID'" $scriptInfo = $global:PSScriptInfos[$scriptID] Log trace " Check if mutex file exists '$($scriptInfo.FileHash.FileName)'..." $mutexFileExists = Test-Path -Path $scriptInfo.FileHash.File if ($mutexFileExists) { Log trace "Remove existing mutex file -> '$($scriptInfo.FileHash.File)'" Remove-Item -Path $scriptInfo.FileHash.File -Force > $null } if ((Get-ScriptIsCalledFromUI) -or $mutexFileExists) { Log info 'Press any key to continue . . . ' $HOST.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') > $null $HOST.UI.RawUI.FlushInputBuffer() } } exit $ExitCode } function Get-FileHashFromCommand([string] $Executable, [string[]] $ArgumentList) { Log trace 'Get-FileHashFromCommand' Log trace " -> `$Executable: '$Command'" Log trace " -> `$ArgumentList: '$ArgumentList'" $combinedValue = "$Executable $ArgumentList" Log trace " combinedValue: '$combinedValue'" $checksum = Get-Checksum -Value $combinedValue $fileName = "psec-$checksum" $file = (Join-Path $env:TEMP $fileName) Log trace " checksum: '$checksum'" Log trace " checksum: '$fileName'" Log trace " checksum: '$file'" $object = [pscustomobject][ordered]@{ FileName = $fileName File = $file Checksum = $checksum } return $object } function Invoke-Process { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $Command, [Parameter(ValueFromRemainingArguments = $true)] [string[]] $CommandArgs ) $commandString = $Command if ($commandArgs) { $commandString += " $commandArgs" } Write-Host "Execute: '$commandString'" -ForegroundColor DarkYellow $startInfo = New-Object System.Diagnostics.ProcessStartInfo $startInfo.FileName = $command $startInfo.Arguments = $commandArgs $startInfo.UseShellExecute = $false $startInfo.WorkingDirectory = Get-Location $process = New-Object System.Diagnostics.Process $process.StartInfo = $startInfo $process.Start() > $null $finished = $false try { while (-not $process.WaitForExit(100)) { # Non-blocking loop done to allow ctr-c interrupts } $finished = $true return $global:LASTEXITCODE = $process.ExitCode } finally { # If we didn't finish then an error occured or the user hit ctrl-c. Either way kill the process if (-not $finished) { $process.Kill() } } } function Start-NativeExecution() { $backupEap = $Script:ErrorActionPreference $Script:ErrorActionPreference = 'Continue' try { if ($args.Length -lt 1) { Log warning 'No arguments specified' return } Log trace "Execute: '$args'" $command = $args[0] | Get-QuotedPath $arguments = $args | Select-Object -Skip 1 | Get-QuotedPath Log trace "Command: '$command'" if ($arguments -and $arguments.Length -gt 0) { Log trace "Arguments: '$arguments'" } $wrapperScriptBlock = [ScriptBlock]::Create("& $command $arguments") $calledFromPrompt = Test-CalledFromPrompt if ($calledFromPrompt) { $wrapperScriptBlock = [ScriptBlock]::Create("& $command $arguments") } else { $wrapperScriptBlock = [ScriptBlock]::Create("& $command $arguments 2>&1") } Log trace "WrapperScriptBlock: '$wrapperScriptBlock'" $messages = & $wrapperScriptBlock # NOTE: If $wrapperScriptBlock's command doesn't have a native invocation, # $LASTEXITCODE will point to the obsolete value Log trace "LASTEXITCODE: $LASTEXITCODE" Log trace "`$?: $?" # Need to check both of these cases for errors as they represent different items # - $?: Did the powershell script block throw an error # - $LASTEXITCODE: Did a windows command executed by the script block end in error if ((-not $?) -or ($LASTEXITCODE -and $LASTEXITCODE -ne 0)) { if ($Error -ne $null) { Log error $Error[0] } Log error "Execution of '$args' failed with exit code $LASTEXITCODE." $logLevel = 'error' } else { $logLevel = 'info' } if ($calledFromPrompt -and (Test-Path Variable:\messages)) { if ($messages -is [System.Object[]]) { foreach ($message in $messages) { if ($message.GetType() -eq [System.Management.Automation.ErrorRecord]) { $lines = $message.Exception.Message.Split("`r`n", [System.StringSplitOptions]::RemoveEmptyEntries) } elseif ($message.GetType() -eq [string]) { $lines = $message.Split("`r`n", [System.StringSplitOptions]::RemoveEmptyEntries) } if (Test-Path Variable:\lines) { $lines | Log $logLevel } } } if ($messages -is [string]) { $messages.Split("`r`n", [System.StringSplitOptions]::RemoveEmptyEntries) | Log $logLevel } } } catch { if ($_.Exception -and $_.Exception.Message) { $_.Exception.Message.Split("`r`n", [System.StringSplitOptions]::RemoveEmptyEntries) | Log error } } finally { if (-not (Test-Path Variable:\messages)) { $messages = $null } $Script:ErrorActionPreference = $backupEap } return $messages } function Get-QuotedPath { [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [string] $Path ) process { Log trace "Path: $Path" if ($Path -match '\s') { return "`"$Path`"" } else { return $Path } } } function Test-CalledFromPrompt() { $command = (Get-PSCallStack)[-2].Command Log trace "PromptCommand: $command" return ($command -eq 'prompt') } function Clear-TempDirectories { [CmdletBinding()] param( [Parameter()] [string[]] $AdditionalPaths, [Parameter()] [switch] $TryRun ) $tempDirName = 'temp' $dirs = [System.Collections.ArrayList]@() Add-ItemWhenExists -Item (Join-Path $env:ProgramFiles $tempDirName) -List $dirs Add-ItemWhenExists -Item (Join-Path ${env:ProgramFiles(x86)} $tempDirName) -List $dirs Add-ItemWhenExists -Item (Join-Path $env:windir $tempDirName) -List $dirs $userDirs = Get-ChildItem 'C:/Users' -Directory -Force foreach ($userDir in $userDirs) { Add-ItemWhenExists -Item (Join-Path $userDir.FullName "AppData/Local/$tempDirName") -List $dirs Add-ItemWhenExists -Item (Join-Path $userDir.FullName "AppData/LocalLow/$tempDirName") -List $dirs Add-ItemWhenExists -Item (Join-Path $userDir.FullName "AppData/Roaming/$tempDirName") -List $dirs } if ($AdditionalPaths) { $AdditionalPaths | Add-ItemWhenExists -List $dirs } for ($i = 0; $i -lt $dirs.Count; $i++) { $items = $dirs[$i] | Get-ChildItem -Recurse -Force -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName | Sort-Object -Descending -Property Length $total = $items | Measure-Object | Select-Object -ExpandProperty Count Log trace "Found '$total' items in '$($dirs[$i])' to remove" Write-Progress -Id 1 -Activity 'Clear TEMP directories' -Status "Step $($($i + 1).ToString().PadLeft($dirs.Count.ToString().Length)) of $($dirs.Count)" -CurrentOperation "Remove all items in '$($dirs[$i])'" -PercentComplete (($i + 1) / $dirs.Count * 100) for ($ii = 0; $ii -lt $items.Count; $ii++) { Write-Progress -Id 2 -ParentId 1 -Activity 'Processing items' -Status "Item $($($ii + 1).ToString().PadLeft($items.Count.ToString().Length)) of $($items.Count)" -CurrentOperation "Remove item '$($items[$ii])'" -PercentComplete (($ii + 1) / $items.Count * 100) if (-not $TryRun) { Remove-ItemSafe -Path $items[$ii] -Retries 16 -Milliseconds 10 } else { Start-Sleep -Milliseconds 1 } } } } function Add-ItemWhenExists { [CmdletBinding()] param( [Parameter(ValueFromPipeline)] [string] $Item, [Parameter()] [System.Collections.ArrayList] $List ) process { if ($Item -and (Test-Path $Item)) { $List.Add($Item) > $null } } } function Remove-ItemSafe { [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [string] $Path, [Parameter()] [int] $Retries = 255, [Parameter()] [int] $Milliseconds = 75 ) process { Log trace "Remove item safe '$Path'..." while ($path -and (Test-Path -Path $Path -ErrorAction SilentlyContinue) -and ($Retries -gt 0)) { try { if ((Test-Path -Path $Path -PathType Container) -and ((Get-ChildItem -Path $Path -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object | Select-Object -ExpandProperty Count) -gt 0)) { Remove-Item -Path $Path -Recurse -Force -ErrorAction SilentlyContinue > $null } else { Remove-Item -Path $path -Force -ErrorAction SilentlyContinue > $null } } catch { Start-Sleep -Milliseconds $Milliseconds } finally { --$Retries } } } } function Invoke-WhenFileChanged { [CmdletBinding()] Param ( [Parameter(Mandatory)] [string] $File, [Parameter(Mandatory )] [string] $Action, [Parameter()] [int] $PoolingIntervalInMS = 100 ) Process { $global:FileChanged = $false $executeCounter = 0 $File = Resolve-Path $File $filePath = Split-Path $File -Parent $fileName = Split-Path $File -Leaf $scriptBlock = [scriptblock]::Create($Action) $watcher = New-Object IO.FileSystemWatcher $filePath, $fileName -Property @{ IncludeSubdirectories = $false EnableRaisingEvents = $true } Log info "::: [$(Get-Date -Format s)] Register event..." $onChange = Register-ObjectEvent $watcher Changed -Action { $global:FileChanged = $true } [System.Console]::TreatControlCAsInput = $true try { while ($true) { if ($global:FileChanged) { ++$executeCounter Log info "::: [$(Get-Date -Format s)] Execute (${executeCounter}): ${Action}" & $scriptBlock $global:FileChanged = $false } if ($Host.UI.RawUI.KeyAvailable -and (3 -eq [int]$Host.UI.RawUI.ReadKey('AllowCtrlC, IncludeKeyUp, NoEcho').Character)) { Log info "::: [$(Get-Date -Format s)] Unregister event..." Unregister-Event -SourceIdentifier $onChange.Name return } Start-Sleep -Milliseconds $PoolingIntervalInMS } } catch [Exception] { Log info "::: [$(Get-Date -Format s)] Unregister event..." Unregister-Event -SourceIdentifier $onChange.Name } } End { [System.Console]::TreatControlCAsInput = $false } } $global:PSScriptInfos = [hashtable]@{} # SIG # Begin signature block # MIIoFAYJKoZIhvcNAQcCoIIoBTCCKAECAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBrOoRlJaNf1Eyc # Cu5aOV0CFVjCCSOOVHTV27UyY8NROKCCIRcwggWNMIIEdaADAgECAhAOmxiO+dAt # 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV # BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa # Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD # ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E # MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy # unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF # xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1 # 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB # MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR # WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6 # nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB # YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S # UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x # q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB # NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP # TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC # AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp # Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv # bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0 # aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB # LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc # Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov # Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy # oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW # juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF # mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z # twGpn1eqXijiuZQwggauMIIElqADAgECAhAHNje3JFR82Ees/ShmKl5bMA0GCSqG # SIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx # GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy # dXN0ZWQgUm9vdCBHNDAeFw0yMjAzMjMwMDAwMDBaFw0zNzAzMjIyMzU5NTlaMGMx # CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMy # RGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcg # Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGhjUGSbPBPXJJUVXH # JQPE8pE3qZdRodbSg9GeTKJtoLDMg/la9hGhRBVCX6SI82j6ffOciQt/nR+eDzMf # UBMLJnOWbfhXqAJ9/UO0hNoR8XOxs+4rgISKIhjf69o9xBd/qxkrPkLcZ47qUT3w # 1lbU5ygt69OxtXXnHwZljZQp09nsad/ZkIdGAHvbREGJ3HxqV3rwN3mfXazL6IRk # tFLydkf3YYMZ3V+0VAshaG43IbtArF+y3kp9zvU5EmfvDqVjbOSmxR3NNg1c1eYb # qMFkdECnwHLFuk4fsbVYTXn+149zk6wsOeKlSNbwsDETqVcplicu9Yemj052FVUm # cJgmf6AaRyBD40NjgHt1biclkJg6OBGz9vae5jtb7IHeIhTZgirHkr+g3uM+onP6 # 5x9abJTyUpURK1h0QCirc0PO30qhHGs4xSnzyqqWc0Jon7ZGs506o9UD4L/wojzK # QtwYSH8UNM/STKvvmz3+DrhkKvp1KCRB7UK/BZxmSVJQ9FHzNklNiyDSLFc1eSuo # 80VgvCONWPfcYd6T/jnA+bIwpUzX6ZhKWD7TA4j+s4/TXkt2ElGTyYwMO1uKIqjB # Jgj5FBASA31fI7tk42PgpuE+9sJ0sj8eCXbsq11GdeJgo1gJASgADoRU7s7pXche # MBK9Rp6103a50g5rmQzSM7TNsQIDAQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB # /wIBADAdBgNVHQ4EFgQUuhbZbU2FL3MpdpovdYxqII+eyG8wHwYDVR0jBBgwFoAU # 7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoG # CCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29j # c3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdp # Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDig # NqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v # dEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZI # hvcNAQELBQADggIBAH1ZjsCTtm+YqUQiAX5m1tghQuGwGC4QTRPPMFPOvxj7x1Bd # 4ksp+3CKDaopafxpwc8dB+k+YMjYC+VcW9dth/qEICU0MWfNthKWb8RQTGIdDAiC # qBa9qVbPFXONASIlzpVpP0d3+3J0FNf/q0+KLHqrhc1DX+1gtqpPkWaeLJ7giqzl # /Yy8ZCaHbJK9nXzQcAp876i8dU+6WvepELJd6f8oVInw1YpxdmXazPByoyP6wCeC # RK6ZJxurJB4mwbfeKuv2nrF5mYGjVoarCkXJ38SNoOeY+/umnXKvxMfBwWpx2cYT # gAnEtp/Nh4cku0+jSbl3ZpHxcpzpSwJSpzd+k1OsOx0ISQ+UzTl63f8lY5knLD0/ # a6fxZsNBzU+2QJshIUDQtxMkzdwdeDrknq3lNHGS1yZr5Dhzq6YBT70/O3itTK37 # xJV77QpfMzmHQXh6OOmc4d0j/R0o08f56PGYX/sr2H7yRp11LB4nLCbbbxV7HhmL # NriT1ObyF5lZynDwN7+YAN8gFk8n+2BnFqFmut1VwDophrCYoCvtlUG3OtUVmDG0 # YgkPCr2B2RP+v6TR81fZvAT6gt4y3wSJ8ADNXcL50CN/AAvkdgIm2fBldkKmKYcJ # RyvmfxqkhQ/8mJb2VVQrH4D6wPIOK+XW+6kvRBVK5xMOHds3OBqhK/bt1nz8MIIG # sDCCBJigAwIBAgIQCK1AsmDSnEyfXs2pvZOu2TANBgkqhkiG9w0BAQwFADBiMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw # HhcNMjEwNDI5MDAwMDAwWhcNMzYwNDI4MjM1OTU5WjBpMQswCQYDVQQGEwJVUzEX # MBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0 # ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMIICIjAN # BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1bQvQtAorXi3XdU5WRuxiEL1M4zr # PYGXcMW7xIUmMJ+kjmjYXPXrNCQH4UtP03hD9BfXHtr50tVnGlJPDqFX/IiZwZHM # gQM+TXAkZLON4gh9NH1MgFcSa0OamfLFOx/y78tHWhOmTLMBICXzENOLsvsI8Irg # nQnAZaf6mIBJNYc9URnokCF4RS6hnyzhGMIazMXuk0lwQjKP+8bqHPNlaJGiTUyC # EUhSaN4QvRRXXegYE2XFf7JPhSxIpFaENdb5LpyqABXRN/4aBpTCfMjqGzLmysL0 # p6MDDnSlrzm2q2AS4+jWufcx4dyt5Big2MEjR0ezoQ9uo6ttmAaDG7dqZy3SvUQa # khCBj7A7CdfHmzJawv9qYFSLScGT7eG0XOBv6yb5jNWy+TgQ5urOkfW+0/tvk2E0 # XLyTRSiDNipmKF+wc86LJiUGsoPUXPYVGUztYuBeM/Lo6OwKp7ADK5GyNnm+960I # HnWmZcy740hQ83eRGv7bUKJGyGFYmPV8AhY8gyitOYbs1LcNU9D4R+Z1MI3sMJN2 # FKZbS110YU0/EpF23r9Yy3IQKUHw1cVtJnZoEUETWJrcJisB9IlNWdt4z4FKPkBH # X8mBUHOFECMhWWCKZFTBzCEa6DgZfGYczXg4RTCZT/9jT0y7qg0IU0F8WD1Hs/q2 # 7IwyCQLMbDwMVhECAwEAAaOCAVkwggFVMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYD # VR0OBBYEFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB8GA1UdIwQYMBaAFOzX44LScV1k # TN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcD # AzB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2lj # ZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29t # L0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0 # cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmww # HAYDVR0gBBUwEzAHBgVngQwBAzAIBgZngQwBBAEwDQYJKoZIhvcNAQEMBQADggIB # ADojRD2NCHbuj7w6mdNW4AIapfhINPMstuZ0ZveUcrEAyq9sMCcTEp6QRJ9L/Z6j # fCbVN7w6XUhtldU/SfQnuxaBRVD9nL22heB2fjdxyyL3WqqQz/WTauPrINHVUHmI # moqKwba9oUgYftzYgBoRGRjNYZmBVvbJ43bnxOQbX0P4PpT/djk9ntSZz0rdKOtf # JqGVWEjVGv7XJz/9kNF2ht0csGBc8w2o7uCJob054ThO2m67Np375SFTWsPK6Wrx # oj7bQ7gzyE84FJKZ9d3OVG3ZXQIUH0AzfAPilbLCIXVzUstG2MQ0HKKlS43Nb3Y3 # LIU/Gs4m6Ri+kAewQ3+ViCCCcPDMyu/9KTVcH4k4Vfc3iosJocsL6TEa/y4ZXDlx # 4b6cpwoG1iZnt5LmTl/eeqxJzy6kdJKt2zyknIYf48FWGysj/4+16oh7cGvmoLr9 # Oj9FpsToFpFSi0HASIRLlk2rREDjjfAVKM7t8RhWByovEMQMCGQ8M4+uKIw8y4+I # Cw2/O/TOHnuO77Xry7fwdxPm5yg/rBKupS8ibEH5glwVZsxsDsrFhsP2JjMMB0ug # 0wcCampAMEhLNKhRILutG4UI4lkNbcoFUCvqShyepf2gpx8GdOfy1lKQ/a+FSCH5 # Vzu0nAPthkX0tGFuv2jiJmCG6sivqf6UHedjGzqGVnhOMIIGwjCCBKqgAwIBAgIQ # BUSv85SdCDmmv9s/X+VhFjANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEX # MBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0 # ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMB4XDTIzMDcxNDAw # MDAwMFoXDTM0MTAxMzIzNTk1OVowSDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRp # Z2lDZXJ0LCBJbmMuMSAwHgYDVQQDExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMzCC # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKNTRYcdg45brD5UsyPgz5/X # 5dLnXaEOCdwvSKOXejsqnGfcYhVYwamTEafNqrJq3RApih5iY2nTWJw1cb86l+uU # UI8cIOrHmjsvlmbjaedp/lvD1isgHMGXlLSlUIHyz8sHpjBoyoNC2vx/CSSUpIIa # 2mq62DvKXd4ZGIX7ReoNYWyd/nFexAaaPPDFLnkPG2ZS48jWPl/aQ9OE9dDH9kgt # XkV1lnX+3RChG4PBuOZSlbVH13gpOWvgeFmX40QrStWVzu8IF+qCZE3/I+PKhu60 # pCFkcOvV5aDaY7Mu6QXuqvYk9R28mxyyt1/f8O52fTGZZUdVnUokL6wrl76f5P17 # cz4y7lI0+9S769SgLDSb495uZBkHNwGRDxy1Uc2qTGaDiGhiu7xBG3gZbeTZD+BY # QfvYsSzhUa+0rRUGFOpiCBPTaR58ZE2dD9/O0V6MqqtQFcmzyrzXxDtoRKOlO0L9 # c33u3Qr/eTQQfqZcClhMAD6FaXXHg2TWdc2PEnZWpST618RrIbroHzSYLzrqawGw # 9/sqhux7UjipmAmhcbJsca8+uG+W1eEQE/5hRwqM/vC2x9XH3mwk8L9CgsqgcT2c # kpMEtGlwJw1Pt7U20clfCKRwo+wK8REuZODLIivK8SgTIUlRfgZm0zu++uuRONhR # B8qUt+JQofM604qDy0B7AgMBAAGjggGLMIIBhzAOBgNVHQ8BAf8EBAMCB4AwDAYD # VR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAgBgNVHSAEGTAXMAgG # BmeBDAEEAjALBglghkgBhv1sBwEwHwYDVR0jBBgwFoAUuhbZbU2FL3MpdpovdYxq # II+eyG8wHQYDVR0OBBYEFKW27xPn783QZKHVVqllMaPe1eNJMFoGA1UdHwRTMFEw # T6BNoEuGSWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRH # NFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcmwwgZAGCCsGAQUFBwEBBIGD # MIGAMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wWAYIKwYB # BQUHMAKGTGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0 # ZWRHNFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcNAQEL # BQADggIBAIEa1t6gqbWYF7xwjU+KPGic2CX/yyzkzepdIpLsjCICqbjPgKjZ5+PF # 7SaCinEvGN1Ott5s1+FgnCvt7T1IjrhrunxdvcJhN2hJd6PrkKoS1yeF844ektrC # QDifXcigLiV4JZ0qBXqEKZi2V3mP2yZWK7Dzp703DNiYdk9WuVLCtp04qYHnbUFc # jGnRuSvExnvPnPp44pMadqJpddNQ5EQSviANnqlE0PjlSXcIWiHFtM+YlRpUurm8 # wWkZus8W8oM3NG6wQSbd3lqXTzON1I13fXVFoaVYJmoDRd7ZULVQjK9WvUzF4UbF # KNOt50MAcN7MmJ4ZiQPq1JE3701S88lgIcRWR+3aEUuMMsOI5ljitts++V+wQtaP # 4xeR0arAVeOGv6wnLEHQmjNKqDbUuXKWfpd5OEhfysLcPTLfddY2Z1qJ+Panx+VP # NTwAvb6cKmx5AdzaROY63jg7B145WPR8czFVoIARyxQMfq68/qTreWWqaNYiyjvr # moI1VygWy2nyMpqy0tg6uLFGhmu6F/3Ed2wVbK6rr3M66ElGt9V/zLY4wNjsHPW2 # obhDLN9OTH0eaHDAdwrUAuBcYLso/zjlUlrWrBciI0707NMX+1Br/wd3H3GXREHJ # uEbTbDJ8WC9nR2XlG3O2mflrLAZG70Ee8PBf4NvZrZCARK+AEEGKMIIHVjCCBT6g # AwIBAgIQDBXwscbz14x9ek55doBnRzANBgkqhkiG9w0BAQ0FADBpMQswCQYDVQQG # EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0 # IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0Ex # MB4XDTI0MDMxMjAwMDAwMFoXDTI1MDMxMjIzNTk1OVowXjELMAkGA1UEBhMCREUx # HzAdBgNVBAcTFkdhcm1pc2NoLVBhcnRlbmtpcmNoZW4xFjAUBgNVBAoTDU1hbnVl # bCBUYW56ZXIxFjAUBgNVBAMTDU1hbnVlbCBUYW56ZXIwggIiMA0GCSqGSIb3DQEB # AQUAA4ICDwAwggIKAoICAQCTsOVLH5jtnViI9CzKdwLIOODRJZAZlTZ6g0fCkQmJ # R44iMkFBK8/O46dckAy/OLWKIGPXuatA/FpylNeSKLeqDusFTELqVgOaFPr7qr6m # F6Y1b1NTv9139cNd2tBEkAbwWxJdzsoVGHjneejsC/u7VazQDiOHRYFJj//yrX02 # T5jFIO38sme77dAgGTfxl+E8yEq5Xzza38sw206dYA3OpX7MQsLl8TjXHkuWC/PK # nc1FRMCfenDYq8KEtUT2b4R4EluRbs9T1ZePZ5kl1pCMsr94CicDfMOuF5QWsqAh # xdEfzpfecVTq0u/NTBd6CzTtyFE8qHSu1yckU6qlcCJXjqSoAcLKZS1J/Qil2eUb # /cbwtupGlx8RCj1OzA0A9rZYmrYk4AeYQEAXOr2dPDVCN0zKPcOkKlNPFDbe8mqX # 6y+h/9Czg1EDwPFP23HKD0bGC8L5G5NHxqPezcdukGKoqtSeQy81lR3GYdiNV5wt # YyPDcSjxgkII6ZHedg6GMGIVCL/0NHh6EXE8SJgXX+JIvjChetUZEsF18ro2VZKj # 4hW6FzK+0HUgyeFsdU6CoWQB097UC5uPaeWyXTIkskG3m+8KvUZp88t6a+K9JI4/ # 26/o77m6WTsnVoXIOGfUlhXmu/vPc5DKwxBTMA5IcGPPJrd4pM27m8niGnzkVq/i # jwIDAQABo4ICAzCCAf8wHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0TkIw # HQYDVR0OBBYEFA630pXEHsvRNF7iqqyeERyJpcd0MD4GA1UdIAQ3MDUwMwYGZ4EM # AQQBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAO # BgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwgbUGA1UdHwSBrTCB # qjBToFGgT4ZNaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3Rl # ZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcmwwU6BRoE+GTWh0 # dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWdu # aW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3JsMIGUBggrBgEFBQcBAQSBhzCBhDAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwGCCsGAQUFBzAC # hlBodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRD # b2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJBgNVHRMEAjAAMA0G # CSqGSIb3DQEBDQUAA4ICAQCrfVGhAbhMkdZAwsrSd4rsmwJWGlNbwnimYvs0xcB4 # A5QiwyPJ6cPibEEdU7soXow25Dk7DHltqlNpJP8eO/IGbmSBtqQPo9oxcNtrs/Hm # FbJh8wKyJ2OtwRi2y7pXxWZZekIvecJ/afSzbs9BEWo2DcmjknYCZkRZmO9CWdjU # 8sVIzBq3zUHsF8gXtm8Tp7kp6Ceo5lKoW8JbOM6RnA0ySj2iGagnQo++3qiH3u/C # GtOlxlz5TR2J3FKXa6Kq3adGm7tSoajN121uEmmo2AoU0gLoQwAxEb4o0czrgNya # /P34G8Tep8Wgq+wzE0KEWLWfJ4Q1u5pMPfAyKUiY6HU2tIpQEN2BKF0tSeRyGdQz # 0p6b4k0+R5dCU3QlbuM2TbU87Nu4ZxS6IiN19qZkxEZN5LPDhS8d6BNQy34uuugg # I/M/iKQCcBtreWEkXZ+DSMCE2D7ElfsqPqkEYemxuIN/MA3RWdlZeFzafNJErQo6 # O/MWmmrvCYunX0i+evzTO4/L7XT+Lldg1Q1psAZfowqGM691aWR6mtd+OX76O1cB # 79IWvHl8ObNQpR5P9U++sn6r20uaWfvK7tliH0LSPLYPfDBsD09VUSx+xHy9h2W2 # KWnX6nd5VU0ig36EaT153pqX54I49b8vj+b+5JcNHeqEV8B6+6xfr1CIux1GgYnL # 1jGCBlMwggZPAgEBMH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0 # LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmlu # ZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMQIQDBXwscbz14x9ek55doBnRzANBglg # hkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3 # DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEV # MC8GCSqGSIb3DQEJBDEiBCA4w9UOpwWwPOnxznhaLRevFTtnC422PmrgzTbi7vOm # lDANBgkqhkiG9w0BAQEFAASCAgBbayAb+l+9nco8bSkrBIi0RiCZWd75qgVNlJhc # e0+9X46PY3Oqt7FUudXBxpUGS5yMfYvOKQB+Nm45OvifwkMhdTR4IUuUBtAgQFpm # 5Qr/kzIXbqGLGEEmrVuHXTmETWpFxct3pOZDhAl3vMGFyuwCRlDTxi28dLqFrCkm # gFH5QPPqguYmQJgmOTDXWDEeQIgNftUU3AwmLyprFxnHExdDTlC+5F3mY6q0fIR1 # 1EiSf3KSVR9UYPZSBMI4JGT6WLsvCFam5yII9OAVKh+YnJG4TXLrcgYRDyamzhUK # qMFEZ5/emD93f0EMs8KswTX331kmEcCMVKHtad3bdrB1dE7b2yyOP4G2uSPo+RFN # 2vSUhLNgEV3Mwff5X+Cz9A/IoTBrUarJpx9izMcVjEPmPG8YbJxegqQfZcL9ZzND # NeTphAEjHJi5sbBohQBFjpiW5PAzrTbJSwoM8W2EbgpSYSL/n+TicH6yyRgims4t # v0AvO37l7RsbvlpUh9YTYKyD5S3BI3AreyUP5q3J1SlBMb+cWc0FSP8cJ49YdmCR # dqftRGFe+zeYwIX+hukqXbpgj60R9m1/NbmTNTloqiOEpEzfIxULXuuCzSAcUvCW # hOxqTNqtqHdQ1jqUpid7lAMrZTtijuUklDV9H5ihYEeuUxmSQMB2bB0BZVrhVoEK # YhGpYqGCAyAwggMcBgkqhkiG9w0BCQYxggMNMIIDCQIBATB3MGMxCzAJBgNVBAYT # AlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQg # VHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0ECEAVEr/OU # nQg5pr/bP1/lYRYwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZI # hvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNDA0MjgxNzUwMzZaMC8GCSqGSIb3DQEJ # BDEiBCDTtygHuIMcddJ5kLjYRk8i8pocVBVPKzDxYVAO8kb5ZDANBgkqhkiG9w0B # AQEFAASCAgBFBfPIIEQq4dXLohp1WKTdJRpJD31Cd55bS/X+Qy0A1pvlXhbJNV7Q # lmB45UdJL4an1CrOdlM1ObtBSkX5hz9ATUIHYMmrHNHOslTYgQD8/DFDU1MjVnwV # CGNyELjQr49mPLZ4HLdsdS5Qy3OOzdQtGcbVwrBd08TeQ9Os8C2LzJZiAffzj/QR # lAGGus6MqdggV9uHOWTl5Bt+18hzqOEeLUNeqpjUsgUf9rdPIJfs5r9a9rNTBKkp # KCImdx7ucygM3KkUjznpKK4Lkik9sJz7652ywpndbppUCEEgwWlBMk6gYtom0URB # xov6GkZauW8pNVF7WUa6vU36VghpjvqdZeBd0rZjov3WRTSnQ+M4oeD5Ys6YAMKK # AN72rwpdeJGCsfdffNc0ibcgCtz4r7qYJb5pMtoOliOEtZqpRg1GFGSSQ3RAl0+3 # /AuEgb+82p52pF1ONZQRgRRa1Qxwpdu5eCUt2aaKob2G98eG/g0hIpHqy6zjLGPO # bt+LTvL3Jl3+IbOJ/wBuOTvYHnzOwqAN5GKKmfsBrttC0xKBN45BOwa17tu29Q45 # vzg3lz5Gwf0YV0OMdO7pfnSMBrS2Z6ooSGUl7AI09olGX2V3eyhFPZ/pFDnI9aGA # zQY7vdNq7WxNbm1IMVXv1HcKxZlf+pKGz8vV8IDN2P9YeZ5mM5wHbg== # SIG # End signature block |