Skip to content

Commit

Permalink
Backport html_safe. Use latest rails_xss plugin for forward-compatibi…
Browse files Browse the repository at this point in the history
…lity with Rails 3.
  • Loading branch information
Santiago Pastorino and José Ignacio Costa authored and jeremy committed Feb 5, 2010
1 parent 0c0da1a commit 9ca6df8
Show file tree
Hide file tree
Showing 37 changed files with 251 additions and 217 deletions.
2 changes: 1 addition & 1 deletion actionmailer/test/fixtures/helpers/example_helper.rb
@@ -1,5 +1,5 @@
module ExampleHelper
def example_format(text)
"<em><strong><small>#{h(text)}</small></strong></em>".html_safe!
"<em><strong><small>#{h(text)}</small></strong></em>".html_safe
end
end
2 changes: 2 additions & 0 deletions actionpack/CHANGELOG
Expand Up @@ -6,6 +6,8 @@

* Fixed that fragment caching should return a cache hit as html_safe (or it would all just get escaped) [DHH]

* Introduce String#html_safe for rails_xss plugin and forward-compatibility with Rails 3. [Michael Koziarski, Santiago Pastorino, José Ignacio Costa]

* Added :alert, :notice, and :flash as options to ActionController::Base#redirect_to that'll automatically set the proper flash before the redirection [DHH]. Examples:

flash[:notice] = 'Post was created'
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/caching/fragments.rb
Expand Up @@ -37,7 +37,7 @@ def fragment_cache_key(key)
def fragment_for(buffer, name = {}, options = nil, &block) #:nodoc:
if perform_caching
if cache = read_fragment(name, options)
buffer.concat(cache.html_safe!)
buffer.safe_concat(cache.html_safe)
else
pos = buffer.length
block.call
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/rack_lint_patch.rb
@@ -1,4 +1,4 @@
# Rack 1.0 does not allow string subclass body. This does not play well with our ActionView::SafeBuffer.
# Rack 1.0 does not allow string subclass body. This does not play well with our ActiveSupport::SafeBuffer.
# The next release of Rack will be allowing string subclass body - http://github.com/rack/rack/commit/de668df02802a0335376a81ba709270e43ba9d55
# TODO : Remove this monkey patch after the next release of Rack

Expand Down
3 changes: 1 addition & 2 deletions actionpack/lib/action_view.rb
Expand Up @@ -49,10 +49,9 @@ def self.load_all!
autoload :TemplateHandler, 'action_view/template_handler'
autoload :TemplateHandlers, 'action_view/template_handlers'
autoload :Helpers, 'action_view/helpers'
autoload :SafeBuffer, 'action_view/safe_buffer'
end

require 'action_view/erb/util'
require 'active_support/core_ext/string/output_safety'


I18n.load_path << "#{File.dirname(__FILE__)}/action_view/locale/en.yml"
44 changes: 0 additions & 44 deletions actionpack/lib/action_view/erb/util.rb

This file was deleted.

12 changes: 6 additions & 6 deletions actionpack/lib/action_view/helpers/active_record_helper.rb
Expand Up @@ -3,7 +3,7 @@

module ActionView
class Base
@@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>".html_safe! }
@@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>".html_safe }
cattr_accessor :field_error_proc
end

Expand Down Expand Up @@ -82,11 +82,11 @@ def form(record_name, options = {})
submit_value = options[:submit_value] || options[:action].gsub(/[^\w]/, '').capitalize

contents = form_tag({:action => action}, :method =>(options[:method] || 'post'), :enctype => options[:multipart] ? 'multipart/form-data': nil)
contents << hidden_field(record_name, :id) unless record.new_record?
contents << all_input_tags(record, record_name, options)
contents.safe_concat hidden_field(record_name, :id) unless record.new_record?
contents.safe_concat all_input_tags(record, record_name, options)
yield contents if block_given?
contents << submit_tag(submit_value)
contents << '</form>'
contents.safe_concat submit_tag(submit_value)
contents.safe_concat '</form>'
end

