Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/proto/http/packet/header.rb
Views: 11766
# -*- coding: binary -*-123module Rex4module Proto5module Http67###8#9# Represents the logical HTTP header portion of an HTTP packet (request or10# response).11#12###13class Packet::Header < Hash1415#16# Initializes an HTTP packet header class that inherits from a Hash base17# class.18#19def initialize20self.dcase_hash = {}2122reset23end2425#26# Parses a header from a string.27#28# XXX - Putting : in a header value breaks this badly29def from_s(header)30reset3132# ghettoooooo!33# If we don't have any newlines..., put one there.34if (header.size > 0 && header !~ /\r\n/)35header << "\r\n"36end3738# put the non-standard line terminations back to normal39# gah. not having look behinds suck,40header.gsub!(/([^\r])\n/n,'\1' + "\r\n")4142# undo folding, kinda ugly but works for now.43header.gsub!(/:\s*\r\n\s+/smni,': ')4445# Extract the command string46self.cmd_string = header.slice!(/.+\r\n/)4748# Extract each header value pair49header.split(/\r\n/mn).each { |str|50if (md = str.match(/^(.+?)\s*:\s*(.+?)\s*$/))51if (self[md[1]])52self[md[1]] << ", " + md[2]53else54self[md[1]] = md[2]55end56end57}58end5960#61# More advanced [] that does downcase comparison.62#63def [](key)64begin65rv = self.fetch(key)66rescue IndexError67rv = nil68end69if (rv == nil)70begin71rv = self.dcase_hash[key.downcase]72rescue IndexError73rv = nil74end75end7677return rv78end7980#81# More advanced []= that does downcase storage.82#83def []=(key, value)84stored = false8586self.each_key { |k|87if (k.downcase == key.downcase)88self.store(k, value)89stored = true90end91}9293self.store(key, value) if (stored == false)94self.dcase_hash[key.downcase] = value95end9697#98# More advanced include? that does downcase comparison99#100def include?(key)101self.each_key.any? { |k|102k.casecmp?(key)103}104end105#106# Converts the header to a string.107#108def to_s(prefix = '')109str = prefix110111if self.junk_headers112while str.length < 4096113if self.fold114str << "X-#{Rex::Text.rand_text_alphanumeric(rand(30) + 5)}:\r\n\t#{Rex::Text.rand_text_alphanumeric(rand(1024) + 1)}\r\n"115else116str << "X-#{Rex::Text.rand_text_alphanumeric(rand(30) + 5)}: #{Rex::Text.rand_text_alphanumeric(rand(1024) + 1)}\r\n"117end118end119end120121each_pair { |var, val|122if self.fold123str << "#{var}:\r\n\t#{val}\r\n"124else125str << "#{var}: #{val}\r\n"126end127}128129str << "\r\n"130131return str132end133134#135# Brings in from an array like yo.136#137def from_a(ary)138ary.each { |e|139self[e[0]] = e[1]140}141end142143#144# Flushes all header pairs.145#146def reset147self.cmd_string = ''148self.clear149self.dcase_hash.clear150end151152#153# Overrides the builtin 'each' operator to avoid the following exception on Ruby 1.9.2+154# "can't add a new key into hash during iteration"155#156def each(&block)157list = []158self.keys.sort.each do |sidx|159list << [sidx, self[sidx]]160end161list.each(&block)162end163164#165# The raw command string associated with the header which will vary between166# requests and responses.167#168attr_accessor :junk_headers169attr_accessor :cmd_string170attr_accessor :fold171172protected173174attr_accessor :dcase_hash # :nodoc:175176end177178end179end180end181182183