[Zope-dev] Zope 2 WebDAV and acquisition

Martin Aspeli optilude+lists at gmail.com
Mon Oct 5 11:21:46 EDT 2009


Martin Aspeli wrote:
> Hi,
> 
> In my travails through the ZPublisher and WebDAV, I've come up with 
> another fun thing.
> 
> As far as I can tell, traversal via acquisition doesn't make any sense 
> for a WebDAV request. If I have /foo and /bar, but not /bar/foo, then 
> traversal to /bar/foo over WebDAV should not acquire /foo and wrap it in 
> /bar.
> 
> One reason for this (apart from being utterly confusing) is that it 
> breaks PUT requests to a NullResource: If I try to PUT to /bar/foo it 
> should create a new object there, not overwrite /foo.
> 
> There is actually some convoluted support for detecting this in 
> ZPublisher.BaseRequest:
> 
>          # Note - no_acquire_flag is necessary to support
>          # things like DAV.  We have to make sure
>          # that the target object is not acquired
>          # if the request_method is other than GET
>          # or POST. Otherwise, you could never use
>          # PUT to add a new object named 'test' if
>          # an object 'test' existed above it in the
>          # heirarchy -- you'd always get the
>          # existing object :(
>          if (no_acquire_flag and
>              hasattr(parents[1], 'aq_base') and
>              not hasattr(parents[1],'__bobo_traverse__')):
>              if not (hasattr(parents[1].aq_base, entry_name) or
>                      parents[1].aq_base.has_key(entry_name)):
>                  raise AttributeError, entry_name
> 
> This doesn't really work, though. The object is acquired, and then all 
> it does is to check that the PUT() method object is a true attribute of 
> the acquired object. But even then, raising AttributeError is wrong.
> 
> What should happen, I think, is that in 
> DefaultPublishTraverse.publishTraverse() we should *not* attempt to 
> acquire for webdav requests. Instead, we should try direct attribute 
> access and then __getitem__() access (which is the next thing it tries 
> after getattr() acquisition). This would then allow the folder to return 
> a NullResource (as OFS.ObjectManager does, for example).
> 
> Any objections? It's a relatively simple condition in 
> DfaultPublishTraverse.publishTraverse().

Actually, I found some code that may be trying to address this (although 
I think it's probably likely that not attempting to acquire in the first 
place is better).

Basically, it allows acquisition during traversal, but when you get to 
the end of the path, it does this:

     if (no_acquire_flag and
         hasattr(object, 'aq_base') and
         not hasattr(object,'__bobo_traverse__')):
         if object.aq_parent is not object.aq_inner.aq_parent:
             from webdav.NullResource import NullResource
             object = NullResource(parents[-2], object.getId(), 
self).__of__(parents[-2])

This would fix the problem, except in my case, the traversed-to object 
(/foo in the example above) happens to have a __bobo_traverse__(), as do 
all CMF types, so the third caluse of the first if statement is false.

I can't see the logic here, though: why would it matter if the acquired 
object happens to have a __bobo_traverse__?

Removing that condition fixes it for me. This would be an even simpler 
bug fix (though I still find it fishy that you can acquire folders 
through WebDAV).

Can anyone explain why that condition is there? Otherwise, I'll rip it 
out. ;-)

Martin

-- 
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book



More information about the Zope-Dev mailing list