Skip to content

Commit 6674f36

Browse files
eTMleahneukirchen
authored andcommitted
better multipart handling
1 parent 3690709 commit 6674f36

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

lib/rack/request.rb

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ def head?; request_method == "HEAD" end
9292
'multipart/form-data'
9393
]
9494

95+
# The set of media-types. Requests that do not indicate
96+
# one of the media types presents in this list will not be eligible
97+
# for param parsing like soap attachments or generic multiparts
98+
PARSEABLE_DATA_MEDIA_TYPES = [
99+
'multipart/related',
100+
'multipart/mixed'
101+
]
102+
95103
# Determine whether the request body contains form-data by checking
96104
# the request media_type against registered form-data media-types:
97105
# "application/x-www-form-urlencoded" and "multipart/form-data". The
@@ -101,6 +109,12 @@ def form_data?
101109
FORM_DATA_MEDIA_TYPES.include?(media_type)
102110
end
103111

112+
# Determine whether the request body contains data by checking
113+
# the request media_type against registered parse-data media-types
114+
def parseable_data?
115+
PARSEABLE_DATA_MEDIA_TYPES.include?(media_type)
116+
end
117+
104118
# Returns the data recieved in the query string.
105119
def GET
106120
if @env["rack.request.query_string"] == query_string
@@ -119,7 +133,7 @@ def GET
119133
def POST
120134
if @env["rack.request.form_input"].eql? @env["rack.input"]
121135
@env["rack.request.form_hash"]
122-
elsif form_data?
136+
elsif form_data? || parseable_data?
123137
@env["rack.request.form_input"] = @env["rack.input"]
124138
unless @env["rack.request.form_hash"] =
125139
Utils::Multipart.parse_multipart(env)

lib/rack/utils.rb

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ module Multipart
293293

294294
def self.parse_multipart(env)
295295
unless env['CONTENT_TYPE'] =~
296-
%r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n
296+
%r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
297297
nil
298298
else
299299
boundary = "--#{$1}"
@@ -319,15 +319,15 @@ def self.parse_multipart(env)
319319
filename = content_type = name = nil
320320

321321
until head && buf =~ rx
322-
if !head && i = buf.index("\r\n\r\n")
322+
if !head && i = buf.index(EOL+EOL)
323323
head = buf.slice!(0, i+2) # First \r\n
324324
buf.slice!(0, 2) # Second \r\n
325325

326326
filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1]
327-
content_type = head[/Content-Type: (.*)\r\n/ni, 1]
328-
name = head[/Content-Disposition:.* name="?([^\";]*)"?/ni, 1]
327+
content_type = head[/Content-Type: (.*)#{EOL}/ni, 1]
328+
name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1]
329329

330-
if filename
330+
if content_type || filename
331331
body = Tempfile.new("RackMultipart")
332332
body.binmode if body.respond_to?(:binmode)
333333
end
@@ -369,6 +369,12 @@ def self.parse_multipart(env)
369369

370370
data = {:filename => filename, :type => content_type,
371371
:name => name, :tempfile => body, :head => head}
372+
elsif !filename && content_type
373+
body.rewind
374+
375+
# Generic multipart cases, not coming from a form
376+
data = {:type => content_type,
377+
:name => name, :tempfile => body, :head => head}
372378
else
373379
data = body
374380
end

0 commit comments

Comments
 (0)