aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
Diffstat (limited to 'camel')
-rw-r--r--camel/ChangeLog46
-rw-r--r--camel/camel-folder.c24
-rw-r--r--camel/camel-folder.h16
-rw-r--r--camel/camel-mime-message.c121
-rw-r--r--camel/camel-mime-message.h74
-rw-r--r--camel/providers/mbox/camel-mbox-folder.c133
-rw-r--r--camel/providers/mbox/camel-mbox-summary.c225
-rw-r--r--camel/providers/mbox/camel-mbox-summary.h6
8 files changed, 469 insertions, 176 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 6c28e6371c..e3e601cb09 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,49 @@
+2000-05-01 NotZed <NotZed@HelixCode.com>
+
+ * providers/mbox/camel-mbox-summary.c
+ (camel_mbox_summary_set_flags_by_uid): New function to update the
+ flags in the summary.
+ (camel_mbox_summary_expunge): Expunge messages from a folder.
+ (offset_content): Re-align offsets of summary when messages
+ added/removed to an existing summary.
+ (camel_mbox_summary_remove_uid): Remove a message summary entry by
+ uid.
+ (index_folder): Restore flags from X-Evolution header, if they are set.
+
+ * providers/mbox/camel-mbox-folder.c (_get_message_by_uid):
+ Connect to the message_changed signal.
+ (_init): Set permanent flags to something reasonable. No user
+ flags yet ...
+ (message_changed): If the flags of the message change, update the
+ flags in the summary.
+ (mbox_expunge): Implement the expunge.
+ (camel_mbox_folder_class_init): Renamed all leading _'s to mbox_'s
+
+ * camel-folder.c (_finalize): Uh, dont free permanent_flags
+ anymore (this wouldn't failed anyway, it was a GList !!!)
+
+ * camel-folder.h (struct _CamelFolder): Change permanent_flags to
+ a bitfield.
+ (list_permanent_flags): Renamed to get_permanent_flags, and
+ returns a bitfield.
+ (camel_folder_expunge): Changed expunge to a void type. The
+ messages would no longer be useful after they have been removed
+ ...
+
+ * camel-mime-message.c (set_flag): Removed.
+ (camel_mime_message_set_flag): Removed.
+ (get_flag): Removed.
+ (camel_mime_message_get_flag): Removed.
+ (add_flag_to_list): Removed.
+ (get_flag_list): Removed.
+ (camel_mime_message_get_flag_list): Removed.
+ (camel_mime_message_get_flags): New interface to get system flags.
+ (camel_mime_message_set_flags): " to set ".
+ (camel_mime_message_get_user_flag): To get a user flag.
+ (camel_mime_message_set_user_flag): To set a user flag.
+ (finalize): Hmm, the old one free'd the key and data, not good
+ when the data is a boolean ...
+
2000-04-30 Dan Winship <danw@helixcode.com>
* camel-provider.h: Tweak the definition of CamelProvider. Among
diff --git a/camel/camel-folder.c b/camel/camel-folder.c
index 31141da5c9..c0d0e5fcb3 100644
--- a/camel/camel-folder.c
+++ b/camel/camel-folder.c
@@ -74,8 +74,8 @@ static gboolean _can_hold_folders (CamelFolder *folder);
static gboolean _can_hold_messages (CamelFolder *folder);
static gboolean _exists (CamelFolder *folder, CamelException *ex);
static gboolean _is_open (CamelFolder *folder);
-static const GList *_list_permanent_flags (CamelFolder *folder,
- CamelException *ex);
+static guint32 _get_permanent_flags (CamelFolder *folder,
+ CamelException *ex);
static CamelFolderOpenMode _get_mode (CamelFolder *folder,
CamelException *ex);
@@ -108,7 +108,7 @@ static gint _get_message_count (CamelFolder *folder,
static gboolean _delete_messages (CamelFolder *folder,
CamelException *ex);
-static GList * _expunge (CamelFolder *folder,
+static void _expunge (CamelFolder *folder,
CamelException *ex);
static void _append_message (CamelFolder *folder,
CamelMimeMessage *message,
@@ -172,7 +172,7 @@ camel_folder_class_init (CamelFolderClass *camel_folder_class)
camel_folder_class->delete_message_by_number = _delete_message_by_number;
camel_folder_class->get_message_count = _get_message_count;
camel_folder_class->append_message = _append_message;
- camel_folder_class->list_permanent_flags = _list_permanent_flags;
+ camel_folder_class->get_permanent_flags = _get_permanent_flags;
camel_folder_class->copy_message_to = _copy_message_to;
camel_folder_class->get_message_uid = _get_message_uid;
camel_folder_class->get_message_by_uid = _get_message_by_uid;
@@ -224,7 +224,6 @@ _finalize (GtkObject *object)
g_free (camel_folder->name);
g_free (camel_folder->full_name);
- g_free (camel_folder->permanent_flags);
if (camel_folder->parent_store)
gtk_object_unref (GTK_OBJECT (camel_folder->parent_store));
@@ -974,12 +973,11 @@ camel_folder_list_subfolders (CamelFolder *folder, CamelException *ex)
-static GList *
+static void
_expunge (CamelFolder *folder, CamelException *ex)
{
g_warning ("CamelFolder::expunge not implemented for `%s'",
gtk_type_name (GTK_OBJECT_TYPE (folder)));
- return NULL;
}
@@ -991,7 +989,7 @@ _expunge (CamelFolder *folder, CamelException *ex)
*
* Return value: list of expunged messages
**/
-GList *
+void
camel_folder_expunge (CamelFolder *folder, CamelException *ex)
{
g_assert (folder != NULL);
@@ -1154,18 +1152,18 @@ camel_folder_append_message (CamelFolder *folder,
}
-static const GList *
-_list_permanent_flags (CamelFolder *folder, CamelException *ex)
+static guint32
+_get_permanent_flags (CamelFolder *folder, CamelException *ex)
{
return folder->permanent_flags;
}
-const GList *
-camel_folder_list_permanent_flags (CamelFolder *folder, CamelException *ex)
+guint32
+camel_folder_get_permanent_flags (CamelFolder *folder, CamelException *ex)
{
g_assert (folder != NULL);
- return CF_CLASS (folder)->list_permanent_flags (folder, ex);
+ return CF_CLASS (folder)->get_permanent_flags (folder, ex);
}
diff --git a/camel/camel-folder.h b/camel/camel-folder.h
index b8b2db0da5..15d8194d2e 100644
--- a/camel/camel-folder.h
+++ b/camel/camel-folder.h
@@ -96,7 +96,6 @@ typedef struct {
gchar *uid;
guint32 flags;
-
time_t date_sent;
time_t date_received;
@@ -116,7 +115,7 @@ struct _CamelFolder
gchar separator;
CamelStore *parent_store;
CamelFolder *parent_folder;
- GList *permanent_flags;
+ guint32 permanent_flags;
gboolean can_hold_folders:1;
gboolean can_hold_messages:1;
@@ -194,8 +193,8 @@ typedef struct {
GList * (*list_subfolders) (CamelFolder *folder,
CamelException *ex);
- GList * (*expunge) (CamelFolder *folder,
- CamelException *ex);
+ void (*expunge) (CamelFolder *folder,
+ CamelException *ex);
gboolean (*has_message_number_capability) (CamelFolder *folder);
@@ -214,8 +213,8 @@ typedef struct {
CamelMimeMessage *message,
CamelException *ex);
- const GList * (*list_permanent_flags) (CamelFolder *folder,
- CamelException *ex);
+ guint32 (*get_permanent_flags) (CamelFolder *folder,
+ CamelException *ex);
void (*copy_message_to) (CamelFolder *folder,
CamelMimeMessage *message,
@@ -291,7 +290,7 @@ gboolean camel_folder_delete (CamelFolder *folder,
CamelException *ex);
gboolean camel_folder_delete_messages (CamelFolder *folder,
CamelException *ex);
-GList * camel_folder_expunge (CamelFolder *folder,
+void camel_folder_expunge (CamelFolder *folder,
CamelException *ex);
@@ -303,8 +302,9 @@ const gchar * camel_folder_get_full_name (CamelFolder *folder);
/* various properties accessors */
gboolean camel_folder_exists (CamelFolder *folder,
CamelException *ex);
-const GList * camel_folder_list_permanent_flags (CamelFolder *folder,
+guint32 camel_folder_get_permanent_flags (CamelFolder *folder,
CamelException *ex);
+
CamelFolderOpenMode camel_folder_get_mode (CamelFolder *folder,
CamelException *ex);
gboolean camel_folder_is_open (CamelFolder *folder);
diff --git a/camel/camel-mime-message.c b/camel/camel-mime-message.c
index 39da00593a..c1cf13403a 100644
--- a/camel/camel-mime-message.c
+++ b/camel/camel-mime-message.c
@@ -58,10 +58,13 @@ static char *recipient_names[] = {
"To", "Cc", "Bcc", NULL
};
+enum SIGNALS {
+ MESSAGE_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
-static void set_flag (CamelMimeMessage *mime_message, const gchar *flag, gboolean value);
-static gboolean get_flag (CamelMimeMessage *mime_message, const gchar *flag);
-static GList *get_flag_list (CamelMimeMessage *mime_message);
static void set_message_number (CamelMimeMessage *mime_message, guint number);
static guint get_message_number (CamelMimeMessage *mime_message);
static int write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
@@ -92,9 +95,6 @@ camel_mime_message_class_init (CamelMimeMessageClass *camel_mime_message_class)
g_hash_table_insert (header_name_table, header_names[i], (gpointer)i+1);
/* virtual method definition */
- camel_mime_message_class->set_flag = set_flag;
- camel_mime_message_class->get_flag = get_flag;
- camel_mime_message_class->get_flag_list = get_flag_list;
camel_mime_message_class->set_message_number = set_message_number;
camel_mime_message_class->get_message_number = get_message_number;
@@ -107,6 +107,16 @@ camel_mime_message_class_init (CamelMimeMessageClass *camel_mime_message_class)
camel_mime_part_class->construct_from_parser = construct_from_parser;
+ signals[MESSAGE_CHANGED] =
+ gtk_signal_new ("message_changed",
+ GTK_RUN_LAST,
+ gtk_object_class->type,
+ GTK_SIGNAL_OFFSET (CamelMimeMessageClass, message_changed),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1, GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (gtk_object_class, signals, LAST_SIGNAL);
+
gtk_object_class->finalize = finalize;
}
@@ -126,7 +136,8 @@ camel_mime_message_init (gpointer object, gpointer klass)
g_hash_table_insert(mime_message->recipients, recipient_names[i], camel_internet_address_new());
}
- mime_message->flags = g_hash_table_new (g_strcase_hash, g_strcase_equal);
+ mime_message->user_flags = g_hash_table_new (g_strcase_hash, g_strcase_equal);
+ mime_message->flags = 0;
mime_message->subject = NULL;
mime_message->reply_to = NULL;
@@ -168,6 +179,11 @@ static void g_lib_is_uber_crappy_shit(gpointer whocares, gpointer getlost, gpoin
gtk_object_unref((GtkObject *)getlost);
}
+static void free_key_only(gpointer whocares, gpointer getlost, gpointer blah)
+{
+ g_free(whocares);
+}
+
static void
finalize (GtkObject *object)
{
@@ -179,13 +195,13 @@ finalize (GtkObject *object)
g_free (message->from);
g_hash_table_foreach (message->recipients, g_lib_is_uber_crappy_shit, NULL);
+
+ if (message->user_flags)
+ g_hash_table_foreach (message->user_flags, free_key_only, NULL);
+ g_hash_table_destroy(message->user_flags);
if (message->folder)
gtk_object_unref (GTK_OBJECT (message->folder));
-
- if (message->flags)
- g_hash_table_foreach (message->flags, g_hash_table_generic_free, NULL);
- g_hash_table_destroy(message->flags);
GTK_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -413,81 +429,56 @@ camel_mime_message_get_recipients (CamelMimeMessage *mime_message,
/* **** */
-
-static void
-set_flag (CamelMimeMessage *mime_message, const gchar *flag, gboolean value)
+guint32
+camel_mime_message_get_flags (CamelMimeMessage *m)
{
- gchar *old_flags;
- gboolean ptr_value;
-
- if (! g_hash_table_lookup_extended (mime_message->flags,
- flag,
- (gpointer)&(old_flags),
- (gpointer)&(ptr_value)) ) {
-
- g_hash_table_insert (mime_message->flags, g_strdup (flag), GINT_TO_POINTER (value));
- } else
- g_hash_table_insert (mime_message->flags, old_flags, GINT_TO_POINTER (value));
-
+ return m->flags;
}
void
-camel_mime_message_set_flag (CamelMimeMessage *mime_message, const gchar *flag, gboolean value)
+camel_mime_message_set_flags (CamelMimeMessage *m, guint32 flags, guint32 set)
{
- g_assert (mime_message);
- g_return_if_fail (!mime_message->expunged);
- CMM_CLASS (mime_message)->set_flag (mime_message, flag, value);
-}
+ guint32 old;
+ printf("%p setting flags %x mask %x\n", m, flags, set);
+ old = m->flags;
+ m->flags = (m->flags & ~flags) | (set & flags);
-static gboolean
-get_flag (CamelMimeMessage *mime_message, const gchar *flag)
-{
- return GPOINTER_TO_INT (g_hash_table_lookup (mime_message->flags, flag));
-}
+ printf("old = %x new = %x\n", old, m->flags);
-gboolean
-camel_mime_message_get_flag (CamelMimeMessage *mime_message, const gchar *flag)
-{
- g_assert (mime_message);
- g_return_val_if_fail (!mime_message->expunged, FALSE);
- return CMM_CLASS (mime_message)->get_flag (mime_message, flag);
+ if (old != m->flags)
+ gtk_signal_emit((GtkObject *)m, signals[MESSAGE_CHANGED], MESSAGE_FLAGS_CHANGED);
}
-
-
-static void
-add_flag_to_list (gpointer key, gpointer value, gpointer user_data)
+gboolean
+camel_mime_message_get_user_flag (CamelMimeMessage *m, const char *name)
{
- GList **flag_list = (GList **)user_data;
- gchar *flag_name = (gchar *)key;
-
- if ((flag_name) && (flag_name[0] != '\0'))
- *flag_list = g_list_append (*flag_list, flag_name);
+ return (gboolean)g_hash_table_lookup(m->user_flags, name);
}
-static GList *
-get_flag_list (CamelMimeMessage *mime_message)
+void
+camel_mime_message_set_user_flag (CamelMimeMessage *m, const char *name, gboolean value)
{
- GList *flag_list = NULL;
-
- if (mime_message->flags)
- g_hash_table_foreach (mime_message->flags, add_flag_to_list, &flag_list);
- return flag_list;
-}
+ gboolean there;
+ char *oldname;
+ gboolean oldvalue;
+ there = g_hash_table_lookup_extended(m->user_flags, name, &oldname, &oldvalue);
-GList *
-camel_mime_message_get_flag_list (CamelMimeMessage *mime_message)
-{
- g_assert (mime_message);
- g_return_val_if_fail (!mime_message->expunged, NULL);
- return CMM_CLASS (mime_message)->get_flag_list (mime_message);
+ if (value && !there) {
+ g_hash_table_insert(m->user_flags, g_strdup(name), (void *)TRUE);
+ gtk_signal_emit((GtkObject *)m, signals[MESSAGE_CHANGED], MESSAGE_FLAGS_CHANGED);
+ } else if (there) {
+ g_hash_table_remove(m->user_flags, name);
+ g_free(oldname);
+ gtk_signal_emit((GtkObject *)m, signals[MESSAGE_CHANGED], MESSAGE_FLAGS_CHANGED);
+ }
}
+/* FIXME: to be removed??? */
static void
set_message_number (CamelMimeMessage *mime_message, guint number)
{
diff --git a/camel/camel-mime-message.h b/camel/camel-mime-message.h
index 141747e3cb..c790138f70 100644
--- a/camel/camel-mime-message.h
+++ b/camel/camel-mime-message.h
@@ -1,10 +1,8 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camelMimeMessage.h : class for a mime message */
-
-/*
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */
+/* camelMimeMessage.h : class for a mime message
*
- * Author :
- * Bertrand Guiheneuf <bertrand@helixcode.com>
+ * Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
+ * Michael Zucchi <notzed@helixcode.com>
*
* Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com)
*
@@ -54,6 +52,18 @@ extern "C" {
/* specify local time */
#define CAMEL_MESSAGE_DATE_CURRENT (~0)
+/* system flag bits */
+enum _CamelMessageFlags {
+ CAMEL_MESSAGE_ANSWERED = 1<<0,
+ CAMEL_MESSAGE_DELETED = 1<<1,
+ CAMEL_MESSAGE_DRAFT = 1<<2,
+ CAMEL_MESSAGE_FLAGGED = 1<<3,
+ CAMEL_MESSAGE_SEEN = 1<<4,
+ /* following flags are for the folder, and are not really permanent flags */
+ CAMEL_MESSAGE_FOLDER_FLAGGED = 1<<16, /* for use by the folder implementation */
+ CAMEL_MESSAGE_USER = 1<<31 /* supports user flags */
+};
+
struct _CamelMimeMessage
{
CamelMimePart parent_object;
@@ -71,49 +81,28 @@ struct _CamelMimeMessage
GHashTable *recipients; /* hash table of CamelInternetAddress's */
/* other fields */
- GHashTable *flags; /* boolean values */
+ guint32 flags; /* system flags */
+ GHashTable *user_flags; /* if present, then true */
gboolean expunged;
guint message_number; /* set by folder object when retrieving message */
gchar *message_uid;
CamelFolder *folder;
-
};
-
+enum _MessageChangeType {
+ MESSAGE_FLAGS_CHANGED,
+ MESSAGE_ENVELOPE_CHANGED,
+};
typedef struct {
CamelMimePartClass parent_class;
-
+
+ /* signals */
+ void (*message_changed) (CamelMimeMessage *, enum _MessageChangeType type);
+
/* Virtual methods */
- void (*set_received_date) (CamelMimeMessage *mime_message,
- const gchar *received_date);
- const gchar * (*get_received_date) (CamelMimeMessage *mime_message);
- const gchar * (*get_sent_date) (CamelMimeMessage *mime_message);
- void (*set_reply_to) (CamelMimeMessage *mime_message,
- const gchar *reply_to);
- const gchar * (*get_reply_to) (CamelMimeMessage *mime_message);
- void (*set_subject) (CamelMimeMessage *mime_message,
- const gchar *subject);
- const gchar * (*get_subject) (CamelMimeMessage *mime_message);
- void (*set_from) (CamelMimeMessage *mime_message,
- const gchar *from);
- const gchar * (*get_from) (CamelMimeMessage *mime_message);
- void (*add_recipient) (CamelMimeMessage *mime_message,
- const gchar *recipient_type,
- const gchar *recipient);
- void (*remove_recipient) (CamelMimeMessage *mime_message,
- const gchar *recipient_type,
- const gchar *recipient);
- const GList * (*get_recipients) (CamelMimeMessage *mime_message,
- const gchar *recipient_type);
- void (*set_flag) (CamelMimeMessage *mime_message,
- const gchar *flag,
- gboolean value);
- gboolean (*get_flag) (CamelMimeMessage *mime_message,
- const gchar *flag);
- GList * (*get_flag_list) (CamelMimeMessage *mime_message);
void (*set_message_number) (CamelMimeMessage *mime_message,
guint number);
guint (*get_message_number) (CamelMimeMessage *mime_message);
@@ -157,13 +146,10 @@ void camel_mime_message_remove_recipient_name (CamelMimeMessage *mime_message,
const CamelInternetAddress *camel_mime_message_get_recipients (CamelMimeMessage *mime_message,
const char *type);
-
-void camel_mime_message_set_flag (CamelMimeMessage *mime_message,
- const gchar *flag,
- gboolean value);
-gboolean camel_mime_message_get_flag (CamelMimeMessage *mime_message,
- const gchar *flag);
-GList * camel_mime_message_get_flag_list (CamelMimeMessage *mime_message);
+guint32 camel_mime_message_get_flags (CamelMimeMessage *m);
+void camel_mime_message_set_flags (CamelMimeMessage *m, guint32 flags, guint32 set);
+gboolean camel_mime_message_get_user_flag (CamelMimeMessage *m, const char *name);
+void camel_mime_message_set_user_flag (CamelMimeMessage *m, const char *name, gboolean value);
guint camel_mime_message_get_message_number (CamelMimeMessage *mime_message);
diff --git a/camel/providers/mbox/camel-mbox-folder.c b/camel/providers/mbox/camel-mbox-folder.c
index 91ac79c22e..c6dfb657e7 100644
--- a/camel/providers/mbox/camel-mbox-folder.c
+++ b/camel/providers/mbox/camel-mbox-folder.c
@@ -57,31 +57,32 @@ static CamelFolderClass *parent_class=NULL;
#define CMBOXS_CLASS(so) CAMEL_STORE_CLASS (GTK_OBJECT(so)->klass)
-static void _init (CamelFolder *folder, CamelStore *parent_store,
+static void mbox_init (CamelFolder *folder, CamelStore *parent_store,
CamelFolder *parent_folder, const gchar *name,
gchar separator, CamelException *ex);
-static void _open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex);
-static void _close (CamelFolder *folder, gboolean expunge, CamelException *ex);
-static gboolean _exists (CamelFolder *folder, CamelException *ex);
-static gboolean _create(CamelFolder *folder, CamelException *ex);
-static gboolean _delete (CamelFolder *folder, gboolean recurse, CamelException *ex);
-static gboolean _delete_messages (CamelFolder *folder, CamelException *ex);
-static GList *_list_subfolders (CamelFolder *folder, CamelException *ex);
-static CamelMimeMessage *_get_message_by_number (CamelFolder *folder, gint number, CamelException *ex);
-static gint _get_message_count (CamelFolder *folder, CamelException *ex);
-static void _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex);
-static GList *_get_uid_list (CamelFolder *folder, CamelException *ex);
-static CamelMimeMessage *_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex);
+static void mbox_open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex);
+static void mbox_close (CamelFolder *folder, gboolean expunge, CamelException *ex);
+static gboolean mbox_exists (CamelFolder *folder, CamelException *ex);
+static gboolean mbox_create(CamelFolder *folder, CamelException *ex);
+static gboolean mbox_delete (CamelFolder *folder, gboolean recurse, CamelException *ex);
+static gboolean mbox_delete_messages (CamelFolder *folder, CamelException *ex);
+static GList *mbox_list_subfolders (CamelFolder *folder, CamelException *ex);
+static CamelMimeMessage *mbox_get_message_by_number (CamelFolder *folder, gint number, CamelException *ex);
+static gint mbox_get_message_count (CamelFolder *folder, CamelException *ex);
+static void mbox_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex);
+static GList *mbox_get_uid_list (CamelFolder *folder, CamelException *ex);
+static CamelMimeMessage *mbox_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex);
+
+static void mbox_expunge (CamelFolder *folder, CamelException *ex);
#if 0
-static void _expunge (CamelFolder *folder, CamelException *ex);
static void _copy_message_to (CamelFolder *folder, CamelMimeMessage *message, CamelFolder *dest_folder, CamelException *ex);
static const gchar *_get_message_uid (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex);
#endif
GPtrArray *summary_get_message_info (CamelFolder *folder, int first, int count);
-static void _finalize (GtkObject *object);
+static void mbox_finalize (GtkObject *object);
static void
camel_mbox_folder_class_init (CamelMboxFolderClass *camel_mbox_folder_class)
@@ -94,24 +95,24 @@ camel_mbox_folder_class_init (CamelMboxFolderClass *camel_mbox_folder_class)
/* virtual method definition */
/* virtual method overload */
- camel_folder_class->init = _init;
- camel_folder_class->open = _open;
- camel_folder_class->close = _close;
- camel_folder_class->exists = _exists;
- camel_folder_class->create = _create;
- camel_folder_class->delete = _delete;
- camel_folder_class->delete_messages = _delete_messages;
- camel_folder_class->list_subfolders = _list_subfolders;
- camel_folder_class->get_message_by_number = _get_message_by_number;
- camel_folder_class->get_message_count = _get_message_count;
- camel_folder_class->append_message = _append_message;
- camel_folder_class->get_uid_list = _get_uid_list;
+ camel_folder_class->init = mbox_init;
+ camel_folder_class->open = mbox_open;
+ camel_folder_class->close = mbox_close;
+ camel_folder_class->exists = mbox_exists;
+ camel_folder_class->create = mbox_create;
+ camel_folder_class->delete = mbox_delete;
+ camel_folder_class->delete_messages = mbox_delete_messages;
+ camel_folder_class->list_subfolders = mbox_list_subfolders;
+ camel_folder_class->get_message_by_number = mbox_get_message_by_number;
+ camel_folder_class->get_message_count = mbox_get_message_count;
+ camel_folder_class->append_message = mbox_append_message;
+ camel_folder_class->get_uid_list = mbox_get_uid_list;
+ camel_folder_class->expunge = mbox_expunge;
#if 0
- camel_folder_class->expunge = _expunge;
camel_folder_class->copy_message_to = _copy_message_to;
camel_folder_class->get_message_uid = _get_message_uid;
#endif
- camel_folder_class->get_message_by_uid = _get_message_by_uid;
+ camel_folder_class->get_message_by_uid = mbox_get_message_by_uid;
camel_folder_class->search_by_expression = camel_mbox_folder_search_by_expression;
camel_folder_class->search_complete = camel_mbox_folder_search_complete;
@@ -119,12 +120,12 @@ camel_mbox_folder_class_init (CamelMboxFolderClass *camel_mbox_folder_class)
camel_folder_class->get_message_info = summary_get_message_info;
- gtk_object_class->finalize = _finalize;
+ gtk_object_class->finalize = mbox_finalize;
}
static void
-_finalize (GtkObject *object)
+mbox_finalize (GtkObject *object)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (object);
@@ -159,7 +160,7 @@ camel_mbox_folder_get_type (void)
}
static void
-_init (CamelFolder *folder, CamelStore *parent_store,
+mbox_init (CamelFolder *folder, CamelStore *parent_store,
CamelFolder *parent_folder, const gchar *name, gchar separator,
CamelException *ex)
{
@@ -180,6 +181,12 @@ _init (CamelFolder *folder, CamelStore *parent_store,
folder->has_uid_capability = TRUE;
folder->has_search_capability = TRUE;
+ folder->permanent_flags = CAMEL_MESSAGE_ANSWERED |
+ CAMEL_MESSAGE_DELETED |
+ CAMEL_MESSAGE_DRAFT |
+ CAMEL_MESSAGE_FLAGGED |
+ CAMEL_MESSAGE_SEEN;
+
mbox_folder->summary = NULL;
/* now set the name info */
@@ -196,7 +203,7 @@ _init (CamelFolder *folder, CamelStore *parent_store,
}
static void
-_open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex)
+mbox_open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
@@ -222,13 +229,17 @@ _open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex)
}
static void
-_close (CamelFolder *folder, gboolean expunge, CamelException *ex)
+mbox_close (CamelFolder *folder, gboolean expunge, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
/* call parent implementation */
parent_class->close (folder, expunge, ex);
+ if (expunge) {
+ mbox_expunge(folder, ex);
+ }
+
/* save index */
if (mbox_folder->index) {
ibex_close(mbox_folder->index);
@@ -240,9 +251,21 @@ _close (CamelFolder *folder, gboolean expunge, CamelException *ex)
}
+static void
+mbox_expunge (CamelFolder *folder, CamelException *ex)
+{
+ CamelMboxFolder *mbox = (CamelMboxFolder *)folder;
+
+ if (camel_mbox_summary_expunge(mbox->summary) == -1) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID, /* FIXME: right error code */
+ "Could not expunge: %s", strerror(errno));
+ }
+}
+
+
/* FIXME: clean up this snot */
static gboolean
-_exists (CamelFolder *folder, CamelException *ex)
+mbox_exists (CamelFolder *folder, CamelException *ex)
{
CamelMboxFolder *mbox_folder;
struct stat stat_buf;
@@ -305,7 +328,7 @@ _exists (CamelFolder *folder, CamelException *ex)
/* FIXME: clean up this snot */
static gboolean
-_create (CamelFolder *folder, CamelException *ex)
+mbox_create (CamelFolder *folder, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
const gchar *folder_file_path, *folder_dir_path;
@@ -376,7 +399,7 @@ _create (CamelFolder *folder, CamelException *ex)
/* FIXME: cleanup */
static gboolean
-_delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
+mbox_delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
const gchar *folder_file_path, *folder_dir_path;
@@ -476,7 +499,7 @@ _delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
/* TODO: remove this */
gboolean
-_delete_messages (CamelFolder *folder, CamelException *ex)
+mbox_delete_messages (CamelFolder *folder, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
@@ -535,7 +558,7 @@ _delete_messages (CamelFolder *folder, CamelException *ex)
/* FIXME: cleanup */
static GList *
-_list_subfolders (CamelFolder *folder, CamelException *ex)
+mbox_list_subfolders (CamelFolder *folder, CamelException *ex)
{
GList *subfolder_name_list = NULL;
@@ -653,7 +676,7 @@ _list_subfolders (CamelFolder *folder, CamelException *ex)
}
static gint
-_get_message_count (CamelFolder *folder, CamelException *ex)
+mbox_get_message_count (CamelFolder *folder, CamelException *ex)
{
CamelMboxFolder *mbox_folder = (CamelMboxFolder *)folder;
@@ -678,7 +701,7 @@ _get_message_count (CamelFolder *folder, CamelException *ex)
/* FIXME: this may need some tweaking for performance? */
/* FIXME: MUST check all sytem call return codes MUST MUST */
static void
-_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex)
+mbox_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder), *source_folder;
CamelStream *output_stream;
@@ -786,7 +809,7 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException
static GList *
-_get_uid_list (CamelFolder *folder, CamelException *ex)
+mbox_get_uid_list (CamelFolder *folder, CamelException *ex)
{
GList *uid_list = NULL;
CamelMboxFolder *mbox_folder = (CamelMboxFolder *)folder;
@@ -803,7 +826,7 @@ _get_uid_list (CamelFolder *folder, CamelException *ex)
}
static CamelMimeMessage *
-_get_message_by_number (CamelFolder *folder, gint number, CamelException *ex)
+mbox_get_message_by_number (CamelFolder *folder, gint number, CamelException *ex)
{
CamelMboxFolder *mbox_folder = (CamelMboxFolder *)folder;
CamelMboxMessageInfo *info;
@@ -818,11 +841,27 @@ _get_message_by_number (CamelFolder *folder, gint number, CamelException *ex)
return NULL;
}
- return _get_message_by_uid (folder, info->info.uid, ex);
+ return mbox_get_message_by_uid (folder, info->info.uid, ex);
+}
+
+/* track flag changes in the summary */
+static void
+message_changed(CamelMimeMessage *m, int type, CamelMboxFolder *mf)
+{
+ printf("Message changed: %s: %d\n", m->message_uid, type);
+ switch (type) {
+ case MESSAGE_FLAGS_CHANGED:
+ camel_mbox_summary_set_flags_by_uid(mf->summary, m->message_uid, m->flags);
+ break;
+ default:
+ printf("Unhandled message change event: %d\n", type);
+ break;
+ }
}
+
static CamelMimeMessage *
-_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex)
+mbox_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
CamelStream *message_stream;
@@ -872,6 +911,10 @@ _get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex)
message->folder = folder;
gtk_object_ref((GtkObject *)folder);
message->message_uid = g_strdup(uid);
+ message->flags = info->info.flags;
+ printf("%p flags = %x = %x\n", message, info->info.flags, message->flags);
+
+ gtk_signal_connect((GtkObject *)message, "message_changed", message_changed, folder);
return message;
}
diff --git a/camel/providers/mbox/camel-mbox-summary.c b/camel/providers/mbox/camel-mbox-summary.c
index 5608afc3df..4d10709fcd 100644
--- a/camel/providers/mbox/camel-mbox-summary.c
+++ b/camel/providers/mbox/camel-mbox-summary.c
@@ -29,6 +29,8 @@
#include <gtk/gtk.h>
+#include <camel/camel-mime-message.h>
+
#include <camel/camel-mime-parser.h>
#include <camel/camel-mime-filter.h>
#include <camel/camel-mime-filter-basic.h>
@@ -374,6 +376,7 @@ message_struct_new(CamelMimeParser *mp, CamelMboxMessageContentInfo *parent, int
ms->info.content = (CamelMessageContentInfo *)body_part_new(mp, parent, start, body);
ms->xev_offset = xev_offset;
+
return ms;
}
@@ -674,6 +677,10 @@ error:
#define SAVEIT
+/* TODO: Allow to sync with current summary info, without over-writing flags if they
+ already exist there */
+/* TODO: Lazy sync, make this read-only, and dont write out xev headers unless we need
+ to? */
static int index_folder(CamelMboxSummary *s, int startoffset)
{
CamelMimeParser *mp;
@@ -705,7 +712,7 @@ static int index_folder(CamelMboxSummary *s, int startoffset)
int write_offset = 0; /* how much does the dest differ from the source pos */
int old_offset = 0;
- guint32 newuid;
+ guint32 newuid, newflags;
off_t xevoffset = -1;
char *tmpname;
@@ -761,6 +768,7 @@ static int index_folder(CamelMboxSummary *s, int startoffset)
case HSCAN_MULTIPART:
case HSCAN_HEADER: /* starting a new header */
newuid=~0;
+ newflags=0;
if (!toplevel) {
char name[32];
unsigned int olduid, oldflags;
@@ -775,6 +783,7 @@ static int index_folder(CamelMboxSummary *s, int startoffset)
if (header_evolution_decode(xev, &olduid, &oldflags) != ~0) {
d(printf(" uid = %d = %x\n", olduid, olduid));
newuid = olduid;
+ newflags = oldflags;
#if 0
while (camel_mime_parser_step(mp, &data, &datalen) != HSCAN_FROM_END)
;
@@ -834,6 +843,7 @@ static int index_folder(CamelMboxSummary *s, int startoffset)
parent = (CamelMboxMessageContentInfo *)message->info.content;
if (newuid != ~0) {
message->info.uid = g_strdup_printf("%u", newuid);
+ message->info.flags = newflags;
} else {
g_warning("This shouldn't happen?");
}
@@ -848,6 +858,7 @@ static int index_folder(CamelMboxSummary *s, int startoffset)
body = (CamelMboxMessageContentInfo *)message->info.content;
if (newuid != ~0) {
message->info.uid = g_strdup_printf("%u", newuid);
+ message->info.flags = newflags;
} else {
g_warning("This shouldn't happen?");
}
@@ -1259,6 +1270,218 @@ guint32 camel_mbox_summary_set_uid(CamelMboxSummary *s, guint32 uid)
return s->nextuid;
}
+void camel_mbox_summary_set_flags_by_uid(CamelMboxSummary *s, const char *uid, guint32 flags)
+{
+ CamelMessageInfo *info;
+
+ info = (CamelMessageInfo *)camel_mbox_summary_uid(s, uid);
+ if (info != NULL) {
+ if (info->flags != flags) {
+ info->flags = flags | CAMEL_MESSAGE_FOLDER_FLAGGED;
+ s->dirty = TRUE;
+ }
+ } else {
+ g_warning("Message has dissapeared from summary? uid %s", uid);
+ }
+}
+
+/* update offsets in the summary to take account deleted parts */
+static void
+offset_content(CamelMboxMessageContentInfo *content, off_t offset)
+{
+ content->pos -= offset;
+ content->bodypos -= offset;
+ content->endpos -= offset;
+ content = (CamelMboxMessageContentInfo *)content->info.childs;
+ while (content) {
+ offset_content(content, offset);
+ content = (CamelMboxMessageContentInfo *)content->info.next;
+ }
+}
+
+void camel_mbox_summary_remove_uid(CamelMboxSummary *s, const char *uid)
+{
+ CamelMboxMessageInfo *oldinfo;
+ char *olduid;
+
+ if (g_hash_table_lookup_extended(s->message_uid, uid, (void *)&olduid, (void *)&oldinfo)) {
+#if 0
+ /* FIXME: this code should be executed to update the summary info,
+ however, only if we're not depending on the info not changing yet */
+ off_t offset = info->endpos - info->pos;
+ int i, count, got = FALSE;
+
+ count = s->messages->len;
+ for (i=0;i<count;i++) {
+ CamelMboxMessageInfo *minfo = g_ptr_array_index(s->messages, i);
+ if (got) {
+ offset_content(minfo, offset);
+ } else if (minfo == info) {
+ got = TRUE;
+ }
+ }
+#endif
+ g_hash_table_remove(s->message_uid, uid);
+ g_ptr_array_remove(s->messages, oldinfo);
+ message_struct_free(oldinfo);
+ g_free(olduid);
+ }
+}
+
+/* perform expunge/update xev headers, etc */
+/* TODO: merge this with the indexing code, so that it can index new parts
+ without having to reread everything again? */
+/* TODO: sync with the mbox, if it has changed */
+int
+camel_mbox_summary_expunge(CamelMboxSummary *s)
+{
+ int quick = TRUE, work=FALSE;
+ int i, count;
+ CamelMboxMessageInfo *info;
+
+ printf("Executing expunge ...\n");
+
+ count = camel_mbox_summary_message_count(s);
+ for (i=0;quick && i<count;i++) {
+ info = camel_mbox_summary_index(s, i);
+ if (info->xev_offset == -1 || info->info.flags & CAMEL_MESSAGE_DELETED)
+ quick = FALSE;
+ else
+ work |= (info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0;
+ }
+ if (quick) {
+ int fd;
+ char name[32];
+
+ if (!work)
+ return 0;
+
+ camel_mbox_summary_save(s);
+
+ fd = open(s->folder_path, O_WRONLY);
+
+ if (fd == -1) {
+ g_error("Cannot open folder for update: %s", strerror(errno));
+ return -1;
+ }
+
+ /* poke in the new xev info */
+ for (i=0;i<count;i++) {
+ info = camel_mbox_summary_index(s, i);
+ g_assert(info);
+ g_assert(info->xev_offset != -1);
+ if (info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) {
+ printf("Setting new flags to message %s = %04x\n", info->info.uid, info->info.flags & 0xffff);
+ lseek(fd, info->xev_offset, SEEK_SET);
+ sprintf(name, "X-Evolution: %08x-%04x\n\n", (unsigned int)strtoul(info->info.uid, NULL, 10), info->info.flags & 0xffff);
+ write(fd, name, strlen(name));
+ info->info.flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
+ }
+ }
+ close(fd);
+ } else {
+ char *tmpname;
+ int fd, fdout;
+ int last_write = 0, offset = 0, summary_end = 0, last_start = 0;
+ CamelMboxMessageContentInfo *content;
+ struct stat st;
+
+ printf("We must expunge messages and/or write headers\n");
+
+ /* FIXME: This should check the current summary is correct */
+
+ /* we have to write out new headers or delete messages, starting from message i */
+
+ fd = open(s->folder_path, O_RDONLY);
+ if (fd == -1) {
+ g_error("Cannot open folder for read: %s", strerror(errno));
+ return -1;
+ }
+
+ tmpname = g_strdup_printf("%s.tmp", s->folder_path);
+ fdout = open(tmpname, O_WRONLY|O_CREAT|O_TRUNC, 0600);
+ if (fdout == -1) {
+ g_error("Cannot open tmp file for write: %s", strerror(errno));
+ close(fd);
+ g_free(tmpname);
+ return -1;
+ }
+
+ for (i=0;i<count;i++) {
+ info = camel_mbox_summary_index(s, i);
+ g_assert(info);
+ g_assert(info->info.content);
+
+ content = (CamelMboxMessageContentInfo *)info->info.content;
+
+ /* FIXME: Must also write out xev headers etc, as appropriate? */
+
+ /* we need to use the end of the previous message, becuase the beginning of
+ this message doesn't include the "^From " line. */
+
+ /* do we remove this message? */
+ if (info->info.flags & CAMEL_MESSAGE_DELETED) {
+ printf("Deleting message: %s\n", info->info.uid);
+ camel_mbox_summary_copy_block(fd, fdout, last_write, last_start-last_write);
+ last_write = content->endpos;
+ last_start = last_write;
+ offset += (content->endpos - content->pos);
+
+ /* remove this message from the index */
+ if (s->index) {
+ char name[32];
+
+ sprintf(name, "%x", info->info.uid);
+ ibex_unindex(s->index, name);
+ }
+
+ camel_mbox_summary_remove_uid(s, info->info.uid);
+ i--; /* redo this index */
+ count--;
+ } else {
+ printf("Keeping message: %s\n", info->info.uid);
+ last_start = content->endpos;
+ offset_content(content, offset);
+ summary_end = content->endpos;
+ }
+ }
+ /* copy the rest of the file ... */
+ camel_mbox_summary_copy_block(fd, fdout, last_write, INT_MAX);
+
+ close(fd);
+ if (close(fdout) == -1) {
+ g_error("Cannot close tmp folder: %s", strerror(errno));
+ unlink(tmpname);
+ g_free(tmpname);
+ return -1;
+ }
+
+ if (rename(tmpname, s->folder_path) == -1) {
+ g_error("Cannot rename folder: %s", strerror(errno));
+ unlink(tmpname);
+ g_free(tmpname);
+ return -1;
+ }
+
+ /* force an index sync */
+ if (s->index) {
+ ibex_write(s->index);
+ }
+
+ /* update summary size to match the actual (written) folder size ... */
+ s->size = summary_end;
+ /* and the time to match the newly written time, so we dont update needlessly */
+ if (stat(s->folder_path, &st) == 0) {
+ s->time = st.st_mtime;
+ }
+
+ camel_mbox_summary_save(s);
+ }
+
+ return 0;
+}
+
+
#if 0
int main(int argc, char **argv)
{
diff --git a/camel/providers/mbox/camel-mbox-summary.h b/camel/providers/mbox/camel-mbox-summary.h
index 80b59ef54f..fda574c6f8 100644
--- a/camel/providers/mbox/camel-mbox-summary.h
+++ b/camel/providers/mbox/camel-mbox-summary.h
@@ -63,15 +63,21 @@ void camel_mbox_summary_unref(CamelMboxSummary *);
int camel_mbox_summary_load(CamelMboxSummary *);
int camel_mbox_summary_save(CamelMboxSummary *);
int camel_mbox_summary_check(CamelMboxSummary *);
+int camel_mbox_summary_expunge(CamelMboxSummary *);
guint32 camel_mbox_summary_next_uid(CamelMboxSummary *);
/* set the minimum uid */
guint32 camel_mbox_summary_set_uid(CamelMboxSummary *s, guint32 uid);
CamelMboxMessageInfo *camel_mbox_summary_uid(CamelMboxSummary *s, const char *uid);
+/* dont use this function yet ... */
+void camel_mbox_summary_remove_uid(CamelMboxSummary *s, const char *uid);
CamelMboxMessageInfo *camel_mbox_summary_index(CamelMboxSummary *, int index);
int camel_mbox_summary_message_count(CamelMboxSummary *);
+/* set flags within a summary item */
+void camel_mbox_summary_set_flags_by_uid(CamelMboxSummary *s, const char *uid, guint32 flags);
+
/* TODO: should be in a utility library */
int camel_mbox_summary_copy_block(int fromfd, int tofd, off_t readpos, size_t bytes);