use of com.zimbra.cs.mailbox.calendar.Invite in project zm-mailbox by Zimbra.
the class ScheduleOutbox method handleEventRequest.
private void handleEventRequest(DavContext ctxt, ZCalendar.ZVCalendar cal, ZComponent req, DelegationInfo delegationInfo, String rcpt, Element resp) throws ServiceException, DavException {
if (!DavResource.isSchedulingEnabled()) {
resp.addElement(DavElements.E_RECIPIENT).addElement(DavElements.E_HREF).setText(rcpt);
resp.addElement(DavElements.E_REQUEST_STATUS).setText("5.3;No scheduling for the user");
return;
}
ArrayList<Address> recipients = new java.util.ArrayList<Address>();
InternetAddress from, sender, to;
Account target = null;
try {
sender = new JavaMailInternetAddress(delegationInfo.getOriginatorEmail());
Provisioning prov = Provisioning.getInstance();
if (ctxt.getActingAsDelegateFor() != null) {
target = prov.getAccountByName(ctxt.getActingAsDelegateFor());
}
if (target != null) {
from = AccountUtil.getFriendlyEmailAddress(target);
} else {
if (delegationInfo.getOwnerEmail() != null) {
from = new JavaMailInternetAddress(delegationInfo.getOwnerEmail());
} else {
target = getMailbox(ctxt).getAccount();
if (AccountUtil.addressMatchesAccount(target, delegationInfo.getOriginatorEmail())) {
// Make sure we don't use two different aliases for From and Sender.
// This is a concern with Apple iCal, which picks a random alias as originator.
from = sender;
} else {
from = AccountUtil.getFriendlyEmailAddress(target);
}
}
}
if (sender.getAddress() != null && sender.getAddress().equalsIgnoreCase(from.getAddress())) {
sender = null;
}
to = new JavaMailInternetAddress(CalDavUtils.stripMailto(rcpt));
recipients.add(to);
} catch (AddressException e) {
resp.addElement(DavElements.E_RECIPIENT).addElement(DavElements.E_HREF).setText(rcpt);
resp.addElement(DavElements.E_REQUEST_STATUS).setText("3.7;" + rcpt);
return;
}
String status = req.getPropVal(ICalTok.STATUS, "");
String method = cal.getPropVal(ICalTok.METHOD, "REQUEST");
String subject = "";
if (method.equals("REQUEST")) {
ZProperty organizerProp = req.getProperty(ICalTok.ORGANIZER);
if (organizerProp != null) {
String organizerStr = this.getAddressFromPrincipalURL(new ZOrganizer(organizerProp).getAddress());
if (!AccountUtil.addressMatchesAccount(getMailbox(ctxt).getAccount(), organizerStr)) {
ZimbraLog.dav.debug("scheduling appointment on behalf of %s", organizerStr);
}
}
} else if (method.equals("REPLY")) {
ZProperty attendeeProp = req.getProperty(ICalTok.ATTENDEE);
if (attendeeProp == null)
throw new DavException("missing property ATTENDEE", HttpServletResponse.SC_BAD_REQUEST);
ZAttendee attendee = new ZAttendee(attendeeProp);
String partStat = attendee.getPartStat();
if (partStat.equals(IcalXmlStrMap.PARTSTAT_ACCEPTED)) {
subject = "Accept: ";
} else if (partStat.equals(IcalXmlStrMap.PARTSTAT_TENTATIVE)) {
subject = "Tentative: ";
} else if (partStat.equals(IcalXmlStrMap.PARTSTAT_DECLINED)) {
subject = "Decline: ";
}
}
if (status.equals("CANCELLED"))
subject = "Cancelled: ";
subject += req.getPropVal(ICalTok.SUMMARY, "");
String uid = req.getPropVal(ICalTok.UID, null);
if (uid == null) {
resp.addElement(DavElements.E_RECIPIENT).addElement(DavElements.E_HREF).setText(rcpt);
resp.addElement(DavElements.E_REQUEST_STATUS).setText("3.1;UID");
return;
}
try {
List<Invite> components = Invite.createFromCalendar(ctxt.getAuthAccount(), null, cal, false);
FriendlyCalendaringDescription friendlyDesc = new FriendlyCalendaringDescription(components, ctxt.getAuthAccount());
String desc = friendlyDesc.getAsPlainText();
String descHtml = req.getDescriptionHtml();
if ((descHtml == null) || (descHtml.length() == 0))
descHtml = friendlyDesc.getAsHtml();
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(ctxt.getAuthAccount());
MimeMessage mm = CalendarMailSender.createCalendarMessage(target, from, sender, recipients, subject, desc, descHtml, uid, cal);
mbox.getMailSender().setSendPartial(true).sendMimeMessage(ctxt.getOperationContext(), mbox, true, mm, null, null, null, null, false);
} catch (ServiceException e) {
resp.addElement(DavElements.E_RECIPIENT).addElement(DavElements.E_HREF).setText(rcpt);
resp.addElement(DavElements.E_REQUEST_STATUS).setText("5.1");
return;
}
resp.addElement(DavElements.E_RECIPIENT).addElement(DavElements.E_HREF).setText(rcpt);
resp.addElement(DavElements.E_REQUEST_STATUS).setText("2.0;Success");
}
use of com.zimbra.cs.mailbox.calendar.Invite in project zm-mailbox by Zimbra.
the class FreeBusy method toVCalendarAsVEvents.
public String toVCalendarAsVEvents() throws ServiceException {
StringWriter writer = new StringWriter();
String publish = ICalTok.PUBLISH.toString();
long now = System.currentTimeMillis();
writer.append("BEGIN:VCALENDAR").append(NL);
writer.append("PRODID:").append(ZCalendar.sZimbraProdID).append(NL);
writer.append("VERSION:").append(ZCalendar.sIcalVersion).append(NL);
writer.append("METHOD:").append(publish).append(NL);
String uidBase = "tmp_" + LdapUtil.generateUUID() + "_";
int uidCount = 0;
TimeZoneMap tzMap = new TimeZoneMap(ICalTimeZone.getUTC());
for (Iterator<Interval> iter = this.iterator(); iter.hasNext(); ) {
FreeBusy.Interval cur = iter.next();
String status = cur.getStatus();
if (status.equals(IcalXmlStrMap.FBTYPE_FREE)) {
continue;
} else if (status.equals(IcalXmlStrMap.FBTYPE_NODATA)) {
// Treat no-data case same as free, because other apps probably won't understand a non-standard fbtype value.
continue;
}
Invite inv = new Invite(publish, tzMap, true);
inv.setUid(uidBase + (++uidCount));
inv.setSeqNo(0);
inv.setDtStamp(now);
inv.setDtStart(ParsedDateTime.fromUTCTime(cur.getStart()));
inv.setDtEnd(ParsedDateTime.fromUTCTime(cur.getEnd()));
inv.setFreeBusy(status);
if (status.equals(IcalXmlStrMap.FBTYPE_BUSY_TENTATIVE)) {
inv.setStatus(IcalXmlStrMap.STATUS_TENTATIVE);
} else if (status.equals(IcalXmlStrMap.FBTYPE_BUSY_UNAVAILABLE)) {
inv.setStatus(IcalXmlStrMap.STATUS_CONFIRMED);
} else {
// busy
inv.setStatus(IcalXmlStrMap.STATUS_CONFIRMED);
}
ZComponent comp = inv.newToVComponent(false, true);
try {
comp.toICalendar(writer);
} catch (IOException e) {
throw ServiceException.FAILURE("can't write iCalendar object", e);
}
}
writer.append("END:VCALENDAR").append(NL);
return writer.toString();
}
use of com.zimbra.cs.mailbox.calendar.Invite 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.calendar.Invite 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.calendar.Invite in project zm-mailbox by Zimbra.
the class CounterCalendarItem 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);
Invite oldInv = null;
// proxy handling
String idStr = request.getAttribute(MailConstants.A_ID, null);
if (idStr != null) {
ItemId iid = new ItemId(idStr, zsc);
if (!iid.belongsTo(acct))
return proxyRequest(request, context, iid.getAccountId());
CalendarItem calItem = mbox.getCalendarItemById(octxt, iid.getId());
if (calItem == null) {
throw MailServiceException.NO_SUCH_CALITEM(iid.toString(), "Could not find calendar item");
}
// 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());
int compNum = (int) request.getAttributeLong(MailConstants.A_CAL_COMP, 0);
if (compNum != 0) {
oldInv = calItem.getInvite(iid.getSubpartId(), compNum);
if (oldInv == null)
throw MailServiceException.INVITE_OUT_OF_DATE(iid.toString());
}
}
Element msgElem = request.getElement(MailConstants.E_MSG);
InviteParser parser = new InviteParser(oldInv);
CalSendData dat = handleMsgElement(zsc, octxt, msgElem, acct, mbox, parser);
MailSender mailSender = mbox.getMailSender();
mailSender.sendMimeMessage(octxt, mbox, dat.mMm);
Element response = getResponseElement(zsc);
return response;
}
Aggregations