public/Initialize-UcmReport.ps1
Function Initialize-UcmReport { <# .SYNOPSIS Checks for clears and creates a new object to store status for reporting later. .DESCRIPTION Checks for clears and creates a new object to store status for reporting later. .EXAMPLE Initialize-UcmReport .INPUTS This function accepts no inputs .OUTPUTS This function does not create pipelined output This Cmdet returns a PSCustomObject with multiple keys to indicate status $Return.Status $Return.Message Return.Status can return one of four values "OK" : Imported All Modules successfully "Warning" : Modules are already loaded "Error" : Something happend when attempting to import the modules, check $return.message for more information "Unknown" : Cmdlet reached the end of the function without returning anything, this shouldnt happen, if it does please log an issue on Github Return.Message returns descriptive text for error messages. .LINK https://www.UcMadScientist.com https://github.com/Atreidae/UcmPSTools .NOTES Version: 1.2 Date: 19/06/2022 .VERSION HISTORY 1.2: Bug fixes for date reporting Added per line item numbers Added per line timestamps Updated Date format to respect system locale Added Subtitle support to HTML report 1.1: Reordered functions into logical order 1.0: Initial Public Release .ACKNOWLEDGEMENTS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseProcessBlockForPipelineCommand', '', Scope='Function')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Scope='Function')] #Required due to how this report works. Report must persist outside of its own scope [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUSeDeclaredVarsMoreThanAssignments', '', Scope='Function')] #Required due to how this report works. Variables must persist outside of their own scope Param ( [Parameter(ValueFromPipelineByPropertyName=$true, Position=1)] [String]$Title="HTML Report", [Parameter(ValueFromPipelineByPropertyName=$true, Position=2)] [String]$SubTitle="The results were as follows", [Parameter(ValueFromPipelineByPropertyName=$true, Position=3)] [string]$StartDate=(Get-Date -format dd.MM.yy.hh.mm), [Parameter(ValueFromPipelineByPropertyName=$true, Position=4)] [string]$NiceDate=(Get-Date -displayhint datetime) ) #region FunctionSetup, Set Default Variables for HTML Reporting and Write Log $function = 'Initialize-UcmReport' [hashtable]$Return = @{} $return.Function = $function $return.Status = "Unknown" $return.Message = "Function did not return a status message" # Log why we were called Write-UcmLog -Message "$($MyInvocation.InvocationName) called with $($MyInvocation.Line)" -Severity 1 -Component $function Write-UcmLog -Message "Parameters" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Keys)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Parameters Values" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Values)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Optional Arguments" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$Args" -Severity 1 -Component $function -LogOnly #endregion FunctionSetup #region FunctionWork #Declare our reports $Global:ProgressReport = @() $Global:ThisReport = @() #Declare our filenames $Global:HTMLReportFilename=".\$Title - $StartDate.html" $Global:CSVReportFilename=".\$Title - $StartDate.csv" #Import the attributes into the report object $Global:ProgressReport | add-member -MemberType NoteProperty -Name "Title"-Value "$title" -Force $Global:ProgressReportTitle = $Title $Global:ProgressReportSubtitle = $Subtitle $Global:ProgressReportStartTime = $NiceDate $Global:ProgressReportItemCount = 0 New-UCMReportStep -StepName "Item" -StepResult "$($Global:ProgressReportItemCount)" } Function New-UCMReportItem { <# .SYNOPSIS Adds a new Line Object to the Report .DESCRIPTION Adds a new Line Object to the Report .EXAMPLE New-UCMReportItem -LineTitle "Username" -LineMessage "bob@contoso.com" .INPUTS This function accepts no inputs .LINK http://www.UcMadScientist.com https://github.com/Atreidae/UcmPSTools .ACKNOWLEDGEMENTS .NOTES Version: 1.1 Date: 19/06/2022 .VERSION HISTORY 1.1: Added per item numbering and timestamping 1.0: Initial Public Release #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseProcessBlockForPipelineCommand', '', Scope='Function')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingfunctions', '', Scope='Function')] #process does not change state, ShouldProcess is not required. [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Scope='Function')] #Required due to how this report works. Report must persist outside of its own scope [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUSeDeclaredVarsMoreThanAssignments', '', Scope='Function')] #Required due to how this report works. Variables must persist outside of their own scope Param ( [Parameter(ValueFromPipelineByPropertyName=$true, Mandatory, Position=1)] $LineTitle, [Parameter(ValueFromPipelineByPropertyName=$true, Mandatory, Position=2)] $LineMessage ) #region FunctionSetup, Set Default Variables for HTML Reporting and Write Log $function = 'New-UcmReportLine' [hashtable]$Return = @{} $return.Function = $function $return.Status = "Unknown" $return.Message = "Function did not return a status message" # Log why we were called Write-UcmLog -Message "$($MyInvocation.InvocationName) called with $($MyInvocation.Line)" -Severity 1 -Component $function Write-UcmLog -Message "Parameters" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Keys)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Parameters Values" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Values)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Optional Arguments" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$Args" -Severity 1 -Component $function -LogOnly #endregion FunctionSetup #region FunctionWork #Add the current time to the end of the old line New-UCMReportStep -Stepname "Time" -StepResult (Get-Date -displayhint time) #Merge the current line item into the report $Global:ProgressReport+= $Global:ThisReport #Init a new line item $Global:ThisReport = @() $Global:ThisReport = New-Object -TypeName PSobject $Global:ThisReport | add-member -MemberType NoteProperty -Name "$LineTitle" -Value $LineMessage #Increment the line counter and add to the new line $Global:ProgressReportItemCount ++ New-UCMReportStep -Stepname "ItemNumber" -StepResult "$Global:ProgressReportItemCount" } Function New-UcmReportStep { <# .SYNOPSIS Adds a new Step to the Report .DESCRIPTION Creates a new Step for the current line item (for example, creating a user) .EXAMPLE New-UcmReportStep -Stepname "Enable User" -StepResult "OK: Created User" .INPUTS This function accepts no inputs .REQUIRED FUNCTIONS Write-UcmLog: https://github.com/Atreidae/PowerShell-Functions/blob/main/New-Office365User.ps1 .LINK http://www.UcMadScientist.com https://github.com/Atreidae/UcmPSTools .ACKNOWLEDGEMENTS .NOTES Version: 1.0 Date: 18/11/2021 .VERSION HISTORY 1.0: Initial Public Release #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseProcessBlockForPipelineCommand', '', Scope='Function')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingfunctions', '', Scope='Function')] #process does not change state, ShouldProcess is not required. [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Scope='Function')] #Required due to how this report works. Report must persist outside of its own scope [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUSeDeclaredVarsMoreThanAssignments', '', Scope='Function')] #Required due to how this report works. Variables must persist outside of their own scope Param ( [Parameter(ValueFromPipelineByPropertyName=$true, Mandatory, Position=1)] $StepName, [Parameter(ValueFromPipelineByPropertyName=$true, Mandatory, Position=2)] $StepResult ) #region FunctionSetup, Set Default Variables for HTML Reporting and Write Log $function = 'New-UcmReportStep' [hashtable]$Return = @{} $return.Function = $function $return.Status = "Unknown" $return.Message = "Function did not return a status message" # Log why we were called Write-UcmLog -Message "$($MyInvocation.InvocationName) called with $($MyInvocation.Line)" -Severity 1 -Component $function Write-UcmLog -Message "Parameters" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Keys)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Parameters Values" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Values)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Optional Arguments" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$Args" -Severity 1 -Component $function -LogOnly #endregion FunctionSetup #region FunctionWork $Global:ThisReport | add-member -MemberType NoteProperty -Name "$StepName"-Value "$StepResult" -Force # endregion FunctionWork } Function Complete-UcmReport { <# .SYNOPSIS Adds the last Line Object to the Report .DESCRIPTION Adds the last Line Object to the Report .EXAMPLE Complete-UcmReport .INPUTS This function accepts no inputs .LINK http://www.UcMadScientist.com https://github.com/Atreidae/UcmPSTools .ACKNOWLEDGEMENTS .NOTES Version: 1.1 Date: 18/11/2021 .VERSION HISTORY 1.0: Initial Public Release #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseProcessBlockForPipelineCommand', '', Scope='Function')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Scope='Function')] #Required due to how this report works. Report must persist outside of its own scope [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUSeDeclaredVarsMoreThanAssignments', '', Scope='Function')] #Required due to how this report works. Variables must persist outside of their own scope Param ( #none ) #region FunctionSetup, Set Default Variables for HTML Reporting and Write Log $function = 'Complete-UcmReport' [hashtable]$Return = @{} $return.Function = $function $return.Status = "Unknown" $return.Message = "Function did not return a status message" # Log why we were called Write-UcmLog -Message "$($MyInvocation.InvocationName) called with $($MyInvocation.Line)" -Severity 1 -Component $function Write-UcmLog -Message "Parameters" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Keys)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Parameters Values" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Values)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Optional Arguments" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$Args" -Severity 1 -Component $function -LogOnly #endregion FunctionSetup #region FunctionWork #Merge the current item and cleanup $Global:ProgressReport+= $Global:ThisReport Remove-variable -Name ProgressReport -scope global $Global:ThisReport = @() $Global:ThisReport = New-Object -TypeName PSobject $Global:ThisReport | add-member -MemberType NoteProperty -Name "End of Report" -Value "End of report" } Function Export-UcmHTMLReport { <# .SYNOPSIS Grabs the data stored in the report object and converts it to HTML .DESCRIPTION Grabs the data stored in the report object and converts it to HTML By default, exports the current open report as a HTML in the current folder with the filename "$Title - $StartDate.html" You can change the path by editing $Global:HTMLReportFilename just before calling this function .EXAMPLE Export-UcmHTMLReport .INPUTS This function accepts no inputs .LINK http://www.UcMadScientist.com https://github.com/Atreidae/UcmPSTools .ACKNOWLEDGEMENTS .NOTES Version: 1.0 Date: 18/11/2021 .VERSION HISTORY 1.1: Added per item numbering and timestamping Fixed formatting issues Fixed repetitive EndDate Bug Removed erronus "EndDate" field from each line item 1.0: Initial Public Release #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseProcessBlockForPipelineCommand', '', Scope='Function')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Scope='Function')] #Required due to how this report works. Report must persist outside of its own scope [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUSeDeclaredVarsMoreThanAssignments', '', Scope='Function')] #Required due to how this report works. Variables must persist outside of their own scope Param ( [Parameter(ValueFromPipelineByPropertyName=$true, Position=1)] [string]$EndDate=(Get-Date -DisplayHint datetime) ) #region FunctionSetup, Set Default Variables for HTML Reporting and Write Log $function = 'Export-UcmHTMLReport' [hashtable]$Return = @{} $return.Function = $function $return.Status = "Unknown" $return.Message = "Function did not return a status message" # Log why we were called Write-UcmLog -Message "$($MyInvocation.InvocationName) called with $($MyInvocation.Line)" -Severity 1 -Component $function Write-UcmLog -Message "Parameters" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Keys)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Parameters Values" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Values)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Optional Arguments" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$Args" -Severity 1 -Component $function -LogOnly #endregion FunctionSetup #region FunctionWork #Import the end time $Global:ProgressReportEndTime = $EndDate #$Report = ($PSCommandPath -replace '.ps1',"$ReportDate.html") #Define the HTML Style $Style = @" <style> BODY{background-color::#b0c4de;font-family:Tahoma;font-size:12pt;} TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;} TH{border-width: 1px;padding: 3px;border-style: solid;border-color: black;color:white;background-color:#000099} TD{border-width: 1px;padding: 3px;border-style: solid;border-color: black;text-align:center;} </style> "@ Try #Export the report { $Global:ProgressReport | ConvertTo-Html -head $Style -body "<h1> $($Global:ProgressReportTitle) </h1> <h2> $Global:ProgressReportSubtitle </h2> The following report was started at $Global:ProgressReportStartTime and finishes at $Global:ProgressReportEndTime <br><br>" | ForEach-Object { #Add formatting for the different states if($_ -like "*<td>OK*") {$_ -replace "<td>OK", "<td bgcolor=#33FF66>OK"} Else {$_} } | ForEach-Object { if($_ -like "*<td>Warning*") {$_ -replace "<td>Warning", "<td bgcolor=#F9E79F>Warning"} Else {$_} } | ForEach-Object { If($_ -like "*<td>Error*") {$_ -replace "<td>Error", "<td bgcolor=#CD6155>Error"} Else {$_} #Write this out } | Out-File $Global:HTMLReportFilename #Open Browser invoke-Item $Global:HTMLReportFilename $Return.Status = "OK" $Return.Message = "HTML Report " Return $Return } Catch { Write-UcmLog -Message "Unexpected error when generating HTML report" -Severity 3 -Component $function Write-UcmLog -Message "$error[0]" -Severity 2 -Component $function } } Function Export-UcmCSVReport { <# .SYNOPSIS Grabs the data stored in the report object and converts it to a CSV .DESCRIPTION Grabs the data stored in the report object and converts it to a CSV Exports the current open report as a HTML in the current folder with the filename "$Title - $StartDate.csv" You can change the path by editing $Global:CSVReportFilename just before calling this function .EXAMPLE Export-UcmCsvReport .INPUTS This function accepts no inputs .LINK http://www.UcMadScientist.com https://github.com/Atreidae/UcmPSTools .ACKNOWLEDGEMENTS .NOTES Version: 1.0 Date: 18/11/2021 .VERSION HISTORY 1.0: Initial Public Release #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseProcessBlockForPipelineCommand', '', Scope='Function')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Scope='Function')] #Required due to how this report works. Report must persist outside of its own scope [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUSeDeclaredVarsMoreThanAssignments', '', Scope='Function')] #Required due to how this report works. Variables must persist outside of their own scope Param ( [Parameter(ValueFromPipelineByPropertyName=$true, Position=1)] [string]$EndDate=(Get-Date -DisplayHint datetime) ) #region FunctionSetup, Set Default Variables for HTML Reporting and Write Log $function = 'Export-UcmCSVReport' [hashtable]$Return = @{} $return.Function = $function $return.Status = "Unknown" $return.Message = "Function did not return a status message" # Log why we were called Write-UcmLog -Message "$($MyInvocation.InvocationName) called with $($MyInvocation.Line)" -Severity 1 -Component $function Write-UcmLog -Message "Parameters" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Keys)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Parameters Values" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Values)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Optional Arguments" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$Args" -Severity 1 -Component $function -LogOnly #endregion FunctionSetup #region FunctionWork #Import the end time Try { $Global:ProgressReport | Export-CSV $Global:CSVReportFilename $Return.Status = "OK" $Return.Message = "CSV Report" Return $Return } Catch { Write-UcmLog -Message "Unexpected error when generating CSV report" -Severity 3 -Component $function Write-UcmLog -Message "$error[0]" -Severity 2 -Component $function } } # SIG # Begin signature block # MIIRwgYJKoZIhvcNAQcCoIIRszCCEa8CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUGs/2uQ9aFk3/+Co735xQ3mp2 # 956ggg4OMIIGsDCCBJigAwIBAgIQCK1AsmDSnEyfXs2pvZOu2TANBgkqhkiG9w0B # AQwFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVk # IFJvb3QgRzQwHhcNMjEwNDI5MDAwMDAwWhcNMzYwNDI4MjM1OTU5WjBpMQswCQYD # VQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lD # ZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEg # Q0ExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1bQvQtAorXi3XdU5 # WRuxiEL1M4zrPYGXcMW7xIUmMJ+kjmjYXPXrNCQH4UtP03hD9BfXHtr50tVnGlJP # DqFX/IiZwZHMgQM+TXAkZLON4gh9NH1MgFcSa0OamfLFOx/y78tHWhOmTLMBICXz # ENOLsvsI8IrgnQnAZaf6mIBJNYc9URnokCF4RS6hnyzhGMIazMXuk0lwQjKP+8bq # HPNlaJGiTUyCEUhSaN4QvRRXXegYE2XFf7JPhSxIpFaENdb5LpyqABXRN/4aBpTC # fMjqGzLmysL0p6MDDnSlrzm2q2AS4+jWufcx4dyt5Big2MEjR0ezoQ9uo6ttmAaD # G7dqZy3SvUQakhCBj7A7CdfHmzJawv9qYFSLScGT7eG0XOBv6yb5jNWy+TgQ5urO # kfW+0/tvk2E0XLyTRSiDNipmKF+wc86LJiUGsoPUXPYVGUztYuBeM/Lo6OwKp7AD # K5GyNnm+960IHnWmZcy740hQ83eRGv7bUKJGyGFYmPV8AhY8gyitOYbs1LcNU9D4 # R+Z1MI3sMJN2FKZbS110YU0/EpF23r9Yy3IQKUHw1cVtJnZoEUETWJrcJisB9IlN # Wdt4z4FKPkBHX8mBUHOFECMhWWCKZFTBzCEa6DgZfGYczXg4RTCZT/9jT0y7qg0I # U0F8WD1Hs/q27IwyCQLMbDwMVhECAwEAAaOCAVkwggFVMBIGA1UdEwEB/wQIMAYB # Af8CAQAwHQYDVR0OBBYEFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB8GA1UdIwQYMBaA # FOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAK # BggrBgEFBQcDAzB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v # Y3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4 # oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJv # b3RHNC5jcmwwHAYDVR0gBBUwEzAHBgVngQwBAzAIBgZngQwBBAEwDQYJKoZIhvcN # AQEMBQADggIBADojRD2NCHbuj7w6mdNW4AIapfhINPMstuZ0ZveUcrEAyq9sMCcT # Ep6QRJ9L/Z6jfCbVN7w6XUhtldU/SfQnuxaBRVD9nL22heB2fjdxyyL3WqqQz/WT # auPrINHVUHmImoqKwba9oUgYftzYgBoRGRjNYZmBVvbJ43bnxOQbX0P4PpT/djk9 # ntSZz0rdKOtfJqGVWEjVGv7XJz/9kNF2ht0csGBc8w2o7uCJob054ThO2m67Np37 # 5SFTWsPK6Wrxoj7bQ7gzyE84FJKZ9d3OVG3ZXQIUH0AzfAPilbLCIXVzUstG2MQ0 # HKKlS43Nb3Y3LIU/Gs4m6Ri+kAewQ3+ViCCCcPDMyu/9KTVcH4k4Vfc3iosJocsL # 6TEa/y4ZXDlx4b6cpwoG1iZnt5LmTl/eeqxJzy6kdJKt2zyknIYf48FWGysj/4+1 # 6oh7cGvmoLr9Oj9FpsToFpFSi0HASIRLlk2rREDjjfAVKM7t8RhWByovEMQMCGQ8 # M4+uKIw8y4+ICw2/O/TOHnuO77Xry7fwdxPm5yg/rBKupS8ibEH5glwVZsxsDsrF # hsP2JjMMB0ug0wcCampAMEhLNKhRILutG4UI4lkNbcoFUCvqShyepf2gpx8GdOfy # 1lKQ/a+FSCH5Vzu0nAPthkX0tGFuv2jiJmCG6sivqf6UHedjGzqGVnhOMIIHVjCC # BT6gAwIBAgIQDyLHeeRvkUFg5QtSFTT8FjANBgkqhkiG9w0BAQsFADBpMQswCQYD # VQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lD # ZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEg # Q0ExMB4XDTIzMDIyMzAwMDAwMFoXDTI2MDIyMzIzNTk1OVowXjELMAkGA1UEBhMC # QVUxETAPBgNVBAgTCFZpY3RvcmlhMRAwDgYDVQQHEwdCZXJ3aWNrMRQwEgYDVQQK # EwtKYW1lcyBBcmJlcjEUMBIGA1UEAxMLSmFtZXMgQXJiZXIwggIiMA0GCSqGSIb3 # DQEBAQUAA4ICDwAwggIKAoICAQC47oExh25TrxvApIYdMRYvjOdZCb8WwgeTemm3 # ZY7BElIWu6+gzRGqQe8RFsN7oIgin5pvjTYIToxt1CCag2A5o8L0NtULmxJEegc+ # VaF24DZQqI4qGQGH/Qnglqys6+yPkwLnfeSxpeWe4u49HUUGDFIxHCh42MlCLp/f # fHT49QhhpO+LyeLnDoUs6DmahyIb6NeE2cW5AYRXEesW7GRNfXzygBSlVWJOgvcy # V5Y4IvAZVx2hKKMTjYFIz4/RYMg7fwYZEJ2LRJ/GnVazobKAvh6ZBet5KwVNI9EI # 29DtWQyK/RoPOguTRcB5VuiZVlv0xjBYM7iJuH2Soa3StQYVxL/5gjZCC9WOs4NR # EIGU3XmHoogFDvoT1vf1izMPFQzdZfgPvy/XXsbgTVo5ncesJ6WtZwqwCXG1K0XW # IPZqTHolc1MyU6K1bEHO+7YWLpKgM9THl644G7PEhcKpNDsHlfvLVQdYhI55UJtc # iyMrTw11CNECvk3GK1mrluvKsrxdaH6G3Sp9VVHRtef6OZ5SlzkM5ID4egB2bXRb # R/69bEuZr5hhm+v2lBSWIbZj/Mva6i/a/TAvy4vvPLo3DRcASkYZDC4T8gDMzmpG # Xs4jAc9sfTL9z+o5u1PLJHFGRjJ+Wa2CgSftCdbKLjn+AY9m8ipc8jmOBKNY9yGI # pQWapQIDAQABo4ICAzCCAf8wHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0 # TkIwHQYDVR0OBBYEFOBsg1xudlbXVSql8pWbiHoTyZS/MA4GA1UdDwEB/wQEAwIH # gDATBgNVHSUEDDAKBggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRw # Oi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmlu # Z1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hB # Mzg0MjAyMUNBMS5jcmwwPgYDVR0gBDcwNTAzBgZngQwBBAEwKTAnBggrBgEFBQcC # ARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGUBggrBgEFBQcBAQSBhzCB # hDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwGCCsGAQUF # BzAChlBodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVk # RzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJBgNVHRMEAjAA # MA0GCSqGSIb3DQEBCwUAA4ICAQBOh5vRXqTCQzv0T1F2EgDkq5VnljlHsa7Ov/d/ # lpOvr8NebBiatxbhfhPCnToY7BD2f7YVsUuQ+VDdcIYsskcU5spBHcFYidg2jGu4 # 59FGMaS765XStDwGGTN/360gEsNYSnKWYL4+8jYWHlzRO0jHloyWz+gF5dYWzdDJ # u1dudLIJ0RgrEVJeLSgIBWygLL5EyIzOPlrxztsILMSbdPTQLeBIm7ipOk4EACx1 # hhBVUsUoCAlASH+yCKDU4v2HFd7SzrkRUrf7XJ2Na2YsiHjiTGqHIE86KyvxGDhT # 3n2/jX23Nh/bkWHurHwTfaTCOQ44ZlAbnZQjBlmrFn5hPMXRpciiQFmrKTPD/nuo # 9MVnCciHEpHJ63/JZNF/eno1122/wVkL7MuRlCVHN7L/wuNQxQk3ARdIju6OD/Gi # Mwg0Qih6HVWJtkHK3ExoUKKKUZCOvIeHxzp+K6FWUupPZKUgWzn4AHMxm6zr+Sde # laIAACqAkxYsDYKbM7WlNi3uIH2HeXqU9uSDt5tgPpImrog/ab4HrhpDfITRgT1c # cxaWQezpJEPC+kqVD41T3wlEie1Qm4vYWg+oBVEMBxVLh6CYbeppCRTEXRGnAiCH # /Ma1uwyWnNCWxrhd1uSi6sj4ISzgnFyGCvsI0gavKpS5AQhapJgk6/fULTFeS+Ee # kRH9FDGCAx4wggMaAgEBMH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lD # ZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2ln # bmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMQIQDyLHeeRvkUFg5QtSFTT8FjAJ # BgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0B # CQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAj # BgkqhkiG9w0BCQQxFgQU3I/G0pKide5xkAHjlTcyaiZtBEAwDQYJKoZIhvcNAQEB # BQAEggIARV9Wu9/OG8TuRvEHFW+SiddzvfJsC/+j7sHd0qFgI4qMopKyfEVvQN9n # p2PniiMwqvhTvdoFoM5aUrfmg9iyjxeBscu85ArmSxThuG3MHZUg0pfl7NhT58BB # ej24SourXkHIDaEhxBZJaihISdI7anokzGaymMWUyBmtQLNj5BOtwFjMnUErVj8x # uUiE1YbkSKuJmoF6xFkez9b0zvLPMz0/vYIk1BnH90oWmhF/rQyxdjaExjIGnGow # LkEiRtRn3iiznvOR6mv/zmXxVoEj0ZrvLSO11v/cXl8/1BJoc6v+kwLYCIhFo7od # pNKuZowHnkNJeyOZNuk07Fuxyc4zJjCsSfKnvMviEFSyB8+0gPmCy0bdZAaZlbZO # Y13s+FON3P+QK/Knf6ftPMp3TIYWPi75Ooaq8mQNZbcyVkOHAAIJDVJrPg4LgyKQ # msV1TEnZxUHowJVmFBXc1/CmGmXfpFki9/50MD+i7oYL/f6qBL1muUCD8USWRqkA # 72uA3+hklMg0+1tk2tb5a9uyAPQrZrHy2a3kr6h0Aggg+ZhH+DRA4pdWujTtVJBu # a2qjrNcMlln/l3X5SQ5ojeJs+CVe6dH9TXwHq7U33CP7C16907IGQ7VOO5ZllMXV # 1DsDnClHMr3fwnLNSAEaiHtzoEBLDEVWKIOWhC79HOrMFG4UP6Y= # SIG # End signature block |