Пример #1
0
    def _delObject(self, id, dp=1, suppress_events=False):
        """Delete an object from this container.

        Also sends IObjectWillBeRemovedEvent and IObjectRemovedEvent.
        """
        ob = self._getOb(id)

        OFS.subscribers.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)
Пример #2
0
def _delObject(self, id, dp=1, suppress_events=False):
    """Delete an object from this container.

    Also sends 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)
Пример #3
0
    def cutAndPaste(self, sourcepath, id, targetpath):
        """ uses OFS to cur and paste an object
            sourecpath must refer to the folder which contains the object to move
            id must be a string containing the id of the object to move
            targetpath must be the folder to move to
            both paths must contain one single %s to place the language
        """
        context = Acquisition.aq_inner(self.context)
        if '%s' not in sourcepath:
            return ["Wrong sourcepath"]
        if '%s' not in targetpath:
            return ["Wrong targetpath"]

        results = []

        for lang in self.langs:
            results.append("Trying language: %s" % lang)

            spath = sourcepath % lang
            source = context.restrictedTraverse(spath, None)
            if source is None:
                results.append("  # Break, source is none")
                continue
            spathtest = "/".join(source.getPhysicalPath())
            if spath != spathtest:
                results.append(
                    "  # Break, requested path not sourcepath (%s != %s)" %
                    (spath, spathtest))
                continue

            tpath = targetpath % lang
            target = context.restrictedTraverse(tpath, None)
            if target is None:
                results.append("  # Break, target is none")
                continue
            tpathtest = "/".join(target.getPhysicalPath())
            if tpath != tpathtest:
                results.append(
                    "  # Break, requested path not targetpath (%s != %s)" %
                    (tpath, tpathtest))
                continue

            ob = getattr(source, id)
            ob = Acquisition.aq_base(ob)
            if ob is None:
                results.append("  # Break, ob is None!!")
            source._delObject(id, suppress_events=True)
            target._setObject(id, ob, set_owner=0, suppress_events=True)
            ob = target._getOb(id)

            notify(ObjectMovedEvent(ob, source, id, target, id))
            notifyContainerModified(source)
            if Acquisition.aq_base(source) is not Acquisition.aq_base(target):
                notifyContainerModified(target)
            ob._postCopy(target, op=1)

            results.append("Copy&Paste successful for language %s" % lang)

        return results
Пример #4
0
def moveObjectsByDelta(self, ids, delta, subset_ids=None,
                       suppress_events=False):
    """ Move specified sub-objects by delta.
    """
    res = self.__five_original_moveObjectsByDelta(ids, delta, subset_ids)
    if not suppress_events:
        notifyContainerModified(self)
    return res
Пример #5
0
 def _delObject(self, id):
     object = self._getOb(id)
     notify(ObjectWillBeRemovedEvent(object, self, id))
     if hasattr(aq_base(object), 'manage_beforeDelete'):
         object.manage_beforeDelete(object, self)
     self._delOb(id)
     notify(ObjectRemovedEvent(object, self, id))
     notifyContainerModified(self)
Пример #6
0
 def _delObject(self, id):
     object = self._getOb(id)
     notify(ObjectWillBeRemovedEvent(object, self, id))
     if hasattr(aq_base(object), 'manage_beforeDelete'):
         object.manage_beforeDelete(object, self)
     self._delOb(id)
     notify(ObjectRemovedEvent(object, self, id))
     notifyContainerModified(self)
Пример #7
0
 def move(self, pos):
     """ AJAX method to change field position within its schema.
     """
     
     schema = IEditableSchema(self.schema)
     fieldname = self.field.__name__
     schema.moveField(fieldname, int(pos))
     notifyContainerModified(self.schema)
     notify(SchemaModifiedEvent(self.aq_parent.aq_parent))
Пример #8
0
 def _setObject(self, id, object):
     notify(ObjectWillBeAddedEvent(object, self, id))
     self._setOb(id, object)
     object = self._getOb(id)
     if hasattr(aq_base(object), 'manage_afterAdd'):
         object.manage_afterAdd(object, self)
     notify(ObjectAddedEvent(object, self, id))
     notifyContainerModified(self)
     return object
Пример #9
0
 def _setObject(self, id, object):
     notify(ObjectWillBeAddedEvent(object, self, id))
     self._setOb(id, object)
     object = self._getOb(id)
     if hasattr(aq_base(object), 'manage_afterAdd'):
         object.manage_afterAdd(object, self)
     notify(ObjectAddedEvent(object, self, id))
     notifyContainerModified(self)
     return object
Пример #10
0
    def __iter__(self):
        # Store positions in a mapping containing an id to position mapping for
        # each parent path {parent_path: {item_id: item_pos}}.
        positions_mapping = {}
        for item in self.previous:
            keys = item.keys()
            pathkey = self.pathkey(*keys)[0]
            poskey = self.poskey(*keys)[0]

            if not (pathkey and poskey):
                yield item
                continue

            item_id = item[pathkey].split('/')[-1]
            parent_path = '/'.join(item[pathkey].split('/')[:-1])
            if parent_path not in positions_mapping:
                positions_mapping[parent_path] = {}
            positions_mapping[parent_path][item_id] = item[poskey]

            yield item

        # Set positions on every parent
        for path, positions in positions_mapping.items():
            # Normalize positions
            ordered_keys = sorted(positions.keys(), key=lambda x: positions[x])
            normalized_positions = {}
            for pos, key in enumerate(ordered_keys):
                normalized_positions[key] = pos

            # TODO: After the new collective.transmogrifier release (>1.4), the
            # utils.py provides a traverse method.
            from collective.transmogrifier.utils import traverse
            parent = traverse(self.context, path)
            # parent = self.context.unrestrictedTraverse(path.lstrip('/'))
            if not parent:
                continue
            # Reorder Collage items
            if parent.portal_type == 'Collage' or parent.portal_type == 'CollageColumn' or parent.portal_type == 'CollageRow':
                for key in normalized_positions.keys():
                    parent.moveObjectToPosition(key, normalized_positions[key])

            parent_base = aq_base(parent)
            if hasattr(parent_base, 'getOrdering'):
                ordering = parent.getOrdering()
                # Only DefaultOrdering of p.folder is supported
                if (not hasattr(ordering, '_order')
                    and not hasattr(ordering, '_pos')):
                    continue
                order = ordering._order()
                pos = ordering._pos()
                order.sort(key=lambda x: normalized_positions.get(x,
                           pos.get(x, self.default_pos)))
                for i, id_ in enumerate(order):
                    pos[id_] = i

                notifyContainerModified(parent)
Пример #11
0
    def cutAndPaste(self, sourcepath, id, targetpath):
        """ Uses OFS to cut and paste an object.
            Sourecpath must refer to the folder which contains the object to
            move. id must be a string containing the id of the object to move.
            targetpath must be the folder to move to.
            Both paths must contain one single %s to place the language
        """
        context = Acquisition.aq_inner(self.context)
        if "%s" not in sourcepath:
            return ["Wrong sourcepath"]
        if "%s" not in targetpath:
            return ["Wrong targetpath"]

        results = []

        for lang in self.langs:
            results.append("Trying language: %s" % lang)

            spath = sourcepath % lang
            source = context.restrictedTraverse(spath, None)
            if source is None:
                results.append("  # Break, source is none")
                continue
            spathtest = "/".join(source.getPhysicalPath())
            if spath != spathtest:
                results.append("  # Break, requested path not sourcepath " "(%s != %s)" % (spath, spathtest))
                continue

            tpath = targetpath % lang
            target = context.restrictedTraverse(tpath, None)
            if target is None:
                results.append("  # Break, target is none")
                continue
            tpathtest = "/".join(target.getPhysicalPath())
            if tpath != tpathtest:
                results.append("  # Break, requested path not targetpath " "(%s != %s)" % (tpath, tpathtest))
                continue

            ob = getattr(source, id, None)
            ob = Acquisition.aq_base(ob)
            if ob is None:
                results.append("  # Break, ob is None!!")
                continue
            source._delObject(id, suppress_events=True)
            target._setObject(id, ob, set_owner=0, suppress_events=True)
            ob = target._getOb(id)

            notify(ObjectMovedEvent(ob, source, id, target, id))
            notifyContainerModified(source)
            if Acquisition.aq_base(source) is not Acquisition.aq_base(target):
                notifyContainerModified(target)
            ob._postCopy(target, op=1)

            results.append("Copy&Paste successful for language %s" % lang)

        return results
Пример #12
0
def moveObjectsByDelta(self,
                       ids,
                       delta,
                       subset_ids=None,
                       suppress_events=False):
    """ Move specified sub-objects by delta.
    """
    res = self.__five_original_moveObjectsByDelta(ids, delta, subset_ids)
    if not suppress_events:
        notifyContainerModified(self)
    return res
Пример #13
0
    def __iter__(self):
        # Store positions in a mapping containing an id to position mapping for
        # each parent path {parent_path: {item_id: item_pos}}.
        positions_mapping = {}
        for item in self.previous:
            keys = item.keys()
            pathkey = self.pathkey(*keys)[0]
            poskey = self.poskey(*keys)[0]

            if not (pathkey and poskey):
                yield item
                continue

            item_id = item[pathkey].split('/')[-1]
            parent_path = '/'.join(item[pathkey].split('/')[:-1])
            if parent_path not in positions_mapping:
                positions_mapping[parent_path] = {}
            positions_mapping[parent_path][item_id] = item[poskey]

            yield item

        # Set positions on every parent
        for path, positions in positions_mapping.items():

            # Normalize positions
            ordered_keys = sorted(positions.keys(), key=lambda x: positions[x])
            normalized_positions = {}
            for pos, key in enumerate(ordered_keys):
                normalized_positions[key] = pos

            # TODO: After the new collective.transmogrifier release (>1.4), the
            # utils.py provides a traverse method.
            from collective.transmogrifier.utils import traverse
            parent = traverse(self.context, path)
            #parent = self.context.unrestrictedTraverse(path.lstrip('/'))
            if not parent:
                continue

            parent_base = aq_base(parent)

            if hasattr(parent_base, 'getOrdering'):
                ordering = parent.getOrdering()
                # Only DefaultOrdering of p.folder is supported
                if (not hasattr(ordering, '_order')
                    and not hasattr(ordering, '_pos')):
                    continue
                order = ordering._order()
                pos = ordering._pos()
                order.sort(key=lambda x: normalized_positions.get(x,
                           pos.get(x, self.default_pos)))
                for i, id_ in enumerate(order):
                    pos[id_] = i

                notifyContainerModified(parent)
Пример #14
0
 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
Пример #15
0
    def moveObjectsByDelta(self,
                           ids,
                           delta,
                           subset_ids=None,
                           suppress_events=False):
        """ Move specified sub-objects by delta.
        """
        if type(ids) is StringType:
            ids = (ids, )
        min_position = 0
        objects = list(self._objects)
        if subset_ids == None:
            subset_ids = [obj['id'] for obj in objects]
        else:
            subset_ids = list(subset_ids)
        # unify moving direction
        if delta > 0:
            ids = list(ids)
            ids.reverse()
            subset_ids.reverse()
        counter = 0

        for id in ids:
            old_position = subset_ids.index(id)
            new_position = max(old_position - abs(delta), min_position)
            if new_position == min_position:
                min_position += 1
            if not old_position == new_position:
                subset_ids.remove(id)
                subset_ids.insert(new_position, id)
                counter += 1

        if counter > 0:
            if delta > 0:
                subset_ids.reverse()
            obj_dict = {}
            for obj in objects:
                obj_dict[obj['id']] = obj
            pos = 0
            for i in range(len(objects)):
                if objects[i]['id'] in subset_ids:
                    try:
                        objects[i] = obj_dict[subset_ids[pos]]
                        pos += 1
                    except KeyError:
                        raise ValueError('The object with the id "%s" does '
                                         'not exist.' % subset_ids[pos])
            self._objects = tuple(objects)

        if not suppress_events:
            notifyContainerModified(self)

        return counter
Пример #16
0
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
Пример #17
0
    def moveObjectsByDelta(self, ids, delta, subset_ids=None,
                           suppress_events=False):
        """Move specified sub-objects by delta."""
        if type(ids) is StringType:
            ids = (ids,)
        min_position = 0
        objects = list(self._objects)
        if subset_ids == None:
            subset_ids = self.getCMFObjectsSubsetIds(objects)
        else:
            subset_ids = list(subset_ids)
        # unify moving direction
        if delta > 0:
            ids = list(ids)
            ids.reverse()
            subset_ids.reverse()
        counter = 0

        for id in ids:
            try:
                old_position = subset_ids.index(id)
            except ValueError:
                continue
            new_position = max(old_position - abs(delta), min_position)
            if new_position == min_position:
                min_position += 1
            if not old_position == new_position:
                subset_ids.remove(id)
                subset_ids.insert(new_position, id)
                counter += 1

        if counter > 0:
            if delta > 0:
                subset_ids.reverse()
            obj_dict = {}
            for obj in objects:
                obj_dict[obj['id']] = obj
            pos = 0
            for i in range(len(objects)):
                if objects[i]['id'] in subset_ids:
                    try:
                        objects[i] = obj_dict[subset_ids[pos]]
                        pos += 1
                    except KeyError:
                        raise ValueError('The object with the id "%s" does '
                                         'not exist.' % subset_ids[pos])
            self._objects = tuple(objects)

        if not suppress_events:
            notifyContainerModified(self)

        return counter
Пример #18
0
    def __iter__(self):
        # Store positions in a mapping containing an id to position mapping for
        # each parent path {parent_path: {item_id: item_pos}}.
        positions_mapping = {}
        for item in self.previous:
            keys = list(item.keys())
            pathkey = self.pathkey(*keys)[0]
            poskey = self.poskey(*keys)[0]
            if not (pathkey and poskey):
                yield item
                continue

            item_id = item[pathkey].split('/')[-1]
            parent_path = '/'.join(item[pathkey].split('/')[:-1])
            if parent_path not in positions_mapping:
                positions_mapping[parent_path] = {}
            positions_mapping[parent_path][item_id] = item[poskey]

            yield item

        # Set positions on every parent
        for path, positions in list(positions_mapping.items()):

            # Normalize positions
            ordered_keys = sorted(list(positions.keys()),
                                  key=lambda x: positions[x])
            normalized_positions = {}
            for pos, key in enumerate(ordered_keys):
                normalized_positions[key] = pos

            path = safe_unicode(path.lstrip('/')).encode('ascii')
            parent = traverse(self.context, path, None)

            if not parent:
                continue

            parent_base = aq_base(parent)

            if hasattr(parent_base, 'getOrdering'):
                ordering = parent.getOrdering()
                # Only DefaultOrdering of p.folder is supported
                if (not hasattr(ordering, '_order')
                        and not hasattr(ordering, '_pos')):
                    continue
                order = ordering._order()
                pos = ordering._pos()
                order.sort(key=lambda x: normalized_positions.get(
                    x, pos.get(x, self.default_pos)))
                for i, id_ in enumerate(order):
                    pos[id_] = i

                notifyContainerModified(parent)
Пример #19
0
    def _delObject(self, id, dp=1, suppress_events=False):
        ob = self._getOb(id)

        OFS.subscribers.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)
Пример #20
0
    def _delObject(self, id, dp=1, suppress_events=False):
        ob = self._getOb(id)

        OFS.subscribers.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)
Пример #21
0
    def __iter__(self):
        # Store positions in a mapping containing an id to position mapping for
        # each parent path {parent_path: {item_id: item_pos}}.
        positions_mapping = {}
        for item in self.previous:
            keys = item.keys()
            pathkey = self.pathkey(*keys)[0]
            poskey = self.poskey(*keys)[0]
            if not (pathkey and poskey):
                yield item
                continue

            item_id = item[pathkey].split('/')[-1]
            parent_path = '/'.join(item[pathkey].split('/')[:-1])
            if parent_path not in positions_mapping:
                positions_mapping[parent_path] = {}
            positions_mapping[parent_path][item_id] = item[poskey]

            yield item

        # Set positions on every parent
        for path, positions in positions_mapping.items():

            # Normalize positions
            ordered_keys = sorted(positions.keys(), key=lambda x: positions[x])
            normalized_positions = {}
            for pos, key in enumerate(ordered_keys):
                normalized_positions[key] = pos

            path = safe_unicode(path.lstrip('/')).encode('ascii')
            parent = traverse(self.context, path, None)

            if not parent:
                continue

            parent_base = aq_base(parent)

            if hasattr(parent_base, 'getOrdering'):
                ordering = parent.getOrdering()
                # Only DefaultOrdering of p.folder is supported
                if (not hasattr(ordering, '_order')
                        and not hasattr(ordering, '_pos')):
                    continue
                order = ordering._order()
                pos = ordering._pos()
                order.sort(key=lambda x: normalized_positions.get(
                    x, pos.get(x, self.default_pos)))
                for i, id_ in enumerate(order):
                    pos[id_] = i

                notifyContainerModified(parent)
Пример #22
0
    def __setitem__(self, name, object):
        """Add the given object to the folder under the given name.
        """
        if not isinstance(name, int):
            raise TypeError("Name must be an integer rather than a %s" %
                            name.__class__.__name__)

        if self.__contains__(name):
            raise DuplicationError("key %r is already in use." % name)

        object, event = contained.containedEvent(object, self, name)
        IOBTreeStorage.__setitem__(self, name, object)

        if event:
            notify(event)
            contained.notifyContainerModified(self)
Пример #23
0
 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
Пример #24
0
def setitem(container, setitemmf, name, object):
    # Do basic name check:
    if isinstance(name, str):
        try:
            name = unicode(name)
        except UnicodeError:
            raise TypeError("name not unicode or ascii string")
    elif not isinstance(name, unicode):
        raise TypeError("name not unicode or ascii string")

    if not name:
        raise ValueError("empty names are not allowed")

    old = container.get(name)
    if old is object:
        return
    if old is not None:
        raise DuplicationError(name)

    oldparent = object.__parent__
    oldname = object.__name__

    # create and store draft
    dct = getUtility(IDraftContentType, IContentType(object).name)

    draft = dct.klass(removeAllProxies(object))

    draft.__name__ = name
    draft.__parent__ = container

    if oldparent is not None:
        draft.shortname = oldname
        draft.location = getUtility(IIntIds).getId(oldparent)

    event.notify(ObjectCreatedEvent(draft))

    # added draft to container
    setitemmf(name, draft)
    event.notify(ObjectAddedEvent(draft, container, name))

    # notify content and container objects
    if oldparent is not None:
        event.notify(
            ObjectMovedEvent(object,oldparent,oldname,draft,object.__name__))

    event.notify(ObjectModifiedEvent(object))
    notifyContainerModified(container)
Пример #25
0
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
Пример #26
0
 def manage_delObjects(self, ids=[], REQUEST=None):
     """Delete reflected files or directories
     
     The objects specified in 'ids' get deleted. This emulates the
     ObjectManager interface enough to support deletion in Plone only.
     When file removal fails, errors are communicated through the return
     of the successful ids and the IStatusMessage utility
     
     """
     if type(ids) is StringType:
         ids = [ids]
     if not ids:
         raise ValueError('No items specified')
     
     # To avoid inconsistencies, first test file availability
     for id in ids:
         if not self.has_key(id):
             raise KeyError(id)
         notify(ObjectWillBeRemovedEvent(self[id], self, id))
         
     problem_ids = []
     path = self.getFilesystemPath()
     for id in ids:
         subpath = os.path.join(path, id)
         ob = self[id]
         try:
             if os.path.isdir(subpath):
                 shutil.rmtree(subpath)
             else:
                 os.unlink(subpath)
             notify(ObjectRemovedEvent(ob, self, id))
         except OSError:
             problem_ids.append(id)
                 
     if problem_ids:
         sm = IStatusMessage(getattr(self, 'REQUEST', None), None)
         if sm is not None:
             sm.addStatusMessage(
                 'Failed to remove some files: %s' % problem_ids, 'stop')
             
     if set(ids) - set(problem_ids):
         indexview = self.unrestrictedTraverse('@@index')
         indexview.index()
         notifyContainerModified(self)
     
     return problem_ids or None # None expected by webdav on success
Пример #27
0
 def moveObjectsByDelta(self, ids, delta, subset_ids=None,
         suppress_events=False):
     """ see interfaces.py """
     order = self._order()
     pos = self._pos()
     min_position = 0
     if isinstance(ids, basestring):
         ids = [ids]
     if subset_ids is None:
         subset_ids = self.idsInOrder()
     elif not isinstance(subset_ids, list):
         subset_ids = list(subset_ids)
     if delta > 0:                   # unify moving direction
         ids = reversed(ids)
         subset_ids.reverse()
     counter = 0
     for id in ids:
         try:
             old_position = subset_ids.index(id)
         except ValueError:
             continue
         new_position = max(old_position - abs(delta), min_position)
         if new_position == min_position:
             min_position += 1
         if not old_position == new_position:
             subset_ids.remove(id)
             subset_ids.insert(new_position, id)
             counter += 1
     if counter > 0:
         if delta > 0:
             subset_ids.reverse()
         idx = 0
         for i in range(len(order)):
             if order[i] in subset_ids:
                 id = subset_ids[idx]
                 try:
                     order[i] = id
                     pos[id] = i
                     idx += 1
                 except KeyError:
                     raise ValueError('No object with id "%s" exists.' % id)
     if not suppress_events:
         notifyContainerModified(self.context)
     return counter
Пример #28
0
    def _setObject(self,
                   id,
                   object,
                   roles=None,
                   user=None,
                   set_owner=1,
                   suppress_events=False):
        ob = object  # better name, keep original function signature
        v = self._checkId(id)
        if v is not None:
            id = v

        # If an object by the given id already exists, remove it.
        if self.has_key(id):
            self._delObject(id)

        if not suppress_events:
            notify(ObjectWillBeAddedEvent(ob, self, id))

        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()

            # 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)

        OFS.subscribers.compatibilityCall('manage_afterAdd', ob, ob, self)

        return id
Пример #29
0
 def manage_renameObjects(self, ids=[], new_ids=[]):
     """Rename reflected files or directories
     
     The objects specified in 'ids' get renamed to 'new_ids'. This emulates 
     the CopyContainer interface enough to support renaming in Plone only.
     When file renaming fails, errors are communicated through the return
     of the successful ids and the IStatusMessage utility
     
     """
     if len(ids) != len(new_ids):
         raise BadRequest('Please rename each listed object.')
     if not ids:
         raise ValueError('No items specified')
     
     # To avoid inconsistencies, first test file availability
     for old, new in zip(ids, new_ids):
         if not self.has_key(old):
             raise KeyError(old)
         if not self.acceptableFilename(new) or self.has_key(new):
             raise CopyError, 'Invalid Id'
         notify(ObjectWillBeMovedEvent(self[old], self, old, self, new))
         
     problem_ids = []
     path = self.getFilesystemPath()
     for id in ids:
         try:
             os.rename(os.path.join(path, old), os.path.join(path, new))
             notify(ObjectMovedEvent(self[new], self, old, self, new))
         except OSError:
             problem_ids.append(old)
                 
     if problem_ids:
         sm = IStatusMessage(getattr(self, 'REQUEST', None), None)
         if sm is not None:
             sm.addStatusMessage(
                 'Failed to rename some files: %s' % problem_ids, 'stop')
             
     if set(ids) - set(problem_ids):
         indexview = self.unrestrictedTraverse('@@index')
         indexview.index()
         notifyContainerModified(self)
     
     return list(set(ids) - set(problem_ids))
Пример #30
0
    def _constructInstance(self, container, id, *args, **kw):
        """Build a bare instance of the appropriate type.

        Does not do any security checks.
        """
        constructor = self.restrictedTraverse(self.constructor_path)

        # make sure ownership is explicit before switching the context
        if not hasattr(aq_base(constructor), '_owner'):
            constructor._owner = aq_get(constructor, '_owner')
        #   Rewrap to get into container's context.
        constructor = aq_base(constructor).__of__(container)

        id = str(id)
        obj = constructor(container, id, *args, **kw)
        if hasattr(obj, '_setPortalTypeName'):
            obj._setPortalTypeName(self.getId())
        notify(ObjectAddedEvent(obj, container, obj.getId()))
        notifyContainerModified(container)
        return obj
Пример #31
0
    def _constructInstance(self, container, id, *args, **kw):
        """Build a bare instance of the appropriate type.

        Does not do any security checks.
        """
        constructor = self.restrictedTraverse( self.constructor_path )

        # make sure ownership is explicit before switching the context
        if not hasattr( aq_base(constructor), '_owner' ):
            constructor._owner = aq_get(constructor, '_owner')
        #   Rewrap to get into container's context.
        constructor = aq_base(constructor).__of__( container )

        id = str(id)
        obj = constructor(container, id, *args, **kw)
        if hasattr(obj, '_setPortalTypeName'):
            obj._setPortalTypeName(self.getId())
        notify(ObjectAddedEvent(obj, container, obj.getId()))
        notifyContainerModified(container)
        return obj
Пример #32
0
    def _constructInstance(self, container, id, *args, **kw):
        """Build a bare instance of the appropriate type.

        Does not do any security checks.
        """
        # XXX: this method violates the rules for tools/utilities:
        # it depends on self.REQUEST
        id = str(id)

        if self.product:
            # oldstyle factory
            m = self._getFactoryMethod(container, check_security=0)

            if getattr(aq_base(m), 'isDocTemp', 0):
                kw['id'] = id
                newid = m(m.aq_parent, self.REQUEST, *args, **kw)
            else:
                newid = m(id, *args, **kw)
            # allow factory to munge ID
            newid = newid or id
            obj = container._getOb(newid)
            if hasattr(obj, '_setPortalTypeName'):
                obj._setPortalTypeName(self.getId())
            notify(ObjectCreatedEvent(obj))
            notify(ObjectAddedEvent(obj, container, newid))
            notifyContainerModified(container)

        else:
            # newstyle factory
            factory = getUtility(IFactory, self.factory)
            obj = factory(id, *args, **kw)
            if hasattr(obj, '_setPortalTypeName'):
                obj._setPortalTypeName(self.getId())
            notify(ObjectCreatedEvent(obj))
            rval = container._setObject(id, obj)
            newid = isinstance(rval, basestring) and rval or id
            obj = container._getOb(newid)

        return obj
Пример #33
0
    def _constructInstance(self, container, id, *args, **kw):
        """Build a bare instance of the appropriate type.

        Does not do any security checks.
        """
        # XXX: this method violates the rules for tools/utilities:
        # it depends on self.REQUEST
        id = str(id)

        if self.product:
            # oldstyle factory
            m = self._getFactoryMethod(container, check_security=0)

            if getattr(aq_base(m), 'isDocTemp', 0):
                kw['id'] = id
                newid = m(m.aq_parent, self.REQUEST, *args, **kw)
            else:
                newid = m(id, *args, **kw)
            # allow factory to munge ID
            newid = newid or id
            obj = container._getOb(newid)
            if hasattr(obj, '_setPortalTypeName'):
                obj._setPortalTypeName(self.getId())
            notify(ObjectCreatedEvent(obj))
            notify(ObjectAddedEvent(obj, container, newid))
            notifyContainerModified(container)

        else:
            # newstyle factory
            factory = getUtility(IFactory, self.factory)
            obj = factory(id, *args, **kw)
            if hasattr(obj, '_setPortalTypeName'):
                obj._setPortalTypeName(self.getId())
            notify(ObjectCreatedEvent(obj))
            rval = container._setObject(id, obj)
            newid = isinstance(rval, basestring) and rval or id
            obj = container._getOb(newid)

        return obj
Пример #34
0
    def _setObject(self, id, object, roles=None, user=None, set_owner=1,
                   suppress_events=False):
        ob = object # better name, keep original function signature
        v = self._checkId(id)
        if v is not None:
            id = v

        # If an object by the given id already exists, remove it.
        if self.has_key(id):
            self._delObject(id)

        if not suppress_events:
            notify(ObjectWillBeAddedEvent(ob, self, id))

        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()

            # 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)

        OFS.subscribers.compatibilityCall('manage_afterAdd', ob, ob, self)

        return id
Пример #35
0
    def updateOrder(self, order):
        if not isinstance(order, types.ListType) and \
            not isinstance(order, types.TupleType):
            raise TypeError('order must be a tuple or a list.')

        if len(order) != len(self.order):
            raise ValueError("Incompatible key set.")

        was_dict = {}
        will_be_dict = {}
        new_order = {}

        orderValues = self.order.values()

        for i in range(len(order)):
            was_dict[orderValues[i]] = 1
            will_be_dict[order[i]] = 1
            new_order[i] = order[i]

        if will_be_dict != was_dict:
            raise ValueError("Incompatible key set.")

        order = []
        keys = list(new_order.keys())
        keys.sort()
        for key in keys:
            if new_order[key] not in order:
                order.append(new_order[key])

        self.order.clear()
        self.border.clear()

        for idx in range(len(order)):
            self.order[idx] = order[idx]
            self.border[order[idx]] = idx
        notifyContainerModified(self)
Пример #36
0
    def updateOrder(self, order):
        """ See `IOrderedContainer`.

        >>> oc = OrderedContainer()
        >>> oc['foo'] = 'bar'
        >>> oc['baz'] = 'quux'
        >>> oc['zork'] = 'grue'
        >>> oc.keys()
        ['foo', 'baz', 'zork']
        >>> oc.updateOrder(['baz', 'foo', 'zork'])
        >>> oc.keys()
        ['baz', 'foo', 'zork']
        >>> oc.updateOrder(['baz', 'zork', 'foo'])
        >>> oc.keys()
        ['baz', 'zork', 'foo']
        >>> oc.updateOrder(['baz', 'zork', 'foo'])
        >>> oc.keys()
        ['baz', 'zork', 'foo']
        >>> oc.updateOrder(('zork', 'foo', 'baz'))
        >>> oc.keys()
        ['zork', 'foo', 'baz']
        >>> oc.updateOrder(['baz', 'zork'])
        Traceback (most recent call last):
        ...
        ValueError: Incompatible key set.
        >>> oc.updateOrder(['foo', 'bar', 'baz', 'quux'])
        Traceback (most recent call last):
        ...
        ValueError: Incompatible key set.
        >>> oc.updateOrder(1)
        Traceback (most recent call last):
        ...
        TypeError: order must be a tuple or a list.
        >>> oc.updateOrder('bar')
        Traceback (most recent call last):
        ...
        TypeError: order must be a tuple or a list.
        >>> oc.updateOrder(['baz', 'zork', 'quux'])
        Traceback (most recent call last):
        ...
        ValueError: Incompatible key set.
        >>> del oc['baz']
        >>> del oc['zork']
        >>> del oc['foo']
        >>> len(oc)
        0
        """

        if not isinstance(order, ListType) and \
            not isinstance(order, TupleType):
            raise TypeError('order must be a tuple or a list.')

        if len(order) != len(self._order):
            raise ValueError("Incompatible key set.")

        was_dict = {}
        will_be_dict = {}
        new_order = PersistentList()

        for i in range(len(order)):
            was_dict[self._order[i]] = 1
            will_be_dict[order[i]] = 1
            new_order.append(order[i])

        if will_be_dict != was_dict:
            raise ValueError("Incompatible key set.")

        self._order = new_order
        notifyContainerModified(self)
Пример #37
0
    def COPY(self, REQUEST, RESPONSE):
        """Create a duplicate of the source resource. This is only allowed
        within the same reflecto directory."""
        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 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)
        
        #### This part is reflecto specific
        if existing:
            object=getattr(parent, name)
            self.dav__validate(object, 'DELETE', REQUEST)
            parent.manage_delObjects([name])
        
        oldpath = self.getFilesystemPath()
        newpath = os.path.join(parent.getFilesystemPath(), name)
        
        if IReflectoDirectory.providedBy(self):
            if depth=='0':
                os.mkdir(newpath, 0775)
            else:
                shutil.copytree(oldpath, newpath)
        else:
            shutil.copy2(oldpath, newpath)
        ob = parent[name]
        ob.indexObject()
        notify(ObjectCopiedEvent(ob, self))
        notify(ObjectClonedEvent(ob))
        notifyContainerModified(parent)
        ####

        # 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
Пример #38
0
    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.
        """
        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)

                OFS.subscribers.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