# Returns a string containing the error message attached to the +method+ on the +object+ if one exists.
Expand Down Expand Up @@ -290,7 +290,7 @@ def to_time_select_tag(options = {}, html_options = {})
end

def error_wrapping(html_tag, has_error)
has_error ? Base.field_error_proc.call(html_tag, self).html_safe! : html_tag
has_error ? Base.field_error_proc.call(html_tag, self) : html_tag
end

def error_message
Expand Down
4 changes: 2 additions & 2 deletions actionpack/lib/action_view/helpers/asset_tag_helper.rb
Expand Up @@ -285,7 +285,7 @@ def javascript_include_tag(*sources)
end
javascript_src_tag(joined_javascript_name, options)
else
expand_javascript_sources(sources, recursive).collect { |source| javascript_src_tag(source, options) }.join("\n").html_safe!
expand_javascript_sources(sources, recursive).collect { |source| javascript_src_tag(source, options) }.join("\n").html_safe
end
end

Expand Down Expand Up @@ -434,7 +434,7 @@ def stylesheet_link_tag(*sources)
end
stylesheet_tag(joined_stylesheet_name, options)
else
expand_stylesheet_sources(sources, recursive).collect { |source| stylesheet_tag(source, options) }.join("\n").html_safe!
expand_stylesheet_sources(sources, recursive).collect { |source| stylesheet_tag(source, options) }.join("\n").html_safe
end
end

Expand Down
4 changes: 2 additions & 2 deletions actionpack/lib/action_view/helpers/capture_helper.rb
Expand Up @@ -118,13 +118,13 @@ def capture(*args, &block)
def content_for(name, content = nil, &block)
ivar = "@content_for_#{name}"
content = capture(&block) if block_given?
instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}".html_safe!)
instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}".html_safe)
nil
end

# Use an alternate output buffer for the duration of the block.
# Defaults to a new empty string.
def with_output_buffer(buf = "") #:nodoc:
def with_output_buffer(buf = ActiveSupport::SafeBuffer.new) #:nodoc:
self.output_buffer, old_buffer = buf, output_buffer
yield
output_buffer
Expand Down
14 changes: 7 additions & 7 deletions actionpack/lib/action_view/helpers/date_helper.rb
Expand Up @@ -616,7 +616,7 @@ def select_datetime

build_selects_from_types(order)
else
"#{select_date}#{@options[:datetime_separator]}#{select_time}".html_safe!
"#{select_date}#{@options[:datetime_separator]}#{select_time}".html_safe
end
end

Expand Down Expand Up @@ -835,7 +835,7 @@ def build_select(type, select_options_as_html)
select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt]
select_html << select_options_as_html.to_s

(content_tag(:select, select_html, select_options) + "\n").html_safe!
(content_tag(:select, select_html, select_options) + "\n").html_safe
end

# Builds a prompt option tag with supplied options or from default options
Expand Down Expand Up @@ -865,7 +865,7 @@ def build_hidden(type, value)
:id => input_id_from_type(type),
:name => input_name_from_type(type),
:value => value
}) + "\n").html_safe!
}) + "\n").html_safe
end

# Returns the name attribute for the input tag
Expand Down Expand Up @@ -896,7 +896,7 @@ def build_selects_from_types(order)
separator = separator(type) unless type == order.first # don't add on last field
select.insert(0, separator.to_s + send("select_#{type}").to_s)
end
select.html_safe!
select.html_safe
end

# Returns the separator for a given datetime component
Expand All @@ -916,15 +916,15 @@ def separator(type)

class InstanceTag #:nodoc:
def to_date_select_tag(options = {}, html_options = {})
datetime_selector(options, html_options).select_date.html_safe!
datetime_selector(options, html_options).select_date.html_safe
end

def to_time_select_tag(options = {}, html_options = {})
datetime_selector(options, html_options).select_time.html_safe!
datetime_selector(options, html_options).select_time.html_safe
end

