From ed3796434af6069ced6a641293cf88eef3b284da Mon Sep 17 00:00:00 2001
From: Bruno Michel
Date: Wed, 25 May 2011 02:42:13 +0200
Subject: [PATCH] Do not modify a safe buffer in helpers
Signed-off-by: Michael Koziarski
---
.../lib/action_view/helpers/text_helper.rb | 40 ++++++++-----------
actionpack/test/template/text_helper_test.rb | 26 ++++++++----
2 files changed, 35 insertions(+), 31 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 5e01306062d2b..c5ac1eba1b8c7 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -115,13 +115,12 @@ def highlight(text, phrases, *args)
end
options.reverse_merge!(:highlighter => '\1')
- text = sanitize(text) unless options[:sanitize] == false
- if text.blank? || phrases.blank?
- text
- else
+ if text.present? && phrases.present?
match = Array(phrases).map { |p| Regexp.escape(p) }.join('|')
- text.gsub(/(#{match})(?!(?:[^<]*?)(?:["'])[^<>]*>)/i, options[:highlighter])
- end.html_safe
+ text = text.to_str.gsub(/(#{match})(?!(?:[^<]*?)(?:["'])[^<>]*>)/i, options[:highlighter])
+ end
+ text = sanitize(text) unless options[:sanitize] == false
+ text
end
# Extracts an excerpt from +text+ that matches the first instance of +phrase+.
@@ -251,14 +250,16 @@ def word_wrap(text, *args)
# simple_format("Look ma! A class!", :class => 'description')
# # => "Look ma! A class!
"
def simple_format(text, html_options={}, options={})
- text = ''.html_safe if text.nil?
+ text = text ? text.to_str : ''
+ text = text.dup if text.frozen?
start_tag = tag('p', html_options, true)
- text = sanitize(text) unless options[:sanitize] == false
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
') # 1 newline -> br
text.insert 0, start_tag
- text.html_safe.safe_concat("")
+ text.concat("")
+ text = sanitize(text) unless options[:sanitize] == false
+ text
end
# Turns all URLs and e-mail addresses into clickable links. The :link option
@@ -477,7 +478,7 @@ def set_cycle(name, cycle_object)
# is yielded and the result is used as the link text.
def auto_link_urls(text, html_options = {}, options = {})
link_attributes = html_options.stringify_keys
- text.gsub(AUTO_LINK_RE) do
+ text.to_str.gsub(AUTO_LINK_RE) do
scheme, href = $1, $&
punctuation = []
@@ -494,14 +495,11 @@ def auto_link_urls(text, html_options = {}, options = {})
end
end
- link_text = block_given?? yield(href) : href
+ link_text = block_given? ? yield(href) : href
href = 'http://' + href unless scheme
- unless options[:sanitize] == false
- link_text = sanitize(link_text)
- href = sanitize(href)
- end
- content_tag(:a, link_text, link_attributes.merge('href' => href), !!options[:sanitize]) + punctuation.reverse.join('')
+ sanitize = options[:sanitize] != false
+ content_tag(:a, link_text, link_attributes.merge('href' => href), sanitize) + punctuation.reverse.join('')
end
end
end
@@ -509,18 +507,14 @@ def auto_link_urls(text, html_options = {}, options = {})
# Turns all email addresses into clickable links. If a block is given,
# each email is yielded and the result is used as the link text.
def auto_link_email_addresses(text, html_options = {}, options = {})
- text.gsub(AUTO_EMAIL_RE) do
+ text.to_str.gsub(AUTO_EMAIL_RE) do
text = $&
if auto_linked?($`, $')
text.html_safe
else
- display_text = (block_given?) ? yield(text) : text
-
- unless options[:sanitize] == false
- text = sanitize(text)
- display_text = sanitize(display_text) unless text == display_text
- end
+ display_text = block_given? ? yield(text) : text
+ display_text = sanitize(display_text) unless options[:sanitize] == false
mail_to text, display_text, html_options
end
end
diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb
index f0d99a0b731e4..9bc9cea14728d 100644
--- a/actionpack/test/template/text_helper_test.rb
+++ b/actionpack/test/template/text_helper_test.rb
@@ -48,6 +48,10 @@ def test_simple_format_should_not_sanitize_input_when_sanitize_option_is_false
assert_equal " test with unsafe string
", simple_format(" test with unsafe string ", {}, :sanitize => false)
end
+ def test_simple_format_should_not_be_html_safe_when_sanitize_option_is_false
+ assert !simple_format(" test with unsafe string ", {}, :sanitize => false).html_safe?
+ end
+
def test_truncate_should_not_be_html_safe
assert !truncate("Hello World!", :length => 12).html_safe?
end
@@ -166,6 +170,13 @@ def test_highlight_with_options_hash
)
end
+ def test_highlight_on_an_html_safe_string
+ assert_equal(
+ "This is a beautiful morning, but also a beautiful day
",
+ highlight("This is a beautiful morning, but also a beautiful day
".html_safe, "beautiful", :highlighter => '\1')
+ )
+ end
+
def test_highlight_with_html
assert_equal(
"This is a beautiful morning, but also a beautiful day
",
@@ -306,13 +317,10 @@ def test_auto_link_parsing
end
end
- def generate_result(link_text, href = nil, escape = false)
- href ||= link_text
- if escape
- %{#{CGI::escapeHTML link_text}}
- else
- %{#{link_text}}
- end
+ def generate_result(link_text, href = nil)
+ href = CGI::escapeHTML(href || link_text)
+ text = CGI::escapeHTML(link_text)
+ %{#{text}}
end
def test_auto_link_should_not_be_html_safe
@@ -323,6 +331,8 @@ def test_auto_link_should_not_be_html_safe
assert !auto_link('').html_safe?, 'should not be html safe'
assert !auto_link("#{link_raw} #{link_raw} #{link_raw}").html_safe?, 'should not be html safe'
assert !auto_link("hello #{email_raw}").html_safe?, 'should not be html safe'
+ assert !auto_link(link_raw.html_safe).html_safe?, 'should not be html safe'
+ assert !auto_link(email_raw.html_safe).html_safe?, 'should not be html safe'
end
def test_auto_link_email_address
@@ -425,7 +435,7 @@ def test_auto_link
def test_auto_link_should_sanitize_input_when_sanitize_option_is_not_false
link_raw = %{http://www.rubyonrails.com?id=1&num=2}
- assert_equal %{http://www.rubyonrails.com?id=1&num=2}, auto_link(link_raw)
+ assert_equal %{http://www.rubyonrails.com?id=1&num=2}, auto_link(link_raw)
end
def test_auto_link_should_not_sanitize_input_when_sanitize_option_is_false