pax_global_header00006660000000000000000000000064125142734230014515gustar00rootroot0000000000000052 comment=405522d3acd6ce850f484d12a7b971c79662d27a actionpack-xml_parser-1.0.2/000077500000000000000000000000001251427342300160035ustar00rootroot00000000000000actionpack-xml_parser-1.0.2/.gitignore000066400000000000000000000002241251427342300177710ustar00rootroot00000000000000*.gem *.rbc .bundle .config .yardoc *.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp actionpack-xml_parser-1.0.2/.travis.yml000066400000000000000000000006551251427342300201220ustar00rootroot00000000000000language: ruby sudo: false rvm: - 1.9 - 2.0 - 2.1 - 2.2 - ruby-head gemfile: - gemfiles/Gemfile-edge - Gemfile notifications: email: false before_install: - gem install bundler matrix: fast_finish: true allow_failures: - rvm: ruby-head exclude: - rvm: 1.9 gemfile: gemfiles/Gemfile-edge - rvm: 2.0 gemfile: gemfiles/Gemfile-edge - rvm: 2.1 gemfile: gemfiles/Gemfile-edge actionpack-xml_parser-1.0.2/Gemfile000066400000000000000000000000471251427342300172770ustar00rootroot00000000000000source 'https://rubygems.org' gemspec actionpack-xml_parser-1.0.2/LICENSE000066400000000000000000000020621251427342300170100ustar00rootroot00000000000000Copyright (c) 2013 Prem Sichanugrist MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. actionpack-xml_parser-1.0.2/README.md000066400000000000000000000011721251427342300172630ustar00rootroot00000000000000actionpack-xml\_parser ====================== A XML parameters parser for Action Pack (removed from core in Rails 4.0) Installation ------------ Include this gem into your Gemfile: ```ruby gem 'actionpack-xml_parser' ``` Then, add `ActionDispatch::XmlParamsParser` middleware after `ActionDispatch::ParamsParser` in `config/application.rb`: ```ruby config.middleware.insert_after ActionDispatch::ParamsParser, ActionDispatch::XmlParamsParser ``` You may need to require the `ActionDispatch::XmlParamsParser` manually. Add the following in your `config/application.rb`: ```ruby require 'action_dispatch/xml_params_parser' ``` actionpack-xml_parser-1.0.2/Rakefile000066400000000000000000000003141251427342300174460ustar00rootroot00000000000000#!/usr/bin/env rake require "bundler/gem_tasks" require 'rake/testtask' Rake::TestTask.new do |t| t.libs = ["test"] t.pattern = "test/**/*_test.rb" t.ruby_opts = ['-w'] end task :default => :test actionpack-xml_parser-1.0.2/actionpack-xml_parser.gemspec000066400000000000000000000012471251427342300236420ustar00rootroot00000000000000Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'actionpack-xml_parser' s.version = '1.0.2' s.summary = 'XML parameters parser for Action Pack (removed from core in Rails 4.0)' s.required_ruby_version = '>= 1.9.3' s.license = 'MIT' s.author = 'Prem Sichanugrist' s.email = 's@sikac.hu' s.homepage = 'http://www.rubyonrails.org' s.files = Dir['LICENSE', 'README.md', 'lib/**/*'] s.require_path = 'lib' s.extra_rdoc_files = %w( README.md ) s.rdoc_options.concat ['--main', 'README.md'] s.add_dependency('actionpack', '>= 4.0.0', '< 5') s.add_development_dependency('rake') end actionpack-xml_parser-1.0.2/gemfiles/000077500000000000000000000000001251427342300175765ustar00rootroot00000000000000actionpack-xml_parser-1.0.2/gemfiles/Gemfile-edge000066400000000000000000000001551251427342300217740ustar00rootroot00000000000000source 'https://rubygems.org' gemspec path: '..' gem 'actionpack', github: 'rails/rails', branch: 'master' actionpack-xml_parser-1.0.2/lib/000077500000000000000000000000001251427342300165515ustar00rootroot00000000000000actionpack-xml_parser-1.0.2/lib/action_dispatch/000077500000000000000000000000001251427342300217055ustar00rootroot00000000000000actionpack-xml_parser-1.0.2/lib/action_dispatch/xml_params_parser.rb000066400000000000000000000031541251427342300257540ustar00rootroot00000000000000require 'active_support/core_ext/hash/conversions' require 'action_dispatch/http/request' require 'active_support/core_ext/hash/indifferent_access' module ActionDispatch class XmlParamsParser def initialize(app) @app = app end def call(env) if params = parse_formatted_parameters(env) env["action_dispatch.request.request_parameters"] = params end @app.call(env) end private def parse_formatted_parameters(env) request = Request.new(env) return false if request.content_length.zero? mime_type = content_type_from_legacy_post_data_format_header(env) || request.content_mime_type if mime_type == Mime::XML # Rails 4.1 moved #deep_munge out of the request and into ActionDispatch::Request::Utils munger = defined?(Request::Utils) ? Request::Utils : request data = munger.deep_munge(Hash.from_xml(request.body.read) || {}) request.body.rewind if request.body.respond_to?(:rewind) data.with_indifferent_access else false end rescue Exception => e # XML code block errors logger(env).debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}" raise ActionDispatch::ParamsParser::ParseError.new(e.message, e) end def content_type_from_legacy_post_data_format_header(env) if env['HTTP_X_POST_DATA_FORMAT'].to_s.downcase == 'xml' Mime::XML end end def logger(env) env['action_dispatch.logger'] || ActiveSupport::Logger.new($stderr) end end end actionpack-xml_parser-1.0.2/lib/actionpack/000077500000000000000000000000001251427342300206655ustar00rootroot00000000000000actionpack-xml_parser-1.0.2/lib/actionpack/xml_parser.rb000066400000000000000000000000541251427342300233650ustar00rootroot00000000000000require 'action_dispatch/xml_params_parser' actionpack-xml_parser-1.0.2/test/000077500000000000000000000000001251427342300167625ustar00rootroot00000000000000actionpack-xml_parser-1.0.2/test/fixtures/000077500000000000000000000000001251427342300206335ustar00rootroot00000000000000actionpack-xml_parser-1.0.2/test/fixtures/500.html000066400000000000000000000000221251427342300220170ustar00rootroot00000000000000500 error fixture actionpack-xml_parser-1.0.2/test/helper.rb000066400000000000000000000047721251427342300206000ustar00rootroot00000000000000require 'bundler/setup' require 'active_support/testing/autorun' require 'action_controller' require 'action_dispatch' require 'action_dispatch/xml_params_parser' FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures') SharedTestRoutes = ActionDispatch::Routing::RouteSet.new module ActionDispatch module SharedRoutes def before_setup @routes = SharedTestRoutes super end end end class RoutedRackApp attr_reader :routes def initialize(routes, &blk) @routes = routes @stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes) end def call(env) @stack.call(env) end end class ActionDispatch::IntegrationTest < ActiveSupport::TestCase include ActionDispatch::SharedRoutes def self.build_app(routes = nil) RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware| middleware.use "ActionDispatch::ShowExceptions", ActionDispatch::PublicExceptions.new(FIXTURE_LOAD_PATH) middleware.use "ActionDispatch::ParamsParser" middleware.use "ActionDispatch::XmlParamsParser" middleware.use "Rack::Head" yield(middleware) if block_given? end end self.app = build_app # Stub Rails dispatcher so it does not get controller references and # simply return the controller#action as Rack::Body. class StubDispatcher < ::ActionDispatch::Routing::RouteSet::Dispatcher protected def controller_reference(controller_param) controller_param end def dispatch(controller, action, env) [200, {'Content-Type' => 'text/html'}, ["#{controller}##{action}"]] end end def self.stub_controllers old_dispatcher = ActionDispatch::Routing::RouteSet::Dispatcher ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher } ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, StubDispatcher } yield ActionDispatch::Routing::RouteSet.new ensure ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher } ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, old_dispatcher } end def with_routing(&block) temporary_routes = ActionDispatch::Routing::RouteSet.new old_app, self.class.app = self.class.app, self.class.build_app(temporary_routes) old_routes = SharedTestRoutes silence_warnings { Object.const_set(:SharedTestRoutes, temporary_routes) } yield temporary_routes ensure self.class.app = old_app silence_warnings { Object.const_set(:SharedTestRoutes, old_routes) } end end actionpack-xml_parser-1.0.2/test/webservice_test.rb000066400000000000000000000160651251427342300225140ustar00rootroot00000000000000require 'helper' class WebServiceTest < ActionDispatch::IntegrationTest class TestController < ActionController::Base def assign_parameters if params[:full] render :text => dump_params_keys else render :text => (params.keys - ['controller', 'action']).sort.join(", ") end end def dump_params_keys(hash = params) hash.keys.sort.inject("") do |s, k| value = hash[k] value = Hash === value ? "(#{dump_params_keys(value)})" : "" s << ", " unless s.empty? s << "#{k}#{value}" end end end def setup @controller = TestController.new @integration_session = nil end def test_check_parameters with_test_route_set do get "/" assert_equal '', @controller.response.body end end def test_post_xml with_test_route_set do post "/", 'content...', {'CONTENT_TYPE' => 'application/xml'} assert_equal 'entry', @controller.response.body assert @controller.params.has_key?(:entry) assert_equal 'content...', @controller.params["entry"]['summary'] assert_equal 'true', @controller.params["entry"]['attributed'] end end def test_put_xml with_test_route_set do put "/", 'content...', {'CONTENT_TYPE' => 'application/xml'} assert_equal 'entry', @controller.response.body assert @controller.params.has_key?(:entry) assert_equal 'content...', @controller.params["entry"]['summary'] assert_equal 'true', @controller.params["entry"]['attributed'] end end def test_put_xml_using_a_type_node with_test_route_set do put "/", 'content...', {'CONTENT_TYPE' => 'application/xml'} assert_equal 'type', @controller.response.body assert @controller.params.has_key?(:type) assert_equal 'content...', @controller.params["type"]['summary'] assert_equal 'true', @controller.params["type"]['attributed'] end end def test_put_xml_using_a_type_node_and_attribute with_test_route_set do put "/", 'false', {'CONTENT_TYPE' => 'application/xml'} assert_equal 'type', @controller.response.body assert @controller.params.has_key?(:type) assert_equal false, @controller.params["type"]['summary'] assert_equal 'true', @controller.params["type"]['attributed'] end end def test_post_xml_using_a_type_node with_test_route_set do post "/", 'arial', {'CONTENT_TYPE' => 'application/xml'} assert_equal 'font', @controller.response.body assert @controller.params.has_key?(:font) assert_equal 'arial', @controller.params['font']['type'] assert_equal 'true', @controller.params["font"]['attributed'] end end def test_post_xml_using_a_root_node_named_type with_test_route_set do post "/", '33', {'CONTENT_TYPE' => 'application/xml'} assert @controller.params.has_key?(:type) assert_equal 33, @controller.params['type'] end end def test_post_xml_using_an_attributted_node_named_type with_test_route_set do with_params_parsers Mime::XML => Proc.new { |data| Hash.from_xml(data)['request'].with_indifferent_access } do post "/", 'Arial,123', {'CONTENT_TYPE' => 'application/xml'} assert_equal 'type, z', @controller.response.body assert @controller.params.has_key?(:type) assert_equal 'Arial,12', @controller.params['type'], @controller.params.inspect assert_equal '3', @controller.params['z'], @controller.params.inspect end end end def test_post_xml_using_a_disallowed_type_attribute $stderr = StringIO.new with_test_route_set do post '/', 'value', 'CONTENT_TYPE' => 'application/xml' assert_response 400 post '/', 'value', 'CONTENT_TYPE' => 'application/xml' assert_response 400 end ensure $stderr = STDERR end def test_register_and_use_xml_simple with_test_route_set do with_params_parsers Mime::XML => Proc.new { |data| Hash.from_xml(data)['request'].with_indifferent_access } do post "/", 'content...SimpleXml', {'CONTENT_TYPE' => 'application/xml'} assert_equal 'summary, title', @controller.response.body assert @controller.params.has_key?(:summary) assert @controller.params.has_key?(:title) assert_equal 'content...', @controller.params["summary"] assert_equal 'SimpleXml', @controller.params["title"] end end end def test_use_xml_ximple_with_empty_request with_test_route_set do assert_nothing_raised { post "/", "", {'CONTENT_TYPE' => 'application/xml'} } assert_equal '', @controller.response.body end end def test_dasherized_keys_as_xml with_test_route_set do post "/?full=1", "\n...\n", {'CONTENT_TYPE' => 'application/xml'} assert_equal 'action, controller, first_key(sub_key), full', @controller.response.body assert_equal "...", @controller.params[:first_key][:sub_key] end end def test_typecast_as_xml with_test_route_set do xml = <<-XML 15 false true 2005-03-17 2005-03-17T21:41:07Z unparsed 1 hello 1974-07-25 XML post "/", xml, {'CONTENT_TYPE' => 'application/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 end def test_entities_unescaped_as_xml_simple with_test_route_set do xml = <<-XML <foo "bar's" & friends> XML post "/", xml, {'CONTENT_TYPE' => 'application/xml'} assert_equal %(), @controller.params[:data] end end private def with_params_parsers(parsers = {}) old_session = @integration_session @app = ActionDispatch::ParamsParser.new(app.routes, parsers) reset! yield ensure @integration_session = old_session end def with_test_route_set with_routing do |set| set.draw do match '/', :to => 'web_service_test/test#assign_parameters', :via => :all end yield end end end actionpack-xml_parser-1.0.2/test/xml_params_parsing_test.rb000066400000000000000000000146761251427342300242520ustar00rootroot00000000000000require 'helper' class XmlParamsParsingTest < ActionDispatch::IntegrationTest class TestController < ActionController::Base class << self attr_accessor :last_request_parameters attr_accessor :last_request end def parse self.class.last_request_parameters = request.request_parameters self.class.last_request = request head :ok end end def teardown TestController.last_request_parameters = nil TestController.last_request = nil end test "parses a strict rack.input" do class Linted undef call if method_defined?(:call) def call(env) bar = env['action_dispatch.request.request_parameters']['foo'] result = "#{bar}" [200, {"Content-Type" => "application/xml", "Content-Length" => result.length.to_s}, [result]] end end req = Rack::MockRequest.new(ActionDispatch::XmlParamsParser.new(Linted.new)) resp = req.post('/', "CONTENT_TYPE" => "application/xml", :input => "bar", :lint => true) assert_equal "bar", resp.body end def assert_parses(expected, xml) with_test_routing do post "/parse", xml, default_headers assert_response :ok assert_equal(expected, TestController.last_request_parameters) end end test "nils are stripped from collections" do if ActiveSupport::VERSION::MAJOR >= 5 # Rails 5 changes the behavior of #deep_munge for security reason. # https://github.com/rails/rails/pull/16924 assert_parses( {"hash" => { "person" => []} }, "") else assert_parses( {"hash" => { "person" => nil} }, "") end assert_parses( {"hash" => { "person" => ['foo']} }, "foo\n") end test "parses hash params" do with_test_routing do xml = "David" post "/parse", xml, default_headers assert_response :ok assert_equal({"person" => {"name" => "David"}}, TestController.last_request_parameters) end end test "parses single file" do with_test_routing do xml = "David#{::Base64.encode64('ABC')}" post "/parse", xml, default_headers assert_response :ok person = TestController.last_request_parameters assert_equal "image/jpg", person['person']['avatar'].content_type assert_equal "me.jpg", person['person']['avatar'].original_filename assert_equal "ABC", person['person']['avatar'].read end end test "logs error if parsing unsuccessful" do with_test_routing do output = StringIO.new xml = "David#{::Base64.encode64('ABC')}" post "/parse", xml, default_headers.merge('action_dispatch.show_exceptions' => true, 'action_dispatch.logger' => ActiveSupport::Logger.new(output)) assert_response :bad_request output.rewind && err = output.read assert err =~ /Error occurred while parsing request parameters/ end end test "occurring a parse error if parsing unsuccessful" do with_test_routing do begin $stderr = StringIO.new # suppress the log xml = "David" exception = assert_raise(ActionDispatch::ParamsParser::ParseError) { post "/parse", xml, default_headers.merge('action_dispatch.show_exceptions' => false) } assert_equal REXML::ParseException, exception.original_exception.class assert_equal exception.original_exception.message, exception.message ensure $stderr = STDERR end end end test "parses multiple files" do xml = <<-end_body David #{::Base64.encode64('ABC')} #{::Base64.encode64('DEF')} end_body with_test_routing do post "/parse", xml, default_headers assert_response :ok end person = TestController.last_request_parameters assert_equal "image/jpg", person['person']['avatars']['avatar'].first.content_type assert_equal "me.jpg", person['person']['avatars']['avatar'].first.original_filename assert_equal "ABC", person['person']['avatars']['avatar'].first.read assert_equal "image/gif", person['person']['avatars']['avatar'].last.content_type assert_equal "you.gif", person['person']['avatars']['avatar'].last.original_filename assert_equal "DEF", person['person']['avatars']['avatar'].last.read end test "rewinds body if it implements rewind" do xml = "Marie" with_test_routing do post "/parse", xml, default_headers assert_equal TestController.last_request.body.read, xml end end private def with_test_routing with_routing do |set| set.draw do post ':action', :to => ::XmlParamsParsingTest::TestController end yield end end def default_headers {'CONTENT_TYPE' => 'application/xml'} end end class LegacyXmlParamsParsingTest < XmlParamsParsingTest private def default_headers {'HTTP_X_POST_DATA_FORMAT' => 'xml'} end end class RootLessXmlParamsParsingTest < ActionDispatch::IntegrationTest class TestController < ActionController::Base wrap_parameters :person, :format => :xml class << self attr_accessor :last_request_parameters end def parse self.class.last_request_parameters = request.request_parameters head :ok end end def teardown TestController.last_request_parameters = nil end test "parses hash params" do with_test_routing do xml = "David" post "/parse", xml, {'CONTENT_TYPE' => 'application/xml'} assert_response :ok assert_equal({"name" => "David", "person" => {"name" => "David"}}, TestController.last_request_parameters) end end private def with_test_routing with_routing do |set| set.draw do post ':action', :to => ::RootLessXmlParamsParsingTest::TestController end yield end end end