diff options
Diffstat (limited to 'src/encoding/json/indent.go')
| -rw-r--r-- | src/encoding/json/indent.go | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/src/encoding/json/indent.go b/src/encoding/json/indent.go index 375f71605a..99951208a0 100644 --- a/src/encoding/json/indent.go +++ b/src/encoding/json/indent.go @@ -11,6 +11,36 @@ func availableBuffer(b *bytes.Buffer) []byte { return b.Bytes()[b.Len():] } +// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029 +// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029 +// so that the JSON will be safe to embed inside HTML <script> tags. +// For historical reasons, web browsers don't honor standard HTML +// escaping within <script> tags, so an alternative JSON encoding must be used. +func HTMLEscape(dst *bytes.Buffer, src []byte) { + dst.Grow(len(src)) + dst.Write(appendHTMLEscape(availableBuffer(dst), src)) +} + +func appendHTMLEscape(dst, src []byte) []byte { + // The characters can only appear in string literals, + // so just scan the string one byte at a time. + start := 0 + for i, c := range src { + if c == '<' || c == '>' || c == '&' { + dst = append(dst, src[start:i]...) + dst = append(dst, '\\', 'u', '0', '0', hex[c>>4], hex[c&0xF]) + start = i + 1 + } + // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9). + if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 { + dst = append(dst, src[start:i]...) + dst = append(dst, '\\', 'u', '2', '0', '2', hex[src[i+2]&0xF]) + start = i + len("\u2029") + } + } + return append(dst, src[start:]...) +} + // Compact appends to dst the JSON-encoded src with // insignificant space characters elided. func Compact(dst *bytes.Buffer, src []byte) error { |
