1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Fix safe buffer by adding a dirty status.

This commit is contained in:
José Valim 2011-06-16 08:38:56 -03:00
parent 1844572fd1
commit 594603b45f
2 changed files with 55 additions and 18 deletions

View file

@ -76,10 +76,24 @@ end
module ActiveSupport #:nodoc: module ActiveSupport #:nodoc:
class SafeBuffer < String class SafeBuffer < String
UNSAFE_STRING_METHODS = ["capitalize", "chomp", "chop", "delete", "downcase", "gsub", "lstrip", "next", "reverse", "rstrip", "slice", "squeeze", "strip", "sub", "succ", "swapcase", "tr", "tr_s", "upcase"].freeze UNSAFE_STRING_METHODS = ["capitalize", "chomp", "chop", "delete", "downcase", "gsub", "lstrip", "next", "reverse", "rstrip", "slice", "squeeze", "strip", "sub", "succ", "swapcase", "tr", "tr_s", "upcase"].freeze
# TODO: Should safe_concat check if the current buffer is dirty or not?
# We should probably raise as it would mean we are adding concatenating
# to something that is safe but it actually isn't.
alias safe_concat concat alias safe_concat concat
def initialize(*)
@dirty = false
super
end
def initialize_copy(other)
super
@dirty = other.dirty?
end
def concat(value) def concat(value)
if value.html_safe? if dirty? || value.html_safe?
super(value) super(value)
else else
super(ERB::Util.h(value)) super(ERB::Util.h(value))
@ -92,11 +106,7 @@ module ActiveSupport #:nodoc:
end end
def html_safe? def html_safe?
true !dirty?
end
def html_safe
self
end end
def to_s def to_s
@ -113,7 +123,6 @@ module ActiveSupport #:nodoc:
def to_yaml(*args) def to_yaml(*args)
return super() if defined?(YAML::ENGINE) && !YAML::ENGINE.syck? return super() if defined?(YAML::ENGINE) && !YAML::ENGINE.syck?
to_str.to_yaml(*args) to_str.to_yaml(*args)
end end
@ -124,18 +133,21 @@ module ActiveSupport #:nodoc:
end end
def #{unsafe_method}!(*args) def #{unsafe_method}!(*args)
raise TypeError, "Cannot modify SafeBuffer in place" @dirty = true
super
end end
EOT EOT
end end
protected
def dirty?
@dirty
end
end end
end end
class String class String
def html_safe!
raise "You can't call html_safe! on a String"
end
def html_safe def html_safe
ActiveSupport::SafeBuffer.new(self) ActiveSupport::SafeBuffer.new(self)
end end

View file

@ -4,6 +4,7 @@ begin
rescue LoadError rescue LoadError
end end
require 'active_support/core_ext/string/inflections'
require 'yaml' require 'yaml'
class SafeBufferTest < ActiveSupport::TestCase class SafeBufferTest < ActiveSupport::TestCase
@ -45,7 +46,7 @@ class SafeBufferTest < ActiveSupport::TestCase
assert_equal ActiveSupport::SafeBuffer, new_buffer.class assert_equal ActiveSupport::SafeBuffer, new_buffer.class
end end
def test_to_yaml test "Should be converted to_yaml" do
str = 'hello!' str = 'hello!'
buf = ActiveSupport::SafeBuffer.new str buf = ActiveSupport::SafeBuffer.new str
yaml = buf.to_yaml yaml = buf.to_yaml
@ -54,22 +55,46 @@ class SafeBufferTest < ActiveSupport::TestCase
assert_equal 'hello!', YAML.load(yaml) assert_equal 'hello!', YAML.load(yaml)
end end
def test_nested test "Should work in nested to_yaml conversion" do
str = 'hello!' str = 'hello!'
data = { 'str' => ActiveSupport::SafeBuffer.new(str) } data = { 'str' => ActiveSupport::SafeBuffer.new(str) }
yaml = YAML.dump data yaml = YAML.dump data
assert_equal({'str' => str}, YAML.load(yaml)) assert_equal({'str' => str}, YAML.load(yaml))
end end
test "Should work with underscore" do
str = "MyTest".html_safe.underscore
assert_equal "my_test", str
end
test "Should not return safe buffer from gsub" do test "Should not return safe buffer from gsub" do
altered_buffer = @buffer.gsub('', 'asdf') altered_buffer = @buffer.gsub('', 'asdf')
assert_equal 'asdf', altered_buffer assert_equal 'asdf', altered_buffer
assert !altered_buffer.html_safe? assert !altered_buffer.html_safe?
end end
test "Should not allow gsub! on safe buffers" do test "Should not return safe buffer from gsub!" do
assert_raise TypeError do @buffer.gsub!('', 'asdf')
@buffer.gsub!('', 'asdf') assert_equal 'asdf', @buffer
end assert !@buffer.html_safe?
end
test "Should escape dirty buffers on add" do
dirty = @buffer
clean = "hello".html_safe
@buffer.gsub!('', '<>')
assert_equal "hello&lt;&gt;", clean + @buffer
end
test "Should concat as a normal string when dirty" do
dirty = @buffer
clean = "hello".html_safe
@buffer.gsub!('', '<>')
assert_equal "<>hello", @buffer + clean
end
test "Should preserve dirty? status on copy" do
@buffer.gsub!('', '<>')
assert !@buffer.dup.html_safe?
end end
end end