[evolution-mapi/gnome-3-0] Bug #648732 - Meeting invitation response not recognized by Outlook



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]