From 4d5a37e52ba0489e430a49230eefd23b5494b86e Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Thu, 17 Jun 2004 16:37:41 +0000 Subject: Fixed to work properly. It was getting ranges wrong before sometimes which 2004-06-17 Jeffrey Stedfast * providers/imap4/camel-imap4-folder.c (imap4_get_uid_set): Fixed to work properly. It was getting ranges wrong before sometimes which was making me lose mail! Ugh. svn path=/trunk/; revision=26393 --- camel/ChangeLog | 4 + camel/providers/imap4/camel-imap4-folder.c | 206 ++++++++++++++++++++--------- 2 files changed, 148 insertions(+), 62 deletions(-) (limited to 'camel') diff --git a/camel/ChangeLog b/camel/ChangeLog index 6698923e6a..d49962db6c 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,5 +1,9 @@ 2004-06-17 Jeffrey Stedfast + * providers/imap4/camel-imap4-folder.c (imap4_get_uid_set): Fixed + to work properly. It was getting ranges wrong before sometimes + which was making me lose mail! Ugh. + Thanks to Christian Kellner for pointing out these bugs (and submitting the original patch for service_setv) diff --git a/camel/providers/imap4/camel-imap4-folder.c b/camel/providers/imap4/camel-imap4-folder.c index fb47d3f994..c5b94af89d 100644 --- a/camel/providers/imap4/camel-imap4-folder.c +++ b/camel/providers/imap4/camel-imap4-folder.c @@ -313,82 +313,164 @@ static struct { { "\\Seen", CAMEL_MESSAGE_SEEN }, }; -static int -imap4_get_uid_set (CamelIMAP4Engine *engine, CamelFolderSummary *summary, GPtrArray *infos, int cur, size_t linelen, char **set) +struct _uidset_range { + struct _uidset_range *next; + guint32 first, last; + uint8_t buflen; + char buf[24]; +}; + +struct _uidset { + CamelFolderSummary *summary; + struct _uidset_range *ranges; + struct _uidset_range *tail; + size_t maxlen, setlen; +}; + +static void +uidset_range_free (struct _uidset_range *range) { - CamelMessageInfo *info; - guint32 this, prev, next; - gboolean range = FALSE; - GString *uidset; - int scount, i; - size_t len; - - if (engine->maxlentype == CAMEL_IMAP4_ENGINE_MAXLEN_LINE) - len = engine->maxlen - linelen; - else - len = engine->maxlen; - - i = cur + 1; - info = (CamelMessageInfo *) infos->pdata[cur]; - fflush (stdout); - uidset = g_string_new (""); - g_string_append (uidset, camel_message_info_uid (info)); - - if (!(i < infos->len)) - goto done; + struct _uidset_range *next; - scount = summary->messages->len; - - /* init this info */ - for (this = 0; this < scount; this++) { - if (info == summary->messages->pdata[this]) - break; + while (range != NULL) { + next = range->next; + g_free (range); + range = next; } - - /* init next info */ - info = (CamelMessageInfo *) infos->pdata[i]; - for (next = this; next < scount; next++) { - if (info == summary->messages->pdata[next]) +} + +static void +uidset_init (struct _uidset *uidset, CamelFolderSummary *summary, size_t maxlen) +{ + uidset->ranges = g_new (struct _uidset_range, 1); + uidset->ranges->next = NULL; + uidset->ranges->buflen = 0; + uidset->ranges->first = 0; + uidset->ranges->last = 0; + + uidset->tail = uidset->ranges; + uidset->summary = summary; + uidset->maxlen = maxlen; + uidset->setlen = 0; +} + +/* returns: -1 on full-and-not-added, 0 on added-and-not-full or 1 on added-and-full */ +static int +uidset_add (struct _uidset *uidset, CamelMessageInfo *info) +{ + GPtrArray *messages = uidset->summary->messages; + struct _uidset_range *node, *tail = uidset->tail; + const char *iuid = camel_message_info_uid (info); + size_t uidlen, len; + guint32 index; + char *colon; + + for (index = tail->last + 1; index < messages->len; index++) { + if (info == messages->pdata[index]) break; } - for ( ; i < infos->len && uidset->len < len; i++) { - prev = this; - this = next; - - if (i + 1 < infos->len) { - info = infos->pdata[i + 1]; - for (next = this; next < scount; next++) { - if (info == summary->messages->pdata[next]) - break; - } - } else { - next = scount; - } - - if (this == (next - 1) || this == (prev + 1)) { - range = TRUE; + g_assert (index < messages->len); + + uidlen = strlen (iuid); + + if (tail->buflen == 0) { + /* first add */ + tail->first = tail->last = index; + strcpy (tail->buf, iuid); + uidset->setlen = uidlen; + tail->buflen = uidlen; + } else if (index == (tail->last + 1)) { + /* add to last range */ + if (tail->last == tail->first) { + /* make sure we've got enough room to add this one... */ + if ((uidset->setlen + uidlen + 1) > uidset->maxlen) + return -1; + + tail->buf[tail->buflen++] = ':'; + uidset->setlen++; } else { - if (range) { - info = (CamelMessageInfo *) summary->messages->pdata[prev]; - g_string_append_printf (uidset, ":%s", camel_message_info_uid (info)); - range = FALSE; - } + colon = strchr (tail->buf, ':') + 1; - info = infos->pdata[i]; - g_string_append_printf (uidset, ",%s", camel_message_info_uid (info)); + len = strlen (colon); + uidset->setlen -= len; + tail->buflen -= len; } + + strcpy (tail->buf + tail->buflen, iuid); + uidset->setlen += uidlen; + tail->buflen += uidlen; + + tail->last = index; + } else if ((uidset->setlen + uidlen + 1) < uidset->maxlen) { + /* the beginning of a new range */ + tail->next = node = g_new (struct _uidset_range, 1); + node->first = node->last = index; + strcpy (node->buf, iuid); + uidset->setlen += uidlen + 1; + node->buflen = uidlen; + uidset->tail = node; + node->next = NULL; + } else { + /* can't add this one... */ + return -1; + } + + fprintf (stderr, "added uid %s to uidset (summary index = %u)\n", iuid, index); + + if (uidset->setlen < uidset->maxlen) + return 0; + + return 1; +} + +static char * +uidset_to_string (struct _uidset *uidset) +{ + struct _uidset_range *range; + GString *string; + char *str; + + string = g_string_new (""); + + range = uidset->ranges; + while (range != NULL) { + g_string_append (string, range->buf); + range = range->next; + if (range) + g_string_append_c (string, ','); } - if (range) { - info = (CamelMessageInfo *) summary->messages->pdata[this]; - g_string_append_printf (uidset, ":%s", camel_message_info_uid (info)); + str = string->str; + g_string_free (string, FALSE); + + return str; +} + +static int +imap4_get_uid_set (CamelIMAP4Engine *engine, CamelFolderSummary *summary, GPtrArray *infos, int cur, size_t linelen, char **set) +{ + struct _uidset uidset; + size_t maxlen; + int rv = 0; + int i; + + if (engine->maxlentype == CAMEL_IMAP4_ENGINE_MAXLEN_LINE) + maxlen = engine->maxlen - linelen; + else + maxlen = engine->maxlen; + + uidset_init (&uidset, summary, maxlen); + + for (i = cur; i < infos->len && rv != 1; i++) { + if ((rv = uidset_add (&uidset, infos->pdata[i])) == -1) + break; } - done: + if (i > cur) + *set = uidset_to_string (&uidset); - *set = uidset->str; - g_string_free (uidset, FALSE); + uidset_range_free (uidset.ranges); return (i - cur); } -- cgit v1.2.3