def _configChangeHook(self, ses, name, value, newvalue): exported.hook_spam("config_change_hook", { "session": ses, "name": name, "oldvalue": value, "newvalue": newvalue })
def connect(self, host, port, sessionname): """ Takes in a host and a port and connects the socket. @param host: the host to connect to @type host: string @param port: the port to connect at @type port: int @param sessionname: the name of the new session @type sessionname: string """ if not self._sock: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, port)) sock.setblocking(1) self._host = host self._port = port self._sock = sock self._sessionname = sessionname ses = exported.get_session(sessionname) exported.hook_spam("connect_hook", \ {"session": ses, "host": host, "port": port}) else: raise Exception("Connection already exists.")
def shutdown(self, args): """ Shuts down the session, shuts down the underlying SocketCommunicator. @param args: the args tuple for the shutdown_hook. @type args: tuple """ if len(args) > 0: quiet = 1 else: quiet = 0 # unregister with the shutdown hook # exported.hook_unregister("shutdown_hook", self.shutdown) if self.getName() != "common": if quiet == 0: event.OutputEvent("Session %s disconnected.\n\"#zap %s\" to kill the session.\n" % (self._name, self._name)).enqueue() exported.hook_spam("disconnect_hook", {"session": self, "host": self._host, "port": self._port}) if self._socket: self._socket.shutdown() self._host = None self._port = 0 self._socket = None
def writeSocket(self, message, tag=None): """ Writes data to the socket. @param message: the data to be written to the mud @type message: string @param tag: Used to tag data being sent to the mud for identification when it comes out of the to_mud_hook. Simply passed through as-is by lyntin internals. @type tag: varies """ for line in message.strip().split("\n"): exported.hook_spam("to_mud_hook", {"session": self, "data": line, "tag": tag}) if self._socket: retval = self._socket.write(str(message)) if retval: exported.write_error("socket write: %s" % retval) else: # if we don't have a socket then we can't do any non-lyntin-command # stuff. exported.write_error("No connection. Create a session.\n(See also: #help, #help session)") return
def get_completion_list(self, text='', position=None): """ Returns the completion list. Rebuilds the list if it is empty. @param text: the text to be completed @type text: string @param position: cursor position in the text @type position: int @returns: all possible completion pairs list [(newtext, newposition)] @rtype: [(string, int)] """ if not self.completion_list_: # # Rebuild the completion list if it is empty after reset. # if position==None or position<0 or position>len(text): position = len(text) # # Gather all the completions from registered completers: # exported.hook_spam("completer_hook", { 'text': text, 'position': position }, self._completion_mapping_helper ) # put an anchor at the end of list self.completion_list_.append((text, position)) return self.completion_list_
def writeSocket(self, message, tag=None): """ Writes data to the socket. @param message: the data to be written to the mud @type message: string @param tag: Used to tag data being sent to the mud for identification when it comes out of the to_mud_hook. Simply passed through as-is by lyntin internals. @type tag: varies """ for line in message.strip().split("\n"): exported.hook_spam("to_mud_hook", { "session": self, "data": line, "tag": tag }) if self._socket: retval = self._socket.write(str(message)) if retval: exported.write_error("socket write: %s" % retval) else: # if we don't have a socket then we can't do any non-lyntin-command # stuff. exported.write_error( "No connection. Create a session.\n(See also: #help, #help session)" ) return
def shutdown(self, args): """ Shuts down the session, shuts down the underlying SocketCommunicator. @param args: the args tuple for the shutdown_hook. @type args: tuple """ if len(args) > 0: quiet = 1 else: quiet = 0 # unregister with the shutdown hook # exported.hook_unregister("shutdown_hook", self.shutdown) if self.getName() != "common": if quiet == 0: event.OutputEvent( "Session %s disconnected.\n\"#zap %s\" to kill the session.\n" % (self._name, self._name)).enqueue() exported.hook_spam("disconnect_hook", { "session": self, "host": self._host, "port": self._port }) if self._socket: self._socket.shutdown() self._host = None self._port = 0 self._socket = None
def bell_cmd(ses, words, input): """ Kicks off the bell for a given session. Anything registered with the bell_hook will get tickled. category: commands """ exported.hook_spam("bell_hook", {"session": ses})
def _varChangeHook(self, var, old, new): """ This calls the variable_change_hook. It allows other modules to know when variable values are changed so that they can handle those changes accordingly. """ exported.hook_spam("variable_change_hook", {"session": self, "variable": var, "oldvalue": old, "newvalue": new})
def execute(self): """ Execute.""" exported.hook_spam(*(self._vargs), **(self._nargs)) # Local variables: # mode:python # py-indent-offset:2 # tab-width:2 # End:
def set_current_session(self, newsession): """ Changes the current session to another session. @param newsession: the session to change to @type newsession: session.Session instance """ previous_session = self._current_session self._current_session = newsession exported.hook_spam("session_change_hook", {"new": newsession, "previous": previous_session}) exported.write_message("%s now current session." % newsession.getName())
def _varChangeHook(self, var, old, new): """ This calls the variable_change_hook. It allows other modules to know when variable values are changed so that they can handle those changes accordingly. """ exported.hook_spam("variable_change_hook", { "session": self, "variable": var, "oldvalue": old, "newvalue": new })
def tallyError(self): """ Adds one to the error count. If we see more than 20 errors, we shutdown. """ self._errorcount = self._errorcount + 1 exported.write_error("WARNING: Unhandled error encountered (%d out of %d)." % (self._errorcount, 20)) exported.hook_spam("error_occurred_hook", {"count": self._errorcount}) if self._errorcount > 20: exported.hook_spam("too_many_errors_hook", {}) exported.write_error("Error count exceeded--shutting down.") sys.exit(0)
def shutdown(): """ This gets called by the Python interpreter atexit. The reason we do shutdown stuff here is we're more likely to catch things here than we are to let everything cycle through the ShutdownEvent. This should probably get fixed up at some point in the future. Do not call this elsewhere. """ import exported try: exported.write_message("shutting down... goodbye.") except: print "shutting down... goodbye." exported.hook_spam("shutdown_hook", {})
def writeUI(self, text): """ Writes a message to the ui. This method uses a lock so that multiple threads can write to the ui without intersecting and crashing the python process. Theoretically you should use the exported module to write things to the ui--it calls this method. @param text: the message to write to the ui @type text: string or ui.base.Message """ self._ui_lock.acquire(1) try: exported.hook_spam("to_user_hook", {"message": text}) finally: self._ui_lock.release()
def write(self, data, convert=1): """ Writes data to the mud after passing it through net_write_data_filter. @param data: the data to write to the socket @type data: bytes @param convert: whether (1) or not (0) we should convert eol stuff to CRLF and IAC to IAC IAC. @type convert: boolean @raises Exception: if we have problems sending the data over the socket """ data = data + b"\n" if convert: data = data.replace(b"\n", b"\r\n") if IAC in data: data = data.replace(IAC, IAC + IAC) if self._shutdownflag == 0: # run the data through the net_write_data_filter hook which # allows things like compressors and other data transformation # mechanisms to do their thing. spamargs = { "session": self._session, "data": data, "dataadj": data } spamargs = exported.hook_spam("net_write_data_filter", argmap=spamargs, mappingfunc=exported.filter_mapper) if spamargs == None: return else: data = spamargs["dataadj"] try: self._sock.send(data) except Exception as e: if self._shutdownflag == 0 and self._session: self._session.shutdown(()) raise Exception(e) return None
def _filterIncomingData(self, data): """ run the data through the net_read_data_filter hook which allows things like compressors and other data transformation mechanisms to do their thing. """ # be careful--this catches both the '' and the None situations if not data: return data spamargs = {"session": self._session, "data": data, "dataadj": data} spamargs = exported.hook_spam("net_read_data_filter", argmap=spamargs, mappingfunc=exported.filter_mapper) if spamargs == None: data = "" else: data = spamargs["dataadj"] return data
def write(self, data, convert=1): """ Writes data to the mud after passing it through net_write_data_filter. @param data: the data to write to the socket @type data: string @param convert: whether (1) or not (0) we should convert eol stuff to CRLF and IAC to IAC IAC. @type convert: boolean @raises Exception: if we have problems sending the data over the socket """ if convert: data = data.replace("\n", "\r\n") if IAC in data: data = data.replace(IAC, IAC+IAC) if self._shutdownflag == 0: # run the data through the net_write_data_filter hook which # allows things like compressors and other data transformation # mechanisms to do their thing. spamargs = {"session": self._session, "data": data, "dataadj": data} spamargs = exported.hook_spam("net_write_data_filter", argmap=spamargs, mappingfunc=exported.filter_mapper) if spamargs == None: return else: data = spamargs["dataadj"] try: self._sock.send(data) except Exception, e: if self._shutdownflag == 0 and self._session: self._session.shutdown(()) raise Exception(e) return None
def filter(self, args): """ Takes in user command lines and handles commands that start with a Lyntin command character. @param args: (session, internal boolean, ..., current input text) @type args: tuple @return: None if we handled the input, or the current input text if we didn't @rtype: None or string """ ses = args["session"] internal = args["internal"] input = args["dataadj"] commandchar = self._engine.getConfigManager().get("commandchar") if len(input) > 1 and input.startswith(commandchar): input = input[1:] # splits out the command name from the rest of the command line words = input.split(" ", 1) # We want an empty argument list if there was one, don't want # array out-of-bounds issues if len(words) < 2: words.append("") # this checks to see if it's a special #@ command. if input.startswith("@"): self.getCommand("@")(ses, input.split(" "), input) if internal == 0: ses.prompt() return # this finds the first matching command and ends there. commands = self.getCommands() commands.sort() for mem in commands: command = None if mem.startswith("^"): if re.compile(mem).search(words[0]): command = self.getCommand(mem) else: if mem.startswith(words[0]): command = self.getCommand(mem) if command: argumentparser = self.getArgParser(mem) if argumentparser == None: command(ses, input.split(" "), input) else: # for printing out the error message, we remove the ^ # from the command name if it's there. fixedmem = mem if len(fixedmem) > 0 and fixedmem.startswith("^"): fixedmem = fixedmem[1:] resolver = exported.hook_spam( "default_resolver_hook", { "session": ses, "commandname": mem }, mappingfunc=exported.query_mapper, donefunc=exported.query_done) try: argdict = argumentparser.parse(words[1], resolver) argdict["command"] = mem command(ses, argdict, input) except ValueError, e: exported.write_error( "%s: %s\nsyntax: %s%s %s" % (fixedmem, e, commandchar, fixedmem, argumentparser.syntaxline)) except argparser.ParserException, e: exported.write_error( "%s: %s\nsyntax: %s%s %s" % (fixedmem, e, commandchar, fixedmem, argumentparser.syntaxline)) if internal == 0: ses.prompt() break
def main(defaultoptions={}): """ This parses the command line arguments and makes sure they're all valid, instantiates a ui, does some setup, spins off an engine thread, and goes into the ui's mainloop. @param defaultoptions: the boot options to use. we update the config.options dict with these options--this is the easiest way to override the ui, moduledir, datadir, et al from a Lyntin run script. @type defaultoptions: dict """ try: import sys, os, traceback, ConfigParser from lyntin import config, event, utils, exported from lyntin.ui import base import locale locale.setlocale(locale.LC_ALL, '') config.options.update(defaultoptions) # read through options and arguments optlist = utils.parse_args(sys.argv[1:]) for mem in optlist: if mem[0] == '--help': print constants.HELPTEXT sys.exit(0) elif mem[0] == '--version': print constants.VERSION sys.exit(0) elif mem[0] in ["--configuration", "-c"]: # ini files OVERRIDE the default options # they can provide multiple ini files, but each new # ini file will OVERRIDE the contents of the previous ini file # where the two files intersect. parser = ConfigParser.ConfigParser() parser.read([mem[1]]) newoptions = {} for s in parser.sections(): for o in parser.options(s): c = parser.get(s, o).split(",") if newoptions.has_key(o): newoptions[o] += c else: newoptions[o] = c config.options.update(newoptions) else: opt = mem[0] while opt.startswith("-"): opt = opt[1:] if len(opt) > 0: if config.options.has_key(opt): if type(config.options[opt]) is list: config.options[opt].append(mem[1]) else: config.options[opt] = mem[1] else: config.options[opt] = [mem[1]] for mem in ["datadir", "ui", "commandchar"]: if config.options.has_key(mem) and type(config.options[mem]) is list: config.options[mem] = config.options[mem][0] # if they haven't set the datadir via the command line, then # we go see if they have a HOME in their environment variables.... if not config.options["datadir"]: if os.environ.has_key("HOME"): config.options["datadir"] = os.environ["HOME"] config.options["datadir"] = utils.fixdir(config.options["datadir"]) def on_shutdown(): """ This gets called by the Python interpreter atexit. The reason we do shutdown stuff here is we're more likely to catch things here than we are to let everything cycle through the ShutdownEvent. This should probably get fixed up at some point in the future. """ if not hasattr(sys, 'frozen'): sys.stderr.write("goodbye.\n") #exported.hook_spam("shutdown_hook", {}) import atexit atexit.register(on_shutdown) # instantiate the engine Engine.instance = Engine() exported.myengine = Engine.instance Engine.instance._setupConfiguration() # instantiate the ui uiinstance = None try: uiname = str(config.options['ui']) modulename = uiname + "ui" uiinstance = base.get_ui(modulename) if not uiinstance: raise ValueError("No ui instance.") except Exception, e: print "Cannot start '%s': %s" % (uiname, e) traceback.print_exc() sys.exit(0) Engine.instance.setUI(uiinstance) # do some more silly initialization stuff # adds the .lyntinrc file to the readfile list if it exists. if config.options["datadir"]: lyntinrcfile = config.options["datadir"] + ".lyntinrc" if os.path.exists(lyntinrcfile): # we want the .lyntinrc file read in first, so then other # files can overwrite the contents therein config.options['readfile'].insert(0, lyntinrcfile) # import modules listed in modulesinit exported.write_message("Loading Lyntin modules.") try: import lyntin.modules lyntin.modules.load_modules() except: exported.write_traceback("Modules did not load correctly.") sys.exit(1) commandchar = Engine.instance._managers["config"].get("commandchar") # handle command files for mem in config.options['readfile']: exported.write_message("Reading in file " + mem) # we have to escape windows os separators because \ has a specific # meaning in the argparser mem = mem.replace("\\", "\\\\") exported.lyntin_command("%sread %s" % (commandchar, mem), internal=1) # spam the startup hook exported.hook_spam("startup_hook", {}) # we're done initialization! exported.write_message(constants.STARTUPTEXT) Engine.instance.writePrompt() engine_thread = Engine.instance.startthread("engine", Engine.instance.runengine) timer_thread = Engine.instance.startthread("timer", Engine.instance.runtimer) try: Engine.instance._ui.runui() finally: if not hasattr(sys, 'frozen'): sys.stderr.write("Shutting down...") event.ShutdownEvent().enqueue() engine_thread.join(10) timer_thread.join(10)
def _configChangeHook(self, ses, name, value, newvalue): exported.hook_spam("config_change_hook", {"session": ses, "name": name, "oldvalue": value, "newvalue": newvalue })
def filter(self, args): """ Takes in user command lines and handles commands that start with a Lyntin command character. @param args: (session, internal boolean, ..., current input text) @type args: tuple @return: None if we handled the input, or the current input text if we didn't @rtype: None or string """ ses = args["session"] internal = args["internal"] input = args["dataadj"] commandchar = self._engine.getConfigManager().get("commandchar") if len(input) > 1 and input.startswith(commandchar): input = input[1:] # splits out the command name from the rest of the command line words = input.split(" ",1) # We want an empty argument list if there was one, don't want # array out-of-bounds issues if len(words) < 2: words.append("") # this checks to see if it's a special #@ command. if input.startswith("@"): self.getCommand("@")(ses, input.split(" "), input) if internal==0: ses.prompt() return # this finds the first matching command and ends there. commands = self.getCommands() commands.sort() for mem in commands: command = None if mem.startswith("^"): if re.compile(mem).search(words[0]): command = self.getCommand(mem) else: if mem.startswith(words[0]): command = self.getCommand(mem) if command: argumentparser = self.getArgParser(mem) if argumentparser == None: command(ses, input.split(" "), input) else: # for printing out the error message, we remove the ^ # from the command name if it's there. fixedmem = mem if len(fixedmem) > 0 and fixedmem.startswith("^"): fixedmem = fixedmem[1:] resolver = exported.hook_spam("default_resolver_hook", {"session": ses, "commandname": mem}, mappingfunc=exported.query_mapper, donefunc=exported.query_done) try: argdict = argumentparser.parse(words[1], resolver) argdict["command"]=mem command(ses, argdict, input) except ValueError, e: exported.write_error("%s: %s\nsyntax: %s%s %s" % (fixedmem, e, commandchar, fixedmem, argumentparser.syntaxline)) except argparser.ParserException, e: exported.write_error("%s: %s\nsyntax: %s%s %s" % (fixedmem, e, commandchar, fixedmem, argumentparser.syntaxline)) if internal == 0: ses.prompt() break
def handleUserData(self, input, internal=0, session=None ): """ This handles input lines from the user in a session-less context. The engine.handleUserData deals with global stuff and then passes the modified input to the session for session-oriented handling. The session can call this method again with expanded input--this method is considered recursive. internal tells whether to spam the input hook and things of that nature. @param input: the data from the user @type input: string @param internal: whether this should be executed internally or not. 0 if we should spam the input hook and record the input to the historymanager; 1 if we shouldn't @type internal: boolean @param session: the session scoping to execute this user input in @type session: session.Session instance @return: the commands that were actually executed (may not be exactly what the user typed--this is for the history manager) @rtype: string """ if self._managers["config"].get("debugmode") == 1: exported.write_message("evaluating: %s" % input) inputlist = utils.split_commands(self._managers["config"].get("splitchar"), input) if session == None: session = self._current_session historyitems = [] commandchar = self._managers["config"].get("commandchar") for mem in inputlist: # mem = mem.strip() if len(mem) == 0: mem = commandchar + "cr" # if it's not internal we spam the hook with the raw input if internal == 0: exported.hook_spam("from_user_hook", {"data": mem}) if mem.startswith("!"): memhistory = self.getManager("history").getHistoryItem(mem) if memhistory != None: self.handleUserData(memhistory, 1, session) historyitems.append(memhistory) continue # if it starts with a # it's a loop, session or command if len(mem) > 0 and mem.startswith(commandchar): # pull off the first token without the commandchar ses = mem.split(" ", 1)[0][1:] # is it a loop (aka repeating command)? if ses.isdigit(): num = int(ses) if mem.find(" ") != -1: command = mem.split(" ", 1)[1] command = utils.strip_braces(command) if num > 0: for i in range(num): loopcommand = self.handleUserData(command, 1, session) historyitems.append(commandchar + ses + " {" + loopcommand + "}") continue # is it a session? if self._sessions.has_key(ses): input = mem.split(" ", 1) if len(input) < 2: self.set_current_session(self._sessions[ses]) else: self.handleUserData(input[1], internal=1, session=self._sessions[ses]) historyitems.append(mem) continue # is it "all" sessions? if ses == "all": newinput = mem.split(" ", 1) if len(newinput) > 1: newinput = newinput[1] else: newinput = commandchar + "cr" for sessionname in self._sessions.keys(): if sessionname != "common": self._sessions[sessionname].handleUserData(newinput, internal) historyitems.append(mem) continue # if we get here then it is not a valid !-expression. and it's going # to the default session historyitems.append(mem) # no command char, so we pass it on to the session.handleUserData # to do session oriented things session.handleUserData(mem, internal) # we don't record internal stuff or input that isn't supposed # to be echo'd executed = ";".join(historyitems) if internal == 0 and self.getConfigManager().get("mudecho") == 1: self.getManager("history").recordHistory(executed) return executed
def main(defaultoptions={}): """ This parses the command line arguments and makes sure they're all valid, instantiates a ui, does some setup, spins off an engine thread, and goes into the ui's mainloop. @param defaultoptions: the boot options to use. we update the config.options dict with these options--this is the easiest way to override the ui, moduledir, datadir, et al from a Lyntin run script. @type defaultoptions: dict """ try: import sys, os, traceback, ConfigParser from lyntin import config, event, utils, exported from lyntin.ui import base import locale locale.setlocale(locale.LC_ALL, '') config.options.update(defaultoptions) # read through options and arguments optlist = utils.parse_args(sys.argv[1:]) for mem in optlist: if mem[0] == '--help': print constants.HELPTEXT sys.exit(0) elif mem[0] == '--version': print constants.VERSION sys.exit(0) elif mem[0] in ["--configuration", "-c"]: # ini files OVERRIDE the default options # they can provide multiple ini files, but each new # ini file will OVERRIDE the contents of the previous ini file # where the two files intersect. parser = ConfigParser.ConfigParser() parser.read([mem[1]]) newoptions = {} for s in parser.sections(): for o in parser.options(s): c = parser.get(s, o).split(",") if newoptions.has_key(o): newoptions[o] += c else: newoptions[o] = c config.options.update(newoptions) else: opt = mem[0] while opt.startswith("-"): opt = opt[1:] if len(opt) > 0: if config.options.has_key(opt): if type(config.options[opt]) is list: config.options[opt].append(mem[1]) else: config.options[opt] = mem[1] else: config.options[opt] = [mem[1]] for mem in ["datadir", "ui", "commandchar"]: if config.options.has_key(mem) and type( config.options[mem]) is list: config.options[mem] = config.options[mem][0] # if they haven't set the datadir via the command line, then # we go see if they have a HOME in their environment variables.... if not config.options["datadir"]: if os.environ.has_key("HOME"): config.options["datadir"] = os.environ["HOME"] config.options["datadir"] = utils.fixdir(config.options["datadir"]) def on_shutdown(): """ This gets called by the Python interpreter atexit. The reason we do shutdown stuff here is we're more likely to catch things here than we are to let everything cycle through the ShutdownEvent. This should probably get fixed up at some point in the future. """ sys.stderr.write("goodbye.\n") #exported.hook_spam("shutdown_hook", {}) import atexit atexit.register(on_shutdown) # instantiate the engine Engine.instance = Engine() exported.myengine = Engine.instance Engine.instance._setupConfiguration() # instantiate the ui uiinstance = None try: uiname = str(config.options['ui']) modulename = uiname + "ui" uiinstance = base.get_ui(modulename) if not uiinstance: raise ValueError("No ui instance.") except Exception, e: print "Cannot start '%s': %s" % (uiname, e) traceback.print_exc() sys.exit(0) Engine.instance.setUI(uiinstance) # do some more silly initialization stuff # adds the .lyntinrc file to the readfile list if it exists. if config.options["datadir"]: lyntinrcfile = config.options["datadir"] + ".lyntinrc" if os.path.exists(lyntinrcfile): # we want the .lyntinrc file read in first, so then other # files can overwrite the contents therein config.options['readfile'].insert(0, lyntinrcfile) # import modules listed in modulesinit exported.write_message("Loading Lyntin modules.") try: import modules.__init__ modules.__init__.load_modules() except: exported.write_traceback("Modules did not load correctly.") sys.exit(1) # spam the startup hook exported.hook_spam("startup_hook", {}) commandchar = Engine.instance._managers["config"].get("commandchar") # handle command files for mem in config.options['readfile']: exported.write_message("Reading in file " + mem) # we have to escape windows os separators because \ has a specific # meaning in the argparser mem = mem.replace("\\", "\\\\") exported.lyntin_command("%sread %s" % (commandchar, mem), internal=1) # we're done initialization! exported.write_message(constants.STARTUPTEXT) Engine.instance.writePrompt() engine_thread = Engine.instance.startthread("engine", Engine.instance.runengine) timer_thread = Engine.instance.startthread("timer", Engine.instance.runtimer) try: Engine.instance._ui.runui() finally: sys.stderr.write("Shutting down...") event.ShutdownEvent().enqueue() engine_thread.join(10) timer_thread.join(10)
def handleUserData(self, input, internal=0, session=None): """ This handles input lines from the user in a session-less context. The engine.handleUserData deals with global stuff and then passes the modified input to the session for session-oriented handling. The session can call this method again with expanded input--this method is considered recursive. internal tells whether to spam the input hook and things of that nature. @param input: the data from the user @type input: string @param internal: whether this should be executed internally or not. 0 if we should spam the input hook and record the input to the historymanager; 1 if we shouldn't @type internal: boolean @param session: the session scoping to execute this user input in @type session: session.Session instance @return: the commands that were actually executed (may not be exactly what the user typed--this is for the history manager) @rtype: string """ if self._managers["config"].get("debugmode") == 1: exported.write_message("evaluating: %s" % input) inputlist = utils.split_commands( self._managers["config"].get("splitchar"), input) if session == None: session = self._current_session historyitems = [] commandchar = self._managers["config"].get("commandchar") for mem in inputlist: # mem = mem.strip() if len(mem) == 0: mem = commandchar + "cr" # if it's not internal we spam the hook with the raw input if internal == 0: exported.hook_spam("from_user_hook", {"data": mem}) if mem.startswith("!"): memhistory = self.getManager("history").getHistoryItem(mem) if memhistory != None: self.handleUserData(memhistory, 1, session) historyitems.append(memhistory) continue # if it starts with a # it's a loop, session or command if len(mem) > 0 and mem.startswith(commandchar): # pull off the first token without the commandchar ses = mem.split(" ", 1)[0][1:] # is it a loop (aka repeating command)? if ses.isdigit(): num = int(ses) if mem.find(" ") != -1: command = mem.split(" ", 1)[1] command = utils.strip_braces(command) if num > 0: for i in range(num): loopcommand = self.handleUserData( command, 1, session) historyitems.append(commandchar + ses + " {" + loopcommand + "}") continue # is it a session? if self._sessions.has_key(ses): input = mem.split(" ", 1) if len(input) < 2: self.set_current_session(self._sessions[ses]) else: self.handleUserData(input[1], internal=1, session=self._sessions[ses]) historyitems.append(mem) continue # is it "all" sessions? if ses == "all": newinput = mem.split(" ", 1) if len(newinput) > 1: newinput = newinput[1] else: newinput = commandchar + "cr" for sessionname in self._sessions.keys(): if sessionname != "common": self._sessions[sessionname].handleUserData( newinput, internal) historyitems.append(mem) continue # if we get here then it is not a valid !-expression. and it's going # to the default session historyitems.append(mem) # no command char, so we pass it on to the session.handleUserData # to do session oriented things session.handleUserData(mem, internal) # we don't record internal stuff or input that isn't supposed # to be echo'd executed = ";".join(historyitems) if internal == 0 and self.getConfigManager().get("mudecho") == 1: self.getManager("history").recordHistory(executed) return executed
def execute(self): """ Execute.""" exported.hook_spam(*(self._vargs), **(self._nargs))
def execute(self): """ Execute the shutdown.""" exported.hook_spam("shutdown_hook", {})
def handleNego(self, data): """ Removes telnet negotiation stuff from the stream and handles it. @param data: the incoming data from the mud that we need to parse for telnet control code stuff @type data: string @return: the data without the telnet control codes @rtype: string """ marker = -1 i = data.find(IAC) while (i != -1): if i + 1 >= len(data): marker = i break if data[i+1] == NOP: data = data[:i] + data[i+2:] self.logControl("receive: IAC NOP") elif data[i+1] == GA or data[i+1] == TELOPT_EOR: data = data[:i] + data[i+2:] # if data is a prompt delimited with some telnet option, # then we'll mark the server as "server with good prompting" self._good_prompts = 1 elif data[i+1] == IAC: data = data[:i] + data[i+1:] i = i + 1 self.logControl("receive: IAC IAC") else: if i + 2 >= len(data): marker = i break # handles DO/DONT/WILL/WONT stuff if data[i+1] in DDWW: option = data[i:i+3] self.logControl("receive: " + _cc(option)) if option[2] == ECHO: if option[1] == WILL: self._config.change("mudecho", "off") elif option[1] == WONT: self._config.change("mudecho", "on") elif option[2] == TERMTYPE: if option[1] == DO: self.write(IAC + WILL + TERMTYPE, 0) self.logControl("send: IAC WILL TERMTYPE") else: self.write(IAC + WONT + TERMTYPE, 0) self.logControl("send: IAC WONT TERMTYPE") elif option[2] == EOR: if option[1] == WILL: self.write(IAC + DO + EOR, 0) self.logControl("send: IAC DO EOR") else: args = {"session": self._session, "data": option} # this will give us back the args (in the case that no one # handled it) or None (in the case that someone handled it # and raised a StopSpammingException). ret = exported.hook_spam("net_handle_telnet_option", args) if ret: if option[1] in DD: self.write(IAC + WONT + option[2], 0) self.logControl("send: " + _cc(IAC + WONT + option[2])) elif option[1] in WW: self.write(IAC + DONT + option[2], 0) self.logControl("send: " + _cc(IAC + DONT + option[2])) data = data[:i] + data[i+3:] # handles SB...SE stuff elif data[i+1] == SB: end = data.find(SE, i) if end == -1: marker = i break option = data[i:end+1] self.logControl("receive: " + _cc(option)) if option[2] == TERMTYPE and option[3] == SEND: self.write(IAC + SB + TERMTYPE + IS + self._termtype + IAC + SE, 0) self.logControl("send: IAC SB TERMTYPE IS " + self._termtype + " IAC SE") else: args = {"session": self._session, "data": option} # this will give us back the args (in the case that no one # handled it) or None (in the case that someone handled it # and raised a StopSpammingException). ret = exported.hook_spam("net_handle_telnet_option", args) data = data[:i] + data[end+1:] # in case they passed us something weird we remove the IAC and # move on else: data = data[:i] + data[i+1:] i = data.find(IAC, i) if marker != -1: self._nego_buffer = data[marker:] data = data[:marker] return data
def execute(self): """ Execute.""" exported.hook_spam("from_mud_hook", {"session": self._session, "data": self._input}) exported.myengine.handleMudData(self._session, self._input)