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 { Invoke-SQLiteBulkCopy -DataTable ([pscustomobject]@{ UpdateId = $guid; Dupe = $file.BaseName } | 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 # MIIjZQYJKoZIhvcNAQcCoIIjVjCCI1ICAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUWQ9oEvp4gDBdlpHn7d8eyEhv # PPCggh2DMIIFGjCCBAKgAwIBAgIQAwW7hiGwoWNfv96uEgTnbTANBgkqhkiG9w0B # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz # c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTIwMDUxMjAwMDAwMFoXDTIzMDYw # ODEyMDAwMFowVzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMQ8wDQYD # VQQHEwZWaWVubmExETAPBgNVBAoTCGRiYXRvb2xzMREwDwYDVQQDEwhkYmF0b29s # czCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALy/Y3ur47++CAG2mOa1 # 6h8WjXjSTvcldDmw4PpAvOOCKNr6xyhg/FOYVIiaeq2N9kVaa5wBawOIxVWuj/rI # aOxeYklQDugPkGUx0Ap+6KrjnnxgE6ONzQGnc1tjlka6N0KazD2WodEBWKXo/Vmk # C/cP9PJVWroCMOwlj7GtEv2IxzxikPm2ICP5KxFK5PmrA+5bzcHJEeqRonlgMn9H # zZkqHr0AU1egnfEIlH4/v6lry1t1KBF/bnDhl9g/L0icS+ychFVkx4OOO4a+qvT8 # xqvvdQjv3PQ1hbzTI3/tXOWu9XxGeeIdZjaJv16FmWKCnloSp1Xb9cVU9XhIpomz # xH0CAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nEDwGD5LfZldQ5Y # MB0GA1UdDgQWBBTwwKD7tgOAQ077Cdfd33qxy+OeIjAOBgNVHQ8BAf8EBAMCB4Aw # EwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0fBHAwbjA1oDOgMYYvaHR0cDovL2Ny # bDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwNaAzoDGGL2h0 # dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3JsMEwG # A1UdIARFMEMwNwYJYIZIAYb9bAMBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3 # LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQQBMIGEBggrBgEFBQcBAQR4MHYwJAYI # KwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBOBggrBgEFBQcwAoZC # aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3VyZWRJ # RENvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQAD # ggEBAI/N+XCVDB/WNqQSrKY85zScHGJjsXgXByYvsitMuG5vo+ODhlh+ILv0CTPl # o2Wo75MnSSqCWR+c6xyN8pDPMPBxm2EtVmXzeKDMIudYyjxmT8PZ3hktj16wXCo8 # 2+65UOse+CHsfoMn/M9WbkQ4rSyWNPRRDodATC2i4flLyeuoIZnyMoz/4N4mWb6s # IAYZ/tNXzm6qwCfkmoMSf9tcTUCXIbVDliJcUZLlJ/SpLg2KzDu9GtnpBzg3AG3L # hwBiPMM8OLGitYjz4VU5RYox0vu1XyLf3f9fKTCxxwKy0EKntWdJk37i+DOMQlCq # Xm5B/KyNxb2utv+qLGlyw9MphEcwggUwMIIEGKADAgECAhAECRgbX9W7ZnVTQ7Vv # lVAIMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdp # Q2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0Rp # Z2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xMzEwMjIxMjAwMDBaFw0yODEw # MjIxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx # GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNI # QTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUA # A4IBDwAwggEKAoIBAQD407Mcfw4Rr2d3B9MLMUkZz9D7RZmxOttE9X/lqJ3bMtdx # 6nadBS63j/qSQ8Cl+YnUNxnXtqrwnIal2CWsDnkoOn7p0WfTxvspJ8fTeyOU5JEj # lpB3gvmhhCNmElQzUHSxKCa7JGnCwlLyFGeKiUXULaGj6YgsIJWuHEqHCN8M9eJN # YBi+qsSyrnAxZjNxPqxwoqvOf+l8y5Kh5TsxHM/q8grkV7tKtel05iv+bMt+dDk2 # DZDv5LVOpKnqagqrhPOsZ061xPeM0SAlI+sIZD5SlsHyDxL0xY4PwaLoLFH3c7y9 # hbFig3NBggfkOItqcyDQD2RzPJ6fpjOp/RnfJZPRAgMBAAGjggHNMIIByTASBgNV # HRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEF # BQcDAzB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp # Z2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQu # Y29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0fBHoweDA6oDig # NoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9v # dENBLmNybDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0 # QXNzdXJlZElEUm9vdENBLmNybDBPBgNVHSAESDBGMDgGCmCGSAGG/WwAAgQwKjAo # BggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAKBghghkgB # hv1sAzAdBgNVHQ4EFgQUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHwYDVR0jBBgwFoAU # Reuir/SSy4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQELBQADggEBAD7sDVoks/Mi # 0RXILHwlKXaoHV0cLToaxO8wYdd+C2D9wz0PxK+L/e8q3yBVN7Dh9tGSdQ9RtG6l # jlriXiSBThCk7j9xjmMOE0ut119EefM2FAaK95xGTlz/kLEbBw6RFfu6r7VRwo0k # riTGxycqoSkoGjpxKAI8LpGjwCUR4pwUR6F6aGivm6dcIFzZcbEMj7uo+MUSaJ/P # QMtARKUT8OZkDCUIQjKyNookAv4vcn4c10lFluhZHen6dGRrsutmQ9qzsIzV6Q3d # 9gEgzpkxYz0IGhizgZtPxpMQBvwHgfqL2vmCSfdibqFT+hKUGIUukpHqaGxEMrJm # oecYpJpkUe8wggWxMIIEmaADAgECAhABJAr7HjgLihbxS3Gd9NPAMA0GCSqGSIb3 # DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAX # BgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3Vy # ZWQgSUQgUm9vdCBDQTAeFw0yMjA2MDkwMDAwMDBaFw0zMTExMDkyMzU5NTlaMGIx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBH # NDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8MCIw # aTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauyefLK # EdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34LzB4Tm # dDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+xembu # d8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhAkHnD # eMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1LyuGwN1 # XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2PVld # QnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37AlLTS # YW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD76GSm # M9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/ybzT # QRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXAj6Kx # fgommfXkaS+YHS312amyHeUbAgMBAAGjggFeMIIBWjAPBgNVHRMBAf8EBTADAQH/ # MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwPTzAfBgNVHSMEGDAWgBRF66Kv # 9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYB # BQUHAwgweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5k # aWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDig # NoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9v # dENBLmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZI # hvcNAQEMBQADggEBAJoWAqUB74H7DbRYsnitqCMZ2XM32mCeUdfL+C9AuaMffEBO # Mz6QPOeJAXWF6GJ7HVbgcbreXsY3vHlcYgBN+El6UU0GMvPF0gAqJyDqiS4VOeAs # Pvh1fCyCQWE1DyPQ7TWV0oiVKUPL4KZYEHxTjp9FySA3FMDtGbp+dznSVJbHphHf # NDP2dVJCSxydjZbVlWxHEhQkXyZB+hpGvd6w5ZFHA6wYCMvL22aJfyucZb++N06+ # LfOdSsPMzEdeyJWVrdHLuyoGIPk/cuo260VyknopexQDPPtN1khxehARigh0zWwb # BFzSipUDdlFQU9Yu90pGw64QLHFMsIe2JzdEYEQwggauMIIElqADAgECAhAHNje3 # JFR82Ees/ShmKl5bMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYD # VQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAf # BgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMjAzMjMwMDAwMDBa # Fw0zNzAzMjIyMzU5NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2Vy # dCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNI # QTI1NiBUaW1lU3RhbXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK # AoICAQDGhjUGSbPBPXJJUVXHJQPE8pE3qZdRodbSg9GeTKJtoLDMg/la9hGhRBVC # X6SI82j6ffOciQt/nR+eDzMfUBMLJnOWbfhXqAJ9/UO0hNoR8XOxs+4rgISKIhjf # 69o9xBd/qxkrPkLcZ47qUT3w1lbU5ygt69OxtXXnHwZljZQp09nsad/ZkIdGAHvb # REGJ3HxqV3rwN3mfXazL6IRktFLydkf3YYMZ3V+0VAshaG43IbtArF+y3kp9zvU5 # EmfvDqVjbOSmxR3NNg1c1eYbqMFkdECnwHLFuk4fsbVYTXn+149zk6wsOeKlSNbw # sDETqVcplicu9Yemj052FVUmcJgmf6AaRyBD40NjgHt1biclkJg6OBGz9vae5jtb # 7IHeIhTZgirHkr+g3uM+onP65x9abJTyUpURK1h0QCirc0PO30qhHGs4xSnzyqqW # c0Jon7ZGs506o9UD4L/wojzKQtwYSH8UNM/STKvvmz3+DrhkKvp1KCRB7UK/BZxm # SVJQ9FHzNklNiyDSLFc1eSuo80VgvCONWPfcYd6T/jnA+bIwpUzX6ZhKWD7TA4j+ # s4/TXkt2ElGTyYwMO1uKIqjBJgj5FBASA31fI7tk42PgpuE+9sJ0sj8eCXbsq11G # deJgo1gJASgADoRU7s7pXcheMBK9Rp6103a50g5rmQzSM7TNsQIDAQABo4IBXTCC # AVkwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUuhbZbU2FL3MpdpovdYxq # II+eyG8wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/ # BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggr # BgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVo # dHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0 # LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20v # RGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjAL # BglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIBAH1ZjsCTtm+YqUQiAX5m1tgh # QuGwGC4QTRPPMFPOvxj7x1Bd4ksp+3CKDaopafxpwc8dB+k+YMjYC+VcW9dth/qE # ICU0MWfNthKWb8RQTGIdDAiCqBa9qVbPFXONASIlzpVpP0d3+3J0FNf/q0+KLHqr # hc1DX+1gtqpPkWaeLJ7giqzl/Yy8ZCaHbJK9nXzQcAp876i8dU+6WvepELJd6f8o # VInw1YpxdmXazPByoyP6wCeCRK6ZJxurJB4mwbfeKuv2nrF5mYGjVoarCkXJ38SN # oOeY+/umnXKvxMfBwWpx2cYTgAnEtp/Nh4cku0+jSbl3ZpHxcpzpSwJSpzd+k1Os # Ox0ISQ+UzTl63f8lY5knLD0/a6fxZsNBzU+2QJshIUDQtxMkzdwdeDrknq3lNHGS # 1yZr5Dhzq6YBT70/O3itTK37xJV77QpfMzmHQXh6OOmc4d0j/R0o08f56PGYX/sr # 2H7yRp11LB4nLCbbbxV7HhmLNriT1ObyF5lZynDwN7+YAN8gFk8n+2BnFqFmut1V # wDophrCYoCvtlUG3OtUVmDG0YgkPCr2B2RP+v6TR81fZvAT6gt4y3wSJ8ADNXcL5 # 0CN/AAvkdgIm2fBldkKmKYcJRyvmfxqkhQ/8mJb2VVQrH4D6wPIOK+XW+6kvRBVK # 5xMOHds3OBqhK/bt1nz8MIIGxjCCBK6gAwIBAgIQCnpKiJ7JmUKQBmM4TYaXnTAN # BgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs # IEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEy # NTYgVGltZVN0YW1waW5nIENBMB4XDTIyMDMyOTAwMDAwMFoXDTMzMDMxNDIzNTk1 # OVowTDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSQwIgYD # VQQDExtEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMiAtIDIwggIiMA0GCSqGSIb3DQEB # AQUAA4ICDwAwggIKAoICAQC5KpYjply8X9ZJ8BWCGPQz7sxcbOPgJS7SMeQ8QK77 # q8TjeF1+XDbq9SWNQ6OB6zhj+TyIad480jBRDTEHukZu6aNLSOiJQX8Nstb5hPGY # Pgu/CoQScWyhYiYB087DbP2sO37cKhypvTDGFtjavOuy8YPRn80JxblBakVCI0Fa # +GDTZSw+fl69lqfw/LH09CjPQnkfO8eTB2ho5UQ0Ul8PUN7UWSxEdMAyRxlb4pgu # j9DKP//GZ888k5VOhOl2GJiZERTFKwygM9tNJIXogpThLwPuf4UCyYbh1RgUtwRF # 8+A4vaK9enGY7BXn/S7s0psAiqwdjTuAaP7QWZgmzuDtrn8oLsKe4AtLyAjRMruD # +iM82f/SjLv3QyPf58NaBWJ+cCzlK7I9Y+rIroEga0OJyH5fsBrdGb2fdEEKr7mO # CdN0oS+wVHbBkE+U7IZh/9sRL5IDMM4wt4sPXUSzQx0jUM2R1y+d+/zNscGnxA7E # 70A+GToC1DGpaaBJ+XXhm+ho5GoMj+vksSF7hmdYfn8f6CvkFLIW1oGhytowkGvu # b3XAsDYmsgg7/72+f2wTGN/GbaR5Sa2Lf2GHBWj31HDjQpXonrubS7LitkE956+n # GijJrWGwoEEYGU7tR5thle0+C2Fa6j56mJJRzT/JROeAiylCcvd5st2E6ifu/n16 # awIDAQABo4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYD # VR0lAQH/BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZI # AYb9bAcBMB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQW # BBSNZLeJIf5WWESEYafqbxw2j92vDTBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8v # Y3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2 # VGltZVN0YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcw # AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8v # Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hB # MjU2VGltZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQANLSN0ptH1 # +OpLmT8B5PYM5K8WndmzjJeCKZxDbwEtqzi1cBG/hBmLP13lhk++kzreKjlaOU7Y # hFmlvBuYquhs79FIaRk4W8+JOR1wcNlO3yMibNXf9lnLocLqTHbKodyhK5a4m1Wp # Gmt90fUCCU+C1qVziMSYgN/uSZW3s8zFp+4O4e8eOIqf7xHJMUpYtt84fMv6XPfk # U79uCnx+196Y1SlliQ+inMBl9AEiZcfqXnSmWzWSUHz0F6aHZE8+RokWYyBry/J7 # 0DXjSnBIqbbnHWC9BCIVJXAGcqlEO2lHEdPu6cegPk8QuTA25POqaQmoi35komWU # EftuMvH1uzitzcCTEdUyeEpLNypM81zctoXAu3AwVXjWmP5UbX9xqUgaeN1Gdy4b # esAzivhKKIwSqHPPLfnTI/KeGeANlCig69saUaCVgo4oa6TOnXbeqXOqSGpZQ65f # 6vgPBkKd3wZolv4qoHRbY2beayy4eKpNcG3wLPEHFX41tOa1DKKZpdcVazUOhdbg # LMzgDCS4fFILHpl878jIxYxYaa+rPeHPzH0VrhS/inHfypex2EfqHIXgRU4SHBQp # WMxv03/LvsEOSm8gnK7ZczJZCOctkqEaEf4ymKZdK5fgi9OczG21Da5HYzhHF1tv # E9pqEG4fSbdEW7QICodaWQR2EaGndwITHDGCBUwwggVIAgEBMIGGMHIxCzAJBgNV # BAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdp # Y2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2Rl # IFNpZ25pbmcgQ0ECEAMFu4YhsKFjX7/erhIE520wCQYFKw4DAhoFAKB4MBgGCisG # AQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFCjh # qS2yeWKUk5qHLZVO9EV9bgLzMA0GCSqGSIb3DQEBAQUABIIBAJwzyLlav+p67hq9 # TVRiPEf3TCyaCK0i0LHzKYwdZYSM4pAXbuC0A6CUK0zl21e8j2+obF+WvEGcyVZh # y0/2VgsR6Rgh0WMR8cGTrfOeHViDQGCt0lARUfKCqjeXqIC24+7WKLz+smvpXxDW # EGQLO9YUiuetLaWRKm58oNL6laudqqJ+HNyHIcDGycjKQoLouCy+CIa4aipZEIy5 # uxa+Edc7LVsAo3ZkA66/xr5Tj1hC1v4W7gDqQJNWoVsj8luEs3lkMeKSvEkje1Ok # c4w4XXR63yOQeHdj7A1fhyDNcg7CcZbXy9jY5YyXTOiEU0LMu6yZ9BqFa0vyciQb # XhysC5ShggMgMIIDHAYJKoZIhvcNAQkGMYIDDTCCAwkCAQEwdzBjMQswCQYDVQQG # EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0 # IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBAhAKekqI # nsmZQpAGYzhNhpedMA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqG # SIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjIwODAxMjAzMTUxWjAvBgkqhkiG9w0B # CQQxIgQg3PnsJNiu8Ti1uNx//9vNjWiDte5kWBR+3EIIhSy72yAwDQYJKoZIhvcN # AQEBBQAEggIAqP5jPY3BA+lmCKrEdPMBtVg8AmqmjAhLeq8kKa5NpNfeO/oaxUC2 # UvH7wd+eLZZJtu9eQLUMe6xfzfN/K+6yJ3zwYl4V0q+WogalOMtIsCyRVwrABwxI # vDwlDTXfyPMTqCEGiWhaDHuYaQDE7dE104YiTjT2zxFL2cHOsIbOb6Obuk51Pwlt # zfo7i4jVAl77gLmln+RnrlU0FhUs17CEWrrRF4MDpwbbjArYTmzScOoFjRoU5sJH # B3MgSBPi2zhualgB1DIEnLnv7bKeTCJZL7EVbHerHw5hbjuHkBqQCiPyXwUm9eYm # X1nyrBBGcZGRcd+rkXxWC4CFeu3b3IurhxcRG+wIsB3+kmQVy3jDEX4JMwCROhMQ # mNBVN+Oz8KsTw9C3leaTRNm8CMZuXr7Rb3oWPKdgFXo4mUUQX52ATR6CvPoe5Ymg # +EgsaO1ifGzfLyHjd8gCxs6gmqW+QAM8e6Jo4Tg0DEtIdbn7Bp+8YcMwHHSOrcot # DQgxIy9y8bXb8vp103LN7FwUURnJ4YnqXXK1Yz3v55ubux+tsZu7siLeV4XwFifw # ijj6GgTbQ3WecF9We3YvWpUMMBIV9YYEv/rvMkbMBjvDHgbMe2uK92ZZ6hL5q50d # YAB1q0BiExBBQCUxfElW1hrDAA/ToPsDvW4HeYpP9XDCHFqxAMqkisU= # SIG # End signature block |