Search in sources :

Example 6 with DavException

use of com.zimbra.cs.dav.DavException in project zm-mailbox by Zimbra.

the class MailItemResource method moveORcopyWithOverwrite.

public void moveORcopyWithOverwrite(DavContext ctxt, Collection dest, String newName, boolean deleteOriginal) throws DavException {
    try {
        if (deleteOriginal)
            move(ctxt, dest, newName);
        else
            copy(ctxt, dest, newName);
    } catch (DavException e) {
        if (e.getStatus() == HttpServletResponse.SC_PRECONDITION_FAILED) {
            // in case of name conflict, delete the existing mail item and
            // attempt the move operation again.
            // return if the error is not ALREADY_EXISTS
            ServiceException se = (ServiceException) e.getCause();
            int id = 0;
            try {
                if (se.getCode().equals(MailServiceException.ALREADY_EXISTS) == false)
                    throw e;
                else {
                    // get the conflicting item-id
                    if (se instanceof SoapFaultException) {
                        // destination belongs other mailbox.
                        String itemIdStr = ((SoapFaultException) se).getArgumentValue("id");
                        ItemId itemId = new ItemId(itemIdStr, dest.getItemId().getAccountId());
                        id = itemId.getId();
                    } else {
                        // destination belongs to same mailbox.
                        String name = null;
                        for (Argument arg : se.getArgs()) {
                            if (arg.name != null && arg.value != null && arg.value.length() > 0) {
                                if (arg.name.equals("name"))
                                    name = arg.value;
                            /* commented out since the exception is giving wrong itemId for copy.
                                       If the the item is conflicting with an existing item we want the
                                       id of the existing item. But, the exception has the proposed id of
                                       the new item which does not exist yet.
                                     else if (arg.mName.equals("itemId"))
                                        id = Integer.parseInt(arg.mValue);
                                     */
                            }
                        }
                        if (id <= 0) {
                            if (name == null && !deleteOriginal) {
                                // in case of copy get the id from source name since we don't support copy with rename.
                                name = ctxt.getItem();
                            }
                            if (name != null) {
                                Mailbox mbox = getMailbox(ctxt);
                                MailItem item = mbox.getItemByPath(ctxt.getOperationContext(), name, dest.getId());
                                id = item.getId();
                            } else
                                throw e;
                        }
                    }
                }
                deleteDestinationItem(ctxt, dest, id);
            } catch (ServiceException se1) {
                throw new DavException("cannot move/copy item", HttpServletResponse.SC_FORBIDDEN, se1);
            }
            if (deleteOriginal)
                move(ctxt, dest, newName);
            else
                copy(ctxt, dest, newName);
        } else {
            throw e;
        }
    }
}
Also used : MailItem(com.zimbra.cs.mailbox.MailItem) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) Argument(com.zimbra.common.service.ServiceException.Argument) Mailbox(com.zimbra.cs.mailbox.Mailbox) ZMailbox(com.zimbra.client.ZMailbox) DavException(com.zimbra.cs.dav.DavException) ItemId(com.zimbra.cs.service.util.ItemId) SoapFaultException(com.zimbra.common.soap.SoapFaultException)

Example 7 with DavException

use of com.zimbra.cs.dav.DavException 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 8 with DavException

use of com.zimbra.cs.dav.DavException in project zm-mailbox by Zimbra.

the class ScheduleOutbox method validateRequest.

/**
     * Check for illegal requests like trying to CANCEL a meeting when not the organizer or a delegate for
     * the organizer
     * e.g. Bug 85875 Mac OS X/10.8.5 Calendar sometimes sending CANCEL when ATTENDEE deletes an instance,
     *      resulting in other attendees getting invalid CANCELs
     */
private void validateRequest(boolean isOrganizerMethod, DelegationInfo delegationInfo, String organizer, DavContext ctxt, ZComponent req) throws ServiceException, DavException {
    if ((!isOrganizerMethod) || (organizer != null && organizer.equals(delegationInfo.getOriginator()))) {
        return;
    }
    // If here, only the ORGANIZER or a delegate acting as the ORGANIZER should be able to do this
    AccountAddressMatcher acctMatcher = new AccountAddressMatcher(ctxt.getAuthAccount());
    if (!acctMatcher.matches(delegationInfo.getOriginatorEmail())) {
        throw new DavException(String.format("invalid POST to scheduling outbox '%s'. originator '%s' is not authorized account or ORGANIZER", ctxt.getRequest().getRequestURI(), delegationInfo.getOriginatorEmail()), HttpServletResponse.SC_BAD_REQUEST);
    }
    String organizerEmail = CalDavUtils.stripMailto(organizer);
    Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(ctxt.getAuthAccount());
    List<com.zimbra.cs.mailbox.Mountpoint> sharedCalendars = mbox.getCalendarMountpoints(ctxt.getOperationContext(), SortBy.NONE);
    if (sharedCalendars != null) {
        for (com.zimbra.cs.mailbox.Mountpoint sharedCalendar : sharedCalendars) {
            Account acct = Provisioning.getInstance().get(AccountBy.id, sharedCalendar.getOwnerId());
            if (acct != null) {
                acctMatcher = new AccountAddressMatcher(acct);
                if (acctMatcher.matches(organizerEmail)) {
                    return;
                }
            }
        }
    }
    // We haven't found a shared calendar for the ORGANIZER that we are a delegate for.
    throw new DavException(String.format("invalid POST to scheduling outbox '%s'. '%s' cannot act as ORGANIZER '%s'", ctxt.getRequest().getRequestURI(), delegationInfo.getOriginatorEmail(), organizerEmail), HttpServletResponse.SC_BAD_REQUEST);
}
Also used : Account(com.zimbra.cs.account.Account) Mailbox(com.zimbra.cs.mailbox.Mailbox) DavException(com.zimbra.cs.dav.DavException) AccountAddressMatcher(com.zimbra.cs.util.AccountUtil.AccountAddressMatcher)

