Search in sources :

Example 26 with TimeZoneMap

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

the class WorkingHours method getWorkingHours.

public static FreeBusy getWorkingHours(Account authAcct, boolean asAdmin, Account account, String name, long start, long end) throws ServiceException {
    // If free/busy viewing is blocked, so is viewing working hours.
    AccessManager accessMgr = AccessManager.getInstance();
    boolean accountAceAllowed = accessMgr.canDo(authAcct, account, User.R_viewFreeBusy, asAdmin);
    if (!accountAceAllowed)
        return FreeBusy.nodataFreeBusy(account.getName(), start, end);
    // Get the working hours preference and parse it.
    String workingHoursPref = account.getPrefCalendarWorkingHours();
    HoursByDay workingHoursByDay = new HoursByDay(workingHoursPref);
    // Build a recurrence rule for each day of the week and expand over the time range.
    IntervalList intervals = new IntervalList(start, end);
    ICalTimeZone tz = Util.getAccountTimeZone(account);
    TimeZoneMap tzmap = new TimeZoneMap(tz);
    StartSpec startSpec = new StartSpec(start, tz);
    for (int day = 1; day <= 7; ++day) {
        TimeRange timeRange = workingHoursByDay.getHoursForDay(day);
        if (timeRange.enabled) {
            IRecurrence rrule = getRecurrenceForDay(day, startSpec, timeRange, tz, tzmap);
            List<Instance> instances = rrule.expandInstances(0, start, end);
            for (Instance inst : instances) {
                Interval ival = new Interval(inst.getStart(), inst.getEnd(), IcalXmlStrMap.FBTYPE_BUSY_UNAVAILABLE);
                intervals.addInterval(ival);
            }
        }
    }
    // hours are shown as out-of-office.
    for (Iterator<Interval> iter = intervals.iterator(); iter.hasNext(); ) {
        Interval interval = iter.next();
        String status = interval.getStatus();
        interval.setStatus(invertStatus(status));
    }
    return new FreeBusy(name, intervals, start, end);
}
Also used : AccessManager(com.zimbra.cs.account.AccessManager) Instance(com.zimbra.cs.mailbox.CalendarItem.Instance) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) IntervalList(com.zimbra.cs.fb.FreeBusy.IntervalList) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone) Interval(com.zimbra.cs.fb.FreeBusy.Interval)

Example 27 with TimeZoneMap

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

the class IcsImportParseHandler method startCalendar.

@Override
public void startCalendar() throws ParserException {
    mComponents.clear();
    mInZCalendar = true;
    mCurCal = new ZVCalendar();
    mMethod = ICalTok.PUBLISH.toString();
    mTimeZoneMap = new TimeZoneMap(Util.getAccountTimeZone(mAccount));
}
Also used : ZVCalendar(com.zimbra.common.calendar.ZCalendar.ZVCalendar) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap)

Example 28 with TimeZoneMap

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

the class Invite method decodeMetadata.

/**
     * This API is public for RedoLogging to call into it -- you probably don't want to call it from
     * anywhere else!
     *
     * @param mailboxId
     * @param meta
     * @param calItem
     * @param accountTZ
     * @return
     * @throws ServiceException
     */
