mirror of
https://github.com/moparisthebest/davmail
synced 2024-12-13 11:12:22 -05:00
Caldav: improve filter handling, support VTODO/VEVENT comp-filter
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1394 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
98ae8917c0
commit
f6a6dd9333
@ -704,7 +704,13 @@ public class CaldavConnection extends AbstractConnection {
|
||||
appendEventsResponses(response, request, events);
|
||||
} else {
|
||||
// TODO: handle contacts ?
|
||||
events = session.searchEvents(request.getFolderPath(), request.timeRangeStart, request.timeRangeEnd);
|
||||
if (request.vTodoOnly) {
|
||||
events = session.searchTasksOnly(request.getFolderPath());
|
||||
} else if (request.vEventOnly) {
|
||||
events = session.searchEventsOnly(request.getFolderPath(), request.timeRangeStart, request.timeRangeEnd);
|
||||
} else {
|
||||
events = session.searchEvents(request.getFolderPath(), request.timeRangeStart, request.timeRangeEnd);
|
||||
}
|
||||
appendEventsResponses(response, request, events);
|
||||
}
|
||||
|
||||
@ -1209,6 +1215,8 @@ public class CaldavConnection extends AbstractConnection {
|
||||
protected boolean isMultiGet;
|
||||
protected String timeRangeStart;
|
||||
protected String timeRangeEnd;
|
||||
protected boolean vTodoOnly;
|
||||
protected boolean vEventOnly;
|
||||
|
||||
protected CaldavRequest(String command, String path, Map<String, String> headers, String body) throws IOException {
|
||||
this.command = command;
|
||||
@ -1418,7 +1426,14 @@ public class CaldavConnection extends AbstractConnection {
|
||||
public void handleCompFilter(XMLStreamReader reader) throws XMLStreamException {
|
||||
while (reader.hasNext() && !isEndTag(reader, "comp-filter")) {
|
||||
reader.nextTag();
|
||||
if (XMLStreamUtil.isStartTag(reader, "time-range")) {
|
||||
if (XMLStreamUtil.isStartTag(reader, "comp-filter")) {
|
||||
String name = reader.getAttributeValue(null, "name");
|
||||
if ("VEVENT".equals(name)) {
|
||||
vEventOnly = true;
|
||||
} else if ("VTODO".equals(name)) {
|
||||
vTodoOnly = true;
|
||||
}
|
||||
} else if (XMLStreamUtil.isStartTag(reader, "time-range")) {
|
||||
timeRangeStart = reader.getAttributeValue(null, "start");
|
||||
timeRangeEnd = reader.getAttributeValue(null, "end");
|
||||
}
|
||||
|
@ -2089,9 +2089,9 @@ public abstract class ExchangeSession {
|
||||
writer.writeHeader("Date", new Date());
|
||||
|
||||
// Make sure invites have a proper subject line
|
||||
String subject = vCalendar.getFirstVeventPropertyValue("SUMMARY");
|
||||
if (subject == null) {
|
||||
subject = BundleMessage.format("MEETING_REQUEST");
|
||||
String vEventSubject = vCalendar.getFirstVeventPropertyValue("SUMMARY");
|
||||
if (vEventSubject == null) {
|
||||
vEventSubject = BundleMessage.format("MEETING_REQUEST");
|
||||
}
|
||||
|
||||
// Write a part of the message that contains the
|
||||
@ -2267,7 +2267,25 @@ public abstract class ExchangeSession {
|
||||
dateCondition = gt("dtstart", formatSearchDate(cal.getTime()));
|
||||
}
|
||||
|
||||
return searchEvents(folderPath, dateCondition);
|
||||
return searchEvents(folderPath, or(isNull("instancetype"),
|
||||
isEqualTo("instancetype", 1),
|
||||
and(isEqualTo("instancetype", 0), dateCondition)));
|
||||
}
|
||||
|
||||
protected Condition getRangeCondition(String timeRangeStart, String timeRangeEnd) throws IOException {
|
||||
try {
|
||||
SimpleDateFormat parser = getZuluDateFormat();
|
||||
ExchangeSession.MultiCondition andCondition = and();
|
||||
if (timeRangeStart != null) {
|
||||
andCondition.add(gte("dtstart", formatSearchDate(parser.parse(timeRangeStart))));
|
||||
}
|
||||
if (timeRangeEnd != null) {
|
||||
andCondition.add(lte("dtend", formatSearchDate(parser.parse(timeRangeEnd))));
|
||||
}
|
||||
return andCondition;
|
||||
} catch (ParseException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2280,30 +2298,47 @@ public abstract class ExchangeSession {
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public List<Event> searchEvents(String folderPath, String timeRangeStart, String timeRangeEnd) throws IOException {
|
||||
try {
|
||||
SimpleDateFormat parser = getZuluDateFormat();
|
||||
ExchangeSession.MultiCondition andCondition = and();
|
||||
if (timeRangeStart != null) {
|
||||
andCondition.add(gte("dtstart", formatSearchDate(parser.parse(timeRangeStart))));
|
||||
}
|
||||
if (timeRangeEnd != null) {
|
||||
andCondition.add(lte("dtend", formatSearchDate(parser.parse(timeRangeEnd))));
|
||||
}
|
||||
return searchEvents(folderPath, andCondition);
|
||||
} catch (ParseException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
Condition dateCondition = getRangeCondition(timeRangeStart, timeRangeEnd);
|
||||
return searchEvents(folderPath, or(isNull("instancetype"),
|
||||
isEqualTo("instancetype", 1),
|
||||
and(isEqualTo("instancetype", 0), dateCondition)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Search events between start and end, exclude tasks.
|
||||
*
|
||||
* @param folderPath Exchange folder path
|
||||
* @param timeRangeStart date range start in zulu format
|
||||
* @param timeRangeEnd date range start in zulu format
|
||||
* @return list of calendar events
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public List<Event> searchEventsOnly(String folderPath, String timeRangeStart, String timeRangeEnd) throws IOException {
|
||||
Condition dateCondition = getRangeCondition(timeRangeStart, timeRangeEnd);
|
||||
return searchEvents(folderPath, or(isEqualTo("instancetype", 1),
|
||||
and(isEqualTo("instancetype", 0), dateCondition)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Search tasks only (VTODO).
|
||||
*
|
||||
* @param folderPath Exchange folder path
|
||||
* @return list of calendar events
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public List<Event> searchTasksOnly(String folderPath) throws IOException {
|
||||
return searchEvents(folderPath, isNull("instancetype"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Search calendar events in provided folder.
|
||||
*
|
||||
* @param folderPath Exchange folder path
|
||||
* @param dateCondition date filter
|
||||
* @param folderPath Exchange folder path
|
||||
* @param filter search filter
|
||||
* @return list of calendar events
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public List<Event> searchEvents(String folderPath, Condition dateCondition) throws IOException {
|
||||
public List<Event> searchEvents(String folderPath, Condition filter) throws IOException {
|
||||
|
||||
Condition privateCondition = null;
|
||||
if (isSharedFolder(folderPath)) {
|
||||
@ -2312,10 +2347,7 @@ public abstract class ExchangeSession {
|
||||
}
|
||||
// instancetype 0 single appointment / 1 master recurring appointment
|
||||
return searchEvents(folderPath, ITEM_PROPERTIES,
|
||||
and(or(isNull("instancetype"),
|
||||
isEqualTo("instancetype", 1),
|
||||
and(isEqualTo("instancetype", 0), dateCondition)),
|
||||
privateCondition));
|
||||
and(filter, privateCondition));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,12 +33,16 @@ import org.apache.jackrabbit.webdav.DavException;
|
||||
import org.apache.jackrabbit.webdav.MultiStatus;
|
||||
import org.apache.jackrabbit.webdav.MultiStatusResponse;
|
||||
import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
|
||||
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
|
||||
import org.apache.log4j.Level;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Test Caldav listener.
|
||||
@ -121,6 +125,13 @@ public class TestCaldav extends AbstractDavMailTestCase {
|
||||
assertEquals(HttpStatus.SC_OK, method.getStatusCode());
|
||||
}
|
||||
|
||||
public void testGetOtherUserCalendar() throws IOException {
|
||||
Settings.setLoggingLevel("httpclient.wire", Level.DEBUG);
|
||||
PropFindMethod method = new PropFindMethod("/principals/users/" + Settings.getProperty("davmail.to") + "/calendar/");
|
||||
httpClient.executeMethod(method);
|
||||
assertEquals(HttpStatus.SC_OK, method.getStatusCode());
|
||||
}
|
||||
|
||||
public void testReportCalendar() throws IOException, DavException {
|
||||
SimpleDateFormat formatter = ExchangeSession.getZuluDateFormat();
|
||||
Calendar cal = Calendar.getInstance();
|
||||
@ -148,17 +159,60 @@ public class TestCaldav extends AbstractDavMailTestCase {
|
||||
assertEquals(HttpStatus.SC_MULTI_STATUS, method.getStatusCode());
|
||||
MultiStatus multiStatus = method.getResponseBodyAsMultiStatus();
|
||||
MultiStatusResponse[] responses = multiStatus.getResponses();
|
||||
|
||||
ExchangeSession.Condition dateCondition = session.and(
|
||||
session.gt("dtstart", session.formatSearchDate(start)),
|
||||
session.lt("dtend", session.formatSearchDate(end))
|
||||
);
|
||||
List<ExchangeSession.Event> events = session.searchEvents("/users/" + session.getEmail() + "/calendar/",
|
||||
session.and(
|
||||
session.gt("dtstart", session.formatSearchDate(start)),
|
||||
session.lt("dtend", session.formatSearchDate(end))
|
||||
)
|
||||
session.or(session.isNull("instancetype"),
|
||||
session.isEqualTo("instancetype", 1),
|
||||
session.and(session.isEqualTo("instancetype", 0), dateCondition))
|
||||
|
||||
);
|
||||
|
||||
assertEquals(events.size(), responses.length);
|
||||
}
|
||||
|
||||
public void testReportTasks() throws IOException, DavException {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
buffer.append("<C:calendar-query xmlns:C=\"urn:ietf:params:xml:ns:caldav\" xmlns:D=\"DAV:\">");
|
||||
buffer.append("<D:prop>");
|
||||
buffer.append("<C:calendar-data/>");
|
||||
buffer.append("</D:prop>");
|
||||
buffer.append("<C:comp-filter name=\"VCALENDAR\">");
|
||||
buffer.append("<C:comp-filter name=\"VTODO\"/>");
|
||||
buffer.append("</C:comp-filter>");
|
||||
buffer.append("<C:filter>");
|
||||
buffer.append("</C:filter>");
|
||||
buffer.append("</C:calendar-query>");
|
||||
SearchReportMethod method = new SearchReportMethod("/users/" + session.getEmail() + "/calendar/", buffer.toString());
|
||||
httpClient.executeMethod(method);
|
||||
assertEquals(HttpStatus.SC_MULTI_STATUS, method.getStatusCode());
|
||||
MultiStatus multiStatus = method.getResponseBodyAsMultiStatus();
|
||||
MultiStatusResponse[] responses = multiStatus.getResponses();
|
||||
}
|
||||
|
||||
public void testReportEventsOnly() throws IOException, DavException {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
buffer.append("<C:calendar-query xmlns:C=\"urn:ietf:params:xml:ns:caldav\" xmlns:D=\"DAV:\">");
|
||||
buffer.append("<D:prop>");
|
||||
buffer.append("<C:calendar-data/>");
|
||||
buffer.append("</D:prop>");
|
||||
buffer.append("<C:comp-filter name=\"VCALENDAR\">");
|
||||
buffer.append("<C:comp-filter name=\"VEVENT\"/>");
|
||||
buffer.append("</C:comp-filter>");
|
||||
buffer.append("<C:filter>");
|
||||
buffer.append("</C:filter>");
|
||||
buffer.append("</C:calendar-query>");
|
||||
SearchReportMethod method = new SearchReportMethod("/users/" + session.getEmail() + "/calendar/", buffer.toString());
|
||||
httpClient.executeMethod(method);
|
||||
assertEquals(HttpStatus.SC_MULTI_STATUS, method.getStatusCode());
|
||||
MultiStatus multiStatus = method.getResponseBodyAsMultiStatus();
|
||||
MultiStatusResponse[] responses = multiStatus.getResponses();
|
||||
}
|
||||
|
||||
public void testCreateCalendar() throws IOException {
|
||||
String folderName = "test & accentué";
|
||||
String encodedFolderpath = URIUtil.encodePath("/users/" + session.getEmail() + "/calendar/" + folderName + '/');
|
||||
|
Loading…
Reference in New Issue
Block a user