Commit e31ee667 authored by 's avatar

*** empty log message ***

parent 95d27aa8
...@@ -85,11 +85,11 @@ ...@@ -85,11 +85,11 @@
"""WebDAV support - collection objects.""" """WebDAV support - collection objects."""
__version__='$Revision: 1.4 $'[11:-2] __version__='$Revision: 1.5 $'[11:-2]
import sys, os, string import sys, os, string
from Resource import Resource from Resource import Resource
from common import urlfix from common import urlfix, rfc1123_date
class Collection(Resource): class Collection(Resource):
...@@ -101,17 +101,19 @@ class Collection(Resource): ...@@ -101,17 +101,19 @@ class Collection(Resource):
__dav_collection__=1 __dav_collection__=1
def redirect_check(self, req, rsp): def dav__init(self, request, response):
# By the spec, we are not supposed to accept /foo for a # By the spec, we are not supposed to accept /foo for a
# collection, we have to redirect to /foo/. # collection, we are supposed to redirect to /foo/.
if req['PATH_INFO'][-1]=='/': if request['PATH_INFO'][-1] != '/':
return raise 'Moved Permanently', request['URL1']+'/'
raise 'Moved Permanently', req['URL1']+'/' response.setHeader('Connection', 'close')
response.setHeader('Date', rfc1123_date())
response.setHeader('DAV', '1')
def HEAD(self, REQUEST, RESPONSE): def HEAD(self, REQUEST, RESPONSE):
"""Retrieve resource information without a response body.""" """Retrieve resource information without a response body."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
self.redirect_check(REQUEST, RESPONSE)
RESPONSE.setStatus(200) RESPONSE.setStatus(200)
return RESPONSE return RESPONSE
...@@ -120,18 +122,15 @@ class Collection(Resource): ...@@ -120,18 +122,15 @@ class Collection(Resource):
resources, though collections are not specifically forbidden resources, though collections are not specifically forbidden
to handle PUT requests. The default response to a PUT request to handle PUT requests. The default response to a PUT request
for collections is 405 (Method Not Allowed).""" for collections is 405 (Method Not Allowed)."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
self.redirect_check(REQUEST, RESPONSE) raise 'Method Not Allowed', 'Method not supported for collections.'
raise 'Method Not Allowed', 'Method not supported for this resource.'
def DELETE(self, REQUEST, RESPONSE): def DELETE(self, REQUEST, RESPONSE):
"""Delete a collection resource. For collection resources, DELETE """Delete a collection resource. For collection resources, DELETE
may return either 200 (OK) or 204 (No Content) to indicate total may return either 200 (OK) or 204 (No Content) to indicate total
success, or may return 207 (Multistatus) to indicate partial success, or may return 207 (Multistatus) to indicate partial
success. Note that in Zope a DELETE never returns 207.""" success. Note that in Zope a DELETE never returns 207."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
self.redirect_check(REQUEST, RESPONSE)
# self.dav__validate('manage_delObjects', REQUEST)
url=urlfix(REQUEST['URL'], 'DELETE') url=urlfix(REQUEST['URL'], 'DELETE')
name=filter(None, string.split(url, '/'))[-1] name=filter(None, string.split(url, '/'))[-1]
# TODO: add lock checking here # TODO: add lock checking here
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
"""WebDAV support - null resource objects.""" """WebDAV support - null resource objects."""
__version__='$Revision: 1.4 $'[11:-2] __version__='$Revision: 1.5 $'[11:-2]
import sys, os, string, mimetypes import sys, os, string, mimetypes
import Acquisition, OFS.content_types import Acquisition, OFS.content_types
...@@ -105,9 +105,18 @@ class NullResource(Persistent, Acquisition.Implicit, Resource): ...@@ -105,9 +105,18 @@ class NullResource(Persistent, Acquisition.Implicit, Resource):
self.__parent__=parent self.__parent__=parent
self.__roles__=parent.__roles__ self.__roles__=parent.__roles__
def __bobo_traverse__(self, REQUEST, name=None):
# We must handle traversal so that we can recognize situations
# where a 409 Conflict must be returned instead of the normal
# 404 Not Found, per [WebDAV 8.3.1].
method=REQUEST.get('REQUEST_METHOD', 'GET')
if method in ('MKCOL',):
raise 'Conflict', 'Collection ancestors must already exist.'
raise 'Not Found', 'The requested resource was not found.'
def HEAD(self, REQUEST, RESPONSE): def HEAD(self, REQUEST, RESPONSE):
"""Retrieve resource information without a response message body.""" """Retrieve resource information without a response message body."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
raise 'Not Found', 'The requested resource does not exist.' raise 'Not Found', 'The requested resource does not exist.'
# Most methods return 404 (Not Found) for null resources. # Most methods return 404 (Not Found) for null resources.
...@@ -115,7 +124,7 @@ class NullResource(Persistent, Acquisition.Implicit, Resource): ...@@ -115,7 +124,7 @@ class NullResource(Persistent, Acquisition.Implicit, Resource):
def PUT(self, REQUEST, RESPONSE): def PUT(self, REQUEST, RESPONSE):
"""Create a new non-collection resource.""" """Create a new non-collection resource."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
type=REQUEST.get_header('content-type', None) type=REQUEST.get_header('content-type', None)
body=REQUEST.get('BODY', '') body=REQUEST.get('BODY', '')
if type is None: if type is None:
...@@ -140,8 +149,7 @@ class NullResource(Persistent, Acquisition.Implicit, Resource): ...@@ -140,8 +149,7 @@ class NullResource(Persistent, Acquisition.Implicit, Resource):
def MKCOL(self, REQUEST, RESPONSE): def MKCOL(self, REQUEST, RESPONSE):
"""Create a new collection resource.""" """Create a new collection resource."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
# self.dav__validate('manage_addFolder', REQUEST)
if REQUEST.get('BODY', ''): if REQUEST.get('BODY', ''):
raise 'Unsupported Media Type', 'Unknown request body.' raise 'Unsupported Media Type', 'Unknown request body.'
parent=self.__parent__ parent=self.__parent__
...@@ -158,10 +166,10 @@ class NullResource(Persistent, Acquisition.Implicit, Resource): ...@@ -158,10 +166,10 @@ class NullResource(Persistent, Acquisition.Implicit, Resource):
def LOCK(self, REQUEST, RESPONSE): def LOCK(self, REQUEST, RESPONSE):
"""Create a lock-null resource.""" """Create a lock-null resource."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
raise 'Method Not Allowed', 'Method not supported for this resource.' raise 'Method Not Allowed', 'Method not supported for this resource.'
def UNLOCK(self): def UNLOCK(self):
"""Remove a lock-null resource.""" """Remove a lock-null resource."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
raise 'Method Not Allowed', 'Method not supported for this resource.' raise 'Method Not Allowed', 'Method not supported for this resource.'
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
"""WebDAV support - resource objects.""" """WebDAV support - resource objects."""
__version__='$Revision: 1.7 $'[11:-2] __version__='$Revision: 1.8 $'[11:-2]
import sys, os, string, mimetypes, xmlcmds import sys, os, string, mimetypes, xmlcmds
from common import absattr, aq_base, urlfix, rfc1123_date from common import absattr, aq_base, urlfix, rfc1123_date
...@@ -104,7 +104,7 @@ class Resource: ...@@ -104,7 +104,7 @@ class Resource:
'MOVE', 'MOVE',
) )
def init_headers(self, r): def dav__init(self, r):
# Init expected HTTP 1.1 / WebDAV headers which are not # Init expected HTTP 1.1 / WebDAV headers which are not
# currently set by the response object automagically. # currently set by the response object automagically.
r.setHeader('Connection', 'close') r.setHeader('Connection', 'close')
...@@ -158,8 +158,12 @@ class Resource: ...@@ -158,8 +158,12 @@ class Resource:
def HEAD(self, REQUEST, RESPONSE): def HEAD(self, REQUEST, RESPONSE):
"""Retrieve resource information without a response body.""" """Retrieve resource information without a response body."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
raise 'Method Not Allowed', 'Method not supported for this resource.' if hasattr(self, 'content_type'):
RESPONSE.setHeader('Content-Type', absattr(self.content_type))
if hasattr(self, 'getSize'):
RESPONSE.setHeader('Content-Length', absattr(self.getSize))
return RESPONSE
def PUT(self, REQUEST, RESPONSE): def PUT(self, REQUEST, RESPONSE):
"""Replace the GET response entity of an existing resource. """Replace the GET response entity of an existing resource.
...@@ -167,17 +171,19 @@ class Resource: ...@@ -167,17 +171,19 @@ class Resource:
PUT should override the default PUT implementation with an PUT should override the default PUT implementation with an
object-specific implementation. By default, PUT requests object-specific implementation. By default, PUT requests
fail with a 405 (Method Not Allowed).""" fail with a 405 (Method Not Allowed)."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
raise 'Method Not Allowed', 'Method not supported for this resource.' raise 'Method Not Allowed', 'Method not supported for this resource.'
OPTIONS__roles__=None
def OPTIONS(self, REQUEST, RESPONSE): def OPTIONS(self, REQUEST, RESPONSE):
"""Retrieve communication options.""" """Retrieve communication options."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
RESPONSE.setHeader('Allow', string.join(self.__http_methods__, ', ')) RESPONSE.setHeader('Allow', string.join(self.__http_methods__, ', '))
RESPONSE.setHeader('Content-Length', 0) RESPONSE.setHeader('Content-Length', 0)
RESPONSE.setStatus(200) RESPONSE.setStatus(200)
return RESPONSE return RESPONSE
TRACE__roles__=None
def TRACE(self, REQUEST, RESPONSE): def TRACE(self, REQUEST, RESPONSE):
"""Return the HTTP message received back to the client as the """Return the HTTP message received back to the client as the
entity-body of a 200 (OK) response. This will often usually entity-body of a 200 (OK) response. This will often usually
...@@ -185,14 +191,13 @@ class Resource: ...@@ -185,14 +191,13 @@ class Resource:
request will fail with a 405 (Method Not Allowed), since it request will fail with a 405 (Method Not Allowed), since it
is not often possible to reproduce the HTTP request verbatim is not often possible to reproduce the HTTP request verbatim
from within the Zope environment.""" from within the Zope environment."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
raise 'Method Not Allowed', 'Method not supported for this resource.' raise 'Method Not Allowed', 'Method not supported for this resource.'
def DELETE(self, REQUEST, RESPONSE): def DELETE(self, REQUEST, RESPONSE):
"""Delete a resource. For non-collection resources, DELETE may """Delete a resource. For non-collection resources, DELETE may
return either 200 or 204 (No Content) to indicate success.""" return either 200 or 204 (No Content) to indicate success."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
# self.dav__validate('manage_delObjects', REQUEST)
url=urlfix(REQUEST['URL'], 'DELETE') url=urlfix(REQUEST['URL'], 'DELETE')
name=filter(None, string.split(url, '/'))[-1] name=filter(None, string.split(url, '/'))[-1]
# TODO: add lock checking here # TODO: add lock checking here
...@@ -202,7 +207,7 @@ class Resource: ...@@ -202,7 +207,7 @@ class Resource:
def PROPFIND(self, REQUEST, RESPONSE): def PROPFIND(self, REQUEST, RESPONSE):
"""Retrieve properties defined on the resource.""" """Retrieve properties defined on the resource."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
try: cmd=xmlcmds.PropFind(REQUEST) try: cmd=xmlcmds.PropFind(REQUEST)
except: raise 'Bad Request', 'Invalid xml request.' except: raise 'Bad Request', 'Invalid xml request.'
result=cmd.apply(self) result=cmd.apply(self)
...@@ -213,7 +218,7 @@ class Resource: ...@@ -213,7 +218,7 @@ class Resource:
def PROPPATCH(self, REQUEST, RESPONSE): def PROPPATCH(self, REQUEST, RESPONSE):
"""Set and/or remove properties defined on the resource.""" """Set and/or remove properties defined on the resource."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
if not hasattr(self, '__propsets__'): if not hasattr(self, '__propsets__'):
raise 'Method Not Allowed', ( raise 'Method Not Allowed', (
'Method not supported for this resource.') 'Method not supported for this resource.')
...@@ -229,7 +234,7 @@ class Resource: ...@@ -229,7 +234,7 @@ class Resource:
def MKCOL(self, REQUEST, RESPONSE): def MKCOL(self, REQUEST, RESPONSE):
"""Create a new collection resource. If called on an existing """Create a new collection resource. If called on an existing
resource, MKCOL must fail with 405 (Method Not Allowed).""" resource, MKCOL must fail with 405 (Method Not Allowed)."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
raise 'Method Not Allowed', 'The resource already exists.' raise 'Method Not Allowed', 'The resource already exists.'
def COPY(self, REQUEST, RESPONSE): def COPY(self, REQUEST, RESPONSE):
...@@ -238,7 +243,7 @@ class Resource: ...@@ -238,7 +243,7 @@ class Resource:
as possible. Though we may later try to make a copy appear as possible. Though we may later try to make a copy appear
seamless across namespaces (e.g. from Zope to Apache), COPY seamless across namespaces (e.g. from Zope to Apache), COPY
is currently only supported within the Zope namespace.""" is currently only supported within the Zope namespace."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
if not hasattr(aq_base(self), 'cb_isCopyable') or \ if not hasattr(aq_base(self), 'cb_isCopyable') or \
not self.cb_isCopyable(): not self.cb_isCopyable():
raise 'Method Not Allowed', 'This object may not be copied.' raise 'Method Not Allowed', 'This object may not be copied.'
...@@ -285,7 +290,7 @@ class Resource: ...@@ -285,7 +290,7 @@ class Resource:
make a move appear seamless across namespaces (e.g. from Zope make a move appear seamless across namespaces (e.g. from Zope
to Apache), MOVE is currently only supported within the Zope to Apache), MOVE is currently only supported within the Zope
namespace.""" namespace."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
if not hasattr(aq_base(self), 'cb_isMoveable') or \ if not hasattr(aq_base(self), 'cb_isMoveable') or \
not self.cb_isMoveable(): not self.cb_isMoveable():
raise 'Method Not Allowed', 'This object may not be moved.' raise 'Method Not Allowed', 'This object may not be moved.'
...@@ -334,12 +339,12 @@ class Resource: ...@@ -334,12 +339,12 @@ class Resource:
DELETE, or MKCOL on the locked resource. All other current methods, DELETE, or MKCOL on the locked resource. All other current methods,
GET in particular, function independently of the lock. GET in particular, function independently of the lock.
""" """
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
raise 'Method Not Allowed', 'Method not supported for this resource.' raise 'Method Not Allowed', 'Method not supported for this resource.'
def UNLOCK(self): def UNLOCK(self):
"""Remove an existing lock on a resource.""" """Remove an existing lock on a resource."""
self.init_headers(RESPONSE) self.dav__init(REQUEST, RESPONSE)
raise 'Method Not Allowed', 'Method not supported for this resource.' raise 'Method Not Allowed', 'Method not supported for this resource.'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment