Extensions/PowerShellCmdletsExtensions.ps1
<#
.SYNOPSIS A wrapper function for Invoke-WebRequest which gets content from a web page on the internet. .DESCRIPTION A wrapper function for Invoke-WebRequest which gets content from a web page on the internet. For PowerShell Core the function calls the Invoke-WebRequest cmdlet directly. For PowerShell 5.1 a custom Certificate Validator is used to cover the missing SkipCertificateCheck parameter. .PARAMETER InvokeParams The hashtable containing the parameters that are going to be passed to the Invoke-WebRequest cmdlet. .PARAMETER SkipCertificateCheck If the value is $true, skips certificate validation checks. This includes all validations such as expiration, revocation, trusted root authority, etc. #> function Invoke-WebRequestX { [CmdletBinding()] [OutputType([Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject])] param ( [Parameter(Mandatory = $true)] [hashtable] $InvokeParams, [Parameter(Mandatory = $true)] [bool] $SkipCertificateCheck ) $tempProgressPreference = $ProgressPreference $ProgressPreference = 'SilentlyContinue' $invokeWebRequestResult = $null if ($Global:PSVersionTable.PSEdition -eq 'Core') { $InvokeParams['SkipCertificateCheck'] = $SkipCertificateCheck $invokeWebRequestResult = Invoke-WebRequest @InvokeParams } else { [System.Net.ServicePointManager]::ServerCertificateValidationCallback = [CustomCertificatesValidator]::GetDelegate() try { $invokeWebRequestResult = Invoke-WebRequest @InvokeParams } finally { $debugLog = [CustomCertificatesValidator]::GetDebugLog() Write-Debug -Message $debugLog } } $ProgressPreference = $tempProgressPreference $invokeWebRequestResult } <# .SYNOPSIS A wrapper function for Invoke-RestMethod which sends an HTTP or HTTPS request to a RESTful web service. .DESCRIPTION A wrapper function for Invoke-RestMethod which sends an HTTP or HTTPS request to a RESTful web service. For PowerShell Core the function calls the Invoke-RestMethod cmdlet directly. For PowerShell 5.1 a custom Certificate Validator is used to cover the missing SkipCertificateCheck parameter. .PARAMETER InvokeParams The hashtable containing the parameters that are going to be passed to the Invoke-RestMethod cmdlet. .PARAMETER SkipCertificateCheck If the value is $true, skips certificate validation checks. This includes all validations such as expiration, revocation, trusted root authority, etc. #> function Invoke-RestMethodX { [CmdletBinding()] [OutputType([System.Object])] param ( [Parameter(Mandatory = $true)] [hashtable] $InvokeParams, [Parameter(Mandatory = $true)] [bool] $SkipCertificateCheck ) $invokeRestMethodResult = $null if ($Global:PSVersionTable.PSEdition -eq 'Core') { $InvokeParams['SkipCertificateCheck'] = $SkipCertificateCheck $invokeRestMethodResult = Invoke-RestMethod @InvokeParams } else { [System.Net.ServicePointManager]::ServerCertificateValidationCallback = [CustomCertificatesValidator]::GetDelegate() try { $invokeRestMethodResult = Invoke-RestMethod @InvokeParams } finally { $debugLog = [CustomCertificatesValidator]::GetDebugLog() Write-Debug -Message $debugLog } } $invokeRestMethodResult } <# .SYNOPSIS Retrieves the Certificate thumbprint for the specified remote host. .DESCRIPTION Retrieves the Certificate thumbprint for the specified remote host. Tcp and Ssl streams are used. .PARAMETER RemoteHostName The IPAddress of the remote host. .PARAMETER Port The port number of the remote host. .PARAMETER Timeout A TimeSpan that represents the number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. #> function Get-TlsCertificateThumbprintFromRemoteHost { [CmdletBinding()] [OutputType([string])] param ( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string] $RemoteHostName, [Parameter(Mandatory = $false, Position = 1)] [ValidateRange(0, 65535)] [int] $Port = 443, [Parameter(Mandatory = $false, Position = 2)] [int] $Timeout = 3000 ) $certificate = $null $certificateThumbprint = $null $sslStream = $null $tcpStream = $null $tcpClient = $null try { $tcpClient = New-Object -TypeName 'System.Net.Sockets.TcpClient' $iAsyncResult = $tcpClient.BeginConnect($RemoteHostName, $Port, $null, $null) $wait = $iAsyncResult.AsyncWaitHandle.WaitOne($Timeout, $false) if (!$wait) { $tcpClient.Close() Write-Warning -Message "Connection attempt to server $RemoteHostName has timed out." } else { $tcpClient.EndConnect($iAsyncResult) | Out-Null if ($tcpClient.Connected) { $tcpStream = $tcpClient.GetStream() $sslStream = New-Object -TypeName 'System.Net.Security.SslStream' -ArgumentList ($tcpStream, $false, ({ $true } -as [System.Net.Security.RemoteCertificateValidationCallback])) $sslStream.AuthenticateAsClient($RemoteHostName, $null, [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12 -bor [System.Net.SecurityProtocolType]::Tls13, $false) $certificate = New-Object -TypeName 'System.Security.Cryptography.X509Certificates.X509Certificate2' -ArgumentList ($sslStream.RemoteCertificate) $certificateThumbprint = $certificate.Thumbprint } else { Write-Warning -Message "Unable to establish connection to server $RemoteHostName on port $Port." } } } catch { throw "SkipCertificateCheck with value True requires retrieving Certificate thumbprint from server $RemoteHostName which failed with the following error : $($_.Exception.Message)" } finally { if ($null -ne $certificate) { $certificate.Dispose() } if ($null -ne $sslStream) { $sslStream.Close() $sslStream.Dispose() } if ($null -ne $tcpStream) { $tcpStream.Close() $tcpStream.Dispose() } if ($null -ne $tcpClient) { $tcpClient.Close() } } $certificateThumbprint } <# .SYNOPSIS A wrapper function that extracts the password from a SecureString as plain text. .DESCRIPTION A wrapper function that extracts the password from a SecureString as plain text. For PowerShell Core the function calls the ConvertFrom-SecureString cmdlet directly. For PowerShell 5.1 the System.Runtime.InteropServices.Marshal type is used to extract the password from the SecureString as plain text. .PARAMETER Password Specifies the SecureString Password from which the plain text password should be extracted. #> function Get-PlainTextPassword { [CmdletBinding()] [OutputType([string])] param ( [Parameter(Mandatory = $true)] [SecureString] $Password ) $plainTextPassword = $null if ($Global:PSVersionTable.PSEdition -eq 'Core') { $plainTextPassword = ConvertFrom-SecureString -SecureString $Password -AsPlainText } else { $passwordAsBinaryString = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password) $plainTextPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($passwordAsBinaryString) } $plainTextPassword } <# .SYNOPSIS A wrapper function that converts a JSON to PSCustomObject. .DESCRIPTION A wrapper function that converts a JSON to PSCustomObject. For PowerShell Core the function calls the ConvertFrom-Json cmdlet directly. For PowerShell 5.1 the Newtonsoft.Json library is used to ensure the same behaviour for both PowerShell versions. .PARAMETER InputObject Specifies the input JSON that should be converted to PSCustomObject. .PARAMETER Depth Gets or sets the maximum depth the JSON input is allowed to have. By default, it is 100. #> function ConvertFrom-JsonX { [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [AllowEmptyString()] [string] $InputObject, [Parameter(Mandatory = $false)] [ValidateRange(1, 1024)] [int] $Depth = 100 ) Process { $result = $null if ($Global:PSVersionTable.PSEdition -eq 'Core') { $result = ConvertFrom-Json -InputObject $InputObject -Depth $Depth } else { try { $jsonSerializerSettings = [Newtonsoft.Json.JsonSerializerSettings]::new() $jsonSerializerSettings.TypeNameHandling = [Newtonsoft.Json.TypeNameHandling]::None $jsonSerializerSettings.MetadataPropertyHandling = [Newtonsoft.Json.MetadataPropertyHandling]::Ignore $jsonSerializerSettings.MaxDepth = $Depth $deserializedObject = [Newtonsoft.Json.JsonConvert]::DeserializeObject($InputObject, $jsonSerializerSettings) if ($deserializedObject -is [Newtonsoft.Json.Linq.JObject]) { $result = ConvertFrom-JObject -JObject $deserializedObject } elseif($deserializedObject -is [Newtonsoft.Json.Linq.JArray]) { $result = ConvertFrom-JArray -JArray $deserializedObject } else { $result = $deserializedObject } } catch { throw "Conversion from JSON failed with error: $($_.Exception.Message)" } } $result } } function ConvertFrom-JObject { [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory = $true)] [System.Object] $JObject ) $psCustomObjectResult = [PSCustomObject] @{} foreach ($entry in $JObject.GetEnumerator()) { if ($null -eq $entry.Key) { return $null } if ($entry.Value -is [Newtonsoft.Json.Linq.JObject]) { $entryValue = ConvertFrom-JObject -JObject $entry.Value $psCustomObjectResult | Add-Member -MemberType NoteProperty -Name $entry.Key -Value $entryValue } elseif ($entry.Value -is [Newtonsoft.Json.Linq.JValue]) { $psCustomObjectResult | Add-Member -MemberType NoteProperty -Name $entry.Key -Value $entry.Value.Value } elseif ($entry.Value -is [Newtonsoft.Json.Linq.JArray]) { $entryValue = ConvertFrom-JArray -JArray $entry.Value if ($null -eq $entryValue) { $entryValue = @() } $psCustomObjectResult | Add-Member -MemberType NoteProperty -Name $entry.Key -Value $entryValue } } $psCustomObjectResult } function ConvertFrom-JArray { [CmdletBinding()] [OutputType([array])] param ( [Parameter(Mandatory = $true)] [System.Object] $JArray ) $arrayResult = @() for ($i = 0; $i -lt $JArray.Count; $i++) { $entry = $JArray[$i] if ($entry -is [Newtonsoft.Json.Linq.JArray]) { $arrayResult += ConvertFrom-JArray -JArray $entry } elseif ($entry -is [Newtonsoft.Json.Linq.JObject]) { $arrayResult += ConvertFrom-JObject -JObject $entry } elseif ($entry -is [Newtonsoft.Json.Linq.JValue]) { $arrayResult += $entry.Value } } if ($arrayResult.Count -eq 1) { , $arrayResult } else { $arrayResult } } # SIG # Begin signature block # MIIohgYJKoZIhvcNAQcCoIIodzCCKHMCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDXehCgWaBdNU1V # 5x8tv0fB+QeMO6168i4h4JcTs02CNqCCDdowggawMIIEmKADAgECAhAIrUCyYNKc # TJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0z # NjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw # ggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0 # JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJr # Q5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhF # LqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+F # LEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh # 3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJ # wZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQay # g9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbI # YViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchAp # QfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRro # OBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IB # WTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+ # YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0P # AQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAC # hjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v # dEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAED # MAgGBmeBDAEEATANBgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql # +Eg08yy25nRm95RysQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFF # UP2cvbaF4HZ+N3HLIvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1h # mYFW9snjdufE5BtfQ/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3Ryw # YFzzDaju4ImhvTnhOE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5Ubdld # AhQfQDN8A+KVssIhdXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw # 8MzK7/0pNVwfiThV9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnP # LqR0kq3bPKSchh/jwVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatE # QOON8BUozu3xGFYHKi8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bn # KD+sEq6lLyJsQfmCXBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQji # WQ1tygVQK+pKHJ6l/aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbq # yK+p/pQd52MbOoZWeE4wggciMIIFCqADAgECAhAOxvKydqFGoH0ObZNXteEIMA0G # CSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjEwODEwMDAwMDAwWhcNMjMwODEw # MjM1OTU5WjCBhzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQ # BgNVBAcTCVBhbG8gQWx0bzEVMBMGA1UEChMMVk13YXJlLCBJbmMuMRUwEwYDVQQD # EwxWTXdhcmUsIEluYy4xITAfBgkqhkiG9w0BCQEWEm5vcmVwbHlAdm13YXJlLmNv # bTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAMD6lJG8OWkM12huIQpO # /q9JnhhhW5UyW9if3/UnoFY3oqmp0JYX/ZrXogUHYXmbt2gk01zz2P5Z89mM4gqR # bGYC2tx+Lez4GxVkyslVPI3PXYcYSaRp39JsF3yYifnp9R+ON8O3Gf5/4EaFmbeT # ElDCFBfExPMqtSvPZDqekodzX+4SK1PIZxCyR3gml8R3/wzhb6Li0mG7l0evQUD0 # FQAbKJMlBk863apeX4ALFZtrnCpnMlOjRb85LsjV5Ku4OhxQi1jlf8wR+za9C3DU # ki60/yiWPu+XXwEUqGInIihECBbp7hfFWrnCCaOgahsVpgz8kKg/XN4OFq7rbh4q # 5IkTauqFhHaE7HKM5bbIBkZ+YJs2SYvu7aHjw4Z8aRjaIbXhI1G+NtaNY7kSRrE4 # fAyC2X2zV5i4a0AuAMM40C1Wm3gTaNtRTHnka/pbynUlFjP+KqAZhOniJg4AUfjX # sG+PG1LH2+w/sfDl1A8liXSZU1qJtUs3wBQFoSGEaGBeDQIDAQABo4ICJTCCAiEw # HwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHQYDVR0OBBYEFIhC+HL9 # QlvsWsztP/I5wYwdfCFNMB0GA1UdEQQWMBSBEm5vcmVwbHlAdm13YXJlLmNvbTAO # BgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwgbUGA1UdHwSBrTCB # qjBToFGgT4ZNaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3Rl # ZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcmwwU6BRoE+GTWh0 # dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWdu # aW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3JsMD4GA1UdIAQ3MDUwMwYGZ4EMAQQB # MCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzCBlAYI # KwYBBQUHAQEEgYcwgYQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0 # LmNvbTBcBggrBgEFBQcwAoZQaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp # Z2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5j # cnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEACQAYaQI6Nt2KgxdN # 6qqfcHB33EZRSXkvs8O9iPZkdDjEx+2fgbBPLUvk9A7T8mRw7brbcJv4PLTYJDFo # c5mlcmG7/5zwTOuIs2nBGXc/uxCnyW8p7kD4Y0JxPKEVQoIQ8lJS9Uy/hBjyakeV # ef982JyzvDbOlLBy6AS3ZpXVkRY5y3Va+3v0R/0xJ+JRxUicQhiZRidq2TCiWEas # d+tLL6jrKaBO+rmP52IM4eS9d4Yids7ogKEBAlJi0NbvuKO0CkgOlFjp1tOvD4sQ # taHIMmqi40p4Tjyf/sY6yGjROXbMeeF1vlwbBAASPWpQuEIxrNHoVN30YfJyuOWj # zdiJUTpeLn9XdjM3UlhfaHP+oIAKcmkd33c40SFRlQG9+P9Wlm7TcPxGU4wzXI8n # Cw/h235jFlAAiWq9L2r7Un7YduqsheJVpGoXmRXJH0T2G2eNFS5/+2sLn98kN2Cn # J7j6C242onjkZuGL2/+gqx8m5Jbpu9P4IAeTC1He/mX9j6XpIu+7uBoRVwuWD1i0 # N5SiUz7Lfnbr6Q1tHMXKDLFdwVKZos2AKEZhv4SU0WvenMJKDgkkhVeHPHbTahQf # P1MetR8tdRs7uyTWAjPK5xf5DLEkXbMrUkpJ089fPvAGVHBcHRMqFA5egexOb6sj # tKncUjJ1xAAtAExGdCh6VD2U5iYxghoCMIIZ/gIBATB9MGkxCzAJBgNVBAYTAlVT # MRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1 # c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEzODQgMjAyMSBDQTECEA7G # 8rJ2oUagfQ5tk1e14QgwDQYJYIZIAWUDBAIBBQCggZYwGQYJKoZIhvcNAQkDMQwG # CisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwKgYKKwYB # BAGCNwIBDDEcMBqhGIAWaHR0cDovL3d3dy52bXdhcmUuY29tLzAvBgkqhkiG9w0B # CQQxIgQgAoKWAekSMFmAzh1sjawIxsuHt22TbUVUcb3a5tFi8U0wDQYJKoZIhvcN # AQEBBQAEggGAVPHZD57Dqm79Z/j94SWfa5M+LNFZXIrAw+i2jNfZrDSBpts0WqUe # k6Si/41tdU7dcMWJBtbohHecflmKDYESHfi1SevSBFXM6Z27UFxPYscHT0LYQc8/ # u2RzQIsNxO8xJ3Fp9f3BVvn8Asb6tqEWMLj/11asytI+vYNbJ9i1bANpStTSasQa # jLGHe9bRun4NLz6TLb8zjv36xXYg4t5mq/BfQdFa34sBzPnakhoCmB1/+LuvmftM # jb0sz4Lwssm/4X06tVIU68XfRWRV3YXRzE8xLa9c6T9xeynKiiYGzjo4EyA8l9/s # KJdjFVrgULXb4TOr9RVC3DbMQ8jKOgR9n4l/I14BjmFGNm63mQf84YxT6CzZ6fYh # NG21xWTHL58NFE7iaep+s+NZnofxtPzAjL6LbRaTJGxzf6ZS/U+q5wv1xbHTPVg2 # ekPoLKWqk7OjLmrrrN1TdJRHAG3XzW1W5O5knwR4cBeUKoL25LXmZoQArW1bmV5r # 8HJoTYwqGyOvoYIXPTCCFzkGCisGAQQBgjcDAwExghcpMIIXJQYJKoZIhvcNAQcC # oIIXFjCCFxICAQMxDzANBglghkgBZQMEAgEFADB3BgsqhkiG9w0BCRABBKBoBGYw # ZAIBAQYJYIZIAYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEID0SOAjmZjqfnthAwkbE # xKh1RkvOyiQoiNPPLQ/0MK75AhBBFYBbBJgxHpDhrnkKJMkfGA8yMDIzMDQxODE0 # MzY0N1qgghMHMIIGwDCCBKigAwIBAgIQDE1pckuU+jwqSj0pB4A9WjANBgkqhkiG # 9w0BAQsFADBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4x # OzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGlt # ZVN0YW1waW5nIENBMB4XDTIyMDkyMTAwMDAwMFoXDTMzMTEyMTIzNTk1OVowRjEL # MAkGA1UEBhMCVVMxETAPBgNVBAoTCERpZ2lDZXJ0MSQwIgYDVQQDExtEaWdpQ2Vy # dCBUaW1lc3RhbXAgMjAyMiAtIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK # AoICAQDP7KUmOsap8mu7jcENmtuh6BSFdDMaJqzQHFUeHjZtvJJVDGH0nQl3PRWW # CC9rZKT9BoMW15GSOBwxApb7crGXOlWvM+xhiummKNuQY1y9iVPgOi2Mh0KuJqTk # u3h4uXoW4VbGwLpkU7sqFudQSLuIaQyIxvG+4C99O7HKU41Agx7ny3JJKB5MgB6F # VueF7fJhvKo6B332q27lZt3iXPUv7Y3UTZWEaOOAy2p50dIQkUYp6z4m8rSMzUy5 # Zsi7qlA4DeWMlF0ZWr/1e0BubxaompyVR4aFeT4MXmaMGgokvpyq0py2909ueMQo # P6McD1AGN7oI2TWmtR7aeFgdOej4TJEQln5N4d3CraV++C0bH+wrRhijGfY59/XB # T3EuiQMRoku7mL/6T+R7Nu8GRORV/zbq5Xwx5/PCUsTmFntafqUlc9vAapkhLWPl # WfVNL5AfJ7fSqxTlOGaHUQhr+1NDOdBk+lbP4PQK5hRtZHi7mP2Uw3Mh8y/CLiDX # gazT8QfU4b3ZXUtuMZQpi+ZBpGWUwFjl5S4pkKa3YWT62SBsGFFguqaBDwklU/G/ # O+mrBw5qBzliGcnWhX8T2Y15z2LF7OF7ucxnEweawXjtxojIsG4yeccLWYONxu71 # LHx7jstkifGxxLjnU15fVdJ9GSlZA076XepFcxyEftfO4tQ6dwIDAQABo4IBizCC # AYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYI # KwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMB8GA1Ud # IwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQWBBRiit7QYfyPMRTt # lwvNPSqUFN9SnDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsMy5kaWdpY2Vy # dC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1waW5n # Q0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcwAYYYaHR0cDovL29j # c3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8vY2FjZXJ0cy5kaWdp # Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1w # aW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQBVqioa80bzeFc3MPx140/WhSPx # /PmVOZsl5vdyipjDd9Rk/BX7NsJJUSx4iGNVCUY5APxp1MqbKfujP8DJAJsTHbCY # idx48s18hc1Tna9i4mFmoxQqRYdKmEIrUPwbtZ4IMAn65C3XCYl5+QnmiM59G7hq # opvBU2AJ6KO4ndetHxy47JhB8PYOgPvk/9+dEKfrALpfSo8aOlK06r8JSRU1Nlma # D1TSsht/fl4JrXZUinRtytIFZyt26/+YsiaVOBmIRBTlClmia+ciPkQh0j8cwJvt # fEiy2JIMkU88ZpSvXQJT657inuTTH4YBZJwAwuladHUNPeF5iL8cAZfJGSOA1zZa # X5YWsWMMxkZAO85dNdRZPkOaGK7DycvD+5sTX2q1x+DzBcNZ3ydiK95ByVO5/zQQ # Z/YmMph7/lxClIGUgp2sCovGSxVK05iQRWAzgOAj3vgDpPZFR+XOuANCR+hBNnF3 # rf2i6Jd0Ti7aHh2MWsgemtXC8MYiqE+bvdgcmlHEL5r2X6cnl7qWLoVXwGDneFZ/ # au/ClZpLEQLIgpzJGgV8unG1TnqZbPTontRamMifv427GFxD9dAq6OJi7ngE273R # +1sKqHB+8JeEeOMIA11HLGOoJTiXAdI/Otrl5fbmm9x+LMz/F0xNAKLY1gEOuIvu # 5uByVYksJxlh9ncBjDCCBq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJ # KoZIhvcNAQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IElu # YzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQg # VHJ1c3RlZCBSb290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVow # YzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQD # EzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGlu # ZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklR # VcclA8TykTepl1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54P # Mx9QEwsmc5Zt+FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupR # PfDWVtTnKC3r07G1decfBmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvo # hGS0UvJ2R/dhgxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV # 5huowWR0QKfAcsW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYV # VSZwmCZ/oBpHIEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6i # c/rnH1pslPJSlRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/Ci # PMpC3BhIfxQ0z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5 # K6jzRWC8I41Y99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oi # qMEmCPkUEBIDfV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuld # yF4wEr1GnrXTdrnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAG # AQH/AgEAMB0GA1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAW # gBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAww # CgYIKwYBBQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8v # b2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRp # Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDow # OKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRS # b290RzQuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkq # hkiG9w0BAQsFAAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvH # UF3iSyn7cIoNqilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0M # CIKoFr2pVs8Vc40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCK # rOX9jLxkJodskr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rA # J4JErpknG6skHibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZ # xhOACcS2n82HhyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScs # PT9rp/Fmw0HNT7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1M # rfvElXvtCl8zOYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXse # GYs2uJPU5vIXmVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWY # MbRiCQ8KvYHZE/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYp # hwlHK+Z/GqSFD/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPww # ggWNMIIEdaADAgECAhAOmxiO+dAt5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9v # dCBDQTAeFw0yMjA4MDEwMDAwMDBaFw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYT # AlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2Vy # dC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJ # KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskh # PfKK2FnC4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIP # Uh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34LzB4TmdDttceItDBvu # INXJIB1jKS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+xembud8hIqGZXV59U # WI4MK7dPpzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4 # AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJoz # QL8I11pJpMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw # 4KISG2aadMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sE # AMx9HJXDj/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZD # pBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/ybzTQRESW+UQUOsx # xcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+Y # HS312amyHeUbAgMBAAGjggE6MIIBNjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW # BBTs1+OC0nFdZEzfLmc/57qYrhwPTzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun # pyGd823IDzAOBgNVHQ8BAf8EBAMCAYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUF # BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6 # Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5j # cnQwRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0Rp # Z2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJ # KoZIhvcNAQEMBQADggEBAHCgv0NcVec4X6CjdBs9thbX979XB72arKGHLOyFXqka # uyL4hxppVCLtpIh3bb0aFPQTSnovLbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP # +fT3rDB6mouyXtTP0UNEm0Mh65ZyoUi0mcudT6cGAxN3J0TU53/oWajwvy8Lpuny # NDzs9wPHh6jSTEAZNUZqaVSwuKFWjuyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiE # n2/K2yCNNWAcAgPLILCsWKAOQGPFmCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4 # VC0nftg62fC2h5b9W9FcrBjDTZ9ztwGpn1eqXijiuZQxggN2MIIDcgIBATB3MGMx # CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMy # RGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcg # Q0ECEAxNaXJLlPo8Kko9KQeAPVowDQYJYIZIAWUDBAIBBQCggdEwGgYJKoZIhvcN # AQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yMzA0MTgxNDM2NDda # MCsGCyqGSIb3DQEJEAIMMRwwGjAYMBYEFPOHIk2GM4KSNamUvL2Plun+HHxzMC8G # CSqGSIb3DQEJBDEiBCCXlPSWLZ5XwgOkpOU8nejp6QQSgjsFeJKNvbQ0u4AyKjA3 # BgsqhkiG9w0BCRACLzEoMCYwJDAiBCDH9OG+MiiJIKviJjq+GsT8T+Z4HC1k0EyA # dVegI7W2+jANBgkqhkiG9w0BAQEFAASCAgBxT5gXHoP8xnggyOV4Mce3fGtgLaMC # 7vq6CQJiWaYUZNtngRM7g77KKyBg0PCE4wBBH6hnhbqTp53Q/BInz5qN5exspGuV # FE8zeRkKjbk5lL+QqHSyQ0oLOA9X/5AK9eX55SOBfMe+E0L6FHN/nQAZLAeUVljV # uN+KbAgO5Rn/Q/qxjG7WPEcYzs+keSV3diFblGVEc6L0VAfVUJQ1FS1avTRO4+uN # zqXzoBBMjRT/E4vQMboW0knM2sTvZUCB+XCkj1xoO9Z9f7EUSi/ltm5ZbAJOJ+sT # W035JKtOqybOrysfiNZPvYQTuyhiLBkaHb/VJcU6V1aW43DhvXTr75qfjrto0PRs # 08qFIKbypVJPDF13lEwwFARpQxsWgUYLfqOkx+Zim97sB2nfnV/RNAEktY1PlQxs # y8BavD1X8w7IkdL+Vx6sWz2HNA2zg9FDWRVz5BODV56Nr3meJr6VcwilyqfzN55N # Z6NTZy/nj4sBMFspyx73Dv5VBd5HZ/p6MtmpPPlQAVpIwbVnWTmHraKUM0wEPno/ # Qi8qQ1b7gVMOQfVFrAu+mfLsVgep0X6WmvcYXy2ZkVerBs7vHYi2UU+yRPc+VXgz # NtRbMonwjSq3pzKtH4B//hhrrQfE/bJ6EQlPHclJ0IOrPZkpzTDkDWSoUSbov4q0 # R4S0vUGt7ufJcQ== # SIG # End signature block |