diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 7abaa07bc7e201c7980b028cde1ae34e929409d6..e78d3a82be56d2216f3cc93ab35cdbee84dd91eb 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -142,8 +142,12 @@ def query(path, details, formats) # Helper for building query glob string based on resolver's pattern. def build_query(path, details) query = @pattern.dup - query.gsub!(/\:prefix(\/)?/, path.prefix.empty? ? "" : "#{path.prefix}\\1") # prefix can be empty... - query.gsub!(/\:action/, path.partial? ? "_#{path.name}" : path.name) + + prefix = path.prefix.empty? ? "" : "#{escape_entry(path.prefix)}\\1" + query.gsub!(/\:prefix(\/)?/, prefix) + + partial = escape_entry(path.partial? ? "_#{path.name}" : path.name) + query.gsub!(/\:action/, partial) details.each do |ext, variants| query.gsub!(/\:#{ext}/, "{#{variants.compact.uniq.join(',')}}") @@ -152,6 +156,10 @@ def build_query(path, details) File.expand_path(query, @path) end + def escape_entry(entry) + entry.gsub(/(\*|\[|\]|\{|\}|\?)/, "\\\\\\1") + end + # Returns the file mtime from the filesystem. def mtime(p) File.mtime(p) @@ -228,8 +236,9 @@ def eql?(resolver) class OptimizedFileSystemResolver < FileSystemResolver #:nodoc: def build_query(path, details) exts = EXTENSIONS.map { |ext| details[ext] } + query = escape_entry(File.join(@path, path)) - File.join(@path, path) + exts.map { |ext| + query + exts.map { |ext| "{#{ext.compact.uniq.map { |e| ".#{e}," }.join}}" }.join end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index ce4b407c7ddca5aeb44f0771cbc21f6130f06812..6bcd606bf4c7c86bc11211fef7eacbcca323d86c 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -405,6 +405,14 @@ def render_with_explicit_template render :template => "test/hello_world" end + def render_with_explicit_unescaped_template + render :template => "test/h*llo_world" + end + + def render_with_explicit_escaped_template + render :template => "test/hello_w*rld" + end + def render_with_explicit_string_template render "test/hello_world" end @@ -1057,6 +1065,12 @@ def test_render_with_explicit_template assert_response :success end + def test_render_with_explicit_unescaped_template + assert_raise(ActionView::MissingTemplate) { get :render_with_explicit_unescaped_template } + get :render_with_explicit_escaped_template + assert_equal "Hello w*rld!", @response.body + end + def test_render_with_explicit_string_template get :render_with_explicit_string_template assert_equal "Hello world!", @response.body diff --git a/actionpack/test/fixtures/test/hello_w*rld.erb b/actionpack/test/fixtures/test/hello_w*rld.erb new file mode 100644 index 0000000000000000000000000000000000000000..bc8fa5e0ca9612bd877d00794071d8a0e966fc21 --- /dev/null +++ b/actionpack/test/fixtures/test/hello_w*rld.erb @@ -0,0 +1 @@ +Hello w*rld! \ No newline at end of file