Search in sources :

Example 11 with ICalTok

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;
}
Also used : InviteChanges(com.zimbra.cs.mailbox.calendar.InviteChanges) MimeMessage(javax.mail.internet.MimeMessage) Message(com.zimbra.cs.mailbox.Message) Element(com.zimbra.common.soap.Element) RecurId(com.zimbra.cs.mailbox.calendar.RecurId) ItemId(com.zimbra.cs.service.util.ItemId) ICalTok(com.zimbra.common.calendar.ZCalendar.ICalTok) CalendarItem(com.zimbra.cs.mailbox.CalendarItem) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) Mailbox(com.zimbra.cs.mailbox.Mailbox) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 12 with ICalTok

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());
}
Also used : ZOrganizer(com.zimbra.cs.mailbox.calendar.ZOrganizer) Period(com.zimbra.cs.mailbox.calendar.Period) ZParameter(com.zimbra.common.calendar.ZCalendar.ZParameter) ICalTok(com.zimbra.common.calendar.ZCalendar.ICalTok) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) ParseException(java.text.ParseException)

Example 13 with ICalTok

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;
        }
    }
}
Also used : ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) ZParameter(com.zimbra.common.calendar.ZCalendar.ZParameter) ICalTok(com.zimbra.common.calendar.ZCalendar.ICalTok)

Example 14 with ICalTok

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);
            }
        }
    }
}
Also used : ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) InternetAddress(javax.mail.internet.InternetAddress) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) Address(javax.mail.Address) InternetAddress(javax.mail.internet.InternetAddress) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) ZParameter(com.zimbra.common.calendar.ZCalendar.ZParameter) ICalTok(com.zimbra.common.calendar.ZCalendar.ICalTok)

Example 15 with ICalTok

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();
    }
}
Also used : Account(com.zimbra.cs.account.Account) Address(javax.mail.Address) InternetAddress(javax.mail.internet.InternetAddress) ArrayList(java.util.ArrayList) RecurId(com.zimbra.cs.mailbox.calendar.RecurId) ItemId(com.zimbra.cs.service.util.ItemId) ICalTok(com.zimbra.common.calendar.ZCalendar.ICalTok) ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) ZVCalendar(com.zimbra.common.calendar.ZCalendar.ZVCalendar) MimeMessage(javax.mail.internet.MimeMessage) FixedMimeMessage(com.zimbra.cs.mime.Mime.FixedMimeMessage) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Aggregations

ICalTok (com.zimbra.common.calendar.ZCalendar.ICalTok)19 ZComponent (com.zimbra.common.calendar.ZCalendar.ZComponent)9 ZProperty (com.zimbra.common.calendar.ZCalendar.ZProperty)9 ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)8 ZParameter (com.zimbra.common.calendar.ZCalendar.ZParameter)7 ServiceException (com.zimbra.common.service.ServiceException)6 ArrayList (java.util.ArrayList)6 ParseException (java.text.ParseException)5 ICalTimeZone (com.zimbra.common.calendar.ICalTimeZone)4 ParsedDuration (com.zimbra.common.calendar.ParsedDuration)4 Account (com.zimbra.cs.account.Account)4 Invite (com.zimbra.cs.mailbox.calendar.Invite)4 ItemId (com.zimbra.cs.service.util.ItemId)4 MimeMessage (javax.mail.internet.MimeMessage)4 ZVCalendar (com.zimbra.common.calendar.ZCalendar.ZVCalendar)3 NoSuchItemException (com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException)3 RecurId (com.zimbra.cs.mailbox.calendar.RecurId)3 IRecurrence (com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence)3 ZOrganizer (com.zimbra.cs.mailbox.calendar.ZOrganizer)3 AccountAddressMatcher (com.zimbra.cs.util.AccountUtil.AccountAddressMatcher)3