Private/Write-ADFSTkLog.ps1
function Write-ADFSTkLog { [CmdletBinding(DefaultParametersetName="Default")] param ( [Parameter(Mandatory=$false, ParameterSetName="Set", ValueFromPipelineByPropertyName=$false)] [string] #The path to the logfile. This needs to be set once in the script. The path will be stored in a global variable 'LogFilePath' $SetLogFilePath, [Parameter(Mandatory=$false, ParameterSetName="Set", ValueFromPipelineByPropertyName=$false)] [string] #The name of the eventlog. This needs to be set once in the script. The name will be stored in a global variable 'EventLogName' $SetEventLogName, [Parameter(Mandatory=$false, ParameterSetName="Set", ValueFromPipelineByPropertyName=$false)] [string] <#The Source that will be used in the eventlog. Use New-EventLog -LogName <EventLogName> -Source <NewSource> to add a new source to a eventlog. This needs to be set once in the script. The name will be stored in a global variable 'EventLogSource'#> $SetEventLogSource, [Parameter(Mandatory=$false, ParameterSetName="Get", ValueFromPipelineByPropertyName=$false)] [switch] #Returns the path to the LogFile. $GetLogFilePath, [Parameter(Mandatory=$false, ParameterSetName="Get", ValueFromPipelineByPropertyName=$false)] [switch] #Returns the name of the EventLog that will be used. $GetEventLogName, [Parameter(Mandatory=$false, ParameterSetName="Get", ValueFromPipelineByPropertyName=$false)] [switch] #Returns the Source of the EventLog that will be used. $GetEventLogSource, [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$true, Position=0)] [ValidateNotNullOrEmpty()] [string] #The message to be written in the log... $Message, [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$true)] [int] #The EventID if EventLog is used $EventID, [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$true)] [string] #Used in LogFile and on Screen to clarify the message. In EventLog the Level on the event is set to EntryType. Default is Information [ValidateSet("Information", "Error", "Warning")] $EntryType="Information", [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$true)] [switch] #If used the EntryType will be set as "Error" the message will be thown as an error. $MajorFault, [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$true)] [int] #Only for EventLog. Task Category on the event is set to Category. If -Verbose is used, Category will be set to 4 $Category=1, [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$false)] [switch] #Used in LogFile and on Screen make the message underlined $Underline, [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$false)] [char] #The char used to make the underline (see parameter Underline). Default is '-' $UnderlineChar='-', [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$true)] [switch] #Use this to get output on the screen $Screen, [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$true)] [switch] #Use this to log to file $File, [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$true)] [switch] #Use this to log to EventLog $EventLog, [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$true)] [switch] #Doesn't write Date and Time in the beginning of the row $SkipDateTime, [Parameter(Mandatory=$false, ParameterSetName="Default", ValueFromPipelineByPropertyName=$true)] [ConsoleColor] #Sets the color the screen-text should be written in $ForegroundColor = [ConsoleColor]::Gray ) Begin { if ($PsCmdlet.ParameterSetName -eq "Set") { if ($SetLogFilePath -ne [string]::Empty) { $FilePath = $SetLogFilePath.SubString(0,$SetLogFilePath.LastIndexOf('\')) if (! (Test-Path ($FilePath))) { Write-Warning (Get-ADFSTkLanguageText logPathNotFound -f $FilePath) } else { Write-Verbose (Get-ADFSTkLanguageText logSettingXPathTo -f 'LogFilePath', $SetLogFilePath) $global:LogFilePath = $SetLogFilePath } } if ($SetEventLogName -ne [string]::Empty) { try { $TestEventLog = Get-EventLog $SetEventLogName -Newest 1 Write-Verbose (Get-ADFSTkLanguageText logSettingXPathTo -f 'EventLogName', $SetEventLogName) $global:EventLogName = $SetEventLogName } catch { Write-Warning (Get-ADFSTkLanguageText logEventLogNameNotExist) } } if ($SetEventLogSource -ne [string]::Empty) { Write-Verbose (Get-ADFSTkLanguageText logSettingXPathTo -f 'SetEventLogSource', $SetLogFilePath) $global:EventLogSource = $SetEventLogSource } } elseif ($PsCmdlet.ParameterSetName -eq "Get") { if ($GetLogFilePath) { $LogFilePath } if ($GetEventLogName) { $EventLogName } if ($GetEventLogSource) { $EventLogSource } } } Process { ### Write main script below ### if ($PsCmdlet.ParameterSetName -eq "Default") { if ($MajorFault) { $EntryType = "Error" } if ($verbosePreference -eq "Continue") { $Category = 4 } $CurrentTime = (Get-Date).ToString() if (!$Screen.IsPresent -and !$File.IsPresent -and !$EventLog.IsPresent) { $Screen = $true if ($EventLogName -ne $null -and $EventLogSource -ne $null) { $EventLog = $true } if ($LogFilePath -ne $null) { $File = $true } } if ($Screen -and -not $MajorFault -and -not $Silent) { #Write-Verbose "Logging to Screen..." if (!$SkipDateTime) { Write-Host "$($CurrentTime): " -ForegroundColor DarkYellow -NoNewline } if ($EntryType -eq "Error") { Write-Error $Message if ($Underline) { Write-Error "$([string]::Empty.PadLeft($ScreenMessage.Length,$UnderlineChar))" } } elseif ($EntryType -eq "Warning") { Write-Warning $Message if ($Underline) { Write-Warning "$([string]::Empty.PadLeft($ScreenMessage.Length,$UnderlineChar))" } } else { if ($verbosePreference -eq "Continue") { Write-Verbose $Message if ($Underline) { Write-Verbose "$([string]::Empty.PadLeft($ScreenMessage.Length,$UnderlineChar))" } } else { Write-Host $Message -ForegroundColor $ForegroundColor if ($Underline) { Write-Host "$([string]::Empty.PadLeft($ScreenMessage.Length,$UnderlineChar))" } } } } if ($File) { if ($LogFilePath -eq [string]::Empty) { Write-Warning (Get-ADFSTkLanguageText logLogFilePathNotSet) } else { $FileMessage = "" if (!$SkipDateTime) { $FileMessage = "$CurrentTime - " } $FileMessage += "$($EntryType): $Message" #Write-Verbose "Logging to File `'$LoggFilePath`'..." Add-Content -Path $LogFilePath -Value $FileMessage if ($Underline) { Add-Content -Path $LogFilePath -Value "$([string]::Empty.PadLeft($FileMessage.Length,$UnderlineChar))" } } } if ($EventLog) { if ($EventLogName -eq [string]::Empty) { Write-Warning (Get-ADFSTkLanguageText logEventLogNameNotSet) } elseif ($EventLogSource -eq [string]::Empty) { Write-Warning (Get-ADFSTkLanguageText logEventSourceNotSet) } else { #Write-Verbose "Logging to EventLog `'$EventLogName`' as Source `'$EventLogSource`'..." Write-EventLog -LogName $EventLogName -Source $EventLogSource -EventId $EventID -Message $Message -EntryType $EntryType -Category $Category } } if($EntryType -eq "Warning") { $global:Warnings++ $global:LastWarning = $Message } elseif($EntryType -eq "Error") { $global:Errors++ $global:LastError = $Message } if ($MajorFault) { throw $Message } } } <# .SYNOPSIS Use this cmdlet to add logging to your script. Can log to Screen/File and EventLog .DESCRIPTION Start by setting FilePath and/or EventLogName/EventLogSource. The values are stored in global variables and don't need to be set again. Call Write-ADFSTkLog with one or more parameters depending on how much logging needed. If a Warning is logged the following global variables will be changed: $Warnings will increase with 1 $LastWarning will be set to $Message If an Error is logged the following global variables will be changed: $Errors will increase with 1 $LastError will be set to $Message If -MajorFault is provided, EntryType will automatically be set as Error and after logging has been done, the Message will be thrown. If a variable namned $Silent is used and equals $true in the script calling Write-ADFSTkLog, no logging to screen will be done .EXAMPLE C:\PS> Write-ADFSTkLog -Message "Hello World!" 2012-02-02 16:40:16: Hello World! -Message parameter are not needed as long as the message is written first C:\PS> Write-ADFSTkLog "Hello World!" -EntryType Warning WARNING: 2012-02-02 16:41:23: Hello World! C:\PS> Write-ADFSTkLog -SetLogFilePath C:\Logs\myLogfile.txt C:\PS> Write-ADFSTkLog "Hello textfile!" -File -Screen -Underline 2012-02-02 16:46:31: Hello textfile! ------------------------------------ .EXAMPLE If none of the parameters (-Screen, -File or -EventLog) is provided, all defined ways will be used. Default will only be the screen, a -SetLogFilePath has been set, the logging will be to screen and file, etc C:\PS> Write-ADFSTkLog -SetLogFilePath C:\Logs\myLogfile.txt C:\PS> Write-ADFSTkLog "Look, I don't use any parameters! :)" 2012-02-02 16:59:46: Look, I don't use any parameters! :) C:\PS> Get-Content $LogFilePath 2012-02-02 16:46:31 - Information: Hello textfile! -------------------------------------------------- 2012-02-02 16:59:46 - Information: Look, I don't use any parameters! :) C:\PS> Write-ADFSTkLog "Something isn't quite right!" -EntryType Warning WARNING: 2012-02-02 17:00:45: Something isn't quite right! C:\PS> Get-Content $LogFilePath 2012-02-02 16:46:31 - Information: Hello textfile! -------------------------------------------------- 2012-02-02 16:59:46 - Information: Look, I don't use any parameters! :) 2012-02-02 17:00:45 - Warning: Something isn't quite right! C:PS> $Warnings 2 C:PS> $Errors 0 C:PS> $LastWarning Something isn't quite right! #> } function Write-ADFSTkVerboseLog { [CmdletBinding(SupportsShouldProcess=$true)] param ( [parameter(Position=0)] [ValidateNotNullOrEmpty()] [string] #The message to be written in the log... $Message, [string] #Used in LogFile and on Screen to clarify the message. In EventLog the Level on the event is set to EntryType. Default is Information [ValidateSet("Information", "Error", "Warning")] $EntryType="Information", [switch] #Use this to log to EventLog $EventLog, [switch] #Use this to log to file $File, [int] #The EventID if EventLog is used $EventID ) if ($verbosePreference -eq "Continue") { if (!$File.IsPresent -and !$EventLog.IsPresent) { if ($EventLogName -ne $null -and $EventLogSource -ne $null) { $EventLog = $true } if ($LogFilePath -ne $null) { $File = $true } } if ($EventLog) { Write-ADFSTkLog -Message $Message -EventLog -EventID $EventID -EntryType $EntryType } if($File) { Write-ADFSTkLog -Message $Message -File -EventID $EventID -EntryType $EntryType } Write-ADFSTkLog -Message $Message -EntryType $EntryType -Screen } <# .SYNOPSIS Use this cmdlet to add Verbose-logging to your script. Logging will always be to screen, but can also be done to File and/or EventLog .DESCRIPTION Start by setting FilePath and/or EventLogName/EventLogSource with Write-ADFSTkLog. Category will always be set to 4 .EXAMPLE Scriptfile below (Test-Script.ps1) --- [CmdletBinding(SupportsShouldProcess=$true)] param() Write-VerboseLiULog "This is a verbose message" --- C:\PS> .\Test-Script.ps1 C:\PS> .\Test-Script.ps1 -Verbose VERBOSE: This is a verbose message .EXAMPLE Scriptfile below (Test-Script.ps1) --- [CmdletBinding(SupportsShouldProcess=$true)] param() Write-ADFSTkLog -SetLogFilePath .\myLogfile.txt Write-VerboseLiULog "This is a verbose message" --- C:\PS> .\Test-Script.ps1 -File -Verbose VERBOSE: Setting LogFilePath to '.\myLogfile.txt'... VERBOSE: 2012-01-04 12:56:50: This is a verbose message C:\PS> Get-Content .\myLogfile.txt 2012-01-04 12:58:13 - Information: This is a verbose message #> } # SIG # Begin signature block # MIId2QYJKoZIhvcNAQcCoIIdyjCCHcYCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUXwqcMZkt0Snjugjmsr/POsrX # 13igghisMIIEfTCCA2WgAwIBAgIDG+cVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV # BAYTAlVTMSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIEluYy4xMTAvBgNV # BAsTKEdvIERhZGR5IENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcN # MTQwMTAxMDcwMDAwWhcNMzEwNTMwMDcwMDAwWjCBgzELMAkGA1UEBhMCVVMxEDAO # BgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdv # RGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmlj # YXRlIEF1dGhvcml0eSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC # AQEAv3FiCPH6WTT3G8kYo/eASVjpIoMTpsUgQwE7hPHmhUmfJ+r2hBtOoLTbcJjH # MgGxBT4HTu70+k8vWTAi56sZVmvigAf88xZ1gDlRe+X5NbZ0TqmNghPktj+pA4P6 # or6KFWp/3gvDthkUBcrqw6gElDtGfDIN8wBmIsiNaW02jBEYt9OyHGC0OPoCjM7T # 3UYH3go+6118yHz7sCtTpJJiaVElBWEaRIGMLKlDliPfrDqBmg4pxRyp6V0etp6e # MAo5zvGIgPtLXcwy7IViQyU0AlYnAZG0O3AqP26x6JyIAX2f1PnbU21gnb8s51ir # uF9G/M7EGwM8CetJMVxpRrPgRwIDAQABo4IBFzCCARMwDwYDVR0TAQH/BAUwAwEB # /zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9BUFuIMGU2g/e # MB8GA1UdIwQYMBaAFNLEsNKR1EwRcbNhyz2h/t2oatTjMDQGCCsGAQUFBwEBBCgw # JjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRkeS5jb20vMDIGA1UdHwQr # MCkwJ6AloCOGIWh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Ryb290LmNybDBGBgNV # HSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cHM6Ly9jZXJ0cy5nb2Rh # ZGR5LmNvbS9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAWQtTvZKGEack # e+1bMc8dH2xwxbhuvk679r6XUOEwf7ooXGKUwuN+M/f7QnaF25UcjCJYdQkMiGVn # OQoWCcWgOJekxSOTP7QYpgEGRJHjp2kntFolfzq3Ms3dhP8qOCkzpN1nsoX+oYgg # HFCJyNwq9kIDN0zmiN/VryTyscPfzLXs4Jlet0lUIDyUGAzHHFIYSaRt4bNYC8nY # 7NmuHDKOKHAN4v6mF56ED71XcLNa6R+ghlO773z/aQvgSMO3kwvIClTErF0UZzds # yqUvMQg3qm5vjLyb4lddJIGvl5echK1srDdMZvNhkREg5L4wn3qkKQmw4TRfZHcY # QFHfjDCmrzCCBNAwggO4oAMCAQICAQcwDQYJKoZIhvcNAQELBQAwgYMxCzAJBgNV # BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRow # GAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UEAxMoR28gRGFkZHkgUm9v # dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjAeFw0xMTA1MDMwNzAwMDBaFw0z # MTA1MDMwNzAwMDBaMIG0MQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTET # MBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4x # LTArBgNVBAsTJGh0dHA6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEz # MDEGA1UEAxMqR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAt # IEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAueDLENSvdr3Uk2Lr # MGS4gQhswwTZYheOL/8+Zc+PzmLmPFIc2hZFS1WreGtjg2KQzg9pbJnIGhSLTMxF # M+qI3J6jryv+gGGdeVfEzy70PzA8XUf8mha8wzeWQVGOEUtU+Ci+0Iy+8DA4HvOw # JvhmR2Nt3nEmR484R1PRRh2049wA6kWsvbxx2apvANvbzTA6eU9fTEf4He9bwsSd # YDuxskOR2KQzTuqz1idPrSWKpcb01dCmrnQFZFeItURV1C0qOj74uL3pMgoClGTE # FjpQ8Uqu53kzrwwgB3/o3wQ5wmkCbGNS+nfBG8h0h8i5kxhQVDVLaU68O9NJLh/c # wdJS+wIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC # AQYwHQYDVR0OBBYEFEDCvSeOzDSDMKIz1/tss/C0LIDOMB8GA1UdIwQYMBaAFDqa # hQcQZyi27/a9BUFuIMGU2g/eMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZ29kYWRkeS5jb20vMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6 # Ly9jcmwuZ29kYWRkeS5jb20vZ2Ryb290LWcyLmNybDBGBgNVHSAEPzA9MDsGBFUd # IAAwMzAxBggrBgEFBQcCARYlaHR0cHM6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBv # c2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEACH5skxDIOLiWqZBL/6FfTwTvbD6c # iAbJUI+mc/dXMRu+vOQv2/i601vgtOfmeWIODKLXamNzMbX1qEikOwgtol2Q17R8 # JU8RVjDEtkSdeyyd5V7m7wxhqr/kKhvuhJ64g33BQ85EpxNwDZEf9MgTrYNg2dhy # qHMkHrWsIg7KF4liWEQbq4klAQAPzcQbYttRtNMPUSqb9Lxz/HbONqTN2dgs6q6b # 9SqykNFNdRiKP4pBkCN9W0v+pANYm0ayw2Bgg/h9UEHOwqGQw7vvAi/SFVTuRBXZ # Cq6nijPtsS12NibcBOuf92EfFdyHb+5GliitoSZ9CgmnLgSjjbz4vAQwATCCBP4w # ggPmoAMCAQICEA1CSuC+Ooj/YEAhzhQA8N0wDQYJKoZIhvcNAQELBQAwcjELMAkG # A1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRp # Z2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRp # bWVzdGFtcGluZyBDQTAeFw0yMTAxMDEwMDAwMDBaFw0zMTAxMDYwMDAwMDBaMEgx # CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4GA1UEAxMX # RGlnaUNlcnQgVGltZXN0YW1wIDIwMjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw # ggEKAoIBAQDC5mGEZ8WK9Q0IpEXKY2tR1zoRQr0KdXVNlLQMULUmEP4dyG+RawyW # 5xpcSO9E5b+bYc0VkWJauP9nC5xj/TZqgfop+N0rcIXeAhjzeG28ffnHbQk9vmp2 # h+mKvfiEXR52yeTGdnY6U9HR01o2j8aj4S8bOrdh1nPsTm0zinxdRS1LsVDmQTo3 # VobckyON91Al6GTm3dOPL1e1hyDrDo4s1SPa9E14RuMDgzEpSlwMMYpKjIjF9zBa # +RSvFV9sQ0kJ/SYjU/aNY+gaq1uxHTDCm2mCtNv8VlS8H6GHq756WwogL0sJyZWn # jbL61mOLTqVyHO6fegFz+BnW/g1JhL0BAgMBAAGjggG4MIIBtDAOBgNVHQ8BAf8E # BAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDBBBgNV # HSAEOjA4MDYGCWCGSAGG/WwHATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRp # Z2ljZXJ0LmNvbS9DUFMwHwYDVR0jBBgwFoAU9LbhIB3+Ka7S5GGlsqIlssgXNW4w # HQYDVR0OBBYEFDZEho6kurBmvrwoLR1ENt3janq8MHEGA1UdHwRqMGgwMqAwoC6G # LGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtdHMuY3JsMDKg # MKAuhixodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLXRzLmNy # bDCBhQYIKwYBBQUHAQEEeTB3MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp # Y2VydC5jb20wTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv # bS9EaWdpQ2VydFNIQTJBc3N1cmVkSURUaW1lc3RhbXBpbmdDQS5jcnQwDQYJKoZI # hvcNAQELBQADggEBAEgc3LXpmiO85xrnIA6OZ0b9QnJRdAojR6OrktIlxHBZvhSg # 5SeBpU0UFRkHefDRBMOG2Tu9/kQCZk3taaQP9rhwz2Lo9VFKeHk2eie38+dSn5On # 7UOee+e03UEiifuHokYDTvz0/rdkd2NfI1Jpg4L6GlPtkMyNoRdzDfTzZTlwS/Oc # 1np72gy8PTLQG8v1Yfx1CAB2vIEO+MDhXM/EEXLnG2RJ2CKadRVC9S0yOIHa9GCi # urRS+1zgYSQlT7LfySmoc0NR2r1j1h9bm/cuG08THfdKDXF+l7f0P4TrweOjSaH6 # zqe/Vs+6WXZhiV9+p7SOZ3j5NpjhyyjaW4emii8wggUcMIIEBKADAgECAghlwdCS # Sbw71zANBgkqhkiG9w0BAQsFADCBtDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0Fy # aXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29t # LCBJbmMuMS0wKwYDVQQLEyRodHRwOi8vY2VydHMuZ29kYWRkeS5jb20vcmVwb3Np # dG9yeS8xMzAxBgNVBAMTKkdvIERhZGR5IFNlY3VyZSBDZXJ0aWZpY2F0ZSBBdXRo # b3JpdHkgLSBHMjAeFw0yMTAxMTkxODM3MzZaFw0yMjAzMDgxODU4MDBaMF4xCzAJ # BgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExFTAT # BgNVBAoTDENBTkFSSUUgSW5jLjEVMBMGA1UEAxMMQ0FOQVJJRSBJbmMuMIIBIjAN # BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2YXwoxaok5jdbi6MkosZ8Gjo3/2Q # C/T+kr45QmgQNprraKKxIJ81D/B5ziHLzEYBDD5qWmfHoDPdwZsfXeNcaGq7EKQj # dw4WDqPm931pz7nFbacW7pdjhXj7+t5sP7r6/napL+G/3904PopUG6bDaJ274fTC # hBb/D5/ZKI9Mklfqsc9+D8U1QHuoP/6Xpd/94vX6opQpyBHMeM4P/jSgXjlkTkrO # KF6NyLwY1a7p5s/mLonkq+/E6iBOoQ/CRdqtcCsHzAd/se3RF2QLrPVrSFP6iEwE # 7RHzvUAIK62C+BdTCzfqLEqfJsuXgjo5y00HOO6ue+Fd80IbCB1u8gVy3QIDAQAB # o4IBhTCCAYEwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzAOBgNV # HQ8BAf8EBAMCB4AwNQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL2NybC5nb2RhZGR5 # LmNvbS9nZGlnMnM1LTYuY3JsMF0GA1UdIARWMFQwSAYLYIZIAYb9bQEHFwIwOTA3 # BggrBgEFBQcCARYraHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv # c2l0b3J5LzAIBgZngQwBBAEwdgYIKwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhho # dHRwOi8vb2NzcC5nb2RhZGR5LmNvbS8wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jZXJ0 # aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS9nZGlnMi5jcnQwHwYDVR0j # BBgwFoAUQMK9J47MNIMwojPX+2yz8LQsgM4wHQYDVR0OBBYEFFD5zINp5mEvJe65 # msd8HlZK4M+QMA0GCSqGSIb3DQEBCwUAA4IBAQBmmyS7tPYHWB7e2TG6SeNOPGSI # l8FSxPxzXJwKU4ITWh50kojCNsU7Jm6zP5WLJqcBbsLNXNnzAb8g0YJM0f+PkSI6 # ECaS6x8tUAAWJVgCCjKnRZn6rctEAKYCJBjdvrHDMSjFiRjQ/KqdyjPuQvEzU7Dt # ID1X3Wmq19k5izOsiEHIMQ/GGTHdJqnUe63Anm4DHgHRy2D0LvxzNAo96rcxcfwm # c8/dwgJYfA8ecKKnjSYsUDCytvDIVPMujUjeaCpw//BBErnUc18qKMGdjeGCc8sn # uVC/acYZ4gyrOOOMNa+V3I0GA6NdRvGOLqeF1tXBbSzbpR2HCoQJ0O1x7MMTMIIF # MTCCBBmgAwIBAgIQCqEl1tYyG35B5AXaNpfCFTANBgkqhkiG9w0BAQsFADBlMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg # Q0EwHhcNMTYwMTA3MTIwMDAwWhcNMzEwMTA3MTIwMDAwWjByMQswCQYDVQQGEwJV # UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu # Y29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgVGltZXN0YW1w # aW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvdAy7kvNj3/d # qbqCmcU5VChXtiNKxA4HRTNREH3Q+X1NaH7ntqD0jbOI5Je/YyGQmL8TvFfTw+F+ # CNZqFAA49y4eO+7MpvYyWf5fZT/gm+vjRkcGGlV+Cyd+wKL1oODeIj8O/36V+/Oj # uiI+GKwR5PCZA207hXwJ0+5dyJoLVOOoCXFr4M8iEA91z3FyTgqt30A6XLdR4aF5 # FMZNJCMwXbzsPGBqrC8HzP3w6kfZiFBe/WZuVmEnKYmEUeaC50ZQ/ZQqLKfkdT66 # mA+Ef58xFNat1fJky3seBdCEGXIX8RcG7z3N1k3vBkL9olMqT4UdxB08r8/arBD1 # 3ays6Vb/kwIDAQABo4IBzjCCAcowHQYDVR0OBBYEFPS24SAd/imu0uRhpbKiJbLI # FzVuMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMBIGA1UdEwEB/wQI # MAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHkG # CCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu # Y29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln # aUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNVHR8EejB4MDqgOKA2hjRodHRw # Oi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3Js # MDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVk # SURSb290Q0EuY3JsMFAGA1UdIARJMEcwOAYKYIZIAYb9bAACBDAqMCgGCCsGAQUF # BwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAsGCWCGSAGG/WwHATAN # BgkqhkiG9w0BAQsFAAOCAQEAcZUS6VGHVmnN793afKpjerN4zwY3QITvS4S/ys8D # Av3Fp8MOIEIsr3fzKx8MIVoqtwU0HWqumfgnoma/Capg33akOpMP+LLR2HwZYuhe # giUexLoceywh4tZbLBQ1QwRostt1AuByx5jWPGTlH0gQGF+JOGFNYkYkh2OMkVIs # rymJ5Xgf1gsUpYDXEkdws3XVk4WTfraSZ/tTYYmo9WuWwPRYaQ18yAGxuSh1t5lj # hSKMYcp5lH5Z/IwP42+1ASa2bKXuh1Eh5Fhgm7oMLSttosR+u8QlK0cCCHxJrhO2 # 4XxCQijGGFbPQTS2Zl22dHv1VjMiLyI2skuiSpXY9aaOUjGCBJcwggSTAgEBMIHB # MIG0MQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2Nv # dHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xLTArBgNVBAsTJGh0 # dHA6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzEzMDEGA1UEAxMqR28g # RGFkZHkgU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyAghlwdCSSbw7 # 1zAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG # 9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIB # FTAjBgkqhkiG9w0BCQQxFgQU+TJDGXfoxz2zJ+nP738yk5UwwYMwDQYJKoZIhvcN # AQEBBQAEggEAeAzShpdSpnY2zv3zfACFZNtxt/3JGKieZov2NKuoxYKkyOkAiixZ # 6xlIhY0JCV+q4frKLL+wgq/uZykk01CzLURH5Qpvdr9iiWlnzYxIGRLpXuphh5/I # Z2bAR/znTBNdD27eW/7YXT7o0C+vN5UqbNMRNDhOox+3GJnKrf3oeaummcetP7sa # iKn5FLXQmMFSjZo+j6MfE4sewaqi+A9u/9k5GXwJ8zNdF9V29TVFpavACkmrO54p # da95guKbNBM5vY4uGt7Wf3OMQxTqeqLL0NuCS97riqIPK6Z675wDN9/pWfy5XVu9 # JsoY6K+1kp+qufDrNpszIarFKZDlCHTwQKGCAjAwggIsBgkqhkiG9w0BCQYxggId # MIICGQIBATCBhjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBT # SEEyIEFzc3VyZWQgSUQgVGltZXN0YW1waW5nIENBAhANQkrgvjqI/2BAIc4UAPDd # MA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkq # hkiG9w0BCQUxDxcNMjEwMzEwMjIyMzQ4WjAvBgkqhkiG9w0BCQQxIgQge1SANMUo # CDrbCrkbW4vEO9HOOkWerjb8GY4Tb7keBC0wDQYJKoZIhvcNAQEBBQAEggEAcpN6 # 9hcU7zqIVDL45EwjPIH9ir6edYJws5D7y4na7q5ZxXNCCVJqnecLmQXNAKBBOWHI # JySDRwbZT0773kGMIoW6R+9C/zVioZ5uaSQE/9ByB3DgFJzSXQEjdp6V14+RN1CS # bRryVVOfKMmC4joOBLolMuJd7z58/VrH2qylvguyt1P/QxCzD+R2sJeh8aHKupew # kt6m+8i9bFn/ix1PKMGdOXbaj6DXZtD4gqHGq7oT7Gw9TSTD3GHFc/U4cTnQzc/j # T9E5zfcOYan1vAmox+tZcLi4LSFe/hSkeffgIheY+IGhZWnxR+MQI/HXgb/21/B6 # 7n4fLtpg8/RH0ZJhSA== # SIG # End signature block |