[evolution-mapi] Bug #615636 - Meeting requests/responses don't match calendar events



commit 8f3efcb72496ff83fb8955ff8165be1b7ae9c9d7
Author: Milan Crha <mcrha redhat com>
Date:   Tue Feb 8 16:28:36 2011 +0100

    Bug #615636 - Meeting requests/responses don't match calendar events

 src/calendar/e-cal-backend-mapi.c             |  120 ++++++++++++++++++++----
 src/libexchangemapi/exchange-mapi-cal-utils.c |  120 +++++++++++++++++++++++--
 src/libexchangemapi/exchange-mapi-cal-utils.h |    4 +-
 3 files changed, 216 insertions(+), 28 deletions(-)
---
diff --git a/src/calendar/e-cal-backend-mapi.c b/src/calendar/e-cal-backend-mapi.c
index 27cf5c0..586f8b1 100644
--- a/src/calendar/e-cal-backend-mapi.c
+++ b/src/calendar/e-cal-backend-mapi.c
@@ -450,7 +450,7 @@ mapi_cal_get_changes_cb (FetchItemsCallbackData *item_data, gpointer data)
 	if (cache_comp == NULL) {
 		ECalComponent *comp = exchange_mapi_cal_util_mapi_props_to_comp (item_data->conn, kind, tmp, array,
 									streams, recipients, attachments,
-									cache_dir, priv->default_zone);
+									cache_dir, priv->default_zone, FALSE);
 
 		if (E_IS_CAL_COMPONENT (comp)) {
 			gchar *comp_str;
@@ -483,7 +483,7 @@ mapi_cal_get_changes_cb (FetchItemsCallbackData *item_data, gpointer data)
 
 				comp = exchange_mapi_cal_util_mapi_props_to_comp (item_data->conn, kind, tmp, array,
 									streams, recipients, attachments,
-									cache_dir, priv->default_zone);
+									cache_dir, priv->default_zone, FALSE);
 
 				e_cal_component_commit_sequence (comp);
 				modif_comp_str = e_cal_component_get_as_string (comp);
@@ -1225,7 +1225,7 @@ mapi_cal_cache_create_cb (FetchItemsCallbackData *item_data, gpointer data)
 	tmp = exchange_mapi_util_mapi_id_to_string (mid);
 	comp = exchange_mapi_cal_util_mapi_props_to_comp (item_data->conn, kind, tmp, properties,
 							streams, recipients, attachments,
-							cache_dir, priv->default_zone);
+							cache_dir, priv->default_zone, FALSE);
 	g_free (tmp);
 
 	if (E_IS_CAL_COMPONENT (comp)) {
@@ -1587,6 +1587,23 @@ capture_req_props (FetchItemsCallbackData *item_data, gpointer data)
 	return TRUE;
 }
 
+static void
+get_comp_mid (icalcomponent *icalcomp, mapi_id_t *mid)
+{
+	gchar *x_mid;
+
+	g_return_if_fail (icalcomp != NULL);
+	g_return_if_fail (mid != NULL);
+
+	x_mid = exchange_mapi_cal_utils_get_icomp_x_prop (icalcomp, "X-EVOLUTION-MAPI-MID");
+	if (x_mid) {
+		exchange_mapi_util_mapi_id_from_string (x_mid, mid);
+		g_free (x_mid);
+	} else {
+		exchange_mapi_util_mapi_id_from_string (icalcomponent_get_uid (icalcomp), mid);
+	}
+}
+
 /* should call free_server_data() before done with cbdata */
 static void
 get_server_data (ECalBackendMAPI *cbmapi, icalcomponent *comp, struct cal_cbdata *cbdata)
