提交 dba82120 编写于 作者: A Aaron Patterson

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
......@@ -271,7 +271,7 @@ def session_options=(options)
# 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 @@ def GET
# 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
......
......@@ -11,6 +11,17 @@ def parse
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 @@ def assert_parses(expected, actual)
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
......
......@@ -394,6 +394,7 @@ def delegate_number_helper_method(method, number, options)
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
......
......@@ -268,7 +268,7 @@ def simple_format(text, html_options = {}, options = {})
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
......
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 TranslationHelper
# 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 @@ def translate(key, options = {})
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
......
......@@ -62,6 +62,13 @@ class DetailsKey #:nodoc:
@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
......
......@@ -14,7 +14,8 @@ def test_number_to_currency
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
......
......@@ -31,7 +31,7 @@ def setup
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册