Example #1
0
    def objects_to_async(self, request_key='__cp'):
        """ get info of files to perform async operation
        """

        newid = self.request.get(request_key)

        if not newid:
            raise CopyError(eNoItemsSpecified)

        try:
            _op, mdatas = _cb_decode(newid)
        except:
            raise CopyError(eInvalid)

        oblist = []
        app = self.context.getPhysicalRoot()

        for mdata in mdatas:
            m = loadMoniker(mdata)
            try:
                ob = m.bind(app)
            except ConflictError:
                raise
            except:
                raise CopyError(eNotFound)

            oblist.append(ob)

        return oblist
Example #2
0
    def objects_to_async(self, request_key='__cp'):
        """ get info of files to perform async operation
        """

        newid = self.request.get(request_key)

        if not newid:
            raise CopyError(eNoItemsSpecified)

        try:
            _op, mdatas = _cb_decode(newid)
        except:
            raise CopyError(eInvalid)

        oblist = []
        app = self.context.getPhysicalRoot()

        for mdata in mdatas:
            m = loadMoniker(mdata)
            try:
                ob = m.bind(app)
            except ConflictError:
                raise
            except:
                raise CopyError(eNotFound)

            oblist.append(ob)

        return oblist
Example #3
0
def async_move(context, success_event, fail_event, **kwargs):
    """ Async job
    """
    newid = kwargs.get('newid', '')
    email = kwargs.get('email', '')

    anno = IAnnotations(context)
    job_id = anno.get('async_move_job')

    if not newid:
        wrapper = IContextWrapper(context)(
            error=u'Invalid newid'
        )
        notify(fail_event(wrapper))
        raise CopyError(eNoItemsSpecified)

    try:
        _op, mdatas = _cb_decode(newid)
    except:
        raise CopyError(eInvalid)
    oblist = []
    app = context.getPhysicalRoot()

    for mdata in mdatas:
        m = loadMoniker(mdata)
        try:
            ob = m.bind(app)
        except ConflictError:
            raise
        except:
            raise CopyError(eNotFound)

        oblist.append(ob)

    wrapper = IContextWrapper(context)(
        folder_move_from=oblist and aq_parent(
            aq_inner(oblist[0])).absolute_url(),
        folder_move_to=context.absolute_url(),
        folder_move_objects=', '.join([obj.getId() for obj in oblist]),
        asyncmove_email=email
    )

    try:
        manage_pasteObjects_no_events(context, cb_copy_data=newid)
    except Exception, err:
        logger.exception(err)

        wrapper.error = err.message
        wrapper.job_id = job_id

        notify(fail_event(wrapper))
        raise CopyError(MessageDialog(
            title='Error',
            message=err.message,
            action='manage_main',
        ))
Example #4
0
    def cb_dataItems(self):
        # List of objects in the clip board
        try:    cp=_cb_decode(self.REQUEST['__cp'])
        except: return []
        oblist=[]

        app = self.getPhysicalRoot()
        for mdata in cp[1]:
            m = loadMoniker(mdata)
            oblist.append(m.bind(app))
        return oblist
