Module: Rex::Ui::Text::DispatcherShell::CommandDispatcher
- Included in:
- Msf::Ui::Console::CommandDispatcher, Post::HWBridge::Ui::Console::CommandDispatcher, Post::Meterpreter::Ui::Console::CommandDispatcher
- Defined in:
- lib/rex/ui/text/dispatcher_shell.rb
Overview
Empty template base class for command dispatchers.
Instance Attribute Summary collapse
-
#shell ⇒ Object
No tab completion items by default.
-
#tab_complete_items ⇒ Object
No tab completion items by default.
Instance Method Summary collapse
-
#cmd_help(cmd = nil, *ignored) ⇒ Object
(also: #cmd_?)
Displays the help banner.
- #cmd_help_help ⇒ Object
-
#cmd_help_tabs(str, words) ⇒ Object
Tab completion for the help command.
-
#commands ⇒ Object
Returns nil for an empty set of commands.
-
#deprecated_cmd(method = nil, *args) ⇒ Object
Print a warning that the called command is deprecated and optionally forward to the replacement
method
(useful for when commands are renamed). -
#deprecated_commands ⇒ Object
Returns an empty set of commands.
- #deprecated_help(method = nil) ⇒ Object
-
#docs_dir ⇒ Object
Return the subdir of the `documentation/` directory that should be used to find usage documentation.
-
#help_to_s(opts = {}) ⇒ Object
Return a pretty, user-readable table of commands provided by this dispatcher.
-
#initialize(shell) ⇒ Object
Initializes the command dispatcher mixin.
-
#print(msg = '') ⇒ Object
Wraps shell.print.
-
#print_error(msg = '') ⇒ Object
(also: #print_bad)
Wraps shell.print_error.
-
#print_good(msg = '') ⇒ Object
Wraps shell.print_good.
-
#print_line(msg = '') ⇒ Object
Wraps shell.print_line.
-
#print_status(msg = '') ⇒ Object
Wraps shell.print_status.
-
#print_warning(msg = '') ⇒ Object
Wraps shell.print_warning.
-
#tab_complete_directory(str, words) ⇒ Object
Return a list of possible directory for tab completion.
-
#tab_complete_filenames(str, words) ⇒ Object
Provide a generic tab completion for file names.
-
#tab_complete_generic(fmt, str, words) ⇒ Object
Provide a generic tab completion function based on the specification pass as fmt.
-
#tab_complete_source_address ⇒ Object
Return a list of possible source addresses for tab completion.
-
#update_prompt(*args) ⇒ Object
Wraps shell.update_prompt.
Instance Attribute Details
#shell ⇒ Object
No tab completion items by default
256 257 258 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 256 def shell @shell end |
#tab_complete_items ⇒ Object
No tab completion items by default
256 257 258 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 256 def tab_complete_items @tab_complete_items end |
Instance Method Details
#cmd_help(cmd = nil, *ignored) ⇒ Object Also known as: cmd_?
Displays the help banner. With no arguments, this is just a list of all commands grouped by dispatcher. Otherwise, tries to use a method named cmd_#<code>cmd</code>_help for the first dispatcher that has a command named cmd
. If no such method exists, uses cmd
as a regex to compare against each enstacked dispatcher's name and dumps commands of any that match.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 150 def cmd_help(cmd=nil, *ignored) if cmd help_found = false cmd_found = false shell.dispatcher_stack.each do |dispatcher| next unless dispatcher.respond_to?(:commands) next if (dispatcher.commands.nil?) next if (dispatcher.commands.length == 0) if dispatcher.respond_to?("cmd_#{cmd}", true) cmd_found = true break unless dispatcher.respond_to?("cmd_#{cmd}_help", true) dispatcher.send("cmd_#{cmd}_help") help_found = true break end end unless cmd_found # We didn't find a cmd, try it as a dispatcher name shell.dispatcher_stack.each do |dispatcher| if dispatcher.name =~ /#{cmd}/i print_line(dispatcher.help_to_s) cmd_found = help_found = true end end end if docs_dir && File.exist?(File.join(docs_dir, cmd + '.md')) print_line print(File.read(File.join(docs_dir, cmd + '.md'))) end print_error("No help for #{cmd}, try -h") if cmd_found and not help_found print_error("No such command") if not cmd_found else print(shell.help_to_s) if docs_dir && File.exist?(File.join(docs_dir + '.md')) print_line print(File.read(File.join(docs_dir + '.md'))) end end end |
#cmd_help_help ⇒ Object
138 139 140 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 138 def cmd_help_help print_line "There's only so much I can do" end |
#cmd_help_tabs(str, words) ⇒ Object
Tab completion for the help command
By default just returns a list of all commands in all dispatchers.
198 199 200 201 202 203 204 205 206 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 198 def cmd_help_tabs(str, words) return [] if words.length > 1 tabs = [] shell.dispatcher_stack.each { |dispatcher| tabs += dispatcher.commands.keys } return tabs end |
#commands ⇒ Object
Returns nil for an empty set of commands.
This method should be overridden to return a Hash with command names for keys and brief help text for values.
46 47 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 46 def commands end |
#deprecated_cmd(method = nil, *args) ⇒ Object
Print a warning that the called command is deprecated and optionally forward to the replacement method
(useful for when commands are renamed).
109 110 111 112 113 114 115 116 117 118 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 109 def deprecated_cmd(method=nil, *args) cmd = caller[0].match(/`cmd_(.*)'/)[1] print_error "The #{cmd} command is DEPRECATED" if cmd == "db_autopwn" print_error "See http://r-7.co/xY65Zr instead" elsif method and self.respond_to?("cmd_#{method}", true) print_error "Use #{method} instead" self.send("cmd_#{method}", *args) end end |
#deprecated_commands ⇒ Object
Returns an empty set of commands.
This method should be overridden if the dispatcher has commands that should be treated as deprecated. Deprecated commands will not show up in help and will not tab-complete, but will still be callable.
56 57 58 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 56 def deprecated_commands [] end |
#deprecated_help(method = nil) ⇒ Object
120 121 122 123 124 125 126 127 128 129 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 120 def deprecated_help(method=nil) cmd = caller[0].match(/`cmd_(.*)_help'/)[1] print_error "The #{cmd} command is DEPRECATED" if cmd == "db_autopwn" print_error "See http://r-7.co/xY65Zr instead" elsif method and self.respond_to?("cmd_#{method}_help", true) print_error "Use 'help #{method}' instead" self.send("cmd_#{method}_help") end end |
#docs_dir ⇒ Object
Return the subdir of the `documentation/` directory that should be used to find usage documentation
TODO: get this value from somewhere that doesn't invert a bunch of dependencies
249 250 251 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 249 def docs_dir File.(File.join(__FILE__, '..', '..', '..', '..', '..', 'documentation', 'cli')) end |
#help_to_s(opts = {}) ⇒ Object
Return a pretty, user-readable table of commands provided by this dispatcher.
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 214 def help_to_s(opts={}) # If this dispatcher has no commands, we can't do anything useful. return "" if commands.nil? or commands.length == 0 # Display the commands tbl = Rex::Text::Table.new( 'Header' => "#{self.name} Commands", 'Indent' => opts['Indent'] || 4, 'Columns' => [ 'Command', 'Description' ], 'ColProps' => { 'Command' => { 'MaxWidth' => 12 } }) commands.sort.each { |c| tbl << c } return "\n" + tbl.to_s + "\n" end |
#initialize(shell) ⇒ Object
Initializes the command dispatcher mixin.
35 36 37 38 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 35 def initialize(shell) self.shell = shell self.tab_complete_items = [] end |
#print(msg = '') ⇒ Object
Wraps shell.print
100 101 102 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 100 def print(msg = '') shell.print(msg) end |
#print_error(msg = '') ⇒ Object Also known as: print_bad
Wraps shell.print_error
63 64 65 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 63 def print_error(msg = '') shell.print_error(msg) end |
#print_good(msg = '') ⇒ Object
Wraps shell.print_good
86 87 88 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 86 def print_good(msg = '') shell.print_good(msg) end |
#print_line(msg = '') ⇒ Object
Wraps shell.print_line
79 80 81 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 79 def print_line(msg = '') shell.print_line(msg) end |
#print_status(msg = '') ⇒ Object
Wraps shell.print_status
72 73 74 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 72 def print_status(msg = '') shell.print_status(msg) end |
#print_warning(msg = '') ⇒ Object
Wraps shell.print_warning
93 94 95 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 93 def print_warning(msg = '') shell.print_warning(msg) end |
#tab_complete_directory(str, words) ⇒ Object
Return a list of possible directory for tab completion.
277 278 279 280 281 282 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 277 def tab_complete_directory(str, words) str = '.' + ::File::SEPARATOR if str.empty? dirs = Dir.glob(str.concat('*'), File::FNM_CASEFOLD).select { |x| File.directory?(x) } dirs end |
#tab_complete_filenames(str, words) ⇒ Object
Provide a generic tab completion for file names.
If the only completion is a directory, this descends into that directory and continues completions with filenames contained within.
264 265 266 267 268 269 270 271 272 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 264 def tab_complete_filenames(str, words) matches = ::Readline::FILENAME_COMPLETION_PROC.call(str) if matches and matches.length == 1 and File.directory?(matches[0]) dir = matches[0] dir += File::SEPARATOR if dir[-1,1] != File::SEPARATOR matches = ::Readline::FILENAME_COMPLETION_PROC.call(dir) end matches end |
#tab_complete_generic(fmt, str, words) ⇒ Object
Provide a generic tab completion function based on the specification pass as fmt. The fmt argument in a hash where values are an array defining how the command should be completed. The first element of the array can be one of:
nil - This argument is a flag and takes no option.
true - This argument takes an option with no suggestions.
:address - This option is a source address.
:bool - This option is a boolean.
:file - This option is a file path.
Array - This option is an array of possible values.
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 296 def tab_complete_generic(fmt, str, words) last_word = words[-1] fmt = fmt.select { |key, value| last_word == key || !words.include?(key) } val = fmt[last_word] return fmt.keys if !val # the last word does not look like a fmtspec arg = val[0] return fmt.keys if !arg # the last word is a fmtspec that takes no argument tabs = [] if arg.to_s.to_sym == :address tabs = tab_complete_source_address elsif arg.to_s.to_sym == :bool tabs = ['true', 'false'] elsif arg.to_s.to_sym == :file tabs = tab_complete_filenames(str, words) elsif arg.kind_of?(Array) tabs = arg.map {|a| a.to_s} end tabs end |
#tab_complete_source_address ⇒ Object
Return a list of possible source addresses for tab completion.
321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 321 def tab_complete_source_address addresses = [Rex::Socket.source_address] # getifaddrs was introduced in 2.1.2 if ::Socket.respond_to?(:getifaddrs) ifaddrs = ::Socket.getifaddrs.select do |ifaddr| ifaddr.addr && ifaddr.addr.ip? end addresses += ifaddrs.map { |ifaddr| ifaddr.addr.ip_address } end addresses end |
#update_prompt(*args) ⇒ Object
Wraps shell.update_prompt
134 135 136 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 134 def update_prompt(*args) shell.update_prompt(*args) end |