From 9c5abb70276da514cb6941348405de2fc1d3176b Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Fri, 11 Jun 2004 15:00:12 +0000 Subject: Handle getting FLAGS even though we didn't request it (server can send us 2004-06-11 Jeffrey Stedfast * providers/imap4/camel-imap4-folder.c (untagged_fetch): Handle getting FLAGS even though we didn't request it (server can send us FLAGS info if another client changed them recently, for example). Also fixed to handle the fact that not every bit of info has to be in a single untagged FETCH response - it may come in several untagged responses. * providers/imap4/camel-imap4-summary.c (envelope_decode_address): Decode the email address name token. (envelope_decode_nstring): rfc2047 decode strings if requested. (decode_envelope): Request that the subject string be rfc2047 decoded. svn path=/trunk/; revision=26310 --- camel/providers/imap4/camel-imap4-folder.c | 34 ++++++++++---- camel/providers/imap4/camel-imap4-summary.c | 69 ++++++++++++++++++++--------- camel/providers/imap4/camel-imap4-summary.h | 2 +- 3 files changed, 75 insertions(+), 30 deletions(-) (limited to 'camel/providers') diff --git a/camel/providers/imap4/camel-imap4-folder.c b/camel/providers/imap4/camel-imap4-folder.c index 006b214488..8570964360 100644 --- a/camel/providers/imap4/camel-imap4-folder.c +++ b/camel/providers/imap4/camel-imap4-folder.c @@ -616,9 +616,13 @@ imap4_refresh_info (CamelFolder *folder, CamelException *ex) static int untagged_fetch (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) { + CamelFolderSummary *summary = ((CamelFolder *) engine->folder)->summary; CamelStream *fstream, *stream = ic->user_data; + CamelFolderChangeInfo *changes; + CamelIMAP4MessageInfo *iinfo; + CamelMessageInfo *info; CamelMimeFilter *crlf; - int left = 2; + guint32 flags; if (camel_imap4_engine_next_token (engine, token, ex) == -1) return -1; @@ -633,6 +637,9 @@ untagged_fetch (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, if (camel_imap4_engine_next_token (engine, token, ex) == -1) goto exception; + if (token->token == ')' || token->token == '\n') + break; + if (token->token != CAMEL_IMAP4_TOKEN_ATOM) goto unexpected; @@ -657,24 +664,35 @@ untagged_fetch (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_stream_write_to_stream ((CamelStream *) engine->istream, fstream); camel_stream_flush (fstream); camel_object_unref (fstream); - - left--; } else if (!strcmp (token->v.atom, "UID")) { if (camel_imap4_engine_next_token (engine, token, ex) == -1) goto exception; if (token->token != CAMEL_IMAP4_TOKEN_NUMBER || token->v.number == 0) goto unexpected; + } else if (!strcmp (token->v.atom, "FLAGS")) { + /* even though we didn't request this bit of information, it might be + * given to us if another client recently changed the flags... */ + if (camel_imap4_parse_flags_list (engine, &flags, ex) == -1) + goto exception; - left--; + if ((info = camel_folder_summary_index (summary, index - 1))) { + iinfo = (CamelIMAP4MessageInfo *) info; + info->flags = camel_imap4_merge_flags (iinfo->server_flags, info->flags, flags); + iinfo->server_flags = flags; + + changes = camel_folder_change_info_new (); + camel_folder_change_info_change_uid (changes, camel_message_info_uid (info)); + camel_object_trigger_event (engine->folder, "folder_changed", changes); + camel_folder_change_info_free (changes); + + camel_folder_summary_info_free (summary, info); + } } else { /* wtf? */ fprintf (stderr, "huh? %s?...\n", token->v.atom); } - } while (left); - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; + } while (1); if (token->token != ')') { fprintf (stderr, "expected ')' to close untagged FETCH response\n"); diff --git a/camel/providers/imap4/camel-imap4-summary.c b/camel/providers/imap4/camel-imap4-summary.c index fa7cd7778a..f5fec4d05e 100644 --- a/camel/providers/imap4/camel-imap4-summary.c +++ b/camel/providers/imap4/camel-imap4-summary.c @@ -105,6 +105,10 @@ camel_imap4_summary_init (CamelIMAP4Summary *summary, CamelIMAP4SummaryClass *kl CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN; folder_summary->message_info_size = sizeof (CamelIMAP4MessageInfo); + + summary->update_flags = TRUE; + summary->exists_changed = FALSE; + summary->uidvalidity_changed = FALSE; } static void @@ -156,8 +160,10 @@ imap4_header_save (CamelFolderSummary *summary, FILE *fout) static int envelope_decode_address (CamelIMAP4Engine *engine, GString *addrs, CamelException *ex) { + char *addr, *name = NULL, *user = NULL; + struct _camel_header_address *cia; camel_imap4_token_t token; - gboolean had_name = FALSE; + const char *domain = NULL; int part = 0; if (camel_imap4_engine_next_token (engine, &token, ex) == -1) @@ -184,25 +190,39 @@ envelope_decode_address (CamelIMAP4Engine *engine, GString *addrs, CamelExceptio case CAMEL_IMAP4_TOKEN_QSTRING: switch (part) { case 0: - g_string_append_printf (addrs, "\"%s\" <", token.v.qstring); - had_name = TRUE; + name = camel_header_decode_string (token.v.qstring, NULL); break; case 2: - g_string_append (addrs, token.v.qstring); + user = g_strdup (token.v.qstring); break; case 3: - g_string_append_printf (addrs, "@%s%s", token.v.qstring, had_name ? ">" : ""); + domain = token.v.qstring; break; } break; default: camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); + g_free (name); + g_free (user); return -1; } part++; } while (part < 4); + addr = g_strdup_printf ("%s@%s", user, domain); + g_free (user); + + cia = camel_header_address_new_name (name, addr); + g_free (name); + g_free (addr); + + addr = camel_header_address_list_format (cia); + camel_header_address_unref (cia); + + g_string_append (addrs, addr); + g_free (addr); + if (camel_imap4_engine_next_token (engine, &token, ex) == -1) return -1; @@ -290,7 +310,7 @@ envelope_decode_date (CamelIMAP4Engine *engine, time_t *date, CamelException *ex } static int -envelope_decode_nstring (CamelIMAP4Engine *engine, char **nstring, CamelException *ex) +envelope_decode_nstring (CamelIMAP4Engine *engine, char **nstring, gboolean rfc2047, CamelException *ex) { camel_imap4_token_t token; @@ -302,10 +322,16 @@ envelope_decode_nstring (CamelIMAP4Engine *engine, char **nstring, CamelExceptio *nstring = NULL; break; case CAMEL_IMAP4_TOKEN_ATOM: - *nstring = g_strdup (token.v.atom); + if (rfc2047) + *nstring = camel_header_decode_string (token.v.atom, NULL); + else + *nstring = g_strdup (token.v.atom); break; case CAMEL_IMAP4_TOKEN_QSTRING: - *nstring = g_strdup (token.v.qstring); + if (rfc2047) + *nstring = camel_header_decode_string (token.v.qstring, NULL); + else + *nstring = g_strdup (token.v.qstring); break; default: camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); @@ -365,7 +391,7 @@ decode_envelope (CamelIMAP4Engine *engine, CamelMessageInfo *info, camel_imap4_t goto exception; /* subject */ - if (envelope_decode_nstring (engine, &nstring, ex) == -1) + if (envelope_decode_nstring (engine, &nstring, TRUE, ex) == -1) goto exception; camel_message_info_set_subject (info, nstring); @@ -400,7 +426,7 @@ decode_envelope (CamelIMAP4Engine *engine, CamelMessageInfo *info, camel_imap4_t g_free (nstring); /* in-reply-to */ - if (envelope_decode_nstring (engine, &nstring, ex) == -1) + if (envelope_decode_nstring (engine, &nstring, FALSE, ex) == -1) goto exception; if (nstring != NULL) { @@ -409,7 +435,7 @@ decode_envelope (CamelIMAP4Engine *engine, CamelMessageInfo *info, camel_imap4_t } /* message-id */ - if (envelope_decode_nstring (engine, &nstring, ex) == -1) + if (envelope_decode_nstring (engine, &nstring, FALSE, ex) == -1) goto exception; if (nstring != NULL) { @@ -1062,18 +1088,20 @@ camel_imap4_summary_expunge (CamelFolderSummary *summary, int seqid) g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - if (!(info = camel_folder_summary_index (summary, seqid - 1))) + seqid--; + if (!(info = camel_folder_summary_index (summary, seqid))) return; - imap4_summary->expunged_changed = TRUE; + imap4_summary->exists--; changes = camel_folder_change_info_new (); camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); - camel_object_trigger_event (imap4_summary->folder, "folder_changed", changes); - camel_folder_change_info_free (changes); camel_folder_summary_info_free (summary, info); camel_folder_summary_remove_index (summary, seqid); + + camel_object_trigger_event (imap4_summary->folder, "folder_changed", changes); + camel_folder_change_info_free (changes); } @@ -1104,14 +1132,12 @@ camel_imap4_summary_flush_updates (CamelFolderSummary *summary, CamelException * engine = ((CamelIMAP4Store *) imap4_summary->folder->parent_store)->engine; - if (imap4_summary->expunged_changed && imap4_summary->exists_changed) { - if (imap4_summary->exists == camel_folder_summary_count (summary)) - imap4_summary->exists_changed = FALSE; - } - if (imap4_summary->uidvalidity_changed) { first = 1; - } else if (imap4_summary->exists_changed && imap4_summary->exists > 0) { + } else if (imap4_summary->update_flags || imap4_summary->exists_changed) { + /* this both updates flags and removes messages which + * have since been expunged from the server by another + * client */ scount = camel_folder_summary_count (summary); ic = imap4_summary_fetch_flags (summary, 1, scount); @@ -1151,6 +1177,7 @@ camel_imap4_summary_flush_updates (CamelFolderSummary *summary, CamelException * g_ptr_array_sort (summary->messages, (GCompareFunc) info_uid_sort); } + imap4_summary->update_flags = FALSE; imap4_summary->exists_changed = FALSE; imap4_summary->uidvalidity_changed = FALSE; diff --git a/camel/providers/imap4/camel-imap4-summary.h b/camel/providers/imap4/camel-imap4-summary.h index 9546a7923d..3bad898a6a 100644 --- a/camel/providers/imap4/camel-imap4-summary.h +++ b/camel/providers/imap4/camel-imap4-summary.h @@ -60,8 +60,8 @@ struct _CamelIMAP4Summary { guint32 uidvalidity; guint uidvalidity_changed:1; - guint expunged_changed; guint exists_changed:1; + guint update_flags:1; }; struct _CamelIMAP4SummaryClass { -- cgit v1.2.3