mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-04-25 08:07:58 -05:00
139 lines
3.4 KiB
Go
139 lines
3.4 KiB
Go
package nhttp
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"net/textproto"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
singleCRLF = []byte("\r\n")
|
|
doubleCRLF = []byte("\r\n\r\n")
|
|
)
|
|
|
|
var (
|
|
crlf = []byte("\r\n")
|
|
colonSpace = []byte(": ")
|
|
)
|
|
|
|
func seeUpcomingDoubleCRLF(r *bufio.Reader) bool {
|
|
for peekSize := 4; ; peekSize++ {
|
|
// This loop stops when Peek returns an error,
|
|
// which it does when r's buffer has been filled.
|
|
buf, err := r.Peek(peekSize)
|
|
if bytes.HasSuffix(buf, doubleCRLF) {
|
|
return true
|
|
}
|
|
if err != nil {
|
|
break
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func numLeadingCRorLF(v []byte) (n int) {
|
|
for _, b := range v {
|
|
if b == '\r' || b == '\n' {
|
|
n++
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
return
|
|
|
|
}
|
|
|
|
// EqualFold is strings.EqualFold, ASCII only. It reports whether s and t
|
|
// are equal, ASCII-case-insensitively.
|
|
func EqualFold(s, t string) bool {
|
|
if len(s) != len(t) {
|
|
return false
|
|
}
|
|
for i := 0; i < len(s); i++ {
|
|
if lower(s[i]) != lower(t[i]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// lower returns the ASCII lowercase version of b.
|
|
func lower(b byte) byte {
|
|
if 'A' <= b && b <= 'Z' {
|
|
return b + ('a' - 'A')
|
|
}
|
|
return b
|
|
}
|
|
|
|
// CanonicalHeaderKey returns the canonical format of the
|
|
// header key s. The canonicalization converts the first
|
|
// letter and any letter following a hyphen to upper case;
|
|
// the rest are converted to lowercase. For example, the
|
|
// canonical key for "accept-encoding" is "Accept-Encoding".
|
|
// If s contains a space or invalid header field bytes, it is
|
|
// returned without modifications.
|
|
func CanonicalHeaderKey(s string) string { return textproto.CanonicalMIMEHeaderKey(s) }
|
|
|
|
// hasToken reports whether token appears with v, ASCII
|
|
// case-insensitive, with space or comma boundaries.
|
|
// token must be all lowercase.
|
|
// v may contain mixed cased.
|
|
func hasToken(v, token string) bool {
|
|
if len(token) > len(v) || token == "" {
|
|
return false
|
|
}
|
|
if v == token {
|
|
return true
|
|
}
|
|
for sp := 0; sp <= len(v)-len(token); sp++ {
|
|
// Check that first character is good.
|
|
// The token is ASCII, so checking only a single byte
|
|
// is sufficient. We skip this potential starting
|
|
// position if both the first byte and its potential
|
|
// ASCII uppercase equivalent (b|0x20) don't match.
|
|
// False positives ('^' => '~') are caught by EqualFold.
|
|
if b := v[sp]; b != token[0] && b|0x20 != token[0] {
|
|
continue
|
|
}
|
|
// Check that start pos is on a valid token boundary.
|
|
if sp > 0 && !isTokenBoundary(v[sp-1]) {
|
|
continue
|
|
}
|
|
// Check that end pos is on a valid token boundary.
|
|
if endPos := sp + len(token); endPos != len(v) && !isTokenBoundary(v[endPos]) {
|
|
continue
|
|
}
|
|
if EqualFold(v[sp:sp+len(token)], token) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isTokenBoundary(b byte) bool {
|
|
return b == ' ' || b == ',' || b == '\t'
|
|
}
|
|
|
|
// appendTime is a non-allocating version of []byte(t.UTC().Format(TimeFormat))
|
|
func appendTime(b []byte, t time.Time) []byte {
|
|
const days = "SunMonTueWedThuFriSat"
|
|
const months = "JanFebMarAprMayJunJulAugSepOctNovDec"
|
|
|
|
t = t.UTC()
|
|
yy, mm, dd := t.Date()
|
|
hh, mn, ss := t.Clock()
|
|
day := days[3*t.Weekday():]
|
|
mon := months[3*(mm-1):]
|
|
|
|
return append(b,
|
|
day[0], day[1], day[2], ',', ' ',
|
|
byte('0'+dd/10), byte('0'+dd%10), ' ',
|
|
mon[0], mon[1], mon[2], ' ',
|
|
byte('0'+yy/1000), byte('0'+(yy/100)%10), byte('0'+(yy/10)%10), byte('0'+yy%10), ' ',
|
|
byte('0'+hh/10), byte('0'+hh%10), ':',
|
|
byte('0'+mn/10), byte('0'+mn%10), ':',
|
|
byte('0'+ss/10), byte('0'+ss%10), ' ',
|
|
'G', 'M', 'T')
|
|
}
|