Search in sources :

Example 1 with ZComponent

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

the class TestCalDav method testFuzzyTimeZoneMatchGMT_06.

@Test
public void testFuzzyTimeZoneMatchGMT_06() throws Exception {
    try (ByteArrayInputStream bais = new ByteArrayInputStream(VtimeZoneGMT_0600_0500.getBytes())) {
        ZVCalendar tzcal = ZCalendar.ZCalendarBuilder.build(bais, MimeConstants.P_CHARSET_UTF8);
        assertNotNull("tzcal", tzcal);
        ZComponent tzcomp = tzcal.getComponent(ICalTok.VTIMEZONE);
        assertNotNull("tzcomp", tzcomp);
        ICalTimeZone tz = ICalTimeZone.fromVTimeZone(tzcomp, false, /* skipLookup */
        ICalTimeZone.TZID_NAME_ASSIGNMENT_BEHAVIOR.ALWAYS_KEEP);
        ICalTimeZone matchtz = ICalTimeZone.lookupMatchingWellKnownTZ(tz);
        assertEquals("ID of Timezone which fuzzy matches GMT=06.00/-05.00", "America/Chicago", matchtz.getID());
    }
}
Also used : ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) ZVCalendar(com.zimbra.common.calendar.ZCalendar.ZVCalendar) ByteArrayInputStream(java.io.ByteArrayInputStream) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone) Test(org.junit.Test)

Example 2 with ZComponent

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

the class Mailbox method writeICalendarForCalendarItems.

public void writeICalendarForCalendarItems(Writer writer, OperationContext octxt, Collection<CalendarItem> calItems, Folder f, boolean useOutlookCompatMode, boolean ignoreErrors, boolean needAppleICalHacks, boolean trimCalItemsList, boolean escapeHtmlTags, boolean includeAttaches) throws ServiceException {
    lock.lock();
    try {
        writer.write("BEGIN:VCALENDAR\r\n");
        if (f != null) {
            writer.write("X-WR-CALNAME:");
            writer.write(f.getName());
            writer.write("\r\n");
            writer.write("X-WR-CALID:");
            writer.write(new ItemId(f).toString());
            writer.write("\r\n");
        }
        ZProperty prop;
        prop = new ZProperty(ICalTok.PRODID, ZCalendar.sZimbraProdID);
        prop.toICalendar(writer, needAppleICalHacks);
        prop = new ZProperty(ICalTok.VERSION, ZCalendar.sIcalVersion);
        prop.toICalendar(writer, needAppleICalHacks);
        prop = new ZProperty(ICalTok.METHOD, ICalTok.PUBLISH.toString());
        prop.toICalendar(writer, needAppleICalHacks);
        // timezones
        ICalTimeZone localTz = Util.getAccountTimeZone(getAccount());
        TimeZoneMap tzmap = new TimeZoneMap(localTz);
        for (CalendarItem calItem : calItems) {
            tzmap.add(calItem.getTimeZoneMap());
        }
        // iterate the tzmap and add all the VTimeZone's
        for (Iterator<ICalTimeZone> iter = tzmap.tzIterator(); iter.hasNext(); ) {
            ICalTimeZone tz = iter.next();
            tz.newToVTimeZone().toICalendar(writer, needAppleICalHacks);
        }
        // help keep memory consumption low
        tzmap = null;
        // build all the event components and add them to the Calendar
        for (Iterator<CalendarItem> iter = calItems.iterator(); iter.hasNext(); ) {
            CalendarItem calItem = iter.next();
            boolean allowPrivateAccess = calItem.isPublic() || calItem.allowPrivateAccess(octxt.getAuthenticatedUser(), octxt.isUsingAdminPrivileges());
            if (trimCalItemsList) {
                // help keep memory consumption low
                iter.remove();
            }
            Invite[] invites = calItem.getInvites();
            if (invites != null && invites.length > 0) {
                boolean appleICalExdateHack = LC.calendar_apple_ical_compatible_canceled_instances.booleanValue();
                ZComponent[] comps = null;
                try {
                    comps = Invite.toVComponents(invites, allowPrivateAccess, useOutlookCompatMode, appleICalExdateHack, includeAttaches);
                } catch (ServiceException e) {
                    if (ignoreErrors) {
                        ZimbraLog.calendar.warn("Error retrieving iCalendar data for item %s: %s", calItem.getId(), e.getMessage(), e);
                    } else {
                        throw e;
                    }
                }
                if (comps != null) {
                    for (ZComponent comp : comps) {
                        comp.toICalendar(writer, needAppleICalHacks, escapeHtmlTags);
                    }
                }
            }
        }
        writer.write("END:VCALENDAR\r\n");
    } catch (IOException e) {
        throw ServiceException.FAILURE("Error writing iCalendar", e);
    } finally {
        lock.release();
    }
}
Also used : IOException(java.io.IOException) ItemId(com.zimbra.cs.service.util.ItemId) SetCalendarItem(com.zimbra.cs.redolog.op.SetCalendarItem) ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone) CreateInvite(com.zimbra.cs.redolog.op.CreateInvite) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 3 with ZComponent

