Class: Rex::Proto::Http::Packet::Header

Inherits:
Hash
  • Object
show all
Defined in:
lib/rex/proto/http/header.rb

Overview

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeHeader

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


20
21
22
23
24
# File 'lib/rex/proto/http/header.rb', line 20

def initialize
  self.dcase_hash = {}

  reset
end

Instance Attribute Details

#cmd_stringObject

Returns the value of attribute cmd_string


162
163
164
# File 'lib/rex/proto/http/header.rb', line 162

def cmd_string
  @cmd_string
end

#foldObject

Returns the value of attribute fold


163
164
165
# File 'lib/rex/proto/http/header.rb', line 163

def fold
  @fold
end

#junk_headersObject

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


161
162
163
# File 'lib/rex/proto/http/header.rb', line 161

def junk_headers
  @junk_headers
end

Instance Method Details

#[](key) ⇒ Object

More advanced [] that does downcase comparison.


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/rex/proto/http/header.rb', line 64

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) ⇒ Object

More advanced []= that does downcase storage.


84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/rex/proto/http/header.rb', line 84

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) ⇒ Object

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"

149
150
151
152
153
154
155
# File 'lib/rex/proto/http/header.rb', line 149

def each(&block)
  list = []
  self.keys.sort.each do |sidx|
    list << [sidx, self[sidx]]
  end
  list.each(&block)
end

#from_a(ary) ⇒ Object

Brings in from an array like yo.


130
131
132
133
134
# File 'lib/rex/proto/http/header.rb', line 130

def from_a(ary)
  ary.each { |e|
    self[e[0]] = e[1]
  }
end

#from_s(header) ⇒ Object

Parses a header from a string.

XXX - Putting : in a header value breaks this badly


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rex/proto/http/header.rb', line 30

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

#resetObject

Flushes all header pairs.


139
140
141
142
143
# File 'lib/rex/proto/http/header.rb', line 139

def reset
  self.cmd_string = ''
  self.clear
  self.dcase_hash.clear
end

#to_s(prefix = '') ⇒ Object

Converts the header to a string.


101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/rex/proto/http/header.rb', line 101

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