Added contrib "evlang", an experimental highly restricted Python code environment. It's intended to be used by untrusted users to add custom code e.g. to their crafted objects and similar. Please heed the warnings in the README file - this is experimental still and more people need to play with it and try to break it.
The system uses a hybrid blacklisting/whitelisting and AST-traversal approach to both remove dangerous builtins as well as disallow potentially exploitable python structures alltogether. Examples are while structures and attribute allocation. All advanced functionality is accessed through a set of "safe" methods on a holder object. You can extend this with your own safe methods in order to add more functionality befitting your game. The system comes with a host of examples, a few scriptable objects and complete commands for adding code to objects. At this point it's not guaranteed that all systems are safe against meddling however - notably Attributes have no locks defined on them by default (although this system does properly check Attribute lock types should they exixt). Please test and try to break - and report problems to the Issue tracker/forum as usual.
This commit is contained in:
parent
3d24ee2242
commit
58e20e2cf1
6 changed files with 1302 additions and 0 deletions
136
contrib/evlang/command.py
Normal file
136
contrib/evlang/command.py
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
|
||||
"""
|
||||
|
||||
Evlang usage examples
|
||||
Commands for use with evlang
|
||||
|
||||
Evennia contribution - Griatch 2012
|
||||
|
||||
The @code command allows to add scripted evlang code to
|
||||
a ScriptableObject. It will handle access checks.
|
||||
|
||||
"""
|
||||
|
||||
from ev import utils
|
||||
from ev import default_cmds
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Evlang-related commands
|
||||
#
|
||||
# Easiest is to add this command to the default cmdset.
|
||||
# Alternatively one could imagine storing it directly only
|
||||
# on scriptable objects.
|
||||
#------------------------------------------------------------
|
||||
|
||||
class CmdCode(default_cmds.MuxCommand):
|
||||
"""
|
||||
add custom code to a scriptable object
|
||||
|
||||
Usage:
|
||||
@code[/switch] <obj>[/<type> [= <codestring> ]]
|
||||
|
||||
Switch:
|
||||
|
||||
delete - clear code of given type from the object.
|
||||
debug - immediately run the given code after adding it.
|
||||
|
||||
This will add custom scripting to an object
|
||||
which allows such modification.
|
||||
|
||||
<type> must be one of the script types allowed
|
||||
on the object. Only supplying the command will
|
||||
return a list of script types possible to add
|
||||
custom scripts to.
|
||||
|
||||
"""
|
||||
key = "@code"
|
||||
locks = "cmd:perm(Builders)"
|
||||
help_category = "Building"
|
||||
|
||||
def func(self):
|
||||
"implements the functionality."
|
||||
caller = self.caller
|
||||
|
||||
if not self.args:
|
||||
caller.msg("Usage: @code <obj>[/<type> [= <codestring>]]")
|
||||
return
|
||||
codetype = None
|
||||
objname = self.lhs
|
||||
if '/' in self.lhs:
|
||||
objname, codetype = [part.strip() for part in self.lhs.rsplit("/", 1)]
|
||||
|
||||
obj = self.caller.search(objname)
|
||||
if not obj:
|
||||
return
|
||||
|
||||
# get the dicts from db storage for easy referencing
|
||||
evlang_scripts = obj.db.evlang_scripts
|
||||
evlang_locks = obj.db.evlang_locks
|
||||
if not (evlang_scripts != None and evlang_locks and obj.ndb.evlang):
|
||||
caller.msg("Object %s can not be scripted." % obj.key)
|
||||
return
|
||||
|
||||
if 'delete' in self.switches:
|
||||
# clearing a code snippet
|
||||
if not codetype:
|
||||
caller.msg("You must specify a code type.")
|
||||
return
|
||||
if not codetype in evlang_scripts:
|
||||
caller.msg("Code type '%s' not found on %s." % (codetype, obj.key))
|
||||
return
|
||||
# this will also update the database
|
||||
obj.ndb.evlang.delete(codetype)
|
||||
caller.msg("Code for type '%s' cleared on %s." % (codetype, obj.key))
|
||||
return
|
||||
|
||||
if not self.rhs:
|
||||
if codetype:
|
||||
scripts = [(name, tup[1], utils.crop(tup[0])) for name, tup in evlang_scripts.items() if name==codetype]
|
||||
scripts.extend([(name, "--", "--") for name in evlang_locks if name not in evlang_scripts if name==codetype])
|
||||
else:
|
||||
# no type specified. List all scripts/slots on object
|
||||
print evlang_scripts
|
||||
scripts = [(name, tup[1], utils.crop(tup[0])) for name, tup in evlang_scripts.items()]
|
||||
scripts.extend([(name, "--", "--") for name in evlang_locks if name not in evlang_scripts])
|
||||
scripts = sorted(scripts, key=lambda p: p[0])
|
||||
|
||||
table = [["type"] + [tup[0] for tup in scripts],
|
||||
["creator"] + [tup[1] for tup in scripts],
|
||||
["code"] + [tup[2] for tup in scripts]]
|
||||
ftable = utils.format_table(table, extra_space=5)
|
||||
string = "{wEvlang scripts on %s:{n" % obj.key
|
||||
for irow, row in enumerate(ftable):
|
||||
if irow == 0:
|
||||
string += "\n" + "".join("{w%s{n" % col for col in row)
|
||||
else:
|
||||
string += "\n" + "".join(col for col in row)
|
||||
|
||||
caller.msg(string)
|
||||
return
|
||||
|
||||
# we have rhs
|
||||
codestring = self.rhs
|
||||
if not codetype in evlang_locks:
|
||||
caller.msg("Code type '%s' cannot be coded on %s." % (codetype, obj.key))
|
||||
return
|
||||
# check access with the locktype "code"
|
||||
if not obj.ndb.evlang.lockhandler.check(caller, "code"):
|
||||
caller.msg("You are not permitted to add code of type %s." % codetype)
|
||||
return
|
||||
# we have code access to this type.
|
||||
oldcode = None
|
||||
if codetype in evlang_scripts:
|
||||
oldcode = str(evlang_scripts[codetype][0])
|
||||
# this updates the database right away too
|
||||
obj.ndb.evlang.add(codetype, codestring, scripter=caller)
|
||||
if oldcode:
|
||||
caller.msg("{wReplaced{n\n %s\n{wWith{n\n %s" % (oldcode, codestring))
|
||||
else:
|
||||
caller.msg("Code added in '%s':\n %s" % (codetype, codestring))
|
||||
if "debug" in self.switches:
|
||||
# debug mode
|
||||
caller.msg("{wDebug: running script (look out for errors below) ...{n\n" + "-"*68)
|
||||
obj.ndb.evlang.run_by_name(codetype, caller, quiet=False)
|
||||
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue