1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge branch 'master-sec'

* master-sec:
  Deep Munge the parameters for GET and POST
  Stop using i18n's built in HTML error handling.
  Ensure simple_format escapes its html attributes
  Escape the unit value provided to number_to_currency
  Only use valid mime type symbols as cache keys
This commit is contained in:
Aaron Patterson 2013-12-03 11:01:56 -08:00
commit dba82120fe
8 changed files with 38 additions and 18 deletions

View file

@ -271,7 +271,7 @@ module ActionDispatch
# Override Rack's GET method to support indifferent access
def GET
@env["action_dispatch.request.query_parameters"] ||= (normalize_encode_params(super) || {})
@env["action_dispatch.request.query_parameters"] ||= deep_munge((normalize_encode_params(super) || {}))
rescue TypeError => e
raise ActionController::BadRequest.new(:query, e)
end
@ -279,7 +279,7 @@ module ActionDispatch
# Override Rack's POST method to support indifferent access
def POST
@env["action_dispatch.request.request_parameters"] ||= (normalize_encode_params(super) || {})
@env["action_dispatch.request.request_parameters"] ||= deep_munge((normalize_encode_params(super) || {}))
rescue TypeError => e
raise ActionController::BadRequest.new(:request, e)
end

View file

@ -11,6 +11,17 @@ class QueryStringParsingTest < ActionDispatch::IntegrationTest
head :ok
end
end
class EarlyParse
def initialize(app)
@app = app
end
def call(env)
# Trigger a Rack parse so that env caches the query params
Rack::Request.new(env).params
@app.call(env)
end
end
def teardown
TestController.last_query_parameters = nil
@ -131,6 +142,10 @@ class QueryStringParsingTest < ActionDispatch::IntegrationTest
set.draw do
get ':action', :to => ::QueryStringParsingTest::TestController
end
@app = self.class.build_app(set) do |middleware|
middleware.use(EarlyParse)
end
get "/parse", actual
assert_response :ok

View file

@ -394,6 +394,7 @@ module ActionView
def escape_unsafe_delimiters_and_separators(options)
options[:separator] = ERB::Util.html_escape(options[:separator]) if options[:separator] && !options[:separator].html_safe?
options[:delimiter] = ERB::Util.html_escape(options[:delimiter]) if options[:delimiter] && !options[:delimiter].html_safe?
options[:unit] = ERB::Util.html_escape(options[:unit]) if options[:unit] && !options[:unit].html_safe?
options
end

View file

@ -268,7 +268,7 @@ module ActionView
content_tag(wrapper_tag, nil, html_options)
else
paragraphs.map! { |paragraph|
content_tag(wrapper_tag, paragraph, html_options, false)
content_tag(wrapper_tag, raw(paragraph), html_options, false)
}.join("\n\n").html_safe
end
end

View file

@ -1,24 +1,14 @@
require 'action_view/helpers/tag_helper'
require 'i18n/exceptions'
module I18n
class ExceptionHandler
include Module.new {
def call(exception, locale, key, options)
exception.is_a?(MissingTranslation) && options[:rescue_format] == :html ? super.html_safe : super
end
}
end
end
module ActionView
# = Action View Translation Helpers
module Helpers
module TranslationHelper
# Delegates to <tt>I18n#translate</tt> but also performs three additional functions.
#
# First, it'll pass the <tt>rescue_format: :html</tt> option to I18n so that any
# thrown +MissingTranslation+ messages will be turned into inline spans that
# First, it will ensure that any thrown +MissingTranslation+ messages will be turned
# into inline spans that:
#
# * have a "translation-missing" class set,
# * contain the missing key as a title attribute and
@ -44,8 +34,11 @@ module ActionView
# naming convention helps to identify translations that include HTML tags so that
# you know what kind of output to expect when you call translate in a template.
def translate(key, options = {})
options.merge!(:rescue_format => :html) unless options.key?(:rescue_format)
options[:default] = wrap_translate_defaults(options[:default]) if options[:default]
# If the user has specified rescue_format then pass it all through, otherwise use
# raise and do the work ourselves
options[:raise] = true unless options.key?(:raise) || options.key?(:rescue_format)
if html_safe_translation_key?(key)
html_safe_options = options.dup
options.except(*I18n::RESERVED_KEYS).each do |name, value|
@ -59,6 +52,9 @@ module ActionView
else
I18n.translate(scope_key_by_partial(key), options)
end
rescue I18n::MissingTranslationData => e
keys = I18n.normalize_keys(e.locale, e.key, e.options[:scope])
content_tag('span', keys.last.to_s.titleize, :class => 'translation_missing', :title => "translation missing: #{keys.join('.')}")
end
alias :t :translate

View file

@ -62,6 +62,13 @@ module ActionView
@details_keys = ThreadSafe::Cache.new
def self.get(details)
if details[:formats]
details = details.dup
syms = Set.new Mime::SET.symbols
details[:formats] = details[:formats].select { |v|
syms.include? v
}
end
@details_keys[details] ||= new
end

View file

@ -14,7 +14,8 @@ class NumberHelperTest < ActionView::TestCase
assert_equal nil, number_to_currency(nil)
assert_equal "$1,234,567,890.50", number_to_currency(1234567890.50)
assert_equal "$1,234,567,892", number_to_currency(1234567891.50, precision: 0)
assert_equal "1,234,567,890.50 - K&#269;", number_to_currency("-1234567890.50", unit: "K&#269;", format: "%n %u", negative_format: "%n - %u")
assert_equal "1,234,567,890.50 - K&#269;", number_to_currency("-1234567890.50", unit: raw("K&#269;"), format: "%n %u", negative_format: "%n - %u")
assert_equal "&amp;pound;1,234,567,890.50", number_to_currency("1234567890.50", unit: "&pound;")
end
def test_number_to_percentage

View file

@ -31,7 +31,7 @@ class TranslationHelperTest < ActiveSupport::TestCase
end
def test_delegates_to_i18n_setting_the_rescue_format_option_to_html
I18n.expects(:translate).with(:foo, :locale => 'en', :rescue_format => :html).returns("")
I18n.expects(:translate).with(:foo, :locale => 'en', :raise=>true).returns("")
translate :foo, :locale => 'en'
end