experimental, non-working imap implementation
svn path=/trunk/; revision=22061
This commit is contained in:
46
camel/providers/imapp/Makefile.am
Normal file
46
camel/providers/imapp/Makefile.am
Normal 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
|
748
camel/providers/imapp/camel-imapp-driver.c
Normal file
748
camel/providers/imapp/camel-imapp-driver.c
Normal 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);
|
||||||
|
}
|
81
camel/providers/imapp/camel-imapp-driver.h
Normal file
81
camel/providers/imapp/camel-imapp-driver.h
Normal 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
|
1156
camel/providers/imapp/camel-imapp-engine.c
Normal file
1156
camel/providers/imapp/camel-imapp-engine.c
Normal file
File diff suppressed because it is too large
Load Diff
154
camel/providers/imapp/camel-imapp-engine.h
Normal file
154
camel/providers/imapp/camel-imapp-engine.h
Normal 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
|
35
camel/providers/imapp/camel-imapp-exception.h
Normal file
35
camel/providers/imapp/camel-imapp-exception.h
Normal 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
|
183
camel/providers/imapp/camel-imapp-fetch-stream.c
Normal file
183
camel/providers/imapp/camel-imapp-fetch-stream.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
47
camel/providers/imapp/camel-imapp-fetch-stream.h
Normal file
47
camel/providers/imapp/camel-imapp-fetch-stream.h
Normal 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 */
|
268
camel/providers/imapp/camel-imapp-folder.c
Normal file
268
camel/providers/imapp/camel-imapp-folder.c
Normal 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
|
||||||
|
*/
|
||||||
|
|
66
camel/providers/imapp/camel-imapp-folder.h
Normal file
66
camel/providers/imapp/camel-imapp-folder.h
Normal 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 */
|
91
camel/providers/imapp/camel-imapp-provider.c
Normal file
91
camel/providers/imapp/camel-imapp-provider.c
Normal 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);
|
||||||
|
}
|
616
camel/providers/imapp/camel-imapp-store-summary.c
Normal file
616
camel/providers/imapp/camel-imapp-store-summary.c
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
102
camel/providers/imapp/camel-imapp-store-summary.h
Normal file
102
camel/providers/imapp/camel-imapp-store-summary.h
Normal 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 */
|
1221
camel/providers/imapp/camel-imapp-store.c
Normal file
1221
camel/providers/imapp/camel-imapp-store.c
Normal file
File diff suppressed because it is too large
Load Diff
77
camel/providers/imapp/camel-imapp-store.h
Normal file
77
camel/providers/imapp/camel-imapp-store.h
Normal 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 */
|
||||||
|
|
||||||
|
|
761
camel/providers/imapp/camel-imapp-stream.c
Normal file
761
camel/providers/imapp/camel-imapp-stream.c
Normal 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;
|
||||||
|
}
|
90
camel/providers/imapp/camel-imapp-stream.h
Normal file
90
camel/providers/imapp/camel-imapp-stream.h
Normal 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 */
|
166
camel/providers/imapp/camel-imapp-summary.c
Normal file
166
camel/providers/imapp/camel-imapp-summary.c
Normal 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);
|
||||||
|
}
|
65
camel/providers/imapp/camel-imapp-summary.h
Normal file
65
camel/providers/imapp/camel-imapp-summary.h
Normal 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 */
|
||||||
|
|
1339
camel/providers/imapp/camel-imapp-utils.c
Normal file
1339
camel/providers/imapp/camel-imapp-utils.c
Normal file
File diff suppressed because it is too large
Load Diff
145
camel/providers/imapp/camel-imapp-utils.h
Normal file
145
camel/providers/imapp/camel-imapp-utils.h
Normal 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
|
1
camel/providers/imapp/libcamelimapp.urls
Normal file
1
camel/providers/imapp/libcamelimapp.urls
Normal file
@ -0,0 +1 @@
|
|||||||
|
imapp
|
Reference in New Issue
Block a user