PowerTribeloo.psm1
function Join-UriQuery { <# .SYNOPSIS Provides ability to join two Url paths together including advanced querying .DESCRIPTION Provides ability to join two Url paths together including advanced querying which is useful for RestAPI/GraphApi calls .PARAMETER BaseUri Primary Url to merge .PARAMETER RelativeOrAbsoluteUri Additional path to merge with primary url (optional) .PARAMETER QueryParameter Parameters and their values in form of hashtable .EXAMPLE Join-UriQuery -BaseUri 'https://evotec.xyz/' -RelativeOrAbsoluteUri '/wp-json/wp/v2/posts' -QueryParameter @{ page = 1 per_page = 20 search = 'SearchString' } .EXAMPLE Join-UriQuery -BaseUri 'https://evotec.xyz/wp-json/wp/v2/posts' -QueryParameter @{ page = 1 per_page = 20 search = 'SearchString' } .EXAMPLE Join-UriQuery -BaseUri 'https://evotec.xyz' -RelativeOrAbsoluteUri '/wp-json/wp/v2/posts' .NOTES General notes #> [alias('Join-UrlQuery')] [CmdletBinding()] param ([parameter(Mandatory)][uri] $BaseUri, [parameter(Mandatory = $false)][uri] $RelativeOrAbsoluteUri, [Parameter()][System.Collections.IDictionary] $QueryParameter) if ($BaseUri -and $RelativeOrAbsoluteUri) { $Url = Join-Uri -BaseUri $BaseUri -RelativeOrAbsoluteUri $RelativeOrAbsoluteUri } else { $Url = $BaseUri } if ($QueryParameter) { $Collection = [System.Web.HttpUtility]::ParseQueryString([String]::Empty) foreach ($key in $QueryParameter.Keys) { $Collection.Add($key, $QueryParameter.$key) } } $uriRequest = [System.UriBuilder] $Url if ($Collection) { $uriRequest.Query = $Collection.ToString() } return $uriRequest.Uri.AbsoluteUri } function Remove-EmptyValue { [alias('Remove-EmptyValues')] [CmdletBinding()] param([alias('Splat', 'IDictionary')][Parameter(Mandatory)][System.Collections.IDictionary] $Hashtable, [string[]] $ExcludeParameter, [switch] $Recursive, [int] $Rerun, [switch] $DoNotRemoveNull, [switch] $DoNotRemoveEmpty, [switch] $DoNotRemoveEmptyArray, [switch] $DoNotRemoveEmptyDictionary) foreach ($Key in [string[]] $Hashtable.Keys) { if ($Key -notin $ExcludeParameter) { if ($Recursive) { if ($Hashtable[$Key] -is [System.Collections.IDictionary]) { if ($Hashtable[$Key].Count -eq 0) { if (-not $DoNotRemoveEmptyDictionary) { $Hashtable.Remove($Key) } } else { Remove-EmptyValue -Hashtable $Hashtable[$Key] -Recursive:$Recursive } } else { if (-not $DoNotRemoveNull -and $null -eq $Hashtable[$Key]) { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmpty -and $Hashtable[$Key] -is [string] -and $Hashtable[$Key] -eq '') { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmptyArray -and $Hashtable[$Key] -is [System.Collections.IList] -and $Hashtable[$Key].Count -eq 0) { $Hashtable.Remove($Key) } } } else { if (-not $DoNotRemoveNull -and $null -eq $Hashtable[$Key]) { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmpty -and $Hashtable[$Key] -is [string] -and $Hashtable[$Key] -eq '') { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmptyArray -and $Hashtable[$Key] -is [System.Collections.IList] -and $Hashtable[$Key].Count -eq 0) { $Hashtable.Remove($Key) } } } } if ($Rerun) { for ($i = 0; $i -lt $Rerun; $i++) { Remove-EmptyValue -Hashtable $Hashtable -Recursive:$Recursive } } } function Join-Uri { <# .SYNOPSIS Provides ability to join two Url paths together .DESCRIPTION Provides ability to join two Url paths together .PARAMETER BaseUri Primary Url to merge .PARAMETER RelativeOrAbsoluteUri Additional path to merge with primary url .EXAMPLE Join-Uri 'https://evotec.xyz/' '/wp-json/wp/v2/posts' .EXAMPLE Join-Uri 'https://evotec.xyz/' 'wp-json/wp/v2/posts' .EXAMPLE Join-Uri -BaseUri 'https://evotec.xyz/' -RelativeOrAbsoluteUri '/wp-json/wp/v2/posts' .EXAMPLE Join-Uri -BaseUri 'https://evotec.xyz/test/' -RelativeOrAbsoluteUri '/wp-json/wp/v2/posts' .NOTES General notes #> [alias('Join-Url')] [cmdletBinding()] param([parameter(Mandatory)][uri] $BaseUri, [parameter(Mandatory)][uri] $RelativeOrAbsoluteUri) return ($BaseUri.OriginalString.TrimEnd('/') + "/" + $RelativeOrAbsoluteUri.OriginalString.TrimStart('/')) } function Convert-TribelooUser { [cmdletBinding()] param( [Array] $Users ) foreach ($User in $Users) { $WorkEmail = $null $Emails = $User.'emails' foreach ($Email in $Emails) { if ($Email.Type -eq 'work') { $WorkEmail = $Email.Value } } [PSCustomObject] @{ Id = $User.'id' UserName = $User.'userName' GivenName = $User.'name'.'givenName' FamilyName = $User.'name'.'familyName' DisplayName = $User.'displayName' NickName = $User.'nickName' EmailAddress = $WorkEmail Active = $User.'active' Formatted = $User.'addresses'[0].'formatted' Created = $User.Meta.Created LastModified = $User.Meta.Updated Location = $User.Meta.location } } } function Connect-Tribeloo { [CmdletBinding()] param( [Parameter(Mandatory)][string] $Token, [Parameter(Mandatory)][alias('Url', 'BaseUri')][string] $Uri, [switch] $Suppress ) $Script:AuthorizationTribeloo = @{ 'Authorization' = "Bearer $Token" 'Content-Type' = 'application/json; charset=utf-8' 'BaseUri' = $Uri } if (-not $Suppress) { return $Script:AuthorizationTribeloo } } function Get-TribelooUser { [CmdletBinding()] param( [string] $Id, [Alias('UserName')][string] $SearchUserName, [Alias('ExternalID')][string] $SearchExternalID, [string] $Search, [ValidateSet( 'id', 'userName', 'givenName', 'familyName', 'displayName', 'nickName', 'emails', 'addresses', 'meta' )] [string] $SearchProperty = 'userName', [string] $SearchOperator = 'eq', [int] $MaxResults, #[int] $StartIndex = 1, #[int] $Count = 1000, [string] $Filter, [ValidateSet( 'id', 'userName', 'givenName', 'familyName', 'displayName', 'nickName', 'emails', 'addresses', 'meta' )] [string] $SortBy, [ValidateSet('ascending', 'descending')][string] $SortOrder, [switch] $Native ) if (-not $Script:AuthorizationTribeloo) { return } $ConvertAttributes = @{ 'id' = 'id' 'userName' = 'userName' 'givenName' = 'name.givenName' 'familyName' = 'name.familyName' 'displayName' = 'di%splayName' 'nickName' = 'nickName' 'emails' = 'emails' 'active' = 'active' 'meta' = 'meta' } if ($SortBy) { $SortByConverted = $ConvertAttributes[$SortBy] } $QueryParameter = @{ #count = if ($Count) { $Count } else { $null } #startIndex = if ($StartIndex) { $StartIndex } else { $null } filter = if ($SearchUserName) { "userName eq `"$SearchUserName`"" } elseif ($SearchExternalID) { "externalId eq `"$SearchExternalID`"" } elseif ($Search -and $SearchProperty) { "$($ConvertAttributes[$SearchProperty]) $SearchOperator `"$Search`"" } else { $Filter } sortBy = $SortByConverted sortOrder = $SortOrder } Remove-EmptyValue -Hashtable $QueryParameter if ($ID) { $Uri = Join-UriQuery -BaseUri $Script:AuthorizationTribeloo.BaseUri -RelativeOrAbsoluteUri "Users/$ID" -QueryParameter $QueryParameter } else { $Uri = Join-UriQuery -BaseUri $Script:AuthorizationTribeloo.BaseUri -RelativeOrAbsoluteUri 'Users' -QueryParameter $QueryParameter } Write-Verbose -Message "Get-TribelooUser - Using query: $Uri" $invokeRestMethodSplat = @{ Method = 'Get' Uri = $Uri Headers = [ordered] @{ 'Content-Type' = 'application/json; charset=utf-8' 'Authorization' = $Script:AuthorizationTribeloo.Authorization 'Cache-Control' = 'no-cache' } ErrorAction = 'Stop' ContentType = 'application/json; charset=utf-8' } try { $BatchObjects = Invoke-RestMethod @invokeRestMethodSplat } catch { if ($PSBoundParameters.ErrorAction -eq 'Stop') { throw } else { $ErrorDetails = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue if ($ErrorDetails.Detail -like '*already exists*directory*') { Write-Warning -Message "Get-TribelooUser - $($ErrorDetails.Detail) [UserName: $UserName / ID: $ID]" return } else { Write-Warning -Message "Get-TribelooUser - Error $($_.Exception.Message), $($ErrorDetails.Detail)" return } } } if ($BatchObjects.Resources) { Write-Verbose -Message "Get-TribelooUser - Got $($BatchObjects.Resources.Count) users (StartIndex: $StartIndex, Count: $Count). Starting to process them." if ($MaxResults -gt 0 -and $BatchObjects.Resources.Count -ge $MaxResults) { # return users if amount of users available is more than we wanted if ($Native) { $BatchObjects.Resources | Select-Object -First $MaxResults } else { Convert-TribelooUser -Users ($BatchObjects.Resources | Select-Object -First $MaxResults) } # $LimitReached = $true } else { # return all users that were given in a batch if ($Native) { $BatchObjects.Resources } else { Convert-TribelooUser -Users $BatchObjects.Resources } } } elseif ($BatchObjects.Schemas -and $BatchObjects.id) { if ($Native) { $BatchObjects } else { Convert-TribelooUser -Users $BatchObjects } } else { Write-Verbose "Get-TribelooUser - No users found" return } # if (-not $Count -and -not $StartIndex) { # # paging is disabled, we don't do anything # } elseif (-not $LimitReached -and $BatchObjects.TotalResults -gt $BatchObjects.StartIndex + $Count) { # # lets get more users because there's more to get and user wanted more # $MaxResults = $MaxResults - $BatchObjects.Resources.Count # Write-Verbose "Get-TribelooUser - Processing more pages (StartIndex: $StartIndex, Count: $Count)." # $getFederatedDirectoryUserSplat = @{ # Authorization = $Authorization # StartIndex = $($BatchObjects.StartIndex + $Count) # Count = $Count # MaxResults = $MaxResults # Filter = $Filter # SortBy = $SortBy # SortOrder = $SortOrder # Native = $Native # } # Remove-EmptyValue -Hashtable $getFederatedDirectoryUserSplat # Get-TribelooUser @getFederatedDirectoryUserSplat # } } function New-TribelooUser { [CmdletBinding(SupportsShouldProcess)] param( [parameter(Mandatory)][string] $UserName, [string] $FamilyName, [string] $GivenName, [parameter(Mandatory)][string] $DisplayName, [string] $NickName, [string] $EmailAddress, [string] $Formatted, [switch] $Active ) if (-not $Script:AuthorizationTribeloo) { return } $Body = [ordered] @{ schemas = @( "urn:ietf:params:scim:schemas:core:2.0:User" ) "userName" = $UserName "name" = [ordered] @{ "familyName" = $FamilyName "givenName" = $GivenName } "displayName" = $DisplayName "nickName" = $NickName "emails" = @( if ($EmailAddress) { @{ "value" = $EmailAddress "type" = "work" "primary" = $true } } ) "addresses" = @( if ($Formatted) { [ordered]@{ "formatted" = $Formatted "type" = "work" } } ) "active" = if ($PSBoundParameters.Keys -contains ('Active')) { $Active.IsPresent } else { $Null } } Try { Remove-EmptyValue -Hashtable $Body -Recursive -Rerun 2 # for troubleshooting if ($VerbosePreference -eq 'Continue') { $Body | ConvertTo-Json -Depth 10 | Write-Verbose } if ($BulkProcessing) { # Return body is used for using Invoke-FederatedDirectory to add/set/remove users in bulk $ReturnObject = [ordered] @{ data = $Body method = 'POST' bulkId = $Body.userName } # for troubleshooting if ($VerbosePreference -eq 'Continue') { $ReturnObject | ConvertTo-Json -Depth 10 | Write-Verbose } return $ReturnObject } $Uri = Join-UriQuery -BaseUri $Script:AuthorizationTribeloo.BaseUri -RelativeOrAbsoluteUri 'Users' $invokeRestMethodSplat = [ordered] @{ Method = 'POST' Uri = $Uri Headers = [ordered] @{ 'Content-Type' = 'application/json; charset=utf-8' 'Authorization' = $Script:AuthorizationTribeloo.Authorization 'Cache-Control' = 'no-cache' } Body = $Body | ConvertTo-Json -Depth 10 ErrorAction = 'Stop' ContentType = 'application/json; charset=utf-8' } if ($DirectoryID) { $invokeRestMethodSplat['Headers']['directoryId'] = $DirectoryID } Write-Verbose -Message "Get-TribelooUser - Using query: $Uri" if ($PSCmdlet.ShouldProcess("username $UserName, displayname $DisplayName", "Adding user")) { $ReturnData = Invoke-RestMethod @invokeRestMethodSplat -Verbose:$false # don't return data as we trust it's been created if (-not $Suppress) { $ReturnData } } # # for troubleshooting # if ($VerbosePreference -eq 'Continue') { # $invokeRestMethodSplat.Remove('body') # $invokeRestMethodSplat | ConvertTo-Json -Depth 10 | Write-Verbose # } } catch { if ($PSBoundParameters.ErrorAction -eq 'Stop') { throw } else { $ErrorDetails = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue if ($ErrorDetails.Detail -like '*already exists*directory*') { Write-Warning -Message "Add-TribelooUser - $($ErrorDetails.Detail) [UserName: $UserName / DisplayName: $DisplayName]" } else { Write-Warning -Message "Add-TribelooUser - Error $($_.Exception.Message), $($ErrorDetails.Detail)" } } } } function Remove-TribelooUser { [CmdletBinding(SupportsShouldProcess)] param( [parameter(Position = 0, ValueFromPipeline, Mandatory, ParameterSetName = 'User')][PSCustomObject[]] $User, [parameter(Mandatory, ParameterSetName = 'Id')][string[]] $Id, [parameter(Mandatory, ParameterSetName = 'UserName')][string[]] $SearchUserName, [switch] $Suppress, [parameter(ParameterSetName = 'All')][switch] $All ) Begin { if (-not $Script:AuthorizationTribeloo) { if ($PSBoundParameters.ErrorAction -eq 'Stop') { throw "No authorization found. Please run 'Connect-Tribeloo' first." } else { Write-Warning -Message "Remove-TribelooUser - No authorization found. Please run 'Connect-Tribeloo' first." return } return } } Process { if ($All) { # lets simplify this for all $Users = Get-TribelooUser foreach ($U in $Users) { Remove-TribelooUser -Id $U.id } } else { if ($Id) { $RemoveID = $Id } elseif ($User) { $RemoveID = $User.Id } elseif ($SearchUserName) { $RemoveID = Foreach ($U in $SearchUserName) { (Get-TribelooUser -UserName $U).Id } } else { return } foreach ($I in $RemoveID) { Try { if ($BulkProcessing) { # Return body is used for using Invoke-FederatedDirectory to add/set/remove users in bulk return [ordered] @{ data = @{ schemas = @("urn:ietf:params:scim:schemas:core:2.0:User") id = $I } method = 'DELETE' bulkId = $I } } $Uri = Join-UriQuery -BaseUri $Script:AuthorizationTribeloo.BaseUri -RelativeOrAbsoluteUri "Users/$I" $invokeRestMethodSplat = [ordered] @{ Method = 'DELETE' Uri = $Uri Headers = [ordered] @{ 'Content-Type' = 'application/json; charset=utf-8' 'Authorization' = $Script:AuthorizationTribeloo.Authorization 'Cache-Control' = 'no-cache' } ErrorAction = 'Stop' ContentType = 'application/json; charset=utf-8' } Remove-EmptyValue -Hashtable $invokeRestMethodSplat -Recursive if ($VerbosePreference -eq 'Continue') { $invokeRestMethodSplat | ConvertTo-Json -Depth 10 | Write-Verbose } if ($PSCmdlet.ShouldProcess($I, "Removing user")) { $ReturnData = Invoke-RestMethod @invokeRestMethodSplat if (-not $Suppress) { $ReturnData } } } catch { $ErrorDetails = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue if ($ErrorDetails.Detail -like "*not found*") { Write-Warning -Message "Remove-TribelooUser - $($ErrorDetails.Detail)." } else { Write-Warning -Message "Remove-TribelooUser - Error $($_.Exception.Message), $($ErrorDetails.Detail)" } } } } } } function Set-TribelooUser { [CmdletBinding(SupportsShouldProcess)] param( [string] $SearchUserName, [string] $Id, [string] $UserName, [string] $FamilyName, [string] $GivenName, [string] $DisplayName, [string] $NickName, [string] $EmailAddress, [string] $Formatted, [bool] $Active, [switch] $Suppress, [ValidateSet('Overwrite', 'Update')][string] $Action = 'Update', [System.Collections.IDictionary] $ActionPerProperty = @{}, [switch] $BulkProcessing ) if (-not $Script:AuthorizationTribeloo) { if ($PSBoundParameters.ErrorAction -eq 'Stop') { throw "No authorization found. Please run 'Connect-Tribeloo' first." } else { Write-Warning -Message "Remove-TribelooUser - No authorization found. Please run 'Connect-Tribeloo' first." return } return } if ($Id) { $SetID = $Id } elseif ($User) { $SetID = $User.Id } elseif ($SearchUserName) { $SetID = Foreach ($U in $SearchUserName) { (Get-TribelooUser -UserName $U).Id } } else { Write-Warning -Message "Set-TribelooUser - No ID or UserName specified." return } if ($ManagerUserName) { $ManagerID = (Get-TribelooUser -UserName $ManagerUserName).Id } if ($Action -eq 'Update') { $TranslatePath = @{ UserName = "userName" FamilyName = "name.familyName" GivenName = 'name.givenName' DisplayName = 'displayName' NickName = 'nickName' EmailAddress = 'emails[type eq "work"].value' Active = 'active' Formatted = 'addresses[type eq "work"].formatted' } $Body = [ordered] @{ schemas = @( "urn:ietf:params:scim:api:messages:2.0:PatchOp" ) Operations = @( foreach ($Key in $PSBoundParameters.Keys) { if ($Key -in $TranslatePath.Keys) { if ($TranslatePath[$Key]) { $Path = $TranslatePath[$Key] } else { $Path = $Key } if ($null -ne $PSBoundParameters[$Key]) { $Value = $PSBoundParameters[$Key] } else { $Value = $null } if ($ActionPerProperty) { if ($ActionPerProperty[$Key]) { $ActionProperty = $ActionPerProperty[$Key] } else { $ActionProperty = 'replace' } } else { $ActionProperty = 'replace' } if ($null -ne $Value) { [ordered] @{ op = $ActionProperty path = $Path value = $Value } } } } ) } } else { $Body = [ordered] @{ schemas = @( "urn:ietf:params:scim:schemas:core:2.0:User" "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User" "urn:ietf:params:scim:schemas:extension:fd:2.0:User" ) "id" = $Id "userName" = $UserName "name" = [ordered] @{ "familyName" = $FamilyName "givenName" = $GivenName } "displayName" = $DisplayName "nickName" = $NickName "emails" = @( if ($EmailAddress) { [ordered]@{ "value" = $EmailAddress "type" = "work" "primary" = $true } } ) "addresses" = @( if ($Formatted) { [ordered]@{ "formatted" = $Formatted "type" = "work" } } ) "active" = if ($PSBoundParameters.Keys -contains ('Active')) { $Active } else { $Null } } } Try { Remove-EmptyValue -Hashtable $Body -Recursive -Rerun 3 $MethodChosen = if ($Action -eq 'Update') { 'PATCH' } else { 'PUT' } if ($BulkProcessing) { # Return body is used for using Invoke-FederatedDirectory to add/set/remove users in bulk if ($Action -eq 'Update') { Write-Warning -Message "Bulk processing is not supported for Update action. Only Overwrite action is supported. Change action to Overwrite or don't use bulk processing for updates." } else { return [ordered] @{ data = $Body method = $MethodChosen bulkId = $SetID } } } $Uri = Join-UriQuery -BaseUri $Script:AuthorizationTribeloo.BaseUri -RelativeOrAbsoluteUri "Users/$SetID" $invokeRestMethodSplat = [ordered] @{ Method = $MethodChosen Uri = $Uri Headers = [ordered] @{ 'Content-Type' = 'application/json' 'Authorization' = $Script:AuthorizationTribeloo.Authorization 'Cache-Control' = 'no-cache' } Body = $Body | ConvertTo-Json -Depth 10 ErrorAction = 'Stop' ContentType = 'application/json; charset=utf-8' } if ($DirectoryID) { $invokeRestMethodSplat['Headers']['directoryId'] = $DirectoryID } # for troubleshooting if ($VerbosePreference -eq 'Continue') { $Body | ConvertTo-Json -Depth 10 | Write-Verbose } if ($PSCmdlet.ShouldProcess($SetID, "Updating user using $Action method")) { $ReturnData = Invoke-RestMethod @invokeRestMethodSplat # don't return data as we trust it's been updated if (-not $Suppress) { $ReturnData } } # # for troubleshooting # if ($VerbosePreference -eq 'Continue') { # $invokeRestMethodSplat.Remove('body') # $invokeRestMethodSplat | ConvertTo-Json -Depth 10 | Write-Verbose # } } catch { if ($PSBoundParameters.ErrorAction -eq 'Stop') { throw } else { $ErrorDetails = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue if ($ErrorDetails.Detail -like '*userName is mandatory*') { Write-Warning -Message "Set-TribelooUser - $($ErrorDetails.Detail) [Id: $SetID]" } else { Write-Warning -Message "Set-TribelooUser - Error $($_.Exception.Message), $($ErrorDetails.Detail) [Id: $SetID]" } } } } # Export functions and aliases as required Export-ModuleMember -Function @('Connect-Tribeloo', 'Get-TribelooUser', 'New-TribelooUser', 'Remove-TribelooUser', 'Set-TribelooUser') -Alias @() # SIG # Begin signature block # MIInPgYJKoZIhvcNAQcCoIInLzCCJysCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCry1RACxvBhKO4 # 80JsMKBl0dxvEQpGFQnV7wLyKY58DqCCITcwggO3MIICn6ADAgECAhAM5+DlF9hG # /o/lYPwb8DA5MA0GCSqGSIb3DQEBBQUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV # BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBa # Fw0zMTExMTAwMDAwMDBaMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lD # ZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC # AQoCggEBAK0OFc7kQ4BcsYfzt2D5cRKlrtwmlIiq9M71IDkoWGAM+IDaqRWVMmE8 # tbEohIqK3J8KDIMXeo+QrIrneVNcMYQq9g+YMjZ2zN7dPKii72r7IfJSYd+fINcf # 4rHZ/hhk0hJbX/lYGDW8R82hNvlrf9SwOD7BG8OMM9nYLxj+KA+zp4PWw25EwGE1 # lhb+WZyLdm3X8aJLDSv/C3LanmDQjpA1xnhVhyChz+VtCshJfDGYM2wi6YfQMlqi # uhOCEe05F52ZOnKh5vqk2dUXMXWuhX0irj8BRob2KHnIsdrkVxfEfhwOsLSSplaz # vbKX7aqn8LfFqD+VFtD/oZbrCF8Yd08CAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGG # MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEXroq/0ksuCMS1Ri6enIZ3zbcgP # MB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBBQUA # A4IBAQCiDrzf4u3w43JzemSUv/dyZtgy5EJ1Yq6H6/LV2d5Ws5/MzhQouQ2XYFwS # TFjk0z2DSUVYlzVpGqhH6lbGeasS2GeBhN9/CTyU5rgmLCC9PbMoifdf/yLil4Qf # 6WXvh+DfwWdJs13rsgkq6ybteL59PyvztyY1bV+JAbZJW58BBZurPSXBzLZ/wvFv # hsb6ZGjrgS2U60K3+owe3WLxvlBnt2y98/Efaww2BxZ/N3ypW2168RJGYIPXJwS+ # S86XvsNnKmgR34DnDDNmvxMNFG7zfx9jEB76jRslbWyPpbdhAbHSoyahEHGdreLD # +cOZUbcrBwjOLuZQsqf6CkUvovDyMIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1U0O1 # b5VQCDANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln # aUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtE # aWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcNMjgx # MDIyMTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBT # SEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEF # AAOCAQ8AMIIBCgKCAQEA+NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid2zLX # cep2nQUut4/6kkPApfmJ1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH03sjlOSR # I5aQd4L5oYQjZhJUM1B0sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxKhwjfDPXi # TWAYvqrEsq5wMWYzcT6scKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzLfnQ5 # Ng2Q7+S1TqSp6moKq4TzrGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR93O8 # vYWxYoNzQYIH5DiLanMg0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckwEgYD # VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYB # BQUHAwMweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5k # aWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4 # oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJv # b3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2Vy # dEFzc3VyZWRJRFJvb3RDQS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIEMCow # KAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZI # AYb9bAMwHQYDVR0OBBYEFFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQYMBaA # FEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1aJLPz # ItEVyCx8JSl2qB1dHC06GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbRknUPUbRu # pY5a4l4kgU4QpO4/cY5jDhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7uq+1UcKN # JK4kxscnKqEpKBo6cSgCPC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7qPjFEmif # z0DLQESlE/DmZAwlCEIysjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPas7CM1ekN # 3fYBIM6ZMWM9CBoYs4GbT8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhsRDKy # ZqHnGKSaZFHvMIIFPTCCBCWgAwIBAgIQBNXcH0jqydhSALrNmpsqpzANBgkqhkiG # 9w0BAQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkw # FwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEy # IEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTIwMDYyNjAwMDAwMFoXDTIz # MDcwNzEyMDAwMFowejELMAkGA1UEBhMCUEwxEjAQBgNVBAgMCcWabMSFc2tpZTER # MA8GA1UEBxMIS2F0b3dpY2UxITAfBgNVBAoMGFByemVteXPFgmF3IEvFgnlzIEVW # T1RFQzEhMB8GA1UEAwwYUHJ6ZW15c8WCYXcgS8WCeXMgRVZPVEVDMIIBIjANBgkq # hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv7KB3iyBrhkLUbbFe9qxhKKPBYqDBqln # r3AtpZplkiVjpi9dMZCchSeT5ODsShPuZCIxJp5I86uf8ibo3vi2S9F9AlfFjVye # 3dTz/9TmCuGH8JQt13ozf9niHecwKrstDVhVprgxi5v0XxY51c7zgMA2g1Ub+3ti # i0vi/OpmKXdL2keNqJ2neQ5cYly/GsI8CREUEq9SZijbdA8VrRF3SoDdsWGf3tZZ # zO6nWn3TLYKQ5/bw5U445u/V80QSoykszHRivTj+H4s8ABiforhi0i76beA6Ea41 # zcH4zJuAp48B4UhjgRDNuq8IzLWK4dlvqrqCBHKqsnrF6BmBrv+BXQIDAQABo4IB # xTCCAcEwHwYDVR0jBBgwFoAUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHQYDVR0OBBYE # FBixNSfoHFAgJk4JkDQLFLRNlJRmMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAK # BggrBgEFBQcDAzB3BgNVHR8EcDBuMDWgM6Axhi9odHRwOi8vY3JsMy5kaWdpY2Vy # dC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNybDA1oDOgMYYvaHR0cDovL2NybDQu # ZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwTAYDVR0gBEUwQzA3 # BglghkgBhv1sAwEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQu # Y29tL0NQUzAIBgZngQwBBAEwgYQGCCsGAQUFBwEBBHgwdjAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tME4GCCsGAQUFBzAChkJodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyQXNzdXJlZElEQ29kZVNpZ25p # bmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAmr1sz4ls # LARi4wG1eg0B8fVJFowtect7SnJUrp6XRnUG0/GI1wXiLIeow1UPiI6uDMsRXPHU # F/+xjJw8SfIbwava2eXu7UoZKNh6dfgshcJmo0QNAJ5PIyy02/3fXjbUREHINrTC # vPVbPmV6kx4Kpd7KJrCo7ED18H/XTqWJHXa8va3MYLrbJetXpaEPpb6zk+l8Rj9y # G4jBVRhenUBUUj3CLaWDSBpOA/+sx8/XB9W9opYfYGb+1TmbCkhUg7TB3gD6o6ES # Jre+fcnZnPVAPESmstwsT17caZ0bn7zETKlNHbc1q+Em9kyBjaQRcEQoQQNpezQu # g9ufqExx6lHYDjCCBY0wggR1oAMCAQICEA6bGI750C3n79tQ4ghAGFowDQYJKoZI # hvcNAQEMBQAwZTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ # MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQgQXNz # dXJlZCBJRCBSb290IENBMB4XDTIyMDgwMTAwMDAwMFoXDTMxMTEwOTIzNTk1OVow # YjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ # d3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290 # IEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAv+aQc2jeu+RdSjww # IjBpM+zCpyUuySE98orYWcLhKac9WKt2ms2uexuEDcQwH/MbpDgW61bGl20dq7J5 # 8soR0uRf1gU8Ug9SH8aeFaV+vp+pVxZZVXKvaJNwwrK6dZlqczKU0RBEEC7fgvMH # hOZ0O21x4i0MG+4g1ckgHWMpLc7sXk7Ik/ghYZs06wXGXuxbGrzryc/NrDRAX7F6 # Zu53yEioZldXn1RYjgwrt0+nMNlW7sp7XeOtyU9e5TXnMcvak17cjo+A2raRmECQ # ecN4x7axxLVqGDgDEI3Y1DekLgV9iPWCPhCRcKtVgkEy19sEcypukQF8IUzUvK4b # A3VdeGbZOjFEmjNAvwjXWkmkwuapoGfdpCe8oU85tRFYF/ckXEaPZPfBaYh2mHY9 # WV1CdoeJl2l6SPDgohIbZpp0yt5LHucOY67m1O+SkjqePdwA5EUlibaaRBkrfsCU # tNJhbesz2cXfSwQAzH0clcOP9yGyshG3u3/y1YxwLEFgqrFjGESVGnZifvaAsPvo # ZKYz0YkH4b235kOkGLimdwHhD5QMIR2yVCkliWzlDlJRR3S+Jqy2QXXeeqxfjT/J # vNNBERJb5RBQ6zHFynIWIgnffEx1P2PsIV/EIFFrb7GrhotPwtZFX50g/KEexcCP # orF+CiaZ9eRpL5gdLfXZqbId5RsCAwEAAaOCATowggE2MA8GA1UdEwEB/wQFMAMB # Af8wHQYDVR0OBBYEFOzX44LScV1kTN8uZz/nupiuHA9PMB8GA1UdIwQYMBaAFEXr # oq/0ksuCMS1Ri6enIZ3zbcgPMA4GA1UdDwEB/wQEAwIBhjB5BggrBgEFBQcBAQRt # MGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEF # BQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJl # ZElEUm9vdENBLmNydDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vY3JsMy5kaWdp # Y2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMBEGA1UdIAQKMAgw # BgYEVR0gADANBgkqhkiG9w0BAQwFAAOCAQEAcKC/Q1xV5zhfoKN0Gz22Ftf3v1cH # vZqsoYcs7IVeqRq7IviHGmlUIu2kiHdtvRoU9BNKei8ttzjv9P+Aufih9/Jy3iS8 # UgPITtAq3votVs/59PesMHqai7Je1M/RQ0SbQyHrlnKhSLSZy51PpwYDE3cnRNTn # f+hZqPC/Lwum6fI0POz3A8eHqNJMQBk1RmppVLC4oVaO7KTVPeix3P0c2PR3WlxU # jG/voVA9/HYJaISfb8rbII01YBwCA8sgsKxYoA5AY8WYIsGyWfVVa88nq2x2zm8j # LfR+cWojayL/ErhULSd+2DrZ8LaHlv1b0VysGMNNn3O3AamfV6peKOK5lDCCBq4w # ggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjELMAkG # A1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRp # Z2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4X # DTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAV # BgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVk # IEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZIhvcN # AQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD0Z5M # om2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39Q7SE # 2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decfBmWN # lCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RUCyFo # bjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+xtVhN # ef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OAe3Vu # JyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRAKKtz # Q87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++bPf4O # uGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+OcD5 # sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2TjY+Cm # 4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZDNIz # tM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBS6 # FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qY # rhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYIKwYB # BQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20w # QQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2Vy # dFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwz # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1UdIAQZ # MBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEAfVmO # wJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnBzx0H # 6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXOlWk/ # R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBwCnzv # qLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q6/ae # sXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJuXdm # kfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEhQNC3 # EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo46Zzh # 3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3v5gA # 3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHzV9m8 # BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZVVCsf # gPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwwggbAMIIEqKADAgECAhAMTWly # S5T6PCpKPSkHgD1aMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYD # VQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBH # NCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjIwOTIxMDAwMDAw # WhcNMzMxMTIxMjM1OTU5WjBGMQswCQYDVQQGEwJVUzERMA8GA1UEChMIRGlnaUNl # cnQxJDAiBgNVBAMTG0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDIyIC0gMjCCAiIwDQYJ # KoZIhvcNAQEBBQADggIPADCCAgoCggIBAM/spSY6xqnya7uNwQ2a26HoFIV0Mxom # rNAcVR4eNm28klUMYfSdCXc9FZYIL2tkpP0GgxbXkZI4HDEClvtysZc6Va8z7GGK # 6aYo25BjXL2JU+A6LYyHQq4mpOS7eHi5ehbhVsbAumRTuyoW51BIu4hpDIjG8b7g # L307scpTjUCDHufLckkoHkyAHoVW54Xt8mG8qjoHffarbuVm3eJc9S/tjdRNlYRo # 44DLannR0hCRRinrPibytIzNTLlmyLuqUDgN5YyUXRlav/V7QG5vFqianJVHhoV5 # PgxeZowaCiS+nKrSnLb3T254xCg/oxwPUAY3ugjZNaa1Htp4WB056PhMkRCWfk3h # 3cKtpX74LRsf7CtGGKMZ9jn39cFPcS6JAxGiS7uYv/pP5Hs27wZE5FX/NurlfDHn # 88JSxOYWe1p+pSVz28BqmSEtY+VZ9U0vkB8nt9KrFOU4ZodRCGv7U0M50GT6Vs/g # 9ArmFG1keLuY/ZTDcyHzL8IuINeBrNPxB9ThvdldS24xlCmL5kGkZZTAWOXlLimQ # prdhZPrZIGwYUWC6poEPCSVT8b876asHDmoHOWIZydaFfxPZjXnPYsXs4Xu5zGcT # B5rBeO3GiMiwbjJ5xwtZg43G7vUsfHuOy2SJ8bHEuOdTXl9V0n0ZKVkDTvpd6kVz # HIR+187i1Dp3AgMBAAGjggGLMIIBhzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/ # BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAgBgNVHSAEGTAXMAgGBmeBDAEE # AjALBglghkgBhv1sBwEwHwYDVR0jBBgwFoAUuhbZbU2FL3MpdpovdYxqII+eyG8w # HQYDVR0OBBYEFGKK3tBh/I8xFO2XC809KpQU31KcMFoGA1UdHwRTMFEwT6BNoEuG # SWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQw # OTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcmwwgZAGCCsGAQUFBwEBBIGDMIGAMCQG # CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wWAYIKwYBBQUHMAKG # TGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJT # QTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggIB # AFWqKhrzRvN4Vzcw/HXjT9aFI/H8+ZU5myXm93KKmMN31GT8Ffs2wklRLHiIY1UJ # RjkA/GnUypsp+6M/wMkAmxMdsJiJ3HjyzXyFzVOdr2LiYWajFCpFh0qYQitQ/Bu1 # nggwCfrkLdcJiXn5CeaIzn0buGqim8FTYAnoo7id160fHLjsmEHw9g6A++T/350Q # p+sAul9Kjxo6UrTqvwlJFTU2WZoPVNKyG39+XgmtdlSKdG3K0gVnK3br/5iyJpU4 # GYhEFOUKWaJr5yI+RCHSPxzAm+18SLLYkgyRTzxmlK9dAlPrnuKe5NMfhgFknADC # 6Vp0dQ094XmIvxwBl8kZI4DXNlpflhaxYwzGRkA7zl011Fk+Q5oYrsPJy8P7mxNf # arXH4PMFw1nfJ2Ir3kHJU7n/NBBn9iYymHv+XEKUgZSCnawKi8ZLFUrTmJBFYDOA # 4CPe+AOk9kVH5c64A0JH6EE2cXet/aLol3ROLtoeHYxayB6a1cLwxiKoT5u92Bya # UcQvmvZfpyeXupYuhVfAYOd4Vn9q78KVmksRAsiCnMkaBXy6cbVOepls9Oie1FqY # yJ+/jbsYXEP10Cro4mLueATbvdH7WwqocH7wl4R44wgDXUcsY6glOJcB0j862uXl # 9uab3H4szP8XTE0AotjWAQ64i+7m4HJViSwnGWH2dwGMMYIFXTCCBVkCAQEwgYYw # cjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ # d3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVk # IElEIENvZGUgU2lnbmluZyBDQQIQBNXcH0jqydhSALrNmpsqpzANBglghkgBZQME # AgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEM # BgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqG # SIb3DQEJBDEiBCAK+xcB08DZPPjCFVs51ma/Lu5xa7crnh3hjXjeVwIwZzANBgkq # hkiG9w0BAQEFAASCAQCEjm6czdyF7YilG/TZ2b/DYjlppbwTObld/Lk7GvJX2LXZ # fG3xvhDQknqdi3GT39zQJKuAoHKu5JELYtIYGqHbRXrMIe3XVRM2fLQ8Xx7VutAO # kswbpO+u9cPmRPLms17PJhbTNBYmdiY5KwmGdd97mepJSlgCXxrNvMv/cy0YbQ1r # 9hfJhoDsBDW6QhX5Ej0LgP6DGxQ6JfWdlwN+WexcgnVJmeN2BuNUnFYHr9UIXkBW # KLPTijWx88H0bHuJIRGBPmjvDMfC5KkmW/IgPrvLF/OwLAsXXHxgLICZyjz5WN3k # l+UuIWjFi++lE8cHqoCH6Hhg3xAg6YP8UhvPcEHVoYIDIDCCAxwGCSqGSIb3DQEJ # BjGCAw0wggMJAgEBMHcwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0 # LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hB # MjU2IFRpbWVTdGFtcGluZyBDQQIQDE1pckuU+jwqSj0pB4A9WjANBglghkgBZQME # AgEFAKBpMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8X # DTIzMDMwODE2NTQxNVowLwYJKoZIhvcNAQkEMSIEIFBFYrZjyqQdgW6x1tH+uiS2 # SQF4c8P9nSePsHA4PuuBMA0GCSqGSIb3DQEBAQUABIICAKCSBvXod/4MCZyPBE+F # HErRK2gfmk8bWhq6pxCdwMEmwSxeOBjiPZ8t5/9fIe/eJMAk1PH4ca3e6eTXGEhH # 0CEvTXpcei6TISBWCcFmUMz/SsOPX7FIXYcpKtrXE7P6YvizpSNnOYAonqitzdQ6 # 2qtc1Lqkq7vnFzSIapA2UFsrf9QUFLoDiKC/E2I4J35PQGvR2cUfD498cLuGrfUZ # 1wMKUa7sxLqK/uxyHLtxhjKLQhC2C36nEmPzWEEzvcreYNkbjTHJ7CBAH9u46bg/ # kHz69ZFosB8fqih6mAhiLys0oPwm4ii6hVeP7hkW1AMLljp3zeKWuFKzHzCkxDoJ # ef2ftOdbEo3HFNkDUPT1T10+sRtcrMx/WRXJsRh+N/APudhcAEDbFr4JHhEhTrfu # 4Z/gc1IBTtGVWLweumdrZUmxP26ct6e9TxO01HCATvUqpfcn6TbJvY0CHdRnaMA9 # A2tmTQxkh7lz4xogN/tfnzmThNiVSlQBWeKHDmDGvicFS8s0t/jZ6k18rTtK/MMV # l2czL9ioqNRS+MBbU2sarp0bhihXo9T0eTe2on8i3EyEr6Y8gf7xmRZu+a7N0FUU # IZCNpLxbjE8xkzLS55PHJfKqoOmW62bn1rskiRDJ41LscD9UQbRXJ/RGcdacow2L # ersMEhVWF/rdHWaVsaWr8oGK # SIG # End signature block |