Example #5
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
Example #6
0
def manage_pasteObjects_no_events(self, cb_copy_data=None, REQUEST=None):
    """Paste previously copied objects into the current object.
    If calling manage_pasteObjects from python code, pass the result of a
    previous call to manage_cutObjects or manage_copyObjects as the first
    argument.
    Also sends IObjectCopiedEvent and IObjectClonedEvent
    or IObjectWillBeMovedEvent and IObjectMovedEvent.
    """
    anno = IAnnotations(self)
    job_id = anno.get('async_move_job')

    if not REQUEST:
        # Create a request to work with
        REQUEST = create_request()

    if cb_copy_data is not None:
        cp = cb_copy_data
    elif REQUEST is not None and REQUEST.has_key('__cp'):
        cp = REQUEST['__cp']
    else:
        cp = None
    if cp is None:
        raise CopyError(eNoData)

    try:
        op, mdatas = _cb_decode(cp)
    except:
        raise CopyError(eInvalid)

    oblist = []
    app = self.getPhysicalRoot()
    cat = getToolByName(self, 'portal_catalog')

    for mdata in mdatas:
        m = loadMoniker(mdata)
        try:
            ob = m.bind(app)
        except ConflictError:
            raise
        except:
            raise CopyError(eNotFound)
        # self._verifyObjectPaste(ob, validate_src=op+1)
        oblist.append(ob)

    result = []

    steps = oblist and int(100/len(oblist)) or 0

    notify(AsyncMoveSaveProgress(
        self, operation='initialize', job_id=job_id, oblist_id=[
            (o.getId(), o.Title()) for o in oblist
            ]))

    if op == 0:
        # Copy operation
        for i, ob in enumerate(oblist):
            orig_id = ob.getId()
            if not ob.cb_isCopyable():
                raise CopyError(eNotSupported % escape(orig_id))

            oid = self._get_id(orig_id)
            result.append({'id': orig_id, 'new_id': oid})

            notify(AsyncMoveSaveProgress(
                self,
                operation='sub_progress',
                job_id=job_id,
                obj_id=ob.getId(), progress=.25
            ))

            ob = ob._getCopy(self)
            ob._setId(oid)

            notify(AsyncMoveSaveProgress(
                self,
                operation='sub_progress',
                job_id=job_id,
                obj_id=ob.getId(),
                progress=.50
            ))

            self._setObject(oid, ob)
            ob = self._getOb(oid)
            ob.wl_clearLocks()

            notify(AsyncMoveSaveProgress(
                self,
                operation='sub_progress',
                job_id=job_id,
                obj_id=ob.getId(),
                progress=.75
            ))

            ob._postCopy(self, op=0)

            compatibilityCall('manage_afterClone', ob, ob)

            notify(AsyncMoveSaveProgress(
                self,
                operation='sub_progress',
                job_id=job_id,
                obj_id=ob.getId(),
                progress=1
            ))

            notify(AsyncMoveSaveProgress(
                self,
                operation='progress',
                job_id=job_id,
                progress=steps*(i+1)/100
            ))

    if op == 1:
        # Move operation
        for i, ob in enumerate(oblist):
            orig_id = ob.getId()

            if not sanity_check(self, ob):
                raise CopyError(
                    "This object cannot be pasted into itself")

            orig_container = aq_parent(aq_inner(ob))
            if aq_base(orig_container) is aq_base(self):
                oid = orig_id
            else:
                oid = self._get_id(orig_id)
            result.append({'id': orig_id, 'new_id': oid})

            unindex_object(ob, recursive=1)
            # try to make ownership explicit so that it gets carried
            # along to the new location if needed.
            ob.manage_changeOwnershipType(explicit=1)

            notify(AsyncMoveSaveProgress(
                self,
                operation='sub_progress',
                job_id=job_id,
                obj_id=ob.getId(),
                progress=.25
            ))

            try:
                obj_path = '/'.join(
                    orig_container.getPhysicalPath()) + '/' + orig_id
                orig_container._delObject(orig_id, suppress_events=True)
                uncatalog_path = obj_path
                try:
                    uncatalog_objs = cat(path=obj_path)
                    for obj_brain in uncatalog_objs:
                        uncatalog_path = obj_brain.getPath()
                        cat.uncatalog_object(uncatalog_path)
                except AttributeError:
                    logger.warn("%s could not be found", uncatalog_path)
            except TypeError:
                orig_container._delObject(orig_id)
                logger.warn(
                    "%s._delObject without suppress_events is discouraged.",
                    orig_container.__class__.__name__)

            notify(AsyncMoveSaveProgress(
                self,
                operation='sub_progress',
                job_id=job_id,
                obj_id=ob.getId(),
                progress=.50
            ))

            ob = aq_base(ob)
            ob._setId(oid)

            try:
                self._setObject(oid, ob, set_owner=0, suppress_events=True)
            except TypeError:
                self._setObject(oid, ob, set_owner=0)
                logger.warn(
                    "%s._setObject without suppress_events is discouraged.",
                    self.__class__.__name__)
            ob = self._getOb(oid)

            ob._postCopy(self, op=1)
            # try to make ownership implicit if possible
            ob.manage_changeOwnershipType(explicit=0)

            notify(AsyncMoveSaveProgress(
                self,
                operation='sub_progress',
                job_id=job_id,
                obj_id=ob.getId(),
                progress=.75
            ))

            reindex_object(ob, recursive=1)

            notify(AsyncMoveSaveProgress(
                self,
                operation='sub_progress',
                job_id=job_id,
                obj_id=ob.getId(),
                progress=1
            ))

            notify(AsyncMoveSaveProgress(
                self,
                operation='progress',
                job_id=job_id,
                progress=steps*(i+1)/100
            ))

    notify(AsyncMoveSaveProgress(
        self, operation='progress', job_id=job_id,
        progress=1
    ))
    del anno['async_move_job']

    return result
Example #7
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
Example #8
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
Example #9
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 = 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:
                    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, update_menu=1,
                                        cb_dataValid=0)

        return result
Example #10
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
Example #11
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