Browse files

Mark formtastic outputs as html_safe

Formtastic::Util.html_safe() checks the available environment and marks a string as html_safe appropriately
  • Loading branch information...
1 parent 2fa8cb8 commit d52d82964841da0c4abbfa34900624c9159e54bb @yabawock yabawock committed with yabawock Apr 15, 2010
Showing with 46 additions and 20 deletions.
  1. +21 −20 lib/formtastic.rb
  2. +25 −0 lib/formtastic/util.rb
View
41 lib/formtastic.rb
@@ -1,5 +1,6 @@
# coding: utf-8
require File.join(File.dirname(__FILE__), *%w[formtastic i18n])
+require File.join(File.dirname(__FILE__), *%w[formtastic util])
require File.join(File.dirname(__FILE__), *%w[formtastic railtie]) if defined?(::Rails::Railtie)
module Formtastic #:nodoc:
@@ -106,7 +107,7 @@ def input(method, options = {})
send(:"inline_#{type}_for", method, options)
end.compact.join("\n")
- return template.content_tag(:li, list_item_content, wrapper_html)
+ return template.content_tag(:li, Formtastic::Util.html_safe(list_item_content), wrapper_html)
end
# Creates an input fieldset and ol tag wrapping for use around a set of inputs. It can be
@@ -343,7 +344,7 @@ def commit_button(*args)
element_class = ['commit', options.delete(:class)].compact.join(' ') # TODO: Add class reflecting on form action.
accesskey = (options.delete(:accesskey) || @@default_commit_button_accesskey) unless button_html.has_key?(:accesskey)
button_html = button_html.merge(:accesskey => accesskey) if accesskey
- template.content_tag(:li, self.submit(text, button_html), :class => element_class)
+ template.content_tag(:li, Formtastic::Util.html_safe(self.submit(text, button_html)), :class => element_class)
end
# A thin wrapper around #fields_for to set :builder => Formtastic::SemanticFormBuilder
@@ -407,7 +408,7 @@ def label(method, options_or_text=nil, options=nil)
text = (options.delete(:label_prefix_for_nested_input) || "") + text
input_name = options.delete(:input_name) || method
- super(input_name, text, options)
+ super(input_name, Formtastic::Util.html_safe(text), options)
end
# Generates error messages for the given method. Errors can be shown as list,
@@ -453,7 +454,7 @@ def semantic_errors(*args)
return nil if full_errors.blank?
html_options[:class] ||= "errors"
template.content_tag(:ul, html_options) do
- full_errors.map { |error| template.content_tag(:li, error) }.join
+ Formtastic::Util.html_safe(full_errors.map { |error| template.content_tag(:li, Formtastic::Util.html_safe(error)) }.join)
end
end
@@ -860,12 +861,12 @@ def radio_input(method, options)
html_options[:checked] = selected_value == value if selected_option_is_present
li_content = template.content_tag(:label,
- "#{self.radio_button(input_name, value, html_options)} #{label}",
+ Formtastic::Util.html_safe("#{self.radio_button(input_name, value, html_options)} #{label}"),
:for => input_id
)
li_options = value_as_class ? { :class => [method.to_s.singularize, value.to_s.downcase].join('_') } : {}
- template.content_tag(:li, li_content, li_options)
+ template.content_tag(:li, Formtastic::Util.html_safe(li_content), li_options)
end
field_set_and_list_wrapping_for_method(method, options, list_item_content)
@@ -1014,10 +1015,10 @@ def date_or_datetime_input(method, options)
opts = strip_formtastic_options(options).merge(:prefix => @object_name, :field_name => field_name, :default => datetime)
item_label_text = labels[input] || ::I18n.t(input.to_s, :default => input.to_s.humanize, :scope => [:datetime, :prompts])
- list_items_capture << template.content_tag(:li, [
- !item_label_text.blank? ? template.content_tag(:label, item_label_text, :for => input_id) : "",
+ list_items_capture << template.content_tag(:li, Formtastic::Util.html_safe([
+ !item_label_text.blank? ? template.content_tag(:label, Formtastic::Util.html_safe(item_label_text), :for => input_id) : "",
template.send(:"select_#{input}", datetime, opts, html_options.merge(:id => input_id))
- ].join("")
+ ].join(""))
)
end
end
@@ -1122,12 +1123,12 @@ def check_boxes_input(method, options)
html_options[:id] = input_id
li_content = template.content_tag(:label,
- "#{self.check_box(input_name, html_options, value, unchecked_value)} #{label}",
+ Formtastic::Util.html_safe("#{self.check_box(input_name, html_options, value, unchecked_value)} #{label}"),
:for => input_id
)
li_options = value_as_class ? { :class => [method.to_s.singularize, value.to_s.downcase].join('_') } : {}
- template.content_tag(:li, li_content, li_options)
+ template.content_tag(:li, Formtastic::Util.html_safe(li_content), li_options)
end
field_set_and_list_wrapping_for_method(method, options, list_item_content)
@@ -1192,29 +1193,29 @@ def inline_input_for(method, options)
def inline_hints_for(method, options) #:nodoc:
options[:hint] = localized_string(method, options[:hint], :hint)
return if options[:hint].blank?
- template.content_tag(:p, options[:hint], :class => 'inline-hints')
+ template.content_tag(:p, Formtastic::Util.html_safe(options[:hint]), :class => 'inline-hints')
end
# Creates an error sentence by calling to_sentence on the errors array.
#
def error_sentence(errors) #:nodoc:
- template.content_tag(:p, errors.to_sentence.untaint, :class => 'inline-errors')
+ template.content_tag(:p, Formtastic::Util.html_safe(errors.to_sentence.untaint), :class => 'inline-errors')
end
# Creates an error li list.
#
def error_list(errors) #:nodoc:
list_elements = []
errors.each do |error|
- list_elements << template.content_tag(:li, error.untaint)
+ list_elements << template.content_tag(:li, Formtastic::Util.html_safe(error.untaint))
end
- template.content_tag(:ul, list_elements.join("\n"), :class => 'errors')
+ template.content_tag(:ul, Formtastic::Util.html_safe(list_elements.join("\n")), :class => 'errors')
end
# Creates an error sentence containing only the first error
#
def error_first(errors) #:nodoc:
- template.content_tag(:p, errors.first.untaint, :class => 'inline-errors')
+ template.content_tag(:p, Formtastic::Util.html_safe(errors.first.untaint), :class => 'inline-errors')
end
# Generates the required or optional string. If the value set is a proc,
@@ -1261,7 +1262,7 @@ def field_set_and_list_wrapping(*args, &block) #:nodoc:
legend = html_options.delete(:name).to_s
legend %= parent_child_index(html_options[:parent]) if html_options[:parent]
- legend = template.content_tag(:legend, template.content_tag(:span, legend)) unless legend.blank?
+ legend = template.content_tag(:legend, template.content_tag(:span, Formtastic::Util.html_safe(legend))) unless legend.blank?
if block_given?
contents = if template.respond_to?(:is_haml?) && template.is_haml?
@@ -1274,11 +1275,11 @@ def field_set_and_list_wrapping(*args, &block) #:nodoc:
# Ruby 1.9: String#to_s behavior changed, need to make an explicit join.
contents = contents.join if contents.respond_to?(:join)
fieldset = template.content_tag(:fieldset,
- legend << template.content_tag(:ol, contents),
+ Formtastic::Util.html_safe(legend) << template.content_tag(:ol, Formtastic::Util.html_safe(contents)),
html_options.except(:builder, :parent)
)
- template.concat(fieldset) if block_given?
+ template.concat(fieldset) if block_given? && (!defined?(Rails::VERSION) || Rails::VERSION::MAJOR == 2)
fieldset
end
@@ -1306,7 +1307,7 @@ def field_set_and_list_wrapping_for_method(method, options, contents) #:nodoc:
template.content_tag(:legend,
self.label(method, options_for_label(options).merge(:for => options.delete(:label_for))), :class => 'label'
) <<
- template.content_tag(:ol, contents)
+ template.content_tag(:ol, Formtastic::Util.html_safe(contents))
)
end
View
25 lib/formtastic/util.rb
@@ -0,0 +1,25 @@
+# Adapted from the rails3 compatibility shim in Haml 2.2
+module Formtastic
+ module Util
+ extend self
+ ## Rails XSS Safety
+
+ # Returns the given text, marked as being HTML-safe.
+ # With older versions of the Rails XSS-safety mechanism,
+ # this destructively modifies the HTML-safety of `text`.
+ #
+ # @param text [String]
+ # @return [String] `text`, marked as HTML-safe
+ def html_safe(text)
+ return text if text.nil?
+ return text.html_safe if defined?(ActiveSupport::SafeBuffer)
+ return text.html_safe!
+ end
+
+ def rails_safe_buffer_class
+ return ActionView::SafeBuffer if defined?(ActionView::SafeBuffer)
+ ActiveSupport::SafeBuffer
+ end
+
+ end
+end

0 comments on commit d52d829

Please sign in to comment.