public/Get-LnvDownload.ps1
|
function Get-LnvDownload { <# .Synopsis Get-LnvDownload finds and downloads updates for Lenovo machine type .Description This script allows users to search for updates that will be downloaded to a folder of their choice -Defaults to Windows 10 updates and a folder named c:\testrepo if you do not specify -Requires users to enter at least a machine type -Can be called without identifiers so long as you use the right order -If a repositoryfolder is specified that doesn't exist the script will create it -PackageType can be: 1: Application 2: Driver 3: Bios 4: Firmware -RebootType can be: 0: No reboot required 1: Forced reboot (update itself initiates the reboot) 3: Requires reboot (Thin Installer/System Update/CV initiates the reboot) 4: Forces shutdown (update itself initiates shutdown) 5: Delayed forced reboot (used for firmware, Thin Installer/System Update/CV will enforce reboot with dialog displaying count-down timer) -Severity can be: 1: Critical 2: Recommended 3: Optional Note: 9 can be used for these three parameters to represent 'All' .PARAMETER MachineType Mandatory : True .PARAMETER WindowsVersion .PARAMETER RepositoryFolder .PARAMETER PackageType .PARAMETER RebootType .PARAMETER Csv .PARAMETER Expand .PARAMETER SkipSignatureCheck Skip verifying that the downloaded installer is digitally signed by Lenovo. By default, after downloading, the installer is verified and any package whose installer is not signed by Lenovo has that file removed and an error raised. Use this switch to bypass the check (not recommended for production). .Example Get-LnvDownload -MachineType 20E4 -WindowsVersion 11 -RepositoryFolder "C:\repository" -PackageType 1 .Example Get-LnvDownload 20E4 11 "C:\repository" .Example Get-LnvDownload -MachineType "20E6" -RepositoryFolder "C:\repository" #> param ( [ValidateLength(4,4)][parameter(Mandatory = $true, position = 0)] [String] $MachineType, [parameter(position = 1, Mandatory = $false )][ValidateSet("10","11")] [String] $WindowsVersion = "11", [parameter(position = 2)][String] $RepositoryFolder = "c:\testrepo", [parameter(position = 3)][String] $PackageType = "9", [parameter(position = 4)][String] $RebootType = "9", [parameter(position = 5)][Switch] $Csv, [parameter(position = 6)][Switch] $Expand, [parameter(position = 7)][Switch] $SkipSignatureCheck ) $url = "https://download.lenovo.com/catalog/" + $MachineType + "_win" + $WindowsVersion + ".xml" if ($Csv) { #Create table format to display information about the updates $tbl = New-Object System.Data.DataTable "Available Updates" $col0 = New-Object System.Data.DataColumn ID $col1 = New-Object System.Data.DataColumn Name #$col2 = New-Object System.Data.DataColumn Category $col3 = New-Object System.Data.DataColumn Version $col4 = New-Object System.Data.DataColumn PackageType $col5 = New-Object System.Data.DataColumn Reboot $col6 = New-Object System.Data.DataColumn Severity $col7 = New-Object System.Data.DataColumn Descriptor $col8 = New-Object System.Data.DataColumn PackageExe $tbl.Columns.Add($col0) $tbl.Columns.Add($col1) #$tbl.Columns.Add($col2) $tbl.Columns.Add($col3) $tbl.Columns.Add($col4) $tbl.Columns.Add($col5) $tbl.Columns.Add($col6) $tbl.Columns.Add($col7) $tbl.Columns.Add($col8) } #accesses the updates xml file for a system try { $systemUpdates = Get-LnvXmlFilePvt $url } catch { Write-Output $_ return } if($Expand) { if(-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Output "Not running in elevated session. Skipping expand." $Expand = $false } else { $hash = [hashtable]::Synchronized(@{}) $hash["RepoPath"] = $RepositoryFolder $initialSessionState = [InitialSessionState]::CreateDefault() $RunspacePool = [RunspaceFactory]::CreateRunspacePool($initialSessionState) [void]$RunspacePool.SetMaxRunspaces(2) $RunspacePool.Open() $Jobs = New-Object System.Collections.ArrayList $Worker = { param($Exe, $Fold) Start-Process -FilePath $Exe -ArgumentList "/VERYSILENT /DIR=`"$Fold`" /EXTRACT=`"YES`"" -wait } } } #holds the urls for all the updates for a system $locations = $systemUpdates.packages.package.location $qnty = $systemUpdates.packages.count Write-Output -InputObject ("Total Updates Found: " + $qnty) #Create Repo & prepare to download #check if we have permissions if (-NOT (Test-Path $RepositoryFolder)) { new-item -ItemType directory -path $RepositoryFolder } #questionable code $RepositoryFolder += "\" $downloadCount = 0 #Loops the updates for a machine to download them in a folder with their readme and xml Foreach ($file in $locations) { try { $up1 = Get-LnvXmlFilePvt $file } catch { Write-Output $_ continue } #only get updates that match specified package type and/or reboot type $pkgType = $up1.Package.PackageType.type $rbType = $up1.Package.Reboot.type $pkgID = $up1.Package.id.ToString() if ((($PackageType -eq 9) -or ($PackageType -match $pkgType)) -and (($RebootType -eq 9) -or ($RebootType -match $rbType))) { #Create Folder for update if it does not already exst $innerFold = $RepositoryFolder.ToString() + $pkgID + "\" if (-NOT (Test-Path $innerFold)) { #Get Links; "$file" is the .xml #.xml $beg = $file.SubString(0, $file.LastIndexOf('/') + 1) #$end = $file.Substring($file.LastIndexOf('/') + 1) #.exe #grab crc as well to use Get-LnvFilePvt? $exeFile = $up1.Package.Files.Installer.File.Name $exeLink = $beg + $exeFile #.readme $readMeFile = $up1.Package.Files.Readme.File.Name $readMeLink = $beg + $readMeFile New-Item -ItemType directory -Path $innerFold #Download all parts of the update $dest = $innerFold + $exeFile try { #$pathToExe = Join-Path -Path $innerFold -ChildPath $exeFile #(New-Object System.Net.WebClient).DownloadFile($exeLink, $innerFold + $exeFile); Start-BitsTransfer -Source $exeLink -Destination $dest -ErrorAction Stop } catch { Write-Output -InputObject "Could not download EXE: $exeFile" } # Verify the downloaded installer is signed by Lenovo before using/expanding it. $signatureValid = $true if (Test-Path -LiteralPath $dest -PathType Leaf) { if ($SkipSignatureCheck) { Write-Warning "Signature verification skipped for '$exeFile' (not recommended for production)." } else { try { $signatureResults = @(Test-LnvSignature -Path $dest -ErrorAction Stop) if ($signatureResults -contains $false) { $signatureValid = $false } } catch { Write-Verbose "Signature check failed for ${dest}: $($_.Exception.Message)" $signatureValid = $false } if (-not $signatureValid) { Remove-Item -LiteralPath $dest -Force -ErrorAction SilentlyContinue Write-Error "File '$exeFile' in package '$pkgID' is not signed by Lenovo; the unsigned file has been removed. Use -SkipSignatureCheck to download it anyway." } } } if ($Expand -and $signatureValid -and (Test-Path -LiteralPath $dest -PathType Leaf)) { $PowerShell = [powershell]::Create() $PowerShell.RunspacePool = $RunspacePool $PowerShell.AddScript($Worker).AddArgument($innerFold + $exeFile).AddArgument($innerFold.TrimEnd('\')) | Out-Null $JobObj = New-Object -TypeName PSObject -Property @{ Runspace = $PowerShell.BeginInvoke() PowerShell = $PowerShell } $Jobs.Add($JobObj) | Out-Null } try { (New-Object System.Net.WebClient).DownloadFile($readMeLink, $innerFold + $readMeFile); } catch { Write-Output -InputObject "Could not download Readme: $readMeFile" } #count could be wrong $downloadCount += 1 if ($Csv) { $luPID = $up1.Package.id #$luCat = $categories_1[$counter] $luName = $up1.Package.Title.Desc.InnerText $luVer = $up1.Package.version $luTyp = $up1.Package.PackageType.type $luReb = $up1.Package.Reboot.type $luSev = $up1.Package.Severity.type $luXml = $file $luExe = $file.Substring(0, $file.LastIndexOf('/') + 1) + ($up1.Package.Files.Installer.File.Name) $row = $tbl.NewRow() $row.ID = $luPID $row.Name = $luName # $row.Category = $luCat $row.Version = $luVer $row.PackageType = $luTyp $row.Reboot = $luReb $row.Severity = $luSev $row.Descriptor = $luXml $row.PackageExe = $luExe $tbl.Rows.Add($row) } } else { Write-Output -InputObject ($up1.Package.id.ToString() + " exists in repository.") if ($Expand) { $beg = $file.SubString(0, $file.LastIndexOf('/') + 1) #$end = $file.Substring($file.LastIndexOf('/') + 1) #.exe #grab crc as well to use Get-LnvFilePvt? $exeFile = $up1.Package.Files.Installer.File.Name $exeLink = $beg + $exeFile $dest = $innerFold + $exeFile # Verify the cached installer is signed by Lenovo before expanding it. $signatureValid = $true if (Test-Path -LiteralPath $dest -PathType Leaf) { if ($SkipSignatureCheck) { Write-Warning "Signature verification skipped for '$exeFile' (not recommended for production)." } else { try { $signatureResults = @(Test-LnvSignature -Path $dest -ErrorAction Stop) if ($signatureResults -contains $false) { $signatureValid = $false } } catch { Write-Verbose "Signature check failed for ${dest}: $($_.Exception.Message)" $signatureValid = $false } if (-not $signatureValid) { Write-Error "File '$exeFile' in package '$pkgID' is not signed by Lenovo; skipping expand. Use -SkipSignatureCheck to expand it anyway." } } } if ($signatureValid -and (Test-Path -LiteralPath $dest -PathType Leaf)) { $PowerShell = [powershell]::Create() $PowerShell.RunspacePool = $RunspacePool $PowerShell.AddScript($Worker).AddArgument($innerFold + $exeFile).AddArgument("${RepositoryFolder}\${MachineType}_${WindowsVersion}\${pkgID}") | Out-Null $JobObj = New-Object -TypeName PSObject -Property @{ Runspace = $PowerShell.BeginInvoke() PowerShell = $PowerShell } $Jobs.Add($JobObj) | Out-Null } } } } } Write-Output -InputObject ("Downloaded Updates: " + $downloadCount) if ($Csv) { $csvFilePath = "${RepositoryFolder}\${MachineType}_${WindowsVersion}.csv" $tbl | Export-Csv -Path $csvFilePath } if($Expand) { while ($Jobs.Runspace.IsCompleted -contains $false) { Write-Output (Get-date).Tostring() "Still expanding packages..." Start-Sleep 15 } $RunspacePool.Dispose() } } # SIG # Begin signature block # MIItugYJKoZIhvcNAQcCoIItqzCCLacCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU0n00QpIPRJdb4Q7VlyDQoky4 # ajCggibcMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIFkDCCA3ig # AwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG # EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl # cnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMw # ODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UE # ChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYD # VQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEppz1Y # q3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lX # FllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxe # TsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbu # yntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I # 9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/CNdaSaTC5qmg # Z92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtmmnTK3kse # 5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKy # Ebe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwh # HbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/ # Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwID # AQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4E # FgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQADggIBALth2X2p # bL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY # ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdN # Oj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4 # i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJ # EVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9NcCOGDErcgdLM # MpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N0XWs0Mr7QbhD # parTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb/UdK # Dd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP # 0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLS # oCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9T # dSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+MIIGsDCCBJigAwIBAgIQCK1AsmDS # nEyfXs2pvZOu2TANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UE # ChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYD # VQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjEwNDI5MDAwMDAwWhcN # MzYwNDI4MjM1OTU5WjBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs # IEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5n # IFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A # MIICCgKCAgEA1bQvQtAorXi3XdU5WRuxiEL1M4zrPYGXcMW7xIUmMJ+kjmjYXPXr # NCQH4UtP03hD9BfXHtr50tVnGlJPDqFX/IiZwZHMgQM+TXAkZLON4gh9NH1MgFcS # a0OamfLFOx/y78tHWhOmTLMBICXzENOLsvsI8IrgnQnAZaf6mIBJNYc9URnokCF4 # RS6hnyzhGMIazMXuk0lwQjKP+8bqHPNlaJGiTUyCEUhSaN4QvRRXXegYE2XFf7JP # hSxIpFaENdb5LpyqABXRN/4aBpTCfMjqGzLmysL0p6MDDnSlrzm2q2AS4+jWufcx # 4dyt5Big2MEjR0ezoQ9uo6ttmAaDG7dqZy3SvUQakhCBj7A7CdfHmzJawv9qYFSL # ScGT7eG0XOBv6yb5jNWy+TgQ5urOkfW+0/tvk2E0XLyTRSiDNipmKF+wc86LJiUG # soPUXPYVGUztYuBeM/Lo6OwKp7ADK5GyNnm+960IHnWmZcy740hQ83eRGv7bUKJG # yGFYmPV8AhY8gyitOYbs1LcNU9D4R+Z1MI3sMJN2FKZbS110YU0/EpF23r9Yy3IQ # KUHw1cVtJnZoEUETWJrcJisB9IlNWdt4z4FKPkBHX8mBUHOFECMhWWCKZFTBzCEa # 6DgZfGYczXg4RTCZT/9jT0y7qg0IU0F8WD1Hs/q27IwyCQLMbDwMVhECAwEAAaOC # AVkwggFVMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFGg34Ou2O/hfEYb7 # /mF7CIhl9E5CMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1Ud # DwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzB3BggrBgEFBQcBAQRrMGkw # JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcw # AoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJv # b3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQu # Y29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwHAYDVR0gBBUwEzAHBgVngQwB # AzAIBgZngQwBBAEwDQYJKoZIhvcNAQEMBQADggIBADojRD2NCHbuj7w6mdNW4AIa # pfhINPMstuZ0ZveUcrEAyq9sMCcTEp6QRJ9L/Z6jfCbVN7w6XUhtldU/SfQnuxaB # RVD9nL22heB2fjdxyyL3WqqQz/WTauPrINHVUHmImoqKwba9oUgYftzYgBoRGRjN # YZmBVvbJ43bnxOQbX0P4PpT/djk9ntSZz0rdKOtfJqGVWEjVGv7XJz/9kNF2ht0c # sGBc8w2o7uCJob054ThO2m67Np375SFTWsPK6Wrxoj7bQ7gzyE84FJKZ9d3OVG3Z # XQIUH0AzfAPilbLCIXVzUstG2MQ0HKKlS43Nb3Y3LIU/Gs4m6Ri+kAewQ3+ViCCC # cPDMyu/9KTVcH4k4Vfc3iosJocsL6TEa/y4ZXDlx4b6cpwoG1iZnt5LmTl/eeqxJ # zy6kdJKt2zyknIYf48FWGysj/4+16oh7cGvmoLr9Oj9FpsToFpFSi0HASIRLlk2r # REDjjfAVKM7t8RhWByovEMQMCGQ8M4+uKIw8y4+ICw2/O/TOHnuO77Xry7fwdxPm # 5yg/rBKupS8ibEH5glwVZsxsDsrFhsP2JjMMB0ug0wcCampAMEhLNKhRILutG4UI # 4lkNbcoFUCvqShyepf2gpx8GdOfy1lKQ/a+FSCH5Vzu0nAPthkX0tGFuv2jiJmCG # 6sivqf6UHedjGzqGVnhOMIIGtDCCBJygAwIBAgIQDcesVwX/IZkuQEMiDDpJhjAN # BgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQg # SW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2Vy # dCBUcnVzdGVkIFJvb3QgRzQwHhcNMjUwNTA3MDAwMDAwWhcNMzgwMTE0MjM1OTU5 # WjBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNV # BAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hB # MjU2IDIwMjUgQ0ExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtHgx # 0wqYQXK+PEbAHKx126NGaHS0URedTa2NDZS1mZaDLFTtQ2oRjzUXMmxCqvkbsDpz # 4aH+qbxeLho8I6jY3xL1IusLopuW2qftJYJaDNs1+JH7Z+QdSKWM06qchUP+AbdJ # gMQB3h2DZ0Mal5kYp77jYMVQXSZH++0trj6Ao+xh/AS7sQRuQL37QXbDhAktVJMQ # bzIBHYJBYgzWIjk8eDrYhXDEpKk7RdoX0M980EpLtlrNyHw0Xm+nt5pnYJU3Gmq6 # bNMI1I7Gb5IBZK4ivbVCiZv7PNBYqHEpNVWC2ZQ8BbfnFRQVESYOszFI2Wv82wnJ # RfN20VRS3hpLgIR4hjzL0hpoYGk81coWJ+KdPvMvaB0WkE/2qHxJ0ucS638ZxqU1 # 4lDnki7CcoKCz6eum5A19WZQHkqUJfdkDjHkccpL6uoG8pbF0LJAQQZxst7VvwDD # jAmSFTUms+wV/FbWBqi7fTJnjq3hj0XbQcd8hjj/q8d6ylgxCZSKi17yVp2NL+cn # T6Toy+rN+nM8M7LnLqCrO2JP3oW//1sfuZDKiDEb1AQ8es9Xr/u6bDTnYCTKIsDq # 1BtmXUqEG1NqzJKS4kOmxkYp2WyODi7vQTCBZtVFJfVZ3j7OgWmnhFr4yUozZtqg # PrHRVHhGNKlYzyjlroPxul+bgIspzOwbtmsgY1MCAwEAAaOCAV0wggFZMBIGA1Ud # EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFO9vU0rp5AZ8esrikFb2L9RJ7MtOMB8G # A1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjAT # BgNVHSUEDDAKBggrBgEFBQcDCDB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGG # GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2Nh # Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYD # VR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0 # VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9 # bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQAXzvsWgBz+Bz0RdnEwvb4LyLU0pn/N0IfF # iBowf0/Dm1wGc/Do7oVMY2mhXZXjDNJQa8j00DNqhCT3t+s8G0iP5kvN2n7Jd2E4 # /iEIUBO41P5F448rSYJ59Ib61eoalhnd6ywFLerycvZTAz40y8S4F3/a+Z1jEMK/ # DMm/axFSgoR8n6c3nuZB9BfBwAQYK9FHaoq2e26MHvVY9gCDA/JYsq7pGdogP8HR # trYfctSLANEBfHU16r3J05qX3kId+ZOczgj5kjatVB+NdADVZKON/gnZruMvNYY2 # o1f4MXRJDMdTSlOLh0HCn2cQLwQCqjFbqrXuvTPSegOOzr4EWj7PtspIHBldNE2K # 9i697cvaiIo2p61Ed2p8xMJb82Yosn0z4y25xUbI7GIN/TpVfHIqQ6Ku/qjTY6hc # 3hsXMrS+U0yy+GWqAXam4ToWd2UQ1KYT70kZjE4YtL8Pbzg0c1ugMZyZZd/BdHLi # Ru7hAWE6bTEm4XYRkA6Tl4KSFLFk43esaUeqGkH/wyW4N7OigizwJWeukcyIPbAv # jSabnf7+Pu0VrFgoiovRDiyx3zEdmcif/sYQsfch28bZeUz2rtY/9TCA6TD8dC3J # E3rYkrhLULy7Dc90G6e8BlqmyIjlgp2+VqsS9/wQD7yFylIz0scmbKvFoW2jNrbM # 1pD2T7m3XDCCBu0wggTVoAMCAQICEAqA7xhLjfEFgtHEdqeVdGgwDQYJKoZIhvcN # AQELBQAwaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEw # PwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IFRpbWVTdGFtcGluZyBSU0E0MDk2 # IFNIQTI1NiAyMDI1IENBMTAeFw0yNTA2MDQwMDAwMDBaFw0zNjA5MDMyMzU5NTla # MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UE # AxMyRGlnaUNlcnQgU0hBMjU2IFJTQTQwOTYgVGltZXN0YW1wIFJlc3BvbmRlciAy # MDI1IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDQRqwtEsae0Oqu # YFazK1e6b1H/hnAKAd/KN8wZQjBjMqiZ3xTWcfsLwOvRxUwXcGx8AUjni6bz52fG # Tfr6PHRNv6T7zsf1Y/E3IU8kgNkeECqVQ+3bzWYesFtkepErvUSbf+EIYLkrLKd6 # qJnuzK8Vcn0DvbDMemQFoxQ2Dsw4vEjoT1FpS54dNApZfKY61HAldytxNM89PZXU # P/5wWWURK+IfxiOg8W9lKMqzdIo7VA1R0V3Zp3DjjANwqAf4lEkTlCDQ0/fKJLKL # kzGBTpx6EYevvOi7XOc4zyh1uSqgr6UnbksIcFJqLbkIXIPbcNmA98Oskkkrvt6l # PAw/p4oDSRZreiwB7x9ykrjS6GS3NR39iTTFS+ENTqW8m6THuOmHHjQNC3zbJ6nJ # 6SXiLSvw4Smz8U07hqF+8CTXaETkVWz0dVVZw7knh1WZXOLHgDvundrAtuvz0D3T # +dYaNcwafsVCGZKUhQPL1naFKBy1p6llN3QgshRta6Eq4B40h5avMcpi54wm0i2e # PZD5pPIssoszQyF4//3DoK2O65Uck5Wggn8O2klETsJ7u8xEehGifgJYi+6I03Uu # T1j7FnrqVrOzaQoVJOeeStPeldYRNMmSF3voIgMFtNGh86w3ISHNm0IaadCKCkUe # 2LnwJKa8TIlwCUNVwppwn4D3/Pt5pwIDAQABo4IBlTCCAZEwDAYDVR0TAQH/BAIw # ADAdBgNVHQ4EFgQU5Dv88jHt/f3X85FxYxlQQ89hjOgwHwYDVR0jBBgwFoAU729T # SunkBnx6yuKQVvYv1Ensy04wDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoG # CCsGAQUFBwMIMIGVBggrBgEFBQcBAQSBiDCBhTAkBggrBgEFBQcwAYYYaHR0cDov # L29jc3AuZGlnaWNlcnQuY29tMF0GCCsGAQUFBzAChlFodHRwOi8vY2FjZXJ0cy5k # aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2 # U0hBMjU2MjAyNUNBMS5jcnQwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL2NybDMu # ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0VGltZVN0YW1waW5nUlNBNDA5 # NlNIQTI1NjIwMjVDQTEuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG # /WwHATANBgkqhkiG9w0BAQsFAAOCAgEAZSqt8RwnBLmuYEHs0QhEnmNAciH45PYi # T9s1i6UKtW+FERp8FgXRGQ/YAavXzWjZhY+hIfP2JkQ38U+wtJPBVBajYfrbIYG+ # Dui4I4PCvHpQuPqFgqp1PzC/ZRX4pvP/ciZmUnthfAEP1HShTrY+2DE5qjzvZs7J # IIgt0GCFD9ktx0LxxtRQ7vllKluHWiKk6FxRPyUPxAAYH2Vy1lNM4kzekd8oEARz # FAWgeW3az2xejEWLNN4eKGxDJ8WDl/FQUSntbjZ80FU3i54tpx5F/0Kr15zW/mJA # xZMVBrTE2oi0fcI8VMbtoRAmaaslNXdCG1+lqvP4FbrQ6IwSBXkZagHLhFU9HCrG # /syTRLLhAezu/3Lr00GrJzPQFnCEH1Y58678IgmfORBPC1JKkYaEt2OdDh4GmO0/ # 5cHelAK2/gTlQJINqDr6JfwyYHXSd+V08X1JUPvB4ILfJdmL+66Gp3CSBXG6IwXM # ZUXBhtCyIaehr0XkBoDIGMUG1dUtwq1qmcwbdUfcSYCn+OwncVUXf53VJUNOaMWM # ts0VlRYxe5nK+At+DI96HAlXHAL5SlfYxJ7La54i71McVWRP66bW+yERNpbJCjyC # YG2j+bdpxo/1Cy4uPcU3AWVPGrbn5PhDBf3Froguzzhk++ami+r3Qrx5bIbY3TVz # giFI7Gq3zWcwggdWMIIFPqADAgECAhAFfARoFtaNDha0m0G6FxiVMA0GCSqGSIb3 # DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFB # MD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5 # NiBTSEEzODQgMjAyMSBDQTEwHhcNMjYwNTE0MDAwMDAwWhcNMjcwNjE3MjM1OTU5 # WjBeMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExFDASBgNV # BAcTC01vcnJpc3ZpbGxlMQ8wDQYDVQQKEwZMZW5vdm8xDzANBgNVBAMTBkxlbm92 # bzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALVacqHydjmqo6bF2tHw # cETPkOZLgPv1tJeIerpLcfmxLoX40GsUiY5l96B13bcfKjKBJQvHsj5D08RfGnif # K+sGsAX8xCgaYNLxq0COKn51GgLLMNgzlE4rR/8mUMuWK2fKXs24dmn7teE2+e+2 # dz/GfHXgrAIPvIr4PN+dZAFeoj6/wfpLLHZXtQLxKVmtDFc7gQZkM6Z8o0HrH2eX # 2MVNQwbZZWvSQhqRN66/LMcXxbLP8SAb6nKRCExflbI5i+MpEq+xOdiJxkP5dC5s # rQ31JGLDdhbuAcUJEdXATzgP1pT9is3uWZm3fro71Kvfa0XLwBZWR2ut8sQ6KUhd # 0Nsmd5c0f2PiD2uTd9mDWHQ34bu9mDunZaeWZrIlUP9MJ8TMM82ao/4tjFNK5m3T # hZUbCGwoepenXq8yjbKMKqHHvcoJY0SmkAIlUzWoRBbRC+uN0TwcR048sZDPo+ZC # gdONLPrjnsIU+NxuhfDMnj4UYbkRbtvnJ+U0O4Eu+ajRS87Li+jN2jHrABvAUXtP # J7DkkxTTfaspzlfxueoqVKcGLnu4PUAthKg3g4hleGgeo7s+krEDAzyvdBnY+b8U # dRH/BCxDr7G5ys/bCMPEzcUFT5LrrVBHO6N2U65iYkamzEo4okrrCNFDJPZC1G/p # NleTeiIadSPTT0tJGPK+nDo1AgMBAAGjggIDMIIB/zAfBgNVHSMEGDAWgBRoN+Dr # tjv4XxGG+/5hewiIZfROQjAdBgNVHQ4EFgQU7R8eucYUNncCkcWYWfCltSt/mxYw # PgYDVR0gBDcwNTAzBgZngQwBBAEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5k # aWdpY2VydC5jb20vQ1BTMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEF # BQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRwOi8vY3JsMy5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIx # Q0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0 # VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcmwwgZQG # CCsGAQUFBwEBBIGHMIGEMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy # dC5jb20wXAYIKwYBBQUHMAKGUGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEu # Y3J0MAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggIBAC0PiOF1B8Qdp2pcfb3P # 6MuzaeTUw77bfMSCcnwY8xFtkyRRp9H6X4ZaSTdAQge3d6NG7OcHnGQ3FKraZqT3 # ugjNEXvH1MXr8SNgFb7t7TyKDK0RmRK9idsycLJfRsmbj0FSTL12jqrzyHrQqkTq # KaDqYfIVan7VxP2On8gq3/OT368z1YJbRgfu/rNpXoYpXTKSfxaIXNE7rEiUwu+T # vi8wgfLqC/a7ujC8vbYRWgaHHsz3bjFVN/h1p78adds2GdxPzYFoS12+JKq2cKGe # Ma5Hbr2YQfHsbpQlzZglB3mGCci+uhN5YGaHleo3Ohd0BHci32RFOA1xdD8fS9TD # pGRMGLKF9z5WTmiGZVR4x54Qwtf4clbA5V0P9d4ppmLZJKdeaHd/JKONVJ9nYV1H # NA52CgvgRWpUc+jxnPL5A3J9qIvUXp98ZQifEyHBFX2VqWTdu9MldzklRo/eAT1k # MUVheRAcd32yLDiFvn7lp2nasJs8Hh+6bUxfHKbKBrNrw7CmcTDzFK119BkykWS0 # vL7xsbCEbavLIhW/ZqEjWA9k/v2FS2wbBQ9YOC8F3magnslxWlZWsym3Dxdm0Hr1 # WKHbnFcBscMiBQ+fhLDAqIG8tPPnNhc7QhOOlxQlbfEDh8QmQbUo2H9hJJEGiHJS # VwuAKbcWembFyAgLV02ASxS7MYIGSDCCBkQCAQEwfTBpMQswCQYDVQQGEwJVUzEX # MBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0 # ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAFfARo # FtaNDha0m0G6FxiVMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgACh # AoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAM # BgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBStK/oyJloObd/0gHydfd4RI7dV # sTANBgkqhkiG9w0BAQEFAASCAgCablnKAZP4uU4lVJVwxbzdQtdyUi4GYnV5l44U # q2UzLqHvwBVu1a6gMAyR4liBTEtDrccgGzYpPP41Ecb2ltH7pwdlGz1qLtf87D0R # rKXWGj+dlOk8EbvLc4zdJReelTBVsOgVDMtZIz4VaDkRHzKemb0AO2gSD0/RY65D # 7kDz80v0BX0IP7yKC9CdLs3H3FDiXzw6LY4R1y5U8i8VHqH3i7f1rZ4sqXnJq/IU # tMgCC4LZHhn6rB/hPXRZW7wQBOKYI47uFBKyJwAALPkdArKuC13giq2As+Y0N9fp # HRFumsa9RWb7vFuRITrYKoj7rgoucdj2jA+D8v9XcdyrzafNK2vlMbxvuMTDWU7J # 0bTBiexQgNidyDw3ZC3kaX0oLiOMUopKWaweqlB86R8tYZbOM/XGZei2CSj/tlpo # vjjg+TWwtwS4dY1lWVVeqj/tLJs2CkLu7lM9TMSOZk+JeSowlyD8ZyJWv/LWX3BT # T5R5IWxsqI8e47qZxdE9zIRHn2aVpsMrvjc1GY8bxH4DLIu3z2lsTnkrPmyowxnh # 90Fo9b8j4ZVPx8MIGV1TCe+fDw/usX24A/cPSVMbSt2KlyO6iU5QFM1dN/D/LqOn # UdLH9ew6oRq+zg996jUKhHKH6BkybbQKTCO0oFEVC7bKapn0TqLUQsIHB3JUtAQq # khM6HaGCAyYwggMiBgkqhkiG9w0BCQYxggMTMIIDDwIBATB9MGkxCzAJBgNVBAYT # AlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQg # VHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTEC # EAqA7xhLjfEFgtHEdqeVdGgwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMx # CwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNjA3MTQxNjEwMzZaMC8GCSqG # SIb3DQEJBDEiBCAO/7NeSNFF8AIFQDLMIINf18ASLo+2IBSUJQ0fwlvM5TANBgkq # hkiG9w0BAQEFAASCAgA+bRl+c+wRuiPjXNtR3Y+bxxaBlckfct/5GJqHNKjRwVKU # CuMG4kJeNbPAffokxKZ6Aefq+Y0+vpoNVCLIYDZ7DeSuW9eeMN0VjzoiTa6b50Pf # FtRK1uiLAujZ+LuUqJ74/9Ssxc0ZcUMqrgzbHcuuO3oknRHw5EN3PHczZYs3DqXb # 94bmLBe8ILF8n4mMQRhkDhT+4EsjaUc2CweKZK//55S/co12KOUyW2VT9vCl9Pru # +3OME0wMzNIuqRTaGL4lnTpQDLHFy/TEhY4Gl/Ht1y2F6epHbHe4+npOGktYXHqL # b7mwohsZpX6p50tVNqSz1QLJqotzTKizkRf87VmUZ5uY4+spt25Tp/9XX87pSxPE # wVPU5K+6cf3LW3ZZeZRpNZSqpaW8iKyzv3cTcMdTlh2Yk0wG/JZTS4z30LXeCvF4 # LaFIZheTrL43yiZa1JxavMqoFGzqTkWV1hoyehfRPyFe3Vo8Ffbsocnj8nxCTcg/ # tQyGWQ5o7Ry59sZ8xS2RUx/R3RsmepZxyjnzSvE0/nM+xP7feX1GPCYbZ755KsrR # Tif/6X0gteDYKNFBI6c/ePqccXIYKBAXcxaW6XnwW1wfLf34gd99vbaNZXYHEOfg # /TOAMPEdXKPQWH9pHxsPqjZ5h++QWZPy81WeBrniORW0MVduISc7q4JHhNQ+Hw== # SIG # End signature block |