summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation
Side-by-side diff
Diffstat (limited to 'libetpan/src/driver/implementation') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/data-message/data_message_driver.c119
-rw-r--r--libetpan/src/driver/implementation/data-message/data_message_driver.h50
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver.c1134
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver.h53
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver_message.c308
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver_types.h71
-rw-r--r--libetpan/src/driver/implementation/db/dbstorage.c144
-rw-r--r--libetpan/src/driver/implementation/db/dbstorage.h61
-rw-r--r--libetpan/src/driver/implementation/hotmail/hotmailstorage.c62
-rw-r--r--libetpan/src/driver/implementation/hotmail/hotmailstorage.h56
-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
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver.c676
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver.h53
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached.c1158
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached.h53
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c334
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_message.c255
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_tools.c198
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_tools.h53
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_types.h96
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirstorage.c193
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirstorage.h69
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver.c515
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver.h52
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached.c1337
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached.h54
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c361
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_message.c225
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_tools.c435
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_tools.h85
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_types.h107
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxstorage.c192
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxstorage.h69
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver.c875
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached.c1315
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached_message.c338
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_message.c213
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_tools.c484
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_tools.h80
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_types.h100
-rw-r--r--libetpan/src/driver/implementation/mh/mhstorage.c192
-rw-r--r--libetpan/src/driver/implementation/mh/mhstorage.h67
-rw-r--r--libetpan/src/driver/implementation/mime-message/mime_message_driver.c914
-rw-r--r--libetpan/src/driver/implementation/mime-message/mime_message_driver.h53
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver.c1180
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached.c1059
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c365
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_message.c169
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_tools.c563
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_tools.h88
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_types.h146
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpstorage.c267
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpstorage.h93
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver.c388
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached.c899
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c355
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_message.c193
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_message.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_tools.c344
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_tools.h82
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_types.h153
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3storage.c284
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3storage.h95
91 files changed, 29843 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/data-message/data_message_driver.c b/libetpan/src/driver/implementation/data-message/data_message_driver.c
new file mode 100644
index 0000000..fbdffcd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/data-message/data_message_driver.c
@@ -0,0 +1,119 @@
+/*
+ * 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 "data_message_driver.h"
+
+#include "mailmessage.h"
+#include "mailmessage_tools.h"
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+static int fetch_size(mailmessage * msg, size_t * result)
+{
+ struct generic_message_t * msg_data;
+
+ msg_data = msg->msg_data;
+ * result = msg_data->msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+
+static mailmessage_driver local_data_message_driver = {
+ .msg_name = "data",
+
+ .msg_initialize = mailmessage_generic_initialize,
+ .msg_uninitialize = mailmessage_generic_uninitialize,
+
+ .msg_flush = mailmessage_generic_flush,
+ .msg_check = NULL,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = mailmessage_generic_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_body,
+ .msg_fetch_size = fetch_size,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = NULL,
+};
+
+mailmessage_driver * data_message_driver = &local_data_message_driver;
+
+
+
+mailmessage * data_message_init(char * data, size_t len)
+{
+ struct generic_message_t * msg_data;
+ mailmessage * msg;
+ int r;
+
+ msg = mailmessage_new();
+ if (msg == NULL)
+ goto err;
+
+ r = mailmessage_init(msg, NULL, data_message_driver, 0, len);
+ if (r < 0)
+ goto free;
+
+ msg_data = msg->msg_data;
+ msg_data->msg_fetched = 1;
+ msg_data->msg_message = data;
+ msg_data->msg_length = len;
+
+ return msg;
+
+ free:
+ mailmessage_free(msg);
+ err:
+ return NULL;
+}
+
+void data_message_detach_mime(mailmessage * msg)
+{
+ msg->msg_mime = NULL;
+}
diff --git a/libetpan/src/driver/implementation/data-message/data_message_driver.h b/libetpan/src/driver/implementation/data-message/data_message_driver.h
new file mode 100644
index 0000000..b6569c2
--- a/dev/null
+++ b/libetpan/src/driver/implementation/data-message/data_message_driver.h
@@ -0,0 +1,50 @@
+/*
+ * 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 DATA_MESSAGE_DRIVER_H
+
+#define DATA_MESSAGE_DRIVER_H
+
+#include <libetpan/mailmessage.h>
+
+#define LIBETPAN_DATA_MESSAGE
+
+extern mailmessage_driver * data_message_driver;
+
+mailmessage * data_message_init(char * data, size_t len);
+
+void data_message_detach_mime(mailmessage * msg);
+
+#endif
diff --git a/libetpan/src/driver/implementation/db/dbdriver.c b/libetpan/src/driver/implementation/db/dbdriver.c
new file mode 100644
index 0000000..e374e64
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbdriver.c
@@ -0,0 +1,1134 @@
+/*
+ * 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 "dbdriver.h"
+#include "imfcache.h"
+#include "generic_cache.h"
+#include "libetpan-config.h"
+#include "dbdriver_message.h"
+#include "mail_cache_db.h"
+#include <string.h>
+#include <stdlib.h>
+#include "mailmessage.h"
+
+static int initialize(mailsession * session);
+
+static void uninitialize(mailsession * session);
+
+static int connect_path(mailsession * session, char * path);
+
+static int logout(mailsession * session);
+
+static int expunge_folder(mailsession * session);
+
+static int status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int recent_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int unseen_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int append_message(mailsession * session,
+ char * message, size_t size);
+
+static int append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
+
+static int get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list);
+
+static int check_folder(mailsession * session);
+
+static int get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static int get_message_by_uid(mailsession * session,
+ const char * uid, mailmessage ** result);
+
+static mailsession_driver local_db_session_driver = {
+ .sess_name = "db",
+
+ .sess_initialize = initialize,
+ .sess_uninitialize = uninitialize,
+
+ .sess_parameters = NULL,
+
+ .sess_connect_stream = NULL,
+ .sess_connect_path = connect_path,
+ .sess_starttls = NULL,
+ .sess_login = NULL,
+ .sess_logout = logout,
+ .sess_noop = NULL,
+
+ .sess_build_folder_name = NULL,
+ .sess_create_folder = NULL,
+ .sess_delete_folder = NULL,
+ .sess_rename_folder = NULL,
+ .sess_check_folder = check_folder,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = NULL,
+ .sess_expunge_folder = expunge_folder,
+ .sess_status_folder = status_folder,
+ .sess_messages_number = messages_number,
+ .sess_recent_number = recent_number,
+ .sess_unseen_number = unseen_number,
+ .sess_list_folders = NULL,
+ .sess_lsub_folders = NULL,
+ .sess_subscribe_folder = NULL,
+ .sess_unsubscribe_folder = NULL,
+
+ .sess_append_message = append_message,
+ .sess_append_message_flags = append_message_flags,
+ .sess_copy_message = NULL,
+ .sess_move_message = NULL,
+
+ .sess_get_messages_list = get_messages_list,
+ .sess_get_envelopes_list = get_envelopes_list,
+ .sess_remove_message = NULL,
+
+ .sess_get_message = get_message,
+ .sess_get_message_by_uid = get_message_by_uid,
+};
+
+mailsession_driver * db_session_driver = &local_db_session_driver;
+
+static inline struct db_session_state_data * get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static int flags_store_process(mailsession * session)
+{
+ unsigned int i;
+ MMAPString * mmapstr;
+ int r;
+ int res;
+ struct mail_cache_db * maildb;
+ struct db_session_state_data * data;
+ struct mail_flags_store * flags_store;
+
+ data = get_data(session);
+
+ flags_store = data->db_flags_store;
+
+ if (carray_count(flags_store->fls_tab) == 0)
+ return MAIL_NO_ERROR;
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = mail_cache_db_open_lock(data->db_filename, &maildb);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto free_mmapstr;
+ }
+
+ for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
+ mailmessage * msg;
+ char key[PATH_MAX];
+
+ msg = carray_get(flags_store->fls_tab, i);
+
+ snprintf(key, sizeof(key), "%lu-flags", (unsigned long) msg->msg_index);
+
+ r = generic_cache_flags_write(maildb, mmapstr,
+ key, msg->msg_flags);
+ }
+
+ mail_flags_store_clear(flags_store);
+
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+ mmap_string_free(mmapstr);
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ err:
+ return res;
+}
+
+static int db_get_next_validity(struct mail_cache_db * maildb,
+ uint32_t * p_validity)
+{
+ int r;
+ char key_value[PATH_MAX];
+ uint32_t validity;
+ void * serialized;
+ size_t serialized_len;
+ int res;
+ MMAPString * mmapstr;
+ size_t cur_token;
+
+ mmapstr = mmap_string_new_len(serialized, serialized_len);
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(key_value, sizeof(key_value), "next-validity");
+
+ r = mail_cache_db_get(maildb, key_value, strlen(key_value),
+ &serialized, &serialized_len);
+
+ if (r >= 0) {
+ size_t cur_token;
+
+ cur_token = 0;
+ r = mailimf_cache_int_read(mmapstr, &cur_token, &validity);
+ if (r < 0)
+ validity = 0;
+ }
+ else {
+ validity = 0;
+ }
+
+ mmap_string_set_size(mmapstr, 0);
+ cur_token = 0;
+ r = mailimf_cache_int_write(mmapstr, &cur_token, validity + 1);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_put(maildb, key_value, strlen(key_value),
+ mmapstr->str, mmapstr->len);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto free_mmapstr;
+ }
+
+ mmap_string_free(mmapstr);
+
+ * p_validity = validity;
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ err:
+ return res;
+}
+
+static int db_get_next_msg_number(struct mail_cache_db * maildb,
+ uint32_t * p_num)
+{
+ int r;
+ char key_value[PATH_MAX];
+ uint32_t num;
+ void * serialized;
+ size_t serialized_len;
+ int res;
+ MMAPString * mmapstr;
+ size_t cur_token;
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(key_value, sizeof(key_value), "next-msg");
+
+ r = mail_cache_db_get(maildb, key_value, strlen(key_value),
+ &serialized, &serialized_len);
+
+ if (r >= 0) {
+ size_t cur_token;
+
+ if (mmap_string_append_len(mmapstr, serialized, serialized_len) == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ cur_token = 0;
+ r = mailimf_cache_int_read(mmapstr, &cur_token, &num);
+ if (r < 0)
+ num = 1;
+ }
+ else {
+ num = 1;
+ }
+
+ mmap_string_set_size(mmapstr, 0);
+ cur_token = 0;
+ r = mailimf_cache_int_write(mmapstr, &cur_token, num + 1);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_put(maildb, key_value, strlen(key_value),
+ mmapstr->str, mmapstr->len);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto free_mmapstr;
+ }
+
+ mmap_string_free(mmapstr);
+
+ * p_num = num;
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ err:
+ return res;
+}
+
+static int db_set_message_list(struct mail_cache_db * maildb,
+ carray * msglist)
+{
+ MMAPString * mmapstr;
+ char key_value[PATH_MAX];
+ int r;
+ unsigned int i;
+ size_t cur_token;
+ int res;
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ cur_token = 0;
+ for(i = 0 ; i < carray_count(msglist) ; i ++) {
+ uint32_t * msg;
+
+ msg = carray_get(msglist, i);
+ r = mailimf_cache_int_write(mmapstr, &cur_token, * msg);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mmapstr;
+ }
+ }
+
+ snprintf(key_value, sizeof(key_value), "message-list");
+ r = mail_cache_db_put(maildb, key_value, strlen(key_value),
+ mmapstr->str, mmapstr->len);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmap_string_free(mmapstr);
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ err:
+ return res;
+}
+
+static int db_get_message_list(struct mail_cache_db * maildb,
+ carray ** p_msglist)
+{
+ carray * msglist;
+ void * serialized;
+ size_t serialized_len;
+ int r;
+ char key_value[PATH_MAX];
+ int res;
+ unsigned int i;
+
+ msglist = carray_new(16);
+ if (msglist == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(key_value, sizeof(key_value), "message-list");
+ r = mail_cache_db_get(maildb, key_value, strlen(key_value),
+ &serialized, &serialized_len);
+ if (r >= 0) {
+ MMAPString * mmapstr;
+ size_t cur_token;
+
+ /* collect message list */
+
+ mmapstr = mmap_string_new_len(serialized, serialized_len);
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_msglist;
+ }
+
+ cur_token = 0;
+ do {
+ uint32_t num;
+ uint32_t * msg;
+
+ r = mailimf_cache_int_read(mmapstr, &cur_token, &num);
+ if (r != MAIL_NO_ERROR)
+ break;
+
+ msg = malloc(sizeof(* msg));
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ mmap_string_free(mmapstr);
+ goto free_msglist;
+ }
+ * msg = num;
+
+ r = carray_add(msglist, msg, NULL);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ free(msg);
+ mmap_string_free(mmapstr);
+ goto free_msglist;
+ }
+ } while (1);
+
+ mmap_string_free(mmapstr);
+ }
+
+ * p_msglist = msglist;
+
+ return MAIL_NO_ERROR;
+
+ free_msglist:
+ for(i = 0 ; i < carray_count(msglist) ; i ++) {
+ uint32_t * msg;
+
+ msg = carray_get(msglist, i);
+ free(msg);
+ }
+ carray_free(msglist);
+ err:
+ return res;
+}
+
+static int initialize(mailsession * session)
+{
+ struct db_session_state_data * data;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto err;
+
+ data->db_filename[0] = '\0';
+
+ data->db_flags_store = mail_flags_store_new();
+ if (data->db_flags_store == NULL)
+ goto free;
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ free(data);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void uninitialize(mailsession * session)
+{
+ struct db_session_state_data * data;
+
+ data = get_data(session);
+
+ flags_store_process(session);
+
+ mail_flags_store_free(data->db_flags_store);
+
+ free(data);
+
+ session->sess_data = NULL;
+}
+
+static int connect_path(mailsession * session, char * path)
+{
+ struct db_session_state_data * data;
+
+ data = get_data(session);
+
+ strncpy(data->db_filename, path, sizeof(data->db_filename));
+
+ return MAIL_NO_ERROR;
+}
+
+static int logout(mailsession * session)
+{
+ return MAIL_NO_ERROR;
+}
+
+static int expunge_folder(mailsession * session)
+{
+ int r;
+ char key_value[PATH_MAX];
+ struct mail_cache_db * maildb;
+ carray * msglist;
+ unsigned int i;
+ struct db_session_state_data * data;
+ int res;
+ chash * msg_table;
+ MMAPString * mmapstr;
+
+ data = get_data(session);
+
+ flags_store_process(session);
+
+ r = mail_cache_db_open_lock(data->db_filename, &maildb);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ r = db_get_message_list(maildb, &msglist);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto close_db;
+ }
+
+ msg_table = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
+ if (msg_table == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_msglist;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_msgtable;
+ }
+
+ i = 0;
+ while (i < carray_count(msglist)) {
+ uint32_t num;
+ uint32_t * msg;
+ chashdatum key;
+ chashdatum value;
+ struct mail_flags * flags;
+ int deleted;
+
+ msg = carray_get(msglist, i);
+ num = * msg;
+
+ deleted = 0;
+ snprintf(key_value, sizeof(key_value), "%lu-flags",
+ (unsigned long) num);
+ r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags);
+ if (r == MAIL_NO_ERROR) {
+ if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0)
+ deleted = 1;
+ }
+
+ if (!deleted) {
+ snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num);
+ key.data = key_value;
+ key.len = strlen(key_value);
+ chash_set(msg_table, &key, &value, NULL);
+
+ snprintf(key_value, sizeof(key_value), "%lu-envelope",
+ (unsigned long) num);
+ key.data = key_value;
+ key.len = strlen(key_value);
+ chash_set(msg_table, &key, &value, NULL);
+
+ snprintf(key_value, sizeof(key_value), "%lu-flags",
+ (unsigned long) num);
+ key.data = key_value;
+ key.len = strlen(key_value);
+ chash_set(msg_table, &key, &value, NULL);
+
+ i ++;
+ }
+ else {
+ free(msg);
+ carray_delete(msglist, i);
+ }
+ }
+
+ mmap_string_free(mmapstr);
+
+ r = mail_cache_db_clean_up(maildb, msg_table);
+
+ chash_free(msg_table);
+
+ r = db_set_message_list(maildb, msglist);
+
+ for(i = 0 ; i < carray_count(msglist) ; i ++) {
+ uint32_t * msg;
+
+ msg = carray_get(msglist, i);
+ free(msg);
+ }
+ carray_free(msglist);
+
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+
+ return MAIL_NO_ERROR;
+
+ free_msgtable:
+ chash_free(msg_table);
+ free_msglist:
+ for(i = 0 ; i < carray_count(msglist) ; i ++) {
+ uint32_t * msg;
+
+ msg = carray_get(msglist, i);
+ free(msg);
+ }
+ close_db:
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+ err:
+ return res;
+}
+
+static int status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ struct mail_cache_db * maildb;
+ char key_value[PATH_MAX];
+ MMAPString * mmapstr;
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ struct db_session_state_data * data;
+ int r;
+ int res;
+ carray * msglist;
+ unsigned int i;
+
+ data = get_data(session);
+
+ flags_store_process(session);
+
+ r = mail_cache_db_open_lock(data->db_filename, &maildb);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ r = db_get_message_list(maildb, &msglist);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto close_db;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ messages = 0;
+ recent = 0;
+ unseen = 0;
+ for(i = 0 ; i < carray_count(msglist) ; i ++) {
+ uint32_t num;
+ uint32_t * msg;
+ int r;
+ struct mail_flags * flags;
+
+ msg = carray_get(msglist, i);
+ num = * msg;
+ free(msg);
+ carray_set(msglist, i, NULL);
+
+ messages ++;
+
+ snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num);
+
+ r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags);
+ if (r == MAIL_NO_ERROR) {
+ if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
+ recent ++;
+ }
+ if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
+ unseen ++;
+ }
+ mail_flags_free(flags);
+ }
+ }
+
+ mmap_string_free(mmapstr);
+
+ carray_free(msglist);
+
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+
+ * result_messages = messages;
+ * result_unseen = unseen;
+ * result_recent = recent;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ for(i = 0 ; i < carray_count(msglist) ; i ++) {
+ uint32_t * msg;
+
+ msg = carray_get(msglist, i);
+ if (msg != NULL)
+ free(msg);
+ }
+ carray_free(msglist);
+ close_db:
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+ err:
+ return res;
+}
+
+static int recent_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ uint32_t dummy_messages;
+ uint32_t dummy_unseen;
+
+ return status_folder(session, mb,
+ &dummy_messages, result, &dummy_unseen);
+}
+
+static int unseen_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ uint32_t dummy_messages;
+ uint32_t dummy_recent;
+
+ return status_folder(session, mb,
+ &dummy_messages, &dummy_recent, result);
+}
+
+static int messages_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ uint32_t dummy_unseen;
+ uint32_t dummy_recent;
+
+ return status_folder(session, mb,
+ result, &dummy_recent, &dummy_unseen);
+}
+
+static int append_message(mailsession * session,
+ char * message, size_t size)
+{
+ return append_message_flags(session, message, size, NULL);
+}
+
+static int append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ carray * msglist;
+ unsigned int i;
+ uint32_t * msg;
+ uint32_t num;
+ char key_value[PATH_MAX];
+ MMAPString * mmapstr;
+ struct mail_cache_db * maildb;
+ struct db_session_state_data * data;
+ size_t cur_token;
+ struct mailimf_fields * fields;
+ int r;
+ int res;
+
+ data = get_data(session);
+
+ r = mail_cache_db_open_lock(data->db_filename, &maildb);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ r = db_get_next_msg_number(maildb, &num);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ r = db_get_message_list(maildb, &msglist);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto close_db;
+ }
+
+ msg = malloc(sizeof(* msg));
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_msglist;
+ }
+
+ * msg = num;
+
+ r = carray_add(msglist, msg, NULL);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ free(msg);
+ goto free_msglist;
+ }
+
+ r = db_set_message_list(maildb, msglist);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_msglist;
+ }
+
+ /* free msglist */
+
+ for(i = 0 ; i < carray_count(msglist) ; i ++) {
+ uint32_t * msg;
+
+ msg = carray_get(msglist, i);
+ free(msg);
+ }
+ carray_free(msglist);
+
+ snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num);
+
+ r = mail_cache_db_put(maildb, key_value, strlen(key_value),
+ message, size);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto close_db;
+ }
+
+ /* write envelope */
+
+ cur_token = 0;
+ r = mailimf_envelope_fields_parse(message, size, &cur_token, &fields);
+ if (r != MAILIMF_NO_ERROR) {
+ res = MAIL_ERROR_PARSE;
+ goto close_db;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db;
+ }
+
+ cur_token = 0;
+ r = mailimf_cache_fields_write(mmapstr, &cur_token, fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ mmap_string_free(mmapstr);
+ goto close_db;
+ }
+
+ snprintf(key_value, sizeof(key_value), "%lu-envelope", (unsigned long) num);
+
+ r = mail_cache_db_put(maildb, key_value, strlen(key_value),
+ mmapstr->str, mmapstr->len);
+
+ mmap_string_free(mmapstr);
+
+ mailimf_fields_free(fields);
+
+ /* write flags */
+
+ if (flags != NULL) {
+ snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num);
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db;
+ }
+
+ r = generic_cache_flags_write(maildb, mmapstr,
+ key_value, flags);
+
+ mmap_string_free(mmapstr);
+
+ if (r != MAIL_NO_ERROR) {
+ res = MAIL_ERROR_FILE;
+ goto close_db;
+ }
+ }
+
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+
+ return MAIL_NO_ERROR;
+
+ free_msglist:
+ for(i = 0 ; i < carray_count(msglist) ; i ++) {
+ uint32_t * msg;
+
+ msg = carray_get(msglist, i);
+ free(msg);
+ }
+ carray_free(msglist);
+ close_db:
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+ err:
+ return res;
+}
+
+static int get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ int r;
+ char key[PATH_MAX];
+ struct mail_cache_db * maildb;
+ struct db_session_state_data * data;
+ int res;
+ carray * msglist;
+ unsigned int i;
+ carray * msgtab;
+ struct mailmessage_list * driver_msglist;
+
+ data = get_data(session);
+
+ r = mail_cache_db_open_lock(data->db_filename, &maildb);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ r = db_get_message_list(maildb, &msglist);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto close_db;
+ }
+
+ msgtab = carray_new(16);
+ if (msgtab == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db;
+ }
+
+ for(i = 0 ; i < carray_count(msglist) ; i ++) {
+ uint32_t msg_num;
+ uint32_t * pmsg_num;
+ mailmessage * msg;
+ size_t size;
+
+ pmsg_num = carray_get(msglist, i);
+ msg_num = * pmsg_num;
+ free(pmsg_num);
+ carray_set(msglist, i, NULL);
+
+ snprintf(key, sizeof(key), "%lu", (unsigned long) msg_num);
+ r = mail_cache_db_get_size(maildb, key, strlen(key), &size);
+ if (r < 0) {
+ continue;
+ }
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = mailmessage_init(msg, session, db_message_driver,
+ msg_num, size);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg);
+ res = r;
+ goto free_list;
+ }
+
+ r = carray_add(msgtab, msg, NULL);
+ if (r < 0) {
+ mailmessage_free(msg);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ carray_free(msglist);
+
+ driver_msglist = mailmessage_list_new(msgtab);
+ if (driver_msglist == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+
+ * result = driver_msglist;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ for(i = 0 ; i < carray_count(msgtab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(msgtab, i);
+ mailmessage_free(msg);
+ }
+ carray_free(msgtab);
+
+ for(i = 0 ; i < carray_count(msglist) ; i ++) {
+ uint32_t * msg;
+
+ msg = carray_get(msglist, i);
+ if (msg != NULL)
+ free(msg);
+ }
+ carray_free(msglist);
+ close_db:
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+ err:
+ return res;
+}
+
+static int get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list)
+{
+ unsigned int i;
+ char key[PATH_MAX];
+ int r;
+ struct mail_cache_db * maildb;
+ int res;
+ struct db_session_state_data * data;
+ MMAPString * mmapstr;
+
+ data = get_data(session);
+
+ flags_store_process(session);
+
+ r = mail_cache_db_open_lock(data->db_filename, &maildb);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db;
+ }
+
+ 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) {
+ snprintf(key, sizeof(key), "%lu-envelope",
+ (unsigned long) msg->msg_index);
+
+ r = generic_cache_fields_read(maildb, mmapstr,
+ key, &msg->msg_fields);
+ }
+
+ if (msg->msg_flags == NULL) {
+ snprintf(key, sizeof(key), "%lu-flags",
+ (unsigned long) msg->msg_index);
+
+ r = generic_cache_flags_read(maildb, mmapstr,
+ key, &msg->msg_flags);
+ }
+ }
+
+ mmap_string_free(mmapstr);
+
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+
+ return MAIL_NO_ERROR;
+
+ close_db:
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+ err:
+ return res;
+}
+
+static int check_folder(mailsession * session)
+{
+ flags_store_process(session);
+
+ return MAIL_NO_ERROR;
+}
+
+static int get_message(mailsession * session,
+ uint32_t num, mailmessage ** result)
+{
+ mailmessage * msg;
+ int r;
+ size_t size;
+ char key[PATH_MAX];
+ struct db_session_state_data * data;
+ struct mail_cache_db * maildb;
+ int res;
+
+ data = get_data(session);
+
+ r = mail_cache_db_open_lock(data->db_filename, &maildb);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db;
+ }
+
+ size = 0;
+ snprintf(key, sizeof(key), "%lu", (unsigned long) num);
+ r = mail_cache_db_get_size(maildb, key, strlen(key), &size);
+ /* ignore error */
+
+ r = mailmessage_init(msg, session, db_message_driver,
+ num, size);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg);
+ res = r;
+ goto close_db;
+ }
+
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+
+ return MAIL_NO_ERROR;
+
+ close_db:
+ mail_cache_db_close_unlock(data->db_filename, maildb);
+ err:
+ return res;
+}
+
+static int get_message_by_uid(mailsession * session,
+ const char * uid, mailmessage ** result)
+{
+ uint32_t msg_num;
+
+ msg_num = strtoul(uid, NULL, 10);
+
+ return get_message(session, msg_num, result);
+}
diff --git a/libetpan/src/driver/implementation/db/dbdriver.h b/libetpan/src/driver/implementation/db/dbdriver.h
new file mode 100644
index 0000000..1c2a96d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbdriver.h
@@ -0,0 +1,53 @@
+/*
+ * 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 DBDRIVER_H
+
+#define DBDRIVER_H
+
+#include <libetpan/dbdriver_message.h>
+#include <libetpan/dbdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * db_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/db/dbdriver_message.c b/libetpan/src/driver/implementation/db/dbdriver_message.c
new file mode 100644
index 0000000..70e9dca
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbdriver_message.c
@@ -0,0 +1,308 @@
+/*
+ * 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 "dbdriver_message.h"
+#include "dbdriver.h"
+#include "mail_cache_db.h"
+
+#include "mailmessage_tools.h"
+#include "generic_cache.h"
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+static int fetch_envelope(mailmessage * msg_info,
+ struct mailimf_fields ** result);
+
+static int get_flags(mailmessage * msg_info,
+ struct mail_flags ** result);
+
+static int prefetch(mailmessage * msg_info);
+
+static void prefetch_free(struct generic_message_t * msg);
+
+static int initialize(mailmessage * msg_info);
+
+static void check(mailmessage * msg_info);
+
+static mailmessage_driver local_db_message_driver = {
+ .msg_name = "db",
+
+ .msg_initialize = initialize,
+ .msg_uninitialize = mailmessage_generic_uninitialize,
+
+ .msg_flush = mailmessage_generic_flush,
+ .msg_check = check,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = mailmessage_generic_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_header,
+ .msg_fetch_size = NULL,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = fetch_envelope,
+
+ .msg_get_flags = get_flags,
+};
+
+mailmessage_driver * db_message_driver = &local_db_message_driver;
+
+struct db_msg_data {
+ MMAPString * msg_content;
+};
+
+static inline struct db_session_state_data *
+get_session_data(mailmessage * msg)
+{
+ return msg->msg_session->sess_data;
+}
+
+static int prefetch(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int res;
+ struct db_msg_data * data;
+ struct db_session_state_data * sess_data;
+ MMAPString * msg_content;
+ struct mail_cache_db * maildb;
+ int r;
+ char key[PATH_MAX];
+ void * msg_data;
+ size_t msg_data_len;
+
+ sess_data = get_session_data(msg_info);
+
+ r = mail_cache_db_open_lock(sess_data->db_filename, &maildb);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ snprintf(key, sizeof(key), "%lu", (unsigned long) msg_info->msg_index);
+ r = mail_cache_db_get(maildb, key, strlen(key), &msg_data, &msg_data_len);
+ if (r < 0) {
+ res = MAIL_ERROR_MSG_NOT_FOUND;
+ goto close_db;
+ }
+
+ msg_content = mmap_string_new_len(msg_data, msg_data_len);
+ if (msg_content == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db;
+ }
+
+ data = malloc(sizeof(* data));
+ if (data == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ data->msg_content = msg_content;
+
+ msg = msg_info->msg_data;
+
+ msg->msg_data = data;
+ msg->msg_message = msg_content->str;
+ msg->msg_length = msg_content->len;
+
+ mail_cache_db_close_unlock(sess_data->db_filename, maildb);
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(msg_content);
+ close_db:
+ mail_cache_db_close_unlock(sess_data->db_filename, maildb);
+ err:
+ return res;
+}
+
+static void prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ struct db_msg_data * data;
+
+ data = msg->msg_data;
+ mmap_string_free(data->msg_content);
+ data->msg_content = NULL;
+ free(data);
+ msg->msg_message = NULL;
+ }
+}
+
+static int initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char key[PATH_MAX];
+
+ snprintf(key, sizeof(key), "%lu", (unsigned long) msg_info->msg_index);
+ msg_info->msg_uid = strdup(key);
+ if (msg_info->msg_uid == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = prefetch;
+ msg->msg_prefetch_free = prefetch_free;
+
+ return MAIL_NO_ERROR;
+}
+
+static void check(mailmessage * msg_info)
+{
+ int r;
+
+ if (msg_info->msg_flags != NULL) {
+ r = mail_flags_store_set(get_session_data(msg_info)->db_flags_store,
+ msg_info);
+ /* ignore errors */
+ }
+}
+
+static int fetch_envelope(mailmessage * msg_info,
+ struct mailimf_fields ** result)
+{
+ char key[PATH_MAX];
+ int r;
+ struct db_session_state_data * sess_data;
+ struct mail_cache_db * maildb;
+ int res;
+ struct mailimf_fields * fields;
+ MMAPString * mmapstr;
+
+ sess_data = get_session_data(msg_info);
+
+ r = mail_cache_db_open_lock(sess_data->db_filename, &maildb);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ snprintf(key, sizeof(key), "%lu-envelope",
+ (unsigned long) msg_info->msg_index);
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db;
+ }
+
+ r = generic_cache_fields_read(maildb, mmapstr,
+ key, &fields);
+
+ mmap_string_free(mmapstr);
+
+ if (r != MAIL_NO_ERROR) {
+ res = MAIL_ERROR_MSG_NOT_FOUND;
+ goto close_db;
+ }
+
+ mail_cache_db_close_unlock(sess_data->db_filename, maildb);
+
+ * result = fields;
+
+ return MAIL_NO_ERROR;
+
+ close_db:
+ mail_cache_db_close_unlock(sess_data->db_filename, maildb);
+ err:
+ return res;
+}
+
+static int get_flags(mailmessage * msg_info,
+ struct mail_flags ** result)
+{
+ char key[PATH_MAX];
+ int r;
+ struct db_session_state_data * sess_data;
+ struct mail_cache_db * maildb;
+ int res;
+ MMAPString * mmapstr;
+
+ sess_data = get_session_data(msg_info);
+
+ r = mail_cache_db_open_lock(sess_data->db_filename, &maildb);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ snprintf(key, sizeof(key), "%lu-flags", (unsigned long) msg_info->msg_index);
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db;
+ }
+
+ r = generic_cache_flags_read(maildb, mmapstr,
+ key, &msg_info->msg_flags);
+
+ mmap_string_free(mmapstr);
+
+ if (r != MAIL_NO_ERROR) {
+ msg_info->msg_flags = mail_flags_new_empty();
+ if (msg_info->msg_flags == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db;
+ }
+ }
+
+ mail_cache_db_close_unlock(sess_data->db_filename, maildb);
+
+ * result = msg_info->msg_flags;
+
+ return MAIL_NO_ERROR;
+
+ close_db:
+ mail_cache_db_close_unlock(sess_data->db_filename, maildb);
+ err:
+ return res;
+}
+
diff --git a/libetpan/src/driver/implementation/db/dbdriver_message.h b/libetpan/src/driver/implementation/db/dbdriver_message.h
new file mode 100644
index 0000000..f634775
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbdriver_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 DBDRIVER_MESSAGE_H
+
+#define DBDRIVER_MESSAGE_H
+
+#include <libetpan/dbdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * db_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/db/dbdriver_types.h b/libetpan/src/driver/implementation/db/dbdriver_types.h
new file mode 100644
index 0000000..052e3db
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbdriver_types.h
@@ -0,0 +1,71 @@
+/*
+ * 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 DBDRIVER_TYPES_H
+
+#define DBDRIVER_TYPES_H
+
+#include <libetpan/libetpan-config.h>
+
+#include <libetpan/maildriver_types.h>
+#include <libetpan/generic_cache_types.h>
+#include <libetpan/mailstorage_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct db_session_state_data {
+ char db_filename[PATH_MAX];
+ struct mail_flags_store * db_flags_store;
+};
+
+/* db storage */
+
+/*
+ db_mailstorage is the state data specific to the db storage.
+
+ - pathname is the path of the db storage.
+*/
+
+struct db_mailstorage {
+ char * db_pathname;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/db/dbstorage.c b/libetpan/src/driver/implementation/db/dbstorage.c
new file mode 100644
index 0000000..c4be63c
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbstorage.c
@@ -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$
+ */
+
+#include "dbstorage.h"
+#include "mailstorage.h"
+
+#include "mail.h"
+#include "mailmessage.h"
+#include "dbdriver.h"
+#include "maildriver.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* db storage */
+
+static int db_mailstorage_connect(struct mailstorage * storage);
+static int
+db_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result);
+static void db_mailstorage_uninitialize(struct mailstorage * storage);
+
+static mailstorage_driver db_mailstorage_driver = {
+ .sto_name = "db",
+ .sto_connect = db_mailstorage_connect,
+ .sto_get_folder_session = db_mailstorage_get_folder_session,
+ .sto_uninitialize = db_mailstorage_uninitialize,
+};
+
+int db_mailstorage_init(struct mailstorage * storage,
+ char * db_pathname)
+{
+ struct db_mailstorage * db_storage;
+
+ db_storage = malloc(sizeof(* db_storage));
+ if (db_storage == NULL)
+ goto err;
+
+ db_storage->db_pathname = strdup(db_pathname);
+ if (db_storage->db_pathname == NULL)
+ goto free;
+
+ storage->sto_data = db_storage;
+ storage->sto_driver = &db_mailstorage_driver;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ free(db_storage);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void db_mailstorage_uninitialize(struct mailstorage * storage)
+{
+ struct db_mailstorage * db_storage;
+
+ db_storage = storage->sto_data;
+ free(db_storage->db_pathname);
+ free(db_storage);
+
+ storage->sto_data = NULL;
+}
+
+static int db_mailstorage_connect(struct mailstorage * storage)
+{
+ struct db_mailstorage * db_storage;
+ mailsession_driver * driver;
+ int r;
+ int res;
+ mailsession * session;
+
+ db_storage = storage->sto_data;
+
+ driver = db_session_driver;
+
+ session = mailsession_new(driver);
+ if (session == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = mailsession_connect_path(session, db_storage->db_pathname);
+ switch (r) {
+ case MAIL_NO_ERROR_NON_AUTHENTICATED:
+ case MAIL_NO_ERROR_AUTHENTICATED:
+ case MAIL_NO_ERROR:
+ break;
+ default:
+ res = r;
+ goto free;
+ }
+
+ storage->sto_session = session;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailsession_free(session);
+ err:
+ return res;
+}
+
+static int
+db_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result)
+{
+ * result = storage->sto_session;
+
+ return MAIL_NO_ERROR;
+}
+
diff --git a/libetpan/src/driver/implementation/db/dbstorage.h b/libetpan/src/driver/implementation/db/dbstorage.h
new file mode 100644
index 0000000..5fa9659
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbstorage.h
@@ -0,0 +1,61 @@
+/*
+ * 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 DBSTORAGE_H
+
+#define DBSTORAGE_H
+
+#include <libetpan/dbdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ db_mailstorage_init is the constructor for a DB storage.
+
+ @param storage this is the storage to initialize.
+
+ @param pathname is the directory that contains the mailbox.
+*/
+
+int db_mailstorage_init(struct mailstorage * storage,
+ char * db_pathname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/hotmail/hotmailstorage.c b/libetpan/src/driver/implementation/hotmail/hotmailstorage.c
new file mode 100644
index 0000000..0d1503b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/hotmail/hotmailstorage.c
@@ -0,0 +1,62 @@
+/*
+ * 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 "hotmailstorage.h"
+
+#include "pop3storage.h"
+#include "pop3driver_types.h"
+
+/*
+ hotway is a gateway from hotmail to POP3
+
+ http://hotwayd.sourceforge.net/
+*/
+
+static char hotway_command[512] = "/usr/bin/hotwayd";
+
+int hotmail_mailstorage_init(struct mailstorage * storage,
+ char * hotmail_login, char * hotmail_password,
+ int hotmail_cached, char * hotmail_cache_directory,
+ char * hotmail_flags_directory)
+{
+ return pop3_mailstorage_init(storage,
+ "hotmail.dummy", 0,
+ hotway_command,
+ CONNECTION_TYPE_COMMAND, POP3_AUTH_TYPE_PLAIN,
+ hotmail_login, hotmail_password,
+ hotmail_cached, hotmail_cache_directory,
+ hotmail_flags_directory);
+}
+
diff --git a/libetpan/src/driver/implementation/hotmail/hotmailstorage.h b/libetpan/src/driver/implementation/hotmail/hotmailstorage.h
new file mode 100644
index 0000000..05d6385
--- a/dev/null
+++ b/libetpan/src/driver/implementation/hotmail/hotmailstorage.h
@@ -0,0 +1,56 @@
+/*
+ * 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 HOTMAILSTORAGE_H
+
+#define HOTMAILSTORAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mailstorage_types.h"
+
+int hotmail_mailstorage_init(struct mailstorage * storage,
+ char * hotmail_login, char * hotmail_password,
+ int hotmail_cached, char * hotmail_cache_directory,
+ char * hotmail_flags_directory);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
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
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver.c b/libetpan/src/driver/implementation/maildir/maildirdriver.c
new file mode 100644
index 0000000..a97fd43
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver.c
@@ -0,0 +1,676 @@
+/*
+ * 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$
+ */
+
+
+/*
+ flags directory MUST be kept so that we can have other flags
+ than standards
+*/
+
+#include "maildirdriver.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "maildir.h"
+#include "maildriver_tools.h"
+#include "maildirdriver_message.h"
+#include "maildirdriver_tools.h"
+#include "mailmessage.h"
+#include "generic_cache.h"
+
+static int initialize(mailsession * session);
+
+static void uninitialize(mailsession * session);
+
+static int connect_path(mailsession * session, char * path);
+
+static int logout(mailsession * session);
+
+static int expunge_folder(mailsession * session);
+
+static int status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int recent_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int unseen_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int append_message(mailsession * session,
+ char * message, size_t size);
+
+static int append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
+
+static int get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list);
+
+static int check_folder(mailsession * session);
+
+static int get_message_by_uid(mailsession * session,
+ const char * uid, mailmessage ** result);
+
+static mailsession_driver local_maildir_session_driver = {
+ .sess_name = "maildir",
+
+ .sess_initialize = initialize,
+ .sess_uninitialize = uninitialize,
+
+ .sess_parameters = NULL,
+
+ .sess_connect_stream = NULL,
+ .sess_connect_path = connect_path,
+ .sess_starttls = NULL,
+ .sess_login = NULL,
+ .sess_logout = logout,
+ .sess_noop = NULL,
+
+ .sess_build_folder_name = NULL,
+ .sess_create_folder = NULL,
+ .sess_delete_folder = NULL,
+ .sess_rename_folder = NULL,
+ .sess_check_folder = check_folder,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = NULL,
+ .sess_expunge_folder = expunge_folder,
+ .sess_status_folder = status_folder,
+ .sess_messages_number = messages_number,
+ .sess_recent_number = recent_number,
+ .sess_unseen_number = unseen_number,
+ .sess_list_folders = NULL,
+ .sess_lsub_folders = NULL,
+ .sess_subscribe_folder = NULL,
+ .sess_unsubscribe_folder = NULL,
+
+ .sess_append_message = append_message,
+ .sess_append_message_flags = append_message_flags,
+ .sess_copy_message = NULL,
+ .sess_move_message = NULL,
+
+ .sess_get_messages_list = get_messages_list,
+ .sess_get_envelopes_list = get_envelopes_list,
+ .sess_remove_message = NULL,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = NULL,
+ .sess_get_message_by_uid = get_message_by_uid,
+};
+
+mailsession_driver * maildir_session_driver = &local_maildir_session_driver;
+
+
+static int flags_store_process(struct maildir * md,
+ struct mail_flags_store * flags_store);
+
+
+static inline struct maildir_session_state_data * get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static struct maildir * get_maildir_session(mailsession * session)
+{
+ return get_data(session)->md_session;
+}
+
+static int initialize(mailsession * session)
+{
+ struct maildir_session_state_data * data;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto err;
+
+ data->md_session = NULL;
+
+ data->md_flags_store = mail_flags_store_new();
+ if (data->md_flags_store == NULL)
+ goto free;
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ free(data);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void uninitialize(mailsession * session)
+{
+ struct maildir_session_state_data * data;
+
+ data = get_data(session);
+
+ if (data->md_session != NULL)
+ flags_store_process(data->md_session, data->md_flags_store);
+
+ mail_flags_store_free(data->md_flags_store);
+ if (data->md_session != NULL)
+ maildir_free(data->md_session);
+
+ free(data);
+
+ session->sess_data = NULL;
+}
+
+
+static int connect_path(mailsession * session, char * path)
+{
+ struct maildir * md;
+ int res;
+ int r;
+
+ if (get_maildir_session(session) != NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ md = maildir_new(path);
+ if (md == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = maildir_update(md);
+ if (r != MAILDIR_NO_ERROR) {
+ res = maildirdriver_maildir_error_to_mail_error(r);
+ goto free;
+ }
+
+ get_data(session)->md_session = md;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ maildir_free(md);
+ err:
+ return res;
+}
+
+static int logout(mailsession * session)
+{
+ struct maildir * md;
+
+ check_folder(session);
+
+ md = get_maildir_session(session);
+ if (md == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ maildir_free(md);
+ get_data(session)->md_session = NULL;
+
+ return MAIL_NO_ERROR;
+}
+
+/* folders operations */
+
+static int status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ int r;
+ struct maildir * md;
+ unsigned int i;
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+
+ check_folder(session);
+
+ md = get_maildir_session(session);
+ if (md == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = maildir_update(md);
+ if (r != MAILDIR_NO_ERROR)
+ return maildirdriver_maildir_error_to_mail_error(r);
+
+ messages = 0;
+ recent = 0;
+ unseen = 0;
+ for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i ++) {
+ struct maildir_msg * msg;
+
+ msg = carray_get(md->mdir_msg_list, i);
+ if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
+ recent ++;
+ if ((msg->msg_flags & MAILDIR_FLAG_SEEN) == 0)
+ unseen ++;
+ messages ++;
+ }
+
+ * result_messages = messages;
+ * result_recent = recent;
+ * result_unseen = unseen;
+
+ return MAIL_NO_ERROR;
+}
+
+static int messages_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ struct maildir * md;
+ int r;
+
+ md = get_maildir_session(session);
+ if (md == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = maildir_update(md);
+ if (r != MAILDIR_NO_ERROR)
+ return maildirdriver_maildir_error_to_mail_error(r);
+
+ * result = carray_count(md->mdir_msg_list);
+
+ return MAIL_NO_ERROR;
+}
+
+static int unseen_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = status_folder(session, mb, &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = unseen;
+
+ return MAIL_NO_ERROR;
+}
+
+static int recent_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = status_folder(session, mb, &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = recent;
+
+ return MAIL_NO_ERROR;
+}
+
+
+/* messages operations */
+
+static int append_message(mailsession * session,
+ char * message, size_t size)
+{
+#if 0
+ struct maildir * md;
+ int r;
+
+ md = get_maildir_session(session);
+ if (md == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = maildir_message_add(md, message, size);
+ if (r != MAILDIR_NO_ERROR)
+ return maildirdriver_maildir_error_to_mail_error(r);
+
+ return MAIL_NO_ERROR;
+#endif
+
+ return append_message_flags(session, message, size, NULL);
+}
+
+static int append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ struct maildir * md;
+ int r;
+ char uid[PATH_MAX];
+ struct maildir_msg * md_msg;
+ chashdatum key;
+ chashdatum value;
+ uint32_t md_flags;
+
+ md = get_maildir_session(session);
+ if (md == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = maildir_message_add_uid(md, message, size,
+ uid, sizeof(uid));
+ if (r != MAILDIR_NO_ERROR)
+ return maildirdriver_maildir_error_to_mail_error(r);
+
+ if (flags == NULL)
+ goto exit;
+
+ key.data = uid;
+ key.len = strlen(uid);
+ r = chash_get(md->mdir_msg_hash, &key, &value);
+ if (r < 0)
+ goto exit;
+
+ md_msg = value.data;
+
+ md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags);
+
+ r = maildir_message_change_flags(md, uid, md_flags);
+ if (r != MAILDIR_NO_ERROR)
+ goto exit;
+
+ return MAIL_NO_ERROR;
+
+ exit:
+ return MAIL_NO_ERROR;
+}
+
+static int get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ struct maildir * md;
+ int r;
+ struct mailmessage_list * env_list;
+ int res;
+
+ md = get_maildir_session(session);
+ if (md == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = maildir_update(md);
+ if (r != MAILDIR_NO_ERROR) {
+ res = maildirdriver_maildir_error_to_mail_error(r);
+ goto err;
+ }
+
+ r = maildir_get_messages_list(session, md,
+ maildir_message_driver, &env_list);
+ if (r != MAILDIR_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ * result = env_list;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ mailmessage_list_free(env_list);
+ err:
+ return res;
+}
+
+static int get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list)
+{
+ int r;
+ struct maildir * md;
+ unsigned int i;
+ int res;
+
+ check_folder(session);
+
+ md = get_maildir_session(session);
+ if (md == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ r = maildir_update(md);
+ if (r != MAILDIR_NO_ERROR) {
+ res = maildirdriver_maildir_error_to_mail_error(r);
+ goto err;
+ }
+
+ r = maildriver_generic_get_envelopes_list(session, env_list);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) {
+ struct maildir_msg * md_msg;
+ mailmessage * msg;
+ uint32_t driver_flags;
+ clist * ext;
+ chashdatum key;
+ chashdatum value;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ key.data = msg->msg_uid;
+ key.len = strlen(msg->msg_uid);
+ r = chash_get(md->mdir_msg_hash, &key, &value);
+ if (r < 0)
+ continue;
+
+ md_msg = value.data;
+
+ driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags);
+
+ if (msg->msg_flags == NULL) {
+ ext = clist_new();
+ if (ext == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ continue;
+ }
+
+ msg->msg_flags = mail_flags_new(driver_flags, ext);
+ if (msg->msg_flags == NULL) {
+ clist_free(ext);
+ res = MAIL_ERROR_MEMORY;
+ continue;
+ }
+
+ if ((md_msg->msg_flags & MAILDIR_FLAG_NEW) != 0) {
+ mail_flags_store_set(get_data(session)->md_flags_store, msg);
+ }
+ }
+ else {
+ msg->msg_flags->fl_flags &= MAIL_FLAG_FORWARDED;
+ msg->msg_flags->fl_flags |= driver_flags;
+ }
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+
+static int expunge_folder(mailsession * session)
+{
+ unsigned int i;
+ int r;
+ int res;
+ struct maildir * md;
+
+ check_folder(session);
+
+ md = get_maildir_session(session);
+ if (md == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = maildir_update(md);
+ if (r != MAILDIR_NO_ERROR) {
+ res = maildirdriver_maildir_error_to_mail_error(r);
+ goto err;
+ }
+
+ for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) {
+ struct maildir_msg * md_msg;
+
+ md_msg = carray_get(md->mdir_msg_list, i);
+
+ if ((md_msg->msg_flags & MAILDIR_FLAG_TRASHED) != 0)
+ maildir_message_remove(md, md_msg->msg_uid);
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+
+static int flags_store_process(struct maildir * md,
+ struct mail_flags_store * flags_store)
+{
+ unsigned int i;
+
+ if (carray_count(flags_store->fls_tab) == 0)
+ return MAIL_NO_ERROR;
+
+ for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
+ mailmessage * msg;
+ uint32_t md_flags;
+
+ msg = carray_get(flags_store->fls_tab, i);
+ md_flags = maildirdriver_flags_to_maildir_flags(msg->msg_flags->fl_flags);
+ md_flags &= ~MAILDIR_FLAG_NEW;
+
+ maildir_message_change_flags(md, msg->msg_uid, md_flags);
+ }
+
+ mail_flags_store_clear(flags_store);
+
+ return MAIL_NO_ERROR;
+}
+
+
+
+static int check_folder(mailsession * session)
+{
+ struct mail_flags_store * flags_store;
+ struct maildir_session_state_data * data;
+ struct maildir * md;
+
+ md = get_maildir_session(session);
+ if (md == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ data = get_data(session);
+ flags_store = data->md_flags_store;
+
+ return flags_store_process(md, flags_store);
+}
+
+static int get_message_by_uid(mailsession * session,
+ const char * uid, mailmessage ** result)
+{
+ int r;
+ struct maildir * md;
+ int res;
+ mailmessage * msg;
+ char * msg_filename;
+ struct stat stat_info;
+
+ md = get_maildir_session(session);
+
+ /* update maildir data */
+
+ r = maildir_update(md);
+ if (r != MAILDIR_NO_ERROR) {
+ res = maildirdriver_maildir_error_to_mail_error(r);
+ goto err;
+ }
+
+ msg_filename = maildir_message_get(md, uid);
+ if (msg_filename == NULL) {
+ res = MAIL_ERROR_INVAL;
+ goto err;
+ }
+
+ r = stat(msg_filename, &stat_info);
+ free(msg_filename);
+ if (r < 0) {
+ res = MAIL_ERROR_INVAL;
+ goto err;
+ }
+
+ /* create message */
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = mailmessage_init(msg, session, maildir_message_driver,
+ 0, stat_info.st_size);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg);
+ res = r;
+ goto err;
+ }
+
+ msg->msg_uid = strdup(uid);
+ if (msg->msg_uid == NULL) {
+ mailmessage_free(msg);
+ res = r;
+ goto err;
+ }
+
+ * result = msg;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver.h b/libetpan/src/driver/implementation/maildir/maildirdriver.h
new file mode 100644
index 0000000..0abe09d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver.h
@@ -0,0 +1,53 @@
+/*
+ * 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 MAILDIRDRIVER_H
+
+#define MAILDIRDRIVER_H
+
+#include <libetpan/maildriver.h>
+#include <libetpan/maildirdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * maildir_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_cached.c b/libetpan/src/driver/implementation/maildir/maildirdriver_cached.c
new file mode 100644
index 0000000..3664362
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_cached.c
@@ -0,0 +1,1158 @@
+/*
+ * 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 "maildirdriver.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mail.h"
+#include "maildir.h"
+#include "maildriver_tools.h"
+#include "maildirdriver_tools.h"
+#include "maildirdriver_cached_message.h"
+#include "mailmessage.h"
+#include "generic_cache.h"
+#include "imfcache.h"
+#include "mail_cache_db.h"
+#include "libetpan-config.h"
+
+static int initialize(mailsession * session);
+
+static void uninitialize(mailsession * session);
+
+static int parameters(mailsession * session,
+ int id, void * value);
+
+static int connect_path(mailsession * session, char * path);
+
+static int logout(mailsession * session);
+
+static int expunge_folder(mailsession * session);
+
+static int status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int recent_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int unseen_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int append_message(mailsession * session,
+ char * message, size_t size);
+
+static int append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
+
+static int get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list);
+
+static int check_folder(mailsession * session);
+
+static int get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static int get_message_by_uid(mailsession * session,
+ const char * uid, mailmessage ** result);
+
+static mailsession_driver local_maildir_cached_session_driver = {
+ .sess_name = "maildir-cached",
+
+ .sess_initialize = initialize,
+ .sess_uninitialize = uninitialize,
+
+ .sess_parameters = parameters,
+
+ .sess_connect_stream = NULL,
+ .sess_connect_path = connect_path,
+ .sess_starttls = NULL,
+ .sess_login = NULL,
+ .sess_logout = logout,
+ .sess_noop = NULL,
+
+ .sess_build_folder_name = NULL,
+ .sess_create_folder = NULL,
+ .sess_delete_folder = NULL,
+ .sess_rename_folder = NULL,
+ .sess_check_folder = check_folder,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = NULL,
+ .sess_expunge_folder = expunge_folder,
+ .sess_status_folder = status_folder,
+ .sess_messages_number = messages_number,
+ .sess_recent_number = recent_number,
+ .sess_unseen_number = unseen_number,
+ .sess_list_folders = NULL,
+ .sess_lsub_folders = NULL,
+ .sess_subscribe_folder = NULL,
+ .sess_unsubscribe_folder = NULL,
+
+ .sess_append_message = append_message,
+ .sess_append_message_flags = append_message_flags,
+ .sess_copy_message = NULL,
+ .sess_move_message = NULL,
+
+ .sess_get_messages_list = get_messages_list,
+ .sess_get_envelopes_list = get_envelopes_list,
+ .sess_remove_message = NULL,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = get_message,
+ .sess_get_message_by_uid = get_message_by_uid,
+};
+
+mailsession_driver * maildir_cached_session_driver =
+&local_maildir_cached_session_driver;
+
+
+static inline struct maildir_cached_session_state_data *
+get_cached_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline mailsession * get_ancestor(mailsession * session)
+{
+ return get_cached_data(session)->md_ancestor;
+}
+
+static inline struct maildir_session_state_data *
+get_ancestor_data(mailsession * session)
+{
+ return get_ancestor(session)->sess_data;
+}
+
+
+static struct maildir * get_maildir_session(mailsession * session)
+{
+ return get_ancestor_data(session)->md_session;
+}
+
+static int initialize(mailsession * session)
+{
+ struct maildir_cached_session_state_data * data;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto err;
+
+ data->md_ancestor = mailsession_new(maildir_session_driver);
+ if (data->md_ancestor == NULL)
+ goto free;
+
+ data->md_flags_store = mail_flags_store_new();
+ if (data->md_flags_store == NULL)
+ goto free_session;
+
+ data->md_quoted_mb = NULL;
+ data->md_cache_directory[0] = '\0';
+ data->md_flags_directory[0] = '\0';
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ free_session:
+ mailsession_free(data->md_ancestor);
+ free:
+ free(data);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void
+free_quoted_mb(struct maildir_cached_session_state_data * maildir_cached_data)
+{
+ if (maildir_cached_data->md_quoted_mb != NULL) {
+ free(maildir_cached_data->md_quoted_mb);
+ maildir_cached_data->md_quoted_mb = NULL;
+ }
+}
+
+static int
+write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ char * uid, struct mail_flags * flags);
+
+#define ENV_NAME "env.db"
+#define FLAGS_NAME "flags.db"
+
+static int flags_store_process(char * flags_directory, char * quoted_mb,
+ struct mail_flags_store * flags_store)
+{
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ unsigned int i;
+ int r;
+ int res;
+
+ if (carray_count(flags_store->fls_tab) == 0)
+ return MAIL_NO_ERROR;
+
+ if (quoted_mb == NULL)
+ return MAIL_NO_ERROR;
+
+ snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
+ flags_directory, MAIL_DIR_SEPARATOR, quoted_mb,
+ MAIL_DIR_SEPARATOR, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(flags_store->fls_tab, i);
+
+ r = write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_uid, msg->msg_flags);
+ if (r != MAIL_NO_ERROR) {
+ /* ignore errors */
+ }
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ mail_flags_store_clear(flags_store);
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static void uninitialize(mailsession * session)
+{
+ struct maildir_cached_session_state_data * data;
+
+ data = get_cached_data(session);
+
+ flags_store_process(data->md_flags_directory,
+ data->md_quoted_mb,
+ data->md_flags_store);
+
+ mail_flags_store_free(data->md_flags_store);
+ mailsession_free(data->md_ancestor);
+ free_quoted_mb(data);
+ free(data);
+
+ session->sess_data = data;
+}
+
+
+static int parameters(mailsession * session,
+ int id, void * value)
+{
+ struct maildir_cached_session_state_data * data;
+ int r;
+
+ data = get_cached_data(session);
+
+ switch (id) {
+ case MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY:
+ strncpy(data->md_cache_directory, value, PATH_MAX);
+ data->md_cache_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(data->md_cache_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+
+ case MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY:
+ strncpy(data->md_flags_directory, value, PATH_MAX);
+ data->md_flags_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(data->md_flags_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+
+ default:
+ return mailsession_parameters(data->md_ancestor, id, value);
+ }
+}
+
+
+static int get_cache_folder(mailsession * session, char ** result)
+{
+ struct maildir * md;
+ char * quoted_mb;
+ int res;
+ int r;
+ char key[PATH_MAX];
+ struct maildir_cached_session_state_data * data;
+
+ md = get_maildir_session(session);
+ data = get_cached_data(session);
+
+ quoted_mb = maildriver_quote_mailbox(md->mdir_path);
+ if (quoted_mb == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(key, PATH_MAX, "%s/%s", data->md_cache_directory, quoted_mb);
+ r = generic_cache_create_dir(key);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_quoted_mb;
+ }
+
+ snprintf(key, PATH_MAX, "%s/%s", data->md_flags_directory, quoted_mb);
+ r = generic_cache_create_dir(key);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_quoted_mb;
+ }
+
+ * result = quoted_mb;
+
+ return MAIL_NO_ERROR;
+
+ free_quoted_mb:
+ free(quoted_mb);
+ err:
+ return res;
+}
+
+
+static int connect_path(mailsession * session, char * path)
+{
+ int r;
+ int res;
+ char * quoted_mb;
+
+ r = mailsession_connect_path(get_ancestor(session), path);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ r = get_cache_folder(session, &quoted_mb);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto logout;
+ }
+
+ get_cached_data(session)->md_quoted_mb = quoted_mb;
+
+ return MAILDIR_NO_ERROR;
+
+ logout:
+ mailsession_logout(get_ancestor(session));
+ err:
+ return res;
+}
+
+static int logout(mailsession * session)
+{
+ struct maildir_cached_session_state_data * data;
+ int r;
+
+ data = get_cached_data(session);
+
+ flags_store_process(data->md_flags_directory,
+ data->md_quoted_mb, data->md_flags_store);
+
+ r = mailsession_logout(get_ancestor(session));
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ free_quoted_mb(get_cached_data(session));
+
+ return MAIL_NO_ERROR;
+}
+
+static int status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ return mailsession_status_folder(get_ancestor(session), mb,
+ result_messages, result_recent, result_unseen);
+}
+
+static int messages_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ return mailsession_messages_number(get_ancestor(session), mb, result);
+}
+
+static int unseen_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ return mailsession_unseen_number(get_ancestor(session), mb, result);
+}
+
+static int recent_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ return mailsession_recent_number(get_ancestor(session), mb, result);
+}
+
+
+static int append_message(mailsession * session,
+ char * message, size_t size)
+{
+#if 0
+ return mailsession_append_message(get_ancestor(session), message, size);
+#endif
+ return append_message_flags(session, message, size, NULL);
+}
+
+static int append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ struct maildir * md;
+ int r;
+ char uid[PATH_MAX];
+ struct maildir_msg * md_msg;
+ chashdatum key;
+ chashdatum value;
+ uint32_t md_flags;
+ struct mail_cache_db * cache_db_flags;
+ char filename_flags[PATH_MAX];
+ MMAPString * mmapstr;
+ struct maildir_cached_session_state_data * data;
+
+ md = get_maildir_session(session);
+ if (md == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = maildir_message_add_uid(md, message, size,
+ uid, sizeof(uid));
+ if (r != MAILDIR_NO_ERROR)
+ return maildirdriver_maildir_error_to_mail_error(r);
+
+ if (flags == NULL)
+ goto exit;
+
+ data = get_cached_data(session);
+
+ snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
+ data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
+ MAIL_DIR_SEPARATOR, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0)
+ goto exit;
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL)
+ goto close_db_flags;
+
+ r = write_cached_flags(cache_db_flags, mmapstr,
+ uid, flags);
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ if (r != MAIL_NO_ERROR)
+ goto exit;
+
+ key.data = uid;
+ key.len = strlen(uid);
+ r = chash_get(md->mdir_msg_hash, &key, &value);
+ if (r < 0)
+ goto exit;
+
+ md_msg = value.data;
+
+ md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags);
+
+ r = maildir_message_change_flags(md, uid, md_flags);
+ if (r != MAILDIR_NO_ERROR)
+ goto exit;
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ exit:
+ return MAIL_NO_ERROR;
+}
+
+#define UID_NAME "uid.db"
+
+static int uid_clean_up(struct mail_cache_db * uid_db,
+ struct mailmessage_list * env_list)
+{
+ chash * hash_exist;
+ int res;
+ int r;
+ unsigned int i;
+ chashdatum key;
+ chashdatum value;
+ char key_str[PATH_MAX];
+
+ /* flush cache */
+
+ hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL);
+ if (hash_exist == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ value.data = NULL;
+ value.len = 0;
+
+ key.data = "max-uid";
+ key.len = strlen("max-uid");
+ r = chash_set(hash_exist, &key, &value, NULL);
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ value.data = NULL;
+ value.len = 0;
+
+ key.data = msg->msg_uid;
+ key.len = strlen(msg->msg_uid);
+ r = chash_set(hash_exist, &key, &value, NULL);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ snprintf(key_str, sizeof(key_str), "uid-%lu",
+ (unsigned long) msg->msg_index);
+ key.data = key_str;
+ key.len = strlen(key_str);
+ r = chash_set(hash_exist, &key, &value, NULL);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+ }
+
+ mail_cache_db_clean_up(uid_db, hash_exist);
+
+ chash_free(hash_exist);
+
+ return MAIL_NO_ERROR;
+
+ free:
+ chash_free(hash_exist);
+ err:
+ return res;
+}
+
+static int get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ struct maildir * md;
+ int r;
+ struct mailmessage_list * env_list;
+ int res;
+ uint32_t max_uid;
+ char filename[PATH_MAX];
+ struct mail_cache_db * uid_db;
+ void * value;
+ size_t value_len;
+ unsigned long i;
+ struct maildir_cached_session_state_data * data;
+ char key[PATH_MAX];
+
+ data = get_cached_data(session);
+
+ md = get_maildir_session(session);
+ if (md == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ check_folder(session);
+
+ r = maildir_update(md);
+ if (r != MAILDIR_NO_ERROR) {
+ res = maildirdriver_maildir_error_to_mail_error(r);
+ goto err;
+ }
+
+ r = maildir_get_messages_list(session, md,
+ maildir_cached_message_driver, &env_list);
+ if (r != MAILDIR_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ /* read/write DB */
+
+ snprintf(filename, sizeof(filename), "%s%c%s%c%s",
+ data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
+ MAIL_DIR_SEPARATOR, UID_NAME);
+
+ r = mail_cache_db_open_lock(filename, &uid_db);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ max_uid = 0;
+ r = mail_cache_db_get(uid_db, "max-uid", sizeof("max-uid") - 1,
+ &value, &value_len);
+ if (r == 0) {
+ memcpy(&max_uid, value, sizeof(max_uid));
+ }
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+ uint32_t index;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ r = mail_cache_db_get(uid_db, msg->msg_uid,
+ strlen(msg->msg_uid), &value, &value_len);
+ if (r < 0) {
+ max_uid ++;
+ msg->msg_index = max_uid;
+ mail_cache_db_put(uid_db, msg->msg_uid,
+ strlen(msg->msg_uid), &msg->msg_index, sizeof(msg->msg_index));
+
+ snprintf(key, sizeof(key), "uid-%lu", (unsigned long) msg->msg_index);
+ mail_cache_db_put(uid_db, key, strlen(key),
+ msg->msg_uid, strlen(msg->msg_uid));
+ }
+ else {
+ memcpy(&index, value, sizeof(index));
+ msg->msg_index = index;
+ }
+ }
+
+ mail_cache_db_put(uid_db, "max-uid", sizeof("max-uid") - 1,
+ &max_uid, sizeof(max_uid));
+
+ uid_clean_up(uid_db, env_list);
+
+ mail_cache_db_close_unlock(filename, uid_db);
+
+ * result = env_list;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ mailmessage_list_free(env_list);
+ err:
+ return res;
+}
+
+static int
+get_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ mailsession * session,
+ char * uid,
+ struct mail_flags ** result)
+{
+ int r;
+ char keyname[PATH_MAX];
+ struct mail_flags * flags;
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%s-flags", uid);
+
+ r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
+ mailsession * session, char * uid,
+ struct mailimf_fields ** result)
+{
+ int r;
+ char keyname[PATH_MAX];
+ struct mailimf_fields * fields;
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%s-envelope", uid);
+
+ r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = fields;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+write_cached_envelope(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ mailsession * session, char * uid,
+ struct mailimf_fields * fields)
+{
+ int r;
+ char keyname[PATH_MAX];
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%s-envelope", uid);
+
+ r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ char * uid, struct mail_flags * flags)
+{
+ int r;
+ char keyname[PATH_MAX];
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%s-flags", uid);
+
+ r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+
+static int get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list)
+{
+ int r;
+ unsigned int i;
+ int res;
+ struct maildir_cached_session_state_data * data;
+ char filename_env[PATH_MAX];
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_env;
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+
+ data = get_cached_data(session);
+
+ flags_store_process(data->md_flags_directory,
+ data->md_quoted_mb, data->md_flags_store);
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(filename_env, PATH_MAX, "%s%c%s%c%s",
+ data->md_cache_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
+ MAIL_DIR_SEPARATOR, ENV_NAME);
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
+ data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
+ MAIL_DIR_SEPARATOR, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto close_db_env;
+ }
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) {
+ mailmessage * msg;
+ struct mailimf_fields * fields;
+ struct mail_flags * flags;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields == NULL) {
+ r = get_cached_envelope(cache_db_env, mmapstr, session,
+ msg->msg_uid, &fields);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_cached = TRUE;
+ msg->msg_fields = fields;
+ }
+ }
+
+ if (msg->msg_flags == NULL) {
+ r = get_cached_flags(cache_db_flags, mmapstr,
+ session, msg->msg_uid, &flags);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_flags = flags;
+ }
+ }
+ }
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+
+ r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto close_db_env;
+ }
+
+ /* must write cache */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields != NULL) {
+ if (!msg->msg_cached) {
+ /* msg->index is the numerical UID of the message */
+ r = write_cached_envelope(cache_db_env, mmapstr,
+ session, msg->msg_uid, msg->msg_fields);
+ }
+ }
+
+ if (msg->msg_flags != NULL) {
+ r = write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_uid, msg->msg_flags);
+ }
+ }
+
+ /* flush cache */
+
+ maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+
+ mmap_string_free(mmapstr);
+
+ return MAIL_NO_ERROR;
+
+ close_db_env:
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ err:
+ return res;
+}
+
+static int expunge_folder(mailsession * session)
+{
+ return mailsession_expunge_folder(get_ancestor(session));
+}
+
+static int check_folder(mailsession * session)
+{
+ struct maildir_cached_session_state_data * data;
+
+ data = get_cached_data(session);
+
+ flags_store_process(data->md_flags_directory,
+ data->md_quoted_mb, data->md_flags_store);
+
+ return mailsession_check_folder(get_ancestor(session));
+}
+
+static int get_message(mailsession * session,
+ uint32_t num, mailmessage ** result)
+{
+ struct maildir * md;
+ int res;
+ mailmessage * msg;
+ char filename[PATH_MAX];
+ struct mail_cache_db * uid_db;
+ char * msg_filename;
+ struct stat stat_info;
+ char key_str[PATH_MAX];
+ void * value;
+ size_t value_len;
+ char uid[PATH_MAX];
+ struct maildir_cached_session_state_data * data;
+ int r;
+
+ data = get_cached_data(session);
+
+ md = get_maildir_session(session);
+
+ /* a get_messages_list() should have been done once before */
+
+ /* read DB */
+
+ snprintf(filename, sizeof(filename), "%s%c%s%c%s",
+ data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
+ MAIL_DIR_SEPARATOR, UID_NAME);
+
+ r = mail_cache_db_open_lock(filename, &uid_db);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(key_str, sizeof(key_str), "uid-%lu", (unsigned long) num);
+
+ r = mail_cache_db_get(uid_db, key_str, strlen(key_str), &value, &value_len);
+ if (r < 0) {
+ res = MAIL_ERROR_INVAL;
+ goto close_db;
+ }
+
+ if (value_len >= PATH_MAX) {
+ res = MAIL_ERROR_INVAL;
+ goto close_db;
+ }
+
+ memcpy(uid, value, value_len);
+ uid[value_len] = '\0';
+
+ mail_cache_db_close_unlock(filename, uid_db);
+
+ /* update maildir data */
+
+ r = maildir_update(md);
+ if (r != MAILDIR_NO_ERROR) {
+ res = maildirdriver_maildir_error_to_mail_error(r);
+ goto err;
+ }
+
+ msg_filename = maildir_message_get(md, uid);
+ if (msg_filename == NULL) {
+ res = MAIL_ERROR_INVAL;
+ goto err;
+ }
+
+ r = stat(msg_filename, &stat_info);
+ free(msg_filename);
+ if (r < 0) {
+ res = MAIL_ERROR_INVAL;
+ goto err;
+ }
+
+ /* create message */
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = mailmessage_init(msg, session, maildir_cached_message_driver,
+ num, stat_info.st_size);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg);
+ res = r;
+ goto err;
+ }
+
+ msg->msg_uid = strdup(uid);
+ if (msg->msg_uid == NULL) {
+ mailmessage_free(msg);
+ res = r;
+ goto err;
+ }
+
+ * result = msg;
+
+ return MAIL_NO_ERROR;
+
+ close_db:
+ mail_cache_db_close_unlock(filename, uid_db);
+ err:
+ return res;
+}
+
+
+static int get_message_by_uid(mailsession * session,
+ const char * uid, mailmessage ** result)
+{
+ int r;
+ struct maildir * md;
+ int res;
+ mailmessage * msg;
+ char filename[PATH_MAX];
+ struct mail_cache_db * uid_db;
+ char * msg_filename;
+ struct stat stat_info;
+ void * value;
+ size_t value_len;
+ struct maildir_cached_session_state_data * data;
+ uint32_t index;
+
+ data = get_cached_data(session);
+
+ md = get_maildir_session(session);
+
+ /* a get_messages_list() should have been done once before */
+
+ /* read DB */
+
+ snprintf(filename, sizeof(filename), "%s%c%s%c%s",
+ data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
+ MAIL_DIR_SEPARATOR, UID_NAME);
+
+ r = mail_cache_db_open_lock(filename, &uid_db);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = mail_cache_db_get(uid_db, uid, strlen(uid), &value, &value_len);
+ if (r < 0) {
+ res = MAIL_ERROR_INVAL;
+ goto close_db;
+ }
+
+ memcpy(&index, value, sizeof(index));
+
+ mail_cache_db_close_unlock(filename, uid_db);
+
+ /* update maildir data */
+
+ r = maildir_update(md);
+ if (r != MAILDIR_NO_ERROR) {
+ res = maildirdriver_maildir_error_to_mail_error(r);
+ goto err;
+ }
+
+ msg_filename = maildir_message_get(md, uid);
+ if (msg_filename == NULL) {
+ res = MAIL_ERROR_INVAL;
+ goto err;
+ }
+
+ r = stat(msg_filename, &stat_info);
+ free(msg_filename);
+ if (r < 0) {
+ res = MAIL_ERROR_INVAL;
+ goto err;
+ }
+
+ /* create message */
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = mailmessage_init(msg, session, maildir_cached_message_driver,
+ index, stat_info.st_size);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg);
+ res = r;
+ goto err;
+ }
+
+ msg->msg_uid = strdup(uid);
+ if (msg->msg_uid == NULL) {
+ mailmessage_free(msg);
+ res = r;
+ goto err;
+ }
+
+ * result = msg;
+
+ return MAIL_NO_ERROR;
+
+ close_db:
+ mail_cache_db_close_unlock(filename, uid_db);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_cached.h b/libetpan/src/driver/implementation/maildir/maildirdriver_cached.h
new file mode 100644
index 0000000..5c3d8a9
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_cached.h
@@ -0,0 +1,53 @@
+/*
+ * 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 MAILDIRDRIVER_CACHED_H
+
+#define MAILDIRDRIVER_CACHED_H
+
+#include <libetpan/maildriver.h>
+#include <libetpan/maildirdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * maildir_cached_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c b/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c
new file mode 100644
index 0000000..d2c30cc
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c
@@ -0,0 +1,334 @@
+/*
+ * 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 "maildirdriver_message.h"
+
+#include "mailmessage_tools.h"
+#include "maildirdriver.h"
+#include "maildir.h"
+#include "generic_cache.h"
+#include "mail_cache_db.h"
+#include "maildirdriver_tools.h"
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+static int get_flags(mailmessage * msg_info,
+ struct mail_flags ** result);
+
+static int prefetch(mailmessage * msg_info);
+
+static void prefetch_free(struct generic_message_t * msg);
+
+static int initialize(mailmessage * msg_info);
+
+static void check(mailmessage * msg_info);
+
+static mailmessage_driver local_maildir_cached_message_driver = {
+ .msg_name = "maildir-cached",
+
+ .msg_initialize = initialize,
+ .msg_uninitialize = mailmessage_generic_uninitialize,
+
+ .msg_flush = mailmessage_generic_flush,
+ .msg_check = check,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = mailmessage_generic_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_header,
+ .msg_fetch_size = NULL,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = get_flags,
+};
+
+mailmessage_driver * maildir_cached_message_driver =
+&local_maildir_cached_message_driver;
+
+struct maildir_msg_data {
+ int fd;
+};
+
+#if 0
+static inline struct maildir_cached_session_state_data *
+get_cached_session_data(mailmessage * msg)
+{
+ return msg->session->data;
+}
+
+static inline mailsession * cached_session_get_ancestor(mailsession * session)
+{
+ return get_data(session)->session;
+}
+
+static inline struct maildir_session_state_data *
+cached_session_get_ancestor_data(mailsession * session)
+{
+ return get_ancestor(session)->data;
+}
+
+static struct maildir * get_maildir_session(mailmessage * msg)
+{
+ return cached_session_get_ancestor_data(msg->session)->session;
+}
+#endif
+static inline struct maildir_cached_session_state_data *
+get_cached_session_data(mailmessage * msg)
+{
+ return msg->msg_session->sess_data;
+}
+
+static inline struct maildir_cached_session_state_data *
+cached_session_get_data(mailsession * s)
+{
+ return s->sess_data;
+}
+
+static inline mailsession * cached_session_get_ancestor(mailsession * s)
+{
+ return cached_session_get_data(s)->md_ancestor;
+}
+
+static inline struct maildir_session_state_data *
+cached_session_get_ancestor_data(mailsession * s)
+{
+ return cached_session_get_ancestor(s)->sess_data;
+}
+
+static inline struct maildir_session_state_data *
+get_session_ancestor_data(mailmessage * msg)
+{
+ return cached_session_get_ancestor_data(msg->msg_session);
+}
+
+static inline struct maildir *
+cached_session_get_maildir_session(mailsession * session)
+{
+ return cached_session_get_ancestor_data(session)->md_session;
+}
+
+static inline struct maildir * get_maildir_session(mailmessage * msg)
+{
+ return cached_session_get_maildir_session(msg->msg_session);
+}
+
+static int prefetch(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int res;
+ struct maildir_msg_data * data;
+ char * filename;
+ int fd;
+ char * mapping;
+ struct maildir * md;
+
+ md = get_maildir_session(msg_info);
+
+ filename = maildir_message_get(md, msg_info->msg_uid);
+ if (filename == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ fd = open(filename, O_RDONLY);
+ free(filename);
+ if (fd == -1) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (mapping == MAP_FAILED) {
+ res = MAIL_ERROR_FILE;
+ goto close;
+ }
+
+ data = malloc(sizeof(* data));
+ if (data == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto unmap;
+ }
+
+ data->fd = fd;
+
+ msg = msg_info->msg_data;
+
+ msg->msg_data = data;
+ msg->msg_message = mapping;
+ msg->msg_length = msg_info->msg_size;
+
+ return MAIL_NO_ERROR;
+
+ unmap:
+ munmap(mapping, msg_info->msg_size);
+ close:
+ close(fd);
+ err:
+ return res;
+}
+
+static void prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ struct maildir_msg_data * data;
+
+ munmap(msg->msg_message, msg->msg_length);
+ msg->msg_message = NULL;
+ data = msg->msg_data;
+ close(data->fd);
+ free(data);
+ }
+}
+
+static int initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = prefetch;
+ msg->msg_prefetch_free = prefetch_free;
+
+ return MAIL_NO_ERROR;
+}
+
+static void check(mailmessage * msg_info)
+{
+ int r;
+
+ if (msg_info->msg_flags != NULL) {
+ r = mail_flags_store_set(get_session_ancestor_data(msg_info)->md_flags_store, msg_info);
+
+ r = mail_flags_store_set(get_cached_session_data(msg_info)->md_flags_store, msg_info);
+ /* ignore errors */
+ }
+}
+
+#define FLAGS_NAME "flags.db"
+
+static int get_flags(mailmessage * msg_info,
+ struct mail_flags ** result)
+{
+ struct mail_cache_db * cache_db_flags;
+ chashdatum key;
+ chashdatum value;
+ struct maildir * md;
+ struct mail_flags * flags;
+ struct maildir_cached_session_state_data * data;
+ struct maildir_msg * md_msg;
+ int r;
+ uint32_t driver_flags;
+ char filename_flags[PATH_MAX];
+ char keyname[PATH_MAX];
+ MMAPString * mmapstr;
+
+ if (msg_info->msg_flags != NULL) {
+ * result = msg_info->msg_flags;
+ return MAIL_NO_ERROR;
+ }
+
+ data = get_cached_session_data(msg_info);
+ flags = mail_flags_store_get(data->md_flags_store,
+ msg_info->msg_index);
+ if (flags != NULL) {
+ msg_info->msg_flags = flags;
+ * result = msg_info->msg_flags;
+ return MAIL_NO_ERROR;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
+ data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
+ MAIL_DIR_SEPARATOR, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0)
+ return MAIL_ERROR_FILE;
+
+ snprintf(keyname, PATH_MAX, "%s-flags", msg_info->msg_uid);
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ return MAIL_ERROR_MEMORY;
+ }
+
+ r = generic_cache_flags_read(cache_db_flags, mmapstr, keyname, &flags);
+ mmap_string_free(mmapstr);
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ if (r != MAIL_NO_ERROR) {
+ flags = mail_flags_new_empty();
+ if (flags == NULL)
+ return MAIL_ERROR_MEMORY;
+ }
+
+ md = get_maildir_session(msg_info);
+ if (md == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ key.data = msg_info->msg_uid;
+ key.len = strlen(msg_info->msg_uid);
+ r = chash_get(md->mdir_msg_hash, &key, &value);
+ if (r < 0)
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ md_msg = value.data;
+
+ driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags);
+
+ flags->fl_flags = driver_flags;
+ msg_info->msg_flags = flags;
+
+ * result = msg_info->msg_flags;
+
+ return MAIL_NO_ERROR;
+}
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.h b/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.h
new file mode 100644
index 0000000..b9e0215
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_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 MAILDIRDRIVER_CACHED_MESSAGE_H
+
+#define MAILDIRDRIVER_CACHED_MESSAGE_H
+
+#include <libetpan/maildirdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * maildir_cached_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_message.c b/libetpan/src/driver/implementation/maildir/maildirdriver_message.c
new file mode 100644
index 0000000..58bc6bd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_message.c
@@ -0,0 +1,255 @@
+/*
+ * 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 "maildirdriver_message.h"
+#include "maildirdriver_tools.h"
+
+#include "mailmessage_tools.h"
+#include "maildirdriver.h"
+#include "maildir.h"
+#include "generic_cache.h"
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+static int get_flags(mailmessage * msg_info,
+ struct mail_flags ** result);
+
+static int prefetch(mailmessage * msg_info);
+
+static void prefetch_free(struct generic_message_t * msg);
+
+static int initialize(mailmessage * msg_info);
+
+static void check(mailmessage * msg_info);
+
+static mailmessage_driver local_maildir_message_driver = {
+ .msg_name = "maildir",
+
+ .msg_initialize = initialize,
+ .msg_uninitialize = mailmessage_generic_uninitialize,
+
+ .msg_flush = mailmessage_generic_flush,
+ .msg_check = check,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = mailmessage_generic_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_header,
+ .msg_fetch_size = NULL,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = get_flags,
+};
+
+mailmessage_driver * maildir_message_driver = &local_maildir_message_driver;
+
+struct maildir_msg_data {
+ int fd;
+};
+
+static inline struct maildir_session_state_data *
+get_session_data(mailmessage * msg)
+{
+ return msg->msg_session->sess_data;
+}
+
+static struct maildir * get_maildir_session(mailmessage * msg)
+{
+ return get_session_data(msg)->md_session;
+}
+
+static int prefetch(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int res;
+ struct maildir_msg_data * data;
+ char * filename;
+ int fd;
+ char * mapping;
+ struct maildir * md;
+
+ md = get_maildir_session(msg_info);
+
+ if (msg_info->msg_uid == NULL) {
+ res = MAIL_ERROR_INVAL;
+ goto err;
+ }
+
+ filename = maildir_message_get(md, msg_info->msg_uid);
+ if (filename == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ fd = open(filename, O_RDONLY);
+ free(filename);
+ if (fd == -1) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (mapping == MAP_FAILED) {
+ res = MAIL_ERROR_FILE;
+ goto close;
+ }
+
+ data = malloc(sizeof(* data));
+ if (data == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto unmap;
+ }
+
+ data->fd = fd;
+
+ msg = msg_info->msg_data;
+
+ msg->msg_data = data;
+ msg->msg_message = mapping;
+ msg->msg_length = msg_info->msg_size;
+
+ return MAIL_NO_ERROR;
+
+ unmap:
+ munmap(mapping, msg_info->msg_size);
+ close:
+ close(fd);
+ err:
+ return res;
+}
+
+static void prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ struct maildir_msg_data * data;
+
+ munmap(msg->msg_message, msg->msg_length);
+ msg->msg_message = NULL;
+ data = msg->msg_data;
+ close(data->fd);
+ free(data);
+ }
+}
+
+static int initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = prefetch;
+ msg->msg_prefetch_free = prefetch_free;
+
+ return MAIL_NO_ERROR;
+}
+
+static void check(mailmessage * msg_info)
+{
+ int r;
+
+ if (msg_info->msg_flags != NULL) {
+ r = mail_flags_store_set(get_session_data(msg_info)->md_flags_store,
+ msg_info);
+ /* ignore errors */
+ }
+}
+
+static int get_flags(mailmessage * msg_info,
+ struct mail_flags ** result)
+{
+ chashdatum key;
+ chashdatum value;
+ struct maildir * md;
+ struct mail_flags * flags;
+ struct maildir_session_state_data * data;
+ struct maildir_msg * md_msg;
+ int r;
+ uint32_t driver_flags;
+ clist * ext;
+
+ if (msg_info->msg_flags != NULL) {
+ * result = msg_info->msg_flags;
+ return MAIL_NO_ERROR;
+ }
+
+ data = get_session_data(msg_info);
+ flags = mail_flags_store_get(data->md_flags_store,
+ msg_info->msg_index);
+ if (flags != NULL) {
+ msg_info->msg_flags = flags;
+ * result = msg_info->msg_flags;
+ return MAIL_NO_ERROR;
+ }
+
+ md = get_maildir_session(msg_info);
+ if (md == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ key.data = msg_info->msg_uid;
+ key.len = strlen(msg_info->msg_uid);
+ r = chash_get(md->mdir_msg_hash, &key, &value);
+ if (r < 0)
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ md_msg = value.data;
+
+ driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags);
+
+ ext = clist_new();
+ if (ext == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ msg_info->msg_flags = mail_flags_new(driver_flags, ext);
+
+ * result = msg_info->msg_flags;
+
+ return MAIL_NO_ERROR;
+}
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_message.h b/libetpan/src/driver/implementation/maildir/maildirdriver_message.h
new file mode 100644
index 0000000..ed0a4d1
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_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 MAILDIRDRIVER_MESSAGE_H
+
+#define MAILDIRDRIVER_MESSAGE_H
+
+#include <libetpan/maildirdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * maildir_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_tools.c b/libetpan/src/driver/implementation/maildir/maildirdriver_tools.c
new file mode 100644
index 0000000..e3036e8
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_tools.c
@@ -0,0 +1,198 @@
+/*
+ * 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 "mailmessage.h"
+#include "maildirdriver_tools.h"
+#include "maildir.h"
+#include "generic_cache.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+
+int maildirdriver_maildir_error_to_mail_error(int error)
+{
+ switch (error) {
+ case MAILDIR_NO_ERROR:
+ return MAIL_NO_ERROR;
+
+ case MAILDIR_ERROR_CREATE:
+ return MAIL_ERROR_FILE;
+
+ case MAILDIR_ERROR_DIRECTORY:
+ return MAIL_ERROR_FILE;
+
+ case MAILDIR_ERROR_MEMORY:
+ return MAIL_ERROR_MEMORY;
+
+ case MAILDIR_ERROR_FILE:
+ return MAIL_ERROR_FILE;
+
+ case MAILDIR_ERROR_FOLDER:
+ return MAIL_ERROR_FOLDER;
+
+ case MAILDIR_ERROR_NOT_FOUND:
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ default:
+ return MAIL_ERROR_INVAL;
+ }
+}
+
+
+
+uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags)
+{
+ uint32_t flags;
+
+ flags = 0;
+ if ((md_flags & MAILDIR_FLAG_NEW) != 0)
+ flags |= MAIL_FLAG_NEW;
+
+ if ((md_flags & MAILDIR_FLAG_SEEN) != 0)
+ flags |= MAIL_FLAG_SEEN;
+
+ if ((md_flags & MAILDIR_FLAG_REPLIED) != 0)
+ flags |= MAIL_FLAG_ANSWERED;
+
+ if ((md_flags & MAILDIR_FLAG_FLAGGED) != 0)
+ flags |= MAIL_FLAG_FLAGGED;
+
+ if ((md_flags & MAILDIR_FLAG_TRASHED) != 0)
+ flags |= MAIL_FLAG_DELETED;
+
+ return flags;
+}
+
+uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags)
+{
+ uint32_t md_flags;
+
+ md_flags = 0;
+ if ((flags & MAIL_FLAG_NEW) != 0)
+ md_flags |= MAILDIR_FLAG_NEW;
+
+ if ((flags & MAIL_FLAG_SEEN) != 0)
+ md_flags |= MAILDIR_FLAG_SEEN;
+
+ if ((flags & MAIL_FLAG_ANSWERED) != 0)
+ md_flags |= MAILDIR_FLAG_REPLIED;
+
+ if ((flags & MAIL_FLAG_FLAGGED) != 0)
+ md_flags |= MAILDIR_FLAG_FLAGGED;
+
+ if ((flags & MAIL_FLAG_DELETED) != 0)
+ md_flags |= MAILDIR_FLAG_TRASHED;
+
+ return md_flags;
+}
+
+
+int maildir_get_messages_list(mailsession * session, struct maildir * md,
+ mailmessage_driver * message_driver,
+ struct mailmessage_list ** result)
+{
+ unsigned int i;
+ struct mailmessage_list * env_list;
+ int r;
+ carray * tab;
+ int res;
+
+ tab = carray_new(128);
+ if (tab == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) {
+ struct maildir_msg * md_msg;
+ mailmessage * msg;
+ char * filename;
+ struct stat stat_info;
+
+ md_msg = carray_get(md->mdir_msg_list, i);
+
+ filename = maildir_message_get(md, md_msg->msg_uid);
+ r = stat(filename, &stat_info);
+ free(filename);
+ if (r < 0)
+ continue;
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = mailmessage_init(msg, session, message_driver,
+ i + 1, stat_info.st_size);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg);
+ res = r;
+ goto free_list;
+ }
+
+ msg->msg_uid = strdup(md_msg->msg_uid);
+ if (msg->msg_uid == NULL) {
+ mailmessage_free(msg);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = carray_add(tab, msg, NULL);
+ if (r < 0) {
+ mailmessage_free(msg);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ env_list = mailmessage_list_new(tab);
+ if (env_list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = env_list;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ for(i = 0 ; i < carray_count(tab) ; i ++)
+ mailmessage_free(carray_get(tab, i));
+ carray_free(tab);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_tools.h b/libetpan/src/driver/implementation/maildir/maildirdriver_tools.h
new file mode 100644
index 0000000..0a738c9
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_tools.h
@@ -0,0 +1,53 @@
+/*
+ * 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 MAILDIRDRIVER_TOOLS_H
+
+#define MAILDIRDRIVER_TOOLS_H
+
+#include "maildriver_types.h"
+#include "maildir.h"
+
+int maildirdriver_maildir_error_to_mail_error(int error);
+
+uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags);
+
+uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags);
+
+int maildir_get_messages_list(mailsession * session, struct maildir * md,
+ mailmessage_driver * message_driver,
+ struct mailmessage_list ** result);
+
+#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_types.h b/libetpan/src/driver/implementation/maildir/maildirdriver_types.h
new file mode 100644
index 0000000..c965b3e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_types.h
@@ -0,0 +1,96 @@
+/*
+ * 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 MAILDIRDRIVER_TYPES_H
+
+#define MAILDIRDRIVER_TYPES_H
+
+#include <libetpan/libetpan-config.h>
+
+#include <libetpan/maildriver_types.h>
+#include <libetpan/maildir.h>
+#include <libetpan/generic_cache_types.h>
+#include <libetpan/mailstorage_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct maildir_session_state_data {
+ struct maildir * md_session;
+ struct mail_flags_store * md_flags_store;
+};
+
+enum {
+ MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
+ MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY,
+};
+
+struct maildir_cached_session_state_data {
+ mailsession * md_ancestor;
+ char * md_quoted_mb;
+ struct mail_flags_store * md_flags_store;
+ char md_cache_directory[PATH_MAX];
+ char md_flags_directory[PATH_MAX];
+};
+
+/* maildir storage */
+
+/*
+ maildir_mailstorage is the state data specific to the maildir storage.
+
+ - pathname is the path of the maildir storage.
+
+ - cached if this value is != 0, a persistant cache will be
+ stored on local system.
+
+ - cache_directory is the location of the cache.
+
+ - flags_directory is the location of the flags.
+*/
+
+struct maildir_mailstorage {
+ char * md_pathname;
+
+ int md_cached;
+ char * md_cache_directory;
+ char * md_flags_directory;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirstorage.c b/libetpan/src/driver/implementation/maildir/maildirstorage.c
new file mode 100644
index 0000000..09f95c7
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirstorage.c
@@ -0,0 +1,193 @@
+/*
+ * 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 "maildirstorage.h"
+#include "mailstorage.h"
+
+#include "mail.h"
+#include "mailmessage.h"
+#include "maildirdriver.h"
+#include "maildirdriver_cached.h"
+#include "maildriver.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* maildir storage */
+
+static int maildir_mailstorage_connect(struct mailstorage * storage);
+static int
+maildir_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result);
+static void maildir_mailstorage_uninitialize(struct mailstorage * storage);
+
+static mailstorage_driver maildir_mailstorage_driver = {
+ .sto_name = "maildir",
+ .sto_connect = maildir_mailstorage_connect,
+ .sto_get_folder_session = maildir_mailstorage_get_folder_session,
+ .sto_uninitialize = maildir_mailstorage_uninitialize,
+};
+
+int maildir_mailstorage_init(struct mailstorage * storage,
+ char * md_pathname, int md_cached,
+ char * md_cache_directory, char * md_flags_directory)
+{
+ struct maildir_mailstorage * maildir_storage;
+
+ maildir_storage = malloc(sizeof(* maildir_storage));
+ if (maildir_storage == NULL)
+ goto err;
+
+ maildir_storage->md_pathname = strdup(md_pathname);
+ if (maildir_storage->md_pathname == NULL)
+ goto free;
+
+ maildir_storage->md_cached = md_cached;
+
+ if (md_cached && (md_cache_directory != NULL) &&
+ (md_flags_directory != NULL)) {
+ maildir_storage->md_cache_directory = strdup(md_cache_directory);
+ if (maildir_storage->md_cache_directory == NULL)
+ goto free_pathname;
+
+ maildir_storage->md_flags_directory = strdup(md_flags_directory);
+ if (maildir_storage->md_flags_directory == NULL)
+ goto free_cache_directory;
+ }
+ else {
+ maildir_storage->md_cached = FALSE;
+ maildir_storage->md_cache_directory = NULL;
+ maildir_storage->md_flags_directory = NULL;
+ }
+
+ storage->sto_data = maildir_storage;
+ storage->sto_driver = &maildir_mailstorage_driver;
+
+ return MAIL_NO_ERROR;
+
+ free_cache_directory:
+ free(maildir_storage->md_cache_directory);
+ free_pathname:
+ free(maildir_storage->md_pathname);
+ free:
+ free(maildir_storage);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void maildir_mailstorage_uninitialize(struct mailstorage * storage)
+{
+ struct maildir_mailstorage * maildir_storage;
+
+ maildir_storage = storage->sto_data;
+ if (maildir_storage->md_flags_directory != NULL)
+ free(maildir_storage->md_flags_directory);
+ if (maildir_storage->md_cache_directory != NULL)
+ free(maildir_storage->md_cache_directory);
+ free(maildir_storage->md_pathname);
+ free(maildir_storage);
+
+ storage->sto_data = NULL;
+}
+
+static int maildir_mailstorage_connect(struct mailstorage * storage)
+{
+ struct maildir_mailstorage * maildir_storage;
+ mailsession_driver * driver;
+ int r;
+ int res;
+ mailsession * session;
+
+ maildir_storage = storage->sto_data;
+
+ if (maildir_storage->md_cached)
+ driver = maildir_cached_session_driver;
+ else
+ driver = maildir_session_driver;
+
+ session = mailsession_new(driver);
+ if (session == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ if (maildir_storage->md_cached) {
+ r = mailsession_parameters(session,
+ MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY,
+ maildir_storage->md_cache_directory);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ r = mailsession_parameters(session,
+ MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY,
+ maildir_storage->md_flags_directory);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+ }
+
+ r = mailsession_connect_path(session, maildir_storage->md_pathname);
+ switch (r) {
+ case MAIL_NO_ERROR_NON_AUTHENTICATED:
+ case MAIL_NO_ERROR_AUTHENTICATED:
+ case MAIL_NO_ERROR:
+ break;
+ default:
+ res = r;
+ goto free;
+ }
+
+ storage->sto_session = session;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailsession_free(session);
+ err:
+ return res;
+}
+
+static int
+maildir_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result)
+{
+ * result = storage->sto_session;
+
+ return MAIL_NO_ERROR;
+}
+
diff --git a/libetpan/src/driver/implementation/maildir/maildirstorage.h b/libetpan/src/driver/implementation/maildir/maildirstorage.h
new file mode 100644
index 0000000..0ad04b9
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirstorage.h
@@ -0,0 +1,69 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef MAILDIRSTORAGE_H
+
+#define MAILDIRSTORAGE_H
+
+#include <libetpan/maildirdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ maildir_mailstorage_init is the constructor for a maildir storage.
+
+ @param storage this is the storage to initialize.
+
+ @param pathname is the directory that contains the mailbox.
+
+ @param cached if this value is != 0, a persistant cache will be
+ stored on local system.
+
+ @param cache_directory is the location of the cache
+
+ @param flags_directory is the location of the flags
+*/
+
+int maildir_mailstorage_init(struct mailstorage * storage,
+ char * md_pathname, int md_cached,
+ char * md_cache_directory, char * md_flags_directory);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver.c b/libetpan/src/driver/implementation/mbox/mboxdriver.c
new file mode 100644
index 0000000..72afa6d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver.c
@@ -0,0 +1,515 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "mboxdriver.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <sys/times.h>
+
+#include "mail.h"
+#include "maildriver_tools.h"
+#include "mailmbox.h"
+#include "mboxdriver_tools.h"
+#include "maildriver.h"
+#include "carray.h"
+#include "mboxdriver_message.h"
+#include "mailmessage.h"
+
+static int mboxdriver_initialize(mailsession * session);
+
+static void mboxdriver_uninitialize(mailsession * session);
+
+static int mboxdriver_parameters(mailsession * session,
+ int id, void * value);
+
+static int mboxdriver_connect_path(mailsession * session, char * path);
+
+static int mboxdriver_logout(mailsession * session);
+
+static int mboxdriver_expunge_folder(mailsession * session);
+
+static int mboxdriver_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int mboxdriver_messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int mboxdriver_append_message(mailsession * session,
+ char * message, size_t size);
+
+static int mboxdriver_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
+
+static int mboxdriver_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int
+mboxdriver_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list);
+
+static int mboxdriver_remove_message(mailsession * session, uint32_t num);
+
+static int mboxdriver_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static int mboxdriver_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result);
+
+static mailsession_driver local_mbox_session_driver = {
+ .sess_name = "mbox",
+
+ .sess_initialize = mboxdriver_initialize,
+ .sess_uninitialize = mboxdriver_uninitialize,
+
+ .sess_parameters = mboxdriver_parameters,
+
+ .sess_connect_path = mboxdriver_connect_path,
+ .sess_connect_stream = NULL,
+ .sess_starttls = NULL,
+ .sess_login = NULL,
+ .sess_logout = mboxdriver_logout,
+ .sess_noop = NULL,
+
+ .sess_build_folder_name = NULL,
+ .sess_create_folder = NULL,
+ .sess_delete_folder = NULL,
+ .sess_rename_folder = NULL,
+ .sess_check_folder = NULL,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = NULL,
+ .sess_expunge_folder = mboxdriver_expunge_folder,
+ .sess_status_folder = mboxdriver_status_folder,
+ .sess_messages_number = mboxdriver_messages_number,
+ .sess_recent_number = mboxdriver_messages_number,
+ .sess_unseen_number = mboxdriver_messages_number,
+ .sess_list_folders = NULL,
+ .sess_lsub_folders = NULL,
+ .sess_subscribe_folder = NULL,
+ .sess_unsubscribe_folder = NULL,
+
+ .sess_append_message = mboxdriver_append_message,
+ .sess_append_message_flags = mboxdriver_append_message_flags,
+ .sess_copy_message = NULL,
+ .sess_move_message = NULL,
+
+ .sess_get_messages_list = mboxdriver_get_messages_list,
+ .sess_get_envelopes_list = mboxdriver_get_envelopes_list,
+ .sess_remove_message = mboxdriver_remove_message,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = mboxdriver_get_message,
+ .sess_get_message_by_uid = mboxdriver_get_message_by_uid,
+};
+
+mailsession_driver * mbox_session_driver = &local_mbox_session_driver;
+
+static inline struct mbox_session_state_data * get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline struct mailmbox_folder * get_mbox_session(mailsession * session)
+{
+ return get_data(session)->mbox_folder;
+}
+
+static int mboxdriver_initialize(mailsession * session)
+{
+ struct mbox_session_state_data * data;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto err;
+
+ data->mbox_folder = NULL;
+
+ data->mbox_force_read_only = FALSE;
+ data->mbox_force_no_uid = TRUE;
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void free_state(struct mbox_session_state_data * mbox_data)
+{
+ if (mbox_data->mbox_folder != NULL) {
+ mailmbox_done(mbox_data->mbox_folder);
+ mbox_data->mbox_folder = NULL;
+ }
+}
+
+static void mboxdriver_uninitialize(mailsession * session)
+{
+ struct mbox_session_state_data * data;
+
+ data = get_data(session);
+
+ free_state(data);
+
+ free(data);
+}
+
+static int mboxdriver_parameters(mailsession * session,
+ int id, void * value)
+{
+ struct mbox_session_state_data * data;
+
+ data = get_data(session);
+
+ switch (id) {
+ case MBOXDRIVER_SET_READ_ONLY:
+ {
+ int * param;
+
+ param = value;
+
+ data->mbox_force_read_only = * param;
+ return MAIL_NO_ERROR;
+ }
+
+ case MBOXDRIVER_SET_NO_UID:
+ {
+ int * param;
+
+ param = value;
+
+ data->mbox_force_no_uid = * param;
+ return MAIL_NO_ERROR;
+ }
+ }
+
+ return MAIL_ERROR_INVAL;
+}
+
+
+static int mboxdriver_connect_path(mailsession * session, char * path)
+{
+ struct mbox_session_state_data * mbox_data;
+ struct mailmbox_folder * folder;
+ int r;
+
+ mbox_data = get_data(session);
+
+ if (mbox_data->mbox_folder != NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = mailmbox_init(path,
+ mbox_data->mbox_force_read_only,
+ mbox_data->mbox_force_no_uid,
+ 0,
+ &folder);
+
+ if (r != MAILMBOX_NO_ERROR)
+ return mboxdriver_mbox_error_to_mail_error(r);
+
+ mbox_data->mbox_folder = folder;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mboxdriver_logout(mailsession * session)
+{
+ struct mbox_session_state_data * mbox_data;
+
+ mbox_data = get_data(session);
+
+ if (mbox_data->mbox_folder == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ free_state(mbox_data);
+
+ mbox_data->mbox_folder = NULL;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mboxdriver_expunge_folder(mailsession * session)
+{
+ int r;
+ struct mbox_session_state_data * mbox_data;
+
+ mbox_data = get_data(session);
+
+ if (mbox_data->mbox_folder == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = mailmbox_expunge(mbox_data->mbox_folder);
+ if (r != MAILMBOX_NO_ERROR)
+ return mboxdriver_mbox_error_to_mail_error(r);
+
+ return MAIL_NO_ERROR;
+}
+
+static int mboxdriver_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ uint32_t count;
+ int r;
+
+ r = mboxdriver_messages_number(session, mb, &count);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result_messages = count;
+ * result_recent = count;
+ * result_unseen = count;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mboxdriver_messages_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ struct mailmbox_folder * folder;
+ int r;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL)
+ return MAIL_ERROR_STATUS;
+
+ r = mailmbox_validate_read_lock(folder);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ mailmbox_read_unlock(folder);
+
+ * result = carray_count(folder->mb_tab) - folder->mb_deleted_count;
+
+ return MAILMBOX_NO_ERROR;
+}
+
+/* messages operations */
+
+static int mboxdriver_append_message(mailsession * session,
+ char * message, size_t size)
+{
+ int r;
+ struct mailmbox_folder * folder;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL)
+ return MAIL_ERROR_APPEND;
+
+ r = mailmbox_append_message(folder, message, size);
+
+ switch (r) {
+ case MAILMBOX_ERROR_FILE:
+ return MAIL_ERROR_DISKSPACE;
+ default:
+ return mboxdriver_mbox_error_to_mail_error(r);
+ }
+}
+
+static int mboxdriver_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ return mboxdriver_append_message(session, message, size);
+}
+
+static int mboxdriver_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ struct mailmbox_folder * folder;
+ int res;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ return mbox_get_messages_list(folder, session, mbox_message_driver, result);
+
+ err:
+ return res;
+}
+
+static int
+mboxdriver_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list)
+{
+ struct mailmbox_folder * folder;
+ unsigned int i;
+ int r;
+ int res;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ r = mailmbox_validate_read_lock(folder);
+ if (r != MAILMBOX_NO_ERROR) {
+ res = mboxdriver_mbox_error_to_mail_error(r);
+ goto err;
+ }
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+ struct mailimf_fields * fields;
+ char * headers;
+ size_t headers_len;
+ size_t cur_token;
+
+ msg = carray_get(env_list->msg_tab, i);
+ if (msg == NULL)
+ continue;
+
+ if (msg->msg_fields != NULL)
+ continue;
+
+ r = mailmbox_fetch_msg_headers_no_lock(folder,
+ msg->msg_index, &headers, &headers_len);
+ if (r != MAILMBOX_NO_ERROR) {
+ res = mboxdriver_mbox_error_to_mail_error(r);
+ goto unlock;
+ }
+
+ cur_token = 0;
+ r = mailimf_envelope_fields_parse(headers, headers_len,
+ &cur_token, &fields);
+
+ if (r != MAILIMF_NO_ERROR)
+ continue;
+
+ msg->msg_fields = fields;
+ }
+
+ mailmbox_read_unlock(folder);
+
+ return MAIL_NO_ERROR;
+
+ unlock:
+ mailmbox_read_unlock(folder);
+ err:
+ return res;
+}
+
+
+static int mboxdriver_remove_message(mailsession * session, uint32_t num)
+{
+ int r;
+ struct mailmbox_folder * folder;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL)
+ return MAIL_ERROR_DELETE;
+
+ r = mailmbox_delete_msg(folder, num);
+
+ return mboxdriver_mbox_error_to_mail_error(r);
+}
+
+static int mboxdriver_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result)
+{
+ mailmessage * msg_info;
+ int r;
+
+ msg_info = mailmessage_new();
+ if (msg_info == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_init(msg_info, session, mbox_message_driver, num, 0);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg_info);
+ return r;
+ }
+
+ * result = msg_info;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mboxdriver_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result)
+{
+ uint32_t num;
+ char * p;
+ chashdatum key;
+ chashdatum data;
+ struct mailmbox_msg_info * info;
+ struct mailmbox_folder * folder;
+ int r;
+
+ if (uid == NULL)
+ return MAIL_ERROR_INVAL;
+
+ num = strtoul(uid, &p, 10);
+ if (p == uid || * p != '-')
+ return MAIL_ERROR_INVAL;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ key.data = &num;
+ key.len = sizeof(num);
+
+ r = chash_get(folder->mb_hash, &key, &data);
+ if (r == 0) {
+ char * body_len_p = p + 1;
+ size_t body_len;
+
+ info = data.data;
+ /* Check if the cached message has the same UID */
+ body_len = strtoul(body_len_p, &p, 10);
+ if (p == body_len_p || * p != '\0')
+ return MAIL_ERROR_INVAL;
+
+ if (body_len == info->msg_body_len)
+ return mboxdriver_get_message(session, num, result);
+ }
+
+ return MAIL_ERROR_MSG_NOT_FOUND;
+}
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver.h b/libetpan/src/driver/implementation/mbox/mboxdriver.h
new file mode 100644
index 0000000..9b37aa4
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver.h
@@ -0,0 +1,52 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef MBOXDRIVER_H
+
+#define MBOXDRIVER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libetpan/mboxdriver_types.h>
+
+extern mailsession_driver * mbox_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c
new file mode 100644
index 0000000..eaa0e48
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c
@@ -0,0 +1,1337 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "mboxdriver_cached.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include "mail.h"
+#include "mail_cache_db.h"
+#include "mboxdriver.h"
+#include "mboxdriver_tools.h"
+#include "maildriver_tools.h"
+#include "mailmbox.h"
+#include "maildriver.h"
+#include "carray.h"
+#include "generic_cache.h"
+#include "imfcache.h"
+#include "mboxdriver_cached_message.h"
+#include "libetpan-config.h"
+
+static int mboxdriver_cached_initialize(mailsession * session);
+
+static void mboxdriver_cached_uninitialize(mailsession * session);
+
+static int mboxdriver_cached_parameters(mailsession * session,
+ int id, void * value);
+
+static int mboxdriver_cached_connect_path(mailsession * session, char * path);
+
+static int mboxdriver_cached_logout(mailsession * session);
+
+static int mboxdriver_cached_check_folder(mailsession * session);
+
+static int mboxdriver_cached_expunge_folder(mailsession * session);
+
+static int mboxdriver_cached_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen);
+static int mboxdriver_cached_messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+static int mboxdriver_cached_recent_number(mailsession * session, char * mb,
+ uint32_t * result);
+static int mboxdriver_cached_unseen_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int mboxdriver_cached_append_message(mailsession * session,
+ char * message, size_t size);
+
+static int mboxdriver_cached_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
+
+static int
+mboxdriver_cached_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int
+mboxdriver_cached_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list);
+
+static int mboxdriver_cached_remove_message(mailsession * session,
+ uint32_t num);
+
+static int mboxdriver_cached_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static int mboxdriver_cached_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result);
+
+static mailsession_driver local_mbox_cached_session_driver = {
+ .sess_name = "mbox-cached",
+
+ .sess_initialize = mboxdriver_cached_initialize,
+ .sess_uninitialize = mboxdriver_cached_uninitialize,
+
+ .sess_parameters = mboxdriver_cached_parameters,
+
+ .sess_connect_path = mboxdriver_cached_connect_path,
+ .sess_connect_stream = NULL,
+ .sess_starttls = NULL,
+ .sess_login = NULL,
+ .sess_logout = mboxdriver_cached_logout,
+ .sess_noop = NULL,
+
+ .sess_build_folder_name = NULL,
+ .sess_create_folder = NULL,
+ .sess_delete_folder = NULL,
+ .sess_rename_folder = NULL,
+ .sess_check_folder = mboxdriver_cached_check_folder,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = NULL,
+ .sess_expunge_folder = mboxdriver_cached_expunge_folder,
+ .sess_status_folder = mboxdriver_cached_status_folder,
+ .sess_messages_number = mboxdriver_cached_messages_number,
+ .sess_recent_number = mboxdriver_cached_recent_number,
+ .sess_unseen_number = mboxdriver_cached_unseen_number,
+ .sess_list_folders = NULL,
+ .sess_lsub_folders = NULL,
+ .sess_subscribe_folder = NULL,
+ .sess_unsubscribe_folder = NULL,
+
+ .sess_append_message = mboxdriver_cached_append_message,
+ .sess_append_message_flags = mboxdriver_cached_append_message_flags,
+
+ .sess_copy_message = NULL,
+ .sess_move_message = NULL,
+
+ .sess_get_messages_list = mboxdriver_cached_get_messages_list,
+ .sess_get_envelopes_list = mboxdriver_cached_get_envelopes_list,
+ .sess_remove_message = mboxdriver_cached_remove_message,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = mboxdriver_cached_get_message,
+ .sess_get_message_by_uid = mboxdriver_cached_get_message_by_uid,
+};
+
+mailsession_driver * mbox_cached_session_driver =
+&local_mbox_cached_session_driver;
+
+
+#define ENV_NAME "env.db"
+#define FLAGS_NAME "flags.db"
+
+
+
+static int mbox_error_to_mail_error(int error)
+{
+ switch (error) {
+ case MAILMBOX_NO_ERROR:
+ return MAIL_NO_ERROR;
+
+ case MAILMBOX_ERROR_PARSE:
+ return MAIL_ERROR_PARSE;
+
+ case MAILMBOX_ERROR_INVAL:
+ return MAIL_ERROR_INVAL;
+
+ case MAILMBOX_ERROR_FILE_NOT_FOUND:
+ return MAIL_ERROR_PARSE;
+
+ case MAILMBOX_ERROR_MEMORY:
+ return MAIL_ERROR_MEMORY;
+
+ case MAILMBOX_ERROR_TEMPORARY_FILE:
+ return MAIL_ERROR_PARSE;
+
+ case MAILMBOX_ERROR_FILE:
+ return MAIL_ERROR_FILE;
+
+ case MAILMBOX_ERROR_MSG_NOT_FOUND:
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ case MAILMBOX_ERROR_READONLY:
+ return MAIL_ERROR_READONLY;
+
+ default:
+ return MAIL_ERROR_INVAL;
+ }
+}
+
+
+
+
+static inline struct mbox_cached_session_state_data *
+get_cached_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline mailsession * get_ancestor(mailsession * session)
+{
+ return get_cached_data(session)->mbox_ancestor;
+}
+
+static inline struct mbox_session_state_data *
+get_ancestor_data(mailsession * session)
+{
+ return get_ancestor(session)->sess_data;
+}
+
+static inline struct mailmbox_folder *
+get_mbox_session(mailsession * session)
+{
+ return get_ancestor_data(session)->mbox_folder;
+}
+
+static int mboxdriver_cached_initialize(mailsession * session)
+{
+ struct mbox_cached_session_state_data * cached_data;
+ struct mbox_session_state_data * mbox_data;
+
+ cached_data = malloc(sizeof(* cached_data));
+ if (cached_data == NULL)
+ goto err;
+
+ cached_data->mbox_flags_store = mail_flags_store_new();
+ if (cached_data->mbox_flags_store == NULL)
+ goto free;
+
+ cached_data->mbox_ancestor = mailsession_new(mbox_session_driver);
+ if (cached_data->mbox_ancestor == NULL)
+ goto free_store;
+
+ cached_data->mbox_quoted_mb = NULL;
+ /*
+ UID must be enabled to take advantage of the cache
+ */
+ mbox_data = cached_data->mbox_ancestor->sess_data;
+ mbox_data->mbox_force_no_uid = FALSE;
+
+ session->sess_data = cached_data;
+
+ return MAIL_NO_ERROR;
+
+ free_store:
+ mail_flags_store_free(cached_data->mbox_flags_store);
+ free:
+ free(cached_data);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void free_state(struct mbox_cached_session_state_data * mbox_data)
+{
+ if (mbox_data->mbox_quoted_mb) {
+ free(mbox_data->mbox_quoted_mb);
+ mbox_data->mbox_quoted_mb = NULL;
+ }
+}
+
+static int mbox_flags_store_process(char * flags_directory, char * quoted_mb,
+ struct mail_flags_store * flags_store)
+{
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ unsigned int i;
+ int r;
+ int res;
+
+ if (carray_count(flags_store->fls_tab) == 0)
+ return MAIL_NO_ERROR;
+
+ if (quoted_mb == NULL)
+ return MAIL_NO_ERROR;
+
+ snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
+ flags_directory, MAIL_DIR_SEPARATOR, quoted_mb,
+ MAIL_DIR_SEPARATOR, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(flags_store->fls_tab, i);
+
+ r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_uid, msg->msg_flags);
+ if (r != MAIL_NO_ERROR) {
+ /* ignore errors */
+ }
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ mail_flags_store_clear(flags_store);
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static void mboxdriver_cached_uninitialize(mailsession * session)
+{
+ struct mbox_cached_session_state_data * data;
+
+ data = get_cached_data(session);
+
+ mbox_flags_store_process(data->mbox_flags_directory,
+ data->mbox_quoted_mb,
+ data->mbox_flags_store);
+
+ mail_flags_store_free(data->mbox_flags_store);
+
+ free_state(data);
+ mailsession_free(data->mbox_ancestor);
+ free(data);
+
+ session->sess_data = NULL;
+}
+
+static int mboxdriver_cached_parameters(mailsession * session,
+ int id, void * value)
+{
+ struct mbox_cached_session_state_data * data;
+ int r;
+
+ data = get_cached_data(session);
+
+ switch (id) {
+ case MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY:
+ strncpy(data->mbox_cache_directory, value, PATH_MAX);
+ data->mbox_cache_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(data->mbox_cache_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+
+ case MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY:
+ strncpy(data->mbox_flags_directory, value, PATH_MAX);
+ data->mbox_flags_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(data->mbox_flags_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+
+ case MBOXDRIVER_SET_NO_UID:
+ return MAIL_ERROR_INVAL;
+
+ default:
+ return mailsession_parameters(data->mbox_ancestor, id, value);
+ }
+}
+
+
+static int get_cache_directory(mailsession * session,
+ char * path, char ** result)
+{
+ char * quoted_mb;
+ char dirname[PATH_MAX];
+ int res;
+ int r;
+ struct mbox_cached_session_state_data * cached_data;
+
+ cached_data = get_cached_data(session);
+
+ quoted_mb = maildriver_quote_mailbox(path);
+ if (quoted_mb == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(dirname, PATH_MAX, "%s%c%s",
+ cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR, quoted_mb);
+
+ r = generic_cache_create_dir(dirname);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ snprintf(dirname, PATH_MAX, "%s%c%s",
+ cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, quoted_mb);
+
+ r = generic_cache_create_dir(dirname);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ * result = quoted_mb;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ free(quoted_mb);
+ err:
+ return res;
+}
+
+
+
+
+#define FILENAME_MAX_UID "max-uid"
+
+/* write max uid current value */
+
+static int write_max_uid_value(mailsession * session)
+{
+ int r;
+ char filename[PATH_MAX];
+ FILE * f;
+ int res;
+
+#if 0
+ struct mbox_session_state_data * mbox_data;
+#endif
+ struct mbox_cached_session_state_data * cached_data;
+ int fd;
+
+ MMAPString * mmapstr;
+ size_t cur_token;
+ struct mailmbox_folder * folder;
+
+ /* expunge the mailbox */
+
+#if 0
+ mbox_data = get_ancestor(session)->data;
+#endif
+ folder = get_mbox_session(session);
+
+ r = mailmbox_validate_write_lock(folder);
+ if (r != MAILMBOX_NO_ERROR) {
+ res = mbox_error_to_mail_error(r);
+ goto err;
+ }
+
+ r = mailmbox_expunge_no_lock(folder);
+ if (r != MAILMBOX_NO_ERROR) {
+ res = r;
+ goto unlock;
+ }
+
+ cached_data = get_cached_data(session);
+
+ snprintf(filename, PATH_MAX, "%s%c%s%c%s",
+ cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR,
+ cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID);
+
+ fd = creat(filename, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ f = fdopen(fd, "w");
+ if (f == NULL) {
+ close(fd);
+ res = MAIL_ERROR_FILE;
+ goto unlock;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close;
+ }
+
+ r = mail_serialize_clear(mmapstr, &cur_token);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mmapstr;
+ }
+
+ r = mailimf_cache_int_write(mmapstr, &cur_token,
+ folder->mb_written_uid);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mmapstr;
+ }
+
+ fwrite(mmapstr->str, 1, mmapstr->len, f);
+
+ mmap_string_free(mmapstr);
+ fclose(f);
+ mailmbox_write_unlock(folder);
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ close:
+ fclose(f);
+ unlock:
+ mailmbox_read_unlock(folder);
+ err:
+ return res;
+}
+
+static int read_max_uid_value(mailsession * session, uint32_t * result)
+{
+ int r;
+ char filename[PATH_MAX];
+ FILE * f;
+ uint32_t written_uid;
+ int res;
+
+ struct mbox_cached_session_state_data * cached_data;
+
+ MMAPString * mmapstr;
+ size_t cur_token;
+ char buf[sizeof(uint32_t)];
+ size_t read_size;
+
+ cached_data = get_cached_data(session);
+
+ snprintf(filename, PATH_MAX, "%s%c%s%c%s",
+ cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR,
+ cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID);
+
+ f = fopen(filename, "r");
+ if (f == NULL) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ read_size = fread(buf, 1, sizeof(uint32_t), f);
+
+ mmapstr = mmap_string_new_len(buf, read_size);
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close;
+ }
+
+ cur_token = 0;
+
+ r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid);
+ if (r != MAIL_NO_ERROR) {
+ fclose(f);
+ res = r;
+ goto free_mmapstr;
+ }
+
+ mmap_string_free(mmapstr);
+ fclose(f);
+
+ * result = written_uid;
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ close:
+ fclose(f);
+ err:
+ return res;
+}
+
+static int mboxdriver_cached_connect_path(mailsession * session, char * path)
+{
+ int r;
+ int res;
+ char * quoted_mb;
+ struct mbox_cached_session_state_data * cached_data;
+ struct mbox_session_state_data * ancestor_data;
+ struct mailmbox_folder * folder;
+ uint32_t written_uid;
+
+ folder = get_mbox_session(session);
+ if (folder != NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ r = get_cache_directory(session, path, &quoted_mb);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ cached_data = get_cached_data(session);
+ free_state(cached_data);
+
+ cached_data->mbox_quoted_mb = quoted_mb;
+
+ written_uid = 0;
+ r = read_max_uid_value(session, &written_uid);
+ /* ignore errors */
+
+ ancestor_data = get_ancestor_data(session);
+
+ r = mailmbox_init(path,
+ ancestor_data->mbox_force_read_only,
+ ancestor_data->mbox_force_no_uid,
+ written_uid,
+ &folder);
+
+ if (r != MAILMBOX_NO_ERROR) {
+ cached_data->mbox_quoted_mb = NULL;
+
+ res = mboxdriver_mbox_error_to_mail_error(r);
+ goto free;
+ }
+
+ ancestor_data->mbox_folder = folder;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ free(quoted_mb);
+ err:
+ return res;
+}
+
+
+static int mboxdriver_cached_logout(mailsession * session)
+{
+ struct mbox_cached_session_state_data * cached_data;
+ int r;
+
+ r = write_max_uid_value(session);
+
+ cached_data = get_cached_data(session);
+
+ mbox_flags_store_process(cached_data->mbox_flags_directory,
+ cached_data->mbox_quoted_mb,
+ cached_data->mbox_flags_store);
+
+ r = mailsession_logout(get_ancestor(session));
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ free_state(cached_data);
+
+ return MAIL_NO_ERROR;
+}
+
+static int mboxdriver_cached_check_folder(mailsession * session)
+{
+ struct mbox_cached_session_state_data * cached_data;
+
+ cached_data = get_cached_data(session);
+
+ mbox_flags_store_process(cached_data->mbox_flags_directory,
+ cached_data->mbox_quoted_mb,
+ cached_data->mbox_flags_store);
+
+ return MAIL_NO_ERROR;
+}
+
+static int mboxdriver_cached_expunge_folder(mailsession * session)
+{
+ struct mailmbox_folder * folder;
+ int res;
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ struct mbox_cached_session_state_data * data;
+ int r;
+ unsigned int i;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ data = get_cached_data(session);
+ if (data->mbox_quoted_mb == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ mbox_flags_store_process(data->mbox_flags_directory,
+ data->mbox_quoted_mb,
+ data->mbox_flags_store);
+
+ snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
+ data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb,
+ MAIL_DIR_SEPARATOR, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
+ struct mailmbox_msg_info * msg_info;
+ struct mail_flags * flags;
+
+ msg_info = carray_get(folder->mb_tab, i);
+ if (msg_info == NULL)
+ continue;
+
+ if (msg_info->msg_deleted)
+ continue;
+
+ r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
+ session, msg_info->msg_uid, &flags);
+ if (r != MAIL_NO_ERROR)
+ continue;
+
+ if (flags->fl_flags & MAIL_FLAG_DELETED) {
+ r = mailmbox_delete_msg(folder, msg_info->msg_uid);
+ }
+
+ mail_flags_free(flags);
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ r = mailmbox_expunge(folder);
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static int mboxdriver_cached_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ struct mailmbox_folder * folder;
+ int res;
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ struct mbox_cached_session_state_data * data;
+ int r;
+ unsigned int i;
+ uint32_t recent;
+ uint32_t unseen;
+ uint32_t num;
+
+ num = 0;
+ recent = 0;
+ unseen = 0;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ data = get_cached_data(session);
+ if (data->mbox_quoted_mb == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ r = mailmbox_validate_read_lock(folder);
+ if (r != MAIL_NO_ERROR) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ mailmbox_read_unlock(folder);
+
+ mbox_flags_store_process(data->mbox_flags_directory, data->mbox_quoted_mb,
+ data->mbox_flags_store);
+
+ snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
+ data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb,
+ MAIL_DIR_SEPARATOR, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
+ struct mailmbox_msg_info * msg_info;
+ struct mail_flags * flags;
+
+ msg_info = carray_get(folder->mb_tab, i);
+ if (msg_info == NULL)
+ continue;
+
+ if (msg_info->msg_deleted)
+ continue;
+
+ r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
+ session, msg_info->msg_uid, &flags);
+ if (r != MAIL_NO_ERROR) {
+ recent ++;
+ unseen ++;
+ num ++;
+ continue;
+ }
+
+ if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
+ recent ++;
+ }
+ if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
+ unseen ++;
+ }
+
+ num ++;
+
+ mail_flags_free(flags);
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ * result_messages = num;
+ * result_recent = recent;
+ * result_unseen = unseen;
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static int mboxdriver_cached_messages_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ return mailsession_messages_number(get_ancestor(session), mb, result);
+}
+
+
+static int mboxdriver_cached_recent_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = mboxdriver_cached_status_folder(session, mb, &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = recent;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mboxdriver_cached_unseen_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = mboxdriver_cached_status_folder(session, mb,
+ &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = unseen;
+
+ return MAIL_NO_ERROR;
+}
+
+/* messages operations */
+
+static int mboxdriver_cached_append_message(mailsession * session,
+ char * message, size_t size)
+{
+ return mboxdriver_cached_append_message_flags(session,
+ message, size, NULL);
+}
+
+static int mboxdriver_cached_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ int r;
+ struct mailmbox_folder * folder;
+ struct mbox_cached_session_state_data * data;
+ unsigned int uid;
+ struct mailmbox_msg_info * msg_info;
+ chashdatum key;
+ chashdatum value;
+ struct mail_cache_db * cache_db_flags;
+ char filename_flags[PATH_MAX];
+ MMAPString * mmapstr;
+ char keyname[PATH_MAX];
+
+ folder = get_mbox_session(session);
+ if (folder == NULL)
+ return MAIL_ERROR_APPEND;
+
+ r = mailmbox_append_message_uid(folder, message, size, &uid);
+
+ switch (r) {
+ case MAILMBOX_ERROR_FILE:
+ return MAIL_ERROR_DISKSPACE;
+ case MAILMBOX_NO_ERROR:
+ break;
+ default:
+ return mboxdriver_mbox_error_to_mail_error(r);
+ }
+
+ /* could store in flags store instead */
+
+ if (flags == NULL)
+ goto exit;
+
+ key.data = &uid;
+ key.len = sizeof(uid);
+ r = chash_get(folder->mb_hash, &key, &value);
+ if (r < 0)
+ goto exit;
+
+ msg_info = value.data;
+
+ data = get_cached_data(session);
+
+ snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
+ data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb,
+ MAIL_DIR_SEPARATOR, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0)
+ goto exit;
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL)
+ goto close_db_flags;
+
+ snprintf(keyname, PATH_MAX, "%u-%lu", uid,
+ (unsigned long) msg_info->msg_body_len);
+
+ r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags);
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ if (r != MAIL_NO_ERROR)
+ goto exit;
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ exit:
+ return MAIL_NO_ERROR;
+}
+
+static int
+mboxdriver_cached_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ struct mailmbox_folder * folder;
+ int res;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ return mbox_get_uid_messages_list(folder,
+ session, mbox_cached_message_driver, result);
+
+ err:
+ return res;
+}
+
+static int
+get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
+ mailsession * session, uint32_t num,
+ struct mailimf_fields ** result)
+{
+ int r;
+ char keyname[PATH_MAX];
+ struct mailimf_fields * fields;
+ int res;
+ struct mailmbox_msg_info * info;
+ struct mailmbox_folder * folder;
+ chashdatum key;
+ chashdatum data;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ key.data = &num;
+ key.len = sizeof(num);
+
+ r = chash_get(folder->mb_hash, &key, &data);
+ if (r < 0) {
+ res = MAIL_ERROR_MSG_NOT_FOUND;
+ goto err;
+ }
+
+ info = data.data;
+
+ snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num,
+ (unsigned long) info->msg_body_len);
+
+ r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = fields;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
+ mailsession * session, uint32_t num,
+ struct mailimf_fields * fields)
+{
+ int r;
+ char keyname[PATH_MAX];
+ int res;
+ struct mailmbox_msg_info * info;
+ struct mailmbox_folder * folder;
+ chashdatum key;
+ chashdatum data;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ key.data = &num;
+ key.len = sizeof(num);
+
+ r = chash_get(folder->mb_hash, &key, &data);
+ if (r < 0) {
+ res = MAIL_ERROR_MSG_NOT_FOUND;
+ goto err;
+ }
+
+ info = data.data;
+
+ snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num,
+ (unsigned long) info->msg_body_len);
+
+ r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+mboxdriver_cached_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list)
+{
+ int r;
+ unsigned int i;
+ struct mbox_cached_session_state_data * cached_data;
+ char filename_env[PATH_MAX];
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_env;
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ int res;
+ struct mailmbox_folder * folder;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ cached_data = get_cached_data(session);
+ if (cached_data->mbox_quoted_mb == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ mbox_flags_store_process(cached_data->mbox_flags_directory,
+ cached_data->mbox_quoted_mb,
+ cached_data->mbox_flags_store);
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(filename_env, PATH_MAX, "%s%c%s%c%s",
+ cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR,
+ cached_data->mbox_quoted_mb,
+ MAIL_DIR_SEPARATOR, ENV_NAME);
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
+ cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR,
+ cached_data->mbox_quoted_mb,
+ MAIL_DIR_SEPARATOR, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto close_db_env;
+ }
+
+ /* fill with cached */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+ struct mailimf_fields * fields;
+ struct mail_flags * flags;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields == NULL) {
+ r = get_cached_envelope(cache_db_env, mmapstr, session,
+ msg->msg_index, &fields);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_cached = TRUE;
+ msg->msg_fields = fields;
+ }
+ }
+
+ if (msg->msg_flags == NULL) {
+ r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
+ session, msg->msg_index,
+ &flags);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_flags = flags;
+ }
+ }
+ }
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+
+ r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mmapstr;
+ }
+
+ /* add flags */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_flags == NULL)
+ msg->msg_flags = mail_flags_new_empty();
+ }
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto close_db_env;
+ }
+
+ /* must write cache */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields != NULL) {
+ if (!msg->msg_cached) {
+ /* msg->msg_index is the numerical UID of the message */
+ r = write_cached_envelope(cache_db_env, mmapstr,
+ session, msg->msg_index, msg->msg_fields);
+ }
+ }
+
+ if (msg->msg_flags != NULL) {
+ r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_uid, msg->msg_flags);
+ }
+ }
+
+ /* flush cache */
+
+ maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+
+ mmap_string_free(mmapstr);
+
+ return MAIL_NO_ERROR;
+
+ close_db_env:
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ err:
+ return res;
+}
+
+
+static int
+mboxdriver_cached_remove_message(mailsession * session, uint32_t num)
+{
+ return mailsession_remove_message(get_ancestor(session), num);
+}
+
+static int mboxdriver_cached_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result)
+{
+ mailmessage * msg_info;
+ int r;
+
+ msg_info = mailmessage_new();
+ if (msg_info == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_init(msg_info, session, mbox_cached_message_driver, num, 0);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg_info);
+ return r;
+ }
+
+ * result = msg_info;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mboxdriver_cached_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result)
+{
+ uint32_t num;
+ char * p;
+ chashdatum key;
+ chashdatum data;
+ struct mailmbox_msg_info * info;
+ struct mailmbox_folder * folder;
+ int r;
+
+ if (uid == NULL)
+ return MAIL_ERROR_INVAL;
+
+ num = strtoul(uid, &p, 10);
+ if (p == uid || * p != '-')
+ return MAIL_ERROR_INVAL;
+
+ folder = get_mbox_session(session);
+ if (folder == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ key.data = &num;
+ key.len = sizeof(num);
+
+ r = chash_get(folder->mb_hash, &key, &data);
+ if (r == 0) {
+ char * body_len_p = p + 1;
+ size_t body_len;
+
+ info = data.data;
+ /* Check if the cached message has the same UID */
+ body_len = strtoul(body_len_p, &p, 10);
+ if (p == body_len_p || * p != '\0')
+ return MAIL_ERROR_INVAL;
+
+ if (body_len == info->msg_body_len)
+ return mboxdriver_cached_get_message(session, num, result);
+ }
+
+ return MAIL_ERROR_MSG_NOT_FOUND;
+}
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h
new file mode 100644
index 0000000..25c4027
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h
@@ -0,0 +1,54 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef MBOXDRIVER_CACHED_H
+
+#define MBOXDRIVER_CACHED_H
+
+#include <libetpan/libetpan-config.h>
+
+#include <libetpan/mboxdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * mbox_cached_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c
new file mode 100644
index 0000000..9f77d32
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c
@@ -0,0 +1,361 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "mboxdriver_cached_message.h"
+
+#include "mailmessage_tools.h"
+#include "mboxdriver_tools.h"
+#include "mboxdriver_cached.h"
+#include "mboxdriver.h"
+#include "mailmbox.h"
+#include "mail_cache_db.h"
+#include "generic_cache.h"
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+static int mbox_prefetch(mailmessage * msg_info);
+
+static void mbox_prefetch_free(struct generic_message_t * msg);
+
+static int mbox_initialize(mailmessage * msg_info);
+
+static void mbox_uninitialize(mailmessage * msg_info);
+
+static void mbox_flush(mailmessage * msg_info);
+
+static void mbox_check(mailmessage * msg_info);
+
+static int mbox_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static int mbox_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result);
+
+static int mbox_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static mailmessage_driver local_mbox_cached_message_driver = {
+ .msg_name = "mbox-cached",
+
+ .msg_initialize = mbox_initialize,
+ .msg_uninitialize = mbox_uninitialize,
+
+ .msg_flush = mbox_flush,
+ .msg_check = mbox_check,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = mbox_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_body,
+ .msg_fetch_size = mbox_fetch_size,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = mbox_get_flags,
+};
+
+mailmessage_driver * mbox_cached_message_driver =
+&local_mbox_cached_message_driver;
+
+static inline struct mbox_cached_session_state_data *
+get_cached_session_data(mailmessage * msg)
+{
+ return msg->msg_session->sess_data;
+}
+
+static inline mailsession * get_ancestor_session(mailmessage * msg)
+{
+ return get_cached_session_data(msg)->mbox_ancestor;
+}
+
+static inline struct mbox_session_state_data *
+get_ancestor_session_data(mailmessage * msg)
+{
+ return get_ancestor_session(msg)->sess_data;
+}
+
+static inline struct mailmbox_folder *
+get_mbox_session(mailmessage * msg)
+{
+ return get_ancestor_session_data(msg)->mbox_folder;
+}
+
+static int mbox_prefetch(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * msg_content;
+ size_t msg_length;
+
+ r = mboxdriver_fetch_msg(get_ancestor_session(msg_info),
+ msg_info->msg_index,
+ &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static void mbox_prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ mmap_string_unref(msg->msg_message);
+ msg->msg_message = NULL;
+ }
+}
+
+static int mbox_initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * uid;
+ char static_uid[PATH_MAX];
+ struct mailmbox_msg_info * info;
+ struct mailmbox_folder * folder;
+ int res;
+ chashdatum key;
+ chashdatum data;
+
+ folder = get_mbox_session(msg_info);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ key.data = (char *) &msg_info->msg_index;
+ key.len = sizeof(msg_info->msg_index);
+
+ r = chash_get(folder->mb_hash, &key, &data);
+ if (r < 0) {
+ res = MAIL_ERROR_MSG_NOT_FOUND;
+ goto err;
+ }
+
+ info = (struct mailmbox_msg_info *) data.data;
+
+ snprintf(static_uid, PATH_MAX, "%u-%lu",
+ msg_info->msg_index, (unsigned long) info->msg_body_len);
+ uid = strdup(static_uid);
+ if (uid == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR) {
+ free(uid);
+ res = r;
+ goto err;
+ }
+
+ msg = msg_info->msg_data;
+
+ msg->msg_prefetch = mbox_prefetch;
+ msg->msg_prefetch_free = mbox_prefetch_free;
+ msg_info->msg_uid = uid;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static void mbox_uninitialize(mailmessage * msg_info)
+{
+ mailmessage_generic_uninitialize(msg_info);
+}
+
+#define FLAGS_NAME "flags.db"
+
+static void mbox_flush(mailmessage * msg_info)
+{
+ mailmessage_generic_flush(msg_info);
+}
+
+static void mbox_check(mailmessage * msg_info)
+{
+ int r;
+
+ if (msg_info->msg_flags != NULL) {
+ r = mail_flags_store_set(get_cached_session_data(msg_info)->mbox_flags_store,
+ msg_info);
+ /* ignore errors */
+ }
+}
+
+
+static int mbox_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ int r;
+ size_t size;
+
+ r = mboxdriver_fetch_size(get_ancestor_session(msg_info),
+ msg_info->msg_index, &size);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = size;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mbox_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result)
+{
+ int r;
+ struct mail_flags * flags;
+ struct mail_cache_db * cache_db_flags;
+ char filename_flags[PATH_MAX];
+ int res;
+ struct mbox_cached_session_state_data * cached_data;
+ MMAPString * mmapstr;
+ struct mailmbox_folder * folder;
+
+ if (msg_info->msg_flags != NULL) {
+ * result = msg_info->msg_flags;
+
+ return MAIL_NO_ERROR;
+ }
+
+ flags = mail_flags_store_get(get_cached_session_data(msg_info)->mbox_flags_store,
+ msg_info->msg_index);
+
+ if (flags == NULL) {
+ folder = get_mbox_session(msg_info);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ cached_data = get_cached_session_data(msg_info);
+ if (cached_data->mbox_quoted_mb == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ cached_data->mbox_flags_directory,
+ cached_data->mbox_quoted_mb, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ if (msg_info->msg_index > folder->mb_written_uid) {
+ flags = mail_flags_new_empty();
+ }
+ else {
+ r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
+ msg_info->msg_session,
+ msg_info->msg_index, &flags);
+ if (r != MAIL_NO_ERROR) {
+ flags = mail_flags_new_empty();
+ if (flags == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+ }
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ }
+
+ msg_info->msg_flags = flags;
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static int mbox_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * msg_content;
+ size_t msg_length;
+
+ msg = msg_info->msg_data;
+ if (msg->msg_message != NULL) {
+ return mailmessage_generic_fetch_header(msg_info, result, result_len);
+ }
+ else {
+ r = mboxdriver_fetch_header(get_ancestor_session(msg_info),
+ msg_info->msg_index,
+ &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = msg_content;
+ * result_len = msg_length;
+
+ return MAIL_NO_ERROR;
+ }
+}
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h
new file mode 100644
index 0000000..144e2da
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h
@@ -0,0 +1,52 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef MBOXDRIVER_CACHED_MESSAGE_H
+
+#define MBOXDRIVER_CACHED_MESSAGE_H
+
+#include <libetpan/mailmessage.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * mbox_cached_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_message.c b/libetpan/src/driver/implementation/mbox/mboxdriver_message.c
new file mode 100644
index 0000000..9bb5a18
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_message.c
@@ -0,0 +1,225 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "mboxdriver_message.h"
+
+#include "mailmessage_tools.h"
+#include "mboxdriver_tools.h"
+#include "mboxdriver.h"
+#include "mailmbox.h"
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+static int mbox_prefetch(mailmessage * msg_info);
+
+static void mbox_prefetch_free(struct generic_message_t * msg);
+
+static int mbox_initialize(mailmessage * msg_info);
+
+static int mbox_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static int mbox_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static mailmessage_driver local_mbox_message_driver = {
+ .msg_name = "mbox",
+
+ .msg_initialize = mbox_initialize,
+ .msg_uninitialize = mailmessage_generic_uninitialize,
+
+ .msg_flush = mailmessage_generic_flush,
+ .msg_check = NULL,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = mbox_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_body,
+ .msg_fetch_size = mbox_fetch_size,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = NULL,
+};
+
+mailmessage_driver * mbox_message_driver = &local_mbox_message_driver;
+
+static inline struct mbox_session_state_data * get_data(mailmessage * msg)
+{
+ return msg->msg_session->sess_data;
+}
+
+static inline struct mailmbox_folder * get_mbox_session(mailmessage * msg)
+{
+ return get_data(msg)->mbox_folder;
+}
+
+
+static int mbox_prefetch(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * msg_content;
+ size_t msg_length;
+
+ r = mboxdriver_fetch_msg(msg_info->msg_session, msg_info->msg_index,
+ &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static void mbox_prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ mmap_string_unref(msg->msg_message);
+ msg->msg_message = NULL;
+ }
+}
+
+static int mbox_initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * uid;
+ char static_uid[PATH_MAX];
+ struct mailmbox_msg_info * info;
+ struct mailmbox_folder * folder;
+ int res;
+ chashdatum key;
+ chashdatum data;
+
+ folder = get_mbox_session(msg_info);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ key.data = &msg_info->msg_index;
+ key.len = sizeof(msg_info->msg_index);
+
+ r = chash_get(folder->mb_hash, &key, &data);
+ if (r < 0) {
+ res = MAIL_ERROR_MSG_NOT_FOUND;
+ goto err;
+ }
+
+ info = data.data;
+
+ snprintf(static_uid, PATH_MAX, "%u-%lu",
+ msg_info->msg_index, (unsigned long) info->msg_body_len);
+ uid = strdup(static_uid);
+ if (uid == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR) {
+ free(uid);
+ res = r;
+ goto err;
+ }
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = mbox_prefetch;
+ msg->msg_prefetch_free = mbox_prefetch_free;
+ msg_info->msg_uid = uid;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int mbox_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ int r;
+ size_t size;
+
+ r = mboxdriver_fetch_size(msg_info->msg_session,
+ msg_info->msg_index, &size);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = size;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mbox_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * msg_content;
+ size_t msg_length;
+
+ msg = msg_info->msg_data;
+ if (msg->msg_message != NULL) {
+ return mailmessage_generic_fetch_header(msg_info, result, result_len);
+ }
+ else {
+ r = mboxdriver_fetch_header(msg_info->msg_session, msg_info->msg_index,
+ &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = msg_content;
+ * result_len = msg_length;
+
+ return MAIL_NO_ERROR;
+ }
+}
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_message.h b/libetpan/src/driver/implementation/mbox/mboxdriver_message.h
new file mode 100644
index 0000000..686e46e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_message.h
@@ -0,0 +1,52 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef MBOXDRIVER_MESSAGE_H
+
+#define MBOXDRIVER_MESSAGE_H
+
+#include <libetpan/mboxdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * mbox_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c
new file mode 100644
index 0000000..dc38cbd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c
@@ -0,0 +1,435 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "mboxdriver_tools.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "maildriver_types.h"
+#include "mailmbox.h"
+#include "mboxdriver_cached.h"
+#include "mboxdriver.h"
+#include "generic_cache.h"
+#include "mailmessage.h"
+#include "imfcache.h"
+#include "mail_cache_db.h"
+
+static inline struct mbox_session_state_data *
+session_get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline struct mailmbox_folder *
+session_get_mbox_session(mailsession * session)
+{
+ return session_get_data(session)->mbox_folder;
+}
+
+static inline struct mbox_cached_session_state_data *
+cached_session_get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline mailsession *
+cached_session_get_ancestor(mailsession * session)
+{
+ return cached_session_get_data(session)->mbox_ancestor;
+}
+
+static inline struct mbox_session_state_data *
+cached_session_get_ancestor_data(mailsession * session)
+{
+ return cached_session_get_ancestor(session)->sess_data;
+}
+
+static inline struct mailmbox_folder *
+cached_session_get_mbox_session(mailsession * session)
+{
+ return session_get_mbox_session(cached_session_get_ancestor(session));
+}
+
+
+int mboxdriver_mbox_error_to_mail_error(int error)
+{
+ switch (error) {
+ case MAILMBOX_NO_ERROR:
+ return MAIL_NO_ERROR;
+
+ case MAILMBOX_ERROR_PARSE:
+ return MAIL_ERROR_PARSE;
+
+ case MAILMBOX_ERROR_INVAL:
+ return MAIL_ERROR_INVAL;
+
+ case MAILMBOX_ERROR_FILE_NOT_FOUND:
+ return MAIL_ERROR_PARSE;
+
+ case MAILMBOX_ERROR_MEMORY:
+ return MAIL_ERROR_MEMORY;
+
+ case MAILMBOX_ERROR_TEMPORARY_FILE:
+ return MAIL_ERROR_PARSE;
+
+ case MAILMBOX_ERROR_FILE:
+ return MAIL_ERROR_FILE;
+
+ case MAILMBOX_ERROR_MSG_NOT_FOUND:
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ case MAILMBOX_ERROR_READONLY:
+ return MAIL_ERROR_READONLY;
+
+ default:
+ return MAIL_ERROR_INVAL;
+ }
+}
+
+int mboxdriver_fetch_msg(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len)
+{
+ int r;
+ char * msg_content;
+ size_t msg_length;
+ struct mailmbox_folder * folder;
+
+ folder = session_get_mbox_session(session);
+ if (folder == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = mailmbox_fetch_msg(folder, index, &msg_content, &msg_length);
+ if (r != MAILMBOX_NO_ERROR)
+ return mboxdriver_mbox_error_to_mail_error(r);
+
+ * result = msg_content;
+ * result_len = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+
+int mboxdriver_fetch_size(mailsession * session, uint32_t index,
+ size_t * result)
+{
+ struct mailmbox_folder * folder;
+ int r;
+ char * data;
+ size_t len;
+ int res;
+
+ folder = session_get_mbox_session(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_FETCH;
+ goto err;
+ }
+
+ r = mailmbox_validate_read_lock(folder);
+ if (r != MAILMBOX_NO_ERROR) {
+ res = mboxdriver_mbox_error_to_mail_error(r);
+ goto err;
+ }
+
+ r = mailmbox_fetch_msg_no_lock(folder, index, &data, &len);
+ if (r != MAILMBOX_NO_ERROR) {
+ res = mboxdriver_mbox_error_to_mail_error(r);
+ goto unlock;
+ }
+
+ mailmbox_read_unlock(folder);
+
+ * result = len;
+
+ return MAIL_NO_ERROR;
+
+ unlock:
+ mailmbox_read_unlock(folder);
+ err:
+ return res;
+}
+
+
+int
+mboxdriver_get_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ mailsession * session,
+ uint32_t num,
+ struct mail_flags ** result)
+{
+ int r;
+ char keyname[PATH_MAX];
+ struct mail_flags * flags;
+ int res;
+ struct mailmbox_msg_info * info;
+ struct mailmbox_folder * folder;
+ chashdatum key;
+ chashdatum data;
+
+ folder = cached_session_get_mbox_session(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ key.data = &num;
+ key.len = sizeof(num);
+
+ r = chash_get(folder->mb_hash, &key, &data);
+ if (r < 0) {
+ res = MAIL_ERROR_MSG_NOT_FOUND;
+ goto err;
+ }
+
+ info = data.data;
+
+ snprintf(keyname, PATH_MAX, "%u-%lu-flags", num,
+ (unsigned long) info->msg_body_len);
+
+ r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+int
+mboxdriver_write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ char * uid,
+ struct mail_flags * flags)
+{
+ int r;
+ char keyname[PATH_MAX];
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%s-flags", uid);
+
+ r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+
+int mboxdriver_fetch_header(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len)
+{
+ int r;
+ char * msg_content;
+ size_t msg_length;
+ struct mailmbox_folder * folder;
+
+ folder = session_get_mbox_session(session);
+ if (folder == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = mailmbox_fetch_msg_headers(folder, index, &msg_content, &msg_length);
+ if (r != MAILMBOX_NO_ERROR)
+ return mboxdriver_mbox_error_to_mail_error(r);
+
+ * result = msg_content;
+ * result_len = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+int mbox_get_locked_messages_list(struct mailmbox_folder * folder,
+ mailsession * session,
+ mailmessage_driver * driver,
+ int (* lock)(struct mailmbox_folder *),
+ int (* unlock)(struct mailmbox_folder *),
+ struct mailmessage_list ** result)
+{
+ struct mailmessage_list * env_list;
+ unsigned int i;
+ int r;
+ int res;
+ carray * tab;
+
+ tab = carray_new(128);
+ if (tab == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = lock(folder);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
+ struct mailmbox_msg_info * msg_info;
+ mailmessage * msg;
+
+ msg_info = carray_get(folder->mb_tab, i);
+ if (msg_info == NULL)
+ continue;
+
+ if (msg_info->msg_deleted)
+ continue;
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto unlock;
+ }
+
+ r = mailmessage_init(msg, session, driver, msg_info->msg_uid,
+ msg_info->msg_size - msg_info->msg_start_len);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto unlock;
+ }
+
+ r = carray_add(tab, msg, NULL);
+ if (r < 0) {
+ mailmessage_free(msg);
+ res = MAIL_ERROR_MEMORY;
+ goto unlock;
+ }
+ }
+
+ env_list = mailmessage_list_new(tab);
+ if (env_list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto unlock;
+ }
+
+ unlock(folder);
+
+ * result = env_list;
+
+ return MAIL_NO_ERROR;
+
+ unlock:
+ unlock(folder);
+ free:
+ for(i = 0 ; i < carray_count(tab) ; i ++)
+ mailmessage_free(carray_get(tab, i));
+ carray_free(tab);
+ err:
+ return res;
+}
+
+static int release_read_mbox(struct mailmbox_folder * folder)
+{
+ int r;
+
+ r = mailmbox_read_unlock(folder);
+ return mboxdriver_mbox_error_to_mail_error(r);
+}
+
+static int acquire_read_mbox(struct mailmbox_folder * folder)
+{
+ int r;
+
+ r = mailmbox_validate_read_lock(folder);
+ return mboxdriver_mbox_error_to_mail_error(r);
+}
+
+static int release_write_mbox(struct mailmbox_folder * folder)
+{
+ int r;
+
+ r = mailmbox_write_unlock(folder);
+ return mboxdriver_mbox_error_to_mail_error(r);
+}
+
+static int acquire_write_mbox(struct mailmbox_folder * folder)
+{
+ int r;
+ int res;
+
+ r = mailmbox_validate_write_lock(folder);
+ if (r != MAILMBOX_NO_ERROR) {
+ res = mboxdriver_mbox_error_to_mail_error(r);
+ goto err;
+ }
+
+ if (folder->mb_written_uid < folder->mb_max_uid) {
+ r = mailmbox_expunge_no_lock(folder);
+ if (r != MAILMBOX_NO_ERROR) {
+ res = mboxdriver_mbox_error_to_mail_error(r);
+ goto unlock;
+ }
+ }
+
+ return MAIL_NO_ERROR;
+
+ unlock:
+ mailmbox_write_unlock(folder);
+ err:
+ return res;
+}
+
+/* get message list with all valid written UID */
+
+int mbox_get_uid_messages_list(struct mailmbox_folder * folder,
+ mailsession * session,
+ mailmessage_driver * driver,
+ struct mailmessage_list ** result)
+{
+ return mbox_get_locked_messages_list(folder, session, driver,
+ acquire_write_mbox, release_write_mbox, result);
+}
+
+
+/* get message list */
+
+int mbox_get_messages_list(struct mailmbox_folder * folder,
+ mailsession * session,
+ mailmessage_driver * driver,
+ struct mailmessage_list ** result)
+{
+ return mbox_get_locked_messages_list(folder, session, driver,
+ acquire_read_mbox, release_read_mbox, result);
+}
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h
new file mode 100644
index 0000000..eebf98c
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h
@@ -0,0 +1,85 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef MBOXDRIVER_TOOLS_H
+
+#define MBOXDRIVER_TOOLS_H
+
+#include "mail_cache_db_types.h"
+#include "mboxdriver_types.h"
+#include "mailmbox.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int mboxdriver_mbox_error_to_mail_error(int error);
+
+int mboxdriver_fetch_msg(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len);
+
+int mboxdriver_fetch_size(mailsession * session, uint32_t index,
+ size_t * result);
+
+int
+mboxdriver_get_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ mailsession * session,
+ uint32_t num,
+ struct mail_flags ** result);
+
+int
+mboxdriver_write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ char * uid, struct mail_flags * flags);
+
+int mbox_get_uid_messages_list(struct mailmbox_folder * folder,
+ mailsession * session,
+ mailmessage_driver * driver,
+ struct mailmessage_list ** result);
+
+int mbox_get_messages_list(struct mailmbox_folder * folder,
+ mailsession * session,
+ mailmessage_driver * driver,
+ struct mailmessage_list ** result);
+
+int mboxdriver_fetch_header(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_types.h b/libetpan/src/driver/implementation/mbox/mboxdriver_types.h
new file mode 100644
index 0000000..23b9acf
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_types.h
@@ -0,0 +1,107 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef MBOXDRIVER_TYPES_H
+
+#define MBOXDRIVER_TYPES_H
+
+#include <libetpan/maildriver_types.h>
+#include <libetpan/mailmbox.h>
+#include <libetpan/mailstorage_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* mbox driver */
+
+enum {
+ MBOXDRIVER_SET_READ_ONLY = 1,
+ MBOXDRIVER_SET_NO_UID,
+};
+
+struct mbox_session_state_data {
+ struct mailmbox_folder * mbox_folder;
+ int mbox_force_read_only;
+ int mbox_force_no_uid;
+};
+
+/* cached version */
+
+enum {
+ /* the mapping of the parameters should be the same as for mbox */
+ MBOXDRIVER_CACHED_SET_READ_ONLY = 1,
+ MBOXDRIVER_CACHED_SET_NO_UID,
+ /* cache specific */
+ MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY,
+ MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY,
+};
+
+struct mbox_cached_session_state_data {
+ mailsession * mbox_ancestor;
+ char * mbox_quoted_mb;
+ char mbox_cache_directory[PATH_MAX];
+ char mbox_flags_directory[PATH_MAX];
+ struct mail_flags_store * mbox_flags_store;
+};
+
+/* mbox storage */
+
+/*
+ mbox_mailstorage is the state data specific to the mbox storage.
+
+ - pathname is the filename that contains the mailbox.
+
+ - cached if this value is != 0, a persistant cache will be
+ stored on local system.
+
+ - cache_directory is the location of the cache.
+
+ - flags_directory is the location of the flags.
+*/
+
+struct mbox_mailstorage {
+ char * mbox_pathname;
+
+ int mbox_cached;
+ char * mbox_cache_directory;
+ char * mbox_flags_directory;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxstorage.c b/libetpan/src/driver/implementation/mbox/mboxstorage.c
new file mode 100644
index 0000000..3944c3b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxstorage.c
@@ -0,0 +1,192 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "mboxstorage.h"
+
+#include "mail.h"
+#include "mailmessage.h"
+#include "mboxdriver.h"
+#include "mboxdriver_cached.h"
+#include "maildriver.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* mbox storage */
+
+static int mbox_mailstorage_connect(struct mailstorage * storage);
+static int
+mbox_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result);
+static void mbox_mailstorage_uninitialize(struct mailstorage * storage);
+
+static mailstorage_driver mbox_mailstorage_driver = {
+ .sto_name = "mbox",
+ .sto_connect = mbox_mailstorage_connect,
+ .sto_get_folder_session = mbox_mailstorage_get_folder_session,
+ .sto_uninitialize = mbox_mailstorage_uninitialize,
+};
+
+int mbox_mailstorage_init(struct mailstorage * storage,
+ char * mbox_pathname, int mbox_cached,
+ char * mbox_cache_directory, char * mbox_flags_directory)
+{
+ struct mbox_mailstorage * mbox_storage;
+
+ mbox_storage = malloc(sizeof(* mbox_storage));
+ if (mbox_storage == NULL)
+ goto err;
+
+ mbox_storage->mbox_pathname = strdup(mbox_pathname);
+ if (mbox_storage->mbox_pathname == NULL)
+ goto free;
+
+ mbox_storage->mbox_cached = mbox_cached;
+
+ if (mbox_cached && (mbox_cache_directory != NULL) &&
+ (mbox_flags_directory != NULL)) {
+ mbox_storage->mbox_cache_directory = strdup(mbox_cache_directory);
+ if (mbox_storage->mbox_cache_directory == NULL)
+ goto free_pathname;
+
+ mbox_storage->mbox_flags_directory = strdup(mbox_flags_directory);
+ if (mbox_storage->mbox_flags_directory == NULL)
+ goto free_cache_directory;
+ }
+ else {
+ mbox_storage->mbox_cached = FALSE;
+ mbox_storage->mbox_cache_directory = NULL;
+ mbox_storage->mbox_flags_directory = NULL;
+ }
+
+ storage->sto_data = mbox_storage;
+ storage->sto_driver = &mbox_mailstorage_driver;
+
+ return MAIL_NO_ERROR;
+
+ free_cache_directory:
+ free(mbox_storage->mbox_cache_directory);
+ free_pathname:
+ free(mbox_storage->mbox_pathname);
+ free:
+ free(mbox_storage);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void mbox_mailstorage_uninitialize(struct mailstorage * storage)
+{
+ struct mbox_mailstorage * mbox_storage;
+
+ mbox_storage = storage->sto_data;
+ if (mbox_storage->mbox_flags_directory != NULL)
+ free(mbox_storage->mbox_flags_directory);
+ if (mbox_storage->mbox_cache_directory != NULL)
+ free(mbox_storage->mbox_cache_directory);
+ free(mbox_storage->mbox_pathname);
+ free(mbox_storage);
+
+ storage->sto_data = NULL;
+}
+
+static int mbox_mailstorage_connect(struct mailstorage * storage)
+{
+ struct mbox_mailstorage * mbox_storage;
+ mailsession_driver * driver;
+ int r;
+ int res;
+ mailsession * session;
+
+ mbox_storage = storage->sto_data;
+
+ if (mbox_storage->mbox_cached)
+ driver = mbox_cached_session_driver;
+ else
+ driver = mbox_session_driver;
+
+ session = mailsession_new(driver);
+ if (session == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ if (mbox_storage->mbox_cached) {
+ r = mailsession_parameters(session,
+ MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY,
+ mbox_storage->mbox_cache_directory);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ r = mailsession_parameters(session,
+ MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY,
+ mbox_storage->mbox_flags_directory);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+ }
+
+ r = mailsession_connect_path(session, mbox_storage->mbox_pathname);
+ switch (r) {
+ case MAIL_NO_ERROR_NON_AUTHENTICATED:
+ case MAIL_NO_ERROR_AUTHENTICATED:
+ case MAIL_NO_ERROR:
+ break;
+ default:
+ res = r;
+ goto free;
+ }
+
+ storage->sto_session = session;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailsession_free(session);
+ err:
+ return res;
+}
+
+static int
+mbox_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result)
+{
+ * result = storage->sto_session;
+
+ return MAIL_NO_ERROR;
+}
+
diff --git a/libetpan/src/driver/implementation/mbox/mboxstorage.h b/libetpan/src/driver/implementation/mbox/mboxstorage.h
new file mode 100644
index 0000000..45aed7b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxstorage.h
@@ -0,0 +1,69 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef MBOXSTORAGE_H
+
+#define MBOXSTORAGE_H
+
+#include <libetpan/mboxdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ mbox_mailstorage_init is the constructor for a mbox storage.
+
+ @param storage this is the storage to initialize.
+
+ @param pathname is the filename that contains the mailbox.
+
+ @param cached if this value is != 0, a persistant cache will be
+ stored on local system.
+
+ @param cache_directory is the location of the cache
+
+ @param flags_directory is the location of the flags
+*/
+
+int mbox_mailstorage_init(struct mailstorage * storage,
+ char * mb_pathname, int mb_cached,
+ char * mb_cache_directory, char * mb_flags_directory);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver.c b/libetpan/src/driver/implementation/mh/mhdriver.c
new file mode 100644
index 0000000..c44afc9
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver.c
@@ -0,0 +1,875 @@
+/*
+ * 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 "mhdriver.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mailmh.h"
+#include "maildriver_tools.h"
+#include "mhdriver_tools.h"
+#include "mhdriver_message.h"
+#include "mailmessage.h"
+
+static int mhdriver_initialize(mailsession * session);
+
+static void mhdriver_uninitialize(mailsession * session);
+
+static int mhdriver_connect_path(mailsession * session, char * path);
+static int mhdriver_logout(mailsession * session);
+
+static int mhdriver_build_folder_name(mailsession * session, char * mb,
+ char * name, char ** result);
+static int mhdriver_create_folder(mailsession * session, char * mb);
+
+static int mhdriver_delete_folder(mailsession * session, char * mb);
+
+static int mhdriver_rename_folder(mailsession * session, char * mb,
+ char * new_name);
+
+static int mhdriver_select_folder(mailsession * session, char * mb);
+
+static int mhdriver_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int mhdriver_messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int mhdriver_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int mhdriver_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int mhdriver_subscribe_folder(mailsession * session, char * mb);
+
+static int mhdriver_unsubscribe_folder(mailsession * session, char * mb);
+
+static int mhdriver_append_message(mailsession * session,
+ char * message, size_t size);
+static int mhdriver_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
+static int mhdriver_copy_message(mailsession * session,
+ uint32_t num, char * mb);
+
+static int mhdriver_remove_message(mailsession * session, uint32_t num);
+
+static int mhdriver_move_message(mailsession * session,
+ uint32_t num, char * mb);
+
+static int mhdriver_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int mhdriver_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static int mhdriver_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result);
+
+static mailsession_driver local_mh_session_driver = {
+ .sess_name = "mh",
+
+ .sess_initialize = mhdriver_initialize,
+ .sess_uninitialize = mhdriver_uninitialize,
+
+ .sess_parameters = NULL,
+
+ .sess_connect_stream = NULL,
+ .sess_connect_path = mhdriver_connect_path,
+ .sess_starttls = NULL,
+ .sess_login = NULL,
+ .sess_logout = mhdriver_logout,
+ .sess_noop = NULL,
+
+ .sess_build_folder_name = mhdriver_build_folder_name,
+ .sess_create_folder = mhdriver_create_folder,
+ .sess_delete_folder = mhdriver_delete_folder,
+ .sess_rename_folder = mhdriver_rename_folder,
+ .sess_check_folder = NULL,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = mhdriver_select_folder,
+ .sess_expunge_folder = NULL,
+ .sess_status_folder = mhdriver_status_folder,
+ .sess_messages_number = mhdriver_messages_number,
+ .sess_recent_number = mhdriver_messages_number,
+ .sess_unseen_number = mhdriver_messages_number,
+ .sess_list_folders = mhdriver_list_folders,
+ .sess_lsub_folders = mhdriver_lsub_folders,
+ .sess_subscribe_folder = mhdriver_subscribe_folder,
+ .sess_unsubscribe_folder = mhdriver_unsubscribe_folder,
+
+ .sess_append_message = mhdriver_append_message,
+ .sess_append_message_flags = mhdriver_append_message_flags,
+ .sess_copy_message = mhdriver_copy_message,
+ .sess_move_message = mhdriver_move_message,
+
+ .sess_get_messages_list = mhdriver_get_messages_list,
+ .sess_get_envelopes_list = maildriver_generic_get_envelopes_list,
+ .sess_remove_message = mhdriver_remove_message,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = mhdriver_get_message,
+ .sess_get_message_by_uid = mhdriver_get_message_by_uid,
+};
+
+mailsession_driver * mh_session_driver = &local_mh_session_driver;
+
+static inline struct mh_session_state_data * get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline struct mailmh * get_mh_session(mailsession * session)
+{
+ return get_data(session)->mh_session;
+}
+
+static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session)
+{
+ return get_data(session)->mh_cur_folder;
+}
+
+static int add_to_list(mailsession * session, char * mb)
+{
+ char * new_mb;
+ struct mh_session_state_data * data;
+ int r;
+
+ data = get_data(session);
+
+ new_mb = strdup(mb);
+ if (new_mb == NULL)
+ return -1;
+
+ r = clist_append(data->mh_subscribed_list, new_mb);
+ if (r < 0) {
+ free(mb);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int remove_from_list(mailsession * session, char * mb)
+{
+ clistiter * cur;
+ struct mh_session_state_data * data;
+
+ data = get_data(session);
+
+ for(cur = clist_begin(data->mh_subscribed_list) ;
+ cur != NULL ; cur = clist_next(cur)) {
+ char * cur_name;
+
+ cur_name = clist_content(cur);
+ if (strcmp(cur_name, mb) == 0) {
+ clist_delete(data->mh_subscribed_list, cur);
+ free(cur_name);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int mhdriver_initialize(mailsession * session)
+{
+ struct mh_session_state_data * data;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto err;
+
+ data->mh_session = NULL;
+ data->mh_cur_folder = NULL;
+
+ data->mh_subscribed_list = clist_new();
+ if (data->mh_subscribed_list == NULL)
+ goto free;
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ free(data);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void mhdriver_uninitialize(mailsession * session)
+{
+ struct mh_session_state_data * data;
+
+ data = get_data(session);
+
+ if (data->mh_session != NULL)
+ mailmh_free(data->mh_session);
+
+ clist_foreach(data->mh_subscribed_list, (clist_func) free, NULL);
+ clist_free(data->mh_subscribed_list);
+
+ free(data);
+
+ session->sess_data = NULL;
+}
+
+
+static int mhdriver_connect_path(mailsession * session, char * path)
+{
+ struct mailmh * mh;
+
+ if (get_mh_session(session) != NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ mh = mailmh_new(path);
+ if (mh == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ get_data(session)->mh_session = mh;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mhdriver_logout(mailsession * session)
+{
+ struct mailmh * mh;
+
+ mh = get_mh_session(session);
+
+ if (mh == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ mailmh_free(mh);
+ get_data(session)->mh_session = NULL;
+
+ return MAIL_NO_ERROR;
+}
+
+/* folders operations */
+
+static int mhdriver_build_folder_name(mailsession * session, char * mb,
+ char * name, char ** result)
+{
+ char * folder_name;
+
+ folder_name = malloc(strlen(mb) + 2 + strlen(name));
+ if (folder_name == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ strcpy(folder_name, mb);
+ strcat(folder_name, "/");
+ strcat(folder_name, name);
+
+ * result = folder_name;
+
+ return MAIL_NO_ERROR;
+}
+
+static int get_parent(mailsession * session, char * mb,
+ struct mailmh_folder ** result_folder,
+ char ** result_name)
+{
+ char * name;
+ size_t length;
+ int i;
+ char * parent_name;
+ struct mailmh_folder * parent;
+ struct mailmh * mh;
+
+ mh = get_mh_session(session);
+ if (mh == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ length = strlen(mb);
+ for(i = length - 1 ; i >= 0 ; i--)
+ if (mb[i] == '/')
+ break;
+ name = mb + i + 1;
+
+ parent_name = malloc(i + 1);
+ /* strndup(mb, i) */
+ if (parent_name == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ strncpy(parent_name, mb, i);
+ parent_name[i] = '\0';
+
+ parent = mailmh_folder_find(mh->mh_main, parent_name);
+ free(parent_name);
+ if (parent == NULL)
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+
+ * result_folder = parent;
+ * result_name = name;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mhdriver_create_folder(mailsession * session, char * mb)
+{
+ int r;
+ struct mailmh_folder * parent;
+ char * name;
+
+ r = get_parent(session, mb, &parent, &name);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ r = mailmh_folder_add_subfolder(parent, name);
+
+ return mhdriver_mh_error_to_mail_error(r);
+}
+
+static int mhdriver_delete_folder(mailsession * session, char * mb)
+{
+ int r;
+ struct mailmh_folder * folder;
+ struct mailmh * mh;
+
+ mh = get_mh_session(session);
+ if (mh == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ folder = mailmh_folder_find(mh->mh_main, mb);
+ if (folder == NULL)
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+
+ if (get_mh_cur_folder(session) == folder)
+ get_data(session)->mh_cur_folder = NULL;
+
+ r = mailmh_folder_remove_subfolder(folder);
+
+ return mhdriver_mh_error_to_mail_error(r);
+}
+
+static int mhdriver_rename_folder(mailsession * session, char * mb,
+ char * new_name)
+{
+ struct mailmh_folder * src_folder;
+ struct mailmh_folder * dst_folder;
+ char * name;
+ struct mailmh * mh;
+ int r;
+
+ r = get_parent(session, new_name, &dst_folder, &name);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ mh = get_mh_session(session);
+ if (mh == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ src_folder = mailmh_folder_find(mh->mh_main, mb);
+ if (src_folder == NULL)
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+
+ if (get_mh_cur_folder(session) == src_folder)
+ get_data(session)->mh_cur_folder = NULL;
+
+ r = mailmh_folder_rename_subfolder(src_folder, dst_folder, name);
+
+ return mhdriver_mh_error_to_mail_error(r);
+}
+
+static int mhdriver_select_folder(mailsession * session, char * mb)
+{
+ struct mailmh_folder * folder;
+ struct mailmh * mh;
+ int r;
+
+ mh = get_mh_session(session);
+ if (mh == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = mailmh_folder_update(mh->mh_main);
+
+ folder = mailmh_folder_find(mh->mh_main, mb);
+ if (folder == NULL)
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+
+ get_data(session)->mh_cur_folder = folder;
+ r = mailmh_folder_update(folder);
+
+ return mhdriver_mh_error_to_mail_error(r);
+}
+
+static int mhdriver_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ uint32_t count;
+ int r;
+
+ r = mhdriver_messages_number(session, mb, &count);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result_messages = count;
+ * result_recent = count;
+ * result_unseen = count;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mhdriver_messages_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ struct mailmh_folder * folder;
+ uint32_t count;
+ struct mailmh * mh;
+ unsigned int i;
+
+ mh = get_mh_session(session);
+ if (mh == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ if (mb != NULL) {
+ folder = mailmh_folder_find(mh->mh_main, mb);
+ if (folder == NULL)
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+ }
+ else {
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL)
+ return MAIL_ERROR_BAD_STATE;
+ }
+
+ mailmh_folder_update(folder);
+ count = 0;
+ for (i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) {
+ struct mailmh_msg_info * msg_info;
+
+ msg_info = carray_get(folder->fl_msgs_tab, i);
+ if (msg_info != NULL)
+ count ++;
+ }
+
+ * result = count;
+
+ return MAIL_NO_ERROR;
+}
+
+
+static int get_list_folders(struct mailmh_folder * folder, clist ** result)
+{
+ unsigned int i;
+ clist * list;
+ char * new_filename;
+ int res;
+ int r;
+
+ list = * result;
+
+ new_filename = strdup(folder->fl_filename);
+ if (new_filename == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ r = mailmh_folder_update(folder);
+
+ switch (r) {
+ case MAILMH_NO_ERROR:
+ break;
+
+ default:
+ res = mhdriver_mh_error_to_mail_error(r);
+ goto free;
+ }
+
+ r = clist_append(list, new_filename);
+ if (r < 0) {
+ free(new_filename);
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ if (folder->fl_subfolders_tab != NULL) {
+ for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) {
+ struct mailmh_folder * subfolder;
+
+ subfolder = carray_get(folder->fl_subfolders_tab, i);
+
+ r = get_list_folders(subfolder, &list);
+ if (r != MAIL_NO_ERROR) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+ }
+ }
+
+ * result = list;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ clist_foreach(list, (clist_func) free, NULL);
+ clist_free(list);
+ return res;
+}
+
+
+static int mhdriver_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ clist * list;
+ int r;
+ struct mailmh * mh;
+ struct mail_list * ml;
+
+ mh = get_mh_session(session);
+
+ if (mh == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ list = clist_new();
+ if (list == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = get_list_folders(mh->mh_main, &list);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ ml = mail_list_new(list);
+ if (ml == NULL)
+ goto free;
+
+ * result = ml;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ clist_foreach(list, (clist_func) free, NULL);
+ clist_free(list);
+ return MAIL_ERROR_MEMORY;
+}
+
+static int mhdriver_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ clist * subscribed;
+ clist * lsub_result;
+ clistiter * cur;
+ struct mail_list * lsub;
+ size_t length;
+ int r;
+
+ length = strlen(mb);
+
+ subscribed = get_data(session)->mh_subscribed_list;
+
+ lsub_result = clist_new();
+ if (lsub_result == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ for(cur = clist_begin(subscribed) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ char * cur_mb;
+ char * new_mb;
+
+ cur_mb = clist_content(cur);
+
+ if (strncmp(mb, cur_mb, length) == 0) {
+ new_mb = strdup(cur_mb);
+ if (new_mb == NULL)
+ goto free_list;
+
+ r = clist_append(lsub_result, new_mb);
+ if (r < 0) {
+ free(new_mb);
+ goto free_list;
+ }
+ }
+ }
+
+ lsub = mail_list_new(lsub_result);
+ if (lsub == NULL)
+ goto free_list;
+
+ * result = lsub;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(lsub_result, (clist_func) free, NULL);
+ clist_free(lsub_result);
+ return MAIL_ERROR_MEMORY;
+}
+
+static int mhdriver_subscribe_folder(mailsession * session, char * mb)
+{
+ int r;
+
+ r = add_to_list(session, mb);
+ if (r < 0)
+ return MAIL_ERROR_SUBSCRIBE;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mhdriver_unsubscribe_folder(mailsession * session, char * mb)
+{
+ int r;
+
+ r = remove_from_list(session, mb);
+ if (r < 0)
+ return MAIL_ERROR_UNSUBSCRIBE;
+
+ return MAIL_NO_ERROR;
+}
+
+/* messages operations */
+
+static int mhdriver_append_message(mailsession * session,
+ char * message, size_t size)
+{
+ int r;
+ struct mailmh_folder * folder;
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = mailmh_folder_add_message(folder, message, size);
+
+ switch (r) {
+ case MAILMH_ERROR_FILE:
+ return MAIL_ERROR_DISKSPACE;
+
+ default:
+ return mhdriver_mh_error_to_mail_error(r);
+ }
+}
+
+static int mhdriver_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ return mhdriver_append_message(session, message, size);
+}
+
+static int mhdriver_copy_message(mailsession * session,
+ uint32_t num, char * mb)
+{
+ int fd;
+ int r;
+ struct mailmh_folder * folder;
+ struct mailmh * mh;
+ int res;
+
+ mh = get_mh_session(session);
+ if (mh == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ r = mailmh_folder_get_message_fd(folder, num, O_RDONLY, &fd);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ folder = mailmh_folder_find(mh->mh_main, mb);
+ if (folder == NULL) {
+ res = MAIL_ERROR_FOLDER_NOT_FOUND;
+ goto close;
+ }
+
+ r = mailmh_folder_add_message_file(folder, fd);
+ if (r != MAIL_NO_ERROR) {
+ res = MAIL_ERROR_COPY;
+ goto close;
+ }
+
+ close(fd);
+
+ return MAIL_NO_ERROR;
+
+ close:
+ close(fd);
+ err:
+ return res;
+}
+
+static int mhdriver_remove_message(mailsession * session, uint32_t num)
+{
+ int r;
+ struct mailmh_folder * folder;
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL)
+ return MAIL_ERROR_DELETE;
+
+ r = mailmh_folder_remove_message(folder, num);
+
+ return mhdriver_mh_error_to_mail_error(r);
+}
+
+static int mhdriver_move_message(mailsession * session,
+ uint32_t num, char * mb)
+{
+ int r;
+ struct mailmh_folder * src_folder;
+ struct mailmh_folder * dest_folder;
+ struct mailmh * mh;
+
+ mh = get_mh_session(session);
+ if (mh == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ src_folder = get_mh_cur_folder(session);
+ if (src_folder == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ dest_folder = mailmh_folder_find(mh->mh_main, mb);
+ if (dest_folder == NULL)
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+
+ r = mailmh_folder_move_message(dest_folder, src_folder, num);
+
+ return mhdriver_mh_error_to_mail_error(r);
+}
+
+
+static int mhdriver_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ struct mailmh_folder * folder;
+ int res;
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ mailmh_folder_update(folder);
+ return mh_get_messages_list(folder, session, mh_message_driver, result);
+
+ err:
+ return res;
+}
+
+static int mhdriver_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result)
+{
+ mailmessage * msg_info;
+ int r;
+
+ msg_info = mailmessage_new();
+ if (msg_info == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_init(msg_info, session, mh_message_driver, num, 0);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg_info);
+ return r;
+ }
+
+ * result = msg_info;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mhdriver_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result)
+{
+ uint32_t index;
+ char *p;
+ struct mailmh_msg_info * mh_msg_info;
+ struct mh_session_state_data * mh_data;
+ chashdatum key;
+ chashdatum data;
+ int r;
+ time_t mtime;
+ char * mtime_p;
+
+ if (uid == NULL)
+ return MAIL_ERROR_INVAL;
+
+ index = strtoul(uid, &p, 10);
+ if (p == uid || * p != '-')
+ return MAIL_ERROR_INVAL;
+
+ mh_data = session->sess_data;
+#if 0
+ mh_msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, index);
+#endif
+ key.data = &index;
+ key.len = sizeof(index);
+ r = chash_get(mh_data->mh_cur_folder->fl_msgs_hash, &key, &data);
+ if (r < 0)
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ mh_msg_info = data.data;
+
+ mtime_p = p + 1;
+
+ mtime = strtoul(mtime_p, &p, 10);
+ if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) {
+ size_t size;
+ char *size_p;
+
+ size_p = p + 1;
+ size = strtoul(size_p, &p, 10);
+ if ((* p == '\0') && (size == mh_msg_info->msg_size))
+ return mhdriver_get_message(session, index, result);
+ }
+ else if (* p != '-') {
+ return MAIL_ERROR_INVAL;
+ }
+
+ return MAIL_ERROR_MSG_NOT_FOUND;
+}
diff --git a/libetpan/src/driver/implementation/mh/mhdriver.h b/libetpan/src/driver/implementation/mh/mhdriver.h
new file mode 100644
index 0000000..a3f45f5
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver.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 MHDRIVER_H
+
+#define MHDRIVER_H
+
+#include <libetpan/maildriver.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * mh_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_cached.c b/libetpan/src/driver/implementation/mh/mhdriver_cached.c
new file mode 100644
index 0000000..1e5c28b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_cached.c
@@ -0,0 +1,1315 @@
+/*
+ * 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 "mhdriver_cached.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mail.h"
+#include "mail_cache_db.h"
+
+#include "generic_cache.h"
+#include "imfcache.h"
+#include "mhdriver.h"
+
+#include "mhdriver_cached_message.h"
+#include "mailmh.h"
+#include "maildriver_tools.h"
+#include "mhdriver_tools.h"
+#include "mailmessage.h"
+
+static int mhdriver_cached_initialize(mailsession * session);
+
+static void mhdriver_cached_uninitialize(mailsession * session);
+
+static int mhdriver_cached_parameters(mailsession * session,
+ int id, void * value);
+
+static int mhdriver_cached_connect_path(mailsession * session, char * path);
+static int mhdriver_cached_logout(mailsession * session);
+
+static int mhdriver_cached_build_folder_name(mailsession * session, char * mb,
+ char * name, char ** result);
+static int mhdriver_cached_create_folder(mailsession * session, char * mb);
+
+static int mhdriver_cached_delete_folder(mailsession * session, char * mb);
+
+static int mhdriver_cached_rename_folder(mailsession * session, char * mb,
+ char * new_name);
+
+static int mhdriver_cached_check_folder(mailsession * session);
+
+static int mhdriver_cached_select_folder(mailsession * session, char * mb);
+
+static int mhdriver_cached_expunge_folder(mailsession * session);
+
+static int mhdriver_cached_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int mhdriver_cached_messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+static int mhdriver_cached_recent_number(mailsession * session, char * mb,
+ uint32_t * result);
+static int mhdriver_cached_unseen_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int mhdriver_cached_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int mhdriver_cached_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb);
+
+static int mhdriver_cached_unsubscribe_folder(mailsession * session,
+ char * mb);
+
+static int mhdriver_cached_append_message(mailsession * session,
+ char * message, size_t size);
+static int mhdriver_cached_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
+static int mhdriver_cached_copy_message(mailsession * session,
+ uint32_t num, char * mb);
+
+static int mhdriver_cached_remove_message(mailsession * session,
+ uint32_t num);
+
+static int mhdriver_cached_move_message(mailsession * session,
+ uint32_t num, char * mb);
+
+static int
+mhdriver_cached_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int
+mhdriver_cached_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list);
+
+static int mhdriver_cached_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static int mhdriver_cached_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result);
+
+static mailsession_driver local_mh_cached_session_driver = {
+ .sess_name = "mh-cached",
+
+ .sess_initialize = mhdriver_cached_initialize,
+ .sess_uninitialize = mhdriver_cached_uninitialize,
+
+ .sess_parameters = mhdriver_cached_parameters,
+
+ .sess_connect_stream = NULL,
+ .sess_connect_path = mhdriver_cached_connect_path,
+ .sess_starttls = NULL,
+ .sess_login = NULL,
+ .sess_logout = mhdriver_cached_logout,
+ .sess_noop = NULL,
+
+ .sess_build_folder_name = mhdriver_cached_build_folder_name,
+ .sess_create_folder = mhdriver_cached_create_folder,
+ .sess_delete_folder = mhdriver_cached_delete_folder,
+ .sess_rename_folder = mhdriver_cached_rename_folder,
+ .sess_check_folder = mhdriver_cached_check_folder,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = mhdriver_cached_select_folder,
+ .sess_expunge_folder = mhdriver_cached_expunge_folder,
+ .sess_status_folder = mhdriver_cached_status_folder,
+ .sess_messages_number = mhdriver_cached_messages_number,
+ .sess_recent_number = mhdriver_cached_recent_number,
+ .sess_unseen_number = mhdriver_cached_unseen_number,
+ .sess_list_folders = mhdriver_cached_list_folders,
+ .sess_lsub_folders = mhdriver_cached_lsub_folders,
+ .sess_subscribe_folder = mhdriver_cached_subscribe_folder,
+ .sess_unsubscribe_folder = mhdriver_cached_unsubscribe_folder,
+
+ .sess_append_message = mhdriver_cached_append_message,
+ .sess_append_message_flags = mhdriver_cached_append_message_flags,
+ .sess_copy_message = mhdriver_cached_copy_message,
+ .sess_move_message = mhdriver_cached_move_message,
+
+ .sess_get_messages_list = mhdriver_cached_get_messages_list,
+ .sess_get_envelopes_list = mhdriver_cached_get_envelopes_list,
+ .sess_remove_message = mhdriver_cached_remove_message,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = mhdriver_cached_get_message,
+ .sess_get_message_by_uid = mhdriver_cached_get_message_by_uid,
+};
+
+mailsession_driver * mh_cached_session_driver =
+&local_mh_cached_session_driver;
+
+#define ENV_NAME "env.db"
+#define FLAGS_NAME "flags.db"
+
+
+static inline struct mh_cached_session_state_data *
+get_cached_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline mailsession * get_ancestor(mailsession * session)
+{
+ return get_cached_data(session)->mh_ancestor;
+}
+
+static inline struct mh_session_state_data *
+get_ancestor_data(mailsession * session)
+{
+ return get_ancestor(session)->sess_data;
+}
+
+static inline struct mailmh *
+get_mh_session(mailsession * session)
+{
+ return get_ancestor_data(session)->mh_session;
+}
+
+static inline struct mailmh_folder *
+get_mh_cur_folder(mailsession * session)
+{
+ return get_ancestor_data(session)->mh_cur_folder;
+}
+
+
+#define FILENAME_MAX_UID "max-uid"
+
+/* write max uid current value */
+
+static int write_max_uid_value(mailsession * session)
+{
+ int r;
+ char filename[PATH_MAX];
+ FILE * f;
+ int res;
+ struct mh_cached_session_state_data * cached_data;
+ struct mh_session_state_data * ancestor_data;
+ int fd;
+
+ MMAPString * mmapstr;
+ size_t cur_token;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ if (cached_data->mh_quoted_mb == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ snprintf(filename, PATH_MAX, "%s/%s/%s",
+ cached_data->mh_cache_directory,
+ cached_data->mh_quoted_mb, FILENAME_MAX_UID);
+
+ fd = creat(filename, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ f = fdopen(fd, "w");
+ if (f == NULL) {
+ close(fd);
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close;
+ }
+
+ r = mail_serialize_clear(mmapstr, &cur_token);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mmapstr;
+ }
+
+ r = mailimf_cache_int_write(mmapstr, &cur_token,
+ ancestor_data->mh_cur_folder->fl_max_index);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mmapstr;
+ }
+
+ fwrite(mmapstr->str, 1, mmapstr->len, f);
+
+ mmap_string_free(mmapstr);
+ fclose(f);
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ close:
+ fclose(f);
+ err:
+ return res;
+}
+
+static int read_max_uid_value(mailsession * session)
+{
+ int r;
+ char filename[PATH_MAX];
+ FILE * f;
+ uint32_t written_uid;
+ int res;
+ struct mh_cached_session_state_data * cached_data;
+ struct mh_session_state_data * ancestor_data;
+
+ MMAPString * mmapstr;
+ size_t cur_token;
+ char buf[sizeof(uint32_t)];
+ size_t read_size;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ snprintf(filename, PATH_MAX, "%s/%s/%s",
+ cached_data->mh_cache_directory,
+ cached_data->mh_quoted_mb, FILENAME_MAX_UID);
+
+ f = fopen(filename, "r");
+ if (f == NULL) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ read_size = fread(buf, 1, sizeof(uint32_t), f);
+
+ mmapstr = mmap_string_new_len(buf, read_size);
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close;
+ }
+
+ cur_token = 0;
+
+ r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid);
+ if (r != MAIL_NO_ERROR) {
+ fclose(f);
+ res = r;
+ goto free_mmapstr;
+ }
+
+ mmap_string_free(mmapstr);
+ fclose(f);
+
+ if (written_uid > ancestor_data->mh_cur_folder->fl_max_index)
+ ancestor_data->mh_cur_folder->fl_max_index = written_uid;
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ close:
+ fclose(f);
+ err:
+ return res;
+}
+
+
+static int mhdriver_cached_initialize(mailsession * session)
+{
+ struct mh_cached_session_state_data * data;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto err;
+
+ data->mh_flags_store = mail_flags_store_new();
+ if (data->mh_flags_store == NULL)
+ goto free;
+
+ data->mh_ancestor = mailsession_new(mh_session_driver);
+ if (data->mh_ancestor == NULL)
+ goto free_store;
+
+ data->mh_quoted_mb = NULL;
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ free_store:
+ mail_flags_store_free(data->mh_flags_store);
+ free:
+ free(data);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void free_state(struct mh_cached_session_state_data * mh_data)
+{
+ if (mh_data->mh_quoted_mb) {
+ free(mh_data->mh_quoted_mb);
+ mh_data->mh_quoted_mb = NULL;
+ }
+}
+
+static int mh_flags_store_process(char * flags_directory, char * quoted_mb,
+ struct mail_flags_store * flags_store)
+{
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ unsigned int i;
+ int r;
+ int res;
+
+ if (carray_count(flags_store->fls_tab) == 0)
+ return MAIL_NO_ERROR;
+
+ if (quoted_mb == NULL)
+ return MAIL_NO_ERROR;
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ flags_directory, quoted_mb, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(flags_store->fls_tab, i);
+
+ r = mhdriver_write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_uid, msg->msg_flags);
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ mail_flags_store_clear(flags_store);
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static void mhdriver_cached_uninitialize(mailsession * session)
+{
+ struct mh_cached_session_state_data * data;
+
+ data = get_cached_data(session);
+
+ mh_flags_store_process(data->mh_flags_directory, data->mh_quoted_mb,
+ data->mh_flags_store);
+
+ mail_flags_store_free(data->mh_flags_store);
+
+ free_state(data);
+ mailsession_free(data->mh_ancestor);
+ free(data);
+
+ session->sess_data = NULL;
+}
+
+static int mhdriver_cached_parameters(mailsession * session,
+ int id, void * value)
+{
+ struct mh_cached_session_state_data * cached_data;
+ int r;
+
+ cached_data = get_cached_data(session);
+
+ switch (id) {
+ case MHDRIVER_CACHED_SET_CACHE_DIRECTORY:
+ strncpy(cached_data->mh_cache_directory, value, PATH_MAX);
+ cached_data->mh_cache_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(cached_data->mh_cache_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+
+ case MHDRIVER_CACHED_SET_FLAGS_DIRECTORY:
+ strncpy(cached_data->mh_flags_directory, value, PATH_MAX);
+ cached_data->mh_flags_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(cached_data->mh_flags_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+ }
+
+ return MAIL_ERROR_INVAL;
+}
+
+static int mhdriver_cached_connect_path(mailsession * session, char * path)
+{
+ return mailsession_connect_path(get_ancestor(session), path);
+}
+
+static int mhdriver_cached_logout(mailsession * session)
+{
+ int r;
+ struct mh_cached_session_state_data * cached_data;
+
+ r = write_max_uid_value(session);
+
+ cached_data = get_cached_data(session);
+
+ mh_flags_store_process(cached_data->mh_flags_directory,
+ cached_data->mh_quoted_mb,
+ cached_data->mh_flags_store);
+
+ return mailsession_logout(get_ancestor(session));
+}
+
+static int mhdriver_cached_check_folder(mailsession * session)
+{
+ struct mh_cached_session_state_data * cached_data;
+
+ cached_data = get_cached_data(session);
+
+ mh_flags_store_process(cached_data->mh_flags_directory,
+ cached_data->mh_quoted_mb,
+ cached_data->mh_flags_store);
+
+ return MAIL_NO_ERROR;
+}
+
+/* folders operations */
+
+static int mhdriver_cached_build_folder_name(mailsession * session, char * mb,
+ char * name, char ** result)
+{
+ return mailsession_build_folder_name(get_ancestor(session),
+ mb, name, result);
+}
+
+static int mhdriver_cached_create_folder(mailsession * session, char * mb)
+{
+ return mailsession_create_folder(get_ancestor(session), mb);
+}
+
+static int mhdriver_cached_delete_folder(mailsession * session, char * mb)
+{
+ return mailsession_delete_folder(get_ancestor(session), mb);
+}
+
+static int mhdriver_cached_rename_folder(mailsession * session, char * mb,
+ char * new_name)
+{
+ return mailsession_rename_folder(get_ancestor(session), mb, new_name);
+}
+
+static int get_cache_directory(mailsession * session,
+ char * path, char ** result)
+{
+ char * quoted_mb;
+ char dirname[PATH_MAX];
+ int res;
+ int r;
+ struct mh_cached_session_state_data * cached_data;
+
+ cached_data = get_cached_data(session);
+
+ quoted_mb = maildriver_quote_mailbox(path);
+ if (quoted_mb == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(dirname, PATH_MAX, "%s/%s",
+ cached_data->mh_cache_directory, quoted_mb);
+
+ r = generic_cache_create_dir(dirname);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ snprintf(dirname, PATH_MAX, "%s/%s",
+ cached_data->mh_flags_directory, quoted_mb);
+
+ r = generic_cache_create_dir(dirname);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ * result = quoted_mb;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ free(quoted_mb);
+ err:
+ return res;
+}
+
+static int mhdriver_cached_select_folder(mailsession * session, char * mb)
+{
+ int r;
+ int res;
+ char * quoted_mb;
+ struct mh_cached_session_state_data * cached_data;
+
+ cached_data = get_cached_data(session);
+
+ mh_flags_store_process(cached_data->mh_flags_directory,
+ cached_data->mh_quoted_mb,
+ cached_data->mh_flags_store);
+
+ r = get_cache_directory(session, mb, &quoted_mb);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ r = mailsession_select_folder(get_ancestor(session), mb);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ r = write_max_uid_value(session);
+
+ free_state(cached_data);
+ cached_data->mh_quoted_mb = quoted_mb;
+
+ r = read_max_uid_value(session);
+
+ return MAIL_NO_ERROR;
+
+ free:
+ free(quoted_mb);
+ err:
+ return res;
+}
+
+static int mhdriver_cached_expunge_folder(mailsession * session)
+{
+ struct mailmh_folder * folder;
+ int res;
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ struct mh_cached_session_state_data * cached_data;
+ unsigned int i;
+ int r;
+
+ cached_data = get_cached_data(session);
+ if (cached_data->mh_quoted_mb == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ mh_flags_store_process(cached_data->mh_flags_directory,
+ cached_data->mh_quoted_mb,
+ cached_data->mh_flags_store);
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
+ struct mailmh_msg_info * mh_info;
+ struct mail_flags * flags;
+
+ mh_info = carray_get(folder->fl_msgs_tab, i);
+ if (mh_info == NULL)
+ continue;
+
+ r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
+ session, mh_info->msg_index, &flags);
+ if (r != MAIL_NO_ERROR)
+ continue;
+
+ if (flags->fl_flags & MAIL_FLAG_DELETED) {
+ r = mailmh_folder_remove_message(folder, mh_info->msg_index);
+ }
+
+ mail_flags_free(flags);
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ mailmh_folder_update(folder);
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+
+static int mhdriver_cached_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages,
+ uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ struct mailmh_folder * folder;
+ int res;
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ struct mh_cached_session_state_data * cached_data;
+ unsigned int i;
+ int r;
+ uint32_t count;
+ uint32_t recent;
+ uint32_t unseen;
+
+ r = mhdriver_cached_select_folder(session, mb);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ count = 0;
+ recent = 0;
+ unseen = 0;
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ cached_data = get_cached_data(session);
+ if (cached_data->mh_quoted_mb == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ cached_data->mh_flags_directory,
+ cached_data->mh_quoted_mb, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
+ struct mailmh_msg_info * mh_info;
+ struct mail_flags * flags;
+
+ mh_info = carray_get(folder->fl_msgs_tab, i);
+ if (mh_info == NULL)
+ continue;
+
+ count ++;
+
+ r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
+ session, mh_info->msg_index,
+ &flags);
+
+ if (r != MAIL_NO_ERROR) {
+ recent ++;
+ unseen ++;
+ continue;
+ }
+
+ if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
+ recent ++;
+ }
+ if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
+ unseen ++;
+ }
+ mail_flags_free(flags);
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ * result_messages = count;
+ * result_recent = recent;
+ * result_unseen = unseen;
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static int mhdriver_cached_messages_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ return mailsession_messages_number(get_ancestor(session), mb, result);
+}
+
+static int mhdriver_cached_recent_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = recent;
+
+ return MAIL_NO_ERROR;
+}
+
+
+static int mhdriver_cached_unseen_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = recent;
+
+ return MAIL_NO_ERROR;
+}
+
+
+static int mhdriver_cached_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ return mailsession_list_folders(get_ancestor(session), mb, result);
+}
+
+static int mhdriver_cached_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ return mailsession_lsub_folders(get_ancestor(session), mb, result);
+}
+
+static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb)
+{
+ return mailsession_subscribe_folder(get_ancestor(session), mb);
+}
+
+static int mhdriver_cached_unsubscribe_folder(mailsession * session,
+ char * mb)
+{
+ return mailsession_unsubscribe_folder(get_ancestor(session), mb);
+}
+
+/* messages operations */
+
+static int mhdriver_cached_append_message(mailsession * session,
+ char * message, size_t size)
+{
+ return mhdriver_cached_append_message_flags(session,
+ message, size, NULL);
+}
+
+static int mhdriver_cached_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ int r;
+ struct mailmh_folder * folder;
+ struct mailmh_msg_info * msg_info;
+ chashdatum key;
+ chashdatum value;
+ uint32_t uid;
+ struct mh_cached_session_state_data * data;
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ char keyname[PATH_MAX];
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = mailmh_folder_add_message_uid(folder,
+ message, size, &uid);
+
+ switch (r) {
+ case MAILMH_ERROR_FILE:
+ return MAIL_ERROR_DISKSPACE;
+
+ case MAILMH_NO_ERROR:
+ break;
+
+ default:
+ return mhdriver_mh_error_to_mail_error(r);
+ }
+
+ if (flags == NULL)
+ goto exit;
+
+ key.data = &uid;
+ key.len = sizeof(uid);
+ r = chash_get(folder->fl_msgs_hash, &key, &value);
+ if (r < 0)
+ return MAIL_ERROR_CACHE_MISS;
+
+ msg_info = value.data;
+
+ data = get_cached_data(session);
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ data->mh_flags_directory, data->mh_quoted_mb, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0)
+ goto exit;
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL)
+ goto close_db_flags;
+
+ snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags",
+ uid, (unsigned long) msg_info->msg_mtime,
+ (unsigned long) msg_info->msg_size);
+
+ r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags);
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ if (r != MAIL_NO_ERROR)
+ goto exit;
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ exit:
+ return MAIL_NO_ERROR;
+}
+
+static int mhdriver_cached_copy_message(mailsession * session,
+ uint32_t num, char * mb)
+{
+ return mailsession_copy_message(get_ancestor(session), num, mb);
+}
+
+static int mhdriver_cached_remove_message(mailsession * session, uint32_t num)
+{
+ return mailsession_remove_message(get_ancestor(session), num);
+}
+
+static int mhdriver_cached_move_message(mailsession * session,
+ uint32_t num, char * mb)
+{
+ return mailsession_move_message(get_ancestor(session), num, mb);
+}
+
+static int
+mhdriver_cached_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ struct mailmh_folder * folder;
+ int res;
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ return mh_get_messages_list(folder, session,
+ mh_cached_message_driver, result);
+
+ err:
+ return res;
+}
+
+
+
+static int
+get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
+ mailsession * session, uint32_t num,
+ struct mailimf_fields ** result)
+{
+ int r;
+ char keyname[PATH_MAX];
+ struct mailimf_fields * fields;
+ int res;
+ struct mailmh_folder * folder;
+ struct mailmh_msg_info * msg_info;
+ chashdatum key;
+ chashdatum data;
+
+ folder = get_mh_cur_folder(session);
+
+#if 0
+ msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num);
+ if (msg_info == NULL)
+ return MAIL_ERROR_CACHE_MISS;
+#endif
+ key.data = &num;
+ key.len = sizeof(num);
+ r = chash_get(folder->fl_msgs_hash, &key, &data);
+ if (r < 0)
+ return MAIL_ERROR_CACHE_MISS;
+ msg_info = data.data;
+
+ snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope",
+ num, (unsigned long) msg_info->msg_mtime,
+ (unsigned long) msg_info->msg_size);
+
+ r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = fields;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
+ mailsession * session, uint32_t num,
+ struct mailimf_fields * fields)
+{
+ int r;
+ char keyname[PATH_MAX];
+ int res;
+ struct mailmh_folder * folder;
+ chashdatum key;
+ chashdatum data;
+ struct mailmh_msg_info * msg_info;
+
+ folder = get_mh_cur_folder(session);
+#if 0
+ msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num);
+ if (msg_info == NULL) {
+ res = MAIL_ERROR_CACHE_MISS;
+ goto err;
+ }
+#endif
+ key.data = &num;
+ key.len = sizeof(num);
+ r = chash_get(folder->fl_msgs_hash, &key, &data);
+ if (r < 0)
+ return MAIL_ERROR_CACHE_MISS;
+ msg_info = data.data;
+
+ snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope",
+ num, (unsigned long) msg_info->msg_mtime,
+ (unsigned long) msg_info->msg_size);
+
+ r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+mhdriver_cached_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list)
+{
+ int r;
+ unsigned int i;
+ char filename_env[PATH_MAX];
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_env;
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ int res;
+ struct mh_cached_session_state_data * cached_data;
+
+ cached_data = get_cached_data(session);
+ if (cached_data->mh_quoted_mb == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ mh_flags_store_process(cached_data->mh_flags_directory,
+ cached_data->mh_quoted_mb,
+ cached_data->mh_flags_store);
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(filename_env, PATH_MAX, "%s/%s/%s",
+ cached_data->mh_cache_directory,
+ cached_data->mh_quoted_mb, ENV_NAME);
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_env;
+ }
+
+ /* fill with cached */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+ struct mailimf_fields * fields;
+ struct mail_flags * flags;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields == NULL) {
+ r = get_cached_envelope(cache_db_env, mmapstr,
+ msg->msg_session, msg->msg_index, &fields);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_cached = TRUE;
+ msg->msg_fields = fields;
+ }
+ }
+
+ if (msg->msg_flags == NULL) {
+ r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
+ session, msg->msg_index, &flags);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_flags = flags;
+ }
+ }
+ }
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+
+ r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_env;
+ }
+
+ /* add flags */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_flags == NULL)
+ msg->msg_flags = mail_flags_new_empty();
+ }
+
+ /* must write cache */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields != NULL) {
+ if (!msg->msg_cached) {
+ r = write_cached_envelope(cache_db_env, mmapstr,
+ session, msg->msg_index, msg->msg_fields);
+ }
+ }
+
+ if (msg->msg_flags != NULL) {
+ r = mhdriver_write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_uid, msg->msg_flags);
+ }
+ }
+
+ /* flush cache */
+
+ maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+
+ mmap_string_free(mmapstr);
+
+ return MAIL_NO_ERROR;
+
+ close_db_env:
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ err:
+ return res;
+}
+
+static int mhdriver_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, mh_cached_message_driver, num, 0);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = msg_info;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mhdriver_cached_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result)
+{
+ uint32_t index;
+ char *p;
+ struct mailmh_msg_info * mh_msg_info;
+ struct mailmh_folder * folder;
+ time_t mtime;
+ char * mtime_p;
+ chashdatum key;
+ chashdatum data;
+ int r;
+
+ if (uid == NULL)
+ return MAIL_ERROR_INVAL;
+
+ index = strtoul(uid, &p, 10);
+ if (p == uid || * p != '-')
+ return MAIL_ERROR_INVAL;
+
+ folder = get_mh_cur_folder(session);
+
+ mh_msg_info = NULL;
+ key.data = &index;
+ key.len = sizeof(index);
+ r = chash_get(folder->fl_msgs_hash, &key, &data);
+ if (r < 0)
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ mh_msg_info = data.data;
+
+ mtime_p = p + 1;
+
+ mtime = strtoul(mtime_p, &p, 10);
+ if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) {
+ size_t size;
+ char *size_p;
+
+ size_p = p + 1;
+ size = strtoul(size_p, &p, 10);
+ if ((* p == '\0') && (size == mh_msg_info->msg_size))
+ return mhdriver_cached_get_message(session, index, result);
+ }
+ else if (*p != '-') {
+ return MAIL_ERROR_INVAL;
+ }
+
+ return MAIL_ERROR_MSG_NOT_FOUND;
+}
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_cached.h b/libetpan/src/driver/implementation/mh/mhdriver_cached.h
new file mode 100644
index 0000000..d2e5803
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_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 MHDRIVER_CACHED_H
+
+#define MHDRIVER_CACHED_H
+
+#include <libetpan/mhdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * mh_cached_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_cached_message.c b/libetpan/src/driver/implementation/mh/mhdriver_cached_message.c
new file mode 100644
index 0000000..a59beea
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_cached_message.c
@@ -0,0 +1,338 @@
+/*
+ * 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 "mhdriver_message.h"
+
+#include "mailmessage_tools.h"
+#include "mhdriver_tools.h"
+#include "mhdriver_cached.h"
+#include "mailmh.h"
+#include "generic_cache.h"
+
+#include "mail_cache_db.h"
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+static int mh_prefetch(mailmessage * msg_info);
+
+static void mh_prefetch_free(struct generic_message_t * msg);
+
+static int mh_initialize(mailmessage * msg_info);
+
+static int mh_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static int mh_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result);
+
+static void mh_uninitialize(mailmessage * msg_info);
+
+static void mh_flush(mailmessage * msg_info);
+
+static void mh_check(mailmessage * msg_info);
+
+static int mh_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static mailmessage_driver local_mh_cached_message_driver = {
+ .msg_name = "mh-cached",
+
+ .msg_initialize = mh_initialize,
+ .msg_uninitialize = mh_uninitialize,
+
+ .msg_flush = mh_flush,
+ .msg_check = mh_check,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = mh_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_body,
+ .msg_fetch_size = mh_fetch_size,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = mh_get_flags,
+};
+
+mailmessage_driver * mh_cached_message_driver =
+&local_mh_cached_message_driver;
+
+static inline struct mh_cached_session_state_data *
+get_cached_session_data(mailmessage * msg)
+{
+ return msg->msg_session->sess_data;
+}
+
+static inline mailsession * get_ancestor_session(mailmessage * msg)
+{
+ return get_cached_session_data(msg)->mh_ancestor;
+}
+
+static inline struct mh_session_state_data *
+get_ancestor_session_data(mailmessage * msg)
+{
+ return get_ancestor_session(msg)->sess_data;
+}
+
+static inline struct mailmh *
+get_mh_session(mailmessage * msg)
+{
+ return get_ancestor_session_data(msg)->mh_session;
+}
+
+static inline struct mailmh_folder *
+get_mh_cur_folder(mailmessage * msg)
+{
+ return get_ancestor_session_data(msg)->mh_cur_folder;
+}
+
+static int mh_prefetch(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * msg_content;
+ size_t msg_length;
+
+ r = mhdriver_fetch_message(get_ancestor_session(msg_info),
+ msg_info->msg_index, &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static void mh_prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ mmap_string_unref(msg->msg_message);
+ msg->msg_message = NULL;
+ }
+}
+
+static int mh_initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * uid;
+ char static_uid[PATH_MAX];
+ struct mailmh_msg_info * mh_msg_info;
+ chashdatum key;
+ chashdatum data;
+ struct mailmh_folder * folder;
+
+ folder = get_mh_cur_folder(msg_info);
+
+ key.data = &msg_info->msg_index;
+ key.len = sizeof(msg_info->msg_index);
+ r = chash_get(folder->fl_msgs_hash, &key, &data);
+ if (r < 0)
+ return MAIL_ERROR_INVAL;
+
+ mh_msg_info = data.data;
+
+ snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index,
+ mh_msg_info->msg_mtime, (unsigned long) mh_msg_info->msg_size);
+ uid = strdup(static_uid);
+ if (uid == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR) {
+ free(uid);
+ return r;
+ }
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = mh_prefetch;
+ msg->msg_prefetch_free = mh_prefetch_free;
+ msg_info->msg_uid = uid;
+
+ return MAIL_NO_ERROR;
+}
+
+static void mh_uninitialize(mailmessage * msg_info)
+{
+ mailmessage_generic_uninitialize(msg_info);
+}
+
+
+#define FLAGS_NAME "flags.db"
+
+static void mh_flush(mailmessage * msg_info)
+{
+ mailmessage_generic_flush(msg_info);
+}
+
+static void mh_check(mailmessage * msg_info)
+{
+ int r;
+
+ if (msg_info->msg_flags != NULL) {
+ r = mail_flags_store_set(get_cached_session_data(msg_info)->mh_flags_store,
+ msg_info);
+ /* ignore errors */
+ }
+}
+
+static int mh_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ int r;
+ size_t size;
+
+ r = mhdriver_fetch_size(get_ancestor_session(msg_info),
+ msg_info->msg_index, &size);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = size;
+
+ return MAIL_NO_ERROR;
+}
+
+static int mh_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result)
+{
+ int r;
+ struct mail_flags * flags;
+ struct mail_cache_db * cache_db_flags;
+ char filename_flags[PATH_MAX];
+ int res;
+ struct mh_cached_session_state_data * cached_data;
+ MMAPString * mmapstr;
+
+ if (msg_info->msg_flags != NULL) {
+ * result = msg_info->msg_flags;
+
+ return MAIL_NO_ERROR;
+ }
+
+ cached_data = get_cached_session_data(msg_info);
+
+ flags = mail_flags_store_get(cached_data->mh_flags_store,
+ msg_info->msg_index);
+
+ if (flags == NULL) {
+ if (cached_data->mh_quoted_mb == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ cached_data->mh_flags_directory,
+ cached_data->mh_quoted_mb, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
+ msg_info->msg_session, msg_info->msg_index, &flags);
+ if (r != MAIL_NO_ERROR) {
+ flags = mail_flags_new_empty();
+ if (flags == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ }
+
+ msg_info->msg_flags = flags;
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static int mh_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * msg_content;
+ size_t msg_length;
+
+ msg = msg_info->msg_data;
+ if (msg->msg_message != NULL) {
+ return mailmessage_generic_fetch_header(msg_info, result, result_len);
+ }
+ else {
+ r = mhdriver_fetch_header(get_ancestor_session(msg_info),
+ msg_info->msg_index, &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = msg_content;
+ * result_len = msg_length;
+
+ return MAIL_NO_ERROR;
+ }
+}
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_cached_message.h b/libetpan/src/driver/implementation/mh/mhdriver_cached_message.h
new file mode 100644
index 0000000..f585708
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_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 MHDRIVER_CACHED_MESSAGE_H
+
+#define MHDRIVER_CACHED_MESSAGE_H
+
+#include <libetpan/mhdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * mh_cached_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_message.c b/libetpan/src/driver/implementation/mh/mhdriver_message.c
new file mode 100644
index 0000000..0e486b4
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_message.c
@@ -0,0 +1,213 @@
+/*
+ * 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 "mhdriver_message.h"
+
+#include "mailmessage_tools.h"
+#include "mhdriver_tools.h"
+#include "mhdriver.h"
+#include "mailmh.h"
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+static int mh_prefetch(mailmessage * msg_info);
+
+static void mh_prefetch_free(struct generic_message_t * msg);
+
+static int mh_initialize(mailmessage * msg_info);
+
+static int mh_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static int mh_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static mailmessage_driver local_mh_message_driver = {
+ .msg_name = "mh",
+
+ .msg_initialize = mh_initialize,
+ .msg_uninitialize = mailmessage_generic_uninitialize,
+
+ .msg_flush = mailmessage_generic_flush,
+ .msg_check = NULL,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = mh_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_body,
+ .msg_fetch_size = mh_fetch_size,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = NULL,
+};
+
+mailmessage_driver * mh_message_driver = &local_mh_message_driver;
+
+static int mh_prefetch(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * msg_content;
+ size_t msg_length;
+
+ r = mhdriver_fetch_message(msg_info->msg_session, msg_info->msg_index,
+ &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static void mh_prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ mmap_string_unref(msg->msg_message);
+ msg->msg_message = NULL;
+ }
+}
+
+static inline struct mh_session_state_data * get_data(mailmessage * msg)
+{
+ return msg->msg_session->sess_data;
+}
+
+static inline struct mailmh_folder * get_mh_cur_folder(mailmessage * msg)
+{
+ return get_data(msg)->mh_cur_folder;
+}
+
+static int mh_initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * uid;
+ char static_uid[PATH_MAX];
+ struct mailmh_msg_info * mh_msg_info;
+ chashdatum key;
+ chashdatum value;
+
+ key.data = &msg_info->msg_index;
+ key.len = sizeof(msg_info->msg_index);
+ r = chash_get(get_mh_cur_folder(msg_info)->fl_msgs_hash, &key, &value);
+ if (r < 0)
+ return MAIL_ERROR_INVAL;
+
+ mh_msg_info = value.data;
+
+ snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index,
+ (unsigned long) mh_msg_info->msg_mtime,
+ (unsigned long) mh_msg_info->msg_size);
+ uid = strdup(static_uid);
+ if (uid == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR) {
+ free(uid);
+ return r;
+ }
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = mh_prefetch;
+ msg->msg_prefetch_free = mh_prefetch_free;
+ msg_info->msg_uid = uid;
+
+ return MAIL_NO_ERROR;
+}
+
+
+static int mh_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ int r;
+ size_t size;
+
+ r = mhdriver_fetch_size(msg_info->msg_session, msg_info->msg_index, &size);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = size;
+
+ return MAIL_NO_ERROR;
+}
+
+
+
+
+static int mh_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * msg_content;
+ size_t msg_length;
+
+ msg = msg_info->msg_data;
+ if (msg->msg_message != NULL) {
+
+ r = mailmessage_generic_fetch_header(msg_info, result, result_len);
+ return r;
+ }
+ else {
+ r = mhdriver_fetch_header(msg_info->msg_session, msg_info->msg_index,
+ &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = msg_content;
+ * result_len = msg_length;
+
+ return MAIL_NO_ERROR;
+ }
+}
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_message.h b/libetpan/src/driver/implementation/mh/mhdriver_message.h
new file mode 100644
index 0000000..2b11f3e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_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 MHDRIVER_MESSAGE_H
+
+#define MHDRIVER_MESSAGE_H
+
+#include <libetpan/mhdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * mh_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_tools.c b/libetpan/src/driver/implementation/mh/mhdriver_tools.c
new file mode 100644
index 0000000..b8bcf03
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_tools.c
@@ -0,0 +1,484 @@
+/*
+ * 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 "mhdriver_tools.h"
+
+#include "mailmessage.h"
+#include "mhdriver.h"
+#include "mhdriver_cached.h"
+#include "maildriver_types.h"
+#include "mailmh.h"
+#include "generic_cache.h"
+#include "imfcache.h"
+#include "mail_cache_db.h"
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+int mhdriver_mh_error_to_mail_error(int error)
+{
+ switch (error) {
+ case MAILMH_NO_ERROR:
+ return MAIL_NO_ERROR;
+
+ case MAILMH_ERROR_FOLDER:
+ return MAIL_ERROR_FOLDER;
+
+ case MAILMH_ERROR_MEMORY:
+ return MAIL_ERROR_MEMORY;
+
+ case MAILMH_ERROR_FILE:
+ return MAIL_ERROR_FILE;
+
+ case MAILMH_ERROR_COULD_NOT_ALLOC_MSG:
+ return MAIL_ERROR_APPEND;
+
+ case MAILMH_ERROR_RENAME:
+ return MAIL_ERROR_RENAME;
+
+ case MAILMH_ERROR_MSG_NOT_FOUND:
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ default:
+ return MAIL_ERROR_INVAL;
+ }
+}
+
+
+static inline struct mh_session_state_data * get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session)
+{
+ return get_data(session)->mh_cur_folder;
+}
+
+static inline struct mh_cached_session_state_data *
+cached_get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+
+static inline mailsession * cached_get_ancestor(mailsession * session)
+{
+ return cached_get_data(session)->mh_ancestor;
+}
+
+static inline struct mh_session_state_data *
+cached_get_ancestor_data(mailsession * session)
+{
+ return get_data(cached_get_ancestor(session));
+}
+
+static inline struct mailmh_folder *
+cached_get_mh_cur_folder(mailsession * session)
+{
+ return get_mh_cur_folder(cached_get_ancestor(session));
+}
+
+int mhdriver_fetch_message(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len)
+{
+ size_t size;
+ size_t cur_token;
+ struct mailmh_folder * folder;
+ int fd;
+ MMAPString * mmapstr;
+ char * str;
+ int res;
+ int r;
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd);
+
+ switch (r) {
+ case MAILMH_NO_ERROR:
+ break;
+
+ default:
+ res = mhdriver_mh_error_to_mail_error(r);
+ goto close;
+ }
+
+ r = mhdriver_fetch_size(session, index, &size);
+
+ switch (r) {
+ case MAILMH_NO_ERROR:
+ break;
+
+ default:
+ res = mhdriver_mh_error_to_mail_error(r);
+ goto close;
+ }
+
+ str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (str == MAP_FAILED) {
+ res = MAIL_ERROR_FETCH;
+ goto close;
+ }
+
+ /* strip "From " header for broken implementations */
+ /* XXX - called twice, make a function */
+ cur_token = 0;
+ if (strncmp("From ", str, 5) == 0) {
+ cur_token += 5;
+
+ while (1) {
+ if (str[cur_token] == '\n') {
+ cur_token ++;
+ break;
+ }
+ if (cur_token >= size)
+ break;
+ cur_token ++;
+ }
+ }
+
+ mmapstr = mmap_string_new_len(str + cur_token, size - cur_token);
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto unmap;
+ }
+
+ if (mmap_string_ref(mmapstr) != 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_str;
+ }
+
+ munmap(str, size);
+ close(fd);
+
+ * result = mmapstr->str;
+ * result_len = mmapstr->len;
+
+ return MAIL_NO_ERROR;
+
+ free_str:
+ mmap_string_free(mmapstr);
+ unmap:
+ munmap(str, size);
+ close:
+ close(fd);
+ err:
+ return res;
+}
+
+
+int mhdriver_fetch_header(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len)
+{
+ size_t size;
+ size_t cur_token;
+ size_t begin;
+ struct mailmh_folder * folder;
+ int fd;
+ MMAPString * mmapstr;
+ char * str;
+ int res;
+ int r;
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd);
+
+ switch (r) {
+ case MAILMH_NO_ERROR:
+ break;
+
+ default:
+ res = mhdriver_mh_error_to_mail_error(r);
+ goto close;
+ }
+
+ r = mhdriver_fetch_size(session, index, &size);
+
+ switch (r) {
+ case MAILMH_NO_ERROR:
+ break;
+
+ default:
+ res = mhdriver_mh_error_to_mail_error(r);
+ goto close;
+ }
+
+ str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (str == MAP_FAILED) {
+ res = MAIL_ERROR_FETCH;
+ goto close;
+ }
+
+ /* strip "From " header for broken implementations */
+ cur_token = 0;
+ if (size > 5) {
+ if (strncmp("From ", str, 5) == 0) {
+ cur_token += 5;
+
+ while (1) {
+ if (str[cur_token] == '\n') {
+ cur_token ++;
+ break;
+ }
+ if (cur_token >= size)
+ break;
+ cur_token ++;
+ }
+ }
+ }
+
+ begin = cur_token;
+
+ while (1) {
+ r = mailimf_ignore_field_parse(str, size, &cur_token);
+ if (r == MAILIMF_NO_ERROR) {
+ /* do nothing */
+ }
+ else
+ break;
+ }
+ mailimf_crlf_parse(str, size, &cur_token);
+
+ mmapstr = mmap_string_new_len(str + begin, cur_token - begin);
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto unmap;
+ }
+
+ if (mmap_string_ref(mmapstr) != 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_str;
+ }
+
+ munmap(str, size);
+ close(fd);
+
+ * result = mmapstr->str;
+ * result_len = mmapstr->len;
+
+ return MAIL_NO_ERROR;
+
+ free_str:
+ mmap_string_free(mmapstr);
+ unmap:
+ munmap(str, size);
+ close:
+ close(fd);
+ err:
+ return res;
+}
+
+
+int mhdriver_fetch_size(mailsession * session, uint32_t index,
+ size_t * result)
+{
+ struct mailmh_folder * folder;
+ int r;
+ struct stat buf;
+ char * name;
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL)
+ return MAIL_ERROR_FETCH;
+
+ r = mailmh_folder_get_message_filename(folder, index, &name);
+
+ switch (r) {
+ case MAILMH_NO_ERROR:
+ break;
+
+ default:
+ return mhdriver_mh_error_to_mail_error(r);
+ }
+
+ r = stat(name, &buf);
+ free(name);
+ if (r == -1)
+ return MAIL_ERROR_FETCH;
+
+ * result = buf.st_size;
+
+ return MAIL_NO_ERROR;
+}
+
+int
+mhdriver_get_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ mailsession * session,
+ uint32_t num,
+ struct mail_flags ** result)
+{
+ int r;
+ char keyname[PATH_MAX];
+ struct mail_flags * flags;
+ int res;
+ struct mailmh_msg_info * msg_info;
+ chashdatum key;
+ chashdatum data;
+ struct mailmh_folder * folder;
+
+ folder = cached_get_mh_cur_folder(session);
+#if 0
+ msg_info = cinthash_find(mh_data->cur_folder->fl_msgs_hash, num);
+ if (msg_info == NULL)
+ return MAIL_ERROR_CACHE_MISS;
+#endif
+ key.data = &num;
+ key.len = sizeof(num);
+ r = chash_get(folder->fl_msgs_hash, &key, &data);
+ if (r < 0)
+ return MAIL_ERROR_CACHE_MISS;
+ msg_info = data.data;
+
+ snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags",
+ num, (unsigned long) msg_info->msg_mtime,
+ (unsigned long) msg_info->msg_size);
+
+ r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+int
+mhdriver_write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ char * uid,
+ struct mail_flags * flags)
+{
+ int r;
+ char keyname[PATH_MAX];
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%s-flags", uid);
+
+ r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+
+int mh_get_messages_list(struct mailmh_folder * folder,
+ mailsession * session, mailmessage_driver * driver,
+ struct mailmessage_list ** result)
+{
+ unsigned int i;
+ struct mailmessage_list * env_list;
+ int r;
+ carray * tab;
+ int res;
+
+ tab = carray_new(128);
+ if (tab == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
+ struct mailmh_msg_info * mh_info;
+ mailmessage * msg;
+
+ mh_info = carray_get(folder->fl_msgs_tab, i);
+ if (mh_info == NULL)
+ continue;
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = mailmessage_init(msg, session, driver,
+ mh_info->msg_index, mh_info->msg_size);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_list;
+ }
+
+ r = carray_add(tab, msg, NULL);
+ if (r < 0) {
+ mailmessage_free(msg);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ env_list = mailmessage_list_new(tab);
+ if (env_list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = env_list;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ for(i = 0 ; i < carray_count(tab) ; i ++)
+ mailmessage_free(carray_get(tab, i));
+ carray_free(tab);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_tools.h b/libetpan/src/driver/implementation/mh/mhdriver_tools.h
new file mode 100644
index 0000000..7b8928e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_tools.h
@@ -0,0 +1,80 @@
+/*
+ * 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 MHDRIVER_TOOLS_H
+
+#define MHDRIVER_TOOLS_H
+
+#include "maildriver_types.h"
+#include "mail_cache_db_types.h"
+#include "mailmh.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int mhdriver_mh_error_to_mail_error(int error);
+
+int mhdriver_fetch_message(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len);
+
+int mhdriver_fetch_header(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len);
+
+int mhdriver_fetch_size(mailsession * session, uint32_t index,
+ size_t * result);
+
+int
+mhdriver_get_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ mailsession * session,
+ uint32_t num,
+ struct mail_flags ** result);
+
+int
+mhdriver_write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ char * uid,
+ struct mail_flags * flags);
+
+int mh_get_messages_list(struct mailmh_folder * folder,
+ mailsession * session, mailmessage_driver * driver,
+ struct mailmessage_list ** result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_types.h b/libetpan/src/driver/implementation/mh/mhdriver_types.h
new file mode 100644
index 0000000..45afb64
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_types.h
@@ -0,0 +1,100 @@
+/*
+ * 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 MHDRIVER_TYPES_H
+
+#define MHDRIVER_TYPES_H
+
+#include <libetpan/libetpan-config.h>
+
+#include <libetpan/maildriver_types.h>
+#include <libetpan/mailmh.h>
+#include <libetpan/clist.h>
+#include <libetpan/generic_cache_types.h>
+#include <libetpan/mailstorage_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct mh_session_state_data {
+ struct mailmh * mh_session;
+
+ struct mailmh_folder * mh_cur_folder;
+
+ clist * mh_subscribed_list;
+};
+
+enum {
+ MHDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
+ MHDRIVER_CACHED_SET_FLAGS_DIRECTORY,
+};
+
+struct mh_cached_session_state_data {
+ mailsession * mh_ancestor;
+ char * mh_quoted_mb;
+ char mh_cache_directory[PATH_MAX];
+ char mh_flags_directory[PATH_MAX];
+ struct mail_flags_store * mh_flags_store;
+};
+
+/* mh storage */
+
+/*
+ mh_mailstorage is the state data specific to the MH storage.
+
+ - pathname is the root path of the MH storage.
+
+ - cached if this value is != 0, a persistant cache will be
+ stored on local system.
+
+ - cache_directory is the location of the cache.
+
+ - flags_directory is the location of the flags.
+*/
+
+struct mh_mailstorage {
+ char * mh_pathname;
+
+ int mh_cached;
+ char * mh_cache_directory;
+ char * mh_flags_directory;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mh/mhstorage.c b/libetpan/src/driver/implementation/mh/mhstorage.c
new file mode 100644
index 0000000..e7fc2f0
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhstorage.c
@@ -0,0 +1,192 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "mhstorage.h"
+
+#include "mhdriver.h"
+#include "mhdriver_cached.h"
+#include "mail.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* mh storage */
+
+static int mh_mailstorage_connect(struct mailstorage * storage);
+static int mh_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result);
+static void mh_mailstorage_uninitialize(struct mailstorage * storage);
+
+static mailstorage_driver mh_mailstorage_driver = {
+ .sto_name = "mh",
+ .sto_connect = mh_mailstorage_connect,
+ .sto_get_folder_session = mh_mailstorage_get_folder_session,
+ .sto_uninitialize = mh_mailstorage_uninitialize,
+};
+
+int mh_mailstorage_init(struct mailstorage * storage,
+ char * mh_pathname, int mh_cached,
+ char * mh_cache_directory, char * mh_flags_directory)
+{
+ struct mh_mailstorage * mh_storage;
+
+ mh_storage = malloc(sizeof(* mh_storage));
+ if (mh_storage == NULL)
+ goto err;
+
+ mh_storage->mh_pathname = strdup(mh_pathname);
+ if (mh_storage->mh_pathname == NULL)
+ goto free;
+
+ mh_storage->mh_cached = mh_cached;
+
+ if (mh_cached && (mh_cache_directory != NULL) &&
+ (mh_flags_directory != NULL)) {
+ mh_storage->mh_cache_directory = strdup(mh_cache_directory);
+ if (mh_storage->mh_cache_directory == NULL)
+ goto free_pathname;
+ mh_storage->mh_flags_directory = strdup(mh_flags_directory);
+ if (mh_storage->mh_flags_directory == NULL)
+ goto free_cache_directory;
+ }
+ else {
+ mh_storage->mh_cached = FALSE;
+ mh_storage->mh_cache_directory = NULL;
+ mh_storage->mh_flags_directory = NULL;
+ }
+
+ storage->sto_data = mh_storage;
+ storage->sto_driver = &mh_mailstorage_driver;
+
+ return MAIL_NO_ERROR;
+
+ free_cache_directory:
+ free(mh_storage->mh_cache_directory);
+ free_pathname:
+ free(mh_storage->mh_pathname);
+ free:
+ free(mh_storage);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void mh_mailstorage_uninitialize(struct mailstorage * storage)
+{
+ struct mh_mailstorage * mh_storage;
+
+ mh_storage = storage->sto_data;
+ if (mh_storage->mh_flags_directory != NULL)
+ free(mh_storage->mh_flags_directory);
+ if (mh_storage->mh_cache_directory != NULL)
+ free(mh_storage->mh_cache_directory);
+ free(mh_storage->mh_pathname);
+ free(mh_storage);
+
+ storage->sto_data = NULL;
+}
+
+static int mh_mailstorage_connect(struct mailstorage * storage)
+{
+ struct mh_mailstorage * mh_storage;
+ mailsession_driver * driver;
+ int r;
+ int res;
+ mailsession * session;
+
+ mh_storage = storage->sto_data;
+
+ if (mh_storage->mh_cached)
+ driver = mh_cached_session_driver;
+ else
+ driver = mh_session_driver;
+
+ session = mailsession_new(driver);
+ if (session == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ if (mh_storage->mh_cached) {
+ r = mailsession_parameters(session,
+ MHDRIVER_CACHED_SET_CACHE_DIRECTORY,
+ mh_storage->mh_cache_directory);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ r = mailsession_parameters(session,
+ MHDRIVER_CACHED_SET_FLAGS_DIRECTORY,
+ mh_storage->mh_flags_directory);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+ }
+
+ r = mailsession_connect_path(session, mh_storage->mh_pathname);
+ switch (r) {
+ case MAIL_NO_ERROR_NON_AUTHENTICATED:
+ case MAIL_NO_ERROR_AUTHENTICATED:
+ case MAIL_NO_ERROR:
+ break;
+ default:
+ res = r;
+ goto free;
+ }
+
+ storage->sto_session = session;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailsession_free(session);
+ err:
+ return res;
+}
+
+static int mh_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result)
+{
+ int r;
+
+ r = mailsession_select_folder(storage->sto_session, pathname);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = storage->sto_session;
+
+ return MAIL_NO_ERROR;
+}
diff --git a/libetpan/src/driver/implementation/mh/mhstorage.h b/libetpan/src/driver/implementation/mh/mhstorage.h
new file mode 100644
index 0000000..be86007
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhstorage.h
@@ -0,0 +1,67 @@
+/*
+ * 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 MHSTORAGE_H
+
+#define MHSTORAGE_H
+
+#include <libetpan/mhdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ mh_mailstorage_init is the constructor for a MH storage
+
+ @param pathname is the filename the root path of the MH storage.
+
+ @param cached if this value is != 0, a persistant cache will be
+ stored on local system.
+
+ @param cache_directory is the location of the cache.
+
+ @param flags_directory is the location of the flags.
+*/
+
+int mh_mailstorage_init(struct mailstorage * storage,
+ char * mh_pathname, int mh_cached,
+ char * mh_cache_directory, char * mh_flags_directory);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/mime-message/mime_message_driver.c b/libetpan/src/driver/implementation/mime-message/mime_message_driver.c
new file mode 100644
index 0000000..06defbd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mime-message/mime_message_driver.c
@@ -0,0 +1,914 @@
+/*
+ * 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 "mime_message_driver.h"
+
+#include "libetpan-config.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mailmessage.h"
+#include "mailmessage_tools.h"
+#include "maildriver_tools.h"
+
+#if 0
+static FILE * get_mime_tmp_file(mailmessage * msg,
+ char * filename, size_t size)
+{
+ int fd;
+ mode_t old_mask;
+ FILE * f;
+
+ if (msg->msg_data == NULL)
+ return NULL;
+
+ snprintf(filename, size, "%s/libetpan-mime-XXXXXX",
+ (char *) msg->msg_data);
+
+ old_mask = umask(0077);
+ fd = mkstemp(filename);
+ umask(old_mask);
+ if (fd == -1)
+ return NULL;
+
+ f = fdopen(fd, "r+");
+ if (f == NULL) {
+ close(fd);
+ unlink(filename);
+ }
+
+ return f;
+}
+#endif
+
+int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir)
+{
+#if 0
+ if (msg->msg_data != NULL)
+ free(msg->msg_data);
+
+ msg->msg_data = strdup(tmpdir);
+ if (msg->msg_data == NULL)
+ return MAIL_ERROR_MEMORY;
+
+#endif
+ return MAIL_NO_ERROR;
+}
+
+void mime_message_detach_mime(mailmessage * msg)
+{
+ msg->msg_mime = NULL;
+}
+
+mailmessage * mime_message_init(struct mailmime * mime)
+{
+ mailmessage * msg;
+ int r;
+
+ msg = mailmessage_new();
+ if (msg == NULL)
+ goto err;
+
+ r = mailmessage_init(msg, NULL, mime_message_driver, 0, 0);
+ if (r != MAIL_NO_ERROR)
+ goto free;
+
+ if (mime != NULL) {
+ mailmime_free(msg->msg_mime);
+ msg->msg_mime = mime;
+ }
+
+ return msg;
+
+ free:
+ mailmessage_free(msg);
+ err:
+ return NULL;
+}
+
+static int initialize(mailmessage * msg)
+{
+ struct mailmime * mime;
+ int res;
+
+ mime = mailmime_new_message_data(NULL);
+ if (mime == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ msg->msg_mime = mime;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static void uninitialize(mailmessage * msg)
+{
+ /* tmp dir name */
+ if (msg->msg_data != NULL)
+ free(msg->msg_data);
+
+ if (msg->msg_mime != NULL)
+ mailmime_free(msg->msg_mime);
+ msg->msg_mime = NULL;
+}
+
+static void flush(mailmessage * msg)
+{
+ /* do nothing */
+}
+
+static void check(mailmessage * msg)
+{
+ /* do nothing */
+}
+
+static void fetch_result_free(mailmessage * msg_info, char * content)
+{
+ mmap_string_unref(content);
+}
+
+#if 0
+static int file_to_mmapstr(FILE * f,
+ char ** result, size_t * result_len)
+{
+ int fd;
+ char * data;
+ struct stat buf;
+ MMAPString * mmapstr;
+ int res;
+ int r;
+
+ fd = fileno(f);
+ if (fd == -1) {
+ res = MAIL_ERROR_FILE;
+
+ goto err;
+ }
+
+ fflush(f);
+ r = fstat(fd, &buf);
+ if (r == -1) {
+ res = MAIL_ERROR_FILE;
+
+ goto err;
+ }
+
+ data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (data == MAP_FAILED) {
+ res = MAIL_ERROR_FILE;
+
+ goto err;
+ }
+
+ mmapstr = mmap_string_new_len(data, buf.st_size);
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+
+ goto unmap;
+ }
+
+ munmap(data, buf.st_size);
+
+ r = mmap_string_ref(mmapstr);
+ if (r != 0) {
+ res = MAIL_ERROR_MEMORY;
+
+ goto err;
+ }
+
+ * result = mmapstr->str;
+ * result_len = mmapstr->len;
+
+ return MAIL_NO_ERROR;
+
+ unmap:
+ munmap(data, buf.st_size);
+ err:
+ return res;
+}
+#endif
+
+#if 0
+static int file_body_to_mmapstr(FILE * f,
+ char ** result, size_t * result_len)
+{
+ int fd;
+ char * data;
+ struct stat buf;
+ MMAPString * mmapstr;
+ size_t cur_token;
+ int res;
+ int r;
+
+ fd = fileno(f);
+ if (fd == -1) {
+ res = MAIL_ERROR_FILE;
+
+ goto err;
+ }
+
+ fflush(f);
+ r = fstat(fd, &buf);
+ if (r == -1) {
+ res = MAIL_ERROR_FILE;
+
+ goto err;
+ }
+
+ data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (data == MAP_FAILED) {
+ res = MAIL_ERROR_FILE;
+
+ goto err;
+ }
+
+ cur_token = 0;
+
+ /* skip header */
+
+ while (1) {
+ r = mailimf_ignore_field_parse(data,
+ buf.st_size, &cur_token);
+ if (r == MAILIMF_NO_ERROR) {
+ /* do nothing */
+ }
+ else
+ break;
+ }
+
+ r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
+ if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
+ res = maildriver_imf_error_to_mail_error(r);
+ goto unmap;
+ }
+
+ mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token);
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+
+ goto unmap;
+ }
+
+ munmap(data, buf.st_size);
+
+ r = mmap_string_ref(mmapstr);
+ if (r != 0) {
+ res = MAIL_ERROR_MEMORY;
+
+ goto err;
+ }
+
+ * result = mmapstr->str;
+ * result_len = mmapstr->len;
+
+ return MAIL_NO_ERROR;
+
+ unmap:
+ munmap(data, buf.st_size);
+ err:
+ return res;
+}
+#endif
+
+
+static int body_to_mmapstr(char * data, size_t size,
+ char ** result, size_t * result_len)
+{
+ MMAPString * mmapstr;
+ size_t cur_token;
+ int res;
+ int r;
+
+ cur_token = 0;
+
+ /* skip header */
+
+ while (1) {
+ r = mailimf_ignore_field_parse(data, size, &cur_token);
+ if (r == MAILIMF_NO_ERROR) {
+ /* do nothing */
+ }
+ else
+ break;
+ }
+
+ r = mailimf_crlf_parse(data, size, &cur_token);
+ if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
+ res = maildriver_imf_error_to_mail_error(r);
+ goto err;
+ }
+
+ mmapstr = mmap_string_new_len(data + cur_token, size - cur_token);
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+
+ goto err;
+ }
+
+ r = mmap_string_ref(mmapstr);
+ if (r != 0) {
+ mmap_string_free(mmapstr);
+ res = MAIL_ERROR_MEMORY;
+
+ goto err;
+ }
+
+ * result = mmapstr->str;
+ * result_len = mmapstr->len;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+
+#if 0
+static int file_body_body_to_mmapstr(FILE * f,
+ char ** result, size_t * result_len)
+{
+ int fd;
+ char * data;
+ struct stat buf;
+ MMAPString * mmapstr;
+ size_t cur_token;
+ int res;
+ int r;
+
+ fd = fileno(f);
+ if (fd == -1) {
+ res = MAIL_ERROR_FILE;
+
+ goto err;
+ }
+
+ fflush(f);
+ r = fstat(fd, &buf);
+ if (r == -1) {
+ res = MAIL_ERROR_FILE;
+
+ goto err;
+ }
+
+ data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (data == MAP_FAILED) {
+ res = MAIL_ERROR_FILE;
+
+ goto err;
+ }
+
+ cur_token = 0;
+
+ /* skip header */
+
+ /* MIME header */
+
+ while (1) {
+ r = mailimf_ignore_field_parse(data,
+ buf.st_size, &cur_token);
+ if (r == MAILIMF_NO_ERROR) {
+ /* do nothing */
+ }
+ else
+ break;
+ }
+
+ r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
+ if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
+ res = maildriver_imf_error_to_mail_error(r);
+ goto unmap;
+ }
+
+ /* headers */
+
+ while (1) {
+ r = mailimf_ignore_field_parse(data,
+ buf.st_size, &cur_token);
+ if (r == MAILIMF_NO_ERROR) {
+ /* do nothing */
+ }
+ else
+ break;
+ }
+
+ r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
+ if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
+ res = maildriver_imf_error_to_mail_error(r);
+ goto unmap;
+ }
+
+ mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token);
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+
+ goto unmap;
+ }
+
+ munmap(data, buf.st_size);
+
+ r = mmap_string_ref(mmapstr);
+ if (r != 0) {
+ res = MAIL_ERROR_MEMORY;
+
+ goto err;
+ }
+
+ * result = mmapstr->str;
+ * result_len = mmapstr->len;
+
+ return MAIL_NO_ERROR;
+
+ unmap:
+ munmap(data, buf.st_size);
+ err:
+ return res;
+}
+#endif
+
+static int body_body_to_mmapstr(char * data, size_t size,
+ char ** result, size_t * result_len)
+{
+ MMAPString * mmapstr;
+ size_t cur_token;
+ int res;
+ int r;
+
+ cur_token = 0;
+
+ /* skip header */
+
+ /* MIME header */
+
+ while (1) {
+ r = mailimf_ignore_field_parse(data, size, &cur_token);
+ if (r == MAILIMF_NO_ERROR) {
+ /* do nothing */
+ }
+ else
+ break;
+ }
+
+ r = mailimf_crlf_parse(data, size, &cur_token);
+ if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
+ res = maildriver_imf_error_to_mail_error(r);
+ goto err;
+ }
+
+ return body_to_mmapstr(data + cur_token, size - cur_token,
+ result, result_len);
+
+ err:
+ return res;
+}
+
+
+static int fetch_section(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result, size_t * result_len)
+{
+ int r;
+#if 0
+ FILE * f;
+#endif
+ int res;
+ int col;
+#if 0
+ char filename[PATH_MAX];
+#endif
+ MMAPString * str;
+
+ if (msg_info->msg_mime == NULL)
+ return MAIL_ERROR_INVAL;
+
+#if 0
+ f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
+ if (f == NULL) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+#endif
+
+ str = mmap_string_new("");
+ if (str == NULL) {
+ res = MAILIMF_ERROR_MEMORY;
+ goto err;
+ }
+
+ col = 0;
+ r = mailmime_write_mem(str, &col, mime);
+ if (r != MAILIMF_NO_ERROR) {
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free;
+ }
+
+#if 0
+ if (mime->mm_parent == NULL)
+ r = file_to_mmapstr(f, result, result_len);
+ else
+ r = file_body_to_mmapstr(f, result, result_len);
+#endif
+ if (mime->mm_parent == NULL) {
+ r = mmap_string_ref(str);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ * result = str->str;
+ * result_len = str->len;
+
+ r = MAIL_NO_ERROR;
+ }
+ else {
+ r = body_to_mmapstr(str->str, str->len, result, result_len);
+ if (r == MAIL_NO_ERROR) {
+ mmap_string_free(str);
+ }
+ }
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+#if 0
+ fclose(f);
+ unlink(filename);
+#endif
+
+ return MAIL_NO_ERROR;
+
+ free:
+#if 0
+ fclose(f);
+ unlink(filename);
+#endif
+ mmap_string_free(str);
+ err:
+ return res;
+}
+
+
+static int fetch_section_header(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result, size_t * result_len)
+{
+ int r;
+#if 0
+ FILE * f;
+#endif
+ int res;
+ int col;
+#if 0
+ char filename[PATH_MAX];
+#endif
+ MMAPString * str;
+
+ if (msg_info->msg_mime == NULL)
+ return MAIL_ERROR_INVAL;
+
+#if 0
+ f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
+ if (f == NULL) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+#endif
+
+ str = mmap_string_new("");
+ if (str == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ col = 0;
+ if (mime->mm_type == MAILMIME_MESSAGE) {
+ if (mime->mm_data.mm_message.mm_fields != NULL) {
+#if 0
+ r = mailimf_fields_write(f, &col, mime->mm_data.mm_message.mm_fields);
+#endif
+ r = mailimf_fields_write_mem(str, &col, mime->mm_data.mm_message.mm_fields);
+ if (r != MAILIMF_NO_ERROR) {
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free;
+ }
+#if 0
+ mailimf_string_write(f, &col, "\r\n", 2);
+#endif
+ mailimf_string_write_mem(str, &col, "\r\n", 2);
+ }
+ }
+
+ r = mmap_string_ref(str);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+#if 0
+ r = file_to_mmapstr(f, result, result_len);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+#endif
+ * result = str->str;
+ * result_len = str->len;
+
+#if 0
+ fclose(f);
+ unlink(filename);
+#endif
+
+ return MAIL_NO_ERROR;
+
+#if 0
+ close:
+ fclose(f);
+ unlink(filename);
+#endif
+ free:
+ mmap_string_free(str);
+ err:
+ return res;
+}
+
+
+static int fetch_section_mime(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result, size_t * result_len)
+{
+ int r;
+#if 0
+ FILE * f;
+#endif
+ int res;
+ int col;
+#if 0
+ char filename[PATH_MAX];
+#endif
+ MMAPString * str;
+
+ if (msg_info->msg_mime == NULL)
+ return MAIL_ERROR_INVAL;
+
+ str = mmap_string_new("");
+ if (str == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+#if 0
+ f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
+ if (f == NULL) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+#endif
+
+ col = 0;
+ if (mime->mm_content_type != NULL) {
+#if 0
+ r = mailmime_content_write(f, &col, mime->mm_content_type);
+#endif
+ r = mailmime_content_write_mem(str, &col, mime->mm_content_type);
+ if (r != MAILIMF_NO_ERROR) {
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free;
+ }
+ }
+ if (mime->mm_mime_fields != NULL) {
+ r = mailmime_fields_write_mem(str, &col, mime->mm_mime_fields);
+ if (r != MAILIMF_NO_ERROR) {
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free;
+ }
+ }
+ mailimf_string_write_mem(str, &col, "\r\n", 2);
+
+#if 0
+ r = file_to_mmapstr(f, result, result_len);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ fclose(f);
+ unlink(filename);
+#endif
+
+ r = mmap_string_ref(str);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ * result = str->str;
+ * result_len = str->len;
+
+ return MAIL_NO_ERROR;
+
+#if 0
+ close:
+ fclose(f);
+ unlink(filename);
+#endif
+ free:
+ mmap_string_free(str);
+ err:
+ return res;
+}
+
+
+
+static int fetch_section_body(mailmessage * msg_info,
+ struct mailmime * mime,
+ char ** result, size_t * result_len)
+{
+ int r;
+#if 0
+ FILE * f;
+#endif
+ int res;
+ int col;
+#if 0
+ char filename[PATH_MAX];
+#endif
+ MMAPString * str;
+
+ if (msg_info->msg_mime == NULL)
+ return MAIL_ERROR_INVAL;
+
+ str = mmap_string_new("");
+ if (str == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+#if 0
+ f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
+ if (f == NULL) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+#endif
+
+ col = 0;
+ if (mime->mm_mime_fields != NULL) {
+#if 0
+ r = mailmime_write(f, &col, mime);
+#endif
+ r = mailmime_write_mem(str, &col, mime);
+ if (r != MAILIMF_NO_ERROR) {
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free;
+ }
+ }
+
+ if (mime->mm_type == MAILMIME_MESSAGE)
+ r = body_body_to_mmapstr(str->str, str->len, result, result_len);
+ else
+ r = body_to_mmapstr(str->str, str->len, result, result_len);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ mmap_string_free(str);
+
+#if 0
+ fclose(f);
+ unlink(filename);
+#endif
+
+ return MAIL_NO_ERROR;
+
+#if 0
+ close:
+ fclose(f);
+ unlink(filename);
+#endif
+ free:
+ mmap_string_free(str);
+ err:
+ return res;
+}
+
+
+static int get_bodystructure(mailmessage * msg_info,
+ struct mailmime ** result)
+{
+ if (msg_info->msg_mime == NULL)
+ return MAIL_ERROR_INVAL;
+
+ * result = msg_info->msg_mime;
+
+ return MAIL_NO_ERROR;
+}
+
+
+static int fetch(mailmessage * msg_info,
+ char ** result, size_t * result_len)
+{
+ return fetch_section(msg_info, msg_info->msg_mime, result, result_len);
+}
+
+static int fetch_header(mailmessage * msg_info,
+ char ** result, size_t * result_len)
+{
+ return fetch_section_header(msg_info,
+ msg_info->msg_mime, result, result_len);
+}
+
+static int fetch_body(mailmessage * msg_info,
+ char ** result, size_t * result_len)
+{
+ return fetch_section_body(msg_info, msg_info->msg_mime, result, result_len);
+}
+
+
+static int fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ char * msg;
+ int r;
+
+ r = fetch(msg_info, &msg, result);
+ if (r != MAIL_NO_ERROR) {
+ return r;
+ }
+
+ fetch_result_free(msg_info, msg);
+
+ return MAIL_NO_ERROR;
+}
+
+
+static mailmessage_driver local_mime_message_driver = {
+ .msg_name = "mime",
+
+ .msg_initialize = initialize,
+ .msg_uninitialize = uninitialize,
+
+ .msg_flush = flush,
+ .msg_check = check,
+
+ .msg_fetch_result_free = fetch_result_free,
+
+ .msg_fetch = fetch,
+ .msg_fetch_header = fetch_header,
+ .msg_fetch_body = fetch_body,
+ .msg_fetch_size = fetch_size,
+ .msg_get_bodystructure = get_bodystructure,
+ .msg_fetch_section = fetch_section,
+ .msg_fetch_section_header = fetch_section_header,
+ .msg_fetch_section_mime = fetch_section_mime,
+ .msg_fetch_section_body = fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = NULL,
+};
+
+mailmessage_driver * mime_message_driver = &local_mime_message_driver;
diff --git a/libetpan/src/driver/implementation/mime-message/mime_message_driver.h b/libetpan/src/driver/implementation/mime-message/mime_message_driver.h
new file mode 100644
index 0000000..6cc3c5b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mime-message/mime_message_driver.h
@@ -0,0 +1,53 @@
+/*
+ * 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 MIME_MESSAGE_DRIVER_H
+
+#define MIME_MESSAGE_DRIVER_H
+
+#include <libetpan/mailmessage.h>
+
+#define LIBETPAN_MIME_MESSAGE
+
+extern mailmessage_driver * mime_message_driver;
+
+mailmessage * mime_message_init(struct mailmime * mime);
+
+void mime_message_detach_mime(mailmessage * msg);
+
+/* deprecated */
+int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir);
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver.c b/libetpan/src/driver/implementation/nntp/nntpdriver.c
new file mode 100644
index 0000000..15b764f
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver.c
@@ -0,0 +1,1180 @@
+/*
+ * 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 "nntpdriver.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "mail.h"
+#include "mailmessage.h"
+#include "nntpdriver_tools.h"
+#include "maildriver_tools.h"
+#include "nntpdriver_message.h"
+
+static int nntpdriver_initialize(mailsession * session);
+
+static void nntpdriver_uninitialize(mailsession * session);
+
+static int nntpdriver_parameters(mailsession * session,
+ int id, void * value);
+
+static int nntpdriver_connect_stream(mailsession * session, mailstream * s);
+
+static int nntpdriver_login(mailsession * session,
+ char * userid, char * password);
+
+static int nntpdriver_logout(mailsession * session);
+
+static int nntpdriver_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages,
+ uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int nntpdriver_messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int nntpdriver_append_message(mailsession * session,
+ char * message, size_t size);
+
+static int nntpdriver_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
+
+static int
+nntpdriver_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list);
+
+
+static int nntpdriver_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int nntpdriver_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int nntpdriver_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int nntpdriver_subscribe_folder(mailsession * session, char * mb);
+
+static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb);
+
+static int nntpdriver_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static int nntpdriver_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result);
+
+static int nntpdriver_noop(mailsession * session);
+
+static mailsession_driver local_nntp_session_driver = {
+ .sess_name = "nntp",
+
+ .sess_initialize = nntpdriver_initialize,
+ .sess_uninitialize = nntpdriver_uninitialize,
+
+ .sess_parameters = nntpdriver_parameters,
+
+ .sess_connect_stream = nntpdriver_connect_stream,
+ .sess_connect_path = NULL,
+ .sess_starttls = NULL,
+ .sess_login = nntpdriver_login,
+ .sess_logout = nntpdriver_logout,
+ .sess_noop = nntpdriver_noop,
+
+ .sess_build_folder_name = NULL,
+ .sess_create_folder = NULL,
+ .sess_delete_folder = NULL,
+ .sess_rename_folder = NULL,
+ .sess_check_folder = NULL,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = nntpdriver_select_folder,
+ .sess_expunge_folder = NULL,
+ .sess_status_folder = nntpdriver_status_folder,
+ .sess_messages_number = nntpdriver_messages_number,
+ .sess_recent_number = nntpdriver_messages_number,
+ .sess_unseen_number = nntpdriver_messages_number,
+ .sess_list_folders = nntpdriver_list_folders,
+ .sess_lsub_folders = nntpdriver_lsub_folders,
+ .sess_subscribe_folder = nntpdriver_subscribe_folder,
+ .sess_unsubscribe_folder = nntpdriver_unsubscribe_folder,
+
+ .sess_append_message = nntpdriver_append_message,
+ .sess_append_message_flags = nntpdriver_append_message_flags,
+ .sess_copy_message = NULL,
+ .sess_move_message = NULL,
+
+ .sess_get_messages_list = nntpdriver_get_messages_list,
+ .sess_get_envelopes_list = nntpdriver_get_envelopes_list,
+ .sess_remove_message = NULL,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = nntpdriver_get_message,
+ .sess_get_message_by_uid = nntpdriver_get_message_by_uid,
+};
+
+
+mailsession_driver * nntp_session_driver = &local_nntp_session_driver;
+
+static inline struct nntp_session_state_data *
+get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline newsnntp * get_nntp_session(mailsession * session)
+{
+ return get_data(session)->nntp_session;
+}
+
+static int nntpdriver_initialize(mailsession * session)
+{
+ struct nntp_session_state_data * data;
+ newsnntp * nntp;
+
+ nntp = newsnntp_new(0, NULL);
+ if (nntp == NULL)
+ goto err;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto free;
+
+ data->nntp_session = nntp;
+
+ data->nntp_userid = NULL;
+ data->nntp_password = NULL;
+
+ data->nntp_group_info = NULL;
+ data->nntp_group_name = NULL;
+
+ data->nntp_subscribed_list = clist_new();
+ if (data->nntp_subscribed_list == NULL)
+ goto free_data;
+
+ data->nntp_max_articles = 0;
+
+ data->nntp_mode_reader = FALSE;
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ free_data:
+ free(data);
+ free:
+ newsnntp_free(nntp);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void nntpdriver_uninitialize(mailsession * session)
+{
+ struct nntp_session_state_data * data;
+
+ data = get_data(session);
+
+ clist_foreach(data->nntp_subscribed_list, (clist_func) free, NULL);
+ clist_free(data->nntp_subscribed_list);
+
+ if (data->nntp_group_info != NULL)
+ newsnntp_group_free(data->nntp_group_info);
+
+ if (data->nntp_group_name != NULL)
+ free(data->nntp_group_name);
+
+ if (data->nntp_userid != NULL)
+ free(data->nntp_userid);
+
+ if (data->nntp_password != NULL)
+ free(data->nntp_password);
+
+ newsnntp_free(data->nntp_session);
+ free(data);
+
+ session->sess_data = NULL;
+}
+
+
+static int nntpdriver_parameters(mailsession * session,
+ int id, void * value)
+{
+ struct nntp_session_state_data * data;
+
+ data = get_data(session);
+
+ switch (id) {
+ case NNTPDRIVER_SET_MAX_ARTICLES:
+ {
+ uint32_t * param;
+
+ param = value;
+
+ data->nntp_max_articles = * param;
+ return MAIL_NO_ERROR;
+ }
+ }
+
+ return MAIL_ERROR_INVAL;
+}
+
+
+static int add_to_list(mailsession * session, char * mb)
+{
+ char * new_mb;
+ int r;
+ struct nntp_session_state_data * data;
+
+ data = get_data(session);
+
+ new_mb = strdup(mb);
+ if (new_mb == NULL)
+ return -1;
+
+ r = clist_append(data->nntp_subscribed_list, new_mb);
+ if (r < 0) {
+ free(mb);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int remove_from_list(mailsession * session, char * mb)
+{
+ clistiter * cur;
+ struct nntp_session_state_data * data;
+
+ data = get_data(session);
+
+ for(cur = clist_begin(data->nntp_subscribed_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ char * cur_name;
+
+ cur_name = clist_content(cur);
+ if (strcmp(cur_name, mb) == 0) {
+ clist_delete(data->nntp_subscribed_list, cur);
+ free(cur_name);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
+static int nntpdriver_connect_stream(mailsession * session, mailstream * s)
+{
+ int r;
+
+ r = newsnntp_connect(get_nntp_session(session), s);
+
+ switch (r) {
+ case NEWSNNTP_NO_ERROR:
+ return MAIL_NO_ERROR_NON_AUTHENTICATED;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+}
+
+static int nntpdriver_login(mailsession * session,
+ char * userid, char * password)
+{
+ struct nntp_session_state_data * data;
+ char * new_userid;
+ char * new_password;
+
+ data = get_data(session);
+
+ if (userid != NULL) {
+ new_userid = strdup(userid);
+ if (new_userid == NULL)
+ goto err;
+ }
+ else
+ new_userid = NULL;
+
+ if (password != NULL) {
+ new_password = strdup(password);
+ if (new_password == NULL)
+ goto free_uid;
+ }
+ else
+ new_password = NULL;
+
+ data->nntp_userid = new_userid;
+ data->nntp_password = new_password;
+
+ return MAIL_NO_ERROR;
+
+ free_uid:
+ if (new_userid != NULL)
+ free(new_userid);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static int nntpdriver_logout(mailsession * session)
+{
+ int r;
+
+ r = newsnntp_quit(get_nntp_session(session));
+
+ return nntpdriver_nntp_error_to_mail_error(r);
+}
+
+
+static int nntpdriver_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages,
+ uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ uint32_t count;
+ int r;
+
+ r = nntpdriver_select_folder(session, mb);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ r = nntpdriver_messages_number(session, mb, &count);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result_messages = count;
+ * result_recent = count;
+ * result_unseen = count;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_messages_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ int r;
+ struct nntp_session_state_data * data;
+
+ if (mb != NULL) {
+ r = nntpdriver_select_folder(session, mb);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ }
+
+ data = get_data(session);
+
+ if (data->nntp_group_info == NULL)
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+
+ * result = data->nntp_group_info->grp_last -
+ data->nntp_group_info->grp_first + 1;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ int r;
+ clist * group_list;
+ newsnntp * nntp;
+ clistiter * cur;
+ char * new_mb;
+ int done;
+ clist * list;
+ struct mail_list * ml;
+ int res;
+
+ nntp = get_nntp_session(session);
+
+ new_mb = NULL;
+ if ((mb != NULL) && (*mb != '\0')) {
+ new_mb = malloc(strlen(mb) + 3);
+ if (new_mb == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ strcpy(new_mb, mb);
+ strcat(new_mb, ".*");
+ }
+
+ done = FALSE;
+ do {
+ if (new_mb != NULL)
+ r = newsnntp_list_active(nntp, new_mb, &group_list);
+ else
+ r = newsnntp_list(nntp, &group_list);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ if (new_mb != NULL)
+ free(new_mb);
+ done = TRUE;
+ break;
+
+ default:
+ if (new_mb != NULL)
+ free(new_mb);
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (!done);
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(cur = clist_begin(group_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct newsnntp_group_info * info;
+ char * new_name;
+
+ info = clist_content(cur);
+ new_name = strdup(info->grp_name);
+ if (new_name == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, new_name);
+ if (r < 0) {
+ free(new_name);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ ml = mail_list_new(list);
+ if (ml == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ newsnntp_list_free(group_list);
+
+ * result = ml;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(list, (clist_func) free, NULL);
+ clist_free(list);
+ newsnntp_list_free(group_list);
+ err:
+ return res;
+}
+
+static int nntpdriver_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ clist * subscribed;
+ clist * lsub_result;
+ clistiter * cur;
+ struct mail_list * lsub;
+ size_t length;
+ int res;
+ int r;
+ struct nntp_session_state_data * data;
+
+ length = strlen(mb);
+
+ data = get_data(session);
+
+ subscribed = data->nntp_subscribed_list;
+ lsub_result = clist_new();
+ if (lsub_result == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(cur = clist_begin(subscribed) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ char * cur_mb;
+ char * new_mb;
+
+ cur_mb = clist_content(cur);
+
+ if (strncmp(mb, cur_mb, length) == 0) {
+ new_mb = strdup(cur_mb);
+ if (new_mb == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(lsub_result, new_mb);
+ if (r < 0) {
+ free(new_mb);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ lsub = mail_list_new(lsub_result);
+ if (lsub == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = lsub;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(lsub_result, (clist_func) free, NULL);
+ clist_free(lsub_result);
+ err:
+ return res;
+}
+
+static int nntpdriver_subscribe_folder(mailsession * session, char * mb)
+{
+ int r;
+
+ r = add_to_list(session, mb);
+ if (r < 0)
+ return MAIL_ERROR_SUBSCRIBE;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb)
+{
+ int r;
+
+ r = remove_from_list(session, mb);
+ if (r < 0)
+ return MAIL_ERROR_UNSUBSCRIBE;
+
+ return MAIL_NO_ERROR;
+}
+
+
+
+/* messages operations */
+
+static int nntpdriver_append_message(mailsession * session,
+ char * message, size_t size)
+{
+ int r;
+ struct nntp_session_state_data * data;
+
+ data = get_data(session);
+
+ do {
+ r = newsnntp_post(get_nntp_session(session), message, size);
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (1);
+}
+
+static int nntpdriver_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ return nntpdriver_append_message(session, message, size);
+}
+
+
+static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item,
+ struct mailimf_fields ** result);
+
+
+static int
+nntpdriver_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list)
+{
+ newsnntp * nntp;
+ int r;
+ struct nntp_session_state_data * data;
+ clist * list;
+ int done;
+ clistiter * cur;
+ uint32_t first_seq;
+ unsigned int i;
+
+ nntp = get_nntp_session(session);
+
+ data = get_data(session);
+
+ if (data->nntp_group_info == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ first_seq = data->nntp_group_info->grp_first;
+
+ if (carray_count(env_list->msg_tab) > 0) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, 0);
+
+ first_seq = msg->msg_index;
+ }
+
+ if (carray_count(env_list->msg_tab) > 0) {
+ i = carray_count(env_list->msg_tab) - 1;
+ while (1) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields != NULL) {
+ first_seq = msg->msg_index + 1;
+ break;
+ }
+
+ if (i == 0)
+ break;
+
+ i --;
+ }
+ }
+
+ if (first_seq > data->nntp_group_info->grp_last) {
+ list = NULL;
+ }
+ else {
+ done = FALSE;
+ do {
+ r = newsnntp_xover_range(nntp, first_seq,
+ data->nntp_group_info->grp_last, &list);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (!done);
+ }
+
+#if 0
+ i = 0;
+ j = 0;
+
+ if (list != NULL) {
+ for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
+ struct newsnntp_xover_resp_item * item;
+ struct mailimf_fields * fields;
+
+ item = clist_content(cur);
+
+ while (i < carray_count(env_list->msg_tab)) {
+ mailmessage * info;
+
+ info = carray_get(env_list->msg_tab, i);
+
+ if (item->ovr_article == info->msg_index) {
+
+ if (info->fields == NULL) {
+ r = xover_resp_to_fields(item, &fields);
+ if (r == MAIL_NO_ERROR) {
+ info->fields = fields;
+ }
+
+ info->size = item->ovr_size;
+
+ carray_set(env_list->msg_tab, j, info);
+ j ++;
+ i ++;
+ break;
+ }
+ else {
+ carray_set(env_list->msg_tab, j, info);
+ j ++;
+ }
+ }
+ else {
+ if (info->fields != NULL) {
+ carray_set(env_list->msg_tab, j, info);
+ j ++;
+ }
+ else {
+ if (info->flags != NULL) {
+ info->flags->flags &= ~MAIL_FLAG_NEW;
+ info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED;
+ mailmessage_check(info);
+ }
+ mailmessage_free(info);
+ carray_set(env_list->msg_tab, i, NULL);
+ }
+ }
+
+ i ++;
+ }
+ }
+ }
+
+ while (i < carray_count(env_list->msg_tab)) {
+ mailmessage * info;
+
+ info = carray_get(env_list->msg_tab, i);
+ if (info->fields != NULL) {
+ carray_set(env_list->msg_tab, j, info);
+ j ++;
+ }
+ else {
+ if (info->flags != NULL) {
+ info->flags->flags &= ~MAIL_FLAG_NEW;
+ info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED;
+ mailmessage_check(info);
+ }
+ mailmessage_free(info);
+ carray_set(env_list->msg_tab, i, NULL);
+ }
+
+ i ++;
+ }
+
+ r = carray_set_size(env_list->msg_tab, j);
+ if (r < 0) {
+ if (list != NULL)
+ newsnntp_xover_resp_list_free(list);
+ return MAIL_ERROR_MEMORY;
+ }
+#endif
+ i = 0;
+
+ if (list != NULL) {
+ for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
+ struct newsnntp_xover_resp_item * item;
+ struct mailimf_fields * fields;
+
+ item = clist_content(cur);
+
+ while (i < carray_count(env_list->msg_tab)) {
+ mailmessage * info;
+
+ info = carray_get(env_list->msg_tab, i);
+
+ if (item->ovr_article == info->msg_index) {
+
+ if (info->msg_fields == NULL) {
+ r = xover_resp_to_fields(item, &fields);
+ if (r == MAIL_NO_ERROR) {
+ info->msg_fields = fields;
+ }
+
+ info->msg_size = item->ovr_size;
+
+ i ++;
+ break;
+ }
+ }
+#if 0
+ else if ((info->fields == NULL) && (info->flags != NULL)) {
+ info->flags->flags &= ~MAIL_FLAG_NEW;
+ info->flags->flags |= MAIL_FLAG_CANCELLED;
+ mailmessage_check(info);
+ }
+#endif
+
+ i ++;
+ }
+ }
+ }
+
+#if 0
+ while (i < env_list->msg_tab->len) {
+ mailmessage * info;
+
+ info = carray_get(env_list->msg_tab, i);
+ if ((info->fields == NULL) && (info->flags != NULL)) {
+ info->flags->flags &= ~MAIL_FLAG_NEW;
+ info->flags->flags |= MAIL_FLAG_CANCELLED;
+ mailmessage_check(info);
+ }
+
+ i ++;
+ }
+#endif
+
+ if (list != NULL)
+ newsnntp_xover_resp_list_free(list);
+
+ return MAIL_NO_ERROR;
+}
+
+
+static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item,
+ struct mailimf_fields ** result)
+{
+ size_t cur_token;
+ clist * list;
+ int r;
+ struct mailimf_fields * fields;
+ int res;
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ if (item->ovr_subject != NULL) {
+ char * subject_str;
+ struct mailimf_subject * subject;
+ struct mailimf_field * field;
+
+ subject_str = strdup(item->ovr_subject);
+ if (subject_str == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ subject = mailimf_subject_new(subject_str);
+ if (subject == NULL) {
+ free(subject_str);
+ 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, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_subject_free(subject);
+ 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 (item->ovr_author != NULL) {
+ struct mailimf_mailbox_list * mb_list;
+ struct mailimf_from * from;
+ struct mailimf_field * field;
+
+ cur_token = 0;
+ r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author),
+ &cur_token, &mb_list);
+ switch (r) {
+ case MAILIMF_NO_ERROR:
+ 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;
+ }
+ break;
+
+ case MAILIMF_ERROR_PARSE:
+ break;
+
+ default:
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free_list;
+ }
+ }
+
+ if (item->ovr_date != NULL) {
+ struct mailimf_date_time * date_time;
+ struct mailimf_orig_date * orig_date;
+ struct mailimf_field * field;
+
+ cur_token = 0;
+ r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date),
+ &cur_token, &date_time);
+ switch (r) {
+ case MAILIMF_NO_ERROR:
+ orig_date = mailimf_orig_date_new(date_time);
+ if (orig_date == 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_date, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_orig_date_free(orig_date);
+ 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 (item->ovr_message_id != NULL) {
+ char * msgid_str;
+ struct mailimf_message_id * msgid;
+ struct mailimf_field * field;
+
+ cur_token = 0;
+ r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id),
+ &cur_token, &msgid_str);
+
+ switch (r) {
+ case MAILIMF_NO_ERROR:
+ msgid = mailimf_message_id_new(msgid_str);
+ if (msgid == NULL) {
+ mailimf_msg_id_free(msgid_str);
+ 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, msgid, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+
+ 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 (item->ovr_references != NULL) {
+ clist * msgid_list;
+ struct mailimf_references * references;
+ struct mailimf_field * field;
+
+ cur_token = 0;
+
+ r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references),
+ &cur_token, &msgid_list);
+
+ switch (r) {
+ case MAILIMF_NO_ERROR:
+ references = mailimf_references_new(msgid_list);
+ if (references == NULL) {
+ clist_foreach(msgid_list,
+ (clist_func) mailimf_msg_id_free, NULL);
+ clist_free(msgid_list);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ 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);
+
+ r = clist_append(list, field);
+ if (r < 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ 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;
+}
+
+
+/* get messages list with group info */
+
+static int nntpdriver_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ return nntp_get_messages_list(session, session, nntp_message_driver, result);
+
+}
+
+static int nntpdriver_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, nntp_message_driver, num, 0);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg_info);
+ return r;
+ }
+
+ * result = msg_info;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_noop(mailsession * session)
+{
+ newsnntp * nntp;
+ int r;
+ struct tm tm;
+
+ nntp = get_nntp_session(session);
+
+ r = newsnntp_date(nntp, &tm);
+
+ return nntpdriver_nntp_error_to_mail_error(r);
+}
+
+static int nntpdriver_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result)
+{
+ uint32_t num;
+ char * p;
+
+ if (uid == NULL)
+ return MAIL_ERROR_INVAL;
+
+ num = strtoul(uid, &p, 10);
+ if ((p == uid) || (* p != '\0'))
+ return MAIL_ERROR_INVAL;
+
+ return nntpdriver_get_message(session, num, result);
+ }
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver.h b/libetpan/src/driver/implementation/nntp/nntpdriver.h
new file mode 100644
index 0000000..56aaa39
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver.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 NNTPDRIVER_H
+
+#define NNTPDRIVER_H
+
+#include <libetpan/nntpdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * nntp_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c
new file mode 100644
index 0000000..5c29b7b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c
@@ -0,0 +1,1059 @@
+/*
+ * 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 "nntpdriver_cached.h"
+
+#include "libetpan-config.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "mail_cache_db.h"
+
+#include "mail.h"
+#include "mailmessage.h"
+#include "maildriver_tools.h"
+#include "nntpdriver.h"
+#include "maildriver.h"
+#include "newsnntp.h"
+#include "generic_cache.h"
+#include "imfcache.h"
+#include "maillock.h"
+#include "nntpdriver_cached_message.h"
+#include "nntpdriver_tools.h"
+
+static int nntpdriver_cached_initialize(mailsession * session);
+
+static void nntpdriver_cached_uninitialize(mailsession * session);
+
+static int nntpdriver_cached_parameters(mailsession * session,
+ int id, void * value);
+
+static int nntpdriver_cached_connect_stream(mailsession * session,
+ mailstream * s);
+
+static int nntpdriver_cached_login(mailsession * session,
+ char * userid, char * password);
+
+static int nntpdriver_cached_logout(mailsession * session);
+
+static int nntpdriver_cached_check_folder(mailsession * session);
+
+static int nntpdriver_cached_select_folder(mailsession * session, char * mb);
+
+static int nntpdriver_cached_status_folder(mailsession * session,
+ char * mb,
+ uint32_t * result_messages,
+ uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int nntpdriver_cached_messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int nntpdriver_cached_recent_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int nntpdriver_cached_unseen_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int nntpdriver_cached_append_message(mailsession * session,
+ char * message, size_t size);
+
+static int nntpdriver_cached_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
+
+static int
+nntpdriver_cached_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list);
+
+
+static int
+nntpdriver_cached_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int nntpdriver_cached_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int nntpdriver_cached_subscribe_folder(mailsession * session,
+ char * mb);
+
+static int nntpdriver_cached_unsubscribe_folder(mailsession * session,
+ char * mb);
+
+static int nntpdriver_cached_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static int nntpdriver_cached_noop(mailsession * session);
+
+static int nntpdriver_cached_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result);
+
+static mailsession_driver local_nntp_cached_session_driver = {
+ .sess_name = "nntp-cached",
+
+ .sess_initialize = nntpdriver_cached_initialize,
+ .sess_uninitialize = nntpdriver_cached_uninitialize,
+
+ .sess_parameters = nntpdriver_cached_parameters,
+
+ .sess_connect_stream = nntpdriver_cached_connect_stream,
+ .sess_connect_path = NULL,
+ .sess_starttls = NULL,
+ .sess_login = nntpdriver_cached_login,
+ .sess_logout = nntpdriver_cached_logout,
+ .sess_noop = nntpdriver_cached_noop,
+
+ .sess_build_folder_name = NULL,
+ .sess_create_folder = NULL,
+ .sess_delete_folder = NULL,
+ .sess_rename_folder = NULL,
+ .sess_check_folder = nntpdriver_cached_check_folder,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = nntpdriver_cached_select_folder,
+ .sess_expunge_folder = NULL,
+ .sess_status_folder = nntpdriver_cached_status_folder,
+ .sess_messages_number = nntpdriver_cached_messages_number,
+ .sess_recent_number = nntpdriver_cached_recent_number,
+ .sess_unseen_number = nntpdriver_cached_unseen_number,
+ .sess_list_folders = nntpdriver_cached_list_folders,
+ .sess_lsub_folders = nntpdriver_cached_lsub_folders,
+ .sess_subscribe_folder = nntpdriver_cached_subscribe_folder,
+ .sess_unsubscribe_folder = nntpdriver_cached_unsubscribe_folder,
+
+ .sess_append_message = nntpdriver_cached_append_message,
+ .sess_append_message_flags = nntpdriver_cached_append_message_flags,
+ .sess_copy_message = NULL,
+ .sess_move_message = NULL,
+
+ .sess_get_messages_list = nntpdriver_cached_get_messages_list,
+ .sess_get_envelopes_list = nntpdriver_cached_get_envelopes_list,
+ .sess_remove_message = NULL,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = nntpdriver_cached_get_message,
+ .sess_get_message_by_uid = nntpdriver_cached_get_message_by_uid,
+};
+
+
+mailsession_driver * nntp_cached_session_driver =
+&local_nntp_cached_session_driver;
+
+#define ENV_NAME "env.db"
+#define FLAGS_NAME "flags.db"
+
+
+
+static void read_article_seq(mailsession * session,
+ uint32_t * pfirst, uint32_t * plast);
+
+static void write_article_seq(mailsession * session,
+ uint32_t first, uint32_t last);
+
+
+static inline struct nntp_cached_session_state_data *
+get_cached_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline mailsession * get_ancestor(mailsession * session)
+{
+ return get_cached_data(session)->nntp_ancestor;
+}
+
+static inline struct nntp_session_state_data *
+get_ancestor_data(mailsession * session)
+{
+ return get_ancestor(session)->sess_data;
+}
+
+static inline newsnntp * get_nntp_session(mailsession * session)
+{
+ return get_ancestor_data(session)->nntp_session;
+}
+
+static int nntpdriver_cached_initialize(mailsession * session)
+{
+ struct nntp_cached_session_state_data * data;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto err;
+
+ data->nntp_flags_store = mail_flags_store_new();
+ if (data->nntp_flags_store == NULL)
+ goto free;
+
+ data->nntp_ancestor = mailsession_new(nntp_session_driver);
+ if (data->nntp_ancestor == NULL)
+ goto free_store;
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ free_store:
+ mail_flags_store_free(data->nntp_flags_store);
+ free:
+ free(data);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static int nntp_flags_store_process(char * flags_directory, char * group_name,
+ struct mail_flags_store * flags_store)
+{
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ unsigned int i;
+ int r;
+ int res;
+
+ if (carray_count(flags_store->fls_tab) == 0)
+ return MAIL_NO_ERROR;
+
+ if (group_name == NULL)
+ return MAIL_NO_ERROR;
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ flags_directory, group_name, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(flags_store->fls_tab, i);
+
+ r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_index, msg->msg_flags);
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ mail_flags_store_clear(flags_store);
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static void nntpdriver_cached_uninitialize(mailsession * session)
+{
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ nntp_flags_store_process(cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name,
+ cached_data->nntp_flags_store);
+
+ mail_flags_store_free(cached_data->nntp_flags_store);
+
+ mailsession_free(cached_data->nntp_ancestor);
+ free(cached_data);
+
+ session->sess_data = NULL;
+}
+
+static int nntpdriver_cached_parameters(mailsession * session,
+ int id, void * value)
+{
+ struct nntp_cached_session_state_data * cached_data;
+ int r;
+
+ cached_data = get_cached_data(session);
+
+ switch (id) {
+ case NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY:
+ strncpy(cached_data->nntp_cache_directory, value, PATH_MAX);
+ cached_data->nntp_cache_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(cached_data->nntp_cache_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+
+ case NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY:
+ strncpy(cached_data->nntp_flags_directory, value, PATH_MAX);
+ cached_data->nntp_flags_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(cached_data->nntp_flags_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+
+ default:
+ return mailsession_parameters(get_ancestor(session), id, value);
+ }
+}
+
+static int nntpdriver_cached_connect_stream(mailsession * session,
+ mailstream * s)
+{
+ return mailsession_connect_stream(get_ancestor(session), s);
+}
+
+static int nntpdriver_cached_login(mailsession * session,
+ char * userid, char * password)
+{
+ return mailsession_login(get_ancestor(session), userid, password);
+}
+
+static int nntpdriver_cached_logout(mailsession * session)
+{
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ nntp_flags_store_process(cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name,
+ cached_data->nntp_flags_store);
+
+ return mailsession_logout(get_ancestor(session));
+}
+
+static int nntpdriver_cached_select_folder(mailsession * session, char * mb)
+{
+ int r;
+ struct nntp_session_state_data * ancestor_data;
+ struct nntp_cached_session_state_data * cached_data;
+ int res;
+ char key[PATH_MAX];
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ nntp_flags_store_process(cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name,
+ cached_data->nntp_flags_store);
+
+ r = mailsession_select_folder(get_ancestor(session), mb);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ if (ancestor_data->nntp_group_name == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name);
+
+ r = generic_cache_create_dir(key);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name);
+
+ r = generic_cache_create_dir(key);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int nntpdriver_cached_check_folder(mailsession * session)
+{
+ struct nntp_session_state_data * ancestor_data;
+ struct nntp_cached_session_state_data * cached_data;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ nntp_flags_store_process(cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name,
+ cached_data->nntp_flags_store);
+
+ return MAIL_NO_ERROR;
+}
+
+
+static int nntpdriver_cached_status_folder(mailsession * session,
+ char * mb, uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ int res;
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ uint32_t i;
+ int r;
+ uint32_t recent;
+ uint32_t unseen;
+ uint32_t first;
+ uint32_t last;
+ uint32_t count;
+ uint32_t additionnal;
+
+ r = nntpdriver_cached_select_folder(session, mb);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ read_article_seq(session, &first, &last);
+
+ count = 0;
+ recent = 0;
+ unseen = 0;
+
+ ancestor_data = get_ancestor_data(session);
+ cached_data = get_cached_data(session);
+ if (ancestor_data->nntp_group_name == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ if (ancestor_data->nntp_group_info->grp_first > first)
+ first = ancestor_data->nntp_group_info->grp_first;
+ if (last < first)
+ last = ancestor_data->nntp_group_info->grp_last;
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = first ; i <= last ; i++) {
+ struct mail_flags * flags;
+
+ r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
+ i, &flags);
+ if (r == MAIL_NO_ERROR) {
+ if ((flags->fl_flags & MAIL_FLAG_CANCELLED) != 0) {
+ mail_flags_free(flags);
+ continue;
+ }
+
+ count ++;
+ if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
+ recent ++;
+ }
+ if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
+ unseen ++;
+ }
+ mail_flags_free(flags);
+ }
+ }
+
+ if ((count == 0) && (first != last)) {
+ count = last - first + 1;
+ recent = count;
+ unseen = count;
+ }
+
+ additionnal = ancestor_data->nntp_group_info->grp_last - last;
+ recent += additionnal;
+ unseen += additionnal;
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ * result_messages = count;
+ * result_recent = recent;
+ * result_unseen = unseen;
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static int nntpdriver_cached_messages_number(mailsession * session,
+ char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = nntpdriver_cached_status_folder(session, mb,
+ &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = messages;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_cached_recent_number(mailsession * session,
+ char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = nntpdriver_cached_status_folder(session, mb,
+ &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = recent;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_cached_unseen_number(mailsession * session,
+ char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = nntpdriver_cached_status_folder(session, mb,
+ &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = unseen;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_cached_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ return mailsession_list_folders(get_ancestor(session), mb, result);
+}
+
+static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ return mailsession_lsub_folders(get_ancestor(session), mb, result);
+}
+
+static int nntpdriver_cached_subscribe_folder(mailsession * session,
+ char * mb)
+{
+ return mailsession_subscribe_folder(get_ancestor(session), mb);
+}
+
+static int nntpdriver_cached_unsubscribe_folder(mailsession * session,
+ char * mb)
+{
+ return mailsession_unsubscribe_folder(get_ancestor(session), mb);
+}
+
+
+
+/* messages operations */
+
+static int nntpdriver_cached_append_message(mailsession * session,
+ char * message, size_t size)
+{
+ return mailsession_append_message(get_ancestor(session), message, size);
+}
+
+static int nntpdriver_cached_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ return nntpdriver_cached_append_message(session, message, size);
+}
+
+
+
+static int
+get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
+ mailsession * session, uint32_t num,
+ struct mailimf_fields ** result)
+{
+ char keyname[PATH_MAX];
+ int r;
+ struct mailimf_fields * fields;
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%i-envelope", num);
+
+ r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = fields;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
+ mailsession * session, uint32_t num,
+ struct mailimf_fields * fields)
+{
+ int r;
+ int res;
+ char keyname[PATH_MAX];
+
+ snprintf(keyname, PATH_MAX, "%i-envelope", num);
+
+ r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+#define SEQ_FILENAME "articles-seq"
+
+static void read_article_seq(mailsession * session,
+ uint32_t * pfirst, uint32_t * plast)
+{
+ FILE * f;
+ struct nntp_session_state_data * ancestor_data;
+ uint32_t first;
+ uint32_t last;
+ char seq_filename[PATH_MAX];
+ struct nntp_cached_session_state_data * cached_data;
+ int r;
+
+ first = 0;
+ last = 0;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ if (ancestor_data->nntp_group_name == NULL)
+ return;
+
+ snprintf(seq_filename, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name, SEQ_FILENAME);
+ f = fopen(seq_filename, "r");
+
+ if (f != NULL) {
+ int fd;
+
+ fd = fileno(f);
+
+ r = maillock_read_lock(seq_filename, fd);
+ if (r == 0) {
+ MMAPString * mmapstr;
+ size_t cur_token;
+ char buf[sizeof(uint32_t) * 2];
+ size_t read_size;
+
+ read_size = fread(buf, 1, sizeof(uint32_t) * 2, f);
+ mmapstr = mmap_string_new_len(buf, read_size);
+ if (mmapstr != NULL) {
+ cur_token = 0;
+ r = mailimf_cache_int_read(mmapstr, &cur_token, &first);
+ r = mailimf_cache_int_read(mmapstr, &cur_token, &last);
+
+ mmap_string_free(mmapstr);
+ }
+
+ maillock_read_unlock(seq_filename, fd);
+ }
+ fclose(f);
+ }
+
+ * pfirst = first;
+ * plast = last;
+}
+
+static void write_article_seq(mailsession * session,
+ uint32_t first, uint32_t last)
+{
+ FILE * f;
+ struct nntp_session_state_data * ancestor_data;
+ char seq_filename[PATH_MAX];
+ struct nntp_cached_session_state_data * cached_data;
+ int r;
+ int fd;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ if (ancestor_data->nntp_group_name == NULL)
+ return;
+
+ snprintf(seq_filename, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name, SEQ_FILENAME);
+
+ fd = creat(seq_filename, S_IRUSR | S_IWUSR);
+ if (fd < 0)
+ return;
+
+ f = fdopen(fd, "w");
+ if (f != NULL) {
+ r = maillock_write_lock(seq_filename, fd);
+ if (r == 0) {
+ MMAPString * mmapstr;
+ size_t cur_token;
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr != NULL) {
+ r = mail_serialize_clear(mmapstr, &cur_token);
+ if (r == MAIL_NO_ERROR) {
+ r = mailimf_cache_int_write(mmapstr, &cur_token, first);
+ r = mailimf_cache_int_write(mmapstr, &cur_token, last);
+
+ fwrite(mmapstr->str, 1, mmapstr->len, f);
+ }
+
+ mmap_string_free(mmapstr);
+ }
+
+ maillock_write_unlock(seq_filename, fd);
+ }
+ fclose(f);
+ }
+ else
+ close(fd);
+}
+
+
+static void get_uid_from_filename(char * filename)
+{
+ char * p;
+
+ if (strcmp(filename, SEQ_FILENAME) == 0)
+ * filename = 0;
+
+ p = strstr(filename, "-header");
+ if (p != NULL)
+ * p = 0;
+}
+
+static int
+nntpdriver_cached_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list)
+{
+ int r;
+ unsigned int i;
+ struct nntp_cached_session_state_data * cached_data;
+ uint32_t first;
+ uint32_t last;
+ struct nntp_session_state_data * ancestor_data;
+ char filename_env[PATH_MAX];
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_env;
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ int res;
+ char cache_dir[PATH_MAX];
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ nntp_flags_store_process(cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name,
+ cached_data->nntp_flags_store);
+
+ if (ancestor_data->nntp_group_name == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ /* read articles sequence */
+
+ read_article_seq(session, &first, &last);
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(filename_env, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name, ENV_NAME);
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name, FLAGS_NAME);
+
+ /* 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_index < first) || (msg->msg_index > last))
+ continue;
+
+ if (msg->msg_fields == NULL) {
+ r = get_cached_envelope(cache_db_env, mmapstr,
+ session, msg->msg_index, &fields);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_fields = fields;
+ msg->msg_cached = TRUE;
+ }
+ }
+ }
+
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+
+ r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ /* add flags */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_flags == NULL) {
+ struct mail_flags * flags;
+
+ r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_index, &flags);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_flags = flags;
+ }
+ else {
+ msg->msg_flags = mail_flags_new_empty();
+ if (msg->msg_fields == NULL) {
+ msg->msg_flags->fl_flags |= MAIL_FLAG_CANCELLED;
+ mailmessage_check(msg);
+ }
+ }
+ }
+ }
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_env;
+ }
+
+ /* must write cache */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields != NULL) {
+ if (!msg->msg_cached) {
+ r = write_cached_envelope(cache_db_env, mmapstr,
+ session, msg->msg_index, msg->msg_fields);
+ }
+ }
+
+ if (msg->msg_flags != NULL) {
+ r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_index, msg->msg_flags);
+ }
+ }
+
+ first = 0;
+ last = 0;
+ if (carray_count(env_list->msg_tab) > 0) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, 0);
+ first = msg->msg_index;
+
+ msg = carray_get(env_list->msg_tab, carray_count(env_list->msg_tab) - 1);
+ last = msg->msg_index;
+ }
+
+ /* write articles sequence */
+
+ write_article_seq(session, first, last);
+
+ /* flush cache */
+
+ maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
+
+ /* remove cache files */
+
+ snprintf(cache_dir, PATH_MAX, "%s/%s",
+ cached_data->nntp_cache_directory, ancestor_data->nntp_group_name);
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+ mmap_string_free(mmapstr);
+
+ maildriver_message_cache_clean_up(cache_dir, env_list,
+ get_uid_from_filename);
+
+ return MAIL_NO_ERROR;
+
+ close_db_env:
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ err:
+ return res;
+}
+
+static int
+nntpdriver_cached_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ return nntp_get_messages_list(get_ancestor(session), session,
+ nntp_cached_message_driver, result);
+}
+
+static int nntpdriver_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, nntp_cached_message_driver, num, 0);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg_info);
+ return r;
+ }
+
+ * result = msg_info;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_cached_noop(mailsession * session)
+{
+ return mailsession_noop(get_ancestor(session));
+}
+
+static int nntpdriver_cached_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result)
+{
+ uint32_t num;
+ char * p;
+
+ if (uid == NULL)
+ return MAIL_ERROR_INVAL;
+
+ num = strtoul(uid, &p, 10);
+ if ((p == uid) || (* p != '\0'))
+ return MAIL_ERROR_INVAL;
+
+ return nntpdriver_cached_get_message(session, num, result);
+}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h
new file mode 100644
index 0000000..c0264de
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_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 NNTPDRIVER_CACHED_H
+
+#define NNTPDRIVER_CACHED_H
+
+#include <libetpan/nntpdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * nntp_cached_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c
new file mode 100644
index 0000000..131b689
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c
@@ -0,0 +1,365 @@
+/*
+ * 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 "nntpdriver_cached_message.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "mail_cache_db.h"
+
+#include "mailmessage.h"
+#include "mailmessage_tools.h"
+#include "nntpdriver.h"
+#include "nntpdriver_tools.h"
+#include "nntpdriver_cached.h"
+#include "nntpdriver_message.h"
+#include "generic_cache.h"
+
+static int nntp_prefetch(mailmessage * msg_info);
+
+static void nntp_prefetch_free(struct generic_message_t * msg);
+
+static int nntp_initialize(mailmessage * msg_info);
+
+static int nntp_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static int nntp_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static void nntp_uninitialize(mailmessage * msg_info);
+
+static void nntp_flush(mailmessage * msg_info);
+
+static void nntp_check(mailmessage * msg_info);
+
+static int nntp_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result);
+
+static mailmessage_driver local_nntp_cached_message_driver = {
+ .msg_name = "nntp-cached",
+
+ .msg_initialize = nntp_initialize,
+ .msg_uninitialize = nntp_uninitialize,
+
+ .msg_flush = nntp_flush,
+ .msg_check = nntp_check,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = nntp_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_body,
+ .msg_fetch_size = nntp_fetch_size,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = nntp_get_flags,
+};
+
+mailmessage_driver * nntp_cached_message_driver =
+&local_nntp_cached_message_driver;
+
+static inline struct nntp_cached_session_state_data *
+get_cached_session_data(mailmessage * msg)
+{
+ return msg->msg_session->sess_data;
+}
+
+static inline mailsession * get_ancestor_session(mailmessage * msg)
+{
+ return get_cached_session_data(msg)->nntp_ancestor;
+}
+
+static inline struct nntp_session_state_data *
+get_ancestor_session_data(mailmessage * msg)
+{
+ return get_ancestor_session(msg)->sess_data;
+}
+
+static inline newsnntp *
+get_nntp_session(mailmessage * msg)
+{
+ return get_ancestor_session_data(msg)->nntp_session;
+}
+
+static int nntp_prefetch(mailmessage * msg_info)
+{
+ char * msg_content;
+ size_t msg_length;
+ struct generic_message_t * msg;
+ int r;
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+ char filename[PATH_MAX];
+
+ /* we try the cached message */
+
+ cached_data = get_cached_session_data(msg_info);
+
+ ancestor_data = get_ancestor_session_data(msg_info);
+
+ snprintf(filename, PATH_MAX, "%s/%s/%i", cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name, msg_info->msg_index);
+
+ r = generic_cache_read(filename, &msg_content, &msg_length);
+ if (r == MAIL_NO_ERROR) {
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+ }
+
+ /* we get the message through the network */
+
+ r = nntpdriver_article(get_ancestor_session(msg_info),
+ msg_info->msg_index, &msg_content,
+ &msg_length);
+
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ /* we write the message cache */
+
+ generic_cache_store(filename, msg_content, msg_length);
+
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static void nntp_prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ mmap_string_unref(msg->msg_message);
+ msg->msg_message = NULL;
+ }
+}
+
+static int nntp_initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * uid;
+ char static_uid[20];
+
+ snprintf(static_uid, 20, "%u", msg_info->msg_index);
+ uid = strdup(static_uid);
+ if (uid == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR) {
+ free(uid);
+ return r;
+ }
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = nntp_prefetch;
+ msg->msg_prefetch_free = nntp_prefetch_free;
+ msg_info->msg_uid = uid;
+
+ return MAIL_NO_ERROR;
+}
+
+
+static void nntp_uninitialize(mailmessage * msg_info)
+{
+ mailmessage_generic_uninitialize(msg_info);
+}
+
+#define FLAGS_NAME "flags.db"
+
+static void nntp_flush(mailmessage * msg_info)
+{
+ mailmessage_generic_flush(msg_info);
+}
+
+
+static void nntp_check(mailmessage * msg_info)
+{
+ int r;
+
+ if (msg_info->msg_flags != NULL) {
+ r = mail_flags_store_set(get_cached_session_data(msg_info)->nntp_flags_store,
+ msg_info);
+ /* ignore errors */
+ }
+}
+
+static int nntp_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ struct generic_message_t * msg;
+ char * headers;
+ size_t headers_length;
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+ int r;
+ char filename[PATH_MAX];
+
+ msg = msg_info->msg_data;
+
+ if (msg->msg_message != NULL)
+ return mailmessage_generic_fetch_header(msg_info,
+ result, result_len);
+
+ /* we try the cached message */
+
+ cached_data = get_cached_session_data(msg_info);
+
+ ancestor_data = get_ancestor_session_data(msg_info);
+
+ snprintf(filename, PATH_MAX, "%s/%s/%i-header",
+ cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name, msg_info->msg_index);
+
+ r = generic_cache_read(filename, &headers, &headers_length);
+ if (r == MAIL_NO_ERROR) {
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+ }
+
+ /* we get the message through the network */
+
+ r = nntpdriver_head(get_ancestor_session(msg_info), msg_info->msg_index,
+ &headers, &headers_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ /* we write the message cache */
+
+ generic_cache_store(filename, headers, headers_length);
+
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntp_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ return nntpdriver_size(get_ancestor_session(msg_info),
+ msg_info->msg_index, result);
+}
+
+static int nntp_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result)
+{
+ int r;
+ struct mail_flags * flags;
+ struct mail_cache_db * cache_db_flags;
+ char filename_flags[PATH_MAX];
+ int res;
+ MMAPString * mmapstr;
+
+ if (msg_info->msg_flags != NULL) {
+ * result = msg_info->msg_flags;
+
+ return MAIL_NO_ERROR;
+ }
+
+ flags = mail_flags_store_get(get_cached_session_data(msg_info)->nntp_flags_store, msg_info->msg_index);
+
+ if (flags == NULL) {
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+
+ cached_data = get_cached_session_data(msg_info);
+
+ ancestor_data = get_ancestor_session_data(msg_info);
+ if (ancestor_data->nntp_group_name == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
+ msg_info->msg_index, &flags);
+ if (r != MAIL_NO_ERROR) {
+ flags = mail_flags_new_empty();
+ if (flags == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ }
+
+ msg_info->msg_flags = flags;
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h
new file mode 100644
index 0000000..f515d48
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_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$
+ */
+
+#include <libetpan/mailmessage_types.h>
+
+#ifndef NNTPDRIVER_CACHED_MESSAGE_H
+
+#define NNTPDRIVER_CACHED_MESSAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * nntp_cached_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_message.c b/libetpan/src/driver/implementation/nntp/nntpdriver_message.c
new file mode 100644
index 0000000..117bc56
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_message.c
@@ -0,0 +1,169 @@
+/*
+ * 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 "nntpdriver_message.h"
+
+#include "mailmessage_tools.h"
+#include "nntpdriver_tools.h"
+#include "nntpdriver.h"
+#include "newsnntp.h"
+#include <string.h>
+#include <stdlib.h>
+
+static int nntp_prefetch(mailmessage * msg_info);
+
+static void nntp_prefetch_free(struct generic_message_t * msg);
+
+static int nntp_initialize(mailmessage * msg_info);
+
+static int nntp_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static int nntp_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static mailmessage_driver local_nntp_message_driver = {
+ .msg_name = "nntp",
+
+ .msg_initialize = nntp_initialize,
+ .msg_uninitialize = mailmessage_generic_uninitialize,
+
+ .msg_flush = mailmessage_generic_flush,
+ .msg_check = NULL,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = nntp_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_body,
+ .msg_fetch_size = nntp_fetch_size,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = NULL,
+};
+
+mailmessage_driver * nntp_message_driver = &local_nntp_message_driver;
+
+static int nntp_prefetch(mailmessage * msg_info)
+{
+ char * msg_content;
+ size_t msg_length;
+ struct generic_message_t * msg;
+ int r;
+
+ r = nntpdriver_article(msg_info->msg_session, msg_info->msg_index,
+ &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static void nntp_prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ mmap_string_unref(msg->msg_message);
+ msg->msg_message = NULL;
+ }
+}
+
+static int nntp_initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * uid;
+ char static_uid[20];
+
+ snprintf(static_uid, 20, "%u", msg_info->msg_index);
+ uid = strdup(static_uid);
+ if (uid == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR) {
+ free(uid);
+ return r;
+ }
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = nntp_prefetch;
+ msg->msg_prefetch_free = nntp_prefetch_free;
+ msg_info->msg_uid = uid;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntp_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ struct generic_message_t * msg;
+ char * headers;
+ size_t headers_length;
+ int r;
+
+ msg = msg_info->msg_data;
+
+ if (msg->msg_message != NULL)
+ return mailmessage_generic_fetch_header(msg_info,
+ result, result_len);
+
+ r = nntpdriver_head(msg_info->msg_session, msg_info->msg_index,
+ &headers, &headers_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntp_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ return nntpdriver_size(msg_info->msg_session, msg_info->msg_index, result);
+}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_message.h b/libetpan/src/driver/implementation/nntp/nntpdriver_message.h
new file mode 100644
index 0000000..15e80b7
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_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 NNTPDRIVER_MESSAGE_H
+
+#define NNTPDRIVER_MESSAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libetpan/nntpdriver_types.h>
+
+extern mailmessage_driver * nntp_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c
new file mode 100644
index 0000000..eef0953
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c
@@ -0,0 +1,563 @@
+/*
+ * 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 "nntpdriver_tools.h"
+
+#include "mail.h"
+#include "nntpdriver.h"
+#include "nntpdriver_cached.h"
+#include "newsnntp.h"
+#include "maildriver_types.h"
+#include "generic_cache.h"
+#include "imfcache.h"
+#include "mailmessage.h"
+#include "mail_cache_db.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+int nntpdriver_nntp_error_to_mail_error(int error)
+{
+ switch (error) {
+ case NEWSNNTP_NO_ERROR:
+ return MAIL_NO_ERROR;
+
+ case NEWSNNTP_ERROR_STREAM:
+ return MAIL_ERROR_STREAM;
+
+ case NEWSNNTP_ERROR_UNEXPECTED:
+ return MAIL_ERROR_PROGRAM_ERROR;
+
+ case NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED:
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+
+ case NEWSNNTP_ERROR_NO_ARTICLE_SELECTED:
+ case NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER:
+ case NEWSNNTP_ERROR_ARTICLE_NOT_FOUND:
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ case NEWSNNTP_ERROR_UNEXPECTED_RESPONSE:
+ case NEWSNNTP_ERROR_INVALID_RESPONSE:
+ return MAIL_ERROR_PARSE;
+
+ case NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP:
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+
+ case NEWSNNTP_ERROR_POSTING_NOT_ALLOWED:
+ return MAIL_ERROR_READONLY;
+
+ case NEWSNNTP_ERROR_POSTING_FAILED:
+ return MAIL_ERROR_APPEND;
+
+ case NEWSNNTP_ERROR_PROGRAM_ERROR:
+ return MAIL_ERROR_PROGRAM_ERROR;
+
+ case NEWSNNTP_ERROR_NO_PERMISSION:
+ return MAIL_ERROR_NO_PERMISSION;
+
+ case NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD:
+ case NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED:
+ return MAIL_ERROR_COMMAND_NOT_SUPPORTED;
+
+ case NEWSNNTP_ERROR_CONNECTION_REFUSED:
+ return MAIL_ERROR_CONNECT;
+
+ case NEWSNNTP_ERROR_MEMORY:
+ return MAIL_ERROR_MEMORY;
+
+ case NEWSNNTP_ERROR_AUTHENTICATION_REJECTED:
+ return MAIL_ERROR_LOGIN;
+
+ case NEWSNNTP_ERROR_BAD_STATE:
+ return MAIL_ERROR_BAD_STATE;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ default:
+ return MAIL_ERROR_INVAL;
+ }
+}
+
+static inline struct nntp_session_state_data *
+session_get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline newsnntp * session_get_nntp_session(mailsession * session)
+{
+ return session_get_data(session)->nntp_session;
+}
+
+static inline struct nntp_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)->nntp_ancestor;
+}
+
+static inline struct nntp_session_state_data *
+cached_session_get_ancestor_data(mailsession * session)
+{
+ return session_get_data(cached_session_get_ancestor(session));
+}
+
+static inline newsnntp * cached_session_get_nntp_session(mailsession * session)
+{
+ return session_get_nntp_session(cached_session_get_ancestor(session));
+}
+
+
+int nntpdriver_authenticate_password(mailsession * session)
+{
+ struct nntp_session_state_data * data;
+ int r;
+
+ data = session_get_data(session);
+
+ if (data->nntp_password == NULL)
+ return MAIL_ERROR_LOGIN;
+
+ r = newsnntp_authinfo_password(session_get_nntp_session(session),
+ data->nntp_password);
+
+ return nntpdriver_nntp_error_to_mail_error(r);
+}
+
+int nntpdriver_mode_reader(mailsession * session)
+{
+ int done;
+ int r;
+
+ done = FALSE;
+
+ do {
+ r = newsnntp_mode_reader(session_get_nntp_session(session));
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ done = TRUE;
+ break;
+ }
+ }
+ while (!done);
+
+ return MAIL_NO_ERROR;
+}
+
+int nntpdriver_authenticate_user(mailsession * session)
+{
+ struct nntp_session_state_data * data;
+ int r;
+
+ data = session_get_data(session);
+
+ if (data->nntp_userid == NULL)
+ return MAIL_ERROR_LOGIN;
+
+ r = newsnntp_authinfo_username(session_get_nntp_session(session),
+ data->nntp_userid);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ return nntpdriver_authenticate_password(session);
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+}
+
+int nntpdriver_article(mailsession * session, uint32_t index,
+ char ** result,
+ size_t * result_len)
+{
+ char * msg_content;
+ size_t msg_length;
+ int r;
+ int done;
+
+ done = FALSE;
+ do {
+ r = newsnntp_article(session_get_nntp_session(session),
+ index, &msg_content, &msg_length);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (!done);
+
+ * result = msg_content;
+ * result_len = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+int nntpdriver_head(mailsession * session, uint32_t index,
+ char ** result,
+ size_t * result_len)
+{
+ char * headers;
+ size_t headers_length;
+ int r;
+ int done;
+
+ done = FALSE;
+ do {
+ r = newsnntp_head(session_get_nntp_session(session),
+ index, &headers, &headers_length);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (!done);
+
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+}
+
+int nntpdriver_size(mailsession * session, uint32_t index,
+ size_t * result)
+{
+ newsnntp * nntp;
+ struct newsnntp_xover_resp_item * item;
+ int r;
+ int done;
+
+ nntp = session_get_nntp_session(session);
+
+ done = FALSE;
+ do {
+ r = newsnntp_xover_single(nntp, index, &item);
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (!done);
+
+ * result = item->ovr_size;
+
+ xover_resp_item_free(item);
+
+ return MAIL_NO_ERROR;
+}
+
+int
+nntpdriver_get_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ uint32_t num,
+ struct mail_flags ** result)
+{
+ int r;
+ char keyname[PATH_MAX];
+ struct mail_flags * flags;
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%u-flags", num);
+
+ r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+int
+nntpdriver_write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ uint32_t num,
+ struct mail_flags * flags)
+{
+ int r;
+ char keyname[PATH_MAX];
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%u-flags", num);
+
+ r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+
+
+int nntpdriver_select_folder(mailsession * session, char * mb)
+{
+ int r;
+ struct newsnntp_group_info * info;
+ newsnntp * nntp_session;
+ struct nntp_session_state_data * data;
+ char * new_name;
+ int done;
+
+ data = session_get_data(session);
+
+ if (!data->nntp_mode_reader) {
+ r = nntpdriver_mode_reader(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ data->nntp_mode_reader = TRUE;
+ }
+
+ if (data->nntp_group_name != NULL)
+ if (strcmp(data->nntp_group_name, mb) == 0)
+ return MAIL_NO_ERROR;
+
+ nntp_session = session_get_nntp_session(session);
+
+ done = FALSE;
+ do {
+ r = newsnntp_group(nntp_session, mb, &info);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+
+ }
+ while (!done);
+
+ new_name = strdup(mb);
+ if (new_name == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ if (data->nntp_group_name != NULL)
+ free(data->nntp_group_name);
+ data->nntp_group_name = new_name;
+ if (data->nntp_group_info != NULL)
+ newsnntp_group_free(data->nntp_group_info);
+ data->nntp_group_info = info;
+
+ return MAIL_NO_ERROR;
+}
+
+
+int nntp_get_messages_list(mailsession * nntp_session,
+ mailsession * session,
+ mailmessage_driver * driver,
+ struct mailmessage_list ** result)
+{
+ carray * tab;
+ struct mailmessage_list * env_list;
+ uint32_t i;
+ int res;
+ int r;
+ struct nntp_session_state_data * data;
+ struct newsnntp_group_info * group_info;
+ uint32_t max;
+ unsigned int cur;
+
+ data = session_get_data(nntp_session);
+
+ if (data->nntp_group_name == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ r = nntpdriver_select_folder(nntp_session, data->nntp_group_name);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ group_info = data->nntp_group_info;
+
+ if (group_info == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ max = group_info->grp_first;
+ if (data->nntp_max_articles != 0) {
+ if (group_info->grp_last - data->nntp_max_articles + 1 > max)
+ max = group_info->grp_last - data->nntp_max_articles + 1;
+ }
+
+ tab = carray_new(128);
+ if (tab == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(i = max ; i <= group_info->grp_last ; i++) {
+ mailmessage * msg;
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = mailmessage_init(msg, session, driver, i, 0);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg);
+ res = r;
+ goto free_list;
+ }
+
+ r = carray_add(tab, msg, NULL);
+ if (r < 0) {
+ mailmessage_free(msg);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ env_list = mailmessage_list_new(tab);
+ if (env_list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = env_list;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ for(cur = 0 ; cur < carray_count(tab) ; cur ++)
+ mailmessage_free(carray_get(tab, cur));
+ carray_free(tab);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h
new file mode 100644
index 0000000..8ca9d16
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h
@@ -0,0 +1,88 @@
+/*
+ * 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 NNTPDRIVER_TOOLS_H
+
+#define NNTPDRIVER_TOOLS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mail_cache_db_types.h"
+#include "nntpdriver_types.h"
+
+int nntpdriver_nntp_error_to_mail_error(int error);
+
+int nntpdriver_authenticate_password(mailsession * session);
+
+int nntpdriver_authenticate_user(mailsession * session);
+
+int nntpdriver_article(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len);
+
+int nntpdriver_head(mailsession * session, uint32_t index,
+ char ** result,
+ size_t * result_len);
+
+int nntpdriver_size(mailsession * session, uint32_t index,
+ size_t * result);
+
+int
+nntpdriver_get_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ uint32_t num,
+ struct mail_flags ** result);
+
+int
+nntpdriver_write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ uint32_t num,
+ struct mail_flags * flags);
+
+int nntpdriver_select_folder(mailsession * session, char * mb);
+
+int nntp_get_messages_list(mailsession * nntp_session,
+ mailsession * session,
+ mailmessage_driver * driver,
+ struct mailmessage_list ** result);
+
+int nntpdriver_mode_reader(mailsession * session);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_types.h b/libetpan/src/driver/implementation/nntp/nntpdriver_types.h
new file mode 100644
index 0000000..7d4b74d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_types.h
@@ -0,0 +1,146 @@
+/*
+ * 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 NNTPDRIVER_TYPES_H
+
+#define NNTPDRIVER_TYPES_H
+
+#include <libetpan/libetpan-config.h>
+
+#include <libetpan/maildriver_types.h>
+#include <libetpan/newsnntp.h>
+#include <libetpan/clist.h>
+#include <libetpan/generic_cache_types.h>
+#include <libetpan/mailstorage_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NNTP driver for session */
+
+enum {
+ NNTPDRIVER_SET_MAX_ARTICLES = 1,
+};
+
+struct nntp_session_state_data {
+ newsnntp * nntp_session;
+ char * nntp_userid;
+ char * nntp_password;
+
+ struct newsnntp_group_info * nntp_group_info;
+ char * nntp_group_name;
+
+ clist * nntp_subscribed_list;
+
+ uint32_t nntp_max_articles;
+
+ int nntp_mode_reader;
+};
+
+/* cached NNTP driver for session */
+
+enum {
+ /* the mapping of the parameters should be the same as for nntp */
+ NNTPDRIVER_CACHED_SET_MAX_ARTICLES = 1,
+ /* cache specific */
+ NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY,
+ NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY,
+};
+
+struct nntp_cached_session_state_data {
+ mailsession * nntp_ancestor;
+ char nntp_cache_directory[PATH_MAX];
+ char nntp_flags_directory[PATH_MAX];
+ struct mail_flags_store * nntp_flags_store;
+};
+
+
+/* nntp storage */
+
+/*
+ nntp_mailstorage is the state data specific to the IMAP4rev1 storage.
+
+ - storage this is the storage to initialize.
+
+ - servername this is the name of the NNTP server
+
+ - port is the port to connect to, on the server.
+ you give 0 to use the default port.
+
+ - connection_type is the type of socket layer to use.
+ The value can be CONNECTION_TYPE_PLAIN or CONNECTION_TYPE_TLS.
+
+ - auth_type is the authenticate mechanism to use.
+ The value can be NNTP_AUTH_TYPE_PLAIN.
+
+ - login is the login of the POP3 account.
+
+ - password is the password of the POP3 account.
+
+ - cached if this value is != 0, a persistant cache will be
+ stored on local system.
+
+ - cache_directory is the location of the cache
+
+ - flags_directory is the location of the flags
+*/
+
+struct nntp_mailstorage {
+ char * nntp_servername;
+ uint16_t nntp_port;
+ char * nntp_command;
+ int nntp_connection_type;
+
+ int nntp_auth_type;
+ char * nntp_login;
+ char * nntp_password;
+
+ int nntp_cached;
+ char * nntp_cache_directory;
+ char * nntp_flags_directory;
+};
+
+/* this is the type of NNTP authentication */
+
+enum {
+ NNTP_AUTH_TYPE_PLAIN, /* plain text authentication */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpstorage.c b/libetpan/src/driver/implementation/nntp/nntpstorage.c
new file mode 100644
index 0000000..8d0e4ff
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpstorage.c
@@ -0,0 +1,267 @@
+/*
+ * 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 "nntpstorage.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "maildriver.h"
+#include "nntpdriver.h"
+#include "nntpdriver_cached.h"
+#include "mailstorage_tools.h"
+#include "mail.h"
+
+/* nntp storage */
+
+#define NNTP_DEFAULT_PORT 119
+#define NNTPS_DEFAULT_PORT 563
+
+static int nntp_mailstorage_connect(struct mailstorage * storage);
+static int nntp_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result);
+static void nntp_mailstorage_uninitialize(struct mailstorage * storage);
+
+static mailstorage_driver nntp_mailstorage_driver = {
+ .sto_name = "nntp",
+ .sto_connect = nntp_mailstorage_connect,
+ .sto_get_folder_session = nntp_mailstorage_get_folder_session,
+ .sto_uninitialize = nntp_mailstorage_uninitialize,
+};
+
+int nntp_mailstorage_init(struct mailstorage * storage,
+ char * nn_servername, uint16_t nn_port,
+ char * nn_command,
+ int nn_connection_type, int nn_auth_type,
+ char * nn_login, char * nn_password,
+ int nn_cached, char * nn_cache_directory, char * nn_flags_directory)
+{
+ struct nntp_mailstorage * nntp_storage;
+ int res;
+
+ nntp_storage = malloc(sizeof(* nntp_storage));
+ if (nntp_storage == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ nntp_storage->nntp_servername = strdup(nn_servername);
+ if (nntp_storage->nntp_servername == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ nntp_storage->nntp_connection_type = nn_connection_type;
+
+ if (nn_port == 0) {
+ switch (nn_connection_type) {
+ case CONNECTION_TYPE_PLAIN:
+ case CONNECTION_TYPE_COMMAND:
+ nn_port = NNTP_DEFAULT_PORT;
+ break;
+
+ case CONNECTION_TYPE_TLS:
+ case CONNECTION_TYPE_COMMAND_TLS:
+ nn_port = NNTPS_DEFAULT_PORT;
+ break;
+
+ default:
+ res = MAIL_ERROR_INVAL;
+ goto free_servername;
+ }
+ }
+
+ nntp_storage->nntp_port = nn_port;
+
+ if (nn_command != NULL) {
+ nntp_storage->nntp_command = strdup(nn_command);
+ if (nntp_storage->nntp_command == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_servername;
+ }
+ }
+ else
+ nntp_storage->nntp_command = NULL;
+
+ nntp_storage->nntp_auth_type = nn_auth_type;
+
+ if (nn_login != NULL) {
+ nntp_storage->nntp_login = strdup(nn_login);
+ if (nntp_storage->nntp_login == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_command;
+ }
+ }
+ else
+ nntp_storage->nntp_login = NULL;
+
+ if (nn_password != NULL) {
+ nntp_storage->nntp_password = strdup(nn_password);
+ if (nntp_storage->nntp_password == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_login;
+ }
+ }
+ else
+ nntp_storage->nntp_password = NULL;
+
+ nntp_storage->nntp_cached = nn_cached;
+
+ if (nn_cached && (nn_cache_directory != NULL) &&
+ (nn_flags_directory != NULL)) {
+ nntp_storage->nntp_cache_directory = strdup(nn_cache_directory);
+ if (nntp_storage->nntp_cache_directory == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_password;
+ }
+ nntp_storage->nntp_flags_directory = strdup(nn_flags_directory);
+ if (nntp_storage->nntp_flags_directory == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_cache_directory;
+ }
+ }
+ else {
+ nntp_storage->nntp_cached = FALSE;
+ nntp_storage->nntp_cache_directory = NULL;
+ nntp_storage->nntp_flags_directory = NULL;
+ }
+
+ storage->sto_data = nntp_storage;
+ storage->sto_driver = &nntp_mailstorage_driver;
+
+ return MAIL_NO_ERROR;
+
+ free_cache_directory:
+ free(nntp_storage->nntp_cache_directory);
+ free_password:
+ free(nntp_storage->nntp_password);
+ free_login:
+ free(nntp_storage->nntp_login);
+ free_command:
+ free(nn_command);
+ free_servername:
+ free(nntp_storage->nntp_servername);
+ free:
+ free(nntp_storage);
+ err:
+ return res;
+}
+
+static void nntp_mailstorage_uninitialize(struct mailstorage * storage)
+{
+ struct nntp_mailstorage * nntp_storage;
+
+ nntp_storage = storage->sto_data;
+
+ if (nntp_storage->nntp_flags_directory != NULL)
+ free(nntp_storage->nntp_flags_directory);
+ if (nntp_storage->nntp_cache_directory != NULL)
+ free(nntp_storage->nntp_cache_directory);
+ if (nntp_storage->nntp_password != NULL)
+ free(nntp_storage->nntp_password);
+ if (nntp_storage->nntp_login != NULL)
+ free(nntp_storage->nntp_login);
+ if (nntp_storage->nntp_command != NULL)
+ free(nntp_storage->nntp_command);
+ free(nntp_storage->nntp_servername);
+ free(nntp_storage);
+
+ storage->sto_data = NULL;
+}
+
+static int nntp_mailstorage_connect(struct mailstorage * storage)
+{
+ struct nntp_mailstorage * nntp_storage;
+ mailsession_driver * driver;
+ int r;
+ int res;
+ mailsession * session;
+
+ nntp_storage = storage->sto_data;
+
+ if (nntp_storage->nntp_cached)
+ driver = nntp_cached_session_driver;
+ else
+ driver = nntp_session_driver;
+
+ r = mailstorage_generic_connect(driver,
+ nntp_storage->nntp_servername,
+ nntp_storage->nntp_port, nntp_storage->nntp_command,
+ nntp_storage->nntp_connection_type,
+ NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY,
+ nntp_storage->nntp_cache_directory,
+ NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY,
+ nntp_storage->nntp_flags_directory,
+ &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,
+ nntp_storage->nntp_connection_type,
+ nntp_storage->nntp_login,
+ nntp_storage->nntp_password);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ storage->sto_session = session;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailsession_free(session);
+ err:
+ return res;
+}
+
+static int nntp_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result)
+{
+ int r;
+
+ r = mailsession_select_folder(storage->sto_session, pathname);
+
+ * result = storage->sto_session;
+
+ return MAIL_NO_ERROR;
+}
diff --git a/libetpan/src/driver/implementation/nntp/nntpstorage.h b/libetpan/src/driver/implementation/nntp/nntpstorage.h
new file mode 100644
index 0000000..7b046f4
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpstorage.h
@@ -0,0 +1,93 @@
+/*
+ * 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 NNTPSTORAGE_H
+
+#define NNTPSTORAGE_H
+
+#include <libetpan/nntpdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ nntp_mailstorage_init is the constructor for a NNTP storage
+
+ @param storage this is the storage to initialize.
+
+ @param servername this is the name of the NNTP 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 NNTP_AUTH_TYPE_PLAIN.
+
+ @param login is the login of the POP3 account.
+
+ @param password is the password of the POP3 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
+
+ @param flags_directory is the location of the flags
+*/
+
+int nntp_mailstorage_init(struct mailstorage * storage,
+ char * nntp_servername, uint16_t nntp_port,
+ char * nntp_command,
+ int nntp_connection_type, int nntp_auth_type,
+ char * nntp_login, char * nntp_password,
+ int nntp_cached, char * nntp_cache_directory,
+ char * nntp_flags_directory);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver.c b/libetpan/src/driver/implementation/pop3/pop3driver.c
new file mode 100644
index 0000000..ea69923
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver.c
@@ -0,0 +1,388 @@
+/*
+ * 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 "pop3driver.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "pop3driver_message.h"
+#include "maildriver_tools.h"
+#include "pop3driver_tools.h"
+#include "mailmessage.h"
+
+static int pop3driver_initialize(mailsession * session);
+
+static void pop3driver_uninitialize(mailsession * session);
+
+static int pop3driver_parameters(mailsession * session,
+ int id, void * value);
+
+static int pop3driver_connect_stream(mailsession * session, mailstream * s);
+
+static int pop3driver_starttls(mailsession * session);
+
+static int pop3driver_login(mailsession * session,
+ char * userid, char * password);
+
+static int pop3driver_logout(mailsession * session);
+
+static int pop3driver_noop(mailsession * session);
+
+static int pop3driver_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int pop3driver_messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int pop3driver_remove_message(mailsession * session, uint32_t num);
+
+static int pop3driver_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int pop3driver_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static mailsession_driver local_pop3_session_driver = {
+ .sess_name = "pop3",
+
+ .sess_initialize = pop3driver_initialize,
+ .sess_uninitialize = pop3driver_uninitialize,
+
+ .sess_parameters = pop3driver_parameters,
+
+ .sess_connect_stream = pop3driver_connect_stream,
+ .sess_connect_path = NULL,
+ .sess_starttls = pop3driver_starttls,
+ .sess_login = pop3driver_login,
+ .sess_logout = pop3driver_logout,
+ .sess_noop = pop3driver_noop,
+
+ .sess_build_folder_name = NULL,
+ .sess_create_folder = NULL,
+ .sess_delete_folder = NULL,
+ .sess_rename_folder = NULL,
+ .sess_check_folder = NULL,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = NULL,
+ .sess_expunge_folder = NULL,
+ .sess_status_folder = pop3driver_status_folder,
+ .sess_messages_number = pop3driver_messages_number,
+ .sess_recent_number = pop3driver_messages_number,
+ .sess_unseen_number = pop3driver_messages_number,
+ .sess_list_folders = NULL,
+ .sess_lsub_folders = NULL,
+ .sess_subscribe_folder = NULL,
+ .sess_unsubscribe_folder = NULL,
+
+ .sess_append_message = NULL,
+ .sess_append_message_flags = NULL,
+ .sess_copy_message = NULL,
+ .sess_move_message = NULL,
+
+ .sess_get_messages_list = pop3driver_get_messages_list,
+ .sess_get_envelopes_list = maildriver_generic_get_envelopes_list,
+ .sess_remove_message = pop3driver_remove_message,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = pop3driver_get_message,
+ .sess_get_message_by_uid = NULL,
+};
+
+mailsession_driver * pop3_session_driver = &local_pop3_session_driver;
+
+static inline struct pop3_session_state_data *
+get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static mailpop3 * get_pop3_session(mailsession * session)
+{
+ return get_data(session)->pop3_session;
+}
+
+static int pop3driver_initialize(mailsession * session)
+{
+ struct pop3_session_state_data * data;
+ mailpop3 * pop3;
+
+ pop3 = mailpop3_new(0, NULL);
+ if (session == NULL)
+ goto err;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto free;
+
+ data->pop3_session = pop3;
+ data->pop3_auth_type = POP3DRIVER_AUTH_TYPE_PLAIN;
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailpop3_free(pop3);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void pop3driver_uninitialize(mailsession * session)
+{
+ struct pop3_session_state_data * data;
+
+ data = get_data(session);
+
+ mailpop3_free(data->pop3_session);
+ free(data);
+
+ session->sess_data = data;
+}
+
+static int pop3driver_connect_stream(mailsession * session, mailstream * s)
+{
+ int r;
+
+ r = mailpop3_connect(get_pop3_session(session), s);
+
+ switch (r) {
+ case MAILPOP3_NO_ERROR:
+ return MAIL_NO_ERROR_NON_AUTHENTICATED;
+
+ default:
+ return pop3driver_pop3_error_to_mail_error(r);
+ }
+}
+
+static int pop3driver_starttls(mailsession * session)
+{
+ int r;
+ int fd;
+ mailstream_low * low;
+ mailstream_low * new_low;
+ mailpop3 * pop3;
+
+ pop3 = get_pop3_session(session);
+
+ r = mailpop3_stls(pop3);
+
+ switch (r) {
+ case MAILPOP3_NO_ERROR:
+ break;
+ default:
+ return pop3driver_pop3_error_to_mail_error(r);
+ }
+
+ low = mailstream_get_low(pop3->pop3_stream);
+ fd = mailstream_low_get_fd(low);
+ if (fd == -1)
+ return MAIL_ERROR_STREAM;
+
+ new_low = mailstream_low_ssl_open(fd);
+ if (new_low == NULL)
+ return MAIL_ERROR_STREAM;
+ mailstream_low_free(low);
+ mailstream_set_low(pop3->pop3_stream, new_low);
+
+ return MAIL_NO_ERROR;
+}
+
+static int pop3driver_parameters(mailsession * session,
+ int id, void * value)
+{
+ struct pop3_session_state_data * data;
+
+ data = get_data(session);
+
+ switch (id) {
+ case POP3DRIVER_SET_AUTH_TYPE:
+ {
+ int * param;
+
+ param = value;
+
+ data->pop3_auth_type = * param;
+ return MAIL_NO_ERROR;
+ }
+ }
+
+ return MAIL_ERROR_INVAL;
+}
+
+static int pop3driver_login(mailsession * session,
+ char * userid, char * password)
+{
+ int r;
+ carray * msg_tab;
+ struct pop3_session_state_data * data;
+
+ data = get_data(session);
+
+ switch (data->pop3_auth_type) {
+ case POP3DRIVER_AUTH_TYPE_TRY_APOP:
+ r = mailpop3_login_apop(get_pop3_session(session), userid, password);
+ if (r != MAILPOP3_NO_ERROR)
+ r = mailpop3_login(get_pop3_session(session), userid, password);
+ break;
+
+ case POP3DRIVER_AUTH_TYPE_APOP:
+ r = mailpop3_login_apop(get_pop3_session(session), userid, password);
+ break;
+
+ default:
+ case POP3DRIVER_AUTH_TYPE_PLAIN:
+ r = mailpop3_login(get_pop3_session(session), userid, password);
+ break;
+ }
+
+ mailpop3_list(get_pop3_session(session), &msg_tab);
+
+ return pop3driver_pop3_error_to_mail_error(r);
+}
+
+static int pop3driver_logout(mailsession * session)
+{
+ int r;
+
+ r = mailpop3_quit(get_pop3_session(session));
+
+ return pop3driver_pop3_error_to_mail_error(r);
+}
+
+static int pop3driver_noop(mailsession * session)
+{
+ int r;
+
+ r = mailpop3_noop(get_pop3_session(session));
+
+ return pop3driver_pop3_error_to_mail_error(r);
+}
+
+static int pop3driver_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages,
+ uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ uint32_t count;
+ int r;
+
+ r = pop3driver_messages_number(session, mb, &count);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result_messages = count;
+ * result_recent = count;
+ * result_unseen = count;
+
+ return MAIL_NO_ERROR;
+}
+
+static int pop3driver_messages_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ carray * msg_tab;
+
+ mailpop3_list(get_pop3_session(session), &msg_tab);
+
+ * result = carray_count(msg_tab) -
+ get_pop3_session(session)->pop3_deleted_count;
+
+ return MAIL_NO_ERROR;
+}
+
+
+/* messages operations */
+
+static int pop3driver_remove_message(mailsession * session, uint32_t num)
+{
+ mailpop3 * pop3;
+ int r;
+
+ pop3 = get_pop3_session(session);
+
+ r = mailpop3_dele(pop3, num);
+ switch (r) {
+ case MAILPOP3_ERROR_BAD_STATE:
+ return MAIL_ERROR_BAD_STATE;
+
+ case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ case MAILPOP3_ERROR_STREAM:
+ return MAIL_ERROR_STREAM;
+
+ case MAILPOP3_NO_ERROR:
+ return MAIL_NO_ERROR;
+
+ default:
+ return MAIL_ERROR_REMOVE;
+ }
+}
+
+static int pop3driver_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ mailpop3 * pop3;
+
+ pop3 = get_pop3_session(session);
+
+ return pop3_get_messages_list(pop3, session,
+ pop3_message_driver, result);
+}
+
+static int pop3driver_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result)
+{
+ mailmessage * msg_info;
+ int r;
+
+ msg_info = mailmessage_new();
+ if (msg_info == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_init(msg_info, session, pop3_message_driver, num, 0);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg_info);
+ return r;
+ }
+
+ * result = msg_info;
+
+ return MAIL_NO_ERROR;
+}
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver.h b/libetpan/src/driver/implementation/pop3/pop3driver.h
new file mode 100644
index 0000000..b70f69e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver.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 POP3DRIVER_H
+
+#define POP3DRIVER_H
+
+#include <libetpan/pop3driver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * pop3_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_cached.c b/libetpan/src/driver/implementation/pop3/pop3driver_cached.c
new file mode 100644
index 0000000..d3cc98e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_cached.c
@@ -0,0 +1,899 @@
+/*
+ * 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 "pop3driver_cached.h"
+
+#include "libetpan-config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "mail.h"
+#include "mail_cache_db.h"
+
+#include "maildriver.h"
+#include "mailmessage.h"
+#include "pop3driver.h"
+#include "mailpop3.h"
+#include "generic_cache.h"
+#include "imfcache.h"
+#include "pop3driver_cached_message.h"
+#include "pop3driver_tools.h"
+#include "maildriver_tools.h"
+
+static int pop3driver_cached_initialize(mailsession * session);
+
+static void pop3driver_cached_uninitialize(mailsession * session);
+
+static int pop3driver_cached_parameters(mailsession * session,
+ int id, void * value);
+
+static int pop3driver_cached_connect_stream(mailsession * session,
+ mailstream * s);
+
+static int pop3driver_cached_starttls(mailsession * session);
+
+static int pop3driver_cached_login(mailsession * session,
+ char * userid, char * password);
+
+static int pop3driver_cached_logout(mailsession * session);
+
+static int pop3driver_cached_check_folder(mailsession * session);
+
+static int pop3driver_cached_noop(mailsession * session);
+
+static int pop3driver_cached_expunge_folder(mailsession * session);
+
+static int pop3driver_cached_status_folder(mailsession * session,
+ char * mb, uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int pop3driver_cached_messages_number(mailsession * session,
+ char * mb,
+ uint32_t * result);
+
+static int pop3driver_cached_recent_number(mailsession * session,
+ char * mb,
+ uint32_t * result);
+
+static int pop3driver_cached_unseen_number(mailsession * session,
+ char * mb,
+ uint32_t * result);
+
+static int pop3driver_cached_remove_message(mailsession * session,
+ uint32_t num);
+
+static int
+pop3driver_cached_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int
+pop3driver_cached_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list);
+
+static int pop3driver_cached_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static int pop3driver_cached_get_message_by_uid(mailsession * session,
+ const char * uid, mailmessage ** result);
+
+static mailsession_driver local_pop3_cached_session_driver = {
+ .sess_name = "pop3-cached",
+
+ .sess_initialize = pop3driver_cached_initialize,
+ .sess_uninitialize = pop3driver_cached_uninitialize,
+
+ .sess_parameters = pop3driver_cached_parameters,
+
+ .sess_connect_stream = pop3driver_cached_connect_stream,
+ .sess_connect_path = NULL,
+ .sess_starttls = pop3driver_cached_starttls,
+ .sess_login = pop3driver_cached_login,
+ .sess_logout = pop3driver_cached_logout,
+ .sess_noop = pop3driver_cached_noop,
+
+ .sess_build_folder_name = NULL,
+ .sess_create_folder = NULL,
+ .sess_delete_folder = NULL,
+ .sess_rename_folder = NULL,
+ .sess_check_folder = pop3driver_cached_check_folder,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = NULL,
+ .sess_expunge_folder = pop3driver_cached_expunge_folder,
+ .sess_status_folder = pop3driver_cached_status_folder,
+ .sess_messages_number = pop3driver_cached_messages_number,
+ .sess_recent_number = pop3driver_cached_recent_number,
+ .sess_unseen_number = pop3driver_cached_unseen_number,
+ .sess_list_folders = NULL,
+ .sess_lsub_folders = NULL,
+ .sess_subscribe_folder = NULL,
+ .sess_unsubscribe_folder = NULL,
+
+ .sess_append_message = NULL,
+ .sess_append_message_flags = NULL,
+ .sess_copy_message = NULL,
+ .sess_move_message = NULL,
+
+ .sess_get_messages_list = pop3driver_cached_get_messages_list,
+ .sess_get_envelopes_list = pop3driver_cached_get_envelopes_list,
+ .sess_remove_message = pop3driver_cached_remove_message,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = pop3driver_cached_get_message,
+ .sess_get_message_by_uid = pop3driver_cached_get_message_by_uid,
+};
+
+mailsession_driver * pop3_cached_session_driver =
+&local_pop3_cached_session_driver;
+
+#define ENV_NAME "env.db"
+#define FLAGS_NAME "flags.db"
+
+
+static inline struct pop3_cached_session_state_data *
+get_cached_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline mailsession * get_ancestor(mailsession * session)
+{
+ return get_cached_data(session)->pop3_ancestor;
+}
+
+static inline struct pop3_session_state_data *
+get_ancestor_data(mailsession * session)
+{
+ return get_ancestor(session)->sess_data;
+}
+
+static inline mailpop3 * get_pop3_session(mailsession * session)
+{
+ return get_ancestor_data(session)->pop3_session;
+}
+
+static int pop3driver_cached_initialize(mailsession * session)
+{
+ struct pop3_cached_session_state_data * data;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto err;
+
+ data->pop3_flags_store = mail_flags_store_new();
+ if (data->pop3_flags_store == NULL)
+ goto free_data;
+
+ data->pop3_ancestor = mailsession_new(pop3_session_driver);
+ if (data->pop3_ancestor == NULL)
+ goto free_store;
+
+ data->pop3_flags_hash = chash_new(128, CHASH_COPYNONE);
+ if (data->pop3_flags_hash == NULL)
+ goto free_session;
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ free_session:
+ mailsession_free(data->pop3_ancestor);
+ free_store:
+ mail_flags_store_free(data->pop3_flags_store);
+ free_data:
+ free(data);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static int pop3_flags_store_process(char * flags_directory,
+ struct mail_flags_store * flags_store)
+{
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ unsigned int i;
+ int r;
+ int res;
+
+ if (carray_count(flags_store->fls_tab) == 0)
+ return MAIL_NO_ERROR;
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s",
+ flags_directory, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(flags_store->fls_tab, i);
+
+ r = pop3driver_write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_uid, msg->msg_flags);
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ mail_flags_store_clear(flags_store);
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static void pop3driver_cached_uninitialize(mailsession * session)
+{
+ struct pop3_cached_session_state_data * data;
+
+ data = get_cached_data(session);
+
+ pop3_flags_store_process(data->pop3_flags_directory,
+ data->pop3_flags_store);
+
+ mail_flags_store_free(data->pop3_flags_store);
+
+ chash_free(data->pop3_flags_hash);
+ mailsession_free(data->pop3_ancestor);
+ free(data);
+
+ session->sess_data = data;
+}
+
+static int pop3driver_cached_check_folder(mailsession * session)
+{
+ struct pop3_cached_session_state_data * pop3_data;
+
+ pop3_data = get_cached_data(session);
+
+ pop3_flags_store_process(pop3_data->pop3_flags_directory,
+ pop3_data->pop3_flags_store);
+
+ return MAIL_NO_ERROR;
+}
+
+static int pop3driver_cached_parameters(mailsession * session,
+ int id, void * value)
+{
+ struct pop3_cached_session_state_data * data;
+ int r;
+
+ data = get_cached_data(session);
+
+ switch (id) {
+ case POP3DRIVER_CACHED_SET_CACHE_DIRECTORY:
+ strncpy(data->pop3_cache_directory, value, PATH_MAX);
+ data->pop3_cache_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(data->pop3_cache_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+
+ case POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY:
+ strncpy(data->pop3_flags_directory, value, PATH_MAX);
+ data->pop3_flags_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(data->pop3_flags_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+
+ default:
+ return mailsession_parameters(data->pop3_ancestor, id, value);
+ }
+}
+
+static int pop3driver_cached_connect_stream(mailsession * session,
+ mailstream * s)
+{
+ int r;
+
+ r = mailsession_connect_stream(get_ancestor(session), s);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+}
+
+static int pop3driver_cached_starttls(mailsession * session)
+{
+ return mailsession_starttls(get_ancestor(session));
+}
+
+
+static int pop3driver_cached_login(mailsession * session,
+ char * userid, char * password)
+{
+ return mailsession_login(get_ancestor(session), userid, password);
+}
+
+static int pop3driver_cached_logout(mailsession * session)
+{
+ struct pop3_cached_session_state_data * cached_data;
+
+ cached_data = get_cached_data(session);
+
+ pop3_flags_store_process(cached_data->pop3_flags_directory,
+ cached_data->pop3_flags_store);
+
+ return mailsession_logout(get_ancestor(session));
+}
+
+static int pop3driver_cached_noop(mailsession * session)
+{
+ return mailsession_noop(get_ancestor(session));
+}
+
+static int pop3driver_cached_expunge_folder(mailsession * session)
+{
+ int res;
+ struct pop3_cached_session_state_data * cached_data;
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ unsigned int i;
+ int r;
+ carray * msg_tab;
+ mailpop3 * pop3;
+
+ pop3 = get_pop3_session(session);
+
+ cached_data = get_cached_data(session);
+
+ pop3_flags_store_process(cached_data->pop3_flags_directory,
+ cached_data->pop3_flags_store);
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s",
+ cached_data->pop3_flags_directory, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ mailpop3_list(pop3, &msg_tab);
+
+ for(i = 0 ; i < carray_count(msg_tab) ; i++) {
+ struct mailpop3_msg_info * pop3_info;
+ struct mail_flags * flags;
+
+ pop3_info = carray_get(msg_tab, i);
+ if (pop3_info == NULL)
+ continue;
+
+ if (pop3_info->msg_deleted)
+ continue;
+
+ r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
+ session, pop3_info->msg_index, &flags);
+ if (r != MAIL_NO_ERROR)
+ continue;
+
+ if (flags->fl_flags & MAIL_FLAG_DELETED) {
+ r = mailpop3_dele(pop3, pop3_info->msg_index);
+ }
+
+ mail_flags_free(flags);
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static int pop3driver_cached_status_folder(mailsession * session,
+ char * mb, uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ int res;
+ struct pop3_cached_session_state_data * cached_data;
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ unsigned int i;
+ int r;
+ carray * msg_tab;
+ mailpop3 * pop3;
+ uint32_t recent;
+ uint32_t unseen;
+
+ recent = 0;
+ unseen = 0;
+
+ pop3 = get_pop3_session(session);
+
+ cached_data = get_cached_data(session);
+
+ pop3_flags_store_process(cached_data->pop3_flags_directory,
+ cached_data->pop3_flags_store);
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s",
+ cached_data->pop3_flags_directory, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ mailpop3_list(pop3, &msg_tab);
+
+ for(i = 0 ; i < carray_count(msg_tab) ; i++) {
+ struct mailpop3_msg_info * pop3_info;
+ struct mail_flags * flags;
+
+ pop3_info = carray_get(msg_tab, i);
+ if (pop3_info == NULL)
+ continue;
+
+ if (pop3_info->msg_deleted)
+ continue;
+
+ r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
+ session, pop3_info->msg_index, &flags);
+ if (r != MAIL_NO_ERROR) {
+ recent ++;
+ unseen ++;
+ continue;
+ }
+
+ if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
+ recent ++;
+ }
+ if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
+ unseen ++;
+ }
+ mail_flags_free(flags);
+
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ * result_messages = carray_count(msg_tab) - pop3->pop3_deleted_count;
+ * result_recent = recent;
+ * result_unseen = unseen;
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static int pop3driver_cached_messages_number(mailsession * session,
+ char * mb,
+ uint32_t * result)
+{
+ return mailsession_messages_number(get_ancestor(session), mb, result);
+}
+
+static int pop3driver_cached_recent_number(mailsession * session,
+ char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = pop3driver_cached_status_folder(session, mb,
+ &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = recent;
+
+ return MAIL_NO_ERROR;
+}
+
+static int pop3driver_cached_unseen_number(mailsession * session,
+ char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = pop3driver_cached_status_folder(session, mb,
+ &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = unseen;
+
+ return MAIL_NO_ERROR;
+}
+
+/* messages operations */
+
+static int pop3driver_cached_remove_message(mailsession * session,
+ uint32_t num)
+{
+ return mailsession_remove_message(get_ancestor(session), num);
+}
+
+static int
+pop3driver_cached_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ mailpop3 * pop3;
+
+ pop3 = get_pop3_session(session);
+
+ return pop3_get_messages_list(pop3, session,
+ pop3_cached_message_driver, result);
+}
+
+
+static int
+get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
+ mailsession * session, uint32_t num,
+ struct mailimf_fields ** result)
+{
+ int r;
+ char keyname[PATH_MAX];
+ struct mailpop3_msg_info * info;
+ struct mailimf_fields * fields;
+ int res;
+ mailpop3 * pop3;
+
+ pop3 = get_pop3_session(session);
+
+ r = mailpop3_get_msg_info(pop3, num, &info);
+ switch (r) {
+ case MAILPOP3_ERROR_BAD_STATE:
+ return MAIL_ERROR_BAD_STATE;
+ case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
+ return MAIL_ERROR_MSG_NOT_FOUND;
+ case MAILPOP3_NO_ERROR:
+ break;
+ default:
+ return MAIL_ERROR_FETCH;
+ }
+
+ snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl);
+
+ r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = fields;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+write_cached_envelope(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ mailsession * session, uint32_t num,
+ struct mailimf_fields * fields)
+{
+ int r;
+ char keyname[PATH_MAX];
+ int res;
+ struct mailpop3_msg_info * info;
+ mailpop3 * pop3;
+
+ pop3 = get_pop3_session(session);
+
+ r = mailpop3_get_msg_info(pop3, num, &info);
+ switch (r) {
+ case MAILPOP3_ERROR_BAD_STATE:
+ return MAIL_ERROR_BAD_STATE;
+ case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
+ return MAIL_ERROR_MSG_NOT_FOUND;
+ case MAILPOP3_NO_ERROR:
+ break;
+ default:
+ return MAIL_ERROR_FETCH;
+ }
+
+ snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl);
+
+ r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static void get_uid_from_filename(char * filename)
+{
+ char * p;
+
+ p = strstr(filename, "-header");
+ if (p != NULL)
+ * p = 0;
+}
+
+static int
+pop3driver_cached_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list)
+{
+ int r;
+ unsigned int i;
+ struct pop3_cached_session_state_data * cached_data;
+ char filename_env[PATH_MAX];
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_env;
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ int res;
+
+ cached_data = get_cached_data(session);
+
+ pop3_flags_store_process(cached_data->pop3_flags_directory,
+ cached_data->pop3_flags_store);
+
+ snprintf(filename_env, PATH_MAX, "%s/%s",
+ cached_data->pop3_cache_directory, ENV_NAME);
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s",
+ cached_data->pop3_flags_directory, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_env;
+ }
+
+ /* fill with cached */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+ struct mailimf_fields * fields;
+ struct mail_flags * flags;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields == NULL) {
+ r = get_cached_envelope(cache_db_env, mmapstr,
+ session, msg->msg_index, &fields);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_cached = TRUE;
+ msg->msg_fields = fields;
+ }
+ }
+
+ if (msg->msg_flags == NULL) {
+ r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
+ session, msg->msg_index, &flags);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_flags = flags;
+ }
+ }
+ }
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+
+ r = maildriver_generic_get_envelopes_list(session, env_list);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mmapstr;
+ }
+
+ /* add flags */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_flags == NULL)
+ msg->msg_flags = mail_flags_new_empty();
+ }
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_env;
+ }
+
+ /* must write cache */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields != NULL) {
+ if (!msg->msg_cached) {
+ r = write_cached_envelope(cache_db_env, mmapstr,
+ session, msg->msg_index, msg->msg_fields);
+ }
+ }
+
+ if (msg->msg_flags != NULL) {
+ r = pop3driver_write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_uid, msg->msg_flags);
+ }
+ }
+
+ /* flush cache */
+
+ maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+ mmap_string_free(mmapstr);
+
+ /* remove cache files */
+
+ maildriver_message_cache_clean_up(cached_data->pop3_cache_directory,
+ env_list, get_uid_from_filename);
+
+ return MAIL_NO_ERROR;
+
+ close_db_env:
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ err:
+ return res;
+}
+
+static int pop3driver_cached_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result)
+{
+ mailmessage * msg_info;
+ int r;
+
+ msg_info = mailmessage_new();
+ if (msg_info == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_init(msg_info, session, pop3_cached_message_driver, num, 0);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg_info);
+ return r;
+ }
+
+ * result = msg_info;
+
+ return MAIL_NO_ERROR;
+}
+
+static int pop3driver_cached_get_message_by_uid(mailsession * session,
+ const char * uid, mailmessage ** result)
+{
+ mailpop3 * pop3;
+ struct mailpop3_msg_info * msg_info;
+ int found;
+ unsigned int i;
+
+ if (uid == NULL)
+ return MAIL_ERROR_INVAL;
+
+ pop3 = get_pop3_session(session);
+
+ found = 0;
+
+ /* iterate all messages and look for uid */
+ for(i = 0 ; i < carray_count(pop3->pop3_msg_tab) ; i++) {
+ msg_info = carray_get(pop3->pop3_msg_tab, i);
+
+ if (msg_info == NULL)
+ continue;
+
+ if (msg_info->msg_deleted)
+ continue;
+
+ /* uid found, stop looking */
+ if (strcmp(msg_info->msg_uidl, uid) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ return pop3driver_cached_get_message(session, msg_info->msg_index, result);
+}
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_cached.h b/libetpan/src/driver/implementation/pop3/pop3driver_cached.h
new file mode 100644
index 0000000..4f4b6c9
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_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 POP3DRIVER_CACHED_H
+
+#define POP3DRIVER_CACHED_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libetpan/pop3driver_types.h>
+
+extern mailsession_driver * pop3_cached_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c b/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c
new file mode 100644
index 0000000..4eed0db
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c
@@ -0,0 +1,355 @@
+/*
+ * 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 "pop3driver_cached_message.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "mail_cache_db.h"
+
+#include "mailmessage.h"
+#include "mailmessage_tools.h"
+#include "pop3driver.h"
+#include "pop3driver_tools.h"
+#include "pop3driver_cached.h"
+#include "pop3driver_message.h"
+#include "generic_cache.h"
+
+static int pop3_prefetch(mailmessage * msg_info);
+
+static void pop3_prefetch_free(struct generic_message_t * msg);
+
+static int pop3_initialize(mailmessage * msg_info);
+
+static void pop3_flush(mailmessage * msg_info);
+
+static void pop3_check(mailmessage * msg_info);
+
+static int pop3_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static int pop3_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static int pop3_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result);
+
+static void pop3_uninitialize(mailmessage * msg_info);
+
+static mailmessage_driver local_pop3_cached_message_driver = {
+ .msg_name = "pop3-cached",
+
+ .msg_initialize = pop3_initialize,
+ .msg_uninitialize = pop3_uninitialize,
+
+ .msg_flush = pop3_flush,
+ .msg_check = pop3_check,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = pop3_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_body,
+ .msg_fetch_size = pop3_fetch_size,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = pop3_get_flags,
+};
+
+mailmessage_driver * pop3_cached_message_driver =
+&local_pop3_cached_message_driver;
+
+
+static inline struct pop3_cached_session_state_data *
+get_cached_session_data(mailmessage * msg)
+{
+ return msg->msg_session->sess_data;
+}
+
+static inline mailsession * get_ancestor_session(mailmessage * msg)
+{
+ return get_cached_session_data(msg)->pop3_ancestor;
+}
+
+static inline struct pop3_session_state_data *
+get_ancestor_session_data(mailmessage * msg)
+{
+ return get_ancestor_session(msg)->sess_data;
+}
+
+static inline mailpop3 * get_pop3_session(mailmessage * msg)
+{
+ return get_ancestor_session_data(msg)->pop3_session;
+}
+
+
+static int pop3_prefetch(mailmessage * msg_info)
+{
+ char * msg_content;
+ size_t msg_length;
+ struct generic_message_t * msg;
+ int r;
+ struct pop3_cached_session_state_data * cached_data;
+ char filename[PATH_MAX];
+
+ /* we try the cached message */
+
+ cached_data = get_cached_session_data(msg_info);
+
+ snprintf(filename, PATH_MAX, "%s/%s",
+ cached_data->pop3_cache_directory, msg_info->msg_uid);
+
+ r = generic_cache_read(filename, &msg_content, &msg_length);
+ if (r == MAIL_NO_ERROR) {
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+ }
+
+ /* we get the message through the network */
+
+ r = pop3driver_retr(get_ancestor_session(msg_info), msg_info->msg_index,
+ &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ /* we write the message cache */
+
+ generic_cache_store(filename, msg_content, msg_length);
+
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static void pop3_prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ mmap_string_unref(msg->msg_message);
+ msg->msg_message = NULL;
+ }
+}
+
+static int pop3_initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * uid;
+ struct mailpop3_msg_info * info;
+ mailpop3 * pop3;
+
+ pop3 = get_pop3_session(msg_info);
+
+ r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info);
+ switch (r) {
+ case MAILPOP3_NO_ERROR:
+ break;
+ default:
+ return pop3driver_pop3_error_to_mail_error(r);
+ }
+
+ uid = strdup(info->msg_uidl);
+ if (uid == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR) {
+ free(uid);
+ return r;
+ }
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = pop3_prefetch;
+ msg->msg_prefetch_free = pop3_prefetch_free;
+ msg_info->msg_uid = uid;
+
+ return MAIL_NO_ERROR;
+}
+
+static void pop3_uninitialize(mailmessage * msg_info)
+{
+ mailmessage_generic_uninitialize(msg_info);
+}
+
+#define FLAGS_NAME "flags.db"
+
+static void pop3_flush(mailmessage * msg_info)
+{
+ mailmessage_generic_flush(msg_info);
+}
+
+static void pop3_check(mailmessage * msg_info)
+{
+ int r;
+
+ if (msg_info->msg_flags != NULL) {
+ r = mail_flags_store_set(get_cached_session_data(msg_info)->pop3_flags_store,
+ msg_info);
+ }
+}
+
+
+static int pop3_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ struct generic_message_t * msg;
+ char * headers;
+ size_t headers_length;
+ int r;
+ struct pop3_cached_session_state_data * cached_data;
+ char filename[PATH_MAX];
+
+ msg = msg_info->msg_data;
+
+ if (msg->msg_message != NULL)
+ return mailmessage_generic_fetch_header(msg_info,
+ result, result_len);
+
+ /* we try the cached message */
+
+ cached_data = get_cached_session_data(msg_info);
+
+ snprintf(filename, PATH_MAX, "%s/%s-header",
+ cached_data->pop3_cache_directory, msg_info->msg_uid);
+
+ r = generic_cache_read(filename, &headers, &headers_length);
+ if (r == MAIL_NO_ERROR) {
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+ }
+
+ /* we get the message trough the network */
+
+ r = pop3driver_header(get_ancestor_session(msg_info), msg_info->msg_index,
+ &headers, &headers_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ generic_cache_store(filename, headers, headers_length);
+
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static int pop3_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ return pop3driver_size(get_ancestor_session(msg_info),
+ msg_info->msg_index, result);
+}
+
+static int pop3_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result)
+{
+ int r;
+ struct mail_flags * flags;
+ struct mail_cache_db * cache_db_flags;
+ char filename_flags[PATH_MAX];
+ int res;
+ struct pop3_cached_session_state_data * cached_data;
+ MMAPString * mmapstr;
+
+ if (msg_info->msg_flags != NULL) {
+ * result = msg_info->msg_flags;
+
+ return MAIL_NO_ERROR;
+ }
+
+ cached_data = get_cached_session_data(msg_info);
+
+ flags = mail_flags_store_get(cached_data->pop3_flags_store,
+ msg_info->msg_index);
+
+ if (flags == NULL) {
+ snprintf(filename_flags, PATH_MAX, "%s/%s",
+ cached_data->pop3_flags_directory, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
+ msg_info->msg_session, msg_info->msg_index, &flags);
+ if (r != MAIL_NO_ERROR) {
+ flags = mail_flags_new_empty();
+ if (flags == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ }
+
+ msg_info->msg_flags = flags;
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.h b/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.h
new file mode 100644
index 0000000..f13cec7
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_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 POP3DRIVER_CACHED_MESSAGE_H
+
+#define POP3DRIVER_CACHED_MESSAGE_H
+
+#include <libetpan/pop3driver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * pop3_cached_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_message.c b/libetpan/src/driver/implementation/pop3/pop3driver_message.c
new file mode 100644
index 0000000..6ea8979
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_message.c
@@ -0,0 +1,193 @@
+/*
+ * 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 "pop3driver_message.h"
+
+#include "mailmessage_tools.h"
+#include "pop3driver_tools.h"
+#include "pop3driver.h"
+#include "mailpop3.h"
+#include <stdlib.h>
+#include <string.h>
+
+static int pop3_prefetch(mailmessage * msg_info);
+
+static void pop3_prefetch_free(struct generic_message_t * msg);
+
+static int pop3_initialize(mailmessage * msg_info);
+
+static int pop3_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static int pop3_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static mailmessage_driver local_pop3_message_driver = {
+ .msg_name = "pop3",
+
+ .msg_initialize = pop3_initialize,
+ .msg_uninitialize = mailmessage_generic_uninitialize,
+
+ .msg_flush = mailmessage_generic_flush,
+ .msg_check = NULL,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = pop3_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_body,
+ .msg_fetch_size = pop3_fetch_size,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = NULL,
+};
+
+mailmessage_driver * pop3_message_driver = &local_pop3_message_driver;
+
+static inline struct pop3_session_state_data *
+get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+
+static mailpop3 * get_pop3_session(mailsession * session)
+{
+ return get_data(session)->pop3_session;
+}
+
+
+static int pop3_prefetch(mailmessage * msg_info)
+{
+ char * msg_content;
+ size_t msg_length;
+ struct generic_message_t * msg;
+ int r;
+
+ r = pop3driver_retr(msg_info->msg_session, msg_info->msg_index,
+ &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static void pop3_prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ mmap_string_unref(msg->msg_message);
+ msg->msg_message = NULL;
+ }
+}
+
+static int pop3_initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * uid;
+ struct mailpop3_msg_info * info;
+ mailpop3 * pop3;
+
+ pop3 = get_pop3_session(msg_info->msg_session);
+
+ r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info);
+ switch (r) {
+ case MAILPOP3_NO_ERROR:
+ break;
+ default:
+ return pop3driver_pop3_error_to_mail_error(r);
+ }
+
+ uid = strdup(info->msg_uidl);
+ if (uid == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR) {
+ free(uid);
+ return r;
+ }
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = pop3_prefetch;
+ msg->msg_prefetch_free = pop3_prefetch_free;
+ msg_info->msg_uid = uid;
+
+ return MAIL_NO_ERROR;
+}
+
+
+static int pop3_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ struct generic_message_t * msg;
+ char * headers;
+ size_t headers_length;
+ int r;
+
+ msg = msg_info->msg_data;
+
+ if (msg->msg_message != NULL)
+ return mailmessage_generic_fetch_header(msg_info,
+ result, result_len);
+
+ r = pop3driver_header(msg_info->msg_session, msg_info->msg_index,
+ &headers, &headers_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static int pop3_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ return pop3driver_size(msg_info->msg_session, msg_info->msg_index, result);
+}
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_message.h b/libetpan/src/driver/implementation/pop3/pop3driver_message.h
new file mode 100644
index 0000000..ad0a01b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_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 POP3DRIVER_MESSAGE_H
+
+#define POP3DRIVER_MESSAGE_H
+
+#include <libetpan/pop3driver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * pop3_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_tools.c b/libetpan/src/driver/implementation/pop3/pop3driver_tools.c
new file mode 100644
index 0000000..73dd22a
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_tools.c
@@ -0,0 +1,344 @@
+/*
+ * 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 "pop3driver_tools.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "maildriver_types.h"
+#include "mailpop3.h"
+#include "pop3driver.h"
+#include "pop3driver_cached.h"
+#include "generic_cache.h"
+#include "imfcache.h"
+#include "mailmessage.h"
+#include "mail_cache_db.h"
+
+int pop3driver_pop3_error_to_mail_error(int error)
+{
+ switch (error) {
+ case MAILPOP3_NO_ERROR:
+ return MAIL_NO_ERROR;
+
+ case MAILPOP3_ERROR_BAD_STATE:
+ return MAIL_ERROR_BAD_STATE;
+
+ case MAILPOP3_ERROR_UNAUTHORIZED:
+ return MAIL_ERROR_CONNECT;
+
+ case MAILPOP3_ERROR_STREAM:
+ return MAIL_ERROR_STREAM;
+
+ case MAILPOP3_ERROR_DENIED:
+ return MAIL_ERROR_CONNECT;
+
+ case MAILPOP3_ERROR_BAD_USER:
+ case MAILPOP3_ERROR_BAD_PASSWORD:
+ return MAIL_ERROR_LOGIN;
+
+ case MAILPOP3_ERROR_CANT_LIST:
+ return MAIL_ERROR_LIST;
+
+ case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ case MAILPOP3_ERROR_MEMORY:
+ return MAIL_ERROR_MEMORY;
+
+ case MAILPOP3_ERROR_CONNECTION_REFUSED:
+ return MAIL_ERROR_CONNECT;
+
+ case MAILPOP3_ERROR_APOP_NOT_SUPPORTED:
+ return MAIL_ERROR_NO_APOP;
+
+ case MAILPOP3_ERROR_CAPA_NOT_SUPPORTED:
+ return MAIL_ERROR_CAPABILITY;
+
+ case MAILPOP3_ERROR_STLS_NOT_SUPPORTED:
+ return MAIL_ERROR_NO_TLS;
+
+ default:
+ return MAIL_ERROR_INVAL;
+ }
+};
+
+static inline struct pop3_session_state_data *
+session_get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline mailpop3 * session_get_pop3_session(mailsession * session)
+{
+ return session_get_data(session)->pop3_session;
+}
+
+static inline struct pop3_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)->pop3_ancestor;
+}
+
+static inline struct pop3_session_state_data *
+cached_session_get_ancestor_data(mailsession * session)
+{
+ return session_get_data(cached_session_get_ancestor(session));
+}
+
+static inline mailpop3 *
+cached_session_get_pop3_session(mailsession * session)
+{
+ return session_get_pop3_session(cached_session_get_ancestor(session));
+}
+
+
+int pop3driver_retr(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len)
+{
+ char * msg_content;
+ size_t msg_length;
+ int r;
+
+ r = mailpop3_retr(session_get_pop3_session(session), index,
+ &msg_content, &msg_length);
+
+ switch (r) {
+ case MAILPOP3_NO_ERROR:
+ break;
+ default:
+ return pop3driver_pop3_error_to_mail_error(r);
+ }
+
+ * result = msg_content;
+ * result_len = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+int pop3driver_header(mailsession * session, uint32_t index,
+ char ** result,
+ size_t * result_len)
+{
+ char * headers;
+ size_t headers_length;
+ int r;
+
+ r = mailpop3_header(session_get_pop3_session(session),
+ index, &headers, &headers_length);
+
+ switch (r) {
+ case MAILPOP3_NO_ERROR:
+ break;
+ default:
+ return pop3driver_pop3_error_to_mail_error(r);
+ }
+
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+}
+
+int pop3driver_size(mailsession * session, uint32_t index,
+ size_t * result)
+{
+ mailpop3 * pop3;
+ carray * msg_tab;
+ struct mailpop3_msg_info * info;
+ int r;
+
+ pop3 = session_get_pop3_session(session);
+
+ mailpop3_list(pop3, &msg_tab);
+
+ r = mailpop3_get_msg_info(pop3, index, &info);
+ switch (r) {
+ case MAILPOP3_NO_ERROR:
+ break;
+ default:
+ return pop3driver_pop3_error_to_mail_error(r);
+ }
+
+ * result = info->msg_size;
+
+ return MAIL_NO_ERROR;
+}
+
+int
+pop3driver_get_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ mailsession * session,
+ uint32_t num,
+ struct mail_flags ** result)
+{
+ int r;
+ char keyname[PATH_MAX];
+ struct mail_flags * flags;
+ int res;
+ struct mailpop3_msg_info * info;
+
+ r = mailpop3_get_msg_info(cached_session_get_pop3_session(session),
+ num, &info);
+ switch (r) {
+ case MAILPOP3_ERROR_BAD_STATE:
+ return MAIL_ERROR_BAD_STATE;
+ case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
+ return MAIL_ERROR_MSG_NOT_FOUND;
+ case MAILPOP3_NO_ERROR:
+ break;
+ default:
+ return MAIL_ERROR_FETCH;
+ }
+
+ snprintf(keyname, PATH_MAX, "%s-flags", info->msg_uidl);
+
+ r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+int
+pop3driver_write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ char * uid,
+ struct mail_flags * flags)
+{
+ int r;
+ char keyname[PATH_MAX];
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%s-flags", uid);
+
+ r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+int pop3_get_messages_list(mailpop3 * pop3,
+ mailsession * session,
+ mailmessage_driver * driver,
+ struct mailmessage_list ** result)
+{
+ carray * msg_tab;
+ carray * tab;
+ struct mailmessage_list * env_list;
+ unsigned int i;
+ int res;
+ int r;
+
+ mailpop3_list(pop3, &msg_tab);
+
+ tab = carray_new(128);
+ if (tab == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(i = 0 ; i < carray_count(msg_tab) ; i++) {
+ struct mailpop3_msg_info * pop3_info;
+ mailmessage * msg;
+
+ pop3_info = carray_get(msg_tab, i);
+
+ if (pop3_info == NULL)
+ continue;
+
+ if (pop3_info->msg_deleted)
+ continue;
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = mailmessage_init(msg, session, driver,
+ (uint32_t) pop3_info->msg_index, pop3_info->msg_size);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg);
+ res = r;
+ goto free_list;
+ }
+
+ r = carray_add(tab, msg, NULL);
+ if (r < 0) {
+ mailmessage_free(msg);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ env_list = mailmessage_list_new(/*list*/ tab);
+ if (env_list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = env_list;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ for(i = 0 ; i < carray_count(tab) ; i ++)
+ mailmessage_free(carray_get(tab, i));
+ carray_free(tab);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_tools.h b/libetpan/src/driver/implementation/pop3/pop3driver_tools.h
new file mode 100644
index 0000000..e6413aa
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_tools.h
@@ -0,0 +1,82 @@
+/*
+ * 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 POP3DRIVER_TOOLS_H
+
+#define POP3DRIVER_TOOLS_H
+
+#include "mail_cache_db_types.h"
+#include "pop3driver_types.h"
+#include "mailpop3.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int pop3driver_pop3_error_to_mail_error(int error);
+
+int pop3driver_retr(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len);
+
+int pop3driver_header(mailsession * session, uint32_t index,
+ char ** result,
+ size_t * result_len);
+
+int pop3driver_size(mailsession * session, uint32_t index,
+ size_t * result);
+
+int
+pop3driver_get_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ mailsession * session,
+ uint32_t num,
+ struct mail_flags ** result);
+
+int
+pop3driver_write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ char * uid,
+ struct mail_flags * flags);
+
+int pop3_get_messages_list(mailpop3 * pop3,
+ mailsession * session,
+ mailmessage_driver * driver,
+ struct mailmessage_list ** result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_types.h b/libetpan/src/driver/implementation/pop3/pop3driver_types.h
new file mode 100644
index 0000000..4bb872c
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_types.h
@@ -0,0 +1,153 @@
+/*
+ * 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 POP3DRIVER_TYPES_H
+
+#define POP3DRIVER_TYPES_H
+
+#include <libetpan/libetpan-config.h>
+
+#include <libetpan/maildriver_types.h>
+#include <libetpan/mailpop3.h>
+#include <libetpan/maildriver_types.h>
+#include <libetpan/chash.h>
+#include <libetpan/mailstorage_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* POP3 driver for session */
+
+enum {
+ POP3DRIVER_SET_AUTH_TYPE = 1,
+};
+
+enum {
+ POP3DRIVER_AUTH_TYPE_PLAIN = 0,
+ POP3DRIVER_AUTH_TYPE_APOP,
+ POP3DRIVER_AUTH_TYPE_TRY_APOP,
+};
+
+struct pop3_session_state_data {
+ int pop3_auth_type;
+ mailpop3 * pop3_session;
+};
+
+/* cached POP3 driver for session */
+
+enum {
+ /* the mapping of the parameters should be the same as for pop3 */
+ POP3DRIVER_CACHED_SET_AUTH_TYPE = 1,
+ /* cache specific */
+ POP3DRIVER_CACHED_SET_CACHE_DIRECTORY,
+ POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY,
+};
+
+struct pop3_cached_session_state_data {
+ mailsession * pop3_ancestor;
+ char pop3_cache_directory[PATH_MAX];
+ char pop3_flags_directory[PATH_MAX];
+ chash * pop3_flags_hash;
+ carray * pop3_flags_array;
+ struct mail_flags_store * pop3_flags_store;
+};
+
+/* pop3 storage */
+
+/*
+ pop3_mailstorage is the state data specific to the POP3 storage.
+
+ - servername this is the name of the POP3 server
+
+ - port is the port to connect to, on the server.
+ you give 0 to use the default port.
+
+ - connection_type is the type of socket layer to use.
+ The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
+ CONNECTION_TYPE_TRY_STARTTLS or CONNECTION_TYPE_TLS.
+
+ - auth_type is the authenticate mechanism to use.
+ The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP
+ or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented.
+
+ - login is the login of the POP3 account.
+
+ - password is the password of the POP3 account.
+
+ - cached if this value is != 0, a persistant cache will be
+ stored on local system.
+
+ - cache_directory is the location of the cache.
+
+ - flags_directory is the location of the flags.
+*/
+
+struct pop3_mailstorage {
+ char * pop3_servername;
+ uint16_t pop3_port;
+ char * pop3_command;
+ int pop3_connection_type;
+
+ int pop3_auth_type;
+ char * pop3_login;
+ char * pop3_password;
+
+ int pop3_cached;
+ char * pop3_cache_directory;
+ char * pop3_flags_directory;
+};
+
+/* this is the type of POP3 authentication */
+
+enum {
+ POP3_AUTH_TYPE_PLAIN, /* plain text authentication */
+ POP3_AUTH_TYPE_APOP, /* APOP authentication */
+ POP3_AUTH_TYPE_TRY_APOP, /* first, try APOP, if it fails,
+ try plain text */
+ POP3_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */
+ POP3_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */
+ POP3_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */
+ POP3_AUTH_TYPE_SASL_PLAIN, /* SASL plain */
+ POP3_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */
+ POP3_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */
+ POP3_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3storage.c b/libetpan/src/driver/implementation/pop3/pop3storage.c
new file mode 100644
index 0000000..1cff650
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3storage.c
@@ -0,0 +1,284 @@
+/*
+ * 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 "pop3storage.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "mail.h"
+#include "mailstorage_tools.h"
+#include "maildriver.h"
+
+/* pop3 storage */
+
+#define POP3_DEFAULT_PORT 110
+#define POP3S_DEFAULT_PORT 995
+
+static int pop3_mailstorage_connect(struct mailstorage * storage);
+static int pop3_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result);
+static void pop3_mailstorage_uninitialize(struct mailstorage * storage);
+
+static mailstorage_driver pop3_mailstorage_driver = {
+ .sto_name = "pop3",
+ .sto_connect = pop3_mailstorage_connect,
+ .sto_get_folder_session = pop3_mailstorage_get_folder_session,
+ .sto_uninitialize = pop3_mailstorage_uninitialize,
+};
+
+int pop3_mailstorage_init(struct mailstorage * storage,
+ char * pop3_servername, uint16_t pop3_port,
+ char * pop3_command,
+ int pop3_connection_type, int pop3_auth_type,
+ char * pop3_login, char * pop3_password,
+ int pop3_cached, char * pop3_cache_directory, char * pop3_flags_directory)
+{
+ struct pop3_mailstorage * pop3_storage;
+
+ pop3_storage = malloc(sizeof(* pop3_storage));
+ if (pop3_storage == NULL)
+ goto err;
+
+ pop3_storage->pop3_servername = strdup(pop3_servername);
+ if (pop3_storage->pop3_servername == NULL)
+ goto free;
+
+ pop3_storage->pop3_connection_type = pop3_connection_type;
+
+ if (pop3_port == 0) {
+ switch (pop3_connection_type) {
+ case CONNECTION_TYPE_PLAIN:
+ case CONNECTION_TYPE_TRY_STARTTLS:
+ case CONNECTION_TYPE_STARTTLS:
+ case CONNECTION_TYPE_COMMAND:
+ case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
+ case CONNECTION_TYPE_COMMAND_STARTTLS:
+ pop3_port = POP3_DEFAULT_PORT;
+ break;
+
+ case CONNECTION_TYPE_TLS:
+ case CONNECTION_TYPE_COMMAND_TLS:
+ pop3_port = POP3S_DEFAULT_PORT;
+ break;
+ }
+ }
+
+ pop3_storage->pop3_port = pop3_port;
+
+ if (pop3_command != NULL) {
+ pop3_storage->pop3_command = strdup(pop3_command);
+ if (pop3_storage->pop3_command == NULL)
+ goto free_servername;
+ }
+ else
+ pop3_storage->pop3_command = NULL;
+
+ pop3_storage->pop3_auth_type = pop3_auth_type;
+
+ if (pop3_login != NULL) {
+ pop3_storage->pop3_login = strdup(pop3_login);
+ if (pop3_storage->pop3_login == NULL)
+ goto free_command;
+ }
+ else
+ pop3_storage->pop3_login = NULL;
+
+ if (pop3_password != NULL) {
+ pop3_storage->pop3_password = strdup(pop3_password);
+ if (pop3_storage->pop3_password == NULL)
+ goto free_login;
+ }
+ else
+ pop3_storage->pop3_password = NULL;
+
+ pop3_storage->pop3_cached = pop3_cached;
+
+ if (pop3_cached && (pop3_cache_directory != NULL) &&
+ (pop3_flags_directory != NULL)) {
+ pop3_storage->pop3_cache_directory = strdup(pop3_cache_directory);
+ if (pop3_storage->pop3_cache_directory == NULL)
+ goto free_password;
+ pop3_storage->pop3_flags_directory = strdup(pop3_flags_directory);
+ if (pop3_storage->pop3_flags_directory == NULL)
+ goto free_cache_directory;
+ }
+ else {
+ pop3_storage->pop3_cached = FALSE;
+ pop3_storage->pop3_cache_directory = NULL;
+ pop3_storage->pop3_flags_directory = NULL;
+ }
+
+ storage->sto_data = pop3_storage;
+ storage->sto_driver = &pop3_mailstorage_driver;
+
+ return MAIL_NO_ERROR;
+
+ free_cache_directory:
+ free(pop3_storage->pop3_cache_directory);
+ free_password:
+ if (pop3_storage->pop3_password != NULL)
+ free(pop3_storage->pop3_password);
+ free_login:
+ if (pop3_storage->pop3_login != NULL)
+ free(pop3_storage->pop3_login);
+ free_command:
+ if (pop3_storage->pop3_command != NULL)
+ free(pop3_storage->pop3_command);
+ free_servername:
+ if (pop3_storage->pop3_servername != NULL)
+ free(pop3_storage->pop3_servername);
+ free:
+ free(pop3_storage);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void pop3_mailstorage_uninitialize(struct mailstorage * storage)
+{
+ struct pop3_mailstorage * pop3_storage;
+
+ pop3_storage = storage->sto_data;
+
+ if (pop3_storage->pop3_flags_directory != NULL)
+ free(pop3_storage->pop3_flags_directory);
+ if (pop3_storage->pop3_cache_directory != NULL)
+ free(pop3_storage->pop3_cache_directory);
+ if (pop3_storage->pop3_password != NULL)
+ free(pop3_storage->pop3_password);
+ if (pop3_storage->pop3_login != NULL)
+ free(pop3_storage->pop3_login);
+ if (pop3_storage->pop3_command != NULL)
+ free(pop3_storage->pop3_command);
+ free(pop3_storage->pop3_servername);
+ free(pop3_storage);
+
+ storage->sto_data = pop3_storage;
+}
+
+static int pop3_mailstorage_connect(struct mailstorage * storage)
+{
+ struct pop3_mailstorage * pop3_storage;
+ mailsession_driver * driver;
+ int r;
+ int res;
+ mailsession * session;
+ int auth_type;
+
+ pop3_storage = storage->sto_data;
+
+ if (pop3_storage->pop3_cached)
+ driver = pop3_cached_session_driver;
+ else
+ driver = pop3_session_driver;
+
+ r = mailstorage_generic_connect(driver,
+ pop3_storage->pop3_servername,
+ pop3_storage->pop3_port, pop3_storage->pop3_command,
+ pop3_storage->pop3_connection_type,
+ POP3DRIVER_CACHED_SET_CACHE_DIRECTORY,
+ pop3_storage->pop3_cache_directory,
+ POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY,
+ pop3_storage->pop3_flags_directory,
+ &session);
+ switch (r) {
+ case MAIL_NO_ERROR_NON_AUTHENTICATED:
+ case MAIL_NO_ERROR_AUTHENTICATED:
+ case MAIL_NO_ERROR:
+ break;
+ default:
+ res = r;
+ goto err;
+ }
+
+ auth_type = -1;
+ switch (pop3_storage->pop3_auth_type) {
+ case POP3_AUTH_TYPE_PLAIN:
+ auth_type = POP3DRIVER_AUTH_TYPE_PLAIN;
+ break;
+ case POP3_AUTH_TYPE_APOP:
+ auth_type = POP3DRIVER_AUTH_TYPE_APOP;
+ break;
+ case POP3_AUTH_TYPE_TRY_APOP:
+ auth_type = POP3DRIVER_AUTH_TYPE_TRY_APOP;
+ break;
+ }
+
+ if (auth_type != -1) {
+ mailsession_parameters(session, POP3DRIVER_SET_AUTH_TYPE, &auth_type);
+ }
+
+ r = mailstorage_generic_auth(session, r,
+ pop3_storage->pop3_auth_type,
+ pop3_storage->pop3_login,
+ pop3_storage->pop3_password);
+ if (r != MAIL_NO_ERROR) {
+ if (pop3_storage->pop3_auth_type == POP3_AUTH_TYPE_TRY_APOP) {
+ /* try in clear authentication */
+ mailsession_free(session);
+
+ pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_PLAIN;
+ r = mailstorage_connect(storage);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ return res;
+ }
+ pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_TRY_APOP;
+
+ return MAIL_NO_ERROR;
+ }
+
+ res = r;
+ goto free;
+ }
+
+ storage->sto_session = session;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailsession_free(session);
+ err:
+ return res;
+}
+
+static int pop3_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result)
+{
+ * result = storage->sto_session;
+
+ return MAIL_NO_ERROR;
+}
+
diff --git a/libetpan/src/driver/implementation/pop3/pop3storage.h b/libetpan/src/driver/implementation/pop3/pop3storage.h
new file mode 100644
index 0000000..e8cd513
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3storage.h
@@ -0,0 +1,95 @@
+/*
+ * 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 POP3STORAGE_H
+
+#define POP3STORAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libetpan/pop3driver_types.h>
+#include <libetpan/pop3driver.h>
+#include <libetpan/pop3driver_cached.h>
+
+/*
+ pop3_mailstorage_init is the constructor for a POP3 storage
+
+ @param storage this is the storage to initialize.
+
+ @param servername this is the name of the POP3 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 POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP
+ or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented.
+
+ @param login is the login of the POP3 account.
+
+ @param password is the password of the POP3 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
+
+ @param flags_directory is the location of the flags
+*/
+
+int pop3_mailstorage_init(struct mailstorage * storage,
+ char * pop3_servername, uint16_t pop3_port,
+ char * pop3_command,
+ int pop3_connection_type, int pop3_auth_type,
+ char * pop3_login, char * pop3_password,
+ int pop3_cached, char * pop3_cache_directory,
+ char * pop3_flags_directory);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif