[Zope3-checkins] SVN: Zope3/trunk/src/zope/documenttemplate/
Shifted responsibility for compiling python exprs to templates
Jim Fulton
jim at zope.com
Fri Jul 23 18:08:14 EDT 2004
Log message for revision 26737:
Shifted responsibility for compiling python exprs to templates
This will make it easier to introduce some needed security in the app
server.
Also got rid os some TemplateDict class-dictionary hacking silliness.
Changed:
U Zope3/trunk/src/zope/documenttemplate/dt_if.py
U Zope3/trunk/src/zope/documenttemplate/dt_in.py
U Zope3/trunk/src/zope/documenttemplate/dt_let.py
U Zope3/trunk/src/zope/documenttemplate/dt_raise.py
U Zope3/trunk/src/zope/documenttemplate/dt_return.py
U Zope3/trunk/src/zope/documenttemplate/dt_string.py
U Zope3/trunk/src/zope/documenttemplate/dt_try.py
U Zope3/trunk/src/zope/documenttemplate/dt_util.py
U Zope3/trunk/src/zope/documenttemplate/dt_var.py
U Zope3/trunk/src/zope/documenttemplate/dt_with.py
U Zope3/trunk/src/zope/documenttemplate/pdocumenttemplate.py
-=-
Modified: Zope3/trunk/src/zope/documenttemplate/dt_if.py
===================================================================
--- Zope3/trunk/src/zope/documenttemplate/dt_if.py 2004-07-23 22:08:09 UTC (rev 26736)
+++ Zope3/trunk/src/zope/documenttemplate/dt_if.py 2004-07-23 22:08:14 UTC (rev 26737)
@@ -77,8 +77,7 @@
$Id$
"""
-from zope.documenttemplate.dt_util import \
- ParseError, parse_params, name_param
+from zope.documenttemplate.dt_util import ParseError, parse_params, name_param
class If:
blockContinuations = 'else', 'elif'
@@ -86,10 +85,10 @@
elses = None
expr = ''
- def __init__(self, blocks):
+ def __init__(self, context, blocks):
tname, args, section = blocks[0]
args = parse_params(args, name='', expr='')
- name,expr = name_param(args,'if',1)
+ name,expr = name_param(context, args,'if',1)
self.__name__ = name
if expr is None:
cond = name
@@ -102,7 +101,7 @@
del blocks[-1]
args = parse_params(args, name='')
if args:
- ename,expr=name_param(args,'else',1)
+ ename,expr=name_param(context, args,'else',1)
if ename != name:
raise ParseError, ('name in else does not match if', 'in')
elses=section.blocks
@@ -113,7 +112,7 @@
raise ParseError, (
'more than one else tag for a single if tag', 'in')
args = parse_params(args, name='', expr='')
- name,expr = name_param(args, 'elif', 1)
+ name,expr = name_param(context, args, 'elif', 1)
if expr is None:
cond = name
else:
@@ -131,10 +130,10 @@
name = 'unless'
blockContinuations = ()
- def __init__(self, blocks):
+ def __init__(self, context, blocks):
tname, args, section = blocks[0]
args=parse_params(args, name='', expr='')
- name,expr=name_param(args, 'unless', 1)
+ name,expr=name_param(context, args, 'unless', 1)
if expr is None:
cond = name
else:
Modified: Zope3/trunk/src/zope/documenttemplate/dt_in.py
===================================================================
--- Zope3/trunk/src/zope/documenttemplate/dt_in.py 2004-07-23 22:08:09 UTC (rev 26736)
+++ Zope3/trunk/src/zope/documenttemplate/dt_in.py 2004-07-23 22:08:14 UTC (rev 26737)
@@ -329,8 +329,8 @@
blockContinuations = ('else',)
name = 'in'
- def __call__(self, blocks):
- i = InClass(blocks)
+ def __call__(self, context, blocks):
+ i = InClass(context, blocks)
if i.batch:
return i.renderwb
else:
@@ -345,7 +345,7 @@
reverse = None
sort_expr = reverse_expr = None
- def __init__(self, blocks):
+ def __init__(self, context, blocks):
tname, args, section = blocks[0]
args=parse_params(args, name='', start='1',end='-1',size='10',
orphan='3',overlap='1',mapping=1,
@@ -360,10 +360,10 @@
if sort=='sequence-item': self.sort=''
if has_key('sort_expr'):
- self.sort_expr = Eval(args['sort_expr'])
+ self.sort_expr = Eval(context, args['sort_expr'])
if has_key('reverse_expr'):
- self.reverse_expr = Eval(args['reverse_expr'])
+ self.reverse_expr = Eval(context, args['reverse_expr'])
if has_key('reverse'):
self.reverse = args['reverse']
@@ -393,7 +393,7 @@
''.join(map(lambda c: "[%s]" % c, v))+
'=[0-9]+&+')
- name, expr = name_param(args, 'in', 1)
+ name, expr = name_param(context, args, 'in', 1)
if expr is not None:
expr = expr.eval
self.__name__, self.expr = name, expr
@@ -404,7 +404,7 @@
tname, args, section = blocks[1]
args=parse_params(args, name='')
if args:
- ename=name_param(args)
+ ename = name_param(context, args)
if ename != name:
raise ParseError, (
'name in else does not match in', 'in')
Modified: Zope3/trunk/src/zope/documenttemplate/dt_let.py
===================================================================
--- Zope3/trunk/src/zope/documenttemplate/dt_let.py 2004-07-23 22:08:09 UTC (rev 26736)
+++ Zope3/trunk/src/zope/documenttemplate/dt_let.py 2004-07-23 22:08:14 UTC (rev 26737)
@@ -50,7 +50,7 @@
blockContinuations = ()
name = 'let'
- def __init__(self, blocks):
+ def __init__(self, context, blocks):
tname, args, section = blocks[0]
self.__name__ = args
self.section = section.blocks
@@ -62,7 +62,7 @@
# expr shorthand
expr = expr[1:-1]
try:
- args[i] = name, Eval(expr).eval
+ args[i] = name, Eval(context, expr).eval
except SyntaxError, v:
m,(huh,l,c,src) = v
raise ParseError, (
Modified: Zope3/trunk/src/zope/documenttemplate/dt_raise.py
===================================================================
--- Zope3/trunk/src/zope/documenttemplate/dt_raise.py 2004-07-23 22:08:09 UTC (rev 26736)
+++ Zope3/trunk/src/zope/documenttemplate/dt_raise.py 2004-07-23 22:08:14 UTC (rev 26737)
@@ -25,19 +25,20 @@
$Id$
'''
-from zope.documenttemplate.dt_util import \
- parse_params, name_param, render_blocks
+from zope.documenttemplate.dt_util \
+ import parse_params, name_param, render_blocks
class Raise:
blockContinuations = ()
name = 'raise'
expr = ''
- def __init__(self, blocks):
+ def __init__(self, context, blocks):
tname, args, section = blocks[0]
self.section=section.blocks
args=parse_params(args, type='', expr='')
- self.__name__, self.expr = name_param(args, 'raise', 1, attr='type')
+ self.__name__, self.expr = name_param(
+ context, args, 'raise', 1, attr='type')
def render(self, md):
expr = self.expr
Modified: Zope3/trunk/src/zope/documenttemplate/dt_return.py
===================================================================
--- Zope3/trunk/src/zope/documenttemplate/dt_return.py 2004-07-23 22:08:09 UTC (rev 26736)
+++ Zope3/trunk/src/zope/documenttemplate/dt_return.py 2004-07-23 22:08:14 UTC (rev 26737)
@@ -21,9 +21,9 @@
name = 'return'
expr = None
- def __init__(self, args):
+ def __init__(self, context, args):
args = parse_params(args, name='', expr='')
- name, expr = name_param(args,'var',1)
+ name, expr = name_param(context, args,'var',1)
self.__name__, self.expr = name, expr
def render(self, md):
Modified: Zope3/trunk/src/zope/documenttemplate/dt_string.py
===================================================================
--- Zope3/trunk/src/zope/documenttemplate/dt_string.py 2004-07-23 22:08:09 UTC (rev 26736)
+++ Zope3/trunk/src/zope/documenttemplate/dt_string.py 2004-07-23 22:08:14 UTC (rev 26737)
@@ -177,9 +177,9 @@
else:
try:
if command is Var:
- r = command(args, self.varExtra(mo))
+ r = command(self, args, self.varExtra(mo))
else:
- r = command(args)
+ r = command(self, args)
if hasattr(r,'simple_form'):
r = r.simple_form
result.append(r)
@@ -248,7 +248,7 @@
sstart = start
else:
try:
- r = scommand(blocks)
+ r = scommand(self, blocks)
if hasattr(r,'simple_form'):
r = r.simple_form
result.append(r)
@@ -503,3 +503,7 @@
if k[:3] in _special: continue
d[k] = v
return d
+
+ def compile_python_expresssion(self, src):
+ return compile(src, getattr(self, '__name__', '<string>'), 'eval')
+
Modified: Zope3/trunk/src/zope/documenttemplate/dt_try.py
===================================================================
--- Zope3/trunk/src/zope/documenttemplate/dt_try.py 2004-07-23 22:08:09 UTC (rev 26736)
+++ Zope3/trunk/src/zope/documenttemplate/dt_try.py 2004-07-23 22:08:14 UTC (rev 26737)
@@ -18,8 +18,9 @@
import sys, traceback
from StringIO import StringIO
-from zope.documenttemplate.dt_util import ParseError, parse_params, render_blocks
-from zope.documenttemplate.dt_util import namespace, InstanceDict
+from zope.documenttemplate.dt_util \
+ import ParseError, parse_params, render_blocks
+from zope.documenttemplate.dt_util import InstanceDict
from zope.documenttemplate.dt_return import DTReturn
from types import StringType
@@ -95,7 +96,7 @@
finallyBlock = None
elseBlock = None
- def __init__(self, blocks):
+ def __init__(self, context, blocks):
tname, args, section = blocks[0]
self.args = parse_params(args)
@@ -178,7 +179,7 @@
f = StringIO()
traceback.print_exc(100,f)
error_tb = f.getvalue()
- ns = namespace(md, error_type=errname, error_value=v,
+ ns = md.namespace(error_type=errname, error_value=v,
error_tb=error_tb)[0]
md._push(InstanceDict(ns,md))
return render_blocks(handler, md)
Modified: Zope3/trunk/src/zope/documenttemplate/dt_util.py
===================================================================
--- Zope3/trunk/src/zope/documenttemplate/dt_util.py 2004-07-23 22:08:09 UTC (rev 26736)
+++ Zope3/trunk/src/zope/documenttemplate/dt_util.py 2004-07-23 22:08:14 UTC (rev 26737)
@@ -16,10 +16,7 @@
$Id$
"""
import re
-import math
-import random
-from __builtin__ import str # needed for pickling (legacy)
from types import ListType, StringType, TupleType
from zope.documenttemplate.pdocumenttemplate import \
@@ -59,209 +56,12 @@
v = v.atoi()
return v or 0
-_marker=[]
-
-def careful_getattr(md, inst, name, default=_marker):
-
- if name[:1] != '_':
-
- try:
- v = getattr(inst, name)
- except:
- if default is not _marker:
- return default
- raise
-
- validate = md.validate
-
- if validate is None:
- return v
-
- if validate(inst, inst, name, v, md):
- return v
-
- raise ValidationError, name
-
-
-def careful_hasattr(md, inst, name):
- v=getattr(inst, name, _marker)
- if v is not _marker:
- try:
- if name[:1] != '_':
- validate = md.validate
- if validate is None:
- return 1
-
- if validate(inst, inst, name, v, md):
- return 1
- except:
- pass
- return 0
-
-
-def careful_getitem(md, mapping, key):
- v = mapping[key]
- if isinstance(v, StringType):
- return v # Short-circuit common case
-
- validate = md.validate
- if validate is None or validate(mapping, mapping, None, v, md):
- return v
- raise ValidationError, key
-
-
-def careful_getslice(md, seq, *indexes):
- v = len(indexes)
- if v == 2:
- v = seq[indexes[0]:indexes[1]]
- elif v == 1:
- v = seq[indexes[0]:]
- else:
- v = seq[:]
-
- if isinstance(seq, StringType):
- return v # Short-circuit common case
-
- validate = md.validate
- if validate is not None:
- for e in v:
- if not validate(seq,seq,None,e,md):
- raise ValidationError, u'unauthorized access to slice member'
-
- return v
-
-
-def careful_range(md, iFirst, *args):
- # limited range function from Martijn Pieters
- RANGELIMIT = 1000
- if not len(args):
- iStart, iEnd, iStep = 0, iFirst, 1
- elif len(args) == 1:
- iStart, iEnd, iStep = iFirst, args[0], 1
- elif len(args) == 2:
- iStart, iEnd, iStep = iFirst, args[0], args[1]
- else:
- raise AttributeError, u'range() requires 1-3 int arguments'
- if iStep == 0:
- raise ValueError, u'zero step for range()'
- iLen = int((iEnd - iStart) / iStep)
- if iLen < 0:
- iLen = 0
- if iLen >= RANGELIMIT:
- raise ValueError, u'range() too large'
- return range(iStart, iEnd, iStep)
-
-
-d = TemplateDict.__dict__
-for name in ('None', 'abs', 'chr', 'divmod', 'float', 'hash', 'hex', 'int',
- 'len', 'max', 'min', 'oct', 'ord', 'round', 'str'):
- d[name] = __builtins__[name]
-
-d['math'] = math
-d['random'] = random
-
-def careful_pow(self, x, y, z):
- if not z:
- raise ValueError, 'pow(x, y, z) with z==0'
- return pow(x,y,z)
-
-d['pow'] = careful_pow
-
-try:
- import DateTime
- d['DateTime']=DateTime.DateTime
-except:
- pass
-
-
-def test(self, *args):
- l = len(args)
- for i in range(1, l, 2):
- if args[i-1]:
- return args[i]
-
- if l%2:
- return args[-1]
-
-d['test'] = test
-
-def obsolete_attr(self, inst, name, md):
- return careful_getattr(md, inst, name)
-
-d['attr'] = obsolete_attr
-d['getattr'] = careful_getattr
-d['hasattr'] = careful_hasattr
-d['range'] = careful_range
-
-def namespace(self, **kw):
- """Create a tuple consisting of a single instance whose attributes are
- provided as keyword arguments."""
- if getattr(self, '__class__', None) != TemplateDict:
- raise TypeError,'''A call was made to DT_Util.namespace() with an
- incorrect "self" argument. It could be caused by a product which
- is not yet compatible with this version of Zope. The traceback
- information may contain more details.)'''
- return apply(self, (), kw)
-
-d['namespace'] = namespace
-
-def render(self, v):
- "Render an object in the way done by the 'name' attribute"
- if hasattr(v, '__render_with_namespace__'):
- v = v.__render_with_namespace__(self)
- else:
- vbase = getattr(v, 'aq_base', v)
- if callable(vbase):
- v = v()
- return v
-
-d['render'] = render
-
-def reorder(self, s, with=None, without=()):
- if with is None:
- with = s
- d = {}
- for i in s:
- if isinstance(i, TupleType) and len(i) == 2:
- k, v = i
- else:
- k = v = i
- d[k] = v
- r = []
- a = r.append
- h = d.has_key
-
- for i in without:
- if isinstance(i, TupleType) and len(i) == 2:
- k, v = i
- else:
- k= v = i
- if h(k):
- del d[k]
-
- for i in with:
- if isinstance(i, TupleType) and len(i) == 2:
- k, v = i
- else:
- k= v = i
- if h(k):
- a((k,d[k]))
- del d[k]
-
- return r
-
-d['reorder'] = reorder
-
-
class Eval:
- def __init__(self, expr):
+ def __init__(self, context, expr):
- expr = expr.strip()
- expr = expr.replace('\n', ' ')
- expr = expr.replace('\r', ' ')
- self.expr = expr
- self.code = compile(expr,'<string>','eval')
+ self.expr = '('+expr.strip()+')'
+ self.code = context.compile_python_expresssion(self.expr)
def eval(self, mapping):
@@ -279,7 +79,7 @@
# does need the name, a NameError will occur.
pass
- return eval(code, {}, d)
+ return eval(code, {'__builtins__': None}, d)
def __call__(self, **kw):
@@ -287,7 +87,8 @@
-def name_param(params,tag='',expr=0, attr='name', default_unnamed=1):
+def name_param(context, params, tag='', expr=0, attr='name',
+ default_unnamed=1):
used = params.has_key
__traceback_info__ = params, tag, expr, attr
@@ -307,7 +108,7 @@
raise ParseError, (u'two exprs given', tag)
v = v[1:-1]
try:
- expr=Eval(v)
+ expr=Eval(context, v)
except SyntaxError, v:
raise ParseError, (
u'<strong>Expression (Python) Syntax error</strong>:'
@@ -338,7 +139,7 @@
return params[attr]
elif expr and used('expr'):
name = params['expr']
- expr = Eval(name)
+ expr = Eval(context, name)
return name, expr
raise ParseError, (u'No %s given' % attr, tag)
Modified: Zope3/trunk/src/zope/documenttemplate/dt_var.py
===================================================================
--- Zope3/trunk/src/zope/documenttemplate/dt_var.py 2004-07-23 22:08:09 UTC (rev 26736)
+++ Zope3/trunk/src/zope/documenttemplate/dt_var.py 2004-07-23 22:08:14 UTC (rev 26737)
@@ -147,7 +147,7 @@
$Id$
"""
-from zope.documenttemplate.dt_util import parse_params, name_param, html_quote, str
+from zope.documenttemplate.dt_util import parse_params, name_param, html_quote
import re, sys
from urllib import quote, quote_plus
@@ -156,7 +156,7 @@
name = 'var'
expr = None
- def __init__(self, args, fmt='s'):
+ def __init__(self, context, args, fmt='s'):
if args[:4] == 'var ':
args = args[4:]
args = parse_params(args, name='', lower=1, upper=1, expr='',
@@ -173,7 +173,7 @@
used(m[0]) and args[m[0]],
modifiers)))
- name, expr = name_param(args, 'var', 1)
+ name, expr = name_param(context, args, 'var', 1)
self.__name__, self.expr = name, expr
self.fmt = fmt
@@ -285,9 +285,9 @@
name = 'call'
expr = None
- def __init__(self, args):
+ def __init__(self, context, args):
args = parse_params(args, name='', expr='')
- name, expr = name_param(args,'call',1)
+ name, expr = name_param(context, args,'call',1)
if expr is None:
expr = name
else:
@@ -451,7 +451,7 @@
name = 'comment'
blockContinuations = ()
- def __init__(self, args, fmt=''):
+ def __init__(self, context, args, fmt=''):
pass
def render(self, md):
Modified: Zope3/trunk/src/zope/documenttemplate/dt_with.py
===================================================================
--- Zope3/trunk/src/zope/documenttemplate/dt_with.py 2004-07-23 22:08:09 UTC (rev 26736)
+++ Zope3/trunk/src/zope/documenttemplate/dt_with.py 2004-07-23 22:08:14 UTC (rev 26737)
@@ -48,10 +48,10 @@
mapping = None
only = 0
- def __init__(self, blocks):
+ def __init__(self, context, blocks):
tname, args, section = blocks[0]
args = parse_params(args, name='', expr='', mapping=1, only=1)
- name, expr = name_param(args, 'with', 1)
+ name, expr = name_param(context, args, 'with', 1)
if expr is None:
expr = name
else:
Modified: Zope3/trunk/src/zope/documenttemplate/pdocumenttemplate.py
===================================================================
--- Zope3/trunk/src/zope/documenttemplate/pdocumenttemplate.py 2004-07-23 22:08:09 UTC (rev 26736)
+++ Zope3/trunk/src/zope/documenttemplate/pdocumenttemplate.py 2004-07-23 22:08:14 UTC (rev 26737)
@@ -171,7 +171,103 @@
m=kw
return (DictInstance(m),)
+ # extra handy utilities that people expect to find in template dicts:
+ import math
+ import random
+
+ def range(md, iFirst, *args):
+ # limited range function from Martijn Pieters
+ RANGELIMIT = 1000
+ if not len(args):
+ iStart, iEnd, iStep = 0, iFirst, 1
+ elif len(args) == 1:
+ iStart, iEnd, iStep = iFirst, args[0], 1
+ elif len(args) == 2:
+ iStart, iEnd, iStep = iFirst, args[0], args[1]
+ else:
+ raise AttributeError, u'range() requires 1-3 int arguments'
+ if iStep == 0:
+ raise ValueError, u'zero step for range()'
+ iLen = int((iEnd - iStart) / iStep)
+ if iLen < 0:
+ iLen = 0
+ if iLen >= RANGELIMIT:
+ raise ValueError, u'range() too large'
+ return range(iStart, iEnd, iStep)
+
+ def pow(self, x, y, z):
+ if not z:
+ raise ValueError, 'pow(x, y, z) with z==0'
+ return pow(x,y,z)
+
+ def test(self, *args):
+ l = len(args)
+ for i in range(1, l, 2):
+ if args[i-1]:
+ return args[i]
+
+ if l%2:
+ return args[-1]
+
+ getattr = getattr
+ attr = getattr
+ hasattr = hasattr
+
+ def namespace(self, **kw):
+ return self(**kw)
+
+ def render(self, v):
+ "Render an object in the way done by the 'name' attribute"
+ if hasattr(v, '__render_with_namespace__'):
+ v = v.__render_with_namespace__(self)
+ else:
+ vbase = getattr(v, 'aq_base', v)
+ if callable(vbase):
+ v = v()
+ return v
+
+ def reorder(self, s, with=None, without=()):
+ if with is None:
+ with = s
+ d = {}
+ for i in s:
+ if isinstance(i, TupleType) and len(i) == 2:
+ k, v = i
+ else:
+ k = v = i
+ d[k] = v
+ r = []
+ a = r.append
+ h = d.has_key
+
+ for i in without:
+ if isinstance(i, TupleType) and len(i) == 2:
+ k, v = i
+ else:
+ k= v = i
+ if h(k):
+ del d[k]
+
+ for i in with:
+ if isinstance(i, TupleType) and len(i) == 2:
+ k, v = i
+ else:
+ k= v = i
+ if h(k):
+ a((k,d[k]))
+ del d[k]
+
+ return r
+
+
+# Add selected builtins to template dicts
+for name in ('None', 'abs', 'chr', 'divmod', 'float', 'hash', 'hex', 'int',
+ 'len', 'max', 'min', 'oct', 'ord', 'round', 'str'):
+ setattr(TemplateDict, name, __builtins__[name])
+
+
+
def render_blocks(blocks, md):
rendered = []
for section in blocks:
More information about the Zope3-Checkins
mailing list