author | zautrix <zautrix> | 2004-09-01 10:23:29 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-09-01 10:23:29 (UTC) |
commit | 6cefbdc9c8f3f3001373f10715361e2740c45395 (patch) (side-by-side diff) | |
tree | cb2c36f57620e698913c27ca4ebe59e4a7c9d46e /kmicromail/libetpan/generic | |
parent | b9257cb225cd29bab5d96fcdaf557926603ee587 (diff) | |
download | kdepimpi-6cefbdc9c8f3f3001373f10715361e2740c45395.zip kdepimpi-6cefbdc9c8f3f3001373f10715361e2740c45395.tar.gz kdepimpi-6cefbdc9c8f3f3001373f10715361e2740c45395.tar.bz2 |
Mail fixes and libetpan updated
38 files changed, 703 insertions, 40 deletions
diff --git a/kmicromail/libetpan/generic/imapdriver.c b/kmicromail/libetpan/generic/imapdriver.c index 0d63319..b3e5982 100644 --- a/kmicromail/libetpan/generic/imapdriver.c +++ b/kmicromail/libetpan/generic/imapdriver.c @@ -1,287 +1,290 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "imapdriver.h" #include "mail.h" #include "imapdriver_tools.h" #include "mailmessage.h" #include "imapdriver_message.h" #include "imapdriver_types.h" #include "maildriver.h" #include "maildriver_tools.h" #include "generic_cache.h" #include <stdlib.h> #include <string.h> static int imapdriver_initialize(mailsession * session); static void imapdriver_uninitialize(mailsession * session); static int imapdriver_connect_stream(mailsession * session, mailstream * s); static int imapdriver_starttls(mailsession * session); static int imapdriver_login(mailsession * session, char * userid, char * password); static int imapdriver_logout(mailsession * session); static int imapdriver_noop(mailsession * session); static int imapdriver_build_folder_name(mailsession * session, char * mb, char * name, char ** result); static int imapdriver_create_folder(mailsession * session, char * mb); static int imapdriver_delete_folder(mailsession * session, char * mb); static int imapdriver_rename_folder(mailsession * session, char * mb, char * new_name); static int imapdriver_check_folder(mailsession * session); static int imapdriver_examine_folder(mailsession * session, char * mb); static int imapdriver_select_folder(mailsession * session, char * mb); static int imapdriver_expunge_folder(mailsession * session); static int imapdriver_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int imapdriver_messages_number(mailsession * session, char * mb, uint32_t * result); static int imapdriver_recent_number(mailsession * session, char * mb, uint32_t * result); static int imapdriver_unseen_number(mailsession * session, char * mb, uint32_t * result); static int imapdriver_list_folders(mailsession * session, char * mb, struct mail_list ** result); static int imapdriver_lsub_folders(mailsession * session, char * mb, struct mail_list ** result); static int imapdriver_subscribe_folder(mailsession * session, char * mb); static int imapdriver_unsubscribe_folder(mailsession * session, char * mb); static int imapdriver_append_message(mailsession * session, char * message, size_t size); +static int imapdriver_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); static int imapdriver_copy_message(mailsession * session, uint32_t num, char * mb); static int imapdriver_get_messages_list(mailsession * session, struct mailmessage_list ** result); static int imapdriver_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list); #if 0 static int imapdriver_search_messages(mailsession * session, char * charset, struct mail_search_key * key, struct mail_search_result ** result); #endif static int imapdriver_get_message(mailsession * session, uint32_t num, mailmessage ** result); static int imapdriver_get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result); static mailsession_driver local_imap_session_driver = { .sess_name = "imap", .sess_initialize = imapdriver_initialize, .sess_uninitialize = imapdriver_uninitialize, .sess_parameters = NULL, .sess_connect_stream = imapdriver_connect_stream, .sess_connect_path = NULL, .sess_starttls = imapdriver_starttls, .sess_login = imapdriver_login, .sess_logout = imapdriver_logout, .sess_noop = imapdriver_noop, .sess_build_folder_name = imapdriver_build_folder_name, .sess_create_folder = imapdriver_create_folder, .sess_delete_folder = imapdriver_delete_folder, .sess_rename_folder = imapdriver_rename_folder, .sess_check_folder = imapdriver_check_folder, .sess_examine_folder = imapdriver_examine_folder, .sess_select_folder = imapdriver_select_folder, .sess_expunge_folder = imapdriver_expunge_folder, .sess_status_folder = imapdriver_status_folder, .sess_messages_number = imapdriver_messages_number, .sess_recent_number = imapdriver_recent_number, .sess_unseen_number = imapdriver_unseen_number, .sess_list_folders = imapdriver_list_folders, .sess_lsub_folders = imapdriver_lsub_folders, .sess_subscribe_folder = imapdriver_subscribe_folder, .sess_unsubscribe_folder = imapdriver_unsubscribe_folder, .sess_append_message = imapdriver_append_message, + .sess_append_message_flags = imapdriver_append_message_flags, .sess_copy_message = imapdriver_copy_message, .sess_move_message = NULL, .sess_get_messages_list = imapdriver_get_messages_list, .sess_get_envelopes_list = imapdriver_get_envelopes_list, .sess_remove_message = NULL, #if 0 .sess_search_messages = imapdriver_search_messages, #endif .sess_get_message = imapdriver_get_message, .sess_get_message_by_uid = imapdriver_get_message_by_uid, }; mailsession_driver * imap_session_driver = &local_imap_session_driver; static inline struct imap_session_state_data * get_data(mailsession * session) { return session->sess_data; } static mailimap * get_imap_session(mailsession * session) { return get_data(session)->imap_session; } static int imapdriver_initialize(mailsession * session) { struct imap_session_state_data * data; mailimap * imap; struct mail_flags_store * flags_store; imap = mailimap_new(0, NULL); if (imap == NULL) goto err; flags_store = mail_flags_store_new(); if (flags_store == NULL) goto free_session; data = malloc(sizeof(* data)); if (data == NULL) goto free_flags_store; data->imap_mailbox = NULL; data->imap_session = imap; data->imap_flags_store = flags_store; session->sess_data = data; return MAIL_NO_ERROR; free_flags_store: mail_flags_store_free(flags_store); free_session: mailimap_free(imap); err: return MAIL_ERROR_MEMORY; } static void imap_flags_store_process(mailimap * imap, struct mail_flags_store * flags_store) { unsigned int i; int r; mailmessage * first; mailmessage * last; mail_flags_store_sort(flags_store); if (carray_count(flags_store->fls_tab) == 0) return; first = carray_get(flags_store->fls_tab, 0); last = first; for(i = 1 ; i < carray_count(flags_store->fls_tab) ; i ++) { mailmessage * msg; msg = carray_get(flags_store->fls_tab, i); if (last->msg_index + 1 == msg->msg_index) { r = mail_flags_compare(first->msg_flags, msg->msg_flags); if (r == 0) { last = msg; continue; } } r = imap_store_flags(imap, first->msg_index, last->msg_index, first->msg_flags); first = msg; last = msg; } r = imap_store_flags(imap, first->msg_index, last->msg_index, first->msg_flags); mail_flags_store_clear(flags_store); } static void imapdriver_uninitialize(mailsession * session) { struct imap_session_state_data * data; data = get_data(session); imap_flags_store_process(data->imap_session, data->imap_flags_store); mail_flags_store_free(data->imap_flags_store); mailimap_free(data->imap_session); if (data->imap_mailbox != NULL) free(data->imap_mailbox); free(data); session->sess_data = NULL; } static int imapdriver_connect_stream(mailsession * session, mailstream * s) { int r; r = mailimap_connect(get_imap_session(session), s); return imap_error_to_mail_error(r); } @@ -646,256 +649,281 @@ static int imapdriver_recent_number(mailsession * session, char * mb, uint32_t recent; uint32_t unseen; int r; r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = recent; return MAIL_NO_ERROR; } static int imapdriver_unseen_number(mailsession * session, char * mb, uint32_t * result) { uint32_t messages; uint32_t recent; uint32_t unseen; int r; r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = unseen; return MAIL_NO_ERROR; } enum { IMAP_LIST, IMAP_LSUB }; static int imapdriver_list_lsub_folders(mailsession * session, int type, char * mb, struct mail_list ** result) { clist * imap_list; struct mail_list * resp; int r; int res; switch (type) { case IMAP_LIST: r = mailimap_list(get_imap_session(session), mb, "*", &imap_list); break; case IMAP_LSUB: r = mailimap_lsub(get_imap_session(session), mb, "*", &imap_list); break; default: res = MAIL_ERROR_LIST; goto err; } switch (r) { case MAILIMAP_NO_ERROR: break; default: res = imap_error_to_mail_error(r); goto err; } r = imap_list_to_list(imap_list, &resp); if (r != MAIL_NO_ERROR) { mailimap_list_result_free(imap_list); res = r; goto err; } mailimap_list_result_free(imap_list); * result = resp; return MAIL_NO_ERROR; err: return res; } static int imapdriver_list_folders(mailsession * session, char * mb, struct mail_list ** result) { return imapdriver_list_lsub_folders(session, IMAP_LIST, mb, result); } static int imapdriver_lsub_folders(mailsession * session, char * mb, struct mail_list ** result) { return imapdriver_list_lsub_folders(session, IMAP_LSUB, mb, result); } static int imapdriver_subscribe_folder(mailsession * session, char * mb) { int r; r = mailimap_subscribe(get_imap_session(session), mb); return imap_error_to_mail_error(r); } static int imapdriver_unsubscribe_folder(mailsession * session, char * mb) { int r; r = mailimap_unsubscribe(get_imap_session(session), mb); return imap_error_to_mail_error(r); } /* messages operations */ static int imapdriver_append_message(mailsession * session, char * message, size_t size) { int r; r = mailimap_append_simple(get_imap_session(session), get_data(session)->imap_mailbox, message, size); return imap_error_to_mail_error(r); } +static int imapdriver_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + struct mailimap_flag_list * flag_list; + int r; + + if (flags != NULL) { + r = imap_flags_to_imap_flags(flags, &flag_list); + if (r != MAIL_NO_ERROR) + return r; + } + else { + flag_list = NULL; + } + + r = mailimap_append(get_imap_session(session), + get_data(session)->imap_mailbox, + flag_list, NULL, message, size); + + if (flag_list != NULL) + mailimap_flag_list_free(flag_list); + + return imap_error_to_mail_error(r); +} + static int imapdriver_copy_message(mailsession * session, uint32_t num, char * mb) { int r; struct mailimap_set * set; int res; set = mailimap_set_new_single(num); if (set == NULL) { res = MAIL_ERROR_MEMORY; goto err; } r = mailimap_uid_copy(get_imap_session(session), set, mb); mailimap_set_free(set); return imap_error_to_mail_error(r); err: return res; } static int imapdriver_get_messages_list(mailsession * session, struct mailmessage_list ** result) { return imap_get_messages_list(get_imap_session(session), session, imap_message_driver, 1, result); } static int imapdriver_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list) { struct mailimap_set * set; struct mailimap_fetch_att * fetch_att; struct mailimap_fetch_type * fetch_type; int res; clist * fetch_result; int r; uint32_t exists; clist * msg_list; if (get_imap_session(session)->imap_selection_info == NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } imap_flags_store_process(get_imap_session(session), get_data(session)->imap_flags_store); exists = get_imap_session(session)->imap_selection_info->sel_exists; if (exists == 0) return MAIL_NO_ERROR; fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); if (fetch_type == NULL) { res = MAIL_ERROR_MEMORY; goto err; } fetch_att = mailimap_fetch_att_new_uid(); if (fetch_att == NULL) { res = MAIL_ERROR_MEMORY; goto free_fetch_type; } r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); if (r != MAILIMAP_NO_ERROR) { mailimap_fetch_att_free(fetch_att); res = MAIL_ERROR_MEMORY; goto free_fetch_type; } fetch_att = mailimap_fetch_att_new_flags(); if (fetch_att == NULL) { res = MAIL_ERROR_MEMORY; goto free_fetch_type; } r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); if (r != MAILIMAP_NO_ERROR) { mailimap_fetch_att_free(fetch_att); res = MAIL_ERROR_MEMORY; goto free_fetch_type; } r = imap_add_envelope_fetch_att(fetch_type); if (r != MAIL_NO_ERROR) { res = r; goto free_fetch_type; } r = maildriver_env_list_to_msg_list(env_list, &msg_list); if (r != MAIL_NO_ERROR) { res = MAIL_ERROR_MEMORY; goto free_fetch_type; } if (clist_begin(msg_list) == NULL) { /* no need to fetch envelopes */ mailimap_fetch_type_free(fetch_type); clist_free(msg_list); return MAIL_NO_ERROR; } r = msg_list_to_imap_set(msg_list, &set); if (r != MAIL_NO_ERROR) { clist_foreach(msg_list, (clist_func) free, NULL); clist_free(msg_list); res = MAIL_ERROR_MEMORY; goto free_fetch_type; } clist_foreach(msg_list, (clist_func) free, NULL); clist_free(msg_list); r = mailimap_uid_fetch(get_imap_session(session), set, fetch_type, &fetch_result); mailimap_fetch_type_free(fetch_type); mailimap_set_free(set); switch (r) { diff --git a/kmicromail/libetpan/generic/imapdriver_cached.c b/kmicromail/libetpan/generic/imapdriver_cached.c index e6af8e8..04044ae 100644 --- a/kmicromail/libetpan/generic/imapdriver_cached.c +++ b/kmicromail/libetpan/generic/imapdriver_cached.c @@ -1,295 +1,298 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "imapdriver_cached.h" #include "libetpan-config.h" #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include "mail.h" #include "imapdriver_tools.h" #include "mail_cache_db.h" #include "mailmessage.h" #include "imapdriver_cached_message.h" #include "maildriver.h" #include "imapdriver_types.h" #include "generic_cache.h" #include "imfcache.h" #include "maildriver_tools.h" #include "imapdriver.h" static int imapdriver_cached_initialize(mailsession * session); static void imapdriver_cached_uninitialize(mailsession * session); static int imapdriver_cached_parameters(mailsession * session, int id, void * value); static int imapdriver_cached_connect_stream(mailsession * session, mailstream * s); static int imapdriver_cached_starttls(mailsession * session); static int imapdriver_cached_login(mailsession * session, char * userid, char * password); static int imapdriver_cached_logout(mailsession * session); static int imapdriver_cached_noop(mailsession * session); static int imapdriver_cached_build_folder_name(mailsession * session, char * mb, char * name, char ** result); static int imapdriver_cached_create_folder(mailsession * session, char * mb); static int imapdriver_cached_delete_folder(mailsession * session, char * mb); static int imapdriver_cached_rename_folder(mailsession * session, char * mb, char * new_name); static int imapdriver_cached_check_folder(mailsession * session); static int imapdriver_cached_examine_folder(mailsession * session, char * mb); static int imapdriver_cached_select_folder(mailsession * session, char * mb); static int imapdriver_cached_expunge_folder(mailsession * session); static int imapdriver_cached_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int imapdriver_cached_messages_number(mailsession * session, char * mb, uint32_t * result); static int imapdriver_cached_recent_number(mailsession * session, char * mb, uint32_t * result); static int imapdriver_cached_unseen_number(mailsession * session, char * mb, uint32_t * result); static int imapdriver_cached_list_folders(mailsession * session, char * mb, struct mail_list ** result); static int imapdriver_cached_lsub_folders(mailsession * session, char * mb, struct mail_list ** result); static int imapdriver_cached_subscribe_folder(mailsession * session, char * mb); static int imapdriver_cached_unsubscribe_folder(mailsession * session, char * mb); static int imapdriver_cached_append_message(mailsession * session, char * message, size_t size); +static int imapdriver_cached_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); static int imapdriver_cached_copy_message(mailsession * session, uint32_t num, char * mb); static int imapdriver_cached_get_messages_list(mailsession * session, struct mailmessage_list ** result); static int imapdriver_cached_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list); static int imapdriver_cached_remove_message(mailsession * session, uint32_t num); #if 0 static int imapdriver_cached_search_messages(mailsession * session, char * charset, struct mail_search_key * key, struct mail_search_result ** result); #endif static int imapdriver_cached_get_message(mailsession * session, uint32_t num, mailmessage ** result); static int imapdriver_cached_get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result); static mailsession_driver local_imap_cached_session_driver = { .sess_name = "imap-cached", .sess_initialize = imapdriver_cached_initialize, .sess_uninitialize = imapdriver_cached_uninitialize, .sess_parameters = imapdriver_cached_parameters, .sess_connect_stream = imapdriver_cached_connect_stream, .sess_connect_path = NULL, .sess_starttls = imapdriver_cached_starttls, .sess_login = imapdriver_cached_login, .sess_logout = imapdriver_cached_logout, .sess_noop = imapdriver_cached_noop, .sess_build_folder_name = imapdriver_cached_build_folder_name, .sess_create_folder = imapdriver_cached_create_folder, .sess_delete_folder = imapdriver_cached_delete_folder, .sess_rename_folder = imapdriver_cached_rename_folder, .sess_check_folder = imapdriver_cached_check_folder, .sess_examine_folder = imapdriver_cached_examine_folder, .sess_select_folder = imapdriver_cached_select_folder, .sess_expunge_folder = imapdriver_cached_expunge_folder, .sess_status_folder = imapdriver_cached_status_folder, .sess_messages_number = imapdriver_cached_messages_number, .sess_recent_number = imapdriver_cached_recent_number, .sess_unseen_number = imapdriver_cached_unseen_number, .sess_list_folders = imapdriver_cached_list_folders, .sess_lsub_folders = imapdriver_cached_lsub_folders, .sess_subscribe_folder = imapdriver_cached_subscribe_folder, .sess_unsubscribe_folder = imapdriver_cached_unsubscribe_folder, .sess_append_message = imapdriver_cached_append_message, + .sess_append_message_flags = imapdriver_cached_append_message_flags, .sess_copy_message = imapdriver_cached_copy_message, .sess_move_message = NULL, .sess_get_messages_list = imapdriver_cached_get_messages_list, .sess_get_envelopes_list = imapdriver_cached_get_envelopes_list, .sess_remove_message = imapdriver_cached_remove_message, #if 0 .sess_search_messages = imapdriver_cached_search_messages, #endif .sess_get_message = imapdriver_cached_get_message, .sess_get_message_by_uid = imapdriver_cached_get_message_by_uid, }; mailsession_driver * imap_cached_session_driver = &local_imap_cached_session_driver; #define CACHE_MESSAGE_LIST static inline struct imap_cached_session_state_data * get_cached_data(mailsession * session) { return session->sess_data; } static inline mailsession * get_ancestor(mailsession * s) { return get_cached_data(s)->imap_ancestor; } static inline struct imap_session_state_data * get_ancestor_data(mailsession * s) { return get_ancestor(s)->sess_data; } static inline mailimap * get_imap_session(mailsession * session) { return get_ancestor_data(session)->imap_session; } static int imapdriver_cached_initialize(mailsession * session) { struct imap_cached_session_state_data * data; data = malloc(sizeof(* data)); if (data == NULL) goto err; data->imap_ancestor = mailsession_new(imap_session_driver); if (data->imap_ancestor == NULL) goto free_data; data->imap_quoted_mb = NULL; data->imap_cache_directory[0] = '\0'; data->imap_uid_list = carray_new(128); if (data->imap_uid_list == NULL) goto free_session; session->sess_data = data; return MAIL_NO_ERROR; free_session: mailsession_free(data->imap_ancestor); free_data: free(data); err: return MAIL_ERROR_MEMORY; } static void free_quoted_mb(struct imap_cached_session_state_data * imap_cached_data) { if (imap_cached_data->imap_quoted_mb != NULL) { free(imap_cached_data->imap_quoted_mb); imap_cached_data->imap_quoted_mb = NULL; } } struct uid_cache_item { uint32_t uid; uint32_t size; }; static int update_uid_cache(mailsession * session, struct mailmessage_list * env_list) { unsigned int i; int r; struct imap_cached_session_state_data * data; int res; data = get_cached_data(session); /* free all UID cache */ for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { struct uid_cache_item * cache_item; cache_item = carray_get(data->imap_uid_list, i); free(cache_item); } /* build UID cache */ r = carray_set_size(data->imap_uid_list, carray_count(env_list->msg_tab)); if (r < 0) { res = MAIL_ERROR_MEMORY; goto err; } for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { struct uid_cache_item * cache_item; mailmessage * msg; cache_item = malloc(sizeof(* cache_item)); if (cache_item == NULL) { res = MAIL_ERROR_MEMORY; goto err; } msg = carray_get(env_list->msg_tab, i); cache_item->uid = msg->msg_index; cache_item->size = msg->msg_size; carray_set(data->imap_uid_list, i, cache_item); } return MAIL_NO_ERROR; @@ -651,256 +654,269 @@ static int imapdriver_cached_select_folder(mailsession * session, char * mb) /* clear UID cache */ carray_set_size(data->imap_uid_list, 0); return MAIL_NO_ERROR; } static int imapdriver_cached_expunge_folder(mailsession * session) { int r; r = mailsession_expunge_folder(get_ancestor(session)); check_for_uid_cache(session); return r; } static int imapdriver_cached_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen) { int r; r = mailsession_status_folder(get_ancestor(session), mb, result_messages, result_recent, result_unseen); check_for_uid_cache(session); return r; } static int imapdriver_cached_messages_number(mailsession * session, char * mb, uint32_t * result) { int r; r = mailsession_messages_number(get_ancestor(session), mb, result); check_for_uid_cache(session); return r; } static int imapdriver_cached_recent_number(mailsession * session, char * mb, uint32_t * result) { int r; r = mailsession_recent_number(get_ancestor(session), mb, result); check_for_uid_cache(session); return r; } static int imapdriver_cached_unseen_number(mailsession * session, char * mb, uint32_t * result) { int r; r = mailsession_unseen_number(get_ancestor(session), mb, result); check_for_uid_cache(session); return r; } static int imapdriver_cached_list_folders(mailsession * session, char * mb, struct mail_list ** result) { int r; r = mailsession_list_folders(get_ancestor(session), mb, result); check_for_uid_cache(session); return r; } static int imapdriver_cached_lsub_folders(mailsession * session, char * mb, struct mail_list ** result) { int r; r = mailsession_lsub_folders(get_ancestor(session), mb, result); check_for_uid_cache(session); return r; } static int imapdriver_cached_subscribe_folder(mailsession * session, char * mb) { int r; r = mailsession_subscribe_folder(get_ancestor(session), mb); check_for_uid_cache(session); return r; } static int imapdriver_cached_unsubscribe_folder(mailsession * session, char * mb) { int r; r = mailsession_unsubscribe_folder(get_ancestor(session), mb); check_for_uid_cache(session); return r; } static int imapdriver_cached_append_message(mailsession * session, char * message, size_t size) { int r; r = mailsession_append_message(get_ancestor(session), message, size); check_for_uid_cache(session); return r; } +static int imapdriver_cached_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + int r; + + r = mailsession_append_message_flags(get_ancestor(session), + message, size, flags); + + check_for_uid_cache(session); + + return r; +} + static int imapdriver_cached_copy_message(mailsession * session, uint32_t num, char * mb) { int r; r = mailsession_copy_message(get_ancestor(session), num, mb); check_for_uid_cache(session); return r; } static int cmp_uid(uint32_t ** pa, uint32_t ** pb) { uint32_t * a; uint32_t * b; a = * pa; b = * pb; return * a - * b; } static int imapdriver_cached_get_messages_list(mailsession * session, struct mailmessage_list ** result) { #if 0 mailsession * imap_session; #endif mailimap * imap; uint32_t uid_max; struct imap_cached_session_state_data * data; struct mailmessage_list * env_list; unsigned i; int r; int res; carray * tab; #if 0 data = session->data; imap_session = get_ancestor(session); imap = ((struct imap_session_state_data *) (imap_session->data))->session; #endif data = get_cached_data(session); imap = get_imap_session(session); uid_max = 0; #ifdef CACHE_MESSAGE_LIST /* get UID max */ uid_max = 0; for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { struct uid_cache_item * cache_item; cache_item = carray_get(data->imap_uid_list, i); if (cache_item->uid > uid_max) uid_max = cache_item->uid; } #endif r = imap_get_messages_list(imap, session, imap_cached_message_driver, uid_max + 1, &env_list); check_for_uid_cache(session); if (r != MAIL_NO_ERROR) { res = r; goto err; } #ifdef CACHE_MESSAGE_LIST /* remove unsollicited message */ i = 0; while (i < carray_count(env_list->msg_tab)) { mailmessage * msg; msg = carray_get(env_list->msg_tab, i); if (msg->msg_index < uid_max + 1) carray_delete(env_list->msg_tab, i); else i ++; } tab = carray_new(carray_count(env_list->msg_tab) + carray_count(data->imap_uid_list)); if (tab == NULL) { res = MAIL_ERROR_MEMORY; goto free; } carray_set_size(tab, carray_count(env_list->msg_tab) + carray_count(data->imap_uid_list)); /* sort cached data before adding them to the list */ qsort(carray_data(data->imap_uid_list), carray_count(data->imap_uid_list), sizeof(* carray_data(data->imap_uid_list)), (int (*)(const void *, const void *)) cmp_uid); /* adds cached UID */ for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { struct uid_cache_item * cache_item; mailmessage * msg; cache_item = carray_get(data->imap_uid_list, i); msg = mailmessage_new(); if (msg == NULL) { res = MAIL_ERROR_MEMORY; goto free; } r = mailmessage_init(msg, session, imap_cached_message_driver, cache_item->uid, cache_item->size); if (r != MAIL_NO_ERROR) { mailmessage_free(msg); res = r; goto free; } carray_set(tab, i, msg); } /* adds new elements */ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { mailmessage * msg; msg = carray_get(env_list->msg_tab, i); diff --git a/kmicromail/libetpan/generic/imapdriver_cached_message.c b/kmicromail/libetpan/generic/imapdriver_cached_message.c index c0542a3..c4357a3 100644 --- a/kmicromail/libetpan/generic/imapdriver_cached_message.c +++ b/kmicromail/libetpan/generic/imapdriver_cached_message.c @@ -87,257 +87,257 @@ static int imap_fetch_section_header(mailmessage * msg_info, static int imap_fetch_section_mime(mailmessage * msg_info, struct mailmime * mime, char ** result, size_t * result_len); static int imap_fetch_section_body(mailmessage * msg_info, struct mailmime * mime, char ** result, size_t * result_len); static int imap_fetch_envelope(mailmessage * msg_info, struct mailimf_fields ** result); static int imap_get_flags(mailmessage * msg_info, struct mail_flags ** result); static mailmessage_driver local_imap_cached_message_driver = { .msg_name = "imap-cached", .msg_initialize = imap_initialize, .msg_uninitialize = imap_uninitialize, .msg_flush = imap_flush, .msg_check = imap_check, .msg_fetch_result_free = imap_fetch_result_free, .msg_fetch = imap_fetch, .msg_fetch_header = imap_fetch_header, .msg_fetch_body = imap_fetch_body, .msg_fetch_size = imap_fetch_size, .msg_get_bodystructure = imap_get_bodystructure, .msg_fetch_section = imap_fetch_section, .msg_fetch_section_header = imap_fetch_section_header, .msg_fetch_section_mime = imap_fetch_section_mime, .msg_fetch_section_body = imap_fetch_section_body, .msg_fetch_envelope = imap_fetch_envelope, .msg_get_flags = imap_get_flags, }; mailmessage_driver * imap_cached_message_driver = &local_imap_cached_message_driver; static inline struct imap_cached_session_state_data * get_cached_session_data(mailmessage * msg) { return msg->msg_session->sess_data; } static inline mailmessage * get_ancestor(mailmessage * msg_info) { return msg_info->msg_data; } static inline struct imap_cached_session_state_data * cached_session_get_data(mailsession * s) { return s->sess_data; } static inline mailsession * cached_session_get_ancestor(mailsession * s) { return cached_session_get_data(s)->imap_ancestor; } static inline struct imap_session_state_data * cached_session_get_ancestor_data(mailsession * s) { return cached_session_get_ancestor(s)->sess_data; } static inline mailimap * cached_session_get_imap_session(mailsession * session) { return cached_session_get_ancestor_data(session)->imap_session; } static inline mailimap * get_imap_session(mailmessage * msg) { return cached_session_get_imap_session(msg->msg_session); } static inline mailsession * get_ancestor_session(mailmessage * msg_info) { return cached_session_get_ancestor(msg_info->msg_session); } static void generate_key_from_mime_section(char * key, size_t size, struct mailmime * mime) { clistiter * cur; MMAPString * gstr; struct mailmime_section * part; int r; snprintf(key, size, "unvalid"); r = mailmime_get_section_id(mime, &part); if (r != MAILIMF_NO_ERROR) goto err; gstr = mmap_string_new("part"); if (gstr == NULL) goto free_section; for(cur = clist_begin(part->sec_list) ; cur != NULL ; cur = clist_next(cur)) { char s[20]; snprintf(s, 20, ".%u", * (uint32_t *) clist_content(cur)); if (mmap_string_append(gstr, s) == NULL) goto free_str; } snprintf(key, size, "%s", gstr->str); mmap_string_free(gstr); mailmime_section_free(part); return; free_str: mmap_string_free(gstr); free_section: mailmime_section_free(part); - err: + err:; } static void generate_key_from_section(char * key, size_t size, mailmessage * msg_info, struct mailmime * mime, int type) { char section_str[PATH_MAX]; generate_key_from_mime_section(section_str, PATH_MAX, mime); switch (type) { case IMAP_SECTION_MESSAGE: snprintf(key, size, "%s-%s", msg_info->msg_uid, section_str); break; case IMAP_SECTION_HEADER: snprintf(key, size, "%s-%s-header", msg_info->msg_uid, section_str); break; case IMAP_SECTION_MIME: snprintf(key, size, "%s-%s-mime", msg_info->msg_uid, section_str); break; case IMAP_SECTION_BODY: snprintf(key, size, "%s-%s-text", msg_info->msg_uid, section_str); break; } } static void generate_key_from_message(char * key, size_t size, mailmessage * msg_info, int type) { switch (type) { case MAILIMAP_MSG_ATT_RFC822: snprintf(key, size, "%s-rfc822", msg_info->msg_uid); break; case MAILIMAP_MSG_ATT_RFC822_HEADER: snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid); break; case MAILIMAP_MSG_ATT_RFC822_TEXT: snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid); break; case MAILIMAP_MSG_ATT_ENVELOPE: snprintf(key, size, "%s-envelope", msg_info->msg_uid); break; } } static void build_cache_name(char * filename, size_t size, mailmessage * msg, char * key) { char * quoted_mb; quoted_mb = get_cached_session_data(msg)->imap_quoted_mb; snprintf(filename, size, "%s/%s", quoted_mb, key); } static int imap_initialize(mailmessage * msg_info) { mailmessage * ancestor; int r; char key[PATH_MAX]; char * uid; mailimap * imap; ancestor = mailmessage_new(); if (ancestor == NULL) return MAIL_ERROR_MEMORY; r = mailmessage_init(ancestor, get_ancestor_session(msg_info), imap_message_driver, msg_info->msg_index, 0); if (r != MAIL_NO_ERROR) { mailmessage_free(ancestor); return r; } imap = get_imap_session(msg_info); snprintf(key, PATH_MAX, "%u-%u", imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index); uid = strdup(key); if (uid == NULL) { mailmessage_free(ancestor); return MAIL_ERROR_MEMORY; } msg_info->msg_data = ancestor; msg_info->msg_uid = uid; return MAIL_NO_ERROR; } static void imap_uninitialize(mailmessage * msg_info) { mailmessage_free(get_ancestor(msg_info)); msg_info->msg_data = NULL; } static void imap_flush(mailmessage * msg_info) { if (msg_info->msg_mime != NULL) { mailmime_free(msg_info->msg_mime); msg_info->msg_mime = NULL; } } static void imap_check(mailmessage * msg_info) { get_ancestor(msg_info)->msg_flags = msg_info->msg_flags; mailmessage_check(get_ancestor(msg_info)); get_ancestor(msg_info)->msg_flags = NULL; } static void imap_fetch_result_free(mailmessage * msg_info, char * msg) { mailmessage_fetch_result_free(get_ancestor(msg_info), msg); } static int imap_fetch(mailmessage * msg_info, char ** result, size_t * result_len) { char key[PATH_MAX]; char filename[PATH_MAX]; int r; char * str; size_t len; diff --git a/kmicromail/libetpan/generic/imapdriver_tools.c b/kmicromail/libetpan/generic/imapdriver_tools.c index 3d737f3..de4008f 100644 --- a/kmicromail/libetpan/generic/imapdriver_tools.c +++ b/kmicromail/libetpan/generic/imapdriver_tools.c @@ -2982,399 +2982,423 @@ uid_list_to_env_list(clist * fetch_result, if (r < 0) { res = MAIL_ERROR_MEMORY; goto free_msg; } } env_list = mailmessage_list_new(tab); if (env_list == NULL) { res = MAIL_ERROR_MEMORY; goto free_list; } * result = env_list; return MAIL_NO_ERROR; free_msg: mailmessage_free(msg); free_list: for(i = 0 ; i < carray_count(tab) ; i++) mailmessage_free(carray_get(tab, i)); err: return res; } /* MAILIMAP_FLAG_FETCH_RECENT, MAILIMAP_FLAG_FETCH_OTHER MAILIMAP_FLAG_ANSWERED, MAILIMAP_FLAG_FLAGGED, MAILIMAP_FLAG_DELETED, MAILIMAP_FLAG_SEEN, MAILIMAP_FLAG_DRAFT, MAILIMAP_FLAG_KEYWORD, MAILIMAP_FLAG_EXTENSION */ static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, struct mail_flags ** result) { struct mail_flags * flags; clist * flag_list; clistiter * cur; flags = mail_flags_new_empty(); if (flags == NULL) goto err; flags->fl_flags = 0; flag_list = att_dyn->att_list; if (flag_list != NULL) { for(cur = clist_begin(flag_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailimap_flag_fetch * flag_fetch; flag_fetch = clist_content(cur); if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT) flags->fl_flags |= MAIL_FLAG_NEW; else { char * keyword; int r; switch (flag_fetch->fl_flag->fl_type) { case MAILIMAP_FLAG_ANSWERED: flags->fl_flags |= MAIL_FLAG_ANSWERED; break; case MAILIMAP_FLAG_FLAGGED: flags->fl_flags |= MAIL_FLAG_FLAGGED; break; case MAILIMAP_FLAG_DELETED: flags->fl_flags |= MAIL_FLAG_DELETED; break; case MAILIMAP_FLAG_SEEN: flags->fl_flags |= MAIL_FLAG_SEEN; break; case MAILIMAP_FLAG_DRAFT: keyword = strdup("Draft"); if (keyword == NULL) goto free; r = clist_append(flags->fl_extension, keyword); if (r < 0) { free(keyword); goto free; } break; case MAILIMAP_FLAG_KEYWORD: if (strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, "$Forwarded") == 0) { flags->fl_flags |= MAIL_FLAG_FORWARDED; } else { keyword = strdup(flag_fetch->fl_flag->fl_data.fl_keyword); if (keyword == NULL) goto free; r = clist_append(flags->fl_extension, keyword); if (r < 0) { free(keyword); goto free; } } break; case MAILIMAP_FLAG_EXTENSION: /* do nothing */ break; } } } /* MAIL_FLAG_NEW was set for \Recent messages. Correct this flag for \Seen messages by unsetting it. */ if ((flags->fl_flags & MAIL_FLAG_SEEN) && (flags->fl_flags & MAIL_FLAG_NEW)) { flags->fl_flags &= ~MAIL_FLAG_NEW; } } * result = flags; return MAIL_NO_ERROR; free: mail_flags_free(flags); err: return MAIL_ERROR_MEMORY; } -static int flags_to_imap_flags(struct mail_flags * flags, - struct mailimap_store_att_flags ** result) +int imap_flags_to_imap_flags(struct mail_flags * flags, + struct mailimap_flag_list ** result) { struct mailimap_flag * flag; struct mailimap_flag_list * flag_list; - struct mailimap_store_att_flags * att_flags; int res; clistiter * cur; int r; - + flag_list = mailimap_flag_list_new_empty(); if (flag_list == NULL) { res = MAIL_ERROR_MEMORY; goto err; } if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0) { flag = mailimap_flag_new_deleted(); if (flag == NULL) { res = MAIL_ERROR_MEMORY; goto free_flag_list; } r = mailimap_flag_list_add(flag_list, flag); if (r != MAILIMAP_NO_ERROR) { mailimap_flag_free(flag); res = MAIL_ERROR_MEMORY; goto free_flag_list; } } if ((flags->fl_flags & MAIL_FLAG_FLAGGED) != 0) { flag = mailimap_flag_new_flagged(); if (flag == NULL) { res = MAIL_ERROR_MEMORY; goto free_flag_list; } r = mailimap_flag_list_add(flag_list, flag); if (r != MAILIMAP_NO_ERROR) { mailimap_flag_free(flag); res = MAIL_ERROR_MEMORY; goto free_flag_list; } } if ((flags->fl_flags & MAIL_FLAG_SEEN) != 0) { flag = mailimap_flag_new_seen(); if (flag == NULL) { res = MAIL_ERROR_MEMORY; goto free_flag_list; } r = mailimap_flag_list_add(flag_list, flag); if (r != MAILIMAP_NO_ERROR) { res = MAIL_ERROR_MEMORY; goto free_flag_list; } } if ((flags->fl_flags & MAIL_FLAG_ANSWERED) != 0) { flag = mailimap_flag_new_answered(); if (flag == NULL) { res = MAIL_ERROR_MEMORY; goto free_flag_list; } r = mailimap_flag_list_add(flag_list, flag); if (r != MAILIMAP_NO_ERROR) { mailimap_flag_free(flag); res = MAIL_ERROR_MEMORY; goto free_flag_list; } } if ((flags->fl_flags & MAIL_FLAG_FORWARDED) != 0) { char * flag_str; flag_str = strdup("$Forwarded"); if (flag_str == NULL) { res = MAIL_ERROR_MEMORY; goto free_flag_list; } flag = mailimap_flag_new_flag_keyword(flag_str); if (flag == NULL) { free(flag_str); res = MAIL_ERROR_MEMORY; goto free_flag_list; } r = mailimap_flag_list_add(flag_list, flag); if (r != MAILIMAP_NO_ERROR) { mailimap_flag_free(flag); res = MAIL_ERROR_MEMORY; goto free_flag_list; } } for(cur = clist_begin(flags->fl_extension) ; cur != NULL ; cur = clist_next(cur)) { char * flag_str; flag_str = clist_content(cur); if (strcasecmp(flag_str, "Draft") == 0) { flag = mailimap_flag_new_draft(); if (flag == NULL) { res = MAIL_ERROR_MEMORY; goto free_flag_list; } r = mailimap_flag_list_add(flag_list, flag); if (r != MAILIMAP_NO_ERROR) { mailimap_flag_free(flag); res = MAIL_ERROR_MEMORY; goto free_flag_list; } } else { flag_str = strdup(flag_str); if (flag_str == NULL) { res = MAIL_ERROR_MEMORY; goto free_flag_list; } flag = mailimap_flag_new_flag_keyword(flag_str); if (flag == NULL) { free(flag_str); res = MAIL_ERROR_MEMORY; goto free_flag_list; } r = mailimap_flag_list_add(flag_list, flag); if (r != MAILIMAP_NO_ERROR) { mailimap_flag_free(flag); res = MAIL_ERROR_MEMORY; goto free_flag_list; } } } + + * result = flag_list; + + return MAIL_NO_ERROR; + + free_flag_list: + mailimap_flag_list_free(flag_list); + err: + return res; +} +static int flags_to_imap_flags(struct mail_flags * flags, + struct mailimap_store_att_flags ** result) +{ + struct mailimap_flag_list * flag_list; + struct mailimap_store_att_flags * att_flags; + int res; + int r; + + r = imap_flags_to_imap_flags(flags, + &flag_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + att_flags = mailimap_store_att_flags_new_set_flags_silent(flag_list); if (att_flags == NULL) { res = MAIL_ERROR_MEMORY; goto free_flag_list; } - + * result = att_flags; - + return MAIL_NO_ERROR; - + free_flag_list: mailimap_flag_list_free(flag_list); err: return res; } static int imap_fetch_result_to_flags(clist * fetch_result, uint32_t index, struct mail_flags ** result) { clistiter * cur; int r; for(cur = clist_begin(fetch_result) ; cur != NULL ; cur = clist_next(cur)) { struct mailimap_msg_att * msg_att; clistiter * item_cur; uint32_t uid; struct mailimap_msg_att_dynamic * att_dyn; msg_att = clist_content(cur); uid = 0; att_dyn = NULL; for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ; item_cur = clist_next(item_cur)) { struct mailimap_msg_att_item * item; item = clist_content(item_cur); if (item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { switch (item->att_data.att_static->att_type) { case MAILIMAP_MSG_ATT_UID: uid = item->att_data.att_static->att_data.att_uid; break; } } else if (item->att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC) { if (att_dyn == NULL) { att_dyn = item->att_data.att_dyn; } } } if (uid != 0) { if (uid == index) { struct mail_flags * flags; if (att_dyn != NULL) { r = imap_flags_to_flags(att_dyn, &flags); if (r == MAIL_NO_ERROR) { * result = flags; return MAIL_NO_ERROR; } } } } } return MAIL_ERROR_MSG_NOT_FOUND; } int imap_fetch_flags(mailimap * imap, uint32_t index, struct mail_flags ** result) { struct mailimap_fetch_att * fetch_att; struct mailimap_fetch_type * fetch_type; struct mailimap_set * set; int r; int res; clist * fetch_result; struct mail_flags * flags; fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); if (fetch_type == NULL) { res = MAIL_ERROR_MEMORY; goto err; } fetch_att = mailimap_fetch_att_new_uid(); if (fetch_att == NULL) { res = MAIL_ERROR_MEMORY; goto free_fetch_type; } r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); if (r != MAILIMAP_NO_ERROR) { mailimap_fetch_att_free(fetch_att); res = MAIL_ERROR_MEMORY; goto free_fetch_type; } fetch_att = mailimap_fetch_att_new_flags(); if (fetch_att == NULL) { res = MAIL_ERROR_MEMORY; goto free_fetch_type; } r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); if (r != MAILIMAP_NO_ERROR) { mailimap_fetch_att_free(fetch_att); res = MAIL_ERROR_MEMORY; goto free_fetch_type; } set = mailimap_set_new_single(index); if (set == NULL) { res = MAIL_ERROR_MEMORY; goto free_fetch_type; } r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result); mailimap_fetch_type_free(fetch_type); mailimap_set_free(set); switch (r) { case MAILIMAP_NO_ERROR: break; default: return imap_error_to_mail_error(r); } r = imap_fetch_result_to_flags(fetch_result, index, &flags); diff --git a/kmicromail/libetpan/generic/imapdriver_tools.h b/kmicromail/libetpan/generic/imapdriver_tools.h index 6582a31..59c993e 100644 --- a/kmicromail/libetpan/generic/imapdriver_tools.h +++ b/kmicromail/libetpan/generic/imapdriver_tools.h @@ -1,113 +1,116 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 IMAPDRIVER_TOOLS_H #define IMAPDRIVER_TOOLS_H #include "mailimap.h" #include "mailmime.h" #include "imapdriver_types.h" #include "mail_cache_db.h" #ifdef __cplusplus extern "C" { #endif int imap_list_to_list(clist * imap_list, struct mail_list ** result); int section_to_imap_section(struct mailmime_section * section, int type, struct mailimap_section ** result); int imap_get_msg_att_info(struct mailimap_msg_att * msg_att, uint32_t * puid, struct mailimap_envelope ** pimap_envelope, char ** preferences, size_t * pref_size, struct mailimap_msg_att_dynamic ** patt_dyn, struct mailimap_body ** pimap_body); int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type); int imap_env_to_fields(struct mailimap_envelope * env, char * ref_str, size_t ref_size, struct mailimf_fields ** result); int imap_fetch_result_to_envelop_list(clist * fetch_result, struct mailmessage_list * env_list); int imap_body_to_body(struct mailimap_body * imap_body, struct mailmime ** result); #if 0 int mail_search_to_imap_search(struct mail_search_key * key, struct mailimap_search_key ** result); #endif int msg_list_to_imap_set(clist * msg_list, struct mailimap_set ** result); int imap_error_to_mail_error(int error); int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last, struct mail_flags * flags); int imap_fetch_flags(mailimap * imap, uint32_t index, struct mail_flags ** result); int imap_get_messages_list(mailimap * imap, mailsession * session, mailmessage_driver * driver, uint32_t first_index, struct mailmessage_list ** result); int imapdriver_get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, mailsession * session, mailmessage * msg, struct mailimf_fields ** result); int imapdriver_write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, mailsession * session, mailmessage * msg, struct mailimf_fields * fields); +int imap_flags_to_imap_flags(struct mail_flags * flags, + struct mailimap_flag_list ** result); + #ifdef __cplusplus } #endif #endif diff --git a/kmicromail/libetpan/generic/imapstorage.c b/kmicromail/libetpan/generic/imapstorage.c index e8683d8..972b6dd 100644 --- a/kmicromail/libetpan/generic/imapstorage.c +++ b/kmicromail/libetpan/generic/imapstorage.c @@ -1,202 +1,202 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "imapstorage.h" #include <stdlib.h> #include <string.h> #include "mail.h" #include "imapdriver.h" #include "imapdriver_cached.h" #include "mailstorage_tools.h" #include "maildriver.h" /* imap storage */ #define IMAP_DEFAULT_PORT 143 #define IMAPS_DEFAULT_PORT 993 static int imap_mailstorage_connect(struct mailstorage * storage); static int imap_mailstorage_get_folder_session(struct mailstorage * storage, char * pathname, mailsession ** result); static void imap_mailstorage_uninitialize(struct mailstorage * storage); static mailstorage_driver imap_mailstorage_driver = { .sto_name = "imap", .sto_connect = imap_mailstorage_connect, .sto_get_folder_session = imap_mailstorage_get_folder_session, .sto_uninitialize = imap_mailstorage_uninitialize, }; int imap_mailstorage_init(struct mailstorage * storage, char * imap_servername, uint16_t imap_port, char * imap_command, int imap_connection_type, int imap_auth_type, char * imap_login, char * imap_password, int imap_cached, char * imap_cache_directory) { struct imap_mailstorage * imap_storage; - imap_storage = malloc(sizeof(struct imap_mailstorage)); + imap_storage = malloc(sizeof(* imap_storage)); if (imap_storage == NULL) goto err; imap_storage->imap_servername = strdup(imap_servername); if (imap_storage->imap_servername == NULL) goto free; imap_storage->imap_connection_type = imap_connection_type; if (imap_port == 0) { switch (imap_connection_type) { case CONNECTION_TYPE_PLAIN: case CONNECTION_TYPE_TRY_STARTTLS: case CONNECTION_TYPE_STARTTLS: case CONNECTION_TYPE_COMMAND: case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: case CONNECTION_TYPE_COMMAND_STARTTLS: imap_port = IMAP_DEFAULT_PORT; break; case CONNECTION_TYPE_TLS: case CONNECTION_TYPE_COMMAND_TLS: imap_port = IMAPS_DEFAULT_PORT; break; } } imap_storage->imap_port = imap_port; if (imap_command != NULL) { imap_storage->imap_command = strdup(imap_command); if (imap_storage->imap_command == NULL) goto free_servername; } else imap_storage->imap_command = NULL; imap_storage->imap_auth_type = imap_auth_type; if (imap_login != NULL) { imap_storage->imap_login = strdup(imap_login); if (imap_storage->imap_login == NULL) goto free_command; } else imap_storage->imap_login = NULL; if (imap_password != NULL) { imap_storage->imap_password = strdup(imap_password); if (imap_storage->imap_password == NULL) goto free_login; } else imap_storage->imap_password = NULL; imap_storage->imap_cached = imap_cached; if (imap_cached && (imap_cache_directory != NULL)) { imap_storage->imap_cache_directory = strdup(imap_cache_directory); if (imap_storage->imap_cache_directory == NULL) goto free_password; } else { imap_storage->imap_cached = FALSE; imap_storage->imap_cache_directory = NULL; } storage->sto_data = imap_storage; storage->sto_driver = &imap_mailstorage_driver; return MAIL_NO_ERROR; free_password: free(imap_storage->imap_password); free_login: free(imap_storage->imap_login); free_command: free(imap_storage->imap_command); free_servername: free(imap_storage->imap_servername); free: free(imap_storage); err: return MAIL_ERROR_MEMORY; } static void imap_mailstorage_uninitialize(struct mailstorage * storage) { struct imap_mailstorage * imap_storage; imap_storage = storage->sto_data; if (imap_storage->imap_cache_directory != NULL) free(imap_storage->imap_cache_directory); if (imap_storage->imap_password != NULL) free(imap_storage->imap_password); if (imap_storage->imap_login != NULL) free(imap_storage->imap_login); if (imap_storage->imap_command != NULL) free(imap_storage->imap_command); free(imap_storage->imap_servername); free(imap_storage); storage->sto_data = NULL; } static int imap_connect(struct mailstorage * storage, mailsession ** result) { struct imap_mailstorage * imap_storage; mailsession_driver * driver; int r; int res; mailsession * session; imap_storage = storage->sto_data; if (imap_storage->imap_cached) driver = imap_cached_session_driver; else driver = imap_session_driver; r = mailstorage_generic_connect(driver, imap_storage->imap_servername, imap_storage->imap_port, imap_storage->imap_command, imap_storage->imap_connection_type, IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY, diff --git a/kmicromail/libetpan/generic/maildirdriver.c b/kmicromail/libetpan/generic/maildirdriver.c index 7830ceb..5f21422 100644 --- a/kmicromail/libetpan/generic/maildirdriver.c +++ b/kmicromail/libetpan/generic/maildirdriver.c @@ -1,497 +1,548 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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$ */ /* flags directory MUST be kept so that we can have other flags than standards */ #include "maildirdriver.h" #include <stdio.h> #include <sys/types.h> #include <dirent.h> #include <unistd.h> #include <sys/stat.h> #include <ctype.h> #include <fcntl.h> #include <sys/mman.h> #include <stdlib.h> #include <string.h> #include "maildir.h" #include "maildriver_tools.h" #include "maildirdriver_message.h" #include "maildirdriver_tools.h" #include "mailmessage.h" #include "generic_cache.h" static int initialize(mailsession * session); static void uninitialize(mailsession * session); static int connect_path(mailsession * session, char * path); static int logout(mailsession * session); static int expunge_folder(mailsession * session); static int status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int recent_number(mailsession * session, char * mb, uint32_t * result); static int unseen_number(mailsession * session, char * mb, uint32_t * result); static int messages_number(mailsession * session, char * mb, uint32_t * result); static int append_message(mailsession * session, char * message, size_t size); +static int append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); + static int get_messages_list(mailsession * session, struct mailmessage_list ** result); static int get_envelopes_list(mailsession * session, struct mailmessage_list * env_list); static int check_folder(mailsession * session); static int get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result); static mailsession_driver local_maildir_session_driver = { .sess_name = "maildir", .sess_initialize = initialize, .sess_uninitialize = uninitialize, .sess_parameters = NULL, .sess_connect_stream = NULL, .sess_connect_path = connect_path, .sess_starttls = NULL, .sess_login = NULL, .sess_logout = logout, .sess_noop = NULL, .sess_build_folder_name = NULL, .sess_create_folder = NULL, .sess_delete_folder = NULL, .sess_rename_folder = NULL, .sess_check_folder = check_folder, .sess_examine_folder = NULL, .sess_select_folder = NULL, .sess_expunge_folder = expunge_folder, .sess_status_folder = status_folder, .sess_messages_number = messages_number, .sess_recent_number = recent_number, .sess_unseen_number = unseen_number, .sess_list_folders = NULL, .sess_lsub_folders = NULL, .sess_subscribe_folder = NULL, .sess_unsubscribe_folder = NULL, .sess_append_message = append_message, + .sess_append_message_flags = append_message_flags, .sess_copy_message = NULL, .sess_move_message = NULL, .sess_get_messages_list = get_messages_list, .sess_get_envelopes_list = get_envelopes_list, .sess_remove_message = NULL, #if 0 .sess_search_messages = maildriver_generic_search_messages, #endif .sess_get_message = NULL, .sess_get_message_by_uid = get_message_by_uid, }; mailsession_driver * maildir_session_driver = &local_maildir_session_driver; static int flags_store_process(struct maildir * md, struct mail_flags_store * flags_store); static inline struct maildir_session_state_data * get_data(mailsession * session) { return session->sess_data; } static struct maildir * get_maildir_session(mailsession * session) { return get_data(session)->md_session; } static int initialize(mailsession * session) { struct maildir_session_state_data * data; data = malloc(sizeof(* data)); if (data == NULL) goto err; data->md_session = NULL; data->md_flags_store = mail_flags_store_new(); if (data->md_flags_store == NULL) goto free; session->sess_data = data; return MAIL_NO_ERROR; free: free(data); err: return MAIL_ERROR_MEMORY; } static void uninitialize(mailsession * session) { struct maildir_session_state_data * data; data = get_data(session); if (data->md_session != NULL) flags_store_process(data->md_session, data->md_flags_store); mail_flags_store_free(data->md_flags_store); if (data->md_session != NULL) maildir_free(data->md_session); free(data); session->sess_data = NULL; } static int connect_path(mailsession * session, char * path) { struct maildir * md; int res; int r; if (get_maildir_session(session) != NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } md = maildir_new(path); if (md == NULL) { res = MAIL_ERROR_MEMORY; goto err; } r = maildir_update(md); if (r != MAILDIR_NO_ERROR) { res = maildirdriver_maildir_error_to_mail_error(r); goto free; } get_data(session)->md_session = md; return MAIL_NO_ERROR; free: maildir_free(md); err: return res; } static int logout(mailsession * session) { struct maildir * md; check_folder(session); md = get_maildir_session(session); if (md == NULL) return MAIL_ERROR_BAD_STATE; maildir_free(md); get_data(session)->md_session = NULL; return MAIL_NO_ERROR; } /* folders operations */ static int status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen) { int r; struct maildir * md; unsigned int i; uint32_t messages; uint32_t recent; uint32_t unseen; check_folder(session); md = get_maildir_session(session); if (md == NULL) return MAIL_ERROR_BAD_STATE; r = maildir_update(md); if (r != MAILDIR_NO_ERROR) return maildirdriver_maildir_error_to_mail_error(r); messages = 0; recent = 0; unseen = 0; for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i ++) { struct maildir_msg * msg; msg = carray_get(md->mdir_msg_list, i); if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) recent ++; if ((msg->msg_flags & MAILDIR_FLAG_SEEN) == 0) unseen ++; messages ++; } * result_messages = messages; * result_recent = recent; * result_unseen = unseen; return MAIL_NO_ERROR; } static int messages_number(mailsession * session, char * mb, uint32_t * result) { struct maildir * md; int r; md = get_maildir_session(session); if (md == NULL) return MAIL_ERROR_BAD_STATE; r = maildir_update(md); if (r != MAILDIR_NO_ERROR) return maildirdriver_maildir_error_to_mail_error(r); * result = carray_count(md->mdir_msg_list); return MAIL_NO_ERROR; } static int unseen_number(mailsession * session, char * mb, uint32_t * result) { uint32_t messages; uint32_t recent; uint32_t unseen; int r; r = status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = unseen; return MAIL_NO_ERROR; } static int recent_number(mailsession * session, char * mb, uint32_t * result) { uint32_t messages; uint32_t recent; uint32_t unseen; int r; r = status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = recent; return MAIL_NO_ERROR; } /* messages operations */ static int append_message(mailsession * session, char * message, size_t size) { +#if 0 struct maildir * md; int r; md = get_maildir_session(session); if (md == NULL) return MAIL_ERROR_BAD_STATE; r = maildir_message_add(md, message, size); if (r != MAILDIR_NO_ERROR) return maildirdriver_maildir_error_to_mail_error(r); return MAIL_NO_ERROR; +#endif + + return append_message_flags(session, message, size, NULL); +} + +static int append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + struct maildir * md; + int r; + char uid[PATH_MAX]; + struct maildir_msg * md_msg; + chashdatum key; + chashdatum value; + uint32_t md_flags; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_message_add_uid(md, message, size, + uid, sizeof(uid)); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + if (flags == NULL) + goto exit; + + key.data = uid; + key.len = strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + goto exit; + + md_msg = value.data; + + md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags); + + r = maildir_message_change_flags(md, uid, md_flags); + if (r != MAILDIR_NO_ERROR) + goto exit; + + return MAIL_NO_ERROR; + + exit: + return MAIL_NO_ERROR; } static int get_messages_list(mailsession * session, struct mailmessage_list ** result) { struct maildir * md; int r; struct mailmessage_list * env_list; int res; md = get_maildir_session(session); if (md == NULL) return MAIL_ERROR_BAD_STATE; r = maildir_update(md); if (r != MAILDIR_NO_ERROR) { res = maildirdriver_maildir_error_to_mail_error(r); goto err; } r = maildir_get_messages_list(session, md, maildir_message_driver, &env_list); if (r != MAILDIR_NO_ERROR) { res = r; goto free_list; } * result = env_list; return MAIL_NO_ERROR; free_list: mailmessage_list_free(env_list); err: return res; } static int get_envelopes_list(mailsession * session, struct mailmessage_list * env_list) { int r; struct maildir * md; unsigned int i; int res; check_folder(session); md = get_maildir_session(session); if (md == NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } r = maildir_update(md); if (r != MAILDIR_NO_ERROR) { res = maildirdriver_maildir_error_to_mail_error(r); goto err; } r = maildriver_generic_get_envelopes_list(session, env_list); if (r != MAIL_NO_ERROR) { res = r; goto err; } for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) { struct maildir_msg * md_msg; mailmessage * msg; uint32_t driver_flags; clist * ext; chashdatum key; chashdatum value; msg = carray_get(env_list->msg_tab, i); key.data = msg->msg_uid; key.len = strlen(msg->msg_uid); r = chash_get(md->mdir_msg_hash, &key, &value); if (r < 0) continue; md_msg = value.data; driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags); if (msg->msg_flags == NULL) { ext = clist_new(); if (ext == NULL) { res = MAIL_ERROR_MEMORY; continue; } msg->msg_flags = mail_flags_new(driver_flags, ext); if (msg->msg_flags == NULL) { clist_free(ext); res = MAIL_ERROR_MEMORY; continue; } if ((md_msg->msg_flags & MAILDIR_FLAG_NEW) != 0) { mail_flags_store_set(get_data(session)->md_flags_store, msg); } } else { msg->msg_flags->fl_flags &= MAIL_FLAG_FORWARDED; msg->msg_flags->fl_flags |= driver_flags; } } return MAIL_NO_ERROR; err: return res; } static int expunge_folder(mailsession * session) { unsigned int i; int r; int res; struct maildir * md; check_folder(session); md = get_maildir_session(session); if (md == NULL) return MAIL_ERROR_BAD_STATE; diff --git a/kmicromail/libetpan/generic/maildirdriver_cached.c b/kmicromail/libetpan/generic/maildirdriver_cached.c index 503d1c9..8a5e206 100644 --- a/kmicromail/libetpan/generic/maildirdriver_cached.c +++ b/kmicromail/libetpan/generic/maildirdriver_cached.c @@ -1,263 +1,267 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "maildirdriver.h" #include <stdio.h> #include <sys/types.h> #include <dirent.h> #include <unistd.h> #include <sys/stat.h> #include <ctype.h> #include <fcntl.h> #include <sys/mman.h> #include <stdlib.h> #include <string.h> #include "mail.h" #include "maildir.h" #include "maildriver_tools.h" #include "maildirdriver_tools.h" #include "maildirdriver_cached_message.h" #include "mailmessage.h" #include "generic_cache.h" #include "imfcache.h" #include "mail_cache_db.h" #include "libetpan-config.h" static int initialize(mailsession * session); static void uninitialize(mailsession * session); static int parameters(mailsession * session, int id, void * value); static int connect_path(mailsession * session, char * path); static int logout(mailsession * session); static int expunge_folder(mailsession * session); static int status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int recent_number(mailsession * session, char * mb, uint32_t * result); static int unseen_number(mailsession * session, char * mb, uint32_t * result); static int messages_number(mailsession * session, char * mb, uint32_t * result); static int append_message(mailsession * session, char * message, size_t size); +static int append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); + static int get_messages_list(mailsession * session, struct mailmessage_list ** result); static int get_envelopes_list(mailsession * session, struct mailmessage_list * env_list); static int check_folder(mailsession * session); static int get_message(mailsession * session, uint32_t num, mailmessage ** result); static int get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result); static mailsession_driver local_maildir_cached_session_driver = { .sess_name = "maildir-cached", .sess_initialize = initialize, .sess_uninitialize = uninitialize, .sess_parameters = parameters, .sess_connect_stream = NULL, .sess_connect_path = connect_path, .sess_starttls = NULL, .sess_login = NULL, .sess_logout = logout, .sess_noop = NULL, .sess_build_folder_name = NULL, .sess_create_folder = NULL, .sess_delete_folder = NULL, .sess_rename_folder = NULL, .sess_check_folder = check_folder, .sess_examine_folder = NULL, .sess_select_folder = NULL, .sess_expunge_folder = expunge_folder, .sess_status_folder = status_folder, .sess_messages_number = messages_number, .sess_recent_number = recent_number, .sess_unseen_number = unseen_number, .sess_list_folders = NULL, .sess_lsub_folders = NULL, .sess_subscribe_folder = NULL, .sess_unsubscribe_folder = NULL, .sess_append_message = append_message, + .sess_append_message_flags = append_message_flags, .sess_copy_message = NULL, .sess_move_message = NULL, .sess_get_messages_list = get_messages_list, .sess_get_envelopes_list = get_envelopes_list, .sess_remove_message = NULL, #if 0 .sess_search_messages = maildriver_generic_search_messages, #endif .sess_get_message = get_message, .sess_get_message_by_uid = get_message_by_uid, }; mailsession_driver * maildir_cached_session_driver = &local_maildir_cached_session_driver; static inline struct maildir_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)->md_ancestor; } static inline struct maildir_session_state_data * get_ancestor_data(mailsession * session) { return get_ancestor(session)->sess_data; } static struct maildir * get_maildir_session(mailsession * session) { return get_ancestor_data(session)->md_session; } static int initialize(mailsession * session) { struct maildir_cached_session_state_data * data; data = malloc(sizeof(* data)); if (data == NULL) goto err; data->md_ancestor = mailsession_new(maildir_session_driver); if (data->md_ancestor == NULL) goto free; data->md_flags_store = mail_flags_store_new(); if (data->md_flags_store == NULL) goto free_session; data->md_quoted_mb = NULL; data->md_cache_directory[0] = '\0'; data->md_flags_directory[0] = '\0'; session->sess_data = data; return MAIL_NO_ERROR; free_session: mailsession_free(data->md_ancestor); free: free(data); err: return MAIL_ERROR_MEMORY; } static void free_quoted_mb(struct maildir_cached_session_state_data * maildir_cached_data) { if (maildir_cached_data->md_quoted_mb != NULL) { free(maildir_cached_data->md_quoted_mb); maildir_cached_data->md_quoted_mb = NULL; } } static int write_cached_flags(struct mail_cache_db * cache_db, MMAPString * mmapstr, char * uid, struct mail_flags * flags); #define ENV_NAME "env.db" #define FLAGS_NAME "flags.db" static int 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 = write_cached_flags(cache_db_flags, mmapstr, @@ -329,259 +333,333 @@ static int parameters(mailsession * session, return MAIL_NO_ERROR; default: return mailsession_parameters(data->md_ancestor, id, value); } } static int get_cache_folder(mailsession * session, char ** result) { struct maildir * md; char * quoted_mb; int res; int r; char key[PATH_MAX]; struct maildir_cached_session_state_data * data; md = get_maildir_session(session); data = get_cached_data(session); quoted_mb = maildriver_quote_mailbox(md->mdir_path); if (quoted_mb == NULL) { res = MAIL_ERROR_MEMORY; goto err; } snprintf(key, PATH_MAX, "%s/%s", data->md_cache_directory, quoted_mb); r = generic_cache_create_dir(key); if (r != MAIL_NO_ERROR) { res = r; goto free_quoted_mb; } snprintf(key, PATH_MAX, "%s/%s", data->md_flags_directory, quoted_mb); r = generic_cache_create_dir(key); if (r != MAIL_NO_ERROR) { res = r; goto free_quoted_mb; } * result = quoted_mb; return MAIL_NO_ERROR; free_quoted_mb: free(quoted_mb); err: return res; } static int connect_path(mailsession * session, char * path) { int r; int res; char * quoted_mb; r = mailsession_connect_path(get_ancestor(session), path); if (r != MAIL_NO_ERROR) { res = r; goto err; } r = get_cache_folder(session, "ed_mb); if (r != MAIL_NO_ERROR) { res = r; goto logout; } get_cached_data(session)->md_quoted_mb = quoted_mb; return MAILDIR_NO_ERROR; logout: mailsession_logout(get_ancestor(session)); err: return res; } static int logout(mailsession * session) { struct maildir_cached_session_state_data * data; int r; data = get_cached_data(session); flags_store_process(data->md_flags_directory, data->md_quoted_mb, data->md_flags_store); r = mailsession_logout(get_ancestor(session)); if (r != MAIL_NO_ERROR) return r; free_quoted_mb(get_cached_data(session)); return MAIL_NO_ERROR; } static int status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen) { return mailsession_status_folder(get_ancestor(session), mb, result_messages, result_recent, result_unseen); } static int messages_number(mailsession * session, char * mb, uint32_t * result) { return mailsession_messages_number(get_ancestor(session), mb, result); } static int unseen_number(mailsession * session, char * mb, uint32_t * result) { return mailsession_unseen_number(get_ancestor(session), mb, result); } static int recent_number(mailsession * session, char * mb, uint32_t * result) { return mailsession_recent_number(get_ancestor(session), mb, result); } static int append_message(mailsession * session, char * message, size_t size) { +#if 0 return mailsession_append_message(get_ancestor(session), message, size); +#endif + return append_message_flags(session, message, size, NULL); } +static int append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + struct maildir * md; + int r; + char uid[PATH_MAX]; + struct maildir_msg * md_msg; + chashdatum key; + chashdatum value; + uint32_t md_flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + MMAPString * mmapstr; + struct maildir_cached_session_state_data * data; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_message_add_uid(md, message, size, + uid, sizeof(uid)); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + if (flags == NULL) + goto exit; + + data = get_cached_data(session); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_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; + + r = write_cached_flags(cache_db_flags, mmapstr, + uid, flags); + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + if (r != MAIL_NO_ERROR) + goto exit; + + key.data = uid; + key.len = strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + goto exit; + + md_msg = value.data; + + md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags); + + r = maildir_message_change_flags(md, uid, md_flags); + if (r != MAILDIR_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; +} #define UID_NAME "uid.db" static int uid_clean_up(struct mail_cache_db * uid_db, struct mailmessage_list * env_list) { chash * hash_exist; int res; int r; unsigned int i; chashdatum key; chashdatum value; char key_str[PATH_MAX]; /* flush cache */ hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); if (hash_exist == NULL) { res = MAIL_ERROR_MEMORY; goto err; } value.data = NULL; value.len = 0; key.data = "max-uid"; key.len = strlen("max-uid"); r = chash_set(hash_exist, &key, &value, NULL); for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { mailmessage * msg; msg = carray_get(env_list->msg_tab, i); value.data = NULL; value.len = 0; key.data = msg->msg_uid; key.len = strlen(msg->msg_uid); r = chash_set(hash_exist, &key, &value, NULL); if (r < 0) { res = MAIL_ERROR_MEMORY; goto free; } snprintf(key_str, sizeof(key_str), "uid-%lu", (unsigned long) msg->msg_index); key.data = key_str; key.len = strlen(key_str); r = chash_set(hash_exist, &key, &value, NULL); if (r < 0) { res = MAIL_ERROR_MEMORY; goto free; } } mail_cache_db_clean_up(uid_db, hash_exist); chash_free(hash_exist); return MAIL_NO_ERROR; free: chash_free(hash_exist); err: return res; } static int get_messages_list(mailsession * session, struct mailmessage_list ** result) { struct maildir * md; int r; struct mailmessage_list * env_list; int res; uint32_t max_uid; char filename[PATH_MAX]; struct mail_cache_db * uid_db; void * value; size_t value_len; unsigned long i; struct maildir_cached_session_state_data * data; char key[PATH_MAX]; data = get_cached_data(session); md = get_maildir_session(session); if (md == NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } check_folder(session); r = maildir_update(md); if (r != MAILDIR_NO_ERROR) { res = maildirdriver_maildir_error_to_mail_error(r); goto err; } r = maildir_get_messages_list(session, md, maildir_cached_message_driver, &env_list); if (r != MAILDIR_NO_ERROR) { res = r; goto err; } /* read/write DB */ snprintf(filename, sizeof(filename), "%s%c%s%c%s", data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, MAIL_DIR_SEPARATOR, UID_NAME); r = mail_cache_db_open_lock(filename, &uid_db); if (r < 0) { res = MAIL_ERROR_MEMORY; goto free_list; } max_uid = 0; r = mail_cache_db_get(uid_db, "max-uid", sizeof("max-uid") - 1, &value, &value_len); if (r == 0) { memcpy(&max_uid, value, sizeof(max_uid)); } for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { mailmessage * msg; diff --git a/kmicromail/libetpan/generic/maildirdriver_cached_message.c b/kmicromail/libetpan/generic/maildirdriver_cached_message.c index 51866aa..34de351 100644 --- a/kmicromail/libetpan/generic/maildirdriver_cached_message.c +++ b/kmicromail/libetpan/generic/maildirdriver_cached_message.c @@ -1,248 +1,334 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "maildirdriver_message.h" #include "mailmessage_tools.h" #include "maildirdriver.h" #include "maildir.h" #include "generic_cache.h" +#include "mail_cache_db.h" +#include "maildirdriver_tools.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 get_flags(mailmessage * msg_info, + struct mail_flags ** result); + static int prefetch(mailmessage * msg_info); static void prefetch_free(struct generic_message_t * msg); static int initialize(mailmessage * msg_info); static void check(mailmessage * msg_info); static mailmessage_driver local_maildir_cached_message_driver = { .msg_name = "maildir-cached", .msg_initialize = initialize, .msg_uninitialize = mailmessage_generic_uninitialize, .msg_flush = mailmessage_generic_flush, .msg_check = check, .msg_fetch_result_free = mailmessage_generic_fetch_result_free, .msg_fetch = mailmessage_generic_fetch, .msg_fetch_header = mailmessage_generic_fetch_header, .msg_fetch_body = mailmessage_generic_fetch_header, .msg_fetch_size = NULL, .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, + .msg_get_flags = get_flags, }; mailmessage_driver * maildir_cached_message_driver = &local_maildir_cached_message_driver; struct maildir_msg_data { int fd; }; #if 0 static inline struct maildir_cached_session_state_data * get_cached_session_data(mailmessage * msg) { return msg->session->data; } static inline mailsession * cached_session_get_ancestor(mailsession * session) { return get_data(session)->session; } static inline struct maildir_session_state_data * cached_session_get_ancestor_data(mailsession * session) { return get_ancestor(session)->data; } static struct maildir * get_maildir_session(mailmessage * msg) { return cached_session_get_ancestor_data(msg->session)->session; } #endif static inline struct maildir_cached_session_state_data * get_cached_session_data(mailmessage * msg) { return msg->msg_session->sess_data; } static inline struct maildir_cached_session_state_data * cached_session_get_data(mailsession * s) { return s->sess_data; } static inline mailsession * cached_session_get_ancestor(mailsession * s) { return cached_session_get_data(s)->md_ancestor; } static inline struct maildir_session_state_data * cached_session_get_ancestor_data(mailsession * s) { return cached_session_get_ancestor(s)->sess_data; } static inline struct maildir_session_state_data * get_session_ancestor_data(mailmessage * msg) { return cached_session_get_ancestor_data(msg->msg_session); } static inline struct maildir * cached_session_get_maildir_session(mailsession * session) { return cached_session_get_ancestor_data(session)->md_session; } static inline struct maildir * get_maildir_session(mailmessage * msg) { return cached_session_get_maildir_session(msg->msg_session); } static int prefetch(mailmessage * msg_info) { struct generic_message_t * msg; int res; struct maildir_msg_data * data; char * filename; int fd; char * mapping; struct maildir * md; md = get_maildir_session(msg_info); filename = maildir_message_get(md, msg_info->msg_uid); if (filename == NULL) { res = MAIL_ERROR_MEMORY; goto err; } fd = open(filename, O_RDONLY); free(filename); if (fd == -1) { res = MAIL_ERROR_FILE; goto err; } mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0); if (mapping == MAP_FAILED) { res = MAIL_ERROR_FILE; goto close; } data = malloc(sizeof(* data)); if (data == NULL) { res = MAIL_ERROR_MEMORY; goto unmap; } data->fd = fd; msg = msg_info->msg_data; msg->msg_data = data; msg->msg_message = mapping; msg->msg_length = msg_info->msg_size; return MAIL_NO_ERROR; unmap: munmap(mapping, msg_info->msg_size); close: close(fd); err: return res; } static void prefetch_free(struct generic_message_t * msg) { if (msg->msg_message != NULL) { struct maildir_msg_data * data; munmap(msg->msg_message, msg->msg_length); msg->msg_message = NULL; data = msg->msg_data; close(data->fd); free(data); } } static int initialize(mailmessage * msg_info) { struct generic_message_t * msg; int r; r = mailmessage_generic_initialize(msg_info); if (r != MAIL_NO_ERROR) return r; msg = msg_info->msg_data; msg->msg_prefetch = prefetch; msg->msg_prefetch_free = prefetch_free; return MAIL_NO_ERROR; } static void check(mailmessage * msg_info) { int r; if (msg_info->msg_flags != NULL) { r = mail_flags_store_set(get_session_ancestor_data(msg_info)->md_flags_store, msg_info); r = mail_flags_store_set(get_cached_session_data(msg_info)->md_flags_store, msg_info); /* ignore errors */ } } + +#define FLAGS_NAME "flags.db" + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + struct mail_cache_db * cache_db_flags; + chashdatum key; + chashdatum value; + struct maildir * md; + struct mail_flags * flags; + struct maildir_cached_session_state_data * data; + struct maildir_msg * md_msg; + int r; + uint32_t driver_flags; + char filename_flags[PATH_MAX]; + char keyname[PATH_MAX]; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + data = get_cached_session_data(msg_info); + flags = mail_flags_store_get(data->md_flags_store, + msg_info->msg_index); + if (flags != NULL) { + msg_info->msg_flags = flags; + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) + return MAIL_ERROR_FILE; + + snprintf(keyname, PATH_MAX, "%s-flags", msg_info->msg_uid); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + return MAIL_ERROR_MEMORY; + } + + r = generic_cache_flags_read(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) { + flags = mail_flags_new_empty(); + if (flags == NULL) + return MAIL_ERROR_MEMORY; + } + + md = get_maildir_session(msg_info); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = msg_info->msg_uid; + key.len = strlen(msg_info->msg_uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + md_msg = value.data; + + driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags); + + flags->fl_flags = driver_flags; + msg_info->msg_flags = flags; + + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; +} diff --git a/kmicromail/libetpan/generic/maildirdriver_message.c b/kmicromail/libetpan/generic/maildirdriver_message.c index 7cf9dd1..613fc39 100644 --- a/kmicromail/libetpan/generic/maildirdriver_message.c +++ b/kmicromail/libetpan/generic/maildirdriver_message.c @@ -1,199 +1,255 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "maildirdriver_message.h" +#include "maildirdriver_tools.h" #include "mailmessage_tools.h" #include "maildirdriver.h" #include "maildir.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 get_flags(mailmessage * msg_info, + struct mail_flags ** result); + static int prefetch(mailmessage * msg_info); static void prefetch_free(struct generic_message_t * msg); static int initialize(mailmessage * msg_info); static void check(mailmessage * msg_info); static mailmessage_driver local_maildir_message_driver = { .msg_name = "maildir", .msg_initialize = initialize, .msg_uninitialize = mailmessage_generic_uninitialize, .msg_flush = mailmessage_generic_flush, .msg_check = check, .msg_fetch_result_free = mailmessage_generic_fetch_result_free, .msg_fetch = mailmessage_generic_fetch, .msg_fetch_header = mailmessage_generic_fetch_header, .msg_fetch_body = mailmessage_generic_fetch_header, .msg_fetch_size = NULL, .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, + .msg_get_flags = get_flags, }; mailmessage_driver * maildir_message_driver = &local_maildir_message_driver; struct maildir_msg_data { int fd; }; static inline struct maildir_session_state_data * get_session_data(mailmessage * msg) { return msg->msg_session->sess_data; } static struct maildir * get_maildir_session(mailmessage * msg) { return get_session_data(msg)->md_session; } static int prefetch(mailmessage * msg_info) { struct generic_message_t * msg; int res; struct maildir_msg_data * data; char * filename; int fd; char * mapping; struct maildir * md; md = get_maildir_session(msg_info); if (msg_info->msg_uid == NULL) { res = MAIL_ERROR_INVAL; goto err; } filename = maildir_message_get(md, msg_info->msg_uid); if (filename == NULL) { res = MAIL_ERROR_MEMORY; goto err; } fd = open(filename, O_RDONLY); free(filename); if (fd == -1) { res = MAIL_ERROR_FILE; goto err; } mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0); if (mapping == MAP_FAILED) { res = MAIL_ERROR_FILE; goto close; } data = malloc(sizeof(* data)); if (data == NULL) { res = MAIL_ERROR_MEMORY; goto unmap; } data->fd = fd; msg = msg_info->msg_data; msg->msg_data = data; msg->msg_message = mapping; msg->msg_length = msg_info->msg_size; return MAIL_NO_ERROR; unmap: munmap(mapping, msg_info->msg_size); close: close(fd); err: return res; } static void prefetch_free(struct generic_message_t * msg) { if (msg->msg_message != NULL) { struct maildir_msg_data * data; munmap(msg->msg_message, msg->msg_length); msg->msg_message = NULL; data = msg->msg_data; close(data->fd); free(data); } } static int initialize(mailmessage * msg_info) { struct generic_message_t * msg; int r; r = mailmessage_generic_initialize(msg_info); if (r != MAIL_NO_ERROR) return r; msg = msg_info->msg_data; msg->msg_prefetch = prefetch; msg->msg_prefetch_free = prefetch_free; return MAIL_NO_ERROR; } static void check(mailmessage * msg_info) { int r; if (msg_info->msg_flags != NULL) { r = mail_flags_store_set(get_session_data(msg_info)->md_flags_store, msg_info); /* ignore errors */ } } + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + chashdatum key; + chashdatum value; + struct maildir * md; + struct mail_flags * flags; + struct maildir_session_state_data * data; + struct maildir_msg * md_msg; + int r; + uint32_t driver_flags; + clist * ext; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + data = get_session_data(msg_info); + flags = mail_flags_store_get(data->md_flags_store, + msg_info->msg_index); + if (flags != NULL) { + msg_info->msg_flags = flags; + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + md = get_maildir_session(msg_info); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = msg_info->msg_uid; + key.len = strlen(msg_info->msg_uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + md_msg = value.data; + + driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags); + + ext = clist_new(); + if (ext == NULL) + return MAIL_ERROR_MEMORY; + + msg_info->msg_flags = mail_flags_new(driver_flags, ext); + + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; +} diff --git a/kmicromail/libetpan/generic/maildirstorage.c b/kmicromail/libetpan/generic/maildirstorage.c index 7e6b461..e37f591 100644 --- a/kmicromail/libetpan/generic/maildirstorage.c +++ b/kmicromail/libetpan/generic/maildirstorage.c @@ -1,192 +1,193 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "maildirstorage.h" #include "mailstorage.h" #include "mail.h" #include "mailmessage.h" #include "maildirdriver.h" #include "maildirdriver_cached.h" #include "maildriver.h" #include <stdlib.h> #include <string.h> /* maildir storage */ static int maildir_mailstorage_connect(struct mailstorage * storage); static int maildir_mailstorage_get_folder_session(struct mailstorage * storage, char * pathname, mailsession ** result); static void maildir_mailstorage_uninitialize(struct mailstorage * storage); static mailstorage_driver maildir_mailstorage_driver = { .sto_name = "maildir", .sto_connect = maildir_mailstorage_connect, .sto_get_folder_session = maildir_mailstorage_get_folder_session, .sto_uninitialize = maildir_mailstorage_uninitialize, }; int maildir_mailstorage_init(struct mailstorage * storage, char * md_pathname, int md_cached, char * md_cache_directory, char * md_flags_directory) { struct maildir_mailstorage * maildir_storage; - maildir_storage = malloc(sizeof(struct maildir_mailstorage)); + maildir_storage = malloc(sizeof(* maildir_storage)); if (maildir_storage == NULL) goto err; maildir_storage->md_pathname = strdup(md_pathname); if (maildir_storage->md_pathname == NULL) goto free; maildir_storage->md_cached = md_cached; if (md_cached && (md_cache_directory != NULL) && (md_flags_directory != NULL)) { maildir_storage->md_cache_directory = strdup(md_cache_directory); if (maildir_storage->md_cache_directory == NULL) goto free_pathname; maildir_storage->md_flags_directory = strdup(md_flags_directory); if (maildir_storage->md_flags_directory == NULL) goto free_cache_directory; } else { maildir_storage->md_cached = FALSE; maildir_storage->md_cache_directory = NULL; maildir_storage->md_flags_directory = NULL; } storage->sto_data = maildir_storage; storage->sto_driver = &maildir_mailstorage_driver; return MAIL_NO_ERROR; free_cache_directory: free(maildir_storage->md_cache_directory); free_pathname: free(maildir_storage->md_pathname); free: free(maildir_storage); err: return MAIL_ERROR_MEMORY; } static void maildir_mailstorage_uninitialize(struct mailstorage * storage) { struct maildir_mailstorage * maildir_storage; maildir_storage = storage->sto_data; if (maildir_storage->md_flags_directory != NULL) free(maildir_storage->md_flags_directory); if (maildir_storage->md_cache_directory != NULL) free(maildir_storage->md_cache_directory); free(maildir_storage->md_pathname); free(maildir_storage); storage->sto_data = NULL; } static int maildir_mailstorage_connect(struct mailstorage * storage) { struct maildir_mailstorage * maildir_storage; mailsession_driver * driver; int r; int res; mailsession * session; maildir_storage = storage->sto_data; if (maildir_storage->md_cached) driver = maildir_cached_session_driver; else driver = maildir_session_driver; session = mailsession_new(driver); if (session == NULL) { res = MAIL_ERROR_MEMORY; goto err; } if (maildir_storage->md_cached) { r = mailsession_parameters(session, MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY, maildir_storage->md_cache_directory); if (r != MAIL_NO_ERROR) { res = r; goto free; } r = mailsession_parameters(session, MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY, maildir_storage->md_flags_directory); if (r != MAIL_NO_ERROR) { res = r; goto free; } } r = mailsession_connect_path(session, maildir_storage->md_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 maildir_mailstorage_get_folder_session(struct mailstorage * storage, char * pathname, mailsession ** result) { * result = storage->sto_session; return MAIL_NO_ERROR; } diff --git a/kmicromail/libetpan/generic/maildirstorage.h b/kmicromail/libetpan/generic/maildirstorage.h index d17ea2c..73d7b20 100644 --- a/kmicromail/libetpan/generic/maildirstorage.h +++ b/kmicromail/libetpan/generic/maildirstorage.h @@ -1,69 +1,69 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 MAILDIRSTORAGE_H #define MAILDIRSTORAGE_H #include <libetpan/maildirdriver_types.h> #ifdef __cplusplus extern "C" { #endif /* - maildir_mailstorage_init is the constructor for a mbox storage. + maildir_mailstorage_init is the constructor for a maildir storage. @param storage this is the storage to initialize. @param pathname is the directory 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 maildir_mailstorage_init(struct mailstorage * storage, char * md_pathname, int md_cached, char * md_cache_directory, char * md_flags_directory); #ifdef __cplusplus } #endif #endif diff --git a/kmicromail/libetpan/generic/maildriver.c b/kmicromail/libetpan/generic/maildriver.c index 01e3e34..1fc478a 100644 --- a/kmicromail/libetpan/generic/maildriver.c +++ b/kmicromail/libetpan/generic/maildriver.c @@ -157,217 +157,227 @@ int mailsession_delete_folder(mailsession * session, char * mb) return session->sess_driver->sess_delete_folder(session, mb); } int mailsession_rename_folder(mailsession * session, char * mb, char * new_name) { if (session->sess_driver->sess_rename_folder == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_rename_folder(session, mb, new_name); } int mailsession_check_folder(mailsession * session) { if (session->sess_driver->sess_check_folder == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_check_folder(session); } int mailsession_examine_folder(mailsession * session, char * mb) { if (session->sess_driver->sess_examine_folder == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_examine_folder(session, mb); } int mailsession_select_folder(mailsession * session, char * mb) { if (session->sess_driver->sess_select_folder == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_select_folder(session, mb); } int mailsession_expunge_folder(mailsession * session) { if (session->sess_driver->sess_expunge_folder == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_expunge_folder(session); } int mailsession_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen) { if (session->sess_driver->sess_status_folder == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_status_folder(session, mb, result_messages, result_recent, result_unseen); } int mailsession_messages_number(mailsession * session, char * mb, uint32_t * result) { if (session->sess_driver->sess_messages_number == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_messages_number(session, mb, result); } int mailsession_recent_number(mailsession * session, char * mb, uint32_t * result) { if (session->sess_driver->sess_recent_number == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_recent_number(session, mb, result); } int mailsession_unseen_number(mailsession * session, char * mb, uint32_t * result) { if (session->sess_driver->sess_unseen_number == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_recent_number(session, mb, result); } int mailsession_list_folders(mailsession * session, char * mb, struct mail_list ** result) { if (session->sess_driver->sess_list_folders == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_list_folders(session, mb, result); } int mailsession_lsub_folders(mailsession * session, char * mb, struct mail_list ** result) { if (session->sess_driver->sess_lsub_folders == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_lsub_folders(session, mb, result); } int mailsession_subscribe_folder(mailsession * session, char * mb) { if (session->sess_driver->sess_subscribe_folder == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_subscribe_folder(session, mb); } int mailsession_unsubscribe_folder(mailsession * session, char * mb) { if (session->sess_driver->sess_unsubscribe_folder == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_unsubscribe_folder(session, mb); } /* message */ int mailsession_append_message(mailsession * session, char * message, size_t size) { if (session->sess_driver->sess_append_message == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_append_message(session, message, size); } +int mailsession_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + if (session->sess_driver->sess_append_message_flags == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_append_message_flags(session, + message, size, flags); +} + int mailsession_copy_message(mailsession * session, uint32_t num, char * mb) { if (session->sess_driver->sess_copy_message == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_copy_message(session, num, mb); } int mailsession_move_message(mailsession * session, uint32_t num, char * mb) { if (session->sess_driver->sess_move_message == NULL) { int r; if ((session->sess_driver->sess_copy_message == NULL) && (session->sess_driver->sess_remove_message == NULL)) return MAIL_ERROR_NOT_IMPLEMENTED; r = mailsession_copy_message(session, num, mb); if (r != MAIL_NO_ERROR) return r; r = mailsession_remove_message(session, num); if (r != MAIL_NO_ERROR) return r; return MAIL_NO_ERROR; } return session->sess_driver->sess_move_message(session, num, mb); } int mailsession_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list) { if (session->sess_driver->sess_get_envelopes_list == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_get_envelopes_list(session, env_list); } int mailsession_get_messages_list(mailsession * session, struct mailmessage_list ** result) { if (session->sess_driver->sess_get_messages_list == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_get_messages_list(session, result); } int mailsession_remove_message(mailsession * session, uint32_t num) { if (session->sess_driver->sess_remove_message == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_remove_message(session, num); } #if 0 int mailsession_search_messages(mailsession * session, char * charset, struct mail_search_key * key, struct mail_search_result ** result) { if (session->sess_driver->sess_search_messages == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_search_messages(session, charset, key, result); } #endif int mailsession_get_message(mailsession * session, uint32_t num, mailmessage ** result) { if (session->sess_driver->sess_get_message == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_get_message(session, num, result); } int mailsession_get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result) { if (session->sess_driver->sess_get_message_by_uid == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return session->sess_driver->sess_get_message_by_uid(session, uid, result); } diff --git a/kmicromail/libetpan/generic/maildriver.h b/kmicromail/libetpan/generic/maildriver.h index 7da9aea..c773190 100644 --- a/kmicromail/libetpan/generic/maildriver.h +++ b/kmicromail/libetpan/generic/maildriver.h @@ -275,256 +275,259 @@ int mailsession_expunge_folder(mailsession * session); */ int mailsession_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); /* mailsession_messages_number queries the number of messages in the folder @param session the session @param mb mailbox to query @param result the number of messages is stored in (* result) @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_messages_number(mailsession * session, char * mb, uint32_t * result); /* mailsession_recent_number queries the number of recent messages in the folder @param session the session @param mb mailbox to query @param result the number of recent messages is stored in (* result) @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_recent_number(mailsession * session, char * mb, uint32_t * result); /* mailsession_unseen_number queries the number of unseen messages in the folder @param session the session @param mb mailbox to query @param result the number of unseen messages is stored in (* result) @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_unseen_number(mailsession * session, char * mb, uint32_t * result); /* NOTE: driver's specific should be used mailsession_list_folders returns the list of all sub-mailboxes of the given mailbox @param session the session @param mb the mailbox @param result list of mailboxes if stored in (* result), this structure have to be freed with mail_list_free() @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_list_folders(mailsession * session, char * mb, struct mail_list ** result); /* NOTE: driver's specific should be used mailsession_lsub_folders returns the list of subscribed sub-mailboxes of the given mailbox @param session the session @param mb the mailbox @param result list of mailboxes if stored in (* result), this structure have to be freed with mail_list_free() @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_lsub_folders(mailsession * session, char * mb, struct mail_list ** result); /* NOTE: driver's specific should be used mailsession_subscribe_folder subscribes to the given mailbox @param session the session @param mb the mailbox @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_subscribe_folder(mailsession * session, char * mb); /* NOTE: driver's specific should be used mailsession_unsubscribe_folder unsubscribes to the given mailbox @param session the session @param mb the mailbox @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_unsubscribe_folder(mailsession * session, char * mb); /* mailsession_append_message adds a RFC 2822 message to the current given mailbox @param session the session @param message is a string that contains the RFC 2822 message @param size this is the size of the message @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_append_message(mailsession * session, char * message, size_t size); +int mailsession_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); + /* NOTE: some drivers does not implement this mailsession_copy_message copies a message whose number is given to a given mailbox. The mailbox must be accessible from the same session. @param session the session @param num the message number @param mb the destination mailbox @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_copy_message(mailsession * session, uint32_t num, char * mb); /* NOTE: some drivers does not implement this mailsession_move_message copies a message whose number is given to a given mailbox. The mailbox must be accessible from the same session. @param session the session @param num the message number @param mb the destination mailbox @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_move_message(mailsession * session, uint32_t num, char * mb); /* mailsession_get_messages_list returns the list of message numbers of the current mailbox. @param session the session @param result the list of message numbers will be stored in (* result), this structure have to be freed with mailmessage_list_free() @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_get_messages_list(mailsession * session, struct mailmessage_list ** result); /* mailsession_get_envelopes_list fills the parsed fields in the mailmessage structures of the mailmessage_list. @param session the session @param result this is the list of mailmessage structures @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_get_envelopes_list(mailsession * session, struct mailmessage_list * result); /* NOTE: some drivers does not implement this mailsession_remove_message removes the given message from the mailbox. The message is permanently deleted. @param session the session @param num is the message number @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_remove_message(mailsession * session, uint32_t num); /* NOTE: this function is not implemented in most drivers mailsession_search_message returns a list of message numbers that corresponds to the given criteria. @param session the session @param charset is the charset to use (it can be NULL) @param key is the list of criteria @param result the search result is stored in (* result), this structure have to be freed with mail_search_result_free() @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ #if 0 int mailsession_search_messages(mailsession * session, char * charset, struct mail_search_key * key, struct mail_search_result ** result); #endif /* mailsession_get_message returns a mailmessage structure that corresponds to the given message number. * WARNING * mailsession_get_message_by_uid() should be used instead. @param session the session @param num the message number @param result the allocated mailmessage structure will be stored in (* result), this structure have to be freed with mailmessage_free() @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned on error */ int mailsession_get_message(mailsession * session, uint32_t num, mailmessage ** result); /* mailsession_get_message_by_uid returns a mailmessage structure that corresponds to the given message unique identifier. This is currently implemented only for cached drivers. * WARNING * That will deprecates the use of mailsession_get_message() @param session the session @param uid the message unique identifier @param result the allocated mailmessage structure will be stored in (* result), this structure have to be freed with mailmessage_free() diff --git a/kmicromail/libetpan/generic/maildriver_types.h b/kmicromail/libetpan/generic/maildriver_types.h index 3ff9440..9eab4d6 100644 --- a/kmicromail/libetpan/generic/maildriver_types.h +++ b/kmicromail/libetpan/generic/maildriver_types.h @@ -382,256 +382,258 @@ void mail_search_result_free(struct mail_search_result * search_result); - messages_number() queries the number of messages in the folder - recent_number() queries the number of recent messages in the folder - unseen_number() queries the number of unseen messages in the folder - list_folders() returns the list of all sub-mailboxes of the given mailbox - lsub_folders() returns the list of subscribed sub-mailboxes of the given mailbox - subscribe_folder() subscribes to the given mailbox - unsubscribe_folder() unsubscribes to the given mailbox - append_message() adds a RFC 2822 message to the current given mailbox - copy_message() copies a message whose number is given to a given mailbox. The mailbox must be accessible from the same session. - move_message() copies a message whose number is given to a given mailbox. The mailbox must be accessible from the same session. - get_messages_list() returns the list of message numbers of the current mailbox. - get_envelopes_list() fills the parsed fields in the mailmessage structures of the mailmessage_list. - remove_message() removes the given message from the mailbox. The message is permanently deleted. - search_message() returns a list of message numbers that corresponds to the given criteria. - get_message returns a mailmessage structure that corresponds to the given message number. - get_message_by_uid returns a mailmessage structure that corresponds to the given message unique identifier. * mandatory functions are the following : - connect_stream() of connect_path() - logout() - get_messages_list() - get_envelopes_list() * we advise you to implement these functions : - select_folder() (in case a session can access several folders) - noop() (to check if the server is responding) - check_folder() (to make a checkpoint of the session) - status_folder(), messages_number(), recent_number(), unseen_number() (to get stat of the folder) - append_message() (but can't be done in the case of POP3 at least) - login() in a case of an authenticated driver. - starttls() in a case of a stream driver, if the procotol supports STARTTLS. - get_message_by_uid() so that the application can remember the message by UID and build its own list of messages. * drivers' specific : Everything that is specific to the driver will be implemented in this function : - parameters() */ struct mailsession_driver { char * sess_name; int (* sess_initialize)(mailsession * session); void (* sess_uninitialize)(mailsession * session); int (* sess_parameters)(mailsession * session, int id, void * value); int (* sess_connect_stream)(mailsession * session, mailstream * s); int (* sess_connect_path)(mailsession * session, char * path); int (* sess_starttls)(mailsession * session); int (* sess_login)(mailsession * session, char * userid, char * password); int (* sess_logout)(mailsession * session); int (* sess_noop)(mailsession * session); /* folders operations */ int (* sess_build_folder_name)(mailsession * session, char * mb, char * name, char ** result); int (* sess_create_folder)(mailsession * session, char * mb); int (* sess_delete_folder)(mailsession * session, char * mb); int (* sess_rename_folder)(mailsession * session, char * mb, char * new_name); int (* sess_check_folder)(mailsession * session); int (* sess_examine_folder)(mailsession * session, char * mb); int (* sess_select_folder)(mailsession * session, char * mb); int (* sess_expunge_folder)(mailsession * session); int (* sess_status_folder)(mailsession * session, char * mb, uint32_t * result_num, uint32_t * result_recent, uint32_t * result_unseen); int (* sess_messages_number)(mailsession * session, char * mb, uint32_t * result); int (* sess_recent_number)(mailsession * session, char * mb, uint32_t * result); int (* sess_unseen_number)(mailsession * session, char * mb, uint32_t * result); int (* sess_list_folders)(mailsession * session, char * mb, struct mail_list ** result); int (* sess_lsub_folders)(mailsession * session, char * mb, struct mail_list ** result); int (* sess_subscribe_folder)(mailsession * session, char * mb); int (* sess_unsubscribe_folder)(mailsession * session, char * mb); /* messages operations */ int (* sess_append_message)(mailsession * session, char * message, size_t size); + int (* sess_append_message_flags)(mailsession * session, + char * message, size_t size, struct mail_flags * flags); int (* sess_copy_message)(mailsession * session, uint32_t num, char * mb); int (* sess_move_message)(mailsession * session, uint32_t num, char * mb); int (* sess_get_message)(mailsession * session, uint32_t num, mailmessage ** result); int (* sess_get_message_by_uid)(mailsession * session, const char * uid, mailmessage ** result); int (* sess_get_messages_list)(mailsession * session, struct mailmessage_list ** result); int (* sess_get_envelopes_list)(mailsession * session, struct mailmessage_list * env_list); int (* sess_remove_message)(mailsession * session, uint32_t num); #if 0 int (* sess_search_messages)(mailsession * session, char * charset, struct mail_search_key * key, struct mail_search_result ** result); #endif }; /* session is the data structure for a mail session. - data is the internal data structure used by the driver It is called when initializing the mailsession structure. - driver is the driver used for the session */ struct mailsession { void * sess_data; mailsession_driver * sess_driver; }; /* mailmessage_driver is the driver structure to get information from messages. - name is the name of the driver - initialize() is the function that will initializes a data structure specific to the driver, it returns a value that will be stored in the field data of the mailsession. The field data of the session is the state of the session, the internal data structure used by the driver. It is called when initializing the mailmessage structure with mailmessage_init(). - uninitialize() frees the structure created with initialize(). It will be called by mailmessage_free(). - flush() will free from memory all temporary structures of the message (for example, the MIME structure of the message). - fetch_result_free() will free all strings resulted by fetch() or any fetch_xxx() functions that returns a string. - fetch() returns the content of the message (headers and text). - fetch_header() returns the content of the headers. - fetch_body() returns the message text (message content without headers) - fetch_size() returns the size of the message content. - get_bodystructure() returns the MIME structure of the message. - fetch_section() returns the content of a given MIME part - fetch_section_header() returns the header of the message contained by the given MIME part. - fetch_section_mime() returns the MIME headers of the given MIME part. - fetch_section_body() returns the text (if this is a message, this is the message content without headers) of the given MIME part. - fetch_envelope() returns a mailimf_fields structure, with a list of fields chosen by the driver. - get_flags() returns a the flags related to the message. When you want to get flags of a message, you have to make sure to call get_flags() at least once before using directly message->flags. */ #define LIBETPAN_MAIL_MESSAGE_CHECK struct mailmessage_driver { char * msg_name; int (* msg_initialize)(mailmessage * msg_info); void (* msg_uninitialize)(mailmessage * msg_info); void (* msg_flush)(mailmessage * msg_info); void (* msg_check)(mailmessage * msg_info); void (* msg_fetch_result_free)(mailmessage * msg_info, char * msg); int (* msg_fetch)(mailmessage * msg_info, char ** result, size_t * result_len); int (* msg_fetch_header)(mailmessage * msg_info, char ** result, size_t * result_len); int (* msg_fetch_body)(mailmessage * msg_info, char ** result, size_t * result_len); int (* msg_fetch_size)(mailmessage * msg_info, size_t * result); int (* msg_get_bodystructure)(mailmessage * msg_info, struct mailmime ** result); int (* msg_fetch_section)(mailmessage * msg_info, struct mailmime * mime, char ** result, size_t * result_len); diff --git a/kmicromail/libetpan/generic/mailfolder.c b/kmicromail/libetpan/generic/mailfolder.c index 2ddc37d..89ba891 100644 --- a/kmicromail/libetpan/generic/mailfolder.c +++ b/kmicromail/libetpan/generic/mailfolder.c @@ -1,96 +1,103 @@ #include "mailfolder.h" #include "maildriver.h" int mailfolder_noop(struct mailfolder * folder) { return mailsession_noop(folder->fld_session); } int mailfolder_check(struct mailfolder * folder) { return mailsession_check_folder(folder->fld_session); } int mailfolder_expunge(struct mailfolder * folder) { return mailsession_expunge_folder(folder->fld_session); } int mailfolder_status(struct mailfolder * folder, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen) { return mailsession_status_folder(folder->fld_session, folder->fld_pathname, result_messages, result_recent, result_unseen); } int mailfolder_append_message(struct mailfolder * folder, char * message, size_t size) { return mailsession_append_message(folder->fld_session, message, size); } +int mailfolder_append_message_flags(struct mailfolder * folder, + char * message, size_t size, struct mail_flags * flags) +{ + return mailsession_append_message_flags(folder->fld_session, message, + size, flags); +} + int mailfolder_get_messages_list(struct mailfolder * folder, struct mailmessage_list ** result) { int r; struct mailmessage_list * msg_list; unsigned int i; r = mailsession_get_messages_list(folder->fld_session, &msg_list); if (r != MAIL_NO_ERROR) return r; for(i = 0 ; i < carray_count(msg_list->msg_tab) ; i ++) { mailmessage * msg; msg = carray_get(msg_list->msg_tab, i); msg->msg_folder = folder; } * result = msg_list; return MAIL_NO_ERROR; } int mailfolder_get_envelopes_list(struct mailfolder * folder, struct mailmessage_list * result) { return mailsession_get_envelopes_list(folder->fld_session, result); } int mailfolder_get_message(struct mailfolder * folder, uint32_t num, mailmessage ** result) { mailmessage * msg; int r; r = mailsession_get_message(folder->fld_session, num, &msg); if (r != MAIL_NO_ERROR) return r; msg->msg_folder = folder; * result = msg; return MAIL_NO_ERROR; } int mailfolder_get_message_by_uid(struct mailfolder * folder, const char * uid, mailmessage ** result) { mailmessage * msg; int r; r = mailsession_get_message_by_uid(folder->fld_session, uid, &msg); if (r != MAIL_NO_ERROR) return r; msg->msg_folder = folder; * result = msg; return MAIL_NO_ERROR; } diff --git a/kmicromail/libetpan/generic/mailfolder.h b/kmicromail/libetpan/generic/mailfolder.h index 3ecad23..ff53470 100644 --- a/kmicromail/libetpan/generic/mailfolder.h +++ b/kmicromail/libetpan/generic/mailfolder.h @@ -1,32 +1,35 @@ #ifndef MAILFOLDER_H #define MAILFOLDER_H #include "mailstorage_types.h" int mailfolder_noop(struct mailfolder * folder); int mailfolder_check(struct mailfolder * folder); int mailfolder_expunge(struct mailfolder * folder); int mailfolder_status(struct mailfolder * folder, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); int mailfolder_append_message(struct mailfolder * folder, char * message, size_t size); +int mailfolder_append_message_flags(struct mailfolder * folder, + char * message, size_t size, struct mail_flags * flags); + int mailfolder_get_messages_list(struct mailfolder * folder, struct mailmessage_list ** result); int mailfolder_get_envelopes_list(struct mailfolder * folder, struct mailmessage_list * result); int mailfolder_get_message(struct mailfolder * folder, uint32_t num, mailmessage ** result); int mailfolder_get_message_by_uid(struct mailfolder * folder, const char * uid, mailmessage ** result); #endif diff --git a/kmicromail/libetpan/generic/mailstorage.c b/kmicromail/libetpan/generic/mailstorage.c index 25e561e..dc91744 100644 --- a/kmicromail/libetpan/generic/mailstorage.c +++ b/kmicromail/libetpan/generic/mailstorage.c @@ -198,137 +198,144 @@ int mailfolder_add_child(struct mailfolder * parent, { unsigned int index; int r; r = carray_add(parent->fld_children, child, &index); if (r < 0) return MAIL_ERROR_MEMORY; child->fld_sibling_index = index; child->fld_parent = parent; return MAIL_NO_ERROR; } int mailfolder_detach_parent(struct mailfolder * folder) { unsigned int i; int r; if (folder->fld_parent == NULL) return MAIL_ERROR_INVAL; r = carray_delete_slow(folder->fld_parent->fld_children, folder->fld_sibling_index); if (r < 0) return MAIL_ERROR_INVAL; for(i = 0 ; i < carray_count(folder->fld_parent->fld_children) ; i ++) { struct mailfolder * child; child = carray_get(folder->fld_parent->fld_children, i); child->fld_sibling_index = i; } folder->fld_parent = NULL; folder->fld_sibling_index = 0; return MAIL_NO_ERROR; } struct mailstorage * mailstorage_new(char * sto_id) { struct mailstorage * storage; storage = malloc(sizeof(struct mailstorage)); if (storage == NULL) goto err; if (sto_id != NULL) { storage->sto_id = strdup(sto_id); if (storage->sto_id == NULL) goto free; } else storage->sto_id = NULL; storage->sto_data = NULL; storage->sto_session = NULL; storage->sto_driver = NULL; storage->sto_shared_folders = clist_new(); if (storage->sto_shared_folders == NULL) goto free_id; return storage; free_id: if (storage->sto_id != NULL) free(storage->sto_id); free: free(storage); err: return NULL; } void mailstorage_free(struct mailstorage * storage) { if (storage->sto_session != NULL) mailstorage_disconnect(storage); if (storage->sto_driver != NULL) { if (storage->sto_driver->sto_uninitialize != NULL) storage->sto_driver->sto_uninitialize(storage); } clist_free(storage->sto_shared_folders); if (storage->sto_id != NULL) free(storage->sto_id); free(storage); } int mailstorage_connect(struct mailstorage * storage) { if (storage->sto_session != NULL) return MAIL_NO_ERROR; if (!clist_isempty(storage->sto_shared_folders)) return MAIL_ERROR_BAD_STATE; if (storage->sto_driver->sto_connect == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return storage->sto_driver->sto_connect(storage); } void mailstorage_disconnect(struct mailstorage * storage) { int r; clistiter * cur; while ((cur = clist_begin(storage->sto_shared_folders)) != NULL) { struct mailfolder * folder; folder = cur->data; mailfolder_disconnect(folder); } if (storage->sto_session == NULL) return; r = mailsession_logout(storage->sto_session); mailsession_free(storage->sto_session); storage->sto_session = NULL; } + +int mailstorage_noop(struct mailstorage * storage) +{ + return mailsession_noop(storage->sto_session); +} + + static int mailstorage_get_folder(struct mailstorage * storage, char * pathname, mailsession ** result) { if (storage->sto_driver->sto_get_folder_session == NULL) return MAIL_ERROR_NOT_IMPLEMENTED; return storage->sto_driver->sto_get_folder_session(storage, pathname, result); } diff --git a/kmicromail/libetpan/generic/mailstorage.h b/kmicromail/libetpan/generic/mailstorage.h index d56aef1..4c57883 100644 --- a/kmicromail/libetpan/generic/mailstorage.h +++ b/kmicromail/libetpan/generic/mailstorage.h @@ -1,98 +1,99 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 MAIL_STORAGE_H #define MAIL_STORAGE_H #include <libetpan/maildriver_types.h> #include <libetpan/mailstorage_types.h> #ifdef __cplusplus extern "C" { #endif /* storage */ /* mailstorage_new This function creates an empty storage. This storage have to be initialized. The "driver" and "data" fields should be initialized. @param id is the name of the storage. It can be NULL. The given parameter is no more needed when the creation is finished. The given string is duplicated. @return The mail storage is returned. */ struct mailstorage * mailstorage_new(char * sto_id); void mailstorage_free(struct mailstorage * storage); /* session will be initialized on success. */ int mailstorage_connect(struct mailstorage * storage); void mailstorage_disconnect(struct mailstorage * storage); +int mailstorage_noop(struct mailstorage * storage); + /* folder */ struct mailfolder * mailfolder_new(struct mailstorage * fld_storage, char * fld_pathname, char * fld_virtual_name); void mailfolder_free(struct mailfolder * folder); int mailfolder_add_child(struct mailfolder * parent, struct mailfolder * child); int mailfolder_detach_parent(struct mailfolder * folder); int mailfolder_connect(struct mailfolder * folder); void mailfolder_disconnect(struct mailfolder * folder); - #ifdef __cplusplus } #endif #endif diff --git a/kmicromail/libetpan/generic/mboxdriver.c b/kmicromail/libetpan/generic/mboxdriver.c index fa3e2ea..c19a668 100644 --- a/kmicromail/libetpan/generic/mboxdriver.c +++ b/kmicromail/libetpan/generic/mboxdriver.c @@ -1,474 +1,484 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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; diff --git a/kmicromail/libetpan/generic/mboxdriver_cached.c b/kmicromail/libetpan/generic/mboxdriver_cached.c index 07871fa..3af7fb9 100644 --- a/kmicromail/libetpan/generic/mboxdriver_cached.c +++ b/kmicromail/libetpan/generic/mboxdriver_cached.c @@ -1,267 +1,272 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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; } } @@ -781,357 +786,436 @@ static int mboxdriver_cached_status_folder(mailsession * session, char * mb, 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 mailsession_append_message(get_ancestor(session), message, 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-%u-envelope", num, info->msg_body_len); + 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-%u-envelope", num, info->msg_body_len); + 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); diff --git a/kmicromail/libetpan/generic/mboxdriver_cached_message.c b/kmicromail/libetpan/generic/mboxdriver_cached_message.c index 6d92b22..828396b 100644 --- a/kmicromail/libetpan/generic/mboxdriver_cached_message.c +++ b/kmicromail/libetpan/generic/mboxdriver_cached_message.c @@ -57,257 +57,258 @@ 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-%u", msg_info->msg_index, info->msg_body_len); + 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; } diff --git a/kmicromail/libetpan/generic/mboxdriver_message.c b/kmicromail/libetpan/generic/mboxdriver_message.c index da9a65d..6922625 100644 --- a/kmicromail/libetpan/generic/mboxdriver_message.c +++ b/kmicromail/libetpan/generic/mboxdriver_message.c @@ -1,225 +1,225 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "mhdriver_message.h" +#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-%u", - msg_info->msg_index, info->msg_body_len); + 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/kmicromail/libetpan/generic/mboxdriver_tools.c b/kmicromail/libetpan/generic/mboxdriver_tools.c index 1e27798..252a20b 100644 --- a/kmicromail/libetpan/generic/mboxdriver_tools.c +++ b/kmicromail/libetpan/generic/mboxdriver_tools.c @@ -92,257 +92,258 @@ int mboxdriver_mbox_error_to_mail_error(int 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-%u-flags", num, info->msg_body_len); + 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; diff --git a/kmicromail/libetpan/generic/mboxstorage.c b/kmicromail/libetpan/generic/mboxstorage.c index 0a7dc93..4b55b2b 100644 --- a/kmicromail/libetpan/generic/mboxstorage.c +++ b/kmicromail/libetpan/generic/mboxstorage.c @@ -1,192 +1,192 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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(struct mbox_mailstorage)); + 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/kmicromail/libetpan/generic/mhdriver.c b/kmicromail/libetpan/generic/mhdriver.c index af38d27..05a6a4f 100644 --- a/kmicromail/libetpan/generic/mhdriver.c +++ b/kmicromail/libetpan/generic/mhdriver.c @@ -1,270 +1,273 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "mhdriver.h" #include <stdio.h> #include <sys/types.h> #include <dirent.h> #include <unistd.h> #include <sys/stat.h> #include <ctype.h> #include <fcntl.h> #include <sys/mman.h> #include <stdlib.h> #include <string.h> #include "mailmh.h" #include "maildriver_tools.h" #include "mhdriver_tools.h" #include "mhdriver_message.h" #include "mailmessage.h" static int mhdriver_initialize(mailsession * session); static void mhdriver_uninitialize(mailsession * session); static int mhdriver_connect_path(mailsession * session, char * path); static int mhdriver_logout(mailsession * session); static int mhdriver_build_folder_name(mailsession * session, char * mb, char * name, char ** result); static int mhdriver_create_folder(mailsession * session, char * mb); static int mhdriver_delete_folder(mailsession * session, char * mb); static int mhdriver_rename_folder(mailsession * session, char * mb, char * new_name); static int mhdriver_select_folder(mailsession * session, char * mb); static int mhdriver_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int mhdriver_messages_number(mailsession * session, char * mb, uint32_t * result); static int mhdriver_list_folders(mailsession * session, char * mb, struct mail_list ** result); static int mhdriver_lsub_folders(mailsession * session, char * mb, struct mail_list ** result); static int mhdriver_subscribe_folder(mailsession * session, char * mb); static int mhdriver_unsubscribe_folder(mailsession * session, char * mb); static int mhdriver_append_message(mailsession * session, char * message, size_t size); +static int mhdriver_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); static int mhdriver_copy_message(mailsession * session, uint32_t num, char * mb); static int mhdriver_remove_message(mailsession * session, uint32_t num); static int mhdriver_move_message(mailsession * session, uint32_t num, char * mb); static int mhdriver_get_messages_list(mailsession * session, struct mailmessage_list ** result); static int mhdriver_get_message(mailsession * session, uint32_t num, mailmessage ** result); static int mhdriver_get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result); static mailsession_driver local_mh_session_driver = { .sess_name = "mh", .sess_initialize = mhdriver_initialize, .sess_uninitialize = mhdriver_uninitialize, .sess_parameters = NULL, .sess_connect_stream = NULL, .sess_connect_path = mhdriver_connect_path, .sess_starttls = NULL, .sess_login = NULL, .sess_logout = mhdriver_logout, .sess_noop = NULL, .sess_build_folder_name = mhdriver_build_folder_name, .sess_create_folder = mhdriver_create_folder, .sess_delete_folder = mhdriver_delete_folder, .sess_rename_folder = mhdriver_rename_folder, .sess_check_folder = NULL, .sess_examine_folder = NULL, .sess_select_folder = mhdriver_select_folder, .sess_expunge_folder = NULL, .sess_status_folder = mhdriver_status_folder, .sess_messages_number = mhdriver_messages_number, .sess_recent_number = mhdriver_messages_number, .sess_unseen_number = mhdriver_messages_number, .sess_list_folders = mhdriver_list_folders, .sess_lsub_folders = mhdriver_lsub_folders, .sess_subscribe_folder = mhdriver_subscribe_folder, .sess_unsubscribe_folder = mhdriver_unsubscribe_folder, - .sess_append_message = mhdriver_append_message, + .sess_append_message = mhdriver_append_message, + .sess_append_message_flags = mhdriver_append_message_flags, .sess_copy_message = mhdriver_copy_message, .sess_move_message = mhdriver_move_message, .sess_get_messages_list = mhdriver_get_messages_list, .sess_get_envelopes_list = maildriver_generic_get_envelopes_list, .sess_remove_message = mhdriver_remove_message, #if 0 .sess_search_messages = maildriver_generic_search_messages, #endif .sess_get_message = mhdriver_get_message, .sess_get_message_by_uid = mhdriver_get_message_by_uid, }; mailsession_driver * mh_session_driver = &local_mh_session_driver; static inline struct mh_session_state_data * get_data(mailsession * session) { return session->sess_data; } static inline struct mailmh * get_mh_session(mailsession * session) { return get_data(session)->mh_session; } static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session) { return get_data(session)->mh_cur_folder; } static int add_to_list(mailsession * session, char * mb) { char * new_mb; struct mh_session_state_data * data; int r; data = get_data(session); new_mb = strdup(mb); if (new_mb == NULL) return -1; r = clist_append(data->mh_subscribed_list, new_mb); if (r < 0) { free(mb); return -1; } return 0; } static int remove_from_list(mailsession * session, char * mb) { clistiter * cur; struct mh_session_state_data * data; data = get_data(session); for(cur = clist_begin(data->mh_subscribed_list) ; cur != NULL ; cur = clist_next(cur)) { char * cur_name; cur_name = clist_content(cur); if (strcmp(cur_name, mb) == 0) { clist_delete(data->mh_subscribed_list, cur); free(cur_name); return 0; } } return -1; } static int mhdriver_initialize(mailsession * session) { struct mh_session_state_data * data; data = malloc(sizeof(* data)); if (data == NULL) goto err; data->mh_session = NULL; data->mh_cur_folder = NULL; data->mh_subscribed_list = clist_new(); if (data->mh_subscribed_list == NULL) goto free; session->sess_data = data; return MAIL_NO_ERROR; free: free(data); err: return MAIL_ERROR_MEMORY; } static void mhdriver_uninitialize(mailsession * session) { struct mh_session_state_data * data; data = get_data(session); if (data->mh_session != NULL) mailmh_free(data->mh_session); clist_foreach(data->mh_subscribed_list, (clist_func) free, NULL); clist_free(data->mh_subscribed_list); free(data); session->sess_data = NULL; } static int mhdriver_connect_path(mailsession * session, char * path) { struct mailmh * mh; if (get_mh_session(session) != NULL) return MAIL_ERROR_BAD_STATE; mh = mailmh_new(path); if (mh == NULL) return MAIL_ERROR_MEMORY; @@ -559,256 +562,262 @@ static int mhdriver_list_folders(mailsession * session, char * mb, int r; struct mailmh * mh; struct mail_list * ml; mh = get_mh_session(session); if (mh == NULL) return MAIL_ERROR_BAD_STATE; list = clist_new(); if (list == NULL) return MAIL_ERROR_MEMORY; r = get_list_folders(mh->mh_main, &list); if (r != MAIL_NO_ERROR) return r; ml = mail_list_new(list); if (ml == NULL) goto free; * result = ml; return MAIL_NO_ERROR; free: clist_foreach(list, (clist_func) free, NULL); clist_free(list); return MAIL_ERROR_MEMORY; } static int mhdriver_lsub_folders(mailsession * session, char * mb, struct mail_list ** result) { clist * subscribed; clist * lsub_result; clistiter * cur; struct mail_list * lsub; size_t length; int r; length = strlen(mb); subscribed = get_data(session)->mh_subscribed_list; lsub_result = clist_new(); if (lsub_result == NULL) return MAIL_ERROR_MEMORY; for(cur = clist_begin(subscribed) ; cur != NULL ; cur = clist_next(cur)) { char * cur_mb; char * new_mb; cur_mb = clist_content(cur); if (strncmp(mb, cur_mb, length) == 0) { new_mb = strdup(cur_mb); if (new_mb == NULL) goto free_list; r = clist_append(lsub_result, new_mb); if (r < 0) { free(new_mb); goto free_list; } } } lsub = mail_list_new(lsub_result); if (lsub == NULL) goto free_list; * result = lsub; return MAIL_NO_ERROR; free_list: clist_foreach(lsub_result, (clist_func) free, NULL); clist_free(lsub_result); return MAIL_ERROR_MEMORY; } static int mhdriver_subscribe_folder(mailsession * session, char * mb) { int r; r = add_to_list(session, mb); if (r < 0) return MAIL_ERROR_SUBSCRIBE; return MAIL_NO_ERROR; } static int mhdriver_unsubscribe_folder(mailsession * session, char * mb) { int r; r = remove_from_list(session, mb); if (r < 0) return MAIL_ERROR_UNSUBSCRIBE; return MAIL_NO_ERROR; } /* messages operations */ static int mhdriver_append_message(mailsession * session, char * message, size_t size) { int r; struct mailmh_folder * folder; folder = get_mh_cur_folder(session); if (folder == NULL) return MAIL_ERROR_BAD_STATE; r = mailmh_folder_add_message(folder, message, size); switch (r) { case MAILMH_ERROR_FILE: return MAIL_ERROR_DISKSPACE; default: return mhdriver_mh_error_to_mail_error(r); } } +static int mhdriver_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + return mhdriver_append_message(session, message, size); +} + static int mhdriver_copy_message(mailsession * session, uint32_t num, char * mb) { int fd; int r; struct mailmh_folder * folder; struct mailmh * mh; int res; mh = get_mh_session(session); if (mh == NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } folder = get_mh_cur_folder(session); if (folder == NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } r = mailmh_folder_get_message_fd(folder, num, O_RDONLY, &fd); if (r != MAIL_NO_ERROR) { res = r; goto err; } folder = mailmh_folder_find(mh->mh_main, mb); if (folder == NULL) { res = MAIL_ERROR_FOLDER_NOT_FOUND; goto close; } r = mailmh_folder_add_message_file(folder, fd); if (r != MAIL_NO_ERROR) { res = MAIL_ERROR_COPY; goto close; } close(fd); return MAIL_NO_ERROR; close: close(fd); err: return res; } static int mhdriver_remove_message(mailsession * session, uint32_t num) { int r; struct mailmh_folder * folder; folder = get_mh_cur_folder(session); if (folder == NULL) return MAIL_ERROR_DELETE; r = mailmh_folder_remove_message(folder, num); return mhdriver_mh_error_to_mail_error(r); } static int mhdriver_move_message(mailsession * session, uint32_t num, char * mb) { int r; struct mailmh_folder * src_folder; struct mailmh_folder * dest_folder; struct mailmh * mh; mh = get_mh_session(session); if (mh == NULL) return MAIL_ERROR_BAD_STATE; src_folder = get_mh_cur_folder(session); if (src_folder == NULL) return MAIL_ERROR_BAD_STATE; dest_folder = mailmh_folder_find(mh->mh_main, mb); if (dest_folder == NULL) return MAIL_ERROR_FOLDER_NOT_FOUND; r = mailmh_folder_move_message(dest_folder, src_folder, num); return mhdriver_mh_error_to_mail_error(r); } static int mhdriver_get_messages_list(mailsession * session, struct mailmessage_list ** result) { struct mailmh_folder * folder; int res; folder = get_mh_cur_folder(session); if (folder == NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } mailmh_folder_update(folder); return mh_get_messages_list(folder, session, mh_message_driver, result); err: return res; } static int mhdriver_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, mh_message_driver, num, 0); if (r != MAIL_NO_ERROR) { mailmessage_free(msg_info); return r; } * result = msg_info; return MAIL_NO_ERROR; } diff --git a/kmicromail/libetpan/generic/mhdriver_cached.c b/kmicromail/libetpan/generic/mhdriver_cached.c index 5c35089..04aa523 100644 --- a/kmicromail/libetpan/generic/mhdriver_cached.c +++ b/kmicromail/libetpan/generic/mhdriver_cached.c @@ -1,295 +1,298 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "mhdriver_cached.h" #include <stdio.h> #include <sys/types.h> #include <dirent.h> #include <unistd.h> #include <sys/stat.h> #include <ctype.h> #include <fcntl.h> #include <sys/mman.h> #include <stdlib.h> #include <string.h> #include "mail.h" #include "mail_cache_db.h" #include "generic_cache.h" #include "imfcache.h" #include "mhdriver.h" #include "mhdriver_cached_message.h" #include "mailmh.h" #include "maildriver_tools.h" #include "mhdriver_tools.h" #include "mailmessage.h" static int mhdriver_cached_initialize(mailsession * session); static void mhdriver_cached_uninitialize(mailsession * session); static int mhdriver_cached_parameters(mailsession * session, int id, void * value); static int mhdriver_cached_connect_path(mailsession * session, char * path); static int mhdriver_cached_logout(mailsession * session); static int mhdriver_cached_build_folder_name(mailsession * session, char * mb, char * name, char ** result); static int mhdriver_cached_create_folder(mailsession * session, char * mb); static int mhdriver_cached_delete_folder(mailsession * session, char * mb); static int mhdriver_cached_rename_folder(mailsession * session, char * mb, char * new_name); static int mhdriver_cached_check_folder(mailsession * session); static int mhdriver_cached_select_folder(mailsession * session, char * mb); static int mhdriver_cached_expunge_folder(mailsession * session); static int mhdriver_cached_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int mhdriver_cached_messages_number(mailsession * session, char * mb, uint32_t * result); static int mhdriver_cached_recent_number(mailsession * session, char * mb, uint32_t * result); static int mhdriver_cached_unseen_number(mailsession * session, char * mb, uint32_t * result); static int mhdriver_cached_list_folders(mailsession * session, char * mb, struct mail_list ** result); static int mhdriver_cached_lsub_folders(mailsession * session, char * mb, struct mail_list ** result); static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb); static int mhdriver_cached_unsubscribe_folder(mailsession * session, char * mb); static int mhdriver_cached_append_message(mailsession * session, char * message, size_t size); +static int mhdriver_cached_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); static int mhdriver_cached_copy_message(mailsession * session, uint32_t num, char * mb); static int mhdriver_cached_remove_message(mailsession * session, uint32_t num); static int mhdriver_cached_move_message(mailsession * session, uint32_t num, char * mb); static int mhdriver_cached_get_messages_list(mailsession * session, struct mailmessage_list ** result); static int mhdriver_cached_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list); static int mhdriver_cached_get_message(mailsession * session, uint32_t num, mailmessage ** result); static int mhdriver_cached_get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result); static mailsession_driver local_mh_cached_session_driver = { .sess_name = "mh-cached", .sess_initialize = mhdriver_cached_initialize, .sess_uninitialize = mhdriver_cached_uninitialize, .sess_parameters = mhdriver_cached_parameters, .sess_connect_stream = NULL, .sess_connect_path = mhdriver_cached_connect_path, .sess_starttls = NULL, .sess_login = NULL, .sess_logout = mhdriver_cached_logout, .sess_noop = NULL, .sess_build_folder_name = mhdriver_cached_build_folder_name, .sess_create_folder = mhdriver_cached_create_folder, .sess_delete_folder = mhdriver_cached_delete_folder, .sess_rename_folder = mhdriver_cached_rename_folder, .sess_check_folder = mhdriver_cached_check_folder, .sess_examine_folder = NULL, .sess_select_folder = mhdriver_cached_select_folder, .sess_expunge_folder = mhdriver_cached_expunge_folder, .sess_status_folder = mhdriver_cached_status_folder, .sess_messages_number = mhdriver_cached_messages_number, .sess_recent_number = mhdriver_cached_recent_number, .sess_unseen_number = mhdriver_cached_unseen_number, .sess_list_folders = mhdriver_cached_list_folders, .sess_lsub_folders = mhdriver_cached_lsub_folders, .sess_subscribe_folder = mhdriver_cached_subscribe_folder, .sess_unsubscribe_folder = mhdriver_cached_unsubscribe_folder, .sess_append_message = mhdriver_cached_append_message, + .sess_append_message_flags = mhdriver_cached_append_message_flags, .sess_copy_message = mhdriver_cached_copy_message, .sess_move_message = mhdriver_cached_move_message, .sess_get_messages_list = mhdriver_cached_get_messages_list, .sess_get_envelopes_list = mhdriver_cached_get_envelopes_list, .sess_remove_message = mhdriver_cached_remove_message, #if 0 .sess_search_messages = maildriver_generic_search_messages, #endif .sess_get_message = mhdriver_cached_get_message, .sess_get_message_by_uid = mhdriver_cached_get_message_by_uid, }; mailsession_driver * mh_cached_session_driver = &local_mh_cached_session_driver; #define ENV_NAME "env.db" #define FLAGS_NAME "flags.db" static inline struct mh_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)->mh_ancestor; } static inline struct mh_session_state_data * get_ancestor_data(mailsession * session) { return get_ancestor(session)->sess_data; } static inline struct mailmh * get_mh_session(mailsession * session) { return get_ancestor_data(session)->mh_session; } static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session) { return get_ancestor_data(session)->mh_cur_folder; } #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; struct mh_cached_session_state_data * cached_data; struct mh_session_state_data * ancestor_data; int fd; MMAPString * mmapstr; size_t cur_token; cached_data = get_cached_data(session); ancestor_data = get_ancestor_data(session); if (cached_data->mh_quoted_mb == NULL) return MAIL_ERROR_BAD_STATE; snprintf(filename, PATH_MAX, "%s/%s/%s", cached_data->mh_cache_directory, cached_data->mh_quoted_mb, 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 err; } 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, ancestor_data->mh_cur_folder->fl_max_index); if (r != MAIL_NO_ERROR) { res = r; goto free_mmapstr; } fwrite(mmapstr->str, 1, mmapstr->len, f); mmap_string_free(mmapstr); fclose(f); return MAIL_NO_ERROR; free_mmapstr: mmap_string_free(mmapstr); close: fclose(f); err: return res; } static int read_max_uid_value(mailsession * session) { int r; @@ -758,373 +761,453 @@ static int mhdriver_cached_status_folder(mailsession * session, char * mb, cached_data->mh_quoted_mb, 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->fl_msgs_tab) ; i++) { struct mailmh_msg_info * mh_info; struct mail_flags * flags; mh_info = carray_get(folder->fl_msgs_tab, i); if (mh_info == NULL) continue; count ++; r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, session, mh_info->msg_index, &flags); if (r != MAIL_NO_ERROR) { recent ++; unseen ++; continue; } if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { recent ++; } if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { unseen ++; } mail_flags_free(flags); } mmap_string_free(mmapstr); mail_cache_db_close_unlock(filename_flags, cache_db_flags); * result_messages = count; * 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 mhdriver_cached_messages_number(mailsession * session, char * mb, uint32_t * result) { return mailsession_messages_number(get_ancestor(session), mb, result); } static int mhdriver_cached_recent_number(mailsession * session, char * mb, uint32_t * result) { uint32_t messages; uint32_t recent; uint32_t unseen; int r; r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = recent; return MAIL_NO_ERROR; } static int mhdriver_cached_unseen_number(mailsession * session, char * mb, uint32_t * result) { uint32_t messages; uint32_t recent; uint32_t unseen; int r; r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = recent; return MAIL_NO_ERROR; } static int mhdriver_cached_list_folders(mailsession * session, char * mb, struct mail_list ** result) { return mailsession_list_folders(get_ancestor(session), mb, result); } static int mhdriver_cached_lsub_folders(mailsession * session, char * mb, struct mail_list ** result) { return mailsession_lsub_folders(get_ancestor(session), mb, result); } static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb) { return mailsession_subscribe_folder(get_ancestor(session), mb); } static int mhdriver_cached_unsubscribe_folder(mailsession * session, char * mb) { return mailsession_unsubscribe_folder(get_ancestor(session), mb); } /* messages operations */ static int mhdriver_cached_append_message(mailsession * session, char * message, size_t size) { - return mailsession_append_message(get_ancestor(session), message, size); + return mhdriver_cached_append_message_flags(session, + message, size, NULL); +} + +static int mhdriver_cached_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + int r; + struct mailmh_folder * folder; + struct mailmh_msg_info * msg_info; + chashdatum key; + chashdatum value; + uint32_t uid; + struct mh_cached_session_state_data * data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + char keyname[PATH_MAX]; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmh_folder_add_message_uid(folder, + message, size, &uid); + + switch (r) { + case MAILMH_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + + case MAILMH_NO_ERROR: + break; + + default: + return mhdriver_mh_error_to_mail_error(r); + } + + if (flags == NULL) + goto exit; + + key.data = &uid; + key.len = sizeof(uid); + r = chash_get(folder->fl_msgs_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + + msg_info = value.data; + + data = get_cached_data(session); + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + data->mh_flags_directory, data->mh_quoted_mb, 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-%lu-flags", + uid, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); + + r = mhdriver_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 mhdriver_cached_copy_message(mailsession * session, uint32_t num, char * mb) { return mailsession_copy_message(get_ancestor(session), num, mb); } static int mhdriver_cached_remove_message(mailsession * session, uint32_t num) { return mailsession_remove_message(get_ancestor(session), num); } static int mhdriver_cached_move_message(mailsession * session, uint32_t num, char * mb) { return mailsession_move_message(get_ancestor(session), num, mb); } static int mhdriver_cached_get_messages_list(mailsession * session, struct mailmessage_list ** result) { struct mailmh_folder * folder; int res; folder = get_mh_cur_folder(session); if (folder == NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } return mh_get_messages_list(folder, session, mh_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 mailmh_folder * folder; struct mailmh_msg_info * msg_info; chashdatum key; chashdatum data; folder = get_mh_cur_folder(session); #if 0 msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num); if (msg_info == NULL) return MAIL_ERROR_CACHE_MISS; #endif key.data = # key.len = sizeof(num); r = chash_get(folder->fl_msgs_hash, &key, &data); if (r < 0) return MAIL_ERROR_CACHE_MISS; msg_info = data.data; - snprintf(keyname, PATH_MAX, "%u-%u-%u-envelope", - num, (uint32_t) msg_info->msg_mtime, msg_info->msg_size); + snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope", + num, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); 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 mailmh_folder * folder; chashdatum key; chashdatum data; struct mailmh_msg_info * msg_info; folder = get_mh_cur_folder(session); #if 0 msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num); if (msg_info == NULL) { res = MAIL_ERROR_CACHE_MISS; goto err; } #endif key.data = # key.len = sizeof(num); r = chash_get(folder->fl_msgs_hash, &key, &data); if (r < 0) return MAIL_ERROR_CACHE_MISS; msg_info = data.data; - snprintf(keyname, PATH_MAX, "%u-%u-%u-envelope", - num, (uint32_t) msg_info->msg_mtime, msg_info->msg_size); + snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope", + num, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); 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 mhdriver_cached_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list) { int r; unsigned int i; 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 mh_cached_session_state_data * cached_data; cached_data = get_cached_data(session); if (cached_data->mh_quoted_mb == NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } mh_flags_store_process(cached_data->mh_flags_directory, cached_data->mh_quoted_mb, cached_data->mh_flags_store); mmapstr = mmap_string_new(""); if (mmapstr == NULL) { res = MAIL_ERROR_MEMORY; goto err; } snprintf(filename_env, PATH_MAX, "%s/%s/%s", cached_data->mh_cache_directory, cached_data->mh_quoted_mb, 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/%s/%s", cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME); r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); if (r < 0) { res = MAIL_ERROR_MEMORY; 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, msg->msg_session, msg->msg_index, &fields); if (r == MAIL_NO_ERROR) { msg->msg_cached = TRUE; msg->msg_fields = fields; } } if (msg->msg_flags == NULL) { r = mhdriver_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; } 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_MEMORY; goto close_db_env; } /* 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(); } /* must write cache */ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { mailmessage * msg; msg = carray_get(env_list->msg_tab, i); diff --git a/kmicromail/libetpan/generic/mhdriver_cached_message.c b/kmicromail/libetpan/generic/mhdriver_cached_message.c index f716fb9..f69868d 100644 --- a/kmicromail/libetpan/generic/mhdriver_cached_message.c +++ b/kmicromail/libetpan/generic/mhdriver_cached_message.c @@ -54,258 +54,258 @@ static int mh_prefetch(mailmessage * msg_info); static void mh_prefetch_free(struct generic_message_t * msg); static int mh_initialize(mailmessage * msg_info); static int mh_fetch_size(mailmessage * msg_info, size_t * result); static int mh_get_flags(mailmessage * msg_info, struct mail_flags ** result); static void mh_uninitialize(mailmessage * msg_info); static void mh_flush(mailmessage * msg_info); static void mh_check(mailmessage * msg_info); static int mh_fetch_header(mailmessage * msg_info, char ** result, size_t * result_len); static mailmessage_driver local_mh_cached_message_driver = { .msg_name = "mh-cached", .msg_initialize = mh_initialize, .msg_uninitialize = mh_uninitialize, .msg_flush = mh_flush, .msg_check = mh_check, .msg_fetch_result_free = mailmessage_generic_fetch_result_free, .msg_fetch = mailmessage_generic_fetch, .msg_fetch_header = mh_fetch_header, .msg_fetch_body = mailmessage_generic_fetch_body, .msg_fetch_size = mh_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 = mh_get_flags, }; mailmessage_driver * mh_cached_message_driver = &local_mh_cached_message_driver; static inline struct mh_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)->mh_ancestor; } static inline struct mh_session_state_data * get_ancestor_session_data(mailmessage * msg) { return get_ancestor_session(msg)->sess_data; } static inline struct mailmh * get_mh_session(mailmessage * msg) { return get_ancestor_session_data(msg)->mh_session; } static inline struct mailmh_folder * get_mh_cur_folder(mailmessage * msg) { return get_ancestor_session_data(msg)->mh_cur_folder; } static int mh_prefetch(mailmessage * msg_info) { struct generic_message_t * msg; int r; char * msg_content; size_t msg_length; r = mhdriver_fetch_message(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 mh_prefetch_free(struct generic_message_t * msg) { if (msg->msg_message != NULL) { mmap_string_unref(msg->msg_message); msg->msg_message = NULL; } } static int mh_initialize(mailmessage * msg_info) { struct generic_message_t * msg; int r; char * uid; char static_uid[PATH_MAX]; struct mailmh_msg_info * mh_msg_info; chashdatum key; chashdatum data; struct mailmh_folder * folder; folder = get_mh_cur_folder(msg_info); key.data = &msg_info->msg_index; key.len = sizeof(msg_info->msg_index); r = chash_get(folder->fl_msgs_hash, &key, &data); if (r < 0) return MAIL_ERROR_INVAL; mh_msg_info = data.data; - snprintf(static_uid, PATH_MAX, "%u-%lu-%u", msg_info->msg_index, - mh_msg_info->msg_mtime, mh_msg_info->msg_size); + snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index, + mh_msg_info->msg_mtime, (unsigned long) mh_msg_info->msg_size); uid = strdup(static_uid); if (uid == NULL) return MAIL_ERROR_MEMORY; r = mailmessage_generic_initialize(msg_info); if (r != MAIL_NO_ERROR) { free(uid); return r; } msg = msg_info->msg_data; msg->msg_prefetch = mh_prefetch; msg->msg_prefetch_free = mh_prefetch_free; msg_info->msg_uid = uid; return MAIL_NO_ERROR; } static void mh_uninitialize(mailmessage * msg_info) { mailmessage_generic_uninitialize(msg_info); } #define FLAGS_NAME "flags.db" static void mh_flush(mailmessage * msg_info) { mailmessage_generic_flush(msg_info); } static void mh_check(mailmessage * msg_info) { int r; if (msg_info->msg_flags != NULL) { r = mail_flags_store_set(get_cached_session_data(msg_info)->mh_flags_store, msg_info); /* ignore errors */ } } static int mh_fetch_size(mailmessage * msg_info, size_t * result) { int r; size_t size; r = mhdriver_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 mh_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 mh_cached_session_state_data * cached_data; MMAPString * mmapstr; if (msg_info->msg_flags != NULL) { * result = msg_info->msg_flags; return MAIL_NO_ERROR; } cached_data = get_cached_session_data(msg_info); flags = mail_flags_store_get(cached_data->mh_flags_store, msg_info->msg_index); if (flags == NULL) { if (cached_data->mh_quoted_mb == NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } snprintf(filename_flags, PATH_MAX, "%s/%s/%s", cached_data->mh_flags_directory, cached_data->mh_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; } r = mhdriver_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; diff --git a/kmicromail/libetpan/generic/mhdriver_message.c b/kmicromail/libetpan/generic/mhdriver_message.c index 2c023e7..aafd2d9 100644 --- a/kmicromail/libetpan/generic/mhdriver_message.c +++ b/kmicromail/libetpan/generic/mhdriver_message.c @@ -19,194 +19,195 @@ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 "mhdriver_message.h" #include "mailmessage_tools.h" #include "mhdriver_tools.h" #include "mhdriver.h" #include "mailmh.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 mh_prefetch(mailmessage * msg_info); static void mh_prefetch_free(struct generic_message_t * msg); static int mh_initialize(mailmessage * msg_info); static int mh_fetch_size(mailmessage * msg_info, size_t * result); static int mh_fetch_header(mailmessage * msg_info, char ** result, size_t * result_len); static mailmessage_driver local_mh_message_driver = { .msg_name = "mh", .msg_initialize = mh_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 = mh_fetch_header, .msg_fetch_body = mailmessage_generic_fetch_body, .msg_fetch_size = mh_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 * mh_message_driver = &local_mh_message_driver; static int mh_prefetch(mailmessage * msg_info) { struct generic_message_t * msg; int r; char * msg_content; size_t msg_length; r = mhdriver_fetch_message(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 mh_prefetch_free(struct generic_message_t * msg) { if (msg->msg_message != NULL) { mmap_string_unref(msg->msg_message); msg->msg_message = NULL; } } static inline struct mh_session_state_data * get_data(mailmessage * msg) { return msg->msg_session->sess_data; } static inline struct mailmh_folder * get_mh_cur_folder(mailmessage * msg) { return get_data(msg)->mh_cur_folder; } static int mh_initialize(mailmessage * msg_info) { struct generic_message_t * msg; int r; char * uid; char static_uid[PATH_MAX]; struct mailmh_msg_info * mh_msg_info; chashdatum key; chashdatum value; key.data = &msg_info->msg_index; key.len = sizeof(msg_info->msg_index); r = chash_get(get_mh_cur_folder(msg_info)->fl_msgs_hash, &key, &value); if (r < 0) return MAIL_ERROR_INVAL; mh_msg_info = value.data; - snprintf(static_uid, PATH_MAX, "%u-%lu-%u", msg_info->msg_index, - mh_msg_info->msg_mtime, mh_msg_info->msg_size); + snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index, + (unsigned long) mh_msg_info->msg_mtime, + (unsigned long) mh_msg_info->msg_size); uid = strdup(static_uid); if (uid == NULL) return MAIL_ERROR_MEMORY; r = mailmessage_generic_initialize(msg_info); if (r != MAIL_NO_ERROR) { free(uid); return r; } msg = msg_info->msg_data; msg->msg_prefetch = mh_prefetch; msg->msg_prefetch_free = mh_prefetch_free; msg_info->msg_uid = uid; return MAIL_NO_ERROR; } static int mh_fetch_size(mailmessage * msg_info, size_t * result) { int r; size_t size; r = mhdriver_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 mh_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) { r = mailmessage_generic_fetch_header(msg_info, result, result_len); return r; } else { r = mhdriver_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/kmicromail/libetpan/generic/mhdriver_tools.c b/kmicromail/libetpan/generic/mhdriver_tools.c index cb863fa..c15bb6d 100644 --- a/kmicromail/libetpan/generic/mhdriver_tools.c +++ b/kmicromail/libetpan/generic/mhdriver_tools.c @@ -244,232 +244,233 @@ int mhdriver_fetch_header(mailsession * session, uint32_t index, default: res = mhdriver_mh_error_to_mail_error(r); goto close; } str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); if (str == MAP_FAILED) { res = MAIL_ERROR_FETCH; goto close; } /* strip "From " header for broken implementations */ cur_token = 0; if (size > 5) { if (strncmp("From ", str, size) == 0) { cur_token += 5; while (str[cur_token] != '\n') { if (cur_token >= size) break; cur_token ++; } } } begin = cur_token; while (1) { r = mailimf_ignore_field_parse(str, size, &cur_token); if (r == MAILIMF_NO_ERROR) { /* do nothing */ } else break; } mailimf_crlf_parse(str, size, &cur_token); mmapstr = mmap_string_new_len(str + begin, cur_token - begin); if (mmapstr == NULL) { res = MAIL_ERROR_MEMORY; goto unmap; } if (mmap_string_ref(mmapstr) != 0) { res = MAIL_ERROR_MEMORY; goto free_str; } munmap(str, size); close(fd); * result = mmapstr->str; * result_len = mmapstr->len; return MAIL_NO_ERROR; free_str: mmap_string_free(mmapstr); unmap: munmap(str, size); close: close(fd); err: return res; } int mhdriver_fetch_size(mailsession * session, uint32_t index, size_t * result) { struct mailmh_folder * folder; int r; struct stat buf; char * name; folder = get_mh_cur_folder(session); if (folder == NULL) return MAIL_ERROR_FETCH; r = mailmh_folder_get_message_filename(folder, index, &name); switch (r) { case MAILMH_NO_ERROR: break; default: return mhdriver_mh_error_to_mail_error(r); } r = stat(name, &buf); free(name); if (r == -1) return MAIL_ERROR_FETCH; * result = buf.st_size; return MAIL_NO_ERROR; } int mhdriver_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 mailmh_msg_info * msg_info; chashdatum key; chashdatum data; struct mailmh_folder * folder; folder = cached_get_mh_cur_folder(session); #if 0 msg_info = cinthash_find(mh_data->cur_folder->fl_msgs_hash, num); if (msg_info == NULL) return MAIL_ERROR_CACHE_MISS; #endif key.data = # key.len = sizeof(num); r = chash_get(folder->fl_msgs_hash, &key, &data); if (r < 0) return MAIL_ERROR_CACHE_MISS; msg_info = data.data; - snprintf(keyname, PATH_MAX, "%u-%u-%u-flags", - num, (uint32_t) msg_info->msg_mtime, msg_info->msg_size); + snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags", + num, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); 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 mhdriver_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 mh_get_messages_list(struct mailmh_folder * folder, mailsession * session, mailmessage_driver * driver, struct mailmessage_list ** result) { unsigned int i; struct mailmessage_list * env_list; int r; carray * tab; int res; tab = carray_new(128); if (tab == NULL) { res = MAIL_ERROR_MEMORY; goto err; } for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { struct mailmh_msg_info * mh_info; mailmessage * msg; mh_info = carray_get(folder->fl_msgs_tab, i); if (mh_info == NULL) continue; msg = mailmessage_new(); if (msg == NULL) { res = MAIL_ERROR_MEMORY; goto free_list; } r = mailmessage_init(msg, session, driver, mh_info->msg_index, mh_info->msg_size); if (r != MAIL_NO_ERROR) { res = r; goto free_list; } r = carray_add(tab, msg, NULL); if (r < 0) { mailmessage_free(msg); res = MAIL_ERROR_MEMORY; goto free_list; } } env_list = mailmessage_list_new(tab); if (env_list == NULL) { res = MAIL_ERROR_MEMORY; goto free_list; } * result = env_list; return MAIL_NO_ERROR; free_list: for(i = 0 ; i < carray_count(tab) ; i ++) mailmessage_free(carray_get(tab, i)); carray_free(tab); err: return res; } diff --git a/kmicromail/libetpan/generic/mhstorage.c b/kmicromail/libetpan/generic/mhstorage.c index 32fc26b..715b961 100644 --- a/kmicromail/libetpan/generic/mhstorage.c +++ b/kmicromail/libetpan/generic/mhstorage.c @@ -1,192 +1,192 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "mhstorage.h" #include "mhdriver.h" #include "mhdriver_cached.h" #include "mail.h" #include <stdlib.h> #include <string.h> /* mh storage */ static int mh_mailstorage_connect(struct mailstorage * storage); static int mh_mailstorage_get_folder_session(struct mailstorage * storage, char * pathname, mailsession ** result); static void mh_mailstorage_uninitialize(struct mailstorage * storage); static mailstorage_driver mh_mailstorage_driver = { .sto_name = "mh", .sto_connect = mh_mailstorage_connect, .sto_get_folder_session = mh_mailstorage_get_folder_session, .sto_uninitialize = mh_mailstorage_uninitialize, }; int mh_mailstorage_init(struct mailstorage * storage, char * mh_pathname, int mh_cached, char * mh_cache_directory, char * mh_flags_directory) { struct mh_mailstorage * mh_storage; - mh_storage = malloc(sizeof(struct mh_mailstorage)); + mh_storage = malloc(sizeof(* mh_storage)); if (mh_storage == NULL) goto err; mh_storage->mh_pathname = strdup(mh_pathname); if (mh_storage->mh_pathname == NULL) goto free; mh_storage->mh_cached = mh_cached; if (mh_cached && (mh_cache_directory != NULL) && (mh_flags_directory != NULL)) { mh_storage->mh_cache_directory = strdup(mh_cache_directory); if (mh_storage->mh_cache_directory == NULL) goto free_pathname; mh_storage->mh_flags_directory = strdup(mh_flags_directory); if (mh_storage->mh_flags_directory == NULL) goto free_cache_directory; } else { mh_storage->mh_cached = FALSE; mh_storage->mh_cache_directory = NULL; mh_storage->mh_flags_directory = NULL; } storage->sto_data = mh_storage; storage->sto_driver = &mh_mailstorage_driver; return MAIL_NO_ERROR; free_cache_directory: free(mh_storage->mh_cache_directory); free_pathname: free(mh_storage->mh_pathname); free: free(mh_storage); err: return MAIL_ERROR_MEMORY; } static void mh_mailstorage_uninitialize(struct mailstorage * storage) { struct mh_mailstorage * mh_storage; mh_storage = storage->sto_data; if (mh_storage->mh_flags_directory != NULL) free(mh_storage->mh_flags_directory); if (mh_storage->mh_cache_directory != NULL) free(mh_storage->mh_cache_directory); free(mh_storage->mh_pathname); free(mh_storage); storage->sto_data = NULL; } static int mh_mailstorage_connect(struct mailstorage * storage) { struct mh_mailstorage * mh_storage; mailsession_driver * driver; int r; int res; mailsession * session; mh_storage = storage->sto_data; if (mh_storage->mh_cached) driver = mh_cached_session_driver; else driver = mh_session_driver; session = mailsession_new(driver); if (session == NULL) { res = MAIL_ERROR_MEMORY; goto err; } if (mh_storage->mh_cached) { r = mailsession_parameters(session, MHDRIVER_CACHED_SET_CACHE_DIRECTORY, mh_storage->mh_cache_directory); if (r != MAIL_NO_ERROR) { res = r; goto free; } r = mailsession_parameters(session, MHDRIVER_CACHED_SET_FLAGS_DIRECTORY, mh_storage->mh_flags_directory); if (r != MAIL_NO_ERROR) { res = r; goto free; } } r = mailsession_connect_path(session, mh_storage->mh_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 mh_mailstorage_get_folder_session(struct mailstorage * storage, char * pathname, mailsession ** result) { int r; r = mailsession_select_folder(storage->sto_session, pathname); if (r != MAIL_NO_ERROR) return r; * result = storage->sto_session; return MAIL_NO_ERROR; } diff --git a/kmicromail/libetpan/generic/nntpdriver.c b/kmicromail/libetpan/generic/nntpdriver.c index fde5f1a..1b65838 100644 --- a/kmicromail/libetpan/generic/nntpdriver.c +++ b/kmicromail/libetpan/generic/nntpdriver.c @@ -1,259 +1,263 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "nntpdriver.h" #include <string.h> #include <stdlib.h> #include "mail.h" #include "mailmessage.h" #include "nntpdriver_tools.h" #include "maildriver_tools.h" #include "nntpdriver_message.h" static int nntpdriver_initialize(mailsession * session); static void nntpdriver_uninitialize(mailsession * session); static int nntpdriver_parameters(mailsession * session, int id, void * value); static int nntpdriver_connect_stream(mailsession * session, mailstream * s); static int nntpdriver_login(mailsession * session, char * userid, char * password); static int nntpdriver_logout(mailsession * session); static int nntpdriver_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int nntpdriver_messages_number(mailsession * session, char * mb, uint32_t * result); static int nntpdriver_append_message(mailsession * session, char * message, size_t size); +static int nntpdriver_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); + static int nntpdriver_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list); static int nntpdriver_get_messages_list(mailsession * session, struct mailmessage_list ** result); static int nntpdriver_list_folders(mailsession * session, char * mb, struct mail_list ** result); static int nntpdriver_lsub_folders(mailsession * session, char * mb, struct mail_list ** result); static int nntpdriver_subscribe_folder(mailsession * session, char * mb); static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb); static int nntpdriver_get_message(mailsession * session, uint32_t num, mailmessage ** result); static int nntpdriver_get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result); static int nntpdriver_noop(mailsession * session); static mailsession_driver local_nntp_session_driver = { .sess_name = "nntp", .sess_initialize = nntpdriver_initialize, .sess_uninitialize = nntpdriver_uninitialize, .sess_parameters = nntpdriver_parameters, .sess_connect_stream = nntpdriver_connect_stream, .sess_connect_path = NULL, .sess_starttls = NULL, .sess_login = nntpdriver_login, .sess_logout = nntpdriver_logout, .sess_noop = nntpdriver_noop, .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 = nntpdriver_select_folder, .sess_expunge_folder = NULL, .sess_status_folder = nntpdriver_status_folder, .sess_messages_number = nntpdriver_messages_number, .sess_recent_number = nntpdriver_messages_number, .sess_unseen_number = nntpdriver_messages_number, .sess_list_folders = nntpdriver_list_folders, .sess_lsub_folders = nntpdriver_lsub_folders, .sess_subscribe_folder = nntpdriver_subscribe_folder, .sess_unsubscribe_folder = nntpdriver_unsubscribe_folder, .sess_append_message = nntpdriver_append_message, + .sess_append_message_flags = nntpdriver_append_message_flags, .sess_copy_message = NULL, .sess_move_message = NULL, .sess_get_messages_list = nntpdriver_get_messages_list, .sess_get_envelopes_list = nntpdriver_get_envelopes_list, .sess_remove_message = NULL, #if 0 .sess_search_messages = maildriver_generic_search_messages, #endif .sess_get_message = nntpdriver_get_message, .sess_get_message_by_uid = nntpdriver_get_message_by_uid, }; mailsession_driver * nntp_session_driver = &local_nntp_session_driver; static inline struct nntp_session_state_data * get_data(mailsession * session) { return session->sess_data; } static inline newsnntp * get_nntp_session(mailsession * session) { return get_data(session)->nntp_session; } static int nntpdriver_initialize(mailsession * session) { struct nntp_session_state_data * data; newsnntp * nntp; nntp = newsnntp_new(0, NULL); if (nntp == NULL) goto err; data = malloc(sizeof(* data)); if (data == NULL) goto free; data->nntp_session = nntp; data->nntp_userid = NULL; data->nntp_password = NULL; data->nntp_group_info = NULL; data->nntp_group_name = NULL; data->nntp_subscribed_list = clist_new(); if (data->nntp_subscribed_list == NULL) goto free_data; data->nntp_max_articles = 0; data->nntp_mode_reader = FALSE; session->sess_data = data; return MAIL_NO_ERROR; free_data: free(data); free: newsnntp_free(nntp); err: return MAIL_ERROR_MEMORY; } static void nntpdriver_uninitialize(mailsession * session) { struct nntp_session_state_data * data; data = get_data(session); clist_foreach(data->nntp_subscribed_list, (clist_func) free, NULL); clist_free(data->nntp_subscribed_list); if (data->nntp_group_info != NULL) newsnntp_group_free(data->nntp_group_info); if (data->nntp_group_name != NULL) free(data->nntp_group_name); if (data->nntp_userid != NULL) free(data->nntp_userid); if (data->nntp_password != NULL) free(data->nntp_password); newsnntp_free(data->nntp_session); free(data); session->sess_data = NULL; } static int nntpdriver_parameters(mailsession * session, int id, void * value) { struct nntp_session_state_data * data; data = get_data(session); switch (id) { case NNTPDRIVER_SET_MAX_ARTICLES: { uint32_t * param; param = value; data->nntp_max_articles = * param; return MAIL_NO_ERROR; } } return MAIL_ERROR_INVAL; } static int add_to_list(mailsession * session, char * mb) { char * new_mb; int r; struct nntp_session_state_data * data; data = get_data(session); @@ -505,256 +509,262 @@ static int nntpdriver_list_folders(mailsession * session, char * mb, free_list: clist_foreach(list, (clist_func) free, NULL); clist_free(list); newsnntp_list_free(group_list); err: return res; } static int nntpdriver_lsub_folders(mailsession * session, char * mb, struct mail_list ** result) { clist * subscribed; clist * lsub_result; clistiter * cur; struct mail_list * lsub; size_t length; int res; int r; struct nntp_session_state_data * data; length = strlen(mb); data = get_data(session); subscribed = data->nntp_subscribed_list; lsub_result = clist_new(); if (lsub_result == NULL) { res = MAIL_ERROR_MEMORY; goto err; } for(cur = clist_begin(subscribed) ; cur != NULL ; cur = clist_next(cur)) { char * cur_mb; char * new_mb; cur_mb = clist_content(cur); if (strncmp(mb, cur_mb, length) == 0) { new_mb = strdup(cur_mb); if (new_mb == NULL) { res = MAIL_ERROR_MEMORY; goto free_list; } r = clist_append(lsub_result, new_mb); if (r < 0) { free(new_mb); res = MAIL_ERROR_MEMORY; goto free_list; } } } lsub = mail_list_new(lsub_result); if (lsub == NULL) { res = MAIL_ERROR_MEMORY; goto free_list; } * result = lsub; return MAIL_NO_ERROR; free_list: clist_foreach(lsub_result, (clist_func) free, NULL); clist_free(lsub_result); err: return res; } static int nntpdriver_subscribe_folder(mailsession * session, char * mb) { int r; r = add_to_list(session, mb); if (r < 0) return MAIL_ERROR_SUBSCRIBE; return MAIL_NO_ERROR; } static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb) { int r; r = remove_from_list(session, mb); if (r < 0) return MAIL_ERROR_UNSUBSCRIBE; return MAIL_NO_ERROR; } /* messages operations */ static int nntpdriver_append_message(mailsession * session, char * message, size_t size) { int r; struct nntp_session_state_data * data; data = get_data(session); do { r = newsnntp_post(get_nntp_session(session), message, size); switch (r) { case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: r = nntpdriver_authenticate_user(session); if (r != MAIL_NO_ERROR) return r; break; case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: r = nntpdriver_authenticate_password(session); if (r != MAIL_NO_ERROR) return r; break; default: return nntpdriver_nntp_error_to_mail_error(r); } } while (1); } +static int nntpdriver_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + return nntpdriver_append_message(session, message, size); +} + static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct mailimf_fields ** result); static int nntpdriver_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list) { newsnntp * nntp; int r; struct nntp_session_state_data * data; clist * list; int done; clistiter * cur; uint32_t first_seq; unsigned int i; nntp = get_nntp_session(session); data = get_data(session); if (data->nntp_group_info == NULL) return MAIL_ERROR_BAD_STATE; first_seq = data->nntp_group_info->grp_first; if (carray_count(env_list->msg_tab) > 0) { mailmessage * msg; msg = carray_get(env_list->msg_tab, 0); first_seq = msg->msg_index; } if (carray_count(env_list->msg_tab) > 0) { i = carray_count(env_list->msg_tab) - 1; while (1) { mailmessage * msg; msg = carray_get(env_list->msg_tab, i); if (msg->msg_fields != NULL) { first_seq = msg->msg_index + 1; break; } if (i == 0) break; i --; } } if (first_seq > data->nntp_group_info->grp_last) { list = NULL; } else { done = FALSE; do { r = newsnntp_xover_range(nntp, first_seq, data->nntp_group_info->grp_last, &list); switch (r) { case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: r = nntpdriver_authenticate_user(session); if (r != MAIL_NO_ERROR) return r; break; case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: r = nntpdriver_authenticate_password(session); if (r != MAIL_NO_ERROR) return r; break; case NEWSNNTP_NO_ERROR: done = TRUE; break; default: return nntpdriver_nntp_error_to_mail_error(r); } } while (!done); } #if 0 i = 0; j = 0; if (list != NULL) { for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { struct newsnntp_xover_resp_item * item; struct mailimf_fields * fields; item = clist_content(cur); while (i < carray_count(env_list->msg_tab)) { mailmessage * info; info = carray_get(env_list->msg_tab, i); if (item->ovr_article == info->msg_index) { if (info->fields == NULL) { r = xover_resp_to_fields(item, &fields); if (r == MAIL_NO_ERROR) { info->fields = fields; } info->size = item->ovr_size; carray_set(env_list->msg_tab, j, info); j ++; i ++; break; } else { carray_set(env_list->msg_tab, j, info); j ++; } } else { if (info->fields != NULL) { carray_set(env_list->msg_tab, j, info); j ++; } diff --git a/kmicromail/libetpan/generic/nntpdriver_cached.c b/kmicromail/libetpan/generic/nntpdriver_cached.c index 1f8a8af..0343a65 100644 --- a/kmicromail/libetpan/generic/nntpdriver_cached.c +++ b/kmicromail/libetpan/generic/nntpdriver_cached.c @@ -1,289 +1,293 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "nntpdriver_cached.h" #include "libetpan-config.h" #include <string.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include "mail_cache_db.h" #include "mail.h" #include "mailmessage.h" #include "maildriver_tools.h" #include "nntpdriver.h" #include "maildriver.h" #include "newsnntp.h" #include "generic_cache.h" #include "imfcache.h" #include "maillock.h" #include "nntpdriver_cached_message.h" #include "nntpdriver_tools.h" static int nntpdriver_cached_initialize(mailsession * session); static void nntpdriver_cached_uninitialize(mailsession * session); static int nntpdriver_cached_parameters(mailsession * session, int id, void * value); static int nntpdriver_cached_connect_stream(mailsession * session, mailstream * s); static int nntpdriver_cached_login(mailsession * session, char * userid, char * password); static int nntpdriver_cached_logout(mailsession * session); static int nntpdriver_cached_check_folder(mailsession * session); static int nntpdriver_cached_select_folder(mailsession * session, char * mb); static int nntpdriver_cached_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int nntpdriver_cached_messages_number(mailsession * session, char * mb, uint32_t * result); static int nntpdriver_cached_recent_number(mailsession * session, char * mb, uint32_t * result); static int nntpdriver_cached_unseen_number(mailsession * session, char * mb, uint32_t * result); static int nntpdriver_cached_append_message(mailsession * session, char * message, size_t size); +static int nntpdriver_cached_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); + static int nntpdriver_cached_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list); static int nntpdriver_cached_get_messages_list(mailsession * session, struct mailmessage_list ** result); static int nntpdriver_cached_list_folders(mailsession * session, char * mb, struct mail_list ** result); static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb, struct mail_list ** result); static int nntpdriver_cached_subscribe_folder(mailsession * session, char * mb); static int nntpdriver_cached_unsubscribe_folder(mailsession * session, char * mb); static int nntpdriver_cached_get_message(mailsession * session, uint32_t num, mailmessage ** result); static int nntpdriver_cached_noop(mailsession * session); static int nntpdriver_cached_get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result); static mailsession_driver local_nntp_cached_session_driver = { .sess_name = "nntp-cached", .sess_initialize = nntpdriver_cached_initialize, .sess_uninitialize = nntpdriver_cached_uninitialize, .sess_parameters = nntpdriver_cached_parameters, .sess_connect_stream = nntpdriver_cached_connect_stream, .sess_connect_path = NULL, .sess_starttls = NULL, .sess_login = nntpdriver_cached_login, .sess_logout = nntpdriver_cached_logout, .sess_noop = nntpdriver_cached_noop, .sess_build_folder_name = NULL, .sess_create_folder = NULL, .sess_delete_folder = NULL, .sess_rename_folder = NULL, .sess_check_folder = nntpdriver_cached_check_folder, .sess_examine_folder = NULL, .sess_select_folder = nntpdriver_cached_select_folder, .sess_expunge_folder = NULL, .sess_status_folder = nntpdriver_cached_status_folder, .sess_messages_number = nntpdriver_cached_messages_number, .sess_recent_number = nntpdriver_cached_recent_number, .sess_unseen_number = nntpdriver_cached_unseen_number, .sess_list_folders = nntpdriver_cached_list_folders, .sess_lsub_folders = nntpdriver_cached_lsub_folders, .sess_subscribe_folder = nntpdriver_cached_subscribe_folder, .sess_unsubscribe_folder = nntpdriver_cached_unsubscribe_folder, .sess_append_message = nntpdriver_cached_append_message, + .sess_append_message_flags = nntpdriver_cached_append_message_flags, .sess_copy_message = NULL, .sess_move_message = NULL, .sess_get_messages_list = nntpdriver_cached_get_messages_list, .sess_get_envelopes_list = nntpdriver_cached_get_envelopes_list, .sess_remove_message = NULL, #if 0 .sess_search_messages = maildriver_generic_search_messages, #endif .sess_get_message = nntpdriver_cached_get_message, .sess_get_message_by_uid = nntpdriver_cached_get_message_by_uid, }; mailsession_driver * nntp_cached_session_driver = &local_nntp_cached_session_driver; #define ENV_NAME "env.db" #define FLAGS_NAME "flags.db" static void read_article_seq(mailsession * session, uint32_t * pfirst, uint32_t * plast); static void write_article_seq(mailsession * session, uint32_t first, uint32_t last); static inline struct nntp_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)->nntp_ancestor; } static inline struct nntp_session_state_data * get_ancestor_data(mailsession * session) { return get_ancestor(session)->sess_data; } static inline newsnntp * get_nntp_session(mailsession * session) { return get_ancestor_data(session)->nntp_session; } static int nntpdriver_cached_initialize(mailsession * session) { struct nntp_cached_session_state_data * data; data = malloc(sizeof(* data)); if (data == NULL) goto err; data->nntp_flags_store = mail_flags_store_new(); if (data->nntp_flags_store == NULL) goto free; data->nntp_ancestor = mailsession_new(nntp_session_driver); if (data->nntp_ancestor == NULL) goto free_store; session->sess_data = data; return MAIL_NO_ERROR; free_store: mail_flags_store_free(data->nntp_flags_store); free: free(data); err: return MAIL_ERROR_MEMORY; } static int nntp_flags_store_process(char * flags_directory, char * group_name, 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 (group_name == NULL) return MAIL_NO_ERROR; snprintf(filename_flags, PATH_MAX, "%s/%s/%s", flags_directory, group_name, 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 = nntpdriver_write_cached_flags(cache_db_flags, mmapstr, msg->msg_index, msg->msg_flags); } 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: @@ -506,256 +510,262 @@ static int nntpdriver_cached_status_folder(mailsession * session, count ++; if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { recent ++; } if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { unseen ++; } mail_flags_free(flags); } } if ((count == 0) && (first != last)) { count = last - first + 1; recent = count; unseen = count; } additionnal = ancestor_data->nntp_group_info->grp_last - last; recent += additionnal; unseen += additionnal; mmap_string_free(mmapstr); mail_cache_db_close_unlock(filename_flags, cache_db_flags); * result_messages = count; * 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 nntpdriver_cached_messages_number(mailsession * session, char * mb, uint32_t * result) { uint32_t messages; uint32_t recent; uint32_t unseen; int r; r = nntpdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = messages; return MAIL_NO_ERROR; } static int nntpdriver_cached_recent_number(mailsession * session, char * mb, uint32_t * result) { uint32_t messages; uint32_t recent; uint32_t unseen; int r; r = nntpdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = recent; return MAIL_NO_ERROR; } static int nntpdriver_cached_unseen_number(mailsession * session, char * mb, uint32_t * result) { uint32_t messages; uint32_t recent; uint32_t unseen; int r; r = nntpdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = unseen; return MAIL_NO_ERROR; } static int nntpdriver_cached_list_folders(mailsession * session, char * mb, struct mail_list ** result) { return mailsession_list_folders(get_ancestor(session), mb, result); } static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb, struct mail_list ** result) { return mailsession_lsub_folders(get_ancestor(session), mb, result); } static int nntpdriver_cached_subscribe_folder(mailsession * session, char * mb) { return mailsession_subscribe_folder(get_ancestor(session), mb); } static int nntpdriver_cached_unsubscribe_folder(mailsession * session, char * mb) { return mailsession_unsubscribe_folder(get_ancestor(session), mb); } /* messages operations */ static int nntpdriver_cached_append_message(mailsession * session, char * message, size_t size) { return mailsession_append_message(get_ancestor(session), message, size); } +static int nntpdriver_cached_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + return nntpdriver_cached_append_message(session, message, size); +} + static int get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, mailsession * session, uint32_t num, struct mailimf_fields ** result) { char keyname[PATH_MAX]; int r; struct mailimf_fields * fields; int res; snprintf(keyname, PATH_MAX, "%i-envelope", num); 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; int res; char keyname[PATH_MAX]; snprintf(keyname, PATH_MAX, "%i-envelope", num); 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; } #define SEQ_FILENAME "articles-seq" static void read_article_seq(mailsession * session, uint32_t * pfirst, uint32_t * plast) { FILE * f; struct nntp_session_state_data * ancestor_data; uint32_t first; uint32_t last; char seq_filename[PATH_MAX]; struct nntp_cached_session_state_data * cached_data; int r; first = 0; last = 0; cached_data = get_cached_data(session); ancestor_data = get_ancestor_data(session); if (ancestor_data->nntp_group_name == NULL) return; snprintf(seq_filename, PATH_MAX, "%s/%s/%s", cached_data->nntp_cache_directory, ancestor_data->nntp_group_name, SEQ_FILENAME); f = fopen(seq_filename, "r"); if (f != NULL) { int fd; fd = fileno(f); r = maillock_read_lock(seq_filename, fd); if (r == 0) { MMAPString * mmapstr; size_t cur_token; char buf[sizeof(uint32_t) * 2]; size_t read_size; read_size = fread(buf, 1, sizeof(uint32_t) * 2, f); mmapstr = mmap_string_new_len(buf, read_size); if (mmapstr != NULL) { cur_token = 0; r = mailimf_cache_int_read(mmapstr, &cur_token, &first); r = mailimf_cache_int_read(mmapstr, &cur_token, &last); mmap_string_free(mmapstr); } maillock_read_unlock(seq_filename, fd); } fclose(f); } * pfirst = first; * plast = last; } static void write_article_seq(mailsession * session, uint32_t first, uint32_t last) { FILE * f; struct nntp_session_state_data * ancestor_data; char seq_filename[PATH_MAX]; struct nntp_cached_session_state_data * cached_data; int r; int fd; cached_data = get_cached_data(session); ancestor_data = get_ancestor_data(session); if (ancestor_data->nntp_group_name == NULL) return; snprintf(seq_filename, PATH_MAX, "%s/%s/%s", cached_data->nntp_cache_directory, ancestor_data->nntp_group_name, SEQ_FILENAME); diff --git a/kmicromail/libetpan/generic/nntpstorage.c b/kmicromail/libetpan/generic/nntpstorage.c index 5ba333b..89974cd 100644 --- a/kmicromail/libetpan/generic/nntpstorage.c +++ b/kmicromail/libetpan/generic/nntpstorage.c @@ -1,202 +1,202 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "nntpstorage.h" #include <stdlib.h> #include <string.h> #include "maildriver.h" #include "nntpdriver.h" #include "nntpdriver_cached.h" #include "mailstorage_tools.h" #include "mail.h" /* nntp storage */ #define NNTP_DEFAULT_PORT 119 #define NNTPS_DEFAULT_PORT 563 static int nntp_mailstorage_connect(struct mailstorage * storage); static int nntp_mailstorage_get_folder_session(struct mailstorage * storage, char * pathname, mailsession ** result); static void nntp_mailstorage_uninitialize(struct mailstorage * storage); static mailstorage_driver nntp_mailstorage_driver = { .sto_name = "nntp", .sto_connect = nntp_mailstorage_connect, .sto_get_folder_session = nntp_mailstorage_get_folder_session, .sto_uninitialize = nntp_mailstorage_uninitialize, }; int nntp_mailstorage_init(struct mailstorage * storage, char * nn_servername, uint16_t nn_port, char * nn_command, int nn_connection_type, int nn_auth_type, char * nn_login, char * nn_password, int nn_cached, char * nn_cache_directory, char * nn_flags_directory) { struct nntp_mailstorage * nntp_storage; int res; - nntp_storage = malloc(sizeof(struct nntp_mailstorage)); + nntp_storage = malloc(sizeof(* nntp_storage)); if (nntp_storage == NULL) { res = MAIL_ERROR_MEMORY; goto err; } nntp_storage->nntp_servername = strdup(nn_servername); if (nntp_storage->nntp_servername == NULL) { res = MAIL_ERROR_MEMORY; goto free; } nntp_storage->nntp_connection_type = nn_connection_type; if (nn_port == 0) { switch (nn_connection_type) { case CONNECTION_TYPE_PLAIN: case CONNECTION_TYPE_COMMAND: nn_port = NNTP_DEFAULT_PORT; break; case CONNECTION_TYPE_TLS: case CONNECTION_TYPE_COMMAND_TLS: nn_port = NNTPS_DEFAULT_PORT; break; default: res = MAIL_ERROR_INVAL; goto free_servername; } } nntp_storage->nntp_port = nn_port; if (nn_command != NULL) { nntp_storage->nntp_command = strdup(nn_command); if (nntp_storage->nntp_command == NULL) { res = MAIL_ERROR_MEMORY; goto free_servername; } } else nntp_storage->nntp_command = NULL; nntp_storage->nntp_auth_type = nn_auth_type; if (nn_login != NULL) { nntp_storage->nntp_login = strdup(nn_login); if (nntp_storage->nntp_login == NULL) { res = MAIL_ERROR_MEMORY; goto free_command; } } else nntp_storage->nntp_login = NULL; if (nn_password != NULL) { nntp_storage->nntp_password = strdup(nn_password); if (nntp_storage->nntp_password == NULL) { res = MAIL_ERROR_MEMORY; goto free_login; } } else nntp_storage->nntp_password = NULL; nntp_storage->nntp_cached = nn_cached; if (nn_cached && (nn_cache_directory != NULL) && (nn_flags_directory != NULL)) { nntp_storage->nntp_cache_directory = strdup(nn_cache_directory); if (nntp_storage->nntp_cache_directory == NULL) { res = MAIL_ERROR_MEMORY; goto free_password; } nntp_storage->nntp_flags_directory = strdup(nn_flags_directory); if (nntp_storage->nntp_flags_directory == NULL) { res = MAIL_ERROR_MEMORY; goto free_cache_directory; } } else { nntp_storage->nntp_cached = FALSE; nntp_storage->nntp_cache_directory = NULL; nntp_storage->nntp_flags_directory = NULL; } storage->sto_data = nntp_storage; storage->sto_driver = &nntp_mailstorage_driver; return MAIL_NO_ERROR; free_cache_directory: free(nntp_storage->nntp_cache_directory); free_password: free(nntp_storage->nntp_password); free_login: free(nntp_storage->nntp_login); free_command: free(nn_command); free_servername: free(nntp_storage->nntp_servername); free: free(nntp_storage); err: return res; } static void nntp_mailstorage_uninitialize(struct mailstorage * storage) { struct nntp_mailstorage * nntp_storage; nntp_storage = storage->sto_data; if (nntp_storage->nntp_flags_directory != NULL) free(nntp_storage->nntp_flags_directory); if (nntp_storage->nntp_cache_directory != NULL) free(nntp_storage->nntp_cache_directory); if (nntp_storage->nntp_password != NULL) free(nntp_storage->nntp_password); if (nntp_storage->nntp_login != NULL) free(nntp_storage->nntp_login); if (nntp_storage->nntp_command != NULL) free(nntp_storage->nntp_command); free(nntp_storage->nntp_servername); free(nntp_storage); storage->sto_data = NULL; } diff --git a/kmicromail/libetpan/generic/pop3driver.c b/kmicromail/libetpan/generic/pop3driver.c index 20b0fc2..375879e 100644 --- a/kmicromail/libetpan/generic/pop3driver.c +++ b/kmicromail/libetpan/generic/pop3driver.c @@ -1,239 +1,240 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "pop3driver.h" #include <string.h> #include <stdlib.h> #include "pop3driver_message.h" #include "maildriver_tools.h" #include "pop3driver_tools.h" #include "mailmessage.h" static int pop3driver_initialize(mailsession * session); static void pop3driver_uninitialize(mailsession * session); static int pop3driver_parameters(mailsession * session, int id, void * value); static int pop3driver_connect_stream(mailsession * session, mailstream * s); static int pop3driver_starttls(mailsession * session); static int pop3driver_login(mailsession * session, char * userid, char * password); static int pop3driver_logout(mailsession * session); static int pop3driver_noop(mailsession * session); static int pop3driver_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int pop3driver_messages_number(mailsession * session, char * mb, uint32_t * result); static int pop3driver_remove_message(mailsession * session, uint32_t num); static int pop3driver_get_messages_list(mailsession * session, struct mailmessage_list ** result); static int pop3driver_get_message(mailsession * session, uint32_t num, mailmessage ** result); static mailsession_driver local_pop3_session_driver = { .sess_name = "pop3", .sess_initialize = pop3driver_initialize, .sess_uninitialize = pop3driver_uninitialize, .sess_parameters = pop3driver_parameters, .sess_connect_stream = pop3driver_connect_stream, .sess_connect_path = NULL, .sess_starttls = pop3driver_starttls, .sess_login = pop3driver_login, .sess_logout = pop3driver_logout, .sess_noop = pop3driver_noop, .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 = NULL, .sess_status_folder = pop3driver_status_folder, .sess_messages_number = pop3driver_messages_number, .sess_recent_number = pop3driver_messages_number, .sess_unseen_number = pop3driver_messages_number, .sess_list_folders = NULL, .sess_lsub_folders = NULL, .sess_subscribe_folder = NULL, .sess_unsubscribe_folder = NULL, .sess_append_message = NULL, + .sess_append_message_flags = NULL, .sess_copy_message = NULL, .sess_move_message = NULL, .sess_get_messages_list = pop3driver_get_messages_list, .sess_get_envelopes_list = maildriver_generic_get_envelopes_list, .sess_remove_message = pop3driver_remove_message, #if 0 .sess_search_messages = maildriver_generic_search_messages, #endif .sess_get_message = pop3driver_get_message, .sess_get_message_by_uid = NULL, }; mailsession_driver * pop3_session_driver = &local_pop3_session_driver; static inline struct pop3_session_state_data * get_data(mailsession * session) { return session->sess_data; } static mailpop3 * get_pop3_session(mailsession * session) { return get_data(session)->pop3_session; } static int pop3driver_initialize(mailsession * session) { struct pop3_session_state_data * data; mailpop3 * pop3; pop3 = mailpop3_new(0, NULL); if (session == NULL) goto err; data = malloc(sizeof(* data)); if (data == NULL) goto free; data->pop3_session = pop3; data->pop3_auth_type = POP3DRIVER_AUTH_TYPE_PLAIN; session->sess_data = data; return MAIL_NO_ERROR; free: mailpop3_free(pop3); err: return MAIL_ERROR_MEMORY; } static void pop3driver_uninitialize(mailsession * session) { struct pop3_session_state_data * data; data = get_data(session); mailpop3_free(data->pop3_session); free(data); session->sess_data = data; } static int pop3driver_connect_stream(mailsession * session, mailstream * s) { int r; r = mailpop3_connect(get_pop3_session(session), s); switch (r) { case MAILPOP3_NO_ERROR: return MAIL_NO_ERROR_NON_AUTHENTICATED; default: return pop3driver_pop3_error_to_mail_error(r); } } static int pop3driver_starttls(mailsession * session) { int r; int fd; mailstream_low * low; mailstream_low * new_low; mailpop3 * pop3; pop3 = get_pop3_session(session); r = mailpop3_stls(pop3); switch (r) { case MAILPOP3_NO_ERROR: break; default: return pop3driver_pop3_error_to_mail_error(r); } low = mailstream_get_low(pop3->pop3_stream); fd = mailstream_low_get_fd(low); if (fd == -1) return MAIL_ERROR_STREAM; new_low = mailstream_low_ssl_open(fd); if (new_low == NULL) return MAIL_ERROR_STREAM; mailstream_low_free(low); mailstream_set_low(pop3->pop3_stream, new_low); return MAIL_NO_ERROR; } static int pop3driver_parameters(mailsession * session, int id, void * value) { struct pop3_session_state_data * data; data = get_data(session); switch (id) { case POP3DRIVER_SET_AUTH_TYPE: { int * param; param = value; data->pop3_auth_type = * param; diff --git a/kmicromail/libetpan/generic/pop3driver_cached.c b/kmicromail/libetpan/generic/pop3driver_cached.c index 6f97303..24f624b 100644 --- a/kmicromail/libetpan/generic/pop3driver_cached.c +++ b/kmicromail/libetpan/generic/pop3driver_cached.c @@ -1,285 +1,289 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "pop3driver_cached.h" #include "libetpan-config.h" #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include "mail.h" #include "mail_cache_db.h" #include "maildriver.h" #include "mailmessage.h" #include "pop3driver.h" #include "mailpop3.h" #include "generic_cache.h" #include "imfcache.h" #include "pop3driver_cached_message.h" #include "pop3driver_tools.h" #include "maildriver_tools.h" static int pop3driver_cached_initialize(mailsession * session); static void pop3driver_cached_uninitialize(mailsession * session); static int pop3driver_cached_parameters(mailsession * session, int id, void * value); static int pop3driver_cached_connect_stream(mailsession * session, mailstream * s); static int pop3driver_cached_starttls(mailsession * session); static int pop3driver_cached_login(mailsession * session, char * userid, char * password); static int pop3driver_cached_logout(mailsession * session); static int pop3driver_cached_check_folder(mailsession * session); static int pop3driver_cached_noop(mailsession * session); static int pop3driver_cached_expunge_folder(mailsession * session); static int pop3driver_cached_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int pop3driver_cached_messages_number(mailsession * session, char * mb, uint32_t * result); static int pop3driver_cached_recent_number(mailsession * session, char * mb, uint32_t * result); static int pop3driver_cached_unseen_number(mailsession * session, char * mb, uint32_t * result); static int pop3driver_cached_remove_message(mailsession * session, uint32_t num); static int pop3driver_cached_get_messages_list(mailsession * session, struct mailmessage_list ** result); static int pop3driver_cached_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list); static int pop3driver_cached_get_message(mailsession * session, uint32_t num, mailmessage ** result); +static int pop3driver_cached_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + static mailsession_driver local_pop3_cached_session_driver = { .sess_name = "pop3-cached", .sess_initialize = pop3driver_cached_initialize, .sess_uninitialize = pop3driver_cached_uninitialize, .sess_parameters = pop3driver_cached_parameters, .sess_connect_stream = pop3driver_cached_connect_stream, .sess_connect_path = NULL, .sess_starttls = pop3driver_cached_starttls, .sess_login = pop3driver_cached_login, .sess_logout = pop3driver_cached_logout, .sess_noop = pop3driver_cached_noop, .sess_build_folder_name = NULL, .sess_create_folder = NULL, .sess_delete_folder = NULL, .sess_rename_folder = NULL, .sess_check_folder = pop3driver_cached_check_folder, .sess_examine_folder = NULL, .sess_select_folder = NULL, .sess_expunge_folder = pop3driver_cached_expunge_folder, .sess_status_folder = pop3driver_cached_status_folder, .sess_messages_number = pop3driver_cached_messages_number, .sess_recent_number = pop3driver_cached_recent_number, .sess_unseen_number = pop3driver_cached_unseen_number, .sess_list_folders = NULL, .sess_lsub_folders = NULL, .sess_subscribe_folder = NULL, .sess_unsubscribe_folder = NULL, .sess_append_message = NULL, + .sess_append_message_flags = NULL, .sess_copy_message = NULL, .sess_move_message = NULL, .sess_get_messages_list = pop3driver_cached_get_messages_list, .sess_get_envelopes_list = pop3driver_cached_get_envelopes_list, .sess_remove_message = pop3driver_cached_remove_message, #if 0 .sess_search_messages = maildriver_generic_search_messages, #endif .sess_get_message = pop3driver_cached_get_message, - .sess_get_message_by_uid = NULL, + .sess_get_message_by_uid = pop3driver_cached_get_message_by_uid, }; mailsession_driver * pop3_cached_session_driver = &local_pop3_cached_session_driver; #define ENV_NAME "env.db" #define FLAGS_NAME "flags.db" static inline struct pop3_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)->pop3_ancestor; } static inline struct pop3_session_state_data * get_ancestor_data(mailsession * session) { return get_ancestor(session)->sess_data; } static inline mailpop3 * get_pop3_session(mailsession * session) { return get_ancestor_data(session)->pop3_session; } static int pop3driver_cached_initialize(mailsession * session) { struct pop3_cached_session_state_data * data; data = malloc(sizeof(* data)); if (data == NULL) goto err; data->pop3_flags_store = mail_flags_store_new(); if (data->pop3_flags_store == NULL) goto free_data; data->pop3_ancestor = mailsession_new(pop3_session_driver); if (data->pop3_ancestor == NULL) goto free_store; data->pop3_flags_hash = chash_new(128, CHASH_COPYNONE); if (data->pop3_flags_hash == NULL) goto free_session; session->sess_data = data; return MAIL_NO_ERROR; free_session: mailsession_free(data->pop3_ancestor); free_store: mail_flags_store_free(data->pop3_flags_store); free_data: free(data); err: return MAIL_ERROR_MEMORY; } static int pop3_flags_store_process(char * flags_directory, 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; snprintf(filename_flags, PATH_MAX, "%s/%s", flags_directory, 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 = pop3driver_write_cached_flags(cache_db_flags, mmapstr, msg->msg_uid, msg->msg_flags); } 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 pop3driver_cached_uninitialize(mailsession * session) { struct pop3_cached_session_state_data * data; data = get_cached_data(session); pop3_flags_store_process(data->pop3_flags_directory, data->pop3_flags_store); mail_flags_store_free(data->pop3_flags_store); chash_free(data->pop3_flags_hash); mailsession_free(data->pop3_ancestor); @@ -730,128 +734,166 @@ pop3driver_cached_get_envelopes_list(mailsession * session, if (r < 0) { res = MAIL_ERROR_MEMORY; 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 = pop3driver_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 = maildriver_generic_get_envelopes_list(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_MEMORY; 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) { r = write_cached_envelope(cache_db_env, mmapstr, session, msg->msg_index, msg->msg_fields); } } if (msg->msg_flags != NULL) { r = pop3driver_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); /* remove cache files */ maildriver_message_cache_clean_up(cached_data->pop3_cache_directory, env_list, get_uid_from_filename); 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 pop3driver_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, pop3_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 pop3driver_cached_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + mailpop3 * pop3; + struct mailpop3_msg_info * msg_info; + int found; + unsigned int i; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + pop3 = get_pop3_session(session); + + found = 0; + + /* iterate all messages and look for uid */ + for(i = 0 ; i < carray_count(pop3->pop3_msg_tab) ; i++) { + msg_info = carray_get(pop3->pop3_msg_tab, i); + + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + /* uid found, stop looking */ + if (strcmp(msg_info->msg_uidl, uid) == 0) { + found = 1; + break; + } + } + + if (!found) + return MAIL_ERROR_MSG_NOT_FOUND; + + return pop3driver_cached_get_message(session, msg_info->msg_index, result); +} diff --git a/kmicromail/libetpan/generic/pop3driver_message.c b/kmicromail/libetpan/generic/pop3driver_message.c index 77bd94c..357bb2e 100644 --- a/kmicromail/libetpan/generic/pop3driver_message.c +++ b/kmicromail/libetpan/generic/pop3driver_message.c @@ -1,159 +1,193 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "pop3driver_message.h" #include "mailmessage_tools.h" #include "pop3driver_tools.h" #include "pop3driver.h" #include "mailpop3.h" +#include <stdlib.h> +#include <string.h> static int pop3_prefetch(mailmessage * msg_info); static void pop3_prefetch_free(struct generic_message_t * msg); static int pop3_initialize(mailmessage * msg_info); static int pop3_fetch_header(mailmessage * msg_info, char ** result, size_t * result_len); static int pop3_fetch_size(mailmessage * msg_info, size_t * result); static mailmessage_driver local_pop3_message_driver = { .msg_name = "pop3", .msg_initialize = pop3_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 = pop3_fetch_header, .msg_fetch_body = mailmessage_generic_fetch_body, .msg_fetch_size = pop3_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 * pop3_message_driver = &local_pop3_message_driver; +static inline struct pop3_session_state_data * +get_data(mailsession * session) +{ + return session->sess_data; +} + + +static mailpop3 * get_pop3_session(mailsession * session) +{ + return get_data(session)->pop3_session; +} + static int pop3_prefetch(mailmessage * msg_info) { char * msg_content; size_t msg_length; struct generic_message_t * msg; int r; r = pop3driver_retr(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 pop3_prefetch_free(struct generic_message_t * msg) { if (msg->msg_message != NULL) { mmap_string_unref(msg->msg_message); msg->msg_message = NULL; } } static int pop3_initialize(mailmessage * msg_info) { struct generic_message_t * msg; int r; + char * uid; + struct mailpop3_msg_info * info; + mailpop3 * pop3; + + pop3 = get_pop3_session(msg_info->msg_session); + + r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info); + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + uid = strdup(info->msg_uidl); + if (uid == NULL) + return MAIL_ERROR_MEMORY; r = mailmessage_generic_initialize(msg_info); - if (r != MAIL_NO_ERROR) + if (r != MAIL_NO_ERROR) { + free(uid); return r; + } msg = msg_info->msg_data; msg->msg_prefetch = pop3_prefetch; msg->msg_prefetch_free = pop3_prefetch_free; + msg_info->msg_uid = uid; return MAIL_NO_ERROR; } static int pop3_fetch_header(mailmessage * msg_info, char ** result, size_t * result_len) { struct generic_message_t * msg; char * headers; size_t headers_length; int r; msg = msg_info->msg_data; if (msg->msg_message != NULL) return mailmessage_generic_fetch_header(msg_info, result, result_len); r = pop3driver_header(msg_info->msg_session, msg_info->msg_index, &headers, &headers_length); if (r != MAIL_NO_ERROR) return r; * result = headers; * result_len = headers_length; return MAIL_NO_ERROR; } static int pop3_fetch_size(mailmessage * msg_info, size_t * result) { return pop3driver_size(msg_info->msg_session, msg_info->msg_index, result); } diff --git a/kmicromail/libetpan/generic/pop3storage.c b/kmicromail/libetpan/generic/pop3storage.c index 8e7a94e..375aeaf 100644 --- a/kmicromail/libetpan/generic/pop3storage.c +++ b/kmicromail/libetpan/generic/pop3storage.c @@ -1,199 +1,199 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "pop3storage.h" #include <stdlib.h> #include <string.h> #include "mail.h" #include "mailstorage_tools.h" #include "maildriver.h" /* pop3 storage */ #define POP3_DEFAULT_PORT 110 #define POP3S_DEFAULT_PORT 995 static int pop3_mailstorage_connect(struct mailstorage * storage); static int pop3_mailstorage_get_folder_session(struct mailstorage * storage, char * pathname, mailsession ** result); static void pop3_mailstorage_uninitialize(struct mailstorage * storage); static mailstorage_driver pop3_mailstorage_driver = { .sto_name = "pop3", .sto_connect = pop3_mailstorage_connect, .sto_get_folder_session = pop3_mailstorage_get_folder_session, .sto_uninitialize = pop3_mailstorage_uninitialize, }; int pop3_mailstorage_init(struct mailstorage * storage, char * pop3_servername, uint16_t pop3_port, char * pop3_command, int pop3_connection_type, int pop3_auth_type, char * pop3_login, char * pop3_password, int pop3_cached, char * pop3_cache_directory, char * pop3_flags_directory) { struct pop3_mailstorage * pop3_storage; - pop3_storage = malloc(sizeof(struct pop3_mailstorage)); + pop3_storage = malloc(sizeof(* pop3_storage)); if (pop3_storage == NULL) goto err; pop3_storage->pop3_servername = strdup(pop3_servername); if (pop3_storage->pop3_servername == NULL) goto free; pop3_storage->pop3_connection_type = pop3_connection_type; if (pop3_port == 0) { switch (pop3_connection_type) { case CONNECTION_TYPE_PLAIN: case CONNECTION_TYPE_TRY_STARTTLS: case CONNECTION_TYPE_STARTTLS: case CONNECTION_TYPE_COMMAND: case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: case CONNECTION_TYPE_COMMAND_STARTTLS: pop3_port = POP3_DEFAULT_PORT; break; case CONNECTION_TYPE_TLS: case CONNECTION_TYPE_COMMAND_TLS: pop3_port = POP3S_DEFAULT_PORT; break; } } pop3_storage->pop3_port = pop3_port; if (pop3_command != NULL) { pop3_storage->pop3_command = strdup(pop3_command); if (pop3_storage->pop3_command == NULL) goto free_servername; } else pop3_storage->pop3_command = NULL; pop3_storage->pop3_auth_type = pop3_auth_type; if (pop3_login != NULL) { pop3_storage->pop3_login = strdup(pop3_login); if (pop3_storage->pop3_login == NULL) goto free_command; } else pop3_storage->pop3_login = NULL; if (pop3_password != NULL) { pop3_storage->pop3_password = strdup(pop3_password); if (pop3_storage->pop3_password == NULL) goto free_login; } else pop3_storage->pop3_password = NULL; pop3_storage->pop3_cached = pop3_cached; if (pop3_cached && (pop3_cache_directory != NULL) && (pop3_flags_directory != NULL)) { pop3_storage->pop3_cache_directory = strdup(pop3_cache_directory); if (pop3_storage->pop3_cache_directory == NULL) goto free_password; pop3_storage->pop3_flags_directory = strdup(pop3_flags_directory); if (pop3_storage->pop3_flags_directory == NULL) goto free_cache_directory; } else { pop3_storage->pop3_cached = FALSE; pop3_storage->pop3_cache_directory = NULL; pop3_storage->pop3_flags_directory = NULL; } storage->sto_data = pop3_storage; storage->sto_driver = &pop3_mailstorage_driver; return MAIL_NO_ERROR; free_cache_directory: free(pop3_storage->pop3_cache_directory); free_password: if (pop3_storage->pop3_password != NULL) free(pop3_storage->pop3_password); free_login: if (pop3_storage->pop3_login != NULL) free(pop3_storage->pop3_login); free_command: if (pop3_storage->pop3_command != NULL) free(pop3_storage->pop3_command); free_servername: if (pop3_storage->pop3_servername != NULL) free(pop3_storage->pop3_servername); free: free(pop3_storage); err: return MAIL_ERROR_MEMORY; } static void pop3_mailstorage_uninitialize(struct mailstorage * storage) { struct pop3_mailstorage * pop3_storage; pop3_storage = storage->sto_data; if (pop3_storage->pop3_flags_directory != NULL) free(pop3_storage->pop3_flags_directory); if (pop3_storage->pop3_cache_directory != NULL) free(pop3_storage->pop3_cache_directory); if (pop3_storage->pop3_password != NULL) free(pop3_storage->pop3_password); if (pop3_storage->pop3_login != NULL) free(pop3_storage->pop3_login); if (pop3_storage->pop3_command != NULL) free(pop3_storage->pop3_command); free(pop3_storage->pop3_servername); free(pop3_storage); storage->sto_data = pop3_storage; } static int pop3_mailstorage_connect(struct mailstorage * storage) { struct pop3_mailstorage * pop3_storage; mailsession_driver * driver; int r; int res; mailsession * session; int auth_type; |