def to_datetime_select_tag(options = {}, html_options = {})
datetime_selector(options, html_options).select_datetime.html_safe!
datetime_selector(options, html_options).select_datetime.html_safe
end

private
Expand Down
4 changes: 2 additions & 2 deletions actionpack/lib/action_view/helpers/debug_helper.rb
Expand Up @@ -27,10 +27,10 @@ module DebugHelper
def debug(object)
begin
Marshal::dump(object)
"<pre class='debug_dump'>#{h(object.to_yaml).gsub(" ", "&nbsp; ")}</pre>"
"<pre class='debug_dump'>#{h(object.to_yaml).gsub(" ", "&nbsp; ")}</pre>".html_safe
rescue Exception => e # errors from Marshal or YAML
# Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback
"<code class='debug_dump'>#{h(object.inspect)}</code>"
"<code class='debug_dump'>#{h(object.inspect)}</code>".html_safe
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions actionpack/lib/action_view/helpers/form_helper.rb
Expand Up @@ -280,7 +280,7 @@ def form_for(record_or_name_or_array, *args, &proc)

concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}))
fields_for(object_name, *(args << options), &proc)
concat('</form>'.html_safe!)
concat('</form>')
end

def apply_form_for_options!(object_or_array, options) #:nodoc:
Expand Down Expand Up @@ -834,7 +834,7 @@ def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0")
add_default_name_and_id(options)
hidden = tag("input", "name" => options["name"], "type" => "hidden", "value" => options['disabled'] && checked ? checked_value : unchecked_value)
checkbox = tag("input", options)
(hidden + checkbox).html_safe!
(hidden + checkbox).html_safe
end

def to_boolean_select_tag(options = {})
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_view/helpers/form_options_helper.rb
Expand Up @@ -296,7 +296,7 @@ def options_for_select(container, selected = nil)
options << %(<option value="#{html_escape(value.to_s)}"#{selected_attribute}#{disabled_attribute}>#{html_escape(text.to_s)}</option>)
end

options_for_select.join("\n").html_safe!
options_for_select.join("\n").html_safe
end

# Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning the
Expand Down
6 changes: 3 additions & 3 deletions actionpack/lib/action_view/helpers/form_tag_helper.rb
Expand Up @@ -432,7 +432,7 @@ def field_set_tag(legend = nil, options = nil, &block)
concat(tag(:fieldset, options, true))
concat(content_tag(:legend, legend)) unless legend.blank?
concat(content)
concat("</fieldset>".html_safe!)
concat("</fieldset>")
end

private
Expand All @@ -459,14 +459,14 @@ def extra_tags_for_form(html_options)

def form_tag_html(html_options)
extra_tags = extra_tags_for_form(html_options)
(tag(:form, html_options, true) + extra_tags).html_safe!
(tag(:form, html_options, true) + extra_tags).html_safe
end

def form_tag_in_block(html_options, &block)
content = capture(&block)
concat(form_tag_html(html_options))
concat(content)
concat("</form>".html_safe!)
concat("</form>")
end

def token_tag
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_view/helpers/number_helper.rb
Expand Up @@ -89,7 +89,7 @@ def number_to_currency(number, options = {})
:precision => precision,
:delimiter => delimiter,
:separator => separator)
).gsub(/%u/, unit)
).gsub(/%u/, unit).html_safe
rescue
number
end
Expand Down
4 changes: 2 additions & 2 deletions actionpack/lib/action_view/helpers/prototype_helper.rb
Expand Up @@ -393,7 +393,7 @@ def remote_form_for(record_or_name_or_array, *args, &proc)

concat(form_remote_tag(options))
fields_for(object_name, *(args << options), &proc)
concat('</form>'.html_safe!)
concat('</form>')
end
alias_method :form_remote_for, :remote_form_for

Expand Down Expand Up @@ -1026,7 +1026,7 @@ def method_missing(method, *arguments)
# page.hide 'spinner'
# end
def update_page(&block)
JavaScriptGenerator.new(@template, &block).to_s.html_safe!
JavaScriptGenerator.new(@template, &block).to_s.html_safe
end

