''' consoleMenu.py Copyright 2006 Andres Riancho This file is part of w3af, w3af.sourceforge.net . w3af is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License. w3af is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with w3af; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ''' # Some traditional imports import traceback import sys from core.controllers.w3afException import w3afException import core.controllers.outputManager as om class consoleMenu: ''' This class is a menu for console. @author: Andres Riancho ( andres.riancho@gmail.com ) ''' def __init__( self ): self._spacesSettings = 20 self._commandHistory = [] self._commandIndex = 0 self._lastKeyWasArrow = False def _parse( self, command ): ''' Parses the user input. @return: A command and its parameters in a tuple. ''' self._commandHistory.append( command ) c = command.split(' ')[0] p = [] p.extend( command.split(' ')[1:] ) return c, p def _printCommand( self, commandIndex, toRemove ): ''' Prints a command to the console using raw console mode. ''' for i in xrange(toRemove): om.out.console( "\b \b", newLine=False ) res = self._commandHistory[ commandIndex ] om.out.console( res , newLine=False ) return res def _read( self ): def go(): res = '' left = '' right = '' while True: c = read(1) if c == '\033': # is an arrow if not self._lastKeyWasArrow: self._commandIndex = len( self._commandHistory ) self._commandHistory.append( res ) self._lastKeyWasArrow = True c = read(2) if c == '[A': #up arrow if self._commandIndex<= 0: om.out.console( "\a", newLine=False ) else: self._commandIndex -= 1 res = self._printCommand( self._commandIndex, len( res ) ) elif c == '[B': #down arrow if self._commandIndex >= (len(self._commandHistory) -1): om.out.console( "\a", newLine=False ) else: self._commandIndex += 1 res = self._printCommand( self._commandIndex, len( res ) ) elif c == '[D': #left arrow if len(res) != 0: om.out.console( "\b \b", newLine=False ) res = res[:-1] elif c == '[C': #right arrow #sys.stdout.write("\b") pass else: self._lastKeyWasArrow = False if ord(c) == 9: # tab! possible = [] for command in self._menu.keys(): if command.find( res ) == 0: possible.append( command ) if len(possible) == 0: om.out.console( "\a", newLine=False ) elif len(possible) == 1: for i in res: om.out.console( "\b \b", newLine=False ) res = possible[0] + ' ' om.out.console( res , newLine=False ) else: for i in res: om.out.console( "\b \b", newLine=False ) om.out.console( "\n\r", newLine=False ) for i in possible: om.out.console( i + "\n\r", newLine=False ) om.out.console( self._prompt, newLine=False ) om.out.console( res, newLine=False ) elif ord(c) == 3: #ctrl+c raise KeyboardInterrupt elif ord(c) == 13: om.out.console( "\n\r", newLine=False ) return res elif ord(c) == 127: #backspace if len(res) != 0: om.out.console( "\b \b", newLine=False ) res = res[:-1] else: res += c om.out.console( c, newLine=False ) if len( self._commands ) != 0: command = self._commands.pop() om.out.console( command, newLine=True ) res = command else: setRawInputMode( True ) try: res = go() except Exception,e: setRawInputMode( False ) raise e else: setRawInputMode( False ) return res def _mainloop( self, prompt, callback=None ): go = True self._prompt = prompt while go != False: om.out.console( prompt, newLine=False ) try: command = self._read() if command != '': if callback == None: go = self._exec( command.strip() ) else: args = (command,) go = apply( callback, args, {} ) except w3afException, e: setRawInputMode( False ) om.out.error( str(e) ) except KeyboardInterrupt,k: setRawInputMode( False ) go = False self._back( [] ) om.out.console( '' ) except: setRawInputMode( False ) raise def mprint( self, col1, col2 ): ''' Prints two columns to the console. ''' spaces = self._spacesSettings spaces -= len( col1 ) om.out.console( col1, newLine=False ) for i in xrange(spaces): om.out.console(' ', newLine=False) if spaces < 0: om.out.console(' ', newLine=False) om.out.console( col2 ) def mprintn( self, printList ): ''' Prints N columns to the console, where N is len(printList) ''' for col in printList: spaces = self._spacesSettings spaces -= len( col ) om.out.console( col, newLine=False ) for i in range(spaces): om.out.console(' ', newLine=False) if spaces < 0: om.out.console(' ', newLine=False) om.out.console( '' ) def setRawInputMode_win( raw ): ''' Sets the raw input mode, in windows. ''' pass def read_win( amt ): res = '' for i in xrange( amt ): res += msvcrt.getch() return res oldSettings = None def setRawInputMode_unix( raw ): ''' Sets the raw input mode, in linux. ''' global oldSettings if raw: fd = sys.stdin.fileno() oldSettings = termios.tcgetattr(fd) tty.setraw(sys.stdin.fileno()) else: if oldSettings == None: fd = sys.stdin.fileno() oldSettings = termios.tcgetattr(fd) termios.tcsetattr( sys.stdin.fileno() , termios.TCSADRAIN, oldSettings ) def read_unix( amt ): return sys.stdin.read( amt ) try: import tty, termios except: # We arent on unix ! try: import msvcrt except: # We arent on windows nor unix raise w3afException('w3af support for OS X aint available yet! Please contribute.') else: setRawInputMode = setRawInputMode_win read = read_win else: setRawInputMode = setRawInputMode_unix read = read_unix