6bbc61
diff -up evolution-data-server-3.8.5/camel/camel-imapx-search.c.imapx-server-side-search evolution-data-server-3.8.5/camel/camel-imapx-search.c
6bbc61
--- evolution-data-server-3.8.5/camel/camel-imapx-search.c.imapx-server-side-search	2013-07-23 13:57:42.000000000 +0200
6bbc61
+++ evolution-data-server-3.8.5/camel/camel-imapx-search.c	2014-02-03 16:39:00.652093324 +0100
6bbc61
@@ -27,6 +27,7 @@
6bbc61
 
6bbc61
 struct _CamelIMAPXSearchPrivate {
6bbc61
 	GWeakRef server;
6bbc61
+	gint *local_data_search; /* not NULL, if testing whether all used headers are all locally available */
6bbc61
 };
6bbc61
 
6bbc61
 enum {
6bbc61
@@ -88,32 +89,194 @@ imapx_search_dispose (GObject *object)
6bbc61
 }
6bbc61
 
6bbc61
 static CamelSExpResult *
6bbc61
+imapx_search_result_match_all (CamelSExp *sexp,
6bbc61
+			       CamelFolderSearch *search)
6bbc61
+{
6bbc61
+	CamelSExpResult *result;
6bbc61
+
6bbc61
+	g_return_val_if_fail (search != NULL, NULL);
6bbc61
+
6bbc61
+	if (search->current != NULL) {
6bbc61
+		result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_BOOL);
6bbc61
+		result->value.boolean = TRUE;
6bbc61
+	} else {
6bbc61
+		gint ii;
6bbc61
+
6bbc61
+		result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_ARRAY_PTR);
6bbc61
+		result->value.ptrarray = g_ptr_array_new ();
6bbc61
+
6bbc61
+		for (ii = 0; ii < search->summary->len; ii++)
6bbc61
+			g_ptr_array_add (
6bbc61
+				result->value.ptrarray,
6bbc61
+				(gpointer) search->summary->pdata[ii]);
6bbc61
+	}
6bbc61
+
6bbc61
+	return result;
6bbc61
+}
6bbc61
+
6bbc61
+static CamelSExpResult *
6bbc61
+imapx_search_result_match_none (CamelSExp *sexp,
6bbc61
+				CamelFolderSearch *search)
6bbc61
+{
6bbc61
+	CamelSExpResult *result;
6bbc61
+
6bbc61
+	g_return_val_if_fail (search != NULL, NULL);
6bbc61
+
6bbc61
+	if (search->current != NULL) {
6bbc61
+		result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_BOOL);
6bbc61
+		result->value.boolean = FALSE;
6bbc61
+	} else {
6bbc61
+		result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_ARRAY_PTR);
6bbc61
+		result->value.ptrarray = g_ptr_array_new ();
6bbc61
+	}
6bbc61
+
6bbc61
+	return result;
6bbc61
+}
6bbc61
+
6bbc61
+static CamelSExpResult *
6bbc61
+imapx_search_process_criteria (CamelSExp *sexp,
6bbc61
+			       CamelFolderSearch *search,
6bbc61
+			       CamelIMAPXServer *server,
6bbc61
+			       const GString *criteria,
6bbc61
+			       const gchar *from_function)
6bbc61
+{
6bbc61
+	CamelSExpResult *result;
6bbc61
+	GPtrArray *uids = NULL;
6bbc61
+	GError *error = NULL;
6bbc61
+
6bbc61
+	uids = camel_imapx_server_uid_search (
6bbc61
+		server, search->folder, criteria->str, NULL, &error);
6bbc61
+
6bbc61
+	/* Sanity check. */
6bbc61
+	g_return_val_if_fail (
6bbc61
+		((uids != NULL) && (error == NULL)) ||
6bbc61
+		((uids == NULL) && (error != NULL)), NULL);
6bbc61
+
6bbc61
+	/* XXX No allowance for errors in CamelSExp callbacks!
6bbc61
+	 *     Dump the error to the console and make like we
6bbc61
+	 *     got an empty result. */
6bbc61
+	if (error != NULL) {
6bbc61
+		g_warning (
6bbc61
+			"%s: (UID SEARCH %s): %s",
6bbc61
+			from_function, criteria->str, error->message);
6bbc61
+		uids = g_ptr_array_new ();
6bbc61
+		g_error_free (error);
6bbc61
+	}
6bbc61
+
6bbc61
+	if (search->current != NULL) {
6bbc61
+		result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_BOOL);
6bbc61
+		result->value.boolean = (uids && uids->len > 0);
6bbc61
+	} else {
6bbc61
+		result = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_ARRAY_PTR);
6bbc61
+		result->value.ptrarray = g_ptr_array_ref (uids);
6bbc61
+	}
6bbc61
+
6bbc61
+	g_ptr_array_unref (uids);
6bbc61
+
6bbc61
+	return result;
6bbc61
+}
6bbc61
+
6bbc61
+static CamelSExpResult *
6bbc61
+imapx_search_match_all (CamelSExp *sexp,
6bbc61
+			gint argc,
6bbc61
+			CamelSExpTerm **argv,
6bbc61
+			CamelFolderSearch *search)
6bbc61
+{
6bbc61
+	CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
6bbc61
+	CamelIMAPXServer *server;
6bbc61
+	CamelSExpResult *result;
6bbc61
+	GPtrArray *summary;
6bbc61
+	gint local_data_search = 0, *prev_local_data_search, ii;
6bbc61
+
6bbc61
+	if (argc != 1)
6bbc61
+		return imapx_search_result_match_none (sexp, search);
6bbc61
+
6bbc61
+	server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
6bbc61
+	if (!server || search->current || !search->summary) {
6bbc61
+		g_clear_object (&server);
6bbc61
+
6bbc61
+		/* Chain up to parent's method. */
6bbc61
+		return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
6bbc61
+			match_all (sexp, argc, argv, search);
6bbc61
+	}
6bbc61
+
6bbc61
+	/* First try to see whether all used headers are available locally - if
6bbc61
+	   they are, then do not use server-side filtering at all. */
6bbc61
+	prev_local_data_search = imapx_search->priv->local_data_search;
6bbc61
+	imapx_search->priv->local_data_search = &local_data_search;
6bbc61
+
6bbc61
+	summary = search->summary_set ? search->summary_set : search->summary;
6bbc61
+
6bbc61
+	if (!CAMEL_IS_VEE_FOLDER (search->folder)) {
6bbc61
+		camel_folder_summary_prepare_fetch_all (search->folder->summary, NULL);
6bbc61
+	}
6bbc61
+
6bbc61
+	for (ii = 0; ii < summary->len; ii++) {
6bbc61
+		search->current = camel_folder_summary_get (search->folder->summary, summary->pdata[ii]);
6bbc61
+		if (search->current) {
6bbc61
+			result = camel_sexp_term_eval (sexp, argv[0]);
6bbc61
+			camel_sexp_result_free (sexp, result);
6bbc61
+			camel_message_info_free (search->current);
6bbc61
+			search->current = NULL;
6bbc61
+			break;
6bbc61
+		}
6bbc61
+	}
6bbc61
+	imapx_search->priv->local_data_search = prev_local_data_search;
6bbc61
+
6bbc61
+	if (local_data_search >= 0) {
6bbc61
+		g_clear_object (&server);
6bbc61
+
6bbc61
+		/* Chain up to parent's method. */
6bbc61
+		return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
6bbc61
+			match_all (sexp, argc, argv, search);
6bbc61
+	}
6bbc61
+
6bbc61
+	/* let's change the requirements a bit, the parent class expects as a result boolean,
6bbc61
+	   but here is expected GPtrArray of matched UIDs */
6bbc61
+	result = camel_sexp_term_eval (sexp, argv[0]);
6bbc61
+
6bbc61
+	g_object_unref (server);
6bbc61
+
6bbc61
+	g_return_val_if_fail (result != NULL, result);
6bbc61
+	g_return_val_if_fail (result->type == CAMEL_SEXP_RES_ARRAY_PTR, result);
6bbc61
+
6bbc61
+	return result;
6bbc61
+}
6bbc61
+
6bbc61
+static CamelSExpResult *
6bbc61
 imapx_search_body_contains (CamelSExp *sexp,
6bbc61
                             gint argc,
6bbc61
                             CamelSExpResult **argv,
6bbc61
                             CamelFolderSearch *search)
