aboutsummaryrefslogtreecommitdiffstats
path: root/actionview/lib
diff options
context:
space:
mode:
authorTimm <kaspth@gmail.com>2013-06-12 15:59:34 +0200
committerTimm <kaspth@gmail.com>2014-06-11 17:53:28 +0200
commitc94e24fbe7bcdf605cafcfabdf97454d1e1e0685 (patch)
treec87092cfabcbb09f8351722b6127dc7d37c87a8f /actionview/lib
parent47baab0c415690aeb71ef3bc4831a462d8ead47b (diff)
downloadrails-c94e24fbe7bcdf605cafcfabdf97454d1e1e0685.tar.gz
rails-c94e24fbe7bcdf605cafcfabdf97454d1e1e0685.tar.bz2
rails-c94e24fbe7bcdf605cafcfabdf97454d1e1e0685.zip
Added Loofah as a dependency in actionview.gemspec.
Implemented ActionView: FullSanitizer, LinkSanitizer and WhiteListSanitizer in sanitizers.rb. Deprecated protocol_separator and bad_tags. Added new tests in sanitizers_test.rb and reimplemented assert_dom_equal with Loofah.
Diffstat (limited to 'actionview/lib')
-rw-r--r--actionview/lib/action_view/helpers/sanitize_helper.rb47
-rw-r--r--actionview/lib/action_view/helpers/sanitize_helper/sanitizers.rb116
2 files changed, 140 insertions, 23 deletions
diff --git a/actionview/lib/action_view/helpers/sanitize_helper.rb b/actionview/lib/action_view/helpers/sanitize_helper.rb
index 049af275b6..66894b5936 100644
--- a/actionview/lib/action_view/helpers/sanitize_helper.rb
+++ b/actionview/lib/action_view/helpers/sanitize_helper.rb
@@ -1,5 +1,5 @@
require 'active_support/core_ext/object/try'
-require 'action_view/vendor/html-scanner'
+require 'action_view/helpers/sanitize_helper/sanitizers'
module ActionView
# = Action View Sanitize Helpers
@@ -65,9 +65,9 @@ module ActionView
self.class.white_list_sanitizer.sanitize_css(style)
end
- # Strips all HTML tags from the +html+, including comments. This uses the
- # html-scanner tokenizer and so its HTML parsing ability is limited by
- # that of html-scanner.
+ # Strips all HTML tags from the +html+, including comments. This uses
+ # Nokogiri for tokenization (via Loofah) and so its HTML parsing ability
+ # is limited by that of Nokogiri.
#
# strip_tags("Strip <i>these</i> tags!")
# # => Strip these tags!
@@ -134,11 +134,7 @@ module ActionView
white_list_sanitizer.allowed_protocols
end
- def sanitized_protocol_separator=(value)
- white_list_sanitizer.protocol_separator = value
- end
-
- # Gets the HTML::FullSanitizer instance used by +strip_tags+. Replace with
+ # Gets the ActionView::FullSanitizer instance used by +strip_tags+. Replace with
# any object that responds to +sanitize+.
#
# class Application < Rails::Application
@@ -146,21 +142,21 @@ module ActionView
# end
#
def full_sanitizer
- @full_sanitizer ||= HTML::FullSanitizer.new
+ @full_sanitizer ||= ActionView::FullSanitizer.new
end
- # Gets the HTML::LinkSanitizer instance used by +strip_links+. Replace with
- # any object that responds to +sanitize+.
+ # Gets the ActionView::LinkSanitizer instance used by +strip_links+.
+ # Replace with any object that responds to +sanitize+.
#
# class Application < Rails::Application
# config.action_view.link_sanitizer = MySpecialSanitizer.new
# end
#
def link_sanitizer
- @link_sanitizer ||= HTML::LinkSanitizer.new
+ @link_sanitizer ||= ActionView::LinkSanitizer.new
end
- # Gets the HTML::WhiteListSanitizer instance used by sanitize and +sanitize_css+.
+ # Gets the ActionView::WhiteListSanitizer instance used by sanitize and +sanitize_css+.
# Replace with any object that responds to +sanitize+.
#
# class Application < Rails::Application
@@ -168,7 +164,12 @@ module ActionView
# end
#
def white_list_sanitizer
- @white_list_sanitizer ||= HTML::WhiteListSanitizer.new
+ @white_list_sanitizer ||= ActionView::WhiteListSanitizer.new
+ end
+
+
+ def sanitized_protocol_separator=(value)
+ ActionView::WhiteListSanitizer.protocol_separator = value
end
# Adds valid HTML attributes that the +sanitize+ helper checks for URIs.
@@ -178,7 +179,7 @@ module ActionView
# end
#
def sanitized_uri_attributes=(attributes)
- HTML::WhiteListSanitizer.uri_attributes.merge(attributes)
+ ActionView::WhiteListSanitizer.update_uri_attributes(attributes)
end
# Adds to the Set of 'bad' tags for the +sanitize+ helper.
@@ -188,7 +189,7 @@ module ActionView
# end
#
def sanitized_bad_tags=(attributes)
- HTML::WhiteListSanitizer.bad_tags.merge(attributes)
+ ActionView::WhiteListSanitizer.bad_tags = attributes
end
# Adds to the Set of allowed tags for the +sanitize+ helper.
@@ -198,7 +199,7 @@ module ActionView
# end
#
def sanitized_allowed_tags=(attributes)
- HTML::WhiteListSanitizer.allowed_tags.merge(attributes)
+ ActionView::WhiteListSanitizer.update_allowed_tags(attributes)
end
# Adds to the Set of allowed HTML attributes for the +sanitize+ helper.
@@ -208,7 +209,7 @@ module ActionView
# end
#
def sanitized_allowed_attributes=(attributes)
- HTML::WhiteListSanitizer.allowed_attributes.merge(attributes)
+ ActionView::WhiteListSanitizer.update_allowed_attributes(attributes)
end
# Adds to the Set of allowed CSS properties for the #sanitize and +sanitize_css+ helpers.
@@ -218,7 +219,7 @@ module ActionView
# end
#
def sanitized_allowed_css_properties=(attributes)
- HTML::WhiteListSanitizer.allowed_css_properties.merge(attributes)
+ ActionView::WhiteListSanitizer.update_allowed_css_properties(attributes)
end
# Adds to the Set of allowed CSS keywords for the +sanitize+ and +sanitize_css+ helpers.
@@ -228,7 +229,7 @@ module ActionView
# end
#
def sanitized_allowed_css_keywords=(attributes)
- HTML::WhiteListSanitizer.allowed_css_keywords.merge(attributes)
+ ActionView::WhiteListSanitizer.update_allowed_css_keywords(attributes)
end
# Adds to the Set of allowed shorthand CSS properties for the +sanitize+ and +sanitize_css+ helpers.
@@ -238,7 +239,7 @@ module ActionView
# end
#
def sanitized_shorthand_css_properties=(attributes)
- HTML::WhiteListSanitizer.shorthand_css_properties.merge(attributes)
+ ActionView::WhiteListSanitizer.update_shorthand_css_properties(attributes)
end
# Adds to the Set of allowed protocols for the +sanitize+ helper.
@@ -248,7 +249,7 @@ module ActionView
# end
#
def sanitized_allowed_protocols=(attributes)
- HTML::WhiteListSanitizer.allowed_protocols.merge(attributes)
+ ActionView::WhiteListSanitizer.update_allowed_protocols(attributes)
end
end
end
diff --git a/actionview/lib/action_view/helpers/sanitize_helper/sanitizers.rb b/actionview/lib/action_view/helpers/sanitize_helper/sanitizers.rb
new file mode 100644
index 0000000000..74be525581
--- /dev/null
+++ b/actionview/lib/action_view/helpers/sanitize_helper/sanitizers.rb
@@ -0,0 +1,116 @@
+require 'active_support/core_ext/class/attribute'
+require 'active_support/deprecation'
+require 'loofah'
+
+module ActionView
+
+ class FullSanitizer
+ def sanitize(html, options = {})
+ Loofah.fragment(html).text
+ end
+ end
+
+ class LinkSanitizer
+ def initialize
+ @link_scrubber = Loofah::Scrubber.new do |node|
+ next unless node.name == 'a'
+ node.before node.children
+ node.remove
+ end
+ end
+
+ def sanitize(html, options = {})
+ Loofah.scrub_fragment(html, @link_scrubber).to_s
+ end
+ end
+
+ class WhiteListSanitizer
+ def sanitize(html, options = {})
+ return nil unless html
+ validate_options(options)
+
+ loofah_fragment = Loofah.fragment(html)
+ loofah_fragment.scrub!(:strip)
+ loofah_fragment.xpath("./form").each { |form| form.remove }
+ loofah_fragment.to_s
+ end
+
+ def sanitize_css(style_string)
+ Loofah::HTML5::Scrub.scrub_css style_string
+ end
+
+ def protocol_separator
+ ActiveSupport::Deprecation.warn('protocol_separator has been deprecated and has no effect.')
+ end
+
+ def protocol_separator=(value)
+ ActiveSupport::Deprecation.warn('protocol_separator= has been deprecated and has no effect.')
+ end
+
+ def bad_tags
+ ActiveSupport::Deprecation.warn('bad_tags has been deprecated and has no effect.')
+ end
+
+ class << self
+ def protocol_separator
+ ActiveSupport::Deprecation.warn('protocol_separator has been deprecated and has no effect.')
+ end
+
+ def protocol_separator=(value)
+ ActiveSupport::Deprecation.warn('protocol_separator= has been deprecated and has no effect.')
+ end
+
+ def bad_tags
+ ActiveSupport::Deprecation.warn('The bad_tags class attribute has been deprecated and has no effect. You can still affect the tags being sanitized using bad_tags= which changes the allowed_tags.')
+ end
+
+ def bad_tags=(tags)
+ allowed_tags.replace(allowed_tags - tags)
+ end
+ end
+
+ [:uri_attributes, :allowed_attributes,
+ :allowed_tags, :allowed_protocols, :allowed_css_properties,
+ :allowed_css_keywords, :shorthand_css_properties].each do |attr|
+ class_attribute attr, :instance_writer => false
+
+ define_method "#{self}.update_#{attr}" do |arg|
+ attr.merge arg
+ end
+ end
+
+ # Constants are from Loofahs source at lib/loofah/html5/whitelist.rb
+ self.uri_attributes = Loofah::HTML5::WhiteList::ATTR_VAL_IS_URI
+
+ self.allowed_tags = Loofah::HTML5::WhiteList::ALLOWED_ELEMENTS
+
+ self.bad_tags = Set.new %w(script)
+
+ self.allowed_attributes = Loofah::HTML5::WhiteList::ALLOWED_ATTRIBUTES
+
+ self.allowed_css_properties = Loofah::HTML5::WhiteList::ALLOWED_CSS_PROPERTIES
+
+ self.allowed_css_keywords = Loofah::HTML5::WhiteList::ALLOWED_CSS_KEYWORDS
+
+ self.shorthand_css_properties = Loofah::HTML5::WhiteList::SHORTHAND_CSS_PROPERTIES
+
+ self.allowed_protocols = Loofah::HTML5::WhiteList::ALLOWED_PROTOCOLS
+
+ protected
+ def validate_options(options)
+ if options[:tags] && !options[:tags].is_a?(Enumerable)
+ raise ArgumentError, "You should pass :tags as an Enumerable"
+ end
+
+ if options[:attributes] && !options[:attributes].is_a?(Enumerable)
+ raise ArgumentError, "You should pass :attributes as an Enumerable"
+ end
+ end
+
+ def contains_bad_protocols?(attr_name, value)
+ protocol_separator = ':'
+ self.uri_attributes.include?(attr_name) &&
+ (value =~ /(^[^\/:]*):|(&#0*58)|(&#x70)|(&#x0*3a)|(%|&#37;)3A/i && !self.allowed_protocols.include?(value.split(protocol_separator).first.downcase.strip))
+ end
+ end
+end