aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog17
-rw-r--r--camel/providers/pop3/camel-pop3-folder.c130
-rw-r--r--camel/providers/pop3/camel-pop3-folder.h10
3 files changed, 75 insertions, 82 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index d04a0e4085..ef540ba517 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,20 @@
+2002-08-06 Not Zed <NotZed@Ximian.com>
+
+ * providers/pop3/camel-pop3-folder.c (cmd_list): Add messageinfo
+ to id table, and store array index in messageinfo too.
+ (fi_to_index): Removed, use index member of messageinfo, fixed
+ callers.
+ (cmd_builduid): Parse the headers of the data, and ignore any
+ status or x-status headers.
+ (uid_to_fi): Removed, use the hashtable instead.
+ (id_to_fi): Same.
+ (cmd_uidl): Add messageinfo to uid table.
+ (pop3_refresh_info): Setup hash tables, and fill out uid table for
+ nonuid capable servers.
+ (pop3_finalize): Destroy hash tables. Only free resources if the
+ uids table is not null (if finalised before we ran refresh info).
+ (id_to_fi): Removed. Use id hash table instead, fixed caller.
+
2002-08-05 Jeffrey Stedfast <fejj@ximian.com>
* camel.c (camel_init): Always set a g_atexit handler to
diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c
index f15b20dcb4..a32672bce9 100644
--- a/camel/providers/pop3/camel-pop3-folder.c
+++ b/camel/providers/pop3/camel-pop3-folder.c
@@ -43,7 +43,7 @@
#include <stdlib.h>
#include <string.h>
-#define d(x)
+#define d(x)
#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o)))
static CamelFolderClass *parent_class;
@@ -59,10 +59,9 @@ static void pop3_set_message_flags (CamelFolder *folder, const char *uid, guint3
static void
camel_pop3_folder_class_init (CamelPOP3FolderClass *camel_pop3_folder_class)
{
- CamelFolderClass *camel_folder_class =
- CAMEL_FOLDER_CLASS (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 ()));
+ parent_class = CAMEL_FOLDER_CLASS(camel_folder_get_type());
/* virtual method overload */
camel_folder_class->refresh_info = pop3_refresh_info;
@@ -102,18 +101,21 @@ pop3_finalize (CamelObject *object)
CamelPOP3Store *pop3_store = (CamelPOP3Store *)((CamelFolder *)pop3_folder)->parent_store;
int i;
- for (i=0;i<pop3_folder->uids->len;i++,fi++) {
- if (fi[0]->cmd) {
- while (camel_pop3_engine_iterate(pop3_store->engine, fi[0]->cmd) > 0)
- ;
- camel_pop3_engine_command_free(pop3_store->engine, fi[0]->cmd);
+ if (pop3_folder->uids) {
+ for (i=0;i<pop3_folder->uids->len;i++,fi++) {
+ if (fi[0]->cmd) {
+ while (camel_pop3_engine_iterate(pop3_store->engine, fi[0]->cmd) > 0)
+ ;
+ camel_pop3_engine_command_free(pop3_store->engine, fi[0]->cmd);
+ }
+
+ g_free(fi[0]->uid);
+ g_free(fi[0]);
}
-
- g_free(fi[0]->uid);
- g_free(fi[0]);
+
+ g_ptr_array_free(pop3_folder->uids, TRUE);
+ g_hash_table_destroy(pop3_folder->uids_uid);
}
-
- g_ptr_array_free(pop3_folder->uids, TRUE);
}
CamelFolder *
@@ -136,71 +138,41 @@ camel_pop3_folder_new (CamelStore *parent, CamelException *ex)
return folder;
}
-static CamelPOP3FolderInfo *
-id_to_fi(CamelPOP3Folder *folder, guint32 id)
-{
- int i;
- CamelPOP3FolderInfo **fi = (CamelPOP3FolderInfo **)folder->uids->pdata;
- int len = folder->uids->len;
-
- for (i=0;i<len;i++, fi++)
- if (fi[0]->id == 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;i<len;i++,fi++)
- if (fi[0]->uid && 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;i<len;i++,fi++)
- if (fi[0] == fin)
- return i;
-
- return -1;
-}
-
/* create a uid from md5 of 'top' output */
static void
cmd_builduid(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data)
{
CamelPOP3FolderInfo *fi = data;
MD5Context md5;
- unsigned char *start;
- unsigned int len;
unsigned char digest[16];
- int ret;
+ struct _header_raw *h;
+ CamelMimeParser *mp;
/* TODO; somehow work out the limit and use that for proper progress reporting
We need a pointer to the folder perhaps? */
camel_operation_progress_count(NULL, fi->id);
md5_init(&md5);
- do {
- ret = camel_pop3_stream_getd(stream, &start, &len);
- if (ret >= 0)
- md5_update(&md5, start, len);
- } while (ret > 0);
+ mp = camel_mime_parser_new();
+ camel_mime_parser_init_with_stream(mp, (CamelStream *)stream);
+ switch (camel_mime_parser_step(mp, NULL, NULL)) {
+ case HSCAN_HEADER:
+ case HSCAN_MESSAGE:
+ case HSCAN_MULTIPART:
+ h = camel_mime_parser_headers_raw(mp);
+ while (h) {
+ if (strcasecmp(h->name, "status") != 0
+ && strcasecmp(h->name, "x-status") != 0) {
+ md5_update(&md5, h->name, strlen(h->name));
+ md5_update(&md5, h->value, strlen(h->value));
+ }
+ h = h->next;
+ }
+ default:
+ }
+ camel_object_unref(mp);
md5_final(&md5, digest);
- fi->uid = base64_encode_simple (digest, 16);
+ fi->uid = base64_encode_simple(digest, 16);
d(printf("building uid for id '%d' = '%s'\n", fi->id, fi->uid));
}
@@ -222,9 +194,11 @@ cmd_list(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data)
fi = g_malloc0(sizeof(*fi));
fi->size = size;
fi->id = id;
+ fi->index = ((CamelPOP3Folder *)folder)->uids->len;
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);
+ g_hash_table_insert(((CamelPOP3Folder *)folder)->uids_id, (void *)id, fi);
}
}
} while (ret>0);
@@ -237,7 +211,7 @@ cmd_uidl(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data)
unsigned int len;
unsigned char *line;
char uid[1025];
- unsigned int id, i=0;
+ unsigned int id;
CamelPOP3FolderInfo *fi;
CamelPOP3Folder *folder = data;
@@ -247,12 +221,11 @@ cmd_uidl(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data)
if (strlen(line) > 1024)
line[1024] = 0;
if (sscanf(line, "%u %s", &id, uid) == 2) {
- fi = id_to_fi(folder, id);
+ fi = g_hash_table_lookup(folder->uids_id, (void *)id);
if (fi) {
- /* fixme: dreadfully inefficient */
- i = fi_to_index(folder, fi);
- camel_operation_progress(NULL, (i+1) * 100 / folder->uids->len);
+ camel_operation_progress(NULL, (fi->index+1) * 100 / folder->uids->len);
fi->uid = g_strdup(uid);
+ g_hash_table_insert(folder->uids_uid, fi->uid, fi);
} else {
g_warning("ID %u (uid: %s) not in previous LIST output", id, uid);
}
@@ -272,6 +245,9 @@ pop3_refresh_info (CamelFolder *folder, CamelException *ex)
camel_operation_start (NULL, _("Retrieving POP summary"));
pop3_folder->uids = g_ptr_array_new ();
+ pop3_folder->uids_uid = g_hash_table_new(g_str_hash, g_str_equal);
+ /* only used during setup */
+ pop3_folder->uids_id = g_hash_table_new(NULL, NULL);
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) {
@@ -289,8 +265,7 @@ pop3_refresh_info (CamelFolder *folder, CamelException *ex)
/* TODO: check every id has a uid & commands returned OK too? */
- /* Free any commands we created along the way */
- camel_pop3_engine_command_free (pop3_store->engine, pcl);
+ camel_pop3_engine_command_free(pop3_store->engine, pcl);
if (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) {
camel_pop3_engine_command_free(pop3_store->engine, pcu);
@@ -301,8 +276,13 @@ pop3_refresh_info (CamelFolder *folder, CamelException *ex)
camel_pop3_engine_command_free(pop3_store->engine, fi->cmd);
fi->cmd = NULL;
}
+ if (fi->uid)
+ g_hash_table_insert(pop3_folder->uids_uid, fi->uid, fi);
}
}
+
+ /* dont need this anymore */
+ g_hash_table_destroy(pop3_folder->uids_id);
camel_operation_end (NULL);
return;
@@ -414,7 +394,7 @@ pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
int ok, i, last;
CamelStream *stream = NULL;
- fi = uid_to_fi(pop3_folder, uid);
+ fi = g_hash_table_lookup(pop3_folder->uids_uid, uid);
if (fi == NULL) {
camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID,
_("No message with uid %s"), uid);
@@ -471,7 +451,7 @@ pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
if (pop3_store->cache != NULL) {
/* This should keep track of the last one retrieved, also how many are still
oustanding incase of random access on large folders */
- i = fi_to_index(pop3_folder, fi)+1;
+ i = fi->index+1;
last = MIN(i+10, pop3_folder->uids->len);
for (;i<last;i++) {
CamelPOP3FolderInfo *pfi = pop3_folder->uids->pdata[i];
@@ -539,7 +519,7 @@ pop3_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, gui
CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder);
CamelPOP3FolderInfo *fi;
- fi = uid_to_fi(pop3_folder, uid);
+ fi = g_hash_table_lookup(pop3_folder->uids_uid, uid);
if (fi)
fi->flags = (fi->flags & ~flags) | (set & flags);
}
diff --git a/camel/providers/pop3/camel-pop3-folder.h b/camel/providers/pop3/camel-pop3-folder.h
index 55eb1d253b..7dab07124c 100644
--- a/camel/providers/pop3/camel-pop3-folder.h
+++ b/camel/providers/pop3/camel-pop3-folder.h
@@ -23,11 +23,9 @@
* USA
*/
-
#ifndef CAMEL_POP3_FOLDER_H
#define CAMEL_POP3_FOLDER_H 1
-
#ifdef __cplusplus
extern "C" {
#pragma }
@@ -44,22 +42,21 @@ typedef struct {
guint32 id;
guint32 size;
guint32 flags;
+ guint32 index; /* index of request */
char *uid;
int err;
struct _CamelPOP3Command *cmd;
struct _CamelStream *stream;
} CamelPOP3FolderInfo;
-
typedef struct {
CamelFolder parent_object;
GPtrArray *uids;
-
+ GHashTable *uids_uid; /* messageinfo by uid */
+ GHashTable *uids_id; /* messageinfo by id */
} CamelPOP3Folder;
-
-
typedef struct {
CamelFolderClass parent_class;
@@ -67,7 +64,6 @@ typedef struct {
} CamelPOP3FolderClass;
-
/* public methods */
CamelFolder *camel_pop3_folder_new (CamelStore *parent, CamelException *ex);