diff options
-rw-r--r-- | camel/ChangeLog | 15 | ||||
-rw-r--r-- | camel/providers/imap4/camel-imap4-folder.c | 34 | ||||
-rw-r--r-- | camel/providers/imap4/camel-imap4-summary.c | 69 | ||||
-rw-r--r-- | camel/providers/imap4/camel-imap4-summary.h | 2 |
4 files changed, 90 insertions, 30 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index a67f634255..361ade4e40 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,18 @@ +2004-06-11 Jeffrey Stedfast <fejj@ximian.com> + + * 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. + 2004-06-11 Not Zed <NotZed@Ximian.com> * providers/local/camel-maildir-store.c (get_folder_info): if we 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 { |