[evolution-ews] Map the ews-oab-props with EContactField's and form EContact. Store the EContact into the db with th



commit 331178f12940ff2b31d31ebc8aee80b552231650
Author: Chenthill Palanisamy <pchenthill novell com>
Date:   Fri Jul 8 21:00:03 2011 +0530

    Map the ews-oab-props with EContactField's and form EContact.
    Store the EContact into the db with the file offset data.
    Use GFileStream itself as GDataStream is not seekable.

 src/addressbook/ews-oab-decoder.c |  433 ++++++++++++++++++++++++++++++-------
 src/addressbook/ews-oab-decoder.h |    1 +
 2 files changed, 361 insertions(+), 73 deletions(-)
---
diff --git a/src/addressbook/ews-oab-decoder.c b/src/addressbook/ews-oab-decoder.c
index 55d4157..84f8900 100644
--- a/src/addressbook/ews-oab-decoder.c
+++ b/src/addressbook/ews-oab-decoder.c
@@ -23,12 +23,14 @@
 #include <stdlib.h>
 #include <glib/gstdio.h>
 
+#include <libebook/e-vcard.h>
+
 #include "ews-oab-decoder.h"
 #include "ews-oab-props.h"
 
 G_DEFINE_TYPE (EwsOabDecoder, ews_oab_decoder, G_TYPE_OBJECT)
 
