cirandas.net

ref: master

vendor/plugins/xss_terminate/lib/xss_terminate.rb


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
module XssTerminate

  def self.sanitize_by_default=(value)
    @@sanitize_by_default = value
  end

  def self.included(base)
    base.extend(ClassMethods)
    # sets up default of stripping tags for all fields
    # FIXME read value from environment.rb
    @@sanitize_by_default = false
    base.send(:xss_terminate) if @@sanitize_by_default
  end

  module ClassMethods

    def xss_terminate(options = {})
      options[:with] ||= 'full'
      filter_with = 'sanitize_fields_with_' + options[:with]
      # :on is util when before_filter dont work for model
      case options[:on]
        when 'create'
          before_create filter_with
        when 'validation'
          before_validation filter_with
        else
          before_save filter_with
      end
      class_attribute "xss_terminate_#{options[:with]}_options".to_sym

      
      self.send("xss_terminate_#{options[:with]}_options=".to_sym, {
        :except => (options[:except] || []),
        :if => (options[:if] || true),
        :only => (options[:only] || options[:sanitize] || [])
      }) if 
      include XssTerminate::InstanceMethods

    end

  end

  module InstanceMethods

    def sanitize_field(sanitizer, field, serialized = false)
      field = field.to_sym
      if serialized
        puts field
        self[field].each_key { |key|
          key = key.to_sym
          self[field][key] = sanitizer.sanitize(self[field][key], encode_special_chars: false, scrubber: permit_scrubber )
        }
      else
        if self[field]
          self[field] = sanitizer.sanitize(self[field], encode_special_chars: false, scrubber: permit_scrubber )
        else
          value = self.send("#{field}")
          return unless value
          value = sanitizer.sanitize(value, encode_special_chars: false, scrubber: permit_scrubber)
          self.send("#{field}=", value)
        end
      end
    end

    def  permit_scrubber
        scrubber = Rails::Html::PermitScrubber.new
        scrubber.tags = Rails.application.config.action_view.sanitized_allowed_tags
        scrubber.attributes = Rails.application.config.action_view.sanitized_allowed_attributes
        scrubber
    end

    def sanitize_columns(with = :full)
      columns_serialized = self.class.serialized_attributes.keys
      only = eval "xss_terminate_#{with}_options[:only]"
      except = eval "xss_terminate_#{with}_options[:except]"
      unless except.empty?
        only.delete_if{ |i| except.include?( i.to_sym ) }
      end
      if_condition = eval "xss_terminate_#{with}_options[:if]"
      only = [] if !if_condition.nil? && if_condition.respond_to?(:call) && !if_condition.call(self)

      return only, columns_serialized
    end

    def sanitize_fields_with_full
      sanitize_fields_with(Rails::Html::FullSanitizer.new,:full)
    end

    def sanitize_fields_with_white_list
      sanitize_fields_with(Rails::Html::WhiteListSanitizer.new,:white_list)
    end

    def sanitize_fields_with_html5lib
      sanitize_fields_with(HTML5libSanitize.new,:html5lib)
    end

    def sanitize_fields_with sanitizer, type
      columns, columns_serialized = sanitize_columns(type)
      columns.each {|column| sanitize_field(sanitizer, column.to_sym, columns_serialized.include?(column))}
    end

  end

end