MSStore.psm1
################################ # Start: Internal use functions ################################ function New-CV() { $cv = [Convert]::ToBase64String([Guid]::NewGuid().ToByteArray(), 0, 12) $cv } function Get-AccessTokenFromSessionData() { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [System.Management.Automation.SessionState] $SessionState ) $connectionInfo = Get-MSStoreConnectionInfo -SessionState $SessionState $token = Get-AccessToken -ConnectionInfo $connectionInfo $token } function Get-AccessToken() { param( [Parameter(Mandatory = $true)] [PSCustomObject]$ConnectionInfo ) $authCtx = $ConnectionInfo.AuthCtx $credentials = $ConnectionInfo.Credentials $clientId = $ConnectionInfo.ClientId $resource = $ConnectionInfo.Resource $userCredential = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential"($credentials.Username, $credentials.Password) $token = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync( $AuthCtx, $Resource, $ClientId, $userCredential).Result $token } function Get-MSStoreConnectionInfo { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [System.Management.Automation.SessionState] $SessionState ) if ($sessionState.PSVariable -eq $null) { throw "unable to access SessionState.PSVariable, Please call Connect-MSStore before calling any other Powershell CmdLet for the MSStore Module" } $connectionInfo = $sessionState.PSVariable.GetValue("ConnectionInfo"); if ($connectionInfo -eq $null) { throw "You must call the Connect-MSStore cmdlet before calling any other cmdlets" } return $connectionInfo } function Get-MSStoreBaseUri() { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [System.Management.Automation.SessionState] $SessionState ) $connectionInfo = Get-MSStoreConnectionInfo -SessionState $SessionState $connectionInfo.MtsBaseUri } ################################ # End: Internal use functions ################################ ################################ # Start: Exported functions ################################ <# .SYNOPSIS Method to retrieve token for access to MSStore #> function Grant-MSStoreClientAppAccess() { param( [string] $ClientId = "295a96a4-53fa-41ee-9a49-91fb99f95a00", [Uri] $RedirectUri = [uri] "http://localhost/mts/tools", [string] $Resource = "https://onestore.microsoft.com" ) $authorityUrl = "https://login.windows.net/common" $authCtx = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" $authorityUrl $platformParams = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" ([Microsoft.IdentityModel.Clients.ActiveDirectory.PromptBehavior]::Always) $token = $authCtx.AcquireTokenAsync($Resource, $ClientId, $RedirectUri, $platformParams).Result if ($token -eq $null) { Write-Error "Unable to properly authorize the client application $($ClientId)" } } <# .SYNOPSIS Method to connect to MSStore with the credentials specified #> function Connect-MSStore() { [CmdletBinding()] param( # Parameter help description [Parameter(Mandatory = $true)] [pscredential] $Credentials, [string] $ClientId = "295a96a4-53fa-41ee-9a49-91fb99f95a00", [Uri] $RedirectUri = [uri] "http://localhost/mts/tools", [string] $Resource = "https://onestore.microsoft.com", [string] $MtsBaseUri = "https://bspmts.mp.microsoft.com" ) $authorityUrl = "https://login.windows.net/common" $authCtx = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" $authorityUrl $connectionInfo = [PSCustomObject]@{ AuthCtx = $authCtx Credentials = $Credentials Resource = $Resource ClientId = $ClientId MtsBaseUri = $MtsBaseUri.TrimEnd("/") # no trailing slashes allowed } $token = Get-AccessToken -ConnectionInfo $connectionInfo if ($token -eq $null) { throw "Unable to retrieve token for user '$($Credentials.Username)', ensure you've allowed access to the client application by calling Grant-MSStoreClientAppAccess" } $sessionState = $PSCmdlet.SessionState $sessionState.PSVariable.Set("ConnectionInfo", $connectionInfo) } <# .SYNOPSIS Method to retrieve applications from tenant's inventory #> function Get-MSStoreInventory() { [CmdletBinding()] param( [string] $ContinuationToken, [switch] $ExcludeOnline, [switch] $IncludeOffline, [int] $MaxResults = 25, [System.Nullable[DateTime]]$ModifiedSince = $null ) $token = Get-AccessTokenFromSessionData -SessionState $PSCmdlet.SessionState $cv = New-CV $mtsBaseUri = Get-MSStoreBaseUri -SessionState $PSCmdlet.SessionState $mDollarBaseUri = "https://displaycatalog.mp.microsoft.com" if ($ExcludeOnline -and $ExcludeOffline) { throw "Cannot exclude both online and offline from the inventory query" } $queryParameters = "" if (-not $ExcludeOnline) { $queryParameters += "licenseTypes=Online&" } if ($IncludeOffline) { $queryParameters += "licenseTypes=Offline&" } if (-not [String]::IsNullOrWhiteSpace($ContinuationToken)) { $queryParameters += "continuationtoken=$($ContinuationToken)&" } if ($MaxResults -ne $null) { $queryParameters += "maxResults=$($MaxResults)&" } if ($ModifiedSince -ne $null) { $queryParameters += "modifiedSince=$($ModifiedSince.Value.ToString("O"))&" } $queryParameters = $queryParameters.TrimEnd("&"); $queryParameters += "&IncludeRemoved=false&includeSubscription=true" $restPath = "$mtsBaseUri/V1/Inventory?$queryParameters" $response = Invoke-RestMethod ` -Method GET ` -Uri $restPath ` -Headers @{ "MS-CV" = $cv "Authorization" = "Bearer $($token.AccessToken)" } $productDictionary = @{} $productList = @($response.inventoryEntries | % {$_.productKey.productId}) -join "," $mDollarQueryParameters = Get-QueryString ([ordered]@{ bigIds = $productList market = "US" languages = "en-us" catalogId = "4" fieldsTemplate = "Details" }) $mDollarRestPath = "$mDollarBaseUri/v7.0/products?$mDollarQueryParameters" $mDollarContinuationToken = $null do { $mDollarresponse = Invoke-RestMethod ` -Method GET ` -Uri $mDollarRestPath ` -Headers @{ "MS-CV" = $cv "Authorization" = "Bearer $($token.AccessToken)" } foreach ($product in $mDollarresponse.products) { $productDictionary.Add($product.productId, $product.LocalizedProperties.ProductTitle) } $mDollarContinuationToken = $result.ContinuationToken }while (-not ([String]::IsNullOrWhiteSpace($mDollarContinuationToken))) foreach ($inventoryEntry in $response.inventoryEntries) { New-Object PSObject -Property @{ ProductTitle = $productDictionary[$inventoryEntry.productKey.productId] ProductId = $inventoryEntry.productKey.productId SkuId = $inventoryEntry.productKey.skuId LicenseType = $inventoryEntry.licenseType } } } function Get-QueryString { param( [System.Collections.Specialized.OrderedDictionary]$Parameters ) if ($Parameters) { @($Parameters.GetEnumerator() | ForEach-Object { $_.Name + '=' + $_.Value }) -join '&' } } function Get-MSStoreSeatAssignments() { [CmdletBinding(DefaultParameterSetName = "Batch")] param( [Parameter(Mandatory = $true)] [string] $ProductId, [Parameter(Mandatory = $true)] [string] $SkuId, [Parameter(ParameterSetName = "Batch")] [ValidateRange(1, 25)] [int]$PageSize = 25 ) $continuationToken = $null do { $result = Get-MtsSeatAssignmentsInternal ` -ProductId $ProductId ` -SkuId $SkuId ` -MaxPageSize $PageSize ` -ContinuationToken $continuationToken ` -SessionState $PSCmdlet.SessionState Write-Output $result.Seats $continuationToken = $result.ContinuationToken } while (-not ([String]::IsNullOrWhiteSpace($continuationToken))) } <# .SYNOPSIS Method to retrieve Seat Assignment details #> function Get-MSStoreSeatAssignmentsInternal() { [CmdletBinding(DefaultParameterSetName = "Base")] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $ProductId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $SkuId , [Parameter(ParameterSetName = "Base")] [string] $ContinuationToken, [Parameter(ParameterSetName = "Base")] [int] $MaxPageSize = 25 ) Get-MtsSeatAssignmentsInternal ` -ProductId $ProductId ` -SkuId $SkuId ` -ContinuationToken $ContinuationToken ` -MaxPageSize $MaxPageSize ` -SessionState $PSCmdlet.SessionState } function Get-MtsSeatAssignmentsInternal() { [CmdletBinding(DefaultParameterSetName = "Base")] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $ProductId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $SkuId , [Parameter(ParameterSetName = "Base")] [string] $ContinuationToken, [Parameter(ParameterSetName = "Base")] [int] $MaxPageSize = 25, [Parameter(Mandatory = $true)] [System.Management.Automation.SessionState] $SessionState ) $token = Get-AccessTokenFromSessionData -SessionState $SessionState $cv = New-CV $mtsBaseUri = Get-MSStoreBaseUri -SessionState $SessionState $queryParameters = "" if (-not [String]::IsNullOrWhiteSpace($ContinuationToken)) { $queryParameters += "continuationtoken=$($ContinuationToken)&" } if ($MaxPageSize -ne $null) { $queryParameters += "maxResults=$($MaxPageSize)&" } # get rid of any trailing ampersands $queryParameters = $queryParameters.TrimEnd("&"); $restPath = "$mtsBaseUri/V1/Inventory/$($ProductId)/$($SkuId)/Seats?$($queryParameters)" $response = Invoke-RestMethod ` -Method GET ` -Uri $restPath ` -Headers @{ "MS-CV" = $cv "Authorization" = "Bearer $($token.AccessToken)" } $response } <# .SYNOPSIS Method to assign seats to a user #> function Add-MSStoreSeatAssignment() { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $Username, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $ProductId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $SkuId ) $token = Get-AccessTokenFromSessionData -SessionState $PSCmdlet.SessionState $cv = New-CV $mtsBaseUri = Get-MSStoreBaseUri -SessionState $PSCmdlet.SessionState $restPath = "$mtsBaseUri/V1/Inventory/$($ProductId)/$($SkuId)/Seats/$($Username)" $response = Invoke-RestMethod ` -Method Post ` -Uri $restPath ` -Headers @{ "MS-CV" = $cv "Authorization" = "Bearer $($token.AccessToken)" } ` -ContentType 'application/json' $response Get-StoreInstallLink $ProductId $SkuId } <# .SYNOPSIS Method to remove seats assignments #> function Remove-MSStoreSeatAssignments() { [CmdletBinding(DefaultParameterSetName = "Usernames")] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $ProductId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $SkuId, [Parameter(Mandatory = $false)] [ValidateRange(1, 25)] [int] $BatchSize = 25, [Parameter(Mandatory = $true, ParameterSetName = "Usernames")] [string[]] $Usernames, [Parameter(Mandatory = $true, ParameterSetName = "Csv")] [ValidateNotNullOrEmpty()] [string] $PathToCsv, [Parameter(Mandatory = $false, ParameterSetName = "Csv")] [ValidateNotNullOrEmpty()] [string] $ColumnName = "Username", [switch] $ShowProgress ) if ($PSCmdlet.ParameterSetName -eq "Usernames") { Start-MtsBulkSeatOperation ` -Operation "reclaim" ` -ProductId $ProductId ` -SkuId $SkuId ` -BatchSize $BatchSize ` -Usernames $Usernames ` -ShowProgress:$ShowProgress ` -SessionState $PSCmdlet.SessionState } elseif ($PSCmdlet.ParameterSetName -eq "Csv") { Start-MtsBulkSeatOperation ` -Operation "reclaim" ` -ProductId $ProductId ` -SkuId $SkuId ` -BatchSize $BatchSize ` -PathToCsv $PathToCsv ` -ColumnName $ColumnName ` -ShowProgress:$ShowProgress ` -SessionState $PSCmdlet.SessionState } } <# .SYNOPSIS Method to assign seats to a user #> function Add-MSStoreSeatAssignments() { [CmdletBinding(DefaultParameterSetName = "Usernames")] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $ProductId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $SkuId, [Parameter(Mandatory = $false)] [ValidateRange(1, 25)] [int] $BatchSize = 25, [Parameter(Mandatory = $true, ParameterSetName = "Usernames")] [string[]] $Usernames, [Parameter(Mandatory = $true, ParameterSetName = "Csv")] [ValidateNotNullOrEmpty()] [string] $PathToCsv, [Parameter(Mandatory = $false, ParameterSetName = "Csv")] [ValidateNotNullOrEmpty()] [string] $ColumnName = "Username", [switch] $ShowProgress ) if ($PSCmdlet.ParameterSetName -eq "Usernames") { Start-MtsBulkSeatOperation ` -Operation "assign" ` -ProductId $ProductId ` -SkuId $SkuId ` -BatchSize $BatchSize ` -Usernames $Usernames ` -ShowProgress:$ShowProgress ` -SessionState $PSCmdlet.SessionState } elseif ($PSCmdlet.ParameterSetName -eq "Csv") { Start-MtsBulkSeatOperation ` -Operation "assign" ` -ProductId $ProductId ` -SkuId $SkuId ` -BatchSize $BatchSize ` -PathToCsv $PathToCsv ` -ColumnName $ColumnName ` -ShowProgress:$ShowProgress ` -SessionState $PSCmdlet.SessionState } Get-StoreInstallLink $ProductId $SkuId } function Start-MtsBulkSeatOperation() { [CmdletBinding(DefaultParameterSetName = "Usernames")] param( [Parameter(Mandatory = $true)] [string] $Operation, [Parameter(Mandatory = $true)] [string] $ProductId, [Parameter(Mandatory = $true)] [string] $SkuId, [Parameter(Mandatory = $false)] [ValidateRange(1, 25)] [int] $BatchSize = 25, [Parameter(Mandatory = $true, ParameterSetName = "Usernames")] [string[]] $Usernames, [Parameter(Mandatory = $true, ParameterSetName = "Csv")] [ValidateNotNullOrEmpty()] [string] $PathToCsv, [Parameter(Mandatory = $false, ParameterSetName = "Csv")] [ValidateNotNullOrEmpty()] [string] $ColumnName = "Username", [switch] $ShowProgress, [Parameter(Mandatory = $true)] [System.Management.Automation.SessionState] $SessionState ) process { $_enforceSingleCall = $false $usernamesToProcess = $null if ($PSCmdlet.ParameterSetName -eq "Usernames") { if ($Usernames -eq $null -or $Usernames.Length -eq 0) { throw "At least one username must be specified in the Usernames parameter" } if ($_enforceSingleCall -and $Usernames.Length -gt 25) { throw "The maximum number of assignments in one call is 25." } $usernamesToProcess = [string[]] ($Usernames | ? {-not [String]::IsNullOrWhiteSpace($_)}) } elseif ($PSCmdlet.ParameterSetName -eq "Csv") { $inputData = Import-Csv -Path $PathToCsv $usernamesToProcess = [string[]] ($inputData | % { $_.$ColumnName}) # read the Csv # take only entries which have a "Username" column in them } $processedItemCount = 0; while ($processedItemCount -lt $usernamesToProcess.Length) { if ($ShowProgress) { Write-Progress -Activity "Bulk Operation" -Status "Percent complete:" -PercentComplete (($processedItemCount / $usernamesToProcess.Length) * 100) } $currentBatch = [string[]]($usernamesToProcess | select-object -Skip $processedItemCount -First $BatchSize) # get a new token on each "batch" to ensure it's not expired $token = Get-AccessTokenFromSessionData -SessionState $SessionState $cv = New-CV $mtsBaseUri = Get-MSStoreBaseUri -SessionState $SessionState $body = @{ usernames = $currentBatch seatAction = $Operation } $restPath = "$mtsBaseUri/V1/Inventory/$($ProductId)/$($SkuId)/Seats" $response = Invoke-RestMethod ` -Method Post ` -Uri $restPath ` -Headers @{ "MS-CV" = $cv "Authorization" = "Bearer $($token.AccessToken)" } ` -Body ($body | ConvertTo-Json) ` -ContentType 'application/json' # process bulk response into individual items $successfulAssignments = [object[]]$response.SeatDetails $failedAssignments = [object[]]$response.FailedSeatOperations if ($successfulAssignments -ne $null) { foreach ($successfulAssignment in $successfulAssignments) { Write-Output (New-Object psobject($successfulAssignment) -Property @{ Result = "Succeeded" }) } } if ($failedAssignments -ne $null) { foreach ($failedAssignment in $failedAssignments) { Write-Output (New-Object psobject($failedAssignment) -Property @{ Result = "Failed" }) } } $processedItemCount += $currentBatch.Length if ($ShowProgress) { Write-Progress -Activity "Bulk Operation" -Status "Percent complete:" -PercentComplete (($processedItemCount / $usernamesToProcess.Length) * 100) } } } } function Remove-MSStoreSeatAssignmentsLegacy() { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateCount(1, 25)] [string[]] $Usernames, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $ProductId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $SkuId ) $token = Get-AccessTokenFromSessionData -SessionState $PSCmdlet.SessionState $cv = New-CV $mtsBaseUri = Get-MSStoreBaseUri -SessionState $PSCmdlet.SessionState $body = @{ usernames = $Usernames seatAction = "reclaim" } $restPath = "$mtsBaseUri/V1/Inventory/$($ProductId)/$($SkuId)/Seats" $response = Invoke-RestMethod ` -Method Post ` -Uri $restPath ` -Headers @{ "MS-CV" = $cv "Authorization" = "Bearer $($token.AccessToken)" } ` -Body ($body | ConvertTo-Json) ` -ContentType 'application/json' $response } <# .SYNOPSIS Method to remove seats assigned to a user #> function Remove-MSStoreSeatAssignment() { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $Username, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $ProductId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $SkuId ) $token = Get-AccessTokenFromSessionData -SessionState $PSCmdlet.SessionState $cv = New-CV $mtsBaseUri = Get-MSStoreBaseUri -SessionState $PSCmdlet.SessionState $restPath = "$mtsBaseUri/V1/Inventory/$($ProductId)/$($SkuId)/Seats/$($Username)" $response = Invoke-RestMethod ` -Method Delete ` -Uri $restPath ` -Headers @{ "MS-CV" = $cv "Authorization" = "Bearer $($token.AccessToken)" } $response } <# .SYNOPSIS Method to retrieve install link for given product and sku #> function Get-StoreInstallLink() { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $ProductId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $SkuId ) write-host "You can provide this URL to your users in order to install this app from the store:" $installLink = "https://businessstore.microsoft.com/en-us/AppInstall?productId=" + $ProductId + "&skuId=" + $SkuId + "&catalogId=4" write-host $installLink `n`n } ################################ # End: Exported functions ################################ Write-Host "MSStore module loaded" # SIG # Begin signature block # MIIkVwYJKoZIhvcNAQcCoIIkSDCCJEQCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBbkz+TOsOZAHLC # 6/jyZ7/boJaNQzH0WHxYK3A00rUHeqCCDZMwggYRMIID+aADAgECAhMzAAAAjoeR # pFcaX8o+AAAAAACOMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMTYxMTE3MjIwOTIxWhcNMTgwMjE3MjIwOTIxWjCBgzEL # MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v # bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UECxMETU9Q # UjEeMBwGA1UEAxMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMIIBIjANBgkqhkiG9w0B # AQEFAAOCAQ8AMIIBCgKCAQEA0IfUQit+ndnGetSiw+MVktJTnZUXyVI2+lS/qxCv # 6cnnzCZTw8Jzv23WAOUA3OlqZzQw9hYXtAGllXyLuaQs5os7efYjDHmP81LfQAEc # wsYDnetZz3Pp2HE5m/DOJVkt0slbCu9+1jIOXXQSBOyeBFOmawJn+E1Zi3fgKyHg # 78CkRRLPA3sDxjnD1CLcVVx3Qv+csuVVZ2i6LXZqf2ZTR9VHCsw43o17lxl9gtAm # +KWO5aHwXmQQ5PnrJ8by4AjQDfJnwNjyL/uJ2hX5rg8+AJcH0Qs+cNR3q3J4QZgH # uBfMorFf7L3zUGej15Tw0otVj1OmlZPmsmbPyTdo5GPHzwIDAQABo4IBgDCCAXww # HwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0OBBYEFKvI1u2y # FdKqjvHM7Ww490VK0Iq7MFIGA1UdEQRLMEmkRzBFMQ0wCwYDVQQLEwRNT1BSMTQw # MgYDVQQFEysyMzAwMTIrYjA1MGM2ZTctNzY0MS00NDFmLWJjNGEtNDM0ODFlNDE1 # ZDA4MB8GA1UdIwQYMBaAFEhuZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEsw # SaBHoEWGQ2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0Nv # ZFNpZ1BDQTIwMTFfMjAxMS0wNy0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsG # AQUFBzAChkVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p # Y0NvZFNpZ1BDQTIwMTFfMjAxMS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkq # hkiG9w0BAQsFAAOCAgEARIkCrGlT88S2u9SMYFPnymyoSWlmvqWaQZk62J3SVwJR # avq/m5bbpiZ9CVbo3O0ldXqlR1KoHksWU/PuD5rDBJUpwYKEpFYx/KCKkZW1v1rO # qQEfZEah5srx13R7v5IIUV58MwJeUTub5dguXwJMCZwaQ9px7eTZ56LadCwXreUM # tRj1VAnUvhxzzSB7pPrI29jbOq76kMWjvZVlrkYtVylY1pLwbNpj8Y8zon44dl7d # 8zXtrJo7YoHQThl8SHywC484zC281TllqZXBA+KSybmr0lcKqtxSCy5WJ6PimJdX # jrypWW4kko6C4glzgtk1g8yff9EEjoi44pqDWLDUmuYx+pRHjn2m4k5589jTajMW # UHDxQruYCen/zJVVWwi/klKoCMTx6PH/QNf5mjad/bqQhdJVPlCtRh/vJQy4njpI # BGPveJiiXQMNAtjcIKvmVrXe7xZmw9dVgh5PgnjJnlQaEGC3F6tAE5GusBnBmjOd # 7jJyzWXMT0aYLQ9RYB58+/7b6Ad5B/ehMzj+CZrbj3u2Or2FhrjMvH0BMLd7Hald # G73MTRf3bkcz1UDfasouUbi1uc/DBNM75ePpEIzrp7repC4zaikvFErqHsEiODUF # he/CBAANa8HYlhRIFa9+UrC4YMRStUqCt4UqAEkqJoMnWkHevdVmSbwLnHhwCbww # ggd6MIIFYqADAgECAgphDpDSAAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYD # VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe # MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv # ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5 # MDlaFw0yNjA3MDgyMTA5MDlaMH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIw # MTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQ # TTS68rZYIZ9CGypr6VpQqrgGOBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULT # iQ15ZId+lGAkbK+eSZzpaF7S35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYS # L+erCFDPs0S3XdjELgN1q2jzy23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494H # DdVceaVJKecNvqATd76UPe/74ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZ # PrGMXeiJT4Qa8qEvWeSQOy2uM1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5 # bmR/U7qcD60ZI4TL9LoDho33X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGS # rhwjp6lm7GEfauEoSZ1fiOIlXdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADh # vKwCgl/bwBWzvRvUVUvnOaEP6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON # 7E1JMKerjt/sW5+v/N2wZuLBl4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xc # v3coKPHtbcMojyyPQDdPweGFRInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqw # iBfenk70lrC8RqBsmNLg1oiMCwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMC # AQAwHQYDVR0OBBYEFEhuZOVQBdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQM # HgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1Ud # IwQYMBaAFHItOgIxkEO5FAVO4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0 # dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0Nl # ckF1dDIwMTFfMjAxMV8wM18yMi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUF # BzAChkJodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0Nl # ckF1dDIwMTFfMjAxMV8wM18yMi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGC # Ny4DMIGDMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp # b3BzL2RvY3MvcHJpbWFyeWNwcy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcA # YQBsAF8AcABvAGwAaQBjAHkAXwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZI # hvcNAQELBQADggIBAGfyhqWY4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4s # PvjDctFtg/6+P+gKyju/R6mj82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKL # UtCw/WvjPgcuKZvmPRul1LUdd5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7 # pKkFDJvtaPpoLpWgKj8qa1hJYx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft # 0N3zDq+ZKJeYTQ49C/IIidYfwzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4 # MnEnGn+x9Cf43iw6IGmYslmJaG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxv # FX1Fp3blQCplo8NdUmKGwx1jNpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG # 0QaxdR8UvmFhtfDcxhsEvt9Bxw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf # 0AApxbGbpT9Fdx41xtKiop96eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkY # S//WsyNodeav+vyL6wuA6mk7r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrv # QQqxP/uozKRdwaGIm1dxVk5IRcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIW # GjCCFhYCAQEwgZUwfjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAA # AI6HkaRXGl/KPgAAAAAAjjANBglghkgBZQMEAgEFAKCCAQcwGQYJKoZIhvcNAQkD # MQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJ # KoZIhvcNAQkEMSIEIJySPJigBXLwjtp3qUXM7NcyVcJOmC0zB2InxIoRR+TvMIGa # BgorBgEEAYI3AgEMMYGLMIGIoF6AXABNAGkAYwByAG8AcwBvAGYAdAAgAFMAdABv # AHIAZQAgAGYAbwByACAAQgB1AHMAaQBuAGUAcwBzACAAUABvAHcAZQByAFMAaABl # AGwAbAAgAG0AbwBkAHUAbABloSaAJGh0dHBzOi8vYnVzaW5lc3NzdG9yZS5taWNy # b3NvZnQuY29tIDANBgkqhkiG9w0BAQEFAASCAQCWpPspADgxw6mfY36DsbaexZDf # 698jWZJjL8lX+HOjBdGlyR5LkDAO2OxNFk9Btzi4N3yH6DDy5qLXeMGXhKYwR2UG # qkwPH7UTcX7oHBr2uCplVpPxGlzuGNUQkKSn0Z60CJ6aBYJ0d+DQ5E/SSWBxdxjL # dvcsarRzx0PXhLDxqN4IUExQLA456fByHJkGRk8uqrtXcIppVOcv+IE2ox/EouU6 # whG198aybepGfCgN4u3dyDtR5dowCDdsWkSLP6O4wK/ql9SVZEGQk5JDnd8c9bw+ # roGOyvFucTWDUscJc7J2o3x4nUst8/hDlNGohebURxKaf0uDpZUf/AFuGWFjoYIT # SjCCE0YGCisGAQQBgjcDAwExghM2MIITMgYJKoZIhvcNAQcCoIITIzCCEx8CAQMx # DzANBglghkgBZQMEAgEFADCCAT0GCyqGSIb3DQEJEAEEoIIBLASCASgwggEkAgEB # BgorBgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEIDQEJx4ObfpU+6tVFbj9skTU # bYVEGcPG4Iffch2fH4elAgZZelNloJsYEzIwMTcwODAxMTMzMTMyLjE0NlowBwIB # AYACAfSggbmkgbYwgbMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xDTALBgNVBAsTBE1PUFIxJzAlBgNVBAsTHm5DaXBoZXIgRFNFIEVTTjpDMEY0 # LTMwODYtREVGODElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj # ZaCCDs0wggZxMIIEWaADAgECAgphCYEqAAAAAAACMA0GCSqGSIb3DQEBCwUAMIGI # MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk # bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylN # aWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0xMDA3 # MDEyMTM2NTVaFw0yNTA3MDEyMTQ2NTVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI # EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv # ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD # QSAyMDEwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqR0NvHcRijog # 7PwTl/X6f2mUa3RUENWlCgCChfvtfGhLLF/Fw+Vhwna3PmYrW/AVUycEMR9BGxqV # Hc4JE458YTBZsTBED/FgiIRUQwzXTbg4CLNC3ZOs1nMwVyaCo0UN0Or1R4HNvyRg # MlhgRvJYR4YyhB50YWeRX4FUsc+TTJLBxKZd0WETbijGGvmGgLvfYfxGwScdJGcS # chohiq9LZIlQYrFd/XcfPfBXday9ikJNQFHRD5wGPmd/9WbAA5ZEfu/QS/1u5ZrK # sajyeioKMfDaTgaRtogINeh4HLDpmc085y9Euqf03GS9pAHBIAmTeM38vMDJRF1e # FpwBBU8iTQIDAQABo4IB5jCCAeIwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYE # FNVjOlyKMZDzQ3t8RhvFM2hahW1VMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBB # MAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP # 6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWlj # cm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2 # LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMu # Y3J0MIGgBgNVHSABAf8EgZUwgZIwgY8GCSsGAQQBgjcuAzCBgTA9BggrBgEFBQcC # ARYxaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL1BLSS9kb2NzL0NQUy9kZWZhdWx0 # Lmh0bTBABggrBgEFBQcCAjA0HjIgHQBMAGUAZwBhAGwAXwBQAG8AbABpAGMAeQBf # AFMAdABhAHQAZQBtAGUAbgB0AC4gHTANBgkqhkiG9w0BAQsFAAOCAgEAB+aIUQ3i # xuCYP4FxAz2do6Ehb7Prpsz1Mb7PBeKp/vpXbRkws8LFZslq3/Xn8Hi9x6ieJeP5 # vO1rVFcIK1GCRBL7uVOMzPRgEop2zEBAQZvcXBf/XPleFzWYJFZLdO9CEMivv3/G # f/I3fVo/HPKZeUqRUgCvOA8X9S95gWXZqbVr5MfO9sp6AG9LMEQkIjzP7QOllo9Z # Kby2/QThcJ8ySif9Va8v/rbljjO7Yl+a21dA6fHOmWaQjP9qYn/dxUoLkSbiOewZ # SnFjnXshbcOco6I8+n99lmqQeKZt0uGc+R38ONiU9MalCpaGpL2eGq4EQoO4tYCb # IjggtSXlZOz39L9+Y1klD3ouOVd2onGqBooPiRa6YacRy5rYDkeagMXQzafQ732D # 8OE7cQnfXXSYIghh2rBQHm+98eEA3+cxB6STOvdlR3jo+KhIq/fecn5ha293qYHL # pwmsObvsxsvYgrRyzR30uIUBHoD7G4kqVDmyW9rIDVWZeodzOwjmmC3qjeAzLhIp # 9cAvVCch98isTtoouLGp25ayp0Kiyc8ZQU3ghvkqmqMRZjDTu3QyS99je/WZii8b # xyGvWbWu3EQ8l1Bx16HSxVXjad5XwdHeMMD9zOZN+w2/XU/pnR4ZOC+8z1gFLu8N # oFA12u8JJxzVs341Hgi62jbb01+P3nSISRIwggTaMIIDwqADAgECAhMzAAAAo+8f # IiCBY9ylAAAAAACjMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w # IFBDQSAyMDEwMB4XDTE2MDkwNzE3NTY0OVoXDTE4MDkwNzE3NTY0OVowgbMxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xDTALBgNVBAsTBE1PUFIx # JzAlBgNVBAsTHm5DaXBoZXIgRFNFIEVTTjpDMEY0LTMwODYtREVGODElMCMGA1UE # AxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCCASIwDQYJKoZIhvcNAQEB # BQADggEPADCCAQoCggEBAKnRHpfHE2n4ODsVF+ZIDvlfgqxUnTAarRBd0PIF9z9o # hjda0ABT5pxtHGjyKcfW/zGYUk0RuvXBZIY6OQknVklen6EhGSkbzFoW4/N9AVUX # LOnhrJb7x5mvKHAAdSL6LnKUVF+60cWsMtTl1h558IGjCr5jvnhpZ+KPhdHJvsh/ # kIvkuH6Yrm++KmQIGki3OSHIavQkS2AQ1HKAcgg46W75O1PtWdsk1E1hyFvTaWMA # Mr3MsVE960C4f7i+u3IdwThs3gmObi2ZOmxFCN6zT1ttbYCR2SObSJlMHuURf7MX # nnaRveImFh8RABw635noLP/sdSxYKXCnFy0o7o+0o18CAwEAAaOCARswggEXMB0G # A1UdDgQWBBT6hbpmZuhGmdpwn7ohJUDb4OixcDAfBgNVHSMEGDAWgBTVYzpcijGQ # 80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jv # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNUaW1TdGFQQ0FfMjAxMC0wNy0w # MS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1p # Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0YVBDQV8yMDEwLTA3LTAxLmNy # dDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMA0GCSqGSIb3DQEB # CwUAA4IBAQAd0UW6W7S/iuaGjUXONYgmEkawM4NqYTHIFnP45iR6asHAFTc8jccp # DUjLdJelsofhBnjVQ4xTOvDiUQ54ttP8HI0l5VMaFdk+erzHu8FOZlhRGA9lJWEh # ob7mkcNgjvkJtD6IwqZygTsc8hAc1QWuiF00VVKoQ4aM8A1UvkvkS+4XlbabvAJr # Fs2yLWz1q9814QaDtFlB5x4B82hN99jeJCxGS0LAjRdzRFArjd52zX90Xd/mZMwy # uJ7Az2VSEQgGepe2g2WjYtjDg7o5jke4U6rDZhocvUlO9NzUB6zSuNFk+eB3yex2 # gMSrFyvrI4O1lonx2EuWkt1vqcI71vOcoYIDdjCCAl4CAQEwgeOhgbmkgbYwgbMx # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xDTALBgNVBAsTBE1P # UFIxJzAlBgNVBAsTHm5DaXBoZXIgRFNFIEVTTjpDMEY0LTMwODYtREVGODElMCMG # A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIlCgEBMAkGBSsOAwIa # BQADFQA15KP7Tj//Jg1x9W1eEnuRljimjaCBwjCBv6SBvDCBuTELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UECxMETU9QUjEnMCUGA1UE # CxMebkNpcGhlciBOVFMgRVNOOjRERTktMEM1RS0zRTA5MSswKQYDVQQDEyJNaWNy # b3NvZnQgVGltZSBTb3VyY2UgTWFzdGVyIENsb2NrMA0GCSqGSIb3DQEBBQUAAgUA # 3SrDBjAiGA8yMDE3MDgwMTA5MDYxNFoYDzIwMTcwODAyMDkwNjE0WjB0MDoGCisG # AQQBhFkKBAExLDAqMAoCBQDdKsMGAgEAMAcCAQACAjmSMAcCAQACAhkUMAoCBQDd # LBSGAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwGgCjAIAgEAAgMW # 42ChCjAIAgEAAgMHoSAwDQYJKoZIhvcNAQEFBQADggEBAHU5OA/4L4u9nxRcS+Dm # gifNaT5/R+PqG8tp08Oi7elVdN5ViaFBROnpY3k2LC0ISZTMXHiiyl4FvjcsjXlz # 6H/SiURpKabyDBxCcK/H0LJLmOgu5rALbJsD7bNcJ+O7su6iJku8VYNFe9b4AB5m # 1t6bihz1/dCwNY/a++QcNWxruz3VQLud+iBxXf6V5Pu317H4I4Bhnhn8hS5YTa+s # n4E3vWZN3UuWezDlOSSao5naGTXs9vBcAY9NtEGtlKYam5pzTEjWferVxkfwUiZo # FcnRAAJZ1K4BsQNU0PEhKLPK3M1V3mmNZtLPHgzRIwqny2Co3YotZ2ZYzH/9Yrzw # 6gwxggL1MIIC8QIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAIT # MwAAAKPvHyIggWPcpQAAAAAAozANBglghkgBZQMEAgEFAKCCATIwGgYJKoZIhvcN # AQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCDnzklYOniYpYeosZDG # 4YpWGh1Ecz/USt1YqJVHfpC9DDCB4gYLKoZIhvcNAQkQAgwxgdIwgc8wgcwwgbEE # FDXko/tOP/8mDXH1bV4Se5GWOKaNMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzAR # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p # Y3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3Rh # bXAgUENBIDIwMTACEzMAAACj7x8iIIFj3KUAAAAAAKMwFgQUfqYwrgG+WdpDCIXP # a1KHEKr64XYwDQYJKoZIhvcNAQELBQAEggEAguFmiVtjqGQLt/EmSlW0kXCdZFSN # 33e4oiC2Qmuhj9ayEppqPyE6RuMkBjELj/iZxPow+/7qds8N97KJ25Jp9F4YQt62 # iRNfRII9cGeoEkX5KTDWzDrsohlQCRELzfe87iAvF+dEoshtnAVPuoc8O2rVt8kg # rL9Y9YMphq89MmlmNkzvwBrfCAvYQD1SMddyIpDSm2ZrQjFpiFnnZHuEC7yM8A66 # hNHb/2Nkufjw7Nku3zekyhH7VfHUUAMIK2VcIFRxU17LbwLEzykv3yIqK0gzCjNp # xFN3GXa4OcLCPqLILw0kSfyYfZB0Njkkq4Wzj/mLnNJTL7e1KfJJxxjhhQ== # SIG # End signature block |