Skip to content
This repository
Browse code

Routing: better support for escaped values in route segments. Closes #…

…7544.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6185 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit de0a0d700e8c3959a3503152b9a495616afbeae5 1 parent f298576
Jeremy Kemper jeremy authored
3  actionpack/CHANGELOG
... ... @@ -1,5 +1,8 @@
1 1 *SVN*
2 2
  3 +* Routing: better support for escaped values in route segments. #7544 [Chris
  4 +Roos]
  5 +
3 6 * Introduce a cookie-based session store as the Rails default. Sessions typically contain at most a user_id and flash message; both fit within the 4K cookie size limit. A secure hash is included with the cookie to ensure data integrity (a user cannot alter his user_id without knowing the secret key included in the hash). If you have more than 4K of session data or don't want your data to be visible to the user, pick another session store. Cookie-based sessions are dramatically faster than the alternatives. [Jeremy Kemper]
4 7
5 8 * Added .erb and .builder as preferred aliases to the now deprecated .rhtml and .rxml extensions [Chad Fowler]. This is done to separate the renderer from the mime type. .erb templates are often used to render emails, atom, csv, whatever. So labeling them .rhtml doesn't make too much sense. The same goes for .rxml, which can be used to build everything from HTML to Atom to whatever. .rhtml and .rxml will continue to work until Rails 3.0, though. So this is a slow phasing out. All generators and examples will start using the new aliases, though.
18 actionpack/lib/action_controller/routing.rb
@@ -412,7 +412,7 @@ def recognition_pattern(wrap = true)
412 412 def recognition_extraction
413 413 next_capture = 1
414 414 extraction = segments.collect do |segment|
415   - x = segment.match_extraction next_capture
  415 + x = segment.match_extraction(next_capture)
416 416 next_capture += Regexp.new(segment.regexp_chunk).number_of_captures
417 417 x
418 418 end
@@ -694,7 +694,7 @@ def extraction_code
694 694 end
695 695
696 696 def interpolation_chunk
697   - "\#{URI.escape(#{local_name}.to_s)}"
  697 + "\#{CGI.escape(#{local_name}.to_s)}"
698 698 end
699 699
700 700 def string_structure(prior_segments)
@@ -725,10 +725,17 @@ def build_pattern(pattern)
725 725 optional? ? Regexp.optionalize(pattern) : pattern
726 726 end
727 727 def match_extraction(next_capture)
728   - hangon = (default ? "|| #{default.inspect}" : "if match[#{next_capture}]")
729   -
730 728 # All non code-related keys (such as :id, :slug) have to be unescaped as other CGI params
731   - "params[:#{key}] = match[#{next_capture}] #{hangon}"
  729 + default_value = default ? default.inspect : nil
  730 + %[
  731 + value = if (m = match[#{next_capture}])
  732 + m = m.gsub('+', '%2B')
  733 + CGI.unescape(m)
  734 + else
  735 + #{default_value}
  736 + end
  737 + params[:#{key}] = value if value
  738 + ]
732 739 end
733 740
734 741 def optionality_implied?
@@ -1292,7 +1299,6 @@ def recognize(request)
1292 1299 end
1293 1300
1294 1301 def recognize_path(path, environment={})
1295   - path = URI.unescape(path)
1296 1302 routes.each do |route|
1297 1303 result = route.recognize(path, environment) and return result
1298 1304 end
40 actionpack/test/controller/routing_test.rb
@@ -13,6 +13,46 @@ def warn(msg)
13 13 end
14 14 end
15 15
  16 +class UriReservedCharactersRoutingTest < Test::Unit::TestCase
  17 + # See RFC 3986, section 2.2 Reserved Characters
  18 +
  19 + def setup
  20 + ActionController::Routing.use_controllers! ['controller']
  21 + @set = ActionController::Routing::RouteSet.new
  22 + @set.draw do |map|
  23 + map.connect ':controller/:action/:var'
  24 + end
  25 + end
  26 +
  27 + def test_should_escape_reserved_uri_characters_within_individual_path_components
  28 + assert_equal '/controller/action/p1%3Ap2', @set.generate(:controller => 'controller', :action => 'action', :var => 'p1:p2')
  29 + assert_equal '/controller/action/p1%2Fp2', @set.generate(:controller => 'controller', :action => 'action', :var => 'p1/p2')
  30 + assert_equal '/controller/action/p1%3Fp2', @set.generate(:controller => 'controller', :action => 'action', :var => 'p1?p2')
  31 + assert_equal '/controller/action/p1%23p2', @set.generate(:controller => 'controller', :action => 'action', :var => 'p1#p2')
  32 + assert_equal '/controller/action/p1%5Bp2', @set.generate(:controller => 'controller', :action => 'action', :var => 'p1[p2')
  33 + assert_equal '/controller/action/p1%5Dp2', @set.generate(:controller => 'controller', :action => 'action', :var => 'p1]p2')
  34 + assert_equal '/controller/action/p1%40p2', @set.generate(:controller => 'controller', :action => 'action', :var => 'p1@p2')
  35 + end
  36 +
  37 + def test_should_recognize_escaped_path_component_and_unescape
  38 + expected_options = {:var => "p1:p2", :controller => "controller", :action => "action"}
  39 + assert_equal expected_options, @set.recognize_path('/controller/action/p1%3Ap2')
  40 + expected_options = {:var => "p1/p2", :controller => "controller", :action => "action"}
  41 + assert_equal expected_options, @set.recognize_path('/controller/action/p1%2Fp2')
  42 + expected_options = {:var => "p1?p2", :controller => "controller", :action => "action"}
  43 + assert_equal expected_options, @set.recognize_path('/controller/action/p1%3Fp2')
  44 + expected_options = {:var => "p1#p2", :controller => "controller", :action => "action"}
  45 + assert_equal expected_options, @set.recognize_path('/controller/action/p1%23p2')
  46 + expected_options = {:var => "p1[p2", :controller => "controller", :action => "action"}
  47 + assert_equal expected_options, @set.recognize_path('/controller/action/p1%5Bp2')
  48 + expected_options = {:var => "p1]p2", :controller => "controller", :action => "action"}
  49 + assert_equal expected_options, @set.recognize_path('/controller/action/p1%5Dp2')
  50 + expected_options = {:var => "p1@p2", :controller => "controller", :action => "action"}
  51 + assert_equal expected_options, @set.recognize_path('/controller/action/p1%40p2')
  52 + end
  53 +
  54 +end
  55 +
16 56 class LegacyRouteSetTests < Test::Unit::TestCase
17 57 attr_reader :rs
18 58 def setup

0 comments on commit de0a0d7

Please sign in to comment.
Something went wrong with that request. Please try again.