diff --git a/cmd/crypto/json.go b/cmd/crypto/json.go new file mode 100644 index 000000000..23878148d --- /dev/null +++ b/cmd/crypto/json.go @@ -0,0 +1,200 @@ +// MinIO Cloud Storage, (C) 2020 MinIO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package crypto + +import ( + "bytes" + "unicode/utf8" +) + +// Adapted from Go stdlib. + +var hexTable = "0123456789abcdef" + +// EscapeStringJSON will escape a string for JSON and write it to dst. +func EscapeStringJSON(dst *bytes.Buffer, s string) { + start := 0 + for i := 0; i < len(s); { + if b := s[i]; b < utf8.RuneSelf { + if htmlSafeSet[b] { + i++ + continue + } + if start < i { + dst.WriteString(s[start:i]) + } + dst.WriteByte('\\') + switch b { + case '\\', '"': + dst.WriteByte(b) + case '\n': + dst.WriteByte('n') + case '\r': + dst.WriteByte('r') + case '\t': + dst.WriteByte('t') + default: + // This encodes bytes < 0x20 except for \t, \n and \r. + // If escapeHTML is set, it also escapes <, >, and & + // because they can lead to security holes when + // user-controlled strings are rendered into JSON + // and served to some browsers. + dst.WriteString(`u00`) + dst.WriteByte(hexTable[b>>4]) + dst.WriteByte(hexTable[b&0xF]) + } + i++ + start = i + continue + } + c, size := utf8.DecodeRuneInString(s[i:]) + if c == utf8.RuneError && size == 1 { + if start < i { + dst.WriteString(s[start:i]) + } + dst.WriteString(`\ufffd`) + i += size + start = i + continue + } + // U+2028 is LINE SEPARATOR. + // U+2029 is PARAGRAPH SEPARATOR. + // They are both technically valid characters in JSON strings, + // but don't work in JSONP, which has to be evaluated as JavaScript, + // and can lead to security holes there. It is valid JSON to + // escape them, so we do so unconditionally. + // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. + if c == '\u2028' || c == '\u2029' { + if start < i { + dst.WriteString(s[start:i]) + } + dst.WriteString(`\u202`) + dst.WriteByte(hexTable[c&0xF]) + i += size + start = i + continue + } + i += size + } + if start < len(s) { + dst.WriteString(s[start:]) + } +} + +// htmlSafeSet holds the value true if the ASCII character with the given +// array position can be safely represented inside a JSON string, embedded +// inside of HTML