mirror of
https://github.com/autc04/Retro68.git
synced 2024-11-24 23:32:06 +00:00
184 lines
3.8 KiB
Go
184 lines
3.8 KiB
Go
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package http
|
|
|
|
import (
|
|
"strings"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// This file deals with lexical matters of HTTP
|
|
|
|
var isTokenTable = [127]bool{
|
|
'!': true,
|
|
'#': 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,
|
|
'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,
|
|
'W': true,
|
|
'V': true,
|
|
'X': true,
|
|
'Y': true,
|
|
'Z': 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,
|
|
}
|
|
|
|
func isToken(r rune) bool {
|
|
i := int(r)
|
|
return i < len(isTokenTable) && isTokenTable[i]
|
|
}
|
|
|
|
func isNotToken(r rune) bool {
|
|
return !isToken(r)
|
|
}
|
|
|
|
// headerValuesContainsToken reports whether any string in values
|
|
// contains the provided token, ASCII case-insensitively.
|
|
func headerValuesContainsToken(values []string, token string) bool {
|
|
for _, v := range values {
|
|
if headerValueContainsToken(v, token) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// isOWS reports whether b is an optional whitespace byte, as defined
|
|
// by RFC 7230 section 3.2.3.
|
|
func isOWS(b byte) bool { return b == ' ' || b == '\t' }
|
|
|
|
// trimOWS returns x with all optional whitespace removes from the
|
|
// beginning and end.
|
|
func trimOWS(x string) string {
|
|
// TODO: consider using strings.Trim(x, " \t") instead,
|
|
// if and when it's fast enough. See issue 10292.
|
|
// But this ASCII-only code will probably always beat UTF-8
|
|
// aware code.
|
|
for len(x) > 0 && isOWS(x[0]) {
|
|
x = x[1:]
|
|
}
|
|
for len(x) > 0 && isOWS(x[len(x)-1]) {
|
|
x = x[:len(x)-1]
|
|
}
|
|
return x
|
|
}
|
|
|
|
// headerValueContainsToken reports whether v (assumed to be a
|
|
// 0#element, in the ABNF extension described in RFC 7230 section 7)
|
|
// contains token amongst its comma-separated tokens, ASCII
|
|
// case-insensitively.
|
|
func headerValueContainsToken(v string, token string) bool {
|
|
v = trimOWS(v)
|
|
if comma := strings.IndexByte(v, ','); comma != -1 {
|
|
return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
|
|
}
|
|
return tokenEqual(v, token)
|
|
}
|
|
|
|
// lowerASCII returns the ASCII lowercase version of b.
|
|
func lowerASCII(b byte) byte {
|
|
if 'A' <= b && b <= 'Z' {
|
|
return b + ('a' - 'A')
|
|
}
|
|
return b
|
|
}
|
|
|
|
// tokenEqual reports whether t1 and t2 are equal, ASCII case-insensitively.
|
|
func tokenEqual(t1, t2 string) bool {
|
|
if len(t1) != len(t2) {
|
|
return false
|
|
}
|
|
for i, b := range t1 {
|
|
if b >= utf8.RuneSelf {
|
|
// No UTF-8 or non-ASCII allowed in tokens.
|
|
return false
|
|
}
|
|
if lowerASCII(byte(b)) != lowerASCII(t2[i]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// isLWS reports whether b is linear white space, according
|
|
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
|
|
// LWS = [CRLF] 1*( SP | HT )
|
|
func isLWS(b byte) bool { return b == ' ' || b == '\t' }
|
|
|
|
// isCTL reports whether b is a control byte, according
|
|
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
|
|
// CTL = <any US-ASCII control character
|
|
// (octets 0 - 31) and DEL (127)>
|
|
func isCTL(b byte) bool {
|
|
const del = 0x7f // a CTL
|
|
return b < ' ' || b == del
|
|
}
|