"""Restricted execution facilities.

The class RExec exports methods r_exec(), r_eval(), r_execfile(), and
r_import(), which correspond roughly to the built-in operations
exec, eval(), execfile() and import, but executing the code in an
environment that only exposes those built-in operations that are
deemed safe.  To this end, a modest collection of 'fake' modules is
created which mimics the standard modules by the same names.  It is a
policy decision which built-in modules and operations are made
available; this module provides a reasonable default, but derived
classes can change the policies e.g. by overriding or extending class
variables like ok_builtin_modules or methods like make_sys().

XXX To do:
- r_open should allow writing tmp dir
- r_exec etc. with explicit globals/locals? (Use rexec("exec ... in ...")?)

"""
from warnings import warnpy3k
warnpy3k("the rexec module has been removed in Python 3.0", stacklevel=2)
del warnpy3k


import sys
import __builtin__
import os
import ihooks
import imp

__all__ = ["RExec"]

class FileBase:

    ok_file_methods = ('fileno', 'flush', 'isatty', 'read', 'readline',
            'readlines', 'seek', 'tell', 'write', 'writelines', 'xreadlines',
            '__iter__')


class FileWrapper(FileBase):

    # XXX This is just like a Bastion -- should use that!

    def __init__(self, f):
        for m in self.ok_file_methods:
            if not hasattr(self, m) and hasattr(f, m):
                setattr(self, m, getattr(f, m))

    def close(self):
        self.flush()


TEMPLATE = """
def %s(self, *args):
        return getattr(self.mod, self.name).%s(*args)
"""

class FileDelegate(FileBase):

    def __init__(self, mod, name):
        self.mod = mod
        self.name = name

    for m in FileBase.ok_file_methods + ('close',):
        exec TEMPLATE % (m, m)


class RHooks(ihooks.Hooks):

    def __init__(self, *args):
        # Hacks to support both old and new interfaces:
        # old interface was RHooks(rexec[, verbose])
        # new interface is RHooks([verbose])
        verbose = 0
        rexec = None
        if args and type(args[-1]) == type(0):
            verbose = args[-1]
            args = args[:-1]
        if args and hasattr(args[0], '__class__'):
            rexec = args[0]
            args = args[1:]
        if args:
            raise TypeError, "too many arguments"
        ihooks.Hooks.__init__(self, verbose)
        self.rexec = rexec

    def set_rexec(self, rexec):
        # Called by RExec instance to complete initialization
        self.rexec = rexec

    def get_suffixes(self):
        return self.rexec.get_suffixes()

    def is_builtin(self, name):
        return self.rexec.is_builtin(name)

    def init_builtin(self, name):
        m = __import__(name)
        return self.rexec.copy_except(m, ())

    def init_frozen(self, name): raise SystemError, "don't use this"
    def load_source(self, *args): raise SystemError, "don't use this"
    def load_compiled(self, *args): raise SystemError, "don't use this"
    def load_package(self, *args): raise SystemError, "don't use this"

    def load_dynamic(self, name, filename, file):
        return self.rexec.load_dynamic(name, filename, file)

    def add_module(self, name):
        return self.rexec.add_module(name)

    def modules_dict(self):
        return self.rexec.modules

    def default_path(self):
        return self.rexec.modules['sys'].path


# XXX Backwards compatibility
RModuleLoader = ihooks.FancyModuleLoader
RModuleImporter = ihooks.ModuleImporter


