storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/crypto/json.go (about) 1 // MinIO Cloud Storage, (C) 2020 MinIO, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package crypto 16 17 import ( 18 "bytes" 19 "unicode/utf8" 20 ) 21 22 // Adapted from Go stdlib. 23 24 var hexTable = "0123456789abcdef" 25 26 // EscapeStringJSON will escape a string for JSON and write it to dst. 27 func EscapeStringJSON(dst *bytes.Buffer, s string) { 28 start := 0 29 for i := 0; i < len(s); { 30 if b := s[i]; b < utf8.RuneSelf { 31 if htmlSafeSet[b] { 32 i++ 33 continue 34 } 35 if start < i { 36 dst.WriteString(s[start:i]) 37 } 38 dst.WriteByte('\\') 39 switch b { 40 case '\\', '"': 41 dst.WriteByte(b) 42 case '\n': 43 dst.WriteByte('n') 44 case '\r': 45 dst.WriteByte('r') 46 case '\t': 47 dst.WriteByte('t') 48 default: 49 // This encodes bytes < 0x20 except for \t, \n and \r. 50 // If escapeHTML is set, it also escapes <, >, and & 51 // because they can lead to security holes when 52 // user-controlled strings are rendered into JSON 53 // and served to some browsers. 54 dst.WriteString(`u00`) 55 dst.WriteByte(hexTable[b>>4]) 56 dst.WriteByte(hexTable[b&0xF]) 57 } 58 i++ 59 start = i 60 continue 61 } 62 c, size := utf8.DecodeRuneInString(s[i:]) 63 if c == utf8.RuneError && size == 1 { 64 if start < i { 65 dst.WriteString(s[start:i]) 66 } 67 dst.WriteString(`\ufffd`) 68 i += size 69 start = i 70 continue 71 } 72 // U+2028 is LINE SEPARATOR. 73 // U+2029 is PARAGRAPH SEPARATOR. 74 // They are both technically valid characters in JSON strings, 75 // but don't work in JSONP, which has to be evaluated as JavaScript, 76 // and can lead to security holes there. It is valid JSON to 77 // escape them, so we do so unconditionally. 78 // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. 79 if c == '\u2028' || c == '\u2029' { 80 if start < i { 81 dst.WriteString(s[start:i]) 82 } 83 dst.WriteString(`\u202`) 84 dst.WriteByte(hexTable[c&0xF]) 85 i += size 86 start = i 87 continue 88 } 89 i += size 90 } 91 if start < len(s) { 92 dst.WriteString(s[start:]) 93 } 94 } 95 96 // htmlSafeSet holds the value true if the ASCII character with the given 97 // array position can be safely represented inside a JSON string, embedded 98 // inside of HTML <script> tags, without any additional escaping. 99 // 100 // All values are true except for the ASCII control characters (0-31), the 101 // double quote ("), the backslash character ("\"), HTML opening and closing 102 // tags ("<" and ">"), and the ampersand ("&"). 103 var htmlSafeSet = [utf8.RuneSelf]bool{ 104 ' ': true, 105 '!': true, 106 '"': false, 107 '#': true, 108 '$': true, 109 '%': true, 110 '&': false, 111 '\'': true, 112 '(': true, 113 ')': true, 114 '*': true, 115 '+': true, 116 ',': true, 117 '-': true, 118 '.': true, 119 '/': true, 120 '0': true, 121 '1': true, 122 '2': true, 123 '3': true, 124 '4': true, 125 '5': true, 126 '6': true, 127 '7': true, 128 '8': true, 129 '9': true, 130 ':': true, 131 ';': true, 132 '<': false, 133 '=': true, 134 '>': false, 135 '?': true, 136 '@': true, 137 'A': true, 138 'B': true, 139 'C': true, 140 'D': true, 141 'E': true, 142 'F': true, 143 'G': true, 144 'H': true, 145 'I': true, 146 'J': true, 147 'K': true, 148 'L': true, 149 'M': true, 150 'N': true, 151 'O': true, 152 'P': true, 153 'Q': true, 154 'R': true, 155 'S': true, 156 'T': true, 157 'U': true, 158 'V': true, 159 'W': true, 160 'X': true, 161 'Y': true, 162 'Z': true, 163 '[': true, 164 '\\': false, 165 ']': true, 166 '^': true, 167 '_': true, 168 '`': true, 169 'a': true, 170 'b': true, 171 'c': true, 172 'd': true, 173 'e': true, 174 'f': true, 175 'g': true, 176 'h': true, 177 'i': true, 178 'j': true, 179 'k': true, 180 'l': true, 181 'm': true, 182 'n': true, 183 'o': true, 184 'p': true, 185 'q': true, 186 'r': true, 187 's': true, 188 't': true, 189 'u': true, 190 'v': true, 191 'w': true, 192 'x': true, 193 'y': true, 194 'z': true, 195 '{': true, 196 '|': true, 197 '}': true, 198 '~': true, 199 '\u007f': true, 200 }