Module: Rex::Ui::Text::DispatcherShell
- Includes:
- Shell
- Included in:
- Post::Meterpreter::Ui::Console
- Defined in:
- lib/rex/ui/text/dispatcher_shell.rb
Overview
The dispatcher shell class is designed to provide a generic means of processing various shell commands that may be located in different modules or chunks of codes. These chunks are referred to as command dispatchers. The only requirement for command dispatchers is that they prefix every method that they wish to be mirrored as a command with the cmd_ prefix.
Defined Under Namespace
Modules: CommandDispatcher
Instance Attribute Summary collapse
-
#blocked ⇒ Object
:nodoc:.
-
#busy ⇒ Object
:nodoc:.
-
#dispatcher_stack ⇒ Object
:nodoc:.
-
#tab_words ⇒ Object
:nodoc:.
Attributes included from Shell
#disable_output, #framework, #input, #on_command_proc, #on_print_proc, #output
Instance Method Summary collapse
-
#append_dispatcher(dispatcher) ⇒ Object
Adds the supplied dispatcher to the end of the dispatcher stack so that it doesn’t affect any enstack’d dispatchers.
-
#block_command(cmd) ⇒ Object
Block a specific command.
-
#blocked_command?(cmd) ⇒ Boolean
Returns nil for an empty set of blocked commands.
-
#current_dispatcher ⇒ Object
Returns the current active dispatcher.
-
#destack_dispatcher ⇒ Object
Pop a dispatcher from the front of the stacker.
-
#enstack_dispatcher(dispatcher) ⇒ Object
Push a dispatcher to the front of the stack.
-
#help_to_s(opts = {}) ⇒ Object
Return a readable version of a help banner for all of the enstacked dispatchers.
-
#initialize(prompt, prompt_char = '>', histfile = nil, framework = nil) ⇒ Object
Initialize the dispatcher shell.
-
#remove_dispatcher(name) ⇒ Object
Removes the supplied dispatcher instance.
-
#run_command(dispatcher, method, arguments) ⇒ Object
Runs the supplied command on the given dispatcher.
-
#run_single(line) ⇒ Object
Run a single command line.
-
#tab_complete(str) ⇒ Object
This method accepts the entire line of text from the Readline routine, stores all completed words, and passes the partial word to the real tab completion function.
-
#tab_complete_helper(dispatcher, str, words) ⇒ Object
Provide command-specific tab completion.
-
#tab_complete_stub(str) ⇒ Object
Performs tab completion of a command, if supported Current words can be found in self.tab_words.
-
#unblock_command(cmd) ⇒ Object
Unblock a specific command.
-
#unknown_command(method, line) ⇒ Object
If the command is unknown…
Methods included from Shell
#init_tab_complete, #init_ui, #print, #print_error, #print_good, #print_line, #print_status, #reset_ui, #run, #set_log_source, #stop, #stopped?, #unset_log_source, #update_prompt
Instance Attribute Details
#blocked ⇒ Object
:nodoc:
525 526 527 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 525 def blocked @blocked end |
#busy ⇒ Object
:nodoc:
524 525 526 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 524 def busy @busy end |
#dispatcher_stack ⇒ Object
:nodoc:
522 523 524 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 522 def dispatcher_stack @dispatcher_stack end |
#tab_words ⇒ Object
:nodoc:
523 524 525 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 523 def tab_words @tab_words end |
Instance Method Details
#append_dispatcher(dispatcher) ⇒ Object
Adds the supplied dispatcher to the end of the dispatcher stack so that it doesn’t affect any enstack’d dispatchers.
452 453 454 455 456 457 458 459 460 461 462 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 452 def append_dispatcher(dispatcher) inst = dispatcher.new(self) self.dispatcher_stack.each { |disp| if (disp.name == inst.name) raise RuntimeError.new("Attempting to load already loaded dispatcher #{disp.name}") end } self.dispatcher_stack.push(inst) inst end |
#block_command(cmd) ⇒ Object
Block a specific command
508 509 510 511 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 508 def block_command(cmd) self.blocked ||= {} self.blocked[cmd] = true end |
#blocked_command?(cmd) ⇒ Boolean
Returns nil for an empty set of blocked commands.
500 501 502 503 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 500 def blocked_command?(cmd) return false if not self.blocked self.blocked.has_key?(cmd) end |
#current_dispatcher ⇒ Object
Returns the current active dispatcher
476 477 478 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 476 def current_dispatcher self.dispatcher_stack[0] end |
#destack_dispatcher ⇒ Object
Pop a dispatcher from the front of the stacker.
444 445 446 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 444 def destack_dispatcher self.dispatcher_stack.shift end |
#enstack_dispatcher(dispatcher) ⇒ Object
Push a dispatcher to the front of the stack.
435 436 437 438 439 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 435 def enstack_dispatcher(dispatcher) self.dispatcher_stack.unshift(inst = dispatcher.new(self)) inst end |
#help_to_s(opts = {}) ⇒ Object
Return a readable version of a help banner for all of the enstacked dispatchers.
See CommandDispatcher#help_to_s
486 487 488 489 490 491 492 493 494 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 486 def help_to_s(opts = {}) str = '' dispatcher_stack.reverse.each { |dispatcher| str << dispatcher.help_to_s } return str end |
#initialize(prompt, prompt_char = '>', histfile = nil, framework = nil) ⇒ Object
Initialize the dispatcher shell.
251 252 253 254 255 256 257 258 259 260 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 251 def initialize(prompt, prompt_char = '>', histfile = nil, framework = nil) super # Initialze the dispatcher array self.dispatcher_stack = [] # Initialize the tab completion array self.tab_words = [] self.on_command_proc = nil end |
#remove_dispatcher(name) ⇒ Object
Removes the supplied dispatcher instance.
467 468 469 470 471 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 467 def remove_dispatcher(name) self.dispatcher_stack.delete_if { |inst| (inst.name == name) } end |
#run_command(dispatcher, method, arguments) ⇒ Object
Runs the supplied command on the given dispatcher.
414 415 416 417 418 419 420 421 422 423 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 414 def run_command(dispatcher, method, arguments) self.busy = true if(blocked_command?(method)) print_error("The #{method} command has been disabled.") else dispatcher.send('cmd_' + method, *arguments) end self.busy = false end |
#run_single(line) ⇒ Object
Run a single command line.
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 364 def run_single(line) arguments = parse_line(line) method = arguments.shift found = false error = false # If output is disabled output will be nil output.reset_color if (output) if (method) entries = dispatcher_stack.length dispatcher_stack.each { |dispatcher| next if not dispatcher.respond_to?('commands') begin if (dispatcher.commands.has_key?(method) or dispatcher.deprecated_commands.include?(method)) self.on_command_proc.call(line.strip) if self.on_command_proc run_command(dispatcher, method, arguments) found = true end rescue error = $! print_error( "Error while running command #{method}: #{$!}" + "\n\nCall stack:\n#{$@.join("\n")}") rescue ::Exception error = $! print_error( "Error while running command #{method}: #{$!}") end # If the dispatcher stack changed as a result of this command, # break out break if (dispatcher_stack.length != entries) } if (found == false and error == false) unknown_command(method, line) end end return found end |
#tab_complete(str) ⇒ Object
This method accepts the entire line of text from the Readline routine, stores all completed words, and passes the partial word to the real tab completion function. This works around a design problem in the Readline module and depends on the Readline.basic_word_break_characters variable being set to x00
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 269 def tab_complete(str) # Check trailing whitespace so we can tell 'x' from 'x ' str_match = str.match(/\s+$/) str_trail = (str_match.nil?) ? '' : str_match[0] # Split the line up by whitespace into words str_words = str.split(/[\s\t\n]+/) # Append an empty word if we had trailing whitespace str_words << '' if str_trail.length > 0 # Place the word list into an instance variable self.tab_words = str_words # Pop the last word and pass it to the real method tab_complete_stub(self.tab_words.pop) end |
#tab_complete_helper(dispatcher, str, words) ⇒ Object
Provide command-specific tab completion
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 344 def tab_complete_helper(dispatcher, str, words) items = [] tabs_meth = "cmd_#{words[0]}_tabs" # Is the user trying to tab complete one of our commands? if (dispatcher.commands.include?(words[0]) and dispatcher.respond_to?(tabs_meth)) res = dispatcher.send(tabs_meth, str, words) return [] if res.nil? items.concat(res) else # Avoid the default completion list for known commands return [] end return items end |
#tab_complete_stub(str) ⇒ Object
Performs tab completion of a command, if supported Current words can be found in self.tab_words
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 290 def tab_complete_stub(str) items = [] return nil if not str # puts "Words(#{tab_words.join(", ")}) Partial='#{str}'" # Next, try to match internal command or value completion # Enumerate each entry in the dispatcher stack dispatcher_stack.each { |dispatcher| # If no command is set and it supports commands, add them all if (tab_words.empty? and dispatcher.respond_to?('commands')) items.concat(dispatcher.commands.keys) end # If the dispatcher exports a tab completion function, use it if(dispatcher.respond_to?('tab_complete_helper')) res = dispatcher.tab_complete_helper(str, tab_words) else res = tab_complete_helper(dispatcher, str, tab_words) end if (res.nil?) # A nil response indicates no optional arguments return [''] if items.empty? else # Otherwise we add the completion items to the list items.concat(res) end } # Verify that our search string is a valid regex begin Regexp.compile(str) rescue RegexpError str = Regexp.escape(str) end # XXX - This still doesn't fix some Regexp warnings: # ./lib/rex/ui/text/dispatcher_shell.rb:171: warning: regexp has `]' without escape # Match based on the partial word items.find_all { |e| e =~ /^#{str}/ # Prepend the rest of the command (or it gets replaced!) }.map { |e| tab_words.dup.push(e).join(' ') } end |
#unblock_command(cmd) ⇒ Object
Unblock a specific command
516 517 518 519 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 516 def unblock_command(cmd) self.blocked || return self.blocked.delete(cmd) end |
#unknown_command(method, line) ⇒ Object
If the command is unknown…
428 429 430 |
# File 'lib/rex/ui/text/dispatcher_shell.rb', line 428 def unknown_command(method, line) print_error("Unknown command: #{method}.") end |