[Checkins] SVN: Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/ Working PublishTraversal adapter

Matthew Wilkes matthew at matthewwilkes.co.uk
Sun Aug 16 16:14:55 EDT 2009


Log message for revision 102862:
  Working PublishTraversal adapter

Changed:
  U   Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/Skinnable.py
  U   Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/configure.zcml
  U   Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/interfaces/_tools.py
  A   Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/traverser.py

-=-
Modified: Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/Skinnable.py
===================================================================
--- Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/Skinnable.py	2009-08-16 19:22:43 UTC (rev 102861)
+++ Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/Skinnable.py	2009-08-16 20:14:54 UTC (rev 102862)
@@ -29,6 +29,8 @@
 from ZODB.POSException import ConflictError
 from zope.interface import implements
 
+from interfaces import ISkinnableObjectManager
+
 logger = logging.getLogger('CMFCore.Skinnable')
 
 

Modified: Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/configure.zcml
===================================================================
--- Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/configure.zcml	2009-08-16 19:22:43 UTC (rev 102861)
+++ Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/configure.zcml	2009-08-16 20:14:54 UTC (rev 102862)
@@ -13,4 +13,10 @@
 
   <include file="tool.zcml"/>
 
+  <adapter
+      factory = ".traverser.PortalRootPublishTraverse"
+      for = ".interfaces.ISkinnableObjectManager zope.interface.Interface"
+      />
+  
+  
 </configure>

Modified: Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/interfaces/_tools.py
===================================================================
--- Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/interfaces/_tools.py	2009-08-16 19:22:43 UTC (rev 102861)
+++ Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/interfaces/_tools.py	2009-08-16 20:14:54 UTC (rev 102862)
@@ -1248,12 +1248,12 @@
         o Permission:  Public
         """
 
-class ISkinnableObjectManager(object):
+class ISkinnableObjectManager(Interface):
     
     """ An object that has skins applied to it."""
 
 
-    def __getattr__(self, name):
+    def __getattr__(name):
         '''
         Looks for the name in an object with wrappers that only reach
         up to the root skins folder.
@@ -1261,28 +1261,28 @@
         This should be fast, flexible, and predictable.
         '''
         
-    def getSkin(self, name=None):
+    def getSkin(name):
         """Returns the requested skin.
         """
 
-    def getSkinNameFromRequest(self, REQUEST=None):
+    def getSkinNameFromRequest(REQUEST):
         '''Returns the skin name from the Request.'''
 
-    def changeSkin(self, skinname, REQUEST=_MARKER):
+    def changeSkin(skinname, REQUEST):
         '''Change the current skin.
 
         Can be called manually, allowing the user to change
         skins in the middle of a request.
         '''
     
-    def getCurrentSkinName(self):
+    def getCurrentSkinName():
         '''Return the current skin name.
         '''
 
-    def clearCurrentSkin(self):
+    def clearCurrentSkin():
         """Clear the current skin."""
 
-    def setupCurrentSkin(self, REQUEST=_MARKER):
+    def setupCurrentSkin(REQUEST):
         '''
         Sets up skindata so that __getattr__ can find it.
 

Added: Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/traverser.py
===================================================================
--- Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/traverser.py	                        (rev 0)
+++ Products.CMFCore/branches/matthewwilkes-traversalprecedence/Products/CMFCore/traverser.py	2009-08-16 20:14:54 UTC (rev 102862)
@@ -0,0 +1,110 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002, 2008 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""CMF portal traverser
+
+$Id: traverser.py 67630 2006-04-27 00:54:03Z jim $
+"""
+__docformat__ = 'restructuredtext'
+
+from zExceptions import Forbidden
+
+from Acquisition.interfaces import IAcquirer
+
+from zope.interface import implements, Interface
+from zope.component import queryMultiAdapter
+from zope.publisher.interfaces.browser import IBrowserPublisher
+
+from ZPublisher.BaseRequest import DefaultPublishTraverse, typeCheck
+
+class PortalRootPublishTraverse(DefaultPublishTraverse):
+
+    implements(IBrowserPublisher)
+        
+    def publishTraverse(self, request, name):
+        object = self.context
+        URL=request['URL']
+        
+
+        if name[:1]=='_':
+            raise Forbidden("Object name begins with an underscore at: %s" % URL)
+
+        
+        if hasattr(object,'__bobo_traverse__'):
+            # We can use the normal logic
+            return super(PortalRootPublishTraverse, self).publishTraverse(request, name)
+        else:
+            
+            subobject = None
+            
+            # No __bobo_traverse__
+            # Try with an unacquired attribute:
+            try:
+                subobject = object.__getattribute__(name).aq_base.__of__(object)
+            except AttributeError:
+                # this is not a direct object
+                pass
+            
+            
+            if subobject is None:
+                # We try to fall back to a view:
+                subobject = queryMultiAdapter((object, request), Interface,
+                                              name)
+                if subobject is not None:
+                    if IAcquirer.providedBy(subobject):
+                        subobject = subobject.__of__(object)
+                    return subobject
+            
+                # And lastly, of there is no view, try acquired attributes, but
+                # only if there is no __bobo_traverse__:
+                try:
+                    subobject=getattr(object, name)
+                    # Again, clear any error status created by __bobo_traverse__
+                    # because we actually found something:
+                    request.response.setStatus(200)
+                    return subobject
+                except AttributeError:
+                    pass
+
+                # Lastly we try with key access:
+                try:
+                    subobject = object[name]
+                except TypeError: # unsubscriptable
+                    raise KeyError(name)
+                
+
+        # Ensure that the object has a docstring, or that the parent
+        # object has a pseudo-docstring for the object. Objects that
+        # have an empty or missing docstring are not published.
+        doc = getattr(subobject, '__doc__', None)
+        if doc is None:
+            doc = getattr(object, '%s__doc__' % name, None)
+        if not doc:
+            raise Forbidden(
+                "The object at %s has an empty or missing " \
+                "docstring. Objects must have a docstring to be " \
+                "published." % URL
+                )
+
+        # Hack for security: in Python 2.2.2, most built-in types
+        # gained docstrings that they didn't have before. That caused
+        # certain mutable types (dicts, lists) to become publishable
+        # when they shouldn't be. The following check makes sure that
+        # the right thing happens in both 2.2.2+ and earlier versions.
+
+        if not typeCheck(subobject):
+            raise Forbidden(
+                "The object at %s is not publishable." % URL
+                )
+
+        return subobject



More information about the Checkins mailing list