示例#1
0
    def test_attribute_uuid_create_handler(self):

        from zope.interface import implementer
        from zope.event import notify
        from zope.lifecycleevent import ObjectCreatedEvent
        from zope.lifecycleevent import ObjectCopiedEvent

        from plone.uuid.interfaces import IAttributeUUID
        from plone.uuid.interfaces import IUUID
        from plone.uuid.interfaces import ATTRIBUTE_NAME

        @implementer(IAttributeUUID)
        class Context(object):
            pass

        context = Context()
        notify(ObjectCreatedEvent(context))

        uuid = IUUID(context, None)
        self.assertNotEqual(uuid, None)
        self.assertTrue(isinstance(uuid, str))

        # calling handler again won't change if UUID already present:
        notify(ObjectCreatedEvent(context))
        self.assertEqual(uuid, IUUID(context, None))

        # ...except when the UUID attribute was the result of a copy
        copied = Context()
        setattr(copied, ATTRIBUTE_NAME, IUUID(context, None))
        self.assertNotEqual(IUUID(copied, None), None)  # mimic copied state
        self.assertEqual(uuid, IUUID(copied, None))     # before handler
        notify(ObjectCopiedEvent(copied, original=context))
        self.assertNotEqual(uuid, None)
        self.assertNotEqual(uuid, IUUID(copied, None))  # copy has new UID
示例#2
0
        def _setter(ob, *args, **kw):
            if ob.isPrincipiaFolderish:
                tool = getattr(Acquisition.aq_parent(ob), 'portal_languages')
                if tool.id in ob.objectIds():
                    ob._delObject(tool.id)

                newob = tool._getCopy(tool)
                newob._setId(tool.id)
                notify(ObjectCopiedEvent(newob, tool))

                ob._setOb(tool.id, newob)
                ob._objects = ob._objects + (dict(meta_type=tool.meta_type,
                                                  id=tool.id), )
                newob = ob._getOb(tool.id)
                newob.wl_clearLocks()
                newob._postCopy(ob, op=0)
                newob.manage_afterClone(newob)

                notify(ObjectClonedEvent(newob))
                languages = kw.get('languages', None)
                if languages:
                    if isinstance(languages, tuple):
                        languages = list(languages)
                    elif isinstance(languages, types.StringType) or isinstance(
                            languages, types.UnicodeType):
                        languages = [languages]
                    newob.supported_langs = languages
                return ["Added language tool to %s" % ob.getId()]
示例#3
0
    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
示例#4
0
    def __call__(self):
        if self.request.method != "POST":
            raise NotFound(self, "library-insert", self.request)
        path = self.request.form.get("path")
        if not path:
            raise NotFound(self, "library-insert",
                           self.request)  # XXX Wrong exception type
        target = aq_inner(self.context)
        app = target.getPhysicalRoot()
        source = app.restrictedTraverse(path)
        if not is_allowed(target, source):
            raise NotFound(self, "library-insert",
                           self.request)  # XXX Wrong exception type
        copy = source._getCopy(target)
        assign_ids(target, copy)
        notify(ObjectCopiedEvent(copy, source))
        target._setObject(copy.id, copy)
        copy = target[copy.id]
        copy._postCopy(target, op=0)
        notify(ObjectClonedEvent(copy))

        api.portal.show_message(
            _(
                'Added a copy of "${title}" to your OiRA tool.',
                mapping={"title": copy.title},
            ),
            request=self.request,
            type="success",
        )
        self.request.RESPONSE.redirect(copy.absolute_url())
示例#5
0
class CopyActionExecutor(object):
    """The executor for this action.
    """
    implements(IExecutable)
    adapts(Interface, ICopyAction, Interface)

    def __init__(self, context, element, event):
        self.context = context
        self.element = element
        self.event = event

    def __call__(self):
        portal_url = getToolByName(self.context, 'portal_url', None)
        if portal_url is None:
            return False

        obj = self.event.object

        path = self.element.target_folder
        if len(path) > 1 and path[0] == '/':
            path = path[1:]
        target = portal_url.getPortalObject().unrestrictedTraverse(
            str(path), None)

        if target is None:
            self.error(
                obj,
                _(u"Target folder ${target} does not exist.",
                  mapping={'target': path}))
            return False

        try:
            obj._notifyOfCopyTo(target, op=0)
        except ConflictError:
            raise
        except Exception, e:
            self.error(obj, str(e))
            return False

        old_id = obj.getId()
        new_id = self.generate_id(target, old_id)

        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)

        OFS.subscribers.compatibilityCall('manage_afterClone', obj, obj)

        notify(ObjectClonedEvent(obj))

        return True
