Class: Honeybadger::Util::Sanitizer Private

Inherits:
Object
  • Object
show all
Defined in:
lib/honeybadger/util/sanitizer.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Sanitizer sanitizes data for sending to Honeybadger's API. The filters are based on Rails' HTTP parameter filter.

Constant Summary collapse

/[;,]\s?/
'='.freeze
'; '.freeze
ENCODE_OPTS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

{ invalid: :replace, undef: :replace, replace: '?'.freeze }.freeze
BASIC_OBJECT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'#<BasicObject>'.freeze
DEPTH =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'[DEPTH]'.freeze
FILTERED =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'[FILTERED]'.freeze
RAISED =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'[RAISED]'.freeze
RECURSION =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'[RECURSION]'.freeze
TRUNCATED =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'[TRUNCATED]'.freeze
IMMUTABLE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

[NilClass, FalseClass, TrueClass, Symbol, Numeric, BigDecimal, Method].freeze
MAX_STRING_SIZE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

65536
VALID_ENCODINGS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

[Encoding::UTF_8, Encoding::ISO_8859_1].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_depth: 20, filters: []) ⇒ Sanitizer

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Sanitizer


35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/honeybadger/util/sanitizer.rb', line 35

def initialize(max_depth: 20, filters: [])
  @filters = !filters.empty?
  @max_depth = max_depth

  strings, @regexps, @blocks = [], [], []

  filters.each do |item|
    case item
    when Proc
      @blocks << item
    when Regexp
      @regexps << item
    else
      strings << Regexp.escape(item.to_s)
    end
  end

  @deep_regexps, @regexps = @regexps.partition { |r| r.to_s.include?('\\.'.freeze) }
  deep_strings, @strings = strings.partition { |s| s.include?('\\.'.freeze) }

  @regexps << Regexp.new(strings.join('|'.freeze), true) unless strings.empty?
  @deep_regexps << Regexp.new(deep_strings.join('|'.freeze), true) unless deep_strings.empty?
end

Class Method Details

.sanitize(data) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


30
31
32
33
# File 'lib/honeybadger/util/sanitizer.rb', line 30

def self.sanitize(data)
  @sanitizer ||= new
  @sanitizer.sanitize(data)
end

Instance Method Details

#filter_cookies(raw_cookies) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/honeybadger/util/sanitizer.rb', line 133

def filter_cookies(raw_cookies)
  return raw_cookies unless filters?

  cookies = []

  raw_cookies.to_s.split(COOKIE_PAIRS).each do |pair|
    name, values = pair.split(COOKIE_SEP, 2)
    values = FILTERED if filter_key?(name)
    cookies << "#{name}=#{values}"
  end

  cookies.join(COOKIE_PAIR_SEP)
end

#filter_url(url) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/honeybadger/util/sanitizer.rb', line 147

def filter_url(url)
  return url unless filters?

  filtered_url = url.to_s.dup

  filtered_url.scan(/(?:^|&|\?)([^=?&]+)=([^&]+)/).each do |m|
    next unless filter_key?(m[0])
    filtered_url.gsub!(/#{Regexp.escape(m[1])}/, FILTERED)
  end

  filtered_url
end

#sanitize(data, depth = 0, stack = nil, parents = []) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/honeybadger/util/sanitizer.rb', line 59

def sanitize(data, depth = 0, stack = nil, parents = [])
  return BASIC_OBJECT if basic_object?(data)

  if recursive?(data)
    return RECURSION if stack && stack.include?(data.object_id)

    stack = stack ? stack.dup : Set.new
    stack << data.object_id
  end

  case data
  when Hash
    return DEPTH if depth >= max_depth

    hash = data.to_hash
    new_hash = {}

    hash.each_pair do |key, value|
      parents.push(key) if deep_regexps
      key = key.kind_of?(Symbol) ? key : sanitize(key, depth+1, stack, parents)

      if filter_key?(key, parents)
        new_hash[key] = FILTERED
      else
        value = sanitize(value, depth+1, stack, parents)

        if blocks.any? && !recursive?(value)
          key = key.dup if can_dup?(key)
          value = value.dup if can_dup?(value)
          blocks.each { |b| b.call(key, value) }
        end

        new_hash[key] = value
      end

      parents.pop if deep_regexps
    end

    new_hash
  when Array, Set
    return DEPTH if depth >= max_depth

    data.to_a.map do |value|
      sanitize(value, depth+1, stack, parents)
    end
  when Numeric, TrueClass, FalseClass, NilClass
    data
  when String
    sanitize_string(data)
  when -> (d) { d.respond_to?(:to_honeybadger) }
    return DEPTH if depth >= max_depth

    begin
      data = data.to_honeybadger
    rescue
      return RAISED
    end

    sanitize(data, depth+1, stack, parents)
  else # all other objects
    klass = data.class

    begin
      data = String(data)
    rescue
      return RAISED
    end

    return "#<#{klass.name}>" if inspected?(data)

    sanitize_string(data)
  end
end