Private/ConvertTo-HDTHtmlText.ps1
|
function ConvertTo-HDTHtmlText { <# .SYNOPSIS Escapes one value for inclusion in the HTML report's text or an attribute. .DESCRIPTION Everything ConvertTo-HDTReport renders goes through here, because everything it renders is untrusted in the only sense that matters: it came from a machine being deployed. A step message routinely carries a command line with an ampersand, an unattend fragment with angle brackets, or a quoted argument with both kinds of quote - and a report that renders those raw either swallows the line the technician opened it for, or renders a machine-supplied string as markup. THE AMPERSAND GOES FIRST, and that ordering is the whole function. Escaping & after < would turn the < just produced into &lt;, which is the classic double-escape bug and reads as literal '<' on the page. Both quotes are escaped as well as the three structural characters, so one function serves text nodes and attribute values alike rather than leaving the caller to choose - a caller that chooses wrongly once is an injected attribute. The function is pure. It has no clock, no filesystem and no state, and $null renders as the empty string rather than 'null', because a report cell for a step that has no exit code should be empty. .PARAMETER Value Anything. A non-string is rendered with ToString first, so an int exit code and a [datetime] both work without the caller casting. .OUTPUTS System.String .EXAMPLE ConvertTo-HDTHtmlText -Value 'cmd.exe /c echo "a<b" & echo done' cmd.exe /c echo "a<b" & echo done #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $true, Position = 0)] [AllowNull()] [AllowEmptyString()] [object] $Value ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' if ($null -eq $Value) { return '' } $text = [string] $Value # & FIRST. See the description. $text = $text.Replace('&', '&') $text = $text.Replace('<', '<') $text = $text.Replace('>', '>') $text = $text.Replace('"', '"') $text = $text.Replace("'", ''') return $text } |