sanitize_helper.rb 9.3 KB
Newer Older
J
Joshua Peek 已提交
1
require 'action_controller/vendor/html-scanner'
2 3 4 5 6 7 8
require 'action_view/helpers/tag_helper'

module ActionView
  module Helpers #:nodoc:
    # The SanitizeHelper module provides a set of methods for scrubbing text of undesired HTML elements.
    # These helper methods extend ActionView making them callable within your template files.
    module SanitizeHelper
9
      # This +sanitize+ helper will html encode all tags and strip all attributes that aren't specifically allowed.
10 11 12 13 14
      # It also strips href/src tags with invalid protocols, like javascript: especially.  It does its best to counter any
      # tricks that hackers may use, like throwing in unicode/ascii/hex values to get past the javascript: filters.  Check out
      # the extensive test suite.
      #
      #   <%= sanitize @article.body %>
15
      #
16
      # You can add or remove tags/attributes if you want to customize it a bit.  See ActionView::Base for full docs on the
17
      # available options.  You can add tags/attributes for single uses of +sanitize+ by passing either the <tt>:attributes</tt> or <tt>:tags</tt> options:
18 19 20 21 22 23 24
      #
      # Normal Use
      #
      #   <%= sanitize @article.body %>
      #
      # Custom Use (only the mentioned tags and attributes are allowed, nothing else)
      #
P
Pratik Naik 已提交
25
      #   <%= sanitize @article.body, :tags => %w(table tr td), :attributes => %w(id class style) %>
26
      #
27
      # Add table tags to the default allowed tags
28
      #
29 30 31
      #   Rails::Initializer.run do |config|
      #     config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td'
      #   end
32
      #
33
      # Remove tags to the default allowed tags
34
      #
35 36 37 38 39
      #   Rails::Initializer.run do |config|
      #     config.after_initialize do
      #       ActionView::Base.sanitized_allowed_tags.delete 'div'
      #     end
      #   end
40
      #
41
      # Change allowed default attributes
42
      #
43 44 45
      #   Rails::Initializer.run do |config|
      #     config.action_view.sanitized_allowed_attributes = 'id', 'class', 'style'
      #   end
46
      #
47 48 49 50 51
      # Please note that sanitizing user-provided text does not guarantee that the
      # resulting markup is valid (conforming to a document type) or even well-formed.
      # The output may still contain e.g. unescaped '<', '>', '&' characters and
      # confuse browsers.
      #
52
      def sanitize(html, options = {})
53 54 55 56 57
        returning self.class.white_list_sanitizer.sanitize(html, options) do |sanitized|
          if sanitized
            sanitized.html_safe!
          end
        end
58 59
      end

P
Pratik Naik 已提交
60
      # Sanitizes a block of CSS code. Used by +sanitize+ when it comes across a style attribute.
61
      def sanitize_css(style)
62
        self.class.white_list_sanitizer.sanitize_css(style)
63 64
      end

65 66
      # Strips all HTML tags from the +html+, including comments.  This uses the
      # html-scanner tokenizer and so its HTML parsing ability is limited by
67 68 69 70 71 72 73 74 75
      # that of html-scanner.
      #
      # ==== Examples
      #
      #   strip_tags("Strip <i>these</i> tags!")
      #   # => Strip these tags!
      #
      #   strip_tags("<b>Bold</b> no more!  <a href='more.html'>See more here</a>...")
      #   # => Bold no more!  See more here...
76
      #
77 78
      #   strip_tags("<div id='top-bar'>Welcome to my website!</div>")
      #   # => Welcome to my website!
79
      def strip_tags(html)
80 81 82 83 84
        returning self.class.full_sanitizer.sanitize(html) do |sanitized|
          if sanitized
            sanitized.html_safe!
          end
        end
85 86 87 88 89 90 91 92 93 94 95 96 97 98
      end

      # Strips all link tags from +text+ leaving just the link text.
      #
      # ==== Examples
      #   strip_links('<a href="http://www.rubyonrails.org">Ruby on Rails</a>')
      #   # => Ruby on Rails
      #
      #   strip_links('Please e-mail me at <a href="mailto:me@email.com">me@email.com</a>.')
      #   # => Please e-mail me at me@email.com.
      #
      #   strip_links('Blog: <a href="http://www.myblog.com/" class="nav" target=\"_blank\">Visit</a>.')
      #   # => Blog: Visit
      def strip_links(html)
99
        self.class.link_sanitizer.sanitize(html)
100 101 102
      end

      module ClassMethods #:nodoc:
103 104 105 106 107 108 109 110 111 112 113 114
        attr_writer :full_sanitizer, :link_sanitizer, :white_list_sanitizer

        def sanitized_protocol_separator
          white_list_sanitizer.protocol_separator
        end

        def sanitized_uri_attributes
          white_list_sanitizer.uri_attributes
        end

        def sanitized_bad_tags
          white_list_sanitizer.bad_tags
115
        end
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

        def sanitized_allowed_tags
          white_list_sanitizer.allowed_tags
        end

        def sanitized_allowed_attributes
          white_list_sanitizer.allowed_attributes
        end

        def sanitized_allowed_css_properties
          white_list_sanitizer.allowed_css_properties
        end

        def sanitized_allowed_css_keywords
          white_list_sanitizer.allowed_css_keywords
        end

        def sanitized_shorthand_css_properties
          white_list_sanitizer.shorthand_css_properties
        end

        def sanitized_allowed_protocols
          white_list_sanitizer.allowed_protocols
        end

        def sanitized_protocol_separator=(value)
          white_list_sanitizer.protocol_separator = value
        end

P
Pratik Naik 已提交
145 146
        # Gets the HTML::FullSanitizer instance used by +strip_tags+.  Replace with
        # any object that responds to +sanitize+.
147 148 149 150 151 152 153 154 155
        #
        #   Rails::Initializer.run do |config|
        #     config.action_view.full_sanitizer = MySpecialSanitizer.new
        #   end
        #
        def full_sanitizer
          @full_sanitizer ||= HTML::FullSanitizer.new
        end

P
Pratik Naik 已提交
156 157
        # Gets the HTML::LinkSanitizer instance used by +strip_links+.  Replace with
        # any object that responds to +sanitize+.
158 159 160 161 162 163 164 165 166
        #
        #   Rails::Initializer.run do |config|
        #     config.action_view.link_sanitizer = MySpecialSanitizer.new
        #   end
        #
        def link_sanitizer
          @link_sanitizer ||= HTML::LinkSanitizer.new
        end

P
Pratik Naik 已提交
167 168
        # Gets the HTML::WhiteListSanitizer instance used by sanitize and +sanitize_css+.
        # Replace with any object that responds to +sanitize+.
169 170 171 172 173 174 175 176
        #
        #   Rails::Initializer.run do |config|
        #     config.action_view.white_list_sanitizer = MySpecialSanitizer.new
        #   end
        #
        def white_list_sanitizer
          @white_list_sanitizer ||= HTML::WhiteListSanitizer.new
        end
177

P
Pratik Naik 已提交
178
        # Adds valid HTML attributes that the +sanitize+ helper checks for URIs.
179 180 181 182 183 184
        #
        #   Rails::Initializer.run do |config|
        #     config.action_view.sanitized_uri_attributes = 'lowsrc', 'target'
        #   end
        #
        def sanitized_uri_attributes=(attributes)
185
          HTML::WhiteListSanitizer.uri_attributes.merge(attributes)
186 187
        end

P
Pratik Naik 已提交
188
        # Adds to the Set of 'bad' tags for the +sanitize+ helper.
189 190 191 192 193 194
        #
        #   Rails::Initializer.run do |config|
        #     config.action_view.sanitized_bad_tags = 'embed', 'object'
        #   end
        #
        def sanitized_bad_tags=(attributes)
195
          HTML::WhiteListSanitizer.bad_tags.merge(attributes)
196
        end
P
Pratik Naik 已提交
197 198

        # Adds to the Set of allowed tags for the +sanitize+ helper.
199 200 201 202 203 204
        #
        #   Rails::Initializer.run do |config|
        #     config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td'
        #   end
        #
        def sanitized_allowed_tags=(attributes)
205
          HTML::WhiteListSanitizer.allowed_tags.merge(attributes)
206 207
        end

P
Pratik Naik 已提交
208
        # Adds to the Set of allowed HTML attributes for the +sanitize+ helper.
209 210 211 212 213 214
        #
        #   Rails::Initializer.run do |config|
        #     config.action_view.sanitized_allowed_attributes = 'onclick', 'longdesc'
        #   end
        #
        def sanitized_allowed_attributes=(attributes)
215
          HTML::WhiteListSanitizer.allowed_attributes.merge(attributes)
216 217
        end

P
Pratik Naik 已提交
218
        # Adds to the Set of allowed CSS properties for the #sanitize and +sanitize_css+ helpers.
219 220 221 222 223 224
        #
        #   Rails::Initializer.run do |config|
        #     config.action_view.sanitized_allowed_css_properties = 'expression'
        #   end
        #
        def sanitized_allowed_css_properties=(attributes)
225
          HTML::WhiteListSanitizer.allowed_css_properties.merge(attributes)
226 227
        end

P
Pratik Naik 已提交
228
        # Adds to the Set of allowed CSS keywords for the +sanitize+ and +sanitize_css+ helpers.
229 230 231 232 233 234
        #
        #   Rails::Initializer.run do |config|
        #     config.action_view.sanitized_allowed_css_keywords = 'expression'
        #   end
        #
        def sanitized_allowed_css_keywords=(attributes)
235
          HTML::WhiteListSanitizer.allowed_css_keywords.merge(attributes)
236 237
        end

P
Pratik Naik 已提交
238
        # Adds to the Set of allowed shorthand CSS properties for the +sanitize+ and +sanitize_css+ helpers.
239 240 241 242 243 244
        #
        #   Rails::Initializer.run do |config|
        #     config.action_view.sanitized_shorthand_css_properties = 'expression'
        #   end
        #
        def sanitized_shorthand_css_properties=(attributes)
245
          HTML::WhiteListSanitizer.shorthand_css_properties.merge(attributes)
246 247
        end

P
Pratik Naik 已提交
248
        # Adds to the Set of allowed protocols for the +sanitize+ helper.
249 250 251 252 253 254
        #
        #   Rails::Initializer.run do |config|
        #     config.action_view.sanitized_allowed_protocols = 'ssh', 'feed'
        #   end
        #
        def sanitized_allowed_protocols=(attributes)
255
          HTML::WhiteListSanitizer.allowed_protocols.merge(attributes)
256 257 258 259 260
        end
      end
    end
  end
end