Search in sources :

Example 1 with MountpointStore

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

the class ImapPath method useReferent.

protected boolean useReferent() throws ServiceException {
    if (getReferent() == this) {
        return false;
    } else if (mScope == Scope.CONTENT) {
        return true;
    }
    // if we're here, we should be at NAME scope -- return whether the original path pointed at a mountpoint
    assert (mScope == Scope.NAME);
    assert (folder != null);
    assert (mReferent != null);
    if (folder instanceof MountpointStore) {
        ItemId iidBase;
        iidBase = new ItemId(((MountpointStore) folder).getTargetItemIdentifier());
        return !iidBase.equals(mReferent.mItemId);
    } else {
        return false;
    }
}
Also used : MountpointStore(com.zimbra.common.mailbox.MountpointStore) ItemId(com.zimbra.cs.service.util.ItemId)

Example 2 with MountpointStore

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

the class ImapHandler method accumulatePaths.

private void accumulatePaths(ImapMailboxStore imapStore, String owner, ImapPath relativeTo, Map<ImapPath, ItemId> paths, Map<ImapPath, ItemId> mountPaths, boolean isMountPath) throws ServiceException {
    Collection<FolderStore> visibleFolders = imapStore.getVisibleFolders(getContext(), credentials, owner, relativeTo);
    // TODO - This probably needs to be the setting for the server for IMAP session's main mailbox
    boolean isMailFolders = Provisioning.getInstance().getLocalServer().isImapDisplayMailFoldersOnly();
    for (FolderStore folderStore : visibleFolders) {
        // chat has item type of message.  hence ignoring the chat folder by name.
        if (isMailFolders && (folderStore.isChatsFolder() || (folderStore.getName().equals("Chats")))) {
            continue;
        }
        /* In remote case, list includes children of mountpoints - filter them out here and instead
             * tackle them via accumulatePaths in the owner mailbox. */
        if (!(folderStore instanceof MountpointStore) && isInMountpointHierarchy(folderStore)) {
            continue;
        }
        ImapPath path = relativeTo == null ? new ImapPath(owner, folderStore, credentials) : new ImapPath(owner, folderStore, relativeTo);
        if (path.isVisible()) {
            if (userAgent != null && userAgent.startsWith(IDInfo.DATASOURCE_IMAP_CLIENT_NAME) && folderStore.isSyncFolder()) {
                // IMAP datasource connections
                continue;
            }
            // boolean alreadyTraversed = paths.put(path, path.asItemId()) != null;
            boolean alreadyTraversed = (!isMountPath) ? paths.put(path, path.asItemId()) != null : mountPaths.put(path, path.asItemId()) != null;
            if (folderStore instanceof MountpointStore && !alreadyTraversed) {
                // mountPaths.put(path, path.asItemId());
                accumulatePaths(path.getOwnerImapMailboxStore(), owner, path, paths, mountPaths, true);
            }
        }
    }
}
Also used : SearchFolderStore(com.zimbra.common.mailbox.SearchFolderStore) FolderStore(com.zimbra.common.mailbox.FolderStore) MountpointStore(com.zimbra.common.mailbox.MountpointStore)

Example 3 with MountpointStore

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

use of com.zimbra.common.mailbox.MountpointStore 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)

Example 5 with MountpointStore

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

the class ImapPath method getReferent.

/**
 * @return If the folder is a mountpoint (i.e. an accepted share), may return an ImapPath representing
 *         that, otherwise, the value is this.
 */
@VisibleForTesting
public ImapPath getReferent() throws ServiceException {
    if (mReferent != null) {
        return mReferent;
    }
    // while calculating, use the base
    mReferent = this;
    // only follow the authenticated user's own mountpoints
    if (mScope == Scope.REFERENCE || mScope == Scope.UNPARSED || !belongsTo(mCredentials)) {
        return mReferent;
    }
    ImapMailboxStore ownerImapMailboxStore = getOwnerImapMailboxStore();
    if (null == ownerImapMailboxStore) {
        return mReferent;
    }
    ItemId iidRemote;
    String subpathRemote = null;
    if (folder == null) {
        try {
            ExistingParentFolderStoreAndUnmatchedPart info = ownerImapMailboxStore.getMailboxStore().getParentFolderStoreAndUnmatchedPart(getContext(), asZimbraPath());
            subpathRemote = info.unmatchedPart;
            if (info.parentFolderStore instanceof MountpointStore || Strings.isNullOrEmpty(subpathRemote)) {
                folder = info.parentFolderStore;
                mItemId = new ItemId(ItemIdentifier.fromOwnerAndFolder(accountIdFromCredentials(), folder));
            }
            if (!(info.parentFolderStore instanceof MountpointStore)) {
                return mReferent;
            }
        } catch (ServiceException e) {
            return mReferent;
        }
    }
    if (!(folder instanceof MountpointStore)) {
        return mReferent;
    }
    // somewhere along the specified path is a visible mountpoint owned by the user
    iidRemote = new ItemId(((MountpointStore) folder).getTargetItemIdentifier());
    // don't allow mountpoints that point at the same mailbox (as it can cause infinite loops)
    if (belongsTo(iidRemote.getAccountId())) {
        return mReferent;
    }
    Account target = Provisioning.getInstance().get(AccountBy.id, iidRemote.getAccountId());
    if (target == null) {
        return mReferent;
    }
    ImapMailboxStore imapMailboxStore = setupMailboxStoreForTarget(target, iidRemote);
    if (null == imapMailboxStore) {
        return mReferent;
    }
    FolderStore fldr = imapMailboxStore.getMailboxStore().getFolderById(getContext(), Integer.toString(iidRemote.getId()));
    if (fldr == null) {
        return mReferent;
    }
    String owner = getOwner(target);
    if (Strings.isNullOrEmpty(subpathRemote)) {
        mReferent = new ImapPath(owner, fldr, mCredentials);
    } else {
        mReferent = ImapPath.get(owner, fldr.getPath() + (fldr.getPath().equals("/") ? "" : "/") + subpathRemote, mCredentials, imapMailboxStore);
    }
    if (mReferent != this) {
        mReferent.mScope = Scope.REFERENCE;
    }
    return mReferent;
}
Also used : Account(com.zimbra.cs.account.Account) ExistingParentFolderStoreAndUnmatchedPart(com.zimbra.common.mailbox.ExistingParentFolderStoreAndUnmatchedPart) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) MountpointStore(com.zimbra.common.mailbox.MountpointStore) FolderStore(com.zimbra.common.mailbox.FolderStore) ItemId(com.zimbra.cs.service.util.ItemId) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Aggregations

MountpointStore (com.zimbra.common.mailbox.MountpointStore)5 FolderStore (com.zimbra.common.mailbox.FolderStore)4 SearchFolderStore (com.zimbra.common.mailbox.SearchFolderStore)3 ServiceException (com.zimbra.common.service.ServiceException)3 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)3 ItemId (com.zimbra.cs.service.util.ItemId)3 ZSharedFolder (com.zimbra.client.ZSharedFolder)2 ItemIdentifier (com.zimbra.common.mailbox.ItemIdentifier)2 MailboxStore (com.zimbra.common.mailbox.MailboxStore)2 AccountServiceException (com.zimbra.cs.account.AccountServiceException)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 ExistingParentFolderStoreAndUnmatchedPart (com.zimbra.common.mailbox.ExistingParentFolderStoreAndUnmatchedPart)1 Account (com.zimbra.cs.account.Account)1 OperationContext (com.zimbra.cs.mailbox.OperationContext)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1