use of com.zimbra.cs.mailbox.CalendarItem in project zm-mailbox by Zimbra.
the class CalendarRequest method echoAddedInvite.
protected static Element echoAddedInvite(Element parent, ItemIdFormatter ifmt, OperationContext octxt, Mailbox mbox, AddInviteData aid, int maxSize, boolean wantHtml, boolean neuter) throws ServiceException {
CalendarItem calItem = mbox.getCalendarItemById(octxt, aid.calItemId);
Invite inv = calItem.getInvite(aid.invId, aid.compNum);
String recurIdZ = null;
if (inv != null && inv.getRecurId() != null)
recurIdZ = inv.getRecurId().getDtZ();
ItemId iid = new ItemId(calItem, aid.invId);
Element echoElem = parent.addElement(MailConstants.E_CAL_ECHO);
ToXML.encodeInviteAsMP(echoElem, ifmt, octxt, calItem, recurIdZ, iid, null, maxSize, wantHtml, neuter, null, false, false);
return echoElem;
}
use of com.zimbra.cs.mailbox.CalendarItem in project zm-mailbox by Zimbra.
the class CompleteTaskInstance method handle.
@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Mailbox mbox = getRequestedMailbox(zsc);
OperationContext octxt = getOperationContext(zsc, context);
ItemId iid = new ItemId(request.getAttribute(MailConstants.A_ID), zsc);
Element exceptElem = request.getElement(MailConstants.E_CAL_EXCEPTION_ID);
mbox.lock.lock();
try {
CalendarItem calItem = mbox.getCalendarItemById(octxt, iid.getId());
if (calItem == null) {
throw MailServiceException.NO_SUCH_CALITEM(iid.toString(), "Could not find calendar item");
}
if (!(calItem instanceof Task)) {
throw MailServiceException.NO_SUCH_CALITEM(iid.toString(), "Calendar item is not a task");
}
Invite inv = calItem.getDefaultInviteOrNull();
if (inv == null) {
throw MailServiceException.NO_SUCH_CALITEM(iid.toString(), "No default invite found");
}
if (!inv.isRecurrence()) {
throw ServiceException.INVALID_REQUEST("Task is not a recurring task", null);
}
ParsedDateTime recurStart = inv.getStartTime();
if (recurStart == null) {
throw ServiceException.INVALID_REQUEST("Recurring task is missing start time", null);
}
// the instance being marked complete
TimeZoneMap tzmap = inv.getTimeZoneMap();
Element tzElem = request.getOptionalElement(MailConstants.E_CAL_TZ);
ICalTimeZone tz = null;
if (tzElem != null) {
tz = CalendarUtils.parseTzElement(tzElem);
tzmap.add(tz);
}
ParsedDateTime exceptDt = CalendarUtils.parseDateTime(exceptElem, tzmap);
if (exceptDt.getUtcTime() != recurStart.getUtcTime()) {
throw MailServiceException.INVITE_OUT_OF_DATE(iid.toString());
}
// Create a new single-instance task for completed date.
Invite completed = createCompletedInstanceInvite(inv, exceptDt);
mbox.addInvite(octxt, completed, calItem.getFolderId());
// Update recurrence's start date to the next instance start date.
long oldStart = recurStart.getUtcTime();
long newStart = -1;
Collection<Instance> instances = calItem.expandInstances(oldStart, Long.MAX_VALUE, false);
for (Instance inst : instances) {
if (inst.getStart() > oldStart) {
newStart = inst.getStart();
break;
}
}
if (newStart != -1) {
// Update DTSTART to newStart.
ParsedDateTime newStartDt = ParsedDateTime.fromUTCTime(newStart);
newStartDt.toTimeZone(inv.getStartTime().getTimeZone());
newStartDt.setHasTime(recurStart.hasTime());
// Update DUE.
ParsedDuration dur = inv.getEffectiveDuration();
if (dur != null) {
ParsedDateTime due = newStartDt.add(dur);
inv.setDtEnd(due);
}
inv.setDtStart(newStartDt);
inv.setSeqNo(inv.getSeqNo() + 1);
inv.setDtStamp(System.currentTimeMillis());
mbox.addInvite(octxt, inv, calItem.getFolderId());
} else {
// No more instance left. Delete the recurring task.
mbox.delete(octxt, calItem.getId(), calItem.getType());
}
} finally {
mbox.lock.release();
}
// response
Element response = getResponseElement(zsc);
return response;
}
use of com.zimbra.cs.mailbox.CalendarItem in project zm-mailbox by Zimbra.
the class CreateCalendarItemException method handle.
@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Account acct = getRequestedAccount(zsc);
Mailbox mbox = getRequestedMailbox(zsc);
OperationContext octxt = getOperationContext(zsc, context);
ItemIdFormatter ifmt = new ItemIdFormatter(zsc);
// proxy handling
Element msgElem = request.getElement(MailConstants.E_MSG);
String folderStr = msgElem.getAttribute(MailConstants.A_FOLDER, null);
ItemId iid = new ItemId(request.getAttribute(MailConstants.A_ID), zsc);
if (!iid.belongsTo(acct)) {
// Proxy it.
if (folderStr != null) {
// make sure that the folder ID is fully qualified
ItemId folderFQ = new ItemId(folderStr, zsc);
msgElem.addAttribute(MailConstants.A_FOLDER, folderFQ.toString());
}
return proxyRequest(request, context, iid.getAccountId());
}
// Check if moving to a different mailbox.
boolean isInterMboxMove = false;
ItemId iidFolder = null;
if (folderStr != null) {
iidFolder = new ItemId(folderStr, zsc);
isInterMboxMove = !iidFolder.belongsTo(mbox);
}
int compNum = (int) request.getAttributeLong(MailConstants.E_INVITE_COMPONENT);
MailSendQueue sendQueue = new MailSendQueue();
Element response = getResponseElement(zsc);
mbox.lock.lock();
try {
CalendarItem calItem = mbox.getCalendarItemById(octxt, iid.getId());
if (calItem == null)
throw MailServiceException.NO_SUCH_CALITEM(iid.getId(), " for CreateCalendarItemExceptionRequest(" + iid + "," + compNum + ")");
// Reject the request if calendar item is under trash or is being moved to trash.
if (calItem.inTrash())
throw ServiceException.INVALID_REQUEST("cannot modify a calendar item under trash", null);
if (!isInterMboxMove && iidFolder != null) {
if (iidFolder.getId() != calItem.getFolderId()) {
Folder destFolder = mbox.getFolderById(octxt, iidFolder.getId());
if (destFolder.inTrash())
throw ServiceException.INVALID_REQUEST("cannot combine with a move to trash", null);
}
}
// Conflict detection. Do it only if requested by client. (for backward compat)
int modSeq = (int) request.getAttributeLong(MailConstants.A_MODIFIED_SEQUENCE, 0);
int revision = (int) request.getAttributeLong(MailConstants.A_REVISION, 0);
if (modSeq != 0 && revision != 0 && (modSeq < calItem.getModifiedSequence() || revision < calItem.getSavedSequence()))
throw MailServiceException.INVITE_OUT_OF_DATE(iid.toString());
Invite inv = calItem.getInvite(iid.getSubpartId(), compNum);
if (inv == null)
throw MailServiceException.INVITE_OUT_OF_DATE(iid.toString());
if (inv.hasRecurId())
throw MailServiceException.INVITE_OUT_OF_DATE("Invite id=" + ifmt.formatItemId(iid) + " comp=" + compNum + " is not the default invite");
if (!calItem.isRecurring())
throw ServiceException.INVALID_REQUEST("CalendarItem " + calItem.getId() + " is not a recurring calendar item", null);
CreateCalendarItemExceptionInviteParser parser = new CreateCalendarItemExceptionInviteParser(calItem.getUid(), inv, sendQueue);
CalSendData dat = handleMsgElement(zsc, octxt, msgElem, acct, mbox, parser);
dat.mDontNotifyAttendees = isInterMboxMove;
int folderId = calItem.getFolderId();
if (!isInterMboxMove && iidFolder != null)
folderId = iidFolder.getId();
// trace logging
if (!dat.mInvite.hasRecurId())
ZimbraLog.calendar.info("<CreateCalendarItemException> id=%d, folderId=%d, subject=\"%s\", UID=%s", iid.getId(), folderId, dat.mInvite.isPublic() ? dat.mInvite.getName() : "(private)", dat.mInvite.getUid());
else
ZimbraLog.calendar.info("<CreateCalendarItemException> id=%d, folderId=%d, subject=\"%s\", UID=%s, recurId=%s", iid.getId(), folderId, dat.mInvite.isPublic() ? dat.mInvite.getName() : "(private)", dat.mInvite.getUid(), dat.mInvite.getRecurId().getDtZ());
boolean hasRecipients;
try {
Address[] rcpts = dat.mMm.getAllRecipients();
hasRecipients = rcpts != null && rcpts.length > 0;
} catch (MessagingException e) {
throw ServiceException.FAILURE("Checking recipients of outgoing msg ", e);
}
// If we are sending this to other people, then we MUST be the organizer!
if (!dat.mInvite.isOrganizer() && hasRecipients)
throw MailServiceException.MUST_BE_ORGANIZER("CreateCalendarItemException");
if (!dat.mInvite.isOrganizer()) {
// neverSent is always false for attendee users.
dat.mInvite.setNeverSent(false);
} else if (!dat.mInvite.hasOtherAttendees()) {
// neverSent is always false for appointments without attendees.
dat.mInvite.setNeverSent(false);
} else if (hasRecipients) {
// neverSent is set to false when attendees are notified.
dat.mInvite.setNeverSent(false);
} else {
// This is the case of organizer saving an invite with attendees, but without sending the notification.
// Set neverSent to false, but only if it isn't already set to true on the series.
// !series.isNeverSent() ? false : true ==> series.isNeverSent()
dat.mInvite.setNeverSent(inv.isNeverSent());
}
boolean forceSend = request.getAttributeBool(MailConstants.A_CAL_FORCESEND, true);
sendCalendarMessage(zsc, octxt, folderId, acct, mbox, dat, response, true, forceSend, sendQueue);
boolean echo = request.getAttributeBool(MailConstants.A_CAL_ECHO, false);
if (echo && dat.mAddInvData != null) {
int maxSize = (int) request.getAttributeLong(MailConstants.A_MAX_INLINED_LENGTH, 0);
boolean wantHTML = request.getAttributeBool(MailConstants.A_WANT_HTML, false);
boolean neuter = request.getAttributeBool(MailConstants.A_NEUTER, true);
echoAddedInvite(response, ifmt, octxt, mbox, dat.mAddInvData, maxSize, wantHTML, neuter);
}
} finally {
mbox.lock.release();
sendQueue.send();
}
// Inter-mailbox move if necessary.
if (isInterMboxMove) {
CalendarItem calItem = mbox.getCalendarItemById(octxt, iid.getId());
List<Integer> ids = new ArrayList<Integer>(1);
ids.add(calItem.getId());
ItemActionHelper.MOVE(octxt, mbox, zsc.getResponseProtocol(), ids, calItem.getType(), null, iidFolder);
}
return response;
}
use of com.zimbra.cs.mailbox.CalendarItem 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);
} catch (HttpException e) {
throw new IOException("Unknown error", e);
} finally {
ZimbraLog.clearContext();
}
/*
out.println("hello world "+req.getParameter("id"));
out.println("path info: "+req.getPathInfo());
out.println("pathtrans: "+req.getPathTranslated());
*/
}
use of com.zimbra.cs.mailbox.CalendarItem in project zm-mailbox by Zimbra.
the class ItemActionHelper method executeRemote.
private ItemActionResult executeRemote() throws ServiceException, IOException, HttpException {
Account target = Provisioning.getInstance().get(Key.AccountBy.id, mIidFolder.getAccountId());
AuthToken at = getAuthToken();
String pxyAuthToken = Provisioning.onLocalServer(target) ? null : at.getProxyAuthToken();
ZAuthToken zat = null;
if (pxyAuthToken == null) {
zat = at.toZAuthToken();
zat.resetProxyAuthToken();
} else {
zat = new ZAuthToken(pxyAuthToken);
}
ZMailbox.Options zoptions = new ZMailbox.Options(zat, AccountUtil.getSoapUri(target));
zoptions.setNoSession(true);
zoptions.setTargetAccount(target.getId());
zoptions.setTargetAccountBy(Key.AccountBy.id);
ZMailbox zmbx = ZMailbox.getMailbox(zoptions);
zmbx.setName(target.getName());
/* need this when logging in using another user's auth */
// check for mountpoints before going any further...
ZFolder zfolder = zmbx.getFolderById(mIidFolder.toString(mAuthenticatedAccount));
if (zfolder instanceof ZMountpoint) {
ItemId iidTarget = new ItemId(((ZMountpoint) zfolder).getCanonicalRemoteId(), mAuthenticatedAccount.getId());
if (!mIidFolder.equals(iidTarget)) {
mIidFolder = iidTarget;
if (++mHopCount > com.zimbra.soap.ZimbraSoapContext.MAX_HOP_COUNT)
throw MailServiceException.TOO_MANY_HOPS(mIidRequestedFolder);
schedule();
return ItemActionResult.create(mOperation);
}
}
boolean deleteOriginal = mOperation != Op.COPY;
String folderStr = mIidFolder.toString();
List<String> createdIds = new ArrayList<String>(itemIds.length);
List<String> nonExistentIds = new ArrayList<String>();
boolean toSpam = mIidFolder.getId() == Mailbox.ID_FOLDER_SPAM;
boolean toMailbox = !toSpam && mIidFolder.getId() != Mailbox.ID_FOLDER_TRASH;
for (MailItem item : mMailbox.getItemById(mOpCtxt, itemIds, type)) {
if (item == null) {
continue;
}
List<Message> msgs = null;
if (item instanceof Conversation) {
msgs = mMailbox.getMessagesByConversation(mOpCtxt, item.getId(), SortBy.DATE_ASC, -1);
}
if (deleteOriginal) {
if (msgs != null) {
// determine which of the conversation's component messages are actually able to be moved
boolean permDenied = false;
for (Iterator<Message> it = msgs.iterator(); it.hasNext(); ) {
Message msg = it.next();
if (!TargetConstraint.checkItem(mTargetConstraint, msg)) {
it.remove();
} else if (!canDelete(msg)) {
it.remove();
permDenied = true;
}
}
// stop here if no messages would be moved...
if (msgs.isEmpty()) {
if (permDenied) {
throw ServiceException.PERM_DENIED("cannot delete any messages in " + item.getType() + " " + item.getId());
}
// all messages were excluded by the TargetConstraint, so there's no failure...
continue;
}
} else {
if (!canDelete(item)) {
throw ServiceException.PERM_DENIED("cannot delete existing copy of " + item.getType() + " " + item.getId());
}
}
}
boolean fromSpam = item.inSpam();
if ((fromSpam && toMailbox) || (!fromSpam && toSpam)) {
try {
Folder dest = mMailbox.getFolderById(mOpCtxt, mIidFolder.getId());
SpamReport report = new SpamReport(toSpam, "remote " + mOperation, dest.getPath());
Folder source = mMailbox.getFolderById(mOpCtxt, item.getFolderId());
report.setSourceFolderPath(source.getPath());
report.setDestAccountName(target.getName());
SpamHandler.getInstance().handle(mOpCtxt, mMailbox, item.getId(), item.getType(), report);
} catch (OutOfMemoryError e) {
Zimbra.halt("out of memory", e);
} catch (Throwable t) {
ZimbraLog.mailop.info("could not train spam filter: " + new ItemId(item).toString(), t);
}
}
// since we can't apply tags to a remote object, hardwiring "tags" to null below...
String flags = (mOperation == Op.UPDATE && mFlags != null ? mFlags : item.getFlagString());
String name = ((mOperation == Op.RENAME || mOperation == Op.UPDATE) && mName != null ? mName : item.getName());
String createdId = null;
InputStream in = null;
switch(item.getType()) {
case CONTACT:
Contact ct = (Contact) item;
Map<String, ZMailbox.ZAttachmentInfo> attachments = new HashMap<String, ZMailbox.ZAttachmentInfo>();
for (Contact.Attachment att : ct.getAttachments()) {
String attachmentId = zmbx.uploadAttachment(att.getFilename(), att.getContent(), att.getContentType(), 0);
ZMailbox.ZAttachmentInfo info = new ZMailbox.ZAttachmentInfo().setAttachmentId(attachmentId);
attachments.put(att.getName(), info);
}
Map<String, String> fields = ct.getFields();
Map<String, String> members = new HashMap<String, String>();
for (String key : fields.keySet()) {
if (ContactConstants.A_groupMember.equals(key)) {
String memberEncoded = fields.get(key);
ContactGroup group = ContactGroup.init(memberEncoded);
for (Member m : group.getMembers()) {
members.put(m.getValue(), m.getType().getSoapEncoded());
}
break;
}
}
fields.remove(ContactConstants.A_groupMember);
ZContact contact = zmbx.createContact(folderStr, null, fields, attachments, members);
createdId = contact.getId();
createdIds.add(createdId);
break;
case MESSAGE:
try {
in = StoreManager.getInstance().getContent(item.getBlob());
createdId = zmbx.addMessage(folderStr, flags, (String) null, item.getDate(), in, item.getSize(), true);
} finally {
ByteUtil.closeStream(in);
}
createdIds.add(createdId);
break;
case VIRTUAL_CONVERSATION:
case CONVERSATION:
for (Message msg : msgs) {
flags = (mOperation == Op.UPDATE && mFlags != null ? mFlags : msg.getFlagString());
try {
in = StoreManager.getInstance().getContent(msg.getBlob());
createdId = zmbx.addMessage(folderStr, flags, (String) null, msg.getDate(), in, msg.getSize(), true);
} finally {
ByteUtil.closeStream(in);
}
createdIds.add(createdId);
}
break;
case DOCUMENT:
Document doc = (Document) item;
SoapHttpTransport transport = new SoapHttpTransport(zoptions.getUri());
try {
in = StoreManager.getInstance().getContent(doc.getBlob());
String uploadId = zmbx.uploadContentAsStream(name, in, doc.getContentType(), doc.getSize(), 4000, true);
// instead of using convenience method from ZMailbox
// we need to hand marshall the request and set the
// response protocol explicitly to what was requested
// from the client.
Element req = new XMLElement(MailConstants.SAVE_DOCUMENT_REQUEST);
Element edoc = req.addUniqueElement(MailConstants.E_DOC);
edoc.addAttribute(MailConstants.A_NAME, name);
edoc.addAttribute(MailConstants.A_FOLDER, folderStr);
edoc.addAttribute(MailConstants.A_FLAGS, flags);
Element upload = edoc.addNonUniqueElement(MailConstants.E_UPLOAD);
upload.addAttribute(MailConstants.A_ID, uploadId);
transport.setResponseProtocol(mResponseProtocol);
transport.setAuthToken(zat);
Element response = transport.invoke(req);
createdId = response.getElement(MailConstants.E_DOC).getAttribute(MailConstants.A_ID);
} finally {
ByteUtil.closeStream(in);
transport.shutdown();
}
createdIds.add(createdId);
break;
case APPOINTMENT:
case TASK:
CalendarItem cal = (CalendarItem) item;
// private calendar item may not be moved by non-owner unless permission was granted
if (!cal.isPublic()) {
boolean asAdmin = mOpCtxt != null ? mOpCtxt.isUsingAdminPrivileges() : false;
if (!cal.allowPrivateAccess(mAuthenticatedAccount, asAdmin))
throw ServiceException.PERM_DENIED("you do not have permission to move/copy a private calendar item from the current folder/mailbox");
}
// Move the item to remote mailbox using SetAppointmentRequest/SetTaskRequest.
QName qname = (item.getType() == MailItem.Type.TASK ? MailConstants.SET_TASK_REQUEST : MailConstants.SET_APPOINTMENT_REQUEST);
Element request = new Element.XMLElement(qname).addAttribute(MailConstants.A_FOLDER, folderStr).addAttribute(MailConstants.A_FLAGS, flags);
ToXML.encodeAlarmTimes(request, cal);
Invite invDefault = cal.getDefaultInviteOrNull();
// Takeover as organizer if we're doing a MOVE and source mailbox is the organizer.
// Don't takeover in a COPY operation.
boolean takeoverAsOrganizer = false;
boolean blockMove = false;
if (Op.MOVE.equals(mOperation)) {
Invite inv = invDefault;
if (inv == null) {
// no default invite; let's use the first invite
Invite[] invs = cal.getInvites();
if (invs != null && invs.length > 0)
inv = invs[0];
}
takeoverAsOrganizer = inv != null && inv.isOrganizer();
blockMove = takeoverAsOrganizer && inv.hasOtherAttendees();
}
if (blockMove) {
throw MailServiceException.INVALID_REQUEST("This operation requires change of organizer and it is not permitted", null);
}
if (invDefault != null) {
addCalendarPart(request.addUniqueElement(MailConstants.A_DEFAULT), cal, invDefault, zmbx, target, takeoverAsOrganizer);
}
for (Invite inv : cal.getInvites()) {
if (inv == null || inv == invDefault)
continue;
String elem = inv.isCancel() ? MailConstants.E_CAL_CANCEL : MailConstants.E_CAL_EXCEPT;
addCalendarPart(request.addNonUniqueElement(elem), cal, inv, zmbx, target, takeoverAsOrganizer);
}
ToXML.encodeCalendarReplies(request, cal);
createdId = zmbx.invoke(request).getAttribute(MailConstants.A_CAL_ID);
createdIds.add(createdId);
break;
default:
throw MailServiceException.CANNOT_COPY(item.getId());
}
try {
if (deleteOriginal && !mIdFormatter.formatItemId(item).equals(createdId)) {
List<Integer> nonExistentItems = new ArrayList<Integer>();
if (msgs == null) {
mMailbox.delete(mOpCtxt, new int[] { item.getId() }, item.getType(), null, nonExistentItems);
} else {
for (Message msg : msgs) {
mMailbox.delete(mOpCtxt, new int[] { msg.getId() }, msg.getType(), null, nonExistentItems);
}
}
for (Integer id : nonExistentItems) {
nonExistentIds.add(id.toString());
}
}
} catch (ServiceException e) {
if (e.getCode() != ServiceException.PERM_DENIED)
throw e;
// something funky happened permissions-wise between the getEffectivePermissions check and here...
ZimbraLog.misc.info("could not delete original item " + item.getId() + "; treating operation as a copy instead");
}
}
ItemActionResult result = ItemActionResult.create(mOperation);
if (Op.HARD_DELETE.equals(mOperation)) {
((DeleteActionResult) result).setNonExistentIds(nonExistentIds);
} else if (Op.COPY.equals(mOperation)) {
((CopyActionResult) result).setCreatedIds(createdIds);
}
for (int itemId : itemIds) {
result.appendSuccessId(Integer.toString(itemId));
}
return result;
}
Aggregations