experimental, non-working imap implementation

svn path=/trunk/; revision=22061
This commit is contained in:
Michael Zucci
2003-08-01 21:07:43 +00:00
parent 330ecafed4
commit e2cd78ca9b
22 changed files with 7458 additions and 0 deletions

View File

@ -0,0 +1,46 @@
## Process this file with automake to produce Makefile.in
libcamelimappincludedir = $(privincludedir)/camel
camel_provider_LTLIBRARIES = libcamelimapp.la
camel_provider_DATA = libcamelimapp.urls
INCLUDES = -I.. \
-I$(srcdir)/.. \
-I$(top_srcdir)/camel \
-I$(top_srcdir)/intl \
-I$(top_srcdir)/e-util \
-I$(top_srcdir) \
$(CAMEL_CFLAGS) \
$(GNOME_INCLUDEDIR) \
$(GTK_INCLUDEDIR) \
-DG_LOG_DOMAIN=\"camel-imapp-provider\" \
-DG_DISABLE_DEPRECATED
libcamelimapp_la_SOURCES = \
camel-imapp-utils.c \
camel-imapp-engine.c \
camel-imapp-stream.c \
camel-imapp-store.c \
camel-imapp-folder.c \
camel-imapp-provider.c \
camel-imapp-store-summary.c \
camel-imapp-driver.c \
camel-imapp-summary.c
libcamelimappinclude_HEADERS = \
camel-imapp-utils.h \
camel-imapp-engine.h \
camel-imapp-stream.h \
camel-imapp-store.h \
camel-imapp-folder.h \
camel-imapp-store-summary.h \
camel-imapp-driver.h \
camel-imapp-summary.h
libcamelimapp_la_LDFLAGS = -avoid-version -module
#noinst_HEADERS = \
# camel-imap-private.h
EXTRA_DIST = libcamelimapp.urls

View File

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

View File

@ -0,0 +1,81 @@
#ifndef _CAMEL_IMAPP_DRIVER_H
#define _CAMEL_IMAPP_DRIVER_H
#include <camel/camel-object.h>
#include "camel-imapp-stream.h"
#include <e-util/e-msgport.h>
#define CAMEL_IMAPP_DRIVER_TYPE (camel_imapp_driver_get_type ())
#define CAMEL_IMAPP_DRIVER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_DRIVER_TYPE, CamelIMAPPDriver))
#define CAMEL_IMAPP_DRIVER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_DRIVER_TYPE, CamelIMAPPDriverClass))
#define CAMEL_IS_IMAP_DRIVER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_DRIVER_TYPE))
typedef struct _CamelIMAPPDriver CamelIMAPPDriver;
typedef struct _CamelIMAPPDriverClass CamelIMAPPDriverClass;
typedef int (*CamelIMAPPDriverFunc)(struct _CamelIMAPPDriver *driver, void *data);
typedef struct _CamelSasl * (*CamelIMAPPSASLFunc)(struct _CamelIMAPPDriver *driver, void *data);
typedef void (*CamelIMAPPLoginFunc)(struct _CamelIMAPPDriver *driver, char **login, char **pass, void *data);
struct _CamelMimeMessage;
struct _CamelIMAPPDriver {
CamelObject parent_object;
struct _CamelIMAPPEngine *engine;
struct _CamelIMAPPFolder *folder;
/* current folder stuff */
GPtrArray *summary;
guint32 uidvalidity;
guint32 exists;
guint32 recent;
guint32 unseen;
guint32 permanentflags;
/* list stuff */
GPtrArray *list_result;
GSList *list_commands;
guint32 list_flags;
/* sem_t list_sem; for controlled access to list variables */
/* this is so the node is always in a list - easier exception management */
EDList body_fetch;
EDList body_fetch_done;
/* factory to get an appropriate sasl mech */
CamelIMAPPSASLFunc get_sasl;
void *get_sasl_data;
/* callbacks, get login username/pass */
CamelIMAPPLoginFunc get_login;
void *get_login_data;
};
struct _CamelIMAPPDriverClass {
CamelObjectClass parent_class;
};
CamelType camel_imapp_driver_get_type (void);
CamelIMAPPDriver * camel_imapp_driver_new(CamelIMAPPStream *stream);
void camel_imapp_driver_set_sasl_factory(CamelIMAPPDriver *id, CamelIMAPPSASLFunc get_sasl, void *sasl_data);
void camel_imapp_driver_set_login_query(CamelIMAPPDriver *id, CamelIMAPPLoginFunc get_login, void *login_data);
void camel_imapp_driver_login(CamelIMAPPDriver *id);
void camel_imapp_driver_select(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder);
void camel_imapp_driver_update(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder);
void camel_imapp_driver_sync(CamelIMAPPDriver *id, gboolean expunge, struct _CamelIMAPPFolder *folder);
struct _CamelStream * camel_imapp_driver_fetch(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder, const char *uid, const char *body);
GPtrArray * camel_imapp_driver_list(CamelIMAPPDriver *id, const char *name, guint32 flags);
struct _CamelStream *camel_imapp_driver_get(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder, const char *uid);
void camel_imapp_driver_append(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder, struct _CamelDataWrapper *);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,154 @@
#ifndef _CAMEL_IMAPP_ENGINE_H
#define _CAMEL_IMAPP_ENGINE_H
#include <camel/camel-object.h>
#include "camel-imapp-stream.h"
#include <e-util/e-msgport.h>
#include "camel-imapp-folder.h"
#define CAMEL_IMAPP_ENGINE_TYPE (camel_imapp_engine_get_type ())
#define CAMEL_IMAPP_ENGINE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_ENGINE_TYPE, CamelIMAPPEngine))
#define CAMEL_IMAPP_ENGINE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_ENGINE_TYPE, CamelIMAPPEngineClass))
#define CAMEL_IS_IMAP_ENGINE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_ENGINE_TYPE))
typedef struct _CamelIMAPPEngine CamelIMAPPEngine;
typedef struct _CamelIMAPPEngineClass CamelIMAPPEngineClass;
typedef struct _CamelIMAPPCommandPart CamelIMAPPCommandPart;
typedef struct _CamelIMAPPCommand CamelIMAPPCommand;
typedef enum {
CAMEL_IMAPP_COMMAND_SIMPLE = 0,
CAMEL_IMAPP_COMMAND_DATAWRAPPER,
CAMEL_IMAPP_COMMAND_STREAM,
CAMEL_IMAPP_COMMAND_AUTH,
CAMEL_IMAPP_COMMAND_MASK = 0xff,
CAMEL_IMAPP_COMMAND_CONTINUATION = 0x8000 /* does this command expect continuation? */
} camel_imapp_command_part_t;
struct _CamelIMAPPCommandPart {
struct _CamelIMAPPCommandPart *next;
struct _CamelIMAPPCommandPart *prev;
struct _CamelIMAPPCommand *parent;
int data_size;
char *data;
camel_imapp_command_part_t type;
int ob_size;
CamelObject *ob;
};
typedef int (*CamelIMAPPEngineFunc)(struct _CamelIMAPPEngine *engine, guint32 id, void *data);
typedef void (*CamelIMAPPCommandFunc)(struct _CamelIMAPPEngine *engine, struct _CamelIMAPPCommand *, void *data);
/* FIXME: make this refcounted */
struct _CamelIMAPPCommand {
struct _CamelIMAPPCommand *next;
struct _CamelIMAPPCommand *prev;
const char *name; /* command name/type (e.g. FETCH) */
/* FIXME: remove this select stuff */
char *select; /* if we need to run against a specific folder */
struct _status_info *status; /* status for command, indicates it is complete if != NULL */
unsigned int tag;
struct _CamelStreamMem *mem; /* for building the part */
EDList parts;
CamelIMAPPCommandPart *current;
CamelIMAPPCommandFunc complete;
void *complete_data;
};
typedef struct _CamelIMAPPSelectResponse CamelIMAPPSelectResponse;
struct _CamelIMAPPSelectResponse {
struct _status_info *status;
guint32 exists;
guint32 recent;
guint32 uidvalidity;
guint32 unseen;
guint32 permanentflags;
};
enum {
IMAP_CAPABILITY_IMAP4 = (1 << 0),
IMAP_CAPABILITY_IMAP4REV1 = (1 << 1),
IMAP_CAPABILITY_STATUS = (1 << 2),
IMAP_CAPABILITY_NAMESPACE = (1 << 3),
IMAP_CAPABILITY_UIDPLUS = (1 << 4),
IMAP_CAPABILITY_LITERALPLUS = (1 << 5),
IMAP_CAPABILITY_STARTTLS = (1 << 6),
};
/* currently selected states */
typedef enum _camel_imapp_engine_state_t {
IMAP_ENGINE_DISCONNECT, /* only happens during shutdown */
IMAP_ENGINE_CONNECT, /* connected, not authenticated */
IMAP_ENGINE_AUTH, /* connected, and authenticated */
IMAP_ENGINE_SELECT, /* and selected, select holds selected folder */
} camel_imapp_engine_state_t;
struct _CamelIMAPPEngine {
CamelObject parent_object;
CamelIMAPPStream *stream;
camel_imapp_engine_state_t state;
guint32 capa; /* capabilities for this server, refresh with :capabilities() */
GHashTable *handlers;
unsigned char tagprefix; /* out tag prefix 'A' 'B' ... 'Z' */
unsigned int tag; /* next command tag */
char *select; /* *currently* selected folder */
char *last_select; /* last selected or to-be selected folder (e.g. outstanding queued select) */
CamelIMAPPCommand *literal;/* current literal op */
EDList active; /* active queue */
EDList queue; /* outstanding queue */
/* keep track of running a select */
struct _CamelIMAPPSelectResponse *select_response;
};
struct _CamelIMAPPEngineClass {
CamelObjectClass parent_class;
unsigned char tagprefix;
/* Events:
status(struct _status_info *);
*/
};
CamelType camel_imapp_engine_get_type (void);
CamelIMAPPEngine *camel_imapp_engine_new(CamelIMAPPStream *stream);
void camel_imapp_engine_add_handler(CamelIMAPPEngine *imap, const char *response, CamelIMAPPEngineFunc func, void *data);
int camel_imapp_engine_iterate(CamelIMAPPEngine *imap, CamelIMAPPCommand *wait); /* throws PARSE,IO exception */
int camel_imapp_engine_skip(CamelIMAPPEngine *imap);
int camel_imapp_engine_capabilities(CamelIMAPPEngine *imap);
CamelIMAPPCommand *camel_imapp_engine_command_new (CamelIMAPPEngine *imap, const char *name, const char *select, const char *fmt, ...);
void camel_imapp_engine_command_complete(CamelIMAPPEngine *imap, struct _CamelIMAPPCommand *, CamelIMAPPCommandFunc func, void *data);
void camel_imapp_engine_command_add (CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, const char *fmt, ...);
void camel_imapp_engine_command_free (CamelIMAPPEngine *imap, CamelIMAPPCommand *ic);
void camel_imapp_engine_command_queue(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic); /* throws IO exception */
CamelIMAPPCommand *camel_imapp_engine_command_find (CamelIMAPPEngine *imap, const char *name);
CamelIMAPPCommand *camel_imapp_engine_command_find_tag(CamelIMAPPEngine *imap, unsigned int tag);
/* util functions */
CamelIMAPPSelectResponse *camel_imapp_engine_select(CamelIMAPPEngine *imap, const char *name);
void camel_imapp_engine_select_free(CamelIMAPPEngine *imap, CamelIMAPPSelectResponse *select);
#endif

View File

@ -0,0 +1,35 @@
/* This implements 'real' exceptions that work a bit like c++/java exceptions */
/* Still experimental code */
#ifndef __CAMEL_IMAPP_EXCEPTION_H
#define __CAMEL_IMAPP_EXCEPTION_H
#include <setjmp.h>
#include "camel/camel-exception.h"
struct _CamelExceptionEnv {
struct _CamelExceptionEnv *parent;
CamelException *ex;
jmp_buf env;
};
#define CAMEL_TRY { struct _CamelExceptionEnv __env; camel_exception_try(&__env); if (setjmp(__env.env) == 0)
#define CAMEL_IGNORE camel_exception_done(&__env); }
#define CAMEL_CATCH(x) { CamelException *x; x=__env.ex; if (x != NULL)
#define CAMEL_DONE } camel_exception_done(&__env); }
#define CAMEL_DROP() camel_exception_drop(&__env)
void camel_exception_setup(void);
/* internal functions, use macro's above */
void camel_exception_try(struct _CamelExceptionEnv *env);
void camel_exception_done(struct _CamelExceptionEnv *env);
void camel_exception_drop(struct _CamelExceptionEnv *env);
/* user functions */
void camel_exception_throw_ex(CamelException *ex) __attribute__ ((noreturn));
void camel_exception_throw(int id, char *fmt, ...) __attribute__ ((noreturn));
#endif

View File

@ -0,0 +1,183 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*-
*
* Author:
* Michael Zucchi <notzed@ximian.com>
*
* Copyright 1999, 2000 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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <glib.h>
#include <camel/camel-stream-mem.h>
#include "camel-imapp-stream.h"
#include "camel-imapp-exception.h"
#define t(x)
#define io(x) x
static CamelObjectClass *parent_class = NULL;
/* Returns the class for a CamelStream */
#define CS_CLASS(so) CAMEL_IMAPP_FETCH_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so))
static ssize_t
stream_read(CamelStream *stream, char *buffer, size_t n)
{
CamelIMAPPFetchStream *is = (CamelIMAPPFetchStream *)stream;
ssize_t max;
/* make sure we have all the data read in */
while (camel_imapp_engine_iterate(is->engine, is->command)>0)
;
if (is->literal == 0 || n == 0)
return 0;
max = is->end - is->ptr;
if (max > 0) {
max = MIN(max, is->literal);
max = MIN(max, n);
memcpy(buffer, is->ptr, max);
is->ptr += max;
} else {
max = MIN(is->literal, n);
max = camel_stream_read(is->source, buffer, max);
if (max <= 0)
return max;
}
is->literal -= max;
return max;
}
static ssize_t
stream_write(CamelStream *stream, const char *buffer, size_t n)
{
CamelIMAPPFetchStream *is = (CamelIMAPPFetchStream *)stream;
return camel_stream_write(is->source, buffer, n);
}
static int
stream_close(CamelStream *stream)
{
/* nop? */
return 0;
}
static int
stream_flush(CamelStream *stream)
{
/* nop? */
return 0;
}
static gboolean
stream_eos(CamelStream *stream)
{
CamelIMAPPFetchStream *is = (CamelIMAPPFetchStream *)stream;
return is->literal == 0;
}
static int
stream_reset(CamelStream *stream)
{
/* nop? reset literal mode? */
return 0;
}
static void
camel_imapp_fetch_stream_class_init (CamelStreamClass *camel_imapp_fetch_stream_class)
{
CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_imapp_fetch_stream_class;
parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE );
/* virtual method definition */
camel_stream_class->read = stream_read;
camel_stream_class->write = stream_write;
camel_stream_class->close = stream_close;
camel_stream_class->flush = stream_flush;
camel_stream_class->eos = stream_eos;
camel_stream_class->reset = stream_reset;
}
static void
camel_imapp_fetch_stream_init(CamelIMAPPFetchStream *is, CamelIMAPPFetchStreamClass *isclass)
{
;
}
static void
camel_imapp_fetch_stream_finalise(CamelIMAPPFetchStream *is)
{
if (is->engine)
camel_object_unref(is->engine);
}
CamelType
camel_imapp_fetch_stream_get_type (void)
{
static CamelType camel_imapp_fetch_stream_type = CAMEL_INVALID_TYPE;
if (camel_imapp_fetch_stream_type == CAMEL_INVALID_TYPE) {
setup_table();
camel_imapp_fetch_stream_type = camel_type_register( camel_stream_get_type(),
"CamelIMAPPFetchStream",
sizeof( CamelIMAPPFetchStream ),
sizeof( CamelIMAPPFetchStreamClass ),
(CamelObjectClassInitFunc) camel_imapp_fetch_stream_class_init,
NULL,
(CamelObjectInitFunc) camel_imapp_fetch_stream_init,
(CamelObjectFinalizeFunc) camel_imapp_fetch_stream_finalise );
}
return camel_imapp_fetch_stream_type;
}
/**
* camel_imapp_fetch_stream_new:
*
* Return value: the stream
**/
CamelStream *
camel_imapp_fetch_stream_new(CamelIMAPPEngine *ie, const char *uid, const char *body)
{
CamelIMAPPFetchStream *is;
is = (CamelIMAPPFetchStream *)camel_object_new(camel_imapp_fetch_stream_get_type ());
is->engine = ie;
camel_object_ref(ie);
is->command = camel_imapp_engine_command_new(ie, "FETCH", NULL, "FETCH %t (BODY[%t]<0.4096>", uid, body);
camel_imapp_engine_command_queue(ie, command);
return (CamelStream *)is;
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2000 Ximian Inc.
*
* Authors: Michael Zucchi <notzed@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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _CAMEL_IMAPP_FETCH_STREAM_H
#define _CAMEL_IMAPP_FETCH_STREAM_H
#include <camel/camel-stream.h>
#define CAMEL_IMAPP_FETCH_STREAM(obj) CAMEL_CHECK_CAST (obj, camel_imapp_fetch_stream_get_type (), CamelIMAPPFetchStream)
#define CAMEL_IMAPP_FETCH_STREAM_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_fetch_stream_get_type (), CamelIMAPPFetchStreamClass)
#define CAMEL_IS_IMAP_FETCH_STREAM(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_fetch_stream_get_type ())
typedef struct _CamelIMAPPFetchStreamClass CamelIMAPPFetchStreamClass;
typedef struct _CamelIMAPPFetchStream CamelIMAPPFetchStream;
struct _CamelIMAPPFetchStream {
CamelStream parent;
struct _CamelIMAPPEngine *engine;
};
struct _CamelIMAPPFetchStreamClass {
CamelStreamClass parent_class;
};
CamelType camel_imapp_fetch_stream_get_type (void);
CamelStream *camel_imapp_fetch_stream_new (struct _CamelIMAPPEngine *src, const char *uid, const char *spec);
#endif /* ! _CAMEL_IMAPP_FETCH_STREAM_H */

View File

@ -0,0 +1,268 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-folder.c : class for a imap folder */
/*
* Authors: Michael Zucchi <notzed@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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include "camel/camel-exception.h"
#include "camel/camel-stream-mem.h"
#include "camel/camel-stream-filter.h"
#include "camel/camel-mime-message.h"
#include "camel/camel-operation.h"
#include "camel/camel-data-cache.h"
#include "camel/camel-session.h"
#include "camel-imapp-store.h"
#include "camel-imapp-folder.h"
#include "camel-imapp-summary.h"
#include "camel-imapp-exception.h"
#include <e-util/md5-utils.h>
#include <stdlib.h>
#include <string.h>
#define d(x)
#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o)))
static CamelFolderClass *parent_class;
static void imap_finalize (CamelObject *object);
static void imap_refresh_info (CamelFolder *folder, CamelException *ex);
static void imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex);
static CamelMimeMessage *imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex);
static void
imap_folder_class_init (CamelIMAPPFolderClass *camel_imapp_folder_class)
{
CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_imapp_folder_class);
parent_class = CAMEL_FOLDER_CLASS(camel_folder_get_type());
/* virtual method overload */
camel_folder_class->refresh_info = imap_refresh_info;
camel_folder_class->sync = imap_sync;
camel_folder_class->get_message = imap_get_message;
/*camel_folder_class->set_message_flags = imap_set_message_flags;*/
}
static void
imap_folder_init(CamelObject *o, CamelObjectClass *klass)
{
CamelFolder *folder = (CamelFolder *)o;
CamelIMAPPFolder *ifolder = (CamelIMAPPFolder *)o;
folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY |
CAMEL_FOLDER_HAS_SEARCH_CAPABILITY);
folder->permanent_flags = CAMEL_MESSAGE_ANSWERED |
CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT |
CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_USER;
/* FIXME: this is just a skeleton */
ifolder->changes = camel_folder_change_info_new();
}
CamelType
camel_imapp_folder_get_type (void)
{
static CamelType camel_imapp_folder_type = CAMEL_INVALID_TYPE;
if (!camel_imapp_folder_type) {
camel_imapp_folder_type = camel_type_register (CAMEL_FOLDER_TYPE, "CamelIMAPPFolder",
sizeof (CamelIMAPPFolder),
sizeof (CamelIMAPPFolderClass),
(CamelObjectClassInitFunc) imap_folder_class_init,
NULL,
imap_folder_init,
(CamelObjectFinalizeFunc) imap_finalize);
}
return camel_imapp_folder_type;
}
void
imap_finalize (CamelObject *object)
{
CamelIMAPPFolder *folder = (CamelIMAPPFolder *)object;
camel_folder_change_info_free(folder->changes);
}
CamelFolder *
camel_imapp_folder_new(CamelStore *store, const char *path)
{
CamelFolder *folder;
char *root;
d(printf("opening imap folder '%s'\n", path));
folder = CAMEL_FOLDER (camel_object_new (CAMEL_IMAPP_FOLDER_TYPE));
camel_folder_construct(folder, store, path, path);
((CamelIMAPPFolder *)folder)->raw_name = g_strdup(path);
folder->summary = camel_imapp_summary_new();
root = camel_session_get_storage_path(((CamelService *)store)->session, (CamelService *)store, NULL);
if (root) {
char *base = g_build_filename(root, path, NULL);
char *file = g_build_filename(base, ".ev-summary", NULL);
camel_mkdir(base, 0777);
g_free(base);
camel_folder_summary_set_filename(folder->summary, file);
printf("loading summary from '%s' (root=%s)\n", file, root);
g_free(file);
camel_folder_summary_load(folder->summary);
g_free(root);
}
return folder;
}
void
camel_imapp_folder_open(CamelIMAPPFolder *folder, CamelException *ex)
{
/* */
}
void
camel_imapp_folder_delete(CamelIMAPPFolder *folder, CamelException *ex)
{
}
void
camel_imapp_folder_rename(CamelIMAPPFolder *folder, const char *new, CamelException *ex)
{
}
void
camel_imapp_folder_close(CamelIMAPPFolder *folder, CamelException *ex)
{
}
static void
imap_refresh_info (CamelFolder *folder, CamelException *ex)
{
printf("imapp refresh info?\n");
}
static void
imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
{
camel_imapp_driver_sync(((CamelIMAPPStore *)(folder->parent_store))->driver, expunge, folder);
}
static CamelMimeMessage *
imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
{
CamelMimeMessage * volatile msg = NULL;
CamelStream * volatile stream = NULL;
printf("get message '%s'\n", uid);
CAMEL_TRY {
/* simple implementation, just get whole message in 1 go */
stream = camel_imapp_driver_fetch(((CamelIMAPPStore *)(folder->parent_store))->driver, (CamelIMAPPFolder *)folder, uid, "");
camel_stream_reset(stream);
msg = camel_mime_message_new();
if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)msg, stream) != -1) {
/* do we care? */
}
} CAMEL_CATCH(e) {
if (msg)
camel_object_unref(msg);
msg = NULL;
camel_exception_xfer(ex, e);
} CAMEL_DONE;
if (stream)
camel_object_unref(stream);
return msg;
}
/* Algorithm for selecting a folder:
- If uidvalidity == old uidvalidity
and exsists == old exists
and recent == old recent
and unseen == old unseen
Assume our summary is correct
for each summary item
mark the summary item as 'old/not updated'
rof
fetch flags from 1:*
for each fetch response
info = summary[index]
if info.uid != uid
info = summary_by_uid[uid]
fi
if info == NULL
create new info @ index
fi
if got.flags
update flags
fi
if got.header
update based on header
mark as retrieved
else if got.body
update based on imap body
mark as retrieved
fi
Async fetch response:
info = summary[index]
if info == null
if uid == null
force resync/select?
info = empty @ index
else if uid && info.uid != uid
force a resync?
return
fi
if got.flags {
info.flags = flags
}
if got.header {
info.init(header)
info.empty = false
}
info.state - 2 bit field in flags
0 = empty, nothing set
1 = uid & flags set
2 = update required
3 = up to date
*/

View File

@ -0,0 +1,66 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-folder.h : Class for a IMAP folder */
/*
* Authors: Michael Zucchi <notzed@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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifndef CAMEL_IMAPP_FOLDER_H
#define CAMEL_IMAPP_FOLDER_H 1
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus }*/
#include <camel/camel-folder.h>
#define CAMEL_IMAPP_FOLDER_TYPE (camel_imapp_folder_get_type ())
#define CAMEL_IMAPP_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_FOLDER_TYPE, CamelIMAPPFolder))
#define CAMEL_IMAPP_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_FOLDER_TYPE, CamelIMAPPFolderClass))
#define CAMEL_IS_IMAP_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_FOLDER_TYPE))
typedef struct _CamelIMAPPFolder {
CamelFolder parent_object;
char *raw_name;
CamelFolderChangeInfo *changes;
guint32 exists;
guint32 recent;
guint32 uidvalidity;
guint32 unseen;
guint32 permanentflags;
} CamelIMAPPFolder;
typedef struct _CamelIMAPPFolderClass {
CamelFolderClass parent_class;
} CamelIMAPPFolderClass;
/* Standard Camel function */
CamelType camel_imapp_folder_get_type (void);
/* public methods */
CamelFolder *camel_imapp_folder_new(CamelStore *parent, const char *path);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CAMEL_IMAPP_FOLDER_H */

View File

@ -0,0 +1,91 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-pop3-provider.c: pop3 provider registration code */
/*
* Authors :
* Dan Winship <danw@ximian.com>
* Michael Zucchi <notzed@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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "camel/camel-provider.h"
#include "camel/camel-session.h"
#include "camel/camel-url.h"
#include "camel/camel-sasl.h"
#include "camel-imapp-store.h"
CamelProviderConfEntry imapp_conf_entries[] = {
{ CAMEL_PROVIDER_CONF_SECTION_START, NULL, NULL,
N_("Message storage") },
{ CAMEL_PROVIDER_CONF_SECTION_END },
{ CAMEL_PROVIDER_CONF_END }
};
static CamelProvider imapp_provider = {
"imapp",
N_("IMAP+"),
N_("Experimental IMAP 4(.1) client\n"
"This is untested and unsupported code, you want to use plain imap instead.\n\n"
" !!! DO NOT USE THIS FOR PRODUCTION EMAIL !!!\n"),
"mail",
CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE |
CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL,
CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH,
imapp_conf_entries,
/* ... */
};
CamelServiceAuthType camel_imapp_password_authtype = {
N_("Password"),
N_("This option will connect to the IMAP server using a "
"plaintext password."),
"",
TRUE
};
void
camel_imapp_module_init(CamelSession *session)
{
imapp_provider.object_types[CAMEL_PROVIDER_STORE] = camel_imapp_store_get_type();
imapp_provider.url_hash = camel_url_hash;
imapp_provider.url_equal = camel_url_equal;
imapp_provider.authtypes = g_list_prepend(imapp_provider.authtypes, camel_sasl_authtype_list(FALSE));
imapp_provider.authtypes = g_list_prepend(imapp_provider.authtypes, &camel_imapp_password_authtype);
camel_session_register_provider(session, &imapp_provider);
}
void
camel_provider_module_init(CamelSession *session)
{
camel_imapp_module_init(session);
}

View File

