Skip to content

Commit

Permalink
Merge pull request #943 from ggrossman/fix_name_token_at_eol
Browse files Browse the repository at this point in the history
Fix bug in parsing of Content-Disposition header where an unquoted name at end-of-line sucked in the trailing newline
  • Loading branch information
tenderlove committed Sep 24, 2015
2 parents a791217 + e424251 commit 7cb2ed4
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lib/rack/multipart.rb
Expand Up @@ -17,7 +17,7 @@ module Multipart
BROKEN_QUOTED = /^#{CONDISP}.*;\sfilename="(.*?)"(?:\s*$|\s*;\s*#{TOKEN}=)/i
BROKEN_UNQUOTED = /^#{CONDISP}.*;\sfilename=(#{TOKEN})/i
MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni
MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:.*\s+name="?([^\";]*)"?/ni
MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:.*\s+name=(#{VALUE})/ni
MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni
# Updated definitions from RFC 2231
ATTRIBUTE_CHAR = %r{[^ \t\v\n\r)(><@,;:\\"/\[\]?='*%]}
Expand Down
6 changes: 5 additions & 1 deletion lib/rack/multipart/parser.rb
Expand Up @@ -245,7 +245,11 @@ def handle_mime_head
@buf.slice!(0, 2) # Second \r\n

content_type = head[MULTIPART_CONTENT_TYPE, 1]
name = head[MULTIPART_CONTENT_DISPOSITION, 1] || head[MULTIPART_CONTENT_ID, 1]
if name = head[MULTIPART_CONTENT_DISPOSITION, 1]
name = Rack::Auth::Digest::Params::dequote(name)
else
name = head[MULTIPART_CONTENT_ID, 1]
end

filename = get_filename(head)

Expand Down
40 changes: 40 additions & 0 deletions test/spec_multipart.rb
Expand Up @@ -607,6 +607,46 @@ def initialize(*)
params["file"][:filename].must_equal 'long' * 100
end

it "parse unquoted parameter values at end of line" do
data = <<-EOF
--AaB03x\r
Content-Type: text/plain\r
Content-Disposition: attachment; name=inline\r
\r
true\r
--AaB03x--\r
EOF

options = {
"CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
"CONTENT_LENGTH" => data.length.to_s,
:input => StringIO.new(data)
}
env = Rack::MockRequest.env_for("/", options)
params = Rack::Multipart.parse_multipart(env)
params["inline"].must_equal 'true'
end

it "parse quoted chars in name parameter" do
data = <<-EOF
--AaB03x\r
Content-Type: text/plain\r
Content-Disposition: attachment; name="quoted\\\\chars\\"in\rname"\r
\r
true\r
--AaB03x--\r
EOF

options = {
"CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
"CONTENT_LENGTH" => data.length.to_s,
:input => StringIO.new(data)
}
env = Rack::MockRequest.env_for("/", options)
params = Rack::Multipart.parse_multipart(env)
params["quoted\\chars\"in\rname"].must_equal 'true'
end

it "support mixed case metadata" do
file = multipart_file(:text)
data = File.open(file, 'rb') { |io| io.read }
Expand Down

0 comments on commit 7cb2ed4

Please sign in to comment.