"""User command functions for the mudpy engine."""
-# Copyright (c) 2004-2019 mudpy authors. Permission to use, copy,
+# Copyright (c) 2004-2020 mudpy authors. Permission to use, copy,
# modify, and distribute this software is granted under terms
# provided in the LICENSE file distributed with this software.
"""Generic error for an unrecognized command word."""
# 90% of the time use a generic error
- # Whitelist the random.randrange() call in bandit since it's not used for
+ # Allow the random.randrange() call in bandit since it's not used for
# security/cryptographic purposes
if random.randrange(10): # nosec
message = '''I'm not sure what "''' + input_data + '''" means...'''
return True
+def evaluate(actor, parameters):
+ """Evaluate a Python expression."""
+
+ if not parameters:
+ message = "You need to supply a Python expression."
+ elif "__" in parameters:
+ message = "Double-underscores (__) are not allowed in expressions."
+ elif "lambda" in parameters:
+ message = "Lambda functions are not allowed in expressions."
+ else:
+ # Strictly limit the allowed builtins and modules
+ eval_globals = {"__builtins__": dict()}
+ for allowed in ("dir", "globals", "len", "locals"):
+ eval_globals["__builtins__"][allowed] = __builtins__[allowed]
+ eval_globals["mudpy"] = mudpy
+ eval_globals["universe"] = actor.universe
+ try:
+ # there is no other option than to use eval() for this, since
+ # its purpose is to evaluate arbitrary expressions, so do what
+ # we can to secure it and allow it for bandit analysis
+ message = repr(eval(parameters, eval_globals)) # nosec
+ except Exception as e:
+ message = ("$(red)Your expression raised an exception...$(eol)"
+ "$(eol)$(bld)%s$(nrm)" % e)
+ actor.send(message)
+ return True
+
+
def halt(actor, parameters):
"""Halt the world."""
if actor.owner:
description = command.get("description")
if not description:
description = "(no short description provided)"
- if command.get("administrative"):
+ if command.is_restricted():
output = "$(red)"
else:
output = "$(grn)"
if actor.can_run(command):
if really_see_also:
really_see_also += ", "
- if command.get("administrative"):
+ if command.is_restricted():
really_see_also += "$(red)"
else:
really_see_also += "$(grn)"
"description", "(no short description provided)")
# administrative command names are in red, others in green
- if command.get("administrative"):
+ if command.is_restricted():
color = "red"
else:
color = "grn"
actor.universe.contents[actor.get("location")].portals()):
if portal.startswith(parameters):
actor.move_direction(portal)
- return(portal)
+ return portal
actor.send("You cannot go that way.")
return True
(facet, str(facets[facet])))
else:
message = 'Element "' + arguments[1] + '" does not exist.'
- elif arguments[0] == "result":
- if len(arguments) < 2:
- message = "You need to specify an expression."
- else:
- try:
- # there is no other option than to use eval() for this, since
- # its purpose is to evaluate arbitrary expressions, so do what
- # we can to secure it and whitelist it for bandit analysis
- message = repr(eval( # nosec
- " ".join(arguments[1:]),
- {"mudpy": mudpy, "universe": actor.universe}))
- except Exception as e:
- message = ("$(red)Your expression raised an exception...$(eol)"
- "$(eol)$(bld)%s$(nrm)" % e)
elif arguments[0] == "log":
if len(arguments) == 4:
if re.match(r"^\d+$", arguments[3]) and int(arguments[3]) >= 0: