mirror of
https://github.com/moparisthebest/davmail
synced 2024-11-12 04:15:08 -05:00
Caldav: Implement Carddav create (only a few attributes mapped)
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1036 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
0faf2497db
commit
956f1b26a0
@ -263,8 +263,8 @@ public class CaldavConnection extends AbstractConnection {
|
||||
} else if (request.isPut()) {
|
||||
String etag = request.getHeader("if-match");
|
||||
String noneMatch = request.getHeader("if-none-match");
|
||||
ExchangeSession.EventResult eventResult = session.createOrUpdateEvent(request.getExchangeFolderPath(), lastPath, request.getBody(), etag, noneMatch);
|
||||
sendHttpResponse(eventResult.status, buildEtagHeader(eventResult.etag), null, "", true);
|
||||
ExchangeSession.ItemResult itemResult = session.createOrUpdateItem(request.getExchangeFolderPath(), lastPath, request.getBody(), etag, noneMatch);
|
||||
sendHttpResponse(itemResult.status, buildEtagHeader(itemResult.etag), null, "", true);
|
||||
|
||||
} else if (request.isDelete()) {
|
||||
int status = session.deleteEvent(request.getExchangeFolderPath(), lastPath);
|
||||
|
@ -103,6 +103,7 @@ public class ExchangeSession {
|
||||
|
||||
protected static final int FREE_BUSY_INTERVAL = 15;
|
||||
|
||||
protected static final Namespace DAV = Namespace.getNamespace("DAV:");
|
||||
protected static final Namespace URN_SCHEMAS_HTTPMAIL = Namespace.getNamespace("urn:schemas:httpmail:");
|
||||
protected static final Namespace SCHEMAS_EXCHANGE = Namespace.getNamespace("http://schemas.microsoft.com/exchange/");
|
||||
protected static final Namespace SCHEMAS_MAPI_PROPTAG = Namespace.getNamespace("http://schemas.microsoft.com/mapi/proptag/");
|
||||
@ -114,7 +115,7 @@ public class ExchangeSession {
|
||||
static {
|
||||
EVENT_REQUEST_PROPERTIES.add(DavPropertyName.create("permanenturl", SCHEMAS_EXCHANGE));
|
||||
EVENT_REQUEST_PROPERTIES.add(DavPropertyName.GETETAG);
|
||||
EVENT_REQUEST_PROPERTIES.add(DavPropertyName.create("contentclass", Namespace.getNamespace("DAV:")));
|
||||
EVENT_REQUEST_PROPERTIES.add(DavPropertyName.create("contentclass", DAV));
|
||||
}
|
||||
|
||||
protected static final DavPropertyNameSet WELL_KNOWN_FOLDERS = new DavPropertyNameSet();
|
||||
@ -138,7 +139,7 @@ public class ExchangeSession {
|
||||
protected static final DavPropertyNameSet FOLDER_PROPERTIES = new DavPropertyNameSet();
|
||||
|
||||
static {
|
||||
FOLDER_PROPERTIES.add(DavPropertyName.create("contentclass", Namespace.getNamespace("DAV:")));
|
||||
FOLDER_PROPERTIES.add(DavPropertyName.create("contentclass", DAV));
|
||||
FOLDER_PROPERTIES.add(DavPropertyName.create("hassubs"));
|
||||
FOLDER_PROPERTIES.add(DavPropertyName.create("nosubs"));
|
||||
FOLDER_PROPERTIES.add(DavPropertyName.create("unreadcount", URN_SCHEMAS_HTTPMAIL));
|
||||
@ -779,7 +780,7 @@ public class ExchangeSession {
|
||||
|
||||
message.permanentUrl = getPropertyIfExists(properties, "permanenturl", SCHEMAS_EXCHANGE);
|
||||
message.size = getIntPropertyIfExists(properties, "x0e080003", SCHEMAS_MAPI_PROPTAG);
|
||||
message.uid = getPropertyIfExists(properties, "uid", Namespace.getNamespace("DAV:"));
|
||||
message.uid = getPropertyIfExists(properties, "uid", DAV);
|
||||
message.imapUid = getLongPropertyIfExists(properties, "x0e230003", SCHEMAS_MAPI_PROPTAG);
|
||||
message.read = "1".equals(getPropertyIfExists(properties, "read", URN_SCHEMAS_HTTPMAIL));
|
||||
message.junk = "1".equals(getPropertyIfExists(properties, "x10830003", SCHEMAS_MAPI_PROPTAG));
|
||||
@ -982,9 +983,9 @@ public class ExchangeSession {
|
||||
String href = URIUtil.decode(entity.getHref());
|
||||
Folder folder = new Folder();
|
||||
DavPropertySet properties = entity.getProperties(HttpStatus.SC_OK);
|
||||
folder.contentClass = getPropertyIfExists(properties, "contentclass", Namespace.getNamespace("DAV:"));
|
||||
folder.hasChildren = "1".equals(getPropertyIfExists(properties, "hassubs", Namespace.getNamespace("DAV:")));
|
||||
folder.noInferiors = "1".equals(getPropertyIfExists(properties, "nosubs", Namespace.getNamespace("DAV:")));
|
||||
folder.contentClass = getPropertyIfExists(properties, "contentclass", DAV);
|
||||
folder.hasChildren = "1".equals(getPropertyIfExists(properties, "hassubs", DAV));
|
||||
folder.noInferiors = "1".equals(getPropertyIfExists(properties, "nosubs", DAV));
|
||||
folder.unreadCount = getIntPropertyIfExists(properties, "unreadcount", URN_SCHEMAS_HTTPMAIL);
|
||||
folder.ctag = getPropertyIfExists(properties, "contenttag", Namespace.getNamespace("http://schemas.microsoft.com/repl/"));
|
||||
folder.etag = getPropertyIfExists(properties, "resourcetag", Namespace.getNamespace("http://schemas.microsoft.com/repl/"));
|
||||
@ -1769,6 +1770,7 @@ public class ExchangeSession {
|
||||
|
||||
/**
|
||||
* Get message body size.
|
||||
*
|
||||
* @return mime message size
|
||||
* @throws IOException on error
|
||||
* @throws MessagingException on error
|
||||
@ -1781,6 +1783,7 @@ public class ExchangeSession {
|
||||
|
||||
/**
|
||||
* Get message body input stream.
|
||||
*
|
||||
* @return mime message InputStream
|
||||
* @throws IOException on error
|
||||
* @throws MessagingException on error
|
||||
@ -1897,21 +1900,38 @@ public class ExchangeSession {
|
||||
protected String etag;
|
||||
protected String contentClass;
|
||||
protected String noneMatch;
|
||||
/**
|
||||
* ICS content
|
||||
*/
|
||||
protected String itemBody;
|
||||
|
||||
/**
|
||||
* Create empty Item.
|
||||
* Build item instance.
|
||||
*
|
||||
* @param messageUrl message url
|
||||
* @param contentClass content class
|
||||
* @param itemBody item body
|
||||
* @param etag item etag
|
||||
* @param noneMatch none match flag
|
||||
*/
|
||||
public Item() {
|
||||
public Item(String messageUrl, String contentClass, String itemBody, String etag, String noneMatch) {
|
||||
this.href = messageUrl;
|
||||
this.contentClass = contentClass;
|
||||
this.itemBody = itemBody;
|
||||
this.etag = etag;
|
||||
this.noneMatch = noneMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return item content type
|
||||
*
|
||||
* @return content type
|
||||
*/
|
||||
public abstract String getContentType();
|
||||
|
||||
/**
|
||||
* Retrieve item body from Exchange
|
||||
*
|
||||
* @return item body
|
||||
* @throws HttpException on error
|
||||
*/
|
||||
@ -1919,14 +1939,15 @@ public class ExchangeSession {
|
||||
|
||||
/**
|
||||
* Build Item instance from multistatusResponse info
|
||||
*
|
||||
* @param multiStatusResponse response
|
||||
* @throws URIException on error
|
||||
*/
|
||||
public Item(MultiStatusResponse multiStatusResponse) throws URIException {
|
||||
href = URIUtil.decode(multiStatusResponse.getHref());
|
||||
permanentUrl = getPropertyIfExists(multiStatusResponse.getProperties(HttpStatus.SC_OK), "permanenturl", SCHEMAS_EXCHANGE);
|
||||
etag = getPropertyIfExists(multiStatusResponse.getProperties(HttpStatus.SC_OK), "getetag", Namespace.getNamespace("DAV:"));
|
||||
displayName = getPropertyIfExists(multiStatusResponse.getProperties(HttpStatus.SC_OK), "displayname", Namespace.getNamespace("DAV:"));
|
||||
etag = getPropertyIfExists(multiStatusResponse.getProperties(HttpStatus.SC_OK), "getetag", DAV);
|
||||
displayName = getPropertyIfExists(multiStatusResponse.getProperties(HttpStatus.SC_OK), "displayname", DAV);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1958,12 +1979,14 @@ public class ExchangeSession {
|
||||
return new HttpException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calendar event object
|
||||
*/
|
||||
public class Contact extends Item {
|
||||
/**
|
||||
* Build Contact instance from multistatusResponse info
|
||||
*
|
||||
* @param multiStatusResponse response
|
||||
* @throws URIException on error
|
||||
*/
|
||||
@ -1971,6 +1994,42 @@ public class ExchangeSession {
|
||||
super(multiStatusResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Contact(String messageUrl, String contentClass, String itemBody, String etag, String noneMatch) {
|
||||
super(messageUrl.endsWith(".vcf") ? messageUrl.substring(0, messageUrl.length() - 3) + "EML" : messageUrl, contentClass, itemBody, etag, noneMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert EML extension to vcf.
|
||||
*
|
||||
* @return item name
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
String name = super.getName();
|
||||
if (name.endsWith(".EML")) {
|
||||
name = name.substring(0, name.length() - 3) + "vcf";
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute vcard uid from name.
|
||||
*
|
||||
* @return uid
|
||||
* @throws URIException on error
|
||||
*/
|
||||
protected String getUid() throws URIException {
|
||||
String uid = getName();
|
||||
int dotIndex = uid.lastIndexOf('.');
|
||||
if (dotIndex > 0) {
|
||||
uid = uid.substring(0, dotIndex);
|
||||
}
|
||||
return URIUtil.encodePath(uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return "text/vcard";
|
||||
@ -1993,7 +2052,7 @@ public class ExchangeSession {
|
||||
writer.writeLine("BEGIN:VCARD");
|
||||
writer.writeLine("VERSION:3.0");
|
||||
writer.write("UID:");
|
||||
writer.writeLine(URIUtil.encodePath(getName()));
|
||||
writer.writeLine(getUid());
|
||||
writer.write("FN:");
|
||||
writer.writeLine(getPropertyIfExists(properties, DavPropertyName.create("cn", URN_SCHEMAS_CONTACTS), ""));
|
||||
// RFC 2426: Family Name, Given Name, Additional Names, Honorific Prefixes, and Honorific Suffixes
|
||||
@ -2032,19 +2091,92 @@ public class ExchangeSession {
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
protected List<DavProperty> buildProperties() throws IOException {
|
||||
ArrayList<DavProperty> list = new ArrayList<DavProperty>();
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("contentclass", DAV), contentClass));
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("outlookmessageclass", SCHEMAS_EXCHANGE), "IPM.Contact"));
|
||||
|
||||
ICSBufferedReader reader = new ICSBufferedReader(new StringReader(itemBody));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
int index = line.indexOf(':');
|
||||
if (index >= 0) {
|
||||
String key = line.substring(0, index);
|
||||
String value = line.substring(index + 1);
|
||||
if ("FN".equals(key)) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("cn", URN_SCHEMAS_CONTACTS), value));
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("subject", URN_SCHEMAS_HTTPMAIL), value));
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("fileas", URN_SCHEMAS_CONTACTS), value));
|
||||
|
||||
} else if ("N".equals(key)) {
|
||||
String[] values = value.split(";");
|
||||
if (values.length > 0) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("sn", URN_SCHEMAS_CONTACTS), values[0]));
|
||||
}
|
||||
if (values.length > 1) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("givenName", URN_SCHEMAS_CONTACTS), values[1]));
|
||||
}
|
||||
} else if ("TEL;TYPE=cell".equals(key)) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("mobile", URN_SCHEMAS_CONTACTS), value));
|
||||
} else if ("TEL;TYPE=work".equals(key)) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("telephoneNumber", URN_SCHEMAS_CONTACTS), value));
|
||||
} else if ("TEL;TYPE=home".equals(key)) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("homePhone", URN_SCHEMAS_CONTACTS), value));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected ItemResult createOrUpdate() throws IOException {
|
||||
int status = 0;
|
||||
PropPatchMethod propPatchMethod = new PropPatchMethod(URIUtil.encodePath(href), buildProperties());
|
||||
propPatchMethod.setRequestHeader("Translate", "f");
|
||||
if (etag != null) {
|
||||
propPatchMethod.setRequestHeader("If-Match", etag);
|
||||
}
|
||||
if (noneMatch != null) {
|
||||
propPatchMethod.setRequestHeader("If-None-Match", noneMatch);
|
||||
}
|
||||
|
||||
try {
|
||||
status = httpClient.executeMethod(propPatchMethod);
|
||||
if (status == HttpStatus.SC_MULTI_STATUS) {
|
||||
if (etag != null) {
|
||||
LOGGER.debug("Updated contact " + href);
|
||||
} else {
|
||||
LOGGER.warn("Overwritten contact " + href);
|
||||
}
|
||||
status = HttpStatus.SC_CREATED;
|
||||
} else {
|
||||
LOGGER.warn("Unable to create or update contact " + status + ' ' + propPatchMethod.getStatusLine());
|
||||
}
|
||||
} finally {
|
||||
propPatchMethod.releaseConnection();
|
||||
}
|
||||
ItemResult itemResult = new ItemResult();
|
||||
// 440 means forbidden on Exchange
|
||||
if (status == 440) {
|
||||
status = HttpStatus.SC_FORBIDDEN;
|
||||
}
|
||||
itemResult.status = status;
|
||||
if (propPatchMethod.getResponseHeader("GetETag") != null) {
|
||||
itemResult.etag = propPatchMethod.getResponseHeader("GetETag").getValue();
|
||||
}
|
||||
|
||||
return itemResult;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calendar event object
|
||||
* Calendar event object.
|
||||
*/
|
||||
public class Event extends Item {
|
||||
/**
|
||||
* ICS content
|
||||
*/
|
||||
protected String icsBody;
|
||||
|
||||
/**
|
||||
* Build Event instance from multistatusResponse info
|
||||
* Build Event instance from response info.
|
||||
*
|
||||
* @param multiStatusResponse response
|
||||
* @throws URIException on error
|
||||
*/
|
||||
@ -2053,9 +2185,10 @@ public class ExchangeSession {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create empty event.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Event() {
|
||||
public Event(String messageUrl, String contentClass, String itemBody, String etag, String noneMatch) {
|
||||
super(messageUrl, contentClass, itemBody, etag, noneMatch);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2567,7 +2700,7 @@ public class ExchangeSession {
|
||||
String organizer = null;
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new ICSBufferedReader(new StringReader(icsBody));
|
||||
reader = new ICSBufferedReader(new StringReader(itemBody));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
int index = line.indexOf(':');
|
||||
@ -2627,7 +2760,7 @@ public class ExchangeSession {
|
||||
return icsMethod;
|
||||
}
|
||||
|
||||
protected EventResult createOrUpdate() throws IOException {
|
||||
protected ItemResult createOrUpdate() throws IOException {
|
||||
String boundary = UUID.randomUUID().toString();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
MimeOutputStreamWriter writer = new MimeOutputStreamWriter(baos);
|
||||
@ -2642,7 +2775,7 @@ public class ExchangeSession {
|
||||
putmethod.setRequestHeader("If-None-Match", noneMatch);
|
||||
}
|
||||
putmethod.setRequestHeader("Content-Type", "message/rfc822");
|
||||
String method = getICSMethod(icsBody);
|
||||
String method = getICSMethod(itemBody);
|
||||
|
||||
writer.writeHeader("Content-Transfer-Encoding", "7bit");
|
||||
writer.writeHeader("Content-class", contentClass);
|
||||
@ -2650,7 +2783,7 @@ public class ExchangeSession {
|
||||
writer.writeHeader("Date", new Date());
|
||||
|
||||
// Make sure invites have a proper subject line
|
||||
writer.writeHeader("Subject", getICSSummary(icsBody));
|
||||
writer.writeHeader("Subject", getICSSummary(itemBody));
|
||||
|
||||
if ("urn:content-classes:calendarmessage".equals(contentClass)) {
|
||||
// need to parse attendees and organizer to build recipients
|
||||
@ -2691,11 +2824,11 @@ public class ExchangeSession {
|
||||
}
|
||||
// if not organizer, set REPLYTIME to force Outlook in attendee mode
|
||||
if (participants.organizer != null && !email.equalsIgnoreCase(participants.organizer)) {
|
||||
if (icsBody.indexOf("METHOD:") < 0) {
|
||||
icsBody = icsBody.replaceAll("BEGIN:VCALENDAR", "BEGIN:VCALENDAR\r\nMETHOD:REQUEST");
|
||||
if (itemBody.indexOf("METHOD:") < 0) {
|
||||
itemBody = itemBody.replaceAll("BEGIN:VCALENDAR", "BEGIN:VCALENDAR\r\nMETHOD:REQUEST");
|
||||
}
|
||||
if (icsBody.indexOf("X-MICROSOFT-CDO-REPLYTIME") < 0) {
|
||||
icsBody = icsBody.replaceAll("END:VEVENT", "X-MICROSOFT-CDO-REPLYTIME:" +
|
||||
if (itemBody.indexOf("X-MICROSOFT-CDO-REPLYTIME") < 0) {
|
||||
itemBody = itemBody.replaceAll("END:VEVENT", "X-MICROSOFT-CDO-REPLYTIME:" +
|
||||
getZuluDateFormat().format(new Date()) + "\r\nEND:VEVENT");
|
||||
}
|
||||
}
|
||||
@ -2710,7 +2843,7 @@ public class ExchangeSession {
|
||||
|
||||
// Write a part of the message that contains the
|
||||
// ICS description so that invites contain the description text
|
||||
String description = getICSDescription(icsBody).replaceAll("\\\\[Nn]", "\r\n");
|
||||
String description = getICSDescription(itemBody).replaceAll("\\\\[Nn]", "\r\n");
|
||||
|
||||
if (description.length() > 0) {
|
||||
writer.writeHeader("Content-Type", "text/plain;\r\n" +
|
||||
@ -2730,7 +2863,7 @@ public class ExchangeSession {
|
||||
writer.writeHeader("Content-Transfer-Encoding", "8bit");
|
||||
writer.writeLn();
|
||||
writer.flush();
|
||||
baos.write(fixICS(icsBody, false).getBytes("UTF-8"));
|
||||
baos.write(fixICS(itemBody, false).getBytes("UTF-8"));
|
||||
writer.writeLn();
|
||||
writer.writeLn("------=_NextPart_" + boundary + "--");
|
||||
writer.close();
|
||||
@ -2751,14 +2884,14 @@ public class ExchangeSession {
|
||||
} finally {
|
||||
putmethod.releaseConnection();
|
||||
}
|
||||
EventResult eventResult = new EventResult();
|
||||
ItemResult itemResult = new ItemResult();
|
||||
// 440 means forbidden on Exchange
|
||||
if (status == 440) {
|
||||
status = HttpStatus.SC_FORBIDDEN;
|
||||
}
|
||||
eventResult.status = status;
|
||||
itemResult.status = status;
|
||||
if (putmethod.getResponseHeader("GetETag") != null) {
|
||||
eventResult.etag = putmethod.getResponseHeader("GetETag").getValue();
|
||||
itemResult.etag = putmethod.getResponseHeader("GetETag").getValue();
|
||||
}
|
||||
|
||||
// trigger activeSync push event, only if davmail.forceActiveSyncUpdate setting is true
|
||||
@ -2766,7 +2899,7 @@ public class ExchangeSession {
|
||||
(Settings.getBooleanProperty("davmail.forceActiveSyncUpdate"))) {
|
||||
ArrayList<DavProperty> propertyList = new ArrayList<DavProperty>();
|
||||
// Set contentclass to make ActiveSync happy
|
||||
propertyList.add(new DefaultDavProperty(DavPropertyName.create("contentclass", Namespace.getNamespace("DAV:")), contentClass));
|
||||
propertyList.add(new DefaultDavProperty(DavPropertyName.create("contentclass", DAV), contentClass));
|
||||
// ... but also set PR_INTERNET_CONTENT to preserve custom properties
|
||||
propertyList.add(new DefaultDavProperty(PR_INTERNET_CONTENT, new String(Base64.encodeBase64(baos.toByteArray()))));
|
||||
PropPatchMethod propPatchMethod = new PropPatchMethod(URIUtil.encodePath(href), propertyList);
|
||||
@ -2776,10 +2909,10 @@ public class ExchangeSession {
|
||||
} else {
|
||||
// need to retrieve new etag
|
||||
Item newItem = getItem(href);
|
||||
eventResult.etag = newItem.etag;
|
||||
itemResult.etag = newItem.etag;
|
||||
}
|
||||
}
|
||||
return eventResult;
|
||||
return itemResult;
|
||||
|
||||
}
|
||||
}
|
||||
@ -2836,7 +2969,7 @@ public class ExchangeSession {
|
||||
} catch (HttpException e) {
|
||||
// failover to DAV:comment property on some Exchange servers
|
||||
if (DEFAULT_SCHEDULE_STATE_PROPERTY.equals(scheduleStateProperty)) {
|
||||
scheduleStateProperty = DavPropertyName.create("comment", Namespace.getNamespace("DAV:"));
|
||||
scheduleStateProperty = DavPropertyName.create("comment", DAV);
|
||||
result = getEventMessages(folderPath);
|
||||
} else {
|
||||
throw e;
|
||||
@ -2923,7 +3056,13 @@ public class ExchangeSession {
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public Item getItem(String folderPath, String itemName) throws IOException {
|
||||
String itemPath = folderPath + '/' + itemName;
|
||||
String itemPath;
|
||||
// convert vcf extension to EML
|
||||
if (itemName.endsWith(".vcf")) {
|
||||
itemPath = folderPath + '/' + itemName.substring(0, itemName.length() - 3) + "EML";
|
||||
} else {
|
||||
itemPath = folderPath + '/' + itemName;
|
||||
}
|
||||
Item item;
|
||||
try {
|
||||
item = getItem(itemPath);
|
||||
@ -2954,7 +3093,7 @@ public class ExchangeSession {
|
||||
throw new DavMailException("EXCEPTION_EVENT_NOT_FOUND");
|
||||
}
|
||||
String contentClass = getPropertyIfExists(responses[0].getProperties(HttpStatus.SC_OK),
|
||||
"contentclass", Namespace.getNamespace("DAV:"));
|
||||
"contentclass", DAV);
|
||||
if ("urn:content-classes:person".equals(contentClass)) {
|
||||
return new Contact(responses[0]);
|
||||
} else if ("urn:content-classes:appointment".equals(contentClass)) {
|
||||
@ -3008,7 +3147,7 @@ public class ExchangeSession {
|
||||
/**
|
||||
* Event result object to hold HTTP status and event etag from an event creation/update.
|
||||
*/
|
||||
public static class EventResult {
|
||||
public static class ItemResult {
|
||||
/**
|
||||
* HTTP status
|
||||
*/
|
||||
@ -3042,28 +3181,34 @@ public class ExchangeSession {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or update event on the Exchange server
|
||||
* Create or update item (event or contact) on the Exchange server
|
||||
*
|
||||
* @param folderPath Exchange folder path
|
||||
* @param eventName event name
|
||||
* @param icsBody event body in iCalendar format
|
||||
* @param itemName event name
|
||||
* @param itemBody event body in iCalendar format
|
||||
* @param etag previous event etag to detect concurrent updates
|
||||
* @param noneMatch if-none-match header value
|
||||
* @return HTTP response event result (status and etag)
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public EventResult createOrUpdateEvent(String folderPath, String eventName, String icsBody, String etag, String noneMatch) throws IOException {
|
||||
String messageUrl = folderPath + '/' + eventName;
|
||||
return internalCreateOrUpdateEvent(messageUrl, "urn:content-classes:appointment", icsBody, etag, noneMatch);
|
||||
public ItemResult createOrUpdateItem(String folderPath, String itemName, String itemBody, String etag, String noneMatch) throws IOException {
|
||||
String messageUrl = folderPath + '/' + itemName;
|
||||
if (itemBody.startsWith("BEGIN:VCALENDAR")) {
|
||||
return internalCreateOrUpdateEvent(messageUrl, "urn:content-classes:appointment", itemBody, etag, noneMatch);
|
||||
} else if (itemBody.startsWith("BEGIN:VCARD")) {
|
||||
return internalCreateOrUpdateContact(messageUrl, "urn:content-classes:person", itemBody, etag, noneMatch);
|
||||
} else {
|
||||
throw new IOException(BundleMessage.format("EXCEPTION_INVALID_MESSAGE_CONTENT", itemBody));
|
||||
}
|
||||
}
|
||||
|
||||
protected EventResult internalCreateOrUpdateEvent(String messageUrl, String contentClass, String icsBody, String etag, String noneMatch) throws IOException {
|
||||
Event event = new Event();
|
||||
event.contentClass = contentClass;
|
||||
event.icsBody = icsBody;
|
||||
event.href = messageUrl;
|
||||
event.etag = etag;
|
||||
event.noneMatch = noneMatch;
|
||||
protected ItemResult internalCreateOrUpdateContact(String messageUrl, String contentClass, String icsBody, String etag, String noneMatch) throws IOException {
|
||||
Contact contact = new Contact(messageUrl, contentClass, icsBody, etag, noneMatch);
|
||||
return contact.createOrUpdate();
|
||||
}
|
||||
|
||||
protected ItemResult internalCreateOrUpdateEvent(String messageUrl, String contentClass, String icsBody, String etag, String noneMatch) throws IOException {
|
||||
Event event = new Event(messageUrl, contentClass, icsBody, etag, noneMatch);
|
||||
return event.createOrUpdate();
|
||||
}
|
||||
|
||||
@ -3156,7 +3301,7 @@ public class ExchangeSession {
|
||||
if (responses.length == 0) {
|
||||
LOGGER.warn(new BundleMessage("EXCEPTION_UNABLE_TO_GET_MAIL_FOLDER", mailPath));
|
||||
} else {
|
||||
displayName = getPropertyIfExists(responses[0].getProperties(HttpStatus.SC_OK), "displayname", Namespace.getNamespace("DAV:"));
|
||||
displayName = getPropertyIfExists(responses[0].getProperties(HttpStatus.SC_OK), "displayname", DAV);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.warn(new BundleMessage("EXCEPTION_UNABLE_TO_GET_MAIL_FOLDER", mailPath));
|
||||
@ -3783,7 +3928,7 @@ public class ExchangeSession {
|
||||
// failover for Exchange 2007, use PROPPATCH with forced timezone
|
||||
if (fakeEventUrl == null) {
|
||||
ArrayList<DavProperty> propertyList = new ArrayList<DavProperty>();
|
||||
propertyList.add(new DefaultDavProperty(DavPropertyName.create("contentclass", Namespace.getNamespace("DAV:")), "urn:content-classes:appointment"));
|
||||
propertyList.add(new DefaultDavProperty(DavPropertyName.create("contentclass", DAV), "urn:content-classes:appointment"));
|
||||
propertyList.add(new DefaultDavProperty(DavPropertyName.create("outlookmessageclass", Namespace.getNamespace("http://schemas.microsoft.com/exchange/")), "IPM.Appointment"));
|
||||
propertyList.add(new DefaultDavProperty(DavPropertyName.create("instancetype", Namespace.getNamespace("urn:schemas:calendar:")), "0"));
|
||||
// get forced timezone id from settings
|
||||
|
Loading…
Reference in New Issue
Block a user