Fix #2141: TALES doesn't traverse correctly over 'repeat' variable

parent baa7ef3b
......@@ -18,6 +18,9 @@ Zope Changes
Bugs Fixed
- Fix #2141: TALES doesn't traverse correctly over 'repeat'
variable
- reStructuredText/ZReST: setting raw_enabled to 0 for security
reasons
......
......@@ -28,6 +28,7 @@ from zope.proxy import removeAllProxies
import zope.app.pagetemplate.engine
import OFS.interfaces
from MultiMapping import MultiMapping
from Acquisition import aq_base
from zExceptions import NotFound, Unauthorized
from Products.Five.browser.providerexpression import Z2ProviderExpression
......@@ -140,8 +141,32 @@ class ZopePathExpr(PathExpr):
return 1
return 0
class SafeMapping(MultiMapping):
"""Mapping with security declarations and limited method exposure.
Since it subclasses MultiMapping, this class can be used to wrap
one or more mapping objects. Restricted Python code will not be
able to mutate the SafeMapping or the wrapped mappings, but will be
able to read any value.
"""
__allow_access_to_unprotected_subobjects__ = True
push = pop = None
_push = MultiMapping.push
_pop = MultiMapping.pop
class ZopeContext(Context):
def __init__(self, engine, contexts):
super(ZopeContext, self).__init__(engine, contexts)
# wrap the top-level 'repeat' variable, as it is visible to
# restricted code
self.setContext('repeat', SafeMapping(self.repeat_vars))
# regenerate the first scope and the scope stack after messing
# with the global context
self.vars = vars = contexts.copy()
self._vars_stack = [vars]
def translate(self, msgid, domain=None, mapping=None, default=None):
context = self.contexts.get('context')
return getGlobalTranslationService().translate(
......
......@@ -56,8 +56,6 @@ class PageTemplateFile(SimpleItem, Script, PageTemplate, Traversable):
security.declareProtected('View management screens',
'read', 'document_src')
_default_bindings = {'name_subpath': 'traverse_subpath'}
def __init__(self, filename, _prefix=None, **kw):
name = kw.pop('__name__', None)
......
......@@ -19,21 +19,7 @@ $Id$
from zope.tales.tests.simpleexpr import SimpleExpr
from zope.tales.tales import ExpressionEngine as Engine
from zope.tales.tales import _default as Default
from MultiMapping import MultiMapping
class SafeMapping(MultiMapping):
'''Mapping with security declarations and limited method exposure.
Since it subclasses MultiMapping, this class can be used to wrap
one or more mapping objects. Restricted Python code will not be
able to mutate the SafeMapping or the wrapped mappings, but will be
able to read any value.
'''
__allow_access_to_unprotected_subobjects__ = 1
push = pop = None
_push = MultiMapping.push
_pop = MultiMapping.pop
from Products.PageTemplates.Expressions import SafeMapping
import zope.deprecation
zope.deprecation.moved("zope.tales.tales", "2.12")
<html>
<body>
<ol tal:define="results python:range(5)">
<tal:block tal:repeat="items results">
<li tal:define="odd repeat/items/odd"
tal:content="python:odd and 'odd' or 'even'">Content</li>
</tal:block>
</ol>
</body>
</html>
<html>
<body>
<ol>
<li>even</li>
<li>odd</li>
<li>even</li>
<li>odd</li>
<li>even</li>
</ol>
</body>
</html>
......@@ -74,7 +74,7 @@ class ExpressionTests(zope.component.testing.PlacelessSetup, unittest.TestCase):
ec = self.ec
ec.beginScope()
ec.setRepeat('loop', "python:[1,2,3]")
assert ec.evaluate("python:repeat['loop'].even()")
assert ec.evaluate("python:repeat['loop'].odd()")
ec.endScope()
def testWrappers(self):
......
......@@ -165,6 +165,9 @@ class HTMLTests(zope.component.testing.PlacelessSetup, unittest.TestCase):
def checkImportOldStyleClass(self):
self.assert_expected(self.folder.t, 'CheckImportOldStyleClass.html')
def checkRepeatVariable(self):
self.assert_expected(self.folder.t, 'RepeatVariable.html')
def test_suite():
return unittest.makeSuite(HTMLTests, 'check')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment