Search in sources :

Example 6 with RecurId

use of com.zimbra.cs.mailbox.calendar.RecurId 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 7 with RecurId

use of com.zimbra.cs.mailbox.calendar.RecurId in project zm-mailbox by Zimbra.

the class CalendarUtils method parseRecurId.

static RecurId parseRecurId(Element e, TimeZoneMap tzmap) throws ServiceException {
    String range = e.getAttribute(MailConstants.A_CAL_RANGE, null);
    ParsedDateTime dt = parseDateTime(e, tzmap);
    return new RecurId(dt, range);
}
Also used : ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) RecurId(com.zimbra.cs.mailbox.calendar.RecurId)

Example 8 with RecurId

use of com.zimbra.cs.mailbox.calendar.RecurId 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);
                }
            }
        }
    }
}
Also used : Account(com.zimbra.cs.account.Account) ParsedMessageOptions(com.zimbra.cs.mime.ParsedMessageOptions) Options(com.zimbra.client.ZMailbox.Options) ZOrganizer(com.zimbra.cs.mailbox.calendar.ZOrganizer) RecurId(com.zimbra.cs.mailbox.calendar.RecurId) IOException(java.io.IOException) SetCalendarItem(com.zimbra.cs.redolog.op.SetCalendarItem) ZMailbox(com.zimbra.client.ZMailbox) RenameMailbox(com.zimbra.cs.redolog.op.RenameMailbox) DbMailbox(com.zimbra.cs.db.DbMailbox) CreateMailbox(com.zimbra.cs.redolog.op.CreateMailbox) ZMailbox(com.zimbra.client.ZMailbox) DeleteMailbox(com.zimbra.cs.redolog.op.DeleteMailbox) StringWriter(java.io.StringWriter) AccountAddressMatcher(com.zimbra.cs.util.AccountUtil.AccountAddressMatcher) AuthToken(com.zimbra.cs.account.AuthToken) ZAuthToken(com.zimbra.common.auth.ZAuthToken) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) CreateInvite(com.zimbra.cs.redolog.op.CreateInvite) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 9 with RecurId

use of com.zimbra.cs.mailbox.calendar.RecurId in project zm-mailbox by Zimbra.

the class ModifyInvitePartStat method redo.

@Override
public void redo() throws Exception {
    Mailbox mbox = MailboxManager.getInstance().getMailboxById(getMailboxId());
    CalendarItem calItem = mbox.getCalendarItemById(null, mCalItemId);
    RecurId recurId = null;
    if (mRecurIdDt != null)
        recurId = new RecurId(ParsedDateTime.parse(mRecurIdDt, calItem.getTimeZoneMap()), mRecurIdRange);
    mbox.modifyPartStat(getOperationContext(), mCalItemId, recurId, mCnStr, mAddressStr, mCUTypeStr, mRoleStr, mPartStatStr, mRsvp, mSeqNo, mDtStamp);
}
Also used : CalendarItem(com.zimbra.cs.mailbox.CalendarItem) Mailbox(com.zimbra.cs.mailbox.Mailbox) RecurId(com.zimbra.cs.mailbox.calendar.RecurId)

Example 10 with RecurId

use of com.zimbra.cs.mailbox.calendar.RecurId 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)

Aggregations

RecurId (com.zimbra.cs.mailbox.calendar.RecurId)23 Invite (com.zimbra.cs.mailbox.calendar.Invite)14 ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)11 Element (com.zimbra.common.soap.Element)11 Account (com.zimbra.cs.account.Account)10 CalendarItem (com.zimbra.cs.mailbox.CalendarItem)9 ZAttendee (com.zimbra.cs.mailbox.calendar.ZAttendee)9 ItemId (com.zimbra.cs.service.util.ItemId)9 Mailbox (com.zimbra.cs.mailbox.Mailbox)8 ZOrganizer (com.zimbra.cs.mailbox.calendar.ZOrganizer)8 ArrayList (java.util.ArrayList)7 MimeMessage (javax.mail.internet.MimeMessage)6 ICalTimeZone (com.zimbra.common.calendar.ICalTimeZone)5 ParsedDuration (com.zimbra.common.calendar.ParsedDuration)5 OperationContext (com.zimbra.cs.mailbox.OperationContext)5 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)5 TimeZoneMap (com.zimbra.common.calendar.TimeZoneMap)4 CalendarResource (com.zimbra.cs.account.CalendarResource)4 IRecurrence (com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence)4 Geo (com.zimbra.common.calendar.Geo)3