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:
parent
1844572fd1
commit
594603b45f
2 changed files with 55 additions and 18 deletions
|
@ -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
|
||||||
|
|
|
@ -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<>", 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
|
||||||
|
|
Loading…
Reference in a new issue