util.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package html
  2. var (
  3. singleQuoteEntityBytes = []byte("'")
  4. doubleQuoteEntityBytes = []byte(""")
  5. )
  6. // 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.
  7. func EscapeAttrVal(buf *[]byte, b []byte, origQuote byte, mustQuote, isXML bool) []byte {
  8. singles := 0
  9. doubles := 0
  10. unquoted := true
  11. for _, c := range b {
  12. if charTable[c] {
  13. unquoted = false
  14. if c == '"' {
  15. doubles++
  16. } else if c == '\'' {
  17. singles++
  18. }
  19. }
  20. }
  21. if unquoted && (!mustQuote || origQuote == 0) && !isXML {
  22. return b
  23. } else if singles == 0 && origQuote == '\'' && !isXML || doubles == 0 && origQuote == '"' {
  24. if len(b)+2 > cap(*buf) {
  25. *buf = make([]byte, 0, len(b)+2)
  26. }
  27. t := (*buf)[:len(b)+2]
  28. t[0] = origQuote
  29. copy(t[1:], b)
  30. t[1+len(b)] = origQuote
  31. return t
  32. }
  33. n := len(b) + 2
  34. var quote byte
  35. var escapedQuote []byte
  36. if singles >= doubles || isXML {
  37. n += doubles * 4
  38. quote = '"'
  39. escapedQuote = doubleQuoteEntityBytes
  40. if singles == doubles && origQuote == '\'' && !isXML {
  41. quote = '\''
  42. escapedQuote = singleQuoteEntityBytes
  43. }
  44. } else {
  45. n += singles * 4
  46. quote = '\''
  47. escapedQuote = singleQuoteEntityBytes
  48. }
  49. if n > cap(*buf) {
  50. *buf = make([]byte, 0, n) // maximum size, not actual size
  51. }
  52. t := (*buf)[:n] // maximum size, not actual size
  53. t[0] = quote
  54. j := 1
  55. start := 0
  56. for i, c := range b {
  57. if c == quote {
  58. j += copy(t[j:], b[start:i])
  59. j += copy(t[j:], escapedQuote)
  60. start = i + 1
  61. }
  62. }
  63. j += copy(t[j:], b[start:])
  64. t[j] = quote
  65. return t[:j+1]
  66. }
  67. var charTable = [256]bool{
  68. // ASCII
  69. false, false, false, false, false, false, false, false,
  70. false, true, true, false, true, true, false, false, // tab, line feed, form feed, carriage return
  71. false, false, false, false, false, false, false, false,
  72. false, false, false, false, false, false, false, false,
  73. true, false, true, false, false, false, false, true, // space, "), '
  74. false, false, false, false, false, false, false, false,
  75. false, false, false, false, false, false, false, false,
  76. false, false, false, false, true, true, true, false, // <, =, >
  77. false, false, false, false, false, false, false, false,
  78. false, false, false, false, false, false, false, false,
  79. false, false, false, false, false, false, false, false,
  80. false, false, false, false, false, false, false, false,
  81. true, false, false, false, false, false, false, false, // `
  82. false, false, false, false, false, false, false, false,
  83. false, false, false, false, false, false, false, false,
  84. false, false, false, false, false, false, false, false,
  85. // non-ASCII
  86. false, false, false, false, false, false, false, false,
  87. false, false, false, false, false, false, false, false,
  88. false, 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. false, false, false, false, false, false, false, false,
  93. false, false, false, false, false, false, false, false,
  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. false, false, false, false, false, false, false, false,
  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. }