Пример #39
0
    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
Пример #40
0
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
Пример #41
0
def cut_and_paste(ob, *args, **kw):
    """ Uses OFS to cut and paste an object.
    """
    err = list()
    targetpath = kw['target_path']
    if not targetpath:
        err.append('You must specify a target path')
    id = kw['id_to_move']
    if not id:
        err.append(u'You must select an object to move')
    targetpath = targetpath.encode('utf-8')
    id = id.encode('utf-8')
    lang = kw['lang']
    portal_path = kw['portal_path']

    if not err:
        if targetpath.startswith('/'):
            if not targetpath.startswith(portal_path):
                targetpath = portal_path + targetpath
        target_base = ob.restrictedTraverse(targetpath, None)
        if target_base is None:
            err.append(u'No object was found at the given taget path %s' \
               % targetpath)
            return err
        if ITranslatable.providedBy(target_base):
            target = target_base.getTranslation(lang)
        else:
            err.append(u'The target object is not translatable. Please '\
                'choose a different target that is translatable.')
            return err
        if target is None:
            err.append(u'No translation in language "%s" was found of '\
                'the target %s' % (lang, targetpath))
            return err
        if not IBaseFolder.providedBy(target):
            err.append(u'The target object is not folderish - pasting is '\
                'not possible.')
            return err
        name = None
        if id in ob.objectIds():
            name = id
            trans_object = getattr(ob, name)
        else:
            # look for translation via getTranslation
            target_object = kw.get('target_object', None)
            if target_object:
                trans_object = target_object.getTranslation(lang)
                if trans_object:
                    if Acquisition.aq_parent(trans_object) == ob:
                        name = trans_object.getId()

        if name is None:
            err.append(u'No translation of the requested object for language '\
                '%s found in %s' % (
                lang, '/'.join(ob.getPhysicalPath())))
            return err
        if target == trans_object:
            err.append(u'The target cannot be identical to the object you '\
                'want to move')
            return err

        ob._delObject(name, suppress_events=True)
        target._setObject(id, trans_object, set_owner=0, suppress_events=True)
        trans_object = target._getOb(id)

        notify(ObjectMovedEvent(trans_object, ob, id, target, id))
        notifyContainerModified(ob)
        if Acquisition.aq_base(ob) is not Acquisition.aq_base(target):
            notifyContainerModified(target)
        trans_object._postCopy(target, op=1)
        trans_object.reindexObject()

    return err
