functions/DailyBuild/Merge-DailyBuildBranch.ps1
|
<#
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. #> [CmdletBinding()] param( [string]$OrganizationUri = $env:SYSTEM_COLLECTIONURI, [string]$Project = $env:SYSTEM_TEAMPROJECTID, [string]$RepositoryName = $env:BUILD_REPOSITORY_NAME, [string]$RepositoryDirectory = $env:BUILD_SOURCESDIRECTORY, [string]$DailyBuildBranch = 'daily-build', [string]$TargetBranch = 'main', [ValidateSet('merge', 'squash')] [string]$MergeStrategy = 'merge', [int]$DefaultPriority = 100, [string]$Pat = $env:DEVOPS_PAT, [switch]$SkipUnchangedPush ) if ($MyInvocation.InvocationName -eq '.') { return } if ([string]::IsNullOrWhiteSpace($TargetBranch)) { $TargetBranch = 'main' } if ($DefaultPriority -lt 0) { $DefaultPriority = 100 } if ($env:SYSTEM_DEBUG -eq 'true') { $VerbosePreference $VerbosePreference = 'Continue' $VerbosePreference Write-Verbose "PWD: $PWD" Write-Verbose "OrganizationUri: $OrganizationUri" Write-Verbose "Project: $Project" Write-Verbose "RepositoryName: $RepositoryName" Write-Verbose "DailyBuildBranch: $DailyBuildBranch" Write-Verbose "MergeStrategy: $MergeStrategy" Write-Verbose "DefaultPriority: $DefaultPriority" Write-Verbose "SkipUnchangedPush: $SkipUnchangedPush" } Push-Location -Path $RepositoryDirectory $gitArgs = @( '-c', "http.extraheader=AUTHORIZATION: Basic $([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("PAT:$Pat")))" ) function Resolve-PullRequestPriority { param( [Parameter(Mandatory = $true)] $Labels ) $resolved = $DefaultPriority foreach ($label in @($Labels | ForEach-Object { $_.name })) { if ($label -match '^priority:(\d+)$') { $val = [int]$Matches[1] if ($val -lt $resolved) { $resolved = $val } } } return $resolved } function Invoke-Git { param( [Parameter(Mandatory = $true)] [string[]]$Args ) Write-Verbose "Running git $($Args -join ' ')" & git @gitArgs @Args if ($LASTEXITCODE -ne 0) { throw "git $($Args -join ' ') failed with exit code $LASTEXITCODE." } } function Get-CommitIdentity { param( [Parameter(Mandatory = $true)] [string]$Ref ) Write-Verbose "Resolving commit identity for $Ref..." $identity = & git @gitArgs 'show' '--no-patch' "--format=%an`n%ae" $Ref if ($LASTEXITCODE -ne 0) { throw "Failed to resolve commit identity for $Ref. Please verify fetch depth." } $identityLines = @($identity | Where-Object { $_ -ne $null }) if ($identityLines.Count -lt 2) { throw "Commit identity for $Ref is incomplete." } return @{ Name = $identityLines[0] Email = $identityLines[1] } } function Invoke-GitWithCommitIdentity { param( [Parameter(Mandatory = $true)] [hashtable]$Identity, [Parameter(Mandatory = $true)] [string[]]$Args ) Write-Verbose "Running git $($Args -join ' ') with identity $($Identity.Name) <$($Identity.Email)>" & git @gitArgs '-c' "user.name=$($Identity.Name)" '-c' "user.email=$($Identity.Email)" @Args if ($LASTEXITCODE -ne 0) { throw "git $($Args -join ' ') failed with exit code $LASTEXITCODE." } } function Get-BuildResultsUrl { $collectionUri = if ($env:SYSTEM_COLLECTIONURI) { $env:SYSTEM_COLLECTIONURI } else { $OrganizationUri } if ([string]::IsNullOrWhiteSpace($collectionUri)) { return '' } $buildId = $env:BUILD_BUILDID if ([string]::IsNullOrWhiteSpace($buildId)) { return '' } $projectName = if ($env:SYSTEM_TEAMPROJECT) { $env:SYSTEM_TEAMPROJECT } else { $Project } $baseUri = $collectionUri.TrimEnd('/') $queryParts = @{ "buildId" = $buildId 'view' = 'logs' "j" = $env:SYSTEM_JOBID "t" = $env:SYSTEM_TASKINSTANCEID "s" = $env:SYSTEM_STAGEID } $queryString = ($queryParts.GetEnumerator() | ForEach-Object { "$($_.Key)=$([uri]::EscapeDataString($_.Value))" }) -join '&' return "$baseUri/$([Uri]::EscapeDataString($projectName))/_build/results?$queryString" } function Set-PullRequestStatus { param( [Parameter(Mandatory = $true)] [int]$PullRequestId, [Parameter(Mandatory = $true)] [int]$IterationId, [Parameter(Mandatory = $true)] [ValidateSet('succeeded', 'failed', 'pending', 'notSet', 'error')] [string]$State, [Parameter(Mandatory = $true)] [string]$Description ) $authHeader = "Basic $([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("PAT:$Pat")))" $targetUrl = Get-BuildResultsUrl $body = @{ state = $State description = $Description iterationId = $IterationId context = @{ name = 'daily-build' genre = 'daily-build' } targetUrl = $targetUrl } | ConvertTo-Json Write-Verbose "Posting status to PR !$PullRequestId (iteration: $IterationId): $State - $Description" $uri = "$OrganizationUri/$([Uri]::EscapeDataString($Project))/_apis/git/repositories/$repositoryId/pullRequests/$PullRequestId/statuses?api-version=7.1" try { Invoke-RestMethod -Uri $uri -Method Post -Body $body -ContentType 'application/json' -Headers @{ Authorization = $authHeader } | Out-Null } catch { Write-Warning "Failed to post status to PR !$PullRequestId : $_" } } function Get-LatestPullRequestIteration { param( [Parameter(Mandatory = $true)] [int]$PullRequestId ) $authHeader = "Basic $([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("PAT:$Pat")))" $uri = "$OrganizationUri/$([Uri]::EscapeDataString($Project))/_apis/git/repositories/$repositoryId/pullRequests/$PullRequestId/iterations?includeCommits=false&api-version=7.1" Write-Verbose "Fetching iterations for PR !$PullRequestId..." $response = Invoke-RestMethod -Uri $uri -Method Get -Headers @{ Authorization = $authHeader } if (-not $response -or -not $response.value -or $response.value.Count -eq 0) { throw "No iterations found for PR !$PullRequestId." } # The API returns iterations in ascending order; the last one is the current iteration. Write-Verbose "Found $($response.value.Count) iterations for PR !$PullRequestId. Returning the latest iteration (ID: $($response.value[-1].id))." return $response.value[-1] } function Resolve-IterationIdForStatus { param( [Parameter(Mandatory = $true)] $PullRequestItem ) if ($PullRequestItem.PSObject.Properties.Name -contains 'Iteration' -and $PullRequestItem.Iteration -and $PullRequestItem.Iteration.Id) { return [int]$PullRequestItem.Iteration.Id } return 1 } $env:AZURE_DEVOPS_EXT_PAT = $Pat $azExtensions = az extension list --query '[].name' --output json | ConvertFrom-Json if ($azExtensions -notcontains 'azure-devops') { az extension add --name azure-devops } az devops configure --defaults organization=$OrganizationUri project=$Project Write-Verbose "Fetching active PRs targeting '$TargetBranch'..." $prResponse = az repos pr list --repository "$RepositoryName" --target-branch $TargetBranch --status active --query '[?!isDraft]' --output json $pr = ($prResponse | ConvertFrom-Json) Write-Verbose "Fetched $($pr.Count) active PRs targeting '$TargetBranch'." $pr = $pr | Where-Object { if (!$_.labels) { $_.labels = @() } $labelNames = @($_.labels | ForEach-Object { $_.name }) $labelNames -notcontains 'AutoMergeIgnore' } $pr = $pr | Sort-Object -Property @( @{ Expression = { Resolve-PullRequestPriority $_.labels }; Ascending = $true }, @{ Expression = { $_.pullRequestId }; Ascending = $true } ) $repositoryId = (az repos show --repository "$RepositoryName" --query id --output tsv).Trim() Invoke-Git @('fetch', 'origin', $TargetBranch) Invoke-Git @('checkout', '-B', $DailyBuildBranch, "origin/$TargetBranch") $mergeLabelScriptPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'ps_modules/D365GitOps/functions/MergeDrivers/Merge-D365LabelFile.ps1' if (Test-Path -Path $mergeLabelScriptPath) { Invoke-Git @('config', 'merge.d365fo-label.driver', "pwsh -File `"$mergeLabelScriptPath`" -Base %O -Ours %A -Theirs %B -MarkerSize %L -FilePath %P") } else { Write-Verbose -Verbose "Merge label driver script not found at $mergeLabelScriptPath. Skipping merge.d365fo-label.driver configuration." } # Module layout (functions/DailyBuild -> functions/MergeDrivers) or extension task layout (ps_modules/D365GitOps). $mergeXmlScriptPath = @( (Join-Path $PSScriptRoot '../MergeDrivers/Merge-D365XmlFile.ps1'), (Join-Path $PSScriptRoot 'ps_modules/D365GitOps/functions/MergeDrivers/Merge-D365XmlFile.ps1') ) | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf } | Select-Object -First 1 if ($mergeXmlScriptPath) { $mergeXmlScriptPath = (Resolve-Path -LiteralPath $mergeXmlScriptPath).ProviderPath.Replace('\', '/') Invoke-Git @('config', 'merge.d365fo-xml.driver', "pwsh -NoProfile -File `"$mergeXmlScriptPath`" -Base %O -Ours %A -Theirs %B -MarkerSize %L -FilePath %P") } else { Write-Verbose -Verbose "Merge XML driver script Merge-D365XmlFile.ps1 not found. Skipping merge.d365fo-xml.driver configuration." } $mergedPRs = @() $skippedPRs = @() foreach ($item in $pr) { if (-not $item.sourceRefName) { Write-Warning "Skipping PR $($item.pullRequestId): missing sourceRefName." continue } if ($item.supportsIterations) { $iteration = Get-LatestPullRequestIteration -PullRequestId $item.pullRequestId $item | Add-Member -MemberType NoteProperty -Name Iteration -Value $iteration if ($item.lastMergeSourceCommit.commitId -ne $item.Iteration.sourceRefCommit.commitId) { Write-Warning "Skipping PR $($item.pullRequestId): source branch has new commits since last iteration." $skippedPRs += $item continue } } $sourceBranch = $item.sourceRefName -replace '^refs/heads/', '' $resolvedPriority = Resolve-PullRequestPriority $item.labels $sourceIdentity = Get-CommitIdentity "origin/$sourceBranch" Write-Host "Merging PR $($item.pullRequestId) from $sourceBranch (priority: $resolvedPriority)" try { switch ($MergeStrategy) { 'squash' { Invoke-Git @('merge', '--squash', "origin/$sourceBranch") Invoke-GitWithCommitIdentity $sourceIdentity @('commit', '-m', "Squash PR !$($item.pullRequestId)") } default { Invoke-GitWithCommitIdentity $sourceIdentity @('merge', '--no-ff', "origin/$sourceBranch", '-m', "Merge PR !$($item.pullRequestId)") } } $mergedPRs += $item } catch { Write-Warning "Merge failed for PR $($item.pullRequestId) ($sourceBranch). Skipping." & git merge --abort | Out-Null & git reset --hard HEAD | Out-Null $skippedPRs += $item continue } } $shouldPush = $true if ($SkipUnchangedPush) { # Silently try to fetch the remote daily-build branch (may not exist yet) & git @gitArgs fetch origin $DailyBuildBranch 2>$null | Out-Null # Check if the remote ref exists & git rev-parse --verify "origin/$DailyBuildBranch" 2>$null | Out-Null if ($LASTEXITCODE -eq 0) { # Compare trees; exit code 0 means no difference & git diff --quiet "origin/$DailyBuildBranch" HEAD if ($LASTEXITCODE -eq 0) { Write-Host "No content changes vs 'origin/$DailyBuildBranch' - skipping push." $shouldPush = $false } } } if ($shouldPush) { Invoke-Git @('push', '--force', 'origin', $DailyBuildBranch) } foreach ($item in $mergedPRs) { try { $iterationId = Resolve-IterationIdForStatus -PullRequestItem $item Set-PullRequestStatus -PullRequestId $item.pullRequestId -IterationId $iterationId -State 'succeeded' -Description "Merged into daily-build (iteration: $iterationId) $($item.lastMergeSourceCommit.commitId)" } catch { Write-Warning "Failed to post status for PR $($item.pullRequestId): $_" } } foreach ($item in $skippedPRs) { try { $iterationId = Resolve-IterationIdForStatus -PullRequestItem $item Set-PullRequestStatus -PullRequestId $item.pullRequestId -IterationId $iterationId -State 'failed' -Description "Merge conflict - skipped (iteration: $iterationId) $($item.lastMergeSourceCommit.commitId)" } catch { Write-Warning "Failed to post status for PR $($item.pullRequestId): $_" } } Write-Host '' Write-Host '=== Daily Build Summary ===' if ($mergedPRs.Count -gt 0) { $mergedList = ($mergedPRs | ForEach-Object { "!$($_.pullRequestId)" }) -join ', ' Write-Host "Merged: $mergedList" } else { Write-Host 'Merged: (none)' } if ($skippedPRs.Count -gt 0) { $skippedList = ($skippedPRs | ForEach-Object { "!$($_.pullRequestId) (merge conflict)" }) -join ', ' Write-Host "Skipped: $skippedList" } else { Write-Host 'Skipped: (none)' } # SIG # Begin signature block # MII2lgYJKoZIhvcNAQcCoII2hzCCNoMCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDCISS7Cg53ihzk # tg/59vnjWm3xuAM4Kb3ezeBILOtcPaCCGzQwggXMMIIDtKADAgECAhBUmNLR1FsZ # lUgTecgRwIeZMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQK # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVu # dGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAy # MDAeFw0yMDA0MTYxODM2MTZaFw00NTA0MTYxODQ0NDBaMHcxCzAJBgNVBAYTAlVT # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jv # c29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo # b3JpdHkgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALORKgeD # Bmf9np3gx8C3pOZCBH8Ppttf+9Va10Wg+3cL8IDzpm1aTXlT2KCGhFdFIMeiVPvH # or+Kx24186IVxC9O40qFlkkN/76Z2BT2vCcH7kKbK/ULkgbk/WkTZaiRcvKYhOuD # PQ7k13ESSCHLDe32R0m3m/nJxxe2hE//uKya13NnSYXjhr03QNAlhtTetcJtYmrV # qXi8LW9J+eVsFBT9FMfTZRY33stuvF4pjf1imxUs1gXmuYkyM6Nix9fWUmcIxC70 # ViueC4fM7Ke0pqrrBc0ZV6U6CwQnHJFnni1iLS8evtrAIMsEGcoz+4m+mOJyoHI1 # vnnhnINv5G0Xb5DzPQCGdTiO0OBJmrvb0/gwytVXiGhNctO/bX9x2P29Da6SZEi3 # W295JrXNm5UhhNHvDzI9e1eM80UHTHzgXhgONXaLbZ7LNnSrBfjgc10yVpRnlyUK # xjU9lJfnwUSLgP3B+PR0GeUw9gb7IVc+BhyLaxWGJ0l7gpPKWeh1R+g/OPTHU3mg # trTiXFHvvV84wRPmeAyVWi7FQFkozA8kwOy6CXcjmTimthzax7ogttc32H83rwjj # O3HbbnMbfZlysOSGM1l0tRYAe1BtxoYT2v3EOYI9JACaYNq6lMAFUSw0rFCZE4e7 # swWAsk0wAly4JoNdtGNz764jlU9gKL431VulAgMBAAGjVDBSMA4GA1UdDwEB/wQE # AwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIftJqhSobyhmYBAcnz1AQ # T2ioojAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQwFAAOCAgEAr2rd5hnn # LZRDGU7L6VCVZKUDkQKL4jaAOxWiUsIWGbZqWl10QzD0m/9gdAmxIR6QFm3FJI9c # Zohj9E/MffISTEAQiwGf2qnIrvKVG8+dBetJPnSgaFvlVixlHIJ+U9pW2UYXeZJF # xBA2CFIpF8svpvJ+1Gkkih6PsHMNzBxKq7Kq7aeRYwFkIqgyuH4yKLNncy2RtNwx # AQv3Rwqm8ddK7VZgxCwIo3tAsLx0J1KH1r6I3TeKiW5niB31yV2g/rarOoDXGpc8 # FzYiQR6sTdWD5jw4vU8w6VSp07YEwzJ2YbuwGMUrGLPAgNW3lbBeUU0i/OxYqujY # lLSlLu2S3ucYfCFX3VVj979tzR/SpncocMfiWzpbCNJbTsgAlrPhgzavhgplXHT2 # 6ux6anSg8Evu75SjrFDyh+3XOjCDyft9V77l4/hByuVkrrOj7FjshZrM77nq81YY # uVxzmq/FdxeDWds3GhhyVKVB0rYjdaNDmuV3fJZ5t0GNv+zcgKCf0Xd1WF81E+Al # GmcLfc4l+gcK5GEh2NQc5QfGNpn0ltDGFf5Ozdeui53bFv0ExpK91IjmqaOqu/dk # ODtfzAzQNb50GQOmxapMomE2gj4d8yu8l13bS3g7LfU772Aj6PXsCyM2la+YZr9T # 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggaSMIIEeqADAgECAhMzAAiWokxQ # x66HAhz8AAAACJaiMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ # RCBWZXJpZmllZCBDUyBFT0MgQ0EgMDMwHhcNMjYxMDE4MDI1MDQ0WhcNMjYxMDIx # MDI1MDQ0WjBVMQswCQYDVQQGEwJTSTESMBAGA1UEBxMJTGp1YmxqYW5hMRgwFgYD # VQQKEw9CRS10ZXJuYSBkLm8uby4xGDAWBgNVBAMTD0JFLXRlcm5hIGQuby5vLjCC # AaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAJdNhrUWIlPmS3c09jFX4He0 # J2ix0cJSDdCoG/rBpushZFn6q5hTOfiTnH970F7MQgY9LFMzSJ+H9qvmmzT1TEdV # AehGdgC/AOlvm39uxZRnhumCOeR1HW4aG5G5v5PpxGmXJvMWN7AEZyJ58JJ8KkDF # u6jxDXhKRZ84iYsgJWFC67i6lsVbHcE94knXw5hTypj1HZ+2Krh6gmYm3kgeqI0O # 9UrUED5Z421D9ZWJHLNNbuUs8A17YOAML3+1Df/arSmLpeWRJ3F3hOViZRAWc0nt # 7Xub+593HSL6YkyYRbTcIHHlRlg4xJ4/N6eoacE7d/3/VnFv9q9UGj5iA1g1hdJT # bkOu+yaXausyD+QYSN4C7fSzsRXxisFJMXW5YCgY9F9bZMAyCNyhl4jxJe+4c8de # /omI+uro3+JJsi/LZVLa1j8YG1pePEeoc1OjyjIuM3v+uii2DPcqqzqzb9nvBTkS # Q9P4hVaH2qvplTxSQT2bLFhH4qXzW2br2QRX+vRERQIDAQABo4IB1DCCAdAwDAYD # VR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwOwYDVR0lBDQwMgYKKwYBBAGCN2EB # AAYIKwYBBQUHAwMGGisGAQQBgjdhpOaoI4H67850gfzolDeutrtWMB0GA1UdDgQW # BBQNYRcTYM26/9pbC1jzU9rO+1c97TAfBgNVHSMEGDAWgBRrXqU0wwXFYkohWo6r # c2Bi1KxjhTBnBgNVHR8EYDBeMFygWqBYhlZodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ1MlMjBF # T0MlMjBDQSUyMDAzLmNybDB0BggrBgEFBQcBAQRoMGYwZAYIKwYBBQUHMAKGWGh0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIw # SUQlMjBWZXJpZmllZCUyMENTJTIwRU9DJTIwQ0ElMjAwMy5jcnQwVAYDVR0gBE0w # SzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNv # bS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTANBgkqhkiG9w0BAQwFAAOCAgEA # ZKezAUaS2Jm1GOnzuWmqfAKI1PXAP5E+sgfqsDxdZRoQzzQcuqJiBWCZhOe0BEFY # OmkRXEnspD21MfIHSyRIk9VPmU9mFWqAv+jX/pQ0l8oPIowCLxo8xwiXRCXFs3bv # Hn9FUPyr/JW0V7396uC+Y33SxXusVMf6b59n0nKAahOHtajGn2SXYDZiBbW6bLe9 # E+kGWygf9E9hMLVYSeN1ecnjAuDOmZ18GifAnVT+Um+u7OLXU5Il2zhn7Hbx2Ti4 # /coiRrPonrb5FvO6AKv9F5JQco5yyAPP63RB5rLEsos5f2phsEG4PJqQkOV8BK02 # EN63hCkp3tmKccH27H1+aWMcYdBT7q4PL7IKxp9osz5OJPpnL7/7MYbDuOKHfZKS # ys+Gm5fqopr/UiB9m+Ul0siycMfltpgZxte1nLxFDpcKebacUnvumdLbOnmIplRQ # eCA/po0gjh2xvcdgNbZRc/sOIE407rWgZ8t91YdvtEAZrMOumbuyUtOzS4bKs3/W # 3NzBvgtPEjP4cKHrefYiD6d2lljA/arXWIBNyc62FW8Uqz5ltn5aqeYjFQEuPD2B # FX2x46InMMIcoQfbYI6ItQuzkROjf+twmPN0ufKD0EWOVsL5qxLEW/s6/XZczvl0 # hDizRrkBbBlrb38oLjGhepN8ZFhS6NCangB5g5jY+nkwggcoMIIFEKADAgECAhMz # AAAAFQU+bhmOkynZAAAAAAAVMA0GCSqGSIb3DQEBDAUAMGMxCzAJBgNVBAYTAlVT # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xNDAyBgNVBAMTK01pY3Jv # c29mdCBJRCBWZXJpZmllZCBDb2RlIFNpZ25pbmcgUENBIDIwMjEwHhcNMjYwMzI2 # MTgxMTI4WhcNMzEwMzI2MTgxMTI4WjBaMQswCQYDVQQGEwJVUzEeMBwGA1UEChMV # TWljcm9zb2Z0IENvcnBvcmF0aW9uMSswKQYDVQQDEyJNaWNyb3NvZnQgSUQgVmVy # aWZpZWQgQ1MgRU9DIENBIDAzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC # AgEA4PTLPQKqLw5zHj7zDnvism4QnfPpaJM2DkZUt5AVV7HnnG8hsAXLHp5ZuWy7 # TBj44iBS8wUBfoIZVVf1NvauRnHXhBAQh00xoS9pKCKy3OFK5YjEXG7/ZjjLUf5e # /8QJr9BceASR59XR7d+376wal5ioynxn+Q6cjv/oZ1e0xK3jLUtfYjvm42f/R56Y # NzwpNHu2Em0UxZMfexWcEVqQuLNzXqUX0V0If1jAI+yZrGHlWaIYuExecltiTKyW # asB3MsyWWLQ9h5Z6OWRCZHYmXBGsRzqG5sDtOmdSfXNt6bPTxiIRmqtbCixAM/Q6 # HOay5GFhrXg67HCoQKdpCHP6GJR/SI+gZDqqoFiDRJBLQvGTRtTGpPod6OuWo9Ik # CpncVuyGWhzuXLsqDIvirWH13iCIN7FSG0thC/JFLbAxnRKjagKv4rKk4tY16i3u # oiqdZ4tUj3bz1vRtNwk7GBevG/8riEEcG3aAQl3pjDSQktHaKwkWOG9lgAMuJ4O0 # gDXBIKwYGX+d+fkHy1OYRs6yoyKWzGm2rlm+RSllCpDLD3FxZF0VjuJ6Cj5uClpR # cqajqWyfyjjVUXiJcR0EXoADgcyIUQe4K/SA0NbHNjIDoEPsVRluKKuBw9JnwIsI # si7JGa5GkOyaGp2IwTXEfUUtumMQFW3AbS4rRU8wiBIOWXUCAwEAAaOCAdwwggHY # MA4GA1UdDwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQUa16l # NMMFxWJKIVqOq3NgYtSsY4UwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUH # AgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0 # b3J5Lmh0bTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTASBgNVHRMBAf8ECDAG # AQH/AgEAMB8GA1UdIwQYMBaAFNlBKbAPD2Ns72nX9c0pnqRIajDmMHAGA1UdHwRp # MGcwZaBjoGGGX2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01p # Y3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDb2RlJTIwU2lnbmluZyUyMFBDQSUy # MDIwMjEuY3JsMH0GCCsGAQUFBwEBBHEwbzBtBggrBgEFBQcwAoZhaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBJRCUyMFZl # cmlmaWVkJTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDIxLmNydDANBgkqhkiG # 9w0BAQwFAAOCAgEAXW4iPM8Fy1/IJSRIf/ENtlDAlIVgTuOmfRT4cDkd5nZakVS5 # GDqJ/zHM1MK4w4cd1/fUjx+T0n5ZBqE75zvWVhzOWBVWKTuzWLgfpn1UhgBmcIhj # gElpNItge75/ZxJSSZqIl8boHx+WHQbK1IE7dABTV5M5qk4JPktR8W9bv9BwqhB1 # WT5NgP+niV2G7aUTORXM9NI4rFJfQUWYEnmzg1fOWwczr3qsgt39D5xwsUSTYTG/ # MT/7Af1SO6X9q4Xkle86lEr/L5/3yDG5V3mlSJaaqKvEj/QSTIxPwqFVycZ5GUET # NRWu5Dfcs7b0XjocUoD4KWcf15f45MMhBVSUwXwad7E4HyHP6Zqr9nobWpC9gBI+ # /BJjj0KIcSU98Ml/j+/BgNubS6QL8490TDB3fM9fGbrlYvutDAMxqTgEh9S/DZa9 # 32UWZ0Dvqcsntgwr2Jh2iH3VIGCap+56McRlb/PfkWhE4dbYAg78DaRQkhu75eQO # GpKPtn8eNPa/U1o1wuzon9SEOWScweEX/BrwYh2I7zJh6ZXnadRRkS3UkRVaQt/z # iqWWOmryKmae/vKT/1kD/dNw3YK7wE+luMTzgcVz2uLRpLDd0rqiWohWB0jcngbn # 5/IrHro1uCGwUmxw+AT6mxd6mfu5xvXf3fxtvy8eJB/XApgX5rGXUpB5rpAwggee # MIIFhqADAgECAhMzAAAAB4ejNKN7pY4cAAAAAAAHMA0GCSqGSIb3DQEBDAUAMHcx # CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBG # BgNVBAMTP01pY3Jvc29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0 # aWZpY2F0ZSBBdXRob3JpdHkgMjAyMDAeFw0yMTA0MDEyMDA1MjBaFw0zNjA0MDEy # MDE1MjBaMGMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y # YXRpb24xNDAyBgNVBAMTK01pY3Jvc29mdCBJRCBWZXJpZmllZCBDb2RlIFNpZ25p # bmcgUENBIDIwMjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCy8MCv # GYgo4t1UekxJbGkIVQm0Uv96SvjB6yUo92cXdylN65Xy96q2YpWCiTas7QPTkGnK # 9QMKDXB2ygS27EAIQZyAd+M8X+dmw6SDtzSZXyGkxP8a8Hi6EO9Zcwh5A+wOALNQ # bNO+iLvpgOnEM7GGB/wm5dYnMEOguua1OFfTUITVMIK8faxkP/4fPdEPCXYyy8NJ # 1fmskNhW5HduNqPZB/NkWbB9xxMqowAeWvPgHtpzyD3PLGVOmRO4ka0WcsEZqyg6 # efk3JiV/TEX39uNVGjgbODZhzspHvKFNU2K5MYfmHh4H1qObU4JKEjKGsqqA6Rzi # ybPqhvE74fEp4n1tiY9/ootdU0vPxRp4BGjQFq28nzawuvaCqUUF2PWxh+o5/TRC # b/cHhcYU8Mr8fTiS15kRmwFFzdVPZ3+JV3s5MulIf3II5FXeghlAH9CvicPhhP+V # aSFW3Da/azROdEm5sv+EUwhBrzqtxoYyE2wmuHKws00x4GGIx7NTWznOm6x/niqV # i7a/mxnnMvQq8EMse0vwX2CfqM7Le/smbRtsEeOtbnJBbtLfoAsC3TdAOnBbUkbU # fG78VRclsE7YDDBUbgWt75lDk53yi7C3n0WkHFU4EZ83i83abd9nHWCqfnYa9qIH # PqjOiuAgSOf4+FRcguEBXlD9mAInS7b6V0UaNwIDAQABo4ICNTCCAjEwDgYDVR0P # AQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTZQSmwDw9jbO9p # 1/XNKZ6kSGow5jBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYzaHR0 # cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRt # MBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMBAf8wHwYD # VR0jBBgwFoAUyH7SaoUqG8oZmAQHJ89QEE9oqKIwgYQGA1UdHwR9MHsweaB3oHWG # c2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUy # MElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRpZmljYXRlJTIw # QXV0aG9yaXR5JTIwMjAyMC5jcmwwgcMGCCsGAQUFBwEBBIG2MIGzMIGBBggrBgEF # BQcwAoZ1aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNy # b3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUyMFJvb3QlMjBDZXJ0aWZp # Y2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3J0MC0GCCsGAQUFBzABhiFodHRwOi8v # b25lb2NzcC5taWNyb3NvZnQuY29tL29jc3AwDQYJKoZIhvcNAQEMBQADggIBAH8l # Kp7+1Kvq3WYK21cjTLpebJDjW4ZbOX3HD5ZiG84vjsFXT0OB+eb+1TiJ55ns0BHl # uC6itMI2vnwc5wDW1ywdCq3TAmx0KWy7xulAP179qX6VSBNQkRXzReFyjvF2BGt6 # FvKFR/imR4CEESMAG8hSkPYso+GjlngM8JPn/ROUrTaeU/BRu/1RFESFVgK2wMz7 # fU4VTd8NXwGZBe/mFPZG6tWwkdmA/jLbp0kNUX7elxu2+HtHo0QO5gdiKF+YTYd1 # BGrmNG8sTURvn09jAhIUJfYNotn7OlThtfQjXqe0qrimgY4Vpoq2MgDW9ESUi1o4 # pzC1zTgIGtdJ/IvY6nqa80jFOTg5qzAiRNdsUvzVkoYP7bi4wLCj+ks2GftUct+f # GUxXMdBUv5sdr0qFPLPB0b8vq516slCfRwaktAxK1S40MCvFbbAXXpAZnU20FaAo # Dwqq/jwzwd8Wo2J83r7O3onQbDO9TyDStgaBNlHzMMQgl95nHBYMelLEHkUnVVVT # UsgC0Huj09duNfMaJ9ogxhPNThgq3i8w3DAGZ61AMeF0C1M+mU5eucj1Ijod5O2M # MPeJQ3/vKBtqGZg4eTtUHt/BPjN74SsJsyHqAdXVS5c+ItyKWg3Eforhox9k3Wgt # WTpgV4gkSiS4+A09roSdOI4vrRw+p+fL4WrxSK5nMYIauDCCGrQCAQEwcTBaMQsw # CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSswKQYD # VQQDEyJNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ1MgRU9DIENBIDAzAhMzAAiWokxQ # x66HAhz8AAAACJaiMA0GCWCGSAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAI # oAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIB # CzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIAY1r2BfhnbKSqiQNLQa # DmxtV7ruzIhsVuhhU9w7XwMEMA0GCSqGSIb3DQEBAQUABIIBgExiAHiPaeQOCdP5 # QESQJ9eVBsMVMgw1NwuuZBAAWBSB7MpndT2ZemJMY9it9mu6wTiYv2Pl+EN5UTtn # BAwhMX98JqiKdH+fP19Zm+eV3WX1fJCvRRBGGoge3tEznLu1Oe2wYcKmVoXX8lP4 # QTBxPQC4aS9w0eIYSfRNErE7xAVilfvrntjfv94U4joaqeVwYT/wDoSQLUoeereI # 7FkcbJayeSObqtG3FkqNmEugej5Mx7PEPKXh+CGbYhjtzIWYnlkgRs/CGgwX93lr # 769aXlV0sDXEN4Q/7/16Mh1JoPMC1dcTWRjEV6N8b8/Fr6vuXG3pOa/w0LoeMeiu # 7eq/6uKqX7ECBKADBcoR8N8RAcordW969xbyoJ5aX/vIWBdcHuu/WF5i9GnyaUvK # LHeFkoJwuwkm5q6Gia9hxEH6V3cPm+HXzjNV2sXkARGgb+xmh0NEfsNgKESGbyJw # lP3qJbWtMyKSyrkNairiNIdpTxDNnmHx4uphb74dT+qa5GXl2KGCGBEwghgNBgor # BgEEAYI3AwMBMYIX/TCCF/kGCSqGSIb3DQEHAqCCF+owghfmAgEDMQ8wDQYJYIZI # AWUDBAIBBQAwggFiBgsqhkiG9w0BCRABBKCCAVEEggFNMIIBSQIBAQYKKwYBBAGE # WQoDATAxMA0GCWCGSAFlAwQCAQUABCD/1Kzdyr22f2unQGRN0cRyurp840owBvYI # Fjht9oxlUQIGasj0Ku3aGBMyMDI2MTAxOTEzMjgyMS44MDNaMASAAgH0oIHhpIHe # MIHbMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQL # ExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxk # IFRTUyBFU046N0EwMC0wNUUwLUQ5NDcxNTAzBgNVBAMTLE1pY3Jvc29mdCBQdWJs # aWMgUlNBIFRpbWUgU3RhbXBpbmcgQXV0aG9yaXR5oIIPITCCB4IwggVqoAMCAQIC # EzMAAAAF5c8P/2YuyYcAAAAAAAUwDQYJKoZIhvcNAQEMBQAwdzELMAkGA1UEBhMC # VVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjFIMEYGA1UEAxM/TWlj # cm9zb2Z0IElkZW50aXR5IFZlcmlmaWNhdGlvbiBSb290IENlcnRpZmljYXRlIEF1 # dGhvcml0eSAyMDIwMB4XDTIwMTExOTIwMzIzMVoXDTM1MTExOTIwNDIzMVowYTEL # MAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAG # A1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjAw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCefOdSY/3gxZ8FfWO1BiKj # HB7X55cz0RMFvWVGR3eRwV1wb3+yq0OXDEqhUhxqoNv6iYWKjkMcLhEFxvJAeNcL # AyT+XdM5i2CgGPGcb95WJLiw7HzLiBKrxmDj1EQB/mG5eEiRBEp7dDGzxKCnTYoc # DOcRr9KxqHydajmEkzXHOeRGwU+7qt8Md5l4bVZrXAhK+WSk5CihNQsWbzT1nRli # VDwunuLkX1hyIWXIArCfrKM3+RHh+Sq5RZ8aYyik2r8HxT+l2hmRllBvE2Wok6IE # aAJanHr24qoqFM9WLeBUSudz+qL51HwDYyIDPSQ3SeHtKog0ZubDk4hELQSxnfVY # XdTGncaBnB60QrEuazvcob9n4yR65pUNBCF5qeA4QwYnilBkfnmeAjRN3LVuLr0g # 0FXkqfYdUmj1fFFhH8k8YBozrEaXnsSL3kdTD01X+4LfIWOuFzTzuoslBrBILfHN # j8RfOxPgjuwNvE6YzauXi4orp4Sm6tF245DaFOSYbWFK5ZgG6cUY2/bUq3g3bQAq # Zt65KcaewEJ3ZyNEobv35Nf6xN6FrA6jF9447+NHvCjeWLCQZ3M8lgeCcnnhTFty # QX3XgCoc6IRXvFOcPVrr3D9RPHCMS6Ckg8wggTrtIVnY8yjbvGOUsAdZbeXUIQAW # Ms0d3cRDv09SvwVRd61evQIDAQABo4ICGzCCAhcwDgYDVR0PAQH/BAQDAgGGMBAG # CSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRraSg6NS9IY0DPe9ivSek+2T3bITBU # BgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNy # b3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoG # CCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQF # MAMBAf8wHwYDVR0jBBgwFoAUyH7SaoUqG8oZmAQHJ89QEE9oqKIwgYQGA1UdHwR9 # MHsweaB3oHWGc2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01p # Y3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRp # ZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcmwwgZQGCCsGAQUFBwEBBIGHMIGE # MIGBBggrBgEFBQcwAoZ1aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j # ZXJ0cy9NaWNyb3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUyMFJvb3Ql # MjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3J0MA0GCSqGSIb3DQEB # DAUAA4ICAQBfiHbHfm21WhV150x4aPpO4dhEmSUVpbixNDmv6TvuIHv1xIs174bN # GO/ilWMm+Jx5boAXrJxagRhHQtiFprSjMktTliL4sKZyt2i+SXncM23gRezzsoOi # Bhv14YSd1Klnlkzvgs29XNjT+c8hIfPRe9rvVCMPiH7zPZcw5nNjthDQ+zD563I1 # nUJ6y59TbXWsuyUsqw7wXZoGzZwijWT5oc6GvD3HDokJY401uhnj3ubBhbkR83Rb # fMvmzdp3he2bvIUztSOuFzRqrLfEvsPkVHYnvH1wtYyrt5vShiKheGpXa2AWpsod # 4OJyT4/y0dggWi8g/tgbhmQlZqDUf3UqUQsZaLdIu/XSjgoZqDjamzCPJtOLi2hB # wL+KsCh0Nbwc21f5xvPSwym0Ukr4o5sCcMUcSy6TEP7uMV8RX0eH/4JLEpGyae6K # i8JYg5v4fsNGif1OXHJ2IWG+7zyjTDfkmQ1snFOTgyEX8qBpefQbF0fx6URrYiar # jmBprwP6ZObwtZXJ23jK3Fg/9uqM3j0P01nzVygTppBabzxPAh/hHhhls6kwo3QL # J6No803jUsZcd4JQxiYHHc+Q/wAMcPUnYKv/q2O444LO1+n6j01z5mggCSlRwD9f # aBIySAcA9S8h22hIAcRQqIGEjolCK9F6nK9ZyX4lhthsGHumaABdWzCCB5cwggV/ # oAMCAQICEzMAAABdxjl4T0B9M/0AAAAAAF0wDQYJKoZIhvcNAQEMBQAwYTELMAkG # A1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UE # AxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjAwHhcN # MjYwOTE3MTg1NzIxWhcNMjcwOTE0MTg1NzIxWjCB2zELMAkGA1UEBhMCVVMxEzAR # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p # Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg # T3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjdBMDAtMDVFMC1E # OTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lIFN0YW1waW5n # IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ33qNzx # FA+JrOqDscZ6+dPsV7GCAvPbhBo9jDI14cLJpN9SETe7u3YkVsVK9T31amVEEsKS # dDZQeDaeSJqUNsIqOzGwBLuxk/X8NlZRiQXWpxvO4DSika/dYqVOkfh0tr7JhkgJ # F9bioPywLlLbWfRzJOCGT7do8j/1LFMTQfDBLA2/tY1Tg0pLAxmcrTdiJhfOVG2f # OLABs5CMGqR41YyyDnCNO537p6f/KbGA/peBuk01fkCPSsgSqRxoPeOcReQY7vI6 # O2rjz5x7zEo9ocxn52SsPBZT6pgHqblwpWUb6b7ahzy83um4DC0SMvUf0hsm/0++ # 9t4vQmrxeVcTNdURAbwXDULV9UL2d81qjD6ZPbuLCoJ2nFVaweldvs9YJeT4mhG0 # OpP+7IovdJu27sqdZ4T8bVWrqd7qdub7NJADmjiTzp8xuLmQrAdDR/PhBDQFggz+ # j88S51ZmyicHcnQkVtEPKi/ksiHSVzKysfOXODEza9IZp45mrUVj/JTIo+nnSGFj # y8SFseXSTmJ+GlRJheRnhQKGUSscz0MNY31EJxAO8SdPqJaR2z30G8YvJNgTi0pU # Mx0ebwGtquF/l+yj4F1fz0SDmCZ1LikqppNEstixJHwa32fb9+aqb+UGBR/A1hr0 # oRoJWbAbiTCF1SyMk9bIhCfPX2JgLDDN/YzNAgMBAAGjggHLMIIBxzAdBgNVHQ4E # FgQUQ9sKXZlO8H4eVu395ahoyH9a57kwHwYDVR0jBBgwFoAUa2koOjUvSGNAz3vY # r0npPtk92yEwbAYDVR0fBGUwYzBhoF+gXYZbaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwUHVibGljJTIwUlNBJTIwVGltZXN0 # YW1waW5nJTIwQ0ElMjAyMDIwLmNybDB5BggrBgEFBQcBAQRtMGswaQYIKwYBBQUH # MAKGXWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9z # b2Z0JTIwUHVibGljJTIwUlNBJTIwVGltZXN0YW1waW5nJTIwQ0ElMjAyMDIwLmNy # dDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB # /wQEAwIHgDBmBgNVHSAEXzBdMFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIB # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9y # eS5odG0wCAYGZ4EMAQQCMA0GCSqGSIb3DQEBDAUAA4ICAQBCyETwKcMu124k4eFo # bUOoCnyXigtf6RyVDV/gjL73YFfBXoO6OKWgOJv6QrNPrzcQfy0kC60s42YCa4aU # WgE04toodo2lHJ9dimsX2vgY1RzMrHyGIxmPRoSJWmUdZvrD2pLYnqaX/KyM/5V/ # Plse6M4GhRGJ1NO+kerQmxd1cTufwcm1K1xzCDKHDbUGe3kLR3MBNsIKLaBs5s9L # lNoCYi+51r5eH2rQlHLTlgQmDh/dK073VDjdPlbQAaWrP5oV7q0MqQVVmyEz4q3X # B4hKgHtinFBzAnmswbFL4R3yLENCsR3iDwA6WCZFUTTMQQooIQ6IrbBy0F++P+HC # JPMSj6OgkOXmNQFCLlmOg4l0OBZo1ToPoCBDIng8jkIrpJjE3THOmCt5GB/128sZ # ElCs7Ohq/B5JAWYlN7Mi5HtwmnXrynaP4RV0j2bi1lr1eYY6N2nfMeD4N6FqLh/b # z/sJq6w81Smv6Zx0WEZAonPpSSgjHPuCBXPMPYOUgpKFPp+JwsYMAjuvKj8mnLNT # hsZVat+MH8MHQiCzEe3LTOb6Anz+q+xuu1+D1H11uQycKOmR3ndc66EY+IyGsWeS # /SDZ7kvXFWpXcK/jWCJuZ5ObEACcwae7ulG78hm7Vl2Dzbcdib7/ETWE08z6mhWi # dmM5mmDrbOQGw78kR9rzYcmTSjGCB0Mwggc/AgEBMHgwYTELMAkGA1UEBhMCVVMx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9z # b2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjACEzMAAABdxjl4T0B9 # M/0AAAAAAF0wDQYJYIZIAWUDBAIBBQCgggScMBEGCyqGSIb3DQEJEAIPMQIFADAa # BgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MTAx # OTEzMjgyMVowLwYJKoZIhvcNAQkEMSIEIEiWUP6pJ0KREPD0b5DXcoR5hWGsVScY # gh/H6hT6bJTyMIG5BgsqhkiG9w0BCRACLzGBqTCBpjCBozCBoAQgLTVkS2/p8+5C # YqFlp0aiuYaFAENeb9zL6xe93MQCSl0wfDBlpGMwYTELMAkGA1UEBhMCVVMxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0 # IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjACEzMAAABdxjl4T0B9M/0A # AAAAAF0wggNeBgsqhkiG9w0BCRACEjGCA00wggNJoYIDRTCCA0EwggIpAgEBMIIB # CaGB4aSB3jCB2zELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO # BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEl # MCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMe # blNoaWVsZCBUU1MgRVNOOjdBMDAtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3Nv # ZnQgUHVibGljIFJTQSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eaIjCgEBMAcGBSsO # AwIaAxUAvae6tbWxgM8HaMBsDxHEmsyWkPWgZzBlpGMwYTELMAkGA1UEBhMCVVMx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9z # b2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjAwDQYJKoZIhvcNAQEL # BQACBQDuf/jZMCIYDzIwMjYxMDE5MDIwMzA1WhgPMjAyNjEwMjAwMjAzMDVaMHQw # OgYKKwYBBAGEWQoEATEsMCowCgIFAO5/+NkCAQAwBwIBAAICEREwBwIBAAICEgcw # CgIFAO6BSlkCAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgC # AQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQsFAAOCAQEAihZ1tLYjQuwX # ieVHwN2TT6HzEDFiHmEYUrwL93mSEC1ttFCndhyK2oZm1D1++19XkbnkinJVT1vr # PQ3ooxhQbd7qO14VAe1T5GyboPE7cSICpdr30HS2JO9phqBW7QAfpTVGT0WSidQm # nXNY8R5XAz7gP4MZuHhj6mPYa7m5pDhppBEwSsGOhcvP2KpsDCm2KDqRFH/+HY2l # ZPg1vcTpZR7SiL6Xp9FTHmJIYjYB9X/CYHRarMw8Lgc9rkB+i+Ft5vQThTgy3Ul4 # v3G6vTbKVYpFkkEdVGmWmmcHbRf+CogAXP1qx1LjPIAukDZIxWZezQusnmHuzAJ2 # hSdpdXKp2TANBgkqhkiG9w0BAQEFAASCAgCMcyFIBnawCxzX6D6v24SzCk9ItCUu # U8g6/RZPcNj3AfMEiDqEjJ/KhnFUkJ9wjt7A94hAnekqUtWAB2wf7plSvN+eaKe/ # 1zzeR1PyvbMOGPijXiwRKd7wkY4qKYNdsgKHNDc7BHwt/2LDCh06Vdcu/nCSwyA0 # 7G7HUC5SscNN4sbMc4R1DZMm8qZ5fefQ774rV9ynP+ud0QYQksqOUXxJsA4OAckH # LyQAi94d0v+RRTaQW7+s8GSavnmA8jINBC6sZftGS4W1tiH9Gb+jbUFat3WC9v/H # OJQeDhYYWJHwQkYH6FyhBUeuLp54gwtiJc1I0F2iXJvw3CF3bOBULOVlHMjK2vF+ # mpDQ6GjAWlIo70XHC6srP7YmXDH5SJrWnqsaz2KBd4CV83A3/ho9hmG9ovTw7qFl # B8SFB9MmYrZn4gVTSkj+q9gVIfcgyyj8r0NCW/Qubnparb/2oWrs7+gIi9aIy24H # 0rQQucf4u0ZAde9l45oqBoy+0lX5RhLQBvXtSLxda9JLgxGTklV10kf1ZuO1wry7 # 3vBi+XSMA1v8UIkb+hJmIQ+Ac3j3phV70UKc/nE9ycAqd6XsNRm3eEBtlTBODw8c # 5nvYVA+8XtOCIIWZkiVXwxXSxdZOPNg7fx077z2kNpP+NFEaarHYWn0CsApZpAcA # F49CiPEubTAdiA== # SIG # End signature block |