Skip to content

Commit

Permalink
- Fixed fallback implementation of manage_DAVget (fixes #799)
Browse files Browse the repository at this point in the history
  • Loading branch information
dataflake committed Mar 7, 2020
1 parent 81081e9 commit c7b09a9
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Expand Up @@ -28,6 +28,9 @@ Bug fixes
- Fixed encoding issue of `displayname` WebDAV property
(`#797 <https://github.com/zopefoundation/Zope/issues/797>`_)

- Fixed fallback implementation of ``manage_DAVget``
(`#799 <https://github.com/zopefoundation/Zope/issues/799>`_)


Other changes
+++++++++++++
Expand Down
27 changes: 27 additions & 0 deletions src/OFS/Image.py
Expand Up @@ -23,6 +23,7 @@
from AccessControl.Permissions import change_images_and_files # NOQA
from AccessControl.Permissions import view as View
from AccessControl.Permissions import view_management_screens
from AccessControl.Permissions import webdav_access
from AccessControl.SecurityInfo import ClassSecurityInfo
from Acquisition import Implicit
from App.Common import rfc1123_date
Expand Down Expand Up @@ -694,6 +695,32 @@ def __len__(self):
data = bytes(self.data)
return len(data)

@security.protected(webdav_access)
def manage_DAVget(self):
"""Return body for WebDAV."""
RESPONSE = self.REQUEST.RESPONSE

if self.ZCacheable_isCachingEnabled():
result = self.ZCacheable_get(default=None)
if result is not None:
# We will always get None from RAMCacheManager but we will
# get something implementing the IStreamIterator interface
# from FileCacheManager.
# the content-length is required here by HTTPResponse.
RESPONSE.setHeader('Content-Length', self.size)
return result

data = self.data
if isinstance(data, bytes):
RESPONSE.setBase(None)
return data

while data is not None:
RESPONSE.write(data.data)
data = data.next

return b''


InitializeClass(File)

Expand Down
9 changes: 9 additions & 0 deletions src/OFS/tests/testFileAndImage.py
Expand Up @@ -299,6 +299,15 @@ def testPrincipiaSearchSource_text(self):
b'come to the aid of the Party.')
self.assertTrue(b'Party' in self.file.PrincipiaSearchSource())

def test_manage_DAVget_binary(self):
self.assertEqual(self.file.manage_DAVget(), self.data)

def test_manage_DAVget_text(self):
text = (b'Now is the time for all good men to '
b'come to the aid of the Party.')
self.file.manage_edit('foobar', 'text/plain', filedata=text)
self.assertEqual(self.file.manage_DAVget(), text)

def test_interfaces(self):
from zope.interface.verify import verifyClass
from OFS.Image import File
Expand Down
16 changes: 13 additions & 3 deletions src/webdav/Resource.py
Expand Up @@ -675,9 +675,19 @@ def UNLOCK(self, REQUEST, RESPONSE):

@security.protected(webdav_access)
def manage_DAVget(self):
"""Gets the document source"""
# The default implementation calls PrincipiaSearchSource
return self.PrincipiaSearchSource()
"""Gets the document source or file data.
This implementation is a last resort fallback. The subclass should
override this method to provide a more appropriate implementation.
Using PrincipiaSearchSource, if it exists. It is one of the few shared
interfaces still around in common Zope content objects.
"""
if getattr(aq_base(self), 'PrincipiaSearchSource', None) is not None:
return self.PrincipiaSearchSource()

# If it doesn't exist, give up.
return ''

@security.protected(webdav_access)
def listDAVObjects(self):
Expand Down
4 changes: 4 additions & 0 deletions src/webdav/tests/testNullResource.py
Expand Up @@ -84,3 +84,7 @@ def _verifyObjectPaste(self, *args, **kw):
nonesuch.PUT(request, response)
except Unauthorized as e:
self.assertTrue(str(e).startswith('Unable to create object'))

def test_manage_DAVget(self):
nonesuch = self._makeOne()
self.assertFalse(nonesuch.manage_DAVget())

0 comments on commit c7b09a9

Please sign in to comment.