def DELETE(self, REQUEST, RESPONSE): """Delete a collection resource. For collection resources, DELETE may return either 200 (OK) or 204 (No Content) to indicate total success, or may return 207 (Multistatus) to indicate partial success. Note that in Zope a DELETE currently never returns 207.""" self.dav__init(REQUEST, RESPONSE) ifhdr = REQUEST.get_header('If', '') url = urlfix(REQUEST['URL'], 'DELETE') name = unquote(filter(None, url.split( '/'))[-1]) parent = self.aq_parent user = getSecurityManager().getUser() token = None # if re.match("/Control_Panel",REQUEST['PATH_INFO']): # RESPONSE.setStatus(403) # RESPONSE.setHeader('Content-Type', 'text/xml; charset="utf-8"') # return RESPONSE # Level 1 of lock checking (is the collection or its parent locked?) if Lockable.wl_isLocked(self): if ifhdr: self.dav__simpleifhandler(REQUEST, RESPONSE, 'DELETE', col=1) else: raise 'Locked' elif Lockable.wl_isLocked(parent): if ifhdr: parent.dav__simpleifhandler(REQUEST, RESPONSE, 'DELETE', col=1) else: raise 'Precondition Failed' # Second level of lock\conflict checking (are any descendants locked, # or is the user not permitted to delete?). This results in a # multistatus response if ifhdr: tokens = self.wl_lockTokens() for tok in tokens: # We already know that the simple if handler succeeded, # we just want to get the right token out of the header now if ifhdr.find(tok) > -1: token = tok cmd = davcmds.DeleteCollection() result = cmd.apply(self, token, user, REQUEST['URL']) if result: # There were conflicts, so we need to report them RESPONSE.setStatus(207) RESPONSE.setHeader('Content-Type', 'text/xml; charset="utf-8"') RESPONSE.setBody(result) else: # There were no conflicts, so we can go ahead and delete # ajung: additional check if we really could delete the collection # (Collector #2196) if parent.manage_delObjects([name],REQUEST=None) is None: RESPONSE.setStatus(204) else: RESPONSE.setStatus(403) return RESPONSE
def DELETE(self, REQUEST, RESPONSE): """Delete a collection resource. For collection resources, DELETE may return either 200 (OK) or 204 (No Content) to indicate total success, or may return 207 (Multistatus) to indicate partial success. Note that in Zope a DELETE currently never returns 207.""" self.dav__init(REQUEST, RESPONSE) ifhdr = REQUEST.get_header('If', '') url = urlfix(REQUEST['URL'], 'DELETE') name = unquote(filter(None, url.split( '/'))[-1]) parent = self.aq_parent user = getSecurityManager().getUser() token = None # if re.match("/Control_Panel",REQUEST['PATH_INFO']): # RESPONSE.setStatus(403) # RESPONSE.setHeader('Content-Type', 'text/xml; charset="utf-8"') # return RESPONSE # Level 1 of lock checking (is the collection or its parent locked?) if Lockable.wl_isLocked(self): if ifhdr: self.dav__simpleifhandler(REQUEST, RESPONSE, 'DELETE', col=1) else: raise Locked elif Lockable.wl_isLocked(parent): if ifhdr: parent.dav__simpleifhandler(REQUEST, RESPONSE, 'DELETE', col=1) else: raise PreconditionFailed # Second level of lock\conflict checking (are any descendants locked, # or is the user not permitted to delete?). This results in a # multistatus response if ifhdr: tokens = self.wl_lockTokens() for tok in tokens: # We already know that the simple if handler succeeded, # we just want to get the right token out of the header now if ifhdr.find(tok) > -1: token = tok cmd = davcmds.DeleteCollection() result = cmd.apply(self, token, user, REQUEST['URL']) if result: # There were conflicts, so we need to report them RESPONSE.setStatus(207) RESPONSE.setHeader('Content-Type', 'text/xml; charset="utf-8"') RESPONSE.setBody(result) else: # There were no conflicts, so we can go ahead and delete # ajung: additional check if we really could delete the collection # (Collector #2196) if parent.manage_delObjects([name],REQUEST=None) is None: RESPONSE.setStatus(204) else: RESPONSE.setStatus(403) return RESPONSE
def dav__simpleifhandler(self, request, response, method='PUT', col=0, url=None, refresh=0): ifhdr = request.get_header('If', None) if Lockable.wl_isLocked(self) and (not ifhdr): raise Locked, "Resource is locked." if not ifhdr: return None if not Lockable.wl_isLocked(self): return None # Since we're a simple if handler, and since some clients don't # pass in the port information in the resource part of an If # header, we're only going to worry about if the paths compare if url is None: url = urlfix(request['URL'], method) url = urlbase(url) # Gets just the path information # if 'col' is passed in, an operation is happening on a submember # of a collection, while the Lock may be on the parent. Lob off # the final part of the URL (ie '/a/b/foo.html' becomes '/a/b/') if col: url = url[:url.rfind('/')+1] havetag = lambda x, self=self: self.wl_hasLock(x) found = 0; resourcetagged = 0 taglist = IfParser(ifhdr) for tag in taglist: if not tag.resource: # There's no resource (url) with this tag tag_list = map(tokenFinder, tag.list) wehave = filter(havetag, tag_list) if not wehave: continue if tag.NOTTED: continue if refresh: for token in wehave: self.wl_getLock(token).refresh() resourcetagged = 1 found = 1; break elif urlbase(tag.resource) == url: resourcetagged = 1 tag_list = map(tokenFinder, tag.list) wehave = filter(havetag, tag_list) if not wehave: continue if tag.NOTTED: continue if refresh: for token in wehave: self.wl_getLock(token).refresh() found = 1; break if resourcetagged and (not found): raise PreconditionFailed, 'Condition failed.' elif resourcetagged and found: return 1 else: return 0
def LOCK(self, REQUEST, RESPONSE): """Lock a resource""" self.dav__init(REQUEST, RESPONSE) security = getSecurityManager() creator = security.getUser() body = REQUEST.get('BODY', '') ifhdr = REQUEST.get_header('If', None) depth = REQUEST.get_header('Depth', 'infinity') alreadylocked = Lockable.wl_isLocked(self) if body and alreadylocked: # This is a full LOCK request, and the Resource is # already locked, so we need to raise the alreadylocked # exception. RESPONSE.setStatus(423) elif body: # This is a normal lock request with an XML payload cmd = davcmds.Lock(REQUEST) token, result = cmd.apply(self, creator, depth=depth) if result: # Return the multistatus result (there were multiple # errors. Note that davcmds.Lock.apply aborted the # transaction already. RESPONSE.setStatus(207) RESPONSE.setHeader('Content-Type', 'text/xml; charset="utf-8"') RESPONSE.setBody(result) else: # Success lock = self.wl_getLock(token) RESPONSE.setStatus(200) RESPONSE.setHeader('Content-Type', 'text/xml; charset="utf-8"') RESPONSE.setHeader('Lock-Token', 'opaquelocktoken:' + token) RESPONSE.setBody(lock.asXML()) else: # There's no body, so this likely to be a refresh request if not ifhdr: raise PreconditionFailed, 'If Header Missing' taglist = IfParser(ifhdr) found = 0 for tag in taglist: for listitem in tag.list: token = tokenFinder(listitem) if token and self.wl_hasLock(token): lock = self.wl_getLock(token) timeout = REQUEST.get_header('Timeout', 'Infinite') lock.setTimeout(timeout) # automatically refreshes found = 1 RESPONSE.setStatus(200) RESPONSE.setHeader('Content-Type', 'text/xml; charset="utf-8"') RESPONSE.setBody(lock.asXML()) break if found: break if not found: RESPONSE.setStatus(412) # Precondition failed return RESPONSE
def PROPPATCH(self, REQUEST, RESPONSE): """Set and/or remove properties defined on the resource.""" self.dav__init(REQUEST, RESPONSE) if not hasattr(aq_base(self), 'propertysheets'): raise MethodNotAllowed, ( 'Method not supported for this resource.') # Lock checking ifhdr = REQUEST.get_header('If', '') if Lockable.wl_isLocked(self): if ifhdr: self.dav__simpleifhandler(REQUEST, RESPONSE, 'PROPPATCH') else: raise Locked, 'Resource is locked.' cmd=davcmds.PropPatch(REQUEST) result=cmd.apply(self) RESPONSE.setStatus(207) RESPONSE.setHeader('Content-Type', 'text/xml; charset="utf-8"') RESPONSE.setBody(result) return RESPONSE
def DELETE(self, REQUEST, RESPONSE): """Delete a resource. For non-collection resources, DELETE may return either 200 or 204 (No Content) to indicate success.""" self.dav__init(REQUEST, RESPONSE) ifhdr = REQUEST.get_header('If', '') url = urlfix(REQUEST['URL'], 'DELETE') name = unquote(filter(None, url.split( '/')[-1])) parent = aq_parent(aq_inner(self)) # Lock checking if Lockable.wl_isLocked(self): if ifhdr: self.dav__simpleifhandler(REQUEST, RESPONSE, 'DELETE') else: # We're locked, and no if header was passed in, so # the client doesn't own a lock. raise Locked, 'Resource is locked.' elif (IWriteLock.providedBy(parent) or WriteLockInterface.isImplementedBy(parent)) and \ parent.wl_isLocked(): if ifhdr: parent.dav__simpleifhandler(REQUEST, RESPONSE, 'DELETE', col=1) else: # Our parent is locked, and no If header was passed in. # When a parent is locked, members cannot be removed raise PreconditionFailed, 'Resource is locked, and no '\ 'condition was passed in.' # Either we're not locked, or a succesful lock token was submitted # so we can delete the lock now. # ajung: Fix for Collector # 2196 if parent.manage_delObjects([name],REQUEST=None) is None: RESPONSE.setStatus(204) else: RESPONSE.setStatus(403) return RESPONSE
def MOVE(self, REQUEST, RESPONSE): """Move a resource to a new location. Though we may later try to make a move appear seamless across namespaces (e.g. from Zope to Apache), MOVE is currently only supported within the Zope namespace.""" self.dav__init(REQUEST, RESPONSE) self.dav__validate(self, 'DELETE', REQUEST) if not hasattr(aq_base(self), 'cb_isMoveable') or \ not self.cb_isMoveable(): raise MethodNotAllowed, 'This object may not be moved.' dest=REQUEST.get_header('Destination', '') try: path = REQUEST.physicalPathFromURL(dest) except ValueError: raise BadRequest, 'No destination given' flag=REQUEST.get_header('Overwrite', 'F') flag=flag.upper() name = path.pop() parent_path = '/'.join(path) try: parent = self.restrictedTraverse(path) except ValueError: raise Conflict, 'Attempt to move to an unknown namespace.' except 'Not Found': raise Conflict, 'The resource %s must exist.' % parent_path except: t, v, tb=sys.exc_info() raise t, v if hasattr(parent, '__null_resource__'): raise Conflict, 'The resource %s must exist.' % parent_path existing=hasattr(aq_base(parent), name) if existing and flag=='F': raise PreconditionFailed, 'Resource %s exists.' % dest try: parent._checkId(name, allow_dup=1) except: raise Forbidden, sys.exc_info()[1] try: parent._verifyObjectPaste(self) except Unauthorized: raise except: raise Forbidden, sys.exc_info()[1] # Now check locks. Since we're affecting the resource that we're # moving as well as the destination, we have to check both. ifhdr = REQUEST.get_header('If', '') if existing: # The destination itself exists, so we need to check its locks destob = aq_base(parent)._getOb(name) if (IWriteLock.providedBy(destob) or WriteLockInterface.isImplementedBy(destob)) and \ destob.wl_isLocked(): if ifhdr: itrue = destob.dav__simpleifhandler( REQUEST, RESPONSE, 'MOVE', url=dest, refresh=1) if not itrue: raise PreconditionFailed else: raise Locked, 'Destination is locked.' elif (IWriteLock.providedBy(parent) or WriteLockInterface.isImplementedBy(parent)) and \ parent.wl_isLocked(): # There's no existing object in the destination folder, so # we need to check the folders locks since we're changing its # member list if ifhdr: itrue = parent.dav__simpleifhandler(REQUEST, RESPONSE, 'MOVE', col=1, url=dest, refresh=1) if not itrue: raise PreconditionFailed, 'Condition failed.' else: raise Locked, 'Destination is locked.' if Lockable.wl_isLocked(self): # Lastly, we check ourselves if ifhdr: itrue = self.dav__simpleifhandler(REQUEST, RESPONSE, 'MOVE', refresh=1) if not itrue: raise PreconditionFailed, 'Condition failed.' else: raise PreconditionFailed, 'Source is locked and no '\ 'condition was passed in.' orig_container = aq_parent(aq_inner(self)) orig_id = self.getId() self._notifyOfCopyTo(parent, op=1) notify(ObjectWillBeMovedEvent(self, orig_container, orig_id, parent, name)) # try to make ownership explicit so that it gets carried # along to the new location if needed. self.manage_changeOwnershipType(explicit=1) ob = self._getCopy(parent) ob._setId(name) try: orig_container._delObject(orig_id, suppress_events=True) except TypeError: # BBB: removed in Zope 2.11 orig_container._delObject(orig_id) warnings.warn( "%s._delObject without suppress_events is deprecated " "and will be removed in Zope 2.11." % orig_container.__class__.__name__, DeprecationWarning) if existing: object=getattr(parent, name) self.dav__validate(object, 'DELETE', REQUEST) parent._delObject(name) try: parent._setObject(name, ob, set_owner=0, suppress_events=True) except TypeError: # BBB: removed in Zope 2.11 parent._setObject(name, ob, set_owner=0) warnings.warn( "%s._setObject without suppress_events is deprecated " "and will be removed in Zope 2.11." % parent.__class__.__name__, DeprecationWarning) ob = parent._getOb(name) notify(ObjectMovedEvent(ob, orig_container, orig_id, parent, name)) notifyContainerModified(orig_container) if aq_base(orig_container) is not aq_base(parent): notifyContainerModified(parent) ob._postCopy(parent, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) RESPONSE.setStatus(existing and 204 or 201) if not existing: RESPONSE.setHeader('Location', dest) RESPONSE.setBody('') return RESPONSE
def MOVE(self, REQUEST, RESPONSE): """Move a resource to a new location. Though we may later try to make a move appear seamless across namespaces (e.g. from Zope to Apache), MOVE is currently only supported within the Zope namespace.""" self.dav__init(REQUEST, RESPONSE) self.dav__validate(self, 'DELETE', REQUEST) if not hasattr(aq_base(self), 'cb_isMoveable') or \ not self.cb_isMoveable(): raise 'Method Not Allowed', 'This object may not be moved.' dest=REQUEST.get_header('Destination', '') try: path = REQUEST.physicalPathFromURL(dest) except ValueError: raise 'Bad Request', 'No destination given' flag=REQUEST.get_header('Overwrite', 'F') flag=flag.upper() name = path.pop() parent_path = '/'.join(path) try: parent = self.restrictedTraverse(path) except ValueError: raise 'Conflict', 'Attempt to move to an unknown namespace.' except 'Not Found': raise 'Conflict', 'The resource %s must exist.' % parent_path except: t, v, tb=sys.exc_info() raise t, v if hasattr(parent, '__null_resource__'): raise 'Conflict', 'The resource %s must exist.' % parent_path existing=hasattr(aq_base(parent), name) if existing and flag=='F': raise 'Precondition Failed', 'Resource %s exists.' % dest try: parent._checkId(name, allow_dup=1) except: raise 'Forbidden', sys.exc_info()[1] try: parent._verifyObjectPaste(self) except Unauthorized: raise except: raise 'Forbidden', sys.exc_info()[1] # Now check locks. Since we're affecting the resource that we're # moving as well as the destination, we have to check both. ifhdr = REQUEST.get_header('If', '') if existing: # The destination itself exists, so we need to check its locks destob = aq_base(parent)._getOb(name) if WriteLockInterface.isImplementedBy(destob) and \ destob.wl_isLocked(): if ifhdr: itrue = destob.dav__simpleifhandler( REQUEST, RESPONSE, 'MOVE', url=dest, refresh=1) if not itrue: raise 'Precondition Failed' else: raise 'Locked', 'Destination is locked.' elif WriteLockInterface.isImplementedBy(parent) and \ parent.wl_isLocked(): # There's no existing object in the destination folder, so # we need to check the folders locks since we're changing its # member list if ifhdr: itrue = parent.dav__simpleifhandler(REQUEST, RESPONSE, 'MOVE', col=1, url=dest, refresh=1) if not itrue: raise 'Precondition Failed', 'Condition failed.' else: raise 'Locked', 'Destination is locked.' if Lockable.wl_isLocked(self): # Lastly, we check ourselves if ifhdr: itrue = self.dav__simpleifhandler(REQUEST, RESPONSE, 'MOVE', refresh=1) if not itrue: raise 'Precondition Failed', 'Condition failed.' else: raise 'Precondition Failed', 'Source is locked and no '\ 'condition was passed in.' ob=aq_base(self._getCopy(parent)) self.aq_parent._delObject(absattr(self.id)) ob._setId(name) if existing: object=getattr(parent, name) self.dav__validate(object, 'DELETE', REQUEST) parent._delObject(name) parent._setObject(name, ob) RESPONSE.setStatus(existing and 204 or 201) if not existing: RESPONSE.setHeader('Location', dest) RESPONSE.setBody('') return RESPONSE