Included Modules

Class/Module Index [+]

Quicksearch

Rex::Ui::Text::DispatcherShell

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.

Public Class Methods

new(prompt, prompt_char = '>', histfile = nil, framework = nil) click to toggle source

Initialize the dispatcher shell.

# File lib/rex/ui/text/dispatcher_shell.rb, line 250
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

Public Instance Methods

append_dispatcher(dispatcher) click to toggle source

Adds the supplied dispatcher to the end of the dispatcher stack so that it doesn't affect any enstack'd dispatchers.

# File lib/rex/ui/text/dispatcher_shell.rb, line 451
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) click to toggle source

Block a specific command

# File lib/rex/ui/text/dispatcher_shell.rb, line 507
def block_command(cmd)
        self.blocked ||= {}
        self.blocked[cmd] = true
end
blocked_command?(cmd) click to toggle source

Returns nil for an empty set of blocked commands.

# File lib/rex/ui/text/dispatcher_shell.rb, line 499
def blocked_command?(cmd)
        return false if not self.blocked
        self.blocked.has_key?(cmd)
end
current_dispatcher() click to toggle source

Returns the current active dispatcher

# File lib/rex/ui/text/dispatcher_shell.rb, line 475
def current_dispatcher
        self.dispatcher_stack[0]
end
destack_dispatcher() click to toggle source

Pop a dispatcher from the front of the stacker.

# File lib/rex/ui/text/dispatcher_shell.rb, line 443
def destack_dispatcher
        self.dispatcher_stack.shift
end
enstack_dispatcher(dispatcher) click to toggle source

Push a dispatcher to the front of the stack.

# File lib/rex/ui/text/dispatcher_shell.rb, line 434
def enstack_dispatcher(dispatcher)
        self.dispatcher_stack.unshift(inst = dispatcher.new(self))

        inst
end
help_to_s(opts = {}) click to toggle source

Return a readable version of a help banner for all of the enstacked dispatchers.

See +CommandDispatcher#help_to_s+

# File lib/rex/ui/text/dispatcher_shell.rb, line 485
def help_to_s(opts = {})
        str = ''

        dispatcher_stack.reverse.each { |dispatcher|
                str << dispatcher.help_to_s
        }

        return str
end
remove_dispatcher(name) click to toggle source

Removes the supplied dispatcher instance.

# File lib/rex/ui/text/dispatcher_shell.rb, line 466
def remove_dispatcher(name)
        self.dispatcher_stack.delete_if { |inst|
                (inst.name == name)
        }
end
run_command(dispatcher, method, arguments) click to toggle source

Runs the supplied command on the given dispatcher.

# File lib/rex/ui/text/dispatcher_shell.rb, line 413
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) click to toggle source

Run a single command line.

# File lib/rex/ui/text/dispatcher_shell.rb, line 363
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) click to toggle source

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

# File lib/rex/ui/text/dispatcher_shell.rb, line 268
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) click to toggle source

Provide command-specific tab completion

# File lib/rex/ui/text/dispatcher_shell.rb, line 343
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) click to toggle source

Performs tab completion of a command, if supported Current words can be found in self.tab_words

# File lib/rex/ui/text/dispatcher_shell.rb, line 289
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) click to toggle source

Unblock a specific command

# File lib/rex/ui/text/dispatcher_shell.rb, line 515
def unblock_command(cmd)
        self.blocked || return
        self.blocked.delete(cmd)
end
unknown_command(method, line) click to toggle source

If the command is unknown...

# File lib/rex/ui/text/dispatcher_shell.rb, line 427
def unknown_command(method, line)
        print_error("Unknown command: #{method}.")
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.