[evolution-mapi] Bug #610697 - GAL addressbook only shows e-mail addresses



commit 879e3b832b154b7e6529f2b6e606e134ccc41312
Author: Milan Crha <mcrha redhat com>
Date:   Fri Apr 23 16:58:47 2010 +0200

    Bug #610697 - GAL addressbook only shows e-mail addresses

 configure.ac                                   |   18 ++-
 src/addressbook/e-book-backend-mapi-gal.c      |  301 ++++++++----------------
 src/addressbook/e-book-backend-mapi.c          |  170 ++++++++------
 src/addressbook/e-book-backend-mapi.h          |   11 +
 src/libexchangemapi/exchange-mapi-connection.c |  109 ++++-----
 src/libexchangemapi/exchange-mapi-connection.h |   13 +-
 src/libexchangemapi/exchange-mapi-utils.c      |   19 ++
 src/libexchangemapi/exchange-mapi-utils.h      |   10 +-
 8 files changed, 303 insertions(+), 348 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index dbdc0a2..9998a52 100644
--- a/configure.ac
+++ b/configure.ac
@@ -148,10 +148,24 @@ save_libs=$LIBS; LIBS="$LIBMAPI_LIBS"
 AC_LINK_IFELSE([AC_LANG_PROGRAM(
 	[[#include <libmapi/libmapi.h>]],
 	[[RegisterNotification (NULL, 0)]])],
-	[AC_DEFINE(HAVE_CORRECT_REGISTERNOTIFICATION, 1, [libmapi provides correct RegisterNotification function]) ac_cv_have_wtu=yes],[ac_cv_have_wtu=no])
+	[AC_DEFINE(HAVE_CORRECT_REGISTERNOTIFICATION, 1, [libmapi provides correct RegisterNotification function]) ac_cv_have_crn=yes],[ac_cv_have_crn=no])
 CFLAGS=$save_cflags
 LIBS=$save_libs
-AC_MSG_RESULT([$ac_cv_have_wtu])
+AC_MSG_RESULT([$ac_cv_have_crn])
+
+dnl ****************************
+dnl Check for GetGALTableCount function
+dnl ****************************
+AC_MSG_CHECKING([libmapi GetGALTableCount function])
+save_cflags=$CFLAGS; CFLAGS=$LIBMAPI_CFLAGS
+save_libs=$LIBS; LIBS="$LIBMAPI_LIBS"
+AC_LINK_IFELSE([AC_LANG_PROGRAM(
+	[[#include <libmapi/libmapi.h>]],
+	[[GetGALTableCount (NULL, NULL)]])],
+	[AC_DEFINE(HAVE_GETGALTABLECOUNT, 1, [libmapi provides GetGALTableCount function]) ac_cv_have_ggtc=yes],[ac_cv_have_ggtc=no])
+CFLAGS=$save_cflags
+LIBS=$save_libs
+AC_MSG_RESULT([$ac_cv_have_ggtc])
 
 dnl ****************************
 dnl Expose version information
diff --git a/src/addressbook/e-book-backend-mapi-gal.c b/src/addressbook/e-book-backend-mapi-gal.c
index c4df69b..d967f79 100644
--- a/src/addressbook/e-book-backend-mapi-gal.c
+++ b/src/addressbook/e-book-backend-mapi-gal.c
@@ -20,76 +20,13 @@
 #include <libedata-book/e-data-book-view.h>
 #include <libedata-book/e-book-backend-cache.h>
 #include <libedata-book/e-book-backend-summary.h>
+
+#include "e-book-backend-mapi.h"
 #include "e-book-backend-mapi-gal.h"
 
 G_DEFINE_TYPE (EBookBackendMAPIGAL, e_book_backend_mapi_gal, E_TYPE_BOOK_BACKEND)
 
 static gboolean enable_debug = TRUE;
-static GList *supported_fields;
-
-#define ELEMENT_TYPE_SIMPLE 0x01
-#define ELEMENT_TYPE_COMPLEX 0x02
-
-static const struct field_element_mapping {
-		EContactField field_id;
-		gint element_type;
-		gint mapi_id;
-		gint contact_type;
-//		gchar *element_name;
-//		void (*populate_contact_func)(EContact *contact,    gpointer data);
-//		void (*set_value_in_gw_item) (EGwItem *item, gpointer data);
-//		void (*set_changes) (EGwItem *new_item, EGwItem *old_item);
-
-	} mappings [] = {
-
-	{ E_CONTACT_UID, PT_UNICODE, 0, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_REV, PT_SYSTIME, PR_LAST_MODIFICATION_TIME, ELEMENT_TYPE_SIMPLE},
-
-	{ E_CONTACT_FILE_AS, PT_UNICODE, PR_EMS_AB_MANAGER_T_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_FULL_NAME, PT_UNICODE, PR_DISPLAY_NAME_UNICODE, ELEMENT_TYPE_SIMPLE },
-	{ E_CONTACT_GIVEN_NAME, PT_UNICODE, PR_GIVEN_NAME_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_FAMILY_NAME, PT_UNICODE, PR_SURNAME_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_NICKNAME, PT_UNICODE, PR_NICKNAME_UNICODE, ELEMENT_TYPE_SIMPLE },
-
-	{ E_CONTACT_EMAIL_1, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x8084), ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_EMAIL_2, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x8094), ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_EMAIL_3, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x80a4), ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_IM_AIM,  PT_UNICODE, PROP_TAG(PT_UNICODE, 0x8062), ELEMENT_TYPE_COMPLEX},
-
-	{ E_CONTACT_PHONE_BUSINESS, PT_UNICODE, PR_OFFICE_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_PHONE_HOME, PT_UNICODE, PR_HOME_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_PHONE_MOBILE, PT_UNICODE, PR_MOBILE_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_PHONE_HOME_FAX, PT_UNICODE, PR_HOME_FAX_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_PHONE_BUSINESS_FAX, PT_UNICODE, PR_BUSINESS_FAX_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_PHONE_PAGER, PT_UNICODE, PR_PAGER_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_PHONE_ASSISTANT, PT_UNICODE, PR_ASSISTANT_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_PHONE_COMPANY, PT_UNICODE, PR_COMPANY_MAIN_PHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
-
-	{ E_CONTACT_HOMEPAGE_URL, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x802b), ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_FREEBUSY_URL, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x80d8), ELEMENT_TYPE_SIMPLE},
-
-	{ E_CONTACT_ROLE, PT_UNICODE, PR_PROFESSION_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_TITLE, PT_UNICODE, PR_TITLE_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_ORG, PT_UNICODE, PR_COMPANY_NAME_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_ORG_UNIT, PT_UNICODE, PR_DEPARTMENT_NAME_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_MANAGER, PT_UNICODE, PR_MANAGER_NAME_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_ASSISTANT, PT_UNICODE, PR_ASSISTANT_UNICODE, ELEMENT_TYPE_SIMPLE},
-
-	{ E_CONTACT_OFFICE, PT_UNICODE, PR_OFFICE_LOCATION_UNICODE, ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_SPOUSE, PT_UNICODE, PR_SPOUSE_NAME_UNICODE, ELEMENT_TYPE_SIMPLE},
-
-	{ E_CONTACT_BIRTH_DATE,  PT_SYSTIME, PR_BIRTHDAY, ELEMENT_TYPE_COMPLEX},
-	{ E_CONTACT_ANNIVERSARY, PT_SYSTIME, PR_WEDDING_ANNIVERSARY, ELEMENT_TYPE_COMPLEX},
-
-	{ E_CONTACT_NOTE, PT_UNICODE, PR_BODY_UNICODE, ELEMENT_TYPE_SIMPLE},
-
-	{ E_CONTACT_ADDRESS_HOME, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x801a), ELEMENT_TYPE_COMPLEX},
-	{ E_CONTACT_ADDRESS_WORK, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x801c), ELEMENT_TYPE_COMPLEX},
-//		{ E_CONTACT_BOOK_URI, ELEMENT_TYPE_SIMPLE, "book_uri"}
-//		{ E_CONTACT_CATEGORIES, },
-	};
-
-static gint maplen = G_N_ELEMENTS(mappings);
 
 struct _EBookBackendMAPIGALPrivate
 {
@@ -111,7 +48,6 @@ struct _EBookBackendMAPIGALPrivate
 	gchar *summary_file_name;
 	EBookBackendSummary *summary;
 	EBookBackendCache *cache;
-
 };
 
 #define SUMMARY_FLUSH_TIMEOUT 5000
@@ -167,15 +103,90 @@ book_view_notify_status (EDataBookView *view, const gchar *status)
 	e_data_book_view_notify_status_message (view, status);
 }
 
+static guint32
+current_time_ms (void)
+{
+	GTimeVal tv;
+
+	g_get_current_time (&tv);
+
+	return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+struct fetch_gal_data
+{
+	EBookBackendMAPIGAL *ebmapi;
+	EDataBookView *book_view;
+	mapi_id_t fid; /* folder ID of contacts, for named IDs */
+	guint32 last_update; /* when in micro-seconds was done last notification about progress */
+};
+
+static gboolean
+fetch_gal_cb (ExchangeMapiConnection *conn, uint32_t row_index, uint32_t n_rows, struct SRow *aRow, gpointer data)
+{
+	EBookBackendMAPIGALPrivate *priv;
+	struct fetch_gal_data *fgd = data;
+	EContact *contact;
+	gchar *uid;
+	guint32 current_time;
+
+	g_return_val_if_fail (conn != NULL, FALSE);
+	g_return_val_if_fail (aRow != NULL, FALSE);
+	g_return_val_if_fail (data != NULL, FALSE);
+
+	priv = fgd->ebmapi->priv;
+	if (priv->kill_cache_build)
+		return FALSE;
+
+	contact = mapi_book_contact_from_props (conn, fgd->fid, NULL, aRow);
+	if (!contact) {
+		/* just ignore them */
+		return TRUE;
+	}
+
+	uid = g_strdup_printf ("%d", row_index);
+	e_contact_set (contact, E_CONTACT_UID, uid);
+	g_free (uid);
+
+	e_book_backend_cache_add_contact (priv->cache, contact);
+	e_book_backend_summary_add_contact (priv->summary, contact);
+
+	if (!fgd->book_view)
+		fgd->book_view = find_book_view (fgd->ebmapi);
+
+	if (fgd->book_view)
+		e_data_book_view_notify_update (fgd->book_view, contact);
+
+	current_time = current_time_ms ();
+	if (fgd->book_view && current_time - fgd->last_update >= 333) {
+		gchar *status_msg;
+
+		if (n_rows > 0) {
+			/* To translators : This is used to cache the downloaded contacts from GAL.
+			   The first %d is an index of the GAL entry,
+			   the second %d is total count of entries in GAL. */
+			status_msg = g_strdup_printf (_("Caching GAL entry %d/%d"), row_index, n_rows);
+		} else {
+			/* To translators : This is used to cache the downloaded contacts from GAL.
+			   %d is an index of the GAL entry. */
+			status_msg = g_strdup_printf (_("Caching GAL entry %d"), row_index);
+		}
+		book_view_notify_status (fgd->book_view, status_msg);
+		g_free (status_msg);
+		fgd->last_update = current_time;
+	}
+
+	g_object_unref (contact);
+
+	return TRUE;
+}
+
 static gpointer
 build_cache (EBookBackendMAPIGAL *ebmapi)
 {
-	EBookBackendMAPIGALPrivate *priv = ((EBookBackendMAPIGAL *) ebmapi)->priv;
+	EBookBackendMAPIGALPrivate *priv = ebmapi->priv;
 	gchar *tmp;
-	GPtrArray *contacts_array = g_ptr_array_new();
-	gint i = 0;
-	gchar *status_msg;
-	EDataBookView *book_view;
+	struct fetch_gal_data fgd = { 0 };
 
 	//FIXME: What if book view is NULL? Can it be? Check that.
 	if (!priv->cache) {
@@ -189,63 +200,33 @@ build_cache (EBookBackendMAPIGAL *ebmapi)
 		printf("Summary file name is %s\n", priv->summary_file_name);
 	}
 
-	exchange_mapi_connection_get_gal (priv->conn, contacts_array);
+	fgd.ebmapi = ebmapi;
+	fgd.book_view = find_book_view (ebmapi);
+	fgd.fid = exchange_mapi_connection_get_default_folder_id (priv->conn, olFolderContacts);
+	fgd.last_update = current_time_ms ();
 
 	e_file_cache_freeze_changes (E_FILE_CACHE (priv->cache));
+	exchange_mapi_connection_fetch_gal (priv->conn,
+					mapi_book_get_prop_list, GET_ALL_KNOWN_IDS,
+					fetch_gal_cb, &fgd);
 
-	book_view = find_book_view (ebmapi);
-
-	if (book_view)
-		e_data_book_view_notify_complete (book_view,
-						  GNOME_Evolution_Addressbook_Success);
-
-	for (i = 0; i < contacts_array->len && !priv->kill_cache_build; i++) {
-		EContact *contact = e_contact_new ();
-		ExchangeMAPIGALEntry *gal_entry = contacts_array->pdata[i];
-		gchar *uid;
-
-		uid = g_strdup_printf ("%d", i);
-
-		e_contact_set (contact, E_CONTACT_UID, uid);
-		e_contact_set (contact, E_CONTACT_FULL_NAME, gal_entry->name);
-		e_contact_set (contact, E_CONTACT_EMAIL_1, gal_entry->email);
-
-		e_book_backend_cache_add_contact (priv->cache, contact);
-		e_book_backend_summary_add_contact (priv->summary, contact);
-
-		if (book_view && (i % 200 == 0)) {
-			/* To translators : This is used to cache the downloaded contacts from GAL.
-			   First %d : Number of contacts cached till now.
-			   Second %d : Total number of contacts which need to be cached.
-			   So (%d/%d) displays the progress.
-			   Example: Caching the GAL entries (1200/50000)â?¦
-			*/
-			status_msg = g_strdup_printf (_("Caching the GAL entries (%d/%d)â?¦ "),
-							 i, contacts_array->len);
-			book_view_notify_status (book_view, status_msg);
-			g_free (status_msg);
-		}
-
-		g_object_unref(contact);
-		g_free (uid);
-	}
-
-	if (book_view) {
-		e_data_book_view_notify_complete (book_view,
-						  GNOME_Evolution_Addressbook_Success);
-		e_data_book_view_unref (book_view);
+	if (fgd.book_view) {
+		e_data_book_view_notify_complete (fgd.book_view, GNOME_Evolution_Addressbook_Success);
+		e_data_book_view_unref (fgd.book_view);
 	}
 
-	g_ptr_array_free (contacts_array, TRUE);
-
 	tmp = g_strdup_printf("%d", priv->kill_cache_build ? 0 : (gint)time (NULL));
 	e_book_backend_cache_set_time (priv->cache, tmp);
 	printf("setting time  %s\n", tmp);
 	g_free (tmp);
+
 	e_file_cache_thaw_changes (E_FILE_CACHE (priv->cache));
+
 	e_book_backend_summary_save (priv->summary);
+
 	priv->is_cache_ready = !priv->kill_cache_build;
 	priv->is_summary_ready = !priv->kill_cache_build;
+
 	return NULL;
 }
 
@@ -255,10 +236,14 @@ e_book_backend_mapi_gal_get_supported_fields (EBookBackend *backend,
 		      guint32	    opid)
 
 {
+	GList *fields;
+
+	fields = mapi_book_get_supported_fields ();
 	e_data_book_respond_get_supported_fields (book,
 						  opid,
 						  GNOME_Evolution_Addressbook_Success,
-						  supported_fields);
+						  fields);
+	g_list_free (fields);
 }
 
 static void
@@ -548,80 +533,6 @@ get_closure (EDataBookView *book_view)
 	return g_object_get_data (G_OBJECT (book_view), "closure");
 }
 
-#if 0
-static EContact *
-emapidump_gal (struct SRow *gal_entry)
-{
-	EContact *contact = e_contact_new ();
-	gint i;
-
-//	exchange_mapi_debug_property_dump (properties);
-	for (i=1; i<maplen; i++) {
-		gpointer value;
-
-		/* can cast it, no writing to the value; and it'll be freed not before the end of this function */
-		value = (gpointer) exchange_mapi_util_find_row_propval (gal_entry, mappings[i].mapi_id);
-		if (mappings[i].element_type == PT_UNICODE && mappings[i].contact_type == ELEMENT_TYPE_SIMPLE) {
-			if (value)
-				e_contact_set (contact, mappings[i].field_id, value);
-		} else if (mappings[i].contact_type == ELEMENT_TYPE_SIMPLE) {
-			if (value && mappings[i].element_type == PT_SYSTIME) {
-				struct FILETIME *t = value;
-				time_t time;
-				NTTIME nt;
-				gchar buff[129];
-
-				nt = t->dwHighDateTime;
-				nt = nt << 32;
-				nt |= t->dwLowDateTime;
-				time = nt_time_to_unix (nt);
-				e_contact_set (contact, mappings[i].field_id, ctime_r (&time, buff));
-			} else {
-				printf("Nothing is printed\n");
-			}
-		}
-	}
-}
-
-static gboolean
-create_gal_contact_cb (FetchItemsCallbackData *item_data, gpointer data)
-{
-	EDataBookView *book_view = data;
-	BESearchClosure *closure = get_closure (book_view);
-	EBookBackendMAPIGAL *be = closure->bg;
-	EContact *contact;
-	EBookBackendMAPIGALPrivate *priv = ((EBookBackendMAPIGAL *) be)->priv;
-	gchar *suid;
-	GSList *l;
-	gint counter;
-
-	if (!e_flag_is_set (closure->running)) {
-		printf("Might be that the operation is cancelled. Lets ask our parent also to do.\n");
-		return FALSE;
-	}
-
-//	contact = emapidump_contact (item_data->properties);
-	for (l=item_data->gallist; l; l=l->next) {
-		struct SRow *SRow = (struct SRow *) (l->data);
-		counter++;
-		contact = emapidump_gal (SRow);
-		suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
-
-		if (contact) {
-			/* UID of the contact is nothing but the concatenated string of hex id of folder and the message.*/
-			e_contact_set (contact, E_CONTACT_UID, suid);
-			e_contact_set (contact, E_CONTACT_BOOK_URI, priv->uri);
-			e_data_book_view_notify_update (book_view, contact);
-			g_object_unref(contact);
-		}
-
-		g_free (suid);
-	}
-	g_print ("\n The counter for the above data is %d\n", counter);
-	return TRUE;
-}
-#endif
-
 static void
 get_contacts_from_cache (EBookBackendMAPIGAL *ebmapi,
 			 const gchar *query,
@@ -779,7 +690,7 @@ book_view_thread (gpointer data)
 	g_object_ref (book_view);
 	e_flag_set (closure->running);
 
-	book_view_notify_status (book_view, "Searchingâ?¦");
+	book_view_notify_status (book_view, _("Searching"));
 	query = e_data_book_view_get_card_query (book_view);
 
 	if (!find_book_view (backend))
@@ -983,7 +894,6 @@ static void e_book_backend_mapi_gal_class_init (EBookBackendMAPIGALClass *klass)
 {
 	GObjectClass  *object_class = G_OBJECT_CLASS (klass);
 	EBookBackendClass *parent_class;
-	gint i;
 
 	e_book_backend_mapi_gal_parent_class = g_type_class_peek_parent (klass);
 
@@ -1009,13 +919,6 @@ static void e_book_backend_mapi_gal_class_init (EBookBackendMAPIGALClass *klass)
 	parent_class->set_mode                   = e_book_backend_mapi_gal_set_mode;
 	parent_class->remove			 = e_book_backend_mapi_gal_remove;
 	object_class->dispose                    = e_book_backend_mapi_gal_dispose;
-
-	supported_fields = NULL;
-	for (i = 0; i < maplen; i++) {
-		supported_fields = g_list_append (supported_fields,
-						  (gchar *)e_contact_field_name (mappings[i].field_id));
-	}
-	supported_fields = g_list_append (supported_fields, (gpointer) "file_as");
 }
 
 /**
diff --git a/src/addressbook/e-book-backend-mapi.c b/src/addressbook/e-book-backend-mapi.c
index 08346fe..c4ab714 100644
--- a/src/addressbook/e-book-backend-mapi.c
+++ b/src/addressbook/e-book-backend-mapi.c
@@ -80,11 +80,8 @@ struct _EBookBackendMAPIPrivate
 #define LOCK() g_mutex_lock (priv->lock)
 #define UNLOCK() g_mutex_unlock (priv->lock)
 
-#define GET_ALL_KNOWN_IDS (GINT_TO_POINTER(1))
-#define GET_SHORT_SUMMARY (GINT_TO_POINTER(2))
-
 /* 'data' is one of GET_ALL_KNOWN_IDS or GET_SHORT_SUMMARY */
-static gboolean
+gboolean
 mapi_book_get_prop_list (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, gpointer data)
 {
 	/* this is a list of all known book MAPI tag IDs;
@@ -101,6 +98,7 @@ mapi_book_get_prop_list (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX
 		PR_COUNTRY_UNICODE,
 		PR_DEPARTMENT_NAME_UNICODE,
 		PR_DISPLAY_NAME_UNICODE,
+		PR_SMTP_ADDRESS_UNICODE, /* used in GAL */
 		PR_EMS_AB_MANAGER_T_UNICODE,
 		PR_FID,
 		PR_GIVEN_NAME_UNICODE,
@@ -136,18 +134,7 @@ mapi_book_get_prop_list (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX
 		PR_SURNAME_UNICODE,
 		PR_TITLE_UNICODE,
 		PR_WEDDING_ANNIVERSARY,
-		PROP_TAG(PT_UNICODE, 0x801a),
-		PROP_TAG(PT_UNICODE, 0x801c),
-		PROP_TAG(PT_UNICODE, 0x801f),
-		PROP_TAG(PT_UNICODE, 0x802b),
-		PROP_TAG(PT_UNICODE, 0x8062),
-		PROP_TAG(PT_UNICODE, 0x8084),
-		PROP_TAG(PT_UNICODE, 0x8093),
-		PROP_TAG(PT_UNICODE, 0x8094),
-		PROP_TAG(PT_UNICODE, 0x80a3),
-		PROP_TAG(PT_UNICODE, 0x80a4),
-		PROP_TAG(PT_UNICODE, 0x80d8),
-		PROP_TAG(PT_UNICODE, 0x812c)
+		PROP_TAG(PT_UNICODE, 0x801f)
 	};
 
 	static uint32_t short_summary_ids[] = {
@@ -173,7 +160,10 @@ mapi_book_get_prop_list (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX
 
 		{ PidLidEmail1OriginalDisplayName, 0 },
 		{ PidLidEmail2OriginalDisplayName, 0 },
-		{ PidLidEmail3OriginalDisplayName, 0 }
+		{ PidLidEmail3OriginalDisplayName, 0 },
+		{ PidLidInstantMessagingAddress, 0 },
+		{ PidLidHtml, 0 },
+		{ PidLidFreeBusyLocation, 0 }
 	};
 
 	g_return_val_if_fail (props != NULL, FALSE);
@@ -184,17 +174,21 @@ mapi_book_get_prop_list (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX
 	if (data == GET_SHORT_SUMMARY && !exchange_mapi_utils_add_props_to_props_array (mem_ctx, props, short_summary_ids, G_N_ELEMENTS (short_summary_ids)))
 		return FALSE;
 
+	/* called with fid = 0 from GAL */
+	if (!fid)
+		fid = exchange_mapi_connection_get_default_folder_id (conn, olFolderContacts);
+
 	return exchange_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, nids, G_N_ELEMENTS (nids));
 }
 
-#define ELEMENT_TYPE_SIMPLE 0x01
-#define ELEMENT_TYPE_COMPLEX 0x02 /* fields which require explicit functions to set values into EContact and EGwItem */
-
 #define SUMMARY_FLUSH_TIMEOUT 5000
+
+#define ELEMENT_TYPE_MASK   0xF /* mask where the real type of the element is stored */
+
 #define ELEMENT_TYPE_SIMPLE 0x01
 #define ELEMENT_TYPE_COMPLEX 0x02
 
-static EContact * emapidump_contact (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SPropValue_array *properties);
+#define ELEMENT_TYPE_NAMEDID 0x10
 
 static const struct field_element_mapping {
 		EContactField field_id;
@@ -217,10 +211,10 @@ static const struct field_element_mapping {
 	{ E_CONTACT_FAMILY_NAME, PT_UNICODE, PR_SURNAME_UNICODE, ELEMENT_TYPE_SIMPLE},
 	{ E_CONTACT_NICKNAME, PT_UNICODE, PR_NICKNAME_UNICODE, ELEMENT_TYPE_SIMPLE },
 
-	{ E_CONTACT_EMAIL_1, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x8084), ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_EMAIL_2, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x8093), ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_EMAIL_3, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x80a3), ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_IM_AIM,  PT_UNICODE, PROP_TAG(PT_UNICODE, 0x8062), ELEMENT_TYPE_COMPLEX},
+	{ E_CONTACT_EMAIL_1, PT_UNICODE, PidLidEmail1OriginalDisplayName, ELEMENT_TYPE_SIMPLE | ELEMENT_TYPE_NAMEDID},
+	{ E_CONTACT_EMAIL_2, PT_UNICODE, PidLidEmail2EmailAddress, ELEMENT_TYPE_SIMPLE | ELEMENT_TYPE_NAMEDID},
+	{ E_CONTACT_EMAIL_3, PT_UNICODE, PidLidEmail3EmailAddress, ELEMENT_TYPE_SIMPLE | ELEMENT_TYPE_NAMEDID},
+	{ E_CONTACT_IM_AIM,  PT_UNICODE, PidLidInstantMessagingAddress, ELEMENT_TYPE_COMPLEX | ELEMENT_TYPE_NAMEDID},
 
 	{ E_CONTACT_PHONE_BUSINESS, PT_UNICODE, PR_OFFICE_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
 	{ E_CONTACT_PHONE_HOME, PT_UNICODE, PR_HOME_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
@@ -231,8 +225,8 @@ static const struct field_element_mapping {
 	{ E_CONTACT_PHONE_ASSISTANT, PT_UNICODE, PR_ASSISTANT_TELEPHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
 	{ E_CONTACT_PHONE_COMPANY, PT_UNICODE, PR_COMPANY_MAIN_PHONE_NUMBER_UNICODE, ELEMENT_TYPE_SIMPLE},
 
-	{ E_CONTACT_HOMEPAGE_URL, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x802b), ELEMENT_TYPE_SIMPLE},
-	{ E_CONTACT_FREEBUSY_URL, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x80d8), ELEMENT_TYPE_SIMPLE},
+	{ E_CONTACT_HOMEPAGE_URL, PT_UNICODE, PidLidHtml, ELEMENT_TYPE_SIMPLE | ELEMENT_TYPE_NAMEDID},
+	{ E_CONTACT_FREEBUSY_URL, PT_UNICODE, PidLidFreeBusyLocation, ELEMENT_TYPE_SIMPLE | ELEMENT_TYPE_NAMEDID},
 
 	{ E_CONTACT_ROLE, PT_UNICODE, PR_PROFESSION_UNICODE, ELEMENT_TYPE_SIMPLE},
 	{ E_CONTACT_TITLE, PT_UNICODE, PR_TITLE_UNICODE, ELEMENT_TYPE_SIMPLE},
@@ -249,8 +243,8 @@ static const struct field_element_mapping {
 
 	{ E_CONTACT_NOTE, PT_UNICODE, PR_BODY_UNICODE, ELEMENT_TYPE_SIMPLE},
 
-	{ E_CONTACT_ADDRESS_HOME, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x801a), ELEMENT_TYPE_COMPLEX},
-	{ E_CONTACT_ADDRESS_WORK, PT_UNICODE, PROP_TAG(PT_UNICODE, 0x801c), ELEMENT_TYPE_COMPLEX},
+	{ E_CONTACT_ADDRESS_HOME, PT_UNICODE, PidLidHomeAddress, ELEMENT_TYPE_COMPLEX | ELEMENT_TYPE_NAMEDID},
+	{ E_CONTACT_ADDRESS_WORK, PT_UNICODE, PidLidOtherAddress, ELEMENT_TYPE_COMPLEX | ELEMENT_TYPE_NAMEDID},
 //		{ E_CONTACT_BOOK_URI, ELEMENT_TYPE_SIMPLE, "book_uri"}
 //		{ E_CONTACT_CATEGORIES, },
 	};
@@ -327,7 +321,7 @@ build_restriction_emails_contains (struct mapi_SRestriction *res,
 }
 
 static gboolean
-build_multiple_restriction_emails_contains (struct mapi_SRestriction *res,
+build_multiple_restriction_emails_contains (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SRestriction *res,
 					    struct mapi_SRestriction_or *or_res,
 					    const gchar *query)
 {
@@ -374,17 +368,17 @@ build_multiple_restriction_emails_contains (struct mapi_SRestriction *res,
 
 	or_res[3].rt = RES_CONTENT;
 	or_res[3].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
-	or_res[3].res.resContent.ulPropTag = PROP_TAG(PT_UNICODE, 0x8084);
+	or_res[3].res.resContent.ulPropTag = exchange_mapi_connection_resolve_named_prop (conn, fid, PidLidEmail1OriginalDisplayName);
 	or_res[3].res.resContent.lpProp.value.lpszA = email;
 
 	or_res[4].rt = RES_CONTENT;
 	or_res[4].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
-	or_res[4].res.resContent.ulPropTag = PROP_TAG(PT_UNICODE, 0x8094);
+	or_res[4].res.resContent.ulPropTag = exchange_mapi_connection_resolve_named_prop (conn, fid, PidLidEmail2OriginalDisplayName);
 	or_res[4].res.resContent.lpProp.value.lpszA = email;
 
 	or_res[5].rt = RES_CONTENT;
 	or_res[5].res.resContent.fuzzy = FL_FULLSTRING | FL_IGNORECASE;
-	or_res[5].res.resContent.ulPropTag = PROP_TAG(PT_UNICODE, 0x80a4);
+	or_res[5].res.resContent.ulPropTag = exchange_mapi_connection_resolve_named_prop (conn, fid, PidLidEmail3OriginalDisplayName);
 	or_res[5].res.resContent.lpProp.value.lpszA = email;
 
 	res = g_new0 (struct mapi_SRestriction, 1);
@@ -794,7 +788,7 @@ mapi_book_write_props (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *
 	/*set_str_named_con_value (PidLidEmail3OriginalDisplayName, E_CONTACT_EMAIL_3);*/
 
 	set_str_named_con_value (PidLidHtml, E_CONTACT_HOMEPAGE_URL);
-	set_str_con_value (PROP_TAG(PT_UNICODE, 0x812c), E_CONTACT_FREEBUSY_URL);
+	set_str_named_con_value (PidLidFreeBusyLocation, E_CONTACT_FREEBUSY_URL);
 
 	set_str_con_value (PR_OFFICE_TELEPHONE_NUMBER_UNICODE, E_CONTACT_PHONE_BUSINESS);
 	set_str_con_value (PR_HOME_TELEPHONE_NUMBER_UNICODE, E_CONTACT_PHONE_HOME);
@@ -1063,7 +1057,7 @@ create_contact_item (FetchItemsCallbackData *item_data, gpointer data)
 	EContact *contact;
 	gchar *suid;
 
-	contact = emapidump_contact (item_data->conn, item_data->fid, item_data->properties);
+	contact = mapi_book_contact_from_props (item_data->conn, item_data->fid, item_data->properties, NULL);
 	suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
 	printf("got contact %s\n", suid);
 	if (contact) {
@@ -1178,7 +1172,7 @@ create_contact_list_cb (FetchItemsCallbackData *item_data, gpointer data)
 	EContact *contact;
 	gchar *suid;
 
-	contact = emapidump_contact (item_data->conn, fid, array);
+	contact = mapi_book_contact_from_props (item_data->conn, fid, array, NULL);
 	suid = exchange_mapi_util_mapi_ids_to_uid (fid, mid);
 
 	if (contact) {
@@ -1314,14 +1308,25 @@ get_closure (EDataBookView *book_view)
 	return g_object_get_data (G_OBJECT (book_view), "closure");
 }
 
-//FIXME: Be more clever in dumping contacts. Can we have a callback mechanism for each types?
-static EContact *
-emapidump_contact (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SPropValue_array *properties)
+static const gchar *
+not_null (gconstpointer ptr)
+{
+	return ptr ? (const gchar *) ptr : "";
+}
+
+/* This is not setting E_CONTACT_UID */
+EContact *
+mapi_book_contact_from_props (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SPropValue_array *mapi_properties, struct SRow *aRow)
 {
 	EContact *contact = e_contact_new ();
 	gint i;
 
-	if (g_str_equal (exchange_mapi_util_find_array_propval (properties, PR_MESSAGE_CLASS), IPM_DISTLIST)) {
+	#define get_proptag(proptag) (aRow ? exchange_mapi_util_find_row_propval (aRow, proptag) : exchange_mapi_util_find_array_propval (mapi_properties, proptag))
+	#define get_str_proptag(proptag) not_null (get_proptag (proptag))
+	#define get_namedid(nid) (aRow ? exchange_mapi_util_find_row_namedid (aRow, conn, fid, nid) : exchange_mapi_util_find_array_namedid (mapi_properties, conn, fid, nid))
+	#define get_str_namedid(nid) not_null (get_namedid (nid))
+
+	if (g_str_equal (get_str_proptag (PR_MESSAGE_CLASS), IPM_DISTLIST)) {
 		const struct mapi_SBinaryArray *members, *members_dlist;
 		GSList *attrs = NULL, *a;
 		gint i;
@@ -1331,10 +1336,10 @@ emapidump_contact (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SPro
 		/* we do not support this option, same as GroupWise */
 		e_contact_set (contact, E_CONTACT_LIST_SHOW_ADDRESSES, GINT_TO_POINTER (TRUE));
 
-		e_contact_set (contact, E_CONTACT_FILE_AS, exchange_mapi_util_find_array_namedid (properties, conn, fid, PidLidDistributionListName));
+		e_contact_set (contact, E_CONTACT_FILE_AS, get_str_namedid (PidLidDistributionListName));
 
-		members = exchange_mapi_util_find_array_namedid (properties, conn, fid, PidLidDistributionListOneOffMembers);
-		members_dlist = exchange_mapi_util_find_array_namedid (properties, conn, fid, PidLidDistributionListMembers);
+		members = get_namedid (PidLidDistributionListOneOffMembers);
+		members_dlist = get_namedid (PidLidDistributionListMembers);
 
 		g_return_val_if_fail (members != NULL, NULL);
 		g_return_val_if_fail (members_dlist != NULL, NULL);
@@ -1399,16 +1404,20 @@ emapidump_contact (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SPro
 		return contact;
 	}
 
-//	exchange_mapi_debug_property_dump (properties);
 	for (i = 1; i < maplen; i++) {
 		gpointer value;
+		gint contact_type;
 
-		/* can cast it, no writing to the value; and it'll be freed not before the end of this function */
-		value = (gpointer) exchange_mapi_util_find_array_propval (properties, mappings[i].mapi_id);
-		if (mappings[i].element_type == PT_UNICODE && mappings[i].contact_type == ELEMENT_TYPE_SIMPLE) {
+		/* can cast value, no writing to the value; and it'll be freed not before the end of this function */
+		if (mappings[i].contact_type & ELEMENT_TYPE_NAMEDID)
+			value = (gpointer) get_namedid (mappings[i].mapi_id);
+		else
+			value = (gpointer) get_proptag (mappings[i].mapi_id);
+		contact_type = mappings[i].contact_type & ELEMENT_TYPE_MASK;
+		if (mappings[i].element_type == PT_UNICODE && contact_type == ELEMENT_TYPE_SIMPLE) {
 			if (value)
 				e_contact_set (contact, mappings[i].field_id, value);
-		} else if (mappings[i].contact_type == ELEMENT_TYPE_SIMPLE) {
+		} else if (contact_type == ELEMENT_TYPE_SIMPLE) {
 			if (value && mappings[i].element_type == PT_SYSTIME) {
 				struct FILETIME *t = value;
 				time_t time;
@@ -1422,7 +1431,7 @@ emapidump_contact (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SPro
 				e_contact_set (contact, mappings[i].field_id, ctime_r (&time, buff));
 			} else
 				printf("Nothing is printed\n");
-		} else if (mappings[i].contact_type == ELEMENT_TYPE_COMPLEX) {
+		} else if (contact_type == ELEMENT_TYPE_COMPLEX) {
 			if (mappings[i].field_id == E_CONTACT_IM_AIM) {
 				GList *list = g_list_append (NULL, value);
 
@@ -1458,26 +1467,38 @@ emapidump_contact (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SPro
 					contact_addr.address_format = NULL;
 					contact_addr.po = NULL;
 					contact_addr.street = (gchar *)value;
-					contact_addr.ext = (gchar *)exchange_mapi_util_find_array_propval (properties, PR_HOME_ADDRESS_POST_OFFICE_BOX_UNICODE);
-					contact_addr.locality = (gchar *)exchange_mapi_util_find_array_propval (properties, PR_HOME_ADDRESS_CITY_UNICODE);
-					contact_addr.region = (gchar *)exchange_mapi_util_find_array_propval (properties, PR_HOME_ADDRESS_STATE_OR_PROVINCE_UNICODE);
-					contact_addr.code = (gchar *)exchange_mapi_util_find_array_propval (properties, PR_HOME_ADDRESS_POSTAL_CODE_UNICODE);
-					contact_addr.country = (gchar *)exchange_mapi_util_find_array_propval (properties, PR_HOME_ADDRESS_COUNTRY_UNICODE);
+					contact_addr.ext = (gchar *) get_str_proptag (PR_HOME_ADDRESS_POST_OFFICE_BOX_UNICODE);
+					contact_addr.locality = (gchar *) get_str_proptag (PR_HOME_ADDRESS_CITY_UNICODE);
+					contact_addr.region = (gchar *) get_str_proptag (PR_HOME_ADDRESS_STATE_OR_PROVINCE_UNICODE);
+					contact_addr.code = (gchar *) get_str_proptag (PR_HOME_ADDRESS_POSTAL_CODE_UNICODE);
+					contact_addr.country = (gchar *) get_str_proptag (PR_HOME_ADDRESS_COUNTRY_UNICODE);
 				} else {
 					contact_addr.address_format = NULL;
 					contact_addr.po = NULL;
 					contact_addr.street = (gchar *)value;
-					contact_addr.ext = (gchar *)exchange_mapi_util_find_array_propval (properties, PR_POST_OFFICE_BOX_UNICODE);
-					contact_addr.locality = (gchar *)exchange_mapi_util_find_array_propval (properties, PR_LOCALITY_UNICODE);
-					contact_addr.region = (gchar *)exchange_mapi_util_find_array_propval (properties, PR_STATE_OR_PROVINCE_UNICODE);
-					contact_addr.code = (gchar *)exchange_mapi_util_find_array_propval (properties, PR_POSTAL_CODE_UNICODE);
-					contact_addr.country = (gchar *)exchange_mapi_util_find_array_propval (properties, PR_COUNTRY_UNICODE);
+					contact_addr.ext = (gchar *) get_str_proptag (PR_POST_OFFICE_BOX_UNICODE);
+					contact_addr.locality = (gchar *) get_str_proptag (PR_LOCALITY_UNICODE);
+					contact_addr.region = (gchar *) get_str_proptag (PR_STATE_OR_PROVINCE_UNICODE);
+					contact_addr.code = (gchar *) get_str_proptag (PR_POSTAL_CODE_UNICODE);
+					contact_addr.country = (gchar *) get_str_proptag (PR_COUNTRY_UNICODE);
 				}
 				e_contact_set (contact, mappings[i].field_id, &contact_addr);
 			}
 		}
 	}
 
+	if (!e_contact_get (contact, E_CONTACT_EMAIL_1)) {
+		gconstpointer value = get_proptag (PR_SMTP_ADDRESS_UNICODE);
+
+		if (value)
+			e_contact_set (contact, E_CONTACT_EMAIL_1, value);
+	}
+
+	#undef get_proptag
+	#undef get_str_proptag
+	#undef get_namedid
+	#undef get_str_namedid
+
 	return contact;
 }
 
@@ -1526,7 +1547,7 @@ create_contact_cb (FetchItemsCallbackData *item_data, gpointer data)
 		return FALSE;
 	}
 
-	contact = emapidump_contact (item_data->conn, item_data->fid, item_data->properties);
+	contact = mapi_book_contact_from_props (item_data->conn, item_data->fid, item_data->properties, NULL);
 	suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
 
 	if (contact) {
@@ -1673,7 +1694,7 @@ book_view_thread (gpointer data)
 		if (e_book_backend_summary_is_summary_query (priv->summary, query)) {
 			or_res = g_new (struct mapi_SRestriction_or, res_count);
 
-			if (!build_multiple_restriction_emails_contains (&res, or_res, query)) {
+			if (!build_multiple_restriction_emails_contains (priv->conn, priv->fid, &res, or_res, query)) {
 				e_data_book_view_notify_complete (book_view,
 							  GNOME_Evolution_Addressbook_OtherError);
 				return;
@@ -1765,7 +1786,7 @@ cache_contact_cb (FetchItemsCallbackData *item_data, gpointer data)
 	EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) be)->priv;
 	gchar *suid;
 
-	contact = emapidump_contact (item_data->conn, item_data->fid, item_data->properties);
+	contact = mapi_book_contact_from_props (item_data->conn, item_data->fid, item_data->properties, NULL);
 	suid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid, item_data->mid);
 
 	if (contact) {
@@ -1931,23 +1952,32 @@ e_book_backend_mapi_get_required_fields (EBookBackend *backend,
 	g_list_free (fields);
 }
 
+/* free it with g_list_free when done with it */
+GList *
+mapi_book_get_supported_fields (void)
+{
+	gint i;
+	GList *fields = NULL;
+
+	for (i = 0; i < maplen; i++) {
+		fields = g_list_append (fields, (gchar *)e_contact_field_name (mappings[i].field_id));
+	}
+
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_BOOK_URI)));
+	return fields;
+}
+
 static void
 e_book_backend_mapi_get_supported_fields (EBookBackend *backend,
 					       EDataBook    *book,
 					       guint32       opid)
 {
-	GList *fields = NULL;
-	gint i;
+	GList *fields;
 
 	if (enable_debug)
 		printf ("mapi get_supported_fields...\n");
 
-	for (i=0; i<maplen; i++)
-	{
-		fields = g_list_append (fields, (gchar *)e_contact_field_name (mappings[i].field_id));
-	}
-	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_BOOK_URI)));
-
+	fields = mapi_book_get_supported_fields ();
 	e_data_book_respond_get_supported_fields (book, opid,
 						  GNOME_Evolution_Addressbook_Success,
 						  fields);
diff --git a/src/addressbook/e-book-backend-mapi.h b/src/addressbook/e-book-backend-mapi.h
index cba39ef..cec9385 100644
--- a/src/addressbook/e-book-backend-mapi.h
+++ b/src/addressbook/e-book-backend-mapi.h
@@ -55,5 +55,16 @@ typedef struct
 EBookBackend *e_book_backend_mapi_new      (void);
 GType         e_book_backend_mapi_get_type (void);
 
+#define GET_ALL_KNOWN_IDS (GINT_TO_POINTER(1))
+#define GET_SHORT_SUMMARY (GINT_TO_POINTER(2))
+
+GList *mapi_book_get_supported_fields (void);
+
+/* data is one of GET_ALL_KNOWN_IDS or GET_SHORT_SUMMARY */
+gboolean mapi_book_get_prop_list (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, gpointer data);
+
+/* only one of mapi_properties and aRow can be set */
+EContact *mapi_book_contact_from_props (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SPropValue_array *mapi_properties, struct SRow *aRow);
+
 #endif /* __E_BOOK_BACKEND_MAPI_H__ */
 
diff --git a/src/libexchangemapi/exchange-mapi-connection.c b/src/libexchangemapi/exchange-mapi-connection.c
index 6fa95a4..98ee685 100644
--- a/src/libexchangemapi/exchange-mapi-connection.c
+++ b/src/libexchangemapi/exchange-mapi-connection.c
@@ -913,90 +913,71 @@ cleanup:
 	return status;
 }
 
-static ExchangeMAPIGALEntry *
-mapidump_PAB_gal_entry (struct SRow *aRow)
-{
-	const gchar	*addrtype;
-	const gchar	*name;
-	const gchar	*email;
-	const gchar	*account;
-	ExchangeMAPIGALEntry *gal_entry;
-
-	addrtype = (const gchar *)exchange_mapi_util_find_row_propval (aRow, PR_ADDRTYPE);
-	name = (const gchar *)exchange_mapi_util_find_row_propval (aRow, PR_DISPLAY_NAME_UNICODE);
-	email = (const gchar *)exchange_mapi_util_find_row_propval (aRow, PR_SMTP_ADDRESS_UNICODE);
-	account = (const gchar *)exchange_mapi_util_find_row_propval (aRow, PR_ACCOUNT_UNICODE);
-
-	printf("[%s] %s:\n\tName: %-25s\n\tEmail: %-25s\n",
-	       addrtype, account, name, email);
-
-	gal_entry = g_new0 (ExchangeMAPIGALEntry, 1);
-	gal_entry->name = g_strdup (name);
-	gal_entry->email = g_strdup (email);
-
-	return gal_entry;
-}
-
 gboolean
-exchange_mapi_connection_get_gal (ExchangeMapiConnection *conn, GPtrArray *contacts_array)
+exchange_mapi_connection_fetch_gal (ExchangeMapiConnection *conn, BuildReadPropsCB build_props, gpointer brp_data, FetchGALCallback cb, gpointer data)
 {
-	struct SPropTagArray	*SPropTagArray;
-	struct SRowSet		*SRowSet;
+	struct SPropTagArray	*propsTagArray;
+	struct SRowSet		*aRowSet;
 	enum MAPISTATUS		retval;
-	uint32_t		i;
-	uint32_t		count;
+	uint32_t		i, count, n_rows = 0;
 	uint8_t			ulFlags;
 	TALLOC_CTX *mem_ctx;
 
 	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	g_return_val_if_fail (build_props != NULL, FALSE);
+	g_return_val_if_fail (cb != NULL, FALSE);
 
-	mem_ctx = talloc_init ("ExchangeMAPI_GetGAL");
+	mem_ctx = talloc_init ("ExchangeMAPI_FetchGAL");
 
 	LOCK ();
 
-	SPropTagArray = set_SPropTagArray(mem_ctx, 0xc,
-					  PR_INSTANCE_KEY,
-					  PR_ENTRYID,
-					  PR_DISPLAY_NAME_UNICODE,
-					  PR_SMTP_ADDRESS_UNICODE,
-					  PR_DISPLAY_TYPE,
-					  PR_OBJECT_TYPE,
-					  PR_ADDRTYPE,
-					  PR_OFFICE_TELEPHONE_NUMBER_UNICODE,
-					  PR_OFFICE_LOCATION_UNICODE,
-					  PR_TITLE_UNICODE,
-					  PR_COMPANY_NAME_UNICODE,
-					  PR_ACCOUNT_UNICODE);
+	#ifdef HAVE_GETGALTABLECOUNT
+	retval = GetGALTableCount (priv->session, &n_rows);
+	if (retval != MAPI_E_SUCCESS) {
+		mapi_errstr ("GetGALTableCount", GetLastError ());
+		n_rows = 0;
+	}
+	#endif
 
-	count = 0x7;
+	propsTagArray = set_SPropTagArray (mem_ctx, 0x1, PR_MESSAGE_CLASS);
+	if (!build_props (conn, 0, mem_ctx, propsTagArray, brp_data)) {
+		mapi_errstr ("build_props", GetLastError ());
+		UNLOCK();
+		talloc_free (mem_ctx);
+		return FALSE;
+	}
+
+	retval = MAPI_E_SUCCESS;
+	count = 0;
 	ulFlags = TABLE_START;
-	do {
-		count += 0x2;
-		SRowSet = NULL;
-		retval = GetGALTable (priv->session, SPropTagArray, &SRowSet, count, ulFlags);
-		if ((!SRowSet) || (!(SRowSet->aRow)) || retval != MAPI_E_SUCCESS) {
-			UNLOCK ();
-			MAPIFreeBuffer (SPropTagArray);
-			return FALSE;
+	while (retval == MAPI_E_SUCCESS) {
+		aRowSet = NULL;
+		/* fetch per 10 items */
+		retval = GetGALTable (priv->session, propsTagArray, &aRowSet, 10, ulFlags);
+		if ((!aRowSet) || (!(aRowSet->aRow)) || retval != MAPI_E_SUCCESS) {
+			break;
 		}
-		if (SRowSet->cRows) {
-			for (i = 0; i < SRowSet->cRows; i++) {
-				ExchangeMAPIGALEntry *gal_entry = g_new0 (ExchangeMAPIGALEntry, 1);
-				gal_entry = mapidump_PAB_gal_entry(&SRowSet->aRow[i]);
-				g_ptr_array_add(contacts_array, gal_entry);
+		if (aRowSet->cRows) {
+			for (i = 0; i < aRowSet->cRows; i++, count++) {
+				if (!cb (conn, count, n_rows, &aRowSet->aRow[i], data)) {
+					retval = MAPI_E_RESERVED;
+					break;
+				}
 			}
+		} else {
+			MAPIFreeBuffer (aRowSet);
+			break;
 		}
+
 		ulFlags = TABLE_CUR;
-		MAPIFreeBuffer(SRowSet);
-	} while (SRowSet->cRows == count);
-	mapi_errstr("GetPABTable", GetLastError());
+		MAPIFreeBuffer (aRowSet);
+	}
 
-	MAPIFreeBuffer(SPropTagArray);
+	talloc_free (mem_ctx);
 
 	UNLOCK ();
 
-	return TRUE;
-
+	return retval == MAPI_E_SUCCESS;
 }
 
 /* Returns TRUE if all recipients were read succcesfully, else returns FALSE */
diff --git a/src/libexchangemapi/exchange-mapi-connection.h b/src/libexchangemapi/exchange-mapi-connection.h
index da8b716..b75e1f8 100644
--- a/src/libexchangemapi/exchange-mapi-connection.h
+++ b/src/libexchangemapi/exchange-mapi-connection.h
@@ -104,11 +104,6 @@ typedef struct {
 } ExchangeMAPIRecipient;
 
 typedef struct {
-	const gchar *name;
-	const gchar *email;
-} ExchangeMAPIGALEntry;
-
-typedef struct {
 	uint32_t cValues;
 	struct SPropValue *lpProps;
 	GSList *streams;
@@ -138,6 +133,7 @@ typedef struct {
 } ResolveNamedIDsData;
 
 typedef gboolean (*FetchCallback)	(FetchItemsCallbackData *item_data, gpointer data);
+typedef gboolean (*FetchGALCallback)	(ExchangeMapiConnection *conn, uint32_t row_index, uint32_t n_rows, struct SRow *aRow, gpointer data);
 typedef gboolean (*BuildWritePropsCB)	(ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropValue **values, uint32_t *n_values, gpointer data);
 typedef gboolean (*BuildReadPropsCB)	(ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, gpointer data);
 
@@ -163,12 +159,15 @@ gboolean		exchange_mapi_connection_fetch_item (ExchangeMapiConnection *conn, map
 					guint32 options);
 
 gboolean		exchange_mapi_connection_fetch_items (ExchangeMapiConnection *conn, mapi_id_t fid,
-					struct mapi_SRestriction *res,struct SSortOrderSet *sort_order,
+					struct mapi_SRestriction *res, struct SSortOrderSet *sort_order,
 					BuildReadPropsCB build_props, gpointer brp_data,
 					FetchCallback cb, gpointer data,
 					guint32 options);
 
-gboolean		exchange_mapi_connection_get_gal (ExchangeMapiConnection *conn, GPtrArray *contacts_array);
+gboolean		exchange_mapi_connection_fetch_gal (ExchangeMapiConnection *conn,
+					BuildReadPropsCB build_props, gpointer brp_data,
+					FetchGALCallback cb, gpointer data);
+
 mapi_id_t		exchange_mapi_connection_create_folder (ExchangeMapiConnection *conn, uint32_t olFolder, mapi_id_t pfid, const gchar *name);
 gboolean		exchange_mapi_connection_remove_folder (ExchangeMapiConnection *conn, mapi_id_t fid);
 gboolean		exchange_mapi_connection_empty_folder (ExchangeMapiConnection *conn, mapi_id_t fid);
diff --git a/src/libexchangemapi/exchange-mapi-utils.c b/src/libexchangemapi/exchange-mapi-utils.c
index 962e24b..1b351c4 100644
--- a/src/libexchangemapi/exchange-mapi-utils.c
+++ b/src/libexchangemapi/exchange-mapi-utils.c
@@ -203,6 +203,25 @@ exchange_mapi_util_find_row_propval (struct SRow *aRow, uint32_t proptag)
 	return (find_SPropValue_data(aRow, proptag));
 }
 
+gconstpointer
+exchange_mapi_util_find_row_namedid (struct SRow *aRow, ExchangeMapiConnection *conn, mapi_id_t fid, uint32_t namedid)
+{
+	uint32_t proptag;
+	gconstpointer res = NULL;
+
+	g_return_val_if_fail (aRow != NULL, NULL);
+	g_return_val_if_fail (conn != NULL, NULL);
+
+	proptag = exchange_mapi_connection_resolve_named_prop (conn, fid, namedid);
+	if (proptag != MAPI_E_RESERVED)
+		res = exchange_mapi_util_find_row_propval (aRow, proptag);
+
+	if (!res)
+		res = exchange_mapi_util_find_row_propval (aRow, namedid);
+
+	return res;
+}
+
 /*
  * Retrieve the property value for a given mapi_SPropValue_array and property tag.
  *
diff --git a/src/libexchangemapi/exchange-mapi-utils.h b/src/libexchangemapi/exchange-mapi-utils.h
index d57e21b..7c78145 100644
--- a/src/libexchangemapi/exchange-mapi-utils.h
+++ b/src/libexchangemapi/exchange-mapi-utils.h
@@ -39,12 +39,10 @@ exchange_mapi_util_mapi_ids_to_uid (mapi_id_t fid, mapi_id_t mid);
 gboolean
 exchange_mapi_util_mapi_ids_from_uid (const gchar *str, mapi_id_t *fid, mapi_id_t *mid);
 
-gconstpointer
-exchange_mapi_util_find_SPropVal_array_propval (struct SPropValue *values, uint32_t proptag);
-gconstpointer
-exchange_mapi_util_find_row_propval (struct SRow *aRow, uint32_t proptag);
-gconstpointer
-exchange_mapi_util_find_array_propval (struct mapi_SPropValue_array *properties, uint32_t proptag);
+gconstpointer exchange_mapi_util_find_SPropVal_array_propval (struct SPropValue *values, uint32_t proptag);
+gconstpointer exchange_mapi_util_find_row_propval (struct SRow *aRow, uint32_t proptag);
+gconstpointer exchange_mapi_util_find_row_namedid (struct SRow *aRow, ExchangeMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
+gconstpointer exchange_mapi_util_find_array_propval (struct mapi_SPropValue_array *properties, uint32_t proptag);
 gconstpointer exchange_mapi_util_find_array_namedid (struct mapi_SPropValue_array *properties, ExchangeMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
 
 ExchangeMAPIStream *



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