diff --git a/lib/webrick/httputils.rb b/lib/webrick/httputils.rb index ea67fdb..92f3044 100644 --- a/lib/webrick/httputils.rb +++ b/lib/webrick/httputils.rb @@ -178,12 +178,12 @@ def parse_header(raw) field.downcase! header[field] = HEADER_CLASSES[field].new unless header.has_key?(field) header[field] << value - when /^\s+([^\r\n\0]*?)\r\n/om + when /^[ \t]+([^\r\n\0]*?)\r\n/om unless field raise HTTPStatus::BadRequest, "bad header '#{line}'." end value = line - value.lstrip! + value.gsub!(/\A[ \t]+/, '') value.slice!(-2..-1) header[field][-1] << " " << value else @@ -191,7 +191,10 @@ def parse_header(raw) end } header.each{|key, values| - values.each(&:strip!) + values.each{|value| + value.gsub!(/\A[ \t]+/, '') + value.gsub!(/[ \t]+\z/, '') + } } header end @@ -202,7 +205,7 @@ def parse_header(raw) def split_header_value(str) str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]++)+) - (?:,\s*|\Z)'xn).flatten + (?:,[ \t]*|\Z)'xn).flatten end module_function :split_header_value @@ -230,9 +233,9 @@ def parse_range_header(ranges_specifier) def parse_qvalues(value) tmp = [] if value - parts = value.split(/,\s*/) + parts = value.split(/,[ \t]*/) parts.each {|part| - if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part) + if m = %r{^([^ \t,]+?)(?:;[ \t]*q=(\d+(?:\.\d+)?))?$}.match(part) val = m[1] q = (m[2] or 1).to_f tmp.push([val, q]) @@ -331,8 +334,8 @@ def <<(str) elsif str == CRLF @header = HTTPUtils::parse_header(@raw_header.join) if cd = self['content-disposition'] - if /\s+name="(.*?)"/ =~ cd then @name = $1 end - if /\s+filename="(.*?)"/ =~ cd then @filename = $1 end + if /[ \t]+name="(.*?)"/ =~ cd then @name = $1 end + if /[ \t]+filename="(.*?)"/ =~ cd then @filename = $1 end end else @raw_header << str diff --git a/test/webrick/test_httprequest.rb b/test/webrick/test_httprequest.rb index 6088f18..ad00d60 100644 --- a/test/webrick/test_httprequest.rb +++ b/test/webrick/test_httprequest.rb @@ -118,6 +118,27 @@ def test_bare_lf_header } end + def test_header_vt_ff_whitespace + msg = <<~HTTP + GET / HTTP/1.1\r + Foo: \x0b1\x0c\r + \r + HTTP + req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP) + req.parse(StringIO.new(msg.gsub(/^ {6}/, ""))) + assert_equal("\x0b1\x0c", req["Foo"]) + + msg = <<~HTTP + GET / HTTP/1.1\r + Foo: \x0b1\x0c\r + \x0b2\x0c\r + \r + HTTP + req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP) + req.parse(StringIO.new(msg.gsub(/^ {6}/, ""))) + assert_equal("\x0b1\x0c \x0b2\x0c", req["Foo"]) + end + def test_bare_cr_request_line msg = <<~HTTP.gsub("\n", "\r\n") GET / HTTP/1.1\r\r