lex.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright 2009 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. package cacheobject
  5. // This file deals with lexical matters of HTTP
  6. func isSeparator(c byte) bool {
  7. switch c {
  8. case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t':
  9. return true
  10. }
  11. return false
  12. }
  13. func isCtl(c byte) bool { return (0 <= c && c <= 31) || c == 127 }
  14. func isChar(c byte) bool { return 0 <= c && c <= 127 }
  15. func isAnyText(c byte) bool { return !isCtl(c) }
  16. func isQdText(c byte) bool { return isAnyText(c) && c != '"' }
  17. func isToken(c byte) bool { return isChar(c) && !isCtl(c) && !isSeparator(c) }
  18. // Valid escaped sequences are not specified in RFC 2616, so for now, we assume
  19. // that they coincide with the common sense ones used by GO. Malformed
  20. // characters should probably not be treated as errors by a robust (forgiving)
  21. // parser, so we replace them with the '?' character.
  22. func httpUnquotePair(b byte) byte {
  23. // skip the first byte, which should always be '\'
  24. switch b {
  25. case 'a':
  26. return '\a'
  27. case 'b':
  28. return '\b'
  29. case 'f':
  30. return '\f'
  31. case 'n':
  32. return '\n'
  33. case 'r':
  34. return '\r'
  35. case 't':
  36. return '\t'
  37. case 'v':
  38. return '\v'
  39. case '\\':
  40. return '\\'
  41. case '\'':
  42. return '\''
  43. case '"':
  44. return '"'
  45. }
  46. return '?'
  47. }
  48. // raw must begin with a valid quoted string. Only the first quoted string is
  49. // parsed and is unquoted in result. eaten is the number of bytes parsed, or -1
  50. // upon failure.
  51. func httpUnquote(raw string) (eaten int, result string) {
  52. buf := make([]byte, len(raw))
  53. if raw[0] != '"' {
  54. return -1, ""
  55. }
  56. eaten = 1
  57. j := 0 // # of bytes written in buf
  58. for i := 1; i < len(raw); i++ {
  59. switch b := raw[i]; b {
  60. case '"':
  61. eaten++
  62. buf = buf[0:j]
  63. return i + 1, string(buf)
  64. case '\\':
  65. if len(raw) < i+2 {
  66. return -1, ""
  67. }
  68. buf[j] = httpUnquotePair(raw[i+1])
  69. eaten += 2
  70. j++
  71. i++
  72. default:
  73. if isQdText(b) {
  74. buf[j] = b
  75. } else {
  76. buf[j] = '?'
  77. }
  78. eaten++
  79. j++
  80. }
  81. }
  82. return -1, ""
  83. }