Example 9 with DavException

use of com.zimbra.cs.dav.DavException in project zm-mailbox by Zimbra.

the class MailItemResource method move.

/* Moves this resource to another Collection. */
public void move(DavContext ctxt, Collection dest, String newName) throws DavException {
    try {
        Mailbox mbox = getMailbox(ctxt);
        ArrayList<Integer> ids = new ArrayList<Integer>();
        ids.add(mId);
        if (newName != null)
            ItemActionHelper.RENAME(ctxt.getOperationContext(), mbox, SoapProtocol.Soap12, ids, type, null, newName, dest.getItemId());
        else
            ItemActionHelper.MOVE(ctxt.getOperationContext(), mbox, SoapProtocol.Soap12, ids, type, null, dest.getItemId());
    } catch (ServiceException se) {
        int resCode = se instanceof MailServiceException.NoSuchItemException ? HttpServletResponse.SC_NOT_FOUND : HttpServletResponse.SC_FORBIDDEN;
        if (se.getCode().equals(MailServiceException.ALREADY_EXISTS))
            resCode = HttpServletResponse.SC_PRECONDITION_FAILED;
        throw new DavException("cannot move item", resCode, se);
    }
}
Also used : Mailbox(com.zimbra.cs.mailbox.Mailbox) ZMailbox(com.zimbra.client.ZMailbox) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) DavException(com.zimbra.cs.dav.DavException) ArrayList(java.util.ArrayList)

Example 10 with DavException

use of com.zimbra.cs.dav.DavException in project zm-mailbox by Zimbra.

the class CalendarCollection method findEventUid.

private String findEventUid(List<Invite> invites) throws DavException {
    String uid = null;
    MailItem.Type itemType = null;
    LinkedList<Invite> inviteList = new LinkedList<Invite>();
    for (Invite i : invites) {
        MailItem.Type mItemType = i.getItemType();
        if (mItemType == MailItem.Type.APPOINTMENT || mItemType == MailItem.Type.TASK) {
            if (uid != null && uid.compareTo(i.getUid()) != 0)
                throw new DavException.InvalidData(DavElements.E_VALID_CALENDAR_OBJECT_RESOURCE, "too many components");
            uid = i.getUid();
        }
        if (itemType != null && itemType != mItemType)
            throw new DavException.InvalidData(DavElements.E_VALID_CALENDAR_OBJECT_RESOURCE, "different types of components in the same resource");
        else
            itemType = mItemType;
        if (i.isRecurrence())
            inviteList.addFirst(i);
        else
            inviteList.addLast(i);
    }
    if (uid == null)
        throw new DavException.InvalidData(DavElements.E_SUPPORTED_CALENDAR_COMPONENT, "no event in the request");
    if ((getDefaultView() == MailItem.Type.APPOINTMENT || getDefaultView() == MailItem.Type.TASK) && (itemType != getDefaultView()))
        throw new DavException.InvalidData(DavElements.E_SUPPORTED_CALENDAR_COMPONENT, "resource type not supported in this collection");
    invites.clear();
    invites.addAll(inviteList);
    return uid;
}
Also used : MailItem(com.zimbra.cs.mailbox.MailItem) DavException(com.zimbra.cs.dav.DavException) LinkedList(java.util.LinkedList) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Aggregations

DavException (com.zimbra.cs.dav.DavException)67 ServiceException (com.zimbra.common.service.ServiceException)27 Element (org.dom4j.Element)25 Account (com.zimbra.cs.account.Account)18 Mailbox (com.zimbra.cs.mailbox.Mailbox)18 DavResource (com.zimbra.cs.dav.resource.DavResource)15 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)15 ArrayList (java.util.ArrayList)14 Provisioning (com.zimbra.cs.account.Provisioning)11 Document (org.dom4j.Document)9 DavResponse (com.zimbra.cs.dav.service.DavResponse)8 MailItem (com.zimbra.cs.mailbox.MailItem)8 Invite (com.zimbra.cs.mailbox.calendar.Invite)7 ZMailbox (com.zimbra.client.ZMailbox)6 RequestProp (com.zimbra.cs.dav.DavContext.RequestProp)6 IOException (java.io.IOException)6 Collection (com.zimbra.cs.dav.resource.Collection)5 Folder (com.zimbra.cs.mailbox.Folder)5 CalendarCollection (com.zimbra.cs.dav.resource.CalendarCollection)4 ZProperty (com.zimbra.common.calendar.ZCalendar.ZProperty)3