Search in sources :

Example 1 with ICalTimeZone

use of com.zimbra.common.calendar.ICalTimeZone in project zm-mailbox by Zimbra.

the class CalDavDataImport method putAppointment.

private String putAppointment(CalendarItem calItem, DataSourceItem dsItem) throws ServiceException, IOException, DavException {
    StringBuilder buf = new StringBuilder();
    ArrayList<String> recipients = new ArrayList<String>();
    buf.append("BEGIN:VCALENDAR\r\n");
    buf.append("VERSION:").append(ZCalendar.sIcalVersion).append("\r\n");
    buf.append("PRODID:").append(ZCalendar.sZimbraProdID).append("\r\n");
    Iterator<ICalTimeZone> iter = calItem.getTimeZoneMap().tzIterator();
    while (iter.hasNext()) {
        ICalTimeZone tz = iter.next();
        CharArrayWriter wr = new CharArrayWriter();
        tz.newToVTimeZone().toICalendar(wr, true);
        wr.flush();
        buf.append(wr.toCharArray());
        wr.close();
    }
    boolean appleICalExdateHack = LC.calendar_apple_ical_compatible_canceled_instances.booleanValue();
    ZComponent[] vcomps = Invite.toVComponents(calItem.getInvites(), true, false, appleICalExdateHack);
    if (vcomps != null) {
        CharArrayWriter wr = new CharArrayWriter();
        for (ZComponent vcomp : vcomps) {
            ZProperty organizer = vcomp.getProperty(ZCalendar.ICalTok.ORGANIZER);
            if (organizer != null)
                organizer.setValue(getUsername());
            vcomp.toICalendar(wr, true);
        }
        wr.flush();
        buf.append(wr.toCharArray());
        wr.close();
    }
    buf.append("END:VCALENDAR\r\n");
    String etag = dsItem.md.get(METADATA_KEY_ETAG, null);
    if (recipients.isEmpty())
        recipients = null;
    Appointment appt = new Appointment(dsItem.remoteId, etag, buf.toString(), recipients);
    return getClient().sendCalendarData(appt);
}
Also used : ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) Appointment(com.zimbra.cs.dav.client.CalDavClient.Appointment) ArrayList(java.util.ArrayList) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone) CharArrayWriter(java.io.CharArrayWriter)

Example 2 with ICalTimeZone

use of com.zimbra.common.calendar.ICalTimeZone in project zm-mailbox by Zimbra.

the class CalendarItem method decodeMetadata.

