Dereference command action functions
authorJeremy Stanley <fungi@yuggoth.org>
Sat, 11 May 2019 13:24:02 +0000 (13:24 +0000)
committerJeremy Stanley <fungi@yuggoth.org>
Sat, 11 May 2019 13:24:02 +0000 (13:24 +0000)
Replace the use of Python expressions for command actions with
simple names of functions relative to the mudpy package namespace.
This removes an unsafe use of exec(). Also start catching all
exceptions raised by the execution of a command and simply logging
them rather than allowing them to crash the engine.

mudpy/misc.py
share/command.yaml

index 62501d4..045e6a5 100644 (file)
@@ -1889,11 +1889,29 @@ def handler_active(user):
         command = find_command(command_name)
 
         # if it's allowed, do it
+        ran = False
         if actor.can_run(command):
-            exec(command.get("action"))
-
-        # otherwise, give an error
-        elif command_name:
+            # dereference the relative object path for the requested function
+            action = mudpy
+            for component in command.get("action").split("."):
+                try:
+                    action = getattr(action, component)
+                    ran = True
+                except AttributeError:
+                    log('Could not find action function for command "%s"')
+                    action = None
+                    break
+            if action:
+                try:
+                    action(actor, parameters)
+                except Exception:
+                    log('Command string "%s" from user %s raised an '
+                        'exception...\n%s' % (
+                            input_data, actor.owner.account.get("name"),
+                            traceback.format_exc()))
+
+        # if the command was not run, give an error
+        if not ran:
             mudpy.command.error(actor, input_data)
 
     # if no input, just idle back with a prompt
index 382e47e..fe78f1f 100644 (file)
@@ -7,7 +7,7 @@ _desc: This is the standard library of command definitions.
 
 _lock: true
 
-command.chat.action: mudpy.command.chat(actor, parameters)
+command.chat.action: command.chat
 command.chat.description: Enter and leave chat mode.
 command.chat.help: The chat command toggles chat mode. When in chat mode, all
     input is passed as a parameter to the say command, unless prepended by an
@@ -15,46 +15,46 @@ command.chat.help: The chat command toggles chat mode. When in chat mode, all
     use:$(eol)$(eol)   !chat
 command.chat.see_also: say
 
-command.create.action: mudpy.command.create(actor, parameters)
+command.create.action: command.create
 command.create.administrative: true
 command.create.description: Create a new element in the universe.
 command.create.help: Ways to create an element:$(eol)$(eol)   create
     actor.avatar_fred_1$(eol)   create other.garply foo/bar/baz
 
-command.delete.action: mudpy.command.delete(actor, parameters)
+command.delete.action: command.delete
 command.delete.administrative: true
 command.delete.description: Delete an existing facet from an element.
 command.delete.help: You can delete any facet of an element as
     follows:$(eol)$(eol)   delete area.boardroom terrain
 
-command.destroy.action: mudpy.command.destroy(actor, parameters)
+command.destroy.action: command.destroy
 command.destroy.administrative: true
 command.destroy.description: Destroy an existing element in the universe.
 command.destroy.help: You can destroy any element in the universe as
     follows:$(eol)$(eol)   destroy prop.dagger
 
-command.halt.action: mudpy.command.halt(actor, parameters)
+command.halt.action: command.halt
 command.halt.administrative: true
 command.halt.description: Shut down the world.
 command.halt.help: This will save all active accounts, disconnect all clients
     and stop the entire program.
 
-command.help.action: mudpy.command.help(actor, parameters)
+command.help.action: command.help
 command.help.description: List commands or get help on one.
 command.help.help: This will list all comand words available to you along with
     a brief description or, alternatively, give you detailed information on one
     command.
 
-command.look.action: mudpy.command.look(actor, parameters)
+command.look.action: command.look
 command.look.description: Look around.
 command.look.help: With the look command, you can see where you are.
 
-command.move.action: mudpy.command.move(actor, parameters)
+command.move.action: command.move
 command.move.description: Move in a specific direction.
 command.move.help: You move in a direction by entering:$(eol)$(eol)   move
     north
 
-command.preferences.action: mudpy.command.preferences(actor, parameters)
+command.preferences.action: command.preferences
 command.preferences.description: View or change your preferences.
 command.preferences.help: If invoked with no parameters, all your current
     preferences and their values are listed. If one parameter is supplied, the
@@ -64,18 +64,18 @@ command.preferences.help: If invoked with no parameters, all your current
     Examples:$(eol)$(eol)   preferences$(eol)   preferences
     prompt$(eol)   preferences prompt $_(time)>
 
-command.quit.action: mudpy.command.quit(actor, parameters)
+command.quit.action: command.quit
 command.quit.description: Leave the World.
 command.quit.help: This will deactivate your avatar and return you to the main
     menu.
 
-command.reload.action: mudpy.command.reload(actor, parameters)
+command.reload.action: command.reload
 command.reload.administrative: true
 command.reload.description: Reload modules and data.
 command.reload.help: This will reload all python modules and read-only data
     files.
 
-command.say.action: mudpy.command.say(actor, parameters)
+command.say.action: command.say
 command.say.description: State something out loud.
 command.say.help: This allows you to speak to other characters within the same
     area. If you end your sentence with punctuation, the message displayed will
@@ -88,14 +88,14 @@ command.say.help: This allows you to speak to other characters within the same
     went teh wrong way?"$(eol)   You say, "youre sure i went teh wrong way?"
 command.say.see_also: chat
 
-command.set.action: mudpy.command.c_set(actor, parameters)
+command.set.action: command.c_set
 command.set.administrative: true
 command.set.description: Set a facet of an element.
 command.set.help: Invoke it like
     this:$(eol)$(eol)   set actor.avatar_dominique_0 description You see
     nothing special.
 
-command.show.action: mudpy.command.show(actor, parameters)
+command.show.action: command.show
 command.show.administrative: true
 command.show.description: Show various data.
 command.show.help: Here are the possible incantations (<parameter> is required,