public static Invite decodeMetadata(int mailboxId, Metadata meta, CalendarItem calItem, ICalTimeZone accountTZ) throws ServiceException {
    byte btype = (byte) meta.getLong(FN_ITEMTYPE, -1);
    MailItem.Type type = btype >= 0 ? MailItem.Type.of(btype) : MailItem.Type.APPOINTMENT;
    String uid = meta.get(FN_UID, null);
    int mailItemId = (int) meta.getLong(FN_INVMSGID);
    int componentNum = (int) meta.getLong(FN_COMPNUM);
    String classProp = meta.get(FN_CLASS, IcalXmlStrMap.CLASS_PUBLIC);
    boolean classPropSetByMe = meta.getBool(FN_CLASS_SETBYME, false);
    String status = meta.get(FN_STATUS, IcalXmlStrMap.STATUS_CONFIRMED);
    String freebusy = meta.get(FN_APPT_FREEBUSY, null);
    String transp = meta.get(FN_TRANSP, IcalXmlStrMap.TRANSP_OPAQUE);
    boolean sentByMe = meta.getBool(FN_SENTBYME);
    String fragment = meta.get(FN_FRAGMENT, "");
    // default to false for backward compat
    boolean descInMeta = meta.getBool(FN_DESC_IN_META, false);
    String desc = descInMeta ? meta.get(FN_DESC, null) : null;
    String descHtml = descInMeta ? meta.get(FN_DESC_HTML, null) : null;
    long completed = meta.getLong(FN_COMPLETED, 0);
    ParsedDateTime dtStart = null;
    ParsedDateTime dtEnd = null;
    ParsedDuration duration = null;
    RecurId recurrenceId = null;
    TimeZoneMap tzMap = Util.decodeFromMetadata(meta.getMap(FN_TZMAP), accountTZ);
    Metadata metaRecur = meta.getMap(FN_RECURRENCE, true);
    Recurrence.IRecurrence recurrence = null;
    if (metaRecur != null) {
        recurrence = Recurrence.decodeMetadata(metaRecur, tzMap);
    }
    String methodStr = meta.get(FN_METHOD, ICalTok.PUBLISH.toString());
    if (ICalTok.CANCEL.toString().equals(methodStr))
        status = IcalXmlStrMap.STATUS_CANCELLED;
    int flags = (int) meta.getLong(FN_APPT_FLAGS, 0);
    try {
        // DtStart
        dtStart = ParsedDateTime.parse(meta.get(FN_START, null), tzMap);
        // DtEnd
        dtEnd = ParsedDateTime.parse(meta.get(FN_END, null), tzMap);
        if ((flags & APPT_FLAG_ALLDAY) != 0) {
            // Fixup historic data with incorrect all-day start/end format.
            if (dtStart != null)
                dtStart.forceDateOnly();
            if (dtEnd != null)
                dtEnd.forceDateOnly();
        }
        // Duration
        duration = ParsedDuration.parse(meta.get(FN_DURATION, null));
        if (meta.containsKey(FN_RECUR_ID)) {
            Metadata rdata = meta.getMap(FN_RECUR_ID);
            recurrenceId = RecurId.decodeMetadata(rdata, tzMap);
        }
    } catch (ParseException e) {
        throw ServiceException.FAILURE(String.format("Error parsing metadata for invite %s-%s in calItem %s", mailItemId, componentNum, (calItem != null) ? Integer.toString(calItem.getId()) : "(null)"), e);
    }
    String name = meta.get(FN_NAME, "");
    String loc = meta.get(FN_LOCATION, null);
    // For existing invites with no partstat, default to ACCEPTED status.
    String partStat = meta.get(FN_PARTSTAT, IcalXmlStrMap.PARTSTAT_ACCEPTED);
    // For existing invites with no RSVP, default to true.
    boolean rsvp = meta.getBool(FN_RSVP, true);
    long dtstamp = meta.getLong(FN_DTSTAMP, 0);
    long lastModified = meta.getLong(FN_LAST_MODIFIED, 0);
    int seqno = (int) meta.getLong(FN_SEQ_NO, 0);
    int lastFullSeqno = (int) meta.getLong(FN_LAST_FULL_SEQ_NO, seqno);
    ZOrganizer org = null;
    try {
        Metadata metaOrg = meta.getMap(FN_ORGANIZER, true);
        org = metaOrg != null ? new ZOrganizer(metaOrg) : null;
    } catch (ServiceException e) {
        sLog.warn("Problem decoding organizer for calItem %s invite %s-%s", (calItem != null) ? Integer.toString(calItem.getId()) : "(null)", mailItemId, componentNum);
    }
    long numAts = meta.getLong(FN_NUM_ATTENDEES, 0);
    ArrayList<ZAttendee> attendees = new ArrayList<ZAttendee>((int) numAts);
    for (int i = 0; i < numAts; i++) {
        try {
            Metadata metaAttendee = meta.getMap(FN_ATTENDEE + i, true);
            if (metaAttendee != null)
                attendees.add(new ZAttendee(metaAttendee));
        } catch (ServiceException e) {
            ZimbraLog.calendar.warn("Problem decoding attendee %s for calendar item %s invite %s-%s", i, (calItem != null) ? Integer.toString(calItem.getId()) : "(null)", mailItemId, componentNum);
        }
    }
    boolean isOrganizer = false;
    if (meta.containsKey(FN_IS_ORGANIZER)) {
        isOrganizer = meta.getBool(FN_IS_ORGANIZER);
    } else {
        // backward compat for invites created before FN_IS_ORGANIZER was introduced
        if (org != null) {
            String orgAddr = org.getAddress();
            Account account = MailboxManager.getInstance().getMailboxById(mailboxId).getAccount();
            AccountAddressMatcher acctMatcher = new AccountAddressMatcher(account);
            isOrganizer = acctMatcher.matches(orgAddr);
        } else {
            // If there are other attendees, it's an Outlook POP/IMAP bug.  If not,
            // it's a properly formatted single-user event.  See isOrganizer()
            // method for more info.
            isOrganizer = numAts < 1;
        }
    }
    String priority = meta.get(FN_PRIORITY, null);
    String pctComplete = meta.get(FN_PCT_COMPLETE, null);
    List<String> comments = null;
    int numComm = (int) meta.getLong(FN_NUM_COMMENTS, 0);
    if (numComm > 0) {
        comments = new ArrayList<String>(numComm);
        for (int i = 0; i < numComm; i++) {
            String comm = meta.get(FN_COMMENT + i, null);
            if (comm != null)
                comments.add(comm);
        }
    }
    List<String> contacts = null;
    int numContacts = (int) meta.getLong(FN_NUM_CONTACTS, 0);
    if (numContacts > 0) {
        contacts = new ArrayList<String>(numContacts);
        for (int i = 0; i < numContacts; i++) {
            String contact = meta.get(FN_CONTACT + i, null);
            if (contact != null)
                contacts.add(contact);
        }
    }
    List<String> categories = null;
    int numCat = (int) meta.getLong(FN_NUM_CATEGORIES, 0);
    if (numCat > 0) {
        categories = new ArrayList<String>(numCat);
        for (int i = 0; i < numCat; i++) {
            String cat = meta.get(FN_CATEGORY + i, null);
            if (cat != null)
                categories.add(cat);
        }
    }
    Geo geo = null;
    Metadata metaGeo = meta.getMap(FN_GEO, true);
    if (metaGeo != null)
        geo = Util.decodeGeoFromMetadata(metaGeo);
    String url = meta.get(FN_URL, null);
    Invite invite = new Invite(type, methodStr, tzMap, calItem, uid, status, priority, pctComplete, completed, freebusy, transp, classProp, dtStart, dtEnd, duration, recurrence, isOrganizer, org, attendees, name, loc, flags, partStat, rsvp, recurrenceId, dtstamp, lastModified, seqno, lastFullSeqno, mailboxId, mailItemId, componentNum, sentByMe, desc, descHtml, fragment, comments, categories, contacts, geo, url);
    // a little hacky, but necessary
    invite.mDescInMeta = descInMeta;
    invite.setClassPropSetByMe(classPropSetByMe);
    long numAlarms = meta.getLong(FN_NUM_ALARMS, 0);
    for (int i = 0; i < numAlarms; i++) {
        try {
            Metadata metaAlarm = meta.getMap(FN_ALARM + i, true);
            if (metaAlarm != null) {
                Alarm alarm = Alarm.decodeMetadata(metaAlarm);
                if (alarm != null)
                    invite.addAlarm(alarm);
            }
        } catch (ServiceException e) {
            ZimbraLog.calendar.warn("Problem decoding alarm %s for calendar item %s invite %s-%s", i, (calItem != null) ? Integer.toString(calItem.getId()) : "(null)", mailItemId, componentNum, e);
        }
    }
    List<ZProperty> xprops = Util.decodeXPropsFromMetadata(meta);
    if (xprops != null) {
        for (ZProperty xprop : xprops) {
            boolean isHtmlDesc = false;
            if (ICalTok.X_ALT_DESC.equals(xprop.getToken())) {
                // Backward compat.  We used to save X-ALT-DESC property as an x-prop.  Now we use it
                // for HTML description, when FMTTYPE=text/html.
                ZParameter fmttype = xprop.getParameter(ICalTok.FMTTYPE);
                if (fmttype != null && MimeConstants.CT_TEXT_HTML.equalsIgnoreCase(fmttype.getValue())) {
                    isHtmlDesc = true;
                    invite.mDescHtml = xprop.getValue();
                }
            }
            if (!isHtmlDesc)
                invite.addXProp(xprop);
        }
    }
    invite.setDontIndexMimeMessage(meta.getBool(FN_DONT_INDEX_MM, false));
    boolean localOnly = meta.getBool(FN_LOCAL_ONLY, false);
    invite.setLocalOnly(localOnly);
    invite.sanitize(false);
    return invite;
}
Also used : IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) Account(com.zimbra.cs.account.Account) ParsedDuration(com.zimbra.common.calendar.ParsedDuration) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) Metadata(com.zimbra.cs.mailbox.Metadata) ArrayList(java.util.ArrayList) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) ZParameter(com.zimbra.common.calendar.ZCalendar.ZParameter) Geo(com.zimbra.common.calendar.Geo) MailItem(com.zimbra.cs.mailbox.MailItem) ServiceException(com.zimbra.common.service.ServiceException) AccountAddressMatcher(com.zimbra.cs.util.AccountUtil.AccountAddressMatcher) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) ParseException(java.text.ParseException)

