Search in sources :

Example 1 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 2 with RecurId

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

the class CalendarItem method requirePrivateCheck.

// If we're adding a private invite, we must make sure the authenticated user has permission to
// access private data.  If we're adding a public invite but the appointment currently has
// some private data, private access permission is not needed as long as the instance(s) being
// updated aren't currently private.
private boolean requirePrivateCheck(Invite newInvite) {
    if (!newInvite.isPublic()) {
        // adding a private invite
        return true;
    }
    if (!isPublic()) {
        RecurId rid = newInvite.getRecurId();
        // If canceling whole series, requester must have private access permission.
        if (rid == null && newInvite.isCancel())
            return true;
        Invite current = getInvite(rid);
        // If no matching recurrence-id was found, look at the current series.
        if (current == null && rid != null)
            current = getInvite((RecurId) null);
        if (current != null && !current.isPublic()) {
            // updating a currently private invite to public
            return true;
        } else {
            // no matching rid found, or current is public
            return false;
        }
    } else {
        // Both old and new are public.
        return false;
    }
}
Also used : RecurId(com.zimbra.cs.mailbox.calendar.RecurId) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 3 with RecurId

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

the class CalendarItem method organizerChangeCheck.

/**
 * Check to make sure the new invite doesn't change the organizer in a disallowed way.
 * @param newInvite
 * @return true if organizer change was detected, false if no change
 * @throws ServiceException
 */
private boolean organizerChangeCheck(Invite newInvite, boolean denyChange) throws ServiceException {
    Invite originalInvite = null;
    if (!newInvite.hasRecurId()) {
        // New invite is not for an exception.
        originalInvite = getDefaultInviteOrNull();
    } else {
        // New invite is for an exception.
        boolean found = false;
        RecurId newRid = newInvite.getRecurId();
        for (Invite inv : mInvites) {
            if (inv.hasRecurId() && newRid.equals(inv.getRecurId())) {
                originalInvite = inv;
                found = true;
                break;
            }
        }
        if (!found) {
            // If no invite with matching RECURRENCE-ID was found, use the default invite.
            originalInvite = getDefaultInviteOrNull();
        }
    }
    if (originalInvite == null) {
        // If no "default" invite was found, use the first one.
        if (mInvites.size() > 0)
            originalInvite = mInvites.get(0);
        if (originalInvite == null) {
            // checks in this method.
            return false;
        }
    }
    boolean updatingSameComponent = true;
    if (newInvite.hasRecurId()) {
        if (originalInvite.hasRecurId()) {
            updatingSameComponent = newInvite.getRecurId().equals(originalInvite.getRecurId());
        } else {
            updatingSameComponent = false;
        }
    }
    boolean changed = false;
    ZOrganizer originalOrganizer = originalInvite.getOrganizer();
    if (!originalInvite.isOrganizer()) {
        // This account WAS NOT the organizer.  Prevent organizer change.
        if (newInvite.hasOrganizer()) {
            String newOrgAddr = newInvite.getOrganizer().getAddress();
            if (originalOrganizer == null) {
                if (denyChange) {
                    newInvite.isTodo();
                    if (updatingSameComponent) {
                        throw BadOrganizerException.ADD_ORGANIZER_NOT_ALLOWED(newOrgAddr, calDesc(newInvite));
                    } else {
                        throw BadOrganizerException.ORGANIZER_INTRODUCED_FOR_EXCEPTION(newOrgAddr, calDesc(newInvite));
                    }
                } else {
                    changed = true;
                }
            } else {
                // Both old and new organizers are set.  They must be the same address.
                String origOrgAddr = originalOrganizer.getAddress();
                if (newOrgAddr == null || !CalendarUtils.belongToSameAccount(origOrgAddr, newOrgAddr)) {
                    if (denyChange) {
                        if (updatingSameComponent) {
                            throw BadOrganizerException.CHANGE_ORGANIZER_NOT_ALLOWED(origOrgAddr, newOrgAddr, calDesc(newInvite));
                        } else {
                            throw BadOrganizerException.DIFF_ORGANIZER_IN_COMPONENTS(origOrgAddr, newOrgAddr, calDesc(newInvite));
                        }
                    } else {
                        changed = true;
                    }
                }
            }
        } else if (originalOrganizer != null) {
            // No organizer for new newInvite but there is one in the original
            String origOrgAddr = originalOrganizer.getAddress();
            if (denyChange) {
                if (updatingSameComponent) {
                    throw BadOrganizerException.DEL_ORGANIZER_NOT_ALLOWED(origOrgAddr, calDesc(newInvite));
                } else {
                    throw BadOrganizerException.MISSING_ORGANIZER_IN_SINGLE_INSTANCE(origOrgAddr, calDesc(newInvite));
                }
            } else {
                changed = true;
            }
        }
    } else {
        // Still don't allow changing the organizer field to an arbitrary address.
        if (newInvite.hasOrganizer()) {
            if (!newInvite.isOrganizer()) {
                String newOrgAddr = newInvite.getOrganizer().getAddress();
                String origOrgAddr = (originalOrganizer != null) ? originalOrganizer.getAddress() : null;
                if (newOrgAddr.equalsIgnoreCase(origOrgAddr)) {
                    /* Speculative fix for Bug 83261.  Had gotten to this point with the same address but
                         * thought that wasn't the organizer for the new invite even though that organizer
                         * passed the test for originalInvite.  Ideally, should track down why the value was wrong
                         * but don't have a full repro scenario.
                         */
                    newInvite.setIsOrganizer(true);
                }
                if (!newInvite.isOrganizer()) {
                    if (denyChange) {
                        if (originalOrganizer != null) {
                            if (updatingSameComponent) {
                                throw BadOrganizerException.CHANGE_ORGANIZER_NOT_ALLOWED(origOrgAddr, newOrgAddr, calDesc(newInvite));
                            } else {
                                throw BadOrganizerException.DIFF_ORGANIZER_IN_COMPONENTS(origOrgAddr, newOrgAddr, calDesc(newInvite));
                            }
                        } else {
                            if (updatingSameComponent) {
                                throw BadOrganizerException.ADD_ORGANIZER_NOT_ALLOWED(newOrgAddr, calDesc(newInvite));
                            } else {
                                throw BadOrganizerException.ORGANIZER_INTRODUCED_FOR_EXCEPTION(newOrgAddr, calDesc(newInvite));
                            }
                        }
                    } else {
                        changed = true;
                    }
                }
            }
        }
    }
    if (changed) {
        String origOrg = originalOrganizer != null ? originalOrganizer.getAddress() : null;
        ZOrganizer newOrganizer = newInvite.getOrganizer();
        String newOrg = newOrganizer != null ? newOrganizer.getAddress() : null;
        boolean wasOrganizer = originalInvite.isOrganizer();
        boolean isOrganizer = newInvite.isOrganizer();
        ZimbraLog.calendar.info("Changed organizer: old=" + origOrg + ", new=" + newOrg + ", wasOrg=" + wasOrganizer + ", isOrg=" + isOrganizer + ", UID=\"" + newInvite.getUid() + "\", invId=" + newInvite.getMailItemId());
    }
    return changed;
}
Also used : ZOrganizer(com.zimbra.cs.mailbox.calendar.ZOrganizer) RecurId(com.zimbra.cs.mailbox.calendar.RecurId) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 4 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.setAccountId(orgAccount.getId());
                    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 5 with RecurId

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

