diff options
Diffstat (limited to 'activesupport/lib/active_support/core_ext/string')
3 files changed, 42 insertions, 31 deletions
diff --git a/activesupport/lib/active_support/core_ext/string/access.rb b/activesupport/lib/active_support/core_ext/string/access.rb index d94e1bfca2..ebd0dd3fc7 100644 --- a/activesupport/lib/active_support/core_ext/string/access.rb +++ b/activesupport/lib/active_support/core_ext/string/access.rb @@ -59,12 +59,12 @@ class String # str.from(0).to(-1) # => "hello" # str.from(1).to(-2) # => "ell" def to(position) - self[0, position + 1] + self[0..position] end # Returns the first character. If a limit is supplied, returns a substring # from the beginning of the string until it reaches the limit value. If the - # given limit is greater than or equal to the string length, returns self. + # given limit is greater than or equal to the string length, returns a copy of self. # # str = "hello" # str.first # => "h" @@ -76,7 +76,7 @@ class String if limit == 0 '' elsif limit >= size - self + self.dup else to(limit - 1) end @@ -84,7 +84,7 @@ class String # Returns the last character of the string. If a limit is supplied, returns a substring # from the end of the string until it reaches the limit value (counting backwards). If - # the given limit is greater than or equal to the string length, returns self. + # the given limit is greater than or equal to the string length, returns a copy of self. # # str = "hello" # str.last # => "o" @@ -96,7 +96,7 @@ class String if limit == 0 '' elsif limit >= size - self + self.dup else from(-limit) end diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb index cf9b1a4ec0..a943752f17 100644 --- a/activesupport/lib/active_support/core_ext/string/inflections.rb +++ b/activesupport/lib/active_support/core_ext/string/inflections.rb @@ -31,7 +31,7 @@ class String def pluralize(count = nil, locale = :en) locale = count if count.is_a?(Symbol) if count == 1 - self + self.dup else ActiveSupport::Inflector.pluralize(self, locale) end @@ -130,6 +130,8 @@ class String # # 'ActiveRecord::CoreExtensions::String::Inflections'.demodulize # => "Inflections" # 'Inflections'.demodulize # => "Inflections" + # '::Inflections'.demodulize # => "Inflections" + # ''.demodulize # => '' # # See also +deconstantize+. def demodulize 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 1b2098fc84..2c8995be9a 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -1,5 +1,6 @@ require 'erb' require 'active_support/core_ext/kernel/singleton_class' +require 'active_support/deprecation' class ERB module Util @@ -70,9 +71,20 @@ class ERB # them inside a script tag to avoid XSS vulnerability: # # <script> - # var currentUser = <%= json_escape current_user.to_json %>; + # var currentUser = <%= raw json_escape(current_user.to_json) %>; # </script> # + # It is necessary to +raw+ the result of +json_escape+, so that quotation marks + # don't get converted to <tt>"</tt> entities. +json_escape+ doesn't + # automatically flag the result as HTML safe, since the raw value is unsafe to + # use inside HTML attributes. + # + # If you need to output JSON elsewhere in your HTML, you can just do something + # like this, as any unsafe characters (including quotation marks) will be + # automatically escaped for you: + # + # <div data-user-info="<%= current_user.to_json %>">...</div> + # # WARNING: this helper only works with valid JSON. Using this on non-JSON values # will open up serious XSS vulnerabilities. For example, if you replace the # +current_user.to_json+ in the example above with user input instead, the browser @@ -88,17 +100,6 @@ class ERB # is recommended that you always apply this helper (other libraries, such as the # JSON gem, do not provide this kind of protection by default; also some gems # might override +to_json+ to bypass Active Support's encoder). - # - # The output of this helper method is marked as HTML safe so that you can directly - # include it inside a <tt><script></tt> tag as shown above. - # - # However, it is NOT safe to use the output of this inside an HTML attribute, - # because quotation marks are not escaped. Doing so might break your page's layout. - # If you intend to use this inside an HTML attribute, you should use the - # +html_escape+ helper (or its +h+ alias) instead: - # - # <div data-user-info="<%= h current_user.to_json %>">...</div> - # def json_escape(s) result = s.to_s.gsub(JSON_ESCAPE_REGEXP, JSON_ESCAPE) s.html_safe? ? result.html_safe : result @@ -124,7 +125,7 @@ module ActiveSupport #:nodoc: class SafeBuffer < String UNSAFE_STRING_METHODS = %w( capitalize chomp chop delete downcase gsub lstrip next reverse rstrip - slice squeeze strip sub succ swapcase tr tr_s upcase prepend + slice squeeze strip sub succ swapcase tr tr_s upcase ) alias_method :original_concat, :concat @@ -169,29 +170,31 @@ module ActiveSupport #:nodoc: self[0, 0] end - def concat(value) - if !html_safe? || value.html_safe? - super(value) - else - super(ERB::Util.h(value)) + %w[concat prepend].each do |method_name| + define_method method_name do |value| + super(html_escape_interpolated_argument(value)) end end alias << concat + def prepend!(value) + ActiveSupport::Deprecation.deprecation_warning "ActiveSupport::SafeBuffer#prepend!", :prepend + prepend value + end + def +(other) dup.concat(other) end def %(args) - args = Array(args).map do |arg| - if !html_safe? || arg.html_safe? - arg - else - ERB::Util.h(arg) - end + case args + when Hash + escaped_args = Hash[args.map { |k,arg| [k, html_escape_interpolated_argument(arg)] }] + else + escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) } end - self.class.new(super(args)) + self.class.new(super(escaped_args)) end def html_safe? @@ -224,6 +227,12 @@ module ActiveSupport #:nodoc: EOT end end + + private + + def html_escape_interpolated_argument(arg) + (!html_safe? || arg.html_safe?) ? arg : ERB::Util.h(arg) + end end end |