use of com.zimbra.client.ZFolder in project zm-mailbox by Zimbra.
the class ImapHandler method doGETACL.
boolean doGETACL(String tag, ImapPath path) throws IOException {
if (!checkState(tag, State.AUTHENTICATED)) {
return true;
}
StringBuilder i4acl = new StringBuilder("ACL ").append(path.asUtf7String());
try {
// make sure the requester has sufficient permissions to make the request
if ((path.getFolderRights() & ACL.RIGHT_ADMIN) == 0) {
ZimbraLog.imap.info("GETACL failed: user does not have admin access: %s", path);
sendNO(tag, "GETACL failed");
return true;
}
// the target folder's owner always has full rights
Account owner = path.getOwnerAccount();
if (owner != null) {
i4acl.append(" \"").append(owner.getName()).append("\" ").append(IMAP_CONCATENATED_RIGHTS);
}
// write out the grants to all users and groups
Short anyoneRights = null;
Object folderobj = path.getFolder();
if (folderobj instanceof Folder) {
ACL acl = ((Folder) folderobj).getEffectiveACL();
if (acl != null) {
for (ACL.Grant grant : acl.getGrants()) {
byte type = grant.getGranteeType();
short rights = grant.getGrantedRights();
if (type == ACL.GRANTEE_AUTHUSER || type == ACL.GRANTEE_PUBLIC) {
anyoneRights = (short) ((anyoneRights == null ? 0 : anyoneRights) | rights);
} else if (type == ACL.GRANTEE_USER || type == ACL.GRANTEE_GROUP) {
NamedEntry entry = FolderAction.lookupGranteeByZimbraId(grant.getGranteeId(), type);
if (entry != null) {
i4acl.append(" \"").append(entry.getName()).append("\" ").append(exportRights(rights));
}
}
}
}
} else {
for (ZGrant zgrant : ((ZFolder) folderobj).getGrants()) {
ZGrant.GranteeType ztype = zgrant.getGranteeType();
short rights = ACL.stringToRights(zgrant.getPermissions());
if (ztype == ZGrant.GranteeType.pub || ztype == ZGrant.GranteeType.all) {
anyoneRights = (short) ((anyoneRights == null ? 0 : anyoneRights) | rights);
} else if (ztype == ZGrant.GranteeType.usr || ztype == ZGrant.GranteeType.grp) {
byte granteeType = ztype == ZGrant.GranteeType.usr ? ACL.GRANTEE_USER : ACL.GRANTEE_GROUP;
NamedEntry entry = FolderAction.lookupGranteeByZimbraId(zgrant.getGranteeId(), granteeType);
if (entry != null) {
i4acl.append(" \"").append(entry.getName()).append("\" ").append(exportRights(rights));
}
}
}
}
// aggregate all the "public" and "auth user" grants into the "anyone" IMAP ACL
if (anyoneRights != null) {
i4acl.append(" anyone ").append(exportRights(anyoneRights));
}
} catch (ServiceException e) {
if (e.getCode().equals(ServiceException.PERM_DENIED)) {
ZimbraLog.imap.info("GETACL failed: permission denied on folder: %s", path);
} else if (e.getCode().equals(MailServiceException.NO_SUCH_FOLDER)) {
ZimbraLog.imap.info("GETACL failed: no such folder: %s", path);
} else {
ZimbraLog.imap.warn("GETACL failed", e);
}
sendNO(tag, "GETACL failed");
return true;
}
sendUntagged(i4acl.toString());
sendNotifications(true, false);
sendOK(tag, "GETACL completed");
return true;
}
use of com.zimbra.client.ZFolder in project zm-mailbox by Zimbra.
the class ImapHandler method accumulatePaths.
private void accumulatePaths(Object mboxobj, String owner, ImapPath relativeTo, Map<ImapPath, ItemId> paths) throws ServiceException {
String root = relativeTo == null ? "" : "/" + relativeTo.asResolvedPath();
if (mboxobj instanceof Mailbox) {
Mailbox mbox = (Mailbox) mboxobj;
Collection<Folder> folders = mbox.getVisibleFolders(getContext());
if (folders == null) {
folders = mbox.getFolderById(getContext(), relativeTo == null ? Mailbox.ID_FOLDER_USER_ROOT : relativeTo.asItemId().getId()).getSubfolderHierarchy();
}
boolean isMailFolders = Provisioning.getInstance().getLocalServer().isImapDisplayMailFoldersOnly();
for (Folder folder : folders) {
if (!folder.getPath().startsWith(root) || folder.getPath().equals(root)) {
continue;
}
//bug 6418 ..filter out folders which are contacts and chat for LIST command.
if (isMailFolders) {
// chat has item type of message.hence ignoring the chat folder by name.
MailItem.Type view = folder.getDefaultView();
if ((view == MailItem.Type.CHAT) || (folder.getName().equals("Chats"))) {
continue;
}
}
ImapPath path = relativeTo == null ? new ImapPath(owner, folder, credentials) : new ImapPath(owner, folder, relativeTo);
if (path.isVisible()) {
if (userAgent != null && userAgent.startsWith(IDInfo.DATASOURCE_IMAP_CLIENT_NAME) && folder.isTagged(Flag.FlagInfo.SYNCFOLDER)) {
//bug 72577 - do not display folders synced with IMAP datasource to downstream IMAP datasource connections
continue;
}
boolean alreadyTraversed = paths.put(path, path.asItemId()) != null;
if (folder instanceof Mountpoint && !alreadyTraversed) {
accumulatePaths(path.getOwnerMailbox(), owner, path, paths);
}
}
}
} else if (mboxobj instanceof ZMailbox) {
ZMailbox zmbx = (ZMailbox) mboxobj;
for (ZFolder zfolder : zmbx.getAllFolders()) {
if (!zfolder.getPath().startsWith(root) || zfolder.getPath().equals(root)) {
continue;
}
ImapPath path = relativeTo == null ? new ImapPath(owner, zfolder, credentials) : new ImapPath(owner, zfolder, relativeTo);
if (path.isVisible()) {
paths.put(path, path.asItemId());
}
}
}
}
use of com.zimbra.client.ZFolder in project zm-mailbox by Zimbra.
the class ImapHandler method doCOPY.
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 = "";
List<MailItem> copies = new ArrayList<MailItem>();
ImapFolder i4folder = getSelectedFolder();
if (i4folder == null) {
throw new ImapSessionClosedException();
}
Mailbox mbox = i4folder.getMailbox();
Set<ImapMessage> i4set;
mbox.lock.lock();
try {
i4set = i4folder.getSubsequence(tag, sequenceSet, byUID);
} finally {
mbox.lock.release();
}
// 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());
}
Object mboxobj = path.getOwnerMailbox();
ItemId iidTarget;
boolean sameMailbox = false;
int uvv;
// check target folder permissions before attempting the copy
if (mboxobj instanceof Mailbox) {
sameMailbox = mbox.getAccountId().equalsIgnoreCase(((Mailbox) mboxobj).getAccountId());
Folder folder = (Folder) path.getFolder();
iidTarget = new ItemId(folder);
uvv = ImapFolder.getUIDValidity(folder);
} else if (mboxobj instanceof ZMailbox) {
ZFolder zfolder = (ZFolder) path.getFolder();
iidTarget = new ItemId(zfolder.getId(), path.getOwnerAccount().getId());
uvv = ImapFolder.getUIDValidity(zfolder);
} else {
throw AccountServiceException.NO_SUCH_ACCOUNT(path.getOwner());
}
long checkpoint = System.currentTimeMillis();
List<Integer> srcUIDs = extensionEnabled("UIDPLUS") ? new ArrayList<Integer>() : null;
List<Integer> copyUIDs = extensionEnabled("UIDPLUS") ? new ArrayList<Integer>() : null;
int i = 0;
List<ImapMessage> i4list = new ArrayList<ImapMessage>(SUGGESTED_COPY_BATCH_SIZE);
List<Integer> idlist = new ArrayList<Integer>(SUGGESTED_COPY_BATCH_SIZE);
List<Integer> createdList = new ArrayList<Integer>(SUGGESTED_COPY_BATCH_SIZE);
for (ImapMessage i4msg : i4set) {
// we're sending 'em off in batches of 50
i4list.add(i4msg);
idlist.add(i4msg.msgId);
if (++i % SUGGESTED_COPY_BATCH_SIZE != 0 && i != i4set.size()) {
continue;
}
if (sameMailbox) {
List<MailItem> copyMsgs;
try {
MailItem.Type type = MailItem.Type.UNKNOWN;
int[] mItemIds = new int[i4list.size()];
int counter = 0;
for (ImapMessage curMsg : i4list) {
mItemIds[counter++] = curMsg.msgId;
if (counter == 1) {
type = curMsg.getType();
} else if (curMsg.getType() != type) {
type = MailItem.Type.UNKNOWN;
}
}
copyMsgs = mbox.imapCopy(getContext(), mItemIds, type, iidTarget.getId());
} catch (IOException e) {
throw ServiceException.FAILURE("Caught IOException executing " + this, e);
}
copies.addAll(copyMsgs);
for (MailItem target : copyMsgs) {
createdList.add(target.getImapUid());
}
} else {
ItemActionHelper op = ItemActionHelper.COPY(getContext(), mbox, null, idlist, MailItem.Type.UNKNOWN, null, iidTarget);
for (String target : op.getCreatedIds()) {
createdList.add(new ItemId(target, selectedFolder.getAuthenticatedAccountId()).getId());
}
}
if (createdList.size() != i4list.size()) {
throw ServiceException.FAILURE("mismatch between original and target count during IMAP COPY", null);
}
if (srcUIDs != null) {
for (ImapMessage source : i4list) {
srcUIDs.add(source.imapUid);
}
for (Integer target : createdList) {
copyUIDs.add(target);
}
}
i4list.clear();
idlist.clear();
createdList.clear();
// 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 && srcUIDs != null && srcUIDs.size() > 0) {
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;
}
use of com.zimbra.client.ZFolder in project zm-mailbox by Zimbra.
the class ImapHandler method doAPPEND.
boolean doAPPEND(String tag, ImapPath path, List<AppendMessage> appends) throws IOException, ImapException {
checkCommandThrottle(new AppendCommand(path, appends));
if (!checkState(tag, State.AUTHENTICATED)) {
return true;
}
Object mboxobj = null;
List<Tag> newTags = new ArrayList<Tag>();
List<Integer> createdIds = new ArrayList<Integer>(appends.size());
StringBuilder appendHint = extensionEnabled("UIDPLUS") ? new StringBuilder() : 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());
}
mboxobj = path.getOwnerMailbox();
Object folderobj = path.getFolder();
Mailbox mbox = mboxobj instanceof Mailbox ? (Mailbox) mboxobj : credentials.getMailbox();
mbox.lock.lock();
try {
ImapFlagCache flagset = ImapFlagCache.getSystemFlags(mbox);
ImapFlagCache tagset = mboxobj instanceof Mailbox ? new ImapFlagCache((Mailbox) mboxobj, getContext()) : new ImapFlagCache();
for (AppendMessage append : appends) {
append.checkFlags(mbox, flagset, tagset, newTags);
}
} finally {
mbox.lock.release();
}
// Append message parts and check message content size
for (AppendMessage append : appends) {
append.checkContent();
}
for (AppendMessage append : appends) {
int id = append.storeContent(mboxobj, folderobj);
if (id > 0) {
createdIds.add(id);
}
}
int uvv = (folderobj instanceof Folder ? ImapFolder.getUIDValidity((Folder) folderobj) : ImapFolder.getUIDValidity((ZFolder) folderobj));
if (appendHint != null && uvv > 0) {
appendHint.append("[APPENDUID ").append(uvv).append(' ').append(ImapFolder.encodeSubsequence(createdIds)).append("] ");
}
} catch (ServiceException e) {
for (AppendMessage append : appends) {
append.cleanup();
}
deleteTags(newTags);
deleteMessages(mboxobj, createdIds);
String msg = "APPEND failed";
if (e.getCode().equals(MailServiceException.NO_SUCH_FOLDER)) {
ZimbraLog.imap.info("APPEND failed: no such folder: " + path);
// of the text of the tagged NO response."
if (path.isCreatable()) {
msg = "[TRYCREATE] APPEND failed: no such mailbox";
}
} else if (e.getCode().equals(MailServiceException.INVALID_NAME)) {
ZimbraLog.imap.info("APPEND failed: " + e.getMessage());
} else if (e.getCode().equals(ImapServiceException.FOLDER_NOT_VISIBLE)) {
ZimbraLog.imap.info("APPEND failed: folder not visible: " + path);
} else if (e.getCode().equals(ImapServiceException.FOLDER_NOT_WRITABLE)) {
ZimbraLog.imap.info("APPEND failed: folder not writable: " + path);
} else if (e.getCode().equals(MailServiceException.QUOTA_EXCEEDED)) {
ZimbraLog.imap.info("APPEND failed: quota exceeded");
} else {
ZimbraLog.imap.warn("APPEND failed", e);
}
sendNO(tag, msg);
return canContinue(e);
}
sendNotifications(true, false);
sendOK(tag, (appendHint == null ? "" : appendHint.toString()) + "APPEND completed");
return true;
}
use of com.zimbra.client.ZFolder in project zm-mailbox by Zimbra.
the class ImapHandler method doRENAME.
boolean doRENAME(String tag, ImapPath oldPath, ImapPath newPath) throws IOException {
if (!checkState(tag, State.AUTHENTICATED)) {
return true;
}
try {
Account source = oldPath.getOwnerAccount(), 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());
}
Object mboxobj = oldPath.getOwnerMailbox();
if (mboxobj instanceof Mailbox) {
int folderId = oldPath.asItemId().getId();
if (folderId == Mailbox.ID_FOLDER_INBOX) {
throw ImapServiceException.CANT_RENAME_INBOX();
}
Mailbox mbox = (Mailbox) mboxobj;
mbox.rename(getContext(), folderId, MailItem.Type.FOLDER, "/" + newPath.asResolvedPath());
} else if (mboxobj instanceof ZMailbox) {
if (oldPath.asItemId().getId() == Mailbox.ID_FOLDER_INBOX) {
throw ImapServiceException.CANT_RENAME_INBOX();
}
ZMailbox zmbx = (ZMailbox) mboxobj;
ZFolder zfolder = (ZFolder) oldPath.getFolder();
zmbx.renameFolder(zfolder.getId(), "/" + 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;
}
Aggregations