eactionpack 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +7 -0
- data/MIT-LICENSE +21 -0
- data/README +469 -0
- data/RUNNING_UNIT_TESTS +24 -0
- data/Rakefile +146 -0
- data/install.rb +30 -0
- data/lib/action_controller.rb +79 -0
- data/lib/action_controller/assertions.rb +69 -0
- data/lib/action_controller/assertions/dom_assertions.rb +39 -0
- data/lib/action_controller/assertions/model_assertions.rb +20 -0
- data/lib/action_controller/assertions/response_assertions.rb +172 -0
- data/lib/action_controller/assertions/routing_assertions.rb +146 -0
- data/lib/action_controller/assertions/selector_assertions.rb +491 -0
- data/lib/action_controller/assertions/tag_assertions.rb +130 -0
- data/lib/action_controller/base.rb +1288 -0
- data/lib/action_controller/benchmarking.rb +94 -0
- data/lib/action_controller/caching.rb +72 -0
- data/lib/action_controller/caching/actions.rb +144 -0
- data/lib/action_controller/caching/fragments.rb +138 -0
- data/lib/action_controller/caching/pages.rb +154 -0
- data/lib/action_controller/caching/sql_cache.rb +18 -0
- data/lib/action_controller/caching/sweeping.rb +97 -0
- data/lib/action_controller/cgi_ext.rb +16 -0
- data/lib/action_controller/cgi_ext/cookie.rb +110 -0
- data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
- data/lib/action_controller/cgi_ext/session.rb +73 -0
- data/lib/action_controller/cgi_ext/stdinput.rb +24 -0
- data/lib/action_controller/cgi_process.rb +223 -0
- data/lib/action_controller/components.rb +166 -0
- data/lib/action_controller/cookies.rb +96 -0
- data/lib/action_controller/dispatcher.rb +162 -0
- data/lib/action_controller/filters.rb +642 -0
- data/lib/action_controller/flash.rb +172 -0
- data/lib/action_controller/headers.rb +31 -0
- data/lib/action_controller/helpers.rb +221 -0
- data/lib/action_controller/http_authentication.rb +124 -0
- data/lib/action_controller/integration.rb +634 -0
- data/lib/action_controller/layout.rb +309 -0
- data/lib/action_controller/mime_responds.rb +173 -0
- data/lib/action_controller/mime_type.rb +186 -0
- data/lib/action_controller/mime_types.rb +20 -0
- data/lib/action_controller/polymorphic_routes.rb +191 -0
- data/lib/action_controller/record_identifier.rb +102 -0
- data/lib/action_controller/request.rb +764 -0
- data/lib/action_controller/request_forgery_protection.rb +140 -0
- data/lib/action_controller/request_profiler.rb +169 -0
- data/lib/action_controller/rescue.rb +258 -0
- data/lib/action_controller/resources.rb +572 -0
- data/lib/action_controller/response.rb +76 -0
- data/lib/action_controller/routing.rb +387 -0
- data/lib/action_controller/routing/builder.rb +203 -0
- data/lib/action_controller/routing/optimisations.rb +120 -0
- data/lib/action_controller/routing/recognition_optimisation.rb +162 -0
- data/lib/action_controller/routing/route.rb +240 -0
- data/lib/action_controller/routing/route_set.rb +436 -0
- data/lib/action_controller/routing/routing_ext.rb +46 -0
- data/lib/action_controller/routing/segments.rb +283 -0
- data/lib/action_controller/session/active_record_store.rb +340 -0
- data/lib/action_controller/session/cookie_store.rb +166 -0
- data/lib/action_controller/session/drb_server.rb +32 -0
- data/lib/action_controller/session/drb_store.rb +35 -0
- data/lib/action_controller/session/mem_cache_store.rb +98 -0
- data/lib/action_controller/session_management.rb +158 -0
- data/lib/action_controller/status_codes.rb +88 -0
- data/lib/action_controller/streaming.rb +155 -0
- data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
- data/lib/action_controller/templates/rescues/_trace.erb +26 -0
- data/lib/action_controller/templates/rescues/diagnostics.erb +11 -0
- data/lib/action_controller/templates/rescues/layout.erb +29 -0
- data/lib/action_controller/templates/rescues/missing_template.erb +2 -0
- data/lib/action_controller/templates/rescues/routing_error.erb +10 -0
- data/lib/action_controller/templates/rescues/template_error.erb +21 -0
- data/lib/action_controller/templates/rescues/unknown_action.erb +2 -0
- data/lib/action_controller/test_case.rb +83 -0
- data/lib/action_controller/test_process.rb +526 -0
- data/lib/action_controller/url_rewriter.rb +142 -0
- data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
- data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
- data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
- data/lib/action_controller/verification.rb +130 -0
- data/lib/action_pack.rb +24 -0
- data/lib/action_pack/version.rb +9 -0
- data/lib/action_view.rb +44 -0
- data/lib/action_view/base.rb +335 -0
- data/lib/action_view/helpers/active_record_helper.rb +276 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +599 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +143 -0
- data/lib/action_view/helpers/benchmark_helper.rb +33 -0
- data/lib/action_view/helpers/cache_helper.rb +40 -0
- data/lib/action_view/helpers/capture_helper.rb +161 -0
- data/lib/action_view/helpers/date_helper.rb +711 -0
- data/lib/action_view/helpers/debug_helper.rb +31 -0
- data/lib/action_view/helpers/form_helper.rb +767 -0
- data/lib/action_view/helpers/form_options_helper.rb +458 -0
- data/lib/action_view/helpers/form_tag_helper.rb +458 -0
- data/lib/action_view/helpers/javascript_helper.rb +148 -0
- data/lib/action_view/helpers/number_helper.rb +186 -0
- data/lib/action_view/helpers/record_identification_helper.rb +20 -0
- data/lib/action_view/helpers/record_tag_helper.rb +59 -0
- data/lib/action_view/helpers/sanitize_helper.rb +229 -0
- data/lib/action_view/helpers/tag_helper.rb +134 -0
- data/lib/action_view/helpers/text_helper.rb +507 -0
- data/lib/action_view/helpers/url_helper.rb +573 -0
- data/lib/action_view/inline_template.rb +20 -0
- data/lib/action_view/partial_template.rb +70 -0
- data/lib/action_view/partials.rb +158 -0
- data/lib/action_view/template.rb +125 -0
- data/lib/action_view/template_error.rb +110 -0
- data/lib/action_view/template_finder.rb +176 -0
- data/lib/action_view/template_handler.rb +34 -0
- data/lib/action_view/template_handlers/builder.rb +27 -0
- data/lib/action_view/template_handlers/compilable.rb +128 -0
- data/lib/action_view/template_handlers/erb.rb +56 -0
- data/lib/action_view/test_case.rb +58 -0
- data/lib/actionpack.rb +1 -0
- data/test/abstract_unit.rb +36 -0
- data/test/active_record_unit.rb +105 -0
- data/test/activerecord/active_record_store_test.rb +141 -0
- data/test/activerecord/render_partial_with_record_identification_test.rb +191 -0
- data/test/adv_attr_test.rb +20 -0
- data/test/controller/action_pack_assertions_test.rb +543 -0
- data/test/controller/addresses_render_test.rb +43 -0
- data/test/controller/assert_select_test.rb +331 -0
- data/test/controller/base_test.rb +219 -0
- data/test/controller/benchmark_test.rb +32 -0
- data/test/controller/caching_test.rb +581 -0
- data/test/controller/capture_test.rb +89 -0
- data/test/controller/cgi_test.rb +116 -0
- data/test/controller/components_test.rb +140 -0
- data/test/controller/content_type_test.rb +139 -0
- data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
- data/test/controller/cookie_test.rb +146 -0
- data/test/controller/custom_handler_test.rb +45 -0
- data/test/controller/deprecation/deprecated_base_methods_test.rb +37 -0
- data/test/controller/dispatcher_test.rb +105 -0
- data/test/controller/fake_controllers.rb +33 -0
- data/test/controller/fake_models.rb +11 -0
- data/test/controller/filter_params_test.rb +49 -0
- data/test/controller/filters_test.rb +881 -0
- data/test/controller/flash_test.rb +146 -0
- data/test/controller/header_test.rb +14 -0
- data/test/controller/helper_test.rb +210 -0
- data/test/controller/html-scanner/cdata_node_test.rb +15 -0
- data/test/controller/html-scanner/document_test.rb +148 -0
- data/test/controller/html-scanner/node_test.rb +89 -0
- data/test/controller/html-scanner/sanitizer_test.rb +269 -0
- data/test/controller/html-scanner/tag_node_test.rb +238 -0
- data/test/controller/html-scanner/text_node_test.rb +50 -0
- data/test/controller/html-scanner/tokenizer_test.rb +131 -0
- data/test/controller/http_authentication_test.rb +54 -0
- data/test/controller/integration_test.rb +252 -0
- data/test/controller/integration_upload_test.rb +43 -0
- data/test/controller/layout_test.rb +255 -0
- data/test/controller/mime_responds_test.rb +514 -0
- data/test/controller/mime_type_test.rb +84 -0
- data/test/controller/new_render_test.rb +843 -0
- data/test/controller/polymorphic_routes_test.rb +174 -0
- data/test/controller/record_identifier_test.rb +139 -0
- data/test/controller/redirect_test.rb +289 -0
- data/test/controller/render_test.rb +484 -0
- data/test/controller/request_forgery_protection_test.rb +305 -0
- data/test/controller/request_test.rb +928 -0
- data/test/controller/rescue_test.rb +517 -0
- data/test/controller/resources_test.rb +873 -0
- data/test/controller/routing_test.rb +2464 -0
- data/test/controller/selector_test.rb +628 -0
- data/test/controller/send_file_test.rb +138 -0
- data/test/controller/session/cookie_store_test.rb +258 -0
- data/test/controller/session/mem_cache_store_test.rb +181 -0
- data/test/controller/session_fixation_test.rb +89 -0
- data/test/controller/session_management_test.rb +178 -0
- data/test/controller/test_test.rb +695 -0
- data/test/controller/url_rewriter_test.rb +310 -0
- data/test/controller/verification_test.rb +270 -0
- data/test/controller/view_paths_test.rb +140 -0
- data/test/controller/webservice_test.rb +229 -0
- data/test/fixtures/addresses/list.erb +1 -0
- data/test/fixtures/bad_customers/_bad_customer.html.erb +1 -0
- data/test/fixtures/companies.yml +24 -0
- data/test/fixtures/company.rb +10 -0
- data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_js.js.erb +1 -0
- data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
- data/test/fixtures/customers/_customer.html.erb +1 -0
- data/test/fixtures/db_definitions/sqlite.sql +49 -0
- data/test/fixtures/developer.rb +9 -0
- data/test/fixtures/developers.yml +21 -0
- data/test/fixtures/developers_projects.yml +13 -0
- data/test/fixtures/fun/games/hello_world.erb +1 -0
- data/test/fixtures/functional_caching/_partial.erb +3 -0
- data/test/fixtures/functional_caching/fragment_cached.html.erb +2 -0
- data/test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb +1 -0
- data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +1 -0
- data/test/fixtures/good_customers/_good_customer.html.erb +1 -0
- data/test/fixtures/helpers/abc_helper.rb +5 -0
- data/test/fixtures/helpers/fun/games_helper.rb +3 -0
- data/test/fixtures/helpers/fun/pdf_helper.rb +3 -0
- data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/item.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/layout_test.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
- data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +1 -0
- data/test/fixtures/layout_tests/views/hello.rhtml +1 -0
- data/test/fixtures/layouts/block_with_layout.erb +3 -0
- data/test/fixtures/layouts/builder.builder +3 -0
- data/test/fixtures/layouts/partial_with_layout.erb +3 -0
- data/test/fixtures/layouts/standard.erb +1 -0
- data/test/fixtures/layouts/talk_from_action.erb +2 -0
- data/test/fixtures/layouts/yield.erb +2 -0
- data/test/fixtures/mascot.rb +3 -0
- data/test/fixtures/mascots.yml +4 -0
- data/test/fixtures/mascots/_mascot.html.erb +1 -0
- data/test/fixtures/multipart/binary_file +0 -0
- data/test/fixtures/multipart/boundary_problem_file +10 -0
- data/test/fixtures/multipart/bracketed_param +5 -0
- data/test/fixtures/multipart/large_text_file +10 -0
- data/test/fixtures/multipart/mixed_files +0 -0
- data/test/fixtures/multipart/mona_lisa.jpg +0 -0
- data/test/fixtures/multipart/single_parameter +5 -0
- data/test/fixtures/multipart/text_file +10 -0
- data/test/fixtures/override/test/hello_world.erb +1 -0
- data/test/fixtures/override2/layouts/test/sub.erb +1 -0
- data/test/fixtures/post_test/layouts/post.html.erb +1 -0
- data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
- data/test/fixtures/post_test/post/index.html.erb +1 -0
- data/test/fixtures/post_test/post/index.iphone.erb +1 -0
- data/test/fixtures/post_test/super_post/index.html.erb +1 -0
- data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
- data/test/fixtures/project.rb +3 -0
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/public/404.html +1 -0
- data/test/fixtures/public/500.html +1 -0
- data/test/fixtures/public/images/rails.png +0 -0
- data/test/fixtures/public/javascripts/application.js +1 -0
- data/test/fixtures/public/javascripts/bank.js +1 -0
- data/test/fixtures/public/javascripts/robber.js +1 -0
- data/test/fixtures/public/javascripts/version.1.0.js +1 -0
- data/test/fixtures/public/stylesheets/bank.css +1 -0
- data/test/fixtures/public/stylesheets/robber.css +1 -0
- data/test/fixtures/public/stylesheets/version.1.0.css +1 -0
- data/test/fixtures/replies.yml +15 -0
- data/test/fixtures/reply.rb +7 -0
- data/test/fixtures/respond_to/all_types_with_layout.html.erb +1 -0
- data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
- data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
- data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
- data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
- data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
- data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
- data/test/fixtures/respond_to/using_defaults.html.erb +1 -0
- data/test/fixtures/respond_to/using_defaults.js.rjs +1 -0
- data/test/fixtures/respond_to/using_defaults.xml.builder +1 -0
- data/test/fixtures/respond_to/using_defaults_with_type_list.html.erb +1 -0
- data/test/fixtures/respond_to/using_defaults_with_type_list.js.rjs +1 -0
- data/test/fixtures/respond_to/using_defaults_with_type_list.xml.builder +1 -0
- data/test/fixtures/scope/test/modgreet.erb +1 -0
- data/test/fixtures/shared.html.erb +1 -0
- data/test/fixtures/symlink_parent/symlinked_layout.erb +5 -0
- data/test/fixtures/test/_customer.erb +1 -0
- data/test/fixtures/test/_customer_counter.erb +1 -0
- data/test/fixtures/test/_customer_greeting.erb +1 -0
- data/test/fixtures/test/_form.erb +1 -0
- data/test/fixtures/test/_hash_greeting.erb +1 -0
- data/test/fixtures/test/_hash_object.erb +2 -0
- data/test/fixtures/test/_hello.builder +1 -0
- data/test/fixtures/test/_labelling_form.erb +1 -0
- data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
- data/test/fixtures/test/_partial.erb +1 -0
- data/test/fixtures/test/_partial.html.erb +1 -0
- data/test/fixtures/test/_partial.js.erb +1 -0
- data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
- data/test/fixtures/test/_partial_only.erb +1 -0
- data/test/fixtures/test/_person.erb +2 -0
- data/test/fixtures/test/_raise.html.erb +1 -0
- data/test/fixtures/test/action_talk_to_layout.erb +2 -0
- data/test/fixtures/test/block_content_for.erb +2 -0
- data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
- data/test/fixtures/test/capturing.erb +4 -0
- data/test/fixtures/test/content_for.erb +2 -0
- data/test/fixtures/test/content_for_concatenated.erb +3 -0
- data/test/fixtures/test/content_for_with_parameter.erb +2 -0
- data/test/fixtures/test/delete_with_js.rjs +2 -0
- data/test/fixtures/test/dot.directory/render_file_with_ivar.erb +1 -0
- data/test/fixtures/test/enum_rjs_test.rjs +6 -0
- data/test/fixtures/test/erb_content_for.erb +2 -0
- data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
- data/test/fixtures/test/formatted_xml_erb.builder +1 -0
- data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
- data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
- data/test/fixtures/test/greeting.erb +1 -0
- data/test/fixtures/test/greeting.js.rjs +1 -0
- data/test/fixtures/test/hello.builder +4 -0
- data/test/fixtures/test/hello_world.erb +1 -0
- data/test/fixtures/test/hello_world_container.builder +3 -0
- data/test/fixtures/test/hello_world_from_rxml.builder +4 -0
- data/test/fixtures/test/hello_world_with_layout_false.erb +1 -0
- data/test/fixtures/test/hello_xml_world.builder +11 -0
- data/test/fixtures/test/list.erb +1 -0
- data/test/fixtures/test/non_erb_block_content_for.builder +4 -0
- data/test/fixtures/test/potential_conflicts.erb +4 -0
- data/test/fixtures/test/render_file_from_template.html.erb +1 -0
- data/test/fixtures/test/render_file_with_ivar.erb +1 -0
- data/test/fixtures/test/render_file_with_locals.erb +1 -0
- data/test/fixtures/test/render_to_string_test.erb +1 -0
- data/test/fixtures/test/update_element_with_capture.erb +9 -0
- data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
- data/test/fixtures/topic.rb +3 -0
- data/test/fixtures/topics.yml +22 -0
- data/test/fixtures/topics/_topic.html.erb +1 -0
- data/test/template/active_record_helper_test.rb +268 -0
- data/test/template/asset_tag_helper_test.rb +514 -0
- data/test/template/atom_feed_helper_test.rb +179 -0
- data/test/template/benchmark_helper_test.rb +60 -0
- data/test/template/date_helper_test.rb +1791 -0
- data/test/template/deprecated_erb_variable_test.rb +9 -0
- data/test/template/erb_util_test.rb +24 -0
- data/test/template/form_helper_test.rb +885 -0
- data/test/template/form_options_helper_test.rb +1333 -0
- data/test/template/form_tag_helper_test.rb +272 -0
- data/test/template/javascript_helper_test.rb +73 -0
- data/test/template/number_helper_test.rb +97 -0
- data/test/template/record_tag_helper_test.rb +54 -0
- data/test/template/sanitize_helper_test.rb +48 -0
- data/test/template/tag_helper_test.rb +77 -0
- data/test/template/template_finder_test.rb +73 -0
- data/test/template/template_object_test.rb +95 -0
- data/test/template/test_test.rb +56 -0
- data/test/template/text_helper_test.rb +367 -0
- data/test/template/url_helper_test.rb +544 -0
- data/test/testing_sandbox.rb +15 -0
- metadata +469 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
require 'abstract_unit'
|
|
2
|
+
require 'digest/sha1'
|
|
3
|
+
|
|
4
|
+
ActionController::Routing::Routes.draw do |map|
|
|
5
|
+
map.connect ':controller/:action/:id'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# simulates cookie session store
|
|
9
|
+
class FakeSessionDbMan
|
|
10
|
+
def self.generate_digest(data)
|
|
11
|
+
Digest::SHA1.hexdigest("secure")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# common controller actions
|
|
16
|
+
module RequestForgeryProtectionActions
|
|
17
|
+
def index
|
|
18
|
+
render :inline => "<%= form_tag('/') {} %>"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def show_button
|
|
22
|
+
render :inline => "<%= button_to('New', '/') {} %>"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def unsafe
|
|
27
|
+
render :text => 'pwn'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def rescue_action(e) raise e end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# sample controllers
|
|
34
|
+
class RequestForgeryProtectionController < ActionController::Base
|
|
35
|
+
include RequestForgeryProtectionActions
|
|
36
|
+
protect_from_forgery :only => :index, :secret => 'abc'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class RequestForgeryProtectionWithoutSecretController < ActionController::Base
|
|
40
|
+
include RequestForgeryProtectionActions
|
|
41
|
+
protect_from_forgery
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# no token is given, assume the cookie store is used
|
|
45
|
+
class CsrfCookieMonsterController < ActionController::Base
|
|
46
|
+
include RequestForgeryProtectionActions
|
|
47
|
+
protect_from_forgery :only => :index
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# sessions are turned off
|
|
51
|
+
class SessionOffController < ActionController::Base
|
|
52
|
+
protect_from_forgery :secret => 'foobar'
|
|
53
|
+
session :off
|
|
54
|
+
def rescue_action(e) raise e end
|
|
55
|
+
include RequestForgeryProtectionActions
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class FreeCookieController < CsrfCookieMonsterController
|
|
59
|
+
self.allow_forgery_protection = false
|
|
60
|
+
|
|
61
|
+
def index
|
|
62
|
+
render :inline => "<%= form_tag('/') {} %>"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def show_button
|
|
66
|
+
render :inline => "<%= button_to('New', '/') {} %>"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# common test methods
|
|
71
|
+
|
|
72
|
+
module RequestForgeryProtectionTests
|
|
73
|
+
def teardown
|
|
74
|
+
ActionController::Base.request_forgery_protection_token = nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def test_should_render_form_with_token_tag
|
|
78
|
+
get :index
|
|
79
|
+
assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_should_render_button_to_with_token_tag
|
|
83
|
+
get :show_button
|
|
84
|
+
assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def test_should_allow_get
|
|
88
|
+
get :index
|
|
89
|
+
assert_response :success
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def test_should_allow_post_without_token_on_unsafe_action
|
|
93
|
+
post :unsafe
|
|
94
|
+
assert_response :success
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def test_should_not_allow_post_without_token
|
|
98
|
+
assert_raises(ActionController::InvalidAuthenticityToken) { post :index }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def test_should_not_allow_put_without_token
|
|
102
|
+
assert_raises(ActionController::InvalidAuthenticityToken) { put :index }
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def test_should_not_allow_delete_without_token
|
|
106
|
+
assert_raises(ActionController::InvalidAuthenticityToken) { delete :index }
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_should_not_allow_api_formatted_post_without_token
|
|
110
|
+
assert_raises(ActionController::InvalidAuthenticityToken) do
|
|
111
|
+
post :index, :format => 'xml'
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_should_not_allow_api_formatted_put_without_token
|
|
116
|
+
assert_raises(ActionController::InvalidAuthenticityToken) do
|
|
117
|
+
put :index, :format => 'xml'
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def test_should_not_allow_api_formatted_delete_without_token
|
|
122
|
+
assert_raises(ActionController::InvalidAuthenticityToken) do
|
|
123
|
+
delete :index, :format => 'xml'
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def test_should_not_allow_api_formatted_post_sent_as_url_encoded_form_without_token
|
|
128
|
+
assert_raises(ActionController::InvalidAuthenticityToken) do
|
|
129
|
+
@request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
|
|
130
|
+
post :index, :format => 'xml'
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def test_should_not_allow_api_formatted_put_sent_as_url_encoded_form_without_token
|
|
135
|
+
assert_raises(ActionController::InvalidAuthenticityToken) do
|
|
136
|
+
@request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
|
|
137
|
+
put :index, :format => 'xml'
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def test_should_not_allow_api_formatted_delete_sent_as_url_encoded_form_without_token
|
|
142
|
+
assert_raises(ActionController::InvalidAuthenticityToken) do
|
|
143
|
+
@request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
|
|
144
|
+
delete :index, :format => 'xml'
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def test_should_not_allow_api_formatted_post_sent_as_multipart_form_without_token
|
|
149
|
+
assert_raises(ActionController::InvalidAuthenticityToken) do
|
|
150
|
+
@request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
|
|
151
|
+
post :index, :format => 'xml'
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def test_should_not_allow_api_formatted_put_sent_as_multipart_form_without_token
|
|
156
|
+
assert_raises(ActionController::InvalidAuthenticityToken) do
|
|
157
|
+
@request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
|
|
158
|
+
put :index, :format => 'xml'
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def test_should_not_allow_api_formatted_delete_sent_as_multipart_form_without_token
|
|
163
|
+
assert_raises(ActionController::InvalidAuthenticityToken) do
|
|
164
|
+
@request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
|
|
165
|
+
delete :index, :format => 'xml'
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def test_should_not_allow_xhr_post_without_token
|
|
170
|
+
assert_raises(ActionController::InvalidAuthenticityToken) { xhr :post, :index }
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def test_should_not_allow_xhr_put_without_token
|
|
174
|
+
assert_raises(ActionController::InvalidAuthenticityToken) { xhr :put, :index }
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def test_should_not_allow_xhr_delete_without_token
|
|
178
|
+
assert_raises(ActionController::InvalidAuthenticityToken) { xhr :delete, :index }
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def test_should_allow_post_with_token
|
|
182
|
+
post :index, :authenticity_token => @token
|
|
183
|
+
assert_response :success
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def test_should_allow_put_with_token
|
|
187
|
+
put :index, :authenticity_token => @token
|
|
188
|
+
assert_response :success
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def test_should_allow_delete_with_token
|
|
192
|
+
delete :index, :authenticity_token => @token
|
|
193
|
+
assert_response :success
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def test_should_allow_post_with_xml
|
|
197
|
+
@request.env['CONTENT_TYPE'] = Mime::XML.to_s
|
|
198
|
+
post :index, :format => 'xml'
|
|
199
|
+
assert_response :success
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def test_should_allow_put_with_xml
|
|
203
|
+
@request.env['CONTENT_TYPE'] = Mime::XML.to_s
|
|
204
|
+
put :index, :format => 'xml'
|
|
205
|
+
assert_response :success
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def test_should_allow_delete_with_xml
|
|
209
|
+
@request.env['CONTENT_TYPE'] = Mime::XML.to_s
|
|
210
|
+
delete :index, :format => 'xml'
|
|
211
|
+
assert_response :success
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# OK let's get our test on
|
|
216
|
+
|
|
217
|
+
class RequestForgeryProtectionControllerTest < Test::Unit::TestCase
|
|
218
|
+
include RequestForgeryProtectionTests
|
|
219
|
+
def setup
|
|
220
|
+
@controller = RequestForgeryProtectionController.new
|
|
221
|
+
@request = ActionController::TestRequest.new
|
|
222
|
+
@response = ActionController::TestResponse.new
|
|
223
|
+
class << @request.session
|
|
224
|
+
def session_id() '123' end
|
|
225
|
+
end
|
|
226
|
+
@token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
|
|
227
|
+
ActionController::Base.request_forgery_protection_token = :authenticity_token
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
class RequestForgeryProtectionWithoutSecretControllerTest < Test::Unit::TestCase
|
|
232
|
+
def setup
|
|
233
|
+
@controller = RequestForgeryProtectionWithoutSecretController.new
|
|
234
|
+
@request = ActionController::TestRequest.new
|
|
235
|
+
@response = ActionController::TestResponse.new
|
|
236
|
+
class << @request.session
|
|
237
|
+
def session_id() '123' end
|
|
238
|
+
end
|
|
239
|
+
@token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
|
|
240
|
+
ActionController::Base.request_forgery_protection_token = :authenticity_token
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def test_should_raise_error_without_secret
|
|
244
|
+
assert_raises ActionController::InvalidAuthenticityToken do
|
|
245
|
+
get :index
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
class CsrfCookieMonsterControllerTest < Test::Unit::TestCase
|
|
251
|
+
include RequestForgeryProtectionTests
|
|
252
|
+
def setup
|
|
253
|
+
@controller = CsrfCookieMonsterController.new
|
|
254
|
+
@request = ActionController::TestRequest.new
|
|
255
|
+
@response = ActionController::TestResponse.new
|
|
256
|
+
class << @request.session
|
|
257
|
+
attr_accessor :dbman
|
|
258
|
+
end
|
|
259
|
+
# simulate a cookie session store
|
|
260
|
+
@request.session.dbman = FakeSessionDbMan
|
|
261
|
+
@token = Digest::SHA1.hexdigest("secure")
|
|
262
|
+
ActionController::Base.request_forgery_protection_token = :authenticity_token
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
class FreeCookieControllerTest < Test::Unit::TestCase
|
|
267
|
+
def setup
|
|
268
|
+
@controller = FreeCookieController.new
|
|
269
|
+
@request = ActionController::TestRequest.new
|
|
270
|
+
@response = ActionController::TestResponse.new
|
|
271
|
+
@token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def test_should_not_render_form_with_token_tag
|
|
275
|
+
get :index
|
|
276
|
+
assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def test_should_not_render_button_to_with_token_tag
|
|
280
|
+
get :show_button
|
|
281
|
+
assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def test_should_allow_all_methods_without_token
|
|
285
|
+
[:post, :put, :delete].each do |method|
|
|
286
|
+
assert_nothing_raised { send(method, :index)}
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
class SessionOffControllerTest < Test::Unit::TestCase
|
|
292
|
+
def setup
|
|
293
|
+
@controller = SessionOffController.new
|
|
294
|
+
@request = ActionController::TestRequest.new
|
|
295
|
+
@response = ActionController::TestResponse.new
|
|
296
|
+
@token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def test_should_raise_correct_exception
|
|
300
|
+
@request.session = {} # session(:off) doesn't appear to work with controller tests
|
|
301
|
+
assert_raises(ActionController::InvalidAuthenticityToken) do
|
|
302
|
+
post :index, :authenticity_token => @token
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
end
|
|
@@ -0,0 +1,928 @@
|
|
|
1
|
+
require 'abstract_unit'
|
|
2
|
+
require 'action_controller/integration'
|
|
3
|
+
|
|
4
|
+
class RequestTest < Test::Unit::TestCase
|
|
5
|
+
def setup
|
|
6
|
+
@request = ActionController::TestRequest.new
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def test_remote_ip
|
|
10
|
+
assert_equal '0.0.0.0', @request.remote_ip
|
|
11
|
+
|
|
12
|
+
@request.remote_addr = '1.2.3.4'
|
|
13
|
+
assert_equal '1.2.3.4', @request.remote_ip
|
|
14
|
+
|
|
15
|
+
@request.remote_addr = '1.2.3.4,3.4.5.6'
|
|
16
|
+
assert_equal '1.2.3.4', @request.remote_ip
|
|
17
|
+
|
|
18
|
+
@request.env['HTTP_CLIENT_IP'] = '2.3.4.5'
|
|
19
|
+
assert_equal '1.2.3.4', @request.remote_ip
|
|
20
|
+
|
|
21
|
+
@request.remote_addr = '192.168.0.1'
|
|
22
|
+
assert_equal '2.3.4.5', @request.remote_ip
|
|
23
|
+
@request.env.delete 'HTTP_CLIENT_IP'
|
|
24
|
+
|
|
25
|
+
@request.remote_addr = '1.2.3.4'
|
|
26
|
+
@request.env['HTTP_X_FORWARDED_FOR'] = '3.4.5.6'
|
|
27
|
+
assert_equal '1.2.3.4', @request.remote_ip
|
|
28
|
+
|
|
29
|
+
@request.remote_addr = '127.0.0.1'
|
|
30
|
+
@request.env['HTTP_X_FORWARDED_FOR'] = '3.4.5.6'
|
|
31
|
+
assert_equal '3.4.5.6', @request.remote_ip
|
|
32
|
+
|
|
33
|
+
@request.env['HTTP_X_FORWARDED_FOR'] = 'unknown,3.4.5.6'
|
|
34
|
+
assert_equal '3.4.5.6', @request.remote_ip
|
|
35
|
+
|
|
36
|
+
@request.env['HTTP_X_FORWARDED_FOR'] = '172.16.0.1,3.4.5.6'
|
|
37
|
+
assert_equal '3.4.5.6', @request.remote_ip
|
|
38
|
+
|
|
39
|
+
@request.env['HTTP_X_FORWARDED_FOR'] = '192.168.0.1,3.4.5.6'
|
|
40
|
+
assert_equal '3.4.5.6', @request.remote_ip
|
|
41
|
+
|
|
42
|
+
@request.env['HTTP_X_FORWARDED_FOR'] = '10.0.0.1,3.4.5.6'
|
|
43
|
+
assert_equal '3.4.5.6', @request.remote_ip
|
|
44
|
+
|
|
45
|
+
@request.env['HTTP_X_FORWARDED_FOR'] = '10.0.0.1, 10.0.0.1, 3.4.5.6'
|
|
46
|
+
assert_equal '3.4.5.6', @request.remote_ip
|
|
47
|
+
|
|
48
|
+
@request.env['HTTP_X_FORWARDED_FOR'] = '127.0.0.1,3.4.5.6'
|
|
49
|
+
assert_equal '3.4.5.6', @request.remote_ip
|
|
50
|
+
|
|
51
|
+
@request.env['HTTP_X_FORWARDED_FOR'] = 'unknown,192.168.0.1'
|
|
52
|
+
assert_equal 'unknown', @request.remote_ip
|
|
53
|
+
|
|
54
|
+
@request.env['HTTP_X_FORWARDED_FOR'] = '9.9.9.9, 3.4.5.6, 10.0.0.1, 172.31.4.4'
|
|
55
|
+
assert_equal '3.4.5.6', @request.remote_ip
|
|
56
|
+
|
|
57
|
+
@request.env['HTTP_CLIENT_IP'] = '8.8.8.8'
|
|
58
|
+
e = assert_raises(ActionController::ActionControllerError) {
|
|
59
|
+
@request.remote_ip
|
|
60
|
+
}
|
|
61
|
+
assert_match /IP spoofing attack/, e.message
|
|
62
|
+
assert_match /HTTP_X_FORWARDED_FOR="9.9.9.9, 3.4.5.6, 10.0.0.1, 172.31.4.4"/, e.message
|
|
63
|
+
assert_match /HTTP_CLIENT_IP="8.8.8.8"/, e.message
|
|
64
|
+
|
|
65
|
+
@request.env['HTTP_X_FORWARDED_FOR'] = '8.8.8.8, 9.9.9.9'
|
|
66
|
+
assert_equal '8.8.8.8', @request.remote_ip
|
|
67
|
+
|
|
68
|
+
@request.env.delete 'HTTP_CLIENT_IP'
|
|
69
|
+
@request.env.delete 'HTTP_X_FORWARDED_FOR'
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_domains
|
|
73
|
+
@request.host = "www.rubyonrails.org"
|
|
74
|
+
assert_equal "rubyonrails.org", @request.domain
|
|
75
|
+
|
|
76
|
+
@request.host = "www.rubyonrails.co.uk"
|
|
77
|
+
assert_equal "rubyonrails.co.uk", @request.domain(2)
|
|
78
|
+
|
|
79
|
+
@request.host = "192.168.1.200"
|
|
80
|
+
assert_nil @request.domain
|
|
81
|
+
|
|
82
|
+
@request.host = "foo.192.168.1.200"
|
|
83
|
+
assert_nil @request.domain
|
|
84
|
+
|
|
85
|
+
@request.host = "192.168.1.200.com"
|
|
86
|
+
assert_equal "200.com", @request.domain
|
|
87
|
+
|
|
88
|
+
@request.host = nil
|
|
89
|
+
assert_nil @request.domain
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def test_subdomains
|
|
93
|
+
@request.host = "www.rubyonrails.org"
|
|
94
|
+
assert_equal %w( www ), @request.subdomains
|
|
95
|
+
|
|
96
|
+
@request.host = "www.rubyonrails.co.uk"
|
|
97
|
+
assert_equal %w( www ), @request.subdomains(2)
|
|
98
|
+
|
|
99
|
+
@request.host = "dev.www.rubyonrails.co.uk"
|
|
100
|
+
assert_equal %w( dev www ), @request.subdomains(2)
|
|
101
|
+
|
|
102
|
+
@request.host = "foobar.foobar.com"
|
|
103
|
+
assert_equal %w( foobar ), @request.subdomains
|
|
104
|
+
|
|
105
|
+
@request.host = "192.168.1.200"
|
|
106
|
+
assert_equal [], @request.subdomains
|
|
107
|
+
|
|
108
|
+
@request.host = "foo.192.168.1.200"
|
|
109
|
+
assert_equal [], @request.subdomains
|
|
110
|
+
|
|
111
|
+
@request.host = "192.168.1.200.com"
|
|
112
|
+
assert_equal %w( 192 168 1 ), @request.subdomains
|
|
113
|
+
|
|
114
|
+
@request.host = nil
|
|
115
|
+
assert_equal [], @request.subdomains
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def test_port_string
|
|
119
|
+
@request.port = 80
|
|
120
|
+
assert_equal "", @request.port_string
|
|
121
|
+
|
|
122
|
+
@request.port = 8080
|
|
123
|
+
assert_equal ":8080", @request.port_string
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def test_relative_url_root
|
|
127
|
+
@request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
|
|
128
|
+
@request.env['SERVER_SOFTWARE'] = 'lighttpd/1.2.3'
|
|
129
|
+
assert_equal '', @request.relative_url_root, "relative_url_root should be disabled on lighttpd"
|
|
130
|
+
|
|
131
|
+
@request.env['SERVER_SOFTWARE'] = 'apache/1.2.3 some random text'
|
|
132
|
+
|
|
133
|
+
@request.env['SCRIPT_NAME'] = nil
|
|
134
|
+
assert_equal "", @request.relative_url_root
|
|
135
|
+
|
|
136
|
+
@request.env['SCRIPT_NAME'] = "/dispatch.cgi"
|
|
137
|
+
assert_equal "", @request.relative_url_root
|
|
138
|
+
|
|
139
|
+
@request.env['SCRIPT_NAME'] = "/myapp.rb"
|
|
140
|
+
assert_equal "", @request.relative_url_root
|
|
141
|
+
|
|
142
|
+
@request.relative_url_root = nil
|
|
143
|
+
@request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
|
|
144
|
+
assert_equal "/hieraki", @request.relative_url_root
|
|
145
|
+
|
|
146
|
+
@request.relative_url_root = nil
|
|
147
|
+
@request.env['SCRIPT_NAME'] = "/collaboration/hieraki/dispatch.cgi"
|
|
148
|
+
assert_equal "/collaboration/hieraki", @request.relative_url_root
|
|
149
|
+
|
|
150
|
+
# apache/scgi case
|
|
151
|
+
@request.relative_url_root = nil
|
|
152
|
+
@request.env['SCRIPT_NAME'] = "/collaboration/hieraki"
|
|
153
|
+
assert_equal "/collaboration/hieraki", @request.relative_url_root
|
|
154
|
+
|
|
155
|
+
@request.relative_url_root = nil
|
|
156
|
+
@request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
|
|
157
|
+
@request.env['SERVER_SOFTWARE'] = 'lighttpd/1.2.3'
|
|
158
|
+
@request.env['RAILS_RELATIVE_URL_ROOT'] = "/hieraki"
|
|
159
|
+
assert_equal "/hieraki", @request.relative_url_root
|
|
160
|
+
|
|
161
|
+
# @env overrides path guess
|
|
162
|
+
@request.relative_url_root = nil
|
|
163
|
+
@request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
|
|
164
|
+
@request.env['SERVER_SOFTWARE'] = 'apache/1.2.3 some random text'
|
|
165
|
+
@request.env['RAILS_RELATIVE_URL_ROOT'] = "/real_url"
|
|
166
|
+
assert_equal "/real_url", @request.relative_url_root
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def test_request_uri
|
|
170
|
+
@request.env['SERVER_SOFTWARE'] = 'Apache 42.342.3432'
|
|
171
|
+
|
|
172
|
+
@request.relative_url_root = nil
|
|
173
|
+
@request.set_REQUEST_URI "http://www.rubyonrails.org/path/of/some/uri?mapped=1"
|
|
174
|
+
assert_equal "/path/of/some/uri?mapped=1", @request.request_uri
|
|
175
|
+
assert_equal "/path/of/some/uri", @request.path
|
|
176
|
+
|
|
177
|
+
@request.relative_url_root = nil
|
|
178
|
+
@request.set_REQUEST_URI "http://www.rubyonrails.org/path/of/some/uri"
|
|
179
|
+
assert_equal "/path/of/some/uri", @request.request_uri
|
|
180
|
+
assert_equal "/path/of/some/uri", @request.path
|
|
181
|
+
|
|
182
|
+
@request.relative_url_root = nil
|
|
183
|
+
@request.set_REQUEST_URI "/path/of/some/uri"
|
|
184
|
+
assert_equal "/path/of/some/uri", @request.request_uri
|
|
185
|
+
assert_equal "/path/of/some/uri", @request.path
|
|
186
|
+
|
|
187
|
+
@request.relative_url_root = nil
|
|
188
|
+
@request.set_REQUEST_URI "/"
|
|
189
|
+
assert_equal "/", @request.request_uri
|
|
190
|
+
assert_equal "/", @request.path
|
|
191
|
+
|
|
192
|
+
@request.relative_url_root = nil
|
|
193
|
+
@request.set_REQUEST_URI "/?m=b"
|
|
194
|
+
assert_equal "/?m=b", @request.request_uri
|
|
195
|
+
assert_equal "/", @request.path
|
|
196
|
+
|
|
197
|
+
@request.relative_url_root = nil
|
|
198
|
+
@request.set_REQUEST_URI "/"
|
|
199
|
+
@request.env['SCRIPT_NAME'] = "/dispatch.cgi"
|
|
200
|
+
assert_equal "/", @request.request_uri
|
|
201
|
+
assert_equal "/", @request.path
|
|
202
|
+
|
|
203
|
+
@request.relative_url_root = nil
|
|
204
|
+
@request.set_REQUEST_URI "/hieraki/"
|
|
205
|
+
@request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
|
|
206
|
+
assert_equal "/hieraki/", @request.request_uri
|
|
207
|
+
assert_equal "/", @request.path
|
|
208
|
+
|
|
209
|
+
@request.relative_url_root = nil
|
|
210
|
+
@request.set_REQUEST_URI "/collaboration/hieraki/books/edit/2"
|
|
211
|
+
@request.env['SCRIPT_NAME'] = "/collaboration/hieraki/dispatch.cgi"
|
|
212
|
+
assert_equal "/collaboration/hieraki/books/edit/2", @request.request_uri
|
|
213
|
+
assert_equal "/books/edit/2", @request.path
|
|
214
|
+
|
|
215
|
+
# The following tests are for when REQUEST_URI is not supplied (as in IIS)
|
|
216
|
+
@request.relative_url_root = nil
|
|
217
|
+
@request.set_REQUEST_URI nil
|
|
218
|
+
@request.env['PATH_INFO'] = "/path/of/some/uri?mapped=1"
|
|
219
|
+
@request.env['SCRIPT_NAME'] = nil #"/path/dispatch.rb"
|
|
220
|
+
assert_equal "/path/of/some/uri?mapped=1", @request.request_uri
|
|
221
|
+
assert_equal "/path/of/some/uri", @request.path
|
|
222
|
+
|
|
223
|
+
@request.set_REQUEST_URI nil
|
|
224
|
+
@request.relative_url_root = nil
|
|
225
|
+
@request.env['PATH_INFO'] = "/path/of/some/uri?mapped=1"
|
|
226
|
+
@request.env['SCRIPT_NAME'] = "/path/dispatch.rb"
|
|
227
|
+
assert_equal "/path/of/some/uri?mapped=1", @request.request_uri
|
|
228
|
+
assert_equal "/of/some/uri", @request.path
|
|
229
|
+
|
|
230
|
+
@request.set_REQUEST_URI nil
|
|
231
|
+
@request.relative_url_root = nil
|
|
232
|
+
@request.env['PATH_INFO'] = "/path/of/some/uri"
|
|
233
|
+
@request.env['SCRIPT_NAME'] = nil
|
|
234
|
+
assert_equal "/path/of/some/uri", @request.request_uri
|
|
235
|
+
assert_equal "/path/of/some/uri", @request.path
|
|
236
|
+
|
|
237
|
+
@request.set_REQUEST_URI nil
|
|
238
|
+
@request.relative_url_root = nil
|
|
239
|
+
@request.env['PATH_INFO'] = "/"
|
|
240
|
+
assert_equal "/", @request.request_uri
|
|
241
|
+
assert_equal "/", @request.path
|
|
242
|
+
|
|
243
|
+
@request.set_REQUEST_URI nil
|
|
244
|
+
@request.relative_url_root = nil
|
|
245
|
+
@request.env['PATH_INFO'] = "/?m=b"
|
|
246
|
+
assert_equal "/?m=b", @request.request_uri
|
|
247
|
+
assert_equal "/", @request.path
|
|
248
|
+
|
|
249
|
+
@request.set_REQUEST_URI nil
|
|
250
|
+
@request.relative_url_root = nil
|
|
251
|
+
@request.env['PATH_INFO'] = "/"
|
|
252
|
+
@request.env['SCRIPT_NAME'] = "/dispatch.cgi"
|
|
253
|
+
assert_equal "/", @request.request_uri
|
|
254
|
+
assert_equal "/", @request.path
|
|
255
|
+
|
|
256
|
+
@request.set_REQUEST_URI nil
|
|
257
|
+
@request.relative_url_root = nil
|
|
258
|
+
@request.env['PATH_INFO'] = "/hieraki/"
|
|
259
|
+
@request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
|
|
260
|
+
assert_equal "/hieraki/", @request.request_uri
|
|
261
|
+
assert_equal "/", @request.path
|
|
262
|
+
|
|
263
|
+
@request.set_REQUEST_URI '/hieraki/dispatch.cgi'
|
|
264
|
+
@request.relative_url_root = '/hieraki'
|
|
265
|
+
assert_equal "/dispatch.cgi", @request.path
|
|
266
|
+
@request.relative_url_root = nil
|
|
267
|
+
|
|
268
|
+
@request.set_REQUEST_URI '/hieraki/dispatch.cgi'
|
|
269
|
+
@request.relative_url_root = '/foo'
|
|
270
|
+
assert_equal "/hieraki/dispatch.cgi", @request.path
|
|
271
|
+
@request.relative_url_root = nil
|
|
272
|
+
|
|
273
|
+
# This test ensures that Rails uses REQUEST_URI over PATH_INFO
|
|
274
|
+
@request.relative_url_root = nil
|
|
275
|
+
@request.env['REQUEST_URI'] = "/some/path"
|
|
276
|
+
@request.env['PATH_INFO'] = "/another/path"
|
|
277
|
+
@request.env['SCRIPT_NAME'] = "/dispatch.cgi"
|
|
278
|
+
assert_equal "/some/path", @request.request_uri
|
|
279
|
+
assert_equal "/some/path", @request.path
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def test_host_with_default_port
|
|
284
|
+
@request.host = "rubyonrails.org"
|
|
285
|
+
@request.port = 80
|
|
286
|
+
assert_equal "rubyonrails.org", @request.host_with_port
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def test_host_with_non_default_port
|
|
290
|
+
@request.host = "rubyonrails.org"
|
|
291
|
+
@request.port = 81
|
|
292
|
+
assert_equal "rubyonrails.org:81", @request.host_with_port
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def test_server_software
|
|
296
|
+
assert_equal nil, @request.server_software
|
|
297
|
+
|
|
298
|
+
@request.env['SERVER_SOFTWARE'] = 'Apache3.422'
|
|
299
|
+
assert_equal 'apache', @request.server_software
|
|
300
|
+
|
|
301
|
+
@request.env['SERVER_SOFTWARE'] = 'lighttpd(1.1.4)'
|
|
302
|
+
assert_equal 'lighttpd', @request.server_software
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def test_xml_http_request
|
|
306
|
+
assert !@request.xml_http_request?
|
|
307
|
+
assert !@request.xhr?
|
|
308
|
+
|
|
309
|
+
@request.env['HTTP_X_REQUESTED_WITH'] = "DefinitelyNotAjax1.0"
|
|
310
|
+
assert !@request.xml_http_request?
|
|
311
|
+
assert !@request.xhr?
|
|
312
|
+
|
|
313
|
+
@request.env['HTTP_X_REQUESTED_WITH'] = "XMLHttpRequest"
|
|
314
|
+
assert @request.xml_http_request?
|
|
315
|
+
assert @request.xhr?
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def test_reports_ssl
|
|
319
|
+
assert !@request.ssl?
|
|
320
|
+
@request.env['HTTPS'] = 'on'
|
|
321
|
+
assert @request.ssl?
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def test_reports_ssl_when_proxied_via_lighttpd
|
|
325
|
+
assert !@request.ssl?
|
|
326
|
+
@request.env['HTTP_X_FORWARDED_PROTO'] = 'https'
|
|
327
|
+
assert @request.ssl?
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def test_symbolized_request_methods
|
|
331
|
+
[:get, :post, :put, :delete].each do |method|
|
|
332
|
+
set_request_method_to method
|
|
333
|
+
assert_equal method, @request.method
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def test_invalid_http_method_raises_exception
|
|
338
|
+
set_request_method_to :random_method
|
|
339
|
+
assert_raises(ActionController::UnknownHttpMethod) do
|
|
340
|
+
@request.method
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def test_allow_method_hacking_on_post
|
|
345
|
+
set_request_method_to :post
|
|
346
|
+
[:get, :head, :options, :put, :post, :delete].each do |method|
|
|
347
|
+
@request.instance_eval { @parameters = { :_method => method } ; @request_method = nil }
|
|
348
|
+
assert_equal(method == :head ? :get : method, @request.method)
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def test_invalid_method_hacking_on_post_raises_exception
|
|
353
|
+
set_request_method_to :post
|
|
354
|
+
@request.instance_eval { @parameters = { :_method => :random_method } ; @request_method = nil }
|
|
355
|
+
assert_raises(ActionController::UnknownHttpMethod) do
|
|
356
|
+
@request.method
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
def test_restrict_method_hacking
|
|
361
|
+
@request.instance_eval { @parameters = { :_method => 'put' } }
|
|
362
|
+
[:get, :put, :delete].each do |method|
|
|
363
|
+
set_request_method_to method
|
|
364
|
+
assert_equal method, @request.method
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
def test_head_masquarading_as_get
|
|
369
|
+
set_request_method_to :head
|
|
370
|
+
assert_equal :get, @request.method
|
|
371
|
+
assert @request.get?
|
|
372
|
+
assert @request.head?
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def test_xml_format
|
|
376
|
+
@request.instance_eval { @parameters = { :format => 'xml' } }
|
|
377
|
+
assert_equal Mime::XML, @request.format
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def test_xhtml_format
|
|
381
|
+
@request.instance_eval { @parameters = { :format => 'xhtml' } }
|
|
382
|
+
assert_equal Mime::HTML, @request.format
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def test_txt_format
|
|
386
|
+
@request.instance_eval { @parameters = { :format => 'txt' } }
|
|
387
|
+
assert_equal Mime::TEXT, @request.format
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def test_nil_format
|
|
391
|
+
@request.instance_eval { @parameters = { :format => nil } }
|
|
392
|
+
@request.env["HTTP_ACCEPT"] = "text/javascript"
|
|
393
|
+
assert_equal Mime::JS, @request.format
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def test_content_type
|
|
397
|
+
@request.env["CONTENT_TYPE"] = "text/html"
|
|
398
|
+
assert_equal Mime::HTML, @request.content_type
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def test_format_assignment_should_set_format
|
|
402
|
+
@request.instance_eval { self.format = :txt }
|
|
403
|
+
assert !@request.format.xml?
|
|
404
|
+
@request.instance_eval { self.format = :xml }
|
|
405
|
+
assert @request.format.xml?
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def test_content_no_type
|
|
409
|
+
assert_equal nil, @request.content_type
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
def test_content_type_xml
|
|
413
|
+
@request.env["CONTENT_TYPE"] = "application/xml"
|
|
414
|
+
assert_equal Mime::XML, @request.content_type
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
def test_content_type_with_charset
|
|
418
|
+
@request.env["CONTENT_TYPE"] = "application/xml; charset=UTF-8"
|
|
419
|
+
assert_equal Mime::XML, @request.content_type
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def test_user_agent
|
|
423
|
+
assert_not_nil @request.user_agent
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def test_parameters
|
|
427
|
+
@request.instance_eval { @request_parameters = { "foo" => 1 } }
|
|
428
|
+
@request.instance_eval { @query_parameters = { "bar" => 2 } }
|
|
429
|
+
|
|
430
|
+
assert_equal({"foo" => 1, "bar" => 2}, @request.parameters)
|
|
431
|
+
assert_equal({"foo" => 1}, @request.request_parameters)
|
|
432
|
+
assert_equal({"bar" => 2}, @request.query_parameters)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
protected
|
|
436
|
+
def set_request_method_to(method)
|
|
437
|
+
@request.env['REQUEST_METHOD'] = method.to_s.upcase
|
|
438
|
+
@request.instance_eval { @request_method = nil }
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
class UrlEncodedRequestParameterParsingTest < Test::Unit::TestCase
|
|
444
|
+
def setup
|
|
445
|
+
@query_string = "action=create_customer&full_name=David%20Heinemeier%20Hansson&customerId=1"
|
|
446
|
+
@query_string_with_empty = "action=create_customer&full_name="
|
|
447
|
+
@query_string_with_array = "action=create_customer&selected[]=1&selected[]=2&selected[]=3"
|
|
448
|
+
@query_string_with_amps = "action=create_customer&name=Don%27t+%26+Does"
|
|
449
|
+
@query_string_with_multiple_of_same_name =
|
|
450
|
+
"action=update_order&full_name=Lau%20Taarnskov&products=4&products=2&products=3"
|
|
451
|
+
@query_string_with_many_equal = "action=create_customer&full_name=abc=def=ghi"
|
|
452
|
+
@query_string_without_equal = "action"
|
|
453
|
+
@query_string_with_many_ampersands =
|
|
454
|
+
"&action=create_customer&&&full_name=David%20Heinemeier%20Hansson"
|
|
455
|
+
@query_string_with_empty_key = "action=create_customer&full_name=David%20Heinemeier%20Hansson&=Save"
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
def test_query_string
|
|
459
|
+
assert_equal(
|
|
460
|
+
{ "action" => "create_customer", "full_name" => "David Heinemeier Hansson", "customerId" => "1"},
|
|
461
|
+
ActionController::AbstractRequest.parse_query_parameters(@query_string)
|
|
462
|
+
)
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def test_deep_query_string
|
|
466
|
+
expected = {'x' => {'y' => {'z' => '10'}}}
|
|
467
|
+
assert_equal(expected, ActionController::AbstractRequest.parse_query_parameters('x[y][z]=10'))
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
def test_deep_query_string_with_array
|
|
471
|
+
assert_equal({'x' => {'y' => {'z' => ['10']}}}, ActionController::AbstractRequest.parse_query_parameters('x[y][z][]=10'))
|
|
472
|
+
assert_equal({'x' => {'y' => {'z' => ['10', '5']}}}, ActionController::AbstractRequest.parse_query_parameters('x[y][z][]=10&x[y][z][]=5'))
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
def test_deep_query_string_with_array_of_hash
|
|
476
|
+
assert_equal({'x' => {'y' => [{'z' => '10'}]}}, ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10'))
|
|
477
|
+
assert_equal({'x' => {'y' => [{'z' => '10', 'w' => '10'}]}}, ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10&x[y][][w]=10'))
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
def test_deep_query_string_with_array_of_hashes_with_one_pair
|
|
481
|
+
assert_equal({'x' => {'y' => [{'z' => '10'}, {'z' => '20'}]}}, ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10&x[y][][z]=20'))
|
|
482
|
+
assert_equal("10", ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10&x[y][][z]=20')["x"]["y"].first["z"])
|
|
483
|
+
assert_equal("10", ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10&x[y][][z]=20').with_indifferent_access[:x][:y].first[:z])
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
def test_deep_query_string_with_array_of_hashes_with_multiple_pairs
|
|
487
|
+
assert_equal(
|
|
488
|
+
{'x' => {'y' => [{'z' => '10', 'w' => 'a'}, {'z' => '20', 'w' => 'b'}]}},
|
|
489
|
+
ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10&x[y][][w]=a&x[y][][z]=20&x[y][][w]=b')
|
|
490
|
+
)
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
def test_query_string_with_nil
|
|
494
|
+
assert_equal(
|
|
495
|
+
{ "action" => "create_customer", "full_name" => ''},
|
|
496
|
+
ActionController::AbstractRequest.parse_query_parameters(@query_string_with_empty)
|
|
497
|
+
)
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
def test_query_string_with_array
|
|
501
|
+
assert_equal(
|
|
502
|
+
{ "action" => "create_customer", "selected" => ["1", "2", "3"]},
|
|
503
|
+
ActionController::AbstractRequest.parse_query_parameters(@query_string_with_array)
|
|
504
|
+
)
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
def test_query_string_with_amps
|
|
508
|
+
assert_equal(
|
|
509
|
+
{ "action" => "create_customer", "name" => "Don't & Does"},
|
|
510
|
+
ActionController::AbstractRequest.parse_query_parameters(@query_string_with_amps)
|
|
511
|
+
)
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
def test_query_string_with_many_equal
|
|
515
|
+
assert_equal(
|
|
516
|
+
{ "action" => "create_customer", "full_name" => "abc=def=ghi"},
|
|
517
|
+
ActionController::AbstractRequest.parse_query_parameters(@query_string_with_many_equal)
|
|
518
|
+
)
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def test_query_string_without_equal
|
|
522
|
+
assert_equal(
|
|
523
|
+
{ "action" => nil },
|
|
524
|
+
ActionController::AbstractRequest.parse_query_parameters(@query_string_without_equal)
|
|
525
|
+
)
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def test_query_string_with_empty_key
|
|
529
|
+
assert_equal(
|
|
530
|
+
{ "action" => "create_customer", "full_name" => "David Heinemeier Hansson" },
|
|
531
|
+
ActionController::AbstractRequest.parse_query_parameters(@query_string_with_empty_key)
|
|
532
|
+
)
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
def test_query_string_with_many_ampersands
|
|
536
|
+
assert_equal(
|
|
537
|
+
{ "action" => "create_customer", "full_name" => "David Heinemeier Hansson"},
|
|
538
|
+
ActionController::AbstractRequest.parse_query_parameters(@query_string_with_many_ampersands)
|
|
539
|
+
)
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
def test_unbalanced_query_string_with_array
|
|
543
|
+
assert_equal(
|
|
544
|
+
{'location' => ["1", "2"], 'age_group' => ["2"]},
|
|
545
|
+
ActionController::AbstractRequest.parse_query_parameters("location[]=1&location[]=2&age_group[]=2")
|
|
546
|
+
)
|
|
547
|
+
assert_equal(
|
|
548
|
+
{'location' => ["1", "2"], 'age_group' => ["2"]},
|
|
549
|
+
ActionController::AbstractRequest.parse_request_parameters({'location[]' => ["1", "2"],
|
|
550
|
+
'age_group[]' => ["2"]})
|
|
551
|
+
)
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
def test_request_hash_parsing
|
|
556
|
+
query = {
|
|
557
|
+
"note[viewers][viewer][][type]" => ["User", "Group"],
|
|
558
|
+
"note[viewers][viewer][][id]" => ["1", "2"]
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
expected = { "note" => { "viewers"=>{"viewer"=>[{ "id"=>"1", "type"=>"User"}, {"type"=>"Group", "id"=>"2"} ]} } }
|
|
562
|
+
|
|
563
|
+
assert_equal(expected, ActionController::AbstractRequest.parse_request_parameters(query))
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def test_parse_params
|
|
568
|
+
input = {
|
|
569
|
+
"customers[boston][first][name]" => [ "David" ],
|
|
570
|
+
"customers[boston][first][url]" => [ "http://David" ],
|
|
571
|
+
"customers[boston][second][name]" => [ "Allan" ],
|
|
572
|
+
"customers[boston][second][url]" => [ "http://Allan" ],
|
|
573
|
+
"something_else" => [ "blah" ],
|
|
574
|
+
"something_nil" => [ nil ],
|
|
575
|
+
"something_empty" => [ "" ],
|
|
576
|
+
"products[first]" => [ "Apple Computer" ],
|
|
577
|
+
"products[second]" => [ "Pc" ],
|
|
578
|
+
"" => [ 'Save' ]
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
expected_output = {
|
|
582
|
+
"customers" => {
|
|
583
|
+
"boston" => {
|
|
584
|
+
"first" => {
|
|
585
|
+
"name" => "David",
|
|
586
|
+
"url" => "http://David"
|
|
587
|
+
},
|
|
588
|
+
"second" => {
|
|
589
|
+
"name" => "Allan",
|
|
590
|
+
"url" => "http://Allan"
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
},
|
|
594
|
+
"something_else" => "blah",
|
|
595
|
+
"something_empty" => "",
|
|
596
|
+
"something_nil" => "",
|
|
597
|
+
"products" => {
|
|
598
|
+
"first" => "Apple Computer",
|
|
599
|
+
"second" => "Pc"
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
assert_equal expected_output, ActionController::AbstractRequest.parse_request_parameters(input)
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
UploadedStringIO = ActionController::UploadedStringIO
|
|
607
|
+
class MockUpload < UploadedStringIO
|
|
608
|
+
def initialize(content_type, original_path, *args)
|
|
609
|
+
self.content_type = content_type
|
|
610
|
+
self.original_path = original_path
|
|
611
|
+
super *args
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
def test_parse_params_from_multipart_upload
|
|
616
|
+
file = MockUpload.new('img/jpeg', 'foo.jpg')
|
|
617
|
+
ie_file = MockUpload.new('img/jpeg', 'c:\\Documents and Settings\\foo\\Desktop\\bar.jpg')
|
|
618
|
+
non_file_text_part = MockUpload.new('text/plain', '', 'abc')
|
|
619
|
+
|
|
620
|
+
input = {
|
|
621
|
+
"something" => [ UploadedStringIO.new("") ],
|
|
622
|
+
"array_of_stringios" => [[ UploadedStringIO.new("One"), UploadedStringIO.new("Two") ]],
|
|
623
|
+
"mixed_types_array" => [[ UploadedStringIO.new("Three"), "NotStringIO" ]],
|
|
624
|
+
"mixed_types_as_checkboxes[strings][nested]" => [[ file, "String", UploadedStringIO.new("StringIO")]],
|
|
625
|
+
"ie_mixed_types_as_checkboxes[strings][nested]" => [[ ie_file, "String", UploadedStringIO.new("StringIO")]],
|
|
626
|
+
"products[string]" => [ UploadedStringIO.new("Apple Computer") ],
|
|
627
|
+
"products[file]" => [ file ],
|
|
628
|
+
"ie_products[string]" => [ UploadedStringIO.new("Microsoft") ],
|
|
629
|
+
"ie_products[file]" => [ ie_file ],
|
|
630
|
+
"text_part" => [non_file_text_part]
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
expected_output = {
|
|
634
|
+
"something" => "",
|
|
635
|
+
"array_of_stringios" => ["One", "Two"],
|
|
636
|
+
"mixed_types_array" => [ "Three", "NotStringIO" ],
|
|
637
|
+
"mixed_types_as_checkboxes" => {
|
|
638
|
+
"strings" => {
|
|
639
|
+
"nested" => [ file, "String", "StringIO" ]
|
|
640
|
+
},
|
|
641
|
+
},
|
|
642
|
+
"ie_mixed_types_as_checkboxes" => {
|
|
643
|
+
"strings" => {
|
|
644
|
+
"nested" => [ ie_file, "String", "StringIO" ]
|
|
645
|
+
},
|
|
646
|
+
},
|
|
647
|
+
"products" => {
|
|
648
|
+
"string" => "Apple Computer",
|
|
649
|
+
"file" => file
|
|
650
|
+
},
|
|
651
|
+
"ie_products" => {
|
|
652
|
+
"string" => "Microsoft",
|
|
653
|
+
"file" => ie_file
|
|
654
|
+
},
|
|
655
|
+
"text_part" => "abc"
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
params = ActionController::AbstractRequest.parse_request_parameters(input)
|
|
659
|
+
assert_equal expected_output, params
|
|
660
|
+
|
|
661
|
+
# Lone filenames are preserved.
|
|
662
|
+
assert_equal 'foo.jpg', params['mixed_types_as_checkboxes']['strings']['nested'].first.original_filename
|
|
663
|
+
assert_equal 'foo.jpg', params['products']['file'].original_filename
|
|
664
|
+
|
|
665
|
+
# But full Windows paths are reduced to their basename.
|
|
666
|
+
assert_equal 'bar.jpg', params['ie_mixed_types_as_checkboxes']['strings']['nested'].first.original_filename
|
|
667
|
+
assert_equal 'bar.jpg', params['ie_products']['file'].original_filename
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
def test_parse_params_with_file
|
|
671
|
+
input = {
|
|
672
|
+
"customers[boston][first][name]" => [ "David" ],
|
|
673
|
+
"something_else" => [ "blah" ],
|
|
674
|
+
"logo" => [ File.new(File.dirname(__FILE__) + "/cgi_test.rb").path ]
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
expected_output = {
|
|
678
|
+
"customers" => {
|
|
679
|
+
"boston" => {
|
|
680
|
+
"first" => {
|
|
681
|
+
"name" => "David"
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
},
|
|
685
|
+
"something_else" => "blah",
|
|
686
|
+
"logo" => File.new(File.dirname(__FILE__) + "/cgi_test.rb").path,
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
assert_equal expected_output, ActionController::AbstractRequest.parse_request_parameters(input)
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
def test_parse_params_with_array
|
|
693
|
+
input = { "selected[]" => [ "1", "2", "3" ] }
|
|
694
|
+
|
|
695
|
+
expected_output = { "selected" => [ "1", "2", "3" ] }
|
|
696
|
+
|
|
697
|
+
assert_equal expected_output, ActionController::AbstractRequest.parse_request_parameters(input)
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
def test_parse_params_with_non_alphanumeric_name
|
|
701
|
+
input = { "a/b[c]" => %w(d) }
|
|
702
|
+
expected = { "a/b" => { "c" => "d" }}
|
|
703
|
+
assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input)
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
def test_parse_params_with_single_brackets_in_middle
|
|
707
|
+
input = { "a/b[c]d" => %w(e) }
|
|
708
|
+
expected = { "a/b" => {} }
|
|
709
|
+
assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input)
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
def test_parse_params_with_separated_brackets
|
|
713
|
+
input = { "a/b@[c]d[e]" => %w(f) }
|
|
714
|
+
expected = { "a/b@" => { }}
|
|
715
|
+
assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input)
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
def test_parse_params_with_separated_brackets_and_array
|
|
719
|
+
input = { "a/b@[c]d[e][]" => %w(f) }
|
|
720
|
+
expected = { "a/b@" => { }}
|
|
721
|
+
assert_equal expected , ActionController::AbstractRequest.parse_request_parameters(input)
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
def test_parse_params_with_unmatched_brackets_and_array
|
|
725
|
+
input = { "a/b@[c][d[e][]" => %w(f) }
|
|
726
|
+
expected = { "a/b@" => { "c" => { }}}
|
|
727
|
+
assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input)
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
def test_parse_params_with_nil_key
|
|
731
|
+
input = { nil => nil, "test2" => %w(value1) }
|
|
732
|
+
expected = { "test2" => "value1" }
|
|
733
|
+
assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input)
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
def test_parse_params_with_array_prefix_and_hashes
|
|
737
|
+
input = { "a[][b][c]" => %w(d) }
|
|
738
|
+
expected = {"a" => [{"b" => {"c" => "d"}}]}
|
|
739
|
+
assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input)
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
def test_parse_params_with_complex_nesting
|
|
743
|
+
input = { "a[][b][c][][d][]" => %w(e) }
|
|
744
|
+
expected = {"a" => [{"b" => {"c" => [{"d" => ["e"]}]}}]}
|
|
745
|
+
assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input)
|
|
746
|
+
end
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
class MultipartRequestParameterParsingTest < Test::Unit::TestCase
|
|
751
|
+
FIXTURE_PATH = File.dirname(__FILE__) + '/../fixtures/multipart'
|
|
752
|
+
|
|
753
|
+
def test_single_parameter
|
|
754
|
+
params = process('single_parameter')
|
|
755
|
+
assert_equal({ 'foo' => 'bar' }, params)
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
def test_bracketed_param
|
|
759
|
+
assert_equal({ 'foo' => { 'baz' => 'bar'}}, process('bracketed_param'))
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
def test_text_file
|
|
763
|
+
params = process('text_file')
|
|
764
|
+
assert_equal %w(file foo), params.keys.sort
|
|
765
|
+
assert_equal 'bar', params['foo']
|
|
766
|
+
|
|
767
|
+
file = params['file']
|
|
768
|
+
assert_kind_of StringIO, file
|
|
769
|
+
assert_equal 'file.txt', file.original_filename
|
|
770
|
+
assert_equal "text/plain", file.content_type
|
|
771
|
+
assert_equal 'contents', file.read
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
def test_boundary_problem_file
|
|
775
|
+
params = process('boundary_problem_file')
|
|
776
|
+
assert_equal %w(file foo), params.keys.sort
|
|
777
|
+
|
|
778
|
+
file = params['file']
|
|
779
|
+
foo = params['foo']
|
|
780
|
+
|
|
781
|
+
if RUBY_VERSION > '1.9'
|
|
782
|
+
assert_kind_of File, file
|
|
783
|
+
else
|
|
784
|
+
assert_kind_of Tempfile, file
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
assert_equal 'file.txt', file.original_filename
|
|
788
|
+
assert_equal "text/plain", file.content_type
|
|
789
|
+
|
|
790
|
+
assert_equal 'bar', foo
|
|
791
|
+
end
|
|
792
|
+
|
|
793
|
+
def test_large_text_file
|
|
794
|
+
params = process('large_text_file')
|
|
795
|
+
assert_equal %w(file foo), params.keys.sort
|
|
796
|
+
assert_equal 'bar', params['foo']
|
|
797
|
+
|
|
798
|
+
file = params['file']
|
|
799
|
+
if RUBY_VERSION > '1.9'
|
|
800
|
+
assert_kind_of File, file
|
|
801
|
+
else
|
|
802
|
+
assert_kind_of Tempfile, file
|
|
803
|
+
end
|
|
804
|
+
assert_equal 'file.txt', file.original_filename
|
|
805
|
+
assert_equal "text/plain", file.content_type
|
|
806
|
+
assert ('a' * 20480) == file.read
|
|
807
|
+
end
|
|
808
|
+
|
|
809
|
+
uses_mocha "test_no_rewind_stream" do
|
|
810
|
+
def test_no_rewind_stream
|
|
811
|
+
# Ensures that parse_multipart_form_parameters works with streams that cannot be rewound
|
|
812
|
+
file = File.open(File.join(FIXTURE_PATH, 'large_text_file'), 'rb')
|
|
813
|
+
file.expects(:rewind).raises(Errno::ESPIPE)
|
|
814
|
+
params = ActionController::AbstractRequest.parse_multipart_form_parameters(file, 'AaB03x', file.stat.size, {})
|
|
815
|
+
assert_not_equal 0, file.pos # file was not rewound after reading
|
|
816
|
+
end
|
|
817
|
+
end
|
|
818
|
+
|
|
819
|
+
def test_binary_file
|
|
820
|
+
params = process('binary_file')
|
|
821
|
+
assert_equal %w(file flowers foo), params.keys.sort
|
|
822
|
+
assert_equal 'bar', params['foo']
|
|
823
|
+
|
|
824
|
+
file = params['file']
|
|
825
|
+
assert_kind_of StringIO, file
|
|
826
|
+
assert_equal 'file.csv', file.original_filename
|
|
827
|
+
assert_nil file.content_type
|
|
828
|
+
assert_equal 'contents', file.read
|
|
829
|
+
|
|
830
|
+
file = params['flowers']
|
|
831
|
+
assert_kind_of StringIO, file
|
|
832
|
+
assert_equal 'flowers.jpg', file.original_filename
|
|
833
|
+
assert_equal "image/jpeg", file.content_type
|
|
834
|
+
assert_equal 19512, file.size
|
|
835
|
+
#assert_equal File.read(File.dirname(__FILE__) + '/../../../activerecord/test/fixtures/flowers.jpg'), file.read
|
|
836
|
+
end
|
|
837
|
+
|
|
838
|
+
def test_mixed_files
|
|
839
|
+
params = process('mixed_files')
|
|
840
|
+
assert_equal %w(files foo), params.keys.sort
|
|
841
|
+
assert_equal 'bar', params['foo']
|
|
842
|
+
|
|
843
|
+
# Ruby CGI doesn't handle multipart/mixed for us.
|
|
844
|
+
files = params['files']
|
|
845
|
+
assert_kind_of String, files
|
|
846
|
+
files.force_encoding('ASCII-8BIT') if files.respond_to?(:force_encoding)
|
|
847
|
+
assert_equal 19756, files.size
|
|
848
|
+
end
|
|
849
|
+
|
|
850
|
+
private
|
|
851
|
+
def process(name)
|
|
852
|
+
File.open(File.join(FIXTURE_PATH, name), 'rb') do |file|
|
|
853
|
+
params = ActionController::AbstractRequest.parse_multipart_form_parameters(file, 'AaB03x', file.stat.size, {})
|
|
854
|
+
assert_equal 0, file.pos # file was rewound after reading
|
|
855
|
+
params
|
|
856
|
+
end
|
|
857
|
+
end
|
|
858
|
+
end
|
|
859
|
+
|
|
860
|
+
class XmlParamsParsingTest < Test::Unit::TestCase
|
|
861
|
+
def test_hash_params
|
|
862
|
+
person = parse_body("<person><name>David</name></person>")[:person]
|
|
863
|
+
assert_kind_of Hash, person
|
|
864
|
+
assert_equal 'David', person['name']
|
|
865
|
+
end
|
|
866
|
+
|
|
867
|
+
def test_single_file
|
|
868
|
+
person = parse_body("<person><name>David</name><avatar type='file' name='me.jpg' content_type='image/jpg'>#{ActiveSupport::Base64.encode64('ABC')}</avatar></person>")
|
|
869
|
+
|
|
870
|
+
assert_equal "image/jpg", person['person']['avatar'].content_type
|
|
871
|
+
assert_equal "me.jpg", person['person']['avatar'].original_filename
|
|
872
|
+
assert_equal "ABC", person['person']['avatar'].read
|
|
873
|
+
end
|
|
874
|
+
|
|
875
|
+
def test_multiple_files
|
|
876
|
+
person = parse_body(<<-end_body)
|
|
877
|
+
<person>
|
|
878
|
+
<name>David</name>
|
|
879
|
+
<avatars>
|
|
880
|
+
<avatar type='file' name='me.jpg' content_type='image/jpg'>#{ActiveSupport::Base64.encode64('ABC')}</avatar>
|
|
881
|
+
<avatar type='file' name='you.gif' content_type='image/gif'>#{ActiveSupport::Base64.encode64('DEF')}</avatar>
|
|
882
|
+
</avatars>
|
|
883
|
+
</person>
|
|
884
|
+
end_body
|
|
885
|
+
|
|
886
|
+
assert_equal "image/jpg", person['person']['avatars']['avatar'].first.content_type
|
|
887
|
+
assert_equal "me.jpg", person['person']['avatars']['avatar'].first.original_filename
|
|
888
|
+
assert_equal "ABC", person['person']['avatars']['avatar'].first.read
|
|
889
|
+
|
|
890
|
+
assert_equal "image/gif", person['person']['avatars']['avatar'].last.content_type
|
|
891
|
+
assert_equal "you.gif", person['person']['avatars']['avatar'].last.original_filename
|
|
892
|
+
assert_equal "DEF", person['person']['avatars']['avatar'].last.read
|
|
893
|
+
end
|
|
894
|
+
|
|
895
|
+
private
|
|
896
|
+
def parse_body(body)
|
|
897
|
+
env = { 'CONTENT_TYPE' => 'application/xml',
|
|
898
|
+
'CONTENT_LENGTH' => body.size.to_s }
|
|
899
|
+
cgi = ActionController::Integration::Session::StubCGI.new(env, body)
|
|
900
|
+
ActionController::CgiRequest.new(cgi).request_parameters
|
|
901
|
+
end
|
|
902
|
+
end
|
|
903
|
+
|
|
904
|
+
class LegacyXmlParamsParsingTest < XmlParamsParsingTest
|
|
905
|
+
private
|
|
906
|
+
def parse_body(body)
|
|
907
|
+
env = { 'HTTP_X_POST_DATA_FORMAT' => 'xml',
|
|
908
|
+
'CONTENT_LENGTH' => body.size.to_s }
|
|
909
|
+
cgi = ActionController::Integration::Session::StubCGI.new(env, body)
|
|
910
|
+
ActionController::CgiRequest.new(cgi).request_parameters
|
|
911
|
+
end
|
|
912
|
+
end
|
|
913
|
+
|
|
914
|
+
class JsonParamsParsingTest < Test::Unit::TestCase
|
|
915
|
+
def test_hash_params
|
|
916
|
+
person = parse_body({:person => {:name => "David"}}.to_json)[:person]
|
|
917
|
+
assert_kind_of Hash, person
|
|
918
|
+
assert_equal 'David', person['name']
|
|
919
|
+
end
|
|
920
|
+
|
|
921
|
+
private
|
|
922
|
+
def parse_body(body)
|
|
923
|
+
env = { 'CONTENT_TYPE' => 'application/json',
|
|
924
|
+
'CONTENT_LENGTH' => body.size.to_s }
|
|
925
|
+
cgi = ActionController::Integration::Session::StubCGI.new(env, body)
|
|
926
|
+
ActionController::CgiRequest.new(cgi).request_parameters
|
|
927
|
+
end
|
|
928
|
+
end
|