Example 29 with TimeZoneMap

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

the class Invite method createFromCalendar.

private static void createFromCalendar(List<Invite> toAdd, Account account, String fragment, ZVCalendar cal, boolean sentByMe, Mailbox mbx, int mailItemId, boolean continueOnError, InviteVisitor visitor) throws ServiceException {
    String method = cal.getPropVal(ICalTok.METHOD, ICalTok.PUBLISH.toString());
    // process the TIMEZONE's first: everything depends on them being there...
    TimeZoneMap tzmap = new TimeZoneMap(Util.getAccountTimeZone(account));
    Map<String, String> tzidRenames = Maps.newHashMap();
    List<ZComponent> components = Lists.newArrayList(cal.getComponentIterator());
    for (ZComponent comp : components) {
        if (ICalTok.VTIMEZONE.equals(comp.getTok())) {
            ICalTimeZone tz = ICalTimeZone.fromVTimeZone(comp, false, /* skipLookup */
            ICalTimeZone.TZID_NAME_ASSIGNMENT_BEHAVIOR.KEEP_IF_DOESNT_CLASH);
            tzmap.add(tz);
            String origTZID = comp.getPropVal(ICalTok.TZID, null);
            if ((null != origTZID) && (origTZID != tz.getID())) {
                tzidRenames.put(origTZID, tz.getID());
            }
        }
    }
    adjustTZIDnames(components, tzidRenames);
    createFromCalendar(toAdd, account, fragment, method, tzmap, cal.getComponentIterator(), sentByMe, mbx, mailItemId, continueOnError, visitor);
}
Also used : ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone)

