summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/imap
Side-by-side diff
Diffstat (limited to 'libetpan/src/driver/implementation/imap') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver.c1226
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached.c1370
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached_message.c664
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_message.c1239
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_tools.c3623
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_tools.h116
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_types.h144
-rw-r--r--libetpan/src/driver/implementation/imap/imapstorage.c297
-rw-r--r--libetpan/src/driver/implementation/imap/imapstorage.h90
13 files changed, 8977 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/imap/imapdriver.c b/libetpan/src/driver/implementation/imap/imapdriver.c
new file mode 100644
index 0000000..815e077
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver.c
@@ -0,0 +1,1226 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "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);
+}
+
+static int imapdriver_login(mailsession * session,
+ char * userid, char * password)
+{
+ int r;
+
+ r = mailimap_login(get_imap_session(session), userid, password);
+
+ return imap_error_to_mail_error(r);
+}
+
+static int imapdriver_logout(mailsession * session)
+{
+ int r;
+
+ imap_flags_store_process(get_imap_session(session),
+ get_data(session)->imap_flags_store);
+
+ r = mailimap_logout(get_imap_session(session));
+
+ return imap_error_to_mail_error(r);
+}
+
+static int imapdriver_noop(mailsession * session)
+{
+ int r;
+
+ r = mailimap_noop(get_imap_session(session));
+
+ return imap_error_to_mail_error(r);
+}
+
+static int imapdriver_build_folder_name(mailsession * session, char * mb,
+ char * name, char ** result)
+{
+ char delimiter[2] = "X";
+ char * folder_name;
+ mailimap * imap;
+ struct mailimap_mailbox_list * mb_list;
+ int r;
+ clist * imap_list;
+
+ imap = get_imap_session(session);
+
+ r = mailimap_list(imap, mb, "", &imap_list);
+ if (r != MAILIMAP_NO_ERROR)
+ return r;
+
+ if (clist_begin(imap_list) == NULL)
+ return MAIL_ERROR_LIST;
+
+ mb_list = clist_begin(imap_list)->data;
+ delimiter[0] = mb_list->mb_delimiter;
+
+ folder_name = malloc(strlen(mb) + strlen(delimiter) + strlen(name) + 1);
+ if (folder_name == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ strcpy(folder_name, mb);
+ strcat(folder_name, delimiter);
+ strcat(folder_name, name);
+
+ * result = folder_name;
+
+ return MAIL_NO_ERROR;
+}
+
+/* folders operations */
+
+static int imapdriver_create_folder(mailsession * session, char * mb)
+{
+ int r;
+
+ r = mailimap_create(get_imap_session(session), mb);
+
+ return imap_error_to_mail_error(r);
+}
+
+static int imapdriver_delete_folder(mailsession * session, char * mb)
+{
+ int r;
+
+ r = mailimap_delete(get_imap_session(session), mb);
+
+ return imap_error_to_mail_error(r);
+}
+
+static int imapdriver_rename_folder(mailsession * session, char * mb,
+ char * new_name)
+{
+ int r;
+
+ r = mailimap_rename(get_imap_session(session), mb, new_name);
+
+ return imap_error_to_mail_error(r);
+}
+
+static int imapdriver_check_folder(mailsession * session)
+{
+ int r;
+
+ imap_flags_store_process(get_imap_session(session),
+ get_data(session)->imap_flags_store);
+
+ r = mailimap_check(get_imap_session(session));
+
+ return imap_error_to_mail_error(r);
+}
+
+static int imapdriver_examine_folder(mailsession * session, char * mb)
+{
+ int r;
+
+ r = mailimap_examine(get_imap_session(session), mb);
+
+ return imap_error_to_mail_error(r);
+}
+
+static int imapdriver_select_folder(mailsession * session, char * mb)
+{
+ int r;
+ char * new_mb;
+ char * old_mb;
+
+ old_mb = get_data(session)->imap_mailbox;
+ if (old_mb != NULL)
+ if (strcmp(mb, old_mb) == 0)
+ return MAIL_NO_ERROR;
+
+ imap_flags_store_process(get_imap_session(session),
+ get_data(session)->imap_flags_store);
+
+ r = mailimap_select(get_imap_session(session), mb);
+
+ switch (r) {
+ case MAILIMAP_NO_ERROR:
+ new_mb = strdup(mb);
+ if (new_mb == NULL) {
+ if (old_mb != NULL)
+ free(old_mb);
+ get_data(session)->imap_mailbox = NULL;
+ return MAIL_ERROR_MEMORY;
+ }
+
+ get_data(session)->imap_mailbox = new_mb;
+
+ return MAIL_NO_ERROR;
+ default:
+ return imap_error_to_mail_error(r);
+ }
+}
+
+static int imapdriver_expunge_folder(mailsession * session)
+{
+ int r;
+
+ imap_flags_store_process(get_imap_session(session),
+ get_data(session)->imap_flags_store);
+
+ r = mailimap_expunge(get_imap_session(session));
+
+ return imap_error_to_mail_error(r);
+}
+
+static int status_selected_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ int r;
+ int res;
+ mailimap * imap;
+ uint32_t exists;
+ uint32_t unseen;
+ uint32_t recent;
+ struct mailimap_search_key * search_key;
+ clist * search_result;
+
+ imap = get_imap_session(session);
+
+ exists = imap->imap_selection_info->sel_exists;
+ recent = imap->imap_selection_info->sel_recent;
+
+ search_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, 0,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, 0, NULL, NULL, NULL);
+ if (search_key == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ /* default : use the RECENT count if search fails */
+ unseen = recent;
+ r = mailimap_search(imap, NULL, search_key, &search_result);
+ mailimap_search_key_free(search_key);
+ if (r == MAILIMAP_NO_ERROR) {
+ /* if this succeed, we use the real count */
+ unseen = clist_count(search_result);
+ mailimap_mailbox_data_search_free(search_result);
+ }
+
+ * result_messages = exists;
+ * result_unseen = unseen;
+ * result_recent = recent;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int status_unselected_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ struct mailimap_status_att_list * att_list;
+ struct mailimap_mailbox_data_status * status;
+ int r;
+ int res;
+ clistiter * cur;
+ mailimap * imap;
+
+ imap = get_imap_session(session);
+
+ att_list = mailimap_status_att_list_new_empty();
+ if (att_list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_MESSAGES);
+ switch (r) {
+ case MAILIMAP_NO_ERROR:
+ break;
+ default:
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_RECENT);
+ switch (r) {
+ case MAILIMAP_NO_ERROR:
+ break;
+ default:
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_UNSEEN);
+ switch (r) {
+ case MAILIMAP_NO_ERROR:
+ break;
+ default:
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ r = mailimap_status(imap, mb, att_list, &status);
+
+ switch (r) {
+ case MAILIMAP_NO_ERROR:
+ break;
+ default:
+ res = imap_error_to_mail_error(r);
+ goto free;
+ }
+
+ * result_messages = 0;
+ * result_recent = 0;
+ * result_unseen = 0;
+
+ for (cur = clist_begin(status->st_info_list);
+ cur != NULL ; cur = clist_next(cur)) {
+ struct mailimap_status_info * status_info;
+
+ status_info = clist_content(cur);
+ switch (status_info->st_att) {
+ case MAILIMAP_STATUS_ATT_MESSAGES:
+ * result_messages = status_info->st_value;
+ break;
+ case MAILIMAP_STATUS_ATT_RECENT:
+ * result_recent = status_info->st_value;
+ break;
+ case MAILIMAP_STATUS_ATT_UNSEEN:
+ * result_unseen = status_info->st_value;
+ break;
+ }
+ }
+
+ mailimap_mailbox_data_status_free(status);
+ mailimap_status_att_list_free(att_list);
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailimap_status_att_list_free(att_list);
+ err:
+ return res;
+}
+
+static int imapdriver_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ int res;
+ int current_folder;
+ char * current_mb;
+
+ if (mb == NULL) {
+ mb = get_data(session)->imap_mailbox;
+ if (mb == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+ }
+
+ current_mb = get_data(session)->imap_mailbox;
+ if (strcmp(mb, current_mb) == 0)
+ current_folder = 1;
+ else
+ current_folder = 0;
+
+ if (current_folder)
+ return status_selected_folder(session, mb, result_messages,
+ result_recent, result_unseen);
+ else
+ return status_unselected_folder(session, mb, result_messages,
+ result_recent, result_unseen);
+
+ err:
+ return res;
+}
+
+/* TODO : more efficient functions */
+
+static int imapdriver_messages_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 = messages;
+
+ return MAIL_NO_ERROR;
+}
+
+static int imapdriver_recent_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 = 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);
+}
+
+
+
+#define IMAP_SET_MAX_COUNT 100
+
+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;
+ clistiter * set_iter;
+
+ 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);
+
+ set_iter = clist_begin(set->set_list);
+ while (set_iter != NULL) {
+ struct mailimap_set * subset;
+ unsigned int count;
+
+ subset = mailimap_set_new_empty();
+ if (subset == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ count = 0;
+ while (count < IMAP_SET_MAX_COUNT) {
+ struct mailimap_set_item * item;
+
+ item = clist_content(set_iter);
+ set_iter = clist_delete(set->set_list, set_iter);
+
+ r = mailimap_set_add(subset, item);
+ if (r != MAILIMAP_NO_ERROR) {
+ mailimap_set_item_free(item);
+ mailimap_set_free(subset);
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ count ++;
+
+ if (set_iter == NULL)
+ break;
+ }
+
+ r = mailimap_uid_fetch(get_imap_session(session), subset,
+ fetch_type, &fetch_result);
+
+ mailimap_set_free(subset);
+
+ switch (r) {
+ case MAILIMAP_NO_ERROR:
+ break;
+ default:
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+ return imap_error_to_mail_error(r);
+ }
+
+ if (clist_begin(fetch_result) == NULL) {
+ res = MAIL_ERROR_FETCH;
+ goto err;
+ }
+
+ r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
+ mailimap_fetch_list_free(fetch_result);
+
+ if (r != MAIL_NO_ERROR) {
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ }
+
+#if 0
+ r = mailimap_uid_fetch(get_imap_session(session), set,
+ fetch_type, &fetch_result);
+#endif
+
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+#if 0
+ 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;
+ }
+#endif
+
+ return MAIL_NO_ERROR;
+
+ free_fetch_type:
+ mailimap_fetch_type_free(fetch_type);
+ err:
+ return res;
+}
+
+
+#if 0
+static int imapdriver_search_messages(mailsession * session, char * charset,
+ struct mail_search_key * key,
+ struct mail_search_result ** result)
+{
+ struct mailimap_search_key * imap_key;
+ int r;
+ clist * imap_result;
+ clist * result_list;
+ struct mail_search_result * search_result;
+ clistiter * cur;
+
+ r = mail_search_to_imap_search(key, &imap_key);
+ if (r != MAIL_NO_ERROR)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailimap_uid_search(get_imap_session(session), charset, imap_key,
+ &imap_result);
+
+ mailimap_search_key_free(imap_key);
+
+ switch (r) {
+ case MAILIMAP_NO_ERROR:
+ break;
+ default:
+ return imap_error_to_mail_error(r);
+ }
+
+ result_list = clist_new();
+ if (result_list == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ for(cur = clist_begin(imap_result) ; cur != NULL ; cur = clist_next(cur)) {
+ uint32_t val = * (uint32_t *) clist_content(cur);
+ uint32_t * new;
+
+ new = malloc(sizeof(* new));
+ if (new == NULL) {
+ goto free_imap_result;
+ }
+
+ * new = val;
+
+ r = clist_append(result_list, new);
+ if (r != 0) {
+ free(new);
+ goto free_imap_result;
+ }
+ }
+
+ search_result = mail_search_result_new(result_list);
+ if (search_result == NULL)
+ goto free_imap_result;
+
+ mailimap_search_result_free(imap_result);
+
+ * result = search_result;
+
+ return MAIL_NO_ERROR;
+
+ free_imap_result:
+ mailimap_search_result_free(imap_result);
+ return MAIL_ERROR_MEMORY;
+}
+#endif
+
+static int imapdriver_starttls(mailsession * session)
+{
+ mailimap * imap;
+ int r;
+ struct mailimap_capability_data * cap_data;
+ clistiter * cur;
+ int starttls;
+ int fd;
+ mailstream_low * low;
+ mailstream_low * new_low;
+ int capability_available;
+
+ imap = get_imap_session(session);
+
+ capability_available = FALSE;
+ if (imap->imap_connection_info != NULL)
+ if (imap->imap_connection_info->imap_capability != NULL) {
+ capability_available = TRUE;
+ cap_data = imap->imap_connection_info->imap_capability;
+ }
+
+ if (!capability_available) {
+ r = mailimap_capability(imap, &cap_data);
+ switch (r) {
+ case MAILIMAP_NO_ERROR:
+ break;
+ default:
+ return imap_error_to_mail_error(r);
+ }
+ }
+
+ starttls = FALSE;
+ for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct mailimap_capability * cap;
+
+ cap = clist_content(cur);
+
+ if (cap->cap_type == MAILIMAP_CAPABILITY_NAME)
+ if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) {
+ starttls = TRUE;
+ break;
+ }
+ }
+
+ if (!capability_available)
+ mailimap_capability_data_free(cap_data);
+
+ if (!starttls)
+ return MAIL_ERROR_NO_TLS;
+
+ r = mailimap_starttls(imap);
+
+ switch (r) {
+ case MAILIMAP_NO_ERROR:
+ break;
+ default:
+ return imap_error_to_mail_error(r);
+ }
+
+ low = mailstream_get_low(imap->imap_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(imap->imap_stream, new_low);
+
+ return MAIL_NO_ERROR;
+}
+
+static int imapdriver_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_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_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_get_message(session, num, result);
+}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver.h b/libetpan/src/driver/implementation/imap/imapdriver.h
new file mode 100644
index 0000000..cbc0c51
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver.h
@@ -0,0 +1,52 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef IMAPDRIVER_H
+
+#define IMAPDRIVER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libetpan/imapdriver_types.h>
+
+extern mailsession_driver * imap_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached.c b/libetpan/src/driver/implementation/imap/imapdriver_cached.c
new file mode 100644
index 0000000..806b282
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached.c
@@ -0,0 +1,1370 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "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;
+
+ 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, &quoted_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_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) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+ mailmessage_free(msg);
+ 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;
+}
+
+#define IMAP_SET_MAX_COUNT 100
+
+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;
+ clistiter * set_iter;
+
+#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);
+
+ set_iter = clist_begin(set->set_list);
+ while (set_iter != NULL) {
+ struct mailimap_set * subset;
+ unsigned int count;
+
+ subset = mailimap_set_new_empty();
+ if (subset == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ count = 0;
+ while (count < IMAP_SET_MAX_COUNT) {
+ struct mailimap_set_item * item;
+
+ item = clist_content(set_iter);
+ set_iter = clist_delete(set->set_list, set_iter);
+
+ r = mailimap_set_add(subset, item);
+ if (r != MAILIMAP_NO_ERROR) {
+ mailimap_set_item_free(item);
+ mailimap_set_free(subset);
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ count ++;
+
+ if (set_iter == NULL)
+ break;
+ }
+
+ r = mailimap_uid_fetch(get_imap_session(session), subset,
+ fetch_type, &fetch_result);
+
+ mailimap_set_free(subset);
+
+ switch (r) {
+ case MAILIMAP_NO_ERROR:
+ break;
+ default:
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+ return imap_error_to_mail_error(r);
+ }
+
+ if (clist_begin(fetch_result) == NULL) {
+ res = MAIL_ERROR_FETCH;
+ goto err;
+ }
+
+ r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
+ mailimap_fetch_list_free(fetch_result);
+
+ if (r != MAIL_NO_ERROR) {
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ }
+
+#if 0
+ r = mailimap_uid_fetch(get_imap_session(session), set,
+ fetch_type, &fetch_result);
+#endif
+
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+
+#if 0
+ 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;
+ }
+#endif
+
+ /* 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);
+}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached.h b/libetpan/src/driver/implementation/imap/imapdriver_cached.h
new file mode 100644
index 0000000..c324f5e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached.h
@@ -0,0 +1,52 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef IMAPDRIVER_CACHED_H
+
+#define IMAPDRIVER_CACHED_H
+
+#include <libetpan/imapdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * imap_cached_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c
new file mode 100644
index 0000000..34e1ca3
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c
@@ -0,0 +1,664 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "imapdriver_cached_message.h"
+
+#include "imapdriver_tools.h"
+#include "imapdriver_message.h"
+#include "imapdriver_cached.h"
+#include "imapdriver_types.h"
+#include "imapdriver.h"
+#include "mailmessage.h"
+#include "generic_cache.h"
+#include "mail_cache_db.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+static int imap_initialize(mailmessage * msg_info);
+
+static void imap_uninitialize(mailmessage * msg_info);
+
+static void imap_flush(mailmessage * msg_info);
+
+static void imap_check(mailmessage * msg_info);
+
+static void imap_fetch_result_free(mailmessage * msg_info,
+ char * msg);
+
+static int imap_fetch(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static int imap_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static int imap_fetch_body(mailmessage * msg_info,
+ char ** result, size_t * result_len);
+
+static int imap_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static int imap_get_bodystructure(mailmessage * msg_info,
+ struct mailmime ** result);
+
+static int imap_fetch_section(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result, size_t * result_len);
+
+static int imap_fetch_section_header(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result,
+ size_t * result_len);
+
+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:;
+}
+
+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;
+
+ generate_key_from_message(key, PATH_MAX,
+ msg_info, MAILIMAP_MSG_ATT_RFC822);
+
+ build_cache_name(filename, PATH_MAX, msg_info, key);
+
+ r = generic_cache_read(filename, &str, &len);
+ if (r == MAIL_NO_ERROR) {
+ * result = str;
+ * result_len = len;
+
+ return MAIL_NO_ERROR;
+ }
+
+ r = mailmessage_fetch(get_ancestor(msg_info),
+ result, result_len);
+ if (r == MAIL_NO_ERROR)
+ generic_cache_store(filename, * result, strlen(* result));
+
+ return r;
+}
+
+static int imap_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ char key[PATH_MAX];
+ char filename[PATH_MAX];
+ int r;
+ char * str;
+ size_t len;
+
+ generate_key_from_message(key, PATH_MAX,
+ msg_info, MAILIMAP_MSG_ATT_RFC822_HEADER);
+
+ build_cache_name(filename, PATH_MAX, msg_info, key);
+
+ r = generic_cache_read(filename, &str, &len);
+ if (r == MAIL_NO_ERROR) {
+ * result = str;
+ * result_len = len;
+
+ return MAIL_NO_ERROR;
+ }
+
+ r = mailmessage_fetch_header(get_ancestor(msg_info), result,
+ result_len);
+ if (r == MAIL_NO_ERROR)
+ generic_cache_store(filename, * result, * result_len);
+
+ return r;
+}
+
+static int imap_fetch_body(mailmessage * msg_info,
+ char ** result, size_t * result_len)
+{
+ char key[PATH_MAX];
+ char filename[PATH_MAX];
+ int r;
+ char * str;
+ size_t len;
+
+ generate_key_from_message(key, PATH_MAX,
+ msg_info, MAILIMAP_MSG_ATT_RFC822_TEXT);
+
+ build_cache_name(filename, PATH_MAX, msg_info, key);
+
+ r = generic_cache_read(filename, &str, &len);
+ if (r == MAIL_NO_ERROR) {
+ * result = str;
+ * result_len = len;
+ return MAIL_NO_ERROR;
+ }
+
+ r = mailmessage_fetch_body(get_ancestor(msg_info), result,
+ result_len);
+ if (r == MAIL_NO_ERROR)
+ generic_cache_store(filename, * result, * result_len);
+
+ return r;
+}
+
+static int imap_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ return mailmessage_fetch_size(get_ancestor(msg_info), result);
+}
+
+static int imap_get_bodystructure(mailmessage * msg_info,
+ struct mailmime ** result)
+{
+ int r;
+
+ if (msg_info->msg_mime != NULL) {
+ * result = msg_info->msg_mime;
+
+ return MAIL_NO_ERROR;
+ }
+
+ r = mailmessage_get_bodystructure(get_ancestor(msg_info),
+ result);
+ if (r == MAIL_NO_ERROR) {
+ msg_info->msg_mime = get_ancestor(msg_info)->msg_mime;
+ get_ancestor(msg_info)->msg_mime = NULL;
+ }
+
+ return r;
+}
+
+static int imap_fetch_section(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result, size_t * result_len)
+{
+ char key[PATH_MAX];
+ char filename[PATH_MAX];
+ int r;
+ char * str;
+ size_t len;
+
+ generate_key_from_section(key, PATH_MAX,
+ msg_info, mime, IMAP_SECTION_MESSAGE);
+
+ build_cache_name(filename, PATH_MAX, msg_info, key);
+
+ r = generic_cache_read(filename, &str, &len);
+ if (r == MAIL_NO_ERROR) {
+ * result = str;
+ * result_len = len;
+
+ return MAIL_NO_ERROR;
+ }
+
+ r = mailmessage_fetch_section(get_ancestor(msg_info),
+ mime, result, result_len);
+ if (r == MAIL_NO_ERROR)
+ generic_cache_store(filename, * result, * result_len);
+
+ return r;
+}
+
+static int imap_fetch_section_header(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result,
+ size_t * result_len)
+{
+ char key[PATH_MAX];
+ char filename[PATH_MAX];
+ int r;
+ char * str;
+ size_t len;
+
+ generate_key_from_section(key, PATH_MAX,
+ msg_info, mime, IMAP_SECTION_HEADER);
+
+ build_cache_name(filename, PATH_MAX, msg_info, key);
+
+ r = generic_cache_read(filename, &str, &len);
+ if (r == MAIL_NO_ERROR) {
+ * result = str;
+ * result_len = len;
+
+ return MAIL_NO_ERROR;
+ }
+
+ r = mailmessage_fetch_section_header(get_ancestor(msg_info),
+ mime, result, result_len);
+ if (r == MAIL_NO_ERROR)
+ generic_cache_store(filename, * result, * result_len);
+
+ return r;
+}
+
+static int imap_fetch_section_mime(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result,
+ size_t * result_len)
+{
+ char key[PATH_MAX];
+ char filename[PATH_MAX];
+ int r;
+ char * str;
+ size_t len;
+
+ generate_key_from_section(key, PATH_MAX,
+ msg_info, mime, IMAP_SECTION_MIME);
+
+ build_cache_name(filename, PATH_MAX, msg_info, key);
+
+ r = generic_cache_read(filename, &str, &len);
+ if (r == MAIL_NO_ERROR) {
+ * result = str;
+ * result_len = len;
+
+ return MAIL_NO_ERROR;
+ }
+
+ r = mailmessage_fetch_section_mime(get_ancestor(msg_info),
+ mime, result, result_len);
+ if (r == MAIL_NO_ERROR)
+ generic_cache_store(filename, * result, * result_len);
+
+ return r;
+}
+
+static int imap_fetch_section_body(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result,
+ size_t * result_len)
+{
+ char key[PATH_MAX];
+ char filename[PATH_MAX];
+ int r;
+ char * str;
+ size_t len;
+
+ generate_key_from_section(key, PATH_MAX,
+ msg_info, mime, IMAP_SECTION_BODY);
+
+ build_cache_name(filename, PATH_MAX, msg_info, key);
+
+ r = generic_cache_read(filename, &str, &len);
+ if (r == MAIL_NO_ERROR) {
+
+ * result = str;
+ * result_len = len;
+
+ return MAIL_NO_ERROR;
+ }
+
+ r = mailmessage_fetch_section_body(get_ancestor(msg_info),
+ mime, result, result_len);
+ if (r == MAIL_NO_ERROR)
+ generic_cache_store(filename, * result, * result_len);
+
+ return r;
+}
+
+static int imap_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result)
+{
+ int r;
+ struct mail_flags * flags;
+
+ if (msg_info->msg_flags != NULL) {
+ * result = msg_info->msg_flags;
+ return MAIL_NO_ERROR;
+ }
+
+ r = mailmessage_get_flags(get_ancestor(msg_info), &flags);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ get_ancestor(msg_info)->msg_flags = NULL;
+ msg_info->msg_flags = flags;
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+}
+
+#define ENV_NAME "env.db"
+
+static int imap_fetch_envelope(mailmessage * msg_info,
+ struct mailimf_fields ** result)
+{
+ struct mailimf_fields * fields;
+ int r;
+ struct mail_cache_db * cache_db;
+ MMAPString * mmapstr;
+ char filename[PATH_MAX];
+ struct imap_cached_session_state_data * data;
+ int res;
+
+ data = get_cached_session_data(msg_info);
+ if (data->imap_quoted_mb == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ 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 err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db;
+ }
+
+ r = imapdriver_get_cached_envelope(cache_db, mmapstr,
+ msg_info->msg_session, msg_info, &fields);
+
+ if ((r != MAIL_ERROR_CACHE_MISS) && (r != MAIL_NO_ERROR)) {
+ res = r;
+ goto close_db;
+ }
+
+ r = mailmessage_fetch_envelope(get_ancestor(msg_info), &fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto close_db;
+ }
+
+ r = imapdriver_write_cached_envelope(cache_db, mmapstr,
+ msg_info->msg_session, msg_info, fields);
+
+ * result = fields;
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename, cache_db);
+
+ return MAIL_NO_ERROR;
+
+ close_db:
+ mail_cache_db_close_unlock(filename, cache_db);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h
new file mode 100644
index 0000000..bf43311
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h
@@ -0,0 +1,52 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef IMAPDRIVER_CACHED_MESSAGE_H
+
+#define IMAPDRIVER_CACHED_MESSAGE_H
+
+#include <libetpan/imapdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * imap_cached_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_message.c b/libetpan/src/driver/implementation/imap/imapdriver_message.c
new file mode 100644
index 0000000..42e645d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_message.c
@@ -0,0 +1,1239 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "imapdriver_message.h"
+
+#include "imapdriver_tools.h"
+#include "imapdriver.h"
+#include "imapdriver_types.h"
+#include "mailimap.h"
+#include "maildriver_tools.h"
+#include "generic_cache.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static int imap_initialize(mailmessage * msg_info);
+
+static void imap_fetch_result_free(mailmessage * msg_info,
+ char * msg);
+
+static int imap_fetch(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static int imap_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static int imap_fetch_body(mailmessage * msg_info,
+ char ** result, size_t * result_len);
+
+static int imap_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static int imap_get_bodystructure(mailmessage * msg_info,
+ struct mailmime ** result);
+
+static int imap_fetch_section(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result, size_t * result_len);
+
+static int imap_fetch_section_header(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result,
+ size_t * result_len);
+
+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 void imap_flush(mailmessage * msg_info);
+
+static void imap_check(mailmessage * msg_info);
+
+static mailmessage_driver local_imap_message_driver = {
+ .msg_name = "imap",
+
+ .msg_initialize = imap_initialize,
+ .msg_uninitialize = NULL,
+
+ .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_message_driver = &local_imap_message_driver;
+
+static inline struct imap_session_state_data *
+get_session_data(mailmessage * msg)
+{
+ return msg->msg_session->sess_data;
+}
+
+static inline mailimap * get_imap_session(mailmessage * msg)
+{
+ return get_session_data(msg)->imap_session;
+}
+
+
+
+static int imap_initialize(mailmessage * msg_info)
+{
+ char key[PATH_MAX];
+ char * uid;
+ mailimap * imap;
+
+ 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) {
+ return MAIL_ERROR_MEMORY;
+ }
+
+ msg_info->msg_uid = uid;
+
+ return MAIL_NO_ERROR;
+}
+
+
+static void imap_fetch_result_free(mailmessage * msg_info,
+ char * msg)
+{
+ if (msg != NULL) {
+ if (mmap_string_unref(msg) != 0)
+ free(msg);
+ }
+}
+
+
+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)
+{
+ int r;
+
+ if (msg_info->msg_flags != NULL) {
+ r = mail_flags_store_set(get_session_data(msg_info)->imap_flags_store,
+ msg_info);
+ /* ignore errors */
+ }
+}
+
+static int imap_fetch(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ int r;
+ struct mailimap_set * set;
+ struct mailimap_fetch_att * fetch_att;
+ struct mailimap_fetch_type * fetch_type;
+ clist * fetch_result;
+ struct mailimap_msg_att * msg_att;
+ struct mailimap_msg_att_item * msg_att_item;
+ char * text;
+ size_t text_length;
+ int res;
+ clistiter * cur;
+ struct mailimap_section * section;
+
+ set = mailimap_set_new_single(msg_info->msg_index);
+ if (set == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+#if 0
+ fetch_att = mailimap_fetch_att_new_rfc822();
+ if (fetch_att == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
+ if (fetch_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_fetch_att;
+ }
+
+ r = mailimap_uid_fetch(get_imap_session(msg_info->session), set,
+ fetch_type, &fetch_result);
+
+ mailimap_fetch_type_free(fetch_type);
+#endif
+
+ section = mailimap_section_new(NULL);
+ if (section == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ fetch_att = mailimap_fetch_att_new_body_peek_section(section);
+ if (fetch_att == NULL) {
+ mailimap_section_free(section);
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
+ if (fetch_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_fetch_att;
+ }
+
+ r = mailimap_uid_fetch(get_imap_session(msg_info), 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);
+ }
+
+ if (clist_begin(fetch_result) == NULL) {
+ mailimap_fetch_list_free(fetch_result);
+ return MAIL_ERROR_FETCH;
+ }
+
+ msg_att = clist_begin(fetch_result)->data;
+
+ text = NULL;
+ text_length = 0;
+
+ for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ msg_att_item = clist_content(cur);
+
+ if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
+#if 0
+ if (msg_att_item->msg_att_static->type == MAILIMAP_MSG_ATT_RFC822) {
+ text = msg_att_item->msg_att_static->rfc822;
+ msg_att_item->msg_att_static->rfc822 = NULL;
+ text_length = msg_att_item->msg_att_static->length;
+ }
+#endif
+ if (msg_att_item->att_data.att_static->att_type ==
+ MAILIMAP_MSG_ATT_BODY_SECTION) {
+ text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
+ /* detach */
+ msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
+ text_length =
+ msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
+ }
+ }
+ }
+
+ mailimap_fetch_list_free(fetch_result);
+
+ if (text == NULL)
+ return MAIL_ERROR_FETCH;
+
+ * result = text;
+ * result_len = text_length;
+
+ return MAIL_NO_ERROR;
+
+ free_fetch_att:
+ mailimap_fetch_att_free(fetch_att);
+ free_set:
+ mailimap_set_free(set);
+ err:
+ return res;
+}
+
+static int imap_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ int r;
+ struct mailimap_set * set;
+ struct mailimap_fetch_att * fetch_att;
+ struct mailimap_fetch_type * fetch_type;
+ clist * fetch_result;
+ struct mailimap_msg_att * msg_att;
+ struct mailimap_msg_att_item * msg_att_item;
+ char * text;
+ size_t text_length;
+ int res;
+ clistiter * cur;
+ struct mailimap_section * section;
+
+ set = mailimap_set_new_single(msg_info->msg_index);
+ if (set == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+#if 0
+ fetch_att = mailimap_fetch_att_new_rfc822_header();
+ if (fetch_att == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
+ if (fetch_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_fetch_att;
+ }
+
+ r = mailimap_uid_fetch(get_imap_session(msg_info->session),
+ set, fetch_type, &fetch_result);
+
+ mailimap_fetch_type_free(fetch_type);
+#endif
+
+ section = mailimap_section_new_header();
+ if (section == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ fetch_att = mailimap_fetch_att_new_body_peek_section(section);
+ if (fetch_att == NULL) {
+ mailimap_section_free(section);
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
+ if (fetch_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_fetch_att;
+ }
+
+ r = mailimap_uid_fetch(get_imap_session(msg_info), 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);
+ }
+
+ if (clist_begin(fetch_result) == NULL) {
+ mailimap_fetch_list_free(fetch_result);
+ return MAIL_ERROR_FETCH;
+ }
+
+ msg_att = clist_begin(fetch_result)->data;
+
+ text = NULL;
+ text_length = 0;
+
+ for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ msg_att_item = clist_content(cur);
+
+ if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
+#if 0
+ if (msg_att_item->msg_att_static->type ==
+ MAILIMAP_MSG_ATT_RFC822_HEADER) {
+ text = msg_att_item->msg_att_static->rfc822_header;
+ msg_att_item->msg_att_static->rfc822_header = NULL;
+ text_length = msg_att_item->msg_att_static->length;
+ }
+#endif
+ if (msg_att_item->att_data.att_static->att_type ==
+ MAILIMAP_MSG_ATT_BODY_SECTION) {
+ text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
+ msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
+ text_length =
+ msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
+ }
+ }
+ }
+
+ mailimap_fetch_list_free(fetch_result);
+
+ if (text == NULL)
+ return MAIL_ERROR_FETCH;
+
+ * result = text;
+ * result_len = text_length;
+
+ return MAIL_NO_ERROR;
+
+ free_fetch_att:
+ mailimap_fetch_att_free(fetch_att);
+ free_set:
+ mailimap_set_free(set);
+ err:
+ return res;
+}
+
+static int imap_fetch_body(mailmessage * msg_info,
+ char ** result, size_t * result_len)
+{
+ int r;
+ struct mailimap_set * set;
+ struct mailimap_fetch_att * fetch_att;
+ struct mailimap_fetch_type * fetch_type;
+ clist * fetch_result;
+ struct mailimap_msg_att * msg_att;
+ struct mailimap_msg_att_item * msg_att_item;
+ char * text;
+ size_t text_length;
+ int res;
+ clistiter * cur;
+ struct mailimap_section * section;
+
+ set = mailimap_set_new_single(msg_info->msg_index);
+ if (set == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+#if 0
+ fetch_att = mailimap_fetch_att_new_rfc822_text();
+ if (fetch_att == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
+ if (fetch_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_fetch_att;
+ }
+
+ r = mailimap_uid_fetch(get_imap_session(msg_info->session), set,
+ fetch_type, &fetch_result);
+
+ mailimap_fetch_type_free(fetch_type);
+#endif
+ section = mailimap_section_new_text();
+ if (section == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ fetch_att = mailimap_fetch_att_new_body_peek_section(section);
+ if (fetch_att == NULL) {
+ mailimap_section_free(section);
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
+ if (fetch_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_fetch_att;
+ }
+
+ r = mailimap_uid_fetch(get_imap_session(msg_info), 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);
+ }
+
+ cur = clist_begin(fetch_result);
+ if (cur == NULL) {
+ mailimap_fetch_list_free(fetch_result);
+ return MAIL_ERROR_FETCH;
+ }
+
+ msg_att = clist_content(cur);
+
+ text = NULL;
+ text_length = 0;
+
+ for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ msg_att_item = clist_content(cur);
+
+ if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
+#if 0
+ if (msg_att_item->msg_att_static->type ==
+ MAILIMAP_MSG_ATT_RFC822_TEXT) {
+ text = msg_att_item->msg_att_static->rfc822_text;
+ msg_att_item->msg_att_static->rfc822_text = NULL;
+ text_length = msg_att_item->msg_att_static->length;
+ }
+#endif
+ if (msg_att_item->att_data.att_static->att_type ==
+ MAILIMAP_MSG_ATT_BODY_SECTION) {
+ text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
+ msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
+ text_length =
+ msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
+ }
+ }
+ }
+
+ mailimap_fetch_list_free(fetch_result);
+
+ if (text == NULL)
+ return MAIL_ERROR_FETCH;
+
+ * result = text;
+ * result_len = text_length;
+
+ return MAIL_NO_ERROR;
+
+ free_fetch_att:
+ mailimap_fetch_att_free(fetch_att);
+ free_set:
+ mailimap_set_free(set);
+ err:
+ return res;
+}
+
+static int imap_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ int r;
+ struct mailimap_set * set;
+ struct mailimap_fetch_att * fetch_att;
+ struct mailimap_fetch_type * fetch_type;
+ clist * fetch_result;
+ struct mailimap_msg_att * msg_att;
+ struct mailimap_msg_att_item * msg_att_item;
+ size_t size;
+ int res;
+ clistiter * cur;
+
+ set = mailimap_set_new_single(msg_info->msg_index);
+ if (set == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ fetch_att = mailimap_fetch_att_new_rfc822_size();
+ if (fetch_att == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
+ if (fetch_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_fetch_att;
+ }
+
+ r = mailimap_uid_fetch(get_imap_session(msg_info), set,
+ fetch_type, &fetch_result);
+
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+
+ switch (r) {
+ case MAILIMAP_ERROR_BAD_STATE:
+ return MAIL_ERROR_BAD_STATE;
+ case MAILIMAP_ERROR_STREAM:
+ return MAIL_ERROR_STREAM;
+ case MAILIMAP_NO_ERROR:
+ break;
+ default:
+ return MAIL_ERROR_FETCH;
+ }
+
+ if (clist_begin(fetch_result) == NULL) {
+ mailimap_fetch_list_free(fetch_result);
+ return MAIL_ERROR_FETCH;
+ }
+
+ msg_att = clist_begin(fetch_result)->data;
+
+ for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ msg_att_item = clist_content(cur);
+
+ if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
+
+ if (msg_att_item->att_data.att_static->att_type ==
+ MAILIMAP_MSG_ATT_RFC822_SIZE) {
+ size = msg_att_item->att_data.att_static->att_data.att_rfc822_size;
+
+ * result = size;
+
+ mailimap_fetch_list_free(fetch_result);
+ return MAIL_NO_ERROR;
+ }
+ }
+ }
+
+ mailimap_fetch_list_free(fetch_result);
+
+ return MAIL_ERROR_FETCH;
+
+ free_fetch_att:
+ mailimap_fetch_att_free(fetch_att);
+ free_set:
+ mailimap_set_free(set);
+ err:
+ return res;
+}
+
+static int imap_get_bodystructure(mailmessage * msg_info,
+ struct mailmime ** result)
+{
+ int r;
+ struct mailimap_set * set;
+ struct mailimap_fetch_att * fetch_att;
+ struct mailimap_fetch_type * fetch_type;
+ clist * fetch_result;
+ struct mailimap_msg_att * msg_att;
+ struct mailimap_body * imap_body;
+ struct mailmime * body;
+ int res;
+ struct mailimf_fields * fields;
+ struct mailmime * new_body;
+ struct mailmime_content * content_message;
+ struct mailimap_envelope * envelope;
+ uint32_t uid;
+ char * references;
+ size_t ref_size;
+ clistiter * cur;
+
+ if (msg_info->msg_mime != NULL) {
+ * result = msg_info->msg_mime;
+
+ return MAIL_NO_ERROR;
+ }
+
+ set = mailimap_set_new_single(msg_info->msg_index);
+ if (set == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
+ if (fetch_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ 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_bodystructure();
+ 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 = mailimap_uid_fetch(get_imap_session(msg_info), 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);
+ }
+
+ cur = clist_begin(fetch_result);
+ if (cur == NULL) {
+ mailimap_fetch_list_free(fetch_result);
+ return MAIL_ERROR_FETCH;
+ }
+
+ msg_att = clist_content(cur);
+
+ uid = 0;
+ references = NULL;
+ ref_size = 0;
+ imap_body = NULL;
+ envelope = NULL;
+
+ r = imap_get_msg_att_info(msg_att,
+ &uid, &envelope, &references, &ref_size, NULL, &imap_body);
+ if (r != MAIL_NO_ERROR) {
+ mailimap_fetch_list_free(fetch_result);
+ res = r;
+ goto err;
+ }
+
+ if (uid != msg_info->msg_index) {
+ mailimap_fetch_list_free(fetch_result);
+ res = MAIL_ERROR_MSG_NOT_FOUND;
+ goto err;
+ }
+
+ if (imap_body == NULL) {
+ mailimap_fetch_list_free(fetch_result);
+ res = MAIL_ERROR_FETCH;
+ goto err;
+ }
+
+ r = imap_body_to_body(imap_body, &body);
+ if (r != MAIL_NO_ERROR) {
+ mailimap_fetch_list_free(fetch_result);
+ res = r;
+ goto err;
+ }
+
+ fields = NULL;
+ if (envelope != NULL) {
+ r = imap_env_to_fields(envelope, references, ref_size, &fields);
+ if (r != MAIL_NO_ERROR) {
+ mailmime_free(body);
+ mailimap_fetch_list_free(fetch_result);
+ res = r;
+ goto err;
+ }
+ }
+
+ content_message = mailmime_get_content_message();
+ if (content_message == NULL) {
+ if (fields != NULL)
+ mailimf_fields_free(fields);
+ mailmime_free(body);
+ mailimap_fetch_list_free(fetch_result);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ new_body = mailmime_new(MAILMIME_MESSAGE, NULL,
+ 0, NULL, content_message,
+ NULL, NULL, NULL, NULL, fields, body);
+
+ if (new_body == NULL) {
+ mailmime_content_free(content_message);
+ if (fields != NULL)
+ mailimf_fields_free(fields);
+ mailmime_free(body);
+ mailimap_fetch_list_free(fetch_result);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ msg_info->msg_mime = new_body;
+
+ mailimap_fetch_list_free(fetch_result);
+
+ * result = new_body;
+
+ return MAIL_NO_ERROR;
+
+ free_fetch_type:
+ mailimap_fetch_type_free(fetch_type);
+ free_set:
+ mailimap_set_free(set);
+ err:
+ return res;
+}
+
+static int
+fetch_imap(mailmessage * msg,
+ struct mailimap_fetch_type * fetch_type,
+ char ** result, size_t * result_len)
+{
+ int r;
+ struct mailimap_msg_att * msg_att;
+ struct mailimap_msg_att_item * msg_att_item;
+ clist * fetch_result;
+ struct mailimap_set * set;
+ char * text;
+ size_t text_length;
+ clistiter * cur;
+
+ set = mailimap_set_new_single(msg->msg_index);
+ if (set == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailimap_uid_fetch(get_imap_session(msg), set,
+ fetch_type, &fetch_result);
+
+ mailimap_set_free(set);
+
+ switch (r) {
+ case MAILIMAP_NO_ERROR:
+ break;
+ default:
+ return imap_error_to_mail_error(r);
+ }
+
+ if (clist_begin(fetch_result) == NULL) {
+ mailimap_fetch_list_free(fetch_result);
+ return MAIL_ERROR_FETCH;
+ }
+
+ msg_att = clist_begin(fetch_result)->data;
+
+ text = NULL;
+ text_length = 0;
+
+ for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ msg_att_item = clist_content(cur);
+
+ if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
+
+ if (msg_att_item->att_data.att_static->att_type ==
+ MAILIMAP_MSG_ATT_BODY_SECTION) {
+ text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
+ msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
+ text_length =
+ msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
+ }
+ }
+ }
+
+ mailimap_fetch_list_free(fetch_result);
+
+ if (text == NULL)
+ return MAIL_ERROR_FETCH;
+
+ * result = text;
+ * result_len = text_length;
+
+ return MAIL_NO_ERROR;
+}
+
+
+static int imap_fetch_section(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result, size_t * result_len)
+{
+ struct mailimap_section * section;
+ struct mailimap_fetch_att * fetch_att;
+ int r;
+ struct mailimap_fetch_type * fetch_type;
+ char * text;
+ size_t text_length;
+ struct mailmime_section * part;
+
+ if (mime->mm_parent == NULL)
+ return imap_fetch(msg_info, result, result_len);
+
+ r = mailmime_get_section_id(mime, &part);
+ if (r != MAILIMF_NO_ERROR)
+ return maildriver_imf_error_to_mail_error(r);
+
+ r = section_to_imap_section(part, IMAP_SECTION_MESSAGE, &section);
+ mailmime_section_free(part);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ fetch_att = mailimap_fetch_att_new_body_peek_section(section);
+ if (fetch_att == NULL) {
+ mailimap_section_free(section);
+ return MAIL_ERROR_MEMORY;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
+ if (fetch_type == NULL) {
+ mailimap_fetch_att_free(fetch_att);
+ return MAIL_ERROR_MEMORY;
+ }
+
+ r = fetch_imap(msg_info, fetch_type, &text, &text_length);
+
+ mailimap_fetch_type_free(fetch_type);
+
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = text;
+ * result_len = text_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static int imap_fetch_section_header(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result,
+ size_t * result_len)
+{
+ struct mailimap_section * section;
+ struct mailimap_fetch_att * fetch_att;
+ int r;
+ struct mailimap_fetch_type * fetch_type;
+ char * text;
+ size_t text_length;
+ struct mailmime_section * part;
+
+ if (mime->mm_parent == NULL)
+ return imap_fetch_header(msg_info, result, result_len);
+
+ r = mailmime_get_section_id(mime, &part);
+ if (r != MAILIMF_NO_ERROR)
+ return maildriver_imf_error_to_mail_error(r);
+
+ r = section_to_imap_section(part, IMAP_SECTION_HEADER, &section);
+ mailmime_section_free(part);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ fetch_att = mailimap_fetch_att_new_body_peek_section(section);
+ if (fetch_att == NULL) {
+ mailimap_section_free(section);
+ return MAIL_ERROR_MEMORY;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
+ if (fetch_type == NULL) {
+ mailimap_fetch_att_free(fetch_att);
+ return MAIL_ERROR_MEMORY;
+ }
+
+ r = fetch_imap(msg_info, fetch_type, &text, &text_length);
+ mailimap_fetch_type_free(fetch_type);
+
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = text;
+ * result_len = text_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static int imap_fetch_section_mime(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result,
+ size_t * result_len)
+{
+ struct mailimap_section * section;
+ struct mailimap_fetch_att * fetch_att;
+ int r;
+ struct mailimap_fetch_type * fetch_type;
+ char * text;
+ size_t text_length;
+ struct mailmime_section * part;
+
+ if (mime->mm_parent == NULL)
+ return MAIL_ERROR_INVAL;
+
+ if (mime->mm_parent->mm_parent == NULL)
+ return imap_fetch_header(msg_info, result, result_len);
+
+ r = mailmime_get_section_id(mime, &part);
+ if (r != MAILIMF_NO_ERROR)
+ return maildriver_imf_error_to_mail_error(r);
+
+ r = section_to_imap_section(part, IMAP_SECTION_MIME, &section);
+ mailmime_section_free(part);
+ if (r != MAIL_NO_ERROR)
+ return MAIL_ERROR_MEMORY;
+
+ fetch_att = mailimap_fetch_att_new_body_peek_section(section);
+ if (fetch_att == NULL) {
+ mailimap_section_free(section);
+ return MAIL_ERROR_MEMORY;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
+ if (fetch_type == NULL) {
+ mailimap_fetch_att_free(fetch_att);
+ return MAIL_ERROR_MEMORY;
+ }
+
+ r = fetch_imap(msg_info, fetch_type, &text, &text_length);
+
+ mailimap_fetch_type_free(fetch_type);
+
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = text;
+ * result_len = text_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static int imap_fetch_section_body(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result,
+ size_t * result_len)
+{
+ struct mailimap_section * section;
+ struct mailimap_fetch_att * fetch_att;
+ int r;
+ struct mailimap_fetch_type * fetch_type;
+ char * text;
+ size_t text_length;
+ struct mailmime_section * part;
+
+ if (mime->mm_parent == NULL)
+ return imap_fetch_body(msg_info, result, result_len);
+
+ if (mime->mm_parent->mm_parent == NULL)
+ return imap_fetch_body(msg_info, result, result_len);
+
+ r = mailmime_get_section_id(mime, &part);
+ if (r != MAILIMF_NO_ERROR)
+ return maildriver_imf_error_to_mail_error(r);
+
+ r = section_to_imap_section(part, IMAP_SECTION_BODY, &section);
+ mailmime_section_free(part);
+ if (r != MAIL_NO_ERROR)
+ return MAIL_ERROR_MEMORY;
+
+ fetch_att = mailimap_fetch_att_new_body_peek_section(section);
+ if (fetch_att == NULL) {
+ mailimap_section_free(section);
+ return MAIL_ERROR_MEMORY;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
+ if (fetch_type == NULL) {
+ mailimap_fetch_att_free(fetch_att);
+ return MAIL_ERROR_MEMORY;
+ }
+
+ r = fetch_imap(msg_info, fetch_type, &text, &text_length);
+
+ mailimap_fetch_type_free(fetch_type);
+
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = text;
+ * result_len = text_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static int imap_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result)
+{
+ int r;
+ struct mail_flags * flags;
+
+ if (msg_info->msg_flags != NULL) {
+ * result = msg_info->msg_flags;
+ return MAIL_NO_ERROR;
+ }
+
+ flags = mail_flags_store_get(get_session_data(msg_info)->imap_flags_store,
+ msg_info->msg_index);
+
+ if (flags == NULL) {
+ r = imap_fetch_flags(get_imap_session(msg_info),
+ msg_info->msg_index, &flags);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ }
+
+ msg_info->msg_flags = flags;
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+}
+
+static int imap_fetch_envelope(mailmessage * msg_info,
+ struct mailimf_fields ** result)
+{
+ int r;
+ struct mailimap_set * set;
+ struct mailimap_fetch_att * fetch_att;
+ struct mailimap_fetch_type * fetch_type;
+ clist * fetch_result;
+ struct mailimap_msg_att * msg_att;
+ int res;
+ struct mailimf_fields * fields;
+ struct mailimap_envelope * envelope;
+ uint32_t uid;
+ char * references;
+ size_t ref_size;
+
+ set = mailimap_set_new_single(msg_info->msg_index);
+ if (set == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
+ if (fetch_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ 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;
+ }
+
+ r = imap_add_envelope_fetch_att(fetch_type);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_fetch_type;
+ }
+
+ r = mailimap_uid_fetch(get_imap_session(msg_info), 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);
+ }
+
+ if (clist_begin(fetch_result) == NULL) {
+ mailimap_fetch_list_free(fetch_result);
+ return MAIL_ERROR_FETCH;
+ }
+
+ msg_att = clist_begin(fetch_result)->data;
+
+ uid = 0;
+ references = NULL;
+ ref_size = 0;
+ envelope = NULL;
+
+ r = imap_get_msg_att_info(msg_att,
+ &uid,
+ &envelope,
+ &references,
+ &ref_size,
+ NULL,
+ NULL);
+ if (r != MAIL_NO_ERROR) {
+ mailimap_fetch_list_free(fetch_result);
+ res = r;
+ goto err;
+ }
+
+ if (uid != msg_info->msg_index) {
+ mailimap_fetch_list_free(fetch_result);
+ res = MAIL_ERROR_MSG_NOT_FOUND;
+ goto err;
+ }
+
+ fields = NULL;
+ if (envelope != NULL) {
+ r = imap_env_to_fields(envelope, references, ref_size, &fields);
+ if (r != MAIL_NO_ERROR) {
+ mailimap_fetch_list_free(fetch_result);
+ res = r;
+ goto err;
+ }
+ }
+
+ mailimap_fetch_list_free(fetch_result);
+
+ * result = fields;
+
+ return MAIL_NO_ERROR;
+
+ free_fetch_type:
+ mailimap_fetch_type_free(fetch_type);
+ free_set:
+ mailimap_set_free(set);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_message.h b/libetpan/src/driver/implementation/imap/imapdriver_message.h
new file mode 100644
index 0000000..74fc2e6
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_message.h
@@ -0,0 +1,52 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef IMAPDRIVER_MESSAGE_H
+
+#define IMAPDRIVER_MESSAGE_H
+
+#include <libetpan/imapdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * imap_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_tools.c b/libetpan/src/driver/implementation/imap/imapdriver_tools.c
new file mode 100644
index 0000000..6051281
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_tools.c
@@ -0,0 +1,3623 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "imapdriver_tools.h"
+
+#include "maildriver.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "mail.h"
+#include "imapdriver_types.h"
+#include "maildriver_tools.h"
+#include "generic_cache.h"
+#include "mailmessage.h"
+#include "mail_cache_db.h"
+
+
+
+static inline struct imap_session_state_data *
+session_get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline struct imap_cached_session_state_data *
+cached_session_get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline mailsession *
+cached_session_get_ancestor(mailsession * session)
+{
+ return cached_session_get_data(session)->imap_ancestor;
+}
+
+static inline struct imap_session_state_data *
+cached_session_get_ancestor_data(mailsession * session)
+{
+ return session_get_data(cached_session_get_ancestor(session));
+}
+
+static inline mailimap *
+cached_session_get_imap_session(mailsession * session)
+{
+ return cached_session_get_ancestor_data(session)->imap_session;
+}
+
+static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn,
+ struct mail_flags ** result);
+
+
+int imap_error_to_mail_error(int error)
+{
+ switch (error) {
+ case MAILIMAP_NO_ERROR:
+ return MAIL_NO_ERROR;
+
+ case MAILIMAP_NO_ERROR_AUTHENTICATED:
+ return MAIL_NO_ERROR_AUTHENTICATED;
+
+ case MAILIMAP_NO_ERROR_NON_AUTHENTICATED:
+ return MAIL_NO_ERROR_NON_AUTHENTICATED;
+
+ case MAILIMAP_ERROR_BAD_STATE:
+ return MAIL_ERROR_BAD_STATE;
+
+ case MAILIMAP_ERROR_STREAM:
+ return MAIL_ERROR_STREAM;
+
+ case MAILIMAP_ERROR_PARSE:
+ return MAIL_ERROR_PARSE;
+
+ case MAILIMAP_ERROR_CONNECTION_REFUSED:
+ return MAIL_ERROR_CONNECT;
+
+ case MAILIMAP_ERROR_MEMORY:
+ return MAIL_ERROR_MEMORY;
+
+ case MAILIMAP_ERROR_FATAL:
+ return MAIL_ERROR_FATAL;
+
+ case MAILIMAP_ERROR_PROTOCOL:
+ return MAIL_ERROR_PROTOCOL;
+
+ case MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION:
+ return MAIL_ERROR_CONNECT;
+
+ case MAILIMAP_ERROR_APPEND:
+ return MAIL_ERROR_APPEND;
+
+ case MAILIMAP_ERROR_NOOP:
+ return MAIL_ERROR_NOOP;
+
+ case MAILIMAP_ERROR_LOGOUT:
+ return MAIL_ERROR_LOGOUT;
+
+ case MAILIMAP_ERROR_CAPABILITY:
+ return MAIL_ERROR_CAPABILITY;
+
+ case MAILIMAP_ERROR_CHECK:
+ return MAIL_ERROR_CHECK;
+
+ case MAILIMAP_ERROR_CLOSE:
+ return MAIL_ERROR_CLOSE;
+
+ case MAILIMAP_ERROR_EXPUNGE:
+ return MAIL_ERROR_EXPUNGE;
+
+ case MAILIMAP_ERROR_COPY:
+ case MAILIMAP_ERROR_UID_COPY:
+ return MAIL_ERROR_COPY;
+
+ case MAILIMAP_ERROR_CREATE:
+ return MAIL_ERROR_CREATE;
+
+ case MAILIMAP_ERROR_DELETE:
+ return MAIL_ERROR_DELETE;
+
+ case MAILIMAP_ERROR_EXAMINE:
+ return MAIL_ERROR_EXAMINE;
+
+ case MAILIMAP_ERROR_FETCH:
+ case MAILIMAP_ERROR_UID_FETCH:
+ return MAIL_ERROR_FETCH;
+
+ case MAILIMAP_ERROR_LIST:
+ return MAIL_ERROR_LIST;
+
+ case MAILIMAP_ERROR_LOGIN:
+ return MAIL_ERROR_LOGIN;
+
+ case MAILIMAP_ERROR_LSUB:
+ return MAIL_ERROR_LSUB;
+
+ case MAILIMAP_ERROR_RENAME:
+ return MAIL_ERROR_RENAME;
+
+ case MAILIMAP_ERROR_SEARCH:
+ case MAILIMAP_ERROR_UID_SEARCH:
+ return MAIL_ERROR_SEARCH;
+
+ case MAILIMAP_ERROR_SELECT:
+ return MAIL_ERROR_SELECT;
+
+ case MAILIMAP_ERROR_STATUS:
+ return MAIL_ERROR_STATUS;
+
+ case MAILIMAP_ERROR_STORE:
+ case MAILIMAP_ERROR_UID_STORE:
+ return MAIL_ERROR_STORE;
+
+ case MAILIMAP_ERROR_SUBSCRIBE:
+ return MAIL_ERROR_SUBSCRIBE;
+
+ case MAILIMAP_ERROR_UNSUBSCRIBE:
+ return MAIL_ERROR_UNSUBSCRIBE;
+
+ case MAILIMAP_ERROR_STARTTLS:
+ return MAIL_ERROR_STARTTLS;
+
+ case MAILIMAP_ERROR_INVAL:
+ return MAIL_ERROR_INVAL;
+
+ default:
+ return MAIL_ERROR_INVAL;
+ }
+}
+
+
+
+
+
+static int
+imap_body_parameter_to_content(struct mailimap_body_fld_param *
+ body_parameter,
+ char * subtype,
+ struct mailmime_type * mime_type,
+ struct mailmime_content ** result);
+
+static int
+imap_body_type_text_to_content_type(char * subtype,
+ struct mailimap_body_fld_param *
+ body_parameter,
+ struct mailmime_content ** result);
+
+
+int imap_list_to_list(clist * imap_list, struct mail_list ** result)
+{
+ clistiter * cur;
+ clist * list;
+ struct mail_list * resp;
+ int r;
+ int res;
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(cur = clist_begin(imap_list) ; cur != NULL ; cur = clist_next(cur)) {
+ struct mailimap_mailbox_list * mb_list;
+ char * new_mb;
+
+ mb_list = clist_content(cur);
+
+ new_mb = strdup(mb_list->mb_name);
+ if (new_mb == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, new_mb);
+ if (r != 0) {
+ free(new_mb);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ resp = mail_list_new(list);
+ if (resp == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = resp;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(list, (clist_func) free, NULL);
+ clist_free(list);
+ err:
+ return res;
+}
+
+int
+section_to_imap_section(struct mailmime_section * section, int type,
+ struct mailimap_section ** result)
+{
+ struct mailimap_section_part * section_part;
+ struct mailimap_section * imap_section;
+ clist * list;
+ clistiter * cur;
+ int r;
+ int res;
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(cur = clist_begin(section->sec_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ uint32_t value;
+ uint32_t * id;
+
+ value = * (uint32_t *) clist_content(cur);
+ id = malloc(sizeof(* id));
+ if (id == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ * id = value;
+ r = clist_append(list, id);
+ if (r != 0) {
+ res = MAIL_ERROR_MEMORY;
+ free(id);
+ goto free_list;
+ }
+ }
+
+ section_part = mailimap_section_part_new(list);
+ if (section_part == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ imap_section = NULL;
+
+ switch (type) {
+ case IMAP_SECTION_MESSAGE:
+ imap_section = mailimap_section_new_part(section_part);
+ break;
+ case IMAP_SECTION_HEADER:
+ imap_section = mailimap_section_new_part_header(section_part);
+ break;
+ case IMAP_SECTION_MIME:
+ imap_section = mailimap_section_new_part_mime(section_part);
+ break;
+ case IMAP_SECTION_BODY:
+ imap_section = mailimap_section_new_part_text(section_part);
+ break;
+ }
+
+ if (imap_section == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_part;
+ }
+
+ * result = imap_section;
+
+ return MAIL_NO_ERROR;
+
+ free_part:
+ mailimap_section_part_free(section_part);
+ free_list:
+ if (list != NULL) {
+ clist_foreach(list, (clist_func) free, NULL);
+ clist_free(list);
+ }
+ err:
+ return res;
+}
+
+
+
+static int
+imap_body_media_basic_to_content_type(struct mailimap_media_basic *
+ media_basic,
+ struct mailimap_body_fld_param *
+ body_parameter,
+ struct mailmime_content ** result)
+{
+ struct mailmime_content * content;
+ struct mailmime_type * mime_type;
+ struct mailmime_discrete_type * discrete_type;
+ struct mailmime_composite_type * composite_type;
+ char * discrete_type_extension;
+ int discrete_type_type;
+ int composite_type_type;
+ int mime_type_type;
+ char * subtype;
+ int r;
+ int res;
+
+ discrete_type = NULL;
+ composite_type = NULL;
+ discrete_type_extension = NULL;
+ subtype = NULL;
+ discrete_type_type = 0;
+ composite_type_type = 0;
+ mime_type_type = 0;
+
+ switch (media_basic->med_type) {
+ case MAILIMAP_MEDIA_BASIC_APPLICATION:
+ mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
+ discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION;
+ break;
+
+ case MAILIMAP_MEDIA_BASIC_AUDIO:
+ mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
+ discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION;
+ break;
+
+ case MAILIMAP_MEDIA_BASIC_IMAGE:
+ mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
+ discrete_type_type = MAILMIME_DISCRETE_TYPE_IMAGE;
+ break;
+
+ case MAILIMAP_MEDIA_BASIC_MESSAGE:
+ mime_type_type = MAILMIME_TYPE_COMPOSITE_TYPE;
+ composite_type_type = MAILMIME_COMPOSITE_TYPE_MESSAGE;
+ break;
+
+ case MAILIMAP_MEDIA_BASIC_VIDEO:
+ mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
+ discrete_type_type = MAILMIME_DISCRETE_TYPE_VIDEO;
+ break;
+
+ case MAILIMAP_MEDIA_BASIC_OTHER:
+ mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
+ discrete_type_type = MAILMIME_DISCRETE_TYPE_EXTENSION;
+ discrete_type_extension = media_basic->med_basic_type;
+ if (discrete_type_extension == NULL) {
+ res = MAIL_ERROR_INVAL;
+ goto err;
+ }
+
+ break;
+
+ default:
+ res = MAIL_ERROR_INVAL;
+ goto err;
+ }
+
+ switch (mime_type_type) {
+ case MAILMIME_TYPE_DISCRETE_TYPE:
+ if (discrete_type_extension != NULL) {
+ discrete_type_extension = strdup(discrete_type_extension);
+ if (discrete_type_extension == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ }
+
+ discrete_type = mailmime_discrete_type_new(discrete_type_type,
+ discrete_type_extension);
+ if (discrete_type == NULL) {
+ if (discrete_type_extension != NULL)
+ free(discrete_type_extension);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ break;
+
+ case MAILMIME_TYPE_COMPOSITE_TYPE:
+ composite_type = mailmime_composite_type_new(composite_type_type,
+ NULL);
+ if (composite_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ break;
+
+ default:
+ res = MAIL_ERROR_INVAL;
+ goto err;
+ }
+
+ mime_type = mailmime_type_new(mime_type_type, discrete_type, composite_type);
+ if (mime_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ r = imap_body_parameter_to_content(body_parameter, media_basic->med_subtype,
+ mime_type, &content);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_type;
+ }
+
+ * result = content;
+
+ return MAIL_NO_ERROR;
+
+ free_type:
+ mailmime_type_free(mime_type);
+ free:
+ if (discrete_type != NULL)
+ mailmime_discrete_type_free(discrete_type);
+ if (composite_type != NULL)
+ mailmime_composite_type_free(composite_type);
+ err:
+ return res;
+}
+
+static int
+imap_disposition_to_mime_disposition(struct mailimap_body_fld_dsp * imap_dsp,
+ struct mailmime_disposition ** result)
+{
+ size_t cur_token;
+ int r;
+ struct mailmime_disposition_type * dsp_type;
+ struct mailmime_disposition * dsp;
+ clist * parameters;
+ int res;
+
+ cur_token = 0;
+ r = mailmime_disposition_type_parse(imap_dsp->dsp_type,
+ strlen(imap_dsp->dsp_type), &cur_token, &dsp_type);
+ if (r != MAILIMF_NO_ERROR) {
+ res = MAILIMF_ERROR_PARSE;
+ goto err;
+ }
+
+ parameters = clist_new();
+ if (parameters == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ if (imap_dsp->dsp_attributes != NULL) {
+ clistiter * cur;
+
+ for(cur = clist_begin(imap_dsp->dsp_attributes->pa_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct mailimap_single_body_fld_param * imap_param;
+ struct mailmime_disposition_parm * dsp_param;
+ struct mailmime_parameter * param;
+ char * filename;
+ char * creation_date;
+ char * modification_date;
+ char * read_date;
+ size_t size;
+ int type;
+
+ imap_param = clist_content(cur);
+
+ filename = NULL;
+ creation_date = NULL;
+ modification_date = NULL;
+ read_date = NULL;
+ size = 0;
+ param = NULL;
+
+ type = mailmime_disposition_guess_type(imap_param->pa_name,
+ strlen(imap_param->pa_name), 0);
+
+ switch (type) {
+ case MAILMIME_DISPOSITION_PARM_FILENAME:
+ if (strcasecmp(imap_param->pa_name, "filename") != 0) {
+ type = MAILMIME_DISPOSITION_PARM_PARAMETER;
+ break;
+ }
+ filename = strdup(imap_param->pa_value);
+ if (filename == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_dsp_type;
+ }
+ break;
+
+ case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
+ if (strcasecmp(imap_param->pa_name, "creation-date") != 0) {
+ type = MAILMIME_DISPOSITION_PARM_PARAMETER;
+ break;
+ }
+ creation_date = strdup(imap_param->pa_value);
+ if (creation_date == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_dsp_type;
+ }
+ break;
+
+ case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
+ if (strcasecmp(imap_param->pa_name, "modification-date") != 0) {
+ type = MAILMIME_DISPOSITION_PARM_PARAMETER;
+ break;
+ }
+ modification_date = strdup(imap_param->pa_value);
+ if (modification_date == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_dsp_type;
+ }
+ break;
+
+ case MAILMIME_DISPOSITION_PARM_READ_DATE:
+ if (strcasecmp(imap_param->pa_name, "read-date") != 0) {
+ type = MAILMIME_DISPOSITION_PARM_PARAMETER;
+ break;
+ }
+ read_date = strdup(imap_param->pa_value);
+ if (read_date == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_dsp_type;
+ }
+ break;
+
+ case MAILMIME_DISPOSITION_PARM_SIZE:
+ if (strcasecmp(imap_param->pa_name, "size") != 0) {
+ type = MAILMIME_DISPOSITION_PARM_PARAMETER;
+ break;
+ }
+ size = strtoul(imap_param->pa_value, NULL, 10);
+ break;
+ }
+
+ if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) {
+ char * name;
+ char * value;
+
+ name = strdup(imap_param->pa_name);
+ if (name == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_dsp_type;
+ }
+
+ value = strdup(imap_param->pa_value);
+ if (value == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ free(name);
+ goto free_dsp_type;
+ }
+
+ param = mailmime_parameter_new(name, value);
+ if (param == NULL) {
+ free(value);
+ free(name);
+ res = MAIL_ERROR_MEMORY;
+ goto free_dsp_type;
+ }
+
+ }
+
+ dsp_param = mailmime_disposition_parm_new(type, filename,
+ creation_date,
+ modification_date,
+ read_date,
+ size, param);
+ if (dsp_param == NULL) {
+ if (filename != NULL)
+ free(filename);
+ if (creation_date != NULL)
+ free(creation_date);
+ if (modification_date != NULL)
+ free(modification_date);
+ if (read_date != NULL)
+ free(read_date);
+ if (param != NULL)
+ mailmime_parameter_free(param);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(parameters, dsp_param);
+ if (r != 0) {
+ mailmime_disposition_parm_free(dsp_param);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ dsp = mailmime_disposition_new(dsp_type, parameters);
+ if (dsp == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = dsp;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(parameters,
+ (clist_func) mailmime_disposition_parm_free, NULL);
+ clist_free(parameters);
+ free_dsp_type:
+ mailmime_disposition_type_free(dsp_type);
+ err:
+ return res;
+}
+
+static int
+imap_language_to_mime_language(struct mailimap_body_fld_lang * imap_lang,
+ struct mailmime_language ** result)
+{
+ clist * list;
+ clistiter * cur;
+ int res;
+ char * single;
+ int r;
+ struct mailmime_language * lang;
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ switch (imap_lang->lg_type) {
+ case MAILIMAP_BODY_FLD_LANG_SINGLE:
+ if (imap_lang->lg_data.lg_single != NULL) {
+ single = strdup(imap_lang->lg_data.lg_single);
+ if (single == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+ r = clist_append(list, single);
+ if (r < 0) {
+ free(single);
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+ }
+
+ break;
+
+ case MAILIMAP_BODY_FLD_LANG_LIST:
+ for(cur = clist_begin(imap_lang->lg_data.lg_list) ;
+ cur != NULL ; cur = clist_next(cur)) {
+ single = strdup(clist_content(cur));
+ if (single == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+ r = clist_append(list, single);
+ if (r < 0) {
+ free(single);
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+ }
+ }
+
+ lang = mailmime_language_new(list);
+ if (lang == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ * result = lang;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ clist_foreach(list, (clist_func) free, NULL);
+ clist_free(list);
+ err:
+ return res;
+}
+
+static int
+imap_body_fields_to_mime_fields(struct mailimap_body_fields * body_fields,
+ struct mailimap_body_fld_dsp * imap_dsp,
+ struct mailimap_body_fld_lang * imap_lang,
+ struct mailmime_fields ** result,
+ uint32_t * pbody_size)
+{
+ struct mailmime_field * mime_field;
+ struct mailmime_fields * mime_fields;
+ clist * list;
+ char * id;
+ struct mailmime_mechanism * encoding;
+ char * description;
+ struct mailmime_disposition * dsp;
+ struct mailmime_language * lang;
+ int type;
+ int r;
+ int res;
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ if (body_fields != NULL) {
+
+ if (pbody_size != NULL)
+ * pbody_size = body_fields->bd_size;
+
+ if (body_fields->bd_id != NULL) {
+ type = MAILMIME_FIELD_ID;
+ id = strdup(body_fields->bd_id);
+ if (id == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ mime_field = mailmime_field_new(type, NULL,
+ NULL, id, NULL, 0, NULL, NULL);
+ if (mime_field == NULL) {
+ free(id);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, mime_field);
+ if (r != 0) {
+ mailmime_field_free(mime_field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ if (body_fields->bd_description != NULL) {
+ type = MAILMIME_FIELD_DESCRIPTION;
+ description = strdup(body_fields->bd_description);
+ if (description == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ mime_field = mailmime_field_new(type, NULL,
+ NULL, NULL, description, 0, NULL, NULL);
+ if (mime_field == NULL) {
+ free(description);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, mime_field);
+ if (r != 0) {
+ mailmime_field_free(mime_field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ if (body_fields->bd_encoding != NULL) {
+ char * encoding_value;
+ int encoding_type;
+
+ type = MAILMIME_FIELD_TRANSFER_ENCODING;
+
+ encoding_value = NULL;
+ switch (body_fields->bd_encoding->enc_type) {
+ case MAILIMAP_BODY_FLD_ENC_7BIT:
+ encoding_type = MAILMIME_MECHANISM_7BIT;
+ break;
+ case MAILIMAP_BODY_FLD_ENC_8BIT:
+ encoding_type = MAILMIME_MECHANISM_8BIT;
+ break;
+ case MAILIMAP_BODY_FLD_ENC_BINARY:
+ encoding_type = MAILMIME_MECHANISM_BINARY;
+ break;
+ case MAILIMAP_BODY_FLD_ENC_BASE64:
+ encoding_type = MAILMIME_MECHANISM_BASE64;
+ break;
+ case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE:
+ encoding_type = MAILMIME_MECHANISM_QUOTED_PRINTABLE;
+ break;
+ case MAILIMAP_BODY_FLD_ENC_OTHER:
+ encoding_type = MAILMIME_MECHANISM_TOKEN;
+ encoding_value = strdup(body_fields->bd_encoding->enc_value);
+ if (encoding_value == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ break;
+ default:
+ res = MAIL_ERROR_INVAL;
+ goto free_list;
+ }
+
+ encoding = mailmime_mechanism_new(encoding_type, encoding_value);
+ if (encoding == NULL) {
+ if (encoding_value != NULL)
+ free(encoding_value);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ mime_field = mailmime_field_new(type, NULL,
+ encoding, NULL, NULL, 0, NULL, NULL);
+ if (mime_field == NULL) {
+ mailmime_mechanism_free(encoding);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, mime_field);
+ if (r != 0) {
+ mailmime_field_free(mime_field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ if (imap_dsp != NULL) {
+ r = imap_disposition_to_mime_disposition(imap_dsp, &dsp);
+ if (r != MAIL_ERROR_PARSE) {
+ if (r != MAIL_NO_ERROR) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ type = MAILMIME_FIELD_DISPOSITION;
+
+ mime_field = mailmime_field_new(type, NULL,
+ NULL, NULL, NULL, 0, dsp, NULL);
+ if (mime_field == NULL) {
+ mailmime_disposition_free(dsp);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, mime_field);
+ if (r != 0) {
+ mailmime_field_free(mime_field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ if (imap_lang != NULL) {
+ r = imap_language_to_mime_language(imap_lang, &lang);
+ if (r != MAIL_NO_ERROR) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ type = MAILMIME_FIELD_LANGUAGE;
+
+ mime_field = mailmime_field_new(type, NULL,
+ NULL, NULL, NULL, 0, NULL, lang);
+ if (mime_field == NULL) {
+ mailmime_language_free(lang);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, mime_field);
+ if (r != 0) {
+ mailmime_field_free(mime_field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ mime_fields = mailmime_fields_new(list);
+ if (mime_fields == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = mime_fields;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(list, (clist_func) mailmime_fields_free, NULL);
+ clist_free(list);
+ err:
+ return res;
+}
+
+static int
+imap_body_type_basic_to_body(struct mailimap_body_type_basic *
+ imap_type_basic,
+ struct mailimap_body_ext_1part *
+ body_ext_1part,
+ struct mailmime ** result)
+{
+ struct mailmime_content * content;
+ struct mailmime_fields * mime_fields;
+ struct mailmime * body;
+ int r;
+ int res;
+ uint32_t mime_size;
+
+ r = imap_body_media_basic_to_content_type(imap_type_basic->bd_media_basic,
+ imap_type_basic->bd_fields->bd_parameter, &content);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ if (body_ext_1part != NULL)
+ r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields,
+ body_ext_1part->bd_disposition,
+ body_ext_1part->bd_language,
+ &mime_fields, &mime_size);
+ else
+ r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields,
+ NULL, NULL,
+ &mime_fields, &mime_size);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_content;
+ }
+
+ body = mailmime_new(MAILMIME_SINGLE, NULL,
+ mime_size, mime_fields, content,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+
+ if (body == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_fields;
+ }
+
+ * result = body;
+
+ return MAIL_NO_ERROR;
+
+ free_fields:
+ mailmime_fields_free(mime_fields);
+ free_content:
+ mailmime_content_free(content);
+ err:
+ return res;
+}
+
+static int
+imap_body_type_text_to_body(struct mailimap_body_type_text *
+ imap_type_text,
+ struct mailimap_body_ext_1part *
+ body_ext_1part,
+ struct mailmime ** result)
+{
+ struct mailmime_content * content;
+ struct mailmime_fields * mime_fields;
+ struct mailmime * body;
+ int r;
+ int res;
+ uint32_t mime_size;
+
+ r = imap_body_type_text_to_content_type(imap_type_text->bd_media_text,
+ imap_type_text->bd_fields->bd_parameter,
+ &content);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ if (body_ext_1part == NULL) {
+ r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields,
+ NULL, NULL,
+ &mime_fields, &mime_size);
+ }
+ else {
+ r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields,
+ body_ext_1part->bd_disposition,
+ body_ext_1part->bd_language,
+ &mime_fields, &mime_size);
+ }
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_content;
+ }
+
+ body = mailmime_new(MAILMIME_SINGLE, NULL,
+ mime_size, mime_fields, content,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+
+ if (body == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_fields;
+ }
+
+ * result = body;
+
+ return MAIL_NO_ERROR;
+
+ free_fields:
+ mailmime_fields_free(mime_fields);
+ free_content:
+ mailmime_content_free(content);
+ err:
+ return res;
+}
+
+static int
+imap_body_parameter_to_content(struct mailimap_body_fld_param *
+ body_parameter,
+ char * subtype,
+ struct mailmime_type * mime_type,
+ struct mailmime_content ** result)
+{
+ clist * parameters;
+ char * new_subtype;
+ struct mailmime_content * content;
+ int r;
+ int res;
+
+ new_subtype = strdup(subtype);
+ if (new_subtype == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ parameters = clist_new();
+ if (parameters == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_subtype;
+ }
+
+ if (body_parameter != NULL) {
+ clistiter * cur;
+
+ for(cur = clist_begin(body_parameter->pa_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct mailimap_single_body_fld_param * imap_param;
+ struct mailmime_parameter * param;
+ char * name;
+ char * value;
+
+ imap_param = clist_content(cur);
+ name = strdup(imap_param->pa_name);
+ if (name == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_parameters;
+ }
+
+ value = strdup(imap_param->pa_value);
+ if (value == NULL) {
+ free(name);
+ res = MAIL_ERROR_MEMORY;
+ goto free_parameters;
+ }
+
+ param = mailmime_parameter_new(name, value);
+ if (param == NULL) {
+ free(value);
+ free(name);
+ res = MAIL_ERROR_MEMORY;
+ goto free_parameters;
+ }
+
+ r = clist_append(parameters, param);
+ if (r != 0) {
+ mailmime_parameter_free(param);
+ res = MAIL_ERROR_MEMORY;
+ goto free_parameters;
+ }
+ }
+ }
+
+ content = mailmime_content_new(mime_type, new_subtype, parameters);
+ if (content == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_parameters;
+ }
+
+ * result = content;
+
+ return MAIL_NO_ERROR;
+
+ free_parameters:
+ clist_foreach(parameters, (clist_func) mailmime_parameter_free, NULL);
+ clist_free(parameters);
+ free_subtype:
+ free(new_subtype);
+ err:
+ return res;
+}
+
+static int
+imap_body_type_text_to_content_type(char * subtype,
+ struct mailimap_body_fld_param *
+ body_parameter,
+ struct mailmime_content ** result)
+{
+ struct mailmime_content * content;
+ struct mailmime_type * mime_type;
+ struct mailmime_discrete_type * discrete_type;
+ int r;
+ int res;
+
+ discrete_type = NULL;
+
+ discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT,
+ NULL);
+ if (discrete_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE,
+ discrete_type, NULL);
+ if (mime_type == NULL) {
+ mailmime_discrete_type_free(discrete_type);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = imap_body_parameter_to_content(body_parameter, subtype,
+ mime_type, &content);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_type;
+ }
+
+ * result = content;
+
+ return MAIL_NO_ERROR;
+
+ free_type:
+ mailmime_type_free(mime_type);
+ err:
+ return res;
+}
+
+
+static int
+imap_body_type_msg_to_body(struct mailimap_body_type_msg *
+ imap_type_msg,
+ struct mailimap_body_ext_1part *
+ body_ext_1part,
+ struct mailmime ** result)
+{
+ struct mailmime * body;
+ struct mailmime * msg_body;
+ struct mailmime_fields * mime_fields;
+ struct mailmime_composite_type * composite_type;
+ struct mailmime_type * mime_type;
+ struct mailmime_content * content_type;
+ struct mailimf_fields * fields;
+ int r;
+ int res;
+ uint32_t mime_size;
+
+ r = imap_body_fields_to_mime_fields(imap_type_msg->bd_fields,
+ body_ext_1part->bd_disposition, body_ext_1part->bd_language,
+ &mime_fields, &mime_size);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ r = imap_env_to_fields(imap_type_msg->bd_envelope, NULL, 0, &fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mime_fields;
+ }
+
+ r = imap_body_to_body(imap_type_msg->bd_body, &msg_body);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_fields;
+ }
+
+ composite_type =
+ mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE,
+ NULL);
+ if (composite_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_fields;
+ }
+
+ mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE,
+ NULL, composite_type);
+ if (mime_type == NULL) {
+ mailmime_composite_type_free(composite_type);
+ res = MAIL_ERROR_MEMORY;
+ goto free_fields;
+ }
+
+ r = imap_body_parameter_to_content(imap_type_msg->bd_fields->bd_parameter,
+ "rfc822", mime_type, &content_type);
+ if (r != MAIL_NO_ERROR) {
+ mailmime_type_free(mime_type);
+ res = MAIL_ERROR_MEMORY;
+ goto free_fields;
+ }
+
+ body = mailmime_new(MAILMIME_MESSAGE, NULL,
+ mime_size, mime_fields, content_type,
+ NULL, NULL, NULL, NULL, fields, msg_body);
+
+ if (body == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_content;
+ }
+
+ * result = body;
+
+ return MAIL_NO_ERROR;
+
+ free_content:
+ mailmime_content_free(content_type);
+ free_fields:
+ mailimf_fields_free(fields);
+ free_mime_fields:
+ mailmime_fields_free(mime_fields);
+ err:
+ return res;
+}
+
+
+static int
+imap_body_type_1part_to_body(struct mailimap_body_type_1part *
+ type_1part,
+ struct mailmime ** result)
+{
+ struct mailmime * body;
+ int r;
+ int res;
+
+ switch (type_1part->bd_type) {
+ case MAILIMAP_BODY_TYPE_1PART_BASIC:
+ r = imap_body_type_basic_to_body(type_1part->bd_data.bd_type_basic,
+ type_1part->bd_ext_1part,
+ &body);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ break;
+ case MAILIMAP_BODY_TYPE_1PART_MSG:
+ r = imap_body_type_msg_to_body(type_1part->bd_data.bd_type_msg,
+ type_1part->bd_ext_1part,
+ &body);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ break;
+ case MAILIMAP_BODY_TYPE_1PART_TEXT:
+ r = imap_body_type_text_to_body(type_1part->bd_data.bd_type_text,
+ type_1part->bd_ext_1part,
+ &body);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ break;
+ }
+
+ * result = body;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+imap_body_type_mpart_to_body(struct mailimap_body_type_mpart *
+ type_mpart,
+ struct mailmime ** result)
+{
+ struct mailmime_fields * mime_fields;
+ struct mailmime_composite_type * composite_type;
+ struct mailmime_type * mime_type;
+ struct mailmime_content * content_type;
+ struct mailmime * body;
+ clistiter * cur;
+ clist * list;
+ int r;
+ int res;
+ uint32_t mime_size;
+
+ r = imap_body_fields_to_mime_fields(NULL,
+ type_mpart->bd_ext_mpart->bd_disposition,
+ type_mpart->bd_ext_mpart->bd_language,
+ &mime_fields, &mime_size);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ composite_type =
+ mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART,
+ NULL);
+ if (composite_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_fields;
+ }
+
+ mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE,
+ NULL, composite_type);
+ if (mime_type == NULL) {
+ mailmime_composite_type_free(composite_type);
+ res = MAIL_ERROR_MEMORY;
+ goto free_fields;
+ }
+
+ r = imap_body_parameter_to_content(type_mpart->bd_ext_mpart->bd_parameter,
+ type_mpart->bd_media_subtype,
+ mime_type, &content_type);
+ if (r != MAIL_NO_ERROR) {
+ mailmime_type_free(mime_type);
+ res = r;
+ goto free_fields;
+ }
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_content;
+ }
+
+ for(cur = clist_begin(type_mpart->bd_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct mailimap_body * imap_body;
+ struct mailmime * sub_body;
+
+ imap_body = clist_content(cur);
+
+ r = imap_body_to_body(imap_body, &sub_body);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ r = clist_append(list, sub_body);
+ if (r != 0) {
+ mailmime_free(sub_body);
+ res = r;
+ goto free_list;
+ }
+ }
+
+ body = mailmime_new(MAILMIME_MULTIPLE, NULL,
+ mime_size, mime_fields, content_type,
+ NULL, NULL, NULL, list, NULL, NULL);
+
+ if (body == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ * result = body;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(list, (clist_func) mailmime_free, NULL);
+ clist_free(list);
+ free_content:
+ mailmime_content_free(content_type);
+ free_fields:
+ mailmime_fields_free(mime_fields);
+ err:
+ return res;
+}
+
+
+int imap_body_to_body(struct mailimap_body * imap_body,
+ struct mailmime ** result)
+{
+ struct mailmime * body;
+ int r;
+ int res;
+
+ switch (imap_body->bd_type) {
+ case MAILIMAP_BODY_1PART:
+ r = imap_body_type_1part_to_body(imap_body->bd_data.bd_body_1part, &body);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+ break;
+ case MAILIMAP_BODY_MPART:
+ r = imap_body_type_mpart_to_body(imap_body->bd_data.bd_body_mpart, &body);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+ break;
+ default:
+ return MAIL_ERROR_INVAL;
+ }
+
+ * result = body;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+int imap_address_to_mailbox(struct mailimap_address * imap_addr,
+ struct mailimf_mailbox ** result)
+{
+ char * dsp_name;
+ char * addr;
+ struct mailimf_mailbox * mb;
+ int res;
+
+ if (imap_addr->ad_personal_name == NULL)
+ dsp_name = NULL;
+ else {
+ dsp_name = strdup(imap_addr->ad_personal_name);
+ if (dsp_name == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ }
+
+ if (imap_addr->ad_host_name == NULL) {
+ addr = strdup(imap_addr->ad_mailbox_name);
+ if (addr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_name;
+ }
+ }
+ else {
+ addr = malloc(strlen(imap_addr->ad_mailbox_name) +
+ strlen(imap_addr->ad_host_name) + 2);
+ if (addr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_name;
+ }
+ strcpy(addr, imap_addr->ad_mailbox_name);
+ strcat(addr, "@");
+ strcat(addr, imap_addr->ad_host_name);
+ }
+
+ mb = mailimf_mailbox_new(dsp_name, addr);
+ if (mb == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_addr;
+ }
+
+ * result = mb;
+
+ return MAIL_NO_ERROR;
+
+ free_addr:
+ free(addr);
+ free_name:
+ free(dsp_name);
+ err:
+ return res;
+}
+
+int imap_address_to_address(struct mailimap_address * imap_addr,
+ struct mailimf_address ** result)
+{
+ struct mailimf_address * addr;
+ struct mailimf_mailbox * mb;
+ int r;
+ int res;
+
+ r = imap_address_to_mailbox(imap_addr, &mb);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
+ if (addr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mb;
+ }
+
+ * result = addr;
+
+ return MAIL_NO_ERROR;
+
+ free_mb:
+ mailimf_mailbox_free(mb);
+ err:
+ return res;
+}
+
+int
+imap_mailbox_list_to_mailbox_list(clist * imap_mailbox_list,
+ struct mailimf_mailbox_list ** result)
+{
+ clistiter * cur;
+ clist * list;
+ struct mailimf_mailbox_list * mb_list;
+ int r;
+ int res;
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct mailimap_address * imap_addr;
+ struct mailimf_mailbox * mb;
+
+ imap_addr = clist_content(cur);
+
+ if (imap_addr->ad_mailbox_name == NULL)
+ continue;
+
+ r = imap_address_to_mailbox(imap_addr, &mb);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ r = clist_append(list, mb);
+ if (r != 0) {
+ mailimf_mailbox_free(mb);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ mb_list = mailimf_mailbox_list_new(list);
+ if (mb_list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = mb_list;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
+ clist_free(list);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+
+
+/*
+ at exit, imap_mb_list will fall on the last element of the group,
+ where mailbox name will be NIL, so that imap_mailbox_list_to_address_list
+ can continue
+*/
+
+static int imap_mailbox_list_to_group(clist * imap_mb_list, clistiter ** iter,
+ struct mailimf_group ** result)
+{
+ clistiter * imap_mailbox_listiter;
+ clist * list;
+ struct mailimf_group * group;
+ struct mailimap_address * imap_addr;
+ char * group_name;
+ clistiter * cur;
+ struct mailimf_mailbox_list * mb_list;
+ int r;
+ int res;
+
+ imap_mailbox_listiter = * iter;
+
+ imap_addr = clist_content(imap_mailbox_listiter);
+ if (imap_addr->ad_mailbox_name == NULL) {
+ res = MAIL_ERROR_INVAL;
+ goto err;
+ }
+
+ group_name = strdup(imap_addr->ad_mailbox_name);
+ if (group_name == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_group_name;
+ }
+
+ for(cur = clist_next(imap_mailbox_listiter) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct mailimf_mailbox * mb;
+
+ imap_addr = clist_content(cur);
+
+ if (imap_addr->ad_mailbox_name == NULL) {
+ break;
+ }
+
+ r = imap_address_to_mailbox(imap_addr, &mb);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ r = clist_append(list, mb);
+ if (r != 0) {
+ mailimf_mailbox_free(mb);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ mb_list = mailimf_mailbox_list_new(list);
+ if (mb_list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ group = mailimf_group_new(group_name, mb_list);
+ if (group == NULL) {
+ mailimf_mailbox_list_free(mb_list);
+ res = MAIL_ERROR_MEMORY;
+ goto free_group_name;
+ }
+
+ * result = group;
+ * iter = cur;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
+ clist_free(list);
+ free_group_name:
+ free(group_name);
+ err:
+ return res;
+}
+
+int
+imap_mailbox_list_to_address_list(clist * imap_mailbox_list,
+ struct mailimf_address_list ** result)
+{
+ clistiter * cur;
+ clist * list;
+ struct mailimf_address_list * addr_list;
+ int r;
+ int res;
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct mailimap_address * imap_addr;
+ struct mailimf_address * addr;
+
+ imap_addr = clist_content(cur);
+
+ if (imap_addr->ad_mailbox_name == NULL)
+ continue;
+
+ if ((imap_addr->ad_host_name == NULL) &&
+ (imap_addr->ad_mailbox_name != NULL)) {
+ struct mailimf_group * group;
+
+ r = imap_mailbox_list_to_group(imap_mailbox_list, &cur, &group);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ addr = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, group);
+ if (addr == NULL) {
+ mailimf_group_free(group);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ else {
+ r = imap_address_to_address(imap_addr, &addr);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+ }
+
+ r = clist_append(list, addr);
+ if (r != 0) {
+ mailimf_address_free(addr);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ addr_list = mailimf_address_list_new(list);
+ if (addr_list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = addr_list;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(list, (clist_func) mailimf_address_free, NULL);
+ clist_free(list);
+ err:
+ return res;
+}
+
+
+int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type)
+{
+ struct mailimap_fetch_att * fetch_att;
+ int res;
+ int r;
+ char * header;
+ clist * hdrlist;
+ struct mailimap_header_list * imap_hdrlist;
+ struct mailimap_section * section;
+
+ fetch_att = mailimap_fetch_att_new_envelope();
+ if (fetch_att == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ 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 err;
+ }
+
+ header = strdup("References");
+ if (header == NULL) {
+ mailimap_fetch_att_free(fetch_att);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ hdrlist = clist_new();
+ if (hdrlist == NULL) {
+ free(header);
+ mailimap_fetch_att_free(fetch_att);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = clist_append(hdrlist, header);
+ if (r < 0) {
+ free(header);
+ clist_foreach(hdrlist, (clist_func) free, NULL);
+ clist_free(hdrlist);
+ mailimap_fetch_att_free(fetch_att);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ imap_hdrlist = mailimap_header_list_new(hdrlist);
+ if (imap_hdrlist == 0) {
+ clist_foreach(hdrlist, (clist_func) free, NULL);
+ clist_free(hdrlist);
+ mailimap_fetch_att_free(fetch_att);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ section = mailimap_section_new_header_fields(imap_hdrlist);
+ if (section == NULL) {
+ mailimap_header_list_free(imap_hdrlist);
+ mailimap_fetch_att_free(fetch_att);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ fetch_att = mailimap_fetch_att_new_body_peek_section(section);
+ if (fetch_att == NULL) {
+ mailimap_section_free(section);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ 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 err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+
+int imap_env_to_fields(struct mailimap_envelope * env,
+ char * ref_str, size_t ref_size,
+ struct mailimf_fields ** result)
+{
+ clist * list;
+ struct mailimf_field * field;
+ int r;
+ struct mailimf_fields * fields;
+ int res;
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ if (env->env_date != NULL) {
+ size_t cur_token;
+ struct mailimf_date_time * date_time;
+
+ cur_token = 0;
+ r = mailimf_date_time_parse(env->env_date, strlen(env->env_date),
+ &cur_token, &date_time);
+
+ if (r == MAILIMF_NO_ERROR) {
+ struct mailimf_orig_date * orig;
+
+ orig = mailimf_orig_date_new(date_time);
+ if (orig == NULL) {
+ mailimf_date_time_free(date_time);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, orig, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_orig_date_free(orig);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r != 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ if (env->env_subject != NULL) {
+ char * subject;
+ struct mailimf_subject * subject_field;
+
+ subject = strdup(env->env_subject);
+ if (subject == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+
+ subject_field = mailimf_subject_new(subject);
+ if (subject_field == NULL) {
+ free(subject);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_SUBJECT,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, subject_field, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_subject_free(subject_field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r != 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ if (env->env_from != NULL) {
+ if (env->env_from->frm_list != NULL) {
+ struct mailimf_mailbox_list * mb_list;
+ struct mailimf_from * from;
+
+ r = imap_mailbox_list_to_mailbox_list(env->env_from->frm_list, &mb_list);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ from = mailimf_from_new(mb_list);
+ if (from == NULL) {
+ mailimf_mailbox_list_free(mb_list);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_FROM,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, from,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_from_free(from);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r != 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ if (env->env_sender != NULL) {
+ if (env->env_sender->snd_list != NULL) {
+ struct mailimf_sender * sender;
+ struct mailimf_mailbox * mb;
+
+ r = imap_address_to_mailbox(clist_begin(env->env_sender->snd_list)->data, &mb);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ sender = mailimf_sender_new(mb);
+ if (sender == NULL) {
+ mailimf_mailbox_free(mb);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_SENDER,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ sender, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_sender_free(sender);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r != 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ if (env->env_reply_to != NULL) {
+ if (env->env_reply_to->rt_list != NULL) {
+ struct mailimf_address_list * addr_list;
+ struct mailimf_reply_to * reply_to;
+
+ r = imap_mailbox_list_to_address_list(env->env_reply_to->rt_list,
+ &addr_list);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ reply_to = mailimf_reply_to_new(addr_list);
+ if (reply_to == NULL) {
+ mailimf_address_list_free(addr_list);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, reply_to, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_reply_to_free(reply_to);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r != 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ if (env->env_to != NULL) {
+ if (env->env_to->to_list != NULL) {
+ struct mailimf_address_list * addr_list;
+ struct mailimf_to * to;
+
+ r = imap_mailbox_list_to_address_list(env->env_to->to_list, &addr_list);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ to = mailimf_to_new(addr_list);
+ if (to == NULL) {
+ mailimf_address_list_free(addr_list);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_TO,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, to, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_to_free(to);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r != 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ if (env->env_cc != NULL) {
+ if (env->env_cc->cc_list != NULL) {
+ struct mailimf_address_list * addr_list;
+ struct mailimf_cc * cc;
+
+ r = imap_mailbox_list_to_address_list(env->env_cc->cc_list, &addr_list);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ cc = mailimf_cc_new(addr_list);
+ if (cc == NULL) {
+ mailimf_address_list_free(addr_list);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_CC,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, cc, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_cc_free(cc);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r != 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ if (env->env_bcc != NULL) {
+ if (env->env_bcc->bcc_list != NULL) {
+ struct mailimf_address_list * addr_list;
+ struct mailimf_bcc * bcc;
+
+ r = imap_mailbox_list_to_address_list(env->env_bcc->bcc_list,
+ &addr_list);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ bcc = mailimf_bcc_new(addr_list);
+ if (bcc == NULL) {
+ mailimf_address_list_free(addr_list);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_BCC,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, bcc, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_bcc_free(bcc);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r != 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ if (env->env_in_reply_to != NULL) {
+ struct mailimf_in_reply_to * in_reply_to;
+ size_t cur_token;
+ clist * msg_id_list;
+
+ cur_token = 0;
+ r = mailimf_msg_id_list_parse(env->env_in_reply_to,
+ strlen(env->env_in_reply_to), &cur_token, &msg_id_list);
+
+ switch (r) {
+ case MAILIMF_NO_ERROR:
+ in_reply_to = mailimf_in_reply_to_new(msg_id_list);
+ if (in_reply_to == NULL) {
+ clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
+ clist_free(msg_id_list);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ in_reply_to,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_in_reply_to_free(in_reply_to);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r != 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ break;
+
+ case MAILIMF_ERROR_PARSE:
+ break;
+
+ default:
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free_list;
+ }
+ }
+
+ if (env->env_message_id != NULL) {
+ char * id;
+ struct mailimf_message_id * msg_id;
+ size_t cur_token;
+
+ cur_token = 0;
+ r = mailimf_msg_id_parse(env->env_message_id, strlen(env->env_message_id),
+ &cur_token, &id);
+ switch (r) {
+ case MAILIMF_NO_ERROR:
+
+ msg_id = mailimf_message_id_new(id);
+ if (msg_id == NULL) {
+ mailimf_msg_id_free(id);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, msg_id, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_message_id_free(msg_id);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r != 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ break;
+
+ case MAILIMF_ERROR_PARSE:
+ break;
+
+ default:
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free_list;
+ }
+ }
+
+ if (ref_str != NULL) {
+ struct mailimf_references * references;
+ size_t cur_token;
+
+ cur_token = 0;
+ r = mailimf_references_parse(ref_str, ref_size,
+ &cur_token, &references);
+ switch (r) {
+ case MAILIMF_NO_ERROR:
+ field = mailimf_field_new(MAILIMF_FIELD_REFERENCES,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL,
+ references, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_references_free(references);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r < 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ break;
+
+ case MAILIMF_ERROR_PARSE:
+ break;
+
+ default:
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free_list;
+ }
+ }
+
+ fields = mailimf_fields_new(list);
+ if (fields == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = fields;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(list, (clist_func) mailimf_field_free, NULL);
+ clist_free(list);
+ err:
+ return res;
+}
+
+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)
+{
+ clistiter * item_cur;
+ uint32_t uid;
+ struct mailimap_envelope * imap_envelope;
+ char * references;
+ size_t ref_size;
+ struct mailimap_msg_att_dynamic * att_dyn;
+ struct mailimap_body * imap_body;
+
+ uid = 0;
+ imap_envelope = NULL;
+ references = NULL;
+ ref_size = 0;
+ att_dyn = NULL;
+ imap_body = 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);
+
+ switch (item->att_type) {
+ case MAILIMAP_MSG_ATT_ITEM_STATIC:
+ switch (item->att_data.att_static->att_type) {
+ case MAILIMAP_MSG_ATT_BODYSTRUCTURE:
+ if (imap_body == NULL)
+ imap_body = item->att_data.att_static->att_data.att_bodystructure;
+ break;
+
+ case MAILIMAP_MSG_ATT_ENVELOPE:
+ if (imap_envelope == NULL) {
+ imap_envelope = item->att_data.att_static->att_data.att_env;
+ }
+ break;
+
+ case MAILIMAP_MSG_ATT_UID:
+ uid = item->att_data.att_static->att_data.att_uid;
+ break;
+
+ case MAILIMAP_MSG_ATT_BODY_SECTION:
+ if (references == NULL) {
+ references = item->att_data.att_static->att_data.att_body_section->sec_body_part;
+ ref_size = item->att_data.att_static->att_data.att_body_section->sec_length;
+ }
+ break;
+ }
+ break;
+
+ case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
+ if (att_dyn == NULL) {
+ att_dyn = item->att_data.att_dyn;
+ }
+ break;
+ }
+ }
+
+ if (puid != NULL)
+ * puid = uid;
+ if (pimap_envelope != NULL)
+ * pimap_envelope = imap_envelope;
+ if (preferences != NULL)
+ * preferences = references;
+ if (pref_size != NULL)
+ * pref_size = ref_size;
+ if (patt_dyn != NULL)
+ * patt_dyn = att_dyn;
+ if (pimap_body != NULL)
+ * pimap_body = imap_body;
+
+ return MAIL_NO_ERROR;
+}
+
+int
+imap_fetch_result_to_envelop_list(clist * fetch_result,
+ struct mailmessage_list * env_list)
+{
+ clistiter * cur;
+ int r;
+ unsigned int i;
+
+ i = 0;
+
+ for(cur = clist_begin(fetch_result) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct mailimap_msg_att * msg_att;
+ uint32_t uid;
+ struct mailimap_envelope * imap_envelope;
+ struct mailimap_msg_att_dynamic * att_dyn;
+ char * references;
+ size_t ref_size;
+
+ msg_att = clist_content(cur);
+
+ r = imap_get_msg_att_info(msg_att, &uid, &imap_envelope,
+ &references, &ref_size,
+ &att_dyn,
+ NULL);
+
+ if (r == MAIL_NO_ERROR) {
+ if (uid != 0) {
+ while (i < carray_count(env_list->msg_tab)) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (uid == msg->msg_index) {
+ struct mailimf_fields * fields;
+ struct mail_flags * flags;
+
+ if (imap_envelope != NULL) {
+ r = imap_env_to_fields(imap_envelope,
+ references, ref_size, &fields);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_fields = fields;
+ }
+ }
+
+ if (att_dyn != NULL) {
+ r = imap_flags_to_flags(att_dyn, &flags);
+
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_flags = flags;
+ }
+ }
+
+ i ++;
+ break;
+ }
+
+ i ++;
+ }
+ }
+ }
+ }
+
+ return MAIL_NO_ERROR;
+}
+
+
+int mailimf_date_time_to_imap_date(struct mailimf_date_time * date,
+ struct mailimap_date ** result)
+{
+ struct mailimap_date * imap_date;
+
+ imap_date = mailimap_date_new(date->dt_day, date->dt_month, date->dt_year);
+ if (imap_date == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ * result = imap_date;
+
+ return MAIL_NO_ERROR;
+}
+
+
+#if 0
+int mail_search_to_imap_search(struct mail_search_key * key,
+ struct mailimap_search_key ** result)
+{
+ struct mailimap_search_key * imap_key;
+
+ char * bcc;
+ struct mailimap_date * before;
+ char * body;
+ char * cc;
+ char * from;
+ struct mailimap_date * on;
+ struct mailimap_date * since;
+ char * subject;
+ char * text;
+ char * to;
+ char * header_name;
+ char * header_value;
+ size_t larger;
+ struct mailimap_search_key * not;
+ struct mailimap_search_key * or1;
+ struct mailimap_search_key * or2;
+ size_t smaller;
+ clist * multiple;
+ int type;
+ clistiter * cur;
+ int r;
+ int res;
+
+ bcc = NULL;
+ before = NULL;
+ body = NULL;
+ cc = NULL;
+ from = NULL;
+ on = NULL;
+ since = NULL;
+ subject = NULL;
+ text = NULL;
+ to = NULL;
+ header_name = NULL;
+ header_value = NULL;
+ not = NULL;
+ or1 = NULL;
+ or2 = NULL;
+ multiple = NULL;
+ larger = 0;
+ smaller = 0;
+
+ switch (key->sk_type) {
+ case MAIL_SEARCH_KEY_ALL:
+ type = MAILIMAP_SEARCH_KEY_ALL;
+ break;
+
+ case MAIL_SEARCH_KEY_ANSWERED:
+ type = MAILIMAP_SEARCH_KEY_ANSWERED;
+ break;
+
+ case MAIL_SEARCH_KEY_BCC:
+ type = MAILIMAP_SEARCH_KEY_BCC;
+ bcc = strdup(key->sk_bcc);
+ if (bcc == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_BEFORE:
+ type = MAILIMAP_SEARCH_KEY_BEFORE;
+ r = mailimf_date_time_to_imap_date(key->sk_before, &before);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_BODY:
+ type = MAILIMAP_SEARCH_KEY_BODY;
+ body = strdup(key->sk_body);
+ if (body == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_CC:
+ type = MAILIMAP_SEARCH_KEY_CC;
+ cc = strdup(key->sk_cc);
+ if (cc == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_DELETED:
+ type = MAILIMAP_SEARCH_KEY_DELETED;
+ break;
+
+ case MAIL_SEARCH_KEY_FLAGGED:
+ type = MAILIMAP_SEARCH_KEY_FLAGGED;
+ break;
+
+ case MAIL_SEARCH_KEY_FROM:
+ type = MAILIMAP_SEARCH_KEY_FROM;
+ from = strdup(key->sk_from);
+ if (from == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_NEW:
+ type = MAILIMAP_SEARCH_KEY_NEW;
+ break;
+
+ case MAIL_SEARCH_KEY_OLD:
+ type = MAILIMAP_SEARCH_KEY_OLD;
+ break;
+
+ case MAIL_SEARCH_KEY_ON:
+ type = MAILIMAP_SEARCH_KEY_ON;
+ r = mailimf_date_time_to_imap_date(key->sk_on, &on);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_RECENT:
+ type = MAILIMAP_SEARCH_KEY_RECENT;
+ break;
+
+ case MAIL_SEARCH_KEY_SEEN:
+ type = MAILIMAP_SEARCH_KEY_SEEN;
+ break;
+
+ case MAIL_SEARCH_KEY_SINCE:
+ type = MAILIMAP_SEARCH_KEY_SINCE;
+ r = mailimf_date_time_to_imap_date(key->sk_since, &since);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_SUBJECT:
+ type = MAILIMAP_SEARCH_KEY_SUBJECT;
+ subject = strdup(key->sk_subject);
+ if (subject == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_TEXT:
+ type = MAILIMAP_SEARCH_KEY_TEXT;
+ text = strdup(key->sk_text);
+ if (text == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_TO:
+ type = MAILIMAP_SEARCH_KEY_TO;
+ to = strdup(key->sk_to);
+ if (to == NULL) {
+ return MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_UNANSWERED:
+ type = MAILIMAP_SEARCH_KEY_UNANSWERED;
+ break;
+
+ case MAIL_SEARCH_KEY_UNDELETED:
+ type = MAILIMAP_SEARCH_KEY_UNFLAGGED;
+ break;
+
+ case MAIL_SEARCH_KEY_UNFLAGGED:
+ type = MAILIMAP_SEARCH_KEY_UNANSWERED;
+ break;
+
+ case MAIL_SEARCH_KEY_UNSEEN:
+ type = MAILIMAP_SEARCH_KEY_UNSEEN;
+ break;
+
+ case MAIL_SEARCH_KEY_HEADER:
+ type = MAILIMAP_SEARCH_KEY_HEADER;
+ header_name = strdup(key->sk_header_name);
+ if (header_name == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ header_value = strdup(key->sk_header_value);
+ if (header_value == NULL) {
+ free(header_name);
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_LARGER:
+ type = MAILIMAP_SEARCH_KEY_LARGER;
+ larger = key->sk_larger;
+ break;
+
+ case MAIL_SEARCH_KEY_NOT:
+ type = MAILIMAP_SEARCH_KEY_NOT;
+ r = mail_search_to_imap_search(key->sk_not, &not);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_OR:
+ type = MAILIMAP_SEARCH_KEY_OR;
+ r = mail_search_to_imap_search(key->sk_or1, &or1);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+ r = mail_search_to_imap_search(key->sk_or2, &or2);
+ if (r != MAIL_NO_ERROR) {
+ mailimap_search_key_free(or1);
+ res = r;
+ goto err;
+ }
+ break;
+
+ case MAIL_SEARCH_KEY_SMALLER:
+ type = MAILIMAP_SEARCH_KEY_SMALLER;
+ smaller = key->sk_smaller;
+ break;
+
+ case MAIL_SEARCH_KEY_MULTIPLE:
+ multiple = clist_new();
+ if (multiple == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ type = MAILIMAP_SEARCH_KEY_MULTIPLE;
+ for(cur = clist_begin(key->sk_multiple) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct mail_search_key * key_elt;
+ struct mailimap_search_key * imap_key_elt;
+
+ key_elt = clist_content(cur);
+ r = mail_search_to_imap_search(key_elt, &imap_key_elt);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ r = clist_append(multiple, imap_key_elt);
+ if (r != 0) {
+ mailimap_search_key_free(imap_key_elt);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ break;
+
+ free_list:
+ clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL);
+ clist_free(multiple);
+ goto err;
+
+ default:
+ return MAIL_ERROR_INVAL;
+ }
+
+ imap_key = mailimap_search_key_new(type, bcc, before, body, cc, from,
+ NULL, on, since, subject, text,
+ to, NULL, header_name,
+ header_value, larger, not, or1, or2,
+ NULL, NULL, NULL, smaller, NULL,
+ NULL, multiple);
+ if (imap_key == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ * result = imap_key;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ if (bcc != NULL)
+ free(bcc);
+ if (before != NULL)
+ mailimap_date_free(before);
+ if (body != NULL)
+ free(body);
+ if (cc != NULL)
+ free(cc);
+ if (from != NULL)
+ free(from);
+ if (on != NULL)
+ mailimap_date_free(on);
+ if (since != NULL)
+ mailimap_date_free(since);
+ if (subject != NULL)
+ free(subject);
+ if (text != NULL)
+ free(text);
+ if (to != NULL)
+ free(to);
+ if (header_name != NULL)
+ free(header_name);
+ if (header_value != NULL)
+ free(header_value);
+ if (not != NULL)
+ mailimap_search_key_free(not);
+ if (or1 != NULL)
+ mailimap_search_key_free(or1);
+ if (or2 != NULL)
+ mailimap_search_key_free(or2);
+ clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL);
+ clist_free(multiple);
+ err:
+ return res;
+}
+#endif
+
+
+int msg_list_to_imap_set(clist * msg_list,
+ struct mailimap_set ** result)
+{
+ struct mailimap_set * imap_set;
+ clistiter * cur;
+ int previous_valid;
+ uint32_t first_seq;
+ uint32_t previous;
+ int r;
+ int res;
+
+ imap_set = mailimap_set_new_empty();
+ if (imap_set == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ cur = clist_begin(msg_list);
+ previous_valid = FALSE;
+ first_seq = 0;
+ previous = 0;
+ while (1) {
+ uint32_t * pindex;
+
+ if ((cur == NULL) && (previous_valid)) {
+ if (first_seq == previous) {
+ r = mailimap_set_add_single(imap_set, first_seq);
+ if (r != MAILIMAP_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+ }
+ else {
+ r = mailimap_set_add_interval(imap_set, first_seq, previous);
+ if (r != MAILIMAP_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+ }
+ break;
+ }
+
+ pindex = clist_content(cur);
+
+ if (!previous_valid) {
+ first_seq = * pindex;
+ previous_valid = TRUE;
+ previous = * pindex;
+ cur = clist_next(cur);
+ }
+ else {
+ if (* pindex != previous + 1) {
+ if (first_seq == previous) {
+ r = mailimap_set_add_single(imap_set, first_seq);
+ if (r != MAILIMAP_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+ }
+ else {
+ r = mailimap_set_add_interval(imap_set, first_seq, previous);
+ if (r != MAILIMAP_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+ }
+ previous_valid = FALSE;
+ }
+ else {
+ previous = * pindex;
+ cur = clist_next(cur);
+ }
+ }
+ }
+
+ * result = imap_set;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailimap_set_free(imap_set);
+ err:
+ return res;
+}
+
+
+static int
+uid_list_to_env_list(clist * fetch_result,
+ struct mailmessage_list ** result,
+ mailsession * session, mailmessage_driver * driver)
+{
+ clistiter * cur;
+ struct mailmessage_list * env_list;
+ int r;
+ int res;
+ carray * tab;
+ unsigned int i;
+ mailmessage * msg;
+
+ tab = carray_new(128);
+ if (tab == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(cur = clist_begin(fetch_result) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct mailimap_msg_att * msg_att;
+ clistiter * item_cur;
+ uint32_t uid;
+ size_t size;
+
+ msg_att = clist_content(cur);
+
+ uid = 0;
+ size = 0;
+ 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);
+
+ switch (item->att_type) {
+ case 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;
+
+ case MAILIMAP_MSG_ATT_RFC822_SIZE:
+ size = item->att_data.att_static->att_data.att_rfc822_size;
+ break;
+ }
+ break;
+ }
+ }
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = mailmessage_init(msg, session, driver, uid, size);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_msg;
+ }
+
+ r = carray_add(tab, msg, NULL);
+ 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;
+}
+
+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;
+ 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);
+ mailimap_fetch_list_free(fetch_result);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ free_fetch_type:
+ mailimap_fetch_type_free(fetch_type);
+ err:
+ return res;
+}
+
+int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last,
+ struct mail_flags * flags)
+{
+ struct mailimap_store_att_flags * att_flags;
+ struct mailimap_set * set;
+ int r;
+ int res;
+
+ set = mailimap_set_new_interval(first, last);
+ if (set == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = flags_to_imap_flags(flags, &att_flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_set;
+ }
+
+ r = mailimap_uid_store(imap, set, att_flags);
+ if (r != MAILIMAP_NO_ERROR) {
+ res = imap_error_to_mail_error(r);
+ goto free_flag;
+ }
+
+ mailimap_store_att_flags_free(att_flags);
+ mailimap_set_free(set);
+
+ return MAIL_NO_ERROR;
+
+ free_flag:
+ mailimap_store_att_flags_free(att_flags);
+ free_set:
+ mailimap_set_free(set);
+ err:
+ return res;
+}
+
+
+
+
+int imap_get_messages_list(mailimap * imap,
+ mailsession * session, mailmessage_driver * driver,
+ uint32_t first_index,
+ struct mailmessage_list ** result)
+{
+ struct mailmessage_list * env_list;
+ int r;
+ struct mailimap_fetch_att * fetch_att;
+ struct mailimap_fetch_type * fetch_type;
+ struct mailimap_set * set;
+ clist * fetch_result;
+ int res;
+
+ set = mailimap_set_new_interval(first_index, 0);
+ if (set == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
+ if (fetch_type == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_set;
+ }
+
+ 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_rfc822_size();
+ 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 = mailimap_uid_fetch(imap, set,
+ fetch_type, &fetch_result);
+
+ mailimap_fetch_type_free(fetch_type);
+ mailimap_set_free(set);
+
+ if (r != MAILIMAP_NO_ERROR) {
+ res = imap_error_to_mail_error(r);
+ goto err;
+ }
+
+ r = uid_list_to_env_list(fetch_result, &env_list, session, driver);
+ mailimap_fetch_list_free(fetch_result);
+
+ * result = env_list;
+
+ return MAIL_NO_ERROR;
+
+ free_fetch_type:
+ mailimap_fetch_type_free(fetch_type);
+ free_set:
+ mailimap_set_free(set);
+ err:
+ return res;
+}
+
+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;
+ }
+}
+
+int
+imapdriver_get_cached_envelope(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ mailsession * session, mailmessage * msg,
+ struct mailimf_fields ** result)
+{
+#if 0
+ mailsession * imap_session;
+#endif
+ mailimap * imap;
+ int r;
+ struct mailimf_fields * fields;
+ int res;
+ char keyname[PATH_MAX];
+
+#if 0
+ imap_session = cached_session_get_ancestor(session);
+ imap = ((struct imap_session_state_data *) (imap_session->data))->session;
+#endif
+ imap = cached_session_get_imap_session(session);
+
+ generate_key_from_message(keyname, PATH_MAX,
+ msg, MAILIMAP_MSG_ATT_ENVELOPE);
+
+ 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;
+}
+
+int
+imapdriver_write_cached_envelope(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ mailsession * session, mailmessage * msg,
+ struct mailimf_fields * fields)
+{
+ char keyname[PATH_MAX];
+ int r;
+ int res;
+
+ generate_key_from_message(keyname, PATH_MAX,
+ msg, MAILIMAP_MSG_ATT_ENVELOPE);
+
+ 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;
+}
+
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_tools.h b/libetpan/src/driver/implementation/imap/imapdriver_tools.h
new file mode 100644
index 0000000..e15fdda
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_tools.h
@@ -0,0 +1,116 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef 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/libetpan/src/driver/implementation/imap/imapdriver_types.h b/libetpan/src/driver/implementation/imap/imapdriver_types.h
new file mode 100644
index 0000000..00559dc
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_types.h
@@ -0,0 +1,144 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef IMAPDRIVER_TYPES_H
+
+#define IMAPDRIVER_TYPES_H
+
+#include <libetpan/libetpan-config.h>
+
+#include <libetpan/mailimap.h>
+#include <libetpan/maildriver_types.h>
+#include <libetpan/generic_cache_types.h>
+#include <libetpan/mailstorage_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* IMAP driver for session */
+
+struct imap_session_state_data {
+ mailimap * imap_session;
+ char * imap_mailbox;
+ struct mail_flags_store * imap_flags_store;
+};
+
+enum {
+ IMAP_SECTION_MESSAGE,
+ IMAP_SECTION_HEADER,
+ IMAP_SECTION_MIME,
+ IMAP_SECTION_BODY
+};
+
+/* cached IMAP driver for session */
+
+enum {
+ IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
+};
+
+struct imap_cached_session_state_data {
+ mailsession * imap_ancestor;
+ char * imap_quoted_mb;
+ char imap_cache_directory[PATH_MAX];
+ carray * imap_uid_list;
+};
+
+
+/* IMAP storage */
+
+/*
+ imap_mailstorage is the state data specific to the IMAP4rev1 storage.
+
+ - servername this is the name of the IMAP4rev1 server
+
+ - port is the port to connect to, on the server.
+ you give 0 to use the default port.
+
+ - command, if non-NULL the command used to connect to the
+ server instead of allowing normal TCP connections to be used.
+
+ - connection_type is the type of socket layer to use.
+ The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
+ CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS or
+ CONNECTION_TYPE_COMMAND.
+
+ - auth_type is the authenticate mechanism to use.
+ The value can be IMAP_AUTH_TYPE_PLAIN.
+ Other values are not yet implemented.
+
+ - login is the login of the IMAP4rev1 account.
+
+ - password is the password of the IMAP4rev1 account.
+
+ - cached if this value is != 0, a persistant cache will be
+ stored on local system.
+
+ - cache_directory is the location of the cache
+*/
+
+struct imap_mailstorage {
+ 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;
+};
+
+/* this is the type of IMAP4rev1 authentication */
+
+enum {
+ IMAP_AUTH_TYPE_PLAIN, /* plain text authentication */
+ IMAP_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */
+ IMAP_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */
+ IMAP_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */
+ IMAP_AUTH_TYPE_SASL_PLAIN, /* SASL plain */
+ IMAP_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */
+ IMAP_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */
+ IMAP_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/imap/imapstorage.c b/libetpan/src/driver/implementation/imap/imapstorage.c
new file mode 100644
index 0000000..0bf6ec2
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapstorage.c
@@ -0,0 +1,297 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "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(* 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,
+ imap_storage->imap_cache_directory,
+ 0, NULL,
+ &session);
+ switch (r) {
+ case MAIL_NO_ERROR_NON_AUTHENTICATED:
+ case MAIL_NO_ERROR_AUTHENTICATED:
+ case MAIL_NO_ERROR:
+ break;
+ default:
+ res = r;
+ goto err;
+ }
+
+ r = mailstorage_generic_auth(session, r,
+ imap_storage->imap_connection_type,
+ imap_storage->imap_login,
+ imap_storage->imap_password);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ * result = session;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailsession_free(session);
+ err:
+ return res;
+}
+
+static int imap_mailstorage_connect(struct mailstorage * storage)
+{
+ mailsession * session;
+ int r;
+ int res;
+
+ r = imap_connect(storage, &session);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ r = mailsession_select_folder(session, "INBOX");
+ if (r != MAIL_NO_ERROR) {
+ mailsession_logout(session);
+ res = r;
+ goto err;
+ }
+
+ storage->sto_session = session;
+ storage->sto_driver = &imap_mailstorage_driver;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+imap_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result)
+{
+ mailsession * session;
+ int r;
+ int res;
+
+ if (strcasecmp(pathname, "INBOX") == 0) {
+ session = storage->sto_session;
+ }
+ else {
+ r = imap_connect(storage, &session);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ r = mailsession_select_folder(session, pathname);
+ if (r != MAIL_NO_ERROR) {
+ mailsession_logout(session);
+ res = r;
+ goto free;
+ }
+ }
+
+ * result = session;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailsession_free(session);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/imap/imapstorage.h b/libetpan/src/driver/implementation/imap/imapstorage.h
new file mode 100644
index 0000000..929a86e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapstorage.h
@@ -0,0 +1,90 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef IMAPSTORAGE_H
+
+#define IMAPSTORAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libetpan/imapdriver_types.h>
+
+/*
+ imap_mailstorage_init is the constructor for a IMAP4rev1 storage
+
+ @param storage this is the storage to initialize.
+
+ @param servername this is the name of the IMAP4rev1 server
+
+ @param port is the port to connect to, on the server.
+ you give 0 to use the default port.
+
+ @param command the command used to connect to the server instead of
+ allowing normal TCP connections to be used.
+
+ @param connection_type is the type of socket layer to use.
+ The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
+ CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
+ CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
+ CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
+
+ @param auth_type is the authenticate mechanism to use.
+ The value can be IMAP_AUTH_TYPE_PLAIN.
+ Other values are not yet implemented.
+
+ @param login is the login of the IMAP4rev1 account.
+
+ @param password is the password of the IMAP4rev1 account.
+
+ @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
+*/
+
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif