summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNot Zed <NotZed@Ximian.com>2002-06-03 18:04:30 +0000
committerJeffrey Stedfast <fejj@src.gnome.org>2002-06-03 18:04:30 +0000
commited7f96c51e369c5e8b541ecef3cbb9a5b7d1b98a (patch)
treec6f78819e802607dc47e1b5f4c3aca95f33924fe
parente42b8a19342e6a164a900319125bdcccdb33d5f3 (diff)
downloadevolution-data-server-ed7f96c51e369c5e8b541ecef3cbb9a5b7d1b98a.tar.gz
Check that any unmatched operation is not concerning any vfolder. OtherEVOLUTION_1_0_6
2002-06-03 Not Zed <NotZed@Ximian.com> * camel-vee-folder.c (camel_vee_folder_add_folder): (folder_changed_change): (folder_changed_remove_uid): (folder_changed_add_uid): (vee_folder_build_folder): Check that any unmatched operation is not concerning any vfolder. Other vfolders should never be part of any unmatched handling. For #24615, and others probably. 2002-05-13 Jeffrey Stedfast <fejj@ximian.com> * providers/imap/camel-imap-search.c (imap_body_contains): Use the new imap_uid_array_to_set() API. Pass in -1 as the maxuid value since fixing this right would be more than just a simple backport and so may run into problems. Backported some fixes from HEAD branch to fix sending long commands. * providers/imap/camel-imap-folder.c (imap_expunge_uids_online): Updated to use the new imap_uid_array_to_set() interface. (imap_expunge_uids_resyncing): Same. (do_copy): Here too. (imap_update_summary): Added a FIXME comment to rewrite allowing for a uid-set limitation. (get_matching): Copy some of the logic over from imap_uid_adday_to_set() to limit the length of the uid-set string. (imap_sync_online): Added a comment to explain what is going on with get_matching() since the behavior has changed slightly. * providers/imap/camel-imap-utils.c (imap_uid_array_to_set): Modify the interface so that we can limit the size of the uid set string returned.
-rw-r--r--camel/ChangeLog34
-rw-r--r--camel/camel-vee-folder.c25
-rw-r--r--camel/providers/imap/camel-imap-folder.c303
-rw-r--r--camel/providers/imap/camel-imap-search.c4
-rw-r--r--camel/providers/imap/camel-imap-utils.c34
-rw-r--r--camel/providers/imap/camel-imap-utils.h2
6 files changed, 254 insertions, 148 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 74d5c6126..4a799f6bc 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,37 @@
+2002-06-03 Not Zed <NotZed@Ximian.com>
+
+ * camel-vee-folder.c (camel_vee_folder_add_folder):
+ (folder_changed_change):
+ (folder_changed_remove_uid):
+ (folder_changed_add_uid):
+ (vee_folder_build_folder): Check that any unmatched operation is
+ not concerning any vfolder. Other vfolders should never be part
+ of any unmatched handling. For #24615, and others probably.
+
+2002-05-13 Jeffrey Stedfast <fejj@ximian.com>
+
+ * providers/imap/camel-imap-search.c (imap_body_contains): Use the
+ new imap_uid_array_to_set() API. Pass in -1 as the maxuid value
+ since fixing this right would be more than just a simple backport
+ and so may run into problems.
+
+ Backported some fixes from HEAD branch to fix sending long commands.
+
+ * providers/imap/camel-imap-folder.c (imap_expunge_uids_online):
+ Updated to use the new imap_uid_array_to_set() interface.
+ (imap_expunge_uids_resyncing): Same.
+ (do_copy): Here too.
+ (imap_update_summary): Added a FIXME comment to rewrite allowing
+ for a uid-set limitation.
+ (get_matching): Copy some of the logic over from
+ imap_uid_adday_to_set() to limit the length of the uid-set string.
+ (imap_sync_online): Added a comment to explain what is going on
+ with get_matching() since the behavior has changed slightly.
+
+ * providers/imap/camel-imap-utils.c (imap_uid_array_to_set):
+ Modify the interface so that we can limit the size of the uid set
+ string returned.
+
2002-05-13 Not Zed <NotZed@Ximian.com>
* camel-folder-thread.c
diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c
index c7f7be98f..bf6a5ceeb 100644
--- a/camel/camel-vee-folder.c
+++ b/camel/camel-vee-folder.c
@@ -346,7 +346,8 @@ camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub)
camel_object_ref((CamelObject *)sub);
p->folders = g_list_append(p->folders, sub);
}
- if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) {
+ if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0
+ && !CAMEL_IS_VEE_FOLDER(sub)) {
camel_object_ref((CamelObject *)sub);
up->folders = g_list_append(up->folders, sub);
}
@@ -959,10 +960,12 @@ folder_added_uid(char *uidin, void *value, struct _update_data *u)
if ( (mi = vee_folder_add_uid(u->vf, u->source, uidin, u->hash)) ) {
camel_folder_change_info_add_uid(u->vf->changes, camel_message_info_uid(mi));
- if (g_hash_table_lookup_extended(unmatched_uids, camel_message_info_uid(mi), (void **)&oldkey, (void **)&n)) {
- g_hash_table_insert(unmatched_uids, oldkey, (void *)(n+1));
- } else {
- g_hash_table_insert(unmatched_uids, g_strdup(camel_message_info_uid(mi)), (void *)1);
+ if (!CAMEL_IS_VEE_FOLDER(u->source)) {
+ if (g_hash_table_lookup_extended(unmatched_uids, camel_message_info_uid(mi), (void **)&oldkey, (void **)&n)) {
+ g_hash_table_insert(unmatched_uids, oldkey, (void *)(n+1));
+ } else {
+ g_hash_table_insert(unmatched_uids, g_strdup(camel_message_info_uid(mi)), (void *)1);
+ }
}
}
}
@@ -1024,7 +1027,8 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException
camel_folder_summary_remove_index(folder->summary, i);
camel_folder_change_info_remove_uid(vf->changes, camel_message_info_uid(mi));
i--;
- if (g_hash_table_lookup_extended(unmatched_uids, uid, (void **)&oldkey, (void **)&n)) {
+ if (!CAMEL_IS_VEE_FOLDER(source)
+ && g_hash_table_lookup_extended(unmatched_uids, uid, (void **)&oldkey, (void **)&n)) {
if (n == 1) {
g_hash_table_remove(unmatched_uids, oldkey);
g_free(oldkey);
@@ -1066,7 +1070,8 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException
}
/* now allhash contains all potentially new uid's for the unmatched folder, process */
- g_hash_table_foreach(allhash, (GHFunc)unmatched_check_uid, &u);
+ if (!CAMEL_IS_VEE_FOLDER(source))
+ g_hash_table_foreach(allhash, (GHFunc)unmatched_check_uid, &u);
/* copy any changes so we can raise them outside the lock */
if (camel_folder_change_info_changed(folder_unmatched->changes)) {
@@ -1127,7 +1132,7 @@ folder_changed_add_uid(CamelFolder *sub, const char *uid, const char hash[8], Ca
vuid = camel_message_info_uid(vinfo);
camel_folder_change_info_add_uid(vf->changes, vuid);
- if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) {
+ if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub)) {
if (g_hash_table_lookup_extended(unmatched_uids, vuid, (void **)&oldkey, (void **)&n)) {
g_hash_table_insert(unmatched_uids, oldkey, (void *)(n+1));
} else {
@@ -1161,7 +1166,7 @@ folder_changed_remove_uid(CamelFolder *sub, const char *uid, const char hash[8],
camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo);
}
- if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) {
+ if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub)) {
if (keep) {
if (g_hash_table_lookup_extended(unmatched_uids, vuid, (void **)&oldkey, (void **)&n)) {
if (n == 1) {
@@ -1366,7 +1371,7 @@ folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg)
memcpy(vuid, hash, 8);
strcpy(vuid+8, uid);
- if (g_hash_table_lookup(unmatched_uids, vuid) == NULL) {
+ if (!CAMEL_IS_VEE_FOLDER(sub) && g_hash_table_lookup(unmatched_uids, vuid) == NULL) {
dd(printf(" adding uid '%s' to Unmatched [newly unmatched]\n", (char *)uid));
vinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info((CamelFolder *)folder_unmatched, vuid);
if (vinfo == NULL) {
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index 45dad9f6b..17135ab26 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -64,6 +64,10 @@
#include "camel-stream.h"
#include "string-utils.h"
+
+/* set to -1 for infinite size */
+#define UID_SET_LIMIT (4096)
+
#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o)))
static CamelDiscoFolderClass *disco_folder_class = NULL;
@@ -729,28 +733,32 @@ imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *
{
CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
CamelImapResponse *response;
+ int uid = 0;
char *set;
- set = imap_uid_array_to_set (folder->summary, uids);
- CAMEL_IMAP_STORE_LOCK (store, command_lock);
- response = camel_imap_command (store, folder, ex,
- "UID STORE %s +FLAGS.SILENT \\Deleted",
- set);
- if (response)
- camel_imap_response_free (store, response);
- if (camel_exception_is_set (ex)) {
- CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
- g_free (set);
- return;
+ while (uid < uids->len) {
+ set = imap_uid_array_to_set (folder->summary, uids, uid, UID_SET_LIMIT, &uid);
+ response = camel_imap_command (store, folder, ex,
+ "UID STORE %s +FLAGS.SILENT \\Deleted",
+ set);
+ if (response)
+ camel_imap_response_free (store, response);
+ if (camel_exception_is_set (ex)) {
+ CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
+ g_free (set);
+ return;
+ }
+
+ if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) {
+ response = camel_imap_command (store, folder, ex,
+ "UID EXPUNGE %s", set);
+ } else
+ response = camel_imap_command (store, folder, ex, "EXPUNGE");
+
+ if (response)
+ camel_imap_response_free (store, response);
}
- if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) {
- response = camel_imap_command (store, folder, ex,
- "UID EXPUNGE %s", set);
- } else
- response = camel_imap_command (store, folder, ex, "EXPUNGE");
- if (response)
- camel_imap_response_free (store, response);
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
}
@@ -774,125 +782,152 @@ static void
imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelException *ex)
{
CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
+ GPtrArray *keep_uids, *mark_uids;
CamelImapResponse *response;
- char *result, *keep_uidset, *mark_uidset;
-
+ char *result;
+
if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) {
imap_expunge_uids_online (folder, uids, ex);
return;
}
-
+
/* If we don't have UID EXPUNGE we need to avoid expunging any
* of the wrong messages. So we search for deleted messages,
* and any that aren't in our to-expunge list get temporarily
* marked un-deleted.
*/
-
+
CAMEL_IMAP_STORE_LOCK (store, command_lock);
response = camel_imap_command (store, folder, ex, "UID SEARCH DELETED");
if (!response) {
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
return;
}
+
result = camel_imap_response_extract (store, response, "SEARCH", ex);
if (!result) {
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
return;
}
-
- keep_uidset = mark_uidset = NULL;
+
if (result[8] == ' ') {
- GPtrArray *keep_uids, *mark_uids;
char *uid, *lasts = NULL;
unsigned long euid, kuid;
int ei, ki;
-
+
keep_uids = g_ptr_array_new ();
mark_uids = g_ptr_array_new ();
-
+
/* Parse SEARCH response */
for (uid = strtok_r (result + 9, " ", &lasts); uid; uid = strtok_r (NULL, " ", &lasts))
g_ptr_array_add (keep_uids, uid);
qsort (keep_uids->pdata, keep_uids->len,
sizeof (void *), uid_compar);
-
+
/* Fill in "mark_uids", empty out "keep_uids" as needed */
for (ei = ki = 0; ei < uids->len; ei++) {
euid = strtoul (uids->pdata[ei], NULL, 10);
-
+
for (kuid = 0; ki < keep_uids->len; ki++) {
kuid = strtoul (keep_uids->pdata[ki], NULL, 10);
-
+
if (kuid >= euid)
break;
}
-
+
if (euid == kuid)
g_ptr_array_remove_index (keep_uids, ki);
else
g_ptr_array_add (mark_uids, uids->pdata[ei]);
}
-
- if (keep_uids->len)
- keep_uidset = imap_uid_array_to_set (folder->summary, keep_uids);
- g_ptr_array_free (keep_uids, TRUE);
-
- if (mark_uids->len)
- mark_uidset = imap_uid_array_to_set (folder->summary, mark_uids);
- g_ptr_array_free (mark_uids, TRUE);
} else {
/* Empty SEARCH result, meaning nothing is marked deleted
* on server.
*/
- mark_uidset = imap_uid_array_to_set (folder->summary, uids);
+
+ keep_uids = NULL;
+ mark_uids = NULL;
}
+
g_free (result);
-
+
/* Unmark messages to be kept */
- if (keep_uidset) {
- response = camel_imap_command (store, folder, ex,
- "UID STORE %s -FLAGS.SILENT \\Deleted",
- keep_uidset);
- if (!response) {
- g_free (keep_uidset);
- g_free (mark_uidset);
- CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
- return;
+ if (keep_uids) {
+ char *uidset;
+ int uid = 0;
+
+ while (uid < keep_uids->len) {
+ uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid);
+
+ response = camel_imap_command (store, folder, ex,
+ "UID STORE %s -FLAGS.SILENT \\Deleted",
+ uidset);
+
+ g_free (uidset);
+
+ if (!response) {
+ g_ptr_array_free (keep_uids, TRUE);
+ g_ptr_array_free (mark_uids, TRUE);
+ CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
+ return;
+ }
+ camel_imap_response_free (store, response);
}
- camel_imap_response_free (store, response);
}
-
+
/* Mark any messages that still need to be marked */
- if (mark_uidset) {
- response = camel_imap_command (store, folder, ex,
- "UID STORE %s +FLAGS.SILENT \\Deleted",
- mark_uidset);
- g_free (mark_uidset);
- if (!response) {
- g_free (keep_uidset);
- CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
- return;
+ if (mark_uids) {
+ char *uidset;
+ int uid = 0;
+
+ while (uid < mark_uids->len) {
+ uidset = imap_uid_array_to_set (folder->summary, mark_uids, uid, UID_SET_LIMIT, &uid);
+
+ response = camel_imap_command (store, folder, ex,
+ "UID STORE %s +FLAGS.SILENT \\Deleted",
+ uidset);
+
+ g_free (uidset);
+
+ if (!response) {
+ g_ptr_array_free (keep_uids, TRUE);
+ g_ptr_array_free (mark_uids, TRUE);
+ CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
+ return;
+ }
+ camel_imap_response_free (store, response);
}
- camel_imap_response_free (store, response);
+
+ g_ptr_array_free (mark_uids, TRUE);
}
-
+
/* Do the actual expunging */
response = camel_imap_command (store, folder, ex, "EXPUNGE");
if (response)
camel_imap_response_free (store, response);
-
+
/* And fix the remaining messages if we mangled them */
- if (keep_uidset) {
- /* Don't pass ex if it's already been set */
- response = camel_imap_command (store, folder,
- camel_exception_is_set (ex) ? NULL : ex,
- "UID STORE %s +FLAGS.SILENT \\Deleted",
- keep_uidset);
- g_free (keep_uidset);
- if (response)
- camel_imap_response_free (store, response);
+ if (keep_uids) {
+ char *uidset;
+ int uid = 0;
+
+ while (uid < keep_uids->len) {
+ uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid);
+
+ /* Don't pass ex if it's already been set */
+ response = camel_imap_command (store, folder,
+ camel_exception_is_set (ex) ? NULL : ex,
+ "UID STORE %s +FLAGS.SILENT \\Deleted",
+ uidset);
+
+ g_free (uidset);
+ if (response)
+ camel_imap_response_free (store, response);
+ }
+
+ g_ptr_array_free (keep_uids, TRUE);
}
-
+
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
}
@@ -1186,16 +1221,22 @@ do_copy (CamelFolder *source, GPtrArray *uids,
{
CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store);
CamelImapResponse *response;
- char *set;
-
- set = imap_uid_array_to_set (source->summary, uids);
- response = camel_imap_command (store, source, ex, "UID COPY %s %F",
- set, destination->full_name);
- if (response && (store->capabilities & IMAP_CAPABILITY_UIDPLUS))
- handle_copyuid (response, source, destination);
-
- camel_imap_response_free (store, response);
- g_free (set);
+ char *uidset;
+ int uid = 0;
+
+ while (uid < uids->len && !camel_exception_is_set (ex)) {
+ uidset = imap_uid_array_to_set (source->summary, uids, uid, UID_SET_LIMIT, &uid);
+
+ response = camel_imap_command (store, source, ex, "UID COPY %s %F",
+ uidset, destination->full_name);
+
+ g_free (uidset);
+
+ if (response && (store->capabilities & IMAP_CAPABILITY_UIDPLUS))
+ handle_copyuid (response, source, destination);
+
+ camel_imap_response_free (store, response);
+ }
}
static void
@@ -1758,13 +1799,13 @@ imap_update_summary (CamelFolder *folder, int exists,
g_free (resp);
if (!data)
continue;
-
+
seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE"));
if (seq < first) {
g_datalist_clear (&data);
continue;
}
-
+
if (g_datalist_get_data (&data, "FLAGS"))
got += IMAP_PRETEND_SIZEOF_FLAGS;
if (g_datalist_get_data (&data, "RFC822.SIZE"))
@@ -1772,22 +1813,22 @@ imap_update_summary (CamelFolder *folder, int exists,
stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
if (stream) {
got += IMAP_PRETEND_SIZEOF_HEADERS;
-
+
/* Use the stream now so we don't tie up many
* many fds if we're fetching many many messages.
*/
add_message_from_data (folder, messages, first, data);
g_datalist_set_data (&data, "BODY_PART_STREAM", NULL);
}
-
+
camel_operation_progress (NULL, got * 100 / size);
g_ptr_array_add (fetch_data, data);
}
camel_operation_end (NULL);
-
+
if (type == CAMEL_IMAP_RESPONSE_ERROR)
goto lose;
-
+
/* Figure out which headers we still need to fetch. */
needheaders = g_ptr_array_new ();
size = got = 0;
@@ -1795,51 +1836,63 @@ imap_update_summary (CamelFolder *folder, int exists,
data = fetch_data->pdata[i];
if (g_datalist_get_data (&data, "BODY_PART_LEN"))
continue;
-
+
uid = g_datalist_get_data (&data, "UID");
if (uid) {
g_ptr_array_add (needheaders, uid);
size += IMAP_PRETEND_SIZEOF_HEADERS;
}
}
-
+
/* And fetch them */
if (needheaders->len) {
- char *set;
-
- /* FIXME: sort needheaders */
- set = imap_uid_array_to_set (folder->summary, needheaders);
- g_ptr_array_free (needheaders, TRUE);
- if (!camel_imap_command_start (store, folder, ex,
- "UID FETCH %s BODY.PEEK[%s]",
- set, header_spec)) {
- g_free (set);
- goto lose;
- }
- g_free (set);
-
+ char *uidset;
+ int uid = 0;
+
+ qsort (needheaders->pdata, needheaders->len,
+ sizeof (void *), uid_compar);
+
camel_operation_start (NULL, _("Fetching summary information for new messages"));
- while ((type = camel_imap_command_response (store, &resp, ex))
- == CAMEL_IMAP_RESPONSE_UNTAGGED) {
- data = parse_fetch_response (imap_folder, resp);
- g_free (resp);
- if (!data)
- continue;
-
- stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
- if (stream) {
- add_message_from_data (folder, messages, first, data);
- got += IMAP_PRETEND_SIZEOF_HEADERS;
- camel_operation_progress (NULL, got * 100 / size);
+
+ while (uid < needheaders->len) {
+ uidset = imap_uid_array_to_set (folder->summary, needheaders, uid, UID_SET_LIMIT, &uid);
+ if (!camel_imap_command_start (store, folder, ex,
+ "UID FETCH %s BODY.PEEK[%s]",
+ uidset, header_spec)) {
+ g_ptr_array_free (needheaders, TRUE);
+ camel_operation_end (NULL);
+ g_free (uidset);
+ goto lose;
+ }
+ g_free (uidset);
+
+ while ((type = camel_imap_command_response (store, &resp, ex))
+ == CAMEL_IMAP_RESPONSE_UNTAGGED) {
+ data = parse_fetch_response (imap_folder, resp);
+ g_free (resp);
+ if (!data)
+ continue;
+
+ stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
+ if (stream) {
+ add_message_from_data (folder, messages, first, data);
+ got += IMAP_PRETEND_SIZEOF_HEADERS;
+ camel_operation_progress (NULL, got * 100 / size);
+ }
+ g_datalist_clear (&data);
+ }
+
+ if (type == CAMEL_IMAP_RESPONSE_ERROR) {
+ g_ptr_array_free (needheaders, TRUE);
+ camel_operation_end (NULL);
+ goto lose;
}
- g_datalist_clear (&data);
}
+
+ g_ptr_array_free (needheaders, TRUE);
camel_operation_end (NULL);
-
- if (type == CAMEL_IMAP_RESPONSE_ERROR)
- goto lose;
}
-
+
/* Now finish up summary entries (fix UIDs, set flags and size) */
for (i = 0; i < fetch_data->len; i++) {
data = fetch_data->pdata[i];
@@ -1892,11 +1945,11 @@ imap_update_summary (CamelFolder *folder, int exists,
size = GPOINTER_TO_INT (g_datalist_get_data (&data, "RFC822.SIZE"));
if (size)
mi->size = size;
-
+
g_datalist_clear (&data);
}
g_ptr_array_free (fetch_data, TRUE);
-
+
/* And add the entries to the summary, etc. */
for (i = 0; i < messages->len; i++) {
mi = messages->pdata[i];
@@ -1906,7 +1959,7 @@ imap_update_summary (CamelFolder *folder, int exists,
}
camel_folder_summary_add (folder->summary, mi);
camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi));
-
+
if ((mi->flags & CAMEL_IMAP_MESSAGE_RECENT))
camel_folder_change_info_recent_uid(changes, camel_message_info_uid (mi));
}
diff --git a/camel/providers/imap/camel-imap-search.c b/camel/providers/imap/camel-imap-search.c
index 2adaaef24..e5e55ec93 100644
--- a/camel/providers/imap/camel-imap-search.c
+++ b/camel/providers/imap/camel-imap-search.c
@@ -129,13 +129,15 @@ imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv,
the real folder size, then use a
message-set to optimise it */
/* TODO: This peeks a bunch of 'private'ish data */
+ int lastuid;
+
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);
+ set = imap_uid_array_to_set(s->folder->summary, sorted, 0, -1, &lastuid);
response = camel_imap_command (store, s->folder, NULL,
"UID SEARCH UID %s BODY \"%s\"",
set, value);
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c
index d5466bf9a..7d2073142 100644
--- a/camel/providers/imap/camel-imap-utils.c
+++ b/camel/providers/imap/camel-imap-utils.c
@@ -648,44 +648,54 @@ get_summary_uid_numeric (CamelFolderSummary *summary, int index)
return uid;
}
+/* the max number of chars that an unsigned 32-bit int can be is 10 chars plus 1 for a possible : */
+#define UID_SET_FULL(setlen, maxlen) (maxlen > 0 ? setlen + 11 >= maxlen : FALSE)
+
/**
* imap_uid_array_to_set:
* @summary: summary for the folder the UIDs come from
* @uids: a (sorted) array of UIDs
+ * @uid: uid index to start at
+ * @maxlen: max length of the set string (or -1 for infinite)
+ * @lastuid: index offset of the last uid used
+ *
+ * Creates an IMAP "set" up to @maxlen bytes long, covering the listed
+ * UIDs starting at index @uid and not covering any UIDs that are in
+ * @summary but not in @uids. It doesn't actually require that all (or
+ * any) of the UIDs be in @summary.
*
- * Creates an IMAP "set" covering the listed UIDs and not covering
- * any UIDs that are in @summary but not in @uids. It doesn't
- * actually require that all (or any) of the UIDs be in @summary.
+ * After calling, @lastuid will be set the index of the first uid
+ * *not* included in the returned set string.
*
* Return value: the set, which the caller must free with g_free()
**/
char *
-imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids)
+imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids, int uid, ssize_t maxlen, int *lastuid)
{
- int ui, si, scount;
unsigned long last_uid, next_summary_uid, this_uid;
gboolean range = FALSE;
+ int si, scount;
GString *gset;
char *set;
- g_return_val_if_fail (uids->len > 0, NULL);
+ g_return_val_if_fail (uids->len > uid, NULL);
- gset = g_string_new (uids->pdata[0]);
- last_uid = strtoul (uids->pdata[0], NULL, 10);
+ gset = g_string_new (uids->pdata[uid]);
+ last_uid = strtoul (uids->pdata[uid], NULL, 10);
next_summary_uid = 0;
scount = camel_folder_summary_count (summary);
- for (ui = 1, si = 0; ui < uids->len; ui++) {
+ for (uid++, si = 0; uid < uids->len && !UID_SET_FULL (gset->len, maxlen); uid++) {
/* Find the next UID in the summary after the one we
* just wrote out.
*/
- for (; last_uid >= next_summary_uid && si < scount; si++)
+ for ( ; last_uid >= next_summary_uid && si < scount; si++)
next_summary_uid = get_summary_uid_numeric (summary, si);
if (last_uid >= next_summary_uid)
next_summary_uid = (unsigned long) -1;
/* Now get the next UID from @uids */
- this_uid = strtoul (uids->pdata[ui], NULL, 10);
+ this_uid = strtoul (uids->pdata[uid], NULL, 10);
if (this_uid == next_summary_uid || this_uid == last_uid + 1)
range = TRUE;
else {
@@ -702,6 +712,8 @@ imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids)
if (range)
g_string_sprintfa (gset, ":%lu", last_uid);
+ *lastuid = uid;
+
set = gset->str;
g_string_free (gset, FALSE);
diff --git a/camel/providers/imap/camel-imap-utils.h b/camel/providers/imap/camel-imap-utils.h
index 8f61fb99d..f64d56743 100644
--- a/camel/providers/imap/camel-imap-utils.h
+++ b/camel/providers/imap/camel-imap-utils.h
@@ -65,7 +65,7 @@ char *imap_quote_string (const char *str);
void imap_skip_list (char **str_p);
-char *imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids);
+char *imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids, int uid, ssize_t maxlen, int *lastuid);
GPtrArray *imap_uid_set_to_array (CamelFolderSummary *summary, const char *uids);
void imap_uid_array_free (GPtrArray *arr);