Class: HTTPDisk::Grep::Main

Inherits:
Object
  • Object
show all
Defined in:
lib/httpdisk/grep/main.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Main

Returns a new instance of Main.



9
10
11
# File 'lib/httpdisk/grep/main.rb', line 9

def initialize(options)
  @options = options
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



7
8
9
# File 'lib/httpdisk/grep/main.rb', line 7

def options
  @options
end

#successObject (readonly)

Returns the value of attribute success.



7
8
9
# File 'lib/httpdisk/grep/main.rb', line 7

def success
  @success
end

Instance Method Details

#pathsObject

file paths to be searched



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/httpdisk/grep/main.rb', line 55

def paths
  # roots
  roots = options[:roots]
  roots = ["."] if roots.empty?

  # find files in roots
  paths = roots.flat_map { Find.find(_1).to_a }.sort
  paths = paths.select { File.file?(_1) }

  # strip default './'
  paths = paths.map { _1.gsub(%r{^\./}, "") } if options[:roots].empty?
  paths
end

#patternObject

regex pattern from options



97
98
99
# File 'lib/httpdisk/grep/main.rb', line 97

def pattern
  @pattern ||= Regexp.new(options[:pattern], Regexp::IGNORECASE)
end

#prepare_body(payload) ⇒ Object

convert raw body into something palatable for pattern matching



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
# File 'lib/httpdisk/grep/main.rb', line 70

def prepare_body(payload)
  body = payload.body

  if (content_type = payload.headers["Content-Type"])
    # Mismatches between Content-Type and body.encoding are fatal, so make
    # an effort to align them.
    if (charset = content_type[/charset=([^;]+)/, 1])
      encoding = begin
        Encoding.find(charset)
      rescue
        nil
      end
      if encoding && body.encoding != encoding
        body.force_encoding(encoding)
      end
    end

    # pretty print json for easier searching
    if /\bjson\b/.match?(content_type)
      body = JSON.pretty_generate(JSON.parse(body))
    end
  end

  body
end

#printerObject

printer for output



102
103
104
105
106
107
108
109
110
111
112
# File 'lib/httpdisk/grep/main.rb', line 102

def printer
  @printer ||= if options[:silent]
    Grep::SilentPrinter.new
  elsif options[:count]
    Grep::CountPrinter.new($stdout)
  elsif options[:head] || $stdout.tty?
    Grep::HeaderPrinter.new($stdout, options[:head])
  else
    Grep::TersePrinter.new($stdout)
  end
end

#runObject

Enumerate file paths one at a time. Returns true if matches were found.



14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/httpdisk/grep/main.rb', line 14

def run
  paths.each do
    run_one(_1)
rescue => e
  if ENV["HTTPDISK_DEBUG"]
    $stderr.puts
    warn e.class
    warn e.backtrace.join("\n")
  end
  raise CliError, "#{e.message[0, 70]} (#{_1})"
  end
  success
end

#run_one(path) ⇒ Object



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
# File 'lib/httpdisk/grep/main.rb', line 28

def run_one(path)
  # read payload & body
  begin
    payload = Zlib::GzipReader.open(path, encoding: "ASCII-8BIT") do
      Payload.read(_1)
    end
  rescue Zlib::GzipFile::Error
    puts "httpdisk: #{path} not in gzip format, skipping" if !options[:silent]
    return
  end

  body = prepare_body(payload)

  # collect all_matches
  all_matches = body.each_line.map do |line|
    [].tap do |matches|
      line.scan(pattern) { matches << Regexp.last_match }
    end
  end.reject(&:empty?)
  return if all_matches.empty?

  # print
  @success = true
  printer.print(path, payload, all_matches)
end