From b894c24f03beeaaeb947676f95c05473ee7691d4 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Wed, 30 Jan 2002 05:14:48 +0000 Subject: Changed name from "NT Login" to simply "Login". 2002-01-30 Not Zed * camel-sasl-login.c: Changed name from "NT Login" to simply "Login". * providers/pop3/*: Entirely new pop implmentation, supporting pipelining. 2002-01-29 Not Zed * camel-data-cache.c (free_busy): We dont want to unref the stream, instead, stop listening to the finalised events, and free the path only. 2002-01-25 Not Zed * camel-data-cache.c (stream_finalised): Remove the object from the busy_stream hashtable, not the busy_path hashtable. svn path=/trunk/; revision=15521 --- camel/providers/pop3/camel-pop3-folder.c | 618 +++++++++++++++++++------------ 1 file changed, 380 insertions(+), 238 deletions(-) (limited to 'camel/providers/pop3/camel-pop3-folder.c') diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c index 5452144eab..777f81fe9b 100644 --- a/camel/providers/pop3/camel-pop3-folder.c +++ b/camel/providers/pop3/camel-pop3-folder.c @@ -4,8 +4,9 @@ /* * Authors: * Dan Winship + * Michael Zucchi * - * Copyright (C) 2000 Ximian, Inc. (www.ximian.com) + * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -26,6 +27,8 @@ #include #endif +#include + #include "camel-pop3-folder.h" #include "camel-pop3-store.h" #include "camel-exception.h" @@ -33,35 +36,28 @@ #include "camel-stream-filter.h" #include "camel-mime-message.h" #include "camel-operation.h" +#include "camel-data-cache.h" #include #include #include +#define d(x) + #define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o))) static CamelFolderClass *parent_class; static void pop3_finalize (CamelObject *object); - static void pop3_refresh_info (CamelFolder *folder, CamelException *ex); -static void pop3_sync (CamelFolder *folder, gboolean expunge, - CamelException *ex); - +static void pop3_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); 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, - gboolean headers_only, CamelException *ex); -static CamelMimeMessage *pop3_get_message (CamelFolder *folder, - const char *uid, - CamelException *ex); -static void pop3_set_message_flags (CamelFolder *folder, const char *uid, - guint32 flags, guint32 set); - -static GPtrArray *parse_listing (int count, char *data); +static CamelMimeMessage *pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex); +static void pop3_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set); static void -camel_pop3_folder_class_init (CamelPop3FolderClass *camel_pop3_folder_class) +camel_pop3_folder_class_init (CamelPOP3FolderClass *camel_pop3_folder_class) { CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_pop3_folder_class); @@ -74,7 +70,7 @@ camel_pop3_folder_class_init (CamelPop3FolderClass *camel_pop3_folder_class) 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->free_uids = camel_folder_free_shallow; camel_folder_class->get_message = pop3_get_message; camel_folder_class->set_message_flags = pop3_set_message_flags; @@ -86,9 +82,9 @@ 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), - sizeof (CamelPop3FolderClass), + camel_pop3_folder_type = camel_type_register (CAMEL_FOLDER_TYPE, "CamelPOP3Folder", + sizeof (CamelPOP3Folder), + sizeof (CamelPOP3FolderClass), (CamelObjectClassInitFunc) camel_pop3_folder_class_init, NULL, NULL, @@ -101,18 +97,24 @@ camel_pop3_folder_get_type (void) 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) - g_free (pop3_folder->flags); + CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (object); + CamelPOP3FolderInfo **fi = (CamelPOP3FolderInfo **)pop3_folder->uids->pdata; + int i; + + for (i=0;iuids->len;i++,fi++) { + g_free(fi[0]->uid); + g_free(fi[0]); + } + + g_ptr_array_free(pop3_folder->uids, TRUE); } CamelFolder * camel_pop3_folder_new (CamelStore *parent, CamelException *ex) { CamelFolder *folder; + + d(printf("opening pop3 INBOX folder\n")); folder = CAMEL_FOLDER (camel_object_new (CAMEL_POP3_FOLDER_TYPE)); camel_folder_construct (folder, parent, "inbox", "inbox"); @@ -127,281 +129,413 @@ camel_pop3_folder_new (CamelStore *parent, CamelException *ex) return folder; } -static GPtrArray * -pop3_generate_uids (CamelFolder *folder, int count, CamelException *ex) +static CamelPOP3FolderInfo * +id_to_fi(CamelPOP3Folder *folder, guint32 id) { - 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 + 1, TRUE, 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); - uids->pdata[i] = uid; - } - - return uids; - - exception: - - for (i = 0; i < count; i++) - g_free (uids->pdata[i]); - g_ptr_array_free (uids, TRUE); - + CamelPOP3FolderInfo **fi = (CamelPOP3FolderInfo **)folder->uids->pdata; + int len = folder->uids->len; + + for (i=0;iid == id) + return fi[0]; + + return NULL; +} + +static CamelPOP3FolderInfo * +uid_to_fi(CamelPOP3Folder *folder, const char *uid) +{ + int i; + CamelPOP3FolderInfo **fi = (CamelPOP3FolderInfo **)folder->uids->pdata; + int len = folder->uids->len; + + for (i=0;iuid && strcmp(fi[0]->uid, uid) == 0) + return fi[0]; + return NULL; } +static int +fi_to_index(CamelPOP3Folder *folder, CamelPOP3FolderInfo *fin) +{ + int i; + CamelPOP3FolderInfo **fi = (CamelPOP3FolderInfo **)folder->uids->pdata; + int len = folder->uids->len; + + for (i=0;iid); + + md5_init(&md5); + do { + ret = camel_pop3_stream_getd(stream, &start, &len); + if (ret >= 0) + md5_update(&md5, start, len); + } while (ret > 0); + md5_final(&md5, digest); + fi->uid = base64_encode_simple (digest, 16); + + d(printf("building uid for id '%d' = '%s'\n", fi->id, fi->uid)); +} + +static void +cmd_list(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) +{ + int ret; + unsigned int len, id, size; + unsigned char *line; + CamelFolder *folder = data; + CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store); + CamelPOP3FolderInfo *fi; + + do { + ret = camel_pop3_stream_line(stream, &line, &len); + if (ret>=0) { + if (sscanf(line, "%u %u", &id, &size) == 2) { + fi = g_malloc0(sizeof(*fi)); + fi->size = size; + fi->id = id; + if ((pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) == 0) + fi->cmd = camel_pop3_engine_command_new(pe, CAMEL_POP3_COMMAND_MULTI, cmd_builduid, fi, "TOP %u 0\r\n", id); + g_ptr_array_add(((CamelPOP3Folder *)folder)->uids, fi); + } + } + } while (ret>0); +} + +static void +cmd_uidl(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) +{ + int ret; + unsigned int len; + unsigned char *line; + char uid[1025]; + unsigned int id, i=0; + CamelPOP3FolderInfo *fi; + CamelPOP3Folder *folder = data; + + do { + ret = camel_pop3_stream_line(stream, &line, &len); + if (ret>=0) { + if (strlen(line) > 1024) + line[1024] = 0; + if (sscanf(line, "%u %s", &id, uid) == 2) { + fi = id_to_fi(folder, id); + if (fi) { + /* fixme: dreadfully inefficient */ + i = fi_to_index(folder, fi); + camel_operation_progress(NULL, (i+1) * 100 / folder->uids->len); + fi->uid = g_strdup(uid); + } else { + g_warning("ID %u (uid: %s) not in previous LIST output", id, uid); + } + } + } + } while (ret>0); +} + 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; - + CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store); + CamelPOP3Folder *pop3_folder = (CamelPOP3Folder *) folder; + CamelPOP3Command *pcl, *pcu = NULL; + int i; + camel_operation_start (NULL, _("Retrieving POP summary")); - - status = camel_pop3_command (pop3_store, &data, ex, "STAT"); - switch (status) { - case CAMEL_POP3_ERR: - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not check POP server for new messages: %s"), - data); - g_free (data); - /* fall through */ - case CAMEL_POP3_FAIL: - camel_operation_end (NULL); - return; - } - - count = atoi (data); - g_free (data); - - if (count == 0) { - camel_operation_end (NULL); - pop3_folder->uids = g_ptr_array_new (); - pop3_folder->flags = g_new0 (guint32, 0); - return; + + pop3_folder->uids = g_ptr_array_new (); + + pcl = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_list, folder, "LIST\r\n"); + if (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) { + pcu = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_uidl, folder, "UIDL\r\n"); } + while ((i = camel_pop3_engine_iterate(pop3_store->engine, NULL)) > 0) + ; - if (pop3_store->supports_uidl != FALSE) { - status = camel_pop3_command (pop3_store, NULL, ex, "UIDL"); - switch (status) { - case CAMEL_POP3_ERR: - pop3_store->supports_uidl = FALSE; - break; - case CAMEL_POP3_FAIL: - camel_operation_end (NULL); - return; - } + if (i == -1) { + if (errno == EINTR) + camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); + else + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get POP summary: %s"), strerror(errno)); } - - if (pop3_store->supports_uidl == FALSE) { - uids = pop3_generate_uids (folder, count, ex); - camel_operation_end (NULL); - if (!uids || camel_exception_is_set (ex)) - return; + + /* TODO: check every id has a uid & commands returned OK too? */ + + /* Free any commands we created along the way */ + if (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) { + camel_pop3_engine_command_free(pop3_store->engine, pcu); } else { - data = camel_pop3_command_get_additional_data (pop3_store, 0, ex); - camel_operation_end (NULL); - if (!data || 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: " - "message listing was " - "incomplete.")); - return; + for (i=0;iuids->len;i++) { + CamelPOP3FolderInfo *fi = pop3_folder->uids->pdata[i]; + if (fi->cmd) { + camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); + fi->cmd = NULL; + } } } - - pop3_folder->uids = uids; - pop3_folder->flags = g_new0 (guint32, uids->len); + + camel_operation_end (NULL); + return; } static void pop3_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) { - CamelPop3Folder *pop3_folder; - CamelPop3Store *pop3_store; - int i, status; - + CamelPOP3Folder *pop3_folder; + CamelPOP3Store *pop3_store; + int i; + CamelPOP3FolderInfo *fi; + if (!expunge) return; - + pop3_folder = CAMEL_POP3_FOLDER (folder); pop3_store = CAMEL_POP3_STORE (folder->parent_store); camel_operation_start(NULL, _("Expunging deleted messages")); for (i = 0; i < pop3_folder->uids->len; i++) { - camel_operation_progress(NULL, (i+1) * 100 / pop3_folder->uids->len); - if (pop3_folder->flags[i] & CAMEL_MESSAGE_DELETED) { - status = camel_pop3_command (pop3_store, NULL, ex, - "DELE %d", i + 1); - if (status != CAMEL_POP3_OK) { - camel_operation_end(NULL); - return; - } + fi = pop3_folder->uids->pdata[i]; + /* busy already? wait for that to finish first */ + if (fi->cmd) { + while (camel_pop3_engine_iterate(pop3_store->engine, fi->cmd) > 0) + ; + camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); + fi->cmd = NULL; + } + + if (fi->flags & CAMEL_MESSAGE_DELETED) { + fi->cmd = camel_pop3_engine_command_new(pop3_store->engine, 0, NULL, NULL, "DELE %u\r\n", fi->id); + + /* also remove from cache */ + if (pop3_store->cache && fi->uid) + camel_data_cache_remove(pop3_store->cache, "cache", fi->uid, NULL); } } + for (i = 0; i < pop3_folder->uids->len; i++) { + fi = pop3_folder->uids->pdata[i]; + /* wait for delete commands to finish */ + if (fi->cmd) { + while (camel_pop3_engine_iterate(pop3_store->engine, fi->cmd) > 0) + ; + camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); + fi->cmd = NULL; + } + camel_operation_progress(NULL, (i+1) * 100 / pop3_folder->uids->len); + } + camel_operation_end(NULL); camel_pop3_store_expunge (pop3_store, ex); } - -static GPtrArray * -parse_listing (int count, char *data) +static void +cmd_tocache(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *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); - len = strcspn (p, "\n"); - if (index <= count && *p == ' ') - ans->pdata[index - 1] = g_strndup (p + 1, len - 1); - p += len; - 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; -} + CamelPOP3FolderInfo *fi = data; + char buffer[2048]; + int w = 0, n; -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; + /* What if it fails? */ + + /* We write an '*' to the start of the stream to say its not complete yet */ + /* This should probably be part of the cache code */ + if ((n = camel_stream_write(fi->stream, "*", 1)) == -1) + goto done; + + while ((n = camel_stream_read((CamelStream *)stream, buffer, sizeof(buffer))) > 0) { + n = camel_stream_write(fi->stream, buffer, n); + if (n == -1) + break; + + w += n; + if (w > fi->size) + w = fi->size; + camel_operation_progress(NULL, (w * 100) / fi->size); } - - return -1; -} -static CamelStreamMem * -pop3_get_message_stream (CamelFolder *folder, int id, gboolean headers_only, CamelException *ex) -{ - CamelStream *stream; - char *result, *body; - int status, total; - - status = camel_pop3_command (CAMEL_POP3_STORE (folder->parent_store), - &result, ex, headers_only ? "TOP %d 0" : "RETR %d", id); - switch (status) { - case CAMEL_POP3_ERR: - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not fetch message: %s"), result); - g_free (result); - /* fall through */ - case CAMEL_POP3_FAIL: - camel_operation_end (NULL); - return NULL; + /* it all worked, output a '#' to say we're a-ok */ + if (n != -1) { + camel_stream_reset(fi->stream); + n = camel_stream_write(fi->stream, "#", 1); } - - if (!result || (result && sscanf (result, "%d", &total) != 1)) - total = 0; - - g_free (result); - body = camel_pop3_command_get_additional_data (CAMEL_POP3_STORE (folder->parent_store), total, ex); - if (!body) { - CamelService *service = CAMEL_SERVICE (folder->parent_store); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not retrieve message from POP " - "server %s: %s"), service->url->host, - camel_exception_get_description (ex)); - camel_operation_end (NULL); - return NULL; +done: + if (n == -1) { + fi->err = errno; + g_warning("POP3 retrieval failed: %s", strerror(errno)); + } else { + fi->err = 0; } - stream = camel_stream_mem_new_with_buffer (body, strlen (body)); - g_free (body); - - return CAMEL_STREAM_MEM (stream); + camel_object_unref((CamelObject *)fi->stream); + fi->stream = NULL; } static CamelMimeMessage * pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex) { - CamelMimeMessage *message; - CamelStreamMem *stream; - int id; - - id = uid_to_number (CAMEL_POP3_FOLDER (folder), uid); - if (id == -1) { + CamelMimeMessage *message = NULL; + CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store); + CamelPOP3Folder *pop3_folder = (CamelPOP3Folder *)folder; + CamelPOP3Command *pcr; + CamelPOP3FolderInfo *fi; + char buffer[1]; + int ok, i; + CamelStream *stream = NULL; + + fi = uid_to_fi(pop3_folder, uid); + if (fi == NULL) { camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("No message with uid %s"), uid); return NULL; } + + /* Sigh, most of the crap in this function is so that the cancel button + returns the proper exception code. Sigh. */ + + camel_operation_start_transient(NULL, _("Retrieving POP message %d"), fi->id); + + /* If we have an oustanding retrieve message running, wait for that to complete + & then retrieve from cache, otherwise, start a new one, and similar */ + + if (fi->cmd != NULL) { + while ((i = camel_pop3_engine_iterate(pop3_store->engine, fi->cmd)) > 0) + ; + + if (i == -1) + fi->err = errno; + + /* getting error code? */ + ok = fi->cmd->state == CAMEL_POP3_COMMAND_DATA; + camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); + fi->cmd = NULL; + + if (fi->err != 0) { + if (fi->err == EINTR) + camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); + else + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), uid, strerror(fi->err)); + goto fail; + } + } - camel_operation_start_transient (NULL, _("Retrieving POP message %d"), id); - stream = pop3_get_message_stream (folder, id, FALSE, ex); - camel_operation_end (NULL); - if (stream == NULL) - return NULL; - + /* check to see if we have safely written flag set */ + if (pop3_store->cache == NULL + || (stream = camel_data_cache_get(pop3_store->cache, "cache", fi->uid, NULL)) == NULL + || camel_stream_read(stream, buffer, 1) != 1 + || buffer[0] != '#') { + + /* Initiate retrieval, if disk backing fails, use a memory backing */ + if (pop3_store->cache == NULL + || (stream = camel_data_cache_add(pop3_store->cache, "cache", fi->uid, NULL)) == NULL) + stream = camel_stream_mem_new(); + + /* ref it, the cache storage routine unref's when done */ + camel_object_ref((CamelObject *)stream); + fi->stream = stream; + fi->err = EIO; + pcr = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_tocache, fi, "RETR %u\r\n", fi->id); + + /* Also initiate retrieval of all following messages, assume we'll be receiving them */ + if (pop3_store->cache != NULL) { + i = fi_to_index(pop3_folder, fi)+1; + for (;iuids->len;i++) { + CamelPOP3FolderInfo *pfi = pop3_folder->uids->pdata[i]; + + if (pfi->uid && pfi->cmd == NULL) { + pfi->stream = camel_data_cache_add(pop3_store->cache, "cache", pfi->uid, NULL); + if (pfi->stream) { + pfi->err = EIO; + pfi->cmd = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, + cmd_tocache, pfi, "RETR %u\r\n", pfi->id); + } + } + } + } + + /* now wait for the first one to finish */ + while ((i = camel_pop3_engine_iterate(pop3_store->engine, pcr)) > 0) + ; + + if (i == -1) + fi->err = errno; + + /* getting error code? */ + ok = pcr->state == CAMEL_POP3_COMMAND_DATA; + camel_pop3_engine_command_free(pop3_store->engine, pcr); + camel_stream_reset(stream); + + /* Check to see we have safely written flag set */ + if (fi->err != 0) { + if (fi->err == EINTR) + camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); + else + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), uid, strerror(fi->err)); + goto done; + } + + if (camel_stream_read(stream, buffer, 1) != 1 + || buffer[0] != '#') { + camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, + _("Cannot get message %s: %s"), uid, _("Unknown reason")); + goto done; + } + } + message = camel_mime_message_new (); - camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (message), - CAMEL_STREAM (stream)); - - camel_object_unref (CAMEL_OBJECT (stream)); - + if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, stream) == -1) { + if (errno == EINTR) + camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); + else + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), uid, strerror(errno)); + camel_object_unref((CamelObject *)message); + message = NULL; + } +done: + camel_object_unref((CamelObject *)stream); +fail: + camel_operation_end(NULL); + return message; } static void -pop3_set_message_flags (CamelFolder *folder, const char *uid, - guint32 flags, guint32 set) +pop3_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set) { - 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); + CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); + CamelPOP3FolderInfo *fi; + + fi = uid_to_fi(pop3_folder, uid); + if (fi) + fi->flags = (fi->flags & ~flags) | (set & flags); } static gint pop3_get_message_count (CamelFolder *folder) { - CamelPop3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); + CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); return pop3_folder->uids->len; } @@ -409,7 +543,15 @@ pop3_get_message_count (CamelFolder *folder) static GPtrArray * pop3_get_uids (CamelFolder *folder) { - CamelPop3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); + CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); + GPtrArray *uids = g_ptr_array_new(); + CamelPOP3FolderInfo **fi = (CamelPOP3FolderInfo **)pop3_folder->uids->pdata; + int i; + + for (i=0;iuids->len;i++,fi++) { + if (fi[0]->uid) + g_ptr_array_add(uids, fi[0]->uid); + } - return pop3_folder->uids; + return uids; } -- cgit v1.2.3