Example 30 with TimeZoneMap

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

the class MetadataTest method legacyCalendarItem.

@Test
public void legacyCalendarItem() throws ServiceException, MessagingException {
    Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(MockProvisioning.DEFAULT_ACCOUNT_ID);
    SetCalendarItemData defaultInv = new SetCalendarItemData();
    MimeMessage message = new JavaMailMimeMessage(JMSession.getSession(), new ZSharedFileInputStream("data/TestMailRaw/invite1"));
    defaultInv.message = new ParsedMessage(message, Calendar.getInstance().getTimeInMillis(), false);
    TimeZoneMap tzMap = new TimeZoneMap(WellKnownTimeZones.getTimeZoneById("EST"));
    Invite invite = new Invite("REQUEST", tzMap, false);
    invite.setUid("test-uid");
    Calendar cal = GregorianCalendar.getInstance();
    cal.set(2005, 1, 21);
    invite.setDtStart(ParsedDateTime.fromUTCTime(cal.getTimeInMillis()));
    cal.set(2005, 2, 21);
    invite.setDtEnd(ParsedDateTime.fromUTCTime(cal.getTimeInMillis()));
    defaultInv.invite = invite;
    CalendarItem calItem = mbox.setCalendarItem(null, Mailbox.ID_FOLDER_CALENDAR, 0, null, defaultInv, null, null, CalendarItem.NEXT_ALARM_KEEP_CURRENT);
    calItem.mData.dateChanged = (int) (cal.getTimeInMillis() / 1000L);
    Metadata meta = calItem.encodeMetadata();
    meta.remove(Metadata.FN_TZMAP);
    calItem.decodeMetadata(meta);
    Assert.assertEquals(0, calItem.getStartTime());
    Assert.assertEquals(0, calItem.getEndTime());
    //simulate existence of FN_TZMAP with bad content. In reality the metadata versions 4, 5, 6 had more subtle differences in invite encoding, but this provokes the exception we need
    meta.put(Metadata.FN_TZMAP, "foo");
    calItem.decodeMetadata(meta);
    Assert.assertEquals(0, calItem.getStartTime());
    Assert.assertEquals(0, calItem.getEndTime());
    cal.set(2007, 2, 21);
    calItem.mData.dateChanged = (int) (cal.getTimeInMillis() / 1000L);
    boolean caught = false;
    try {
        calItem.decodeMetadata(meta);
    } catch (ServiceException se) {
        if (se.getCode().equalsIgnoreCase(ServiceException.INVALID_REQUEST)) {
            caught = true;
        }
    }
    Assert.assertTrue("new(er) appointment with bad metadata", caught);
}
Also used : ParsedMessage(com.zimbra.cs.mime.ParsedMessage) Calendar(com.ibm.icu.util.Calendar) GregorianCalendar(com.ibm.icu.util.GregorianCalendar) JavaMailMimeMessage(com.zimbra.common.mime.shim.JavaMailMimeMessage) SetCalendarItemData(com.zimbra.cs.mailbox.Mailbox.SetCalendarItemData) ZSharedFileInputStream(com.zimbra.common.zmime.ZSharedFileInputStream) ServiceException(com.zimbra.common.service.ServiceException) MimeMessage(javax.mail.internet.MimeMessage) JavaMailMimeMessage(com.zimbra.common.mime.shim.JavaMailMimeMessage) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) Invite(com.zimbra.cs.mailbox.calendar.Invite) Test(org.junit.Test)

