Browse files

Multipart form values may have a content type without being treated a…

…s uploaded files if they do not provide a filename. Closes #6401.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@5473 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
1 parent d3100ec commit 0342393b30e46a5a6433420e9e1b192ec65f8a11 @jeremy jeremy committed Nov 9, 2006
Showing with 47 additions and 37 deletions.
  1. +39 −32 actionpack/lib/action_controller/cgi_ext/cgi_methods.rb
  2. +8 −5 actionpack/test/controller/cgi_test.rb
View
71 actionpack/lib/action_controller/cgi_ext/cgi_methods.rb
@@ -63,43 +63,50 @@ def parse_formatted_request_parameters(mime_type, raw_post_data)
private
def get_typed_value(value)
- # test most frequent case first
- if value.is_a?(String)
- value
- elsif value.respond_to?(:content_type) && ! value.content_type.blank?
- # Uploaded file
- unless value.respond_to?(:full_original_filename)
- class << value
- alias_method :full_original_filename, :original_filename
+ case value
+ when String
+ value
+ when NilClass
+ ''
+ when Array
+ value.map { |v| get_typed_value(v) }
+ else
+ # Uploaded file provides content type and filename.
+ if value.respond_to?(:content_type) &&
+ !value.content_type.blank? &&
+ !value.original_filename.blank?
+ unless value.respond_to?(:full_original_filename)
+ class << value
+ alias_method :full_original_filename, :original_filename
- # Take the basename of the upload's original filename.
- # This handles the full Windows paths given by Internet Explorer
- # (and perhaps other broken user agents) without affecting
- # those which give the lone filename.
- # The Windows regexp is adapted from Perl's File::Basename.
- def original_filename
- if md = /^(?:.*[:\\\/])?(.*)/m.match(full_original_filename)
- md.captures.first
- else
- File.basename full_original_filename
+ # Take the basename of the upload's original filename.
+ # This handles the full Windows paths given by Internet Explorer
+ # (and perhaps other broken user agents) without affecting
+ # those which give the lone filename.
+ # The Windows regexp is adapted from Perl's File::Basename.
+ def original_filename
+ if md = /^(?:.*[:\\\/])?(.*)/m.match(full_original_filename)
+ md.captures.first
+ else
+ File.basename full_original_filename
+ end
+ end
end
end
- end
- end
- # Return the same value after overriding original_filename.
- value
+ # Return the same value after overriding original_filename.
+ value
- elsif value.respond_to?(:read)
- # Value as part of a multipart request
- result = value.read
- value.rewind
- result
- elsif value.class == Array
- value.collect { |v| get_typed_value(v) }
- else
- # other value (neither string nor a multipart request)
- value.to_s
+ # Multipart values may have content type, but no filename.
+ elsif value.respond_to?(:read)
+ result = value.read
+ value.rewind
+ result
+
+ # Unknown value, neither string nor multipart.
+ else
+ raise "Unknown form value: #{value.inspect}"
+ end
end
end
end
View
13 actionpack/test/controller/cgi_test.rb
@@ -155,9 +155,10 @@ def test_parse_params
end
def test_parse_params_from_multipart_upload
- mockup = Struct.new(:content_type, :original_filename)
+ mockup = Struct.new(:content_type, :original_filename, :read, :rewind)
file = mockup.new('img/jpeg', 'foo.jpg')
ie_file = mockup.new('img/jpeg', 'c:\\Documents and Settings\\foo\\Desktop\\bar.jpg')
+ non_file_text_part = mockup.new('text/plain', '', 'abc')
input = {
"something" => [ StringIO.new("") ],
@@ -168,9 +169,10 @@ def test_parse_params_from_multipart_upload
"products[string]" => [ StringIO.new("Apple Computer") ],
"products[file]" => [ file ],
"ie_products[string]" => [ StringIO.new("Microsoft") ],
- "ie_products[file]" => [ ie_file ]
+ "ie_products[file]" => [ ie_file ],
+ "text_part" => [non_file_text_part]
}
-
+
expected_output = {
"something" => "",
"array_of_stringios" => ["One", "Two"],
@@ -192,7 +194,8 @@ def test_parse_params_from_multipart_upload
"ie_products" => {
"string" => "Microsoft",
"file" => ie_file
- }
+ },
+ "text_part" => "abc"
}
params = CGIMethods.parse_request_parameters(input)
@@ -338,7 +341,7 @@ def test_mixed_files
assert_equal 'bar', params['foo']
# Ruby CGI doesn't handle multipart/mixed for us.
- assert_kind_of StringIO, params['files']
+ assert_kind_of String, params['files']
assert_equal 19756, params['files'].size
end

0 comments on commit 0342393

Please sign in to comment.