6bbc61
 {
6bbc61
+	CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
6bbc61
 	CamelIMAPXServer *server;
6bbc61
 	CamelSExpResult *result;
6bbc61
-	CamelSExpResultType type;
6bbc61
 	GString *criteria;
6bbc61
-	GPtrArray *uids;
6bbc61
 	gint ii, jj;
6bbc61
-	GError *error = NULL;
6bbc61
+
6bbc61
+	/* Always do body-search server-side */
6bbc61
+	if (imapx_search->priv->local_data_search) {
6bbc61
+		*imapx_search->priv->local_data_search = -1;
6bbc61
+		return imapx_search_result_match_none (sexp, search);
6bbc61
+	}
6bbc61
 
6bbc61
 	/* Match everything if argv = [""] */
6bbc61
 	if (argc == 1 && argv[0]->value.string[0] == '\0')
6bbc61
-		goto match_all;
6bbc61
+		return imapx_search_result_match_all (sexp, search);
6bbc61
 
6bbc61
 	/* Match nothing if empty argv or empty summary. */
6bbc61
 	if (argc == 0 || search->summary->len == 0)
6bbc61
-		goto match_none;
6bbc61
+		return imapx_search_result_match_none (sexp, search);
6bbc61
 
6bbc61
 	server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
6bbc61
 
6bbc61
 	/* This will be NULL if we're offline.  Search from cache. */
6bbc61
-	if (server == NULL)
6bbc61
-		goto chain_up;
6bbc61
+	if (server == NULL) {
6bbc61
+		/* Chain up to parent's method. */
6bbc61
+		return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
6bbc61
+			body_contains (sexp, argc, argv, search);
6bbc61
+	}
6bbc61
 
6bbc61
 	/* Build the IMAP search criteria. */
6bbc61
 
6bbc61
@@ -157,78 +320,217 @@ imapx_search_body_contains (CamelSExp *s
6bbc61
 		}
6bbc61
 	}
