[evolution-mapi/gnome-3-0] Bug #648732 - Meeting invitation response not recognized by Outlook
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi/gnome-3-0] Bug #648732 - Meeting invitation response not recognized by Outlook
- Date: Wed, 4 May 2011 12:45:00 +0000 (UTC)
commit 5917c6d9b2cb999a4fde8d3f91c6ac5d78bb9a87
Author: Milan Crha <mcrha redhat com>
Date: Wed May 4 14:44:41 2011 +0200
Bug #648732 - Meeting invitation response not recognized by Outlook
src/calendar/e-cal-backend-mapi.c | 132 +++++++++++++++++-------
src/libexchangemapi/exchange-mapi-cal-utils.c | 137 +++++++++++--------------
src/libexchangemapi/exchange-mapi-cal-utils.h | 2 +-
3 files changed, 157 insertions(+), 114 deletions(-)
---
diff --git a/src/calendar/e-cal-backend-mapi.c b/src/calendar/e-cal-backend-mapi.c
index ce66ad4..6946c15 100644
--- a/src/calendar/e-cal-backend-mapi.c
+++ b/src/calendar/e-cal-backend-mapi.c
@@ -642,32 +642,41 @@ mapi_cal_get_known_ids (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX
PR_SENT_REPRESENTING_NAME_UNICODE,
PR_SMTP_ADDRESS_UNICODE,
PR_START_DATE,
- PR_SUBJECT_UNICODE,
- PROP_TAG(PT_BINARY, 0x0003),
- PROP_TAG(PT_BINARY, 0x0023),
- PROP_TAG(PT_BINARY, 0x8216),
- PROP_TAG(PT_BINARY, 0x825E),
- PROP_TAG(PT_BINARY, 0x825F),
- PROP_TAG(PT_BOOLEAN, 0x8126),
- PROP_TAG(PT_BOOLEAN, 0x8215),
- PROP_TAG(PT_BOOLEAN, 0x8223),
- PROP_TAG(PT_BOOLEAN, 0x8503),
- PROP_TAG(PT_DOUBLE, 0x8102),
- PROP_TAG(PT_LONG, 0x8101),
- PROP_TAG(PT_LONG, 0x8201),
- PROP_TAG(PT_LONG, 0x8205),
- PROP_TAG(PT_STRING8, 0x8208),
- PROP_TAG(PT_SYSTIME, 0x8104),
- PROP_TAG(PT_SYSTIME, 0x8105),
- PROP_TAG(PT_SYSTIME, 0x810F),
- PROP_TAG(PT_SYSTIME, 0x820D),
- PROP_TAG(PT_SYSTIME, 0x820E),
- PROP_TAG(PT_SYSTIME, 0x8502),
- PROP_TAG(PT_SYSTIME, 0x8560)
+ PR_SUBJECT_UNICODE
+ };
+
+ /* do not make this array static, the function modifies it on run */
+ ResolveNamedIDsData known_nids[] = {
+ { PidLidGlobalObjectId, 0 },
+ { PidLidCleanGlobalObjectId, 0 },
+ { PidLidAppointmentRecur, 0 },
+ { PidLidAppointmentTimeZoneDefinitionStartDisplay, 0 },
+ { PidLidAppointmentTimeZoneDefinitionEndDisplay, 0 },
+ { PidLidTaskFRecurring, 0 },
+ { PidLidAppointmentSubType, 0 },
+ { PidLidRecurring, 0 },
+ { PidLidReminderSet, 0 },
+ { PidLidPercentComplete, 0 },
+ { PidLidTaskStatus, 0 },
+ { PidLidAppointmentSequence, 0 },
+ { PidLidBusyStatus, 0 },
+ { PidLidLocation, 0 },
+ { PidLidTaskStartDate, 0 },
+ { PidLidTaskDueDate, 0 },
+ { PidLidTaskDateCompleted, 0 },
+ { PidLidAppointmentStartWhole, 0 },
+ { PidLidAppointmentEndWhole, 0 },
+ { PidLidReminderTime, 0 },
+ { PidLidReminderSignalTime, 0 },
+ { PidLidExceptionReplaceTime, 0 },
+ { PidNameKeywords, 0 }
};
g_return_val_if_fail (props != NULL, FALSE);
+ if (!exchange_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, known_nids, G_N_ELEMENTS (known_nids)))
+ return FALSE;
+
return exchange_mapi_utils_add_props_to_props_array (mem_ctx, props, known_cal_mapi_ids, G_N_ELEMENTS (known_cal_mapi_ids));
}
@@ -1634,19 +1643,22 @@ get_comp_mid (icalcomponent *icalcomp, mapi_id_t *mid)
/* should call free_server_data() before done with cbdata */
static void
-get_server_data (ECalBackendMAPI *cbmapi, icalcomponent *comp, struct cal_cbdata *cbdata)
+get_server_data (ECalBackendMAPI *cbmapi, ECalComponent *comp, struct cal_cbdata *cbdata)
{
ECalBackendMAPIPrivate *priv = cbmapi->priv;
+ icalcomponent *icalcomp;
const gchar *uid;
mapi_id_t mid;
struct mapi_SRestriction res;
struct SPropValue sprop;
struct Binary_r sb;
uint32_t proptag = 0x0;
+ gchar *propval;
TALLOC_CTX *mem_ctx;
- uid = icalcomponent_get_uid (comp);
- get_comp_mid (comp, &mid);
+ icalcomp = e_cal_component_get_icalcomponent (comp);
+ uid = icalcomponent_get_uid (icalcomp);
+ get_comp_mid (icalcomp, &mid);
if (exchange_mapi_connection_fetch_item (priv->conn, priv->fid, mid,
mapi_cal_get_required_props, NULL,
capture_req_props, cbdata,
@@ -1661,7 +1673,22 @@ get_server_data (ECalBackendMAPI *cbmapi, icalcomponent *comp, struct cal_cbdata
res.res.resProperty.relop = RELOP_EQ;
res.res.resProperty.ulPropTag = proptag;
- exchange_mapi_cal_util_generate_globalobjectid (TRUE, uid, &sb);
+ propval = exchange_mapi_cal_utils_get_icomp_x_prop (icalcomp, "X-EVOLUTION-MAPI-GLOBALID");
+ if (propval && *propval) {
+ gsize len = 0;
+
+ sb.lpb = g_base64_decode (propval, &len);
+ sb.cb = len;
+ } else {
+ struct icaltimetype ical_creation_time = { 0 };
+ struct FILETIME creation_time = { 0 };
+
+ e_cal_component_get_dtstamp (comp, &ical_creation_time);
+
+ exchange_mapi_util_time_t_to_filetime (icaltime_as_timet (ical_creation_time), &creation_time);
+ exchange_mapi_cal_util_generate_globalobjectid (TRUE, uid, NULL, ical_creation_time.year ? &creation_time : NULL, &sb);
+ }
+ g_free (propval);
mem_ctx = talloc_init ("ExchangeMAPI_cal_get_server_data");
set_SPropValue_proptag (&sprop, proptag, (gconstpointer ) &sb);
@@ -2016,7 +2043,7 @@ ecbm_modify_object (ECalBackend *backend, EDataCal *cal, const gchar *calobj, Ca
cbdata.msgflags = MSGFLAG_READ;
cbdata.is_modify = TRUE;
- get_server_data (cbmapi, icalcomp, &cbdata);
+ get_server_data (cbmapi, comp, &cbdata);
if (modifier_is_organizer(cbmapi, comp)) {
cbdata.meeting_type = (recipients != NULL) ? MEETING_OBJECT : NOT_A_MEETING;
cbdata.resp = (recipients != NULL) ? olResponseOrganized : olResponseNone;
@@ -2226,7 +2253,11 @@ ecbm_send_objects (ECalBackend *backend, EDataCal *cal, const gchar *calobj, GLi
GSList *attachments = NULL;
GSList *streams = NULL;
const gchar *compuid;
- struct Binary_r globalid;
+ gchar *propval;
+ struct Binary_r globalid = { 0 }, cleanglobalid = { 0 };
+ struct timeval *exception_repleace_time = NULL, ex_rep_time = { 0 };
+ struct FILETIME creation_time = { 0 };
+ struct icaltimetype ical_creation_time = { 0 };
e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (subcomp));
@@ -2278,7 +2309,7 @@ ecbm_send_objects (ECalBackend *backend, EDataCal *cal, const gchar *calobj, GLi
break;
}
- get_server_data (cbmapi, subcomp, &cbdata);
+ get_server_data (cbmapi, comp, &cbdata);
free_and_dupe_str (cbdata.username, ecbm_get_user_name (cbmapi));
free_and_dupe_str (cbdata.useridtype, "SMTP");
free_and_dupe_str (cbdata.userid, ecbm_get_user_email (cbmapi));
@@ -2290,24 +2321,53 @@ ecbm_send_objects (ECalBackend *backend, EDataCal *cal, const gchar *calobj, GLi
e_cal_component_get_uid (comp, &compuid);
+ e_cal_component_get_dtstamp (comp, &ical_creation_time);
+ exchange_mapi_util_time_t_to_filetime (icaltime_as_timet (ical_creation_time), &creation_time);
+
+ propval = exchange_mapi_cal_utils_get_icomp_x_prop (e_cal_component_get_icalcomponent (comp), "X-EVOLUTION-MAPI-EXREPTIME");
+ if (propval && *propval) {
+ mapi_id_t val64 = 0;
+
+ if (exchange_mapi_util_mapi_id_from_string (propval, &val64)) {
+ memcpy (&ex_rep_time, &val64, 8);
+ exception_repleace_time = &ex_rep_time;
+ }
+ }
+ g_free (propval);
+
/* inherit GlobalID from the source object, if available */
if (e_cal_component_get_icalcomponent (comp)) {
- gchar *propval;
-
propval = exchange_mapi_cal_utils_get_icomp_x_prop (e_cal_component_get_icalcomponent (comp), "X-EVOLUTION-MAPI-GLOBALID");
if (propval && *propval) {
- exchange_mapi_cal_util_generate_globalobjectid (TRUE, propval, &globalid);
+ gsize len = 0;
+
+ globalid.lpb = g_base64_decode (propval, &len);
+ globalid.cb = len;
+
+ cleanglobalid.lpb = g_memdup (globalid.lpb, globalid.cb);
+ cleanglobalid.cb = globalid.cb;
+
+ /* PidLidCleanGlobalObjectId is same as PidLidGlobalObjectId,
+ only exception-information are zeros */
+ if (cleanglobalid.lpb && cleanglobalid.cb > 20) {
+ for (len = 16; len < 20; len++) {
+ cleanglobalid.lpb[len] = 0;
+ }
+ }
+
compuid = NULL;
}
g_free (propval);
}
- if (compuid)
- exchange_mapi_cal_util_generate_globalobjectid (TRUE, compuid, &globalid);
+ if (compuid) {
+ exchange_mapi_cal_util_generate_globalobjectid (FALSE, compuid, exception_repleace_time, ical_creation_time.year ? &creation_time : NULL, &globalid);
+ exchange_mapi_cal_util_generate_globalobjectid (TRUE, compuid, exception_repleace_time, ical_creation_time.year ? &creation_time : NULL, &cleanglobalid);
+ }
cbdata.globalid = &globalid;
- cbdata.cleanglobalid = &globalid;
+ cbdata.cleanglobalid = &cleanglobalid;
mid = exchange_mapi_connection_create_item (priv->conn, olFolderSentMail, 0,
exchange_mapi_cal_utils_write_props_cb, &cbdata,
@@ -2316,6 +2376,8 @@ ecbm_send_objects (ECalBackend *backend, EDataCal *cal, const gchar *calobj, GLi
cbdata.cleanglobalid = NULL;
free_server_data (&cbdata);
g_free (cbdata.props);
+ g_free (globalid.lpb);
+ g_free (cleanglobalid.lpb);
if (!mid) {
g_object_unref (comp);
diff --git a/src/libexchangemapi/exchange-mapi-cal-utils.c b/src/libexchangemapi/exchange-mapi-cal-utils.c
index 9a74174..d14d892 100644
--- a/src/libexchangemapi/exchange-mapi-cal-utils.c
+++ b/src/libexchangemapi/exchange-mapi-cal-utils.c
@@ -568,11 +568,14 @@ static const uint8_t GID_START_SEQ[] = {
0x74, 0xc5, 0xb7, 0x10, 0x1a, 0x82, 0xe0, 0x08
};
+/* exception_replace_time is a value of PidLidExceptionReplaceTime; this is not used for 'clean' object ids.
+ creation_time is a value of PR_CREATION_TIME
+*/
void
-exchange_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, struct Binary_r *sb)
+exchange_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, const struct timeval *exception_replace_time, const struct FILETIME *creation_time, struct Binary_r *sb)
{
GByteArray *ba;
- guint32 flag32;
+ guint32 val32;
guchar *buf = NULL;
gsize len;
d(guint32 i);
@@ -581,36 +584,40 @@ exchange_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *
ba = g_byte_array_append (ba, GID_START_SEQ, (sizeof (GID_START_SEQ) / sizeof (GID_START_SEQ[0])));
- /* FIXME for exceptions */
- if (is_clean || TRUE) {
- flag32 = 0;
- ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
+ val32 = 0;
+ if (!is_clean && exception_replace_time) {
+ struct icaltimetype icaltm = icaltime_from_timet_with_zone (exception_replace_time->tv_sec, 0, icaltimezone_get_utc_timezone ());
+
+ val32 |= (icaltm.year & 0xFF00) << 16;
+ val32 |= (icaltm.year & 0xFF) << 16;
+ val32 |= (icaltm.month & 0xFF) << 8;
+ val32 |= (icaltm.day & 0xFF);
}
- /* creation time - may be all 0's */
- flag32 = 0;
- ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
- flag32 = 0;
- ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
- /* RESERVED - should be all 0's */
- flag32 = 0;
- ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
- flag32 = 0;
- ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
+ /* creation time */
+ val32 = creation_time ? creation_time->dwLowDateTime : 0;
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
+ val32 = creation_time ? creation_time->dwHighDateTime : 0;
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
- /* FIXME: cleanup the UID first */
+ /* RESERVED - should be all 0's */
+ val32 = 0;
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
+ val32 = 0;
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
/* We put Evolution's UID in base64 here */
buf = g_base64_decode (uid, &len);
if (len % 2 != 0)
--len;
- flag32 = len;
+ val32 = len;
/* Size in bytes of the following data */
- ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
+ ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
/* Data */
- ba = g_byte_array_append (ba, (const guint8 *)buf, flag32);
+ ba = g_byte_array_append (ba, (const guint8 *)buf, val32);
g_free (buf);
sb->lpb = ba->data;
@@ -623,17 +630,18 @@ exchange_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *
g_byte_array_free (ba, FALSE);
}
+/* returns complete globalid as base64 encoded string */
static gchar *
-id_to_string (GByteArray *ba)
+globalid_to_string (GByteArray *ba)
{
guint8 *ptr;
guint len;
- gchar *buf = NULL;
- guint32 flag32, i, j;
+ guint32 i, j;
g_return_val_if_fail (ba != NULL, NULL);
+
/* MSDN docs: the globalID must have an even number of bytes */
- if ((ba->len)%2 != 0)
+ if ((ba->len) % 2 != 0)
return NULL;
ptr = ba->data;
@@ -644,49 +652,8 @@ id_to_string (GByteArray *ba)
if (*ptr != GID_START_SEQ[j])
return NULL;
- /* FIXME: for exceptions - len = 4 bytes */
- flag32 = *((guint32 *)ptr);
- i += sizeof (guint32);
- if (!(i < len) || flag32 != 0)
- return NULL;
- ptr += sizeof (guint32);
-
- /* Creation time - len = 8 bytes - skip it */
- flag32 = *((guint32 *)ptr);
- i += sizeof (guint32);
- if (!(i < len))
- return NULL;
- ptr += sizeof (guint32);
-
- flag32 = *((guint32 *)ptr);
- i += sizeof (guint32);
- if (!(i < len))
- return NULL;
- ptr += sizeof (guint32);
-
- /* Reserved bytes - len = 8 bytes */
- flag32 = *((guint32 *)ptr);
- i += sizeof (guint32);
- if (!(i < len) || flag32 != 0)
- return NULL;
- ptr += sizeof (guint32);
-
- flag32 = *((guint32 *)ptr);
- i += sizeof (guint32);
- if (!(i < len) || flag32 != 0)
- return NULL;
- ptr += sizeof (guint32);
-
- /* This is the real data */
- flag32 = *((guint32 *)ptr);
- i += sizeof (guint32);
- if (!(i < len) || flag32 != (len - i))
- return NULL;
- ptr += sizeof (guint32);
-
- buf = g_base64_encode (ptr, flag32);
-
- return buf;
+ /* take complete global id */
+ return g_base64_encode (ba->data, ba->len);
}
ECalComponent *
@@ -778,20 +745,10 @@ exchange_mapi_cal_util_mapi_props_to_comp (ExchangeMapiConnection *conn, mapi_id
gboolean all_day;
ExchangeMAPIStream *stream;
- /* CleanGlobalObjectId */
- stream = exchange_mapi_util_find_stream (streams, PidLidCleanGlobalObjectId);
- if (stream) {
- gchar *value = id_to_string (stream->value);
- prop = icalproperty_new_x (value);
- icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-CLEAN-GLOBALID");
- icalcomponent_add_property (ical_comp, prop);
- g_free (value);
- }
-
/* GlobalObjectId */
stream = exchange_mapi_util_find_stream (streams, PidLidGlobalObjectId);
if (stream) {
- gchar *value = id_to_string (stream->value);
+ gchar *value = globalid_to_string (stream->value);
prop = icalproperty_new_x (value);
icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-GLOBALID");
icalcomponent_add_property (ical_comp, prop);
@@ -808,6 +765,16 @@ exchange_mapi_cal_util_mapi_props_to_comp (ExchangeMapiConnection *conn, mapi_id
g_free (value);
}
+ ui32 = find_mapi_SPropValue_data(properties, PR_OWNER_APPT_ID);
+ if (ui32) {
+ gchar *value = exchange_mapi_util_mapi_id_to_string ((mapi_id_t) (*ui32));
+
+ prop = icalproperty_new_x (value);
+ icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-OWNER-APPT-ID");
+ icalcomponent_add_property (ical_comp, prop);
+ g_free (value);
+ }
+
/* AppointmentSequence */
ui32 = (const uint32_t *)find_mapi_SPropValue_data(properties, PidLidAppointmentSequence);
if (ui32) {
@@ -1200,6 +1167,7 @@ exchange_mapi_cal_utils_add_named_ids (ExchangeMapiConnection *conn, mapi_id_t f
{ PidLidReminderSignalTime, 0 },
{ PidLidTimeZoneStruct, 0 },
{ PidLidTimeZoneDescription, 0 },
+ { PidLidExceptionReplaceTime, 0 },
{ PidNameKeywords, 0 }
};
icalcomponent_kind kind = pkind;
@@ -1696,6 +1664,19 @@ exchange_mapi_cal_utils_write_props_cb (ExchangeMapiConnection *conn, mapi_id_t
set_named_value (PidLidRecurrenceType, &flag32);
flag32 = cbdata->appt_id;
+ if (!flag32) {
+ gchar *propval;
+
+ propval = exchange_mapi_cal_utils_get_icomp_x_prop (e_cal_component_get_icalcomponent (comp), "X-EVOLUTION-MAPI-OWNER-APPT-ID");
+ if (propval && *propval) {
+ mapi_id_t as_id = 0;
+
+ if (exchange_mapi_util_mapi_id_from_string (propval, &as_id))
+ flag32 = (uint32_t) as_id;
+ }
+
+ g_free (propval);
+ }
set_value (PR_OWNER_APPT_ID, &flag32);
flag32 = cbdata->appt_seq;
diff --git a/src/libexchangemapi/exchange-mapi-cal-utils.h b/src/libexchangemapi/exchange-mapi-cal-utils.h
index 88350c5..5000ae9 100644
--- a/src/libexchangemapi/exchange-mapi-cal-utils.h
+++ b/src/libexchangemapi/exchange-mapi-cal-utils.h
@@ -88,7 +88,7 @@ exchange_mapi_cal_util_mapi_props_to_comp (ExchangeMapiConnection *conn, mapi_id
const gchar *local_store_uri, const icaltimezone *default_zone, gboolean is_reply, GSList **detached_components);
void
-exchange_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, struct Binary_r *sb);
+exchange_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, const struct timeval *exception_replace_time, const struct FILETIME *creation_time, struct Binary_r *sb);
gchar *
exchange_mapi_cal_util_camel_helper (ExchangeMapiConnection *conn, mapi_id_t fid, mapi_id_t mid, mapi_object_t *obj_message, const gchar *msg_class,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]