Commit 2e153b46 authored by Evan Simpson's avatar Evan Simpson

Fix Collector #581, with unit test.

Tidy up inconsistency use of getattr/guarded_getattr.
parent baa8fbb1
......@@ -6,6 +6,12 @@ Zope Changes
Bugs Fixed
- Collector #581: TALES Path traversal should not special-case a blank
string in the second element position. It now skips directly
to item access when a path element is blank or has a leading '_'.
- Fixed inconsistent attribute access in TALES Paths.
- Collector #587: fixed wrong migration to string methods in
DTMLMethod.py
......
......@@ -17,7 +17,7 @@ Page Template-specific implementation of TALES, with handlers
for Python expressions, string literals, and paths.
"""
__version__='$Revision: 1.41 $'[11:-2]
__version__='$Revision: 1.42 $'[11:-2]
import re, sys
from TALES import Engine, CompilerError, _valid_name, NAME_RE, \
......@@ -291,13 +291,6 @@ def restrictedTraverse(object, path, securityManager,
get=getattr, has=hasattr, N=None, M=[],
TupleType=type(()) ):
if not path[0]:
# If the path starts with an empty string, go to the root first.
object = object.getPhysicalRoot()
if not securityManager.validateValue(object):
raise Unauthorized
path.pop(0)
REQUEST = {'path': path}
REQUEST['TraversalRequestNameStack'] = path = path[:] # Copy!
path.reverse()
......@@ -310,9 +303,14 @@ def restrictedTraverse(object, path, securityManager,
object = object(*name)
continue
if name[0] == '_':
# Never allowed in a URL.
raise AttributeError, name
if not name or name[0] == '_':
# Skip directly to item access
o = object[name]
# Check access to the item.
if not validate(object, object, name, o):
raise Unauthorized, name
object = o
continue
if name=='..':
o = get(object, 'aq_parent', M)
......@@ -333,8 +331,7 @@ def restrictedTraverse(object, path, securityManager,
container = aq_parent(aq_inner(o))
elif has(o, 'im_self'):
container = o.im_self
elif (has(get(object, 'aq_base', object), name)
and get(object, name) == o):
elif (has(aq_base(object), name) and get(object, name) == o):
container = object
if not validate(object, container, name, o):
raise Unauthorized, name
......@@ -354,14 +351,14 @@ def restrictedTraverse(object, path, securityManager,
# Try to re-raise the original attribute error.
# XXX I think this only happens with
# ExtensionClass instances.
get(object, name)
guarded_getattr(object, name)
raise
except TypeError, exc:
if str(exc).find('unsubscriptable') >= 0:
# The object does not support the item interface.
# Try to re-raise the original attribute error.
# XXX This is sooooo ugly.
get(object, name)
guarded_getattr(object, name)
raise
else:
# Check access to the item.
......
......@@ -4,9 +4,20 @@ from Products.PageTemplates import Expressions
class ExpressionTests(unittest.TestCase):
def setUp(self):
self.e = e = Expressions.getEngine()
self.ec = e.getContext(
one = 1,
d = {'one': 1, 'b': 'b', '': 'blank', '_': 'under'},
blank = '',
)
def tearDown(self):
del self.e, self.ec
def testCompile(self):
'''Test expression compilation'''
e = Expressions.getEngine()
e = self.e
for p in ('x', 'x/y', 'x/y/z'):
e.compile(p)
e.compile('path:a|b|c/d/e')
......@@ -16,6 +27,22 @@ class ExpressionTests(unittest.TestCase):
e.compile('python: 2 + 2')
e.compile('python: 2 \n+\n 2\n')
def testSimpleEval(self):
'''Test simple expression evaluation'''
ec = self.ec
assert ec.evaluate('one') == 1
assert ec.evaluate('d/one') == 1
assert ec.evaluate('d/b') == 'b'
def testEval1(self):
'''Test advanced expression evaluation 1'''
ec = self.ec
assert ec.evaluate('x | nothing') is None
assert ec.evaluate('d/') == 'blank'
assert ec.evaluate('d/_') == 'under'
assert ec.evaluate('d/ | nothing') == 'blank'
assert ec.evaluate('d/?blank') == 'blank'
def test_suite():
return unittest.makeSuite(ExpressionTests)
......
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