commit 0ea01125225149bde949b39e66e114276c1d752d
Author: Milan Crha <mcrha@redhat.com>
Date:   Mon Mar 12 17:12:32 2012 +0530

    Bug #648877 - Address completion gives mailbox name rather than contact name

diff --git a/src/addressbook/e-book-backend-ews.c b/src/addressbook/e-book-backend-ews.c
index aff82f2..340e7a7 100644
--- a/src/addressbook/e-book-backend-ews.c
+++ b/src/addressbook/e-book-backend-ews.c
@@ -180,8 +180,10 @@ ebews_populate_uid	(EContact *contact, EEwsItem *item)
 	const EwsId *id;
 
 	id = e_ews_item_get_id (item);
-	e_contact_set (contact, E_CONTACT_UID, id->id);
-	e_contact_set (contact, E_CONTACT_REV, id->change_key);
+	if (id) {
+		e_contact_set (contact, E_CONTACT_UID, id->id);
+		e_contact_set (contact, E_CONTACT_REV, id->change_key);
+	}
 }
 
 static void
@@ -190,7 +192,8 @@ ebews_populate_full_name	(EContact *contact, EEwsItem *item)
 	const EwsCompleteName *cn;
 
 	cn = e_ews_item_get_complete_name (item);
-	e_contact_set (contact, E_CONTACT_FULL_NAME, cn->full_name);
+	if (cn)
+		e_contact_set (contact, E_CONTACT_FULL_NAME, cn->full_name);
 }
 
 static void
@@ -199,7 +202,8 @@ ebews_populate_nick_name	(EContact *contact, EEwsItem *item)
 	const EwsCompleteName *cn;
 
 	cn = e_ews_item_get_complete_name (item);
-	e_contact_set (contact, E_CONTACT_NICKNAME, cn->nick_name);
+	if (cn)
+		e_contact_set (contact, E_CONTACT_NICKNAME, cn->nick_name);
 }
 
 static void
@@ -2076,7 +2080,7 @@ e_book_backend_ews_start_book_view (EBookBackend  *backend,
 	gboolean is_autocompletion = FALSE;
 	gchar *auto_comp_str = NULL;
 	GCancellable *cancellable;
-	GSList *ids = NULL, *mailboxes = NULL, *l;
+	GSList *ids = NULL, *mailboxes = NULL, *l, *contacts = NULL, *c;
 	EwsFolderId *fid;
 	gboolean includes_last_item;
 	ESource *source;
@@ -2139,7 +2143,7 @@ e_book_backend_ews_start_book_view (EBookBackend  *backend,
 		   find_items rather than resolve_names to support all queries */
 		g_hash_table_insert (priv->ops, book_view, cancellable);
 		e_ews_connection_resolve_names	(priv->cnc, EWS_PRIORITY_MEDIUM, auto_comp_str,
-						 EWS_SEARCH_AD, NULL, FALSE, &mailboxes, NULL,
+						 EWS_SEARCH_AD, NULL, TRUE, &mailboxes, &contacts,
 						 &includes_last_item, cancellable, &error);
 		g_free (auto_comp_str);
 		g_hash_table_remove (priv->ops, book_view);
@@ -2151,26 +2155,51 @@ e_book_backend_ews_start_book_view (EBookBackend  *backend,
 			return;
 		}
 
-		for (l = mailboxes; l != NULL; l = g_slist_next (l)) {
+		for (l = mailboxes, c = contacts; l != NULL; l = g_slist_next (l), c = c ? g_slist_next (c) : NULL) {
 			EwsMailbox *mb = l->data;
+			EwsResolveContact *rc = c ? c->data : NULL;
 			EContact *contact;
 
 			contact = e_contact_new ();
 
 			/* We do not get an id from the server, so just using email_id as uid for now */
 			e_contact_set (contact, E_CONTACT_UID, mb->email);
-			e_contact_set (contact, E_CONTACT_FULL_NAME, mb->name);
-			e_contact_set (contact, E_CONTACT_EMAIL_1, mb->email);
+
+			if (rc && rc->display_name && *rc->display_name)
+				e_contact_set (contact, E_CONTACT_FULL_NAME, rc->display_name);
+			else
+				e_contact_set (contact, E_CONTACT_FULL_NAME, mb->name);
+
+			if (rc && g_hash_table_size (rc->email_addresses) > 0) {
+				GList *emails = g_hash_table_get_values (rc->email_addresses), *iter;
+				GList *use_emails = NULL;
+
+				for (iter = emails; iter; iter = iter->next) {
+					if (iter->data && g_str_has_prefix (iter->data, "SMTP:"))
+						use_emails = g_list_prepend (use_emails, ((gchar *) iter->data) + 5);
+				}
+
+				if (!use_emails)
+					use_emails = g_list_prepend (use_emails, mb->email);
+
+				e_contact_set (contact, E_CONTACT_EMAIL, use_emails);
+
+				g_list_free (use_emails);
+				g_list_free (emails);
+			} else
+				e_contact_set (contact, E_CONTACT_EMAIL_1, mb->email);
 
 			e_data_book_view_notify_update (book_view, contact);
 
 			g_free (mb->email);
 			g_free (mb->name);
 			g_free (mb);
+			e_ews_free_resolve_contact (rc);
 			g_object_unref (contact);
 		}
 
 		g_slist_free (mailboxes);
+		g_slist_free (contacts);
 		e_data_book_view_notify_complete (book_view, EDB_ERROR (OtherError));
 		e_data_book_view_unref (book_view);
 		g_clear_error (&error);
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index 666e15f..c4beb70 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -602,18 +602,25 @@ resolve_names_response_cb (ESoapParameter *subparam, EwsNode *enode)
 
 		node = e_soap_parameter_get_first_child_by_name (subparam, "Mailbox");
 		mb = e_ews_item_mailbox_from_soap_param (node);
-		if (mb)
-			mailboxes = g_slist_append (mailboxes, mb);
+		if (mb) {
+			EwsResolveContact *rc;
 
-		/* TODO parse contacts */
+			mailboxes = g_slist_prepend (mailboxes, mb);
+
+			/* 'mailboxes' and 'contact_items' match 1:1, but if the contact information
+			   wasn't found, then NULL is stored in the corresponding position */
+			node = e_soap_parameter_get_first_child_by_name (subparam, "Contact");
+			rc = e_ews_item_resolve_contact_from_soap_param (node);
+			contact_items = g_slist_prepend (contact_items, rc);
+		}
 	}
 
 	async_data = g_simple_async_result_get_op_res_gpointer (enode->simple);
 
 	/* Reuse existing variables */
-	async_data->items = mailboxes;
+	async_data->items = g_slist_reverse (mailboxes);
 	async_data->includes_last_item = includes_last_item;
-	async_data->items_created = contact_items;
+	async_data->items_created = g_slist_reverse (contact_items);
 }
 
 static void
@@ -2800,6 +2807,11 @@ e_ews_connection_resolve_names_finish	(EEwsConnection *cnc,
 
 	if (contact_items)
 		*contact_items = async_data->items_created;
+	else {
+		g_slist_foreach (async_data->items_created, (GFunc)e_ews_free_resolve_contact, NULL);
+		g_slist_free (async_data->items_created);
+	}
+
 	*mailboxes = async_data->items;
 
 	return TRUE;
diff --git a/src/server/e-ews-item.c b/src/server/e-ews-item.c
index e31cb70..429e37b 100644
--- a/src/server/e-ews-item.c
+++ b/src/server/e-ews-item.c
@@ -1795,4 +1795,38 @@ e_ews_item_get_tzid (EEwsItem *item)
 	return item->priv->timezone;
 }
 
+EwsResolveContact *
+e_ews_item_resolve_contact_from_soap_param (ESoapParameter *param)
+{
+	ESoapParameter *subparam;
+	EwsResolveContact *rc;
+
+	if (!param)
+		return NULL;
+
+	rc = g_new0 (EwsResolveContact, 1);
+	rc->email_addresses = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+	subparam = e_soap_parameter_get_first_child_by_name (param, "DisplayName");
+	if (subparam)
+		rc->display_name = e_soap_parameter_get_string_value (subparam);
+
+	subparam = e_soap_parameter_get_first_child_by_name (param, "EmailAddresses");
+	if (subparam)
+		parse_entries (rc->email_addresses, subparam, (EwsGetValFunc) e_soap_parameter_get_string_value);
 
+	return rc;
+}
+
+void
+e_ews_free_resolve_contact (gpointer rc)
+{
+	EwsResolveContact *resc = rc;
+
+	if (!resc)
+		return;
+
+	g_free (resc->display_name);
+	g_hash_table_unref (resc->email_addresses);
+	g_free (resc);
+}
diff --git a/src/server/e-ews-item.h b/src/server/e-ews-item.h
index 94b36a6..9d4bc64 100644
--- a/src/server/e-ews-item.h
+++ b/src/server/e-ews-item.h
@@ -80,6 +80,11 @@ typedef struct {
 } EwsMailbox;
 
 typedef struct {
+	gchar *display_name;
+	GHashTable *email_addresses;
+} EwsResolveContact;
+
+typedef struct {
 	EwsMailbox *mailbox;
 	gchar *attendeetype;
 	gchar *responsetype;
@@ -151,6 +156,9 @@ const GSList *
 EwsMailbox *
 		e_ews_item_mailbox_from_soap_param
 						(ESoapParameter *param);
+EwsResolveContact *
+		e_ews_item_resolve_contact_from_soap_param (ESoapParameter *param);
+void		e_ews_free_resolve_contact	(/*EwsResolveContact * */ gpointer rc);
 
 const GSList *	e_ews_item_get_modified_occurrences
 						(EEwsItem *item);
