diff options
Diffstat (limited to 'lib/webrick/httputils.rb')
-rw-r--r-- | lib/webrick/httputils.rb | 127 |
1 files changed, 116 insertions, 11 deletions
diff --git a/lib/webrick/httputils.rb b/lib/webrick/httputils.rb index 57ae364b35..a0ca3a48c7 100644 --- a/lib/webrick/httputils.rb +++ b/lib/webrick/httputils.rb @@ -12,12 +12,21 @@ require 'socket' require 'tempfile' module WEBrick - CR = "\x0d" - LF = "\x0a" - CRLF = "\x0d\x0a" + CR = "\x0d" # :nodoc: + LF = "\x0a" # :nodoc: + CRLF = "\x0d\x0a" # :nodoc: + + ## + # HTTPUtils provides utility methods for working with the HTTP protocol. + # + # This module is generally used internally by WEBrick module HTTPUtils + ## + # Normalizes a request path. Raises an exception if the path cannot be + # normalized. + def normalize_path(path) raise "abnormal path `#{path}'" if path[0] != ?/ ret = path.dup @@ -31,7 +40,8 @@ module WEBrick end module_function :normalize_path - ##### + ## + # Default mime types DefaultMimeTypes = { "ai" => "application/postscript", @@ -92,7 +102,9 @@ module WEBrick "zip" => "application/zip", } - # Load Apache compatible mime.types file. + ## + # Loads Apache-compatible mime.types in +file+. + def load_mime_types(file) open(file){ |io| hash = Hash.new @@ -109,6 +121,10 @@ module WEBrick end module_function :load_mime_types + ## + # Returns the mime type of +filename+ from the list in +mime_tab+. If no + # mime type was found application/octet-stream is returned. + def mime_type(filename, mime_tab) suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase) suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase) @@ -116,7 +132,9 @@ module WEBrick end module_function :mime_type - ##### + ## + # Parses an HTTP header +raw+ into a hash of header fields with an Array + # of values. def parse_header(raw) header = Hash.new([].freeze) @@ -148,12 +166,18 @@ module WEBrick end module_function :parse_header + ## + # Splits a header value +str+ according to HTTP specification. + def split_header_value(str) str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+) (?:,\s*|\Z)'xn).flatten end module_function :split_header_value + ## + # Parses a Range header value +ranges_specifier+ + def parse_range_header(ranges_specifier) if /^bytes=(.*)/ =~ ranges_specifier byte_range_set = split_header_value($1) @@ -169,6 +193,9 @@ module WEBrick end module_function :parse_range_header + ## + # Parses q values in +value+ as used in Accept headers. + def parse_qvalues(value) tmp = [] if value @@ -187,7 +214,8 @@ module WEBrick end module_function :parse_qvalues - ##### + ## + # Removes quotes and escapes from +str+ def dequote(str) ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup @@ -196,20 +224,43 @@ module WEBrick end module_function :dequote + ## + # Quotes and escapes quotes in +str+ + def quote(str) '"' << str.gsub(/[\\\"]/o, "\\\1") << '"' end module_function :quote - ##### + ## + # Stores multipart form data. FormData objects are created when + # WEBrick::HTTPUtils.parse_form_data is called. class FormData < String - EmptyRawHeader = [].freeze - EmptyHeader = {}.freeze + EmptyRawHeader = [].freeze # :nodoc: + EmptyHeader = {}.freeze # :nodoc: + + ## + # The name of the form data part - attr_accessor :name, :filename, :next_data + attr_accessor :name + + ## + # The filename of the form data part + + attr_accessor :filename + + attr_accessor :next_data # :nodoc: protected :next_data + ## + # Creates a new FormData object. + # + # +args+ is an Array of form data entries. One FormData will be created + # for each entry. + # + # This is called by WEBrick::HTTPUtils.parse_form_data for you + def initialize(*args) @name = @filename = @next_data = nil if args.empty? @@ -226,6 +277,9 @@ module WEBrick end end + ## + # Retrieves the header at the first entry in +key+ + def [](*key) begin @header[key[0].downcase].join(", ") @@ -234,6 +288,12 @@ module WEBrick end end + ## + # Adds +str+ to this FormData which may be the body, a header or a + # header entry. + # + # This is called by WEBrick::HTTPUtils.parse_form_data for you + def <<(str) if @header super @@ -249,6 +309,11 @@ module WEBrick self end + ## + # Adds +data+ at the end of the chain of entries + # + # This is called by WEBrick::HTTPUtils.parse_form_data for you. + def append_data(data) tmp = self while tmp @@ -261,6 +326,9 @@ module WEBrick self end + ## + # Yields each entry in this FormData + def each_data tmp = self while tmp @@ -270,6 +338,9 @@ module WEBrick end end + ## + # Returns all the FormData as an Array + def list ret = [] each_data{|data| @@ -278,13 +349,22 @@ module WEBrick ret end + ## + # A FormData will behave like an Array + alias :to_ary :list + ## + # This FormData's body + def to_s String.new(self) end end + ## + # Parses the query component of a URI in +str+ + def parse_query(str) query = Hash.new if str @@ -306,6 +386,9 @@ module WEBrick end module_function :parse_query + ## + # Parses form data in +io+ with the given +boundary+ + def parse_form_data(io, boundary) boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/ form_data = Hash.new @@ -350,6 +433,8 @@ module WEBrick module_function + # :stopdoc: + def _make_regex(str) /([#{Regexp.escape(str)}])/n end def _make_regex!(str) /([^#{Regexp.escape(str)}])/n end def _escape(str, regex) str.gsub(regex){ "%%%02X" % $1.ord } end @@ -361,24 +446,41 @@ module WEBrick ESCAPED = /%([0-9a-fA-F]{2})/ UNESCAPED_PCHAR = _make_regex!(unreserved+":@&=+$,") + # :startdoc: + + ## + # Escapes HTTP reserved and unwise characters in +str+ + def escape(str) _escape(str, UNESCAPED) end + ## + # Unescapes HTTP reserved and unwise characters in +str+ + def unescape(str) _unescape(str, ESCAPED) end + ## + # Escapes form reserved characters in +str+ + def escape_form(str) ret = _escape(str, UNESCAPED_FORM) ret.gsub!(/ /, "+") ret end + ## + # Unescapes form reserved characters in +str+ + def unescape_form(str) _unescape(str.gsub(/\+/, " "), ESCAPED) end + ## + # Escapes path +str+ + def escape_path(str) result = "" str.scan(%r{/([^/]*)}).each{|i| @@ -387,6 +489,9 @@ module WEBrick return result end + ## + # Escapes 8 bit characters in +str+ + def escape8bit(str) _escape(str, NONASCII) end |