@@ -1601,7 +1618,7 @@ get_server_data (ECalBackendMAPI *cbmapi, icalcomponent *comp, struct cal_cbdata
 	TALLOC_CTX *mem_ctx;
 
 	uid = icalcomponent_get_uid (comp);
-	exchange_mapi_util_mapi_id_from_string (uid, &mid);
+	get_comp_mid (comp, &mid);
 	if (exchange_mapi_connection_fetch_item (priv->conn, priv->fid, mid,
 					mapi_cal_get_required_props, NULL,
 					capture_req_props, cbdata,
@@ -1670,14 +1687,12 @@ ecbm_create_object (ECalBackend *backend, EDataCal *cal, gchar **calobj, gchar *
 	icalcomponent_kind kind;
 	icalcomponent *icalcomp;
 	ECalComponent *comp;
-	const gchar *compuid;
 	mapi_id_t mid = 0;
 	gchar *tmp = NULL;
 	GSList *recipients = NULL;
 	GSList *attachments = NULL;
 	GSList *streams = NULL;
 	struct cal_cbdata cbdata = { 0 };
-	struct Binary_r globalid;
 	struct icaltimetype current;
 	const gchar *cache_dir;
 	GError *mapi_error = NULL;
@@ -1757,16 +1772,13 @@ ecbm_create_object (ECalBackend *backend, EDataCal *cal, gchar **calobj, gchar *
 			cbdata.resp = (recipients != NULL) ? olResponseOrganized : olResponseNone;
 			cbdata.appt_id = exchange_mapi_cal_util_get_new_appt_id (priv->conn, priv->fid);
 			cbdata.appt_seq = 0;
-			e_cal_component_get_uid (comp, &compuid);
-			exchange_mapi_cal_util_generate_globalobjectid (TRUE, compuid, &globalid);
-			cbdata.globalid = &globalid;
-			cbdata.cleanglobalid = &globalid;
+			cbdata.globalid = NULL;
+			cbdata.cleanglobalid = NULL;
 
 			mid = exchange_mapi_connection_create_item (priv->conn, priv->olFolder, priv->fid,
 							exchange_mapi_cal_utils_write_props_cb, &cbdata,
 							recipients, attachments, streams, MAPI_OPTIONS_DONT_SUBMIT, &mapi_error);
 			g_free (cbdata.props);
-//			g_free (globalid.lpb);
 			if (!mid) {
 				g_object_unref (comp);
 				exchange_mapi_util_free_recipient_list (&recipients);
@@ -1798,8 +1810,7 @@ ecbm_create_object (ECalBackend *backend, EDataCal *cal, gchar **calobj, gchar *
 			return;
 	}
 
-	/* blatant HACK /me blames some stupid design in e-d-s */
-	if (e_cal_component_has_attachments (comp) && !fetch_deltas(cbmapi))
+	if (!fetch_deltas(cbmapi))
 		g_cond_signal (priv->dlock->cond);
 
 	g_object_unref (comp);
@@ -1970,7 +1981,8 @@ ecbm_modify_object (ECalBackend *backend, EDataCal *cal, const gchar *calobj, Ca
 			g_propagate_error (error, EDC_ERROR (ObjectNotFound));
 			return;
 		}
-		exchange_mapi_util_mapi_id_from_string (uid, &mid);
+
+		get_comp_mid (e_cal_component_get_icalcomponent (cache_comp), &mid);
 
 		cbdata.comp = comp;
 		cbdata.msgflags = MSGFLAG_READ;
@@ -2076,7 +2088,7 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal,
 			return;
 		}
 
-		exchange_mapi_util_mapi_id_from_string (uid, &mid);
+		get_comp_mid (icalcomp, &mid);
 
 		if (mod == CALOBJ_MOD_THIS && rid && *rid) {
 			gchar *obj = NULL, *new_object = NULL, *new_calobj = NULL;
@@ -2249,7 +2261,23 @@ ecbm_send_objects (ECalBackend *backend, EDataCal *cal, const gchar *calobj, GLi
 			cbdata.get_tz_data = cbmapi;
 
 			e_cal_component_get_uid (comp, &compuid);
-			exchange_mapi_cal_util_generate_globalobjectid (TRUE, compuid, &globalid);
+
+			/* 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);
+					compuid = NULL;
+				}
+
+				g_free (propval);
+			}
+
+			if (compuid)
+				exchange_mapi_cal_util_generate_globalobjectid (TRUE, compuid, &globalid);
+
 			cbdata.globalid = &globalid;
 			cbdata.cleanglobalid = &globalid;
 
@@ -2365,10 +2393,62 @@ ecbm_receive_objects (ECalBackend *backend, EDataCal *cal, const gchar *calobj,
 				g_free (old_object);
 				g_free (new_object);
 				break;
-			case ICAL_METHOD_REPLY :
-				/* responses are automatically updated even as they are rendered (just like in Outlook) */
-				/* FIXME: the above might not be true anymore */
-				break;
+			case ICAL_METHOD_REPLY : {
+				ECalComponent *cache_comp;
+
+				g_mutex_lock (priv->mutex);
+				cache_comp = e_cal_backend_store_get_component (priv->store, uid, NULL);
+				g_mutex_unlock (priv->mutex);
+				if (cache_comp) {
+					gboolean any_changed = FALSE;
+					GSList *reply_attendees = NULL, *ri, *cache_attendees = NULL, *ci;
+
+					e_cal_component_get_attendee_list (comp, &reply_attendees);
+					e_cal_component_get_attendee_list (cache_comp, &cache_attendees);
+
+					for (ri = reply_attendees; ri; ri = ri->next) {
+						ECalComponentAttendee *ra = ri->data;
+
+						if (!ra || !ra->value || !*ra->value)
+							continue;
+
+						for (ci = cache_attendees; ci; ci = ci->next) {
+							ECalComponentAttendee *ca = ci->data;
+
+							if (!ca || !ca->value || !*ca->value || g_ascii_strcasecmp (ra->value, ca->value) != 0)
+								continue;
+
+							if (ca->status == ra->status)
+								continue;
+
+							ca->status = ra->status;
+							any_changed = TRUE;
+						}
+					}
+
+					if (any_changed) {
+						old_object = NULL;
+						new_object = NULL;
+
+						e_cal_component_set_attendee_list (cache_comp, cache_attendees);
+
+						comp_str = e_cal_component_get_as_string (cache_comp);
+						ecbm_modify_object (backend, cal, comp_str, CALOBJ_MOD_ALL, &old_object, &new_object, &err);
+
+						g_free (old_object);
+						g_free (new_object);
+						g_free (comp_str);
+					}
+
+					e_cal_component_free_attendee_list (reply_attendees);
+					e_cal_component_free_attendee_list (cache_attendees);
+
+					if (err)
+						stop = TRUE;
+
+					g_object_unref (cache_comp);
+				}
+				} break;
 			default :
 				break;
 			}
diff --git a/src/libexchangemapi/exchange-mapi-cal-utils.c b/src/libexchangemapi/exchange-mapi-cal-utils.c
index 93cab9d..f947bf4 100644
--- a/src/libexchangemapi/exchange-mapi-cal-utils.c
+++ b/src/libexchangemapi/exchange-mapi-cal-utils.c
@@ -687,7 +687,7 @@ id_to_string (GByteArray *ba)
 ECalComponent *
 exchange_mapi_cal_util_mapi_props_to_comp (ExchangeMapiConnection *conn, icalcomponent_kind kind, const gchar *mid, struct mapi_SPropValue_array *properties,
 					   GSList *streams, GSList *recipients, GSList *attachments,
-					   const gchar *local_store_uri, const icaltimezone *default_zone)
+					   const gchar *local_store_uri, const icaltimezone *default_zone, gboolean is_reply)
 {
 	ECalComponent *comp = NULL;
 	struct timeval t;
@@ -770,6 +770,16 @@ exchange_mapi_cal_util_mapi_props_to_comp (ExchangeMapiConnection *conn, icalcom
 			prop = icalproperty_new_x (value);
 			icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-GLOBALID");
 			icalcomponent_add_property (ical_comp, prop);
+			if (value && *value) {
+				e_cal_component_set_uid (comp, value);
+
+				if (!g_str_equal (value, mid)) {
+					prop = icalproperty_new_x (mid);
+					icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-MID");
+					icalcomponent_add_property (ical_comp, prop);
+				}
+			}
+
 			g_free (value);
 		}
 
@@ -833,9 +843,75 @@ exchange_mapi_cal_util_mapi_props_to_comp (ExchangeMapiConnection *conn, icalcom
 		if (recipients) {
 			b = (const bool *)find_mapi_SPropValue_data(properties, PR_RESPONSE_REQUESTED);
 			ical_attendees_from_props (ical_comp, recipients, (b && *b));
-			if (icalcomponent_get_first_property (ical_comp, ICAL_ORGANIZER_PROPERTY) == NULL) {
+			if (is_reply) {
+				if (icalcomponent_get_first_property (ical_comp, ICAL_ORGANIZER_PROPERTY) == NULL) {
+					gchar *val, *to_free = NULL;
+					const gchar *name = exchange_mapi_util_find_array_propval (properties, PR_RCVD_REPRESENTING_NAME_UNICODE);
+					const gchar *email_type = exchange_mapi_util_find_array_propval (properties, PR_RCVD_REPRESENTING_ADDRTYPE_UNICODE);
+					const gchar *email = exchange_mapi_util_find_array_propval (properties, PR_RCVD_REPRESENTING_EMAIL_ADDRESS_UNICODE);
+
+					if (!name)
+						name = "";
+					if (!email_type)
+						email_type = "";
+					if (!email)
+						email = "";
+
+					if (g_str_equal (email_type, "EX")) {
+						to_free = exchange_mapi_connection_ex_to_smtp (conn, email, NULL);
+						email = to_free;
+					}
+
+					val = g_strdup_printf ("MAILTO:%s", email);
+					prop = icalproperty_new_organizer (val);
+					g_free (val);
+
+					/* CN */
+					param = icalparameter_new_cn (name);
+					icalproperty_add_parameter (prop, param);
+
+					icalcomponent_add_property (ical_comp, prop);
+
+					g_free (to_free);
+				}
+
+				if (icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY) == NULL) {
+					const uint32_t *ui32;
+					gchar *val, *to_free = NULL;
+					const gchar *name = exchange_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_NAME_UNICODE);
+					const gchar *email_type = exchange_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_ADDRTYPE_UNICODE);
+					const gchar *email = exchange_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE);
+
+					if (!name)
+						name = "";
+					if (!email_type)
+						email_type = "";
+					if (!email)
+						email = "";
+
+					if (g_str_equal (email_type, "EX")) {
+						to_free = exchange_mapi_connection_ex_to_smtp (conn, email, NULL);
+						email = to_free;
+					}
+
+					val = g_strdup_printf ("MAILTO:%s", email);
+					prop = icalproperty_new_attendee (val);
+					g_free (val);
+
+					/* CN */
+					param = icalparameter_new_cn (name);
+					icalproperty_add_parameter (prop, param);
+
+					ui32 = exchange_mapi_util_find_array_propval (properties, PidLidResponseStatus);
+					param = icalparameter_new_partstat (get_partstat_from_trackstatus (ui32 ? *ui32 : olResponseNone));
+					icalproperty_add_parameter (prop, param);
+
+					icalcomponent_add_property (ical_comp, prop);
+
+					g_free (to_free);
+				}
+			} else if (icalcomponent_get_first_property (ical_comp, ICAL_ORGANIZER_PROPERTY) == NULL) {
 				gchar *val, *sender_free = NULL, *sent_free = NULL;
-//				const gchar *sender_name = (const gchar *) exchange_mapi_util_find_array_propval (properties, PR_SENDER_NAME_UNICODE);
 				const gchar *sender_email_type = (const gchar *) exchange_mapi_util_find_array_propval (properties, PR_SENDER_ADDRTYPE_UNICODE);
 				const gchar *sender_email = (const gchar *) exchange_mapi_util_find_array_propval (properties, PR_SENDER_EMAIL_ADDRESS_UNICODE);
 				const gchar *sent_name = (const gchar *) exchange_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_NAME_UNICODE);
@@ -1012,8 +1088,8 @@ fetch_camel_cal_comp_cb (FetchItemsCallbackData *item_data, gpointer data)
 			smid = e_cal_component_gen_uid();
 		comp = exchange_mapi_cal_util_mapi_props_to_comp (item_data->conn, fccd->kind, smid,
 							item_data->properties, item_data->streams, item_data->recipients,
-							item_data->attachments, filepath, NULL);
-		e_cal_component_set_uid (comp, smid);
+							item_data->attachments, filepath, NULL, TRUE);
+
 		g_free (smid);
 	}
 
@@ -1560,8 +1636,13 @@ exchange_mapi_cal_utils_write_props_cb (ExchangeMapiConnection *conn, mapi_id_t
 		flag32 = cbdata->appt_seq;
 		set_named_value (PidLidAppointmentSequence, &flag32);
 
-		set_named_value (PidLidCleanGlobalObjectId, cbdata->cleanglobalid);
-		set_named_value (PidLidGlobalObjectId, cbdata->globalid);
+		if (cbdata->cleanglobalid) {
+			set_named_value (PidLidCleanGlobalObjectId, cbdata->cleanglobalid);
+		}
+
+		if (cbdata->globalid) {
+			set_named_value (PidLidGlobalObjectId, cbdata->globalid);
+		}
 
 		flag32 = cbdata->resp;
 		set_named_value (PidLidResponseStatus, &flag32);
@@ -2125,3 +2206,28 @@ exchange_mapi_cal_utils_get_props_cb (ExchangeMapiConnection *conn, mapi_id_t fi
 
 	return exchange_mapi_cal_utils_add_named_ids (conn, fid, mem_ctx, props, GPOINTER_TO_INT (data));
 }
+
+gchar *
+exchange_mapi_cal_utils_get_icomp_x_prop (icalcomponent *comp, const gchar *key)
+{
+	icalproperty *xprop;
+
+	/* Find the old one first */
+	xprop = icalcomponent_get_first_property (comp, ICAL_X_PROPERTY);
+
+	while (xprop) {
+		const gchar *str = icalproperty_get_x_name (xprop);
+
+		if (str && !strcmp (str, key)) {
+			break;
+		}
+
+		xprop = icalcomponent_get_next_property (comp, ICAL_X_PROPERTY);
+	}
+
+	if (xprop)
+		return icalproperty_get_value_as_string_r (xprop);
+
+	return NULL;
+}
+
diff --git a/src/libexchangemapi/exchange-mapi-cal-utils.h b/src/libexchangemapi/exchange-mapi-cal-utils.h
index 9ac1f4c..d88acfa 100644
--- a/src/libexchangemapi/exchange-mapi-cal-utils.h
+++ b/src/libexchangemapi/exchange-mapi-cal-utils.h
@@ -85,7 +85,7 @@ exchange_mapi_cal_util_fetch_attachments (ECalComponent *comp, GSList **attach_l
 ECalComponent *
 exchange_mapi_cal_util_mapi_props_to_comp (ExchangeMapiConnection *conn, icalcomponent_kind kind, const gchar *mid, struct mapi_SPropValue_array *properties,
 					   GSList *streams, GSList *recipients, GSList *attachments,
-					   const gchar *local_store_uri, const icaltimezone *default_zone);
+					   const gchar *local_store_uri, const icaltimezone *default_zone, gboolean is_reply);
 
 void
 exchange_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, struct Binary_r *sb);
@@ -103,6 +103,8 @@ gboolean exchange_mapi_cal_utils_write_props_cb (ExchangeMapiConnection *conn, m
 
 gboolean exchange_mapi_cal_utils_get_free_busy_data (ExchangeMapiConnection *conn, const GList *users, time_t start, time_t end, GList **freebusy, GError **mapi_error);
 
+gchar *exchange_mapi_cal_utils_get_icomp_x_prop (icalcomponent *comp, const gchar *key);
+
 G_END_DECLS
 
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]