aboutsummaryrefslogblamecommitdiffstats
path: root/actionview/lib/action_view/helpers/sanitize_helper/sanitizers.rb
blob: c6bbf5e3f781cb0cebadea21870aa68885f9fb84 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                                 
                                                       

                 

                                                    
                 
             
                                    



                                                            




                                                        
         







                                    


                                                 


       
                                 
                  

                                         






                                                      
                                      




                                           

                                    

                                             

                                                                     

                                                  



                                                          
                                                        
                                      
         







                                                 
                                   


                                  
                                   


                
                         







                                                                                                    
                          


                  
                                                                                                                                                                                                                       





















                                                                        
                                           









                                                                                      

     
require 'active_support/core_ext/class/attribute'
require 'active_support/deprecation'
require 'action_view/helpers/sanitize_helper/scrubbers'

module ActionView
  XPATHS_TO_REMOVE = %w{.//script .//form comment()}

  class Sanitizer
    # :nodoc:
    def sanitize(html, options = {})
      raise NotImplementedError, "subclasses must implement"
    end

    def remove_xpaths(html, xpaths)
      if html.respond_to?(:xpath)
        xpaths.each { |xpath| html.xpath(xpath).remove }
        html.to_s
      else
        remove_xpaths(Loofah.fragment(html), xpaths)
      end
    end
  end

  class FullSanitizer < Sanitizer
    def sanitize(html, options = {})
      return nil unless html
      return html if html.empty?

      Loofah.fragment(html).tap do |fragment|
        remove_xpaths(fragment, XPATHS_TO_REMOVE)
      end.text
    end
  end

  class LinkSanitizer < Sanitizer
    def initialize
      @link_scrubber = TargetScrubber.new
      @link_scrubber.tags = %w(a href)
    end

    def sanitize(html, options = {})
      Loofah.scrub_fragment(html, @link_scrubber).to_s
    end
  end

  class WhiteListSanitizer < Sanitizer

    def initialize
      @permit_scrubber = PermitScrubber.new
    end

    def sanitize(html, options = {})
      return nil unless html

      loofah_fragment = Loofah.fragment(html)
      if scrubber = options[:scrubber]
        # No duck typing, Loofah ensures subclass of Loofah::Scrubber
        loofah_fragment.scrub!(scrubber)
      elsif options[:tags] || options[:attributes]
        @permit_scrubber.tags = options[:tags]
        @permit_scrubber.attributes = options[:attributes]
        loofah_fragment.scrub!(@permit_scrubber)
      else
        remove_xpaths(loofah_fragment, XPATHS_TO_REMOVE)
        loofah_fragment.scrub!(:strip)
      end
      loofah_fragment.to_s
    end

    def sanitize_css(style_string)
      Loofah::HTML5::Scrub.scrub_css style_string
    end

    def protocol_separator
      self.class.protocol_separator
    end

    def protocol_separator=(value)
      self.class.protocol_separator
    end

    def bad_tags
      self.class.bad_tags
    end

    class << self
      def protocol_separator
        ActiveSupport::Deprecation.warn('protocol_separator has been deprecated and has no effect.')
      end

      def protocol_separator=(value)
        protocol_separator
      end

      def bad_tags
        ActiveSupport::Deprecation.warn('bad_tags has been deprecated and has no effect. You can still affect the tags being sanitized using ActionView::WhiteListSanitizer.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 form)

    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
  end
end