davmail/src/java/davmail/exchange/VCalendar.java

206 lines
7.0 KiB
Java
Raw Normal View History

/*
* 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 java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
/**
* VCalendar object.
*/
public class VCalendar extends VObject {
protected VObject firstVevent;
protected VObject vTimezone;
protected String email;
/**
* Create VCalendar object from reader;
*
* @param reader stream reader
* @param email current user email
* @throws IOException on error
*/
public VCalendar(BufferedReader reader, String email) throws IOException {
super(reader);
if (!"VCALENDAR".equals(type)) {
throw new IOException("Invalid type: " + type);
}
this.email = email;
}
/**
* Create VCalendar object from reader;
*
* @param vCalendarBody item body
* @param email current user email
* @throws IOException on error
*/
public VCalendar(String vCalendarBody, String email) throws IOException {
this(new ICSBufferedReader(new StringReader(vCalendarBody)), email);
}
@Override
protected void addVObject(VObject vObject) {
super.addVObject(vObject);
if (firstVevent == null && "VEVENT".equals(vObject.type)) {
firstVevent = vObject;
}
if ("VTIMEZONE".equals(vObject.type)) {
vTimezone = vObject;
}
}
protected boolean isAllDay(VObject vObject) {
VProperty dtstart = vObject.getProperty("DTSTART");
return dtstart != null && dtstart.hasParam("VALUE", "DATE");
}
protected boolean hasCdoAllDay(VObject vObject) {
return vObject.getProperty("X-MICROSOFT-CDO-ALLDAYEVENT") != null;
}
protected boolean hasCdoBusyStatus(VObject vObject) {
return vObject.getProperty("X-MICROSOFT-CDO-BUSYSTATUS") != null;
}
protected boolean isCdoAllDay(VObject vObject) {
return "TRUE".equals(vObject.getPropertyValue("X-MICROSOFT-CDO-ALLDAYEVENT"));
}
protected boolean isAppleiCal() {
return getPropertyValue("PRODID").contains("iCal");
}
protected String getOrganizer() {
String organizer = firstVevent.getPropertyValue("ORGANIZER");
if (organizer.startsWith("MAILTO:")) {
return organizer.substring(7);
} else {
return organizer;
}
}
protected String getMethod() {
return getPropertyValue("METHOD");
}
protected void fixVCalendar(boolean fromServer) {
// append missing method
if (getProperty("METHOD") == null) {
setPropertyValue("METHOD", "PUBLISH");
}
// iCal 4 global private flag
if (fromServer) {
setPropertyValue("X-CALENDARSERVER-ACCESS", getCalendarServerAccess());
}
String calendarServerAccess = getPropertyValue("X-CALENDARSERVER-ACCESS");
// TODO: patch timezone for iPhone
// iterate over vObjects
for (VObject vObject : vObjects) {
if ("VEVENT".equals(vObject.type)) {
if (calendarServerAccess != null) {
vObject.setPropertyValue("CLASS", getEventClass(calendarServerAccess));
} else if (vObject.getPropertyValue("X-CALENDARSERVER-ACCESS") != null) {
vObject.setPropertyValue("CLASS", getEventClass(vObject.getPropertyValue("X-CALENDARSERVER-ACCESS")));
}
if (!fromServer) {
// add organizer line to all events created in Exchange for active sync
if (vObject.getPropertyValue("ORGANIZER") == null) {
vObject.setPropertyValue("ORGANIZER", "MAILTO:" + email);
}
// set OWA allday flag
vObject.setPropertyValue("X-MICROSOFT-CDO-ALLDAYEVENT", isAllDay(vObject) ? "TRUE" : "FALSE");
fixAttendees(vObject);
} else {
// remove organizer line for event without attendees for iPhone
if (getProperty("ATTENDEE") == null) {
vObject.setPropertyValue("ORGANIZER", null);
}
}
}
}
}
/**
* Replace iCal4 (Snow Leopard) principal paths with mailto expression
*
* @param value attendee value or ics line
* @return fixed value
*/
protected String replaceIcal4Principal(String value) {
if (value.contains("/principals/__uuids__/")) {
return value.replaceAll("/principals/__uuids__/([^/]*)__AT__([^/]*)/", "mailto:$1@$2");
} else {
return value;
}
}
private void fixAttendees(VObject vObject) {
if (properties != null) {
for (VProperty property : properties) {
if ("ATTENDEE".equalsIgnoreCase(property.getKey())) {
property.setValue(replaceIcal4Principal(property.getValue()));
// ignore attendee as organizer
if (property.getValue().contains(email)) {
property.setValue(null);
}
}
}
}
}
/**
* Convert X-CALENDARSERVER-ACCESS to CLASS.
*
* @return CLASS value
*/
protected String getEventClass(String calendarServerAccess) {
if ("PRIVATE".equalsIgnoreCase(calendarServerAccess)) {
return "CONFIDENTIAL";
} else if ("CONFIDENTIAL".equalsIgnoreCase(calendarServerAccess) || "RESTRICTED".equalsIgnoreCase(calendarServerAccess)) {
return "PRIVATE";
} else {
return calendarServerAccess;
}
}
/**
* Convert CLASS to X-CALENDARSERVER-ACCESS.
*
* @return X-CALENDARSERVER-ACCESS value
*/
protected String getCalendarServerAccess() {
String eventClass = firstVevent.getPropertyValue("CLASS");
if ("PRIVATE".equalsIgnoreCase(eventClass)) {
return "CONFIDENTIAL";
} else if ("CONFIDENTIAL".equalsIgnoreCase(eventClass)) {
return "PRIVATE";
} else {
return eventClass;
}
}
}