From e3b89230f065c48c84b48c88edb6eb088374c487 Mon Sep 17 00:00:00 2001 From: zautrix Date: Sat, 03 Jul 2004 16:33:12 +0000 Subject: Initial revision --- (limited to 'kmicromail/libetpan/generic/imapdriver_cached.c') diff --git a/kmicromail/libetpan/generic/imapdriver_cached.c b/kmicromail/libetpan/generic/imapdriver_cached.c new file mode 100644 index 0000000..e6af8e8 --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver_cached.c @@ -0,0 +1,1274 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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_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_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; + + err: + return res; +} + +static void check_for_uid_cache(mailsession * session) +{ +#if 0 + mailsession * imap; +#endif + mailimap * imap; +#if 0 + struct imap_session_state_data * imap_data; +#endif + clist * list; + clistiter * cur; + struct imap_cached_session_state_data * data; + unsigned int i; + unsigned dest; + + data = get_cached_data(session); +#if 0 + imap = get_ancestor(session); + + imap_data = imap->data; +#endif + + imap = get_imap_session(session); + + if (imap->imap_response_info == NULL) + return; + + list = imap->imap_response_info->rsp_expunged; + if (list == NULL) + return; + + dest = 0; + i = 0; + /* remove expunged */ + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + uint32_t expunged; + + expunged = * (uint32_t *) clist_content(cur); + + while (i < carray_count(data->imap_uid_list)) { + struct uid_cache_item * cache_item; + + if (dest + 1 == expunged) { + cache_item = carray_get(data->imap_uid_list, i); + free(cache_item); + i ++; + break; + } + else { + cache_item = carray_get(data->imap_uid_list, i); + carray_set(data->imap_uid_list, dest, cache_item); + i ++; + dest ++; + } + } + } + /* complete list */ + while (i < carray_count(data->imap_uid_list)) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + carray_set(data->imap_uid_list, dest, cache_item); + i ++; + dest ++; + } + carray_set_size(data->imap_uid_list, dest); +} + +static void imapdriver_cached_uninitialize(mailsession * session) +{ + struct imap_cached_session_state_data * data; + unsigned int i; + + data = get_cached_data(session); + + 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); + } + carray_free(data->imap_uid_list); + free_quoted_mb(data); + mailsession_free(data->imap_ancestor); + free(data); + + session->sess_data = NULL; +} + + +static int imapdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct imap_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->imap_cache_directory, value, PATH_MAX); + data->imap_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->imap_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + } + + return MAIL_ERROR_INVAL; +} + + +static int imapdriver_cached_connect_stream(mailsession * session, + mailstream * s) +{ + int r; + + check_for_uid_cache(session); + + r = mailsession_connect_stream(get_ancestor(session), s); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_starttls(mailsession * session) +{ + int r; + + r = mailsession_starttls(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_login(mailsession * session, + char * userid, char * password) +{ + int r; + + r = mailsession_login(get_ancestor(session), userid, password); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_logout(mailsession * session) +{ + int r; + + r = mailsession_logout(get_ancestor(session)); + + check_for_uid_cache(session); + + if (r == MAIL_NO_ERROR) { + struct imap_cached_session_state_data * imap_cached_data; + + imap_cached_data = get_cached_data(session); + + free_quoted_mb(imap_cached_data); + } + + return r; +} + +static int imapdriver_cached_noop(mailsession * session) +{ + int r; + + r = mailsession_noop(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_build_folder_name(mailsession * session, + char * mb, + char * name, char ** result) +{ + int r; + + r = mailsession_build_folder_name(get_ancestor(session), mb, + name, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_create_folder(mailsession * session, char * mb) +{ + int r; + + r = mailsession_create_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_delete_folder(mailsession * session, char * mb) +{ + int r; + + r = mailsession_delete_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_rename_folder(mailsession * session, char * mb, + char * new_name) +{ + int r; + + r = mailsession_rename_folder(get_ancestor(session), mb, new_name); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_check_folder(mailsession * session) +{ + int r; + + r = mailsession_check_folder(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_examine_folder(mailsession * session, + char * mb) +{ + int r; + + r = mailsession_examine_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int get_cache_folder(mailsession * session, char ** result) +{ +#if 0 + mailsession * imap_session; +#endif + mailimap * imap; + char * mb; + char * cache_dir; + char * dirname; + char * quoted_mb; + int res; + int r; + char key[PATH_MAX]; +#if 0 + struct imap_session_state_data * imap_data; + struct imap_cached_session_state_data * cached_data; +#endif + +#if 0 + imap_session = get_ancestor(session); + imap_data = imap_session->data; + imap = imap_data->session; +#endif + imap = get_imap_session(session); + + mb = get_ancestor_data(session)->imap_mailbox; + + cache_dir = get_cached_data(session)->imap_cache_directory; + + if (imap->imap_state != MAILIMAP_STATE_SELECTED) + return MAIL_ERROR_BAD_STATE; + + if (imap->imap_selection_info == NULL) + return MAIL_ERROR_BAD_STATE; + + quoted_mb = maildriver_quote_mailbox(mb); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key, PATH_MAX, "%s/%s", cache_dir, quoted_mb); + + dirname = strdup(key); + if (dirname == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mb; + } + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_dirname; + } + + free(quoted_mb); + + * result = dirname; + + return MAIL_NO_ERROR; + + free_dirname: + free(dirname); + free_mb: + free(quoted_mb); + err: + return res; +} + +static int imapdriver_cached_select_folder(mailsession * session, char * mb) +{ + int r; + char * quoted_mb; + struct imap_cached_session_state_data * data; + mailsession * imap; + char * old_mb; + + imap = get_ancestor(session); + + old_mb = get_ancestor_data(session)->imap_mailbox; + if (old_mb != NULL) + if (strcmp(mb, old_mb) == 0) + return MAIL_NO_ERROR; + + r = mailsession_select_folder(get_ancestor(session), mb); + if (r != MAIL_NO_ERROR) + return r; + + check_for_uid_cache(session); + + r = get_cache_folder(session, "ed_mb); + if (r != MAIL_NO_ERROR) + return r; + + data = get_cached_data(session); + if (data->imap_quoted_mb != NULL) + free(data->imap_quoted_mb); + data->imap_quoted_mb = quoted_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_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); + carray_set(tab, carray_count(data->imap_uid_list) + i, msg); + } + + /* replace list of messages in env_list */ + carray_free(env_list->msg_tab); + env_list->msg_tab = tab; + + r = update_uid_cache(session, env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } +#endif + + * result = env_list; + + return MAIL_NO_ERROR; + + free: + mailmessage_list_free(env_list); + err: + return res; +} + +static int get_flags_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; + clist * msg_list; +#if 0 + struct imap_session_state_data * data; +#endif + unsigned i; + unsigned dest; + +#if 0 + data = session->data; +#endif + + 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 = maildriver_env_list_to_msg_list_no_flags(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 */ + + clist_free(msg_list); + mailimap_fetch_type_free(fetch_type); + 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) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + r = imap_fetch_result_to_envelop_list(fetch_result, env_list); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + /* remove messages that don't have flags */ + i = 0; + dest = 0; + while (i < carray_count(env_list->msg_tab)) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg->msg_flags != NULL) { + carray_set(env_list->msg_tab, dest, msg); + dest ++; + } + else { + mailmessage_free(msg); + } + i ++; + } + carray_set_size(env_list->msg_tab, dest); + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + err: + return res; +} + + +#define ENV_NAME "env.db" + +static void get_uid_from_filename(char * filename) +{ + char * p; + + p = strstr(filename, "-part"); + if (p != NULL) + * p = 0; + p = strstr(filename, "-envelope"); + if (p != NULL) + * p = 0; + p = strstr(filename, "-rfc822"); + if (p != NULL) + * p = 0; +} + +static int +imapdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + int res; + uint32_t i; + struct imap_cached_session_state_data * data; + MMAPString * mmapstr; + struct mail_cache_db * cache_db; + char filename[PATH_MAX]; + + data = get_cached_data(session); + if (data->imap_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = imapdriver_get_cached_envelope(cache_db, mmapstr, + session, msg, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + } + + mail_cache_db_close_unlock(filename, cache_db); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + check_for_uid_cache(session); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = get_flags_list(session, env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + +#ifdef CACHE_MESSAGE_LIST + r = update_uid_cache(session, env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } +#endif + + /* must write cache */ + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + 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 = imapdriver_write_cached_envelope(cache_db, mmapstr, + session, msg, msg->msg_fields); + } + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db, NULL, env_list); + + mail_cache_db_close_unlock(filename, cache_db); + mmap_string_free(mmapstr); + + /* remove cache files */ + + maildriver_message_cache_clean_up(data->imap_quoted_mb, env_list, + get_uid_from_filename); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int imapdriver_cached_remove_message(mailsession * session, + uint32_t num) +{ + int r; + + r = mailsession_remove_message(get_ancestor(session), num); + + check_for_uid_cache(session); + + return r; +} + +#if 0 +static int imapdriver_cached_search_messages(mailsession * session, + char * charset, + struct mail_search_key * key, + struct mail_search_result ** + result) +{ + int r; + + r = mailsession_search_messages(get_ancestor(session), charset, key, result); + + check_for_uid_cache(session); + + return r; +} +#endif + +static int imapdriver_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, imap_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +/* Retrieve a message by UID + * libEtPan! uid format for IMAP is "UIDVALIDITY-UID" + * where UIDVALIDITY and UID are decimal representation of + * respectively uidvalidity and uid numbers. + * Return value: + * MAIL_ERROR_INVAL if uid is NULL or has an incorrect format. + * MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found + * MAIL_NO_ERROR if message was found. Result is in result + */ +static int imapdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t uidvalidity; + uint32_t num; + char * p1, * p2; + mailimap *imap; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + uidvalidity = strtoul(uid, &p1, 10); + if (p1 == uid || * p1 != '-') + return MAIL_ERROR_INVAL; + + p1++; + num = strtoul(p1, &p2, 10); + if (p2 == p1 || * p2 != '\0') + return MAIL_ERROR_INVAL; + + imap = get_imap_session(session); + if (imap->imap_selection_info->sel_uidvalidity != uidvalidity) + return MAIL_ERROR_MSG_NOT_FOUND; + + return imapdriver_cached_get_message(session, num, result); +} -- cgit v0.9.0.2