class RExec(ihooks._Verbose):
    """Basic restricted execution framework.

    Code executed in this restricted environment will only have access to
    modules and functions that are deemed safe; you can subclass RExec to
    add or remove capabilities as desired.

    The RExec class can prevent code from performing unsafe operations like
    reading or writing disk files, or using TCP/IP sockets.  However, it does
    not protect against code using extremely large amounts of memory or
    processor time.

    """

    ok_path = tuple(sys.path)           # That's a policy decision

    ok_builtin_modules = ('audioop', 'array', 'binascii',
                          'cmath', 'errno', 'imageop',
                          'marshal', 'math', 'md5', 'operator',
                          'parser', 'select',
                          'sha', '_sre', 'strop', 'struct', 'time',
                          '_weakref')

    ok_posix_names = ('error', 'fstat', 'listdir', 'lstat', 'readlink',
                      'stat', 'times', 'uname', 'getpid', 'getppid',
                      'getcwd', 'getuid', 'getgid', 'geteuid', 'getegid')

    ok_sys_names = ('byteorder', 'copyright', 'exit', 'getdefaultencoding',
                    'getrefcount', 'hexversion', 'maxint', 'maxunicode',
                    'platform', 'ps1', 'ps2', 'version', 'version_info')

    nok_builtin_names = ('open', 'file', 'reload', '__import__')

    ok_file_types = (imp.C_EXTENSION, imp.PY_SOURCE)

    def __init__(self, hooks = None, verbose = 0):
        """Returns an instance of the RExec class.

        The hooks parameter is an instance of the RHooks class or a subclass
        of it.  If it is omitted or None, the default RHooks class is
        instantiated.

        Whenever the RExec module searches for a module (even a built-in one)
        or reads a module's code, it doesn't actually go out to the file
        system itself.  Rather, it calls methods of an RHooks instance that
        was passed to or created by its constructor.  (Actually, the RExec
        object doesn't make these calls --- they are made by a module loader
        object that's part of the RExec object.  This allows another level of
        flexibility, which can be useful when changing the mechanics of
        import within the restricted environment.)

        By providing an alternate RHooks object, we can control the file
        system accesses made to import a module, without changing the
        actual algorithm that controls the order in which those accesses are
        made.  For instance, we could substitute an RHooks object that
        passes all filesystem requests to a file server elsewhere, via some
        RPC mechanism such as ILU.  Grail's applet loader uses this to support
        importing applets from a URL for a directory.

        If the verbose parameter is true, additional debugging output may be
        sent to standard output.

        """

        raise RuntimeError, "This code is not secure in Python 2.2 and later"

        ihooks._Verbose.__init__(self, verbose)
        # XXX There's a circular reference here:
        self.hooks = hooks or RHooks(verbose)
        self.hooks.set_rexec(self)
        self.modules = {}
        self.ok_dynamic_modules = self.ok_builtin_modules
        list = []
        for mname in self.ok_builtin_modules:
            if mname in sys.builtin_module_names:
                list.append(mname)
        self.ok_builtin_modules = tuple(list)
        self.set_trusted_path()
        self.make_builtin()
        self.make_initial_modules()
        # make_sys must be last because it adds the already created
        # modules to its builtin_module_names
        self.make_sys()
        self.loader = RModuleLoader(self.hooks, verbose)
        self.importer = RModuleImporter(self.loader, verbose)

    def set_trusted_path(self):
        # Set the path from which dynamic modules may be loaded.
        # Those dynamic modules must also occur in ok_builtin_modules
        self.trusted_path = filter(os.path.isabs, sys.path)

    def load_dynamic(self, name, filename, file):
        if name not in self.ok_dynamic_modules:
            raise ImportError, "untrusted dynamic module: %s" % name
        if name in sys.modules:
            src = sys.modules[name]
        else:
            src = imp.load_dynamic(name, filename, file)
        dst = self.copy_except(src, [])
        return dst

    def make_initial_modules(self):
        self.make_main()
        self.make_osname()

    # Helpers for RHooks

    def get_suffixes(self):
        return [item   # (suff, mode, type)
                for item in imp.get_suffixes()
                if item[2] in self.ok_file_types]

    def is_builtin(self, mname):
        return mname in self.ok_builtin_modules

    # The make_* methods create specific built-in modules

    def make_builtin(self):
        m = self.copy_except(__builtin__, self.nok_builtin_names)
        m.__import__ = self.r_import
        m.reload = self.r_reload
        m.open = m.file = self.r_open

    def make_main(self):
        self.add_module('__main__')

    def make_osname(self):
        osname = os.name
        src = __import__(osname)
        dst = self.copy_only(src, self.ok_posix_names)
        dst.environ = e = {}
        for key, value in os.environ.items():
            e[key] = value

    def make_sys(self):
        m = self.copy_only(sys, self.ok_sys_names)
        m.modules = self.modules
        m.argv = ['RESTRICTED']
        m.path = map(None, self.ok_path)
        m.exc_info = self.r_exc_info
        m = self.modules['sys']
        l = self.modules.keys() + list(self.ok_builtin_modules)
        l.sort()
        m.builtin_module_names = tuple(l)

    # The copy_* methods copy existing modules with some changes

    def copy_except(self, src, exceptions):
        dst = self.copy_none(src)
        for name in dir(src):
            setattr(dst, name, getattr(src, name))
        for name in exceptions:
            try:
                delattr(dst, name)
            except AttributeError:
                pass
        return dst

    def copy_only(self, src, names):
        dst = self.copy_none(src)
        for name in names:
            try:
                value = getattr(src, name)
            except AttributeError:
                continue
            setattr(dst, name, value)
        return dst

    def copy_none(self, src):
        m = self.add_module(src.__name__)
        m.__doc__ = src.__doc__
        return m

    # Add a module -- return an existing module or create one

    def add_module(self, mname):
        m = self.modules.get(mname)
        if m is None:
            self.modules[mname] = m = self.hooks.new_module(mname)
        m.__builtins__ = self.modules['__builtin__']
        return m

    # The r* methods are public interfaces

    def r_exec(self, code):
        """Execute code within a restricted environment.

        The code parameter must either be a string containing one or more
        lines of Python code, or a compiled code object, which will be
        executed in the restricted environment's __main__ module.

        """
        m = self.add_module('__main__')
        exec code in m.__dict__

    def r_eval(self, code):
        """Evaluate code within a restricted environment.

        The code parameter must either be a string containing a Python
        expression, or a compiled code object, which will be evaluated in
        the restricted environment's __main__ module.  The value of the
        expression or code object will be returned.

        """
        m = self.add_module('__main__')
        return eval(code, m.__dict__)

    def r_execfile(self, file):
        """Execute the Python code in the file in the restricted
        environment's __main__ module.

        """
        m = self.add_module('__main__')
        execfile(file, m.__dict__)

    def r_import(self, mname, globals={}, locals={}, fromlist=[]):
        """Import a module, raising an ImportError exception if the module
        is considered unsafe.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        """
        return self.importer.import_module(mname, globals, locals, fromlist)

    def r_reload(self, m):
        """Reload the module object, re-parsing and re-initializing it.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        """
        return self.importer.reload(m)

    def r_unload(self, m):
        """Unload the module.

        Removes it from the restricted environment's sys.modules dictionary.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        """
        return self.importer.unload(m)

    # The s_* methods are similar but also swap std{in,out,err}

    def make_delegate_files(self):
        s = self.modules['sys']
        self.delegate_stdin = FileDelegate(s, 'stdin')
        self.delegate_stdout = FileDelegate(s, 'stdout')
        self.delegate_stderr = FileDelegate(s, 'stderr')
        self.restricted_stdin = FileWrapper(sys.stdin)
        self.restricted_stdout = FileWrapper(sys.stdout)
        self.restricted_stderr = FileWrapper(sys.stderr)

    def set_files(self):
        if not hasattr(self, 'save_stdin'):
            self.save_files()
        if not hasattr(self, 'delegate_stdin'):
            self.make_delegate_files()
        s = self.modules['sys']
        s.stdin = self.restricted_stdin
        s.stdout = self.restricted_stdout
        s.stderr = self.restricted_stderr
        sys.stdin = self.delegate_stdin
        sys.stdout = self.delegate_stdout
        sys.stderr = self.delegate_stderr

    def reset_files(self):
        self.restore_files()
        s = self.modules['sys']
        self.restricted_stdin = s.stdin
        self.restricted_stdout = s.stdout
        self.restricted_stderr = s.stderr


    def save_files(self):
        self.save_stdin = sys.stdin
        self.save_stdout = sys.stdout
        self.save_stderr = sys.stderr

    def restore_files(self):
        sys.stdin = self.save_stdin
        sys.stdout = self.save_stdout
        sys.stderr = self.save_stderr

    def s_apply(self, func, args=(), kw={}):
        self.save_files()
        try:
            self.set_files()
            r = func(*args, **kw)
        finally:
            self.restore_files()
        return r

    def s_exec(self, *args):
        """Execute code within a restricted environment.

        Similar to the r_exec() method, but the code will be granted access
        to restricted versions of the standard I/O streams sys.stdin,
        sys.stderr, and sys.stdout.

        The code parameter must either be a string containing one or more
        lines of Python code, or a compiled code object, which will be
        executed in the restricted environment's __main__ module.

        """
        return self.s_apply(self.r_exec, args)

    def s_eval(self, *args):
        """Evaluate code within a restricted environment.

        Similar to the r_eval() method, but the code will be granted access
        to restricted versions of the standard I/O streams sys.stdin,
        sys.stderr, and sys.stdout.

        The code parameter must either be a string containing a Python
        expression, or a compiled code object, which will be evaluated in
        the restricted environment's __main__ module.  The value of the
        expression or code object will be returned.

        """
        return self.s_apply(self.r_eval, args)

    def s_execfile(self, *args):
        """Execute the Python code in the file in the restricted
        environment's __main__ module.

        Similar to the r_execfile() method, but the code will be granted
        access to restricted versions of the standard I/O streams sys.stdin,
        sys.stderr, and sys.stdout.

        """
        return self.s_apply(self.r_execfile, args)

    def s_import(self, *args):
        """Import a module, raising an ImportError exception if the module
        is considered unsafe.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        Similar to the r_import() method, but has access to restricted
        versions of the standard I/O streams sys.stdin, sys.stderr, and
        sys.stdout.

        """
        return self.s_apply(self.r_import, args)

    def s_reload(self, *args):
        """Reload the module object, re-parsing and re-initializing it.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        Similar to the r_reload() method, but has access to restricted
        versions of the standard I/O streams sys.stdin, sys.stderr, and
        sys.stdout.

        """
        return self.s_apply(self.r_reload, args)

    def s_unload(self, *args):
        """Unload the module.

        Removes it from the restricted environment's sys.modules dictionary.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        Similar to the r_unload() method, but has access to restricted
        versions of the standard I/O streams sys.stdin, sys.stderr, and
        sys.stdout.

        """
        return self.s_apply(self.r_unload, args)

    # Restricted open(...)

    def r_open(self, file, mode='r', buf=-1):
        """Method called when open() is called in the restricted environment.

        The arguments are identical to those of the open() function, and a
        file object (or a class instance compatible with file objects)
        should be returned.  RExec's default behaviour is allow opening
        any file for reading, but forbidding any attempt to write a file.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        """
        mode = str(mode)
        if mode not in ('r', 'rb'):
            raise IOError, "can't open files for writing in restricted mode"
        return open(file, mode, buf)

    # Restricted version of sys.exc_info()

    def r_exc_info(self):
        ty, va, tr = sys.exc_info()
        tr = None
        return ty, va, tr


