diff --git a/src/java/davmail/caldav/CaldavConnection.java b/src/java/davmail/caldav/CaldavConnection.java index 07a34cda..04d635db 100644 --- a/src/java/davmail/caldav/CaldavConnection.java +++ b/src/java/davmail/caldav/CaldavConnection.java @@ -4,18 +4,18 @@ import davmail.AbstractConnection; import davmail.Settings; import davmail.exchange.ExchangeSession; import davmail.exchange.ExchangeSessionFactory; +import davmail.exchange.ICSBufferedReader; import davmail.tray.DavGatewayTray; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.util.URIUtil; import org.apache.commons.httpclient.auth.AuthenticationException; +import org.apache.commons.httpclient.util.URIUtil; import org.apache.log4j.Logger; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.net.Socket; @@ -209,7 +209,12 @@ 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])) { - sendFreeBusy(body); + if (body.indexOf("VFREEBUSY") >=0) { + sendFreeBusy(body); + } else { + int status = session.sendEvent(body); + sendHttpResponse(status, true); + } } else if ("PROPFIND".equals(command) && "users".equals(paths[1]) && paths.length == 4 && "calendar".equals(paths[3])) { sendCalendar(request, depth, paths[2]); } else if ("REPORT".equals(command) && "users".equals(paths[1]) && paths.length == 4 && "calendar".equals(paths[3]) @@ -577,13 +582,10 @@ public class CaldavConnection extends AbstractConnection { public void sendFreeBusy(String body) throws IOException { Map valueMap = new HashMap(); Map keyMap = new HashMap(); - BufferedReader reader = new BufferedReader(new StringReader(body)); + ICSBufferedReader reader = new ICSBufferedReader(new StringReader(body)); String line; - String key = null; + String key; while ((line = reader.readLine()) != null) { - if (line.startsWith(" ") && "ATTENDEE".equals(key)) { - valueMap.put(key, valueMap.get(key) + line.substring(1)); - } else { int index = line.indexOf(':'); if (index <= 0) { throw new IOException("Invalid request: " + body); @@ -598,35 +600,36 @@ public class CaldavConnection extends AbstractConnection { } valueMap.put(key, value); keyMap.put(key, fullkey); - } } String freeBusy = session.getFreebusy(valueMap); if (freeBusy != null) { - String response = "" + - "" + - "" + - "" + - "" + valueMap.get("ATTENDEE") + "" + - "" + - "2.0;Success" + - "BEGIN:VCALENDAR\n" + - "VERSION:2.0\n" + - "PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN\n" + - "METHOD:REPLY\n" + - "BEGIN:VFREEBUSY\n" + - "DTSTAMP:" + valueMap.get("DTSTAMP") + "\n" + - "ORGANIZER:" + valueMap.get("ORGANIZER") + "\n" + - "DTSTART:" + valueMap.get("DTSTART") + "\n" + - "DTEND:" + valueMap.get("DTEND") + "\n" + - "UID:" + valueMap.get("UID") + "\n" + - keyMap.get("ATTENDEE") + ";" + valueMap.get("ATTENDEE") + "\n" + - "FREEBUSY;FBTYPE=BUSY-UNAVAILABLE:" + freeBusy + "\n" + - "END:VFREEBUSY\n" + - "END:VCALENDAR" + - "" + - "" + - ""; - sendHttpResponse(HttpStatus.SC_OK, null, "text/xml;charset=UTF-8", response, true); + StringBuilder response = new StringBuilder(); + + response.append("") + .append("") + .append("") + .append("") + .append("").append(valueMap.get("ATTENDEE")).append("") + .append("") + .append("2.0;Success") + .append("BEGIN:VCALENDAR\n") + .append("VERSION:2.0\n") + .append("PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN\n") + .append("METHOD:REPLY\n") + .append("BEGIN:VFREEBUSY\n") + .append("DTSTAMP:").append(valueMap.get("DTSTAMP")).append("\n") + .append("ORGANIZER:").append(valueMap.get("ORGANIZER")).append("\n") + .append("DTSTART:").append(valueMap.get("DTSTART")).append("\n") + .append("DTEND:").append(valueMap.get("DTEND")).append("\n") + .append("UID:").append(valueMap.get("UID")).append("\n") + .append(keyMap.get("ATTENDEE")).append(";").append(valueMap.get("ATTENDEE")).append("\n") + .append("FREEBUSY;FBTYPE=BUSY-UNAVAILABLE:").append(freeBusy).append("\n") + .append("END:VFREEBUSY\n") + .append("END:VCALENDAR") + .append("") + .append("") + .append(""); + sendHttpResponse(HttpStatus.SC_OK, null, "text/xml;charset=UTF-8", response.toString(), true); } else { sendHttpResponse(HttpStatus.SC_NOT_FOUND, null, "text/plain", "Unknown recipient: " + valueMap.get("ATTENDEE"), true); } diff --git a/src/java/davmail/exchange/ExchangeSession.java b/src/java/davmail/exchange/ExchangeSession.java index af169674..c4ffb6cf 100644 --- a/src/java/davmail/exchange/ExchangeSession.java +++ b/src/java/davmail/exchange/ExchangeSession.java @@ -457,10 +457,10 @@ public class ExchangeSession { * Create message in specified folder. * Will overwrite an existing message with same subject in the same folder * - * @param folderUrl Exchange folder URL - * @param messageName message name - * @param properties message properties (flags) - * @param messageBody mail body + * @param folderUrl Exchange folder URL + * @param messageName message name + * @param properties message properties (flags) + * @param messageBody mail body * @throws java.io.IOException when unable to create message */ public void createMessage(String folderUrl, String messageName, HashMap properties, String messageBody) throws IOException { @@ -1076,23 +1076,23 @@ public class ExchangeSession { String destination = deleteditemsUrl + messageUrl.substring(messageUrl.lastIndexOf("/")); LOGGER.debug("Deleting : " + messageUrl + " to " + destination); // mark message as read - HashMap properties = new HashMap(); + HashMap properties = new HashMap(); properties.put("read", "1"); updateMessage(this, properties); MoveMethod method = new MoveMethod(URIUtil.encodePath(messageUrl), - URIUtil.encodePath(destination)); + URIUtil.encodePath(destination)); method.addRequestHeader("Overwrite", "f"); method.addRequestHeader("Allow-rename", "t"); method.setDebug(4); int status = wdr.retrieveSessionInstance().executeMethod(method); if (status != HttpStatus.SC_CREATED) { - HttpException ex = new HttpException(); + HttpException ex = new HttpException(); ex.setReasonCode(status); ex.setReason(method.getStatusText()); throw ex; } - if (method.getResponseHeader("Location")!= null) { + if (method.getResponseHeader("Location") != null) { destination = method.getResponseHeader("Location").getValue(); } @@ -1328,9 +1328,29 @@ public class ExchangeSession { return line.substring(0, keyIndex) + ";VALUE=DATE:" + line.substring(valueIndex + 1, valueEndIndex); } + + public int sendEvent(String icsBody) throws IOException { + String messageUrl = URIUtil.encodePathQuery(draftsUrl + "/" + UUID.randomUUID().toString() + ".EML"); + int status = internalCreateOrUpdateEvent(messageUrl, icsBody, null, null); + if (status != HttpStatus.SC_CREATED) { + return status; + } else { + boolean sent = wdr.moveMethod(messageUrl, sendmsgUrl); + if (!sent) { + throw new IOException("Unable to send message: " + wdr.getStatusCode() + + " " + wdr.getStatusMessage()); + } + return wdr.getStatusCode(); + } + } + public int createOrUpdateEvent(String path, String icsBody, String etag, String noneMatch) throws IOException { String messageUrl = URIUtil.encodePathQuery(calendarUrl + "/" + URIUtil.decode(path)); - String uid = path.substring(0, path.lastIndexOf(".")); + return internalCreateOrUpdateEvent(messageUrl, icsBody, etag, noneMatch); + } + + protected int 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"); putmethod.setRequestHeader("Overwrite", "f");