389 lines
16 KiB
Java
389 lines
16 KiB
Java
/*
|
|
* DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
|
|
* Copyright (C) 2010 Mickael Guessant
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
package davmail.exchange;
|
|
|
|
import davmail.BundleMessage;
|
|
import junit.framework.TestCase;
|
|
|
|
import java.io.IOException;
|
|
import java.io.StringReader;
|
|
|
|
/**
|
|
* Test ExchangeSession event conversion.
|
|
*/
|
|
@SuppressWarnings({"UseOfSystemOutOrSystemErr"})
|
|
public class TestExchangeSessionEvent extends TestCase {
|
|
static String email = "user@company.com";
|
|
static VObject vTimeZone;
|
|
|
|
static {
|
|
try {
|
|
vTimeZone = new VObject(new ICSBufferedReader(new StringReader("BEGIN:VTIMEZONE\n" +
|
|
"TZID:(GMT+01.00) Paris/Madrid/Brussels/Copenhagen\n" +
|
|
"X-MICROSOFT-CDO-TZID:3\n" +
|
|
"BEGIN:STANDARD\n" +
|
|
"DTSTART:16010101T030000\n" +
|
|
"TZOFFSETFROM:+0200\n" +
|
|
"TZOFFSETTO:+0100\n" +
|
|
"RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=10;BYDAY=-1SU\n" +
|
|
"END:STANDARD\n" +
|
|
"BEGIN:DAYLIGHT\n" +
|
|
"DTSTART:16010101T020000\n" +
|
|
"TZOFFSETFROM:+0100\n" +
|
|
"TZOFFSETTO:+0200\n" +
|
|
"RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=-1SU\n" +
|
|
"END:DAYLIGHT\n" +
|
|
"END:VTIMEZONE")));
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
|
|
protected String fixICS(String icsBody, boolean fromServer) throws IOException {
|
|
VCalendar vCalendar = new VCalendar(icsBody, email, vTimeZone);
|
|
vCalendar.fixVCalendar(fromServer);
|
|
return vCalendar.toString();
|
|
}
|
|
|
|
public void testNoClass() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
String toClient = fixICS(itemBody, true);
|
|
System.out.println(toServer);
|
|
System.out.println(toClient);
|
|
assertTrue(toServer.indexOf("CLASS") < 0);
|
|
assertTrue(toClient.indexOf("CLASS") < 0);
|
|
assertTrue(toClient.indexOf("X-CALENDARSERVER-ACCESS") < 0);
|
|
}
|
|
|
|
public void testPublicClass() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"CLASS:PUBLIC\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
String toClient = fixICS(itemBody, true);
|
|
System.out.println(toServer);
|
|
System.out.println(toClient);
|
|
assertTrue(toServer.indexOf("CLASS:PUBLIC") >= 0);
|
|
assertTrue(toClient.indexOf("CLASS:PUBLIC") >= 0);
|
|
assertTrue(toClient.indexOf("X-CALENDARSERVER-ACCESS:PUBLIC") >= 0);
|
|
}
|
|
|
|
public void testPrivateClass() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"CLASS:PRIVATE\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
String toClient = fixICS(itemBody, true);
|
|
System.out.println(toServer);
|
|
System.out.println(toClient);
|
|
assertTrue(toServer.indexOf("CLASS:PRIVATE") >= 0);
|
|
assertTrue(toClient.indexOf("CLASS:PRIVATE") >= 0);
|
|
assertTrue(toClient.indexOf("X-CALENDARSERVER-ACCESS:CONFIDENTIAL") >= 0);
|
|
}
|
|
|
|
public void testConfidentialClass() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"CLASS:CONFIDENTIAL\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
String toClient = fixICS(itemBody, true);
|
|
System.out.println(toServer);
|
|
System.out.println(toClient);
|
|
assertTrue(toServer.indexOf("CLASS:CONFIDENTIAL") >= 0);
|
|
assertTrue(toClient.indexOf("CLASS:CONFIDENTIAL") >= 0);
|
|
assertTrue(toClient.indexOf("X-CALENDARSERVER-ACCESS:PRIVATE") >= 0);
|
|
}
|
|
|
|
public void testCalendarServerAccessPrivate() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"PRODID:-//Apple Inc.//iCal 4.0.3//EN\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"X-CALENDARSERVER-ACCESS:PRIVATE\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
System.out.println(toServer);
|
|
assertTrue(toServer.indexOf("CLASS:CONFIDENTIAL") >= 0);
|
|
}
|
|
|
|
public void testCalendarServerAccessConfidential() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"PRODID:-//Apple Inc.//iCal 4.0.3//EN\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"X-CALENDARSERVER-ACCESS:CONFIDENTIAL\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
System.out.println(toServer);
|
|
assertTrue(toServer.indexOf("CLASS:PRIVATE") >= 0);
|
|
}
|
|
|
|
public void testCalendarServerAccessPublic() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"PRODID:-//Apple Inc.//iCal 4.0.3//EN\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"X-CALENDARSERVER-ACCESS:PUBLIC\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
System.out.println(toServer);
|
|
assertTrue(toServer.indexOf("CLASS:PUBLIC") >= 0);
|
|
}
|
|
|
|
public void testCalendarServerAccessNone() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"PRODID:-//Apple Inc.//iCal 4.0.3//EN\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
System.out.println(toServer);
|
|
assertFalse(toServer.contains("CLASS"));
|
|
}
|
|
|
|
public void testNoOrganizer() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
System.out.println(toServer);
|
|
assertTrue(toServer.contains("ORGANIZER"));
|
|
}
|
|
|
|
|
|
public void testValarm() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"BEGIN:VALARM\n" +
|
|
"TRIGGER:-PT15M\n" +
|
|
"ATTACH;VALUE=URI:Basso\n" +
|
|
"ACTION:AUDIO\n" +
|
|
"END:VALARM\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
System.out.println(toServer);
|
|
assertTrue(toServer.contains("ACTION:DISPLAY"));
|
|
}
|
|
|
|
public void testReceiveAllDay() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
vTimeZone +
|
|
"BEGIN:VEVENT\n" +
|
|
"DTSTART;TZID=\"(GMT+01.00) Paris/Madrid/Brussels/Copenhagen\":20100615T000000\n" +
|
|
"DTEND;TZID=\"(GMT+01.00) Paris/Madrid/Brussels/Copenhagen\":20100616T000000\n" +
|
|
"X-MICROSOFT-CDO-ALLDAYEVENT:TRUE\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toClient = fixICS(itemBody, true);
|
|
System.out.println(toClient);
|
|
// OWA created allday events have the X-MICROSOFT-CDO-ALLDAYEVENT set to true and always 000000 in event time
|
|
// just remove the TZID, add VALUE=DATE param and set a date only value
|
|
assertTrue(toClient.contains("DTSTART;VALUE=DATE:20100615"));
|
|
assertTrue(toClient.contains("DTEND;VALUE=DATE:20100616"));
|
|
}
|
|
|
|
public void testSendAllDay() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"DTSTART;VALUE=DATE:20100615\n" +
|
|
"DTEND;VALUE=DATE:20100616\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
System.out.println(toServer);
|
|
// Client created allday event have no timezone and no time information in date values
|
|
// first set the X-MICROSOFT-CDO-ALLDAYEVENT flag for OWA
|
|
assertTrue(toServer.contains("X-MICROSOFT-CDO-ALLDAYEVENT:TRUE"));
|
|
// then patch TZID for Outlook (need to retrieve OWA TZID
|
|
assertTrue(toServer.contains("BEGIN:VTIMEZONE"));
|
|
assertTrue(toServer.contains("TZID:" + vTimeZone.getPropertyValue("TZID")));
|
|
assertTrue(toServer.contains("DTSTART;TZID=\"" + vTimeZone.getPropertyValue("TZID") + "\":20100615T000000"));
|
|
assertTrue(toServer.contains("DTEND;TZID=\"" + vTimeZone.getPropertyValue("TZID") + "\":20100616T000000"));
|
|
}
|
|
|
|
public void testRsvp() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"ATTENDEE;PARTSTAT=ACCEPTED;RSVP=TRUE:MAILTO:" + email + "\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toClient = fixICS(itemBody, true);
|
|
System.out.println(toClient);
|
|
assertTrue(toClient.contains("ATTENDEE;PARTSTAT=ACCEPTED:MAILTO:" + email));
|
|
}
|
|
|
|
public void testExdate() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"EXDATE;TZID=\"Europe/Paris\":20100809T150000,20100823T150000\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toClient = fixICS(itemBody, true);
|
|
System.out.println(toClient);
|
|
assertTrue(toClient.contains("EXDATE;TZID=\"Europe/Paris\":20100823T150000"));
|
|
|
|
}
|
|
|
|
public void testEmptyLine() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toClient = fixICS(itemBody, true);
|
|
System.out.println(toClient);
|
|
}
|
|
|
|
public void testAttendeeStatus() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"ATTENDEE;PARTSTAT=ACCEPTED;RSVP=FALSE:MAILTO:" + email + "\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
VCalendar vCalendar = new VCalendar(itemBody, email, vTimeZone);
|
|
vCalendar.fixVCalendar(false);
|
|
String status = vCalendar.getAttendeeStatus();
|
|
assertEquals("ACCEPTED", status);
|
|
System.out.println("'" + BundleMessage.format(status) + "'");
|
|
}
|
|
|
|
public void testMissingTzid() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"DTSTART:20100101T000000\n" +
|
|
"DTEND:20100102T000000\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, false);
|
|
System.out.println(toServer);
|
|
assertTrue(toServer.contains("DTSTART;TZID="));
|
|
assertTrue(toServer.contains("DTEND;TZID="));
|
|
}
|
|
|
|
public void testBroken() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN\n" +
|
|
"VERSION:2.0\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"CREATED:20100916T115132Z\n" +
|
|
"LAST-MODIFIED:20100916T115138Z\n" +
|
|
"DTSTAMP:20100916T115138Z\n" +
|
|
"UID:d72ff8cc-f3ee-4fbc-b44d-1aaf78d92847\n" +
|
|
"SUMMARY:New Event\n" +
|
|
"DTSTART;VALUE=DATE:20100929\n" +
|
|
"DTEND;VALUE=DATE:20100930\n" +
|
|
"TRANSP:TRANSPARENT\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, true);
|
|
System.out.println(toServer);
|
|
}
|
|
|
|
public void testFloatingTimezone() throws IOException {
|
|
String itemBody = "BEGIN:VCALENDAR\n" +
|
|
"PRODID:Microsoft CDO for Microsoft Exchange\n" +
|
|
"VERSION:2.0\n" +
|
|
"BEGIN:VTIMEZONE\n" +
|
|
"TZID:Pacific Time (US & Canada)\\; Tijuana\n" +
|
|
"BEGIN:STANDARD\n" +
|
|
"DTSTART:16010101T030000\n" +
|
|
"TZOFFSETFROM:-0700\n" +
|
|
"TZOFFSETTO:-0800\n" +
|
|
"RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=11;BYDAY=1SU\n" +
|
|
"END:STANDARD\n" +
|
|
"BEGIN:DAYLIGHT\n" +
|
|
"DTSTART:16010101T010000\n" +
|
|
"TZOFFSETFROM:-0800\n" +
|
|
"TZOFFSETTO:-0700\n" +
|
|
"RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=2SU\n" +
|
|
"END:DAYLIGHT\n" +
|
|
"END:VTIMEZONE" +
|
|
"BEGIN:VEVENT\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toServer = fixICS(itemBody, true);
|
|
System.out.println(toServer);
|
|
}
|
|
|
|
public void testAnotherBroken() throws IOException {
|
|
String icsBody = "BEGIN:VCALENDAR\n" +
|
|
"METHOD:PUBLISH\n" +
|
|
"PRODID:Microsoft Exchange Server 2010\n" +
|
|
"VERSION:2.0\n" +
|
|
"BEGIN:VTIMEZONE\n" +
|
|
"TZID:GMT -0800 (Standard) / GMT -0700 (Daylight)\\n\n" +
|
|
"BEGIN:STANDARD\n" +
|
|
"DTSTART:16010101T020000\n" +
|
|
"TZOFFSETFROM:-0700\n" +
|
|
"TZOFFSETTO:-0800\n" +
|
|
"RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11\n" +
|
|
"END:STANDARD\n" +
|
|
"BEGIN:DAYLIGHT\n" +
|
|
"DTSTART:16010101T020000\n" +
|
|
"TZOFFSETFROM:-0800\n" +
|
|
"TZOFFSETTO:-0700\n" +
|
|
"RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3\n" +
|
|
"END:DAYLIGHT\n" +
|
|
"END:VTIMEZONE\n" +
|
|
"BEGIN:VEVENT\n" +
|
|
"ORGANIZER;CN=John Doe:MAILTO:aTargetAddress@dummy.com\n" +
|
|
"DESCRIPTION;LANGUAGE=en-US:Look over broken timezone.\\n\n" +
|
|
"SUMMARY;LANGUAGE=en-US:meeting\n" +
|
|
"DTSTART;TZID=GMT -0800 (Standard) / GMT -0700 (Daylight)\n" +
|
|
":20060210T130000\n" +
|
|
"DTEND;TZID=GMT -0800 (Standard) / GMT -0700 (Daylight)\n" +
|
|
":20060210T143000\n" +
|
|
"UID:040000008200E00074C5B7101A82E00800000000D01FF309972CC601000000000000000\n" +
|
|
" 010000000B389A3C5092D7640A06D2EF5A2125577\n" +
|
|
"CLASS:PUBLIC\n" +
|
|
"PRIORITY:5\n" +
|
|
"DTSTAMP:20060208T180425Z\n" +
|
|
"TRANSP:OPAQUE\n" +
|
|
"STATUS:CONFIRMED\n" +
|
|
"SEQUENCE:0\n" +
|
|
"LOCATION;LANGUAGE=en-US:not sure\n" +
|
|
"X-MICROSOFT-CDO-APPT-SEQUENCE:0\n" +
|
|
"X-MICROSOFT-CDO-OWNERAPPTID:1602758614\n" +
|
|
"X-MICROSOFT-CDO-BUSYSTATUS:BUSY\n" +
|
|
"X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY\n" +
|
|
"X-MICROSOFT-CDO-ALLDAYEVENT:FALSE\n" +
|
|
"X-MICROSOFT-CDO-IMPORTANCE:1\n" +
|
|
"X-MICROSOFT-CDO-INSTTYPE:0\n" +
|
|
"X-MICROSOFT-DISALLOW-COUNTER:FALSE\n" +
|
|
"END:VEVENT\n" +
|
|
"END:VCALENDAR";
|
|
String toClient = fixICS(icsBody, true);
|
|
System.out.println(toClient);
|
|
|
|
}
|
|
}
|