Public/ps1/Job/Get-ApprxrRemoteJob.ps1
|
<#
.SYNOPSIS Retrieves and executes a remote job for a specified Apprxr pipeline. .DESCRIPTION Fetches a job assignment from the remote server for the given pipeline, processes the job, and logs the result. Supports multiple job types: - SQL: Executes a SQL job using Start-ApprxrJobSql - FILE: Handles file jobs using Start-ApprxrJobFile - HTTP: Executes HTTP jobs using Start-ApprxrJobHtml - PRINT: Sends a base64 PDF/ZPL to a printer (auto-detects Zebra) and returns print queue - GET_PRINTERS: Returns all available printers with driver, type, and Zebra/label detection - GET_PRINT_QUEUE: Returns the current print queue for a printer (or all printers) - REFRESH_SPOOLER: Graceful Restart-Service Spooler (clears stale in-memory state) - RESTART_SPOOLER: Force-stop with Stop-Process escalation, then start (no file cleanup) - CLEAN_SPOOLER: Force-stop + delete every file in spool\PRINTERS + start (destructive recovery) - FULL_SPOOLER: CLEAN_SPOOLER plus restart PrintNotify and Winmgmt (WMI) - use when Get-Printer / cmdlets hang even though Spooler itself is fine - RESET_SPOOLER: Legacy alias for CLEAN_SPOOLER (back-compat with v1.0.464) - INSTALL_SUMATRAPDF: Downloads SumatraPDF portable to %LOCALAPPDATA%\SumatraPDF\ and stores the path in config (used by PRINT for silent PDF printing) - START_PIPELINES: Starts all Apprxr pipelines with startup validation - START_PIPELINE: Starts a single pipeline by name (arguments.Name) - STOP_PIPELINES: Stops all Apprxr jobs - GET_PIPELINES: Retrieves all pipeline names - CREATE_PIPELINE: Creates a new pipeline job - SELFUPDATE: Triggers Apprxr module upgrade - GET_VERSION: Returns Apprxr environment information from Get-ApprxrInfo, including the module version - LOGFILE: Returns the last N lines of the current log file - ERRORLOG: Returns the last N lines of the error log file (errors only) - ROTATE_LOG: Rotates the current log file to an archive (independent of retention) - GET_LOGFILES: Returns a list of all available log files with size and last modified date - DELETE_LOGFILE: Deletes a specific log file by name (from job.arguments.FileName) - POWERSHELL: Executes arbitrary PowerShell code (if provided) Logs all actions and sends results back to the remote server. .PARAMETER pipeline The name of the pipeline to retrieve a job for. Use 'Default' for the default channel. .EXAMPLE Get-ApprxrRemoteJob -pipeline 'Pipeline1' # Retrieves and executes a remote job for the 'Pipeline1' channel. .EXAMPLE Get-ApprxrRemoteJob -pipeline 'Default' # Retrieves and executes a remote job for the default channel. .NOTES - Used for remote job management and execution in Apprxr automation. - Handles multiple job types and actions as described above. - Sends job results back to the remote server via Get-ApprxrResult. - Logs all received jobs and actions for auditing. - Errors are returned in the result object and logged. #> function Get-ApprxrRemoteJob{ param ($pipeline) if (-not [string]::IsNullOrEmpty($pipeline) -and $pipeline -ne "Default") { $channelId = "?channelId=$($pipeline)" } $deliverResult = "api/services/app/RemoteControl/SetDeliveries" $getTask= "api/services/app/RemoteControl/GetAssignment$channelId" #Get the job from the server $job = (Get-ApprxrResult -request $getTask).result if (-not $job){ return } try { # Log the job but truncate large payloads (Base64File can be many MB) $jobLogSafe = $job | ConvertTo-Json -Depth 2 -Compress if ($jobLogSafe.Length -gt 2000) { $jobLogSafe = $jobLogSafe.Substring(0, 2000) + '... [truncated]' } Log "Receive the following job: $jobLogSafe" $jobLogSafe = $null if ($job.Action -eq "SQL") { $sqlResult = Start-ApprxrJobSql -taskInformation $job $result = [PSCustomObject]@{ data = $sqlResult.data success = $sqlResult.success message = $sqlResult.message Id = $job.Id } # Truncate SQL log to avoid serialising huge DataTable results. $sqlLogJson = $result | ConvertTo-Json -Depth 3 if ($sqlLogJson.Length -gt 10000) { $sqlLogJson = $sqlLogJson.Substring(0, 10000) + '... [truncated]' } Log ("SQL result: " + $sqlLogJson) $sqlLogJson = $null } elseif ($job.Action -eq "FILE") { $fileResult = Start-ApprxrJobFile -Base64File ($job.arguments.Base64File) -FileLocation ($job.arguments.FileLocation) -Mode ($job.arguments.Mode) -FileName ($job.arguments.FileName) $result = [PSCustomObject]@{ data = $fileResult.data success = $fileResult.success message = $fileResult.message Id = $job.Id } } elseif ($job.Action -eq "HTTP") { $httpResult = Start-ApprxrJobHtml -taskInformation $job $result = [PSCustomObject]@{ data = $httpResult.data success = $httpResult.success message = $httpResult.message Id = $job.Id } } elseif ($job.Action -eq "PRINT") { $printResult = Start-ApprxrJobPrint -taskInformation $job $result = [PSCustomObject]@{ data = @($printResult.data) success = $printResult.success message = $printResult.message Id = $job.Id } } elseif ($job.Action -eq "GET_PRINTERS") { try { $printerList = @(Get-ApprxrPrinters) $result = [PSCustomObject]@{ success = $true message = "$($printerList.Count) printer(s) found" data = $printerList Id = $job.Id } } catch { $result = [PSCustomObject]@{ success = $false message = "Failed to list printers: $_" Id = $job.Id } } } elseif ($job.Action -eq "GET_PRINT_QUEUE") { try { $queuePrinterName = if ($job.arguments -and $job.arguments.PrinterName) { $job.arguments.PrinterName } else { $null } $queueData = Get-ApprxrPrintQueue -PrinterName $queuePrinterName $result = [PSCustomObject]@{ success = $true message = "$($queueData.Count) entry/entries in print queue" data = @($queueData) Id = $job.Id } } catch { $result = [PSCustomObject]@{ success = $false message = "Failed to get print queue: $_" Id = $job.Id } } } elseif ($job.Action -eq "INSTALL_SUMATRAPDF") { # Provision SumatraPDF on the host so PRINT jobs can use the # silent-print path. Optional arguments: # InstallPath - override default %LOCALAPPDATA%\SumatraPDF # DownloadUrl - override default download URL # Force - re-download even if already present try { $sumatraParams = @{} if ($job.arguments) { if ($job.arguments.InstallPath) { $sumatraParams['InstallPath'] = $job.arguments.InstallPath } if ($job.arguments.DownloadUrl) { $sumatraParams['DownloadUrl'] = $job.arguments.DownloadUrl } if ($job.arguments.Force) { $sumatraParams['Force'] = [bool]$job.arguments.Force } } $installResult = Install-ApprxrSumatra @sumatraParams $msg = if ($installResult.Success) { if ($installResult.AlreadyInstalled) { "SumatraPDF already installed at $($installResult.Path); config $(if ($installResult.ConfigStored) { 'updated' } else { 'NOT updated' })." } else { "SumatraPDF installed at $($installResult.Path); config $(if ($installResult.ConfigStored) { 'updated' } else { 'NOT updated' })." } } else { "INSTALL_SUMATRAPDF failed: $(($installResult.Steps | Select-Object -Last 1))" } $result = [PSCustomObject]@{ success = [bool]$installResult.Success message = $msg data = @($installResult) Id = $job.Id } } catch { $result = [PSCustomObject]@{ success = $false message = "INSTALL_SUMATRAPDF failed: $($_.Exception.Message)" Id = $job.Id } } } elseif ($job.Action -in @("REFRESH_SPOOLER", "RESTART_SPOOLER", "CLEAN_SPOOLER", "FULL_SPOOLER", "RESET_SPOOLER")) { # Four escalating recovery actions, plus the legacy RESET_SPOOLER # alias kept for back-compat with v1.0.464: # REFRESH_SPOOLER - graceful Restart-Service (clears stale state) # RESTART_SPOOLER - force-stop with Stop-Process escalation # CLEAN_SPOOLER - force-stop + wipe spool folder (destructive) # FULL_SPOOLER - CLEAN + restart PrintNotify + restart Winmgmt # (use when cmdlets hang but Spooler is fine) # RESET_SPOOLER - alias for CLEAN_SPOOLER $spoolerMode = switch ($job.Action) { 'REFRESH_SPOOLER' { 'Refresh' } 'RESTART_SPOOLER' { 'Restart' } 'FULL_SPOOLER' { 'Full' } default { 'Clean' } } try { $resetResult = Reset-ApprxrSpooler -Mode $spoolerMode $result = [PSCustomObject]@{ success = [bool]$resetResult.Success message = "$($job.Action) [$spoolerMode]: final status '$($resetResult.FinalStatus)'; removed $($resetResult.StuckFilesRemoved) stuck file(s)." data = @($resetResult) Id = $job.Id } } catch { $result = [PSCustomObject]@{ success = $false message = "$($job.Action) failed: $($_.Exception.Message)" Id = $job.Id } } } elseif ($job.Action -eq "START_PIPELINES") { try { $startResult = Start-ApprxrPipelines $allOk = $startResult.Failed.Count -eq 0 $result = [PSCustomObject]@{ success = $allOk message = "Started: $($startResult.Started.Count), Failed: $($startResult.Failed.Count)" + $(if ($startResult.Failed.Count -gt 0) { " ($($startResult.Failed -join ', '))" } else { '' }) data = @($startResult) Id = $job.Id } } catch { $result = [PSCustomObject]@{ success = $false message = "Failed to start pipelines: $_" Id = $job.Id } } } elseif ($job.Action -eq "START_PIPELINE") { try { if (-not $job.arguments -or -not $job.arguments.Name) { throw "Missing required argument: arguments.Name. Expected: { `"Action`": `"START_PIPELINE`", `"arguments`": { `"Name`": `"PipelineName`" } }" } $startResult = Start-ApprxrPipelines -Name $job.arguments.Name $ok = $startResult.Failed.Count -eq 0 $result = [PSCustomObject]@{ success = $ok message = if ($ok) { "Pipeline '$($job.arguments.Name)' started" } else { "Pipeline '$($job.arguments.Name)' failed to start" } data = @($startResult) Id = $job.Id } } catch { $result = [PSCustomObject]@{ success = $false message = "Failed to start pipeline: $_" Id = $job.Id } } } elseif ($job.Action -eq "GET_PIPELINES") { $pipelineNames = @(Get-ApprxrPipelines) $result = [PSCustomObject]@{ success = $true message = "Found $($pipelineNames.Count) pipeline(s): $($pipelineNames -join ', ')" data = $pipelineNames Id = $job.Id } } elseif ($job.Action -eq "STOP_PIPELINES") { try { $stopResult = Stop-ApprxrJobs $allOk = $stopResult.Failed.Count -eq 0 $result = [PSCustomObject]@{ success = $allOk message = "Stopped: $($stopResult.Stopped.Count), Failed: $($stopResult.Failed.Count)" + $(if ($stopResult.Failed.Count -gt 0) { " ($($stopResult.Failed -join ', '))" } else { '' }) data = @($stopResult) Id = $job.Id } } catch { $result = [PSCustomObject]@{ success = $false message = "Failed to stop pipelines: $_" Id = $job.Id } } } elseif ($job.Action -eq "CREATE_PIPELINE") { try { if (-not $job.arguments -or -not $job.arguments.Name) { throw "Missing required argument: arguments.Name. Expected: { `"Action`": `"CREATE_PIPELINE`", `"arguments`": { `"Name`": `"PipelineName`", `"WaitTime`": 10, `"DirectProcessing`": false } }" } $pipelineSleep = if ($job.arguments.WaitTime) { [int]$job.arguments.WaitTime } else { 10 } $pipelineDirect = if ($job.arguments.DirectProcessing) { [bool]$job.arguments.DirectProcessing } else { $false } Create-ApprxrPipelineJob -jobParam $job.arguments $result = [PSCustomObject]@{ success = $true message = "Pipeline '$($job.arguments.Name)' created (Sleep=$pipelineSleep, DirectProcessing=$pipelineDirect)" Id = $job.Id } } catch { $result = [PSCustomObject]@{ success = $false message = "Failed to create pipeline: $_" Id = $job.Id } } } elseif ($job.Action -eq "SELFUPDATE") { $result = [PSCustomObject]@{ success = $true message = Start-ApprxrUpgrade Id = $job.Id } } elseif ($job.Action -eq "GET_VERSION") { $info = Get-ApprxrInfo $result = [PSCustomObject]@{ success = $true message = "Apprxr status generated on $((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) (version $($info.Version))." data = @($info) Id = $job.Id } } elseif ($job.Action -eq "LOGFILE") { #$lines = if ($job.arguments.Lines) { $job.arguments.Lines } else { 50 } $lines = 250 $logContent = [string](Get-ApprxrLog -Tail $lines | Out-String) $result = [PSCustomObject]@{ success = $true message = $logContent Id = $job.Id } } elseif ($job.Action -eq "ERRORLOG") { $lines = 250 $logContent = [string](Get-ApprxrLog -Tail $lines -ErrorLog | Out-String) $result = [PSCustomObject]@{ success = $true message = if ([string]::IsNullOrWhiteSpace($logContent)) { "(no errors recorded)" } else { $logContent } Id = $job.Id } } elseif ($job.Action -eq "ROTATE_LOG") { try { Log "ROTATE_LOG: Rotating current log file on demand" Move-ApprxrLogFile $result = [PSCustomObject]@{ success = $true message = "Log file rotated successfully" Id = $job.Id } } catch { $result = [PSCustomObject]@{ success = $false message = "Failed to rotate log file: $_" Id = $job.Id } } } elseif ($job.Action -eq "GET_LOGFILES") { try { $logFolder = if ($LogManagement -and $LogManagement.LogFolder) { Split-Path $LogManagement.LogFolder -Parent } else { $null } if (-not $logFolder -or -not (Test-Path $logFolder)) { $result = [PSCustomObject]@{ success = $false message = "Log folder not found: $logFolder" Id = $job.Id } } else { $logFiles = @(Get-ChildItem -Path $logFolder -File -ErrorAction Stop | Where-Object { $_.Name -like 'logfile*' } | Sort-Object LastWriteTime -Descending | ForEach-Object { [PSCustomObject]@{ Name = $_.Name SizeKB = [math]::Round($_.Length / 1KB, 1) LastModified = $_.LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') } }) $result = [PSCustomObject]@{ success = $true message = "$($logFiles.Count) log file(s) found" data = $logFiles Id = $job.Id } } } catch { $result = [PSCustomObject]@{ success = $false message = "Failed to list log files: $_" Id = $job.Id } } } elseif ($job.Action -eq "DELETE_LOGFILE") { try { $fileNameToDelete = $job.arguments.FileName if ([string]::IsNullOrWhiteSpace($fileNameToDelete)) { $result = [PSCustomObject]@{ success = $false message = "DELETE_LOGFILE: FileName argument is required. Expected: { `"Action`": `"DELETE_LOGFILE`", `"arguments`": { `"FileName`": `"logfile.txt_1712678400`" } }" Id = $job.Id } } else { $logFolder = if ($LogManagement -and $LogManagement.LogFolder) { Split-Path $LogManagement.LogFolder -Parent } else { $null } # Prevent path traversal — only allow plain file names if ($fileNameToDelete -match '[/\\]') { $result = [PSCustomObject]@{ success = $false message = "DELETE_LOGFILE: Path separators not allowed in FileName. Use plain file name only, e.g. `"logfile.txt_1712678400`"" Id = $job.Id } } else { $targetFile = Join-Path $logFolder $fileNameToDelete # Guard: only delete files that are inside the log folder and match logfile pattern if (-not (Test-Path $targetFile)) { $result = [PSCustomObject]@{ success = $false message = "DELETE_LOGFILE: File not found: $fileNameToDelete" Id = $job.Id } } elseif ($fileNameToDelete -notlike 'logfile*') { $result = [PSCustomObject]@{ success = $false message = "DELETE_LOGFILE: Only log files (logfile*) can be deleted" Id = $job.Id } } else { Log "DELETE_LOGFILE: Deleting $fileNameToDelete" Remove-Item -Path $targetFile -Force -ErrorAction Stop $result = [PSCustomObject]@{ success = $true message = "Deleted: $fileNameToDelete" Id = $job.Id } } } } } catch { $result = [PSCustomObject]@{ success = $false message = "Failed to delete log file: $_" Id = $job.Id } } } elseif ($job.Action -like 'POWERSHELL' -and $job.Command) { try { $psResult = Invoke-Expression $job.Command $result = [PSCustomObject]@{ success = $true message = $psResult executedCommand = $job.Command Id = $job.Id } } catch { $result = [PSCustomObject]@{ success = $false message = ("PowerShell command failed: " + $_) executedCommand = $job.Command } } } else { $result = [PSCustomObject]@{ success = $false message = "Unknown action: '$($job.Action)'. Valid actions: SQL, FILE, HTTP, PRINT, GET_PRINTERS, GET_PRINT_QUEUE, REFRESH_SPOOLER, RESTART_SPOOLER, CLEAN_SPOOLER, FULL_SPOOLER, RESET_SPOOLER, INSTALL_SUMATRAPDF, START_PIPELINES, START_PIPELINE, STOP_PIPELINES, GET_PIPELINES, CREATE_PIPELINE, SELFUPDATE, GET_VERSION, LOGFILE, ERRORLOG, ROTATE_LOG, GET_LOGFILES, DELETE_LOGFILE, POWERSHELL" } } } catch { $result = [PSCustomObject]@{ success = $false message = ("There is a unhandled error: " + $_) } } # Send result to server (DeliveryInputDto) # public class DeliveryInputDto # { # public Guid Id { get; set; } # public JArray Data { get; set; } # public string Message { get; set; } # public bool Success { get; set; } # public DateTime CreationDate { get; set; } # } # Id must always be the original job.Id. $deliveryData = @() $deliveryMessage = $null $deliverySuccess = $false if ($null -ne $result -and $null -ne $result.PSObject.Properties['success']) { $deliverySuccess = [bool]$result.success } if ($null -ne $result -and $null -ne $result.PSObject.Properties['data']) { $deliveryData = @($result.data) } if ($null -ne $result -and $null -ne $result.PSObject.Properties['message']) { $messageValue = $result.message if ($messageValue -is [string]) { $deliveryMessage = [string]$messageValue } elseif ($null -ne $messageValue -and $deliveryData.Count -eq 0) { # This is a fallback and will be removed later. If message is not a string, it will be transferred via Data (JArray). But if message is not a string and data is empty, we will try to convert message to string and send it via Message property for backward compatibility. $deliveryMessage = $messageValue # Non-string payloads are transferred via Data (JArray). $deliveryData = @($messageValue) } } # --- Clear large incoming payloads from memory before delivery --- # Base64File can be many MB; keeping it in $job while building the # delivery body doubles memory usage and can crash the pipeline. if ($job.arguments -and $job.arguments.PSObject.Properties['Base64File']) { $job.arguments.Base64File = $null } # Truncate delivery message if too large (e.g. huge log output) if ($null -ne $deliveryMessage -and $deliveryMessage.Length -gt 50000) { $deliveryMessage = $deliveryMessage.Substring(0, 50000) + "`n... [truncated at 50 KB]" } $deliveryInput = [PSCustomObject]@{ Id = $job.Id Data = $deliveryData Message = $deliveryMessage Success = $deliverySuccess CreationDate = (Get-Date).ToString('o') } # Serialize once and reuse for both logging and the API call to avoid # creating two multi-MB JSON copies of potentially large payloads. $deliveryBody = $deliveryInput | ConvertTo-Json -Depth 5 $deliveryInput = $null # Safety check: if the serialized body is extremely large, truncate # to avoid OutOfMemoryException on the HTTP POST and 413 from the server. $maxDeliveryBytes = 5 * 1024 * 1024 # 5 MB if ($deliveryBody.Length -gt $maxDeliveryBytes) { Log -msg "[Get-ApprxrRemoteJob] Delivery payload too large ($([math]::Round($deliveryBody.Length / 1MB, 1)) MB). Sending truncated result." -IsError $deliveryBody = $null $deliveryBody = [PSCustomObject]@{ Id = $job.Id Data = @() Message = "Result truncated: payload exceeded $([math]::Round($maxDeliveryBytes / 1MB)) MB. Job completed with Success=$deliverySuccess." Success = $deliverySuccess CreationDate = (Get-Date).ToString('o') } | ConvertTo-Json -Depth 5 } try { Get-ApprxrResult -request $deliverResult -body $deliveryBody } catch { $statusCode = 0 if ($_.Exception.Response) { try { $statusCode = [int]$_.Exception.Response.StatusCode } catch {} } if ($statusCode -eq 0 -and $_.Exception.Message -match '\(413\)') { $statusCode = 413 } if ($statusCode -eq 413) { Log -msg "[Get-ApprxrRemoteJob] Delivery of job $($job.Id) rejected with 413 (Request Entity Too Large). Payload will not be retried." -IsError } else { # Log but don't rethrow — a delivery failure must NOT kill the pipeline thread Log -msg "[Get-ApprxrRemoteJob] Delivery failed for job $($job.Id): $($_.Exception.Message)" -IsError } } # Release large intermediate objects to avoid accumulation across # the tight while($true) loop in the calling job thread. Remove-Variable result -ErrorAction SilentlyContinue $job = $null $sqlResult = $null $httpResult = $null $fileResult = $null $printResult = $null $deliveryInput = $null $deliveryBody = $null $deliveryData = $null $deliveryMessage = $null $deliveryData = $null $deliveryMessage = $null } # SIG # Begin signature block # MIInKgYJKoZIhvcNAQcCoIInGzCCJxcCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBEaDjwAEkDbCGV # tBX4mrwhxsEgMzPjR2TbacosGeUV5KCCIKYwggWNMIIEdaADAgECAhAOmxiO+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 # twGpn1eqXijiuZQwggaXMIIEf6ADAgECAhAfsijAKebq6quDMIHCRvIfMA0GCSqG # SIb3DQEBCwUAMGoxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBT # eXN0ZW1zIFMuQS4xODA2BgNVBAMTL0NlcnR1bSBFeHRlbmRlZCBWYWxpZGF0aW9u # IENvZGUgU2lnbmluZyAyMDIxIENBMB4XDTI2MDIwMzEzNTE0NFoXDTI4MDIwMzEz # NTE0M1owgaExHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYB # BAGCNzwCAQMTAk5MMREwDwYDVQQFEwg5NjMyNDU2MjELMAkGA1UEBhMCTkwxEDAO # BgNVBAgMB1V0cmVjaHQxEzARBgNVBAcMCkFtZXJzZm9vcnQxETAPBgNVBAoMCEFQ # UFJYIEJWMREwDwYDVQQDDAhBUFBSWCBCVjCCAaIwDQYJKoZIhvcNAQEBBQADggGP # ADCCAYoCggGBAOF+mHloTjmkknba8mOejw0Gq3Aczy1dtatfdLM70ken0n07zIlY # 2jNmyTv5I5RixXAt3LJUwWnUQH8okGFJYvnLZRPyjpCxnEqq8GL6puhKjIIcTs8W # VhoADX+mFtLXygLrfk1j6A+dnNXjoCQMsVSEYppSGrpMpKsPQONb1mmFRx66vqro # HcP93qWYTm/f3TpRzlscIxcQ/3Ab+KLeW0sHgC/a8MVHLicbdUe/pka4jMM98Djj # BtkBc18dI6ECtrDfB2FXXFomvgm5UyPaf2sYxMPL+X/iCNhaQevoT3vttxMvKzAD # JxJK7VsV2nrCvxfTaP4cVd9FfoxUqjCE0eA/IH3qrKqAv3eONjMrRzoO9jJumusi # t91wYT1dwTe/o2FAwfmZ7qxofCXTlO008weUDY5UBw8d+BavVvnDNR08eEcCJN37 # wBJn1hhjFZZD6OxVcMEoyhIG5tJqvmBPyR5A1oYeGSL+/xBbLpAQR0oAhAivxvn4 # POX2r4M/wXGJewIDAQABo4IBfzCCAXswDAYDVR0TAQH/BAIwADBBBgNVHR8EOjA4 # MDagNKAyhjBodHRwOi8vY2V2Y3NjYTIwMjEuY3JsLmNlcnR1bS5wbC9jZXZjc2Nh # MjAyMS5jcmwwdwYIKwYBBQUHAQEEazBpMC4GCCsGAQUFBzABhiJodHRwOi8vY2V2 # Y3NjYTIwMjEub2NzcC1jZXJ0dW0uY29tMDcGCCsGAQUFBzAChitodHRwOi8vcmVw # b3NpdG9yeS5jZXJ0dW0ucGwvY2V2Y3NjYTIwMjEuY2VyMB8GA1UdIwQYMBaAFKxX # yggW3D/FMRwKTdv78d6ZJy00MB0GA1UdDgQWBBSEZ5pbrzKazBz6ZCRYAbuQVlDy # pDBKBgNVHSAEQzBBMAcGBWeBDAEDMDYGCyqEaAGG9ncCBQEHMCcwJQYIKwYBBQUH # AgEWGWh0dHBzOi8vd3d3LmNlcnR1bS5wbC9DUFMwEwYDVR0lBAwwCgYIKwYBBQUH # AwMwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQARtX2dHRUVP9uH # 5FuVIvj22UsNMW2gsexnRxeL/xKxY4BXv6UkQmcgABKbYlWGH0wodaKRhrT9NyK1 # tt0P1C53zAkaiwNU7gSge7s/OPk2yA7g++iVBUDXRelZVCWi31V8yRVV+zXAFEkK # timx00QcEhLFu1DAyjABmKouChHJyqF4dHWytvQZQHw1dfG1OSh6F82thRipW/q1 # ggWzm91QdieGlaSBZy9N881+h4V23R7oJVyWcCUtar19rBJH+/TaZHMo3VDVazhr # CYUKMf/f6RA+iuSsPcpwMi7BZzTxawQtEe/1vG3RLVP94bWl69gY8LiTe0OU23tp # 1PuTiHFLEXjTIb9WnBljH2PvUpJVaxQAMZrunKZvuafYSAvcEfSiRvgFg3r1UH9I # nLjJVxsjfxjnbg5y/5SChh+OBbld7+NdvWVoFUGwqK2IuALD0O2/gtQBS/+UZuiB # GsWpTv9PWI9/C2kPjEcBjC3sZedZOjkEJNSb8siUDItoswA+ddZRBBLdkNJCIKX4 # +lrKAAXdOqGu1QSu57G/OOLyjeUHEWx73XzoPMdgGfkcbdSBQoWBevDbC2xLzqr6 # EQZhplxGR39HZ4M4GyNFcpL4Xhuw1Gma8ldGTeuNw5ktP5Jmf9zvrjP5epHgMl6r # jO0VG4wGU+R4e/FPQClKsyxI/cTJMjCCBrQwggScoAMCAQICEA3HrFcF/yGZLkBD # Igw6SYYwDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp # Z2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMY # RGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTI1MDUwNzAwMDAwMFoXDTM4MDEx # NDIzNTk1OVowaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu # MUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IFRpbWVTdGFtcGluZyBSU0E0 # MDk2IFNIQTI1NiAyMDI1IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBALR4MdMKmEFyvjxGwBysddujRmh0tFEXnU2tjQ2UtZmWgyxU7UNqEY81FzJs # Qqr5G7A6c+Gh/qm8Xi4aPCOo2N8S9SLrC6Kbltqn7SWCWgzbNfiR+2fkHUiljNOq # nIVD/gG3SYDEAd4dg2dDGpeZGKe+42DFUF0mR/vtLa4+gKPsYfwEu7EEbkC9+0F2 # w4QJLVSTEG8yAR2CQWIM1iI5PHg62IVwxKSpO0XaF9DPfNBKS7Zazch8NF5vp7ea # Z2CVNxpqumzTCNSOxm+SAWSuIr21Qomb+zzQWKhxKTVVgtmUPAW35xUUFREmDrMx # SNlr/NsJyUXzdtFUUt4aS4CEeIY8y9IaaGBpPNXKFifinT7zL2gdFpBP9qh8SdLn # Eut/GcalNeJQ55IuwnKCgs+nrpuQNfVmUB5KlCX3ZA4x5HHKS+rqBvKWxdCyQEEG # cbLe1b8Aw4wJkhU1JrPsFfxW1gaou30yZ46t4Y9F20HHfIY4/6vHespYMQmUiote # 8ladjS/nJ0+k6MvqzfpzPDOy5y6gqztiT96Fv/9bH7mQyogxG9QEPHrPV6/7umw0 # 52AkyiLA6tQbZl1KhBtTasySkuJDpsZGKdlsjg4u70EwgWbVRSX1Wd4+zoFpp4Ra # +MlKM2baoD6x0VR4RjSpWM8o5a6D8bpfm4CLKczsG7ZrIGNTAgMBAAGjggFdMIIB # WTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTvb1NK6eQGfHrK4pBW9i/U # SezLTjAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8E # BAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsG # AQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0 # dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQu # Y3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsG # CWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEAF877FoAc/gc9EXZxML2+C8i1 # NKZ/zdCHxYgaMH9Pw5tcBnPw6O6FTGNpoV2V4wzSUGvI9NAzaoQk97frPBtIj+ZL # zdp+yXdhOP4hCFATuNT+ReOPK0mCefSG+tXqGpYZ3essBS3q8nL2UwM+NMvEuBd/ # 2vmdYxDCvwzJv2sRUoKEfJ+nN57mQfQXwcAEGCvRR2qKtntujB71WPYAgwPyWLKu # 6RnaID/B0ba2H3LUiwDRAXx1Neq9ydOal95CHfmTnM4I+ZI2rVQfjXQA1WSjjf4J # 2a7jLzWGNqNX+DF0SQzHU0pTi4dBwp9nEC8EAqoxW6q17r0z0noDjs6+BFo+z7bK # SBwZXTRNivYuve3L2oiKNqetRHdqfMTCW/NmKLJ9M+MtucVGyOxiDf06VXxyKkOi # rv6o02OoXN4bFzK0vlNMsvhlqgF2puE6FndlENSmE+9JGYxOGLS/D284NHNboDGc # mWXfwXRy4kbu4QFhOm0xJuF2EZAOk5eCkhSxZON3rGlHqhpB/8MluDezooIs8CVn # rpHMiD2wL40mm53+/j7tFaxYKIqL0Q4ssd8xHZnIn/7GELH3IdvG2XlM9q7WP/Uw # gOkw/HQtyRN62JK4S1C8uw3PdBunvAZapsiI5YKdvlarEvf8EA+8hcpSM9LHJmyr # xaFtoza2zNaQ9k+5t1wwggbNMIIEtaADAgECAhEAu/DMtbe4Mf0hrjJ3iuQMiTAN # BgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8g # VGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9u # IEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAy # MB4XDTIxMDUxOTA1MzIxM1oXDTM2MDUxODA1MzIxM1owajELMAkGA1UEBhMCUEwx # ITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMgUy5BLjE4MDYGA1UEAxMvQ2Vy # dHVtIEV4dGVuZGVkIFZhbGlkYXRpb24gQ29kZSBTaWduaW5nIDIwMjEgQ0EwggIi # MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCUvvjwlqjf9eedRTK+NoavZlVx # mQTPIN1nK5XQRUQWyPWwHD54wa2aD2kRDrAjBf71/T0XN9Oqms5ML/Jolgryv3JW # 7/yahp7lg/wn3PDnNwzC1BlFMyCdEktQmUXMmE4mmxSutRY1OGGagENWPjbQ1R/x # 4HuTByWbG+TUV7dIPxE7TMy9Npco4f09DN6QFRXdk7bZTu58kxu6MFH6mzQkC3IX # vExfo0c/CT4/hTZD2XknHjXLzi9jzInSHS9GQqeXd6nWbkwEu7znKpNEcSElorDS # EcRhc1OSOLjUK0x0cOw8whzQ0fWGkPoqgCslbjZoko7U7kj/Fn4TWQ8s75LHjhVa # o+w2SWMP0ELWYIkq1ComGq3wqBD7VU6rtCDoUf237HkgRBxLXFjwp444oKWnchYM # Z7epWX8jqntSr4QHeidL72c6XswQIIZsFglV4BO28jO02yS7w4iyY0c6PQs34GZ7 # SWphsN1DaiX9ysc6hovVYoVA94t+3p4TI1RtK9Ayh0atmfYPJqtBfk5kJ1h4nNax # 0lZmJL9chJjZQb+7XW8MQgstiQdsegaz2QL6Edm+94N8IW6TYaalyO9LeR35A9Mo # TLo79rdB04naTqWdPTBKh7DpS53ZAQn5dYs2per+m7ZeIxnEWaNcG+PbRh+ZslFb # 6M75JgN43szB+/VYVQIDAQABo4IBVTCCAVEwDwYDVR0TAQH/BAUwAwEB/zAdBgNV # HQ4EFgQUrFfKCBbcP8UxHApN2/vx3pknLTQwHwYDVR0jBBgwFoAUtqFUOQLDoD+O # irz61PgcptE6Dv0wDgYDVR0PAQH/BAQDAgEGMBMGA1UdJQQMMAoGCCsGAQUFBwMD # MDAGA1UdHwQpMCcwJaAjoCGGH2h0dHA6Ly9jcmwuY2VydHVtLnBsL2N0bmNhMi5j # cmwwbAYIKwYBBQUHAQEEYDBeMCgGCCsGAQUFBzABhhxodHRwOi8vc3ViY2Eub2Nz # cC1jZXJ0dW0uY29tMDIGCCsGAQUFBzAChiZodHRwOi8vcmVwb3NpdG9yeS5jZXJ0 # dW0ucGwvY3RuY2EyLmNlcjA5BgNVHSAEMjAwMC4GBFUdIAAwJjAkBggrBgEFBQcC # ARYYaHR0cDovL3d3dy5jZXJ0dW0ucGwvQ1BTMA0GCSqGSIb3DQEBDAUAA4ICAQC7 # khlZjFbU+gsRdcraFFJKj1PL63MVudnm/AILuNaxm7LIZOYtrZaRWEpR0qd3uhSp # UEI29fMBZvuu3CHXJsM58hbJFo4YoHnyDJgTkeVmc10fd1NI//cI3nRD1/Alx09y # WhPZlze0A/Bvwc3LcZtTywfsL5tD3QAL8ZqelrHt1Eb8AnDEnAzKNbm1mwYmD/5d # y1XkIKfsM1pmRM2ZDcJ4qpwVewE7g+4e+Y+iq42LuaHPvNAkwq0daA9Hp3qemk0c # RFfM5257MvEsu+6w8+44mpQUOgpASVIjY3l2vdf6BUfBJfsd3pcp/2hfDnXaql9A # oB7ps7eCZb9VXKm/u2lTRMf5esOcZFy4udsnGBaOwSSUe0chYusfJ9IjsmpoMl4C # W5E0R/U55Bz6TpDo+gaXQJL4i/zv0UR5papGsDguBASp9g/OfnvGTeWrS9l5orEk # tu9ExrFfPvAKxZK+4AO9bapPhMATraKo6kx6K51pS1ZO2pf1r3B+lXN5bTLgp8g/ # dygUZm2cmauBAzJA5v/iHOb0b4b4Muqc8dxgcX1jZRLtLvxnAWxkKIMfj7A4M0Jr # N4rLBUpPFM0+Bp2sR7rtFqNZW56huaDkxO75eNRN2z4A959R5GBRnFWtgE65+B1R # HAQQ/TOF4mU0Y3oIhVQr3rUh4tdSvIxr8QpsDKIvsDCCBu0wggTVoAMCAQICEAqA # 7xhLjfEFgtHEdqeVdGgwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxFzAV # BgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVk # IEc0IFRpbWVTdGFtcGluZyBSU0E0MDk2IFNIQTI1NiAyMDI1IENBMTAeFw0yNTA2 # MDQwMDAwMDBaFw0zNjA5MDMyMzU5NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQK # Ew5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgU0hBMjU2IFJTQTQw # OTYgVGltZXN0YW1wIFJlc3BvbmRlciAyMDI1IDEwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQDQRqwtEsae0OquYFazK1e6b1H/hnAKAd/KN8wZQjBjMqiZ # 3xTWcfsLwOvRxUwXcGx8AUjni6bz52fGTfr6PHRNv6T7zsf1Y/E3IU8kgNkeECqV # Q+3bzWYesFtkepErvUSbf+EIYLkrLKd6qJnuzK8Vcn0DvbDMemQFoxQ2Dsw4vEjo # T1FpS54dNApZfKY61HAldytxNM89PZXUP/5wWWURK+IfxiOg8W9lKMqzdIo7VA1R # 0V3Zp3DjjANwqAf4lEkTlCDQ0/fKJLKLkzGBTpx6EYevvOi7XOc4zyh1uSqgr6Un # bksIcFJqLbkIXIPbcNmA98Oskkkrvt6lPAw/p4oDSRZreiwB7x9ykrjS6GS3NR39 # iTTFS+ENTqW8m6THuOmHHjQNC3zbJ6nJ6SXiLSvw4Smz8U07hqF+8CTXaETkVWz0 # dVVZw7knh1WZXOLHgDvundrAtuvz0D3T+dYaNcwafsVCGZKUhQPL1naFKBy1p6ll # N3QgshRta6Eq4B40h5avMcpi54wm0i2ePZD5pPIssoszQyF4//3DoK2O65Uck5Wg # gn8O2klETsJ7u8xEehGifgJYi+6I03UuT1j7FnrqVrOzaQoVJOeeStPeldYRNMmS # F3voIgMFtNGh86w3ISHNm0IaadCKCkUe2LnwJKa8TIlwCUNVwppwn4D3/Pt5pwID # AQABo4IBlTCCAZEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU5Dv88jHt/f3X85Fx # YxlQQ89hjOgwHwYDVR0jBBgwFoAU729TSunkBnx6yuKQVvYv1Ensy04wDgYDVR0P # AQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMIGVBggrBgEFBQcBAQSB # iDCBhTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMF0GCCsG # AQUFBzAChlFodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz # dGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2U0hBMjU2MjAyNUNBMS5jcnQwXwYDVR0f # BFgwVjBUoFKgUIZOaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1 # c3RlZEc0VGltZVN0YW1waW5nUlNBNDA5NlNIQTI1NjIwMjVDQTEuY3JsMCAGA1Ud # IAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEA # ZSqt8RwnBLmuYEHs0QhEnmNAciH45PYiT9s1i6UKtW+FERp8FgXRGQ/YAavXzWjZ # hY+hIfP2JkQ38U+wtJPBVBajYfrbIYG+Dui4I4PCvHpQuPqFgqp1PzC/ZRX4pvP/ # ciZmUnthfAEP1HShTrY+2DE5qjzvZs7JIIgt0GCFD9ktx0LxxtRQ7vllKluHWiKk # 6FxRPyUPxAAYH2Vy1lNM4kzekd8oEARzFAWgeW3az2xejEWLNN4eKGxDJ8WDl/FQ # USntbjZ80FU3i54tpx5F/0Kr15zW/mJAxZMVBrTE2oi0fcI8VMbtoRAmaaslNXdC # G1+lqvP4FbrQ6IwSBXkZagHLhFU9HCrG/syTRLLhAezu/3Lr00GrJzPQFnCEH1Y5 # 8678IgmfORBPC1JKkYaEt2OdDh4GmO0/5cHelAK2/gTlQJINqDr6JfwyYHXSd+V0 # 8X1JUPvB4ILfJdmL+66Gp3CSBXG6IwXMZUXBhtCyIaehr0XkBoDIGMUG1dUtwq1q # mcwbdUfcSYCn+OwncVUXf53VJUNOaMWMts0VlRYxe5nK+At+DI96HAlXHAL5SlfY # xJ7La54i71McVWRP66bW+yERNpbJCjyCYG2j+bdpxo/1Cy4uPcU3AWVPGrbn5PhD # Bf3Froguzzhk++ami+r3Qrx5bIbY3TVzgiFI7Gq3zWcxggXaMIIF1gIBATB+MGox # CzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4x # ODA2BgNVBAMTL0NlcnR1bSBFeHRlbmRlZCBWYWxpZGF0aW9uIENvZGUgU2lnbmlu # ZyAyMDIxIENBAhAfsijAKebq6quDMIHCRvIfMA0GCWCGSAFlAwQCAQUAoIGEMBgG # CisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcC # AQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIE # IPI0oMN1qnnpCwH6V5DkyPfn7mVSETC7ugNwyaFCaUvIMA0GCSqGSIb3DQEBAQUA # BIIBgI+WOnGOl0qZCIIhHetQR/8JMKjvbaRN/LYte7IPdGlkvtt6IHEFHEgv5qx0 # d+eH+xjLcFBfdqnXYNK/YUjdyQsQl5mMUbG13jvK6w2jfjgrJ6TVWinse5hKnb8p # eHe8ODed4BB2FWscM/zdfUjC9GyFJY9QvazP4kjhIf432Yrw5w/SfF448wFfPuEf # AbUUFHUZPnHgnEKdBlz0RC9u/U2C7xbR271rtHvdg15Lhvb4X8PUYnq4QQBPJyIx # ngmx5837hDmVFdbOSyqEK9rWSn8H7ggXab7vU+yx1DBRWa91cQ9qm5p8VcaGg0nG # 3rrhdCKSr2/49zQaEJGt7wIk7Xz6nni5cpthwstyFBqrmAfyR+9HoWKCS4kFotKT # 5fWI6oFMIN/d9IcNqmx9RAixUXOK8gkVEebZXBzlmmJL6zZLpDXbqXEBIZPxfnb9 # ZfqNNRP5CwUg4IBgz5jvo5wJq8MRTgEaK20GFt5U5j9tw+pnefPGMuo4Sumh476U # +6KYqaGCAyYwggMiBgkqhkiG9w0BCQYxggMTMIIDDwIBATB9MGkxCzAJBgNVBAYT # AlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQg # VHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTEC # EAqA7xhLjfEFgtHEdqeVdGgwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMx # CwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNjA1MDQxMTA1MDdaMC8GCSqG # SIb3DQEJBDEiBCB/Phd3+AtKxSFCfx0vTG6+kxqVfosMLnjleuVTMjaT2DANBgkq # hkiG9w0BAQEFAASCAgBYO+9M8CZVUjgdhjh2ZKF+YtMoAfcJQVwCo8kg//UACpHN # 6YMuY82UUmBMVLzZiKp613yvvUffBMeH/cJI7fG61/OrM7OX3jFhgiM6PLZ/Kpls # 7IkHQ5AS9OEwzWL1OUtBOkvrDe029zAE++zyrtURJsLvgKXc6ClRoBojZjQYpYpa # Q1Seg+cBkv98oPkdVig0yVjsOMOyG9aI+50AZ0VKalAVi5n7iiWxs9VjQCm7B699 # Ga/fwHBX8mvTTaWVQlP7ZjIUL+tkb7xLDy9BQQxGo4NJWM/l40/dH0yd9WmREb4r # TlKe4+IO1VspJuo2bMXA1DKVso2dpS9/gNVtlVapalxVXXCYPgIcwKKxufNslZSN # vg/R3LpnaKb9QyMTJLWLWzbwlDP0tZfKjHcyuYNkoJg+YiusN4og4XT16uBdmje9 # +bD8hWQLa1XLDysOmsmBMzAyH3QVqTDC6fRkZHKWa5E+0AnWMeFhGI4s2wiOhxls # BQlTYP5+/nllBhim7zaC0OjrtNooV6VNAATOoP7+M/KjYIDDjOqmjvDz+76D3OKL # 79GfI+TbJ2e1v2c9eX5YFliiCfKNV2PE7U1F37eZ5bk/6gFIb5rTIQv8iMbeP9Qi # 4FUue/9/hA0+j9zNRJiEPMNqcJarwKwuZABkvrYw2wwlyv21NYgeIYaYcv7slQ== # SIG # End signature block |