From 70039c8cb0b2e3ab22d988693fe5b1b77d1eb1a9 Mon Sep 17 00:00:00 2001 From: mguessan Date: Mon, 2 Nov 2009 22:56:08 +0000 Subject: [PATCH] Caldav: get current VTIMEZONE body from OWA to create Allday events compatible with Outlook. Users still need to select the same Timezone in Outlook and OWA. git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@815 3d1905a2-6b24-0410-a738-b14d5a86fcbd --- .../davmail/exchange/ExchangeSession.java | 73 +++++++++++++++++++ .../davmail/exchange/ICSBufferedWriter.java | 11 +++ 2 files changed, 84 insertions(+) diff --git a/src/java/davmail/exchange/ExchangeSession.java b/src/java/davmail/exchange/ExchangeSession.java index 3be9a8a9..f2c459ad 100644 --- a/src/java/davmail/exchange/ExchangeSession.java +++ b/src/java/davmail/exchange/ExchangeSession.java @@ -20,6 +20,7 @@ package davmail.exchange; import davmail.BundleMessage; import davmail.Settings; +import davmail.util.StringUtil; import davmail.exception.DavMailAuthenticationException; import davmail.exception.DavMailException; import davmail.http.DavGatewayHttpClientFacade; @@ -1895,6 +1896,8 @@ public class ExchangeSession { boolean isAppleiCal = false; boolean hasAttendee = false; boolean hasCdoBusyStatus = false; + // detect ics event with empty timezone (all day from Lightning) + boolean hasTimezone = false; String transp = null; String validTimezoneId = null; String eventClass = null; @@ -1957,6 +1960,8 @@ public class ExchangeSession { } } else if ("X-MICROSOFT-CDO-BUSYSTATUS".equals(key)) { hasCdoBusyStatus = true; + } else if ("BEGIN:VTIMEZONE".equals(line)) { + hasTimezone = true; } } } @@ -1981,6 +1986,10 @@ public class ExchangeSession { if (validTimezoneId != null && line.indexOf(";TZID=") >= 0) { line = fixTimezoneId(line, validTimezoneId); } + if (!fromServer && "BEGIN:VEVENT".equals(line) && !hasTimezone) { + result.write(ExchangeSession.this.getVTimezone().timezoneBody); + hasTimezone = true; + } if (!fromServer && currentAllDayState.isAllDay && "X-MICROSOFT-CDO-ALLDAYEVENT:FALSE".equals(line)) { line = "X-MICROSOFT-CDO-ALLDAYEVENT:TRUE"; } else if (!fromServer && "END:VEVENT".equals(line)) { @@ -2002,6 +2011,10 @@ public class ExchangeSession { line = getAllDayLine(line); } else if (fromServer && currentAllDayState.isCdoAllDay && line.startsWith("DTEND") && !line.startsWith("DTEND;VALUE=DATE")) { line = getAllDayLine(line); + } else if (!fromServer && currentAllDayState.isAllDay && line.startsWith("DTSTART") && line.startsWith("DTSTART;VALUE=DATE")) { + line = "DTSTART;TZID=\""+ExchangeSession.this.getVTimezone().timezoneId+"\":" + line.substring(19) + "T000000"; + } else if (!fromServer && currentAllDayState.isAllDay && line.startsWith("DTEND") && line.startsWith("DTEND;VALUE=DATE")) { + line = "DTEND;TZID=\""+ExchangeSession.this.getVTimezone().timezoneId+"\":" + line.substring(17) + "T000000"; } else if (line.startsWith("TZID:") && validTimezoneId != null) { line = "TZID:" + validTimezoneId; } else if ("BEGIN:VEVENT".equals(line)) { @@ -3160,6 +3173,66 @@ public class ExchangeSession { } } + protected final class VTimezone { + private String timezoneBody; + private String timezoneId; + + /** + * create a fake event to get VTIMEZONE body + */ + private void load() { + try { + // create temporary folder + String folderPath = ExchangeSession.this.getFolderPath("davmailtemp"); + ExchangeSession.this.createCalendarFolder(folderPath); + + PostMethod postMethod = new PostMethod(folderPath); + postMethod.addParameter("Cmd", "saveappt"); + postMethod.addParameter("FORMTYPE", "appointment"); + String fakeEventUrl = null; + try { + // create fake event + int statusCode = ExchangeSession.this.httpClient.executeMethod(postMethod); + if (statusCode == HttpStatus.SC_OK) { + fakeEventUrl = StringUtil.getToken(postMethod.getResponseBodyAsString(), "", ""); + } + } finally { + postMethod.releaseConnection(); + } + if (fakeEventUrl != null) { + // get fake event body + GetMethod getMethod = new GetMethod(URIUtil.encodePath(fakeEventUrl)); + getMethod.setRequestHeader("Translate", "f"); + try { + ExchangeSession.this.httpClient.executeMethod(getMethod); + timezoneBody = "BEGIN:VTIMEZONE" + + StringUtil.getToken(getMethod.getResponseBodyAsString(), "BEGIN:VTIMEZONE", "END:VTIMEZONE") + + "END:VTIMEZONE\r\n"; + timezoneId = StringUtil.getToken(timezoneBody, "TZID:", "\r\n"); + } finally { + getMethod.releaseConnection(); + } + } + + // delete temporary folder + ExchangeSession.this.deleteFolder("davmailtemp"); + } catch (IOException e) { + LOGGER.warn("Unable to get VTIMEZONE info: " + e, e); + } + } + } + + protected VTimezone vTimezone; + + protected VTimezone getVTimezone() { + if (vTimezone == null) { + // need to load Timezone info from OWA + vTimezone = new VTimezone(); + vTimezone.load(); + } + return vTimezone; + } + /** * Return internal HttpClient instance * diff --git a/src/java/davmail/exchange/ICSBufferedWriter.java b/src/java/davmail/exchange/ICSBufferedWriter.java index 2348f1c3..3535bcec 100644 --- a/src/java/davmail/exchange/ICSBufferedWriter.java +++ b/src/java/davmail/exchange/ICSBufferedWriter.java @@ -25,6 +25,17 @@ package davmail.exchange; public class ICSBufferedWriter { final StringBuilder buffer = new StringBuilder(); + /** + * Write content to buffer, do not split lines. + * + * @param content ics content + */ + public void write(String content) { + if (content != null) { + buffer.append(content); + } + } + /** * Write line to buffer, split lines at 75 characters. *