diff options
-rw-r--r-- | camel/ChangeLog | 34 | ||||
-rw-r--r-- | camel/camel-vee-folder.c | 25 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-folder.c | 303 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-search.c | 4 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-utils.c | 34 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-utils.h | 2 |
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); |