Search in sources :

Example 1 with ZOrganizer

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

the class AutoScheduler method getAutoScheduler.

public static AutoScheduler getAutoScheduler(Mailbox userMailbox, Mailbox calendarMailbox, Invite[] origInvites, int calendarMailItemId, int flags, String[] tags, SetCalendarItemData scidDefault, SetCalendarItemData[] scidExceptions, List<ReplyInfo> replies, DavContext context) {
    if (!DavResource.isCalendarAutoSchedulingEnabled()) {
        return null;
    }
    if (calendarMailbox == null) {
        // We don't know who to act as
        return null;
    }
    ZOrganizer organizer = null;
    Account organizerAcct = null;
    try {
        if (scidDefault == null || scidDefault.invite == null) {
            if (isEmpty(origInvites)) {
                // No new or old invites!
                return null;
            }
            organizer = origInvites[0].getOrganizer();
            organizerAcct = origInvites[0].getOrganizerAccount();
        } else {
            organizer = scidDefault.invite.getOrganizer();
            organizerAcct = scidDefault.invite.getOrganizerAccount();
        }
        if (organizer == null) {
            // no organizer means no scheduling
            return null;
        }
        // TODO:  Does the auth user have scheduling capability for the calendar
        if (calendarMailbox.getAccount().sameAccount(organizerAcct)) {
            return new OrganizerAutoScheduler(userMailbox, calendarMailbox, origInvites, calendarMailItemId, flags, tags, scidDefault, scidExceptions, replies, context);
        } else {
            return new AttendeeAutoScheduler(userMailbox, calendarMailbox, origInvites, calendarMailItemId, flags, tags, scidDefault, scidExceptions, replies, context);
        }
    } catch (ServiceException e) {
        ZimbraLog.dav.debug("Hit this whilst getting AutoScheduler", e);
    }
    return null;
}
Also used : Account(com.zimbra.cs.account.Account) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) ZOrganizer(com.zimbra.cs.mailbox.calendar.ZOrganizer)

Example 2 with ZOrganizer

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

the class ScheduleOutbox method adjustOrganizer.

/**
     * For Vanilla CalDAV access where Apple style delegation has not been enabled, attempts by the delegate
     * to use a shared calendar acting as themselves are translated to appear as if acting as a delegate,
     * otherwise the experience can be very poor.
     * @throws ServiceException
     */
