/* camel-mbox-folder.c : Abstract class for an email folder */
/*
+ * Author : Bertrand Guiheneuf <bertrand@helixcode.com>
*
- * Copyright (C) 1999 Bertrand Guiheneuf <bertrand@helixcode.com> .
+ * Copyright (C) 1999 Helix Code .
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
#include <config.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include "camel-mbox-store.h"
#include "string-utils.h"
#include "camel-log.h"
-#include "camel-stream-buffered-fs.h"
-#include "camel-folder-summary.h"
+#include "camel-stream-fs.h"
+#include "camel-mbox-summary.h"
+#include "camel-mbox-parser.h"
+#include "camel-mbox-utils.h"
#include "gmime-utils.h"
+#include "camel-mbox-search.h"
+#include "camel-data-wrapper.h"
+#include "camel-mime-message.h"
#include "camel-exception.h"
-#if 0
-#include "mbox-utils.h"
-#include "mbox-uid.h"
-#include "mbox-summary.h"
-#endif
-
static CamelFolderClass *parent_class=NULL;
/* Returns the class for a CamelMboxFolder */
#define CMBOXS_CLASS(so) CAMEL_STORE_CLASS (GTK_OBJECT(so)->klass)
-static void _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex);
+static void _init (CamelFolder *folder, CamelStore *parent_store,
+ CamelFolder *parent_folder, const gchar *name,
+ gchar separator, CamelException *ex);
static void _set_name(CamelFolder *folder, const gchar *name, 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);
-#if 0
static CamelMimeMessage *_get_message_by_number (CamelFolder *folder, gint number, CamelException *ex);
static gint _get_message_count (CamelFolder *folder, CamelException *ex);
-static gint _append_message (CamelFolder *folder, CamelMimeMessage *message, 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);
+#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);
-static CamelMimeMessage *_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex);
-static GList *_get_uid_list (CamelFolder *folder, CamelException *ex);
#endif
static void _finalize (GtkObject *object);
parent_class = gtk_type_class (camel_folder_get_type ());
/* virtual method definition */
+
/* virtual method overload */
- camel_folder_class->init_with_store = _init_with_store;
+ camel_folder_class->init = _init;
camel_folder_class->set_name = _set_name;
camel_folder_class->open = _open;
camel_folder_class->close = _close;
camel_folder_class->delete = _delete;
camel_folder_class->delete_messages = _delete_messages;
camel_folder_class->list_subfolders = _list_subfolders;
-#if 0
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;
+#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;
- camel_folder_class->get_message_by_uid = _get_message_by_uid;
- camel_folder_class->get_uid_list = _get_uid_list;
#endif
+ camel_folder_class->get_message_by_uid = _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;
+ camel_folder_class->search_cancel = camel_mbox_folder_search_cancel;
+
gtk_object_class->finalize = _finalize;
}
-
+
static void
-_init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex)
+_init (CamelFolder *folder, CamelStore *parent_store,
+ CamelFolder *parent_folder, const gchar *name, gchar separator,
+ CamelException *ex)
{
- CAMEL_LOG_FULL_DEBUG ("Entering CamelMhFolder::init_with_store\n");
+
+
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::init_with_store\n");
/* call parent method */
- parent_class->init_with_store (folder, parent_store, ex);
+ parent_class->init (folder, parent_store, parent_folder,
+ name, separator, ex);
if (camel_exception_get_id (ex)) return;
- /* we assume that the parent init_with_store
+ /* we assume that the parent init
method checks for the existance of @folder */
folder->can_hold_messages = TRUE;
folder->can_hold_folders = TRUE;
folder->has_summary_capability = TRUE;
folder->has_uid_capability = TRUE;
-
- folder->summary = NULL;
-
- CAMEL_LOG_FULL_DEBUG ("Leaving CamelMhFolder::init_with_store\n");
+ folder->has_search_capability = TRUE;
+ folder->summary = NULL;
+
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::init_with_store\n");
}
+/* internal method used to :
+ - test for the existence of a summary file
+ - test the sync between the summary and the mbox file
+ - load the summary or create it if necessary
+*/
+static void
+_check_get_or_maybe_generate_summary_file (CamelMboxFolder *mbox_folder,
+ CamelException *ex)
+{
+ CamelFolder *folder = CAMEL_FOLDER (mbox_folder);
+ CamelMboxSummary *summ;
+ GArray *message_info_array;
+ gint mbox_file_fd;
+ guint32 next_uid;
+ guint32 file_size;
+ struct stat st;
+
+ folder->summary = NULL;
+
+ /* Test for the existence and up-to-dateness of the summary file. */
+ if (access (mbox_folder->summary_file_path, F_OK) == 0) {
+ summ = camel_mbox_summary_load (mbox_folder->summary_file_path,
+ ex);
+ if (summ) {
+ if (stat (mbox_folder->folder_file_path, &st) == 0 &&
+ summ->mbox_file_size == st.st_size &&
+ summ->mbox_modtime == st.st_mtime)
+ folder->summary = CAMEL_FOLDER_SUMMARY (summ);
+ else
+ gtk_object_destroy (GTK_OBJECT (summ));
+ } else {
+ /* Bad summary file */
+ if (camel_exception_get_id (ex) !=
+ CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID)
+ return;
+ camel_exception_clear (ex);
+ }
+ }
+
+ /* In the case where the summary does not exist (or was the
+ * wrong version), or is not in sync with the mbox file,
+ * regenerate it.
+ */
+ if (folder->summary == NULL) {
+ /* Parse the mbox folder and get some information
+ * about the messages.
+ */
+ mbox_file_fd = open (mbox_folder->folder_file_path, O_RDONLY);
+ if (mbox_file_fd != -1) {
+ message_info_array =
+ camel_mbox_parse_file (mbox_file_fd, "From ",
+ 0, &file_size,
+ &next_uid, TRUE,
+ NULL, 0, ex);
+ close (mbox_file_fd);
+ if (camel_exception_get_id (ex))
+ return;
+
+ next_uid = camel_mbox_write_xev (mbox_folder,
+ mbox_folder->folder_file_path,
+ message_info_array,
+ &file_size,
+ next_uid, ex);
+ if (camel_exception_get_id (ex)) {
+ /* ** FIXME : free the preparsed information */
+ return;
+ }
+
+ summ = CAMEL_MBOX_SUMMARY (gtk_object_new (camel_mbox_summary_get_type (), NULL));
+ summ->message_info = parsed_information_to_mbox_summary (message_info_array);
+ summ->nb_message = summ->message_info->len;
+ summ->next_uid = next_uid;
+ summ->mbox_file_size = file_size;
+ /* **FIXME : Free the parsed information structure */
+ } else {
+ summ = CAMEL_MBOX_SUMMARY (gtk_object_new (camel_mbox_summary_get_type (), NULL));
+ summ->message_info = g_array_new (FALSE, FALSE, sizeof (CamelMboxSummaryInformation));
+ summ->nb_message = 0;
+ summ->next_uid = 0;
+ summ->mbox_file_size = 0;
+ }
+
+ folder->summary = CAMEL_FOLDER_SUMMARY (summ);
+ }
+}
_open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
- struct dirent *dir_entry;
- DIR *dir_handle;
-
-
- if (folder->open_state == FOLDER_OPEN) {
- camel_exception_set (ex,
- CAMEL_EXCEPTION_FOLDER_INVALID_STATE,
- "folder is already open");
- return;
+
+ mbox_folder->index = ibex_open(mbox_folder->index_file_path, O_CREAT|O_RDWR, 0600);
+ if (mbox_folder->index == NULL) {
+ g_warning("Could not open/create index file: %s: indexing will not function",
+ strerror(errno));
}
-
+ /* call parent class */
+ parent_class->open (folder, mode, ex);
+ if (camel_exception_get_id(ex))
+ return;
+
#if 0
- Here, we need to check for the summary file
- existence and create it if necessary.
/* get (or create) uid list */
if (!(mbox_load_uid_list (mbox_folder) > 0))
mbox_generate_uid_list (mbox_folder);
-
- /* get or create summary */
- /* it is important that it comes after uid list reading/generation */
- if (!(mbox_load_summary (mbox_folder) > 0))
- mbox_generate_summary (folder);
+#endif
-#endif
+ _check_get_or_maybe_generate_summary_file (mbox_folder, ex);
}
-
-
-
-
static void
_close (CamelFolder *folder, gboolean expunge, CamelException *ex)
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
-
+ CamelMboxSummary *mbox_summary = CAMEL_MBOX_SUMMARY (folder->summary);
+ struct stat st;
/* call parent implementation */
parent_class->close (folder, expunge, ex);
+
+ /* save index */
+ if (mbox_folder->index) {
+ ibex_close(mbox_folder->index);
+ }
+
+ /* Update the summary and save it to disk */
+ if (stat (mbox_folder->folder_file_path, &st) == 0) {
+ mbox_summary->mbox_file_size = st.st_size;
+ mbox_summary->mbox_modtime = st.st_mtime;
+ }
+ camel_mbox_summary_save (mbox_summary,
+ mbox_folder->summary_file_path, ex);
}
{
CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
const gchar *root_dir_path;
- gchar *full_name;
- const gchar *parent_full_name;
- gchar separator;
CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::set_name\n");
g_free (mbox_folder->folder_file_path);
g_free (mbox_folder->folder_dir_path);
+ g_free (mbox_folder->index_file_path);
- separator = camel_store_get_separator (folder->parent_store);
root_dir_path = camel_mbox_store_get_toplevel_dir (CAMEL_MBOX_STORE(folder->parent_store));
CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::set_name full_name is %s\n", folder->full_name);
CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::set_name root_dir_path is %s\n", root_dir_path);
- CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::separator is %c\n", separator);
- mbox_folder->folder_file_path = g_strdup_printf ("%s%c%s", root_dir_path, separator, folder->full_name);
- mbox_folder->folder_dir_path = g_strdup_printf ("%s%c%s.sdb", root_dir_path, separator, folder->full_name);
-
-
+ mbox_folder->folder_file_path = g_strdup_printf ("%s/%s", root_dir_path, folder->full_name);
+ mbox_folder->summary_file_path = g_strdup_printf ("%s/%s-ev-summary", root_dir_path, folder->full_name);
+ mbox_folder->folder_dir_path = g_strdup_printf ("%s/%s.sdb", root_dir_path, folder->full_name);
+ mbox_folder->index_file_path = g_strdup_printf ("%s/%s.ibex", root_dir_path, folder->full_name);
+
CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::set_name mbox_folder->folder_file_path is %s\n",
mbox_folder->folder_file_path);
CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::set_name mbox_folder->folder_dir_path is %s\n",
static gboolean
_exists (CamelFolder *folder, CamelException *ex)
{
- CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
+ CamelMboxFolder *mbox_folder;
struct stat stat_buf;
gint stat_error;
gboolean exists;
+ g_assert(folder != NULL);
+
CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::exists\n");
- /* check if the folder object exists */
- if (!folder) {
- camel_exception_set (ex,
- CAMEL_EXCEPTION_FOLDER_NULL,
- "folder object is NULL");
- return FALSE;
- }
+ mbox_folder = CAMEL_MBOX_FOLDER (folder);
/* check if the mbox file path is determined */
if (!mbox_folder->folder_file_path) {
"undetermined folder directory path. Maybe use set_name ?");
return FALSE;
}
-
+
+
+ /* we should not check for that here */
+#if 0
/* check if the mbox directory exists */
+ access_result = access (mbox_folder->folder_dir_path, F_OK);
+ if (access_result < 0) {
+ CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::exists errot when executing access on %s\n",
+ mbox_folder->folder_dir_path);
+ CAMEL_LOG_FULL_DEBUG (" Full error text is : %s\n", strerror(errno));
+ camel_exception_set (ex,
+ CAMEL_EXCEPTION_SYSTEM,
+ strerror(errno));
+ return FALSE;
+ }
stat_error = stat (mbox_folder->folder_dir_path, &stat_buf);
if (stat_error == -1) {
CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::exists when executing stat on %s, stat_error = %d\n",
}
exists = S_ISDIR (stat_buf.st_mode);
if (!exists) return FALSE;
+#endif
+
/* check if the mbox file exists */
stat_error = stat (mbox_folder->folder_file_path, &stat_buf);
- if (stat_error == -1) {
- CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::exists when executing stat on %s, stat_error = %d\n",
- mbox_folder->folder_file_path, stat_error);
- CAMEL_LOG_FULL_DEBUG (" Full error text is : %s\n", strerror(errno));
- camel_exception_set (ex,
- CAMEL_EXCEPTION_SYSTEM,
- strerror(errno));
+ if (stat_error == -1)
return FALSE;
- }
-
- exists = S_REG (stat_buf.st_mode);
+
+ exists = S_ISREG (stat_buf.st_mode);
/* we should check the rights here */
CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::exists\n");
static gboolean
_create (CamelFolder *folder, CamelException *ex)
{
- CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
+ CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
+ CamelMboxSummary *summary;
const gchar *folder_file_path, *folder_dir_path;
mode_t dir_mode = S_IRWXU;
gint mkdir_error;
gboolean folder_already_exists;
int creat_fd;
- mode_t old_umask;
-
- /* check if the folder object exists */
- if (!folder) {
- camel_exception_set (ex,
- CAMEL_EXCEPTION_FOLDER_NULL,
- "folder object is NULL");
- return FALSE;
- }
+ g_assert(folder != NULL);
/* call default implementation */
parent_class->create (folder, ex);
/* get the paths of what we need to create */
folder_file_path = mbox_folder->folder_file_path;
- folder_dir_path = mbox_folder->folder_file_path;
+ folder_dir_path = mbox_folder->folder_dir_path;
if (!(folder_file_path || folder_dir_path)) {
camel_exception_set (ex,
/* if the folder already exists, simply return */
folder_already_exists = camel_folder_exists (folder,ex);
- if (camel_exception_get_id (ex)) return FALSE;
+ if (camel_exception_get_id (ex))
+ return FALSE;
- if (folder_already_exists) return TRUE;
+ if (folder_already_exists)
+ return TRUE;
/* create the directory for the subfolders */
mkdir_error = mkdir (folder_dir_path, dir_mode);
- if (mkdir_error == -1) goto io_error;
+ if (mkdir_error == -1)
+ goto io_error;
/* create the mbox file */
/* it must be rw for the user and none for the others */
- old_umask = umask (0700);
creat_fd = open (folder_file_path,
O_WRONLY | O_CREAT | O_APPEND,
- S_IRUSR | S_IWUSR);
- umask (old_umask);
- if (creat_fd == -1) goto io_error;
+ 0600);
+ if (creat_fd == -1)
+ goto io_error;
+
close (creat_fd);
-
+
+ /* create the summary object */
+ summary = CAMEL_MBOX_SUMMARY (gtk_object_new (camel_mbox_summary_get_type (), NULL));
+ summary->nb_message = 0;
+ summary->next_uid = 1;
+ summary->mbox_file_size = 0;
+ summary->message_info = g_array_new (FALSE, FALSE, sizeof (CamelMboxSummaryInformation));
+
return TRUE;
/* exception handling for io errors */
-
-
-
-
-
static gboolean
_delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
{
- CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
+ CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
const gchar *folder_file_path, *folder_dir_path;
gint rmdir_error = 0;
gint unlink_error = 0;
gboolean folder_already_exists;
- /* check if the folder object exists */
- if (!folder) {
- camel_exception_set (ex,
- CAMEL_EXCEPTION_FOLDER_NULL,
- "folder object is NULL");
- return FALSE;
- }
+ g_assert(folder != NULL);
+ /* check if the folder object exists */
/* in the case where the folder does not exist,
return immediatly */
folder_already_exists = camel_folder_exists (folder, ex);
- if (camel_exception_get_id (ex)) return FALSE;
+ if (camel_exception_get_id (ex))
+ return FALSE;
- if (!folder_already_exists) return TRUE;
+ if (!folder_already_exists)
+ return TRUE;
/* call default implementation.
parent_class->delete (folder, recurse, ex);
- /* get the paths of what we need to delete */
+ /* get the paths of what we need to be deleted */
folder_file_path = mbox_folder->folder_file_path;
folder_dir_path = mbox_folder->folder_file_path;
CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::delete removing directory %s\n", folder_dir_path);
rmdir_error = rmdir (folder_dir_path);
if (rmdir_error == -1)
- switch errno {
+ switch (errno) {
case EACCES :
camel_exception_set (ex,
CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
/* physically delete the file */
unlink_error = unlink (folder_dir_path);
if (unlink_error == -1)
- switch errno {
+ switch (errno) {
case EACCES :
case EPERM :
case EROFS :
_delete_messages (CamelFolder *folder, CamelException *ex)
{
- CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
+ CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
const gchar *folder_file_path;
gboolean folder_already_exists;
int creat_fd;
- mode_t old_umask;
-
-
- /* check if the folder object exists */
- if (!folder) {
- camel_exception_set (ex,
- CAMEL_EXCEPTION_FOLDER_NULL,
- "folder object is NULL");
- return FALSE;
- }
+ g_assert(folder!=NULL);
+
/* in the case where the folder does not exist,
return immediatly */
folder_already_exists = camel_folder_exists (folder, ex);
/* create the mbox file */
/* it must be rw for the user and none for the others */
- old_umask = umask (0700);
creat_fd = open (folder_file_path,
O_WRONLY | O_TRUNC,
- S_IRUSR | S_IWUSR);
- umask (old_umask);
- if (creat_fd == -1) goto io_error;
+ 0600);
+ if (creat_fd == -1)
+ goto io_error;
close (creat_fd);
return TRUE;
}
-
-
-
-
-
-
-
static GList *
_list_subfolders (CamelFolder *folder, CamelException *ex)
{
GList *subfolder_name_list = NULL;
- CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder);
+ CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
const gchar *folder_dir_path;
gboolean folder_exists;
struct stat stat_buf;
gint stat_error = 0;
- GList *file_list;
gchar *entry_name;
gchar *full_entry_name;
gchar *real_folder_name;
DIR *dir_handle;
gboolean folder_suffix_found;
- gchar *io_error_text;
-
-
/* check if the folder object exists */
if (!folder) {
CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::list_subfolders adding "
"%s\n", entry_name);
- /* if the folder is a netscape folder, remove the
+ /* if the folder is a netscape folder, remove the
".sdb" from the name */
real_folder_name = string_prefix (entry_name, ".sdb", &folder_suffix_found);
/* stick here the tests for other folder suffixes if any */
/* io exception handling */
- io_error :
-
- switch errno {
+ switch (errno) {
case EACCES :
camel_exception_setv (ex,
+static gint
+_get_message_count (CamelFolder *folder, CamelException *ex)
+{
+ gint message_count;
+ g_assert (folder);
+ g_assert (folder->summary);
+
+ message_count = CAMEL_MBOX_SUMMARY (folder->summary)->nb_message;
+ CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::get_message_count found %d messages\n", message_count);
+ return message_count;
+}
+static void
+_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex)
+{
+ CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
+ CamelMboxSummary *summary = CAMEL_MBOX_SUMMARY (folder->summary);
+ CamelStream *output_stream;
+ guint32 tmp_file_size;
+ guint32 next_uid;
+ gint tmp_file_fd;
+ GArray *message_info_array;
+ GArray *mbox_summary_info;
+ gchar *tmp_message_filename;
+ gint fd1, fd2;
+ int i;
+
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::append_message\n");
+
+ tmp_message_filename = g_strdup_printf ("%s.tmp",
+ mbox_folder->folder_file_path);
+
+ /* write the message itself */
+ output_stream = camel_stream_fs_new_with_name (tmp_message_filename,
+ CAMEL_STREAM_FS_WRITE);
+ if (output_stream != NULL) {
+ camel_stream_write_string (output_stream, "From - \n");
+ camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), output_stream);
+ }
+ camel_stream_close (output_stream);
+ gtk_object_unref (GTK_OBJECT (output_stream));
+
+ /* at this point we have saved the message to a
+ temporary file, now, we have to add the x-evolution
+ field and also update the main summary */
+
+ /*
+ First : parse the mbox file, but only from the
+ position where the message has been added,
+ wich happens to be the last postion in the
+ mbox file before we added the message.
+ This position is still stored in the summary
+ for the moment
+ */
+ next_uid = summary->next_uid;
+ tmp_file_fd = open (tmp_message_filename, O_RDONLY);
+ message_info_array =
+ camel_mbox_parse_file (tmp_file_fd, "From - ", 0,
+ &tmp_file_size, &next_uid, TRUE,
+ NULL, 0, ex);
+
+ close (tmp_file_fd);
+
+ /* get the value of the last available UID
+ as saved in the summary file, again */
+ next_uid = summary->next_uid;
+
+ /* make sure all our of message info's have 0 uid - ignore any
+ set elsewhere */
+ for (i=0;i<message_info_array->len;i++) {
+ g_array_index(message_info_array, CamelMboxParserMessageInfo, i).uid = 0;
+ }
+
+ /*
+ OK, this is not very efficient, we should not use the same
+ method as for parsing an entire mail file,
+ but I have no time to write a simpler parser
+ */
+ next_uid = camel_mbox_write_xev (mbox_folder, tmp_message_filename,
+ message_info_array, &tmp_file_size, next_uid, ex);
+
+ if (camel_exception_get_id (ex)) {
+ /* ** FIXME : free the preparsed information */
+ return;
+ }
+
+ mbox_summary_info =
+ parsed_information_to_mbox_summary (message_info_array);
+
+ /* store the number of messages as well as the summary array */
+ summary->nb_message += 1;
+ summary->next_uid = next_uid;
+
+ ((CamelMboxSummaryInformation *)(mbox_summary_info->data))->position +=
+ summary->mbox_file_size;
+ summary->mbox_file_size += tmp_file_size;
+
+ camel_mbox_summary_append_entries (summary, mbox_summary_info);
+ g_array_free (mbox_summary_info, TRUE);
+
+
+ /* append the temporary file message to the mbox file */
+ fd1 = open (tmp_message_filename, O_RDONLY);
+ fd2 = open (mbox_folder->folder_file_path,
+ O_WRONLY | O_CREAT | O_APPEND,
+ 0600);
+
+ if (fd2 == -1) {
+ camel_exception_setv (ex,
+ CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
+ "could not open the mbox folder file for appending the message\n"
+ "\t%s\n"
+ "Full error is : %s\n",
+ mbox_folder->folder_file_path,
+ strerror (errno));
+ return;
+ }
+
+ camel_mbox_copy_file_chunk (fd1,
+ fd2,
+ tmp_file_size,
+ ex);
+ close (fd1);
+ close (fd2);
+
+ /* remove the temporary file */
+ unlink (tmp_message_filename);
+
+ g_free (tmp_message_filename);
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::append_message\n");
+}
+
+
+
+
+static GList *
+_get_uid_list (CamelFolder *folder, CamelException *ex)
+{
+ GArray *message_info_array;
+ CamelMboxSummaryInformation *message_info;
+ GList *uid_list = NULL;
+ int i;
+
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::get_uid_list\n");
+
+ message_info_array =
+ CAMEL_MBOX_SUMMARY (folder->summary)->message_info;
+
+ for (i=0; i<message_info_array->len; i++) {
+ message_info = (CamelMboxSummaryInformation *)(message_info_array->data) + i;
+ uid_list = g_list_prepend (uid_list, g_strdup_printf ("%u", message_info->uid));
+ }
+
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::get_uid_list\n");
+
+ return uid_list;
+}
+
static CamelMimeMessage *
_get_message_by_number (CamelFolder *folder, gint number, CamelException *ex)
{
- CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
- const gchar *directory_path;
- gchar *message_name;
- gchar *message_file_name;
- CamelStream *input_stream = NULL;
+ GArray *message_info_array;
+ CamelMboxSummaryInformation *message_info;
+ char uidbuf[20];
+
+ message_info_array =
+ CAMEL_MBOX_SUMMARY (folder->summary)->message_info;
+
+ if (number > message_info_array->len) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
+ "No such message %d in folder `%s'.",
+ number, folder->name);
+ return NULL;
+ }
+
+ message_info =
+ (CamelMboxSummaryInformation *)(message_info_array->data) +
+ (number - 1);
+ sprintf (uidbuf, "%lu", message_info->uid);
+
+ return _get_message_by_uid (folder, uidbuf, ex);
+}
+
+
+static CamelMimeMessage *
+_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex)
+{
+
+ CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder);
+ GArray *message_info_array;
+ CamelMboxSummaryInformation *message_info = NULL;
+ guint32 searched_uid;
+ int i;
+ gboolean uid_found;
+ CamelStream *message_stream;
CamelMimeMessage *message = NULL;
- GList *message_list = NULL;
+ CamelStore *parent_store;
+
+ CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::get_message_by_uid\n");
- g_assert(folder);
+ searched_uid = strtoul (uid, NULL, 10);
+
+ message_info_array =
+ CAMEL_MBOX_SUMMARY (folder->summary)->message_info;
+ i=0;
+ uid_found = FALSE;
+ /* first, look for the message that has the searched uid */
+ while ((i<message_info_array->len) && (!uid_found)) {
+ message_info = (CamelMboxSummaryInformation *)(message_info_array->data) + i;
+ uid_found = (message_info->uid == searched_uid);
+ i++;
+ }
- directory_path = mh_folder->directory_path;
- if (!directory_path) return NULL;
+ /* if the uid was not found, raise an exception and return */
+ if (!uid_found) {
+ camel_exception_setv (ex,
+ CAMEL_EXCEPTION_FOLDER_INVALID_UID,
+ "uid %s not found in the folder",
+ uid);
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::get_uid_list\n");
+ return NULL;
+ }
+
+ /* at this point, the message_info structure
+ contains the informations concerning the
+ message that was searched for */
+
+ /* create a stream bound to the message */
+ message_stream = camel_stream_fs_new_with_name_and_bounds (mbox_folder->folder_file_path,
+ CAMEL_STREAM_FS_READ,
+ message_info->position,
+ message_info->position + message_info->size);
+
+
+ /* get the parent store */
+ parent_store = camel_folder_get_parent_store (folder, ex);
+ if (camel_exception_get_id (ex)) {
+ gtk_object_unref (GTK_OBJECT (message_stream));
+ return NULL;
+ }
-
- message_name = g_list_nth_data (mh_folder->file_name_list, number);
+ message = camel_mime_message_new ();
+ camel_data_wrapper_set_input_stream (CAMEL_DATA_WRAPPER (message), message_stream);
+
- if (message_name != NULL) {
- CAMEL_LOG_FULL_DEBUG ("CanelMhFolder::get_message message number = %d, name = %s\n",
- number, message_name);
- message_file_name = g_strdup_printf ("%s/%s", directory_path, message_name);
- input_stream = camel_stream_buffered_fs_new_with_name (message_file_name, CAMEL_STREAM_BUFFERED_FS_READ);
-
- if (input_stream != NULL) {
-#warning use session field here
- message = camel_mime_message_new_with_session ( (CamelSession *)NULL);
- camel_data_wrapper_construct_from_stream ( CAMEL_DATA_WRAPPER (message), input_stream);
- gtk_object_unref (GTK_OBJECT (input_stream));
- message->message_number = number;
- gtk_object_set_data_full (GTK_OBJECT (message), "filename",
- g_strdup (message_name), _filename_free);
-
-#warning Set flags and all this stuff here
- }
- g_free (message_file_name);
- } else
- CAMEL_LOG_FULL_DEBUG ("CanelMhFolder::get_message message number = %d, not found\n", number);
+
- return message;
+ CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::get_uid_list\n");
+ return message;
}