aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/core_ext/string/output_safety.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib/active_support/core_ext/string/output_safety.rb')
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb65
1 files changed, 52 insertions, 13 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 c27cbc37c5..3bf4edbdef 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -51,7 +51,8 @@ class ERB
# <%=j @person.to_json %>
#
def json_escape(s)
- s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
+ result = s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
+ s.html_safe? ? result.html_safe : result
end
alias j json_escape
@@ -66,7 +67,7 @@ class Object
end
end
-class Fixnum
+class Numeric
def html_safe?
true
end
@@ -74,10 +75,34 @@ end
module ActiveSupport #:nodoc:
class SafeBuffer < String
- alias safe_concat concat
+ UNSAFE_STRING_METHODS = ["capitalize", "chomp", "chop", "delete", "downcase", "gsub", "lstrip", "next", "reverse", "rstrip", "slice", "squeeze", "strip", "sub", "succ", "swapcase", "tr", "tr_s", "upcase"].freeze
+
+ alias_method :original_concat, :concat
+ private :original_concat
+
+ class SafeConcatError < StandardError
+ def initialize
+ super "Could not concatenate to the buffer because it is not html safe."
+ end
+ end
+
+ def safe_concat(value)
+ raise SafeConcatError if dirty?
+ original_concat(value)
+ end
+
+ def initialize(*)
+ @dirty = false
+ super
+ end
+
+ def initialize_copy(other)
+ super
+ @dirty = other.dirty?
+ end
def concat(value)
- if value.html_safe?
+ if dirty? || value.html_safe?
super(value)
else
super(ERB::Util.h(value))
@@ -90,15 +115,15 @@ module ActiveSupport #:nodoc:
end
def html_safe?
- true
+ !dirty?
end
- def html_safe
+ def to_s
self
end
- def to_s
- self
+ def to_param
+ to_str
end
def encode_with(coder)
@@ -107,17 +132,31 @@ module ActiveSupport #:nodoc:
def to_yaml(*args)
return super() if defined?(YAML::ENGINE) && !YAML::ENGINE.syck?
-
to_str.to_yaml(*args)
end
+
+ UNSAFE_STRING_METHODS.each do |unsafe_method|
+ class_eval <<-EOT, __FILE__, __LINE__
+ def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
+ to_str.#{unsafe_method}(*args, &block) # to_str.gsub(*args, &block)
+ end # end
+
+ def #{unsafe_method}!(*args) # def gsub!(*args)
+ @dirty = true # @dirty = true
+ super # super
+ end # end
+ EOT
+ end
+
+ protected
+
+ def dirty?
+ @dirty
+ end
end
end
class String
- def html_safe!
- raise "You can't call html_safe! on a String"
- end
-
def html_safe
ActiveSupport::SafeBuffer.new(self)
end