aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog15
-rw-r--r--camel/providers/imap4/camel-imap4-folder.c34
-rw-r--r--camel/providers/imap4/camel-imap4-summary.c69
-rw-r--r--camel/providers/imap4/camel-imap4-summary.h2
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 {