diff options
author | Michael Zucci <zucchi@src.gnome.org> | 2003-08-02 05:07:43 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2003-08-02 05:07:43 +0800 |
commit | e2cd78ca9b706f30f51a648db9da220e9b5a68a2 (patch) | |
tree | a1a211c5f2e2447b22eb2d610c25f58173961c6f /camel/providers/imapp/camel-imapp-driver.c | |
parent | 330ecafed407197d31c30170e1c76674d3ed91e8 (diff) | |
download | gsoc2013-evolution-e2cd78ca9b706f30f51a648db9da220e9b5a68a2.tar.gz gsoc2013-evolution-e2cd78ca9b706f30f51a648db9da220e9b5a68a2.tar.zst gsoc2013-evolution-e2cd78ca9b706f30f51a648db9da220e9b5a68a2.zip |
experimental, non-working imap implementation
svn path=/trunk/; revision=22061
Diffstat (limited to 'camel/providers/imapp/camel-imapp-driver.c')
-rw-r--r-- | camel/providers/imapp/camel-imapp-driver.c | 748 |
1 files changed, 748 insertions, 0 deletions
diff --git a/camel/providers/imapp/camel-imapp-driver.c b/camel/providers/imapp/camel-imapp-driver.c new file mode 100644 index 0000000000..f9daced770 --- /dev/null +++ b/camel/providers/imapp/camel-imapp-driver.c @@ -0,0 +1,748 @@ + + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> + +#include "camel-imapp-driver.h" +#include "camel-imapp-utils.h" +#include "camel-imapp-folder.h" +#include "camel-imapp-engine.h" +#include "camel-imapp-summary.h" +#include "camel-imapp-exception.h" + +#include <camel/camel-stream-mem.h> +#include <camel/camel-stream-null.h> + +#include <camel/camel-folder-summary.h> +#include <camel/camel-store.h> +#include <camel/camel-mime-utils.h> +#include <camel/camel-sasl.h> + +#define d(x) x + +static int driver_resp_fetch(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); +static int driver_resp_expunge(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); +static int driver_resp_exists(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); +static int driver_resp_list(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); + +static void driver_status(CamelIMAPPEngine *ie, struct _status_info *sinfo, CamelIMAPPDriver *sdata); + +static void +class_init(CamelIMAPPDriverClass *ieclass) +{ +} + +static void +object_init(CamelIMAPPDriver *ie, CamelIMAPPDriverClass *ieclass) +{ + ie->summary = g_ptr_array_new(); + e_dlist_init(&ie->body_fetch); + e_dlist_init(&ie->body_fetch_done); +} + +static void +object_finalise(CamelIMAPPDriver *ie, CamelIMAPPDriverClass *ieclass) +{ + if (ie->folder) + camel_object_unref((CamelObject *)ie->folder); + if (ie->engine) + camel_object_unref((CamelObject *)ie->engine); + if (ie->summary) + g_ptr_array_free(ie->summary, TRUE); +} + +CamelType +camel_imapp_driver_get_type (void) +{ + static CamelType type = CAMEL_INVALID_TYPE; + + if (type == CAMEL_INVALID_TYPE) { + type = camel_type_register ( + camel_object_get_type (), + "CamelIMAPPDriver", + sizeof (CamelIMAPPDriver), + sizeof (CamelIMAPPDriverClass), + (CamelObjectClassInitFunc) class_init, + NULL, + (CamelObjectInitFunc) object_init, + (CamelObjectFinalizeFunc) object_finalise); + + /* blah ... could just use it in object setup? */ + /* TEMPORARY */ + camel_exception_setup(); + } + + return type; +} + +CamelIMAPPDriver * +camel_imapp_driver_new(CamelIMAPPStream *stream) +{ + CamelIMAPPDriver *driver; + CamelIMAPPEngine *ie; + + driver = CAMEL_IMAPP_DRIVER (camel_object_new (CAMEL_IMAPP_DRIVER_TYPE)); + ie = driver->engine = camel_imapp_engine_new(stream); + + camel_imapp_engine_add_handler(ie, "FETCH", (CamelIMAPPEngineFunc)driver_resp_fetch, driver); + camel_imapp_engine_add_handler(ie, "EXPUNGE", (CamelIMAPPEngineFunc)driver_resp_expunge, driver); + camel_imapp_engine_add_handler(ie, "EXISTS", (CamelIMAPPEngineFunc)driver_resp_exists, driver); + camel_imapp_engine_add_handler(ie, "LIST", (CamelIMAPPEngineFunc)driver_resp_list, driver); + camel_object_hook_event(ie, "status", (CamelObjectEventHookFunc)driver_status, driver); + + return driver; +} + +void +camel_imapp_driver_set_sasl_factory(CamelIMAPPDriver *id, CamelIMAPPSASLFunc get_sasl, void *sasl_data) +{ + id->get_sasl = get_sasl; + id->get_sasl_data = sasl_data; +} + +void +camel_imapp_driver_set_login_query(CamelIMAPPDriver *id, CamelIMAPPLoginFunc get_login, void *login_data) +{ + id->get_login = get_login; + id->get_login_data = login_data; +} + +void +camel_imapp_driver_login(CamelIMAPPDriver *id) +/* throws SERVICE_CANT_AUTHENTICATE, SYSTEM_IO */ +{ + CamelIMAPPCommand * volatile ic = NULL; + + /* connect? */ + /* camel_imapp_engine_connect() */ + /* or above? */ + + CAMEL_TRY { + CamelSasl *sasl; + + if (id->get_sasl + && (sasl = id->get_sasl(id, id->get_sasl_data))) { + ic = camel_imapp_engine_command_new(id->engine, "AUTHENTICATE", NULL, "AUTHENTICATE %A", sasl); + camel_object_unref(sasl); + } else { + char *user, *pass; + + g_assert(id->get_login); + id->get_login(id, &user, &pass, id->get_login_data); + ic = camel_imapp_engine_command_new(id->engine, "LOGIN", NULL, "LOGIN %s %s", user, pass); + g_free(user); + g_free(pass); + } + + camel_imapp_engine_command_queue(id->engine, ic); + while (camel_imapp_engine_iterate(id->engine, ic) > 0) + ; + + if (ic->status->result != IMAP_OK) + camel_exception_throw(CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, "Login failed: %s", ic->status->text); + camel_imapp_engine_command_free(id->engine, ic); + } CAMEL_CATCH(ex) { + if (ic) + camel_imapp_engine_command_free(id->engine, ic); + camel_exception_throw_ex(ex); + } CAMEL_DONE; +} + +void +camel_imapp_driver_select(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder) +{ + CamelIMAPPSelectResponse *sr; + CamelIMAPPCommand * volatile ic = NULL; + CamelIMAPPCommand * volatile ic2 = NULL; + guint32 count; + CamelFolderSummary *summary; + + if (id->folder) { + if (folder == id->folder) + return; + camel_imapp_driver_sync(id, FALSE, id->folder); + if (camel_folder_change_info_changed(id->folder->changes)) { + camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); + camel_folder_change_info_clear(id->folder->changes); + } + camel_object_unref(id->folder); + id->folder = NULL; + } + + summary = ((CamelFolder *)folder)->summary; + + ic = camel_imapp_engine_command_new(id->engine, "SELECT", NULL, "SELECT %t", folder->raw_name); + camel_imapp_engine_command_queue(id->engine, ic); + while (camel_imapp_engine_iterate(id->engine, ic)>0) + ; + camel_imapp_engine_command_free(id->engine, ic); + + id->folder = folder; + camel_object_ref(folder); + + count = camel_folder_summary_count(summary); + if (count > 0 && count <= id->exists) { + ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, + "FETCH 1:%u (UID FLAGS)", count); + camel_imapp_engine_command_queue(id->engine, ic); + if (count < id->exists) { + ic2 = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, + "FETCH %u:* (UID FLAGS ENVELOPE)", count+1); + camel_imapp_engine_command_queue(id->engine, ic2); + } else { + ic2 = NULL; + } + + while (camel_imapp_engine_iterate(id->engine, ic2?ic2:ic)>0) + ; + + camel_imapp_engine_command_free(id->engine, ic); + if (ic2) + camel_imapp_engine_command_free(id->engine, ic2); + } else { + ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, + "FETCH 1:* (UID FLAGS ENVELOPE)"); + camel_imapp_engine_command_queue(id->engine, ic); + while (camel_imapp_engine_iterate(id->engine, ic)>0) + ; + camel_imapp_engine_command_free(id->engine, ic); + } + + /* TODO: need to set exists/etc in summary */ + folder->exists = id->exists; + folder->uidvalidity = id->uidvalidity; + + printf("saving summary '%s'\n", summary->summary_path); + camel_folder_summary_save(summary); + + if (camel_folder_change_info_changed(id->folder->changes)) { + camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); + camel_folder_change_info_clear(id->folder->changes); + } +} + +static void +imapp_driver_check(CamelIMAPPDriver *id) +{ + guint32 count; + CamelIMAPPCommand *ic; + + /* FIXME: exception handling */ + + if (id->folder->exists != id->exists) { + count = camel_folder_summary_count(((CamelFolder *)id->folder)->summary); + if (count < id->exists) { + printf("fetching new messages\n"); + ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, + "FETCH %u:* (UID FLAGS ENVELOPE)", count+1); + camel_imapp_engine_command_queue(id->engine, ic); + while (camel_imapp_engine_iterate(id->engine, ic)>0) + ; + camel_imapp_engine_command_free(id->engine, ic); + } else if (count > id->exists) { + printf("folder shrank with no expunge notificaitons!? uh, dunno what to do\n"); + } + } + + printf("checking for change info changes\n"); + if (camel_folder_change_info_changed(id->folder->changes)) { + printf("got somechanges! added=%d changed=%d removed=%d\n", + id->folder->changes->uid_added->len, + id->folder->changes->uid_changed->len, + id->folder->changes->uid_removed->len); + camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); + camel_folder_change_info_clear(id->folder->changes); + } +} + +void +camel_imapp_driver_update(CamelIMAPPDriver *id, CamelIMAPPFolder *folder) +{ + if (id->folder == folder) { + CamelIMAPPCommand *ic; + + /* this will automagically update flags & expunge items */ + ic = camel_imapp_engine_command_new(id->engine, "NOOP", NULL, "NOOP"); + camel_imapp_engine_command_queue(id->engine, ic); + while (camel_imapp_engine_iterate(id->engine, ic)>0) + ; + camel_imapp_engine_command_free(id->engine, ic); + + imapp_driver_check(id); + } else { + camel_imapp_driver_select(id, folder); + } +} + +/* FIXME: this is basically a copy of the same in camel-imapp-utils.c */ +static struct { + char *name; + guint32 flag; +} flag_table[] = { + { "\\ANSWERED", CAMEL_MESSAGE_ANSWERED }, + { "\\DELETED", CAMEL_MESSAGE_DELETED }, + { "\\DRAFT", CAMEL_MESSAGE_DRAFT }, + { "\\FLAGGED", CAMEL_MESSAGE_FLAGGED }, + { "\\SEEN", CAMEL_MESSAGE_SEEN }, + /* { "\\RECENT", CAMEL_IMAPP_MESSAGE_RECENT }, */ +}; + +/* + flags 00101000 + sflags 01001000 + ^ 01100000 +~flags 11010111 +& 01000000 + +&flags 00100000 +*/ + +static void +imapp_write_flags(CamelIMAPPDriver *id, guint32 orset, gboolean on, CamelFolderSummary *summary) +{ + guint32 i, j, count; + CamelIMAPPMessageInfo *info; + CamelIMAPPCommand *ic = NULL; + struct _uidset_state ss; + GSList *commands = NULL; + + /* FIXME: exception handling */ + + count = camel_folder_summary_count(summary); + for (j=0;j<sizeof(flag_table)/sizeof(flag_table[0]);j++) { + int flush; + + if ((orset & flag_table[j].flag) == 0) + continue; + + printf("checking/storing %s flags '%s'\n", on?"on":"off", flag_table[j].name); + + flush = 0; + imapp_uidset_init(&ss, id->engine); + for (i=0;i<count;i++) { + info = (CamelIMAPPMessageInfo *)camel_folder_summary_index(summary, i); + if (info) { + guint32 flags = info->info.flags & CAMEL_IMAPP_SERVER_FLAGS; + guint32 sflags = info->server_flags & CAMEL_IMAPP_SERVER_FLAGS; + + if ( (on && (((flags ^ sflags) & flags) & flag_table[j].flag)) + || (!on && (((flags ^ sflags) & ~flags) & flag_table[j].flag))) { + if (ic == NULL) + ic = camel_imapp_engine_command_new(id->engine, "STORE", NULL, "UID STORE "); + flush = imapp_uidset_add(&ss, ic, camel_message_info_uid(info)); + } + camel_folder_summary_info_free(summary, (CamelMessageInfo *)info); + } + + if (i == count-1 && ic != NULL) + flush |= imapp_uidset_done(&ss, ic); + + if (flush) { + flush = 0; + camel_imapp_engine_command_add(id->engine, ic, " %tFLAGS.SILENT (%t)", on?"+":"-", flag_table[j].name); + camel_imapp_engine_command_queue(id->engine, ic); + commands = g_slist_prepend(commands, ic); + ic = NULL; + } + } + } + + /* flush off any requests we may have outstanding */ + /* TODO: for max benefit, should have this routine do both on and off flags in one go */ + while (commands) { + GSList *next = commands->next; + + ic = commands->data; + g_slist_free_1(commands); + commands = next; + + while (camel_imapp_engine_iterate(id->engine, ic)>0) + ; + camel_imapp_engine_command_free(id->engine, ic); + } +} + +void +camel_imapp_driver_sync(CamelIMAPPDriver *id, gboolean expunge, CamelIMAPPFolder *folder) +{ + CamelFolderSummary *summary; + guint i, count, on_orset, off_orset; + CamelIMAPPMessageInfo *info; + CamelIMAPPCommand *ic; + + /* FIXME: exception handling */ + + camel_imapp_driver_update(id, folder); + + summary = ((CamelFolder *)folder)->summary; + count = camel_folder_summary_count(summary); + /* find out which flags have turned on, which have tunred off */ + off_orset = on_orset = 0; + for (i=0;i<count;i++) { + guint32 flags, sflags; + + info = (CamelIMAPPMessageInfo *)camel_folder_summary_index(summary, i); + if (info == NULL) + continue; + flags = info->info.flags & CAMEL_IMAPP_SERVER_FLAGS; + sflags = info->server_flags & CAMEL_IMAPP_SERVER_FLAGS; + if (flags != sflags) { + off_orset |= ( flags ^ sflags ) & ~flags; + on_orset |= (flags ^ sflags) & flags; + } + camel_folder_summary_info_free(summary, (CamelMessageInfo *)info); + } + + if (on_orset || off_orset) { + /* turn on or off all messages matching */ + if (on_orset) + imapp_write_flags(id, on_orset, TRUE, summary); + if (off_orset) + imapp_write_flags(id, off_orset, FALSE, summary); + + /* success (no exception), make sure we match what we're supposed to */ + for (i=0;i<count;i++) { + guint32 flags, sflags; + + info = (CamelIMAPPMessageInfo *)camel_folder_summary_index(summary, i); + if (info == NULL) + continue; + info->server_flags = info->info.flags & CAMEL_IMAPP_SERVER_FLAGS; + camel_folder_summary_info_free(summary, (CamelMessageInfo *)info); + } + camel_folder_summary_touch(summary); + /* could save summary here, incase of failure? */ + } + + if (expunge) { + ic = camel_imapp_engine_command_new(id->engine, "EXPUNGE", NULL, "EXPUNGE"); + camel_imapp_engine_command_queue(id->engine, ic); + while (camel_imapp_engine_iterate(id->engine, ic)>0) + ; + camel_imapp_engine_command_free(id->engine, ic); + } + + printf("saving summary '%s'\n", summary->summary_path); + camel_folder_summary_save(summary); + + if (camel_folder_change_info_changed(id->folder->changes)) { + camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); + camel_folder_change_info_clear(id->folder->changes); + } +} + +struct _fetch_data { + struct _fetch_data *next; + struct _fetch_data *prev; + + CamelStream *data; + const char *uid; + const char *section; +}; + +CamelStream * +camel_imapp_driver_fetch(CamelIMAPPDriver *id, CamelIMAPPFolder *folder, const char *uid, const char *section) +{ + struct _fetch_data fd; + CamelIMAPPCommand *ic; + + fd.data = NULL; + fd.uid = uid; + fd.section = section; + e_dlist_addtail(&id->body_fetch, (EDListNode *)&fd); + + CAMEL_TRY { + camel_imapp_driver_select(id, folder); + + ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, "UID FETCH %t (BODY.PEEK[%t])", uid, section); + camel_imapp_engine_command_queue(id->engine, ic); + while (camel_imapp_engine_iterate(id->engine, ic)>0) + ; + camel_imapp_engine_command_free(id->engine, ic); + imapp_driver_check(id); + } CAMEL_CATCH(e) { + /* FIXME: do exception properly */ + } CAMEL_DONE; + + e_dlist_remove((EDListNode *)&fd); + + return fd.data; +} + +GPtrArray * +camel_imapp_driver_list(CamelIMAPPDriver *id, const char *name, guint32 flags) +{ + CamelIMAPPCommand *ic; + GPtrArray *res; + + g_assert(id->list_commands == NULL); + g_assert(id->list_result == NULL); + + /* FIXME: make sure we only have a single list running at a time */ + /* sem_wait(id->list_sem); */ + + /* FIXME: namespace stuff (done in store code?) */ + + /* FIXME: if name != "", we need to also do list "name.%" (. == sep) */ + + id->list_result = g_ptr_array_new(); + id->list_flags = flags; + ic = camel_imapp_engine_command_new(id->engine, "LIST", NULL, "LIST \"\" %f", name[0]?name:"%"); + camel_imapp_engine_command_queue(id->engine, ic); + while (ic) { + while (camel_imapp_engine_iterate(id->engine, ic)>0) + ; + camel_imapp_engine_command_free(id->engine, ic); + + if (id->list_commands) { + GSList *top = id->list_commands; + + id->list_commands = top->next; + ic = top->data; + g_slist_free_1(top); + } else { + ic = NULL; + } + } + + res = id->list_result; + id->list_result = NULL; + + /* sem_post(id->list_sem); */ + + return res; +} + +static int +driver_resp_list(CamelIMAPPEngine *ie, guint32 idx, CamelIMAPPDriver *id) +{ + struct _list_info *linfo; + + /* FIXME: exceptions */ + + linfo = imap_parse_list(ie->stream); + printf("store list: '%s' ('%c')\n", linfo->name, linfo->separator); + if (id->list_result) { + if ((linfo->flags & CAMEL_FOLDER_NOINFERIORS) == 0 + && (id->list_flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) + && linfo->separator) { + int depth = 0; + char *p = linfo->name; + char c = linfo->separator; + + /* this is expensive ... but if we've listed this deep we're going slow anyway */ + while (*p && depth < 10) { + if (*p == c) + depth++; + p++; + } + + if (depth < 10 + && (linfo->name[0] == 0 || linfo->name[strlen(linfo->name)-1] != c)) { + CamelIMAPPCommand *ic; + + ic = camel_imapp_engine_command_new(id->engine, "LIST", NULL, "LIST \"\" %t%c%%", linfo->name, c); + id->list_commands = g_slist_prepend(id->list_commands, ic); + camel_imapp_engine_command_queue(id->engine, ic); + } + } + /* FIXME: dont add to list if name ends in separator */ + g_ptr_array_add(id->list_result, linfo); + } else { + g_warning("unexpected list response\n"); + imap_free_list(linfo); + } + + return camel_imapp_engine_skip(ie); +} + +/* ********************************************************************** */ + +static void +driver_status(CamelIMAPPEngine *ie, struct _status_info *sinfo, CamelIMAPPDriver *sdata) +{ + printf("got status response ...\n"); + switch(sinfo->condition) { + case IMAP_READ_WRITE: + printf("folder is read-write\n"); + break; + case IMAP_READ_ONLY: + printf("folder is read-only\n"); + break; + case IMAP_UIDVALIDITY: + sdata->uidvalidity = sinfo->u.uidvalidity; + break; +#if 0 + /* not defined yet ... */ + case IMAP_UIDNEXT: + printf("got uidnext for folder: %d\n", sinfo->u.uidnext); + break; +#endif + case IMAP_UNSEEN: + sdata->unseen = sinfo->u.unseen; + break; + case IMAP_PERMANENTFLAGS: + sdata->permanentflags = sinfo->u.permanentflags; + break; + case IMAP_ALERT: + printf("ALERT!: %s\n", sinfo->text); + break; + case IMAP_PARSE: + printf("PARSE: %s\n", sinfo->text); + break; + default: + break; + } +} + +static int +driver_resp_exists(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata) +{ + /* should this be an event instead? */ + + sdata->exists = id; + + return camel_imapp_engine_skip(ie); +} + +static int +driver_resp_expunge(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata) +{ + printf("got expunge response %u\n", id); + if (sdata->folder != NULL) { + CamelMessageInfo *info; + CamelFolderSummary *summary = ((CamelFolder *)sdata->folder)->summary; + + info = camel_folder_summary_index(summary, id-1); + if (info) { + printf("expunging msg %d\n", id); + camel_folder_summary_remove(summary, info); + camel_folder_summary_info_free(summary, info); + camel_folder_change_info_remove_uid(sdata->folder->changes, camel_message_info_uid(info)); + } else { + printf("can not find msg %u from expunge\n", id); + } + } + + return camel_imapp_engine_skip(ie); +} + +static int +driver_resp_fetch(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata) +{ + struct _fetch_info *finfo = NULL; + CamelMessageInfo *info, *uinfo; + unsigned int i; + CamelFolderSummary *summary; + + printf("got fetch response %d\n", id); + + if (sdata->folder == NULL) + goto done; + + summary = ((CamelFolder *)sdata->folder)->summary; + + finfo = imap_parse_fetch(ie->stream); + imap_dump_fetch(finfo); + + info = camel_folder_summary_index(summary, id-1); + if (info == NULL) { + if (finfo->uid == NULL) { + printf("got fetch response for currently unknown message %u\n", id); + goto done; + } + uinfo = camel_folder_summary_uid(summary, finfo->uid); + if (uinfo) { + /* we have a problem ... index mismatch */ + printf("index mismatch, uid '%s' not at index '%u'\n", + finfo->uid, id); + camel_folder_summary_info_free(summary, uinfo); + } + /* pad out the summary till we have enough indexes */ + for (i=camel_folder_summary_count(summary);i<id;i++) { + info = camel_folder_summary_info_new(summary); + if (i == id-1) { + printf("inserting new info @ %u\n", i); + camel_message_info_set_uid(info, g_strdup(finfo->uid)); + } else { + char uidtmp[32]; + + sprintf(uidtmp, "blank-%u", i); + camel_message_info_set_uid(info, g_strdup(uidtmp)); + printf("inserting empty uid %s\n", uidtmp); + } + + camel_folder_summary_add(summary, info); + } + info = camel_folder_summary_index(summary, id-1); + g_assert(info != NULL); + } else { + if (finfo->uid) { + /* FIXME: need to handle blank-* uids, somehow */ + while (info && strcmp(camel_message_info_uid(info), finfo->uid) != 0) { + printf("index mismatch, uid '%s' not at index '%u', got '%s' instead (removing)\n", + finfo->uid, id, camel_message_info_uid(info)); + + camel_folder_change_info_remove_uid(sdata->folder->changes, camel_message_info_uid(info)); + camel_folder_summary_remove(summary, info); + camel_folder_summary_info_free(summary, info); + info = camel_folder_summary_index(summary, id-1); + } + } else { + printf("got info for unknown message %u\n", id); + } + } + + if (info) { + if (finfo->got & FETCH_MINFO) { + /* if we only use ENVELOPE? */ + camel_message_info_set_subject(info, g_strdup(camel_message_info_subject(finfo->minfo))); + camel_message_info_set_from(info, g_strdup(camel_message_info_from(finfo->minfo))); + camel_message_info_set_to(info, g_strdup(camel_message_info_to(finfo->minfo))); + camel_message_info_set_cc(info, g_strdup(camel_message_info_cc(finfo->minfo))); + info->date_sent = finfo->minfo->date_sent; + camel_folder_change_info_add_uid(sdata->folder->changes, camel_message_info_uid(info)); + printf("adding change info uid '%s'\n", camel_message_info_uid(info)); + } + + if (finfo->got & FETCH_FLAGS) { + if ((info->flags & CAMEL_IMAPP_SERVER_FLAGS) != (finfo->flags & CAMEL_IMAPP_SERVER_FLAGS)) { + camel_folder_change_info_change_uid(sdata->folder->changes, camel_message_info_uid(info)); + info->flags = (info->flags & ~(CAMEL_IMAPP_SERVER_FLAGS)) | (finfo->flags & CAMEL_IMAPP_SERVER_FLAGS); + camel_folder_summary_touch(summary); + } + ((CamelIMAPPMessageInfo *)info)->server_flags = finfo->flags & CAMEL_IMAPP_SERVER_FLAGS; + } + + if ((finfo->got & (FETCH_BODY|FETCH_UID)) == (FETCH_BODY|FETCH_UID)) { + struct _fetch_data *fd, *fn; + + fd = (struct _fetch_data *)sdata->body_fetch.head; + fn = fd->next; + while (fn) { + if (!strcmp(finfo->uid, fd->uid) && !strcmp(finfo->section, fd->section)) { + if (fd->data) + camel_object_unref(fd->data); + fd->data = finfo->body; + camel_object_ref(fd->data); + e_dlist_remove((EDListNode *)fd); + e_dlist_addtail(&sdata->body_fetch_done, (EDListNode *)fd); + break; + } + fd = fn; + fn = fn->next; + } + } + + camel_folder_summary_info_free(summary, info); + } else { + printf("dont know what to do with message\n"); + } + done: + imap_free_fetch(finfo); + + return camel_imapp_engine_skip(ie); +} |