11##############################################################################
22#
33# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
4- #
4+ #
55# This software is subject to the provisions of the Zope Public License,
66# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
77# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
88# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
99# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
1010# FOR A PARTICULAR PURPOSE
11- #
11+ #
1212##############################################################################
13+ # Modified for Roundup:
14+ #
15+ # 1. Removed all Zope-specific code (doesn't even try to import that stuff now)
16+ # 2. Removed all Acquisition
1317
1418"""Page Template Expression Engine
1519
1620Page Template-specific implementation of TALES, with handlers
1721for Python expressions, string literals, and paths.
18-
19-
20- Modified for Roundup 0.5 release:
21-
22- - Removed all Zope-specific code (doesn't even try to import that stuff now)
23- - Removed all Acquisition
24- - Made traceback info more informative
25-
2622"""
27- __docformat__ = 'restructuredtext'
2823
29- __version__ = '$Revision: 1.9 $' [11 :- 2 ]
24+ __version__ = '$Revision: 1.10 $' [11 :- 2 ]
3025
3126import re , sys
3227from TALES import Engine , CompilerError , _valid_name , NAME_RE , \
3328 Undefined , Default , _parse_expr
34- from string import strip , split , join , replace , lstrip
29+
3530
3631_engine = None
3732def getEngine ():
@@ -53,10 +48,17 @@ def installHandlers(engine):
5348 reg ('defer' , DeferExpr )
5449
5550from PythonExpr import getSecurityManager , PythonExpr
51+ guarded_getattr = getattr
5652try :
5753 from zExceptions import Unauthorized
5854except ImportError :
5955 Unauthorized = "Unauthorized"
56+
57+ def acquisition_security_filter (orig , inst , name , v , real_validate ):
58+ if real_validate (orig , inst , name , v ):
59+ return 1
60+ raise Unauthorized , name
61+
6062def call_with_ns (f , ns , arg = 1 ):
6163 if arg == 2 :
6264 return f (None , ns )
@@ -70,6 +72,8 @@ def __getitem__(self, module):
7072 __import__ (module )
7173 return sys .modules [module ]
7274
75+ SecureModuleImporter = _SecureModuleImporter ()
76+
7377Undefs = (Undefined , AttributeError , KeyError ,
7478 TypeError , IndexError , Unauthorized )
7579
@@ -95,9 +99,9 @@ def render(ob, ns):
9599
96100class SubPathExpr :
97101 def __init__ (self , path ):
98- self ._path = path = split ( strip (path ), '/' )
102+ self ._path = path = path . strip (). split ( '/' )
99103 self ._base = base = path .pop (0 )
100- if not _valid_name (base ):
104+ if base and not _valid_name (base ):
101105 raise CompilerError , 'Invalid variable name "%s"' % base
102106 # Parse path
103107 self ._dp = dp = []
@@ -123,7 +127,7 @@ def _eval(self, econtext,
123127 path [i :i + 1 ] = list (val )
124128 base = self ._base
125129 __traceback_info__ = 'path expression "%s"' % ('/' .join (self ._path ))
126- if base == 'CONTEXTS' :
130+ if base == 'CONTEXTS' or not base :
127131 ob = econtext .contexts
128132 else :
129133 ob = vars [base ]
@@ -138,15 +142,15 @@ def __init__(self, name, expr, engine):
138142 self ._s = expr
139143 self ._name = name
140144 self ._hybrid = 0
141- paths = split (expr , '|' )
145+ paths = expr . split ('|' )
142146 self ._subexprs = []
143147 add = self ._subexprs .append
144148 for i in range (len (paths )):
145- path = lstrip ( paths [i ])
149+ path = paths [i ]. lstrip ( )
146150 if _parse_expr (path ):
147151 # This part is the start of another expression type,
148152 # so glue it back together and compile it.
149- add (engine .compile (lstrip ( join (paths [i :], '|' ))))
153+ add (engine .compile (( '|' . join (paths [i :]). lstrip ( ))))
150154 self ._hybrid = 1
151155 break
152156 add (SubPathExpr (path )._eval )
@@ -194,18 +198,18 @@ def __str__(self):
194198 def __repr__ (self ):
195199 return '%s:%s' % (self ._name , `self._s` )
196200
197-
198- _interp = re .compile (r'\$(%(n)s)|\${(%(n)s(?:/%(n)s )*)}' % {'n' : NAME_RE })
201+
202+ _interp = re .compile (r'\$(%(n)s)|\${(%(n)s(?:/[^}]* )*)}' % {'n' : NAME_RE })
199203
200204class StringExpr :
201205 def __init__ (self , name , expr , engine ):
202206 self ._s = expr
203207 if '%' in expr :
204- expr = replace (expr , '%' , '%%' )
208+ expr = expr . replace ('%' , '%%' )
205209 self ._vars = vars = []
206210 if '$' in expr :
207211 parts = []
208- for exp in split (expr , '$$' ):
212+ for exp in expr . split ('$$' ):
209213 if parts : parts .append ('$' )
210214 m = _interp .search (exp )
211215 while m is not None :
@@ -219,15 +223,16 @@ def __init__(self, name, expr, engine):
219223 raise CompilerError , (
220224 '$ must be doubled or followed by a simple path' )
221225 parts .append (exp )
222- expr = join (parts , '' )
226+ expr = '' . join (parts )
223227 self ._expr = expr
224-
228+
225229 def __call__ (self , econtext ):
226230 vvals = []
227231 for var in self ._vars :
228232 v = var (econtext )
229- if isinstance (v , Exception ):
230- raise v
233+ # I hope this isn't in use anymore.
234+ ## if isinstance(v, Exception):
235+ ## raise v
231236 vvals .append (v )
232237 return self ._expr % tuple (vvals )
233238
@@ -239,11 +244,14 @@ def __repr__(self):
239244
240245class NotExpr :
241246 def __init__ (self , name , expr , compiler ):
242- self ._s = expr = lstrip (expr )
247+ self ._s = expr = expr . lstrip ()
243248 self ._c = compiler .compile (expr )
244-
249+
245250 def __call__ (self , econtext ):
246- return not econtext .evaluateBoolean (self ._c )
251+ # We use the (not x) and 1 or 0 formulation to avoid changing
252+ # the representation of the result in Python 2.3, where the
253+ # result of "not" becomes an instance of bool.
254+ return (not econtext .evaluateBoolean (self ._c )) and 1 or 0
247255
248256 def __repr__ (self ):
249257 return 'not:%s' % `self._s`
@@ -261,53 +269,45 @@ def __call__(self):
261269
262270class DeferExpr :
263271 def __init__ (self , name , expr , compiler ):
264- self ._s = expr = lstrip (expr )
272+ self ._s = expr = expr . lstrip ()
265273 self ._c = compiler .compile (expr )
266-
274+
267275 def __call__ (self , econtext ):
268276 return DeferWrapper (self ._c , econtext )
269277
270278 def __repr__ (self ):
271279 return 'defer:%s' % `self._s`
272280
273- class TraversalError :
274- def __init__ (self , path , name ):
275- self .path = path
276- self .name = name
277281
278- def restrictedTraverse (self , path , securityManager ,
282+ def restrictedTraverse (object , path , securityManager ,
279283 get = getattr , has = hasattr , N = None , M = [],
280284 TupleType = type (()) ):
281285
282286 REQUEST = {'path' : path }
283287 REQUEST ['TraversalRequestNameStack' ] = path = path [:] # Copy!
284- if not path [0 ]:
285- # If the path starts with an empty string, go to the root first.
286- self = self .getPhysicalRoot ()
287- path .pop (0 )
288-
289288 path .reverse ()
290- object = self
291- #print 'TRAVERSE', (object, path)
292- done = []
289+ validate = securityManager .validate
290+ __traceback_info__ = REQUEST
293291 while path :
294292 name = path .pop ()
295- __traceback_info__ = TraversalError (done , name )
296293
297- # if isinstance(name, TupleType):
298- # object = apply( object, name)
299- # continue
294+ if isinstance (name , TupleType ):
295+ object = object ( * name )
296+ continue
300297
301- # if name[0] == '_':
302- # # Never allowed in a URL.
303- # raise AttributeError, name
298+ if not name :
299+ # Skip directly to item access
300+ o = object [name ]
301+ # Check access to the item.
302+ if not validate (object , object , name , o ):
303+ raise Unauthorized , name
304+ object = o
305+ continue
304306
305307 # Try an attribute.
306- o = get (object , name , M )
307- # print '...', (object, name, M, o)
308+ o = guarded_getattr (object , name , M )
308309 if o is M :
309310 # Try an item.
310- # print '... try an item'
311311 try :
312312 # XXX maybe in Python 2.2 we can just check whether
313313 # the object has the attribute "__getitem__"
@@ -319,18 +319,15 @@ def restrictedTraverse(self, path, securityManager,
319319 # Try to re-raise the original attribute error.
320320 # XXX I think this only happens with
321321 # ExtensionClass instances.
322- get (object , name )
322+ guarded_getattr (object , name )
323323 raise
324324 except TypeError , exc :
325325 if str (exc ).find ('unsubscriptable' ) >= 0 :
326326 # The object does not support the item interface.
327327 # Try to re-raise the original attribute error.
328328 # XXX This is sooooo ugly.
329- get (object , name )
329+ guarded_getattr (object , name )
330330 raise
331- #print '... object is now', `o`
332331 object = o
333- done .append ((name , o ))
334332
335333 return object
336-
0 commit comments