[Zope-dev] Zope 2.4.2 DTML Method Bug

Steve Alexander steve@cat-box.net
Fri, 02 Nov 2001 11:51:02 +0000


Matthew T. Kromer wrote:

> 
> 
> I think that is fixed but I'm not positive that its in 2.4.2  -- I know 
> its on my 2_4 branch; I think we just barely missed this for 2.4.2 -- I 
> see the change going into the log about a week later.
> 
> I'll ask Brian if we're going to put out a 2.4.3 to include the fix.


Matt,

Please see my report in the new Collector.
The patch at the end of this email is better than the one in the 
Collector, and also not mangled by stx :-)


Your fix in the trunk does only fixes the symptom. It does not address 
the problem of DTML Methods not being reenterant.

Your fix is to wrap in a try-except the act of removing validate from 
the __dict__ of the dtml method object:

    try: del self.__dict__['validate']
    except: pass

If you have a dtml method object that calls itself (that is, __call__ is 
called when a __call__ is already executing), then the validate 
attribute will be removed before the outer call is finished.


Here's my patch. As a bonus, we get rid of an unqualified except: statement.

This is a patch against the trunk.

*** DTMLMethod.py.orig  Fri Nov  2 11:45:54 2001
--- DTMLMethod.py       Fri Nov  2 11:47:45 2001
***************
*** 180,186 ****

           security=getSecurityManager()
           security.addContext(self)
!         self.__dict__['validate'] = security.DTMLValidate
           try:

               if client is None:
--- 180,192 ----

           security=getSecurityManager()
           security.addContext(self)
!
!         if self.__dict__.has_key('validate'):
!             fist_time_through=0
!         else:
!             self.__dict__['validate'] = security.DTMLValidate
!             first_time_through=1
!
           try:

               if client is None:
***************
*** 200,207 ****

           finally:
               security.removeContext(self)
!             try: del self.__dict__['validate']
!             except: pass

           have_key=RESPONSE.headers.has_key
           if not (have_key('content-type') or have_key('Content-Type')):
--- 206,213 ----

           finally:
               security.removeContext(self)
!             if first_time_through:
!                 del self.__dict__['validate']

           have_key=RESPONSE.headers.has_key
           if not (have_key('content-type') or have_key('Content-Type')):


You could also only add the dtml method to the security context on the 
first time through, although I think this would break the detection of 
excessive recursion. So, I haven't done that.

--
Steve Alexander
Software Engineer
Cat-Box limited