Class: Rex::Proto::Http::Packet
- Inherits:
-
Object
- Object
- Rex::Proto::Http::Packet
- Defined in:
- lib/rex/proto/http/packet.rb
Overview
This class represents an HTTP packet.
Defined Under Namespace
Modules: ParseCode, ParseState Classes: Header
Instance Attribute Summary collapse
-
#auto_cl ⇒ Object
Returns the value of attribute auto_cl.
-
#body ⇒ Object
Returns the value of attribute body.
-
#bufq ⇒ Object
Returns the value of attribute bufq.
-
#chunk_max_size ⇒ Object
Returns the value of attribute chunk_max_size.
-
#chunk_min_size ⇒ Object
Returns the value of attribute chunk_min_size.
-
#compress ⇒ Object
Returns the value of attribute compress.
-
#error ⇒ Object
Returns the value of attribute error.
-
#headers ⇒ Object
Returns the value of attribute headers.
-
#incomplete ⇒ Object
readonly
Returns the value of attribute incomplete.
-
#max_data ⇒ Object
Returns the value of attribute max_data.
-
#state ⇒ Object
Returns the value of attribute state.
-
#transfer_chunked ⇒ Object
Returns the value of attribute transfer_chunked.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Return the associated header value, if any.
-
#[]=(key, value) ⇒ Object
Set the associated header value.
-
#chunk(str, min_size = 1, max_size = 1000) ⇒ Object
Build a ‘Transfer-Encoding: chunked’ payload with random chunk sizes.
-
#cmd_string ⇒ Object
Returns the command string, such as:.
-
#completed? ⇒ Boolean
Returns whether or not parsing has completed.
-
#from_s(str) ⇒ Object
Converts the packet from a string.
-
#initialize ⇒ Packet
constructor
Initializes an instance of an HTTP packet.
-
#parse(buf) ⇒ Object
Parses the supplied buffer.
-
#reset ⇒ Object
Reset the parsing state and buffers.
-
#reset_except_queue ⇒ Object
Reset the parsing state but leave the buffers.
-
#to_s ⇒ Object
Converts the packet to a string.
Constructor Details
#initialize ⇒ Packet
Initializes an instance of an HTTP packet.
40 41 42 43 44 45 |
# File 'lib/rex/proto/http/packet.rb', line 40 def initialize() self.headers = Header.new self.auto_cl = true reset end |
Instance Attribute Details
#auto_cl ⇒ Object
Returns the value of attribute auto_cl.
233 234 235 |
# File 'lib/rex/proto/http/packet.rb', line 233 def auto_cl @auto_cl end |
#body ⇒ Object
Returns the value of attribute body.
232 233 234 |
# File 'lib/rex/proto/http/packet.rb', line 232 def body @body end |
#bufq ⇒ Object
Returns the value of attribute bufq.
231 232 233 |
# File 'lib/rex/proto/http/packet.rb', line 231 def bufq @bufq end |
#chunk_max_size ⇒ Object
Returns the value of attribute chunk_max_size.
240 241 242 |
# File 'lib/rex/proto/http/packet.rb', line 240 def chunk_max_size @chunk_max_size end |
#chunk_min_size ⇒ Object
Returns the value of attribute chunk_min_size.
239 240 241 |
# File 'lib/rex/proto/http/packet.rb', line 239 def chunk_min_size @chunk_min_size end |
#compress ⇒ Object
Returns the value of attribute compress.
236 237 238 |
# File 'lib/rex/proto/http/packet.rb', line 236 def compress @compress end |
#error ⇒ Object
Returns the value of attribute error.
229 230 231 |
# File 'lib/rex/proto/http/packet.rb', line 229 def error @error end |
#headers ⇒ Object
Returns the value of attribute headers.
228 229 230 |
# File 'lib/rex/proto/http/packet.rb', line 228 def headers @headers end |
#incomplete ⇒ Object
Returns the value of attribute incomplete.
237 238 239 |
# File 'lib/rex/proto/http/packet.rb', line 237 def incomplete @incomplete end |
#max_data ⇒ Object
Returns the value of attribute max_data.
234 235 236 |
# File 'lib/rex/proto/http/packet.rb', line 234 def max_data @max_data end |
#state ⇒ Object
Returns the value of attribute state.
230 231 232 |
# File 'lib/rex/proto/http/packet.rb', line 230 def state @state end |
#transfer_chunked ⇒ Object
Returns the value of attribute transfer_chunked.
235 236 237 |
# File 'lib/rex/proto/http/packet.rb', line 235 def transfer_chunked @transfer_chunked end |
Instance Method Details
#[](key) ⇒ Object
Return the associated header value, if any.
50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/rex/proto/http/packet.rb', line 50 def [](key) if (self.headers.include?(key)) return self.headers[key] end self.headers.each_pair do |k,v| if (k.downcase == key.downcase) return v end end return nil end |
#[]=(key, value) ⇒ Object
Set the associated header value.
67 68 69 |
# File 'lib/rex/proto/http/packet.rb', line 67 def []=(key, value) self.headers[key] = value end |
#chunk(str, min_size = 1, max_size = 1000) ⇒ Object
Build a ‘Transfer-Encoding: chunked’ payload with random chunk sizes
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/rex/proto/http/packet.rb', line 150 def chunk(str, min_size = 1, max_size = 1000) chunked = '' # min chunk size is 1 byte if (min_size < 1); min_size = 1; end # don't be dumb if (max_size < min_size); max_size = min_size; end while (str.size > 0) chunk = str.slice!(0, rand(max_size - min_size) + min_size) chunked += sprintf("%x", chunk.size) + "\r\n" + chunk + "\r\n" end chunked += "0\r\n\r\n" end |
#cmd_string ⇒ Object
Returns the command string, such as:
HTTP/1.0 200 OK for a response
or
GET /foo HTTP/1.0 for a request
224 225 226 |
# File 'lib/rex/proto/http/packet.rb', line 224 def cmd_string self.headers.cmd_string end |
#completed? ⇒ Boolean
Returns whether or not parsing has completed.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/rex/proto/http/packet.rb', line 132 def completed? return true if self.state == ParseState::Completed # If the parser state is processing the body and there are an # undetermined number of bytes left to read, we just need to say that # things are completed as it's hard to tell whether or not they really # are. if (self.state == ParseState::ProcessingBody and self.body_bytes_left < 0) return true end false end |
#from_s(str) ⇒ Object
Converts the packet from a string.
210 211 212 213 |
# File 'lib/rex/proto/http/packet.rb', line 210 def from_s(str) reset parse(str) end |
#parse(buf) ⇒ Object
Parses the supplied buffer. Returns one of the two parser processing codes (Completed, Partial, or Error).
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/rex/proto/http/packet.rb', line 75 def parse(buf) # Append the incoming buffer to the buffer queue. self.bufq += buf.to_s begin # Process the header if(self.state == ParseState::ProcessingHeader) parse_header end # Continue on to the body if the header was processed if(self.state == ParseState::ProcessingBody) # Chunked encoding sets the parsing state on its own if (self.body_bytes_left == 0 and not self.transfer_chunked) self.state = ParseState::Completed else parse_body end end rescue # XXX: BUG: This rescue might be a problem because it will swallow TimeoutError self.error = $! return ParseCode::Error end # Return completed or partial to the parsing status to the caller (self.state == ParseState::Completed) ? ParseCode::Completed : ParseCode::Partial end |
#reset ⇒ Object
Reset the parsing state and buffers.
109 110 111 112 113 114 115 116 |
# File 'lib/rex/proto/http/packet.rb', line 109 def reset self.state = ParseState::ProcessingHeader self.transfer_chunked = false self.inside_chunk = false self.headers.reset self.bufq = '' self.body = '' end |
#reset_except_queue ⇒ Object
Reset the parsing state but leave the buffers.
121 122 123 124 125 126 127 |
# File 'lib/rex/proto/http/packet.rb', line 121 def reset_except_queue self.state = ParseState::ProcessingHeader self.transfer_chunked = false self.inside_chunk = false self.headers.reset self.body = '' end |
#to_s ⇒ Object
Converts the packet to a string.
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/rex/proto/http/packet.rb', line 169 def to_s content = self.body.to_s.dup # Update the content length field in the header with the body length. if (content) if !self.compress.nil? case self.compress when 'gzip' self.headers['Content-Encoding'] = 'gzip' content = Rex::Text.gzip(content) when 'deflate' self.headers['Content-Encoding'] = 'deflate' content = Rex::Text.zlib_deflate(content) when 'none' # this one is fine... # when 'compress' else raise RuntimeError, 'Invalid Content-Encoding' end end if (self.auto_cl == true && self.transfer_chunked == true) raise RuntimeError, "'Content-Length' and 'Transfer-Encoding: chunked' are incompatible" elsif self.auto_cl == true self.headers['Content-Length'] = content.length elsif self.transfer_chunked == true if self.proto != '1.1' raise RuntimeError, 'Chunked encoding is only available via 1.1' end self.headers['Transfer-Encoding'] = 'chunked' content = self.chunk(content, self.chunk_min_size, self.chunk_max_size) end end str = self.headers.to_s(cmd_string) str += content || '' end |