@ -0,0 +1,616 @@
/*
* Copyright (C) 2002 Ximian Inc.
*
* Authors: Michael Zucchi <notzed@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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "camel-imapp-store-summary.h"
#include "camel/camel-file-utils.h"
#include "camel-string-utils.h"
#include "e-util/md5-utils.h"
#include "e-util/e-memory.h"
#include "camel-private.h"
#include "camel-utf8.h"
#define d(x)
#define io(x) /* io debug */
#define CAMEL_IMAPP_STORE_SUMMARY_VERSION_0 (0)
#define CAMEL_IMAPP_STORE_SUMMARY_VERSION (0)
#define _PRIVATE(o) (((CamelIMAPPStoreSummary *)(o))->priv)
static int summary_header_load(CamelStoreSummary *, FILE *);
static int summary_header_save(CamelStoreSummary *, FILE *);
/*static CamelStoreInfo * store_info_new(CamelStoreSummary *, const char *);*/
static CamelStoreInfo * store_info_load(CamelStoreSummary *, FILE *);
static int store_info_save(CamelStoreSummary *, FILE *, CamelStoreInfo *);
static void store_info_free(CamelStoreSummary *, CamelStoreInfo *);
static const char *store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int);
static void store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int, const char *);
static void camel_imapp_store_summary_class_init (CamelIMAPPStoreSummaryClass *klass);
static void camel_imapp_store_summary_init (CamelIMAPPStoreSummary *obj);
static void camel_imapp_store_summary_finalise (CamelObject *obj);
static CamelStoreSummaryClass *camel_imapp_store_summary_parent;
static void
camel_imapp_store_summary_class_init (CamelIMAPPStoreSummaryClass *klass)
{
CamelStoreSummaryClass *ssklass = (CamelStoreSummaryClass *)klass;
ssklass->summary_header_load = summary_header_load;
ssklass->summary_header_save = summary_header_save;
/*ssklass->store_info_new = store_info_new;*/
ssklass->store_info_load = store_info_load;
ssklass->store_info_save = store_info_save;
ssklass->store_info_free = store_info_free;
ssklass->store_info_string = store_info_string;
ssklass->store_info_set_string = store_info_set_string;
}
static void
camel_imapp_store_summary_init (CamelIMAPPStoreSummary *s)
{
/*struct _CamelIMAPPStoreSummaryPrivate *p;
p = _PRIVATE(s) = g_malloc0(sizeof(*p));*/
((CamelStoreSummary *)s)->store_info_size = sizeof(CamelIMAPPStoreInfo);
s->version = CAMEL_IMAPP_STORE_SUMMARY_VERSION;
}
static void
camel_imapp_store_summary_finalise (CamelObject *obj)
{
/*struct _CamelIMAPPStoreSummaryPrivate *p;*/
/*CamelIMAPPStoreSummary *s = (CamelIMAPPStoreSummary *)obj;*/
/*p = _PRIVATE(obj);
g_free(p);*/
}
CamelType
camel_imapp_store_summary_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
if (type == CAMEL_INVALID_TYPE) {
camel_imapp_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type();
type = camel_type_register((CamelType)camel_imapp_store_summary_parent, "CamelIMAPPStoreSummary",
sizeof (CamelIMAPPStoreSummary),
sizeof (CamelIMAPPStoreSummaryClass),
(CamelObjectClassInitFunc) camel_imapp_store_summary_class_init,
NULL,
(CamelObjectInitFunc) camel_imapp_store_summary_init,
(CamelObjectFinalizeFunc) camel_imapp_store_summary_finalise);
}
return type;
}
/**
* camel_imapp_store_summary_new:
*
* Create a new CamelIMAPPStoreSummary object.
*
* Return value: A new CamelIMAPPStoreSummary widget.
**/
CamelIMAPPStoreSummary *
camel_imapp_store_summary_new (void)
{
CamelIMAPPStoreSummary *new = CAMEL_IMAPP_STORE_SUMMARY ( camel_object_new (camel_imapp_store_summary_get_type ()));
return new;
}
/**
* camel_imapp_store_summary_full_name:
* @s:
* @path:
*
* Retrieve a summary item by full name.
*
* A referenced to the summary item is returned, which may be
* ref'd or free'd as appropriate.
*
* Return value: The summary item, or NULL if the @full_name name
* is not available.
* It must be freed using camel_store_summary_info_free().
**/
CamelIMAPPStoreInfo *
camel_imapp_store_summary_full_name(CamelIMAPPStoreSummary *s, const char *full_name)
{
int count, i;
CamelIMAPPStoreInfo *info;
count = camel_store_summary_count((CamelStoreSummary *)s);
for (i=0;i<count;i++) {
info = (CamelIMAPPStoreInfo *)camel_store_summary_index((CamelStoreSummary *)s, i);
if (info) {
if (strcmp(info->full_name, full_name) == 0)
return info;
camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info);
}
}
return NULL;
}
char *
camel_imapp_store_summary_full_to_path(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep)
{
char *path, *p;
int c;
const char *f;
if (dir_sep != '/') {
p = path = alloca(strlen(full_name)*3+1);
f = full_name;
while ( (c = *f++ & 0xff) ) {
if (c == dir_sep)
*p++ = '/';
else if (c == '/' || c == '%')
p += sprintf(p, "%%%02X", c);
else
*p++ = c;
}
*p = 0;
} else
path = (char *)full_name;
return camel_utf7_utf8(path);
}
static guint32 hexnib(guint32 c)
{
if (c >= '0' && c <= '9')
return c-'0';
else if (c>='A' && c <= 'Z')
return c-'A'+10;
else
return 0;
}
char *
camel_imapp_store_summary_path_to_full(CamelIMAPPStoreSummary *s, const char *path, char dir_sep)
{
unsigned char *full, *f;
guint32 c, v = 0;
const char *p;
int state=0;
char *subpath, *last = NULL;
CamelStoreInfo *si;
CamelIMAPPStoreNamespace *ns;
/* check to see if we have a subpath of path already defined */
subpath = alloca(strlen(path)+1);
strcpy(subpath, path);
do {
si = camel_store_summary_path((CamelStoreSummary *)s, subpath);
if (si == NULL) {
last = strrchr(subpath, '/');
if (last)
*last = 0;
}
} while (si == NULL && last);
/* path is already present, use the raw version we have */
if (si && strlen(subpath) == strlen(path)) {
f = g_strdup(camel_imapp_store_info_full_name(s, si));
camel_store_summary_info_free((CamelStoreSummary *)s, si);
return f;
}
ns = camel_imapp_store_summary_namespace_find_path(s, path);
f = full = alloca(strlen(path)*2+1);
if (si)
p = path + strlen(subpath);
else if (ns)
p = path + strlen(ns->path);
else
p = path;
while ( (c = camel_utf8_getc((const unsigned char **)&p)) ) {
switch(state) {
case 0:
if (c == '%')
state = 1;
else {
if (c == '/')
c = dir_sep;
camel_utf8_putc(&f, c);
}
break;
case 1:
state = 2;
v = hexnib(c)<<4;
break;
case 2:
state = 0;
v |= hexnib(c);
camel_utf8_putc(&f, v);
break;
}
}
camel_utf8_putc(&f, c);
/* merge old path part if required */
f = camel_utf8_utf7(full);
if (si) {
full = g_strdup_printf("%s%s", camel_imapp_store_info_full_name(s, si), f);
g_free(f);
camel_store_summary_info_free((CamelStoreSummary *)s, si);
f = full;
} else if (ns) {
full = g_strdup_printf("%s%s", ns->full_name, f);
g_free(f);
f = full;
}
return f;
}
CamelIMAPPStoreInfo *
camel_imapp_store_summary_add_from_full(CamelIMAPPStoreSummary *s, const char *full, char dir_sep)
{
CamelIMAPPStoreInfo *info;
char *pathu8, *prefix;
int len;
char *full_name;
CamelIMAPPStoreNamespace *ns;
d(printf("adding full name '%s' '%c'\n", full, dir_sep));
len = strlen(full);
full_name = alloca(len+1);
strcpy(full_name, full);
if (full_name[len-1] == dir_sep)
full_name[len-1] = 0;
info = camel_imapp_store_summary_full_name(s, full_name);
if (info) {
camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info);
d(printf(" already there\n"));
return info;
}
ns = camel_imapp_store_summary_namespace_find_full(s, full_name);
if (ns) {
d(printf("(found namespace for '%s' ns '%s') ", full_name, ns->path));
len = strlen(ns->full_name);
if (len >= strlen(full_name)) {
pathu8 = g_strdup(ns->path);
} else {
if (full_name[len] == ns->sep)
len++;
prefix = camel_imapp_store_summary_full_to_path(s, full_name+len, ns->sep);
if (*ns->path) {
pathu8 = g_strdup_printf ("%s/%s", ns->path, prefix);
g_free (prefix);
} else {
pathu8 = prefix;
}
}
d(printf(" (pathu8 = '%s')", pathu8));
} else {
d(printf("(Cannot find namespace for '%s')\n", full_name));
pathu8 = camel_imapp_store_summary_full_to_path(s, full_name, dir_sep);
}
info = (CamelIMAPPStoreInfo *)camel_store_summary_add_from_path((CamelStoreSummary *)s, pathu8);
if (info) {
d(printf(" '%s' -> '%s'\n", pathu8, full_name));
camel_store_info_set_string((CamelStoreSummary *)s, (CamelStoreInfo *)info, CAMEL_IMAPP_STORE_INFO_FULL_NAME, full_name);
} else
d(printf(" failed\n"));
return info;
}
/* should this be const? */
/* TODO: deprecate/merge this function with path_to_full */
char *
camel_imapp_store_summary_full_from_path(CamelIMAPPStoreSummary *s, const char *path)
{
CamelIMAPPStoreNamespace *ns;
char *name = NULL;
ns = camel_imapp_store_summary_namespace_find_path(s, path);
if (ns)
name = camel_imapp_store_summary_path_to_full(s, path, ns->sep);
d(printf("looking up path %s -> %s\n", path, name?name:"not found"));
return name;
}
/* TODO: this api needs some more work */
CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_new(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep)
{
CamelIMAPPStoreNamespace *ns;
char *p;
int len;
ns = g_malloc0(sizeof(*ns));
ns->full_name = g_strdup(full_name);
len = strlen(ns->full_name)-1;
if (len >= 0 && ns->full_name[len] == dir_sep)
ns->full_name[len] = 0;
ns->sep = dir_sep;
p = ns->path = camel_imapp_store_summary_full_to_path(s, ns->full_name, dir_sep);
while (*p) {
if (*p == '/')
*p = '.';
p++;
}
return ns;
}
void camel_imapp_store_summary_namespace_set(CamelIMAPPStoreSummary *s, CamelIMAPPStoreNamespace *ns)
{
static void namespace_clear(CamelStoreSummary *s);
d(printf("Setting namesapce to '%s' '%c' -> '%s'\n", ns->full_name, ns->sep, ns->path));
namespace_clear((CamelStoreSummary *)s);
s->namespace = ns;
camel_store_summary_touch((CamelStoreSummary *)s);
}
CamelIMAPPStoreNamespace *
camel_imapp_store_summary_namespace_find_path(CamelIMAPPStoreSummary *s, const char *path)
{
int len;
CamelIMAPPStoreNamespace *ns;
/* NB: this currently only compares against 1 namespace, in future compare against others */
ns = s->namespace;
while (ns) {
len = strlen(ns->path);
if (len == 0
|| (strncmp(ns->path, path, len) == 0
&& (path[len] == '/' || path[len] == 0)))
break;
ns = NULL;
}
/* have a default? */
return ns;
}
CamelIMAPPStoreNamespace *
camel_imapp_store_summary_namespace_find_full(CamelIMAPPStoreSummary *s, const char *full)
{
int len;
CamelIMAPPStoreNamespace *ns;
/* NB: this currently only compares against 1 namespace, in future compare against others */
ns = s->namespace;
while (ns) {
len = strlen(ns->full_name);
d(printf("find_full: comparing namespace '%s' to name '%s'\n", ns->full_name, full));
if (len == 0
|| (strncmp(ns->full_name, full, len) == 0
&& (full[len] == ns->sep || full[len] == 0)))
break;
ns = NULL;
}
/* have a default? */
return ns;
}
static void
namespace_free(CamelStoreSummary *s, CamelIMAPPStoreNamespace *ns)
{
g_free(ns->path);
g_free(ns->full_name);
g_free(ns);
}
static void
namespace_clear(CamelStoreSummary *s)
{
CamelIMAPPStoreSummary *is = (CamelIMAPPStoreSummary *)s;
if (is->namespace)
namespace_free(s, is->namespace);
is->namespace = NULL;
}
static CamelIMAPPStoreNamespace *
namespace_load(CamelStoreSummary *s, FILE *in)
{
CamelIMAPPStoreNamespace *ns;
guint32 sep = '/';
ns = g_malloc0(sizeof(*ns));
if (camel_file_util_decode_string(in, &ns->path) == -1
|| camel_file_util_decode_string(in, &ns->full_name) == -1
|| camel_file_util_decode_uint32(in, &sep) == -1) {
namespace_free(s, ns);
ns = NULL;
} else {
ns->sep = sep;
}
return ns;
}
static int
namespace_save(CamelStoreSummary *s, FILE *in, CamelIMAPPStoreNamespace *ns)
{
if (camel_file_util_encode_string(in, ns->path) == -1
|| camel_file_util_encode_string(in, ns->full_name) == -1
|| camel_file_util_encode_uint32(in, (guint32)ns->sep) == -1)
return -1;
return 0;
}
static int
summary_header_load(CamelStoreSummary *s, FILE *in)
{
CamelIMAPPStoreSummary *is = (CamelIMAPPStoreSummary *)s;
gint32 version, capabilities, count;
namespace_clear(s);
if (camel_imapp_store_summary_parent->summary_header_load((CamelStoreSummary *)s, in) == -1
|| camel_file_util_decode_fixed_int32(in, &version) == -1)
return -1;
is->version = version;
if (version < CAMEL_IMAPP_STORE_SUMMARY_VERSION_0) {
g_warning("Store summary header version too low");
return -1;
}
/* note file format can be expanded to contain more namespaces, but only 1 at the moment */
if (camel_file_util_decode_fixed_int32(in, &capabilities) == -1
|| camel_file_util_decode_fixed_int32(in, &count) == -1
|| count > 1)
return -1;
is->capabilities = capabilities;
if (count == 1) {
if ((is->namespace = namespace_load(s, in)) == NULL)
return -1;
}
return 0;
}
static int
summary_header_save(CamelStoreSummary *s, FILE *out)
{
CamelIMAPPStoreSummary *is = (CamelIMAPPStoreSummary *)s;
guint32 count;
count = is->namespace?1:0;
/* always write as latest version */
if (camel_imapp_store_summary_parent->summary_header_save((CamelStoreSummary *)s, out) == -1
|| camel_file_util_encode_fixed_int32(out, CAMEL_IMAPP_STORE_SUMMARY_VERSION) == -1
|| camel_file_util_encode_fixed_int32(out, is->capabilities) == -1
|| camel_file_util_encode_fixed_int32(out, count) == -1)
return -1;
if (is->namespace && namespace_save(s, out, is->namespace) == -1)
return -1;
return 0;
}
static CamelStoreInfo *
store_info_load(CamelStoreSummary *s, FILE *in)
{
CamelIMAPPStoreInfo *mi;
mi = (CamelIMAPPStoreInfo *)camel_imapp_store_summary_parent->store_info_load(s, in);
if (mi) {
if (camel_file_util_decode_string(in, &mi->full_name) == -1) {
camel_store_summary_info_free(s, (CamelStoreInfo *)mi);
mi = NULL;
}
}
return (CamelStoreInfo *)mi;
}
static int
store_info_save(CamelStoreSummary *s, FILE *out, CamelStoreInfo *mi)
{
CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi;
if (camel_imapp_store_summary_parent->store_info_save(s, out, mi) == -1
|| camel_file_util_encode_string(out, isi->full_name) == -1)
return -1;
return 0;
}
static void
store_info_free(CamelStoreSummary *s, CamelStoreInfo *mi)
{
CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi;
g_free(isi->full_name);
camel_imapp_store_summary_parent->store_info_free(s, mi);
}
static const char *
store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type)
{
CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi;
/* FIXME: Locks? */
g_assert (mi != NULL);
switch (type) {
case CAMEL_IMAPP_STORE_INFO_FULL_NAME:
return isi->full_name;
default:
return camel_imapp_store_summary_parent->store_info_string(s, mi, type);
}
}
static void
store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *str)
{
CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi;
g_assert(mi != NULL);
switch(type) {
case CAMEL_IMAPP_STORE_INFO_FULL_NAME:
d(printf("Set full name %s -> %s\n", isi->full_name, str));
CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
g_free(isi->full_name);
isi->full_name = g_strdup(str);
CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
break;
default:
camel_imapp_store_summary_parent->store_info_set_string(s, mi, type, str);
break;
}
}

