You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							99 lines
						
					
					
						
							2.7 KiB
						
					
					
				
			
		
		
	
	
							99 lines
						
					
					
						
							2.7 KiB
						
					
					
				const EventEmitter = require('events').EventEmitter
 | 
						|
const inherits = require('util').inherits
 | 
						|
const getLimit = require('../../../lib/utils').getLimit
 | 
						|
 | 
						|
const StreamSearch = require('../../streamsearch/sbmh')
 | 
						|
 | 
						|
const B_DCRLF = Buffer.from('\r\n\r\n')
 | 
						|
const RE_CRLF = /\r\n/g
 | 
						|
const RE_HDR = /^([^:]+):[ \t]?([\x00-\xFF]+)?$/ // eslint-disable-line no-control-regex
 | 
						|
 | 
						|
function HeaderParser (cfg) {
 | 
						|
  EventEmitter.call(this)
 | 
						|
 | 
						|
  cfg = cfg || {}
 | 
						|
  const self = this
 | 
						|
  this.nread = 0
 | 
						|
  this.maxed = false
 | 
						|
  this.npairs = 0
 | 
						|
  this.maxHeaderPairs = getLimit(cfg, 'maxHeaderPairs', 2000)
 | 
						|
  this.maxHeaderSize = getLimit(cfg, 'maxHeaderSize', 80 * 1024)
 | 
						|
  this.buffer = ''
 | 
						|
  this.header = {}
 | 
						|
  this.finished = false
 | 
						|
  this.ss = new StreamSearch(B_DCRLF)
 | 
						|
  this.ss.on('info', function (isMatch, data, start, end) {
 | 
						|
    if (data && !self.maxed) {
 | 
						|
      if (self.nread + end - start >= self.maxHeaderSize) {
 | 
						|
        end = self.maxHeaderSize - self.nread + start
 | 
						|
        self.nread = self.maxHeaderSize
 | 
						|
        self.maxed = true
 | 
						|
      } else { self.nread += (end - start) }
 | 
						|
 | 
						|
      self.buffer += data.toString('binary', start, end)
 | 
						|
    }
 | 
						|
    if (isMatch) { self._finish() }
 | 
						|
  })
 | 
						|
}
 | 
						|
inherits(HeaderParser, EventEmitter)
 | 
						|
 | 
						|
HeaderParser.prototype.push = function (data) {
 | 
						|
  const r = this.ss.push(data)
 | 
						|
  if (this.finished) { return r }
 | 
						|
}
 | 
						|
 | 
						|
HeaderParser.prototype.reset = function () {
 | 
						|
  this.finished = false
 | 
						|
  this.buffer = ''
 | 
						|
  this.header = {}
 | 
						|
  this.ss.reset()
 | 
						|
}
 | 
						|
 | 
						|
HeaderParser.prototype._finish = function () {
 | 
						|
  if (this.buffer) { this._parseHeader() }
 | 
						|
  this.ss.matches = this.ss.maxMatches
 | 
						|
  const header = this.header
 | 
						|
  this.header = {}
 | 
						|
  this.buffer = ''
 | 
						|
  this.finished = true
 | 
						|
  this.nread = this.npairs = 0
 | 
						|
  this.maxed = false
 | 
						|
  this.emit('header', header)
 | 
						|
}
 | 
						|
 | 
						|
HeaderParser.prototype._parseHeader = function () {
 | 
						|
  if (this.npairs === this.maxHeaderPairs) { return }
 | 
						|
 | 
						|
  const lines = this.buffer.split(RE_CRLF)
 | 
						|
  const len = lines.length
 | 
						|
  let m, h
 | 
						|
 | 
						|
  for (var i = 0; i < len; ++i) { // eslint-disable-line no-var
 | 
						|
    if (lines[i].length === 0) { continue }
 | 
						|
    if (lines[i][0] === '\t' || lines[i][0] === ' ') {
 | 
						|
      // folded header content
 | 
						|
      // RFC2822 says to just remove the CRLF and not the whitespace following
 | 
						|
      // it, so we follow the RFC and include the leading whitespace ...
 | 
						|
      if (h) {
 | 
						|
        this.header[h][this.header[h].length - 1] += lines[i]
 | 
						|
        continue
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    const posColon = lines[i].indexOf(':')
 | 
						|
    if (
 | 
						|
      posColon === -1 ||
 | 
						|
      posColon === 0
 | 
						|
    ) {
 | 
						|
      return
 | 
						|
    }
 | 
						|
    m = RE_HDR.exec(lines[i])
 | 
						|
    h = m[1].toLowerCase()
 | 
						|
    this.header[h] = this.header[h] || []
 | 
						|
    this.header[h].push((m[2] || ''))
 | 
						|
    if (++this.npairs === this.maxHeaderPairs) { break }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
module.exports = HeaderParser
 |