commit 4740ce99f9aa4bdca3fd10e7a86b07925971e079
Author: Punit Jain <jpunit@novell.com>
Date:   Wed Mar 14 16:36:22 2012 +0530

    Bug #654810 finditem API implementation

diff --git a/src/addressbook/Makefile.am b/src/addressbook/Makefile.am
index 7264a9c..89e9230 100644
--- a/src/addressbook/Makefile.am
+++ b/src/addressbook/Makefile.am
@@ -38,11 +38,11 @@ libebookbackendews_la_LIBADD =					\
 	$(top_builddir)/src/addressbook/lzx/liblzx.la		\
 	$(LIBEBACKEND_LIBS)					\
 	$(LIBEDATASERVER_LIBS)					\
-	$(LIBEDATABOOK_LIBS) \
+	$(LIBEDATABOOK_LIBS) 					\
 	$(LIBEBOOK_LIBS)					\
 	$(DB_LIBS)						\
 	$(EVOLUTION_ADDRESSBOOK_LIBS)				\
-	$(SQLITE3_LIBS)	\
+	$(SQLITE3_LIBS)						\
 	$(SOUP_LIBS)
 
 libebookbackendews_la_LDFLAGS =		\
diff --git a/src/addressbook/e-book-backend-ews.c b/src/addressbook/e-book-backend-ews.c
index 340e7a7..45410c7 100644
--- a/src/addressbook/e-book-backend-ews.c
+++ b/src/addressbook/e-book-backend-ews.c
@@ -56,12 +56,15 @@
 #include "e-ews-message.h"
 #include "e-ews-connection.h"
 #include "e-ews-item.h"
+#include <e-ews-query-to-restriction.h>
 
 #define d(x) x
 #define EDB_ERROR(_code) GNOME_Evolution_Addressbook_##_code
 
 G_DEFINE_TYPE (EBookBackendEws, e_book_backend_ews, E_TYPE_BOOK_BACKEND)
 
