Skip to content

Commit

Permalink
Fix character escaping issues during config generation
Browse files Browse the repository at this point in the history
Many years ago, microsoft#24 attempted to properly escape special characters
in a string by creating its own `Get-EscapedJsonValue` function, but
that only escaped `\`, `\t`, `\r`, `\n`.  That doesn't cover all the
possible characters needing to be encoded though.

At the time, this clearly seemed like a _good_ idea, but looking back
at this code with more experience, it's not clear to me why I didn't
just use `ConvertTo-Json` directly. Doing that now.

One additional update that needed to be done however was to "escape"
in `tag` and `notesForCertification` with '//' with '\\'.  This isn't
_completely_ correct, but not doing so meant that anything after that
would be improperly flagged as a comment by `Remove-Comment` and then
removed.
  • Loading branch information
HowardWolosky committed Aug 14, 2020
1 parent ae50bce commit ca442e3
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 57 deletions.
51 changes: 0 additions & 51 deletions StoreBroker/Helpers.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -321,57 +321,6 @@ function Get-SHA512Hash
return [System.BitConverter]::ToString($sha512.ComputeHash($utf8.GetBytes($PlainText))) -replace '-', ''
}

function Get-EscapedJsonValue
{
<#
.SYNOPSIS
Escapes special characters within a string for use within a JSON value.
.DESCRIPTION
Escapes special characters within a string for use within a JSON value.
The Git repo for this module can be found here: http://aka.ms/StoreBroker
.PARAMETER Value
The string that needs to be escaped
.EXAMPLE
Get-EscapedJsonValue -Value 'This is my "quote". Look here: c:\windows\'
Returns back the string 'This is my \"quote\". Look here: c:\\windows\\'
.OUTPUTS
System.String - A string with special characters escaped for use within JSON.
.NOTES
Normalizes newlines and carriage returns to always be \r\n.
#>
[CmdletBinding()]
param(
[Parameter(
Mandatory,
ValueFromPipeline)]
[AllowNull()]
[AllowEmptyString()]
[string] $Value
)

# The syntax of -replace is a bit confusing, so it's worth a note here.
# The first parameter is a regular expression match pattern. The second parameter is a replacement string.
# So, when we try to do "-replace '\\', '\\", that's matching a single backslash (which has to be
# escaped within the match regular expression as a double-backslash), and replacing it with a
# string containing literally two backslashes.
# (And as a reminder, PowerShell's escape character is actually the backtick (`) and not backslash (\).)

# \, ", <tab>
$escaped = $Value -replace '\\', '\\' -replace '"', '\"' -replace '\t', '\t'

# Now normalize actual CR's and LF's with their control codes. We'll ensure all variations are uniformly formatted as \r\n
$escaped = $escaped -replace '\r\n', '\r\n' -replace '\r', '\r\n' -replace '\n', '\r\n'

return $escaped
}

function ConvertTo-Array
{
<#
Expand Down
12 changes: 6 additions & 6 deletions StoreBroker/PackageTool.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,16 @@ function Get-StoreBrokerConfigFileContentForIapId
$updated = $updated -replace '"lifetime": ".*",', "`"lifetime`": `"$($sub.lifetime)`","
$updated = $updated -replace '"contentType": ".*",', "`"contentType`": `"$($sub.contentType)`","

$tag = Get-EscapedJsonValue -Value $sub.tag
$updated = $updated -replace '"tag": ""', "`"tag`": `"$tag`""
$tag = ConvertTo-Json -InputObject ($sub.tag -replace '//', '\\') # Ensure // doesn't get stripped out as a comment later on.
$updated = $updated -replace '"tag": ""', "`"tag`": $tag"

$keywords = $sub.keywords | ConvertTo-Json -Depth $script:jsonConversionDepth
if ($null -eq $keywords) { $keywords = "[ ]" }
$updated = $updated -replace '(\s+)"keywords": \[.*(\r|\n)+\s*\]', "`$1`"keywords`": $keywords"

# NOTES FOR CERTIFICATION
$notesForCertification = Get-EscapedJsonValue -Value $sub.notesForCertification
$updated = $updated -replace '"notesForCertification": ""', "`"notesForCertification`": `"$notesForCertification`""
$notesForCertification = ConvertTo-Json -InputObject ($sub.notesForCertification -replace '//', '\\') # Ensure // doesn't get stripped out as a comment later on.
$updated = $updated -replace '"notesForCertification": ""', "`"notesForCertification`": $notesForCertification"

return $updated
}
Expand Down Expand Up @@ -361,8 +361,8 @@ function Get-StoreBrokerConfigFileContentForAppId
}

# NOTES FOR CERTIFICATION
$notesForCertification = Get-EscapedJsonValue -Value $sub.notesForCertification
$updated = $updated -replace '"notesForCertification": ""', "`"notesForCertification`": `"$notesForCertification`""
$notesForCertification = ConvertTo-Json -InputObject ($sub.notesForCertification -replace '//', '\\') # Ensure // doesn't get stripped out as a comment later on.
$updated = $updated -replace '"notesForCertification": ""', "`"notesForCertification`": $notesForCertification"

return $updated
}
Expand Down

0 comments on commit ca442e3

Please sign in to comment.