-#define d(x)
+#define d(x) x
 
 #define GET_PRIVATE(o) \
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), EWS_TYPE_OAB_DECODER, EwsOabDecoderPrivate))
@@ -40,14 +42,153 @@ typedef struct _EwsOabDecoderPrivate EwsOabDecoderPrivate;
 
 struct _EwsOabDecoderPrivate {
 	gchar *cache_dir;
+	gchar *folder_id;
 	GFileInputStream *fis;
-	GDataInputStream *dis;
 
 	EBookBackendSqliteDB *ebsdb;
 
 	guint32 total_records;
 	GSList *hdr_props;
 	GSList *oab_props;
+
+	GHashTable *prop_index_dict;
+};
+
+/* The of properties which will be accumulated and later set in EContact */
+typedef struct {
+	EContactAddress *addr;
+} EwsDeferredSet;
+
+static void
+ews_populate_simple_string (EContact *contact, EContactField field, gpointer value, gpointer user_data)
+{
+	const gchar *str = (const gchar *) value;
+	e_contact_set (contact, field, str);
+}
+
+static void
+ews_deffered_populate_physical_address (EwsDeferredSet *dset, guint32 prop_id, gpointer value)
+{
+	gchar *val = g_strdup ((gchar *)value);
+
+	if (!dset->addr)
+		dset->addr = g_new0 (EContactAddress, 1);
+	
+	switch (prop_id) {
+		case EWS_PT_STREET_ADDRESS:
+			dset->addr->street = val;
+			break;
+		case EWS_PT_LOCALITY:
+			dset->addr->locality = val;
+			break;
+		case EWS_PT_STATE_OR_PROVINCE:
+			dset->addr->region = val;
+			break;
+		case EWS_PT_POSTAL_CODE:
+			dset->addr->code = val;
+			break;
+		case EWS_PT_COUNTRY:
+			dset->addr->country = val;
+			break;
+		default:
+			g_free (val);
+			break;
+	}
+}
+
+static void
+ews_populate_phone_numbers (EContact *contact, EContactField field, gpointer value, gpointer user_data)
+{
+	GSList *values = (GSList *) value;
+	gint i, len;
+
+	/* Just the two phone numbers from the list. it would be either business or home phone number. I don't
+	   see a cleaner way than this at the moment */
+	len = g_slist_length (values);
+	for (i = 0; i < 2 && i < len; i++) {
+		const gchar *val = g_slist_nth_data (values, i);
+		e_contact_set (contact, field + i, val);
+	}
+}
+
+static void
+ews_populate_string_list (EContact *contact, EContactField field, gpointer value, gpointer user_data)
+{
+	GSList *sl_values = (GSList *)	value, *sl;
+	GList *l_values = NULL;
+
+
+	for (sl = sl_values; sl != NULL; sl = g_slist_next (sl)) {
+		const gchar *val = (gchar *) sl_values->data;
+		l_values = g_list_prepend (l_values, g_strdup (val));
+	}
+
+	l_values = g_list_reverse (l_values);
+	e_contact_set (contact, field, l_values);
+
+	g_list_free (l_values);
+}
+
+static void
+ews_populate_photo (EContact *contact, EContactField field, gpointer value, gpointer user_data)
+{
+	EwsOabDecoder *eod = EWS_OAB_DECODER (user_data);
+	EwsOabDecoderPrivate *priv = GET_PRIVATE (eod);
+	const gchar *val = (gchar *) value;
+	EContactPhoto *photo = g_new0 (EContactPhoto, 1);
+	gchar *fullname = e_contact_get (contact, E_CONTACT_FULL_NAME);
+	gchar *filename = NULL, *pic_name = NULL;
+
+	/* Rename the binary file to fullname.png */
+	if (fullname) {
+		pic_name = g_strconcat (fullname, ".png", NULL);
+		filename = g_build_filename (priv->cache_dir, pic_name, NULL);
+		g_rename (val, filename);
+	} else
+		filename = g_strdup (val);
+
+	photo->type = E_CONTACT_PHOTO_TYPE_URI;
+	photo->data.uri = filename;
+
+	e_contact_set (contact, field, (gpointer) photo);
+	
+	g_free (photo);
+	g_free (fullname);
+	g_free (pic_name);
+	g_free (filename);
+}
+
+static const struct prop_field_mapping {
+	guint32 prop_id;
+	EContactField field;
+	void (*populate_function) (EContact *contact, EContactField field, gpointer value, gpointer user_data);
+	void (*defered_populate_function) (EwsDeferredSet *dset, guint32 prop_id, gpointer value);
+} prop_map [] = {
+	{EWS_PT_SMTP_ADDRESS, E_CONTACT_EMAIL_1, ews_populate_simple_string},
+	{EWS_PT_DISPLAY_NAME, E_CONTACT_FULL_NAME, ews_populate_simple_string},
+	{EWS_PT_ACCOUNT, E_CONTACT_NICKNAME, ews_populate_simple_string},
+	{EWS_PT_SURNAME, E_CONTACT_FAMILY_NAME, ews_populate_simple_string},
+	{EWS_PT_GIVEN_NAME, E_CONTACT_GIVEN_NAME, ews_populate_simple_string},
+	{EWS_PT_BUS_TEL_NUMBER, E_CONTACT_PHONE_BUSINESS, ews_populate_simple_string},
+	{EWS_PT_STREET_ADDRESS, E_CONTACT_ADDRESS_WORK, NULL, ews_deffered_populate_physical_address},
+	{EWS_PT_LOCALITY, E_CONTACT_ADDRESS_WORK, NULL, ews_deffered_populate_physical_address},
+	{EWS_PT_STATE_OR_PROVINCE, E_CONTACT_ADDRESS_WORK, NULL, ews_deffered_populate_physical_address},
+	{EWS_PT_POSTAL_CODE, E_CONTACT_ADDRESS_WORK, NULL, ews_deffered_populate_physical_address},
+	{EWS_PT_COUNTRY, E_CONTACT_ADDRESS_WORK, NULL, ews_deffered_populate_physical_address},
+	{EWS_PT_TITLE, E_CONTACT_TITLE, ews_populate_simple_string},
+	{EWS_PT_COMPANY_NAME, E_CONTACT_ORG, ews_populate_simple_string},
+	{EWS_PT_ASSISTANT, E_CONTACT_ASSISTANT, ews_populate_simple_string},
+	{EWS_PT_DEPARTMENT_NAME, E_CONTACT_ORG_UNIT, ews_populate_simple_string},
+	{EWS_PT_HOME_TEL_NUMBER, E_CONTACT_PHONE_HOME, ews_populate_simple_string},
+	{EWS_PT_BUS_TEL_NUMBERS, E_CONTACT_PHONE_BUSINESS, ews_populate_phone_numbers},
+	{EWS_PT_HOME_TEL_NUMBERS, E_CONTACT_PHONE_HOME, ews_populate_phone_numbers},
+	{EWS_PT_PRIMARY_FAX_NUMBER, E_CONTACT_PHONE_BUSINESS_FAX, ews_populate_simple_string},
+	{EWS_PT_MOB_TEL_NUMBER, E_CONTACT_PHONE_MOBILE, ews_populate_simple_string},
+	{EWS_PT_ASSISTANT_TEL_NUMBER, E_CONTACT_PHONE_ASSISTANT, ews_populate_simple_string},
+	{EWS_PT_PAGER_NUMBER, E_CONTACT_PHONE_PAGER, ews_populate_simple_string},
+	{EWS_PT_COMMENT, E_CONTACT_NOTE, ews_populate_simple_string},
+	{EWS_PT_DL_MEMBERS, E_CONTACT_EMAIL, ews_populate_string_list},
+	{EWS_PT_THUMBNAIL_PHOTO, E_CONTACT_PHOTO, ews_populate_photo}
 };
 
 static void
