diff options
Diffstat (limited to 'actionview')
-rw-r--r-- | actionview/CHANGELOG.md | 7 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/number_helper.rb | 8 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/text_helper.rb | 2 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/translation_helper.rb | 10 | ||||
-rw-r--r-- | actionview/test/template/erb_util_test.rb | 46 | ||||
-rw-r--r-- | actionview/test/template/text_helper_test.rb | 5 | ||||
-rw-r--r-- | actionview/test/template/translation_helper_test.rb | 6 |
7 files changed, 79 insertions, 5 deletions
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index d53b321f97..9e58c193b1 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,10 @@ +* Fixed a long-standing bug in `json_escape` that causes quotation marks to be stripped. + This method also escapes the \u2028 and \u2029 unicode newline characters which are + treated as \n in JavaScript. This matches the behaviour of the AS::JSON encoder. (The + original change in the encoder was introduced in #10534.) + + *Godfrey Chan* + * `ActionView::MissingTemplate` includes underscore when raised for a partial. Fixes #13002. diff --git a/actionview/lib/action_view/helpers/number_helper.rb b/actionview/lib/action_view/helpers/number_helper.rb index 13387078a4..ad825cd1f1 100644 --- a/actionview/lib/action_view/helpers/number_helper.rb +++ b/actionview/lib/action_view/helpers/number_helper.rb @@ -100,10 +100,10 @@ module ActionView # # number_to_currency(-1234567890.50, negative_format: "(%u%n)") # # => ($1,234,567,890.50) - # number_to_currency(1234567890.50, unit: "£", separator: ",", delimiter: "") - # # => £1234567890,50 - # number_to_currency(1234567890.50, unit: "£", separator: ",", delimiter: "", format: "%n %u") - # # => 1234567890,50 £ + # number_to_currency(1234567890.50, unit: "R$", separator: ",", delimiter: "") + # # => R$1234567890,50 + # number_to_currency(1234567890.50, unit: "R$", separator: ",", delimiter: "", format: "%n %u") + # # => 1234567890,50 R$ def number_to_currency(number, options = {}) delegate_number_helper_method(:number_to_currency, number, options) end diff --git a/actionview/lib/action_view/helpers/text_helper.rb b/actionview/lib/action_view/helpers/text_helper.rb index e75c6cabc9..3478eadbf2 100644 --- a/actionview/lib/action_view/helpers/text_helper.rb +++ b/actionview/lib/action_view/helpers/text_helper.rb @@ -31,6 +31,8 @@ module ActionView include SanitizeHelper include TagHelper + include OutputSafetyHelper + # The preferred method of outputting text in your views is to use the # <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods # do not operate as expected in an eRuby code block. If you absolutely must diff --git a/actionview/lib/action_view/helpers/translation_helper.rb b/actionview/lib/action_view/helpers/translation_helper.rb index a1a2bebb6e..3ae1df04fe 100644 --- a/actionview/lib/action_view/helpers/translation_helper.rb +++ b/actionview/lib/action_view/helpers/translation_helper.rb @@ -38,7 +38,13 @@ module ActionView # 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 options.key?(:raise) || options.key?(:rescue_format) + raise_error = options[:raise] || options[:rescue_format] + else + raise_error = false + options[:raise] = true + end + if html_safe_translation_key?(key) html_safe_options = options.dup options.except(*I18n::RESERVED_KEYS).each do |name, value| @@ -53,6 +59,8 @@ module ActionView I18n.translate(scope_key_by_partial(key), options) end rescue I18n::MissingTranslationData => e + raise e if raise_error + 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 diff --git a/actionview/test/template/erb_util_test.rb b/actionview/test/template/erb_util_test.rb index 9a7c617eb3..9bacbba908 100644 --- a/actionview/test/template/erb_util_test.rb +++ b/actionview/test/template/erb_util_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'active_support/json' class ErbUtilTest < ActiveSupport::TestCase include ERB::Util @@ -15,6 +16,51 @@ class ErbUtilTest < ActiveSupport::TestCase end end + HTML_ESCAPE_TEST_CASES = [ + ['<br>', '<br>'], + ['a & b', 'a & b'], + ['"quoted" string', '"quoted" string'], + ["'quoted' string", ''quoted' string'], + [ + '<script type="application/javascript">alert("You are \'pwned\'!")</script>', + '<script type="application/javascript">alert("You are 'pwned'!")</script>' + ] + ] + + JSON_ESCAPE_TEST_CASES = [ + ['1', '1'], + ['null', 'null'], + ['"&"', '"\u0026"'], + ['"</script>"', '"\u003c/script\u003e"'], + ['["</script>"]', '["\u003c/script\u003e"]'], + ['{"name":"</script>"}', '{"name":"\u003c/script\u003e"}'], + [%({"name":"d\u2028h\u2029h"}), '{"name":"d\u2028h\u2029h"}'] + ] + + def test_html_escape + HTML_ESCAPE_TEST_CASES.each do |(raw, expected)| + assert_equal expected, html_escape(raw) + end + end + + def test_json_escape + JSON_ESCAPE_TEST_CASES.each do |(raw, expected)| + assert_equal expected, json_escape(raw) + end + end + + def test_json_escape_does_not_alter_json_string_meaning + JSON_ESCAPE_TEST_CASES.each do |(raw, _)| + assert_equal ActiveSupport::JSON.decode(raw), ActiveSupport::JSON.decode(json_escape(raw)) + end + end + + def test_json_escape_is_idempotent + JSON_ESCAPE_TEST_CASES.each do |(raw, _)| + assert_equal json_escape(raw), json_escape(json_escape(raw)) + end + end + def test_json_escape_returns_unsafe_strings_when_passed_unsafe_strings value = json_escape("asdf") assert !value.html_safe? diff --git a/actionview/test/template/text_helper_test.rb b/actionview/test/template/text_helper_test.rb index dd1a92acfb..5b3bccf951 100644 --- a/actionview/test/template/text_helper_test.rb +++ b/actionview/test/template/text_helper_test.rb @@ -21,6 +21,11 @@ class TextHelperTest < ActionView::TestCase assert simple_format("<b> test with html tags </b>").html_safe? end + def test_simple_format_included_in_isolation + helper_klass = Class.new { include ActionView::Helpers::TextHelper } + assert helper_klass.new.simple_format("<b> test with html tags </b>").html_safe? + end + def test_simple_format assert_equal "<p></p>", simple_format(nil) diff --git a/actionview/test/template/translation_helper_test.rb b/actionview/test/template/translation_helper_test.rb index 0dfe47f5f4..269714fad0 100644 --- a/actionview/test/template/translation_helper_test.rb +++ b/actionview/test/template/translation_helper_test.rb @@ -53,6 +53,12 @@ class TranslationHelperTest < ActiveSupport::TestCase assert_equal false, translate(:"translations.missing", :rescue_format => nil).html_safe? end + def test_raises_missing_translation_message_with_raise_option + assert_raise(I18n::MissingTranslationData) do + translate(:"translations.missing", :raise => true) + end + end + def test_i18n_translate_defaults_to_nil_rescue_format expected = 'translation missing: en.translations.missing' assert_equal expected, I18n.translate(:"translations.missing") |