Diffstat (limited to 'libetpan/src/driver/implementation/mbox') (more/less context) (ignore whitespace changes)
13 files changed, 3536 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver.c b/libetpan/src/driver/implementation/mbox/mboxdriver.c new file mode 100644 index 0000000..72afa6d --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxdriver.c @@ -0,0 +1,515 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mboxdriver.h" + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <dirent.h> +#include <unistd.h> +#include <sys/stat.h> +#include <ctype.h> +#include <stdlib.h> +#include <sys/times.h> + +#include "mail.h" +#include "maildriver_tools.h" +#include "mailmbox.h" +#include "mboxdriver_tools.h" +#include "maildriver.h" +#include "carray.h" +#include "mboxdriver_message.h" +#include "mailmessage.h" + +static int mboxdriver_initialize(mailsession * session); + +static void mboxdriver_uninitialize(mailsession * session); + +static int mboxdriver_parameters(mailsession * session, + int id, void * value); + +static int mboxdriver_connect_path(mailsession * session, char * path); + +static int mboxdriver_logout(mailsession * session); + +static int mboxdriver_expunge_folder(mailsession * session); + +static int mboxdriver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int mboxdriver_messages_number(mailsession * session, char * mb, + uint32_t * result); + +static int mboxdriver_append_message(mailsession * session, + char * message, size_t size); + +static int mboxdriver_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); + +static int mboxdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +mboxdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int mboxdriver_remove_message(mailsession * session, uint32_t num); + +static int mboxdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mboxdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mbox_session_driver = { + .sess_name = "mbox", + + .sess_initialize = mboxdriver_initialize, + .sess_uninitialize = mboxdriver_uninitialize, + + .sess_parameters = mboxdriver_parameters, + + .sess_connect_path = mboxdriver_connect_path, + .sess_connect_stream = NULL, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = mboxdriver_logout, + .sess_noop = NULL, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = NULL, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = mboxdriver_expunge_folder, + .sess_status_folder = mboxdriver_status_folder, + .sess_messages_number = mboxdriver_messages_number, + .sess_recent_number = mboxdriver_messages_number, + .sess_unseen_number = mboxdriver_messages_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = mboxdriver_append_message, + .sess_append_message_flags = mboxdriver_append_message_flags, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = mboxdriver_get_messages_list, + .sess_get_envelopes_list = mboxdriver_get_envelopes_list, + .sess_remove_message = mboxdriver_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = mboxdriver_get_message, + .sess_get_message_by_uid = mboxdriver_get_message_by_uid, +}; + +mailsession_driver * mbox_session_driver = &local_mbox_session_driver; + +static inline struct mbox_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmbox_folder * get_mbox_session(mailsession * session) +{ + return get_data(session)->mbox_folder; +} + +static int mboxdriver_initialize(mailsession * session) +{ + struct mbox_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->mbox_folder = NULL; + + data->mbox_force_read_only = FALSE; + data->mbox_force_no_uid = TRUE; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + err: + return MAIL_ERROR_MEMORY; +} + +static void free_state(struct mbox_session_state_data * mbox_data) +{ + if (mbox_data->mbox_folder != NULL) { + mailmbox_done(mbox_data->mbox_folder); + mbox_data->mbox_folder = NULL; + } +} + +static void mboxdriver_uninitialize(mailsession * session) +{ + struct mbox_session_state_data * data; + + data = get_data(session); + + free_state(data); + + free(data); +} + +static int mboxdriver_parameters(mailsession * session, + int id, void * value) +{ + struct mbox_session_state_data * data; + + data = get_data(session); + + switch (id) { + case MBOXDRIVER_SET_READ_ONLY: + { + int * param; + + param = value; + + data->mbox_force_read_only = * param; + return MAIL_NO_ERROR; + } + + case MBOXDRIVER_SET_NO_UID: + { + int * param; + + param = value; + + data->mbox_force_no_uid = * param; + return MAIL_NO_ERROR; + } + } + + return MAIL_ERROR_INVAL; +} + + +static int mboxdriver_connect_path(mailsession * session, char * path) +{ + struct mbox_session_state_data * mbox_data; + struct mailmbox_folder * folder; + int r; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder != NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_init(path, + mbox_data->mbox_force_read_only, + mbox_data->mbox_force_no_uid, + 0, + &folder); + + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + mbox_data->mbox_folder = folder; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_logout(mailsession * session) +{ + struct mbox_session_state_data * mbox_data; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder == NULL) + return MAIL_ERROR_BAD_STATE; + + free_state(mbox_data); + + mbox_data->mbox_folder = NULL; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_expunge_folder(mailsession * session) +{ + int r; + struct mbox_session_state_data * mbox_data; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_expunge(mbox_data->mbox_folder); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = mboxdriver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + struct mailmbox_folder * folder; + int r; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_STATUS; + + r = mailmbox_validate_read_lock(folder); + if (r != MAIL_NO_ERROR) + return r; + + mailmbox_read_unlock(folder); + + * result = carray_count(folder->mb_tab) - folder->mb_deleted_count; + + return MAILMBOX_NO_ERROR; +} + +/* messages operations */ + +static int mboxdriver_append_message(mailsession * session, + char * message, size_t size) +{ + int r; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_APPEND; + + r = mailmbox_append_message(folder, message, size); + + switch (r) { + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + default: + return mboxdriver_mbox_error_to_mail_error(r); + } +} + +static int mboxdriver_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + return mboxdriver_append_message(session, message, size); +} + +static int mboxdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmbox_folder * folder; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + return mbox_get_messages_list(folder, session, mbox_message_driver, result); + + err: + return res; +} + +static int +mboxdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + struct mailmbox_folder * folder; + unsigned int i; + int r; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + char * headers; + size_t headers_len; + size_t cur_token; + + msg = carray_get(env_list->msg_tab, i); + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) + continue; + + r = mailmbox_fetch_msg_headers_no_lock(folder, + msg->msg_index, &headers, &headers_len); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + + cur_token = 0; + r = mailimf_envelope_fields_parse(headers, headers_len, + &cur_token, &fields); + + if (r != MAILIMF_NO_ERROR) + continue; + + msg->msg_fields = fields; + } + + mailmbox_read_unlock(folder); + + return MAIL_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + + +static int mboxdriver_remove_message(mailsession * session, uint32_t num) +{ + int r; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_DELETE; + + r = mailmbox_delete_msg(folder, num); + + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int mboxdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mbox_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + chashdatum key; + chashdatum data; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int r; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r == 0) { + char * body_len_p = p + 1; + size_t body_len; + + info = data.data; + /* Check if the cached message has the same UID */ + body_len = strtoul(body_len_p, &p, 10); + if (p == body_len_p || * p != '\0') + return MAIL_ERROR_INVAL; + + if (body_len == info->msg_body_len) + return mboxdriver_get_message(session, num, result); + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver.h b/libetpan/src/driver/implementation/mbox/mboxdriver.h new file mode 100644 index 0000000..9b37aa4 --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_H + +#define MBOXDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mboxdriver_types.h> + +extern mailsession_driver * mbox_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c new file mode 100644 index 0000000..eaa0e48 --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c @@ -0,0 +1,1337 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mboxdriver_cached.h" + +#include <stdio.h> +#include <string.h> +#include <dirent.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> + +#include "mail.h" +#include "mail_cache_db.h" +#include "mboxdriver.h" +#include "mboxdriver_tools.h" +#include "maildriver_tools.h" +#include "mailmbox.h" +#include "maildriver.h" +#include "carray.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mboxdriver_cached_message.h" +#include "libetpan-config.h" + +static int mboxdriver_cached_initialize(mailsession * session); + +static void mboxdriver_cached_uninitialize(mailsession * session); + +static int mboxdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int mboxdriver_cached_connect_path(mailsession * session, char * path); + +static int mboxdriver_cached_logout(mailsession * session); + +static int mboxdriver_cached_check_folder(mailsession * session); + +static int mboxdriver_cached_expunge_folder(mailsession * session); + +static int mboxdriver_cached_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); +static int mboxdriver_cached_messages_number(mailsession * session, char * mb, + uint32_t * result); +static int mboxdriver_cached_recent_number(mailsession * session, char * mb, + uint32_t * result); +static int mboxdriver_cached_unseen_number(mailsession * session, char * mb, + uint32_t * result); + +static int mboxdriver_cached_append_message(mailsession * session, + char * message, size_t size); + +static int mboxdriver_cached_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); + +static int +mboxdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +mboxdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int mboxdriver_cached_remove_message(mailsession * session, + uint32_t num); + +static int mboxdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mboxdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mbox_cached_session_driver = { + .sess_name = "mbox-cached", + + .sess_initialize = mboxdriver_cached_initialize, + .sess_uninitialize = mboxdriver_cached_uninitialize, + + .sess_parameters = mboxdriver_cached_parameters, + + .sess_connect_path = mboxdriver_cached_connect_path, + .sess_connect_stream = NULL, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = mboxdriver_cached_logout, + .sess_noop = NULL, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = mboxdriver_cached_check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = mboxdriver_cached_expunge_folder, + .sess_status_folder = mboxdriver_cached_status_folder, + .sess_messages_number = mboxdriver_cached_messages_number, + .sess_recent_number = mboxdriver_cached_recent_number, + .sess_unseen_number = mboxdriver_cached_unseen_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = mboxdriver_cached_append_message, + .sess_append_message_flags = mboxdriver_cached_append_message_flags, + + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = mboxdriver_cached_get_messages_list, + .sess_get_envelopes_list = mboxdriver_cached_get_envelopes_list, + .sess_remove_message = mboxdriver_cached_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = mboxdriver_cached_get_message, + .sess_get_message_by_uid = mboxdriver_cached_get_message_by_uid, +}; + +mailsession_driver * mbox_cached_session_driver = +&local_mbox_cached_session_driver; + + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + + +static int mbox_error_to_mail_error(int error) +{ + switch (error) { + case MAILMBOX_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILMBOX_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + case MAILMBOX_ERROR_FILE_NOT_FOUND: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILMBOX_ERROR_TEMPORARY_FILE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILMBOX_ERROR_MSG_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILMBOX_ERROR_READONLY: + return MAIL_ERROR_READONLY; + + default: + return MAIL_ERROR_INVAL; + } +} + + + + +static inline struct mbox_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline struct mailmbox_folder * +get_mbox_session(mailsession * session) +{ + return get_ancestor_data(session)->mbox_folder; +} + +static int mboxdriver_cached_initialize(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + struct mbox_session_state_data * mbox_data; + + cached_data = malloc(sizeof(* cached_data)); + if (cached_data == NULL) + goto err; + + cached_data->mbox_flags_store = mail_flags_store_new(); + if (cached_data->mbox_flags_store == NULL) + goto free; + + cached_data->mbox_ancestor = mailsession_new(mbox_session_driver); + if (cached_data->mbox_ancestor == NULL) + goto free_store; + + cached_data->mbox_quoted_mb = NULL; + /* + UID must be enabled to take advantage of the cache + */ + mbox_data = cached_data->mbox_ancestor->sess_data; + mbox_data->mbox_force_no_uid = FALSE; + + session->sess_data = cached_data; + + return MAIL_NO_ERROR; + + free_store: + mail_flags_store_free(cached_data->mbox_flags_store); + free: + free(cached_data); + err: + return MAIL_ERROR_MEMORY; +} + +static void free_state(struct mbox_cached_session_state_data * mbox_data) +{ + if (mbox_data->mbox_quoted_mb) { + free(mbox_data->mbox_quoted_mb); + mbox_data->mbox_quoted_mb = NULL; + } +} + +static int mbox_flags_store_process(char * flags_directory, char * quoted_mb, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (quoted_mb == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + flags_directory, MAIL_DIR_SEPARATOR, quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + if (r != MAIL_NO_ERROR) { + /* ignore errors */ + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void mboxdriver_cached_uninitialize(mailsession * session) +{ + struct mbox_cached_session_state_data * data; + + data = get_cached_data(session); + + mbox_flags_store_process(data->mbox_flags_directory, + data->mbox_quoted_mb, + data->mbox_flags_store); + + mail_flags_store_free(data->mbox_flags_store); + + free_state(data); + mailsession_free(data->mbox_ancestor); + free(data); + + session->sess_data = NULL; +} + +static int mboxdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct mbox_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->mbox_cache_directory, value, PATH_MAX); + data->mbox_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->mbox_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(data->mbox_flags_directory, value, PATH_MAX); + data->mbox_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->mbox_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MBOXDRIVER_SET_NO_UID: + return MAIL_ERROR_INVAL; + + default: + return mailsession_parameters(data->mbox_ancestor, id, value); + } +} + + +static int get_cache_directory(mailsession * session, + char * path, char ** result) +{ + char * quoted_mb; + char dirname[PATH_MAX]; + int res; + int r; + struct mbox_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + quoted_mb = maildriver_quote_mailbox(path); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(dirname, PATH_MAX, "%s%c%s", + cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + snprintf(dirname, PATH_MAX, "%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = quoted_mb; + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + + + + +#define FILENAME_MAX_UID "max-uid" + +/* write max uid current value */ + +static int write_max_uid_value(mailsession * session) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + int res; + +#if 0 + struct mbox_session_state_data * mbox_data; +#endif + struct mbox_cached_session_state_data * cached_data; + int fd; + + MMAPString * mmapstr; + size_t cur_token; + struct mailmbox_folder * folder; + + /* expunge the mailbox */ + +#if 0 + mbox_data = get_ancestor(session)->data; +#endif + folder = get_mbox_session(session); + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mbox_error_to_mail_error(r); + goto err; + } + + r = mailmbox_expunge_no_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + cached_data = get_cached_data(session); + + snprintf(filename, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID); + + fd = creat(filename, S_IRUSR | S_IWUSR); + if (fd < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + f = fdopen(fd, "w"); + if (f == NULL) { + close(fd); + res = MAIL_ERROR_FILE; + goto unlock; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mailimf_cache_int_write(mmapstr, &cur_token, + folder->mb_written_uid); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + fwrite(mmapstr->str, 1, mmapstr->len, f); + + mmap_string_free(mmapstr); + fclose(f); + mailmbox_write_unlock(folder); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +static int read_max_uid_value(mailsession * session, uint32_t * result) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + uint32_t written_uid; + int res; + + struct mbox_cached_session_state_data * cached_data; + + MMAPString * mmapstr; + size_t cur_token; + char buf[sizeof(uint32_t)]; + size_t read_size; + + cached_data = get_cached_data(session); + + snprintf(filename, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID); + + f = fopen(filename, "r"); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + read_size = fread(buf, 1, sizeof(uint32_t), f); + + mmapstr = mmap_string_new_len(buf, read_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + cur_token = 0; + + r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid); + if (r != MAIL_NO_ERROR) { + fclose(f); + res = r; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + fclose(f); + + * result = written_uid; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + err: + return res; +} + +static int mboxdriver_cached_connect_path(mailsession * session, char * path) +{ + int r; + int res; + char * quoted_mb; + struct mbox_cached_session_state_data * cached_data; + struct mbox_session_state_data * ancestor_data; + struct mailmbox_folder * folder; + uint32_t written_uid; + + folder = get_mbox_session(session); + if (folder != NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = get_cache_directory(session, path, "ed_mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + cached_data = get_cached_data(session); + free_state(cached_data); + + cached_data->mbox_quoted_mb = quoted_mb; + + written_uid = 0; + r = read_max_uid_value(session, &written_uid); + /* ignore errors */ + + ancestor_data = get_ancestor_data(session); + + r = mailmbox_init(path, + ancestor_data->mbox_force_read_only, + ancestor_data->mbox_force_no_uid, + written_uid, + &folder); + + if (r != MAILMBOX_NO_ERROR) { + cached_data->mbox_quoted_mb = NULL; + + res = mboxdriver_mbox_error_to_mail_error(r); + goto free; + } + + ancestor_data->mbox_folder = folder; + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + + +static int mboxdriver_cached_logout(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + int r; + + r = write_max_uid_value(session); + + cached_data = get_cached_data(session); + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + r = mailsession_logout(get_ancestor(session)); + if (r != MAIL_NO_ERROR) + return r; + + free_state(cached_data); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_check_folder(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_expunge_folder(mailsession * session) +{ + struct mailmbox_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mbox_cached_session_state_data * data; + int r; + unsigned int i; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + data = get_cached_data(session); + if (data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mbox_flags_store_process(data->mbox_flags_directory, + data->mbox_quoted_mb, + data->mbox_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + struct mail_flags * flags; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg_info->msg_uid, &flags); + if (r != MAIL_NO_ERROR) + continue; + + if (flags->fl_flags & MAIL_FLAG_DELETED) { + r = mailmbox_delete_msg(folder, msg_info->msg_uid); + } + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + r = mailmbox_expunge(folder); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mboxdriver_cached_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mailmbox_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mbox_cached_session_state_data * data; + int r; + unsigned int i; + uint32_t recent; + uint32_t unseen; + uint32_t num; + + num = 0; + recent = 0; + unseen = 0; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + data = get_cached_data(session); + if (data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mailmbox_read_unlock(folder); + + mbox_flags_store_process(data->mbox_flags_directory, data->mbox_quoted_mb, + data->mbox_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + struct mail_flags * flags; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg_info->msg_uid, &flags); + if (r != MAIL_NO_ERROR) { + recent ++; + unseen ++; + num ++; + continue; + } + + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + + num ++; + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = num; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mboxdriver_cached_messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + + +static int mboxdriver_cached_recent_number(mailsession * session, char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mboxdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_unseen_number(mailsession * session, char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mboxdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +/* messages operations */ + +static int mboxdriver_cached_append_message(mailsession * session, + char * message, size_t size) +{ + return mboxdriver_cached_append_message_flags(session, + message, size, NULL); +} + +static int mboxdriver_cached_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + int r; + struct mailmbox_folder * folder; + struct mbox_cached_session_state_data * data; + unsigned int uid; + struct mailmbox_msg_info * msg_info; + chashdatum key; + chashdatum value; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + MMAPString * mmapstr; + char keyname[PATH_MAX]; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_APPEND; + + r = mailmbox_append_message_uid(folder, message, size, &uid); + + switch (r) { + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + case MAILMBOX_NO_ERROR: + break; + default: + return mboxdriver_mbox_error_to_mail_error(r); + } + + /* could store in flags store instead */ + + if (flags == NULL) + goto exit; + + key.data = &uid; + key.len = sizeof(uid); + r = chash_get(folder->mb_hash, &key, &value); + if (r < 0) + goto exit; + + msg_info = value.data; + + data = get_cached_data(session); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) + goto exit; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) + goto close_db_flags; + + snprintf(keyname, PATH_MAX, "%u-%lu", uid, + (unsigned long) msg_info->msg_body_len); + + r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags); + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + if (r != MAIL_NO_ERROR) + goto exit; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + exit: + return MAIL_NO_ERROR; +} + +static int +mboxdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmbox_folder * folder; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + return mbox_get_uid_messages_list(folder, + session, mbox_cached_message_driver, result); + + err: + return res; +} + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailimf_fields * fields; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num, + (unsigned long) info->msg_body_len); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num, + (unsigned long) info->msg_body_len); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +mboxdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + struct mbox_cached_session_state_data * cached_data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + cached_data = get_cached_data(session); + if (cached_data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, session, + msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_index, + &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) + msg->msg_flags = mail_flags_new_empty(); + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + /* msg->msg_index is the numerical UID of the message */ + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + + +static int +mboxdriver_cached_remove_message(mailsession * session, uint32_t num) +{ + return mailsession_remove_message(get_ancestor(session), num); +} + +static int mboxdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mbox_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + chashdatum key; + chashdatum data; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int r; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r == 0) { + char * body_len_p = p + 1; + size_t body_len; + + info = data.data; + /* Check if the cached message has the same UID */ + body_len = strtoul(body_len_p, &p, 10); + if (p == body_len_p || * p != '\0') + return MAIL_ERROR_INVAL; + + if (body_len == info->msg_body_len) + return mboxdriver_cached_get_message(session, num, result); + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h new file mode 100644 index 0000000..25c4027 --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_CACHED_H + +#define MBOXDRIVER_CACHED_H + +#include <libetpan/libetpan-config.h> + +#include <libetpan/mboxdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mbox_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c new file mode 100644 index 0000000..9f77d32 --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c @@ -0,0 +1,361 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mboxdriver_cached_message.h" + +#include "mailmessage_tools.h" +#include "mboxdriver_tools.h" +#include "mboxdriver_cached.h" +#include "mboxdriver.h" +#include "mailmbox.h" +#include "mail_cache_db.h" +#include "generic_cache.h" + +#include <unistd.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +static int mbox_prefetch(mailmessage * msg_info); + +static void mbox_prefetch_free(struct generic_message_t * msg); + +static int mbox_initialize(mailmessage * msg_info); + +static void mbox_uninitialize(mailmessage * msg_info); + +static void mbox_flush(mailmessage * msg_info); + +static void mbox_check(mailmessage * msg_info); + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mbox_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mbox_cached_message_driver = { + .msg_name = "mbox-cached", + + .msg_initialize = mbox_initialize, + .msg_uninitialize = mbox_uninitialize, + + .msg_flush = mbox_flush, + .msg_check = mbox_check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mbox_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = mbox_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = mbox_get_flags, +}; + +mailmessage_driver * mbox_cached_message_driver = +&local_mbox_cached_message_driver; + +static inline struct mbox_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline struct mailmbox_folder * +get_mbox_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->mbox_folder; +} + +static int mbox_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mboxdriver_fetch_msg(get_ancestor_session(msg_info), + msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mbox_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int mbox_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int res; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = (char *) &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = (struct mailmbox_msg_info *) data.data; + + snprintf(static_uid, PATH_MAX, "%u-%lu", + msg_info->msg_index, (unsigned long) info->msg_body_len); + uid = strdup(static_uid); + if (uid == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + res = r; + goto err; + } + + msg = msg_info->msg_data; + + msg->msg_prefetch = mbox_prefetch; + msg->msg_prefetch_free = mbox_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void mbox_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + +#define FLAGS_NAME "flags.db" + +static void mbox_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + +static void mbox_check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_cached_session_data(msg_info)->mbox_flags_store, + msg_info); + /* ignore errors */ + } +} + + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mboxdriver_fetch_size(get_ancestor_session(msg_info), + msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + +static int mbox_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + struct mbox_cached_session_state_data * cached_data; + MMAPString * mmapstr; + struct mailmbox_folder * folder; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + flags = mail_flags_store_get(get_cached_session_data(msg_info)->mbox_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + cached_data = get_cached_session_data(msg_info); + if (cached_data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + if (msg_info->msg_index > folder->mb_written_uid) { + flags = mail_flags_new_empty(); + } + else { + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_session, + msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + return mailmessage_generic_fetch_header(msg_info, result, result_len); + } + else { + r = mboxdriver_fetch_header(get_ancestor_session(msg_info), + msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h new file mode 100644 index 0000000..144e2da --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_CACHED_MESSAGE_H + +#define MBOXDRIVER_CACHED_MESSAGE_H + +#include <libetpan/mailmessage.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_message.c b/libetpan/src/driver/implementation/mbox/mboxdriver_message.c new file mode 100644 index 0000000..9bb5a18 --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxdriver_message.c @@ -0,0 +1,225 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mboxdriver_message.h" + +#include "mailmessage_tools.h" +#include "mboxdriver_tools.h" +#include "mboxdriver.h" +#include "mailmbox.h" + +#include <unistd.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +static int mbox_prefetch(mailmessage * msg_info); + +static void mbox_prefetch_free(struct generic_message_t * msg); + +static int mbox_initialize(mailmessage * msg_info); + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mbox_message_driver = { + .msg_name = "mbox", + + .msg_initialize = mbox_initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = NULL, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mbox_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = mbox_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +}; + +mailmessage_driver * mbox_message_driver = &local_mbox_message_driver; + +static inline struct mbox_session_state_data * get_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline struct mailmbox_folder * get_mbox_session(mailmessage * msg) +{ + return get_data(msg)->mbox_folder; +} + + +static int mbox_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mboxdriver_fetch_msg(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mbox_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int mbox_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int res; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(static_uid, PATH_MAX, "%u-%lu", + msg_info->msg_index, (unsigned long) info->msg_body_len); + uid = strdup(static_uid); + if (uid == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + res = r; + goto err; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = mbox_prefetch; + msg->msg_prefetch_free = mbox_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mboxdriver_fetch_size(msg_info->msg_session, + msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + return mailmessage_generic_fetch_header(msg_info, result, result_len); + } + else { + r = mboxdriver_fetch_header(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_message.h b/libetpan/src/driver/implementation/mbox/mboxdriver_message.h new file mode 100644 index 0000000..686e46e --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_MESSAGE_H + +#define MBOXDRIVER_MESSAGE_H + +#include <libetpan/mboxdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c new file mode 100644 index 0000000..dc38cbd --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c @@ -0,0 +1,435 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mboxdriver_tools.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include "maildriver_types.h" +#include "mailmbox.h" +#include "mboxdriver_cached.h" +#include "mboxdriver.h" +#include "generic_cache.h" +#include "mailmessage.h" +#include "imfcache.h" +#include "mail_cache_db.h" + +static inline struct mbox_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmbox_folder * +session_get_mbox_session(mailsession * session) +{ + return session_get_data(session)->mbox_folder; +} + +static inline struct mbox_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * +cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return cached_session_get_ancestor(session)->sess_data; +} + +static inline struct mailmbox_folder * +cached_session_get_mbox_session(mailsession * session) +{ + return session_get_mbox_session(cached_session_get_ancestor(session)); +} + + +int mboxdriver_mbox_error_to_mail_error(int error) +{ + switch (error) { + case MAILMBOX_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILMBOX_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + case MAILMBOX_ERROR_FILE_NOT_FOUND: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILMBOX_ERROR_TEMPORARY_FILE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILMBOX_ERROR_MSG_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILMBOX_ERROR_READONLY: + return MAIL_ERROR_READONLY; + + default: + return MAIL_ERROR_INVAL; + } +} + +int mboxdriver_fetch_msg(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + int r; + char * msg_content; + size_t msg_length; + struct mailmbox_folder * folder; + + folder = session_get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_fetch_msg(folder, index, &msg_content, &msg_length); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + + +int mboxdriver_fetch_size(mailsession * session, uint32_t index, + size_t * result) +{ + struct mailmbox_folder * folder; + int r; + char * data; + size_t len; + int res; + + folder = session_get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + r = mailmbox_fetch_msg_no_lock(folder, index, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + + mailmbox_read_unlock(folder); + + * result = len; + + return MAIL_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + + +int +mboxdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = cached_session_get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-flags", num, + (unsigned long) info->msg_body_len); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +mboxdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int mboxdriver_fetch_header(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + int r; + char * msg_content; + size_t msg_length; + struct mailmbox_folder * folder; + + folder = session_get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_fetch_msg_headers(folder, index, &msg_content, &msg_length); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + +int mbox_get_locked_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + int (* lock)(struct mailmbox_folder *), + int (* unlock)(struct mailmbox_folder *), + struct mailmessage_list ** result) +{ + struct mailmessage_list * env_list; + unsigned int i; + int r; + int res; + carray * tab; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = lock(folder); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + mailmessage * msg; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlock; + } + + r = mailmessage_init(msg, session, driver, msg_info->msg_uid, + msg_info->msg_size - msg_info->msg_start_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlock; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto unlock; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlock; + } + + unlock(folder); + + * result = env_list; + + return MAIL_NO_ERROR; + + unlock: + unlock(folder); + free: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} + +static int release_read_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_read_unlock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int acquire_read_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_validate_read_lock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int release_write_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_write_unlock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int acquire_write_mbox(struct mailmbox_folder * folder) +{ + int r; + int res; + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + if (folder->mb_written_uid < folder->mb_max_uid) { + r = mailmbox_expunge_no_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + } + + return MAIL_NO_ERROR; + + unlock: + mailmbox_write_unlock(folder); + err: + return res; +} + +/* get message list with all valid written UID */ + +int mbox_get_uid_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + return mbox_get_locked_messages_list(folder, session, driver, + acquire_write_mbox, release_write_mbox, result); +} + + +/* get message list */ + +int mbox_get_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + return mbox_get_locked_messages_list(folder, session, driver, + acquire_read_mbox, release_read_mbox, result); +} diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h new file mode 100644 index 0000000..eebf98c --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h @@ -0,0 +1,85 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_TOOLS_H + +#define MBOXDRIVER_TOOLS_H + +#include "mail_cache_db_types.h" +#include "mboxdriver_types.h" +#include "mailmbox.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mboxdriver_mbox_error_to_mail_error(int error); + +int mboxdriver_fetch_msg(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +int mboxdriver_fetch_size(mailsession * session, uint32_t index, + size_t * result); + +int +mboxdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result); + +int +mboxdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, struct mail_flags * flags); + +int mbox_get_uid_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +int mbox_get_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +int mboxdriver_fetch_header(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_types.h b/libetpan/src/driver/implementation/mbox/mboxdriver_types.h new file mode 100644 index 0000000..23b9acf --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxdriver_types.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_TYPES_H + +#define MBOXDRIVER_TYPES_H + +#include <libetpan/maildriver_types.h> +#include <libetpan/mailmbox.h> +#include <libetpan/mailstorage_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* mbox driver */ + +enum { + MBOXDRIVER_SET_READ_ONLY = 1, + MBOXDRIVER_SET_NO_UID, +}; + +struct mbox_session_state_data { + struct mailmbox_folder * mbox_folder; + int mbox_force_read_only; + int mbox_force_no_uid; +}; + +/* cached version */ + +enum { + /* the mapping of the parameters should be the same as for mbox */ + MBOXDRIVER_CACHED_SET_READ_ONLY = 1, + MBOXDRIVER_CACHED_SET_NO_UID, + /* cache specific */ + MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY, + MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY, +}; + +struct mbox_cached_session_state_data { + mailsession * mbox_ancestor; + char * mbox_quoted_mb; + char mbox_cache_directory[PATH_MAX]; + char mbox_flags_directory[PATH_MAX]; + struct mail_flags_store * mbox_flags_store; +}; + +/* mbox storage */ + +/* + mbox_mailstorage is the state data specific to the mbox storage. + + - pathname is the filename that contains the mailbox. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct mbox_mailstorage { + char * mbox_pathname; + + int mbox_cached; + char * mbox_cache_directory; + char * mbox_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libetpan/src/driver/implementation/mbox/mboxstorage.c b/libetpan/src/driver/implementation/mbox/mboxstorage.c new file mode 100644 index 0000000..3944c3b --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxstorage.c @@ -0,0 +1,192 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mboxstorage.h" + +#include "mail.h" +#include "mailmessage.h" +#include "mboxdriver.h" +#include "mboxdriver_cached.h" +#include "maildriver.h" + +#include <stdlib.h> +#include <string.h> + +/* mbox storage */ + +static int mbox_mailstorage_connect(struct mailstorage * storage); +static int +mbox_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void mbox_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver mbox_mailstorage_driver = { + .sto_name = "mbox", + .sto_connect = mbox_mailstorage_connect, + .sto_get_folder_session = mbox_mailstorage_get_folder_session, + .sto_uninitialize = mbox_mailstorage_uninitialize, +}; + +int mbox_mailstorage_init(struct mailstorage * storage, + char * mbox_pathname, int mbox_cached, + char * mbox_cache_directory, char * mbox_flags_directory) +{ + struct mbox_mailstorage * mbox_storage; + + mbox_storage = malloc(sizeof(* mbox_storage)); + if (mbox_storage == NULL) + goto err; + + mbox_storage->mbox_pathname = strdup(mbox_pathname); + if (mbox_storage->mbox_pathname == NULL) + goto free; + + mbox_storage->mbox_cached = mbox_cached; + + if (mbox_cached && (mbox_cache_directory != NULL) && + (mbox_flags_directory != NULL)) { + mbox_storage->mbox_cache_directory = strdup(mbox_cache_directory); + if (mbox_storage->mbox_cache_directory == NULL) + goto free_pathname; + + mbox_storage->mbox_flags_directory = strdup(mbox_flags_directory); + if (mbox_storage->mbox_flags_directory == NULL) + goto free_cache_directory; + } + else { + mbox_storage->mbox_cached = FALSE; + mbox_storage->mbox_cache_directory = NULL; + mbox_storage->mbox_flags_directory = NULL; + } + + storage->sto_data = mbox_storage; + storage->sto_driver = &mbox_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(mbox_storage->mbox_cache_directory); + free_pathname: + free(mbox_storage->mbox_pathname); + free: + free(mbox_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void mbox_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct mbox_mailstorage * mbox_storage; + + mbox_storage = storage->sto_data; + if (mbox_storage->mbox_flags_directory != NULL) + free(mbox_storage->mbox_flags_directory); + if (mbox_storage->mbox_cache_directory != NULL) + free(mbox_storage->mbox_cache_directory); + free(mbox_storage->mbox_pathname); + free(mbox_storage); + + storage->sto_data = NULL; +} + +static int mbox_mailstorage_connect(struct mailstorage * storage) +{ + struct mbox_mailstorage * mbox_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + mbox_storage = storage->sto_data; + + if (mbox_storage->mbox_cached) + driver = mbox_cached_session_driver; + else + driver = mbox_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (mbox_storage->mbox_cached) { + r = mailsession_parameters(session, + MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY, + mbox_storage->mbox_cache_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = mailsession_parameters(session, + MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY, + mbox_storage->mbox_flags_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + r = mailsession_connect_path(session, mbox_storage->mbox_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int +mbox_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + diff --git a/libetpan/src/driver/implementation/mbox/mboxstorage.h b/libetpan/src/driver/implementation/mbox/mboxstorage.h new file mode 100644 index 0000000..45aed7b --- a/dev/null +++ b/libetpan/src/driver/implementation/mbox/mboxstorage.h @@ -0,0 +1,69 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXSTORAGE_H + +#define MBOXSTORAGE_H + +#include <libetpan/mboxdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mbox_mailstorage_init is the constructor for a mbox storage. + + @param storage this is the storage to initialize. + + @param pathname is the filename that contains the mailbox. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +int mbox_mailstorage_init(struct mailstorage * storage, + char * mb_pathname, int mb_cached, + char * mb_cache_directory, char * mb_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif |