class Rex::Proto::Http::Packet::Header

Represents the logical HTTP header portion of an HTTP packet (request or response).

Attributes

cmd_string[RW]
fold[RW]
junk_headers[RW]

The raw command string associated with the header which will vary between requests and responses.

Public Class Methods

new() click to toggle source

Initializes an HTTP packet header class that inherits from a Hash base class.

# File lib/rex/proto/http/packet/header.rb, line 19
def initialize
  self.dcase_hash = {}

  reset
end

Public Instance Methods

[](key) click to toggle source

More advanced [] that does downcase comparison.

# File lib/rex/proto/http/packet/header.rb, line 63
def [](key)
  begin
    rv = self.fetch(key)
  rescue IndexError
    rv = nil
  end
  if (rv == nil)
    begin
      rv = self.dcase_hash[key.downcase]
    rescue IndexError
      rv = nil
    end
  end

  return rv
end
[]=(key, value) click to toggle source

More advanced []= that does downcase storage.

# File lib/rex/proto/http/packet/header.rb, line 83
def []=(key, value)
  stored = false

  self.each_key { |k|
    if (k.downcase == key.downcase)
      self.store(k, value)
      stored = true
    end
  }

  self.store(key, value) if (stored == false)
  self.dcase_hash[key.downcase] = value
end
each(&block) click to toggle source

Overrides the builtin 'each' operator to avoid the following exception on Ruby 1.9.2+

"can't add a new key into hash during iteration"
# File lib/rex/proto/http/packet/header.rb, line 148
def each(&block)
  list = []
  self.keys.sort.each do |sidx|
    list << [sidx, self[sidx]]
  end
  list.each(&block)
end
from_a(ary) click to toggle source

Brings in from an array like yo.

# File lib/rex/proto/http/packet/header.rb, line 129
def from_a(ary)
  ary.each { |e|
    self[e[0]] = e[1]
  }
end
from_s(header) click to toggle source

Parses a header from a string.

XXX - Putting : in a header value breaks this badly

# File lib/rex/proto/http/packet/header.rb, line 29
def from_s(header)
  reset

  # ghettoooooo!
  # If we don't have any newlines..., put one there.
  if (header.size > 0 && header !~ /\r\n/)
    header << "\r\n"
  end

  # put the non-standard line terminations back to normal
  # gah.  not having look behinds suck,
  header.gsub!(/([^\r])\n/n,'\1' + "\r\n")

  # undo folding, kinda ugly but works for now.
  header.gsub!(/:\s*\r\n\s+/smni,': ')

  # Extract the command string
  self.cmd_string = header.slice!(/.+\r\n/)

  # Extract each header value pair
  header.split(/\r\n/mn).each { |str|
    if (md = str.match(/^(.+?)\s*:\s*(.+?)\s*$/))
      if (self[md[1]])
        self[md[1]] << ", " + md[2]
      else
        self[md[1]] = md[2]
      end
    end
  }
end
reset() click to toggle source

Flushes all header pairs.

# File lib/rex/proto/http/packet/header.rb, line 138
def reset
  self.cmd_string = ''
  self.clear
  self.dcase_hash.clear
end
to_s(prefix = '') click to toggle source

Converts the header to a string.

# File lib/rex/proto/http/packet/header.rb, line 100
def to_s(prefix = '')
  str = prefix

  if self.junk_headers
    while str.length < 4096
      if self.fold
        str << "X-#{Rex::Text.rand_text_alphanumeric(rand(30) + 5)}:\r\n\t#{Rex::Text.rand_text_alphanumeric(rand(1024) + 1)}\r\n"
      else
        str << "X-#{Rex::Text.rand_text_alphanumeric(rand(30) + 5)}: #{Rex::Text.rand_text_alphanumeric(rand(1024) + 1)}\r\n"
      end
    end
  end

  each_pair { |var, val|
    if self.fold
      str << "#{var}:\r\n\t#{val}\r\n"
    else
      str << "#{var}: #{val}\r\n"
    end
  }

  str << "\r\n"

  return str
end