the class CalendarUtils method parseReplyList.

public static List<ReplyInfo> parseReplyList(Element element, TimeZoneMap tzMap) throws ServiceException {
    List<ReplyInfo> list = new ArrayList<ReplyInfo>();
    for (Iterator<Element> iter = element.elementIterator(MailConstants.E_CAL_REPLY); iter.hasNext(); ) {
        Element riElem = iter.next();
        String addr = riElem.getAttribute(MailConstants.A_CAL_ATTENDEE);
        ZAttendee at = new ZAttendee(addr);
        String sentBy = riElem.getAttribute(MailConstants.A_CAL_SENTBY, null);
        if (sentBy != null)
            at.setSentBy(sentBy);
        String partStat = riElem.getAttribute(MailConstants.A_CAL_PARTSTAT, null);
        if (partStat != null)
            at.setPartStat(partStat);
        int seq = (int) riElem.getAttributeLong(MailConstants.A_SEQ);
        long dtStamp = riElem.getAttributeLong(MailConstants.A_DATE);
        RecurId recurId = RecurId.fromXml(riElem, tzMap);
        ReplyInfo ri = new ReplyInfo(at, seq, dtStamp, recurId);
        list.add(ri);
    }
    return list;
}
Also used : Element(com.zimbra.common.soap.Element) ZAttendee(com.zimbra.cs.mailbox.calendar.ZAttendee) ArrayList(java.util.ArrayList) RecurId(com.zimbra.cs.mailbox.calendar.RecurId) ReplyInfo(com.zimbra.cs.mailbox.CalendarItem.ReplyInfo)

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