@Override
void decodeMetadata(Metadata meta) throws ServiceException {
    super.decodeMetadata(meta);
    mUid = Invite.fixupIfOutlookUid(meta.get(Metadata.FN_UID, null));
    mInvites = new ArrayList<Invite>();
    ICalTimeZone accountTZ = Util.getAccountTimeZone(getMailbox().getAccount());
    if (meta.containsKey(Metadata.FN_TZMAP)) {
        try {
            Set<String> tzids = new HashSet<String>();
            mTzMap = Util.decodeFromMetadata(meta.getMap(Metadata.FN_TZMAP), accountTZ);
            // appointment/task start and end
            mStartTime = meta.getLong(Metadata.FN_CALITEM_START, 0);
            mEndTime = meta.getLong(Metadata.FN_CALITEM_END, 0);
            // invite ID's
            long numComp = meta.getLong(Metadata.FN_NUM_COMPONENTS);
            for (int i = 0; i < numComp; i++) {
                Metadata md = meta.getMap(Metadata.FN_INV + i);
                Invite inv = Invite.decodeMetadata(getMailboxId(), md, this, accountTZ);
                mInvites.add(inv);
                tzids.addAll(inv.getReferencedTZIDs());
                mTzMap.add(inv.getTimeZoneMap());
            }
            Metadata metaRecur = meta.getMap(FN_CALITEM_RECURRENCE, true);
            if (metaRecur != null) {
                mRecurrence = Recurrence.decodeMetadata(metaRecur, mTzMap);
                if (mRecurrence != null) {
                    tzids.addAll(Recurrence.getReferencedTZIDs(mRecurrence));
                }
            }
            if (meta.containsKey(Metadata.FN_REPLY_LIST)) {
                mReplyList = ReplyList.decodeFromMetadata(meta.getMap(Metadata.FN_REPLY_LIST), mTzMap);
                // Get all TZIDs referenced by replies.
                for (ReplyInfo ri : mReplyList.mReplies) {
                    if (ri.mRecurId != null) {
                        ParsedDateTime dt = ri.mRecurId.getDt();
                        if (dt != null && dt.hasTime()) {
                            ICalTimeZone tz = dt.getTimeZone();
                            if (tz != null)
                                tzids.add(tz.getID());
                        }
                    }
                }
            } else {
                mReplyList = new ReplyList();
            }
            Metadata metaAlarmData = meta.getMap(Metadata.FN_ALARM_DATA, true);
            if (metaAlarmData != null)
                mAlarmData = AlarmData.decodeMetadata(metaAlarmData);
            // Reduce tzmap to minimal set of TZIDs referenced by invites, recurrence, and replies.
            mTzMap.reduceTo(tzids);
        } catch (ServiceException se) {
            if (ServiceException.INVALID_REQUEST.equals(se.getCode()) && this.getChangeDate() < new GregorianCalendar(2006, 0, 1).getTimeInMillis()) {
                //could have been metadata version 3, 4 or 5.
                //All of those versions have FN_TZMAP, but different format for other fields
                //these are edge cases that should only appear in dev/df/cf
                mStartTime = 0;
                mEndTime = 0;
            } else {
                throw se;
            }
        }
    } else {
        //version 2 or earlier
        mStartTime = 0;
        mEndTime = 0;
    }
}
Also used : GregorianCalendar(java.util.GregorianCalendar) ServiceException(com.zimbra.common.service.ServiceException) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) Invite(com.zimbra.cs.mailbox.calendar.Invite) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone) HashSet(java.util.HashSet)

Example 3 with ICalTimeZone

use of com.zimbra.common.calendar.ICalTimeZone in project zm-mailbox by Zimbra.