@@ -59,15 +200,25 @@ ews_oab_decoder_finalize (GObject *object)
 		g_free (priv->cache_dir);
 		priv->cache_dir = NULL;
 	}
-	
+
+	if (priv->folder_id) {
+		g_free (priv->folder_id);
+		priv->folder_id = NULL;
+	}
+
 	if (priv->ebsdb) {
 		g_object_unref (priv->ebsdb);
 		priv->ebsdb = NULL;
 	}
 
-	if (priv->dis) {
-		g_object_unref (priv->dis);
-		priv->dis = NULL;
+	if (priv->fis) {
+		g_object_unref (priv->fis);
+		priv->fis = NULL;
+	}
+
+	if (priv->prop_index_dict) {
+		g_hash_table_destroy (priv->prop_index_dict);
+		priv->prop_index_dict = NULL;
 	}
 
 	G_OBJECT_CLASS (ews_oab_decoder_parent_class)->finalize (object);
@@ -87,13 +238,19 @@ static void
 ews_oab_decoder_init (EwsOabDecoder *self)
 {
 	EwsOabDecoderPrivate *priv = GET_PRIVATE (self);
+	gint i;
 
 	priv->cache_dir = NULL;
+
+	priv->prop_index_dict = g_hash_table_new (g_direct_hash, g_direct_equal);
+	for (i = 1; i <= G_N_ELEMENTS (prop_map); i++)
+		g_hash_table_insert (priv->prop_index_dict, GINT_TO_POINTER (prop_map[i-1].prop_id), GINT_TO_POINTER (i));
 }
 
 EwsOabDecoder*
 ews_oab_decoder_new	(const gchar *oab_filename,
 			 const gchar *cache_dir,
+			 const gchar *folder_id,
 			 EBookBackendSqliteDB *ebsdb,
 		   	 GError **error)
 {
@@ -110,11 +267,10 @@ ews_oab_decoder_new	(const gchar *oab_filename,
 	if (err)
 		goto exit;
 	
-	priv->dis = g_data_input_stream_new ((GInputStream *) priv->fis);
 	priv->ebsdb = g_object_ref (ebsdb);
 	priv->cache_dir = g_strdup (cache_dir);
+	priv->folder_id = g_strdup (folder_id);
 
-	g_data_input_stream_set_byte_order (priv->dis, G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN);
 exit:
 	if (gf)
 		g_object_unref (gf);
@@ -140,6 +296,62 @@ ews_oab_decoder_error_quark (void)
 	return quark;
 }
 
+/* endian-neutral reading of little-endian data */
+#define __egi32(a,n) ( ((((unsigned char *) a)[n+3]) << 24) | \
+		       ((((unsigned char *) a)[n+2]) << 16) | \
+		       ((((unsigned char *) a)[n+1]) <<  8) | \
+		       ((((unsigned char *) a)[n+0])))
+#define EndGetI64(a) ((((unsigned long long int) __egi32(a,4)) << 32) | \
+		      ((unsigned int) __egi32(a,0)))
+#define EndGetI32(a) __egi32(a,0)
+#define EndGetI16(a) ((((a)[1])<<8)|((a)[0]))
+
+static guint32
+ews_oab_read_uint32 (GInputStream *is, GCancellable *cancellable, GError **error)
+{
+	gchar *str = g_malloc0 (4);
+	guint32 ret = 0;
+	
+	g_input_stream_read (is, str, 4, cancellable, error);
+	if (!*error)
+		ret = EndGetI32 (str);
+
+	g_free (str);
+	return ret;
+}
+
+static guint16
+ews_oab_read_uint16 (GInputStream *is, GCancellable *cancellable, GError **error)
+{
+	gchar *str = g_malloc0 (2);
+	guint16 ret = 0;
+	
+	g_input_stream_read (is, str, 2, cancellable, error);
+	if (!*error)
+		ret = EndGetI16 (str);
+
+	g_free (str);
+	return ret;
+}
+
+/* Read upto the stop char include the same */
+static gchar *
+ews_oab_read_upto (GInputStream *is, gchar stop, GCancellable *cancellable, GError **error)
+{
+	gchar c = -1;
+	GString *str;
+
+	str = g_string_new (NULL);
+	do {
+		g_input_stream_read (is, &c, 1, cancellable, error);
+		if (c == stop)
+			break;
+		str = g_string_append_c (str, c);
+	} while (!*error);
+
+	return g_string_free (str, FALSE);
+}
+
 typedef struct {
 	guint32 version;
 	guint32 serial;
@@ -154,7 +366,7 @@ ews_read_oab_header (EwsOabDecoder *eod, GCancellable *cancellable, GError **err
 
 	o_hdr = g_new0 (EwsOabHdr, 1);
 
-	o_hdr->version = g_data_input_stream_read_uint32 (priv->dis, cancellable, error);
+	o_hdr->version = ews_oab_read_uint32 (G_INPUT_STREAM (priv->fis), cancellable, error);
 	if (*error)
 		goto exit;
 
@@ -163,10 +375,10 @@ ews_read_oab_header (EwsOabDecoder *eod, GCancellable *cancellable, GError **err
 		goto exit;
 	}
 
-	o_hdr->serial = g_data_input_stream_read_uint32 (priv->dis, cancellable, error);
+	o_hdr->serial = ews_oab_read_uint32 (G_INPUT_STREAM (priv->fis), cancellable, error);
 	if (*error)
 		goto exit;
-	o_hdr->total_recs = g_data_input_stream_read_uint32 (priv->dis, cancellable, error);
+	o_hdr->total_recs = ews_oab_read_uint32 (G_INPUT_STREAM (priv->fis), cancellable, error);
 
 exit:
 	if (*error) {
@@ -186,7 +398,7 @@ ews_decode_hdr_props (EwsOabDecoder *eod, gboolean oab_hdrs, GCancellable *cance
 	GSList **props;
 	
 	/* number of properties */
-	num_props = g_data_input_stream_read_uint32 (priv->dis, cancellable, error);
+	num_props = ews_oab_read_uint32 (G_INPUT_STREAM (priv->fis), cancellable, error);
 	if (*error)
 		return FALSE;
 
@@ -198,13 +410,13 @@ ews_decode_hdr_props (EwsOabDecoder *eod, gboolean oab_hdrs, GCancellable *cance
 	for (i = 0; i < num_props; i++) {
 		guint32 prop_id, flags;
 		
-		prop_id = g_data_input_stream_read_uint32 (priv->dis, cancellable, error);
-		d(g_print ("%x \n", prop_id);)
+		prop_id = ews_oab_read_uint32 (G_INPUT_STREAM (priv->fis), cancellable, error);
+		d(g_print ("%X \n", prop_id);)
 		*props = g_slist_prepend (*props, GUINT_TO_POINTER (prop_id));
 		
 		if (*error)
 			return FALSE;
-		flags = g_data_input_stream_read_uint32 (priv->dis, cancellable, error);
+		flags = ews_oab_read_uint32 (G_INPUT_STREAM (priv->fis), cancellable, error);
 		if (*error)
 			return FALSE;
 
@@ -225,7 +437,7 @@ ews_decode_metadata (EwsOabDecoder *eod, GCancellable *cancellable, GError **err
 	guint32 size;
 
 	/* Size */
-	size = g_data_input_stream_read_uint32 (priv->dis, cancellable, error);
+	size = ews_oab_read_uint32 (G_INPUT_STREAM (priv->fis), cancellable, error);
 	if (*error)
 		return FALSE;
 
@@ -257,11 +469,11 @@ ews_decode_uint32 (EwsOabDecoder *eod, GCancellable *cancellable, GError **error
 {
 	EwsOabDecoderPrivate *priv = GET_PRIVATE (eod);
 	guint8 first;
-	guint32 ret = -1, num;
+	guint32 ret = 0, num;
 	
-	first = g_data_input_stream_read_byte (priv->dis, cancellable, error);
+	g_input_stream_read (G_INPUT_STREAM (priv->fis), &first, 1, cancellable, error);
 	if (*error)
-		goto exit;
+		return ret;
 	
 	if (first & 0x80)
 		num = first & 0x0F;
@@ -269,18 +481,18 @@ ews_decode_uint32 (EwsOabDecoder *eod, GCancellable *cancellable, GError **error
 		return (guint32) first;
 
 	if (num == 1) {
-		ret = g_data_input_stream_read_byte (priv->dis, cancellable, error);
-		goto exit;
+		g_input_stream_read (G_INPUT_STREAM (priv->fis), &first, 1, cancellable, error);
+		return (guint32) first;
 	}
 
 	if (num == 2)
-		ret = (guint16) g_data_input_stream_read_uint16 (priv->dis, cancellable, error);
+		ret = ews_oab_read_uint16 (G_INPUT_STREAM (priv->fis), cancellable, error);
 	if (num == 3) {
 		gchar *tmp, *str = g_malloc0 (num + 1);
 	
-		g_input_stream_read (G_INPUT_STREAM (priv->dis), str, num, cancellable, error);
+		g_input_stream_read (G_INPUT_STREAM (priv->fis), str, num, cancellable, error);
 		/* not sure if its the right way to do, test it */
-		tmp = g_strconcat ("0000", str, NULL);
+		tmp = g_strconcat ("0", str, NULL);
 
 		ret = atoi (tmp);
 		ret = GUINT32_SWAP_LE_BE (ret);
@@ -288,9 +500,8 @@ ews_decode_uint32 (EwsOabDecoder *eod, GCancellable *cancellable, GError **error
 		g_free (str);
 		g_free (tmp);
 	} else if (num == 4)
-		ret = g_data_input_stream_read_uint32 (priv->dis, cancellable, error);
+		ret = ews_oab_read_uint32 (G_INPUT_STREAM (priv->fis), cancellable, error);
 
-exit:
 	return ret;	
 }
 
@@ -307,7 +518,7 @@ ews_decode_binary (EwsOabDecoder *eod, GCancellable *cancellable, GError **error
 		return NULL;
 	
 	binary = g_malloc (len);
-	g_input_stream_read (G_INPUT_STREAM (priv->dis), binary, len, cancellable, error);
+	g_input_stream_read (G_INPUT_STREAM (priv->fis), binary, len, cancellable, error);
 	if (*error)
 		goto exit;
 
@@ -340,7 +551,7 @@ ews_decode_oab_prop (EwsOabDecoder *eod, guint32 prop_id, GCancellable *cancella
 			val = ews_decode_uint32 (eod, cancellable, error);
 			ret_val = GUINT_TO_POINTER (val);
 			
-			d(g_print ("prop id %x prop type: int32 value %d \n", prop_id, val);)
+			d(g_print ("prop id %X prop type: int32 value %d \n", prop_id, val);)
 		
 			break;		
 		}
@@ -348,29 +559,27 @@ ews_decode_oab_prop (EwsOabDecoder *eod, guint32 prop_id, GCancellable *cancella
 		{
 			guchar val;
 
-			val = g_data_input_stream_read_byte (priv->dis, cancellable, error);
+			g_input_stream_read (G_INPUT_STREAM (priv->fis), &val, 1, cancellable, error);
 			ret_val = GUINT_TO_POINTER ((guint) val);
-			d(g_print ("prop id %x prop type: bool value %d \n", prop_id, val);)
+			d(g_print ("prop id %X prop type: bool value %d \n", prop_id, val);)
 			
 			break;
 		}
 		case EWS_PTYP_STRING8:
 		case EWS_PTYP_STRING:
 		{
-			gsize len;
 			gchar *val;
 		       	
-			val= g_data_input_stream_read_upto (priv->dis, "\0", 1, &len, cancellable, error);
-			g_data_input_stream_read_byte (priv->dis, cancellable, error);
+			val = ews_oab_read_upto (G_INPUT_STREAM (priv->fis), '\0', cancellable, error);
 			ret_val = (gpointer) val;
 			
-			d(g_print ("prop id %x prop type: string value %s \n", prop_id, val);)
+			d(g_print ("prop id %X prop type: string value %s \n", prop_id, val);)
 			break;
 		}
 		case EWS_PTYP_BINARY:
 		{
 			ret_val = ews_decode_binary (eod, cancellable, error);
-			d(g_print ("prop id %x prop type: binary value %s \n", prop_id, (gchar *) ret_val);)
+			d(g_print ("prop id %X prop type: binary value %s \n", prop_id, (gchar *) ret_val);)
 			break;
 		}
 		case EWS_PTYP_MULTIPLEINTEGER32:
@@ -384,7 +593,7 @@ ews_decode_oab_prop (EwsOabDecoder *eod, guint32 prop_id, GCancellable *cancella
 			num = ews_decode_uint32 (eod, cancellable, error);
 			if (*error)
 				break;
-			d(g_print ("prop id %x prop type: multi-num %d \n", prop_id, num);)
+			d(g_print ("prop id %X prop type: multi-num %d \n", prop_id, num);)
 
 			for (i = 0; i < num; i++) {
 				gpointer val;
@@ -396,7 +605,7 @@ ews_decode_oab_prop (EwsOabDecoder *eod, guint32 prop_id, GCancellable *cancella
 					val = GUINT_TO_POINTER (v);
 					list = g_slist_prepend (list, val);
 					
-					d(g_print ("prop id %x prop type: multi-int32 %d \n", prop_id, v);)
+					d(g_print ("prop id %X prop type: multi-int32 %d \n", prop_id, v);)
 					if (*error) {
 						g_slist_free (list);
 						return NULL;
@@ -406,15 +615,10 @@ ews_decode_oab_prop (EwsOabDecoder *eod, guint32 prop_id, GCancellable *cancella
 
 					if (prop_type == EWS_PTYP_MULTIPLEBINARY) {
 						val = ews_decode_binary (eod, cancellable, error);
-						
-						d(g_print ("prop id %x prop type: multi-string %s \n", prop_id, val);)
+						d(g_print ("prop id %X prop type: multi-string %s \n", prop_id, val);)
 					} else {
-						gsize len;
-
-						val= g_data_input_stream_read_upto (priv->dis, "\0", 1, &len, cancellable, error);
-						g_data_input_stream_read_byte (priv->dis, cancellable, error);
-					
-						d(g_print ("prop id %x prop type: multi-string %s \n", prop_id, val);)
+						val = ews_oab_read_upto (G_INPUT_STREAM (priv->fis), '\0', cancellable, error);
+						d(g_print ("prop id %X prop type: multi-string %s \n", prop_id, val);)
 					}
 
 					if (*error) {
@@ -454,7 +658,8 @@ ews_destroy_oab_prop (guint32 prop_id, gpointer val, gboolean delete_files)
 			g_free ((gchar *) val);
 			break;
 		case EWS_PTYP_MULTIPLEBINARY:
-			g_slist_foreach ((GSList *)val, (GFunc) g_unlink, NULL);
+			if (delete_files)
+				g_slist_foreach ((GSList *)val, (GFunc) g_unlink, NULL);
 		case EWS_PTYP_MULTIPLESTRING8:
 		case EWS_PTYP_MULTIPLESTRING:
 			g_slist_foreach ((GSList *)val, (GFunc) g_free, NULL);
@@ -471,36 +676,35 @@ ews_destroy_oab_prop (guint32 prop_id, gpointer val, gboolean delete_files)
  * ews_decode_addressbook_record 
  * @eod: 
  * @contact: Pass a valid EContact for decoding the address-book record. NULL in case of header record.
- * @props: 
+ * @props:
+ * @dset: used to collect multiple properties that needs to be combined and stored as one EContactField
  * @cancellable: 
  * @error: 
  * 
- * Decodes the header and address-book records.
+ * Decodes the address-book records starting from presence bit array.
+ *
+ *
  * Returns: 
  **/
 static gboolean
-ews_decode_addressbook_record (EwsOabDecoder *eod, EContact *contact, GSList *props, GCancellable *cancellable, GError **error)
+ews_decode_addressbook_record (EwsOabDecoder *eod, EContact *contact, EwsDeferredSet *dset, GSList *props, GCancellable *cancellable, GError **error)
 {
 	EwsOabDecoderPrivate *priv = GET_PRIVATE (eod);
 	guint bit_array_size, i, len;
 	gchar *bit_str;
 	gboolean ret = TRUE;
-	goffset offset;
-
-	/* fetch the offset */
-	offset = g_seekable_tell ((GSeekable *) priv->fis);
 
 	len = g_slist_length (props);
 	bit_array_size = (guint) ceil (len/8.0);
 	bit_str = g_malloc0 (bit_array_size);
-	g_input_stream_read (G_INPUT_STREAM (priv->dis), bit_str, bit_array_size, cancellable, error);
+	g_input_stream_read (G_INPUT_STREAM (priv->fis), bit_str, bit_array_size, cancellable, error);
 	if (*error) {
 		ret = FALSE;	
 		goto exit;
 	}
 
 	for (i = 0; i < len; i++) {
-		gpointer val;
+		gpointer val, index;
 		guint32 prop_id;
 
 		if (!ews_is_bit_set (bit_str, i))
@@ -512,13 +716,19 @@ ews_decode_addressbook_record (EwsOabDecoder *eod, EContact *contact, GSList *pr
 		val = ews_decode_oab_prop (eod, prop_id, cancellable, error);
 
 		/* Check the contact map and store the data in EContact */
-		if (contact) {
-			
+		index = g_hash_table_lookup (priv->prop_index_dict, GINT_TO_POINTER (prop_id));
+		if (contact && index) {
+			gint i = GPOINTER_TO_INT (index);
+
+			if (prop_map [i-1].populate_function)
+				prop_map [i-1].populate_function (contact, prop_map[i-1].field, val, (gpointer) eod);
+			else
+				prop_map [i-1].defered_populate_function (dset, prop_id, val);
 		}
 
-		/* Store the contact summary into the db along with the offset */
-
-		ews_destroy_oab_prop (prop_id, val, *error ? TRUE : FALSE);
+		/* delete the binary file if we do not have the property in the index or if there
+		   was an error */
+		ews_destroy_oab_prop (prop_id, val, (*error || !index) ? TRUE : FALSE);
 		if (*error)
 			goto exit;
 	}
@@ -530,7 +740,7 @@ exit:
 	return ret;
 }
 
-/* Decodes the hrd and address-book records and stores the address-book records inside the db */
+/* Decodes the hdr and address-book records and stores the address-book records inside the db */
 static gboolean
 ews_decode_and_store_oab_records (EwsOabDecoder *eod, GCancellable *cancellable, GError **error)
 {
@@ -538,8 +748,8 @@ ews_decode_and_store_oab_records (EwsOabDecoder *eod, GCancellable *cancellable,
 	gboolean ret = TRUE;
 	guint32 size, i;
 
-	size = g_data_input_stream_read_uint32 (priv->dis, cancellable, error);
-	ews_decode_addressbook_record (eod, NULL, priv->hdr_props, cancellable, error);
+	size = ews_oab_read_uint32 (G_INPUT_STREAM (priv->fis), cancellable, error);
+	ews_decode_addressbook_record (eod, NULL, NULL, priv->hdr_props, cancellable, error);
 	if (*error) {
 		ret = FALSE;
 		goto exit;
@@ -547,25 +757,66 @@ ews_decode_and_store_oab_records (EwsOabDecoder *eod, GCancellable *cancellable,
 
 	for (i = 0; i < priv->total_records; i++) {
 		EContact *contact;
+		EwsDeferredSet *dset;
+		gchar *uid = NULL, *bdata = NULL;
+		goffset offset;
 
 		contact = e_contact_new ();
-		size = g_data_input_stream_read_uint32 (priv->dis, cancellable, error);
-		ews_decode_addressbook_record (eod, contact, priv->oab_props, cancellable, error);
-		if (*error) {
-			g_object_unref (contact);
-			ret = FALSE;
-			goto exit;
-		}
+		dset = g_new0 (EwsDeferredSet, 1);
+		size = ews_oab_read_uint32 (G_INPUT_STREAM (priv->fis), cancellable, error);
+
+		/* fetch the offset */
+		offset = g_seekable_tell ((GSeekable *) priv->fis);
+
+		ews_decode_addressbook_record (eod, contact, dset, priv->oab_props, cancellable, error);
+		if (*error)
+			goto error;
 		
-		/* Store the contact summary into db with its offset */
+		if (dset->addr)
+			e_contact_set (contact, E_CONTACT_ADDRESS_WORK, dset->addr);
+	
+		/* set the smtp address as contact's uid */
+		uid = (gchar *) e_contact_get (contact, E_CONTACT_EMAIL_1);
+		e_contact_set (contact, E_CONTACT_UID, uid);
 
+		/* convert the offset to string */
+		bdata = g_strdup_printf ("%"G_GOFFSET_FORMAT, offset);
+
+		d(g_print ("%s \n", e_vcard_to_string ((EVCard *) contact, EVC_FORMAT_VCARD_30));)
+			
+		/* Store the contact inside the db with the offset */
+		e_book_backend_sqlitedb_add_contact (priv->ebsdb, priv->folder_id, contact, FALSE, error);
+		if (*error)
+			goto error;
+
+		e_book_backend_sqlitedb_set_contact_bdata (priv->ebsdb, priv->folder_id, uid, bdata, error);
+
+error:		
 		g_object_unref (contact);
+		e_contact_address_free (dset->addr);
+		g_free (dset);
+		g_free (uid);
+		g_free (bdata);
+
+		if (*error) {
+			ret = FALSE;	
+			goto exit;
+		}
 	}
 
 exit: 
 	return ret;	
 }
 
+static gboolean
+ews_store_oab_props (EwsOabDecoder *eod, GError **error)
+{
+	gboolean ret = TRUE;
+	/* TODO Implement */
+
+	return ret;
+}
+
 /**
  * ews_oab_decoder_decode 
  * @eod: 
@@ -600,6 +851,10 @@ ews_oab_decoder_decode	(EwsOabDecoder *eod,
 		goto exit;
 	
 	ret = ews_decode_and_store_oab_records (eod, cancellable, &err);
+	if (!ret)
+		goto exit;
+
+	ret = ews_store_oab_props (eod, &err);
 
 exit:
 	if (o_hdr)
@@ -628,20 +883,25 @@ ews_oab_decoder_get_contact_from_offset	(EwsOabDecoder *eod,
 					 GError **error)
 {
 	EwsOabDecoderPrivate *priv = GET_PRIVATE (eod);
+	EwsDeferredSet *dset;
 	EContact *contact = NULL;
 
-	if (!g_seekable_seek ((GSeekable *) priv->dis, offset, G_SEEK_CUR, cancellable, error))
+	if (!g_seekable_seek ((GSeekable *) priv->fis, offset, G_SEEK_CUR, cancellable, error))
 		return NULL;
 
 	/* priv->oab_props = fetch from sqlite db */ 
 
 	contact = e_contact_new ();
-	ews_decode_addressbook_record (eod, contact, priv->oab_props, cancellable, error);
+	dset = g_new0 (EwsDeferredSet, 1);
+	ews_decode_addressbook_record (eod, contact, dset, priv->oab_props, cancellable, error);
 	if (*error) {
 		g_object_unref (contact);
 		contact = NULL;
 	}
 	
+	e_contact_address_free (dset->addr);
+	g_free (dset);
+	
 	if (priv->oab_props) {
 		g_slist_free (priv->oab_props);
 		priv->oab_props = NULL;
@@ -649,3 +909,30 @@ ews_oab_decoder_get_contact_from_offset	(EwsOabDecoder *eod,
 
 	return contact;
 }
+
+/*
+gint 
+main (gint argc, gchar *argv [])
+{
+	EBookBackendSqliteDB *ebsdb;
+	EwsOabDecoder *eod;
+	GError *err = NULL;
+
+	g_type_init ();
+	g_thread_init (NULL);
+
+	if (argc != 3) {
+		g_print ("Pass the oab filename  and cache dir as argument \n");
+		return -1;
+	}
+
+	ebsdb = e_book_backend_sqlitedb_new (argv [2], "dum", "de", "dum", FALSE, NULL);
+	eod = ews_oab_decoder_new (argv [1], argv [2], "de", ebsdb, &err);
+	if (!ews_oab_decoder_decode (eod, NULL, &err)) {
+		g_print ("Unable to decode %s \n", err->message);
+	}
+
+
+	if (err)
+		g_clear_error (&err);
+} */
diff --git a/src/addressbook/ews-oab-decoder.h b/src/addressbook/ews-oab-decoder.h
index 9f0cb55..8e09e86 100644
--- a/src/addressbook/ews-oab-decoder.h
+++ b/src/addressbook/ews-oab-decoder.h
@@ -60,6 +60,7 @@ GType ews_oab_decoder_get_type (void);
 
 EwsOabDecoder*	ews_oab_decoder_new	(const gchar *oab_filename,
 					 const gchar *cache_dir,
+					 const gchar *folder_id,
 					 EBookBackendSqliteDB *ebsdb,
 					 GError **error);
 gboolean	ews_oab_decoder_decode	(EwsOabDecoder *eod,



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