[Zope-CMF] Re: Inconstancy with CA traversal

Laurence Rowe l at lrowe.co.uk
Mon Jun 30 08:13:25 EDT 2008


Tres Seaver wrote:
> 
> I don't get it:  why isn't OFS.Traversable's check sufficient?
> __bobo_traverse__ has a bad enough (insane, actually) contract, without
> adding security checking to it.

Tres: You're quite right, the security check happens outside of 
bobo_traverse.

Dylan: Could you try this patch and see if it works for you. It really
needs some tests writing for it too.

Laurence

-------------- next part --------------
Index: Products/CMFCore/Skinnable.py
===================================================================
--- Products/CMFCore/Skinnable.py	(revision 87827)
+++ Products/CMFCore/Skinnable.py	(working copy)
@@ -27,6 +27,10 @@
 from Globals import InitializeClass
 from OFS.ObjectManager import ObjectManager
 from ZODB.POSException import ConflictError
+from zExceptions import NotFound
+import webdav
+from zope.interface import implements, Interface
+from zope.component import queryMultiAdapter
 
 logger = logging.getLogger('CMFCore.Skinnable')
 
@@ -94,6 +98,56 @@
         if superGetAttr is None:
             raise AttributeError, name
         return superGetAttr(self, name)
+    
+    def __bobo_traverse__(self, REQUEST, name):
+        '''
+        Ensures that views are traversed before skin objects
+        '''
+        resource = _marker = _MARKER
+        
+        # Look up unskinned objects
+        unskinned = super(SkinnableObjectManager, aq_base(self))
+        next = getattr(unskinned, name, _marker)
+        if next is _marker:
+            try:
+                try:
+                    next = self[name]
+                    # The item lookup may return a NullResource,
+                    # if this is the case we save it and return it
+                    # if all other lookups fail.
+                    if isinstance(next,
+                                  webdav.NullResource.NullResource):
+                        resource = next
+                        raise KeyError(name)
+                except (TypeError, AttributeError):
+                        # Raise NotFound for easier debugging
+                        # instead of AttributeError: __getitem__
+                        raise NotFound(name)
+                        
+            except (AttributeError, NotFound, KeyError), e:
+                # Try to look for a view
+                next = queryMultiAdapter((self, self.REQUEST),
+                                         Interface, name)
+                if next is not None:
+                    return next.__of__(self)
+    
+                # Lookup skin objects
+                next = getattr(aq_base(self), name, _marker)
+                if next is not _marker:
+                    return next
+        
+                # Try acquired attributes
+                next = getattr(self, name, _marker)
+                if next is not _marker:
+                    return next
+        
+                if next is _marker:
+                    # If we have a NullResource from earlier use it.
+                    next = resource
+                    if next is _marker:
+                        # Nothing found re-raise error
+                        raise e
+        return next
 
     security.declarePrivate('getSkin')
     def getSkin(self, name=None):


More information about the Zope-CMF mailing list