|
|
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 |
/**
|