Src/Plugins/Html/Html.ps1
function Get-HtmlCanvasHeight { <# .SYNOPSIS Calculates the usable document canvas height. #> [CmdletBinding()] param ( [Parameter(Mandatory)] [System.String] $Orientation ) process { if ($Orientation -eq 'Portrait') { $pageHeight = $Document.Options['PageHeight'] return ($pageHeight - $Document.Options['MarginTop'] - $Document.Options['MarginBottom']) -as [System.Int32] } else { $pageHeight = $Document.Options['PageWidth'] return ($pageHeight - $Document.Options['MarginTop'] - (($Document.Options['MarginBottom'] * 1.5) -as [System.Int32])) } } } function Get-HtmlListItemInlineStyle { <# .SYNOPSIS Generates inline Html style attribute from PScribo list Item style overrides. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Management.Automation.PSObject] $Item ) process { $itemStyleBuilder = New-Object -TypeName System.Text.StringBuilder if ($Item.Font) { $fontList = $List.Font -Join "','" [ref] $null = $itemStyleBuilder.AppendFormat(" font-family: '{0}';", $fontList) } if ($Item.Size -gt 0) { ## Create culture invariant decimal https://github.com/iainbrighton/PScribo/issues/6 $invariantItemSize = ConvertTo-InvariantCultureString -Object ($Item.Size / 12) -Format 'f2' [ref] $null = $itemStyleBuilder.AppendFormat(' font-size: {0}rem;', $invariantItemSize) } if ($Item.Bold -eq $true) { [ref] $null = $itemStyleBuilder.Append(' font-weight: bold;') } if ($Item.Italic -eq $true) { [ref] $null = $itemStyleBuilder.Append(' font-style: italic;') } if ($Item.Underline -eq $true) { [ref] $null = $itemStyleBuilder.Append(' text-decoration: underline;') } if (-not [System.String]::IsNullOrEmpty($Item.Color)) { $color = Resolve-PScriboStyleColor -Color $Item.Color [ref] $null = $itemStyleBuilder.AppendFormat(' color: #{0};', $color) } return $itemStyleBuilder.ToString().TrimStart() } } function Get-HtmlParagraphInlineStyle { <# .SYNOPSIS Generates inline Html style attribute from PScribo paragraph style overrides. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Management.Automation.PSObject] $Paragraph, [Parameter(ValueFromPipelineByPropertyName)] [System.Management.Automation.SwitchParameter] $NoIndent ) process { $paragraphStyleBuilder = New-Object -TypeName System.Text.StringBuilder if (-not $NoIndent) { if ($Paragraph.Tabs -gt 0) { ## Default to 1/2in tab spacing $tabEm = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter (12.7 * $Paragraph.Tabs)) -Format 'f2' [ref] $null = $paragraphStyleBuilder.AppendFormat(' margin-left: {0}rem;', $tabEm) } } if ($Paragraph.Font) { [ref] $null = $paragraphStyleBuilder.AppendFormat(" font-family: '{0}';", $Paragraph.Font -Join "','") } if ($Paragraph.Size -gt 0) { ## Create culture invariant decimal https://github.com/iainbrighton/PScribo/issues/6 $invariantParagraphSize = ConvertTo-InvariantCultureString -Object ($Paragraph.Size / 12) -Format 'f2' [ref] $null = $paragraphStyleBuilder.AppendFormat(' font-size: {0}rem;', $invariantParagraphSize) } if ($Paragraph.Bold -eq $true) { [ref] $null = $paragraphStyleBuilder.Append(' font-weight: bold;') } if ($Paragraph.Italic -eq $true) { [ref] $null = $paragraphStyleBuilder.Append(' font-style: italic;') } if ($Paragraph.Underline -eq $true) { [ref] $null = $paragraphStyleBuilder.Append(' text-decoration: underline;') } if (-not [System.String]::IsNullOrEmpty($Paragraph.Color)) { $color = Resolve-PScriboStyleColor -Color $Paragraph.Color [ref] $null = $paragraphStyleBuilder.AppendFormat(' color: #{0};', $color) } return $paragraphStyleBuilder.ToString().TrimStart() } } function Get-HtmlStyle { <# .SYNOPSIS Generates html stylesheet style attributes from a PScribo document style. #> [CmdletBinding()] [OutputType([System.String])] param ( ## PScribo document style [Parameter(Mandatory, ValueFromPipeline)] [System.Management.Automation.PSObject] $Style ) process { $styleBuilder = New-Object -TypeName System.Text.StringBuilder [ref] $null = $styleBuilder.AppendFormat(" font-family: '{0}';", $Style.Font -join "','") ## Create culture invariant decimal https://github.com/iainbrighton/PScribo/issues/6 $invariantFontSize = ConvertTo-InvariantCultureString -Object ($Style.Size / 12) -Format 'f2' [ref] $null = $styleBuilder.AppendFormat(' font-size: {0}rem;', $invariantFontSize) [ref] $null = $styleBuilder.AppendFormat(' text-align: {0};', $Style.Align.ToLower()) if ($Style.Bold) { [ref] $null = $styleBuilder.Append(' font-weight: bold;') } else { [ref] $null = $styleBuilder.Append(' font-weight: normal;') } if ($Style.Italic) { [ref] $null = $styleBuilder.Append(' font-style: italic;') } if ($Style.Underline) { [ref] $null = $styleBuilder.Append(' text-decoration: underline;') } if ($Style.Color) { $color = Resolve-PScriboStyleColor -Color $Style.Color [ref] $null = $styleBuilder.AppendFormat(' color: #{0};', $color) } if ($Style.BackgroundColor) { $backgroundColor = Resolve-PScriboStyleColor -Color $Style.BackgroundColor [ref] $null = $styleBuilder.AppendFormat(' background-color: #{0};', $backgroundColor) } return $styleBuilder.ToString() } } function Get-HtmlTable { <# .SYNOPSIS Generates html <table> from a PScribo.Table object. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Management.Automation.PSObject] $Table ) begin { $formattedTables = ConvertTo-PScriboPreformattedTable -Table $Table } process { $tableStyle = Get-PScriboDocumentStyle -TableStyle $Table.Style $tableBuilder = New-Object -TypeName System.Text.StringBuilder foreach ($formattedTable in $formattedTables) { if ($Table.HasCaption -and ($tableStyle.CaptionLocation -eq 'Above')) { [ref] $null = $tableBuilder.Append((Get-HtmlTableCaption -Table $Table)) } [ref] $null = $tableBuilder.Append((Get-HtmlTableDiv -Table $Table)) [ref] $null = $tableBuilder.Append((Get-HtmlTableColGroup -Table $Table)) ## Table headers $startRow = 0 if ($formattedTable.HasHeaderRow) { [ref] $null = $tableBuilder.Append('<thead><tr>') foreach ($cell in $formattedTable.Rows[0].Cells) { [ref] $null = $tableBuilder.AppendFormat('<th>{0}</th>', $cell.Content) } [ref] $null = $tableBuilder.Append('</tr></thead>') $startRow += 1 } ## Table rows [ref] $null = $tableBuilder.AppendLine('<tbody>') for ($r = $startRow; $r -lt $formattedTable.Rows.Count; $r++) { $row = $formattedTable.Rows[$r] if ($row.IsStyleInherited) { [ref] $null = $tableBuilder.Append('<tr>') } else { [ref] $null = $tableBuilder.AppendFormat('<tr style="{0}">', (Get-HtmlStyle -Style $Document.Styles[$row.Style]).Trim()) } for ($c = 0; $c -lt $row.Cells.Count; $c++) { $cell = $row.Cells[$c] if ([System.String]::IsNullOrEmpty($cell.Content)) { $encodedHtmlContent = ' ' # is already encoded (#72) } else { $cellContent = Resolve-PScriboToken -InputObject $cell.Content $encodedHtmlContent = [System.Net.WebUtility]::HtmlEncode($cellContent) $encodedHtmlContent = $encodedHtmlContent.Replace([System.Environment]::NewLine, '<br />') } if ($formattedTable.HasHeaderColumn -and ($c -eq 0)) { ## Display first column with header styling [ref] $null = $tableBuilder.AppendFormat('<th>{0}</th>', $encodedHtmlContent) } else { if ($cell.IsStyleInherited) { [ref] $null = $tableBuilder.AppendFormat('<td>{0}</td>', $encodedHtmlContent) } else { $propertyStyleHtml = (Get-HtmlStyle -Style $Document.Styles[$cell.Style]).Trim() [ref] $null = $tableBuilder.AppendFormat('<td style="{0}">{1}</td>', $propertyStyleHtml, $encodedHtmlContent) } } } [ref] $null = $tableBuilder.AppendLine('</tr>') } [ref] $null = $tableBuilder.AppendLine('</tbody></table>') if ($Table.HasCaption -and ($tableStyle.CaptionLocation -eq 'Below')) { [ref] $null = $tableBuilder.Append((Get-HtmlTableCaption -Table $Table)) } ## Add a space between each table to mirror Word output rendering [ref] $null = $tableBuilder.AppendLine('<br /></div>') } return $tableBuilder.ToString() } } function Get-HtmlTableCaption { <# .SYNOPSIS Generates html <p> caption from a PScribo.Table object. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Management.Automation.PSObject] $Table ) process { $tableStyle = Get-PScriboDocumentStyle -TableStyle $Table.Style ## Scaffold paragraph and paragraph run for table caption $paragraphId = '{0}{1}' -f $tableStyle.CaptionPrefix, $Table.Number $paragraph = New-PScriboParagraph -Id $paragraphId -Style $tableStyle.CaptionStyle -NoIncrementCounter $paragraphRunText = '{0} {1} {2}' -f $tableStyle.CaptionPrefix, $Table.CaptionNumber, $Table.Caption $paragraphRun = New-PScriboParagraphRun -Text $paragraphRunText $paragraphRun.IsParagraphRunEnd = $true [ref] $null = $paragraph.Sections.Add($paragraphRun) return (Out-HtmlParagraph -Paragraph $paragraph) } } function Get-HtmlTableColGroup { <# .SYNOPSIS Generates Html <colgroup> tags based on table column widths #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Management.Automation.PSObject] $Table ) process { $colGroupBuilder = New-Object -TypeName 'System.Text.StringBuilder' if ($Table.ColumnWidths) { [ref] $null = $colGroupBuilder.Append('<colgroup>') foreach ($columnWidth in $Table.ColumnWidths) { if ($null -eq $columnWidth) { [ref] $null = $colGroupBuilder.Append('<col />') } else { [ref] $null = $colGroupBuilder.AppendFormat('<col style="max-width:{0}%; min-width:{0}%; width:{0}%" />', $columnWidth) } } [ref] $null = $colGroupBuilder.AppendLine('</colgroup>') } return $colGroupBuilder.ToString() } } function Get-HtmlTableDiv { <# .SYNOPSIS Generates Html <div style=..><table style=..> tags based upon table width, columns and indentation .NOTES A <div> is required to ensure that the table stays within the "page" boundaries/margins. #> param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Management.Automation.PSObject] $Table ) process { $divBuilder = New-Object -TypeName 'System.Text.StringBuilder' [ref] $null = $divBuilder.Append('<div style="word-break: break-word; overflow-wrap: anywhere; ') if ($Table.Tabs -gt 0) { $invariantMarginLeft = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter (12.7 * $Table.Tabs)) [ref] $null = $divBuilder.AppendFormat('margin-left: {0}rem; ' -f $invariantMarginLeft) } ## Ensure we close the <div style=" "> tag [ref] $null = $divBuilder.AppendFormat('"><table class="{0}"', $Table.Style.ToLower()) $styleElements = @() if ($Table.Width -gt 0) { $styleElements += 'width:{0}%;' -f $Table.Width } if ($Table.ColumnWidths) { $styleElements += 'table-layout: fixed;' #$styleElements += 'word-break: break-word;' # 'word-wrap: break-word;' or 'overflow-wrap: break-word;'? } if ($styleElements.Count -gt 0) { [ref] $null = $divBuilder.AppendFormat(' style="{0}">', [System.String]::Join(' ', $styleElements)) } else { [ref] $null = $divBuilder.Append('>') } return $divBuilder.ToString() } } function Get-HtmlTablePaddingStyle { <# .SYNOPSIS Generates html stylesheet style padding attributes from a PScribo document table style. #> [CmdletBinding()] [OutputType([System.String])] param ( ## PScribo document table style [Parameter(Mandatory, ValueFromPipeline)] [System.Management.Automation.PSObject] $TableStyle ) process { $tableStyleBuilder = New-Object -TypeName 'System.Text.StringBuilder' [ref] $null = $tableStyleBuilder.AppendFormat(' padding: {0}rem {1}rem {2}rem {3}rem;', (ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $TableStyle.PaddingTop)), (ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $TableStyle.PaddingRight)), (ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $TableStyle.PaddingBottom)), (ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $TableStyle.PaddingLeft))) return $tableStyleBuilder.ToString() } } function Get-HtmlTableStyle { <# .SYNOPSIS Generates html stylesheet style attributes from a PScribo document table style. #> [CmdletBinding()] [OutputType([System.String])] param ( ## PScribo document table style [Parameter(Mandatory, ValueFromPipeline)] [System.Management.Automation.PSObject] $TableStyle ) process { $tableStyleBuilder = New-Object -TypeName 'System.Text.StringBuilder' [ref] $null = $tableStyleBuilder.AppendFormat((Get-HtmlTablePaddingStyle -TableStyle $TableStyle)) [ref] $null = $tableStyleBuilder.AppendFormat(' border-style: {0};', $TableStyle.BorderStyle.ToLower()) if ($TableStyle.BorderWidth -gt 0) { $invariantBorderWidth = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $TableStyle.BorderWidth) [ref] $null = $tableStyleBuilder.AppendFormat(' border-width: {0}rem;', $invariantBorderWidth) $borderColor = Resolve-PScriboStyleColor -Color $TableStyle.BorderColor [ref] $null = $tableStyleBuilder.AppendFormat(' border-color: #{0};', $borderColor.ToLower()) } [ref] $null = $tableStyleBuilder.Append(' border-collapse: collapse;') ## <table align="center"> is deprecated in Html5 if ($TableStyle.Align -eq 'Center') { [ref] $null = $tableStyleBuilder.Append(' margin-left: auto; margin-right: auto;') } elseif ($TableStyle.Align -eq 'Right') { [ref] $null = $tableStyleBuilder.Append(' margin-left: auto; margin-right: 0;') } return $tableStyleBuilder.ToString() } } function New-PScriboHtmlOption { <# .SYNOPSIS Sets the text plugin specific formatting/output options. .NOTES All plugin options should be prefixed with the plugin name. #> [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')] [OutputType([System.Collections.Hashtable])] param ( [Parameter(ValueFromPipelineByPropertyName)] [ValidateNotNull()] [System.Boolean] $NoPageLayoutStyle = $false ) process { return @{ NoPageLayoutStyle = $NoPageLayoutStyle } } } function Out-HtmlBlankLine { <# .SYNOPSIS Outputs html PScribo.Blankline. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Management.Automation.PSObject] $BlankLine ) process { $blankLineBuilder = New-Object -TypeName System.Text.StringBuilder for ($i = 0; $i -lt $BlankLine.LineCount; $i++) { [ref] $null = $blankLineBuilder.Append('<br />') } return $blankLineBuilder.ToString() } } function Out-HtmlDocument { <# .SYNOPSIS Html output plugin for PScribo. .DESCRIPTION Outputs a Html file representation of a PScribo document object. #> [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments','pluginName')] [OutputType([System.IO.FileInfo])] param ( ## PScribo document object to convert to a text document [Parameter(Mandatory, ValueFromPipeline)] [System.Management.Automation.PSObject] $Document, ## Output directory path for the .html file [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [ValidateNotNullOrEmpty()] [System.String] $Path, ### Hashtable of all plugin supported options [Parameter(ValueFromPipelineByPropertyName)] [AllowNull()] [System.Collections.Hashtable] $Options ) process { $pluginName = 'Html' $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() Write-PScriboMessage -Message ($localized.DocumentProcessingStarted -f $Document.Name) ## Merge the document, plugin default and specified/specific plugin options $mergePScriboPluginOptionParams = @{ DefaultPluginOptions = New-PScriboHtmlOption DocumentOptions = $Document.Options PluginOptions = $Options } $options = Merge-PScriboPluginOption @mergePScriboPluginOptionParams $noPageLayoutStyle = $Options['NoPageLayoutStyle'] $topMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $options['MarginTop']) -Format 'f2' $leftMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $options['MarginLeft']) -Format 'f2' $bottomMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $options['MarginBottom']) -Format 'f2' $rightMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $options['MarginRight']) -Format 'f2' $script:currentPageNumber = 1 [System.Text.StringBuilder] $htmlBuilder = New-Object System.Text.StringBuilder [ref] $null = $htmlBuilder.AppendLine('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">') [ref] $null = $htmlBuilder.AppendLine('<html xmlns="http://www.w3.org/1999/xhtml">') [ref] $null = $htmlBuilder.AppendLine('<head><title>{0}</title>' -f $Document.Name) [ref] $null = $htmlBuilder.AppendLine('{0}</head><body>' -f (Out-HtmlStyle -Styles $Document.Styles -TableStyles $Document.TableStyles -NoPageLayoutStyle:$noPageLayoutStyle)) [ref] $null = $htmlBuilder.AppendFormat('<div class="{0}">', $options['PageOrientation'].ToLower()) [ref] $null = $htmlBuilder.AppendFormat('<div class="{0}" style="padding-top: {1}rem; padding-left: {2}rem; padding-bottom: {3}rem; padding-right: {4}rem;">', $Document.DefaultStyle, $topMargin, $leftMargin, $bottomMargin, $rightMargin).AppendLine() [ref] $null = $htmlBuilder.AppendLine((Out-HtmlHeaderFooter -Header -FirstPage)) $canvasHeight = Get-HtmlCanvasHeight -Orientation $options['PageOrientation'] [ref] $null = $htmlBuilder.AppendFormat('<div style="min-height: {0}mm" >', $canvasHeight) foreach ($subSection in $Document.Sections.GetEnumerator()) { $currentIndentationLevel = 1 if ($null -ne $subSection.PSObject.Properties['Level']) { $currentIndentationLevel = $subSection.Level +1 } Write-PScriboProcessSectionId -SectionId $subSection.Id -SectionType $subSection.Type -Indent $currentIndentationLevel switch ($subSection.Type) { 'PScribo.Section' { [ref] $null = $htmlBuilder.Append((Out-HtmlSection -Section $subSection)) } 'PScribo.Paragraph' { [ref] $null = $htmlBuilder.Append((Out-HtmlParagraph -Paragraph $subSection)) } 'PScribo.Table' { [ref] $null = $htmlBuilder.Append((Out-HtmlTable -Table $subSection)) } 'PScribo.LineBreak' { [ref] $null = $htmlBuilder.Append((Out-HtmlLineBreak)) } 'PScribo.PageBreak' { [ref] $null = $htmlBuilder.Append((Out-HtmlPageBreak -Orientation $options['PageOrientation'])) } 'PScribo.TOC' { [ref] $null = $htmlBuilder.Append((Out-HtmlTOC -TOC $subSection)) } 'PScribo.BlankLine' { [ref] $null = $htmlBuilder.Append((Out-HtmlBlankLine -BlankLine $subSection)) } 'PScribo.Image' { [ref] $null = $htmlBuilder.Append((Out-HtmlImage -Image $subSection)) } 'PScribo.ListReference' { $htmlList = Out-HtmlList -List $Document.Lists[$subSection.Number -1] [ref] $null = $htmlBuilder.Append($htmlList).AppendLine() } Default { Write-PScriboMessage -Message ($localized.PluginUnsupportedSection -f $subSection.Type) -IsWarning } } } #end foreach section [ref] $null = $htmlBuilder.AppendLine('</div>') ## Canvas [ref] $null = $htmlBuilder.Append((Out-HtmlHeaderFooter -Footer)) [ref] $null = $htmlBuilder.AppendLine('</div></div></body>') $stopwatch.Stop() Write-PScriboMessage -Message ($localized.DocumentProcessingCompleted -f $Document.Name) $destinationPath = Join-Path $Path ('{0}.html' -f $Document.Name) Write-PScriboMessage -Message ($localized.SavingFile -f $destinationPath) $htmlBuilder.ToString().TrimEnd() | Out-File -FilePath $destinationPath -Force -Encoding utf8 [ref] $null = $htmlBuilder if ($stopwatch.Elapsed.TotalSeconds -gt 90) { Write-PScriboMessage -Message ($localized.TotalProcessingTimeMinutes -f $stopwatch.Elapsed.TotalMinutes) } else { Write-PScriboMessage -Message ($localized.TotalProcessingTimeSeconds -f $stopwatch.Elapsed.TotalSeconds) } Write-Output (Get-Item -Path $destinationPath) } } function Out-HtmlHeaderFooter { [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'DefaultHeader')] [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FirstPageHeader')] [System.Management.Automation.SwitchParameter] $Header, [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'DefaultFooter')] [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FirstPageFooter')] [System.Management.Automation.SwitchParameter] $Footer, [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FirstPageHeader')] [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FirstPageFooter')] [System.Management.Automation.SwitchParameter] $FirstPage ) process { $headerFooter = Get-PScriboHeaderFooter @PSBoundParameters if ($null -ne $headerFooter) { [System.Text.StringBuilder] $hfBuilder = New-Object System.Text.StringBuilder [ref] $null = $hfBuilder.Append('<div>') foreach ($subSection in $headerFooter.Sections.GetEnumerator()) { switch ($subSection.Type) { 'PScribo.Paragraph' { [ref] $null = $hfBuilder.Append((Out-HtmlParagraph -Paragraph $subSection)) } 'PScribo.Table' { [ref] $null = $hfBuilder.Append((Out-HtmlTable -Table $subSection)) } 'PScribo.BlankLine' { [ref] $null = $hfBuilder.Append((Out-HtmlBlankLine -BlankLine $subSection)) } 'PScribo.LineBreak' { [ref] $null = $hfBuilder.Append((Out-HtmlLineBreak)) } } } [ref] $null = $hfBuilder.Append('</div>') return $hfBuilder.ToString() } } } function Out-HtmlImage { <# .SYNOPSIS Output embedded Html image. #> [CmdletBinding()] param ( ## PScribo Image object [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Management.Automation.PSObject] $Image ) process { [System.Text.StringBuilder] $imageBuilder = New-Object -TypeName 'System.Text.StringBuilder' [ref] $null = $imageBuilder.AppendFormat('<div align="{0}">', $Image.Align).AppendLine() $imageBase64 = [System.Convert]::ToBase64String($Image.Bytes) [ref] $null = $imageBuilder.AppendFormat('<img src="data:{0};base64, {1}" alt="{2}" height="{3}" width="{4}" />', $Image.MimeType, $imageBase64, $Image.Text, $Image.Height, $Image.Width).AppendLine() [ref] $null = $imageBuilder.AppendLine('</div>') return $imageBuilder.ToString() } } function Out-HtmlLineBreak { <# .SYNOPSIS Output formatted Html line break. #> [CmdletBinding()] [OutputType([System.String])] param ( ) process { return '<hr />' } } function Out-HtmlList { <# .SYNOPSIS Output formatted Html list. #> [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments','Options')] param ( ## List to output [Parameter(Mandatory, ValueFromPipeline)] [System.Management.Automation.PSObject] $List, ## List indent [Parameter(ValueFromPipelineByPropertyName)] [System.Int32] $Indent, ## Number style [Parameter(ValueFromPipelineByPropertyName)] [System.String] $NumberStyle, ## Bullet style [Parameter(ValueFromPipelineByPropertyName)] [System.String] $BulletStyle ) begin { ## Fix Set-StrictMode if (-not (Test-Path -Path Variable:\Options)) { $options = New-PScriboHtmlOption } } process { $leader = ''.PadRight($Indent, ' ') $listBuilder = New-Object -TypeName System.Text.StringBuilder if ($List.IsNumbered) { if ($List.HasNumberStyle) { $NumberStyle = $List.NumberStyle } elseif (-not $PSBoundParameters.ContainsKey('NumberStyle')) { $NumberStyle = $Document.DefaultNumberStyle } $style = $Document.NumberStyles[$NumberStyle] $outHtmlListParams = @{ NumberStyle = $NumberStyle } switch ($style.Format) { 'Number' { $inlineStyle = 'decimal' } 'Letter' { if ($style.Uppercase) { $inlineStyle = 'upper-alpha' } else { $inlineStyle = 'lower-alpha' } } 'Roman' { if ($style.Uppercase) { $inlineStyle = 'upper-roman' } else { $inlineStyle = 'lower-roman' } } 'Custom' { $inlineStyle = 'decimal' } } if ($List.HasStyle) { [ref] $null = $listBuilder.AppendFormat('{0}<ol class="{1}" style="list-style-type:{2};">', $leader, $List.Style, $inlineStyle) } else { [ref] $null = $listBuilder.AppendFormat('{0}<ol style="list-style-type:{1};">', $leader, $inlineStyle) } [ref] $null = $listBuilder.AppendLine() } else { if ($List.HasBulletStyle) { $BulletStyle = $List.BulletStyle } switch ($BulletStyle) { Circle { $inlineStyle = ' style="list-style-type:circle;"' } Disc { $inlineStyle = ' style="list-style-type:disc;"' } Square { $inlineStyle = ' style="list-style-type:square;"' } Default { ## Dash style is not supported in Html so default to the browser's rendering engine $inlineStyle = '' } } $outHtmlListParams = @{ BulletStyle = $BulletStyle } if ($List.HasStyle) { [ref] $null = $listBuilder.AppendFormat('{0}<ul class="{1}"{2}>', $leader, $List.Style, $inlineStyle) } else { [ref] $null = $listBuilder.AppendFormat('{0}<ul{1}>', $leader, $inlineStyle) } [ref] $null = $listBuilder.AppendLine() } $leader = ''.PadRight($Indent, ' ') foreach ($item in $List.Items) { if ($item.Type -eq 'PScribo.Item') { if (($item.HasStyle -eq $true) -and ($item.HasInlineStyle -eq $true)) { $inlineStyle = Get-HtmlListItemInlineStyle -Item $item [ref] $null = $listBuilder.AppendFormat('{0}<li class="{1}" style="{2}">{3}</li>', $leader, $item.Style, $inlineStyle, $item.Text) } elseif ($item.HasStyle) { [ref] $null = $listBuilder.AppendFormat('{0} <li class="{1}"">{2}</li>', $leader, $item.Style, $item.Text) } elseif ($item.HasInlineStyle) { $inlineStyle = Get-HtmlListItemInlineStyle -Item $item [ref] $null = $listBuilder.AppendFormat('{0} <li style="{1}">{2}</li>', $leader, $inlineStyle, $item.Text) } else { [ref] $null = $listBuilder.AppendFormat('{0} <li>{1}</li>', $leader, $item.Text) } [ref] $null = $listBuilder.AppendLine() } else { $nestedList = Out-HtmlList -List $item -Indent ($Indent +2) @outHtmlListParams [ref] $null = $listBuilder.AppendLine($nestedList) } } if ($List.IsNumbered) { [ref] $null = $listBuilder.AppendFormat('{0}</ol>', $leader) } else { [ref] $null = $listBuilder.AppendFormat('{0}</ul>', $leader) } [ref] $null = $listBuilder.AppendLine() return $listBuilder.ToString() } } function Out-HtmlPageBreak { <# .SYNOPSIS Output formatted Html page break. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.String] $Orientation ) process { [System.Text.StringBuilder] $pageBreakBuilder = New-Object 'System.Text.StringBuilder' [ref] $null = $pageBreakBuilder.Append('</div>') ## Canvas $isFirstPage = $currentPageNumber -eq 1 [ref] $null = $pageBreakBuilder.Append((Out-HtmlHeaderFooter -Footer -FirstPage:$isFirstPage)) $script:currentPageNumber++ [ref] $null = $pageBreakBuilder.Append('</div></div>') $topMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $Document.Options['MarginTop']) -Format 'f2' $leftMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $Document.Options['MarginLeft']) -Format 'f2' $bottomMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $Document.Options['MarginBottom']) -Format 'f2' $rightMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $Document.Options['MarginRight']) -Format 'f2' [ref] $null = $pageBreakBuilder.AppendFormat('<div class="{0}">', $Orientation.ToLower()) [ref] $null = $pageBreakBuilder.AppendFormat('<div class="{0}" style="padding-top: {1}rem; padding-left: {2}rem; padding-bottom: {3}rem; padding-right: {4}rem;">', $Document.DefaultStyle, $topMargin, $leftMargin, $bottomMargin, $rightMargin).AppendLine() $canvasHeight = Get-HtmlCanvasHeight -Orientation $Orientation [ref] $null = $pageBreakBuilder.AppendFormat('<div style="min-height: {0}mm" >', $canvasHeight) [ref] $null = $pageBreakBuilder.Append((Out-HtmlHeaderFooter -Header)) return $pageBreakBuilder.ToString() } } function Out-HtmlParagraph { <# .SYNOPSIS Output formatted Html paragraph run. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Management.Automation.PSObject] $Paragraph ) process { [System.Text.StringBuilder] $paragraphBuilder = New-Object -TypeName 'System.Text.StringBuilder' if ([System.String]::IsNullOrEmpty($Paragraph.Style)) { if ($Paragraph.Tabs -gt 0) { ## Default to 1/2in tab spacing $tabEm = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter (12.7 * $Paragraph.Tabs)) -Format 'f2' [ref] $null = $paragraphBuilder.AppendFormat('<div style="margin-left: {0}rem;" >', $tabEm) } else { [ref] $null = $paragraphBuilder.Append('<div>') } } else { if ($Paragraph.Tabs -gt 0) { ## Default to 1/2in tab spacing $tabEm = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter (12.7 * $Paragraph.Tabs)) -Format 'f2' [ref] $null = $paragraphBuilder.AppendFormat('<div class="{0}" style="margin-left: {1}rem;" >', $Paragraph.Style, $tabEm) } else { [ref] $null = $paragraphBuilder.AppendFormat('<div class="{0}">', $Paragraph.Style) } } foreach ($paragraphRun in $Paragraph.Sections) { if (($paragraphRun.HasStyle -eq $true) -and ($paragraphRun.HasInlineStyle -eq $true)) { $inlineStyle = Get-HtmlParagraphInlineStyle -Paragraph $paragraphRun -NoIndent [ref] $null = $paragraphBuilder.AppendFormat('<span class="{0}" style="{1}">', $paragraphRun.Style, $inlineStyle) } elseif ($paragraphRun.HasStyle) { [ref] $null = $paragraphBuilder.AppendFormat('<span class="{0}">', $paragraphRun.Style) } elseif ($paragraphRun.HasInlineStyle) { $inlineStyle = Get-HtmlParagraphInlineStyle -Paragraph $paragraphRun -NoIndent [ref] $null = $paragraphBuilder.AppendFormat('<span style="{0}">', $inlineStyle) } $text = Resolve-PScriboToken -InputObject $paragraphRun.Text $encodedText = [System.Net.WebUtility]::HtmlEncode($text) $encodedText = $encodedText.Replace([System.Environment]::NewLine, '<br />') [ref] $null = $paragraphBuilder.Append($encodedText) if (($paragraphRun.IsParagraphRunEnd -eq $false) -and ($paragraphRun.NoSpace -eq $false)) { [ref] $null = $paragraphBuilder.Append(' ') } if ($paragraphRun.HasStyle -or $paragraphRun.HasInlineStyle) { [ref] $null = $paragraphBuilder.Append('</span>') } } [ref] $null = $paragraphBuilder.Append('</div>') return $paragraphBuilder.ToString() } } function Out-HtmlSection { <# .SYNOPSIS Output formatted Html section. #> [CmdletBinding()] [OutputType([System.String])] param ( ## Section to output [Parameter(Mandatory, ValueFromPipeline)] [System.Management.Automation.PSObject] $Section ) process { [System.Text.StringBuilder] $sectionBuilder = New-Object System.Text.StringBuilder if ($Section.IsSectionBreak) { [ref] $null = $sectionBuilder.Append((Out-HtmlPageBreak -Orientation $Section.Orientation)) } $encodedSectionName = [System.Net.WebUtility]::HtmlEncode($Section.Name) if ($Document.Options['EnableSectionNumbering']) { [System.String] $sectionName = '{0} {1}' -f $Section.Number, $encodedSectionName } else { [System.String] $sectionName = '{0}' -f $encodedSectionName } [int] $headerLevel = $Section.Number.Split('.').Count ## Html <h5> is the maximum supported level if ($headerLevel -gt 6) { Write-PScriboMessage -Message $localized.MaxHeadingLevelWarning -IsWarning $headerLevel = 6 } if ([System.String]::IsNullOrEmpty($Section.Style)) { $className = $Document.DefaultStyle } else { $className = $Section.Style } if ($Section.Tabs -gt 0) { $tabEm = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter (12.7 * $Section.Tabs)) -Format 'f2' [ref] $null = $sectionBuilder.AppendFormat('<div style="margin-left: {0}rem;">' -f $tabEm) } [ref] $null = $sectionBuilder.AppendFormat('<a name="{0}"><h{1} class="{2}">{3}</h{1}></a>', $Section.Id, $headerLevel, $className, $sectionName.TrimStart()) if ($Section.Tabs -gt 0) { [ref] $null = $sectionBuilder.Append('</div>') } foreach ($subSection in $Section.Sections.GetEnumerator()) { $currentIndentationLevel = 1 if ($null -ne $subSection.PSObject.Properties['Level']) { $currentIndentationLevel = $subSection.Level +1 } Write-PScriboProcessSectionId -SectionId $subSection.Id -SectionType $subSection.Type -Indent $currentIndentationLevel switch ($subSection.Type) { 'PScribo.Section' { [ref] $null = $sectionBuilder.Append((Out-HtmlSection -Section $subSection)) } 'PScribo.Paragraph' { [ref] $null = $sectionBuilder.Append((Out-HtmlParagraph -Paragraph $subSection)) } 'PScribo.LineBreak' { [ref] $null = $sectionBuilder.Append((Out-HtmlLineBreak)) } 'PScribo.PageBreak' { [ref] $null = $sectionBuilder.Append((Out-HtmlPageBreak -Orientation $Section.Orientation)) } 'PScribo.Table' { [ref] $null = $sectionBuilder.Append((Out-HtmlTable -Table $subSection)) } 'PScribo.BlankLine' { [ref] $null = $sectionBuilder.Append((Out-HtmlBlankLine -BlankLine $subSection)) } 'PScribo.Image' { [ref] $null = $sectionBuilder.Append((Out-HtmlImage -Image $subSection)) } 'PScribo.ListReference' { $htmlList = Out-HtmlList -List $Document.Lists[$subSection.Number -1] [ref] $null = $sectionBuilder.Append($htmlList).AppendLine() } Default { Write-PScriboMessage -Message ($localized.PluginUnsupportedSection -f $subSection.Type) -IsWarning } } } return $sectionBuilder.ToString() } } function Out-HtmlStyle { <# .SYNOPSIS Generates an in-line HTML CSS stylesheet from a PScribo document styles and table styles. #> [CmdletBinding()] [OutputType([System.String])] param ( ## PScribo document styles [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [System.Collections.Hashtable] $Styles, ## PScribo document tables styles [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [System.Collections.Hashtable] $TableStyles, ## Suppress page layout styling [Parameter(ValueFromPipelineByPropertyName)] [System.Management.Automation.SwitchParameter] $NoPageLayoutStyle ) process { $stylesBuilder = New-Object -TypeName 'System.Text.StringBuilder' [ref] $null = $stylesBuilder.AppendLine('<style type="text/css">') $pageWidth = $Document.Options['PageWidth'] $pageHeight = $Document.Options['PageHeight'] if (-not $NoPageLayoutStyle) { ## Add HTML page layout styling options, e.g. when emailing HTML documents [ref] $null = $stylesBuilder.AppendLine('html { height: 100%; -webkit-background-size: cover; -moz-background-size: cover; -o-background-size: cover; background-size: cover; background: #e6e6e6; }') [ref] $null = $stylesBuilder.Append("page { background: white; display: block; margin-top: 1rem; margin-left: auto; margin-right: auto; margin-bottom: 1rem; ") [ref] $null = $stylesBuilder.AppendLine('border-style: solid; border-width: 1px; border-color: #c6c6c6; }') [ref] $null = $stylesBuilder.AppendLine('@media print { body, page { margin: 0; box-shadow: 0; } }') [ref] $null = $stylesBuilder.AppendLine('hr { margin-top: 1.0rem; }') [ref] $null = $stylesBuilder.Append(" .portrait { background: white; width: $($pageWidth)mm; display: block; margin-top: 1rem; margin-left: auto; margin-right: auto; margin-bottom: 1rem; position: relative; ") [ref] $null = $stylesBuilder.AppendLine('border-style: solid; border-width: 1px; border-color: #c6c6c6; }') [ref] $null = $stylesBuilder.Append(" .landscape { background: white; width: $($pageHeight)mm; display: block; margin-top: 1rem; margin-left: auto; margin-right: auto; margin-bottom: 1rem; position: relative; ") [ref] $null = $stylesBuilder.AppendLine('border-style: solid; border-width: 1px; border-color: #c6c6c6; }') } foreach ($style in $Styles.Keys) { ## Build style $htmlStyle = Get-HtmlStyle -Style $Styles[$style] [ref] $null = $stylesBuilder.AppendFormat(' .{0} {{{1} }}', $Styles[$style].Id, $htmlStyle).AppendLine() } foreach ($tableStyle in $TableStyles.Keys) { $tStyle = $TableStyles[$tableStyle] $tableStyleId = $tStyle.Id.ToLower() $htmlTableStyle = Get-HtmlTableStyle -TableStyle $tStyle $htmlHeaderStyle = Get-HtmlStyle -Style $Styles[$tStyle.HeaderStyle] $htmlRowStyle = Get-HtmlStyle -Style $Styles[$tStyle.RowStyle] $htmlAlternateRowStyle = Get-HtmlStyle -Style $Styles[$tStyle.AlternateRowStyle] ## Generate table style [ref] $null = $stylesBuilder.AppendFormat(' table.{0} {{{1} }}', $tableStyleId, $htmlTableStyle).AppendLine() [ref] $null = $stylesBuilder.AppendFormat(' table.{0} th {{{1}{2} }}', $tableStyleId, $htmlHeaderStyle, $htmlTableStyle).AppendLine() [ref] $null = $stylesBuilder.AppendFormat(' table.{0} td {{{1} }}', $tableStyleId, $htmlTableStyle).AppendLine() [ref] $null = $stylesBuilder.AppendFormat(' table.{0} tr:nth-child(odd) {{{1}{2} }}', $tableStyleId, $htmlRowStyle, $htmlTableStyle).AppendLine() [ref] $null = $stylesBuilder.AppendFormat(' table.{0} tr:nth-child(even) {{{1}{2} }}', $tableStyleId, $htmlAlternateRowStyle, $htmlTableStyle).AppendLine() } [ref] $null = $stylesBuilder.AppendLine('</style>') return $stylesBuilder.ToString().TrimEnd() } } function Out-HtmlTable { <# .SYNOPSIS Output formatted Html <table> from PScribo.Table object. .NOTES One table is output per table row with the -List parameter. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Management.Automation.PSObject] $Table ) process { [System.Text.StringBuilder] $tableBuilder = New-Object -TypeName 'System.Text.StringBuilder' $formattedTable = Get-HtmlTable -Table $Table [ref] $null = $tableBuilder.Append($formattedTable) return $tableBuilder.ToString() } } function Out-HtmlTOC { <# .SYNOPSIS Generates Html table of contents. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Management.Automation.PSObject] $TOC ) process { $tocBuilder = New-Object -TypeName 'System.Text.StringBuilder' [ref] $null = $tocBuilder.AppendFormat('<h1 class="{0}">{1}</h1>', $TOC.ClassId, $TOC.Name) #[ref] $null = $tocBuilder.AppendLine('<table style="width: 100%;">') [ref] $null = $tocBuilder.AppendLine('<table>') foreach ($tocEntry in $Document.TOC) { $sectionNumberIndent = ' ' * $tocEntry.Level if ($Document.Options['EnableSectionNumbering']) { [ref] $null = $tocBuilder.AppendFormat('<tr><td>{0}</td><td>{1}<a href="#{2}" style="text-decoration: none;">{3}</a></td></tr>', $tocEntry.Number, $sectionNumberIndent, $tocEntry.Id, $tocEntry.Name).AppendLine() } else { [ref] $null = $tocBuilder.AppendFormat('<tr><td>{0}<a href="#{1}" style="text-decoration: none;">{2}</a></td></tr>', $sectionNumberIndent, $tocEntry.Id, $tocEntry.Name).AppendLine() } } [ref] $null = $tocBuilder.AppendLine('</table>') return $tocBuilder.ToString() } } # SIG # Begin signature block # MIIuugYJKoZIhvcNAQcCoIIuqzCCLqcCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCC/l7VnqsKqfVs/ # nG/XTx9AGvIF+ZNYtfxU+LN3XH2h+qCCE6QwggWQMIIDeKADAgECAhAFmxtXno4h # MuI5B72nd3VcMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0z # ODAxMTUxMjAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 # IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB # AL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/z # G6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZ # anMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7s # Wxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL # 2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfb # BHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3 # JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3c # AORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqx # YxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0 # viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aL # T8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1Ud # EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzf # Lmc/57qYrhwPTzANBgkqhkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNk # aA9Wz3eucPn9mkqZucl4XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjS # PMFDQK4dUPVS/JA7u5iZaWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK # 7VB6fWIhCoDIc2bRoAVgX+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eB # cg3AFDLvMFkuruBx8lbkapdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp # 5aPNoiBB19GcZNnqJqGLFNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msg # dDDS4Dk0EIUhFQEI6FUy3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vri # RbgjU2wGb2dVf0a1TD9uKFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ7 # 9ARj6e/CVABRoIoqyc54zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5 # nLGbsQAe79APT0JsyQq87kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3 # i0objwG2J5VT6LaJbVu8aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0H # EEcRrYc9B9F1vM/zZn4wggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0G # CSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 # IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTla # MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE # AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz # ODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C # 0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce # 2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0da # E6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6T # SXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoA # FdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7Oh # D26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM # 1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z # 8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05 # huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNY # mtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP # /2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0T # AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYD # VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG # A1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV # HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU # cnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATAN # BgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95Ry # sQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HL # IvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5Btf # Q/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnh # OE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIh # dXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV # 9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/j # wVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYH # Ki8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmC # XBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l # /aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZW # eE4wggdYMIIFQKADAgECAhAIfHT3o/FeY5ksO94AUhTmMA0GCSqGSIb3DQEBCwUA # MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE # AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz # ODQgMjAyMSBDQTEwHhcNMjMxMDE4MDAwMDAwWhcNMjYxMjE2MjM1OTU5WjBgMQsw # CQYDVQQGEwJHQjEPMA0GA1UEBxMGTG9uZG9uMR8wHQYDVQQKExZWaXJ0dWFsIEVu # Z2luZSBMaW1pdGVkMR8wHQYDVQQDExZWaXJ0dWFsIEVuZ2luZSBMaW1pdGVkMIIC # IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtyhrsCMi6pgLcX5sWY7I09dO # WKweRHfDwW5AN6ffgLCYO9dqWWxvqu95FqnNVRyt1VNzEl3TevKVhRE0GGdirei3 # VqnFFjLDwD2jHhGY8qoSYyfffj/WYq2DkvNI62C3gUwSeP3FeqKRalc2c3V2v4jh # yEYhrgG3nfnWQ/Oq2xzuiCqHy1E4U+IKKDtrXls4JX2Z4J/uAHZIAyKfrcTRQOhZ # R4ZS1cQkeSBU9Urx578rOmxL0si0GAoaYQC49W7OimRelbahxZw/R+f5ch+C1ycU # CpeXLg+bFhpa0+EXnkGidlILZbJiZJn7qvMQTZgipQKZ8nhX3rtJLqTeodPWzcCk # tXQUy0q5fxhR3e6Ls7XQesq/G2yMcCMTCd6eltze0OgabvL6Xkhir5lATHaJtnmw # FlcKzRr1YXK1k1D84hWfKSAdUg8T1O72ztimbqFLg6WoC8M2qqsHcm2DOc9hM3i2 # CWRpegikitRvZ9i1wkA9arGh7+a7UD+nLh2hnGmO06wONLNqABOEn4JOVnNrQ1gY # eDeH9FDx7IYuAvMsfXG9Bo+I97TR2VfwDAx+ccR+UQLON3aQyFZ3BefYnvUu0gUR # ikEAnAS4Jnc3BHizgb0voz0iWRDjFoTTmCmrInCVDGc+5KMy0xyoUwdQvYvRGAWB # 61OCWnXBXbAEPniTZ80CAwEAAaOCAgMwggH/MB8GA1UdIwQYMBaAFGg34Ou2O/hf # EYb7/mF7CIhl9E5CMB0GA1UdDgQWBBRuAv58K4EDYLmb7WNcxt5+r4NfnzA+BgNV # HSAENzA1MDMGBmeBDAEEATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRpZ2lj # ZXJ0LmNvbS9DUFMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMD # MIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEu # Y3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz # dGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNybDCBlAYIKwYB # BQUHAQEEgYcwgYQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNv # bTBcBggrBgEFBQcwAoZQaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lD # ZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcnQw # CQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAgEAnXMg6efkBrwLIvd1Xmuh0dam # 9FhUtDEj+P5SIqdP/U4veOv66NEQhBHLbW2Dvrdm6ec0HMj9b4e8pt4ylKFzHIPj # fpuRffHVR9JQSx8qpryN6pP49DfCkAYeZGqjY3pGRzd/xQ0cfwcuYbUF+vwVk7tj # q8c93VHCM0rb5M4N2hD1Ze1pvZxtaf9QnFKFzgXZjr02K6bswQc2+n5jFCp7zV1f # KTstyb68rhSJBWKK1tMeFk6a6HXr5buTD3skluC0oyPmD7yAd97r2owjDMEveEso # kADP/z7XQk7wqbwbpi4W6Uju2qHK/9UUsVRF5KTVEAIzVw2V1Aq/Jh3JuSV7b7C1 # 4CghNekltBb+w7YVp8/IFcj7axqnpNQ/+f7RVc3A5hyjV+MkoSwn8Sg7a7hn6SzX # jec/TfRVvWCmG94MQHko+6206uIXrZnmQ6UQYFyOHRlyKDEozzkZhIcVlsZloUjL # 3FZ5V/l8TIIzbc3bkEnu4iByksNvRxI6c5264OLauYlWv50ZUPwXmZ9gX8bs3BqZ # avbGUrOW2PIjtWhtvs4zHhMBCoU1Z0OMvXcF9rUDqefmVCZK46xz3DGKVkDQnxY6 # UWQ3GL60/lEzju4YS99LJVQks2UGmP6LAzlEZ1dnGqi1aQ51OidCYEs39B75PsvO # By2iAR8pBVi/byWBypExghpsMIIaaAIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYD # VQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBH # NCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEzODQgMjAyMSBDQTECEAh8dPej8V5j # mSw73gBSFOYwDQYJYIZIAWUDBAIBBQCggYQwGAYKKwYBBAGCNwIBDDEKMAigAoAA # oQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4w # DAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgOuok+ylV9Gz6Zp3yp9eyX/F8 # 1OLa+I7w5j+eKAYS3pAwDQYJKoZIhvcNAQEBBQAEggIAKwjLYQ2BgU7uTbv9OGZP # mQqc/SyXNXCKHNwOB4cTPLmMgQTqdSKXfYOHczBFneiE9aBKYIQ2YsyDMrI1nNeq # 3jwuT2LurKBa4i4To+eiE+MWTHWLgQGhhjdDjvNfsHOmPz1CkpXGxi8GpZznb1k9 # jcFdsceB+wcbcpUw8qi+MDUJaol9cdPC5ycTJGmqQs01AAr45mxl6h0MF3Ecg5Uk # uPpO7l8Exo7ZzZ3Jt5hL7Lh80vRDNq09a8ZtO40sR2+dgumutQnB9mCxwC22cJlT # Vuovl89pAHwNoHG+QEZAQ5JyiAoeaRbxXxr6Lt+78h0SJxOuQaJP527/ioDBuD8+ # PJ4J1HeZXnTFztjHMuyidzlESeee938K/LUkkyzDKtXx9EO/x6nakyH8lSBTx0jl # iPMgkciFztVehDGeFjVxhzwTFfC7IqawzyAcwM6U662mO9ZnaRiOM3Y8+OJg975N # wRiw14a5X2SBLGAcVpOYcPqoLkX2H5UOWxANIcXfZh/a1/TfSv7qtfCzWGO13JfC # Mt1Xe+F9UQS+NO7Iyy82I2lYCUbpW0+QBmfgvvcMhyLNmB+eFznG2n3QUWkBDT8a # UypFAcZkMHREiUvz/6szUoF7FZDINpCbXfH0e53O6DocRYfdCc/fx2YOOi8JQHSz # xpWjm/cf8SaPY8ZDlLNfS0Chghc5MIIXNQYKKwYBBAGCNwMDATGCFyUwghchBgkq # hkiG9w0BBwKgghcSMIIXDgIBAzEPMA0GCWCGSAFlAwQCAQUAMHcGCyqGSIb3DQEJ # EAEEoGgEZjBkAgEBBglghkgBhv1sBwEwMTANBglghkgBZQMEAgEFAAQguxTVcL7F # 3wcnL33QoSMm2oqyMSCpqyTSfWABdbgRpoACEFO1fzRBuc2j3XJK1MdsHk0YDzIw # MjUwMzA3MDg1NTAxWqCCEwMwgga8MIIEpKADAgECAhALrma8Wrp/lYfG+ekE4zME # MA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2Vy # dCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNI # QTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjQwOTI2MDAwMDAwWhcNMzUxMTI1MjM1 # OTU5WjBCMQswCQYDVQQGEwJVUzERMA8GA1UEChMIRGlnaUNlcnQxIDAeBgNVBAMT # F0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDI0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A # MIICCgKCAgEAvmpzn/aVIauWMLpbbeZZo7Xo/ZEfGMSIO2qZ46XB/QowIEMSvgjE # dEZ3v4vrrTHleW1JWGErrjOL0J4L0HqVR1czSzvUQ5xF7z4IQmn7dHY7yijvoQ7u # jm0u6yXF2v1CrzZopykD07/9fpAT4BxpT9vJoJqAsP8YuhRvflJ9YeHjes4fduks # THulntq9WelRWY++TFPxzZrbILRYynyEy7rS1lHQKFpXvo2GePfsMRhNf1F41nyE # g5h7iOXv+vjX0K8RhUisfqw3TTLHj1uhS66YX2LZPxS4oaf33rp9HlfqSBePejlY # eEdU740GKQM7SaVSH3TbBL8R6HwX9QVpGnXPlKdE4fBIn5BBFnV+KwPxRNUNK6lY # k2y1WSKour4hJN0SMkoaNV8hyyADiX1xuTxKaXN12HgR+8WulU2d6zhzXomJ2Ple # I9V2yfmfXSPGYanGgxzqI+ShoOGLomMd3mJt92nm7Mheng/TBeSA2z4I78JpwGpT # RHiT7yHqBiV2ngUIyCtd0pZ8zg3S7bk4QC4RrcnKJ3FbjyPAGogmoiZ33c1HG93V # p6lJ415ERcC7bFQMRbxqrMVANiav1k425zYyFMyLNyE1QulQSgDpW9rtvVcIH7Wv # G9sqYup9j8z9J1XqbBZPJ5XLln8mS8wWmdDLnBHXgYly/p1DhoQo5fkCAwEAAaOC # AYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQM # MAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATAf # BgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57IbzAdBgNVHQ4EFgQUn1csA3cO # KBWQZqVjXu5Pkh92oFswWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2NybDMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNIQTI1NlRpbWVTdGFt # cGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAwJAYIKwYBBQUHMAGGGGh0dHA6 # Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcwAoZMaHR0cDovL2NhY2VydHMu # ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNIQTI1NlRpbWVT # dGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAPa0eH3aZW+M4hBJH2UOR # 9hHbm04IHdEoT8/T3HuBSyZeq3jSi5GXeWP7xCKhVireKCnCs+8GZl2uVYFvQe+p # PTScVJeCZSsMo1JCoZN2mMew/L4tpqVNbSpWO9QGFwfMEy60HofN6V51sMLMXNTL # fhVqs+e8haupWiArSozyAmGH/6oMQAh078qRh6wvJNU6gnh5OruCP1QUAvVSu4kq # VOcJVozZR5RRb/zPd++PGE3qF1P3xWvYViUJLsxtvge/mzA75oBfFZSbdakHJe2B # VDGIGVNVjOp8sNt70+kEoMF+T6tptMUNlehSR7vM+C13v9+9ZOUKzfRUAYSyyEmY # tsnpltD/GWX8eM70ls1V6QG/ZOB6b6Yum1HvIiulqJ1Elesj5TMHq8CWT/xrW7tw # ipXTJ5/i5pkU5E16RSBAdOp12aw8IQhhA/vEbFkEiF2abhuFixUDobZaA0VhqAsM # HOmaT3XThZDNi5U2zHKhUs5uHHdG6BoQau75KiNbh0c+hatSF+02kULkftARjsyE # pHKsF7u5zKRbt5oK5YGwFvgc4pEVUNytmB3BpIiowOIIuDgP5M9WArHYSAR16gc0 # dP2XdkMEP5eBsX7bf/MGN4K3HP50v/01ZHo/Z5lGLvNwQ7XHBx1yomzLP8lx4Q1z # ZKDyHcp4VQJLu2kWTsKsOqQwggauMIIElqADAgECAhAHNje3JFR82Ees/ShmKl5b # MA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD # ZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMjAzMjMwMDAwMDBaFw0zNzAzMjIyMzU5 # NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkG # A1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3Rh # bXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGhjUGSbPB # PXJJUVXHJQPE8pE3qZdRodbSg9GeTKJtoLDMg/la9hGhRBVCX6SI82j6ffOciQt/ # nR+eDzMfUBMLJnOWbfhXqAJ9/UO0hNoR8XOxs+4rgISKIhjf69o9xBd/qxkrPkLc # Z47qUT3w1lbU5ygt69OxtXXnHwZljZQp09nsad/ZkIdGAHvbREGJ3HxqV3rwN3mf # XazL6IRktFLydkf3YYMZ3V+0VAshaG43IbtArF+y3kp9zvU5EmfvDqVjbOSmxR3N # Ng1c1eYbqMFkdECnwHLFuk4fsbVYTXn+149zk6wsOeKlSNbwsDETqVcplicu9Yem # j052FVUmcJgmf6AaRyBD40NjgHt1biclkJg6OBGz9vae5jtb7IHeIhTZgirHkr+g # 3uM+onP65x9abJTyUpURK1h0QCirc0PO30qhHGs4xSnzyqqWc0Jon7ZGs506o9UD # 4L/wojzKQtwYSH8UNM/STKvvmz3+DrhkKvp1KCRB7UK/BZxmSVJQ9FHzNklNiyDS # LFc1eSuo80VgvCONWPfcYd6T/jnA+bIwpUzX6ZhKWD7TA4j+s4/TXkt2ElGTyYwM # O1uKIqjBJgj5FBASA31fI7tk42PgpuE+9sJ0sj8eCXbsq11GdeJgo1gJASgADoRU # 7s7pXcheMBK9Rp6103a50g5rmQzSM7TNsQIDAQABo4IBXTCCAVkwEgYDVR0TAQH/ # BAgwBgEB/wIBADAdBgNVHQ4EFgQUuhbZbU2FL3MpdpovdYxqII+eyG8wHwYDVR0j # BBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1Ud # JQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0 # cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8E # PDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz # dGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEw # DQYJKoZIhvcNAQELBQADggIBAH1ZjsCTtm+YqUQiAX5m1tghQuGwGC4QTRPPMFPO # vxj7x1Bd4ksp+3CKDaopafxpwc8dB+k+YMjYC+VcW9dth/qEICU0MWfNthKWb8RQ # TGIdDAiCqBa9qVbPFXONASIlzpVpP0d3+3J0FNf/q0+KLHqrhc1DX+1gtqpPkWae # LJ7giqzl/Yy8ZCaHbJK9nXzQcAp876i8dU+6WvepELJd6f8oVInw1YpxdmXazPBy # oyP6wCeCRK6ZJxurJB4mwbfeKuv2nrF5mYGjVoarCkXJ38SNoOeY+/umnXKvxMfB # wWpx2cYTgAnEtp/Nh4cku0+jSbl3ZpHxcpzpSwJSpzd+k1OsOx0ISQ+UzTl63f8l # Y5knLD0/a6fxZsNBzU+2QJshIUDQtxMkzdwdeDrknq3lNHGS1yZr5Dhzq6YBT70/ # O3itTK37xJV77QpfMzmHQXh6OOmc4d0j/R0o08f56PGYX/sr2H7yRp11LB4nLCbb # bxV7HhmLNriT1ObyF5lZynDwN7+YAN8gFk8n+2BnFqFmut1VwDophrCYoCvtlUG3 # OtUVmDG0YgkPCr2B2RP+v6TR81fZvAT6gt4y3wSJ8ADNXcL50CN/AAvkdgIm2fBl # dkKmKYcJRyvmfxqkhQ/8mJb2VVQrH4D6wPIOK+XW+6kvRBVK5xMOHds3OBqhK/bt # 1nz8MIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0BAQwF # ADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL # ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElE # IFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQswCQYD # VQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGln # aWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIi # MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKn # JS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/W # BTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHi # LQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhm # V1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHE # tWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 # MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mX # aXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZ # xd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfh # vbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvl # EFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn1 # 5GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV # HQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SSy4Ix # LVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAkBggr # BgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdo # dHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290 # Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNv # bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRVHSAA # MA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyhhyzs # hV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO0Cre # +i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo8L8v # C6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++hUD38 # dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5xaiNr # Iv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMYIDdjCCA3ICAQEw # dzBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNV # BAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1w # aW5nIENBAhALrma8Wrp/lYfG+ekE4zMEMA0GCWCGSAFlAwQCAQUAoIHRMBoGCSqG # SIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjUwMzA3MDg1 # NTAxWjArBgsqhkiG9w0BCRACDDEcMBowGDAWBBTb04XuYtvSPnvk9nFIUIck1YZb # RTAvBgkqhkiG9w0BCQQxIgQgs0gbbOnDTje/YXVVJTk+7g9FW8rJIyCqIna3ADff # zbUwNwYLKoZIhvcNAQkQAi8xKDAmMCQwIgQgdnafqPJjLx9DCzojMK7WVnX+13Pb # BdZluQWTmEOPmtswDQYJKoZIhvcNAQEBBQAEggIAKTU58WZYycvxJi0GxHsVc/kA # bLCclNVJjifzeUDvZ9pxc8QwbEy81TAA5VJtIKYIzkdB82118uVBV/xTQ5VvHiBF # UtTeFLSip22zKjj4k2gMIqTtFqAjJJKXcx0q+FZAxC44h+cxOqRMW8FKw2BugrL1 # w258pum4TBDs2QW14Xhsliee6PuqcwA2gwrL4halodkqBgXLlkv/9AbeRovYkbhq # kxz3whLI0LdUlSGbIVF7UmqgTpDkgnn4R9W+ky20luXk+z1WkjQFjpemjmoOIQTi # BHYLNw1OEIGm7ptift5zFGsa5kozJ8jTuDfOj9yu5xeWEGYIaPmPBQLqMpL9SZOG # ydfyNoMrrbIAFnm+gEzup4fUvtwsdRIsXsEFYQGchWeVZttYJB5LawSes46Rmhya # hh1StX5zZ2mIFD89/x13T0bbRSwNtCAee2UiF59OlQdLq3iZXRyxfB7/EBocep+J # MopGhbNmA4bBEbO8WaMp2p0hYEfmDzFJwVonCtRdAARBpScoo5yswgq+tlnXqd7m # TlGdg3n1hhLnolNx7GAjVLbhI6XUD+//1zXu10/OLfLlf8NlVeiWPs6eh3VV/+Dz # IkcqG1muUjHVK7zVGXxXZGx1w6tdRR9//HU36cml6rQ+X8i1hKE26VnXGdu4IKy+ # rIsa/pWpraw8hMSmyVQ= # SIG # End signature block |