GraphHelper.psm1
|
#region Public commands function Add-GraphLargeFile { <# .SYNOPSIS Uploads large files to Microsoft Graph using the resumable upload protocol .DESCRIPTION Uploads large files to Microsoft Graph (OneDrive, SharePoint, etc.) using the resumable upload session API. This function handles files of any size by splitting them into chunks and uploading them sequentially. The upload uses 5MB chunks (320KB * 16) which is optimal for Graph API uploads and supports resumable uploads in case of network interruptions. The function automatically creates an upload session and manages the chunked upload process. .PARAMETER LocalFilePath The full path to the local file to upload. The file must exist and be readable. .PARAMETER GraphFilePath The Microsoft Graph API path where the file should be uploaded, excluding the ':/createUploadSession' suffix. Example: 'https://graph.microsoft.com/v1.0/me/drive/root:/Documents/myfile.pdf' .EXAMPLE Add-GraphLargeFile -LocalFilePath 'C:\Files\presentation.pptx' -GraphFilePath 'https://graph.microsoft.com/v1.0/me/drive/root:/Documents/presentation.pptx' Uploads a PowerPoint file to the current user's OneDrive Documents folder. .EXAMPLE Add-GraphLargeFile -LocalFilePath 'C:\Videos\training.mp4' -GraphFilePath 'https://graph.microsoft.com/v1.0/sites/{site-id}/drive/root:/Videos/training.mp4' -Verbose Uploads a video file to a SharePoint site's Videos folder with verbose output showing upload progress. .NOTES - Uses 5MB chunks for optimal performance - Automatically handles upload session creation - Supports conflict behavior of 'replace' - existing files will be overwritten - Uses Invoke-GraphWithRetry internally for reliability - Enable -Verbose to see detailed upload progress - Uses the authentication factory configured via Set-GraphAadFactory .LINK https://learn.microsoft.com/en-us/graph/api/driveitem-createuploadsession #> [CmdletBinding()] param ( [Parameter(Mandatory)] $LocalFilePath, [Parameter(Mandatory)] $GraphFilePath ) begin { $chunkSize = 320KB * 16 # 5MB chunks $graphUri = GetGraphRequestUri -Uri "$GraphFilePath" } process { $item = Get-Item -Path $LocalFilePath $fileSize = $item.length $fileStream = [System.IO.File]::OpenRead($item.FullName) Write-Verbose "Filesize: $fileSize" Write-Verbose "Chunksize: $chunkSize" try { $payload = @{ item = @{ '@microsoft.graph.conflictBehavior' = 'replace' } } Write-Verbose "Requesting upload session on $graphUri`:/createUploadSession" $uploadSession = Invoke-GraphWithRetry ` -RequestUri "$graphUri`:/createUploadSession" ` -method Post ` -body ($payload | ConvertTo-Json -Depth 10) ` -ContentType 'application/json' ` -ErrorAction Stop $uploadUrl = $uploadSession.uploadUrl Write-Verbose "UploadUrl: $uploadUrl" $offset = 0 while ($offset -lt $fileSize) { $bytesToRead = [Math]::Min($chunkSize, $fileSize - $offset) $buffer = New-Object byte[] $bytesToRead $bytesRead = $fileStream.Read($buffer, 0, $bytesToRead) if ($bytesRead -gt 0) { $contentRange = "bytes $offset-$($offset + $bytesRead - 1)/$fileSize" Write-Verbose "Writing range: $contentRange" Invoke-GraphWithRetry ` -RequestUri $uploadUrl ` -method Put ` -body $buffer ` -headers @{ 'Content-Range' = $contentRange } ` -ContentType 'application/octet-stream' | out-null $offset += $bytesRead } } } finally { $fileStream.Close() } } } function Get-GraphAuthorizationHeader { <# .SYNOPSIS Retrieves an authorization header for Microsoft Graph API calls .DESCRIPTION Obtains an access token from the configured AAD authentication factory with the Graph API scope and returns it as a hashtable containing the Authorization header. This command can be called directly but is primarily used by other module functions. .PARAMETER FactoryName Optional factory name override used to obtain the token. If omitted, the factory configured by Set-GraphAadFactory is used. .OUTPUTS System.Collections.Hashtable Returns a hashtable with the Authorization header containing the Bearer token. .EXAMPLE $authHeader = Get-GraphAuthorizationHeader Retrieves the authorization header for Graph API calls. .EXAMPLE $authHeader = Get-GraphAuthorizationHeader -FactoryName 'ManagedIdentityFactory' Retrieves the authorization header by explicitly selecting a token factory. .NOTES This function uses the factory configured via Set-GraphAadFactory. #> param ( $FactoryName = $script:graphConnection.FactoryName ) process { Get-AadToken -Factory $FactoryName -Scope $script:graphConnection.GraphScope -AsHashTable } } function Get-GraphData { <# .SYNOPSIS Retrieves data from Microsoft Graph API with automatic pagination .DESCRIPTION Executes a Microsoft Graph API GET request and automatically handles pagination by following @odata.nextLink references. This function retrieves all pages of data and returns the complete dataset. It uses Invoke-GraphWithRetry internally, so it inherits automatic retry logic for throttling. The function intelligently handles both single objects and arrays of results from the Graph API. .PARAMETER RequestUri The complete Microsoft Graph API request URL including query parameters. Example: 'https://graph.microsoft.com/v1.0/users' .PARAMETER OperationName The operation name to use for Application Insights logging. Default is 'Get-GraphData'. .PARAMETER AdditionalHeaders Additional HTTP headers to include in requests (for example ConsistencyLevel for advanced queries). .OUTPUTS System.Object[] Returns all objects from the Graph API response, automatically handling pagination. .EXAMPLE Get-GraphData -RequestUri 'https://graph.microsoft.com/v1.0/users' Retrieves all users from Microsoft Graph, automatically paginating through all result pages. .EXAMPLE Get-GraphData -RequestUri 'https://graph.microsoft.com/v1.0/groups?$filter=startswith(displayName,''Sales'')' Retrieves all groups whose display name starts with 'Sales', handling pagination automatically. .EXAMPLE Get-GraphData -RequestUri 'https://graph.microsoft.com/v1.0/me/messages?$top=50' -OperationName 'GetUserMessages' Retrieves all messages for the current user with custom operation name for Application Insights tracking. .NOTES - Automatically handles pagination via @odata.nextLink - Uses Invoke-GraphWithRetry internally for throttling protection - Suitable for large datasets that span multiple pages - Uses the authentication factory configured via Set-GraphAadFactory #> param ( [Parameter(Mandatory)] [Alias('Uri')] [string]$RequestUri, [Parameter()] $OperationName = 'Get-GraphData', [Parameter()] [System.Collections.Hashtable]$AdditionalHeaders = @{} ) process { $uri = GetGraphRequestUri $RequestUri while($true) { try { #get page of results $result = Invoke-GraphWithRetry -RequestUri $uri -method Get -Headers $AdditionalHeaders -ErrorAction Stop if($null -ne $result.value) { #returning array of results $result.value } else { #returning single object $result } $uri = $result.'@odata.nextLink' if([string]::IsNullOrEmpty($uri)) { #no more pages break; } } catch { Write-Warning "Could not retrieve data for uri: $uri. Error: $($_.Exception.Message)" throw } } } } function Invoke-GraphWithRetry { <# .SYNOPSIS Invokes a Graph API with automatic retry logic for throttling .DESCRIPTION Executes a Microsoft Graph API request with built-in retry logic to handle HTTP 429 (Too Many Requests) throttling responses. The function will automatically retry up to 100 times with exponential backoff when throttled. If the request returns paged results, it retrieves only a single page - callers should use Get-GraphData for automatic pagination. Supports Application Insights logging when an AILogger instance is provided when importing the module .PARAMETER RequestUri The complete Microsoft Graph API request URL including query parameters. Example: 'https://graph.microsoft.com/v1.0/users?$top=10' .PARAMETER Method The HTTP method to use for the request. Valid values are: Get, Post, Put, Patch, Delete. Default is 'Get'. .PARAMETER Body The request body for Post, Put, or Patch requests. Can be a string or object that will be sent with the request. .PARAMETER ContentType The content type for the request body. Default is 'application/json'. .PARAMETER Headers Additional HTTP headers to include in the request. The Authorization header will be automatically added. .PARAMETER OperationName The operation name to use for Application Insights logging. Default is 'Invoke-GraphWithRetry'. .PARAMETER RetryableErrorCodes HTTP status codes that should trigger retries. Default is 429. .PARAMETER MaxRetries Maximum number of retry attempts before the error is thrown. Default is 100. .PARAMETER DefaultBackOffSeconds Fallback delay in seconds used when the response does not include Retry-After. .OUTPUTS System.Object Returns the response from the Graph API call. .EXAMPLE Invoke-GraphWithRetry -RequestUri 'https://graph.microsoft.com/v1.0/users' Retrieves users from Microsoft Graph using the default GET method. .EXAMPLE $body = @{ displayName = 'Test Group' } | ConvertTo-Json Invoke-GraphWithRetry -RequestUri 'https://graph.microsoft.com/v1.0/groups' -Method Post -Body $body Creates a new group in Microsoft Graph. .EXAMPLE Invoke-GraphWithRetry -RequestUri 'https://graph.microsoft.com/v1.0/users/user@domain.com' -Method Delete Deletes a user from Microsoft Graph. .NOTES - Automatically handles HTTP 429 throttling with exponential backoff - Maximum retry attempts: 100 - Uses the authentication factory configured via Set-GraphAadFactory - Supports Application Insights telemetry when configured #> param ( [Parameter(Mandatory)] [Alias('Uri')] [string]$RequestUri, [Parameter()] $method = 'Get', [Parameter()] $body, [Parameter()] $contentType = 'application/json', [parameter()] [System.Collections.Hashtable] $Headers = @{}, [Parameter()] $OperationName = 'Invoke-GraphWithRetry', [Parameter()] [int[]]$RetryableErrorCodes = @(429), [Parameter()] [int]$MaxRetries = 100, [Parameter()] [int]$DefaultBackOffSeconds = 1 ) begin { $retries = 0 $graphUri = GetGraphRequestUri -Uri $RequestUri } process { do { $authHeader = Get-GraphAuthorizationHeader Write-Verbose "Invoking Graph API: $graphUri with method $method. Attempt #$($retries + 1)" $headers['Authorization'] = $authHeader['Authorization'] $resultCode = 'Ok' try { $requestStart = Get-Date -AsUTC switch($method) { {$_ -in @('Get', 'Delete')} { $result = Invoke-RestMethod -method $method -Uri $graphUri -headers $headers -ErrorAction Stop -Verbose:$VerbosePreference break; } {$_ -in @('Post', 'Patch', 'Put')} { $result = Invoke-RestMethod -method $method -Uri $graphUri -body $body -headers $headers -ContentType $contentType -ErrorAction Stop -Verbose:$VerbosePreference break; } } if($script:graphConnection.AiLogger) { Write-AiDependency -Target 'graph.microsoft.com' -DependencyType 'Graph API' -Name $OperationName -Data $graphUri -Start $requestStart -ResultCode 'Ok' -Success $true -Connection $script:graphConnection.AiLogger } $result break; #do-while } catch { $err = $_ if($null -ne $script:graphConnection.AiLogger) { Write-AiException -Exception $err.Exception -Connection $script:graphConnection.AiLogger } if($null -ne $err.exception.Response.StatusCode) { $resultCode = $err.exception.Response.StatusCode } else { $resultCode = 'Unknown' } if($retries -le $MaxRetries -and ($err.exception.Response.StatusCode -in $RetryableErrorCodes)) { $retries++ switch($err.exception.Response.StatusCode) { 429 { $retryAfter = $err.exception.Response.Headers['Retry-After'] if($null -eq $retryAfter) { $retryAfter = $DefaultBackOffSeconds * $retries } $waitTime = [int]$retryAfter break; } default { $waitTime = $DefaultBackOffSeconds * $retries break; } } Write-Warning "Retrying because of status code $($err.exception.Response.StatusCode) for $waitTime secs" start-sleep -Seconds $waitTime } else { throw } } finally { if($null -ne $script:graphConnection.AiLogger) { Write-AiDependency -Target 'graph.microsoft.com' -DependencyType 'Graph API' -Name $OperationName -Data $graphUri -Start $requestStart -ResultCode $resultCode -Success ($resultCode -eq 'Ok') -Connection $script:graphConnection.AiLogger } } }while($true) } } function Set-GraphAadFactory { <# .SYNOPSIS Sets the AAD authentication factory name for Graph API operations .DESCRIPTION Configures the authentication factory to be used for obtaining access tokens when making Graph API calls. The factory name corresponds to a factory registered with the AadAuthenticationFactory module. .PARAMETER Name The name of the authentication factory to use. This should match a factory registered with AadAuthenticationFactory module. Common values include 'ManagedIdentityFactory' or custom factory names. .EXAMPLE Set-GraphAadFactory -Name 'ManagedIdentityFactory' Configures the module to use managed identity for authentication. .EXAMPLE Set-GraphAadFactory -Name 'MyCustomFactory' Configures the module to use a custom authentication factory. #> param ( [Parameter(Mandatory)] [string]$Name ) process { $script:graphConnection.FactoryName = $Name } } function Set-GraphAiLogger { <# .SYNOPSIS Sets the Application Insights logger for telemetry .DESCRIPTION Configures the Application Insights logger instance to be used for logging telemetry data during Graph API operations. .PARAMETER Logger The AILogger instance to use for logging. This should be created using the ApplicationInsights module. .EXAMPLE $aiLogger = New-AiLogger -InstrumentationKey 'your-instrumentation-key' Set-GraphAiLogger -Logger $aiLogger Configures the module to use the specified Application Insights logger for telemetry. #> param ( [Parameter(Mandatory)] $Logger ) process { $script:graphConnection.AiLogger = $Logger } } function Set-GraphBaseUri { <# .SYNOPSIS Sets the base URI used for Microsoft Graph API requests. .DESCRIPTION Configures the base URI used to build absolute request URIs when a relative path is supplied to commands such as Invoke-GraphWithRetry and Get-GraphData. .PARAMETER BaseUri The base URI to use for Graph requests. Defaults to https://graph.microsoft.com/v1.0 when the module is imported. .EXAMPLE Set-GraphBaseUri -BaseUri 'https://graph.microsoft.com/v1.0' Uses the global Microsoft Graph endpoint. .EXAMPLE Set-GraphBaseUri -BaseUri 'https://graph.microsoft.us/v1.0' Uses the Microsoft Graph US Government endpoint. #> param ( [Parameter(Mandatory)] [string]$BaseUri ) process { $script:graphConnection.BaseUri = $BaseUri } } function Set-GraphScopes { <# .SYNOPSIS Sets the scopes for Graph API authentication .DESCRIPTION Configures the scope to be used when requesting access tokens for Graph API calls. The default scope is 'https://graph.microsoft.com/.default' which uses the permissions assigned to the application in Azure AD. .PARAMETER Scopes The scopes to use when requesting access tokens. The default is 'https://graph.microsoft.com/.default'. .EXAMPLE Set-GraphScopes -Scopes 'https://graph.microsoft.com/.default' Configures the module to use the default Graph API scope for authentication. .EXAMPLE Set-GraphScopes -Scopes 'https://graph.microsoft.com/User.Read' Configures the module to request a token with only User.Read permissions. #> param ( [Parameter()] [string[]]$Scopes = @('https://graph.microsoft.com/.default') ) process { $script:graphConnection.GraphScope = $Scopes } } #endregion Public commands #region Internal commands function GetGraphRequestUri { param ( [Parameter(Mandatory)] [string]$Uri ) process { if(-not $uri.StartsWith('http')) { if(-not $script:graphConnection.BaseUri) { throw "BaseUri is not set. Please call Set-GraphBaseUri first or provide a full Uri" } return "$($script:graphConnection.BaseUri.TrimEnd('/'))/$($uri.TrimStart('/'))" } else { return $uri } } } #endregion Internal commands #region Module initialization $script:graphConnection = [PSCustomObject]@{ FactoryName = 'graph' AiLogger = $null BaseUri = 'https://graph.microsoft.com/v1.0' GraphScope = @('https://graph.microsoft.com/.default') } #endregion Module initialization # SIG # Begin signature block # MIIuMwYJKoZIhvcNAQcCoIIuJDCCLiACAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCjdgassV0BGuJf # Gkd3bsfkCkgTNGRnkl+xNzto8c+TEqCCE2AwggWQMIIDeKADAgECAhAFmxtXno4h # MuI5B72nd3VcMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0z # ODAxMTUxMjAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 # IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB # AL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/z # G6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZ # anMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7s # Wxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL # 2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfb # BHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3 # JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3c # AORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqx # YxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0 # viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aL # T8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1Ud # EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzf # Lmc/57qYrhwPTzANBgkqhkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNk # aA9Wz3eucPn9mkqZucl4XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjS # PMFDQK4dUPVS/JA7u5iZaWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK # 7VB6fWIhCoDIc2bRoAVgX+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eB # cg3AFDLvMFkuruBx8lbkapdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp # 5aPNoiBB19GcZNnqJqGLFNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msg # dDDS4Dk0EIUhFQEI6FUy3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vri # RbgjU2wGb2dVf0a1TD9uKFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ7 # 9ARj6e/CVABRoIoqyc54zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5 # nLGbsQAe79APT0JsyQq87kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3 # i0objwG2J5VT6LaJbVu8aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0H # EEcRrYc9B9F1vM/zZn4wggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0G # CSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 # IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTla # MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE # AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz # ODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C # 0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce # 2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0da # E6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6T # SXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoA # FdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7Oh # D26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM # 1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z # 8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05 # huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNY # mtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP # /2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0T # AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYD # VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG # A1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV # HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU # cnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATAN # BgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95Ry # sQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HL # IvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5Btf # Q/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnh # OE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIh # dXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV # 9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/j # wVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYH # Ki8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmC # XBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l # /aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZW # eE4wggcUMIIE/KADAgECAhAP9xCe9qf4ax3LBs7uih/sMA0GCSqGSIb3DQEBCwUA # MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE # AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz # ODQgMjAyMSBDQTEwHhcNMjMxMTA4MDAwMDAwWhcNMjYxMDAxMjM1OTU5WjCBnDET # MBEGCysGAQQBgjc8AgEDEwJDWjEdMBsGA1UEDwwUUHJpdmF0ZSBPcmdhbml6YXRp # b24xETAPBgNVBAUTCDA0OTIzNjkzMQswCQYDVQQGEwJDWjEOMAwGA1UEBxMFUHJh # aGExGjAYBgNVBAoTEUdyZXlDb3JiZWwgcy5yLm8uMRowGAYDVQQDExFHcmV5Q29y # YmVsIHMuci5vLjCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAJ8t/Qga # dJKtGC7EqH4pmIU73fInH+j1scmVnrJtXL8tGlKzWZ7qlWDWOJBR3owF9CVqL4IX # BGImH8Miowj6RKKqhEe9UtxiH5ipV6msnzAjTFkwqR9vjfEm9vrU1JuXWvAWAfYx # qYg92oyCEBDQxpURpZmqAVSBy9U/ScDwE4NykZGzb0oYSPtzStd8RJvtUkc4126w # YKMbVe/kdY1mDbKO9DLfpbSIj3vghrH6XeHwEb7/jAVYI7Vl+jUyyqfmYHD7FldQ # X2fZfwvoGSibY1uWvvP0/vm0yd6uDbDjCDOTQW8Lxl5wvlXEf5ewn2oaPSoa6ov3 # 1XmnxL5iT8c1LM06JFCwfHS9e0NSyNr86IiKaxQO9/MANrYciTicObtD3cBcSRDO # pEUfhc4TvA5DQZaakSduVJWPdMhxQs9iWeYMOzh5NDTB3xAx8eLBn7Uj++hjI3FQ # WGEPw4Ew6WoDsJShU0HemlDJGTPW9EZSWHGdNFr1BxXEPb4F7DbjJZn33QIDAQAB # o4ICAjCCAf4wHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHQYDVR0O # BBYEFP2yViJvcgO05qXIH6aJSXB/QcEhMD0GA1UdIAQ2MDQwMgYFZ4EMAQMwKTAn # BggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMA4GA1UdDwEB # /wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBP # hk1odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2Rl # U2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2Ny # bDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0 # MDk2U0hBMzg0MjAyMUNBMS5jcmwwgZQGCCsGAQUFBwEBBIGHMIGEMCQGCCsGAQUF # BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXAYIKwYBBQUHMAKGUGh0dHA6 # Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWdu # aW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0MAkGA1UdEwQCMAAwDQYJKoZIhvcN # AQELBQADggIBADCe9Fh40HN9RneCehz5MrBy4O9WYsYCMJ7qJ9DsBT+Hed98UOKB # k/XjgSLfsj5eZRHRmz3HzhGDK1PaRI+yIUVQx96a4qL7adktmrHex3fW39Iq+tPB # rHtiEIp9rwunATeZpk+876u0AXYD1VDRWCtkL8zwZU0oqL6U/mWEIXzkryCB5N3x # xtE54jMmW7MKi1+To4yQcrK3zQ394e2dr50L+aF2fgJ5mo1/YJvzyLLhigbqpoYG # U/gjZonhNJXUaYogpHSTgUaBRlIKZ5xCnrFfJlOsbkhex4QAcdkU6XC+XyYfEQka # 7ERwgxmEoRT3NlZ8/EbrQxJP4S1H8Z29M4D3L6rXNXXmv0IbfA9FQcqEco3Y3tRW # dgdcFEwJmYTo0mCZrYTJHgkKW8xDvQ5BJISAp/ydOX5tSa71ojx1/Kp7qizqjBN/ # W77jdqJ89N1y+N/SOiHOCH9NO5pDLsHpTWW/arvjZT0I8dVYkqK0V39rh95XELI+ # NwBZvV4AsKLirjrkZU3pwCz6O99VmPkBqp9TA5wl13NdTpDHuQ6QyVT7hbC8LF5p # z6x/xO/+tEGxG+1A31UTJPmkxhhUlR+NE3ZXiXhcG72CFHYUUvqwlThPkFYe4Ygf # j9ADmss08k0JhVU5rkbrC2h+549HPlFu/XOSIrps4SXzInjHPEYuBETzMYIaKTCC # GiUCAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4x # QTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQw # OTYgU0hBMzg0IDIwMjEgQ0ExAhAP9xCe9qf4ax3LBs7uih/sMA0GCWCGSAFlAwQC # AQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwG # CisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZI # hvcNAQkEMSIEIBVdfrIeA0FlhoPtjsWCaYmTd6AG8/9Bs0ZS9ij3f7ZsMA0GCSqG # SIb3DQEBAQUABIIBgFi5+gfAfUN3QHToHCJlHippg0Vxm3t/kZqzE4WNPoIhFXhE # 5L3AvD65I1fYW+8fCJO9MObYATdj7ID/x/AMKTYDhkRhg2cCax0W9qFQhJDt6Zk3 # /aNNNXeuUmea7Lx5pRtYfxI8FUSW4efHxcg22K+Es4Hl1LEtGYvt9tIR45XmS5dn # OnY9lXZLG5uNSvrV2NRcoJaotk+K9tX/YRHV5O7YDAlohsQ1KatB8k1PY4U2xrw6 # 2WnRncZ6sqgbEwmPrJmbDi1T5jgqQTE6qaOu5CPDBdtb47+fCTWisrYCe4f5eKC9 # e4ljAyOKOYWEEgFxuh8/m6JOCYKdFaAi36d1OZ4BN7qonLbCug/kUgudJCGZkIfH # QW6JlYiYK599MTjWpt5LDTpnXHhCf29QB7U4xC4uVfS1NYEZwIkJW2/p8g3eCs2d # FHeJN9ZOfex7uUvsGNcRAjq2WoFH+TKG1wA82SSkb+nKyP4TtPqMPcx/bQNIAuN5 # 4PzOskQAx4CxhiJqeaGCF3YwghdyBgorBgEEAYI3AwMBMYIXYjCCF14GCSqGSIb3 # DQEHAqCCF08wghdLAgEDMQ8wDQYJYIZIAWUDBAIBBQAwdwYLKoZIhvcNAQkQAQSg # aARmMGQCAQEGCWCGSAGG/WwHATAxMA0GCWCGSAFlAwQCAQUABCD9P44AVc1YIjAv # CmQISABBRJtHrVDdbIgH0Hq5wxMJCwIQenBeL4HlUfP0nH4x48lMqRgPMjAyNjA0 # MDIxNzUxMzFaoIITOjCCBu0wggTVoAMCAQICEAqA7xhLjfEFgtHEdqeVdGgwDQYJ # KoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IFRpbWVTdGFtcGluZyBS # U0E0MDk2IFNIQTI1NiAyMDI1IENBMTAeFw0yNTA2MDQwMDAwMDBaFw0zNjA5MDMy # MzU5NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7 # MDkGA1UEAxMyRGlnaUNlcnQgU0hBMjU2IFJTQTQwOTYgVGltZXN0YW1wIFJlc3Bv # bmRlciAyMDI1IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDQRqwt # Esae0OquYFazK1e6b1H/hnAKAd/KN8wZQjBjMqiZ3xTWcfsLwOvRxUwXcGx8AUjn # i6bz52fGTfr6PHRNv6T7zsf1Y/E3IU8kgNkeECqVQ+3bzWYesFtkepErvUSbf+EI # YLkrLKd6qJnuzK8Vcn0DvbDMemQFoxQ2Dsw4vEjoT1FpS54dNApZfKY61HAldytx # NM89PZXUP/5wWWURK+IfxiOg8W9lKMqzdIo7VA1R0V3Zp3DjjANwqAf4lEkTlCDQ # 0/fKJLKLkzGBTpx6EYevvOi7XOc4zyh1uSqgr6UnbksIcFJqLbkIXIPbcNmA98Os # kkkrvt6lPAw/p4oDSRZreiwB7x9ykrjS6GS3NR39iTTFS+ENTqW8m6THuOmHHjQN # C3zbJ6nJ6SXiLSvw4Smz8U07hqF+8CTXaETkVWz0dVVZw7knh1WZXOLHgDvundrA # tuvz0D3T+dYaNcwafsVCGZKUhQPL1naFKBy1p6llN3QgshRta6Eq4B40h5avMcpi # 54wm0i2ePZD5pPIssoszQyF4//3DoK2O65Uck5Wggn8O2klETsJ7u8xEehGifgJY # i+6I03UuT1j7FnrqVrOzaQoVJOeeStPeldYRNMmSF3voIgMFtNGh86w3ISHNm0Ia # adCKCkUe2LnwJKa8TIlwCUNVwppwn4D3/Pt5pwIDAQABo4IBlTCCAZEwDAYDVR0T # AQH/BAIwADAdBgNVHQ4EFgQU5Dv88jHt/f3X85FxYxlQQ89hjOgwHwYDVR0jBBgw # FoAU729TSunkBnx6yuKQVvYv1Ensy04wDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB # /wQMMAoGCCsGAQUFBwMIMIGVBggrBgEFBQcBAQSBiDCBhTAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMF0GCCsGAQUFBzAChlFodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBpbmdS # U0E0MDk2U0hBMjU2MjAyNUNBMS5jcnQwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDov # L2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0VGltZVN0YW1waW5n # UlNBNDA5NlNIQTI1NjIwMjVDQTEuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsG # CWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEAZSqt8RwnBLmuYEHs0QhEnmNA # ciH45PYiT9s1i6UKtW+FERp8FgXRGQ/YAavXzWjZhY+hIfP2JkQ38U+wtJPBVBaj # YfrbIYG+Dui4I4PCvHpQuPqFgqp1PzC/ZRX4pvP/ciZmUnthfAEP1HShTrY+2DE5 # qjzvZs7JIIgt0GCFD9ktx0LxxtRQ7vllKluHWiKk6FxRPyUPxAAYH2Vy1lNM4kze # kd8oEARzFAWgeW3az2xejEWLNN4eKGxDJ8WDl/FQUSntbjZ80FU3i54tpx5F/0Kr # 15zW/mJAxZMVBrTE2oi0fcI8VMbtoRAmaaslNXdCG1+lqvP4FbrQ6IwSBXkZagHL # hFU9HCrG/syTRLLhAezu/3Lr00GrJzPQFnCEH1Y58678IgmfORBPC1JKkYaEt2Od # Dh4GmO0/5cHelAK2/gTlQJINqDr6JfwyYHXSd+V08X1JUPvB4ILfJdmL+66Gp3CS # BXG6IwXMZUXBhtCyIaehr0XkBoDIGMUG1dUtwq1qmcwbdUfcSYCn+OwncVUXf53V # JUNOaMWMts0VlRYxe5nK+At+DI96HAlXHAL5SlfYxJ7La54i71McVWRP66bW+yER # NpbJCjyCYG2j+bdpxo/1Cy4uPcU3AWVPGrbn5PhDBf3Froguzzhk++ami+r3Qrx5 # bIbY3TVzgiFI7Gq3zWcwgga0MIIEnKADAgECAhANx6xXBf8hmS5AQyIMOkmGMA0G # CSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 # IFRydXN0ZWQgUm9vdCBHNDAeFw0yNTA1MDcwMDAwMDBaFw0zODAxMTQyMzU5NTla # MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE # AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEy # NTYgMjAyNSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0eDHT # CphBcr48RsAcrHXbo0ZodLRRF51NrY0NlLWZloMsVO1DahGPNRcybEKq+RuwOnPh # of6pvF4uGjwjqNjfEvUi6wuim5bap+0lgloM2zX4kftn5B1IpYzTqpyFQ/4Bt0mA # xAHeHYNnQxqXmRinvuNgxVBdJkf77S2uPoCj7GH8BLuxBG5AvftBdsOECS1UkxBv # MgEdgkFiDNYiOTx4OtiFcMSkqTtF2hfQz3zQSku2Ws3IfDReb6e3mmdglTcaarps # 0wjUjsZvkgFkriK9tUKJm/s80FiocSk1VYLZlDwFt+cVFBURJg6zMUjZa/zbCclF # 83bRVFLeGkuAhHiGPMvSGmhgaTzVyhYn4p0+8y9oHRaQT/aofEnS5xLrfxnGpTXi # UOeSLsJygoLPp66bkDX1ZlAeSpQl92QOMeRxykvq6gbylsXQskBBBnGy3tW/AMOM # CZIVNSaz7BX8VtYGqLt9MmeOreGPRdtBx3yGOP+rx3rKWDEJlIqLXvJWnY0v5ydP # pOjL6s36czwzsucuoKs7Yk/ehb//Wx+5kMqIMRvUBDx6z1ev+7psNOdgJMoiwOrU # G2ZdSoQbU2rMkpLiQ6bGRinZbI4OLu9BMIFm1UUl9VnePs6BaaeEWvjJSjNm2qA+ # sdFUeEY0qVjPKOWug/G6X5uAiynM7Bu2ayBjUwIDAQABo4IBXTCCAVkwEgYDVR0T # AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU729TSunkBnx6yuKQVvYv1Ensy04wHwYD # VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG # A1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV # HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU # cnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1s # BwEwDQYJKoZIhvcNAQELBQADggIBABfO+xaAHP4HPRF2cTC9vgvItTSmf83Qh8WI # GjB/T8ObXAZz8OjuhUxjaaFdleMM0lBryPTQM2qEJPe36zwbSI/mS83afsl3YTj+ # IQhQE7jU/kXjjytJgnn0hvrV6hqWGd3rLAUt6vJy9lMDPjTLxLgXf9r5nWMQwr8M # yb9rEVKChHyfpzee5kH0F8HABBgr0UdqirZ7bowe9Vj2AIMD8liyrukZ2iA/wdG2 # th9y1IsA0QF8dTXqvcnTmpfeQh35k5zOCPmSNq1UH410ANVko43+Cdmu4y81hjaj # V/gxdEkMx1NKU4uHQcKfZxAvBAKqMVuqte69M9J6A47OvgRaPs+2ykgcGV00TYr2 # Lr3ty9qIijanrUR3anzEwlvzZiiyfTPjLbnFRsjsYg39OlV8cipDoq7+qNNjqFze # GxcytL5TTLL4ZaoBdqbhOhZ3ZRDUphPvSRmMThi0vw9vODRzW6AxnJll38F0cuJG # 7uEBYTptMSbhdhGQDpOXgpIUsWTjd6xpR6oaQf/DJbg3s6KCLPAlZ66RzIg9sC+N # Jpud/v4+7RWsWCiKi9EOLLHfMR2ZyJ/+xhCx9yHbxtl5TPau1j/1MIDpMPx0LckT # etiSuEtQvLsNz3Qbp7wGWqbIiOWCnb5WqxL3/BAPvIXKUjPSxyZsq8WhbaM2tszW # kPZPubdcMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMYIDfDCCA3gC # AQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/ # BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYg # U0hBMjU2IDIwMjUgQ0ExAhAKgO8YS43xBYLRxHanlXRoMA0GCWCGSAFlAwQCAQUA # oIHRMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcN # MjYwNDAyMTc1MTMxWjArBgsqhkiG9w0BCRACDDEcMBowGDAWBBTdYjCshgotMGva # OLFoeVIwB/tBfjAvBgkqhkiG9w0BCQQxIgQgozFxwYgwQyCZ6/mGbF+0/xBu2kX4 # nF3dOwGmVUFgT5gwNwYLKoZIhvcNAQkQAi8xKDAmMCQwIgQgSqA/oizXXITFXJOP # go5na5yuyrM/420mmqM08UYRCjMwDQYJKoZIhvcNAQEBBQAEggIAem2KmV962Sq4 # oEaV1rFblOer5pH47Jnv84G3arxLDi843ehpM6FYIssiy1XS94S8PkwTmyTpUvQl # Fch7zlZWVKE58pQvMdSm1+UHoaq93ljgjjGcCkt10djkhEyq1raKjfuHWYo87zS5 # +b8ppqLKiXLQrbmSdVLOEPww6y95PQzX3RmaHL9aeZJHTVgTHRcD5AZQ8NuG92K1 # 3XUXOZgwxfcMk7qgJ5h/BkyaAyAiuBqZjLPXMDZqCu4/wBjUbgfh/rbdJKO9bRsx # b/JKMbV+qeuN/Rt6XyAM7Phz/9XXv0aGdTdsfHiEUnbxByfD9qi7VI8RTtXGI9TD # BDtEIW4MG4gHQo1lyAH6itHu98vLen8S2pBsEenGvmmvfQOYafRMIDDf51JQaTjq # 7U2t1TlkpXvMC1MBDONwMtulDEekjg05Jd6+h+PZ4RKp1AjW6d9MQh5Zsozeq/RR # r7fO0zekkdCgmc1icDjb36yMpJA5c0RrXcBQy3Sr7z1WHqhjFTUSw7IKxomEDomt # Z5yik10X9+a97MmLAQAMd5pQoRUHTjlYqNrpPf2wk21iRSapjVBKtSpdTJbbCLME # LjkKGBcEn5/qWAkY47GvNfnZq4egXU+IvqXPartjtPNZBksFRroCHQuV3f1GLH/T # OmkQeeOT5TxzxS1Do53tTgZkvGmWpVY= # SIG # End signature block |