use of com.zimbra.common.calendar.ZCalendar.ZComponent 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 4 with ZComponent

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

the class ScheduleOutbox method handlePost.

@Override
public void handlePost(DavContext ctxt) throws DavException, IOException, ServiceException {
    DelegationInfo delegationInfo = new DelegationInfo(ctxt.getRequest().getHeader(DavProtocol.HEADER_ORIGINATOR));
    Enumeration<String> recipients = ctxt.getRequest().getHeaders(DavProtocol.HEADER_RECIPIENT);
    InputStream in = ctxt.getUpload().getInputStream();
    ZCalendar.ZVCalendar vcalendar = ZCalendar.ZCalendarBuilder.build(in, MimeConstants.P_CHARSET_UTF8);
    Closeables.closeQuietly(in);
    Iterator<ZComponent> iter = vcalendar.getComponentIterator();
    ZComponent req = null;
    while (iter.hasNext()) {
        req = iter.next();
        if (req.getTok() != ICalTok.VTIMEZONE)
            break;
        req = null;
    }
    if (req == null) {
        throw new DavException("empty request", HttpServletResponse.SC_BAD_REQUEST);
    }
    ZimbraLog.dav.debug("originator: %s", delegationInfo.getOriginator());
    boolean isVEventOrVTodo = ICalTok.VEVENT.equals(req.getTok()) || ICalTok.VTODO.equals(req.getTok());
    boolean isOrganizerMethod = false, isCancel = false;
    if (isVEventOrVTodo) {
        String method = vcalendar.getPropVal(ICalTok.METHOD, null);
        if (method != null) {
            isOrganizerMethod = Invite.isOrganizerMethod(method);
            isCancel = ICalTok.CANCEL.toString().equalsIgnoreCase(method);
            ;
        }
        // Apple iCal fixup
        CalDavUtils.removeAttendeeForOrganizer(req);
    }
    // Get organizer and list of attendees. (mailto:email values)
    ArrayList<String> attendees = new ArrayList<String>();
    String organizer = null;
    for (Iterator<ZProperty> propsIter = req.getPropertyIterator(); propsIter.hasNext(); ) {
        ZProperty prop = propsIter.next();
        ICalTok token = prop.getToken();
        if (ICalTok.ATTENDEE.equals(token)) {
            String val = prop.getValue();
            if (val != null) {
                attendees.add(val.trim());
            }
        } else if (ICalTok.ORGANIZER.equals(token)) {
            String val = prop.getValue();
            if (val != null) {
                organizer = val.trim();
                String addr = CalDavUtils.stripMailto(organizer);
                // Rewrite the alias to primary address
                Account acct = Provisioning.getInstance().get(AccountBy.name, addr);
                if (acct != null) {
                    String newAddr = acct.getName();
                    if (!addr.equals(newAddr)) {
                        organizer = "mailto:" + newAddr;
                        prop.setValue(organizer);
                    }
                }
            }
        }
    }
    // Apple iCal is very inconsistent about the user's identity when the account has aliases.
    if (isVEventOrVTodo && delegationInfo.getOriginator() != null && ctxt.getAuthAccount() != null) {
        AccountAddressMatcher acctMatcher = new AccountAddressMatcher(ctxt.getAuthAccount());
        if (acctMatcher.matches(delegationInfo.getOriginatorEmail())) {
            if (isOrganizerMethod) {
                if (organizer != null) {
                    String organizerEmail = CalDavUtils.stripMailto(organizer);
                    if (!organizerEmail.equalsIgnoreCase(delegationInfo.getOriginatorEmail()) && acctMatcher.matches(organizerEmail)) {
                        delegationInfo.setOriginator(organizer);
                        ZimbraLog.dav.debug("changing originator to %s to match address/alias used in ORGANIZER", delegationInfo.getOriginator());
                    }
                }
            } else {
                for (String at : attendees) {
                    String atEmail = CalDavUtils.stripMailto(at);
                    if (delegationInfo.getOriginatorEmail().equalsIgnoreCase(atEmail)) {
                        break;
                    } else if (acctMatcher.matches(atEmail)) {
                        delegationInfo.setOriginator(at);
                        ZimbraLog.dav.debug("changing originator to %s to match address/alias used in ATTENDEE", delegationInfo.getOriginator());
                        break;
                    }
                }
            }
        }
    }
    // Get the recipients.
    ArrayList<String> rcptArray = new ArrayList<String>();
    while (recipients.hasMoreElements()) {
        String rcptHdr = recipients.nextElement();
        String[] rcpts = null;
        if (rcptHdr.indexOf(',') > 0) {
            rcpts = rcptHdr.split(",");
        } else {
            rcpts = new String[] { rcptHdr };
        }
        for (String rcpt : rcpts) {
            if (rcpt != null) {
                rcpt = rcpt.trim();
                if (rcpt.length() != 0) {
                    // Workaround for Apple iCal: Ignore attendees with address "invalid:nomail".
                    if (rcpt.equalsIgnoreCase("invalid:nomail")) {
                        continue;
                    }
                    if (isVEventOrVTodo) {
                        // iCal can sometimes do that when organizer account has aliases.
                        if (isOrganizerMethod && rcpt.equalsIgnoreCase(organizer)) {
                            continue;
                        }
                        // as ATTENDEE in the CANCEL component being sent.  (iCal does that part correctly, at least.)
                        if (isCancel) {
                            boolean isAttendee = false;
                            // Rcpt must be an attendee of the cancel component.
                            for (String at : attendees) {
                                if (rcpt.equalsIgnoreCase(at)) {
                                    isAttendee = true;
                                    break;
                                }
                            }
                            if (!isAttendee) {
                                ZimbraLog.dav.info("Ignoring non-attendee recipient '%s' of CANCEL request; likely a client bug", rcpt);
                                continue;
                            }
                        }
                    }
                    // All checks passed.
                    rcptArray.add(rcpt);
                }
            }
        }
    }
    Element scheduleResponse = ctxt.getDavResponse().getTop(DavElements.E_SCHEDULE_RESPONSE);
    for (String rcpt : rcptArray) {
        ZimbraLog.dav.debug("recipient email: " + rcpt);
        Element resp = scheduleResponse.addElement(DavElements.E_CALDAV_RESPONSE);
        switch(req.getTok()) {
            case VFREEBUSY:
                handleFreebusyRequest(ctxt, req, delegationInfo.getOriginator(), rcpt, resp);
                break;
            case VEVENT:
                // records.
                if (isOrganizerMethod) {
                    adjustOrganizer(ctxt, vcalendar, req, delegationInfo);
                }
                validateRequest(isOrganizerMethod, delegationInfo, organizer, ctxt, req);
                handleEventRequest(ctxt, vcalendar, req, delegationInfo, rcpt, resp);
                break;
            default:
                throw new DavException("unrecognized request: " + req.getTok(), HttpServletResponse.SC_BAD_REQUEST);
        }
    }
}
Also used : Account(com.zimbra.cs.account.Account) DavException(com.zimbra.cs.dav.DavException) InputStream(java.io.InputStream) Element(org.dom4j.Element) ArrayList(java.util.ArrayList) ICalTok(com.zimbra.common.calendar.ZCalendar.ICalTok) ZCalendar(com.zimbra.common.calendar.ZCalendar) ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) AccountAddressMatcher(com.zimbra.cs.util.AccountUtil.AccountAddressMatcher) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty)

