Add messageinfo to id table, and store array index in messageinfo too.

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.

svn path=/trunk/; revision=17706
This commit is contained in:
Not Zed
2002-08-06 04:11:33 +00:00
committed by Michael Zucci
parent 5c45e184a4
commit 8a030c88e2
3 changed files with 75 additions and 82 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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);