+static gboolean ebews_fetch_items (EBookBackendEws *ebews,  GSList *items, gboolean store_to_cache, GSList **vcards, GError **error);
+
 typedef struct {
 	GCond *cond;
 	GMutex *mutex;
@@ -1158,18 +1161,18 @@ e_book_backend_ews_get_contact	(EBookBackend *backend,
 				 GCancellable *cancellable,
 				 const gchar   *id)
 {
-	EBookBackendEws *gwb;
+	EBookBackendEws *ebews;
 
-	gwb =  E_BOOK_BACKEND_EWS (backend);
+	ebews =  E_BOOK_BACKEND_EWS (backend);
 
-	switch (gwb->priv->mode) {
+	switch (ebews->priv->mode) {
 
 	case GNOME_Evolution_Addressbook_MODE_LOCAL :
 		e_data_book_respond_get_contact (book, opid, EDB_ERROR (ContactNotFound), "");
 		return;
 
 	case GNOME_Evolution_Addressbook_MODE_REMOTE :
-		if (gwb->priv->cnc == NULL) {
+		if (ebews->priv->cnc == NULL) {
 			e_data_book_respond_get_contact (book, opid, EDB_ERROR (OtherError), NULL);
 			return;
 		}
@@ -1187,28 +1190,92 @@ e_book_backend_ews_get_contact_list	(EBookBackend *backend,
 					 GCancellable *cancellable,
 					 const gchar   *query )
 {
-	GList *vcard_list;
-	EBookBackendEws *egwb;
+	GSList *vcard_list = NULL;
+	GSList *list, *l;
+	GError *error = NULL;
+	EBookBackendEws *ebews;
+	EBookBackendEwsPrivate *priv;
 
-	egwb = E_BOOK_BACKEND_EWS (backend);
-	vcard_list = NULL;
+	ebews = E_BOOK_BACKEND_EWS (backend);
+	priv = ebews->priv;
 
-	switch (egwb->priv->mode) {
+	switch (priv->mode) {
 
 	case GNOME_Evolution_Addressbook_MODE_LOCAL :
 
-		e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (Success), vcard_list);
-		return;
+		if (e_book_backend_sqlitedb_get_is_populated (priv->ebsdb, priv->folder_id, NULL)) {
+			list = e_book_backend_sqlitedb_search (priv->ebsdb, priv->folder_id, query, NULL, NULL, NULL, &error);
+			l = list;
+			while (l) {
+				EbSdbSearchData *s_data = (EbSdbSearchData *) l->data;
+
+				vcard_list = g_slist_append (vcard_list, g_strdup (s_data->vcard));
+				e_book_backend_sqlitedb_search_data_free (s_data);
+				l = l->next;
+			}
+			e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (Success), (GList *) vcard_list);
+
+			g_slist_free (list);
+			g_slist_foreach (vcard_list, (GFunc) g_free, NULL);
+			g_slist_free (vcard_list);
+			return;
+		} else
+			e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (OfflineUnavailable), (GList *) vcard_list);
+			return;
 
 	case GNOME_Evolution_Addressbook_MODE_REMOTE:
 
-		if (egwb->priv->cnc == NULL) {
+		if (priv->cnc == NULL) {
 			e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (AuthenticationRequired), NULL);
 			return;
 		}
 
-		e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (Success), vcard_list);
+		if (e_book_backend_sqlitedb_get_is_populated (priv->ebsdb, priv->folder_id, NULL)) {
+			list = e_book_backend_sqlitedb_search (priv->ebsdb, priv->folder_id, query, NULL, NULL, NULL, &error);
+			l = list;
+			while (l) {
+				EbSdbSearchData *s_data = (EbSdbSearchData *) l->data;
+
+				vcard_list = g_slist_append (vcard_list, g_strdup (s_data->vcard));
+				e_book_backend_sqlitedb_search_data_free (s_data);
+				l = l->next;
+			}
+
+			e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (Success), (GList *) vcard_list);
+
+			g_slist_free (list);
+			g_slist_foreach (vcard_list, (GFunc) g_free, NULL);
+			g_slist_free (vcard_list);
+			return;
+
+		} else if (!priv->marked_for_offline) {
+			GSList *items=NULL;
+			EwsFolderId *fid=NULL;
+			gboolean includes_last_item;
+
+			fid = g_new0 (EwsFolderId, 1);
+			fid->id = g_strdup (priv->folder_id);
+			fid->is_distinguished_id = FALSE;
+
+			e_ews_connection_find_folder_items (priv->cnc, EWS_PRIORITY_MEDIUM,
+								fid, "IdOnly", NULL, NULL, query,
+								EWS_FOLDER_TYPE_CONTACTS,
+								&includes_last_item,
+							 	&items, (EwsConvertQueryCallback) (e_ews_query_to_restriction),
+								NULL, &error);
+
+			/*we have got Id for items lets fetch them using getitem operation*/
+			ebews_fetch_items (ebews, items, FALSE, &vcard_list, &error);
+			e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (Success), (GList *) vcard_list);
+
+			e_ews_folder_free_fid (fid);
+			g_slist_foreach (vcard_list, (GFunc) g_free, NULL);
+			g_slist_free (vcard_list);
+			return;
+		} else
+			e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (OtherError), (GList *) vcard_list);
 		return;
+
 	default :
 		break;
 
@@ -1724,6 +1791,38 @@ ebews_store_contact_items (EBookBackendEws *ebews, GSList *new_items, gboolean d
 }
 
 static void
+ebews_get_vcards_list (GSList *new_items, GSList **vcards)
+{
+	GSList *l;
+
+	for (l = new_items; l != NULL; l = g_slist_next (l)) {
+		EContact *contact;
+		gint i, element_type;
+		EEwsItem *item;
+		gchar *vcard_string=NULL;
+	
+		item = (EEwsItem *) l->data;
+		contact = e_contact_new ();
+
+		for (i = 0; i < G_N_ELEMENTS (mappings); i++) {
+			element_type = mappings[i].element_type;
+			if (element_type == ELEMENT_TYPE_SIMPLE && !mappings [i].populate_contact_func) {
+				const char *val = mappings [i].get_simple_prop_func (item);
+				if (val != NULL)
+					e_contact_set (contact, mappings [i].field_id, val);
+			} else
+				mappings[i].populate_contact_func (contact, item);
+		}
+		vcard_string = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+		*vcards = g_slist_append (*vcards, g_strdup(vcard_string));
+		g_free (vcard_string);
+		g_object_unref (item);
+		g_object_unref (contact);
+	}
+	g_slist_free (new_items);
+}
+
+static void
 ews_mb_free (EwsMailbox *mb)
 {
 	if (mb) {
@@ -1785,7 +1884,52 @@ ebews_store_distribution_list_items (EBookBackendEws *ebews, const EwsId *id, co
 }
 
 static void
-ebews_sync_items (EBookBackendEws *ebews, GSList *items, GError **error)
+ebews_vcards_append_dl (const EwsId *id, const gchar *d_name, GSList *members, GSList **vcards)
+{
+	GSList *l;
+	EContact *contact;
+	gchar *vcard_string=NULL;
+
+	contact = e_contact_new ();
+	e_contact_set (contact, E_CONTACT_UID, id->id);
+	e_contact_set (contact, E_CONTACT_REV, id->change_key);
+	
+	e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (TRUE));
+	e_contact_set (contact, E_CONTACT_LIST_SHOW_ADDRESSES, GINT_TO_POINTER (TRUE));
+	e_contact_set (contact, E_CONTACT_FULL_NAME, d_name);
+
+	for (l = members; l != NULL; l = g_slist_next (l)) {
+		EwsMailbox *mb = (EwsMailbox *)	l->data;
+		EVCardAttribute *attr;
+
+		attr = e_vcard_attribute_new (NULL, EVC_EMAIL);
+		if (mb->name) {
+			gint len = strlen (mb->name);
+			gchar *value;
+
+			if (mb->name [0] == '\"' && mb->name [len - 1] == '\"')
+				value = g_strdup_printf ("%s <%s>", mb->name, mb->email);
+			else
+				value = g_strdup_printf ("\"%s\" <%s>", mb->name, mb->email);
+
+			e_vcard_attribute_add_value (attr, value);
+			g_free (value);
+		} else
+			e_vcard_attribute_add_value (attr, mb->email);
+
+		e_vcard_add_attribute (E_VCARD (contact), attr);
+		ews_mb_free (mb);
+	}
+	vcard_string = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+	*vcards = g_slist_append (*vcards, g_strdup(vcard_string));
+	g_free (vcard_string);
+	g_slist_free (members);
+	g_object_unref (contact);
+}
+
+
+static gboolean
+ebews_fetch_items (EBookBackendEws *ebews, GSList *items, gboolean store_to_cache, GSList **vcards, GError **error)
 {
 	EBookBackendEwsPrivate *priv;
 	EEwsConnection *cnc;
@@ -1822,8 +1966,12 @@ ebews_sync_items (EBookBackendEws *ebews, GSList *items, GError **error)
 	if (*error)
 		goto cleanup;
 
-	if (new_items)
-		ebews_store_contact_items (ebews, new_items, FALSE, error);
+	if (new_items) {
+		if (store_to_cache)
+			ebews_store_contact_items (ebews, new_items, FALSE, error);
+		else
+			ebews_get_vcards_list (new_items, vcards);
+	}
 	new_items = NULL;
 
 	/* Get the display names of the distribution lists */
@@ -1856,8 +2004,12 @@ ebews_sync_items (EBookBackendEws *ebews, GSList *items, GError **error)
 		e_ews_connection_expand_dl (cnc, EWS_PRIORITY_MEDIUM, mb, &members, &includes_last, NULL, error);
 		if (*error)
 			goto cleanup;
+
+		if (store_to_cache)
+			ebews_store_distribution_list_items (ebews, id, d_name, members, error);
+		else
+			ebews_vcards_append_dl (id, d_name, members, vcards);
 		
-		ebews_store_distribution_list_items (ebews, id, d_name, members, error);
 		g_free (mb);
 
 		if (*error)
@@ -1879,6 +2031,8 @@ cleanup:
 		g_slist_foreach (contact_item_ids, (GFunc) g_free, NULL);
 		g_slist_free (contact_item_ids);
 	}
+
+	return TRUE;
 }
 
 static gboolean
@@ -1919,7 +2073,7 @@ ebews_start_sync	(gpointer data)
 			ebews_sync_deleted_items (ebews, items_deleted, &error);
 
 		if (items_created)
-			ebews_sync_items (ebews, items_created, &error);
+			ebews_fetch_items (ebews, items_created, TRUE, NULL, &error);
 
 		if (error) {
 			if (items_updated) {
@@ -1931,7 +2085,7 @@ ebews_start_sync	(gpointer data)
 		}
 
 		if (items_updated)
-			ebews_sync_items (ebews, items_updated, &error);
+			ebews_fetch_items (ebews, items_updated, TRUE, NULL, &error);
 
 		if (error)
 			break;
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index 67cda45..b4c49bb 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -97,6 +97,7 @@ struct _EwsAsyncData {
 	GSList *items_updated;
 	GSList *items_deleted;
 
+	gint total_items;
 	const gchar *directory;
 	GSList *items;
 	gchar *sync_state;
@@ -578,6 +579,38 @@ get_folder_response_cb  (ESoapParameter *subparam, EwsNode *enode)
 	}
 }
 
+static void 
+find_folder_items_response_cb (ESoapParameter *subparam, EwsNode *enode)
+{
+	ESoapParameter *node, *subparam1;
+	EwsAsyncData *async_data;
+	gchar *last, *total;
+	gint total_items;
+	EEwsItem *item;
+	gboolean includes_last_item = FALSE;
+
+	node = e_soap_parameter_get_first_child_by_name (subparam, "RootFolder");
+	total = e_soap_parameter_get_property (node, "TotalItemsInView");
+	total_items = atoi (total);
+	g_free (total);
+	last = e_soap_parameter_get_property (node, "IncludesLastItemInRange");
+	if (!strcmp (last, "true"))
+		includes_last_item = TRUE;
+	g_free (last);
+
+	async_data = g_simple_async_result_get_op_res_gpointer (enode->simple);
+
+	node = e_soap_parameter_get_first_child_by_name (node, "Items");
+	for (subparam1 = e_soap_parameter_get_first_child (node);
+	     subparam1; subparam1 = e_soap_parameter_get_next_child (subparam1)) {
+		item = e_ews_item_new_from_soap_parameter (subparam1);
+		if (!item) continue;
+		async_data->items = g_slist_append (async_data->items, item);
+	}
+	async_data->total_items = total_items;
+	async_data->includes_last_item = includes_last_item;
+}
+
 /* Used for CreateItems and GetItems */
 static void
 get_items_response_cb (ESoapParameter *subparam, EwsNode *enode)
@@ -1938,6 +1971,47 @@ ews_append_additional_props_to_msg (ESoapMessage *msg, EwsAdditionalProps *add_p
 	e_soap_message_end_element (msg);
 }
 
+static void
+ews_write_sort_order_to_msg (ESoapMessage *msg, EwsSortOrder *sort_order)
+{
+	if (!sort_order)
+		return;
+
+	e_soap_message_start_element (msg, "SortOrder", NULL, NULL);
+	e_soap_message_start_element (msg, "FieldOrder", NULL, NULL);
+	e_soap_message_add_attribute (msg, "Order", sort_order->order, NULL, NULL);
+
+	if (sort_order->uri_type == NORMAL_FIELD_URI)
+		e_ews_message_write_string_parameter_with_attribute (msg, "FieldURI", NULL, NULL, "FieldURI", (gchar *) sort_order->field_uri);
+	else if (sort_order->uri_type == INDEXED_FIELD_URI) {
+		EwsIndexedFieldURI *in_furi = (EwsIndexedFieldURI *) sort_order->field_uri;
+
+		e_soap_message_start_element (msg, "IndexedFieldURI", NULL, NULL);
+		e_soap_message_add_attribute (msg, "FieldURI", in_furi->field_uri, NULL, NULL);
+		e_soap_message_add_attribute (msg, "FieldIndex", in_furi->field_index, NULL, NULL);
+		e_soap_message_end_element (msg);
+	} else if (sort_order->uri_type == EXTENDED_FIELD_URI) {
+		EwsExtendedFieldURI *ex_furi = (EwsExtendedFieldURI *) sort_order->field_uri;
+			
+		e_soap_message_start_element (msg, "ExtendedFieldURI", NULL, NULL);
+		
+		if (ex_furi->distinguished_prop_set_id)
+			e_soap_message_add_attribute (msg, "DistinguishedPropertySetId", ex_furi->distinguished_prop_set_id, NULL, NULL);
+		if (ex_furi->prop_set_id)
+			e_soap_message_add_attribute (msg, "PropertySetId", ex_furi->prop_set_id, NULL, NULL);
+		if (ex_furi->prop_name)
+			e_soap_message_add_attribute (msg, "PropertyName", ex_furi->prop_name, NULL, NULL);
+		if (ex_furi->prop_id)
+			e_soap_message_add_attribute (msg, "PropertyId", ex_furi->prop_id, NULL, NULL);
+		if (ex_furi->prop_type)
+			e_soap_message_add_attribute (msg, "PropertyType", ex_furi->prop_type, NULL, NULL);
+
+		e_soap_message_end_element (msg);
+	}
+
+	e_soap_message_end_element (msg);
+	e_soap_message_end_element (msg);
+}
 
 /**
  * e_ews_connection_sync_folder_items_start
@@ -2114,6 +2188,148 @@ ews_append_folder_ids_to_msg (ESoapMessage *msg, const gchar *email, GSList *fol
 	}
 }
 
+/**
+ * e_ews_connection_find_folder_items_start
+ * @cnc: The EWS Connection
+ * @pri: The priority associated with the request
+ * @fid: The folder id to which the items belong
+ * @default_props: Can take one of the values: IdOnly,Default or AllProperties
+ * @add_props: Specify any additional properties to be fetched
+ * @sort_order: Specific sorting order for items
+ * @query: evo query based on which items will be fetched
+ * @type: type of folder
+ * @convert_query_cb: a callback method to convert query to ews restiction
+ * @cb: Responses are parsed and returned to this callback
+ * @cancellable: a GCancellable to monitor cancelled operations
+ * @user_data: user data passed to callback
+ **/
+void
+e_ews_connection_find_folder_items_start	(EEwsConnection *cnc,
+						 gint pri,
+						 EwsFolderId *fid,
+						 const gchar *default_props,
+						 EwsAdditionalProps *add_props,
+						 EwsSortOrder *sort_order,
+						 const gchar *query,
+						 EwsFolderType type,
+						 EwsConvertQueryCallback convert_query_cb,
+						 GAsyncReadyCallback cb,
+						 GCancellable *cancellable,
+						 gpointer user_data)
+{
+	ESoapMessage *msg;
+	GSimpleAsyncResult *simple;
+	EwsAsyncData *async_data;
+
+	msg = e_ews_message_new_with_header (cnc->priv->uri, "FindItem", "Traversal", "Shallow", EWS_EXCHANGE_2007_SP1);
+	e_soap_message_start_element (msg, "ItemShape", "messages", NULL);
+	e_ews_message_write_string_parameter (msg, "BaseShape", NULL, default_props);
+
+	ews_append_additional_props_to_msg (msg, add_props);
+
+	e_soap_message_end_element (msg);
+
+	/*write restriction message based on query*/
+	if (convert_query_cb)
+		convert_query_cb (msg, query, type);
+
+	if (sort_order)
+		ews_write_sort_order_to_msg (msg, sort_order);
+
+	e_soap_message_start_element (msg, "ParentFolderIds", "messages", NULL);
+
+	if (fid->is_distinguished_id)
+		e_ews_message_write_string_parameter_with_attribute (msg, "DistinguishedFolderId", NULL, NULL, "Id", fid->id);
+	else
+		e_ews_message_write_string_parameter_with_attribute (msg, "FolderId", NULL, NULL, "Id", fid->id);
+
+	e_soap_message_end_element (msg);
+
+	/* Complete the footer and print the request */
+	e_ews_message_write_footer (msg);
+
+      	simple = g_simple_async_result_new (G_OBJECT (cnc),
+                                      cb,
+                                      user_data,
+                                      e_ews_connection_find_folder_items_start);
+
+	async_data = g_new0 (EwsAsyncData, 1);
+	g_simple_async_result_set_op_res_gpointer (
+		simple, async_data, (GDestroyNotify) async_data_free);
+
+	ews_connection_queue_request (cnc, msg, find_folder_items_response_cb, pri,
+				      cancellable, simple, cb == ews_sync_reply_cb);
+}
+
+gboolean
+e_ews_connection_find_folder_items_finish	(EEwsConnection *cnc,
+						 GAsyncResult *result,
+						 gboolean *includes_last_item,
+						 GSList **items,
+						 GError **error)
+{
+	GSimpleAsyncResult *simple;
+	EwsAsyncData *async_data;
+
+	g_return_val_if_fail (
+		g_simple_async_result_is_valid (
+		result, G_OBJECT (cnc), e_ews_connection_find_folder_items_start),
+		FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+	async_data = g_simple_async_result_get_op_res_gpointer (simple);
+
+	if (g_simple_async_result_propagate_error (simple, error))
+		return FALSE;
+
+	*includes_last_item = async_data->includes_last_item;
+	*items = async_data->items;
+
+	return TRUE;
+}
+
+gboolean
+e_ews_connection_find_folder_items	(EEwsConnection *cnc,
+					 gint pri,
+					 EwsFolderId *fid,
+					 const gchar *default_props,
+					 EwsAdditionalProps *add_props,
+					 EwsSortOrder *sort_order,
+					 const gchar *query,
+					 EwsFolderType type,
+					 gboolean *includes_last_item,
+					 GSList **items,
+					 EwsConvertQueryCallback convert_query_cb,
+					 GCancellable *cancellable,
+					 GError **error)
+{
+	EwsSyncData *sync_data;
+	gboolean result;
+
+	sync_data = g_new0 (EwsSyncData, 1);
+	sync_data->eflag = e_flag_new ();
+
+	e_ews_connection_find_folder_items_start	(cnc, pri, fid, default_props,
+							 add_props, sort_order, query,
+							 type, convert_query_cb,
+							 ews_sync_reply_cb, NULL,
+							 (gpointer) sync_data);
+
+	e_flag_wait (sync_data->eflag);
+
+	result = e_ews_connection_find_folder_items_finish (cnc, sync_data->res,
+							    includes_last_item,
+							    items,
+							    error);
+
+	e_flag_free (sync_data->eflag);
+	g_object_unref (sync_data->res);
+	g_free (sync_data);
+
+	return result;
+}
+
+
 void
 e_ews_connection_sync_folder_hierarchy_start	(EEwsConnection *cnc,
 						 gint pri,
@@ -3276,7 +3492,7 @@ e_ews_connection_move_folder	(EEwsConnection *cnc,
 }
 
 
-void		
+void
 e_ews_connection_get_folder_start	(EEwsConnection *cnc,
 					 gint pri,
 					 const gchar *folder_shape,
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index a2eb33a..60e1465 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -138,6 +138,11 @@ typedef struct{
 	gboolean view_priv_items;
 }EwsDelegateInfo;
 
+typedef enum {
+	NORMAL_FIELD_URI,
+	INDEXED_FIELD_URI,
+	EXTENDED_FIELD_URI
+} EwsFieldURIType;
 
 typedef struct {
 	gchar *distinguished_prop_set_id;
@@ -159,6 +164,12 @@ typedef struct {
 	GSList *indexed_furis;
 } EwsAdditionalProps;
 
+typedef struct {
+	gchar *order;
+	gint uri_type;
+	gpointer field_uri;
+} EwsSortOrder;
+
 GType		e_ews_connection_get_type	(void);
 EEwsConnection *e_ews_connection_new		(const gchar *uri,
 						 const gchar *username,
@@ -223,6 +234,47 @@ gboolean	e_ews_connection_sync_folder_items
 						 GCancellable *cancellable,
 						 GError **error);
 
+typedef void	(*EwsConvertQueryCallback) (ESoapMessage *msg,
+						 const gchar *query,
+						 EwsFolderType type);
+
+void		e_ews_connection_find_folder_items_start
+						(EEwsConnection *cnc,
+						 gint pri,
+						 EwsFolderId *fid,
+						 const gchar *props,
+						 EwsAdditionalProps *add_props,
+						 EwsSortOrder *sort_order,
+						 const gchar *query,
+						 EwsFolderType type,
+						 EwsConvertQueryCallback convert_query_cb,
+						 GAsyncReadyCallback cb,
+						 GCancellable *cancellable,
+						 gpointer user_data);
+
+gboolean	e_ews_connection_find_folder_items_finish
+						(EEwsConnection *cnc,
+						 GAsyncResult *result,
+						 gboolean *includes_last_item,
+						 GSList **items,
+						 GError **error);
+
+gboolean	e_ews_connection_find_folder_items
+						(EEwsConnection *cnc,
+						 gint pri,
+						 EwsFolderId *fid,
+						 const gchar *default_props,
+						 EwsAdditionalProps *add_props,
+						 EwsSortOrder *sort_order,
+						 const gchar *query,
+						 EwsFolderType type,
+						 gboolean *includes_last_item,
+						 GSList **items,
+						 EwsConvertQueryCallback convert_query_cb,
+						 GCancellable *cancellable,
+						 GError **error);
+
+
 /* Get folder items */
 void		e_ews_connection_get_items_start
 						(EEwsConnection *cnc,
diff --git a/src/server/e-ews-item.c b/src/server/e-ews-item.c
index 429e37b..508e549 100644
--- a/src/server/e-ews-item.c
+++ b/src/server/e-ews-item.c
@@ -862,56 +862,77 @@ static gboolean
 e_ews_item_set_from_soap_parameter (EEwsItem *item, ESoapParameter *param)
 {
 	EEwsItemPrivate *priv = item->priv;
-	ESoapParameter *subparam, *node;
+	ESoapParameter *subparam, *node=NULL;
 	gboolean contact = FALSE, task = FALSE;
+	const gchar *name;
 
 	g_return_val_if_fail (param != NULL, FALSE);
 
-	if ((node = e_soap_parameter_get_first_child_by_name (param, "AttachmentId"))) {
-		priv->attachment_id = g_new0 (EwsId, 1);
-		priv->attachment_id->id = e_soap_parameter_get_property (node, "Id");
-		priv->attachment_id->change_key = e_soap_parameter_get_property (node, "ChangeKey");
-	} else if ((node = e_soap_parameter_get_first_child_by_name (param, "ItemId"))) {
-		/*Spesial case when we are facing  <ReadFlagChange> during sync folders*/
-		priv->item_id = g_new0 (EwsId, 1);
-		priv->item_id->id = e_soap_parameter_get_property (node, "Id");
-		priv->item_id->change_key = e_soap_parameter_get_property (node, "ChangeKey");
-		return TRUE;
-	} else if ((node = e_soap_parameter_get_first_child_by_name (param, "Message")))
+	name = e_soap_parameter_get_name (param);
+
+	/*We get two types of response for items from server like below from two apis
+	 *  Syncfolderitems			and  		Finditem
+	 * <m:Changes>							<t:Items>
+            <t:Create>							  <t:Contact>
+              <t:Contact>						    <t:ItemId Id="AS4AUn=" ChangeKey="fsVU4==" />
+                <t:ItemId Id="AAA=" ChangeKey="NAgws"/>			  </t:Contact>
+              </t:Contact>						  <t:Contact>
+            </t:Create>							    <t:ItemId Id="AS4BS=" ChangeKey="fjidU4==" />
+	      <t:Contact>						  </t:Contact>
+                <t:ItemId Id="ABB=" ChangeKey="GCDab"/>			  ...
+              </t:Contact>						</t:Items>
+	    </t:Create>
+	    ...
+	   </m:Changes> 
+	   So check param is the node we want to use, by comparing name or is it child of the param */
+
+	if (!g_ascii_strcasecmp (name, "Message") || (node = e_soap_parameter_get_first_child_by_name (param, "Message")))
 		priv->item_type = E_EWS_ITEM_TYPE_MESSAGE;
-	else if ((node = e_soap_parameter_get_first_child_by_name (param, "PostItem")))
+	else if (!g_ascii_strcasecmp (name, "PostItem") || (node = e_soap_parameter_get_first_child_by_name (param, "PostItem")))
 		priv->item_type = E_EWS_ITEM_TYPE_POST_ITEM;
-	else if ((node = e_soap_parameter_get_first_child_by_name (param, "CalendarItem")))
+	else if (!g_ascii_strcasecmp (name, "CalendarItem") || (node = e_soap_parameter_get_first_child_by_name (param, "CalendarItem")))
 		priv->item_type = E_EWS_ITEM_TYPE_CALENDAR_ITEM;
-	else if ((node = e_soap_parameter_get_first_child_by_name (param, "Contact"))) {
+	else if (!g_ascii_strcasecmp (name, "Contact") || (node = e_soap_parameter_get_first_child_by_name (param, "Contact"))) {
 		contact = TRUE;	
 		priv->item_type = E_EWS_ITEM_TYPE_CONTACT;
 		priv->contact_fields = g_new0 (struct _EEwsContactFields, 1);
-	} else if ((node = e_soap_parameter_get_first_child_by_name (param, "DistributionList")))
+	} else if (!g_ascii_strcasecmp (name, "DistributionList") || (node = e_soap_parameter_get_first_child_by_name (param, "DistributionList")))
 		priv->item_type = E_EWS_ITEM_TYPE_GROUP;
-	else if ((node = e_soap_parameter_get_first_child_by_name (param, "MeetingMessage")))
+	else if (!g_ascii_strcasecmp (name, "MeetingMessage") || (node = e_soap_parameter_get_first_child_by_name (param, "MeetingMessage")))
 		priv->item_type = E_EWS_ITEM_TYPE_MEETING_MESSAGE;
-	else if ((node = e_soap_parameter_get_first_child_by_name (param, "MeetingRequest")))
+	else if (!g_ascii_strcasecmp (name, "MeetingRequest") || (node = e_soap_parameter_get_first_child_by_name (param, "MeetingRequest")))
 		priv->item_type = E_EWS_ITEM_TYPE_MEETING_REQUEST;
-	else if ((node = e_soap_parameter_get_first_child_by_name (param, "MeetingResponse")))
+	else if (!g_ascii_strcasecmp (name, "MeetingResponse") || (node = e_soap_parameter_get_first_child_by_name (param, "MeetingResponse")))
 		priv->item_type = E_EWS_ITEM_TYPE_MEETING_RESPONSE;
-	else if ((node = e_soap_parameter_get_first_child_by_name (param, "MeetingCancellation")))
+	else if (!g_ascii_strcasecmp (name, "MeetingCancellation") || (node = e_soap_parameter_get_first_child_by_name (param, "MeetingCancellation")))
 		priv->item_type = E_EWS_ITEM_TYPE_MEETING_CANCELLATION;
-	else if ((node = e_soap_parameter_get_first_child_by_name (param, "Task"))) {
+	else if (!g_ascii_strcasecmp (name, "Task") || (node = e_soap_parameter_get_first_child_by_name (param, "Task"))) {
 		task = TRUE;
 		priv->item_type = E_EWS_ITEM_TYPE_TASK;
 		priv->task_fields = g_new0 (struct _EEwsTaskFields, 1);
 		priv->task_fields->has_due_date = FALSE;
 		priv->task_fields->has_start_date = FALSE;
 		priv->task_fields->has_complete_date = FALSE;
-	}
-	else if ((node = e_soap_parameter_get_first_child_by_name (param, "Item")))
+	} else if (!g_ascii_strcasecmp (name, "Item") || (node = e_soap_parameter_get_first_child_by_name (param, "Item")))
 		priv->item_type = E_EWS_ITEM_TYPE_GENERIC_ITEM;
-	else {
+	else if ((node = e_soap_parameter_get_first_child_by_name (param, "AttachmentId"))) {
+		priv->attachment_id = g_new0 (EwsId, 1);
+		priv->attachment_id->id = e_soap_parameter_get_property (node, "Id");
+		priv->attachment_id->change_key = e_soap_parameter_get_property (node, "ChangeKey");
+	} else if ((node = e_soap_parameter_get_first_child_by_name (param, "ItemId"))) {
+		/*Spesial case when we are facing  <ReadFlagChange> during sync folders*/
+		priv->item_id = g_new0 (EwsId, 1);
+		priv->item_id->id = e_soap_parameter_get_property (node, "Id");
+		priv->item_id->change_key = e_soap_parameter_get_property (node, "ChangeKey");
+		return TRUE;
+	} else {
 		g_warning ("Unable to find the Item type \n");
 		return FALSE;
 	}
 
+	if (!node)
+		node = param;
+
 	for (subparam = e_soap_parameter_get_first_child (node);
 			subparam != NULL;
 			subparam = e_soap_parameter_get_next_child (subparam)) {
diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am
index 947940a..a810ff1 100644
--- a/src/utils/Makefile.am
+++ b/src/utils/Makefile.am
@@ -10,7 +10,8 @@ libewsutils_la_CPPFLAGS = \
 	$(LIBEDATASERVER_CFLAGS)			\
 	$(SQLITE3_CFLAGS)				\
 	$(DEBUG_CFLAGS)					\
-	$(CAMEL_CFLAGS)
+	$(CAMEL_CFLAGS)					\
+	$(LIBEDATACAL_CFLAGS)
 
 libewsutils_la_SOURCES =				\
 	ews-camel-compat.h				\
@@ -20,14 +21,33 @@ libewsutils_la_SOURCES =				\
 	e-sqlite3-vfs.c					\
 	e-sqlite3-vfs.h					\
 	ews-camel-common.c				\
-	ews-camel-common.h
+	ews-camel-common.h				\
+	e-ews-query-to-restriction.c			\
+	e-ews-query-to-restriction.h
 
 libewsutils_la_LIBADD =					\
 	$(top_builddir)/src/server/libeews-1.2.la 	\
-	$(SQLITE3_LIBS)	\
+	$(SQLITE3_LIBS)					\
 	$(LIBEDATASERVER_LIBS)				\
-	$(CAMEL_LIBS)
+	$(CAMEL_LIBS)					\
+	$(LIBEDATACAL_LIBS)
 
 libewsutils_la_LDFLAGS = $(NO_UNDEFINED)
 
+noinst_PROGRAMS = ews-test-finditem-query
+
+TESTS = ews-test-finditem-query
+check_PROGRAMS = ews-test-finditem-query
+
+ews_test_finditem_query_CPPFLAGS =			\
+	$(libewsutils_la_CPPFLAGS)			
+
+ews_test_finditem_query_SOURCES = 			\
+	ews-test-finditem-query.c			\
+	e-ews-query-to-restriction.c			\
+	e-ews-query-to-restriction.h
+
+ews_test_finditem_query_LDADD = 			\
+	$(libewsutils_la_LIBADD)
+
 -include $(top_srcdir)/git.mk
diff --git a/src/utils/e-ews-query-to-restriction.c b/src/utils/e-ews-query-to-restriction.c
index b7d3f06..4bb18cb 100644
--- a/src/utils/e-ews-query-to-restriction.c
+++ b/src/utils/e-ews-query-to-restriction.c
@@ -665,7 +665,7 @@ message_func_system_flag (ESExp *f,
 			WRITE_EXISTS_MESSAGE (msg, "item:HasAttachments")
 		} else if (!g_ascii_strcasecmp(name, "deleted") || !g_ascii_strcasecmp(name, "junk")) {
 			r = e_sexp_result_new (f, ESEXP_RES_BOOL);
-			r->value.boolean = FALSE;
+			r->value.bool = FALSE;
 			return r;
 		}
 	}
@@ -717,6 +717,23 @@ message_func_current_date (ESExp *f,
 	return r;
 }
 
+/* slightly modified version from master */
+static time_t
+ews_add_months (time_t t,
+		gint months)
+{
+	time_t res;
+
+	if (!months)
+		return t;
+
+	/* just for issues, to return something inaccurate, but sane */
+	res = t + (60 * 60 * 24 * 30 * months);
+
+	return res;
+}
+
+
 static ESExpResult *
 message_func_relative_months (ESExp *f,
 				gint argc,
@@ -728,11 +745,11 @@ message_func_relative_months (ESExp *f,
 
 	if (argc != 1 || argv[0]->type != ESEXP_RES_INT) {
 		r = e_sexp_result_new (f, ESEXP_RES_BOOL);
-		r->value.boolean = FALSE;
+		r->value.bool = FALSE;
 
 	} else {
 		r = e_sexp_result_new (f, ESEXP_RES_INT);
-		r->value.number = camel_folder_search_util_add_months (time (NULL), argv[0]->value.number);
+		r->value.number = ews_add_months (time (NULL), argv[0]->value.number);
 	}
 
 	return r;
