[evolution-mapi] Bug #616912 - Undefined symbol mapi_book_get_prop_list on GAL backend



commit 38db692ee3b953960bb60b0b73a93dad8d3336a0
Author: Milan Crha <mcrha redhat com>
Date:   Wed Apr 28 15:49:50 2010 +0200

    Bug #616912 - Undefined symbol mapi_book_get_prop_list on GAL backend

 src/addressbook/Makefile.am                 |    4 +
 src/addressbook/e-book-backend-mapi-gal.c   |    8 +-
 src/addressbook/e-book-backend-mapi-utils.c |  434 +++++++++++++++++++++++++++
 src/addressbook/e-book-backend-mapi-utils.h |   41 +++
 src/addressbook/e-book-backend-mapi.c       |  422 +-------------------------
 src/addressbook/e-book-backend-mapi.h       |   12 -
 6 files changed, 495 insertions(+), 426 deletions(-)
---
diff --git a/src/addressbook/Makefile.am b/src/addressbook/Makefile.am
index d6f2a00..ec55a5f 100644
--- a/src/addressbook/Makefile.am
+++ b/src/addressbook/Makefile.am
@@ -13,11 +13,15 @@ extension_LTLIBRARIES = libebookbackendmapi.la \
 libebookbackendmapi_la_SOURCES =		\
 	e-book-backend-mapi.c			\
 	e-book-backend-mapi.h			\
+	e-book-backend-mapi-utils.c		\
+	e-book-backend-mapi-utils.h		\
 	e-book-backend-mapi-factory.c
 
 libebookbackendmapigal_la_SOURCES =		\
 	e-book-backend-mapi-gal.c		\
 	e-book-backend-mapi-gal.h		\
+	e-book-backend-mapi-utils.c		\
+	e-book-backend-mapi-utils.h		\
 	e-book-backend-mapi-gal-factory.c
 
 libebookbackendmapi_la_LIBADD =			\
diff --git a/src/addressbook/e-book-backend-mapi-gal.c b/src/addressbook/e-book-backend-mapi-gal.c
index 045c8ea..e6c2b88 100644
--- a/src/addressbook/e-book-backend-mapi-gal.c
+++ b/src/addressbook/e-book-backend-mapi-gal.c
@@ -21,8 +21,8 @@
 #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"
+#include "e-book-backend-mapi-utils.h"
 
 G_DEFINE_TYPE (EBookBackendMAPIGAL, e_book_backend_mapi_gal, E_TYPE_BOOK_BACKEND)
 
@@ -138,7 +138,7 @@ fetch_gal_cb (ExchangeMapiConnection *conn, uint32_t row_index, uint32_t n_rows,
 	if (priv->kill_cache_build)
 		return FALSE;
 
-	contact = mapi_book_contact_from_props (conn, fgd->fid, NULL, aRow);
+	contact = mapi_book_utils_contact_from_props (conn, fgd->fid, NULL, aRow);
 	if (!contact) {
 		/* just ignore them */
 		return TRUE;
@@ -207,7 +207,7 @@ build_cache (EBookBackendMAPIGAL *ebmapi)
 
 	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,
+					mapi_book_utils_get_prop_list, GET_ALL_KNOWN_IDS,
 					fetch_gal_cb, &fgd);
 
 	if (fgd.book_view) {
@@ -238,7 +238,7 @@ e_book_backend_mapi_gal_get_supported_fields (EBookBackend *backend,
 {
 	GList *fields;
 
-	fields = mapi_book_get_supported_fields ();
+	fields = mapi_book_utils_get_supported_fields ();
 	e_data_book_respond_get_supported_fields (book,
 						  opid,
 						  GNOME_Evolution_Addressbook_Success,
diff --git a/src/addressbook/e-book-backend-mapi-utils.c b/src/addressbook/e-book-backend-mapi-utils.c
new file mode 100644
index 0000000..13a5c04
--- /dev/null
+++ b/src/addressbook/e-book-backend-mapi-utils.c
@@ -0,0 +1,434 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ *    Srinivasa Ragavan <sragavan novell com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <libebook/e-contact.h>
+#include <camel/camel.h>
+
+#include "exchange-mapi-utils.h"
+#include "exchange-mapi-defs.h"
+
+#include "e-book-backend-mapi-utils.h"
+
+#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
+
+#define ELEMENT_TYPE_NAMEDID 0x10
+
+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, 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},
+	{ 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, 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},
+	{ 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, 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, },
+	};
+
+
+/* free it with g_list_free when done with it */
+GList *
+mapi_book_utils_get_supported_fields (void)
+{
+	gint i;
+	GList *fields = NULL;
+
+	for (i = 0; i < G_N_ELEMENTS (mappings); 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;
+}
+
+/* 'data' is one of GET_ALL_KNOWN_IDS or GET_SHORT_SUMMARY */
+gboolean
+mapi_book_utils_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;
+	   if you add new add it here too, otherwise it may not be fetched */
+	static uint32_t known_book_mapi_ids[] = {
+		PR_ASSISTANT_TELEPHONE_NUMBER_UNICODE,
+		PR_ASSISTANT_UNICODE,
+		PR_BIRTHDAY,
+		PR_BODY,
+		PR_BODY_UNICODE,
+		PR_BUSINESS_FAX_NUMBER_UNICODE,
+		PR_COMPANY_MAIN_PHONE_NUMBER_UNICODE,
+		PR_COMPANY_NAME_UNICODE,
+		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,
+		PR_HASATTACH,
+		PR_HOME_ADDRESS_CITY_UNICODE,
+		PR_HOME_ADDRESS_COUNTRY_UNICODE,
+		PR_HOME_ADDRESS_POSTAL_CODE_UNICODE,
+		PR_HOME_ADDRESS_POST_OFFICE_BOX_UNICODE,
+		PR_HOME_ADDRESS_STATE_OR_PROVINCE_UNICODE,
+		PR_HOME_FAX_NUMBER_UNICODE,
+		PR_HOME_TELEPHONE_NUMBER_UNICODE,
+		PR_INSTANCE_NUM,
+		PR_INST_ID,
+		PR_LAST_MODIFICATION_TIME,
+		PR_LOCALITY_UNICODE,
+		PR_MANAGER_NAME_UNICODE,
+		PR_MESSAGE_CLASS,
+		PR_MID,
+		PR_MOBILE_TELEPHONE_NUMBER_UNICODE,
+		PR_NICKNAME_UNICODE,
+		PR_NORMALIZED_SUBJECT_UNICODE,
+		PR_OFFICE_LOCATION_UNICODE,
+		PR_OFFICE_TELEPHONE_NUMBER_UNICODE,
+		PR_PAGER_TELEPHONE_NUMBER_UNICODE,
+		PR_POSTAL_CODE_UNICODE,
+		PR_POST_OFFICE_BOX_UNICODE,
+		PR_PROFESSION_UNICODE,
+		PR_RULE_MSG_NAME,
+		PR_RULE_MSG_PROVIDER,
+		PR_SPOUSE_NAME_UNICODE,
+		PR_STATE_OR_PROVINCE_UNICODE,
+		PR_SUBJECT_UNICODE,
+		PR_SURNAME_UNICODE,
+		PR_TITLE_UNICODE,
+		PR_WEDDING_ANNIVERSARY,
+		PROP_TAG(PT_UNICODE, 0x801f)
+	};
+
+	static uint32_t short_summary_ids[] = {
+		PR_FID,
+		PR_MID,
+		PR_INST_ID,
+		PR_INSTANCE_NUM,
+		PR_SUBJECT_UNICODE,
+		PR_MESSAGE_CLASS,
+		PR_HASATTACH,
+		/* FIXME: is this tag fit to check if a recipient table exists or not? */
+		/* PR_DISCLOSURE_OF_RECIPIENTS, */
+		PR_RULE_MSG_PROVIDER,
+		PR_RULE_MSG_NAME
+	};
+	
+	/* do not make this array static, the function modifies it on run */
+	ResolveNamedIDsData nids[] = {
+		{ PidLidDistributionListName, 0 },
+		{ PidLidDistributionListOneOffMembers, 0 },
+		{ PidLidDistributionListMembers, 0 },
+		{ PidLidDistributionListChecksum, 0 },
+
+		{ PidLidEmail1OriginalDisplayName, 0 },
+		{ PidLidEmail2OriginalDisplayName, 0 },
+		{ PidLidEmail3OriginalDisplayName, 0 },
+		{ PidLidInstantMessagingAddress, 0 },
+		{ PidLidHtml, 0 },
+		{ PidLidFreeBusyLocation, 0 }
+	};
+
+	g_return_val_if_fail (props != NULL, FALSE);
+
+	if (data == GET_ALL_KNOWN_IDS && !exchange_mapi_utils_add_props_to_props_array (mem_ctx, props, known_book_mapi_ids, G_N_ELEMENTS (known_book_mapi_ids)))
+		return FALSE;
+
+	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));
+}
+
+static gchar *
+bin_to_string (const uint8_t *lpb, uint32_t cb)
+{
+	gchar *res, *p;
+	uint32_t i;
+
+	g_return_val_if_fail (lpb != NULL, NULL);
+	g_return_val_if_fail (cb > 0, NULL);
+
+	res = g_new0 (gchar, cb * 2 + 1);
+	for (i = 0, p = res; i < cb; i++, p += 2) {
+		sprintf (p, "%02x", lpb[i] & 0xFF);
+	}
+
+	return res;
+}
+
+static const gchar *
+not_null (gconstpointer ptr)
+{
+	return ptr ? (const gchar *) ptr : "";
+}
+
+/* This is not setting E_CONTACT_UID */
+EContact *
+mapi_book_utils_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;
+
+	#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;
+
+		/* it's a contact list/distribution list, fetch members and return it */
+		e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (TRUE));
+		/* 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, get_str_namedid (PidLidDistributionListName));
+
+		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);
+
+		/* these two lists should be in sync */
+		g_return_val_if_fail (members_dlist->cValues == members->cValues, NULL);
+
+		for (i = 0; i < members->cValues; i++) {
+			struct Binary_r br;
+			gchar *display_name = NULL, *email = NULL;
+			gchar *str;
+
+			br.lpb = members->bin[i].lpb;
+			br.cb = members->bin[i].cb;
+			if (exchange_mapi_util_entryid_decode_oneoff (&br, &display_name, &email)) {
+				EVCardAttribute *attr;
+				gchar *value;
+				CamelInternetAddress *addr;
+
+				addr = camel_internet_address_new ();
+				attr = e_vcard_attribute_new (NULL, EVC_EMAIL);
+
+				camel_internet_address_add (addr, display_name, email);
+
+				value = camel_address_encode (CAMEL_ADDRESS (addr));
+
+				if (value)
+					e_vcard_attribute_add_value (attr, value);
+
+				g_free (value);
+				g_object_unref (addr);
+
+				str = g_strdup_printf ("%d", i + 1);
+				e_vcard_attribute_add_param_with_value (attr,
+						e_vcard_attribute_param_new (EMA_X_MEMBERID),
+						str);
+				g_free (str);
+
+				/* keep the value from ListMembers with the email, to not need to generate it on list changes;
+				   new values added in evolution-mapi will be always SMTP addresses anyway */
+				str = bin_to_string (members_dlist->bin[i].lpb, members_dlist->bin[i].cb);
+				if (str) {
+					e_vcard_attribute_add_param_with_value (attr,
+						e_vcard_attribute_param_new (EMA_X_MEMBERVALUE),
+						str);
+					g_free (str);
+				}
+
+				attrs = g_slist_prepend (attrs, attr);
+			}
+
+			g_free (display_name);
+			g_free (email);
+		}
+
+		for (a = attrs; a; a = a->next) {
+			e_vcard_add_attribute (E_VCARD (contact), a->data);
+		}
+
+		g_slist_free (attrs);
+
+		return contact;
+	}
+
+	for (i = 1; i < G_N_ELEMENTS (mappings); i++) {
+		gpointer value;
+		gint contact_type;
+
+		/* 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 (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");
+		} else if (contact_type == ELEMENT_TYPE_COMPLEX) {
+			if (mappings[i].field_id == E_CONTACT_IM_AIM) {
+				GList *list = g_list_append (NULL, value);
+
+				e_contact_set (contact, mappings[i].field_id, list);
+
+				g_list_free (list);
+			} else if (mappings[i].field_id == E_CONTACT_BIRTH_DATE
+				   || mappings[i].field_id == E_CONTACT_ANNIVERSARY) {
+				struct FILETIME *t = value;
+				time_t time;
+				NTTIME nt;
+				struct tm * tmtime;
+				if (value) {
+					EContactDate date = {0};
+					nt = t->dwHighDateTime;
+					nt = nt << 32;
+					nt |= t->dwLowDateTime;
+					time = nt_time_to_unix (nt);
+					tmtime = gmtime (&time);
+					//FIXME: Move to new libmapi api to get string dates.
+					date.day = tmtime->tm_mday + 1;
+					date.month = tmtime->tm_mon + 1;
+					date.year = tmtime->tm_year + 1900;
+					e_contact_set (contact, mappings[i].field_id, &date);
+				}
+
+			} else if (mappings[i].field_id == E_CONTACT_ADDRESS_WORK
+				   || mappings[i].field_id == E_CONTACT_ADDRESS_HOME) {
+				EContactAddress contact_addr = { 0 };
+
+				/* type-casting below to not allocate memory twice; e_contact_set will copy values itself. */
+				if (mappings[i].field_id == E_CONTACT_ADDRESS_HOME) {
+					contact_addr.address_format = NULL;
+					contact_addr.po = NULL;
+					contact_addr.street = (gchar *)value;
+					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 *) 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;
+}
diff --git a/src/addressbook/e-book-backend-mapi-utils.h b/src/addressbook/e-book-backend-mapi-utils.h
new file mode 100644
index 0000000..52a2ece
--- /dev/null
+++ b/src/addressbook/e-book-backend-mapi-utils.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __E_BOOK_BACKEND_MAPI_UTILS_H__
+#define __E_BOOK_BACKEND_MAPI_UTILS_H__
+
+#include "exchange-mapi-connection.h"
+
+/* vCard parameter name in contact list */
+#define EMA_X_MEMBERID "X-EMA-MEMBER-ID"
+#define EMA_X_MEMBERVALUE "X-EMA-MEMBER-VALUE"
+
+GList *mapi_book_utils_get_supported_fields (void);
+
+#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 */
+gboolean mapi_book_utils_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_utils_contact_from_props (ExchangeMapiConnection *conn, mapi_id_t fid, struct mapi_SPropValue_array *mapi_properties, struct SRow *aRow);
+
+#endif /* __E_BOOK_BACKEND_MAPI_UTILS_H__ */
diff --git a/src/addressbook/e-book-backend-mapi.c b/src/addressbook/e-book-backend-mapi.c
index daa2a1e..9ce10a6 100644
--- a/src/addressbook/e-book-backend-mapi.c
+++ b/src/addressbook/e-book-backend-mapi.c
@@ -47,10 +47,7 @@
 #include <libedata-book/e-book-backend-cache.h>
 #include <libedata-book/e-book-backend-summary.h>
 #include "e-book-backend-mapi.h"
-
-/* vCard parameter name in contact list */
-#define EMA_X_MEMBERID "X-EMA-MEMBER-ID"
-#define EMA_X_MEMBERVALUE "X-EMA-MEMBER-VALUE"
+#include "e-book-backend-mapi-utils.h"
 
 G_DEFINE_TYPE (EBookBackendMAPI, e_book_backend_mapi, E_TYPE_BOOK_BACKEND)
 
@@ -80,177 +77,8 @@ struct _EBookBackendMAPIPrivate
 #define LOCK() g_mutex_lock (priv->lock)
 #define UNLOCK() g_mutex_unlock (priv->lock)
 
-/* '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)
-{
-	/* this is a list of all known book MAPI tag IDs;
-	   if you add new add it here too, otherwise it may not be fetched */
-	static uint32_t known_book_mapi_ids[] = {
-		PR_ASSISTANT_TELEPHONE_NUMBER_UNICODE,
-		PR_ASSISTANT_UNICODE,
-		PR_BIRTHDAY,
-		PR_BODY,
-		PR_BODY_UNICODE,
-		PR_BUSINESS_FAX_NUMBER_UNICODE,
-		PR_COMPANY_MAIN_PHONE_NUMBER_UNICODE,
-		PR_COMPANY_NAME_UNICODE,
-		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,
-		PR_HASATTACH,
-		PR_HOME_ADDRESS_CITY_UNICODE,
-		PR_HOME_ADDRESS_COUNTRY_UNICODE,
-		PR_HOME_ADDRESS_POSTAL_CODE_UNICODE,
-		PR_HOME_ADDRESS_POST_OFFICE_BOX_UNICODE,
-		PR_HOME_ADDRESS_STATE_OR_PROVINCE_UNICODE,
-		PR_HOME_FAX_NUMBER_UNICODE,
-		PR_HOME_TELEPHONE_NUMBER_UNICODE,
-		PR_INSTANCE_NUM,
-		PR_INST_ID,
-		PR_LAST_MODIFICATION_TIME,
-		PR_LOCALITY_UNICODE,
-		PR_MANAGER_NAME_UNICODE,
-		PR_MESSAGE_CLASS,
-		PR_MID,
-		PR_MOBILE_TELEPHONE_NUMBER_UNICODE,
-		PR_NICKNAME_UNICODE,
-		PR_NORMALIZED_SUBJECT_UNICODE,
-		PR_OFFICE_LOCATION_UNICODE,
-		PR_OFFICE_TELEPHONE_NUMBER_UNICODE,
-		PR_PAGER_TELEPHONE_NUMBER_UNICODE,
-		PR_POSTAL_CODE_UNICODE,
-		PR_POST_OFFICE_BOX_UNICODE,
-		PR_PROFESSION_UNICODE,
-		PR_RULE_MSG_NAME,
-		PR_RULE_MSG_PROVIDER,
-		PR_SPOUSE_NAME_UNICODE,
-		PR_STATE_OR_PROVINCE_UNICODE,
-		PR_SUBJECT_UNICODE,
-		PR_SURNAME_UNICODE,
-		PR_TITLE_UNICODE,
-		PR_WEDDING_ANNIVERSARY,
-		PROP_TAG(PT_UNICODE, 0x801f)
-	};
-
-	static uint32_t short_summary_ids[] = {
-		PR_FID,
-		PR_MID,
-		PR_INST_ID,
-		PR_INSTANCE_NUM,
-		PR_SUBJECT_UNICODE,
-		PR_MESSAGE_CLASS,
-		PR_HASATTACH,
-		/* FIXME: is this tag fit to check if a recipient table exists or not? */
-		/* PR_DISCLOSURE_OF_RECIPIENTS, */
-		PR_RULE_MSG_PROVIDER,
-		PR_RULE_MSG_NAME
-	};
-	
-	/* do not make this array static, the function modifies it on run */
-	ResolveNamedIDsData nids[] = {
-		{ PidLidDistributionListName, 0 },
-		{ PidLidDistributionListOneOffMembers, 0 },
-		{ PidLidDistributionListMembers, 0 },
-		{ PidLidDistributionListChecksum, 0 },
-
-		{ PidLidEmail1OriginalDisplayName, 0 },
-		{ PidLidEmail2OriginalDisplayName, 0 },
-		{ PidLidEmail3OriginalDisplayName, 0 },
-		{ PidLidInstantMessagingAddress, 0 },
-		{ PidLidHtml, 0 },
-		{ PidLidFreeBusyLocation, 0 }
-	};
-
-	g_return_val_if_fail (props != NULL, FALSE);
-
-	if (data == GET_ALL_KNOWN_IDS && !exchange_mapi_utils_add_props_to_props_array (mem_ctx, props, known_book_mapi_ids, G_N_ELEMENTS (known_book_mapi_ids)))
-		return FALSE;
-
-	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 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
-
-#define ELEMENT_TYPE_NAMEDID 0x10
-
-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, 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},
-	{ 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, 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},
-	{ 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, 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, },
-	};
-
-static gint maplen = G_N_ELEMENTS(mappings);
-
 #if 0
 static EDataBookView *
 find_book_view (EBookBackendMAPI *ebmapi)
