Classes/reporting.psm1
<#
.SYNOPSIS Common Reporting functions across all modules/scenarios .DESCRIPTION Logging, Reporting .INPUTS Inputs (if any) .OUTPUTS Output (if any) .NOTES General notes #> function Set-AzStackHciOutputPath { param ($Path, $Source='azshciarc/Diagnostic') if ([string]::IsNullOrEmpty($Path)) { $Path = Join-Path -Path $HOME -ChildPath ".AzStackHci" } $Global:AzStackHciArcInstallerLogFile = Join-Path -Path $Path -ChildPath 'AzStackHciArcIntegration.log' Assert-EventLog -source $Source Set-AzStackHciIdentifier } function Log-Info { <# .SYNOPSIS Write verbose logging to disk .DESCRIPTION Formats and writes verbose logging to disk under scriptroot. Log type (or severity) is essentially cosmetic to the verbose log file, no action should be inferred, such as termination of the script. .EXAMPLE Write-AzStackHciEnvironmentLog -Message ('Script messaging include data {0}' -f $data) -Type 'Info|Warning|Error' -Function 'FunctionName' .INPUTS Message - a string of the body of the log entry Type - a cosmetic type or severity for the message, must be info, warning or error Function - ideally the name of the function or the script writing the log entry. .OUTPUTS Appends Log entry to AzStackHciArcIntegration.log under the script root. .NOTES General notes #> [cmdletbinding()] param( [string] $Message, [ValidateSet('Info', 'Warning', 'Error', 'Success')] [string] $Type = 'Info', [ValidateNotNullOrEmpty()] [string]$Function = ((Get-PSCallStack)[0].Command), [switch]$ConsoleOut, [switch]$Telemetry ) $Message = RunMask $Message if ($ConsoleOut) { if ($true) { switch -wildcard ($function) { '*-AzStackHciArc*' { $foregroundcolor = 'DarkYellow' } default { $foregroundcolor = "White" } } switch ($Type) { 'Success' { $foregroundcolor = 'Green' } 'Warning' { $foregroundcolor = 'Yellow' } 'Error' { $foregroundcolor = 'Red' } default { $foregroundcolor = "White" } } Write-Host $message -ForegroundColor $foregroundcolor } else { Write-Host $message } } else { Write-Verbose $message } if (-not [string]::IsNullOrEmpty($message)) { # Log to ETW if ($Telemetry) { $source = "azshciarc/Telemetry" $EventId = 17201 } else { $source = "azshciarc/Operational" $EventId = 17203 } $logName = 'azshciarc' $EventType = switch ($Type) { "Error" { "Error" } "Warning" { "Warning" } "Success" { "Information" } "Info" { "Information" } Default { "Information" } } # Only write telemetry or non-info entries to the eventlog to save time and noise. if ($Telemetry -or $EventType -ne "Information") { Write-ETWLog -Source $Source -logName $logName -Message $Message -EventType $EventType -EventId $EventId } # Log to file $entry = "[{0}] [{1}] [{2}] {3}" -f ([datetime]::now).tostring(), $type, $function, ($Message -replace "`n|`t", "") if (-not (Test-Path $AzStackHciArcInstallerLogFile)) { New-Item -Path $AzStackHciArcInstallerLogFile -Force | Out-Null } $retries = 3 for ($i = 1; $i -le $retries; $i++) { try { $entry | Out-File -FilePath $AzStackHciArcInstallerLogFile -Append -Force -Encoding UTF8 $writeFailed = $false break } catch { $writeFailed = "Log-info $i/$retries failed: $($_.ToString())" start-sleep -Seconds 5 } } if ($writeFailed) { throw $writeFailed } } } function RunMask { [cmdletbinding()] [OutputType([string])] Param ( [Parameter(ValueFromPipeline = $True)] [string] $in ) Begin {} Process { try { <#$in | Get-PIIMask | Get-GuidMask#> $in | Get-GuidMask } catch { $_.exception } } End {} } function Get-PIIMask { [cmdletbinding()] [OutputType([string])] Param ( [Parameter(ValueFromPipeline = $True)] [string] $in ) Begin { $pii = $($ENV:USERDNSDOMAIN), $($ENV:COMPUTERNAME), $($ENV:USERNAME), $($ENV:USERDOMAIN) | ForEach-Object { if ($null -ne $PSITEM) { $PSITEM } } $r = $pii -join '|' } Process { try { return [regex]::replace($in, $r, "[*redacted*]") } catch { $_.exception } } End {} } function Get-GuidMask { [OutputType([string])] [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $True)] [String] $guid ) Begin { $r = [regex]::new("(-([a-fA-F0-9]{4}-){3})") } Process { try { return [regex]::replace($guid, $r, "-xxxx-xxxx-xxxx-") } catch { $_.exception } } End {} } function Write-AzStackHciHeader { <# .SYNOPSIS Write invocation and system information into log and writes cmdlet name and version to screen. #> param ( [Parameter()] [System.Management.Automation.InvocationInfo] $invocation, [psobject] $params, [switch] $PassThru ) try { $paramToString = ($params.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join ';' $cmdLetName = Get-CmdletName $cmdletVersion = (Get-Command $cmdletName -ErrorAction SilentlyContinue).version.tostring() Log-Info -Message '' Log-Info -Message ('{0} v{1} started.' -f ` $cmdLetName, $cmdletVersion) ` -ConsoleOut:(-not $PassThru) #TODO: Need to fix module name Log-Info -Telemetry -Message ('{0} started version: {1} with parameters: {2}. Id:{3}' ` -f $cmdLetName, (Get-Module AzStackHci.EnvironmentChecker).Version.ToString(), $paramToString, $ENV:EnvChkrId) Log-Info -Message ('OSVersion: {0} PSVersion: {1} PSEdition: {2} Security Protocol: {3} Lanaguage Mode: {4}' -f ` [environment]::OSVersion.Version.tostring(), $PSVersionTable.PSVersion.tostring(), $PSEdition, [Net.ServicePointManager]::SecurityProtocol, $ExecutionContext.SessionState.LanguageMode) Write-PsSessionInfo -params $params } catch { if (-not $PassThru) { Log-Info ("Unable to write header to screen. Error: {0}" -f $_.exception.message) } } } function Write-AzStackHciArcInstallerFooter { <# .SYNOPSIS Writes report, log and cmdlet to screen. #> param ( [Parameter()] [System.Management.Automation.InvocationInfo] $invocation, [switch] $failed, [switch] $PassThru ) Log-Info -Message ("`nLog location: $AzStackHciArcInstallerLogFile") -ConsoleOut:(-not $PassThru) # Log-Info -Message ("Report location: $AzStackHciEnvironmentReport") -ConsoleOut:(-not $PassThru) # Log-Info -Message ("Use -Passthru parameter to return results as a PSObject.") -ConsoleOut:(-not $PassThru) if ($failed) { Log-Info -Message ("{0} failed" -f (Get-CmdletName)) -ConsoleOut:(-not $PassThru) -Type Error -Telemetry } else { Log-Info -Message ("{0} completed. Id:{1} " -f (Get-CmdletName),$ENV:EnvChkrId) -Telemetry } } function Get-CmdletName { try { foreach ($c in (Get-PSCallStack).Command) { $functionCalled = Select-String -InputObject $c -Pattern "Invoke-AzStackHci(.*)Validation" if ($functionCalled) { break } } $functionCalled } catch { throw "Hci Validation" } } function Write-ETWLog { [CmdletBinding()] param ( [Parameter()] [string] $source = 'azshciarc/Diagnostic', [Parameter()] [string] $logName = 'azshciarc', [Parameter(Mandatory = $true)] [string] $Message, [Parameter()] [string] $EventId = 0, [Parameter()] [string] $EventType = 'Information' ) try { Write-EventLog -LogName $LogName -Source $Source -EntryType $EventType -Message $Message -EventId $EventId } catch { throw "Creating event log failed. Error $($_.exception.message)" } } function Assert-EventLog { param ( [Parameter()] [string] $source = 'azshciarc/Diagnostic' ) try { $eventLog = Get-EventLog -LogName azshciarc -Source $Source -ErrorAction SilentlyContinue } catch {} # Try to create the log if (-not $eventLog) { New-AzStackHciArcIntegrationLog } } function Test-Elevation { return ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } function New-AzStackHciArcIntegrationLog { try { $scriptBlock = { $logName = 'azshciarc' $sources = @('azshciarc/Operational', 'azshciarc/Diagnostic', 'azshciarc/Telemetry') foreach ($source in $sources) { New-EventLog -LogName $logName -Source $Source -ErrorAction SilentlyContinue Limit-EventLog -LogName $logName -MaximumSize 250MB -ErrorAction SilentlyContinue Write-EventLog -Message ('Initializing log provider {0}' -f $source) -EventId 0 -EntryType Information -Source $source -LogName $logName -ErrorAction Stop } } if (Test-Elevation) { Invoke-Command -ScriptBlock $scriptBlock } else { $psProcess = if (Join-Path -Path $PSHOME -ChildPath powershell.exe -Resolve -ErrorAction SilentlyContinue) { Join-Path -Path $PSHOME -ChildPath powershell.exe } elseif (Join-Path -Path $PSHOME -ChildPath pwsh.exe -Resolve -ErrorAction SilentlyContinue) { Join-Path -Path $PSHOME -ChildPath pwsh.exe } else { throw "Cannot find powershell process. Please run powershell elevated and run the following command: 'New-EventLog -LogName $logName -Source $sourceName'" } Write-Warning "We need to run an elevated process to register our event log. `nPlease continue and accept the UAC prompt to continue. `nAlternatively, run: `nNew-EventLog -LogName $logName -Source $source `nmanually and restart this command." if (Grant-UACConcent) { Start-Process $psProcess -Verb Runas -ArgumentList "-command (Invoke-Command -ScriptBlock {$scriptBlock})" -Wait } else { throw "Unable to elevate and register event log provider." } } } catch { throw "Failed to create Environment Checker log. Error: $($_.Exception.Message)" } } function Remove-AzStackHciArcIntegrationEventLog { <# .SYNOPSIS Remove AzStackHCI Environment Checker event log .EXAMPLE Remove-AzStackHciArcIntegrationEventLog -Verbose Remove AzStackHCI Environment Checker event log #> [cmdletbinding()] param() Remove-EventLog -LogName "azshciarc" } function Grant-UACConcent { $concentAnswered = $false $concent = $false while ($false -eq $concentAnswered) { $promptResponse = Read-Host -Prompt "Register the event log. (Y/N)" if ($promptResponse -imatch '^y$|^yes$') { $concentAnswered = $true $concent = $true } elseif ($promptResponse -imatch '^n$|^no$') { $concentAnswered = $true $concent = $false } else { Write-Warning "Unexpected response" } } return $concent } function Write-Summary { param ($result, $property1, $property2, $property3, $seperator = '->') try { $summary = Get-Summary @PSBoundParameters # Write percentage Write-Host "`nSummary" Write-Host $lTxt.Summary if (-not ([string]::IsNullOrEmpty($summary.FailedResourceCritical))) { Write-Host " " -NoNewline Write-StatusSymbol -status 'Failed' -Severity Critical Write-Host (" {0} Critical Issue(s)" -f @($summary.FailedResourceCritical).Count) } if (-not ([string]::IsNullOrEmpty($summary.FailedResourceWarning))) { Write-Host " " -NoNewline Write-StatusSymbol -status 'Failed' -Severity Warning Write-Host (" {0} Warning Issue(s)" -f @($summary.FailedResourceWarning).Count) } if (-not ([string]::IsNullOrEmpty($summary.FailedResourceInformational))) { Write-Host " " -NoNewline Write-StatusSymbol -status 'Failed' -Severity Informational Write-Host (" {0} Informational Issue(s)" -f @($summary.FailedResourceInformational).Count) } if ($Summary.successCount -gt 0) { Write-Host " " -NoNewline Write-StatusSymbol -status 'Succeeded' Write-Host (" {0} successes" -f ($Summary.successCount)) } <#Write-Host @expandDownSymbol Write-Host " " -NoNewline switch ($Severity) { 'Critical' { Write-Host @redCrossSymbol } 'Warning' { Write-Host @warningSymbol } Default { Write-Host @redCrossSymbol } }#> #Write-Host (" {0} / {1} ({2}%)" -f $summary.SuccessCount, $Result.AdditionalData.Resource.Count, $summary.SuccessPercentage) # Write issues by severity foreach ($severity in 'Critical', 'Warning', 'Informational') { $SeverityProp = "FailedResource{0}" -f $severity $failedResources = $summary.$SeverityProp | Sort-Object | Get-Unique if ($failedResources -gt 0) { Write-Host "" Write-Severity -severity $Severity Write-Host "" #Write-Host "`n$Severity Issues:" $failedResources | Sort-Object | Get-Unique | ForEach-Object { Write-Host " " -NoNewline switch ($Severity) { 'Critical' { Write-Host @redCrossSymbol } 'Warning' { Write-Host @warningSymbol } Default { Write-Host @redCrossSymbol } } Write-Host " $PSITEM" } } } if ($Summary.HelpLinks) { Write-Host "`nRemediation: " $Summary.HelpLinks | ForEach-Object { Write-Host " " -NoNewline Write-Host @helpSymbol Write-Host " $PSITEM" } } if (-not $summary.FailedResourceCritical -and -not $summary.FailedResourceWarning -and -not $summary.FailedResourceInformational) { Write-Host "`nSummary" Write-Host @expandOutSymbol Write-Host " " -NoNewline Write-Host @greenTickSymbol Write-Host (" {0} / {1} ({2}%) resources test successfully." -f $summary.SuccessCount, $Result.AdditionalData.Resource.Count, $summary.SuccessPercentage) } } catch { Log-Info -Message "Summary failed. $($_.Exception.Message)" -ConsoleOut -Type Warning } } function Get-Summary { param ($result, $property1, $property2, $property3, $seperator = '->') try { if (-not $result) { throw "Unable to write summary. Check tests run successfully." } [array]$success = $result | Select-Object -ExpandProperty AdditionalData | Where-Object Status -EQ 'Succeeded' [array]$HelpLinks = $result | Where-Object Status -NE 'Succeeded' | Select-Object -ExpandProperty Remediation | Sort-Object | Get-Unique [array]$nonSuccess = $result | Select-Object -ExpandProperty AdditionalData | Where-Object Status -NE 'Succeeded' [array]$nonSuccessCritical = $result | Where-Object Severity -EQ Critical | Select-Object -ExpandProperty AdditionalData | Where-Object Status -NE 'Succeeded' [array]$nonSuccessWarning = $result | Where-Object Severity -EQ Warning | Select-Object -ExpandProperty AdditionalData | Where-Object Status -NE 'Succeeded' [array]$nonSuccessInformational = $result | Where-Object Severity -EQ Informational | Select-Object -ExpandProperty AdditionalData | Where-Object Status -NE 'Succeeded' $successPercentage = if ($success.count -gt 0) { [Math]::Round(($success.Count / $result.AdditionalData.Resource.count) * 100) } else { 0 } $sourceDestsb = { if ([string]::IsNullOrEmpty($_.$property2) -and [string]::IsNullOrEmpty($_.$property3)) { "{0}" -f $_.$property1 } elseif ([string]::IsNullOrEmpty($_.$property3)) { "{0}{1}{2}" -f $_.$property1, $seperator, $_.$property2 } else { "{0}{1}{2}({3})" -f $_.$property1, $seperator, $_.$property2, $_.$property3 } } $FailedResourceCritical = $nonSuccessCritical | Select-Object @{ label = 'SourceDest'; Expression = $sourceDestsb } -ErrorAction SilentlyContinue | Select-Object -ExpandProperty SourceDest | Sort-Object | Get-Unique $FailedResourceWarning = $nonSuccessWarning | Select-Object @{ label = 'SourceDest'; Expression = $sourceDestsb } -ErrorAction SilentlyContinue | Select-Object -ExpandProperty SourceDest | Sort-Object | Get-Unique $FailedResourceInformational = $nonSuccessInformational | Select-Object @{ label = 'SourceDest'; Expression = $sourceDestsb } -ErrorAction SilentlyContinue | Select-Object -ExpandProperty SourceDest | Sort-Object | Get-Unique $summary = New-Object -Type PsObject -Property @{ successCount = $success.Count nonSuccessCount = $nonSuccess.Count successPercentage = $successPercentage HelpLinks = $HelpLinks FailedResourceCritical = $FailedResourceCritical FailedResourceWarning = $FailedResourceWarning FailedResourceInformational = $FailedResourceInformational } return $summary } catch { throw "Unable to calculate summary. Error $($_.exception.message)" } } # Symbols $global:greenTickSymbol = @{ Object = [Char]0x2713 #8730 ForegroundColor = 'Green' NoNewLine = $true } $global:redCrossSymbol = @{ Object = [Char]0x2622 #0x00D7 ForegroundColor = 'Red' NoNewLine = $true } $global:WarningSymbol = @{ Object = [char]0x26A0 ForegroundColor = 'Yellow' NoNewLine = $true } $global:bulletSymbol = @{ Object = [Char]0x25BA NoNewLine = $true } # Text $global:needsAttention = @{ object = $lTxt.NeedsAttention; ForegroundColor = 'Yellow' NoNewLine = $true } $global:needsRemediation = @{ object = $lTxt.NeedsRemediation; ForegroundColor = 'Red' NoNewLine = $true } $global:ForInformation = @{ object = $lTxt.ForInformation; NoNewLine = $true } $global:expandDownSymbol = @{ object = [Char]0x25BC # expand down NoNewLine = $true } $global:expandOutSymbol = @{ object = [Char]0x25BA # expand out NoNewLine = $true } $global:helpSymbol = @{ object = [char]0x270E #0x263C # sunshine NoNewLine = $true #ForegroundColor = 'Yellow' } $global:Critical = @{ object = $lTxt.Critical; ForegroundColor = 'Red' NoNewLine = $true } $global:Warning = @{ object = $lTxt.Warning; ForegroundColor = 'Yellow' NoNewLine = $true } $global:Information = @{ object = $lTxt.Informational; NoNewLine = $true } $global:isHealthy = @{ object = $lTxt.Healthy NoNewLine = $true } function Write-StatusSymbol { param ($status, $severity) switch ($status) { "Succeeded" { Write-Host @greenTickSymbol } "Failed" { switch ($Severity) { 'Critical' { Write-Host @redCrossSymbol } 'Warning' { Write-Host @warningSymbol } Default { Write-Host @redCrossSymbol } } } Default { Write-Host @bulletSymbol } } } function Write-Severity { param ($severity) switch ($severity) { 'Critical' { Write-Host @needsRemediation } 'Warning' { Write-Host @needsAttention } 'Informational' { Write-Host @ForInformation } Default { Write-Host @Critical } } } function Set-AzStackHciIdentifier { $ENV:EnvChkrId = $null if ([string]::IsNullOrEmpty($ENV:EnvChkrOp)) { $ENV:EnvChkrOp = 'Manual' } $validatorCmd = Get-CmdletName if(-not [string]::IsNullOrWhiteSpace($validatorCmd)) { $ENV:EnvChkrId = "{0}\{1}\{2}" -f $ENV:EnvChkrOp, $validatorCmd.matches.groups[1], (([system.guid]::newguid()) -split '-' | Select-Object -first 1) } } function Write-PsSessionInfo { <# .SYNOPSIS Write some pertainent information to the log about any PsSessions passed #> [CmdletBinding()] param ( $params ) try { if ($params['PsSession']) { foreach ($session in $params['PsSession']) { Log-Info -Message ("PsSession info: {0}, {1}, {2}, {3}, {4}, {5}" -f $session.ComputerName, $session.Name, $session.Id, $session.Runspace.ConnectionInfo.credential.username, $session.Runspace.SessionStateProxy.LanguageMode, $session.Runspace.ConnectionInfo.AuthenticationMechanism) } } else { Log-Info -Message "No PsSession info to write" } } catch { Log-Info -Message "Failed to write PsSession info: $($_.exception.message)" } } function Write-AzStackHciResult { <# .SYNOPSIS Displays results to screen .DESCRIPTION Displays test results to screen, highlighting failed tests. #> param ( [Parameter()] [string] $Title, [Parameter()] [psobject] $result, $seperator = ' -> ', [switch] $Expand, [switch] $ShowFailedOnly ) try { if (-not $result) { throw "Results missing. Ensure tests ran successfully." } Log-Info ("`n{0}:" -f $Title) -ConsoleOut foreach ($r in ($result | Sort-Object Status, Title, Description)) { if ($r.status -ne 'Succeeded' -or $Expand) { Write-StatusSymbol -Status $r.Status -Severity $r.Severity Write-Host " " -NoNewline Write-Host @expandDownSymbol Write-Host " " -NoNewline if ($r.status -ne 'Succeeded') { switch ($r.Severity) { Critical { Write-Host @needsRemediation } Warning { Write-Host @needsAttention } Informational { Write-Host @forInformation } Default { Write-Host @Critical } } } Write-Host " " -NoNewline Write-Host ($r.TargetResourceType + " - " + $r.Title + " " + $r.Description) foreach ($detail in ($r.AdditionalData | Sort-Object Status -Descending)) { if ($ShowFailedOnly -and $detail.Status -eq 'Succeeded') { continue } else { Write-Host " " -NoNewline Write-StatusSymbol -Status $detail.Status -Severity $r.Severity Write-Host " " -NoNewline Write-Host " " -NoNewline Write-Host ("{0}{1}{2}" -f $detail.Source, $seperator, $detail.Resource) } } if ($detail.Status -ne 'Succeeded') { Write-Host " " -NoNewline Write-Host @helpSymbol Write-Host (" Help URL: {0}" -f $r.Remediation) Write-Host "" } } else { if (-not $ShowFailedOnly) { Write-Host @expandOutSymbol Write-Host " " -NoNewline Write-Host @greenTickSymbol Write-Host " " -NoNewline Write-Host @isHealthy Write-Host " " -NoNewline Write-Host ($r.TargetResourceType + " " + $r.Title + " " + $r.Description) } } } } catch { Log-Info "Unable to write results. Error: $($_.exception.message)" -Type Warning } } # Export-ModuleMember -function Get-AzStackHciArcIntegrationEvents Export-ModuleMember -function Log-Info Export-ModuleMember -function Set-AzStackHciOutputPath Export-ModuleMember -function Write-AzStackHciArcInstallerFooter Export-ModuleMember -function Write-AzStackHciHeader Export-ModuleMember -function Write-AzStackHciResult Export-ModuleMember -function Write-ETWLog # Export-ModuleMember -function Write-ETWResult Export-ModuleMember -function Write-Summary # SIG # Begin signature block # MIIoKgYJKoZIhvcNAQcCoIIoGzCCKBcCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB5+pBWXz29fUiI # JZ07K+2BIdqG9JVuoxaM9U4z67fdiKCCDXYwggX0MIID3KADAgECAhMzAAADrzBA # 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 # /Xmfwb1tbWrJUnMTDXpQzTGCGgowghoGAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAAOvMEAOTKNNBUEAAAAAA68wDQYJYIZIAWUDBAIB # BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIGh7AOvcVmHI7vBcLLoeGnJm # e6CSxcbJ7CjFj3MvE9uBMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB # BQAEggEAWLiGLTorGnXUstp5r5jthg3xu2+y2KUkAazWbJ5GO1eqSK4T982UZ3hw # vDzD9UMp90zd1IvLbjFbzIAtOqadoPDqPrO4siXuLjVuOQUDZ5E9PgBqu9P6vzl1 # pHRcmPSU5nMg35e8zqVU9iwci04ltr4f+z3nWXLeaWDm9zJCYj45yYQyBTE8pTbV # 3Kofx7cP8qvTD9P2WHWV3Vmb4Cclk1uEmDx0/ToV9dmkupJS2ebXXC/z4dYYi+/1 # CAwDnFTmjf+fgCcc81nsgembUyYO8kO+D4vjzLLSUDI8xkISYuoJrcJIOGwSlrI7 # Jz4GZfv9hf+ccO3IUI34Salsg4vqPaGCF5QwgheQBgorBgEEAYI3AwMBMYIXgDCC # F3wGCSqGSIb3DQEHAqCCF20wghdpAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFSBgsq # hkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl # AwQCAQUABCA0BP9THJjp9QxQ5rxwDJxFuLOlW2/xa1Cr6rxcb2sxtAIGZwfyfBIJ # GBMyMDI0MTAxNDIyNDQ1Ny42MzVaMASAAgH0oIHRpIHOMIHLMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l # cmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046ODkwMC0w # NUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Wg # ghHqMIIHIDCCBQigAwIBAgITMwAAAe3hX8vV96VdcwABAAAB7TANBgkqhkiG9w0B # AQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYD # VQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0yMzEyMDYxODQ1 # NDFaFw0yNTAzMDUxODQ1NDFaMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz # aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv # cnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25z # MScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046ODkwMC0wNUUwLUQ5NDcxJTAjBgNV # BAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEB # AQUAA4ICDwAwggIKAoICAQCoMMJskrrqapycLxPC1H7zD7g88NpbEaQ6SjcTIRbz # CVyYQNsz8TaL1pqFTEAPL1X7ojL4/EaEW+UjNqZs/ayMyW4YIpFPZP2x4FBMVCdd # seF2i+aMMjDHi0LcTQZxM2s3mFMrCZAWSfLYXYDIimFBz8j0oLWGy3VgLmBTKM4x # Lqv7DZUz8B2SoAmbEtp62ngSl0hOoN73SFwE+Y24SvGQMWhykpG+vXDwcpWvwDe+ # TgnrLR7ATRFXN5JS26dm2yy6SYFMRYnME3dMHCQ/UQIQQNC8nLmIvdKkAoWEMXtJ # sGEo3QrM2S2SBv4PpHRzRukzTtP+UAceGxM9JyrwUQP5OCEmW6YchEyRDSwP4hU9 # f7B0Ayh14Pw9vJo7jewNjeMPIkmneyLSi0ruv2ox/xRGtcJ9yBNC5BaRktjz7stP # aojR+PDA2fuBtCo8xKlkt53mUb7AY+CZHHqhLm76pdMF6BHv2TvwlVBeQRN22Xja # VVRwCgjgJnNewt7PejcrpUn0qHLgLq+1BN1DzYukWkTr7wT0zl0iXr+NtqUkWSOn # WRfe8N21tB6uv3VkW8nFdChtbbZZz24peLtJEZuNrN8Xf9PTPMzZXDJBI1EciR/9 # 1QcGoZFmVbFVb2rUIAs01+ZkewvbhmGVDefX9oZG4/K4gGUsTvTW+r1JZMxUT2Mw # qQIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFM4b8Oz33hAqBEfKlAZf0NKh4CIZMB8G # A1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCG # Tmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUy # MFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4w # XAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2Vy # dHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwG # A1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQD # AgeAMA0GCSqGSIb3DQEBCwUAA4ICAQCd1gK2Rd+eGL0eHi+iE6/qDY8sbbsO4ema # ncp6KPN+xq5ZAatiBR4jmRRhm+9Vik0Fo0DLWi/N28bFI7dXYw09p3vCipbjy4Eo # ifm0Nud7/4U30i9+7RvW7XOQ3rx37+U7vq9lk6yYpGCNp0jlJ188/CuRPgqJnfq5 # EdeafH2AoG46hKWTeB7DuXasGt6spJOenGedSre34MWZqeTIQ0raOItZnFuGDy4+ # xoD1qRz2QW+u2gCHaG8AQjhYUM4uTi9t6kttj6c7Xamr2zrWuceDhz7sKLttLTJ7 # ws5YrA2I8cTlbMAf2KW0GVjKbYGd+LZGduEK7/7fs4GUkMqc51FsNdG1n+zgc7zH # u2oGGeCBg4s8ZR0ZFyx7jsgm9sSFCKQ5CsbAvlr/60Ndk5TeMR8Js2kNUicu2CqZ # 03833TsvTgk7iD1KLgfS16HEvjN6m4VKJKgjJ7OJJzabtS4JQgUnJrIZfyosk4D1 # 8rZni9pUwN03WgTmd10WTwiZOu4g8Un6iKcPMY/iFqTu4ntkzFUxBBpbFG6k1CIN # ZmoirEWmCtG3lyZ2IddmjtIefTkIvGWb4Jxzz7l2m/E2kGOixDJHsahZVmwsoNvh # y5ku/inU++dXHzw+hlvqTSFT89rIFVhcmsWPDJPNRSSpMhoJ33V2Za/lkKcbkUM0 # SbQgS9qsdzCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZI # hvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw # DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x # MjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAy # MDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC # AQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg4r25Phdg # M/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPF # dvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6 # GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBp # Dco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL64NF50Zu # yjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3E # XzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0 # lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1q # GFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ # +QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PA # PBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkw # EgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxG # NSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARV # MFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWlj # cm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAK # BggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC # AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX # zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v # cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI # KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG # 9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0x # M7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmC # VgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449 # xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wM # nosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDS # PeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2d # Y3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxn # GSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+Crvs # QWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokL # jzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL # 6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggNN # MIICNQIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw # b3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEn # MCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjg5MDAtMDVFMC1EOTQ3MSUwIwYDVQQD # ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQDu # HayKTCaYsYxJh+oWTx6uVPFw+aCBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w # IFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA6re2pTAiGA8yMDI0MTAxNDE1MjYy # OVoYDzIwMjQxMDE1MTUyNjI5WjB0MDoGCisGAQQBhFkKBAExLDAqMAoCBQDqt7al # AgEAMAcCAQACAgp/MAcCAQACAhO1MAoCBQDquQglAgEAMDYGCisGAQQBhFkKBAIx # KDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZI # hvcNAQELBQADggEBAFtfOac/UCDI/s4RhvKcCPtrXT1lykvJE5b4uEqC2B0LyQnZ # qT8SKtK9T99zfSp/j/v7cnGC4B141RkGAEOKFSnfvpw043dAuSPvgEtNCCJNbAm+ # Fd+AnDmqqvDeNiKcKZFhBBUsWC/0kwcKotqXJhdzTUegxOc2Ecv6mWiqPy+4KeUO # IXOGs7vmV7dcP0+efc7T+cMNaxv4/lN1jC94WK5h2V9W6wHgqQlr562v3yAkRcBW # DItWbNGhcbP++8hnSgRlqcBwwR7lA7ySXQDY0LIysYQEknSNaVYU4G41ngzigzYE # bDqqHH1j9f1OURNMau0l3oBVar6KdqMfCO4723wxggQNMIIECQIBATCBkzB8MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNy # b3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAe3hX8vV96VdcwABAAAB7TAN # BglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8G # CSqGSIb3DQEJBDEiBCDqGIqCJ1Ka4fIf0b96VOPL8vq/bsHj9mK4uJhtckkiGTCB # +gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EII0uDWg0CFseKxK3A16l1wrIwrsS # DrXZ6xSf0F4xbMo5MIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw # MTACEzMAAAHt4V/L1felXXMAAQAAAe0wIgQgZFJ/v/0iNlUBDRXPAoCr2qbd1rpi # l8AN8a6+GfGjbN4wDQYJKoZIhvcNAQELBQAEggIAGUwxStf+V5YJEhrZAMaJUwYM # R2J9y47mnHtytnXWUSD7mia6TpzTsP4xWolXgv5ZuCt7a9PTJxRvNhAZFRD/EN6B # IyWrpkp1s75YB28+LeoY31zlv0mbXlIn83HndMGbogIiy4v99ZmEeZxRgEvaHBTF # xBAEx+HRBuPToVeoyP9h4fkJflNeVPzg7SWsjUmQhUJruvXP7D4aP1ZsxewcL3Zv # SxoOwwrvIMAdheFAatfpD3cmsM9lioMDJwJHBniTBaWh3uZ5gSiSetSCWGBUGEKQ # C1NC8vopiTKHDlrkspHloDXc07IUw7Uv4DUdrayGbiA/44L8J4WWgJrvf6JkGsSg # 1cBODKzFMe1GDjh1+baWdPXVhw78M0Gff4mkBO0VtjziUY/S1gZoPlrP5HmFanTl # pKPb1G8I6SgZvbsctbtV0ToKYuTcTKFnHFM5VORwDjpgcWhMURHSO6K1ZLF1BTIY # FuUW0dLytNtfUixdUajUIbIBDXUIvo7Jww9U/DWio3X5CJMxLPfgNugVhS993P6g # 2kZBR/t/S0emmfgmcRom2RhliEq3JLdkAdwmgYjNO1u2NAPEIZGkH13OWZQQNN8E # ks3jzLkZoO+ZlwRoFDr35oIhVcRm4VioHousZp2GHMFyJG4qkIoIdylyVDI9m3Dr # H6x4rNbujpJLlE/EOsI= # SIG # End signature block |