1// Copyright 2010 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package json implements encoding and decoding of JSON objects as defined in 6// RFC 4627. The mapping between JSON objects and Go values is described 7// in the documentation for the Marshal and Unmarshal functions. 8// 9// See "JSON and Go" for an introduction to this package: 10// http://golang.org/doc/articles/json_and_go.html 11 12package collatejson 13 14import "unicode/utf8" 15 16var hex = "0123456789abcdef" 17 18// Copied from golang src/pkg/encoding/json/encode.go 19// Modified to use []byte as input and use DecodeRune() instead of 20// DecodeRuneInString. 21func encodeString(s []byte, text []byte) ([]byte, error) { 22 text = append(text, '"') 23 start := 0 24 for i := 0; i < len(s); { 25 if b := s[i]; b < utf8.RuneSelf { 26 if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' { 27 i++ 28 continue 29 } 30 if start < i { 31 text = append(text, s[start:i]...) 32 } 33 switch b { 34 case '\\', '"': 35 text = append(text, '\\') 36 text = append(text, b) 37 case '\n': 38 text = append(text, '\\') 39 text = append(text, 'n') 40 case '\r': 41 text = append(text, '\\') 42 text = append(text, 'r') 43 default: 44 // This encodes bytes < 0x20 except for \n and \r, 45 // as well as <, > and &. The latter are escaped because they 46 // can lead to security holes when user-controlled strings 47 // are rendered into JSON and served to some browsers. 48 49 text = append(text, `\u00`...) 50 text = append(text, hex[b>>4]) 51 text = append(text, hex[b&0xF]) 52 } 53 i++ 54 start = i 55 continue 56 } 57 c, size := utf8.DecodeRune(s[i:]) 58 if c == utf8.RuneError && size == 1 { 59 if start < i { 60 text = append(text, s[start:i]...) 61 } 62 text = append(text, `\ufffd`...) 63 i += size 64 start = i 65 continue 66 } 67 // U+2028 is LINE SEPARATOR. 68 // U+2029 is PARAGRAPH SEPARATOR. 69 // They are both technically valid characters in JSON strings, 70 // but don't work in JSONP, which has to be evaluated as JavaScript, 71 // and can lead to security holes there. It is valid JSON to 72 // escape them, so we do so unconditionally. 73 // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. 74 if c == '\u2028' || c == '\u2029' { 75 if start < i { 76 text = append(text, s[start:i]...) 77 } 78 text = append(text, `\u202`...) 79 text = append(text, hex[c&0xF]) 80 i += size 81 start = i 82 continue 83 } 84 i += size 85 } 86 if start < len(s) { 87 text = append(text, s[start:]...) 88 } 89 text = append(text, '"') 90 return text, nil 91} 92