#!/usr/bin/env python # Time-stamp: <2005-04-05 18:03:59 crabbkw> # Code and design by Casey Crabb (crabbkw@nafai.dyndns.org) # This code is licensed under the BSD license. # See the LICENSE file for details # # Copyright Casey Crabb (crabbkw@nafai.dyndns.org) July 2001 # # from __future__ import nested_scopes from threading import * from IMCom import IMCom, errorCodes from Preferences import Preferences from LogHandler import LogHandler from AutoStatus import AutoStatus import CICommands from Colors import * import types import string import socket import os import time import sys import getpass import operator import signal import traceback import SocketWrapper import pprint import getopt import math try: import fcntl import termios import struct TERMWIDTH=1 except: TERMWIDTH=0 try: import codecs CODECS = 1 except: CODECS = 0 try: import locale LOCALE = 1 except: LOCALE = 0 try: import readline READLINE = 1 except: READLINE = 0 if sys.version_info[0] >= 2 and sys.version_info[1] >= 2: METACLASSES = 1 else: METACLASSES = 0 VERSION = "1.33 patch 1" tabCompleteToLastUser=0 terminalWidth = 80 pp = pprint.PrettyPrinter(indent=4) def mySort(x, y): a,b = x c,d = y return cmp(b,d) def getTerminalWidth(): height, width = getheightwidth() #print "(width,height) (",width,",",height,")" return width def getTerminalHeight(): height, width = getheightwidth() #print "(width,height) (",width,",",height,")" return height def getheightwidth(): """Return the height and width of the console in characters """ if not TERMWIDTH: return 24, 80 try: return int(os.environ["LINES"]), int(os.environ["COLUMNS"]) except KeyError: height, width = struct.unpack("hhhh", fcntl.ioctl(0, termios.TIOCGWINSZ ,"\000"*8))[0:2] if not height: return 25, 80 return int(height), int(width) class WrapperMetaclass: def __init__(self, prefix, wrapper): self.prefix = prefix self.wrapper = wrapper def __call__(self, name, bases, attrs): methodNames = [] additionalMethods = [] for k in attrs: if k.startswith(self.prefix): methodNames.append(k) additionalMethods.append(["_"+k, attrs[k]]) attrs[k] = self.wrapper(attrs[k]) for k in additionalMethods: attrs[k[0]]=k[1] attrs['methodNames'] = methodNames return type(name, bases, attrs) def methodWrapper(aMethod): def wrappingMethod(*args, **kw): tmp = args[0] # tmp is the object itself, hopefully a CLI instance if tmp.callbacks.has_key(aMethod.__name__): for func in tmp.callbacks[aMethod.__name__][0]: # call all the pre-method modules in order. res = func(*args, **kw) if(res == -1): return res if type(res) is types.ListType and len(res) == len(args): args = res aResult = aMethod(*args, **kw) # call the method itself if tmp.callbacks.has_key(aMethod.__name__): for func in tmp.callbacks[aMethod.__name__][1]: # call all the post-method modules in order. res = func(*args, **kw) if(res == -1): return res if type(res) is types.ListType and len(res) == len(args): args = res return aResult return wrappingMethod class CLI: "The Main thread and heart of the IMCom CLI interface." if METACLASSES: __metaclass__ = WrapperMetaclass('handle', methodWrapper) def __init__(self, debugging, profileName): #Thread.__init__(self) self.PRE = 0 # constant for the handle* mixins self.POST = 1 # constant for the handle* mixins self.callbacks = {} # keys are string names of methods, values are callable objects. self.importedModules = {} # keys are strings of module names, values are their imported contents. self.VERSION = VERSION self.threadHash = {} self.prompt = "IMCom> " self.lastMessaged = None self.lastReceived = None self.lastToDict = {} self.lastFromDict = {} self.showPresenceUpdates = 1 self.ringBell = 1 self.confRingBell = 1 self.currentStatus = "online" self.currentStatusType = "auto" self.currentStatusReason = "" self.debug = debugging self.debugdetails = { "autostatus" : 0, } self.mode = 0 self.MULTILINE = 1 self.outputQueue = [] self.gettingCommand = 0 self.pendingCommand = 0 self.userQueue = [] self.commandQueue = [] self.socketlisteners = [] self.socketserver = '' self.autostatus = None self.colorscheme = {} self.prefs = Preferences() if profileName == "": self.profile = self.prefs.getDefaultProfile() else: if self.prefs.getProfile(profileName) != None: self.profile = self.prefs.getProfile(profileName) else: print "The profile '"+profileName+"' doesn't exist." print "These are the profiles you have: " for key in self.prefs.profiles.keys(): print key print sys.exit(-1) self.imcom = IMCom(self) self.registerCallbacks() self.loghandler = LogHandler( self, self.profile ) if(READLINE): readline.parse_and_bind("tab: complete") readline.parse_and_bind("set bell-style none") readline.set_completer_delims(" ") readline.set_completer(tabCompleter) def registerCallbacks(self): self.imcom.cbHandleConferenceMessage = self.handleConferenceMessage self.imcom.cbHandleDisconnected = self.handleDisconnected self.imcom.cbHandleAdminWho = self.handleAdminWho self.imcom.cbHandlePresenceUpdate = self.handlePresenceUpdate self.imcom.cbHandlePresenceError = self.handlePresenceError self.imcom.cbHandleMessageReceive = self.handleMessageReceive self.imcom.cbHandleMessageError = self.handleMessageError self.imcom.cbHandleIQError = self.handleIQError self.imcom.cbHandleInfoError = self.handleInfoError self.imcom.cbHandleFileReceive = self.handleFileReceive self.imcom.cbHandleFileReceived = self.handleFileReceived self.imcom.cbHandleFileErrorReceived = self.handleFileErrorReceived self.imcom.cbHandleAgentList = self.handleAgentList self.imcom.cbHandleAgentRegister = self.handleAgentRegister self.imcom.cbHandleAgentRegistered = self.handleAgentRegistered self.imcom.cbHandleSubscribe = self.handleSubscribe self.imcom.cbHandleSubscribed = self.handleSubscribed self.imcom.cbHandleUnsubscribed = self.handleUnsubscribed self.imcom.cbHandleUnsubscribe = self.handleUnsubscribe self.imcom.cbHandleRosterUpdateCheck = self.handleRosterUpdateCheck self.imcom.cbHandleRosterUpdate = self.handleRosterUpdate self.imcom.cbHandleVCardSubmit = self.handleVCardSubmit self.imcom.cbHandleVCard = self.handleVCard self.imcom.cbHandleNoVCard = self.handleNoVCard self.imcom.cbHandleLogin = self.login self.imcom.cbHandleGrabRoster = self.grabRoster self.imcom.cbHandleAgentUnRegistered = self.handleAgentUnRegistered self.imcom.cbHandleNegotiationRequest = self.handleNegotiationRequest self.imcom.cbHandleNegotiationResult = self.handleNegotiationResult self.imcom.cbHandleVersionResponse = self.handleVersionResponse self.imcom.cbHandleChangePassword = self.handleChangePassword self.imcom.cbHandleConferenceMessage = self.handleConferenceMessage self.imcom.cbHandleConferencePresence = self.handleConferencePresence self.imcom.cbHandleConferenceCreated = self.handleConferenceCreated self.imcom.cbHandleConferenceNicknameChange = self.handleConferenceNicknameChange self.imcom.cbHandleConferenceNicknameChangeSuccess = self.handleConferenceNicknameChangeSuccess self.imcom.cbHandleConferenceInvite = self.handleConferenceInvite self.imcom.cbHandleConferenceSubject = self.handleConferenceSubject self.imcom.cbHandleConferenceKicked = self.handleConferenceKicked self.imcom.cbHandleConferenceUserKicked = self.handleConferenceUserKicked self.imcom.cbHandleConferenceBanned = self.handleConferenceBanned self.imcom.cbHandleConferenceUserBanned = self.handleConferenceUserBanned self.imcom.cbHandleConferenceDestroyed = self.handleConferenceDestroyed self.imcom.cbHandleConferenceConfig = self.handleConferenceConfig self.imcom.cbHandleConferenceConfigSet = self.handleConferenceConfigSet self.imcom.cbHandleNickCollision = self.handleNickCollision self.imcom.cbHandleNickHasSlash = self.handleNickHasSlash self.imcom.cbHandleStreamError = self.handleStreamError self.imcom.cbHandleStreamClose = self.handleStreamClose # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # ------------------------------------------------------------------------- # Functions for module support and mixins # ------------------------------------------------------------------------- # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def registerCallback(self, name, preOrPost, func): # check preOrPost to validate it exists in the appropriate range # check function to make sure its a valid, existing function on CLI # check to make sure callback is not none # check to see if there is an enter for function in our hash # if there isn't add a default one of [[][]] # if there is, pull out preOrPost. # append callback to it. if not METACLASSES: return -1 if not preOrPost in [0, 1]: print "registerCallback, cannot register your callback\n ", "preOrPost passed in (",preOrPost, ") isn't a valid, not in list: ", [0,1] return -1 if not callable(func): print "registerCallback, cannot register your callback\n ", "the function you gave me isn't callable." return -1 if not name in self.methodNames: print "registerCallback, cannot register your callback\n ", name, "isn't a valid method name in list: ", self.methodNames return -1 if not self.callbacks.has_key(name) or self.callbacks[name] == None: self.callbacks[name] = [[], []] self.callbacks[name][preOrPost].append(func) return 0 def appendCallback(self, name, preOrPost, func): return self.registerCallback(name, preOrPost, func) def unRegisterCallback(self, name, preOrPost, func): # check preOrPost to validate it exists in the appropriate range # check function to make sure its a valid, existing function on CLI # check to make sure callback is not none # check to see if there is an enter for function in our hash # if there isn't just return # if there is, pull out preOrPost. # remove callback from it. if not METACLASSES: return -1 if not preOrPost in [0, 1] or not name in self.methodNames: print name, "isn't a valid method name in list: ", self.methodNames return -1 if(self.callbacks.has_key(name) and self.callbacks[name] != None): try: self.callbacks[name][preOrPost].remove(func) except: return -1 return 0 def removeCallback(self, function, preOrPost, callback): return self.registerCallback(function, preOrPost, callback) def registerCommand(self, commandText, commandName, commandHelp, commandFunction): if commandText == None or commandName == None or commandHelp == None or not callable(commandFunction): return -1 if self.prefs.checkCommandCollision(commandName, commandText, self.profile.moduleCommands) or self.profile.sessioncommands.has_key(commandName): self.output("Warning, a naming collision has occured; not allowing module to register command: " + commandName) return -1 self.profile.moduleCommands[commandName] = [commandText.lower(), commandFunction] self.profile.sessioncommands[commandName] = commandText.lower() self.prefs.commands.registerModuleCommandHelp(commandName, commandHelp) return 0 def unRegisterCommand(self, commandName): try: del self.profile.moduleCommands[commandName] self.prefs.commands.unRegisterModuleCommandHelp(commandName) except: cli.output("Problems unregistering command") def reloadModule(self, module): if not METACLASSES: return -1 if not self.importedModules.has_key(module): return self.loadModule(module) result = self.unloadModule(module) theobj = getattr(self.importedModules[module], module) reload(theobj) return self.loadModule(module) def loadModule(self, module): # initialize the module # hand it it's config # call its setup procedure so it can register callbacks if not METACLASSES: return -1 if module in self.profile.loadedModules: return -1 if not self.importedModules.has_key(module): try: self.importedModules[module] = __import__("usermodules."+module) if(cli.debug): print "loaded from user" except ImportError: self.importedModules[module] = __import__("modules."+module) if(cli.debug): print "loaded from dist" moduleInstance = self.importedModules[module] XMLDOMNode = self.profile.getModuleConfig(module) modobj = getattr(getattr(moduleInstance, module), module)(XMLDOMNode) #eval("moduleInstance." + module + "." + module + "(XMLDOMNode)") modobj.printShortDescription() modobj.registerCallbacks(self) self.profile.modules[module] = modobj self.profile.loadedModules.append(modobj) return modobj def unloadModule(self, aMod): if not METACLASSES: return -1 if(self == None or not self.profile.modules.has_key(aMod)): return -1 aModObj = self.profile.modules[aMod] if aModObj == None: return -1 retval = aModObj.unRegisterCallbacks(self) try: self.profile.loadedModules.remove(aModObj) self.profile.modules[aMod] = None except: pass return 0 def initializeAllModules(self): if not METACLASSES or len(self.profile.loadedModules) > 0: return -1 for aMod in self.profile.modules.keys(): aModObj = self.loadModule(aMod) def configureModule(self, aMod): if not METACLASSES: return -1 if not self.profile.modules.has_key(aMod): return -1 aModObj = self.profile.modules[aMod] if aModObj == None: return -1 self.pendingCommand = 1 self.gettingCommand = 1 self.mode = self.MULTILINE aModObj.configureModuleCLI(self) self.gettingCommand = 0 self.pendingCommand = 0 self.mode = 0 self.dumpQueue() # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # ------------------------------------------------------------------------- # Functions for the login procedure # ------------------------------------------------------------------------- # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def grabRoster(self): """This function is called by the IMCom library when the roster has been downloaded. Because the presence events for people can come before the roster is downloaded this function needs to print out people for whom we've already gotten presence updates from. This is because the presence code doesn't show us presence information for anyone who is not on our roster.""" self.output("Roster has been downloaded") if(self.readyToRoll): self.imcom.sendOnline() self.readyToRoll = 1 keys = self.imcom.jidhash.keys() for item in keys: if(self.imcom.preshash.has_key(item)): available, status, show = self.imcom.preshash[item] if(not available): continue if(self.showPresenceUpdates): if( self.imcom.gjidhash.has_key(item) and (operator.contains(self.imcom.gjidhash[item], "lurker") or operator.contains(self.imcom.gjidhash[item], "ignore"))): return a,show,status = self.imcom.preshash[item] nick = self.getNick(item) ttime = self.getTime() ddate = self.getDate() self.output(self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] + " changed status to " + self.colorscheme["statuscolor"] + show + self.colorscheme["defaultcolor"] + " (" + self.colorscheme["desccolor"] + status + self.colorscheme["defaultcolor"] + ") at " + self.colorscheme["timecolor"] + ttime + self.colorscheme["defaultcolor"]) else: self.imcom.preshash[item] = (0, "unavailable", "offline") def login(self, successful): """This function is called by the IMCom library. It lets us know whether the login was successful or not.""" if(successful): self.output(self.colorscheme["usercolor"] + "Logged on" + self.colorscheme["defaultcolor"]) else: self.output(self.colorscheme["errorcolor"] + "Login FAILED!" + self.colorscheme["defaultcolor"]) def applyProfileWrapper(self): result = (-1, "No Error") iter = 0 for iter in range(5): result = cli.applyProfile() if result[0] == 0: return result if result[0] == 1: print result[1] sys.exit(-1) if result[0] == 3: print "Check your configuration file with regards to the current profile." sys.exit(-1) print result[1] print "Sleeping for 5 seconds." time.sleep(5) print "Giving up." return result def applyProfile(self): """This function actually begins the login process by selecting a profile and calling the IMCom library's changeProfile command. If no profile is available we allow the user to create one. This does not let the user create an account, only lets them to create a profile for an account pre-existing.""" if(self.profile!=None): p = self.profile useSSL = 1 if(p.switches['ssl'][0] == "false" or p.switches['ssl'][0] == "no" or p.switches['ssl'][0] == "off" or p.switches['ssl'][0] == 0): useSSL = 0 clearpass = 0 if(p.switches['clearpass'][0] == "true" or p.switches['clearpass'][0] == "yes" or p.switches['clearpass'][0] == "on" or p.switches['clearpass'][0] == 1): clearpass = 1 self.readyToRoll = 0 self.imcom.DTCPPORT = p.DTCPPort self.initializeAllModules() result = self.imcom.changeProfile(p.server, p.port, p.user, p.password, p.resource, useSSL, clearpass, p.priority, p.encoding) if result[0] != 0: return result self.loghandler.initLogHandler(p) self.autostatus = AutoStatus( self, self.profile ) self.autostatus.start() self.loghandler.setProfile( self.profile ) self.autostatus.setProfile( self.profile ) if(self.readyToRoll): self.imcom.sendOnline() self.readyToRoll = 1 return result else: # I should create a new profile here. print("No profiles available or default profile not set.") self.createNewProfile() self.profile = self.prefs.getDefaultProfile() return self.applyProfile() def applyPrefs(self, debugging): """This function sets all the preference switches.""" if(self.profile == None): return p = self.profile if(p.switches['ringbell'][0] == "true"): self.ringBell = 1 else: self.ringBell = 0 if(p.switches['confringbell'][0] == "true"): self.confRingBell = 1 else: self.confRingBell = 0 if( p.switches['colors'][0] == "true"): self.setColors() else: self.setNoColors() if( debugging != 0 or not p.switches['debug'][0] == "false" ): self.debug = 1 self.imcom.setDebug(1) else: self.debug = 0 self.imcom.setDebug(0) if( p.switches['nickprompt'][0] == "false"): self.useNickAsPrompt = 0 else: self.useNickAsPrompt = 1 if( p.switches['allowinterrupt'][0] == "false" ): self.allowInterrupt = 0 else: self.allowInterrupt = 1 if( p.switches['statusshow'][0] == "false" or p.switches['statusshow'][0] == "no"): self.showPresenceUpdates = 0 else: self.showPresenceUpdates = 1 def createNewProfile(self): """This function creates a new profile and overwrites the preferences file ~/.imcom/imcomrc""" print("You don't seem to have a profile, lets make a new one") name = raw_input("Enter a profile name > ") server = raw_input("Enter the server name > ") useSSL = raw_input("Do you want to use SSL? (yes) > ") clearpass = raw_input("Do you want your password transmitted as clear text ? (no) > ") if clearpass == None or len(clearpass) == 0 or clearpass =="no" or clearpass == "n": clearpass = 0 else: clearpass = 1 defaultPort = "5222" if useSSL == None or len(useSSL) == 0 or useSSL == "yes" or useSSL == "y": defaultPort = "5223" useSSL = 1 else: useSSL = 0 port = raw_input("Enter the port (" + defaultPort + ") > ") if(port == None or len(port) == 0): port = defaultPort user = raw_input("Enter your login > " ) password = getpass.getpass("Enter your password > ") resource = raw_input("Enter the resource (imcom) > ") if(resource == None or len(resource) == 0): resource = "imcom" encoding = raw_input("Enter the encoding you want to use (iso-8859-1) > ") if(encoding == None or len(encoding) == 0): encoding = "iso-8859-1" self.prefs.createInitialProfile(name,server,useSSL, clearpass, port, user,password,resource, encoding) # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # ------------------------------------------------------------------------- # The functions which begin with handle are callbacks from the # IMCom library # ------------------------------------------------------------------------- # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def handleStreamClose(self): self.output("The stream closed on us?") self.imcom = None sys.exit(-1) def handleStreamError(self, text): self.output(self.colorscheme["errorcolor"] + "There was a stream error: " + text + self.colorscheme["defaultcolor"]) def handleQuit(self): """This function is called by the quit command on a clean quit. Its only purpose is for modules to be able to do things on quit.""" def handleDisconnected(self): """This is called by the IMCom library when the server has disconnected us unexpectantly. In theory it should go into EVAL mode essentially dumped a developer onto a Python console with the state of IMCom preserved. This however, does not work well yet.""" self.output(self.colorscheme["errorcolor"] + "Server Disconnected us at " + self.colorscheme["timecolor"] + self.getTime() + self.colorscheme["defaultcolor"]) if(self.debug): self.output(self.colorscheme["errorcolor"] + "Going into EVAL mode, EOF (Control-d) to quit." + self.colorscheme["defaultcolor"]) line = "blah" while line: try: line = raw_input("> ") try: pp.pprint(eval(line)) except: print self.colorscheme["errorcolor"] + "That didn't eval well" + self.colorscheme["defaultcolor"] except EOFError: sys.exit(-1) except KeyboardInterrupt: sys.exit(-1) sys.exit(-1) self.output("Sleeping for 5 seconds before reconnecting.") time.sleep(5) self.output("Attempting to reconnect now.") self.imcom = None self.imcom = IMCom(self) self.registerCallbacks() result = self.applyProfileWrapper() if result[0] != 0: sys.exit(-1) if(self.currentStatus == "chat"): self.imcom.sendChat() elif(self.currentStatus == "away"): self.imcom.sendAway(self.currentStatusReason) elif(self.currentStatus == "xa"): self.imcom.sendXA(self.currentStatusReason) elif(self.currentStatus == "dnd"): self.imcom.sendDND(self.currentStatusReason) def handleAdminWho(self, who, show, status, available, resource): """This function is called by the IMCom library when there has been a request for the list of users on the server. You must be admin for this function to work.""" s = self.colorscheme["usercolor"] + who + "/" + resource + self.colorscheme["defaultcolor"] + " is " + self.colorscheme["statuscolor"] + show + self.colorscheme["defaultcolor"] + " as " + self.colorscheme["desccolor"] + \ status + self.colorscheme["defaultcolor"] self.output(s) def handlePresenceUpdate(self, who, show, status, available, resource, duplicate): """This function is called by the IMCom library when there has been a change in someone's precense. The user must be subscribed to the presence.""" #if(self.debug): # logDebug("Updating presence of " + who + " to " + show + # " as " + status) # don't print the status of anyone not in our jidlist and not # a transport #if( (not self.imcom.jidhash.has_key(who) or # not self.imcom.gjidhash.has_key(who) ) and # ( string.find( who, "@" ) != -1 ) ): # if(self.debug): # logDebug("jidhash doesn't have a " + who) # return nick = self.getNick(who) # these handle error conditions in transports. if( ( string.find( who, "@" ) == -1 ) and show and show == "offline" ): s = self.colorscheme["errorcolor"] + "ERROR: " + self.colorscheme["defaultcolor"] + \ nick + " is offline" if(status): s = s + " : " + status self.output(s) return if( ( string.find( who, "@" ) == -1 ) and show and ( string.find( show, " " ) != -1 ) ): s = self.colorscheme["errorcolor"] + "Notice: " + self.colorscheme["defaultcolor"] + \ nick + ": " + show self.output(s) return # this is in response to a bug in trillian (icq program) # yes, the fix should be server-side but you know.... if( ( self.profile.switches['igndupstatus'][0] == "true" ) and duplicate ): return # commented out for testing/reimplementation of how IMCom # deals with transports. #if( string.find( who, "@" ) == -1 and not self.imcom.agenthash.has_key(who)): # return # don't display the presence of people in the lurker group. if( self.imcom.gjidhash.has_key(who) and (operator.contains(self.imcom.gjidhash[who],"lurker") or operator.contains(self.imcom.gjidhash[who],"ignore"))): if(self.debug): logDebug("Skipping lurker: " + who) return # only display status updates if we are set to display status updates. if(self.showPresenceUpdates): ttime = self.getTime() ddate = self.getDate() if(available): s = self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] # if they have a resource, and they're not a transport # then add the resource string. if(resource != None and resource != "" and not self.imcom.agenthash.has_key(who)): s = s + "/" + self.colorscheme["keycolor"] + resource + self.colorscheme["defaultcolor"] # append the rest of the information s = s + " changed status to " + \ self.colorscheme["statuscolor"] + show + self.colorscheme["defaultcolor"] + " (" + \ self.colorscheme["desccolor"] + status + self.colorscheme["defaultcolor"] + ") at " + \ self.colorscheme["timecolor"] + ttime + self.colorscheme["defaultcolor"] self.output(s) else: s= self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] # if they have a resource, and they're not a transport # then add the resource string. if(resource != None and resource != "" and not self.imcom.agenthash.has_key(who)): s = s + "/" + self.colorscheme["keycolor"] + resource + self.colorscheme["defaultcolor"] # append the rest of the information s = s + " is unavailable : " + \ self.colorscheme["desccolor"] + status + self.colorscheme["defaultcolor"] + \ " at " + self.colorscheme["timecolor"] + ttime + self.colorscheme["defaultcolor"] self.output(s) def handlePresenceError(self, ffrom, code, text): towrite = self.colorscheme["errorcolor"] + "ERROR: " + self.colorscheme["usercolor"] + ffrom + self.colorscheme["defaultcolor"] + " says " + text + "(" + code + ")." if self.imcom.conferences.has_key(ffrom): del self.imcom.confnick[self.imcom.conferences[ffrom][0]] del self.imcom.conferences[ffrom] if (not self.imcom.subscriptions.has_key(ffrom) or self.imcom.subscriptions[ffrom] == 'from' or self.imcom.subscriptions[ffrom] == 'none'): return self.output(towrite) return def handleUserPresenceChange(self, oldStatus, oldReason, newStatus, newReason): # this function is here simply to allow modules to know when the user's presence has changed. pass def handleConferenceMessage(self, conf, nick, body, delay): "This function is called from the IMCom library when a message has been received from a conference" if(self.profile.switches['confsuppress'][0] == "false"): towrite = self.colorscheme["keycolor"] + conf + self.colorscheme["defaultcolor"] + "/" + self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] ttime = self.getTime() ddate = self.getDate() towrite = towrite + " - Conference Message - " # append the timestamp and the rest of the information towrite = towrite + self.colorscheme["timecolor"] + ddate + " | " + ttime + self.colorscheme["defaultcolor"] towrite = towrite + "\n" + self.colorscheme["messagebodycolor"] + body + self.colorscheme["defaultcolor"] else: towrite = self.colorscheme["keycolor"] + conf + self.colorscheme["defaultcolor"] + "/" + self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] + " : " towrite = towrite + self.colorscheme["messagebodycolor"] + body + self.colorscheme["defaultcolor"] # ring the terminal bell if configured to if(self.confRingBell): self.printText(chr(7)) self.output(towrite) def handleConferenceCreated(self, conf): towrite = self.colorscheme["usercolor"] + conf + self.colorscheme["defaultcolor"] + " was just created by you. You need to set it up. I am requesting the form." self.output(towrite) self.imcom.sendConferenceConfigRequest(conf) return def handleConferenceConfigSet(self, conf): towrite = self.colorscheme["usercolor"] + conf + self.colorscheme["defaultcolor"] + " configuration was set successfully." self.output(towrite) return def handleConferenceConfig(self, conf, xmlform): towrite = self.colorscheme["messagebodycolor"] + xmlform.instructions + self.colorscheme["defaultcolor"] self.output(towrite) answers = self.getXDataAnswers(xmlform.fields) self.imcom.sendConferenceConfigResults(conf, answers) def handleConferenceNicknameChange(self, conf, oldnick, newnick): towrite = self.colorscheme["keycolor"] + self.imcom.conferences[conf][0] + self.colorscheme["defaultcolor"] + "/" + self.colorscheme["usercolor"] + oldnick + self.colorscheme["defaultcolor"] towrite = towrite + " has changed their nickname to " + self.colorscheme["usercolor"] + newnick + self.colorscheme["defaultcolor"] + "." self.output(towrite) def handleConferenceNicknameChangeSuccess(self, conf, oldnick, newnick): towrite = "You successfully changed your nick name from " + self.colorscheme["usercolor"] + oldnick + self.colorscheme["defaultcolor"] towrite = towrite + " to " + self.colorscheme["usercolor"] + newnick + self.colorscheme["defaultcolor"] + " in conference " towrite = towrite + self.colorscheme["keycolor"] + self.imcom.conferences[conf][0] + self.colorscheme["defaultcolor"] + "." self.output(towrite) def handleConferencePresence(self, conf, nick, show, reason, affiliation, role, jid): "This function is called from the IMCom library when someone in a conference has changed status" if(self.showPresenceUpdates):# and 0): if reason == None: reason = show towrite = self.colorscheme["keycolor"] + self.imcom.conferences[conf][0] + self.colorscheme["defaultcolor"] + "/" + self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] towrite = towrite + " changed status to " + self.colorscheme["statuscolor"] + show + self.colorscheme["defaultcolor"] towrite = towrite + " as " + self.colorscheme["desccolor"] + reason + self.colorscheme["defaultcolor"] if affiliation != None: towrite = towrite + " (" + self.colorscheme["keycolor"] + affiliation + self.colorscheme["defaultcolor"] + ") " if role != None: towrite = towrite + " (" + self.colorscheme["keycolor"] + role + self.colorscheme["defaultcolor"] + ") " ttime = self.getTime() towrite = towrite + " at " + self.colorscheme["timecolor"] + ttime + self.colorscheme["defaultcolor"] self.output(towrite) def handleConferenceInvite(self, conf, ffrom, reason, password): towrite = self.colorscheme["usercolor"] + ffrom + self.colorscheme["defaultcolor"] + " invites you to join " + self.colorscheme["keycolor"] + conf + self.colorscheme["defaultcolor"] + "\n" towrite = towrite + " -- " + reason if password != None: towrite = towrite + "\nThe password is: " + self.colorscheme["keycolor"] + password + self.colorscheme["defaultcolor"] self.output(towrite) def handleConferenceSubject(self, conf, ffrom, subject): towrite = self.colorscheme["keycolor"] + conf + self.colorscheme["defaultcolor"] + "/" + self.colorscheme["usercolor"] + ffrom + self.colorscheme["defaultcolor"] + " set the subject to " towrite = towrite + self.colorscheme["desccolor"] + subject + self.colorscheme["defaultcolor"] self.output(towrite) def handleConferenceKicked(self, conf, reason, jidOfKicker): towrite = self.colorscheme["errorcolor"] + "KICKED: " + self.colorscheme["defaultcolor"] + " from " + self.colorscheme["keycolor"] + conf + self.colorscheme["defaultcolor"] if jidOfKicker != None: towrite = towrite + " by " + self.colorscheme["usercolor"] + jidOfKicker + self.colorscheme["defaultcolor"] if reason != None: towrite = towrite + " : " + reason self.output(towrite) def handleConferenceUserKicked(self, conf, person, reason, jidOfKicker): towrite = self.colorscheme["keycolor"] + self.imcom.conferences[conf][0] + self.colorscheme["defaultcolor"] + "/" + self.colorscheme["usercolor"] + person + self.colorscheme["defaultcolor"] towrite = towrite + " was kicked" if jidOfKicker != None: towrite = towrite + " by " + self.colorscheme["usercolor"] + jidOfKicker + self.colorscheme["defaultcolor"] if reason != None: towrite = towrite + " for : " + self.colorscheme["desccolor"] + reason + self.colorscheme["defaultcolor"] towrite = towrite + "." self.output(towrite) def handleConferenceBanned(self, conf, reason, jidOfKicker): towrite = self.colorscheme["errorcolor"] + "BANNED: " + self.colorscheme["defaultcolor"] + " from " + self.colorscheme["keycolor"] + conf + self.colorscheme["defaultcolor"] if jidOfKicker != None: towrite = towrite + " by " + self.colorscheme["usercolor"] + jidOfKicker + self.colorscheme["defaultcolor"] if reason != None: towrite = towrite + " : " + reason self.output(towrite) def handleConferenceUserBanned(self, conf, person, reason, jidOfKicker): towrite = self.colorscheme["keycolor"] + self.imcom.conferences[conf][0] + self.colorscheme["defaultcolor"] + "/" + self.colorscheme["usercolor"] + person + self.colorscheme["defaultcolor"] towrite = towrite + " was banned" if jidOfKicker != None: towrite = towrite + " by " + self.colorscheme["usercolor"] + jidOfKicker + self.colorscheme["defaultcolor"] if reason != None: towrite = towrite + " for : " + self.colorscheme["desccolor"] + reason + self.colorscheme["defaultcolor"] towrite = towrite + "." self.output(towrite) def handleConferenceDestroyed(self, conf): towrite = self.colorscheme["keycolor"] + conf + self.colorscheme["defaultcolor"] + " has been " + self.colorscheme["errorcolor"] + "destroyed" + self.colorscheme["defaultcolor"] + "." self.output(towrite) def handleMessageReceive(self, ffrom, body, thread, delay, resource): """This function is called from the IMCom library when a message has been received from a user or transport/service.""" # don't display messages from people who belong to the ignore # group. if( self.imcom.gjidhash.has_key(ffrom) and operator.contains(self.imcom.gjidhash[ffrom],"ignore")): if(self.debug): logDebug("Skipping message from ignored user: " + ffrom) return # append the jid to the top of the stack of last users to # event us. self.appendUserQueue(ffrom) # try and get their nickname. otherwise their nickname is # their jid. try: nick = self.imcom.jidhash[ffrom] except: nick = ffrom ttime = None ddate = None towrite = None towrite = self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] if(resource != ""): towrite = towrite + "/" + self.colorscheme["keycolor"] + resource + self.colorscheme["defaultcolor"] # if the delay timestamp exists, format it properly, otherwise # the current time. if(delay != None): # parse the delay, attach the timestamp in good format. # tuple is (year, month, day, hour, minutes, seconds, # daysintotheyear, dst) mytup = (int(delay[:4]),int(delay[4:6]),int(delay[6:8]), int(delay[9:11]),int(delay[12:14]),int(delay[15:17]),0,0,0) thet = time.localtime( time.mktime(mytup) - time.timezone) ttime = time.strftime('%H:%M:%S',thet) ddate = time.strftime('%m/%d/%Y',thet) towrite = towrite + " - " + self.colorscheme["errorcolor"] + \ "DELAYED " + self.colorscheme["defaultcolor"] + "Message - " else: ttime = self.getTime() ddate = self.getDate() towrite = towrite + " - Message - " # append the timestamp and the rest of the information towrite = towrite + self.colorscheme["timecolor"] + ttime + self.colorscheme["defaultcolor"] if(delay != None): towrite = towrite + " on " + self.colorscheme["timecolor"] + ddate towrite = towrite + "\n" + self.colorscheme["messagebodycolor"] + body + self.colorscheme["defaultcolor"] # ring the terminal bell if configured to if(self.ringBell): if(self.profile.audiocmd != None): os.spawnv(os.P_NOWAIT,self.profile.audiocmd,(self.profile.audiocmd,self.profile.audioargs,)) self.printText(chr(7)) self.lastReceived = ffrom self.output(towrite) # threadhash is used so that if someone is seeing this as a # particular conversation we continue the conversation. (Silly # GUI apps) self.threadHash[ffrom] = thread self.logMessage(ffrom,ffrom,ddate,ttime,body) def handleMessageError(self, ffrom, body, code): """This function is called by the IMCom library when there has been some sort of error related to sending or receiving a message. CLI just prints out the information for the user.""" if ffrom == None: ffrom = "from-value-not-set" if body == None: body = "" if code == None: code = "0" if( ( code == "0" or code == 0 ) and body != "" ): towrite = self.colorscheme["errorcolor"] + "ERROR: " + self.colorscheme["defaultcolor"] + body else: towrite = self.colorscheme["errorcolor"] + "ERROR: " + self.colorscheme["defaultcolor"] + \ "sending message to"\ " " + self.colorscheme["usercolor"] + ffrom + self.colorscheme["defaultcolor"] + " :"\ " " + self.colorscheme["errorcolor"] + errorCodes[code] + self.colorscheme["defaultcolor"] self.output(towrite) def handleIQError(self, ffrom, code, body): """This function is called by the IMCom library when there has been some sort of error related to information request or submission. CLI just prints out the information for the user.""" towrite = self.colorscheme["errorcolor"] + "ERROR: " + self.colorscheme["defaultcolor"] + "InfoQuery event"\ " " + self.colorscheme["usercolor"] + ffrom + self.colorscheme["defaultcolor"] + " :"\ " " + self.colorscheme["errorcolor"] + errorCodes[code] + self.colorscheme["defaultcolor"] if body != None: towrite = towrite + " : " + self.colorscheme["errorcolor"] + body + self.colorscheme["defaultcolor"] self.output(towrite) def handleChangePassword(self, success, newPassword, errorCode, errorText): towrite = None if success == 1: towrite = "Your password has been successfully change." self.profile.password = newPassword self.prefs.writePreferences() else: towrite = self.colorscheme["errorcolor"] + "ERROR: " + self.colorscheme["defaultcolor"] + " Your password could not be changed." towrite = towrite + self.colorscheme["errorcolor"] + errorCodes[code] + self.colorscheme["defaultcolor"] + errorText self.output(towrite) return def handleInfoError(self, code, text): """This function is called by the IMCom library when there has been some sort of error related to information request. CLI just prints out the information for the user.""" towrite = self.colorscheme["errorcolor"] + "ERROR: " + self.colorscheme["defaultcolor"] + "getting info"\ " Code: " + self.colorscheme["errorcolor"] + code + self.colorscheme["defaultcolor"] + " "\ " Text: " + self.colorscheme["errorcolor"] + text + self.colorscheme["defaultcolor"] self.output(towrite) def handleFileReceive(self, jid, url): """This function is called by the IMCom library when someone has requested to send us a file.""" self.appendUserQueue(jid) nick = self.getNick(jid) towrite = self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] + " wants to send you"\ " a file at URL:\n" + self.colorscheme["keycolor"] + url + self.colorscheme["defaultcolor"] +\ "\nTo receive the file type: \n" + \ self.prefs.getCommand(self.profile, "getfile") + \ " " + nick self.output(towrite) def handleFileReceived(self, jid, url, id): """This function is called by the IMCom library when we have successfully received the file.""" self.appendUserQueue(jid) nick = self.getNick(jid) file = url[url.rfind('/')+1:] towrite = "Successfully receieved a file from " + self.colorscheme["usercolor"] +\ nick + self.colorscheme["defaultcolor"] + \ "\nThe file is saved in " + self.colorscheme["keycolor"] + "~/.imcom/files/" + \ file + self.colorscheme["defaultcolor"] self.output(towrite) def handleFileErrorReceived(self, jid, url, id, type, text): """This function is called by the IMCom library when there has been some sort of error in file transmission.""" self.appendUserQueue(jid) towrite = self.colorscheme["errorcolor"] + "Error: " + self.colorscheme["defaultcolor"] + \ "An error occured trying to get a file from " + \ self.colorscheme["usercolor"] + jid + self.colorscheme["defaultcolor"] + ".\nThe URL: " + \ self.colorscheme["keycolor"] + url + self.colorscheme["defaultcolor"] + "\n" + \ "Errortype: " + str(type) + "\n" + \ "Errorvalue: " + str(text) self.output(towrite) def handleAgentList(self, theList): """This function is called by the IMCom library when we have received a list of agents from the server. Agents is another word for Transport or Server in Jabber terminology.""" self.output("The following is a list of transports available on" + " your Jabber server.") for i in theList: if(i.name): self.output(self.colorscheme["keycolor"] + i.jid + self.colorscheme["defaultcolor"] + " : " + self.colorscheme["defaultcolor"] + i.name) def handleAgentRegister(self, id, ffrom, instructions, fields): # # this will cause issues if gettingCommand is already set to 1 # however, in that case things get *really* complicated anyway... # and it's not likely to happen unless the user is playing with us # self.output("Please finish whatever command you're currently entering (or just hit enter) to begin registration process.") self.pendingCommand = 1 while(self.gettingCommand == 1): time.sleep(0.01) self.output("\n\nThe following are instructions to complete the "\ "registration process, they may be of use, then "\ "again, don't count on it.\n\n") self.output(self.colorscheme["desccolor"] + instructions + self.colorscheme["defaultcolor"] + "\n\n") self.gettingCommand = 1 params = ffrom for i in fields: params += "<" + i CICommands.interactiveregCommand(self, params) self.dumpQueue() self.pendingCommand = 0 self.gettingCommand = 0 def handleAgentRegistered(self, ffrom): """This function is called by the IMCom library when an agent has been successfully registered.""" self.output("Your registration request to " + ffrom + " was successful. I will authorize the transport now " "for you.") addcommand = self.prefs.getCommand( self.profile, "add" ) self.output( "To add contacts who use the " + self.getNick( ffrom ) + " use the command:\n" + addcommand + " id@" + ffrom + " nick\n" + "for instance, " + addcommand + " airog@" + ffrom + " airog" ) self.imcom.sendSubscribed(ffrom) # + "/registered") is it needed? return def handleAgentUnRegistered(self, ffrom): """This function is called by the IMCom library when an agent has been successfully removed.""" self.output("Your registration to " + ffrom + " was cancelled successfully.") return def handleSubscribe(self, ffrom, ask): """This function is called by the IMCom library when someone is requesting to add us to their roster.""" self.appendUserQueue(ffrom) if(self.debug): logDebug("Handling a subscribe request, from : " + ffrom) ffrom = self.getNick(ffrom) self.output(self.colorscheme["usercolor"] + ffrom + self.colorscheme["defaultcolor"] + " requests permission to subscribe to your presence") def handleSubscribed(self, ffrom): """This function is called by the IMCom library when someone authorized you to add them to your roster.""" self.appendUserQueue(ffrom) nick = self.getNick(ffrom) self.output(self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] + " authorized your subscription request") def handleUnsubscribed(self, ffrom, success): """This function is called by the IMCom library when the unsubscribe process is complete.""" self.appendUserQueue(ffrom) if(success): nick = self.getNick(ffrom) if self.imcom.asks[ffrom] == 'subscribe': self.output(self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] + " refused to grant authorization for you to subscribe to their presence. ") return self.output("Unsubscribed from " + self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] + "'s presence") else: self.output("Yowza! Unsubscription process failed!") def handleUnsubscribe(self, ffrom): """This function is called by the IMCom library when someone is requesting to remove us from their roster.""" self.output(self.colorscheme["usercolor"] + ffrom + self.colorscheme["defaultcolor"] + " is unsubscribing from your presence.") # Reports whether a change to the roster was successful or not def handleRosterUpdateCheck(self, successful, message): """This function is called by the IMCom library after a roster change has been made, telling us whether or not it was successful""" if(successful): self.output("Roster update successful: " + message) else: self.output("Roster update " + self.colorscheme["errorcolor"] + " Error: " + message + self.colorscheme["defaultcolor"]) # Called when there has been a change to the roster def handleRosterUpdate(self, jid, name, subs, ask, success): """This function is called by the IMCom library when another resource has made a change to our roster. """ # update our roster lists based upon information in jid, name if(subs == "remove"): if(success): self.output("Removed " + self.colorscheme["usercolor"] + jid + self.colorscheme["defaultcolor"] + " from our lists") return else: self.output("Removal process " + self.colorscheme["errorcolor"] + "failed!" + self.colorscheme["defaultcolor"]) return def handleNickCollision(self, nickname, newjid, oldjid): if nickname == None: nickname = "" if newjid == None: newjid = "" if oldjid == None: oldjid = "" self.output(self.colorscheme["errorcolor"] + "WARNING:" + self.colorscheme["defaultcolor"] + " A nickname collision occured.\n" + "Nickname: " + self.colorscheme["keycolor"] + nickname + self.colorscheme["defaultcolor"] + " is now linked to JID: " + self.colorscheme["keycolor"] + newjid + self.colorscheme["defaultcolor"] + " instead of " + self.colorscheme["keycolor"] + oldjid + self.colorscheme["defaultcolor"]) def handleNickHasSlash(self, nickname, newnick, jid): self.output(self.colorscheme["errorcolor"] + "WARNING:" + self.colorscheme["defaultcolor"] + " The nickname " + self.colorscheme["usercolor"] + nickname + self.colorscheme["defaultcolor"] + " contains a slash. IMCom doesn't allow for this. For the duration of this session the user's nickname will be " + self.colorscheme["usercolor"] + newnick + self.colorscheme["defaultcolor"] + ".") def handleVCardSubmit(self, success): if success: self.output("Successfully submitted your vcard") else: self.output("Your VCard submission was unsuccessful.") def handleVCard(self, ffrom, fn, given, family, nickname, email): self.appendUserQueue(ffrom) if(ffrom == None): return self.output("Information on " + self.colorscheme["usercolor"] + ffrom + self.colorscheme["defaultcolor"] + ": ") if(fn != None): self.output(self.colorscheme["keycolor"] + "Fullname: " + self.colorscheme["desccolor"] + fn + self.colorscheme["defaultcolor"]) if(given != None): self.output(self.colorscheme["keycolor"] + "Given: " + self.colorscheme["desccolor"] + given + self.colorscheme["defaultcolor"]) if(family != None): self.output(self.colorscheme["keycolor"] + "Family: " + self.colorscheme["desccolor"] + family + self.colorscheme["defaultcolor"]) if(nickname != None): self.output(self.colorscheme["keycolor"] + "Nickname: " + self.colorscheme["desccolor"] + nickname + self.colorscheme["defaultcolor"]) if(email != None): self.output(self.colorscheme["keycolor"] + "Email: " + self.colorscheme["desccolor"] + email + self.colorscheme["defaultcolor"]) def handleNoVCard(self, ffrom): self.appendUserQueue(ffrom) if(ffrom == None): return self.output("There is no information (no vcard filed) for " + self.colorscheme["usercolor"] + ffrom + self.colorscheme["defaultcolor"] + ". ") return def handleNegotiationRequest(self, ffrom, type, options, id): nick = self.getNick(ffrom) text = self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] + " is requesting (id: " + self.colorscheme["keycolor"] + id + self.colorscheme["defaultcolor"] + ") " text = text + "which of the following works for you for " + self.colorscheme["desccolor"] + type + self.colorscheme["defaultcolor"] + ".\n" for option in options: text = text + option + "\n" self.output(text) def handleNegotiationResult(self, ffrom, type, options, id): nick = self.getNick(ffrom) text = self.colorscheme["usercolor"] + nick + self.colorscheme["defaultcolor"] + " has specified (id: " + self.colorscheme["keycolor"] + id + self.colorscheme["defaultcolor"] + ") " text = text + "that " + self.colorscheme["keycolor"] + options[0] + self.colorscheme["defaultcolor"] + " works for them for " + self.colorscheme["desccolor"] + type + self.colorscheme["defaultcolor"] self.output(text) def handleVersionResponse(self, ffrom, fromResource, name, version, os): nick = self.getNick(ffrom) text = self.colorscheme["usercolor"] + nick + "/" + fromResource + self.colorscheme["defaultcolor"] + " is using client: " + self.colorscheme["desccolor"] + name + self.colorscheme["defaultcolor"] if version != None: text = text + " version: " + self.colorscheme["keycolor"] + version + self.colorscheme["defaultcolor"] if os != None: text = text + " on os: " + self.colorscheme["keycolor"] + os + self.colorscheme["defaultcolor"] self.output(text) # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # ------------------------------------------------------------------------- # Utility Functions # ------------------------------------------------------------------------- # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def addSocketWrapper(self, sw): self.socketlisteners.append(sw) self.output("A client socket started.") def removeSocketWrapper(self, sw): self.socketlisteners.remove(sw) self.output("A client socket disconnected.") def getColor(self, fg, bg): if bg != "": retval = fg[:-1] + ";" + bg[4:] return retval return fg def overrideColor(self, colorname, newfgcolor, newbgcolor=""): if not colorname in self.colorscheme.keys(): return None fcolor = self.getColor(newfgcolor, newbgcolor) ocolor = self.colorscheme[colorname] self.colorscheme[colorname] = fcolor return ocolor def setColors(self): g = self.profile.sessioncolors self.colorscheme["backgroundcolor"] = g["background"] self.colorscheme["usercolor"] = self.getColor(g["user"], self.colorscheme["backgroundcolor"]) self.colorscheme["statuscolor"] = self.getColor(g["status"], self.colorscheme["backgroundcolor"]) self.colorscheme["errorcolor"] = self.getColor(g["error"], self.colorscheme["backgroundcolor"]) self.colorscheme["messagebodycolor"] = self.getColor(g["messagebody"], self.colorscheme["backgroundcolor"]) self.colorscheme["timecolor"] = self.getColor(g["time"], self.colorscheme["backgroundcolor"]) self.colorscheme["desccolor"] = self.getColor(g["desc"], self.colorscheme["backgroundcolor"]) self.colorscheme["sepcolor"] = self.getColor(g["sep"], self.colorscheme["backgroundcolor"]) self.colorscheme["defaultcolor"] = self.getColor(g["default"], self.colorscheme["backgroundcolor"]) self.colorscheme["keycolor"] = self.getColor(g["key"], self.colorscheme["backgroundcolor"]) self.profile.switches['colors'][0] = "true" CICommands.setCIColors(self.prefs, self.profile) def setNoColors(self): self.colorscheme["usercolor"] = "" self.colorscheme["statuscolor"] = "" self.colorscheme["errorcolor"] = "" self.colorscheme["messagebodycolor"] = "" self.colorscheme["timecolor"] = "" self.colorscheme["desccolor"] = "" self.colorscheme["sepcolor"] = "" self.colorscheme["defaultcolor"] = "" self.colorscheme["keycolor"] = "" self.colorscheme["backgroundcolor"] = "" self.profile.switches['colors'][0] = "false" CICommands.setCIColors(self.prefs, self.profile) def beginLine(self): if(self.profile.switches['clearline'][0] == "true"): if TERMWIDTH and self.gettingCommand: myStrlen = len(self.prompt) if(READLINE == 1): myStrlen = myStrlen + len(readline.get_line_buffer()) myHeight = int(math.floor(myStrlen / getTerminalWidth())) myWidth = myStrlen % getTerminalWidth() for n in range(myHeight+1): output=chr(27)+"[%dD"%getTerminalWidth() + self.colorscheme["backgroundcolor"] + chr(27)+"[K" + self.colorscheme["backgroundcolor"] self.printText(output) if n != myHeight: output=chr(27)+"[1A" self.printText(output) else: output=chr(27)+"[%dD"%getTerminalWidth() + self.colorscheme["backgroundcolor"] self.printText(output) def clearCommand(self): self.beginLine() if(self.profile.switches['clearline'][0] == "true"): output=chr(27)+"[K" + self.colorscheme["backgroundcolor"]# + chr(27)+"[%dD"%getTerminalWidth() self.printText(output) else: self.printText("\n") def clearScreen(self): if(self.profile.switches['colors'][0] == "true"): output = self.colorscheme["defaultcolor"] + chr(27)+"[J" + self.colorscheme["defaultcolor"] sys.stdout.write(output) sys.stdout.flush() def statusNag(self): if( self.currentStatus != "online" ): self.output( "Your current status is " + self.colorscheme["statuscolor"] + self.currentStatus + self.colorscheme["defaultcolor"] + ": " + self.colorscheme["desccolor"] + self.currentStatusReason + self.colorscheme["defaultcolor"] ) def printText(self, st): try: sys.stdout.write(st.encode(self.profile.encoding, 'replace')) sys.stdout.flush() except: traceback.print_exc() print "An exception occuring trying to print to terminal." print "This is most likely due to an extended ascii character." print "You may have missed a message or query response." def dumpQueue(self): for item in self.outputQueue: self.clearCommand() self.printText(item+"\n") self.outputQueue = [] def output(self, st): st = self.colorscheme["defaultcolor"] + st for key in self.socketlisteners: key.sendData(st+"\n.\n") if(( self.mode == self.MULTILINE) and ( not self.allowInterrupt )): self.outputQueue.append(st) return self.clearCommand() self.printText(st+"\n") if(READLINE == 1 and self.gettingCommand): self.printText(self.prompt + unicode(readline.get_line_buffer(),self.profile.encoding)) elif(self.gettingCommand): self.printText(self.prompt) def checkto(self, nick): if(nick == None): return 0 if(-1 != string.find(nick,"@")): return 1 if self.imcom.nickhash.has_key(nick): return 1 if self.imcom.confnick.has_key(nick): return 1 tmp = string.split(nick,".") if(len(tmp) > 1): return 1 return 0 def getTime(self): return time.strftime('%H:%M:%S',time.localtime(time.time())) def getDate(self): return time.strftime('%m/%d/%Y',time.localtime(time.time())) # begin add by ted def logMultiMessage(self, fnames, sender, ddate, ttime, text): for fname in fnames: self.logMessage(fname, sender, ddate, ttime, text) # end add by ted def logMessage(self, fname, sender, ddate, ttime, text): path = os.environ['HOME']+"/.imcom/"+self.profile.name+"/" if( sender == self.profile.user+"@"+self.profile.server ): self.lastToDict[fname] = text else: self.lastFromDict[sender] = text # strip filename of /'s from resource string.. if(-1 != fname.find("/")): fname = fname[:fname.find("/")] # fix the text by replacing < with < etc. text = self.imcom.normalize(text) # make sure path exists. try: os.makedirs(path[:-1],0700) except: pass try: if (fname != self.getNick(fname)): os.symlink(fname,path+self.getNick(fname)) except: pass try: aFile = path+fname aFile = aFile.encode(self.profile.encoding) if(CODECS): f = codecs.open(aFile,"ab+", self.profile.encoding, 'replace') else: f = open(aFile,"ab+") f.write("") f.write(text) f.write("\n") f.flush() f.close() except: print "There was an exception attempting to log the message" traceback.print_exc() def getJID(self, nick): result = nick resource = None if nick == None or len(nick) == 0: return (None, None) if(nick != None and -1 != string.find(nick,"/")): resource = nick[string.find(nick,'/')+1:] nick = nick[:string.find(nick,'/')] else: resource = None if nick == None or len(nick) == 0: return (None, None) if(nick[0] == "$" and len(nick) == 2): n = int(nick[1]) if(len(self.userQueue)>n): result = self.userQueue[n] if(self.debug): logDebug("$? Result is: " + result) return (result, self.imcom.normalize(resource)) else: result = nick if(self.imcom.nickhash.has_key(nick)): result = self.imcom.nickhash[nick] elif(self.imcom.confnick.has_key(nick)): result = self.imcom.confnick[nick] else: for key in self.imcom.agenthash.keys(): if self.imcom.agenthash[key] == nick: result = key if not self.imcom.preshash.has_key(result): result = result + "/registered" break if(self.imcom.jidhash.has_key(result) and self.imcom.reshash.has_key(result) and resource == None): resource = self.imcom.reshash[result][0] return (result, self.imcom.normalize(resource)) def isAgent(self, jid): return ( self.imcom.agenthash.has_key(jid) or self.imcom.agenthash.has_key(jid[:-11])) def getNick(self, jid): result = jid if jid.find("/") != -1: jid = jid[:jid.find("/")] if( string.find( jid, "@" ) == -1 ): if( self.imcom.agenthash.has_key(jid) ): return self.imcom.agenthash[jid] if(self.imcom.jidhash.has_key(jid) and self.imcom.jidhash[jid] != None): result = self.imcom.jidhash[jid] else: result = jid return result def updateKeyInHash(self, hash, oldkey, newkey): keys = hash.keys() for item in keys: if(item == oldkey): value = hash[item] hash[newkey]=value return def updateHash(self, hash, oldkey, newkey, value): keys = hash.keys() for item in keys: if(item == oldkey): del hash[item] hash[newkey] = value def appendUserQueue(self, ffrom): self.userQueue.insert(0,ffrom) if(len(self.userQueue) > 10): self.userQueue = self.userQueue[:10] return # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # ------------------------------------------------------------------------- # XData Functions # ------------------------------------------------------------------------- # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def createXDataLabel(self, var, label, required, default): myLabel = self.colorscheme["desccolor"] if label != None: myLabel = myLabel + label else: myLabel = myLabel + var if default != None: myLabel = myLabel + self.colorscheme["defaultcolor"] + " [" + self.colorscheme["keycolor"] + str(default) + self.colorscheme["defaultcolor"] + "] : " else: myLabel = myLabel + self.colorscheme["defaultcolor"] + " : " return myLabel def getXDataListSingleAnswer(self, var, label, default, options, required): lstlen = len(options) print "You may answer with a number between 1 and", lstlen myLabel = self.createXDataLabel(var, label, required, None) n = 1 for option in options: print self.colorscheme["keycolor"], n, self.colorscheme["defaultcolor"] + ":" + self.colorscheme["desccolor"], option[0], self.colorscheme["defaultcolor"] n = n + 1 result = None print myLabel result = raw_input( "> " ) if result == '' and not required: return [var, ''] answer = None try: answer = int(result) except: pass while answer == None or answer > lstlen or answer < 1: print "Please answer with a number between 1 and", lstlen print myLabel result = raw_input("> " ) if result == '' and not required: return [var, ''] answer = None try: answer = int(result) except: pass return [var, options[answer-1][1]] def getXDataBooleanAnswer(self, var, label, value, required): print "You may answer with (yes, true, 1, y, t), (no, false, 0, n, f)\nJust hit enter if you don't want to answer at all." myLabel = self.createXDataLabel(var, label, required, value) result = None answer = None print myLabel result = raw_input( "> " ) if value != None and result == '': result = value if result.lower() in ("yes", "true", "1", "y", "t"): answer = 1 if result.lower() in ("no", "false", "0", "n", "f"): answer = 0 if result == '': answer = "" while (required and result == None) or answer == None: if required: print "This is a required field, please enter a valid answer." else: print "Please answer with (yes, true, 1, y, t), (no, false, 0, n, f)\nJust hit enter if you don't want to answer at all." print myLabel result = raw_input( "> " ) if result.lower() in ("yes", "true", "1", "y", "t"): answer = 1 if result.lower() in ("no", "false", "0", "n", "f"): answer = 0 if result == '': answer = "" return [var, str(answer)] def getXDataTextSingleAnswer(self, var, label, value, required, private): myLabel = self.createXDataLabel(var, label, required, value) result = None print myLabel if private: result = getpass.getpass( "> " ) else: result = raw_input( "> " ) if value != None and result == '': result = value while required and result == '': print "This is a required field, please enter it correctly." print myLabel if private: result = getpass.getpass( "> " ) else: result = raw_input( "> " ) return [var, result] def getXDataTextMultiAnswer(self, var, label, value, required): myLabel = self.createXDataLabel(var, label, required, value) result = "" done = None print "Please enter information, finishing with a single period on a line of its own." print myLabel while(not done): tmp = raw_input( "> " ) if tmp == ".": done = 1 continue result = result + "\n" + tmp return [var, result] def getXDataListMultiAnswer(self, var, label, default, options, required): myLabel = self.createXDataLabel(var, label, required, None) result = '' lstlen = len(options) print "Please select as many options as you want 1-"+str(lstlen)+" delimiting by commas only, no spaces." n = 1 for option in options: print self.colorscheme["keycolor"], n, self.colorscheme["defaultcolor"] + ":" + self.colorscheme["desccolor"], option[0], self.colorscheme["defaultcolor"] n = n + 1 print myLabel tmp = raw_input( "> " ) tmps = tmp.split(",") for num in tmp: try: i = int(num) if i < 1 or i > lstlen: continue result = result + "\n" + options[i][1] except: pass return result def getXDataJIDSingleAnswer(self, var, label, value, required): myLabel = self.createXDataLabel(var, label, required, value) result = None gaveGarbage = 0 print "You may either use a fully qualified JID, or the nick name of someone on your roster." print myLabel result = raw_input( "> " ) if value != None and result == '': result = value # validate jid here by nick or jid validation routine jid = self.getJID(result)[0] if(not self.checkTo(jid)): gaveGarbage = 1 while (required and result == '') or gaveGarbage: print "This is a required field, please enter it correctly." print myLabel result = raw_input( "> " ) # validate jid here by nick or jid validation routine jid = self.getJID(result)[0] if(not self.checkTo(jid)): gaveGarbage = 1 else: gaveGarbage = 0 return [var, jid] def getXDataJIDMultiAnswer(self, var, label, value, required): myLabel = self.createXDataLabel(var, label, required, value) result = '' print "You may either use a fully qualified JID, or the nick name of someone on your roster." print "Separate JIDs with commas only." print myLabel tmp = raw_input( "> " ) if value != None and tmp == '': result = value tmps = tmp.split(',') for maybeJid in tmps: # validate jid here by nick or jid validation routine jid = self.getJID(maybeJid)[0] if(self.checkTo(jid)): result = result + "\n" + jid return [var, result] def getXDataAnswers(self, xdataInformation): self.output("Please finish whatever command you're currently entering (or just hit enter) to begin filling out this form.") self.pendingCommand = 1 while(self.gettingCommand == 1): time.sleep(0.01) self.mode = self.MULTILINE if(READLINE == 1): readline.parse_and_bind("set disable-completion on") self.gettingCommand = 1 answers = [] for field in xdataInformation: print required = None if field[5] != None: required = int(field[5]) if field[6] != None: print self.colorscheme["desccolor"] + field[6] + self.colorscheme["defaultcolor"] if field[0] == "hidden": answers.append([field[1], field[3]]) continue if field[0] == "fixed": print field[3] continue if field[0] == "text-single": answers.append(self.getXDataTextSingleAnswer(field[1], field[2], field[3], required, 0)) continue if field[0] == "list-single": answers.append(self.getXDataListSingleAnswer(field[1], field[2], field[3], field[4], required)) continue if field[0] == "list-multi": answers.append(self.getXDataListMultiAnswer(field[1], field[2], field[3], field[4], required)) continue if field[0] == "boolean": answers.append(self.getXDataBooleanAnswer(field[1], field[2], field[3], required)) continue if field[0] == "text-private": answers.append(self.getXDataTextSingleAnswer(field[1], field[2], field[3], required, 1)) continue if field[0] == "text-multi": answers.append(self.getXDataTextMultiAnswer(field[1], field[2], field[3], required)) continue if field[0] == "jid-single": answers.append(self.getXDataJIDSingleAnswer(field[1], field[2], field[3], required)) continue if field[0] == "jid-multi": answers.append(self.getXDataJIDMultiAnswer(field[1], field[2], field[3], required)) continue self.gettingCommand = 0 self.pendingCommand = 0 if(READLINE == 1): # turn completions back on readline.parse_and_bind("set disable-completion off") # show the messages that came in while they were busy self.dumpQueue() self.mode = 0 return answers # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # ------------------------------------------------------------------------- # Command Line Input, Execution Functions # ------------------------------------------------------------------------- # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def run(self): self.running = 1 self.clearScreen() try: while(self.running): if( len( self.commandQueue ) == 0 ): while self.pendingCommand != 0: self.gettingCommand = 0 time.sleep(0.1) self.gettingCommand = 1 self.line = raw_input(self.prompt) self.gettingCommand = 0 else: self.line = self.commandQueue.pop( 0 ) self.executeCommand(self.line) except EOFError: print self.executeCommand(self.prefs.getCommand(self.profile,"quit")) except KeyboardInterrupt: print self.executeCommand(self.prefs.getCommand(self.profile,"quit")) #except: # print "something bad happened" # print "Unexpected error:", sys.exc_info()[0] # self.executeCommand(self.profile.commands.quit) def getAllText(self,prompt): l = "" t = "" saveprompt = "" self.mode = self.MULTILINE if(READLINE == 1): readline.parse_and_bind("set disable-completion on") self.gettingCommand = 1 # save the current prompt before we change it saveprompt = self.prompt self.prompt = "[" + prompt + "]: " l = raw_input( self.prompt ) while(l != "."): if(l == "#"): t = None break t = t + l + "\n" l = raw_input("[" + prompt + "]: ") self.gettingCommand = 0 if(READLINE == 1): # turn completions back on readline.parse_and_bind("set disable-completion off") # show the messages that came in while they were busy self.dumpQueue() self.mode = 0 # repair the prompt self.prompt = saveprompt # remove the last newline? if( t != None ): t = t[:-1] t = unicode(t, self.profile.encoding) return t def checkAlias(self, command, line, profile): if(profile.aliases.has_key(command)): return profile.aliases[command] + " " + line return None def executeCommand(self, line): p = self.prefs pr = self.profile if not isinstance(line,types.UnicodeType): line = unicode(line, pr.encoding) temp = string.split(line,None,1) if self.autostatus != None: self.autostatus.setIdleTime( 0 ) self.autostatus.doAutoStatus() if(len(temp)==0): return command = string.lower(temp[0]) if(len(temp)>1): line = temp[1] else: line = "" line = string.strip(line) a = self.checkAlias(command, line, pr) if(a != None): self.executeCommand(a) return if(command == "/startserver"): self.socketserver = SocketWrapper.listener(self) self.socketserver.start() print "Started ths socket server" return if(command == "/stopserver"): self.socketserver.cli = None self.socketserver.running = 0 print "Stopped the socket server" return if(command == "/eval"): try: pp.pprint(eval(line)) except: traceback.print_exc() a,b,c = sys.exc_info() print "An exception occured" print(a) print(b) print(c) print self.colorscheme["errorcolor"] + "ERROR: " + self.colorscheme["defaultcolor"] + \ "This doesn't evaluate well: <" + line + ">" return for key in self.profile.moduleCommands.keys(): if command == self.profile.moduleCommands[key][0].lower(): self.profile.moduleCommands[key][1](line) return keys = pr.sessioncommands.keys() for key in keys: if command == pr.sessioncommands[key].lower(): #callstring = key + "Command(self, line)" #eval(callstring) getattr(CICommands, key+"Command")(self,line) return print "What you say?? (" + self.prefs.getCommand(self.profile, "help") + " for help.)" def findItem(self, dict, item): keys = dict.keys() for blah in keys: if(dict[blah] == item): return blah return None def printRoster(self): self.printRosterBackend( 0 ); def printRosterGetLists(self, keys, doCulling): if(keys == None): keys = self.imcom.jidhash.keys() chatPeople = [] onlinePeople = [] awayPeople = [] xaPeople = [] dndPeople = [] offlinePeople = [] mxn = 0 # max nick length mxs = 0 # max show length mxt = 0 # max status length for person in keys: # cull only if we're told to. if(doCulling): # don't bother with people we're not subscribed to # unless we've asked for permission or they are a transport if((not self.imcom.subscriptions.has_key(person) or self.imcom.subscriptions[person] == 'from' or self.imcom.subscriptions[person] == 'none') and (self.imcom.asks[person] == 'none' or self.imcom.asks[person] == None) and not self.isAgent(person)): continue # if the person is in the ignore or lurker group, skip them if(not self.imcom.gjidhash.has_key(person)): continue glist = self.imcom.gjidhash[person] if(operator.contains(glist, "lurker") or operator.contains(glist, "ignore")): continue # if we don't have a presence entry for this person, skip them if not self.imcom.preshash.has_key(person): continue # get the nick and calculate max lengths nick = self.getNick(person) available,show,status = self.imcom.preshash[person] if(len(nick) > mxn): mxn = len(nick) if(len(show) > mxs): mxs = len(show) if(len(status) > mxt): mxt = len(status) if show == "chat": chatPeople.append(nick) if show == "online": onlinePeople.append(nick) if show == "away": awayPeople.append(nick) if show == "xa": xaPeople.append(nick) if show == "dnd": dndPeople.append(nick) if not available: offlinePeople.append(nick) chatPeople.sort() onlinePeople.sort() awayPeople.sort() xaPeople.sort() dndPeople.sort() offlinePeople.sort() return [mxn, mxs, mxt, chatPeople, onlinePeople, awayPeople, xaPeople, dndPeople, offlinePeople] def printRosterPrintList(self, aList, mxn, mxs, mxt): trs = "" # trs is theReturnString for nick in aList: jid = self.getJID(nick)[0]#self.imcom.nickhash[nick] if not self.imcom.preshash.has_key(jid): continue available,show,status = self.imcom.preshash[jid] asks = "" if(self.imcom.asks.has_key(jid) and self.imcom.asks[jid] == 'subscribe'): asks = " awaiting authorization" if not available: line = self.colorscheme["usercolor"] + string.ljust(nick,mxn+4) + \ self.colorscheme["defaultcolor"] + self.colorscheme["statuscolor"] + \ string.ljust(show,mxs+2) + self.colorscheme["defaultcolor"] +\ self.colorscheme["desccolor"] + status + self.colorscheme["defaultcolor"] + asks trs = trs + line + "\n" else: resources = "" if(self.imcom.reshash.has_key(jid)): for res in self.imcom.reshash[jid][2].keys(): ress = self.imcom.reshash[jid][2][res][1][0] if(resources == "" and res != ""): resources = " from resources: (" + self.colorscheme["keycolor"] + res + \ self.colorscheme["defaultcolor"] + ", " + self.colorscheme["statuscolor"] + ress + \ self.colorscheme["defaultcolor"] + ")" elif(resources != ""): resources = resources + ", (" + self.colorscheme["keycolor"] + res + \ self.colorscheme["defaultcolor"] + ", " + self.colorscheme["statuscolor"] + ress + \ self.colorscheme["defaultcolor"] + ")" line = self.colorscheme["usercolor"] + string.ljust(nick,mxn+4) +\ self.colorscheme["defaultcolor"] + self.colorscheme["statuscolor"] +\ string.ljust(show,mxs+2) + self.colorscheme["defaultcolor"] +\ self.colorscheme["desccolor"] + status + self.colorscheme["defaultcolor"] + resources + asks trs = trs + line + "\n" return trs def printRosterBackend(self, onlineonly): mxn, mxs, mxt, chatPeople, onlinePeople, awayPeople, xaPeople, dndPeople, offlinePeople = self.printRosterGetLists(None, 1) trs = "" # trs is theReturnString trs = trs + self.colorscheme["sepcolor"] + \ "----------------------------------------" + self.colorscheme["defaultcolor"] + "\n" trs = trs + "You are currently " + self.colorscheme["statuscolor"] + self.imcom.status + \ self.colorscheme["defaultcolor"] + ":" + self.currentStatusReason + "\n" trs = trs + self.colorscheme["sepcolor"] + \ "---------------Your Roster--------------" + self.colorscheme["defaultcolor"] + "\n" statList = [] if( not onlineonly): statList.append(offlinePeople) statList = statList + [dndPeople, xaPeople, awayPeople, onlinePeople, chatPeople] for aList in statList: trs = trs + self.printRosterPrintList(aList, mxn, mxs, mxt) self.output(trs) def printOnlineRoster(self): self.printRosterBackend( 1 ); def showGroupMembers(self, groupname): keys = self.imcom.grouphash[groupname] mxn, mxs, mxt, chatPeople, onlinePeople, awayPeople, xaPeople, dndPeople, offlinePeople = self.printRosterGetLists(keys, 0) self.printText(self.colorscheme["sepcolor"] + "----------------------------------------" + self.colorscheme["defaultcolor"] + "\n") self.printText(self.colorscheme["keycolor"] + string.center(groupname,40) + self.colorscheme["defaultcolor"] + "\n") self.printText(self.colorscheme["sepcolor"] + "----------------------------------------" + self.colorscheme["defaultcolor"] + "\n") statList = [offlinePeople, dndPeople, xaPeople, awayPeople, onlinePeople, chatPeople] trs = "" for aList in statList: trs = trs + self.printRosterPrintList(aList, mxn, mxs, mxt) self.output(trs) def timeInRange( self, unixTime, beginTime, endTime ): curtime = time.localtime( unixTime ) beginTime = 0, 0, 0, int( beginTime[0] ), int( beginTime[1] ), \ 0, 0, 0, curtime[8] endTime = 0, 0, 0, int( endTime[0] ), int( endTime[1] ), \ 0, 0, 0, curtime[8] curtime = 0, 0, 0, curtime[3], curtime[4], 0, 0, 0, curtime[8] if( ( time.mktime( curtime ) >= time.mktime( beginTime ) ) and ( time.mktime( curtime ) <= time.mktime( endTime ) ) ): return 1 return 0 def doAutoStatus( self, idleTime ): self.output( "Wow, michael just made a serious error. Please "\ "message him at michael@www.cosby.dhs.org to "\ "mention this." ) return def tabCompleter(text, state): global cli, tabCompleteToLastUser try: if(text == None): return None if len(readline.get_line_buffer()) == 0 and cli.lastMessaged != None: if tabCompleteToLastUser: tabCompleteToLastUser = 0 return None else: tabCompleteToLastUser = 1 lastMessagedNick = cli.getNick(cli.lastMessaged) if lastMessagedNick.find(' ') != -1: lastMessagedNick = '"' + lastMessagedNick + '"' return cli.prefs.getCommand(cli.profile, "msg") + " " + lastMessagedNick + " " if (len(readline.get_line_buffer()) == 1 and readline.get_line_buffer()[0] != "") and cli.lastReceived != None: if tabCompleteToLastUser: tabCompleteToLastUser = 0 return None else: tabCompleteToLastUser = 1 lastReceivedNick = cli.getNick(cli.lastReceived) if lastReceivedNick.find(' ') != -1: lastReceivedNick = '"' + lastReceivedNick + '"' return cli.prefs.getCommand(cli.profile, "msg") + " " + lastReceivedNick + " " params = string.split(readline.get_line_buffer()) if(len(params) == 1 and readline.get_line_buffer()[-1] != ' '): # We're tab completing a command r = completeFromHash(cli.profile.aliases,text,state) if(r == None): return completeFromHashValue(cli.profile.sessioncommands, text,state) else: return r if((len(params) == 1 and readline.get_line_buffer()[-1] == ' ') or (len(params) == 2 and readline.get_line_buffer()[-1] != ' ')): # We're probably completing a nick foo = 1 while foo: val = completeFromHash(cli.imcom.nickhash,text,state) if val == None or not operator.contains(cli.getJID(val)[0],"ignore"): if val != None: val += " " foo = 0 else: state=state+1 return val if((len(params) == 3 and readline.get_line_buffer()[-1] != ' ') or (len(params) == 2 and readline.get_line_buffer()[-1] == ' ')): # Command specific tab completion return None return None except: traceback.print_exc() a,b,c = sys.exc_info() print "An exception occured" print(a) print(b) print(c) def completeFromHash(hash, text, state): keys = hash.keys() i=0 if not isinstance(text,types.UnicodeType): text = unicode(text, cli.profile.encoding) if len(text) > 0 and text[0] in ("'", '"'): text = text[1:] for item in keys: if (item == None): continue if (text == item[:len(text)]): if(i == state): #print "Returning " + item if(item.find(' ') != -1): return '"' + item + '"' return item else: i = i + 1 #print "Returning None" return None def completeFromHashValue(hash, text, state): #print "In completeFromHashValue" #print "hash is: ", hash keys = hash.keys() i = 0 for item in keys: val = hash[item] if(text == val[:len(text)]): if(i == state): return val else: i = i + 1 return None def printStartup(): print("IMCom version " + str(VERSION) + " is released under the BSD license.\nSee LICENSE for details") print("Written by Casey Crabb (JID: airog@floobin.cx)") def logDebug(s): #print s.encode(self.profile.encoding, "replace") print s.encode('ASCII', "replace") def printUsage(): printStartup() print("Usage: imcom [opts]") print("-d --debug Turn on debugging") print("-p --profile Use the specified profile") print("Example: imcom -p floobin.cx") print("Example: imcom") print("Example: imcom -d") print("") def handler(signum, frame): #global cli #if cli.debug: print 'Signal handler called with signal', signum print 'Frame is ', frame pass def quithandler(signum, frame): cli.executeCommand(cli.prefs.getCommand(cli.profile,"quit")) if(__name__ == "__main__"): global cli # if LOCALE: # locale.setlocale(locale.LC_ALL, "de") #("US","ISO-8859-1")) signal.signal(signal.SIGINT,quithandler) getTerminalWidth() # printStartup() # remove the old debug log file try: os.remove(os.environ['HOME']+"/.imcom/debuglog.log") except: pass args = "hdp:" longargs = ["debug","profile=","help"] try: opts, args = getopt.getopt(sys.argv[1:], args, longargs) except getopt.GetoptError: printUsage() sys.exit(2) debugMode=0 profileName="" for o, a in opts: if o in ("-h", "--help"): printUsage() sys.exit(0) if o in ("-d", "--debug"): debugMode=1 if o in ("-p", "--profile"): profileName=a printStartup() cli = CLI(debugMode, profileName) cli.applyPrefs(debugMode) result = cli.applyProfileWrapper() cli.applyPrefs(debugMode) if result[0] != 0: sys.exit(-1) #cli.start() cli.run() def yesnostr( val ): if( val ): return "yes" else: return "no" def truefalsestr( val ): if( val ): return "true" else: return "false"