6bbc61
 
6bbc61
-	uids = camel_imapx_server_uid_search (
6bbc61
-		server, search->folder, criteria->str, NULL, &error);
6bbc61
+	result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
6bbc61
 
6bbc61
-	/* Sanity check. */
6bbc61
-	g_return_val_if_fail (
6bbc61
-		((uids != NULL) && (error == NULL)) ||
6bbc61
-		((uids == NULL) && (error != NULL)), NULL);
6bbc61
+	g_string_free (criteria, TRUE);
6bbc61
+	g_object_unref (server);
6bbc61
 
6bbc61
-	/* XXX No allowance for errors in CamelSExp callbacks!
6bbc61
-	 *     Dump the error to the console and make like we
6bbc61
-	 *     got an empty result. */
6bbc61
-	if (error != NULL) {
6bbc61
-		g_warning (
6bbc61
-			"%s: (UID SEARCH %s): %s",
6bbc61
-			G_STRFUNC, criteria->str, error->message);
6bbc61
-		uids = g_ptr_array_new ();
6bbc61
-		g_error_free (error);
6bbc61
+	return result;
6bbc61
+}
6bbc61
+
6bbc61
+static gboolean
6bbc61
+imapx_search_is_header_from_summary (const gchar *header_name)
6bbc61
+{
6bbc61
+	return  g_ascii_strcasecmp (header_name, "From") == 0 ||
6bbc61
+		g_ascii_strcasecmp (header_name, "To") == 0 ||
6bbc61
+		g_ascii_strcasecmp (header_name, "CC") == 0 ||
6bbc61
+		g_ascii_strcasecmp (header_name, "Subject") == 0;
6bbc61
+}
6bbc61
+
6bbc61
+static CamelSExpResult *
6bbc61
+imapx_search_header_contains (CamelSExp *sexp,
6bbc61
+			      gint argc,
6bbc61
+			      CamelSExpResult **argv,
6bbc61
+			      CamelFolderSearch *search)
6bbc61
+{
6bbc61
+	CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
6bbc61
+	CamelIMAPXServer *server;
6bbc61
+	CamelSExpResult *result;
6bbc61
+	const gchar *headername, *command = NULL;
6bbc61
+	GString *criteria;
6bbc61
+	gint ii, jj;
6bbc61
+
6bbc61
+	/* Match nothing if empty argv or empty summary. */
6bbc61
+	if (argc <= 1 ||
6bbc61
+	    argv[0]->type != CAMEL_SEXP_RES_STRING ||
6bbc61
+	    search->summary->len == 0)
6bbc61
+		return imapx_search_result_match_none (sexp, search);
6bbc61
+
6bbc61
+	headername = argv[0]->value.string;
6bbc61
+
6bbc61
+	if (imapx_search_is_header_from_summary (headername)) {
6bbc61
+		if (imapx_search->priv->local_data_search) {
6bbc61
+			if (*imapx_search->priv->local_data_search >= 0)
6bbc61
+				*imapx_search->priv->local_data_search = (*imapx_search->priv->local_data_search) + 1;
6bbc61
+			return imapx_search_result_match_all (sexp, search);
6bbc61
+		}
6bbc61
+
6bbc61
+		/* Chain up to parent's method. */
6bbc61
+		return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
6bbc61
+			header_contains (sexp, argc, argv, search);
6bbc61
+	} else if (imapx_search->priv->local_data_search) {
6bbc61
+		*imapx_search->priv->local_data_search = -1;
6bbc61
+		return imapx_search_result_match_none (sexp, search);
6bbc61
+	}
6bbc61
+
6bbc61
+	server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
6bbc61
+
6bbc61
+	/* This will be NULL if we're offline.  Search from cache. */
6bbc61
+	if (server == NULL) {
6bbc61
+		/* Chain up to parent's method. */
6bbc61
+		return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
6bbc61
+			header_contains (sexp, argc, argv, search);
6bbc61
 	}
6bbc61
 
6bbc61
+	/* Build the IMAP search criteria. */
6bbc61
+
6bbc61
+	criteria = g_string_sized_new (128);
6bbc61
+
6bbc61
 	if (search->current != NULL) {
6bbc61
-		type = CAMEL_SEXP_RES_BOOL;
6bbc61
-		result = camel_sexp_result_new (sexp, type);
6bbc61
-		result->value.boolean = (uids->len > 0);
6bbc61
-	} else {
6bbc61
-		type = CAMEL_SEXP_RES_ARRAY_PTR;
6bbc61
-		result = camel_sexp_result_new (sexp, type);
6bbc61
-		result->value.ptrarray = g_ptr_array_ref (uids);
6bbc61
+		const gchar *uid;
6bbc61
+
6bbc61
+		/* Limit the search to a single UID. */
6bbc61
+		uid = camel_message_info_uid (search->current);
6bbc61
+		g_string_append_printf (criteria, "UID %s", uid);
6bbc61
 	}
6bbc61
 
6bbc61
-	g_ptr_array_unref (uids);
6bbc61
+	if (g_ascii_strcasecmp (headername, "From") == 0)
6bbc61
+		command = "FROM";
6bbc61
+	else if (g_ascii_strcasecmp (headername, "To") == 0)
6bbc61
+		command = "TO";
6bbc61
+	else if (g_ascii_strcasecmp (headername, "CC") == 0)
6bbc61
+		command = "CC";
6bbc61
+	else if (g_ascii_strcasecmp (headername, "Bcc") == 0)
6bbc61
+		command = "BCC";
6bbc61
+	else if (g_ascii_strcasecmp (headername, "Subject") == 0)
6bbc61
+		command = "SUBJECT";
6bbc61
 
6bbc61
-	g_string_free (criteria, TRUE);
6bbc61
+	for (ii = 1; ii < argc; ii++) {
6bbc61
+		struct _camel_search_words *words;
6bbc61
+		const guchar *term;
6bbc61
+
6bbc61
+		if (argv[ii]->type != CAMEL_SEXP_RES_STRING)
6bbc61
+			continue;
6bbc61
+
6bbc61
+		/* Handle multiple search words within a single term. */
6bbc61
+		term = (const guchar *) argv[ii]->value.string;
6bbc61
+		words = camel_search_words_split (term);
6bbc61
+
6bbc61
+		for (jj = 0; jj < words->len; jj++) {
6bbc61
+			gchar *cp;
6bbc61
+
6bbc61
+			if (criteria->len > 0)
6bbc61
+				g_string_append_c (criteria, ' ');
6bbc61
+
6bbc61
+			if (command)
6bbc61
+				g_string_append (criteria, command);
6bbc61
+			else
6bbc61
+				g_string_append_printf (criteria, "HEADER \"%s\"", headername);
6bbc61
+
6bbc61
+			g_string_append (criteria, " \"");
6bbc61
+
6bbc61
+			cp = words->words[jj]->word;
6bbc61
+			for (; *cp != '\0'; cp++) {
6bbc61
+				if (*cp == '\\' || *cp == '"')
6bbc61
+					g_string_append_c (criteria, '\\');
6bbc61
+				g_string_append_c (criteria, *cp);
6bbc61
+			}
6bbc61
+
6bbc61
+			g_string_append_c (criteria, '"');
6bbc61
+		}
6bbc61
+	}
6bbc61
+
6bbc61
+	result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
6bbc61
 
6bbc61
+	g_string_free (criteria, TRUE);
6bbc61
 	g_object_unref (server);
6bbc61
 
6bbc61
 	return result;
6bbc61
+}
6bbc61
 
