1
0
mirror of https://github.com/moparisthebest/davmail synced 2025-01-13 06:28:19 -05:00

Caldav: experimental principal switch (access another user calendar) - untested

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@475 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2009-03-25 21:59:27 +00:00
parent cc61a50a39
commit 0889191527
2 changed files with 68 additions and 65 deletions

View File

@ -154,7 +154,7 @@ public class CaldavConnection extends AbstractConnection {
DavGatewayTray.error(e);
}
try {
sendErr(HttpStatus.SC_SERVICE_UNAVAILABLE, e);
sendErr(e);
} catch (IOException e2) {
DavGatewayTray.debug("Exception sending error to client", e2);
}
@ -220,7 +220,7 @@ public class CaldavConnection extends AbstractConnection {
} else if ("PROPFIND".equals(command) && "users".equals(paths[1]) && paths.length == 4 && "inbox".equals(paths[3])) {
sendInbox(request, depth, paths[2]);
} else if ("REPORT".equals(command) && "users".equals(paths[1]) && paths.length == 4 && "inbox".equals(paths[3])) {
reportEvents(request, "INBOX");
reportEvents(request, paths[2], "INBOX");
} else if ("PROPFIND".equals(command) && "users".equals(paths[1]) && paths.length == 4 && "outbox".equals(paths[3])) {
sendOutbox(request, paths[2]);
} else if ("POST".equals(command) && "users".equals(paths[1]) && paths.length == 4 && "outbox".equals(paths[3])) {
@ -228,43 +228,37 @@ public class CaldavConnection extends AbstractConnection {
sendFreeBusy(body);
} else {
int status = session.sendEvent(body);
sendHttpResponse(status, true);
sendHttpResponse(status);
}
} else if ("PROPFIND".equals(command) && "users".equals(paths[1]) && paths.length == 4 && "calendar".equals(paths[3])) {
sendCalendar(request, depth, paths[2]);
} else if ("PROPPATCH".equals(command) && "users".equals(paths[1]) && paths.length == 4 && "calendar".equals(paths[3])) {
patchCalendar(request, depth, paths[2]);
} else if ("REPORT".equals(command) && "users".equals(paths[1]) && paths.length == 4 && "calendar".equals(paths[3])
// only current user for now
&& session.getEmail().equalsIgnoreCase(paths[2])) {
reportEvents(request, "calendar");
patchCalendar();
} else if ("REPORT".equals(command) && "users".equals(paths[1]) && paths.length == 4 && "calendar".equals(paths[3])) {
reportEvents(request, paths[2], "calendar");
} else if ("PUT".equals(command) && "users".equals(paths[1]) && paths.length == 5 && "calendar".equals(paths[3])
// only current user for now
&& session.getEmail().equalsIgnoreCase(paths[2])) {
} else if ("PUT".equals(command) && "users".equals(paths[1]) && paths.length == 5 && "calendar".equals(paths[3])) {
String etag = headers.get("if-match");
String noneMatch = headers.get("if-none-match");
ExchangeSession.EventResult eventResult = session.createOrUpdateEvent(paths[4].replaceAll("&", "&"), body, etag, noneMatch);
ExchangeSession.EventResult eventResult = session.createOrUpdateEvent(paths[2], paths[4].replaceAll("&", "&"), body, etag, noneMatch);
if (eventResult.etag != null) {
HashMap<String, String> responseHeaders = new HashMap<String, String>();
responseHeaders.put("ETag", eventResult.etag);
sendHttpResponse(eventResult.status, responseHeaders, null, "", true);
} else {
sendHttpResponse(eventResult.status, true);
sendHttpResponse(eventResult.status);
}
} else if ("DELETE".equals(command) && "users".equals(paths[1]) && paths.length == 5
// only current user for now
&& session.getEmail().equalsIgnoreCase(paths[2])) {
} else if ("DELETE".equals(command) && "users".equals(paths[1]) && paths.length == 5) {
if ("inbox".equals(paths[3])) {
paths[3] = "INBOX";
}
int status = session.deleteEvent(paths[3], paths[4].replaceAll("&amp;", "&"));
sendHttpResponse(status, true);
int status = session.deleteEvent(paths[2], paths[3], paths[4].replaceAll("&amp;", "&"));
sendHttpResponse(status);
} else if ("GET".equals(command) && "users".equals(paths[1]) && paths.length == 5 && "calendar".equals(paths[3])
// only current user for now
&& session.getEmail().equalsIgnoreCase(paths[2])) {
ExchangeSession.Event event = session.getEvent(paths[3], paths[4]);
ExchangeSession.Event event = session.getEvent(paths[2], paths[3], paths[4]);
sendHttpResponse(HttpStatus.SC_OK, null, "text/calendar;charset=UTF-8", event.getICS(), true);
} else {
@ -281,6 +275,7 @@ public class CaldavConnection extends AbstractConnection {
int count = 0;
for (ExchangeSession.Event event : events) {
DavGatewayTray.debug("Retrieving event " + (++count) + "/" + size);
DavGatewayTray.switchIcon();
appendEventResponse(response, request, path, event);
}
}
@ -391,7 +386,7 @@ public class CaldavConnection extends AbstractConnection {
appendInbox(response, principal, request);
if (depth == 1) {
DavGatewayTray.debug("Searching calendar messages...");
List<ExchangeSession.Event> events = session.getEventMessages();
List<ExchangeSession.Event> events = session.getEventMessages(principal);
DavGatewayTray.debug("Found " + events.size() + " calendar messages");
appendEventsResponses(response, request, "inbox", events);
}
@ -413,7 +408,7 @@ public class CaldavConnection extends AbstractConnection {
appendCalendar(response, principal, request);
if (depth == 1) {
DavGatewayTray.debug("Searching calendar events...");
List<ExchangeSession.Event> events = session.getAllEvents();
List<ExchangeSession.Event> events = session.getAllEvents(principal);
DavGatewayTray.debug("Found " + events.size() + " calendar events");
appendEventsResponses(response, request, "calendar", events);
}
@ -421,7 +416,7 @@ public class CaldavConnection extends AbstractConnection {
response.close();
}
public void patchCalendar(CaldavRequest request, int depth, String principal) throws IOException {
public void patchCalendar() throws IOException {
CaldavResponse response = new CaldavResponse(HttpStatus.SC_MULTI_STATUS);
response.startMultistatus();
// just ignore calendar folder proppatch (color not supported in Exchange)
@ -438,7 +433,7 @@ public class CaldavConnection extends AbstractConnection {
}
}
public void reportEvents(CaldavRequest request, String path) throws IOException {
public void reportEvents(CaldavRequest request, String principal, String path) throws IOException {
List<ExchangeSession.Event> events;
List<String> notFound = new ArrayList<String>();
if (request.isMultiGet()) {
@ -451,19 +446,19 @@ public class CaldavConnection extends AbstractConnection {
String eventName = getEventFileNameFromPath(href);
if (eventName == null) {
notFound.add(href);
} else if ("inbox".equals(eventName)) {
} else if ("inbox".equals(eventName)|| "calendar".equals(eventName)) {
// Sunbird: just ignore
} else {
events.add(session.getEvent(path, eventName));
events.add(session.getEvent(principal, path, eventName));
}
} catch (HttpException e) {
notFound.add(href);
}
}
} else if ("INBOX".equals(path)) {
events = session.getEventMessages();
events = session.getEventMessages(principal);
} else {
events = session.getAllEvents();
events = session.getAllEvents(principal);
}
CaldavResponse response = new CaldavResponse(HttpStatus.SC_MULTI_STATUS);
@ -529,11 +524,11 @@ public class CaldavConnection extends AbstractConnection {
actualPrincipal = session.getEmail();
}
if (!session.getEmail().equals(principal)) {
String message = "Invalid principal path, try /principals/users/" + session.getEmail();
DavGatewayTray.error(message);
sendErr(HttpStatus.SC_NOT_FOUND, message);
} else {
//if (!session.getEmail().equals(principal)) {
// String message = "Invalid principal path, try /principals/users/" + session.getEmail();
// DavGatewayTray.error(message);
// sendErr(HttpStatus.SC_NOT_FOUND, message);
//} else {
CaldavResponse response = new CaldavResponse(HttpStatus.SC_MULTI_STATUS);
response.startMultistatus();
response.startResponse("/principals/users/" + principal);
@ -565,7 +560,7 @@ public class CaldavConnection extends AbstractConnection {
response.endResponse();
response.endMultistatus();
response.close();
}
//}
}
public void sendFreeBusy(String body) throws IOException {
@ -647,15 +642,15 @@ public class CaldavConnection extends AbstractConnection {
buffer.append(path);
Map<String, String> responseHeaders = new HashMap<String, String>();
responseHeaders.put("Location", buffer.toString());
sendHttpResponse(HttpStatus.SC_MOVED_PERMANENTLY, responseHeaders, true);
sendHttpResponse(HttpStatus.SC_MOVED_PERMANENTLY, responseHeaders);
}
public void sendErr(int status, Exception e) throws IOException {
public void sendErr(Exception e) throws IOException {
String message = e.getMessage();
if (message == null) {
message = e.toString();
}
sendErr(status, message);
sendErr(HttpStatus.SC_SERVICE_UNAVAILABLE, message);
}
public void sendErr(int status, String message) throws IOException {
@ -665,21 +660,21 @@ public class CaldavConnection extends AbstractConnection {
public void sendOptions() throws IOException {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Allow", "OPTIONS, GET, PROPFIND, PUT, POST");
sendHttpResponse(HttpStatus.SC_OK, headers, true);
sendHttpResponse(HttpStatus.SC_OK, headers);
}
public void sendUnauthorized() throws IOException {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("WWW-Authenticate", "Basic realm=\"" + Settings.getProperty("davmail.url") + "\"");
sendHttpResponse(HttpStatus.SC_UNAUTHORIZED, headers, true);
sendHttpResponse(HttpStatus.SC_UNAUTHORIZED, headers);
}
public void sendHttpResponse(int status, boolean keepAlive) throws IOException {
sendHttpResponse(status, null, null, (byte[]) null, keepAlive);
public void sendHttpResponse(int status) throws IOException {
sendHttpResponse(status, null, null, (byte[]) null, true);
}
public void sendHttpResponse(int status, Map<String, String> headers, boolean keepAlive) throws IOException {
sendHttpResponse(status, headers, null, (byte[]) null, keepAlive);
public void sendHttpResponse(int status, Map<String, String> headers) throws IOException {
sendHttpResponse(status, headers, null, (byte[]) null, true);
}
public void sendChunkedHttpResponse(int status) throws IOException {

View File

@ -109,10 +109,6 @@ public class ExchangeSession {
private boolean disableGalLookup = false;
ExchangeSessionFactory.PoolKey getPoolKey() {
return poolKey;
}
/**
* Create an exchange session for the given URL.
* The session is not actually established until a call to login()
@ -1170,15 +1166,17 @@ public class ExchangeSession {
}
}
public List<Event> getEventMessages() throws IOException {
public List<Event> getEventMessages(String principal) throws IOException {
String folderUrl = replacePrincipal(inboxUrl, principal);
String searchQuery = "Select \"DAV:getetag\"" +
" FROM Scope('SHALLOW TRAVERSAL OF \"" + inboxUrl + "\"')\n" +
" FROM Scope('SHALLOW TRAVERSAL OF \"" + folderUrl + "\"')\n" +
" WHERE \"DAV:contentclass\" = 'urn:content-classes:calendarmessage'\n" +
" ORDER BY \"urn:schemas:calendar:dtstart\" DESC\n";
return getEvents(inboxUrl, searchQuery);
return getEvents(folderUrl, searchQuery);
}
public List<Event> getAllEvents() throws IOException {
public List<Event> getAllEvents(String principal) throws IOException {
String folderUrl = replacePrincipal(calendarUrl, principal);
int caldavPastDelay = Settings.getIntProperty("davmail.caldavPastDelay", Integer.MAX_VALUE);
String dateCondition = "";
if (caldavPastDelay != Integer.MAX_VALUE) {
@ -1188,7 +1186,7 @@ public class ExchangeSession {
}
String searchQuery = "Select \"DAV:getetag\"" +
" FROM Scope('SHALLOW TRAVERSAL OF \"" + calendarUrl + "\"')\n" +
" FROM Scope('SHALLOW TRAVERSAL OF \"" + folderUrl + "\"')\n" +
" WHERE (" +
" \"urn:schemas:calendar:instancetype\" is null OR" +
" \"urn:schemas:calendar:instancetype\" = 1\n" +
@ -1196,7 +1194,7 @@ public class ExchangeSession {
dateCondition +
" )) AND \"DAV:contentclass\" = 'urn:content-classes:appointment'\n" +
" ORDER BY \"urn:schemas:calendar:dtstart\" DESC\n";
return getEvents(calendarUrl, searchQuery);
return getEvents(folderUrl, searchQuery);
}
public List<Event> getEvents(String path, String searchQuery) throws IOException {
@ -1208,8 +1206,8 @@ public class ExchangeSession {
return events;
}
public Event getEvent(String path, String eventName) throws IOException {
String eventPath = URIUtil.encodePath(getFolderPath(path)) + "/" + URIUtil.encodeWithinQuery(eventName);
public Event getEvent(String principal, String path, String eventName) throws IOException {
String eventPath = URIUtil.encodePath(replacePrincipal(getFolderPath(path), principal)) + "/" + URIUtil.encodeWithinQuery(eventName);
LOGGER.debug("getEvent(" + eventPath + "/" + eventName + ")");
Enumeration calendarEnum = DavGatewayHttpClientFacade.executePropFindMethod(httpClient, eventPath, 0, EVENT_REQUEST_PROPERTIES);
if (!calendarEnum.hasMoreElements()) {
@ -1400,8 +1398,8 @@ public class ExchangeSession {
}
}
public EventResult createOrUpdateEvent(String path, String icsBody, String etag, String noneMatch) throws IOException {
String messageUrl = URIUtil.encodePathQuery(calendarUrl + "/" + URIUtil.decode(path));
public EventResult createOrUpdateEvent(String principal, String path, String icsBody, String etag, String noneMatch) throws IOException {
String messageUrl = URIUtil.encodePathQuery(replacePrincipal(calendarUrl, principal) + "/" + URIUtil.decode(path));
return internalCreateOrUpdateEvent(messageUrl, "urn:content-classes:appointment", icsBody, etag, noneMatch);
}
@ -1567,18 +1565,15 @@ public class ExchangeSession {
DavGatewayHttpClientFacade.executeDeleteMethod(httpClient, URIUtil.encodePath(getFolderPath(path)));
}
public int deleteMessage(String path) throws IOException {
return DavGatewayHttpClientFacade.executeDeleteMethod(httpClient, URIUtil.encodePath(path));
}
public int deleteEvent(String path, String eventName) throws IOException {
public int deleteEvent(String principal, String path, String eventName) throws IOException {
int status;
if (path.startsWith("INBOX")) {
// do not delete calendar messages, move to trash
moveToTrash(URIUtil.encodePath(getFolderPath(URIUtil.decode(path))), eventName);
moveToTrash(URIUtil.encodePath(replacePrincipal(getFolderPath(URIUtil.decode(path)), principal)), eventName);
status = HttpStatus.SC_OK;
} else {
status = DavGatewayHttpClientFacade.executeDeleteMethod(httpClient, URIUtil.encodePath(getFolderPath(URIUtil.decode(path))) + "/" + eventName);
status = DavGatewayHttpClientFacade.executeDeleteMethod(httpClient,
URIUtil.encodePath(replacePrincipal(getFolderPath(URIUtil.decode(path)), principal)) + "/" + eventName);
}
return status;
}
@ -1699,6 +1694,19 @@ public class ExchangeSession {
return alias;
}
public String replacePrincipal(String folderUrl, String principal) throws IOException {
if (!alias.equals(principal) && !email.equals(principal)) {
int index = mailPath.lastIndexOf("/", mailPath.length() - 2);
if (index >= 0 && mailPath.endsWith("/")) {
return mailPath.substring(0, index) + "/" + principal + "/" + folderUrl.substring(inboxUrl.lastIndexOf("/"));
} else {
throw new IOException("Invalid mail path: " + mailPath);
}
} else {
return folderUrl;
}
}
public String getEmail(String alias) throws IOException {
String emailResult = null;
if (alias != null) {
@ -1921,7 +1929,7 @@ public class ExchangeSession {
* Free time returns 0, Tentative returns 1, Busy returns 2, and Out of Office (OOF) returns 3
*/
public static final class FreeBusy {
SimpleDateFormat icalParser;
final SimpleDateFormat icalParser;
boolean knownAttendee = true;
static final HashMap<Character, String> FBTYPES = new HashMap<Character, String>();
@ -1931,7 +1939,7 @@ public class ExchangeSession {
FBTYPES.put('3', "BUSY-UNAVAILABLE");
}
HashMap<String, StringBuilder> busyMap = new HashMap<String, StringBuilder>();
final HashMap<String, StringBuilder> busyMap = new HashMap<String, StringBuilder>();
protected StringBuilder getBusyBuffer(char type) {
String fbType = FBTYPES.get(Character.valueOf(type));