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:
parent
88d93893d9
commit
cb2b6baac3
@ -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;
|
||||
|
@ -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>();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user