def _delObject(self, id, dp=1, suppress_events=False): """Delete an object from this container. Also sends IObjectWillBeRemovedEvent and IObjectRemovedEvent. """ ob = self._getOb(id) compatibilityCall('manage_beforeDelete', ob, ob, self) if not suppress_events: notify(ObjectWillBeRemovedEvent(ob, self, id)) self._objects = tuple([i for i in self._objects if i['id'] != id]) self._delOb(id) # Indicate to the object that it has been deleted. This is # necessary for object DB mount points. Note that we have to # tolerate failure here because the object being deleted could # be a Broken object, and it is not possible to set attributes # on Broken objects. try: ob._v__object_deleted__ = 1 except: pass if not suppress_events: notify(ObjectRemovedEvent(ob, self, id)) notifyContainerModified(self)
def manage_clone(self, ob, id, REQUEST=None): """Clone an object, creating a new object with the given id. """ if not ob.cb_isCopyable(): raise CopyError('Not Supported') try: self._checkId(id) except Exception: raise CopyError('Invalid Id') self._verifyObjectPaste(ob) try: ob._notifyOfCopyTo(self, op=0) except ConflictError: raise except Exception: raise CopyError('Clone Error') orig_ob = ob ob = ob._getCopy(self) ob._setId(id) notify(ObjectCopiedEvent(ob, orig_ob)) self._setObject(id, ob) ob = self._getOb(id) ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) return ob
def _delObject(self, id, dp=1, suppress_events=False): """Delete an object from this container. Also sends IObjectWillBeRemovedEvent and IObjectRemovedEvent. """ ob = self._getOb(id) compatibilityCall('manage_beforeDelete', ob, ob, self) if not suppress_events: notify(ObjectWillBeRemovedEvent(ob, self, id)) self._objects = tuple([i for i in self._objects if i['id'] != id]) self._delOb(id) # Indicate to the object that it has been deleted. This is # necessary for object DB mount points. Note that we have to # tolerate failure here because the object being deleted could # be a Broken object, and it is not possible to set attributes # on Broken objects. try: ob._v__object_deleted__ = 1 except Exception: pass if not suppress_events: notify(ObjectRemovedEvent(ob, self, id)) notifyContainerModified(self)
def _setObject(self, id, object, roles=None, user=None, set_owner=1, suppress_events=False): """Set an object into this container. Also sends IObjectWillBeAddedEvent and IObjectAddedEvent. """ ob = object if not suppress_events: # notify(ObjectAddedEvent(ob, self, id)) notifyContainerModified(self) compatibilityCall('manage_afterAdd', ob, ob, self) return id
def __copy(self, content, to_identifier): # Copy a content to to_identifier in the container copy = content._getCopy(self.context) copy._setId(to_identifier) notify(ObjectCopiedEvent(copy, content)) self.context._setObject(to_identifier, copy) copy = self.context._getOb(to_identifier) compatibilityCall('manage_afterClone', copy, copy) notify(ObjectClonedEvent(copy)) return copy
def _setObject(self, id, object, roles=None, user=None, set_owner=1, suppress_events=False): """Set an object into this container. Also sends IObjectAddedEvent. """ ob = object # better name, keep original function signature v = self._checkId(id) if v is not None: id = v t = getattr(ob, 'meta_type', None) # If an object by the given id already exists, remove it. for object_info in self._objects: if object_info['id'] == id: self._delObject(id) break if not suppress_events: notify(ObjectWillBeAddedEvent(ob, self, id)) self._objects = self._objects + ({'id': id, 'meta_type': t}, ) self._setOb(id, ob) ob = self._getOb(id) if set_owner: # TODO: eventify manage_fixupOwnershipAfterAdd # This will be called for a copy/clone, or a normal _setObject. ob.manage_fixupOwnershipAfterAdd() if set_owner: # Try to give user the local role "Owner", but only if # no local roles have been set on the object yet. if getattr(ob, '__ac_local_roles__', _marker) is None: user = getSecurityManager().getUser() if user is not None: userid = user.getId() if userid is not None: ob.manage_setLocalRoles(userid, ['Owner']) if not suppress_events: notify(ObjectAddedEvent(ob, self, id)) notifyContainerModified(self) compatibilityCall('manage_afterAdd', ob, ob, self) return id
def _delObject(self, id, dp=1, suppress_events=False): ob = self._getOb(id) compatibilityCall('manage_beforeDelete', ob, ob, self) if not suppress_events: notify(ObjectWillBeRemovedEvent(ob, self, id)) self._delOb(id) if not suppress_events: notify(ObjectRemovedEvent(ob, self, id)) notifyContainerModified(self)
def deleter(self): to_delete = [] container_ids = set(self.context.objectIds()) try: protected = self.context._reserved_names except: protected = () content = yield while content is not None: try: content.is_deletable() except ContentError as error: result = error else: content_id = content.getId() if (content_id in container_ids and content_id not in protected and aq_base(self.context) is aq_base(aq_parent(content))): to_delete.append((content_id, content)) result = content else: result = ContentError( _(u"Cannot delete content."), content) content = yield result # Event for identifier, content in to_delete: compatibilityCall('manage_beforeDelete', content, content, self.context) notify(ObjectWillBeRemovedEvent(content, self.context, identifier)) # Delete for identifier, content in to_delete: self.context._objects = tuple( [i for i in self.context._objects if i['id'] != identifier]) self.context._delOb(identifier) try: content._v__object_deleted__ = 1 except: pass # Event for identifier, content in to_delete: notify(ObjectRemovedEvent(content, self.context, identifier)) if to_delete: notifyContainerModified(self.context)
def deleter(self): to_delete = [] container_ids = set(self.context.objectIds()) try: protected = self.context._reserved_names except: protected = () content = yield while content is not None: try: content.is_deletable() except ContentError as error: result = error else: content_id = content.getId() if (content_id in container_ids and content_id not in protected and aq_base(self.context) is aq_base(aq_parent(content))): to_delete.append((content_id, content)) result = content else: result = ContentError(_("Cannot delete content."), content) content = yield result # Event for identifier, content in to_delete: compatibilityCall('manage_beforeDelete', content, content, self.context) notify(ObjectWillBeRemovedEvent(content, self.context, identifier)) # Delete for identifier, content in to_delete: self.context._objects = tuple( [i for i in self.context._objects if i['id'] != identifier]) self.context._delOb(identifier) try: content._v__object_deleted__ = 1 except: pass # Event for identifier, content in to_delete: notify(ObjectRemovedEvent(content, self.context, identifier)) if to_delete: notifyContainerModified(self.context)
def _setObject(self, id, object, roles=None, user=None, set_owner=1, suppress_events=False): """Set an object into this container. Also sends IObjectAddedEvent. """ ob = object # better name, keep original function signature v = self._checkId(id) if v is not None: id = v t = getattr(ob, 'meta_type', None) # If an object by the given id already exists, remove it. for object_info in self._objects: if object_info['id'] == id: self._delObject(id) break if not suppress_events: notify(ObjectWillBeAddedEvent(ob, self, id)) self._objects = self._objects + ({'id': id, 'meta_type': t},) self._setOb(id, ob) ob = self._getOb(id) if set_owner: # TODO: eventify manage_fixupOwnershipAfterAdd # This will be called for a copy/clone, or a normal _setObject. ob.manage_fixupOwnershipAfterAdd() if set_owner: # Try to give user the local role "Owner", but only if # no local roles have been set on the object yet. if getattr(ob, '__ac_local_roles__', _marker) is None: user = getSecurityManager().getUser() if user is not None: userid = user.getId() if userid is not None: ob.manage_setLocalRoles(userid, ['Owner']) if not suppress_events: notify(ObjectAddedEvent(ob, self, id)) notifyContainerModified(self) compatibilityCall('manage_afterAdd', ob, ob, self) return id
def manage_delObjects(self, ids=[], REQUEST=None): """Delete objects. """ if isinstance(ids, str): ids = [ids] try: protected = self._reserved_names except: protected = () deleted_objects = [] for identifier in ids: if identifier in protected: continue ob = self._getOb(identifier, None) if ob is None: continue deleted_objects.append((identifier, ob)) for identifier, ob in deleted_objects: compatibilityCall('manage_beforeDelete', ob, ob, self) notify(ObjectWillBeRemovedEvent(ob, self, identifier)) for identifier, ob in deleted_objects: self._objects = tuple( [i for i in self._objects if i['id'] != identifier]) self._delOb(identifier) try: ob._v__object_deleted__ = 1 except: pass for identifier, ob in deleted_objects: notify(ObjectRemovedEvent(ob, self, identifier)) if deleted_objects: notifyContainerModified(self) if REQUEST is not None: # For ZMI REQUEST.RESPONSE.redirect( absoluteURL(self, REQUEST) + '/manage_main')
def manage_clone(self, ob, id, REQUEST=None): """Clone an object, creating a new object with the given id. """ if not ob.cb_isCopyable(): raise CopyError(eNotSupported % escape(ob.getId())) try: self._checkId(id) except: raise CopyError(MessageDialog( title='Invalid Id', message=sys.exc_info()[1], action ='manage_main')) self._verifyObjectPaste(ob) try: ob._notifyOfCopyTo(self, op=0) except ConflictError: raise except: raise CopyError(MessageDialog( title="Clone Error", message=sys.exc_info()[1], action='manage_main')) orig_ob = ob ob = ob._getCopy(self) ob._setId(id) notify(ObjectCopiedEvent(ob, orig_ob)) self._setObject(id, ob) ob = self._getOb(id) ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) return ob
def manage_clone(self, ob, id, REQUEST=None): """Clone an object, creating a new object with the given id. """ if not ob.cb_isCopyable(): raise CopyError, eNotSupported % escape(ob.getId()) try: self._checkId(id) except: raise CopyError, MessageDialog( title='Invalid Id', message=sys.exc_info()[1], action ='manage_main') self._verifyObjectPaste(ob) try: ob._notifyOfCopyTo(self, op=0) except ConflictError: raise except: raise CopyError, MessageDialog( title="Clone Error", message=sys.exc_info()[1], action='manage_main') orig_ob = ob ob = ob._getCopy(self) ob._setId(id) notify(ObjectCopiedEvent(ob, orig_ob)) self._setObject(id, ob) ob = self._getOb(id) ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) return ob
def copyObject(ob, newParent, newName=None): """Move an object to a new container. """ oldParent = aq_parent(ob) orig_id = ob.getId() if not ob.cb_isCopyable(): raise CopyError(eNotSupported % escape(orig_id)) try: ob._notifyOfCopyTo(newParent, op=0) except ConflictError: raise except: raise CopyError(MessageDialog( title="Copy Error", message=sys.exc_info()[1], action='manage_main')) if newName is None: id = newParent._get_id(orig_id) else: id = newName orig_ob = ob ob = ob._getCopy(oldParent) ob._setId(id) notify(ObjectCopiedEvent(ob, orig_ob)) newParent._setObject(id, ob) ob = newParent._getOb(id) ob.wl_clearLocks() ob._postCopy(newParent, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) return ob
def _pasteObjects(self, cp, cb_maxsize=0): """Paste previously copied objects into the current object. ``cp`` is the list of objects for paste as encoded by ``_cb_encode``. If calling _pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. ``cb_maxsize`` is the maximum size of the JSON representation of the object list. Set it to a non-zero value to prevent DoS attacks with huge object lists or zlib bombs. This method sends IObjectCopiedEvent and IObjectClonedEvent or IObjectWillBeMovedEvent and IObjectMovedEvent. Returns tuple of (operator, list of {'id': orig_id, 'new_id': new_id}). Where `operator` is 0 for a copy operation and 1 for a move operation. """ if cp is None: raise CopyError('No clipboard data found.') try: op, mdatas = _cb_decode(cp, cb_maxsize) except Exception as e: six.raise_from(CopyError('Clipboard Error'), e) oblist = [] app = self.getPhysicalRoot() for mdata in mdatas: m = loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except Exception: raise CopyError('Item Not Found') self._verifyObjectPaste(ob, validate_src=op + 1) oblist.append(ob) result = [] if op == 0: # Copy operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isCopyable(): raise CopyError('Not Supported') try: ob._notifyOfCopyTo(self, op=0) except ConflictError: raise except Exception: raise CopyError('Copy Error') id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) orig_ob = ob ob = ob._getCopy(self) ob._setId(id) notify(ObjectCopiedEvent(ob, orig_ob)) self._setObject(id, ob) ob = self._getOb(id) ob.wl_clearLocks() ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) elif op == 1: # Move operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isMoveable(): raise CopyError('Not Supported') try: ob._notifyOfCopyTo(self, op=1) except ConflictError: raise except Exception: raise CopyError('Move Error') if not sanity_check(self, ob): raise CopyError("This object cannot be pasted into itself") orig_container = aq_parent(aq_inner(ob)) if aq_base(orig_container) is aq_base(self): id = orig_id else: id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) notify( ObjectWillBeMovedEvent(ob, orig_container, orig_id, self, id)) # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) try: orig_container._delObject(orig_id, suppress_events=True) except TypeError: orig_container._delObject(orig_id) warnings.warn( "%s._delObject without suppress_events is discouraged." % orig_container.__class__.__name__, DeprecationWarning) ob = aq_base(ob) ob._setId(id) try: self._setObject(id, ob, set_owner=0, suppress_events=True) except TypeError: self._setObject(id, ob, set_owner=0) warnings.warn( "%s._setObject without suppress_events is discouraged." % self.__class__.__name__, DeprecationWarning) ob = self._getOb(id) notify(ObjectMovedEvent(ob, orig_container, orig_id, self, id)) notifyContainerModified(orig_container) if aq_base(orig_container) is not aq_base(self): notifyContainerModified(self) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) return op, result
def COPY(self, REQUEST, RESPONSE): """Create a duplicate of the source resource whose state and behavior match that of the source resource as closely as possible. Though we may later try to make a copy appear seamless across namespaces (e.g. from Zope to Apache), COPY is currently only supported within the Zope namespace.""" self.dav__init(REQUEST, RESPONSE) if not hasattr(aq_base(self), 'cb_isCopyable') or \ not self.cb_isCopyable(): raise MethodNotAllowed, 'This object may not be copied.' depth=REQUEST.get_header('Depth', 'infinity') if not depth in ('0', 'infinity'): raise BadRequest, 'Invalid Depth header.' dest=REQUEST.get_header('Destination', '') while dest and dest[-1]=='/': dest=dest[:-1] if not dest: raise BadRequest, 'Invalid Destination header.' try: path = REQUEST.physicalPathFromURL(dest) except ValueError: raise BadRequest, 'Invalid Destination header' name = path.pop() oflag=REQUEST.get_header('Overwrite', 'F').upper() if not oflag in ('T', 'F'): raise BadRequest, 'Invalid Overwrite header.' try: parent=self.restrictedTraverse(path) except ValueError: raise Conflict, 'Attempt to copy to an unknown namespace.' except NotFound: raise Conflict, 'Object ancestors must already exist.' except: t, v, tb=sys.exc_info() raise t, v if hasattr(parent, '__null_resource__'): raise Conflict, 'Object ancestors must already exist.' existing=hasattr(aq_base(parent), name) if existing and oflag=='F': raise PreconditionFailed, 'Destination resource exists.' 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. The If header on a copy only cares about the # lock on the destination, so we need to check out the destinations # lock status. 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) and destob.wl_isLocked(): if ifhdr: itrue = destob.dav__simpleifhandler( REQUEST, RESPONSE, 'COPY', refresh=1) if not itrue: raise PreconditonFailed else: raise Locked, 'Destination is locked.' elif IWriteLock.providedBy(parent) and parent.wl_isLocked(): if ifhdr: parent.dav__simpleifhandler(REQUEST, RESPONSE, 'COPY', refresh=1) else: raise Locked, 'Destination is locked.' self._notifyOfCopyTo(parent, op=0) ob = self._getCopy(parent) ob._setId(name) if depth=='0' and isDavCollection(ob): for id in ob.objectIds(): ob._delObject(id) notify(ObjectCopiedEvent(ob, self)) if existing: object=getattr(parent, name) self.dav__validate(object, 'DELETE', REQUEST) parent._delObject(name) parent._setObject(name, ob) ob = parent._getOb(name) ob._postCopy(parent, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) # We remove any locks from the copied object because webdav clients # don't track the lock status and the lock token for copied resources ob.wl_clearLocks() RESPONSE.setStatus(existing and 204 or 201) if not existing: RESPONSE.setHeader('Location', dest) RESPONSE.setBody('') return RESPONSE
def manage_pasteObjects_no_events(self, cb_copy_data=None, REQUEST=None): """Paste previously copied objects into the current object. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. Also sends IObjectCopiedEvent and IObjectClonedEvent or IObjectWillBeMovedEvent and IObjectMovedEvent. """ anno = IAnnotations(self) job_id = anno.get('async_move_job') if not REQUEST: # Create a request to work with REQUEST = create_request() if cb_copy_data is not None: cp = cb_copy_data elif REQUEST is not None and REQUEST.has_key('__cp'): cp = REQUEST['__cp'] else: cp = None if cp is None: raise CopyError(eNoData) try: op, mdatas = _cb_decode(cp) except: raise CopyError(eInvalid) oblist = [] app = self.getPhysicalRoot() cat = getToolByName(self, 'portal_catalog') for mdata in mdatas: m = loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except: raise CopyError(eNotFound) # self._verifyObjectPaste(ob, validate_src=op+1) oblist.append(ob) result = [] steps = oblist and int(100/len(oblist)) or 0 notify(AsyncMoveSaveProgress( self, operation='initialize', job_id=job_id, oblist_id=[ (o.getId(), o.Title()) for o in oblist ])) if op == 0: # Copy operation for i, ob in enumerate(oblist): orig_id = ob.getId() if not ob.cb_isCopyable(): raise CopyError(eNotSupported % escape(orig_id)) oid = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': oid}) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.25 )) ob = ob._getCopy(self) ob._setId(oid) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.50 )) self._setObject(oid, ob) ob = self._getOb(oid) ob.wl_clearLocks() notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.75 )) ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=1 )) notify(AsyncMoveSaveProgress( self, operation='progress', job_id=job_id, progress=steps*(i+1)/100 )) if op == 1: # Move operation for i, ob in enumerate(oblist): orig_id = ob.getId() if not sanity_check(self, ob): raise CopyError( "This object cannot be pasted into itself") orig_container = aq_parent(aq_inner(ob)) if aq_base(orig_container) is aq_base(self): oid = orig_id else: oid = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': oid}) unindex_object(ob, recursive=1) # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.25 )) try: obj_path = '/'.join( orig_container.getPhysicalPath()) + '/' + orig_id orig_container._delObject(orig_id, suppress_events=True) uncatalog_path = obj_path try: uncatalog_objs = cat(path=obj_path) for obj_brain in uncatalog_objs: uncatalog_path = obj_brain.getPath() cat.uncatalog_object(uncatalog_path) except AttributeError: logger.warn("%s could not be found", uncatalog_path) except TypeError: orig_container._delObject(orig_id) logger.warn( "%s._delObject without suppress_events is discouraged.", orig_container.__class__.__name__) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.50 )) ob = aq_base(ob) ob._setId(oid) try: self._setObject(oid, ob, set_owner=0, suppress_events=True) except TypeError: self._setObject(oid, ob, set_owner=0) logger.warn( "%s._setObject without suppress_events is discouraged.", self.__class__.__name__) ob = self._getOb(oid) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.75 )) reindex_object(ob, recursive=1) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=1 )) notify(AsyncMoveSaveProgress( self, operation='progress', job_id=job_id, progress=steps*(i+1)/100 )) notify(AsyncMoveSaveProgress( self, operation='progress', job_id=job_id, progress=1 )) del anno['async_move_job'] return result
def manage_pasteObjects(self, cb_copy_data=None, REQUEST=None): """Paste previously copied objects into the current object. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. Also sends IObjectCopiedEvent and IObjectClonedEvent or IObjectWillBeMovedEvent and IObjectMovedEvent. """ cp = cb_copy_data if cp is None and REQUEST is not None and '__cp' in REQUEST: cp = REQUEST['__cp'] if cp is None: raise CopyError('No clipboard data found.') try: op, mdatas = _cb_decode(cp) except Exception as e: six.raise_from(CopyError('Clipboard Error'), e) oblist = [] app = self.getPhysicalRoot() for mdata in mdatas: m = loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except Exception: raise CopyError('Item Not Found') self._verifyObjectPaste(ob, validate_src=op + 1) oblist.append(ob) result = [] if op == 0: # Copy operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isCopyable(): raise CopyError('Not Supported') try: ob._notifyOfCopyTo(self, op=0) except ConflictError: raise except Exception: raise CopyError('Copy Error') id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) orig_ob = ob ob = ob._getCopy(self) ob._setId(id) notify(ObjectCopiedEvent(ob, orig_ob)) self._setObject(id, ob) ob = self._getOb(id) ob.wl_clearLocks() ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) if REQUEST is not None: return self.manage_main(self, REQUEST, cb_dataValid=1) elif op == 1: # Move operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isMoveable(): raise CopyError('Not Supported') try: ob._notifyOfCopyTo(self, op=1) except ConflictError: raise except Exception: raise CopyError('Move Error') if not sanity_check(self, ob): raise CopyError("This object cannot be pasted into itself") orig_container = aq_parent(aq_inner(ob)) if aq_base(orig_container) is aq_base(self): id = orig_id else: id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) notify( ObjectWillBeMovedEvent(ob, orig_container, orig_id, self, id)) # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) try: orig_container._delObject(orig_id, suppress_events=True) except TypeError: orig_container._delObject(orig_id) warnings.warn( "%s._delObject without suppress_events is discouraged." % orig_container.__class__.__name__, DeprecationWarning) ob = aq_base(ob) ob._setId(id) try: self._setObject(id, ob, set_owner=0, suppress_events=True) except TypeError: self._setObject(id, ob, set_owner=0) warnings.warn( "%s._setObject without suppress_events is discouraged." % self.__class__.__name__, DeprecationWarning) ob = self._getOb(id) notify(ObjectMovedEvent(ob, orig_container, orig_id, self, id)) notifyContainerModified(orig_container) if aq_base(orig_container) is not aq_base(self): notifyContainerModified(self) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) if REQUEST is not None: REQUEST['RESPONSE'].setCookie( '__cp', 'deleted', path='%s' % cookie_path(REQUEST), expires='Wed, 31-Dec-97 23:59:59 GMT') REQUEST['__cp'] = None return self.manage_main(self, REQUEST, cb_dataValid=0) return result
except Exception, e: raise e orig_obj = obj obj = obj._getCopy(target) obj._setId(new_id) notify(ObjectCopiedEvent(obj, orig_obj)) target._setObject(new_id, obj) obj = target._getOb(new_id) obj.wl_clearLocks() obj._postCopy(target, op=0) subscribers.compatibilityCall('manage_afterClone', obj, obj) notify(ObjectClonedEvent(obj)) class EnableRevisionView(BrowserView): """ Clone revision view """ implements(IEnableRevisionView) def __call__(self): """ Create a new revision folder based on an existing item """ context_id = self.context.getId() parent = getMultiAdapter((self.context, self.request), name=u'plone_context_state').parent() try: uniqueid = parent.generateUniqueId('Folder') uniqueid = parent.invokeFactory('Folder', uniqueid)
def COPY(self, REQUEST, RESPONSE): """Create a duplicate of the source resource whose state and behavior match that of the source resource as closely as possible. Though we may later try to make a copy appear seamless across namespaces (e.g. from Zope to Apache), COPY is currently only supported within the Zope namespace.""" self.dav__init(REQUEST, RESPONSE) if not hasattr(aq_base(self), 'cb_isCopyable') or \ not self.cb_isCopyable(): raise MethodNotAllowed('This object may not be copied.') depth = REQUEST.get_header('Depth', 'infinity') if depth not in ('0', 'infinity'): raise BadRequest('Invalid Depth header.') dest = REQUEST.get_header('Destination', '') while dest and dest[-1] == '/': dest = dest[:-1] if not dest: raise BadRequest('Invalid Destination header.') try: path = REQUEST.physicalPathFromURL(dest) except ValueError: raise BadRequest('Invalid Destination header') name = path.pop() oflag = REQUEST.get_header('Overwrite', 'F').upper() if oflag not in ('T', 'F'): raise BadRequest('Invalid Overwrite header.') try: parent = self.restrictedTraverse(path) except ValueError: raise Conflict('Attempt to copy to an unknown namespace.') except NotFound: raise Conflict('Object ancestors must already exist.') except Exception: raise if hasattr(parent, '__null_resource__'): raise Conflict('Object ancestors must already exist.') existing = hasattr(aq_base(parent), name) if existing and oflag == 'F': raise PreconditionFailed('Destination resource exists.') try: parent._checkId(name, allow_dup=1) except Exception: raise Forbidden(sys.exc_info()[1]) try: parent._verifyObjectPaste(self) except Unauthorized: raise except Exception: raise Forbidden(sys.exc_info()[1]) # Now check locks. The If header on a copy only cares about the # lock on the destination, so we need to check out the destinations # lock status. 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) and destob.wl_isLocked(): if ifhdr: itrue = destob.dav__simpleifhandler( REQUEST, RESPONSE, 'COPY', refresh=1) if not itrue: raise PreconditionFailed() else: raise Locked('Destination is locked.') elif IWriteLock.providedBy(parent) and parent.wl_isLocked(): if ifhdr: parent.dav__simpleifhandler(REQUEST, RESPONSE, 'COPY', refresh=1) else: raise Locked('Destination is locked.') self._notifyOfCopyTo(parent, op=0) ob = self._getCopy(parent) ob._setId(name) if depth == '0' and isDavCollection(ob): for id in ob.objectIds(): ob._delObject(id) notify(ObjectCopiedEvent(ob, self)) if existing: object = getattr(parent, name) self.dav__validate(object, 'DELETE', REQUEST) parent._delObject(name) parent._setObject(name, ob) ob = parent._getOb(name) ob._postCopy(parent, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) # We remove any locks from the copied object because webdav clients # don't track the lock status and the lock token for copied resources ob.wl_clearLocks() RESPONSE.setStatus(existing and 204 or 201) if not existing: RESPONSE.setHeader('Location', dest) RESPONSE.setBody('') return RESPONSE
def manage_pasteObjects(self, cb_copy_data=None, REQUEST=None): """Paste previously copied objects into the current object. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. Also sends IObjectCopiedEvent or IObjectMovedEvent. """ if cb_copy_data is not None: cp = cb_copy_data elif REQUEST is not None and REQUEST.has_key('__cp'): cp = REQUEST['__cp'] else: cp = None if cp is None: raise CopyError, eNoData try: op, mdatas = _cb_decode(cp) except: raise CopyError, eInvalid oblist = [] app = self.getPhysicalRoot() for mdata in mdatas: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except: raise CopyError, eNotFound self._verifyObjectPaste(ob, validate_src=op+1) oblist.append(ob) result = [] if op == 0: # Copy operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isCopyable(): raise CopyError, eNotSupported % escape(orig_id) try: ob._notifyOfCopyTo(self, op=0) except ConflictError: raise except: raise CopyError, MessageDialog( title="Copy Error", message=sys.exc_info()[1], action='manage_main') id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) orig_ob = ob ob = ob._getCopy(self) ob._setId(id) notify(ObjectCopiedEvent(ob, orig_ob)) self._setObject(id, ob) ob = self._getOb(id) ob.wl_clearLocks() ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=1) elif op == 1: # Move operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isMoveable(): raise CopyError, eNotSupported % escape(orig_id) try: ob._notifyOfCopyTo(self, op=1) except ConflictError: raise except: raise CopyError, MessageDialog( title="Move Error", message=sys.exc_info()[1], action='manage_main') if not sanity_check(self, ob): raise CopyError, "This object cannot be pasted into itself" orig_container = aq_parent(aq_inner(ob)) if aq_base(orig_container) is aq_base(self): id = orig_id else: id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) notify(ObjectWillBeMovedEvent(ob, orig_container, orig_id, self, id)) # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) 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) ob = aq_base(ob) ob._setId(id) try: self._setObject(id, ob, set_owner=0, suppress_events=True) except TypeError: # BBB: removed in Zope 2.11 self._setObject(id, ob, set_owner=0) warnings.warn( "%s._setObject without suppress_events is deprecated " "and will be removed in Zope 2.11." % self.__class__.__name__, DeprecationWarning) ob = self._getOb(id) notify(ObjectMovedEvent(ob, orig_container, orig_id, self, id)) notifyContainerModified(orig_container) if aq_base(orig_container) is not aq_base(self): notifyContainerModified(self) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) if REQUEST is not None: REQUEST['RESPONSE'].setCookie('__cp', 'deleted', path='%s' % cookie_path(REQUEST), expires='Wed, 31-Dec-97 23:59:59 GMT') REQUEST['__cp'] = None return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=0) return result
def _pasteObjects(self, cp, cb_maxsize=0): """Paste previously copied objects into the current object. ``cp`` is the list of objects for paste as encoded by ``_cb_encode``. If calling _pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. ``cb_maxsize`` is the maximum size of the JSON representation of the object list. Set it to a non-zero value to prevent DoS attacks with huge object lists or zlib bombs. This method sends IObjectCopiedEvent and IObjectClonedEvent or IObjectWillBeMovedEvent and IObjectMovedEvent. Returns tuple of (operator, list of {'id': orig_id, 'new_id': new_id}). Where `operator` is 0 for a copy operation and 1 for a move operation. """ if cp is None: raise CopyError('No clipboard data found.') try: op, mdatas = _cb_decode(cp, cb_maxsize) except Exception as e: six.raise_from(CopyError('Clipboard Error'), e) oblist = [] app = self.getPhysicalRoot() for mdata in mdatas: m = loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except Exception: raise CopyError('Item Not Found') self._verifyObjectPaste(ob, validate_src=op + 1) oblist.append(ob) result = [] if op == 0: # Copy operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isCopyable(): raise CopyError('Not Supported') try: ob._notifyOfCopyTo(self, op=0) except ConflictError: raise except Exception: raise CopyError('Copy Error') id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) orig_ob = ob ob = ob._getCopy(self) ob._setId(id) notify(ObjectCopiedEvent(ob, orig_ob)) self._setObject(id, ob) ob = self._getOb(id) ob.wl_clearLocks() ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) elif op == 1: # Move operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isMoveable(): raise CopyError('Not Supported') try: ob._notifyOfCopyTo(self, op=1) except ConflictError: raise except Exception: raise CopyError('Move Error') if not sanity_check(self, ob): raise CopyError("This object cannot be pasted into itself") orig_container = aq_parent(aq_inner(ob)) if aq_base(orig_container) is aq_base(self): id = orig_id else: id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) notify(ObjectWillBeMovedEvent(ob, orig_container, orig_id, self, id)) # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) try: orig_container._delObject(orig_id, suppress_events=True) except TypeError: orig_container._delObject(orig_id) warnings.warn( "%s._delObject without suppress_events is discouraged." % orig_container.__class__.__name__, DeprecationWarning) ob = aq_base(ob) ob._setId(id) try: self._setObject(id, ob, set_owner=0, suppress_events=True) except TypeError: self._setObject(id, ob, set_owner=0) warnings.warn( "%s._setObject without suppress_events is discouraged." % self.__class__.__name__, DeprecationWarning) ob = self._getOb(id) notify(ObjectMovedEvent(ob, orig_container, orig_id, self, id)) notifyContainerModified(orig_container) if aq_base(orig_container) is not aq_base(self): notifyContainerModified(self) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) return op, result