diff --git a/src/java/davmail/caldav/CaldavConnection.java b/src/java/davmail/caldav/CaldavConnection.java index 04d635db..04fa5507 100644 --- a/src/java/davmail/caldav/CaldavConnection.java +++ b/src/java/davmail/caldav/CaldavConnection.java @@ -62,11 +62,20 @@ public class CaldavConnection extends AbstractConnection { throw new IOException("Invalid content length: " + contentLength); } char[] buffer = new char[size]; - int actualSize = in.read(buffer); - if (actualSize < 0) { - throw new IOException("End of stream reached reading content"); + StringBuilder builder = new StringBuilder(); + int actualSize = in.read(buffer); + builder.append(buffer, 0, actualSize); + if (actualSize < 0) { + throw new IOException("End of stream reached reading content"); + } + // dirty hack to ensure full content read + // TODO : replace with a dedicated reader + while (builder.toString().getBytes("UTF-8").length < size) { + actualSize = in.read(buffer); + builder.append(buffer, 0, actualSize); } - return new String(buffer, 0, actualSize); + + return builder.toString(); } } @@ -105,6 +114,8 @@ public class CaldavConnection extends AbstractConnection { String path = tokens.nextToken(); String content = getContent(headers.get("content-length")); setSocketTimeout(headers.get("keep-alive")); + // client requested connection close + closed = "close".equals(headers.get("connection")); if ("OPTIONS".equals(command)) { sendOptions(); } else if (!headers.containsKey("authorization")) { @@ -209,8 +220,8 @@ public class CaldavConnection extends AbstractConnection { } 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])) { - if (body.indexOf("VFREEBUSY") >=0) { - sendFreeBusy(body); + if (body.indexOf("VFREEBUSY") >= 0) { + sendFreeBusy(body); } else { int status = session.sendEvent(body); sendHttpResponse(status, true); @@ -226,9 +237,15 @@ public class CaldavConnection extends AbstractConnection { // only current user for now && session.getEmail().equalsIgnoreCase(paths[2])) { String etag = headers.get("if-match"); - String noneMatch = headers.get("if-none-match"); - int status = session.createOrUpdateEvent(paths[4], body, etag, noneMatch); - sendHttpResponse(status, true); + String noneMatch = headers.get("if-none-match"); + ExchangeSession.EventResult eventResult = session.createOrUpdateEvent(paths[4], body, etag, noneMatch); + if (eventResult.etag != null) { + HashMap responseHeaders = new HashMap(); + responseHeaders.put("GetETag", eventResult.etag); + sendHttpResponse(eventResult.status, responseHeaders, "text/html", "", true); + } else { + sendHttpResponse(eventResult.status, true); + } } else if ("DELETE".equals(command) && "users".equals(paths[1]) && paths.length == 5 && "calendar".equals(paths[3]) // only current user for now @@ -417,7 +434,7 @@ public class CaldavConnection extends AbstractConnection { if (depth == 1) { DavGatewayTray.debug("Searching calendar events..."); List events = session.getAllEvents(); - DavGatewayTray.debug("Found "+events.size()+" calendar events"); + DavGatewayTray.debug("Found " + events.size() + " calendar events"); appendEventsResponses(buffer, request, events); } buffer.append(""); @@ -441,7 +458,7 @@ public class CaldavConnection extends AbstractConnection { int count = 0; int total = request.getHrefs().size(); for (String href : request.getHrefs()) { - DavGatewayTray.debug("Report event "+(++count)+"/"+total); + DavGatewayTray.debug("Report event " + (++count) + "/" + total); try { String eventName = getEventFileNameFromPath(href); if (eventName == null) { @@ -586,20 +603,20 @@ public class CaldavConnection extends AbstractConnection { String line; String key; while ((line = reader.readLine()) != null) { - int index = line.indexOf(':'); - if (index <= 0) { - throw new IOException("Invalid request: " + body); - } - String fullkey = line.substring(0, index); - String value = line.substring(index + 1); - int semicolonIndex = fullkey.indexOf(";"); - if (semicolonIndex > 0) { - key = fullkey.substring(0, semicolonIndex); - } else { - key = fullkey; - } - valueMap.put(key, value); - keyMap.put(key, fullkey); + int index = line.indexOf(':'); + if (index <= 0) { + throw new IOException("Invalid request: " + body); + } + String fullkey = line.substring(0, index); + String value = line.substring(index + 1); + int semicolonIndex = fullkey.indexOf(";"); + if (semicolonIndex > 0) { + key = fullkey.substring(0, semicolonIndex); + } else { + key = fullkey; + } + valueMap.put(key, value); + keyMap.put(key, fullkey); } String freeBusy = session.getFreebusy(valueMap); if (freeBusy != null) { @@ -690,8 +707,8 @@ public class CaldavConnection extends AbstractConnection { if (contentType != null) { sendClient("Content-Type: " + contentType); } - sendClient("Connection: " + (keepAlive ? "keep-alive" : "close")); - closed = !keepAlive; + closed = closed || !keepAlive; + sendClient("Connection: " + (closed ? "close" : "keep-alive")); if (content != null && content.length() > 0) { sendClient("Content-Length: " + content.getBytes("UTF-8").length); } else { diff --git a/src/java/davmail/exchange/ExchangeSession.java b/src/java/davmail/exchange/ExchangeSession.java index 68c844ce..2e1f04cd 100644 --- a/src/java/davmail/exchange/ExchangeSession.java +++ b/src/java/davmail/exchange/ExchangeSession.java @@ -1329,9 +1329,14 @@ public class ExchangeSession { } + public class EventResult { + public int status; + public String etag; + } + public int sendEvent(String icsBody) throws IOException { String messageUrl = URIUtil.encodePathQuery(draftsUrl + "/" + UUID.randomUUID().toString() + ".EML"); - int status = internalCreateOrUpdateEvent(messageUrl, icsBody, null, null); + int status = internalCreateOrUpdateEvent(messageUrl, icsBody, null, null).status; if (status != HttpStatus.SC_CREATED) { return status; } else { @@ -1344,12 +1349,12 @@ public class ExchangeSession { } } - public int createOrUpdateEvent(String path, String icsBody, String etag, String noneMatch) throws IOException { + public EventResult createOrUpdateEvent(String path, String icsBody, String etag, String noneMatch) throws IOException { String messageUrl = URIUtil.encodePathQuery(calendarUrl + "/" + URIUtil.decode(path)); return internalCreateOrUpdateEvent(messageUrl, icsBody, etag, noneMatch); } - protected int internalCreateOrUpdateEvent(String messageUrl, String icsBody, String etag, String noneMatch) throws IOException { + protected EventResult internalCreateOrUpdateEvent(String messageUrl, String icsBody, String etag, String noneMatch) throws IOException { String uid = UUID.randomUUID().toString(); PutMethod putmethod = new PutMethod(messageUrl); putmethod.setRequestHeader("Translate", "f"); @@ -1391,7 +1396,12 @@ public class ExchangeSession { } finally { putmethod.releaseConnection(); } - return status; + EventResult eventResult = new EventResult(); + eventResult.status = status; + if (putmethod.getResponseHeader("GetETag") != null) { + eventResult.etag = putmethod.getResponseHeader("GetETag").getValue(); + } + return eventResult; }