Search in sources :

Example 1 with ZSharedFolder

use of com.zimbra.client.ZSharedFolder in project zm-mailbox by Zimbra.

the class ImapHandler method doCOPY.

/**
 * @param path of target folder
 */
protected boolean doCOPY(String tag, String sequenceSet, ImapPath path, boolean byUID) throws IOException, ImapException {
    checkCommandThrottle(new CopyCommand(sequenceSet, path));
    if (!checkState(tag, State.SELECTED)) {
        return true;
    }
    String command = (byUID ? "UID COPY" : "COPY");
    String copyuid = "";
    ImapFolder i4folder = getSelectedFolder();
    if (i4folder == null) {
        throw new ImapSessionClosedException();
    }
    MailboxStore mbox = i4folder.getMailbox();
    Set<ImapMessage> i4set;
    mbox.lock(false);
    try {
        i4set = i4folder.getSubsequence(tag, sequenceSet, byUID);
    } catch (ImapParseException ipe) {
        ZimbraLog.imap.error(ipe);
        throw ipe;
    } finally {
        mbox.unlock();
    }
    if (i4set.size() > LC.imap_max_items_in_copy.intValue()) {
        sendNO(tag, "COPY rejected, too many items in copy request");
        return true;
    }
    // accessed mailbox that contains expunged messages."
    if (!byUID && i4set.contains(null)) {
        sendNO(tag, "COPY rejected because some of the requested messages were expunged");
        return true;
    }
    i4set.remove(null);
    try {
        if (!path.isVisible()) {
            throw ImapServiceException.FOLDER_NOT_VISIBLE(path.asImapPath());
        } else if (!path.isWritable(ACL.RIGHT_INSERT)) {
            throw ImapServiceException.FOLDER_NOT_WRITABLE(path.asImapPath());
        }
        MailboxStore mbxStore = path.getOwnerMailbox();
        if (null == mbxStore) {
            throw AccountServiceException.NO_SUCH_ACCOUNT(path.getOwner());
        }
        FolderStore targetFolder = path.getFolder();
        FolderStore selectedFolder = null;
        try {
            selectedFolder = i4folder.getFolder();
        } catch (ServiceException e1) {
            ZimbraLog.imap.error("Problem with selected folder %s during doCOPY", e1.getMessage());
            return true;
        }
        // check target folder permissions before attempting the copy
        ImapMailboxStore selectedImapMboxStore = i4folder.getImapMailboxStore();
        boolean sameMailbox = selectedImapMboxStore.getAccountId().equalsIgnoreCase(mbxStore.getAccountId());
        boolean selectedFolderInOtherMailbox;
        ItemIdentifier fromFolderId;
        if (selectedFolder instanceof MountpointStore) {
            selectedFolderInOtherMailbox = true;
            fromFolderId = ((MountpointStore) selectedFolder).getTargetItemIdentifier();
        } else if (selectedFolder instanceof ZSharedFolder) {
            selectedFolderInOtherMailbox = true;
            fromFolderId = selectedFolder.getFolderItemIdentifier();
        } else {
            selectedFolderInOtherMailbox = false;
            fromFolderId = selectedFolder.getFolderItemIdentifier();
        }
        int uvv = targetFolder.getUIDValidity();
        ItemId iidTarget = new ItemId(targetFolder, path.getOwnerAccount().getId());
        ItemIdentifier targetIdentifier = iidTarget.toItemIdentifier();
        long checkpoint = System.currentTimeMillis();
        List<Integer> copyUIDs = extensionEnabled("UIDPLUS") ? Lists.newArrayListWithCapacity(i4set.size()) : null;
        final List<ImapMessage> i4list = Lists.newArrayList(i4set);
        final List<List<ImapMessage>> batches = Lists.partition(i4list, SUGGESTED_COPY_BATCH_SIZE);
        for (List<ImapMessage> batch : batches) {
            if (sameMailbox && !selectedFolderInOtherMailbox) {
                copyOwnItems(selectedImapMboxStore, batch, iidTarget, copyUIDs);
            } else {
                copyItemsBetweenMailboxes(selectedImapMboxStore, batch, fromFolderId, targetIdentifier, copyUIDs);
            }
            // send a gratuitous untagged response to keep pissy clients from closing the socket from inactivity
            long now = System.currentTimeMillis();
            if (now - checkpoint > MAXIMUM_IDLE_PROCESSING_MILLIS) {
                sendIdleUntagged();
                checkpoint = now;
            }
        }
        if (uvv > 0 && copyUIDs != null && copyUIDs.size() > 0) {
            List<Integer> srcUIDs = Lists.newArrayListWithCapacity(i4set.size());
            for (ImapMessage i4msg : i4set) {
                srcUIDs.add(i4msg.imapUid);
            }
            copyuid = "[COPYUID " + uvv + ' ' + ImapFolder.encodeSubsequence(srcUIDs) + ' ' + ImapFolder.encodeSubsequence(copyUIDs) + "] ";
        }
    } catch (IOException e) {
        // 6.4.7: "If the COPY command is unsuccessful for any reason, server implementations
        // MUST restore the destination mailbox to its state before the COPY attempt."
        ZimbraLog.imap.warn("%s failed", command, e);
        sendNO(tag, command + " failed");
        return true;
    } catch (ServiceException e) {
        // 6.4.7: "If the COPY command is unsuccessful for any reason, server implementations
        // MUST restore the destination mailbox to its state before the COPY attempt."
        String rcode = "";
        if (e.getCode().equals(MailServiceException.NO_SUCH_FOLDER)) {
            ZimbraLog.imap.info("%s failed: no such folder: %s", command, path);
            if (path.isCreatable()) {
                rcode = "[TRYCREATE] ";
            }
        } else if (e.getCode().equals(ImapServiceException.FOLDER_NOT_VISIBLE)) {
            ZimbraLog.imap.info("%s failed: folder not visible: %s", command, path);
        } else if (e.getCode().equals(ImapServiceException.FOLDER_NOT_WRITABLE)) {
            ZimbraLog.imap.info("%s failed: folder not writable: %s", command, path);
        } else {
            ZimbraLog.imap.warn("%s failed", command, e);
        }
        sendNO(tag, rcode + command + " failed");
        return canContinue(e);
    }
    // RFC 2180 4.4: "COPY is the only IMAP4 sequence number command that is safe to allow
    // an EXPUNGE response on.  This is because a client is not permitted
    // to cascade several COPY commands together."
    sendNotifications(true, false);
    sendOK(tag, copyuid + command + " completed");
    return true;
}
Also used : MailboxStore(com.zimbra.common.mailbox.MailboxStore) SearchFolderStore(com.zimbra.common.mailbox.SearchFolderStore) FolderStore(com.zimbra.common.mailbox.FolderStore) ZSharedFolder(com.zimbra.client.ZSharedFolder) IOException(java.io.IOException) ItemId(com.zimbra.cs.service.util.ItemId) ItemIdentifier(com.zimbra.common.mailbox.ItemIdentifier) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) MountpointStore(com.zimbra.common.mailbox.MountpointStore) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList)

