private/Update-Db.ps1
function new-db { $script:dailydb = "C:\github\kbupdate\library\db\kb.sqlite" Remove-Item -Path $dailydb -ErrorAction Ignore $null = New-SQLiteConnection -DataSource $dailydb # updateid is not uniqueidentifier cuz I can't figure out how to do WHERE # and it gets in the way of the import Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE TABLE [Kb]( [UpdateId] [nvarchar](36) PRIMARY KEY NOT NULL, [Title] [nvarchar](200) NOT NULL, [Id] int NULL, [Architecture] [nvarchar](5) NULL, [Language] [nvarchar](25) NULL, [Hotfix] bit NULL, [Description] [nvarchar](1500) NULL, [LastModified] smalldatetime NULL, [Size] [nvarchar](50) NULL, [Classification] [nvarchar](512) NULL, [SupportedProducts] [nvarchar](50) NULL, [MSRCNumber] [nvarchar](25) NULL, [MSRCSeverity] [nvarchar](50) NULL, [RebootBehavior] [nvarchar](50) NULL, [RequestsUserInput] bit NULL, [ExclusiveInstall] bit NULL, [NetworkRequired] bit NULL, [UninstallNotes] [nvarchar](1500) NULL, [UninstallSteps] [nvarchar](1500) NULL )" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE TABLE [SupersededBy]( [UpdateId] [nvarchar](36) NOT NULL, [Kb] int NULL, [Description] [nvarchar](200) NULL )" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE TABLE [Supersedes]( [UpdateId] [nvarchar](36) NOT NULL, [Kb] int NULL, [Description] [nvarchar](200) NULL )" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE TABLE [Link]( [UpdateId] [nvarchar](36) NOT NULL, [Link] [nvarchar](512) NULL )" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE TABLE [KbDupe]( [UpdateId] [nvarchar](36) NOT NULL, [Dupe] [nvarchar](36) NOT NULL )" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE TABLE [notfound]( [UpdateId] [nvarchar](36) NOT NULL )" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE INDEX tag_uid_kb ON Kb (UpdateId)" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE INDEX tag_uid_superby ON SupersededBy (UpdateId)" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE INDEX tag_uid_supers ON Supersedes (UpdateId)" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE INDEX tag_uid_link ON Link (UpdateId)" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE INDEX tag_uid_dupe ON KbDupe (Dupe)" Get-ChildItem $dailydb } function Get-Info1 { #Invoke-SqliteQuery -DataSource $dailydb -Query "select * from Kb" #Invoke-SqliteQuery -DataSource $dailydb -Query "select * from SupersededBy" #Invoke-SqliteQuery -DataSource $dailydb -Query "select * from Supersedes" #Invoke-SqliteQuery -DataSource $dailydb -Query "select * from Link" #Invoke-SqliteQuery -DataSource $dailydb -Query "select * from KbDupe" } function New-Index { Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE INDEX tag_uid_kb ON Kb (UpdateId)" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE INDEX tag_uid_superby ON SupersededBy (UpdateId)" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE INDEX tag_uid_supers ON Supersedes (UpdateId)" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE INDEX tag_uid_link ON Link (UpdateId)" Invoke-SqliteQuery -DataSource $dailydb -Query "CREATE INDEX tag_uid_dupe ON KbDupe (Dupe)" } function Update-Db { [CmdletBinding()] param() Import-Module C:\github\dbatools $script:db = "C:\github\sqldb\kbold.sqlite" $dailydb = "C:\github\sqldb\kbnew.sqlite" #$new = (Get-ChildItem C:\temp\kb\newoutput).BaseName $new = "313e209f-aaac-4694-ac61-675f6e9e6b60","4eb83e93-c0f2-4a71-ba43-053787ecfa2e","b46acc67-3232-4a91-88d2-867cb9d0286c","be4386c2-16b5-4f26-a574-915648bcec2d","d0478bde-b17d-4cd7-9cbc-939c62b62c96" $new | Invoke-Parallel -ImportVariables -ImportFunctions -RunspaceTimeout 180 -Quiet -ScriptBlock { Import-Module PSFramework, PSSQLite, dbatools #$update = Get-KbUpdate -Pattern $guid -Source Web $guid = $PSItem $update = Get-KbUpdate -Pattern $guid if ($update.SupportedProducts) { $update.SupportedProducts = $update.SupportedProducts -join "|" } $Kb = $update | Select-Object -Property * -ExcludeProperty SupersededBy, Supersedes, Link, InputObject $SupersededBy = $update.SupersededBy $Supersedes = $update.Supersedes $Link = $update.Link if ($update.UpdateId) { # delete old entries Invoke-SqliteQuery -DataSource $script:db -Query "delete from Kb where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $dailydb -Query "delete from Kb where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $script:db -Query "delete from SupersededBy where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $dailydb -Query "delete from SupersededBy where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $script:db -Query "delete from Supersedes where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $dailydb -Query "delete from Supersedes where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $script:db -Query "delete from Link where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $dailydb -Query "delete from Link where UpdateId = '$($update.UpdateId)'" } foreach ($item in $Kb) { $null = Add-Member -InputObject $item -NotePropertyName DateAdded -NotePropertyValue (Get-Date) -Force try { Invoke-SQLiteBulkCopy -DataTable ($item | ConvertTo-DbaDataTable) -DataSource $dailydb -Table Kb -Confirm:$false } catch { $null = Add-Content -Value $PSItem -Path C:\temp\kbs\new\Dupes.txt Stop-PSFFunction -Message $PSItem -ErrorRecord $_ -Continue } } try { foreach ($item in $SupersededBy) { if ($null -ne $item.Kb -and '' -ne $item.Kb) { if ($item.Kb) { Invoke-SQLiteBulkCopy -DataTable ([pscustomobject]@{ UpdateId = $update.UpdateId; Kb = $item.Kb; Description = $item.Description } | ConvertTo-DbaDataTable) -DataSource $dailydb -Table SupersededBy -Confirm:$false } } } foreach ($item in $Supersedes) { if ($null -ne $item.Kb -and '' -ne $item.Kb) { if ($item.Kb) { Invoke-SQLiteBulkCopy -DataTable ([pscustomobject]@{ UpdateId = $update.UpdateId; Kb = $item.Kb; Description = $item.Description } | ConvertTo-DbaDataTable) -DataSource $dailydb -Table Supersedes -Confirm:$false } } } foreach ($item in $Link) { Invoke-SQLiteBulkCopy -DataTable ([pscustomobject]@{UpdateId = $update.UpdateId; Link = $item } | ConvertTo-DbaDataTable) -DataSource $dailydb -Table Link -Confirm:$false } $null = Add-Content -Value $guid -Path C:\temp\kbs\new\NewAll.txt } catch { $null = Add-Content -Value $PSItem -Path C:\temp\kbs\new\errors.txt Stop-PSFFunction -Message $gui$PSItemd -ErrorRecord $_ -Continue } } } function Update-DbFromFile { [CmdletBinding()] param() $files = Get-ChildItem -Path C:\temp\kbs\new\*.xml -Recurse $i = 0 foreach ($file in $files) { $update = Import-CliXml $file.FullName $guid = $update.UpdateId $i++ if (($i % 100) -eq 0) { write-warning $i } if (-not $exists) { $kb = $update | Select-Object -Property * -ExcludeProperty SupersededBy, Supersedes, Link, InputObject $SupersededBy = $update.SupersededBy $Supersedes = $update.Supersedes $Link = $update.Link try { Invoke-SQLiteBulkCopy -DataTable ($kb | ConvertTo-DbaDataTable) -DataSource $dailydb -Table Kb -Confirm:$false } catch { if ($file.BaseName) { $value = $file.BaseName } else { $value = $file } Invoke-SQLiteBulkCopy -DataTable ([pscustomobject]@{ UpdateId = $guid; Dupe = $value } | ConvertTo-DbaDataTable) -DataSource $dailydb -Table KbDupe -Confirm:$false #Add-Content -Path C:\temp\dupes.txt -Value $guid, $file.BaseName Stop-PSFFunction -Message $guid -ErrorRecord $_ -Continue } try { foreach ($item in $SupersededBy) { Invoke-SQLiteBulkCopy -DataTable ([pscustomobject]@{ UpdateId = $guid; Kb = $item.Kb; Description = $item.Description } | ConvertTo-DbaDataTable) -DataSource $dailydb -Table SupersededBy -Confirm:$false } foreach ($item in $Supersedes) { Invoke-SQLiteBulkCopy -DataTable ([pscustomobject]@{ UpdateId = $guid; Kb = $item.Kb; Description = $item.Description } | ConvertTo-DbaDataTable) -DataSource $dailydb -Table Supersedes -Confirm:$false } foreach ($item in $Link) { Invoke-SQLiteBulkCopy -DataTable ([pscustomobject]@{UpdateId = $guid; Link = $item } | ConvertTo-DbaDataTable) -DataSource $dailydb -Table Link -Confirm:$false } } catch { Stop-PSFFunction -Message $guid -ErrorRecord $_ -Continue } } } } function Add-Kb { [CmdletBinding()] param( [string[]]$Name ) foreach ($guid in $Name) { $update = Get-KbUpdate -Pattern $guid -Source Web $update.SupportedProducts = $update.SupportedProducts -join ", " $Kb = $update | Select-Object -Property * -ExcludeProperty SupersededBy, Supersedes, Link, InputObject $SupersededBy = $update.SupersededBy $Supersedes = $update.Supersedes $Link = $update.Link if ($update.UpdateId) { # delete old entries Invoke-SqliteQuery -DataSource $script:db -Query "delete from Kb where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $dailydb -Query "delete from Kb where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $script:db -Query "delete from SupersededBy where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $dailydb -Query "delete from SupersededBy where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $script:db -Query "delete from Supersedes where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $dailydb -Query "delete from Supersedes where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $script:db -Query "delete from Link where UpdateId = '$($update.UpdateId)'" Invoke-SqliteQuery -DataSource $dailydb -Query "delete from Link where UpdateId = '$($update.UpdateId)'" } foreach ($item in $Kb) { $null = Add-Member -InputObject $item -NotePropertyName DateAdded -NotePropertyValue (Get-Date) -Force try { Invoke-SQLiteBulkCopy -DataTable ($item | ConvertTo-DbaDataTable) -DataSource $dailydb -Table Kb -Confirm:$false } catch { $null = Add-Content -Value $guid -Path C:\updates\Dupes.txt Stop-PSFFunction -Message $guid -ErrorRecord $_ -Continue } } try { foreach ($item in $SupersededBy) { if ($null -ne $item.Kb -and '' -ne $item.Kb) { Invoke-SQLiteBulkCopy -DataTable ([pscustomobject]@{ UpdateId = $guid; Kb = $item.Kb; Description = $item.Description } | ConvertTo-DbaDataTable) -DataSource $dailydb -Table SupersededBy -Confirm:$false } } foreach ($item in $Supersedes) { if ($null -ne $item.Kb -and '' -ne $item.Kb) { Invoke-SQLiteBulkCopy -DataTable ([pscustomobject]@{ UpdateId = $guid; Kb = $item.Kb; Description = $item.Description } | ConvertTo-DbaDataTable) -DataSource $dailydb -Table Supersedes -Confirm:$false } } foreach ($item in $Link) { Invoke-SQLiteBulkCopy -DataTable ([pscustomobject]@{UpdateId = $guid; Link = $item } | ConvertTo-DbaDataTable) -DataSource $dailydb -Table Link -Confirm:$false } $update $null = Add-Content -Value $guid -Path C:\updates\NewAll.txt } catch { Stop-PSFFunction -Message $guid -ErrorRecord $_ -Continue } } $newer = $xml.OfflineSyncPackage.Updates.Update $ds = New-Object System.Data.DataSet $ds.ReadXml($xmlfile) ($ds.Tables["FileLocation"].Select("Id = '$fileid'")).Url function Fix-Db { [CmdletBinding()] param() function Get-Info ($Text, $Pattern) { if ($Pattern -match "labelTitle") { if ($Pattern -match "SupportedProducts") { # no idea what the regex below does but it's not working for SupportedProducts # do it the manual way instead $block = [regex]::Match($Text, $Pattern + '[\s\S]*?\s*(.*?)\s*<\/div>').Groups[0].Value $supported = $block -split "</span>" | Select-Object -Last 1 $supported.Trim().Replace("</div>","").Split(",").Trim() } else { # this should work... not accounting for multiple divs however? [regex]::Match($Text, $Pattern + '[\s\S]*?\s*(.*?)\s*<\/div>').Groups[1].Value } } elseif ($Pattern -match "span ") { [regex]::Match($Text, $Pattern + '(.*?)<\/span>').Groups[1].Value } else { [regex]::Match($Text, $Pattern + "\s?'?(.*?)'?;").Groups[1].Value } } $new = (Invoke-SqliteQuery -DataSource "C:\github\kbupdate-library\library\kb.sqlite" -Query "select UpdateId from kb where Classification like '%security%' and MSRCNumber is NULL").UpdateId #$new | Invoke-Parallel -ImportVariables -ImportFunctions -RunspaceTimeout 180 -ScriptBlock { Import-Module PSSQLite $new | ForEach-Object { $updateid = $PSItem $detaildialog = Invoke-TlsWebRequest -Uri "https://www.catalog.update.microsoft.com/ScopedViewInline.aspx?updateid=$updateid" $msrcnumber = Get-Info -Text $detaildialog -Pattern '<span id="ScopedViewHandler_labelSecurityBulliten_Separator" class="labelTitle">' if ($msrcnumber -eq "n/a" -or $msrcnumber -eq "Unspecified") { $msrcnumber = $null } if ($msrcnumber) { $query = "update Kb set MSRCNumber = '$msrcnumber' where UpdateId = '$updateid';" write-warning $query Invoke-SqliteQuery -DataSource "C:\github\kbupdate-library\library\kb.sqlite" -Query $query } else { write-warning nope } } } } # SIG # Begin signature block # MIIjYAYJKoZIhvcNAQcCoIIjUTCCI00CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBJUbo1K7tGhnKy # wI9R/OboKMnYM3P8EvClAjxJbIyJ2qCCHVkwggUaMIIEAqADAgECAhADBbuGIbCh # Y1+/3q4SBOdtMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNV # BAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwHhcN # MjAwNTEyMDAwMDAwWhcNMjMwNjA4MTIwMDAwWjBXMQswCQYDVQQGEwJVUzERMA8G # A1UECBMIVmlyZ2luaWExDzANBgNVBAcTBlZpZW5uYTERMA8GA1UEChMIZGJhdG9v # bHMxETAPBgNVBAMTCGRiYXRvb2xzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB # CgKCAQEAvL9je6vjv74IAbaY5rXqHxaNeNJO9yV0ObDg+kC844Io2vrHKGD8U5hU # iJp6rY32RVprnAFrA4jFVa6P+sho7F5iSVAO6A+QZTHQCn7oquOefGATo43NAadz # W2OWRro3QprMPZah0QFYpej9WaQL9w/08lVaugIw7CWPsa0S/YjHPGKQ+bYgI/kr # EUrk+asD7lvNwckR6pGieWAyf0fNmSoevQBTV6Cd8QiUfj+/qWvLW3UoEX9ucOGX # 2D8vSJxL7JyEVWTHg447hr6q9PzGq+91CO/c9DWFvNMjf+1c5a71fEZ54h1mNom/ # XoWZYoKeWhKnVdv1xVT1eEimibPEfQIDAQABo4IBxTCCAcEwHwYDVR0jBBgwFoAU # WsS5eyoKo6XqcQPAYPkt9mV1DlgwHQYDVR0OBBYEFPDAoPu2A4BDTvsJ193ferHL # 454iMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzB3BgNVHR8E # cDBuMDWgM6Axhi9odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVk # LWNzLWcxLmNybDA1oDOgMYYvaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTIt # YXNzdXJlZC1jcy1nMS5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAwEwKjAoBggr # BgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBBAEw # gYQGCCsGAQUFBwEBBHgwdjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNl # cnQuY29tME4GCCsGAQUFBzAChkJodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20v # RGlnaUNlcnRTSEEyQXNzdXJlZElEQ29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/ # BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAj835cJUMH9Y2pBKspjznNJwcYmOxeBcH # Ji+yK0y4bm+j44OGWH4gu/QJM+WjZajvkydJKoJZH5zrHI3ykM8w8HGbYS1WZfN4 # oMwi51jKPGZPw9neGS2PXrBcKjzb7rlQ6x74Iex+gyf8z1ZuRDitLJY09FEOh0BM # LaLh+UvJ66ghmfIyjP/g3iZZvqwgBhn+01fObqrAJ+SagxJ/21xNQJchtUOWIlxR # kuUn9KkuDYrMO70a2ekHODcAbcuHAGI8wzw4saK1iPPhVTlFijHS+7VfIt/d/18p # MLHHArLQQqe1Z0mTfuL4M4xCUKpebkH8rI3Fva62/6osaXLD0ymERzCCBTAwggQY # oAMCAQICEAQJGBtf1btmdVNDtW+VUAgwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UE # BhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2lj # ZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4X # DTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcjELMAkGA1UEBhMCVVMxFTAT # BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEx # MC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBD # QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPjTsxx/DhGvZ3cH0wsx # SRnP0PtFmbE620T1f+Wondsy13Hqdp0FLreP+pJDwKX5idQ3Gde2qvCchqXYJawO # eSg6funRZ9PG+yknx9N7I5TkkSOWkHeC+aGEI2YSVDNQdLEoJrskacLCUvIUZ4qJ # RdQtoaPpiCwgla4cSocI3wz14k1gGL6qxLKucDFmM3E+rHCiq85/6XzLkqHlOzEc # z+ryCuRXu0q16XTmK/5sy350OTYNkO/ktU6kqepqCquE86xnTrXE94zRICUj6whk # PlKWwfIPEvTFjg/BougsUfdzvL2FsWKDc0GCB+Q4i2pzINAPZHM8np+mM6n9Gd8l # k9ECAwEAAaOCAc0wggHJMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQD # AgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHkGCCsGAQUFBwEBBG0wazAkBggrBgEF # BQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRw # Oi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0Eu # Y3J0MIGBBgNVHR8EejB4MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20v # RGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5k # aWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsME8GA1UdIARI # MEYwOAYKYIZIAYb9bAACBDAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdp # Y2VydC5jb20vQ1BTMAoGCGCGSAGG/WwDMB0GA1UdDgQWBBRaxLl7KgqjpepxA8Bg # +S32ZXUOWDAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkqhkiG # 9w0BAQsFAAOCAQEAPuwNWiSz8yLRFcgsfCUpdqgdXRwtOhrE7zBh134LYP3DPQ/E # r4v97yrfIFU3sOH20ZJ1D1G0bqWOWuJeJIFOEKTuP3GOYw4TS63XX0R58zYUBor3 # nEZOXP+QsRsHDpEV+7qvtVHCjSSuJMbHJyqhKSgaOnEoAjwukaPAJRHinBRHoXpo # aK+bp1wgXNlxsQyPu6j4xRJon89Ay0BEpRPw5mQMJQhCMrI2iiQC/i9yfhzXSUWW # 6Fkd6fp0ZGuy62ZD2rOwjNXpDd32ASDOmTFjPQgaGLOBm0/GkxAG/AeB+ova+YJJ # 92JuoVP6EpQYhS6SkepobEQysmah5xikmmRR7zCCBY0wggR1oAMCAQICEA6bGI75 # 0C3n79tQ4ghAGFowDQYJKoZIhvcNAQEMBQAwZTELMAkGA1UEBhMCVVMxFTATBgNV # BAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIG # A1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTIyMDgwMTAwMDAw # MFoXDTMxMTEwOTIzNTk1OVowYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lD # ZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGln # aUNlcnQgVHJ1c3RlZCBSb290IEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC # CgKCAgEAv+aQc2jeu+RdSjwwIjBpM+zCpyUuySE98orYWcLhKac9WKt2ms2uexuE # DcQwH/MbpDgW61bGl20dq7J58soR0uRf1gU8Ug9SH8aeFaV+vp+pVxZZVXKvaJNw # wrK6dZlqczKU0RBEEC7fgvMHhOZ0O21x4i0MG+4g1ckgHWMpLc7sXk7Ik/ghYZs0 # 6wXGXuxbGrzryc/NrDRAX7F6Zu53yEioZldXn1RYjgwrt0+nMNlW7sp7XeOtyU9e # 5TXnMcvak17cjo+A2raRmECQecN4x7axxLVqGDgDEI3Y1DekLgV9iPWCPhCRcKtV # gkEy19sEcypukQF8IUzUvK4bA3VdeGbZOjFEmjNAvwjXWkmkwuapoGfdpCe8oU85 # tRFYF/ckXEaPZPfBaYh2mHY9WV1CdoeJl2l6SPDgohIbZpp0yt5LHucOY67m1O+S # kjqePdwA5EUlibaaRBkrfsCUtNJhbesz2cXfSwQAzH0clcOP9yGyshG3u3/y1Yxw # LEFgqrFjGESVGnZifvaAsPvoZKYz0YkH4b235kOkGLimdwHhD5QMIR2yVCkliWzl # DlJRR3S+Jqy2QXXeeqxfjT/JvNNBERJb5RBQ6zHFynIWIgnffEx1P2PsIV/EIFFr # b7GrhotPwtZFX50g/KEexcCPorF+CiaZ9eRpL5gdLfXZqbId5RsCAwEAAaOCATow # ggE2MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOzX44LScV1kTN8uZz/nupiu # HA9PMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA4GA1UdDwEB/wQE # AwIBhjB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp # Z2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQu # Y29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDBFBgNVHR8EPjA8MDqgOKA2 # hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290 # Q0EuY3JsMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQwFAAOCAQEAcKC/ # Q1xV5zhfoKN0Gz22Ftf3v1cHvZqsoYcs7IVeqRq7IviHGmlUIu2kiHdtvRoU9BNK # ei8ttzjv9P+Aufih9/Jy3iS8UgPITtAq3votVs/59PesMHqai7Je1M/RQ0SbQyHr # lnKhSLSZy51PpwYDE3cnRNTnf+hZqPC/Lwum6fI0POz3A8eHqNJMQBk1RmppVLC4 # oVaO7KTVPeix3P0c2PR3WlxUjG/voVA9/HYJaISfb8rbII01YBwCA8sgsKxYoA5A # Y8WYIsGyWfVVa88nq2x2zm8jLfR+cWojayL/ErhULSd+2DrZ8LaHlv1b0VysGMNN # n3O3AamfV6peKOK5lDCCBq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJ # 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 # ggbAMIIEqKADAgECAhADyzT9Pf8SETOf8HxLIVfHMA0GCSqGSIb3DQEBCwUAMGMx # CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMy # RGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcg # Q0EwHhcNMjIwODMwMDAwMDAwWhcNMjMwODI5MjM1OTU5WjBGMQswCQYDVQQGEwJV # UzERMA8GA1UEChMIRGlnaUNlcnQxJDAiBgNVBAMTG0RpZ2lDZXJ0IFRpbWVzdGFt # cCAyMDIyIC0gMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAM/spSY6 # xqnya7uNwQ2a26HoFIV0MxomrNAcVR4eNm28klUMYfSdCXc9FZYIL2tkpP0GgxbX # kZI4HDEClvtysZc6Va8z7GGK6aYo25BjXL2JU+A6LYyHQq4mpOS7eHi5ehbhVsbA # umRTuyoW51BIu4hpDIjG8b7gL307scpTjUCDHufLckkoHkyAHoVW54Xt8mG8qjoH # ffarbuVm3eJc9S/tjdRNlYRo44DLannR0hCRRinrPibytIzNTLlmyLuqUDgN5YyU # XRlav/V7QG5vFqianJVHhoV5PgxeZowaCiS+nKrSnLb3T254xCg/oxwPUAY3ugjZ # Naa1Htp4WB056PhMkRCWfk3h3cKtpX74LRsf7CtGGKMZ9jn39cFPcS6JAxGiS7uY # v/pP5Hs27wZE5FX/NurlfDHn88JSxOYWe1p+pSVz28BqmSEtY+VZ9U0vkB8nt9Kr # FOU4ZodRCGv7U0M50GT6Vs/g9ArmFG1keLuY/ZTDcyHzL8IuINeBrNPxB9Thvdld # S24xlCmL5kGkZZTAWOXlLimQprdhZPrZIGwYUWC6poEPCSVT8b876asHDmoHOWIZ # ydaFfxPZjXnPYsXs4Xu5zGcTB5rBeO3GiMiwbjJ5xwtZg43G7vUsfHuOy2SJ8bHE # uOdTXl9V0n0ZKVkDTvpd6kVzHIR+187i1Dp3AgMBAAGjggGLMIIBhzAOBgNVHQ8B # Af8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAg # BgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwHwYDVR0jBBgwFoAUuhbZ # bU2FL3MpdpovdYxqII+eyG8wHQYDVR0OBBYEFGKK3tBh/I8xFO2XC809KpQU31Kc # MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdp # Q2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcmwwgZAG # CCsGAQUFBwEBBIGDMIGAMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy # dC5jb20wWAYIKwYBBQUHMAKGTGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcnQw # DQYJKoZIhvcNAQELBQADggIBAC0UyaEGSS3dimxaHgXjrMnYnjeKsKYhIj9EyjE9 # ywwM33xT5ZRqdiX3Isk7nEIElPWCRN5u4oTo7k5EGGktx3ZsrHpzf0siEEmEdDfy # gtNBlXYxLvlZab8HVrslWfexM+66XRCFK19PgSnudu0gC3XaxWbC6eAeWmgBTLRk # tDRpqbY9fj1d6REtuXxf4RNrN0MDT+kVDdt1BVTHDTlfGDbA6HAXR1Vc+khF8cv4 # RMJ8vvP3p6z05qFttPe3RMWPCC+d8hKtJI+2C3hBwdKChzJizkfq60Vrqqj+dEeB # nrUYhUcYIIz6WeVYk72r/31a9SowYPuTzNCktU59LF6Y2/bMPIpHeHhsBAvg2RMx # DzH4TfzgKkGM8F8VDpTAKUXe8vlzzsNjJ4m+oeGi72Kj6if/M07iiT4kMEQV5Fg8 # BotKdIqx7a1Cf+aqpZq5+DAcFhPwo4uoKtSLAWY0aIACxRKSFqIHngiuc2t9n+vB # /oM/rtlQNnnlt8E2hvC3yQl5+M/7sqzX4vI3BBv6ASmOsDaYOGrb90BA77kpxccg # avKscb/UdmJ+yGZjMyuuUzjPpKpGxMG95S9ATieDVuDFi68taSY81PJVmxBD/MrB # bfTZ9JBLS5F1s0ecKEr6OOY1PvLIry+8TrgnFUP5KT019GjiRV2GVCOBx9aBB9M+ # oTliMYIFXTCCBVkCAQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lD # ZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGln # aUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBDQQIQAwW7hiGwoWNf # v96uEgTnbTANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgACh # AoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAM # BgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCD/dmMP+WVqt9VUSyonWl4i3kdQ # fFFzcVPSD+g79qRz9jANBgkqhkiG9w0BAQEFAASCAQATe2Dm7G53Dk+ejGfvekY7 # gzkZwNht3rPYEW7Is3upvmAwcjnQD1VNexeQHWKHBeCQKPe1CWzqROS9JIgg2p+0 # IiSht6SyyL7A28DAPxdEGPHqA4hPi3RVi6vy/rn6uuoAEE3puo3ghgqA/OAntr8B # gtkcapgEBDZW/0KvBtOEyc+EdJtnuv7t9sGvwcmgWxTgbQhaesdWwUG47JFRu+Io # F7dJFbKdRsrjsfwStB5LkikAoYieSLCgvfeQ2ma6iEGscNeBeT3iiEP6xJJ6ubV4 # K0vjqYL/6c83dkxBT/1zZE6KqlWbjMmouoFNoEaYRKAtINfQ0ut6jH9FKmUiQY1x # oYIDIDCCAxwGCSqGSIb3DQEJBjGCAw0wggMJAgEBMHcwYzELMAkGA1UEBhMCVVMx # FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVz # dGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQQIQA8s0/T3/EhEz # n/B8SyFXxzANBglghkgBZQMEAgEFAKBpMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0B # BwEwHAYJKoZIhvcNAQkFMQ8XDTIyMDkyMTA5MzczNFowLwYJKoZIhvcNAQkEMSIE # II5R9VSBa0VK6HcY061p9Zn+npXMRvT9xUB+/tdLu/F6MA0GCSqGSIb3DQEBAQUA # BIICABt2gW/73sys5vqx+WiwVpqMy1XdwC8hG5JHrKH8cb6s9HAO87hMvGyv5opt # qrASTdWr/2PSi+4UwSQaDW9ks0+ezC8zhs4fmGdMvEBOQMqRfwQeDv2lBifmK7OV # rK4PneMHiFxA022ILJxuRenXqpsWlrFrme3BEFhgZp/3XSbBhKuOuXLPsVXXZ6qa # bV6tImWoHmvH3ecbF+fweUzpS4/0HtUhMU7ZuC+/A7vs8CDfc0z/A/ckGJXvUVZK # eAFnL+s/OVsOqCr1UDdS18G01BP/Xflf7EUB/9Bc3eyFjcP7Sxf5yrdRoCaK6fZf # WzgjPZ3IDaIMuJI8cqOg1/d2SwiHGAMznx/s/bdk5lHfvZx7q4A7CmltTF6dpL6M # WGdXcg0uBOoJXTvNwwwuQob1V6DZ0nusVGUTJDD5jFqrwTRPwkqNCBGn6ST1thza # /QcVX/ISJog2zQZtHMvoKlNywf/YmEYBqjhrQ7tDHU4gn7bVZNsu4w9yWCXA2MV3 # 2Iwy8BLyEvnOk2BovF+dhhHfvBbfAmSqoZ6/O+3CVIpdZgeun/rMsBen3aa09xZA # P2htrTsJPipZd+j0ijGi31AE5s2L+Gqe0T9Z8cZ5PpSWeyVQS9FS97ORZbfT2TOj # 6M4A6Yzt93NAvkuJ4jqo+NCl4KZgkun4VogNjAeS6mqJ/cr2 # SIG # End signature block |