[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/pagetemplate/ - add
tests for trusted and untrusted path:modules/... expressions
Fred L. Drake, Jr.
fred at zope.com
Wed Jul 21 12:02:21 EDT 2004
Log message for revision 26657:
- add tests for trusted and untrusted path:modules/... expressions
- make them actually work as advertised
(untrusted module import can raise KeyError instead of NotFoundErr or
some flavor of Forbidden; seems less than right)
- add docstrings
Changed:
U Zope3/trunk/src/zope/app/pagetemplate/engine.py
A Zope3/trunk/src/zope/app/pagetemplate/tests/trusted.py
-=-
Modified: Zope3/trunk/src/zope/app/pagetemplate/engine.py
===================================================================
--- Zope3/trunk/src/zope/app/pagetemplate/engine.py 2004-07-21 16:01:38 UTC (rev 26656)
+++ Zope3/trunk/src/zope/app/pagetemplate/engine.py 2004-07-21 16:02:21 UTC (rev 26657)
@@ -19,12 +19,15 @@
"""
import sys
+from zope.interface import implements
+
from zope.tales.expressions import PathExpr, StringExpr, NotExpr, DeferExpr
from zope.tales.expressions import SimpleModuleImporter
from zope.tales.pythonexpr import PythonExpr
from zope.tales.tales import ExpressionEngine, Context
from zope.component.exceptions import ComponentLookupError
+from zope.exceptions import NotFoundError
from zope.proxy import removeAllProxies
from zope.security.proxy import ProxyFactory
from zope.security.builtins import RestrictedBuiltins
@@ -33,7 +36,7 @@
from zope.app import zapi
from zope.app.i18n import ZopeMessageIDFactory as _
from zope.app.traversing.adapters import Traverser
-from zope.app.traversing.interfaces import IPathAdapter
+from zope.app.traversing.interfaces import IPathAdapter, ITraversable
class InlineCodeError(Exception):
pass
@@ -59,6 +62,7 @@
return eval(self._code, vars)
class ZopeContextBase(Context):
+ """Base class for both trusted and untrusted evaluation contexts."""
def evaluateText(self, expr):
text = self.evaluate(expr)
@@ -110,6 +114,7 @@
class ZopeContext(ZopeContextBase):
+ """Evaluation context for untrusted programs."""
def setContext(self, name, value):
# Hook to allow subclasses to do things like adding security proxies
@@ -117,7 +122,7 @@
class TrustedZopeContext(ZopeContextBase):
- pass
+ """Evaluation context for trusted programs."""
class AdapterNamespaces(object):
@@ -170,7 +175,38 @@
return namespace
class ZopeEngine(ExpressionEngine):
+ """Untrusted expression engine.
+ This engine does not allow modules to be imported; only modules
+ already available may be accessed::
+
+ >>> modname = 'zope.app.pagetemplate.tests.trusted'
+ >>> engine = _Engine()
+ >>> context = engine.getContext(engine.getBaseNames())
+
+ >>> modname in sys.modules
+ False
+ >>> context.evaluate('modules/' + modname)
+ Traceback (most recent call last):
+ ...
+ KeyError: 'zope.app.pagetemplate.tests.trusted'
+
+ (The use of KeyError is an unfortunate implementation detail; I
+ think this should be a NotFoundError.)
+
+ Modules which have already been imported by trusted code are
+ available, wrapped in security proxies::
+
+ >>> m = context.evaluate('modules/sys')
+ >>> m.__name__
+ 'sys'
+ >>> m._getframe
+ Traceback (most recent call last):
+ ...
+ ForbiddenAttribute: ('_getframe', <module 'sys' (built-in)>)
+
+ """
+
_create_context = ZopeContext
def __init__(self):
@@ -198,10 +234,49 @@
class TrustedZopeEngine(ZopeEngine):
+ """Trusted expression engine.
+ This engine allows modules to be imported::
+
+ >>> modname = 'zope.app.pagetemplate.tests.trusted'
+ >>> engine = _TrustedEngine()
+ >>> context = engine.getContext(engine.getBaseNames())
+
+ >>> modname in sys.modules
+ False
+ >>> m = context.evaluate('modules/' + modname)
+ >>> m.__name__ == modname
+ True
+ >>> modname in sys.modules
+ True
+
+ Since this is trusted code, we can look at whatever is in the
+ module, not just __name__ or what's declared in a security
+ assertion::
+
+ >>> m.x
+ 42
+
+ Clean up after ourselves::
+
+ >>> del sys.modules[modname]
+
+ """
+
_create_context = TrustedZopeContext
+class TraversableModuleImporter(SimpleModuleImporter):
+
+ implements(ITraversable)
+
+ def traverse(self, name, further_path):
+ try:
+ return self[name]
+ except KeyError:
+ raise NotFoundError(name)
+
+
def _Engine(engine=None):
if engine is None:
engine = ZopeEngine()
@@ -221,7 +296,7 @@
engine = TrustedZopeEngine()
engine = _create_base_engine(engine)
engine.registerType('python', PythonExpr)
- engine.registerBaseName('modules', SimpleModuleImporter())
+ engine.registerBaseName('modules', TraversableModuleImporter())
return engine
def _create_base_engine(engine):
Added: Zope3/trunk/src/zope/app/pagetemplate/tests/trusted.py
===================================================================
--- Zope3/trunk/src/zope/app/pagetemplate/tests/trusted.py 2004-07-21 16:01:38 UTC (rev 26656)
+++ Zope3/trunk/src/zope/app/pagetemplate/tests/trusted.py 2004-07-21 16:02:21 UTC (rev 26657)
@@ -0,0 +1,22 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Sample of a module imported by a trusted module.
+
+This module won't be imported by an untrusted template using a
+path:modules/... expression.
+
+$Id$
+"""
+
+x = 42
Property changes on: Zope3/trunk/src/zope/app/pagetemplate/tests/trusted.py
___________________________________________________________________
Name: svn:mime-type
+ text/x-python
Name: svn:eol-style
+ native
More information about the Zope3-Checkins
mailing list