1
0
mirror of https://github.com/moparisthebest/davmail synced 2024-12-13 11:12:22 -05:00

Caldav: failover for broken event, rebuild VCalendar content from raw properties

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1439 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2010-09-13 16:07:49 +00:00
parent 88d93893d9
commit cb2b6baac3
5 changed files with 148 additions and 10 deletions

View File

@ -84,8 +84,15 @@ public class VCalendar extends VObject {
this(new ICSBufferedReader(new InputStreamReader(new ByteArrayInputStream(vCalendarContent), "UTF-8")), email, vTimezone);
}
/**
* Empty constructor
*/
public VCalendar() {
type="VCALENDAR";
}
@Override
protected void addVObject(VObject vObject) {
public void addVObject(VObject vObject) {
super.addVObject(vObject);
if (firstVevent == null && "VEVENT".equals(vObject.type)) {
firstVevent = vObject;

View File

@ -84,6 +84,9 @@ public class VObject {
this(new ICSBufferedReader(new StringReader(itemBody)));
}
public VObject() {
}
protected void handleLine(String line, BufferedReader reader) throws IOException {
// skip empty lines
@ -98,14 +101,14 @@ public class VObject {
}
}
protected void addVObject(VObject vObject) {
public void addVObject(VObject vObject) {
if (vObjects == null) {
vObjects = new ArrayList<VObject>();
}
vObjects.add(vObject);
}
protected void addProperty(VProperty property) {
public void addProperty(VProperty property) {
if (property.getValue() != null) {
if (properties == null) {
properties = new ArrayList<VProperty>();

View File

@ -230,7 +230,7 @@ public class VProperty {
addParam(paramName, (String) null);
}
protected void addParam(String paramName, String paramValue) {
public void addParam(String paramName, String paramValue) {
List<String> paramValues = new ArrayList<String>();
paramValues.add(paramValue);
addParam(paramName, paramValues);

View File

@ -24,9 +24,7 @@ import davmail.exception.DavMailAuthenticationException;
import davmail.exception.DavMailException;
import davmail.exception.HttpNotFoundException;
import davmail.exception.InsufficientStorageException;
import davmail.exchange.ExchangeSession;
import davmail.exchange.VObject;
import davmail.exchange.XMLStreamUtil;
import davmail.exchange.*;
import davmail.http.DavGatewayHttpClientFacade;
import davmail.ui.tray.DavGatewayTray;
import davmail.util.IOUtil;
@ -49,6 +47,7 @@ import org.apache.jackrabbit.webdav.property.DavPropertySet;
import org.w3c.dom.Node;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimePart;
@ -1279,7 +1278,7 @@ public class DavExchangeSession extends ExchangeSession {
*/
@Override
public byte[] getEventContent() throws IOException {
byte[] result;
byte[] result = null;
LOGGER.debug("Get event subject: " + subject + " permanentUrl: " + permanentUrl);
// try to get PR_INTERNET_CONTENT
try {
@ -1298,11 +1297,105 @@ public class DavExchangeSession extends ExchangeSession {
} catch (DavException e) {
throw buildHttpException(e);
} catch (IOException e) {
deleteBroken();
throw buildHttpException(e);
LOGGER.warn(e.getMessage());
} catch (MessagingException e) {
throw buildHttpException(e);
}
// failover: rebuild event from MAPI properties
if (result == null) {
result = getICSFromItemProperties();
}
// debug code
//if (new String(result).indexOf("VTODO") < 0) {
// LOGGER.debug("Rebuilt body: " + new String(getICSFromItemProperties()));
//}
return result;
}
private byte[] getICSFromItemProperties() throws IOException {
byte[] result = null;
// experimental: build VCALENDAR from properties
DavPropertyNameSet davPropertyNameSet = new DavPropertyNameSet();
davPropertyNameSet.add(Field.getPropertyName("method"));
davPropertyNameSet.add(Field.getPropertyName("created"));
davPropertyNameSet.add(Field.getPropertyName("calendarlastmodified"));
davPropertyNameSet.add(Field.getPropertyName("dtstamp"));
davPropertyNameSet.add(Field.getPropertyName("calendaruid"));
davPropertyNameSet.add(Field.getPropertyName("subject"));
davPropertyNameSet.add(Field.getPropertyName("dtstart"));
davPropertyNameSet.add(Field.getPropertyName("dtend"));
davPropertyNameSet.add(Field.getPropertyName("transparent"));
davPropertyNameSet.add(Field.getPropertyName("organizer"));
davPropertyNameSet.add(Field.getPropertyName("to"));
davPropertyNameSet.add(Field.getPropertyName("description"));
davPropertyNameSet.add(Field.getPropertyName("alldayevent"));
davPropertyNameSet.add(Field.getPropertyName("busystatus"));
PropFindMethod propFindMethod = new PropFindMethod(permanentUrl, davPropertyNameSet, 0);
try {
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executeMethod(httpClient, propFindMethod);
if (responses.length == 0) {
throw new HttpNotFoundException(permanentUrl + " not found");
}
DavPropertySet davPropertySet = responses[0].getProperties(HttpStatus.SC_OK);
VCalendar localVCalendar = new VCalendar();
localVCalendar.setPropertyValue("PRODID", "-//davmail.sf.net/NONSGML DavMail Calendar V1.1//EN");
localVCalendar.setPropertyValue("VERSION", "2.0");
localVCalendar.setPropertyValue("METHOD", getPropertyIfExists(davPropertySet, "method"));
VObject vEvent = new VObject();
vEvent.type = "VEVENT";
vEvent.setPropertyValue("CREATED", convertDateFromExchange(getPropertyIfExists(davPropertySet, "created")));
vEvent.setPropertyValue("LAST-MODIFIED", convertDateFromExchange(getPropertyIfExists(davPropertySet, "calendarlastmodified")));
vEvent.setPropertyValue("DTSTAMP", convertDateFromExchange(getPropertyIfExists(davPropertySet, "dtstamp")));
vEvent.setPropertyValue("UID", getPropertyIfExists(davPropertySet, "calendaruid"));
vEvent.setPropertyValue("SUMMARY", getPropertyIfExists(davPropertySet, "subject"));
vEvent.setPropertyValue("DTSTART", convertDateFromExchange(getPropertyIfExists(davPropertySet, "dtstart")));
vEvent.setPropertyValue("DTEND", convertDateFromExchange(getPropertyIfExists(davPropertySet, "dtend")));
vEvent.setPropertyValue("TRANSP", getPropertyIfExists(davPropertySet, "transparent"));
String organizer = getPropertyIfExists(davPropertySet, "organizer");
String organizerEmail = null;
if (organizer != null) {
InternetAddress organizerAddress = new InternetAddress(organizer);
organizerEmail = organizerAddress.getAddress();
vEvent.setPropertyValue("ORGANIZER", "MAILTO:" + organizerEmail);
}
// Parse attendee list
String toHeader = getPropertyIfExists(davPropertySet, "to");
if (toHeader != null && !organizerEmail.equals(toHeader)) {
InternetAddress[] attendees = InternetAddress.parseHeader(toHeader, false);
for (InternetAddress attendee : attendees) {
if (!attendee.getAddress().equalsIgnoreCase(organizerEmail)) {
VProperty vProperty = new VProperty("ATTENDEE", attendee.getAddress());
if (attendee.getPersonal() != null) {
vProperty.addParam("CN", attendee.getPersonal());
}
vEvent.addProperty(vProperty);
}
}
}
vEvent.setPropertyValue("DESCRIPTION", getPropertyIfExists(davPropertySet, "description"));
vEvent.setPropertyValue("X-MICROSOFT-CDO-ALLDAYEVENT",
"1".equals(getPropertyIfExists(davPropertySet, "alldayevent")) ? "TRUE" : "FALSE");
vEvent.setPropertyValue("X-MICROSOFT-CDO-BUSYSTATUS", getPropertyIfExists(davPropertySet, "busystatus"));
localVCalendar.addVObject(vEvent);
result = localVCalendar.toString().getBytes("UTF-8");
} catch (MessagingException e) {
LOGGER.warn("Unable to rebuild event content: " + e.getMessage(), e);
throw buildHttpException(e);
} catch (IOException e) {
LOGGER.warn("Unable to rebuild event content: " + e.getMessage(), e);
throw buildHttpException(e);
} finally {
propFindMethod.releaseConnection();
}
return result;
}

View File

@ -160,8 +160,43 @@ public class Field {
createField(URN_SCHEMAS_CALENDAR, "instancetype"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:instancetype/Integer
createField(URN_SCHEMAS_CALENDAR, "dtstart"); // 0x10C3 SystemTime
createField(URN_SCHEMAS_CALENDAR, "dtend"); // 0x10C4 SystemTime
//createField(URN_SCHEMAS_CALENDAR, "prodid"); // // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:prodid/String
createField("calendarversion", URN_SCHEMAS_CALENDAR, "version"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:version/String
createField(URN_SCHEMAS_CALENDAR, "method"); // // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:method/String
createField("calendarlastmodified", URN_SCHEMAS_CALENDAR, "lastmodified"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:isorganizer/Boolean
createField(URN_SCHEMAS_CALENDAR, "dtstamp"); // PidLidOwnerCriticalChange
createField("calendaruid", URN_SCHEMAS_CALENDAR, "uid"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:uid/String
createField(URN_SCHEMAS_CALENDAR, "transparent"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:transparent/String
createField(URN_SCHEMAS_CALENDAR, "organizer");
createField(URN_SCHEMAS_CALENDAR, "created"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:created/SystemTime
createField(URN_SCHEMAS_CALENDAR, "alldayevent"); // DistinguishedPropertySetType.Appointment/0x8215 Boolean
// TODO
createField(SCHEMAS_MAPI, "allattendeesstring"); // PidLidAllAttendeesString
createField(SCHEMAS_MAPI, "required_attendees"); // PidLidRequiredAttendees
createField(SCHEMAS_MAPI, "apptendtime"); // PidLidAppointmentEndTime
createField(SCHEMAS_MAPI, "apptstateflags"); // PidLidAppointmentStateFlags 1: Meeting, 2: Received, 4: Cancelled
createField(URN_SCHEMAS_CALENDAR, "isorganizer"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:isorganizer/Boolean
createField(URN_SCHEMAS_CALENDAR, "location"); // DistinguishedPropertySetType.Appointment/0x8208 String
createField(URN_SCHEMAS_CALENDAR, "attendeerole"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:attendeerole/Integer
createField(URN_SCHEMAS_CALENDAR, "busystatus"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:busystatus/String
createField(URN_SCHEMAS_CALENDAR, "exdate"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:exdate/PtypMultipleTime
createField(URN_SCHEMAS_CALENDAR, "exrule"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:exrule/PtypMultipleString
createField(URN_SCHEMAS_CALENDAR, "recurrenceidrange"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:recurrenceidrange/String
createField(URN_SCHEMAS_CALENDAR, "rdate"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:rdate/PtypMultipleTime
createField(URN_SCHEMAS_CALENDAR, "rrule"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:rrule/PtypMultipleString
createField(URN_SCHEMAS_CALENDAR, "reminderoffset"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:reminderoffset/Integer
createField(URN_SCHEMAS_CALENDAR, "timezone"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:timezone/String
createField(SCHEMAS_EXCHANGE, "sensitivity"); // PR_SENSITIVITY 0x0036 Integer
createField(URN_SCHEMAS_CALENDAR, "timezoneid"); // DistinguishedPropertySetType.PublicStrings/urn:schemas:calendar:timezoneid/Integer
// should use PidLidServerProcessed ?
createField("processed", 0x65e8, PropertyType.Boolean);// PR_MESSAGE_PROCESSED
createField(DAV, "contentclass");