6bbc61
-match_all:
6bbc61
-	if (search->current != NULL) {
6bbc61
-		type = CAMEL_SEXP_RES_BOOL;
6bbc61
-		result = camel_sexp_result_new (sexp, type);
6bbc61
-		result->value.boolean = TRUE;
6bbc61
-	} else {
6bbc61
-		type = CAMEL_SEXP_RES_ARRAY_PTR;
6bbc61
-		result = camel_sexp_result_new (sexp, type);
6bbc61
-		result->value.ptrarray = g_ptr_array_new ();
6bbc61
+static CamelSExpResult *
6bbc61
+imapx_search_header_exists (CamelSExp *sexp,
6bbc61
+			    gint argc,
6bbc61
+			    CamelSExpResult **argv,
6bbc61
+			    CamelFolderSearch *search)
6bbc61
+{
6bbc61
+	CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
6bbc61
+	CamelIMAPXServer *server;
6bbc61
+	CamelSExpResult *result;
6bbc61
+	GString *criteria;
6bbc61
+	gint ii;
6bbc61
 
6bbc61
-		for (ii = 0; ii < search->summary->len; ii++)
6bbc61
-			g_ptr_array_add (
6bbc61
-				result->value.ptrarray,
6bbc61
-				(gpointer) search->summary->pdata[ii]);
6bbc61
+	/* Match nothing if empty argv or empty summary. */
6bbc61
+	if (argc == 0 || search->summary->len == 0)
6bbc61
+		return imapx_search_result_match_none (sexp, search);
6bbc61
+
6bbc61
+	/* Check if asking for locally stored headers only */
6bbc61
+	for (ii = 0; ii < argc; ii++) {
6bbc61
+		if (argv[ii]->type != CAMEL_SEXP_RES_STRING)
6bbc61
+			continue;
6bbc61
+
6bbc61
+		if (!imapx_search_is_header_from_summary (argv[ii]->value.string))
6bbc61
+			break;
6bbc61
 	}
6bbc61
 
6bbc61
-	return result;
6bbc61
+	/* All headers are from summary */
6bbc61
+	if (ii == argc) {
6bbc61
+		if (imapx_search->priv->local_data_search) {
6bbc61
+			if (*imapx_search->priv->local_data_search >= 0)
6bbc61
+				*imapx_search->priv->local_data_search = (*imapx_search->priv->local_data_search) + 1;
6bbc61
+
6bbc61
+			return imapx_search_result_match_all (sexp, search);
6bbc61
+		}
6bbc61
+
6bbc61
+		/* Chain up to parent's method. */
6bbc61
+		return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
6bbc61
+			header_exists (sexp, argc, argv, search);
6bbc61
+	} else if (imapx_search->priv->local_data_search) {
6bbc61
+		*imapx_search->priv->local_data_search = -1;
6bbc61
+		return imapx_search_result_match_none (sexp, search);
6bbc61
+	}
6bbc61
+
6bbc61
+	server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
6bbc61
+
6bbc61
+	/* This will be NULL if we're offline.  Search from cache. */
6bbc61
+	if (server == NULL) {
6bbc61
+		/* Chain up to parent's method. */
6bbc61
+		return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
6bbc61
+			header_exists (sexp, argc, argv, search);
6bbc61
+	}
6bbc61
+
6bbc61
+	/* Build the IMAP search criteria. */
6bbc61
+
6bbc61
+	criteria = g_string_sized_new (128);
6bbc61
 
6bbc61
-match_none:
6bbc61
 	if (search->current != NULL) {
6bbc61
-		type = CAMEL_SEXP_RES_BOOL;
6bbc61
-		result = camel_sexp_result_new (sexp, type);
6bbc61
-		result->value.boolean = FALSE;
6bbc61
-	} else {
6bbc61
-		type = CAMEL_SEXP_RES_ARRAY_PTR;
6bbc61
-		result = camel_sexp_result_new (sexp, type);
6bbc61
-		result->value.ptrarray = g_ptr_array_new ();
6bbc61
+		const gchar *uid;
6bbc61
+
6bbc61
+		/* Limit the search to a single UID. */
6bbc61
+		uid = camel_message_info_uid (search->current);
6bbc61
+		g_string_append_printf (criteria, "UID %s", uid);
6bbc61
 	}
6bbc61
 
6bbc61
-	return result;
6bbc61
+	for (ii = 0; ii < argc; ii++) {
6bbc61
+		const gchar *headername;
6bbc61
+
6bbc61
+		if (argv[ii]->type != CAMEL_SEXP_RES_STRING)
6bbc61
+			continue;
6bbc61
+
6bbc61
+		headername = argv[ii]->value.string;
6bbc61
+
6bbc61
+		if (criteria->len > 0)
6bbc61
+			g_string_append_c (criteria, ' ');
6bbc61
 
6bbc61
-chain_up:
6bbc61
-	/* Chain up to parent's body_contains() method. */
6bbc61
-	return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
6bbc61
-		body_contains (sexp, argc, argv, search);
6bbc61
+		g_string_append_printf (criteria, "HEADER \"%s\" \"\"", headername);
6bbc61
+	}
6bbc61
+
6bbc61
+	result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
6bbc61
+
6bbc61
+	g_string_free (criteria, TRUE);
6bbc61
+	g_object_unref (server);
6bbc61
+
6bbc61
+	return result;
6bbc61
 }
6bbc61
 
6bbc61
 static void
6bbc61
@@ -245,7 +547,10 @@ camel_imapx_search_class_init (CamelIMAP
6bbc61
 	object_class->dispose = imapx_search_dispose;
6bbc61
 
6bbc61
 	search_class = CAMEL_FOLDER_SEARCH_CLASS (class);
6bbc61
+	search_class->match_all = imapx_search_match_all;
6bbc61
 	search_class->body_contains = imapx_search_body_contains;
6bbc61
+	search_class->header_contains = imapx_search_header_contains;
6bbc61
+	search_class->header_exists = imapx_search_header_exists;
6bbc61
 
6bbc61
 	g_object_class_install_property (
6bbc61
 		object_class,
6bbc61
@@ -263,6 +568,7 @@ static void
6bbc61
 camel_imapx_search_init (CamelIMAPXSearch *search)
6bbc61
 {
6bbc61
 	search->priv = CAMEL_IMAPX_SEARCH_GET_PRIVATE (search);
6bbc61
+	search->priv->local_data_search = NULL;
6bbc61
 }
6bbc61
 
6bbc61
 /**