@@ -518,23 +346,6 @@ e_book_backend_mapi_get_static_capabilities (EBookBackend *backend)
 	return g_strdup ("net,bulk-removes,do-initial-query,contact-lists");
 }
 
-static gchar *
-bin_to_string (const uint8_t *lpb, uint32_t cb)
-{
-	gchar *res, *p;
-	uint32_t i;
-
-	g_return_val_if_fail (lpb != NULL, NULL);
-	g_return_val_if_fail (cb > 0, NULL);
-
-	res = g_new0 (gchar, cb * 2 + 1);
-	for (i = 0, p = res; i < cb; i++, p += 2) {
-		sprintf (p, "%02x", lpb[i] & 0xFF);
-	}
-
-	return res;
-}
-
 static uint32_t
 string_to_bin (TALLOC_CTX *mem_ctx, const gchar *str, uint8_t **lpb)
 {
@@ -1057,7 +868,7 @@ create_contact_item (FetchItemsCallbackData *item_data, gpointer data)
 	EContact *contact;
 	gchar *suid;
 
-	contact = mapi_book_contact_from_props (item_data->conn, item_data->fid, item_data->properties, NULL);
+	contact = mapi_book_utils_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) {
@@ -1131,7 +942,7 @@ e_book_backend_mapi_get_contact (EBookBackend *backend,
 
 			exchange_mapi_util_mapi_ids_from_uid (id, &fid, &mid);
 			exchange_mapi_connection_fetch_item (priv->conn, priv->fid, mid,
-							mapi_book_get_prop_list, GET_ALL_KNOWN_IDS,
+							mapi_book_utils_get_prop_list, GET_ALL_KNOWN_IDS,
 							create_contact_item, contact,
 							MAPI_OPTIONS_FETCH_ALL);
 
@@ -1172,7 +983,7 @@ create_contact_list_cb (FetchItemsCallbackData *item_data, gpointer data)
 	EContact *contact;
 	gchar *suid;
 
-	contact = mapi_book_contact_from_props (item_data->conn, fid, array, NULL);
+	contact = mapi_book_utils_contact_from_props (item_data->conn, fid, array, NULL);
 	suid = exchange_mapi_util_mapi_ids_to_uid (fid, mid);
 
 	if (contact) {
@@ -1260,7 +1071,7 @@ e_book_backend_mapi_get_contact_list (EBookBackend *backend,
 			}
 
 			if (!exchange_mapi_connection_fetch_items (priv->conn, priv->fid, &res, NULL,
-								mapi_book_get_prop_list, GET_SHORT_SUMMARY,
+								mapi_book_utils_get_prop_list, GET_SHORT_SUMMARY,
 								create_contact_list_cb, &vcard_str,
 								MAPI_OPTIONS_FETCH_ALL)) {
 				e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
@@ -1308,200 +1119,6 @@ get_closure (EDataBookView *book_view)
 	return g_object_get_data (G_OBJECT (book_view), "closure");
 }
 
-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;
-
-	#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;
-
-		/* it's a contact list/distribution list, fetch members and return it */
-		e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (TRUE));
-		/* 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, get_str_namedid (PidLidDistributionListName));
-
-		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);
-
-		/* these two lists should be in sync */
-		g_return_val_if_fail (members_dlist->cValues == members->cValues, NULL);
-
-		for (i = 0; i < members->cValues; i++) {
-			struct Binary_r br;
-			gchar *display_name = NULL, *email = NULL;
-			gchar *str;
-
-			br.lpb = members->bin[i].lpb;
-			br.cb = members->bin[i].cb;
-			if (exchange_mapi_util_entryid_decode_oneoff (&br, &display_name, &email)) {
-				EVCardAttribute *attr;
-				gchar *value;
-				CamelInternetAddress *addr;
-
-				addr = camel_internet_address_new ();
-				attr = e_vcard_attribute_new (NULL, EVC_EMAIL);
-
-				camel_internet_address_add (addr, display_name, email);
-
-				value = camel_address_encode (CAMEL_ADDRESS (addr));
-
-				if (value)
-					e_vcard_attribute_add_value (attr, value);
-
-				g_free (value);
-				g_object_unref (addr);
-
-				str = g_strdup_printf ("%d", i + 1);
-				e_vcard_attribute_add_param_with_value (attr,
-						e_vcard_attribute_param_new (EMA_X_MEMBERID),
-						str);
-				g_free (str);
-
-				/* keep the value from ListMembers with the email, to not need to generate it on list changes;
-				   new values added in evolution-mapi will be always SMTP addresses anyway */
-				str = bin_to_string (members_dlist->bin[i].lpb, members_dlist->bin[i].cb);
-				if (str) {
-					e_vcard_attribute_add_param_with_value (attr,
-						e_vcard_attribute_param_new (EMA_X_MEMBERVALUE),
-						str);
-					g_free (str);
-				}
-
-				attrs = g_slist_prepend (attrs, attr);
-			}
-
-			g_free (display_name);
-			g_free (email);
-		}
-
-		for (a = attrs; a; a = a->next) {
-			e_vcard_add_attribute (E_VCARD (contact), a->data);
-		}
-
-		g_slist_free (attrs);
-
-		return contact;
-	}
-
-	for (i = 1; i < maplen; i++) {
-		gpointer value;
-		gint contact_type;
-
-		/* 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 (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");
-		} else if (contact_type == ELEMENT_TYPE_COMPLEX) {
-			if (mappings[i].field_id == E_CONTACT_IM_AIM) {
-				GList *list = g_list_append (NULL, value);
-
-				e_contact_set (contact, mappings[i].field_id, list);
-
-				g_list_free (list);
-			} else if (mappings[i].field_id == E_CONTACT_BIRTH_DATE
-				   || mappings[i].field_id == E_CONTACT_ANNIVERSARY) {
-				struct FILETIME *t = value;
-				time_t time;
-				NTTIME nt;
-				struct tm * tmtime;
-				if (value) {
-					EContactDate date = {0};
-					nt = t->dwHighDateTime;
-					nt = nt << 32;
-					nt |= t->dwLowDateTime;
-					time = nt_time_to_unix (nt);
-					tmtime = gmtime (&time);
-					//FIXME: Move to new libmapi api to get string dates.
-					date.day = tmtime->tm_mday + 1;
-					date.month = tmtime->tm_mon + 1;
-					date.year = tmtime->tm_year + 1900;
-					e_contact_set (contact, mappings[i].field_id, &date);
-				}
-
-			} else if (mappings[i].field_id == E_CONTACT_ADDRESS_WORK
-				   || mappings[i].field_id == E_CONTACT_ADDRESS_HOME) {
-				EContactAddress contact_addr = { 0 };
-
-				/* type-casting below to not allocate memory twice; e_contact_set will copy values itself. */
-				if (mappings[i].field_id == E_CONTACT_ADDRESS_HOME) {
-					contact_addr.address_format = NULL;
-					contact_addr.po = NULL;
-					contact_addr.street = (gchar *)value;
-					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 *) 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;
-}
-
 static void
 get_contacts_from_cache (EBookBackendMAPI *ebmapi,
 			 const gchar *query,
@@ -1547,7 +1164,7 @@ create_contact_cb (FetchItemsCallbackData *item_data, gpointer data)
 		return FALSE;
 	}
 
-	contact = mapi_book_contact_from_props (item_data->conn, item_data->fid, item_data->properties, NULL);
+	contact = mapi_book_utils_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) {
@@ -1702,7 +1319,7 @@ book_view_thread (gpointer data)
 
 			//FIXME: We need to fetch only the query from the server live and not everything.
 			if (!exchange_mapi_connection_fetch_items (priv->conn, priv->fid, &res, NULL,
-							   mapi_book_get_prop_list, GET_SHORT_SUMMARY,
+							   mapi_book_utils_get_prop_list, GET_SHORT_SUMMARY,
 							   create_contact_cb, book_view,
 							   MAPI_OPTIONS_FETCH_ALL)) {
 			if (e_flag_is_set (closure->running))
@@ -1717,7 +1334,7 @@ book_view_thread (gpointer data)
 			}
 		} else {
 			if (!exchange_mapi_connection_fetch_items (priv->conn, priv->fid, NULL, NULL,
-							mapi_book_get_prop_list, GET_ALL_KNOWN_IDS,
+							mapi_book_utils_get_prop_list, GET_ALL_KNOWN_IDS,
 							create_contact_cb, book_view,
 							MAPI_OPTIONS_FETCH_ALL)) {
 				if (e_flag_is_set (closure->running))
@@ -1786,7 +1403,7 @@ cache_contact_cb (FetchItemsCallbackData *item_data, gpointer data)
 	EBookBackendMAPIPrivate *priv = ((EBookBackendMAPI *) be)->priv;
 	gchar *suid;
 
-	contact = mapi_book_contact_from_props (item_data->conn, item_data->fid, item_data->properties, NULL);
+	contact = mapi_book_utils_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) {
@@ -1823,7 +1440,7 @@ build_cache (EBookBackendMAPI *ebmapi)
 	e_file_cache_freeze_changes (E_FILE_CACHE (priv->cache));
 
 	if (!exchange_mapi_connection_fetch_items (priv->conn, priv->fid, NULL, NULL,
-						mapi_book_get_prop_list, GET_ALL_KNOWN_IDS,
+						mapi_book_utils_get_prop_list, GET_ALL_KNOWN_IDS,
 						cache_contact_cb, ebmapi,
 						MAPI_OPTIONS_FETCH_ALL)) {
 		printf("Error during caching addressbook\n");
@@ -1867,7 +1484,7 @@ update_cache (EBookBackendMAPI *ebmapi)
 	e_file_cache_freeze_changes (E_FILE_CACHE (priv->cache));
 
 	if (!exchange_mapi_connection_fetch_items (priv->conn, priv->fid, &res, NULL,
-						mapi_book_get_prop_list, GET_ALL_KNOWN_IDS,
+						mapi_book_utils_get_prop_list, GET_ALL_KNOWN_IDS,
 						cache_contact_cb, ebmapi,
 						MAPI_OPTIONS_FETCH_ALL)) {
 		printf("Error during caching addressbook\n");
@@ -1952,21 +1569,6 @@ 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,
@@ -1977,7 +1579,7 @@ e_book_backend_mapi_get_supported_fields (EBookBackend *backend,
 	if (enable_debug)
 		printf ("mapi get_supported_fields...\n");
 
-	fields = mapi_book_get_supported_fields ();
+	fields = mapi_book_utils_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 cec9385..46d495d 100644
--- a/src/addressbook/e-book-backend-mapi.h
+++ b/src/addressbook/e-book-backend-mapi.h
@@ -55,16 +55,4 @@ 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__ */
-



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