Example 5 with ZComponent

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

the class CalendarCollection method findSummary.

private String findSummary(ZVCalendar cal) {
    Iterator<ZComponent> iter = cal.getComponentIterator();
    while (iter.hasNext()) {
        ZComponent comp = iter.next();
        String summary = comp.getPropVal(ICalTok.SUMMARY, null);
        if (summary != null)
            return summary;
    }
    return "calendar event";
}
Also used : ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent)

Aggregations

ZComponent (com.zimbra.common.calendar.ZCalendar.ZComponent)41 ZProperty (com.zimbra.common.calendar.ZCalendar.ZProperty)22 ZVCalendar (com.zimbra.common.calendar.ZCalendar.ZVCalendar)19 ICalTimeZone (com.zimbra.common.calendar.ICalTimeZone)16 Test (org.junit.Test)11 ArrayList (java.util.ArrayList)10 ICalTok (com.zimbra.common.calendar.ZCalendar.ICalTok)9 ZParameter (com.zimbra.common.calendar.ZCalendar.ZParameter)8 ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)7 Account (com.zimbra.cs.account.Account)7 Invite (com.zimbra.cs.mailbox.calendar.Invite)7 ByteArrayInputStream (java.io.ByteArrayInputStream)7 IOException (java.io.IOException)7 InputStream (java.io.InputStream)7 TimeZoneMap (com.zimbra.common.calendar.TimeZoneMap)5 ServiceException (com.zimbra.common.service.ServiceException)4 MessagingException (javax.mail.MessagingException)4 MimeMessage (javax.mail.internet.MimeMessage)4 ParsedMessage (com.zimbra.cs.mime.ParsedMessage)3 CalendarPartInfo (com.zimbra.cs.mime.ParsedMessage.CalendarPartInfo)3