Permalink
Browse files

Merge pull request #5606 from teohm/multipart_unicode_param_name

multipart POST - utf8 param name not encoded
  • Loading branch information...
2 parents a662a78 + b307210 commit 29030d3f89298905acc782df89b758d163dcf630 @steveklabnik steveklabnik committed Mar 15, 2013
@@ -18,7 +18,7 @@ def parameters
query_parameters.dup
end
params.merge!(path_parameters)
- encode_params(params).with_indifferent_access
+ params.with_indifferent_access
end
end
alias :params :parameters
@@ -50,40 +50,33 @@ def reset_parameters #:nodoc:
private
+ # Convert nested Hash to HashWithIndifferentAccess
+ # and UTF-8 encode both keys and values in nested Hash.
+ #
# TODO: Validate that the characters are UTF-8. If they aren't,
# you'll get a weird error down the road, but our form handling
# should really prevent that from happening
- def encode_params(params)
+ def normalize_encode_params(params)
if params.is_a?(String)
return params.force_encoding(Encoding::UTF_8).encode!
elsif !params.is_a?(Hash)
return params
end
- params.each_value do |v|
- case v
- when Hash
- encode_params(v)
- when Array
- v.map! {|el| encode_params(el) }
- else
- encode_params(v)
- end
- end
- end
-
- # Convert nested Hash to ActiveSupport::HashWithIndifferentAccess
- def normalize_parameters(value)
- case value
- when Hash
- h = {}
- value.each { |k, v| h[k] = normalize_parameters(v) }
- h.with_indifferent_access
- when Array
- value.map { |e| normalize_parameters(e) }
- else
- value
+ new_hash = {}
+ params.each do |k, v|
+ new_key = k.is_a?(String) ? k.dup.force_encoding("UTF-8").encode! : k
+ new_hash[new_key] =
+ case v
+ when Hash
+ normalize_encode_params(v)
+ when Array
+ v.map! {|el| normalize_encode_params(el) }
+ else
+ normalize_encode_params(v)
+ end
end
+ new_hash.with_indifferent_access
end
end
end
@@ -273,15 +273,15 @@ def session_options=(options)
# Override Rack's GET method to support indifferent access
def GET
- @env["action_dispatch.request.query_parameters"] ||= (normalize_parameters(super) || {})
+ @env["action_dispatch.request.query_parameters"] ||= (normalize_encode_params(super) || {})
rescue TypeError => e
raise ActionController::BadRequest.new(:query, e)
end
alias :query_parameters :GET
# Override Rack's POST method to support indifferent access
def POST
- @env["action_dispatch.request.request_parameters"] ||= (normalize_parameters(super) || {})
+ @env["action_dispatch.request.request_parameters"] ||= (normalize_encode_params(super) || {})
rescue TypeError => e
raise ActionController::BadRequest.new(:request, e)
end
@@ -75,16 +75,16 @@ def encode_filename(filename)
end
module Upload # :nodoc:
- # Convert nested Hash to ActiveSupport::HashWithIndifferentAccess and replace
- # file upload hash with UploadedFile objects
- def normalize_parameters(value)
+ # Replace file upload hash with UploadedFile objects
+ # when normalize and encode parameters.
+ def normalize_encode_params(value)
if Hash === value && value.has_key?(:tempfile)
UploadedFile.new(value)
else
super
end
end
- private :normalize_parameters
+ private :normalize_encode_params
end
end
end
@@ -1,13 +1,15 @@
+# encoding: utf-8
require 'abstract_unit'
class MultipartParamsParsingTest < ActionDispatch::IntegrationTest
class TestController < ActionController::Base
class << self
- attr_accessor :last_request_parameters
+ attr_accessor :last_request_parameters, :last_parameters
end
def parse
self.class.last_request_parameters = request.request_parameters
+ self.class.last_parameters = request.parameters
head :ok
end
@@ -30,6 +32,23 @@ def teardown
assert_equal({ 'foo' => { 'baz' => 'bar'}}, parse_multipart('bracketed_param'))
end
+ test "parse single utf8 parameter" do
+ assert_equal({ 'Iñtërnâtiônàlizætiøn_name' => 'Iñtërnâtiônàlizætiøn_value'},
+ parse_multipart('single_utf8_param'), "request.request_parameters")
+ assert_equal(
+ 'Iñtërnâtiônàlizætiøn_value',
+ TestController.last_parameters['Iñtërnâtiônàlizætiøn_name'], "request.parameters")
+ end
+
+ test "parse bracketed utf8 parameter" do
+ assert_equal({ 'Iñtërnâtiônàlizætiøn_name' => {
+ 'Iñtërnâtiônàlizætiøn_nested_name' => 'Iñtërnâtiônàlizætiøn_value'} },
+ parse_multipart('bracketed_utf8_param'), "request.request_parameters")
+ assert_equal(
+ {'Iñtërnâtiônàlizætiøn_nested_name' => 'Iñtërnâtiônàlizætiøn_value'},
+ TestController.last_parameters['Iñtërnâtiônàlizætiøn_name'], "request.parameters")
+ end
+
test "parses text file" do
params = parse_multipart('text_file')
assert_equal %w(file foo), params.keys.sort
@@ -0,0 +1,5 @@
+--AaB03x
+Content-Disposition: form-data; name="Iñtërnâtiônàlizætiøn_name[Iñtërnâtiônàlizætiøn_nested_name]"
+
+Iñtërnâtiônàlizætiøn_value
+--AaB03x--
@@ -0,0 +1,5 @@
+--AaB03x
+Content-Disposition: form-data; name="Iñtërnâtiônàlizætiøn_name"
+
+Iñtërnâtiônàlizætiøn_value
+--AaB03x--

0 comments on commit 29030d3

Please sign in to comment.