Parse-OSOTConfig.ps1
<#PSScriptInfo
.VERSION 0.7 .GUID 9665fc5d-be92-46e9-acac-cfd3637a3b0a .AUTHOR Evgenij Smirnov .COMPANYNAME metaBPA.org .COPYRIGHT 2020 metaBPA.org .TAGS .LICENSEURI .PROJECTURI https://metabpa.org/projects/various-scripts/osot-parser/ .ICONURI https://metabpa.org/wp-content/uploads/2019/11/metaBPA-150x150.ico .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .SYNOPSIS Parses an OSOT configuration file and generates actual executable scripts (.cmd and .ps1). .DESCRIPTION Parses an OSOT configuration file and generates actual executable scripts. .PARAMETER OSOTFIle Full path to XML file generated by OSOT. .PARAMETER OutPath Full path to folder where generated files will be created. .PARAMETER UsePowerShellForServiceCommands Output 'Set-Service' and 'Stop-Service' instead of 'sc config' and 'sc stop'. .PARAMETER UsePowerShellForSchTasksCommands Output 'Enable-ScheduledTask' and 'Disable-ScheduledTask' instead of 'schtasks.exe'. .PARAMETER AddCommentsToOutput Incorporate commets from the XML file into the script .PARAMETER PassThru Output the actual commands to the pipeline instead of statistics. .PARAMETER MaskExtensions Make the output files non-executable by adding.txt to the full path. .PARAMETER SuppressFileOutput Suppress the creation of output files. .INPUTS None. You cannot pipe objects to Parse-OSOTConfig.ps1. .OUTPUTS If -PassThru is specified, an array of PSCustomObjects each representing a command to run on an image. If -PassThru is not specified, an PSCustomObject that contains some statistics about the processed config. .EXAMPLE ./Parse-OSOTConfig.ps1 -OSOTFile c:\temp\Win10Config.xml -OutPath c:\temp\osotcommands -PassThru .EXAMPLE ./Parse-OSOTConfig.ps1 -OSOTFile c:\temp\Win10Config.xml -OutPath c:\temp\osotcommands -UsePowerShellForServiceCommands -AddCommentsToOutput .LINK https://metabpa.org/projects/various-scripts/osot-parser/ .LINK https://flings.vmware.com/vmware-os-optimization-tool #> [CmdletBinding()] Param( [Parameter(Mandatory=$true)][System.IO.FileInfo]$OSOTFile, [Parameter(Mandatory=$true)][System.IO.FileInfo]$OutPath, [Parameter(Mandatory=$false)][switch]$UsePowerShellForServiceCommands, [Parameter(Mandatory=$false)][switch]$UsePowerShellForSchTasksCommands, [Parameter(Mandatory=$false)][switch]$AddCommentsToOutput, [Parameter(Mandatory=$false)][switch]$PassThru, [Parameter(Mandatory=$false)][switch]$MaskExtensions, [Parameter(Mandatory=$false)][switch]$SuppressFileOutput ) #region functions function Make-Content { [CmdletBinding()] Param( [Parameter(Mandatory=$true)][string]$OutFile, [Parameter(Mandatory=$false)][string]$FileComment, [Parameter(Mandatory=$true)][PSCustomObject[]]$ContentData ) if ($ContentData.Where({$_.lang -eq 'powershell'}).Count -gt 0) { $ps_out_file = "$OutPath\$($OutFile).ps1" if ($MaskExtensions) { $ps_out_file = $ps_out_file + ".txt" } "<#`r`n`t$FileComment from OST File $($OSOTFile.FullName)`r`n#>`r`n" | Set-Content -Path $ps_out_file -Encoding UTF8 -Force } if ($ContentData.Where({$_.lang -eq 'cmd'}).Count -gt 0) { $cmd_out_file = "$OutPath\$($OutFile).cmd" if ($MaskExtensions) { $cmd_out_file = $cmd_out_file + ".txt" } "@ECHO OFF`r`nREM $FileComment from OST File $($OSOTFile.FullName)`r`n" | Set-Content -Path $cmd_out_file -Encoding UTF8 -Force } foreach ($action in $ContentData.where({!$_.defuser})) { if ($action.lang -eq 'cmd') { if ($AddCommentsToOutput) { "REM $($action.group) | $($action.comment)" | Add-Content $cmd_out_file -Encoding UTF8 } $action.line | Add-Content $cmd_out_file -Encoding UTF8 } elseif ($action.lang -eq 'powershell') { if ($AddCommentsToOutput) { "# $($action.group) | $($action.comment)" | Add-Content $ps_out_file -Encoding UTF8 } $action.line | Add-Content $ps_out_file -Encoding UTF8 } } if ($stats.DefaultUserActions -gt 0) { 'reg LOAD "HKEY_USERS\temp" C:\Users\Default\NTUSERS.DAT' | Add-Content $cmd_out_file -Encoding UTF8 foreach ($action in $ContentData.where({$_.defuser})) { if ($action.lang -eq 'cmd') { if ($AddCommentsToOutput) { "REM $($action.group) | $($action.comment)" | Add-Content $cmd_out_file -Encoding UTF8 } $action.line | Add-Content $cmd_out_file -Encoding UTF8 } elseif ($action.lang -eq 'powershell') { Write-Warning "PowerShell action in default user context: $($action.line)" } } 'reg UNLOAD "HKEY_USERS\temp"' | Add-Content $cmd_out_file -Encoding UTF8 } } #endregion #region init if (Test-Path -Path $OSOTFile -PathType Leaf) { try { $OSOTConfig = [xml](Get-Content -Path $OSOTFile) } catch { Write-Warning "Error parsing XML: $($_.Exception.Message)" return 7 } } else { Write-Warning "File not found: $OSOTFile" return 2 } if ($SuppressFileOutput -and ($MaskExtensions -or $AddCommentsToOutput)) { Write-Warning "You specified -SuppressFileOutput together with one of the file modifiers (-MaskExtensions and -AddCommentsToOutput). No output files will be created." } $cmd = @() $unprocessed = 0 $nline = 0 #endregion #region parse foreach ($ActionGroup in $OSOTConfig.sequence.group.ChildNodes) { foreach ($ActionStepBlock in $ActionGroup.childNodes) { $ActionStep = $ActionStepBlock.action $nline++ switch ($ActionStep.type) { 'Registry' { $regcmd = $null if ($ActionStep.params.keyName -eq $null) { Write-Warning "Null key value encountered!" $unprocessed++ } else { $xkey = (($ActionStep.params.keyName.Trim() -replace "HKLM","HKEY_LOCAL_MACHINE") -replace "HKU","HKEY_USERS") -replace "HKCU","HKEY_CURRENT_USER" $xval = $null $xtype = $null $xdata = $null switch ($ActionStep.command) { 'ADD' { $xval = $ActionStep.params.valueName $xdata = $ActionStep.params.data $xtype = $ActionStep.params.type if ($xval -eq $null) { if ($xtype -ne $null) { $xval = '(Default)' } } else { $xval = $xval.Trim() } if ($xval) { $xval = ('/v "{0}"' -f $xval) if ($xtype -eq 'REG_SZ') { $xdata = ('/d "{0}"' -f $xdata) } else { $xdata = ('/d {0}' -f $xdata) } $xtype = ('/t {0}' -f $xtype) } $regcmd = "$(('reg ADD "{0}" {1} {2} {3}' -f $xkey,$xval,$xtype,$xdata).Trim()) /f" } 'DELETEVALUE' { $xval = $ActionStep.params.valueName if ($xval) { $xkey = ('{0}\{1}' -f $xkey,$xval) } $regcmd = "$('reg DELETE "{0}"' -f $xkey) /f" } 'LOAD' { <# nuthin' to do, will be added automatically #> } 'UNLOAD' { <# nuthin' to do, will be added automatically #> } default { Write-Warning "Unknown registry operation: $($ActionStep.command)" $unprocessed++ } } if ($null -ne $regcmd) { $cmd += [PSCustomObject]@{ 'nline' = $nline 'lang' = 'cmd' 'line' = $regcmd 'recommended' = ($ActionStepBlock.category -eq 'recommended') 'mandatory' = ($ActionStepBlock.category -eq 'mandatory') 'defuser' = ($regcmd -match 'HKEY_USERS\\temp\\') 'comment' = $ActionStepBlock.description 'group' = $ActionGroup.name } } } } 'Service' { $xname = $ActionStep.params.serviceName $xmode = $ActionStep.params.startMode if ($null -ne $xname) { if ($null -ne $xmode) { if ($UsePowerShellForServiceCommands) { $cmd += [PSCustomObject]@{ 'nline' = $nline 'lang' = 'powershell' 'line' = 'Set-Service "{0}" -StartupType {1}' -f $xname,$xmode 'recommended' = ($ActionStepBlock.category -eq 'recommended') 'mandatory' = ($ActionStepBlock.category -eq 'mandatory') 'defuser' = $false 'comment' = $ActionStepBlock.description 'group' = $ActionGroup.name } if ($xmode -ne 'AUTOMATIC') { $cmd += [PSCustomObject]@{ 'nline' = $nline 'lang' = 'powershell' 'line' = 'Stop-Service "{0}" -Force' -f $xname 'recommended' = ($ActionStepBlock.category -eq 'recommended') 'mandatory' = ($ActionStepBlock.category -eq 'mandatory') 'defuser' = $false 'comment' = $ActionStepBlock.description 'group' = $ActionGroup.name } } } else { $cmd += [PSCustomObject]@{ 'nline' = $nline 'lang' = 'cmd' 'line' = 'sc config "{0}" start={1}' -f $xname,$xmode 'recommended' = ($ActionStepBlock.category -eq 'recommended') 'mandatory' = ($ActionStepBlock.category -eq 'mandatory') 'defuser' = $false 'comment' = $ActionStepBlock.description 'group' = $ActionGroup.name } if ($xmode -ne 'AUTOMATIC') { $cmd += [PSCustomObject]@{ 'nline' = $nline 'lang' = 'cmd' 'line' = 'sc stop "{0}"' -f $xname 'recommended' = ($ActionStepBlock.category -eq 'recommended') 'mandatory' = ($ActionStepBlock.category -eq 'mandatory') 'defuser' = $false 'comment' = $ActionStepBlock.description 'group' = $ActionGroup.name } } } } else { Write-Warning "Service start mode empty at step $($ActionStepBlock.name)" $unprocessed++ } } else { Write-Warning "Service name empty at step $($ActionStepBlock.name)" $unprocessed++ } } 'SchTasks' { $xname = $ActionStep.params.TaskName $xmode = $ActionStep.params.Status if ($null -ne $xname) { if ($null -ne $xmode) { if ($UsePowerShellForServiceCommands) { if ($xmode -eq 'DISABLED') { $xmode = 'Disable' } else { $xmode = 'Enable' } if ($xname -match "\\") { $xpath = "\" + $xname.Substring(0,$xname.LastIndexOf("\") + 1) $xname = $xname.Substring($xname.LastIndexOf("\") + 1) } else { $xpath = "\" } $cmd += [PSCustomObject]@{ 'nline' = $nline 'lang' = 'powershell' 'line' = '{1}-ScheduledTask -TaskName "{0}" -TaskPath "{2}"' -f $xname,$xmode,$xpath 'recommended' = ($ActionStepBlock.category -eq 'recommended') 'mandatory' = ($ActionStepBlock.category -eq 'mandatory') 'defuser' = $false 'comment' = $ActionStepBlock.description 'group' = $ActionGroup.name } } else { if ($xmode -eq 'DISABLED') { $xmode = 'disable' } else { $xmode = 'enable' } $cmd += [PSCustomObject]@{ 'nline' = $nline 'lang' = 'cmd' 'line' = 'schtasks /change /tn "{0}" /{1}' -f $xname,$xmode 'recommended' = ($ActionStepBlock.category -eq 'recommended') 'mandatory' = ($ActionStepBlock.category -eq 'mandatory') 'defuser' = $false 'comment' = $ActionStepBlock.description 'group' = $ActionGroup.name } } } else { Write-Warning "SchTask status empty at step $($ActionStepBlock.name)" $unprocessed++ } } else { Write-Warning "SchTask name empty at step $($ActionStepBlock.name)" $unprocessed++ } } 'ShellExecute' { $xcmd = $ActionStep.command if (($xcmd -match '^Powershell "& {(?<pscmd>[a-zA-Z\d]+\-[a-zA-Z\d]+\s.*)}"$') -or ($xcmd -match '^Powershell (?<pscmd>[a-zA-Z\d]+\-[a-zA-Z\d]+\s.*)$')) { $cmd += [PSCustomObject]@{ 'nline' = $nline 'lang' = 'powershell' 'line' = $Matches['pscmd'] 'recommended' = ($ActionStepBlock.category -eq 'recommended') 'mandatory' = ($ActionStepBlock.category -eq 'mandatory') 'defuser' = $false 'comment' = $ActionStepBlock.description 'group' = $ActionGroup.name } } elseif ($xcmd -match '^Powershell "& {(?<batcmd>.*)}"$') { $cmd += [PSCustomObject]@{ 'nline' = $nline 'lang' = 'cmd' 'line' = $Matches['batcmd'] 'recommended' = ($ActionStepBlock.category -eq 'recommended') 'mandatory' = ($ActionStepBlock.category -eq 'mandatory') 'defuser' = $false 'comment' = $ActionStepBlock.description 'group' = $ActionGroup.name } } elseif ($xcmd -match '^Powershell (?<batcmd>.*)$') { $cmd += [PSCustomObject]@{ 'nline' = $nline 'lang' = 'cmd' 'line' = $Matches['batcmd'] 'recommended' = ($ActionStepBlock.category -eq 'recommended') 'mandatory' = ($ActionStepBlock.category -eq 'mandatory') 'defuser' = $false 'comment' = $ActionStepBlock.description 'group' = $ActionGroup.name } } else { $cmd += [PSCustomObject]@{ 'nline' = $nline 'lang' = 'cmd' 'line' = $xcmd 'recommended' = ($ActionStepBlock.category -eq 'recommended') 'mandatory' = ($ActionStepBlock.category -eq 'mandatory') 'defuser' = $false 'comment' = $ActionStepBlock.description 'group' = $ActionGroup.name } } } default { if ($ActionStep.type -ne $null) { Write-Warning "Unknown action type: $($ActionStep.type) at step $($ActionStepBlock.name)" $unprocessed++ } } } } } #endregion #region stats $stats = [PSCustomObject]@{ 'OSOTFile' = $OSOTFile.FullName 'TotalActions' = $cmd.Count 'CMDActions' = $cmd.Where({$_.lang -eq 'cmd'}).Count 'PSActions' = $cmd.Where({$_.lang -eq 'powershell'}).Count 'DefaultUserActions' = $cmd.Where({$_.defuser}).Count 'MandatoryActions' = $cmd.Where({$_.mandatory}).Count 'RecommendedActions' = $cmd.Where({$_.recommended}).Count 'OptionalActions' = $cmd.Where({!$_.recommended -and !$_.mandatory}).Count 'UnprocessedSteps' = $unprocessed } #endregion #region output if (!$SuppressFileOutput) { if (!(Test-Path $OutPath -Pathtype Container)) { New-Item $OutPath -ItemType Directory -Force } [ordered]@{'stats' = $stats; 'commands' = $cmd} | ConvertTo-Json -Depth 4 | Set-Content "$OutPath\osot_processed.json" -Force Make-Content -OutFile 'all_actions' -FileComment 'All Actions' -ContentData $cmd Make-Content -OutFile 'mandatory_actions' -FileComment 'Mandatory Actions' -ContentData ($cmd.Where({$_.mandatory})) Make-Content -OutFile 'recommended_actions' -FileComment 'Recommended Actions' -ContentData ($cmd.Where({$_.recommended})) Make-Content -OutFile 'optional_actions' -FileComment 'Optional Actions' -ContentData ($cmd.Where({!$_.mandatory -and !$_.recommended})) } #endregion if ($PassThru) { return $cmd } else { return $stats } # SIG # Begin signature block # MIIefQYJKoZIhvcNAQcCoIIebjCCHmoCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUGqXIPWxfAcMXN1jYfTbwS2B3 # z0mgghnAMIIFQTCCAymgAwIBAgITXwAAAAIjZCsPuYSflAAAAAAAAjANBgkqhkiG # 9w0BAQsFADBcMQswCQYDVQQGEwJERTEPMA0GA1UEBxMGQmVybGluMRQwEgYDVQQK # EwttZXRhQlBBLm9yZzEMMAoGA1UECxMDRGV2MRgwFgYDVQQDEw9tZXRhQlBBIFJv # b3QgQ0EwHhcNMTkxMTA4MjEwNzI4WhcNMjAxMTA4MjExNzI4WjBcMQswCQYDVQQG # EwJERTEPMA0GA1UEBxMGQmVybGluMRQwEgYDVQQKEwttZXRhQlBBLm9yZzEMMAoG # A1UECxMDRGV2MRgwFgYDVQQDEw9FdmdlbmlqIFNtaXJub3YwggEiMA0GCSqGSIb3 # DQEBAQUAA4IBDwAwggEKAoIBAQDBL4oFbzMU7zkuwMFsG8Ckbk73VtcvE/gz5CFd # Rf3f/WVMe27r6VQLUfeaLYwjavfe9MaSHngXhC0Ivsbf6IlKtY1oXJFKXuEnNvzC # s3njl5LXVoWf29wGmOOAbPWBlI7+nBwvcNRHYnZ4ZaLSO9cdhre9gARTvMptUUL9 # 3Njf3jw9iwdLRg7wMk1TB3yB7nlHHd0G8YiPzlltOV9sesfpnFuorR2IPwkfaEfu # Z6t/nHsuWtvliaT++PbDv9d0tnKiQVJ+h9cwMoTO8kIbg7Q52pT+paMrcEn7hyN+ # XjyG/oJUb6IyDOMgv2Fa+MJ9SWnT9z4Ueap4/JJhkiv8qaf5AgMBAAGjgfswgfgw # DgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBRm # y7quPiRE14SnwXiztcO0WxBDYzAfBgNVHSMEGDAWgBT5ujnudnaVxT34rTRrGEb0 # f87i+DA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vcGtpLm1ldGFicGEub3JnL21l # dGFCUEFfUm9vdF9DQS5jcmwwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzAChipo # dHRwOi8vcGtpLm1ldGFicGEub3JnL21ldGFCUEFfUm9vdF9DQS5jcnQwDAYDVR0T # AQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAc05mB0AuoLmHwh5aPGw+VYSlXzDg # ugs1HwjI3iNe6FQZ1a+E1yupvdLHFrjs+7nBtRzQNdbf6Gs2ulQgaxKzC+qtrgiu # vkiO7q9mPza1WkkXCDtVatyMnRt6i9aK/Qy0B+lQxVL3gZhHKNiBlZd9lZbps699 # SHuT2lyytJEIQdXWKEm137+3FHFKIso9cQ820Lzh+251VukxuqRHR2A5BhiHRPww # phRzMyfxGwUZWx1WSqgefEyHcqft562LnYluDXPxfEUNRPtTzAMbR8MH6zuom6QE # pA3UzrJvwgYGnKkGyfj7SQijvvukfwHbcTRbbq73Jv6YKnFlwG8A6BKDYWYpQdgT # 7ENlXhJ1TEZe+8O4XOUZokYQoFJbOn9dz2AyKJCQDYev3+uDqNhlVavcMG8YXBjv # W/Y6NbUb1W2W+kDFtdCG74sXgTZyvqsDsEb57UniGxo0+/uYqxRnFexruJ/Il3OO # kLv2Up4aov018yowmSYriJY2u9B7NyzPqNTh8KYo/RCm9INUn/SA3JNJ0g9udssR # tkdbPCpq+e1j9Xjf6V5qkXQcNMuuZLf6RswS/tsuaqlhqRrHDdk4I+EcDj5o0n+C # ur9horiACMCK5fjpgogRaqkuzCshtO1qc20F9tk0tUr3iD8N63MSbQBmxeyP16Et # 7ZEHLtu+fmM06ckwggZqMIIFUqADAgECAhADAZoCOv9YsWvW1ermF/BmMA0GCSqG # SIb3DQEBBQUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx # GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IEFz # c3VyZWQgSUQgQ0EtMTAeFw0xNDEwMjIwMDAwMDBaFw0yNDEwMjIwMDAwMDBaMEcx # CzAJBgNVBAYTAlVTMREwDwYDVQQKEwhEaWdpQ2VydDElMCMGA1UEAxMcRGlnaUNl # cnQgVGltZXN0YW1wIFJlc3BvbmRlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC # AQoCggEBAKNkXfx8s+CCNeDg9sYq5kl1O8xu4FOpnx9kWeZ8a39rjJ1V+JLjntVa # Y1sCSVDZg85vZu7dy4XpX6X51Id0iEQ7Gcnl9ZGfxhQ5rCTqqEsskYnMXij0ZLZQ # t/USs3OWCmejvmGfrvP9Enh1DqZbFP1FI46GRFV9GIYFjFWHeUhG98oOjafeTl/i # qLYtWQJhiGFyGGi5uHzu5uc0LzF3gTAfuzYBje8n4/ea8EwxZI3j6/oZh6h+z+yM # DDZbesF6uHjHyQYuRhDIjegEYNu8c3T6Ttj+qkDxss5wRoPp2kChWTrZFQlXmVYw # k/PJYczQCMxr7GJCkawCwO+k8IkRj3cCAwEAAaOCAzUwggMxMA4GA1UdDwEB/wQE # AwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMIIBvwYD # VR0gBIIBtjCCAbIwggGhBglghkgBhv1sBwEwggGSMCgGCCsGAQUFBwIBFhxodHRw # czovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBB # AG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBh # AHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBj # AGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABT # ACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABB # AGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBh # AGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBh # AHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAu # MAsGCWCGSAGG/WwDFTAfBgNVHSMEGDAWgBQVABIrE5iymQftHt+ivlcNK2cCzTAd # BgNVHQ4EFgQUYVpNJLZJMp1KKnkag0v0HonByn0wfQYDVR0fBHYwdDA4oDagNIYy # aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEQ0EtMS5j # cmwwOKA2oDSGMmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy # ZWRJRENBLTEuY3JsMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDov # L29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5k # aWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURDQS0xLmNydDANBgkqhkiG9w0B # AQUFAAOCAQEAnSV+GzNNsiaBXJuGziMgD4CH5Yj//7HUaiwx7ToXGXEXzakbvFoW # OQCd42yE5FpA+94GAYw3+puxnSR+/iCkV61bt5qwYCbqaVchXTQvH3Gwg5QZBWs1 # kBCge5fH9j/n4hFBpr1i2fAnPTgdKG86Ugnw7HBi02JLsOBzppLA044x2C/jbRcT # Bu7kA7YUq/OPQ6dxnSHdFMoVXZJB2vkPgdGZdA0mxA5/G7X1oPHGdwYoFenYk+VV # FvC7Cqsc21xIJ2bIo4sKHOWV2q7ELlmgYd3a822iYemKC23sEhi991VUQAOSK2vC # UcIKSK+w1G7g9BQKOhvjjz3Kr2qNe9zYRDCCBs0wggW1oAMCAQICEAb9+QOWA63q # AArrPye7uhswDQYJKoZIhvcNAQEFBQAwZTELMAkGA1UEBhMCVVMxFTATBgNVBAoT # DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UE # AxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTA2MTExMDAwMDAwMFoX # DTIxMTExMDAwMDAwMFowYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0 # IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNl # cnQgQXNzdXJlZCBJRCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC # AQEA6IItmfnKwkKVpYBzQHDSnlZUXKnE0kEGj8kz/E1FkVyBn+0snPgWWd+etSQV # wpi5tHdJ3InECtqvy15r7a2wcTHrzzpADEZNk+yLejYIA6sMNP4YSYL+x8cxSIB8 # HqIPkg5QycaH6zY/2DDD/6b3+6LNb3Mj/qxWBZDwMiEWicZwiPkFl32jx0PdAug7 # Pe2xQaPtP77blUjE7h6z8rwMK5nQxl0SQoHhg26Ccz8mSxSQrllmCsSNvtLOBq6t # hG9IhJtPQLnxTPKvmPv2zkBdXPao8S+v7Iki8msYZbHBc63X8djPHgp0XEK4aH63 # 1XcKJ1Z8D2KkPzIUYJX9BwSiCQIDAQABo4IDejCCA3YwDgYDVR0PAQH/BAQDAgGG # MDsGA1UdJQQ0MDIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUF # BwMEBggrBgEFBQcDCDCCAdIGA1UdIASCAckwggHFMIIBtAYKYIZIAYb9bAABBDCC # AaQwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMt # cmVwb3NpdG9yeS5odG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBz # AGUAIABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBv # AG4AcwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAg # AHQAaABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMAIABhAG4AZAAg # AHQAaABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBt # AGUAbgB0ACAAdwBoAGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0 # AHkAIABhAG4AZAAgAGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABo # AGUAcgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wCwYJYIZIAYb9 # bAMVMBIGA1UdEwEB/wQIMAYBAf8CAQAweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUF # BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6 # Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5j # cnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmw0LmRp # Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwHQYDVR0OBBYE # FBUAEisTmLKZB+0e36K+Vw0rZwLNMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6en # IZ3zbcgPMA0GCSqGSIb3DQEBBQUAA4IBAQBGUD7Jtygkpzgdtlspr1LPUukxR6tW # XHvVDQtBs+/sdR90OPKyXGGinJXDUOSCuSPRujqGcq04eKx1XRcXNHJHhZRW0eu7 # NoR3zCSl8wQZVann4+erYs37iy2QwsDStZS9Xk+xBdIOPRqpFFumhjFiqKgz5Js5 # p8T1zh14dpQlc+Qqq8+cdkvtX8JLFuRLcEwAiR78xXm8TBJX/l/hHrwCXaj++wc4 # Tw3GXZG5D2dFzdaD7eeSDY2xaYxP+1ngIw/Sqq4AfO6cQg7PkdcntxbuD8O9fAqg # 7iwIVYUiuOsYGk38KiGtSTGDR5V3cdyxG0tLHBCcdxTBnU8vWpUIKRAmMIIHODCC # BSCgAwIBAgIQEw12KjF18pBAJDt0qQwq6jANBgkqhkiG9w0BAQsFADBcMQswCQYD # VQQGEwJERTEPMA0GA1UEBxMGQmVybGluMRQwEgYDVQQKEwttZXRhQlBBLm9yZzEM # MAoGA1UECxMDRGV2MRgwFgYDVQQDEw9tZXRhQlBBIFJvb3QgQ0EwHhcNMTkxMTA4 # MjAwMDU5WhcNMzkxMTA4MjAxMDU0WjBcMQswCQYDVQQGEwJERTEPMA0GA1UEBxMG # QmVybGluMRQwEgYDVQQKEwttZXRhQlBBLm9yZzEMMAoGA1UECxMDRGV2MRgwFgYD # VQQDEw9tZXRhQlBBIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK # AoICAQCw2DkS2wXYAPJTQVkEccotAn/ba+ZxjYqvZOnOO1QbHk8XDSZCFrTADHjU # BvYZPVZDg/OPg082TOmln7uVfipsHt29WSWCVco6WTGbb2gHfTFpAoltfdRnsTWt # +J0l69tdPWVVxMpvsNv1S/FrfkEVLBW6k9glHSjmvz6uJNvF/UKtkkkElpPtbLsS # jNCwIqXJ7maZTNEEUGnmDYHhj2Bi7Ex5w2fKw5k5IvCr4BO6LLIim9HialiT0pMK # JMkWSQmQqDlC/WUjh5cmOD4fRq2cL8QiiJjz1mpbALd9zz7F9KO/7F9WZXQaiEK/ # vgBsB8LnjWlE/qh9eoWSw1ib+Pp2Nxs2Wmk433Di4pgkad4eZHC0ENF8/8VU/Via # a2PQJdwoK/ouAvUJz+JQ/q7hNClpoNa7dbgrtw63W0DeC7NbSHE7469ftrkkHsfy # S7y2YM68Nw/0s1kgQSneeqbOAMYIW1d634QJniOqzn1kb2wSHj+f/g90HTa+8vmh # wBC/AGWPZB28qxVz7CjQ6uRfNpQnP3WvEXaJbmKldhvzyTzAWxfhXRzNlRx8Ije1 # BsditmsB1W3V93AU+EH/FXs4r4toQCyAQL4ldXCEmcVxHO2qk3ZDjVIrDddk3wP3 # 9VZP9UTm/laSs/zhWIDYHdZe6Kh7kX95pt10hZqS73O4gcfWmQIDAQABo4IB9DCC # AfAwCwYDVR0PBAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFPm6 # Oe52dpXFPfitNGsYRvR/zuL4MBAGCSsGAQQBgjcVAQQDAgEAMIIBmgYDVR0gBIIB # kTCCAY0wggGJBgwrBgEEAYOHcQEBAQEwggF3MIIBRgYIKwYBBQUHAgIwggE4HoIB # NABUAGgAaQBzACAAUABLAEkAIABpAHMAIABpAG4AdABlAG4AZABlAGQAIABmAG8A # cgAgAGMAZQByAHQAaQBmAGkAYwBhAHQAaQBvAG4AIABiAHkAIABtAGUAdABhAEIA # UABBAC4AbwByAGcALAAgAEUAdgBnAGUAbgBpAGoAIABTAG0AaQByAG4AbwB2ACwA # IABCAGUAcgBsAGkAbgAgAG8AbgBsAHkALgAgAEYAbwByACAAZABlAHQAYQBpAGwA # cwAsACAAYwBvAG4AcwB1AGwAdAAgAHQAaABlACAAQwBlAHIAdABpAGYAaQBjAGEA # dABpAG8AbgAgAFAAbwBsAGkAYwB5ACAAUwB0AGEAdABlAG0AZQBuAHQAIABsAGkA # bgBrAGUAZAAgAGIAZQBsAG8AdwAuMCsGCCsGAQUFBwIBFh9odHRwOi8vcGtpLm1l # dGFicGEub3JnL2Nwcy5odG1sMA0GCSqGSIb3DQEBCwUAA4ICAQBuwVs984+DElFQ # BzO7r96a2/QZosjcZst3/KLCJQXRNjfrtHzGNDFRCj5MSqet9jXfC0Q0XQnus28S # NG75qpzdkdKFruAjffOP1qOWEjnsljK+KkNafHXywlNUDI4Y3LzO44jF33gpTPjM # 0KjWUGPRmwkOyapyEh629S7AlXikuYJLFDddsEVmzf9jVMjEQi37BzyaERwokkwg # bW4hxIVycoPyfPhiAVChPj/IHFVaUDYb6vvL5/LD6fS9qd7VbJgOtkrpZhBzV3n4 # Gi7cOHVvGylta/gp4sdpB62QBNTjUS8JOkU1ECLDpO+QfKdKn1jYqpv9vIVYvj52 # 4yPx92T/dp2zZqJd9/3/M35b9pk0J3ACf77Lb2sM98/G4HK5NI8LqdM8iEKQkPQ4 # 9gkujnnQrmm1CMYRND498GfcgxQo2h+TFrxEWfZRHrPmoPtp90E9lW/vgwsgvtGN # iBR6+wcEeBGm3TnwDUZsXhSUO0wyWSGhPWzxnM+ADC0iMpeBeTn22v+NA2S2mNOF # f0K83O+r6LhjcnoD6kehQ30hHdvplxUs/D+IiOVkwyhznAmEpLP0Wv3e+ggN0qDP # zYbKRjgJYcJBFU0us1+UADDg2mxxuJbNWmT7QXnh6eOlFPrYnwIdjmhJwkeaY7/N # bSbexF0k2hTNI6d526AFcHAVSjJqBDGCBCcwggQjAgEBMHMwXDELMAkGA1UEBhMC # REUxDzANBgNVBAcTBkJlcmxpbjEUMBIGA1UEChMLbWV0YUJQQS5vcmcxDDAKBgNV # BAsTA0RldjEYMBYGA1UEAxMPbWV0YUJQQSBSb290IENBAhNfAAAAAiNkKw+5hJ+U # AAAAAAACMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkG # CSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEE # AYI3AgEVMCMGCSqGSIb3DQEJBDEWBBQ8Bl6ouwooau5yODMBDf4vKuAjhzANBgkq # hkiG9w0BAQEFAASCAQBavwd0teHvXrWA9fHEtwnYrZOeiSYtWsPs4XDcuvecgMbP # ffb/7ZqmEKCQanFOEQ07EgkqAdH+3n2dHwyz2kuNIjM0MrvW7iZLzA59Fys6NWI0 # 0F+VorgBLZd1kmm4DSRE+SH43l2fMlFVrolfq/Q0EcTMvQINVDjWztG28ZBz/avx # rlUWkX2nO1H/qRyIwirSFWb6IEk3Z51On232w6b6TlrQFnu0YFXrHCmGamqb/aaI # 3Z0W8IhChwXxcas4r6AtA30uP3+Nxf7Nb9rgLRE5TqX/TWtQ5AyLesvs1WPCKJKG # XFZPoNZAQDZeIBOjGp3rXMSr3XM+kATj5HQ8JU07oYICDzCCAgsGCSqGSIb3DQEJ # BjGCAfwwggH4AgEBMHYwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0 # IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNl # cnQgQXNzdXJlZCBJRCBDQS0xAhADAZoCOv9YsWvW1ermF/BmMAkGBSsOAwIaBQCg # XTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yMDAz # MjYxOTU3MjFaMCMGCSqGSIb3DQEJBDEWBBSwH3WEmWk53wad2ayfzCUFDdIWjjAN # BgkqhkiG9w0BAQEFAASCAQAQGkk8jedOZJ0aEIfuezVNe8rdZRdAOQqAZ4RJEBfb # 6rInVcklY33S8Rmi6jw9HtwvxCIE0EhRM/lawtoOl2OfWnV/Sugvas6dEUFo2zIO # MZ2OfxoyLRq+zoW0wQgE4PrfIVWJ6zZ68IeHShkMSKICAmV1Y+DTM3DmOmIzPPKO # JYNtwbiHC6rKW5XSzoS6MckxdTskNQvfw0fyl+K4F48xXf2aQPs1LZCBya4tmCaA # u7Z/r1EowSgrJ6OWhEdmMsfYzk8a3I5tTgFKfjy2777rM30+RRsPS6DmSzcl2lL0 # seQKzHUTZtZy4NZMEByEtHtsmxFj2g89uPwJynns4EcK # SIG # End signature block |