the class CancelCalendarItem 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);
    ItemId iid = new ItemId(request.getAttribute(MailConstants.A_ID), zsc);
    if (!iid.hasSubpart())
        throw ServiceException.INVALID_REQUEST("missing invId subpart: id should be specified as \"item-inv\"", null);
    int compNum = (int) request.getAttributeLong(MailConstants.E_INVITE_COMPONENT);
    CalendarItem calItem = mbox.getCalendarItemById(octxt, iid.getId());
    if (calItem == null)
        throw MailServiceException.NO_SUCH_CALITEM(iid.getId(), " for CancelCalendarItemRequest(" + iid + "," + compNum + ")");
    if (calItem.inTrash())
        throw ServiceException.INVALID_REQUEST("cannot cancel a calendar item under trash", null);
    // We probably don't want to bother with conflict check for a cancel request...
    Invite inv = calItem.getInvite(iid.getSubpartId(), compNum);
    if (inv == null)
        throw MailServiceException.INVITE_OUT_OF_DATE(iid.toString());
    MailSendQueue sendQueue = new MailSendQueue();
    try {
        Element recurElt = request.getOptionalElement(MailConstants.E_INSTANCE);
        if (recurElt != null) {
            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);
            }
            RecurId recurId = CalendarUtils.parseRecurId(recurElt, tzmap);
            // trace logging
            ZimbraLog.calendar.info("<CancelCalendarItem> id=%d, folderId=%d, subject=\"%s\", UID=%s, recurId=%s", calItem.getId(), calItem.getFolderId(), inv.isPublic() ? inv.getName() : "(private)", calItem.getUid(), recurId.getDtZ());
            Element msgElem = request.getOptionalElement(MailConstants.E_MSG);
            cancelInstance(zsc, octxt, msgElem, acct, mbox, calItem, inv, recurId, inv.getAttendees(), sendQueue);
        } else {
            // if recur is not set, then we're canceling the entire calendar item...
            // trace logging
            ZimbraLog.calendar.info("<CancelCalendarItem> id=%d, folderId=%d, subject=\"%s\", UID=%s", calItem.getId(), calItem.getFolderId(), inv.isPublic() ? inv.getName() : "(private)", calItem.getUid());
            Invite seriesInv = calItem.getDefaultInviteOrNull();
            if (seriesInv != null) {
                if (seriesInv.getMethod().equals(ICalTok.REQUEST.toString()) || seriesInv.getMethod().equals(ICalTok.PUBLISH.toString())) {
                    if (seriesInv.isOrganizer()) {
                        // Send cancel notice to attendees who were invited to exception instances only.
                        // These attendees need to be notified separately because they aren't included in the series
                        // cancel notice.
                        List<ZAttendee> atsSeries = seriesInv.getAttendees();
                        Invite[] invs = calItem.getInvites();
                        long now = octxt != null ? octxt.getTimestamp() : System.currentTimeMillis();
                        for (Invite exceptInv : invs) {
                            if (exceptInv != seriesInv) {
                                String mthd = exceptInv.getMethod();
                                if ((mthd.equals(ICalTok.REQUEST.toString()) || mthd.equals(ICalTok.PUBLISH.toString())) && inviteIsAfterTime(exceptInv, now)) {
                                    List<ZAttendee> atsExcept = exceptInv.getAttendees();
                                    // Find exception instance attendees who aren't series attendees.
                                    List<ZAttendee> ats = CalendarUtils.getRemovedAttendees(atsExcept, atsSeries, false, acct);
                                    if (!ats.isEmpty()) {
                                        // notify ats
                                        cancelInstance(zsc, octxt, null, acct, mbox, calItem, exceptInv, exceptInv.getRecurId(), ats, sendQueue);
                                    }
                                }
                            }
                        }
                    }
                    // Finally, cancel the series.
                    Element msgElem = request.getOptionalElement(MailConstants.E_MSG);
                    cancelInvite(zsc, octxt, msgElem, acct, mbox, calItem, seriesInv, sendQueue);
                }
                // disable change constraint checking since we've just successfully done a modify
                octxt = new OperationContext(octxt).unsetChangeConstraint();
            }
        }
    } finally {
        sendQueue.send();
    }
    Element response = getResponseElement(zsc);
    return response;
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) Account(com.zimbra.cs.account.Account) Element(com.zimbra.common.soap.Element) RecurId(com.zimbra.cs.mailbox.calendar.RecurId) ItemId(com.zimbra.cs.service.util.ItemId) CalendarItem(com.zimbra.cs.mailbox.CalendarItem) Mailbox(com.zimbra.cs.mailbox.Mailbox) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) ZAttendee(com.zimbra.cs.mailbox.calendar.ZAttendee) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) Invite(com.zimbra.cs.mailbox.calendar.Invite) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone)

Example 4 with ICalTimeZone

use of com.zimbra.common.calendar.ICalTimeZone in project zm-mailbox by Zimbra.

the class CalendarUtils method parseTimeZones.

static void parseTimeZones(Element parent, TimeZoneMap tzMap) throws ServiceException {
    assert (tzMap != null);
    for (Iterator iter = parent.elementIterator(MailConstants.E_CAL_TZ); iter.hasNext(); ) {
        Element tzElem = (Element) iter.next();
        ICalTimeZone tz = parseTzElement(tzElem);
        tzMap.add(tz);
    }
}
Also used : Element(com.zimbra.common.soap.Element) Iterator(java.util.Iterator) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone)

Example 5 with ICalTimeZone

use of com.zimbra.common.calendar.ICalTimeZone in project zm-mailbox by Zimbra.

the class Mailbox method writeICalendarForCalendarItems.