Example 2 with ZSharedFolder

use of com.zimbra.client.ZSharedFolder in project zm-mailbox by Zimbra.

the class ImapSessionManager method openFolder.

protected FolderDetails openFolder(ImapPath path, byte params, ImapHandler handler) throws ServiceException {
    ZimbraLog.imap.debug("opening folder: %s", path);
    if (!path.isSelectable()) {
        throw ServiceException.PERM_DENIED("cannot select folder: " + path);
    }
    if ((params & ImapFolder.SELECT_CONDSTORE) != 0) {
        handler.activateExtension(ImapExtension.CONDSTORE);
    }
    FolderStore folder = path.getFolder();
    String folderIdAsString = folder.getFolderIdAsString();
    int folderId = folder.getFolderIdInOwnerMailbox();
    MailboxStore mbox = folder.getMailboxStore();
    ImapMailboxStore imapStore = ImapMailboxStore.get(mbox);
    // don't have a session when the folder is loaded...
    OperationContext octxt = handler.getCredentials().getContext();
    List<ImapMessage> i4list = null;
    // *always* recalculate the contents of search folders
    if (folder instanceof SearchFolderStore) {
        i4list = loadVirtualFolder(octxt, (SearchFolderStore) folder);
    } else {
        waitForWaitSetNotifications(imapStore, folder);
    }
    mbox.lock(true);
    try {
        // need mInitialRecent to be set *before* loading the folder so we can determine what's \Recent
        if (!(folder instanceof ZSharedFolder)) {
            folder = mbox.getFolderById(octxt, folderIdAsString);
            if (folder == null) {
                throw MailServiceException.NO_SUCH_FOLDER(path.asImapPath());
            }
        }
        int recentCutoff = imapStore.getImapRECENTCutoff(folder);
        if (i4list == null) {
            List<ImapListener> listners = imapStore.getListeners(folder);
            // first option is to duplicate an existing registered session
            // (could try to just activate an inactive session, but this logic is simpler for now)
            i4list = duplicateExistingSession(folderId, listners);
            // no matching session means we next check for serialized folder data
            if (i4list == null) {
                i4list = duplicateSerializedFolder(folder);
            } else if (CONSISTENCY_CHECK) {
                Collections.sort(i4list);
            // sort only if using list from duplicated session which may be out of order
            // if loaded from serialized folder order _should_ already be OK since no changes have occurred
            }
            // do the consistency check, if requested
            if (CONSISTENCY_CHECK) {
                i4list = consistencyCheck(i4list, imapStore, octxt, folder);
            }
            // no matching serialized session means we have to go to the DB to get the messages
            if (i4list == null) {
                ItemIdentifier ident;
                if (folder instanceof MountpointStore) {
                    ident = ((MountpointStore) folder).getTargetItemIdentifier();
                } else {
                    ident = folder.getFolderItemIdentifier();
                }
                i4list = imapStore.openImapFolder(octxt, ident);
            }
        }
        Collections.sort(i4list);
        // check messages for imapUid <= 0 and assign new IMAP IDs if necessary
        renumberMessages(octxt, mbox, i4list);
        ImapFolder i4folder = new ImapFolder(path, params, handler);
        // don't rely on the <code>Folder</code> object being updated in place
        if (!(folder instanceof ZSharedFolder)) {
            folder = mbox.getFolderById(octxt, folderIdAsString);
        }
        // can't set these until *after* loading the folder because UID renumbering affects them
        InitialFolderValues initial = new InitialFolderValues(folder);
        for (ImapMessage i4msg : i4list) {
            i4folder.cache(i4msg, i4msg.imapUid > recentCutoff);
            if (initial.firstUnread == -1 && (i4msg.flags & Flag.BITMASK_UNREAD) != 0) {
                initial.firstUnread = i4msg.sequence;
            }
        }
        i4folder.setInitialSize();
        ZimbraLog.imap.debug("ImapSessionManager.openFolder.  Folder with id=%s added message list %s", folderIdAsString, i4list);
        ImapListener session = null;
        try {
            session = imapStore.createListener(i4folder, handler);
            session.register();
            sessions.put(session, session);
            imapStore.registerWithImapServerListener(session);
            return new FolderDetails(session, initial);
        } catch (ServiceException e) {
            if (session != null) {
                session.unregister();
            }
            throw e;
        }
    } finally {
        mbox.unlock();
    }
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) MailboxStore(com.zimbra.common.mailbox.MailboxStore) FolderStore(com.zimbra.common.mailbox.FolderStore) SearchFolderStore(com.zimbra.common.mailbox.SearchFolderStore) ZSharedFolder(com.zimbra.client.ZSharedFolder) ItemIdentifier(com.zimbra.common.mailbox.ItemIdentifier) SearchFolderStore(com.zimbra.common.mailbox.SearchFolderStore) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) MountpointStore(com.zimbra.common.mailbox.MountpointStore)

Aggregations

ZSharedFolder (com.zimbra.client.ZSharedFolder)2 FolderStore (com.zimbra.common.mailbox.FolderStore)2 ItemIdentifier (com.zimbra.common.mailbox.ItemIdentifier)2 MailboxStore (com.zimbra.common.mailbox.MailboxStore)2 MountpointStore (com.zimbra.common.mailbox.MountpointStore)2 SearchFolderStore (com.zimbra.common.mailbox.SearchFolderStore)2 ServiceException (com.zimbra.common.service.ServiceException)2 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)2 AccountServiceException (com.zimbra.cs.account.AccountServiceException)1 OperationContext (com.zimbra.cs.mailbox.OperationContext)1 ItemId (com.zimbra.cs.service.util.ItemId)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1