| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // Copyright (c) 2015-2021 MinIO, Inc.
 | 
					
						
							| 
									
										
										
										
											2021-01-19 17:39:04 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							| 
									
										
										
										
											2021-01-19 17:39:04 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							| 
									
										
										
										
											2021-01-19 17:39:04 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2021-01-19 17:39:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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 <script> tags, without any additional escaping.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // All values are true except for the ASCII control characters (0-31), the
 | 
					
						
							|  |  |  | // double quote ("), the backslash character ("\"), HTML opening and closing
 | 
					
						
							|  |  |  | // tags ("<" and ">"), and the ampersand ("&").
 | 
					
						
							|  |  |  | var htmlSafeSet = [utf8.RuneSelf]bool{ | 
					
						
							|  |  |  | 	' ':      true, | 
					
						
							|  |  |  | 	'!':      true, | 
					
						
							|  |  |  | 	'"':      false, | 
					
						
							|  |  |  | 	'#':      true, | 
					
						
							|  |  |  | 	'$':      true, | 
					
						
							|  |  |  | 	'%':      true, | 
					
						
							|  |  |  | 	'&':      false, | 
					
						
							|  |  |  | 	'\'':     true, | 
					
						
							|  |  |  | 	'(':      true, | 
					
						
							|  |  |  | 	')':      true, | 
					
						
							|  |  |  | 	'*':      true, | 
					
						
							|  |  |  | 	'+':      true, | 
					
						
							|  |  |  | 	',':      true, | 
					
						
							|  |  |  | 	'-':      true, | 
					
						
							|  |  |  | 	'.':      true, | 
					
						
							|  |  |  | 	'/':      true, | 
					
						
							|  |  |  | 	'0':      true, | 
					
						
							|  |  |  | 	'1':      true, | 
					
						
							|  |  |  | 	'2':      true, | 
					
						
							|  |  |  | 	'3':      true, | 
					
						
							|  |  |  | 	'4':      true, | 
					
						
							|  |  |  | 	'5':      true, | 
					
						
							|  |  |  | 	'6':      true, | 
					
						
							|  |  |  | 	'7':      true, | 
					
						
							|  |  |  | 	'8':      true, | 
					
						
							|  |  |  | 	'9':      true, | 
					
						
							|  |  |  | 	':':      true, | 
					
						
							|  |  |  | 	';':      true, | 
					
						
							|  |  |  | 	'<':      false, | 
					
						
							|  |  |  | 	'=':      true, | 
					
						
							|  |  |  | 	'>':      false, | 
					
						
							|  |  |  | 	'?':      true, | 
					
						
							|  |  |  | 	'@':      true, | 
					
						
							|  |  |  | 	'A':      true, | 
					
						
							|  |  |  | 	'B':      true, | 
					
						
							|  |  |  | 	'C':      true, | 
					
						
							|  |  |  | 	'D':      true, | 
					
						
							|  |  |  | 	'E':      true, | 
					
						
							|  |  |  | 	'F':      true, | 
					
						
							|  |  |  | 	'G':      true, | 
					
						
							|  |  |  | 	'H':      true, | 
					
						
							|  |  |  | 	'I':      true, | 
					
						
							|  |  |  | 	'J':      true, | 
					
						
							|  |  |  | 	'K':      true, | 
					
						
							|  |  |  | 	'L':      true, | 
					
						
							|  |  |  | 	'M':      true, | 
					
						
							|  |  |  | 	'N':      true, | 
					
						
							|  |  |  | 	'O':      true, | 
					
						
							|  |  |  | 	'P':      true, | 
					
						
							|  |  |  | 	'Q':      true, | 
					
						
							|  |  |  | 	'R':      true, | 
					
						
							|  |  |  | 	'S':      true, | 
					
						
							|  |  |  | 	'T':      true, | 
					
						
							|  |  |  | 	'U':      true, | 
					
						
							|  |  |  | 	'V':      true, | 
					
						
							|  |  |  | 	'W':      true, | 
					
						
							|  |  |  | 	'X':      true, | 
					
						
							|  |  |  | 	'Y':      true, | 
					
						
							|  |  |  | 	'Z':      true, | 
					
						
							|  |  |  | 	'[':      true, | 
					
						
							|  |  |  | 	'\\':     false, | 
					
						
							|  |  |  | 	']':      true, | 
					
						
							|  |  |  | 	'^':      true, | 
					
						
							|  |  |  | 	'_':      true, | 
					
						
							|  |  |  | 	'`':      true, | 
					
						
							|  |  |  | 	'a':      true, | 
					
						
							|  |  |  | 	'b':      true, | 
					
						
							|  |  |  | 	'c':      true, | 
					
						
							|  |  |  | 	'd':      true, | 
					
						
							|  |  |  | 	'e':      true, | 
					
						
							|  |  |  | 	'f':      true, | 
					
						
							|  |  |  | 	'g':      true, | 
					
						
							|  |  |  | 	'h':      true, | 
					
						
							|  |  |  | 	'i':      true, | 
					
						
							|  |  |  | 	'j':      true, | 
					
						
							|  |  |  | 	'k':      true, | 
					
						
							|  |  |  | 	'l':      true, | 
					
						
							|  |  |  | 	'm':      true, | 
					
						
							|  |  |  | 	'n':      true, | 
					
						
							|  |  |  | 	'o':      true, | 
					
						
							|  |  |  | 	'p':      true, | 
					
						
							|  |  |  | 	'q':      true, | 
					
						
							|  |  |  | 	'r':      true, | 
					
						
							|  |  |  | 	's':      true, | 
					
						
							|  |  |  | 	't':      true, | 
					
						
							|  |  |  | 	'u':      true, | 
					
						
							|  |  |  | 	'v':      true, | 
					
						
							|  |  |  | 	'w':      true, | 
					
						
							|  |  |  | 	'x':      true, | 
					
						
							|  |  |  | 	'y':      true, | 
					
						
							|  |  |  | 	'z':      true, | 
					
						
							|  |  |  | 	'{':      true, | 
					
						
							|  |  |  | 	'|':      true, | 
					
						
							|  |  |  | 	'}':      true, | 
					
						
							|  |  |  | 	'~':      true, | 
					
						
							|  |  |  | 	'\u007f': true, | 
					
						
							|  |  |  | } |