Tab completion changes, start of completion routines

git-svn-id: file:///home/svn/incoming/trunk@3061 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
HD Moore 2005-11-23 22:12:49 +00:00
parent 2dc8cd66d3
commit cad67cec49
4 changed files with 129 additions and 15 deletions

View File

@ -581,7 +581,7 @@ class Core
print_line("#{name} => #{value}")
end
#
# Sets the supplied variables in the global datastore.
#
@ -636,7 +636,18 @@ class Core
end
}
end
#
# Tab completion for the show command
#
def cmd_show_tabs(str, words)
res = %w{all encoders nops exploits payloads recon plugins}
if (active_module)
res.concat(%w{ options advanced })
end
return res
end
#
# Unloads a plugin by its name.
#
@ -659,6 +670,13 @@ class Core
end
}
end
#
# Tab completion for the unload command
#
def cmd_unload_tabs(str, words)
framework.plugins.each { k.name }
end
#
# Unsets a value if it's been set.
@ -700,7 +718,15 @@ class Core
datastore.delete(val)
end
end
#
# Tab completion for the unset command
#
def cmd_unset_tabs(str, words)
datastore = active_module ? active_module.datastore : self.framework.datastore
datastore.keys
end
#
# Unsets variables in the global data store.
#
@ -709,7 +735,14 @@ class Core
cmd_unset(*args)
end
#
# Tab completion for the unsetg command
#
def cmd_unsetg_tabs(str, words)
self.framework.datastore.keys
end
#
# Uses a module.
#
@ -771,7 +804,19 @@ class Core
# Update the command prompt
driver.update_prompt("#{mod.type}(#{mod.refname}) ")
end
#
# Tab completion for the use command
#
def cmd_use_tabs(str, words)
res = []
framework.modules.each_module { |refname, mod|
res << refname
res << mod.fullname
}
return res
end
#
# Returns the revision of the console library
#
@ -791,6 +836,27 @@ class Core
recalculate_tab_complete
end
#
# Provide command-specific tab completion
#
def tab_complete_helper(str, words)
items = []
# Is the user trying to tab complete one of our commands?
if (commands.include?(words[0]))
if (self.respond_to?('cmd_'+words[0]+'_tabs'))
res = self.send('cmd_'+words[0]+'_tabs', str, words)
return nil if res.nil?
items.concat(res)
else
# Avoid the default completion list for known commands
return nil
end
end
return items
end
protected
#
@ -798,11 +864,7 @@ protected
#
def recalculate_tab_complete
self.tab_complete_items = []
framework.modules.each_module { |refname, mod|
self.tab_complete_items << refname
self.tab_complete_items << mod.fullname
}
# wont be needed much longer
end
#

View File

@ -66,6 +66,9 @@ class Driver < Msf::Ui::Driver
# Process the resource script
process_rc_file
# Initialize the tab completion array
self.tab_words = []
end
#
@ -201,6 +204,7 @@ class Driver < Msf::Ui::Driver
protected
attr_writer :framework # :nodoc:
attr_accessor :tab_words # :nodoc:
##
#
@ -260,6 +264,31 @@ protected
set_log_level(Rex::LogSource, val)
set_log_level(Msf::LogSource, val)
end
#
# 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
#
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 parent
super(self.tab_words.pop)
end
end

View File

@ -95,24 +95,46 @@ module DispatcherShell
#
# Performs tab completion on shell input if supported.
# Current words can be found in self.tab_words
#
def tab_complete(str)
items = []
# 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 it supports commands, query them all
if (dispatcher.respond_to?('commands'))
# 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.to_a.map { |x| x[0] })
end
# XXX - This should now be obsolete!
# If the dispatcher has custom tab completion items, use them
items.concat(dispatcher.tab_complete_items || [])
# items.concat(dispatcher.tab_complete_items || [])
# 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)
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
end
}
# 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

View File

@ -21,10 +21,11 @@ begin
#
def initialize(tab_complete_proc = nil)
if (tab_complete_proc)
::Readline.basic_word_break_characters = "\x00"
::Readline.completion_proc = tab_complete_proc
end
end
#
# Regular old gets, reads a line of input and returns it to the caller.
#