Search in sources :

Example 26 with MailboxStore

use of com.zimbra.common.mailbox.MailboxStore in project zm-mailbox by Zimbra.

the class ImapHandler method doRENAME.

private boolean doRENAME(String tag, ImapPath oldPath, ImapPath newPath) throws IOException {
    if (!checkState(tag, State.AUTHENTICATED)) {
        return true;
    }
    try {
        Account source = oldPath.getOwnerAccount();
        Account target = newPath.getOwnerAccount();
        if (source == null || target == null) {
            ZimbraLog.imap.info("RENAME failed: no such account for %s or %s", oldPath, newPath);
            sendNO(tag, "RENAME failed: no such account");
            return true;
        } else if (!source.getId().equalsIgnoreCase(target.getId())) {
            ZimbraLog.imap.info("RENAME failed: cannot move folder between mailboxes");
            sendNO(tag, "RENAME failed: cannot rename mailbox to other user's namespace");
            return true;
        } else if (!newPath.isCreatable()) {
            ZimbraLog.imap.info("RENAME failed: hidden folder or parent: %s", newPath);
            sendNO(tag, "RENAME failed");
            return true;
        } else if (!oldPath.isVisible()) {
            throw MailServiceException.NO_SUCH_FOLDER(oldPath.asZimbraPath());
        }
        MailboxStore mboxStore = oldPath.getOwnerMailbox();
        if (null != mboxStore) {
            FolderStore pathFolder = oldPath.getFolder();
            if (pathFolder.isInboxFolder()) {
                throw ImapServiceException.CANT_RENAME_INBOX();
            }
            mboxStore.renameFolder(getContext(), pathFolder, "/" + newPath.asResolvedPath());
        } else {
            ZimbraLog.imap.info("RENAME failed: cannot get mailbox for path: " + oldPath);
            sendNO(tag, "RENAME failed");
            return true;
        }
    } catch (ServiceException e) {
        if (e.getCode().equals(ImapServiceException.CANT_RENAME_INBOX)) {
            ZimbraLog.imap.info("RENAME failed: RENAME of INBOX not supported");
            sendNO(tag, "RENAME failed: RENAME of INBOX not supported");
            return true;
        } else if (e.getCode().equals(MailServiceException.NO_SUCH_FOLDER)) {
            ZimbraLog.imap.info("RENAME failed: no such folder: %s", oldPath);
        } else if (e.getCode().equals(MailServiceException.IMMUTABLE_OBJECT)) {
            ZimbraLog.imap.info("RENAME failed: cannot rename system folder: %s", oldPath);
        } else if (e.getCode().equals(MailServiceException.CANNOT_CONTAIN)) {
            ZimbraLog.imap.info("RENAME failed: invalid target folder: %s", newPath);
        } else {
            ZimbraLog.imap.warn("RENAME failed", e);
        }
        sendNO(tag, "RENAME failed");
        return canContinue(e);
    }
    // note: if ImapFolder contains a pathname, we may need to update mSelectedFolder
    sendNotifications(true, false);
    sendOK(tag, "RENAME completed");
    return true;
}
Also used : Account(com.zimbra.cs.account.Account) GuestAccount(com.zimbra.cs.account.GuestAccount) MailboxStore(com.zimbra.common.mailbox.MailboxStore) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) SearchFolderStore(com.zimbra.common.mailbox.SearchFolderStore) FolderStore(com.zimbra.common.mailbox.FolderStore)

Example 27 with MailboxStore

use of com.zimbra.common.mailbox.MailboxStore 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 28 with MailboxStore

use of com.zimbra.common.mailbox.MailboxStore in project zm-mailbox by Zimbra.

the class ImapHandler method copyItemsBetweenMailboxes.

private void copyItemsBetweenMailboxes(ImapMailboxStore selectedImapMboxStore, List<ImapMessage> batch, ItemIdentifier fromFolderId, ItemIdentifier targetIdentifier, List<Integer> copyUIDs) throws ServiceException {
    List<ItemIdentifier> identList = Lists.newArrayListWithCapacity(batch.size());
    List<Integer> createdList = Lists.newArrayListWithCapacity(batch.size());
    for (ImapMessage i4msg : batch) {
        identList.add(ItemIdentifier.fromAccountIdAndItemId(fromFolderId.accountId, i4msg.msgId));
    }
    MailboxStore selectedStore = selectedImapMboxStore.getMailboxStore();
    List<String> copyIds = selectedStore.copyItemAction(getContext(), targetIdentifier, identList);
    for (String copyId : copyIds) {
        if (copyId.isEmpty()) {
            continue;
        }
        // For newly created items, the UID is the same as the id in the target mailbox
        ItemIdentifier itemIdentifier = new ItemIdentifier(copyId, (String) null);
        createdList.add(itemIdentifier.id);
    }
    if (createdList.size() != identList.size()) {
        throw ServiceException.FAILURE(String.format("mismatch between original (%s) and target (%s) count during IMAP COPY", identList.size(), createdList.size()), null);
    }
    if (copyUIDs != null) {
        copyUIDs.addAll(createdList);
    }
}
Also used : ItemIdentifier(com.zimbra.common.mailbox.ItemIdentifier) MailboxStore(com.zimbra.common.mailbox.MailboxStore)

Example 29 with MailboxStore

use of com.zimbra.common.mailbox.MailboxStore in project zm-mailbox by Zimbra.

the class ImapSessionManager method closeFolder.

protected void closeFolder(ImapListener session, boolean isUnregistering) {
    // detach session from handler and jettison session state from folder
    if (session.isInteractive()) {
        session.inactivate();
    }
    // no fancy stuff for search folders since they're always recalculated on load
    if (session.isVirtual()) {
        session.detach();
        return;
    }
    // checkpoint the folder data if desired
    if (SERIALIZE_ON_CLOSE) {
        try {
            // could use session.serialize() if we want to leave it in memory...
            ZimbraLog.imap.debug("Paging session during close: %s", session);
            session.unload(false);
        } catch (MailboxInMaintenanceException miMe) {
            if (ZimbraLog.imap.isDebugEnabled()) {
                ZimbraLog.imap.info("Mailbox in maintenance detected during close - will detach %s", session, miMe);
            } else {
                ZimbraLog.imap.info("Mailbox in maintenance detected during close - will detach %s", session);
            }
            session.detach();
            return;
        } catch (Exception e) {
            ZimbraLog.imap.warn("Skipping error while trying to serialize during close %s", session, e);
        }
    }
    if (isUnregistering) {
        return;
    }
    // recognize if we're not configured to allow sessions to hang around after end of SELECT
    if (TERMINATE_ON_CLOSE) {
        session.detach();
        return;
    }
    // if there are still other listeners on this folder, this session is unnecessary
    MailboxStore mbox = session.getMailbox();
    if (mbox != null) {
        mbox.lock(true);
        try {
            for (ImapListener i4listener : session.getImapMboxStore().getListeners(session.getFolderItemIdentifier())) {
                if (differentSessions(i4listener, session)) {
                    ZimbraLog.imap.trace("more recent listener exists for folder.  Detaching %s", session);
                    session.detach();
                    recordAccess(i4listener);
                    return;
                }
            }
        } finally {
            mbox.unlock();
        }
    }
}
Also used : MailboxStore(com.zimbra.common.mailbox.MailboxStore) MailboxInMaintenanceException(com.zimbra.cs.mailbox.MailServiceException.MailboxInMaintenanceException) ServiceException(com.zimbra.common.service.ServiceException) MailboxInMaintenanceException(com.zimbra.cs.mailbox.MailServiceException.MailboxInMaintenanceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException)

Example 30 with MailboxStore

use of com.zimbra.common.mailbox.MailboxStore in project zm-mailbox by Zimbra.

the class ImapSessionManager method cacheKey.

private String cacheKey(FolderStore folder, boolean active) {
    MailboxStore mbox = folder.getMailboxStore();
    int modseq = folder instanceof SearchFolderStore ? mbox.getLastChangeID() : folder.getImapMODSEQ();
    int uvv = folder instanceof SearchFolderStore ? mbox.getLastChangeID() : ImapFolder.getUIDValidity(folder);
    String acctId = null;
    try {
        acctId = mbox.getAccountId();
    } catch (ServiceException e) {
        acctId = "<unknown>";
    }
    if (active) {
        // use '_' as separator
        return String.format("%s_%d_%d_%d", acctId, folder.getFolderIdInOwnerMailbox(), modseq, uvv);
    } else {
        // use ':' as a separator
        return String.format("%s:%d:%d:%d", acctId, folder.getFolderIdInOwnerMailbox(), modseq, uvv);
    }
}
Also used : SearchFolderStore(com.zimbra.common.mailbox.SearchFolderStore) MailboxStore(com.zimbra.common.mailbox.MailboxStore) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException)

Aggregations

MailboxStore (com.zimbra.common.mailbox.MailboxStore)34 ServiceException (com.zimbra.common.service.ServiceException)22 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)17 AccountServiceException (com.zimbra.cs.account.AccountServiceException)14 SearchFolderStore (com.zimbra.common.mailbox.SearchFolderStore)10 FolderStore (com.zimbra.common.mailbox.FolderStore)9 ArrayList (java.util.ArrayList)6 ItemIdentifier (com.zimbra.common.mailbox.ItemIdentifier)5 Account (com.zimbra.cs.account.Account)4 ZimbraMailItem (com.zimbra.common.mailbox.ZimbraMailItem)3 ImapMessageSet (com.zimbra.cs.imap.ImapMessage.ImapMessageSet)3 Mailbox (com.zimbra.cs.mailbox.Mailbox)3 IOException (java.io.IOException)3 ZMailbox (com.zimbra.client.ZMailbox)2 ZSharedFolder (com.zimbra.client.ZSharedFolder)2 MountpointStore (com.zimbra.common.mailbox.MountpointStore)2 ZimbraQueryHit (com.zimbra.common.mailbox.ZimbraQueryHit)2 ZimbraQueryHitResults (com.zimbra.common.mailbox.ZimbraQueryHitResults)2 ZimbraSearchParams (com.zimbra.common.mailbox.ZimbraSearchParams)2 GuestAccount (com.zimbra.cs.account.GuestAccount)2