use of com.zimbra.cs.mailbox.MailItem in project zm-mailbox by Zimbra.
the class ImapPartSpecifier method getContent.
Pair<Long, InputStream> getContent(Object obj) throws IOException, BinaryDecodingException, ServiceException {
Pair<Long, InputStream> contents;
if (obj instanceof MimeMessage) {
contents = getContent((MimeMessage) obj);
} else if (obj instanceof MailItem) {
if (!isEntireMessage()) {
throw ServiceException.FAILURE("called writeMessage on non-toplevel part", null);
}
contents = ImapMessage.getContent((MailItem) obj);
} else {
throw ServiceException.FAILURE("called write() with unexpected argument: " + (obj == null ? "null" : obj.getClass().getSimpleName()), null);
}
if (octetStart >= 0 && contents != null) {
// if there is a "partial" octet start/length constraint on this
// part specifier, apply it here
InputStream is = contents.getSecond();
long statedLength = contents.getFirst();
long realLength = Math.max(0, Math.min(statedLength < 0 ? Integer.MAX_VALUE : statedLength, octetEnd) - octetStart);
try {
int start = octetStart;
// don't do skip() correctly
if (is instanceof com.sun.mail.util.BASE64DecoderStream || is instanceof com.sun.mail.util.QPDecoderStream) {
ByteUtil.skip(is, start);
start = 0;
}
is = ByteUtil.SegmentInputStream.create(is, start, start + realLength);
} catch (StartOutOfBoundsException e) {
//return empty string {0} when start is out of range
ZimbraLog.imap.warn("IMAP part requested start out of range", e);
is = new ByteArrayInputStream(new byte[0]);
statedLength = realLength = 0;
} catch (IOException ioe) {
ByteUtil.closeStream(is);
throw ioe;
}
contents = new Pair<Long, InputStream>(statedLength < 0 ? -1 : realLength, is);
}
return contents;
}
use of com.zimbra.cs.mailbox.MailItem in project zm-mailbox by Zimbra.
the class ImapSession method notifyPendingChanges.
@Override
public void notifyPendingChanges(PendingModifications pns, int changeId, Session source) {
if (!pns.hasNotifications()) {
return;
}
ImapHandler i4handler = handler;
try {
synchronized (this) {
AddedItems added = new AddedItems();
if (pns.deleted != null) {
for (Map.Entry<ModificationKey, Change> entry : pns.deleted.entrySet()) {
handleDelete(changeId, entry.getKey().getItemId(), entry.getValue());
}
}
if (pns.created != null) {
for (MailItem item : pns.created.values()) {
handleCreate(changeId, item, added);
}
}
if (pns.modified != null) {
for (Change chg : pns.modified.values()) {
handleModify(changeId, chg, added);
}
}
// add new messages to the currently selected mailbox
if (!added.isEmpty()) {
mFolder.handleAddedMessages(changeId, added);
}
mFolder.finishNotification(changeId);
}
if (i4handler != null && i4handler.isIdle()) {
i4handler.sendNotifications(true, true);
}
} catch (IOException e) {
// which calls Session.doCleanup, which calls Mailbox.removeListener
if (ZimbraLog.imap.isDebugEnabled()) {
// with stack trace
ZimbraLog.imap.debug("Failed to notify, closing %s", this, e);
} else {
// without stack trace
ZimbraLog.imap.info("Failed to notify (%s), closing %s", e.toString(), this);
}
if (i4handler != null) {
i4handler.close();
}
}
}
use of com.zimbra.cs.mailbox.MailItem in project zm-mailbox by Zimbra.
the class CalListCache method notifyCommittedChanges.
void notifyCommittedChanges(PendingModifications mods, int changeId) {
ChangeMap changeMap = new ChangeMap(1);
if (mods.created != null) {
for (Map.Entry<ModificationKey, MailItem> entry : mods.created.entrySet()) {
MailItem item = entry.getValue();
if (item instanceof Folder) {
Folder folder = (Folder) item;
MailItem.Type viewType = folder.getDefaultView();
if (viewType == MailItem.Type.APPOINTMENT || viewType == MailItem.Type.TASK) {
ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
changedFolders.created.add(folder.getId());
}
}
}
}
if (mods.modified != null) {
for (Map.Entry<ModificationKey, Change> entry : mods.modified.entrySet()) {
Change change = entry.getValue();
Object whatChanged = change.what;
if (whatChanged instanceof Folder) {
Folder folder = (Folder) whatChanged;
MailItem.Type viewType = folder.getDefaultView();
if (viewType == MailItem.Type.APPOINTMENT || viewType == MailItem.Type.TASK) {
ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
int folderId = folder.getId();
if ((change.why & Change.FOLDER) != 0) {
// moving the calendar folder to another parent folder
int parentFolder = folder.getFolderId();
changedFolders.created.add(folderId);
if (parentFolder == Mailbox.ID_FOLDER_TRASH) {
changedFolders.deleted.add(folderId);
} else {
changedFolders.created.add(folderId);
}
} else {
// not a folder move, but something else changed, either calendar's metadata
// or a child item (appointment/task)
changedFolders.modified.add(folderId);
}
}
} else if (whatChanged instanceof Message) {
Message msg = (Message) whatChanged;
if (msg.hasCalendarItemInfos()) {
if (msg.getFolderId() == Mailbox.ID_FOLDER_INBOX || (change.why & Change.FOLDER) != 0) {
// If message was moved, we don't know which folder it was moved from.
// Just invalidate the Inbox because that's the only message folder we care
// about in calendaring.
ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
changedFolders.modified.add(Mailbox.ID_FOLDER_INBOX);
}
}
}
}
}
if (mods.deleted != null) {
for (Map.Entry<ModificationKey, Change> entry : mods.deleted.entrySet()) {
MailItem.Type type = (MailItem.Type) entry.getValue().what;
if (type == MailItem.Type.FOLDER) {
// We only have item id. Let's just assume it's a calendar folder id and check
// against the cached list.
ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
changedFolders.deleted.add(entry.getKey().getItemId());
}
// Let's not worry about hard deletes of invite/reply emails. It has no practical benefit.
}
}
try {
for (Map.Entry<String, ChangedFolders> entry : changeMap.entrySet()) {
ChangedFolders changedFolders = entry.getValue();
if (changedFolders.isEmpty())
continue;
String accountId = entry.getKey();
AccountKey key = new AccountKey(accountId);
CalList list = mMemcachedLookup.get(key);
if (list != null) {
boolean updated = false;
CalList newList = new CalList(list);
for (Integer folderId : changedFolders.created) {
if (!list.contains(folderId)) {
updated = true;
newList.add(folderId);
}
}
for (Integer folderId : changedFolders.modified) {
if (list.contains(folderId))
updated = true;
}
for (Integer folderId : changedFolders.deleted) {
if (list.contains(folderId)) {
updated = true;
newList.remove(folderId);
}
}
// There was a change. Increment the version and put back to cache.
if (updated) {
newList.incrementSeq();
mMemcachedLookup.put(key, newList);
}
}
}
} catch (ServiceException e) {
ZimbraLog.calendar.warn("Unable to notify calendar list cache. Some cached data may become stale.", e);
}
}
use of com.zimbra.cs.mailbox.MailItem in project zm-mailbox by Zimbra.
the class CtagInfoCache method notifyCommittedChanges.
void notifyCommittedChanges(PendingModifications mods, int changeId) {
int inboxFolder = Mailbox.ID_FOLDER_INBOX;
Set<CalendarKey> keysToInvalidate = new HashSet<CalendarKey>();
if (mods.created != null) {
for (Map.Entry<ModificationKey, MailItem> entry : mods.created.entrySet()) {
MailItem item = entry.getValue();
if (item instanceof Message) {
Message msg = (Message) item;
if (msg.hasCalendarItemInfos() && msg.getFolderId() == inboxFolder) {
CalendarKey key = new CalendarKey(msg.getMailbox().getAccountId(), inboxFolder);
keysToInvalidate.add(key);
}
}
}
}
if (mods.modified != null) {
for (Map.Entry<ModificationKey, Change> entry : mods.modified.entrySet()) {
Change change = entry.getValue();
Object whatChanged = change.what;
if (whatChanged instanceof Folder) {
Folder folder = (Folder) whatChanged;
MailItem.Type viewType = folder.getDefaultView();
if (viewType == MailItem.Type.APPOINTMENT || viewType == MailItem.Type.TASK) {
CalendarKey key = new CalendarKey(folder.getMailbox().getAccountId(), folder.getId());
keysToInvalidate.add(key);
}
} else if (whatChanged instanceof Message) {
Message msg = (Message) whatChanged;
if (msg.hasCalendarItemInfos()) {
if (msg.getFolderId() == inboxFolder || (change.why & Change.FOLDER) != 0) {
// If message was moved, we don't know which folder it was moved from.
// Just invalidate the Inbox because that's the only message folder we care
// about in calendaring.
CalendarKey key = new CalendarKey(msg.getMailbox().getAccountId(), inboxFolder);
keysToInvalidate.add(key);
}
}
}
}
}
if (mods.deleted != null) {
for (Entry<ModificationKey, Change> entry : mods.deleted.entrySet()) {
Type type = (Type) entry.getValue().what;
if (type == MailItem.Type.FOLDER) {
// We only have item id. Assume it's a folder id and issue a delete.
String acctId = entry.getKey().getAccountId();
if (acctId == null)
// just to be safe
continue;
CalendarKey key = new CalendarKey(acctId, entry.getKey().getItemId());
keysToInvalidate.add(key);
}
// Let's not worry about hard deletes of invite/reply emails. It has no practical benefit.
}
}
try {
mMemcachedLookup.removeMulti(keysToInvalidate);
} catch (ServiceException e) {
ZimbraLog.calendar.warn("Unable to notify ctag info cache. Some cached data may become stale.", e);
}
}
use of com.zimbra.cs.mailbox.MailItem in project zm-mailbox by Zimbra.
the class ContentServlet method getCommand.
private void getCommand(HttpServletRequest req, HttpServletResponse resp, AuthToken token) throws ServletException, IOException {
ItemId iid = null;
try {
iid = new ItemId(req.getParameter(PARAM_MSGID), (String) null);
} catch (ServiceException e) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, L10nUtil.getMessage(MsgKey.errInvalidId, req));
return;
}
String part = req.getParameter(PARAM_PART);
String fmt = req.getParameter(PARAM_FORMAT);
String dumpsterParam = req.getParameter(PARAM_DUMPSTER);
boolean fromDumpster = dumpsterParam != null && !dumpsterParam.equals("0") && !dumpsterParam.equalsIgnoreCase("false");
try {
// need to proxy the fetch if the mailbox lives on another server
if (!iid.isLocal()) {
// wrong server; proxy to the right one...
proxyServletRequest(req, resp, iid.getAccountId());
return;
}
String authId = token.getAccountId();
String accountId = iid.getAccountId() != null ? iid.getAccountId() : authId;
AccountUtil.addAccountToLogContext(Provisioning.getInstance(), accountId, ZimbraLog.C_NAME, ZimbraLog.C_ID, token);
if (!accountId.equalsIgnoreCase(authId))
ZimbraLog.addToContext(ZimbraLog.C_AID, authId);
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(accountId);
if (mbox == null) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, L10nUtil.getMessage(MsgKey.errMailboxNotFound, req));
return;
}
ZimbraLog.addMboxToContext(mbox.getId());
MailItem item = mbox.getItemById(new OperationContext(token), iid.getId(), MailItem.Type.UNKNOWN, fromDumpster);
if (item == null) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, L10nUtil.getMessage(MsgKey.errMessageNotFound, req));
return;
}
try {
if (part == null) {
// they want the entire message...
boolean sync = "1".equals(req.getParameter(PARAM_SYNC));
StringBuffer hdr = new StringBuffer();
if (sync) {
// for sync, return metadata as headers to avoid extra SOAP round-trips
resp.addHeader("X-Zimbra-Tags", TagUtil.getTagIdString(item));
resp.addHeader("X-Zimbra-Tag-Names", TagUtil.encodeTags(item.getTags()));
resp.addHeader("X-Zimbra-Flags", item.getFlagString());
resp.addHeader("X-Zimbra-Received", Long.toString(item.getDate()));
resp.addHeader("X-Zimbra-Modified", Long.toString(item.getChangeDate()));
// also return metadata inline in the message content for now
hdr.append("X-Zimbra-Tags: ").append(TagUtil.getTagIdString(item)).append("\n");
hdr.append("X-Zimbra-Tag-Names: ").append(TagUtil.encodeTags(item.getTags()));
hdr.append("X-Zimbra-Flags: ").append(item.getFlagString()).append("\n");
hdr.append("X-Zimbra-Received: ").append(item.getDate()).append("\n");
hdr.append("X-Zimbra-Modified: ").append(item.getChangeDate()).append("\n");
}
if (item instanceof Message) {
Message msg = (Message) item;
if (sync) {
resp.addHeader("X-Zimbra-Conv", Integer.toString(msg.getConversationId()));
hdr.append("X-Zimbra-Conv: ").append(msg.getConversationId()).append("\n");
resp.getOutputStream().write(hdr.toString().getBytes());
}
resp.setContentType(MimeConstants.CT_TEXT_PLAIN);
InputStream is = msg.getContentStream();
ByteUtil.copy(is, true, resp.getOutputStream(), false);
} else if (item instanceof CalendarItem) {
CalendarItem calItem = (CalendarItem) item;
if (sync) {
resp.getOutputStream().write(hdr.toString().getBytes());
}
resp.setContentType(MimeConstants.CT_TEXT_PLAIN);
if (iid.hasSubpart()) {
int invId = iid.getSubpartId();
MimeMessage mm = calItem.getSubpartMessage(invId);
if (mm == null) {
// Backward compatibility for pre-5.0.16 ZDesktop: Build a MIME message on the fly.
Invite[] invs = calItem.getInvites(invId);
if (invs != null && invs.length > 0) {
Invite invite = invs[0];
mm = CalendarMailSender.createCalendarMessage(invite);
}
}
if (mm != null)
mm.writeTo(resp.getOutputStream());
} else {
InputStream is = calItem.getRawMessage();
if (is != null)
ByteUtil.copy(is, true, resp.getOutputStream(), false);
}
}
return;
} else {
MimePart mp = null;
if (item instanceof Message) {
mp = getMimePart((Message) item, part);
} else {
CalendarItem calItem = (CalendarItem) item;
if (iid.hasSubpart()) {
MimeMessage mbp = calItem.getSubpartMessage(iid.getSubpartId());
if (mbp != null)
mp = Mime.getMimePart(mbp, part);
} else {
mp = getMimePart(calItem, part);
}
}
if (mp != null) {
String contentType = mp.getContentType();
if (contentType == null) {
contentType = MimeConstants.CT_APPLICATION_OCTET_STREAM;
}
if (contentType.toLowerCase().startsWith(MimeConstants.CT_TEXT_HTML) && (FORMAT_DEFANGED_HTML.equals(fmt) || FORMAT_DEFANGED_HTML_NOT_IMAGES.equals(fmt))) {
sendbackDefangedHtml(mp, contentType, resp, fmt);
} else {
if (!isTrue(Provisioning.A_zimbraAttachmentsViewInHtmlOnly, mbox.getAccountId())) {
sendbackOriginalDoc(mp, contentType, req, resp);
} else {
req.setAttribute(ATTR_MIMEPART, mp);
req.setAttribute(ATTR_MSGDIGEST, item.getDigest());
req.setAttribute(ATTR_CONTENTURL, req.getRequestURL().toString());
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(CONVERSION_PATH);
dispatcher.forward(req, resp);
}
}
return;
}
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, L10nUtil.getMessage(MsgKey.errPartNotFound, req));
}
} catch (MessagingException e) {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
} catch (NoSuchItemException e) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND, L10nUtil.getMessage(MsgKey.errNoSuchItem, req));
} catch (ServiceException e) {
returnError(resp, e);
} finally {
ZimbraLog.clearContext();
}
/*
out.println("hello world "+req.getParameter("id"));
out.println("path info: "+req.getPathInfo());
out.println("pathtrans: "+req.getPathTranslated());
*/
}
Aggregations