From a74c859d8c64ac576255fbc36b5f59468b42ddce Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 25 Mar 2000 05:18:55 +0000 Subject: change the CamelFolderSummary interfaces to allow partial summary queries * camel-folder-summary.[ch]: change the CamelFolderSummary interfaces to allow partial summary queries (for dealing with very large folders). Remove the "extended_fields" from CamelFolderInfo and CamelMessageInfo: this is better dealt with by subtyping. * providers/mbox/camel-mbox-summary.[ch]: Make CamelMboxSummary a subclass of CamelFolderSummary. Update interfaces for that. Remove the internal/external summary distinction. Remove the (unused) md5 checksum in the folder summary. Change the summary file format (primarily to make it no longer byte-order dependent) and add a version number to it so it will be easier to change in the future. * providers/mbox/camel-mbox-folder.[ch] * providers/mbox/camel-mbox-search.c * providers/mbox/camel-mbox-utils.c: update for summary changes * camel-exception-list.def: add CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID svn path=/trunk/; revision=2159 --- camel/providers/mbox/camel-mbox-folder.c | 278 +++++++-------- camel/providers/mbox/camel-mbox-folder.h | 5 - camel/providers/mbox/camel-mbox-search.c | 4 +- camel/providers/mbox/camel-mbox-summary.c | 564 ++++++++++++++++-------------- camel/providers/mbox/camel-mbox-summary.h | 60 ++-- camel/providers/mbox/camel-mbox-utils.c | 13 +- 6 files changed, 466 insertions(+), 458 deletions(-) (limited to 'camel/providers/mbox') diff --git a/camel/providers/mbox/camel-mbox-folder.c b/camel/providers/mbox/camel-mbox-folder.c index 8c7303924e..b8a18f201a 100644 --- a/camel/providers/mbox/camel-mbox-folder.c +++ b/camel/providers/mbox/camel-mbox-folder.c @@ -39,11 +39,9 @@ #include "string-utils.h" #include "camel-log.h" #include "camel-stream-buffered-fs.h" -#include "camel-folder-summary.h" #include "camel-mbox-summary.h" #include "camel-mbox-parser.h" #include "camel-mbox-utils.h" -#include "md5-utils.h" #include "gmime-utils.h" #include "camel-mbox-search.h" #include "camel-data-wrapper.h" @@ -196,7 +194,7 @@ _init (CamelFolder *folder, CamelStore *parent_store, folder->has_summary_capability = TRUE; folder->has_uid_capability = TRUE; folder->has_search_capability = TRUE; - folder->summary = camel_folder_summary_new (); + folder->summary = NULL; CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::init_with_store\n"); } @@ -209,92 +207,74 @@ _init (CamelFolder *folder, CamelStore *parent_store, - load the summary or create it if necessary */ static void -_check_get_or_maybe_generate_summary_file (CamelMboxFolder *mbox_folder, CamelException *ex) +_check_get_or_maybe_generate_summary_file (CamelMboxFolder *mbox_folder, + CamelException *ex) { CamelFolder *folder = CAMEL_FOLDER (mbox_folder); + CamelMboxSummary *summ; GArray *message_info_array; - gboolean summary_file_exists; - gboolean summary_file_is_sync; - GArray *mbox_summary_info; gint mbox_file_fd; guint32 next_uid; guint32 file_size; - - /* test for the existence of the summary file */ - summary_file_exists = (access (mbox_folder->summary_file_path, F_OK) == 0); - - /* if the summary file exists, test if the - md5 of the mbox file is still in sync - with the one we had computed the last time - we saved the summary file */ - if (summary_file_exists) { - - summary_file_is_sync = - camel_mbox_check_summary_sync (mbox_folder->summary_file_path, - mbox_folder->folder_file_path, - ex); - if (camel_exception_get_id (ex)) return; + struct stat st; + + folder->summary = NULL; + + /* Test for the existence and up-to-dateness of the summary file. */ + if (stat (mbox_folder->summary_file_path, &st) == 0) { + summ = camel_mbox_summary_load (mbox_folder->summary_file_path, + ex); + if (summ) { + if (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 is not in sync with the mbox file - regenerate it */ - if ( !(summary_file_exists && summary_file_is_sync)) { - - /* parse the mbox folder and get some - information about the messages */ - + /* 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); - message_info_array = camel_mbox_parse_file (mbox_file_fd, - "From ", - 0, - &file_size, - &next_uid, - TRUE, - NULL, - 0, - ex); - + 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)) { + if (camel_exception_get_id (ex)) return; - } - - next_uid = camel_mbox_write_xev (mbox_folder->folder_file_path, - message_info_array, &file_size, next_uid, ex); + next_uid = camel_mbox_write_xev (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; } - - mbox_summary_info = + + 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 */ - /* allocate an internal summary object */ - mbox_folder->internal_summary = g_new (CamelMboxSummary, 1); - - /* generate the folder md5 signature */ - md5_get_digest_from_file (mbox_folder->folder_file_path, mbox_folder->internal_summary->md5_digest); - - /* store the number of messages as well as the summary array */ - mbox_folder->internal_summary->nb_message = mbox_summary_info->len; - mbox_folder->internal_summary->next_uid = next_uid; - mbox_folder->internal_summary->mbox_file_size = file_size; - mbox_folder->internal_summary->message_info = mbox_summary_info; - - } else { - /* every thing seems ok, just read the summary file from disk */ - mbox_folder->internal_summary = camel_mbox_load_summary (mbox_folder->summary_file_path, ex); + folder->summary = CAMEL_FOLDER_SUMMARY (summ); } - - /* copy the internal summary information to the external - folder summary used by the display engines */ - camel_mbox_summary_append_internal_to_external (mbox_folder->internal_summary, folder->summary, 0); } @@ -303,17 +283,17 @@ static void _open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex) { CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); - //struct dirent *dir_entry; - //struct stat stat_buf; /* call parent class */ parent_class->open (folder, mode, ex); if (camel_exception_get_id(ex)) return; +#if 0 /* get (or create) uid list */ - //if (!(mbox_load_uid_list (mbox_folder) > 0)) - // mbox_generate_uid_list (mbox_folder); + if (!(mbox_load_uid_list (mbox_folder) > 0)) + mbox_generate_uid_list (mbox_folder); +#endif _check_get_or_maybe_generate_summary_file (mbox_folder, ex); } @@ -324,12 +304,12 @@ _close (CamelFolder *folder, gboolean expunge, CamelException *ex) { CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); - /* call parent implementation */ parent_class->close (folder, expunge, ex); - - /* save the folder summary on disc */ - camel_mbox_save_summary (mbox_folder->internal_summary, mbox_folder->summary_file_path, ex); + + /* save the folder summary on disk */ + camel_mbox_summary_save (CAMEL_MBOX_SUMMARY (folder->summary), + mbox_folder->summary_file_path, ex); } @@ -340,8 +320,6 @@ _set_name (CamelFolder *folder, const gchar *name, CamelException *ex) { CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); const gchar *root_dir_path; - //gchar *full_name; - //const gchar *parent_full_name; CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::set_name\n"); @@ -353,21 +331,19 @@ _set_name (CamelFolder *folder, const gchar *name, CamelException *ex) g_free (mbox_folder->folder_dir_path); g_free (mbox_folder->index_file_path); - 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); - - 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", - mbox_folder->folder_dir_path); - CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::set_name\n"); + root_dir_path = camel_mbox_store_get_toplevel_dir (CAMEL_MBOX_STORE (folder->parent_store)); + + 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); } @@ -387,8 +363,8 @@ _exists (CamelFolder *folder, CamelException *ex) CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::exists\n"); - mbox_folder = CAMEL_MBOX_FOLDER(folder); - + mbox_folder = CAMEL_MBOX_FOLDER (folder); + /* check if the mbox file path is determined */ if (!mbox_folder->folder_file_path) { camel_exception_set (ex, @@ -456,7 +432,8 @@ _exists (CamelFolder *folder, CamelException *ex) 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; @@ -482,14 +459,17 @@ _create (CamelFolder *folder, CamelException *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 */ @@ -497,15 +477,16 @@ _create (CamelFolder *folder, CamelException *ex) creat_fd = open (folder_file_path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR, 0600); - if (creat_fd == -1) goto io_error; + if (creat_fd == -1) + goto io_error; close (creat_fd); - /* create the summary object */ - mbox_folder->internal_summary = g_new (CamelMboxSummary, 1); - mbox_folder->internal_summary->nb_message = 0; - mbox_folder->internal_summary->next_uid = 1; - mbox_folder->internal_summary->mbox_file_size = 0; - mbox_folder->internal_summary->message_info = g_array_new (FALSE, FALSE, sizeof (CamelMboxSummaryInformation)); + /* 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; @@ -531,15 +512,10 @@ _create (CamelFolder *folder, CamelException *ex) - - - - - 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; @@ -552,9 +528,11 @@ _delete (CamelFolder *folder, gboolean recurse, CamelException *ex) /* 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. @@ -641,7 +619,7 @@ gboolean _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; @@ -673,7 +651,8 @@ _delete_messages (CamelFolder *folder, CamelException *ex) creat_fd = open (folder_file_path, O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR, 0600); - if (creat_fd == -1) goto io_error; + if (creat_fd == -1) + goto io_error; close (creat_fd); return TRUE; @@ -701,25 +680,17 @@ _delete_messages (CamelFolder *folder, CamelException *ex) } - - - - - - - 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; @@ -727,9 +698,6 @@ _list_subfolders (CamelFolder *folder, CamelException *ex) DIR *dir_handle; gboolean folder_suffix_found; - //gchar *io_error_text; - - /* check if the folder object exists */ if (!folder) { @@ -839,14 +807,12 @@ _list_subfolders (CamelFolder *folder, CamelException *ex) static gint _get_message_count (CamelFolder *folder, CamelException *ex) { - - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); gint message_count; g_assert (folder); - g_assert (mbox_folder->internal_summary); + g_assert (folder->summary); - message_count = mbox_folder->internal_summary->nb_message; + 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; @@ -856,7 +822,8 @@ _get_message_count (CamelFolder *folder, CamelException *ex) static void _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex) { - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); + CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); + CamelMboxSummary *summary = CAMEL_MBOX_SUMMARY (folder->summary); CamelStream *output_stream; guint32 tmp_file_size; guint32 next_uid; @@ -868,10 +835,12 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::append_message\n"); - tmp_message_filename = g_strdup_printf ("%s.tmp", mbox_folder->folder_file_path); + 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); + 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); @@ -880,7 +849,7 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException /* 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 summary */ + field and also update the main summary */ /* First : parse the mbox file, but only from the @@ -890,7 +859,7 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException This position is still stored in the summary for the moment */ - next_uid = mbox_folder->internal_summary->next_uid; + 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, @@ -901,7 +870,7 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException /* get the value of the last available UID as saved in the summary file */ - next_uid = mbox_folder->internal_summary->next_uid; + next_uid = summary->next_uid; /* OK, this is not very efficient, we should not use the same @@ -920,20 +889,14 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException parsed_information_to_mbox_summary (message_info_array); /* store the number of messages as well as the summary array */ - mbox_folder->internal_summary->nb_message += 1; - mbox_folder->internal_summary->next_uid = next_uid; + summary->nb_message += 1; + summary->next_uid = next_uid; - ((CamelMboxSummaryInformation *)(mbox_summary_info->data))->position += mbox_folder->internal_summary->mbox_file_size; - mbox_folder->internal_summary->mbox_file_size += tmp_file_size; - - camel_mbox_summary_append_entries (mbox_folder->internal_summary, mbox_summary_info); - - /* append the new entry of the internal summary to - the external summary */ - camel_mbox_summary_append_internal_to_external (mbox_folder->internal_summary, - folder->summary, - mbox_folder->internal_summary->nb_message-1); + ((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); @@ -964,9 +927,6 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException /* remove the temporary file */ //unlink (tmp_message_filename); - /* generate the folder md5 signature */ - md5_get_digest_from_file (mbox_folder->folder_file_path, mbox_folder->internal_summary->md5_digest); - g_free (tmp_message_filename); CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::append_message\n"); } @@ -977,7 +937,6 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException static GList * _get_uid_list (CamelFolder *folder, CamelException *ex) { - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); GArray *message_info_array; CamelMboxSummaryInformation *message_info; GList *uid_list = NULL; @@ -985,10 +944,10 @@ _get_uid_list (CamelFolder *folder, CamelException *ex) CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::get_uid_list\n"); - message_info_array = mbox_folder->internal_summary->message_info; + message_info_array = + CAMEL_MBOX_SUMMARY (folder->summary)->message_info; for (i=0; ilen; i++) { - message_info = (CamelMboxSummaryInformation *)(message_info_array->data) + i; uid_list = g_list_prepend (uid_list, g_strdup_printf ("%u", message_info->uid)); } @@ -1009,7 +968,7 @@ static CamelMimeMessage * _get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex) { - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); + CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); GArray *message_info_array; CamelMboxSummaryInformation *message_info = NULL; guint32 searched_uid; @@ -1021,9 +980,10 @@ _get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex) CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::get_message_by_uid\n"); - searched_uid = strtoul(uid, (char **)NULL, 10); + searched_uid = strtoul (uid, NULL, 10); - message_info_array = mbox_folder->internal_summary->message_info; + message_info_array = + CAMEL_MBOX_SUMMARY (folder->summary)->message_info; i=0; uid_found = FALSE; diff --git a/camel/providers/mbox/camel-mbox-folder.h b/camel/providers/mbox/camel-mbox-folder.h index 4caa28fd6a..ba17642144 100644 --- a/camel/providers/mbox/camel-mbox-folder.h +++ b/camel/providers/mbox/camel-mbox-folder.h @@ -35,7 +35,6 @@ extern "C" { #include #include "camel-folder.h" -#include "camel-mbox-summary.h" /* #include "camel-store.h" */ @@ -48,15 +47,11 @@ extern "C" { typedef struct { CamelFolder parent_object; - CamelFolderSummary *external_summary; - /* the external summary is intended to be read by callers */ - gchar *folder_file_path; /* contains the messages */ gchar *summary_file_path; /* contains the messages summary */ gchar *folder_dir_path; /* contains the subfolders */ gchar *index_file_path; /* index of body contents */ - CamelMboxSummary *internal_summary; /* internal summary object */ GList *uid_array; int search_id; /* next search id */ diff --git a/camel/providers/mbox/camel-mbox-search.c b/camel/providers/mbox/camel-mbox-search.c index 22aa599709..8a55ffee1d 100644 --- a/camel/providers/mbox/camel-mbox-search.c +++ b/camel/providers/mbox/camel-mbox-search.c @@ -28,13 +28,13 @@ #include #include -#include "camel/camel-folder-summary.h" #include "camel/camel-mime-message.h" #include "camel/camel-mime-part.h" #include "camel/camel-stream.h" #include "camel/camel-stream-fs.h" #include "camel/camel.h" #include "camel-mbox-folder.h" +#include "camel-mbox-summary.h" #include "camel-mbox-search.h" #define HAVE_FILTER @@ -300,7 +300,7 @@ int camel_mbox_folder_search_by_expression(CamelFolder *folder, const char *expr gtk_object_ref((GtkObject *)ctx->summary); /* FIXME: the index should be global to the folder */ - ctx->message_info = camel_folder_summary_get_message_info_list(ctx->summary); + ctx->message_info = CAMEL_MBOX_SUMMARY(ctx->summary)->message_info; ctx->message_current = NULL; ctx->index = ibex_open(CAMEL_MBOX_FOLDER(folder)->index_file_path, FALSE); if (!ctx->index) { diff --git a/camel/providers/mbox/camel-mbox-summary.c b/camel/providers/mbox/camel-mbox-summary.c index 9216f89e97..fd72206226 100644 --- a/camel/providers/mbox/camel-mbox-summary.c +++ b/camel/providers/mbox/camel-mbox-summary.c @@ -28,7 +28,6 @@ #include "camel-exception.h" #include "camel-mbox-folder.h" #include "camel-mbox-summary.h" -#include "camel-folder-summary.h" #include "md5-utils.h" @@ -41,104 +40,230 @@ #include #include +static CamelFolderSummaryClass *parent_class = NULL; +static int count_messages (CamelFolderSummary *summary); +static int count_subfolders (CamelFolderSummary *summary); +static GPtrArray *get_subfolder_info (CamelFolderSummary *summary, + int first, int count); +static GPtrArray *get_message_info (CamelFolderSummary *summary, + int first, int count); +static void finalize (GtkObject *object); +static void +camel_mbox_summary_class_init (CamelMboxSummaryClass *camel_mbox_summary_class) +{ + GtkObjectClass *gtk_object_class = + GTK_OBJECT_CLASS (camel_mbox_summary_class); + CamelFolderSummaryClass *camel_folder_summary_class = + CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_class); -/* - * The mbox provider uses a summary files, - * so that it has an internal and an external - * summary. The internal summary is a summary - * containing a lot of information, including - * infos on how to access mails in the mbox file - * - * On the other hand, the external summary is - * an implementation of the structure defined in - * the camel-folder-summary file (toplevel camel - * directory) - * - * To sum up, the internal summary is only a - * subset of the internal summary. - */ + parent_class = gtk_type_class (camel_folder_summary_get_type ()); + + /* virtual method override */ + camel_folder_summary_class->count_messages = count_messages; + camel_folder_summary_class->count_subfolders = count_subfolders; + camel_folder_summary_class->get_subfolder_info = get_subfolder_info; + camel_folder_summary_class->get_message_info = get_message_info; + + gtk_object_class->finalize = finalize; +} + + +GtkType +camel_mbox_summary_get_type (void) +{ + static GtkType camel_mbox_summary_type = 0; + + if (!camel_mbox_summary_type) { + GtkTypeInfo camel_mbox_summary_info = + { + "CamelMboxSummary", + sizeof (CamelMboxSummary), + sizeof (CamelMboxSummaryClass), + (GtkClassInitFunc) camel_mbox_summary_class_init, + (GtkObjectInitFunc) NULL, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + camel_mbox_summary_type = gtk_type_unique (camel_folder_summary_get_type (), &camel_mbox_summary_info); + } + + return camel_mbox_summary_type; +} + +static void +finalize (GtkObject *object) +{ + CamelMboxSummary *summary = CAMEL_MBOX_SUMMARY (object); + CamelMboxSummaryInformation *info; + int i; + + for (i = 0; i < summary->message_info->len; i++) { + info = &(((CamelMboxSummaryInformation *)summary->message_info->data)[i]); + g_free (info->headers.subject); + g_free (info->headers.sender); + g_free (info->headers.to); + g_free (info->headers.sent_date); + g_free (info->headers.received_date); + g_free (info->headers.uid); + } + g_array_free (summary->message_info, TRUE); + + GTK_OBJECT_CLASS (parent_class)->finalize (object); +} + +static int +count_messages (CamelFolderSummary *summary) +{ + return CAMEL_MBOX_SUMMARY (summary)->nb_message; +} + +static int +count_subfolders (CamelFolderSummary *summary) +{ + /* XXX */ + g_warning ("CamelMboxSummary::count_subfolders not implemented"); + return 0; +} +static GPtrArray * +get_subfolder_info (CamelFolderSummary *summary, int first, int count) +{ + /* XXX */ + g_warning ("CamelMboxSummary::count_subfolders not implemented"); + return 0; +} +static GPtrArray * +get_message_info (CamelFolderSummary *summary, int first, int count) +{ + CamelMboxSummary *mbox_summary = CAMEL_MBOX_SUMMARY (summary); + CamelMboxSummaryInformation *info; + GPtrArray *arr; + + /* XXX bounds check */ + + arr = g_ptr_array_new (); + for (; count; count--) { + info = &((CamelMboxSummaryInformation *)mbox_summary->message_info->data)[first++]; + g_ptr_array_add (arr, info); + } + + return arr; +} /** - * camel_mbox_save_summary: + * camel_mbox_summary_save: * @summary: * @filename: * @ex: * - * save the internal summary into a file + * save the summary into a file **/ void -camel_mbox_save_summary (CamelMboxSummary *summary, const gchar *filename, CamelException *ex) +camel_mbox_summary_save (CamelMboxSummary *summary, const gchar *filename, + CamelException *ex) { CamelMboxSummaryInformation *msg_info; guint cur_msg; - guint field_lgth; + guint field_length; gint fd; - gint write_result; + gint write_result; /* XXX use this */ + guint32 data; CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::save_summary entering \n"); - fd = open (filename, - O_WRONLY | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR); + fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR); if (fd == -1) { - camel_exception_setv (ex, - CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, - "could not create the mbox summary file\n" - "\t%s\n" - "Full error is : %s\n", - filename, - strerror (errno)); - return; - } - - /* compute and write the mbox file md5 signature */ - //md5_get_digest_from_file (filename, summary->md5_digest); - - /* write the number of messages + the md5 signatures - + next UID + mbox file size */ - write_result = write (fd, summary, G_STRUCT_OFFSET (CamelMboxSummary, message_info)); - - - for (cur_msg=0; cur_msg < summary->nb_message; cur_msg++) { - - msg_info = (CamelMboxSummaryInformation *)(summary->message_info->data) + cur_msg; - - /* write message position + message size - + x-evolution offset + uid + status */ - write (fd, (gchar *)msg_info, - sizeof (guint32) + 2 * sizeof (guint) + - sizeof (guint32) + sizeof (guchar)); - - /* write subject */ - field_lgth = msg_info->subject ? strlen (msg_info->subject) : 0; - write (fd, &field_lgth, sizeof (guint)); - if (field_lgth) - write (fd, msg_info->subject, field_lgth); - /* write sender */ - field_lgth = msg_info->sender ? strlen (msg_info->sender) : 0; - write (fd, &field_lgth, sizeof (gint)); - if (field_lgth) - write (fd, msg_info->sender, field_lgth); - - /* write to */ - field_lgth = msg_info->to ? strlen (msg_info->to) : 0; - write (fd, &field_lgth, sizeof (gint)); - if (field_lgth) - write (fd, msg_info->to, field_lgth); - - /* write date */ - field_lgth = msg_info->date ? strlen (msg_info->date) : 0; - write (fd, &field_lgth, sizeof (guint)); - if (field_lgth) - write (fd, msg_info->date, field_lgth); - + camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, + "could not create the mbox summary " + "file\n\t%s\nFull error is : %s\n", + filename, + strerror (errno)); + return; + } + /* We write the file out in network byte order, not because + * that makes sense, but because it's easy. + */ + + data = htons (CAMEL_MBOX_SUMMARY_VERSION); + write (fd, &data, sizeof (data)); + + data = htons (summary->nb_message); + write (fd, &data, sizeof (data)); + data = htons (summary->next_uid); + write (fd, &data, sizeof (data)); + data = htons (summary->mbox_file_size); + write (fd, &data, sizeof (data)); + data = htons (summary->mbox_modtime); + write (fd, &data, sizeof (data)); + + for (cur_msg = 0; cur_msg < summary->nb_message; cur_msg++) { + msg_info = (CamelMboxSummaryInformation *) + (summary->message_info->data) + cur_msg; + + /* Write meta-info. */ + data = htons (msg_info->position); + write (fd, &data, sizeof (data)); + data = htons (msg_info->size); + write (fd, &data, sizeof (data)); + data = htons (msg_info->x_evolution_offset); + write (fd, &data, sizeof (data)); + data = htons (msg_info->uid); + write (fd, &data, sizeof (data)); + write (fd, &msg_info->status, 1); + + /* Write subject. */ + if (msg_info->headers.subject) + field_length = htons (strlen (msg_info->headers.subject)); + else + field_length = 0; + write (fd, &field_length, sizeof (field_length)); + if (msg_info->headers.subject) + write (fd, msg_info->headers.subject, field_length); + + /* Write sender. */ + if (msg_info->headers.sender) + field_length = htons (strlen (msg_info->headers.sender)); + else + field_length = 0; + write (fd, &field_length, sizeof (field_length)); + if (msg_info->headers.sender) + write (fd, msg_info->headers.sender, field_length); + + /* Write to. */ + if (msg_info->headers.to) + field_length = htons (strlen (msg_info->headers.to)); + else + field_length = 0; + write (fd, &field_length, sizeof (field_length)); + if (msg_info->headers.to) + write (fd, msg_info->headers.to, field_length); + + /* Write sent date. */ + if (msg_info->headers.sent_date) + field_length = htons (strlen (msg_info->headers.sent_date)); + else + field_length = 0; + write (fd, &field_length, sizeof (field_length)); + if (msg_info->headers.sent_date) + write (fd, msg_info->headers.sent_date, field_length); + + /* Write received date. */ + if (msg_info->headers.received_date) + field_length = htons (strlen (msg_info->headers.received_date)); + else + field_length = 0; + write (fd, &field_length, sizeof (field_length)); + if (msg_info->headers.received_date) + write (fd, msg_info->headers.received_date, field_length); } - + close (fd); CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::save_summary leaving \n"); @@ -146,227 +271,152 @@ camel_mbox_save_summary (CamelMboxSummary *summary, const gchar *filename, Camel - - /** - * camel_mbox_load_summary: + * camel_mbox_summary_load: * @filename: * @ex: * - * load the internal summary from a file + * load the summary from a file * * Return value: **/ CamelMboxSummary * -camel_mbox_load_summary (const gchar *filename, CamelException *ex) +camel_mbox_summary_load (const gchar *filename, CamelException *ex) { CamelMboxSummaryInformation *msg_info; guint cur_msg; - guint field_lgth; + guint field_length; gint fd; CamelMboxSummary *summary; gint read_result; + guint32 data; CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::save_summary entering \n"); fd = open (filename, O_RDONLY); if (fd == -1) { - camel_exception_setv (ex, - CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, - "could not open the mbox summary file\n" - "\t%s\n" - "Full error is : %s\n", - filename, - strerror (errno)); - return NULL; - } - summary = g_new0 (CamelMboxSummary, 1); - - /* read the message number, the md5 signature - and the next available UID + mbox file size */ - read_result = read (fd, summary, G_STRUCT_OFFSET (CamelMboxSummary, message_info)); - - - summary->message_info = g_array_new (FALSE, FALSE, sizeof (CamelMboxSummaryInformation)); - summary->message_info = g_array_set_size (summary->message_info, summary->nb_message); - - - for (cur_msg=0; cur_msg < summary->nb_message; cur_msg++) { - - msg_info = (CamelMboxSummaryInformation *)(summary->message_info->data) + cur_msg; - - /* read message position + message size - + x-evolution offset + uid + status */ - read (fd, (gchar *)msg_info, - sizeof (guint32) + 2 * sizeof (guint) + - sizeof (guint32) + sizeof (guchar)); - + camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, + "could not open the mbox summary file\n" + "\t%s\nFull error is : %s\n", + filename, strerror (errno)); + return NULL; + } - /* read the subject */ - read (fd, &field_lgth, sizeof (gint)); - if (field_lgth > 0) { - msg_info->subject = g_new0 (gchar, field_lgth + 1); - read (fd, msg_info->subject, field_lgth); + /* Verify version number. */ + read (fd, &data, sizeof(data)); + data = ntohs (data); + + if (data != CAMEL_MBOX_SUMMARY_VERSION) { + camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID, + "This folder summary was written by " + "%s version of this software.", + data < CAMEL_MBOX_SUMMARY_VERSION ? + "an older" : "a newer"); + return NULL; + } + + summary = CAMEL_MBOX_SUMMARY (gtk_object_new (camel_mbox_summary_get_type (), NULL)); + + read (fd, &data, sizeof(data)); + summary->nb_message = ntohs (data); + read (fd, &data, sizeof(data)); + summary->next_uid = ntohs (data); + read (fd, &data, sizeof(data)); + summary->mbox_file_size = ntohs (data); + read (fd, &data, sizeof(data)); + summary->mbox_modtime = ntohs (data); + + summary->message_info = + g_array_new (FALSE, FALSE, + sizeof (CamelMboxSummaryInformation)); + g_array_set_size (summary->message_info, summary->nb_message); + + for (cur_msg = 0; cur_msg < summary->nb_message; cur_msg++) { + msg_info = (CamelMboxSummaryInformation *) + (summary->message_info->data) + cur_msg; + + /* Read the meta-info. */ + read (fd, &data, sizeof(data)); + msg_info->position = ntohs (data); + read (fd, &data, sizeof(data)); + msg_info->size = ntohs (data); + read (fd, &data, sizeof(data)); + msg_info->x_evolution_offset = ntohs (data); + read (fd, &(msg_info->status), 1); + read (fd, &data, sizeof(data)); + msg_info->uid = ntohs (data); + msg_info->headers.uid = g_strdup_printf ("%d", msg_info->uid); + read (fd, &msg_info->status, 1); + + /* Read the subject. */ + read (fd, &field_length, sizeof (field_length)); + field_length = ntohs (field_length); + if (field_length > 0) { + msg_info->headers.subject = + g_new0 (gchar, field_length + 1); + read (fd, msg_info->headers.subject, field_length); } else - msg_info->subject = NULL; + msg_info->headers.subject = NULL; - /* read the sender */ - read (fd, &field_lgth, sizeof (gint)); - if (field_lgth > 0) { - msg_info->sender = g_new0 (gchar, field_lgth + 1); - read (fd, msg_info->sender, field_lgth); + /* Read the sender. */ + read (fd, &field_length, sizeof (field_length)); + field_length = ntohs (field_length); + if (field_length > 0) { + msg_info->headers.sender = + g_new0 (gchar, field_length + 1); + read (fd, msg_info->headers.sender, field_length); } else - msg_info->sender = NULL; + msg_info->headers.sender = NULL; - /* read the "to" field */ - read (fd, &field_lgth, sizeof (gint)); - if (field_lgth > 0) { - msg_info->to = g_new0 (gchar, field_lgth + 1); - read (fd, msg_info->to, field_lgth); + /* Read the "to" field. */ + read (fd, &field_length, sizeof (field_length)); + field_length = ntohs (field_length); + if (field_length > 0) { + msg_info->headers.to = + g_new0 (gchar, field_length + 1); + read (fd, msg_info->headers.to, field_length); } else - msg_info->to = NULL; - - /* read the "date" field */ - read (fd, &field_lgth, sizeof (gint)); - if (field_lgth > 0) { - msg_info->date = g_new0 (gchar, field_lgth + 1); - read (fd, msg_info->date, field_lgth); + msg_info->headers.to = NULL; + + /* Read the sent date field. */ + read (fd, &field_length, sizeof (field_length)); + field_length = ntohs (field_length); + if (field_length > 0) { + msg_info->headers.sent_date = + g_new0 (gchar, field_length + 1); + read (fd, msg_info->headers.sent_date, field_length); } else - msg_info->date = NULL; - - - - + msg_info->headers.sent_date = NULL; + + /* Read the received date field. */ + read (fd, &field_length, sizeof (field_length)); + field_length = ntohs (field_length); + if (field_length > 0) { + msg_info->headers.received_date = + g_new0 (gchar, field_length + 1); + read (fd, msg_info->headers.received_date, + field_length); + } else + msg_info->headers.received_date = NULL; } - - close (fd); - return summary; -} - - - - - - - - - -/** - * camel_mbox_check_summary_sync: - * @summary_filename: - * @mbox_filename: - * @ex: - * - * check if the summary file is in sync with the mbox file - * - * Return value: - **/ -gboolean -camel_mbox_check_summary_sync (gchar *summary_filename, - gchar *mbox_filename, - CamelException *ex) - -{ - gint fd; - guchar summary_md5[16]; - guchar real_md5[16]; - - - CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::save_summary entering \n"); - fd = open (summary_filename, O_RDONLY); - if (fd == -1) { - camel_exception_setv (ex, - CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, - "could not open the mbox summary file\n" - "\t%s\n" - "Full error is : %s\n", - summary_filename, - strerror (errno)); - return FALSE; - } - - /* skip the message number field */ - lseek (fd, sizeof (guint), SEEK_SET); - - /* read the md5 signature stored in the summary file */ - read (fd, summary_md5, sizeof (guchar) * 16); close (fd); - /* ** FIXME : check for exception in all these operations */ - - /* compute the actual md5 signature on the - mbox file */ - md5_get_digest_from_file (mbox_filename, real_md5); - - return (strncmp (real_md5, summary_md5, 16) == 0); + return summary; } - - - /** * camel_mbox_summary_append_entries: * @summary: * @entries: * - * append an entry to an internal summary + * append an entry to a summary **/ void camel_mbox_summary_append_entries (CamelMboxSummary *summary, GArray *entries) { - - summary->message_info = g_array_append_vals (summary->message_info, entries->data, entries->len); - -} - - - - -/** - * camel_mbox_summary_append_internal_to_external: - * @internal: - * @external: - * @first_entry: first entry to append. - * - * append some entries from the internal summary to - * the external one. - **/ -void -camel_mbox_summary_append_internal_to_external (CamelMboxSummary *internal, - CamelFolderSummary *external, - guint first_entry) -{ - GArray *internal_array; - GArray *external_array; - - CamelMessageInfo external_entry; - CamelMboxSummaryInformation *internal_entry; - - int i; - - - internal_array = internal->message_info; - external_array = external->message_info_list; - - /* we don't set any extra fields */ - external_entry.extended_fields = NULL; - - - for (i=first_entry; ilen; i++) { - internal_entry = (CamelMboxSummaryInformation *)(internal_array->data) + i; - - external_entry.subject = internal_entry->subject ? strdup (internal_entry->subject) : NULL; - external_entry.uid = g_strdup_printf ("%u", internal_entry->uid); - external_entry.sent_date = internal_entry->date ? strdup (internal_entry->date) : NULL; - external_entry.sender = internal_entry->sender ? strdup (internal_entry->sender) : NULL; - external_entry.size = internal_entry->size; - - g_array_append_vals (external_array, &external_entry, 1); - - } - - + summary->message_info = g_array_append_vals (summary->message_info, + entries->data, + entries->len); } - diff --git a/camel/providers/mbox/camel-mbox-summary.h b/camel/providers/mbox/camel-mbox-summary.h index 4ee4770a03..f8570f15c0 100644 --- a/camel/providers/mbox/camel-mbox-summary.h +++ b/camel/providers/mbox/camel-mbox-summary.h @@ -25,61 +25,61 @@ #ifndef MBOX_SUMMARY_H #define MBOX_SUMMARY_H 1 -#include +#include +#define CAMEL_MBOX_SUMMARY_TYPE (camel_mbox_summary_get_type ()) +#define CAMEL_MBOX_SUMMARY(obj) (GTK_CHECK_CAST((obj), CAMEL_MBOX_SUMMARY_TYPE, CamelMboxSummary)) +#define CAMEL_MBOX_SUMMARY_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), CAMEL_MBOX_SUMMARY_TYPE, CamelMboxSummaryClass)) +#define CAMEL_IS_MBOX_SUMMARY(o) (GTK_CHECK_TYPE((o), CAMEL_MBOX_SUMMARY_TYPE)) + + +#define CAMEL_MBOX_SUMMARY_VERSION 1 -/* This contains information about one message inside - * the mbox file. This is used in the intenal summary */ typedef struct { + CamelMessageInfo headers; guint32 position; guint size; guint x_evolution_offset; guint32 uid; guchar status; - gchar *subject; - gchar *sender; - gchar *to; - gchar *date; - gchar *received_date; } CamelMboxSummaryInformation; /* this contains informations about the whole mbox file */ typedef struct { - - guint nb_message; /* number of messages in the summary */ - guchar md5_digest[16]; /* md5 signature of the mbox file */ + CamelFolderSummary parent_object; + + guint nb_message; /* number of messages in the summary */ guint32 next_uid; guint32 mbox_file_size; - - GArray *message_info; /* array of CamelMboxSummaryInformation */ - -} CamelMboxSummary; + guint32 mbox_modtime; + GArray *message_info; /* array of CamelMboxSummaryInformation */ -void -camel_mbox_save_summary (CamelMboxSummary *summary, const gchar *filename, CamelException *ex); +} CamelMboxSummary; + +typedef struct { + CamelFolderSummaryClass parent_class; -CamelMboxSummary * -camel_mbox_load_summary (const gchar *filename, CamelException *ex); +} CamelMboxSummaryClass; -gboolean -camel_mbox_check_summary_sync (gchar *summary_filename, - gchar *mbox_filename, - CamelException *ex); -void -camel_mbox_summary_append_entries (CamelMboxSummary *summary, GArray *entries); +GtkType camel_mbox_summary_get_type (void); +void camel_mbox_summary_save (CamelMboxSummary *summary, + const gchar *filename, CamelException *ex); +CamelMboxSummary *camel_mbox_summary_load (const gchar *filename, + CamelException *ex); +gboolean camel_mbox_summary_check_sync (gchar *summary_filename, + gchar *mbox_filename, + CamelException *ex); -void -camel_mbox_summary_append_internal_to_external (CamelMboxSummary *internal, - CamelFolderSummary *external, - guint first_entry); +void camel_mbox_summary_append_entries (CamelMboxSummary *summary, + GArray *entries); -#endif /* MH_SUMMARY_H */ +#endif /* MBOX_SUMMARY_H */ diff --git a/camel/providers/mbox/camel-mbox-utils.c b/camel/providers/mbox/camel-mbox-utils.c index aa2d19a079..1b16941148 100644 --- a/camel/providers/mbox/camel-mbox-utils.c +++ b/camel/providers/mbox/camel-mbox-utils.c @@ -57,7 +57,6 @@ #include #include "camel-mbox-utils.h" #include "camel-mbox-parser.h" -#include "camel-folder-summary.h" #include "camel-mbox-summary.h" @@ -367,19 +366,23 @@ parsed_information_to_mbox_summary (GArray *parsed_information) cur_sum_info->x_evolution_offset = cur_msg_info->x_evolution_offset; cur_sum_info->uid = cur_msg_info->uid; + cur_sum_info->headers.uid = g_strdup_printf ("%d", + cur_sum_info->uid); cur_sum_info->status = cur_msg_info->status; - cur_sum_info->subject = cur_msg_info->subject; + cur_sum_info->headers.subject = cur_msg_info->subject; cur_msg_info->subject = NULL; - cur_sum_info->sender = cur_msg_info->from; + cur_sum_info->headers.sender = cur_msg_info->from; cur_msg_info->from = NULL; - cur_sum_info->to = cur_msg_info->to; + cur_sum_info->headers.to = cur_msg_info->to; cur_msg_info->to = NULL; - cur_sum_info->date = cur_msg_info->date; + /* XXX I'm guessing one of these is wrong. */ + cur_sum_info->headers.received_date = cur_msg_info->date; + cur_sum_info->headers.sent_date = g_strdup (cur_msg_info->date); cur_msg_info->date = NULL; } -- cgit v1.2.3