示例#6
0
    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
示例#7
0
    def __call__(self):
        portal_url = getToolByName(self.context, 'portal_url', None)
        if portal_url is None:
            return False

        obj = self.event.object

        path = self.element.target_folder
        if len(path) > 1 and path[0] == '/':
            path = path[1:]
        target = portal_url.getPortalObject().unrestrictedTraverse(
            str(path),
            None,
        )

        if target is None:
            self.error(
                obj,
                _(u'Target folder ${target} does not exist.',
                  mapping={'target': path}))
            return False

        try:
            obj._notifyOfCopyTo(target, op=0)
        except ConflictError:
            raise
        except Exception as e:
            self.error(obj, str(e))
            return False

        old_id = obj.getId()
        new_id = self.generate_id(target, old_id)

        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)

        OFS.subscribers.compatibilityCall('manage_afterClone', obj, obj)

        notify(ObjectClonedEvent(obj))

        return True
示例#8
0
def onObjectDeletion(object=None):

    import transaction
    from zope.event import notify
    from zope.app.container.contained import ObjectMovedEvent
    from zope.app.container.contained import notifyContainerModified
    from OFS.event import ObjectClonedEvent
    import OFS.subscribers
    from zope.lifecycleevent import ObjectCopiedEvent

    if object <> None:
        portal = object.portal_url.getPortalObject()

        org_user = getSecurityManager().getUser()

        try:
            objRBin = getPreferredRecycleBin(object)

            if objRBin <> None:
                #impersonateUser
                username = getUserToImpersonate(portal, objRBin)
                impersonateUser(portal, username)
                #
                parent = aq_parent(aq_inner(object))

                orig_id = object.getId()
                id = _get_id(objRBin, orig_id)

                orig_ob = object
                object = object._getCopy(parent)

                object._setId(id)

                addPropertiesOnDelete(portal, object, orig_ob, org_user,
                                      "/".join(parent.getPhysicalPath()))

                notify(ObjectCopiedEvent(object, orig_ob))
                objRBin._setObject(id, object)

                ob = objRBin._getOb(id)
                ob._postCopy(objRBin, op=0)
                OFS.subscribers.compatibilityCall('manage_afterClone', ob, ob)
                notify(ObjectClonedEvent(ob))

        except AttributeError:
            pass

        #undo imporsination
        newSecurityManager(None, org_user)
def backup_form(form, site):
    formId = form.getId()
    copyId = 'original-premigration-%s' % formId
    series = form.__parent__
    ## make clone:
    unwrapped = aq_base(form)
    copied = unwrapped._getCopy(series)
    copied._setId(copyId)
    copied.title = '%s (archival copy, pre-migration)' % copied.title
    notify(ObjectCopiedEvent(copied, form))
    series._setObject(copyId, copied)
    copied = series._getOb(copyId)
    notify(ObjectClonedEvent(copied))
    ## make clone private:
    site.portal_workflow.doActionFor(copied, 'hide')
示例#10
0
    def test_copy_subfolder(self):
        copied_subfolder = api.content.copy(
            self.first_classification_subfolder,
            self.second_classification_folder)

        notify(
            ObjectCopiedEvent(
                self.first_classification_subfolder,
                copied_subfolder,
            ))

        copied_subfolder_indexes = self.get_index_data(copied_subfolder)
        self.assertEqual(copied_subfolder_indexes["ClassificationFolderSort"],
                         "Folder2|Subfolder1")
        self.assertIn("folder2", copied_subfolder_indexes["SearchableText"])
def _add_language_tool(country_folder, country_name, languages):
    log.info('_add_language_tool for %s' % country_name)
    tool = getToolByName(country_folder, 'portal_languages')
    newob = tool._getCopy(tool)
    newob._setId(tool.id)
    notify(ObjectCopiedEvent(newob, tool))

    country_folder._setOb(tool.id, newob)
    country_folder._objects = country_folder._objects + (dict(
        meta_type=tool.meta_type, id=tool.id), )

    ltool = country_folder._getOb(tool.id)
    ltool.wl_clearLocks()
    ltool._postCopy(country_folder, op=0)
    ltool.manage_afterClone(ltool)
    notify(ObjectClonedEvent(ltool))
    ltool.supported_langs = languages
