Search in sources :

Example 1 with ZProperty

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

the class Attach method toZProperty.

public ZProperty toZProperty() {
    ZProperty prop;
    if (mUri != null) {
        prop = new ZProperty(ICalTok.ATTACH, mUri);
    } else {
        prop = new ZProperty(ICalTok.ATTACH, mBinaryB64Data);
        prop.addParameter(new ZParameter(ICalTok.VALUE, "BINARY"));
        prop.addParameter(new ZParameter(ICalTok.ENCODING, "BASE64"));
    }
    if (mContentType != null) {
        prop.addParameter(new ZParameter(ICalTok.FMTTYPE, mContentType));
    }
    if (fileName != null) {
        /* We recognise X-FILENAME incoming as well from Microsoft documentation but CalDAV clients are more
             * likely to use X-APPLE-FILENAME
             */
        prop.addParameter(new ZParameter(ICalTok.X_APPLE_FILENAME, fileName));
    }
    return prop;
}
Also used : ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) ZParameter(com.zimbra.common.calendar.ZCalendar.ZParameter)

Example 2 with ZProperty

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

the class ParsedDateTime method toProperty.

public ZProperty toProperty(ICalTok tok, boolean useOutlookCompatMode) {
    ZProperty toRet = new ZProperty(tok, getDateTimePartString(useOutlookCompatMode));
    String tzName = getTZName();
    if (!useOutlookCompatMode && !hasTime()) {
        toRet.addParameter(new ZParameter(ICalTok.VALUE, ICalTok.DATE.toString()));
    } else {
        if (tzName != null) {
            toRet.addParameter(new ZParameter(ICalTok.TZID, tzName));
        }
    }
    return toRet;
}
Also used : ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) ZParameter(com.zimbra.common.calendar.ZCalendar.ZParameter)

Example 3 with ZProperty

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

the class CalDavDataImport method putAppointment.

private String putAppointment(CalendarItem calItem, DataSourceItem dsItem) throws ServiceException, IOException, DavException {
    StringBuilder buf = new StringBuilder();
    ArrayList<String> recipients = new ArrayList<String>();
    buf.append("BEGIN:VCALENDAR\r\n");
    buf.append("VERSION:").append(ZCalendar.sIcalVersion).append("\r\n");
    buf.append("PRODID:").append(ZCalendar.sZimbraProdID).append("\r\n");
    Iterator<ICalTimeZone> iter = calItem.getTimeZoneMap().tzIterator();
    while (iter.hasNext()) {
        ICalTimeZone tz = iter.next();
        CharArrayWriter wr = new CharArrayWriter();
        tz.newToVTimeZone().toICalendar(wr, true);
        wr.flush();
        buf.append(wr.toCharArray());
        wr.close();
    }
    boolean appleICalExdateHack = LC.calendar_apple_ical_compatible_canceled_instances.booleanValue();
    ZComponent[] vcomps = Invite.toVComponents(calItem.getInvites(), true, false, appleICalExdateHack);
    if (vcomps != null) {
        CharArrayWriter wr = new CharArrayWriter();
        for (ZComponent vcomp : vcomps) {
            ZProperty organizer = vcomp.getProperty(ZCalendar.ICalTok.ORGANIZER);
            if (organizer != null)
                organizer.setValue(getUsername());
            vcomp.toICalendar(wr, true);
        }
        wr.flush();
        buf.append(wr.toCharArray());
        wr.close();
    }
    buf.append("END:VCALENDAR\r\n");
    String etag = dsItem.md.get(METADATA_KEY_ETAG, null);
    if (recipients.isEmpty())
        recipients = null;
    Appointment appt = new Appointment(dsItem.remoteId, etag, buf.toString(), recipients);
    return getClient().sendCalendarData(appt);
}
Also used : ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) Appointment(com.zimbra.cs.dav.client.CalDavClient.Appointment) ArrayList(java.util.ArrayList) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone) CharArrayWriter(java.io.CharArrayWriter)

Example 4 with ZProperty

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

the class CalDavUtils method removeAttendeeForOrganizer.

// Fixup for ATTENDEE properties set by Apple iCal
// Don't let the organizer to be also listed as an attendee.
public static void removeAttendeeForOrganizer(ZComponent comp) {
    if (!DebugConfig.caldavAllowAttendeeForOrganizer && (ICalTok.VEVENT.equals(comp.getTok()) || ICalTok.VTODO.equals(comp.getTok()))) {
        String organizer = comp.getPropVal(ICalTok.ORGANIZER, null);
        if (organizer != null) {
            organizer = organizer.trim();
            AccountAddressMatcher acctMatcher = null;
            String address = stripMailto(organizer);
            if (address != null) {
                try {
                    Account acct = Provisioning.getInstance().get(AccountBy.name, address);
                    if (acct != null) {
                        acctMatcher = new AccountAddressMatcher(acct);
                    }
                } catch (ServiceException e) {
                    // ignore
                    ZimbraLog.dav.warn("could not get the account matcher for " + address, e);
                }
            }
            for (Iterator<ZProperty> propIter = comp.getPropertyIterator(); propIter.hasNext(); ) {
                ZProperty prop = propIter.next();
                if (ICalTok.ATTENDEE.equals(prop.getToken())) {
                    String att = prop.getValue();
                    if (att != null) {
                        att = att.trim();
                        try {
                            // iCal has a habit of listing the organizer as an ATTENDEE.  Undo it.
                            if (att.equalsIgnoreCase(organizer) || (acctMatcher != null && acctMatcher.matches(stripMailto(att)))) {
                                propIter.remove();
                            }
                        } catch (ServiceException e) {
                            // ignore
                            ZimbraLog.dav.warn("exception while matching the attendee address " + att, e);
                        }
                    } else {
                        // We haven't seen this case occur, but just in case.
                        propIter.remove();
                    }
                }
            }
        }
    }
}
Also used : Account(com.zimbra.cs.account.Account) ServiceException(com.zimbra.common.service.ServiceException) AccountAddressMatcher(com.zimbra.cs.util.AccountUtil.AccountAddressMatcher) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty)

Example 5 with ZProperty

use of com.zimbra.common.calendar.ZCalendar.ZProperty 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)

Aggregations

ZProperty (com.zimbra.common.calendar.ZCalendar.ZProperty)49 ZParameter (com.zimbra.common.calendar.ZCalendar.ZParameter)19 ZComponent (com.zimbra.common.calendar.ZCalendar.ZComponent)18 ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)13 ArrayList (java.util.ArrayList)12 Account (com.zimbra.cs.account.Account)10 ICalTok (com.zimbra.common.calendar.ZCalendar.ICalTok)9 ZVCalendar (com.zimbra.common.calendar.ZCalendar.ZVCalendar)9 ICalTimeZone (com.zimbra.common.calendar.ICalTimeZone)8 Invite (com.zimbra.cs.mailbox.calendar.Invite)8 ParsedDuration (com.zimbra.common.calendar.ParsedDuration)7 ZOrganizer (com.zimbra.cs.mailbox.calendar.ZOrganizer)7 TimeZoneMap (com.zimbra.common.calendar.TimeZoneMap)6 ServiceException (com.zimbra.common.service.ServiceException)6 ParseException (java.text.ParseException)6 IRecurrence (com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence)5 AccountAddressMatcher (com.zimbra.cs.util.AccountUtil.AccountAddressMatcher)5 Element (com.zimbra.common.soap.Element)4 IOException (java.io.IOException)4 Geo (com.zimbra.common.calendar.Geo)3