Class: Rex::Parser::Arguments

Inherits:
Object
  • Object
show all
Defined in:
lib/rex/parser/arguments.rb

Overview

This class parses arguments in a getopt style format, kind of. Unfortunately, the default ruby getopt implementation will only work on ARGV, so we can't use it.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fmt) ⇒ Arguments

Initializes the format list with an array of formats like:

Arguments.new(

'-b'                => [ false, "some text"                 ],
['-b']              => [ false, "some text"                 ],
'--sample'          => [ false, "sample long arg"           ],
'--also-a-sample'   => [ false, "sample longer arg"         ],
['-x', '--execute'] => [ true, "mixing long and short args" ]

)



26
27
28
29
30
# File 'lib/rex/parser/arguments.rb', line 26

def initialize(fmt)
  normalised_fmt = fmt.map { |key, | [Array(key), ] }.to_h
  self.fmt = normalised_fmt
  self.longest = normalised_fmt.keys.map { |key| key.flatten.join(', ') }.max_by(&:length)
end

Class Method Details

.from_s(str) ⇒ Object

Takes a string and converts it into an array of arguments.



35
36
37
# File 'lib/rex/parser/arguments.rb', line 35

def self.from_s(str)
  Shellwords.shellwords(str)
end

Instance Method Details

#arg_required?(opt) ⇒ Boolean

Returns:

  • (Boolean)


107
108
109
110
111
112
# File 'lib/rex/parser/arguments.rb', line 107

def arg_required?(opt)
  value = select_value_from_fmt_option(opt)
  return false if value.nil?

  value.first
end

#include?(search) ⇒ Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/rex/parser/arguments.rb', line 103

def include?(search)
  fmt.keys.flatten.include?(search)
end

#merge(to_merge) ⇒ Object

Return new Parser object featuring options from the base object and including the options hash that was passed in



119
120
121
122
123
# File 'lib/rex/parser/arguments.rb', line 119

def merge(to_merge)
  return fmt unless to_merge.is_a?(Hash)

  Rex::Parser::Arguments.new(fmt.clone.merge(to_merge))
end

#option_keysObject



114
115
116
# File 'lib/rex/parser/arguments.rb', line 114

def option_keys
  fmt.keys.flatten
end

#parse(args, &_block) ⇒ Object

Parses the supplied arguments into a set of options.



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
# File 'lib/rex/parser/arguments.rb', line 42

def parse(args, &_block)
  # e.g. '-x' or '-xyz'
  short_flag = /^-[a-zA-Z]+$/
  # e.g. '--verbose', '--very-verbose' or '--very-very-verbose'
  long_flag = /^--([a-zA-Z]+)((-[a-zA-Z]+)*)$/

  skip_next = false

  args.each_with_index do |arg, idx|
    if skip_next
      skip_next = false
      next
    end

    param = nil
    if arg =~ short_flag
      arg.split('')[1..-1].each do |letter|
        next unless include?("-#{letter}")

        if arg_required?("-#{letter}")
          param = args[idx + 1]
          skip_next = true
        end

        yield "-#{letter}", idx, param
      end
    elsif arg =~ long_flag && include?(arg)
      if arg_required?(arg)
        param = args[idx + 1]
        skip_next = true
      end

      yield arg, idx, param
    else
      # else treat the passed in flag as argument
      yield nil, idx, arg
    end
  end
end

#usageObject

Returns usage information for this parsing context.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/rex/parser/arguments.rb', line 85

def usage
  txt = ["\nOPTIONS:\n"]

  fmt.sort_by { |key, | key.to_s.downcase }.each do |key, val|
    opt = val[0] ? " <opt>  " : "        "

    # Get all arguments for a command
    output = key.join(', ')
    output += opt

    # Left align the fmt options and <opt> string
    txt << "    #{(output).ljust((longest + opt).length)}#{val[1]}"
  end

  txt << ""
  txt.join("\n")
end