From 459559a8bced28f25888802e40c7182392ea94cc Mon Sep 17 00:00:00 2001 From: Jamis Buck Date: Sat, 18 Mar 2006 05:07:27 +0000 Subject: [PATCH] XML-formatted requests are typecast according to "type" attributes for :xml_simple git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3915 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionpack/CHANGELOG | 2 + .../action_controller/cgi_ext/cgi_methods.rb | 44 ++++++++++++++- actionpack/test/controller/webservice_test.rb | 54 ++++++++++++++++++- 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 609cdf0bd5349..014287b9243cc 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* XML-formatted requests are typecast according to "type" attributes for :xml_simple [Jamis Buck] + * Added protection against proxy setups treating requests as local even when they're not #3898 [stephen_purcell@yahoo.com] * Added TestRequest#raw_post that simulate raw_post from CgiRequest #3042 [francois.beausoleil@gmail.com] diff --git a/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb b/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb index 776f74a10068d..f19e70839da58 100755 --- a/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb +++ b/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb @@ -63,7 +63,11 @@ def self.parse_formatted_request_parameters(mime_type, raw_post_data) when Proc strategy.call(raw_post_data) when :xml_simple - XmlSimple.xml_in(raw_post_data, 'ForceArray' => false, 'keeproot' => true) + typecast_xml_value(XmlSimple.xml_in(raw_post_data, + 'forcearray' => false, + 'forcecontent' => true, + 'keeproot' => true, + 'contentkey' => '__content__')) when :yaml YAML.load(raw_post_data) when :xml_node @@ -77,8 +81,46 @@ def self.parse_formatted_request_parameters(mime_type, raw_post_data) "raw_post_data" => raw_post_data, "format" => mime_type } end + def self.typecast_xml_value(value) + case value + when Hash + if value.has_key?("__content__") + content = translate_xml_entities(value["__content__"]) + case value["type"] + when "integer" then content.to_i + when "boolean" then content == "true" + when "datetime" then Time.parse(content) + when "date" then Date.parse(content) + else content + end + else + value.empty? ? nil : value.inject({}) do |h,(k,v)| + h[k] = typecast_xml_value(v) + h + end + end + when Array + value.map! { |i| typecast_xml_value(i) } + case value.length + when 0 then nil + when 1 then value.first + else value + end + else + raise "can't typecast #{value.inspect}" + end + end + private + def self.translate_xml_entities(value) + value.gsub(/</, "<"). + gsub(/>/, ">"). + gsub(/"/, '"'). + gsub(/'/, "'"). + gsub(/&/, "&") + end + def self.dasherize_keys(params) case params.class.to_s when "Hash" diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb index 90691e9e9cddc..d49f6e79415fd 100644 --- a/actionpack/test/controller/webservice_test.rb +++ b/actionpack/test/controller/webservice_test.rb @@ -106,14 +106,66 @@ def test_dasherized_keys_as_xml ActionController::Base.param_parsers[Mime::XML] = :xml_simple process('POST', 'application/xml', "\n...\n", true) assert_equal 'action, controller, first_key(sub_key), full', @controller.response.body + assert_equal "...", @controller.params[:first_key][:sub_key] + end + + def test_typecast_as_xml + ActionController::Base.param_parsers[Mime::XML] = :xml_simple + process('POST', 'application/xml', <<-XML) + + 15 + false + true + 2005-03-17 + 2005-03-17T21:41:07Z + unparsed + 1 + hello + 1974-07-25 + + XML + params = @controller.params + assert_equal 15, params[:data][:a] + assert_equal false, params[:data][:b] + assert_equal true, params[:data][:c] + assert_equal Date.new(2005,3,17), params[:data][:d] + assert_equal Time.utc(2005,3,17,21,41,7), params[:data][:e] + assert_equal "unparsed", params[:data][:f] + assert_equal [1, "hello", Date.new(1974,7,25)], params[:data][:g] end def test_dasherized_keys_as_yaml ActionController::Base.param_parsers[Mime::YAML] = :yaml process('POST', 'application/x-yaml', "---\nfirst-key:\n sub-key: ...\n", true) assert_equal 'action, controller, first_key(sub_key), full', @controller.response.body + assert_equal "...", @controller.params[:first_key][:sub_key] + end + + def test_typecast_as_yaml + ActionController::Base.param_parsers[Mime::YAML] = :yaml + process('POST', 'application/x-yaml', <<-YAML) + --- + data: + a: 15 + b: false + c: true + d: 2005-03-17 + e: 2005-03-17T21:41:07Z + f: unparsed + g: + - 1 + - hello + - 1974-07-25 + YAML + params = @controller.params + assert_equal 15, params[:data][:a] + assert_equal false, params[:data][:b] + assert_equal true, params[:data][:c] + assert_equal Date.new(2005,3,17), params[:data][:d] + assert_equal Time.utc(2005,3,17,21,41,7), params[:data][:e] + assert_equal "unparsed", params[:data][:f] + assert_equal [1, "hello", Date.new(1974,7,25)], params[:data][:g] end - private