[Zope-Checkins] CVS: Zope2 - DT_In.py:1.48.4.3 DT_String.py:1.39.54.1 DT_Util.py:1.72.18.6 DT_With.py:1.11.142.1 DocumentTemplate.py:1.10.160.2 cDocumentTemplate.c:1.35.60.1 pDocumentTemplate.py:1.27.40.1
shane@digicool.com
shane@digicool.com
Thu, 26 Apr 2001 18:25:40 -0400 (EDT)
Update of /cvs-repository/Zope2/lib/python/DocumentTemplate
In directory korak:/tmp/cvs-serv10837/lib/python/DocumentTemplate
Modified Files:
Tag: RestrictedPythonBranch
DT_In.py DT_String.py DT_Util.py DT_With.py
DocumentTemplate.py cDocumentTemplate.c pDocumentTemplate.py
Log Message:
Modified the way DTML namespaces implement security: now there is an
attribute of TemplateDicts called read_guard which implements the
"read guard" interface as defined by RestrictedPython.
--- Updated File DT_In.py in package Zope2 --
--- DT_In.py 2001/04/25 20:26:35 1.48.4.2
+++ DT_In.py 2001/04/26 22:25:08 1.48.4.3
@@ -595,7 +595,7 @@
else:
result = []
append=result.append
- validate=md.validate
+ read_guard = md.read_guard
for index in range(first,end):
# preset
kw['previous-sequence']= 0
@@ -625,17 +625,17 @@
if index==last: kw['sequence-end']=1
- client=sequence[index]
-
- if validate is not None:
- try: vv=validate(sequence,sequence,None,client,md)
- except: vv=0
- if not vv:
+ if read_guard is not None:
+ try: client = read_guard(sequence)[index]
+ except ValidationError, vv:
if (params.has_key('skip_unauthorized') and
params['skip_unauthorized']):
if index==first: kw['sequence-start']=0
continue
- raise ValidationError, index
+ raise ValidationError, '(item %s): %s' % (
+ index, vv)
+ else:
+ client = sequence[index]
kw['sequence-index']=index
if type(client)==TupleType and len(client)==2:
@@ -708,20 +708,20 @@
try:
result = []
append=result.append
- validate=md.validate
+ read_guard = md.read_guard
for index in range(l):
if index==last: kw['sequence-end']=1
- client=sequence[index]
-
- if validate is not None:
- try: vv=validate(sequence,sequence,None,client,md)
- except: vv=0
- if not vv:
- if (self.args.has_key('skip_unauthorized') and
- self.args['skip_unauthorized']):
- if index==1: kw['sequence-start']=0
+ if read_guard is not None:
+ try: client = read_guard(sequence)[index]
+ except ValidationError, vv:
+ if (params.has_key('skip_unauthorized') and
+ params['skip_unauthorized']):
+ if index==first: kw['sequence-start']=0
continue
- raise ValidationError, index
+ raise ValidationError, '(item %s): %s' % (
+ index, vv)
+ else:
+ client = sequence[index]
kw['sequence-index']=index
if type(client)==TupleType and len(client)==2:
--- Updated File DT_String.py in package Zope2 --
--- DT_String.py 2000/12/12 21:20:25 1.39
+++ DT_String.py 2001/04/26 22:25:08 1.39.54.1
@@ -500,7 +500,7 @@
if globals: push(globals)
if mapping:
push(mapping)
- md.validate=self.validate
+ md.read_guard=self.read_guard
if client is not None:
if type(client)==type(()):
md.this=client[-1]
@@ -545,8 +545,8 @@
if pushed: md._pop(pushed) # Get rid of circular reference!
md.level=level # Restore previous level
- validate__roles__=()
- validate=None
+ read_guard__roles__=()
+ read_guard=None
def __str__(self):
return self.read()
--- Updated File DT_Util.py in package Zope2 --
--- DT_Util.py 2001/04/26 02:43:15 1.72.18.5
+++ DT_Util.py 2001/04/26 22:25:08 1.72.18.6
@@ -87,6 +87,7 @@
import regex, string, math, os
from string import strip, join, atoi, lower, split, find
+from RestrictedPython.Eval import RestrictionCapableEval
str=__builtins__['str'] # Waaaaa, waaaaaaaa needed for pickling waaaaa
@@ -103,46 +104,22 @@
if type(v) is st: v=atoi(v)
return v or 0
-_marker=[]
+_marker = [] # Create a new marker object.
def careful_getattr(md, inst, name, default=_marker):
-
- if name[:1]!='_':
-
- # Try to get the attribute normally so that we don't
- # accidentally acquire when we shouldn't.
- try: v=getattr(inst, name)
- except:
- if default is not _marker:
- return default
- raise
-
- validate=md.validate
-
- if validate is None: return v
-
- if hasattr(inst,'aq_acquire'):
- return inst.aq_acquire(name, validate, md)
-
- if validate(inst,inst,name,v,md): return v
-
- raise ValidationError, name
+ read_guard = md.read_guard
+ if read_guard is not None:
+ inst = read_guard(inst)
+ if default is _marker:
+ return getattr(inst, name)
+ else:
+ return getattr(inst, name, default)
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 hasattr(inst,'aq_acquire'):
- inst.aq_acquire(name, validate, md)
- return 1
-
- if validate(inst,inst,name,v,md): return 1
- except: pass
- return 0
+ read_guard = md.read_guard
+ if read_guard is not None:
+ inst = read_guard(inst)
+ return hasattr(inst, name)
def careful_range(md, iFirst, *args):
# limited range function from Martijn Pieters
@@ -196,10 +173,6 @@
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
@@ -263,78 +236,31 @@
d['reorder']=reorder
-class DTMLGuard:
- _md = None
-
- def __init__(self, ob):
- self._ob = ob
-
- def __getattr__(self, name):
- if name[:1]!='_': # This condition is probably unnecessary.
- inst = self._ob
- # Try to get the attribute normally so that we don't
- # accidentally acquire when we shouldn't.
- try: v=getattr(inst, name)
- except:
- if default is not _marker:
- return default
- raise
- md = self._md
- validate = md.validate
- if validate is None:
- return v
- if hasattr(inst, 'aq_acquire'):
- return inst.aq_acquire(name, validate, md)
- if validate(inst, inst, name, v, md):
- return v
- raise ValidationError, name
-
- def __len__(self):
- return len(self._ob)
-
- def __getitem__(self, key):
- mapping = self._ob
- v = mapping[key]
- if type(v) is type(''):
- return v # Short-circuit common case
- md = self._md
- validate = md.validate
- if validate is None or validate(mapping, mapping, None, v, md):
- return v
- raise ValidationError, key
-
- def __getslice__(self, lo, hi):
- seq = self._ob
- v = seq[lo:hi]
- if type(seq) is type(''):
- return v # Short-circuit common case
- md = self._md
- validate = md.validate
- if validate is not None:
- for e in v:
- if not validate(seq, seq, None, e, md):
- raise ValidationError, (
- 'unauthorized access to slice member')
- return v
-
-from RestrictedPython.Eval import RestrictionCapableEval
-
class Eval(RestrictionCapableEval):
def eval(self, md):
- # Create a temporary subclass of DTMLGuard.
- class Guard (DTMLGuard): pass
- Guard._md = md
- d = {'_': md, '_read_guard': Guard}
+ guard = getattr(md, 'read_guard', None)
+ if guard is not None:
+ self.prepRestrictedCode()
+ code = self.rcode
+ d = {'_': md, '_read_': guard}
+ else:
+ self.prepUnrestrictedCode()
+ code = self.ucode
+ d = {'_': md}
+ d.update(self.globals)
+ has_key = d.has_key
for name in self.used:
__traceback_info__ = name
- try: d[name] = md.getitem(name,0)
+ try:
+ if not has_key(name):
+ d[name] = md.getitem(name, 0)
except KeyError:
# Swallow KeyErrors since the expression
# might not actually need the name. If it
# does need the name, a NameError will occur.
pass
- return eval(self.code, self.globals, d)
+ return eval(code, d)
def __call__(self, **kw):
# Never used?
--- Updated File DT_With.py in package Zope2 --
--- DT_With.py 2000/05/11 18:54:14 1.11
+++ DT_With.py 2001/04/26 22:25:08 1.11.142.1
@@ -139,8 +139,8 @@
if self.only:
_md=md
md=TemplateDict()
- if hasattr(_md, 'validate'):
- md.validate=_md.validate
+ if hasattr(_md, 'read_guard'):
+ md.read_guard = _md.read_guard
md._push(v)
try: return render_blocks(self.section, md)
--- Updated File DocumentTemplate.py in package Zope2 --
--- DocumentTemplate.py 2001/04/26 02:43:16 1.10.160.1
+++ DocumentTemplate.py 2001/04/26 22:25:08 1.10.160.2
@@ -145,31 +145,15 @@
Document templates provide a basic level of access control by
preventing access to names beginning with an underscore.
- Addational control may be provided by providing document templates
- with a 'validate' method. This would typically be done by
+ Additional control may be provided by providing document templates
+ with a 'read_guard' method. This would typically be done by
subclassing one or more of the DocumentTemplate classes.
- If provided, the the 'validate' method will be called when objects
+ If provided, the the 'read_guard' method will be called when objects
are accessed as accessed as instance attributes or when they are
- accessed through keyed access in an expression.. The 'validate'
- method will be called with five arguments:
-
- 1. The containing object that the object was accessed from,
-
- 2. The actual containing object that the object was found in,
- which may be different from the containing onject the object
- was accessed from, if the containing object supports
- acquisition,
-
- 3. The name used to acces the object,
-
- 4. The object, and
-
- 5. The namespace object used to render the document template.
-
- If a document template was called from Bobo, then the namespace
- object will have an attribute, AUTHENTICATED_USER that is the
- user object that was found if and when Bobo authenticated a user.
+ accessed through keyed access in an expression.. The 'read_guard'
+ method will be called with the containing object. It can
+ return a wrapper object from which the attribute will be accessed.
Document Templates may be created 4 ways:
--- Updated File cDocumentTemplate.c in package Zope2 --
--- cDocumentTemplate.c 2000/11/21 22:08:50 1.35
+++ cDocumentTemplate.c 2001/04/26 22:25:08 1.35.60.1
@@ -92,7 +92,7 @@
static PyObject *py_isDocTemp=0, *py_blocks=0, *py_=0, *join=0, *py_acquire;
static PyObject *py___call__, *py___roles__, *py_AUTHENTICATED_USER;
static PyObject *py_hasRole, *py__proxy_roles, *py_Unauthorized;
-static PyObject *py_Unauthorized_fmt, *py_validate;
+static PyObject *py_Unauthorized_fmt, *py_read_guard;
static PyObject *py__push, *py__pop, *py_aq_base, *py_renderNS;
/* ----------------------------------------------------- */
@@ -108,7 +108,7 @@
PyObject *inst;
PyObject *cache;
PyObject *namespace;
- PyObject *validate;
+ PyObject *read_guard;
} InstanceDictobject;
staticforward PyExtensionClass InstanceDictType;
@@ -116,18 +116,18 @@
static PyObject *
InstanceDict___init__(InstanceDictobject *self, PyObject *args)
{
- self->validate=NULL;
+ self->read_guard=NULL;
UNLESS(PyArg_ParseTuple(args, "OO|O",
&(self->inst),
&(self->namespace),
- &(self->validate)))
+ &(self->read_guard)))
return NULL;
Py_INCREF(self->inst);
Py_INCREF(self->namespace);
- if (self->validate)
- Py_INCREF(self->validate);
+ if (self->read_guard)
+ Py_INCREF(self->read_guard);
else
- UNLESS(self->validate=PyObject_GetAttr(self->namespace, py_validate))
+ UNLESS(self->read_guard=PyObject_GetAttr(self->namespace, py_read_guard))
return NULL;
UNLESS(self->cache=PyDict_New()) return NULL;
@@ -150,7 +150,7 @@
Py_XDECREF(self->inst);
Py_XDECREF(self->cache);
Py_XDECREF(self->namespace);
- Py_XDECREF(self->validate);
+ Py_XDECREF(self->read_guard);
Py_DECREF(self->ob_type);
PyMem_DEL(self);
}
@@ -182,7 +182,7 @@
char *name;
/* Try to get value from the cache */
- if (r=PyObject_GetItem(self->cache, key)) return r;
+ if ((r=PyObject_GetItem(self->cache, key))) return r;
PyErr_Clear();
/* Check for __str__ */
@@ -193,56 +193,31 @@
return PyObject_Str(self->inst);
}
- /* Do explicit acquisition with "roles" rule */
- if (r=PyObject_GetAttr(self->inst, py_acquire))
- {
- /* Sanity check in case of explicit Aq */
- if (v=PyObject_GetAttr(self->inst, key)) Py_DECREF(v);
- else
- {
- Py_DECREF(r);
- goto KeyError;
- }
-
- if (self->validate != Py_None)
- {
- UNLESS_ASSIGN(r,PyObject_CallFunction(
- r, "OOO", key, self->validate, self->namespace))
- {
- PyObject *tb;
-
- PyErr_Fetch(&r, &v, &tb);
- if (r != PyExc_AttributeError || PyObject_Compare(v,key))
- {
- PyErr_Restore(r,v,tb);
- return NULL;
- }
- Py_XDECREF(r);
- Py_XDECREF(v);
- Py_XDECREF(tb);
-
- goto KeyError;
- }
- }
- else
- UNLESS_ASSIGN(r, PyObject_GetAttr(self->inst, key)) goto KeyError;
- }
- else
- {
- PyErr_Clear();
+ if (self->read_guard != Py_None) {
+ r = PyObject_CallFunction(self->read_guard, "O", self->inst);
+ if (!r) return NULL;
+ }
+ else {
+ r = self->inst;
+ Py_INCREF(r);
+ }
- /* OK, use getattr */
- UNLESS(r=PyObject_GetAttr(self->inst, key)) goto KeyError;
+ ASSIGN(r, PyObject_GetAttr(r, key));
+ if (!r) {
+ PyObject *tb;
+
+ PyErr_Fetch(&r, &v, &tb);
+ if (r != PyExc_AttributeError) /* || PyObject_Compare(v,key)) */
+ {
+ PyErr_Restore(r,v,tb);
+ return NULL;
+ }
+ Py_XDECREF(r);
+ Py_XDECREF(v);
+ Py_XDECREF(tb);
- if (self->validate != Py_None)
- {
- UNLESS(v=PyObject_CallFunction(
- self->validate,"OOOOO",
- self->inst, self->inst, key, r, self->namespace))
- return NULL;
- Py_DECREF(v);
- }
- }
+ goto KeyError;
+ }
if (r && PyObject_SetItem(self->cache, key, r) < 0) PyErr_Clear();
@@ -312,9 +287,7 @@
staticforward PyExtensionClass MMtype;
static PyObject *
-MM_push(self, args)
- MM *self;
- PyObject *args;
+MM_push(MM *self, PyObject *args)
{
PyObject *src;
UNLESS(PyArg_Parse(args, "O", &src)) return NULL;
@@ -324,9 +297,7 @@
}
static PyObject *
-MM_pop(self, args)
- MM *self;
- PyObject *args;
+MM_pop(MM *self, PyObject *args)
{
int i=1, l;
PyObject *r;
@@ -343,9 +314,7 @@
}
static PyObject *
-MM__init__(self, args)
- MM *self;
- PyObject *args;
+MM__init__(MM *self, PyObject *args)
{
UNLESS(PyArg_Parse(args, "")) return NULL;
UNLESS(self->data=PyList_New(0)) return NULL;
@@ -385,7 +354,7 @@
Py_INCREF(base);
}
- if ( value = PyObject_GetAttr(base, py_isDocTemp) ) {
+ if ( (value = PyObject_GetAttr(base, py_isDocTemp)) ) {
if (PyObject_IsTrue(value)) {
result = 1;
}
@@ -408,12 +377,12 @@
while (--i >= 0)
{
e=PyList_GetItem(self->data,i);
- if (e=PyObject_GetItem(e,key))
+ if ((e=PyObject_GetItem(e,key)))
{
if (!call) return e;
/* Try calling __render_with_namespace__ */
- if (rr = PyObject_GetAttr(e, py_renderNS))
+ if ((rr = PyObject_GetAttr(e, py_renderNS)))
{
Py_DECREF(e);
UNLESS_ASSIGN(rr, PyObject_CallFunction(rr, "O", self))
@@ -516,8 +485,7 @@
};
static void
-MM_dealloc(self)
- MM *self;
+MM_dealloc(MM *self)
{
Py_XDECREF(self->data);
Py_XDECREF(self->dict);
@@ -538,7 +506,7 @@
{
PyObject *v;
- if (v=PyDict_GetItem(self->dict, name))
+ if ((v=PyDict_GetItem(self->dict, name)))
{
Py_INCREF(v);
return v;
@@ -568,8 +536,7 @@
}
static int
-MM_length(self)
- MM *self;
+MM_length(MM *self)
{
long l=0, el, i;
PyObject *e=0;
@@ -800,7 +767,7 @@
{
/* We have to be careful to handle key errors here */
n=cond;
- if (cond=PyObject_GetItem(md,cond))
+ if ((cond=PyObject_GetItem(md,cond)))
{
if (PyDict_SetItem(cache, n, cond) < 0)
{
@@ -912,7 +879,7 @@
};
void
-initcDocumentTemplate()
+initcDocumentTemplate(void)
{
PyObject *m, *d;
char *rev="$Revision$";
@@ -927,7 +894,7 @@
UNLESS(py___roles__=PyString_FromString("__roles__")) return;
UNLESS(py__proxy_roles=PyString_FromString("_proxy_roles")) return;
UNLESS(py_hasRole=PyString_FromString("hasRole")) return;
- UNLESS(py_validate=PyString_FromString("validate")) return;
+ UNLESS(py_read_guard=PyString_FromString("read_guard")) return;
UNLESS(py__push=PyString_FromString("_push")) return;
UNLESS(py__pop=PyString_FromString("_pop")) return;
UNLESS(py_aq_base=PyString_FromString("aq_base")) return;
--- Updated File pDocumentTemplate.py in package Zope2 --
--- pDocumentTemplate.py 2001/01/16 18:08:27 1.27
+++ pDocumentTemplate.py 2001/04/26 22:25:08 1.27.40.1
@@ -117,14 +117,14 @@
class InstanceDict:
- validate=None
+ read_guard=None
- def __init__(self,o,namespace,validate=None):
+ def __init__(self,o,namespace,read_guard=None):
self.self=o
self.cache={}
self.namespace=namespace
- if validate is None: self.validate=namespace.validate
- else: self.validate=validate
+ if read_guard is None: self.read_guard=namespace.read_guard
+ else: self.read_guard=read_guard
def has_key(self,key):
return hasattr(self.self,key)
@@ -144,13 +144,16 @@
if key[:1]=='_':
if key != '__str__':
raise KeyError, key # Don't divuldge private data
- r=str(inst)
+ return str(inst)
+
+ read_guard = self.read_guard
+ if read_guard is None:
+ inst1 = inst
else:
- try: r=getattr(inst,key)
- except AttributeError: raise KeyError, key
+ inst1 = read_guard(inst)
- v=self.validate
- if v is not None: v(inst,inst,key,r,self.namespace)
+ try: r = getattr(inst1, key)
+ except AttributeError: raise KeyError, key
self.cache[key]=r
return r