mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Fixed optimized route segment escaping. Closes #9562.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7487 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
3f29043f45
commit
148202d401
4 changed files with 38 additions and 30 deletions
|
@ -1,5 +1,7 @@
|
||||||
*SVN*
|
*SVN*
|
||||||
|
|
||||||
|
* Fixed optimized route segment escaping. #9562 [wildchild, Jeremy Kemper]
|
||||||
|
|
||||||
* root_path returns '/' not ''. #9563 [lifofifo]
|
* root_path returns '/' not ''. #9563 [lifofifo]
|
||||||
|
|
||||||
* Fixed that setting request.format should also affect respond_to blocks [DHH]
|
* Fixed that setting request.format should also affect respond_to blocks [DHH]
|
||||||
|
|
|
@ -718,8 +718,8 @@ module ActionController
|
||||||
s << "\n#{expiry_statement}"
|
s << "\n#{expiry_statement}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def interpolation_chunk
|
def interpolation_chunk(value_code = "#{local_name}.to_s")
|
||||||
"\#{URI.escape(#{local_name}.to_s, ActionController::Routing::Segment::UNSAFE_PCHAR)}"
|
"\#{URI.escape(#{value_code}, ActionController::Routing::Segment::UNSAFE_PCHAR)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def string_structure(prior_segments)
|
def string_structure(prior_segments)
|
||||||
|
@ -776,8 +776,8 @@ module ActionController
|
||||||
end
|
end
|
||||||
|
|
||||||
# Don't URI.escape the controller name since it may contain slashes.
|
# Don't URI.escape the controller name since it may contain slashes.
|
||||||
def interpolation_chunk
|
def interpolation_chunk(value_code = "#{local_name}.to_s")
|
||||||
"\#{#{local_name}.to_s}"
|
"\#{#{value_code}}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Make sure controller names like Admin/Content are correctly normalized to
|
# Make sure controller names like Admin/Content are correctly normalized to
|
||||||
|
@ -799,8 +799,8 @@ module ActionController
|
||||||
RESERVED_PCHAR = "#{Segment::RESERVED_PCHAR}/"
|
RESERVED_PCHAR = "#{Segment::RESERVED_PCHAR}/"
|
||||||
UNSAFE_PCHAR = Regexp.new("[^#{URI::REGEXP::PATTERN::UNRESERVED}#{RESERVED_PCHAR}]", false, 'N').freeze
|
UNSAFE_PCHAR = Regexp.new("[^#{URI::REGEXP::PATTERN::UNRESERVED}#{RESERVED_PCHAR}]", false, 'N').freeze
|
||||||
|
|
||||||
def interpolation_chunk
|
def interpolation_chunk(value_code = "#{local_name}.to_s")
|
||||||
"\#{URI.escape(#{local_name}.to_s, ActionController::Routing::PathSegment::UNSAFE_PCHAR)}"
|
"\#{URI.escape(#{value_code}, ActionController::Routing::PathSegment::UNSAFE_PCHAR)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def default
|
def default
|
||||||
|
@ -1150,34 +1150,33 @@ module ActionController
|
||||||
@module.send(:protected, selector)
|
@module.send(:protected, selector)
|
||||||
helpers << selector
|
helpers << selector
|
||||||
end
|
end
|
||||||
|
|
||||||
def define_url_helper(route, name, kind, options)
|
def define_url_helper(route, name, kind, options)
|
||||||
selector = url_helper_name(name, kind)
|
selector = url_helper_name(name, kind)
|
||||||
# The segment keys used for positional paramters
|
# The segment keys used for positional paramters
|
||||||
|
|
||||||
hash_access_method = hash_access_name(name, kind)
|
hash_access_method = hash_access_name(name, kind)
|
||||||
|
|
||||||
|
# allow ordered parameters to be associated with corresponding
|
||||||
|
# dynamic segments, so you can do
|
||||||
|
#
|
||||||
|
# foo_url(bar, baz, bang)
|
||||||
|
#
|
||||||
|
# instead of
|
||||||
|
#
|
||||||
|
# foo_url(:bar => bar, :baz => baz, :bang => bang)
|
||||||
|
#
|
||||||
|
# Also allow options hash, so you can do
|
||||||
|
#
|
||||||
|
# foo_url(bar, baz, bang, :sort_by => 'baz')
|
||||||
|
#
|
||||||
@module.send :module_eval, <<-end_eval # We use module_eval to avoid leaks
|
@module.send :module_eval, <<-end_eval # We use module_eval to avoid leaks
|
||||||
def #{selector}(*args)
|
def #{selector}(*args)
|
||||||
|
|
||||||
#{generate_optimisation_block(route, kind)}
|
#{generate_optimisation_block(route, kind)}
|
||||||
|
|
||||||
opts = if args.empty? || Hash === args.first
|
opts = if args.empty? || Hash === args.first
|
||||||
args.first || {}
|
args.first || {}
|
||||||
else
|
else
|
||||||
# allow ordered parameters to be associated with corresponding
|
|
||||||
# dynamic segments, so you can do
|
|
||||||
#
|
|
||||||
# foo_url(bar, baz, bang)
|
|
||||||
#
|
|
||||||
# instead of
|
|
||||||
#
|
|
||||||
# foo_url(:bar => bar, :baz => baz, :bang => bang)
|
|
||||||
#
|
|
||||||
# Also allow options hash, so you can do
|
|
||||||
#
|
|
||||||
# foo_url(bar, baz, bang, :sort_by => 'baz')
|
|
||||||
#
|
|
||||||
options = args.last.is_a?(Hash) ? args.pop : {}
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
||||||
args = args.zip(#{route.segment_keys.inspect}).inject({}) do |h, (v, k)|
|
args = args.zip(#{route.segment_keys.inspect}).inject({}) do |h, (v, k)|
|
||||||
h[k] = v
|
h[k] = v
|
||||||
|
@ -1185,7 +1184,7 @@ module ActionController
|
||||||
end
|
end
|
||||||
options.merge(args)
|
options.merge(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
url_for(#{hash_access_method}(opts))
|
url_for(#{hash_access_method}(opts))
|
||||||
end
|
end
|
||||||
end_eval
|
end_eval
|
||||||
|
@ -1193,7 +1192,7 @@ module ActionController
|
||||||
helpers << selector
|
helpers << selector
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_accessor :routes, :named_routes
|
attr_accessor :routes, :named_routes
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
|
@ -1445,4 +1444,4 @@ module ActionController
|
||||||
|
|
||||||
Routes = RouteSet.new
|
Routes = RouteSet.new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -56,7 +56,6 @@ module ActionController
|
||||||
elements = []
|
elements = []
|
||||||
idx = 0
|
idx = 0
|
||||||
|
|
||||||
|
|
||||||
if kind == :url
|
if kind == :url
|
||||||
elements << '#{request.protocol}'
|
elements << '#{request.protocol}'
|
||||||
elements << '#{request.host_with_port}'
|
elements << '#{request.host_with_port}'
|
||||||
|
@ -67,10 +66,10 @@ module ActionController
|
||||||
# we don't include the trailing slashes, so skip them.
|
# we don't include the trailing slashes, so skip them.
|
||||||
((route.segments.size == 1 && kind == :path) ? route.segments : route.segments[0..-2]).each do |segment|
|
((route.segments.size == 1 && kind == :path) ? route.segments : route.segments[0..-2]).each do |segment|
|
||||||
if segment.is_a?(DynamicSegment)
|
if segment.is_a?(DynamicSegment)
|
||||||
elements << "\#{URI.escape(args[#{idx}].to_param, ActionController::Routing::Segment::UNSAFE_PCHAR)}"
|
elements << segment.interpolation_chunk("args[#{idx}].to_param")
|
||||||
idx += 1
|
idx += 1
|
||||||
else
|
else
|
||||||
elements << segment.to_s
|
elements << segment.interpolation_chunk
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
%("#{elements * ''}")
|
%("#{elements * ''}")
|
||||||
|
|
|
@ -273,6 +273,14 @@ class LegacyRouteSetTests < Test::Unit::TestCase
|
||||||
assert_equal [], results[:path]
|
assert_equal [], results[:path]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_paths_slashes_unescaped_with_ordered_parameters
|
||||||
|
rs.add_named_route :path, '/file/*path', :controller => 'content'
|
||||||
|
|
||||||
|
# No / to %2F in URI, only for query params.
|
||||||
|
x = setup_for_named_route
|
||||||
|
assert_equal("/file/hello/world", x.send(:path_path, 'hello/world'))
|
||||||
|
end
|
||||||
|
|
||||||
def test_non_controllers_cannot_be_matched
|
def test_non_controllers_cannot_be_matched
|
||||||
rs.draw do |map|
|
rs.draw do |map|
|
||||||
map.connect ':controller/:action/:id'
|
map.connect ':controller/:action/:id'
|
||||||
|
|
Loading…
Reference in a new issue