private void adjustOrganizer(DavContext ctxt, ZCalendar.ZVCalendar cal, ZComponent req, DelegationInfo delegationInfo) throws ServiceException {
    // BusyCal 2.5.3 seems to post with the wrong organizer even if ical delegation is switched on - even though
    // it uses the right ORGANIZER in the calendar entry.
    // if (ctxt.useIcalDelegation()) { return; }
    Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(ctxt.getAuthAccount());
    String uid = req.getPropVal(ICalTok.UID, null);
    CalendarItem matchingCalendarEntry = mbox.getCalendarItemByUid(ctxt.getOperationContext(), uid);
    if (matchingCalendarEntry == null) {
        List<com.zimbra.cs.mailbox.Mountpoint> sharedCalendars = mbox.getCalendarMountpoints(ctxt.getOperationContext(), SortBy.NONE);
        if (sharedCalendars == null) {
            // Can't work out anything useful
            return;
        }
        Set<Account> accts = Sets.newHashSet();
        for (com.zimbra.cs.mailbox.Mountpoint sharedCalendar : sharedCalendars) {
            accts.add(Provisioning.getInstance().get(AccountBy.id, sharedCalendar.getOwnerId()));
        }
        for (Account acct : accts) {
            Mailbox sbox = MailboxManager.getInstance().getMailboxByAccount(acct);
            matchingCalendarEntry = sbox.getCalendarItemByUid(ctxt.getOperationContext(), uid);
            if (matchingCalendarEntry != null) {
                break;
            }
        }
    }
    if (matchingCalendarEntry == null) {
        return;
    }
    Invite[] invites = matchingCalendarEntry.getInvites();
    if (invites == null) {
        return;
    }
    for (Invite inv : invites) {
        ZOrganizer org = inv.getOrganizer();
        if (org != null) {
            delegationInfo.setOwner(org.getAddress());
            if (Strings.isNullOrEmpty(org.getCn())) {
                Account ownerAcct = Provisioning.getInstance().get(AccountBy.name, org.getAddress());
                if (!Strings.isNullOrEmpty(ownerAcct.getDisplayName())) {
                    delegationInfo.setOwnerCn(ownerAcct.getDisplayName());
                }
            } else {
                delegationInfo.setOwnerCn(org.getCn());
            }
            break;
        }
    }
    if (delegationInfo.getOwner() == null) {
        return;
    }
    AccountAddressMatcher acctMatcher = new AccountAddressMatcher(ctxt.getAuthAccount());
    boolean originatorIsCalEntryOrganizer = acctMatcher.matches(delegationInfo.getOwnerEmail());
    if (originatorIsCalEntryOrganizer) {
        return;
    }
    for (ZComponent component : cal.getComponents()) {
        ZProperty organizerProp = component.getProperty(ICalTok.ORGANIZER);
        if (organizerProp != null) {
            organizerProp.setValue(delegationInfo.getOwner());
            ZParameter cn = organizerProp.getParameter(ICalTok.CN);
            if (cn == null) {
                organizerProp.addParameter(new ZParameter(ICalTok.CN, delegationInfo.getOwnerCn()));
            } else {
                cn.setValue(delegationInfo.getOwnerCn());
            }
            ZParameter sentBy = organizerProp.getParameter(ICalTok.SENT_BY);
            if (sentBy == null) {
                organizerProp.addParameter(new ZParameter(ICalTok.SENT_BY, delegationInfo.getOriginator()));
            } else {
                sentBy.setValue(delegationInfo.getOriginator());
            }
        }
    }
}
Also used : Account(com.zimbra.cs.account.Account) ZOrganizer(com.zimbra.cs.mailbox.calendar.ZOrganizer) ZParameter(com.zimbra.common.calendar.ZCalendar.ZParameter) CalendarItem(com.zimbra.cs.mailbox.CalendarItem) ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) Mailbox(com.zimbra.cs.mailbox.Mailbox) AccountAddressMatcher(com.zimbra.cs.util.AccountUtil.AccountAddressMatcher) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 3 with ZOrganizer

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

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

the class CalendarItem method create.

static CalendarItem create(int id, Folder folder, int flags, Tag.NormalizedTags ntags, String uid, ParsedMessage pm, Invite firstInvite, long nextAlarm, CustomMetadata custom) throws ServiceException {
    firstInvite.sanitize(false);
    if (!folder.canAccess(ACL.RIGHT_INSERT)) {
        throw ServiceException.PERM_DENIED("you do not have the required rights on the folder");
    }
    if (!firstInvite.isPublic() && !folder.canAccess(ACL.RIGHT_PRIVATE)) {
        throw ServiceException.PERM_DENIED("you do not have permission to create private calendar item in this folder");
    }
    Mailbox mbox = folder.getMailbox();
    if (pm != null && pm.hasAttachments()) {
        firstInvite.setHasAttachment(true);
        flags |= Flag.BITMASK_ATTACHED;
    } else {
        firstInvite.setHasAttachment(false);
        flags &= ~Flag.BITMASK_ATTACHED;
    }
    if (firstInvite.isDraft()) {
        flags |= Flag.BITMASK_DRAFT;
    } else {
        flags &= ~Flag.BITMASK_DRAFT;
    }
    if (firstInvite.isHighPriority()) {
        flags |= Flag.BITMASK_HIGH_PRIORITY;
    } else {
        flags &= ~Flag.BITMASK_HIGH_PRIORITY;
    }
    if (firstInvite.isLowPriority()) {
        flags |= Flag.BITMASK_LOW_PRIORITY;
    } else {
        flags &= ~Flag.BITMASK_LOW_PRIORITY;
    }
    MailItem.Type type = firstInvite.isEvent() ? Type.APPOINTMENT : Type.TASK;
    String sender = null;
    ZOrganizer org = firstInvite.getOrganizer();
    if (org != null) {
        sender = org.getIndexString();
    }
    sender = Strings.nullToEmpty(sender);
    String subject = Strings.nullToEmpty(firstInvite.getName());
    List<Invite> invites = new ArrayList<Invite>();
    invites.add(firstInvite);
    Recurrence.IRecurrence recur = firstInvite.getRecurrence();
    long startTime, endTime;
    if (recur != null) {
        ParsedDateTime dtStart = recur.getStartTime();
        startTime = dtStart != null ? dtStart.getUtcTime() : 0;
        ParsedDateTime dtEnd = recur.getEndTime();
        endTime = dtEnd != null ? dtEnd.getUtcTime() : 0;
    } else {
        ParsedDateTime dtStart = firstInvite.getStartTime();
        startTime = dtStart != null ? dtStart.getUtcTime() : 0;
        ParsedDateTime dtEnd = firstInvite.getEffectiveEndTime();
        endTime = dtEnd != null ? dtEnd.getUtcTime() : startTime;
    }
    Account account = mbox.getAccount();
    firstInvite.updateMyPartStat(account, firstInvite.getPartStat());
    UnderlyingData data = new UnderlyingData();
    data.id = id;
    data.type = type.toByte();
    data.folderId = folder.getId();
    if (!folder.inSpam() || mbox.getAccount().getBooleanAttr(Provisioning.A_zimbraJunkMessagesIndexingEnabled, false)) {
        data.indexId = IndexStatus.DEFERRED.id();
    }
    data.imapId = id;
    data.date = mbox.getOperationTimestamp();
    data.setFlags(flags & (Flag.FLAGS_CALITEM | Flag.FLAGS_GENERIC));
    data.setTags(ntags);
    data.setSubject(subject);
    data.metadata = encodeMetadata(DEFAULT_COLOR_RGB, 1, 1, custom, uid, startTime, endTime, recur, invites, firstInvite.getTimeZoneMap(), new ReplyList(), null);
    data.contentChanged(mbox, false);
    if (!firstInvite.hasRecurId()) {
        ZimbraLog.calendar.info("Adding CalendarItem: id=%d, Message-ID=\"%s\", folderId=%d, subject=\"%s\", UID=%s", data.id, pm != null ? pm.getMessageID() : "(none)", folder.getId(), firstInvite.isPublic() ? firstInvite.getName() : "(private)", firstInvite.getUid());
    } else {
        ZimbraLog.calendar.info("Adding CalendarItem: id=%d, Message-ID=\"%s\", folderId=%d, subject=\"%s\", UID=%s, recurId=%s", data.id, pm != null ? pm.getMessageID() : "(none)", folder.getId(), firstInvite.isPublic() ? firstInvite.getName() : "(private)", firstInvite.getUid(), firstInvite.getRecurId().getDtZ());
    }
    new DbMailItem(mbox).setSender(sender).create(data);
    CalendarItem item = type == Type.APPOINTMENT ? new Appointment(mbox, data) : new Task(mbox, data);
    Invite defInvite = item.getDefaultInviteOrNull();
    if (defInvite != null) {
        Collection<Instance> instances = item.expandInstances(CalendarUtils.MICROSOFT_EPOC_START_MS_SINCE_EPOC, Long.MAX_VALUE, false);
        if (instances.isEmpty()) {
            ZimbraLog.calendar.info("CalendarItem has effectively zero instances: id=%d, folderId=%d, subject=\"%s\", UID=%s ", data.id, folder.getId(), firstInvite.isPublic() ? firstInvite.getName() : "(private)", firstInvite.getUid());
            item.delete();
            throw ServiceException.FORBIDDEN("Recurring series has effectively zero instances");
        }
    }
    // If we're creating an invite during email delivery, always default to NEEDS_ACTION state.
    // If not email delivery, we assume the requesting client knows what it's doing and has set the
    // correct partstat in the invite.
    String defaultPartStat;
    if (mbox.getOperationContext() == null) {
        // octxt == null implies we're in email delivery.  (There needs to be better way to determine this...)
        defaultPartStat = IcalXmlStrMap.PARTSTAT_NEEDS_ACTION;
    } else {
        defaultPartStat = firstInvite.getPartStat();
    }
    item.processPartStat(firstInvite, pm != null ? pm.getMimeMessage() : null, true, defaultPartStat);
    item.finishCreation(null);
    folder.updateHighestMODSEQ();
    if (pm != null) {
        item.createBlob(pm, firstInvite);
    }
    item.mEndTime = item.recomputeRecurrenceEndTime(item.mEndTime);
    if (firstInvite.hasAlarm()) {
        item.recomputeNextAlarm(nextAlarm, false, false);
        item.saveMetadata();
        AlarmData alarmData = item.getAlarmData();
        if (alarmData != null) {
            long newNextAlarm = alarmData.getNextAtBase();
            if (newNextAlarm > 0 && newNextAlarm < item.mStartTime) {
                item.mStartTime = newNextAlarm;
            }
        }
    }
    DbMailItem.addToCalendarItemTable(item);
    Callback cb = getCallback();
    if (cb != null) {
        cb.created(item);
    }
    return item;
}
Also used : IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) Recurrence(com.zimbra.cs.mailbox.calendar.Recurrence) Account(com.zimbra.cs.account.Account) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) DbMailItem(com.zimbra.cs.db.DbMailItem) ZOrganizer(com.zimbra.cs.mailbox.calendar.ZOrganizer) ArrayList(java.util.ArrayList) DbMailItem(com.zimbra.cs.db.DbMailItem) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 5 with ZOrganizer

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

the class CalendarItem method getSender.

@Override
public String getSender() {
    String sender = null;
    Invite firstInvite = getDefaultInviteOrNull();
    if (firstInvite != null) {
        ZOrganizer org = firstInvite.getOrganizer();
        if (org != null)
            sender = org.getIndexString();
    }
    return Strings.nullToEmpty(sender);
}
Also used : ZOrganizer(com.zimbra.cs.mailbox.calendar.ZOrganizer) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Aggregations

ZOrganizer (com.zimbra.cs.mailbox.calendar.ZOrganizer)26 Invite (com.zimbra.cs.mailbox.calendar.Invite)16 Account (com.zimbra.cs.account.Account)15 ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)10 RecurId (com.zimbra.cs.mailbox.calendar.RecurId)8 ZProperty (com.zimbra.common.calendar.ZCalendar.ZProperty)7 Element (com.zimbra.common.soap.Element)7 ZAttendee (com.zimbra.cs.mailbox.calendar.ZAttendee)7 IOException (java.io.IOException)6 ParsedDuration (com.zimbra.common.calendar.ParsedDuration)5 AccountAddressMatcher (com.zimbra.cs.util.AccountUtil.AccountAddressMatcher)5 Date (java.util.Date)5 Geo (com.zimbra.common.calendar.Geo)4 ServiceException (com.zimbra.common.service.ServiceException)4 Mailbox (com.zimbra.cs.mailbox.Mailbox)4 IRecurrence (com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence)4 ItemId (com.zimbra.cs.service.util.ItemId)4 ArrayList (java.util.ArrayList)4 MimeMessage (javax.mail.internet.MimeMessage)4 TimeZoneMap (com.zimbra.common.calendar.TimeZoneMap)3