# Works like update_page but wraps the generated JavaScript in a <script>
Expand Down
4 changes: 2 additions & 2 deletions actionpack/lib/action_view/helpers/raw_output_helper.rb
Expand Up @@ -2,8 +2,8 @@ module ActionView #:nodoc:
module Helpers #:nodoc:
module RawOutputHelper
def raw(stringish)
stringish.to_s.html_safe!
stringish.to_s.html_safe
end
end
end
end
end
12 changes: 2 additions & 10 deletions actionpack/lib/action_view/helpers/sanitize_helper.rb
Expand Up @@ -49,11 +49,7 @@ module SanitizeHelper
# confuse browsers.
#
def sanitize(html, options = {})
returning self.class.white_list_sanitizer.sanitize(html, options) do |sanitized|
if sanitized
sanitized.html_safe!
end
end
self.class.white_list_sanitizer.sanitize(html, options).try(:html_safe)
end

# Sanitizes a block of CSS code. Used by +sanitize+ when it comes across a style attribute.
Expand All @@ -76,11 +72,7 @@ def sanitize_css(style)
# strip_tags("<div id='top-bar'>Welcome to my website!</div>")
# # => Welcome to my website!
def strip_tags(html)
returning self.class.full_sanitizer.sanitize(html) do |sanitized|
if sanitized
sanitized.html_safe!
end
end
self.class.full_sanitizer.sanitize(html).try(:html_safe)
end

# Strips all link tags from +text+ leaving just the link text.
Expand Down
10 changes: 5 additions & 5 deletions actionpack/lib/action_view/helpers/tag_helper.rb
@@ -1,4 +1,4 @@
require 'action_view/erb/util'
require 'active_support/core_ext/string/output_safety'
require 'set'

module ActionView
Expand Down Expand Up @@ -38,7 +38,7 @@ module TagHelper
# tag("img", { :src => "open &amp; shut.png" }, false, false)
# # => <img src="open &amp; shut.png" />
def tag(name, options = nil, open = false, escape = true)
"<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe!
"<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe
end

# Returns an HTML block tag of type +name+ surrounding the +content+. Add
Expand Down Expand Up @@ -91,7 +91,7 @@ def content_tag(name, content_or_options_with_block = nil, options = nil, escape
# cdata_section(File.read("hello_world.txt"))
# # => <![CDATA[<hello from a text file]]>
def cdata_section(content)
"<![CDATA[#{content}]]>".html_safe!
"<![CDATA[#{content}]]>".html_safe
end

# Returns an escaped version of +html+ without affecting existing escaped entities.
Expand Down Expand Up @@ -125,7 +125,7 @@ def block_called_from_erb?(block)

def content_tag_string(name, content, options, escape = true)
tag_options = tag_options(options, escape) if options
"<#{name}#{tag_options}>#{content}</#{name}>".html_safe!
"<#{name}#{tag_options}>#{content}</#{name}>".html_safe
end

def tag_options(options, escape = true)
Expand All @@ -142,7 +142,7 @@ def tag_options(options, escape = true)
else
attrs = options.map { |key, value| %(#{key}="#{value}") }
end
" #{attrs.sort * ' '}".html_safe! unless attrs.empty?
" #{attrs.sort * ' '}".html_safe unless attrs.empty?
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_view/helpers/text_helper.rb
Expand Up @@ -29,7 +29,7 @@ def concat(string, unused_binding = nil)
ActiveSupport::Deprecation.warn("The binding argument of #concat is no longer needed. Please remove it from your views and helpers.", caller)
end

output_buffer << string
output_buffer.safe_concat(string)
end

# Truncates a given +text+ after a given <tt>:length</tt> if +text+ is longer than <tt>:length</tt>
Expand Down

1 comment on commit 9ca6df8

@aslakhellesoy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ouch! This breaks ERB. Please make a subclass of ERB instead and override functionality there. Then use that internally. https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/4034-monkey-patched-erb-breaks-other-libraries-relying-on-standard-behaviour-from-erb

Please sign in to comment.