def test():
    import getopt, traceback
    opts, args = getopt.getopt(sys.argv[1:], 'vt:')
    verbose = 0
    trusted = []
    for o, a in opts:
        if o == '-v':
            verbose = verbose+1
        if o == '-t':
            trusted.append(a)
    r = RExec(verbose=verbose)
    if trusted:
        r.ok_builtin_modules = r.ok_builtin_modules + tuple(trusted)
    if args:
        r.modules['sys'].argv = args
        r.modules['sys'].path.insert(0, os.path.dirname(args[0]))
    else:
        r.modules['sys'].path.insert(0, "")
    fp = sys.stdin
    if args and args[0] != '-':
        try:
            fp = open(args[0])
        except IOError, msg:
            print "%s: can't open file %r" % (sys.argv[0], args[0])
            return 1
    if fp.isatty():
        try:
            import readline
        except ImportError:
            pass
        import code
        class RestrictedConsole(code.InteractiveConsole):
            def runcode(self, co):
                self.locals['__builtins__'] = r.modules['__builtin__']
                r.s_apply(code.InteractiveConsole.runcode, (self, co))
        try:
            RestrictedConsole(r.modules['__main__'].__dict__).interact()
        except SystemExit, n:
            return n
    else:
        text = fp.read()
        fp.close()
        c = compile(text, fp.name, 'exec')
        try:
            r.s_exec(c)
        except SystemExit, n:
            return n
        except:
            traceback.print_exc()
            return 1


if __name__ == '__main__':
    sys.exit(test())