Aggregations

TimeZoneMap (com.zimbra.common.calendar.TimeZoneMap)30 Invite (com.zimbra.cs.mailbox.calendar.Invite)15 ICalTimeZone (com.zimbra.common.calendar.ICalTimeZone)12 ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)10 ZVCalendar (com.zimbra.common.calendar.ZCalendar.ZVCalendar)8 Element (com.zimbra.common.soap.Element)8 ZProperty (com.zimbra.common.calendar.ZCalendar.ZProperty)7 Date (java.util.Date)7 Account (com.zimbra.cs.account.Account)6 Mailbox (com.zimbra.cs.mailbox.Mailbox)6 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)6 ArrayList (java.util.ArrayList)6 ParsedDuration (com.zimbra.common.calendar.ParsedDuration)5 ZComponent (com.zimbra.common.calendar.ZCalendar.ZComponent)5 ServiceException (com.zimbra.common.service.ServiceException)5 CalendarItem (com.zimbra.cs.mailbox.CalendarItem)5 Instance (com.zimbra.cs.mailbox.CalendarItem.Instance)5 ItemId (com.zimbra.cs.service.util.ItemId)5 OperationContext (com.zimbra.cs.mailbox.OperationContext)4 RecurId (com.zimbra.cs.mailbox.calendar.RecurId)4