public void writeICalendarForCalendarItems(Writer writer, OperationContext octxt, Collection<CalendarItem> calItems, Folder f, boolean useOutlookCompatMode, boolean ignoreErrors, boolean needAppleICalHacks, boolean trimCalItemsList, boolean escapeHtmlTags, boolean includeAttaches) throws ServiceException {
    lock.lock();
    try {
        writer.write("BEGIN:VCALENDAR\r\n");
        if (f != null) {
            writer.write("X-WR-CALNAME:");
            writer.write(f.getName());
            writer.write("\r\n");
            writer.write("X-WR-CALID:");
            writer.write(new ItemId(f).toString());
            writer.write("\r\n");
        }
        ZProperty prop;
        prop = new ZProperty(ICalTok.PRODID, ZCalendar.sZimbraProdID);
        prop.toICalendar(writer, needAppleICalHacks);
        prop = new ZProperty(ICalTok.VERSION, ZCalendar.sIcalVersion);
        prop.toICalendar(writer, needAppleICalHacks);
        prop = new ZProperty(ICalTok.METHOD, ICalTok.PUBLISH.toString());
        prop.toICalendar(writer, needAppleICalHacks);
        // timezones
        ICalTimeZone localTz = Util.getAccountTimeZone(getAccount());
        TimeZoneMap tzmap = new TimeZoneMap(localTz);
        for (CalendarItem calItem : calItems) {
            tzmap.add(calItem.getTimeZoneMap());
        }
        // iterate the tzmap and add all the VTimeZone's
        for (Iterator<ICalTimeZone> iter = tzmap.tzIterator(); iter.hasNext(); ) {
            ICalTimeZone tz = iter.next();
            tz.newToVTimeZone().toICalendar(writer, needAppleICalHacks);
        }
        // help keep memory consumption low
        tzmap = null;
        // build all the event components and add them to the Calendar
        for (Iterator<CalendarItem> iter = calItems.iterator(); iter.hasNext(); ) {
            CalendarItem calItem = iter.next();
            boolean allowPrivateAccess = calItem.isPublic() || calItem.allowPrivateAccess(octxt.getAuthenticatedUser(), octxt.isUsingAdminPrivileges());
            if (trimCalItemsList) {
                // help keep memory consumption low
                iter.remove();
            }
            Invite[] invites = calItem.getInvites();
            if (invites != null && invites.length > 0) {
                boolean appleICalExdateHack = LC.calendar_apple_ical_compatible_canceled_instances.booleanValue();
                ZComponent[] comps = null;
                try {
                    comps = Invite.toVComponents(invites, allowPrivateAccess, useOutlookCompatMode, appleICalExdateHack, includeAttaches);
                } catch (ServiceException e) {
                    if (ignoreErrors) {
                        ZimbraLog.calendar.warn("Error retrieving iCalendar data for item %s: %s", calItem.getId(), e.getMessage(), e);
                    } else {
                        throw e;
                    }
                }
                if (comps != null) {
                    for (ZComponent comp : comps) {
                        comp.toICalendar(writer, needAppleICalHacks, escapeHtmlTags);
                    }
                }
            }
        }
        writer.write("END:VCALENDAR\r\n");
    } catch (IOException e) {
        throw ServiceException.FAILURE("Error writing iCalendar", e);
    } finally {
        lock.release();
    }
}
Also used : IOException(java.io.IOException) ItemId(com.zimbra.cs.service.util.ItemId) SetCalendarItem(com.zimbra.cs.redolog.op.SetCalendarItem) ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone) CreateInvite(com.zimbra.cs.redolog.op.CreateInvite) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Aggregations

ICalTimeZone (com.zimbra.common.calendar.ICalTimeZone)62 ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)17 ZComponent (com.zimbra.common.calendar.ZCalendar.ZComponent)14 TimeZoneMap (com.zimbra.common.calendar.TimeZoneMap)12 Element (com.zimbra.common.soap.Element)11 ZVCalendar (com.zimbra.common.calendar.ZCalendar.ZVCalendar)10 ServiceException (com.zimbra.common.service.ServiceException)10 ArrayList (java.util.ArrayList)10 ZProperty (com.zimbra.common.calendar.ZCalendar.ZProperty)8 Account (com.zimbra.cs.account.Account)8 Invite (com.zimbra.cs.mailbox.calendar.Invite)8 Mailbox (com.zimbra.cs.mailbox.Mailbox)7 IOException (java.io.IOException)7 Metadata (com.zimbra.cs.mailbox.Metadata)6 ItemId (com.zimbra.cs.service.util.ItemId)6 ParseException (java.text.ParseException)6 OperationContext (com.zimbra.cs.mailbox.OperationContext)5 RecurId (com.zimbra.cs.mailbox.calendar.RecurId)5 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)5 GregorianCalendar (java.util.GregorianCalendar)5