use of com.zimbra.common.calendar.ZCalendar.ICalTok in project zm-mailbox by Zimbra.
the class ToXML method encodeInvitesForMessage.
private static Element encodeInvitesForMessage(Element parent, ItemIdFormatter ifmt, OperationContext octxt, Message msg, int fields, boolean neuter) throws ServiceException {
if (fields != NOTIFY_FIELDS && !needToOutput(fields, Change.INVITE)) {
return parent;
}
Element ie = parent.addNonUniqueElement(MailConstants.E_INVITE);
Mailbox mbox = msg.getMailbox();
for (Iterator<Message.CalendarItemInfo> iter = msg.getCalendarItemInfoIterator(); iter.hasNext(); ) {
Message.CalendarItemInfo info = iter.next();
CalendarItem calItem = null;
ICalTok method = ICalTok.REQUEST;
Invite invCi = info.getInvite();
if (invCi != null) {
method = Invite.lookupMethod(invCi.getMethod());
}
Invite invite = invCi;
ItemId calendarItemId = info.getCalendarItemId();
if (info.calItemCreated()) {
try {
calItem = mbox.getCalendarItemById(octxt, calendarItemId);
} catch (MailServiceException.NoSuchItemException e) {
// Calendar item has been deleted. Bug 84877 - don't include stale references to it in SOAP response
calendarItemId = null;
} catch (ServiceException e) {
// eat PERM_DENIED
if (e.getCode() != ServiceException.PERM_DENIED) {
throw e;
}
// If we can't access it. Don't include a reference to it.
calendarItemId = null;
}
// Do staleness check for invitation messages.
if (ICalTok.REQUEST.equals(method) || ICalTok.PUBLISH.equals(method)) {
if (calItem != null && calItem.getFolderId() != Mailbox.ID_FOLDER_TRASH) {
if (invCi != null) {
// See if the messsage's invite is outdated.
Invite invCurr = calItem.getInvite(invCi.getRecurId());
if (invCurr != null) {
if (invCi.getSeqNo() >= invCurr.getSeqNo()) {
// Invite is new or same as what's in the appointment. Show it.
invite = invCi;
} else {
// Outdated. Don't show it.
invite = null;
}
} else {
// New invite. Show it.
invite = invCi;
}
} else {
// legacy case
invite = calItem.getInvite(msg.getId(), info.getComponentNo());
// invite == null if the invite was outdated by a newer update
}
}
}
} else {
// We have an invite that wasn't auto-added.
if (invCi != null) {
if (!Invite.isOrganizerMethod(invCi.getMethod()) || ICalTok.DECLINECOUNTER.equals(method)) {
invite = invCi;
} else {
try {
calItem = mbox.getCalendarItemByUid(octxt, invCi.getUid());
} catch (MailServiceException.NoSuchItemException e) {
// ignore
} catch (ServiceException e) {
// eat PERM_DENIED
if (e.getCode() != ServiceException.PERM_DENIED) {
throw e;
}
}
if (calItem != null) {
// See if the messsage's invite is outdated.
Invite invCurr = calItem.getInvite(invCi.getRecurId());
if (invCurr != null) {
if (invCi.getSeqNo() >= invCurr.getSeqNo()) {
// Invite is new or same as what's in the appointment. Show it.
invite = invCi;
} else {
// Outdated. Don't show it.
invite = null;
}
} else {
// New invite. Show it.
invite = invCi;
}
} else {
// Appointment doesn't exist. The invite in the message should be displayed and the
// user can manually add the appointment.
invite = invCi;
}
}
}
}
if (invite != null) {
setCalendarItemType(ie, invite.getItemType());
encodeTimeZoneMap(ie, invite.getTimeZoneMap());
com.zimbra.soap.mail.type.CalendarItemInfo remoteCalendarItem = null;
if (calItem == null) {
remoteCalendarItem = msg.getRemoteCalendarItem(invite);
if (remoteCalendarItem != null) {
calendarItemId = new ItemId(remoteCalendarItem.getId(), (String) null);
}
}
encodeInviteComponent(ie, ifmt, octxt, calItem, calendarItemId, invite, fields, neuter);
ICalTok invMethod = Invite.lookupMethod(invite.getMethod());
if (ICalTok.REQUEST.equals(invMethod) || ICalTok.PUBLISH.equals(invMethod)) {
InviteChanges invChanges = info.getInviteChanges();
if (invChanges != null && !invChanges.noChange()) {
Element comp = ie.getOptionalElement(MailConstants.E_INVITE_COMPONENT);
if (comp != null) {
comp.addAttribute(MailConstants.A_CAL_CHANGES, invChanges.toString());
}
}
if (calItem != null) {
boolean showAll = invite.isPublic() || allowPrivateAccess(octxt, calItem);
if (showAll) {
RecurId rid = invite.getRecurId();
encodeCalendarReplies(ie, calItem, invite, rid != null ? rid.getDtZ() : null);
}
} else if (null != remoteCalendarItem) {
CalendarReply.encodeCalendarReplyList(ie, remoteCalendarItem.getCalendarReplies());
}
}
}
}
return ie;
}
use of com.zimbra.common.calendar.ZCalendar.ICalTok in project zm-mailbox by Zimbra.
the class FreeBusy method parse.
/**
* Create a FreeBusy object from VFREEBUSY ZComponent.
* @param comp
* @return
* @throws ServiceException
*/
public static FreeBusy parse(ZComponent comp) throws ServiceException {
String name = null;
ParsedDateTime dtStart = null;
ParsedDateTime dtEnd = null;
List<Interval> intervals = new ArrayList<Interval>();
TimeZoneMap tzmap = new TimeZoneMap(ICalTimeZone.getUTC());
Iterator<ZProperty> propIter = comp.getPropertyIterator();
while (propIter.hasNext()) {
ZProperty prop = propIter.next();
ICalTok tok = prop.getToken();
if (tok == null)
continue;
switch(tok) {
case DTSTART:
try {
dtStart = ParsedDateTime.parse(prop, tzmap);
} catch (ParseException e) {
throw ServiceException.INVALID_REQUEST("bad DTSTART: " + prop.toString(), e);
}
break;
case DTEND:
try {
dtEnd = ParsedDateTime.parse(prop, tzmap);
} catch (ParseException e) {
throw ServiceException.INVALID_REQUEST("bad DTEND: " + prop.toString(), e);
}
break;
case ORGANIZER:
ZOrganizer att = new ZOrganizer(prop);
name = att.getAddress();
break;
case FREEBUSY:
String fbStatus = IcalXmlStrMap.FBTYPE_FREE;
ZParameter fbType = prop.getParameter(ICalTok.FBTYPE);
if (fbType != null)
fbStatus = IcalXmlStrMap.sFreeBusyMap.toXml(fbType.getValue());
List<String> vals = prop.getValueList();
for (String fbVal : vals) {
Period period;
try {
period = Period.parse(fbVal, ICalTimeZone.getUTC(), tzmap);
} catch (ParseException e) {
throw ServiceException.INVALID_REQUEST("bad period value: " + fbVal, e);
}
intervals.add(new Interval(period.getStart().getUtcTime(), period.getEnd().getUtcTime(), fbStatus));
}
break;
}
}
if (name == null)
throw ServiceException.INVALID_REQUEST("VFREEBUSY missing ORGANIZER", null);
if (dtStart == null || dtEnd == null)
throw ServiceException.INVALID_REQUEST("VFREEBUSY missing DTSTART/DTEND", null);
IntervalList ivalList = new IntervalList(dtStart.getUtcTime(), dtEnd.getUtcTime());
for (Interval ival : intervals) {
ivalList.addInterval(ival);
}
return new FreeBusy(name, ivalList, dtStart.getUtcTime(), dtEnd.getUtcTime());
}
use of com.zimbra.common.calendar.ZCalendar.ICalTok in project zm-mailbox by Zimbra.
the class ForwardCalendarItem method setDescProps.
private static void setDescProps(ZVCalendar cal, String descPlain, String descHtml) {
for (Iterator<ZComponent> compIter = cal.getComponentIterator(); compIter.hasNext(); ) {
ZComponent comp = compIter.next();
ICalTok compName = ICalTok.lookup(comp.getName());
if (ICalTok.VEVENT.equals(compName) || ICalTok.VTODO.equals(compName)) {
// Remove existing DESCRIPTION and X-ALT-DESC properties.
for (Iterator<ZProperty> propIter = comp.getPropertyIterator(); propIter.hasNext(); ) {
ZProperty prop = propIter.next();
ICalTok tok = prop.getToken();
if (ICalTok.DESCRIPTION.equals(tok) || ICalTok.X_ALT_DESC.equals(tok))
propIter.remove();
}
if (descPlain != null && descPlain.length() > 0) {
comp.addProperty(new ZProperty(ICalTok.DESCRIPTION, descPlain));
}
if (descHtml != null && descHtml.length() > 0) {
ZProperty prop = new ZProperty(ICalTok.X_ALT_DESC, descHtml);
prop.addParameter(new ZParameter(ICalTok.FMTTYPE, MimeConstants.CT_TEXT_HTML));
comp.addProperty(prop);
}
// only update the first component (comps are ordered correctly)
break;
}
}
}
use of com.zimbra.common.calendar.ZCalendar.ICalTok in project zm-mailbox by Zimbra.
the class ForwardCalendarItem method setSentByAndAttendees.
private static void setSentByAndAttendees(ZVCalendar cal, String sentBy, Address[] rcpts) throws ServiceException {
// Set SENT-BY to sender's email address in ORGANIZER property of all VEVENT/VTODO components.
// Required by Outlook.
// Also, remove existing ATTENDEEs and add ATTENDEE lines for forwardees.
String sentByAddr = "mailto:" + sentBy;
for (Iterator<ZComponent> compIter = cal.getComponentIterator(); compIter.hasNext(); ) {
ZComponent comp = compIter.next();
ICalTok compName = ICalTok.lookup(comp.getName());
if (ICalTok.VEVENT.equals(compName) || ICalTok.VTODO.equals(compName)) {
// Remove existing ATTENDEEs and X-MS-OLK-SENDER.
for (Iterator<ZProperty> propIter = comp.getPropertyIterator(); propIter.hasNext(); ) {
ZProperty prop = propIter.next();
if (ICalTok.ATTENDEE.equals(prop.getToken()) || "X-MS-OLK-SENDER".equalsIgnoreCase(prop.getName()))
propIter.remove();
}
// SENT-BY
ZProperty orgProp = comp.getProperty(ICalTok.ORGANIZER);
if (orgProp != null) {
ZParameter sentByParam = orgProp.getParameter(ICalTok.SENT_BY);
if (sentByParam != null) {
sentByParam.setValue(sentByAddr);
} else {
sentByParam = new ZParameter(ICalTok.SENT_BY, sentByAddr);
orgProp.addParameter(sentByParam);
}
// Set X-MS-OLK-SENDER, another Outlook special.
ZProperty xMsOlkSender = new ZProperty("X-MS-OLK-SENDER");
xMsOlkSender.setValue(sentByAddr);
comp.addProperty(xMsOlkSender);
}
// ATTENDEEs
if (rcpts == null)
throw ServiceException.INVALID_REQUEST("Missing forwardees", null);
for (Address r : rcpts) {
InternetAddress rcpt = (InternetAddress) r;
String email = "mailto:" + rcpt.getAddress();
ZProperty att = new ZProperty(ICalTok.ATTENDEE, email);
String name = rcpt.getPersonal();
if (name != null && name.length() > 0)
att.addParameter(new ZParameter(ICalTok.CN, name));
att.addParameter(new ZParameter(ICalTok.PARTSTAT, ICalTok.NEEDS_ACTION.toString()));
att.addParameter(new ZParameter(ICalTok.RSVP, "TRUE"));
comp.addProperty(att);
}
}
}
}
use of com.zimbra.common.calendar.ZCalendar.ICalTok in project zm-mailbox by Zimbra.
the class CalendarRequest method notifyCalendarItem.
// Notify attendees following an update to the series of a recurring appointment. Only the
// added attendees are notified if notifyAllAttendees is false. If it is true all attendees
// for each invite are notified. (Some invites may have more attendees than others.)
protected static void notifyCalendarItem(ZimbraSoapContext zsc, OperationContext octxt, Account acct, Mailbox mbox, CalendarItem calItem, boolean notifyAllAttendees, List<ZAttendee> addedAttendees, boolean ignorePastExceptions, MailSendQueue sendQueue) throws ServiceException {
boolean onBehalfOf = isOnBehalfOfRequest(zsc);
Account authAcct = getAuthenticatedAccount(zsc);
boolean hidePrivate = !calItem.isPublic() && !calItem.allowPrivateAccess(authAcct, zsc.isUsingAdminPrivileges());
Address from = AccountUtil.getFriendlyEmailAddress(acct);
Address sender = null;
if (onBehalfOf)
sender = AccountUtil.getFriendlyEmailAddress(authAcct);
List<Address> addedRcpts = CalendarMailSender.toListFromAttendees(addedAttendees);
long now = octxt != null ? octxt.getTimestamp() : System.currentTimeMillis();
mbox.lock.lock();
try {
// Refresh the cal item so we see the latest blob, whose path may have been changed
// earlier in the current request.
calItem = mbox.getCalendarItemById(octxt, calItem.getId());
Invite[] invites = calItem.getInvites();
// Get exception instances. These will be included in the series update email.
List<Invite> exceptions = new ArrayList<Invite>();
for (Invite inv : invites) {
if (inv.hasRecurId()) {
exceptions.add(inv);
}
}
// Send the update invites.
boolean didExceptions = false;
for (Invite inv : invites) {
if (ignorePastExceptions && inv.hasRecurId() && !inviteIsAfterTime(inv, now)) {
continue;
}
// Make the new iCalendar part to send.
ZVCalendar cal = inv.newToICalendar(!hidePrivate);
// For series invite, append the exception instances.
if (inv.isRecurrence() && !didExceptions) {
// Find the VEVENT/VTODO for the series.
ZComponent seriesComp = null;
for (Iterator<ZComponent> compIter = cal.getComponentIterator(); compIter.hasNext(); ) {
ZComponent comp = compIter.next();
ICalTok compName = comp.getTok();
if (ICalTok.VEVENT.equals(compName) || ICalTok.VTODO.equals(compName)) {
if (comp.getProperty(ICalTok.RRULE) != null) {
seriesComp = comp;
break;
}
}
}
for (Invite except : exceptions) {
if (except.isCancel() && seriesComp != null) {
// Cancels are added as EXDATEs in the series VEVENT/VTODO.
RecurId rid = except.getRecurId();
if (rid != null && rid.getDt() != null) {
ZProperty exdate = rid.getDt().toProperty(ICalTok.EXDATE, false);
seriesComp.addProperty(exdate);
}
} else {
// Exception instances are added as additional VEVENTs/VTODOs.
ZComponent exceptComp = except.newToVComponent(false, !hidePrivate);
cal.addComponent(exceptComp);
}
}
didExceptions = true;
}
// Compose email using the existing MimeMessage as template and send it.
MimeMessage mmInv = calItem.getSubpartMessage(inv.getMailItemId());
List<Address> rcpts;
if (notifyAllAttendees) {
rcpts = CalendarMailSender.toListFromAttendees(inv.getAttendees());
} else {
rcpts = addedRcpts;
}
if (rcpts != null && !rcpts.isEmpty()) {
MimeMessage mmModify = CalendarMailSender.createCalendarMessage(authAcct, from, sender, rcpts, mmInv, inv, cal, true);
CalSendData csd = new CalSendData();
csd.mMm = mmModify;
csd.mOrigId = new ItemId(mbox, inv.getMailItemId());
MailSendQueueEntry entry = new MailSendQueueEntry(octxt, mbox, csd, null);
sendQueue.add(entry);
}
}
} finally {
mbox.lock.release();
}
}
Aggregations