Пример #42
0
    def MOVE(self, REQUEST, RESPONSE):
        """Move a resource to a new location within the reflector"""
        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) 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) 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)

        #### This part is reflecto specific
        notify(ObjectWillBeMovedEvent(self, orig_container, orig_id,
                                      parent, name))
        self.unindexObject()
        if existing:
            object=parent[name]
            self.dav__validate(object, 'DELETE', REQUEST)
            parent.manage_delObjects([name])
            
        os.rename(self.getFilesystemPath(), os.path.join(parent.getFilesystemPath(), name))
        ob = parent[name]
        ob.indexObject()
        ####
        
        notify(ObjectMovedEvent(ob, orig_container, orig_id, parent, name))
        notifyContainerModified(orig_container)
        if aq_base(orig_container) is not aq_base(parent):
            notifyContainerModified(parent)

        RESPONSE.setStatus(existing and 204 or 201)
        if not existing:
            RESPONSE.setHeader('Location', dest)
        RESPONSE.setBody('')
        return RESPONSE
Пример #43
0
    def manage_renameObject(self, id, new_id, REQUEST=None):
        """Rename a particular sub-object.
        """
        try:
            self._checkId(new_id)
        except:
            raise CopyError, MessageDialog(
                title='Invalid Id',
                message=sys.exc_info()[1],
                action ='manage_main')

        ob = self._getOb(id)

        if ob.wl_isLocked():
            raise ResourceLockedError, ('Object "%s" is locked via WebDAV'
                                        % ob.getId())
        if not ob.cb_isMoveable():
            raise CopyError, eNotSupported % escape(id)
        self._verifyObjectPaste(ob)

        try:
            ob._notifyOfCopyTo(self, op=1)
        except ConflictError:
            raise
        except:
            raise CopyError, MessageDialog(
                title="Rename Error",
                message=sys.exc_info()[1],
                action ='manage_main')

        notify(ObjectWillBeMovedEvent(ob, self, id, self, new_id))

        try:
            self._delObject(id, suppress_events=True)
        except TypeError:
            # BBB: removed in Zope 2.11
            self._delObject(id)
            warnings.warn(
                "%s._delObject without suppress_events is deprecated "
                "and will be removed in Zope 2.11." %
                self.__class__.__name__, DeprecationWarning)
        ob = aq_base(ob)
        ob._setId(new_id)

        # Note - because a rename always keeps the same context, we
        # can just leave the ownership info unchanged.
        try:
            self._setObject(new_id, ob, set_owner=0, suppress_events=True)
        except TypeError:
            # BBB: removed in Zope 2.11
            self._setObject(new_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(new_id)

        notify(ObjectMovedEvent(ob, self, id, self, new_id))
        notifyContainerModified(self)

        ob._postCopy(self, op=1)

        if REQUEST is not None:
            return self.manage_main(self, REQUEST, update_menu=1)
        return None
Пример #44
0
    def update(self):
        if self.updated:
            return

        context = self.context
        request = self.request

        if 'form.buttons.apply' in request:
            self.environ['applyButton'] = True

        elif 'form.buttons.rename' in request:
            if not request.get("ids"):
                IStatusMessage(request).add(
                    _("You didn't specify any ids to rename."), 'warning')
            else:
                interface.alsoProvides(self, IRenameContainerContents)

        elif "form.buttons.delete" in request:
            self.removeObjects()

        elif "form.buttons.copy" in request:
            self.copyObjects()

        elif "form.buttons.cut" in request:
            self.cutObjects()

        elif "form.buttons.paste" in request:
            self.pasteObjects()

        elif "form.buttons.pasteLink" in request:
            self.pasteObjectLinks()

        order = IOrder(context, None)
        if order is not None and IReordable.providedBy(order):
            self.orderButtons = len(order) > 1

            changed = False
            selected = request.get('ids', [])

            if 'form.buttons.moveup' in request:
                changed = order.moveUp(selected)

            elif 'form.buttons.movetop' in request:
                changed = order.moveTop(selected)

            elif 'form.buttons.movedown' in request:
                changed = order.moveDown(selected)

            elif 'form.buttons.movebottom' in request:
                changed = order.moveBottom(selected)

            if changed:
                notifyContainerModified(context)
                IStatusMessage(request).add(
                    _(u'Items order have been changed.'))
        else:
            self.orderButtons = False

        super(ContainerContents, self).update()

        self.setupButtons()

        self.updated = True
Пример #45
0
def manage_renameObject(self, id, new_id, REQUEST=None):
    """Rename a particular sub-object.
    """
    try:
        self._checkId(new_id)
    except:
        raise CopyError, MessageDialog(
            title='Invalid Id',
            message=sys.exc_info()[1],
            action ='manage_main')

    ob = self._getOb(id)

    if ob.wl_isLocked():
        raise ResourceLockedError, ('Object "%s" is locked via WebDAV'
                                    % ob.getId())
    if not ob.cb_isMoveable():
        raise CopyError, eNotSupported % escape(id)
    self._verifyObjectPaste(ob)

    try:
        ob._notifyOfCopyTo(self, op=1)
    except ConflictError:
        raise
    except:
        raise CopyError, MessageDialog(
            title="Rename Error",
            message=sys.exc_info()[1],
            action ='manage_main')

    notify(ObjectWillBeMovedEvent(ob, self, id, self, new_id))

    try:
        self._delObject(id, suppress_events=True)
    except TypeError:
        # BBB: removed in Zope 2.11
        self._delObject(id)
        warnings.warn(
            "%s._delObject without suppress_events is deprecated "
            "and will be removed in Zope 2.11." %
            self.__class__.__name__, DeprecationWarning)
    ob = aq_base(ob)
    ob._setId(new_id)

    # Note - because a rename always keeps the same context, we
    # can just leave the ownership info unchanged.
    try:
        self._setObject(new_id, ob, set_owner=0, suppress_events=True)
    except TypeError:
        # BBB: removed in Zope 2.11
        self._setObject(new_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(new_id)

    notify(ObjectMovedEvent(ob, self, id, self, new_id))
    notifyContainerModified(self)

    ob._postCopy(self, op=1)

    if REQUEST is not None:
        return self.manage_main(self, REQUEST, update_menu=1)
    return None
Пример #46
0
    def manage_pasteObjects(self, cp):
        """Paste previously copied objects into the current object."""
        op, mdatas = _cb_decode(cp)
        COPY = op == 0 # Otherwise its a paste operation
        
        # Copy or paste always fails without write permission here
        sman = getSecurityManager()
        if not sman.checkPermission(AddFilesystemObject, self):
            raise CopyError, 'Insufficient Privileges'
        
        oblist = []
        app = self.getPhysicalRoot()
        
        # Loading and security checks
        for mdata in mdatas:
            m = loadMoniker(mdata)
            try:
                ob = m.bind(app)
            except ConflictError:
                raise
            except:
                raise CopyError, 'Item not found'
            if not IReflectoProxy.providedBy(ob) or IReflector.providedBy(ob):
                raise CopyError, 'Cannot paste into this object'
            parent = aq_parent(aq_inner(ob))
            if not sman.validate(None, parent, None, ob):
                raise Unauthorized(ob.getId())
            if not COPY:
                if not sman.checkPermission(DeleteObjects, parent):
                    raise Unauthorized('Delete not allowed')
                prefix = os.path.commonprefix((ob.getFilesystemPath(),
                                               self.getFilesystemPath()))
                if prefix == ob.getFilesystemPath():
                    raise CopyError, "This object cannot be pasted into itself"
            oblist.append(ob)

        result = []
        problem_ids = []
        path = self.getFilesystemPath()
        for ob in oblist:
            old = ob.getId()
            new = self._generate_copy_id(old)
            result.append(dict(id=old, new_id=new))
            oldpath = ob.getFilesystemPath()
            newpath = os.path.join(path, new)
            
            if COPY:
                try:
                    if IReflectoDirectory.providedBy(ob):
                        shutil.copytree(oldpath, newpath)
                    else:
                        shutil.copy2(oldpath, newpath)
                    notify(ObjectCopiedEvent(self[new], ob))
                    notify(ObjectClonedEvent(self[new]))
                except EnvironmentError:
                    problem_ids.append(result.pop())
            else:
                # paste/move
                oldparent = aq_parent(aq_inner(ob))
                notify(ObjectWillBeMovedEvent(ob, oldparent, old, self, new))
                
                if aq_base(self) is aq_base(oldparent):
                    # No need to move from self to self
                    result[-1]['new_id'] = old
                    # Original CopyContainer does emit events for this case
                    notify(ObjectMovedEvent(ob, self, old, self, old))
                    continue
                
                try:
                    shutil.move(oldpath, newpath)
                    indexview = oldparent.unrestrictedTraverse('@@index')
                    indexview.index()
                    notify(ObjectMovedEvent(self[new], oldparent, old, self,
                                            new))
                    notifyContainerModified(oldparent)
                except EnvironmentError:
                    if os.path.exists(newpath):
                        # partial move
                        try:
                            if os.path.isdir(newpath):
                                shutil.rmtree(newpath)
                            else:
                                os.unlink(newpath)
                        except EnvironmentError:
                            pass # Really weird access issues, time to bail
                    problem_ids.append(result.pop())
                
        if problem_ids:
            sm = IStatusMessage(getattr(self, 'REQUEST', None), None)
            if sm is not None:
                sm.addStatusMessage(
                    'Failed to copy or paste some files: %s' % problem_ids,
                    'stop')
                
        if result:
            indexview = self.unrestrictedTraverse('@@index')
            indexview.index()
            notifyContainerModified(self)
        
        return result
Пример #47
0
    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