Framework/Managers/BatchScanManager.ps1
Set-StrictMode -Version Latest class BatchScanManager { hidden [string] $OrgName = $null; hidden [string] $ProjectName = $null; [PSObject] $ControlSettings; hidden [string] $BatchScanTrackerFileName=$null; hidden [string] $AzSKTempStatePath = (Join-Path $([Constants]::AzSKAppFolderPath) "TempState" | Join-Path -ChildPath "BatchScanData"); hidden [string] $MasterFilePath; hidden [PSObject] $BatchScanTrackerObj = $null; hidden [PSObject] $ScanPendingForBatch = $null; hidden static [BatchScanManager] $Instance =$null; hidden [int] $BatchSize = 0; hidden [bool] $isUpdated = $false; static [BatchScanManager] GetInstance( [string] $OrganizationName,[string] $ProjectName) { if ( $null -eq [BatchScanManager]::Instance) { [BatchScanManager]::Instance = [BatchScanManager]::new($OrganizationName,$ProjectName); } [BatchScanManager]::Instance.OrgName = $OrganizationName; [BatchScanManager]::Instance.ProjectName = $ProjectName; return [BatchScanManager]::Instance } static [BatchScanManager] GetInstance() { if ( $null -eq [BatchScanManager]::Instance) { [BatchScanManager]::Instance = [BatchScanManager]::new(); } return [BatchScanManager]::Instance } static [void] ClearInstance() { [BatchScanManager]::Instance = $null } BatchScanManager([string] $OrganizationName,[string] $ProjectName){ $this.ControlSettings = [ConfigurationManager]::LoadServerConfigFile("ControlSettings.json"); $this.OrgName = $OrganizationName; if($this.CheckIfProjectValid($ProjectName) -eq $false){ Write-Host "You have supplied an invalid project name. Re run the command with correct project." -ForegroundColor Red throw; } $this.ProjectName=$ProjectName; if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("BatchSize")){ $this.BatchSize = $PSCmdlet.MyInvocation.BoundParameters["BatchSize"] } else { $this.BatchSize = $this.ControlSettings.BatchScan.BatchTrackerUpdateFrequency } #need to make batch size half as both builds and releases will be scanned if($PSCmdlet.MyInvocation.BoundParameters.ResourceTypeName -eq "Build_Release"){ if($this.BatchSize%2 -eq 0){ $this.BatchSize=$this.BatchSize/2; } else { $this.BatchSize=($this.BatchSize-1)/2; } } if ([string]::isnullorwhitespace($this.BatchScanTrackerFileName)) { $this.BatchScanTrackerFileName = [Constants]::BatchScanTrackerBlobName } $this.GetBatchScanTrackerObject(); } BatchScanManager() { $this.ControlSettings = [ConfigurationManager]::LoadServerConfigFile("ControlSettings.json"); if ([string]::isnullorwhitespace($this.BatchScanTrackerFileName)) { $this.BatchScanTrackerFileName = [Constants]::BatchScanTrackerBlobName } $this.GetBatchScanTrackerObject(); } [bool] CheckIfProjectValid($ProjectName){ $apiURL = 'https://dev.azure.com/{0}/_apis/projects?$top=1000&api-version=6.0' -f $($this.OrgName); $responseObj = ""; try { $responseObj = [WebRequestHelper]::InvokeGetWebRequest($apiURL) ; } catch { Write-Host 'Project not found: Incorrect project name or you do not have necessary permission to access the project.' -ForegroundColor Red throw; } if (([Helpers]::CheckMember($responseObj, "count") -and $responseObj[0].count -gt 0) -or (($responseObj | Measure-Object).Count -gt 0 -and [Helpers]::CheckMember($responseObj[0], "name"))) { $projects = $responseObj | Where-Object { $ProjectName -contains $_.name } if (!$projects) { return $false; } } return $true; } [int] GetBatchSize() { return $this.BatchSize } hidden [void] GetBatchScanTrackerObject(){ if(![string]::isnullorwhitespace($this.OrgName) -and ![string]::isnullorwhitespace($this.ProjectName)){ if(-not (Test-Path (Join-Path (Join-Path $this.AzSKTempStatePath $this.OrgName) $this.ProjectName))) { New-Item -ItemType Directory -Path (Join-Path (Join-Path $this.AzSKTempStatePath $this.OrgName) $this.ProjectName) -ErrorAction Stop | Out-Null } } else{ if(-not (Test-Path "$this.AzSKTempStatePath")) { New-Item -ItemType Directory -Path "$this.AzSKTempStatePath" -ErrorAction Stop | Out-Null } } if($null -ne $this.MasterFilePath){ $this.BatchScanTrackerObj = Get-content $this.MasterFilePath | ConvertFrom-Json } else { $this.BatchScanTrackerObj=$null; } } [PSObject] GetBatchStatus(){ return Get-content $this.MasterFilePath | ConvertFrom-Json; } hidden [void] GetBatchTrackerFile($OrgName,$ProjectName){ $this.OrgName=$OrgName; $this.ProjectName=$ProjectName; if(![string]::isnullorwhitespace($this.OrgName) -and ![string]::isnullorwhitespace($this.ProjectName)){ if(Test-Path (Join-Path (Join-Path $this.AzSKTempStatePath $this.OrgName) $this.BatchScanTrackerFileName)) { $this.ScanPendingForBatch = Get-Content (Join-Path (Join-Path $this.AzSKTempStatePath (Join-Path $this.OrgName $this.ProjectName)) $this.BatchScanTrackerFileName) -Raw } $this.MasterFilePath = (Join-Path (Join-Path $this.AzSKTempStatePath (Join-Path $this.OrgName $this.ProjectName)) $this.BatchScanTrackerFileName) } else { $this.MasterFilePath = (Join-Path $this.AzSKTempStatePath $this.BatchScanTrackerFileName) } } [void] RemoveBatchScanData(){ if($null -ne $this.BatchScanTrackerObj){ if(![string]::isnullorwhitespace($this.OrgName) -and ![string]::isnullorwhitespace($this.ProjectName)){ if(Test-Path (Join-Path $this.AzSKTempStatePath (Join-Path $this.OrgName $this.ProjectName))) { Remove-Item -Path (Join-Path (Join-Path $this.AzSKTempStatePath (Join-Path $this.OrgName $this.ProjectName)) $this.BatchScanTrackerFileName) } } $this.BatchScanTrackerObj=$null; } } hidden[bool] IsBatchScanInProgress($OrgName,$ProjectName){ $this.GetBatchTrackerFile($OrgName,$ProjectName); if($null -ne $this.ControlSettings.BatchScan){ $batchTrackerFileValidForDays = [Int32]::Parse($this.ControlSettings.BatchScan.BatchTrackerValidforDays); $this.GetBatchScanTrackerObject(); if($null -eq $this.BatchScanTrackerObj){ return $false; } if( (Get-Item $this.MasterFilePath).creationtime.AddDays($batchTrackerFileValidforDays) -lt [DateTime]::UtcNow) { $this.RemoveBatchScanData(); $this.ScanPendingForBatch = $null; return $false; } return $true; } else { $this.ScanPendingForBatch=$null; return $false; } return $true; } [void] CreateBatchMasterList(){ $batchStatus = [BatchScanResourceMap]@{ Skip = 0; Top = $this.GetBatchSize(); BuildCurrentContinuationToken=$null; BuildNextContinuationToken=$null; ReleaseCurrentContinuationToken=$null; ReleaseNextContinuationToken=$null; BatchScanState= [BatchScanState]::INIT; TokenLastModifiedTime = [DateTime]:: UtcNow; ResourceCount=0; SkipMarker = 'False'; UpcError = 'False' } if($PSCmdlet.MyInvocation.BoundParameters.ResourceTypeName -eq "Build"){ $batchStatus = $batchStatus | Select-Object -Property * -ExcludeProperty ReleaseCurrentContinuationToken $batchStatus = $batchStatus | Select-Object -Property * -ExcludeProperty ReleaseNextContinuationToken $batchStatus = $batchStatus | Select-Object -Property * -ExcludeProperty SkipMarker } if($PSCmdlet.MyInvocation.BoundParameters.ResourceTypeName -eq "Release"){ $batchStatus = $batchStatus | Select-Object -Property * -ExcludeProperty BuildCurrentContinuationToken $batchStatus = $batchStatus | Select-Object -Property * -ExcludeProperty BuildNextContinuationToken $batchStatus = $batchStatus | Select-Object -Property * -ExcludeProperty SkipMarker } $this.BatchScanTrackerObj=$batchStatus; $this.WriteToBatchTrackerFile() } [void] WriteToBatchTrackerFile() { if($null -ne $this.BatchScanTrackerObj){ if(![string]::isnullorwhitespace($this.OrgName) -and ![string]::isnullorwhitespace($this.ProjectName)){ if(-not (Test-Path (Join-Path $this.AzSKTempStatePath (Join-Path $this.OrgName $this.ProjectName)))) { New-Item -ItemType Directory -Path (Join-Path $this.AzSKTempStatePath (Join-Path $this.OrgName $this.ProjectName)) -ErrorAction Stop | Out-Null } } else{ if(-not (Test-Path "$this.AzSKTempStatePath")) { New-Item -ItemType Directory -Path "$this.AzSKTempStatePath" -ErrorAction Stop | Out-Null } } Write-Host "Updating batch tracker file" -ForegroundColor Green [JsonHelper]::ConvertToJsonCustom( $this.BatchScanTrackerObj) | Out-File $this.MasterFilePath -Force Write-Host "Batch tracker file updated" -ForegroundColor Green } } #to check if anyone either builds or releases have been scanned and other resource is still left, is useful only when build_release is resource type [bool] isPreviousScanPartiallyComplete(){ if(![string]::isnullorwhitespace($this.OrgName) -and ![string]::isnullorwhitespace($this.ProjectName)){ if( ($null -ne $this.MasterFilePath) -and (Test-Path $this.MasterFilePath)){ $batchStatus = Get-Content $this.MasterFilePath | ConvertFrom-Json if($batchStatus.Skip -gt 0 -and [string]::IsNullOrEmpty($batchStatus.ReleaseNextContinuationToken) -and $batchStatus.BatchScanState -eq [BatchScanState]::COMP) { return $true; } if($batchStatus.Skip -gt 0 -and [string]::IsNullOrEmpty($batchStatus.BuildNextContinuationToken) -and $batchStatus.BatchScanState -eq [BatchScanState]::COMP) { return $true; } if($batchStatus.Skip -gt 0 -and [string]::IsNullOrEmpty($batchStatus.ReleaseNextContinuationToken) -and [string]::IsNullOrEmpty($batchStatus.ReleaseCurrentContinuationToken)) { return $true; } if($batchStatus.Skip -gt 0 -and [string]::IsNullOrEmpty($batchStatus.BuildNextContinuationToken) -and [string]::IsNullOrEmpty($batchStatus.BuildCurrentContinuationToken)) { return $true; } } } return $false; } hidden static [PSObject] GetBaseFrameworkPath() { $moduleName = $([Constants]::AzSKModuleName) #Remove Staging from module name before forming config base path $moduleName = $moduleName -replace "Staging", "" #Irrespective of whether Dev-Test mode is on or off, base framework path will now remain same as the new source code repo doesn't have AzSK.Framework folder. $basePath = (Get-Item $PSScriptRoot).Parent.FullName return $basePath } hidden static [PSObject] LoadFrameworkConfigFile([string] $fileName, [bool] $parseJson) { #Load file from AzSK App folder" $fileName = $fileName.Split('\')[-1] $extension = [System.IO.Path]::GetExtension($fileName); $basePath = [BatchScanManager]::GetBaseFrameworkPath() $rootConfigPath = $basePath | Join-Path -ChildPath "Configurations"; $filePath = (Get-ChildItem $rootConfigPath -Name -Recurse -Include $fileName) | Select-Object -First 1 if ($filePath) { if ($parseJson) { if ($extension -eq ".json" -or $extension -eq ".lawsview") { $fileContent = (Get-Content -Raw -Path (Join-Path $rootConfigPath $filePath)) | ConvertFrom-Json } else { $fileContent = (Get-Content -Raw -Path (Join-Path $rootConfigPath $filePath)) } } else { $fileContent = (Get-Content -Raw -Path (Join-Path $rootConfigPath $filePath)) } } else { throw "Unable to find the specified file '$fileName'" } if (-not $fileContent) { throw "The specified file '$fileName' is empty" } return $fileContent; } [void] UpdateBatchMasterList(){ if(![string]::isnullorwhitespace($this.OrgName) -and ![string]::isnullorwhitespace($this.ProjectName)){ if(Test-Path $this.MasterFilePath){ $batchStatus = Get-Content $this.MasterFilePath | ConvertFrom-Json $isReleaseScan=$false; $isBuildScan=$false; if($batchStatus.PSobject.Properties.name -match "ReleaseCurrentContinuationToken") { $isReleaseScan=$true; } if($batchStatus.PSobject.Properties.name -match "BuildCurrentContinuationToken") { $isBuildScan=$true; } if($batchStatus.BatchScanState -eq [BatchScanState]:: INIT ){ if($batchStatus.Skip -eq 0){ if($isReleaseScan) { $batchStatus.ReleaseCurrentContinuationToken=$null; } if($isBuildScan) { $batchStatus.BuildCurrentContinuationToken=$null; } Write-Host "Found a previous batch scan with no scanned resources. Continuing the scan from start `n " -ForegroundColor Green } else { #anyone of the resource has been completely scanned need to make batch size double again if($PSCmdlet.MyInvocation.BoundParameters.ResourceTypeName -eq 'Build_Release' -and $this.isPreviousScanPartiallyComplete() ){ if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("BatchSize")){ $this.BatchSize = $PSCmdlet.MyInvocation.BoundParameters["BatchSize"] } else { $this.BatchSize = $this.ControlSettings.BatchScan.BatchTrackerUpdateFrequency } if($this.BatchSize%2 -ne 0){ $this.BatchSize=$this.BatchSize-1 } } Write-Host "Found a previous batch scan in progress with $($batchStatus.ResourceCount) resources scanned. Resuming the scan from last batch. `n " -ForegroundColor Green if($this.CheckContTokenValidity($batchStatus.TokenLastModifiedTime)){ return; } else { #find the updated token if($isBuildScan -and $batchStatus.Skip -ne 0 -and (-not [string]::IsNullOrEmpty($batchStatus.BuildCurrentContinuationToken))){ $batchStatus.BuildCurrentContinuationToken=$this.GetUpdatedContToken($batchStatus.Skip,$batchStatus.Top,'Build'); } if($isReleaseScan -and $batchStatus.Skip -ne 0 -and (-not [string]::IsNullOrEmpty($batchStatus.ReleaseCurrentContinuationToken))){ $batchStatus.ReleaseCurrentContinuationToken=$this.GetUpdatedContToken($batchStatus.Skip,$batchStatus.Top,'Release'); } $batchStatus.TokenLastModifiedTime=[DateTime]::UtcNow; } } } else { #anyone of the resource has been completely scanned need to make batch size double again if($PSCmdlet.MyInvocation.BoundParameters.ResourceTypeName -eq 'Build_Release' -and $this.isPreviousScanPartiallyComplete() ){ if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("BatchSize")){ $this.BatchSize = $PSCmdlet.MyInvocation.BoundParameters["BatchSize"] } else { $this.BatchSize = $this.ControlSettings.BatchScan.BatchTrackerUpdateFrequency } if($this.BatchSize%2 -ne 0){ $this.BatchSize=$this.BatchSize-1 } } Write-Host "Found a previous batch scan with $($batchStatus.ResourceCount) resources scanned. Starting fresh scan for the next batch. `n " -ForegroundColor Green #anyone of the resource has been completely scanned need to update skip by original batch size. However for the first time skip should only be updated by half if($PSCmdlet.MyInvocation.BoundParameters.ResourceTypeName -eq 'Build_Release' -and $batchStatus.SkipMarker -eq "False" -and $this.isPreviousScanPartiallyComplete() ){ $batchStatus.Skip=$batchStatus.Skip + ($this.GetBatchSize()/2); $batchStatus.SkipMarker = "True" } else { $batchStatus.Skip+=$this.GetBatchSize(); } $batchStatus.BatchScanState=[BatchScanState]::INIT if($this.CheckContTokenValidity($batchStatus.TokenLastModifiedTime)){ if($isReleaseScan) { $batchStatus.ReleaseCurrentContinuationToken=$batchStatus.ReleaseNextContinuationToken } if($isBuildScan){ $batchStatus.BuildCurrentContinuationToken=$batchStatus.BuildNextContinuationToken } } else { #find the updated token if($isBuildScan -and $batchStatus.Skip -ne 0 -and (-not [string]::IsNullOrEmpty($batchStatus.BuildNextContinuationToken))){ $batchStatus.BuildCurrentContinuationToken=$this.GetUpdatedContToken($batchStatus.Skip,$batchStatus.Top,'Build'); } if($isReleaseScan -and $batchStatus.Skip -ne 0 -and (-not [string]::IsNullOrEmpty($batchStatus.ReleaseNextContinuationToken))){ $batchStatus.ReleaseCurrentContinuationToken=$this.GetUpdatedContToken($batchStatus.Skip,$batchStatus.Top,'Release'); } #in case builds have been completely scanned, i.e end of builds if($isBuildScan -and $batchStatus.Skip -ne 0 -and [string]::IsNullOrEmpty($batchStatus.BuildNextContinuationToken)){ $batchStatus.BuildCurrentContinuationToken=$batchStatus.BuildNextContinuationToken } #in case releases have been completely scanned, i.e end of releases if($isReleaseScan -and $batchStatus.Skip -ne 0 -and [string]::IsNullOrEmpty($batchStatus.ReleaseNextContinuationToken)){ $batchStatus.ReleaseCurrentContinuationToken=$batchStatus.ReleaseNextContinuationToken } $batchStatus.TokenLastModifiedTime=[DateTime]::UtcNow; } } $this.BatchScanTrackerObj=$batchStatus; $this.WriteToBatchTrackerFile(); } } } [bool] IsScanComplete(){ if($PSCmdlet.MyInvocation.BoundParameters.ResourceTypeName -eq 'Build' -and [string]::IsNullOrEmpty($this.GetBuildContinuationToken()) -and $this.GetBatchScanState() -eq [BatchScanState]::COMP){ return $true; } elseif($PSCmdlet.MyInvocation.BoundParameters.ResourceTypeName -eq 'Release' -and [string]::IsNullOrEmpty($this.GetReleaseContinuationToken()) -and $this.GetBatchScanState() -eq [BatchScanState]::COMP){ return $true; } elseif($PSCmdlet.MyInvocation.BoundParameters.ResourceTypeName -eq 'Build_Release' -and [string]::IsNullOrEmpty($this.GetReleaseContinuationToken()) -and [string]::IsNullOrEmpty($this.GetBuildContinuationToken()) -and $this.GetBatchScanState() -eq [BatchScanState]::COMP) { return $true; } else{ $batchStatus = Get-Content $this.MasterFilePath | ConvertFrom-Json if($batchStatus.UpcError -eq 'False'){ Write-Host "Another project seems to be in partial commit. Therefore the scan for this project cannot be completed. Either complete the scan for the previous project using the GADS command or delete the file %LOCALAPPDATA%/Microsoft/AzSK.ADO/TempState/PartialScanData/[org_name]" -ForegroundColor Yellow return $true; } else{ return $false; } } return $false; } hidden [bool] CheckContTokenValidity([DateTime] $lastModifiedTime){ if($lastModifiedTime.AddHours([INT32]::Parse(15)) -lt [DateTime]::UtcNow){ return $false } return $true; } [string] GetSkip(){ if(![string]::isnullorwhitespace($this.OrgName) -and ![string]::isnullorwhitespace($this.ProjectName)){ if(Test-Path $this.MasterFilePath){ $batchStatus = Get-Content $this.MasterFilePath | ConvertFrom-Json return $batchStatus.Skip; } } return $null; } [string] GetTop(){ if(![string]::isnullorwhitespace($this.OrgName) -and ![string]::isnullorwhitespace($this.ProjectName)){ if(Test-Path $this.MasterFilePath){ $batchStatus = Get-Content $this.MasterFilePath | ConvertFrom-Json return $batchStatus.Top; } } return $null; } [string] GetBuildContinuationToken(){ if(![string]::isnullorwhitespace($this.OrgName) -and ![string]::isnullorwhitespace($this.ProjectName)){ if(Test-Path $this.MasterFilePath){ $batchStatus = Get-Content $this.MasterFilePath | ConvertFrom-Json return $batchStatus.BuildNextContinuationToken; } } return $null; } [string] GetReleaseContinuationToken(){ if(![string]::isnullorwhitespace($this.OrgName) -and ![string]::isnullorwhitespace($this.ProjectName)){ if(Test-Path $this.MasterFilePath){ $batchStatus = Get-Content $this.MasterFilePath | ConvertFrom-Json return $batchStatus.ReleaseNextContinuationToken; } } return $null; } [BatchScanState] GetBatchScanState(){ if(![string]::isnullorwhitespace($this.OrgName) -and ![string]::isnullorwhitespace($this.ProjectName)){ if(Test-Path $this.MasterFilePath){ $batchStatus = Get-Content $this.MasterFilePath | ConvertFrom-Json return $batchStatus.BatchScanState; } } return $null; } [string] GetUpdatedContToken([int] $skip, [string] $top, [string] $resourceType){ $tempSkip=0; if($PSCmdlet.MyInvocation.BoundParameters.ResourceTypeName -eq 'Build_Release' -and $this.isPreviousScanPartiallyComplete() ){ $topNQueryString = '&$top={0}' -f ($this.GetBatchSize()/2); } else { $topNQueryString = '&$top={0}' -f $this.GetBatchSize(); } if($resourceType -eq 'Build'){ $resourceDefnURL = ("https://dev.azure.com/{0}/{1}/_apis/build/definitions?queryOrder=lastModifiedDescending&api-version=6.0" +$topNQueryString) -f $this.OrgName, $this.ProjectName; } else { $resourceDefnURL = ("https://vsrm.dev.azure.com/{0}/{1}/_apis/release/definitions?api-version=6.0" +$topNQueryString) -f $this.OrgName, $this.ProjectName; } $continuationToken=$null; $originalUri=$resourceDefnURL; $validationUrl=$null; while($tempSkip -lt $skip){ $validationUrl=$originalUri; $originalUri=$resourceDefnURL; if($PSCmdlet.MyInvocation.BoundParameters.ResourceTypeName -eq 'Build_Release' -and $this.isPreviousScanPartiallyComplete() ){ $tempSkip+=($this.GetBatchSize()/2); } else { $tempSkip+=$this.GetBatchSize(); } $updatedUriAndContToken=[WebRequestHelper]:: InvokeWebRequestForContinuationToken($validationUrl,$originalUri,$tempSkip,$resourceType); $continuationToken=$updatedUriAndContToken[0]; $originalUri=$updatedUriAndContToken[1]; } return $continuationToken; } } # SIG # Begin signature block # MIInpQYJKoZIhvcNAQcCoIInljCCJ5ICAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCoK/k19q382Opj # MHIEkt9FdMF9cefc0jeEuYipMGUXzKCCDYUwggYDMIID66ADAgECAhMzAAADTU6R # phoosHiPAAAAAANNMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjMwMzE2MTg0MzI4WhcNMjQwMzE0MTg0MzI4WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDUKPcKGVa6cboGQU03ONbUKyl4WpH6Q2Xo9cP3RhXTOa6C6THltd2RfnjlUQG+ # Mwoy93iGmGKEMF/jyO2XdiwMP427j90C/PMY/d5vY31sx+udtbif7GCJ7jJ1vLzd # j28zV4r0FGG6yEv+tUNelTIsFmmSb0FUiJtU4r5sfCThvg8dI/F9Hh6xMZoVti+k # bVla+hlG8bf4s00VTw4uAZhjGTFCYFRytKJ3/mteg2qnwvHDOgV7QSdV5dWdd0+x # zcuG0qgd3oCCAjH8ZmjmowkHUe4dUmbcZfXsgWlOfc6DG7JS+DeJak1DvabamYqH # g1AUeZ0+skpkwrKwXTFwBRltAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUId2Img2Sp05U6XI04jli2KohL+8w # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwMDUxNzAfBgNVHSMEGDAW # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB # ACMET8WuzLrDwexuTUZe9v2xrW8WGUPRQVmyJ1b/BzKYBZ5aU4Qvh5LzZe9jOExD # YUlKb/Y73lqIIfUcEO/6W3b+7t1P9m9M1xPrZv5cfnSCguooPDq4rQe/iCdNDwHT # 6XYW6yetxTJMOo4tUDbSS0YiZr7Mab2wkjgNFa0jRFheS9daTS1oJ/z5bNlGinxq # 2v8azSP/GcH/t8eTrHQfcax3WbPELoGHIbryrSUaOCphsnCNUqUN5FbEMlat5MuY # 94rGMJnq1IEd6S8ngK6C8E9SWpGEO3NDa0NlAViorpGfI0NYIbdynyOB846aWAjN # fgThIcdzdWFvAl/6ktWXLETn8u/lYQyWGmul3yz+w06puIPD9p4KPiWBkCesKDHv # XLrT3BbLZ8dKqSOV8DtzLFAfc9qAsNiG8EoathluJBsbyFbpebadKlErFidAX8KE # usk8htHqiSkNxydamL/tKfx3V/vDAoQE59ysv4r3pE+zdyfMairvkFNNw7cPn1kH # Gcww9dFSY2QwAxhMzmoM0G+M+YvBnBu5wjfxNrMRilRbxM6Cj9hKFh0YTwba6M7z # ntHHpX3d+nabjFm/TnMRROOgIXJzYbzKKaO2g1kWeyG2QtvIR147zlrbQD4X10Ab # rRg9CpwW7xYxywezj+iNAc+QmFzR94dzJkEPUSCJPsTFMIIHejCCBWKgAwIBAgIK # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+ # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6 # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3 # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7 # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/ # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGXYwghlyAgEBMIGVMH4x # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAANNTpGmGiiweI8AAAAA # A00wDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIEWW # 6JLAp6Afcmkawoa+rJ8riyg4Dv8wwSgw1qF5Yo7XMEIGCisGAQQBgjcCAQwxNDAy # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20wDQYJKoZIhvcNAQEBBQAEggEAq9B+tm1ciyoXVu2taMKFq24U8j0rCBHMGnFp # Wr0j4ZgfQjdPAwGcNJUYOroO2xzQeHb832M++L+hw1ReEu3KKTRknDhEMP7JVG5D # bzcyj4w/RqHVJPvA9BZ2+CXw8/4Ohv+ECsQn1qah0pR+RxoceQZlaiKHQHnpTydb # tAvljjH/WqVpu9cHmRHvehqPoflJss88dzlJAIREH97Dpmqd71XdIZkcYrIsbiUM # z0Yyae5WFrleLEw0+8pHaDi8tJDcH1puydN4edNzeQXNWCQZBPPsWMP13y1+iF8O # d40Il4vSBsqhd+Lx6R6ZF8aJsJrNeIRn3teNofCNhz4r//r7TaGCFwAwghb8Bgor # BgEEAYI3AwMBMYIW7DCCFugGCSqGSIb3DQEHAqCCFtkwghbVAgEDMQ8wDQYJYIZI # AWUDBAIBBQAwggFRBgsqhkiG9w0BCRABBKCCAUAEggE8MIIBOAIBAQYKKwYBBAGE # WQoDATAxMA0GCWCGSAFlAwQCAQUABCCo/REQgBSTdpSC7fEY30e/2I5ZXou3+XRC # UTFW+w9nuQIGZIr321JnGBMyMDIzMDYxNjA4MjcwOC41MDVaMASAAgH0oIHQpIHN # MIHKMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQL # ExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMg # VFNTIEVTTjpERDhDLUUzMzctMkZBRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt # U3RhbXAgU2VydmljZaCCEVcwggcMMIIE9KADAgECAhMzAAABxQPNzSGh9O85AAEA # AAHFMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw # MB4XDTIyMTEwNDE5MDEzMloXDTI0MDIwMjE5MDEzMlowgcoxCzAJBgNVBAYTAlVT # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVy # aWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOkREOEMtRTMz # Ny0yRkFFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIC # IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq0hds70eX23J7pappaKXRhz+ # TT7JJ3OvVf3+N8fNpxRs5jY4hEv3BV/w5EWXbZdO4m3xj01lTI/xDkq+ytjuiPe8 # xGXsZxDntv7L1EzMd5jISqJ+eYu8kgV056mqs8dBo55xZPPPcxf5u19zn04aMQF5 # PXV/C4ZLSjFa9IFNcribdOm3lGW1rQRFa2jUsup6gv634q5UwH09WGGu0z89Rbtb # yM55vmBgWV8ed6bZCZrcoYIjML8FRTvGlznqm6HtwZdXMwKHT3a/kLUSPiGAsrIg # Ezz7NpBpeOsgs9TrwyWTZBNbBwyIACmQ34j+uR4et2hZk+NH49KhEJyYD2+dOIaD # GB2EUNFSYcy1MkgtZt1eRqBB0m+YPYz7HjocPykKYNQZ7Tv+zglOffCiax1jOb0u # 6IYC5X1Jr8AwTcsaDyu3qAhx8cFQN9DDgiVZw+URFZ8oyoDk6sIV1nx5zZLy+hNt # akePX9S7Y8n1qWfAjoXPE6K0/dbTw87EOJL/BlJGcKoFTytr0zPg/MNJSb6f2a/w # DkXoGCGWJiQrGTxjOP+R96/nIIG05eE1Lpky2FOdYMPB4DhW7tBdZautepTTuShm # gn+GKER8AoA1gSSk1EC5ZX4cppVngJpblMBu8r/tChfHVdXviY6hDShHwQCmZqZe # bgSYHnHl4urE+4K6ZC8CAwEAAaOCATYwggEyMB0GA1UdDgQWBBRU6rs4v1mxNYG/ # rtpLwrVwek0FazAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNV # HR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2Ny # bC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYI # KwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAy # MDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMA0G # CSqGSIb3DQEBCwUAA4ICAQCMqN58frMHOScciK+Cdnr6dK8fTsgQDeZ9bvQjCuxN # IJZJ92+xpeKRCf3Xq47qdRykkKUnZC6dHhLwt1fhwyiy/LfdVQ9yf1hYZ/RpTS+z # 0hnaoK+P/IDAiUNm32NXLhDBu0P4Sb/uCV4jOuNUcmJhppBQgQVhFx/57JYk1LCd # jIee//GrcfbkQtiYob9Oa93DSjbsD1jqaicEnkclUN/mEm9ZsnCnA1+/OQDp/8Q4 # cPfH94LM4J6X0NtNBeVywvWH0wuMaOJzHgDLCeJUkFE9HE8sBDVedmj6zPJAI+7o # zLjYqw7i4RFbiStfWZSGjwt+lLJQZRWUCcT3aHYvTo1YWDZskohWg77w9fF2QbiO # 9DfnqoZ7QozHi7RiPpbjgkJMAhrhpeTf/at2e9+HYkKObUmgPArH1Wjivwm1d7PY # WsarL7u5qZuk36Gb1mETS1oA2XX3+C3rgtzRohP89qZVf79lVvjmg34NtICK/pMk # 99SButghtipFSMQdbXUnS2oeLt9cKuv1MJu+gJ83qXTNkQ2QqhxtNRvbE9QqmqJQ # w5VW/4SZze1pPXxyOTO5yDq+iRIUubqeQzmUcCkiyNuCLHWh8OLCI5mIOC1iLtVD # f2lw9eWropwu5SDJtT/ZwqIU1qb2U+NjkNcj1hbODBRELaTTWd91RJiUI9ncJkGg # /jCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcNAQEL # BQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH # EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNV # BAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4X # DTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMCVVMxEzAR # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p # Y3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3Rh # bXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM # 57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg4r25PhdgM/9cT8dm # 95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPFdvWGUNzB # RMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6GnszrYBb # fowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBpDco2LXCO # Mcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL64NF50ZuyjLVwIYw # XE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW # /aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0lBw0gg/w # EPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1qGFphAXPK # Z6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2 # BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PAPBXbGjfH # CBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkwEgYJKwYB # BAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxGNSnPEP8v # BO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARVMFMwUQYM # KwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0 # LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEF # BQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD # VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBW # BgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny # bC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUH # AQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp # L2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0BAQsF # AAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0xM7U518Jx # Nj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmCVgADsAW+ # iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449xvNo32X2 # pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wMnosZiefw # C2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7 # T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2dY3RILLFO # Ry3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxnGSgkujhL # mm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3L # wUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokLjzbaukz5 # m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL6Xu/OHBE # 0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggLOMIICNwIB # ATCB+KGB0KSBzTCByjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEmMCQGA1UE # CxMdVGhhbGVzIFRTUyBFU046REQ4Qy1FMzM3LTJGQUUxJTAjBgNVBAMTHE1pY3Jv # c29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAHBgUrDgMCGgMVACEAGvYXZJK7 # cUo62+LvEYQEx7/noIGDMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw # MTAwDQYJKoZIhvcNAQEFBQACBQDoNh76MCIYDzIwMjMwNjE2MDczNjI2WhgPMjAy # MzA2MTcwNzM2MjZaMHcwPQYKKwYBBAGEWQoEATEvMC0wCgIFAOg2HvoCAQAwCgIB # AAICEloCAf8wBwIBAAICEVAwCgIFAOg3cHoCAQAwNgYKKwYBBAGEWQoEAjEoMCYw # DAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0B # AQUFAAOBgQBakBpdMOT3Jcbqw9sLyfylXhNcEX5TlqqHTtpWhiIlccoc+uuTCMtP # A0qMFQ7Y/4bWVvN1jSCnPnbU34J1wyqtKdnkW+talWZNkyh5biK7/DlPDoMPr6rG # Bx4IY/vn5MxX1ryVBWDuK2Uuj+wMNmrsKigrYyta0BuImECgICj3cjGCBA0wggQJ # AgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD # VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAk # BgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABxQPNzSGh # 9O85AAEAAAHFMA0GCWCGSAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZI # hvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEILmw91elRxN7YRUX373tapRa2qK99UgU # sihQsvS3PzQEMIH6BgsqhkiG9w0BCRACLzGB6jCB5zCB5DCBvQQgGQGxkfYkd0wK # +V09wO0sO+sm8gAMyj5EuKPqvNQ/fLEwgZgwgYCkfjB8MQswCQYDVQQGEwJVUzET # MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV # TWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T # dGFtcCBQQ0EgMjAxMAITMwAAAcUDzc0hofTvOQABAAABxTAiBCBP93xuC5haMhsv # J/S7kTm6RPZojzZjrN8lyRTeOXgaeTANBgkqhkiG9w0BAQsFAASCAgB4IKrslqZc # Ulr5IVVY00bxEYt5WY7c2qavSKZkcYWfCIaRivsJisYoidm89s+7lRYs0ph+Sebb # Bf4mDENxN1mfDQGGg3So1rP4AhBW9qO9PkU8AseyZ0Q9u+79P0VsXq88HUohyYUB # lsTDkRscbbjoECYsNd8npGpcQKeY2cMYwOKLdEtDxovlLPNhPo9Grfo9LyihFpG6 # 1wBW5jOMMSxRRb2C5jwHuElNXYOn+mVWQX0NpuZsdqRQbb1Ef93V5pHA9z1upWq3 # NPuJxBeAs23ldx3tfigch/ZYu0Ubkik4zjDf/fPRc4pk2xZkp+MZiI5g27L54fPA # OLV/QaD959Kp8/2Pc2WSfsrxiF8fZeO0n8f8GdCSmUei1qK3CLYlk3nvJ5k4+1J5 # zy9XjPhLIVu0QZSVyjYIKUAy/nXYfOXtjpsSRMeZKIK85OtuamBVAESTcwraYu7o # PO58381shLbxn89Qf/FtBsQYshx6QySsBkz1J0uSf8CuOptZ3MyOkGp0K73iqHwB # 1/da7eyAUhc3W1xzDLzdU0puOUqGUKUFv6WteLFujAzgLzDOHtZk3pUmouieXttP # uFlexNDPHStKXUUCK+CC8CzIae5JrqWOMVTqvOaEEdLbDSxlAgsn++4dVDG37Zqw # FCf+0EcXDKZQE76qJafUb6/RsDRW7MFGZQ== # SIG # End signature block |