winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

PowerShellGet.ResourceHelper.psm1 (27387B)


      1 #
      2 # Copyright (c) Microsoft Corporation.
      3 #
      4 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      5 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      6 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      7 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      8 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      9 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     10 # THE SOFTWARE.
     11 #
     12 
     13 <#
     14     Helper functions for PowerShellGet DSC Resources.
     15 #>
     16 
     17 # Import localization helper functions.
     18 $helperName = 'PowerShellGet.LocalizationHelper'
     19 $resourceModuleRoot = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent
     20 $dscResourcesFolderFilePath = Join-Path -Path $resourceModuleRoot -ChildPath "Modules\$helperName\$helperName.psm1"
     21 Import-Module -Name $dscResourcesFolderFilePath
     22 
     23 # Import Localization Strings
     24 $script:localizedData = Get-LocalizedData -ResourceName 'PowerShellGet.ResourceHelper' -ScriptRoot $PSScriptRoot
     25 
     26 <#
     27     .SYNOPSIS
     28         This is a helper function that extract the parameters from a given table.
     29 
     30     .PARAMETER FunctionBoundParameters
     31         Specifies the hash table containing a set of parameters to be extracted.
     32 
     33     .PARAMETER ArgumentNames
     34         Specifies a list of arguments you want to extract.
     35 #>
     36 function New-SplatParameterHashTable {
     37     [CmdletBinding()]
     38     [OutputType([System.Collections.Hashtable])]
     39     param
     40     (
     41         [Parameter(Mandatory = $true)]
     42         [System.Collections.Hashtable]
     43         $FunctionBoundParameters,
     44 
     45         [Parameter(Mandatory = $true)]
     46         [System.String[]]
     47         $ArgumentNames
     48     )
     49 
     50     Write-Verbose -Message ($script:localizedData.CallingFunction -f $($MyInvocation.MyCommand))
     51 
     52     $returnValue = @{}
     53 
     54     foreach ($arg in $ArgumentNames) {
     55         if ($FunctionBoundParameters.ContainsKey($arg)) {
     56             # Found an argument we are looking for, so we add it to return collection.
     57             $returnValue.Add($arg, $FunctionBoundParameters[$arg])
     58         }
     59     }
     60 
     61     return $returnValue
     62 }
     63 
     64 <#
     65     .SYNOPSIS
     66         This is a helper function that validate that a value is correct and used correctly.
     67 
     68     .PARAMETER Value
     69         Specifies the value to be validated.
     70 
     71     .PARAMETER Type
     72         Specifies the type of argument.
     73 
     74     .PARAMETER Type
     75         Specifies the name of the provider.
     76 
     77     .OUTPUTS
     78         None. Throws an error if the test fails.
     79 #>
     80 function Test-ParameterValue {
     81     [CmdletBinding()]
     82     param
     83     (
     84         [Parameter(Mandatory = $true)]
     85         [ValidateNotNullOrEmpty()]
     86         [System.String]
     87         $Value,
     88 
     89         [Parameter(Mandatory = $true)]
     90         [ValidateNotNullOrEmpty()]
     91         [System.String]
     92         $Type,
     93 
     94         [Parameter(Mandatory = $true)]
     95         [ValidateNotNullOrEmpty()]
     96         [System.String]
     97         $ProviderName
     98     )
     99 
    100     Write-Verbose -Message ($script:localizedData.CallingFunction -f $($MyInvocation.MyCommand))
    101 
    102     switch ($Type) {
    103         'SourceUri' {
    104             # Checks whether given URI represents specific scheme
    105             # Most common schemes: file, http, https, ftp
    106             $scheme = @('http', 'https', 'file', 'ftp')
    107 
    108             $newUri = $Value -as [System.URI]
    109             $returnValue = ($newUri -and $newUri.AbsoluteURI -and ($scheme -icontains $newUri.Scheme))
    110 
    111             if ($returnValue -eq $false) {
    112                 $errorMessage = $script:localizedData.InValidUri -f $Value
    113                 New-InvalidArgumentException -ArgumentName $Type -Message $errorMessage
    114             }
    115         }
    116 
    117         'DestinationPath' {
    118             $returnValue = Test-Path -Path $Value
    119 
    120             if ($returnValue -eq $false) {
    121                 $errorMessage = $script:localizedData.PathDoesNotExist -f $Value
    122                 New-InvalidArgumentException -ArgumentName $Type -Message $errorMessage
    123             }
    124         }
    125 
    126         'PackageSource' {
    127             # Value can be either the package source Name or source Uri.
    128 
    129             # Check if the source is a Uri.
    130             $uri = $Value -as [System.URI]
    131 
    132             if ($uri -and $uri.AbsoluteURI) {
    133                 # Check if it's a valid Uri.
    134                 Test-ParameterValue -Value $Value -Type 'SourceUri' -ProviderName $ProviderName
    135             }
    136             else {
    137                 # Check if it's a registered package source name.
    138                 $source = PackageManagement\Get-PackageSource -Name $Value -ProviderName $ProviderName -ErrorVariable ev
    139 
    140                 if ((-not $source) -or $ev) {
    141                     # We do not need to throw error here as Get-PackageSource does already.
    142                     Write-Verbose -Message ($script:localizedData.SourceNotFound -f $source)
    143                 }
    144             }
    145         }
    146 
    147         default {
    148             $errorMessage = $script:localizedData.UnexpectedArgument -f $Type
    149             New-InvalidArgumentException -ArgumentName $Type -Message $errorMessage
    150         }
    151     }
    152 }
    153 
    154 <#
    155     .SYNOPSIS
    156         This is a helper function that does the version validation.
    157 
    158     .PARAMETER RequiredVersion
    159         Provides the required version.
    160 
    161     .PARAMETER MaximumVersion
    162         Provides the maximum version.
    163 
    164     .PARAMETER MinimumVersion
    165         Provides the minimum version.
    166 #>
    167 function Test-VersionParameter {
    168     [CmdletBinding()]
    169     param
    170     (
    171         [Parameter()]
    172         [System.String]
    173         $RequiredVersion,
    174 
    175         [Parameter()]
    176         [System.String]
    177         $MinimumVersion,
    178 
    179         [Parameter()]
    180         [System.String]
    181         $MaximumVersion
    182     )
    183 
    184     Write-Verbose -Message ($localizedData.CallingFunction -f $($MyInvocation.MyCommand))
    185 
    186     $isValid = $false
    187 
    188     # Case 1: No further check required if a user provides either none or one of these: minimumVersion, maximumVersion, and requiredVersion.
    189     if ($PSBoundParameters.Count -le 1) {
    190         return $true
    191     }
    192 
    193     # Case 2: #If no RequiredVersion is provided.
    194     if (-not $PSBoundParameters.ContainsKey('RequiredVersion')) {
    195         # If no RequiredVersion, both MinimumVersion and MaximumVersion are provided. Otherwise fall into the Case #1.
    196         $isValid = $PSBoundParameters['MinimumVersion'] -le $PSBoundParameters['MaximumVersion']
    197     }
    198 
    199     # Case 3: RequiredVersion is provided.
    200     #        In this case  MinimumVersion and/or MaximumVersion also are provided. Otherwise fall in to Case #1.
    201     #        This is an invalid case. When RequiredVersion is provided, others are not allowed. so $isValid is false, which is already set in the init.
    202 
    203     if ($isValid -eq $false) {
    204         $errorMessage = $script:localizedData.VersionError
    205         New-InvalidArgumentException `
    206             -ArgumentName 'RequiredVersion, MinimumVersion or MaximumVersion' `
    207             -Message $errorMessage
    208     }
    209 }
    210 
    211 <#
    212     .SYNOPSIS
    213         This is a helper function that retrieves the InstallationPolicy from the given repository.
    214 
    215     .PARAMETER RepositoryName
    216         Provides the repository Name.
    217 #>
    218 function Get-InstallationPolicy {
    219     [CmdletBinding()]
    220     param
    221     (
    222         [Parameter(Mandatory = $true)]
    223         [ValidateNotNullOrEmpty()]
    224         [System.String] $RepositoryName
    225     )
    226 
    227     Write-Verbose -Message ($LocalizedData.CallingFunction -f $($MyInvocation.MyCommand))
    228 
    229     $repositoryObject = PackageManagement\Get-PackageSource -Name $RepositoryName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
    230 
    231     if ($repositoryObject) {
    232         return $repositoryObject.IsTrusted
    233     }
    234 }
    235 
    236 <#
    237     .SYNOPSIS
    238         This method is used to compare current and desired values for any DSC resource.
    239 
    240     .PARAMETER CurrentValues
    241         This is hash table of the current values that are applied to the resource.
    242 
    243     .PARAMETER DesiredValues
    244         This is a PSBoundParametersDictionary of the desired values for the resource.
    245 
    246     .PARAMETER ValuesToCheck
    247         This is a list of which properties in the desired values list should be checked.
    248         If this is empty then all values in DesiredValues are checked.
    249 #>
    250 function Test-DscParameterState {
    251     [CmdletBinding()]
    252     param
    253     (
    254         [Parameter(Mandatory = $true)]
    255         [System.Collections.Hashtable]
    256         $CurrentValues,
    257 
    258         [Parameter(Mandatory = $true)]
    259         [System.Object]
    260         $DesiredValues,
    261 
    262         [Parameter()]
    263         [System.Array]
    264         $ValuesToCheck
    265     )
    266 
    267     $returnValue = $true
    268 
    269     if (($DesiredValues.GetType().Name -ne 'HashTable') `
    270             -and ($DesiredValues.GetType().Name -ne 'CimInstance') `
    271             -and ($DesiredValues.GetType().Name -ne 'PSBoundParametersDictionary')) {
    272         $errorMessage = $script:localizedData.PropertyTypeInvalidForDesiredValues -f $($DesiredValues.GetType().Name)
    273         New-InvalidArgumentException -ArgumentName 'DesiredValues' -Message $errorMessage
    274     }
    275 
    276     if (($DesiredValues.GetType().Name -eq 'CimInstance') -and ($null -eq $ValuesToCheck)) {
    277         $errorMessage = $script:localizedData.PropertyTypeInvalidForValuesToCheck
    278         New-InvalidArgumentException -ArgumentName 'ValuesToCheck' -Message $errorMessage
    279     }
    280 
    281     if (($null -eq $ValuesToCheck) -or ($ValuesToCheck.Count -lt 1)) {
    282         $keyList = $DesiredValues.Keys
    283     }
    284     else {
    285         $keyList = $ValuesToCheck
    286     }
    287 
    288     $keyList | ForEach-Object -Process {
    289         if (($_ -ne 'Verbose')) {
    290             if (($CurrentValues.ContainsKey($_) -eq $false) `
    291                     -or ($CurrentValues.$_ -ne $DesiredValues.$_) `
    292                     -or (($DesiredValues.GetType().Name -ne 'CimInstance' -and $DesiredValues.ContainsKey($_) -eq $true) -and ($null -ne $DesiredValues.$_ -and $DesiredValues.$_.GetType().IsArray))) {
    293                 if ($DesiredValues.GetType().Name -eq 'HashTable' -or `
    294                         $DesiredValues.GetType().Name -eq 'PSBoundParametersDictionary') {
    295                     $checkDesiredValue = $DesiredValues.ContainsKey($_)
    296                 }
    297                 else {
    298                     # If DesiredValue is a CimInstance.
    299                     $checkDesiredValue = $false
    300                     if (([System.Boolean]($DesiredValues.PSObject.Properties.Name -contains $_)) -eq $true) {
    301                         if ($null -ne $DesiredValues.$_) {
    302                             $checkDesiredValue = $true
    303                         }
    304                     }
    305                 }
    306 
    307                 if ($checkDesiredValue) {
    308                     $desiredType = $DesiredValues.$_.GetType()
    309                     $fieldName = $_
    310                     if ($desiredType.IsArray -eq $true) {
    311                         if (($CurrentValues.ContainsKey($fieldName) -eq $false) `
    312                                 -or ($null -eq $CurrentValues.$fieldName)) {
    313                             Write-Verbose -Message ($script:localizedData.PropertyValidationError -f $fieldName) -Verbose
    314 
    315                             $returnValue = $false
    316                         }
    317                         else {
    318                             $arrayCompare = Compare-Object -ReferenceObject $CurrentValues.$fieldName `
    319                                 -DifferenceObject $DesiredValues.$fieldName
    320                             if ($null -ne $arrayCompare) {
    321                                 Write-Verbose -Message ($script:localizedData.PropertiesDoesNotMatch -f $fieldName) -Verbose
    322 
    323                                 $arrayCompare | ForEach-Object -Process {
    324                                     Write-Verbose -Message ($script:localizedData.PropertyThatDoesNotMatch -f $_.InputObject, $_.SideIndicator) -Verbose
    325                                 }
    326 
    327                                 $returnValue = $false
    328                             }
    329                         }
    330                     }
    331                     else {
    332                         switch ($desiredType.Name) {
    333                             'String' {
    334                                 if (-not [System.String]::IsNullOrEmpty($CurrentValues.$fieldName) -or `
    335                                         -not [System.String]::IsNullOrEmpty($DesiredValues.$fieldName)) {
    336                                     Write-Verbose -Message ($script:localizedData.ValueOfTypeDoesNotMatch `
    337                                             -f $desiredType.Name, $fieldName, $($CurrentValues.$fieldName), $($DesiredValues.$fieldName)) -Verbose
    338 
    339                                     $returnValue = $false
    340                                 }
    341                             }
    342 
    343                             'Int32' {
    344                                 if (-not ($DesiredValues.$fieldName -eq 0) -or `
    345                                         -not ($null -eq $CurrentValues.$fieldName)) {
    346                                     Write-Verbose -Message ($script:localizedData.ValueOfTypeDoesNotMatch `
    347                                             -f $desiredType.Name, $fieldName, $($CurrentValues.$fieldName), $($DesiredValues.$fieldName)) -Verbose
    348 
    349                                     $returnValue = $false
    350                                 }
    351                             }
    352 
    353                             { $_ -eq 'Int16' -or $_ -eq 'UInt16'} {
    354                                 if (-not ($DesiredValues.$fieldName -eq 0) -or `
    355                                         -not ($null -eq $CurrentValues.$fieldName)) {
    356                                     Write-Verbose -Message ($script:localizedData.ValueOfTypeDoesNotMatch `
    357                                             -f $desiredType.Name, $fieldName, $($CurrentValues.$fieldName), $($DesiredValues.$fieldName)) -Verbose
    358 
    359                                     $returnValue = $false
    360                                 }
    361                             }
    362 
    363                             default {
    364                                 Write-Warning -Message ($script:localizedData.UnableToCompareProperty `
    365                                         -f $fieldName, $desiredType.Name)
    366 
    367                                 $returnValue = $false
    368                             }
    369                         }
    370                     }
    371                 }
    372             }
    373         }
    374     }
    375 
    376     return $returnValue
    377 }
    378 
    379 # SIG # Begin signature block
    380 # MIIjkgYJKoZIhvcNAQcCoIIjgzCCI38CAQExDzANBglghkgBZQMEAgEFADB5Bgor
    381 # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
    382 # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBH3QB1YDOZOOwJ
    383 # V+KQVBF6PeRCZ7EOOlwmL67tD15ypKCCDYEwggX/MIID56ADAgECAhMzAAABh3IX
    384 # chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
    385 # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
    386 # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
    387 # bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw
    388 # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
    389 # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
    390 # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
    391 # AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB
    392 # znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH
    393 # sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d
    394 # weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ
    395 # itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV
    396 # Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
    397 # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw
    398 # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
    399 # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu
    400 # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
    401 # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
    402 # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
    403 # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
    404 # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy
    405 # S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K
    406 # NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV
    407 # BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr
    408 # qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx
    409 # zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe
    410 # yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g
    411 # yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf
    412 # AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI
    413 # 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5
    414 # GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea
    415 # jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS
    416 # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
    417 # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
    418 # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
    419 # ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
    420 # MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
    421 # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
    422 # H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
    423 # AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
    424 # OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
    425 # 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
    426 # y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
    427 # 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
    428 # M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
    429 # X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
    430 # XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
    431 # 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
    432 # l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
    433 # RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
    434 # CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
    435 # BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
    436 # DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
    437 # 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
    438 # LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
    439 # Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
    440 # Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
    441 # Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
    442 # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
    443 # cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
    444 # XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
    445 # 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
    446 # 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
    447 # d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
    448 # Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
    449 # wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
    450 # aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
    451 # NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
    452 # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
    453 # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
    454 # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
    455 # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZzCCFWMCAQEwgZUwfjELMAkG
    456 # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
    457 # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
    458 # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN
    459 # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
    460 # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgAchP/Cco
    461 # Y2JAjut9Hy3IC65/Rf67ea66bxFJosTcn0EwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
    462 # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
    463 # BgkqhkiG9w0BAQEFAASCAQCA7tKfqWfEy22S/6wr4OyvRkvECIOlgOTLpZGyP7iT
    464 # 16UqNis22r/tHfj0nQMVembrz5WOUvHZPrU72+fJAZqMdCB5H0wHmeBOmie166xn
    465 # CDvlSHtJr5sPZeRDNQFeJN2nN+I47eFwThr5ndx6Gp548DoyDWBnFQz2tgvVpIWA
    466 # TBFrWf8ZulTYcMH3QhzlgEmmgEsU2vT5nbBmmK2QICDzcWA3tIzHSQ7jQxqL+9Oj
    467 # 9EVvuJTf0e81f05xNUmunrwWuoHzIYOF7LmpZqWFp4m8rg5Davtum5Rq60TcofSH
    468 # gKzh10SD1+hAHm7/aqz640BMXsMJCBHofYDzXY0Un7sWoYIS8TCCEu0GCisGAQQB
    469 # gjcDAwExghLdMIIS2QYJKoZIhvcNAQcCoIISyjCCEsYCAQMxDzANBglghkgBZQME
    470 # AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB
    471 # MDEwDQYJYIZIAWUDBAIBBQAEIJeyBGsDoIyvzKdclhGjO92lMFh4eXEiupSWXMgA
    472 # yrYhAgZfYQdYOoMYEzIwMjAwOTIyMjIxOTUwLjk4M1owBIACAfSggdSkgdEwgc4x
    473 # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
    474 # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p
    475 # Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg
    476 # VFNTIEVTTjpGODdBLUUzNzQtRDdCOTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt
    477 # U3RhbXAgU2VydmljZaCCDkQwggT1MIID3aADAgECAhMzAAABL7GnF3lWlBeHAAAA
    478 # AAEvMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
    479 # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
    480 # cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw
    481 # MB4XDTE5MTIxOTAxMTUwNloXDTIxMDMxNzAxMTUwNlowgc4xCzAJBgNVBAYTAlVT
    482 # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
    483 # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy
    484 # YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpGODdB
    485 # LUUzNzQtRDdCOTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj
    486 # ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKh8VkvVIwXD8sn0zT2n
    487 # EdyEZ9UNHY7ACbOZA4obAHvD1hauw9K1Z2lRWG+m8Ars9l35GoMXdPgshM3hZKQW
    488 # fhrLnF9/GDZoilhc2LhMqNPXs06rAJ8YODB6i0Cg1CFCYnyOYvywXKY3xGJN09Dg
    489 # PXWfczEm2P/a3rmrXMrK5EFc3ahxrC51c+UuAMKV9xJyzJVLShPwPBJl+CjdMDPJ
    490 # f24DZXIYec3gCN2xean1DFCI0gaqJprMeL4Om1KY2AZMIgBPEkoY1N7AI5e7ybkI
    491 # L8+Mz3inijb4rDTkXk86ztUwy4bdc1MyKe2j2odT+QIDA2+M8cMTIGlKn7EyD2NN
    492 # XU8CAwEAAaOCARswggEXMB0GA1UdDgQWBBSml/VRpBNFkAMDiqcoqWi85j/qljAf
    493 # BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH
    494 # hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU
    495 # aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF
    496 # BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0
    497 # YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG
    498 # AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQB4q6ilv2SlGvJD/7dbfoIKZBO2i6YA
    499 # wckw57TpCrt2+SAx2dcF7JvRMCPhLCSgqjyNcJRs40cEXPbLdzZMJHzcv73AF7L6
    500 # mWZXg2aBjG1Sc5qM4jjE/nwIX+C6/odm5/asU4JIlFCuUZjzqdir18HkRVQve2Hw
    501 # V0lCXHQs+V3m9DyyA9b6LSIk3GOFZu7F11Wyx/5dVXisPPTPwh9JXfMD9W173M1+
    502 # ZZycmO03lUc4G1FilgpxWNdgWn/DO9ZhoW5yN6+BUddnJ4cCcCjcg8sB5rktPP8p
    503 # VZAQ7aUqkAeqo+FuCkAUAdJRESCpR5wgSPtVvFPMjONE36DbKtfzkfiHMIIGcTCC
    504 # BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC
    505 # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
    506 # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv
    507 # b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcN
    508 # MjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
    509 # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
    510 # aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIw
    511 # DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0
    512 # VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEw
    513 # RA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQe
    514 # dGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKx
    515 # Xf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4G
    516 # kbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEA
    517 # AaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7
    518 # fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC
    519 # AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX
    520 # zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v
    521 # cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI
    522 # KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j
    523 # b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0g
    524 # AQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93
    525 # d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYB
    526 # BQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUA
    527 # bQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOh
    528 # IW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS
    529 # +7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlK
    530 # kVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon
    531 # /VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOi
    532 # PPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/
    533 # fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCII
    534 # YdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0
    535 # cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a
    536 # KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ
    537 # cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+
    538 # NR4Iuto229Nfj950iEkSoYIC0jCCAjsCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT
    539 # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
    540 # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP
    541 # cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpG
    542 # ODdBLUUzNzQtRDdCOTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy
    543 # dmljZaIjCgEBMAcGBSsOAwIaAxUAM/CZCUpclQ9qfr/r3y9osIIPSmSggYMwgYCk
    544 # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
    545 # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
    546 # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF
    547 # AOMUwAMwIhgPMjAyMDA5MjIyMjI1MDdaGA8yMDIwMDkyMzIyMjUwN1owdzA9Bgor
    548 # BgEEAYRZCgQBMS8wLTAKAgUA4xTAAwIBADAKAgEAAgIeewIB/zAHAgEAAgIQ0jAK
    549 # AgUA4xYRgwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB
    550 # AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAB7Ib0ORN4cnD/0V
    551 # iEDrzl7vxjx6981A8Z/8I+X0n7qQHdeGFJcXGEEO5pDD62VMfd28ZrxPWgMd0Chx
    552 # mj5EdvR3U6+gRYzyYY5Vi5srADcWf3pMoYsEQhZuYeohtFQuYFJt2t26GskSlEy3
    553 # qXFkFqIoBCjz1SsmfA5nTtE2zXHSMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMC
    554 # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
    555 # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp
    556 # bWUtU3RhbXAgUENBIDIwMTACEzMAAAEvsacXeVaUF4cAAAAAAS8wDQYJYIZIAWUD
    557 # BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B
    558 # CQQxIgQgDY7vkk/uubZSKGprOnZ2WnFZqhRkEJ7KVJ5R6hogo/AwgfoGCyqGSIb3
    559 # DQEJEAIvMYHqMIHnMIHkMIG9BCBC5RecGZvugnvVXg80zlrGv1uV35LNk+H9dBj3
    560 # ChFPvTCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
    561 # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
    562 # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB
    563 # L7GnF3lWlBeHAAAAAAEvMCIEIAt7o8jjQ4zf04GvFGrnuSSwfsToGMPMzYw+3a3k
    564 # vP0dMA0GCSqGSIb3DQEBCwUABIIBABIE9hcJhxcSYL9zQrK7AunfYI2qZBNrD9dB
    565 # FIYwBnLNOYAPgpjC5Nxrp/4fSrWPyWFkXzwB6rjofda3zWpOywWKMc4lK0yHRYrO
    566 # 7r0FmXd9zxdaJKpbHpc8xG2vb6pI9dh/eXFGNS8KRu+oKZFX2/l5IxRAz4QRMxq6
    567 # /heHcZpWjeIknMhP+bMAqaMV9h3jEojCli0hdwawbTpq8Oyvo6wlwNqLvmtBc7Xs
    568 # 8of9f6I/zTCn6yhbyDEVXxPhn3qjrQzi790XXe3xvmAKkkEW/NO2ZOS/2EpfjFms
    569 # wYhh6tKYg2k2j6mfCGmwvx2cx32zR/m4/ieGClCeKPiRlPvgip0=
    570 # SIG # End signature block