aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers')
-rw-r--r--camel/providers/imap/camel-imap-command.c2
-rw-r--r--camel/providers/imap/camel-imap-folder.c46
-rw-r--r--camel/providers/imap/camel-imap-search.c45
-rw-r--r--camel/providers/local/camel-local-folder.c44
-rw-r--r--camel/providers/local/camel-spool-folder.c43
5 files changed, 175 insertions, 5 deletions
diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c
index 64095b320d..141ae19ae5 100644
--- a/camel/providers/imap/camel-imap-command.c
+++ b/camel/providers/imap/camel-imap-command.c
@@ -678,7 +678,7 @@ imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt,
len += arglen * 2;
start = p + 1;
break;
-
+
case '%':
start = p;
break;
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index b17ffb55cd..5fe517f4ef 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -97,6 +97,7 @@ static void imap_move_messages_to (CamelFolder *source, GPtrArray *uids,
/* searching */
static GPtrArray *imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex);
+static GPtrArray *imap_search_by_uids (CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex);
static void imap_search_free (CamelFolder *folder, GPtrArray *uids);
static void imap_thaw (CamelFolder *folder);
@@ -115,6 +116,7 @@ camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class)
camel_folder_class->get_message = imap_get_message;
camel_folder_class->move_messages_to = imap_move_messages_to;
camel_folder_class->search_by_expression = imap_search_by_expression;
+ camel_folder_class->search_by_uids = imap_search_by_uids;
camel_folder_class->search_free = imap_search_free;
camel_folder_class->thaw = imap_thaw;
@@ -1301,6 +1303,50 @@ imap_search_by_expression (CamelFolder *folder, const char *expression, CamelExc
return matches;
}
+static GPtrArray *
+imap_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex)
+{
+ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER(folder);
+ GPtrArray *summary, *matches;
+ int i;
+
+ if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (folder->parent_store), ex))
+ return NULL;
+
+ /* NOTE: could get away without the search lock by creating a new
+ search object each time */
+
+ summary = g_ptr_array_new();
+ for (i=0;i<uids->len;i++) {
+ CamelMessageInfo *info;
+
+ info = camel_folder_get_message_info(folder, uids->pdata[i]);
+ if (info)
+ g_ptr_array_add(summary, info);
+ }
+
+ if (summary->len == 0)
+ return summary;
+
+ CAMEL_IMAP_FOLDER_LOCK(folder, search_lock);
+
+ if (imap_folder->search == NULL)
+ imap_folder->search = camel_imap_search_new();
+
+ camel_folder_search_set_folder(imap_folder->search, folder);
+ camel_folder_search_set_summary(imap_folder->search, summary);
+
+ matches = camel_folder_search_execute_expression(imap_folder->search, expression, ex);
+
+ CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock);
+
+ for (i=0;i<summary->len;i++)
+ camel_folder_free_message_info(folder, summary->pdata[i]);
+ g_ptr_array_free(summary, TRUE);
+
+ return matches;
+}
+
static void
imap_search_free (CamelFolder *folder, GPtrArray *uids)
{
diff --git a/camel/providers/imap/camel-imap-search.c b/camel/providers/imap/camel-imap-search.c
index 3c96449963..0418a34617 100644
--- a/camel/providers/imap/camel-imap-search.c
+++ b/camel/providers/imap/camel-imap-search.c
@@ -34,6 +34,7 @@
#include "camel-imap-store.h"
#include "camel-imap-search.h"
#include "camel-imap-private.h"
+#include "camel-imap-utils.h"
static ESExpResult *
imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv,
@@ -67,6 +68,21 @@ camel_imap_search_get_type (void)
return camel_imap_search_type;
}
+static int
+cmp_uid(const void *ap, const void *bp)
+{
+ unsigned int a, b;
+
+ a = strtoul(((char **)ap)[0], NULL, 10);
+ b = strtoul(((char **)bp)[0], NULL, 10);
+ if (a<b)
+ return -1;
+ else if (a>b)
+ return 1;
+
+ return 0;
+}
+
static ESExpResult *
imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv,
CamelFolderSearch *s)
@@ -79,6 +95,9 @@ imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv,
ESExpResult *r;
CamelMessageInfo *info;
GHashTable *uid_hash = NULL;
+ char *set;
+ GPtrArray *sorted;
+ int i;
if (s->current) {
uid = camel_message_info_uid (s->current);
@@ -100,11 +119,29 @@ imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv,
g_ptr_array_add (r->value.ptrarray, (char *)camel_message_info_uid (info));
}
} else {
- /* FIXME: danw: what if we have multiple string args? */
+ /* If searching a (reasonably small) subset of
+ the real folder size, then use a
+ message-set to optimise it */
+ /* TODO: This peeks a bunch of 'private'ish data */
+ if (s->summary->len < camel_folder_get_message_count(s->folder)/2) {
+ sorted = g_ptr_array_new();
+ g_ptr_array_set_size(sorted, s->summary->len);
+ for (i=0;i<s->summary->len;i++)
+ sorted->pdata[i] = (void *)camel_message_info_uid((CamelMessageInfo *)s->summary->pdata[i]);
+ qsort(sorted->pdata, sorted->len, sizeof(sorted->pdata[0]), cmp_uid);
+ set = imap_uid_array_to_set(s->folder->summary, sorted);
+ response = camel_imap_command (store, s->folder, NULL,
+ "UID SEARCH UID %s BODY \"%s\"",
+ set, value);
+ g_free(set);
+ g_ptr_array_free(sorted, TRUE);
+ } else {
+ response = camel_imap_command (store, s->folder, NULL,
+ "UID SEARCH BODY \"%s\"",
+ value);
+ }
+
r->value.ptrarray = g_ptr_array_new ();
- response = camel_imap_command (store, s->folder, NULL,
- "UID SEARCH BODY \"%s\"",
- value);
}
}
diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c
index 43622eb23a..27b49a5c70 100644
--- a/camel/providers/local/camel-local-folder.c
+++ b/camel/providers/local/camel-local-folder.c
@@ -62,6 +62,7 @@ static void local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex
static void local_expunge(CamelFolder *folder, CamelException *ex);
static GPtrArray *local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex);
+static GPtrArray *local_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex);
static void local_search_free(CamelFolder *folder, GPtrArray * result);
static void local_finalize(CamelObject * object);
@@ -80,6 +81,7 @@ camel_local_folder_class_init(CamelLocalFolderClass * camel_local_folder_class)
camel_folder_class->expunge = local_expunge;
camel_folder_class->search_by_expression = local_search_by_expression;
+ camel_folder_class->search_by_uids = local_search_by_uids;
camel_folder_class->search_free = local_search_free;
camel_local_folder_class->lock = local_lock;
@@ -334,6 +336,48 @@ local_search_by_expression(CamelFolder *folder, const char *expression, CamelExc
return matches;
}
+static GPtrArray *
+local_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex)
+{
+ CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder);
+ GPtrArray *summary, *matches;
+ int i;
+
+ /* NOTE: could get away without the search lock by creating a new
+ search object each time */
+
+ summary = g_ptr_array_new();
+ for (i=0;i<uids->len;i++) {
+ CamelMessageInfo *info;
+
+ info = camel_folder_get_message_info(folder, uids->pdata[i]);
+ if (info)
+ g_ptr_array_add(summary, info);
+ }
+
+ if (summary->len == 0)
+ return summary;
+
+ CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock);
+
+ if (local_folder->search == NULL)
+ local_folder->search = camel_folder_search_new();
+
+ camel_folder_search_set_folder(local_folder->search, folder);
+ camel_folder_search_set_body_index(local_folder->search, local_folder->index);
+ camel_folder_search_set_summary(local_folder->search, summary);
+
+ matches = camel_folder_search_execute_expression(local_folder->search, expression, ex);
+
+ CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock);
+
+ for (i=0;i<summary->len;i++)
+ camel_folder_free_message_info(folder, summary->pdata[i]);
+ g_ptr_array_free(summary, TRUE);
+
+ return matches;
+}
+
static void
local_search_free(CamelFolder *folder, GPtrArray * result)
{
diff --git a/camel/providers/local/camel-spool-folder.c b/camel/providers/local/camel-spool-folder.c
index bc715e46bc..9e487dfa89 100644
--- a/camel/providers/local/camel-spool-folder.c
+++ b/camel/providers/local/camel-spool-folder.c
@@ -64,6 +64,7 @@ static void spool_sync(CamelFolder *folder, gboolean expunge, CamelException *ex
static void spool_expunge(CamelFolder *folder, CamelException *ex);
static GPtrArray *spool_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex);
+static GPtrArray *spool_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex);
static void spool_search_free(CamelFolder *folder, GPtrArray * result);
static void spool_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, CamelException *ex);
@@ -87,6 +88,7 @@ camel_spool_folder_class_init(CamelSpoolFolderClass * camel_spool_folder_class)
camel_folder_class->expunge = spool_expunge;
camel_folder_class->search_by_expression = spool_search_by_expression;
+ camel_folder_class->search_by_uids = spool_search_by_uids;
camel_folder_class->search_free = spool_search_free;
/* virtual method overload */
@@ -363,6 +365,47 @@ spool_search_by_expression(CamelFolder *folder, const char *expression, CamelExc
return matches;
}
+static GPtrArray *
+spool_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex)
+{
+ CamelSpoolFolder *spool_folder = CAMEL_SPOOL_FOLDER(folder);
+ GPtrArray *summary, *matches;
+ int i;
+
+ /* NOTE: could get away without the search lock by creating a new
+ search object each time */
+
+ summary = g_ptr_array_new();
+ for (i=0;i<uids->len;i++) {
+ CamelMessageInfo *info;
+
+ info = camel_folder_get_message_info(folder, uids->pdata[i]);
+ if (info)
+ g_ptr_array_add(summary, info);
+ }
+
+ if (summary->len == 0)
+ return summary;
+
+ CAMEL_SPOOL_FOLDER_LOCK(folder, search_lock);
+
+ if (spool_folder->search == NULL)
+ spool_folder->search = camel_folder_search_new();
+
+ camel_folder_search_set_folder(spool_folder->search, folder);
+ camel_folder_search_set_summary(spool_folder->search, summary);
+
+ matches = camel_folder_search_execute_expression(spool_folder->search, expression, ex);
+
+ CAMEL_SPOOL_FOLDER_UNLOCK(folder, search_lock);
+
+ for (i=0;i<summary->len;i++)
+ camel_folder_free_message_info(folder, summary->pdata[i]);
+ g_ptr_array_free(summary, TRUE);
+
+ return matches;
+}
+
static void
spool_search_free(CamelFolder *folder, GPtrArray * result)
{