View File

@ -0,0 +1,102 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2002 Ximian Inc.
*
* Authors: Michael Zucchi <notzed@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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _CAMEL_IMAPP_STORE_SUMMARY_H
#define _CAMEL_IMAPP_STORE_SUMMARY_H
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus */
#include <camel/camel-object.h>
#include <camel/camel-store-summary.h>
#define CAMEL_IMAPP_STORE_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imapp_store_summary_get_type (), CamelIMAPPStoreSummary)
#define CAMEL_IMAPP_STORE_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_store_summary_get_type (), CamelIMAPPStoreSummaryClass)
#define CAMEL_IS_IMAP_STORE_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_store_summary_get_type ())
typedef struct _CamelIMAPPStoreSummary CamelIMAPPStoreSummary;
typedef struct _CamelIMAPPStoreSummaryClass CamelIMAPPStoreSummaryClass;
typedef struct _CamelIMAPPStoreInfo CamelIMAPPStoreInfo;
enum {
CAMEL_IMAPP_STORE_INFO_FULL_NAME = CAMEL_STORE_INFO_LAST,
CAMEL_IMAPP_STORE_INFO_LAST,
};
struct _CamelIMAPPStoreInfo {
CamelStoreInfo info;
char *full_name;
};
typedef struct _CamelIMAPPStoreNamespace CamelIMAPPStoreNamespace;
struct _CamelIMAPPStoreNamespace {
char *path; /* display path */
char *full_name; /* real name */
char sep; /* directory separator */
};
struct _CamelIMAPPStoreSummary {
CamelStoreSummary summary;
struct _CamelIMAPPStoreSummaryPrivate *priv;
/* header info */
guint32 version; /* version of base part of file */
guint32 capabilities;
CamelIMAPPStoreNamespace *namespace; /* eventually to be a list */
};
struct _CamelIMAPPStoreSummaryClass {
CamelStoreSummaryClass summary_class;
};
CamelType camel_imapp_store_summary_get_type (void);
CamelIMAPPStoreSummary *camel_imapp_store_summary_new (void);
/* TODO: this api needs some more work, needs to support lists */
CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_new(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep);
void camel_imapp_store_summary_namespace_set(CamelIMAPPStoreSummary *s, CamelIMAPPStoreNamespace *ns);
CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_find_path(CamelIMAPPStoreSummary *s, const char *path);
CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_find_full(CamelIMAPPStoreSummary *s, const char *full_name);
/* converts to/from utf8 canonical nasmes */
char *camel_imapp_store_summary_full_to_path(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep);
char *camel_imapp_store_summary_path_to_full(CamelIMAPPStoreSummary *s, const char *path, char dir_sep);
CamelIMAPPStoreInfo *camel_imapp_store_summary_full_name(CamelIMAPPStoreSummary *s, const char *full_name);
CamelIMAPPStoreInfo *camel_imapp_store_summary_add_from_full(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep);
/* a convenience lookup function. always use this if path known */
char *camel_imapp_store_summary_full_from_path(CamelIMAPPStoreSummary *s, const char *path);
/* helper macro's */
#define camel_imapp_store_info_full_name(s, i) (camel_store_info_string((CamelStoreSummary *)s, (const CamelStoreInfo *)i, CAMEL_IMAPP_STORE_INFO_FULL_NAME))
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* ! _CAMEL_IMAPP_STORE_SUMMARY_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,77 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-store.h : class for an imap store */
/*
* Authors: Michael Zucchi <notzed@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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifndef CAMEL_IMAPP_STORE_H
#define CAMEL_IMAPP_STORE_H 1
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus }*/
#include <camel/camel-types.h>
#include <camel/camel-store.h>
#include "camel-imapp-driver.h"
#include "e-util/e-memory.h"
#define CAMEL_IMAPP_STORE_TYPE (camel_imapp_store_get_type ())
#define CAMEL_IMAPP_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_STORE_TYPE, CamelIMAPPStore))
#define CAMEL_IMAPP_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_STORE_TYPE, CamelIMAPPStoreClass))
#define CAMEL_IS_IMAP_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_STORE_TYPE))
struct _pending_fetch {
struct _pending_fetch *next;
struct _pending_fetch *prev;
CamelMessageInfo *info;
};
typedef struct {
CamelStore parent_object;
struct _CamelIMAPPStoreSummary *summary; /* in-memory list of folders */
struct _CamelIMAPPDriver *driver; /* IMAP processing engine */
struct _CamelDataCache *cache;
/* if we had a login error, what to show to user */
char *login_error;
GPtrArray *pending_list;
} CamelIMAPPStore;
typedef struct {
CamelStoreClass parent_class;
} CamelIMAPPStoreClass;
/* Standard Camel function */
CamelType camel_imapp_store_get_type (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CAMEL_IMAPP_STORE_H */

View File

@ -0,0 +1,761 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*-
*
* Author:
* Michael Zucchi <notzed@ximian.com>
*
* Copyright 1999, 2000 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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <glib.h>
#include <camel/camel-stream-mem.h>
#include "camel-imapp-stream.h"
#include "camel-imapp-exception.h"
#define t(x)
#define io(x) x
static void setup_table(void);
static CamelObjectClass *parent_class = NULL;
/* Returns the class for a CamelStream */
#define CS_CLASS(so) CAMEL_IMAPP_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so))
#define CAMEL_IMAPP_STREAM_SIZE (4096)
#define CAMEL_IMAPP_STREAM_TOKEN (4096) /* maximum token size */
static int
stream_fill(CamelIMAPPStream *is)
{
int left = 0;
if (is->source) {
left = is->end - is->ptr;
memcpy(is->buf, is->ptr, left);
is->end = is->buf + left;
is->ptr = is->buf;
left = camel_stream_read(is->source, is->end, CAMEL_IMAPP_STREAM_SIZE - (is->end - is->buf));
if (left > 0) {
is->end += left;
io(printf("camel_imapp_read: buffer is '%.*s'\n", is->end - is->ptr, is->ptr));
return is->end - is->ptr;
} else {
io(printf("camel_imapp_read: -1\n"));
return -1;
}
}
printf("camel_imapp_read: 0\n");
return 0;
}
static ssize_t
stream_read(CamelStream *stream, char *buffer, size_t n)
{
CamelIMAPPStream *is = (CamelIMAPPStream *)stream;
ssize_t max;
if (is->literal == 0 || n == 0)
return 0;
max = is->end - is->ptr;
if (max > 0) {
max = MIN(max, is->literal);
max = MIN(max, n);
memcpy(buffer, is->ptr, max);
is->ptr += max;
} else {
max = MIN(is->literal, n);
max = camel_stream_read(is->source, buffer, max);
if (max <= 0)
return max;
}
is->literal -= max;
return max;
}
static ssize_t
stream_write(CamelStream *stream, const char *buffer, size_t n)
{
CamelIMAPPStream *is = (CamelIMAPPStream *)stream;
return camel_stream_write(is->source, buffer, n);
}
static int
stream_close(CamelStream *stream)
{
/* nop? */
return 0;
}
static int
stream_flush(CamelStream *stream)
{
/* nop? */
return 0;
}
static gboolean
stream_eos(CamelStream *stream)
{
CamelIMAPPStream *is = (CamelIMAPPStream *)stream;
return is->literal == 0;
}
static int
stream_reset(CamelStream *stream)
{
/* nop? reset literal mode? */
return 0;
}
static void
camel_imapp_stream_class_init (CamelStreamClass *camel_imapp_stream_class)
{
CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_imapp_stream_class;
parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE );
/* virtual method definition */
camel_stream_class->read = stream_read;
camel_stream_class->write = stream_write;
camel_stream_class->close = stream_close;
camel_stream_class->flush = stream_flush;
camel_stream_class->eos = stream_eos;
camel_stream_class->reset = stream_reset;
}
static void
camel_imapp_stream_init(CamelIMAPPStream *is, CamelIMAPPStreamClass *isclass)
{
/* +1 is room for appending a 0 if we need to for a token */
is->ptr = is->end = is->buf = g_malloc(CAMEL_IMAPP_STREAM_SIZE+1);
is->tokenptr = is->tokenbuf = g_malloc(CAMEL_IMAPP_STREAM_SIZE+1);
is->tokenend = is->tokenbuf + CAMEL_IMAPP_STREAM_SIZE;
}
static void
camel_imapp_stream_finalise(CamelIMAPPStream *is)
{
g_free(is->buf);
if (is->source)
camel_object_unref((CamelObject *)is->source);
}
CamelType
camel_imapp_stream_get_type (void)
{
static CamelType camel_imapp_stream_type = CAMEL_INVALID_TYPE;
if (camel_imapp_stream_type == CAMEL_INVALID_TYPE) {
setup_table();
camel_imapp_stream_type = camel_type_register( camel_stream_get_type(),
"CamelIMAPPStream",
sizeof( CamelIMAPPStream ),
sizeof( CamelIMAPPStreamClass ),
(CamelObjectClassInitFunc) camel_imapp_stream_class_init,
NULL,
(CamelObjectInitFunc) camel_imapp_stream_init,
(CamelObjectFinalizeFunc) camel_imapp_stream_finalise );
}
return camel_imapp_stream_type;
}
/**
* camel_imapp_stream_new:
*
* Returns a NULL stream. A null stream is always at eof, and
* always returns success for all reads and writes.
*
* Return value: the stream
**/
CamelStream *
camel_imapp_stream_new(CamelStream *source)
{
CamelIMAPPStream *is;
is = (CamelIMAPPStream *)camel_object_new(camel_imapp_stream_get_type ());
camel_object_ref((CamelObject *)source);
is->source = source;
return (CamelStream *)is;
}
/*
From rfc2060
ATOM_CHAR ::= <any CHAR except atom_specials>
atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards /
quoted_specials
CHAR ::= <any 7-bit US-ASCII character except NUL,
0x01 - 0x7f>
CTL ::= <any ASCII control character and DEL,
0x00 - 0x1f, 0x7f>
SPACE ::= <ASCII SP, space, 0x20>
list_wildcards ::= "%" / "*"
quoted_specials ::= <"> / "\"
*/
static unsigned char imap_specials[256] = {
/* 00 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 10 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 20 */0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
/* 30 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 40 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 50 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
/* 60 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 70 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
#define imap_is_atom(c) ((imap_specials[(c)&0xff] & 0x01) != 0)
#define imap_is_simple(c) ((imap_specials[(c)&0xff] & 0x02) != 0)
#define imap_not_id(c) ((imap_specials[(c)&0xff] & 0x04) != 0)
/* could be pregenerated, but this is cheap */
static struct {
unsigned char *chars;
unsigned char mask;
} is_masks[] = {
{ "\n*()[]+", 2 },
{ " \r\n()[]+", 4 },
};
static void setup_table(void)
{
int i;
unsigned char *p, c;
for (i=0;i<(int)(sizeof(is_masks)/sizeof(is_masks[0]));i++) {
p = is_masks[i].chars;
while ((c = *p++))
imap_specials[c] |= is_masks[i].mask;
}
}
#if 0
static int
skip_ws(CamelIMAPPStream *is, unsigned char *pp, unsigned char *pe)
{
register unsigned char c, *p;
unsigned char *e;
p = is->ptr;
e = is->end;
do {
while (p >= e ) {
is->ptr = p;
if (stream_fill(is) == IMAP_TOK_ERROR)
return IMAP_TOK_ERROR;
p = is->ptr;
e = is->end;
}
c = *p++;
} while (c == ' ' || c == '\r');
is->ptr = p;
is->end = e;
return c;
}
#endif
/* FIXME: these should probably handle it themselves,
and get rid of the token interface? */
int
camel_imapp_stream_atom(CamelIMAPPStream *is, unsigned char **data, unsigned int *lenp)
{
unsigned char *p, c;
/* this is only 'approximate' atom */
switch(camel_imapp_stream_token(is, data, lenp)) {
case IMAP_TOK_TOKEN:
p = *data;
while ((c = *p))
*p++ = toupper(c);
case IMAP_TOK_INT:
return 0;
case IMAP_TOK_ERROR:
return IMAP_TOK_ERROR;
default:
camel_exception_throw(1, "expecting atom");
printf("expecting atom!\n");
return IMAP_TOK_PROTOCOL;
}
}
/* gets an atom, a quoted_string, or a literal */
int
camel_imapp_stream_astring(CamelIMAPPStream *is, unsigned char **data)
{
unsigned char *p, *start;
unsigned int len, inlen;
switch(camel_imapp_stream_token(is, data, &len)) {
case IMAP_TOK_TOKEN:
case IMAP_TOK_INT:
case IMAP_TOK_STRING:
return 0;
case IMAP_TOK_LITERAL:
/* FIXME: just grow buffer */
if (len >= CAMEL_IMAPP_STREAM_TOKEN) {
camel_exception_throw(1, "astring: literal too long");
printf("astring too long\n");
return IMAP_TOK_PROTOCOL;
}
p = is->tokenptr;
camel_imapp_stream_set_literal(is, len);
do {
len = camel_imapp_stream_getl(is, &start, &inlen);
if (len < 0)
return len;
memcpy(p, start, inlen);
p += inlen;
} while (len > 0);
*data = is->tokenptr;
return 0;
case IMAP_TOK_ERROR:
/* wont get unless no exception hanlder*/
return IMAP_TOK_ERROR;
default:
camel_exception_throw(1, "expecting astring");
printf("expecting astring!\n");
return IMAP_TOK_PROTOCOL;
}
}
/* check for NIL or (small) quoted_string or literal */
int
camel_imapp_stream_nstring(CamelIMAPPStream *is, unsigned char **data)
{
unsigned char *p, *start;
unsigned int len, inlen;
switch(camel_imapp_stream_token(is, data, &len)) {
case IMAP_TOK_STRING:
return 0;
case IMAP_TOK_LITERAL:
/* FIXME: just grow buffer */
if (len >= CAMEL_IMAPP_STREAM_TOKEN) {
camel_exception_throw(1, "nstring: literal too long");
return IMAP_TOK_PROTOCOL;
}
p = is->tokenptr;
camel_imapp_stream_set_literal(is, len);
do {
len = camel_imapp_stream_getl(is, &start, &inlen);
if (len < 0)
return len;
memcpy(p, start, inlen);
p += inlen;
} while (len > 0);
*data = is->tokenptr;
return 0;
case IMAP_TOK_TOKEN:
p = *data;
if (toupper(p[0]) == 'N' && toupper(p[1]) == 'I' && toupper(p[2]) == 'L' && p[3] == 0) {
*data = NULL;
return 0;
}
default:
camel_exception_throw(1, "expecting nstring");
return IMAP_TOK_PROTOCOL;
case IMAP_TOK_ERROR:
/* we'll never get this unless there are no exception handlers anyway */
return IMAP_TOK_ERROR;
}
}
/* parse an nstring as a stream */
int
camel_imapp_stream_nstring_stream(CamelIMAPPStream *is, CamelStream **stream)
/* throws IO,PARSE exception */
{
unsigned char *token;
unsigned int len;
int ret = 0;
CamelStream * volatile mem = NULL;
*stream = NULL;
CAMEL_TRY {
switch(camel_imapp_stream_token(is, &token, &len)) {
case IMAP_TOK_STRING:
mem = camel_stream_mem_new_with_buffer(token, len);
*stream = mem;
break;
case IMAP_TOK_LITERAL:
/* if len is big, we could automatically use a file backing */
camel_imapp_stream_set_literal(is, len);
mem = camel_stream_mem_new();
if (camel_stream_write_to_stream((CamelStream *)is, mem) == -1)
camel_exception_throw(1, "nstring: io error: %s", strerror(errno));
camel_stream_reset(mem);
*stream = mem;
break;
case IMAP_TOK_TOKEN:
if (toupper(token[0]) == 'N' && toupper(token[1]) == 'I' && toupper(token[2]) == 'L' && token[3] == 0) {
*stream = NULL;
break;
}
default:
ret = -1;
camel_exception_throw(1, "nstring: token not string");
}
} CAMEL_CATCH(ex) {
if (mem)
camel_object_unref((CamelObject *)mem);
camel_exception_throw_ex(ex);
} CAMEL_DONE;
/* never reaches here anyway */
return ret;
}
guint32
camel_imapp_stream_number(CamelIMAPPStream *is)
{
unsigned char *token;
unsigned int len;
if (camel_imapp_stream_token(is, &token, &len) != IMAP_TOK_INT) {
camel_exception_throw(1, "expecting number");
return 0;
}
return strtoul(token, 0, 10);
}
int
camel_imapp_stream_text(CamelIMAPPStream *is, unsigned char **text)
{
GByteArray *build = g_byte_array_new();
unsigned char *token;
unsigned int len;
int tok;
CAMEL_TRY {
while (is->unget > 0) {
switch (is->unget_tok) {
case IMAP_TOK_TOKEN:
case IMAP_TOK_STRING:
case IMAP_TOK_INT:
g_byte_array_append(build, is->unget_token, is->unget_len);
g_byte_array_append(build, " ", 1);
default: /* invalid, but we'll ignore */
break;
}
is->unget--;
}
do {
tok = camel_imapp_stream_gets(is, &token, &len);
if (tok < 0)
camel_exception_throw(1, "io error: %s", strerror(errno));
if (len)
g_byte_array_append(build, token, len);
} while (tok > 0);
} CAMEL_CATCH(ex) {
*text = NULL;
g_byte_array_free(build, TRUE);
camel_exception_throw_ex(ex);
} CAMEL_DONE;
g_byte_array_append(build, "", 1);
*text = build->data;
g_byte_array_free(build, FALSE);
return 0;
}
/* Get one token from the imap stream */
camel_imapp_token_t
/* throws IO,PARSE exception */
camel_imapp_stream_token(CamelIMAPPStream *is, unsigned char **data, unsigned int *len)
{
register unsigned char c, *p, *o, *oe;
unsigned char *e;
unsigned int literal;
int digits;
if (is->unget > 0) {
is->unget--;
*data = is->unget_token;
*len = is->unget_len;
/*printf("token UNGET '%c' %s\n", is->unget_tok, is->unget_token);*/
return is->unget_tok;
}
if (is->literal > 0)
g_warning("stream_token called with literal %d", is->literal);
p = is->ptr;
e = is->end;
/* skip whitespace/prefill buffer */
do {
while (p >= e ) {
is->ptr = p;
if (stream_fill(is) == IMAP_TOK_ERROR)
goto io_error;
p = is->ptr;
e = is->end;
}
c = *p++;
} while (c == ' ' || c == '\r');
/*strchr("\n*()[]+", c)*/
if (imap_is_simple(c)) {
is->ptr = p;
t(printf("token '%c'\n", c));
return c;
} else if (c == '{') {
literal = 0;
*data = p;
while (1) {
while (p < e) {
c = *p++;
if (isdigit(c) && literal < (UINT_MAX/10)) {
literal = literal * 10 + (c - '0');
} else if (c == '}') {
while (1) {
while (p < e) {
c = *p++;
if (c == '\n') {
*len = literal;
is->ptr = p;
is->literal = literal;
t(printf("token LITERAL %d\n", literal));
return IMAP_TOK_LITERAL;
}
}
is->ptr = p;
if (stream_fill(is) == IMAP_TOK_ERROR)
goto io_error;
p = is->ptr;
e = is->end;
}
} else {
if (isdigit(c))
printf("Protocol error: literal too big\n");
else
printf("Protocol error: literal contains invalid char %02x '%c'\n", c, isprint(c)?c:c);
goto protocol_error;
}
}
is->ptr = p;
if (stream_fill(is) == IMAP_TOK_ERROR)
goto io_error;
p = is->ptr;
e = is->end;
}
} else if (c == '"') {
o = is->tokenptr;
oe = is->tokenptr + CAMEL_IMAPP_STREAM_TOKEN - 1;
while (1) {
while (p < e) {
c = *p++;
if (c == '\\') {
while (p >= e) {
is->ptr = p;
if (stream_fill(is) == IMAP_TOK_ERROR)
goto io_error;
p = is->ptr;
e = is->end;
}
c = *p++;
} else if (c == '\"') {
is->ptr = p;
*o = 0;
*data = is->tokenbuf;
*len = o - is->tokenbuf;
t(printf("token STRING '%s'\n", is->tokenbuf));
return IMAP_TOK_STRING;
}
if (c == '\n' || c == '\r' || o>=oe) {
if (o >= oe)
printf("Protocol error: string too long\n");
else
printf("Protocol error: truncated string\n");
goto protocol_error;
} else {
*o++ = c;
}
}
is->ptr = p;
if (stream_fill(is) == IMAP_TOK_ERROR)
goto io_error;
p = is->ptr;
e = is->end;
}
} else {
o = is->tokenptr;
oe = is->tokenptr + CAMEL_IMAPP_STREAM_TOKEN - 1;
digits = isdigit(c);
*o++ = c;
while (1) {
while (p < e) {
c = *p++;
/*if (strchr(" \r\n*()[]+", c) != NULL) {*/
if (imap_not_id(c)) {
if (c == ' ' || c == '\r')
is->ptr = p;
else
is->ptr = p-1;
*o = 0;
*data = is->tokenbuf;
*len = o - is->tokenbuf;
t(printf("token TOKEN '%s'\n", is->tokenbuf));
return digits?IMAP_TOK_INT:IMAP_TOK_TOKEN;
} else if (o < oe) {
digits &= isdigit(c);
*o++ = c;
} else {
printf("Protocol error: token too long\n");
goto protocol_error;
}
}
is->ptr = p;
if (stream_fill(is) == IMAP_TOK_ERROR)
goto io_error;
p = is->ptr;
e = is->end;
}
}
/* Had an i/o erorr */
io_error:
printf("Got io error\n");
camel_exception_throw(1, "io error");
return IMAP_TOK_ERROR;
/* Protocol error, skip until next lf? */
protocol_error:
printf("Got protocol error\n");
if (c == '\n')
is->ptr = p-1;
else
is->ptr = p;
camel_exception_throw(1, "protocol error");
return IMAP_TOK_PROTOCOL;
}
void
camel_imapp_stream_ungettoken(CamelIMAPPStream *is, camel_imapp_token_t tok, unsigned char *token, unsigned int len)
{
/*printf("ungettoken: '%c' '%s'\n", tok, token);*/
is->unget_tok = tok;
is->unget_token = token;
is->unget_len = len;
is->unget++;
}
/* returns -1 on error, 0 if last lot of data, >0 if more remaining */
int camel_imapp_stream_gets(CamelIMAPPStream *is, unsigned char **start, unsigned int *len)
{
int max;
unsigned char *end;
*len = 0;
max = is->end - is->ptr;
if (max == 0) {
max = stream_fill(is);
if (max <= 0)
return max;
}
*start = is->ptr;
end = memchr(is->ptr, '\n', max);
if (end)
max = (end - is->ptr) + 1;
*start = is->ptr;
*len = max;
is->ptr += max;
return end == NULL?1:0;
}
void camel_imapp_stream_set_literal(CamelIMAPPStream *is, unsigned int literal)
{
is->literal = literal;
}
/* returns -1 on erorr, 0 if last data, >0 if more data left */
int camel_imapp_stream_getl(CamelIMAPPStream *is, unsigned char **start, unsigned int *len)
{
int max;
*len = 0;
if (is->literal > 0) {
max = is->end - is->ptr;
if (max == 0) {
max = stream_fill(is);
if (max <= 0)
return max;
}
max = MIN(max, is->literal);
*start = is->ptr;
*len = max;
is->ptr += max;
is->literal -= max;
}
if (is->literal > 0)
return 1;
return 0;
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2000 Ximian Inc.
*
* Authors: Michael Zucchi <notzed@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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _CAMEL_IMAPP_STREAM_H
#define _CAMEL_IMAPP_STREAM_H
#include <camel/camel-stream.h>
#define CAMEL_IMAPP_STREAM(obj) CAMEL_CHECK_CAST (obj, camel_imapp_stream_get_type (), CamelIMAPPStream)
#define CAMEL_IMAPP_STREAM_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_stream_get_type (), CamelIMAPPStreamClass)
#define CAMEL_IS_IMAP_STREAM(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_stream_get_type ())
typedef struct _CamelIMAPPStreamClass CamelIMAPPStreamClass;
typedef struct _CamelIMAPPStream CamelIMAPPStream;
typedef enum {
IMAP_TOK_PROTOCOL = -2,
IMAP_TOK_ERROR = -1,
IMAP_TOK_TOKEN = 256,
IMAP_TOK_STRING,
IMAP_TOK_INT,
IMAP_TOK_LITERAL,
} camel_imapp_token_t;
struct _CamelIMAPPStream {
CamelStream parent;
CamelStream *source;
/*int state;*/
unsigned char *buf, *ptr, *end;
unsigned int literal;
unsigned int unget;
camel_imapp_token_t unget_tok;
unsigned char *unget_token;
unsigned int unget_len;
unsigned char *tokenbuf, *tokenptr, *tokenend;
};
struct _CamelIMAPPStreamClass {
CamelStreamClass parent_class;
};
CamelType camel_imapp_stream_get_type (void);
CamelStream *camel_imapp_stream_new (CamelStream *source);
camel_imapp_token_t camel_imapp_stream_token (CamelIMAPPStream *is, unsigned char **start, unsigned int *len); /* throws IO,PARSE exception */
void camel_imapp_stream_ungettoken (CamelIMAPPStream *is, camel_imapp_token_t tok, unsigned char *token, unsigned int len);
void camel_imapp_stream_set_literal (CamelIMAPPStream *is, unsigned int literal);
int camel_imapp_stream_gets (CamelIMAPPStream *is, unsigned char **start, unsigned int *len);
int camel_imapp_stream_getl (CamelIMAPPStream *is, unsigned char **start, unsigned int *len);
/* all throw IO,PARSE exceptions */
/* gets an atom, upper-cases */
int camel_imapp_stream_atom (CamelIMAPPStream *is, unsigned char **start, unsigned int *len);
/* gets an atom or string */
int camel_imapp_stream_astring (CamelIMAPPStream *is, unsigned char **start);
/* gets a NIL or a string, start==NULL if NIL */
int camel_imapp_stream_nstring (CamelIMAPPStream *is, unsigned char **start);
/* gets a NIL or string into a stream, stream==NULL if NIL */
int camel_imapp_stream_nstring_stream(CamelIMAPPStream *is, CamelStream **stream);
/* gets 'text' */
int camel_imapp_stream_text (CamelIMAPPStream *is, unsigned char **text);
/* gets a 'number' */
guint32 camel_imapp_stream_number(CamelIMAPPStream *is);
#endif /* ! _CAMEL_IMAPP_STREAM_H */

View File

@ -0,0 +1,166 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright(C) 2000 Ximian Inc.
*
* Authors:
* Michael Zucchi <notzed@ximian.com>
* Dan Winship <danw@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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/stat.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "camel-imapp-summary.h"
#include <camel/camel-file-utils.h>
#define CAMEL_IMAPP_SUMMARY_VERSION (0x1000)
static int summary_header_load(CamelFolderSummary *, FILE *);
static int summary_header_save(CamelFolderSummary *, FILE *);
static CamelMessageInfo *message_info_load(CamelFolderSummary *s, FILE *in);
static int message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *info);
static void camel_imapp_summary_class_init(CamelIMAPPSummaryClass *klass);
static void camel_imapp_summary_init (CamelIMAPPSummary *obj);
static CamelFolderSummaryClass *camel_imapp_summary_parent;
CamelType
camel_imapp_summary_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(
camel_folder_summary_get_type(), "CamelIMAPPSummary",
sizeof(CamelIMAPPSummary),
sizeof(CamelIMAPPSummaryClass),
(CamelObjectClassInitFunc) camel_imapp_summary_class_init,
NULL,
(CamelObjectInitFunc) camel_imapp_summary_init,
NULL);
}
return type;
}
static void
camel_imapp_summary_class_init(CamelIMAPPSummaryClass *klass)
{
CamelFolderSummaryClass *cfs_class =(CamelFolderSummaryClass *) klass;
camel_imapp_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type()));
cfs_class->summary_header_load = summary_header_load;
cfs_class->summary_header_save = summary_header_save;
cfs_class->message_info_load = message_info_load;
cfs_class->message_info_save = message_info_save;
}
static void
camel_imapp_summary_init(CamelIMAPPSummary *obj)
{
CamelFolderSummary *s =(CamelFolderSummary *)obj;
/* subclasses need to set the right instance data sizes */
s->message_info_size = sizeof(CamelIMAPPMessageInfo);
s->content_info_size = sizeof(CamelMessageContentInfo);
/* and a unique file version */
s->version += CAMEL_IMAPP_SUMMARY_VERSION;
}
/**
* camel_imapp_summary_new:
* @filename: the file to store the summary in.
*
* This will create a new CamelIMAPPSummary object and read in the
* summary data from disk, if it exists.
*
* Return value: A new CamelIMAPPSummary object.
**/
CamelFolderSummary *
camel_imapp_summary_new(void)
{
CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY(camel_object_new(camel_imapp_summary_get_type()));
return summary;
}
static int
summary_header_load(CamelFolderSummary *s, FILE *in)
{
CamelIMAPPSummary *ims = CAMEL_IMAPP_SUMMARY(s);
if (camel_imapp_summary_parent->summary_header_load(s, in) == -1)
return -1;
return camel_file_util_decode_uint32(in, &ims->uidvalidity);
}
static int
summary_header_save(CamelFolderSummary *s, FILE *out)
{
CamelIMAPPSummary *ims = CAMEL_IMAPP_SUMMARY(s);
if (camel_imapp_summary_parent->summary_header_save(s, out) == -1)
return -1;
return camel_file_util_encode_uint32(out, ims->uidvalidity);
}
static CamelMessageInfo *
message_info_load(CamelFolderSummary *s, FILE *in)
{
CamelMessageInfo *info;
CamelIMAPPMessageInfo *iinfo;
info = camel_imapp_summary_parent->message_info_load(s, in);
if (info) {
iinfo =(CamelIMAPPMessageInfo *)info;
if (camel_file_util_decode_uint32(in, &iinfo->server_flags) == -1)
goto error;
}
return info;
error:
camel_folder_summary_info_free(s, info);
return NULL;
}
static int
message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *info)
{
CamelIMAPPMessageInfo *iinfo =(CamelIMAPPMessageInfo *)info;
if (camel_imapp_summary_parent->message_info_save(s, out, info) == -1)
return -1;
return camel_file_util_encode_uint32(out, iinfo->server_flags);
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2000 Ximian Inc.
*
* Authors:
* Michael Zucchi <notzed@ximian.com>
* Dan Winship <danw@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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _CAMEL_IMAPP_SUMMARY_H
#define _CAMEL_IMAPP_SUMMARY_H
#include <camel/camel-folder-summary.h>
#include <camel/camel-exception.h>
#define CAMEL_IMAPP_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imapp_summary_get_type (), CamelIMAPPSummary)
#define CAMEL_IMAPP_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_summary_get_type (), CamelIMAPPSummaryClass)
#define CAMEL_IS_IMAPP_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_summary_get_type ())
#define CAMEL_IMAPP_SERVER_FLAGS (CAMEL_MESSAGE_ANSWERED | \
CAMEL_MESSAGE_DELETED | \
CAMEL_MESSAGE_DRAFT | \
CAMEL_MESSAGE_FLAGGED | \
CAMEL_MESSAGE_SEEN)
#define CAMEL_IMAPP_MESSAGE_RECENT (1 << 8)
typedef struct _CamelIMAPPSummaryClass CamelIMAPPSummaryClass;
typedef struct _CamelIMAPPSummary CamelIMAPPSummary;
typedef struct _CamelIMAPPMessageInfo {
CamelMessageInfo info;
guint32 server_flags;
} CamelIMAPPMessageInfo;
struct _CamelIMAPPSummary {
CamelFolderSummary parent;
guint32 uidvalidity;
};
struct _CamelIMAPPSummaryClass {
CamelFolderSummaryClass parent_class;
};
CamelType camel_imapp_summary_get_type (void);
CamelFolderSummary *camel_imapp_summary_new (void);
#endif /* ! _CAMEL_IMAPP_SUMMARY_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,145 @@
#ifndef _CAMEL_IMAPP_UTILS_H
#define _CAMEL_IMAPP_UTILS_H
#include <camel/camel-mime-utils.h>
/* FIXME: the enum should be split up into logical groups, so that testing
can be done more accurately? */
/* list of strings we know about that can be *quickly* tokenised */
enum _imap_id {
IMAP_UNKNOWN = 0,
IMAP_ALERT,
IMAP_BYE,
IMAP_BAD,
IMAP_NO,
IMAP_OK,
IMAP_PREAUTH,
IMAP_NEWNAME,
IMAP_PARSE,
IMAP_PERMANENTFLAGS,
IMAP_READ_ONLY,
IMAP_READ_WRITE,
IMAP_TRYCREATE,
IMAP_UIDVALIDITY,
IMAP_UNSEEN,
IMAP_ENVELOPE,
IMAP_FLAGS,
IMAP_INTERNALDATE,
IMAP_RFC822_HEADER,
IMAP_RFC822_TEXT,
IMAP_RFC822_SIZE,
IMAP_BODYSTRUCTURE,
IMAP_BODY,
IMAP_UID,
};
/* str MUST be in upper case, tokenised using gperf function */
enum _imap_id imap_tokenise(register const char *str, register unsigned int len);
/* this flag should be part of imapfoldersummary */
enum {
CAMEL_IMAPP_MESSAGE_RECENT = (1<<8),
};
/* ********************************************************************** */
void imap_parse_flags(CamelIMAPPStream *stream, guint32 *flagsp) /* IO,PARSE */;
void imap_write_flags(CamelStream *stream, guint32 flags) /* IO */;
/* ********************************************************************** */
void imap_parse_param_list(CamelIMAPPStream *is, struct _header_param **plist) /* IO,PARSE */;
struct _CamelMimeDisposition *imap_parse_ext_optional(CamelIMAPPStream *is) /* IO,PARSE */;
struct _CamelMessageContentInfo *imap_parse_body_fields(CamelIMAPPStream *is) /* IO,PARSE */;
struct _header_address *imap_parse_address_list(CamelIMAPPStream *is) /* IO,PARSE */;
struct _CamelMessageInfo *imap_parse_envelope(CamelIMAPPStream *is) /* IO, PARSE */;
struct _CamelMessageContentInfo *imap_parse_body(CamelIMAPPStream *is) /* IO,PARSE */;
char *imap_parse_section(CamelIMAPPStream *is) /* IO,PARSE */;
void imap_free_body(struct _CamelMessageContentInfo *cinfo);
/* ********************************************************************** */
/* all the possible stuff we might get from a fetch request */
/* this assumes the caller/server doesn't send any one of these types twice */
struct _fetch_info {
guint32 got; /* what we got, see below */
CamelStream *body; /* BODY[.*](<.*>)? */
CamelStream *text; /* RFC822.TEXT */
CamelStream *header; /* RFC822.HEADER */
CamelMessageInfo *minfo; /* ENVELOPE */
CamelMessageContentInfo *cinfo; /* BODYSTRUCTURE,BODY */
guint32 size; /* RFC822.SIZE */
guint32 offset; /* start offset of a BODY[]<offset.length> request */
guint32 flags; /* FLAGS */
char *date; /* INTERNALDATE */
char *section; /* section for a BODY[section] request */
char *uid; /* UID */
};
#define FETCH_BODY (1<<0)
#define FETCH_TEXT (1<<1)
#define FETCH_HEADER (1<<2)
#define FETCH_MINFO (1<<3)
#define FETCH_CINFO (1<<4)
#define FETCH_SIZE (1<<5)
#define FETCH_OFFSET (1<<6)
#define FETCH_FLAGS (1<<7)
#define FETCH_DATE (1<<8)
#define FETCH_SECTION (1<<9)
#define FETCH_UID (1<<10)
struct _fetch_info *imap_parse_fetch(CamelIMAPPStream *is);
void imap_free_fetch(struct _fetch_info *finfo);
void imap_dump_fetch(struct _fetch_info *finfo);
/* ********************************************************************** */
struct _status_info {
enum _imap_id result; /* ok/no/bad/preauth only */
enum _imap_id condition; /* read-only/read-write/alert/parse/trycreate/newname/permanentflags/uidvalidity/unseen */
union {
struct {
char *oldname;
char *newname;
} newname;
guint32 permanentflags;
guint32 uidvalidity;
guint32 unseen;
} u;
char *text;
};
struct _status_info *imap_parse_status(CamelIMAPPStream *is);
void imap_free_status(struct _status_info *sinfo);
/* ********************************************************************** */
/* should this just return a FolderInfo?
should this just return the name & flags & separator by reference? */
struct _list_info {
guint32 flags:24;
char separator;
char *name;
};
struct _list_info *imap_parse_list(CamelIMAPPStream *is);
char *imapp_list_get_path(struct _list_info *li);
void imap_free_list(struct _list_info *linfo);
/* ********************************************************************** */
struct _uidset_state {
struct _CamelIMAPPEngine *ie;
int len;
guint32 start;
guint32 last;
};
struct _CamelIMAPPEngine;
struct _CamelIMAPPCommand;
void imapp_uidset_init(struct _uidset_state *ss, struct _CamelIMAPPEngine *ie);
int imapp_uidset_done(struct _uidset_state *ss, struct _CamelIMAPPCommand *ic);
int imapp_uidset_add(struct _uidset_state *ss, struct _CamelIMAPPCommand *ic, const char *uid);
#endif

View File

@ -0,0 +1 @@
imapp