Microsoft.PowerShell.ODataUtils.psm1

Import-LocalizedData LocalizedData -FileName Microsoft.PowerShell.ODataUtilsStrings.psd1

. "$PSScriptRoot\Microsoft.PowerShell.ODataUtilsHelper.ps1"

#########################################################
# Generates PowerShell module containing client side
# proxy cmdlets that can be used to interact with an
# OData based server side endpoint.
#########################################################
function Export-ODataEndpointProxy 
{
    [CmdletBinding(
    DefaultParameterSetName='CDXML',
    SupportsShouldProcess=$true,
    HelpUri="http://go.microsoft.com/fwlink/?LinkId=510069")]
    [OutputType([System.IO.FileInfo])]
    param
    (
        [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNullOrEmpty()]
        [string] $Uri,

        [Parameter(Position=1, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNullOrEmpty()]
        [string] $OutputModule,

        [Parameter(Position=2, ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNullOrEmpty()]
        [string] $MetadataUri,

        [Parameter(Position=3, ValueFromPipelineByPropertyName=$true)]
        [PSCredential] $Credential,
    
        [Parameter(Position=4, ValueFromPipelineByPropertyName=$true)]
        [ValidateSet('Put', 'Post', 'Patch')]
        [string] $CreateRequestMethod='Post',
    
        [Parameter(Position=5, ValueFromPipelineByPropertyName=$true)]
        [ValidateSet('Put', 'Post', 'Patch')]
        [string] $UpdateRequestMethod='Patch',

        [Parameter(Position=6, ValueFromPipelineByPropertyName=$true)]
        [ValidateSet('ODataAdapter', 'NetworkControllerAdapter', 'ODataV4Adapter')]
        [string] $CmdletAdapter='ODataAdapter',

        [Parameter(Position=7, ValueFromPipelineByPropertyName=$true)]
        [Hashtable] $ResourceNameMapping,

        [parameter (Position=8,ValueFromPipelineByPropertyName=$true)]
        [switch] $Force,

        [Parameter(Position=9, ValueFromPipelineByPropertyName=$true)]
        [Hashtable] $CustomData,

        [parameter (Position=10,ValueFromPipelineByPropertyName=$true)]
        [switch] $AllowClobber,

        [parameter (Position=11,ValueFromPipelineByPropertyName=$true)]
        [switch] $AllowUnsecureConnection,

        [parameter (Position=12,ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNull()]
        [Hashtable] $Headers,

        [parameter (Position=13,ValueFromPipelineByPropertyName=$true)]
        [switch] $SkipCertificateCheck
    )

    BEGIN 
    {
        if (!$MetadataUri)
        {
            $Uri = $Uri.TrimEnd('/')
            $MetadataUri = $Uri + '/$metadata'
            $PSBoundParameters["MetadataUri"] = $MetadataUri
        }

        # Validate to make sure that a valid URI is supplied as input.
        try
        {
            $connectionUri = [System.Uri]::new($Uri)
        }
        catch
        {
            $errorMessage = ($LocalizedData.InValidUri -f $Uri)
            $exception = [System.InvalidOperationException]::new($errorMessage, $_.Exception)
            $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyInvalidUriFormat" $null ([System.Management.Automation.ErrorCategory]::InvalidArgument) $exception $Uri
            $PSCmdlet.ThrowTerminatingError($errorRecord)
        }
        
        if($connectionUri.Scheme -eq "http" -and !$AllowUnsecureConnection.IsPresent)
        {
            $errorMessage = ($LocalizedData.AllowUnsecureConnectionMessage -f $PSCmdlet.MyInvocation.MyCommand.Name, $Uri, "Uri")
            $exception = [System.InvalidOperationException]::new($errorMessage, $_.Exception)
            $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyUnSecureConnection" $null ([System.Management.Automation.ErrorCategory]::InvalidArgument) $exception $Uri
            $PSCmdlet.ThrowTerminatingError($errorRecord)
        }

        $OutputModuleExists = Test-Path -Path $OutputModule -PathType Container

        if($OutputModuleExists -and ($Force -eq $false))
        {
            $errorMessage = ($LocalizedData.ModuleAlreadyExistsAndForceParameterIsNotSpecified -f $OutputModule)
            $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyOutputModuleExists" $errorMessage ([System.Management.Automation.ErrorCategory]::ResourceExists) $null $OutputModule
            $PSCmdlet.ThrowTerminatingError($errorRecord)
        }
        
        $isWhatIf = $psboundparameters.ContainsKey("WhatIf")

        if(!$OutputModuleExists)
        {
            if(!$isWhatIf)
            {
                $OutputModule = (New-Item -Path $OutputModule -ItemType Directory).FullName
            }
        }
        else
        {
            $resolvedOutputModulePath = Resolve-Path -Path $OutputModule -ErrorAction Stop -Verbose
            if($resolvedOutputModulePath.Count -gt 1)
            {    
                $errorMessage = ($LocalizedData.OutputModulePathIsNotUnique -f $OutputModule)
                $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyOutputModulePathIsNotUnique" $errorMessage ([System.Management.Automation.ErrorCategory]::InvalidArgument) $null $OutputModule
                $PSCmdlet.ThrowTerminatingError($errorRecord)
            }
            
            # Make sure that the path specified is a valid file system directory path.
            if([system.IO.Directory]::Exists($resolvedOutputModulePath))
            {
                $OutputModule = $resolvedOutputModulePath
            }
            else
            {
                $errorMessage = ($LocalizedData.OutputModulePathIsNotFileSystemPath -f $OutputModule)
                $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyPathIsNotFileSystemPath" $errorMessage ([System.Management.Automation.ErrorCategory]::InvalidArgument) $null $OutputModule
                $PSCmdlet.ThrowTerminatingError($errorRecord)
            } 
        }

        $rootDir = [System.IO.Directory]::GetDirectoryRoot($OutputModule)

        if($rootDir -eq $OutputModule)
        {
            $errorMessage = ($LocalizedData.InvalidOutputModulePath -f $OutputModule)
            $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyInvalidOutputModulePath" $errorMessage ([System.Management.Automation.ErrorCategory]::InvalidArgument) $null $OutputModule
            $PSCmdlet.ThrowTerminatingError($errorRecord)
        }

        if(!$isWhatIf)
        {
            $progressBarStatus = ($LocalizedData.ProgressBarMessage -f $Uri)
            ProgressBarHelper "Export-ODataEndpointProxy" $progressBarStatus 0 100 100 1
        }

        # Add parameters to $PSBoundParameters, which were not passed by user, but the default value is set
        $parametersWithDefaultValue = @("CreateRequestMethod", "UpdateRequestMethod", "CmdletAdapter")

        foreach ($parameterWithDefaultValue in $parametersWithDefaultValue)
        {
            if (!$PSBoundParameters.ContainsKey($parameterWithDefaultValue))
            {
                $PSBoundParameters.Add($parameterWithDefaultValue, (Get-Variable $parameterWithDefaultValue).Value)
            }
        }
    }

    END 
    {
        if($pscmdlet.ShouldProcess($Uri))
        {
            try
            {
                $PSBoundParameters.Add("ProgressBarStatus", $progressBarStatus)
                $PSBoundParameters.Add("PSCmdlet", $PSCmdlet)

                # Import module based on selected CmdletAdapter
                $adapterToImport = $CmdletAdapter
                
                # NetworkControllerAdapter relies on ODataAdapter
                if ($CmdletAdapter -eq 'NetworkControllerAdapter')
                {
                    $adapterToImport = 'ODataAdapter'
                }

                # According to Redfish specification DSP0266v1.0.1 Redfish Service Metadata Document and Redfish Service Root URIs (used by Export-ODataEndpointProxy) are required to start with '/redfish/v1' (section "6.3 Redfish-Defined URIs and Relative URI Rules").
                # We use this as indicator of whether Export-ODataEndpointProxy was attempted against a Redfish endpoint.
                if ($connectionUri.AbsolutePath.StartsWith('/redfish/',[StringComparison]::OrdinalIgnoreCase))
                {
                    $adapterToImport = 'RedfishAdapter'
                }
 
                Write-Debug ($LocalizedData.SelectedAdapter -f $adapterPSScript)

                $adapterPSScript = "$PSScriptRoot\Microsoft.PowerShell." + $adapterToImport + ".ps1"
                
                . $adapterPSScript
                ExportODataEndpointProxy @PSBoundParameters
            }
            catch
            {
                if ($adapterToImport -eq 'RedfishAdapter')
                {
                    throw
                }
                else
                {
                    $errorMessage = ($LocalizedData.InValidMetadata -f $Uri)
                    $exception = [System.InvalidOperationException]::new($errorMessage, $_.Exception)
                    $errorRecord = CreateErrorRecordHelper "ODataEndpointProxyInvalidInput" $null ([System.Management.Automation.ErrorCategory]::InvalidData) $exception $Uri
                    $PSCmdlet.ThrowTerminatingError($errorRecord)
                }
            }
            finally
            {
                Write-Progress -Activity "Export-ODataEndpointProxy" -Completed
            }
        }
    }
}

Export-ModuleMember -Function @('Export-ODataEndpointProxy')

# SIG # Begin signature block
# MIIasAYJKoZIhvcNAQcCoIIaoTCCGp0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUlMx0XSI94ZuGL1cR4kNLyfnd
# iqOgghWDMIIEwzCCA6ugAwIBAgITMwAAALgYPKjXA3t9ggAAAAAAuDANBgkqhkiG
# 9w0BAQUFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw
# HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwHhcNMTYwOTA3MTc1ODQ1
# WhcNMTgwOTA3MTc1ODQ1WjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjENMAsGA1UECxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNO
# OjdEMkUtMzc4Mi1CMEY3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT
# ZXJ2aWNlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnaLG0E/Tu86w
# owRN6AiltXrcmafSmbdl78ODWZEpnPV2rV91m1UxxEVn7L1gt/exIySWKBgy0zIH
# XIXBnVmOO7s8588G/Qq0f7pLzFnfFXFBzDBlVgVHmB7Ak/SQ66Is5TEqd0TyF9ff
# Gv2ooVfaWe2S4RXSp7lhQfB7oH4e2jevuq95SAdNGFkzOhJqmxuaFpU9rXDJqKPx
# QTqvv8qfnaKZBfQre8sfpaFbJOpaZgx0zWcCL4OKtxiRaC1SwPn7PUoT6aXD1lbQ
# 2A1aXm1RelZDXObiflpUSLnSZEKs37JvErwzoIIz1jA2DT8UfEUBfO+0NLRogoL/
# 87WD7Bv5fQIDAQABo4IBCTCCAQUwHQYDVR0OBBYEFJG/eoXgR5qRzeoSYD0njQuK
# MU6CMB8GA1UdIwQYMBaAFCM0+NlSRnAK7UD7dvuzK7DDNbMPMFQGA1UdHwRNMEsw
# SaBHoEWGQ2h0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3Rz
# L01pY3Jvc29mdFRpbWVTdGFtcFBDQS5jcmwwWAYIKwYBBQUHAQEETDBKMEgGCCsG
# AQUFBzAChjxodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY3Jv
# c29mdFRpbWVTdGFtcFBDQS5jcnQwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZI
# hvcNAQEFBQADggEBACNjoS6XJKHJZbomlN/SYgCUqHRYj2pE3Gad4Ey0L5lo2o0w
# pbIXKvWLcuRw4HjGQOeu59IPh2YoJszmbiMYeGI7fAan95UyvaLC1TJ8bdljy5nF
# tQCuxVP0RfhNrp9DYNs2baYB7FIe9DQ3fjb3OuoEYIcjFAl8JEX/l5ANWcS1n9SN
# KagAdS/9piabhNUutyV4xb5HuQXBiXZZmHzYLdenq+SkHYlL1/Yu2Hx6Dx2d/CCh
# oLLfMJ+9bTinZLxL6kL75Nv08HyBlilnpgDMO30o8M/udMfcIj8BszosMJ84cTw+
# QR7BgiBbz2Lkk3UufsxgSSggcyhpJH8MlwgoLoEwggTtMIID1aADAgECAhMzAAAB
# QJap7nBW/swHAAEAAAFAMA0GCSqGSIb3DQEBBQUAMHkxCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xIzAhBgNVBAMTGk1pY3Jvc29mdCBDb2RlIFNp
# Z25pbmcgUENBMB4XDTE2MDgxODIwMTcxN1oXDTE3MTEwMjIwMTcxN1owgYMxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xDTALBgNVBAsTBE1PUFIx
# HjAcBgNVBAMTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjCCASIwDQYJKoZIhvcNAQEB
# BQADggEPADCCAQoCggEBANtLi+kDal/IG10KBTnk1Q6S0MThi+ikDQUZWMA81ynd
# ibdobkuffryavVSGOanxODUW5h2s+65r3Akw77ge32z4SppVl0jII4mzWSc0vZUx
# R5wPzkA1Mjf+6fNPpBqks3m8gJs/JJjE0W/Vf+dDjeTc8tLmrmbtBDohlKZX3APb
# LMYb/ys5qF2/Vf7dSd9UBZSrM9+kfTGmTb1WzxYxaD+Eaxxt8+7VMIruZRuetwgc
# KX6TvfJ9QnY4ItR7fPS4uXGew5T0goY1gqZ0vQIz+lSGhaMlvqqJXuI5XyZBmBre
# ueZGhXi7UTICR+zk+R+9BFF15hKbduuFlxQiCqET92ECAwEAAaOCAWEwggFdMBMG
# A1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBSc5ehtgleuNyTe6l6pxF+QHc7Z
# ezBSBgNVHREESzBJpEcwRTENMAsGA1UECxMETU9QUjE0MDIGA1UEBRMrMjI5ODAz
# K2Y3ODViMWMwLTVkOWYtNDMxNi04ZDZhLTc0YWU2NDJkZGUxYzAfBgNVHSMEGDAW
# gBTLEejK0rQWWAHJNy4zFha5TJoKHzBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8v
# Y3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNDb2RTaWdQQ0Ff
# MDgtMzEtMjAxMC5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY0NvZFNpZ1BDQV8wOC0z
# MS0yMDEwLmNydDANBgkqhkiG9w0BAQUFAAOCAQEAa+RW49cTHSBA+W3p3k7bXR7G
# bCaj9+UJgAz/V+G01Nn5XEjhBn/CpFS4lnr1jcmDEwxxv/j8uy7MFXPzAGtOJar0
# xApylFKfd00pkygIMRbZ3250q8ToThWxmQVEThpJSSysee6/hU+EbkfvvtjSi0lp
# DimD9aW9oxshraKlPpAgnPWfEj16WXVk79qjhYQyEgICamR3AaY5mLPuoihJbKwk
# Mig+qItmLPsC2IMvI5KR91dl/6TV6VEIlPbW/cDVwCBF/UNJT3nuZBl/YE7ixMpT
# Th/7WpENW80kg3xz6MlCdxJfMSbJsM5TimFU98KNcpnxxbYdfqqQhAQ6l3mtYDCC
# BbwwggOkoAMCAQICCmEzJhoAAAAAADEwDQYJKoZIhvcNAQEFBQAwXzETMBEGCgmS
# JomT8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEtMCsGA1UE
# AxMkTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDgz
# MTIyMTkzMloXDTIwMDgzMTIyMjkzMloweTELMAkGA1UEBhMCVVMxEzARBgNVBAgT
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjEjMCEGA1UEAxMaTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQ
# Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCycllcGTBkvx2aYCAg
# Qpl2U2w+G9ZvzMvx6mv+lxYQ4N86dIMaty+gMuz/3sJCTiPVcgDbNVcKicquIEn0
# 8GisTUuNpb15S3GbRwfa/SXfnXWIz6pzRH/XgdvzvfI2pMlcRdyvrT3gKGiXGqel
# cnNW8ReU5P01lHKg1nZfHndFg4U4FtBzWwW6Z1KNpbJpL9oZC/6SdCnidi9U3RQw
# WfjSjWL9y8lfRjFQuScT5EAwz3IpECgixzdOPaAyPZDNoTgGhVxOVoIoKgUyt0vX
# T2Pn0i1i8UU956wIAPZGoZ7RW4wmU+h6qkryRs83PDietHdcpReejcsRj1Y8wawJ
# XwPTAgMBAAGjggFeMIIBWjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTLEejK
# 0rQWWAHJNy4zFha5TJoKHzALBgNVHQ8EBAMCAYYwEgYJKwYBBAGCNxUBBAUCAwEA
# ATAjBgkrBgEEAYI3FQIEFgQU/dExTtMmipXhmGA7qDFvpjy82C0wGQYJKwYBBAGC
# NxQCBAweCgBTAHUAYgBDAEEwHwYDVR0jBBgwFoAUDqyCYEBWJ5flJRP8KuEKU5VZ
# 5KQwUAYDVR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3Br
# aS9jcmwvcHJvZHVjdHMvbWljcm9zb2Z0cm9vdGNlcnQuY3JsMFQGCCsGAQUFBwEB
# BEgwRjBEBggrBgEFBQcwAoY4aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9j
# ZXJ0cy9NaWNyb3NvZnRSb290Q2VydC5jcnQwDQYJKoZIhvcNAQEFBQADggIBAFk5
# Pn8mRq/rb0CxMrVq6w4vbqhJ9+tfde1MOy3XQ60L/svpLTGjI8x8UJiAIV2sPS9M
# uqKoVpzjcLu4tPh5tUly9z7qQX/K4QwXaculnCAt+gtQxFbNLeNK0rxw56gNogOl
# VuC4iktX8pVCnPHz7+7jhh80PLhWmvBTI4UqpIIck+KUBx3y4k74jKHK6BOlkU7I
# G9KPcpUqcW2bGvgc8FPWZ8wi/1wdzaKMvSeyeWNWRKJRzfnpo1hW3ZsCRUQvX/Ta
# rtSCMm78pJUT5Otp56miLL7IKxAOZY6Z2/Wi+hImCWU4lPF6H0q70eFW6NB4lhhc
# yTUWX92THUmOLb6tNEQc7hAVGgBd3TVbIc6YxwnuhQ6MT20OE049fClInHLR82zK
# wexwo1eSV32UjaAbSANa98+jZwp0pTbtLS8XyOZyNxL0b7E8Z4L5UrKNMxZlHg6K
# 3RDeZPRvzkbU0xfpecQEtNP7LN8fip6sCvsTJ0Ct5PnhqX9GuwdgR2VgQE6wQuxO
# 7bN2edgKNAltHIAxH+IOVN3lofvlRxCtZJj/UBYufL8FIXrilUEnacOTj5XJjdib
# Ia4NXJzwoq6GaIMMai27dmsAHZat8hZ79haDJLmIz2qoRzEvmtzjcT3XAH5iR9HO
# iMm4GPoOco3Boz2vAkBq/2mbluIQqBC0N1AI1sM9MIIGBzCCA++gAwIBAgIKYRZo
# NAAAAAAAHDANBgkqhkiG9w0BAQUFADBfMRMwEQYKCZImiZPyLGQBGRYDY29tMRkw
# FwYKCZImiZPyLGQBGRYJbWljcm9zb2Z0MS0wKwYDVQQDEyRNaWNyb3NvZnQgUm9v
# dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcwNDAzMTI1MzA5WhcNMjEwNDAz
# MTMwMzA5WjB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw
# HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwggEiMA0GCSqGSIb3DQEB
# AQUAA4IBDwAwggEKAoIBAQCfoWyx39tIkip8ay4Z4b3i48WZUSNQrc7dGE4kD+7R
# p9FMrXQwIBHrB9VUlRVJlBtCkq6YXDAm2gBr6Hu97IkHD/cOBJjwicwfyzMkh53y
# 9GccLPx754gd6udOo6HBI1PKjfpFzwnQXq/QsEIEovmmbJNn1yjcRlOwhtDlKEYu
# J6yGT1VSDOQDLPtqkJAwbofzWTCd+n7Wl7PoIZd++NIT8wi3U21StEWQn0gASkdm
# EScpZqiX5NMGgUqi+YSnEUcUCYKfhO1VeP4Bmh1QCIUAEDBG7bfeI0a7xC1Un68e
# eEExd8yb3zuDk6FhArUdDbH895uyAc4iS1T/+QXDwiALAgMBAAGjggGrMIIBpzAP
# BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQjNPjZUkZwCu1A+3b7syuwwzWzDzAL
# BgNVHQ8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwgZgGA1UdIwSBkDCBjYAUDqyC
# YEBWJ5flJRP8KuEKU5VZ5KShY6RhMF8xEzARBgoJkiaJk/IsZAEZFgNjb20xGTAX
# BgoJkiaJk/IsZAEZFgltaWNyb3NvZnQxLTArBgNVBAMTJE1pY3Jvc29mdCBSb290
# IENlcnRpZmljYXRlIEF1dGhvcml0eYIQea0WoUqgpa1Mc1j0BxMuZTBQBgNVHR8E
# STBHMEWgQ6BBhj9odHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9k
# dWN0cy9taWNyb3NvZnRyb290Y2VydC5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsG
# AQUFBzAChjhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY3Jv
# c29mdFJvb3RDZXJ0LmNydDATBgNVHSUEDDAKBggrBgEFBQcDCDANBgkqhkiG9w0B
# AQUFAAOCAgEAEJeKw1wDRDbd6bStd9vOeVFNAbEudHFbbQwTq86+e4+4LtQSooxt
# YrhXAstOIBNQmd16QOJXu69YmhzhHQGGrLt48ovQ7DsB7uK+jwoFyI1I4vBTFd1P
# q5Lk541q1YDB5pTyBi+FA+mRKiQicPv2/OR4mS4N9wficLwYTp2OawpylbihOZxn
# LcVRDupiXD8WmIsgP+IHGjL5zDFKdjE9K3ILyOpwPf+FChPfwgphjvDXuBfrTot/
# xTUrXqO/67x9C0J71FNyIe4wyrt4ZVxbARcKFA7S2hSY9Ty5ZlizLS/n+YWGzFFW
# 6J1wlGysOUzU9nm/qhh6YinvopspNAZ3GmLJPR5tH4LwC8csu89Ds+X57H2146So
# dDW4TsVxIxImdgs8UoxxWkZDFLyzs7BNZ8ifQv+AeSGAnhUwZuhCEl4ayJ4iIdBD
# 6Svpu/RIzCzU2DKATCYqSCRfWupW76bemZ3KOm+9gSd0BhHudiG/m4LBJ1S2sWo9
# iaF2YbRuoROmv6pH8BJv/YoybLL+31HIjCPJZr2dHYcSZAI9La9Zj7jkIeW1sMpj
# tHhUBdRBLlCslLCleKuzoJZ1GtmShxN1Ii8yqAhuoFuMJb+g74TKIdbrHk/Jmu5J
# 4PcBZW+JC33Iacjmbuqnl84xKf8OxVtc2E0bodj6L54/LlUWa8kTo/0xggSXMIIE
# kwIBATCBkDB5MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSMw
# IQYDVQQDExpNaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQQITMwAAAUCWqe5wVv7M
# BwABAAABQDAJBgUrDgMCGgUAoIGwMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEE
# MBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBSr
# +bWUCJ5B1ZJ8ErdXR152ZzrUnDBQBgorBgEEAYI3AgEMMUIwQKAWgBQAUABvAHcA
# ZQByAFMAaABlAGwAbKEmgCRodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vUG93ZXJT
# aGVsbCAwDQYJKoZIhvcNAQEBBQAEggEAFdbF1eZaWCWukJ0S3M+dObqQVMbzPats
# LUObgROBKp8esCTaiX7VbJRuw460fIJbkGmYH1Fzf3BEwRJsUktdvLpxGEkyCjtQ
# 2vmPdGAFDexocL8BuC1cZDlCI5W1mJ3By7IdyqgxiIpzp0gnZX6sFYL8/6+gptFk
# sZhVrMKSSWAOq3RoOwcbmT6mnxSQH2P3PkqVGGbDjDls3F9V/tyStCDsQNn5sfpl
# MOgH+VeKpIQSMrZ47WSPvPkBYiRi+mBBzPvxwa+/TzDK4MdqpWd+ndcXduPlK1BD
# McASJwyMa0nvdTt138AkvKb2ul4uMVS0lwiFXdzoc1FTogGATEM09qGCAigwggIk
# BgkqhkiG9w0BCQYxggIVMIICEQIBATCBjjB3MQswCQYDVQQGEwJVUzETMBEGA1UE
# CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z
# b2Z0IENvcnBvcmF0aW9uMSEwHwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQ
# Q0ECEzMAAAC4GDyo1wN7fYIAAAAAALgwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJ
# AzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE2MTAyODIxNDU1N1owIwYJ
# KoZIhvcNAQkEMRYEFIv0cjEeHBcQOQouIEbBNIEUEYSWMA0GCSqGSIb3DQEBBQUA
# BIIBAGAEHJq29A3xymOYrGTBkvx3djeK3scDUXmqptwInULQVPdLJdRRjvUHF340
# KYK0h6ffjYigvcVHjaOT4RH2Z1T6Ess9y2Hqzp7TX6SWRpmMzlEi9b117ypnJ0++
# j+8LqXjSM3LGR+73UNoBBkKisd8NaSmiezO6Mq39ebznaitselGfOPgkYckYVjqI
# 2LVGizlZynv2gdYuMBnUyWsIfxGtw1zSVMopov9sr9gWWSuezZX1SV5WjMpkDBS+
# 0FBamL2WKnaQDBPHge2T/YahFtw9Jzl29An9MKMKJoe+ZkutBZ7tgzMVN0l+8TJj
# gjb4k41VKSzfuVERpTfOO9dI0yM=
# SIG # End signature block