[evolution-ews] Bug #655325 - Support follow up flag
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] Bug #655325 - Support follow up flag
- Date: Fri, 23 Aug 2013 18:12:00 +0000 (UTC)
commit 4418315c41008b8d83b7f9cbfe70b9cc9063adc7
Author: Milan Crha <mcrha redhat com>
Date: Fri Aug 23 20:09:57 2013 +0200
Bug #655325 - Support follow up flag
src/calendar/e-cal-backend-ews.c | 2 +-
src/camel/camel-ews-folder.c | 37 ++---
src/camel/camel-ews-transport.c | 2 +-
src/camel/camel-ews-utils.c | 220 ++++++++++++++++++++++-
src/camel/camel-ews-utils.h | 2 +
src/server/e-ews-connection.c | 118 ++++++++++++-
src/server/e-ews-item-change.c | 371 ++++++++++++++++++++++++++++++++++++++
src/server/e-ews-item-change.h | 122 +++++++++++++
src/server/e-ews-item.c | 228 +++++++++++++++++++++---
src/server/e-ews-item.h | 31 ++++
src/server/e-ews-message.c | 58 ++++++
src/server/e-ews-message.h | 21 +++
src/server/e-soap-message.c | 17 ++-
src/server/e-soap-message.h | 2 +-
src/utils/ews-camel-common.c | 99 ++++++++---
src/utils/ews-camel-common.h | 6 +-
16 files changed, 1239 insertions(+), 97 deletions(-)
---
diff --git a/src/calendar/e-cal-backend-ews.c b/src/calendar/e-cal-backend-ews.c
index b60a81a..21d5445 100644
--- a/src/calendar/e-cal-backend-ews.c
+++ b/src/calendar/e-cal-backend-ews.c
@@ -3064,7 +3064,7 @@ ewscal_send_cancellation_email (ECalBackend *backend,
camel_medium_set_content ((CamelMedium *) message, (CamelDataWrapper *) multi);
g_object_unref (multi);
- camel_ews_utils_create_mime_message (cnc, "SendOnly", NULL, message, 0, from, NULL, NULL, NULL, NULL,
&error);
+ camel_ews_utils_create_mime_message (cnc, "SendOnly", NULL, message, NULL, from, NULL, NULL, NULL,
NULL, &error);
if (error) {
g_warning ("Failed to send cancellation email: %s", error->message);
diff --git a/src/camel/camel-ews-folder.c b/src/camel/camel-ews-folder.c
index b51f824..e00fc59 100644
--- a/src/camel/camel-ews-folder.c
+++ b/src/camel/camel-ews-folder.c
@@ -61,11 +61,18 @@ which needs to be better organized via functions */
#define MAX_ATTACHMENT_SIZE 1*1024*1024 /*In bytes*/
-#define SUMMARY_ITEM_FLAGS "item:ResponseObjects item:Sensitivity item:Importance item:Categories"
+/* there are written more follow-up flags, but it's read only few of them */
+#define SUMMARY_FOLLOWUP_FLAGS " mapi:int:0x1090" /* PidTagFlagStatus */ \
+ " mapi:time:0x1091" /* PidTagFlagCompleteTime */ \
+ " mapi:dist:string:Common:0x8530" /* PidLidFlagRequest */ \
+ " mapi:dist:time:Task:0x8105" /* PidLidTaskDueDate */
+
+#define SUMMARY_ITEM_FLAGS "item:ResponseObjects item:Sensitivity item:Importance item:Categories"
SUMMARY_FOLLOWUP_FLAGS
#define ITEM_PROPS "item:Subject item:DateTimeReceived item:DateTimeSent item:DateTimeCreated item:Size " \
"item:HasAttachments item:InReplyTo"
#define SUMMARY_ITEM_PROPS ITEM_PROPS " " SUMMARY_ITEM_FLAGS
+
#define SUMMARY_MESSAGE_FLAGS SUMMARY_ITEM_FLAGS " message:IsRead mapi:int:0x0e07 mapi:int:0x0e17
mapi:int:0x1080 mapi:int:0x1081"
#define SUMMARY_MESSAGE_PROPS ITEM_PROPS " message:From message:Sender message:ToRecipients
message:CcRecipients " \
"message:BccRecipients message:IsRead message:References message:InternetMessageId " \
@@ -789,28 +796,9 @@ msg_update_flags (ESoapMessage *msg,
if (mi->info.flags & CAMEL_MESSAGE_FORWARDED)
icon = 0x106;
- e_soap_message_start_element (msg, "SetItemField", NULL, NULL);
-
- e_soap_message_start_element (msg, "ExtendedFieldURI", NULL, NULL);
- e_soap_message_add_attribute (msg, "PropertyTag", "0x1080", NULL, NULL);
- e_soap_message_add_attribute (msg, "PropertyType", "Integer", NULL, NULL);
- e_soap_message_end_element (msg);
-
- e_soap_message_start_element (msg, "Message", NULL, NULL);
- e_soap_message_start_element (msg, "ExtendedProperty", NULL, NULL);
-
- /* And now we have to specify the field *again*. Yay for XML crap */
- e_soap_message_start_element (msg, "ExtendedFieldURI", NULL, NULL);
- e_soap_message_add_attribute (msg, "PropertyTag", "0x1080", NULL, NULL);
- e_soap_message_add_attribute (msg, "PropertyType", "Integer", NULL, NULL);
- e_soap_message_end_element (msg);
-
- e_ews_message_write_int_parameter (msg, "Value", NULL, icon);
-
- e_soap_message_end_element (msg); /* ExtendedProperty */
- e_soap_message_end_element (msg); /* Message */
- e_soap_message_end_element (msg); /* SetItemField */
+ e_ews_message_add_set_item_field_extended_tag_int (msg, NULL, "Message", 0x1080,
icon);
}
+
/* now update the Categories */
e_soap_message_start_element (msg, "SetItemField", NULL, NULL);
@@ -827,6 +815,8 @@ msg_update_flags (ESoapMessage *msg,
e_soap_message_end_element (msg); /* Message */
e_soap_message_end_element (msg); /* SetItemField */
+ ews_utils_update_followup_flags (msg, (CamelMessageInfo *) mi);
+
e_ews_message_end_item_change (msg);
mi->info.flags = mi->info.flags & (~CAMEL_MESSAGE_FOLDER_FLAGGED);
@@ -1623,8 +1613,7 @@ ews_append_message_sync (CamelFolder *folder,
fid = e_ews_folder_id_new (folder_id, NULL, FALSE);
if (!camel_ews_utils_create_mime_message (
cnc, "SaveOnly", fid, message,
- camel_message_info_flags (info),
- from, NULL, &itemid, &changekey,
+ info, from, NULL, &itemid, &changekey,
cancellable, &local_error)) {
camel_ews_store_maybe_disconnect (ews_store, local_error);
g_propagate_error (error, local_error);
diff --git a/src/camel/camel-ews-transport.c b/src/camel/camel-ews-transport.c
index 948960f..7acc19c 100644
--- a/src/camel/camel-ews-transport.c
+++ b/src/camel/camel-ews-transport.c
@@ -164,7 +164,7 @@ ews_send_to_sync (CamelTransport *transport,
}
success = camel_ews_utils_create_mime_message (
- cnc, "SendOnly", NULL, message, 0,
+ cnc, "SendOnly", NULL, message, NULL,
from, recipients, NULL, NULL, cancellable, error);
g_object_unref (cnc);
diff --git a/src/camel/camel-ews-utils.c b/src/camel/camel-ews-utils.c
index 0d24ae3..ee68dc3 100644
--- a/src/camel/camel-ews-utils.c
+++ b/src/camel/camel-ews-utils.c
@@ -32,6 +32,8 @@
#include "server/camel-ews-settings.h"
#include "server/e-ews-message.h"
+#include "server/e-ews-item-change.h"
+#include "utils/ews-camel-common.h"
#include "camel-ews-utils.h"
@@ -435,7 +437,8 @@ ews_utils_replace_server_user_flags (ESoapMessage *msg,
* receipt-handled flag for message receipts, which we
* don't want showing up in the categories, so
* silently drop it here */
- if (strcmp (n, "receipt-handled") == 0)
+ if (strcmp (n, "receipt-handled") == 0 ||
+ strcmp (n, "$has-cal") == 0)
continue;
e_ews_message_write_string_parameter (msg, "String", NULL, n);
}
@@ -639,6 +642,70 @@ ews_set_threading_data (CamelEwsMessageInfo *mi,
camel_header_references_list_clear (&refs);
}
+static gboolean
+camel_ews_utils_update_follow_up_flags (EEwsItem *item,
+ CamelMessageInfo *info)
+{
+ gboolean changed = FALSE, found;
+ time_t completed_tt, dueby_tt;
+ const gchar *followup_name;
+ gint flag_status;
+
+ /* PidTagFlagStatus */
+ found = FALSE;
+ flag_status = e_ews_item_get_extended_property_as_int (item, NULL, 0x1090, &found);
+ if (!found)
+ flag_status = 0;
+
+ /* PidTagFlagCompleteTime */
+ found = FALSE;
+ completed_tt = e_ews_item_get_extended_property_as_time (item, NULL, 0x1091, &found);
+ if (!found)
+ completed_tt = (time_t) 0;
+
+ /* PidLidFlagRequest */
+ found = FALSE;
+ followup_name = e_ews_item_get_extended_property_as_string (item, "Common", 0x8530, &found);
+ if (!found)
+ followup_name = NULL;
+
+ /* PidLidTaskDueDate */
+ found = FALSE;
+ dueby_tt = e_ews_item_get_extended_property_as_time (item, "Task", 0x8105, &found);
+ if (!found)
+ dueby_tt = (time_t) 0;
+
+ if (flag_status == 1) {
+ /* complete */
+ if (!camel_message_info_user_tag (info, "follow-up"))
+ changed = camel_message_info_set_user_tag (info, "follow-up", followup_name ?
followup_name : "follow-up") || changed;
+ if (completed_tt != (time_t) 0) {
+ gchar *text = camel_header_format_date (completed_tt, 0);
+ changed = camel_message_info_set_user_tag (info, "completed-on", text) || changed;
+ g_free (text);
+ } else {
+ changed = camel_message_info_set_user_tag (info, "completed-on", NULL) || changed;
+ }
+ } else if (flag_status == 2) {
+ /* follow-up */
+ changed = camel_message_info_set_user_tag (info, "follow-up", followup_name ? followup_name :
"follow-up") || changed;
+ changed = camel_message_info_set_user_tag (info, "completed-on", NULL) || changed;
+ if (dueby_tt != (time_t) 0) {
+ gchar *text = camel_header_format_date (dueby_tt, 0);
+ changed = camel_message_info_set_user_tag (info, "due-by", text) || changed;
+ g_free (text);
+ } else {
+ changed = camel_message_info_set_user_tag (info, "due-by", NULL) || changed;
+ }
+ } else {
+ changed = camel_message_info_set_user_tag (info, "follow-up", NULL) || changed;
+ changed = camel_message_info_set_user_tag (info, "completed-on", NULL) || changed;
+ changed = camel_message_info_set_user_tag (info, "due-by", NULL) || changed;
+ }
+
+ return changed;
+}
+
void
camel_ews_utils_sync_updated_items (CamelEwsFolder *ews_folder,
GSList *items_updated)
@@ -665,17 +732,26 @@ camel_ews_utils_sync_updated_items (CamelEwsFolder *ews_folder,
camel_folder_summary_get (folder->summary, id->id);
if (mi) {
gint server_flags;
+ gboolean changed, was_changed;
+ was_changed = (mi->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0;
server_flags = ews_utils_get_server_flags (item);
ews_utils_merge_server_user_flags (item, mi);
- if (camel_ews_update_message_info_flags (
+ changed = camel_ews_update_message_info_flags (
folder->summary, (CamelMessageInfo *) mi,
- server_flags, NULL))
+ server_flags, NULL);
+ changed = camel_ews_utils_update_follow_up_flags (item, (CamelMessageInfo *) mi) ||
changed;
+
+ if (changed)
camel_folder_change_info_change_uid (ci, mi->info.uid);
g_free (mi->change_key);
mi->change_key = g_strdup (id->change_key);
mi->info.dirty = TRUE;
+ if (!was_changed) {
+ /* do not save to the server what was just read, when did not change locally
before */
+ mi->info.flags = mi->info.flags & (~CAMEL_MESSAGE_FOLDER_FLAGGED);
+ }
camel_message_info_free (mi);
g_object_unref (item);
@@ -789,6 +865,8 @@ camel_ews_utils_sync_created_items (CamelEwsFolder *ews_folder,
mi->info.flags |= server_flags;
mi->server_flags = server_flags;
+ camel_ews_utils_update_follow_up_flags (item, (CamelMessageInfo *) mi);
+
camel_folder_summary_add (
folder->summary, (CamelMessageInfo *) mi);
@@ -839,3 +917,139 @@ camel_ews_utils_get_host_name (CamelSettings *settings)
return host;
}
+
+void
+ews_utils_update_followup_flags (ESoapMessage *msg,
+ CamelMessageInfo *mi)
+{
+ const gchar *followup, *completed, *dueby;
+ time_t completed_tt = (time_t) 0 , dueby_tt = (time_t) 0;
+
+ g_return_if_fail (msg != NULL);
+ g_return_if_fail (mi != NULL);
+
+ followup = camel_message_info_user_tag (mi, "follow-up");
+ completed = camel_message_info_user_tag (mi, "completed-on");
+ dueby = camel_message_info_user_tag (mi, "due-by");
+
+ if (followup && !*followup)
+ followup = NULL;
+
+ if (completed && *completed)
+ completed_tt = camel_header_decode_date (completed, NULL);
+
+ if (dueby && *dueby)
+ dueby_tt = camel_header_decode_date (dueby, NULL);
+
+ /* PidTagFlagStatus */
+ e_ews_message_add_set_item_field_extended_tag_int (msg, NULL, "Message", 0x1090,
+ followup ? (completed_tt != (time_t) 0 ? 0x01 /* followupComplete */: 0x02 /* followupFlagged
*/) : 0x0);
+
+ if (followup) {
+ time_t now_tt = time (NULL);
+
+ /* PidLidFlagRequest */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_string (msg, NULL, "Message",
"Common", 0x8530, followup);
+
+ /* PidTagToDoItemFlags */
+ e_ews_message_add_set_item_field_extended_tag_int (msg, NULL, "Message", 0x0e2b, 1);
+
+ if (completed_tt == (time_t) 0 && dueby_tt == (time_t) 0) {
+ /* PidLidTaskStatus */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_int (msg, NULL,
"Message", "Task", 0x8101, 0);
+
+ /* PidLidPercentComplete */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_double (msg, NULL,
"Message", "Task", 0x8102, 0.0);
+
+ /* PidLidTaskStartDate */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_time (msg, NULL,
"Message", "Task", 0x8104, now_tt);
+
+ /* PidLidTaskDueDate */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_time (msg, NULL,
"Message", "Task", 0x8105, now_tt);
+
+ /* PidLidTaskComplete */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_boolean (msg, NULL,
"Message", "Task", 0x811c, FALSE);
+ }
+ } else {
+ /* PidTagFlagStatus */
+ e_ews_message_add_delete_item_field_extended_tag (msg, 0x1090, E_EWS_MESSAGE_DATA_TYPE_INT);
+
+ /* PidTagFlagCompleteTime */
+ e_ews_message_add_delete_item_field_extended_tag (msg, 0x1091, E_EWS_MESSAGE_DATA_TYPE_TIME);
+
+ /* PidTagToDoItemFlags */
+ e_ews_message_add_delete_item_field_extended_tag (msg, 0x0e2b, E_EWS_MESSAGE_DATA_TYPE_INT);
+
+ /* PidTagFollowupIcon */
+ e_ews_message_add_delete_item_field_extended_tag (msg, 0x1095, E_EWS_MESSAGE_DATA_TYPE_INT);
+
+ /* PidLidFlagRequest */
+ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Common", 0x8530,
E_EWS_MESSAGE_DATA_TYPE_STRING);
+
+ /* PidLidFlagString */
+ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Common", 0x85c0,
E_EWS_MESSAGE_DATA_TYPE_INT);
+
+ /* PidLidTaskStatus */
+ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x8101,
E_EWS_MESSAGE_DATA_TYPE_INT);
+
+ /* PidLidPercentComplete */
+ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x8102,
E_EWS_MESSAGE_DATA_TYPE_DOUBLE);
+
+ /* PidLidTaskStartDate */
+ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x8104,
E_EWS_MESSAGE_DATA_TYPE_TIME);
+
+ /* PidLidTaskDueDate */
+ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x8105,
E_EWS_MESSAGE_DATA_TYPE_TIME);
+
+ /* PidLidTaskDateCompleted */
+ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x810f,
E_EWS_MESSAGE_DATA_TYPE_TIME);
+
+ /* PidLidTaskComplete */
+ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x811c,
E_EWS_MESSAGE_DATA_TYPE_BOOLEAN);
+ }
+
+ if (followup && completed_tt != (time_t) 0) {
+ /* minute precision */
+ completed_tt = completed_tt - (completed_tt % 60);
+
+ /* PidTagFlagCompleteTime */
+ e_ews_message_add_set_item_field_extended_tag_time (msg, NULL, "Message", 0x1091,
completed_tt);
+
+ /* PidTagFollowupIcon */
+ e_ews_message_add_delete_item_field_extended_tag (msg, 0x1095, E_EWS_MESSAGE_DATA_TYPE_INT);
+
+ /* PidLidTaskDateCompleted */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_time (msg, NULL, "Message",
"Task", 0x810f, completed_tt);
+
+ /* PidLidTaskStatus */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_int (msg, NULL, "Message",
"Task", 0x8101, 2);
+
+ /* PidLidPercentComplete */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_double (msg, NULL, "Message",
"Task", 0x8102, 1.0);
+
+ /* PidLidTaskComplete */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_boolean (msg, NULL, "Message",
"Task", 0x811c, TRUE);
+ }
+
+ if (followup && dueby_tt != (time_t) 0 && completed_tt == (time_t) 0) {
+ time_t now_tt = time (NULL);
+
+ if (now_tt > dueby_tt)
+ now_tt = dueby_tt - 1;
+
+ /* PidLidTaskStatus */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_int (msg, NULL, "Message",
"Task", 0x8101, 0);
+
+ /* PidLidPercentComplete */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_double (msg, NULL, "Message",
"Task", 0x8102, 0.0);
+
+ /* PidLidTaskStartDate */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_time (msg, NULL, "Message",
"Task", 0x8104, now_tt);
+
+ /* PidLidTaskDueDate */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_time (msg, NULL, "Message",
"Task", 0x8105, dueby_tt);
+
+ /* PidLidTaskComplete */
+ e_ews_message_add_set_item_field_extended_distinguished_tag_boolean (msg, NULL, "Message",
"Task", 0x811c, FALSE);
+ }
+}
diff --git a/src/camel/camel-ews-utils.h b/src/camel/camel-ews-utils.h
index 80d9977..a48d86d 100644
--- a/src/camel/camel-ews-utils.h
+++ b/src/camel/camel-ews-utils.h
@@ -74,6 +74,8 @@ void camel_ews_utils_sync_updated_items
void ews_utils_replace_server_user_flags
(ESoapMessage *msg,
CamelEwsMessageInfo *mi);
+void ews_utils_update_followup_flags (ESoapMessage *msg,
+ CamelMessageInfo *mi);
gchar * camel_ews_utils_get_host_name (CamelSettings *settings);
G_END_DECLS
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index 8a33ac3..ca635d3 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -3810,6 +3810,96 @@ e_ews_connection_satisfies_server_version (EEwsConnection *cnc,
return cnc->priv->version >= version;
}
+static gboolean
+ews_decode_mapi_property_string_type (const gchar *type_string,
+ EEwsMessageDataType *data_type)
+{
+ g_return_val_if_fail (type_string != NULL, FALSE);
+ g_return_val_if_fail (data_type != NULL, FALSE);
+
+ if (g_ascii_strcasecmp (type_string, "boolean") == 0) {
+ *data_type = E_EWS_MESSAGE_DATA_TYPE_BOOLEAN;
+ return TRUE;
+ }
+
+ if (g_ascii_strcasecmp (type_string, "int") == 0) {
+ *data_type = E_EWS_MESSAGE_DATA_TYPE_INT;
+ return TRUE;
+ }
+
+ if (g_ascii_strcasecmp (type_string, "double") == 0) {
+ *data_type = E_EWS_MESSAGE_DATA_TYPE_DOUBLE;
+ return TRUE;
+ }
+
+ if (g_ascii_strcasecmp (type_string, "string") == 0) {
+ *data_type = E_EWS_MESSAGE_DATA_TYPE_STRING;
+ return TRUE;
+ }
+
+ if (g_ascii_strcasecmp (type_string, "time") == 0) {
+ *data_type = E_EWS_MESSAGE_DATA_TYPE_TIME;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+ews_decode_mapi_property_string_id (const gchar *hexa_id,
+ guint32 *prop_id)
+{
+ gint64 value;
+
+ g_return_val_if_fail (hexa_id != NULL, FALSE);
+ g_return_val_if_fail (prop_id != NULL, FALSE);
+ g_return_val_if_fail (g_ascii_strncasecmp (hexa_id, "0x", 2) == 0, FALSE);
+
+ value = g_ascii_strtoll (hexa_id + 2, NULL, 16);
+ *prop_id = (guint32) value;
+
+ return value != 0;
+}
+
+/* expects either "mapi:Type:0xPropId" or "mapi:dist:Type:SetId:0xPropId"
+ where 'type' is one of boolean/int/double/string/time */
+static gboolean
+ews_decode_mapi_property_string (const gchar *prop_descr,
+ EEwsMessageDataType *data_type,
+ guint32 *prop_id,
+ gchar **distinguished_set_id)
+{
+ gchar **split;
+ guint len;
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (prop_descr != NULL, FALSE);
+ g_return_val_if_fail (data_type != NULL, FALSE);
+ g_return_val_if_fail (prop_id != NULL, FALSE);
+ g_return_val_if_fail (distinguished_set_id != NULL, FALSE);
+ g_return_val_if_fail (g_ascii_strncasecmp (prop_descr, "mapi:", 5) == 0, FALSE);
+
+ split = g_strsplit (prop_descr, ":", 0);
+ g_return_val_if_fail (split != NULL, FALSE);
+
+ len = g_strv_length (split);
+ if (len == 3
+ && ews_decode_mapi_property_string_type (split[1], data_type)
+ && ews_decode_mapi_property_string_id (split[2], prop_id)) {
+ res = TRUE;
+ } else if (len == 5
+ && g_ascii_strcasecmp (split[1], "dist") == 0
+ && ews_decode_mapi_property_string_type (split[2], data_type)
+ && ews_decode_mapi_property_string_id (split[4], prop_id)) {
+ *distinguished_set_id = g_strdup (split[3]);
+ res = *distinguished_set_id && **distinguished_set_id;
+ }
+
+ g_strfreev (split);
+
+ return res;
+}
+
void
e_ews_connection_get_items (EEwsConnection *cnc,
gint pri,
@@ -3875,12 +3965,28 @@ e_ews_connection_get_items (EEwsConnection *cnc,
e_soap_message_start_element (msg, "AdditionalProperties", NULL, NULL);
while (prop[i]) {
- /* XX FIXME: Come up with a better way of doing this */
- if (!g_ascii_strncasecmp (prop[i], "mapi:int:0x", 11)) {
- e_soap_message_start_element (msg, "ExtendedFieldURI", NULL, NULL);
- e_soap_message_add_attribute (msg, "PropertyTag", prop[i] + 9, NULL, NULL);
- e_soap_message_add_attribute (msg, "PropertyType", "Integer", NULL, NULL);
- e_soap_message_end_element (msg);
+ if (g_ascii_strncasecmp (prop[i], "mapi:", 5) == 0) {
+ EEwsMessageDataType data_type;
+ guint32 prop_id = -1;
+ gchar *distinguished_set_id = NULL;
+
+ if (ews_decode_mapi_property_string (prop[i], &data_type, &prop_id,
&distinguished_set_id)) {
+ const gchar *prop_type = e_ews_message_data_type_get_xml_name
(data_type);
+
+ if (prop_type) {
+ if (distinguished_set_id) {
+ e_ews_message_write_extended_distinguished_tag (msg,
distinguished_set_id, prop_id, prop_type);
+ } else {
+ e_ews_message_write_extended_tag (msg, prop_id,
prop_type);
+ }
+ } else {
+ g_warning ("%s: Failed to decode mapi property type from
'%s'", G_STRFUNC, prop[i]);
+ }
+ } else {
+ g_warning ("%s: Failed to decode mapi property from '%s'", G_STRFUNC,
prop[i]);
+ }
+
+ g_free (distinguished_set_id);
} else {
e_ews_message_write_string_parameter_with_attribute (msg, "FieldURI", NULL,
NULL, "FieldURI", prop[i]);
}
diff --git a/src/server/e-ews-item-change.c b/src/server/e-ews-item-change.c
index b598aa0..38270c1 100644
--- a/src/server/e-ews-item-change.c
+++ b/src/server/e-ews-item-change.c
@@ -195,3 +195,374 @@ e_ews_message_add_delete_item_field_indexed (ESoapMessage *msg,
g_free (fielduri);
}
+
+const gchar *
+e_ews_message_data_type_get_xml_name (EEwsMessageDataType data_type)
+{
+ switch (data_type) {
+ case E_EWS_MESSAGE_DATA_TYPE_BOOLEAN:
+ return "Boolean";
+ case E_EWS_MESSAGE_DATA_TYPE_INT:
+ return "Integer";
+ case E_EWS_MESSAGE_DATA_TYPE_DOUBLE:
+ return "Double";
+ case E_EWS_MESSAGE_DATA_TYPE_STRING:
+ return "String";
+ case E_EWS_MESSAGE_DATA_TYPE_TIME:
+ return "SystemTime";
+ }
+
+ g_warn_if_reached ();
+
+ return NULL;
+}
+
+void
+e_ews_message_add_delete_item_field_extended_tag (ESoapMessage *msg,
+ guint32 prop_id,
+ EEwsMessageDataType data_type)
+{
+ const gchar *prop_type = e_ews_message_data_type_get_xml_name (data_type);
+
+ g_return_if_fail (prop_type != NULL);
+
+ e_soap_message_start_element (msg, "DeleteItemField", NULL, NULL);
+ e_ews_message_write_extended_tag (msg, prop_id, prop_type);
+ e_soap_message_end_element (msg); /* DeleteItemField */
+}
+
+void
+e_ews_message_add_delete_item_field_extended_distinguished_tag (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ EEwsMessageDataType data_type)
+{
+ const gchar *prop_type = e_ews_message_data_type_get_xml_name (data_type);
+
+ g_return_if_fail (prop_type != NULL);
+
+ e_soap_message_start_element (msg, "DeleteItemField", NULL, NULL);
+ e_ews_message_write_extended_distinguished_tag (msg, set_id, prop_id, prop_type);
+ e_soap_message_end_element (msg); /* DeleteItemField */
+}
+
+static void
+ews_message_write_data_value (ESoapMessage *msg,
+ EEwsMessageDataType data_type,
+ gconstpointer value)
+{
+ g_return_if_fail (value != NULL);
+
+ switch (data_type) {
+ case E_EWS_MESSAGE_DATA_TYPE_BOOLEAN:
+ e_ews_message_write_string_parameter (msg, "Value", NULL, (*((const gboolean *) value)) ?
"true" : "false");
+ return;
+ case E_EWS_MESSAGE_DATA_TYPE_INT:
+ e_ews_message_write_int_parameter (msg, "Value", NULL, *((const gint *) value));
+ return;
+ case E_EWS_MESSAGE_DATA_TYPE_DOUBLE:
+ e_ews_message_write_double_parameter (msg, "Value", NULL, *((const gdouble *) value));
+ return;
+ case E_EWS_MESSAGE_DATA_TYPE_STRING:
+ e_ews_message_write_string_parameter (msg, "Value", NULL, (const gchar *) value);
+ return;
+ case E_EWS_MESSAGE_DATA_TYPE_TIME:
+ e_ews_message_write_time_parameter (msg, "Value", NULL, *((const time_t *) value));
+ return;
+ }
+
+ g_warn_if_reached ();
+}
+
+static void
+ews_message_add_extended_property_tag (ESoapMessage *msg,
+ guint32 prop_id,
+ EEwsMessageDataType data_type,
+ gconstpointer value)
+{
+ const gchar *prop_type = e_ews_message_data_type_get_xml_name (data_type);
+
+ g_return_if_fail (prop_type != NULL);
+
+ e_soap_message_start_element (msg, "ExtendedProperty", NULL, NULL);
+
+ e_ews_message_write_extended_tag (msg, prop_id, prop_type);
+ ews_message_write_data_value (msg, data_type, value);
+
+ e_soap_message_end_element (msg); /* ExtendedProperty */
+}
+
+static void
+ews_message_add_extended_property_distinguished_tag (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ EEwsMessageDataType data_type,
+ gconstpointer value)
+{
+ const gchar *prop_type = e_ews_message_data_type_get_xml_name (data_type);
+
+ g_return_if_fail (prop_type != NULL);
+
+ e_soap_message_start_element (msg, "ExtendedProperty", NULL, NULL);
+
+ e_ews_message_write_extended_distinguished_tag (msg, set_id, prop_id, prop_type);
+ ews_message_write_data_value (msg, data_type, value);
+
+ e_soap_message_end_element (msg); /* ExtendedProperty */
+}
+
+static void
+ews_message_add_set_item_field_extended_tag (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ guint32 prop_id,
+ EEwsMessageDataType data_type,
+ gconstpointer value)
+{
+ const gchar *prop_type = e_ews_message_data_type_get_xml_name (data_type);
+
+ g_return_if_fail (prop_type != NULL);
+
+ e_soap_message_start_element (msg, "SetItemField", NULL, NULL);
+ e_ews_message_write_extended_tag (msg, prop_id, prop_type);
+
+ e_soap_message_start_element (msg, elem_name, elem_prefix, NULL);
+ ews_message_add_extended_property_tag (msg, prop_id, data_type, value);
+ e_soap_message_end_element (msg); /* elem_name */
+
+ e_soap_message_end_element (msg); /* SetItemField */
+}
+
+static void
+ews_message_add_set_item_field_extended_distinguished_tag (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ const gchar *set_id,
+ guint32 prop_id,
+ EEwsMessageDataType data_type,
+ gconstpointer value)
+{
+ const gchar *prop_type = e_ews_message_data_type_get_xml_name (data_type);
+
+ g_return_if_fail (prop_type != NULL);
+
+ e_soap_message_start_element (msg, "SetItemField", NULL, NULL);
+
+ e_ews_message_write_extended_distinguished_tag (msg, set_id, prop_id, prop_type);
+
+ e_soap_message_start_element (msg, elem_name, elem_prefix, NULL);
+ ews_message_add_extended_property_distinguished_tag (msg, set_id, prop_id, data_type, value);
+ e_soap_message_end_element (msg); /* elem_name */
+
+ e_soap_message_end_element (msg); /* SetItemField */
+}
+
+void
+e_ews_message_add_set_item_field_extended_tag_boolean (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ guint32 prop_id,
+ gboolean value)
+{
+ ews_message_add_set_item_field_extended_tag (msg, elem_prefix, elem_name, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_BOOLEAN, &value);
+}
+
+void
+e_ews_message_add_set_item_field_extended_tag_int (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ guint32 prop_id,
+ gint value)
+{
+ ews_message_add_set_item_field_extended_tag (msg, elem_prefix, elem_name, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_INT, &value);
+}
+
+void
+e_ews_message_add_set_item_field_extended_tag_double (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ guint32 prop_id,
+ gdouble value)
+{
+ ews_message_add_set_item_field_extended_tag (msg, elem_prefix, elem_name, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_DOUBLE, &value);
+}
+
+void
+e_ews_message_add_set_item_field_extended_tag_string (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ guint32 prop_id,
+ const gchar *value)
+{
+ ews_message_add_set_item_field_extended_tag (msg, elem_prefix, elem_name, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_STRING, value);
+}
+
+void
+e_ews_message_add_set_item_field_extended_tag_time (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ guint32 prop_id,
+ time_t value)
+{
+ ews_message_add_set_item_field_extended_tag (msg, elem_prefix, elem_name, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_TIME, &value);
+}
+
+void
+e_ews_message_add_set_item_field_extended_distinguished_tag_boolean (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ const gchar *set_id,
+ guint32 prop_id,
+ gboolean value)
+{
+ ews_message_add_set_item_field_extended_distinguished_tag (msg, elem_prefix, elem_name, set_id,
prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_BOOLEAN, &value);
+}
+
+void
+e_ews_message_add_set_item_field_extended_distinguished_tag_int (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ const gchar *set_id,
+ guint32 prop_id,
+ gint value)
+{
+ ews_message_add_set_item_field_extended_distinguished_tag (msg, elem_prefix, elem_name, set_id,
prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_INT, &value);
+}
+
+void
+e_ews_message_add_set_item_field_extended_distinguished_tag_double (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ const gchar *set_id,
+ guint32 prop_id,
+ gdouble value)
+{
+ ews_message_add_set_item_field_extended_distinguished_tag (msg, elem_prefix, elem_name, set_id,
prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_DOUBLE, &value);
+}
+
+void
+e_ews_message_add_set_item_field_extended_distinguished_tag_string (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ const gchar *set_id,
+ guint32 prop_id,
+ const gchar *value)
+{
+ ews_message_add_set_item_field_extended_distinguished_tag (msg, elem_prefix, elem_name, set_id,
prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_STRING, value);
+}
+
+void
+e_ews_message_add_set_item_field_extended_distinguished_tag_time (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ const gchar *set_id,
+ guint32 prop_id,
+ time_t value)
+{
+ ews_message_add_set_item_field_extended_distinguished_tag (msg, elem_prefix, elem_name, set_id,
prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_TIME, &value);
+}
+
+void
+e_ews_message_add_extended_property_tag_boolean (ESoapMessage *msg,
+ guint32 prop_id,
+ gboolean value)
+{
+ ews_message_add_extended_property_tag (msg, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_BOOLEAN, &value);
+}
+
+void
+e_ews_message_add_extended_property_tag_int (ESoapMessage *msg,
+ guint32 prop_id,
+ gint value)
+{
+ ews_message_add_extended_property_tag (msg, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_INT, &value);
+}
+
+void
+e_ews_message_add_extended_property_tag_double (ESoapMessage *msg,
+ guint32 prop_id,
+ gdouble value)
+{
+ ews_message_add_extended_property_tag (msg, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_DOUBLE, &value);
+}
+
+void
+e_ews_message_add_extended_property_tag_string (ESoapMessage *msg,
+ guint32 prop_id,
+ const gchar *value)
+{
+ ews_message_add_extended_property_tag (msg, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_STRING, value);
+}
+
+void
+e_ews_message_add_extended_property_tag_time (ESoapMessage *msg,
+ guint32 prop_id,
+ time_t value)
+{
+ ews_message_add_extended_property_tag (msg, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_TIME, &value);
+}
+
+void
+e_ews_message_add_extended_property_distinguished_tag_boolean (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ gboolean value)
+{
+ ews_message_add_extended_property_distinguished_tag (msg, set_id, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_BOOLEAN, &value);
+}
+
+void
+e_ews_message_add_extended_property_distinguished_tag_int (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ gint value)
+{
+ ews_message_add_extended_property_distinguished_tag (msg, set_id, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_INT, &value);
+}
+
+void
+e_ews_message_add_extended_property_distinguished_tag_double (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ gdouble value)
+{
+ ews_message_add_extended_property_distinguished_tag (msg, set_id, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_DOUBLE, &value);
+}
+
+void
+e_ews_message_add_extended_property_distinguished_tag_string (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ const gchar *value)
+{
+ ews_message_add_extended_property_distinguished_tag (msg, set_id, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_STRING, value);
+}
+
+void
+e_ews_message_add_extended_property_distinguished_tag_time (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ time_t value)
+{
+ ews_message_add_extended_property_distinguished_tag (msg, set_id, prop_id,
+ E_EWS_MESSAGE_DATA_TYPE_TIME, &value);
+}
diff --git a/src/server/e-ews-item-change.h b/src/server/e-ews-item-change.h
index 7b8d5c5..0102daa 100644
--- a/src/server/e-ews-item-change.h
+++ b/src/server/e-ews-item-change.h
@@ -51,6 +51,128 @@ void e_ews_message_add_delete_item_field (ESoapMessage *msg, const gchar *name,
void e_ews_message_add_delete_item_field_indexed (ESoapMessage *msg, const gchar *name, const gchar
*fielduri_prefix, const gchar *field_index);
+typedef enum {
+ E_EWS_MESSAGE_DATA_TYPE_BOOLEAN,
+ E_EWS_MESSAGE_DATA_TYPE_INT,
+ E_EWS_MESSAGE_DATA_TYPE_DOUBLE,
+ E_EWS_MESSAGE_DATA_TYPE_STRING,
+ E_EWS_MESSAGE_DATA_TYPE_TIME
+} EEwsMessageDataType;
+
+const gchar *
+ e_ews_message_data_type_get_xml_name (EEwsMessageDataType data_type);
+
+void e_ews_message_add_delete_item_field_extended_tag (ESoapMessage *msg,
+ guint32 prop_id,
+ EEwsMessageDataType data_type);
+
+void e_ews_message_add_delete_item_field_extended_distinguished_tag
+ (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ EEwsMessageDataType data_type);
+
+void e_ews_message_add_set_item_field_extended_tag_boolean (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ guint32 prop_id,
+ gboolean value);
+void e_ews_message_add_set_item_field_extended_tag_int (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ guint32 prop_id,
+ gint value);
+void e_ews_message_add_set_item_field_extended_tag_double (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ guint32 prop_id,
+ gdouble value);
+void e_ews_message_add_set_item_field_extended_tag_string (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ guint32 prop_id,
+ const gchar *value);
+void e_ews_message_add_set_item_field_extended_tag_time (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ guint32 prop_id,
+ time_t value);
+void e_ews_message_add_set_item_field_extended_distinguished_tag_boolean
+ (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ const gchar *set_id,
+ guint32 prop_id,
+ gboolean value);
+void e_ews_message_add_set_item_field_extended_distinguished_tag_int
+ (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ const gchar *set_id,
+ guint32 prop_id,
+ gint value);
+void e_ews_message_add_set_item_field_extended_distinguished_tag_double
+ (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ const gchar *set_id,
+ guint32 prop_id,
+ gdouble value);
+void e_ews_message_add_set_item_field_extended_distinguished_tag_string
+ (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ const gchar *set_id,
+ guint32 prop_id,
+ const gchar *value);
+void e_ews_message_add_set_item_field_extended_distinguished_tag_time
+ (ESoapMessage *msg,
+ const gchar *elem_prefix,
+ const gchar *elem_name,
+ const gchar *set_id,
+ guint32 prop_id,
+ time_t value);
+void e_ews_message_add_extended_property_tag_boolean (ESoapMessage *msg,
+ guint32 prop_id,
+ gboolean value);
+void e_ews_message_add_extended_property_tag_int (ESoapMessage *msg,
+ guint32 prop_id,
+ gint value);
+void e_ews_message_add_extended_property_tag_double (ESoapMessage *msg,
+ guint32 prop_id,
+ gdouble value);
+void e_ews_message_add_extended_property_tag_string (ESoapMessage *msg,
+ guint32 prop_id,
+ const gchar *value);
+void e_ews_message_add_extended_property_tag_time (ESoapMessage *msg,
+ guint32 prop_id,
+ time_t value);
+void e_ews_message_add_extended_property_distinguished_tag_boolean
+ (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ gboolean value);
+void e_ews_message_add_extended_property_distinguished_tag_int
+ (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ gint value);
+void e_ews_message_add_extended_property_distinguished_tag_double
+ (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ gdouble value);
+void e_ews_message_add_extended_property_distinguished_tag_string
+ (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ const gchar *value);
+void e_ews_message_add_extended_property_distinguished_tag_time
+ (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ time_t value);
+
G_END_DECLS
#endif
diff --git a/src/server/e-ews-item.c b/src/server/e-ews-item.c
index a096280..c137dd0 100644
--- a/src/server/e-ews-item.c
+++ b/src/server/e-ews-item.c
@@ -32,6 +32,7 @@
#include <glib/gprintf.h>
#include <libsoup/soup-misc.h>
#include "e-ews-item.h"
+#include "e-ews-item-change.h"
#ifdef G_OS_WIN32
@@ -158,6 +159,9 @@ struct _EEwsItemPrivate {
guint32 mapi_message_status; /* http://msdn.microsoft.com/en-us/library/cc839915.aspx */
guint32 mapi_message_flags; /* http://msdn.microsoft.com/en-us/library/cc839733.aspx */
+ GHashTable *mapi_extended_tags; /* simple tag->string_value */
+ GHashTable *mapi_extended_sets; /* setid-> [ tag->string_value ] */
+
/* properties */
EwsId *item_id;
gchar *subject;
@@ -220,6 +224,16 @@ e_ews_item_dispose (GObject *object)
g_clear_error (&priv->error);
+ if (priv->mapi_extended_sets) {
+ g_hash_table_destroy (priv->mapi_extended_sets);
+ priv->mapi_extended_sets = NULL;
+ }
+
+ if (priv->mapi_extended_tags) {
+ g_hash_table_destroy (priv->mapi_extended_tags);
+ priv->mapi_extended_tags = NULL;
+ }
+
if (priv->item_id) {
g_free (priv->item_id->id);
g_free (priv->item_id->change_key);
@@ -348,6 +362,9 @@ e_ews_item_init (EEwsItem *item)
item->priv = priv;
priv->item_type = E_EWS_ITEM_TYPE_UNKNOWN;
+
+ priv->mapi_extended_tags = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+ priv->mapi_extended_sets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)
g_hash_table_destroy);
}
static void
@@ -452,9 +469,10 @@ static void
parse_extended_property (EEwsItemPrivate *priv,
ESoapParameter *param)
{
+ EEwsMessageDataType data_type;
ESoapParameter *subparam;
- gchar *str;
- guint32 tag, value;
+ gchar *str, *setid;
+ guint32 tag;
subparam = e_soap_parameter_get_first_child_by_name (param, "ExtendedFieldURI");
if (!subparam)
@@ -464,53 +482,84 @@ parse_extended_property (EEwsItemPrivate *priv,
if (!str)
return;
- /* We only handle integer MAPI properties for now... */
- if (g_ascii_strcasecmp (str, "Integer")) {
+ /* We only handle some MAPI properties for now... */
+ if (g_ascii_strcasecmp (str, "Boolean") == 0) {
+ data_type = E_EWS_MESSAGE_DATA_TYPE_BOOLEAN;
+ } else if (g_ascii_strcasecmp (str, "Integer") == 0) {
+ data_type = E_EWS_MESSAGE_DATA_TYPE_INT;
+ } else if (g_ascii_strcasecmp (str, "Double") == 0) {
+ data_type = E_EWS_MESSAGE_DATA_TYPE_DOUBLE;
+ } else if (g_ascii_strcasecmp (str, "String") == 0) {
+ data_type = E_EWS_MESSAGE_DATA_TYPE_STRING;
+ } else if (g_ascii_strcasecmp (str, "SystemTime") == 0) {
+ data_type = E_EWS_MESSAGE_DATA_TYPE_TIME;
+ } else {
g_free (str);
return;
}
g_free (str);
str = e_soap_parameter_get_property (subparam, "PropertyTag");
- if (!str)
- return;
+ if (!str) {
+ str = e_soap_parameter_get_property (subparam, "PropertyId");
+ if (!str)
+ return;
+ }
tag = strtol (str, NULL, 0);
g_free (str);
+ setid = e_soap_parameter_get_property (subparam, "DistinguishedPropertySetId");
+
subparam = e_soap_parameter_get_first_child_by_name (param, "Value");
- if (!subparam)
+ if (!subparam) {
+ g_free (setid);
return;
+ }
str = e_soap_parameter_get_string_value (subparam);
- if (!str)
+ if (!str) {
+ g_free (setid);
return;
+ }
- value = strtol (str, NULL, 0);
- g_free (str);
+ if (data_type == E_EWS_MESSAGE_DATA_TYPE_INT) {
+ guint32 value;
- switch (tag) {
- case 0x01080: /* PidTagIconIndex */
- priv->mapi_icon_index = value;
- break;
+ value = strtol (str, NULL, 0);
- case 0x1081:
- priv->mapi_last_verb_executed = value;
- break;
+ switch (tag) {
+ case 0x01080: /* PidTagIconIndex */
+ priv->mapi_icon_index = value;
+ break;
- case 0xe07:
- priv->mapi_message_flags = value;
- break;
+ case 0x1081:
+ priv->mapi_last_verb_executed = value;
+ break;
- case 0xe17:
- priv->mapi_message_status = value;
- break;
+ case 0xe07:
+ priv->mapi_message_flags = value;
+ break;
- default:
- g_print (
- "Fetched unrecognised MAPI property 0x%x, value %d\n",
- tag, value);
+ case 0xe17:
+ priv->mapi_message_status = value;
+ break;
+ }
}
+
+ if (setid) {
+ GHashTable *set_hash = g_hash_table_lookup (priv->mapi_extended_sets, setid);
+ if (!set_hash) {
+ set_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+ g_hash_table_insert (priv->mapi_extended_sets, setid, set_hash);
+ }
+
+ g_hash_table_insert (set_hash, GUINT_TO_POINTER (tag), g_strdup (str));
+ } else {
+ g_hash_table_insert (priv->mapi_extended_tags, GUINT_TO_POINTER (tag), g_strdup (str));
+ }
+
+ g_free (str);
}
static void
@@ -1500,6 +1549,131 @@ e_ews_item_get_attachments_ids (EEwsItem *item)
return item->priv->attachments_ids;
}
+const gchar *
+e_ews_item_get_extended_tag (EEwsItem *item,
+ guint32 prop_tag)
+{
+ g_return_val_if_fail (E_IS_EWS_ITEM (item), NULL);
+
+ if (!item->priv->mapi_extended_tags)
+ return NULL;
+
+ return g_hash_table_lookup (item->priv->mapi_extended_tags, GUINT_TO_POINTER (prop_tag));
+}
+
+const gchar *
+e_ews_item_get_extended_distinguished_tag (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id)
+{
+ GHashTable *set_tags;
+
+ g_return_val_if_fail (E_IS_EWS_ITEM (item), NULL);
+
+ if (!item->priv->mapi_extended_sets)
+ return NULL;
+
+ set_tags = g_hash_table_lookup (item->priv->mapi_extended_sets, set_id);
+ if (!set_tags)
+ return NULL;
+
+ return g_hash_table_lookup (set_tags, GUINT_TO_POINTER (prop_id));
+}
+
+gboolean
+e_ews_item_get_extended_property_as_boolean (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id_or_tag,
+ gboolean *found)
+{
+ const gchar *value;
+
+ value = e_ews_item_get_extended_property_as_string (item, set_id, prop_id_or_tag, found);
+ if (!value)
+ return FALSE;
+
+ if (g_str_equal (value, "true"))
+ return TRUE;
+
+ if (g_str_equal (value, "true"))
+ return FALSE;
+
+ if (found)
+ *found = FALSE;
+ return FALSE;
+}
+
+gint
+e_ews_item_get_extended_property_as_int (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id_or_tag,
+ gboolean *found)
+{
+ const gchar *value;
+
+ value = e_ews_item_get_extended_property_as_string (item, set_id, prop_id_or_tag, found);
+ if (!value)
+ return 0;
+
+ return strtol (value, NULL, 0);
+}
+
+gdouble
+e_ews_item_get_extended_property_as_double (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id_or_tag,
+ gboolean *found)
+{
+ const gchar *value;
+
+ value = e_ews_item_get_extended_property_as_string (item, set_id, prop_id_or_tag, found);
+ if (!value)
+ return 0.0;
+
+ return g_ascii_strtod (value, NULL);
+}
+
+const gchar *
+e_ews_item_get_extended_property_as_string (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id_or_tag,
+ gboolean *found)
+{
+ const gchar *value;
+
+ if (set_id)
+ value = e_ews_item_get_extended_distinguished_tag (item, set_id, prop_id_or_tag);
+ else
+ value = e_ews_item_get_extended_tag (item, prop_id_or_tag);
+
+ if (found)
+ *found = value != NULL;
+
+ return value;
+}
+
+time_t
+e_ews_item_get_extended_property_as_time (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id_or_tag,
+ gboolean *found)
+{
+ const gchar *value;
+ GTimeVal tv;
+
+ value = e_ews_item_get_extended_property_as_string (item, set_id, prop_id_or_tag, found);
+ if (!value)
+ return (time_t) 0;
+
+ if (g_time_val_from_iso8601 (value, &tv))
+ return tv.tv_sec;
+
+ if (found)
+ *found = FALSE;
+
+ return (time_t) 0;
+}
+
gchar *
e_ews_embed_attachment_id_in_uri (const gchar *olduri,
const gchar *attach_id)
diff --git a/src/server/e-ews-item.h b/src/server/e-ews-item.h
index 5a7309e..3e3dddd 100644
--- a/src/server/e-ews-item.h
+++ b/src/server/e-ews-item.h
@@ -225,6 +225,37 @@ const GSList * e_ews_item_get_modified_occurrences
gchar * e_ews_embed_attachment_id_in_uri (const gchar *olduri, const gchar *attach_id);
GSList * e_ews_item_get_attachments_ids
(EEwsItem *item);
+const gchar * e_ews_item_get_extended_tag (EEwsItem *item,
+ guint32 prop_tag);
+const gchar * e_ews_item_get_extended_distinguished_tag
+ (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id);
+gboolean e_ews_item_get_extended_property_as_boolean
+ (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id_or_tag,
+ gboolean *found);
+gint e_ews_item_get_extended_property_as_int
+ (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id_or_tag,
+ gboolean *found);
+gdouble e_ews_item_get_extended_property_as_double
+ (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id_or_tag,
+ gboolean *found);
+const gchar * e_ews_item_get_extended_property_as_string
+ (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id_or_tag,
+ gboolean *found);
+time_t e_ews_item_get_extended_property_as_time
+ (EEwsItem *item,
+ const gchar *set_id,
+ guint32 prop_id_or_tag,
+ gboolean *found);
EEwsAttachmentInfo *
e_ews_dump_file_attachment_from_soap_parameter (ESoapParameter *param, const gchar *cache, const gchar
*comp_uid);
diff --git a/src/server/e-ews-message.c b/src/server/e-ews-message.c
index 5803bfa..7d353b2 100644
--- a/src/server/e-ews-message.c
+++ b/src/server/e-ews-message.c
@@ -188,6 +188,28 @@ e_ews_message_write_int_parameter (ESoapMessage *msg,
}
void
+e_ews_message_write_double_parameter (ESoapMessage *msg,
+ const gchar *name,
+ const gchar *prefix,
+ gdouble value)
+{
+ e_soap_message_start_element (msg, name, prefix, NULL);
+ e_soap_message_write_double (msg, value);
+ e_soap_message_end_element (msg);
+}
+
+void
+e_ews_message_write_time_parameter (ESoapMessage *msg,
+ const gchar *name,
+ const gchar *prefix,
+ time_t value)
+{
+ e_soap_message_start_element (msg, name, prefix, NULL);
+ e_soap_message_write_time (msg, value);
+ e_soap_message_end_element (msg);
+}
+
+void
e_ews_message_write_footer (ESoapMessage *msg)
{
e_soap_message_end_element (msg);
@@ -196,3 +218,39 @@ e_ews_message_write_footer (ESoapMessage *msg)
e_soap_message_persist (msg);
}
+
+void
+e_ews_message_write_extended_tag (ESoapMessage *msg,
+ guint32 prop_id,
+ const gchar *prop_type)
+{
+ gchar *num;
+
+ num = g_strdup_printf ("%d", prop_id);
+
+ e_soap_message_start_element (msg, "ExtendedFieldURI", NULL, NULL);
+ e_soap_message_add_attribute (msg, "PropertyTag", num, NULL, NULL);
+ e_soap_message_add_attribute (msg, "PropertyType", prop_type, NULL, NULL);
+ e_soap_message_end_element (msg); /* ExtendedFieldURI */
+
+ g_free (num);
+}
+
+void
+e_ews_message_write_extended_distinguished_tag (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ const gchar *prop_type)
+{
+ gchar *num;
+
+ num = g_strdup_printf ("%d", prop_id);
+
+ e_soap_message_start_element (msg, "ExtendedFieldURI", NULL, NULL);
+ e_soap_message_add_attribute (msg, "DistinguishedPropertySetId", set_id, NULL, NULL);
+ e_soap_message_add_attribute (msg, "PropertyId", num, NULL, NULL);
+ e_soap_message_add_attribute (msg, "PropertyType", prop_type, NULL, NULL);
+ e_soap_message_end_element (msg); /* ExtendedFieldURI */
+
+ g_free (num);
+}
diff --git a/src/server/e-ews-message.h b/src/server/e-ews-message.h
index 30f6920..28884a6 100644
--- a/src/server/e-ews-message.h
+++ b/src/server/e-ews-message.h
@@ -68,8 +68,29 @@ void e_ews_message_write_int_parameter
const gchar *name,
const gchar *prefix,
glong value);
+void e_ews_message_write_double_parameter
+ (ESoapMessage *msg,
+ const gchar *name,
+ const gchar *prefix,
+ gdouble value);
+void e_ews_message_write_time_parameter
+ (ESoapMessage *msg,
+ const gchar *name,
+ const gchar *prefix,
+ time_t value);
void e_ews_message_write_footer (ESoapMessage *msg);
+void e_ews_message_write_extended_tag
+ (ESoapMessage *msg,
+ guint32 prop_id,
+ const gchar *prop_type);
+
+void e_ews_message_write_extended_distinguished_tag
+ (ESoapMessage *msg,
+ const gchar *set_id,
+ guint32 prop_id,
+ const gchar *prop_type);
+
G_END_DECLS
#endif
diff --git a/src/server/e-soap-message.c b/src/server/e-soap-message.c
index 903b5f8..ca7e39c 100644
--- a/src/server/e-soap-message.c
+++ b/src/server/e-soap-message.c
@@ -844,21 +844,26 @@ e_soap_message_write_base64 (ESoapMessage *msg,
/**
* e_soap_message_write_time:
* @msg: the #ESoapMessage.
- * @timeval: pointer to a time_t to encode
+ * @timeval: the time_t to encode
*
- * Writes the stringified value of @timeval as the current element's
+ * Writes the iso8601 value of @timeval as the current element's
* content.
**/
void
e_soap_message_write_time (ESoapMessage *msg,
- const time_t *timeval)
+ time_t timeval)
{
- gchar *string;
+ GTimeVal tv;
+ gchar *iso_time;
g_return_if_fail (E_IS_SOAP_MESSAGE (msg));
- string = g_strchomp (ctime (timeval));
- e_soap_message_write_string (msg, string);
+ tv.tv_usec = 0;
+ tv.tv_sec = timeval;
+
+ iso_time = g_time_val_to_iso8601 (&tv);
+ e_soap_message_write_string (msg, iso_time);
+ g_free (iso_time);
}
/**
diff --git a/src/server/e-soap-message.h b/src/server/e-soap-message.h
index c44b73d..b2e0fa1 100644
--- a/src/server/e-soap-message.h
+++ b/src/server/e-soap-message.h
@@ -94,7 +94,7 @@ void e_soap_message_write_base64 (ESoapMessage *msg,
const gchar *string,
gint len);
void e_soap_message_write_time (ESoapMessage *msg,
- const time_t *timeval);
+ time_t timeval);
void e_soap_message_write_string (ESoapMessage *msg,
const gchar *string);
void e_soap_message_write_buffer (ESoapMessage *msg,
diff --git a/src/utils/ews-camel-common.c b/src/utils/ews-camel-common.c
index 9dd6d8e..768c3a7 100644
--- a/src/utils/ews-camel-common.c
+++ b/src/utils/ews-camel-common.c
@@ -28,10 +28,11 @@
#include "ews-camel-common.h"
#include "server/e-ews-message.h"
+#include "server/e-ews-item-change.h"
struct _create_mime_msg_data {
CamelMimeMessage *message;
- gint32 message_camel_flags;
+ CamelMessageInfo *info;
CamelAddress *from;
CamelAddress *recipients;
};
@@ -117,7 +118,11 @@ create_mime_message_cb (ESoapMessage *msg,
GByteArray *bytes;
gchar *base64;
gint msgflag;
+ guint32 message_camel_flags = 0;
+ if (create_data->info)
+ message_camel_flags = camel_message_info_flags (create_data->info);
+
e_soap_message_start_element (msg, "Message", NULL, NULL);
e_soap_message_start_element (msg, "MimeContent", NULL, NULL);
@@ -169,7 +174,7 @@ create_mime_message_cb (ESoapMessage *msg,
msg,
"Importance",
NULL,
- (create_data->message_camel_flags & CAMEL_MESSAGE_FLAGGED) != 0 ? "High" : "Normal",
+ (message_camel_flags & CAMEL_MESSAGE_FLAGGED) != 0 ? "High" : "Normal",
NULL,
NULL);
@@ -179,34 +184,82 @@ create_mime_message_cb (ESoapMessage *msg,
* sees this property that you're setting the value to 0
* ... it never checks */
msgflag = MAPI_MSGFLAG_READ; /* draft or sent is always read */
- if ((create_data->message_camel_flags & CAMEL_MESSAGE_DRAFT) != 0)
+ if ((message_camel_flags & CAMEL_MESSAGE_DRAFT) != 0)
msgflag |= MAPI_MSGFLAG_UNSENT;
- e_soap_message_start_element (msg, "ExtendedProperty", NULL, NULL);
- e_soap_message_start_element (msg, "ExtendedFieldURI", NULL, NULL);
- e_soap_message_add_attribute (msg, "PropertyTag", "0x0E07", NULL, NULL);
- e_soap_message_add_attribute (msg, "PropertyType", "Integer", NULL, NULL);
- e_soap_message_end_element (msg); /* ExtendedFieldURI */
+ e_ews_message_add_extended_property_tag_int (msg, 0x0e07, msgflag);
- e_ews_message_write_int_parameter (msg, "Value", NULL, msgflag);
+ if ((message_camel_flags & (CAMEL_MESSAGE_FORWARDED | CAMEL_MESSAGE_ANSWERED)) != 0) {
+ gint icon;
- e_soap_message_end_element (msg); /* ExtendedProperty */
+ icon = (message_camel_flags & CAMEL_MESSAGE_ANSWERED) != 0 ? 0x105 : 0x106;
- if ((create_data->message_camel_flags & (CAMEL_MESSAGE_FORWARDED | CAMEL_MESSAGE_ANSWERED)) != 0) {
- gint icon;
+ e_ews_message_add_extended_property_tag_int (msg, 0x1080, icon);
+ }
+
+ if (create_data->info) {
+ const gchar *followup, *completed, *dueby;
+ time_t completed_tt = (time_t) 0 , dueby_tt = (time_t) 0;
+
+ /* follow-up flags */
+ followup = camel_message_info_user_tag (create_data->info, "follow-up");
+ completed = camel_message_info_user_tag (create_data->info, "completed-on");
+ dueby = camel_message_info_user_tag (create_data->info, "due-by");
- icon = (create_data->message_camel_flags & CAMEL_MESSAGE_ANSWERED) != 0 ? 0x105 : 0x106;
+ if (followup && !*followup)
+ followup = NULL;
- e_soap_message_start_element (msg, "ExtendedProperty", NULL, NULL);
+ if (completed && *completed)
+ completed_tt = camel_header_decode_date (completed, NULL);
+
+ if (dueby && *dueby)
+ dueby_tt = camel_header_decode_date (dueby, NULL);
+
+ /* PidTagFlagStatus */
+ e_ews_message_add_extended_property_tag_int (msg, 0x1090,
+ followup ? (completed_tt != (time_t) 0 ? 0x01 /* followupComplete */: 0x02 /*
followupFlagged */) : 0x0);
+
+ if (followup) {
+ /* PidLidFlagRequest */
+ e_ews_message_add_extended_property_distinguished_tag_string (msg, "Common", 0x8530,
followup);
+
+ /* PidTagToDoItemFlags */
+ e_ews_message_add_extended_property_tag_int (msg, 0x0e2b, 1);
+ }
- e_soap_message_start_element (msg, "ExtendedFieldURI", NULL, NULL);
- e_soap_message_add_attribute (msg, "PropertyTag", "0x1080", NULL, NULL);
- e_soap_message_add_attribute (msg, "PropertyType", "Integer", NULL, NULL);
- e_soap_message_end_element (msg); /* ExtendedFieldURI */
+ if (followup && completed_tt != (time_t) 0) {
+ /* minute precision */
+ completed_tt = completed_tt - (completed_tt % 60);
- e_ews_message_write_int_parameter (msg, "Value", NULL, icon);
+ /* PidTagFlagCompleteTime */
+ e_ews_message_add_extended_property_tag_time (msg, 0x1091, completed_tt);
- e_soap_message_end_element (msg); /* ExtendedProperty */
+ /* PidLidTaskDateCompleted */
+ e_ews_message_add_extended_property_distinguished_tag_time (msg, "Task", 0x810f,
completed_tt);
+
+ /* PidLidTaskStatus */
+ e_ews_message_add_extended_property_distinguished_tag_int (msg, "Task", 0x8101, 2);
+
+ /* PidLidPercentComplete */
+ e_ews_message_add_extended_property_distinguished_tag_double (msg, "Task", 0x8102,
1.0);
+
+ /* PidLidTaskComplete */
+ e_ews_message_add_extended_property_distinguished_tag_boolean (msg, "Task", 0x811c,
TRUE);
+ }
+
+ if (followup && dueby_tt != (time_t) 0 && completed_tt == (time_t) 0) {
+ /* PidLidTaskStatus */
+ e_ews_message_add_extended_property_distinguished_tag_int (msg, "Task", 0x8101, 0);
+
+ /* PidLidPercentComplete */
+ e_ews_message_add_extended_property_distinguished_tag_double (msg, "Task", 0x8102,
0.0);
+
+ /* PidLidTaskDueDate */
+ e_ews_message_add_extended_property_distinguished_tag_time (msg, "Task", 0x8105,
dueby_tt);
+
+ /* PidLidTaskComplete */
+ e_ews_message_add_extended_property_distinguished_tag_boolean (msg, "Task", 0x811c,
FALSE);
+ }
}
if (create_data->recipients) {
@@ -231,7 +284,7 @@ create_mime_message_cb (ESoapMessage *msg,
msg,
"IsRead",
NULL,
- (create_data->message_camel_flags & CAMEL_MESSAGE_SEEN) != 0 ? "true" : "false",
+ (message_camel_flags & CAMEL_MESSAGE_SEEN) != 0 ? "true" : "false",
NULL,
NULL);
@@ -245,7 +298,7 @@ camel_ews_utils_create_mime_message (EEwsConnection *cnc,
const gchar *disposition,
const EwsFolderId *fid,
CamelMimeMessage *message,
- gint32 message_camel_flags,
+ CamelMessageInfo *info,
CamelAddress *from,
CamelAddress *recipients,
gchar **itemid,
@@ -263,7 +316,7 @@ camel_ews_utils_create_mime_message (EEwsConnection *cnc,
create_data = g_new0 (struct _create_mime_msg_data, 1);
create_data->message = message;
- create_data->message_camel_flags = message_camel_flags;
+ create_data->info = info;
create_data->from = from;
create_data->recipients = recipients;
diff --git a/src/utils/ews-camel-common.h b/src/utils/ews-camel-common.h
index cbb357e..2f9a37d 100644
--- a/src/utils/ews-camel-common.h
+++ b/src/utils/ews-camel-common.h
@@ -32,7 +32,7 @@ camel_ews_utils_create_mime_message (EEwsConnection *cnc,
const gchar *disposition,
const EwsFolderId *fid,
CamelMimeMessage *message,
- gint32 message_camel_flags,
+ CamelMessageInfo *info,
CamelAddress *from,
CamelAddress *recipients,
gchar **itemid,
@@ -42,9 +42,5 @@ camel_ews_utils_create_mime_message (EEwsConnection *cnc,
G_END_DECLS
-#ifdef __cplusplus
-}
-#endif
-
#endif /* EWS_CAMEL_COMMON_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]