util.go (3659B)
1 package html 2 3 var ( 4 singleQuoteEntityBytes = []byte("'") 5 doubleQuoteEntityBytes = []byte(""") 6 ) 7 8 // EscapeAttrVal returns the escaped attribute value bytes with quotes. Either single or double quotes are used, whichever is shorter. If there are no quotes present in the value and the value is in HTML (not XML), it will return the value without quotes. 9 func EscapeAttrVal(buf *[]byte, b []byte, origQuote byte, mustQuote, isXML bool) []byte { 10 singles := 0 11 doubles := 0 12 unquoted := true 13 for _, c := range b { 14 if charTable[c] { 15 unquoted = false 16 if c == '"' { 17 doubles++ 18 } else if c == '\'' { 19 singles++ 20 } 21 } 22 } 23 if unquoted && (!mustQuote || origQuote == 0) && !isXML { 24 return b 25 } else if singles == 0 && origQuote == '\'' && !isXML || doubles == 0 && origQuote == '"' { 26 if len(b)+2 > cap(*buf) { 27 *buf = make([]byte, 0, len(b)+2) 28 } 29 t := (*buf)[:len(b)+2] 30 t[0] = origQuote 31 copy(t[1:], b) 32 t[1+len(b)] = origQuote 33 return t 34 } 35 36 n := len(b) + 2 37 var quote byte 38 var escapedQuote []byte 39 if singles >= doubles || isXML { 40 n += doubles * 4 41 quote = '"' 42 escapedQuote = doubleQuoteEntityBytes 43 if singles == doubles && origQuote == '\'' && !isXML { 44 quote = '\'' 45 escapedQuote = singleQuoteEntityBytes 46 } 47 } else { 48 n += singles * 4 49 quote = '\'' 50 escapedQuote = singleQuoteEntityBytes 51 } 52 if n > cap(*buf) { 53 *buf = make([]byte, 0, n) // maximum size, not actual size 54 } 55 t := (*buf)[:n] // maximum size, not actual size 56 t[0] = quote 57 j := 1 58 start := 0 59 for i, c := range b { 60 if c == quote { 61 j += copy(t[j:], b[start:i]) 62 j += copy(t[j:], escapedQuote) 63 start = i + 1 64 } 65 } 66 j += copy(t[j:], b[start:]) 67 t[j] = quote 68 return t[:j+1] 69 } 70 71 var charTable = [256]bool{ 72 // ASCII 73 false, false, false, false, false, false, false, false, 74 false, true, true, false, true, true, false, false, // tab, line feed, form feed, carriage return 75 false, false, false, false, false, false, false, false, 76 false, false, false, false, false, false, false, false, 77 78 true, false, true, false, false, false, false, true, // space, "), ' 79 false, false, false, false, false, false, false, false, 80 false, false, false, false, false, false, false, false, 81 false, false, false, false, true, true, true, false, // <, =, > 82 83 false, false, false, false, false, false, false, false, 84 false, false, false, false, false, false, false, false, 85 false, false, false, false, false, false, false, false, 86 false, false, false, false, false, false, false, false, 87 88 true, false, false, false, false, false, false, false, // ` 89 false, false, false, false, false, false, false, false, 90 false, false, false, false, false, false, false, false, 91 false, false, false, false, false, false, false, false, 92 93 // non-ASCII 94 false, false, false, false, false, false, false, false, 95 false, false, false, false, false, false, false, false, 96 false, false, false, false, false, false, false, false, 97 false, false, false, false, false, false, false, false, 98 99 false, false, false, false, false, false, false, false, 100 false, false, false, false, false, false, false, false, 101 false, false, false, false, false, false, false, false, 102 false, false, false, false, false, false, false, false, 103 104 false, false, false, false, false, false, false, false, 105 false, false, false, false, false, false, false, false, 106 false, false, false, false, false, false, false, false, 107 false, false, false, false, false, false, false, false, 108 109 false, false, false, false, false, false, false, false, 110 false, false, false, false, false, false, false, false, 111 false, false, false, false, false, false, false, false, 112 false, false, false, false, false, false, false, false, 113 }