[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/ Implement untrusted
traveral for page templates.
Fred L. Drake, Jr.
fred at zope.com
Fri Jul 23 12:16:30 EDT 2004
Log message for revision 26704:
Implement untrusted traveral for page templates.
- Use separate subclasses of PathExpr to implement path expressions
for trusted and untrusted templates. The untrusted class uses a new
traversal function that makes sure the result at each step is
wrapped in the appropriate security proxy.
- Add missing security declarations in a couple of tests.
Changed:
U Zope3/trunk/src/zope/app/pagetemplate/engine.py
U Zope3/trunk/src/zope/app/traversing/ftests/test_vhosting.py
U Zope3/trunk/src/zope/app/zptpage/tests/test_zptpage.py
-=-
Modified: Zope3/trunk/src/zope/app/pagetemplate/engine.py
===================================================================
--- Zope3/trunk/src/zope/app/pagetemplate/engine.py 2004-07-23 14:50:20 UTC (rev 26703)
+++ Zope3/trunk/src/zope/app/pagetemplate/engine.py 2004-07-23 16:16:30 UTC (rev 26704)
@@ -36,19 +36,26 @@
from zope.app import zapi
from zope.app.i18n import ZopeMessageIDFactory as _
-from zope.app.traversing.adapters import Traverser
+from zope.app.traversing.adapters import Traverser, traversePathElement
from zope.app.traversing.interfaces import IPathAdapter, ITraversable
class InlineCodeError(Exception):
pass
+
def zopeTraverser(object, path_items, econtext):
"""Traverses a sequence of names, first trying attributes then items.
"""
- traverser = Traverser(object)
- return traverser.traverse(path_items,
- request=getattr(econtext, 'request', None))
+ request = getattr(econtext, 'request', None)
+ path_items = list(path_items)
+ path_items.reverse()
+ while path_items:
+ name = path_items.pop()
+ object = traversePathElement(object, name, path_items,
+ request=request)
+ object = ProxyFactory(object)
+ return object
class ZopePathExpr(PathExpr):
@@ -56,6 +63,20 @@
super(ZopePathExpr, self).__init__(name, expr, engine, zopeTraverser)
+def trustedZopeTraverser(object, path_items, econtext):
+ """Traverses a sequence of names, first trying attributes then items.
+ """
+ traverser = Traverser(object)
+ return traverser.traverse(path_items,
+ request=getattr(econtext, 'request', None))
+
+class TrustedZopePathExpr(PathExpr):
+
+ def __init__(self, name, expr, engine):
+ super(TrustedZopePathExpr, self).__init__(name, expr, engine,
+ trustedZopeTraverser)
+
+
# Create a version of the restricted built-ins that uses a safe
# version of getattr() that wraps values in security proxies where
# appropriate:
@@ -196,6 +217,7 @@
self.namespaces[name] = namespace
return namespace
+
class ZopeEngine(ExpressionEngine):
"""Untrusted expression engine.
@@ -237,6 +259,54 @@
>>> type(r)
<type 'zope.security._proxy._Proxy'>
+ General path expressions provide objects that are wrapped in
+ security proxies as well::
+
+ >>> from zope.app.container.sample import SampleContainer
+ >>> from zope.app.tests.placelesssetup import setUp, tearDown
+ >>> from zope.security.checker import NamesChecker, defineChecker
+
+ >>> class Container(SampleContainer):
+ ... implements(ITraversable)
+ ... def traverse(self, name, further_path):
+ ... return self[name]
+
+ >>> setUp()
+ >>> defineChecker(Container, NamesChecker(['traverse']))
+ >>> d = engine.getBaseNames()
+ >>> foo = Container()
+ >>> foo.__name__ = 'foo'
+ >>> d['foo'] = ProxyFactory(foo)
+ >>> foo['bar'] = bar = Container()
+ >>> bar.__name__ = 'bar'
+ >>> bar.__parent__ = foo
+ >>> bar['baz'] = baz = Container()
+ >>> baz.__name__ = 'baz'
+ >>> baz.__parent__ = bar
+ >>> context = engine.getContext(d)
+
+ >>> o1 = context.evaluate('foo/bar')
+ >>> o1.__name__
+ 'bar'
+ >>> type(o1)
+ <type 'zope.security._proxy._Proxy'>
+
+ >>> o2 = context.evaluate('foo/bar/baz')
+ >>> o2.__name__
+ 'baz'
+ >>> type(o2)
+ <type 'zope.security._proxy._Proxy'>
+ >>> o3 = o2.__parent__
+ >>> type(o3)
+ <type 'zope.security._proxy._Proxy'>
+ >>> o1 == o3
+ True
+
+ >>> o1 is o2
+ False
+
+ >>> tearDown()
+
"""
_create_context = ZopeContext
@@ -312,7 +382,7 @@
def _Engine(engine=None):
if engine is None:
engine = ZopeEngine()
- engine = _create_base_engine(engine)
+ engine = _create_base_engine(engine, ZopePathExpr)
engine.registerType('python', ZopePythonExpr)
# Using a proxy around sys.modules allows page templates to use
@@ -326,14 +396,14 @@
def _TrustedEngine(engine=None):
if engine is None:
engine = TrustedZopeEngine()
- engine = _create_base_engine(engine)
+ engine = _create_base_engine(engine, TrustedZopePathExpr)
engine.registerType('python', PythonExpr)
engine.registerBaseName('modules', TraversableModuleImporter())
return engine
-def _create_base_engine(engine):
- for pt in ZopePathExpr._default_type_names:
- engine.registerType(pt, ZopePathExpr)
+def _create_base_engine(engine, pathtype):
+ for pt in pathtype._default_type_names:
+ engine.registerType(pt, pathtype)
engine.registerType('string', StringExpr)
engine.registerType('not', NotExpr)
engine.registerType('defer', DeferExpr)
Modified: Zope3/trunk/src/zope/app/traversing/ftests/test_vhosting.py
===================================================================
--- Zope3/trunk/src/zope/app/traversing/ftests/test_vhosting.py 2004-07-23 14:50:20 UTC (rev 26703)
+++ Zope3/trunk/src/zope/app/traversing/ftests/test_vhosting.py 2004-07-23 16:16:30 UTC (rev 26704)
@@ -22,7 +22,7 @@
from transaction import get_transaction
from zope.app.publisher.browser.resource import Resource
from zope.app.traversing.api import traverse
-from zope.security.checker import defineChecker, NoProxy
+from zope.security.checker import defineChecker, NamesChecker, NoProxy
from zope.app.container.contained import Contained
from zope.app.zptpage.zptpage import ZPTPage
@@ -125,6 +125,7 @@
def test_resources(self):
ztapi.browserResource('quux', Resource)
+ defineChecker(Resource, NamesChecker(['__call__']))
self.addPage('/foo/bar/pt',
u'<span tal:replace="context/++resource++quux" />')
self.verify('/foo/bar/pt', 'http://localhost/@@/quux\n')
Modified: Zope3/trunk/src/zope/app/zptpage/tests/test_zptpage.py
===================================================================
--- Zope3/trunk/src/zope/app/zptpage/tests/test_zptpage.py 2004-07-23 14:50:20 UTC (rev 26703)
+++ Zope3/trunk/src/zope/app/zptpage/tests/test_zptpage.py 2004-07-23 16:16:30 UTC (rev 26704)
@@ -110,6 +110,8 @@
return 'None'
return name
+ defineChecker(AU, NamesChecker(['__str__']))
+
from zope.app.traversing.namespace import view
ztapi.provideNamespaceHandler('view', view)
ztapi.browserView(IZPTPage, 'name', AU)
More information about the Zope3-Checkins
mailing list