diff options
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/lib/active_support/core_ext/string/output_safety.rb | 46 | ||||
-rw-r--r-- | activesupport/test/safe_buffer_test.rb | 18 |
2 files changed, 62 insertions, 2 deletions
diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 3a80de4617..e3f62d7d26 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -135,10 +135,12 @@ module ActiveSupport #:nodoc: class SafeBuffer < String UNSAFE_STRING_METHODS = %w( capitalize chomp chop delete delete_prefix delete_suffix - downcase gsub lstrip next reverse rstrip slice squeeze strip - sub succ swapcase tr tr_s unicode_normalize upcase + downcase lstrip next reverse rstrip slice squeeze strip + succ swapcase tr tr_s unicode_normalize upcase ) + UNSAFE_STRING_METHODS_WITH_BACKREF = %w(gsub sub) + alias_method :original_concat, :concat private :original_concat @@ -249,11 +251,51 @@ module ActiveSupport #:nodoc: end end + UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method| + if unsafe_method.respond_to?(unsafe_method) + class_eval <<-EOT, __FILE__, __LINE__ + 1 + def #{unsafe_method}(*args, &block) + if block + to_str.#{unsafe_method}(*args) { |*params| + set_block_back_references(block, $~) + block.call(*params) + } + else + to_str.#{unsafe_method}(*args) + end + end + + def #{unsafe_method}!(*args, &block) + @html_safe = false + if block + super(*args) { |*params| + set_block_back_references(block, $~) + block.call(*params) + } + else + super + end + end + EOT + end + end + private def html_escape_interpolated_argument(arg) (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s) end + + def set_block_back_references(block, match_data) + Thread.current[:__active_support_safe_buffer_backref] = match_data + begin + block.binding.eval(<<-EOC) + $~ = Thread.current[:__active_support_safe_buffer_backref] + EOC + ensure + Thread.current[:__active_support_safe_buffer_backref] = nil + end + end end end diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb index 49a3951623..9449adb6de 100644 --- a/activesupport/test/safe_buffer_test.rb +++ b/activesupport/test/safe_buffer_test.rb @@ -216,4 +216,22 @@ class SafeBufferTest < ActiveSupport::TestCase x = "Hello".html_safe assert_nil x[/a/, 1] end + + test "Should set back references" do + a = "foo123".html_safe + a2 = a.sub(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo", a2 + assert_not_predicate a2, :html_safe? + a.sub!(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo", a + assert_not_predicate a, :html_safe? + + b = "foo123 bar456".html_safe + b2 = b.gsub(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo 456bar", b2 + assert_not_predicate b2, :html_safe? + b.gsub!(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo 456bar", b + assert_not_predicate b, :html_safe? + end end |