use of com.zimbra.cs.mailbox.calendar.ZOrganizer in project zm-mailbox by Zimbra.
the class CalendarUtils method cancelInvite.
private static Invite cancelInvite(Account acct, Account senderAcct, boolean allowPrivateAccess, boolean onBehalfOf, Invite inv, String comment, List<ZAttendee> forAttendees, RecurId recurId, boolean incrementSeq) throws ServiceException {
Invite cancel = new Invite(inv.getItemType(), ICalTok.CANCEL.toString(), inv.getTimeZoneMap(), inv.isOrganizer());
// ORGANIZER
if (inv.hasOrganizer()) {
ZOrganizer org = new ZOrganizer(inv.getOrganizer());
if (onBehalfOf && senderAcct != null)
org.setSentBy(senderAcct.getName());
cancel.setOrganizer(org);
}
// ATTENDEEs
List<ZAttendee> attendees = forAttendees != null ? forAttendees : inv.getAttendees();
for (ZAttendee a : attendees) cancel.addAttendee(a);
cancel.setClassProp(inv.getClassProp());
boolean showAll = inv.isPublic() || allowPrivateAccess;
Locale locale = acct.getLocale();
if (!showAll) {
// SUMMARY
String sbj = L10nUtil.getMessage(MsgKey.calendarSubjectWithheld, locale);
cancel.setName(CalendarMailSender.getCancelSubject(sbj, locale));
} else {
// SUMMARY
cancel.setName(CalendarMailSender.getCancelSubject(inv.getName(), locale));
// COMMENT
if (comment != null && !comment.equals(""))
cancel.addComment(comment);
}
// UID
cancel.setUid(inv.getUid());
// RECURRENCE-ID
if (inv.hasRecurId()) {
// FIXME: if RECURRENCE-ID can be a range (THISANDFUTURE) then we'll
// need to be smarter here
cancel.setRecurId(inv.getRecurId());
} else {
if (recurId != null) {
cancel.setRecurId(recurId);
}
}
// all-day
// bug 30121
cancel.setIsAllDayEvent(inv.isAllDayEvent());
// DTSTART, DTEND, and LOCATION (Outlook seems to require these, even
// though they are optional according to RFC2446.)
ParsedDateTime dtStart = recurId == null ? inv.getStartTime() : recurId.getDt();
if (dtStart != null) {
cancel.setDtStart(dtStart);
ParsedDuration dur = inv.getEffectiveDuration();
if (dur != null)
cancel.setDtEnd(dtStart.add(dur));
}
// LOCATION
cancel.setLocation(inv.getLocation());
// SEQUENCE
int seq = inv.getSeqNo();
if (incrementSeq) {
// present value. (bug 8465)
if (acct != null && inv.isOrganizer())
seq++;
}
cancel.setSeqNo(seq);
// STATUS
cancel.setStatus(IcalXmlStrMap.STATUS_CANCELLED);
// DTSTAMP
cancel.setDtStamp(new Date().getTime());
return cancel;
}
use of com.zimbra.cs.mailbox.calendar.ZOrganizer in project zm-mailbox by Zimbra.
the class CalendarUtils method parseInviteForCreateException.
static ParseMimeMessage.InviteParserResult parseInviteForCreateException(Account account, MailItem.Type type, Element inviteElem, TimeZoneMap tzMap, String uid, Invite defaultInv) throws ServiceException {
if (tzMap == null) {
tzMap = new TimeZoneMap(Util.getAccountTimeZone(account));
}
Invite create = new Invite(ICalTok.PUBLISH.toString(), tzMap, false);
create.setSentByMe(true);
CalendarUtils.parseInviteElementCommon(account, type, inviteElem, create, true, false);
// DTSTAMP
if (create.getDTStamp() == 0) {
//zdsync
create.setDtStamp(new Date().getTime());
}
// UID
if (uid != null && uid.length() > 0)
create.setUid(uid);
// SEQUENCE - Make sure it's greater than the series sequence. (bugs 19111 and 35036)
create.setSeqNo(Math.max(create.getSeqNo(), defaultInv.getSeqNo() + 1));
// Don't allow changing organizer in an exception instance.
create.setOrganizer(defaultInv.hasOrganizer() ? new ZOrganizer(defaultInv.getOrganizer()) : null);
create.setIsOrganizer(account);
// change tracking
String changes = parseInviteChanges(inviteElem);
if (changes != null) {
// Set the changes as x-prop in the serialized iCalendar object, but not to the parsed Invite object.
create.addXProp(new ZProperty(ICalTok.X_ZIMBRA_CHANGES, changes));
}
ZVCalendar iCal = create.newToICalendar(true);
// Don't set the changes x-prop in the parsed Invite.
create.removeXProp(ICalTok.X_ZIMBRA_CHANGES.toString());
String summaryStr = create.getName() != null ? create.getName() : "";
ParseMimeMessage.InviteParserResult toRet = new ParseMimeMessage.InviteParserResult();
toRet.mCal = iCal;
toRet.mUid = create.getUid();
toRet.mSummary = summaryStr;
toRet.mInvite = create;
return toRet;
}
use of com.zimbra.cs.mailbox.calendar.ZOrganizer 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.cs.mailbox.calendar.ZOrganizer in project zm-mailbox by Zimbra.
the class Mailbox method processICalReplies.
private void processICalReplies(OperationContext octxt, ZVCalendar cal, String sender) throws ServiceException {
// Reply from Outlook will usually have PRODID set to the following:
//
// Outlook2007+ZCO: PRODID:-//Microsoft Corporation//Outlook 12.0 MIMEDIR//EN
// Outlook2010+ZCO: PRODID:-//Microsoft Corporation//Outlook 14.0 MIMEDIR//EN
// Outlook20xx+Exchange: PRODID:Microsoft Exchange Server 2007
// (if Exchange is Exchange 2007; Exchange 2010 probably works similarly)
//
// Lowest common denominator is "Microsoft" substring.
String prodId = cal.getPropVal(ICalTok.PRODID, null);
boolean fromOutlook = prodId != null && prodId.toLowerCase().contains("microsoft");
AccountAddressMatcher acctMatcher = new AccountAddressMatcher(getAccount());
List<Invite> components = Invite.createFromCalendar(getAccount(), null, cal, false);
for (Invite inv : components) {
String orgAddress;
if (inv.hasOrganizer()) {
ZOrganizer org = inv.getOrganizer();
orgAddress = org.getAddress();
} else {
ZimbraLog.calendar.warn("No ORGANIZER found in REPLY. Assuming current mailbox.");
orgAddress = getAccount().getName();
}
if (acctMatcher.matches(orgAddress)) {
// RECURRENCE-ID.
if (fromOutlook && !inv.isAllDayEvent() && inv.hasRecurId()) {
RecurId rid = inv.getRecurId();
if (rid.getDt() != null && rid.getDt().hasZeroTime()) {
CalendarItem calItem = getCalendarItemByUid(octxt, inv.getUid());
if (calItem != null) {
Invite seriesInv = calItem.getDefaultInviteOrNull();
if (seriesInv != null) {
ParsedDateTime seriesDtStart = seriesInv.getStartTime();
if (seriesDtStart != null) {
ParsedDateTime fixedDt = seriesDtStart.cloneWithNewDate(rid.getDt());
RecurId fixedRid = new RecurId(fixedDt, rid.getRange());
ZimbraLog.calendar.debug("Fixed up invalid RECURRENCE-ID with zero time; before=[%s], after=[%s]", rid, fixedRid);
inv.setRecurId(fixedRid);
}
}
}
}
}
processICalReply(octxt, inv, sender);
} else {
Account orgAccount = inv.getOrganizerAccount();
// Unknown organizer
if (orgAccount == null) {
ZimbraLog.calendar.warn("Unknown organizer " + orgAddress + " in REPLY");
continue;
}
if (Provisioning.onLocalServer(orgAccount)) {
// Run in the context of organizer's mailbox.
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(orgAccount);
OperationContext orgOctxt = new OperationContext(mbox);
mbox.processICalReply(orgOctxt, inv, sender);
} else {
// Organizer's mailbox is on a remote server.
String uri = AccountUtil.getSoapUri(orgAccount);
if (uri == null) {
ZimbraLog.calendar.warn("Unable to determine URI for organizer account %s", orgAddress);
continue;
}
try {
// TODO: Get the iCalendar data from the
// MIME part since we already have it.
String ical;
StringWriter sr = null;
try {
sr = new StringWriter();
inv.setMethod(ICalTok.REPLY.toString());
inv.newToICalendar(true).toICalendar(sr);
ical = sr.toString();
} finally {
if (sr != null) {
sr.close();
}
}
Options options = new Options();
AuthToken authToken = AuthToken.getCsrfUnsecuredAuthToken(getAuthToken(octxt));
options.setAuthToken(authToken.toZAuthToken());
options.setTargetAccount(orgAccount.getName());
options.setTargetAccountBy(AccountBy.name);
options.setUri(uri);
options.setNoSession(true);
ZMailbox zmbox = ZMailbox.getMailbox(options);
zmbox.iCalReply(ical, sender);
} catch (IOException e) {
throw ServiceException.FAILURE("Error while posting REPLY to organizer mailbox host", e);
}
}
}
}
}
use of com.zimbra.cs.mailbox.calendar.ZOrganizer in project zm-mailbox by Zimbra.
the class CacheToXML method encodeInstanceData.
// SOAP SearchResponse format for calendar items
//
// <appt> or <task>
// f - flags
// t - tags
// <or> - organizer
// a - address
// d - CN (display name)
// sentBy - sent-by address
// x-uid - UID
// uid - UID
// priority
// ptst - PARTSTAT
// fb - intended freebusy (appt only)
// fba - actual freebusy (appt only)
// transp - TRANSP (appt only)
// percentComplete - PERCENT-COMPLETE (task only)
// name - SUMMARY
// loc - LOCATION
// fr - fragment
// otherAtt - has attendees ("other" meaning other than organizer)
// isOrg - mailbox owner is organizer
// id - "<calItemId>-<invId>" (or is it just calItemId? can this be fully-qualified?)
// invId - invite id
// compNum - component number
// l - folder id (can be fully-qualified)
// status - STATUS
// class - CLASS
// dueDate - DUE (task only)
// dur - DURATION
// allDay - is this an all-day appt/task?
// recur - is this recurring?
// cat - CATEGORIES
// geo - GEO
// <inst>+ (attrs are given only when different from default value at <appt> level)
// fba
// ptst
// s - DTSTART
// tzo - timezone offset in millis (for all-day only)
// dur
// ex - instance is an exception
// // begin exception block (following attrs are possible only when ex=1)
// invId - "<calItemId>-<invId>" (notice this is different from invId at appt/task)
// compNum
// fr
// priority
// fb
// transp
// percentComplete
// name
// loc
// otherAtt
// isOrg
// status
// class
// allDay
// recur
// cat
// geo
// // end exception block
// // NOTE: Only invId is a new instance-level attribute.
// <alarmData> (next alarm to fire)
// nextAlarm - time at which the next alarm fires
// alarmInstStart - start time of the instance for the alarm
// name - SUMMARY of the instance
// loc - LOCATION of the instance
// invId - integer invite id of the instance
// compNum - component number of the instance
// <alarm> (details on the alarm itself)
// action - alarm ACTION type
// <trigger>
// <abs> (mutually exclusive with <rel>)
// d - absolute alarm trigger time
// <rel> (a duration, plus "related" attr)
// neg - value is negative
// w - weeks
// d - days
// h - hours
// m - minutes
// s - seconds
// related - duration is from start or end of instance
// <repeat> (a duration, plus "count" attr)
// neg - value is negative
// w - weeks
// d - days
// h - hours
// m - minutes
// s - seconds
// count - how many times to repeat after initial
// <desc>text</desc> - DESCRIPTION
// <attach> (attachment info)
// uri - URI of the external attachment
// ct - Content-Type of attachment
// or, <attach>base64-encoded attachment data</attach> (Q: why not ct as well?)
// <summary>email summary</summary> (action=email only)
// <at>+ (Attendees, for email recipients)
// a - address
// url - address (for backward compat)
// d - display name
// sentBy - sent-by
// dir
// lang
// cutype
// role
// ptst
// member
// delTo - DELEGATED-TO
// delFrom - DELEGATED-FROM
// // Q: Do we really need anything other than "a", and possibly "d" and "sentBy"?
//
private static void encodeInstanceData(Element parent, ItemIdFormatter ifmt, int calItemId, InstanceData instance, FullInstanceData defaultInstance, boolean isException, boolean isAppointment, boolean allowPrivateAccess, boolean legacyFormat) throws ServiceException {
if (isException && instance.getDtStart() != null) {
parent.addAttribute(MailConstants.A_CAL_START_TIME, instance.getDtStart().longValue());
}
if (instance.getDuration() != null) {
String attribute = !legacyFormat ? MailConstants.A_CAL_NEW_DURATION : MailConstants.A_CAL_DURATION;
parent.addAttribute(attribute, instance.getDuration().longValue());
}
// parent.addAttribute(MailConstants.A_TASK_DUE_DATE, instance.getDtEnd().longValue());
if (instance.getTZOffset() != null)
parent.addAttribute(MailConstants.A_CAL_TZ_OFFSET, instance.getTZOffset().longValue());
parent.addAttribute(MailConstants.A_CAL_PARTSTAT, instance.getPartStat());
if (isAppointment)
parent.addAttribute(MailConstants.A_APPT_FREEBUSY_ACTUAL, instance.getFreeBusyActual());
else
parent.addAttribute(MailConstants.A_TASK_PERCENT_COMPLETE, instance.getPercentComplete());
parent.addAttribute(MailConstants.A_CAL_RECURRENCE_ID_Z, instance.getRecurIdZ());
if (!(instance instanceof FullInstanceData))
return;
FullInstanceData fullInstance = (FullInstanceData) instance;
boolean showAll = allowPrivateAccess || fullInstance.isPublic(defaultInstance);
if (isException) {
parent.addAttribute(MailConstants.A_CAL_IS_EXCEPTION, true);
// HACK: ZWC insists on receiving recur=false on exceptions.
parent.addAttribute(MailConstants.A_CAL_RECUR, false);
}
// Organizer
ZOrganizer organizer = fullInstance.getOrganizer();
if (organizer != null) {
Element orgElt = parent.addUniqueElement(MailConstants.E_CAL_ORGANIZER);
String addr = IDNUtil.toUnicode(organizer.getAddress());
orgElt.addAttribute(MailConstants.A_ADDRESS, addr);
orgElt.addAttribute(MailConstants.A_URL, addr);
orgElt.addAttribute(MailConstants.A_DISPLAY, organizer.getCn());
orgElt.addAttribute(MailConstants.A_CAL_SENTBY, organizer.getSentBy());
}
if (showAll) {
parent.addAttribute(MailConstants.A_CAL_PRIORITY, fullInstance.getPriority());
parent.addAttribute(MailConstants.A_CAL_PARTSTAT, fullInstance.getPartStat());
if (isAppointment) {
parent.addAttribute(MailConstants.A_APPT_FREEBUSY, fullInstance.getFreeBusyIntended());
parent.addAttribute(MailConstants.A_APPT_TRANSPARENCY, fullInstance.getTransparency());
}
parent.addAttribute(MailConstants.A_NAME, fullInstance.getSummary());
parent.addAttribute(MailConstants.A_CAL_LOCATION, fullInstance.getLocation());
List<String> categories = fullInstance.getCategories();
if (categories != null) {
for (String cat : categories) {
parent.addElement(MailConstants.E_CAL_CATEGORY).setText(cat);
}
}
Geo geo = fullInstance.getGeo();
if (geo != null)
geo.toXml(parent);
// fragment has already been sanitized...
String fragment = fullInstance.getFragment();
if (fragment != null && !fragment.equals(""))
parent.addAttribute(MailConstants.E_FRAG, fragment, Element.Disposition.CONTENT);
Integer numAttendees = fullInstance.getNumAttendees();
if (numAttendees != null)
parent.addAttribute(MailConstants.A_CAL_OTHER_ATTENDEES, numAttendees.intValue() > 0);
if (fullInstance.hasAlarm() != null)
parent.addAttribute(MailConstants.A_CAL_ALARM, fullInstance.hasAlarm().booleanValue());
}
if (fullInstance.isOrganizer() != null)
parent.addAttribute(MailConstants.A_CAL_ISORG, fullInstance.isOrganizer().booleanValue());
if (!isException)
parent.addAttribute(MailConstants.A_ID, ifmt.formatItemId(calItemId));
parent.addAttribute(MailConstants.A_CAL_INV_ID, ifmt.formatItemId(calItemId, fullInstance.getInvId()));
parent.addAttribute(MailConstants.A_CAL_COMPONENT_NUM, fullInstance.getCompNum());
parent.addAttribute(MailConstants.A_CAL_STATUS, fullInstance.getStatus());
parent.addAttribute(MailConstants.A_CAL_CLASS, fullInstance.getClassProp());
if (fullInstance.isAllDay() != null)
parent.addAttribute(MailConstants.A_CAL_ALLDAY, fullInstance.isAllDay().booleanValue());
if (fullInstance.isDraft() != null)
parent.addAttribute(MailConstants.A_CAL_DRAFT, fullInstance.isDraft().booleanValue());
if (fullInstance.isNeverSent() != null)
parent.addAttribute(MailConstants.A_CAL_NEVER_SENT, fullInstance.isNeverSent().booleanValue());
}
Aggregations