示例#12
0
    def translateThis(self, attrs=[]):
        """ Translates the current object into all languages and transferres the given attributes """
        context = Acquisition.aq_inner(self.context)
        if 'title' not in attrs:
            attrs.append('title')
        # Only do this from the canonical
        context = context.getCanonical()
        res = []
        for lang in self.langs:
            if context.hasTranslation(lang):
                res.append("Translation for %s exists" % lang)
                continue
            context.addTranslation(lang)
            trans = context.getTranslation(lang)
            res.append("Added Translation for %s" % lang)
            for attr in attrs:
                val = context.getField(attr).getAccessor(context)()
                trans.getField(attr).getMutator(trans)(val)
                res.append("  > Transferred Attribute %s" % attr)
            if context.portal_type == 'Topic':
                # copy the contents as well
                ids = context.objectIds()
                ids.remove('syndication_information')

                for id in ids:
                    orig_ob = getattr(context, id)
                    ob = orig_ob._getCopy(context)
                    ob._setId(id)
                    notify(ObjectCopiedEvent(ob, orig_ob))

                    trans._setObject(id, ob)
                    ob = trans._getOb(id)
                    ob.wl_clearLocks()
                    ob._postCopy(trans, op=0)
                    ob.manage_afterClone(ob)

                    notify(ObjectClonedEvent(ob))

                res.append("  > Transferred Topic contents")

        return res
示例#13
0
    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
示例#14
0
 def update(self):
     req = self.request
     if req.get('REQUEST_METHOD', 'GET') == 'POST' and 'makeclone' in req:
         source = self.context
         parent = source.__parent__
         target = source._getCopy(parent)
         target.title = req.get('clone_title', source.title).decode('utf-8')
         target.description = req.get(
             'clone_description',
             source.description,
             ).decode('utf-8')
         target_id = self.target_id(target, parent)
         target._setId(target_id)
         notify(ObjectCopiedEvent(target, source))
         parent._setObject(target_id, target)
         target = parent.get(target_id)
         target.wl_clearLocks()
         notify(ObjectClonedEvent(target))
         self.status.add(
             u'Created a new data set with title "%s" cloned from '
             u'original data set "%s"' % (target.title, source.title),
             type=u'info',
             )
         req.response.redirect(target.absolute_url() + '/edit')
示例#15
0
    def copyTo(self, target, new_name=None):
        """Copy this object to the `target` given.

        Returns the new name within the `target`. After the copy
        is created and before adding it to the target container,
        an `IObjectCopied` event is published.
        """
        obj = self.context
        container = obj.__parent__

        orig_name = obj.__name__
        if new_name is None:
            new_name = orig_name

        checkObject(target, new_name, obj)

        chooser = INameChooser(target)
        new_name = chooser.chooseName(new_name, obj)

        new = copy(obj)
        notify(ObjectCopiedEvent(new, obj))

        target[new_name] = new
        return new_name
示例#16
0
    def render(self):
        if self.request.method != 'POST':
            raise NotFound(self, 'library-insert', self.request)
        path = self.request.form.get('path')
        if not path:
            raise NotFound(self, 'library-insert', self.request)  # XXX Wrong exception type
        target = aq_inner(self.context)
        app = target.getPhysicalRoot()
        source = app.restrictedTraverse(path)
        if not is_allowed(target, source):
            raise NotFound(self, 'library-insert', self.request)  # XXX Wrong exception type
        copy = source._getCopy(target)
        assign_ids(target, copy)
        notify(ObjectCopiedEvent(copy, source))
        target._setObject(copy.id, copy)
        copy = target[copy.id]
        copy._postCopy(target, op=0)
        notify(ObjectClonedEvent(copy))

        IStatusMessage(self.request).addStatusMessage(
                _(u'Added a copy of "${title}" to your OiRA tool.',
                    mapping={'title': copy.title}),
                type='success')
        self.response.redirect(copy.absolute_url())
示例#17
0
    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
示例#18
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
示例#19
0
    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
示例#20
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.
        """
        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
示例#21
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
示例#22
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