Module: HEITT::Decoder

Defined in:
lib/heitt/decoder.rb

Constant Summary collapse

ENCODED_B64 =
'[A-Za-z0-9+\/]'
BASE_HEXBYTE =
'[[:xdigit:]]'

Class Method Summary collapse

Class Method Details

.binary?(string) ⇒ Boolean

Returns:

  • (Boolean)


7
8
9
10
11
12
13
# File 'lib/heitt/decoder.rb', line 7

def self.binary?(string)
  return true if string.encoding == Encoding::ASCII_8BIT && !string.valid_encoding?
  return true if string.include?("\x00")
  sample = string.bytes.first(4096)
  non_printable = sample.count { |b| b < 32 || b > 126}
  (non_printable.to_f / sample.size) > 0.30
end

.decode_layer(string) ⇒ Object



23
24
25
26
27
# File 'lib/heitt/decoder.rb', line 23

def self.decode_layer(string)
  return [:base64, Base64.decode64(string)] if likely_base64?(string)
  return [:hex, [string].pack("H*")] if likely_hex?(string)
  nil
end

.likely_base64?(string) ⇒ Boolean

Returns:

  • (Boolean)


15
16
17
# File 'lib/heitt/decoder.rb', line 15

def self.likely_base64?(string)
  string.match(/\A(?:#{ENCODED_B64}{4})*(?:#{ENCODED_B64}{2}==|#{ENCODED_B64}{3}=)?\z/)
end

.likely_hex?(string) ⇒ Boolean

Returns:

  • (Boolean)


19
20
21
# File 'lib/heitt/decoder.rb', line 19

def self.likely_hex?(string)
  string.match(/\A#{BASE_HEXBYTE}+\z/) && string.length.even?
end

.peel(string, peel_limit: 12) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/heitt/decoder.rb', line 30

def self.peel(string, peel_limit: 12)
  steps = []
  current = string.gsub(/\s+/, '')

  peel_limit.times do
    result = decode_layer(current)
    break unless result
    method, decoded = result
    decoded = decoded.gsub(/\s+/, '')
    break if binary?(decoded)

    steps << { method: method, result: decoded }
    current = decoded
  end
  { final: current, steps: steps }
end