diff options
-rw-r--r-- | camel/ChangeLog | 10 | ||||
-rw-r--r-- | camel/providers/pop3/camel-pop3-folder.c | 187 |
2 files changed, 129 insertions, 68 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index fd46fc93c1..219209bd82 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,5 +1,15 @@ 2001-08-06 Jeffrey Stedfast <fejj@ximian.com> + * providers/pop3/camel-pop3-folder.c (pop3_get_message_stream): + New internal function to get a message stream by message sequence + id (so that we can share code between pop3_get_message and + pop3_generate_uids). + (pop3_get_message): Use pop3_get_message_stream. + (pop3_generate_uids): New function to generate UIDs based on the + message - this fixes bug #1256. + (pop3_refresh_info): If the server doesn't support UIDL, call + pop3_generate_uids to get our list of UIDs. + * providers/imap/camel-imap-store.c (get_folder_info_online): Don't strstr for noselect=yes, that's just plain broken. diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c index 0032077fd6..2648a48a5b 100644 --- a/camel/providers/pop3/camel-pop3-folder.c +++ b/camel/providers/pop3/camel-pop3-folder.c @@ -35,6 +35,8 @@ #include "camel-mime-message.h" #include "camel-operation.h" +#include <e-util/md5-utils.h> + #include <stdlib.h> #include <string.h> @@ -49,6 +51,8 @@ static void pop3_sync (CamelFolder *folder, gboolean expunge, static gint pop3_get_message_count (CamelFolder *folder); static GPtrArray *pop3_get_uids (CamelFolder *folder); +static CamelStreamMem *pop3_get_message_stream (CamelFolder *folder, int id, + CamelException *ex); static CamelMimeMessage *pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex); @@ -62,17 +66,17 @@ camel_pop3_folder_class_init (CamelPop3FolderClass *camel_pop3_folder_class) { CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_pop3_folder_class); - + parent_class = CAMEL_FOLDER_CLASS(camel_type_get_global_classfuncs (camel_folder_get_type ())); - + /* virtual method overload */ camel_folder_class->refresh_info = pop3_refresh_info; camel_folder_class->sync = pop3_sync; - + camel_folder_class->get_message_count = pop3_get_message_count; camel_folder_class->get_uids = pop3_get_uids; camel_folder_class->free_uids = camel_folder_free_nop; - + camel_folder_class->get_message = pop3_get_message; camel_folder_class->set_message_flags = pop3_set_message_flags; } @@ -82,10 +86,10 @@ camel_pop3_folder_init (gpointer object) { CamelFolder *folder = CAMEL_FOLDER (object); CamelPop3Folder *pop3_folder = CAMEL_POP3_FOLDER (object); - + folder->has_summary_capability = FALSE; folder->has_search_capability = FALSE; - + pop3_folder->uids = NULL; pop3_folder->flags = NULL; } @@ -94,7 +98,7 @@ CamelType camel_pop3_folder_get_type (void) { static CamelType camel_pop3_folder_type = CAMEL_INVALID_TYPE; - + if (!camel_pop3_folder_type) { camel_pop3_folder_type = camel_type_register (CAMEL_FOLDER_TYPE, "CamelPop3Folder", sizeof (CamelPop3Folder), @@ -104,7 +108,7 @@ camel_pop3_folder_get_type (void) (CamelObjectInitFunc) camel_pop3_folder_init, (CamelObjectFinalizeFunc) pop3_finalize); } - + return camel_pop3_folder_type; } @@ -112,7 +116,7 @@ void pop3_finalize (CamelObject *object) { CamelPop3Folder *pop3_folder = CAMEL_POP3_FOLDER (object); - + if (pop3_folder->uids) camel_folder_free_deep (NULL, pop3_folder->uids); if (pop3_folder->flags) @@ -123,31 +127,71 @@ CamelFolder * camel_pop3_folder_new (CamelStore *parent, CamelException *ex) { CamelFolder *folder; - + folder = CAMEL_FOLDER (camel_object_new (CAMEL_POP3_FOLDER_TYPE)); camel_folder_construct (folder, parent, "inbox", "inbox"); - + /* mt-ok, since we dont have the folder-lock for new() */ camel_folder_refresh_info (folder, ex);/* mt-ok */ if (camel_exception_is_set (ex)) { camel_object_unref (CAMEL_OBJECT (folder)); folder = NULL; } - + return folder; } +static GPtrArray * +pop3_generate_uids (CamelFolder *folder, int count, CamelException *ex) +{ + /* FIXME: This is extremely inefficient but there's no way + around it. Because of that, perhaps we should have some way + of caching these messages so we don't have to download them + a second time for this session? */ + GPtrArray *uids; + int i; + + uids = g_ptr_array_new (); + g_ptr_array_set_size (uids, count); + + for (i = 0; i < count; i++) { + CamelStreamMem *stream; + guchar digest[16]; + char *uid; + + stream = pop3_get_message_stream (folder, i, ex); + if (stream == NULL) + goto exception; + + md5_get_digest (stream->buffer->data, stream->buffer->len, digest); + camel_object_unref (CAMEL_OBJECT (stream)); + + uid = base64_encode_simple (digest, 16); + g_ptr_array_add (uids, uid); + } + + return uids; + + exception: + + for (i = 0; i < count; i++) + g_free (uids->pdata[i]); + g_ptr_array_free (uids, TRUE); + + return NULL; +} + static void pop3_refresh_info (CamelFolder *folder, CamelException *ex) { + CamelPop3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store); + CamelPop3Folder *pop3_folder = (CamelPop3Folder *) folder; GPtrArray *uids; int status, count; char *data; - CamelPop3Folder *pop3_folder = (CamelPop3Folder *) folder; - CamelPop3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store); - - camel_operation_start(NULL, _("Retrieving POP summary")); - + + camel_operation_start (NULL, _("Retrieving POP summary")); + status = camel_pop3_command (pop3_store, &data, ex, "STAT"); switch (status) { case CAMEL_POP3_ERR: @@ -157,13 +201,13 @@ pop3_refresh_info (CamelFolder *folder, CamelException *ex) g_free (data); /* fall through */ case CAMEL_POP3_FAIL: - camel_operation_end(NULL); + camel_operation_end (NULL); return; } - + count = atoi (data); g_free (data); - + if (pop3_store->supports_uidl != FALSE) { status = camel_pop3_command (pop3_store, NULL, ex, "UIDL"); switch (status) { @@ -171,29 +215,24 @@ pop3_refresh_info (CamelFolder *folder, CamelException *ex) pop3_store->supports_uidl = FALSE; break; case CAMEL_POP3_FAIL: - camel_operation_end(NULL); + camel_operation_end (NULL); return; } } - + if (pop3_store->supports_uidl == FALSE) { - int i; - - uids = g_ptr_array_new (); - g_ptr_array_set_size (uids, count); - - for (i = 0; i < count; i++) - uids->pdata[i] = g_strdup_printf ("%d", i + 1); - camel_operation_end(NULL); + uids = pop3_generate_uids (folder, count, ex); + + camel_operation_end (NULL); } else { data = camel_pop3_command_get_additional_data (pop3_store, 0, ex); camel_operation_end(NULL); if (camel_exception_is_set (ex)) return; - + uids = parse_listing (count, data); g_free (data); - + if (!uids) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Could not open folder: " @@ -202,7 +241,7 @@ pop3_refresh_info (CamelFolder *folder, CamelException *ex) return; } } - + pop3_folder->uids = uids; pop3_folder->flags = g_new0 (guint32, uids->len); } @@ -216,10 +255,10 @@ pop3_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) if (!expunge) return; - + pop3_folder = CAMEL_POP3_FOLDER (folder); pop3_store = CAMEL_POP3_STORE (folder->parent_store); - + for (i = 0; i < pop3_folder->uids->len; i++) { if (pop3_folder->flags[i] & CAMEL_MESSAGE_DELETED) { status = camel_pop3_command (pop3_store, NULL, ex, @@ -228,7 +267,7 @@ pop3_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) return; } } - + camel_pop3_store_expunge (pop3_store, ex); } @@ -239,10 +278,10 @@ parse_listing (int count, char *data) GPtrArray *ans; char *p; int index, len; - + ans = g_ptr_array_new (); g_ptr_array_set_size (ans, count); - + p = data; while (*p) { index = strtoul (p, &p, 10); @@ -253,14 +292,14 @@ parse_listing (int count, char *data) if (*p == '\n') p++; } - + for (index = 0; index < count; index++) { if (ans->pdata[index] == NULL) { g_ptr_array_free (ans, TRUE); return NULL; } } - + return ans; } @@ -268,35 +307,26 @@ static int uid_to_number (CamelPop3Folder *pop3_folder, const char *uid) { int i; - + for (i = 0; i < pop3_folder->uids->len; i++) { if (!strcmp (uid, pop3_folder->uids->pdata[i])) return i + 1; } - + return -1; } - -static CamelMimeMessage * -pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex) +static CamelStreamMem * +pop3_get_message_stream (CamelFolder *folder, int id, CamelException *ex) { - int status, num, total; + CamelStream *stream; char *result, *body; - CamelStream *msgstream; - CamelMimeMessage *msg; + int status, total; - num = uid_to_number (CAMEL_POP3_FOLDER (folder), uid); - if (num == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("No message with uid %s"), uid); - return NULL; - } - - camel_operation_start_transient (NULL, _("Retrieving POP message %d"), num); + camel_operation_start_transient (NULL, _("Retrieving POP message %d"), id); status = camel_pop3_command (CAMEL_POP3_STORE (folder->parent_store), - &result, ex, "RETR %d", num); + &result, ex, "RETR %d", id); switch (status) { case CAMEL_POP3_ERR: camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, @@ -323,18 +353,39 @@ pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex) return NULL; } - msgstream = camel_stream_mem_new_with_buffer (body, strlen (body)); + stream = camel_stream_mem_new_with_buffer (body, strlen (body)); g_free (body); - msg = camel_mime_message_new (); - camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), - CAMEL_STREAM (msgstream)); + camel_operation_end (NULL); - camel_object_unref (CAMEL_OBJECT (msgstream)); + return CAMEL_STREAM_MEM (stream); +} + +static CamelMimeMessage * +pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex) +{ + CamelMimeMessage *message; + CamelStreamMem *stream; + int id; - camel_operation_end (NULL); + id = uid_to_number (CAMEL_POP3_FOLDER (folder), uid); + if (id == -1) { + camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, + _("No message with uid %s"), uid); + return NULL; + } + + stream = pop3_get_message_stream (folder, id, ex); + if (stream == NULL) + return NULL; + + message = camel_mime_message_new (); + camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (message), + CAMEL_STREAM (stream)); - return msg; + camel_object_unref (CAMEL_OBJECT (stream)); + + return message; } static void @@ -343,11 +394,11 @@ pop3_set_message_flags (CamelFolder *folder, const char *uid, { CamelPop3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); int num; - + num = uid_to_number (pop3_folder, uid); if (num == -1) return; - + pop3_folder->flags[num - 1] = (pop3_folder->flags[num] & ~flags) | (set & flags); } @@ -356,7 +407,7 @@ static gint pop3_get_message_count (CamelFolder *folder) { CamelPop3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); - + return pop3_folder->uids->len; } @@ -364,6 +415,6 @@ static GPtrArray * pop3_get_uids (CamelFolder *folder) { CamelPop3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); - + return pop3_folder->uids; } |