reader.mx raw

   1  // Copyright 2010 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  
   5  package textproto
   6  
   7  import (
   8  	"bufio"
   9  	"bytes"
  10  	"errors"
  11  	"fmt"
  12  	"io"
  13  	"math"
  14  	"strconv"
  15  	"sync"
  16  	_ "unsafe" // for linkname
  17  )
  18  
  19  // TODO: This should be a distinguishable error (ErrMessageTooLarge)
  20  // to allow mime/multipart to detect it.
  21  var errMessageTooLarge = errors.New("message too large")
  22  
  23  // A Reader implements convenience methods for reading requests
  24  // or responses from a text protocol network connection.
  25  type Reader struct {
  26  	R   *bufio.Reader
  27  	dot *dotReader
  28  	buf []byte // a re-usable buffer for readContinuedLineSlice
  29  }
  30  
  31  // NewReader returns a new [Reader] reading from r.
  32  //
  33  // To avoid denial of service attacks, the provided [bufio.Reader]
  34  // should be reading from an [io.LimitReader] or similar Reader to bound
  35  // the size of responses.
  36  func NewReader(r *bufio.Reader) *Reader {
  37  	return &Reader{R: r}
  38  }
  39  
  40  // ReadLine reads a single line from r,
  41  // eliding the final \n or \r\n from the returned string.
  42  func (r *Reader) ReadLine() (string, error) {
  43  	line, err := r.readLineSlice(-1)
  44  	return string(line), err
  45  }
  46  
  47  // ReadLineBytes is like [Reader.ReadLine] but returns a []byte instead of a string.
  48  func (r *Reader) ReadLineBytes() ([]byte, error) {
  49  	line, err := r.readLineSlice(-1)
  50  	if line != nil {
  51  		line = bytes.Clone(line)
  52  	}
  53  	return line, err
  54  }
  55  
  56  // readLineSlice reads a single line from r,
  57  // up to lim bytes long (or unlimited if lim is less than 0),
  58  // eliding the final \r or \r\n from the returned string.
  59  func (r *Reader) readLineSlice(lim int64) ([]byte, error) {
  60  	r.closeDot()
  61  	var line []byte
  62  	for {
  63  		l, more, err := r.R.ReadLine()
  64  		if err != nil {
  65  			return nil, err
  66  		}
  67  		if lim >= 0 && int64(len(line))+int64(len(l)) > lim {
  68  			return nil, errMessageTooLarge
  69  		}
  70  		// Avoid the copy if the first call produced a full line.
  71  		if line == nil && !more {
  72  			return l, nil
  73  		}
  74  		line = append(line, l...)
  75  		if !more {
  76  			break
  77  		}
  78  	}
  79  	return line, nil
  80  }
  81  
  82  // ReadContinuedLine reads a possibly continued line from r,
  83  // eliding the final trailing ASCII white space.
  84  // Lines after the first are considered continuations if they
  85  // begin with a space or tab character. In the returned data,
  86  // continuation lines are separated from the previous line
  87  // only by a single space: the newline and leading white space
  88  // are removed.
  89  //
  90  // For example, consider this input:
  91  //
  92  //	Line 1
  93  //	  continued...
  94  //	Line 2
  95  //
  96  // The first call to ReadContinuedLine will return "Line 1 continued..."
  97  // and the second will return "Line 2".
  98  //
  99  // Empty lines are never continued.
 100  func (r *Reader) ReadContinuedLine() (string, error) {
 101  	line, err := r.readContinuedLineSlice(-1, noValidation)
 102  	return string(line), err
 103  }
 104  
 105  // trim returns s with leading and trailing spaces and tabs removed.
 106  // It does not assume Unicode or UTF-8.
 107  func trim(s []byte) []byte {
 108  	i := 0
 109  	for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
 110  		i++
 111  	}
 112  	n := len(s)
 113  	for n > i && (s[n-1] == ' ' || s[n-1] == '\t') {
 114  		n--
 115  	}
 116  	return s[i:n]
 117  }
 118  
 119  // ReadContinuedLineBytes is like [Reader.ReadContinuedLine] but
 120  // returns a []byte instead of a string.
 121  func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
 122  	line, err := r.readContinuedLineSlice(-1, noValidation)
 123  	if line != nil {
 124  		line = bytes.Clone(line)
 125  	}
 126  	return line, err
 127  }
 128  
 129  // readContinuedLineSlice reads continued lines from the reader buffer,
 130  // returning a byte slice with all lines. The validateFirstLine function
 131  // is run on the first read line, and if it returns an error then this
 132  // error is returned from readContinuedLineSlice.
 133  // It reads up to lim bytes of data (or unlimited if lim is less than 0).
 134  func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) {
 135  	if validateFirstLine == nil {
 136  		return nil, fmt.Errorf("missing validateFirstLine func")
 137  	}
 138  
 139  	// Read the first line.
 140  	line, err := r.readLineSlice(lim)
 141  	if err != nil {
 142  		return nil, err
 143  	}
 144  	if len(line) == 0 { // blank line - no continuation
 145  		return line, nil
 146  	}
 147  
 148  	if err := validateFirstLine(line); err != nil {
 149  		return nil, err
 150  	}
 151  
 152  	// Optimistically assume that we have started to buffer the next line
 153  	// and it starts with an ASCII letter (the next header key), or a blank
 154  	// line, so we can avoid copying that buffered data around in memory
 155  	// and skipping over non-existent whitespace.
 156  	if r.R.Buffered() > 1 {
 157  		peek, _ := r.R.Peek(2)
 158  		if len(peek) > 0 && (isASCIILetter(peek[0]) || peek[0] == '\n') ||
 159  			len(peek) == 2 && peek[0] == '\r' && peek[1] == '\n' {
 160  			return trim(line), nil
 161  		}
 162  	}
 163  
 164  	// ReadByte or the next readLineSlice will flush the read buffer;
 165  	// copy the slice into buf.
 166  	r.buf = append(r.buf[:0], trim(line)...)
 167  
 168  	if lim < 0 {
 169  		lim = math.MaxInt64
 170  	}
 171  	lim -= int64(len(r.buf))
 172  
 173  	// Read continuation lines.
 174  	for r.skipSpace() > 0 {
 175  		r.buf = append(r.buf, ' ')
 176  		if int64(len(r.buf)) >= lim {
 177  			return nil, errMessageTooLarge
 178  		}
 179  		line, err := r.readLineSlice(lim - int64(len(r.buf)))
 180  		if err != nil {
 181  			break
 182  		}
 183  		r.buf = append(r.buf, trim(line)...)
 184  	}
 185  	return r.buf, nil
 186  }
 187  
 188  // skipSpace skips R over all spaces and returns the number of bytes skipped.
 189  func (r *Reader) skipSpace() int {
 190  	n := 0
 191  	for {
 192  		c, err := r.R.ReadByte()
 193  		if err != nil {
 194  			// Bufio will keep err until next read.
 195  			break
 196  		}
 197  		if c != ' ' && c != '\t' {
 198  			r.R.UnreadByte()
 199  			break
 200  		}
 201  		n++
 202  	}
 203  	return n
 204  }
 205  
 206  func (r *Reader) readCodeLine(expectCode int) (code int, continued bool, message string, err error) {
 207  	line, err := r.ReadLine()
 208  	if err != nil {
 209  		return
 210  	}
 211  	return parseCodeLine(line, expectCode)
 212  }
 213  
 214  func parseCodeLine(line string, expectCode int) (code int, continued bool, message string, err error) {
 215  	if len(line) < 4 || line[3] != ' ' && line[3] != '-' {
 216  		err = ProtocolError("short response: " + line)
 217  		return
 218  	}
 219  	continued = line[3] == '-'
 220  	code, err = strconv.Atoi(line[0:3])
 221  	if err != nil || code < 100 {
 222  		err = ProtocolError("invalid response code: " + line)
 223  		return
 224  	}
 225  	message = line[4:]
 226  	if 1 <= expectCode && expectCode < 10 && code/100 != expectCode ||
 227  		10 <= expectCode && expectCode < 100 && code/10 != expectCode ||
 228  		100 <= expectCode && expectCode < 1000 && code != expectCode {
 229  		err = &Error{code, message}
 230  	}
 231  	return
 232  }
 233  
 234  // ReadCodeLine reads a response code line of the form
 235  //
 236  //	code message
 237  //
 238  // where code is a three-digit status code and the message
 239  // extends to the rest of the line. An example of such a line is:
 240  //
 241  //	220 plan9.bell-labs.com ESMTP
 242  //
 243  // If the prefix of the status does not match the digits in expectCode,
 244  // ReadCodeLine returns with err set to &Error{code, message}.
 245  // For example, if expectCode is 31, an error will be returned if
 246  // the status is not in the range [310,319].
 247  //
 248  // If the response is multi-line, ReadCodeLine returns an error.
 249  //
 250  // An expectCode <= 0 disables the check of the status code.
 251  func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err error) {
 252  	code, continued, message, err := r.readCodeLine(expectCode)
 253  	if err == nil && continued {
 254  		err = ProtocolError("unexpected multi-line response: " + message)
 255  	}
 256  	return
 257  }
 258  
 259  // ReadResponse reads a multi-line response of the form:
 260  //
 261  //	code-message line 1
 262  //	code-message line 2
 263  //	...
 264  //	code message line n
 265  //
 266  // where code is a three-digit status code. The first line starts with the
 267  // code and a hyphen. The response is terminated by a line that starts
 268  // with the same code followed by a space. Each line in message is
 269  // separated by a newline (\n).
 270  //
 271  // See page 36 of RFC 959 (https://www.ietf.org/rfc/rfc959.txt) for
 272  // details of another form of response accepted:
 273  //
 274  //	code-message line 1
 275  //	message line 2
 276  //	...
 277  //	code message line n
 278  //
 279  // If the prefix of the status does not match the digits in expectCode,
 280  // ReadResponse returns with err set to &Error{code, message}.
 281  // For example, if expectCode is 31, an error will be returned if
 282  // the status is not in the range [310,319].
 283  //
 284  // An expectCode <= 0 disables the check of the status code.
 285  func (r *Reader) ReadResponse(expectCode int) (code int, message string, err error) {
 286  	code, continued, first, err := r.readCodeLine(expectCode)
 287  	multi := continued
 288  	var messageBuilder bytes.Buffer
 289  	messageBuilder.WriteString(first)
 290  	for continued {
 291  		line, err := r.ReadLine()
 292  		if err != nil {
 293  			return 0, "", err
 294  		}
 295  
 296  		var code2 int
 297  		var moreMessage string
 298  		code2, continued, moreMessage, err = parseCodeLine(line, 0)
 299  		if err != nil || code2 != code {
 300  			messageBuilder.WriteByte('\n')
 301  			messageBuilder.WriteString(bytes.TrimRight(line, "\r\n"))
 302  			continued = true
 303  			continue
 304  		}
 305  		messageBuilder.WriteByte('\n')
 306  		messageBuilder.WriteString(moreMessage)
 307  	}
 308  	message = messageBuilder.String()
 309  	if err != nil && multi && message != "" {
 310  		// replace one line error message with all lines (full message)
 311  		err = &Error{code, message}
 312  	}
 313  	return
 314  }
 315  
 316  // DotReader returns a new [Reader] that satisfies Reads using the
 317  // decoded text of a dot-encoded block read from r.
 318  // The returned Reader is only valid until the next call
 319  // to a method on r.
 320  //
 321  // Dot encoding is a common framing used for data blocks
 322  // in text protocols such as SMTP.  The data consists of a sequence
 323  // of lines, each of which ends in "\r\n".  The sequence itself
 324  // ends at a line containing just a dot: ".\r\n".  Lines beginning
 325  // with a dot are escaped with an additional dot to avoid
 326  // looking like the end of the sequence.
 327  //
 328  // The decoded form returned by the Reader's Read method
 329  // rewrites the "\r\n" line endings into the simpler "\n",
 330  // removes leading dot escapes if present, and stops with error [io.EOF]
 331  // after consuming (and discarding) the end-of-sequence line.
 332  func (r *Reader) DotReader() io.Reader {
 333  	r.closeDot()
 334  	r.dot = &dotReader{r: r}
 335  	return r.dot
 336  }
 337  
 338  type dotReader struct {
 339  	r     *Reader
 340  	state int
 341  }
 342  
 343  // Read satisfies reads by decoding dot-encoded data read from d.r.
 344  func (d *dotReader) Read(b []byte) (n int, err error) {
 345  	// Run data through a simple state machine to
 346  	// elide leading dots, rewrite trailing \r\n into \n,
 347  	// and detect ending .\r\n line.
 348  	const (
 349  		stateBeginLine = iota // beginning of line; initial state; must be zero
 350  		stateDot              // read . at beginning of line
 351  		stateDotCR            // read .\r at beginning of line
 352  		stateCR               // read \r (possibly at end of line)
 353  		stateData             // reading data in middle of line
 354  		stateEOF              // reached .\r\n end marker line
 355  	)
 356  	br := d.r.R
 357  	for n < len(b) && d.state != stateEOF {
 358  		var c byte
 359  		c, err = br.ReadByte()
 360  		if err != nil {
 361  			if err == io.EOF {
 362  				err = io.ErrUnexpectedEOF
 363  			}
 364  			break
 365  		}
 366  		switch d.state {
 367  		case stateBeginLine:
 368  			if c == '.' {
 369  				d.state = stateDot
 370  				continue
 371  			}
 372  			if c == '\r' {
 373  				d.state = stateCR
 374  				continue
 375  			}
 376  			d.state = stateData
 377  
 378  		case stateDot:
 379  			if c == '\r' {
 380  				d.state = stateDotCR
 381  				continue
 382  			}
 383  			if c == '\n' {
 384  				d.state = stateEOF
 385  				continue
 386  			}
 387  			d.state = stateData
 388  
 389  		case stateDotCR:
 390  			if c == '\n' {
 391  				d.state = stateEOF
 392  				continue
 393  			}
 394  			// Not part of .\r\n.
 395  			// Consume leading dot and emit saved \r.
 396  			br.UnreadByte()
 397  			c = '\r'
 398  			d.state = stateData
 399  
 400  		case stateCR:
 401  			if c == '\n' {
 402  				d.state = stateBeginLine
 403  				break
 404  			}
 405  			// Not part of \r\n. Emit saved \r
 406  			br.UnreadByte()
 407  			c = '\r'
 408  			d.state = stateData
 409  
 410  		case stateData:
 411  			if c == '\r' {
 412  				d.state = stateCR
 413  				continue
 414  			}
 415  			if c == '\n' {
 416  				d.state = stateBeginLine
 417  			}
 418  		}
 419  		b[n] = c
 420  		n++
 421  	}
 422  	if err == nil && d.state == stateEOF {
 423  		err = io.EOF
 424  	}
 425  	if err != nil && d.r.dot == d {
 426  		d.r.dot = nil
 427  	}
 428  	return
 429  }
 430  
 431  // closeDot drains the current DotReader if any,
 432  // making sure that it reads until the ending dot line.
 433  func (r *Reader) closeDot() {
 434  	if r.dot == nil {
 435  		return
 436  	}
 437  	buf := []byte{:128}
 438  	for r.dot != nil {
 439  		// When Read reaches EOF or an error,
 440  		// it will set r.dot == nil.
 441  		r.dot.Read(buf)
 442  	}
 443  }
 444  
 445  // ReadDotBytes reads a dot-encoding and returns the decoded data.
 446  //
 447  // See the documentation for the [Reader.DotReader] method for details about dot-encoding.
 448  func (r *Reader) ReadDotBytes() ([]byte, error) {
 449  	return io.ReadAll(r.DotReader())
 450  }
 451  
 452  // ReadDotLines reads a dot-encoding and returns a slice
 453  // containing the decoded lines, with the final \r\n or \n elided from each.
 454  //
 455  // See the documentation for the [Reader.DotReader] method for details about dot-encoding.
 456  func (r *Reader) ReadDotLines() ([][]byte, error) {
 457  	// We could use ReadDotBytes and then Split it,
 458  	// but reading a line at a time avoids needing a
 459  	// large contiguous block of memory and is simpler.
 460  	var v [][]byte
 461  	var err error
 462  	for {
 463  		var line string
 464  		line, err = r.ReadLine()
 465  		if err != nil {
 466  			if err == io.EOF {
 467  				err = io.ErrUnexpectedEOF
 468  			}
 469  			break
 470  		}
 471  
 472  		// Dot by itself marks end; otherwise cut one dot.
 473  		if len(line) > 0 && line[0] == '.' {
 474  			if len(line) == 1 {
 475  				break
 476  			}
 477  			line = line[1:]
 478  		}
 479  		v = append(v, line)
 480  	}
 481  	return v, err
 482  }
 483  
 484  var colon = []byte(":")
 485  
 486  // ReadMIMEHeader reads a MIME-style header from r.
 487  // The header is a sequence of possibly continued Key: Value lines
 488  // ending in a blank line.
 489  // The returned map m maps [CanonicalMIMEHeaderKey](key) to a
 490  // sequence of values in the same order encountered in the input.
 491  //
 492  // For example, consider this input:
 493  //
 494  //	My-Key: Value 1
 495  //	Long-Key: Even
 496  //	       Longer Value
 497  //	My-Key: Value 2
 498  //
 499  // Given that input, ReadMIMEHeader returns the map:
 500  //
 501  //	map[string][][]byte{
 502  //		"My-Key": {"Value 1", "Value 2"},
 503  //		"Long-Key": {"Even Longer Value"},
 504  //	}
 505  func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
 506  	return readMIMEHeader(r, math.MaxInt64, math.MaxInt64)
 507  }
 508  
 509  // readMIMEHeader is accessed from mime/multipart.
 510  //go:linkname readMIMEHeader
 511  
 512  // readMIMEHeader is a version of ReadMIMEHeader which takes a limit on the header size.
 513  // It is called by the mime/multipart package.
 514  func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) {
 515  	// Avoid lots of small slice allocations later by allocating one
 516  	// large one ahead of time which we'll cut up into smaller
 517  	// slices. If this isn't big enough later, we allocate small ones.
 518  	var strs [][]byte
 519  	hint := r.upcomingHeaderKeys()
 520  	if hint > 0 {
 521  		if hint > 1000 {
 522  			hint = 1000 // set a cap to avoid overallocation
 523  		}
 524  		strs = [][]byte{:hint}
 525  	}
 526  
 527  	m := make(MIMEHeader, hint)
 528  
 529  	// Account for 400 bytes of overhead for the MIMEHeader, plus 200 bytes per entry.
 530  	// Benchmarking map creation as of go1.20, a one-entry MIMEHeader is 416 bytes and large
 531  	// MIMEHeaders average about 200 bytes per entry.
 532  	maxMemory -= 400
 533  	const mapEntryOverhead = 200
 534  
 535  	// The first line cannot start with a leading space.
 536  	if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') {
 537  		const errorLimit = 80 // arbitrary limit on how much of the line we'll quote
 538  		line, err := r.readLineSlice(errorLimit)
 539  		if err != nil {
 540  			return m, err
 541  		}
 542  		return m, ProtocolError("malformed MIME header initial line: " + string(line))
 543  	}
 544  
 545  	for {
 546  		kv, err := r.readContinuedLineSlice(maxMemory, mustHaveFieldNameColon)
 547  		if len(kv) == 0 {
 548  			return m, err
 549  		}
 550  
 551  		// Key ends at first colon.
 552  		k, v, ok := bytes.Cut(kv, colon)
 553  		if !ok {
 554  			return m, ProtocolError("malformed MIME header line: " + string(kv))
 555  		}
 556  		key, ok := canonicalMIMEHeaderKey(k)
 557  		if !ok {
 558  			return m, ProtocolError("malformed MIME header line: " + string(kv))
 559  		}
 560  		for _, c := range v {
 561  			if !validHeaderValueByte(c) {
 562  				return m, ProtocolError("malformed MIME header line: " + string(kv))
 563  			}
 564  		}
 565  
 566  		maxHeaders--
 567  		if maxHeaders < 0 {
 568  			return nil, errMessageTooLarge
 569  		}
 570  
 571  		// Skip initial spaces in value.
 572  		value := string(bytes.TrimLeft(v, " \t"))
 573  
 574  		vv := m[key]
 575  		if vv == nil {
 576  			maxMemory -= int64(len(key))
 577  			maxMemory -= mapEntryOverhead
 578  		}
 579  		maxMemory -= int64(len(value))
 580  		if maxMemory < 0 {
 581  			return m, errMessageTooLarge
 582  		}
 583  		if vv == nil && len(strs) > 0 {
 584  			// More than likely this will be a single-element key.
 585  			// Most headers aren't multi-valued.
 586  			// Set the capacity on strs[0] to 1, so any future append
 587  			// won't extend the slice into the other bytes.
 588  			vv, strs = strs[:1:1], strs[1:]
 589  			vv[0] = value
 590  			m[key] = vv
 591  		} else {
 592  			m[key] = append(vv, value)
 593  		}
 594  
 595  		if err != nil {
 596  			return m, err
 597  		}
 598  	}
 599  }
 600  
 601  // noValidation is a no-op validation func for readContinuedLineSlice
 602  // that permits any lines.
 603  func noValidation(_ []byte) error { return nil }
 604  
 605  // mustHaveFieldNameColon ensures that, per RFC 7230, the
 606  // field-name is on a single line, so the first line must
 607  // contain a colon.
 608  func mustHaveFieldNameColon(line []byte) error {
 609  	if bytes.IndexByte(line, ':') < 0 {
 610  		return ProtocolError(fmt.Sprintf("malformed MIME header: missing colon: %q", line))
 611  	}
 612  	return nil
 613  }
 614  
 615  var nl = []byte("\n")
 616  
 617  // upcomingHeaderKeys returns an approximation of the number of keys
 618  // that will be in this header. If it gets confused, it returns 0.
 619  func (r *Reader) upcomingHeaderKeys() (n int) {
 620  	// Try to determine the 'hint' size.
 621  	r.R.Peek(1) // force a buffer load if empty
 622  	s := r.R.Buffered()
 623  	if s == 0 {
 624  		return
 625  	}
 626  	peek, _ := r.R.Peek(s)
 627  	for len(peek) > 0 && n < 1000 {
 628  		var line []byte
 629  		line, peek, _ = bytes.Cut(peek, nl)
 630  		if len(line) == 0 || (len(line) == 1 && line[0] == '\r') {
 631  			// Blank line separating headers from the body.
 632  			break
 633  		}
 634  		if line[0] == ' ' || line[0] == '\t' {
 635  			// Folded continuation of the previous line.
 636  			continue
 637  		}
 638  		n++
 639  	}
 640  	return n
 641  }
 642  
 643  // CanonicalMIMEHeaderKey returns the canonical format of the
 644  // MIME header key s. The canonicalization converts the first
 645  // letter and any letter following a hyphen to upper case;
 646  // the rest are converted to lowercase. For example, the
 647  // canonical key for "accept-encoding" is "Accept-Encoding".
 648  // MIME header keys are assumed to be ASCII only.
 649  // If s contains a space or invalid header field bytes as
 650  // defined by RFC 9112, it is returned without modifications.
 651  func CanonicalMIMEHeaderKey(s string) string {
 652  	// Quick check for canonical encoding.
 653  	upper := true
 654  	for i := 0; i < len(s); i++ {
 655  		c := s[i]
 656  		if !validHeaderFieldByte(c) {
 657  			return s
 658  		}
 659  		if upper && 'a' <= c && c <= 'z' {
 660  			s, _ = canonicalMIMEHeaderKey([]byte(s))
 661  			return s
 662  		}
 663  		if !upper && 'A' <= c && c <= 'Z' {
 664  			s, _ = canonicalMIMEHeaderKey([]byte(s))
 665  			return s
 666  		}
 667  		upper = c == '-'
 668  	}
 669  	return s
 670  }
 671  
 672  const toLower = 'a' - 'A'
 673  
 674  // validHeaderFieldByte reports whether c is a valid byte in a header
 675  // field name. RFC 7230 says:
 676  //
 677  //	header-field   = field-name ":" OWS field-value OWS
 678  //	field-name     = token
 679  //	tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
 680  //	        "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
 681  //	token = 1*tchar
 682  func validHeaderFieldByte(c byte) bool {
 683  	// mask is a 128-bit bitmap with 1s for allowed bytes,
 684  	// so that the byte c can be tested with a shift and an and.
 685  	// If c >= 128, then 1<<c and 1<<(c-64) will both be zero,
 686  	// and this function will return false.
 687  	const mask = 0 |
 688  		(1<<(10)-1)<<'0' |
 689  		(1<<(26)-1)<<'a' |
 690  		(1<<(26)-1)<<'A' |
 691  		1<<'!' |
 692  		1<<'#' |
 693  		1<<'$' |
 694  		1<<'%' |
 695  		1<<'&' |
 696  		1<<'\'' |
 697  		1<<'*' |
 698  		1<<'+' |
 699  		1<<'-' |
 700  		1<<'.' |
 701  		1<<'^' |
 702  		1<<'_' |
 703  		1<<'`' |
 704  		1<<'|' |
 705  		1<<'~'
 706  	return ((uint64(1)<<c)&(mask&(1<<64-1)) |
 707  		(uint64(1)<<(c-64))&(mask>>64)) != 0
 708  }
 709  
 710  // validHeaderValueByte reports whether c is a valid byte in a header
 711  // field value. RFC 7230 says:
 712  //
 713  //	field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
 714  //	field-vchar    = VCHAR / obs-text
 715  //	obs-text       = %x80-FF
 716  //
 717  // RFC 5234 says:
 718  //
 719  //	HTAB           =  %x09
 720  //	SP             =  %x20
 721  //	VCHAR          =  %x21-7E
 722  func validHeaderValueByte(c byte) bool {
 723  	// mask is a 128-bit bitmap with 1s for allowed bytes,
 724  	// so that the byte c can be tested with a shift and an and.
 725  	// If c >= 128, then 1<<c and 1<<(c-64) will both be zero.
 726  	// Since this is the obs-text range, we invert the mask to
 727  	// create a bitmap with 1s for disallowed bytes.
 728  	const mask = 0 |
 729  		(1<<(0x7f-0x21)-1)<<0x21 | // VCHAR: %x21-7E
 730  		1<<0x20 | // SP: %x20
 731  		1<<0x09 // HTAB: %x09
 732  	return ((uint64(1)<<c)&^(mask&(1<<64-1)) |
 733  		(uint64(1)<<(c-64))&^(mask>>64)) == 0
 734  }
 735  
 736  // canonicalMIMEHeaderKey is like CanonicalMIMEHeaderKey but is
 737  // allowed to mutate the provided byte slice before returning the
 738  // string.
 739  //
 740  // For invalid inputs (if a contains spaces or non-token bytes), a
 741  // is unchanged and a string copy is returned.
 742  //
 743  // ok is true if the header key contains only valid characters and spaces.
 744  // ReadMIMEHeader accepts header keys containing spaces, but does not
 745  // canonicalize them.
 746  func canonicalMIMEHeaderKey(a []byte) (_ string, ok bool) {
 747  	if len(a) == 0 {
 748  		return "", false
 749  	}
 750  
 751  	// See if a looks like a header key. If not, return it unchanged.
 752  	noCanon := false
 753  	for _, c := range a {
 754  		if validHeaderFieldByte(c) {
 755  			continue
 756  		}
 757  		// Don't canonicalize.
 758  		if c == ' ' {
 759  			// We accept invalid headers with a space before the
 760  			// colon, but must not canonicalize them.
 761  			// See https://go.dev/issue/34540.
 762  			noCanon = true
 763  			continue
 764  		}
 765  		return string(a), false
 766  	}
 767  	if noCanon {
 768  		return string(a), true
 769  	}
 770  
 771  	upper := true
 772  	for i, c := range a {
 773  		// Canonicalize: first letter upper case
 774  		// and upper case after each dash.
 775  		// (Host, User-Agent, If-Modified-Since).
 776  		// MIME headers are ASCII only, so no Unicode issues.
 777  		if upper && 'a' <= c && c <= 'z' {
 778  			c -= toLower
 779  		} else if !upper && 'A' <= c && c <= 'Z' {
 780  			c += toLower
 781  		}
 782  		a[i] = c
 783  		upper = c == '-' // for next time
 784  	}
 785  	commonHeaderOnce.Do(initCommonHeader)
 786  	// The compiler recognizes m[string(byteSlice)] as a special
 787  	// case, so a copy of a's bytes into a new string does not
 788  	// happen in this map lookup:
 789  	if v := commonHeader[string(a)]; v != "" {
 790  		return v, true
 791  	}
 792  	return string(a), true
 793  }
 794  
 795  // commonHeader interns common header bytes.
 796  var commonHeader map[string]string
 797  
 798  var commonHeaderOnce sync.Once
 799  
 800  func initCommonHeader() {
 801  	commonHeader = map[string]string{}
 802  	for _, v := range [][]byte{
 803  		"Accept",
 804  		"Accept-Charset",
 805  		"Accept-Encoding",
 806  		"Accept-Language",
 807  		"Accept-Ranges",
 808  		"Cache-Control",
 809  		"Cc",
 810  		"Connection",
 811  		"Content-Id",
 812  		"Content-Language",
 813  		"Content-Length",
 814  		"Content-Transfer-Encoding",
 815  		"Content-Type",
 816  		"Cookie",
 817  		"Date",
 818  		"Dkim-Signature",
 819  		"Etag",
 820  		"Expires",
 821  		"From",
 822  		"Host",
 823  		"If-Modified-Since",
 824  		"If-None-Match",
 825  		"In-Reply-To",
 826  		"Last-Modified",
 827  		"Location",
 828  		"Message-Id",
 829  		"Mime-Version",
 830  		"Pragma",
 831  		"Received",
 832  		"Return-Path",
 833  		"Server",
 834  		"Set-Cookie",
 835  		"Subject",
 836  		"To",
 837  		"User-Agent",
 838  		"Via",
 839  		"X-Forwarded-For",
 840  		"X-Imforwards",
 841  		"X-Powered-By",
 842  	} {
 843  		commonHeader[v] = v
 844  	}
 845  }
 846