Framework/BugLog/AutoCloseBugManager.ps1
Set-StrictMode -Version Latest class AutoCloseBugManager { hidden [string] $OrganizationName; hidden [PSObject] $ControlSettings; hidden [string] $ScanSource; hidden [bool] $UseAzureStorageAccount = $false; hidden [BugLogHelper] $BugLogHelperObj; static [SVTEventContext []] $ClosedBugs=$null; hidden $ClosedBugTemplate= $null; AutoCloseBugManager([string] $orgName) { $this.OrganizationName = $orgName; $this.ControlSettings = [ConfigurationManager]::LoadServerConfigFile("ControlSettings.json"); $this.ScanSource = [AzSKSettings]::GetInstance().GetScanSource(); if ([Helpers]::CheckMember($this.ControlSettings.BugLogging, "UseAzureStorageAccount", $null)) { $this.UseAzureStorageAccount = $this.ControlSettings.BugLogging.UseAzureStorageAccount; if ($this.UseAzureStorageAccount) { $this.BugLogHelperObj = [BugLogHelper]::BugLogHelperInstance if (!$this.BugLogHelperObj) { $this.BugLogHelperObj = [BugLogHelper]::GetInstance($this.OrganizationName); } } } } #function to auto close resolved bugs hidden [void] AutoCloseBug([SVTEventContext []] $ControlResults) { #tags that need to be searched $TagSearchKeyword = "" #flag to check number of current keywords in the tag $QueryKeyWordCount = 0; #maximum no of keywords that need to be checked per batch $MaxKeyWordsToQuery=0; #all passing control results go here $PassedControlResults = @(); $autoCloseOrgBugFlag=$true $autoCloseProjBugFlag=$true; [AutoCloseBugManager]::ClosedBugs=$null try { $MaxKeyWordsToQuery = $this.ControlSettings.BugLogging.MaxKeyWordsToQueryForBugClose; $autoCloseOrgBugFlag=$this.ControlSettings.BugLogging.AutoCloseOrgBug $autoCloseProjBugFlag=$this.ControlSettings.BugLogging.AutoCloseProjectBug } catch { $MaxKeyWordsToQuery=30 $autoCloseOrgBugFlag=$true $autoCloseProjBugFlag=$true; } #collect all passed control results $ControlResults | ForEach-Object { if ($_.ControlResults[0].VerificationResult -eq "Passed") { #to check if org level bugs should be auto closed based on control settings if($_.FeatureName -eq "Organization"){ if($autoCloseOrgBugFlag -eq $true){ $PassedControlResults += $_ } } #to check if proj level bugs should be auto closed based on control settings elseif($_.FeatureName -eq "Project"){ if($autoCloseProjBugFlag -eq $true){ $PassedControlResults += $_ } } else { $PassedControlResults += $_ } } } #number of passed controls $PassedControlResultsLength = ($PassedControlResults | Measure-Object).Count #This Hash map is used to map an ADOScan hashtag value to a control. $hashToControlIDMap=@{} #the following loop will call api for bug closing in batches of size as defined in control settings, #first check if passed controls length is less than the batch size, if yes then we have to combine all tags in one go #and call the api #if length is more divide the control results in chunks of batch size, after a particular batch is made call the api #reinitialize the variables for the next batch $PassedControlResults | ForEach-Object { $control = $_; #if control results are less than the maximum no of tags per batch #ToDo add common method for both if and else condition if ($PassedControlResultsLength -lt $MaxKeyWordsToQuery) { #check for number of tags in current query $QueryKeyWordCount++; if ($this.UseAzureStorageAccount -and $this.ScanSource -eq "CA") { $tagHash=$this.GetHashedTag($control.ControlItem.Id, $control.ResourceContext.ResourceId) $hashToControlIDMap.add($tagHash,$control); #complete the query $TagSearchKeyword += "(ADOScannerHashId eq '" + $tagHash + "') or " #if the query count equals the passing control results, search for bugs for this batch if ($QueryKeyWordCount -eq $PassedControlResultsLength) { #to remove OR from the last tag keyword. Ex: Tags: Tag1 OR Tags: Tag2 OR. Remove the last OR from this keyword $TagSearchKeyword = $TagSearchKeyword.Substring(0, $TagSearchKeyword.length - 3) $closedBugsResponse = $this.BugLogHelperObj.GetTableEntityAndCloseBug($TagSearchKeyword) if ($closedBugsResponse){ $this.closedBugInfoCollect($closedBugsResponse, $hashToControlIDMap) } } } else { $tagHash=$this.GetHashedTag($control.ControlItem.Id, $control.ResourceContext.ResourceId) $hashToControlIDMap.add($tagHash,$control); $TagSearchKeyword += "Tags: " + $tagHash + " OR " #if the query count equals the passing control results, search for bugs for this batch if ($QueryKeyWordCount -eq $PassedControlResultsLength) { #to remove OR from the last tag keyword. Ex: Tags: Tag1 OR Tags: Tag2 OR. Remove the last OR from this keyword $TagSearchKeyword = $TagSearchKeyword.Substring(0, $TagSearchKeyword.length - 3) $response = $this.GetWorkItemByHash($TagSearchKeyword,$MaxKeyWordsToQuery) #if bug was present if ($response[0].results.count -gt 0) { $ids = @(); $ids += $response.results.fields."system.id"; $closedBugsResponse = $this.CloseBugsInBulk($ids); #$response.results | ForEach-Object { # #close the bug # $id = $_.fields."system.id" # $Project = $_.project.name # $this.CloseBug($id, $Project) #} if ($closedBugsResponse){ $this.closedBugInfoCollect($closedBugsResponse, $hashToControlIDMap) } } } } } #if the number of control results was more than batch size else { $QueryKeyWordCount++; if ($this.UseAzureStorageAccount -and $this.ScanSource -eq "CA") { $tagHash=$this.GetHashedTag($control.ControlItem.Id, $control.ResourceContext.ResourceId) $hashToControlIDMap.add($tagHash,$control); $TagSearchKeyword += "(ADOScannerHashId eq '" + $tagHash + "') or " #if number of tags reaches batch limit if ($QueryKeyWordCount -eq $MaxKeyWordsToQuery) { #query for all these tags and their bugs $TagSearchKeyword = $TagSearchKeyword.Substring(0, $TagSearchKeyword.length - 3) $closedBugsResponse = $this.BugLogHelperObj.GetTableEntityAndCloseBug($TagSearchKeyword); if ($closedBugsResponse){ $this.closedBugInfoCollect($closedBugsResponse, $hashToControlIDMap) } #Reinitialize for the next batch $QueryKeyWordCount = 0; $TagSearchKeyword = ""; $PassedControlResultsLength -= $MaxKeyWordsToQuery $hashToControlIDMap.Clear(); } } else { $tagHash=$this.GetHashedTag($control.ControlItem.Id, $control.ResourceContext.ResourceId) $hashToControlIDMap.add($tagHash,$control); $TagSearchKeyword += "Tags: " + $tagHash + " OR " #if number of tags reaches batch limit if ($QueryKeyWordCount -eq $MaxKeyWordsToQuery) { #query for all these tags and their bugs $TagSearchKeyword = $TagSearchKeyword.Substring(0, $TagSearchKeyword.length - 3) $response = $this.GetWorkItemByHash($TagSearchKeyword,$MaxKeyWordsToQuery) if ($response[0].results.count -gt 0) { $ids = @(); $ids += $response.results.fields."system.id"; $closedBugsResponse = $this.CloseBugsInBulk($ids); #$response.results | ForEach-Object { # $id = $_.fields."system.id" # $Project = $_.project.name # $this.CloseBug($id, $Project) #} if ($closedBugsResponse){ $this.closedBugInfoCollect($closedBugsResponse, $hashToControlIDMap) } } #Reinitialize for the next batch $QueryKeyWordCount = 0; $TagSearchKeyword = ""; $PassedControlResultsLength -= $MaxKeyWordsToQuery $hashToControlIDMap.Clear(); } } } } $hashToControlIDMap.Clear(); $hashToControlIDMap=$null Remove-Variable hashToControlIDMap; } #function to auto close resolved bugs hidden [void] AutoCloseBugCSV([SVTEventContext []] $PassedControlResults) { #tags that need to be searched $TagSearchKeyword = "" #flag to check number of current keywords in the tag $QueryKeyWordCount = 0; #maximum no of keywords that need to be checked per batch $MaxKeyWordsToQuery=0; $autoCloseOrgBugFlag=$true $autoCloseProjBugFlag=$true; [AutoCloseBugManager]::ClosedBugs=$null try { $MaxKeyWordsToQuery = $this.ControlSettings.BugLogging.MaxKeyWordsToQueryForBugClose; $autoCloseOrgBugFlag=$this.ControlSettings.BugLogging.AutoCloseOrgBug $autoCloseProjBugFlag=$this.ControlSettings.BugLogging.AutoCloseProjectBug } catch { $MaxKeyWordsToQuery=30 $autoCloseOrgBugFlag=$true $autoCloseProjBugFlag=$true; } #number of passed controls $PassedControlResultsLength = ($PassedControlResults | Measure-Object).Count #This Hash map is used to map an ADOScan hashtag value to a control. $hashToControlIDMap=@{} $PassedControlResults | ForEach-Object { $control = $_; #if control results are less than the maximum no of tags per batch #ToDo add common method for both if and else condition if ($PassedControlResultsLength -lt $MaxKeyWordsToQuery) { #check for number of tags in current query $QueryKeyWordCount++; if ($this.UseAzureStorageAccount ) { $tagHash=$this.GetHashedTag($control.ControlItem.Id, $control.ResourceContext.ResourceId) $hashToControlIDMap.add($tagHash,$control); #complete the query $TagSearchKeyword += "(ADOScannerHashId eq '" + $tagHash + "') or " #if the query count equals the passing control results, search for bugs for this batch if ($QueryKeyWordCount -eq $PassedControlResultsLength) { #to remove OR from the last tag keyword. Ex: Tags: Tag1 OR Tags: Tag2 OR. Remove the last OR from this keyword $TagSearchKeyword = $TagSearchKeyword.Substring(0, $TagSearchKeyword.length - 3) $closedBugsResponse = $this.BugLogHelperObj.GetTableEntityAndCloseBug($TagSearchKeyword) if ($closedBugsResponse){ $this.closedBugInfoCollect($closedBugsResponse, $hashToControlIDMap) } } } else { $tagHash=$this.GetHashedTag($control.ControlItem.Id, $control.ResourceContext.ResourceId) $hashToControlIDMap.add($tagHash,$control); $TagSearchKeyword += "Tags: " + $tagHash + " OR " #if the query count equals the passing control results, search for bugs for this batch if ($QueryKeyWordCount -eq $PassedControlResultsLength) { #to remove OR from the last tag keyword. Ex: Tags: Tag1 OR Tags: Tag2 OR. Remove the last OR from this keyword $TagSearchKeyword = $TagSearchKeyword.Substring(0, $TagSearchKeyword.length - 3) $response = $this.GetWorkItemByHash($TagSearchKeyword,$MaxKeyWordsToQuery) #if bug was present if ($response[0].results.count -gt 0) { $ids = @(); $ids += $response.results.fields."system.id"; $closedBugsResponse = $this.CloseBugsInBulk($ids); if ($closedBugsResponse){ $this.closedBugInfoCollect($closedBugsResponse, $hashToControlIDMap) } } } } } #if the number of control results was more than batch size else { $QueryKeyWordCount++; if ($this.UseAzureStorageAccount ) { $tagHash=$this.GetHashedTag($control.ControlItem.Id, $control.ResourceContext.ResourceId) $hashToControlIDMap.add($tagHash,$control); $TagSearchKeyword += "(ADOScannerHashId eq '" + $tagHash + "') or " #if number of tags reaches batch limit if ($QueryKeyWordCount -eq $MaxKeyWordsToQuery) { #query for all these tags and their bugs $TagSearchKeyword = $TagSearchKeyword.Substring(0, $TagSearchKeyword.length - 3) $closedBugsResponse = $this.BugLogHelperObj.GetTableEntityAndCloseBug($TagSearchKeyword); if ($closedBugsResponse){ $this.closedBugInfoCollect($closedBugsResponse, $hashToControlIDMap) } #Reinitialize for the next batch $QueryKeyWordCount = 0; $TagSearchKeyword = ""; $PassedControlResultsLength -= $MaxKeyWordsToQuery $hashToControlIDMap.Clear(); } } else { $tagHash=$this.GetHashedTag($control.ControlItem.Id, $control.ResourceContext.ResourceId) $hashToControlIDMap.add($tagHash,$control); $TagSearchKeyword += "Tags: " + $tagHash + " OR " #if number of tags reaches batch limit if ($QueryKeyWordCount -eq $MaxKeyWordsToQuery) { #query for all these tags and their bugs $TagSearchKeyword = $TagSearchKeyword.Substring(0, $TagSearchKeyword.length - 3) $response = $this.GetWorkItemByHash($TagSearchKeyword,$MaxKeyWordsToQuery) if ($response[0].results.count -gt 0) { $ids = @(); $ids += $response.results.fields."system.id"; $closedBugsResponse = $this.CloseBugsInBulk($ids); if ($closedBugsResponse){ $this.closedBugInfoCollect($closedBugsResponse, $hashToControlIDMap) } } #Reinitialize for the next batch $QueryKeyWordCount = 0; $TagSearchKeyword = ""; $PassedControlResultsLength -= $MaxKeyWordsToQuery $hashToControlIDMap.Clear(); } } } } $hashToControlIDMap.Clear(); $hashToControlIDMap=$null Remove-Variable hashToControlIDMap; } #function to close an active bug hidden [void] CloseBug([string] $id, [string] $Project) { $url = "https://dev.azure.com/{0}/{1}/_apis/wit/workitems/{2}?api-version=6.0" -f $this.OrganizationName, $Project, $id #load the closed bug template $BugTemplate = [ConfigurationManager]::LoadServerConfigFile("TemplateForClosedBug.Json") $BugTemplate = $BugTemplate | ConvertTo-Json -Depth 10 $header = [WebRequestHelper]::GetAuthHeaderFromUriPatch($url) try { $responseObj = Invoke-RestMethod -Uri $url -Method Patch -ContentType "application/json-patch+json ; charset=utf-8" -Headers $header -Body $BugTemplate } catch { Write-Host "Could not close the bug" -ForegroundColor Red } } #function to close an active bugs in bulk hidden [object] CloseBugsInBulk([string[]] $ids) { try { $closeBugTemplate = @(); if($PSCmdlet.MyInvocation.BoundParameters["ClosedBugTemplateFilePath"]){ $this.ClosedBugTemplate = Get-Content $PSCmdlet.MyInvocation.BoundParameters["ClosedBugTemplateFilePath"] | ConvertFrom-Json foreach ($id in $ids) { $closeBugTemplate += [PSCustomObject] @{ method = 'PATCH'; uri = "/_apis/wit/workitems/$($id)?api-version=4.1"; headers = @{"Content-Type" = 'application/json-patch+json'}; body =@($this.ClosedBugTemplate) } } } else{ foreach ($id in $ids) { $closeBugTemplate += [PSCustomObject] @{ method = 'PATCH'; uri = "/_apis/wit/workitems/$($id)?api-version=4.1"; headers = @{"Content-Type" = 'application/json-patch+json'}; body = @(@{op = "add"; "path"= "/fields/System.State"; "value"= "Closed"}; @{op = "add"; "path"= "/fields/Microsoft.VSTS.Common.ResolvedReason"; "value"= ""}) } } } if ($closeBugTemplate.count -gt 0) { $body = $null; if ($closeBugTemplate.count -eq 1) { $body = "[$($closeBugTemplate | ConvertTo-Json -depth 10)]" } else { $body = $closeBugTemplate | ConvertTo-Json -depth 10 } $uri = 'https://{0}.visualstudio.com/_apis/wit/$batch?api-version=4.1' -f $this.OrganizationName $header = [WebRequestHelper]::GetAuthHeaderFromUriPatch($uri) $adoResult = Invoke-RestMethod -Uri $uri -Method Patch -ContentType "application/json" -Headers $header -Body $body if ($adoResult -and $adoResult.count -gt 0) { return $adoResult.value; } } return $false; } catch { Write-Host $_ Write-Host "Could not close the bug." -ForegroundColor Red return $false } } hidden [void] closedBugInfoCollect([object] $closedBugsResponse, [hashtable] $hashToControlIDMap){ # Hash map checks for duplicate work items $hashClosedBugs=@{} $closedBugsResponse| ForEach-Object{ #Store closed bug details $bug=$_.body |ConvertFrom-Json $controlHashValue=$null #Fetch hash From storage account CA response if($this.UseAzureStorageAccount -and $this.ScanSource -eq "CA"){ $controlHashValue=$bug.ADOScannerHashID } #Fetch hash for regular scan else{ $controlHashValue=$bug.fields.'System.Tags' #in case the bug has multiple tags, even if bug is closed, CSV will not be generated if we dont find the tag explicit to scan id $controlHashValue = $controlHashValue.Split(";") | where {$_.Trim() -like "ADOScanID: *"} $controlHashValue = $controlHashValue.Trim(); } $bugState = 'Closed' if($null -ne $this.ClosedBugTemplate){ $bugState = ($this.ClosedBugTemplate | where {$_.path -like "*System.State*"}).value } if ($hashToControlIDMap.ContainsKey($controlHashValue) -and $bug.fields.'System.State' -eq $bugState) { $id=$bug.id $project=$bug.fields.'System.TeamProject' $urlClose= "https://dev.azure.com/{0}/{1}/_workitems/edit/{2}" -f $this.OrganizationName, $project , $id; $hashToControlIDMap[$controlHashValue].ControlResults.AddMessage("Closed Bug",$urlClose); # duplicate work items do not populate static variable $ClosedBugs multiple times if(!$hashClosedBugs.ContainsKey($controlHashValue)){ [AutoCloseBugManager]::ClosedBugs+=$hashToControlIDMap[$controlHashValue] $hashClosedBugs.add($controlHashValue,$true) } } } $hashClosedBugs.Clear() } #function to retrieve all new/active/resolved bugs hidden [object] GetWorkItemByHash([string] $hash,[int] $MaxKeyWordsToQuery) { $url = "https://almsearch.dev.azure.com/{0}/_apis/search/workitemsearchresults?api-version=6.0-preview.1" -f $this.OrganizationName #take results have been doubled, as their might be chances for a bug to be logged more than once, if the tag id is copied. #in this case we want all the instances of this bug to be closed #sprint 2201: added new states for standalone bug logging #TODO: in case we need custom system states for partner teams, fetch system states to check from org policy $body = '{"searchText": "{0}","$skip": 0,"$top": 60,"filters": {"System.TeamProject": [],"System.WorkItemType": ["Bug"],"System.State": ["New","Active","Resolved","Approved","Committed","In Progress","In Review"]}}'| ConvertFrom-Json $body.searchText = $hash $response = [WebRequestHelper]:: InvokePostWebRequest($url, $body) return $response } #function to create hash for bug tag hidden [string] GetHashedTag([string] $ControlId, [string] $ResourceId) { $hashedTag = $null $stringToHash = "$ResourceId#$ControlId"; #return the bug tag if ($this.UseAzureStorageAccount -and $this.ScanSource -eq "CA") { return [AutoBugLog]::ComputeHashX($stringToHash); } else { return "ADOScanID: " + [AutoBugLog]::ComputeHashX($stringToHash) } } } # SIG # Begin signature block # MIInuAYJKoZIhvcNAQcCoIInqTCCJ6UCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDgBe1uym8URWEm # mkmOZzFtrrmNtRUrA1UQLzrhgFRAdaCCDYEwggX/MIID56ADAgECAhMzAAACUosz # qviV8znbAAAAAAJSMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjEwOTAyMTgzMjU5WhcNMjIwOTAxMTgzMjU5WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDQ5M+Ps/X7BNuv5B/0I6uoDwj0NJOo1KrVQqO7ggRXccklyTrWL4xMShjIou2I # sbYnF67wXzVAq5Om4oe+LfzSDOzjcb6ms00gBo0OQaqwQ1BijyJ7NvDf80I1fW9O # L76Kt0Wpc2zrGhzcHdb7upPrvxvSNNUvxK3sgw7YTt31410vpEp8yfBEl/hd8ZzA # v47DCgJ5j1zm295s1RVZHNp6MoiQFVOECm4AwK2l28i+YER1JO4IplTH44uvzX9o # RnJHaMvWzZEpozPy4jNO2DDqbcNs4zh7AWMhE1PWFVA+CHI/En5nASvCvLmuR/t8 # q4bc8XR8QIZJQSp+2U6m2ldNAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUNZJaEUGL2Guwt7ZOAu4efEYXedEw # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDY3NTk3MB8GA1UdIwQYMBaAFEhu # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAFkk3 # uSxkTEBh1NtAl7BivIEsAWdgX1qZ+EdZMYbQKasY6IhSLXRMxF1B3OKdR9K/kccp # kvNcGl8D7YyYS4mhCUMBR+VLrg3f8PUj38A9V5aiY2/Jok7WZFOAmjPRNNGnyeg7 # l0lTiThFqE+2aOs6+heegqAdelGgNJKRHLWRuhGKuLIw5lkgx9Ky+QvZrn/Ddi8u # TIgWKp+MGG8xY6PBvvjgt9jQShlnPrZ3UY8Bvwy6rynhXBaV0V0TTL0gEx7eh/K1 # o8Miaru6s/7FyqOLeUS4vTHh9TgBL5DtxCYurXbSBVtL1Fj44+Od/6cmC9mmvrti # yG709Y3Rd3YdJj2f3GJq7Y7KdWq0QYhatKhBeg4fxjhg0yut2g6aM1mxjNPrE48z # 6HWCNGu9gMK5ZudldRw4a45Z06Aoktof0CqOyTErvq0YjoE4Xpa0+87T/PVUXNqf # 7Y+qSU7+9LtLQuMYR4w3cSPjuNusvLf9gBnch5RqM7kaDtYWDgLyB42EfsxeMqwK # WwA+TVi0HrWRqfSx2olbE56hJcEkMjOSKz3sRuupFCX3UroyYf52L+2iVTrda8XW # esPG62Mnn3T8AuLfzeJFuAbfOSERx7IFZO92UPoXE1uEjL5skl1yTZB3MubgOA4F # 8KoRNhviFAEST+nG8c8uIsbZeb08SeYQMqjVEmkwggd6MIIFYqADAgECAgphDpDS # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 # ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla # MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT # H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB # AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG # OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S # 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz # y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7 # 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u # M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33 # X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl # XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP # 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB # l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF # RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM # CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ # BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud # DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO # 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0 # LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y # Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p # Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y # Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw # cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA # XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY # 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj # 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd # d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ # Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf # wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ # aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j # NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIZjTCCGYkCAQEwgZUwfjELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAlKLM6r4lfM52wAAAAACUjAN # BglghkgBZQMEAgEFAKCBsDAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQggnqlrKTB # aMn9Tcm/qp08JhjyylWvbPz/cnW76WFilr0wRAYKKwYBBAGCNwIBDDE2MDSgFIAS # AE0AaQBjAHIAbwBzAG8AZgB0oRyAGmh0dHBzOi8vd3d3Lm1pY3Jvc29mdC5jb20g # MA0GCSqGSIb3DQEBAQUABIIBALfI0eTp9e4e0qqFhyRRxt236fQVAlVr36i1LQrw # 2cCux9oPDZzwKydb0JcOUk6ePXKYESkhsnHBpcbTsDI5XFyycONYVEPtW/9pkUIx # RZMJZSz6T/7pLOPZpoArFi6Reon8H4xA9uwL0PzEjhUkr7ZmXzS+OVynQtrrOHAy # 85ePefM6LUn9GggAf4dH1zZL8nbz0qbBg9SeOKVWLg+ApHiCp59eeYPIJojC2J+E # 1OrI6AhSBdfo+MIYRLNr2G7IC78dBxlUrjrdIbI5xHohUt5hoIsF1DHYwfvDHE9F # KzRQOLCXztInZPwsPivRW+U0NNyrztp0bTtJBtQzTgzM4kqhghcVMIIXEQYKKwYB # BAGCNwMDATGCFwEwghb9BgkqhkiG9w0BBwKgghbuMIIW6gIBAzEPMA0GCWCGSAFl # AwQCAQUAMIIBWAYLKoZIhvcNAQkQAQSgggFHBIIBQzCCAT8CAQEGCisGAQQBhFkK # AwEwMTANBglghkgBZQMEAgEFAAQg+kNQG9JmVsQHMRWdb0cvbPdyWBeBPHgTWNN3 # SoCGfowCBmHCS2qU3xgSMjAyMjAxMDcwODU5MDAuNjNaMASAAgH0oIHYpIHVMIHS # MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk # bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRN # aWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRo # YWxlcyBUU1MgRVNOOjg2REYtNEJCQy05MzM1MSUwIwYDVQQDExxNaWNyb3NvZnQg # VGltZS1TdGFtcCBTZXJ2aWNloIIRZTCCBxQwggT8oAMCAQICEzMAAAGMAZdiRzZ2 # ZjsAAQAAAYwwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB # IDIwMTAwHhcNMjExMDI4MTkyNzQ0WhcNMjMwMTI2MTkyNzQ0WjCB0jELMAkGA1UE # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0 # IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNT # IEVTTjo4NkRGLTRCQkMtOTMzNTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3Rh # bXAgU2VydmljZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANNIaEyh # E/khrGssPvQRXZvrmfpLxDxi3ebBfF5U91MuGBqk/Ovg6/Bt5Oqv5UWoIsUSr5/o # NgBUS/Vbmagtbk72u3WTfQoYqLRxxZsskGT2pV3SUwvJyiK24EzFwMIf5m4Z5qGs # bCPYxpYr2IIuRjThO7uk1eFDrZ1T/IqIU1HzTCoWWiXc5lg44Vguy4z1yIWpvUIU # ZFc65MXySnOfQLGhg9z74kZIB6BsX6XVhzz2lvIohB43ODw5gipbltyfiHVN/B/j # JCj5npAuxrUUy1ygQrlil0vE42WP8JDXM1jRKPpeSdzmXR3lYoMacwp3rJGX3B18 # awl9obnu6ib1q5LBUrZGWzhuyGJmn2DEK2RrpZe9j50taCHUHWJ0ef54HL0kG9dR # kNJDTA84irEnfuYn1GmGyS2dFxMTVeKi1wkuuQ4/vBcoAo7Tb5A4geR7PSOyvc8W # bFG+3yikhhGfcgNCYE1m3ADwmD7bgB1SfFCmk/eu6SZu/q94YHHt/FVN/bKXnhx4 # GgkuL163pUy4lDAJdDrZOZ3CkCnNpBp77sD9kQkt5BBBQMaJ8C5/Kcnncq3mU2wT # EAan9aN5I9IpTie/3/z93Na52mDtNRgyaJr+6LaW+c/tYa0qCLPLvunq7iSgk4oX # dIv/G3OuwChe+sKVrr1vQYW1DE7FpMMOK+NnAgMBAAGjggE2MIIBMjAdBgNVHQ4E # FgQUls5ThqmCIWCIeVadPojK3UCLUiMwHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXS # ZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIw # MTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0 # YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAK # BggrBgEFBQcDCDANBgkqhkiG9w0BAQsFAAOCAgEA12jFRVjCCanW5UGSuqJLO3HQ # lMHjwJphCHnbMrrIFDCEJUKmo3wj/YhufMjhUkcdpOfY9oQAUmQcRZm5FY8IWBAt # ciT0JveOuIFM+RvrjludYvLnnngd4dovg5qFjSjUrpSDcn0hoFujwgwokajt6p/C # mFcy86Hpnz4q/1FceQgIFXBAwDLcW0a0x1wQAV8gmumkN/o7pFgeWkMy8OqoR4c+ # xyDlPav0PWNjZ1QSj38yJcD429ja0Bn0J107LHxQ/fDqUR6tO2VMdtYOKbPFd94U # kpCdrg8IbaeVbRRpxfgMcxQZQr3N9yz05l7HM5cuvskIAEcJjR3jQNutlqiyyTPO # CM/DktVXxNTesmApC44PNfsxl7I7zBpowZYssWcF1hliZrKLwek+odRq35rzCrnT # hPdg+u0kd809w3QOScC/UwM1/FIYtGhmLZ+bjVAxW8SKMyETKS1aT/2Di54Pq9r/ # LPJclr9Gn48GWBwSeuDFlTcR3GjbY85GLUI3WeW4cpGunV/g7UA/W4d844tEpa31 # QyC8RG+jo8qrXxo+4lmbya2+AKiFYB0Gg84LosREvYnrRYpB33+qfewuaqG002ys # DdABD96ubXsiPTSDlZSZdIIuSG3efB4n9ySzur6fuch146Ei/zJYRZrxrWmJkMA+ # ys05vbgAxeAcz/5sdr8wggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAV # MA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo # b3JpdHkgMjAxMDAeFw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jv # c29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A # MIICCgKCAgEA5OGmTOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK # 4OK9uT4XYDP/XE/HZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKDRLem # jkZrBxTzxXb1hlDcwUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+ # NSZk2pg7uhp7M62AW36MEBydUv626GIl3GoPz130/o5Tz9bshVZN7928jaTjkY+y # OSxRnOlwaQ3KNi1wjjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56KTes # y+uDRedGbsoy1cCGMFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39IM9z # fUGaRnXNxF803RKJ1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHovwUD # o9Fzpk03dJQcNIIP8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDq # hFFG4tG9ahhaYQFzymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZki1ugpoMhXV8w # dJGUlNi5UPkLiWHzNgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N # +VLEhReTwDwV2xo3xwgVGD94q0W29R6HXtqPnhZyacaue7e3PmriLq0CAwEAAaOC # Ad0wggHZMBIGCSsGAQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5k # xJq+gpE8RjUpzxD/LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnpcjBc # BgNVHSAEVTBTMFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYD # VR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYD # VR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxi # aNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3Nv # ZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMu # Y3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNy # b3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQw # DQYJKoZIhvcNAQELBQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pcFLY+Tkdk # eLEGk5c9MTO1OdfCcTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYe # eNg2LpypglYAA7AFvonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4U3Uk # V7ndn/OOPcbzaN9l9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wX # sFSFQrP8DJ6LGYnn8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb30mj # dAy87JGA0j3mSj5mO0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY # 3UA8x1RtnWN0SCyxTkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmR # aw2fpCjcZxkoJLo4S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyh # YWxz/gq77EFmPWn9y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGConsXHRWJjXD+ # 57XQKBqJC4822rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7t # fqAxM328y+l7vzhwRNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEGahC0HVUzWLOh # cGbyoYIC1DCCAj0CAQEwggEAoYHYpIHVMIHSMQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z # b2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVy # YXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOjg2REYtNEJC # Qy05MzM1MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMK # AQEwBwYFKw4DAhoDFQA0ovIU66v0PKKacHhsrmSzRCav1aCBgzCBgKR+MHwxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jv # c29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBBQUAAgUA5YHheTAi # GA8yMDIyMDEwNzA1NDUyOVoYDzIwMjIwMTA4MDU0NTI5WjB0MDoGCisGAQQBhFkK # BAExLDAqMAoCBQDlgeF5AgEAMAcCAQACAgrUMAcCAQACAk83MAoCBQDlgzL5AgEA # MDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAI # AgEAAgMBhqAwDQYJKoZIhvcNAQEFBQADgYEA3sLSDaxnFDVGnyNplR6D7bzkpGpe # azG2GydGxgDjkHOKmKvJwb6eai92dCwyn6vwj7ASPQ3XrjvFs47LAFCwnvsT5hgG # qppZecy6CCmEqEr//IAJN5l0SIrEqN+jYrCik2+/l5AygXkbyOZ+U3jsvd8Q/gQv # zDPQSfOjIWj6VVoxggQNMIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z # b2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ # Q0EgMjAxMAITMwAAAYwBl2JHNnZmOwABAAABjDANBglghkgBZQMEAgEFAKCCAUow # GgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCA4IDZx # DfcH08flt2gy41tNuYH4yqNXFuCLdxnnH6+jlTCB+gYLKoZIhvcNAQkQAi8xgeow # gecwgeQwgb0EINWti/gVKpDPBn/E5iEFnYHik062FyMDqHzriYgYmGmeMIGYMIGA # pH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE # AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAGMAZdiRzZ2ZjsA # AQAAAYwwIgQg8/eceS/pFmvNqa/I5c09DyUUW64PGnLy6jBkY7mabMUwDQYJKoZI # hvcNAQELBQAEggIAnfOiaK/+TkK1gdZfGb3r49YU7A0wVnNUjrI9+lQfxO2IbiU8 # HqNOL/AxyiATvbtu9GvVWFSzXzReV+cCq8dheNwy/lfLuqNwFKblFa//8QGSO8GT # RsdoaPJeaSTG61z9Bovjnv7gogopctSjBXBYeF/IK8xfRWBccVw6P7UN5gRComKm # NyM+gIVPgs2mGrQ2e+AskC9eAkWJdmC/00XhVGRl6D5In/m/ybap46g+li3PhCFT # zLb57grGuDVb7wtfu5Pf/0hnTntES5ix5WZT0AykkgWMx8m7PznBBUWS61KXqEEK # oFjs2BlDrnXq4FrvhJMJkgkZ/duhBBFgjKm0Un3iTvbnDhUenNFec45OlwKbLL1f # 4oj+7xEI5coi3dP5VBhL+6d2l1Gkj+FEhPRGfpcyM+piKuA769keaSbNg4HglE0U # TkdWswA7Uw3xJcbSJkPhL5CxnQJZH9Y8F+Pv9QMwjDEX0aPhBAYdWtMEb4VWVSJ6 # oMImNUeRQRiGihubYwEujTreeETMvdZ21NKpjidX8AUuilguFUJAwpbQ7xjGj2rM # vOBVoDIAm6gyifRwDJC8O/FrTnEdOOzfwzUWryCUEuGzyL7zYrVrBWl0a1nHvoe6 # a8jNmutJWSgmDzRCv5n25UZiYHGRqVilw53bJinCww5t6DFfSth0J8WdoCk= # SIG # End signature block |