diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index bfad9f8d31..4c76e9642f 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -74,6 +74,7 @@ module ActionView options.reverse_merge!(:length => 30) + text = sanitize(text) unless text.html_safe? || options[:safe] text.truncate(options.delete(:length), options) if text end @@ -105,6 +106,7 @@ module ActionView end options.reverse_merge!(:highlighter => '\1') + text = sanitize(text) unless text.html_safe? || options[:safe] if text.blank? || phrases.blank? text else @@ -244,13 +246,14 @@ module ActionView # def textilize(text, *options) options ||= [:hard_breaks] + text = sanitize(text) unless text.html_safe? || options.delete(:safe) if text.blank? "" else textilized = RedCloth.new(text, options) textilized.to_html - end + end.html_safe end # Returns the text with all the Textile codes turned into HTML tags, @@ -271,8 +274,8 @@ module ActionView # # textilize_without_paragraph("Visit the Rails website "here":http://www.rubyonrails.org/.) # # => "Visit the Rails website here." - def textilize_without_paragraph(text) - textiled = textilize(text) + def textilize_without_paragraph(text, *options) + textiled = textilize(text, options) if textiled[0..2] == "
" then textiled = textiled[3..-1] end if textiled[-4..-1] == "
" then textiled = textiled[0..-5] end return textiled @@ -295,8 +298,9 @@ module ActionView # # markdown('![The ROR logo](http://rubyonrails.com/images/rails.png "Ruby on Rails")') # # => '' - def markdown(text) - text.blank? ? "" : BlueCloth.new(text).to_html + def markdown(text, options = {}) + text = sanitize(text) unless options[:safe] + (text.blank? ? "" : BlueCloth.new(text).to_html).html_safe end # Returns +text+ transformed into HTML using simple formatting rules. @@ -320,14 +324,15 @@ module ActionView # # simple_format("Look ma! A class!", :class => 'description') # # => "Look ma! A class!
" - def simple_format(text, html_options={}) + def simple_format(text, html_options={}, options={}) + text = '' if text.nil? start_tag = tag('p', html_options, true) - text = h(text) + text = sanitize(text) unless text.html_safe? || options[:safe] text.gsub!(/\r\n?/, "\n") # \r\n and \r -> \n text.gsub!(/\n\n+/, "\n\n#{start_tag}") # 2+ newline -> paragraph text.gsub!(/([^\n]\n)(?=[^\n])/, '\1<b> test with unsafe string </b>
", simple_format(" test with unsafe string ") + def test_simple_format_should_sanitize_unsafe_input + assert_equal "test with unsafe string
", simple_format(" test with unsafe string ") end - def test_simple_format_should_not_escape_safe_input + def test_simple_format_should_not_sanitize_input_if_safe_option + assert_equal "test with unsafe string
", simple_format(" test with unsafe string ", {}, :safe => true) + end + + def test_simple_format_should_not_sanitize_safe_input assert_equal "test with safe string
", simple_format(" test with safe string ".html_safe) end + def test_truncate_should_be_html_safe + assert truncate("Hello World!", :length => 12).html_safe? + end + def test_truncate assert_equal "Hello World!", truncate("Hello World!", :length => 12) assert_equal "Hello Wor...", truncate("Hello World!!", :length => 12) end + def test_truncate_should_sanitize_unsafe_input + assert_equal "Hello World!", truncate("Hello World!", :length => 12) + assert_equal "Hello Wor...", truncate("Hello World!!", :length => 12) + end + + def test_truncate_should_not_sanitize_input_if_safe_option + assert_equal "HelloThis is a beautiful morning, but also a beautiful day
", "beautiful") ) assert_equal( - "This is a beautiful morning, but also a beautiful day
", + "This is a beautiful morning, but also a beautiful day
", highlight("This is a beautiful morning, but also a beautiful day
", "beautiful") ) end @@ -286,7 +334,17 @@ class TextHelperTest < ActionView::TestCase %{#{CGI::escapeHTML link_text}} end - def test_auto_linking + def test_auto_link_should_be_html_safe + email_raw = 'santiago@wyeworks.com' + link_raw = 'http://www.rubyonrails.org' + + assert auto_link(nil).html_safe? + assert auto_link('').html_safe? + assert auto_link("#{link_raw} #{link_raw} #{link_raw}").html_safe? + assert auto_link("hello #{email_raw}").html_safe? + end + + def test_auto_link email_raw = 'david@loudthinking.com' email_result = %{#{email_raw}} link_raw = 'http://www.rubyonrails.com' @@ -378,6 +436,21 @@ class TextHelperTest < ActionView::TestCase assert_equal %(#{link10_result} Link
), auto_link("#{link10_raw} Link
") end + def test_auto_link_should_sanitize_unsafe_input + link_raw = %{http://www.rubyonrails.com?id=1&num=2} + assert_equal %{http://www.rubyonrails.com?id=1&num=2}, auto_link(link_raw) + end + + def test_auto_link_should_sanitize_unsafe_input + link_raw = %{http://www.rubyonrails.com?id=1&num=2} + assert_equal %{http://www.rubyonrails.com?id=1&num=2}, auto_link(link_raw, :safe => true) + end + + def test_auto_link_should_not_sanitize_safe_input + link_raw = %{http://www.rubyonrails.com?id=1&num=2} + assert_equal %{http://www.rubyonrails.com?id=1&num=2}, auto_link(link_raw.html_safe) + end + def test_auto_link_other_protocols ftp_raw = 'ftp://example.com/file.txt' assert_equal %(Download #{generate_result(ftp_raw)}), auto_link("Download #{ftp_raw}") @@ -587,7 +660,12 @@ class TextHelperTest < ActionView::TestCase assert_equal(%w{Specialized Fuji Giant}, @cycles) end + # TODO test textilize_without_paragraph and markdown if defined? RedCloth + def test_textilize_should_be_html_safe + assert textilize("*This is Textile!* Rejoice!").html_safe? + end + def test_textilize assert_equal("This is Textile! Rejoice!
", textilize("*This is Textile!* Rejoice!")) end @@ -600,6 +678,18 @@ class TextHelperTest < ActionView::TestCase assert_equal("This is worded <strong>strongly</strong>
", textilize("This is worded strongly", :filter_html)) end + def test_textilize_should_sanitize_unsafe_input + assert_equal("This is worded strongly
", textilize("This is worded strongly")) + end + + def test_textilize_should_not_sanitize_input_if_safe_option + assert_equal("This is worded strongly
", textilize("This is worded strongly", :safe)) + end + + def test_textilize_should_not_sanitize_safe_input + assert_equal("This is worded strongly
", textilize("This is worded strongly".html_safe)) + end + def test_textilize_with_hard_breaks assert_equal("This is one scary world.
\n True.