summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver
Unidiff
Diffstat (limited to 'libetpan/src/driver') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/TODO9
-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
-rw-r--r--libetpan/src/driver/interface/maildriver.c383
-rw-r--r--libetpan/src/driver/interface/maildriver.h546
-rw-r--r--libetpan/src/driver/interface/maildriver_errors.h102
-rw-r--r--libetpan/src/driver/interface/maildriver_tools.c841
-rw-r--r--libetpan/src/driver/interface/maildriver_tools.h81
-rw-r--r--libetpan/src/driver/interface/maildriver_types.c340
-rw-r--r--libetpan/src/driver/interface/maildriver_types.h795
-rw-r--r--libetpan/src/driver/interface/maildriver_types_helper.c104
-rw-r--r--libetpan/src/driver/interface/maildriver_types_helper.h99
-rw-r--r--libetpan/src/driver/interface/mailfolder.c138
-rw-r--r--libetpan/src/driver/interface/mailfolder.h70
-rw-r--r--libetpan/src/driver/interface/mailmessage.c240
-rw-r--r--libetpan/src/driver/interface/mailmessage.h379
-rw-r--r--libetpan/src/driver/interface/mailmessage_tools.c600
-rw-r--r--libetpan/src/driver/interface/mailmessage_tools.h103
-rw-r--r--libetpan/src/driver/interface/mailmessage_types.c92
-rw-r--r--libetpan/src/driver/interface/mailmessage_types.h50
-rw-r--r--libetpan/src/driver/interface/mailstorage.c341
-rw-r--r--libetpan/src/driver/interface/mailstorage.h99
-rw-r--r--libetpan/src/driver/interface/mailstorage_tools.c372
-rw-r--r--libetpan/src/driver/interface/mailstorage_tools.h67
-rw-r--r--libetpan/src/driver/interface/mailstorage_types.h203
-rw-r--r--libetpan/src/driver/tools/generic_cache.c729
-rw-r--r--libetpan/src/driver/tools/generic_cache.h109
-rw-r--r--libetpan/src/driver/tools/generic_cache_types.h56
-rw-r--r--libetpan/src/driver/tools/imfcache.c1429
-rw-r--r--libetpan/src/driver/tools/imfcache.h75
-rw-r--r--libetpan/src/driver/tools/mailthread.c1742
-rw-r--r--libetpan/src/driver/tools/mailthread.h108
-rw-r--r--libetpan/src/driver/tools/mailthread_types.c90
-rw-r--r--libetpan/src/driver/tools/mailthread_types.h64
123 files changed, 40299 insertions, 0 deletions
diff --git a/libetpan/src/driver/TODO b/libetpan/src/driver/TODO
new file mode 100644
index 0000000..4ba2c46
--- a/dev/null
+++ b/libetpan/src/driver/TODO
@@ -0,0 +1,9 @@
1- get_message_list() will disconnect and reconnect POP3 box
2- add UID to non-cached drivers, help clients to recognize messages
3- move IMAP UID cache to non-cached driver
4- fix message size (put it in cache)
5- XXX : fetch body in nntp do not use generic_fetch_body
6- add flags prototype to add or remove flags
7- cache bodystructures
8- search is not implemented
9- list of folder new implementation
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "data_message_driver.h"
37
38#include "mailmessage.h"
39#include "mailmessage_tools.h"
40
41#include <unistd.h>
42#include <sys/mman.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <fcntl.h>
46#include <string.h>
47#include <stdlib.h>
48
49static int fetch_size(mailmessage * msg, size_t * result)
50{
51 struct generic_message_t * msg_data;
52
53 msg_data = msg->msg_data;
54 * result = msg_data->msg_length;
55
56 return MAIL_NO_ERROR;
57}
58
59
60static mailmessage_driver local_data_message_driver = {
61 .msg_name = "data",
62
63 .msg_initialize = mailmessage_generic_initialize,
64 .msg_uninitialize = mailmessage_generic_uninitialize,
65
66 .msg_flush = mailmessage_generic_flush,
67 .msg_check = NULL,
68
69 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
70
71 .msg_fetch = mailmessage_generic_fetch,
72 .msg_fetch_header = mailmessage_generic_fetch_header,
73 .msg_fetch_body = mailmessage_generic_fetch_body,
74 .msg_fetch_size = fetch_size,
75 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
76 .msg_fetch_section = mailmessage_generic_fetch_section,
77 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
78 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
79 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
80 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
81
82 .msg_get_flags = NULL,
83};
84
85mailmessage_driver * data_message_driver = &local_data_message_driver;
86
87
88
89mailmessage * data_message_init(char * data, size_t len)
90{
91 struct generic_message_t * msg_data;
92 mailmessage * msg;
93 int r;
94
95 msg = mailmessage_new();
96 if (msg == NULL)
97 goto err;
98
99 r = mailmessage_init(msg, NULL, data_message_driver, 0, len);
100 if (r < 0)
101 goto free;
102
103 msg_data = msg->msg_data;
104 msg_data->msg_fetched = 1;
105 msg_data->msg_message = data;
106 msg_data->msg_length = len;
107
108 return msg;
109
110 free:
111 mailmessage_free(msg);
112 err:
113 return NULL;
114}
115
116void data_message_detach_mime(mailmessage * msg)
117{
118 msg->msg_mime = NULL;
119}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DATA_MESSAGE_DRIVER_H
37
38#define DATA_MESSAGE_DRIVER_H
39
40#include <libetpan/mailmessage.h>
41
42#define LIBETPAN_DATA_MESSAGE
43
44extern mailmessage_driver * data_message_driver;
45
46mailmessage * data_message_init(char * data, size_t len);
47
48void data_message_detach_mime(mailmessage * msg);
49
50#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "dbdriver.h"
37#include "imfcache.h"
38#include "generic_cache.h"
39#include "libetpan-config.h"
40#include "dbdriver_message.h"
41#include "mail_cache_db.h"
42#include <string.h>
43#include <stdlib.h>
44#include "mailmessage.h"
45
46static int initialize(mailsession * session);
47
48static void uninitialize(mailsession * session);
49
50static int connect_path(mailsession * session, char * path);
51
52static int logout(mailsession * session);
53
54static int expunge_folder(mailsession * session);
55
56static int status_folder(mailsession * session, char * mb,
57 uint32_t * result_messages, uint32_t * result_recent,
58 uint32_t * result_unseen);
59
60static int recent_number(mailsession * session, char * mb,
61 uint32_t * result);
62
63static int unseen_number(mailsession * session, char * mb,
64 uint32_t * result);
65
66static int messages_number(mailsession * session, char * mb,
67 uint32_t * result);
68
69static int append_message(mailsession * session,
70 char * message, size_t size);
71
72static int append_message_flags(mailsession * session,
73 char * message, size_t size, struct mail_flags * flags);
74
75static int get_messages_list(mailsession * session,
76 struct mailmessage_list ** result);
77
78static int get_envelopes_list(mailsession * session,
79 struct mailmessage_list * env_list);
80
81static int check_folder(mailsession * session);
82
83static int get_message(mailsession * session,
84 uint32_t num, mailmessage ** result);
85
86static int get_message_by_uid(mailsession * session,
87 const char * uid, mailmessage ** result);
88
89static mailsession_driver local_db_session_driver = {
90 .sess_name = "db",
91
92 .sess_initialize = initialize,
93 .sess_uninitialize = uninitialize,
94
95 .sess_parameters = NULL,
96
97 .sess_connect_stream = NULL,
98 .sess_connect_path = connect_path,
99 .sess_starttls = NULL,
100 .sess_login = NULL,
101 .sess_logout = logout,
102 .sess_noop = NULL,
103
104 .sess_build_folder_name = NULL,
105 .sess_create_folder = NULL,
106 .sess_delete_folder = NULL,
107 .sess_rename_folder = NULL,
108 .sess_check_folder = check_folder,
109 .sess_examine_folder = NULL,
110 .sess_select_folder = NULL,
111 .sess_expunge_folder = expunge_folder,
112 .sess_status_folder = status_folder,
113 .sess_messages_number = messages_number,
114 .sess_recent_number = recent_number,
115 .sess_unseen_number = unseen_number,
116 .sess_list_folders = NULL,
117 .sess_lsub_folders = NULL,
118 .sess_subscribe_folder = NULL,
119 .sess_unsubscribe_folder = NULL,
120
121 .sess_append_message = append_message,
122 .sess_append_message_flags = append_message_flags,
123 .sess_copy_message = NULL,
124 .sess_move_message = NULL,
125
126 .sess_get_messages_list = get_messages_list,
127 .sess_get_envelopes_list = get_envelopes_list,
128 .sess_remove_message = NULL,
129
130 .sess_get_message = get_message,
131 .sess_get_message_by_uid = get_message_by_uid,
132};
133
134mailsession_driver * db_session_driver = &local_db_session_driver;
135
136static inline struct db_session_state_data * get_data(mailsession * session)
137{
138 return session->sess_data;
139}
140
141static int flags_store_process(mailsession * session)
142{
143 unsigned int i;
144 MMAPString * mmapstr;
145 int r;
146 int res;
147 struct mail_cache_db * maildb;
148 struct db_session_state_data * data;
149 struct mail_flags_store * flags_store;
150
151 data = get_data(session);
152
153 flags_store = data->db_flags_store;
154
155 if (carray_count(flags_store->fls_tab) == 0)
156 return MAIL_NO_ERROR;
157
158 mmapstr = mmap_string_new("");
159 if (mmapstr == NULL) {
160 res = MAIL_ERROR_MEMORY;
161 goto err;
162 }
163
164 r = mail_cache_db_open_lock(data->db_filename, &maildb);
165 if (r < 0) {
166 res = MAIL_ERROR_FILE;
167 goto free_mmapstr;
168 }
169
170 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
171 mailmessage * msg;
172 char key[PATH_MAX];
173
174 msg = carray_get(flags_store->fls_tab, i);
175
176 snprintf(key, sizeof(key), "%lu-flags", (unsigned long) msg->msg_index);
177
178 r = generic_cache_flags_write(maildb, mmapstr,
179 key, msg->msg_flags);
180 }
181
182 mail_flags_store_clear(flags_store);
183
184 mail_cache_db_close_unlock(data->db_filename, maildb);
185 mmap_string_free(mmapstr);
186
187 return MAIL_NO_ERROR;
188
189 free_mmapstr:
190 mmap_string_free(mmapstr);
191 err:
192 return res;
193}
194
195static int db_get_next_validity(struct mail_cache_db * maildb,
196 uint32_t * p_validity)
197{
198 int r;
199 char key_value[PATH_MAX];
200 uint32_t validity;
201 void * serialized;
202 size_t serialized_len;
203 int res;
204 MMAPString * mmapstr;
205 size_t cur_token;
206
207 mmapstr = mmap_string_new_len(serialized, serialized_len);
208 if (mmapstr == NULL) {
209 res = MAIL_ERROR_MEMORY;
210 goto err;
211 }
212
213 snprintf(key_value, sizeof(key_value), "next-validity");
214
215 r = mail_cache_db_get(maildb, key_value, strlen(key_value),
216 &serialized, &serialized_len);
217
218 if (r >= 0) {
219 size_t cur_token;
220
221 cur_token = 0;
222 r = mailimf_cache_int_read(mmapstr, &cur_token, &validity);
223 if (r < 0)
224 validity = 0;
225 }
226 else {
227 validity = 0;
228 }
229
230 mmap_string_set_size(mmapstr, 0);
231 cur_token = 0;
232 r = mailimf_cache_int_write(mmapstr, &cur_token, validity + 1);
233 if (r < 0) {
234 res = MAIL_ERROR_MEMORY;
235 goto free_mmapstr;
236 }
237
238 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
239 mmapstr->str, mmapstr->len);
240 if (r < 0) {
241 res = MAIL_ERROR_FILE;
242 goto free_mmapstr;
243 }
244
245 mmap_string_free(mmapstr);
246
247 * p_validity = validity;
248
249 return MAIL_NO_ERROR;
250
251 free_mmapstr:
252 mmap_string_free(mmapstr);
253 err:
254 return res;
255}
256
257static int db_get_next_msg_number(struct mail_cache_db * maildb,
258 uint32_t * p_num)
259{
260 int r;
261 char key_value[PATH_MAX];
262 uint32_t num;
263 void * serialized;
264 size_t serialized_len;
265 int res;
266 MMAPString * mmapstr;
267 size_t cur_token;
268
269 mmapstr = mmap_string_new("");
270 if (mmapstr == NULL) {
271 res = MAIL_ERROR_MEMORY;
272 goto err;
273 }
274
275 snprintf(key_value, sizeof(key_value), "next-msg");
276
277 r = mail_cache_db_get(maildb, key_value, strlen(key_value),
278 &serialized, &serialized_len);
279
280 if (r >= 0) {
281 size_t cur_token;
282
283 if (mmap_string_append_len(mmapstr, serialized, serialized_len) == NULL) {
284 res = MAIL_ERROR_MEMORY;
285 goto err;
286 }
287
288 cur_token = 0;
289 r = mailimf_cache_int_read(mmapstr, &cur_token, &num);
290 if (r < 0)
291 num = 1;
292 }
293 else {
294 num = 1;
295 }
296
297 mmap_string_set_size(mmapstr, 0);
298 cur_token = 0;
299 r = mailimf_cache_int_write(mmapstr, &cur_token, num + 1);
300 if (r < 0) {
301 res = MAIL_ERROR_MEMORY;
302 goto free_mmapstr;
303 }
304
305 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
306 mmapstr->str, mmapstr->len);
307 if (r < 0) {
308 res = MAIL_ERROR_FILE;
309 goto free_mmapstr;
310 }
311
312 mmap_string_free(mmapstr);
313
314 * p_num = num;
315
316 return MAIL_NO_ERROR;
317
318 free_mmapstr:
319 mmap_string_free(mmapstr);
320 err:
321 return res;
322}
323
324static int db_set_message_list(struct mail_cache_db * maildb,
325 carray * msglist)
326{
327 MMAPString * mmapstr;
328 char key_value[PATH_MAX];
329 int r;
330 unsigned int i;
331 size_t cur_token;
332 int res;
333
334 mmapstr = mmap_string_new("");
335 if (mmapstr == NULL) {
336 res = MAIL_ERROR_MEMORY;
337 goto err;
338 }
339
340 cur_token = 0;
341 for(i = 0 ; i < carray_count(msglist) ; i ++) {
342 uint32_t * msg;
343
344 msg = carray_get(msglist, i);
345 r = mailimf_cache_int_write(mmapstr, &cur_token, * msg);
346 if (r != MAIL_NO_ERROR) {
347 res = r;
348 goto free_mmapstr;
349 }
350 }
351
352 snprintf(key_value, sizeof(key_value), "message-list");
353 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
354 mmapstr->str, mmapstr->len);
355 if (r < 0) {
356 res = MAIL_ERROR_FILE;
357 goto err;
358 }
359
360 mmap_string_free(mmapstr);
361
362 return MAIL_NO_ERROR;
363
364 free_mmapstr:
365 mmap_string_free(mmapstr);
366 err:
367 return res;
368}
369
370static int db_get_message_list(struct mail_cache_db * maildb,
371 carray ** p_msglist)
372{
373 carray * msglist;
374 void * serialized;
375 size_t serialized_len;
376 int r;
377 char key_value[PATH_MAX];
378 int res;
379 unsigned int i;
380
381 msglist = carray_new(16);
382 if (msglist == NULL) {
383 res = MAIL_ERROR_MEMORY;
384 goto err;
385 }
386
387 snprintf(key_value, sizeof(key_value), "message-list");
388 r = mail_cache_db_get(maildb, key_value, strlen(key_value),
389 &serialized, &serialized_len);
390 if (r >= 0) {
391 MMAPString * mmapstr;
392 size_t cur_token;
393
394 /* collect message list */
395
396 mmapstr = mmap_string_new_len(serialized, serialized_len);
397 if (mmapstr == NULL) {
398 res = MAIL_ERROR_MEMORY;
399 goto free_msglist;
400 }
401
402 cur_token = 0;
403 do {
404 uint32_t num;
405 uint32_t * msg;
406
407 r = mailimf_cache_int_read(mmapstr, &cur_token, &num);
408 if (r != MAIL_NO_ERROR)
409 break;
410
411 msg = malloc(sizeof(* msg));
412 if (msg == NULL) {
413 res = MAIL_ERROR_MEMORY;
414 mmap_string_free(mmapstr);
415 goto free_msglist;
416 }
417 * msg = num;
418
419 r = carray_add(msglist, msg, NULL);
420 if (r < 0) {
421 res = MAIL_ERROR_MEMORY;
422 free(msg);
423 mmap_string_free(mmapstr);
424 goto free_msglist;
425 }
426 } while (1);
427
428 mmap_string_free(mmapstr);
429 }
430
431 * p_msglist = msglist;
432
433 return MAIL_NO_ERROR;
434
435 free_msglist:
436 for(i = 0 ; i < carray_count(msglist) ; i ++) {
437 uint32_t * msg;
438
439 msg = carray_get(msglist, i);
440 free(msg);
441 }
442 carray_free(msglist);
443 err:
444 return res;
445}
446
447static int initialize(mailsession * session)
448{
449 struct db_session_state_data * data;
450
451 data = malloc(sizeof(* data));
452 if (data == NULL)
453 goto err;
454
455 data->db_filename[0] = '\0';
456
457 data->db_flags_store = mail_flags_store_new();
458 if (data->db_flags_store == NULL)
459 goto free;
460
461 session->sess_data = data;
462
463 return MAIL_NO_ERROR;
464
465 free:
466 free(data);
467 err:
468 return MAIL_ERROR_MEMORY;
469}
470
471static void uninitialize(mailsession * session)
472{
473 struct db_session_state_data * data;
474
475 data = get_data(session);
476
477 flags_store_process(session);
478
479 mail_flags_store_free(data->db_flags_store);
480
481 free(data);
482
483 session->sess_data = NULL;
484}
485
486static int connect_path(mailsession * session, char * path)
487{
488 struct db_session_state_data * data;
489
490 data = get_data(session);
491
492 strncpy(data->db_filename, path, sizeof(data->db_filename));
493
494 return MAIL_NO_ERROR;
495}
496
497static int logout(mailsession * session)
498{
499 return MAIL_NO_ERROR;
500}
501
502static int expunge_folder(mailsession * session)
503{
504 int r;
505 char key_value[PATH_MAX];
506 struct mail_cache_db * maildb;
507 carray * msglist;
508 unsigned int i;
509 struct db_session_state_data * data;
510 int res;
511 chash * msg_table;
512 MMAPString * mmapstr;
513
514 data = get_data(session);
515
516 flags_store_process(session);
517
518 r = mail_cache_db_open_lock(data->db_filename, &maildb);
519 if (r < 0) {
520 res = MAIL_ERROR_FILE;
521 goto err;
522 }
523
524 r = db_get_message_list(maildb, &msglist);
525 if (r != MAIL_NO_ERROR) {
526 res = r;
527 goto close_db;
528 }
529
530 msg_table = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
531 if (msg_table == NULL) {
532 res = MAIL_ERROR_MEMORY;
533 goto free_msglist;
534 }
535
536 mmapstr = mmap_string_new("");
537 if (mmapstr == NULL) {
538 res = MAIL_ERROR_MEMORY;
539 goto free_msgtable;
540 }
541
542 i = 0;
543 while (i < carray_count(msglist)) {
544 uint32_t num;
545 uint32_t * msg;
546 chashdatum key;
547 chashdatum value;
548 struct mail_flags * flags;
549 int deleted;
550
551 msg = carray_get(msglist, i);
552 num = * msg;
553
554 deleted = 0;
555 snprintf(key_value, sizeof(key_value), "%lu-flags",
556 (unsigned long) num);
557 r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags);
558 if (r == MAIL_NO_ERROR) {
559 if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0)
560 deleted = 1;
561 }
562
563 if (!deleted) {
564 snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num);
565 key.data = key_value;
566 key.len = strlen(key_value);
567 chash_set(msg_table, &key, &value, NULL);
568
569 snprintf(key_value, sizeof(key_value), "%lu-envelope",
570 (unsigned long) num);
571 key.data = key_value;
572 key.len = strlen(key_value);
573 chash_set(msg_table, &key, &value, NULL);
574
575 snprintf(key_value, sizeof(key_value), "%lu-flags",
576 (unsigned long) num);
577 key.data = key_value;
578 key.len = strlen(key_value);
579 chash_set(msg_table, &key, &value, NULL);
580
581 i ++;
582 }
583 else {
584 free(msg);
585 carray_delete(msglist, i);
586 }
587 }
588
589 mmap_string_free(mmapstr);
590
591 r = mail_cache_db_clean_up(maildb, msg_table);
592
593 chash_free(msg_table);
594
595 r = db_set_message_list(maildb, msglist);
596
597 for(i = 0 ; i < carray_count(msglist) ; i ++) {
598 uint32_t * msg;
599
600 msg = carray_get(msglist, i);
601 free(msg);
602 }
603 carray_free(msglist);
604
605 mail_cache_db_close_unlock(data->db_filename, maildb);
606
607 return MAIL_NO_ERROR;
608
609 free_msgtable:
610 chash_free(msg_table);
611 free_msglist:
612 for(i = 0 ; i < carray_count(msglist) ; i ++) {
613 uint32_t * msg;
614
615 msg = carray_get(msglist, i);
616 free(msg);
617 }
618 close_db:
619 mail_cache_db_close_unlock(data->db_filename, maildb);
620 err:
621 return res;
622}
623
624static int status_folder(mailsession * session, char * mb,
625 uint32_t * result_messages, uint32_t * result_recent,
626 uint32_t * result_unseen)
627{
628 struct mail_cache_db * maildb;
629 char key_value[PATH_MAX];
630 MMAPString * mmapstr;
631 uint32_t messages;
632 uint32_t recent;
633 uint32_t unseen;
634 struct db_session_state_data * data;
635 int r;
636 int res;
637 carray * msglist;
638 unsigned int i;
639
640 data = get_data(session);
641
642 flags_store_process(session);
643
644 r = mail_cache_db_open_lock(data->db_filename, &maildb);
645 if (r < 0) {
646 res = MAIL_ERROR_FILE;
647 goto err;
648 }
649
650 r = db_get_message_list(maildb, &msglist);
651 if (r != MAIL_NO_ERROR) {
652 res = r;
653 goto close_db;
654 }
655
656 mmapstr = mmap_string_new("");
657 if (mmapstr == NULL) {
658 res = MAIL_ERROR_MEMORY;
659 goto free_list;
660 }
661
662 messages = 0;
663 recent = 0;
664 unseen = 0;
665 for(i = 0 ; i < carray_count(msglist) ; i ++) {
666 uint32_t num;
667 uint32_t * msg;
668 int r;
669 struct mail_flags * flags;
670
671 msg = carray_get(msglist, i);
672 num = * msg;
673 free(msg);
674 carray_set(msglist, i, NULL);
675
676 messages ++;
677
678 snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num);
679
680 r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags);
681 if (r == MAIL_NO_ERROR) {
682 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
683 recent ++;
684 }
685 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
686 unseen ++;
687 }
688 mail_flags_free(flags);
689 }
690 }
691
692 mmap_string_free(mmapstr);
693
694 carray_free(msglist);
695
696 mail_cache_db_close_unlock(data->db_filename, maildb);
697
698 * result_messages = messages;
699 * result_unseen = unseen;
700 * result_recent = recent;
701
702 return MAIL_NO_ERROR;
703
704 free_list:
705 for(i = 0 ; i < carray_count(msglist) ; i ++) {
706 uint32_t * msg;
707
708 msg = carray_get(msglist, i);
709 if (msg != NULL)
710 free(msg);
711 }
712 carray_free(msglist);
713 close_db:
714 mail_cache_db_close_unlock(data->db_filename, maildb);
715 err:
716 return res;
717}
718
719static int recent_number(mailsession * session, char * mb,
720 uint32_t * result)
721{
722 uint32_t dummy_messages;
723 uint32_t dummy_unseen;
724
725 return status_folder(session, mb,
726 &dummy_messages, result, &dummy_unseen);
727}
728
729static int unseen_number(mailsession * session, char * mb,
730 uint32_t * result)
731{
732 uint32_t dummy_messages;
733 uint32_t dummy_recent;
734
735 return status_folder(session, mb,
736 &dummy_messages, &dummy_recent, result);
737}
738
739static int messages_number(mailsession * session, char * mb,
740 uint32_t * result)
741{
742 uint32_t dummy_unseen;
743 uint32_t dummy_recent;
744
745 return status_folder(session, mb,
746 result, &dummy_recent, &dummy_unseen);
747}
748
749static int append_message(mailsession * session,
750 char * message, size_t size)
751{
752 return append_message_flags(session, message, size, NULL);
753}
754
755static int append_message_flags(mailsession * session,
756 char * message, size_t size, struct mail_flags * flags)
757{
758 carray * msglist;
759 unsigned int i;
760 uint32_t * msg;
761 uint32_t num;
762 char key_value[PATH_MAX];
763 MMAPString * mmapstr;
764 struct mail_cache_db * maildb;
765 struct db_session_state_data * data;
766 size_t cur_token;
767 struct mailimf_fields * fields;
768 int r;
769 int res;
770
771 data = get_data(session);
772
773 r = mail_cache_db_open_lock(data->db_filename, &maildb);
774 if (r < 0) {
775 res = MAIL_ERROR_FILE;
776 goto err;
777 }
778
779 r = db_get_next_msg_number(maildb, &num);
780 if (r != MAIL_NO_ERROR) {
781 res = r;
782 goto err;
783 }
784
785 r = db_get_message_list(maildb, &msglist);
786 if (r != MAIL_NO_ERROR) {
787 res = r;
788 goto close_db;
789 }
790
791 msg = malloc(sizeof(* msg));
792 if (msg == NULL) {
793 res = MAIL_ERROR_MEMORY;
794 goto free_msglist;
795 }
796
797 * msg = num;
798
799 r = carray_add(msglist, msg, NULL);
800 if (r < 0) {
801 res = MAIL_ERROR_MEMORY;
802 free(msg);
803 goto free_msglist;
804 }
805
806 r = db_set_message_list(maildb, msglist);
807 if (r != MAIL_NO_ERROR) {
808 res = r;
809 goto free_msglist;
810 }
811
812 /* free msglist */
813
814 for(i = 0 ; i < carray_count(msglist) ; i ++) {
815 uint32_t * msg;
816
817 msg = carray_get(msglist, i);
818 free(msg);
819 }
820 carray_free(msglist);
821
822 snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num);
823
824 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
825 message, size);
826 if (r < 0) {
827 res = MAIL_ERROR_FILE;
828 goto close_db;
829 }
830
831 /* write envelope */
832
833 cur_token = 0;
834 r = mailimf_envelope_fields_parse(message, size, &cur_token, &fields);
835 if (r != MAILIMF_NO_ERROR) {
836 res = MAIL_ERROR_PARSE;
837 goto close_db;
838 }
839
840 mmapstr = mmap_string_new("");
841 if (mmapstr == NULL) {
842 res = MAIL_ERROR_MEMORY;
843 goto close_db;
844 }
845
846 cur_token = 0;
847 r = mailimf_cache_fields_write(mmapstr, &cur_token, fields);
848 if (r != MAIL_NO_ERROR) {
849 res = r;
850 mmap_string_free(mmapstr);
851 goto close_db;
852 }
853
854 snprintf(key_value, sizeof(key_value), "%lu-envelope", (unsigned long) num);
855
856 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
857 mmapstr->str, mmapstr->len);
858
859 mmap_string_free(mmapstr);
860
861 mailimf_fields_free(fields);
862
863 /* write flags */
864
865 if (flags != NULL) {
866 snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num);
867
868 mmapstr = mmap_string_new("");
869 if (mmapstr == NULL) {
870 res = MAIL_ERROR_MEMORY;
871 goto close_db;
872 }
873
874 r = generic_cache_flags_write(maildb, mmapstr,
875 key_value, flags);
876
877 mmap_string_free(mmapstr);
878
879 if (r != MAIL_NO_ERROR) {
880 res = MAIL_ERROR_FILE;
881 goto close_db;
882 }
883 }
884
885 mail_cache_db_close_unlock(data->db_filename, maildb);
886
887 return MAIL_NO_ERROR;
888
889 free_msglist:
890 for(i = 0 ; i < carray_count(msglist) ; i ++) {
891 uint32_t * msg;
892
893 msg = carray_get(msglist, i);
894 free(msg);
895 }
896 carray_free(msglist);
897 close_db:
898 mail_cache_db_close_unlock(data->db_filename, maildb);
899 err:
900 return res;
901}
902
903static int get_messages_list(mailsession * session,
904 struct mailmessage_list ** result)
905{
906 int r;
907 char key[PATH_MAX];
908 struct mail_cache_db * maildb;
909 struct db_session_state_data * data;
910 int res;
911 carray * msglist;
912 unsigned int i;
913 carray * msgtab;
914 struct mailmessage_list * driver_msglist;
915
916 data = get_data(session);
917
918 r = mail_cache_db_open_lock(data->db_filename, &maildb);
919 if (r < 0) {
920 res = MAIL_ERROR_FILE;
921 goto err;
922 }
923
924 r = db_get_message_list(maildb, &msglist);
925 if (r != MAIL_NO_ERROR) {
926 res = r;
927 goto close_db;
928 }
929
930 msgtab = carray_new(16);
931 if (msgtab == NULL) {
932 res = MAIL_ERROR_MEMORY;
933 goto close_db;
934 }
935
936 for(i = 0 ; i < carray_count(msglist) ; i ++) {
937 uint32_t msg_num;
938 uint32_t * pmsg_num;
939 mailmessage * msg;
940 size_t size;
941
942 pmsg_num = carray_get(msglist, i);
943 msg_num = * pmsg_num;
944 free(pmsg_num);
945 carray_set(msglist, i, NULL);
946
947 snprintf(key, sizeof(key), "%lu", (unsigned long) msg_num);
948 r = mail_cache_db_get_size(maildb, key, strlen(key), &size);
949 if (r < 0) {
950 continue;
951 }
952
953 msg = mailmessage_new();
954 if (msg == NULL) {
955 res = MAIL_ERROR_MEMORY;
956 goto free_list;
957 }
958
959 r = mailmessage_init(msg, session, db_message_driver,
960 msg_num, size);
961 if (r != MAIL_NO_ERROR) {
962 mailmessage_free(msg);
963 res = r;
964 goto free_list;
965 }
966
967 r = carray_add(msgtab, msg, NULL);
968 if (r < 0) {
969 mailmessage_free(msg);
970 res = MAIL_ERROR_MEMORY;
971 goto free_list;
972 }
973 }
974 carray_free(msglist);
975
976 driver_msglist = mailmessage_list_new(msgtab);
977 if (driver_msglist == NULL) {
978 res = MAIL_ERROR_MEMORY;
979 goto free_list;
980 }
981
982 mail_cache_db_close_unlock(data->db_filename, maildb);
983
984 * result = driver_msglist;
985
986 return MAIL_NO_ERROR;
987
988 free_list:
989 for(i = 0 ; i < carray_count(msgtab) ; i ++) {
990 mailmessage * msg;
991
992 msg = carray_get(msgtab, i);
993 mailmessage_free(msg);
994 }
995 carray_free(msgtab);
996
997 for(i = 0 ; i < carray_count(msglist) ; i ++) {
998 uint32_t * msg;
999
1000 msg = carray_get(msglist, i);
1001 if (msg != NULL)
1002 free(msg);
1003 }
1004 carray_free(msglist);
1005 close_db:
1006 mail_cache_db_close_unlock(data->db_filename, maildb);
1007 err:
1008 return res;
1009}
1010
1011static int get_envelopes_list(mailsession * session,
1012 struct mailmessage_list * env_list)
1013{
1014 unsigned int i;
1015 char key[PATH_MAX];
1016 int r;
1017 struct mail_cache_db * maildb;
1018 int res;
1019 struct db_session_state_data * data;
1020 MMAPString * mmapstr;
1021
1022 data = get_data(session);
1023
1024 flags_store_process(session);
1025
1026 r = mail_cache_db_open_lock(data->db_filename, &maildb);
1027 if (r < 0) {
1028 res = MAIL_ERROR_FILE;
1029 goto err;
1030 }
1031
1032 mmapstr = mmap_string_new("");
1033 if (mmapstr == NULL) {
1034 res = MAIL_ERROR_MEMORY;
1035 goto close_db;
1036 }
1037
1038 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1039 mailmessage * msg;
1040
1041 msg = carray_get(env_list->msg_tab, i);
1042 if (msg->msg_fields == NULL) {
1043 snprintf(key, sizeof(key), "%lu-envelope",
1044 (unsigned long) msg->msg_index);
1045
1046 r = generic_cache_fields_read(maildb, mmapstr,
1047 key, &msg->msg_fields);
1048 }
1049
1050 if (msg->msg_flags == NULL) {
1051 snprintf(key, sizeof(key), "%lu-flags",
1052 (unsigned long) msg->msg_index);
1053
1054 r = generic_cache_flags_read(maildb, mmapstr,
1055 key, &msg->msg_flags);
1056 }
1057 }
1058
1059 mmap_string_free(mmapstr);
1060
1061 mail_cache_db_close_unlock(data->db_filename, maildb);
1062
1063 return MAIL_NO_ERROR;
1064
1065 close_db:
1066 mail_cache_db_close_unlock(data->db_filename, maildb);
1067 err:
1068 return res;
1069}
1070
1071static int check_folder(mailsession * session)
1072{
1073 flags_store_process(session);
1074
1075 return MAIL_NO_ERROR;
1076}
1077
1078static int get_message(mailsession * session,
1079 uint32_t num, mailmessage ** result)
1080{
1081 mailmessage * msg;
1082 int r;
1083 size_t size;
1084 char key[PATH_MAX];
1085 struct db_session_state_data * data;
1086 struct mail_cache_db * maildb;
1087 int res;
1088
1089 data = get_data(session);
1090
1091 r = mail_cache_db_open_lock(data->db_filename, &maildb);
1092 if (r < 0) {
1093 res = MAIL_ERROR_FILE;
1094 goto err;
1095 }
1096
1097 msg = mailmessage_new();
1098 if (msg == NULL) {
1099 res = MAIL_ERROR_MEMORY;
1100 goto close_db;
1101 }
1102
1103 size = 0;
1104 snprintf(key, sizeof(key), "%lu", (unsigned long) num);
1105 r = mail_cache_db_get_size(maildb, key, strlen(key), &size);
1106 /* ignore error */
1107
1108 r = mailmessage_init(msg, session, db_message_driver,
1109 num, size);
1110 if (r != MAIL_NO_ERROR) {
1111 mailmessage_free(msg);
1112 res = r;
1113 goto close_db;
1114 }
1115
1116 mail_cache_db_close_unlock(data->db_filename, maildb);
1117
1118 return MAIL_NO_ERROR;
1119
1120 close_db:
1121 mail_cache_db_close_unlock(data->db_filename, maildb);
1122 err:
1123 return res;
1124}
1125
1126static int get_message_by_uid(mailsession * session,
1127 const char * uid, mailmessage ** result)
1128{
1129 uint32_t msg_num;
1130
1131 msg_num = strtoul(uid, NULL, 10);
1132
1133 return get_message(session, msg_num, result);
1134}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBDRIVER_H
37
38#define DBDRIVER_H
39
40#include <libetpan/dbdriver_message.h>
41#include <libetpan/dbdriver_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47extern mailsession_driver * db_session_driver;
48
49#ifdef __cplusplus
50}
51#endif
52
53#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "dbdriver_message.h"
37#include "dbdriver.h"
38#include "mail_cache_db.h"
39
40#include "mailmessage_tools.h"
41#include "generic_cache.h"
42
43#include <unistd.h>
44#include <sys/mman.h>
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <fcntl.h>
48#include <string.h>
49#include <stdlib.h>
50
51static int fetch_envelope(mailmessage * msg_info,
52 struct mailimf_fields ** result);
53
54static int get_flags(mailmessage * msg_info,
55 struct mail_flags ** result);
56
57static int prefetch(mailmessage * msg_info);
58
59static void prefetch_free(struct generic_message_t * msg);
60
61static int initialize(mailmessage * msg_info);
62
63static void check(mailmessage * msg_info);
64
65static mailmessage_driver local_db_message_driver = {
66 .msg_name = "db",
67
68 .msg_initialize = initialize,
69 .msg_uninitialize = mailmessage_generic_uninitialize,
70
71 .msg_flush = mailmessage_generic_flush,
72 .msg_check = check,
73
74 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
75
76 .msg_fetch = mailmessage_generic_fetch,
77 .msg_fetch_header = mailmessage_generic_fetch_header,
78 .msg_fetch_body = mailmessage_generic_fetch_header,
79 .msg_fetch_size = NULL,
80 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
81 .msg_fetch_section = mailmessage_generic_fetch_section,
82 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
83 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
84 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
85 .msg_fetch_envelope = fetch_envelope,
86
87 .msg_get_flags = get_flags,
88};
89
90mailmessage_driver * db_message_driver = &local_db_message_driver;
91
92struct db_msg_data {
93 MMAPString * msg_content;
94};
95
96static inline struct db_session_state_data *
97get_session_data(mailmessage * msg)
98{
99 return msg->msg_session->sess_data;
100}
101
102static int prefetch(mailmessage * msg_info)
103{
104 struct generic_message_t * msg;
105 int res;
106 struct db_msg_data * data;
107 struct db_session_state_data * sess_data;
108 MMAPString * msg_content;
109 struct mail_cache_db * maildb;
110 int r;
111 char key[PATH_MAX];
112 void * msg_data;
113 size_t msg_data_len;
114
115 sess_data = get_session_data(msg_info);
116
117 r = mail_cache_db_open_lock(sess_data->db_filename, &maildb);
118 if (r < 0) {
119 res = MAIL_ERROR_FILE;
120 goto err;
121 }
122
123 snprintf(key, sizeof(key), "%lu", (unsigned long) msg_info->msg_index);
124 r = mail_cache_db_get(maildb, key, strlen(key), &msg_data, &msg_data_len);
125 if (r < 0) {
126 res = MAIL_ERROR_MSG_NOT_FOUND;
127 goto close_db;
128 }
129
130 msg_content = mmap_string_new_len(msg_data, msg_data_len);
131 if (msg_content == NULL) {
132 res = MAIL_ERROR_MEMORY;
133 goto close_db;
134 }
135
136 data = malloc(sizeof(* data));
137 if (data == NULL) {
138 res = MAIL_ERROR_MEMORY;
139 goto free_mmapstr;
140 }
141
142 data->msg_content = msg_content;
143
144 msg = msg_info->msg_data;
145
146 msg->msg_data = data;
147 msg->msg_message = msg_content->str;
148 msg->msg_length = msg_content->len;
149
150 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
151
152 return MAIL_NO_ERROR;
153
154 free_mmapstr:
155 mmap_string_free(msg_content);
156 close_db:
157 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
158 err:
159 return res;
160}
161
162static void prefetch_free(struct generic_message_t * msg)
163{
164 if (msg->msg_message != NULL) {
165 struct db_msg_data * data;
166
167 data = msg->msg_data;
168 mmap_string_free(data->msg_content);
169 data->msg_content = NULL;
170 free(data);
171 msg->msg_message = NULL;
172 }
173}
174
175static int initialize(mailmessage * msg_info)
176{
177 struct generic_message_t * msg;
178 int r;
179 char key[PATH_MAX];
180
181 snprintf(key, sizeof(key), "%lu", (unsigned long) msg_info->msg_index);
182 msg_info->msg_uid = strdup(key);
183 if (msg_info->msg_uid == NULL)
184 return MAIL_ERROR_MEMORY;
185
186 r = mailmessage_generic_initialize(msg_info);
187 if (r != MAIL_NO_ERROR)
188 return r;
189
190 msg = msg_info->msg_data;
191 msg->msg_prefetch = prefetch;
192 msg->msg_prefetch_free = prefetch_free;
193
194 return MAIL_NO_ERROR;
195}
196
197static void check(mailmessage * msg_info)
198{
199 int r;
200
201 if (msg_info->msg_flags != NULL) {
202 r = mail_flags_store_set(get_session_data(msg_info)->db_flags_store,
203 msg_info);
204 /* ignore errors */
205 }
206}
207
208static int fetch_envelope(mailmessage * msg_info,
209 struct mailimf_fields ** result)
210{
211 char key[PATH_MAX];
212 int r;
213 struct db_session_state_data * sess_data;
214 struct mail_cache_db * maildb;
215 int res;
216 struct mailimf_fields * fields;
217 MMAPString * mmapstr;
218
219 sess_data = get_session_data(msg_info);
220
221 r = mail_cache_db_open_lock(sess_data->db_filename, &maildb);
222 if (r < 0) {
223 res = MAIL_ERROR_FILE;
224 goto err;
225 }
226
227 snprintf(key, sizeof(key), "%lu-envelope",
228 (unsigned long) msg_info->msg_index);
229
230 mmapstr = mmap_string_new("");
231 if (mmapstr == NULL) {
232 res = MAIL_ERROR_MEMORY;
233 goto close_db;
234 }
235
236 r = generic_cache_fields_read(maildb, mmapstr,
237 key, &fields);
238
239 mmap_string_free(mmapstr);
240
241 if (r != MAIL_NO_ERROR) {
242 res = MAIL_ERROR_MSG_NOT_FOUND;
243 goto close_db;
244 }
245
246 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
247
248 * result = fields;
249
250 return MAIL_NO_ERROR;
251
252 close_db:
253 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
254 err:
255 return res;
256}
257
258static int get_flags(mailmessage * msg_info,
259 struct mail_flags ** result)
260{
261 char key[PATH_MAX];
262 int r;
263 struct db_session_state_data * sess_data;
264 struct mail_cache_db * maildb;
265 int res;
266 MMAPString * mmapstr;
267
268 sess_data = get_session_data(msg_info);
269
270 r = mail_cache_db_open_lock(sess_data->db_filename, &maildb);
271 if (r < 0) {
272 res = MAIL_ERROR_FILE;
273 goto err;
274 }
275
276 snprintf(key, sizeof(key), "%lu-flags", (unsigned long) msg_info->msg_index);
277
278 mmapstr = mmap_string_new("");
279 if (mmapstr == NULL) {
280 res = MAIL_ERROR_MEMORY;
281 goto close_db;
282 }
283
284 r = generic_cache_flags_read(maildb, mmapstr,
285 key, &msg_info->msg_flags);
286
287 mmap_string_free(mmapstr);
288
289 if (r != MAIL_NO_ERROR) {
290 msg_info->msg_flags = mail_flags_new_empty();
291 if (msg_info->msg_flags == NULL) {
292 res = MAIL_ERROR_MEMORY;
293 goto close_db;
294 }
295 }
296
297 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
298
299 * result = msg_info->msg_flags;
300
301 return MAIL_NO_ERROR;
302
303 close_db:
304 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
305 err:
306 return res;
307}
308
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBDRIVER_MESSAGE_H
37
38#define DBDRIVER_MESSAGE_H
39
40#include <libetpan/dbdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * db_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBDRIVER_TYPES_H
37
38#define DBDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/generic_cache_types.h>
44#include <libetpan/mailstorage_types.h>
45
46#ifdef __cplusplus
47extern "C" {
48#endif
49
50struct db_session_state_data {
51 char db_filename[PATH_MAX];
52 struct mail_flags_store * db_flags_store;
53};
54
55/* db storage */
56
57/*
58 db_mailstorage is the state data specific to the db storage.
59
60 - pathname is the path of the db storage.
61*/
62
63struct db_mailstorage {
64 char * db_pathname;
65};
66
67#ifdef __cplusplus
68}
69#endif
70
71#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "dbstorage.h"
37#include "mailstorage.h"
38
39#include "mail.h"
40#include "mailmessage.h"
41#include "dbdriver.h"
42#include "maildriver.h"
43
44#include <stdlib.h>
45#include <string.h>
46
47/* db storage */
48
49static int db_mailstorage_connect(struct mailstorage * storage);
50static int
51db_mailstorage_get_folder_session(struct mailstorage * storage,
52 char * pathname, mailsession ** result);
53static void db_mailstorage_uninitialize(struct mailstorage * storage);
54
55static mailstorage_driver db_mailstorage_driver = {
56 .sto_name = "db",
57 .sto_connect = db_mailstorage_connect,
58 .sto_get_folder_session = db_mailstorage_get_folder_session,
59 .sto_uninitialize = db_mailstorage_uninitialize,
60};
61
62int db_mailstorage_init(struct mailstorage * storage,
63 char * db_pathname)
64{
65 struct db_mailstorage * db_storage;
66
67 db_storage = malloc(sizeof(* db_storage));
68 if (db_storage == NULL)
69 goto err;
70
71 db_storage->db_pathname = strdup(db_pathname);
72 if (db_storage->db_pathname == NULL)
73 goto free;
74
75 storage->sto_data = db_storage;
76 storage->sto_driver = &db_mailstorage_driver;
77
78 return MAIL_NO_ERROR;
79
80 free:
81 free(db_storage);
82 err:
83 return MAIL_ERROR_MEMORY;
84}
85
86static void db_mailstorage_uninitialize(struct mailstorage * storage)
87{
88 struct db_mailstorage * db_storage;
89
90 db_storage = storage->sto_data;
91 free(db_storage->db_pathname);
92 free(db_storage);
93
94 storage->sto_data = NULL;
95}
96
97static int db_mailstorage_connect(struct mailstorage * storage)
98{
99 struct db_mailstorage * db_storage;
100 mailsession_driver * driver;
101 int r;
102 int res;
103 mailsession * session;
104
105 db_storage = storage->sto_data;
106
107 driver = db_session_driver;
108
109 session = mailsession_new(driver);
110 if (session == NULL) {
111 res = MAIL_ERROR_MEMORY;
112 goto err;
113 }
114
115 r = mailsession_connect_path(session, db_storage->db_pathname);
116 switch (r) {
117 case MAIL_NO_ERROR_NON_AUTHENTICATED:
118 case MAIL_NO_ERROR_AUTHENTICATED:
119 case MAIL_NO_ERROR:
120 break;
121 default:
122 res = r;
123 goto free;
124 }
125
126 storage->sto_session = session;
127
128 return MAIL_NO_ERROR;
129
130 free:
131 mailsession_free(session);
132 err:
133 return res;
134}
135
136static int
137db_mailstorage_get_folder_session(struct mailstorage * storage,
138 char * pathname, mailsession ** result)
139{
140 * result = storage->sto_session;
141
142 return MAIL_NO_ERROR;
143}
144
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBSTORAGE_H
37
38#define DBSTORAGE_H
39
40#include <libetpan/dbdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 db_mailstorage_init is the constructor for a DB storage.
48
49 @param storage this is the storage to initialize.
50
51 @param pathname is the directory that contains the mailbox.
52*/
53
54int db_mailstorage_init(struct mailstorage * storage,
55 char * db_pathname);
56
57#ifdef __cplusplus
58}
59#endif
60
61#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "hotmailstorage.h"
37
38#include "pop3storage.h"
39#include "pop3driver_types.h"
40
41/*
42 hotway is a gateway from hotmail to POP3
43
44 http://hotwayd.sourceforge.net/
45*/
46
47static char hotway_command[512] = "/usr/bin/hotwayd";
48
49int hotmail_mailstorage_init(struct mailstorage * storage,
50 char * hotmail_login, char * hotmail_password,
51 int hotmail_cached, char * hotmail_cache_directory,
52 char * hotmail_flags_directory)
53{
54 return pop3_mailstorage_init(storage,
55 "hotmail.dummy", 0,
56 hotway_command,
57 CONNECTION_TYPE_COMMAND, POP3_AUTH_TYPE_PLAIN,
58 hotmail_login, hotmail_password,
59 hotmail_cached, hotmail_cache_directory,
60 hotmail_flags_directory);
61}
62
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef HOTMAILSTORAGE_H
37
38#define HOTMAILSTORAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailstorage_types.h"
45
46int hotmail_mailstorage_init(struct mailstorage * storage,
47 char * hotmail_login, char * hotmail_password,
48 int hotmail_cached, char * hotmail_cache_directory,
49 char * hotmail_flags_directory);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
56
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver.h"
37
38#include "mail.h"
39#include "imapdriver_tools.h"
40#include "mailmessage.h"
41#include "imapdriver_message.h"
42#include "imapdriver_types.h"
43#include "maildriver.h"
44#include "maildriver_tools.h"
45#include "generic_cache.h"
46
47#include <stdlib.h>
48#include <string.h>
49
50static int imapdriver_initialize(mailsession * session);
51
52static void imapdriver_uninitialize(mailsession * session);
53
54static int imapdriver_connect_stream(mailsession * session, mailstream * s);
55
56static int imapdriver_starttls(mailsession * session);
57
58static int imapdriver_login(mailsession * session,
59 char * userid, char * password);
60
61static int imapdriver_logout(mailsession * session);
62
63static int imapdriver_noop(mailsession * session);
64
65static int imapdriver_build_folder_name(mailsession * session, char * mb,
66 char * name, char ** result);
67
68static int imapdriver_create_folder(mailsession * session, char * mb);
69
70static int imapdriver_delete_folder(mailsession * session, char * mb);
71
72static int imapdriver_rename_folder(mailsession * session, char * mb,
73 char * new_name);
74
75static int imapdriver_check_folder(mailsession * session);
76
77static int imapdriver_examine_folder(mailsession * session, char * mb);
78
79static int imapdriver_select_folder(mailsession * session, char * mb);
80static int imapdriver_expunge_folder(mailsession * session);
81
82static int imapdriver_status_folder(mailsession * session, char * mb,
83 uint32_t * result_messages, uint32_t * result_recent,
84 uint32_t * result_unseen);
85
86static int imapdriver_messages_number(mailsession * session, char * mb,
87 uint32_t * result);
88
89static int imapdriver_recent_number(mailsession * session, char * mb,
90 uint32_t * result);
91
92static int imapdriver_unseen_number(mailsession * session, char * mb,
93 uint32_t * result);
94
95static int imapdriver_list_folders(mailsession * session, char * mb,
96 struct mail_list ** result);
97static int imapdriver_lsub_folders(mailsession * session, char * mb,
98 struct mail_list ** result);
99static int imapdriver_subscribe_folder(mailsession * session, char * mb);
100static int imapdriver_unsubscribe_folder(mailsession * session, char * mb);
101static int imapdriver_append_message(mailsession * session,
102 char * message, size_t size);
103static int imapdriver_append_message_flags(mailsession * session,
104 char * message, size_t size, struct mail_flags * flags);
105static int imapdriver_copy_message(mailsession * session,
106 uint32_t num, char * mb);
107
108static int imapdriver_get_messages_list(mailsession * session,
109 struct mailmessage_list ** result);
110
111static int
112imapdriver_get_envelopes_list(mailsession * session,
113 struct mailmessage_list * env_list);
114
115
116#if 0
117static int imapdriver_search_messages(mailsession * session, char * charset,
118 struct mail_search_key * key,
119 struct mail_search_result ** result);
120#endif
121
122static int imapdriver_get_message(mailsession * session,
123 uint32_t num, mailmessage ** result);
124
125static int imapdriver_get_message_by_uid(mailsession * session,
126 const char * uid,
127 mailmessage ** result);
128
129static mailsession_driver local_imap_session_driver = {
130 .sess_name = "imap",
131
132 .sess_initialize = imapdriver_initialize,
133 .sess_uninitialize = imapdriver_uninitialize,
134
135 .sess_parameters = NULL,
136
137 .sess_connect_stream = imapdriver_connect_stream,
138 .sess_connect_path = NULL,
139 .sess_starttls = imapdriver_starttls,
140 .sess_login = imapdriver_login,
141 .sess_logout = imapdriver_logout,
142 .sess_noop = imapdriver_noop,
143
144 .sess_build_folder_name = imapdriver_build_folder_name,
145 .sess_create_folder = imapdriver_create_folder,
146 .sess_delete_folder = imapdriver_delete_folder,
147 .sess_rename_folder = imapdriver_rename_folder,
148 .sess_check_folder = imapdriver_check_folder,
149 .sess_examine_folder = imapdriver_examine_folder,
150 .sess_select_folder = imapdriver_select_folder,
151 .sess_expunge_folder = imapdriver_expunge_folder,
152 .sess_status_folder = imapdriver_status_folder,
153 .sess_messages_number = imapdriver_messages_number,
154 .sess_recent_number = imapdriver_recent_number,
155 .sess_unseen_number = imapdriver_unseen_number,
156 .sess_list_folders = imapdriver_list_folders,
157 .sess_lsub_folders = imapdriver_lsub_folders,
158 .sess_subscribe_folder = imapdriver_subscribe_folder,
159 .sess_unsubscribe_folder = imapdriver_unsubscribe_folder,
160
161 .sess_append_message = imapdriver_append_message,
162 .sess_append_message_flags = imapdriver_append_message_flags,
163 .sess_copy_message = imapdriver_copy_message,
164 .sess_move_message = NULL,
165
166 .sess_get_messages_list = imapdriver_get_messages_list,
167 .sess_get_envelopes_list = imapdriver_get_envelopes_list,
168 .sess_remove_message = NULL,
169#if 0
170 .sess_search_messages = imapdriver_search_messages,
171#endif
172
173 .sess_get_message = imapdriver_get_message,
174 .sess_get_message_by_uid = imapdriver_get_message_by_uid,
175};
176
177mailsession_driver * imap_session_driver = &local_imap_session_driver;
178
179static inline struct imap_session_state_data * get_data(mailsession * session)
180{
181 return session->sess_data;
182}
183
184static mailimap * get_imap_session(mailsession * session)
185{
186 return get_data(session)->imap_session;
187}
188
189static int imapdriver_initialize(mailsession * session)
190{
191 struct imap_session_state_data * data;
192 mailimap * imap;
193 struct mail_flags_store * flags_store;
194
195 imap = mailimap_new(0, NULL);
196 if (imap == NULL)
197 goto err;
198
199 flags_store = mail_flags_store_new();
200 if (flags_store == NULL)
201 goto free_session;
202
203 data = malloc(sizeof(* data));
204 if (data == NULL)
205 goto free_flags_store;
206
207 data->imap_mailbox = NULL;
208 data->imap_session = imap;
209 data->imap_flags_store = flags_store;
210
211 session->sess_data = data;
212
213 return MAIL_NO_ERROR;
214
215 free_flags_store:
216 mail_flags_store_free(flags_store);
217 free_session:
218 mailimap_free(imap);
219 err:
220 return MAIL_ERROR_MEMORY;
221}
222
223static void imap_flags_store_process(mailimap * imap,
224 struct mail_flags_store * flags_store)
225{
226 unsigned int i;
227 int r;
228 mailmessage * first;
229 mailmessage * last;
230
231 mail_flags_store_sort(flags_store);
232
233 if (carray_count(flags_store->fls_tab) == 0)
234 return;
235
236 first = carray_get(flags_store->fls_tab, 0);
237 last = first;
238
239 for(i = 1 ; i < carray_count(flags_store->fls_tab) ; i ++) {
240 mailmessage * msg;
241
242 msg = carray_get(flags_store->fls_tab, i);
243
244 if (last->msg_index + 1 == msg->msg_index) {
245 r = mail_flags_compare(first->msg_flags, msg->msg_flags);
246 if (r == 0) {
247 last = msg;
248 continue;
249 }
250 }
251
252 r = imap_store_flags(imap, first->msg_index,
253 last->msg_index, first->msg_flags);
254
255 first = msg;
256 last = msg;
257 }
258
259 r = imap_store_flags(imap, first->msg_index, last->msg_index,
260 first->msg_flags);
261
262 mail_flags_store_clear(flags_store);
263}
264
265static void imapdriver_uninitialize(mailsession * session)
266{
267 struct imap_session_state_data * data;
268
269 data = get_data(session);
270
271 imap_flags_store_process(data->imap_session,
272 data->imap_flags_store);
273 mail_flags_store_free(data->imap_flags_store);
274
275 mailimap_free(data->imap_session);
276 if (data->imap_mailbox != NULL)
277 free(data->imap_mailbox);
278 free(data);
279
280 session->sess_data = NULL;
281}
282
283static int imapdriver_connect_stream(mailsession * session, mailstream * s)
284{
285 int r;
286
287 r = mailimap_connect(get_imap_session(session), s);
288
289 return imap_error_to_mail_error(r);
290}
291
292static int imapdriver_login(mailsession * session,
293 char * userid, char * password)
294{
295 int r;
296
297 r = mailimap_login(get_imap_session(session), userid, password);
298
299 return imap_error_to_mail_error(r);
300}
301
302static int imapdriver_logout(mailsession * session)
303{
304 int r;
305
306 imap_flags_store_process(get_imap_session(session),
307 get_data(session)->imap_flags_store);
308
309 r = mailimap_logout(get_imap_session(session));
310
311 return imap_error_to_mail_error(r);
312}
313
314static int imapdriver_noop(mailsession * session)
315{
316 int r;
317
318 r = mailimap_noop(get_imap_session(session));
319
320 return imap_error_to_mail_error(r);
321}
322
323static int imapdriver_build_folder_name(mailsession * session, char * mb,
324 char * name, char ** result)
325{
326 char delimiter[2] = "X";
327 char * folder_name;
328 mailimap * imap;
329 struct mailimap_mailbox_list * mb_list;
330 int r;
331 clist * imap_list;
332
333 imap = get_imap_session(session);
334
335 r = mailimap_list(imap, mb, "", &imap_list);
336 if (r != MAILIMAP_NO_ERROR)
337 return r;
338
339 if (clist_begin(imap_list) == NULL)
340 return MAIL_ERROR_LIST;
341
342 mb_list = clist_begin(imap_list)->data;
343 delimiter[0] = mb_list->mb_delimiter;
344
345 folder_name = malloc(strlen(mb) + strlen(delimiter) + strlen(name) + 1);
346 if (folder_name == NULL)
347 return MAIL_ERROR_MEMORY;
348
349 strcpy(folder_name, mb);
350 strcat(folder_name, delimiter);
351 strcat(folder_name, name);
352
353 * result = folder_name;
354
355 return MAIL_NO_ERROR;
356}
357
358/* folders operations */
359
360static int imapdriver_create_folder(mailsession * session, char * mb)
361{
362 int r;
363
364 r = mailimap_create(get_imap_session(session), mb);
365
366 return imap_error_to_mail_error(r);
367}
368
369static int imapdriver_delete_folder(mailsession * session, char * mb)
370{
371 int r;
372
373 r = mailimap_delete(get_imap_session(session), mb);
374
375 return imap_error_to_mail_error(r);
376}
377
378static int imapdriver_rename_folder(mailsession * session, char * mb,
379 char * new_name)
380{
381 int r;
382
383 r = mailimap_rename(get_imap_session(session), mb, new_name);
384
385 return imap_error_to_mail_error(r);
386}
387
388static int imapdriver_check_folder(mailsession * session)
389{
390 int r;
391
392 imap_flags_store_process(get_imap_session(session),
393 get_data(session)->imap_flags_store);
394
395 r = mailimap_check(get_imap_session(session));
396
397 return imap_error_to_mail_error(r);
398}
399
400static int imapdriver_examine_folder(mailsession * session, char * mb)
401{
402 int r;
403
404 r = mailimap_examine(get_imap_session(session), mb);
405
406 return imap_error_to_mail_error(r);
407}
408
409static int imapdriver_select_folder(mailsession * session, char * mb)
410{
411 int r;
412 char * new_mb;
413 char * old_mb;
414
415 old_mb = get_data(session)->imap_mailbox;
416 if (old_mb != NULL)
417 if (strcmp(mb, old_mb) == 0)
418 return MAIL_NO_ERROR;
419
420 imap_flags_store_process(get_imap_session(session),
421 get_data(session)->imap_flags_store);
422
423 r = mailimap_select(get_imap_session(session), mb);
424
425 switch (r) {
426 case MAILIMAP_NO_ERROR:
427 new_mb = strdup(mb);
428 if (new_mb == NULL) {
429 if (old_mb != NULL)
430 free(old_mb);
431 get_data(session)->imap_mailbox = NULL;
432 return MAIL_ERROR_MEMORY;
433 }
434
435 get_data(session)->imap_mailbox = new_mb;
436
437 return MAIL_NO_ERROR;
438 default:
439 return imap_error_to_mail_error(r);
440 }
441}
442
443static int imapdriver_expunge_folder(mailsession * session)
444{
445 int r;
446
447 imap_flags_store_process(get_imap_session(session),
448 get_data(session)->imap_flags_store);
449
450 r = mailimap_expunge(get_imap_session(session));
451
452 return imap_error_to_mail_error(r);
453}
454
455static int status_selected_folder(mailsession * session, char * mb,
456 uint32_t * result_messages, uint32_t * result_recent,
457 uint32_t * result_unseen)
458{
459 int r;
460 int res;
461 mailimap * imap;
462 uint32_t exists;
463 uint32_t unseen;
464 uint32_t recent;
465 struct mailimap_search_key * search_key;
466 clist * search_result;
467
468 imap = get_imap_session(session);
469
470 exists = imap->imap_selection_info->sel_exists;
471 recent = imap->imap_selection_info->sel_recent;
472
473 search_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN,
474 NULL, NULL, NULL, NULL, NULL,
475 NULL, NULL, NULL, NULL, NULL,
476 NULL, NULL, NULL, NULL, 0,
477 NULL, NULL, NULL, NULL, NULL,
478 NULL, 0, NULL, NULL, NULL);
479 if (search_key == NULL) {
480 res = MAIL_ERROR_MEMORY;
481 goto err;
482 }
483
484 /* default : use the RECENT count if search fails */
485 unseen = recent;
486 r = mailimap_search(imap, NULL, search_key, &search_result);
487 mailimap_search_key_free(search_key);
488 if (r == MAILIMAP_NO_ERROR) {
489 /* if this succeed, we use the real count */
490 unseen = clist_count(search_result);
491 mailimap_mailbox_data_search_free(search_result);
492 }
493
494 * result_messages = exists;
495 * result_unseen = unseen;
496 * result_recent = recent;
497
498 return MAIL_NO_ERROR;
499
500 err:
501 return res;
502}
503
504static int status_unselected_folder(mailsession * session, char * mb,
505 uint32_t * result_messages, uint32_t * result_recent,
506 uint32_t * result_unseen)
507{
508 struct mailimap_status_att_list * att_list;
509 struct mailimap_mailbox_data_status * status;
510 int r;
511 int res;
512 clistiter * cur;
513 mailimap * imap;
514
515 imap = get_imap_session(session);
516
517 att_list = mailimap_status_att_list_new_empty();
518 if (att_list == NULL) {
519 res = MAIL_ERROR_MEMORY;
520 goto err;
521 }
522
523 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_MESSAGES);
524 switch (r) {
525 case MAILIMAP_NO_ERROR:
526 break;
527 default:
528 res = MAIL_ERROR_MEMORY;
529 goto free;
530 }
531
532 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_RECENT);
533 switch (r) {
534 case MAILIMAP_NO_ERROR:
535 break;
536 default:
537 res = MAIL_ERROR_MEMORY;
538 goto free;
539 }
540
541 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_UNSEEN);
542 switch (r) {
543 case MAILIMAP_NO_ERROR:
544 break;
545 default:
546 res = MAIL_ERROR_MEMORY;
547 goto free;
548 }
549
550 r = mailimap_status(imap, mb, att_list, &status);
551
552 switch (r) {
553 case MAILIMAP_NO_ERROR:
554 break;
555 default:
556 res = imap_error_to_mail_error(r);
557 goto free;
558 }
559
560 * result_messages = 0;
561 * result_recent = 0;
562 * result_unseen = 0;
563
564 for (cur = clist_begin(status->st_info_list);
565 cur != NULL ; cur = clist_next(cur)) {
566 struct mailimap_status_info * status_info;
567
568 status_info = clist_content(cur);
569 switch (status_info->st_att) {
570 case MAILIMAP_STATUS_ATT_MESSAGES:
571 * result_messages = status_info->st_value;
572 break;
573 case MAILIMAP_STATUS_ATT_RECENT:
574 * result_recent = status_info->st_value;
575 break;
576 case MAILIMAP_STATUS_ATT_UNSEEN:
577 * result_unseen = status_info->st_value;
578 break;
579 }
580 }
581
582 mailimap_mailbox_data_status_free(status);
583 mailimap_status_att_list_free(att_list);
584
585 return MAIL_NO_ERROR;
586
587 free:
588 mailimap_status_att_list_free(att_list);
589 err:
590 return res;
591}
592
593static int imapdriver_status_folder(mailsession * session, char * mb,
594 uint32_t * result_messages, uint32_t * result_recent,
595 uint32_t * result_unseen)
596{
597 int res;
598 int current_folder;
599 char * current_mb;
600
601 if (mb == NULL) {
602 mb = get_data(session)->imap_mailbox;
603 if (mb == NULL) {
604 res = MAIL_ERROR_BAD_STATE;
605 goto err;
606 }
607 }
608
609 current_mb = get_data(session)->imap_mailbox;
610 if (strcmp(mb, current_mb) == 0)
611 current_folder = 1;
612 else
613 current_folder = 0;
614
615 if (current_folder)
616 return status_selected_folder(session, mb, result_messages,
617 result_recent, result_unseen);
618 else
619 return status_unselected_folder(session, mb, result_messages,
620 result_recent, result_unseen);
621
622 err:
623 return res;
624}
625
626/* TODO : more efficient functions */
627
628static int imapdriver_messages_number(mailsession * session, char * mb,
629 uint32_t * result)
630{
631 uint32_t messages;
632 uint32_t recent;
633 uint32_t unseen;
634 int r;
635
636 r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen);
637 if (r != MAIL_NO_ERROR)
638 return r;
639
640 * result = messages;
641
642 return MAIL_NO_ERROR;
643}
644
645static int imapdriver_recent_number(mailsession * session, char * mb,
646 uint32_t * result)
647{
648 uint32_t messages;
649 uint32_t recent;
650 uint32_t unseen;
651 int r;
652
653 r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen);
654 if (r != MAIL_NO_ERROR)
655 return r;
656
657 * result = recent;
658
659 return MAIL_NO_ERROR;
660}
661
662static int imapdriver_unseen_number(mailsession * session, char * mb,
663 uint32_t * result)
664{
665 uint32_t messages;
666 uint32_t recent;
667 uint32_t unseen;
668 int r;
669
670 r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen);
671 if (r != MAIL_NO_ERROR)
672 return r;
673
674 * result = unseen;
675
676 return MAIL_NO_ERROR;
677}
678
679enum {
680 IMAP_LIST, IMAP_LSUB
681};
682
683static int imapdriver_list_lsub_folders(mailsession * session, int type,
684 char * mb,
685 struct mail_list ** result)
686{
687 clist * imap_list;
688 struct mail_list * resp;
689 int r;
690 int res;
691
692 switch (type) {
693 case IMAP_LIST:
694 r = mailimap_list(get_imap_session(session), mb,
695 "*", &imap_list);
696 break;
697 case IMAP_LSUB:
698 r = mailimap_lsub(get_imap_session(session), mb,
699 "*", &imap_list);
700 break;
701 default:
702 res = MAIL_ERROR_LIST;
703 goto err;
704 }
705
706 switch (r) {
707 case MAILIMAP_NO_ERROR:
708 break;
709 default:
710 res = imap_error_to_mail_error(r);
711 goto err;
712 }
713
714 r = imap_list_to_list(imap_list, &resp);
715 if (r != MAIL_NO_ERROR) {
716 mailimap_list_result_free(imap_list);
717 res = r;
718 goto err;
719 }
720
721 mailimap_list_result_free(imap_list);
722
723 * result = resp;
724
725 return MAIL_NO_ERROR;
726
727 err:
728 return res;
729}
730
731static int imapdriver_list_folders(mailsession * session, char * mb,
732 struct mail_list ** result)
733{
734 return imapdriver_list_lsub_folders(session, IMAP_LIST, mb,
735 result);
736}
737
738static int imapdriver_lsub_folders(mailsession * session, char * mb,
739 struct mail_list ** result)
740{
741 return imapdriver_list_lsub_folders(session, IMAP_LSUB, mb,
742 result);
743}
744
745static int imapdriver_subscribe_folder(mailsession * session, char * mb)
746{
747 int r;
748
749 r = mailimap_subscribe(get_imap_session(session), mb);
750
751 return imap_error_to_mail_error(r);
752}
753
754static int imapdriver_unsubscribe_folder(mailsession * session, char * mb)
755{
756 int r;
757
758 r = mailimap_unsubscribe(get_imap_session(session), mb);
759
760 return imap_error_to_mail_error(r);
761}
762
763/* messages operations */
764
765static int imapdriver_append_message(mailsession * session,
766 char * message, size_t size)
767{
768 int r;
769
770 r = mailimap_append_simple(get_imap_session(session),
771 get_data(session)->imap_mailbox,
772 message, size);
773
774 return imap_error_to_mail_error(r);
775}
776
777static int imapdriver_append_message_flags(mailsession * session,
778 char * message, size_t size, struct mail_flags * flags)
779{
780 struct mailimap_flag_list * flag_list;
781 int r;
782
783 if (flags != NULL) {
784 r = imap_flags_to_imap_flags(flags, &flag_list);
785 if (r != MAIL_NO_ERROR)
786 return r;
787 }
788 else {
789 flag_list = NULL;
790 }
791
792 r = mailimap_append(get_imap_session(session),
793 get_data(session)->imap_mailbox,
794 flag_list, NULL, message, size);
795
796 if (flag_list != NULL)
797 mailimap_flag_list_free(flag_list);
798
799 return imap_error_to_mail_error(r);
800}
801
802static int imapdriver_copy_message(mailsession * session,
803 uint32_t num, char * mb)
804{
805 int r;
806 struct mailimap_set * set;
807 int res;
808
809 set = mailimap_set_new_single(num);
810 if (set == NULL) {
811 res = MAIL_ERROR_MEMORY;
812 goto err;
813 }
814
815 r = mailimap_uid_copy(get_imap_session(session), set, mb);
816
817 mailimap_set_free(set);
818
819 return imap_error_to_mail_error(r);
820
821 err:
822 return res;
823}
824
825static int imapdriver_get_messages_list(mailsession * session,
826 struct mailmessage_list ** result)
827{
828 return imap_get_messages_list(get_imap_session(session),
829 session, imap_message_driver, 1,
830 result);
831}
832
833
834
835#define IMAP_SET_MAX_COUNT 100
836
837static int
838imapdriver_get_envelopes_list(mailsession * session,
839 struct mailmessage_list * env_list)
840{
841 struct mailimap_set * set;
842 struct mailimap_fetch_att * fetch_att;
843 struct mailimap_fetch_type * fetch_type;
844 int res;
845 clist * fetch_result;
846 int r;
847 uint32_t exists;
848 clist * msg_list;
849 clistiter * set_iter;
850
851 if (get_imap_session(session)->imap_selection_info == NULL) {
852 res = MAIL_ERROR_BAD_STATE;
853 goto err;
854 }
855
856 imap_flags_store_process(get_imap_session(session),
857 get_data(session)->imap_flags_store);
858
859 exists = get_imap_session(session)->imap_selection_info->sel_exists;
860
861 if (exists == 0)
862 return MAIL_NO_ERROR;
863
864 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
865 if (fetch_type == NULL) {
866 res = MAIL_ERROR_MEMORY;
867 goto err;
868 }
869
870 fetch_att = mailimap_fetch_att_new_uid();
871 if (fetch_att == NULL) {
872 res = MAIL_ERROR_MEMORY;
873 goto free_fetch_type;
874 }
875
876 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
877 if (r != MAILIMAP_NO_ERROR) {
878 mailimap_fetch_att_free(fetch_att);
879 res = MAIL_ERROR_MEMORY;
880 goto free_fetch_type;
881 }
882
883 fetch_att = mailimap_fetch_att_new_flags();
884 if (fetch_att == NULL) {
885 res = MAIL_ERROR_MEMORY;
886 goto free_fetch_type;
887 }
888
889 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
890 if (r != MAILIMAP_NO_ERROR) {
891 mailimap_fetch_att_free(fetch_att);
892 res = MAIL_ERROR_MEMORY;
893 goto free_fetch_type;
894 }
895
896 r = imap_add_envelope_fetch_att(fetch_type);
897 if (r != MAIL_NO_ERROR) {
898 res = r;
899 goto free_fetch_type;
900 }
901
902 r = maildriver_env_list_to_msg_list(env_list, &msg_list);
903 if (r != MAIL_NO_ERROR) {
904 res = MAIL_ERROR_MEMORY;
905 goto free_fetch_type;
906 }
907
908 if (clist_begin(msg_list) == NULL) {
909 /* no need to fetch envelopes */
910
911 mailimap_fetch_type_free(fetch_type);
912 clist_free(msg_list);
913 return MAIL_NO_ERROR;
914 }
915
916 r = msg_list_to_imap_set(msg_list, &set);
917 if (r != MAIL_NO_ERROR) {
918 clist_foreach(msg_list, (clist_func) free, NULL);
919 clist_free(msg_list);
920 res = MAIL_ERROR_MEMORY;
921 goto free_fetch_type;
922 }
923 clist_foreach(msg_list, (clist_func) free, NULL);
924 clist_free(msg_list);
925
926 set_iter = clist_begin(set->set_list);
927 while (set_iter != NULL) {
928 struct mailimap_set * subset;
929 unsigned int count;
930
931 subset = mailimap_set_new_empty();
932 if (subset == NULL) {
933 res = MAIL_ERROR_MEMORY;
934 mailimap_fetch_type_free(fetch_type);
935 mailimap_set_free(set);
936 res = MAIL_ERROR_MEMORY;
937 goto err;
938 }
939
940 count = 0;
941 while (count < IMAP_SET_MAX_COUNT) {
942 struct mailimap_set_item * item;
943
944 item = clist_content(set_iter);
945 set_iter = clist_delete(set->set_list, set_iter);
946
947 r = mailimap_set_add(subset, item);
948 if (r != MAILIMAP_NO_ERROR) {
949 mailimap_set_item_free(item);
950 mailimap_set_free(subset);
951 mailimap_fetch_type_free(fetch_type);
952 mailimap_set_free(set);
953 res = MAIL_ERROR_MEMORY;
954 goto err;
955 }
956
957 count ++;
958
959 if (set_iter == NULL)
960 break;
961 }
962
963 r = mailimap_uid_fetch(get_imap_session(session), subset,
964 fetch_type, &fetch_result);
965
966 mailimap_set_free(subset);
967
968 switch (r) {
969 case MAILIMAP_NO_ERROR:
970 break;
971 default:
972 mailimap_fetch_type_free(fetch_type);
973 mailimap_set_free(set);
974 return imap_error_to_mail_error(r);
975 }
976
977 if (clist_begin(fetch_result) == NULL) {
978 res = MAIL_ERROR_FETCH;
979 goto err;
980 }
981
982 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
983 mailimap_fetch_list_free(fetch_result);
984
985 if (r != MAIL_NO_ERROR) {
986 mailimap_fetch_type_free(fetch_type);
987 mailimap_set_free(set);
988 res = MAIL_ERROR_MEMORY;
989 goto err;
990 }
991 }
992
993#if 0
994 r = mailimap_uid_fetch(get_imap_session(session), set,
995 fetch_type, &fetch_result);
996#endif
997
998 mailimap_fetch_type_free(fetch_type);
999 mailimap_set_free(set);
1000#if 0
1001 switch (r) {
1002 case MAILIMAP_NO_ERROR:
1003 break;
1004 default:
1005 return imap_error_to_mail_error(r);
1006 }
1007
1008 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
1009 mailimap_fetch_list_free(fetch_result);
1010
1011 if (r != MAIL_NO_ERROR) {
1012 res = MAIL_ERROR_MEMORY;
1013 goto err;
1014 }
1015#endif
1016
1017 return MAIL_NO_ERROR;
1018
1019 free_fetch_type:
1020 mailimap_fetch_type_free(fetch_type);
1021 err:
1022 return res;
1023}
1024
1025
1026#if 0
1027static int imapdriver_search_messages(mailsession * session, char * charset,
1028 struct mail_search_key * key,
1029 struct mail_search_result ** result)
1030{
1031 struct mailimap_search_key * imap_key;
1032 int r;
1033 clist * imap_result;
1034 clist * result_list;
1035 struct mail_search_result * search_result;
1036 clistiter * cur;
1037
1038 r = mail_search_to_imap_search(key, &imap_key);
1039 if (r != MAIL_NO_ERROR)
1040 return MAIL_ERROR_MEMORY;
1041
1042 r = mailimap_uid_search(get_imap_session(session), charset, imap_key,
1043 &imap_result);
1044
1045 mailimap_search_key_free(imap_key);
1046
1047 switch (r) {
1048 case MAILIMAP_NO_ERROR:
1049 break;
1050 default:
1051 return imap_error_to_mail_error(r);
1052 }
1053
1054 result_list = clist_new();
1055 if (result_list == NULL)
1056 return MAIL_ERROR_MEMORY;
1057
1058 for(cur = clist_begin(imap_result) ; cur != NULL ; cur = clist_next(cur)) {
1059 uint32_t val = * (uint32_t *) clist_content(cur);
1060 uint32_t * new;
1061
1062 new = malloc(sizeof(* new));
1063 if (new == NULL) {
1064 goto free_imap_result;
1065 }
1066
1067 * new = val;
1068
1069 r = clist_append(result_list, new);
1070 if (r != 0) {
1071 free(new);
1072 goto free_imap_result;
1073 }
1074 }
1075
1076 search_result = mail_search_result_new(result_list);
1077 if (search_result == NULL)
1078 goto free_imap_result;
1079
1080 mailimap_search_result_free(imap_result);
1081
1082 * result = search_result;
1083
1084 return MAIL_NO_ERROR;
1085
1086 free_imap_result:
1087 mailimap_search_result_free(imap_result);
1088 return MAIL_ERROR_MEMORY;
1089}
1090#endif
1091
1092static int imapdriver_starttls(mailsession * session)
1093{
1094 mailimap * imap;
1095 int r;
1096 struct mailimap_capability_data * cap_data;
1097 clistiter * cur;
1098 int starttls;
1099 int fd;
1100 mailstream_low * low;
1101 mailstream_low * new_low;
1102 int capability_available;
1103
1104 imap = get_imap_session(session);
1105
1106 capability_available = FALSE;
1107 if (imap->imap_connection_info != NULL)
1108 if (imap->imap_connection_info->imap_capability != NULL) {
1109 capability_available = TRUE;
1110 cap_data = imap->imap_connection_info->imap_capability;
1111 }
1112
1113 if (!capability_available) {
1114 r = mailimap_capability(imap, &cap_data);
1115 switch (r) {
1116 case MAILIMAP_NO_ERROR:
1117 break;
1118 default:
1119 return imap_error_to_mail_error(r);
1120 }
1121 }
1122
1123 starttls = FALSE;
1124 for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ;
1125 cur = clist_next(cur)) {
1126 struct mailimap_capability * cap;
1127
1128 cap = clist_content(cur);
1129
1130 if (cap->cap_type == MAILIMAP_CAPABILITY_NAME)
1131 if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) {
1132 starttls = TRUE;
1133 break;
1134 }
1135 }
1136
1137 if (!capability_available)
1138 mailimap_capability_data_free(cap_data);
1139
1140 if (!starttls)
1141 return MAIL_ERROR_NO_TLS;
1142
1143 r = mailimap_starttls(imap);
1144
1145 switch (r) {
1146 case MAILIMAP_NO_ERROR:
1147 break;
1148 default:
1149 return imap_error_to_mail_error(r);
1150 }
1151
1152 low = mailstream_get_low(imap->imap_stream);
1153 fd = mailstream_low_get_fd(low);
1154 if (fd == -1)
1155 return MAIL_ERROR_STREAM;
1156
1157 new_low = mailstream_low_ssl_open(fd);
1158 if (new_low == NULL)
1159 return MAIL_ERROR_STREAM;
1160
1161 mailstream_low_free(low);
1162 mailstream_set_low(imap->imap_stream, new_low);
1163
1164 return MAIL_NO_ERROR;
1165}
1166
1167static int imapdriver_get_message(mailsession * session,
1168 uint32_t num, mailmessage ** result)
1169{
1170 mailmessage * msg_info;
1171 int r;
1172
1173 msg_info = mailmessage_new();
1174 if (msg_info == NULL)
1175 return MAIL_ERROR_MEMORY;
1176
1177 r = mailmessage_init(msg_info, session, imap_message_driver, num, 0);
1178 if (r != MAIL_NO_ERROR) {
1179 mailmessage_free(msg_info);
1180 return r;
1181 }
1182
1183 * result = msg_info;
1184
1185 return MAIL_NO_ERROR;
1186}
1187
1188/* Retrieve a message by UID
1189
1190 libEtPan! uid format for IMAP is "UIDVALIDITY-UID"
1191 where UIDVALIDITY and UID are decimal representation of
1192 respectively uidvalidity and uid numbers.
1193
1194 Return value:
1195 MAIL_ERROR_INVAL if uid is NULL or has an incorrect format.
1196 MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found
1197 MAIL_NO_ERROR if message was found. Result is in result
1198*/
1199
1200static int imapdriver_get_message_by_uid(mailsession * session,
1201 const char * uid,
1202 mailmessage ** result)
1203{
1204 uint32_t uidvalidity;
1205 uint32_t num;
1206 char * p1, * p2;
1207 mailimap * imap;
1208
1209 if (uid == NULL)
1210 return MAIL_ERROR_INVAL;
1211
1212 uidvalidity = strtoul(uid, &p1, 10);
1213 if (p1 == uid || * p1 != '-')
1214 return MAIL_ERROR_INVAL;
1215
1216 p1++;
1217 num = strtoul(p1, &p2, 10);
1218 if (p2 == p1 || * p2 != '\0')
1219 return MAIL_ERROR_INVAL;
1220
1221 imap = get_imap_session(session);
1222 if (imap->imap_selection_info->sel_uidvalidity != uidvalidity)
1223 return MAIL_ERROR_MSG_NOT_FOUND;
1224
1225 return imapdriver_get_message(session, num, result);
1226}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_H
37
38#define IMAPDRIVER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/imapdriver_types.h>
45
46extern mailsession_driver * imap_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_cached.h"
37
38#include "libetpan-config.h"
39
40#include <stdio.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <fcntl.h>
44#include <string.h>
45#include <unistd.h>
46#include <stdlib.h>
47
48#include "mail.h"
49#include "imapdriver_tools.h"
50#include "mail_cache_db.h"
51#include "mailmessage.h"
52#include "imapdriver_cached_message.h"
53#include "maildriver.h"
54#include "imapdriver_types.h"
55#include "generic_cache.h"
56#include "imfcache.h"
57#include "maildriver_tools.h"
58#include "imapdriver.h"
59
60static int imapdriver_cached_initialize(mailsession * session);
61static void imapdriver_cached_uninitialize(mailsession * session);
62
63static int imapdriver_cached_parameters(mailsession * session,
64 int id, void * value);
65
66static int imapdriver_cached_connect_stream(mailsession * session,
67 mailstream * s);
68
69static int imapdriver_cached_starttls(mailsession * session);
70
71static int imapdriver_cached_login(mailsession * session,
72 char * userid, char * password);
73static int imapdriver_cached_logout(mailsession * session);
74static int imapdriver_cached_noop(mailsession * session);
75static int imapdriver_cached_build_folder_name(mailsession * session,
76 char * mb,
77 char * name, char ** result);
78static int imapdriver_cached_create_folder(mailsession * session, char * mb);
79static int imapdriver_cached_delete_folder(mailsession * session, char * mb);
80static int imapdriver_cached_rename_folder(mailsession * session, char * mb,
81 char * new_name);
82static int imapdriver_cached_check_folder(mailsession * session);
83static int imapdriver_cached_examine_folder(mailsession * session,
84 char * mb);
85static int imapdriver_cached_select_folder(mailsession * session, char * mb);
86static int imapdriver_cached_expunge_folder(mailsession * session);
87static int imapdriver_cached_status_folder(mailsession * session, char * mb,
88 uint32_t * result_messages,
89 uint32_t * result_recent,
90 uint32_t * result_unseen);
91static int imapdriver_cached_messages_number(mailsession * session,
92 char * mb,
93 uint32_t * result);
94static int imapdriver_cached_recent_number(mailsession * session, char * mb,
95 uint32_t * result);
96static int imapdriver_cached_unseen_number(mailsession * session, char * mb,
97 uint32_t * result);
98static int imapdriver_cached_list_folders(mailsession * session, char * mb,
99 struct mail_list ** result);
100static int imapdriver_cached_lsub_folders(mailsession * session, char * mb,
101 struct mail_list ** result);
102static int imapdriver_cached_subscribe_folder(mailsession * session,
103 char * mb);
104static int imapdriver_cached_unsubscribe_folder(mailsession * session,
105 char * mb);
106static int imapdriver_cached_append_message(mailsession * session,
107 char * message, size_t size);
108static int imapdriver_cached_append_message_flags(mailsession * session,
109 char * message, size_t size, struct mail_flags * flags);
110static int imapdriver_cached_copy_message(mailsession * session,
111 uint32_t num, char * mb);
112
113static int imapdriver_cached_get_messages_list(mailsession * session,
114 struct mailmessage_list **
115 result);
116static int
117imapdriver_cached_get_envelopes_list(mailsession * session,
118 struct mailmessage_list * env_list);
119static int imapdriver_cached_remove_message(mailsession * session,
120 uint32_t num);
121
122#if 0
123static int imapdriver_cached_search_messages(mailsession * session,
124 char * charset,
125 struct mail_search_key * key,
126 struct mail_search_result **
127 result);
128#endif
129
130static int imapdriver_cached_get_message(mailsession * session,
131 uint32_t num, mailmessage ** result);
132
133static int imapdriver_cached_get_message_by_uid(mailsession * session,
134 const char * uid,
135 mailmessage ** result);
136
137static mailsession_driver local_imap_cached_session_driver = {
138 .sess_name = "imap-cached",
139
140 .sess_initialize = imapdriver_cached_initialize,
141 .sess_uninitialize = imapdriver_cached_uninitialize,
142
143 .sess_parameters = imapdriver_cached_parameters,
144
145 .sess_connect_stream = imapdriver_cached_connect_stream,
146 .sess_connect_path = NULL,
147 .sess_starttls = imapdriver_cached_starttls,
148 .sess_login = imapdriver_cached_login,
149 .sess_logout = imapdriver_cached_logout,
150 .sess_noop = imapdriver_cached_noop,
151
152 .sess_build_folder_name = imapdriver_cached_build_folder_name,
153 .sess_create_folder = imapdriver_cached_create_folder,
154 .sess_delete_folder = imapdriver_cached_delete_folder,
155 .sess_rename_folder = imapdriver_cached_rename_folder,
156 .sess_check_folder = imapdriver_cached_check_folder,
157 .sess_examine_folder = imapdriver_cached_examine_folder,
158 .sess_select_folder = imapdriver_cached_select_folder,
159 .sess_expunge_folder = imapdriver_cached_expunge_folder,
160 .sess_status_folder = imapdriver_cached_status_folder,
161 .sess_messages_number = imapdriver_cached_messages_number,
162 .sess_recent_number = imapdriver_cached_recent_number,
163 .sess_unseen_number = imapdriver_cached_unseen_number,
164 .sess_list_folders = imapdriver_cached_list_folders,
165 .sess_lsub_folders = imapdriver_cached_lsub_folders,
166 .sess_subscribe_folder = imapdriver_cached_subscribe_folder,
167 .sess_unsubscribe_folder = imapdriver_cached_unsubscribe_folder,
168
169 .sess_append_message = imapdriver_cached_append_message,
170 .sess_append_message_flags = imapdriver_cached_append_message_flags,
171 .sess_copy_message = imapdriver_cached_copy_message,
172 .sess_move_message = NULL,
173
174 .sess_get_messages_list = imapdriver_cached_get_messages_list,
175 .sess_get_envelopes_list = imapdriver_cached_get_envelopes_list,
176 .sess_remove_message = imapdriver_cached_remove_message,
177#if 0
178 .sess_search_messages = imapdriver_cached_search_messages,
179#endif
180
181 .sess_get_message = imapdriver_cached_get_message,
182 .sess_get_message_by_uid = imapdriver_cached_get_message_by_uid,
183};
184
185mailsession_driver * imap_cached_session_driver =
186&local_imap_cached_session_driver;
187
188#define CACHE_MESSAGE_LIST
189
190static inline struct imap_cached_session_state_data *
191get_cached_data(mailsession * session)
192{
193 return session->sess_data;
194}
195
196static inline mailsession * get_ancestor(mailsession * s)
197{
198 return get_cached_data(s)->imap_ancestor;
199}
200
201static inline
202struct imap_session_state_data * get_ancestor_data(mailsession * s)
203{
204 return get_ancestor(s)->sess_data;
205}
206
207static inline mailimap * get_imap_session(mailsession * session)
208{
209 return get_ancestor_data(session)->imap_session;
210}
211
212static int imapdriver_cached_initialize(mailsession * session)
213{
214 struct imap_cached_session_state_data * data;
215
216 data = malloc(sizeof(* data));
217 if (data == NULL)
218 goto err;
219
220 data->imap_ancestor = mailsession_new(imap_session_driver);
221 if (data->imap_ancestor == NULL)
222 goto free_data;
223 data->imap_quoted_mb = NULL;
224 data->imap_cache_directory[0] = '\0';
225 data->imap_uid_list = carray_new(128);
226 if (data->imap_uid_list == NULL)
227 goto free_session;
228
229 session->sess_data = data;
230
231 return MAIL_NO_ERROR;
232
233 free_session:
234 mailsession_free(data->imap_ancestor);
235 free_data:
236 free(data);
237 err:
238 return MAIL_ERROR_MEMORY;
239}
240
241static void
242free_quoted_mb(struct imap_cached_session_state_data * imap_cached_data)
243{
244 if (imap_cached_data->imap_quoted_mb != NULL) {
245 free(imap_cached_data->imap_quoted_mb);
246 imap_cached_data->imap_quoted_mb = NULL;
247 }
248}
249
250struct uid_cache_item {
251 uint32_t uid;
252 uint32_t size;
253};
254
255static int update_uid_cache(mailsession * session,
256 struct mailmessage_list * env_list)
257{
258 unsigned int i;
259 int r;
260 struct imap_cached_session_state_data * data;
261 int res;
262
263 data = get_cached_data(session);
264
265 /* free all UID cache */
266 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
267 struct uid_cache_item * cache_item;
268
269 cache_item = carray_get(data->imap_uid_list, i);
270 free(cache_item);
271 }
272
273 /* build UID cache */
274 r = carray_set_size(data->imap_uid_list,
275 carray_count(env_list->msg_tab));
276 if (r < 0) {
277 res = MAIL_ERROR_MEMORY;
278 goto err;
279 }
280
281 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
282 struct uid_cache_item * cache_item;
283 mailmessage * msg;
284
285 cache_item = malloc(sizeof(* cache_item));
286 if (cache_item == NULL) {
287 res = MAIL_ERROR_MEMORY;
288 goto err;
289 }
290 msg = carray_get(env_list->msg_tab, i);
291 cache_item->uid = msg->msg_index;
292 cache_item->size = msg->msg_size;
293
294 carray_set(data->imap_uid_list, i, cache_item);
295 }
296
297 return MAIL_NO_ERROR;
298
299 err:
300 return res;
301}
302
303static void check_for_uid_cache(mailsession * session)
304{
305#if 0
306 mailsession * imap;
307#endif
308 mailimap * imap;
309#if 0
310 struct imap_session_state_data * imap_data;
311#endif
312 clist * list;
313 clistiter * cur;
314 struct imap_cached_session_state_data * data;
315 unsigned int i;
316 unsigned dest;
317
318 data = get_cached_data(session);
319#if 0
320 imap = get_ancestor(session);
321
322 imap_data = imap->data;
323#endif
324
325 imap = get_imap_session(session);
326
327 if (imap->imap_response_info == NULL)
328 return;
329
330 list = imap->imap_response_info->rsp_expunged;
331 if (list == NULL)
332 return;
333
334 dest = 0;
335 i = 0;
336 /* remove expunged */
337 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
338 uint32_t expunged;
339
340 expunged = * (uint32_t *) clist_content(cur);
341
342 while (i < carray_count(data->imap_uid_list)) {
343 struct uid_cache_item * cache_item;
344
345 if (dest + 1 == expunged) {
346 cache_item = carray_get(data->imap_uid_list, i);
347 free(cache_item);
348 i ++;
349 break;
350 }
351 else {
352 cache_item = carray_get(data->imap_uid_list, i);
353 carray_set(data->imap_uid_list, dest, cache_item);
354 i ++;
355 dest ++;
356 }
357 }
358 }
359 /* complete list */
360 while (i < carray_count(data->imap_uid_list)) {
361 struct uid_cache_item * cache_item;
362
363 cache_item = carray_get(data->imap_uid_list, i);
364 carray_set(data->imap_uid_list, dest, cache_item);
365 i ++;
366 dest ++;
367 }
368 carray_set_size(data->imap_uid_list, dest);
369}
370
371static void imapdriver_cached_uninitialize(mailsession * session)
372{
373 struct imap_cached_session_state_data * data;
374 unsigned int i;
375
376 data = get_cached_data(session);
377
378 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
379 struct uid_cache_item * cache_item;
380
381 cache_item = carray_get(data->imap_uid_list, i);
382 free(cache_item);
383 }
384 carray_free(data->imap_uid_list);
385 free_quoted_mb(data);
386 mailsession_free(data->imap_ancestor);
387 free(data);
388
389 session->sess_data = NULL;
390}
391
392
393static int imapdriver_cached_parameters(mailsession * session,
394 int id, void * value)
395{
396 struct imap_cached_session_state_data * data;
397 int r;
398
399 data = get_cached_data(session);
400
401 switch (id) {
402 case IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY:
403 strncpy(data->imap_cache_directory, value, PATH_MAX);
404 data->imap_cache_directory[PATH_MAX - 1] = '\0';
405
406 r = generic_cache_create_dir(data->imap_cache_directory);
407 if (r != MAIL_NO_ERROR)
408 return r;
409
410 return MAIL_NO_ERROR;
411 }
412
413 return MAIL_ERROR_INVAL;
414}
415
416
417static int imapdriver_cached_connect_stream(mailsession * session,
418 mailstream * s)
419{
420 int r;
421
422 check_for_uid_cache(session);
423
424 r = mailsession_connect_stream(get_ancestor(session), s);
425
426 check_for_uid_cache(session);
427
428 return r;
429}
430
431static int imapdriver_cached_starttls(mailsession * session)
432{
433 int r;
434
435 r = mailsession_starttls(get_ancestor(session));
436
437 check_for_uid_cache(session);
438
439 return r;
440}
441
442static int imapdriver_cached_login(mailsession * session,
443 char * userid, char * password)
444{
445 int r;
446
447 r = mailsession_login(get_ancestor(session), userid, password);
448
449 check_for_uid_cache(session);
450
451 return r;
452}
453
454static int imapdriver_cached_logout(mailsession * session)
455{
456 int r;
457
458 r = mailsession_logout(get_ancestor(session));
459
460 check_for_uid_cache(session);
461
462 if (r == MAIL_NO_ERROR) {
463 struct imap_cached_session_state_data * imap_cached_data;
464
465 imap_cached_data = get_cached_data(session);
466
467 free_quoted_mb(imap_cached_data);
468 }
469
470 return r;
471}
472
473static int imapdriver_cached_noop(mailsession * session)
474{
475 int r;
476
477 r = mailsession_noop(get_ancestor(session));
478
479 check_for_uid_cache(session);
480
481 return r;
482}
483
484static int imapdriver_cached_build_folder_name(mailsession * session,
485 char * mb,
486 char * name, char ** result)
487{
488 int r;
489
490 r = mailsession_build_folder_name(get_ancestor(session), mb,
491 name, result);
492
493 check_for_uid_cache(session);
494
495 return r;
496}
497
498static int imapdriver_cached_create_folder(mailsession * session, char * mb)
499{
500 int r;
501
502 r = mailsession_create_folder(get_ancestor(session), mb);
503
504 check_for_uid_cache(session);
505
506 return r;
507}
508
509static int imapdriver_cached_delete_folder(mailsession * session, char * mb)
510{
511 int r;
512
513 r = mailsession_delete_folder(get_ancestor(session), mb);
514
515 check_for_uid_cache(session);
516
517 return r;
518}
519
520static int imapdriver_cached_rename_folder(mailsession * session, char * mb,
521 char * new_name)
522{
523 int r;
524
525 r = mailsession_rename_folder(get_ancestor(session), mb, new_name);
526
527 check_for_uid_cache(session);
528
529 return r;
530}
531
532static int imapdriver_cached_check_folder(mailsession * session)
533{
534 int r;
535
536 r = mailsession_check_folder(get_ancestor(session));
537
538 check_for_uid_cache(session);
539
540 return r;
541}
542
543static int imapdriver_cached_examine_folder(mailsession * session,
544 char * mb)
545{
546 int r;
547
548 r = mailsession_examine_folder(get_ancestor(session), mb);
549
550 check_for_uid_cache(session);
551
552 return r;
553}
554
555static int get_cache_folder(mailsession * session, char ** result)
556{
557#if 0
558 mailsession * imap_session;
559#endif
560 mailimap * imap;
561 char * mb;
562 char * cache_dir;
563 char * dirname;
564 char * quoted_mb;
565 int res;
566 int r;
567 char key[PATH_MAX];
568#if 0
569 struct imap_session_state_data * imap_data;
570 struct imap_cached_session_state_data * cached_data;
571#endif
572
573#if 0
574 imap_session = get_ancestor(session);
575 imap_data = imap_session->data;
576 imap = imap_data->session;
577#endif
578 imap = get_imap_session(session);
579
580 mb = get_ancestor_data(session)->imap_mailbox;
581
582 cache_dir = get_cached_data(session)->imap_cache_directory;
583
584 if (imap->imap_state != MAILIMAP_STATE_SELECTED)
585 return MAIL_ERROR_BAD_STATE;
586
587 if (imap->imap_selection_info == NULL)
588 return MAIL_ERROR_BAD_STATE;
589
590 quoted_mb = maildriver_quote_mailbox(mb);
591 if (quoted_mb == NULL) {
592 res = MAIL_ERROR_MEMORY;
593 goto err;
594 }
595
596 snprintf(key, PATH_MAX, "%s/%s", cache_dir, quoted_mb);
597
598 dirname = strdup(key);
599 if (dirname == NULL) {
600 res = MAIL_ERROR_MEMORY;
601 goto free_mb;
602 }
603
604 r = generic_cache_create_dir(dirname);
605 if (r != MAIL_NO_ERROR) {
606 res = r;
607 goto free_dirname;
608 }
609
610 free(quoted_mb);
611
612 * result = dirname;
613
614 return MAIL_NO_ERROR;
615
616 free_dirname:
617 free(dirname);
618 free_mb:
619 free(quoted_mb);
620 err:
621 return res;
622}
623
624static int imapdriver_cached_select_folder(mailsession * session, char * mb)
625{
626 int r;
627 char * quoted_mb;
628 struct imap_cached_session_state_data * data;
629 mailsession * imap;
630 char * old_mb;
631
632 imap = get_ancestor(session);
633
634 old_mb = get_ancestor_data(session)->imap_mailbox;
635 if (old_mb != NULL)
636 if (strcmp(mb, old_mb) == 0)
637 return MAIL_NO_ERROR;
638
639 r = mailsession_select_folder(get_ancestor(session), mb);
640 if (r != MAIL_NO_ERROR)
641 return r;
642
643 check_for_uid_cache(session);
644
645 r = get_cache_folder(session, &quoted_mb);
646 if (r != MAIL_NO_ERROR)
647 return r;
648
649 data = get_cached_data(session);
650 if (data->imap_quoted_mb != NULL)
651 free(data->imap_quoted_mb);
652 data->imap_quoted_mb = quoted_mb;
653
654 /* clear UID cache */
655 carray_set_size(data->imap_uid_list, 0);
656
657 return MAIL_NO_ERROR;
658}
659
660static int imapdriver_cached_expunge_folder(mailsession * session)
661{
662 int r;
663
664 r = mailsession_expunge_folder(get_ancestor(session));
665
666 check_for_uid_cache(session);
667
668 return r;
669}
670
671static int imapdriver_cached_status_folder(mailsession * session, char * mb,
672 uint32_t * result_messages, uint32_t * result_recent,
673 uint32_t * result_unseen)
674{
675 int r;
676
677 r = mailsession_status_folder(get_ancestor(session), mb, result_messages,
678 result_recent, result_unseen);
679
680 check_for_uid_cache(session);
681
682 return r;
683}
684
685static int imapdriver_cached_messages_number(mailsession * session,
686 char * mb,
687 uint32_t * result)
688{
689 int r;
690
691 r = mailsession_messages_number(get_ancestor(session), mb, result);
692
693 check_for_uid_cache(session);
694
695 return r;
696}
697
698static int imapdriver_cached_recent_number(mailsession * session, char * mb,
699 uint32_t * result)
700{
701 int r;
702
703 r = mailsession_recent_number(get_ancestor(session), mb, result);
704
705 check_for_uid_cache(session);
706
707 return r;
708}
709
710static int imapdriver_cached_unseen_number(mailsession * session, char * mb,
711 uint32_t * result)
712{
713 int r;
714
715 r = mailsession_unseen_number(get_ancestor(session), mb, result);
716
717 check_for_uid_cache(session);
718
719 return r;
720}
721
722static int imapdriver_cached_list_folders(mailsession * session, char * mb,
723 struct mail_list ** result)
724{
725 int r;
726
727 r = mailsession_list_folders(get_ancestor(session), mb, result);
728
729 check_for_uid_cache(session);
730
731 return r;
732}
733
734static int imapdriver_cached_lsub_folders(mailsession * session, char * mb,
735 struct mail_list ** result)
736{
737 int r;
738
739 r = mailsession_lsub_folders(get_ancestor(session), mb, result);
740
741 check_for_uid_cache(session);
742
743 return r;
744}
745
746static int imapdriver_cached_subscribe_folder(mailsession * session,
747 char * mb)
748{
749 int r;
750
751 r = mailsession_subscribe_folder(get_ancestor(session), mb);
752
753 check_for_uid_cache(session);
754
755 return r;
756}
757
758static int imapdriver_cached_unsubscribe_folder(mailsession * session,
759 char * mb)
760{
761 int r;
762
763 r = mailsession_unsubscribe_folder(get_ancestor(session), mb);
764
765 check_for_uid_cache(session);
766
767 return r;
768}
769
770static int imapdriver_cached_append_message(mailsession * session,
771 char * message, size_t size)
772{
773 int r;
774
775 r = mailsession_append_message(get_ancestor(session), message, size);
776
777 check_for_uid_cache(session);
778
779 return r;
780}
781
782static int imapdriver_cached_append_message_flags(mailsession * session,
783 char * message, size_t size, struct mail_flags * flags)
784{
785 int r;
786
787 r = mailsession_append_message_flags(get_ancestor(session),
788 message, size, flags);
789
790 check_for_uid_cache(session);
791
792 return r;
793}
794
795static int imapdriver_cached_copy_message(mailsession * session,
796 uint32_t num, char * mb)
797{
798 int r;
799
800 r = mailsession_copy_message(get_ancestor(session), num, mb);
801
802 check_for_uid_cache(session);
803
804 return r;
805}
806
807static int cmp_uid(uint32_t ** pa, uint32_t ** pb)
808{
809 uint32_t * a;
810 uint32_t * b;
811
812 a = * pa;
813 b = * pb;
814
815 return * a - * b;
816}
817
818
819static int imapdriver_cached_get_messages_list(mailsession * session,
820 struct mailmessage_list **
821 result)
822{
823#if 0
824 mailsession * imap_session;
825#endif
826 mailimap * imap;
827 uint32_t uid_max;
828 struct imap_cached_session_state_data * data;
829 struct mailmessage_list * env_list;
830 unsigned i;
831 int r;
832 int res;
833 carray * tab;
834
835#if 0
836 data = session->data;
837 imap_session = get_ancestor(session);
838 imap = ((struct imap_session_state_data *) (imap_session->data))->session;
839#endif
840 data = get_cached_data(session);
841 imap = get_imap_session(session);
842
843 uid_max = 0;
844
845#ifdef CACHE_MESSAGE_LIST
846 /* get UID max */
847 uid_max = 0;
848 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
849 struct uid_cache_item * cache_item;
850
851 cache_item = carray_get(data->imap_uid_list, i);
852 if (cache_item->uid > uid_max)
853 uid_max = cache_item->uid;
854 }
855#endif
856
857 r = imap_get_messages_list(imap, session, imap_cached_message_driver,
858 uid_max + 1, &env_list);
859
860 check_for_uid_cache(session);
861
862 if (r != MAIL_NO_ERROR) {
863 res = r;
864 goto err;
865 }
866
867#ifdef CACHE_MESSAGE_LIST
868 /* remove unsollicited message */
869 i = 0;
870 while (i < carray_count(env_list->msg_tab)) {
871 mailmessage * msg;
872
873 msg = carray_get(env_list->msg_tab, i);
874 if (msg->msg_index < uid_max + 1) {
875 mailmessage * msg;
876
877 msg = carray_get(env_list->msg_tab, i);
878 mailmessage_free(msg);
879 carray_delete(env_list->msg_tab, i);
880 }
881 else {
882 i ++;
883 }
884 }
885
886 tab = carray_new(carray_count(env_list->msg_tab) +
887 carray_count(data->imap_uid_list));
888 if (tab == NULL) {
889 res = MAIL_ERROR_MEMORY;
890 goto free;
891 }
892 carray_set_size(tab,
893 carray_count(env_list->msg_tab) + carray_count(data->imap_uid_list));
894
895 /* sort cached data before adding them to the list */
896 qsort(carray_data(data->imap_uid_list), carray_count(data->imap_uid_list),
897 sizeof(* carray_data(data->imap_uid_list)),
898 (int (*)(const void *, const void *)) cmp_uid);
899
900 /* adds cached UID */
901 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
902 struct uid_cache_item * cache_item;
903 mailmessage * msg;
904
905 cache_item = carray_get(data->imap_uid_list, i);
906
907 msg = mailmessage_new();
908 if (msg == NULL) {
909 res = MAIL_ERROR_MEMORY;
910 goto free;
911 }
912
913 r = mailmessage_init(msg, session, imap_cached_message_driver,
914 cache_item->uid, cache_item->size);
915 if (r != MAIL_NO_ERROR) {
916 mailmessage_free(msg);
917 res = r;
918 goto free;
919 }
920
921 carray_set(tab, i, msg);
922 }
923
924 /* adds new elements */
925 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
926 mailmessage * msg;
927
928 msg = carray_get(env_list->msg_tab, i);
929 carray_set(tab, carray_count(data->imap_uid_list) + i, msg);
930 }
931
932 /* replace list of messages in env_list */
933 carray_free(env_list->msg_tab);
934 env_list->msg_tab = tab;
935
936 r = update_uid_cache(session, env_list);
937 if (r != MAIL_NO_ERROR) {
938 res = r;
939 goto free;
940 }
941#endif
942
943 * result = env_list;
944
945 return MAIL_NO_ERROR;
946
947 free:
948 mailmessage_list_free(env_list);
949 err:
950 return res;
951}
952
953#define IMAP_SET_MAX_COUNT 100
954
955static int get_flags_list(mailsession * session,
956 struct mailmessage_list * env_list)
957{
958 struct mailimap_set * set;
959 struct mailimap_fetch_att * fetch_att;
960 struct mailimap_fetch_type * fetch_type;
961 int res;
962 clist * fetch_result;
963 int r;
964 clist * msg_list;
965#if 0
966 struct imap_session_state_data * data;
967#endif
968 unsigned i;
969 unsigned dest;
970 clistiter * set_iter;
971
972#if 0
973 data = session->data;
974#endif
975
976 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
977 if (fetch_type == NULL) {
978 res = MAIL_ERROR_MEMORY;
979 goto err;
980 }
981
982 fetch_att = mailimap_fetch_att_new_uid();
983 if (fetch_att == NULL) {
984 res = MAIL_ERROR_MEMORY;
985 goto free_fetch_type;
986 }
987
988 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
989 if (r != MAILIMAP_NO_ERROR) {
990 mailimap_fetch_att_free(fetch_att);
991 res = MAIL_ERROR_MEMORY;
992 goto free_fetch_type;
993 }
994
995 fetch_att = mailimap_fetch_att_new_flags();
996 if (fetch_att == NULL) {
997 res = MAIL_ERROR_MEMORY;
998 goto free_fetch_type;
999 }
1000
1001 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1002 if (r != MAILIMAP_NO_ERROR) {
1003 mailimap_fetch_att_free(fetch_att);
1004 res = MAIL_ERROR_MEMORY;
1005 goto free_fetch_type;
1006 }
1007
1008 r = maildriver_env_list_to_msg_list_no_flags(env_list, &msg_list);
1009 if (r != MAIL_NO_ERROR) {
1010 res = MAIL_ERROR_MEMORY;
1011 goto free_fetch_type;
1012 }
1013
1014 if (clist_begin(msg_list) == NULL) {
1015 /* no need to fetch envelopes */
1016
1017 clist_free(msg_list);
1018 mailimap_fetch_type_free(fetch_type);
1019 return MAIL_NO_ERROR;
1020 }
1021
1022 r = msg_list_to_imap_set(msg_list, &set);
1023 if (r != MAIL_NO_ERROR) {
1024 clist_foreach(msg_list, (clist_func) free, NULL);
1025 clist_free(msg_list);
1026 res = MAIL_ERROR_MEMORY;
1027 goto free_fetch_type;
1028 }
1029 clist_foreach(msg_list, (clist_func) free, NULL);
1030 clist_free(msg_list);
1031
1032 set_iter = clist_begin(set->set_list);
1033 while (set_iter != NULL) {
1034 struct mailimap_set * subset;
1035 unsigned int count;
1036
1037 subset = mailimap_set_new_empty();
1038 if (subset == NULL) {
1039 res = MAIL_ERROR_MEMORY;
1040 mailimap_fetch_type_free(fetch_type);
1041 mailimap_set_free(set);
1042 res = MAIL_ERROR_MEMORY;
1043 goto err;
1044 }
1045
1046 count = 0;
1047 while (count < IMAP_SET_MAX_COUNT) {
1048 struct mailimap_set_item * item;
1049
1050 item = clist_content(set_iter);
1051 set_iter = clist_delete(set->set_list, set_iter);
1052
1053 r = mailimap_set_add(subset, item);
1054 if (r != MAILIMAP_NO_ERROR) {
1055 mailimap_set_item_free(item);
1056 mailimap_set_free(subset);
1057 mailimap_fetch_type_free(fetch_type);
1058 mailimap_set_free(set);
1059 res = MAIL_ERROR_MEMORY;
1060 goto err;
1061 }
1062
1063 count ++;
1064
1065 if (set_iter == NULL)
1066 break;
1067 }
1068
1069 r = mailimap_uid_fetch(get_imap_session(session), subset,
1070 fetch_type, &fetch_result);
1071
1072 mailimap_set_free(subset);
1073
1074 switch (r) {
1075 case MAILIMAP_NO_ERROR:
1076 break;
1077 default:
1078 mailimap_fetch_type_free(fetch_type);
1079 mailimap_set_free(set);
1080 return imap_error_to_mail_error(r);
1081 }
1082
1083 if (clist_begin(fetch_result) == NULL) {
1084 res = MAIL_ERROR_FETCH;
1085 goto err;
1086 }
1087
1088 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
1089 mailimap_fetch_list_free(fetch_result);
1090
1091 if (r != MAIL_NO_ERROR) {
1092 mailimap_fetch_type_free(fetch_type);
1093 mailimap_set_free(set);
1094 res = MAIL_ERROR_MEMORY;
1095 goto err;
1096 }
1097 }
1098
1099#if 0
1100 r = mailimap_uid_fetch(get_imap_session(session), set,
1101 fetch_type, &fetch_result);
1102#endif
1103
1104 mailimap_fetch_type_free(fetch_type);
1105 mailimap_set_free(set);
1106
1107#if 0
1108 switch (r) {
1109 case MAILIMAP_NO_ERROR:
1110 break;
1111 default:
1112 return imap_error_to_mail_error(r);
1113 }
1114
1115 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
1116 mailimap_fetch_list_free(fetch_result);
1117
1118 if (r != MAIL_NO_ERROR) {
1119 res = MAIL_ERROR_MEMORY;
1120 goto err;
1121 }
1122#endif
1123
1124 /* remove messages that don't have flags */
1125 i = 0;
1126 dest = 0;
1127 while (i < carray_count(env_list->msg_tab)) {
1128 mailmessage * msg;
1129
1130 msg = carray_get(env_list->msg_tab, i);
1131 if (msg->msg_flags != NULL) {
1132 carray_set(env_list->msg_tab, dest, msg);
1133 dest ++;
1134 }
1135 else {
1136 mailmessage_free(msg);
1137 }
1138 i ++;
1139 }
1140 carray_set_size(env_list->msg_tab, dest);
1141
1142 return MAIL_NO_ERROR;
1143
1144 free_fetch_type:
1145 mailimap_fetch_type_free(fetch_type);
1146 err:
1147 return res;
1148}
1149
1150
1151#define ENV_NAME "env.db"
1152
1153static void get_uid_from_filename(char * filename)
1154{
1155 char * p;
1156
1157 p = strstr(filename, "-part");
1158 if (p != NULL)
1159 * p = 0;
1160 p = strstr(filename, "-envelope");
1161 if (p != NULL)
1162 * p = 0;
1163 p = strstr(filename, "-rfc822");
1164 if (p != NULL)
1165 * p = 0;
1166}
1167
1168static int
1169imapdriver_cached_get_envelopes_list(mailsession * session,
1170 struct mailmessage_list * env_list)
1171{
1172 int r;
1173 int res;
1174 uint32_t i;
1175 struct imap_cached_session_state_data * data;
1176 MMAPString * mmapstr;
1177 struct mail_cache_db * cache_db;
1178 char filename[PATH_MAX];
1179
1180 data = get_cached_data(session);
1181 if (data->imap_quoted_mb == NULL) {
1182 res = MAIL_ERROR_BAD_STATE;
1183 goto err;
1184 }
1185
1186 mmapstr = mmap_string_new("");
1187 if (mmapstr == NULL) {
1188 res = MAIL_ERROR_MEMORY;
1189 goto err;
1190 }
1191
1192 snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME);
1193
1194 r = mail_cache_db_open_lock(filename, &cache_db);
1195 if (r < 0) {
1196 res = MAIL_ERROR_MEMORY;
1197 goto free_mmapstr;
1198 }
1199
1200 /* fill with cached */
1201
1202 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1203 mailmessage * msg;
1204 struct mailimf_fields * fields;
1205
1206 msg = carray_get(env_list->msg_tab, i);
1207
1208 if (msg->msg_fields == NULL) {
1209 r = imapdriver_get_cached_envelope(cache_db, mmapstr,
1210 session, msg, &fields);
1211 if (r == MAIL_NO_ERROR) {
1212 msg->msg_cached = TRUE;
1213 msg->msg_fields = fields;
1214 }
1215 }
1216 }
1217
1218 mail_cache_db_close_unlock(filename, cache_db);
1219
1220 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
1221
1222 check_for_uid_cache(session);
1223
1224 if (r != MAIL_NO_ERROR) {
1225 res = r;
1226 goto free_mmapstr;
1227 }
1228
1229 r = get_flags_list(session, env_list);
1230
1231 if (r != MAIL_NO_ERROR) {
1232 res = r;
1233 goto free_mmapstr;
1234 }
1235
1236#ifdef CACHE_MESSAGE_LIST
1237 r = update_uid_cache(session, env_list);
1238 if (r != MAIL_NO_ERROR) {
1239 res = r;
1240 goto free_mmapstr;
1241 }
1242#endif
1243
1244 /* must write cache */
1245
1246 r = mail_cache_db_open_lock(filename, &cache_db);
1247 if (r < 0) {
1248 res = MAIL_ERROR_MEMORY;
1249 goto free_mmapstr;
1250 }
1251
1252 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1253 mailmessage * msg;
1254
1255 msg = carray_get(env_list->msg_tab, i);
1256
1257 if (msg->msg_fields != NULL) {
1258 if (!msg->msg_cached) {
1259 r = imapdriver_write_cached_envelope(cache_db, mmapstr,
1260 session, msg, msg->msg_fields);
1261 }
1262 }
1263 }
1264
1265 /* flush cache */
1266
1267 maildriver_cache_clean_up(cache_db, NULL, env_list);
1268
1269 mail_cache_db_close_unlock(filename, cache_db);
1270 mmap_string_free(mmapstr);
1271
1272 /* remove cache files */
1273
1274 maildriver_message_cache_clean_up(data->imap_quoted_mb, env_list,
1275 get_uid_from_filename);
1276
1277 return MAIL_NO_ERROR;
1278
1279 free_mmapstr:
1280 mmap_string_free(mmapstr);
1281 err:
1282 return res;
1283}
1284
1285static int imapdriver_cached_remove_message(mailsession * session,
1286 uint32_t num)
1287{
1288 int r;
1289
1290 r = mailsession_remove_message(get_ancestor(session), num);
1291
1292 check_for_uid_cache(session);
1293
1294 return r;
1295}
1296
1297#if 0
1298static int imapdriver_cached_search_messages(mailsession * session,
1299 char * charset,
1300 struct mail_search_key * key,
1301 struct mail_search_result **
1302 result)
1303{
1304 int r;
1305
1306 r = mailsession_search_messages(get_ancestor(session), charset, key, result);
1307
1308 check_for_uid_cache(session);
1309
1310 return r;
1311}
1312#endif
1313
1314static int imapdriver_cached_get_message(mailsession * session,
1315 uint32_t num, mailmessage ** result)
1316{
1317 mailmessage * msg_info;
1318 int r;
1319
1320 msg_info = mailmessage_new();
1321 if (msg_info == NULL)
1322 return MAIL_ERROR_MEMORY;
1323
1324 r = mailmessage_init(msg_info, session, imap_cached_message_driver, num, 0);
1325 if (r != MAIL_NO_ERROR) {
1326 mailmessage_free(msg_info);
1327 return r;
1328 }
1329
1330 * result = msg_info;
1331
1332 return MAIL_NO_ERROR;
1333}
1334
1335/* Retrieve a message by UID
1336 * libEtPan! uid format for IMAP is "UIDVALIDITY-UID"
1337 * where UIDVALIDITY and UID are decimal representation of
1338 * respectively uidvalidity and uid numbers.
1339 * Return value:
1340 * MAIL_ERROR_INVAL if uid is NULL or has an incorrect format.
1341 * MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found
1342 * MAIL_NO_ERROR if message was found. Result is in result
1343 */
1344static int imapdriver_cached_get_message_by_uid(mailsession * session,
1345 const char * uid,
1346 mailmessage ** result)
1347{
1348 uint32_t uidvalidity;
1349 uint32_t num;
1350 char * p1, * p2;
1351 mailimap *imap;
1352
1353 if (uid == NULL)
1354 return MAIL_ERROR_INVAL;
1355
1356 uidvalidity = strtoul(uid, &p1, 10);
1357 if (p1 == uid || * p1 != '-')
1358 return MAIL_ERROR_INVAL;
1359
1360 p1++;
1361 num = strtoul(p1, &p2, 10);
1362 if (p2 == p1 || * p2 != '\0')
1363 return MAIL_ERROR_INVAL;
1364
1365 imap = get_imap_session(session);
1366 if (imap->imap_selection_info->sel_uidvalidity != uidvalidity)
1367 return MAIL_ERROR_MSG_NOT_FOUND;
1368
1369 return imapdriver_cached_get_message(session, num, result);
1370}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_CACHED_H
37
38#define IMAPDRIVER_CACHED_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * imap_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_cached_message.h"
37
38#include "imapdriver_tools.h"
39#include "imapdriver_message.h"
40#include "imapdriver_cached.h"
41#include "imapdriver_types.h"
42#include "imapdriver.h"
43#include "mailmessage.h"
44#include "generic_cache.h"
45#include "mail_cache_db.h"
46
47#include <string.h>
48#include <stdlib.h>
49
50static int imap_initialize(mailmessage * msg_info);
51
52static void imap_uninitialize(mailmessage * msg_info);
53
54static void imap_flush(mailmessage * msg_info);
55
56static void imap_check(mailmessage * msg_info);
57
58static void imap_fetch_result_free(mailmessage * msg_info,
59 char * msg);
60
61static int imap_fetch(mailmessage * msg_info,
62 char ** result,
63 size_t * result_len);
64
65static int imap_fetch_header(mailmessage * msg_info,
66 char ** result,
67 size_t * result_len);
68
69static int imap_fetch_body(mailmessage * msg_info,
70 char ** result, size_t * result_len);
71
72static int imap_fetch_size(mailmessage * msg_info,
73 size_t * result);
74
75static int imap_get_bodystructure(mailmessage * msg_info,
76 struct mailmime ** result);
77
78static int imap_fetch_section(mailmessage * msg_info,
79 struct mailmime * mime,
80 char ** result, size_t * result_len);
81
82static int imap_fetch_section_header(mailmessage * msg_info,
83 struct mailmime * mime,
84 char ** result,
85 size_t * result_len);
86
87static int imap_fetch_section_mime(mailmessage * msg_info,
88 struct mailmime * mime,
89 char ** result,
90 size_t * result_len);
91
92static int imap_fetch_section_body(mailmessage * msg_info,
93 struct mailmime * mime,
94 char ** result,
95 size_t * result_len);
96
97
98static int imap_fetch_envelope(mailmessage * msg_info,
99 struct mailimf_fields ** result);
100
101static int imap_get_flags(mailmessage * msg_info,
102 struct mail_flags ** result);
103
104static mailmessage_driver local_imap_cached_message_driver = {
105 .msg_name = "imap-cached",
106
107 .msg_initialize = imap_initialize,
108 .msg_uninitialize = imap_uninitialize,
109
110 .msg_flush = imap_flush,
111 .msg_check = imap_check,
112
113 .msg_fetch_result_free = imap_fetch_result_free,
114
115 .msg_fetch = imap_fetch,
116 .msg_fetch_header = imap_fetch_header,
117 .msg_fetch_body = imap_fetch_body,
118 .msg_fetch_size = imap_fetch_size,
119 .msg_get_bodystructure = imap_get_bodystructure,
120 .msg_fetch_section = imap_fetch_section,
121 .msg_fetch_section_header = imap_fetch_section_header,
122 .msg_fetch_section_mime = imap_fetch_section_mime,
123 .msg_fetch_section_body = imap_fetch_section_body,
124 .msg_fetch_envelope = imap_fetch_envelope,
125
126 .msg_get_flags = imap_get_flags,
127};
128
129mailmessage_driver * imap_cached_message_driver =
130&local_imap_cached_message_driver;
131
132static inline struct imap_cached_session_state_data *
133get_cached_session_data(mailmessage * msg)
134{
135 return msg->msg_session->sess_data;
136}
137
138static inline mailmessage * get_ancestor(mailmessage * msg_info)
139{
140 return msg_info->msg_data;
141}
142
143static inline struct imap_cached_session_state_data *
144cached_session_get_data(mailsession * s)
145{
146 return s->sess_data;
147}
148
149static inline mailsession * cached_session_get_ancestor(mailsession * s)
150{
151 return cached_session_get_data(s)->imap_ancestor;
152}
153
154static inline struct imap_session_state_data *
155cached_session_get_ancestor_data(mailsession * s)
156{
157 return cached_session_get_ancestor(s)->sess_data;
158}
159
160static inline mailimap *
161cached_session_get_imap_session(mailsession * session)
162{
163 return cached_session_get_ancestor_data(session)->imap_session;
164}
165
166static inline mailimap * get_imap_session(mailmessage * msg)
167{
168 return cached_session_get_imap_session(msg->msg_session);
169}
170
171static inline mailsession * get_ancestor_session(mailmessage * msg_info)
172{
173 return cached_session_get_ancestor(msg_info->msg_session);
174}
175
176
177static void generate_key_from_mime_section(char * key, size_t size,
178 struct mailmime * mime)
179{
180 clistiter * cur;
181 MMAPString * gstr;
182 struct mailmime_section * part;
183 int r;
184
185 snprintf(key, size, "unvalid");
186
187 r = mailmime_get_section_id(mime, &part);
188 if (r != MAILIMF_NO_ERROR)
189 goto err;
190
191 gstr = mmap_string_new("part");
192 if (gstr == NULL)
193 goto free_section;
194
195 for(cur = clist_begin(part->sec_list) ;
196 cur != NULL ; cur = clist_next(cur)) {
197 char s[20];
198
199 snprintf(s, 20, ".%u", * (uint32_t *) clist_content(cur));
200 if (mmap_string_append(gstr, s) == NULL)
201 goto free_str;
202 }
203
204 snprintf(key, size, "%s", gstr->str);
205
206 mmap_string_free(gstr);
207 mailmime_section_free(part);
208
209 return;
210
211 free_str:
212 mmap_string_free(gstr);
213 free_section:
214 mailmime_section_free(part);
215 err:;
216}
217
218static void generate_key_from_section(char * key, size_t size,
219 mailmessage * msg_info,
220 struct mailmime * mime, int type)
221{
222 char section_str[PATH_MAX];
223
224 generate_key_from_mime_section(section_str, PATH_MAX, mime);
225
226 switch (type) {
227 case IMAP_SECTION_MESSAGE:
228 snprintf(key, size, "%s-%s", msg_info->msg_uid, section_str);
229 break;
230 case IMAP_SECTION_HEADER:
231 snprintf(key, size, "%s-%s-header", msg_info->msg_uid, section_str);
232 break;
233 case IMAP_SECTION_MIME:
234 snprintf(key, size, "%s-%s-mime", msg_info->msg_uid, section_str);
235 break;
236 case IMAP_SECTION_BODY:
237 snprintf(key, size, "%s-%s-text", msg_info->msg_uid, section_str);
238 break;
239 }
240}
241
242static void generate_key_from_message(char * key, size_t size,
243 mailmessage * msg_info,
244 int type)
245{
246 switch (type) {
247 case MAILIMAP_MSG_ATT_RFC822:
248 snprintf(key, size, "%s-rfc822", msg_info->msg_uid);
249 break;
250 case MAILIMAP_MSG_ATT_RFC822_HEADER:
251 snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid);
252 break;
253 case MAILIMAP_MSG_ATT_RFC822_TEXT:
254 snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid);
255 break;
256 case MAILIMAP_MSG_ATT_ENVELOPE:
257 snprintf(key, size, "%s-envelope", msg_info->msg_uid);
258 break;
259 }
260}
261
262static void build_cache_name(char * filename, size_t size,
263 mailmessage * msg, char * key)
264{
265 char * quoted_mb;
266
267 quoted_mb = get_cached_session_data(msg)->imap_quoted_mb;
268
269 snprintf(filename, size, "%s/%s", quoted_mb, key);
270}
271
272static int imap_initialize(mailmessage * msg_info)
273{
274 mailmessage * ancestor;
275 int r;
276 char key[PATH_MAX];
277 char * uid;
278 mailimap * imap;
279
280 ancestor = mailmessage_new();
281 if (ancestor == NULL)
282 return MAIL_ERROR_MEMORY;
283
284 r = mailmessage_init(ancestor, get_ancestor_session(msg_info),
285 imap_message_driver,
286 msg_info->msg_index, 0);
287 if (r != MAIL_NO_ERROR) {
288 mailmessage_free(ancestor);
289 return r;
290 }
291
292 imap = get_imap_session(msg_info);
293
294 snprintf(key, PATH_MAX, "%u-%u",
295 imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index);
296 uid = strdup(key);
297 if (uid == NULL) {
298 mailmessage_free(ancestor);
299 return MAIL_ERROR_MEMORY;
300 }
301
302 msg_info->msg_data = ancestor;
303 msg_info->msg_uid = uid;
304
305 return MAIL_NO_ERROR;
306}
307
308static void imap_uninitialize(mailmessage * msg_info)
309{
310 mailmessage_free(get_ancestor(msg_info));
311 msg_info->msg_data = NULL;
312}
313
314static void imap_flush(mailmessage * msg_info)
315{
316 if (msg_info->msg_mime != NULL) {
317 mailmime_free(msg_info->msg_mime);
318 msg_info->msg_mime = NULL;
319 }
320}
321
322static void imap_check(mailmessage * msg_info)
323{
324 get_ancestor(msg_info)->msg_flags = msg_info->msg_flags;
325 mailmessage_check(get_ancestor(msg_info));
326 get_ancestor(msg_info)->msg_flags = NULL;
327}
328
329static void imap_fetch_result_free(mailmessage * msg_info,
330 char * msg)
331{
332 mailmessage_fetch_result_free(get_ancestor(msg_info), msg);
333}
334
335static int imap_fetch(mailmessage * msg_info,
336 char ** result,
337 size_t * result_len)
338{
339 char key[PATH_MAX];
340 char filename[PATH_MAX];
341 int r;
342 char * str;
343 size_t len;
344
345 generate_key_from_message(key, PATH_MAX,
346 msg_info, MAILIMAP_MSG_ATT_RFC822);
347
348 build_cache_name(filename, PATH_MAX, msg_info, key);
349
350 r = generic_cache_read(filename, &str, &len);
351 if (r == MAIL_NO_ERROR) {
352 * result = str;
353 * result_len = len;
354
355 return MAIL_NO_ERROR;
356 }
357
358 r = mailmessage_fetch(get_ancestor(msg_info),
359 result, result_len);
360 if (r == MAIL_NO_ERROR)
361 generic_cache_store(filename, * result, strlen(* result));
362
363 return r;
364}
365
366static int imap_fetch_header(mailmessage * msg_info,
367 char ** result,
368 size_t * result_len)
369{
370 char key[PATH_MAX];
371 char filename[PATH_MAX];
372 int r;
373 char * str;
374 size_t len;
375
376 generate_key_from_message(key, PATH_MAX,
377 msg_info, MAILIMAP_MSG_ATT_RFC822_HEADER);
378
379 build_cache_name(filename, PATH_MAX, msg_info, key);
380
381 r = generic_cache_read(filename, &str, &len);
382 if (r == MAIL_NO_ERROR) {
383 * result = str;
384 * result_len = len;
385
386 return MAIL_NO_ERROR;
387 }
388
389 r = mailmessage_fetch_header(get_ancestor(msg_info), result,
390 result_len);
391 if (r == MAIL_NO_ERROR)
392 generic_cache_store(filename, * result, * result_len);
393
394 return r;
395}
396
397static int imap_fetch_body(mailmessage * msg_info,
398 char ** result, size_t * result_len)
399{
400 char key[PATH_MAX];
401 char filename[PATH_MAX];
402 int r;
403 char * str;
404 size_t len;
405
406 generate_key_from_message(key, PATH_MAX,
407 msg_info, MAILIMAP_MSG_ATT_RFC822_TEXT);
408
409 build_cache_name(filename, PATH_MAX, msg_info, key);
410
411 r = generic_cache_read(filename, &str, &len);
412 if (r == MAIL_NO_ERROR) {
413 * result = str;
414 * result_len = len;
415 return MAIL_NO_ERROR;
416 }
417
418 r = mailmessage_fetch_body(get_ancestor(msg_info), result,
419 result_len);
420 if (r == MAIL_NO_ERROR)
421 generic_cache_store(filename, * result, * result_len);
422
423 return r;
424}
425
426static int imap_fetch_size(mailmessage * msg_info,
427 size_t * result)
428{
429 return mailmessage_fetch_size(get_ancestor(msg_info), result);
430}
431
432static int imap_get_bodystructure(mailmessage * msg_info,
433 struct mailmime ** result)
434{
435 int r;
436
437 if (msg_info->msg_mime != NULL) {
438 * result = msg_info->msg_mime;
439
440 return MAIL_NO_ERROR;
441 }
442
443 r = mailmessage_get_bodystructure(get_ancestor(msg_info),
444 result);
445 if (r == MAIL_NO_ERROR) {
446 msg_info->msg_mime = get_ancestor(msg_info)->msg_mime;
447 get_ancestor(msg_info)->msg_mime = NULL;
448 }
449
450 return r;
451}
452
453static int imap_fetch_section(mailmessage * msg_info,
454 struct mailmime * mime,
455 char ** result, size_t * result_len)
456{
457 char key[PATH_MAX];
458 char filename[PATH_MAX];
459 int r;
460 char * str;
461 size_t len;
462
463 generate_key_from_section(key, PATH_MAX,
464 msg_info, mime, IMAP_SECTION_MESSAGE);
465
466 build_cache_name(filename, PATH_MAX, msg_info, key);
467
468 r = generic_cache_read(filename, &str, &len);
469 if (r == MAIL_NO_ERROR) {
470 * result = str;
471 * result_len = len;
472
473 return MAIL_NO_ERROR;
474 }
475
476 r = mailmessage_fetch_section(get_ancestor(msg_info),
477 mime, result, result_len);
478 if (r == MAIL_NO_ERROR)
479 generic_cache_store(filename, * result, * result_len);
480
481 return r;
482}
483
484static int imap_fetch_section_header(mailmessage * msg_info,
485 struct mailmime * mime,
486 char ** result,
487 size_t * result_len)
488{
489 char key[PATH_MAX];
490 char filename[PATH_MAX];
491 int r;
492 char * str;
493 size_t len;
494
495 generate_key_from_section(key, PATH_MAX,
496 msg_info, mime, IMAP_SECTION_HEADER);
497
498 build_cache_name(filename, PATH_MAX, msg_info, key);
499
500 r = generic_cache_read(filename, &str, &len);
501 if (r == MAIL_NO_ERROR) {
502 * result = str;
503 * result_len = len;
504
505 return MAIL_NO_ERROR;
506 }
507
508 r = mailmessage_fetch_section_header(get_ancestor(msg_info),
509 mime, result, result_len);
510 if (r == MAIL_NO_ERROR)
511 generic_cache_store(filename, * result, * result_len);
512
513 return r;
514}
515
516static int imap_fetch_section_mime(mailmessage * msg_info,
517 struct mailmime * mime,
518 char ** result,
519 size_t * result_len)
520{
521 char key[PATH_MAX];
522 char filename[PATH_MAX];
523 int r;
524 char * str;
525 size_t len;
526
527 generate_key_from_section(key, PATH_MAX,
528 msg_info, mime, IMAP_SECTION_MIME);
529
530 build_cache_name(filename, PATH_MAX, msg_info, key);
531
532 r = generic_cache_read(filename, &str, &len);
533 if (r == MAIL_NO_ERROR) {
534 * result = str;
535 * result_len = len;
536
537 return MAIL_NO_ERROR;
538 }
539
540 r = mailmessage_fetch_section_mime(get_ancestor(msg_info),
541 mime, result, result_len);
542 if (r == MAIL_NO_ERROR)
543 generic_cache_store(filename, * result, * result_len);
544
545 return r;
546}
547
548static int imap_fetch_section_body(mailmessage * msg_info,
549 struct mailmime * mime,
550 char ** result,
551 size_t * result_len)
552{
553 char key[PATH_MAX];
554 char filename[PATH_MAX];
555 int r;
556 char * str;
557 size_t len;
558
559 generate_key_from_section(key, PATH_MAX,
560 msg_info, mime, IMAP_SECTION_BODY);
561
562 build_cache_name(filename, PATH_MAX, msg_info, key);
563
564 r = generic_cache_read(filename, &str, &len);
565 if (r == MAIL_NO_ERROR) {
566
567 * result = str;
568 * result_len = len;
569
570 return MAIL_NO_ERROR;
571 }
572
573 r = mailmessage_fetch_section_body(get_ancestor(msg_info),
574 mime, result, result_len);
575 if (r == MAIL_NO_ERROR)
576 generic_cache_store(filename, * result, * result_len);
577
578 return r;
579}
580
581static int imap_get_flags(mailmessage * msg_info,
582 struct mail_flags ** result)
583{
584 int r;
585 struct mail_flags * flags;
586
587 if (msg_info->msg_flags != NULL) {
588 * result = msg_info->msg_flags;
589 return MAIL_NO_ERROR;
590 }
591
592 r = mailmessage_get_flags(get_ancestor(msg_info), &flags);
593 if (r != MAIL_NO_ERROR)
594 return r;
595
596 get_ancestor(msg_info)->msg_flags = NULL;
597 msg_info->msg_flags = flags;
598 * result = flags;
599
600 return MAIL_NO_ERROR;
601}
602
603#define ENV_NAME "env.db"
604
605static int imap_fetch_envelope(mailmessage * msg_info,
606 struct mailimf_fields ** result)
607{
608 struct mailimf_fields * fields;
609 int r;
610 struct mail_cache_db * cache_db;
611 MMAPString * mmapstr;
612 char filename[PATH_MAX];
613 struct imap_cached_session_state_data * data;
614 int res;
615
616 data = get_cached_session_data(msg_info);
617 if (data->imap_quoted_mb == NULL) {
618 res = MAIL_ERROR_BAD_STATE;
619 goto err;
620 }
621
622 snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME);
623
624 r = mail_cache_db_open_lock(filename, &cache_db);
625 if (r < 0) {
626 res = MAIL_ERROR_MEMORY;
627 goto err;
628 }
629
630 mmapstr = mmap_string_new("");
631 if (mmapstr == NULL) {
632 res = MAIL_ERROR_MEMORY;
633 goto close_db;
634 }
635
636 r = imapdriver_get_cached_envelope(cache_db, mmapstr,
637 msg_info->msg_session, msg_info, &fields);
638
639 if ((r != MAIL_ERROR_CACHE_MISS) && (r != MAIL_NO_ERROR)) {
640 res = r;
641 goto close_db;
642 }
643
644 r = mailmessage_fetch_envelope(get_ancestor(msg_info), &fields);
645 if (r != MAIL_NO_ERROR) {
646 res = r;
647 goto close_db;
648 }
649
650 r = imapdriver_write_cached_envelope(cache_db, mmapstr,
651 msg_info->msg_session, msg_info, fields);
652
653 * result = fields;
654
655 mmap_string_free(mmapstr);
656 mail_cache_db_close_unlock(filename, cache_db);
657
658 return MAIL_NO_ERROR;
659
660 close_db:
661 mail_cache_db_close_unlock(filename, cache_db);
662 err:
663 return res;
664}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_CACHED_MESSAGE_H
37
38#define IMAPDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * imap_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_message.h"
37
38#include "imapdriver_tools.h"
39#include "imapdriver.h"
40#include "imapdriver_types.h"
41#include "mailimap.h"
42#include "maildriver_tools.h"
43#include "generic_cache.h"
44
45#include <stdlib.h>
46#include <string.h>
47
48static int imap_initialize(mailmessage * msg_info);
49
50static void imap_fetch_result_free(mailmessage * msg_info,
51 char * msg);
52
53static int imap_fetch(mailmessage * msg_info,
54 char ** result,
55 size_t * result_len);
56
57static int imap_fetch_header(mailmessage * msg_info,
58 char ** result,
59 size_t * result_len);
60
61static int imap_fetch_body(mailmessage * msg_info,
62 char ** result, size_t * result_len);
63
64static int imap_fetch_size(mailmessage * msg_info,
65 size_t * result);
66
67static int imap_get_bodystructure(mailmessage * msg_info,
68 struct mailmime ** result);
69
70static int imap_fetch_section(mailmessage * msg_info,
71 struct mailmime * mime,
72 char ** result, size_t * result_len);
73
74static int imap_fetch_section_header(mailmessage * msg_info,
75 struct mailmime * mime,
76 char ** result,
77 size_t * result_len);
78
79static int imap_fetch_section_mime(mailmessage * msg_info,
80 struct mailmime * mime,
81 char ** result,
82 size_t * result_len);
83
84static int imap_fetch_section_body(mailmessage * msg_info,
85 struct mailmime * mime,
86 char ** result,
87 size_t * result_len);
88
89static int imap_fetch_envelope(mailmessage * msg_info,
90 struct mailimf_fields ** result);
91
92static int imap_get_flags(mailmessage * msg_info,
93 struct mail_flags ** result);
94
95static void imap_flush(mailmessage * msg_info);
96
97static void imap_check(mailmessage * msg_info);
98
99static mailmessage_driver local_imap_message_driver = {
100 .msg_name = "imap",
101
102 .msg_initialize = imap_initialize,
103 .msg_uninitialize = NULL,
104
105 .msg_flush = imap_flush,
106 .msg_check = imap_check,
107
108 .msg_fetch_result_free = imap_fetch_result_free,
109
110 .msg_fetch = imap_fetch,
111 .msg_fetch_header = imap_fetch_header,
112 .msg_fetch_body = imap_fetch_body,
113 .msg_fetch_size = imap_fetch_size,
114 .msg_get_bodystructure = imap_get_bodystructure,
115 .msg_fetch_section = imap_fetch_section,
116 .msg_fetch_section_header = imap_fetch_section_header,
117 .msg_fetch_section_mime = imap_fetch_section_mime,
118 .msg_fetch_section_body = imap_fetch_section_body,
119 .msg_fetch_envelope = imap_fetch_envelope,
120
121 .msg_get_flags = imap_get_flags,
122};
123
124mailmessage_driver * imap_message_driver = &local_imap_message_driver;
125
126static inline struct imap_session_state_data *
127get_session_data(mailmessage * msg)
128{
129 return msg->msg_session->sess_data;
130}
131
132static inline mailimap * get_imap_session(mailmessage * msg)
133{
134 return get_session_data(msg)->imap_session;
135}
136
137
138
139static int imap_initialize(mailmessage * msg_info)
140{
141 char key[PATH_MAX];
142 char * uid;
143 mailimap * imap;
144
145 imap = get_imap_session(msg_info);
146
147 snprintf(key, PATH_MAX, "%u-%u",
148 imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index);
149
150 uid = strdup(key);
151 if (uid == NULL) {
152 return MAIL_ERROR_MEMORY;
153 }
154
155 msg_info->msg_uid = uid;
156
157 return MAIL_NO_ERROR;
158}
159
160
161static void imap_fetch_result_free(mailmessage * msg_info,
162 char * msg)
163{
164 if (msg != NULL) {
165 if (mmap_string_unref(msg) != 0)
166 free(msg);
167 }
168}
169
170
171static void imap_flush(mailmessage * msg_info)
172{
173 if (msg_info->msg_mime != NULL) {
174 mailmime_free(msg_info->msg_mime);
175 msg_info->msg_mime = NULL;
176 }
177}
178
179static void imap_check(mailmessage * msg_info)
180{
181 int r;
182
183 if (msg_info->msg_flags != NULL) {
184 r = mail_flags_store_set(get_session_data(msg_info)->imap_flags_store,
185 msg_info);
186 /* ignore errors */
187 }
188}
189
190static int imap_fetch(mailmessage * msg_info,
191 char ** result,
192 size_t * result_len)
193{
194 int r;
195 struct mailimap_set * set;
196 struct mailimap_fetch_att * fetch_att;
197 struct mailimap_fetch_type * fetch_type;
198 clist * fetch_result;
199 struct mailimap_msg_att * msg_att;
200 struct mailimap_msg_att_item * msg_att_item;
201 char * text;
202 size_t text_length;
203 int res;
204 clistiter * cur;
205 struct mailimap_section * section;
206
207 set = mailimap_set_new_single(msg_info->msg_index);
208 if (set == NULL) {
209 res = MAIL_ERROR_MEMORY;
210 goto err;
211 }
212
213#if 0
214 fetch_att = mailimap_fetch_att_new_rfc822();
215 if (fetch_att == NULL) {
216 res = MAIL_ERROR_MEMORY;
217 goto free_set;
218 }
219
220 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
221 if (fetch_type == NULL) {
222 res = MAIL_ERROR_MEMORY;
223 goto free_fetch_att;
224 }
225
226 r = mailimap_uid_fetch(get_imap_session(msg_info->session), set,
227 fetch_type, &fetch_result);
228
229 mailimap_fetch_type_free(fetch_type);
230#endif
231
232 section = mailimap_section_new(NULL);
233 if (section == NULL) {
234 res = MAIL_ERROR_MEMORY;
235 goto free_set;
236 }
237
238 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
239 if (fetch_att == NULL) {
240 mailimap_section_free(section);
241 res = MAIL_ERROR_MEMORY;
242 goto free_set;
243 }
244
245 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
246 if (fetch_type == NULL) {
247 res = MAIL_ERROR_MEMORY;
248 goto free_fetch_att;
249 }
250
251 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
252 fetch_type, &fetch_result);
253
254 mailimap_fetch_type_free(fetch_type);
255 mailimap_set_free(set);
256
257 switch (r) {
258 case MAILIMAP_NO_ERROR:
259 break;
260 default:
261 return imap_error_to_mail_error(r);
262 }
263
264 if (clist_begin(fetch_result) == NULL) {
265 mailimap_fetch_list_free(fetch_result);
266 return MAIL_ERROR_FETCH;
267 }
268
269 msg_att = clist_begin(fetch_result)->data;
270
271 text = NULL;
272 text_length = 0;
273
274 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
275 cur = clist_next(cur)) {
276 msg_att_item = clist_content(cur);
277
278 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
279#if 0
280 if (msg_att_item->msg_att_static->type == MAILIMAP_MSG_ATT_RFC822) {
281 text = msg_att_item->msg_att_static->rfc822;
282 msg_att_item->msg_att_static->rfc822 = NULL;
283 text_length = msg_att_item->msg_att_static->length;
284 }
285#endif
286 if (msg_att_item->att_data.att_static->att_type ==
287 MAILIMAP_MSG_ATT_BODY_SECTION) {
288 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
289 /* detach */
290 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
291 text_length =
292 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
293 }
294 }
295 }
296
297 mailimap_fetch_list_free(fetch_result);
298
299 if (text == NULL)
300 return MAIL_ERROR_FETCH;
301
302 * result = text;
303 * result_len = text_length;
304
305 return MAIL_NO_ERROR;
306
307 free_fetch_att:
308 mailimap_fetch_att_free(fetch_att);
309 free_set:
310 mailimap_set_free(set);
311 err:
312 return res;
313}
314
315static int imap_fetch_header(mailmessage * msg_info,
316 char ** result,
317 size_t * result_len)
318{
319 int r;
320 struct mailimap_set * set;
321 struct mailimap_fetch_att * fetch_att;
322 struct mailimap_fetch_type * fetch_type;
323 clist * fetch_result;
324 struct mailimap_msg_att * msg_att;
325 struct mailimap_msg_att_item * msg_att_item;
326 char * text;
327 size_t text_length;
328 int res;
329 clistiter * cur;
330 struct mailimap_section * section;
331
332 set = mailimap_set_new_single(msg_info->msg_index);
333 if (set == NULL) {
334 res = MAIL_ERROR_MEMORY;
335 goto err;
336 }
337
338#if 0
339 fetch_att = mailimap_fetch_att_new_rfc822_header();
340 if (fetch_att == NULL) {
341 res = MAIL_ERROR_MEMORY;
342 goto free_set;
343 }
344
345 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
346 if (fetch_type == NULL) {
347 res = MAIL_ERROR_MEMORY;
348 goto free_fetch_att;
349 }
350
351 r = mailimap_uid_fetch(get_imap_session(msg_info->session),
352 set, fetch_type, &fetch_result);
353
354 mailimap_fetch_type_free(fetch_type);
355#endif
356
357 section = mailimap_section_new_header();
358 if (section == NULL) {
359 res = MAIL_ERROR_MEMORY;
360 goto free_set;
361 }
362
363 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
364 if (fetch_att == NULL) {
365 mailimap_section_free(section);
366 res = MAIL_ERROR_MEMORY;
367 goto free_set;
368 }
369
370 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
371 if (fetch_type == NULL) {
372 res = MAIL_ERROR_MEMORY;
373 goto free_fetch_att;
374 }
375
376 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
377 fetch_type, &fetch_result);
378
379 mailimap_fetch_type_free(fetch_type);
380 mailimap_set_free(set);
381
382 switch (r) {
383 case MAILIMAP_NO_ERROR:
384 break;
385 default:
386 return imap_error_to_mail_error(r);
387 }
388
389 if (clist_begin(fetch_result) == NULL) {
390 mailimap_fetch_list_free(fetch_result);
391 return MAIL_ERROR_FETCH;
392 }
393
394 msg_att = clist_begin(fetch_result)->data;
395
396 text = NULL;
397 text_length = 0;
398
399 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
400 cur = clist_next(cur)) {
401 msg_att_item = clist_content(cur);
402
403 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
404#if 0
405 if (msg_att_item->msg_att_static->type ==
406 MAILIMAP_MSG_ATT_RFC822_HEADER) {
407 text = msg_att_item->msg_att_static->rfc822_header;
408 msg_att_item->msg_att_static->rfc822_header = NULL;
409 text_length = msg_att_item->msg_att_static->length;
410 }
411#endif
412 if (msg_att_item->att_data.att_static->att_type ==
413 MAILIMAP_MSG_ATT_BODY_SECTION) {
414 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
415 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
416 text_length =
417 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
418 }
419 }
420 }
421
422 mailimap_fetch_list_free(fetch_result);
423
424 if (text == NULL)
425 return MAIL_ERROR_FETCH;
426
427 * result = text;
428 * result_len = text_length;
429
430 return MAIL_NO_ERROR;
431
432 free_fetch_att:
433 mailimap_fetch_att_free(fetch_att);
434 free_set:
435 mailimap_set_free(set);
436 err:
437 return res;
438}
439
440static int imap_fetch_body(mailmessage * msg_info,
441 char ** result, size_t * result_len)
442{
443 int r;
444 struct mailimap_set * set;
445 struct mailimap_fetch_att * fetch_att;
446 struct mailimap_fetch_type * fetch_type;
447 clist * fetch_result;
448 struct mailimap_msg_att * msg_att;
449 struct mailimap_msg_att_item * msg_att_item;
450 char * text;
451 size_t text_length;
452 int res;
453 clistiter * cur;
454 struct mailimap_section * section;
455
456 set = mailimap_set_new_single(msg_info->msg_index);
457 if (set == NULL) {
458 res = MAIL_ERROR_MEMORY;
459 goto err;
460 }
461
462#if 0
463 fetch_att = mailimap_fetch_att_new_rfc822_text();
464 if (fetch_att == NULL) {
465 res = MAIL_ERROR_MEMORY;
466 goto free_set;
467 }
468
469 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
470 if (fetch_type == NULL) {
471 res = MAIL_ERROR_MEMORY;
472 goto free_fetch_att;
473 }
474
475 r = mailimap_uid_fetch(get_imap_session(msg_info->session), set,
476 fetch_type, &fetch_result);
477
478 mailimap_fetch_type_free(fetch_type);
479#endif
480 section = mailimap_section_new_text();
481 if (section == NULL) {
482 res = MAIL_ERROR_MEMORY;
483 goto free_set;
484 }
485
486 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
487 if (fetch_att == NULL) {
488 mailimap_section_free(section);
489 res = MAIL_ERROR_MEMORY;
490 goto free_set;
491 }
492
493 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
494 if (fetch_type == NULL) {
495 res = MAIL_ERROR_MEMORY;
496 goto free_fetch_att;
497 }
498
499 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
500 fetch_type, &fetch_result);
501
502 mailimap_fetch_type_free(fetch_type);
503 mailimap_set_free(set);
504
505 switch (r) {
506 case MAILIMAP_NO_ERROR:
507 break;
508 default:
509 return imap_error_to_mail_error(r);
510 }
511
512 cur = clist_begin(fetch_result);
513 if (cur == NULL) {
514 mailimap_fetch_list_free(fetch_result);
515 return MAIL_ERROR_FETCH;
516 }
517
518 msg_att = clist_content(cur);
519
520 text = NULL;
521 text_length = 0;
522
523 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
524 cur = clist_next(cur)) {
525 msg_att_item = clist_content(cur);
526
527 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
528#if 0
529 if (msg_att_item->msg_att_static->type ==
530 MAILIMAP_MSG_ATT_RFC822_TEXT) {
531 text = msg_att_item->msg_att_static->rfc822_text;
532 msg_att_item->msg_att_static->rfc822_text = NULL;
533 text_length = msg_att_item->msg_att_static->length;
534 }
535#endif
536 if (msg_att_item->att_data.att_static->att_type ==
537 MAILIMAP_MSG_ATT_BODY_SECTION) {
538 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
539 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
540 text_length =
541 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
542 }
543 }
544 }
545
546 mailimap_fetch_list_free(fetch_result);
547
548 if (text == NULL)
549 return MAIL_ERROR_FETCH;
550
551 * result = text;
552 * result_len = text_length;
553
554 return MAIL_NO_ERROR;
555
556 free_fetch_att:
557 mailimap_fetch_att_free(fetch_att);
558 free_set:
559 mailimap_set_free(set);
560 err:
561 return res;
562}
563
564static int imap_fetch_size(mailmessage * msg_info,
565 size_t * result)
566{
567 int r;
568 struct mailimap_set * set;
569 struct mailimap_fetch_att * fetch_att;
570 struct mailimap_fetch_type * fetch_type;
571 clist * fetch_result;
572 struct mailimap_msg_att * msg_att;
573 struct mailimap_msg_att_item * msg_att_item;
574 size_t size;
575 int res;
576 clistiter * cur;
577
578 set = mailimap_set_new_single(msg_info->msg_index);
579 if (set == NULL) {
580 res = MAIL_ERROR_MEMORY;
581 goto err;
582 }
583
584 fetch_att = mailimap_fetch_att_new_rfc822_size();
585 if (fetch_att == NULL) {
586 res = MAIL_ERROR_MEMORY;
587 goto free_set;
588 }
589
590 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
591 if (fetch_type == NULL) {
592 res = MAIL_ERROR_MEMORY;
593 goto free_fetch_att;
594 }
595
596 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
597 fetch_type, &fetch_result);
598
599 mailimap_fetch_type_free(fetch_type);
600 mailimap_set_free(set);
601
602 switch (r) {
603 case MAILIMAP_ERROR_BAD_STATE:
604 return MAIL_ERROR_BAD_STATE;
605 case MAILIMAP_ERROR_STREAM:
606 return MAIL_ERROR_STREAM;
607 case MAILIMAP_NO_ERROR:
608 break;
609 default:
610 return MAIL_ERROR_FETCH;
611 }
612
613 if (clist_begin(fetch_result) == NULL) {
614 mailimap_fetch_list_free(fetch_result);
615 return MAIL_ERROR_FETCH;
616 }
617
618 msg_att = clist_begin(fetch_result)->data;
619
620 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
621 cur = clist_next(cur)) {
622 msg_att_item = clist_content(cur);
623
624 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
625
626 if (msg_att_item->att_data.att_static->att_type ==
627 MAILIMAP_MSG_ATT_RFC822_SIZE) {
628 size = msg_att_item->att_data.att_static->att_data.att_rfc822_size;
629
630 * result = size;
631
632 mailimap_fetch_list_free(fetch_result);
633 return MAIL_NO_ERROR;
634 }
635 }
636 }
637
638 mailimap_fetch_list_free(fetch_result);
639
640 return MAIL_ERROR_FETCH;
641
642 free_fetch_att:
643 mailimap_fetch_att_free(fetch_att);
644 free_set:
645 mailimap_set_free(set);
646 err:
647 return res;
648}
649
650static int imap_get_bodystructure(mailmessage * msg_info,
651 struct mailmime ** result)
652{
653 int r;
654 struct mailimap_set * set;
655 struct mailimap_fetch_att * fetch_att;
656 struct mailimap_fetch_type * fetch_type;
657 clist * fetch_result;
658 struct mailimap_msg_att * msg_att;
659 struct mailimap_body * imap_body;
660 struct mailmime * body;
661 int res;
662 struct mailimf_fields * fields;
663 struct mailmime * new_body;
664 struct mailmime_content * content_message;
665 struct mailimap_envelope * envelope;
666 uint32_t uid;
667 char * references;
668 size_t ref_size;
669 clistiter * cur;
670
671 if (msg_info->msg_mime != NULL) {
672 * result = msg_info->msg_mime;
673
674 return MAIL_NO_ERROR;
675 }
676
677 set = mailimap_set_new_single(msg_info->msg_index);
678 if (set == NULL) {
679 res = MAIL_ERROR_MEMORY;
680 goto err;
681 }
682
683 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
684 if (fetch_type == NULL) {
685 res = MAIL_ERROR_MEMORY;
686 goto free_set;
687 }
688
689 fetch_att = mailimap_fetch_att_new_uid();
690 if (fetch_att == NULL) {
691 res = MAIL_ERROR_MEMORY;
692 goto free_fetch_type;
693 }
694
695 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
696 if (r != MAILIMAP_NO_ERROR) {
697 mailimap_fetch_att_free(fetch_att);
698 res = MAIL_ERROR_MEMORY;
699 goto free_fetch_type;
700 }
701
702 fetch_att = mailimap_fetch_att_new_bodystructure();
703 if (fetch_att == NULL) {
704 res = MAIL_ERROR_MEMORY;
705 goto free_fetch_type;
706 }
707
708 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
709 if (r != MAILIMAP_NO_ERROR) {
710 mailimap_fetch_att_free(fetch_att);
711 res = MAIL_ERROR_MEMORY;
712 goto free_fetch_type;
713 }
714
715 r = imap_add_envelope_fetch_att(fetch_type);
716 if (r != MAIL_NO_ERROR) {
717 res = r;
718 goto free_fetch_type;
719 }
720
721
722 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
723 fetch_type, &fetch_result);
724
725 mailimap_fetch_type_free(fetch_type);
726 mailimap_set_free(set);
727
728 switch (r) {
729 case MAILIMAP_NO_ERROR:
730 break;
731 default:
732 return imap_error_to_mail_error(r);
733 }
734
735 cur = clist_begin(fetch_result);
736 if (cur == NULL) {
737 mailimap_fetch_list_free(fetch_result);
738 return MAIL_ERROR_FETCH;
739 }
740
741 msg_att = clist_content(cur);
742
743 uid = 0;
744 references = NULL;
745 ref_size = 0;
746 imap_body = NULL;
747 envelope = NULL;
748
749 r = imap_get_msg_att_info(msg_att,
750 &uid, &envelope, &references, &ref_size, NULL, &imap_body);
751 if (r != MAIL_NO_ERROR) {
752 mailimap_fetch_list_free(fetch_result);
753 res = r;
754 goto err;
755 }
756
757 if (uid != msg_info->msg_index) {
758 mailimap_fetch_list_free(fetch_result);
759 res = MAIL_ERROR_MSG_NOT_FOUND;
760 goto err;
761 }
762
763 if (imap_body == NULL) {
764 mailimap_fetch_list_free(fetch_result);
765 res = MAIL_ERROR_FETCH;
766 goto err;
767 }
768
769 r = imap_body_to_body(imap_body, &body);
770 if (r != MAIL_NO_ERROR) {
771 mailimap_fetch_list_free(fetch_result);
772 res = r;
773 goto err;
774 }
775
776 fields = NULL;
777 if (envelope != NULL) {
778 r = imap_env_to_fields(envelope, references, ref_size, &fields);
779 if (r != MAIL_NO_ERROR) {
780 mailmime_free(body);
781 mailimap_fetch_list_free(fetch_result);
782 res = r;
783 goto err;
784 }
785 }
786
787 content_message = mailmime_get_content_message();
788 if (content_message == NULL) {
789 if (fields != NULL)
790 mailimf_fields_free(fields);
791 mailmime_free(body);
792 mailimap_fetch_list_free(fetch_result);
793 res = MAIL_ERROR_MEMORY;
794 goto err;
795 }
796
797 new_body = mailmime_new(MAILMIME_MESSAGE, NULL,
798 0, NULL, content_message,
799 NULL, NULL, NULL, NULL, fields, body);
800
801 if (new_body == NULL) {
802 mailmime_content_free(content_message);
803 if (fields != NULL)
804 mailimf_fields_free(fields);
805 mailmime_free(body);
806 mailimap_fetch_list_free(fetch_result);
807 res = MAIL_ERROR_MEMORY;
808 goto err;
809 }
810 msg_info->msg_mime = new_body;
811
812 mailimap_fetch_list_free(fetch_result);
813
814 * result = new_body;
815
816 return MAIL_NO_ERROR;
817
818 free_fetch_type:
819 mailimap_fetch_type_free(fetch_type);
820 free_set:
821 mailimap_set_free(set);
822 err:
823 return res;
824}
825
826static int
827fetch_imap(mailmessage * msg,
828 struct mailimap_fetch_type * fetch_type,
829 char ** result, size_t * result_len)
830{
831 int r;
832 struct mailimap_msg_att * msg_att;
833 struct mailimap_msg_att_item * msg_att_item;
834 clist * fetch_result;
835 struct mailimap_set * set;
836 char * text;
837 size_t text_length;
838 clistiter * cur;
839
840 set = mailimap_set_new_single(msg->msg_index);
841 if (set == NULL)
842 return MAIL_ERROR_MEMORY;
843
844 r = mailimap_uid_fetch(get_imap_session(msg), set,
845 fetch_type, &fetch_result);
846
847 mailimap_set_free(set);
848
849 switch (r) {
850 case MAILIMAP_NO_ERROR:
851 break;
852 default:
853 return imap_error_to_mail_error(r);
854 }
855
856 if (clist_begin(fetch_result) == NULL) {
857 mailimap_fetch_list_free(fetch_result);
858 return MAIL_ERROR_FETCH;
859 }
860
861 msg_att = clist_begin(fetch_result)->data;
862
863 text = NULL;
864 text_length = 0;
865
866 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
867 cur = clist_next(cur)) {
868 msg_att_item = clist_content(cur);
869
870 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
871
872 if (msg_att_item->att_data.att_static->att_type ==
873 MAILIMAP_MSG_ATT_BODY_SECTION) {
874 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
875 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
876 text_length =
877 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
878 }
879 }
880 }
881
882 mailimap_fetch_list_free(fetch_result);
883
884 if (text == NULL)
885 return MAIL_ERROR_FETCH;
886
887 * result = text;
888 * result_len = text_length;
889
890 return MAIL_NO_ERROR;
891}
892
893
894static int imap_fetch_section(mailmessage * msg_info,
895 struct mailmime * mime,
896 char ** result, size_t * result_len)
897{
898 struct mailimap_section * section;
899 struct mailimap_fetch_att * fetch_att;
900 int r;
901 struct mailimap_fetch_type * fetch_type;
902 char * text;
903 size_t text_length;
904 struct mailmime_section * part;
905
906 if (mime->mm_parent == NULL)
907 return imap_fetch(msg_info, result, result_len);
908
909 r = mailmime_get_section_id(mime, &part);
910 if (r != MAILIMF_NO_ERROR)
911 return maildriver_imf_error_to_mail_error(r);
912
913 r = section_to_imap_section(part, IMAP_SECTION_MESSAGE, &section);
914 mailmime_section_free(part);
915 if (r != MAIL_NO_ERROR)
916 return r;
917
918 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
919 if (fetch_att == NULL) {
920 mailimap_section_free(section);
921 return MAIL_ERROR_MEMORY;
922 }
923
924 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
925 if (fetch_type == NULL) {
926 mailimap_fetch_att_free(fetch_att);
927 return MAIL_ERROR_MEMORY;
928 }
929
930 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
931
932 mailimap_fetch_type_free(fetch_type);
933
934 if (r != MAIL_NO_ERROR)
935 return r;
936
937 * result = text;
938 * result_len = text_length;
939
940 return MAIL_NO_ERROR;
941}
942
943static int imap_fetch_section_header(mailmessage * msg_info,
944 struct mailmime * mime,
945 char ** result,
946 size_t * result_len)
947{
948 struct mailimap_section * section;
949 struct mailimap_fetch_att * fetch_att;
950 int r;
951 struct mailimap_fetch_type * fetch_type;
952 char * text;
953 size_t text_length;
954 struct mailmime_section * part;
955
956 if (mime->mm_parent == NULL)
957 return imap_fetch_header(msg_info, result, result_len);
958
959 r = mailmime_get_section_id(mime, &part);
960 if (r != MAILIMF_NO_ERROR)
961 return maildriver_imf_error_to_mail_error(r);
962
963 r = section_to_imap_section(part, IMAP_SECTION_HEADER, &section);
964 mailmime_section_free(part);
965 if (r != MAIL_NO_ERROR)
966 return r;
967
968 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
969 if (fetch_att == NULL) {
970 mailimap_section_free(section);
971 return MAIL_ERROR_MEMORY;
972 }
973
974 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
975 if (fetch_type == NULL) {
976 mailimap_fetch_att_free(fetch_att);
977 return MAIL_ERROR_MEMORY;
978 }
979
980 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
981 mailimap_fetch_type_free(fetch_type);
982
983 if (r != MAIL_NO_ERROR)
984 return r;
985
986 * result = text;
987 * result_len = text_length;
988
989 return MAIL_NO_ERROR;
990}
991
992static int imap_fetch_section_mime(mailmessage * msg_info,
993 struct mailmime * mime,
994 char ** result,
995 size_t * result_len)
996{
997 struct mailimap_section * section;
998 struct mailimap_fetch_att * fetch_att;
999 int r;
1000 struct mailimap_fetch_type * fetch_type;
1001 char * text;
1002 size_t text_length;
1003 struct mailmime_section * part;
1004
1005 if (mime->mm_parent == NULL)
1006 return MAIL_ERROR_INVAL;
1007
1008 if (mime->mm_parent->mm_parent == NULL)
1009 return imap_fetch_header(msg_info, result, result_len);
1010
1011 r = mailmime_get_section_id(mime, &part);
1012 if (r != MAILIMF_NO_ERROR)
1013 return maildriver_imf_error_to_mail_error(r);
1014
1015 r = section_to_imap_section(part, IMAP_SECTION_MIME, &section);
1016 mailmime_section_free(part);
1017 if (r != MAIL_NO_ERROR)
1018 return MAIL_ERROR_MEMORY;
1019
1020 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1021 if (fetch_att == NULL) {
1022 mailimap_section_free(section);
1023 return MAIL_ERROR_MEMORY;
1024 }
1025
1026 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1027 if (fetch_type == NULL) {
1028 mailimap_fetch_att_free(fetch_att);
1029 return MAIL_ERROR_MEMORY;
1030 }
1031
1032 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
1033
1034 mailimap_fetch_type_free(fetch_type);
1035
1036 if (r != MAIL_NO_ERROR)
1037 return r;
1038
1039 * result = text;
1040 * result_len = text_length;
1041
1042 return MAIL_NO_ERROR;
1043}
1044
1045static int imap_fetch_section_body(mailmessage * msg_info,
1046 struct mailmime * mime,
1047 char ** result,
1048 size_t * result_len)
1049{
1050 struct mailimap_section * section;
1051 struct mailimap_fetch_att * fetch_att;
1052 int r;
1053 struct mailimap_fetch_type * fetch_type;
1054 char * text;
1055 size_t text_length;
1056 struct mailmime_section * part;
1057
1058 if (mime->mm_parent == NULL)
1059 return imap_fetch_body(msg_info, result, result_len);
1060
1061 if (mime->mm_parent->mm_parent == NULL)
1062 return imap_fetch_body(msg_info, result, result_len);
1063
1064 r = mailmime_get_section_id(mime, &part);
1065 if (r != MAILIMF_NO_ERROR)
1066 return maildriver_imf_error_to_mail_error(r);
1067
1068 r = section_to_imap_section(part, IMAP_SECTION_BODY, &section);
1069 mailmime_section_free(part);
1070 if (r != MAIL_NO_ERROR)
1071 return MAIL_ERROR_MEMORY;
1072
1073 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1074 if (fetch_att == NULL) {
1075 mailimap_section_free(section);
1076 return MAIL_ERROR_MEMORY;
1077 }
1078
1079 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1080 if (fetch_type == NULL) {
1081 mailimap_fetch_att_free(fetch_att);
1082 return MAIL_ERROR_MEMORY;
1083 }
1084
1085 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
1086
1087 mailimap_fetch_type_free(fetch_type);
1088
1089 if (r != MAIL_NO_ERROR)
1090 return r;
1091
1092 * result = text;
1093 * result_len = text_length;
1094
1095 return MAIL_NO_ERROR;
1096}
1097
1098static int imap_get_flags(mailmessage * msg_info,
1099 struct mail_flags ** result)
1100{
1101 int r;
1102 struct mail_flags * flags;
1103
1104 if (msg_info->msg_flags != NULL) {
1105 * result = msg_info->msg_flags;
1106 return MAIL_NO_ERROR;
1107 }
1108
1109 flags = mail_flags_store_get(get_session_data(msg_info)->imap_flags_store,
1110 msg_info->msg_index);
1111
1112 if (flags == NULL) {
1113 r = imap_fetch_flags(get_imap_session(msg_info),
1114 msg_info->msg_index, &flags);
1115 if (r != MAIL_NO_ERROR)
1116 return r;
1117 }
1118
1119 msg_info->msg_flags = flags;
1120
1121 * result = flags;
1122
1123 return MAIL_NO_ERROR;
1124}
1125
1126static int imap_fetch_envelope(mailmessage * msg_info,
1127 struct mailimf_fields ** result)
1128{
1129 int r;
1130 struct mailimap_set * set;
1131 struct mailimap_fetch_att * fetch_att;
1132 struct mailimap_fetch_type * fetch_type;
1133 clist * fetch_result;
1134 struct mailimap_msg_att * msg_att;
1135 int res;
1136 struct mailimf_fields * fields;
1137 struct mailimap_envelope * envelope;
1138 uint32_t uid;
1139 char * references;
1140 size_t ref_size;
1141
1142 set = mailimap_set_new_single(msg_info->msg_index);
1143 if (set == NULL) {
1144 res = MAIL_ERROR_MEMORY;
1145 goto err;
1146 }
1147
1148 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
1149 if (fetch_type == NULL) {
1150 res = MAIL_ERROR_MEMORY;
1151 goto free_set;
1152 }
1153
1154 fetch_att = mailimap_fetch_att_new_uid();
1155 if (fetch_att == NULL) {
1156 res = MAIL_ERROR_MEMORY;
1157 goto free_fetch_type;
1158 }
1159
1160 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1161 if (r != MAILIMAP_NO_ERROR) {
1162 mailimap_fetch_att_free(fetch_att);
1163 res = MAIL_ERROR_MEMORY;
1164 goto free_fetch_type;
1165 }
1166
1167 r = imap_add_envelope_fetch_att(fetch_type);
1168 if (r != MAIL_NO_ERROR) {
1169 res = r;
1170 goto free_fetch_type;
1171 }
1172
1173 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
1174 fetch_type, &fetch_result);
1175
1176 mailimap_fetch_type_free(fetch_type);
1177 mailimap_set_free(set);
1178
1179 switch (r) {
1180 case MAILIMAP_NO_ERROR:
1181 break;
1182 default:
1183 return imap_error_to_mail_error(r);
1184 }
1185
1186 if (clist_begin(fetch_result) == NULL) {
1187 mailimap_fetch_list_free(fetch_result);
1188 return MAIL_ERROR_FETCH;
1189 }
1190
1191 msg_att = clist_begin(fetch_result)->data;
1192
1193 uid = 0;
1194 references = NULL;
1195 ref_size = 0;
1196 envelope = NULL;
1197
1198 r = imap_get_msg_att_info(msg_att,
1199 &uid,
1200 &envelope,
1201 &references,
1202 &ref_size,
1203 NULL,
1204 NULL);
1205 if (r != MAIL_NO_ERROR) {
1206 mailimap_fetch_list_free(fetch_result);
1207 res = r;
1208 goto err;
1209 }
1210
1211 if (uid != msg_info->msg_index) {
1212 mailimap_fetch_list_free(fetch_result);
1213 res = MAIL_ERROR_MSG_NOT_FOUND;
1214 goto err;
1215 }
1216
1217 fields = NULL;
1218 if (envelope != NULL) {
1219 r = imap_env_to_fields(envelope, references, ref_size, &fields);
1220 if (r != MAIL_NO_ERROR) {
1221 mailimap_fetch_list_free(fetch_result);
1222 res = r;
1223 goto err;
1224 }
1225 }
1226
1227 mailimap_fetch_list_free(fetch_result);
1228
1229 * result = fields;
1230
1231 return MAIL_NO_ERROR;
1232
1233 free_fetch_type:
1234 mailimap_fetch_type_free(fetch_type);
1235 free_set:
1236 mailimap_set_free(set);
1237 err:
1238 return res;
1239}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_MESSAGE_H
37
38#define IMAPDRIVER_MESSAGE_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * imap_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_tools.h"
37
38#include "maildriver.h"
39
40#include <stdlib.h>
41#include <string.h>
42
43#include "mail.h"
44#include "imapdriver_types.h"
45#include "maildriver_tools.h"
46#include "generic_cache.h"
47#include "mailmessage.h"
48#include "mail_cache_db.h"
49
50
51
52static inline struct imap_session_state_data *
53session_get_data(mailsession * session)
54{
55 return session->sess_data;
56}
57
58static inline struct imap_cached_session_state_data *
59cached_session_get_data(mailsession * session)
60{
61 return session->sess_data;
62}
63
64static inline mailsession *
65cached_session_get_ancestor(mailsession * session)
66{
67 return cached_session_get_data(session)->imap_ancestor;
68}
69
70static inline struct imap_session_state_data *
71cached_session_get_ancestor_data(mailsession * session)
72{
73 return session_get_data(cached_session_get_ancestor(session));
74}
75
76static inline mailimap *
77cached_session_get_imap_session(mailsession * session)
78{
79 return cached_session_get_ancestor_data(session)->imap_session;
80}
81
82static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn,
83 struct mail_flags ** result);
84
85
86int imap_error_to_mail_error(int error)
87{
88 switch (error) {
89 case MAILIMAP_NO_ERROR:
90 return MAIL_NO_ERROR;
91
92 case MAILIMAP_NO_ERROR_AUTHENTICATED:
93 return MAIL_NO_ERROR_AUTHENTICATED;
94
95 case MAILIMAP_NO_ERROR_NON_AUTHENTICATED:
96 return MAIL_NO_ERROR_NON_AUTHENTICATED;
97
98 case MAILIMAP_ERROR_BAD_STATE:
99 return MAIL_ERROR_BAD_STATE;
100
101 case MAILIMAP_ERROR_STREAM:
102 return MAIL_ERROR_STREAM;
103
104 case MAILIMAP_ERROR_PARSE:
105 return MAIL_ERROR_PARSE;
106
107 case MAILIMAP_ERROR_CONNECTION_REFUSED:
108 return MAIL_ERROR_CONNECT;
109
110 case MAILIMAP_ERROR_MEMORY:
111 return MAIL_ERROR_MEMORY;
112
113 case MAILIMAP_ERROR_FATAL:
114 return MAIL_ERROR_FATAL;
115
116 case MAILIMAP_ERROR_PROTOCOL:
117 return MAIL_ERROR_PROTOCOL;
118
119 case MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION:
120 return MAIL_ERROR_CONNECT;
121
122 case MAILIMAP_ERROR_APPEND:
123 return MAIL_ERROR_APPEND;
124
125 case MAILIMAP_ERROR_NOOP:
126 return MAIL_ERROR_NOOP;
127
128 case MAILIMAP_ERROR_LOGOUT:
129 return MAIL_ERROR_LOGOUT;
130
131 case MAILIMAP_ERROR_CAPABILITY:
132 return MAIL_ERROR_CAPABILITY;
133
134 case MAILIMAP_ERROR_CHECK:
135 return MAIL_ERROR_CHECK;
136
137 case MAILIMAP_ERROR_CLOSE:
138 return MAIL_ERROR_CLOSE;
139
140 case MAILIMAP_ERROR_EXPUNGE:
141 return MAIL_ERROR_EXPUNGE;
142
143 case MAILIMAP_ERROR_COPY:
144 case MAILIMAP_ERROR_UID_COPY:
145 return MAIL_ERROR_COPY;
146
147 case MAILIMAP_ERROR_CREATE:
148 return MAIL_ERROR_CREATE;
149
150 case MAILIMAP_ERROR_DELETE:
151 return MAIL_ERROR_DELETE;
152
153 case MAILIMAP_ERROR_EXAMINE:
154 return MAIL_ERROR_EXAMINE;
155
156 case MAILIMAP_ERROR_FETCH:
157 case MAILIMAP_ERROR_UID_FETCH:
158 return MAIL_ERROR_FETCH;
159
160 case MAILIMAP_ERROR_LIST:
161 return MAIL_ERROR_LIST;
162
163 case MAILIMAP_ERROR_LOGIN:
164 return MAIL_ERROR_LOGIN;
165
166 case MAILIMAP_ERROR_LSUB:
167 return MAIL_ERROR_LSUB;
168
169 case MAILIMAP_ERROR_RENAME:
170 return MAIL_ERROR_RENAME;
171
172 case MAILIMAP_ERROR_SEARCH:
173 case MAILIMAP_ERROR_UID_SEARCH:
174 return MAIL_ERROR_SEARCH;
175
176 case MAILIMAP_ERROR_SELECT:
177 return MAIL_ERROR_SELECT;
178
179 case MAILIMAP_ERROR_STATUS:
180 return MAIL_ERROR_STATUS;
181
182 case MAILIMAP_ERROR_STORE:
183 case MAILIMAP_ERROR_UID_STORE:
184 return MAIL_ERROR_STORE;
185
186 case MAILIMAP_ERROR_SUBSCRIBE:
187 return MAIL_ERROR_SUBSCRIBE;
188
189 case MAILIMAP_ERROR_UNSUBSCRIBE:
190 return MAIL_ERROR_UNSUBSCRIBE;
191
192 case MAILIMAP_ERROR_STARTTLS:
193 return MAIL_ERROR_STARTTLS;
194
195 case MAILIMAP_ERROR_INVAL:
196 return MAIL_ERROR_INVAL;
197
198 default:
199 return MAIL_ERROR_INVAL;
200 }
201}
202
203
204
205
206
207static int
208imap_body_parameter_to_content(struct mailimap_body_fld_param *
209 body_parameter,
210 char * subtype,
211 struct mailmime_type * mime_type,
212 struct mailmime_content ** result);
213
214static int
215imap_body_type_text_to_content_type(char * subtype,
216 struct mailimap_body_fld_param *
217 body_parameter,
218 struct mailmime_content ** result);
219
220
221int imap_list_to_list(clist * imap_list, struct mail_list ** result)
222{
223 clistiter * cur;
224 clist * list;
225 struct mail_list * resp;
226 int r;
227 int res;
228
229 list = clist_new();
230 if (list == NULL) {
231 res = MAIL_ERROR_MEMORY;
232 goto err;
233 }
234
235 for(cur = clist_begin(imap_list) ; cur != NULL ; cur = clist_next(cur)) {
236 struct mailimap_mailbox_list * mb_list;
237 char * new_mb;
238
239 mb_list = clist_content(cur);
240
241 new_mb = strdup(mb_list->mb_name);
242 if (new_mb == NULL) {
243 res = MAIL_ERROR_MEMORY;
244 goto free_list;
245 }
246
247 r = clist_append(list, new_mb);
248 if (r != 0) {
249 free(new_mb);
250 res = MAIL_ERROR_MEMORY;
251 goto free_list;
252 }
253 }
254
255 resp = mail_list_new(list);
256 if (resp == NULL) {
257 res = MAIL_ERROR_MEMORY;
258 goto free_list;
259 }
260
261 * result = resp;
262
263 return MAIL_NO_ERROR;
264
265 free_list:
266 clist_foreach(list, (clist_func) free, NULL);
267 clist_free(list);
268 err:
269 return res;
270}
271
272int
273section_to_imap_section(struct mailmime_section * section, int type,
274 struct mailimap_section ** result)
275{
276 struct mailimap_section_part * section_part;
277 struct mailimap_section * imap_section;
278 clist * list;
279 clistiter * cur;
280 int r;
281 int res;
282
283 list = clist_new();
284 if (list == NULL) {
285 res = MAIL_ERROR_MEMORY;
286 goto err;
287 }
288
289 for(cur = clist_begin(section->sec_list) ; cur != NULL ;
290 cur = clist_next(cur)) {
291 uint32_t value;
292 uint32_t * id;
293
294 value = * (uint32_t *) clist_content(cur);
295 id = malloc(sizeof(* id));
296 if (id == NULL) {
297 res = MAIL_ERROR_MEMORY;
298 goto free_list;
299 }
300 * id = value;
301 r = clist_append(list, id);
302 if (r != 0) {
303 res = MAIL_ERROR_MEMORY;
304 free(id);
305 goto free_list;
306 }
307 }
308
309 section_part = mailimap_section_part_new(list);
310 if (section_part == NULL) {
311 res = MAIL_ERROR_MEMORY;
312 goto free_list;
313 }
314
315 imap_section = NULL;
316
317 switch (type) {
318 case IMAP_SECTION_MESSAGE:
319 imap_section = mailimap_section_new_part(section_part);
320 break;
321 case IMAP_SECTION_HEADER:
322 imap_section = mailimap_section_new_part_header(section_part);
323 break;
324 case IMAP_SECTION_MIME:
325 imap_section = mailimap_section_new_part_mime(section_part);
326 break;
327 case IMAP_SECTION_BODY:
328 imap_section = mailimap_section_new_part_text(section_part);
329 break;
330 }
331
332 if (imap_section == NULL) {
333 res = MAIL_ERROR_MEMORY;
334 goto free_part;
335 }
336
337 * result = imap_section;
338
339 return MAIL_NO_ERROR;
340
341 free_part:
342 mailimap_section_part_free(section_part);
343 free_list:
344 if (list != NULL) {
345 clist_foreach(list, (clist_func) free, NULL);
346 clist_free(list);
347 }
348 err:
349 return res;
350}
351
352
353
354static int
355imap_body_media_basic_to_content_type(struct mailimap_media_basic *
356 media_basic,
357 struct mailimap_body_fld_param *
358 body_parameter,
359 struct mailmime_content ** result)
360{
361 struct mailmime_content * content;
362 struct mailmime_type * mime_type;
363 struct mailmime_discrete_type * discrete_type;
364 struct mailmime_composite_type * composite_type;
365 char * discrete_type_extension;
366 int discrete_type_type;
367 int composite_type_type;
368 int mime_type_type;
369 char * subtype;
370 int r;
371 int res;
372
373 discrete_type = NULL;
374 composite_type = NULL;
375 discrete_type_extension = NULL;
376 subtype = NULL;
377 discrete_type_type = 0;
378 composite_type_type = 0;
379 mime_type_type = 0;
380
381 switch (media_basic->med_type) {
382 case MAILIMAP_MEDIA_BASIC_APPLICATION:
383 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
384 discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION;
385 break;
386
387 case MAILIMAP_MEDIA_BASIC_AUDIO:
388 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
389 discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION;
390 break;
391
392 case MAILIMAP_MEDIA_BASIC_IMAGE:
393 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
394 discrete_type_type = MAILMIME_DISCRETE_TYPE_IMAGE;
395 break;
396
397 case MAILIMAP_MEDIA_BASIC_MESSAGE:
398 mime_type_type = MAILMIME_TYPE_COMPOSITE_TYPE;
399 composite_type_type = MAILMIME_COMPOSITE_TYPE_MESSAGE;
400 break;
401
402 case MAILIMAP_MEDIA_BASIC_VIDEO:
403 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
404 discrete_type_type = MAILMIME_DISCRETE_TYPE_VIDEO;
405 break;
406
407 case MAILIMAP_MEDIA_BASIC_OTHER:
408 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
409 discrete_type_type = MAILMIME_DISCRETE_TYPE_EXTENSION;
410 discrete_type_extension = media_basic->med_basic_type;
411 if (discrete_type_extension == NULL) {
412 res = MAIL_ERROR_INVAL;
413 goto err;
414 }
415
416 break;
417
418 default:
419 res = MAIL_ERROR_INVAL;
420 goto err;
421 }
422
423 switch (mime_type_type) {
424 case MAILMIME_TYPE_DISCRETE_TYPE:
425 if (discrete_type_extension != NULL) {
426 discrete_type_extension = strdup(discrete_type_extension);
427 if (discrete_type_extension == NULL) {
428 res = MAIL_ERROR_MEMORY;
429 goto err;
430 }
431 }
432
433 discrete_type = mailmime_discrete_type_new(discrete_type_type,
434 discrete_type_extension);
435 if (discrete_type == NULL) {
436 if (discrete_type_extension != NULL)
437 free(discrete_type_extension);
438 res = MAIL_ERROR_MEMORY;
439 goto err;
440 }
441
442 break;
443
444 case MAILMIME_TYPE_COMPOSITE_TYPE:
445 composite_type = mailmime_composite_type_new(composite_type_type,
446 NULL);
447 if (composite_type == NULL) {
448 res = MAIL_ERROR_MEMORY;
449 goto err;
450 }
451
452 break;
453
454 default:
455 res = MAIL_ERROR_INVAL;
456 goto err;
457 }
458
459 mime_type = mailmime_type_new(mime_type_type, discrete_type, composite_type);
460 if (mime_type == NULL) {
461 res = MAIL_ERROR_MEMORY;
462 goto free;
463 }
464
465 r = imap_body_parameter_to_content(body_parameter, media_basic->med_subtype,
466 mime_type, &content);
467 if (r != MAIL_NO_ERROR) {
468 res = r;
469 goto free_type;
470 }
471
472 * result = content;
473
474 return MAIL_NO_ERROR;
475
476 free_type:
477 mailmime_type_free(mime_type);
478 free:
479 if (discrete_type != NULL)
480 mailmime_discrete_type_free(discrete_type);
481 if (composite_type != NULL)
482 mailmime_composite_type_free(composite_type);
483 err:
484 return res;
485}
486
487static int
488imap_disposition_to_mime_disposition(struct mailimap_body_fld_dsp * imap_dsp,
489 struct mailmime_disposition ** result)
490{
491 size_t cur_token;
492 int r;
493 struct mailmime_disposition_type * dsp_type;
494 struct mailmime_disposition * dsp;
495 clist * parameters;
496 int res;
497
498 cur_token = 0;
499 r = mailmime_disposition_type_parse(imap_dsp->dsp_type,
500 strlen(imap_dsp->dsp_type), &cur_token, &dsp_type);
501 if (r != MAILIMF_NO_ERROR) {
502 res = MAILIMF_ERROR_PARSE;
503 goto err;
504 }
505
506 parameters = clist_new();
507 if (parameters == NULL) {
508 res = MAIL_ERROR_MEMORY;
509 goto err;
510 }
511
512 if (imap_dsp->dsp_attributes != NULL) {
513 clistiter * cur;
514
515 for(cur = clist_begin(imap_dsp->dsp_attributes->pa_list) ; cur != NULL ;
516 cur = clist_next(cur)) {
517 struct mailimap_single_body_fld_param * imap_param;
518 struct mailmime_disposition_parm * dsp_param;
519 struct mailmime_parameter * param;
520 char * filename;
521 char * creation_date;
522 char * modification_date;
523 char * read_date;
524 size_t size;
525 int type;
526
527 imap_param = clist_content(cur);
528
529 filename = NULL;
530 creation_date = NULL;
531 modification_date = NULL;
532 read_date = NULL;
533 size = 0;
534 param = NULL;
535
536 type = mailmime_disposition_guess_type(imap_param->pa_name,
537 strlen(imap_param->pa_name), 0);
538
539 switch (type) {
540 case MAILMIME_DISPOSITION_PARM_FILENAME:
541 if (strcasecmp(imap_param->pa_name, "filename") != 0) {
542 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
543 break;
544 }
545 filename = strdup(imap_param->pa_value);
546 if (filename == NULL) {
547 res = MAIL_ERROR_MEMORY;
548 goto free_dsp_type;
549 }
550 break;
551
552 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
553 if (strcasecmp(imap_param->pa_name, "creation-date") != 0) {
554 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
555 break;
556 }
557 creation_date = strdup(imap_param->pa_value);
558 if (creation_date == NULL) {
559 res = MAIL_ERROR_MEMORY;
560 goto free_dsp_type;
561 }
562 break;
563
564 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
565 if (strcasecmp(imap_param->pa_name, "modification-date") != 0) {
566 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
567 break;
568 }
569 modification_date = strdup(imap_param->pa_value);
570 if (modification_date == NULL) {
571 res = MAIL_ERROR_MEMORY;
572 goto free_dsp_type;
573 }
574 break;
575
576 case MAILMIME_DISPOSITION_PARM_READ_DATE:
577 if (strcasecmp(imap_param->pa_name, "read-date") != 0) {
578 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
579 break;
580 }
581 read_date = strdup(imap_param->pa_value);
582 if (read_date == NULL) {
583 res = MAIL_ERROR_MEMORY;
584 goto free_dsp_type;
585 }
586 break;
587
588 case MAILMIME_DISPOSITION_PARM_SIZE:
589 if (strcasecmp(imap_param->pa_name, "size") != 0) {
590 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
591 break;
592 }
593 size = strtoul(imap_param->pa_value, NULL, 10);
594 break;
595 }
596
597 if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) {
598 char * name;
599 char * value;
600
601 name = strdup(imap_param->pa_name);
602 if (name == NULL) {
603 res = MAIL_ERROR_MEMORY;
604 goto free_dsp_type;
605 }
606
607 value = strdup(imap_param->pa_value);
608 if (value == NULL) {
609 res = MAIL_ERROR_MEMORY;
610 free(name);
611 goto free_dsp_type;
612 }
613
614 param = mailmime_parameter_new(name, value);
615 if (param == NULL) {
616 free(value);
617 free(name);
618 res = MAIL_ERROR_MEMORY;
619 goto free_dsp_type;
620 }
621
622 }
623
624 dsp_param = mailmime_disposition_parm_new(type, filename,
625 creation_date,
626 modification_date,
627 read_date,
628 size, param);
629 if (dsp_param == NULL) {
630 if (filename != NULL)
631 free(filename);
632 if (creation_date != NULL)
633 free(creation_date);
634 if (modification_date != NULL)
635 free(modification_date);
636 if (read_date != NULL)
637 free(read_date);
638 if (param != NULL)
639 mailmime_parameter_free(param);
640 res = MAIL_ERROR_MEMORY;
641 goto free_list;
642 }
643
644 r = clist_append(parameters, dsp_param);
645 if (r != 0) {
646 mailmime_disposition_parm_free(dsp_param);
647 res = MAIL_ERROR_MEMORY;
648 goto free_list;
649 }
650 }
651 }
652
653 dsp = mailmime_disposition_new(dsp_type, parameters);
654 if (dsp == NULL) {
655 res = MAIL_ERROR_MEMORY;
656 goto free_list;
657 }
658
659 * result = dsp;
660
661 return MAIL_NO_ERROR;
662
663 free_list:
664 clist_foreach(parameters,
665 (clist_func) mailmime_disposition_parm_free, NULL);
666 clist_free(parameters);
667 free_dsp_type:
668 mailmime_disposition_type_free(dsp_type);
669 err:
670 return res;
671}
672
673static int
674imap_language_to_mime_language(struct mailimap_body_fld_lang * imap_lang,
675 struct mailmime_language ** result)
676{
677 clist * list;
678 clistiter * cur;
679 int res;
680 char * single;
681 int r;
682 struct mailmime_language * lang;
683
684 list = clist_new();
685 if (list == NULL) {
686 res = MAIL_ERROR_MEMORY;
687 goto err;
688 }
689
690 switch (imap_lang->lg_type) {
691 case MAILIMAP_BODY_FLD_LANG_SINGLE:
692 if (imap_lang->lg_data.lg_single != NULL) {
693 single = strdup(imap_lang->lg_data.lg_single);
694 if (single == NULL) {
695 res = MAIL_ERROR_MEMORY;
696 goto free;
697 }
698 r = clist_append(list, single);
699 if (r < 0) {
700 free(single);
701 res = MAIL_ERROR_MEMORY;
702 goto free;
703 }
704 }
705
706 break;
707
708 case MAILIMAP_BODY_FLD_LANG_LIST:
709 for(cur = clist_begin(imap_lang->lg_data.lg_list) ;
710 cur != NULL ; cur = clist_next(cur)) {
711 single = strdup(clist_content(cur));
712 if (single == NULL) {
713 res = MAIL_ERROR_MEMORY;
714 goto free;
715 }
716 r = clist_append(list, single);
717 if (r < 0) {
718 free(single);
719 res = MAIL_ERROR_MEMORY;
720 goto free;
721 }
722 }
723 }
724
725 lang = mailmime_language_new(list);
726 if (lang == NULL) {
727 res = MAIL_ERROR_MEMORY;
728 goto free;
729 }
730
731 * result = lang;
732
733 return MAIL_NO_ERROR;
734
735 free:
736 clist_foreach(list, (clist_func) free, NULL);
737 clist_free(list);
738 err:
739 return res;
740}
741
742static int
743imap_body_fields_to_mime_fields(struct mailimap_body_fields * body_fields,
744 struct mailimap_body_fld_dsp * imap_dsp,
745 struct mailimap_body_fld_lang * imap_lang,
746 struct mailmime_fields ** result,
747 uint32_t * pbody_size)
748{
749 struct mailmime_field * mime_field;
750 struct mailmime_fields * mime_fields;
751 clist * list;
752 char * id;
753 struct mailmime_mechanism * encoding;
754 char * description;
755 struct mailmime_disposition * dsp;
756 struct mailmime_language * lang;
757 int type;
758 int r;
759 int res;
760
761 list = clist_new();
762 if (list == NULL) {
763 res = MAIL_ERROR_MEMORY;
764 goto err;
765 }
766
767 if (body_fields != NULL) {
768
769 if (pbody_size != NULL)
770 * pbody_size = body_fields->bd_size;
771
772 if (body_fields->bd_id != NULL) {
773 type = MAILMIME_FIELD_ID;
774 id = strdup(body_fields->bd_id);
775 if (id == NULL) {
776 res = MAIL_ERROR_MEMORY;
777 goto free_list;
778 }
779
780 mime_field = mailmime_field_new(type, NULL,
781 NULL, id, NULL, 0, NULL, NULL);
782 if (mime_field == NULL) {
783 free(id);
784 res = MAIL_ERROR_MEMORY;
785 goto free_list;
786 }
787
788 r = clist_append(list, mime_field);
789 if (r != 0) {
790 mailmime_field_free(mime_field);
791 res = MAIL_ERROR_MEMORY;
792 goto free_list;
793 }
794 }
795
796 if (body_fields->bd_description != NULL) {
797 type = MAILMIME_FIELD_DESCRIPTION;
798 description = strdup(body_fields->bd_description);
799 if (description == NULL) {
800 res = MAIL_ERROR_MEMORY;
801 goto free_list;
802 }
803
804 mime_field = mailmime_field_new(type, NULL,
805 NULL, NULL, description, 0, NULL, NULL);
806 if (mime_field == NULL) {
807 free(description);
808 res = MAIL_ERROR_MEMORY;
809 goto free_list;
810 }
811
812 r = clist_append(list, mime_field);
813 if (r != 0) {
814 mailmime_field_free(mime_field);
815 res = MAIL_ERROR_MEMORY;
816 goto free_list;
817 }
818 }
819
820 if (body_fields->bd_encoding != NULL) {
821 char * encoding_value;
822 int encoding_type;
823
824 type = MAILMIME_FIELD_TRANSFER_ENCODING;
825
826 encoding_value = NULL;
827 switch (body_fields->bd_encoding->enc_type) {
828 case MAILIMAP_BODY_FLD_ENC_7BIT:
829 encoding_type = MAILMIME_MECHANISM_7BIT;
830 break;
831 case MAILIMAP_BODY_FLD_ENC_8BIT:
832 encoding_type = MAILMIME_MECHANISM_8BIT;
833 break;
834 case MAILIMAP_BODY_FLD_ENC_BINARY:
835 encoding_type = MAILMIME_MECHANISM_BINARY;
836 break;
837 case MAILIMAP_BODY_FLD_ENC_BASE64:
838 encoding_type = MAILMIME_MECHANISM_BASE64;
839 break;
840 case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE:
841 encoding_type = MAILMIME_MECHANISM_QUOTED_PRINTABLE;
842 break;
843 case MAILIMAP_BODY_FLD_ENC_OTHER:
844 encoding_type = MAILMIME_MECHANISM_TOKEN;
845 encoding_value = strdup(body_fields->bd_encoding->enc_value);
846 if (encoding_value == NULL) {
847 res = MAIL_ERROR_MEMORY;
848 goto free_list;
849 }
850 break;
851 default:
852 res = MAIL_ERROR_INVAL;
853 goto free_list;
854 }
855
856 encoding = mailmime_mechanism_new(encoding_type, encoding_value);
857 if (encoding == NULL) {
858 if (encoding_value != NULL)
859 free(encoding_value);
860 res = MAIL_ERROR_MEMORY;
861 goto free_list;
862 }
863
864 mime_field = mailmime_field_new(type, NULL,
865 encoding, NULL, NULL, 0, NULL, NULL);
866 if (mime_field == NULL) {
867 mailmime_mechanism_free(encoding);
868 res = MAIL_ERROR_MEMORY;
869 goto free_list;
870 }
871
872 r = clist_append(list, mime_field);
873 if (r != 0) {
874 mailmime_field_free(mime_field);
875 res = MAIL_ERROR_MEMORY;
876 goto free_list;
877 }
878 }
879 }
880
881 if (imap_dsp != NULL) {
882 r = imap_disposition_to_mime_disposition(imap_dsp, &dsp);
883 if (r != MAIL_ERROR_PARSE) {
884 if (r != MAIL_NO_ERROR) {
885 res = MAIL_ERROR_MEMORY;
886 goto free_list;
887 }
888
889 type = MAILMIME_FIELD_DISPOSITION;
890
891 mime_field = mailmime_field_new(type, NULL,
892 NULL, NULL, NULL, 0, dsp, NULL);
893 if (mime_field == NULL) {
894 mailmime_disposition_free(dsp);
895 res = MAIL_ERROR_MEMORY;
896 goto free_list;
897 }
898
899 r = clist_append(list, mime_field);
900 if (r != 0) {
901 mailmime_field_free(mime_field);
902 res = MAIL_ERROR_MEMORY;
903 goto free_list;
904 }
905 }
906 }
907
908 if (imap_lang != NULL) {
909 r = imap_language_to_mime_language(imap_lang, &lang);
910 if (r != MAIL_NO_ERROR) {
911 res = MAIL_ERROR_MEMORY;
912 goto free_list;
913 }
914
915 type = MAILMIME_FIELD_LANGUAGE;
916
917 mime_field = mailmime_field_new(type, NULL,
918 NULL, NULL, NULL, 0, NULL, lang);
919 if (mime_field == NULL) {
920 mailmime_language_free(lang);
921 res = MAIL_ERROR_MEMORY;
922 goto free_list;
923 }
924
925 r = clist_append(list, mime_field);
926 if (r != 0) {
927 mailmime_field_free(mime_field);
928 res = MAIL_ERROR_MEMORY;
929 goto free_list;
930 }
931 }
932
933 mime_fields = mailmime_fields_new(list);
934 if (mime_fields == NULL) {
935 res = MAIL_ERROR_MEMORY;
936 goto free_list;
937 }
938
939 * result = mime_fields;
940
941 return MAIL_NO_ERROR;
942
943 free_list:
944 clist_foreach(list, (clist_func) mailmime_fields_free, NULL);
945 clist_free(list);
946 err:
947 return res;
948}
949
950static int
951imap_body_type_basic_to_body(struct mailimap_body_type_basic *
952 imap_type_basic,
953 struct mailimap_body_ext_1part *
954 body_ext_1part,
955 struct mailmime ** result)
956{
957 struct mailmime_content * content;
958 struct mailmime_fields * mime_fields;
959 struct mailmime * body;
960 int r;
961 int res;
962 uint32_t mime_size;
963
964 r = imap_body_media_basic_to_content_type(imap_type_basic->bd_media_basic,
965 imap_type_basic->bd_fields->bd_parameter, &content);
966 if (r != MAIL_NO_ERROR) {
967 res = r;
968 goto err;
969 }
970
971 if (body_ext_1part != NULL)
972 r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields,
973 body_ext_1part->bd_disposition,
974 body_ext_1part->bd_language,
975 &mime_fields, &mime_size);
976 else
977 r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields,
978 NULL, NULL,
979 &mime_fields, &mime_size);
980 if (r != MAIL_NO_ERROR) {
981 res = r;
982 goto free_content;
983 }
984
985 body = mailmime_new(MAILMIME_SINGLE, NULL,
986 mime_size, mime_fields, content,
987 NULL, NULL, NULL, NULL, NULL, NULL);
988
989 if (body == NULL) {
990 res = MAIL_ERROR_MEMORY;
991 goto free_fields;
992 }
993
994 * result = body;
995
996 return MAIL_NO_ERROR;
997
998 free_fields:
999 mailmime_fields_free(mime_fields);
1000 free_content:
1001 mailmime_content_free(content);
1002 err:
1003 return res;
1004}
1005
1006static int
1007imap_body_type_text_to_body(struct mailimap_body_type_text *
1008 imap_type_text,
1009 struct mailimap_body_ext_1part *
1010 body_ext_1part,
1011 struct mailmime ** result)
1012{
1013 struct mailmime_content * content;
1014 struct mailmime_fields * mime_fields;
1015 struct mailmime * body;
1016 int r;
1017 int res;
1018 uint32_t mime_size;
1019
1020 r = imap_body_type_text_to_content_type(imap_type_text->bd_media_text,
1021 imap_type_text->bd_fields->bd_parameter,
1022 &content);
1023 if (r != MAIL_NO_ERROR) {
1024 res = r;
1025 goto err;
1026 }
1027
1028 if (body_ext_1part == NULL) {
1029 r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields,
1030 NULL, NULL,
1031 &mime_fields, &mime_size);
1032 }
1033 else {
1034 r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields,
1035 body_ext_1part->bd_disposition,
1036 body_ext_1part->bd_language,
1037 &mime_fields, &mime_size);
1038 }
1039 if (r != MAIL_NO_ERROR) {
1040 res = r;
1041 goto free_content;
1042 }
1043
1044 body = mailmime_new(MAILMIME_SINGLE, NULL,
1045 mime_size, mime_fields, content,
1046 NULL, NULL, NULL, NULL, NULL, NULL);
1047
1048 if (body == NULL) {
1049 res = MAIL_ERROR_MEMORY;
1050 goto free_fields;
1051 }
1052
1053 * result = body;
1054
1055 return MAIL_NO_ERROR;
1056
1057 free_fields:
1058 mailmime_fields_free(mime_fields);
1059 free_content:
1060 mailmime_content_free(content);
1061 err:
1062 return res;
1063}
1064
1065static int
1066imap_body_parameter_to_content(struct mailimap_body_fld_param *
1067 body_parameter,
1068 char * subtype,
1069 struct mailmime_type * mime_type,
1070 struct mailmime_content ** result)
1071{
1072 clist * parameters;
1073 char * new_subtype;
1074 struct mailmime_content * content;
1075 int r;
1076 int res;
1077
1078 new_subtype = strdup(subtype);
1079 if (new_subtype == NULL) {
1080 res = MAIL_ERROR_MEMORY;
1081 goto err;
1082 }
1083
1084 parameters = clist_new();
1085 if (parameters == NULL) {
1086 res = MAIL_ERROR_MEMORY;
1087 goto free_subtype;
1088 }
1089
1090 if (body_parameter != NULL) {
1091 clistiter * cur;
1092
1093 for(cur = clist_begin(body_parameter->pa_list) ; cur != NULL ;
1094 cur = clist_next(cur)) {
1095 struct mailimap_single_body_fld_param * imap_param;
1096 struct mailmime_parameter * param;
1097 char * name;
1098 char * value;
1099
1100 imap_param = clist_content(cur);
1101 name = strdup(imap_param->pa_name);
1102 if (name == NULL) {
1103 res = MAIL_ERROR_MEMORY;
1104 goto free_parameters;
1105 }
1106
1107 value = strdup(imap_param->pa_value);
1108 if (value == NULL) {
1109 free(name);
1110 res = MAIL_ERROR_MEMORY;
1111 goto free_parameters;
1112 }
1113
1114 param = mailmime_parameter_new(name, value);
1115 if (param == NULL) {
1116 free(value);
1117 free(name);
1118 res = MAIL_ERROR_MEMORY;
1119 goto free_parameters;
1120 }
1121
1122 r = clist_append(parameters, param);
1123 if (r != 0) {
1124 mailmime_parameter_free(param);
1125 res = MAIL_ERROR_MEMORY;
1126 goto free_parameters;
1127 }
1128 }
1129 }
1130
1131 content = mailmime_content_new(mime_type, new_subtype, parameters);
1132 if (content == NULL) {
1133 res = MAIL_ERROR_MEMORY;
1134 goto free_parameters;
1135 }
1136
1137 * result = content;
1138
1139 return MAIL_NO_ERROR;
1140
1141 free_parameters:
1142 clist_foreach(parameters, (clist_func) mailmime_parameter_free, NULL);
1143 clist_free(parameters);
1144 free_subtype:
1145 free(new_subtype);
1146 err:
1147 return res;
1148}
1149
1150static int
1151imap_body_type_text_to_content_type(char * subtype,
1152 struct mailimap_body_fld_param *
1153 body_parameter,
1154 struct mailmime_content ** result)
1155{
1156 struct mailmime_content * content;
1157 struct mailmime_type * mime_type;
1158 struct mailmime_discrete_type * discrete_type;
1159 int r;
1160 int res;
1161
1162 discrete_type = NULL;
1163
1164 discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT,
1165 NULL);
1166 if (discrete_type == NULL) {
1167 res = MAIL_ERROR_MEMORY;
1168 goto err;
1169 }
1170
1171 mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE,
1172 discrete_type, NULL);
1173 if (mime_type == NULL) {
1174 mailmime_discrete_type_free(discrete_type);
1175 res = MAIL_ERROR_MEMORY;
1176 goto err;
1177 }
1178
1179 r = imap_body_parameter_to_content(body_parameter, subtype,
1180 mime_type, &content);
1181 if (r != MAIL_NO_ERROR) {
1182 res = r;
1183 goto free_type;
1184 }
1185
1186 * result = content;
1187
1188 return MAIL_NO_ERROR;
1189
1190 free_type:
1191 mailmime_type_free(mime_type);
1192 err:
1193 return res;
1194}
1195
1196
1197static int
1198imap_body_type_msg_to_body(struct mailimap_body_type_msg *
1199 imap_type_msg,
1200 struct mailimap_body_ext_1part *
1201 body_ext_1part,
1202 struct mailmime ** result)
1203{
1204 struct mailmime * body;
1205 struct mailmime * msg_body;
1206 struct mailmime_fields * mime_fields;
1207 struct mailmime_composite_type * composite_type;
1208 struct mailmime_type * mime_type;
1209 struct mailmime_content * content_type;
1210 struct mailimf_fields * fields;
1211 int r;
1212 int res;
1213 uint32_t mime_size;
1214
1215 r = imap_body_fields_to_mime_fields(imap_type_msg->bd_fields,
1216 body_ext_1part->bd_disposition, body_ext_1part->bd_language,
1217 &mime_fields, &mime_size);
1218 if (r != MAIL_NO_ERROR) {
1219 res = r;
1220 goto err;
1221 }
1222
1223 r = imap_env_to_fields(imap_type_msg->bd_envelope, NULL, 0, &fields);
1224 if (r != MAIL_NO_ERROR) {
1225 res = r;
1226 goto free_mime_fields;
1227 }
1228
1229 r = imap_body_to_body(imap_type_msg->bd_body, &msg_body);
1230 if (r != MAIL_NO_ERROR) {
1231 res = r;
1232 goto free_fields;
1233 }
1234
1235 composite_type =
1236 mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE,
1237 NULL);
1238 if (composite_type == NULL) {
1239 res = MAIL_ERROR_MEMORY;
1240 goto free_fields;
1241 }
1242
1243 mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE,
1244 NULL, composite_type);
1245 if (mime_type == NULL) {
1246 mailmime_composite_type_free(composite_type);
1247 res = MAIL_ERROR_MEMORY;
1248 goto free_fields;
1249 }
1250
1251 r = imap_body_parameter_to_content(imap_type_msg->bd_fields->bd_parameter,
1252 "rfc822", mime_type, &content_type);
1253 if (r != MAIL_NO_ERROR) {
1254 mailmime_type_free(mime_type);
1255 res = MAIL_ERROR_MEMORY;
1256 goto free_fields;
1257 }
1258
1259 body = mailmime_new(MAILMIME_MESSAGE, NULL,
1260 mime_size, mime_fields, content_type,
1261 NULL, NULL, NULL, NULL, fields, msg_body);
1262
1263 if (body == NULL) {
1264 res = MAIL_ERROR_MEMORY;
1265 goto free_content;
1266 }
1267
1268 * result = body;
1269
1270 return MAIL_NO_ERROR;
1271
1272 free_content:
1273 mailmime_content_free(content_type);
1274 free_fields:
1275 mailimf_fields_free(fields);
1276 free_mime_fields:
1277 mailmime_fields_free(mime_fields);
1278 err:
1279 return res;
1280}
1281
1282
1283static int
1284imap_body_type_1part_to_body(struct mailimap_body_type_1part *
1285 type_1part,
1286 struct mailmime ** result)
1287{
1288 struct mailmime * body;
1289 int r;
1290 int res;
1291
1292 switch (type_1part->bd_type) {
1293 case MAILIMAP_BODY_TYPE_1PART_BASIC:
1294 r = imap_body_type_basic_to_body(type_1part->bd_data.bd_type_basic,
1295 type_1part->bd_ext_1part,
1296 &body);
1297 if (r != MAIL_NO_ERROR) {
1298 res = r;
1299 goto err;
1300 }
1301
1302 break;
1303 case MAILIMAP_BODY_TYPE_1PART_MSG:
1304 r = imap_body_type_msg_to_body(type_1part->bd_data.bd_type_msg,
1305 type_1part->bd_ext_1part,
1306 &body);
1307 if (r != MAIL_NO_ERROR) {
1308 res = r;
1309 goto err;
1310 }
1311
1312 break;
1313 case MAILIMAP_BODY_TYPE_1PART_TEXT:
1314 r = imap_body_type_text_to_body(type_1part->bd_data.bd_type_text,
1315 type_1part->bd_ext_1part,
1316 &body);
1317 if (r != MAIL_NO_ERROR) {
1318 res = r;
1319 goto err;
1320 }
1321
1322 break;
1323 }
1324
1325 * result = body;
1326
1327 return MAIL_NO_ERROR;
1328
1329 err:
1330 return res;
1331}
1332
1333static int
1334imap_body_type_mpart_to_body(struct mailimap_body_type_mpart *
1335 type_mpart,
1336 struct mailmime ** result)
1337{
1338 struct mailmime_fields * mime_fields;
1339 struct mailmime_composite_type * composite_type;
1340 struct mailmime_type * mime_type;
1341 struct mailmime_content * content_type;
1342 struct mailmime * body;
1343 clistiter * cur;
1344 clist * list;
1345 int r;
1346 int res;
1347 uint32_t mime_size;
1348
1349 r = imap_body_fields_to_mime_fields(NULL,
1350 type_mpart->bd_ext_mpart->bd_disposition,
1351 type_mpart->bd_ext_mpart->bd_language,
1352 &mime_fields, &mime_size);
1353 if (r != MAIL_NO_ERROR) {
1354 res = r;
1355 goto err;
1356 }
1357
1358 composite_type =
1359 mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART,
1360 NULL);
1361 if (composite_type == NULL) {
1362 res = MAIL_ERROR_MEMORY;
1363 goto free_fields;
1364 }
1365
1366 mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE,
1367 NULL, composite_type);
1368 if (mime_type == NULL) {
1369 mailmime_composite_type_free(composite_type);
1370 res = MAIL_ERROR_MEMORY;
1371 goto free_fields;
1372 }
1373
1374 r = imap_body_parameter_to_content(type_mpart->bd_ext_mpart->bd_parameter,
1375 type_mpart->bd_media_subtype,
1376 mime_type, &content_type);
1377 if (r != MAIL_NO_ERROR) {
1378 mailmime_type_free(mime_type);
1379 res = r;
1380 goto free_fields;
1381 }
1382
1383 list = clist_new();
1384 if (list == NULL) {
1385 res = MAIL_ERROR_MEMORY;
1386 goto free_content;
1387 }
1388
1389 for(cur = clist_begin(type_mpart->bd_list) ; cur != NULL ;
1390 cur = clist_next(cur)) {
1391 struct mailimap_body * imap_body;
1392 struct mailmime * sub_body;
1393
1394 imap_body = clist_content(cur);
1395
1396 r = imap_body_to_body(imap_body, &sub_body);
1397 if (r != MAIL_NO_ERROR) {
1398 res = r;
1399 goto free_list;
1400 }
1401
1402 r = clist_append(list, sub_body);
1403 if (r != 0) {
1404 mailmime_free(sub_body);
1405 res = r;
1406 goto free_list;
1407 }
1408 }
1409
1410 body = mailmime_new(MAILMIME_MULTIPLE, NULL,
1411 mime_size, mime_fields, content_type,
1412 NULL, NULL, NULL, list, NULL, NULL);
1413
1414 if (body == NULL) {
1415 res = MAIL_ERROR_MEMORY;
1416 goto err;
1417 }
1418
1419 * result = body;
1420
1421 return MAIL_NO_ERROR;
1422
1423 free_list:
1424 clist_foreach(list, (clist_func) mailmime_free, NULL);
1425 clist_free(list);
1426 free_content:
1427 mailmime_content_free(content_type);
1428 free_fields:
1429 mailmime_fields_free(mime_fields);
1430 err:
1431 return res;
1432}
1433
1434
1435int imap_body_to_body(struct mailimap_body * imap_body,
1436 struct mailmime ** result)
1437{
1438 struct mailmime * body;
1439 int r;
1440 int res;
1441
1442 switch (imap_body->bd_type) {
1443 case MAILIMAP_BODY_1PART:
1444 r = imap_body_type_1part_to_body(imap_body->bd_data.bd_body_1part, &body);
1445 if (r != MAIL_NO_ERROR) {
1446 res = r;
1447 goto err;
1448 }
1449 break;
1450 case MAILIMAP_BODY_MPART:
1451 r = imap_body_type_mpart_to_body(imap_body->bd_data.bd_body_mpart, &body);
1452 if (r != MAIL_NO_ERROR) {
1453 res = r;
1454 goto err;
1455 }
1456 break;
1457 default:
1458 return MAIL_ERROR_INVAL;
1459 }
1460
1461 * result = body;
1462
1463 return MAIL_NO_ERROR;
1464
1465 err:
1466 return res;
1467}
1468
1469int imap_address_to_mailbox(struct mailimap_address * imap_addr,
1470 struct mailimf_mailbox ** result)
1471{
1472 char * dsp_name;
1473 char * addr;
1474 struct mailimf_mailbox * mb;
1475 int res;
1476
1477 if (imap_addr->ad_personal_name == NULL)
1478 dsp_name = NULL;
1479 else {
1480 dsp_name = strdup(imap_addr->ad_personal_name);
1481 if (dsp_name == NULL) {
1482 res = MAIL_ERROR_MEMORY;
1483 goto err;
1484 }
1485 }
1486
1487 if (imap_addr->ad_host_name == NULL) {
1488 addr = strdup(imap_addr->ad_mailbox_name);
1489 if (addr == NULL) {
1490 res = MAIL_ERROR_MEMORY;
1491 goto free_name;
1492 }
1493 }
1494 else {
1495 addr = malloc(strlen(imap_addr->ad_mailbox_name) +
1496 strlen(imap_addr->ad_host_name) + 2);
1497 if (addr == NULL) {
1498 res = MAIL_ERROR_MEMORY;
1499 goto free_name;
1500 }
1501 strcpy(addr, imap_addr->ad_mailbox_name);
1502 strcat(addr, "@");
1503 strcat(addr, imap_addr->ad_host_name);
1504 }
1505
1506 mb = mailimf_mailbox_new(dsp_name, addr);
1507 if (mb == NULL) {
1508 res = MAIL_ERROR_MEMORY;
1509 goto free_addr;
1510 }
1511
1512 * result = mb;
1513
1514 return MAIL_NO_ERROR;
1515
1516 free_addr:
1517 free(addr);
1518 free_name:
1519 free(dsp_name);
1520 err:
1521 return res;
1522}
1523
1524int imap_address_to_address(struct mailimap_address * imap_addr,
1525 struct mailimf_address ** result)
1526{
1527 struct mailimf_address * addr;
1528 struct mailimf_mailbox * mb;
1529 int r;
1530 int res;
1531
1532 r = imap_address_to_mailbox(imap_addr, &mb);
1533 if (r != MAIL_NO_ERROR) {
1534 res = r;
1535 goto err;
1536 }
1537
1538 addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
1539 if (addr == NULL) {
1540 res = MAIL_ERROR_MEMORY;
1541 goto free_mb;
1542 }
1543
1544 * result = addr;
1545
1546 return MAIL_NO_ERROR;
1547
1548 free_mb:
1549 mailimf_mailbox_free(mb);
1550 err:
1551 return res;
1552}
1553
1554int
1555imap_mailbox_list_to_mailbox_list(clist * imap_mailbox_list,
1556 struct mailimf_mailbox_list ** result)
1557{
1558 clistiter * cur;
1559 clist * list;
1560 struct mailimf_mailbox_list * mb_list;
1561 int r;
1562 int res;
1563
1564 list = clist_new();
1565 if (list == NULL) {
1566 res = MAIL_ERROR_MEMORY;
1567 goto err;
1568 }
1569
1570 for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ;
1571 cur = clist_next(cur)) {
1572 struct mailimap_address * imap_addr;
1573 struct mailimf_mailbox * mb;
1574
1575 imap_addr = clist_content(cur);
1576
1577 if (imap_addr->ad_mailbox_name == NULL)
1578 continue;
1579
1580 r = imap_address_to_mailbox(imap_addr, &mb);
1581 if (r != MAIL_NO_ERROR) {
1582 res = r;
1583 goto free_list;
1584 }
1585
1586 r = clist_append(list, mb);
1587 if (r != 0) {
1588 mailimf_mailbox_free(mb);
1589 res = MAIL_ERROR_MEMORY;
1590 goto free_list;
1591 }
1592 }
1593
1594 mb_list = mailimf_mailbox_list_new(list);
1595 if (mb_list == NULL) {
1596 res = MAIL_ERROR_MEMORY;
1597 goto free_list;
1598 }
1599
1600 * result = mb_list;
1601
1602 return MAIL_NO_ERROR;
1603
1604 free_list:
1605 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
1606 clist_free(list);
1607 err:
1608 return MAIL_ERROR_MEMORY;
1609}
1610
1611
1612
1613/*
1614 at exit, imap_mb_list will fall on the last element of the group,
1615 where mailbox name will be NIL, so that imap_mailbox_list_to_address_list
1616 can continue
1617*/
1618
1619static int imap_mailbox_list_to_group(clist * imap_mb_list, clistiter ** iter,
1620 struct mailimf_group ** result)
1621{
1622 clistiter * imap_mailbox_listiter;
1623 clist * list;
1624 struct mailimf_group * group;
1625 struct mailimap_address * imap_addr;
1626 char * group_name;
1627 clistiter * cur;
1628 struct mailimf_mailbox_list * mb_list;
1629 int r;
1630 int res;
1631
1632 imap_mailbox_listiter = * iter;
1633
1634 imap_addr = clist_content(imap_mailbox_listiter);
1635 if (imap_addr->ad_mailbox_name == NULL) {
1636 res = MAIL_ERROR_INVAL;
1637 goto err;
1638 }
1639
1640 group_name = strdup(imap_addr->ad_mailbox_name);
1641 if (group_name == NULL) {
1642 res = MAIL_ERROR_MEMORY;
1643 goto err;
1644 }
1645
1646 list = clist_new();
1647 if (list == NULL) {
1648 res = MAIL_ERROR_MEMORY;
1649 goto free_group_name;
1650 }
1651
1652 for(cur = clist_next(imap_mailbox_listiter) ; cur != NULL ;
1653 cur = clist_next(cur)) {
1654 struct mailimf_mailbox * mb;
1655
1656 imap_addr = clist_content(cur);
1657
1658 if (imap_addr->ad_mailbox_name == NULL) {
1659 break;
1660 }
1661
1662 r = imap_address_to_mailbox(imap_addr, &mb);
1663 if (r != MAIL_NO_ERROR) {
1664 res = r;
1665 goto free_list;
1666 }
1667
1668 r = clist_append(list, mb);
1669 if (r != 0) {
1670 mailimf_mailbox_free(mb);
1671 res = MAIL_ERROR_MEMORY;
1672 goto free_list;
1673 }
1674 }
1675
1676 mb_list = mailimf_mailbox_list_new(list);
1677 if (mb_list == NULL) {
1678 res = MAIL_ERROR_MEMORY;
1679 goto free_list;
1680 }
1681
1682 group = mailimf_group_new(group_name, mb_list);
1683 if (group == NULL) {
1684 mailimf_mailbox_list_free(mb_list);
1685 res = MAIL_ERROR_MEMORY;
1686 goto free_group_name;
1687 }
1688
1689 * result = group;
1690 * iter = cur;
1691
1692 return MAIL_NO_ERROR;
1693
1694 free_list:
1695 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
1696 clist_free(list);
1697 free_group_name:
1698 free(group_name);
1699 err:
1700 return res;
1701}
1702
1703int
1704imap_mailbox_list_to_address_list(clist * imap_mailbox_list,
1705 struct mailimf_address_list ** result)
1706{
1707 clistiter * cur;
1708 clist * list;
1709 struct mailimf_address_list * addr_list;
1710 int r;
1711 int res;
1712
1713 list = clist_new();
1714 if (list == NULL) {
1715 res = MAIL_ERROR_MEMORY;
1716 goto err;
1717 }
1718
1719 for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ;
1720 cur = clist_next(cur)) {
1721 struct mailimap_address * imap_addr;
1722 struct mailimf_address * addr;
1723
1724 imap_addr = clist_content(cur);
1725
1726 if (imap_addr->ad_mailbox_name == NULL)
1727 continue;
1728
1729 if ((imap_addr->ad_host_name == NULL) &&
1730 (imap_addr->ad_mailbox_name != NULL)) {
1731 struct mailimf_group * group;
1732
1733 r = imap_mailbox_list_to_group(imap_mailbox_list, &cur, &group);
1734 if (r != MAIL_NO_ERROR) {
1735 res = r;
1736 goto free_list;
1737 }
1738
1739 addr = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, group);
1740 if (addr == NULL) {
1741 mailimf_group_free(group);
1742 res = MAIL_ERROR_MEMORY;
1743 goto free_list;
1744 }
1745 }
1746 else {
1747 r = imap_address_to_address(imap_addr, &addr);
1748 if (r != MAIL_NO_ERROR) {
1749 res = r;
1750 goto free_list;
1751 }
1752 }
1753
1754 r = clist_append(list, addr);
1755 if (r != 0) {
1756 mailimf_address_free(addr);
1757 res = MAIL_ERROR_MEMORY;
1758 goto free_list;
1759 }
1760 }
1761
1762 addr_list = mailimf_address_list_new(list);
1763 if (addr_list == NULL) {
1764 res = MAIL_ERROR_MEMORY;
1765 goto free_list;
1766 }
1767
1768 * result = addr_list;
1769
1770 return MAIL_NO_ERROR;
1771
1772 free_list:
1773 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
1774 clist_free(list);
1775 err:
1776 return res;
1777}
1778
1779
1780int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type)
1781{
1782 struct mailimap_fetch_att * fetch_att;
1783 int res;
1784 int r;
1785 char * header;
1786 clist * hdrlist;
1787 struct mailimap_header_list * imap_hdrlist;
1788 struct mailimap_section * section;
1789
1790 fetch_att = mailimap_fetch_att_new_envelope();
1791 if (fetch_att == NULL) {
1792 res = MAIL_ERROR_MEMORY;
1793 goto err;
1794 }
1795
1796 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1797 if (r != MAILIMAP_NO_ERROR) {
1798 mailimap_fetch_att_free(fetch_att);
1799 res = MAIL_ERROR_MEMORY;
1800 goto err;
1801 }
1802
1803 header = strdup("References");
1804 if (header == NULL) {
1805 mailimap_fetch_att_free(fetch_att);
1806 res = MAIL_ERROR_MEMORY;
1807 goto err;
1808 }
1809
1810 hdrlist = clist_new();
1811 if (hdrlist == NULL) {
1812 free(header);
1813 mailimap_fetch_att_free(fetch_att);
1814 res = MAIL_ERROR_MEMORY;
1815 goto err;
1816 }
1817
1818 r = clist_append(hdrlist, header);
1819 if (r < 0) {
1820 free(header);
1821 clist_foreach(hdrlist, (clist_func) free, NULL);
1822 clist_free(hdrlist);
1823 mailimap_fetch_att_free(fetch_att);
1824 res = MAIL_ERROR_MEMORY;
1825 goto err;
1826 }
1827
1828 imap_hdrlist = mailimap_header_list_new(hdrlist);
1829 if (imap_hdrlist == 0) {
1830 clist_foreach(hdrlist, (clist_func) free, NULL);
1831 clist_free(hdrlist);
1832 mailimap_fetch_att_free(fetch_att);
1833 res = MAIL_ERROR_MEMORY;
1834 goto err;
1835 }
1836
1837 section = mailimap_section_new_header_fields(imap_hdrlist);
1838 if (section == NULL) {
1839 mailimap_header_list_free(imap_hdrlist);
1840 mailimap_fetch_att_free(fetch_att);
1841 res = MAIL_ERROR_MEMORY;
1842 goto err;
1843 }
1844
1845 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1846 if (fetch_att == NULL) {
1847 mailimap_section_free(section);
1848 res = MAIL_ERROR_MEMORY;
1849 goto err;
1850 }
1851
1852 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1853 if (r != MAILIMAP_NO_ERROR) {
1854 mailimap_fetch_att_free(fetch_att);
1855 res = MAIL_ERROR_MEMORY;
1856 goto err;
1857 }
1858
1859 return MAIL_NO_ERROR;
1860
1861 err:
1862 return res;
1863}
1864
1865
1866int imap_env_to_fields(struct mailimap_envelope * env,
1867 char * ref_str, size_t ref_size,
1868 struct mailimf_fields ** result)
1869{
1870 clist * list;
1871 struct mailimf_field * field;
1872 int r;
1873 struct mailimf_fields * fields;
1874 int res;
1875
1876 list = clist_new();
1877 if (list == NULL) {
1878 res = MAIL_ERROR_MEMORY;
1879 goto err;
1880 }
1881
1882 if (env->env_date != NULL) {
1883 size_t cur_token;
1884 struct mailimf_date_time * date_time;
1885
1886 cur_token = 0;
1887 r = mailimf_date_time_parse(env->env_date, strlen(env->env_date),
1888 &cur_token, &date_time);
1889
1890 if (r == MAILIMF_NO_ERROR) {
1891 struct mailimf_orig_date * orig;
1892
1893 orig = mailimf_orig_date_new(date_time);
1894 if (orig == NULL) {
1895 mailimf_date_time_free(date_time);
1896 res = MAIL_ERROR_MEMORY;
1897 goto free_list;
1898 }
1899
1900 field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE,
1901 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1902 NULL, orig, NULL,
1903 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1904 NULL, NULL, NULL, NULL, NULL);
1905 if (field == NULL) {
1906 mailimf_orig_date_free(orig);
1907 res = MAIL_ERROR_MEMORY;
1908 goto free_list;
1909 }
1910
1911 r = clist_append(list, field);
1912 if (r != 0) {
1913 mailimf_field_free(field);
1914 res = MAIL_ERROR_MEMORY;
1915 goto free_list;
1916 }
1917 }
1918 }
1919
1920 if (env->env_subject != NULL) {
1921 char * subject;
1922 struct mailimf_subject * subject_field;
1923
1924 subject = strdup(env->env_subject);
1925 if (subject == NULL) {
1926 res = MAIL_ERROR_MEMORY;
1927 goto free_list;
1928 }
1929
1930
1931 subject_field = mailimf_subject_new(subject);
1932 if (subject_field == NULL) {
1933 free(subject);
1934 res = MAIL_ERROR_MEMORY;
1935 goto free_list;
1936 }
1937
1938 field = mailimf_field_new(MAILIMF_FIELD_SUBJECT,
1939 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1940 NULL, NULL, NULL,
1941 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1942 NULL, subject_field, NULL, NULL, NULL);
1943 if (field == NULL) {
1944 mailimf_subject_free(subject_field);
1945 res = MAIL_ERROR_MEMORY;
1946 goto free_list;
1947 }
1948
1949 r = clist_append(list, field);
1950 if (r != 0) {
1951 mailimf_field_free(field);
1952 res = MAIL_ERROR_MEMORY;
1953 goto free_list;
1954 }
1955 }
1956
1957 if (env->env_from != NULL) {
1958 if (env->env_from->frm_list != NULL) {
1959 struct mailimf_mailbox_list * mb_list;
1960 struct mailimf_from * from;
1961
1962 r = imap_mailbox_list_to_mailbox_list(env->env_from->frm_list, &mb_list);
1963
1964 if (r != MAIL_NO_ERROR) {
1965 res = r;
1966 goto free_list;
1967 }
1968
1969 from = mailimf_from_new(mb_list);
1970 if (from == NULL) {
1971 mailimf_mailbox_list_free(mb_list);
1972 res = MAIL_ERROR_MEMORY;
1973 goto free_list;
1974 }
1975
1976 field = mailimf_field_new(MAILIMF_FIELD_FROM,
1977 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1978 NULL, NULL, from,
1979 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1980 NULL, NULL, NULL, NULL, NULL);
1981 if (field == NULL) {
1982 mailimf_from_free(from);
1983 res = MAIL_ERROR_MEMORY;
1984 goto free_list;
1985 }
1986
1987 r = clist_append(list, field);
1988 if (r != 0) {
1989 mailimf_field_free(field);
1990 res = MAIL_ERROR_MEMORY;
1991 goto free_list;
1992 }
1993 }
1994 }
1995
1996 if (env->env_sender != NULL) {
1997 if (env->env_sender->snd_list != NULL) {
1998 struct mailimf_sender * sender;
1999 struct mailimf_mailbox * mb;
2000
2001 r = imap_address_to_mailbox(clist_begin(env->env_sender->snd_list)->data, &mb);
2002
2003 if (r != MAIL_NO_ERROR) {
2004 res = r;
2005 goto free_list;
2006 }
2007
2008 sender = mailimf_sender_new(mb);
2009 if (sender == NULL) {
2010 mailimf_mailbox_free(mb);
2011 res = MAIL_ERROR_MEMORY;
2012 goto free_list;
2013 }
2014
2015 field = mailimf_field_new(MAILIMF_FIELD_SENDER,
2016 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2017 NULL, NULL, NULL,
2018 sender, NULL, NULL, NULL, NULL, NULL, NULL,
2019 NULL, NULL, NULL, NULL, NULL);
2020 if (field == NULL) {
2021 mailimf_sender_free(sender);
2022 res = MAIL_ERROR_MEMORY;
2023 goto free_list;
2024 }
2025
2026 r = clist_append(list, field);
2027 if (r != 0) {
2028 mailimf_field_free(field);
2029 res = MAIL_ERROR_MEMORY;
2030 goto free_list;
2031 }
2032 }
2033 }
2034
2035 if (env->env_reply_to != NULL) {
2036 if (env->env_reply_to->rt_list != NULL) {
2037 struct mailimf_address_list * addr_list;
2038 struct mailimf_reply_to * reply_to;
2039
2040 r = imap_mailbox_list_to_address_list(env->env_reply_to->rt_list,
2041 &addr_list);
2042
2043 if (r != MAIL_NO_ERROR) {
2044 res = r;
2045 goto free_list;
2046 }
2047
2048 reply_to = mailimf_reply_to_new(addr_list);
2049 if (reply_to == NULL) {
2050 mailimf_address_list_free(addr_list);
2051 res = MAIL_ERROR_MEMORY;
2052 goto free_list;
2053 }
2054
2055 field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO,
2056 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2057 NULL, NULL, NULL,
2058 NULL, reply_to, NULL, NULL, NULL, NULL, NULL,
2059 NULL, NULL, NULL, NULL, NULL);
2060 if (field == NULL) {
2061 mailimf_reply_to_free(reply_to);
2062 res = MAIL_ERROR_MEMORY;
2063 goto free_list;
2064 }
2065
2066 r = clist_append(list, field);
2067 if (r != 0) {
2068 mailimf_field_free(field);
2069 res = MAIL_ERROR_MEMORY;
2070 goto free_list;
2071 }
2072 }
2073 }
2074
2075 if (env->env_to != NULL) {
2076 if (env->env_to->to_list != NULL) {
2077 struct mailimf_address_list * addr_list;
2078 struct mailimf_to * to;
2079
2080 r = imap_mailbox_list_to_address_list(env->env_to->to_list, &addr_list);
2081
2082 if (r != MAIL_NO_ERROR) {
2083 res = r;
2084 goto free_list;
2085 }
2086
2087 to = mailimf_to_new(addr_list);
2088 if (to == NULL) {
2089 mailimf_address_list_free(addr_list);
2090 res = MAIL_ERROR_MEMORY;
2091 goto free_list;
2092 }
2093
2094 field = mailimf_field_new(MAILIMF_FIELD_TO,
2095 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2096 NULL, NULL, NULL,
2097 NULL, NULL, to, NULL, NULL, NULL, NULL,
2098 NULL, NULL, NULL, NULL, NULL);
2099 if (field == NULL) {
2100 mailimf_to_free(to);
2101 res = MAIL_ERROR_MEMORY;
2102 goto free_list;
2103 }
2104
2105 r = clist_append(list, field);
2106 if (r != 0) {
2107 mailimf_field_free(field);
2108 res = MAIL_ERROR_MEMORY;
2109 goto free_list;
2110 }
2111 }
2112 }
2113
2114 if (env->env_cc != NULL) {
2115 if (env->env_cc->cc_list != NULL) {
2116 struct mailimf_address_list * addr_list;
2117 struct mailimf_cc * cc;
2118
2119 r = imap_mailbox_list_to_address_list(env->env_cc->cc_list, &addr_list);
2120
2121 if (r != MAIL_NO_ERROR) {
2122 res = r;
2123 goto free_list;
2124 }
2125
2126 cc = mailimf_cc_new(addr_list);
2127 if (cc == NULL) {
2128 mailimf_address_list_free(addr_list);
2129 res = MAIL_ERROR_MEMORY;
2130 goto free_list;
2131 }
2132
2133 field = mailimf_field_new(MAILIMF_FIELD_CC,
2134 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2135 NULL, NULL, NULL,
2136 NULL, NULL, NULL, cc, NULL, NULL, NULL,
2137 NULL, NULL, NULL, NULL, NULL);
2138 if (field == NULL) {
2139 mailimf_cc_free(cc);
2140 res = MAIL_ERROR_MEMORY;
2141 goto free_list;
2142 }
2143
2144 r = clist_append(list, field);
2145 if (r != 0) {
2146 mailimf_field_free(field);
2147 res = MAIL_ERROR_MEMORY;
2148 goto free_list;
2149 }
2150 }
2151 }
2152
2153 if (env->env_bcc != NULL) {
2154 if (env->env_bcc->bcc_list != NULL) {
2155 struct mailimf_address_list * addr_list;
2156 struct mailimf_bcc * bcc;
2157
2158 r = imap_mailbox_list_to_address_list(env->env_bcc->bcc_list,
2159 &addr_list);
2160
2161 if (r != MAIL_NO_ERROR) {
2162 res = r;
2163 goto free_list;
2164 }
2165
2166 bcc = mailimf_bcc_new(addr_list);
2167 if (bcc == NULL) {
2168 mailimf_address_list_free(addr_list);
2169 res = MAIL_ERROR_MEMORY;
2170 goto free_list;
2171 }
2172
2173 field = mailimf_field_new(MAILIMF_FIELD_BCC,
2174 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2175 NULL, NULL, NULL,
2176 NULL, NULL, NULL, NULL, bcc, NULL, NULL,
2177 NULL, NULL, NULL, NULL, NULL);
2178 if (field == NULL) {
2179 mailimf_bcc_free(bcc);
2180 res = MAIL_ERROR_MEMORY;
2181 goto free_list;
2182 }
2183
2184 r = clist_append(list, field);
2185 if (r != 0) {
2186 mailimf_field_free(field);
2187 res = MAIL_ERROR_MEMORY;
2188 goto free_list;
2189 }
2190 }
2191 }
2192
2193 if (env->env_in_reply_to != NULL) {
2194 struct mailimf_in_reply_to * in_reply_to;
2195 size_t cur_token;
2196 clist * msg_id_list;
2197
2198 cur_token = 0;
2199 r = mailimf_msg_id_list_parse(env->env_in_reply_to,
2200 strlen(env->env_in_reply_to), &cur_token, &msg_id_list);
2201
2202 switch (r) {
2203 case MAILIMF_NO_ERROR:
2204 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
2205 if (in_reply_to == NULL) {
2206 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
2207 clist_free(msg_id_list);
2208 res = MAIL_ERROR_MEMORY;
2209 goto free_list;
2210 }
2211
2212 field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO,
2213 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2214 NULL, NULL, NULL,
2215 NULL, NULL, NULL, NULL, NULL, NULL,
2216 in_reply_to,
2217 NULL, NULL, NULL, NULL, NULL);
2218 if (field == NULL) {
2219 mailimf_in_reply_to_free(in_reply_to);
2220 res = MAIL_ERROR_MEMORY;
2221 goto free_list;
2222 }
2223
2224 r = clist_append(list, field);
2225 if (r != 0) {
2226 mailimf_field_free(field);
2227 res = MAIL_ERROR_MEMORY;
2228 goto free_list;
2229 }
2230 break;
2231
2232 case MAILIMF_ERROR_PARSE:
2233 break;
2234
2235 default:
2236 res = maildriver_imf_error_to_mail_error(r);
2237 goto free_list;
2238 }
2239 }
2240
2241 if (env->env_message_id != NULL) {
2242 char * id;
2243 struct mailimf_message_id * msg_id;
2244 size_t cur_token;
2245
2246 cur_token = 0;
2247 r = mailimf_msg_id_parse(env->env_message_id, strlen(env->env_message_id),
2248 &cur_token, &id);
2249 switch (r) {
2250 case MAILIMF_NO_ERROR:
2251
2252 msg_id = mailimf_message_id_new(id);
2253 if (msg_id == NULL) {
2254 mailimf_msg_id_free(id);
2255 res = MAIL_ERROR_MEMORY;
2256 goto free_list;
2257 }
2258
2259 field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID,
2260 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2261 NULL, NULL, NULL,
2262 NULL, NULL, NULL, NULL, NULL, msg_id, NULL,
2263 NULL, NULL, NULL, NULL, NULL);
2264 if (field == NULL) {
2265 mailimf_message_id_free(msg_id);
2266 res = MAIL_ERROR_MEMORY;
2267 goto free_list;
2268 }
2269
2270 r = clist_append(list, field);
2271 if (r != 0) {
2272 mailimf_field_free(field);
2273 res = MAIL_ERROR_MEMORY;
2274 goto free_list;
2275 }
2276 break;
2277
2278 case MAILIMF_ERROR_PARSE:
2279 break;
2280
2281 default:
2282 res = maildriver_imf_error_to_mail_error(r);
2283 goto free_list;
2284 }
2285 }
2286
2287 if (ref_str != NULL) {
2288 struct mailimf_references * references;
2289 size_t cur_token;
2290
2291 cur_token = 0;
2292 r = mailimf_references_parse(ref_str, ref_size,
2293 &cur_token, &references);
2294 switch (r) {
2295 case MAILIMF_NO_ERROR:
2296 field = mailimf_field_new(MAILIMF_FIELD_REFERENCES,
2297 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2298 NULL, NULL, NULL,
2299 NULL, NULL, NULL, NULL, NULL, NULL,
2300 NULL,
2301 references, NULL, NULL, NULL, NULL);
2302 if (field == NULL) {
2303 mailimf_references_free(references);
2304 res = MAIL_ERROR_MEMORY;
2305 goto free_list;
2306 }
2307
2308 r = clist_append(list, field);
2309 if (r < 0) {
2310 mailimf_field_free(field);
2311 res = MAIL_ERROR_MEMORY;
2312 goto free_list;
2313 }
2314 break;
2315
2316 case MAILIMF_ERROR_PARSE:
2317 break;
2318
2319 default:
2320 res = maildriver_imf_error_to_mail_error(r);
2321 goto free_list;
2322 }
2323 }
2324
2325 fields = mailimf_fields_new(list);
2326 if (fields == NULL) {
2327 res = MAIL_ERROR_MEMORY;
2328 goto free_list;
2329 }
2330
2331 * result = fields;
2332
2333 return MAIL_NO_ERROR;
2334
2335 free_list:
2336 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
2337 clist_free(list);
2338 err:
2339 return res;
2340}
2341
2342int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
2343 uint32_t * puid,
2344 struct mailimap_envelope ** pimap_envelope,
2345 char ** preferences,
2346 size_t * pref_size,
2347 struct mailimap_msg_att_dynamic ** patt_dyn,
2348 struct mailimap_body ** pimap_body)
2349{
2350 clistiter * item_cur;
2351 uint32_t uid;
2352 struct mailimap_envelope * imap_envelope;
2353 char * references;
2354 size_t ref_size;
2355 struct mailimap_msg_att_dynamic * att_dyn;
2356 struct mailimap_body * imap_body;
2357
2358 uid = 0;
2359 imap_envelope = NULL;
2360 references = NULL;
2361 ref_size = 0;
2362 att_dyn = NULL;
2363 imap_body = NULL;
2364
2365 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
2366 item_cur = clist_next(item_cur)) {
2367 struct mailimap_msg_att_item * item;
2368
2369 item = clist_content(item_cur);
2370
2371 switch (item->att_type) {
2372 case MAILIMAP_MSG_ATT_ITEM_STATIC:
2373 switch (item->att_data.att_static->att_type) {
2374 case MAILIMAP_MSG_ATT_BODYSTRUCTURE:
2375 if (imap_body == NULL)
2376 imap_body = item->att_data.att_static->att_data.att_bodystructure;
2377 break;
2378
2379 case MAILIMAP_MSG_ATT_ENVELOPE:
2380 if (imap_envelope == NULL) {
2381 imap_envelope = item->att_data.att_static->att_data.att_env;
2382 }
2383 break;
2384
2385 case MAILIMAP_MSG_ATT_UID:
2386 uid = item->att_data.att_static->att_data.att_uid;
2387 break;
2388
2389 case MAILIMAP_MSG_ATT_BODY_SECTION:
2390 if (references == NULL) {
2391 references = item->att_data.att_static->att_data.att_body_section->sec_body_part;
2392 ref_size = item->att_data.att_static->att_data.att_body_section->sec_length;
2393 }
2394 break;
2395 }
2396 break;
2397
2398 case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
2399 if (att_dyn == NULL) {
2400 att_dyn = item->att_data.att_dyn;
2401 }
2402 break;
2403 }
2404 }
2405
2406 if (puid != NULL)
2407 * puid = uid;
2408 if (pimap_envelope != NULL)
2409 * pimap_envelope = imap_envelope;
2410 if (preferences != NULL)
2411 * preferences = references;
2412 if (pref_size != NULL)
2413 * pref_size = ref_size;
2414 if (patt_dyn != NULL)
2415 * patt_dyn = att_dyn;
2416 if (pimap_body != NULL)
2417 * pimap_body = imap_body;
2418
2419 return MAIL_NO_ERROR;
2420}
2421
2422int
2423imap_fetch_result_to_envelop_list(clist * fetch_result,
2424 struct mailmessage_list * env_list)
2425{
2426 clistiter * cur;
2427 int r;
2428 unsigned int i;
2429
2430 i = 0;
2431
2432 for(cur = clist_begin(fetch_result) ; cur != NULL ;
2433 cur = clist_next(cur)) {
2434 struct mailimap_msg_att * msg_att;
2435 uint32_t uid;
2436 struct mailimap_envelope * imap_envelope;
2437 struct mailimap_msg_att_dynamic * att_dyn;
2438 char * references;
2439 size_t ref_size;
2440
2441 msg_att = clist_content(cur);
2442
2443 r = imap_get_msg_att_info(msg_att, &uid, &imap_envelope,
2444 &references, &ref_size,
2445 &att_dyn,
2446 NULL);
2447
2448 if (r == MAIL_NO_ERROR) {
2449 if (uid != 0) {
2450 while (i < carray_count(env_list->msg_tab)) {
2451 mailmessage * msg;
2452
2453 msg = carray_get(env_list->msg_tab, i);
2454
2455 if (uid == msg->msg_index) {
2456 struct mailimf_fields * fields;
2457 struct mail_flags * flags;
2458
2459 if (imap_envelope != NULL) {
2460 r = imap_env_to_fields(imap_envelope,
2461 references, ref_size, &fields);
2462 if (r == MAIL_NO_ERROR) {
2463 msg->msg_fields = fields;
2464 }
2465 }
2466
2467 if (att_dyn != NULL) {
2468 r = imap_flags_to_flags(att_dyn, &flags);
2469
2470 if (r == MAIL_NO_ERROR) {
2471 msg->msg_flags = flags;
2472 }
2473 }
2474
2475 i ++;
2476 break;
2477 }
2478
2479 i ++;
2480 }
2481 }
2482 }
2483 }
2484
2485 return MAIL_NO_ERROR;
2486}
2487
2488
2489int mailimf_date_time_to_imap_date(struct mailimf_date_time * date,
2490 struct mailimap_date ** result)
2491{
2492 struct mailimap_date * imap_date;
2493
2494 imap_date = mailimap_date_new(date->dt_day, date->dt_month, date->dt_year);
2495 if (imap_date == NULL)
2496 return MAIL_ERROR_MEMORY;
2497
2498 * result = imap_date;
2499
2500 return MAIL_NO_ERROR;
2501}
2502
2503
2504#if 0
2505int mail_search_to_imap_search(struct mail_search_key * key,
2506 struct mailimap_search_key ** result)
2507{
2508 struct mailimap_search_key * imap_key;
2509
2510 char * bcc;
2511 struct mailimap_date * before;
2512 char * body;
2513 char * cc;
2514 char * from;
2515 struct mailimap_date * on;
2516 struct mailimap_date * since;
2517 char * subject;
2518 char * text;
2519 char * to;
2520 char * header_name;
2521 char * header_value;
2522 size_t larger;
2523 struct mailimap_search_key * not;
2524 struct mailimap_search_key * or1;
2525 struct mailimap_search_key * or2;
2526 size_t smaller;
2527 clist * multiple;
2528 int type;
2529 clistiter * cur;
2530 int r;
2531 int res;
2532
2533 bcc = NULL;
2534 before = NULL;
2535 body = NULL;
2536 cc = NULL;
2537 from = NULL;
2538 on = NULL;
2539 since = NULL;
2540 subject = NULL;
2541 text = NULL;
2542 to = NULL;
2543 header_name = NULL;
2544 header_value = NULL;
2545 not = NULL;
2546 or1 = NULL;
2547 or2 = NULL;
2548 multiple = NULL;
2549 larger = 0;
2550 smaller = 0;
2551
2552 switch (key->sk_type) {
2553 case MAIL_SEARCH_KEY_ALL:
2554 type = MAILIMAP_SEARCH_KEY_ALL;
2555 break;
2556
2557 case MAIL_SEARCH_KEY_ANSWERED:
2558 type = MAILIMAP_SEARCH_KEY_ANSWERED;
2559 break;
2560
2561 case MAIL_SEARCH_KEY_BCC:
2562 type = MAILIMAP_SEARCH_KEY_BCC;
2563 bcc = strdup(key->sk_bcc);
2564 if (bcc == NULL) {
2565 res = MAIL_ERROR_MEMORY;
2566 goto err;
2567 }
2568 break;
2569
2570 case MAIL_SEARCH_KEY_BEFORE:
2571 type = MAILIMAP_SEARCH_KEY_BEFORE;
2572 r = mailimf_date_time_to_imap_date(key->sk_before, &before);
2573 if (r != MAIL_NO_ERROR) {
2574 res = r;
2575 goto err;
2576 }
2577 break;
2578
2579 case MAIL_SEARCH_KEY_BODY:
2580 type = MAILIMAP_SEARCH_KEY_BODY;
2581 body = strdup(key->sk_body);
2582 if (body == NULL) {
2583 res = MAIL_ERROR_MEMORY;
2584 goto err;
2585 }
2586 break;
2587
2588 case MAIL_SEARCH_KEY_CC:
2589 type = MAILIMAP_SEARCH_KEY_CC;
2590 cc = strdup(key->sk_cc);
2591 if (cc == NULL) {
2592 res = MAIL_ERROR_MEMORY;
2593 goto err;
2594 }
2595 break;
2596
2597 case MAIL_SEARCH_KEY_DELETED:
2598 type = MAILIMAP_SEARCH_KEY_DELETED;
2599 break;
2600
2601 case MAIL_SEARCH_KEY_FLAGGED:
2602 type = MAILIMAP_SEARCH_KEY_FLAGGED;
2603 break;
2604
2605 case MAIL_SEARCH_KEY_FROM:
2606 type = MAILIMAP_SEARCH_KEY_FROM;
2607 from = strdup(key->sk_from);
2608 if (from == NULL) {
2609 res = MAIL_ERROR_MEMORY;
2610 goto err;
2611 }
2612 break;
2613
2614 case MAIL_SEARCH_KEY_NEW:
2615 type = MAILIMAP_SEARCH_KEY_NEW;
2616 break;
2617
2618 case MAIL_SEARCH_KEY_OLD:
2619 type = MAILIMAP_SEARCH_KEY_OLD;
2620 break;
2621
2622 case MAIL_SEARCH_KEY_ON:
2623 type = MAILIMAP_SEARCH_KEY_ON;
2624 r = mailimf_date_time_to_imap_date(key->sk_on, &on);
2625 if (r != MAIL_NO_ERROR) {
2626 res = r;
2627 goto err;
2628 }
2629 break;
2630
2631 case MAIL_SEARCH_KEY_RECENT:
2632 type = MAILIMAP_SEARCH_KEY_RECENT;
2633 break;
2634
2635 case MAIL_SEARCH_KEY_SEEN:
2636 type = MAILIMAP_SEARCH_KEY_SEEN;
2637 break;
2638
2639 case MAIL_SEARCH_KEY_SINCE:
2640 type = MAILIMAP_SEARCH_KEY_SINCE;
2641 r = mailimf_date_time_to_imap_date(key->sk_since, &since);
2642 if (r != MAIL_NO_ERROR) {
2643 res = r;
2644 goto err;
2645 }
2646 break;
2647
2648 case MAIL_SEARCH_KEY_SUBJECT:
2649 type = MAILIMAP_SEARCH_KEY_SUBJECT;
2650 subject = strdup(key->sk_subject);
2651 if (subject == NULL) {
2652 res = MAIL_ERROR_MEMORY;
2653 goto err;
2654 }
2655 break;
2656
2657 case MAIL_SEARCH_KEY_TEXT:
2658 type = MAILIMAP_SEARCH_KEY_TEXT;
2659 text = strdup(key->sk_text);
2660 if (text == NULL) {
2661 res = MAIL_ERROR_MEMORY;
2662 goto err;
2663 }
2664 break;
2665
2666 case MAIL_SEARCH_KEY_TO:
2667 type = MAILIMAP_SEARCH_KEY_TO;
2668 to = strdup(key->sk_to);
2669 if (to == NULL) {
2670 return MAIL_ERROR_MEMORY;
2671 goto err;
2672 }
2673 break;
2674
2675 case MAIL_SEARCH_KEY_UNANSWERED:
2676 type = MAILIMAP_SEARCH_KEY_UNANSWERED;
2677 break;
2678
2679 case MAIL_SEARCH_KEY_UNDELETED:
2680 type = MAILIMAP_SEARCH_KEY_UNFLAGGED;
2681 break;
2682
2683 case MAIL_SEARCH_KEY_UNFLAGGED:
2684 type = MAILIMAP_SEARCH_KEY_UNANSWERED;
2685 break;
2686
2687 case MAIL_SEARCH_KEY_UNSEEN:
2688 type = MAILIMAP_SEARCH_KEY_UNSEEN;
2689 break;
2690
2691 case MAIL_SEARCH_KEY_HEADER:
2692 type = MAILIMAP_SEARCH_KEY_HEADER;
2693 header_name = strdup(key->sk_header_name);
2694 if (header_name == NULL) {
2695 res = MAIL_ERROR_MEMORY;
2696 goto err;
2697 }
2698 header_value = strdup(key->sk_header_value);
2699 if (header_value == NULL) {
2700 free(header_name);
2701 res = MAIL_ERROR_MEMORY;
2702 goto err;
2703 }
2704 break;
2705
2706 case MAIL_SEARCH_KEY_LARGER:
2707 type = MAILIMAP_SEARCH_KEY_LARGER;
2708 larger = key->sk_larger;
2709 break;
2710
2711 case MAIL_SEARCH_KEY_NOT:
2712 type = MAILIMAP_SEARCH_KEY_NOT;
2713 r = mail_search_to_imap_search(key->sk_not, &not);
2714 if (r != MAIL_NO_ERROR) {
2715 res = r;
2716 goto err;
2717 }
2718 break;
2719
2720 case MAIL_SEARCH_KEY_OR:
2721 type = MAILIMAP_SEARCH_KEY_OR;
2722 r = mail_search_to_imap_search(key->sk_or1, &or1);
2723 if (r != MAIL_NO_ERROR) {
2724 res = r;
2725 goto err;
2726 }
2727 r = mail_search_to_imap_search(key->sk_or2, &or2);
2728 if (r != MAIL_NO_ERROR) {
2729 mailimap_search_key_free(or1);
2730 res = r;
2731 goto err;
2732 }
2733 break;
2734
2735 case MAIL_SEARCH_KEY_SMALLER:
2736 type = MAILIMAP_SEARCH_KEY_SMALLER;
2737 smaller = key->sk_smaller;
2738 break;
2739
2740 case MAIL_SEARCH_KEY_MULTIPLE:
2741 multiple = clist_new();
2742 if (multiple == NULL) {
2743 res = MAIL_ERROR_MEMORY;
2744 goto err;
2745 }
2746
2747 type = MAILIMAP_SEARCH_KEY_MULTIPLE;
2748 for(cur = clist_begin(key->sk_multiple) ; cur != NULL ;
2749 cur = clist_next(cur)) {
2750 struct mail_search_key * key_elt;
2751 struct mailimap_search_key * imap_key_elt;
2752
2753 key_elt = clist_content(cur);
2754 r = mail_search_to_imap_search(key_elt, &imap_key_elt);
2755 if (r != MAIL_NO_ERROR) {
2756 res = r;
2757 goto free_list;
2758 }
2759
2760 r = clist_append(multiple, imap_key_elt);
2761 if (r != 0) {
2762 mailimap_search_key_free(imap_key_elt);
2763 res = MAIL_ERROR_MEMORY;
2764 goto free_list;
2765 }
2766 }
2767 break;
2768
2769 free_list:
2770 clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL);
2771 clist_free(multiple);
2772 goto err;
2773
2774 default:
2775 return MAIL_ERROR_INVAL;
2776 }
2777
2778 imap_key = mailimap_search_key_new(type, bcc, before, body, cc, from,
2779 NULL, on, since, subject, text,
2780 to, NULL, header_name,
2781 header_value, larger, not, or1, or2,
2782 NULL, NULL, NULL, smaller, NULL,
2783 NULL, multiple);
2784 if (imap_key == NULL) {
2785 res = MAIL_ERROR_MEMORY;
2786 goto free;
2787 }
2788
2789 * result = imap_key;
2790
2791 return MAIL_NO_ERROR;
2792
2793 free:
2794 if (bcc != NULL)
2795 free(bcc);
2796 if (before != NULL)
2797 mailimap_date_free(before);
2798 if (body != NULL)
2799 free(body);
2800 if (cc != NULL)
2801 free(cc);
2802 if (from != NULL)
2803 free(from);
2804 if (on != NULL)
2805 mailimap_date_free(on);
2806 if (since != NULL)
2807 mailimap_date_free(since);
2808 if (subject != NULL)
2809 free(subject);
2810 if (text != NULL)
2811 free(text);
2812 if (to != NULL)
2813 free(to);
2814 if (header_name != NULL)
2815 free(header_name);
2816 if (header_value != NULL)
2817 free(header_value);
2818 if (not != NULL)
2819 mailimap_search_key_free(not);
2820 if (or1 != NULL)
2821 mailimap_search_key_free(or1);
2822 if (or2 != NULL)
2823 mailimap_search_key_free(or2);
2824 clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL);
2825 clist_free(multiple);
2826 err:
2827 return res;
2828}
2829#endif
2830
2831
2832int msg_list_to_imap_set(clist * msg_list,
2833 struct mailimap_set ** result)
2834{
2835 struct mailimap_set * imap_set;
2836 clistiter * cur;
2837 int previous_valid;
2838 uint32_t first_seq;
2839 uint32_t previous;
2840 int r;
2841 int res;
2842
2843 imap_set = mailimap_set_new_empty();
2844 if (imap_set == NULL) {
2845 res = MAIL_ERROR_MEMORY;
2846 goto err;
2847 }
2848
2849 cur = clist_begin(msg_list);
2850 previous_valid = FALSE;
2851 first_seq = 0;
2852 previous = 0;
2853 while (1) {
2854 uint32_t * pindex;
2855
2856 if ((cur == NULL) && (previous_valid)) {
2857 if (first_seq == previous) {
2858 r = mailimap_set_add_single(imap_set, first_seq);
2859 if (r != MAILIMAP_NO_ERROR) {
2860 res = r;
2861 goto free;
2862 }
2863 }
2864 else {
2865 r = mailimap_set_add_interval(imap_set, first_seq, previous);
2866 if (r != MAILIMAP_NO_ERROR) {
2867 res = r;
2868 goto free;
2869 }
2870 }
2871 break;
2872 }
2873
2874 pindex = clist_content(cur);
2875
2876 if (!previous_valid) {
2877 first_seq = * pindex;
2878 previous_valid = TRUE;
2879 previous = * pindex;
2880 cur = clist_next(cur);
2881 }
2882 else {
2883 if (* pindex != previous + 1) {
2884 if (first_seq == previous) {
2885 r = mailimap_set_add_single(imap_set, first_seq);
2886 if (r != MAILIMAP_NO_ERROR) {
2887 res = r;
2888 goto free;
2889 }
2890 }
2891 else {
2892 r = mailimap_set_add_interval(imap_set, first_seq, previous);
2893 if (r != MAILIMAP_NO_ERROR) {
2894 res = r;
2895 goto free;
2896 }
2897 }
2898 previous_valid = FALSE;
2899 }
2900 else {
2901 previous = * pindex;
2902 cur = clist_next(cur);
2903 }
2904 }
2905 }
2906
2907 * result = imap_set;
2908
2909 return MAIL_NO_ERROR;
2910
2911 free:
2912 mailimap_set_free(imap_set);
2913 err:
2914 return res;
2915}
2916
2917
2918static int
2919uid_list_to_env_list(clist * fetch_result,
2920 struct mailmessage_list ** result,
2921 mailsession * session, mailmessage_driver * driver)
2922{
2923 clistiter * cur;
2924 struct mailmessage_list * env_list;
2925 int r;
2926 int res;
2927 carray * tab;
2928 unsigned int i;
2929 mailmessage * msg;
2930
2931 tab = carray_new(128);
2932 if (tab == NULL) {
2933 res = MAIL_ERROR_MEMORY;
2934 goto err;
2935 }
2936
2937 for(cur = clist_begin(fetch_result) ; cur != NULL ;
2938 cur = clist_next(cur)) {
2939 struct mailimap_msg_att * msg_att;
2940 clistiter * item_cur;
2941 uint32_t uid;
2942 size_t size;
2943
2944 msg_att = clist_content(cur);
2945
2946 uid = 0;
2947 size = 0;
2948 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
2949 item_cur = clist_next(item_cur)) {
2950 struct mailimap_msg_att_item * item;
2951
2952 item = clist_content(item_cur);
2953
2954 switch (item->att_type) {
2955 case MAILIMAP_MSG_ATT_ITEM_STATIC:
2956 switch (item->att_data.att_static->att_type) {
2957 case MAILIMAP_MSG_ATT_UID:
2958 uid = item->att_data.att_static->att_data.att_uid;
2959 break;
2960
2961 case MAILIMAP_MSG_ATT_RFC822_SIZE:
2962 size = item->att_data.att_static->att_data.att_rfc822_size;
2963 break;
2964 }
2965 break;
2966 }
2967 }
2968
2969 msg = mailmessage_new();
2970 if (msg == NULL) {
2971 res = MAIL_ERROR_MEMORY;
2972 goto free_list;
2973 }
2974
2975 r = mailmessage_init(msg, session, driver, uid, size);
2976 if (r != MAIL_NO_ERROR) {
2977 res = r;
2978 goto free_msg;
2979 }
2980
2981 r = carray_add(tab, msg, NULL);
2982 if (r < 0) {
2983 res = MAIL_ERROR_MEMORY;
2984 goto free_msg;
2985 }
2986 }
2987
2988 env_list = mailmessage_list_new(tab);
2989 if (env_list == NULL) {
2990 res = MAIL_ERROR_MEMORY;
2991 goto free_list;
2992 }
2993
2994 * result = env_list;
2995
2996 return MAIL_NO_ERROR;
2997
2998 free_msg:
2999 mailmessage_free(msg);
3000 free_list:
3001 for(i = 0 ; i < carray_count(tab) ; i++)
3002 mailmessage_free(carray_get(tab, i));
3003 err:
3004 return res;
3005}
3006
3007
3008/*
3009 MAILIMAP_FLAG_FETCH_RECENT,
3010 MAILIMAP_FLAG_FETCH_OTHER
3011
3012 MAILIMAP_FLAG_ANSWERED,
3013 MAILIMAP_FLAG_FLAGGED,
3014 MAILIMAP_FLAG_DELETED,
3015 MAILIMAP_FLAG_SEEN,
3016 MAILIMAP_FLAG_DRAFT,
3017 MAILIMAP_FLAG_KEYWORD,
3018 MAILIMAP_FLAG_EXTENSION
3019*/
3020
3021static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn,
3022 struct mail_flags ** result)
3023{
3024 struct mail_flags * flags;
3025 clist * flag_list;
3026 clistiter * cur;
3027
3028 flags = mail_flags_new_empty();
3029 if (flags == NULL)
3030 goto err;
3031 flags->fl_flags = 0;
3032
3033 flag_list = att_dyn->att_list;
3034 if (flag_list != NULL) {
3035 for(cur = clist_begin(flag_list) ; cur != NULL ;
3036 cur = clist_next(cur)) {
3037 struct mailimap_flag_fetch * flag_fetch;
3038
3039 flag_fetch = clist_content(cur);
3040 if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT)
3041 flags->fl_flags |= MAIL_FLAG_NEW;
3042 else {
3043 char * keyword;
3044 int r;
3045
3046 switch (flag_fetch->fl_flag->fl_type) {
3047 case MAILIMAP_FLAG_ANSWERED:
3048 flags->fl_flags |= MAIL_FLAG_ANSWERED;
3049 break;
3050 case MAILIMAP_FLAG_FLAGGED:
3051 flags->fl_flags |= MAIL_FLAG_FLAGGED;
3052 break;
3053 case MAILIMAP_FLAG_DELETED:
3054 flags->fl_flags |= MAIL_FLAG_DELETED;
3055 break;
3056 case MAILIMAP_FLAG_SEEN:
3057 flags->fl_flags |= MAIL_FLAG_SEEN;
3058 break;
3059 case MAILIMAP_FLAG_DRAFT:
3060 keyword = strdup("Draft");
3061 if (keyword == NULL)
3062 goto free;
3063 r = clist_append(flags->fl_extension, keyword);
3064 if (r < 0) {
3065 free(keyword);
3066 goto free;
3067 }
3068 break;
3069 case MAILIMAP_FLAG_KEYWORD:
3070 if (strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword,
3071 "$Forwarded") == 0) {
3072 flags->fl_flags |= MAIL_FLAG_FORWARDED;
3073 }
3074 else {
3075 keyword = strdup(flag_fetch->fl_flag->fl_data.fl_keyword);
3076 if (keyword == NULL)
3077 goto free;
3078 r = clist_append(flags->fl_extension, keyword);
3079 if (r < 0) {
3080 free(keyword);
3081 goto free;
3082 }
3083 }
3084 break;
3085 case MAILIMAP_FLAG_EXTENSION:
3086 /* do nothing */
3087 break;
3088 }
3089 }
3090 }
3091 /*
3092 MAIL_FLAG_NEW was set for \Recent messages.
3093 Correct this flag for \Seen messages by unsetting it.
3094 */
3095 if ((flags->fl_flags & MAIL_FLAG_SEEN) && (flags->fl_flags & MAIL_FLAG_NEW)) {
3096 flags->fl_flags &= ~MAIL_FLAG_NEW;
3097 }
3098 }
3099
3100 * result = flags;
3101
3102 return MAIL_NO_ERROR;
3103
3104 free:
3105 mail_flags_free(flags);
3106 err:
3107 return MAIL_ERROR_MEMORY;
3108}
3109
3110int imap_flags_to_imap_flags(struct mail_flags * flags,
3111 struct mailimap_flag_list ** result)
3112{
3113 struct mailimap_flag * flag;
3114 struct mailimap_flag_list * flag_list;
3115 int res;
3116 clistiter * cur;
3117 int r;
3118
3119 flag_list = mailimap_flag_list_new_empty();
3120 if (flag_list == NULL) {
3121 res = MAIL_ERROR_MEMORY;
3122 goto err;
3123 }
3124
3125 if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0) {
3126 flag = mailimap_flag_new_deleted();
3127 if (flag == NULL) {
3128 res = MAIL_ERROR_MEMORY;
3129 goto free_flag_list;
3130 }
3131 r = mailimap_flag_list_add(flag_list, flag);
3132 if (r != MAILIMAP_NO_ERROR) {
3133 mailimap_flag_free(flag);
3134 res = MAIL_ERROR_MEMORY;
3135 goto free_flag_list;
3136 }
3137 }
3138
3139 if ((flags->fl_flags & MAIL_FLAG_FLAGGED) != 0) {
3140 flag = mailimap_flag_new_flagged();
3141 if (flag == NULL) {
3142 res = MAIL_ERROR_MEMORY;
3143 goto free_flag_list;
3144 }
3145 r = mailimap_flag_list_add(flag_list, flag);
3146 if (r != MAILIMAP_NO_ERROR) {
3147 mailimap_flag_free(flag);
3148 res = MAIL_ERROR_MEMORY;
3149 goto free_flag_list;
3150 }
3151 }
3152
3153 if ((flags->fl_flags & MAIL_FLAG_SEEN) != 0) {
3154 flag = mailimap_flag_new_seen();
3155 if (flag == NULL) {
3156 res = MAIL_ERROR_MEMORY;
3157 goto free_flag_list;
3158 }
3159 r = mailimap_flag_list_add(flag_list, flag);
3160 if (r != MAILIMAP_NO_ERROR) {
3161 res = MAIL_ERROR_MEMORY;
3162 goto free_flag_list;
3163 }
3164 }
3165
3166 if ((flags->fl_flags & MAIL_FLAG_ANSWERED) != 0) {
3167 flag = mailimap_flag_new_answered();
3168 if (flag == NULL) {
3169 res = MAIL_ERROR_MEMORY;
3170 goto free_flag_list;
3171 }
3172 r = mailimap_flag_list_add(flag_list, flag);
3173 if (r != MAILIMAP_NO_ERROR) {
3174 mailimap_flag_free(flag);
3175 res = MAIL_ERROR_MEMORY;
3176 goto free_flag_list;
3177 }
3178 }
3179
3180 if ((flags->fl_flags & MAIL_FLAG_FORWARDED) != 0) {
3181 char * flag_str;
3182
3183 flag_str = strdup("$Forwarded");
3184 if (flag_str == NULL) {
3185 res = MAIL_ERROR_MEMORY;
3186 goto free_flag_list;
3187 }
3188 flag = mailimap_flag_new_flag_keyword(flag_str);
3189 if (flag == NULL) {
3190 free(flag_str);
3191 res = MAIL_ERROR_MEMORY;
3192 goto free_flag_list;
3193 }
3194 r = mailimap_flag_list_add(flag_list, flag);
3195 if (r != MAILIMAP_NO_ERROR) {
3196 mailimap_flag_free(flag);
3197 res = MAIL_ERROR_MEMORY;
3198 goto free_flag_list;
3199 }
3200 }
3201
3202 for(cur = clist_begin(flags->fl_extension) ; cur != NULL ;
3203 cur = clist_next(cur)) {
3204 char * flag_str;
3205
3206 flag_str = clist_content(cur);
3207
3208 if (strcasecmp(flag_str, "Draft") == 0) {
3209 flag = mailimap_flag_new_draft();
3210 if (flag == NULL) {
3211 res = MAIL_ERROR_MEMORY;
3212 goto free_flag_list;
3213 }
3214 r = mailimap_flag_list_add(flag_list, flag);
3215 if (r != MAILIMAP_NO_ERROR) {
3216 mailimap_flag_free(flag);
3217 res = MAIL_ERROR_MEMORY;
3218 goto free_flag_list;
3219 }
3220 }
3221 else {
3222 flag_str = strdup(flag_str);
3223 if (flag_str == NULL) {
3224 res = MAIL_ERROR_MEMORY;
3225 goto free_flag_list;
3226 }
3227 flag = mailimap_flag_new_flag_keyword(flag_str);
3228 if (flag == NULL) {
3229 free(flag_str);
3230 res = MAIL_ERROR_MEMORY;
3231 goto free_flag_list;
3232 }
3233 r = mailimap_flag_list_add(flag_list, flag);
3234 if (r != MAILIMAP_NO_ERROR) {
3235 mailimap_flag_free(flag);
3236 res = MAIL_ERROR_MEMORY;
3237 goto free_flag_list;
3238 }
3239 }
3240 }
3241
3242 * result = flag_list;
3243
3244 return MAIL_NO_ERROR;
3245
3246 free_flag_list:
3247 mailimap_flag_list_free(flag_list);
3248 err:
3249 return res;
3250}
3251
3252static int flags_to_imap_flags(struct mail_flags * flags,
3253 struct mailimap_store_att_flags ** result)
3254{
3255 struct mailimap_flag_list * flag_list;
3256 struct mailimap_store_att_flags * att_flags;
3257 int res;
3258 int r;
3259
3260 r = imap_flags_to_imap_flags(flags,
3261 &flag_list);
3262 if (r != MAIL_NO_ERROR) {
3263 res = r;
3264 goto err;
3265 }
3266
3267 att_flags = mailimap_store_att_flags_new_set_flags_silent(flag_list);
3268 if (att_flags == NULL) {
3269 res = MAIL_ERROR_MEMORY;
3270 goto free_flag_list;
3271 }
3272
3273 * result = att_flags;
3274
3275 return MAIL_NO_ERROR;
3276
3277 free_flag_list:
3278 mailimap_flag_list_free(flag_list);
3279 err:
3280 return res;
3281}
3282
3283
3284static int
3285imap_fetch_result_to_flags(clist * fetch_result, uint32_t index,
3286 struct mail_flags ** result)
3287{
3288 clistiter * cur;
3289 int r;
3290
3291 for(cur = clist_begin(fetch_result) ; cur != NULL ;
3292 cur = clist_next(cur)) {
3293 struct mailimap_msg_att * msg_att;
3294 clistiter * item_cur;
3295 uint32_t uid;
3296 struct mailimap_msg_att_dynamic * att_dyn;
3297
3298 msg_att = clist_content(cur);
3299
3300 uid = 0;
3301 att_dyn = NULL;
3302
3303 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
3304 item_cur = clist_next(item_cur)) {
3305 struct mailimap_msg_att_item * item;
3306
3307 item = clist_content(item_cur);
3308
3309 if (item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
3310 switch (item->att_data.att_static->att_type) {
3311 case MAILIMAP_MSG_ATT_UID:
3312 uid = item->att_data.att_static->att_data.att_uid;
3313 break;
3314 }
3315 }
3316 else if (item->att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC) {
3317 if (att_dyn == NULL) {
3318 att_dyn = item->att_data.att_dyn;
3319 }
3320 }
3321 }
3322
3323 if (uid != 0) {
3324 if (uid == index) {
3325 struct mail_flags * flags;
3326
3327 if (att_dyn != NULL) {
3328 r = imap_flags_to_flags(att_dyn, &flags);
3329
3330 if (r == MAIL_NO_ERROR) {
3331 * result = flags;
3332 return MAIL_NO_ERROR;
3333 }
3334 }
3335 }
3336 }
3337 }
3338
3339 return MAIL_ERROR_MSG_NOT_FOUND;
3340}
3341
3342
3343int imap_fetch_flags(mailimap * imap,
3344 uint32_t index, struct mail_flags ** result)
3345{
3346 struct mailimap_fetch_att * fetch_att;
3347 struct mailimap_fetch_type * fetch_type;
3348 struct mailimap_set * set;
3349 int r;
3350 int res;
3351 clist * fetch_result;
3352 struct mail_flags * flags;
3353
3354 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
3355 if (fetch_type == NULL) {
3356 res = MAIL_ERROR_MEMORY;
3357 goto err;
3358 }
3359
3360 fetch_att = mailimap_fetch_att_new_uid();
3361 if (fetch_att == NULL) {
3362 res = MAIL_ERROR_MEMORY;
3363 goto free_fetch_type;
3364 }
3365
3366 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3367 if (r != MAILIMAP_NO_ERROR) {
3368 mailimap_fetch_att_free(fetch_att);
3369 res = MAIL_ERROR_MEMORY;
3370 goto free_fetch_type;
3371 }
3372
3373 fetch_att = mailimap_fetch_att_new_flags();
3374 if (fetch_att == NULL) {
3375 res = MAIL_ERROR_MEMORY;
3376 goto free_fetch_type;
3377 }
3378
3379 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3380 if (r != MAILIMAP_NO_ERROR) {
3381 mailimap_fetch_att_free(fetch_att);
3382 res = MAIL_ERROR_MEMORY;
3383 goto free_fetch_type;
3384 }
3385
3386 set = mailimap_set_new_single(index);
3387 if (set == NULL) {
3388 res = MAIL_ERROR_MEMORY;
3389 goto free_fetch_type;
3390 }
3391
3392 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
3393
3394 mailimap_fetch_type_free(fetch_type);
3395 mailimap_set_free(set);
3396
3397 switch (r) {
3398 case MAILIMAP_NO_ERROR:
3399 break;
3400 default:
3401 return imap_error_to_mail_error(r);
3402 }
3403
3404 r = imap_fetch_result_to_flags(fetch_result, index, &flags);
3405 mailimap_fetch_list_free(fetch_result);
3406
3407 if (r != MAIL_NO_ERROR) {
3408 res = r;
3409 goto err;
3410 }
3411
3412 * result = flags;
3413
3414 return MAIL_NO_ERROR;
3415
3416 free_fetch_type:
3417 mailimap_fetch_type_free(fetch_type);
3418 err:
3419 return res;
3420}
3421
3422int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last,
3423 struct mail_flags * flags)
3424{
3425 struct mailimap_store_att_flags * att_flags;
3426 struct mailimap_set * set;
3427 int r;
3428 int res;
3429
3430 set = mailimap_set_new_interval(first, last);
3431 if (set == NULL) {
3432 res = MAIL_ERROR_MEMORY;
3433 goto err;
3434 }
3435
3436 r = flags_to_imap_flags(flags, &att_flags);
3437 if (r != MAIL_NO_ERROR) {
3438 res = r;
3439 goto free_set;
3440 }
3441
3442 r = mailimap_uid_store(imap, set, att_flags);
3443 if (r != MAILIMAP_NO_ERROR) {
3444 res = imap_error_to_mail_error(r);
3445 goto free_flag;
3446 }
3447
3448 mailimap_store_att_flags_free(att_flags);
3449 mailimap_set_free(set);
3450
3451 return MAIL_NO_ERROR;
3452
3453 free_flag:
3454 mailimap_store_att_flags_free(att_flags);
3455 free_set:
3456 mailimap_set_free(set);
3457 err:
3458 return res;
3459}
3460
3461
3462
3463
3464int imap_get_messages_list(mailimap * imap,
3465 mailsession * session, mailmessage_driver * driver,
3466 uint32_t first_index,
3467 struct mailmessage_list ** result)
3468{
3469 struct mailmessage_list * env_list;
3470 int r;
3471 struct mailimap_fetch_att * fetch_att;
3472 struct mailimap_fetch_type * fetch_type;
3473 struct mailimap_set * set;
3474 clist * fetch_result;
3475 int res;
3476
3477 set = mailimap_set_new_interval(first_index, 0);
3478 if (set == NULL) {
3479 res = MAIL_ERROR_MEMORY;
3480 goto err;
3481 }
3482
3483 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
3484 if (fetch_type == NULL) {
3485 res = MAIL_ERROR_MEMORY;
3486 goto free_set;
3487 }
3488
3489 fetch_att = mailimap_fetch_att_new_uid();
3490 if (fetch_att == NULL) {
3491 res = MAIL_ERROR_MEMORY;
3492 goto free_fetch_type;
3493 }
3494
3495 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3496 if (r != MAILIMAP_NO_ERROR) {
3497 mailimap_fetch_att_free(fetch_att);
3498 res = MAIL_ERROR_MEMORY;
3499 goto free_fetch_type;
3500 }
3501
3502 fetch_att = mailimap_fetch_att_new_rfc822_size();
3503 if (fetch_att == NULL) {
3504 res = MAIL_ERROR_MEMORY;
3505 goto free_fetch_type;
3506 }
3507
3508 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3509 if (r != MAILIMAP_NO_ERROR) {
3510 mailimap_fetch_att_free(fetch_att);
3511 res = MAIL_ERROR_MEMORY;
3512 goto free_fetch_type;
3513 }
3514
3515 r = mailimap_uid_fetch(imap, set,
3516 fetch_type, &fetch_result);
3517
3518 mailimap_fetch_type_free(fetch_type);
3519 mailimap_set_free(set);
3520
3521 if (r != MAILIMAP_NO_ERROR) {
3522 res = imap_error_to_mail_error(r);
3523 goto err;
3524 }
3525
3526 r = uid_list_to_env_list(fetch_result, &env_list, session, driver);
3527 mailimap_fetch_list_free(fetch_result);
3528
3529 * result = env_list;
3530
3531 return MAIL_NO_ERROR;
3532
3533 free_fetch_type:
3534 mailimap_fetch_type_free(fetch_type);
3535 free_set:
3536 mailimap_set_free(set);
3537 err:
3538 return res;
3539}
3540
3541static void generate_key_from_message(char * key, size_t size,
3542 mailmessage * msg_info,
3543 int type)
3544{
3545 switch (type) {
3546 case MAILIMAP_MSG_ATT_RFC822:
3547 snprintf(key, size, "%s-rfc822", msg_info->msg_uid);
3548 break;
3549 case MAILIMAP_MSG_ATT_RFC822_HEADER:
3550 snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid);
3551 break;
3552 case MAILIMAP_MSG_ATT_RFC822_TEXT:
3553 snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid);
3554 break;
3555 case MAILIMAP_MSG_ATT_ENVELOPE:
3556 snprintf(key, size, "%s-envelope", msg_info->msg_uid);
3557 break;
3558 }
3559}
3560
3561int
3562imapdriver_get_cached_envelope(struct mail_cache_db * cache_db,
3563 MMAPString * mmapstr,
3564 mailsession * session, mailmessage * msg,
3565 struct mailimf_fields ** result)
3566{
3567#if 0
3568 mailsession * imap_session;
3569#endif
3570 mailimap * imap;
3571 int r;
3572 struct mailimf_fields * fields;
3573 int res;
3574 char keyname[PATH_MAX];
3575
3576#if 0
3577 imap_session = cached_session_get_ancestor(session);
3578 imap = ((struct imap_session_state_data *) (imap_session->data))->session;
3579#endif
3580 imap = cached_session_get_imap_session(session);
3581
3582 generate_key_from_message(keyname, PATH_MAX,
3583 msg, MAILIMAP_MSG_ATT_ENVELOPE);
3584
3585 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
3586 if (r != MAIL_NO_ERROR) {
3587 res = r;
3588 goto err;
3589 }
3590
3591 * result = fields;
3592
3593 return MAIL_NO_ERROR;
3594
3595err:
3596 return res;
3597}
3598
3599int
3600imapdriver_write_cached_envelope(struct mail_cache_db * cache_db,
3601 MMAPString * mmapstr,
3602 mailsession * session, mailmessage * msg,
3603 struct mailimf_fields * fields)
3604{
3605 char keyname[PATH_MAX];
3606 int r;
3607 int res;
3608
3609 generate_key_from_message(keyname, PATH_MAX,
3610 msg, MAILIMAP_MSG_ATT_ENVELOPE);
3611
3612 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
3613 if (r != MAIL_NO_ERROR) {
3614 res = r;
3615 goto err;
3616 }
3617
3618 return MAIL_NO_ERROR;
3619
3620err:
3621 return res;
3622}
3623
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_TOOLS_H
37
38#define IMAPDRIVER_TOOLS_H
39
40#include "mailimap.h"
41#include "mailmime.h"
42#include "imapdriver_types.h"
43#include "mail_cache_db.h"
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
49int imap_list_to_list(clist * imap_list, struct mail_list ** result);
50
51int
52section_to_imap_section(struct mailmime_section * section, int type,
53 struct mailimap_section ** result);
54
55int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
56 uint32_t * puid,
57 struct mailimap_envelope ** pimap_envelope,
58 char ** preferences,
59 size_t * pref_size,
60 struct mailimap_msg_att_dynamic ** patt_dyn,
61 struct mailimap_body ** pimap_body);
62
63int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type);
64
65int imap_env_to_fields(struct mailimap_envelope * env,
66 char * ref_str, size_t ref_size,
67 struct mailimf_fields ** result);
68
69int
70imap_fetch_result_to_envelop_list(clist * fetch_result,
71 struct mailmessage_list * env_list);
72
73int imap_body_to_body(struct mailimap_body * imap_body,
74 struct mailmime ** result);
75
76#if 0
77int mail_search_to_imap_search(struct mail_search_key * key,
78 struct mailimap_search_key ** result);
79#endif
80
81int msg_list_to_imap_set(clist * msg_list,
82 struct mailimap_set ** result);
83
84int imap_error_to_mail_error(int error);
85
86int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last,
87 struct mail_flags * flags);
88
89int imap_fetch_flags(mailimap * imap,
90 uint32_t index, struct mail_flags ** result);
91
92int imap_get_messages_list(mailimap * imap,
93 mailsession * session, mailmessage_driver * driver,
94 uint32_t first_index,
95 struct mailmessage_list ** result);
96
97int
98imapdriver_get_cached_envelope(struct mail_cache_db * cache_db,
99 MMAPString * mmapstr,
100 mailsession * session, mailmessage * msg,
101 struct mailimf_fields ** result);
102
103int
104imapdriver_write_cached_envelope(struct mail_cache_db * cache_db,
105 MMAPString * mmapstr,
106 mailsession * session, mailmessage * msg,
107 struct mailimf_fields * fields);
108
109int imap_flags_to_imap_flags(struct mail_flags * flags,
110 struct mailimap_flag_list ** result);
111
112#ifdef __cplusplus
113}
114#endif
115
116#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_TYPES_H
37
38#define IMAPDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/mailimap.h>
43#include <libetpan/maildriver_types.h>
44#include <libetpan/generic_cache_types.h>
45#include <libetpan/mailstorage_types.h>
46
47#ifdef __cplusplus
48extern "C" {
49#endif
50
51/* IMAP driver for session */
52
53struct imap_session_state_data {
54 mailimap * imap_session;
55 char * imap_mailbox;
56 struct mail_flags_store * imap_flags_store;
57};
58
59enum {
60 IMAP_SECTION_MESSAGE,
61 IMAP_SECTION_HEADER,
62 IMAP_SECTION_MIME,
63 IMAP_SECTION_BODY
64};
65
66/* cached IMAP driver for session */
67
68enum {
69 IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
70};
71
72struct imap_cached_session_state_data {
73 mailsession * imap_ancestor;
74 char * imap_quoted_mb;
75 char imap_cache_directory[PATH_MAX];
76 carray * imap_uid_list;
77};
78
79
80/* IMAP storage */
81
82/*
83 imap_mailstorage is the state data specific to the IMAP4rev1 storage.
84
85 - servername this is the name of the IMAP4rev1 server
86
87 - port is the port to connect to, on the server.
88 you give 0 to use the default port.
89
90 - command, if non-NULL the command used to connect to the
91 server instead of allowing normal TCP connections to be used.
92
93 - connection_type is the type of socket layer to use.
94 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
95 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS or
96 CONNECTION_TYPE_COMMAND.
97
98 - auth_type is the authenticate mechanism to use.
99 The value can be IMAP_AUTH_TYPE_PLAIN.
100 Other values are not yet implemented.
101
102 - login is the login of the IMAP4rev1 account.
103
104 - password is the password of the IMAP4rev1 account.
105
106 - cached if this value is != 0, a persistant cache will be
107 stored on local system.
108
109 - cache_directory is the location of the cache
110*/
111
112struct imap_mailstorage {
113 char * imap_servername;
114 uint16_t imap_port;
115 char * imap_command;
116 int imap_connection_type;
117
118 int imap_auth_type;
119 char * imap_login;
120 char * imap_password;
121
122 int imap_cached;
123 char * imap_cache_directory;
124};
125
126/* this is the type of IMAP4rev1 authentication */
127
128enum {
129 IMAP_AUTH_TYPE_PLAIN, /* plain text authentication */
130 IMAP_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */
131 IMAP_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */
132 IMAP_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */
133 IMAP_AUTH_TYPE_SASL_PLAIN, /* SASL plain */
134 IMAP_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */
135 IMAP_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */
136 IMAP_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */
137};
138
139
140#ifdef __cplusplus
141}
142#endif
143
144#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapstorage.h"
37
38#include <stdlib.h>
39#include <string.h>
40
41#include "mail.h"
42#include "imapdriver.h"
43#include "imapdriver_cached.h"
44#include "mailstorage_tools.h"
45#include "maildriver.h"
46
47/* imap storage */
48
49#define IMAP_DEFAULT_PORT 143
50#define IMAPS_DEFAULT_PORT 993
51
52static int imap_mailstorage_connect(struct mailstorage * storage);
53static int
54imap_mailstorage_get_folder_session(struct mailstorage * storage,
55 char * pathname, mailsession ** result);
56static void imap_mailstorage_uninitialize(struct mailstorage * storage);
57
58static mailstorage_driver imap_mailstorage_driver = {
59 .sto_name = "imap",
60 .sto_connect = imap_mailstorage_connect,
61 .sto_get_folder_session = imap_mailstorage_get_folder_session,
62 .sto_uninitialize = imap_mailstorage_uninitialize,
63};
64
65int imap_mailstorage_init(struct mailstorage * storage,
66 char * imap_servername, uint16_t imap_port,
67 char * imap_command,
68 int imap_connection_type, int imap_auth_type,
69 char * imap_login, char * imap_password,
70 int imap_cached, char * imap_cache_directory)
71{
72 struct imap_mailstorage * imap_storage;
73
74 imap_storage = malloc(sizeof(* imap_storage));
75 if (imap_storage == NULL)
76 goto err;
77
78 imap_storage->imap_servername = strdup(imap_servername);
79 if (imap_storage->imap_servername == NULL)
80 goto free;
81
82 imap_storage->imap_connection_type = imap_connection_type;
83
84 if (imap_port == 0) {
85 switch (imap_connection_type) {
86 case CONNECTION_TYPE_PLAIN:
87 case CONNECTION_TYPE_TRY_STARTTLS:
88 case CONNECTION_TYPE_STARTTLS:
89 case CONNECTION_TYPE_COMMAND:
90 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
91 case CONNECTION_TYPE_COMMAND_STARTTLS:
92 imap_port = IMAP_DEFAULT_PORT;
93 break;
94
95 case CONNECTION_TYPE_TLS:
96 case CONNECTION_TYPE_COMMAND_TLS:
97 imap_port = IMAPS_DEFAULT_PORT;
98 break;
99 }
100 }
101
102 imap_storage->imap_port = imap_port;
103
104 if (imap_command != NULL) {
105 imap_storage->imap_command = strdup(imap_command);
106 if (imap_storage->imap_command == NULL)
107 goto free_servername;
108 }
109 else
110 imap_storage->imap_command = NULL;
111
112 imap_storage->imap_auth_type = imap_auth_type;
113
114 if (imap_login != NULL) {
115 imap_storage->imap_login = strdup(imap_login);
116 if (imap_storage->imap_login == NULL)
117 goto free_command;
118 }
119 else
120 imap_storage->imap_login = NULL;
121
122 if (imap_password != NULL) {
123 imap_storage->imap_password = strdup(imap_password);
124 if (imap_storage->imap_password == NULL)
125 goto free_login;
126 }
127 else
128 imap_storage->imap_password = NULL;
129
130 imap_storage->imap_cached = imap_cached;
131
132 if (imap_cached && (imap_cache_directory != NULL)) {
133 imap_storage->imap_cache_directory = strdup(imap_cache_directory);
134 if (imap_storage->imap_cache_directory == NULL)
135 goto free_password;
136 }
137 else {
138 imap_storage->imap_cached = FALSE;
139 imap_storage->imap_cache_directory = NULL;
140 }
141
142 storage->sto_data = imap_storage;
143 storage->sto_driver = &imap_mailstorage_driver;
144
145 return MAIL_NO_ERROR;
146
147 free_password:
148 free(imap_storage->imap_password);
149 free_login:
150 free(imap_storage->imap_login);
151 free_command:
152 free(imap_storage->imap_command);
153 free_servername:
154 free(imap_storage->imap_servername);
155 free:
156 free(imap_storage);
157 err:
158 return MAIL_ERROR_MEMORY;
159}
160
161static void imap_mailstorage_uninitialize(struct mailstorage * storage)
162{
163 struct imap_mailstorage * imap_storage;
164
165 imap_storage = storage->sto_data;
166
167 if (imap_storage->imap_cache_directory != NULL)
168 free(imap_storage->imap_cache_directory);
169 if (imap_storage->imap_password != NULL)
170 free(imap_storage->imap_password);
171 if (imap_storage->imap_login != NULL)
172 free(imap_storage->imap_login);
173 if (imap_storage->imap_command != NULL)
174 free(imap_storage->imap_command);
175 free(imap_storage->imap_servername);
176 free(imap_storage);
177
178 storage->sto_data = NULL;
179}
180
181static int imap_connect(struct mailstorage * storage,
182 mailsession ** result)
183{
184 struct imap_mailstorage * imap_storage;
185 mailsession_driver * driver;
186 int r;
187 int res;
188 mailsession * session;
189
190 imap_storage = storage->sto_data;
191
192 if (imap_storage->imap_cached)
193 driver = imap_cached_session_driver;
194 else
195 driver = imap_session_driver;
196
197 r = mailstorage_generic_connect(driver,
198 imap_storage->imap_servername,
199 imap_storage->imap_port,
200 imap_storage->imap_command,
201 imap_storage->imap_connection_type,
202 IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY,
203 imap_storage->imap_cache_directory,
204 0, NULL,
205 &session);
206 switch (r) {
207 case MAIL_NO_ERROR_NON_AUTHENTICATED:
208 case MAIL_NO_ERROR_AUTHENTICATED:
209 case MAIL_NO_ERROR:
210 break;
211 default:
212 res = r;
213 goto err;
214 }
215
216 r = mailstorage_generic_auth(session, r,
217 imap_storage->imap_connection_type,
218 imap_storage->imap_login,
219 imap_storage->imap_password);
220 if (r != MAIL_NO_ERROR) {
221 res = r;
222 goto free;
223 }
224
225 * result = session;
226
227 return MAIL_NO_ERROR;
228
229 free:
230 mailsession_free(session);
231 err:
232 return res;
233}
234
235static int imap_mailstorage_connect(struct mailstorage * storage)
236{
237 mailsession * session;
238 int r;
239 int res;
240
241 r = imap_connect(storage, &session);
242 if (r != MAIL_NO_ERROR) {
243 res = r;
244 goto err;
245 }
246
247 r = mailsession_select_folder(session, "INBOX");
248 if (r != MAIL_NO_ERROR) {
249 mailsession_logout(session);
250 res = r;
251 goto err;
252 }
253
254 storage->sto_session = session;
255 storage->sto_driver = &imap_mailstorage_driver;
256
257 return MAIL_NO_ERROR;
258
259 err:
260 return res;
261}
262
263static int
264imap_mailstorage_get_folder_session(struct mailstorage * storage,
265 char * pathname, mailsession ** result)
266{
267 mailsession * session;
268 int r;
269 int res;
270
271 if (strcasecmp(pathname, "INBOX") == 0) {
272 session = storage->sto_session;
273 }
274 else {
275 r = imap_connect(storage, &session);
276 if (r != MAIL_NO_ERROR) {
277 res = r;
278 goto err;
279 }
280
281 r = mailsession_select_folder(session, pathname);
282 if (r != MAIL_NO_ERROR) {
283 mailsession_logout(session);
284 res = r;
285 goto free;
286 }
287 }
288
289 * result = session;
290
291 return MAIL_NO_ERROR;
292
293 free:
294 mailsession_free(session);
295 err:
296 return res;
297}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPSTORAGE_H
37
38#define IMAPSTORAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/imapdriver_types.h>
45
46/*
47 imap_mailstorage_init is the constructor for a IMAP4rev1 storage
48
49 @param storage this is the storage to initialize.
50
51 @param servername this is the name of the IMAP4rev1 server
52
53 @param port is the port to connect to, on the server.
54 you give 0 to use the default port.
55
56 @param command the command used to connect to the server instead of
57 allowing normal TCP connections to be used.
58
59 @param connection_type is the type of socket layer to use.
60 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
61 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
62 CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
63 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
64
65 @param auth_type is the authenticate mechanism to use.
66 The value can be IMAP_AUTH_TYPE_PLAIN.
67 Other values are not yet implemented.
68
69 @param login is the login of the IMAP4rev1 account.
70
71 @param password is the password of the IMAP4rev1 account.
72
73 @param cached if this value is != 0, a persistant cache will be
74 stored on local system.
75
76 @param cache_directory is the location of the cache
77*/
78
79int imap_mailstorage_init(struct mailstorage * storage,
80 char * imap_servername, uint16_t imap_port,
81 char * imap_command,
82 int imap_connection_type, int imap_auth_type,
83 char * imap_login, char * imap_password,
84 int imap_cached, char * imap_cache_directory);
85
86#ifdef __cplusplus
87}
88#endif
89
90#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36
37/*
38 flags directory MUST be kept so that we can have other flags
39 than standards
40*/
41
42#include "maildirdriver.h"
43
44#include <stdio.h>
45#include <sys/types.h>
46#include <dirent.h>
47#include <unistd.h>
48#include <sys/stat.h>
49#include <ctype.h>
50#include <fcntl.h>
51#include <sys/mman.h>
52#include <stdlib.h>
53#include <string.h>
54
55#include "maildir.h"
56#include "maildriver_tools.h"
57#include "maildirdriver_message.h"
58#include "maildirdriver_tools.h"
59#include "mailmessage.h"
60#include "generic_cache.h"
61
62static int initialize(mailsession * session);
63
64static void uninitialize(mailsession * session);
65
66static int connect_path(mailsession * session, char * path);
67
68static int logout(mailsession * session);
69
70static int expunge_folder(mailsession * session);
71
72static int status_folder(mailsession * session, char * mb,
73 uint32_t * result_messages, uint32_t * result_recent,
74 uint32_t * result_unseen);
75
76static int recent_number(mailsession * session, char * mb,
77 uint32_t * result);
78
79static int unseen_number(mailsession * session, char * mb,
80 uint32_t * result);
81
82static int messages_number(mailsession * session, char * mb,
83 uint32_t * result);
84
85static int append_message(mailsession * session,
86 char * message, size_t size);
87
88static int append_message_flags(mailsession * session,
89 char * message, size_t size, struct mail_flags * flags);
90
91static int get_messages_list(mailsession * session,
92 struct mailmessage_list ** result);
93
94static int get_envelopes_list(mailsession * session,
95 struct mailmessage_list * env_list);
96
97static int check_folder(mailsession * session);
98
99static int get_message_by_uid(mailsession * session,
100 const char * uid, mailmessage ** result);
101
102static mailsession_driver local_maildir_session_driver = {
103 .sess_name = "maildir",
104
105 .sess_initialize = initialize,
106 .sess_uninitialize = uninitialize,
107
108 .sess_parameters = NULL,
109
110 .sess_connect_stream = NULL,
111 .sess_connect_path = connect_path,
112 .sess_starttls = NULL,
113 .sess_login = NULL,
114 .sess_logout = logout,
115 .sess_noop = NULL,
116
117 .sess_build_folder_name = NULL,
118 .sess_create_folder = NULL,
119 .sess_delete_folder = NULL,
120 .sess_rename_folder = NULL,
121 .sess_check_folder = check_folder,
122 .sess_examine_folder = NULL,
123 .sess_select_folder = NULL,
124 .sess_expunge_folder = expunge_folder,
125 .sess_status_folder = status_folder,
126 .sess_messages_number = messages_number,
127 .sess_recent_number = recent_number,
128 .sess_unseen_number = unseen_number,
129 .sess_list_folders = NULL,
130 .sess_lsub_folders = NULL,
131 .sess_subscribe_folder = NULL,
132 .sess_unsubscribe_folder = NULL,
133
134 .sess_append_message = append_message,
135 .sess_append_message_flags = append_message_flags,
136 .sess_copy_message = NULL,
137 .sess_move_message = NULL,
138
139 .sess_get_messages_list = get_messages_list,
140 .sess_get_envelopes_list = get_envelopes_list,
141 .sess_remove_message = NULL,
142#if 0
143 .sess_search_messages = maildriver_generic_search_messages,
144#endif
145
146 .sess_get_message = NULL,
147 .sess_get_message_by_uid = get_message_by_uid,
148};
149
150mailsession_driver * maildir_session_driver = &local_maildir_session_driver;
151
152
153static int flags_store_process(struct maildir * md,
154 struct mail_flags_store * flags_store);
155
156
157static inline struct maildir_session_state_data * get_data(mailsession * session)
158{
159 return session->sess_data;
160}
161
162static struct maildir * get_maildir_session(mailsession * session)
163{
164 return get_data(session)->md_session;
165}
166
167static int initialize(mailsession * session)
168{
169 struct maildir_session_state_data * data;
170
171 data = malloc(sizeof(* data));
172 if (data == NULL)
173 goto err;
174
175 data->md_session = NULL;
176
177 data->md_flags_store = mail_flags_store_new();
178 if (data->md_flags_store == NULL)
179 goto free;
180
181 session->sess_data = data;
182
183 return MAIL_NO_ERROR;
184
185 free:
186 free(data);
187 err:
188 return MAIL_ERROR_MEMORY;
189}
190
191static void uninitialize(mailsession * session)
192{
193 struct maildir_session_state_data * data;
194
195 data = get_data(session);
196
197 if (data->md_session != NULL)
198 flags_store_process(data->md_session, data->md_flags_store);
199
200 mail_flags_store_free(data->md_flags_store);
201 if (data->md_session != NULL)
202 maildir_free(data->md_session);
203
204 free(data);
205
206 session->sess_data = NULL;
207}
208
209
210static int connect_path(mailsession * session, char * path)
211{
212 struct maildir * md;
213 int res;
214 int r;
215
216 if (get_maildir_session(session) != NULL) {
217 res = MAIL_ERROR_BAD_STATE;
218 goto err;
219 }
220
221 md = maildir_new(path);
222 if (md == NULL) {
223 res = MAIL_ERROR_MEMORY;
224 goto err;
225 }
226
227 r = maildir_update(md);
228 if (r != MAILDIR_NO_ERROR) {
229 res = maildirdriver_maildir_error_to_mail_error(r);
230 goto free;
231 }
232
233 get_data(session)->md_session = md;
234
235 return MAIL_NO_ERROR;
236
237 free:
238 maildir_free(md);
239 err:
240 return res;
241}
242
243static int logout(mailsession * session)
244{
245 struct maildir * md;
246
247 check_folder(session);
248
249 md = get_maildir_session(session);
250 if (md == NULL)
251 return MAIL_ERROR_BAD_STATE;
252
253 maildir_free(md);
254 get_data(session)->md_session = NULL;
255
256 return MAIL_NO_ERROR;
257}
258
259/* folders operations */
260
261static int status_folder(mailsession * session, char * mb,
262 uint32_t * result_messages, uint32_t * result_recent,
263 uint32_t * result_unseen)
264{
265 int r;
266 struct maildir * md;
267 unsigned int i;
268 uint32_t messages;
269 uint32_t recent;
270 uint32_t unseen;
271
272 check_folder(session);
273
274 md = get_maildir_session(session);
275 if (md == NULL)
276 return MAIL_ERROR_BAD_STATE;
277
278 r = maildir_update(md);
279 if (r != MAILDIR_NO_ERROR)
280 return maildirdriver_maildir_error_to_mail_error(r);
281
282 messages = 0;
283 recent = 0;
284 unseen = 0;
285 for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i ++) {
286 struct maildir_msg * msg;
287
288 msg = carray_get(md->mdir_msg_list, i);
289 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
290 recent ++;
291 if ((msg->msg_flags & MAILDIR_FLAG_SEEN) == 0)
292 unseen ++;
293 messages ++;
294 }
295
296 * result_messages = messages;
297 * result_recent = recent;
298 * result_unseen = unseen;
299
300 return MAIL_NO_ERROR;
301}
302
303static int messages_number(mailsession * session, char * mb,
304 uint32_t * result)
305{
306 struct maildir * md;
307 int r;
308
309 md = get_maildir_session(session);
310 if (md == NULL)
311 return MAIL_ERROR_BAD_STATE;
312
313 r = maildir_update(md);
314 if (r != MAILDIR_NO_ERROR)
315 return maildirdriver_maildir_error_to_mail_error(r);
316
317 * result = carray_count(md->mdir_msg_list);
318
319 return MAIL_NO_ERROR;
320}
321
322static int unseen_number(mailsession * session, char * mb,
323 uint32_t * result)
324{
325 uint32_t messages;
326 uint32_t recent;
327 uint32_t unseen;
328 int r;
329
330 r = status_folder(session, mb, &messages, &recent, &unseen);
331 if (r != MAIL_NO_ERROR)
332 return r;
333
334 * result = unseen;
335
336 return MAIL_NO_ERROR;
337}
338
339static int recent_number(mailsession * session, char * mb,
340 uint32_t * result)
341{
342 uint32_t messages;
343 uint32_t recent;
344 uint32_t unseen;
345 int r;
346
347 r = status_folder(session, mb, &messages, &recent, &unseen);
348 if (r != MAIL_NO_ERROR)
349 return r;
350
351 * result = recent;
352
353 return MAIL_NO_ERROR;
354}
355
356
357/* messages operations */
358
359static int append_message(mailsession * session,
360 char * message, size_t size)
361{
362#if 0
363 struct maildir * md;
364 int r;
365
366 md = get_maildir_session(session);
367 if (md == NULL)
368 return MAIL_ERROR_BAD_STATE;
369
370 r = maildir_message_add(md, message, size);
371 if (r != MAILDIR_NO_ERROR)
372 return maildirdriver_maildir_error_to_mail_error(r);
373
374 return MAIL_NO_ERROR;
375#endif
376
377 return append_message_flags(session, message, size, NULL);
378}
379
380static int append_message_flags(mailsession * session,
381 char * message, size_t size, struct mail_flags * flags)
382{
383 struct maildir * md;
384 int r;
385 char uid[PATH_MAX];
386 struct maildir_msg * md_msg;
387 chashdatum key;
388 chashdatum value;
389 uint32_t md_flags;
390
391 md = get_maildir_session(session);
392 if (md == NULL)
393 return MAIL_ERROR_BAD_STATE;
394
395 r = maildir_message_add_uid(md, message, size,
396 uid, sizeof(uid));
397 if (r != MAILDIR_NO_ERROR)
398 return maildirdriver_maildir_error_to_mail_error(r);
399
400 if (flags == NULL)
401 goto exit;
402
403 key.data = uid;
404 key.len = strlen(uid);
405 r = chash_get(md->mdir_msg_hash, &key, &value);
406 if (r < 0)
407 goto exit;
408
409 md_msg = value.data;
410
411 md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags);
412
413 r = maildir_message_change_flags(md, uid, md_flags);
414 if (r != MAILDIR_NO_ERROR)
415 goto exit;
416
417 return MAIL_NO_ERROR;
418
419 exit:
420 return MAIL_NO_ERROR;
421}
422
423static int get_messages_list(mailsession * session,
424 struct mailmessage_list ** result)
425{
426 struct maildir * md;
427 int r;
428 struct mailmessage_list * env_list;
429 int res;
430
431 md = get_maildir_session(session);
432 if (md == NULL)
433 return MAIL_ERROR_BAD_STATE;
434
435 r = maildir_update(md);
436 if (r != MAILDIR_NO_ERROR) {
437 res = maildirdriver_maildir_error_to_mail_error(r);
438 goto err;
439 }
440
441 r = maildir_get_messages_list(session, md,
442 maildir_message_driver, &env_list);
443 if (r != MAILDIR_NO_ERROR) {
444 res = r;
445 goto free_list;
446 }
447
448 * result = env_list;
449
450 return MAIL_NO_ERROR;
451
452 free_list:
453 mailmessage_list_free(env_list);
454 err:
455 return res;
456}
457
458static int get_envelopes_list(mailsession * session,
459 struct mailmessage_list * env_list)
460{
461 int r;
462 struct maildir * md;
463 unsigned int i;
464 int res;
465
466 check_folder(session);
467
468 md = get_maildir_session(session);
469 if (md == NULL) {
470 res = MAIL_ERROR_BAD_STATE;
471 goto err;
472 }
473
474 r = maildir_update(md);
475 if (r != MAILDIR_NO_ERROR) {
476 res = maildirdriver_maildir_error_to_mail_error(r);
477 goto err;
478 }
479
480 r = maildriver_generic_get_envelopes_list(session, env_list);
481 if (r != MAIL_NO_ERROR) {
482 res = r;
483 goto err;
484 }
485
486 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) {
487 struct maildir_msg * md_msg;
488 mailmessage * msg;
489 uint32_t driver_flags;
490 clist * ext;
491 chashdatum key;
492 chashdatum value;
493
494 msg = carray_get(env_list->msg_tab, i);
495
496 key.data = msg->msg_uid;
497 key.len = strlen(msg->msg_uid);
498 r = chash_get(md->mdir_msg_hash, &key, &value);
499 if (r < 0)
500 continue;
501
502 md_msg = value.data;
503
504 driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags);
505
506 if (msg->msg_flags == NULL) {
507 ext = clist_new();
508 if (ext == NULL) {
509 res = MAIL_ERROR_MEMORY;
510 continue;
511 }
512
513 msg->msg_flags = mail_flags_new(driver_flags, ext);
514 if (msg->msg_flags == NULL) {
515 clist_free(ext);
516 res = MAIL_ERROR_MEMORY;
517 continue;
518 }
519
520 if ((md_msg->msg_flags & MAILDIR_FLAG_NEW) != 0) {
521 mail_flags_store_set(get_data(session)->md_flags_store, msg);
522 }
523 }
524 else {
525 msg->msg_flags->fl_flags &= MAIL_FLAG_FORWARDED;
526 msg->msg_flags->fl_flags |= driver_flags;
527 }
528 }
529
530 return MAIL_NO_ERROR;
531
532 err:
533 return res;
534}
535
536
537static int expunge_folder(mailsession * session)
538{
539 unsigned int i;
540 int r;
541 int res;
542 struct maildir * md;
543
544 check_folder(session);
545
546 md = get_maildir_session(session);
547 if (md == NULL)
548 return MAIL_ERROR_BAD_STATE;
549
550 r = maildir_update(md);
551 if (r != MAILDIR_NO_ERROR) {
552 res = maildirdriver_maildir_error_to_mail_error(r);
553 goto err;
554 }
555
556 for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) {
557 struct maildir_msg * md_msg;
558
559 md_msg = carray_get(md->mdir_msg_list, i);
560
561 if ((md_msg->msg_flags & MAILDIR_FLAG_TRASHED) != 0)
562 maildir_message_remove(md, md_msg->msg_uid);
563 }
564
565 return MAIL_NO_ERROR;
566
567 err:
568 return res;
569}
570
571
572static int flags_store_process(struct maildir * md,
573 struct mail_flags_store * flags_store)
574{
575 unsigned int i;
576
577 if (carray_count(flags_store->fls_tab) == 0)
578 return MAIL_NO_ERROR;
579
580 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
581 mailmessage * msg;
582 uint32_t md_flags;
583
584 msg = carray_get(flags_store->fls_tab, i);
585 md_flags = maildirdriver_flags_to_maildir_flags(msg->msg_flags->fl_flags);
586 md_flags &= ~MAILDIR_FLAG_NEW;
587
588 maildir_message_change_flags(md, msg->msg_uid, md_flags);
589 }
590
591 mail_flags_store_clear(flags_store);
592
593 return MAIL_NO_ERROR;
594}
595
596
597
598static int check_folder(mailsession * session)
599{
600 struct mail_flags_store * flags_store;
601 struct maildir_session_state_data * data;
602 struct maildir * md;
603
604 md = get_maildir_session(session);
605 if (md == NULL)
606 return MAIL_ERROR_BAD_STATE;
607
608 data = get_data(session);
609 flags_store = data->md_flags_store;
610
611 return flags_store_process(md, flags_store);
612}
613
614static int get_message_by_uid(mailsession * session,
615 const char * uid, mailmessage ** result)
616{
617 int r;
618 struct maildir * md;
619 int res;
620 mailmessage * msg;
621 char * msg_filename;
622 struct stat stat_info;
623
624 md = get_maildir_session(session);
625
626 /* update maildir data */
627
628 r = maildir_update(md);
629 if (r != MAILDIR_NO_ERROR) {
630 res = maildirdriver_maildir_error_to_mail_error(r);
631 goto err;
632 }
633
634 msg_filename = maildir_message_get(md, uid);
635 if (msg_filename == NULL) {
636 res = MAIL_ERROR_INVAL;
637 goto err;
638 }
639
640 r = stat(msg_filename, &stat_info);
641 free(msg_filename);
642 if (r < 0) {
643 res = MAIL_ERROR_INVAL;
644 goto err;
645 }
646
647 /* create message */
648
649 msg = mailmessage_new();
650 if (msg == NULL) {
651 res = MAIL_ERROR_MEMORY;
652 goto err;
653 }
654
655 r = mailmessage_init(msg, session, maildir_message_driver,
656 0, stat_info.st_size);
657 if (r != MAIL_NO_ERROR) {
658 mailmessage_free(msg);
659 res = r;
660 goto err;
661 }
662
663 msg->msg_uid = strdup(uid);
664 if (msg->msg_uid == NULL) {
665 mailmessage_free(msg);
666 res = r;
667 goto err;
668 }
669
670 * result = msg;
671
672 return MAIL_NO_ERROR;
673
674 err:
675 return res;
676}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_H
37
38#define MAILDIRDRIVER_H
39
40#include <libetpan/maildriver.h>
41#include <libetpan/maildirdriver_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47extern mailsession_driver * maildir_session_driver;
48
49#ifdef __cplusplus
50}
51#endif
52
53#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildirdriver.h"
37
38#include <stdio.h>
39#include <sys/types.h>
40#include <dirent.h>
41#include <unistd.h>
42#include <sys/stat.h>
43#include <ctype.h>
44#include <fcntl.h>
45#include <sys/mman.h>
46#include <stdlib.h>
47#include <string.h>
48
49#include "mail.h"
50#include "maildir.h"
51#include "maildriver_tools.h"
52#include "maildirdriver_tools.h"
53#include "maildirdriver_cached_message.h"
54#include "mailmessage.h"
55#include "generic_cache.h"
56#include "imfcache.h"
57#include "mail_cache_db.h"
58#include "libetpan-config.h"
59
60static int initialize(mailsession * session);
61
62static void uninitialize(mailsession * session);
63
64static int parameters(mailsession * session,
65 int id, void * value);
66
67static int connect_path(mailsession * session, char * path);
68
69static int logout(mailsession * session);
70
71static int expunge_folder(mailsession * session);
72
73static int status_folder(mailsession * session, char * mb,
74 uint32_t * result_messages, uint32_t * result_recent,
75 uint32_t * result_unseen);
76
77static int recent_number(mailsession * session, char * mb,
78 uint32_t * result);
79
80static int unseen_number(mailsession * session, char * mb,
81 uint32_t * result);
82
83static int messages_number(mailsession * session, char * mb,
84 uint32_t * result);
85
86static int append_message(mailsession * session,
87 char * message, size_t size);
88
89static int append_message_flags(mailsession * session,
90 char * message, size_t size, struct mail_flags * flags);
91
92static int get_messages_list(mailsession * session,
93 struct mailmessage_list ** result);
94
95static int get_envelopes_list(mailsession * session,
96 struct mailmessage_list * env_list);
97
98static int check_folder(mailsession * session);
99
100static int get_message(mailsession * session,
101 uint32_t num, mailmessage ** result);
102
103static int get_message_by_uid(mailsession * session,
104 const char * uid, mailmessage ** result);
105
106static mailsession_driver local_maildir_cached_session_driver = {
107 .sess_name = "maildir-cached",
108
109 .sess_initialize = initialize,
110 .sess_uninitialize = uninitialize,
111
112 .sess_parameters = parameters,
113
114 .sess_connect_stream = NULL,
115 .sess_connect_path = connect_path,
116 .sess_starttls = NULL,
117 .sess_login = NULL,
118 .sess_logout = logout,
119 .sess_noop = NULL,
120
121 .sess_build_folder_name = NULL,
122 .sess_create_folder = NULL,
123 .sess_delete_folder = NULL,
124 .sess_rename_folder = NULL,
125 .sess_check_folder = check_folder,
126 .sess_examine_folder = NULL,
127 .sess_select_folder = NULL,
128 .sess_expunge_folder = expunge_folder,
129 .sess_status_folder = status_folder,
130 .sess_messages_number = messages_number,
131 .sess_recent_number = recent_number,
132 .sess_unseen_number = unseen_number,
133 .sess_list_folders = NULL,
134 .sess_lsub_folders = NULL,
135 .sess_subscribe_folder = NULL,
136 .sess_unsubscribe_folder = NULL,
137
138 .sess_append_message = append_message,
139 .sess_append_message_flags = append_message_flags,
140 .sess_copy_message = NULL,
141 .sess_move_message = NULL,
142
143 .sess_get_messages_list = get_messages_list,
144 .sess_get_envelopes_list = get_envelopes_list,
145 .sess_remove_message = NULL,
146#if 0
147 .sess_search_messages = maildriver_generic_search_messages,
148#endif
149
150 .sess_get_message = get_message,
151 .sess_get_message_by_uid = get_message_by_uid,
152};
153
154mailsession_driver * maildir_cached_session_driver =
155&local_maildir_cached_session_driver;
156
157
158static inline struct maildir_cached_session_state_data *
159get_cached_data(mailsession * session)
160{
161 return session->sess_data;
162}
163
164static inline mailsession * get_ancestor(mailsession * session)
165{
166 return get_cached_data(session)->md_ancestor;
167}
168
169static inline struct maildir_session_state_data *
170get_ancestor_data(mailsession * session)
171{
172 return get_ancestor(session)->sess_data;
173}
174
175
176static struct maildir * get_maildir_session(mailsession * session)
177{
178 return get_ancestor_data(session)->md_session;
179}
180
181static int initialize(mailsession * session)
182{
183 struct maildir_cached_session_state_data * data;
184
185 data = malloc(sizeof(* data));
186 if (data == NULL)
187 goto err;
188
189 data->md_ancestor = mailsession_new(maildir_session_driver);
190 if (data->md_ancestor == NULL)
191 goto free;
192
193 data->md_flags_store = mail_flags_store_new();
194 if (data->md_flags_store == NULL)
195 goto free_session;
196
197 data->md_quoted_mb = NULL;
198 data->md_cache_directory[0] = '\0';
199 data->md_flags_directory[0] = '\0';
200
201 session->sess_data = data;
202
203 return MAIL_NO_ERROR;
204
205 free_session:
206 mailsession_free(data->md_ancestor);
207 free:
208 free(data);
209 err:
210 return MAIL_ERROR_MEMORY;
211}
212
213static void
214free_quoted_mb(struct maildir_cached_session_state_data * maildir_cached_data)
215{
216 if (maildir_cached_data->md_quoted_mb != NULL) {
217 free(maildir_cached_data->md_quoted_mb);
218 maildir_cached_data->md_quoted_mb = NULL;
219 }
220}
221
222static int
223write_cached_flags(struct mail_cache_db * cache_db,
224 MMAPString * mmapstr,
225 char * uid, struct mail_flags * flags);
226
227#define ENV_NAME "env.db"
228#define FLAGS_NAME "flags.db"
229
230static int flags_store_process(char * flags_directory, char * quoted_mb,
231 struct mail_flags_store * flags_store)
232{
233 char filename_flags[PATH_MAX];
234 struct mail_cache_db * cache_db_flags;
235 MMAPString * mmapstr;
236 unsigned int i;
237 int r;
238 int res;
239
240 if (carray_count(flags_store->fls_tab) == 0)
241 return MAIL_NO_ERROR;
242
243 if (quoted_mb == NULL)
244 return MAIL_NO_ERROR;
245
246 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
247 flags_directory, MAIL_DIR_SEPARATOR, quoted_mb,
248 MAIL_DIR_SEPARATOR, FLAGS_NAME);
249
250 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
251 if (r < 0) {
252 res = MAIL_ERROR_FILE;
253 goto err;
254 }
255
256 mmapstr = mmap_string_new("");
257 if (mmapstr == NULL) {
258 res = MAIL_ERROR_MEMORY;
259 goto close_db_flags;
260 }
261
262 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
263 mailmessage * msg;
264
265 msg = carray_get(flags_store->fls_tab, i);
266
267 r = write_cached_flags(cache_db_flags, mmapstr,
268 msg->msg_uid, msg->msg_flags);
269 if (r != MAIL_NO_ERROR) {
270 /* ignore errors */
271 }
272 }
273
274 mmap_string_free(mmapstr);
275 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
276
277 mail_flags_store_clear(flags_store);
278
279 return MAIL_NO_ERROR;
280
281 close_db_flags:
282 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
283 err:
284 return res;
285}
286
287static void uninitialize(mailsession * session)
288{
289 struct maildir_cached_session_state_data * data;
290
291 data = get_cached_data(session);
292
293 flags_store_process(data->md_flags_directory,
294 data->md_quoted_mb,
295 data->md_flags_store);
296
297 mail_flags_store_free(data->md_flags_store);
298 mailsession_free(data->md_ancestor);
299 free_quoted_mb(data);
300 free(data);
301
302 session->sess_data = data;
303}
304
305
306static int parameters(mailsession * session,
307 int id, void * value)
308{
309 struct maildir_cached_session_state_data * data;
310 int r;
311
312 data = get_cached_data(session);
313
314 switch (id) {
315 case MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY:
316 strncpy(data->md_cache_directory, value, PATH_MAX);
317 data->md_cache_directory[PATH_MAX - 1] = '\0';
318
319 r = generic_cache_create_dir(data->md_cache_directory);
320 if (r != MAIL_NO_ERROR)
321 return r;
322
323 return MAIL_NO_ERROR;
324
325 case MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY:
326 strncpy(data->md_flags_directory, value, PATH_MAX);
327 data->md_flags_directory[PATH_MAX - 1] = '\0';
328
329 r = generic_cache_create_dir(data->md_flags_directory);
330 if (r != MAIL_NO_ERROR)
331 return r;
332
333 return MAIL_NO_ERROR;
334
335 default:
336 return mailsession_parameters(data->md_ancestor, id, value);
337 }
338}
339
340
341static int get_cache_folder(mailsession * session, char ** result)
342{
343 struct maildir * md;
344 char * quoted_mb;
345 int res;
346 int r;
347 char key[PATH_MAX];
348 struct maildir_cached_session_state_data * data;
349
350 md = get_maildir_session(session);
351 data = get_cached_data(session);
352
353 quoted_mb = maildriver_quote_mailbox(md->mdir_path);
354 if (quoted_mb == NULL) {
355 res = MAIL_ERROR_MEMORY;
356 goto err;
357 }
358
359 snprintf(key, PATH_MAX, "%s/%s", data->md_cache_directory, quoted_mb);
360 r = generic_cache_create_dir(key);
361 if (r != MAIL_NO_ERROR) {
362 res = r;
363 goto free_quoted_mb;
364 }
365
366 snprintf(key, PATH_MAX, "%s/%s", data->md_flags_directory, quoted_mb);
367 r = generic_cache_create_dir(key);
368 if (r != MAIL_NO_ERROR) {
369 res = r;
370 goto free_quoted_mb;
371 }
372
373 * result = quoted_mb;
374
375 return MAIL_NO_ERROR;
376
377 free_quoted_mb:
378 free(quoted_mb);
379 err:
380 return res;
381}
382
383
384static int connect_path(mailsession * session, char * path)
385{
386 int r;
387 int res;
388 char * quoted_mb;
389
390 r = mailsession_connect_path(get_ancestor(session), path);
391 if (r != MAIL_NO_ERROR) {
392 res = r;
393 goto err;
394 }
395
396 r = get_cache_folder(session, &quoted_mb);
397 if (r != MAIL_NO_ERROR) {
398 res = r;
399 goto logout;
400 }
401
402 get_cached_data(session)->md_quoted_mb = quoted_mb;
403
404 return MAILDIR_NO_ERROR;
405
406 logout:
407 mailsession_logout(get_ancestor(session));
408 err:
409 return res;
410}
411
412static int logout(mailsession * session)
413{
414 struct maildir_cached_session_state_data * data;
415 int r;
416
417 data = get_cached_data(session);
418
419 flags_store_process(data->md_flags_directory,
420 data->md_quoted_mb, data->md_flags_store);
421
422 r = mailsession_logout(get_ancestor(session));
423 if (r != MAIL_NO_ERROR)
424 return r;
425
426 free_quoted_mb(get_cached_data(session));
427
428 return MAIL_NO_ERROR;
429}
430
431static int status_folder(mailsession * session, char * mb,
432 uint32_t * result_messages, uint32_t * result_recent,
433 uint32_t * result_unseen)
434{
435 return mailsession_status_folder(get_ancestor(session), mb,
436 result_messages, result_recent, result_unseen);
437}
438
439static int messages_number(mailsession * session, char * mb,
440 uint32_t * result)
441{
442 return mailsession_messages_number(get_ancestor(session), mb, result);
443}
444
445static int unseen_number(mailsession * session, char * mb,
446 uint32_t * result)
447{
448 return mailsession_unseen_number(get_ancestor(session), mb, result);
449}
450
451static int recent_number(mailsession * session, char * mb,
452 uint32_t * result)
453{
454 return mailsession_recent_number(get_ancestor(session), mb, result);
455}
456
457
458static int append_message(mailsession * session,
459 char * message, size_t size)
460{
461#if 0
462 return mailsession_append_message(get_ancestor(session), message, size);
463#endif
464 return append_message_flags(session, message, size, NULL);
465}
466
467static int append_message_flags(mailsession * session,
468 char * message, size_t size, struct mail_flags * flags)
469{
470 struct maildir * md;
471 int r;
472 char uid[PATH_MAX];
473 struct maildir_msg * md_msg;
474 chashdatum key;
475 chashdatum value;
476 uint32_t md_flags;
477 struct mail_cache_db * cache_db_flags;
478 char filename_flags[PATH_MAX];
479 MMAPString * mmapstr;
480 struct maildir_cached_session_state_data * data;
481
482 md = get_maildir_session(session);
483 if (md == NULL)
484 return MAIL_ERROR_BAD_STATE;
485
486 r = maildir_message_add_uid(md, message, size,
487 uid, sizeof(uid));
488 if (r != MAILDIR_NO_ERROR)
489 return maildirdriver_maildir_error_to_mail_error(r);
490
491 if (flags == NULL)
492 goto exit;
493
494 data = get_cached_data(session);
495
496 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
497 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
498 MAIL_DIR_SEPARATOR, FLAGS_NAME);
499
500 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
501 if (r < 0)
502 goto exit;
503
504 mmapstr = mmap_string_new("");
505 if (mmapstr == NULL)
506 goto close_db_flags;
507
508 r = write_cached_flags(cache_db_flags, mmapstr,
509 uid, flags);
510
511 mmap_string_free(mmapstr);
512 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
513
514 if (r != MAIL_NO_ERROR)
515 goto exit;
516
517 key.data = uid;
518 key.len = strlen(uid);
519 r = chash_get(md->mdir_msg_hash, &key, &value);
520 if (r < 0)
521 goto exit;
522
523 md_msg = value.data;
524
525 md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags);
526
527 r = maildir_message_change_flags(md, uid, md_flags);
528 if (r != MAILDIR_NO_ERROR)
529 goto exit;
530
531 return MAIL_NO_ERROR;
532
533 close_db_flags:
534 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
535 exit:
536 return MAIL_NO_ERROR;
537}
538
539#define UID_NAME "uid.db"
540
541static int uid_clean_up(struct mail_cache_db * uid_db,
542 struct mailmessage_list * env_list)
543{
544 chash * hash_exist;
545 int res;
546 int r;
547 unsigned int i;
548 chashdatum key;
549 chashdatum value;
550 char key_str[PATH_MAX];
551
552 /* flush cache */
553
554 hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL);
555 if (hash_exist == NULL) {
556 res = MAIL_ERROR_MEMORY;
557 goto err;
558 }
559
560 value.data = NULL;
561 value.len = 0;
562
563 key.data = "max-uid";
564 key.len = strlen("max-uid");
565 r = chash_set(hash_exist, &key, &value, NULL);
566
567 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
568 mailmessage * msg;
569
570 msg = carray_get(env_list->msg_tab, i);
571
572 value.data = NULL;
573 value.len = 0;
574
575 key.data = msg->msg_uid;
576 key.len = strlen(msg->msg_uid);
577 r = chash_set(hash_exist, &key, &value, NULL);
578 if (r < 0) {
579 res = MAIL_ERROR_MEMORY;
580 goto free;
581 }
582
583 snprintf(key_str, sizeof(key_str), "uid-%lu",
584 (unsigned long) msg->msg_index);
585 key.data = key_str;
586 key.len = strlen(key_str);
587 r = chash_set(hash_exist, &key, &value, NULL);
588 if (r < 0) {
589 res = MAIL_ERROR_MEMORY;
590 goto free;
591 }
592 }
593
594 mail_cache_db_clean_up(uid_db, hash_exist);
595
596 chash_free(hash_exist);
597
598 return MAIL_NO_ERROR;
599
600 free:
601 chash_free(hash_exist);
602 err:
603 return res;
604}
605
606static int get_messages_list(mailsession * session,
607 struct mailmessage_list ** result)
608{
609 struct maildir * md;
610 int r;
611 struct mailmessage_list * env_list;
612 int res;
613 uint32_t max_uid;
614 char filename[PATH_MAX];
615 struct mail_cache_db * uid_db;
616 void * value;
617 size_t value_len;
618 unsigned long i;
619 struct maildir_cached_session_state_data * data;
620 char key[PATH_MAX];
621
622 data = get_cached_data(session);
623
624 md = get_maildir_session(session);
625 if (md == NULL) {
626 res = MAIL_ERROR_BAD_STATE;
627 goto err;
628 }
629
630 check_folder(session);
631
632 r = maildir_update(md);
633 if (r != MAILDIR_NO_ERROR) {
634 res = maildirdriver_maildir_error_to_mail_error(r);
635 goto err;
636 }
637
638 r = maildir_get_messages_list(session, md,
639 maildir_cached_message_driver, &env_list);
640 if (r != MAILDIR_NO_ERROR) {
641 res = r;
642 goto err;
643 }
644
645 /* read/write DB */
646
647 snprintf(filename, sizeof(filename), "%s%c%s%c%s",
648 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
649 MAIL_DIR_SEPARATOR, UID_NAME);
650
651 r = mail_cache_db_open_lock(filename, &uid_db);
652 if (r < 0) {
653 res = MAIL_ERROR_MEMORY;
654 goto free_list;
655 }
656
657 max_uid = 0;
658 r = mail_cache_db_get(uid_db, "max-uid", sizeof("max-uid") - 1,
659 &value, &value_len);
660 if (r == 0) {
661 memcpy(&max_uid, value, sizeof(max_uid));
662 }
663
664 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
665 mailmessage * msg;
666 uint32_t index;
667
668 msg = carray_get(env_list->msg_tab, i);
669
670 r = mail_cache_db_get(uid_db, msg->msg_uid,
671 strlen(msg->msg_uid), &value, &value_len);
672 if (r < 0) {
673 max_uid ++;
674 msg->msg_index = max_uid;
675 mail_cache_db_put(uid_db, msg->msg_uid,
676 strlen(msg->msg_uid), &msg->msg_index, sizeof(msg->msg_index));
677
678 snprintf(key, sizeof(key), "uid-%lu", (unsigned long) msg->msg_index);
679 mail_cache_db_put(uid_db, key, strlen(key),
680 msg->msg_uid, strlen(msg->msg_uid));
681 }
682 else {
683 memcpy(&index, value, sizeof(index));
684 msg->msg_index = index;
685 }
686 }
687
688 mail_cache_db_put(uid_db, "max-uid", sizeof("max-uid") - 1,
689 &max_uid, sizeof(max_uid));
690
691 uid_clean_up(uid_db, env_list);
692
693 mail_cache_db_close_unlock(filename, uid_db);
694
695 * result = env_list;
696
697 return MAIL_NO_ERROR;
698
699 free_list:
700 mailmessage_list_free(env_list);
701 err:
702 return res;
703}
704
705static int
706get_cached_flags(struct mail_cache_db * cache_db,
707 MMAPString * mmapstr,
708 mailsession * session,
709 char * uid,
710 struct mail_flags ** result)
711{
712 int r;
713 char keyname[PATH_MAX];
714 struct mail_flags * flags;
715 int res;
716
717 snprintf(keyname, PATH_MAX, "%s-flags", uid);
718
719 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
720 if (r != MAIL_NO_ERROR) {
721 res = r;
722 goto err;
723 }
724
725 * result = flags;
726
727 return MAIL_NO_ERROR;
728
729 err:
730 return res;
731}
732
733static int
734get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
735 mailsession * session, char * uid,
736 struct mailimf_fields ** result)
737{
738 int r;
739 char keyname[PATH_MAX];
740 struct mailimf_fields * fields;
741 int res;
742
743 snprintf(keyname, PATH_MAX, "%s-envelope", uid);
744
745 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
746 if (r != MAIL_NO_ERROR) {
747 res = r;
748 goto err;
749 }
750
751 * result = fields;
752
753 return MAIL_NO_ERROR;
754
755 err:
756 return res;
757}
758
759static int
760write_cached_envelope(struct mail_cache_db * cache_db,
761 MMAPString * mmapstr,
762 mailsession * session, char * uid,
763 struct mailimf_fields * fields)
764{
765 int r;
766 char keyname[PATH_MAX];
767 int res;
768
769 snprintf(keyname, PATH_MAX, "%s-envelope", uid);
770
771 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
772 if (r != MAIL_NO_ERROR) {
773 res = r;
774 goto err;
775 }
776
777 return MAIL_NO_ERROR;
778
779 err:
780 return res;
781}
782
783static int
784write_cached_flags(struct mail_cache_db * cache_db,
785 MMAPString * mmapstr,
786 char * uid, struct mail_flags * flags)
787{
788 int r;
789 char keyname[PATH_MAX];
790 int res;
791
792 snprintf(keyname, PATH_MAX, "%s-flags", uid);
793
794 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
795 if (r != MAIL_NO_ERROR) {
796 res = r;
797 goto err;
798 }
799
800 return MAIL_NO_ERROR;
801
802 err:
803 return res;
804}
805
806
807static int get_envelopes_list(mailsession * session,
808 struct mailmessage_list * env_list)
809{
810 int r;
811 unsigned int i;
812 int res;
813 struct maildir_cached_session_state_data * data;
814 char filename_env[PATH_MAX];
815 char filename_flags[PATH_MAX];
816 struct mail_cache_db * cache_db_env;
817 struct mail_cache_db * cache_db_flags;
818 MMAPString * mmapstr;
819
820 data = get_cached_data(session);
821
822 flags_store_process(data->md_flags_directory,
823 data->md_quoted_mb, data->md_flags_store);
824
825 mmapstr = mmap_string_new("");
826 if (mmapstr == NULL) {
827 res = MAIL_ERROR_MEMORY;
828 goto err;
829 }
830
831 snprintf(filename_env, PATH_MAX, "%s%c%s%c%s",
832 data->md_cache_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
833 MAIL_DIR_SEPARATOR, ENV_NAME);
834
835 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
836 if (r < 0) {
837 res = MAIL_ERROR_MEMORY;
838 goto free_mmapstr;
839 }
840
841 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
842 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
843 MAIL_DIR_SEPARATOR, FLAGS_NAME);
844
845 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
846 if (r < 0) {
847 res = MAIL_ERROR_FILE;
848 goto close_db_env;
849 }
850
851 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) {
852 mailmessage * msg;
853 struct mailimf_fields * fields;
854 struct mail_flags * flags;
855
856 msg = carray_get(env_list->msg_tab, i);
857
858 if (msg->msg_fields == NULL) {
859 r = get_cached_envelope(cache_db_env, mmapstr, session,
860 msg->msg_uid, &fields);
861 if (r == MAIL_NO_ERROR) {
862 msg->msg_cached = TRUE;
863 msg->msg_fields = fields;
864 }
865 }
866
867 if (msg->msg_flags == NULL) {
868 r = get_cached_flags(cache_db_flags, mmapstr,
869 session, msg->msg_uid, &flags);
870 if (r == MAIL_NO_ERROR) {
871 msg->msg_flags = flags;
872 }
873 }
874 }
875
876 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
877 mail_cache_db_close_unlock(filename_env, cache_db_env);
878
879 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
880 if (r != MAIL_NO_ERROR) {
881 res = r;
882 goto free_mmapstr;
883 }
884
885 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
886 if (r < 0) {
887 res = MAIL_ERROR_MEMORY;
888 goto free_mmapstr;
889 }
890
891 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
892 if (r < 0) {
893 res = MAIL_ERROR_FILE;
894 goto close_db_env;
895 }
896
897 /* must write cache */
898
899 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
900 mailmessage * msg;
901
902 msg = carray_get(env_list->msg_tab, i);
903
904 if (msg->msg_fields != NULL) {
905 if (!msg->msg_cached) {
906 /* msg->index is the numerical UID of the message */
907 r = write_cached_envelope(cache_db_env, mmapstr,
908 session, msg->msg_uid, msg->msg_fields);
909 }
910 }
911
912 if (msg->msg_flags != NULL) {
913 r = write_cached_flags(cache_db_flags, mmapstr,
914 msg->msg_uid, msg->msg_flags);
915 }
916 }
917
918 /* flush cache */
919
920 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
921
922 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
923 mail_cache_db_close_unlock(filename_env, cache_db_env);
924
925 mmap_string_free(mmapstr);
926
927 return MAIL_NO_ERROR;
928
929 close_db_env:
930 mail_cache_db_close_unlock(filename_env, cache_db_env);
931 free_mmapstr:
932 mmap_string_free(mmapstr);
933 err:
934 return res;
935}
936
937static int expunge_folder(mailsession * session)
938{
939 return mailsession_expunge_folder(get_ancestor(session));
940}
941
942static int check_folder(mailsession * session)
943{
944 struct maildir_cached_session_state_data * data;
945
946 data = get_cached_data(session);
947
948 flags_store_process(data->md_flags_directory,
949 data->md_quoted_mb, data->md_flags_store);
950
951 return mailsession_check_folder(get_ancestor(session));
952}
953
954static int get_message(mailsession * session,
955 uint32_t num, mailmessage ** result)
956{
957 struct maildir * md;
958 int res;
959 mailmessage * msg;
960 char filename[PATH_MAX];
961 struct mail_cache_db * uid_db;
962 char * msg_filename;
963 struct stat stat_info;
964 char key_str[PATH_MAX];
965 void * value;
966 size_t value_len;
967 char uid[PATH_MAX];
968 struct maildir_cached_session_state_data * data;
969 int r;
970
971 data = get_cached_data(session);
972
973 md = get_maildir_session(session);
974
975 /* a get_messages_list() should have been done once before */
976
977 /* read DB */
978
979 snprintf(filename, sizeof(filename), "%s%c%s%c%s",
980 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
981 MAIL_DIR_SEPARATOR, UID_NAME);
982
983 r = mail_cache_db_open_lock(filename, &uid_db);
984 if (r < 0) {
985 res = MAIL_ERROR_MEMORY;
986 goto err;
987 }
988
989 snprintf(key_str, sizeof(key_str), "uid-%lu", (unsigned long) num);
990
991 r = mail_cache_db_get(uid_db, key_str, strlen(key_str), &value, &value_len);
992 if (r < 0) {
993 res = MAIL_ERROR_INVAL;
994 goto close_db;
995 }
996
997 if (value_len >= PATH_MAX) {
998 res = MAIL_ERROR_INVAL;
999 goto close_db;
1000 }
1001
1002 memcpy(uid, value, value_len);
1003 uid[value_len] = '\0';
1004
1005 mail_cache_db_close_unlock(filename, uid_db);
1006
1007 /* update maildir data */
1008
1009 r = maildir_update(md);
1010 if (r != MAILDIR_NO_ERROR) {
1011 res = maildirdriver_maildir_error_to_mail_error(r);
1012 goto err;
1013 }
1014
1015 msg_filename = maildir_message_get(md, uid);
1016 if (msg_filename == NULL) {
1017 res = MAIL_ERROR_INVAL;
1018 goto err;
1019 }
1020
1021 r = stat(msg_filename, &stat_info);
1022 free(msg_filename);
1023 if (r < 0) {
1024 res = MAIL_ERROR_INVAL;
1025 goto err;
1026 }
1027
1028 /* create message */
1029
1030 msg = mailmessage_new();
1031 if (msg == NULL) {
1032 res = MAIL_ERROR_MEMORY;
1033 goto err;
1034 }
1035
1036 r = mailmessage_init(msg, session, maildir_cached_message_driver,
1037 num, stat_info.st_size);
1038 if (r != MAIL_NO_ERROR) {
1039 mailmessage_free(msg);
1040 res = r;
1041 goto err;
1042 }
1043
1044 msg->msg_uid = strdup(uid);
1045 if (msg->msg_uid == NULL) {
1046 mailmessage_free(msg);
1047 res = r;
1048 goto err;
1049 }
1050
1051 * result = msg;
1052
1053 return MAIL_NO_ERROR;
1054
1055 close_db:
1056 mail_cache_db_close_unlock(filename, uid_db);
1057 err:
1058 return res;
1059}
1060
1061
1062static int get_message_by_uid(mailsession * session,
1063 const char * uid, mailmessage ** result)
1064{
1065 int r;
1066 struct maildir * md;
1067 int res;
1068 mailmessage * msg;
1069 char filename[PATH_MAX];
1070 struct mail_cache_db * uid_db;
1071 char * msg_filename;
1072 struct stat stat_info;
1073 void * value;
1074 size_t value_len;
1075 struct maildir_cached_session_state_data * data;
1076 uint32_t index;
1077
1078 data = get_cached_data(session);
1079
1080 md = get_maildir_session(session);
1081
1082 /* a get_messages_list() should have been done once before */
1083
1084 /* read DB */
1085
1086 snprintf(filename, sizeof(filename), "%s%c%s%c%s",
1087 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
1088 MAIL_DIR_SEPARATOR, UID_NAME);
1089
1090 r = mail_cache_db_open_lock(filename, &uid_db);
1091 if (r < 0) {
1092 res = MAIL_ERROR_MEMORY;
1093 goto err;
1094 }
1095
1096 r = mail_cache_db_get(uid_db, uid, strlen(uid), &value, &value_len);
1097 if (r < 0) {
1098 res = MAIL_ERROR_INVAL;
1099 goto close_db;
1100 }
1101
1102 memcpy(&index, value, sizeof(index));
1103
1104 mail_cache_db_close_unlock(filename, uid_db);
1105
1106 /* update maildir data */
1107
1108 r = maildir_update(md);
1109 if (r != MAILDIR_NO_ERROR) {
1110 res = maildirdriver_maildir_error_to_mail_error(r);
1111 goto err;
1112 }
1113
1114 msg_filename = maildir_message_get(md, uid);
1115 if (msg_filename == NULL) {
1116 res = MAIL_ERROR_INVAL;
1117 goto err;
1118 }
1119
1120 r = stat(msg_filename, &stat_info);
1121 free(msg_filename);
1122 if (r < 0) {
1123 res = MAIL_ERROR_INVAL;
1124 goto err;
1125 }
1126
1127 /* create message */
1128
1129 msg = mailmessage_new();
1130 if (msg == NULL) {
1131 res = MAIL_ERROR_MEMORY;
1132 goto err;
1133 }
1134
1135 r = mailmessage_init(msg, session, maildir_cached_message_driver,
1136 index, stat_info.st_size);
1137 if (r != MAIL_NO_ERROR) {
1138 mailmessage_free(msg);
1139 res = r;
1140 goto err;
1141 }
1142
1143 msg->msg_uid = strdup(uid);
1144 if (msg->msg_uid == NULL) {
1145 mailmessage_free(msg);
1146 res = r;
1147 goto err;
1148 }
1149
1150 * result = msg;
1151
1152 return MAIL_NO_ERROR;
1153
1154 close_db:
1155 mail_cache_db_close_unlock(filename, uid_db);
1156 err:
1157 return res;
1158}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_CACHED_H
37
38#define MAILDIRDRIVER_CACHED_H
39
40#include <libetpan/maildriver.h>
41#include <libetpan/maildirdriver_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47extern mailsession_driver * maildir_cached_session_driver;
48
49#ifdef __cplusplus
50}
51#endif
52
53#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildirdriver_message.h"
37
38#include "mailmessage_tools.h"
39#include "maildirdriver.h"
40#include "maildir.h"
41#include "generic_cache.h"
42#include "mail_cache_db.h"
43#include "maildirdriver_tools.h"
44
45#include <unistd.h>
46#include <sys/mman.h>
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <fcntl.h>
50#include <string.h>
51#include <stdlib.h>
52
53static int get_flags(mailmessage * msg_info,
54 struct mail_flags ** result);
55
56static int prefetch(mailmessage * msg_info);
57
58static void prefetch_free(struct generic_message_t * msg);
59
60static int initialize(mailmessage * msg_info);
61
62static void check(mailmessage * msg_info);
63
64static mailmessage_driver local_maildir_cached_message_driver = {
65 .msg_name = "maildir-cached",
66
67 .msg_initialize = initialize,
68 .msg_uninitialize = mailmessage_generic_uninitialize,
69
70 .msg_flush = mailmessage_generic_flush,
71 .msg_check = check,
72
73 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
74
75 .msg_fetch = mailmessage_generic_fetch,
76 .msg_fetch_header = mailmessage_generic_fetch_header,
77 .msg_fetch_body = mailmessage_generic_fetch_header,
78 .msg_fetch_size = NULL,
79 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
80 .msg_fetch_section = mailmessage_generic_fetch_section,
81 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
82 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
83 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
84 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
85
86 .msg_get_flags = get_flags,
87};
88
89mailmessage_driver * maildir_cached_message_driver =
90&local_maildir_cached_message_driver;
91
92struct maildir_msg_data {
93 int fd;
94};
95
96#if 0
97static inline struct maildir_cached_session_state_data *
98get_cached_session_data(mailmessage * msg)
99{
100 return msg->session->data;
101}
102
103static inline mailsession * cached_session_get_ancestor(mailsession * session)
104{
105 return get_data(session)->session;
106}
107
108static inline struct maildir_session_state_data *
109cached_session_get_ancestor_data(mailsession * session)
110{
111 return get_ancestor(session)->data;
112}
113
114static struct maildir * get_maildir_session(mailmessage * msg)
115{
116 return cached_session_get_ancestor_data(msg->session)->session;
117}
118#endif
119static inline struct maildir_cached_session_state_data *
120get_cached_session_data(mailmessage * msg)
121{
122 return msg->msg_session->sess_data;
123}
124
125static inline struct maildir_cached_session_state_data *
126cached_session_get_data(mailsession * s)
127{
128 return s->sess_data;
129}
130
131static inline mailsession * cached_session_get_ancestor(mailsession * s)
132{
133 return cached_session_get_data(s)->md_ancestor;
134}
135
136static inline struct maildir_session_state_data *
137cached_session_get_ancestor_data(mailsession * s)
138{
139 return cached_session_get_ancestor(s)->sess_data;
140}
141
142static inline struct maildir_session_state_data *
143get_session_ancestor_data(mailmessage * msg)
144{
145 return cached_session_get_ancestor_data(msg->msg_session);
146}
147
148static inline struct maildir *
149cached_session_get_maildir_session(mailsession * session)
150{
151 return cached_session_get_ancestor_data(session)->md_session;
152}
153
154static inline struct maildir * get_maildir_session(mailmessage * msg)
155{
156 return cached_session_get_maildir_session(msg->msg_session);
157}
158
159static int prefetch(mailmessage * msg_info)
160{
161 struct generic_message_t * msg;
162 int res;
163 struct maildir_msg_data * data;
164 char * filename;
165 int fd;
166 char * mapping;
167 struct maildir * md;
168
169 md = get_maildir_session(msg_info);
170
171 filename = maildir_message_get(md, msg_info->msg_uid);
172 if (filename == NULL) {
173 res = MAIL_ERROR_MEMORY;
174 goto err;
175 }
176
177 fd = open(filename, O_RDONLY);
178 free(filename);
179 if (fd == -1) {
180 res = MAIL_ERROR_FILE;
181 goto err;
182 }
183
184 mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0);
185 if (mapping == MAP_FAILED) {
186 res = MAIL_ERROR_FILE;
187 goto close;
188 }
189
190 data = malloc(sizeof(* data));
191 if (data == NULL) {
192 res = MAIL_ERROR_MEMORY;
193 goto unmap;
194 }
195
196 data->fd = fd;
197
198 msg = msg_info->msg_data;
199
200 msg->msg_data = data;
201 msg->msg_message = mapping;
202 msg->msg_length = msg_info->msg_size;
203
204 return MAIL_NO_ERROR;
205
206 unmap:
207 munmap(mapping, msg_info->msg_size);
208 close:
209 close(fd);
210 err:
211 return res;
212}
213
214static void prefetch_free(struct generic_message_t * msg)
215{
216 if (msg->msg_message != NULL) {
217 struct maildir_msg_data * data;
218
219 munmap(msg->msg_message, msg->msg_length);
220 msg->msg_message = NULL;
221 data = msg->msg_data;
222 close(data->fd);
223 free(data);
224 }
225}
226
227static int initialize(mailmessage * msg_info)
228{
229 struct generic_message_t * msg;
230 int r;
231
232 r = mailmessage_generic_initialize(msg_info);
233 if (r != MAIL_NO_ERROR)
234 return r;
235
236 msg = msg_info->msg_data;
237 msg->msg_prefetch = prefetch;
238 msg->msg_prefetch_free = prefetch_free;
239
240 return MAIL_NO_ERROR;
241}
242
243static void check(mailmessage * msg_info)
244{
245 int r;
246
247 if (msg_info->msg_flags != NULL) {
248 r = mail_flags_store_set(get_session_ancestor_data(msg_info)->md_flags_store, msg_info);
249
250 r = mail_flags_store_set(get_cached_session_data(msg_info)->md_flags_store, msg_info);
251 /* ignore errors */
252 }
253}
254
255#define FLAGS_NAME "flags.db"
256
257static int get_flags(mailmessage * msg_info,
258 struct mail_flags ** result)
259{
260 struct mail_cache_db * cache_db_flags;
261 chashdatum key;
262 chashdatum value;
263 struct maildir * md;
264 struct mail_flags * flags;
265 struct maildir_cached_session_state_data * data;
266 struct maildir_msg * md_msg;
267 int r;
268 uint32_t driver_flags;
269 char filename_flags[PATH_MAX];
270 char keyname[PATH_MAX];
271 MMAPString * mmapstr;
272
273 if (msg_info->msg_flags != NULL) {
274 * result = msg_info->msg_flags;
275 return MAIL_NO_ERROR;
276 }
277
278 data = get_cached_session_data(msg_info);
279 flags = mail_flags_store_get(data->md_flags_store,
280 msg_info->msg_index);
281 if (flags != NULL) {
282 msg_info->msg_flags = flags;
283 * result = msg_info->msg_flags;
284 return MAIL_NO_ERROR;
285 }
286
287 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
288 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
289 MAIL_DIR_SEPARATOR, FLAGS_NAME);
290
291 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
292 if (r < 0)
293 return MAIL_ERROR_FILE;
294
295 snprintf(keyname, PATH_MAX, "%s-flags", msg_info->msg_uid);
296
297 mmapstr = mmap_string_new("");
298 if (mmapstr == NULL) {
299 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
300 return MAIL_ERROR_MEMORY;
301 }
302
303 r = generic_cache_flags_read(cache_db_flags, mmapstr, keyname, &flags);
304 mmap_string_free(mmapstr);
305
306 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
307
308 if (r != MAIL_NO_ERROR) {
309 flags = mail_flags_new_empty();
310 if (flags == NULL)
311 return MAIL_ERROR_MEMORY;
312 }
313
314 md = get_maildir_session(msg_info);
315 if (md == NULL)
316 return MAIL_ERROR_BAD_STATE;
317
318 key.data = msg_info->msg_uid;
319 key.len = strlen(msg_info->msg_uid);
320 r = chash_get(md->mdir_msg_hash, &key, &value);
321 if (r < 0)
322 return MAIL_ERROR_MSG_NOT_FOUND;
323
324 md_msg = value.data;
325
326 driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags);
327
328 flags->fl_flags = driver_flags;
329 msg_info->msg_flags = flags;
330
331 * result = msg_info->msg_flags;
332
333 return MAIL_NO_ERROR;
334}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_CACHED_MESSAGE_H
37
38#define MAILDIRDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/maildirdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * maildir_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildirdriver_message.h"
37#include "maildirdriver_tools.h"
38
39#include "mailmessage_tools.h"
40#include "maildirdriver.h"
41#include "maildir.h"
42#include "generic_cache.h"
43
44#include <unistd.h>
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <sys/stat.h>
48#include <fcntl.h>
49#include <string.h>
50#include <stdlib.h>
51
52static int get_flags(mailmessage * msg_info,
53 struct mail_flags ** result);
54
55static int prefetch(mailmessage * msg_info);
56
57static void prefetch_free(struct generic_message_t * msg);
58
59static int initialize(mailmessage * msg_info);
60
61static void check(mailmessage * msg_info);
62
63static mailmessage_driver local_maildir_message_driver = {
64 .msg_name = "maildir",
65
66 .msg_initialize = initialize,
67 .msg_uninitialize = mailmessage_generic_uninitialize,
68
69 .msg_flush = mailmessage_generic_flush,
70 .msg_check = check,
71
72 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
73
74 .msg_fetch = mailmessage_generic_fetch,
75 .msg_fetch_header = mailmessage_generic_fetch_header,
76 .msg_fetch_body = mailmessage_generic_fetch_header,
77 .msg_fetch_size = NULL,
78 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
79 .msg_fetch_section = mailmessage_generic_fetch_section,
80 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
81 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
82 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
83 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
84
85 .msg_get_flags = get_flags,
86};
87
88mailmessage_driver * maildir_message_driver = &local_maildir_message_driver;
89
90struct maildir_msg_data {
91 int fd;
92};
93
94static inline struct maildir_session_state_data *
95get_session_data(mailmessage * msg)
96{
97 return msg->msg_session->sess_data;
98}
99
100static struct maildir * get_maildir_session(mailmessage * msg)
101{
102 return get_session_data(msg)->md_session;
103}
104
105static int prefetch(mailmessage * msg_info)
106{
107 struct generic_message_t * msg;
108 int res;
109 struct maildir_msg_data * data;
110 char * filename;
111 int fd;
112 char * mapping;
113 struct maildir * md;
114
115 md = get_maildir_session(msg_info);
116
117 if (msg_info->msg_uid == NULL) {
118 res = MAIL_ERROR_INVAL;
119 goto err;
120 }
121
122 filename = maildir_message_get(md, msg_info->msg_uid);
123 if (filename == NULL) {
124 res = MAIL_ERROR_MEMORY;
125 goto err;
126 }
127
128 fd = open(filename, O_RDONLY);
129 free(filename);
130 if (fd == -1) {
131 res = MAIL_ERROR_FILE;
132 goto err;
133 }
134
135 mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0);
136 if (mapping == MAP_FAILED) {
137 res = MAIL_ERROR_FILE;
138 goto close;
139 }
140
141 data = malloc(sizeof(* data));
142 if (data == NULL) {
143 res = MAIL_ERROR_MEMORY;
144 goto unmap;
145 }
146
147 data->fd = fd;
148
149 msg = msg_info->msg_data;
150
151 msg->msg_data = data;
152 msg->msg_message = mapping;
153 msg->msg_length = msg_info->msg_size;
154
155 return MAIL_NO_ERROR;
156
157 unmap:
158 munmap(mapping, msg_info->msg_size);
159 close:
160 close(fd);
161 err:
162 return res;
163}
164
165static void prefetch_free(struct generic_message_t * msg)
166{
167 if (msg->msg_message != NULL) {
168 struct maildir_msg_data * data;
169
170 munmap(msg->msg_message, msg->msg_length);
171 msg->msg_message = NULL;
172 data = msg->msg_data;
173 close(data->fd);
174 free(data);
175 }
176}
177
178static int initialize(mailmessage * msg_info)
179{
180 struct generic_message_t * msg;
181 int r;
182
183 r = mailmessage_generic_initialize(msg_info);
184 if (r != MAIL_NO_ERROR)
185 return r;
186
187 msg = msg_info->msg_data;
188 msg->msg_prefetch = prefetch;
189 msg->msg_prefetch_free = prefetch_free;
190
191 return MAIL_NO_ERROR;
192}
193
194static void check(mailmessage * msg_info)
195{
196 int r;
197
198 if (msg_info->msg_flags != NULL) {
199 r = mail_flags_store_set(get_session_data(msg_info)->md_flags_store,
200 msg_info);
201 /* ignore errors */
202 }
203}
204
205static int get_flags(mailmessage * msg_info,
206 struct mail_flags ** result)
207{
208 chashdatum key;
209 chashdatum value;
210 struct maildir * md;
211 struct mail_flags * flags;
212 struct maildir_session_state_data * data;
213 struct maildir_msg * md_msg;
214 int r;
215 uint32_t driver_flags;
216 clist * ext;
217
218 if (msg_info->msg_flags != NULL) {
219 * result = msg_info->msg_flags;
220 return MAIL_NO_ERROR;
221 }
222
223 data = get_session_data(msg_info);
224 flags = mail_flags_store_get(data->md_flags_store,
225 msg_info->msg_index);
226 if (flags != NULL) {
227 msg_info->msg_flags = flags;
228 * result = msg_info->msg_flags;
229 return MAIL_NO_ERROR;
230 }
231
232 md = get_maildir_session(msg_info);
233 if (md == NULL)
234 return MAIL_ERROR_BAD_STATE;
235
236 key.data = msg_info->msg_uid;
237 key.len = strlen(msg_info->msg_uid);
238 r = chash_get(md->mdir_msg_hash, &key, &value);
239 if (r < 0)
240 return MAIL_ERROR_MSG_NOT_FOUND;
241
242 md_msg = value.data;
243
244 driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags);
245
246 ext = clist_new();
247 if (ext == NULL)
248 return MAIL_ERROR_MEMORY;
249
250 msg_info->msg_flags = mail_flags_new(driver_flags, ext);
251
252 * result = msg_info->msg_flags;
253
254 return MAIL_NO_ERROR;
255}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_MESSAGE_H
37
38#define MAILDIRDRIVER_MESSAGE_H
39
40#include <libetpan/maildirdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * maildir_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmessage.h"
37#include "maildirdriver_tools.h"
38#include "maildir.h"
39#include "generic_cache.h"
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <stdlib.h>
43#include <string.h>
44
45int maildirdriver_maildir_error_to_mail_error(int error)
46{
47 switch (error) {
48 case MAILDIR_NO_ERROR:
49 return MAIL_NO_ERROR;
50
51 case MAILDIR_ERROR_CREATE:
52 return MAIL_ERROR_FILE;
53
54 case MAILDIR_ERROR_DIRECTORY:
55 return MAIL_ERROR_FILE;
56
57 case MAILDIR_ERROR_MEMORY:
58 return MAIL_ERROR_MEMORY;
59
60 case MAILDIR_ERROR_FILE:
61 return MAIL_ERROR_FILE;
62
63 case MAILDIR_ERROR_FOLDER:
64 return MAIL_ERROR_FOLDER;
65
66 case MAILDIR_ERROR_NOT_FOUND:
67 return MAIL_ERROR_MSG_NOT_FOUND;
68
69 default:
70 return MAIL_ERROR_INVAL;
71 }
72}
73
74
75
76uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags)
77{
78 uint32_t flags;
79
80 flags = 0;
81 if ((md_flags & MAILDIR_FLAG_NEW) != 0)
82 flags |= MAIL_FLAG_NEW;
83
84 if ((md_flags & MAILDIR_FLAG_SEEN) != 0)
85 flags |= MAIL_FLAG_SEEN;
86
87 if ((md_flags & MAILDIR_FLAG_REPLIED) != 0)
88 flags |= MAIL_FLAG_ANSWERED;
89
90 if ((md_flags & MAILDIR_FLAG_FLAGGED) != 0)
91 flags |= MAIL_FLAG_FLAGGED;
92
93 if ((md_flags & MAILDIR_FLAG_TRASHED) != 0)
94 flags |= MAIL_FLAG_DELETED;
95
96 return flags;
97}
98
99uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags)
100{
101 uint32_t md_flags;
102
103 md_flags = 0;
104 if ((flags & MAIL_FLAG_NEW) != 0)
105 md_flags |= MAILDIR_FLAG_NEW;
106
107 if ((flags & MAIL_FLAG_SEEN) != 0)
108 md_flags |= MAILDIR_FLAG_SEEN;
109
110 if ((flags & MAIL_FLAG_ANSWERED) != 0)
111 md_flags |= MAILDIR_FLAG_REPLIED;
112
113 if ((flags & MAIL_FLAG_FLAGGED) != 0)
114 md_flags |= MAILDIR_FLAG_FLAGGED;
115
116 if ((flags & MAIL_FLAG_DELETED) != 0)
117 md_flags |= MAILDIR_FLAG_TRASHED;
118
119 return md_flags;
120}
121
122
123int maildir_get_messages_list(mailsession * session, struct maildir * md,
124 mailmessage_driver * message_driver,
125 struct mailmessage_list ** result)
126{
127 unsigned int i;
128 struct mailmessage_list * env_list;
129 int r;
130 carray * tab;
131 int res;
132
133 tab = carray_new(128);
134 if (tab == NULL) {
135 res = MAIL_ERROR_MEMORY;
136 goto err;
137 }
138
139 for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) {
140 struct maildir_msg * md_msg;
141 mailmessage * msg;
142 char * filename;
143 struct stat stat_info;
144
145 md_msg = carray_get(md->mdir_msg_list, i);
146
147 filename = maildir_message_get(md, md_msg->msg_uid);
148 r = stat(filename, &stat_info);
149 free(filename);
150 if (r < 0)
151 continue;
152
153 msg = mailmessage_new();
154 if (msg == NULL) {
155 res = MAIL_ERROR_MEMORY;
156 goto free_list;
157 }
158
159 r = mailmessage_init(msg, session, message_driver,
160 i + 1, stat_info.st_size);
161 if (r != MAIL_NO_ERROR) {
162 mailmessage_free(msg);
163 res = r;
164 goto free_list;
165 }
166
167 msg->msg_uid = strdup(md_msg->msg_uid);
168 if (msg->msg_uid == NULL) {
169 mailmessage_free(msg);
170 res = MAIL_ERROR_MEMORY;
171 goto free_list;
172 }
173
174 r = carray_add(tab, msg, NULL);
175 if (r < 0) {
176 mailmessage_free(msg);
177 res = MAIL_ERROR_MEMORY;
178 goto free_list;
179 }
180 }
181
182 env_list = mailmessage_list_new(tab);
183 if (env_list == NULL) {
184 res = MAIL_ERROR_MEMORY;
185 goto free_list;
186 }
187
188 * result = env_list;
189
190 return MAIL_NO_ERROR;
191
192 free_list:
193 for(i = 0 ; i < carray_count(tab) ; i ++)
194 mailmessage_free(carray_get(tab, i));
195 carray_free(tab);
196 err:
197 return res;
198}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_TOOLS_H
37
38#define MAILDIRDRIVER_TOOLS_H
39
40#include "maildriver_types.h"
41#include "maildir.h"
42
43int maildirdriver_maildir_error_to_mail_error(int error);
44
45uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags);
46
47uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags);
48
49int maildir_get_messages_list(mailsession * session, struct maildir * md,
50 mailmessage_driver * message_driver,
51 struct mailmessage_list ** result);
52
53#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_TYPES_H
37
38#define MAILDIRDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/maildir.h>
44#include <libetpan/generic_cache_types.h>
45#include <libetpan/mailstorage_types.h>
46
47#ifdef __cplusplus
48extern "C" {
49#endif
50
51struct maildir_session_state_data {
52 struct maildir * md_session;
53 struct mail_flags_store * md_flags_store;
54};
55
56enum {
57 MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
58 MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY,
59};
60
61struct maildir_cached_session_state_data {
62 mailsession * md_ancestor;
63 char * md_quoted_mb;
64 struct mail_flags_store * md_flags_store;
65 char md_cache_directory[PATH_MAX];
66 char md_flags_directory[PATH_MAX];
67};
68
69/* maildir storage */
70
71/*
72 maildir_mailstorage is the state data specific to the maildir storage.
73
74 - pathname is the path of the maildir storage.
75
76 - cached if this value is != 0, a persistant cache will be
77 stored on local system.
78
79 - cache_directory is the location of the cache.
80
81 - flags_directory is the location of the flags.
82*/
83
84struct maildir_mailstorage {
85 char * md_pathname;
86
87 int md_cached;
88 char * md_cache_directory;
89 char * md_flags_directory;
90};
91
92#ifdef __cplusplus
93}
94#endif
95
96#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildirstorage.h"
37#include "mailstorage.h"
38
39#include "mail.h"
40#include "mailmessage.h"
41#include "maildirdriver.h"
42#include "maildirdriver_cached.h"
43#include "maildriver.h"
44
45#include <stdlib.h>
46#include <string.h>
47
48/* maildir storage */
49
50static int maildir_mailstorage_connect(struct mailstorage * storage);
51static int
52maildir_mailstorage_get_folder_session(struct mailstorage * storage,
53 char * pathname, mailsession ** result);
54static void maildir_mailstorage_uninitialize(struct mailstorage * storage);
55
56static mailstorage_driver maildir_mailstorage_driver = {
57 .sto_name = "maildir",
58 .sto_connect = maildir_mailstorage_connect,
59 .sto_get_folder_session = maildir_mailstorage_get_folder_session,
60 .sto_uninitialize = maildir_mailstorage_uninitialize,
61};
62
63int maildir_mailstorage_init(struct mailstorage * storage,
64 char * md_pathname, int md_cached,
65 char * md_cache_directory, char * md_flags_directory)
66{
67 struct maildir_mailstorage * maildir_storage;
68
69 maildir_storage = malloc(sizeof(* maildir_storage));
70 if (maildir_storage == NULL)
71 goto err;
72
73 maildir_storage->md_pathname = strdup(md_pathname);
74 if (maildir_storage->md_pathname == NULL)
75 goto free;
76
77 maildir_storage->md_cached = md_cached;
78
79 if (md_cached && (md_cache_directory != NULL) &&
80 (md_flags_directory != NULL)) {
81 maildir_storage->md_cache_directory = strdup(md_cache_directory);
82 if (maildir_storage->md_cache_directory == NULL)
83 goto free_pathname;
84
85 maildir_storage->md_flags_directory = strdup(md_flags_directory);
86 if (maildir_storage->md_flags_directory == NULL)
87 goto free_cache_directory;
88 }
89 else {
90 maildir_storage->md_cached = FALSE;
91 maildir_storage->md_cache_directory = NULL;
92 maildir_storage->md_flags_directory = NULL;
93 }
94
95 storage->sto_data = maildir_storage;
96 storage->sto_driver = &maildir_mailstorage_driver;
97
98 return MAIL_NO_ERROR;
99
100 free_cache_directory:
101 free(maildir_storage->md_cache_directory);
102 free_pathname:
103 free(maildir_storage->md_pathname);
104 free:
105 free(maildir_storage);
106 err:
107 return MAIL_ERROR_MEMORY;
108}
109
110static void maildir_mailstorage_uninitialize(struct mailstorage * storage)
111{
112 struct maildir_mailstorage * maildir_storage;
113
114 maildir_storage = storage->sto_data;
115 if (maildir_storage->md_flags_directory != NULL)
116 free(maildir_storage->md_flags_directory);
117 if (maildir_storage->md_cache_directory != NULL)
118 free(maildir_storage->md_cache_directory);
119 free(maildir_storage->md_pathname);
120 free(maildir_storage);
121
122 storage->sto_data = NULL;
123}
124
125static int maildir_mailstorage_connect(struct mailstorage * storage)
126{
127 struct maildir_mailstorage * maildir_storage;
128 mailsession_driver * driver;
129 int r;
130 int res;
131 mailsession * session;
132
133 maildir_storage = storage->sto_data;
134
135 if (maildir_storage->md_cached)
136 driver = maildir_cached_session_driver;
137 else
138 driver = maildir_session_driver;
139
140 session = mailsession_new(driver);
141 if (session == NULL) {
142 res = MAIL_ERROR_MEMORY;
143 goto err;
144 }
145
146 if (maildir_storage->md_cached) {
147 r = mailsession_parameters(session,
148 MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY,
149 maildir_storage->md_cache_directory);
150 if (r != MAIL_NO_ERROR) {
151 res = r;
152 goto free;
153 }
154
155 r = mailsession_parameters(session,
156 MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY,
157 maildir_storage->md_flags_directory);
158 if (r != MAIL_NO_ERROR) {
159 res = r;
160 goto free;
161 }
162 }
163
164 r = mailsession_connect_path(session, maildir_storage->md_pathname);
165 switch (r) {
166 case MAIL_NO_ERROR_NON_AUTHENTICATED:
167 case MAIL_NO_ERROR_AUTHENTICATED:
168 case MAIL_NO_ERROR:
169 break;
170 default:
171 res = r;
172 goto free;
173 }
174
175 storage->sto_session = session;
176
177 return MAIL_NO_ERROR;
178
179 free:
180 mailsession_free(session);
181 err:
182 return res;
183}
184
185static int
186maildir_mailstorage_get_folder_session(struct mailstorage * storage,
187 char * pathname, mailsession ** result)
188{
189 * result = storage->sto_session;
190
191 return MAIL_NO_ERROR;
192}
193
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRSTORAGE_H
37
38#define MAILDIRSTORAGE_H
39
40#include <libetpan/maildirdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 maildir_mailstorage_init is the constructor for a maildir storage.
48
49 @param storage this is the storage to initialize.
50
51 @param pathname is the directory that contains the mailbox.
52
53 @param cached if this value is != 0, a persistant cache will be
54 stored on local system.
55
56 @param cache_directory is the location of the cache
57
58 @param flags_directory is the location of the flags
59*/
60
61int maildir_mailstorage_init(struct mailstorage * storage,
62 char * md_pathname, int md_cached,
63 char * md_cache_directory, char * md_flags_directory);
64
65#ifdef __cplusplus
66}
67#endif
68
69#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxdriver.h"
37
38#include <stdio.h>
39#include <string.h>
40#include <sys/types.h>
41#include <dirent.h>
42#include <unistd.h>
43#include <sys/stat.h>
44#include <ctype.h>
45#include <stdlib.h>
46#include <sys/times.h>
47
48#include "mail.h"
49#include "maildriver_tools.h"
50#include "mailmbox.h"
51#include "mboxdriver_tools.h"
52#include "maildriver.h"
53#include "carray.h"
54#include "mboxdriver_message.h"
55#include "mailmessage.h"
56
57static int mboxdriver_initialize(mailsession * session);
58
59static void mboxdriver_uninitialize(mailsession * session);
60
61static int mboxdriver_parameters(mailsession * session,
62 int id, void * value);
63
64static int mboxdriver_connect_path(mailsession * session, char * path);
65
66static int mboxdriver_logout(mailsession * session);
67
68static int mboxdriver_expunge_folder(mailsession * session);
69
70static int mboxdriver_status_folder(mailsession * session, char * mb,
71 uint32_t * result_messages, uint32_t * result_recent,
72 uint32_t * result_unseen);
73
74static int mboxdriver_messages_number(mailsession * session, char * mb,
75 uint32_t * result);
76
77static int mboxdriver_append_message(mailsession * session,
78 char * message, size_t size);
79
80static int mboxdriver_append_message_flags(mailsession * session,
81 char * message, size_t size, struct mail_flags * flags);
82
83static int mboxdriver_get_messages_list(mailsession * session,
84 struct mailmessage_list ** result);
85
86static int
87mboxdriver_get_envelopes_list(mailsession * session,
88 struct mailmessage_list * env_list);
89
90static int mboxdriver_remove_message(mailsession * session, uint32_t num);
91
92static int mboxdriver_get_message(mailsession * session,
93 uint32_t num, mailmessage ** result);
94
95static int mboxdriver_get_message_by_uid(mailsession * session,
96 const char * uid,
97 mailmessage ** result);
98
99static mailsession_driver local_mbox_session_driver = {
100 .sess_name = "mbox",
101
102 .sess_initialize = mboxdriver_initialize,
103 .sess_uninitialize = mboxdriver_uninitialize,
104
105 .sess_parameters = mboxdriver_parameters,
106
107 .sess_connect_path = mboxdriver_connect_path,
108 .sess_connect_stream = NULL,
109 .sess_starttls = NULL,
110 .sess_login = NULL,
111 .sess_logout = mboxdriver_logout,
112 .sess_noop = NULL,
113
114 .sess_build_folder_name = NULL,
115 .sess_create_folder = NULL,
116 .sess_delete_folder = NULL,
117 .sess_rename_folder = NULL,
118 .sess_check_folder = NULL,
119 .sess_examine_folder = NULL,
120 .sess_select_folder = NULL,
121 .sess_expunge_folder = mboxdriver_expunge_folder,
122 .sess_status_folder = mboxdriver_status_folder,
123 .sess_messages_number = mboxdriver_messages_number,
124 .sess_recent_number = mboxdriver_messages_number,
125 .sess_unseen_number = mboxdriver_messages_number,
126 .sess_list_folders = NULL,
127 .sess_lsub_folders = NULL,
128 .sess_subscribe_folder = NULL,
129 .sess_unsubscribe_folder = NULL,
130
131 .sess_append_message = mboxdriver_append_message,
132 .sess_append_message_flags = mboxdriver_append_message_flags,
133 .sess_copy_message = NULL,
134 .sess_move_message = NULL,
135
136 .sess_get_messages_list = mboxdriver_get_messages_list,
137 .sess_get_envelopes_list = mboxdriver_get_envelopes_list,
138 .sess_remove_message = mboxdriver_remove_message,
139#if 0
140 .sess_search_messages = maildriver_generic_search_messages,
141#endif
142
143 .sess_get_message = mboxdriver_get_message,
144 .sess_get_message_by_uid = mboxdriver_get_message_by_uid,
145};
146
147mailsession_driver * mbox_session_driver = &local_mbox_session_driver;
148
149static inline struct mbox_session_state_data * get_data(mailsession * session)
150{
151 return session->sess_data;
152}
153
154static inline struct mailmbox_folder * get_mbox_session(mailsession * session)
155{
156 return get_data(session)->mbox_folder;
157}
158
159static int mboxdriver_initialize(mailsession * session)
160{
161 struct mbox_session_state_data * data;
162
163 data = malloc(sizeof(* data));
164 if (data == NULL)
165 goto err;
166
167 data->mbox_folder = NULL;
168
169 data->mbox_force_read_only = FALSE;
170 data->mbox_force_no_uid = TRUE;
171
172 session->sess_data = data;
173
174 return MAIL_NO_ERROR;
175
176 err:
177 return MAIL_ERROR_MEMORY;
178}
179
180static void free_state(struct mbox_session_state_data * mbox_data)
181{
182 if (mbox_data->mbox_folder != NULL) {
183 mailmbox_done(mbox_data->mbox_folder);
184 mbox_data->mbox_folder = NULL;
185 }
186}
187
188static void mboxdriver_uninitialize(mailsession * session)
189{
190 struct mbox_session_state_data * data;
191
192 data = get_data(session);
193
194 free_state(data);
195
196 free(data);
197}
198
199static int mboxdriver_parameters(mailsession * session,
200 int id, void * value)
201{
202 struct mbox_session_state_data * data;
203
204 data = get_data(session);
205
206 switch (id) {
207 case MBOXDRIVER_SET_READ_ONLY:
208 {
209 int * param;
210
211 param = value;
212
213 data->mbox_force_read_only = * param;
214 return MAIL_NO_ERROR;
215 }
216
217 case MBOXDRIVER_SET_NO_UID:
218 {
219 int * param;
220
221 param = value;
222
223 data->mbox_force_no_uid = * param;
224 return MAIL_NO_ERROR;
225 }
226 }
227
228 return MAIL_ERROR_INVAL;
229}
230
231
232static int mboxdriver_connect_path(mailsession * session, char * path)
233{
234 struct mbox_session_state_data * mbox_data;
235 struct mailmbox_folder * folder;
236 int r;
237
238 mbox_data = get_data(session);
239
240 if (mbox_data->mbox_folder != NULL)
241 return MAIL_ERROR_BAD_STATE;
242
243 r = mailmbox_init(path,
244 mbox_data->mbox_force_read_only,
245 mbox_data->mbox_force_no_uid,
246 0,
247 &folder);
248
249 if (r != MAILMBOX_NO_ERROR)
250 return mboxdriver_mbox_error_to_mail_error(r);
251
252 mbox_data->mbox_folder = folder;
253
254 return MAIL_NO_ERROR;
255}
256
257static int mboxdriver_logout(mailsession * session)
258{
259 struct mbox_session_state_data * mbox_data;
260
261 mbox_data = get_data(session);
262
263 if (mbox_data->mbox_folder == NULL)
264 return MAIL_ERROR_BAD_STATE;
265
266 free_state(mbox_data);
267
268 mbox_data->mbox_folder = NULL;
269
270 return MAIL_NO_ERROR;
271}
272
273static int mboxdriver_expunge_folder(mailsession * session)
274{
275 int r;
276 struct mbox_session_state_data * mbox_data;
277
278 mbox_data = get_data(session);
279
280 if (mbox_data->mbox_folder == NULL)
281 return MAIL_ERROR_BAD_STATE;
282
283 r = mailmbox_expunge(mbox_data->mbox_folder);
284 if (r != MAILMBOX_NO_ERROR)
285 return mboxdriver_mbox_error_to_mail_error(r);
286
287 return MAIL_NO_ERROR;
288}
289
290static int mboxdriver_status_folder(mailsession * session, char * mb,
291 uint32_t * result_messages, uint32_t * result_recent,
292 uint32_t * result_unseen)
293{
294 uint32_t count;
295 int r;
296
297 r = mboxdriver_messages_number(session, mb, &count);
298 if (r != MAIL_NO_ERROR)
299 return r;
300
301 * result_messages = count;
302 * result_recent = count;
303 * result_unseen = count;
304
305 return MAIL_NO_ERROR;
306}
307
308static int mboxdriver_messages_number(mailsession * session, char * mb,
309 uint32_t * result)
310{
311 struct mailmbox_folder * folder;
312 int r;
313
314 folder = get_mbox_session(session);
315 if (folder == NULL)
316 return MAIL_ERROR_STATUS;
317
318 r = mailmbox_validate_read_lock(folder);
319 if (r != MAIL_NO_ERROR)
320 return r;
321
322 mailmbox_read_unlock(folder);
323
324 * result = carray_count(folder->mb_tab) - folder->mb_deleted_count;
325
326 return MAILMBOX_NO_ERROR;
327}
328
329/* messages operations */
330
331static int mboxdriver_append_message(mailsession * session,
332 char * message, size_t size)
333{
334 int r;
335 struct mailmbox_folder * folder;
336
337 folder = get_mbox_session(session);
338 if (folder == NULL)
339 return MAIL_ERROR_APPEND;
340
341 r = mailmbox_append_message(folder, message, size);
342
343 switch (r) {
344 case MAILMBOX_ERROR_FILE:
345 return MAIL_ERROR_DISKSPACE;
346 default:
347 return mboxdriver_mbox_error_to_mail_error(r);
348 }
349}
350
351static int mboxdriver_append_message_flags(mailsession * session,
352 char * message, size_t size, struct mail_flags * flags)
353{
354 return mboxdriver_append_message(session, message, size);
355}
356
357static int mboxdriver_get_messages_list(mailsession * session,
358 struct mailmessage_list ** result)
359{
360 struct mailmbox_folder * folder;
361 int res;
362
363 folder = get_mbox_session(session);
364 if (folder == NULL) {
365 res = MAIL_ERROR_BAD_STATE;
366 goto err;
367 }
368
369 return mbox_get_messages_list(folder, session, mbox_message_driver, result);
370
371 err:
372 return res;
373}
374
375static int
376mboxdriver_get_envelopes_list(mailsession * session,
377 struct mailmessage_list * env_list)
378{
379 struct mailmbox_folder * folder;
380 unsigned int i;
381 int r;
382 int res;
383
384 folder = get_mbox_session(session);
385 if (folder == NULL) {
386 res = MAIL_ERROR_BAD_STATE;
387 goto err;
388 }
389
390 r = mailmbox_validate_read_lock(folder);
391 if (r != MAILMBOX_NO_ERROR) {
392 res = mboxdriver_mbox_error_to_mail_error(r);
393 goto err;
394 }
395
396 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
397 mailmessage * msg;
398 struct mailimf_fields * fields;
399 char * headers;
400 size_t headers_len;
401 size_t cur_token;
402
403 msg = carray_get(env_list->msg_tab, i);
404 if (msg == NULL)
405 continue;
406
407 if (msg->msg_fields != NULL)
408 continue;
409
410 r = mailmbox_fetch_msg_headers_no_lock(folder,
411 msg->msg_index, &headers, &headers_len);
412 if (r != MAILMBOX_NO_ERROR) {
413 res = mboxdriver_mbox_error_to_mail_error(r);
414 goto unlock;
415 }
416
417 cur_token = 0;
418 r = mailimf_envelope_fields_parse(headers, headers_len,
419 &cur_token, &fields);
420
421 if (r != MAILIMF_NO_ERROR)
422 continue;
423
424 msg->msg_fields = fields;
425 }
426
427 mailmbox_read_unlock(folder);
428
429 return MAIL_NO_ERROR;
430
431 unlock:
432 mailmbox_read_unlock(folder);
433 err:
434 return res;
435}
436
437
438static int mboxdriver_remove_message(mailsession * session, uint32_t num)
439{
440 int r;
441 struct mailmbox_folder * folder;
442
443 folder = get_mbox_session(session);
444 if (folder == NULL)
445 return MAIL_ERROR_DELETE;
446
447 r = mailmbox_delete_msg(folder, num);
448
449 return mboxdriver_mbox_error_to_mail_error(r);
450}
451
452static int mboxdriver_get_message(mailsession * session,
453 uint32_t num, mailmessage ** result)
454{
455 mailmessage * msg_info;
456 int r;
457
458 msg_info = mailmessage_new();
459 if (msg_info == NULL)
460 return MAIL_ERROR_MEMORY;
461
462 r = mailmessage_init(msg_info, session, mbox_message_driver, num, 0);
463 if (r != MAIL_NO_ERROR) {
464 mailmessage_free(msg_info);
465 return r;
466 }
467
468 * result = msg_info;
469
470 return MAIL_NO_ERROR;
471}
472
473static int mboxdriver_get_message_by_uid(mailsession * session,
474 const char * uid,
475 mailmessage ** result)
476{
477 uint32_t num;
478 char * p;
479 chashdatum key;
480 chashdatum data;
481 struct mailmbox_msg_info * info;
482 struct mailmbox_folder * folder;
483 int r;
484
485 if (uid == NULL)
486 return MAIL_ERROR_INVAL;
487
488 num = strtoul(uid, &p, 10);
489 if (p == uid || * p != '-')
490 return MAIL_ERROR_INVAL;
491
492 folder = get_mbox_session(session);
493 if (folder == NULL)
494 return MAIL_ERROR_BAD_STATE;
495
496 key.data = &num;
497 key.len = sizeof(num);
498
499 r = chash_get(folder->mb_hash, &key, &data);
500 if (r == 0) {
501 char * body_len_p = p + 1;
502 size_t body_len;
503
504 info = data.data;
505 /* Check if the cached message has the same UID */
506 body_len = strtoul(body_len_p, &p, 10);
507 if (p == body_len_p || * p != '\0')
508 return MAIL_ERROR_INVAL;
509
510 if (body_len == info->msg_body_len)
511 return mboxdriver_get_message(session, num, result);
512 }
513
514 return MAIL_ERROR_MSG_NOT_FOUND;
515}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_H
37
38#define MBOXDRIVER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mboxdriver_types.h>
45
46extern mailsession_driver * mbox_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxdriver_cached.h"
37
38#include <stdio.h>
39#include <string.h>
40#include <dirent.h>
41#include <unistd.h>
42#include <ctype.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <fcntl.h>
46#include <stdlib.h>
47
48#include "mail.h"
49#include "mail_cache_db.h"
50#include "mboxdriver.h"
51#include "mboxdriver_tools.h"
52#include "maildriver_tools.h"
53#include "mailmbox.h"
54#include "maildriver.h"
55#include "carray.h"
56#include "generic_cache.h"
57#include "imfcache.h"
58#include "mboxdriver_cached_message.h"
59#include "libetpan-config.h"
60
61static int mboxdriver_cached_initialize(mailsession * session);
62
63static void mboxdriver_cached_uninitialize(mailsession * session);
64
65static int mboxdriver_cached_parameters(mailsession * session,
66 int id, void * value);
67
68static int mboxdriver_cached_connect_path(mailsession * session, char * path);
69
70static int mboxdriver_cached_logout(mailsession * session);
71
72static int mboxdriver_cached_check_folder(mailsession * session);
73
74static int mboxdriver_cached_expunge_folder(mailsession * session);
75
76static int mboxdriver_cached_status_folder(mailsession * session, char * mb,
77 uint32_t * result_messages, uint32_t * result_recent,
78 uint32_t * result_unseen);
79static int mboxdriver_cached_messages_number(mailsession * session, char * mb,
80 uint32_t * result);
81static int mboxdriver_cached_recent_number(mailsession * session, char * mb,
82 uint32_t * result);
83static int mboxdriver_cached_unseen_number(mailsession * session, char * mb,
84 uint32_t * result);
85
86static int mboxdriver_cached_append_message(mailsession * session,
87 char * message, size_t size);
88
89static int mboxdriver_cached_append_message_flags(mailsession * session,
90 char * message, size_t size, struct mail_flags * flags);
91
92static int
93mboxdriver_cached_get_messages_list(mailsession * session,
94 struct mailmessage_list ** result);
95
96static int
97mboxdriver_cached_get_envelopes_list(mailsession * session,
98 struct mailmessage_list * env_list);
99
100static int mboxdriver_cached_remove_message(mailsession * session,
101 uint32_t num);
102
103static int mboxdriver_cached_get_message(mailsession * session,
104 uint32_t num, mailmessage ** result);
105
106static int mboxdriver_cached_get_message_by_uid(mailsession * session,
107 const char * uid,
108 mailmessage ** result);
109
110static mailsession_driver local_mbox_cached_session_driver = {
111 .sess_name = "mbox-cached",
112
113 .sess_initialize = mboxdriver_cached_initialize,
114 .sess_uninitialize = mboxdriver_cached_uninitialize,
115
116 .sess_parameters = mboxdriver_cached_parameters,
117
118 .sess_connect_path = mboxdriver_cached_connect_path,
119 .sess_connect_stream = NULL,
120 .sess_starttls = NULL,
121 .sess_login = NULL,
122 .sess_logout = mboxdriver_cached_logout,
123 .sess_noop = NULL,
124
125 .sess_build_folder_name = NULL,
126 .sess_create_folder = NULL,
127 .sess_delete_folder = NULL,
128 .sess_rename_folder = NULL,
129 .sess_check_folder = mboxdriver_cached_check_folder,
130 .sess_examine_folder = NULL,
131 .sess_select_folder = NULL,
132 .sess_expunge_folder = mboxdriver_cached_expunge_folder,
133 .sess_status_folder = mboxdriver_cached_status_folder,
134 .sess_messages_number = mboxdriver_cached_messages_number,
135 .sess_recent_number = mboxdriver_cached_recent_number,
136 .sess_unseen_number = mboxdriver_cached_unseen_number,
137 .sess_list_folders = NULL,
138 .sess_lsub_folders = NULL,
139 .sess_subscribe_folder = NULL,
140 .sess_unsubscribe_folder = NULL,
141
142 .sess_append_message = mboxdriver_cached_append_message,
143 .sess_append_message_flags = mboxdriver_cached_append_message_flags,
144
145 .sess_copy_message = NULL,
146 .sess_move_message = NULL,
147
148 .sess_get_messages_list = mboxdriver_cached_get_messages_list,
149 .sess_get_envelopes_list = mboxdriver_cached_get_envelopes_list,
150 .sess_remove_message = mboxdriver_cached_remove_message,
151#if 0
152 .sess_search_messages = maildriver_generic_search_messages,
153#endif
154
155 .sess_get_message = mboxdriver_cached_get_message,
156 .sess_get_message_by_uid = mboxdriver_cached_get_message_by_uid,
157};
158
159mailsession_driver * mbox_cached_session_driver =
160&local_mbox_cached_session_driver;
161
162
163#define ENV_NAME "env.db"
164#define FLAGS_NAME "flags.db"
165
166
167
168static int mbox_error_to_mail_error(int error)
169{
170 switch (error) {
171 case MAILMBOX_NO_ERROR:
172 return MAIL_NO_ERROR;
173
174 case MAILMBOX_ERROR_PARSE:
175 return MAIL_ERROR_PARSE;
176
177 case MAILMBOX_ERROR_INVAL:
178 return MAIL_ERROR_INVAL;
179
180 case MAILMBOX_ERROR_FILE_NOT_FOUND:
181 return MAIL_ERROR_PARSE;
182
183 case MAILMBOX_ERROR_MEMORY:
184 return MAIL_ERROR_MEMORY;
185
186 case MAILMBOX_ERROR_TEMPORARY_FILE:
187 return MAIL_ERROR_PARSE;
188
189 case MAILMBOX_ERROR_FILE:
190 return MAIL_ERROR_FILE;
191
192 case MAILMBOX_ERROR_MSG_NOT_FOUND:
193 return MAIL_ERROR_MSG_NOT_FOUND;
194
195 case MAILMBOX_ERROR_READONLY:
196 return MAIL_ERROR_READONLY;
197
198 default:
199 return MAIL_ERROR_INVAL;
200 }
201}
202
203
204
205
206static inline struct mbox_cached_session_state_data *
207get_cached_data(mailsession * session)
208{
209 return session->sess_data;
210}
211
212static inline mailsession * get_ancestor(mailsession * session)
213{
214 return get_cached_data(session)->mbox_ancestor;
215}
216
217static inline struct mbox_session_state_data *
218get_ancestor_data(mailsession * session)
219{
220 return get_ancestor(session)->sess_data;
221}
222
223static inline struct mailmbox_folder *
224get_mbox_session(mailsession * session)
225{
226 return get_ancestor_data(session)->mbox_folder;
227}
228
229static int mboxdriver_cached_initialize(mailsession * session)
230{
231 struct mbox_cached_session_state_data * cached_data;
232 struct mbox_session_state_data * mbox_data;
233
234 cached_data = malloc(sizeof(* cached_data));
235 if (cached_data == NULL)
236 goto err;
237
238 cached_data->mbox_flags_store = mail_flags_store_new();
239 if (cached_data->mbox_flags_store == NULL)
240 goto free;
241
242 cached_data->mbox_ancestor = mailsession_new(mbox_session_driver);
243 if (cached_data->mbox_ancestor == NULL)
244 goto free_store;
245
246 cached_data->mbox_quoted_mb = NULL;
247 /*
248 UID must be enabled to take advantage of the cache
249 */
250 mbox_data = cached_data->mbox_ancestor->sess_data;
251 mbox_data->mbox_force_no_uid = FALSE;
252
253 session->sess_data = cached_data;
254
255 return MAIL_NO_ERROR;
256
257 free_store:
258 mail_flags_store_free(cached_data->mbox_flags_store);
259 free:
260 free(cached_data);
261 err:
262 return MAIL_ERROR_MEMORY;
263}
264
265static void free_state(struct mbox_cached_session_state_data * mbox_data)
266{
267 if (mbox_data->mbox_quoted_mb) {
268 free(mbox_data->mbox_quoted_mb);
269 mbox_data->mbox_quoted_mb = NULL;
270 }
271}
272
273static int mbox_flags_store_process(char * flags_directory, char * quoted_mb,
274 struct mail_flags_store * flags_store)
275{
276 char filename_flags[PATH_MAX];
277 struct mail_cache_db * cache_db_flags;
278 MMAPString * mmapstr;
279 unsigned int i;
280 int r;
281 int res;
282
283 if (carray_count(flags_store->fls_tab) == 0)
284 return MAIL_NO_ERROR;
285
286 if (quoted_mb == NULL)
287 return MAIL_NO_ERROR;
288
289 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
290 flags_directory, MAIL_DIR_SEPARATOR, quoted_mb,
291 MAIL_DIR_SEPARATOR, FLAGS_NAME);
292
293 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
294 if (r < 0) {
295 res = MAIL_ERROR_FILE;
296 goto err;
297 }
298
299 mmapstr = mmap_string_new("");
300 if (mmapstr == NULL) {
301 res = MAIL_ERROR_MEMORY;
302 goto close_db_flags;
303 }
304
305 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
306 mailmessage * msg;
307
308 msg = carray_get(flags_store->fls_tab, i);
309
310 r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr,
311 msg->msg_uid, msg->msg_flags);
312 if (r != MAIL_NO_ERROR) {
313 /* ignore errors */
314 }
315 }
316
317 mmap_string_free(mmapstr);
318 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
319
320 mail_flags_store_clear(flags_store);
321
322 return MAIL_NO_ERROR;
323
324 close_db_flags:
325 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
326 err:
327 return res;
328}
329
330static void mboxdriver_cached_uninitialize(mailsession * session)
331{
332 struct mbox_cached_session_state_data * data;
333
334 data = get_cached_data(session);
335
336 mbox_flags_store_process(data->mbox_flags_directory,
337 data->mbox_quoted_mb,
338 data->mbox_flags_store);
339
340 mail_flags_store_free(data->mbox_flags_store);
341
342 free_state(data);
343 mailsession_free(data->mbox_ancestor);
344 free(data);
345
346 session->sess_data = NULL;
347}
348
349static int mboxdriver_cached_parameters(mailsession * session,
350 int id, void * value)
351{
352 struct mbox_cached_session_state_data * data;
353 int r;
354
355 data = get_cached_data(session);
356
357 switch (id) {
358 case MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY:
359 strncpy(data->mbox_cache_directory, value, PATH_MAX);
360 data->mbox_cache_directory[PATH_MAX - 1] = '\0';
361
362 r = generic_cache_create_dir(data->mbox_cache_directory);
363 if (r != MAIL_NO_ERROR)
364 return r;
365
366 return MAIL_NO_ERROR;
367
368 case MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY:
369 strncpy(data->mbox_flags_directory, value, PATH_MAX);
370 data->mbox_flags_directory[PATH_MAX - 1] = '\0';
371
372 r = generic_cache_create_dir(data->mbox_flags_directory);
373 if (r != MAIL_NO_ERROR)
374 return r;
375
376 return MAIL_NO_ERROR;
377
378 case MBOXDRIVER_SET_NO_UID:
379 return MAIL_ERROR_INVAL;
380
381 default:
382 return mailsession_parameters(data->mbox_ancestor, id, value);
383 }
384}
385
386
387static int get_cache_directory(mailsession * session,
388 char * path, char ** result)
389{
390 char * quoted_mb;
391 char dirname[PATH_MAX];
392 int res;
393 int r;
394 struct mbox_cached_session_state_data * cached_data;
395
396 cached_data = get_cached_data(session);
397
398 quoted_mb = maildriver_quote_mailbox(path);
399 if (quoted_mb == NULL) {
400 res = MAIL_ERROR_MEMORY;
401 goto err;
402 }
403
404 snprintf(dirname, PATH_MAX, "%s%c%s",
405 cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR, quoted_mb);
406
407 r = generic_cache_create_dir(dirname);
408 if (r != MAIL_NO_ERROR) {
409 res = r;
410 goto free;
411 }
412
413 snprintf(dirname, PATH_MAX, "%s%c%s",
414 cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, quoted_mb);
415
416 r = generic_cache_create_dir(dirname);
417 if (r != MAIL_NO_ERROR) {
418 res = r;
419 goto free;
420 }
421
422 * result = quoted_mb;
423
424 return MAIL_NO_ERROR;
425
426 free:
427 free(quoted_mb);
428 err:
429 return res;
430}
431
432
433
434
435#define FILENAME_MAX_UID "max-uid"
436
437/* write max uid current value */
438
439static int write_max_uid_value(mailsession * session)
440{
441 int r;
442 char filename[PATH_MAX];
443 FILE * f;
444 int res;
445
446#if 0
447 struct mbox_session_state_data * mbox_data;
448#endif
449 struct mbox_cached_session_state_data * cached_data;
450 int fd;
451
452 MMAPString * mmapstr;
453 size_t cur_token;
454 struct mailmbox_folder * folder;
455
456 /* expunge the mailbox */
457
458#if 0
459 mbox_data = get_ancestor(session)->data;
460#endif
461 folder = get_mbox_session(session);
462
463 r = mailmbox_validate_write_lock(folder);
464 if (r != MAILMBOX_NO_ERROR) {
465 res = mbox_error_to_mail_error(r);
466 goto err;
467 }
468
469 r = mailmbox_expunge_no_lock(folder);
470 if (r != MAILMBOX_NO_ERROR) {
471 res = r;
472 goto unlock;
473 }
474
475 cached_data = get_cached_data(session);
476
477 snprintf(filename, PATH_MAX, "%s%c%s%c%s",
478 cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR,
479 cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID);
480
481 fd = creat(filename, S_IRUSR | S_IWUSR);
482 if (fd < 0) {
483 res = MAIL_ERROR_FILE;
484 goto err;
485 }
486
487 f = fdopen(fd, "w");
488 if (f == NULL) {
489 close(fd);
490 res = MAIL_ERROR_FILE;
491 goto unlock;
492 }
493
494 mmapstr = mmap_string_new("");
495 if (mmapstr == NULL) {
496 res = MAIL_ERROR_MEMORY;
497 goto close;
498 }
499
500 r = mail_serialize_clear(mmapstr, &cur_token);
501 if (r != MAIL_NO_ERROR) {
502 res = r;
503 goto free_mmapstr;
504 }
505
506 r = mailimf_cache_int_write(mmapstr, &cur_token,
507 folder->mb_written_uid);
508 if (r != MAIL_NO_ERROR) {
509 res = r;
510 goto free_mmapstr;
511 }
512
513 fwrite(mmapstr->str, 1, mmapstr->len, f);
514
515 mmap_string_free(mmapstr);
516 fclose(f);
517 mailmbox_write_unlock(folder);
518
519 return MAIL_NO_ERROR;
520
521 free_mmapstr:
522 mmap_string_free(mmapstr);
523 close:
524 fclose(f);
525 unlock:
526 mailmbox_read_unlock(folder);
527 err:
528 return res;
529}
530
531static int read_max_uid_value(mailsession * session, uint32_t * result)
532{
533 int r;
534 char filename[PATH_MAX];
535 FILE * f;
536 uint32_t written_uid;
537 int res;
538
539 struct mbox_cached_session_state_data * cached_data;
540
541 MMAPString * mmapstr;
542 size_t cur_token;
543 char buf[sizeof(uint32_t)];
544 size_t read_size;
545
546 cached_data = get_cached_data(session);
547
548 snprintf(filename, PATH_MAX, "%s%c%s%c%s",
549 cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR,
550 cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID);
551
552 f = fopen(filename, "r");
553 if (f == NULL) {
554 res = MAIL_ERROR_FILE;
555 goto err;
556 }
557
558 read_size = fread(buf, 1, sizeof(uint32_t), f);
559
560 mmapstr = mmap_string_new_len(buf, read_size);
561 if (mmapstr == NULL) {
562 res = MAIL_ERROR_MEMORY;
563 goto close;
564 }
565
566 cur_token = 0;
567
568 r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid);
569 if (r != MAIL_NO_ERROR) {
570 fclose(f);
571 res = r;
572 goto free_mmapstr;
573 }
574
575 mmap_string_free(mmapstr);
576 fclose(f);
577
578 * result = written_uid;
579
580 return MAIL_NO_ERROR;
581
582 free_mmapstr:
583 mmap_string_free(mmapstr);
584 close:
585 fclose(f);
586 err:
587 return res;
588}
589
590static int mboxdriver_cached_connect_path(mailsession * session, char * path)
591{
592 int r;
593 int res;
594 char * quoted_mb;
595 struct mbox_cached_session_state_data * cached_data;
596 struct mbox_session_state_data * ancestor_data;
597 struct mailmbox_folder * folder;
598 uint32_t written_uid;
599
600 folder = get_mbox_session(session);
601 if (folder != NULL) {
602 res = MAIL_ERROR_BAD_STATE;
603 goto err;
604 }
605
606 r = get_cache_directory(session, path, &quoted_mb);
607 if (r != MAIL_NO_ERROR) {
608 res = r;
609 goto err;
610 }
611
612 cached_data = get_cached_data(session);
613 free_state(cached_data);
614
615 cached_data->mbox_quoted_mb = quoted_mb;
616
617 written_uid = 0;
618 r = read_max_uid_value(session, &written_uid);
619 /* ignore errors */
620
621 ancestor_data = get_ancestor_data(session);
622
623 r = mailmbox_init(path,
624 ancestor_data->mbox_force_read_only,
625 ancestor_data->mbox_force_no_uid,
626 written_uid,
627 &folder);
628
629 if (r != MAILMBOX_NO_ERROR) {
630 cached_data->mbox_quoted_mb = NULL;
631
632 res = mboxdriver_mbox_error_to_mail_error(r);
633 goto free;
634 }
635
636 ancestor_data->mbox_folder = folder;
637
638 return MAIL_NO_ERROR;
639
640 free:
641 free(quoted_mb);
642 err:
643 return res;
644}
645
646
647static int mboxdriver_cached_logout(mailsession * session)
648{
649 struct mbox_cached_session_state_data * cached_data;
650 int r;
651
652 r = write_max_uid_value(session);
653
654 cached_data = get_cached_data(session);
655
656 mbox_flags_store_process(cached_data->mbox_flags_directory,
657 cached_data->mbox_quoted_mb,
658 cached_data->mbox_flags_store);
659
660 r = mailsession_logout(get_ancestor(session));
661 if (r != MAIL_NO_ERROR)
662 return r;
663
664 free_state(cached_data);
665
666 return MAIL_NO_ERROR;
667}
668
669static int mboxdriver_cached_check_folder(mailsession * session)
670{
671 struct mbox_cached_session_state_data * cached_data;
672
673 cached_data = get_cached_data(session);
674
675 mbox_flags_store_process(cached_data->mbox_flags_directory,
676 cached_data->mbox_quoted_mb,
677 cached_data->mbox_flags_store);
678
679 return MAIL_NO_ERROR;
680}
681
682static int mboxdriver_cached_expunge_folder(mailsession * session)
683{
684 struct mailmbox_folder * folder;
685 int res;
686 char filename_flags[PATH_MAX];
687 struct mail_cache_db * cache_db_flags;
688 MMAPString * mmapstr;
689 struct mbox_cached_session_state_data * data;
690 int r;
691 unsigned int i;
692
693 folder = get_mbox_session(session);
694 if (folder == NULL) {
695 res = MAIL_ERROR_BAD_STATE;
696 goto err;
697 }
698
699 data = get_cached_data(session);
700 if (data->mbox_quoted_mb == NULL) {
701 res = MAIL_ERROR_BAD_STATE;
702 goto err;
703 }
704
705 mbox_flags_store_process(data->mbox_flags_directory,
706 data->mbox_quoted_mb,
707 data->mbox_flags_store);
708
709 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
710 data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb,
711 MAIL_DIR_SEPARATOR, FLAGS_NAME);
712
713 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
714 if (r < 0) {
715 res = MAIL_ERROR_FILE;
716 goto err;
717 }
718
719 mmapstr = mmap_string_new("");
720 if (mmapstr == NULL) {
721 res = MAIL_ERROR_MEMORY;
722 goto close_db_flags;
723 }
724
725 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
726 struct mailmbox_msg_info * msg_info;
727 struct mail_flags * flags;
728
729 msg_info = carray_get(folder->mb_tab, i);
730 if (msg_info == NULL)
731 continue;
732
733 if (msg_info->msg_deleted)
734 continue;
735
736 r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
737 session, msg_info->msg_uid, &flags);
738 if (r != MAIL_NO_ERROR)
739 continue;
740
741 if (flags->fl_flags & MAIL_FLAG_DELETED) {
742 r = mailmbox_delete_msg(folder, msg_info->msg_uid);
743 }
744
745 mail_flags_free(flags);
746 }
747
748 mmap_string_free(mmapstr);
749 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
750
751 r = mailmbox_expunge(folder);
752
753 return MAIL_NO_ERROR;
754
755 close_db_flags:
756 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
757 err:
758 return res;
759}
760
761static int mboxdriver_cached_status_folder(mailsession * session, char * mb,
762 uint32_t * result_messages, uint32_t * result_recent,
763 uint32_t * result_unseen)
764{
765 struct mailmbox_folder * folder;
766 int res;
767 char filename_flags[PATH_MAX];
768 struct mail_cache_db * cache_db_flags;
769 MMAPString * mmapstr;
770 struct mbox_cached_session_state_data * data;
771 int r;
772 unsigned int i;
773 uint32_t recent;
774 uint32_t unseen;
775 uint32_t num;
776
777 num = 0;
778 recent = 0;
779 unseen = 0;
780
781 folder = get_mbox_session(session);
782 if (folder == NULL) {
783 res = MAIL_ERROR_BAD_STATE;
784 goto err;
785 }
786
787 data = get_cached_data(session);
788 if (data->mbox_quoted_mb == NULL) {
789 res = MAIL_ERROR_BAD_STATE;
790 goto err;
791 }
792
793 r = mailmbox_validate_read_lock(folder);
794 if (r != MAIL_NO_ERROR) {
795 res = MAIL_ERROR_BAD_STATE;
796 goto err;
797 }
798
799 mailmbox_read_unlock(folder);
800
801 mbox_flags_store_process(data->mbox_flags_directory, data->mbox_quoted_mb,
802 data->mbox_flags_store);
803
804 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
805 data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb,
806 MAIL_DIR_SEPARATOR, FLAGS_NAME);
807
808 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
809 if (r < 0) {
810 res = MAIL_ERROR_FILE;
811 goto err;
812 }
813
814 mmapstr = mmap_string_new("");
815 if (mmapstr == NULL) {
816 res = MAIL_ERROR_MEMORY;
817 goto close_db_flags;
818 }
819
820 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
821 struct mailmbox_msg_info * msg_info;
822 struct mail_flags * flags;
823
824 msg_info = carray_get(folder->mb_tab, i);
825 if (msg_info == NULL)
826 continue;
827
828 if (msg_info->msg_deleted)
829 continue;
830
831 r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
832 session, msg_info->msg_uid, &flags);
833 if (r != MAIL_NO_ERROR) {
834 recent ++;
835 unseen ++;
836 num ++;
837 continue;
838 }
839
840 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
841 recent ++;
842 }
843 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
844 unseen ++;
845 }
846
847 num ++;
848
849 mail_flags_free(flags);
850 }
851
852 mmap_string_free(mmapstr);
853 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
854
855 * result_messages = num;
856 * result_recent = recent;
857 * result_unseen = unseen;
858
859 return MAIL_NO_ERROR;
860
861 close_db_flags:
862 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
863 err:
864 return res;
865}
866
867static int mboxdriver_cached_messages_number(mailsession * session, char * mb,
868 uint32_t * result)
869{
870 return mailsession_messages_number(get_ancestor(session), mb, result);
871}
872
873
874static int mboxdriver_cached_recent_number(mailsession * session, char * mb,
875 uint32_t * result)
876{
877 uint32_t messages;
878 uint32_t recent;
879 uint32_t unseen;
880 int r;
881
882 r = mboxdriver_cached_status_folder(session, mb, &messages, &recent, &unseen);
883 if (r != MAIL_NO_ERROR)
884 return r;
885
886 * result = recent;
887
888 return MAIL_NO_ERROR;
889}
890
891static int mboxdriver_cached_unseen_number(mailsession * session, char * mb,
892 uint32_t * result)
893{
894 uint32_t messages;
895 uint32_t recent;
896 uint32_t unseen;
897 int r;
898
899 r = mboxdriver_cached_status_folder(session, mb,
900 &messages, &recent, &unseen);
901 if (r != MAIL_NO_ERROR)
902 return r;
903
904 * result = unseen;
905
906 return MAIL_NO_ERROR;
907}
908
909/* messages operations */
910
911static int mboxdriver_cached_append_message(mailsession * session,
912 char * message, size_t size)
913{
914 return mboxdriver_cached_append_message_flags(session,
915 message, size, NULL);
916}
917
918static int mboxdriver_cached_append_message_flags(mailsession * session,
919 char * message, size_t size, struct mail_flags * flags)
920{
921 int r;
922 struct mailmbox_folder * folder;
923 struct mbox_cached_session_state_data * data;
924 unsigned int uid;
925 struct mailmbox_msg_info * msg_info;
926 chashdatum key;
927 chashdatum value;
928 struct mail_cache_db * cache_db_flags;
929 char filename_flags[PATH_MAX];
930 MMAPString * mmapstr;
931 char keyname[PATH_MAX];
932
933 folder = get_mbox_session(session);
934 if (folder == NULL)
935 return MAIL_ERROR_APPEND;
936
937 r = mailmbox_append_message_uid(folder, message, size, &uid);
938
939 switch (r) {
940 case MAILMBOX_ERROR_FILE:
941 return MAIL_ERROR_DISKSPACE;
942 case MAILMBOX_NO_ERROR:
943 break;
944 default:
945 return mboxdriver_mbox_error_to_mail_error(r);
946 }
947
948 /* could store in flags store instead */
949
950 if (flags == NULL)
951 goto exit;
952
953 key.data = &uid;
954 key.len = sizeof(uid);
955 r = chash_get(folder->mb_hash, &key, &value);
956 if (r < 0)
957 goto exit;
958
959 msg_info = value.data;
960
961 data = get_cached_data(session);
962
963 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
964 data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb,
965 MAIL_DIR_SEPARATOR, FLAGS_NAME);
966
967 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
968 if (r < 0)
969 goto exit;
970
971 mmapstr = mmap_string_new("");
972 if (mmapstr == NULL)
973 goto close_db_flags;
974
975 snprintf(keyname, PATH_MAX, "%u-%lu", uid,
976 (unsigned long) msg_info->msg_body_len);
977
978 r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags);
979
980 mmap_string_free(mmapstr);
981 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
982
983 if (r != MAIL_NO_ERROR)
984 goto exit;
985
986 return MAIL_NO_ERROR;
987
988 close_db_flags:
989 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
990 exit:
991 return MAIL_NO_ERROR;
992}
993
994static int
995mboxdriver_cached_get_messages_list(mailsession * session,
996 struct mailmessage_list ** result)
997{
998 struct mailmbox_folder * folder;
999 int res;
1000
1001 folder = get_mbox_session(session);
1002 if (folder == NULL) {
1003 res = MAIL_ERROR_BAD_STATE;
1004 goto err;
1005 }
1006
1007 return mbox_get_uid_messages_list(folder,
1008 session, mbox_cached_message_driver, result);
1009
1010 err:
1011 return res;
1012}
1013
1014static int
1015get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
1016 mailsession * session, uint32_t num,
1017 struct mailimf_fields ** result)
1018{
1019 int r;
1020 char keyname[PATH_MAX];
1021 struct mailimf_fields * fields;
1022 int res;
1023 struct mailmbox_msg_info * info;
1024 struct mailmbox_folder * folder;
1025 chashdatum key;
1026 chashdatum data;
1027
1028 folder = get_mbox_session(session);
1029 if (folder == NULL) {
1030 res = MAIL_ERROR_BAD_STATE;
1031 goto err;
1032 }
1033
1034 key.data = &num;
1035 key.len = sizeof(num);
1036
1037 r = chash_get(folder->mb_hash, &key, &data);
1038 if (r < 0) {
1039 res = MAIL_ERROR_MSG_NOT_FOUND;
1040 goto err;
1041 }
1042
1043 info = data.data;
1044
1045 snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num,
1046 (unsigned long) info->msg_body_len);
1047
1048 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
1049 if (r != MAIL_NO_ERROR) {
1050 res = r;
1051 goto err;
1052 }
1053
1054 * result = fields;
1055
1056 return MAIL_NO_ERROR;
1057
1058 err:
1059 return res;
1060}
1061
1062static int
1063write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
1064 mailsession * session, uint32_t num,
1065 struct mailimf_fields * fields)
1066{
1067 int r;
1068 char keyname[PATH_MAX];
1069 int res;
1070 struct mailmbox_msg_info * info;
1071 struct mailmbox_folder * folder;
1072 chashdatum key;
1073 chashdatum data;
1074
1075 folder = get_mbox_session(session);
1076 if (folder == NULL) {
1077 res = MAIL_ERROR_BAD_STATE;
1078 goto err;
1079 }
1080
1081 key.data = &num;
1082 key.len = sizeof(num);
1083
1084 r = chash_get(folder->mb_hash, &key, &data);
1085 if (r < 0) {
1086 res = MAIL_ERROR_MSG_NOT_FOUND;
1087 goto err;
1088 }
1089
1090 info = data.data;
1091
1092 snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num,
1093 (unsigned long) info->msg_body_len);
1094
1095 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
1096 if (r != MAIL_NO_ERROR) {
1097 res = r;
1098 goto err;
1099 }
1100
1101 return MAIL_NO_ERROR;
1102
1103 err:
1104 return res;
1105}
1106
1107static int
1108mboxdriver_cached_get_envelopes_list(mailsession * session,
1109 struct mailmessage_list * env_list)
1110{
1111 int r;
1112 unsigned int i;
1113 struct mbox_cached_session_state_data * cached_data;
1114 char filename_env[PATH_MAX];
1115 char filename_flags[PATH_MAX];
1116 struct mail_cache_db * cache_db_env;
1117 struct mail_cache_db * cache_db_flags;
1118 MMAPString * mmapstr;
1119 int res;
1120 struct mailmbox_folder * folder;
1121
1122 folder = get_mbox_session(session);
1123 if (folder == NULL) {
1124 res = MAIL_ERROR_BAD_STATE;
1125 goto err;
1126 }
1127
1128 cached_data = get_cached_data(session);
1129 if (cached_data->mbox_quoted_mb == NULL) {
1130 res = MAIL_ERROR_BAD_STATE;
1131 goto err;
1132 }
1133
1134 mbox_flags_store_process(cached_data->mbox_flags_directory,
1135 cached_data->mbox_quoted_mb,
1136 cached_data->mbox_flags_store);
1137
1138 mmapstr = mmap_string_new("");
1139 if (mmapstr == NULL) {
1140 res = MAIL_ERROR_MEMORY;
1141 goto err;
1142 }
1143
1144 snprintf(filename_env, PATH_MAX, "%s%c%s%c%s",
1145 cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR,
1146 cached_data->mbox_quoted_mb,
1147 MAIL_DIR_SEPARATOR, ENV_NAME);
1148
1149 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
1150 if (r < 0) {
1151 res = MAIL_ERROR_MEMORY;
1152 goto free_mmapstr;
1153 }
1154
1155 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
1156 cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR,
1157 cached_data->mbox_quoted_mb,
1158 MAIL_DIR_SEPARATOR, FLAGS_NAME);
1159
1160 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
1161 if (r < 0) {
1162 res = MAIL_ERROR_FILE;
1163 goto close_db_env;
1164 }
1165
1166 /* fill with cached */
1167
1168 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1169 mailmessage * msg;
1170 struct mailimf_fields * fields;
1171 struct mail_flags * flags;
1172
1173 msg = carray_get(env_list->msg_tab, i);
1174
1175 if (msg->msg_fields == NULL) {
1176 r = get_cached_envelope(cache_db_env, mmapstr, session,
1177 msg->msg_index, &fields);
1178 if (r == MAIL_NO_ERROR) {
1179 msg->msg_cached = TRUE;
1180 msg->msg_fields = fields;
1181 }
1182 }
1183
1184 if (msg->msg_flags == NULL) {
1185 r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
1186 session, msg->msg_index,
1187 &flags);
1188 if (r == MAIL_NO_ERROR) {
1189 msg->msg_flags = flags;
1190 }
1191 }
1192 }
1193
1194 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
1195 mail_cache_db_close_unlock(filename_env, cache_db_env);
1196
1197 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
1198
1199 if (r != MAIL_NO_ERROR) {
1200 res = r;
1201 goto free_mmapstr;
1202 }
1203
1204 /* add flags */
1205
1206 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1207 mailmessage * msg;
1208
1209 msg = carray_get(env_list->msg_tab, i);
1210
1211 if (msg->msg_flags == NULL)
1212 msg->msg_flags = mail_flags_new_empty();
1213 }
1214
1215 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
1216 if (r < 0) {
1217 res = MAIL_ERROR_MEMORY;
1218 goto free_mmapstr;
1219 }
1220
1221 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
1222 if (r < 0) {
1223 res = MAIL_ERROR_FILE;
1224 goto close_db_env;
1225 }
1226
1227 /* must write cache */
1228
1229 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1230 mailmessage * msg;
1231
1232 msg = carray_get(env_list->msg_tab, i);
1233
1234 if (msg->msg_fields != NULL) {
1235 if (!msg->msg_cached) {
1236 /* msg->msg_index is the numerical UID of the message */
1237 r = write_cached_envelope(cache_db_env, mmapstr,
1238 session, msg->msg_index, msg->msg_fields);
1239 }
1240 }
1241
1242 if (msg->msg_flags != NULL) {
1243 r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr,
1244 msg->msg_uid, msg->msg_flags);
1245 }
1246 }
1247
1248 /* flush cache */
1249
1250 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
1251
1252 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
1253 mail_cache_db_close_unlock(filename_env, cache_db_env);
1254
1255 mmap_string_free(mmapstr);
1256
1257 return MAIL_NO_ERROR;
1258
1259 close_db_env:
1260 mail_cache_db_close_unlock(filename_env, cache_db_env);
1261 free_mmapstr:
1262 mmap_string_free(mmapstr);
1263 err:
1264 return res;
1265}
1266
1267
1268static int
1269mboxdriver_cached_remove_message(mailsession * session, uint32_t num)
1270{
1271 return mailsession_remove_message(get_ancestor(session), num);
1272}
1273
1274static int mboxdriver_cached_get_message(mailsession * session,
1275 uint32_t num, mailmessage ** result)
1276{
1277 mailmessage * msg_info;
1278 int r;
1279
1280 msg_info = mailmessage_new();
1281 if (msg_info == NULL)
1282 return MAIL_ERROR_MEMORY;
1283
1284 r = mailmessage_init(msg_info, session, mbox_cached_message_driver, num, 0);
1285 if (r != MAIL_NO_ERROR) {
1286 mailmessage_free(msg_info);
1287 return r;
1288 }
1289
1290 * result = msg_info;
1291
1292 return MAIL_NO_ERROR;
1293}
1294
1295static int mboxdriver_cached_get_message_by_uid(mailsession * session,
1296 const char * uid,
1297 mailmessage ** result)
1298{
1299 uint32_t num;
1300 char * p;
1301 chashdatum key;
1302 chashdatum data;
1303 struct mailmbox_msg_info * info;
1304 struct mailmbox_folder * folder;
1305 int r;
1306
1307 if (uid == NULL)
1308 return MAIL_ERROR_INVAL;
1309
1310 num = strtoul(uid, &p, 10);
1311 if (p == uid || * p != '-')
1312 return MAIL_ERROR_INVAL;
1313
1314 folder = get_mbox_session(session);
1315 if (folder == NULL)
1316 return MAIL_ERROR_BAD_STATE;
1317
1318 key.data = &num;
1319 key.len = sizeof(num);
1320
1321 r = chash_get(folder->mb_hash, &key, &data);
1322 if (r == 0) {
1323 char * body_len_p = p + 1;
1324 size_t body_len;
1325
1326 info = data.data;
1327 /* Check if the cached message has the same UID */
1328 body_len = strtoul(body_len_p, &p, 10);
1329 if (p == body_len_p || * p != '\0')
1330 return MAIL_ERROR_INVAL;
1331
1332 if (body_len == info->msg_body_len)
1333 return mboxdriver_cached_get_message(session, num, result);
1334 }
1335
1336 return MAIL_ERROR_MSG_NOT_FOUND;
1337}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_CACHED_H
37
38#define MBOXDRIVER_CACHED_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/mboxdriver_types.h>
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48extern mailsession_driver * mbox_cached_session_driver;
49
50#ifdef __cplusplus
51}
52#endif
53
54#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxdriver_cached_message.h"
37
38#include "mailmessage_tools.h"
39#include "mboxdriver_tools.h"
40#include "mboxdriver_cached.h"
41#include "mboxdriver.h"
42#include "mailmbox.h"
43#include "mail_cache_db.h"
44#include "generic_cache.h"
45
46#include <unistd.h>
47#include <sys/mman.h>
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <string.h>
52#include <stdlib.h>
53
54static int mbox_prefetch(mailmessage * msg_info);
55
56static void mbox_prefetch_free(struct generic_message_t * msg);
57
58static int mbox_initialize(mailmessage * msg_info);
59
60static void mbox_uninitialize(mailmessage * msg_info);
61
62static void mbox_flush(mailmessage * msg_info);
63
64static void mbox_check(mailmessage * msg_info);
65
66static int mbox_fetch_size(mailmessage * msg_info,
67 size_t * result);
68
69static int mbox_get_flags(mailmessage * msg_info,
70 struct mail_flags ** result);
71
72static int mbox_fetch_header(mailmessage * msg_info,
73 char ** result,
74 size_t * result_len);
75
76static mailmessage_driver local_mbox_cached_message_driver = {
77 .msg_name = "mbox-cached",
78
79 .msg_initialize = mbox_initialize,
80 .msg_uninitialize = mbox_uninitialize,
81
82 .msg_flush = mbox_flush,
83 .msg_check = mbox_check,
84
85 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
86
87 .msg_fetch = mailmessage_generic_fetch,
88 .msg_fetch_header = mbox_fetch_header,
89 .msg_fetch_body = mailmessage_generic_fetch_body,
90 .msg_fetch_size = mbox_fetch_size,
91 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
92 .msg_fetch_section = mailmessage_generic_fetch_section,
93 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
94 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
95 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
96 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
97
98 .msg_get_flags = mbox_get_flags,
99};
100
101mailmessage_driver * mbox_cached_message_driver =
102&local_mbox_cached_message_driver;
103
104static inline struct mbox_cached_session_state_data *
105get_cached_session_data(mailmessage * msg)
106{
107 return msg->msg_session->sess_data;
108}
109
110static inline mailsession * get_ancestor_session(mailmessage * msg)
111{
112 return get_cached_session_data(msg)->mbox_ancestor;
113}
114
115static inline struct mbox_session_state_data *
116get_ancestor_session_data(mailmessage * msg)
117{
118 return get_ancestor_session(msg)->sess_data;
119}
120
121static inline struct mailmbox_folder *
122get_mbox_session(mailmessage * msg)
123{
124 return get_ancestor_session_data(msg)->mbox_folder;
125}
126
127static int mbox_prefetch(mailmessage * msg_info)
128{
129 struct generic_message_t * msg;
130 int r;
131 char * msg_content;
132 size_t msg_length;
133
134 r = mboxdriver_fetch_msg(get_ancestor_session(msg_info),
135 msg_info->msg_index,
136 &msg_content, &msg_length);
137 if (r != MAIL_NO_ERROR)
138 return r;
139
140 msg = msg_info->msg_data;
141
142 msg->msg_message = msg_content;
143 msg->msg_length = msg_length;
144
145 return MAIL_NO_ERROR;
146}
147
148static void mbox_prefetch_free(struct generic_message_t * msg)
149{
150 if (msg->msg_message != NULL) {
151 mmap_string_unref(msg->msg_message);
152 msg->msg_message = NULL;
153 }
154}
155
156static int mbox_initialize(mailmessage * msg_info)
157{
158 struct generic_message_t * msg;
159 int r;
160 char * uid;
161 char static_uid[PATH_MAX];
162 struct mailmbox_msg_info * info;
163 struct mailmbox_folder * folder;
164 int res;
165 chashdatum key;
166 chashdatum data;
167
168 folder = get_mbox_session(msg_info);
169 if (folder == NULL) {
170 res = MAIL_ERROR_BAD_STATE;
171 goto err;
172 }
173
174 key.data = (char *) &msg_info->msg_index;
175 key.len = sizeof(msg_info->msg_index);
176
177 r = chash_get(folder->mb_hash, &key, &data);
178 if (r < 0) {
179 res = MAIL_ERROR_MSG_NOT_FOUND;
180 goto err;
181 }
182
183 info = (struct mailmbox_msg_info *) data.data;
184
185 snprintf(static_uid, PATH_MAX, "%u-%lu",
186 msg_info->msg_index, (unsigned long) info->msg_body_len);
187 uid = strdup(static_uid);
188 if (uid == NULL) {
189 res = MAIL_ERROR_MEMORY;
190 goto err;
191 }
192
193 r = mailmessage_generic_initialize(msg_info);
194 if (r != MAIL_NO_ERROR) {
195 free(uid);
196 res = r;
197 goto err;
198 }
199
200 msg = msg_info->msg_data;
201
202 msg->msg_prefetch = mbox_prefetch;
203 msg->msg_prefetch_free = mbox_prefetch_free;
204 msg_info->msg_uid = uid;
205
206 return MAIL_NO_ERROR;
207
208 err:
209 return res;
210}
211
212static void mbox_uninitialize(mailmessage * msg_info)
213{
214 mailmessage_generic_uninitialize(msg_info);
215}
216
217#define FLAGS_NAME "flags.db"
218
219static void mbox_flush(mailmessage * msg_info)
220{
221 mailmessage_generic_flush(msg_info);
222}
223
224static void mbox_check(mailmessage * msg_info)
225{
226 int r;
227
228 if (msg_info->msg_flags != NULL) {
229 r = mail_flags_store_set(get_cached_session_data(msg_info)->mbox_flags_store,
230 msg_info);
231 /* ignore errors */
232 }
233}
234
235
236static int mbox_fetch_size(mailmessage * msg_info,
237 size_t * result)
238{
239 int r;
240 size_t size;
241
242 r = mboxdriver_fetch_size(get_ancestor_session(msg_info),
243 msg_info->msg_index, &size);
244 if (r != MAIL_NO_ERROR)
245 return r;
246
247 * result = size;
248
249 return MAIL_NO_ERROR;
250}
251
252static int mbox_get_flags(mailmessage * msg_info,
253 struct mail_flags ** result)
254{
255 int r;
256 struct mail_flags * flags;
257 struct mail_cache_db * cache_db_flags;
258 char filename_flags[PATH_MAX];
259 int res;
260 struct mbox_cached_session_state_data * cached_data;
261 MMAPString * mmapstr;
262 struct mailmbox_folder * folder;
263
264 if (msg_info->msg_flags != NULL) {
265 * result = msg_info->msg_flags;
266
267 return MAIL_NO_ERROR;
268 }
269
270 flags = mail_flags_store_get(get_cached_session_data(msg_info)->mbox_flags_store,
271 msg_info->msg_index);
272
273 if (flags == NULL) {
274 folder = get_mbox_session(msg_info);
275 if (folder == NULL) {
276 res = MAIL_ERROR_BAD_STATE;
277 goto err;
278 }
279
280 cached_data = get_cached_session_data(msg_info);
281 if (cached_data->mbox_quoted_mb == NULL) {
282 res = MAIL_ERROR_BAD_STATE;
283 goto err;
284 }
285
286 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
287 cached_data->mbox_flags_directory,
288 cached_data->mbox_quoted_mb, FLAGS_NAME);
289
290 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
291 if (r < 0) {
292 res = MAIL_ERROR_MEMORY;
293 goto err;
294 }
295
296 mmapstr = mmap_string_new("");
297 if (mmapstr == NULL) {
298 res = MAIL_ERROR_MEMORY;
299 goto close_db_flags;
300 }
301
302 if (msg_info->msg_index > folder->mb_written_uid) {
303 flags = mail_flags_new_empty();
304 }
305 else {
306 r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
307 msg_info->msg_session,
308 msg_info->msg_index, &flags);
309 if (r != MAIL_NO_ERROR) {
310 flags = mail_flags_new_empty();
311 if (flags == NULL) {
312 res = MAIL_ERROR_MEMORY;
313 goto free_mmapstr;
314 }
315 }
316 }
317
318 mmap_string_free(mmapstr);
319 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
320 }
321
322 msg_info->msg_flags = flags;
323
324 * result = flags;
325
326 return MAIL_NO_ERROR;
327
328 free_mmapstr:
329 mmap_string_free(mmapstr);
330 close_db_flags:
331 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
332 err:
333 return res;
334}
335
336static int mbox_fetch_header(mailmessage * msg_info,
337 char ** result,
338 size_t * result_len)
339{
340 struct generic_message_t * msg;
341 int r;
342 char * msg_content;
343 size_t msg_length;
344
345 msg = msg_info->msg_data;
346 if (msg->msg_message != NULL) {
347 return mailmessage_generic_fetch_header(msg_info, result, result_len);
348 }
349 else {
350 r = mboxdriver_fetch_header(get_ancestor_session(msg_info),
351 msg_info->msg_index,
352 &msg_content, &msg_length);
353 if (r != MAIL_NO_ERROR)
354 return r;
355
356 * result = msg_content;
357 * result_len = msg_length;
358
359 return MAIL_NO_ERROR;
360 }
361}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_CACHED_MESSAGE_H
37
38#define MBOXDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/mailmessage.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mbox_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxdriver_message.h"
37
38#include "mailmessage_tools.h"
39#include "mboxdriver_tools.h"
40#include "mboxdriver.h"
41#include "mailmbox.h"
42
43#include <unistd.h>
44#include <sys/mman.h>
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <fcntl.h>
48#include <string.h>
49#include <stdlib.h>
50
51static int mbox_prefetch(mailmessage * msg_info);
52
53static void mbox_prefetch_free(struct generic_message_t * msg);
54
55static int mbox_initialize(mailmessage * msg_info);
56
57static int mbox_fetch_size(mailmessage * msg_info,
58 size_t * result);
59
60static int mbox_fetch_header(mailmessage * msg_info,
61 char ** result,
62 size_t * result_len);
63
64static mailmessage_driver local_mbox_message_driver = {
65 .msg_name = "mbox",
66
67 .msg_initialize = mbox_initialize,
68 .msg_uninitialize = mailmessage_generic_uninitialize,
69
70 .msg_flush = mailmessage_generic_flush,
71 .msg_check = NULL,
72
73 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
74
75 .msg_fetch = mailmessage_generic_fetch,
76 .msg_fetch_header = mbox_fetch_header,
77 .msg_fetch_body = mailmessage_generic_fetch_body,
78 .msg_fetch_size = mbox_fetch_size,
79 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
80 .msg_fetch_section = mailmessage_generic_fetch_section,
81 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
82 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
83 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
84 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
85
86 .msg_get_flags = NULL,
87};
88
89mailmessage_driver * mbox_message_driver = &local_mbox_message_driver;
90
91static inline struct mbox_session_state_data * get_data(mailmessage * msg)
92{
93 return msg->msg_session->sess_data;
94}
95
96static inline struct mailmbox_folder * get_mbox_session(mailmessage * msg)
97{
98 return get_data(msg)->mbox_folder;
99}
100
101
102static int mbox_prefetch(mailmessage * msg_info)
103{
104 struct generic_message_t * msg;
105 int r;
106 char * msg_content;
107 size_t msg_length;
108
109 r = mboxdriver_fetch_msg(msg_info->msg_session, msg_info->msg_index,
110 &msg_content, &msg_length);
111 if (r != MAIL_NO_ERROR)
112 return r;
113
114 msg = msg_info->msg_data;
115
116 msg->msg_message = msg_content;
117 msg->msg_length = msg_length;
118
119 return MAIL_NO_ERROR;
120}
121
122static void mbox_prefetch_free(struct generic_message_t * msg)
123{
124 if (msg->msg_message != NULL) {
125 mmap_string_unref(msg->msg_message);
126 msg->msg_message = NULL;
127 }
128}
129
130static int mbox_initialize(mailmessage * msg_info)
131{
132 struct generic_message_t * msg;
133 int r;
134 char * uid;
135 char static_uid[PATH_MAX];
136 struct mailmbox_msg_info * info;
137 struct mailmbox_folder * folder;
138 int res;
139 chashdatum key;
140 chashdatum data;
141
142 folder = get_mbox_session(msg_info);
143 if (folder == NULL) {
144 res = MAIL_ERROR_BAD_STATE;
145 goto err;
146 }
147
148 key.data = &msg_info->msg_index;
149 key.len = sizeof(msg_info->msg_index);
150
151 r = chash_get(folder->mb_hash, &key, &data);
152 if (r < 0) {
153 res = MAIL_ERROR_MSG_NOT_FOUND;
154 goto err;
155 }
156
157 info = data.data;
158
159 snprintf(static_uid, PATH_MAX, "%u-%lu",
160 msg_info->msg_index, (unsigned long) info->msg_body_len);
161 uid = strdup(static_uid);
162 if (uid == NULL) {
163 res = MAIL_ERROR_MEMORY;
164 goto err;
165 }
166
167 r = mailmessage_generic_initialize(msg_info);
168 if (r != MAIL_NO_ERROR) {
169 free(uid);
170 res = r;
171 goto err;
172 }
173
174 msg = msg_info->msg_data;
175 msg->msg_prefetch = mbox_prefetch;
176 msg->msg_prefetch_free = mbox_prefetch_free;
177 msg_info->msg_uid = uid;
178
179 return MAIL_NO_ERROR;
180
181 err:
182 return res;
183}
184
185static int mbox_fetch_size(mailmessage * msg_info,
186 size_t * result)
187{
188 int r;
189 size_t size;
190
191 r = mboxdriver_fetch_size(msg_info->msg_session,
192 msg_info->msg_index, &size);
193 if (r != MAIL_NO_ERROR)
194 return r;
195
196 * result = size;
197
198 return MAIL_NO_ERROR;
199}
200
201static int mbox_fetch_header(mailmessage * msg_info,
202 char ** result,
203 size_t * result_len)
204{
205 struct generic_message_t * msg;
206 int r;
207 char * msg_content;
208 size_t msg_length;
209
210 msg = msg_info->msg_data;
211 if (msg->msg_message != NULL) {
212 return mailmessage_generic_fetch_header(msg_info, result, result_len);
213 }
214 else {
215 r = mboxdriver_fetch_header(msg_info->msg_session, msg_info->msg_index,
216 &msg_content, &msg_length);
217 if (r != MAIL_NO_ERROR)
218 return r;
219
220 * result = msg_content;
221 * result_len = msg_length;
222
223 return MAIL_NO_ERROR;
224 }
225}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_MESSAGE_H
37
38#define MBOXDRIVER_MESSAGE_H
39
40#include <libetpan/mboxdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mbox_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxdriver_tools.h"
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <unistd.h>
42
43#include "maildriver_types.h"
44#include "mailmbox.h"
45#include "mboxdriver_cached.h"
46#include "mboxdriver.h"
47#include "generic_cache.h"
48#include "mailmessage.h"
49#include "imfcache.h"
50#include "mail_cache_db.h"
51
52static inline struct mbox_session_state_data *
53session_get_data(mailsession * session)
54{
55 return session->sess_data;
56}
57
58static inline struct mailmbox_folder *
59session_get_mbox_session(mailsession * session)
60{
61 return session_get_data(session)->mbox_folder;
62}
63
64static inline struct mbox_cached_session_state_data *
65cached_session_get_data(mailsession * session)
66{
67 return session->sess_data;
68}
69
70static inline mailsession *
71cached_session_get_ancestor(mailsession * session)
72{
73 return cached_session_get_data(session)->mbox_ancestor;
74}
75
76static inline struct mbox_session_state_data *
77cached_session_get_ancestor_data(mailsession * session)
78{
79 return cached_session_get_ancestor(session)->sess_data;
80}
81
82static inline struct mailmbox_folder *
83cached_session_get_mbox_session(mailsession * session)
84{
85 return session_get_mbox_session(cached_session_get_ancestor(session));
86}
87
88
89int mboxdriver_mbox_error_to_mail_error(int error)
90{
91 switch (error) {
92 case MAILMBOX_NO_ERROR:
93 return MAIL_NO_ERROR;
94
95 case MAILMBOX_ERROR_PARSE:
96 return MAIL_ERROR_PARSE;
97
98 case MAILMBOX_ERROR_INVAL:
99 return MAIL_ERROR_INVAL;
100
101 case MAILMBOX_ERROR_FILE_NOT_FOUND:
102 return MAIL_ERROR_PARSE;
103
104 case MAILMBOX_ERROR_MEMORY:
105 return MAIL_ERROR_MEMORY;
106
107 case MAILMBOX_ERROR_TEMPORARY_FILE:
108 return MAIL_ERROR_PARSE;
109
110 case MAILMBOX_ERROR_FILE:
111 return MAIL_ERROR_FILE;
112
113 case MAILMBOX_ERROR_MSG_NOT_FOUND:
114 return MAIL_ERROR_MSG_NOT_FOUND;
115
116 case MAILMBOX_ERROR_READONLY:
117 return MAIL_ERROR_READONLY;
118
119 default:
120 return MAIL_ERROR_INVAL;
121 }
122}
123
124int mboxdriver_fetch_msg(mailsession * session, uint32_t index,
125 char ** result, size_t * result_len)
126{
127 int r;
128 char * msg_content;
129 size_t msg_length;
130 struct mailmbox_folder * folder;
131
132 folder = session_get_mbox_session(session);
133 if (folder == NULL)
134 return MAIL_ERROR_BAD_STATE;
135
136 r = mailmbox_fetch_msg(folder, index, &msg_content, &msg_length);
137 if (r != MAILMBOX_NO_ERROR)
138 return mboxdriver_mbox_error_to_mail_error(r);
139
140 * result = msg_content;
141 * result_len = msg_length;
142
143 return MAIL_NO_ERROR;
144}
145
146
147int mboxdriver_fetch_size(mailsession * session, uint32_t index,
148 size_t * result)
149{
150 struct mailmbox_folder * folder;
151 int r;
152 char * data;
153 size_t len;
154 int res;
155
156 folder = session_get_mbox_session(session);
157 if (folder == NULL) {
158 res = MAIL_ERROR_FETCH;
159 goto err;
160 }
161
162 r = mailmbox_validate_read_lock(folder);
163 if (r != MAILMBOX_NO_ERROR) {
164 res = mboxdriver_mbox_error_to_mail_error(r);
165 goto err;
166 }
167
168 r = mailmbox_fetch_msg_no_lock(folder, index, &data, &len);
169 if (r != MAILMBOX_NO_ERROR) {
170 res = mboxdriver_mbox_error_to_mail_error(r);
171 goto unlock;
172 }
173
174 mailmbox_read_unlock(folder);
175
176 * result = len;
177
178 return MAIL_NO_ERROR;
179
180 unlock:
181 mailmbox_read_unlock(folder);
182 err:
183 return res;
184}
185
186
187int
188mboxdriver_get_cached_flags(struct mail_cache_db * cache_db,
189 MMAPString * mmapstr,
190 mailsession * session,
191 uint32_t num,
192 struct mail_flags ** result)
193{
194 int r;
195 char keyname[PATH_MAX];
196 struct mail_flags * flags;
197 int res;
198 struct mailmbox_msg_info * info;
199 struct mailmbox_folder * folder;
200 chashdatum key;
201 chashdatum data;
202
203 folder = cached_session_get_mbox_session(session);
204 if (folder == NULL) {
205 res = MAIL_ERROR_BAD_STATE;
206 goto err;
207 }
208
209 key.data = &num;
210 key.len = sizeof(num);
211
212 r = chash_get(folder->mb_hash, &key, &data);
213 if (r < 0) {
214 res = MAIL_ERROR_MSG_NOT_FOUND;
215 goto err;
216 }
217
218 info = data.data;
219
220 snprintf(keyname, PATH_MAX, "%u-%lu-flags", num,
221 (unsigned long) info->msg_body_len);
222
223 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
224 if (r != MAIL_NO_ERROR) {
225 res = r;
226 goto err;
227 }
228
229 * result = flags;
230
231 return MAIL_NO_ERROR;
232
233 err:
234 return res;
235}
236
237int
238mboxdriver_write_cached_flags(struct mail_cache_db * cache_db,
239 MMAPString * mmapstr,
240 char * uid,
241 struct mail_flags * flags)
242{
243 int r;
244 char keyname[PATH_MAX];
245 int res;
246
247 snprintf(keyname, PATH_MAX, "%s-flags", uid);
248
249 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
250 if (r != MAIL_NO_ERROR) {
251 res = r;
252 goto err;
253 }
254
255 return MAIL_NO_ERROR;
256
257 err:
258 return res;
259}
260
261
262int mboxdriver_fetch_header(mailsession * session, uint32_t index,
263 char ** result, size_t * result_len)
264{
265 int r;
266 char * msg_content;
267 size_t msg_length;
268 struct mailmbox_folder * folder;
269
270 folder = session_get_mbox_session(session);
271 if (folder == NULL)
272 return MAIL_ERROR_BAD_STATE;
273
274 r = mailmbox_fetch_msg_headers(folder, index, &msg_content, &msg_length);
275 if (r != MAILMBOX_NO_ERROR)
276 return mboxdriver_mbox_error_to_mail_error(r);
277
278 * result = msg_content;
279 * result_len = msg_length;
280
281 return MAIL_NO_ERROR;
282}
283
284int mbox_get_locked_messages_list(struct mailmbox_folder * folder,
285 mailsession * session,
286 mailmessage_driver * driver,
287 int (* lock)(struct mailmbox_folder *),
288 int (* unlock)(struct mailmbox_folder *),
289 struct mailmessage_list ** result)
290{
291 struct mailmessage_list * env_list;
292 unsigned int i;
293 int r;
294 int res;
295 carray * tab;
296
297 tab = carray_new(128);
298 if (tab == NULL) {
299 res = MAIL_ERROR_MEMORY;
300 goto err;
301 }
302
303 r = lock(folder);
304 if (r != MAIL_NO_ERROR) {
305 res = r;
306 goto free;
307 }
308
309 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
310 struct mailmbox_msg_info * msg_info;
311 mailmessage * msg;
312
313 msg_info = carray_get(folder->mb_tab, i);
314 if (msg_info == NULL)
315 continue;
316
317 if (msg_info->msg_deleted)
318 continue;
319
320 msg = mailmessage_new();
321 if (msg == NULL) {
322 res = MAIL_ERROR_MEMORY;
323 goto unlock;
324 }
325
326 r = mailmessage_init(msg, session, driver, msg_info->msg_uid,
327 msg_info->msg_size - msg_info->msg_start_len);
328 if (r != MAIL_NO_ERROR) {
329 res = r;
330 goto unlock;
331 }
332
333 r = carray_add(tab, msg, NULL);
334 if (r < 0) {
335 mailmessage_free(msg);
336 res = MAIL_ERROR_MEMORY;
337 goto unlock;
338 }
339 }
340
341 env_list = mailmessage_list_new(tab);
342 if (env_list == NULL) {
343 res = MAIL_ERROR_MEMORY;
344 goto unlock;
345 }
346
347 unlock(folder);
348
349 * result = env_list;
350
351 return MAIL_NO_ERROR;
352
353 unlock:
354 unlock(folder);
355 free:
356 for(i = 0 ; i < carray_count(tab) ; i ++)
357 mailmessage_free(carray_get(tab, i));
358 carray_free(tab);
359 err:
360 return res;
361}
362
363static int release_read_mbox(struct mailmbox_folder * folder)
364{
365 int r;
366
367 r = mailmbox_read_unlock(folder);
368 return mboxdriver_mbox_error_to_mail_error(r);
369}
370
371static int acquire_read_mbox(struct mailmbox_folder * folder)
372{
373 int r;
374
375 r = mailmbox_validate_read_lock(folder);
376 return mboxdriver_mbox_error_to_mail_error(r);
377}
378
379static int release_write_mbox(struct mailmbox_folder * folder)
380{
381 int r;
382
383 r = mailmbox_write_unlock(folder);
384 return mboxdriver_mbox_error_to_mail_error(r);
385}
386
387static int acquire_write_mbox(struct mailmbox_folder * folder)
388{
389 int r;
390 int res;
391
392 r = mailmbox_validate_write_lock(folder);
393 if (r != MAILMBOX_NO_ERROR) {
394 res = mboxdriver_mbox_error_to_mail_error(r);
395 goto err;
396 }
397
398 if (folder->mb_written_uid < folder->mb_max_uid) {
399 r = mailmbox_expunge_no_lock(folder);
400 if (r != MAILMBOX_NO_ERROR) {
401 res = mboxdriver_mbox_error_to_mail_error(r);
402 goto unlock;
403 }
404 }
405
406 return MAIL_NO_ERROR;
407
408 unlock:
409 mailmbox_write_unlock(folder);
410 err:
411 return res;
412}
413
414/* get message list with all valid written UID */
415
416int mbox_get_uid_messages_list(struct mailmbox_folder * folder,
417 mailsession * session,
418 mailmessage_driver * driver,
419 struct mailmessage_list ** result)
420{
421 return mbox_get_locked_messages_list(folder, session, driver,
422 acquire_write_mbox, release_write_mbox, result);
423}
424
425
426/* get message list */
427
428int mbox_get_messages_list(struct mailmbox_folder * folder,
429 mailsession * session,
430 mailmessage_driver * driver,
431 struct mailmessage_list ** result)
432{
433 return mbox_get_locked_messages_list(folder, session, driver,
434 acquire_read_mbox, release_read_mbox, result);
435}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_TOOLS_H
37
38#define MBOXDRIVER_TOOLS_H
39
40#include "mail_cache_db_types.h"
41#include "mboxdriver_types.h"
42#include "mailmbox.h"
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48int mboxdriver_mbox_error_to_mail_error(int error);
49
50int mboxdriver_fetch_msg(mailsession * session, uint32_t index,
51 char ** result, size_t * result_len);
52
53int mboxdriver_fetch_size(mailsession * session, uint32_t index,
54 size_t * result);
55
56int
57mboxdriver_get_cached_flags(struct mail_cache_db * cache_db,
58 MMAPString * mmapstr,
59 mailsession * session,
60 uint32_t num,
61 struct mail_flags ** result);
62
63int
64mboxdriver_write_cached_flags(struct mail_cache_db * cache_db,
65 MMAPString * mmapstr,
66 char * uid, struct mail_flags * flags);
67
68int mbox_get_uid_messages_list(struct mailmbox_folder * folder,
69 mailsession * session,
70 mailmessage_driver * driver,
71 struct mailmessage_list ** result);
72
73int mbox_get_messages_list(struct mailmbox_folder * folder,
74 mailsession * session,
75 mailmessage_driver * driver,
76 struct mailmessage_list ** result);
77
78int mboxdriver_fetch_header(mailsession * session, uint32_t index,
79 char ** result, size_t * result_len);
80
81#ifdef __cplusplus
82}
83#endif
84
85#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_TYPES_H
37
38#define MBOXDRIVER_TYPES_H
39
40#include <libetpan/maildriver_types.h>
41#include <libetpan/mailmbox.h>
42#include <libetpan/mailstorage_types.h>
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48/* mbox driver */
49
50enum {
51 MBOXDRIVER_SET_READ_ONLY = 1,
52 MBOXDRIVER_SET_NO_UID,
53};
54
55struct mbox_session_state_data {
56 struct mailmbox_folder * mbox_folder;
57 int mbox_force_read_only;
58 int mbox_force_no_uid;
59};
60
61/* cached version */
62
63enum {
64 /* the mapping of the parameters should be the same as for mbox */
65 MBOXDRIVER_CACHED_SET_READ_ONLY = 1,
66 MBOXDRIVER_CACHED_SET_NO_UID,
67 /* cache specific */
68 MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY,
69 MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY,
70};
71
72struct mbox_cached_session_state_data {
73 mailsession * mbox_ancestor;
74 char * mbox_quoted_mb;
75 char mbox_cache_directory[PATH_MAX];
76 char mbox_flags_directory[PATH_MAX];
77 struct mail_flags_store * mbox_flags_store;
78};
79
80/* mbox storage */
81
82/*
83 mbox_mailstorage is the state data specific to the mbox storage.
84
85 - pathname is the filename that contains the mailbox.
86
87 - cached if this value is != 0, a persistant cache will be
88 stored on local system.
89
90 - cache_directory is the location of the cache.
91
92 - flags_directory is the location of the flags.
93*/
94
95struct mbox_mailstorage {
96 char * mbox_pathname;
97
98 int mbox_cached;
99 char * mbox_cache_directory;
100 char * mbox_flags_directory;
101};
102
103#ifdef __cplusplus
104}
105#endif
106
107#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxstorage.h"
37
38#include "mail.h"
39#include "mailmessage.h"
40#include "mboxdriver.h"
41#include "mboxdriver_cached.h"
42#include "maildriver.h"
43
44#include <stdlib.h>
45#include <string.h>
46
47/* mbox storage */
48
49static int mbox_mailstorage_connect(struct mailstorage * storage);
50static int
51mbox_mailstorage_get_folder_session(struct mailstorage * storage,
52 char * pathname, mailsession ** result);
53static void mbox_mailstorage_uninitialize(struct mailstorage * storage);
54
55static mailstorage_driver mbox_mailstorage_driver = {
56 .sto_name = "mbox",
57 .sto_connect = mbox_mailstorage_connect,
58 .sto_get_folder_session = mbox_mailstorage_get_folder_session,
59 .sto_uninitialize = mbox_mailstorage_uninitialize,
60};
61
62int mbox_mailstorage_init(struct mailstorage * storage,
63 char * mbox_pathname, int mbox_cached,
64 char * mbox_cache_directory, char * mbox_flags_directory)
65{
66 struct mbox_mailstorage * mbox_storage;
67
68 mbox_storage = malloc(sizeof(* mbox_storage));
69 if (mbox_storage == NULL)
70 goto err;
71
72 mbox_storage->mbox_pathname = strdup(mbox_pathname);
73 if (mbox_storage->mbox_pathname == NULL)
74 goto free;
75
76 mbox_storage->mbox_cached = mbox_cached;
77
78 if (mbox_cached && (mbox_cache_directory != NULL) &&
79 (mbox_flags_directory != NULL)) {
80 mbox_storage->mbox_cache_directory = strdup(mbox_cache_directory);
81 if (mbox_storage->mbox_cache_directory == NULL)
82 goto free_pathname;
83
84 mbox_storage->mbox_flags_directory = strdup(mbox_flags_directory);
85 if (mbox_storage->mbox_flags_directory == NULL)
86 goto free_cache_directory;
87 }
88 else {
89 mbox_storage->mbox_cached = FALSE;
90 mbox_storage->mbox_cache_directory = NULL;
91 mbox_storage->mbox_flags_directory = NULL;
92 }
93
94 storage->sto_data = mbox_storage;
95 storage->sto_driver = &mbox_mailstorage_driver;
96
97 return MAIL_NO_ERROR;
98
99 free_cache_directory:
100 free(mbox_storage->mbox_cache_directory);
101 free_pathname:
102 free(mbox_storage->mbox_pathname);
103 free:
104 free(mbox_storage);
105 err:
106 return MAIL_ERROR_MEMORY;
107}
108
109static void mbox_mailstorage_uninitialize(struct mailstorage * storage)
110{
111 struct mbox_mailstorage * mbox_storage;
112
113 mbox_storage = storage->sto_data;
114 if (mbox_storage->mbox_flags_directory != NULL)
115 free(mbox_storage->mbox_flags_directory);
116 if (mbox_storage->mbox_cache_directory != NULL)
117 free(mbox_storage->mbox_cache_directory);
118 free(mbox_storage->mbox_pathname);
119 free(mbox_storage);
120
121 storage->sto_data = NULL;
122}
123
124static int mbox_mailstorage_connect(struct mailstorage * storage)
125{
126 struct mbox_mailstorage * mbox_storage;
127 mailsession_driver * driver;
128 int r;
129 int res;
130 mailsession * session;
131
132 mbox_storage = storage->sto_data;
133
134 if (mbox_storage->mbox_cached)
135 driver = mbox_cached_session_driver;
136 else
137 driver = mbox_session_driver;
138
139 session = mailsession_new(driver);
140 if (session == NULL) {
141 res = MAIL_ERROR_MEMORY;
142 goto err;
143 }
144
145 if (mbox_storage->mbox_cached) {
146 r = mailsession_parameters(session,
147 MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY,
148 mbox_storage->mbox_cache_directory);
149 if (r != MAIL_NO_ERROR) {
150 res = r;
151 goto free;
152 }
153
154 r = mailsession_parameters(session,
155 MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY,
156 mbox_storage->mbox_flags_directory);
157 if (r != MAIL_NO_ERROR) {
158 res = r;
159 goto free;
160 }
161 }
162
163 r = mailsession_connect_path(session, mbox_storage->mbox_pathname);
164 switch (r) {
165 case MAIL_NO_ERROR_NON_AUTHENTICATED:
166 case MAIL_NO_ERROR_AUTHENTICATED:
167 case MAIL_NO_ERROR:
168 break;
169 default:
170 res = r;
171 goto free;
172 }
173
174 storage->sto_session = session;
175
176 return MAIL_NO_ERROR;
177
178 free:
179 mailsession_free(session);
180 err:
181 return res;
182}
183
184static int
185mbox_mailstorage_get_folder_session(struct mailstorage * storage,
186 char * pathname, mailsession ** result)
187{
188 * result = storage->sto_session;
189
190 return MAIL_NO_ERROR;
191}
192
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXSTORAGE_H
37
38#define MBOXSTORAGE_H
39
40#include <libetpan/mboxdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mbox_mailstorage_init is the constructor for a mbox storage.
48
49 @param storage this is the storage to initialize.
50
51 @param pathname is the filename that contains the mailbox.
52
53 @param cached if this value is != 0, a persistant cache will be
54 stored on local system.
55
56 @param cache_directory is the location of the cache
57
58 @param flags_directory is the location of the flags
59*/
60
61int mbox_mailstorage_init(struct mailstorage * storage,
62 char * mb_pathname, int mb_cached,
63 char * mb_cache_directory, char * mb_flags_directory);
64
65#ifdef __cplusplus
66}
67#endif
68
69#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhdriver.h"
37
38#include <stdio.h>
39#include <sys/types.h>
40#include <dirent.h>
41#include <unistd.h>
42#include <sys/stat.h>
43#include <ctype.h>
44#include <fcntl.h>
45#include <sys/mman.h>
46#include <stdlib.h>
47#include <string.h>
48
49#include "mailmh.h"
50#include "maildriver_tools.h"
51#include "mhdriver_tools.h"
52#include "mhdriver_message.h"
53#include "mailmessage.h"
54
55static int mhdriver_initialize(mailsession * session);
56
57static void mhdriver_uninitialize(mailsession * session);
58
59static int mhdriver_connect_path(mailsession * session, char * path);
60static int mhdriver_logout(mailsession * session);
61
62static int mhdriver_build_folder_name(mailsession * session, char * mb,
63 char * name, char ** result);
64static int mhdriver_create_folder(mailsession * session, char * mb);
65
66static int mhdriver_delete_folder(mailsession * session, char * mb);
67
68static int mhdriver_rename_folder(mailsession * session, char * mb,
69 char * new_name);
70
71static int mhdriver_select_folder(mailsession * session, char * mb);
72
73static int mhdriver_status_folder(mailsession * session, char * mb,
74 uint32_t * result_messages, uint32_t * result_recent,
75 uint32_t * result_unseen);
76
77static int mhdriver_messages_number(mailsession * session, char * mb,
78 uint32_t * result);
79
80static int mhdriver_list_folders(mailsession * session, char * mb,
81 struct mail_list ** result);
82
83static int mhdriver_lsub_folders(mailsession * session, char * mb,
84 struct mail_list ** result);
85
86static int mhdriver_subscribe_folder(mailsession * session, char * mb);
87
88static int mhdriver_unsubscribe_folder(mailsession * session, char * mb);
89
90static int mhdriver_append_message(mailsession * session,
91 char * message, size_t size);
92static int mhdriver_append_message_flags(mailsession * session,
93 char * message, size_t size, struct mail_flags * flags);
94static int mhdriver_copy_message(mailsession * session,
95 uint32_t num, char * mb);
96
97static int mhdriver_remove_message(mailsession * session, uint32_t num);
98
99static int mhdriver_move_message(mailsession * session,
100 uint32_t num, char * mb);
101
102static int mhdriver_get_messages_list(mailsession * session,
103 struct mailmessage_list ** result);
104
105static int mhdriver_get_message(mailsession * session,
106 uint32_t num, mailmessage ** result);
107
108static int mhdriver_get_message_by_uid(mailsession * session,
109 const char * uid,
110 mailmessage ** result);
111
112static mailsession_driver local_mh_session_driver = {
113 .sess_name = "mh",
114
115 .sess_initialize = mhdriver_initialize,
116 .sess_uninitialize = mhdriver_uninitialize,
117
118 .sess_parameters = NULL,
119
120 .sess_connect_stream = NULL,
121 .sess_connect_path = mhdriver_connect_path,
122 .sess_starttls = NULL,
123 .sess_login = NULL,
124 .sess_logout = mhdriver_logout,
125 .sess_noop = NULL,
126
127 .sess_build_folder_name = mhdriver_build_folder_name,
128 .sess_create_folder = mhdriver_create_folder,
129 .sess_delete_folder = mhdriver_delete_folder,
130 .sess_rename_folder = mhdriver_rename_folder,
131 .sess_check_folder = NULL,
132 .sess_examine_folder = NULL,
133 .sess_select_folder = mhdriver_select_folder,
134 .sess_expunge_folder = NULL,
135 .sess_status_folder = mhdriver_status_folder,
136 .sess_messages_number = mhdriver_messages_number,
137 .sess_recent_number = mhdriver_messages_number,
138 .sess_unseen_number = mhdriver_messages_number,
139 .sess_list_folders = mhdriver_list_folders,
140 .sess_lsub_folders = mhdriver_lsub_folders,
141 .sess_subscribe_folder = mhdriver_subscribe_folder,
142 .sess_unsubscribe_folder = mhdriver_unsubscribe_folder,
143
144 .sess_append_message = mhdriver_append_message,
145 .sess_append_message_flags = mhdriver_append_message_flags,
146 .sess_copy_message = mhdriver_copy_message,
147 .sess_move_message = mhdriver_move_message,
148
149 .sess_get_messages_list = mhdriver_get_messages_list,
150 .sess_get_envelopes_list = maildriver_generic_get_envelopes_list,
151 .sess_remove_message = mhdriver_remove_message,
152#if 0
153 .sess_search_messages = maildriver_generic_search_messages,
154#endif
155
156 .sess_get_message = mhdriver_get_message,
157 .sess_get_message_by_uid = mhdriver_get_message_by_uid,
158};
159
160mailsession_driver * mh_session_driver = &local_mh_session_driver;
161
162static inline struct mh_session_state_data * get_data(mailsession * session)
163{
164 return session->sess_data;
165}
166
167static inline struct mailmh * get_mh_session(mailsession * session)
168{
169 return get_data(session)->mh_session;
170}
171
172static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session)
173{
174 return get_data(session)->mh_cur_folder;
175}
176
177static int add_to_list(mailsession * session, char * mb)
178{
179 char * new_mb;
180 struct mh_session_state_data * data;
181 int r;
182
183 data = get_data(session);
184
185 new_mb = strdup(mb);
186 if (new_mb == NULL)
187 return -1;
188
189 r = clist_append(data->mh_subscribed_list, new_mb);
190 if (r < 0) {
191 free(mb);
192 return -1;
193 }
194
195 return 0;
196}
197
198static int remove_from_list(mailsession * session, char * mb)
199{
200 clistiter * cur;
201 struct mh_session_state_data * data;
202
203 data = get_data(session);
204
205 for(cur = clist_begin(data->mh_subscribed_list) ;
206 cur != NULL ; cur = clist_next(cur)) {
207 char * cur_name;
208
209 cur_name = clist_content(cur);
210 if (strcmp(cur_name, mb) == 0) {
211 clist_delete(data->mh_subscribed_list, cur);
212 free(cur_name);
213 return 0;
214 }
215 }
216
217 return -1;
218}
219
220static int mhdriver_initialize(mailsession * session)
221{
222 struct mh_session_state_data * data;
223
224 data = malloc(sizeof(* data));
225 if (data == NULL)
226 goto err;
227
228 data->mh_session = NULL;
229 data->mh_cur_folder = NULL;
230
231 data->mh_subscribed_list = clist_new();
232 if (data->mh_subscribed_list == NULL)
233 goto free;
234
235 session->sess_data = data;
236
237 return MAIL_NO_ERROR;
238
239 free:
240 free(data);
241 err:
242 return MAIL_ERROR_MEMORY;
243}
244
245static void mhdriver_uninitialize(mailsession * session)
246{
247 struct mh_session_state_data * data;
248
249 data = get_data(session);
250
251 if (data->mh_session != NULL)
252 mailmh_free(data->mh_session);
253
254 clist_foreach(data->mh_subscribed_list, (clist_func) free, NULL);
255 clist_free(data->mh_subscribed_list);
256
257 free(data);
258
259 session->sess_data = NULL;
260}
261
262
263static int mhdriver_connect_path(mailsession * session, char * path)
264{
265 struct mailmh * mh;
266
267 if (get_mh_session(session) != NULL)
268 return MAIL_ERROR_BAD_STATE;
269
270 mh = mailmh_new(path);
271 if (mh == NULL)
272 return MAIL_ERROR_MEMORY;
273
274 get_data(session)->mh_session = mh;
275
276 return MAIL_NO_ERROR;
277}
278
279static int mhdriver_logout(mailsession * session)
280{
281 struct mailmh * mh;
282
283 mh = get_mh_session(session);
284
285 if (mh == NULL)
286 return MAIL_ERROR_BAD_STATE;
287
288 mailmh_free(mh);
289 get_data(session)->mh_session = NULL;
290
291 return MAIL_NO_ERROR;
292}
293
294/* folders operations */
295
296static int mhdriver_build_folder_name(mailsession * session, char * mb,
297 char * name, char ** result)
298{
299 char * folder_name;
300
301 folder_name = malloc(strlen(mb) + 2 + strlen(name));
302 if (folder_name == NULL)
303 return MAIL_ERROR_MEMORY;
304
305 strcpy(folder_name, mb);
306 strcat(folder_name, "/");
307 strcat(folder_name, name);
308
309 * result = folder_name;
310
311 return MAIL_NO_ERROR;
312}
313
314static int get_parent(mailsession * session, char * mb,
315 struct mailmh_folder ** result_folder,
316 char ** result_name)
317{
318 char * name;
319 size_t length;
320 int i;
321 char * parent_name;
322 struct mailmh_folder * parent;
323 struct mailmh * mh;
324
325 mh = get_mh_session(session);
326 if (mh == NULL)
327 return MAIL_ERROR_BAD_STATE;
328
329 length = strlen(mb);
330 for(i = length - 1 ; i >= 0 ; i--)
331 if (mb[i] == '/')
332 break;
333 name = mb + i + 1;
334
335 parent_name = malloc(i + 1);
336 /* strndup(mb, i) */
337 if (parent_name == NULL)
338 return MAIL_ERROR_MEMORY;
339
340 strncpy(parent_name, mb, i);
341 parent_name[i] = '\0';
342
343 parent = mailmh_folder_find(mh->mh_main, parent_name);
344 free(parent_name);
345 if (parent == NULL)
346 return MAIL_ERROR_FOLDER_NOT_FOUND;
347
348 * result_folder = parent;
349 * result_name = name;
350
351 return MAIL_NO_ERROR;
352}
353
354static int mhdriver_create_folder(mailsession * session, char * mb)
355{
356 int r;
357 struct mailmh_folder * parent;
358 char * name;
359
360 r = get_parent(session, mb, &parent, &name);
361 if (r != MAIL_NO_ERROR)
362 return r;
363
364 r = mailmh_folder_add_subfolder(parent, name);
365
366 return mhdriver_mh_error_to_mail_error(r);
367}
368
369static int mhdriver_delete_folder(mailsession * session, char * mb)
370{
371 int r;
372 struct mailmh_folder * folder;
373 struct mailmh * mh;
374
375 mh = get_mh_session(session);
376 if (mh == NULL)
377 return MAIL_ERROR_BAD_STATE;
378
379 folder = mailmh_folder_find(mh->mh_main, mb);
380 if (folder == NULL)
381 return MAIL_ERROR_FOLDER_NOT_FOUND;
382
383 if (get_mh_cur_folder(session) == folder)
384 get_data(session)->mh_cur_folder = NULL;
385
386 r = mailmh_folder_remove_subfolder(folder);
387
388 return mhdriver_mh_error_to_mail_error(r);
389}
390
391static int mhdriver_rename_folder(mailsession * session, char * mb,
392 char * new_name)
393{
394 struct mailmh_folder * src_folder;
395 struct mailmh_folder * dst_folder;
396 char * name;
397 struct mailmh * mh;
398 int r;
399
400 r = get_parent(session, new_name, &dst_folder, &name);
401 if (r != MAIL_NO_ERROR)
402 return r;
403
404 mh = get_mh_session(session);
405 if (mh == NULL)
406 return MAIL_ERROR_BAD_STATE;
407
408 src_folder = mailmh_folder_find(mh->mh_main, mb);
409 if (src_folder == NULL)
410 return MAIL_ERROR_FOLDER_NOT_FOUND;
411
412 if (get_mh_cur_folder(session) == src_folder)
413 get_data(session)->mh_cur_folder = NULL;
414
415 r = mailmh_folder_rename_subfolder(src_folder, dst_folder, name);
416
417 return mhdriver_mh_error_to_mail_error(r);
418}
419
420static int mhdriver_select_folder(mailsession * session, char * mb)
421{
422 struct mailmh_folder * folder;
423 struct mailmh * mh;
424 int r;
425
426 mh = get_mh_session(session);
427 if (mh == NULL)
428 return MAIL_ERROR_BAD_STATE;
429
430 r = mailmh_folder_update(mh->mh_main);
431
432 folder = mailmh_folder_find(mh->mh_main, mb);
433 if (folder == NULL)
434 return MAIL_ERROR_FOLDER_NOT_FOUND;
435
436 get_data(session)->mh_cur_folder = folder;
437 r = mailmh_folder_update(folder);
438
439 return mhdriver_mh_error_to_mail_error(r);
440}
441
442static int mhdriver_status_folder(mailsession * session, char * mb,
443 uint32_t * result_messages, uint32_t * result_recent,
444 uint32_t * result_unseen)
445{
446 uint32_t count;
447 int r;
448
449 r = mhdriver_messages_number(session, mb, &count);
450 if (r != MAIL_NO_ERROR)
451 return r;
452
453 * result_messages = count;
454 * result_recent = count;
455 * result_unseen = count;
456
457 return MAIL_NO_ERROR;
458}
459
460static int mhdriver_messages_number(mailsession * session, char * mb,
461 uint32_t * result)
462{
463 struct mailmh_folder * folder;
464 uint32_t count;
465 struct mailmh * mh;
466 unsigned int i;
467
468 mh = get_mh_session(session);
469 if (mh == NULL)
470 return MAIL_ERROR_BAD_STATE;
471
472 if (mb != NULL) {
473 folder = mailmh_folder_find(mh->mh_main, mb);
474 if (folder == NULL)
475 return MAIL_ERROR_FOLDER_NOT_FOUND;
476 }
477 else {
478 folder = get_mh_cur_folder(session);
479 if (folder == NULL)
480 return MAIL_ERROR_BAD_STATE;
481 }
482
483 mailmh_folder_update(folder);
484 count = 0;
485 for (i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) {
486 struct mailmh_msg_info * msg_info;
487
488 msg_info = carray_get(folder->fl_msgs_tab, i);
489 if (msg_info != NULL)
490 count ++;
491 }
492
493 * result = count;
494
495 return MAIL_NO_ERROR;
496}
497
498
499static int get_list_folders(struct mailmh_folder * folder, clist ** result)
500{
501 unsigned int i;
502 clist * list;
503 char * new_filename;
504 int res;
505 int r;
506
507 list = * result;
508
509 new_filename = strdup(folder->fl_filename);
510 if (new_filename == NULL) {
511 res = MAIL_ERROR_MEMORY;
512 goto free;
513 }
514
515 r = mailmh_folder_update(folder);
516
517 switch (r) {
518 case MAILMH_NO_ERROR:
519 break;
520
521 default:
522 res = mhdriver_mh_error_to_mail_error(r);
523 goto free;
524 }
525
526 r = clist_append(list, new_filename);
527 if (r < 0) {
528 free(new_filename);
529 res = MAIL_ERROR_MEMORY;
530 goto free;
531 }
532
533 if (folder->fl_subfolders_tab != NULL) {
534 for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) {
535 struct mailmh_folder * subfolder;
536
537 subfolder = carray_get(folder->fl_subfolders_tab, i);
538
539 r = get_list_folders(subfolder, &list);
540 if (r != MAIL_NO_ERROR) {
541 res = MAIL_ERROR_MEMORY;
542 goto free;
543 }
544 }
545 }
546
547 * result = list;
548
549 return MAIL_NO_ERROR;
550
551 free:
552 clist_foreach(list, (clist_func) free, NULL);
553 clist_free(list);
554 return res;
555}
556
557
558static int mhdriver_list_folders(mailsession * session, char * mb,
559 struct mail_list ** result)
560{
561 clist * list;
562 int r;
563 struct mailmh * mh;
564 struct mail_list * ml;
565
566 mh = get_mh_session(session);
567
568 if (mh == NULL)
569 return MAIL_ERROR_BAD_STATE;
570
571 list = clist_new();
572 if (list == NULL)
573 return MAIL_ERROR_MEMORY;
574
575 r = get_list_folders(mh->mh_main, &list);
576 if (r != MAIL_NO_ERROR)
577 return r;
578
579 ml = mail_list_new(list);
580 if (ml == NULL)
581 goto free;
582
583 * result = ml;
584
585 return MAIL_NO_ERROR;
586
587 free:
588 clist_foreach(list, (clist_func) free, NULL);
589 clist_free(list);
590 return MAIL_ERROR_MEMORY;
591}
592
593static int mhdriver_lsub_folders(mailsession * session, char * mb,
594 struct mail_list ** result)
595{
596 clist * subscribed;
597 clist * lsub_result;
598 clistiter * cur;
599 struct mail_list * lsub;
600 size_t length;
601 int r;
602
603 length = strlen(mb);
604
605 subscribed = get_data(session)->mh_subscribed_list;
606
607 lsub_result = clist_new();
608 if (lsub_result == NULL)
609 return MAIL_ERROR_MEMORY;
610
611 for(cur = clist_begin(subscribed) ; cur != NULL ;
612 cur = clist_next(cur)) {
613 char * cur_mb;
614 char * new_mb;
615
616 cur_mb = clist_content(cur);
617
618 if (strncmp(mb, cur_mb, length) == 0) {
619 new_mb = strdup(cur_mb);
620 if (new_mb == NULL)
621 goto free_list;
622
623 r = clist_append(lsub_result, new_mb);
624 if (r < 0) {
625 free(new_mb);
626 goto free_list;
627 }
628 }
629 }
630
631 lsub = mail_list_new(lsub_result);
632 if (lsub == NULL)
633 goto free_list;
634
635 * result = lsub;
636
637 return MAIL_NO_ERROR;
638
639 free_list:
640 clist_foreach(lsub_result, (clist_func) free, NULL);
641 clist_free(lsub_result);
642 return MAIL_ERROR_MEMORY;
643}
644
645static int mhdriver_subscribe_folder(mailsession * session, char * mb)
646{
647 int r;
648
649 r = add_to_list(session, mb);
650 if (r < 0)
651 return MAIL_ERROR_SUBSCRIBE;
652
653 return MAIL_NO_ERROR;
654}
655
656static int mhdriver_unsubscribe_folder(mailsession * session, char * mb)
657{
658 int r;
659
660 r = remove_from_list(session, mb);
661 if (r < 0)
662 return MAIL_ERROR_UNSUBSCRIBE;
663
664 return MAIL_NO_ERROR;
665}
666
667/* messages operations */
668
669static int mhdriver_append_message(mailsession * session,
670 char * message, size_t size)
671{
672 int r;
673 struct mailmh_folder * folder;
674
675 folder = get_mh_cur_folder(session);
676 if (folder == NULL)
677 return MAIL_ERROR_BAD_STATE;
678
679 r = mailmh_folder_add_message(folder, message, size);
680
681 switch (r) {
682 case MAILMH_ERROR_FILE:
683 return MAIL_ERROR_DISKSPACE;
684
685 default:
686 return mhdriver_mh_error_to_mail_error(r);
687 }
688}
689
690static int mhdriver_append_message_flags(mailsession * session,
691 char * message, size_t size, struct mail_flags * flags)
692{
693 return mhdriver_append_message(session, message, size);
694}
695
696static int mhdriver_copy_message(mailsession * session,
697 uint32_t num, char * mb)
698{
699 int fd;
700 int r;
701 struct mailmh_folder * folder;
702 struct mailmh * mh;
703 int res;
704
705 mh = get_mh_session(session);
706 if (mh == NULL) {
707 res = MAIL_ERROR_BAD_STATE;
708 goto err;
709 }
710
711 folder = get_mh_cur_folder(session);
712 if (folder == NULL) {
713 res = MAIL_ERROR_BAD_STATE;
714 goto err;
715 }
716
717 r = mailmh_folder_get_message_fd(folder, num, O_RDONLY, &fd);
718 if (r != MAIL_NO_ERROR) {
719 res = r;
720 goto err;
721 }
722
723 folder = mailmh_folder_find(mh->mh_main, mb);
724 if (folder == NULL) {
725 res = MAIL_ERROR_FOLDER_NOT_FOUND;
726 goto close;
727 }
728
729 r = mailmh_folder_add_message_file(folder, fd);
730 if (r != MAIL_NO_ERROR) {
731 res = MAIL_ERROR_COPY;
732 goto close;
733 }
734
735 close(fd);
736
737 return MAIL_NO_ERROR;
738
739 close:
740 close(fd);
741 err:
742 return res;
743}
744
745static int mhdriver_remove_message(mailsession * session, uint32_t num)
746{
747 int r;
748 struct mailmh_folder * folder;
749
750 folder = get_mh_cur_folder(session);
751 if (folder == NULL)
752 return MAIL_ERROR_DELETE;
753
754 r = mailmh_folder_remove_message(folder, num);
755
756 return mhdriver_mh_error_to_mail_error(r);
757}
758
759static int mhdriver_move_message(mailsession * session,
760 uint32_t num, char * mb)
761{
762 int r;
763 struct mailmh_folder * src_folder;
764 struct mailmh_folder * dest_folder;
765 struct mailmh * mh;
766
767 mh = get_mh_session(session);
768 if (mh == NULL)
769 return MAIL_ERROR_BAD_STATE;
770
771 src_folder = get_mh_cur_folder(session);
772 if (src_folder == NULL)
773 return MAIL_ERROR_BAD_STATE;
774
775 dest_folder = mailmh_folder_find(mh->mh_main, mb);
776 if (dest_folder == NULL)
777 return MAIL_ERROR_FOLDER_NOT_FOUND;
778
779 r = mailmh_folder_move_message(dest_folder, src_folder, num);
780
781 return mhdriver_mh_error_to_mail_error(r);
782}
783
784
785static int mhdriver_get_messages_list(mailsession * session,
786 struct mailmessage_list ** result)
787{
788 struct mailmh_folder * folder;
789 int res;
790
791 folder = get_mh_cur_folder(session);
792 if (folder == NULL) {
793 res = MAIL_ERROR_BAD_STATE;
794 goto err;
795 }
796
797 mailmh_folder_update(folder);
798 return mh_get_messages_list(folder, session, mh_message_driver, result);
799
800 err:
801 return res;
802}
803
804static int mhdriver_get_message(mailsession * session,
805 uint32_t num, mailmessage ** result)
806{
807 mailmessage * msg_info;
808 int r;
809
810 msg_info = mailmessage_new();
811 if (msg_info == NULL)
812 return MAIL_ERROR_MEMORY;
813
814 r = mailmessage_init(msg_info, session, mh_message_driver, num, 0);
815 if (r != MAIL_NO_ERROR) {
816 mailmessage_free(msg_info);
817 return r;
818 }
819
820 * result = msg_info;
821
822 return MAIL_NO_ERROR;
823}
824
825static int mhdriver_get_message_by_uid(mailsession * session,
826 const char * uid,
827 mailmessage ** result)
828{
829 uint32_t index;
830 char *p;
831 struct mailmh_msg_info * mh_msg_info;
832 struct mh_session_state_data * mh_data;
833 chashdatum key;
834 chashdatum data;
835 int r;
836 time_t mtime;
837 char * mtime_p;
838
839 if (uid == NULL)
840 return MAIL_ERROR_INVAL;
841
842 index = strtoul(uid, &p, 10);
843 if (p == uid || * p != '-')
844 return MAIL_ERROR_INVAL;
845
846 mh_data = session->sess_data;
847#if 0
848 mh_msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, index);
849#endif
850 key.data = &index;
851 key.len = sizeof(index);
852 r = chash_get(mh_data->mh_cur_folder->fl_msgs_hash, &key, &data);
853 if (r < 0)
854 return MAIL_ERROR_MSG_NOT_FOUND;
855
856 mh_msg_info = data.data;
857
858 mtime_p = p + 1;
859
860 mtime = strtoul(mtime_p, &p, 10);
861 if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) {
862 size_t size;
863 char *size_p;
864
865 size_p = p + 1;
866 size = strtoul(size_p, &p, 10);
867 if ((* p == '\0') && (size == mh_msg_info->msg_size))
868 return mhdriver_get_message(session, index, result);
869 }
870 else if (* p != '-') {
871 return MAIL_ERROR_INVAL;
872 }
873
874 return MAIL_ERROR_MSG_NOT_FOUND;
875}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_H
37
38#define MHDRIVER_H
39
40#include <libetpan/maildriver.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * mh_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhdriver_cached.h"
37
38#include <stdio.h>
39#include <sys/types.h>
40#include <dirent.h>
41#include <unistd.h>
42#include <sys/stat.h>
43#include <ctype.h>
44#include <fcntl.h>
45#include <sys/mman.h>
46#include <stdlib.h>
47#include <string.h>
48
49#include "mail.h"
50#include "mail_cache_db.h"
51
52#include "generic_cache.h"
53#include "imfcache.h"
54#include "mhdriver.h"
55
56#include "mhdriver_cached_message.h"
57#include "mailmh.h"
58#include "maildriver_tools.h"
59#include "mhdriver_tools.h"
60#include "mailmessage.h"
61
62static int mhdriver_cached_initialize(mailsession * session);
63
64static void mhdriver_cached_uninitialize(mailsession * session);
65
66static int mhdriver_cached_parameters(mailsession * session,
67 int id, void * value);
68
69static int mhdriver_cached_connect_path(mailsession * session, char * path);
70static int mhdriver_cached_logout(mailsession * session);
71
72static int mhdriver_cached_build_folder_name(mailsession * session, char * mb,
73 char * name, char ** result);
74static int mhdriver_cached_create_folder(mailsession * session, char * mb);
75
76static int mhdriver_cached_delete_folder(mailsession * session, char * mb);
77
78static int mhdriver_cached_rename_folder(mailsession * session, char * mb,
79 char * new_name);
80
81static int mhdriver_cached_check_folder(mailsession * session);
82
83static int mhdriver_cached_select_folder(mailsession * session, char * mb);
84
85static int mhdriver_cached_expunge_folder(mailsession * session);
86
87static int mhdriver_cached_status_folder(mailsession * session, char * mb,
88 uint32_t * result_messages, uint32_t * result_recent,
89 uint32_t * result_unseen);
90
91static int mhdriver_cached_messages_number(mailsession * session, char * mb,
92 uint32_t * result);
93static int mhdriver_cached_recent_number(mailsession * session, char * mb,
94 uint32_t * result);
95static int mhdriver_cached_unseen_number(mailsession * session, char * mb,
96 uint32_t * result);
97
98static int mhdriver_cached_list_folders(mailsession * session, char * mb,
99 struct mail_list ** result);
100
101static int mhdriver_cached_lsub_folders(mailsession * session, char * mb,
102 struct mail_list ** result);
103
104static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb);
105
106static int mhdriver_cached_unsubscribe_folder(mailsession * session,
107 char * mb);
108
109static int mhdriver_cached_append_message(mailsession * session,
110 char * message, size_t size);
111static int mhdriver_cached_append_message_flags(mailsession * session,
112 char * message, size_t size, struct mail_flags * flags);
113static int mhdriver_cached_copy_message(mailsession * session,
114 uint32_t num, char * mb);
115
116static int mhdriver_cached_remove_message(mailsession * session,
117 uint32_t num);
118
119static int mhdriver_cached_move_message(mailsession * session,
120 uint32_t num, char * mb);
121
122static int
123mhdriver_cached_get_messages_list(mailsession * session,
124 struct mailmessage_list ** result);
125
126static int
127mhdriver_cached_get_envelopes_list(mailsession * session,
128 struct mailmessage_list * env_list);
129
130static int mhdriver_cached_get_message(mailsession * session,
131 uint32_t num, mailmessage ** result);
132
133static int mhdriver_cached_get_message_by_uid(mailsession * session,
134 const char * uid,
135 mailmessage ** result);
136
137static mailsession_driver local_mh_cached_session_driver = {
138 .sess_name = "mh-cached",
139
140 .sess_initialize = mhdriver_cached_initialize,
141 .sess_uninitialize = mhdriver_cached_uninitialize,
142
143 .sess_parameters = mhdriver_cached_parameters,
144
145 .sess_connect_stream = NULL,
146 .sess_connect_path = mhdriver_cached_connect_path,
147 .sess_starttls = NULL,
148 .sess_login = NULL,
149 .sess_logout = mhdriver_cached_logout,
150 .sess_noop = NULL,
151
152 .sess_build_folder_name = mhdriver_cached_build_folder_name,
153 .sess_create_folder = mhdriver_cached_create_folder,
154 .sess_delete_folder = mhdriver_cached_delete_folder,
155 .sess_rename_folder = mhdriver_cached_rename_folder,
156 .sess_check_folder = mhdriver_cached_check_folder,
157 .sess_examine_folder = NULL,
158 .sess_select_folder = mhdriver_cached_select_folder,
159 .sess_expunge_folder = mhdriver_cached_expunge_folder,
160 .sess_status_folder = mhdriver_cached_status_folder,
161 .sess_messages_number = mhdriver_cached_messages_number,
162 .sess_recent_number = mhdriver_cached_recent_number,
163 .sess_unseen_number = mhdriver_cached_unseen_number,
164 .sess_list_folders = mhdriver_cached_list_folders,
165 .sess_lsub_folders = mhdriver_cached_lsub_folders,
166 .sess_subscribe_folder = mhdriver_cached_subscribe_folder,
167 .sess_unsubscribe_folder = mhdriver_cached_unsubscribe_folder,
168
169 .sess_append_message = mhdriver_cached_append_message,
170 .sess_append_message_flags = mhdriver_cached_append_message_flags,
171 .sess_copy_message = mhdriver_cached_copy_message,
172 .sess_move_message = mhdriver_cached_move_message,
173
174 .sess_get_messages_list = mhdriver_cached_get_messages_list,
175 .sess_get_envelopes_list = mhdriver_cached_get_envelopes_list,
176 .sess_remove_message = mhdriver_cached_remove_message,
177#if 0
178 .sess_search_messages = maildriver_generic_search_messages,
179#endif
180
181 .sess_get_message = mhdriver_cached_get_message,
182 .sess_get_message_by_uid = mhdriver_cached_get_message_by_uid,
183};
184
185mailsession_driver * mh_cached_session_driver =
186&local_mh_cached_session_driver;
187
188#define ENV_NAME "env.db"
189#define FLAGS_NAME "flags.db"
190
191
192static inline struct mh_cached_session_state_data *
193get_cached_data(mailsession * session)
194{
195 return session->sess_data;
196}
197
198static inline mailsession * get_ancestor(mailsession * session)
199{
200 return get_cached_data(session)->mh_ancestor;
201}
202
203static inline struct mh_session_state_data *
204get_ancestor_data(mailsession * session)
205{
206 return get_ancestor(session)->sess_data;
207}
208
209static inline struct mailmh *
210get_mh_session(mailsession * session)
211{
212 return get_ancestor_data(session)->mh_session;
213}
214
215static inline struct mailmh_folder *
216get_mh_cur_folder(mailsession * session)
217{
218 return get_ancestor_data(session)->mh_cur_folder;
219}
220
221
222#define FILENAME_MAX_UID "max-uid"
223
224/* write max uid current value */
225
226static int write_max_uid_value(mailsession * session)
227{
228 int r;
229 char filename[PATH_MAX];
230 FILE * f;
231 int res;
232 struct mh_cached_session_state_data * cached_data;
233 struct mh_session_state_data * ancestor_data;
234 int fd;
235
236 MMAPString * mmapstr;
237 size_t cur_token;
238
239 cached_data = get_cached_data(session);
240 ancestor_data = get_ancestor_data(session);
241
242 if (cached_data->mh_quoted_mb == NULL)
243 return MAIL_ERROR_BAD_STATE;
244
245 snprintf(filename, PATH_MAX, "%s/%s/%s",
246 cached_data->mh_cache_directory,
247 cached_data->mh_quoted_mb, FILENAME_MAX_UID);
248
249 fd = creat(filename, S_IRUSR | S_IWUSR);
250 if (fd < 0) {
251 res = MAIL_ERROR_FILE;
252 goto err;
253 }
254
255 f = fdopen(fd, "w");
256 if (f == NULL) {
257 close(fd);
258 res = MAIL_ERROR_FILE;
259 goto err;
260 }
261
262 mmapstr = mmap_string_new("");
263 if (mmapstr == NULL) {
264 res = MAIL_ERROR_MEMORY;
265 goto close;
266 }
267
268 r = mail_serialize_clear(mmapstr, &cur_token);
269 if (r != MAIL_NO_ERROR) {
270 res = r;
271 goto free_mmapstr;
272 }
273
274 r = mailimf_cache_int_write(mmapstr, &cur_token,
275 ancestor_data->mh_cur_folder->fl_max_index);
276 if (r != MAIL_NO_ERROR) {
277 res = r;
278 goto free_mmapstr;
279 }
280
281 fwrite(mmapstr->str, 1, mmapstr->len, f);
282
283 mmap_string_free(mmapstr);
284 fclose(f);
285
286 return MAIL_NO_ERROR;
287
288 free_mmapstr:
289 mmap_string_free(mmapstr);
290 close:
291 fclose(f);
292 err:
293 return res;
294}
295
296static int read_max_uid_value(mailsession * session)
297{
298 int r;
299 char filename[PATH_MAX];
300 FILE * f;
301 uint32_t written_uid;
302 int res;
303 struct mh_cached_session_state_data * cached_data;
304 struct mh_session_state_data * ancestor_data;
305
306 MMAPString * mmapstr;
307 size_t cur_token;
308 char buf[sizeof(uint32_t)];
309 size_t read_size;
310
311 cached_data = get_cached_data(session);
312 ancestor_data = get_ancestor_data(session);
313
314 snprintf(filename, PATH_MAX, "%s/%s/%s",
315 cached_data->mh_cache_directory,
316 cached_data->mh_quoted_mb, FILENAME_MAX_UID);
317
318 f = fopen(filename, "r");
319 if (f == NULL) {
320 res = MAIL_ERROR_FILE;
321 goto err;
322 }
323
324 read_size = fread(buf, 1, sizeof(uint32_t), f);
325
326 mmapstr = mmap_string_new_len(buf, read_size);
327 if (mmapstr == NULL) {
328 res = MAIL_ERROR_MEMORY;
329 goto close;
330 }
331
332 cur_token = 0;
333
334 r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid);
335 if (r != MAIL_NO_ERROR) {
336 fclose(f);
337 res = r;
338 goto free_mmapstr;
339 }
340
341 mmap_string_free(mmapstr);
342 fclose(f);
343
344 if (written_uid > ancestor_data->mh_cur_folder->fl_max_index)
345 ancestor_data->mh_cur_folder->fl_max_index = written_uid;
346
347 return MAIL_NO_ERROR;
348
349 free_mmapstr:
350 mmap_string_free(mmapstr);
351 close:
352 fclose(f);
353 err:
354 return res;
355}
356
357
358static int mhdriver_cached_initialize(mailsession * session)
359{
360 struct mh_cached_session_state_data * data;
361
362 data = malloc(sizeof(* data));
363 if (data == NULL)
364 goto err;
365
366 data->mh_flags_store = mail_flags_store_new();
367 if (data->mh_flags_store == NULL)
368 goto free;
369
370 data->mh_ancestor = mailsession_new(mh_session_driver);
371 if (data->mh_ancestor == NULL)
372 goto free_store;
373
374 data->mh_quoted_mb = NULL;
375
376 session->sess_data = data;
377
378 return MAIL_NO_ERROR;
379
380 free_store:
381 mail_flags_store_free(data->mh_flags_store);
382 free:
383 free(data);
384 err:
385 return MAIL_ERROR_MEMORY;
386}
387
388static void free_state(struct mh_cached_session_state_data * mh_data)
389{
390 if (mh_data->mh_quoted_mb) {
391 free(mh_data->mh_quoted_mb);
392 mh_data->mh_quoted_mb = NULL;
393 }
394}
395
396static int mh_flags_store_process(char * flags_directory, char * quoted_mb,
397 struct mail_flags_store * flags_store)
398{
399 char filename_flags[PATH_MAX];
400 struct mail_cache_db * cache_db_flags;
401 MMAPString * mmapstr;
402 unsigned int i;
403 int r;
404 int res;
405
406 if (carray_count(flags_store->fls_tab) == 0)
407 return MAIL_NO_ERROR;
408
409 if (quoted_mb == NULL)
410 return MAIL_NO_ERROR;
411
412 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
413 flags_directory, quoted_mb, FLAGS_NAME);
414
415 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
416 if (r < 0) {
417 res = MAIL_ERROR_FILE;
418 goto err;
419 }
420
421 mmapstr = mmap_string_new("");
422 if (mmapstr == NULL) {
423 res = MAIL_ERROR_MEMORY;
424 goto close_db_flags;
425 }
426
427 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
428 mailmessage * msg;
429
430 msg = carray_get(flags_store->fls_tab, i);
431
432 r = mhdriver_write_cached_flags(cache_db_flags, mmapstr,
433 msg->msg_uid, msg->msg_flags);
434 }
435
436 mmap_string_free(mmapstr);
437 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
438
439 mail_flags_store_clear(flags_store);
440
441 return MAIL_NO_ERROR;
442
443 close_db_flags:
444 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
445 err:
446 return res;
447}
448
449static void mhdriver_cached_uninitialize(mailsession * session)
450{
451 struct mh_cached_session_state_data * data;
452
453 data = get_cached_data(session);
454
455 mh_flags_store_process(data->mh_flags_directory, data->mh_quoted_mb,
456 data->mh_flags_store);
457
458 mail_flags_store_free(data->mh_flags_store);
459
460 free_state(data);
461 mailsession_free(data->mh_ancestor);
462 free(data);
463
464 session->sess_data = NULL;
465}
466
467static int mhdriver_cached_parameters(mailsession * session,
468 int id, void * value)
469{
470 struct mh_cached_session_state_data * cached_data;
471 int r;
472
473 cached_data = get_cached_data(session);
474
475 switch (id) {
476 case MHDRIVER_CACHED_SET_CACHE_DIRECTORY:
477 strncpy(cached_data->mh_cache_directory, value, PATH_MAX);
478 cached_data->mh_cache_directory[PATH_MAX - 1] = '\0';
479
480 r = generic_cache_create_dir(cached_data->mh_cache_directory);
481 if (r != MAIL_NO_ERROR)
482 return r;
483
484 return MAIL_NO_ERROR;
485
486 case MHDRIVER_CACHED_SET_FLAGS_DIRECTORY:
487 strncpy(cached_data->mh_flags_directory, value, PATH_MAX);
488 cached_data->mh_flags_directory[PATH_MAX - 1] = '\0';
489
490 r = generic_cache_create_dir(cached_data->mh_flags_directory);
491 if (r != MAIL_NO_ERROR)
492 return r;
493
494 return MAIL_NO_ERROR;
495 }
496
497 return MAIL_ERROR_INVAL;
498}
499
500static int mhdriver_cached_connect_path(mailsession * session, char * path)
501{
502 return mailsession_connect_path(get_ancestor(session), path);
503}
504
505static int mhdriver_cached_logout(mailsession * session)
506{
507 int r;
508 struct mh_cached_session_state_data * cached_data;
509
510 r = write_max_uid_value(session);
511
512 cached_data = get_cached_data(session);
513
514 mh_flags_store_process(cached_data->mh_flags_directory,
515 cached_data->mh_quoted_mb,
516 cached_data->mh_flags_store);
517
518 return mailsession_logout(get_ancestor(session));
519}
520
521static int mhdriver_cached_check_folder(mailsession * session)
522{
523 struct mh_cached_session_state_data * cached_data;
524
525 cached_data = get_cached_data(session);
526
527 mh_flags_store_process(cached_data->mh_flags_directory,
528 cached_data->mh_quoted_mb,
529 cached_data->mh_flags_store);
530
531 return MAIL_NO_ERROR;
532}
533
534/* folders operations */
535
536static int mhdriver_cached_build_folder_name(mailsession * session, char * mb,
537 char * name, char ** result)
538{
539 return mailsession_build_folder_name(get_ancestor(session),
540 mb, name, result);
541}
542
543static int mhdriver_cached_create_folder(mailsession * session, char * mb)
544{
545 return mailsession_create_folder(get_ancestor(session), mb);
546}
547
548static int mhdriver_cached_delete_folder(mailsession * session, char * mb)
549{
550 return mailsession_delete_folder(get_ancestor(session), mb);
551}
552
553static int mhdriver_cached_rename_folder(mailsession * session, char * mb,
554 char * new_name)
555{
556 return mailsession_rename_folder(get_ancestor(session), mb, new_name);
557}
558
559static int get_cache_directory(mailsession * session,
560 char * path, char ** result)
561{
562 char * quoted_mb;
563 char dirname[PATH_MAX];
564 int res;
565 int r;
566 struct mh_cached_session_state_data * cached_data;
567
568 cached_data = get_cached_data(session);
569
570 quoted_mb = maildriver_quote_mailbox(path);
571 if (quoted_mb == NULL) {
572 res = MAIL_ERROR_MEMORY;
573 goto err;
574 }
575
576 snprintf(dirname, PATH_MAX, "%s/%s",
577 cached_data->mh_cache_directory, quoted_mb);
578
579 r = generic_cache_create_dir(dirname);
580 if (r != MAIL_NO_ERROR) {
581 res = r;
582 goto free;
583 }
584
585 snprintf(dirname, PATH_MAX, "%s/%s",
586 cached_data->mh_flags_directory, quoted_mb);
587
588 r = generic_cache_create_dir(dirname);
589 if (r != MAIL_NO_ERROR) {
590 res = r;
591 goto free;
592 }
593
594 * result = quoted_mb;
595
596 return MAIL_NO_ERROR;
597
598 free:
599 free(quoted_mb);
600 err:
601 return res;
602}
603
604static int mhdriver_cached_select_folder(mailsession * session, char * mb)
605{
606 int r;
607 int res;
608 char * quoted_mb;
609 struct mh_cached_session_state_data * cached_data;
610
611 cached_data = get_cached_data(session);
612
613 mh_flags_store_process(cached_data->mh_flags_directory,
614 cached_data->mh_quoted_mb,
615 cached_data->mh_flags_store);
616
617 r = get_cache_directory(session, mb, &quoted_mb);
618 if (r != MAIL_NO_ERROR) {
619 res = r;
620 goto err;
621 }
622
623 r = mailsession_select_folder(get_ancestor(session), mb);
624 if (r != MAIL_NO_ERROR) {
625 res = r;
626 goto free;
627 }
628
629 r = write_max_uid_value(session);
630
631 free_state(cached_data);
632 cached_data->mh_quoted_mb = quoted_mb;
633
634 r = read_max_uid_value(session);
635
636 return MAIL_NO_ERROR;
637
638 free:
639 free(quoted_mb);
640 err:
641 return res;
642}
643
644static int mhdriver_cached_expunge_folder(mailsession * session)
645{
646 struct mailmh_folder * folder;
647 int res;
648 char filename_flags[PATH_MAX];
649 struct mail_cache_db * cache_db_flags;
650 MMAPString * mmapstr;
651 struct mh_cached_session_state_data * cached_data;
652 unsigned int i;
653 int r;
654
655 cached_data = get_cached_data(session);
656 if (cached_data->mh_quoted_mb == NULL) {
657 res = MAIL_ERROR_BAD_STATE;
658 goto err;
659 }
660
661 mh_flags_store_process(cached_data->mh_flags_directory,
662 cached_data->mh_quoted_mb,
663 cached_data->mh_flags_store);
664
665 folder = get_mh_cur_folder(session);
666 if (folder == NULL) {
667 res = MAIL_ERROR_BAD_STATE;
668 goto err;
669 }
670
671 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
672 cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME);
673
674 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
675 if (r < 0) {
676 res = MAIL_ERROR_FILE;
677 goto err;
678 }
679
680 mmapstr = mmap_string_new("");
681 if (mmapstr == NULL) {
682 res = MAIL_ERROR_MEMORY;
683 goto close_db_flags;
684 }
685
686 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
687 struct mailmh_msg_info * mh_info;
688 struct mail_flags * flags;
689
690 mh_info = carray_get(folder->fl_msgs_tab, i);
691 if (mh_info == NULL)
692 continue;
693
694 r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
695 session, mh_info->msg_index, &flags);
696 if (r != MAIL_NO_ERROR)
697 continue;
698
699 if (flags->fl_flags & MAIL_FLAG_DELETED) {
700 r = mailmh_folder_remove_message(folder, mh_info->msg_index);
701 }
702
703 mail_flags_free(flags);
704 }
705
706 mmap_string_free(mmapstr);
707 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
708
709 mailmh_folder_update(folder);
710
711 return MAIL_NO_ERROR;
712
713 close_db_flags:
714 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
715 err:
716 return res;
717}
718
719
720static int mhdriver_cached_status_folder(mailsession * session, char * mb,
721 uint32_t * result_messages,
722 uint32_t * result_recent,
723 uint32_t * result_unseen)
724{
725 struct mailmh_folder * folder;
726 int res;
727 char filename_flags[PATH_MAX];
728 struct mail_cache_db * cache_db_flags;
729 MMAPString * mmapstr;
730 struct mh_cached_session_state_data * cached_data;
731 unsigned int i;
732 int r;
733 uint32_t count;
734 uint32_t recent;
735 uint32_t unseen;
736
737 r = mhdriver_cached_select_folder(session, mb);
738 if (r != MAIL_NO_ERROR) {
739 res = r;
740 goto err;
741 }
742
743 count = 0;
744 recent = 0;
745 unseen = 0;
746
747 folder = get_mh_cur_folder(session);
748 if (folder == NULL) {
749 res = MAIL_ERROR_BAD_STATE;
750 goto err;
751 }
752
753 cached_data = get_cached_data(session);
754 if (cached_data->mh_quoted_mb == NULL) {
755 res = MAIL_ERROR_BAD_STATE;
756 goto err;
757 }
758
759 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
760 cached_data->mh_flags_directory,
761 cached_data->mh_quoted_mb, FLAGS_NAME);
762
763 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
764 if (r < 0) {
765 res = MAIL_ERROR_FILE;
766 goto err;
767 }
768
769 mmapstr = mmap_string_new("");
770 if (mmapstr == NULL) {
771 res = MAIL_ERROR_MEMORY;
772 goto close_db_flags;
773 }
774
775 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
776 struct mailmh_msg_info * mh_info;
777 struct mail_flags * flags;
778
779 mh_info = carray_get(folder->fl_msgs_tab, i);
780 if (mh_info == NULL)
781 continue;
782
783 count ++;
784
785 r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
786 session, mh_info->msg_index,
787 &flags);
788
789 if (r != MAIL_NO_ERROR) {
790 recent ++;
791 unseen ++;
792 continue;
793 }
794
795 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
796 recent ++;
797 }
798 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
799 unseen ++;
800 }
801 mail_flags_free(flags);
802 }
803
804 mmap_string_free(mmapstr);
805 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
806
807 * result_messages = count;
808 * result_recent = recent;
809 * result_unseen = unseen;
810
811 return MAIL_NO_ERROR;
812
813 close_db_flags:
814 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
815 err:
816 return res;
817}
818
819static int mhdriver_cached_messages_number(mailsession * session, char * mb,
820 uint32_t * result)
821{
822 return mailsession_messages_number(get_ancestor(session), mb, result);
823}
824
825static int mhdriver_cached_recent_number(mailsession * session, char * mb,
826 uint32_t * result)
827{
828 uint32_t messages;
829 uint32_t recent;
830 uint32_t unseen;
831 int r;
832
833 r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen);
834 if (r != MAIL_NO_ERROR)
835 return r;
836
837 * result = recent;
838
839 return MAIL_NO_ERROR;
840}
841
842
843static int mhdriver_cached_unseen_number(mailsession * session, char * mb,
844 uint32_t * result)
845{
846 uint32_t messages;
847 uint32_t recent;
848 uint32_t unseen;
849 int r;
850
851 r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen);
852 if (r != MAIL_NO_ERROR)
853 return r;
854
855 * result = recent;
856
857 return MAIL_NO_ERROR;
858}
859
860
861static int mhdriver_cached_list_folders(mailsession * session, char * mb,
862 struct mail_list ** result)
863{
864 return mailsession_list_folders(get_ancestor(session), mb, result);
865}
866
867static int mhdriver_cached_lsub_folders(mailsession * session, char * mb,
868 struct mail_list ** result)
869{
870 return mailsession_lsub_folders(get_ancestor(session), mb, result);
871}
872
873static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb)
874{
875 return mailsession_subscribe_folder(get_ancestor(session), mb);
876}
877
878static int mhdriver_cached_unsubscribe_folder(mailsession * session,
879 char * mb)
880{
881 return mailsession_unsubscribe_folder(get_ancestor(session), mb);
882}
883
884/* messages operations */
885
886static int mhdriver_cached_append_message(mailsession * session,
887 char * message, size_t size)
888{
889 return mhdriver_cached_append_message_flags(session,
890 message, size, NULL);
891}
892
893static int mhdriver_cached_append_message_flags(mailsession * session,
894 char * message, size_t size, struct mail_flags * flags)
895{
896 int r;
897 struct mailmh_folder * folder;
898 struct mailmh_msg_info * msg_info;
899 chashdatum key;
900 chashdatum value;
901 uint32_t uid;
902 struct mh_cached_session_state_data * data;
903 char filename_flags[PATH_MAX];
904 struct mail_cache_db * cache_db_flags;
905 MMAPString * mmapstr;
906 char keyname[PATH_MAX];
907
908 folder = get_mh_cur_folder(session);
909 if (folder == NULL)
910 return MAIL_ERROR_BAD_STATE;
911
912 r = mailmh_folder_add_message_uid(folder,
913 message, size, &uid);
914
915 switch (r) {
916 case MAILMH_ERROR_FILE:
917 return MAIL_ERROR_DISKSPACE;
918
919 case MAILMH_NO_ERROR:
920 break;
921
922 default:
923 return mhdriver_mh_error_to_mail_error(r);
924 }
925
926 if (flags == NULL)
927 goto exit;
928
929 key.data = &uid;
930 key.len = sizeof(uid);
931 r = chash_get(folder->fl_msgs_hash, &key, &value);
932 if (r < 0)
933 return MAIL_ERROR_CACHE_MISS;
934
935 msg_info = value.data;
936
937 data = get_cached_data(session);
938
939 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
940 data->mh_flags_directory, data->mh_quoted_mb, FLAGS_NAME);
941
942 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
943 if (r < 0)
944 goto exit;
945
946 mmapstr = mmap_string_new("");
947 if (mmapstr == NULL)
948 goto close_db_flags;
949
950 snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags",
951 uid, (unsigned long) msg_info->msg_mtime,
952 (unsigned long) msg_info->msg_size);
953
954 r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags);
955
956 mmap_string_free(mmapstr);
957 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
958
959 if (r != MAIL_NO_ERROR)
960 goto exit;
961
962 return MAIL_NO_ERROR;
963
964 close_db_flags:
965 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
966 exit:
967 return MAIL_NO_ERROR;
968}
969
970static int mhdriver_cached_copy_message(mailsession * session,
971 uint32_t num, char * mb)
972{
973 return mailsession_copy_message(get_ancestor(session), num, mb);
974}
975
976static int mhdriver_cached_remove_message(mailsession * session, uint32_t num)
977{
978 return mailsession_remove_message(get_ancestor(session), num);
979}
980
981static int mhdriver_cached_move_message(mailsession * session,
982 uint32_t num, char * mb)
983{
984 return mailsession_move_message(get_ancestor(session), num, mb);
985}
986
987static int
988mhdriver_cached_get_messages_list(mailsession * session,
989 struct mailmessage_list ** result)
990{
991 struct mailmh_folder * folder;
992 int res;
993
994 folder = get_mh_cur_folder(session);
995 if (folder == NULL) {
996 res = MAIL_ERROR_BAD_STATE;
997 goto err;
998 }
999
1000 return mh_get_messages_list(folder, session,
1001 mh_cached_message_driver, result);
1002
1003 err:
1004 return res;
1005}
1006
1007
1008
1009static int
1010get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
1011 mailsession * session, uint32_t num,
1012 struct mailimf_fields ** result)
1013{
1014 int r;
1015 char keyname[PATH_MAX];
1016 struct mailimf_fields * fields;
1017 int res;
1018 struct mailmh_folder * folder;
1019 struct mailmh_msg_info * msg_info;
1020 chashdatum key;
1021 chashdatum data;
1022
1023 folder = get_mh_cur_folder(session);
1024
1025#if 0
1026 msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num);
1027 if (msg_info == NULL)
1028 return MAIL_ERROR_CACHE_MISS;
1029#endif
1030 key.data = &num;
1031 key.len = sizeof(num);
1032 r = chash_get(folder->fl_msgs_hash, &key, &data);
1033 if (r < 0)
1034 return MAIL_ERROR_CACHE_MISS;
1035 msg_info = data.data;
1036
1037 snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope",
1038 num, (unsigned long) msg_info->msg_mtime,
1039 (unsigned long) msg_info->msg_size);
1040
1041 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
1042 if (r != MAIL_NO_ERROR) {
1043 res = r;
1044 goto err;
1045 }
1046
1047 * result = fields;
1048
1049 return MAIL_NO_ERROR;
1050
1051 err:
1052 return res;
1053}
1054
1055static int
1056write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
1057 mailsession * session, uint32_t num,
1058 struct mailimf_fields * fields)
1059{
1060 int r;
1061 char keyname[PATH_MAX];
1062 int res;
1063 struct mailmh_folder * folder;
1064 chashdatum key;
1065 chashdatum data;
1066 struct mailmh_msg_info * msg_info;
1067
1068 folder = get_mh_cur_folder(session);
1069#if 0
1070 msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num);
1071 if (msg_info == NULL) {
1072 res = MAIL_ERROR_CACHE_MISS;
1073 goto err;
1074 }
1075#endif
1076 key.data = &num;
1077 key.len = sizeof(num);
1078 r = chash_get(folder->fl_msgs_hash, &key, &data);
1079 if (r < 0)
1080 return MAIL_ERROR_CACHE_MISS;
1081 msg_info = data.data;
1082
1083 snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope",
1084 num, (unsigned long) msg_info->msg_mtime,
1085 (unsigned long) msg_info->msg_size);
1086
1087 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
1088 if (r != MAIL_NO_ERROR) {
1089 res = r;
1090 goto err;
1091 }
1092
1093 return MAIL_NO_ERROR;
1094
1095 err:
1096 return res;
1097}
1098
1099static int
1100mhdriver_cached_get_envelopes_list(mailsession * session,
1101 struct mailmessage_list * env_list)
1102{
1103 int r;
1104 unsigned int i;
1105 char filename_env[PATH_MAX];
1106 char filename_flags[PATH_MAX];
1107 struct mail_cache_db * cache_db_env;
1108 struct mail_cache_db * cache_db_flags;
1109 MMAPString * mmapstr;
1110 int res;
1111 struct mh_cached_session_state_data * cached_data;
1112
1113 cached_data = get_cached_data(session);
1114 if (cached_data->mh_quoted_mb == NULL) {
1115 res = MAIL_ERROR_BAD_STATE;
1116 goto err;
1117 }
1118
1119 mh_flags_store_process(cached_data->mh_flags_directory,
1120 cached_data->mh_quoted_mb,
1121 cached_data->mh_flags_store);
1122
1123 mmapstr = mmap_string_new("");
1124 if (mmapstr == NULL) {
1125 res = MAIL_ERROR_MEMORY;
1126 goto err;
1127 }
1128
1129 snprintf(filename_env, PATH_MAX, "%s/%s/%s",
1130 cached_data->mh_cache_directory,
1131 cached_data->mh_quoted_mb, ENV_NAME);
1132
1133 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
1134 if (r < 0) {
1135 res = MAIL_ERROR_MEMORY;
1136 goto free_mmapstr;
1137 }
1138
1139 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
1140 cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME);
1141
1142 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
1143 if (r < 0) {
1144 res = MAIL_ERROR_MEMORY;
1145 goto close_db_env;
1146 }
1147
1148 /* fill with cached */
1149
1150 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1151 mailmessage * msg;
1152 struct mailimf_fields * fields;
1153 struct mail_flags * flags;
1154
1155 msg = carray_get(env_list->msg_tab, i);
1156
1157 if (msg->msg_fields == NULL) {
1158 r = get_cached_envelope(cache_db_env, mmapstr,
1159 msg->msg_session, msg->msg_index, &fields);
1160 if (r == MAIL_NO_ERROR) {
1161 msg->msg_cached = TRUE;
1162 msg->msg_fields = fields;
1163 }
1164 }
1165
1166 if (msg->msg_flags == NULL) {
1167 r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
1168 session, msg->msg_index, &flags);
1169 if (r == MAIL_NO_ERROR) {
1170 msg->msg_flags = flags;
1171 }
1172 }
1173 }
1174
1175 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
1176 mail_cache_db_close_unlock(filename_env, cache_db_env);
1177
1178 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
1179
1180 if (r != MAIL_NO_ERROR) {
1181 res = r;
1182 goto free_mmapstr;
1183 }
1184
1185 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
1186 if (r < 0) {
1187 res = MAIL_ERROR_MEMORY;
1188 goto free_mmapstr;
1189 }
1190
1191 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
1192 if (r < 0) {
1193 res = MAIL_ERROR_MEMORY;
1194 goto close_db_env;
1195 }
1196
1197 /* add flags */
1198
1199 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1200 mailmessage * msg;
1201
1202 msg = carray_get(env_list->msg_tab, i);
1203
1204 if (msg->msg_flags == NULL)
1205 msg->msg_flags = mail_flags_new_empty();
1206 }
1207
1208 /* must write cache */
1209
1210 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1211 mailmessage * msg;
1212
1213 msg = carray_get(env_list->msg_tab, i);
1214
1215 if (msg->msg_fields != NULL) {
1216 if (!msg->msg_cached) {
1217 r = write_cached_envelope(cache_db_env, mmapstr,
1218 session, msg->msg_index, msg->msg_fields);
1219 }
1220 }
1221
1222 if (msg->msg_flags != NULL) {
1223 r = mhdriver_write_cached_flags(cache_db_flags, mmapstr,
1224 msg->msg_uid, msg->msg_flags);
1225 }
1226 }
1227
1228 /* flush cache */
1229
1230 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
1231
1232 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
1233 mail_cache_db_close_unlock(filename_env, cache_db_env);
1234
1235 mmap_string_free(mmapstr);
1236
1237 return MAIL_NO_ERROR;
1238
1239 close_db_env:
1240 mail_cache_db_close_unlock(filename_env, cache_db_env);
1241 free_mmapstr:
1242 mmap_string_free(mmapstr);
1243 err:
1244 return res;
1245}
1246
1247static int mhdriver_cached_get_message(mailsession * session,
1248 uint32_t num, mailmessage ** result)
1249{
1250 mailmessage * msg_info;
1251 int r;
1252
1253 msg_info = mailmessage_new();
1254 if (msg_info == NULL)
1255 return MAIL_ERROR_MEMORY;
1256
1257 r = mailmessage_init(msg_info, session, mh_cached_message_driver, num, 0);
1258 if (r != MAIL_NO_ERROR)
1259 return r;
1260
1261 * result = msg_info;
1262
1263 return MAIL_NO_ERROR;
1264}
1265
1266static int mhdriver_cached_get_message_by_uid(mailsession * session,
1267 const char * uid,
1268 mailmessage ** result)
1269{
1270 uint32_t index;
1271 char *p;
1272 struct mailmh_msg_info * mh_msg_info;
1273 struct mailmh_folder * folder;
1274 time_t mtime;
1275 char * mtime_p;
1276 chashdatum key;
1277 chashdatum data;
1278 int r;
1279
1280 if (uid == NULL)
1281 return MAIL_ERROR_INVAL;
1282
1283 index = strtoul(uid, &p, 10);
1284 if (p == uid || * p != '-')
1285 return MAIL_ERROR_INVAL;
1286
1287 folder = get_mh_cur_folder(session);
1288
1289 mh_msg_info = NULL;
1290 key.data = &index;
1291 key.len = sizeof(index);
1292 r = chash_get(folder->fl_msgs_hash, &key, &data);
1293 if (r < 0)
1294 return MAIL_ERROR_MSG_NOT_FOUND;
1295
1296 mh_msg_info = data.data;
1297
1298 mtime_p = p + 1;
1299
1300 mtime = strtoul(mtime_p, &p, 10);
1301 if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) {
1302 size_t size;
1303 char *size_p;
1304
1305 size_p = p + 1;
1306 size = strtoul(size_p, &p, 10);
1307 if ((* p == '\0') && (size == mh_msg_info->msg_size))
1308 return mhdriver_cached_get_message(session, index, result);
1309 }
1310 else if (*p != '-') {
1311 return MAIL_ERROR_INVAL;
1312 }
1313
1314 return MAIL_ERROR_MSG_NOT_FOUND;
1315}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_CACHED_H
37
38#define MHDRIVER_CACHED_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * mh_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhdriver_message.h"
37
38#include "mailmessage_tools.h"
39#include "mhdriver_tools.h"
40#include "mhdriver_cached.h"
41#include "mailmh.h"
42#include "generic_cache.h"
43
44#include "mail_cache_db.h"
45
46#include <unistd.h>
47#include <sys/mman.h>
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <string.h>
52#include <stdlib.h>
53
54static int mh_prefetch(mailmessage * msg_info);
55
56static void mh_prefetch_free(struct generic_message_t * msg);
57
58static int mh_initialize(mailmessage * msg_info);
59
60static int mh_fetch_size(mailmessage * msg_info,
61 size_t * result);
62
63static int mh_get_flags(mailmessage * msg_info,
64 struct mail_flags ** result);
65
66static void mh_uninitialize(mailmessage * msg_info);
67
68static void mh_flush(mailmessage * msg_info);
69
70static void mh_check(mailmessage * msg_info);
71
72static int mh_fetch_header(mailmessage * msg_info,
73 char ** result,
74 size_t * result_len);
75
76static mailmessage_driver local_mh_cached_message_driver = {
77 .msg_name = "mh-cached",
78
79 .msg_initialize = mh_initialize,
80 .msg_uninitialize = mh_uninitialize,
81
82 .msg_flush = mh_flush,
83 .msg_check = mh_check,
84
85 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
86
87 .msg_fetch = mailmessage_generic_fetch,
88 .msg_fetch_header = mh_fetch_header,
89 .msg_fetch_body = mailmessage_generic_fetch_body,
90 .msg_fetch_size = mh_fetch_size,
91 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
92 .msg_fetch_section = mailmessage_generic_fetch_section,
93 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
94 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
95 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
96 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
97
98 .msg_get_flags = mh_get_flags,
99};
100
101mailmessage_driver * mh_cached_message_driver =
102&local_mh_cached_message_driver;
103
104static inline struct mh_cached_session_state_data *
105get_cached_session_data(mailmessage * msg)
106{
107 return msg->msg_session->sess_data;
108}
109
110static inline mailsession * get_ancestor_session(mailmessage * msg)
111{
112 return get_cached_session_data(msg)->mh_ancestor;
113}
114
115static inline struct mh_session_state_data *
116get_ancestor_session_data(mailmessage * msg)
117{
118 return get_ancestor_session(msg)->sess_data;
119}
120
121static inline struct mailmh *
122get_mh_session(mailmessage * msg)
123{
124 return get_ancestor_session_data(msg)->mh_session;
125}
126
127static inline struct mailmh_folder *
128get_mh_cur_folder(mailmessage * msg)
129{
130 return get_ancestor_session_data(msg)->mh_cur_folder;
131}
132
133static int mh_prefetch(mailmessage * msg_info)
134{
135 struct generic_message_t * msg;
136 int r;
137 char * msg_content;
138 size_t msg_length;
139
140 r = mhdriver_fetch_message(get_ancestor_session(msg_info),
141 msg_info->msg_index, &msg_content, &msg_length);
142 if (r != MAIL_NO_ERROR)
143 return r;
144
145 msg = msg_info->msg_data;
146
147 msg->msg_message = msg_content;
148 msg->msg_length = msg_length;
149
150 return MAIL_NO_ERROR;
151}
152
153static void mh_prefetch_free(struct generic_message_t * msg)
154{
155 if (msg->msg_message != NULL) {
156 mmap_string_unref(msg->msg_message);
157 msg->msg_message = NULL;
158 }
159}
160
161static int mh_initialize(mailmessage * msg_info)
162{
163 struct generic_message_t * msg;
164 int r;
165 char * uid;
166 char static_uid[PATH_MAX];
167 struct mailmh_msg_info * mh_msg_info;
168 chashdatum key;
169 chashdatum data;
170 struct mailmh_folder * folder;
171
172 folder = get_mh_cur_folder(msg_info);
173
174 key.data = &msg_info->msg_index;
175 key.len = sizeof(msg_info->msg_index);
176 r = chash_get(folder->fl_msgs_hash, &key, &data);
177 if (r < 0)
178 return MAIL_ERROR_INVAL;
179
180 mh_msg_info = data.data;
181
182 snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index,
183 mh_msg_info->msg_mtime, (unsigned long) mh_msg_info->msg_size);
184 uid = strdup(static_uid);
185 if (uid == NULL)
186 return MAIL_ERROR_MEMORY;
187
188 r = mailmessage_generic_initialize(msg_info);
189 if (r != MAIL_NO_ERROR) {
190 free(uid);
191 return r;
192 }
193
194 msg = msg_info->msg_data;
195 msg->msg_prefetch = mh_prefetch;
196 msg->msg_prefetch_free = mh_prefetch_free;
197 msg_info->msg_uid = uid;
198
199 return MAIL_NO_ERROR;
200}
201
202static void mh_uninitialize(mailmessage * msg_info)
203{
204 mailmessage_generic_uninitialize(msg_info);
205}
206
207
208#define FLAGS_NAME "flags.db"
209
210static void mh_flush(mailmessage * msg_info)
211{
212 mailmessage_generic_flush(msg_info);
213}
214
215static void mh_check(mailmessage * msg_info)
216{
217 int r;
218
219 if (msg_info->msg_flags != NULL) {
220 r = mail_flags_store_set(get_cached_session_data(msg_info)->mh_flags_store,
221 msg_info);
222 /* ignore errors */
223 }
224}
225
226static int mh_fetch_size(mailmessage * msg_info,
227 size_t * result)
228{
229 int r;
230 size_t size;
231
232 r = mhdriver_fetch_size(get_ancestor_session(msg_info),
233 msg_info->msg_index, &size);
234 if (r != MAIL_NO_ERROR)
235 return r;
236
237 * result = size;
238
239 return MAIL_NO_ERROR;
240}
241
242static int mh_get_flags(mailmessage * msg_info,
243 struct mail_flags ** result)
244{
245 int r;
246 struct mail_flags * flags;
247 struct mail_cache_db * cache_db_flags;
248 char filename_flags[PATH_MAX];
249 int res;
250 struct mh_cached_session_state_data * cached_data;
251 MMAPString * mmapstr;
252
253 if (msg_info->msg_flags != NULL) {
254 * result = msg_info->msg_flags;
255
256 return MAIL_NO_ERROR;
257 }
258
259 cached_data = get_cached_session_data(msg_info);
260
261 flags = mail_flags_store_get(cached_data->mh_flags_store,
262 msg_info->msg_index);
263
264 if (flags == NULL) {
265 if (cached_data->mh_quoted_mb == NULL) {
266 res = MAIL_ERROR_BAD_STATE;
267 goto err;
268 }
269
270 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
271 cached_data->mh_flags_directory,
272 cached_data->mh_quoted_mb, FLAGS_NAME);
273
274 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
275 if (r < 0) {
276 res = MAIL_ERROR_MEMORY;
277 goto err;
278 }
279
280 mmapstr = mmap_string_new("");
281 if (mmapstr == NULL) {
282 res = MAIL_ERROR_MEMORY;
283 goto close_db_flags;
284 }
285
286 r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
287 msg_info->msg_session, msg_info->msg_index, &flags);
288 if (r != MAIL_NO_ERROR) {
289 flags = mail_flags_new_empty();
290 if (flags == NULL) {
291 res = MAIL_ERROR_MEMORY;
292 goto free_mmapstr;
293 }
294 }
295
296 mmap_string_free(mmapstr);
297 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
298 }
299
300 msg_info->msg_flags = flags;
301
302 * result = flags;
303
304 return MAIL_NO_ERROR;
305
306 free_mmapstr:
307 mmap_string_free(mmapstr);
308 close_db_flags:
309 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
310 err:
311 return res;
312}
313
314static int mh_fetch_header(mailmessage * msg_info,
315 char ** result,
316 size_t * result_len)
317{
318 struct generic_message_t * msg;
319 int r;
320 char * msg_content;
321 size_t msg_length;
322
323 msg = msg_info->msg_data;
324 if (msg->msg_message != NULL) {
325 return mailmessage_generic_fetch_header(msg_info, result, result_len);
326 }
327 else {
328 r = mhdriver_fetch_header(get_ancestor_session(msg_info),
329 msg_info->msg_index, &msg_content, &msg_length);
330 if (r != MAIL_NO_ERROR)
331 return r;
332
333 * result = msg_content;
334 * result_len = msg_length;
335
336 return MAIL_NO_ERROR;
337 }
338}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_CACHED_MESSAGE_H
37
38#define MHDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mh_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhdriver_message.h"
37
38#include "mailmessage_tools.h"
39#include "mhdriver_tools.h"
40#include "mhdriver.h"
41#include "mailmh.h"
42
43#include <unistd.h>
44#include <sys/mman.h>
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <fcntl.h>
48#include <string.h>
49#include <stdlib.h>
50
51static int mh_prefetch(mailmessage * msg_info);
52
53static void mh_prefetch_free(struct generic_message_t * msg);
54
55static int mh_initialize(mailmessage * msg_info);
56
57static int mh_fetch_size(mailmessage * msg_info,
58 size_t * result);
59
60static int mh_fetch_header(mailmessage * msg_info,
61 char ** result,
62 size_t * result_len);
63
64static mailmessage_driver local_mh_message_driver = {
65 .msg_name = "mh",
66
67 .msg_initialize = mh_initialize,
68 .msg_uninitialize = mailmessage_generic_uninitialize,
69
70 .msg_flush = mailmessage_generic_flush,
71 .msg_check = NULL,
72
73 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
74
75 .msg_fetch = mailmessage_generic_fetch,
76 .msg_fetch_header = mh_fetch_header,
77 .msg_fetch_body = mailmessage_generic_fetch_body,
78 .msg_fetch_size = mh_fetch_size,
79 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
80 .msg_fetch_section = mailmessage_generic_fetch_section,
81 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
82 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
83 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
84 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
85
86 .msg_get_flags = NULL,
87};
88
89mailmessage_driver * mh_message_driver = &local_mh_message_driver;
90
91static int mh_prefetch(mailmessage * msg_info)
92{
93 struct generic_message_t * msg;
94 int r;
95 char * msg_content;
96 size_t msg_length;
97
98 r = mhdriver_fetch_message(msg_info->msg_session, msg_info->msg_index,
99 &msg_content, &msg_length);
100 if (r != MAIL_NO_ERROR)
101 return r;
102
103 msg = msg_info->msg_data;
104
105 msg->msg_message = msg_content;
106 msg->msg_length = msg_length;
107
108 return MAIL_NO_ERROR;
109}
110
111static void mh_prefetch_free(struct generic_message_t * msg)
112{
113 if (msg->msg_message != NULL) {
114 mmap_string_unref(msg->msg_message);
115 msg->msg_message = NULL;
116 }
117}
118
119static inline struct mh_session_state_data * get_data(mailmessage * msg)
120{
121 return msg->msg_session->sess_data;
122}
123
124static inline struct mailmh_folder * get_mh_cur_folder(mailmessage * msg)
125{
126 return get_data(msg)->mh_cur_folder;
127}
128
129static int mh_initialize(mailmessage * msg_info)
130{
131 struct generic_message_t * msg;
132 int r;
133 char * uid;
134 char static_uid[PATH_MAX];
135 struct mailmh_msg_info * mh_msg_info;
136 chashdatum key;
137 chashdatum value;
138
139 key.data = &msg_info->msg_index;
140 key.len = sizeof(msg_info->msg_index);
141 r = chash_get(get_mh_cur_folder(msg_info)->fl_msgs_hash, &key, &value);
142 if (r < 0)
143 return MAIL_ERROR_INVAL;
144
145 mh_msg_info = value.data;
146
147 snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index,
148 (unsigned long) mh_msg_info->msg_mtime,
149 (unsigned long) mh_msg_info->msg_size);
150 uid = strdup(static_uid);
151 if (uid == NULL)
152 return MAIL_ERROR_MEMORY;
153
154 r = mailmessage_generic_initialize(msg_info);
155 if (r != MAIL_NO_ERROR) {
156 free(uid);
157 return r;
158 }
159
160 msg = msg_info->msg_data;
161 msg->msg_prefetch = mh_prefetch;
162 msg->msg_prefetch_free = mh_prefetch_free;
163 msg_info->msg_uid = uid;
164
165 return MAIL_NO_ERROR;
166}
167
168
169static int mh_fetch_size(mailmessage * msg_info,
170 size_t * result)
171{
172 int r;
173 size_t size;
174
175 r = mhdriver_fetch_size(msg_info->msg_session, msg_info->msg_index, &size);
176 if (r != MAIL_NO_ERROR)
177 return r;
178
179 * result = size;
180
181 return MAIL_NO_ERROR;
182}
183
184
185
186
187static int mh_fetch_header(mailmessage * msg_info,
188 char ** result,
189 size_t * result_len)
190{
191 struct generic_message_t * msg;
192 int r;
193 char * msg_content;
194 size_t msg_length;
195
196 msg = msg_info->msg_data;
197 if (msg->msg_message != NULL) {
198
199 r = mailmessage_generic_fetch_header(msg_info, result, result_len);
200 return r;
201 }
202 else {
203 r = mhdriver_fetch_header(msg_info->msg_session, msg_info->msg_index,
204 &msg_content, &msg_length);
205 if (r != MAIL_NO_ERROR)
206 return r;
207
208 * result = msg_content;
209 * result_len = msg_length;
210
211 return MAIL_NO_ERROR;
212 }
213}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_MESSAGE_H
37
38#define MHDRIVER_MESSAGE_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mh_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhdriver_tools.h"
37
38#include "mailmessage.h"
39#include "mhdriver.h"
40#include "mhdriver_cached.h"
41#include "maildriver_types.h"
42#include "mailmh.h"
43#include "generic_cache.h"
44#include "imfcache.h"
45#include "mail_cache_db.h"
46
47#include <unistd.h>
48#include <sys/mman.h>
49#include <sys/types.h>
50#include <sys/stat.h>
51#include <fcntl.h>
52#include <string.h>
53#include <stdlib.h>
54
55int mhdriver_mh_error_to_mail_error(int error)
56{
57 switch (error) {
58 case MAILMH_NO_ERROR:
59 return MAIL_NO_ERROR;
60
61 case MAILMH_ERROR_FOLDER:
62 return MAIL_ERROR_FOLDER;
63
64 case MAILMH_ERROR_MEMORY:
65 return MAIL_ERROR_MEMORY;
66
67 case MAILMH_ERROR_FILE:
68 return MAIL_ERROR_FILE;
69
70 case MAILMH_ERROR_COULD_NOT_ALLOC_MSG:
71 return MAIL_ERROR_APPEND;
72
73 case MAILMH_ERROR_RENAME:
74 return MAIL_ERROR_RENAME;
75
76 case MAILMH_ERROR_MSG_NOT_FOUND:
77 return MAIL_ERROR_MSG_NOT_FOUND;
78
79 default:
80 return MAIL_ERROR_INVAL;
81 }
82}
83
84
85static inline struct mh_session_state_data * get_data(mailsession * session)
86{
87 return session->sess_data;
88}
89
90static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session)
91{
92 return get_data(session)->mh_cur_folder;
93}
94
95static inline struct mh_cached_session_state_data *
96cached_get_data(mailsession * session)
97{
98 return session->sess_data;
99}
100
101
102static inline mailsession * cached_get_ancestor(mailsession * session)
103{
104 return cached_get_data(session)->mh_ancestor;
105}
106
107static inline struct mh_session_state_data *
108cached_get_ancestor_data(mailsession * session)
109{
110 return get_data(cached_get_ancestor(session));
111}
112
113static inline struct mailmh_folder *
114cached_get_mh_cur_folder(mailsession * session)
115{
116 return get_mh_cur_folder(cached_get_ancestor(session));
117}
118
119int mhdriver_fetch_message(mailsession * session, uint32_t index,
120 char ** result, size_t * result_len)
121{
122 size_t size;
123 size_t cur_token;
124 struct mailmh_folder * folder;
125 int fd;
126 MMAPString * mmapstr;
127 char * str;
128 int res;
129 int r;
130
131 folder = get_mh_cur_folder(session);
132 if (folder == NULL) {
133 res = MAIL_ERROR_BAD_STATE;
134 goto err;
135 }
136
137 r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd);
138
139 switch (r) {
140 case MAILMH_NO_ERROR:
141 break;
142
143 default:
144 res = mhdriver_mh_error_to_mail_error(r);
145 goto close;
146 }
147
148 r = mhdriver_fetch_size(session, index, &size);
149
150 switch (r) {
151 case MAILMH_NO_ERROR:
152 break;
153
154 default:
155 res = mhdriver_mh_error_to_mail_error(r);
156 goto close;
157 }
158
159 str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
160 if (str == MAP_FAILED) {
161 res = MAIL_ERROR_FETCH;
162 goto close;
163 }
164
165 /* strip "From " header for broken implementations */
166 /* XXX - called twice, make a function */
167 cur_token = 0;
168 if (strncmp("From ", str, 5) == 0) {
169 cur_token += 5;
170
171 while (1) {
172 if (str[cur_token] == '\n') {
173 cur_token ++;
174 break;
175 }
176 if (cur_token >= size)
177 break;
178 cur_token ++;
179 }
180 }
181
182 mmapstr = mmap_string_new_len(str + cur_token, size - cur_token);
183 if (mmapstr == NULL) {
184 res = MAIL_ERROR_MEMORY;
185 goto unmap;
186 }
187
188 if (mmap_string_ref(mmapstr) != 0) {
189 res = MAIL_ERROR_MEMORY;
190 goto free_str;
191 }
192
193 munmap(str, size);
194 close(fd);
195
196 * result = mmapstr->str;
197 * result_len = mmapstr->len;
198
199 return MAIL_NO_ERROR;
200
201 free_str:
202 mmap_string_free(mmapstr);
203 unmap:
204 munmap(str, size);
205 close:
206 close(fd);
207 err:
208 return res;
209}
210
211
212int mhdriver_fetch_header(mailsession * session, uint32_t index,
213 char ** result, size_t * result_len)
214{
215 size_t size;
216 size_t cur_token;
217 size_t begin;
218 struct mailmh_folder * folder;
219 int fd;
220 MMAPString * mmapstr;
221 char * str;
222 int res;
223 int r;
224
225 folder = get_mh_cur_folder(session);
226 if (folder == NULL) {
227 res = MAIL_ERROR_BAD_STATE;
228 goto err;
229 }
230
231 r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd);
232
233 switch (r) {
234 case MAILMH_NO_ERROR:
235 break;
236
237 default:
238 res = mhdriver_mh_error_to_mail_error(r);
239 goto close;
240 }
241
242 r = mhdriver_fetch_size(session, index, &size);
243
244 switch (r) {
245 case MAILMH_NO_ERROR:
246 break;
247
248 default:
249 res = mhdriver_mh_error_to_mail_error(r);
250 goto close;
251 }
252
253 str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
254 if (str == MAP_FAILED) {
255 res = MAIL_ERROR_FETCH;
256 goto close;
257 }
258
259 /* strip "From " header for broken implementations */
260 cur_token = 0;
261 if (size > 5) {
262 if (strncmp("From ", str, 5) == 0) {
263 cur_token += 5;
264
265 while (1) {
266 if (str[cur_token] == '\n') {
267 cur_token ++;
268 break;
269 }
270 if (cur_token >= size)
271 break;
272 cur_token ++;
273 }
274 }
275 }
276
277 begin = cur_token;
278
279 while (1) {
280 r = mailimf_ignore_field_parse(str, size, &cur_token);
281 if (r == MAILIMF_NO_ERROR) {
282 /* do nothing */
283 }
284 else
285 break;
286 }
287 mailimf_crlf_parse(str, size, &cur_token);
288
289 mmapstr = mmap_string_new_len(str + begin, cur_token - begin);
290 if (mmapstr == NULL) {
291 res = MAIL_ERROR_MEMORY;
292 goto unmap;
293 }
294
295 if (mmap_string_ref(mmapstr) != 0) {
296 res = MAIL_ERROR_MEMORY;
297 goto free_str;
298 }
299
300 munmap(str, size);
301 close(fd);
302
303 * result = mmapstr->str;
304 * result_len = mmapstr->len;
305
306 return MAIL_NO_ERROR;
307
308 free_str:
309 mmap_string_free(mmapstr);
310 unmap:
311 munmap(str, size);
312 close:
313 close(fd);
314 err:
315 return res;
316}
317
318
319int mhdriver_fetch_size(mailsession * session, uint32_t index,
320 size_t * result)
321{
322 struct mailmh_folder * folder;
323 int r;
324 struct stat buf;
325 char * name;
326
327 folder = get_mh_cur_folder(session);
328 if (folder == NULL)
329 return MAIL_ERROR_FETCH;
330
331 r = mailmh_folder_get_message_filename(folder, index, &name);
332
333 switch (r) {
334 case MAILMH_NO_ERROR:
335 break;
336
337 default:
338 return mhdriver_mh_error_to_mail_error(r);
339 }
340
341 r = stat(name, &buf);
342 free(name);
343 if (r == -1)
344 return MAIL_ERROR_FETCH;
345
346 * result = buf.st_size;
347
348 return MAIL_NO_ERROR;
349}
350
351int
352mhdriver_get_cached_flags(struct mail_cache_db * cache_db,
353 MMAPString * mmapstr,
354 mailsession * session,
355 uint32_t num,
356 struct mail_flags ** result)
357{
358 int r;
359 char keyname[PATH_MAX];
360 struct mail_flags * flags;
361 int res;
362 struct mailmh_msg_info * msg_info;
363 chashdatum key;
364 chashdatum data;
365 struct mailmh_folder * folder;
366
367 folder = cached_get_mh_cur_folder(session);
368#if 0
369 msg_info = cinthash_find(mh_data->cur_folder->fl_msgs_hash, num);
370 if (msg_info == NULL)
371 return MAIL_ERROR_CACHE_MISS;
372#endif
373 key.data = &num;
374 key.len = sizeof(num);
375 r = chash_get(folder->fl_msgs_hash, &key, &data);
376 if (r < 0)
377 return MAIL_ERROR_CACHE_MISS;
378 msg_info = data.data;
379
380 snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags",
381 num, (unsigned long) msg_info->msg_mtime,
382 (unsigned long) msg_info->msg_size);
383
384 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
385 if (r != MAIL_NO_ERROR) {
386 res = r;
387 goto err;
388 }
389
390 * result = flags;
391
392 return MAIL_NO_ERROR;
393
394 err:
395 return res;
396}
397
398int
399mhdriver_write_cached_flags(struct mail_cache_db * cache_db,
400 MMAPString * mmapstr,
401 char * uid,
402 struct mail_flags * flags)
403{
404 int r;
405 char keyname[PATH_MAX];
406 int res;
407
408 snprintf(keyname, PATH_MAX, "%s-flags", uid);
409
410 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
411 if (r != MAIL_NO_ERROR) {
412 res = r;
413 goto err;
414 }
415
416 return MAIL_NO_ERROR;
417
418 err:
419 return res;
420}
421
422
423int mh_get_messages_list(struct mailmh_folder * folder,
424 mailsession * session, mailmessage_driver * driver,
425 struct mailmessage_list ** result)
426{
427 unsigned int i;
428 struct mailmessage_list * env_list;
429 int r;
430 carray * tab;
431 int res;
432
433 tab = carray_new(128);
434 if (tab == NULL) {
435 res = MAIL_ERROR_MEMORY;
436 goto err;
437 }
438
439 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
440 struct mailmh_msg_info * mh_info;
441 mailmessage * msg;
442
443 mh_info = carray_get(folder->fl_msgs_tab, i);
444 if (mh_info == NULL)
445 continue;
446
447 msg = mailmessage_new();
448 if (msg == NULL) {
449 res = MAIL_ERROR_MEMORY;
450 goto free_list;
451 }
452
453 r = mailmessage_init(msg, session, driver,
454 mh_info->msg_index, mh_info->msg_size);
455 if (r != MAIL_NO_ERROR) {
456 res = r;
457 goto free_list;
458 }
459
460 r = carray_add(tab, msg, NULL);
461 if (r < 0) {
462 mailmessage_free(msg);
463 res = MAIL_ERROR_MEMORY;
464 goto free_list;
465 }
466 }
467
468 env_list = mailmessage_list_new(tab);
469 if (env_list == NULL) {
470 res = MAIL_ERROR_MEMORY;
471 goto free_list;
472 }
473
474 * result = env_list;
475
476 return MAIL_NO_ERROR;
477
478 free_list:
479 for(i = 0 ; i < carray_count(tab) ; i ++)
480 mailmessage_free(carray_get(tab, i));
481 carray_free(tab);
482 err:
483 return res;
484}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_TOOLS_H
37
38#define MHDRIVER_TOOLS_H
39
40#include "maildriver_types.h"
41#include "mail_cache_db_types.h"
42#include "mailmh.h"
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48int mhdriver_mh_error_to_mail_error(int error);
49
50int mhdriver_fetch_message(mailsession * session, uint32_t index,
51 char ** result, size_t * result_len);
52
53int mhdriver_fetch_header(mailsession * session, uint32_t index,
54 char ** result, size_t * result_len);
55
56int mhdriver_fetch_size(mailsession * session, uint32_t index,
57 size_t * result);
58
59int
60mhdriver_get_cached_flags(struct mail_cache_db * cache_db,
61 MMAPString * mmapstr,
62 mailsession * session,
63 uint32_t num,
64 struct mail_flags ** result);
65
66int
67mhdriver_write_cached_flags(struct mail_cache_db * cache_db,
68 MMAPString * mmapstr,
69 char * uid,
70 struct mail_flags * flags);
71
72int mh_get_messages_list(struct mailmh_folder * folder,
73 mailsession * session, mailmessage_driver * driver,
74 struct mailmessage_list ** result);
75
76#ifdef __cplusplus
77}
78#endif
79
80#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_TYPES_H
37
38#define MHDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/mailmh.h>
44#include <libetpan/clist.h>
45#include <libetpan/generic_cache_types.h>
46#include <libetpan/mailstorage_types.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52struct mh_session_state_data {
53 struct mailmh * mh_session;
54
55 struct mailmh_folder * mh_cur_folder;
56
57 clist * mh_subscribed_list;
58};
59
60enum {
61 MHDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
62 MHDRIVER_CACHED_SET_FLAGS_DIRECTORY,
63};
64
65struct mh_cached_session_state_data {
66 mailsession * mh_ancestor;
67 char * mh_quoted_mb;
68 char mh_cache_directory[PATH_MAX];
69 char mh_flags_directory[PATH_MAX];
70 struct mail_flags_store * mh_flags_store;
71};
72
73/* mh storage */
74
75/*
76 mh_mailstorage is the state data specific to the MH storage.
77
78 - pathname is the root path of the MH storage.
79
80 - cached if this value is != 0, a persistant cache will be
81 stored on local system.
82
83 - cache_directory is the location of the cache.
84
85 - flags_directory is the location of the flags.
86*/
87
88struct mh_mailstorage {
89 char * mh_pathname;
90
91 int mh_cached;
92 char * mh_cache_directory;
93 char * mh_flags_directory;
94};
95
96#ifdef __cplusplus
97}
98#endif
99
100#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhstorage.h"
37
38#include "mhdriver.h"
39#include "mhdriver_cached.h"
40#include "mail.h"
41
42#include <stdlib.h>
43#include <string.h>
44
45/* mh storage */
46
47static int mh_mailstorage_connect(struct mailstorage * storage);
48static int mh_mailstorage_get_folder_session(struct mailstorage * storage,
49 char * pathname, mailsession ** result);
50static void mh_mailstorage_uninitialize(struct mailstorage * storage);
51
52static mailstorage_driver mh_mailstorage_driver = {
53 .sto_name = "mh",
54 .sto_connect = mh_mailstorage_connect,
55 .sto_get_folder_session = mh_mailstorage_get_folder_session,
56 .sto_uninitialize = mh_mailstorage_uninitialize,
57};
58
59int mh_mailstorage_init(struct mailstorage * storage,
60 char * mh_pathname, int mh_cached,
61 char * mh_cache_directory, char * mh_flags_directory)
62{
63 struct mh_mailstorage * mh_storage;
64
65 mh_storage = malloc(sizeof(* mh_storage));
66 if (mh_storage == NULL)
67 goto err;
68
69 mh_storage->mh_pathname = strdup(mh_pathname);
70 if (mh_storage->mh_pathname == NULL)
71 goto free;
72
73 mh_storage->mh_cached = mh_cached;
74
75 if (mh_cached && (mh_cache_directory != NULL) &&
76 (mh_flags_directory != NULL)) {
77 mh_storage->mh_cache_directory = strdup(mh_cache_directory);
78 if (mh_storage->mh_cache_directory == NULL)
79 goto free_pathname;
80 mh_storage->mh_flags_directory = strdup(mh_flags_directory);
81 if (mh_storage->mh_flags_directory == NULL)
82 goto free_cache_directory;
83 }
84 else {
85 mh_storage->mh_cached = FALSE;
86 mh_storage->mh_cache_directory = NULL;
87 mh_storage->mh_flags_directory = NULL;
88 }
89
90 storage->sto_data = mh_storage;
91 storage->sto_driver = &mh_mailstorage_driver;
92
93 return MAIL_NO_ERROR;
94
95 free_cache_directory:
96 free(mh_storage->mh_cache_directory);
97 free_pathname:
98 free(mh_storage->mh_pathname);
99 free:
100 free(mh_storage);
101 err:
102 return MAIL_ERROR_MEMORY;
103}
104
105static void mh_mailstorage_uninitialize(struct mailstorage * storage)
106{
107 struct mh_mailstorage * mh_storage;
108
109 mh_storage = storage->sto_data;
110 if (mh_storage->mh_flags_directory != NULL)
111 free(mh_storage->mh_flags_directory);
112 if (mh_storage->mh_cache_directory != NULL)
113 free(mh_storage->mh_cache_directory);
114 free(mh_storage->mh_pathname);
115 free(mh_storage);
116
117 storage->sto_data = NULL;
118}
119
120static int mh_mailstorage_connect(struct mailstorage * storage)
121{
122 struct mh_mailstorage * mh_storage;
123 mailsession_driver * driver;
124 int r;
125 int res;
126 mailsession * session;
127
128 mh_storage = storage->sto_data;
129
130 if (mh_storage->mh_cached)
131 driver = mh_cached_session_driver;
132 else
133 driver = mh_session_driver;
134
135 session = mailsession_new(driver);
136 if (session == NULL) {
137 res = MAIL_ERROR_MEMORY;
138 goto err;
139 }
140
141 if (mh_storage->mh_cached) {
142 r = mailsession_parameters(session,
143 MHDRIVER_CACHED_SET_CACHE_DIRECTORY,
144 mh_storage->mh_cache_directory);
145 if (r != MAIL_NO_ERROR) {
146 res = r;
147 goto free;
148 }
149
150 r = mailsession_parameters(session,
151 MHDRIVER_CACHED_SET_FLAGS_DIRECTORY,
152 mh_storage->mh_flags_directory);
153 if (r != MAIL_NO_ERROR) {
154 res = r;
155 goto free;
156 }
157 }
158
159 r = mailsession_connect_path(session, mh_storage->mh_pathname);
160 switch (r) {
161 case MAIL_NO_ERROR_NON_AUTHENTICATED:
162 case MAIL_NO_ERROR_AUTHENTICATED:
163 case MAIL_NO_ERROR:
164 break;
165 default:
166 res = r;
167 goto free;
168 }
169
170 storage->sto_session = session;
171
172 return MAIL_NO_ERROR;
173
174 free:
175 mailsession_free(session);
176 err:
177 return res;
178}
179
180static int mh_mailstorage_get_folder_session(struct mailstorage * storage,
181 char * pathname, mailsession ** result)
182{
183 int r;
184
185 r = mailsession_select_folder(storage->sto_session, pathname);
186 if (r != MAIL_NO_ERROR)
187 return r;
188
189 * result = storage->sto_session;
190
191 return MAIL_NO_ERROR;
192}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHSTORAGE_H
37
38#define MHSTORAGE_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mh_mailstorage_init is the constructor for a MH storage
48
49 @param pathname is the filename the root path of the MH storage.
50
51 @param cached if this value is != 0, a persistant cache will be
52 stored on local system.
53
54 @param cache_directory is the location of the cache.
55
56 @param flags_directory is the location of the flags.
57*/
58
59int mh_mailstorage_init(struct mailstorage * storage,
60 char * mh_pathname, int mh_cached,
61 char * mh_cache_directory, char * mh_flags_directory);
62
63#ifdef __cplusplus
64}
65#endif
66
67#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mime_message_driver.h"
37
38#include "libetpan-config.h"
39
40#include <sys/stat.h>
41#include <sys/types.h>
42#include <unistd.h>
43#include <sys/mman.h>
44#include <stdlib.h>
45#include <string.h>
46
47#include "mailmessage.h"
48#include "mailmessage_tools.h"
49#include "maildriver_tools.h"
50
51#if 0
52static FILE * get_mime_tmp_file(mailmessage * msg,
53 char * filename, size_t size)
54{
55 int fd;
56 mode_t old_mask;
57 FILE * f;
58
59 if (msg->msg_data == NULL)
60 return NULL;
61
62 snprintf(filename, size, "%s/libetpan-mime-XXXXXX",
63 (char *) msg->msg_data);
64
65 old_mask = umask(0077);
66 fd = mkstemp(filename);
67 umask(old_mask);
68 if (fd == -1)
69 return NULL;
70
71 f = fdopen(fd, "r+");
72 if (f == NULL) {
73 close(fd);
74 unlink(filename);
75 }
76
77 return f;
78}
79#endif
80
81int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir)
82{
83#if 0
84 if (msg->msg_data != NULL)
85 free(msg->msg_data);
86
87 msg->msg_data = strdup(tmpdir);
88 if (msg->msg_data == NULL)
89 return MAIL_ERROR_MEMORY;
90
91#endif
92 return MAIL_NO_ERROR;
93}
94
95void mime_message_detach_mime(mailmessage * msg)
96{
97 msg->msg_mime = NULL;
98}
99
100mailmessage * mime_message_init(struct mailmime * mime)
101{
102 mailmessage * msg;
103 int r;
104
105 msg = mailmessage_new();
106 if (msg == NULL)
107 goto err;
108
109 r = mailmessage_init(msg, NULL, mime_message_driver, 0, 0);
110 if (r != MAIL_NO_ERROR)
111 goto free;
112
113 if (mime != NULL) {
114 mailmime_free(msg->msg_mime);
115 msg->msg_mime = mime;
116 }
117
118 return msg;
119
120 free:
121 mailmessage_free(msg);
122 err:
123 return NULL;
124}
125
126static int initialize(mailmessage * msg)
127{
128 struct mailmime * mime;
129 int res;
130
131 mime = mailmime_new_message_data(NULL);
132 if (mime == NULL) {
133 res = MAIL_ERROR_MEMORY;
134 goto err;
135 }
136
137 msg->msg_mime = mime;
138
139 return MAIL_NO_ERROR;
140
141 err:
142 return res;
143}
144
145static void uninitialize(mailmessage * msg)
146{
147 /* tmp dir name */
148 if (msg->msg_data != NULL)
149 free(msg->msg_data);
150
151 if (msg->msg_mime != NULL)
152 mailmime_free(msg->msg_mime);
153 msg->msg_mime = NULL;
154}
155
156static void flush(mailmessage * msg)
157{
158 /* do nothing */
159}
160
161static void check(mailmessage * msg)
162{
163 /* do nothing */
164}
165
166static void fetch_result_free(mailmessage * msg_info, char * content)
167{
168 mmap_string_unref(content);
169}
170
171#if 0
172static int file_to_mmapstr(FILE * f,
173 char ** result, size_t * result_len)
174{
175 int fd;
176 char * data;
177 struct stat buf;
178 MMAPString * mmapstr;
179 int res;
180 int r;
181
182 fd = fileno(f);
183 if (fd == -1) {
184 res = MAIL_ERROR_FILE;
185
186 goto err;
187 }
188
189 fflush(f);
190 r = fstat(fd, &buf);
191 if (r == -1) {
192 res = MAIL_ERROR_FILE;
193
194 goto err;
195 }
196
197 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
198 if (data == MAP_FAILED) {
199 res = MAIL_ERROR_FILE;
200
201 goto err;
202 }
203
204 mmapstr = mmap_string_new_len(data, buf.st_size);
205 if (mmapstr == NULL) {
206 res = MAIL_ERROR_MEMORY;
207
208 goto unmap;
209 }
210
211 munmap(data, buf.st_size);
212
213 r = mmap_string_ref(mmapstr);
214 if (r != 0) {
215 res = MAIL_ERROR_MEMORY;
216
217 goto err;
218 }
219
220 * result = mmapstr->str;
221 * result_len = mmapstr->len;
222
223 return MAIL_NO_ERROR;
224
225 unmap:
226 munmap(data, buf.st_size);
227 err:
228 return res;
229}
230#endif
231
232#if 0
233static int file_body_to_mmapstr(FILE * f,
234 char ** result, size_t * result_len)
235{
236 int fd;
237 char * data;
238 struct stat buf;
239 MMAPString * mmapstr;
240 size_t cur_token;
241 int res;
242 int r;
243
244 fd = fileno(f);
245 if (fd == -1) {
246 res = MAIL_ERROR_FILE;
247
248 goto err;
249 }
250
251 fflush(f);
252 r = fstat(fd, &buf);
253 if (r == -1) {
254 res = MAIL_ERROR_FILE;
255
256 goto err;
257 }
258
259 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
260 if (data == MAP_FAILED) {
261 res = MAIL_ERROR_FILE;
262
263 goto err;
264 }
265
266 cur_token = 0;
267
268 /* skip header */
269
270 while (1) {
271 r = mailimf_ignore_field_parse(data,
272 buf.st_size, &cur_token);
273 if (r == MAILIMF_NO_ERROR) {
274 /* do nothing */
275 }
276 else
277 break;
278 }
279
280 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
281 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
282 res = maildriver_imf_error_to_mail_error(r);
283 goto unmap;
284 }
285
286 mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token);
287 if (mmapstr == NULL) {
288 res = MAIL_ERROR_MEMORY;
289
290 goto unmap;
291 }
292
293 munmap(data, buf.st_size);
294
295 r = mmap_string_ref(mmapstr);
296 if (r != 0) {
297 res = MAIL_ERROR_MEMORY;
298
299 goto err;
300 }
301
302 * result = mmapstr->str;
303 * result_len = mmapstr->len;
304
305 return MAIL_NO_ERROR;
306
307 unmap:
308 munmap(data, buf.st_size);
309 err:
310 return res;
311}
312#endif
313
314
315static int body_to_mmapstr(char * data, size_t size,
316 char ** result, size_t * result_len)
317{
318 MMAPString * mmapstr;
319 size_t cur_token;
320 int res;
321 int r;
322
323 cur_token = 0;
324
325 /* skip header */
326
327 while (1) {
328 r = mailimf_ignore_field_parse(data, size, &cur_token);
329 if (r == MAILIMF_NO_ERROR) {
330 /* do nothing */
331 }
332 else
333 break;
334 }
335
336 r = mailimf_crlf_parse(data, size, &cur_token);
337 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
338 res = maildriver_imf_error_to_mail_error(r);
339 goto err;
340 }
341
342 mmapstr = mmap_string_new_len(data + cur_token, size - cur_token);
343 if (mmapstr == NULL) {
344 res = MAIL_ERROR_MEMORY;
345
346 goto err;
347 }
348
349 r = mmap_string_ref(mmapstr);
350 if (r != 0) {
351 mmap_string_free(mmapstr);
352 res = MAIL_ERROR_MEMORY;
353
354 goto err;
355 }
356
357 * result = mmapstr->str;
358 * result_len = mmapstr->len;
359
360 return MAIL_NO_ERROR;
361
362 err:
363 return res;
364}
365
366
367#if 0
368static int file_body_body_to_mmapstr(FILE * f,
369 char ** result, size_t * result_len)
370{
371 int fd;
372 char * data;
373 struct stat buf;
374 MMAPString * mmapstr;
375 size_t cur_token;
376 int res;
377 int r;
378
379 fd = fileno(f);
380 if (fd == -1) {
381 res = MAIL_ERROR_FILE;
382
383 goto err;
384 }
385
386 fflush(f);
387 r = fstat(fd, &buf);
388 if (r == -1) {
389 res = MAIL_ERROR_FILE;
390
391 goto err;
392 }
393
394 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
395 if (data == MAP_FAILED) {
396 res = MAIL_ERROR_FILE;
397
398 goto err;
399 }
400
401 cur_token = 0;
402
403 /* skip header */
404
405 /* MIME header */
406
407 while (1) {
408 r = mailimf_ignore_field_parse(data,
409 buf.st_size, &cur_token);
410 if (r == MAILIMF_NO_ERROR) {
411 /* do nothing */
412 }
413 else
414 break;
415 }
416
417 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
418 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
419 res = maildriver_imf_error_to_mail_error(r);
420 goto unmap;
421 }
422
423 /* headers */
424
425 while (1) {
426 r = mailimf_ignore_field_parse(data,
427 buf.st_size, &cur_token);
428 if (r == MAILIMF_NO_ERROR) {
429 /* do nothing */
430 }
431 else
432 break;
433 }
434
435 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
436 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
437 res = maildriver_imf_error_to_mail_error(r);
438 goto unmap;
439 }
440
441 mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token);
442 if (mmapstr == NULL) {
443 res = MAIL_ERROR_MEMORY;
444
445 goto unmap;
446 }
447
448 munmap(data, buf.st_size);
449
450 r = mmap_string_ref(mmapstr);
451 if (r != 0) {
452 res = MAIL_ERROR_MEMORY;
453
454 goto err;
455 }
456
457 * result = mmapstr->str;
458 * result_len = mmapstr->len;
459
460 return MAIL_NO_ERROR;
461
462 unmap:
463 munmap(data, buf.st_size);
464 err:
465 return res;
466}
467#endif
468
469static int body_body_to_mmapstr(char * data, size_t size,
470 char ** result, size_t * result_len)
471{
472 MMAPString * mmapstr;
473 size_t cur_token;
474 int res;
475 int r;
476
477 cur_token = 0;
478
479 /* skip header */
480
481 /* MIME header */
482
483 while (1) {
484 r = mailimf_ignore_field_parse(data, size, &cur_token);
485 if (r == MAILIMF_NO_ERROR) {
486 /* do nothing */
487 }
488 else
489 break;
490 }
491
492 r = mailimf_crlf_parse(data, size, &cur_token);
493 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
494 res = maildriver_imf_error_to_mail_error(r);
495 goto err;
496 }
497
498 return body_to_mmapstr(data + cur_token, size - cur_token,
499 result, result_len);
500
501 err:
502 return res;
503}
504
505
506static int fetch_section(mailmessage * msg_info,
507 struct mailmime * mime,
508 char ** result, size_t * result_len)
509{
510 int r;
511#if 0
512 FILE * f;
513#endif
514 int res;
515 int col;
516#if 0
517 char filename[PATH_MAX];
518#endif
519 MMAPString * str;
520
521 if (msg_info->msg_mime == NULL)
522 return MAIL_ERROR_INVAL;
523
524#if 0
525 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
526 if (f == NULL) {
527 res = MAIL_ERROR_FILE;
528 goto err;
529 }
530#endif
531
532 str = mmap_string_new("");
533 if (str == NULL) {
534 res = MAILIMF_ERROR_MEMORY;
535 goto err;
536 }
537
538 col = 0;
539 r = mailmime_write_mem(str, &col, mime);
540 if (r != MAILIMF_NO_ERROR) {
541 res = maildriver_imf_error_to_mail_error(r);
542 goto free;
543 }
544
545#if 0
546 if (mime->mm_parent == NULL)
547 r = file_to_mmapstr(f, result, result_len);
548 else
549 r = file_body_to_mmapstr(f, result, result_len);
550#endif
551 if (mime->mm_parent == NULL) {
552 r = mmap_string_ref(str);
553 if (r < 0) {
554 res = MAIL_ERROR_MEMORY;
555 goto free;
556 }
557
558 * result = str->str;
559 * result_len = str->len;
560
561 r = MAIL_NO_ERROR;
562 }
563 else {
564 r = body_to_mmapstr(str->str, str->len, result, result_len);
565 if (r == MAIL_NO_ERROR) {
566 mmap_string_free(str);
567 }
568 }
569
570 if (r != MAIL_NO_ERROR) {
571 res = r;
572 goto free;
573 }
574
575#if 0
576 fclose(f);
577 unlink(filename);
578#endif
579
580 return MAIL_NO_ERROR;
581
582 free:
583#if 0
584 fclose(f);
585 unlink(filename);
586#endif
587 mmap_string_free(str);
588 err:
589 return res;
590}
591
592
593static int fetch_section_header(mailmessage * msg_info,
594 struct mailmime * mime,
595 char ** result, size_t * result_len)
596{
597 int r;
598#if 0
599 FILE * f;
600#endif
601 int res;
602 int col;
603#if 0
604 char filename[PATH_MAX];
605#endif
606 MMAPString * str;
607
608 if (msg_info->msg_mime == NULL)
609 return MAIL_ERROR_INVAL;
610
611#if 0
612 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
613 if (f == NULL) {
614 res = MAIL_ERROR_FILE;
615 goto err;
616 }
617#endif
618
619 str = mmap_string_new("");
620 if (str == NULL) {
621 res = MAIL_ERROR_MEMORY;
622 goto err;
623 }
624
625 col = 0;
626 if (mime->mm_type == MAILMIME_MESSAGE) {
627 if (mime->mm_data.mm_message.mm_fields != NULL) {
628#if 0
629 r = mailimf_fields_write(f, &col, mime->mm_data.mm_message.mm_fields);
630#endif
631 r = mailimf_fields_write_mem(str, &col, mime->mm_data.mm_message.mm_fields);
632 if (r != MAILIMF_NO_ERROR) {
633 res = maildriver_imf_error_to_mail_error(r);
634 goto free;
635 }
636#if 0
637 mailimf_string_write(f, &col, "\r\n", 2);
638#endif
639 mailimf_string_write_mem(str, &col, "\r\n", 2);
640 }
641 }
642
643 r = mmap_string_ref(str);
644 if (r < 0) {
645 res = MAIL_ERROR_MEMORY;
646 goto free;
647 }
648
649#if 0
650 r = file_to_mmapstr(f, result, result_len);
651 if (r != MAIL_NO_ERROR) {
652 res = r;
653 goto free;
654 }
655#endif
656 * result = str->str;
657 * result_len = str->len;
658
659#if 0
660 fclose(f);
661 unlink(filename);
662#endif
663
664 return MAIL_NO_ERROR;
665
666#if 0
667 close:
668 fclose(f);
669 unlink(filename);
670#endif
671 free:
672 mmap_string_free(str);
673 err:
674 return res;
675}
676
677
678static int fetch_section_mime(mailmessage * msg_info,
679 struct mailmime * mime,
680 char ** result, size_t * result_len)
681{
682 int r;
683#if 0
684 FILE * f;
685#endif
686 int res;
687 int col;
688#if 0
689 char filename[PATH_MAX];
690#endif
691 MMAPString * str;
692
693 if (msg_info->msg_mime == NULL)
694 return MAIL_ERROR_INVAL;
695
696 str = mmap_string_new("");
697 if (str == NULL) {
698 res = MAIL_ERROR_MEMORY;
699 goto err;
700 }
701
702#if 0
703 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
704 if (f == NULL) {
705 res = MAIL_ERROR_FILE;
706 goto err;
707 }
708#endif
709
710 col = 0;
711 if (mime->mm_content_type != NULL) {
712#if 0
713 r = mailmime_content_write(f, &col, mime->mm_content_type);
714#endif
715 r = mailmime_content_write_mem(str, &col, mime->mm_content_type);
716 if (r != MAILIMF_NO_ERROR) {
717 res = maildriver_imf_error_to_mail_error(r);
718 goto free;
719 }
720 }
721 if (mime->mm_mime_fields != NULL) {
722 r = mailmime_fields_write_mem(str, &col, mime->mm_mime_fields);
723 if (r != MAILIMF_NO_ERROR) {
724 res = maildriver_imf_error_to_mail_error(r);
725 goto free;
726 }
727 }
728 mailimf_string_write_mem(str, &col, "\r\n", 2);
729
730#if 0
731 r = file_to_mmapstr(f, result, result_len);
732 if (r != MAIL_NO_ERROR) {
733 res = r;
734 goto free;
735 }
736
737 fclose(f);
738 unlink(filename);
739#endif
740
741 r = mmap_string_ref(str);
742 if (r < 0) {
743 res = MAIL_ERROR_MEMORY;
744 goto free;
745 }
746
747 * result = str->str;
748 * result_len = str->len;
749
750 return MAIL_NO_ERROR;
751
752#if 0
753 close:
754 fclose(f);
755 unlink(filename);
756#endif
757 free:
758 mmap_string_free(str);
759 err:
760 return res;
761}
762
763
764
765static int fetch_section_body(mailmessage * msg_info,
766 struct mailmime * mime,
767 char ** result, size_t * result_len)
768{
769 int r;
770#if 0
771 FILE * f;
772#endif
773 int res;
774 int col;
775#if 0
776 char filename[PATH_MAX];
777#endif
778 MMAPString * str;
779
780 if (msg_info->msg_mime == NULL)
781 return MAIL_ERROR_INVAL;
782
783 str = mmap_string_new("");
784 if (str == NULL) {
785 res = MAIL_ERROR_MEMORY;
786 goto err;
787 }
788
789#if 0
790 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
791 if (f == NULL) {
792 res = MAIL_ERROR_FILE;
793 goto err;
794 }
795#endif
796
797 col = 0;
798 if (mime->mm_mime_fields != NULL) {
799#if 0
800 r = mailmime_write(f, &col, mime);
801#endif
802 r = mailmime_write_mem(str, &col, mime);
803 if (r != MAILIMF_NO_ERROR) {
804 res = maildriver_imf_error_to_mail_error(r);
805 goto free;
806 }
807 }
808
809 if (mime->mm_type == MAILMIME_MESSAGE)
810 r = body_body_to_mmapstr(str->str, str->len, result, result_len);
811 else
812 r = body_to_mmapstr(str->str, str->len, result, result_len);
813
814 if (r != MAIL_NO_ERROR) {
815 res = r;
816 goto free;
817 }
818
819 mmap_string_free(str);
820
821#if 0
822 fclose(f);
823 unlink(filename);
824#endif
825
826 return MAIL_NO_ERROR;
827
828#if 0
829 close:
830 fclose(f);
831 unlink(filename);
832#endif
833 free:
834 mmap_string_free(str);
835 err:
836 return res;
837}
838
839
840static int get_bodystructure(mailmessage * msg_info,
841 struct mailmime ** result)
842{
843 if (msg_info->msg_mime == NULL)
844 return MAIL_ERROR_INVAL;
845
846 * result = msg_info->msg_mime;
847
848 return MAIL_NO_ERROR;
849}
850
851
852static int fetch(mailmessage * msg_info,
853 char ** result, size_t * result_len)
854{
855 return fetch_section(msg_info, msg_info->msg_mime, result, result_len);
856}
857
858static int fetch_header(mailmessage * msg_info,
859 char ** result, size_t * result_len)
860{
861 return fetch_section_header(msg_info,
862 msg_info->msg_mime, result, result_len);
863}
864
865static int fetch_body(mailmessage * msg_info,
866 char ** result, size_t * result_len)
867{
868 return fetch_section_body(msg_info, msg_info->msg_mime, result, result_len);
869}
870
871
872static int fetch_size(mailmessage * msg_info,
873 size_t * result)
874{
875 char * msg;
876 int r;
877
878 r = fetch(msg_info, &msg, result);
879 if (r != MAIL_NO_ERROR) {
880 return r;
881 }
882
883 fetch_result_free(msg_info, msg);
884
885 return MAIL_NO_ERROR;
886}
887
888
889static mailmessage_driver local_mime_message_driver = {
890 .msg_name = "mime",
891
892 .msg_initialize = initialize,
893 .msg_uninitialize = uninitialize,
894
895 .msg_flush = flush,
896 .msg_check = check,
897
898 .msg_fetch_result_free = fetch_result_free,
899
900 .msg_fetch = fetch,
901 .msg_fetch_header = fetch_header,
902 .msg_fetch_body = fetch_body,
903 .msg_fetch_size = fetch_size,
904 .msg_get_bodystructure = get_bodystructure,
905 .msg_fetch_section = fetch_section,
906 .msg_fetch_section_header = fetch_section_header,
907 .msg_fetch_section_mime = fetch_section_mime,
908 .msg_fetch_section_body = fetch_section_body,
909 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
910
911 .msg_get_flags = NULL,
912};
913
914mailmessage_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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MIME_MESSAGE_DRIVER_H
37
38#define MIME_MESSAGE_DRIVER_H
39
40#include <libetpan/mailmessage.h>
41
42#define LIBETPAN_MIME_MESSAGE
43
44extern mailmessage_driver * mime_message_driver;
45
46mailmessage * mime_message_init(struct mailmime * mime);
47
48void mime_message_detach_mime(mailmessage * msg);
49
50/* deprecated */
51int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir);
52
53#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpdriver.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "mail.h"
42#include "mailmessage.h"
43#include "nntpdriver_tools.h"
44#include "maildriver_tools.h"
45#include "nntpdriver_message.h"
46
47static int nntpdriver_initialize(mailsession * session);
48
49static void nntpdriver_uninitialize(mailsession * session);
50
51static int nntpdriver_parameters(mailsession * session,
52 int id, void * value);
53
54static int nntpdriver_connect_stream(mailsession * session, mailstream * s);
55
56static int nntpdriver_login(mailsession * session,
57 char * userid, char * password);
58
59static int nntpdriver_logout(mailsession * session);
60
61static int nntpdriver_status_folder(mailsession * session, char * mb,
62 uint32_t * result_messages,
63 uint32_t * result_recent,
64 uint32_t * result_unseen);
65
66static int nntpdriver_messages_number(mailsession * session, char * mb,
67 uint32_t * result);
68
69static int nntpdriver_append_message(mailsession * session,
70 char * message, size_t size);
71
72static int nntpdriver_append_message_flags(mailsession * session,
73 char * message, size_t size, struct mail_flags * flags);
74
75static int
76nntpdriver_get_envelopes_list(mailsession * session,
77 struct mailmessage_list * env_list);
78
79
80static int nntpdriver_get_messages_list(mailsession * session,
81 struct mailmessage_list ** result);
82
83static int nntpdriver_list_folders(mailsession * session, char * mb,
84 struct mail_list ** result);
85
86static int nntpdriver_lsub_folders(mailsession * session, char * mb,
87 struct mail_list ** result);
88
89static int nntpdriver_subscribe_folder(mailsession * session, char * mb);
90
91static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb);
92
93static int nntpdriver_get_message(mailsession * session,
94 uint32_t num, mailmessage ** result);
95
96static int nntpdriver_get_message_by_uid(mailsession * session,
97 const char * uid,
98 mailmessage ** result);
99
100static int nntpdriver_noop(mailsession * session);
101
102static mailsession_driver local_nntp_session_driver = {
103 .sess_name = "nntp",
104
105 .sess_initialize = nntpdriver_initialize,
106 .sess_uninitialize = nntpdriver_uninitialize,
107
108 .sess_parameters = nntpdriver_parameters,
109
110 .sess_connect_stream = nntpdriver_connect_stream,
111 .sess_connect_path = NULL,
112 .sess_starttls = NULL,
113 .sess_login = nntpdriver_login,
114 .sess_logout = nntpdriver_logout,
115 .sess_noop = nntpdriver_noop,
116
117 .sess_build_folder_name = NULL,
118 .sess_create_folder = NULL,
119 .sess_delete_folder = NULL,
120 .sess_rename_folder = NULL,
121 .sess_check_folder = NULL,
122 .sess_examine_folder = NULL,
123 .sess_select_folder = nntpdriver_select_folder,
124 .sess_expunge_folder = NULL,
125 .sess_status_folder = nntpdriver_status_folder,
126 .sess_messages_number = nntpdriver_messages_number,
127 .sess_recent_number = nntpdriver_messages_number,
128 .sess_unseen_number = nntpdriver_messages_number,
129 .sess_list_folders = nntpdriver_list_folders,
130 .sess_lsub_folders = nntpdriver_lsub_folders,
131 .sess_subscribe_folder = nntpdriver_subscribe_folder,
132 .sess_unsubscribe_folder = nntpdriver_unsubscribe_folder,
133
134 .sess_append_message = nntpdriver_append_message,
135 .sess_append_message_flags = nntpdriver_append_message_flags,
136 .sess_copy_message = NULL,
137 .sess_move_message = NULL,
138
139 .sess_get_messages_list = nntpdriver_get_messages_list,
140 .sess_get_envelopes_list = nntpdriver_get_envelopes_list,
141 .sess_remove_message = NULL,
142#if 0
143 .sess_search_messages = maildriver_generic_search_messages,
144#endif
145
146 .sess_get_message = nntpdriver_get_message,
147 .sess_get_message_by_uid = nntpdriver_get_message_by_uid,
148};
149
150
151mailsession_driver * nntp_session_driver = &local_nntp_session_driver;
152
153static inline struct nntp_session_state_data *
154get_data(mailsession * session)
155{
156 return session->sess_data;
157}
158
159static inline newsnntp * get_nntp_session(mailsession * session)
160{
161 return get_data(session)->nntp_session;
162}
163
164static int nntpdriver_initialize(mailsession * session)
165{
166 struct nntp_session_state_data * data;
167 newsnntp * nntp;
168
169 nntp = newsnntp_new(0, NULL);
170 if (nntp == NULL)
171 goto err;
172
173 data = malloc(sizeof(* data));
174 if (data == NULL)
175 goto free;
176
177 data->nntp_session = nntp;
178
179 data->nntp_userid = NULL;
180 data->nntp_password = NULL;
181
182 data->nntp_group_info = NULL;
183 data->nntp_group_name = NULL;
184
185 data->nntp_subscribed_list = clist_new();
186 if (data->nntp_subscribed_list == NULL)
187 goto free_data;
188
189 data->nntp_max_articles = 0;
190
191 data->nntp_mode_reader = FALSE;
192
193 session->sess_data = data;
194
195 return MAIL_NO_ERROR;
196
197 free_data:
198 free(data);
199 free:
200 newsnntp_free(nntp);
201 err:
202 return MAIL_ERROR_MEMORY;
203}
204
205static void nntpdriver_uninitialize(mailsession * session)
206{
207 struct nntp_session_state_data * data;
208
209 data = get_data(session);
210
211 clist_foreach(data->nntp_subscribed_list, (clist_func) free, NULL);
212 clist_free(data->nntp_subscribed_list);
213
214 if (data->nntp_group_info != NULL)
215 newsnntp_group_free(data->nntp_group_info);
216
217 if (data->nntp_group_name != NULL)
218 free(data->nntp_group_name);
219
220 if (data->nntp_userid != NULL)
221 free(data->nntp_userid);
222
223 if (data->nntp_password != NULL)
224 free(data->nntp_password);
225
226 newsnntp_free(data->nntp_session);
227 free(data);
228
229 session->sess_data = NULL;
230}
231
232
233static int nntpdriver_parameters(mailsession * session,
234 int id, void * value)
235{
236 struct nntp_session_state_data * data;
237
238 data = get_data(session);
239
240 switch (id) {
241 case NNTPDRIVER_SET_MAX_ARTICLES:
242 {
243 uint32_t * param;
244
245 param = value;
246
247 data->nntp_max_articles = * param;
248 return MAIL_NO_ERROR;
249 }
250 }
251
252 return MAIL_ERROR_INVAL;
253}
254
255
256static int add_to_list(mailsession * session, char * mb)
257{
258 char * new_mb;
259 int r;
260 struct nntp_session_state_data * data;
261
262 data = get_data(session);
263
264 new_mb = strdup(mb);
265 if (new_mb == NULL)
266 return -1;
267
268 r = clist_append(data->nntp_subscribed_list, new_mb);
269 if (r < 0) {
270 free(mb);
271 return -1;
272 }
273
274 return 0;
275}
276
277static int remove_from_list(mailsession * session, char * mb)
278{
279 clistiter * cur;
280 struct nntp_session_state_data * data;
281
282 data = get_data(session);
283
284 for(cur = clist_begin(data->nntp_subscribed_list) ; cur != NULL ;
285 cur = clist_next(cur)) {
286 char * cur_name;
287
288 cur_name = clist_content(cur);
289 if (strcmp(cur_name, mb) == 0) {
290 clist_delete(data->nntp_subscribed_list, cur);
291 free(cur_name);
292 return 0;
293 }
294 }
295
296 return -1;
297}
298
299
300static int nntpdriver_connect_stream(mailsession * session, mailstream * s)
301{
302 int r;
303
304 r = newsnntp_connect(get_nntp_session(session), s);
305
306 switch (r) {
307 case NEWSNNTP_NO_ERROR:
308 return MAIL_NO_ERROR_NON_AUTHENTICATED;
309
310 default:
311 return nntpdriver_nntp_error_to_mail_error(r);
312 }
313}
314
315static int nntpdriver_login(mailsession * session,
316 char * userid, char * password)
317{
318 struct nntp_session_state_data * data;
319 char * new_userid;
320 char * new_password;
321
322 data = get_data(session);
323
324 if (userid != NULL) {
325 new_userid = strdup(userid);
326 if (new_userid == NULL)
327 goto err;
328 }
329 else
330 new_userid = NULL;
331
332 if (password != NULL) {
333 new_password = strdup(password);
334 if (new_password == NULL)
335 goto free_uid;
336 }
337 else
338 new_password = NULL;
339
340 data->nntp_userid = new_userid;
341 data->nntp_password = new_password;
342
343 return MAIL_NO_ERROR;
344
345 free_uid:
346 if (new_userid != NULL)
347 free(new_userid);
348 err:
349 return MAIL_ERROR_MEMORY;
350}
351
352static int nntpdriver_logout(mailsession * session)
353{
354 int r;
355
356 r = newsnntp_quit(get_nntp_session(session));
357
358 return nntpdriver_nntp_error_to_mail_error(r);
359}
360
361
362static int nntpdriver_status_folder(mailsession * session, char * mb,
363 uint32_t * result_messages,
364 uint32_t * result_recent,
365 uint32_t * result_unseen)
366{
367 uint32_t count;
368 int r;
369
370 r = nntpdriver_select_folder(session, mb);
371 if (r != MAIL_NO_ERROR)
372 return r;
373
374 r = nntpdriver_messages_number(session, mb, &count);
375 if (r != MAIL_NO_ERROR)
376 return r;
377
378 * result_messages = count;
379 * result_recent = count;
380 * result_unseen = count;
381
382 return MAIL_NO_ERROR;
383}
384
385static int nntpdriver_messages_number(mailsession * session, char * mb,
386 uint32_t * result)
387{
388 int r;
389 struct nntp_session_state_data * data;
390
391 if (mb != NULL) {
392 r = nntpdriver_select_folder(session, mb);
393 if (r != MAIL_NO_ERROR)
394 return r;
395 }
396
397 data = get_data(session);
398
399 if (data->nntp_group_info == NULL)
400 return MAIL_ERROR_FOLDER_NOT_FOUND;
401
402 * result = data->nntp_group_info->grp_last -
403 data->nntp_group_info->grp_first + 1;
404
405 return MAIL_NO_ERROR;
406}
407
408static int nntpdriver_list_folders(mailsession * session, char * mb,
409 struct mail_list ** result)
410{
411 int r;
412 clist * group_list;
413 newsnntp * nntp;
414 clistiter * cur;
415 char * new_mb;
416 int done;
417 clist * list;
418 struct mail_list * ml;
419 int res;
420
421 nntp = get_nntp_session(session);
422
423 new_mb = NULL;
424 if ((mb != NULL) && (*mb != '\0')) {
425 new_mb = malloc(strlen(mb) + 3);
426 if (new_mb == NULL) {
427 res = MAIL_ERROR_MEMORY;
428 goto err;
429 }
430 strcpy(new_mb, mb);
431 strcat(new_mb, ".*");
432 }
433
434 done = FALSE;
435 do {
436 if (new_mb != NULL)
437 r = newsnntp_list_active(nntp, new_mb, &group_list);
438 else
439 r = newsnntp_list(nntp, &group_list);
440
441 switch (r) {
442 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
443 r = nntpdriver_authenticate_user(session);
444 if (r != MAIL_NO_ERROR) {
445 res = r;
446 goto err;
447 }
448 break;
449
450 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
451 r = nntpdriver_authenticate_password(session);
452 if (r != MAIL_NO_ERROR) {
453 res = r;
454 goto err;
455 }
456 break;
457
458 case NEWSNNTP_NO_ERROR:
459 if (new_mb != NULL)
460 free(new_mb);
461 done = TRUE;
462 break;
463
464 default:
465 if (new_mb != NULL)
466 free(new_mb);
467 return nntpdriver_nntp_error_to_mail_error(r);
468 }
469 }
470 while (!done);
471
472 list = clist_new();
473 if (list == NULL) {
474 res = MAIL_ERROR_MEMORY;
475 goto err;
476 }
477
478 for(cur = clist_begin(group_list) ; cur != NULL ;
479 cur = clist_next(cur)) {
480 struct newsnntp_group_info * info;
481 char * new_name;
482
483 info = clist_content(cur);
484 new_name = strdup(info->grp_name);
485 if (new_name == NULL) {
486 res = MAIL_ERROR_MEMORY;
487 goto free_list;
488 }
489
490 r = clist_append(list, new_name);
491 if (r < 0) {
492 free(new_name);
493 res = MAIL_ERROR_MEMORY;
494 goto free_list;
495 }
496 }
497
498 ml = mail_list_new(list);
499 if (ml == NULL) {
500 res = MAIL_ERROR_MEMORY;
501 goto free_list;
502 }
503
504 newsnntp_list_free(group_list);
505
506 * result = ml;
507
508 return MAIL_NO_ERROR;
509
510 free_list:
511 clist_foreach(list, (clist_func) free, NULL);
512 clist_free(list);
513 newsnntp_list_free(group_list);
514 err:
515 return res;
516}
517
518static int nntpdriver_lsub_folders(mailsession * session, char * mb,
519 struct mail_list ** result)
520{
521 clist * subscribed;
522 clist * lsub_result;
523 clistiter * cur;
524 struct mail_list * lsub;
525 size_t length;
526 int res;
527 int r;
528 struct nntp_session_state_data * data;
529
530 length = strlen(mb);
531
532 data = get_data(session);
533
534 subscribed = data->nntp_subscribed_list;
535 lsub_result = clist_new();
536 if (lsub_result == NULL) {
537 res = MAIL_ERROR_MEMORY;
538 goto err;
539 }
540
541 for(cur = clist_begin(subscribed) ; cur != NULL ;
542 cur = clist_next(cur)) {
543 char * cur_mb;
544 char * new_mb;
545
546 cur_mb = clist_content(cur);
547
548 if (strncmp(mb, cur_mb, length) == 0) {
549 new_mb = strdup(cur_mb);
550 if (new_mb == NULL) {
551 res = MAIL_ERROR_MEMORY;
552 goto free_list;
553 }
554
555 r = clist_append(lsub_result, new_mb);
556 if (r < 0) {
557 free(new_mb);
558 res = MAIL_ERROR_MEMORY;
559 goto free_list;
560 }
561 }
562 }
563
564 lsub = mail_list_new(lsub_result);
565 if (lsub == NULL) {
566 res = MAIL_ERROR_MEMORY;
567 goto free_list;
568 }
569
570 * result = lsub;
571
572 return MAIL_NO_ERROR;
573
574 free_list:
575 clist_foreach(lsub_result, (clist_func) free, NULL);
576 clist_free(lsub_result);
577 err:
578 return res;
579}
580
581static int nntpdriver_subscribe_folder(mailsession * session, char * mb)
582{
583 int r;
584
585 r = add_to_list(session, mb);
586 if (r < 0)
587 return MAIL_ERROR_SUBSCRIBE;
588
589 return MAIL_NO_ERROR;
590}
591
592static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb)
593{
594 int r;
595
596 r = remove_from_list(session, mb);
597 if (r < 0)
598 return MAIL_ERROR_UNSUBSCRIBE;
599
600 return MAIL_NO_ERROR;
601}
602
603
604
605/* messages operations */
606
607static int nntpdriver_append_message(mailsession * session,
608 char * message, size_t size)
609{
610 int r;
611 struct nntp_session_state_data * data;
612
613 data = get_data(session);
614
615 do {
616 r = newsnntp_post(get_nntp_session(session), message, size);
617 switch (r) {
618 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
619 r = nntpdriver_authenticate_user(session);
620 if (r != MAIL_NO_ERROR)
621 return r;
622 break;
623
624 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
625 r = nntpdriver_authenticate_password(session);
626 if (r != MAIL_NO_ERROR)
627 return r;
628 break;
629
630 default:
631 return nntpdriver_nntp_error_to_mail_error(r);
632 }
633 }
634 while (1);
635}
636
637static int nntpdriver_append_message_flags(mailsession * session,
638 char * message, size_t size, struct mail_flags * flags)
639{
640 return nntpdriver_append_message(session, message, size);
641}
642
643
644static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item,
645 struct mailimf_fields ** result);
646
647
648static int
649nntpdriver_get_envelopes_list(mailsession * session,
650 struct mailmessage_list * env_list)
651{
652 newsnntp * nntp;
653 int r;
654 struct nntp_session_state_data * data;
655 clist * list;
656 int done;
657 clistiter * cur;
658 uint32_t first_seq;
659 unsigned int i;
660
661 nntp = get_nntp_session(session);
662
663 data = get_data(session);
664
665 if (data->nntp_group_info == NULL)
666 return MAIL_ERROR_BAD_STATE;
667
668 first_seq = data->nntp_group_info->grp_first;
669
670 if (carray_count(env_list->msg_tab) > 0) {
671 mailmessage * msg;
672
673 msg = carray_get(env_list->msg_tab, 0);
674
675 first_seq = msg->msg_index;
676 }
677
678 if (carray_count(env_list->msg_tab) > 0) {
679 i = carray_count(env_list->msg_tab) - 1;
680 while (1) {
681 mailmessage * msg;
682
683 msg = carray_get(env_list->msg_tab, i);
684
685 if (msg->msg_fields != NULL) {
686 first_seq = msg->msg_index + 1;
687 break;
688 }
689
690 if (i == 0)
691 break;
692
693 i --;
694 }
695 }
696
697 if (first_seq > data->nntp_group_info->grp_last) {
698 list = NULL;
699 }
700 else {
701 done = FALSE;
702 do {
703 r = newsnntp_xover_range(nntp, first_seq,
704 data->nntp_group_info->grp_last, &list);
705
706 switch (r) {
707 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
708 r = nntpdriver_authenticate_user(session);
709 if (r != MAIL_NO_ERROR)
710 return r;
711 break;
712
713 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
714 r = nntpdriver_authenticate_password(session);
715 if (r != MAIL_NO_ERROR)
716 return r;
717 break;
718
719 case NEWSNNTP_NO_ERROR:
720 done = TRUE;
721 break;
722
723 default:
724 return nntpdriver_nntp_error_to_mail_error(r);
725 }
726 }
727 while (!done);
728 }
729
730#if 0
731 i = 0;
732 j = 0;
733
734 if (list != NULL) {
735 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
736 struct newsnntp_xover_resp_item * item;
737 struct mailimf_fields * fields;
738
739 item = clist_content(cur);
740
741 while (i < carray_count(env_list->msg_tab)) {
742 mailmessage * info;
743
744 info = carray_get(env_list->msg_tab, i);
745
746 if (item->ovr_article == info->msg_index) {
747
748 if (info->fields == NULL) {
749 r = xover_resp_to_fields(item, &fields);
750 if (r == MAIL_NO_ERROR) {
751 info->fields = fields;
752 }
753
754 info->size = item->ovr_size;
755
756 carray_set(env_list->msg_tab, j, info);
757 j ++;
758 i ++;
759 break;
760 }
761 else {
762 carray_set(env_list->msg_tab, j, info);
763 j ++;
764 }
765 }
766 else {
767 if (info->fields != NULL) {
768 carray_set(env_list->msg_tab, j, info);
769 j ++;
770 }
771 else {
772 if (info->flags != NULL) {
773 info->flags->flags &= ~MAIL_FLAG_NEW;
774 info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED;
775 mailmessage_check(info);
776 }
777 mailmessage_free(info);
778 carray_set(env_list->msg_tab, i, NULL);
779 }
780 }
781
782 i ++;
783 }
784 }
785 }
786
787 while (i < carray_count(env_list->msg_tab)) {
788 mailmessage * info;
789
790 info = carray_get(env_list->msg_tab, i);
791 if (info->fields != NULL) {
792 carray_set(env_list->msg_tab, j, info);
793 j ++;
794 }
795 else {
796 if (info->flags != NULL) {
797 info->flags->flags &= ~MAIL_FLAG_NEW;
798 info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED;
799 mailmessage_check(info);
800 }
801 mailmessage_free(info);
802 carray_set(env_list->msg_tab, i, NULL);
803 }
804
805 i ++;
806 }
807
808 r = carray_set_size(env_list->msg_tab, j);
809 if (r < 0) {
810 if (list != NULL)
811 newsnntp_xover_resp_list_free(list);
812 return MAIL_ERROR_MEMORY;
813 }
814#endif
815 i = 0;
816
817 if (list != NULL) {
818 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
819 struct newsnntp_xover_resp_item * item;
820 struct mailimf_fields * fields;
821
822 item = clist_content(cur);
823
824 while (i < carray_count(env_list->msg_tab)) {
825 mailmessage * info;
826
827 info = carray_get(env_list->msg_tab, i);
828
829 if (item->ovr_article == info->msg_index) {
830
831 if (info->msg_fields == NULL) {
832 r = xover_resp_to_fields(item, &fields);
833 if (r == MAIL_NO_ERROR) {
834 info->msg_fields = fields;
835 }
836
837 info->msg_size = item->ovr_size;
838
839 i ++;
840 break;
841 }
842 }
843#if 0
844 else if ((info->fields == NULL) && (info->flags != NULL)) {
845 info->flags->flags &= ~MAIL_FLAG_NEW;
846 info->flags->flags |= MAIL_FLAG_CANCELLED;
847 mailmessage_check(info);
848 }
849#endif
850
851 i ++;
852 }
853 }
854 }
855
856#if 0
857 while (i < env_list->msg_tab->len) {
858 mailmessage * info;
859
860 info = carray_get(env_list->msg_tab, i);
861 if ((info->fields == NULL) && (info->flags != NULL)) {
862 info->flags->flags &= ~MAIL_FLAG_NEW;
863 info->flags->flags |= MAIL_FLAG_CANCELLED;
864 mailmessage_check(info);
865 }
866
867 i ++;
868 }
869#endif
870
871 if (list != NULL)
872 newsnntp_xover_resp_list_free(list);
873
874 return MAIL_NO_ERROR;
875}
876
877
878static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item,
879 struct mailimf_fields ** result)
880{
881 size_t cur_token;
882 clist * list;
883 int r;
884 struct mailimf_fields * fields;
885 int res;
886
887 list = clist_new();
888 if (list == NULL) {
889 res = MAIL_ERROR_MEMORY;
890 goto err;
891 }
892
893 if (item->ovr_subject != NULL) {
894 char * subject_str;
895 struct mailimf_subject * subject;
896 struct mailimf_field * field;
897
898 subject_str = strdup(item->ovr_subject);
899 if (subject_str == NULL) {
900 res = MAIL_ERROR_MEMORY;
901 goto free_list;
902 }
903
904 subject = mailimf_subject_new(subject_str);
905 if (subject == NULL) {
906 free(subject_str);
907 res = MAIL_ERROR_MEMORY;
908 goto free_list;
909 }
910
911 field = mailimf_field_new(MAILIMF_FIELD_SUBJECT,
912 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
913 NULL, NULL, NULL,
914 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
915 NULL, subject, NULL, NULL, NULL);
916 if (field == NULL) {
917 mailimf_subject_free(subject);
918 res = MAIL_ERROR_MEMORY;
919 goto free_list;
920 }
921
922 r = clist_append(list, field);
923 if (r < 0) {
924 mailimf_field_free(field);
925 res = MAIL_ERROR_MEMORY;
926 goto free_list;
927 }
928 }
929
930 if (item->ovr_author != NULL) {
931 struct mailimf_mailbox_list * mb_list;
932 struct mailimf_from * from;
933 struct mailimf_field * field;
934
935 cur_token = 0;
936 r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author),
937 &cur_token, &mb_list);
938 switch (r) {
939 case MAILIMF_NO_ERROR:
940 from = mailimf_from_new(mb_list);
941 if (from == NULL) {
942 mailimf_mailbox_list_free(mb_list);
943 res = MAIL_ERROR_MEMORY;
944 goto free_list;
945 }
946
947 field = mailimf_field_new(MAILIMF_FIELD_FROM,
948 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
949 NULL, NULL, from,
950 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
951 NULL, NULL, NULL, NULL, NULL);
952 if (field == NULL) {
953 mailimf_from_free(from);
954 res = MAIL_ERROR_MEMORY;
955 goto free_list;
956 }
957
958 r = clist_append(list, field);
959 if (r < 0) {
960 mailimf_field_free(field);
961 res = MAIL_ERROR_MEMORY;
962 goto free_list;
963 }
964 break;
965
966 case MAILIMF_ERROR_PARSE:
967 break;
968
969 default:
970 res = maildriver_imf_error_to_mail_error(r);
971 goto free_list;
972 }
973 }
974
975 if (item->ovr_date != NULL) {
976 struct mailimf_date_time * date_time;
977 struct mailimf_orig_date * orig_date;
978 struct mailimf_field * field;
979
980 cur_token = 0;
981 r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date),
982 &cur_token, &date_time);
983 switch (r) {
984 case MAILIMF_NO_ERROR:
985 orig_date = mailimf_orig_date_new(date_time);
986 if (orig_date == NULL) {
987 mailimf_date_time_free(date_time);
988 res = MAIL_ERROR_MEMORY;
989 goto free_list;
990 }
991
992 field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE,
993 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
994 NULL, orig_date, NULL,
995 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
996 NULL, NULL, NULL, NULL, NULL);
997 if (field == NULL) {
998 mailimf_orig_date_free(orig_date);
999 res = MAIL_ERROR_MEMORY;
1000 goto free_list;
1001 }
1002
1003 r = clist_append(list, field);
1004 if (r < 0) {
1005 mailimf_field_free(field);
1006 res = MAIL_ERROR_MEMORY;
1007 goto free_list;
1008 }
1009 break;
1010
1011 case MAILIMF_ERROR_PARSE:
1012 break;
1013
1014 default:
1015 res = maildriver_imf_error_to_mail_error(r);
1016 goto free_list;
1017 }
1018 }
1019
1020 if (item->ovr_message_id != NULL) {
1021 char * msgid_str;
1022 struct mailimf_message_id * msgid;
1023 struct mailimf_field * field;
1024
1025 cur_token = 0;
1026 r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id),
1027 &cur_token, &msgid_str);
1028
1029 switch (r) {
1030 case MAILIMF_NO_ERROR:
1031 msgid = mailimf_message_id_new(msgid_str);
1032 if (msgid == NULL) {
1033 mailimf_msg_id_free(msgid_str);
1034 res = MAIL_ERROR_MEMORY;
1035 goto free_list;
1036 }
1037
1038 field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID,
1039 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1040 NULL, NULL, NULL,
1041 NULL, NULL, NULL, NULL, NULL, msgid, NULL,
1042 NULL, NULL, NULL, NULL, NULL);
1043
1044 r = clist_append(list, field);
1045 if (r < 0) {
1046 mailimf_field_free(field);
1047 res = MAIL_ERROR_MEMORY;
1048 goto free_list;
1049 }
1050 break;
1051
1052 case MAILIMF_ERROR_PARSE:
1053 break;
1054
1055 default:
1056 res = maildriver_imf_error_to_mail_error(r);
1057 goto free_list;
1058 }
1059 }
1060
1061 if (item->ovr_references != NULL) {
1062 clist * msgid_list;
1063 struct mailimf_references * references;
1064 struct mailimf_field * field;
1065
1066 cur_token = 0;
1067
1068 r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references),
1069 &cur_token, &msgid_list);
1070
1071 switch (r) {
1072 case MAILIMF_NO_ERROR:
1073 references = mailimf_references_new(msgid_list);
1074 if (references == NULL) {
1075 clist_foreach(msgid_list,
1076 (clist_func) mailimf_msg_id_free, NULL);
1077 clist_free(msgid_list);
1078 res = MAIL_ERROR_MEMORY;
1079 goto free_list;
1080 }
1081
1082 field = mailimf_field_new(MAILIMF_FIELD_REFERENCES,
1083 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1084 NULL, NULL, NULL,
1085 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1086 references, NULL, NULL, NULL, NULL);
1087
1088 r = clist_append(list, field);
1089 if (r < 0) {
1090 mailimf_field_free(field);
1091 res = MAIL_ERROR_MEMORY;
1092 goto free_list;
1093 }
1094
1095 case MAILIMF_ERROR_PARSE:
1096 break;
1097
1098 default:
1099 res = maildriver_imf_error_to_mail_error(r);
1100 goto free_list;
1101 }
1102 }
1103
1104 fields = mailimf_fields_new(list);
1105 if (fields == NULL) {
1106 res = MAIL_ERROR_MEMORY;
1107 goto free_list;
1108 }
1109
1110 * result = fields;
1111
1112 return MAIL_NO_ERROR;
1113
1114 free_list:
1115 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
1116 clist_free(list);
1117 err:
1118 return res;
1119}
1120
1121
1122/* get messages list with group info */
1123
1124static int nntpdriver_get_messages_list(mailsession * session,
1125 struct mailmessage_list ** result)
1126{
1127 return nntp_get_messages_list(session, session, nntp_message_driver, result);
1128
1129}
1130
1131static int nntpdriver_get_message(mailsession * session,
1132 uint32_t num, mailmessage ** result)
1133{
1134 mailmessage * msg_info;
1135 int r;
1136
1137 msg_info = mailmessage_new();
1138 if (msg_info == NULL)
1139 return MAIL_ERROR_MEMORY;
1140
1141 r = mailmessage_init(msg_info, session, nntp_message_driver, num, 0);
1142 if (r != MAIL_NO_ERROR) {
1143 mailmessage_free(msg_info);
1144 return r;
1145 }
1146
1147 * result = msg_info;
1148
1149 return MAIL_NO_ERROR;
1150}
1151
1152static int nntpdriver_noop(mailsession * session)
1153{
1154 newsnntp * nntp;
1155 int r;
1156 struct tm tm;
1157
1158 nntp = get_nntp_session(session);
1159
1160 r = newsnntp_date(nntp, &tm);
1161
1162 return nntpdriver_nntp_error_to_mail_error(r);
1163}
1164
1165static int nntpdriver_get_message_by_uid(mailsession * session,
1166 const char * uid,
1167 mailmessage ** result)
1168{
1169 uint32_t num;
1170 char * p;
1171
1172 if (uid == NULL)
1173 return MAIL_ERROR_INVAL;
1174
1175 num = strtoul(uid, &p, 10);
1176 if ((p == uid) || (* p != '\0'))
1177 return MAIL_ERROR_INVAL;
1178
1179 return nntpdriver_get_message(session, num, result);
1180 }
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_H
37
38#define NNTPDRIVER_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * nntp_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpdriver_cached.h"
37
38#include "libetpan-config.h"
39
40#include <string.h>
41#include <stdio.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <fcntl.h>
45#include <unistd.h>
46#include <stdlib.h>
47
48#include "mail_cache_db.h"
49
50#include "mail.h"
51#include "mailmessage.h"
52#include "maildriver_tools.h"
53#include "nntpdriver.h"
54#include "maildriver.h"
55#include "newsnntp.h"
56#include "generic_cache.h"
57#include "imfcache.h"
58#include "maillock.h"
59#include "nntpdriver_cached_message.h"
60#include "nntpdriver_tools.h"
61
62static int nntpdriver_cached_initialize(mailsession * session);
63
64static void nntpdriver_cached_uninitialize(mailsession * session);
65
66static int nntpdriver_cached_parameters(mailsession * session,
67 int id, void * value);
68
69static int nntpdriver_cached_connect_stream(mailsession * session,
70 mailstream * s);
71
72static int nntpdriver_cached_login(mailsession * session,
73 char * userid, char * password);
74
75static int nntpdriver_cached_logout(mailsession * session);
76
77static int nntpdriver_cached_check_folder(mailsession * session);
78
79static int nntpdriver_cached_select_folder(mailsession * session, char * mb);
80
81static int nntpdriver_cached_status_folder(mailsession * session,
82 char * mb,
83 uint32_t * result_messages,
84 uint32_t * result_recent,
85 uint32_t * result_unseen);
86
87static int nntpdriver_cached_messages_number(mailsession * session, char * mb,
88 uint32_t * result);
89
90static int nntpdriver_cached_recent_number(mailsession * session, char * mb,
91 uint32_t * result);
92
93static int nntpdriver_cached_unseen_number(mailsession * session, char * mb,
94 uint32_t * result);
95
96static int nntpdriver_cached_append_message(mailsession * session,
97 char * message, size_t size);
98
99static int nntpdriver_cached_append_message_flags(mailsession * session,
100 char * message, size_t size, struct mail_flags * flags);
101
102static int
103nntpdriver_cached_get_envelopes_list(mailsession * session,
104 struct mailmessage_list * env_list);
105
106
107static int
108nntpdriver_cached_get_messages_list(mailsession * session,
109 struct mailmessage_list ** result);
110
111static int nntpdriver_cached_list_folders(mailsession * session, char * mb,
112 struct mail_list ** result);
113
114static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb,
115 struct mail_list ** result);
116
117static int nntpdriver_cached_subscribe_folder(mailsession * session,
118 char * mb);
119
120static int nntpdriver_cached_unsubscribe_folder(mailsession * session,
121 char * mb);
122
123static int nntpdriver_cached_get_message(mailsession * session,
124 uint32_t num, mailmessage ** result);
125
126static int nntpdriver_cached_noop(mailsession * session);
127
128static int nntpdriver_cached_get_message_by_uid(mailsession * session,
129 const char * uid,
130 mailmessage ** result);
131
132static mailsession_driver local_nntp_cached_session_driver = {
133 .sess_name = "nntp-cached",
134
135 .sess_initialize = nntpdriver_cached_initialize,
136 .sess_uninitialize = nntpdriver_cached_uninitialize,
137
138 .sess_parameters = nntpdriver_cached_parameters,
139
140 .sess_connect_stream = nntpdriver_cached_connect_stream,
141 .sess_connect_path = NULL,
142 .sess_starttls = NULL,
143 .sess_login = nntpdriver_cached_login,
144 .sess_logout = nntpdriver_cached_logout,
145 .sess_noop = nntpdriver_cached_noop,
146
147 .sess_build_folder_name = NULL,
148 .sess_create_folder = NULL,
149 .sess_delete_folder = NULL,
150 .sess_rename_folder = NULL,
151 .sess_check_folder = nntpdriver_cached_check_folder,
152 .sess_examine_folder = NULL,
153 .sess_select_folder = nntpdriver_cached_select_folder,
154 .sess_expunge_folder = NULL,
155 .sess_status_folder = nntpdriver_cached_status_folder,
156 .sess_messages_number = nntpdriver_cached_messages_number,
157 .sess_recent_number = nntpdriver_cached_recent_number,
158 .sess_unseen_number = nntpdriver_cached_unseen_number,
159 .sess_list_folders = nntpdriver_cached_list_folders,
160 .sess_lsub_folders = nntpdriver_cached_lsub_folders,
161 .sess_subscribe_folder = nntpdriver_cached_subscribe_folder,
162 .sess_unsubscribe_folder = nntpdriver_cached_unsubscribe_folder,
163
164 .sess_append_message = nntpdriver_cached_append_message,
165 .sess_append_message_flags = nntpdriver_cached_append_message_flags,
166 .sess_copy_message = NULL,
167 .sess_move_message = NULL,
168
169 .sess_get_messages_list = nntpdriver_cached_get_messages_list,
170 .sess_get_envelopes_list = nntpdriver_cached_get_envelopes_list,
171 .sess_remove_message = NULL,
172#if 0
173 .sess_search_messages = maildriver_generic_search_messages,
174#endif
175
176 .sess_get_message = nntpdriver_cached_get_message,
177 .sess_get_message_by_uid = nntpdriver_cached_get_message_by_uid,
178};
179
180
181mailsession_driver * nntp_cached_session_driver =
182&local_nntp_cached_session_driver;
183
184#define ENV_NAME "env.db"
185#define FLAGS_NAME "flags.db"
186
187
188
189static void read_article_seq(mailsession * session,
190 uint32_t * pfirst, uint32_t * plast);
191
192static void write_article_seq(mailsession * session,
193 uint32_t first, uint32_t last);
194
195
196static inline struct nntp_cached_session_state_data *
197get_cached_data(mailsession * session)
198{
199 return session->sess_data;
200}
201
202static inline mailsession * get_ancestor(mailsession * session)
203{
204 return get_cached_data(session)->nntp_ancestor;
205}
206
207static inline struct nntp_session_state_data *
208get_ancestor_data(mailsession * session)
209{
210 return get_ancestor(session)->sess_data;
211}
212
213static inline newsnntp * get_nntp_session(mailsession * session)
214{
215 return get_ancestor_data(session)->nntp_session;
216}
217
218static int nntpdriver_cached_initialize(mailsession * session)
219{
220 struct nntp_cached_session_state_data * data;
221
222 data = malloc(sizeof(* data));
223 if (data == NULL)
224 goto err;
225
226 data->nntp_flags_store = mail_flags_store_new();
227 if (data->nntp_flags_store == NULL)
228 goto free;
229
230 data->nntp_ancestor = mailsession_new(nntp_session_driver);
231 if (data->nntp_ancestor == NULL)
232 goto free_store;
233
234 session->sess_data = data;
235
236 return MAIL_NO_ERROR;
237
238 free_store:
239 mail_flags_store_free(data->nntp_flags_store);
240 free:
241 free(data);
242 err:
243 return MAIL_ERROR_MEMORY;
244}
245
246static int nntp_flags_store_process(char * flags_directory, char * group_name,
247 struct mail_flags_store * flags_store)
248{
249 char filename_flags[PATH_MAX];
250 struct mail_cache_db * cache_db_flags;
251 MMAPString * mmapstr;
252 unsigned int i;
253 int r;
254 int res;
255
256 if (carray_count(flags_store->fls_tab) == 0)
257 return MAIL_NO_ERROR;
258
259 if (group_name == NULL)
260 return MAIL_NO_ERROR;
261
262 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
263 flags_directory, group_name, FLAGS_NAME);
264
265 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
266 if (r < 0) {
267 res = MAIL_ERROR_FILE;
268 goto err;
269 }
270
271 mmapstr = mmap_string_new("");
272 if (mmapstr == NULL) {
273 res = MAIL_ERROR_MEMORY;
274 goto close_db_flags;
275 }
276
277 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
278 mailmessage * msg;
279
280 msg = carray_get(flags_store->fls_tab, i);
281
282 r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr,
283 msg->msg_index, msg->msg_flags);
284 }
285
286 mmap_string_free(mmapstr);
287 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
288
289 mail_flags_store_clear(flags_store);
290
291 return MAIL_NO_ERROR;
292
293 close_db_flags:
294 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
295 err:
296 return res;
297}
298
299static void nntpdriver_cached_uninitialize(mailsession * session)
300{
301 struct nntp_cached_session_state_data * cached_data;
302 struct nntp_session_state_data * ancestor_data;
303
304 cached_data = get_cached_data(session);
305 ancestor_data = get_ancestor_data(session);
306
307 nntp_flags_store_process(cached_data->nntp_flags_directory,
308 ancestor_data->nntp_group_name,
309 cached_data->nntp_flags_store);
310
311 mail_flags_store_free(cached_data->nntp_flags_store);
312
313 mailsession_free(cached_data->nntp_ancestor);
314 free(cached_data);
315
316 session->sess_data = NULL;
317}
318
319static int nntpdriver_cached_parameters(mailsession * session,
320 int id, void * value)
321{
322 struct nntp_cached_session_state_data * cached_data;
323 int r;
324
325 cached_data = get_cached_data(session);
326
327 switch (id) {
328 case NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY:
329 strncpy(cached_data->nntp_cache_directory, value, PATH_MAX);
330 cached_data->nntp_cache_directory[PATH_MAX - 1] = '\0';
331
332 r = generic_cache_create_dir(cached_data->nntp_cache_directory);
333 if (r != MAIL_NO_ERROR)
334 return r;
335
336 return MAIL_NO_ERROR;
337
338 case NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY:
339 strncpy(cached_data->nntp_flags_directory, value, PATH_MAX);
340 cached_data->nntp_flags_directory[PATH_MAX - 1] = '\0';
341
342 r = generic_cache_create_dir(cached_data->nntp_flags_directory);
343 if (r != MAIL_NO_ERROR)
344 return r;
345
346 return MAIL_NO_ERROR;
347
348 default:
349 return mailsession_parameters(get_ancestor(session), id, value);
350 }
351}
352
353static int nntpdriver_cached_connect_stream(mailsession * session,
354 mailstream * s)
355{
356 return mailsession_connect_stream(get_ancestor(session), s);
357}
358
359static int nntpdriver_cached_login(mailsession * session,
360 char * userid, char * password)
361{
362 return mailsession_login(get_ancestor(session), userid, password);
363}
364
365static int nntpdriver_cached_logout(mailsession * session)
366{
367 struct nntp_cached_session_state_data * cached_data;
368 struct nntp_session_state_data * ancestor_data;
369
370 cached_data = get_cached_data(session);
371 ancestor_data = get_ancestor_data(session);
372
373 nntp_flags_store_process(cached_data->nntp_flags_directory,
374 ancestor_data->nntp_group_name,
375 cached_data->nntp_flags_store);
376
377 return mailsession_logout(get_ancestor(session));
378}
379
380static int nntpdriver_cached_select_folder(mailsession * session, char * mb)
381{
382 int r;
383 struct nntp_session_state_data * ancestor_data;
384 struct nntp_cached_session_state_data * cached_data;
385 int res;
386 char key[PATH_MAX];
387
388 cached_data = get_cached_data(session);
389 ancestor_data = get_ancestor_data(session);
390
391 nntp_flags_store_process(cached_data->nntp_flags_directory,
392 ancestor_data->nntp_group_name,
393 cached_data->nntp_flags_store);
394
395 r = mailsession_select_folder(get_ancestor(session), mb);
396 if (r != MAIL_NO_ERROR)
397 return r;
398
399 if (ancestor_data->nntp_group_name == NULL)
400 return MAIL_ERROR_BAD_STATE;
401
402 snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_cache_directory,
403 ancestor_data->nntp_group_name);
404
405 r = generic_cache_create_dir(key);
406 if (r != MAIL_NO_ERROR) {
407 res = r;
408 goto err;
409 }
410
411 snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_flags_directory,
412 ancestor_data->nntp_group_name);
413
414 r = generic_cache_create_dir(key);
415 if (r != MAIL_NO_ERROR) {
416 res = r;
417 goto err;
418 }
419
420 return MAIL_NO_ERROR;
421
422 err:
423 return res;
424}
425
426static int nntpdriver_cached_check_folder(mailsession * session)
427{
428 struct nntp_session_state_data * ancestor_data;
429 struct nntp_cached_session_state_data * cached_data;
430
431 cached_data = get_cached_data(session);
432 ancestor_data = get_ancestor_data(session);
433
434 nntp_flags_store_process(cached_data->nntp_flags_directory,
435 ancestor_data->nntp_group_name,
436 cached_data->nntp_flags_store);
437
438 return MAIL_NO_ERROR;
439}
440
441
442static int nntpdriver_cached_status_folder(mailsession * session,
443 char * mb, uint32_t * result_messages, uint32_t * result_recent,
444 uint32_t * result_unseen)
445{
446 int res;
447 struct nntp_cached_session_state_data * cached_data;
448 struct nntp_session_state_data * ancestor_data;
449 char filename_flags[PATH_MAX];
450 struct mail_cache_db * cache_db_flags;
451 MMAPString * mmapstr;
452 uint32_t i;
453 int r;
454 uint32_t recent;
455 uint32_t unseen;
456 uint32_t first;
457 uint32_t last;
458 uint32_t count;
459 uint32_t additionnal;
460
461 r = nntpdriver_cached_select_folder(session, mb);
462 if (r != MAIL_NO_ERROR) {
463 res = r;
464 goto err;
465 }
466
467 read_article_seq(session, &first, &last);
468
469 count = 0;
470 recent = 0;
471 unseen = 0;
472
473 ancestor_data = get_ancestor_data(session);
474 cached_data = get_cached_data(session);
475 if (ancestor_data->nntp_group_name == NULL) {
476 res = MAIL_ERROR_BAD_STATE;
477 goto err;
478 }
479
480 if (ancestor_data->nntp_group_info->grp_first > first)
481 first = ancestor_data->nntp_group_info->grp_first;
482 if (last < first)
483 last = ancestor_data->nntp_group_info->grp_last;
484
485 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
486 cached_data->nntp_flags_directory,
487 ancestor_data->nntp_group_name, FLAGS_NAME);
488
489 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
490 if (r < 0) {
491 res = MAIL_ERROR_MEMORY;
492 goto err;
493 }
494
495 mmapstr = mmap_string_new("");
496 if (mmapstr == NULL) {
497 res = MAIL_ERROR_MEMORY;
498 goto close_db_flags;
499 }
500
501 for(i = first ; i <= last ; i++) {
502 struct mail_flags * flags;
503
504 r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
505 i, &flags);
506 if (r == MAIL_NO_ERROR) {
507 if ((flags->fl_flags & MAIL_FLAG_CANCELLED) != 0) {
508 mail_flags_free(flags);
509 continue;
510 }
511
512 count ++;
513 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
514 recent ++;
515 }
516 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
517 unseen ++;
518 }
519 mail_flags_free(flags);
520 }
521 }
522
523 if ((count == 0) && (first != last)) {
524 count = last - first + 1;
525 recent = count;
526 unseen = count;
527 }
528
529 additionnal = ancestor_data->nntp_group_info->grp_last - last;
530 recent += additionnal;
531 unseen += additionnal;
532
533 mmap_string_free(mmapstr);
534 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
535
536 * result_messages = count;
537 * result_recent = recent;
538 * result_unseen = unseen;
539
540 return MAIL_NO_ERROR;
541
542 close_db_flags:
543 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
544 err:
545 return res;
546}
547
548static int nntpdriver_cached_messages_number(mailsession * session,
549 char * mb,
550 uint32_t * result)
551{
552 uint32_t messages;
553 uint32_t recent;
554 uint32_t unseen;
555 int r;
556
557 r = nntpdriver_cached_status_folder(session, mb,
558 &messages, &recent, &unseen);
559 if (r != MAIL_NO_ERROR)
560 return r;
561
562 * result = messages;
563
564 return MAIL_NO_ERROR;
565}
566
567static int nntpdriver_cached_recent_number(mailsession * session,
568 char * mb,
569 uint32_t * result)
570{
571 uint32_t messages;
572 uint32_t recent;
573 uint32_t unseen;
574 int r;
575
576 r = nntpdriver_cached_status_folder(session, mb,
577 &messages, &recent, &unseen);
578 if (r != MAIL_NO_ERROR)
579 return r;
580
581 * result = recent;
582
583 return MAIL_NO_ERROR;
584}
585
586static int nntpdriver_cached_unseen_number(mailsession * session,
587 char * mb,
588 uint32_t * result)
589{
590 uint32_t messages;
591 uint32_t recent;
592 uint32_t unseen;
593 int r;
594
595 r = nntpdriver_cached_status_folder(session, mb,
596 &messages, &recent, &unseen);
597 if (r != MAIL_NO_ERROR)
598 return r;
599
600 * result = unseen;
601
602 return MAIL_NO_ERROR;
603}
604
605static int nntpdriver_cached_list_folders(mailsession * session, char * mb,
606 struct mail_list ** result)
607{
608 return mailsession_list_folders(get_ancestor(session), mb, result);
609}
610
611static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb,
612 struct mail_list ** result)
613{
614 return mailsession_lsub_folders(get_ancestor(session), mb, result);
615}
616
617static int nntpdriver_cached_subscribe_folder(mailsession * session,
618 char * mb)
619{
620 return mailsession_subscribe_folder(get_ancestor(session), mb);
621}
622
623static int nntpdriver_cached_unsubscribe_folder(mailsession * session,
624 char * mb)
625{
626 return mailsession_unsubscribe_folder(get_ancestor(session), mb);
627}
628
629
630
631/* messages operations */
632
633static int nntpdriver_cached_append_message(mailsession * session,
634 char * message, size_t size)
635{
636 return mailsession_append_message(get_ancestor(session), message, size);
637}
638
639static int nntpdriver_cached_append_message_flags(mailsession * session,
640 char * message, size_t size, struct mail_flags * flags)
641{
642 return nntpdriver_cached_append_message(session, message, size);
643}
644
645
646
647static int
648get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
649 mailsession * session, uint32_t num,
650 struct mailimf_fields ** result)
651{
652 char keyname[PATH_MAX];
653 int r;
654 struct mailimf_fields * fields;
655 int res;
656
657 snprintf(keyname, PATH_MAX, "%i-envelope", num);
658
659 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
660 if (r != MAIL_NO_ERROR) {
661 res = r;
662 goto err;
663 }
664
665 * result = fields;
666
667 return MAIL_NO_ERROR;
668
669 err:
670 return res;
671}
672
673static int
674write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
675 mailsession * session, uint32_t num,
676 struct mailimf_fields * fields)
677{
678 int r;
679 int res;
680 char keyname[PATH_MAX];
681
682 snprintf(keyname, PATH_MAX, "%i-envelope", num);
683
684 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
685 if (r != MAIL_NO_ERROR) {
686 res = r;
687 goto err;
688 }
689
690 return MAIL_NO_ERROR;
691
692 err:
693 return res;
694}
695
696#define SEQ_FILENAME "articles-seq"
697
698static void read_article_seq(mailsession * session,
699 uint32_t * pfirst, uint32_t * plast)
700{
701 FILE * f;
702 struct nntp_session_state_data * ancestor_data;
703 uint32_t first;
704 uint32_t last;
705 char seq_filename[PATH_MAX];
706 struct nntp_cached_session_state_data * cached_data;
707 int r;
708
709 first = 0;
710 last = 0;
711
712 cached_data = get_cached_data(session);
713 ancestor_data = get_ancestor_data(session);
714
715 if (ancestor_data->nntp_group_name == NULL)
716 return;
717
718 snprintf(seq_filename, PATH_MAX, "%s/%s/%s",
719 cached_data->nntp_cache_directory,
720 ancestor_data->nntp_group_name, SEQ_FILENAME);
721 f = fopen(seq_filename, "r");
722
723 if (f != NULL) {
724 int fd;
725
726 fd = fileno(f);
727
728 r = maillock_read_lock(seq_filename, fd);
729 if (r == 0) {
730 MMAPString * mmapstr;
731 size_t cur_token;
732 char buf[sizeof(uint32_t) * 2];
733 size_t read_size;
734
735 read_size = fread(buf, 1, sizeof(uint32_t) * 2, f);
736 mmapstr = mmap_string_new_len(buf, read_size);
737 if (mmapstr != NULL) {
738 cur_token = 0;
739 r = mailimf_cache_int_read(mmapstr, &cur_token, &first);
740 r = mailimf_cache_int_read(mmapstr, &cur_token, &last);
741
742 mmap_string_free(mmapstr);
743 }
744
745 maillock_read_unlock(seq_filename, fd);
746 }
747 fclose(f);
748 }
749
750 * pfirst = first;
751 * plast = last;
752}
753
754static void write_article_seq(mailsession * session,
755 uint32_t first, uint32_t last)
756{
757 FILE * f;
758 struct nntp_session_state_data * ancestor_data;
759 char seq_filename[PATH_MAX];
760 struct nntp_cached_session_state_data * cached_data;
761 int r;
762 int fd;
763
764 cached_data = get_cached_data(session);
765 ancestor_data = get_ancestor_data(session);
766
767 if (ancestor_data->nntp_group_name == NULL)
768 return;
769
770 snprintf(seq_filename, PATH_MAX, "%s/%s/%s",
771 cached_data->nntp_cache_directory,
772 ancestor_data->nntp_group_name, SEQ_FILENAME);
773
774 fd = creat(seq_filename, S_IRUSR | S_IWUSR);
775 if (fd < 0)
776 return;
777
778 f = fdopen(fd, "w");
779 if (f != NULL) {
780 r = maillock_write_lock(seq_filename, fd);
781 if (r == 0) {
782 MMAPString * mmapstr;
783 size_t cur_token;
784
785 mmapstr = mmap_string_new("");
786 if (mmapstr != NULL) {
787 r = mail_serialize_clear(mmapstr, &cur_token);
788 if (r == MAIL_NO_ERROR) {
789 r = mailimf_cache_int_write(mmapstr, &cur_token, first);
790 r = mailimf_cache_int_write(mmapstr, &cur_token, last);
791
792 fwrite(mmapstr->str, 1, mmapstr->len, f);
793 }
794
795 mmap_string_free(mmapstr);
796 }
797
798 maillock_write_unlock(seq_filename, fd);
799 }
800 fclose(f);
801 }
802 else
803 close(fd);
804}
805
806
807static void get_uid_from_filename(char * filename)
808{
809 char * p;
810
811 if (strcmp(filename, SEQ_FILENAME) == 0)
812 * filename = 0;
813
814 p = strstr(filename, "-header");
815 if (p != NULL)
816 * p = 0;
817}
818
819static int
820nntpdriver_cached_get_envelopes_list(mailsession * session,
821 struct mailmessage_list * env_list)
822{
823 int r;
824 unsigned int i;
825 struct nntp_cached_session_state_data * cached_data;
826 uint32_t first;
827 uint32_t last;
828 struct nntp_session_state_data * ancestor_data;
829 char filename_env[PATH_MAX];
830 char filename_flags[PATH_MAX];
831 struct mail_cache_db * cache_db_env;
832 struct mail_cache_db * cache_db_flags;
833 MMAPString * mmapstr;
834 int res;
835 char cache_dir[PATH_MAX];
836
837 cached_data = get_cached_data(session);
838 ancestor_data = get_ancestor_data(session);
839
840 nntp_flags_store_process(cached_data->nntp_flags_directory,
841 ancestor_data->nntp_group_name,
842 cached_data->nntp_flags_store);
843
844 if (ancestor_data->nntp_group_name == NULL) {
845 res = MAIL_ERROR_BAD_STATE;
846 goto err;
847 }
848
849 /* read articles sequence */
850
851 read_article_seq(session, &first, &last);
852
853 mmapstr = mmap_string_new("");
854 if (mmapstr == NULL) {
855 res = MAIL_ERROR_MEMORY;
856 goto err;
857 }
858
859 snprintf(filename_env, PATH_MAX, "%s/%s/%s",
860 cached_data->nntp_cache_directory,
861 ancestor_data->nntp_group_name, ENV_NAME);
862
863 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
864 if (r < 0) {
865 res = MAIL_ERROR_MEMORY;
866 goto free_mmapstr;
867 }
868
869 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
870 cached_data->nntp_flags_directory,
871 ancestor_data->nntp_group_name, FLAGS_NAME);
872
873 /* fill with cached */
874
875 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
876 mailmessage * msg;
877 struct mailimf_fields * fields;
878
879 msg = carray_get(env_list->msg_tab, i);
880
881 if ((msg->msg_index < first) || (msg->msg_index > last))
882 continue;
883
884 if (msg->msg_fields == NULL) {
885 r = get_cached_envelope(cache_db_env, mmapstr,
886 session, msg->msg_index, &fields);
887 if (r == MAIL_NO_ERROR) {
888 msg->msg_fields = fields;
889 msg->msg_cached = TRUE;
890 }
891 }
892 }
893
894 mail_cache_db_close_unlock(filename_env, cache_db_env);
895
896 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
897
898 if (r != MAIL_NO_ERROR) {
899 res = r;
900 goto free_mmapstr;
901 }
902
903 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
904 if (r < 0) {
905 res = MAIL_ERROR_MEMORY;
906 goto free_mmapstr;
907 }
908
909 /* add flags */
910
911 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
912 mailmessage * msg;
913
914 msg = carray_get(env_list->msg_tab, i);
915
916 if (msg->msg_flags == NULL) {
917 struct mail_flags * flags;
918
919 r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
920 msg->msg_index, &flags);
921 if (r == MAIL_NO_ERROR) {
922 msg->msg_flags = flags;
923 }
924 else {
925 msg->msg_flags = mail_flags_new_empty();
926 if (msg->msg_fields == NULL) {
927 msg->msg_flags->fl_flags |= MAIL_FLAG_CANCELLED;
928 mailmessage_check(msg);
929 }
930 }
931 }
932 }
933
934 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
935
936 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
937 if (r < 0) {
938 res = MAIL_ERROR_MEMORY;
939 goto free_mmapstr;
940 }
941
942 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
943 if (r < 0) {
944 res = MAIL_ERROR_MEMORY;
945 goto close_db_env;
946 }
947
948 /* must write cache */
949
950 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
951 mailmessage * msg;
952
953 msg = carray_get(env_list->msg_tab, i);
954
955 if (msg->msg_fields != NULL) {
956 if (!msg->msg_cached) {
957 r = write_cached_envelope(cache_db_env, mmapstr,
958 session, msg->msg_index, msg->msg_fields);
959 }
960 }
961
962 if (msg->msg_flags != NULL) {
963 r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr,
964 msg->msg_index, msg->msg_flags);
965 }
966 }
967
968 first = 0;
969 last = 0;
970 if (carray_count(env_list->msg_tab) > 0) {
971 mailmessage * msg;
972
973 msg = carray_get(env_list->msg_tab, 0);
974 first = msg->msg_index;
975
976 msg = carray_get(env_list->msg_tab, carray_count(env_list->msg_tab) - 1);
977 last = msg->msg_index;
978 }
979
980 /* write articles sequence */
981
982 write_article_seq(session, first, last);
983
984 /* flush cache */
985
986 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
987
988 /* remove cache files */
989
990 snprintf(cache_dir, PATH_MAX, "%s/%s",
991 cached_data->nntp_cache_directory, ancestor_data->nntp_group_name);
992
993 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
994 mail_cache_db_close_unlock(filename_env, cache_db_env);
995 mmap_string_free(mmapstr);
996
997 maildriver_message_cache_clean_up(cache_dir, env_list,
998 get_uid_from_filename);
999
1000 return MAIL_NO_ERROR;
1001
1002 close_db_env:
1003 mail_cache_db_close_unlock(filename_env, cache_db_env);
1004 free_mmapstr:
1005 mmap_string_free(mmapstr);
1006 err:
1007 return res;
1008}
1009
1010static int
1011nntpdriver_cached_get_messages_list(mailsession * session,
1012 struct mailmessage_list ** result)
1013{
1014 return nntp_get_messages_list(get_ancestor(session), session,
1015 nntp_cached_message_driver, result);
1016}
1017
1018static int nntpdriver_cached_get_message(mailsession * session,
1019 uint32_t num, mailmessage ** result)
1020{
1021 mailmessage * msg_info;
1022 int r;
1023
1024 msg_info = mailmessage_new();
1025 if (msg_info == NULL)
1026 return MAIL_ERROR_MEMORY;
1027
1028 r = mailmessage_init(msg_info, session, nntp_cached_message_driver, num, 0);
1029 if (r != MAIL_NO_ERROR) {
1030 mailmessage_free(msg_info);
1031 return r;
1032 }
1033
1034 * result = msg_info;
1035
1036 return MAIL_NO_ERROR;
1037}
1038
1039static int nntpdriver_cached_noop(mailsession * session)
1040{
1041 return mailsession_noop(get_ancestor(session));
1042}
1043
1044static int nntpdriver_cached_get_message_by_uid(mailsession * session,
1045 const char * uid,
1046 mailmessage ** result)
1047{
1048 uint32_t num;
1049 char * p;
1050
1051 if (uid == NULL)
1052 return MAIL_ERROR_INVAL;
1053
1054 num = strtoul(uid, &p, 10);
1055 if ((p == uid) || (* p != '\0'))
1056 return MAIL_ERROR_INVAL;
1057
1058 return nntpdriver_cached_get_message(session, num, result);
1059}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_CACHED_H
37
38#define NNTPDRIVER_CACHED_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * nntp_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpdriver_cached_message.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "mail_cache_db.h"
42
43#include "mailmessage.h"
44#include "mailmessage_tools.h"
45#include "nntpdriver.h"
46#include "nntpdriver_tools.h"
47#include "nntpdriver_cached.h"
48#include "nntpdriver_message.h"
49#include "generic_cache.h"
50
51static int nntp_prefetch(mailmessage * msg_info);
52
53static void nntp_prefetch_free(struct generic_message_t * msg);
54
55static int nntp_initialize(mailmessage * msg_info);
56
57static int nntp_fetch_header(mailmessage * msg_info,
58 char ** result,
59 size_t * result_len);
60
61static int nntp_fetch_size(mailmessage * msg_info,
62 size_t * result);
63
64static void nntp_uninitialize(mailmessage * msg_info);
65
66static void nntp_flush(mailmessage * msg_info);
67
68static void nntp_check(mailmessage * msg_info);
69
70static int nntp_get_flags(mailmessage * msg_info,
71 struct mail_flags ** result);
72
73static mailmessage_driver local_nntp_cached_message_driver = {
74 .msg_name = "nntp-cached",
75
76 .msg_initialize = nntp_initialize,
77 .msg_uninitialize = nntp_uninitialize,
78
79 .msg_flush = nntp_flush,
80 .msg_check = nntp_check,
81
82 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
83
84 .msg_fetch = mailmessage_generic_fetch,
85 .msg_fetch_header = nntp_fetch_header,
86 .msg_fetch_body = mailmessage_generic_fetch_body,
87 .msg_fetch_size = nntp_fetch_size,
88 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
89 .msg_fetch_section = mailmessage_generic_fetch_section,
90 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
91 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
92 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
93 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
94
95 .msg_get_flags = nntp_get_flags,
96};
97
98mailmessage_driver * nntp_cached_message_driver =
99&local_nntp_cached_message_driver;
100
101static inline struct nntp_cached_session_state_data *
102get_cached_session_data(mailmessage * msg)
103{
104 return msg->msg_session->sess_data;
105}
106
107static inline mailsession * get_ancestor_session(mailmessage * msg)
108{
109 return get_cached_session_data(msg)->nntp_ancestor;
110}
111
112static inline struct nntp_session_state_data *
113get_ancestor_session_data(mailmessage * msg)
114{
115 return get_ancestor_session(msg)->sess_data;
116}
117
118static inline newsnntp *
119get_nntp_session(mailmessage * msg)
120{
121 return get_ancestor_session_data(msg)->nntp_session;
122}
123
124static int nntp_prefetch(mailmessage * msg_info)
125{
126 char * msg_content;
127 size_t msg_length;
128 struct generic_message_t * msg;
129 int r;
130 struct nntp_cached_session_state_data * cached_data;
131 struct nntp_session_state_data * ancestor_data;
132 char filename[PATH_MAX];
133
134 /* we try the cached message */
135
136 cached_data = get_cached_session_data(msg_info);
137
138 ancestor_data = get_ancestor_session_data(msg_info);
139
140 snprintf(filename, PATH_MAX, "%s/%s/%i", cached_data->nntp_cache_directory,
141 ancestor_data->nntp_group_name, msg_info->msg_index);
142
143 r = generic_cache_read(filename, &msg_content, &msg_length);
144 if (r == MAIL_NO_ERROR) {
145 msg = msg_info->msg_data;
146
147 msg->msg_message = msg_content;
148 msg->msg_length = msg_length;
149
150 return MAIL_NO_ERROR;
151 }
152
153 /* we get the message through the network */
154
155 r = nntpdriver_article(get_ancestor_session(msg_info),
156 msg_info->msg_index, &msg_content,
157 &msg_length);
158
159 if (r != MAIL_NO_ERROR)
160 return r;
161
162 /* we write the message cache */
163
164 generic_cache_store(filename, msg_content, msg_length);
165
166 msg = msg_info->msg_data;
167
168 msg->msg_message = msg_content;
169 msg->msg_length = msg_length;
170
171 return MAIL_NO_ERROR;
172}
173
174static void nntp_prefetch_free(struct generic_message_t * msg)
175{
176 if (msg->msg_message != NULL) {
177 mmap_string_unref(msg->msg_message);
178 msg->msg_message = NULL;
179 }
180}
181
182static int nntp_initialize(mailmessage * msg_info)
183{
184 struct generic_message_t * msg;
185 int r;
186 char * uid;
187 char static_uid[20];
188
189 snprintf(static_uid, 20, "%u", msg_info->msg_index);
190 uid = strdup(static_uid);
191 if (uid == NULL)
192 return MAIL_ERROR_MEMORY;
193
194 r = mailmessage_generic_initialize(msg_info);
195 if (r != MAIL_NO_ERROR) {
196 free(uid);
197 return r;
198 }
199
200 msg = msg_info->msg_data;
201 msg->msg_prefetch = nntp_prefetch;
202 msg->msg_prefetch_free = nntp_prefetch_free;
203 msg_info->msg_uid = uid;
204
205 return MAIL_NO_ERROR;
206}
207
208
209static void nntp_uninitialize(mailmessage * msg_info)
210{
211 mailmessage_generic_uninitialize(msg_info);
212}
213
214#define FLAGS_NAME "flags.db"
215
216static void nntp_flush(mailmessage * msg_info)
217{
218 mailmessage_generic_flush(msg_info);
219}
220
221
222static void nntp_check(mailmessage * msg_info)
223{
224 int r;
225
226 if (msg_info->msg_flags != NULL) {
227 r = mail_flags_store_set(get_cached_session_data(msg_info)->nntp_flags_store,
228 msg_info);
229 /* ignore errors */
230 }
231}
232
233static int nntp_fetch_header(mailmessage * msg_info,
234 char ** result,
235 size_t * result_len)
236{
237 struct generic_message_t * msg;
238 char * headers;
239 size_t headers_length;
240 struct nntp_cached_session_state_data * cached_data;
241 struct nntp_session_state_data * ancestor_data;
242 int r;
243 char filename[PATH_MAX];
244
245 msg = msg_info->msg_data;
246
247 if (msg->msg_message != NULL)
248 return mailmessage_generic_fetch_header(msg_info,
249 result, result_len);
250
251 /* we try the cached message */
252
253 cached_data = get_cached_session_data(msg_info);
254
255 ancestor_data = get_ancestor_session_data(msg_info);
256
257 snprintf(filename, PATH_MAX, "%s/%s/%i-header",
258 cached_data->nntp_cache_directory,
259 ancestor_data->nntp_group_name, msg_info->msg_index);
260
261 r = generic_cache_read(filename, &headers, &headers_length);
262 if (r == MAIL_NO_ERROR) {
263 * result = headers;
264 * result_len = headers_length;
265
266 return MAIL_NO_ERROR;
267 }
268
269 /* we get the message through the network */
270
271 r = nntpdriver_head(get_ancestor_session(msg_info), msg_info->msg_index,
272 &headers, &headers_length);
273 if (r != MAIL_NO_ERROR)
274 return r;
275
276 /* we write the message cache */
277
278 generic_cache_store(filename, headers, headers_length);
279
280 * result = headers;
281 * result_len = headers_length;
282
283 return MAIL_NO_ERROR;
284}
285
286static int nntp_fetch_size(mailmessage * msg_info,
287 size_t * result)
288{
289 return nntpdriver_size(get_ancestor_session(msg_info),
290 msg_info->msg_index, result);
291}
292
293static int nntp_get_flags(mailmessage * msg_info,
294 struct mail_flags ** result)
295{
296 int r;
297 struct mail_flags * flags;
298 struct mail_cache_db * cache_db_flags;
299 char filename_flags[PATH_MAX];
300 int res;
301 MMAPString * mmapstr;
302
303 if (msg_info->msg_flags != NULL) {
304 * result = msg_info->msg_flags;
305
306 return MAIL_NO_ERROR;
307 }
308
309 flags = mail_flags_store_get(get_cached_session_data(msg_info)->nntp_flags_store, msg_info->msg_index);
310
311 if (flags == NULL) {
312 struct nntp_cached_session_state_data * cached_data;
313 struct nntp_session_state_data * ancestor_data;
314
315 cached_data = get_cached_session_data(msg_info);
316
317 ancestor_data = get_ancestor_session_data(msg_info);
318 if (ancestor_data->nntp_group_name == NULL) {
319 res = MAIL_ERROR_BAD_STATE;
320 goto err;
321 }
322
323 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
324 cached_data->nntp_flags_directory,
325 ancestor_data->nntp_group_name, FLAGS_NAME);
326
327 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
328 if (r < 0) {
329 res = MAIL_ERROR_MEMORY;
330 goto err;
331 }
332
333 mmapstr = mmap_string_new("");
334 if (mmapstr == NULL) {
335 res = MAIL_ERROR_MEMORY;
336 goto close_db_flags;
337 }
338
339 r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
340 msg_info->msg_index, &flags);
341 if (r != MAIL_NO_ERROR) {
342 flags = mail_flags_new_empty();
343 if (flags == NULL) {
344 res = MAIL_ERROR_MEMORY;
345 goto free_mmapstr;
346 }
347 }
348
349 mmap_string_free(mmapstr);
350 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
351 }
352
353 msg_info->msg_flags = flags;
354
355 * result = flags;
356
357 return MAIL_NO_ERROR;
358
359 free_mmapstr:
360 mmap_string_free(mmapstr);
361 close_db_flags:
362 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
363 err:
364 return res;
365}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include <libetpan/mailmessage_types.h>
37
38#ifndef NNTPDRIVER_CACHED_MESSAGE_H
39
40#define NNTPDRIVER_CACHED_MESSAGE_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * nntp_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpdriver_message.h"
37
38#include "mailmessage_tools.h"
39#include "nntpdriver_tools.h"
40#include "nntpdriver.h"
41#include "newsnntp.h"
42#include <string.h>
43#include <stdlib.h>
44
45static int nntp_prefetch(mailmessage * msg_info);
46
47static void nntp_prefetch_free(struct generic_message_t * msg);
48
49static int nntp_initialize(mailmessage * msg_info);
50
51static int nntp_fetch_header(mailmessage * msg_info,
52 char ** result,
53 size_t * result_len);
54
55static int nntp_fetch_size(mailmessage * msg_info,
56 size_t * result);
57
58static mailmessage_driver local_nntp_message_driver = {
59 .msg_name = "nntp",
60
61 .msg_initialize = nntp_initialize,
62 .msg_uninitialize = mailmessage_generic_uninitialize,
63
64 .msg_flush = mailmessage_generic_flush,
65 .msg_check = NULL,
66
67 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
68
69 .msg_fetch = mailmessage_generic_fetch,
70 .msg_fetch_header = nntp_fetch_header,
71 .msg_fetch_body = mailmessage_generic_fetch_body,
72 .msg_fetch_size = nntp_fetch_size,
73 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
74 .msg_fetch_section = mailmessage_generic_fetch_section,
75 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
76 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
77 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
78 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
79
80 .msg_get_flags = NULL,
81};
82
83mailmessage_driver * nntp_message_driver = &local_nntp_message_driver;
84
85static int nntp_prefetch(mailmessage * msg_info)
86{
87 char * msg_content;
88 size_t msg_length;
89 struct generic_message_t * msg;
90 int r;
91
92 r = nntpdriver_article(msg_info->msg_session, msg_info->msg_index,
93 &msg_content, &msg_length);
94 if (r != MAIL_NO_ERROR)
95 return r;
96
97 msg = msg_info->msg_data;
98
99 msg->msg_message = msg_content;
100 msg->msg_length = msg_length;
101
102 return MAIL_NO_ERROR;
103}
104
105static void nntp_prefetch_free(struct generic_message_t * msg)
106{
107 if (msg->msg_message != NULL) {
108 mmap_string_unref(msg->msg_message);
109 msg->msg_message = NULL;
110 }
111}
112
113static int nntp_initialize(mailmessage * msg_info)
114{
115 struct generic_message_t * msg;
116 int r;
117 char * uid;
118 char static_uid[20];
119
120 snprintf(static_uid, 20, "%u", msg_info->msg_index);
121 uid = strdup(static_uid);
122 if (uid == NULL)
123 return MAIL_ERROR_MEMORY;
124
125 r = mailmessage_generic_initialize(msg_info);
126 if (r != MAIL_NO_ERROR) {
127 free(uid);
128 return r;
129 }
130
131 msg = msg_info->msg_data;
132 msg->msg_prefetch = nntp_prefetch;
133 msg->msg_prefetch_free = nntp_prefetch_free;
134 msg_info->msg_uid = uid;
135
136 return MAIL_NO_ERROR;
137}
138
139static int nntp_fetch_header(mailmessage * msg_info,
140 char ** result,
141 size_t * result_len)
142{
143 struct generic_message_t * msg;
144 char * headers;
145 size_t headers_length;
146 int r;
147
148 msg = msg_info->msg_data;
149
150 if (msg->msg_message != NULL)
151 return mailmessage_generic_fetch_header(msg_info,
152 result, result_len);
153
154 r = nntpdriver_head(msg_info->msg_session, msg_info->msg_index,
155 &headers, &headers_length);
156 if (r != MAIL_NO_ERROR)
157 return r;
158
159 * result = headers;
160 * result_len = headers_length;
161
162 return MAIL_NO_ERROR;
163}
164
165static int nntp_fetch_size(mailmessage * msg_info,
166 size_t * result)
167{
168 return nntpdriver_size(msg_info->msg_session, msg_info->msg_index, result);
169}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_MESSAGE_H
37
38#define NNTPDRIVER_MESSAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/nntpdriver_types.h>
45
46extern mailmessage_driver * nntp_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpdriver_tools.h"
37
38#include "mail.h"
39#include "nntpdriver.h"
40#include "nntpdriver_cached.h"
41#include "newsnntp.h"
42#include "maildriver_types.h"
43#include "generic_cache.h"
44#include "imfcache.h"
45#include "mailmessage.h"
46#include "mail_cache_db.h"
47
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <unistd.h>
52#include <string.h>
53#include <stdlib.h>
54
55int nntpdriver_nntp_error_to_mail_error(int error)
56{
57 switch (error) {
58 case NEWSNNTP_NO_ERROR:
59 return MAIL_NO_ERROR;
60
61 case NEWSNNTP_ERROR_STREAM:
62 return MAIL_ERROR_STREAM;
63
64 case NEWSNNTP_ERROR_UNEXPECTED:
65 return MAIL_ERROR_PROGRAM_ERROR;
66
67 case NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED:
68 return MAIL_ERROR_FOLDER_NOT_FOUND;
69
70 case NEWSNNTP_ERROR_NO_ARTICLE_SELECTED:
71 case NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER:
72 case NEWSNNTP_ERROR_ARTICLE_NOT_FOUND:
73 return MAIL_ERROR_MSG_NOT_FOUND;
74
75 case NEWSNNTP_ERROR_UNEXPECTED_RESPONSE:
76 case NEWSNNTP_ERROR_INVALID_RESPONSE:
77 return MAIL_ERROR_PARSE;
78
79 case NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP:
80 return MAIL_ERROR_FOLDER_NOT_FOUND;
81
82 case NEWSNNTP_ERROR_POSTING_NOT_ALLOWED:
83 return MAIL_ERROR_READONLY;
84
85 case NEWSNNTP_ERROR_POSTING_FAILED:
86 return MAIL_ERROR_APPEND;
87
88 case NEWSNNTP_ERROR_PROGRAM_ERROR:
89 return MAIL_ERROR_PROGRAM_ERROR;
90
91 case NEWSNNTP_ERROR_NO_PERMISSION:
92 return MAIL_ERROR_NO_PERMISSION;
93
94 case NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD:
95 case NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED:
96 return MAIL_ERROR_COMMAND_NOT_SUPPORTED;
97
98 case NEWSNNTP_ERROR_CONNECTION_REFUSED:
99 return MAIL_ERROR_CONNECT;
100
101 case NEWSNNTP_ERROR_MEMORY:
102 return MAIL_ERROR_MEMORY;
103
104 case NEWSNNTP_ERROR_AUTHENTICATION_REJECTED:
105 return MAIL_ERROR_LOGIN;
106
107 case NEWSNNTP_ERROR_BAD_STATE:
108 return MAIL_ERROR_BAD_STATE;
109
110 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
111 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
112 default:
113 return MAIL_ERROR_INVAL;
114 }
115}
116
117static inline struct nntp_session_state_data *
118session_get_data(mailsession * session)
119{
120 return session->sess_data;
121}
122
123static inline newsnntp * session_get_nntp_session(mailsession * session)
124{
125 return session_get_data(session)->nntp_session;
126}
127
128static inline struct nntp_cached_session_state_data *
129cached_session_get_data(mailsession * session)
130{
131 return session->sess_data;
132}
133
134static inline mailsession * cached_session_get_ancestor(mailsession * session)
135{
136 return cached_session_get_data(session)->nntp_ancestor;
137}
138
139static inline struct nntp_session_state_data *
140cached_session_get_ancestor_data(mailsession * session)
141{
142 return session_get_data(cached_session_get_ancestor(session));
143}
144
145static inline newsnntp * cached_session_get_nntp_session(mailsession * session)
146{
147 return session_get_nntp_session(cached_session_get_ancestor(session));
148}
149
150
151int nntpdriver_authenticate_password(mailsession * session)
152{
153 struct nntp_session_state_data * data;
154 int r;
155
156 data = session_get_data(session);
157
158 if (data->nntp_password == NULL)
159 return MAIL_ERROR_LOGIN;
160
161 r = newsnntp_authinfo_password(session_get_nntp_session(session),
162 data->nntp_password);
163
164 return nntpdriver_nntp_error_to_mail_error(r);
165}
166
167int nntpdriver_mode_reader(mailsession * session)
168{
169 int done;
170 int r;
171
172 done = FALSE;
173
174 do {
175 r = newsnntp_mode_reader(session_get_nntp_session(session));
176
177 switch (r) {
178 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
179 r = nntpdriver_authenticate_user(session);
180 if (r != MAIL_NO_ERROR)
181 return r;
182 break;
183
184 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
185 r = nntpdriver_authenticate_password(session);
186 if (r != MAIL_NO_ERROR)
187 return r;
188 break;
189
190 case NEWSNNTP_NO_ERROR:
191 done = TRUE;
192 break;
193
194 default:
195 done = TRUE;
196 break;
197 }
198 }
199 while (!done);
200
201 return MAIL_NO_ERROR;
202}
203
204int nntpdriver_authenticate_user(mailsession * session)
205{
206 struct nntp_session_state_data * data;
207 int r;
208
209 data = session_get_data(session);
210
211 if (data->nntp_userid == NULL)
212 return MAIL_ERROR_LOGIN;
213
214 r = newsnntp_authinfo_username(session_get_nntp_session(session),
215 data->nntp_userid);
216
217 switch (r) {
218 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
219 return nntpdriver_authenticate_password(session);
220
221 default:
222 return nntpdriver_nntp_error_to_mail_error(r);
223 }
224}
225
226int nntpdriver_article(mailsession * session, uint32_t index,
227 char ** result,
228 size_t * result_len)
229{
230 char * msg_content;
231 size_t msg_length;
232 int r;
233 int done;
234
235 done = FALSE;
236 do {
237 r = newsnntp_article(session_get_nntp_session(session),
238 index, &msg_content, &msg_length);
239
240 switch (r) {
241 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
242 r = nntpdriver_authenticate_user(session);
243 if (r != MAIL_NO_ERROR)
244 return r;
245 break;
246
247 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
248 r = nntpdriver_authenticate_password(session);
249 if (r != MAIL_NO_ERROR)
250 return r;
251 break;
252
253 case NEWSNNTP_NO_ERROR:
254 done = TRUE;
255 break;
256
257 default:
258 return nntpdriver_nntp_error_to_mail_error(r);
259 }
260 }
261 while (!done);
262
263 * result = msg_content;
264 * result_len = msg_length;
265
266 return MAIL_NO_ERROR;
267}
268
269int nntpdriver_head(mailsession * session, uint32_t index,
270 char ** result,
271 size_t * result_len)
272{
273 char * headers;
274 size_t headers_length;
275 int r;
276 int done;
277
278 done = FALSE;
279 do {
280 r = newsnntp_head(session_get_nntp_session(session),
281 index, &headers, &headers_length);
282
283 switch (r) {
284 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
285 r = nntpdriver_authenticate_user(session);
286 if (r != MAIL_NO_ERROR)
287 return r;
288 break;
289
290 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
291 r = nntpdriver_authenticate_password(session);
292 if (r != MAIL_NO_ERROR)
293 return r;
294 break;
295
296 case NEWSNNTP_NO_ERROR:
297 done = TRUE;
298 break;
299
300 default:
301 return nntpdriver_nntp_error_to_mail_error(r);
302 }
303 }
304 while (!done);
305
306 * result = headers;
307 * result_len = headers_length;
308
309 return MAIL_NO_ERROR;
310}
311
312int nntpdriver_size(mailsession * session, uint32_t index,
313 size_t * result)
314{
315 newsnntp * nntp;
316 struct newsnntp_xover_resp_item * item;
317 int r;
318 int done;
319
320 nntp = session_get_nntp_session(session);
321
322 done = FALSE;
323 do {
324 r = newsnntp_xover_single(nntp, index, &item);
325 switch (r) {
326 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
327 r = nntpdriver_authenticate_user(session);
328 if (r != MAIL_NO_ERROR)
329 return r;
330 break;
331
332 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
333 r = nntpdriver_authenticate_password(session);
334 if (r != MAIL_NO_ERROR)
335 return r;
336 break;
337
338 case NEWSNNTP_NO_ERROR:
339 done = TRUE;
340 break;
341
342 default:
343 return nntpdriver_nntp_error_to_mail_error(r);
344 }
345 }
346 while (!done);
347
348 * result = item->ovr_size;
349
350 xover_resp_item_free(item);
351
352 return MAIL_NO_ERROR;
353}
354
355int
356nntpdriver_get_cached_flags(struct mail_cache_db * cache_db,
357 MMAPString * mmapstr,
358 uint32_t num,
359 struct mail_flags ** result)
360{
361 int r;
362 char keyname[PATH_MAX];
363 struct mail_flags * flags;
364 int res;
365
366 snprintf(keyname, PATH_MAX, "%u-flags", num);
367
368 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
369 if (r != MAIL_NO_ERROR) {
370 res = r;
371 goto err;
372 }
373
374 * result = flags;
375
376 return MAIL_NO_ERROR;
377
378 err:
379 return res;
380}
381
382int
383nntpdriver_write_cached_flags(struct mail_cache_db * cache_db,
384 MMAPString * mmapstr,
385 uint32_t num,
386 struct mail_flags * flags)
387{
388 int r;
389 char keyname[PATH_MAX];
390 int res;
391
392 snprintf(keyname, PATH_MAX, "%u-flags", num);
393
394 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
395 if (r != MAIL_NO_ERROR) {
396 res = r;
397 goto err;
398 }
399
400 return MAIL_NO_ERROR;
401
402 err:
403 return res;
404}
405
406
407
408int nntpdriver_select_folder(mailsession * session, char * mb)
409{
410 int r;
411 struct newsnntp_group_info * info;
412 newsnntp * nntp_session;
413 struct nntp_session_state_data * data;
414 char * new_name;
415 int done;
416
417 data = session_get_data(session);
418
419 if (!data->nntp_mode_reader) {
420 r = nntpdriver_mode_reader(session);
421 if (r != MAIL_NO_ERROR)
422 return r;
423
424 data->nntp_mode_reader = TRUE;
425 }
426
427 if (data->nntp_group_name != NULL)
428 if (strcmp(data->nntp_group_name, mb) == 0)
429 return MAIL_NO_ERROR;
430
431 nntp_session = session_get_nntp_session(session);
432
433 done = FALSE;
434 do {
435 r = newsnntp_group(nntp_session, mb, &info);
436
437 switch (r) {
438 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
439 r = nntpdriver_authenticate_user(session);
440 if (r != MAIL_NO_ERROR)
441 return r;
442 break;
443
444 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
445 r = nntpdriver_authenticate_password(session);
446 if (r != MAIL_NO_ERROR)
447 return r;
448 break;
449
450 case NEWSNNTP_NO_ERROR:
451 done = TRUE;
452 break;
453
454 default:
455 return nntpdriver_nntp_error_to_mail_error(r);
456 }
457
458 }
459 while (!done);
460
461 new_name = strdup(mb);
462 if (new_name == NULL)
463 return MAIL_ERROR_MEMORY;
464
465 if (data->nntp_group_name != NULL)
466 free(data->nntp_group_name);
467 data->nntp_group_name = new_name;
468 if (data->nntp_group_info != NULL)
469 newsnntp_group_free(data->nntp_group_info);
470 data->nntp_group_info = info;
471
472 return MAIL_NO_ERROR;
473}
474
475
476int nntp_get_messages_list(mailsession * nntp_session,
477 mailsession * session,
478 mailmessage_driver * driver,
479 struct mailmessage_list ** result)
480{
481 carray * tab;
482 struct mailmessage_list * env_list;
483 uint32_t i;
484 int res;
485 int r;
486 struct nntp_session_state_data * data;
487 struct newsnntp_group_info * group_info;
488 uint32_t max;
489 unsigned int cur;
490
491 data = session_get_data(nntp_session);
492
493 if (data->nntp_group_name == NULL) {
494 res = MAIL_ERROR_BAD_STATE;
495 goto err;
496 }
497
498 r = nntpdriver_select_folder(nntp_session, data->nntp_group_name);
499 if (r != MAIL_NO_ERROR) {
500 res = r;
501 goto err;
502 }
503
504 group_info = data->nntp_group_info;
505
506 if (group_info == NULL) {
507 res = MAIL_ERROR_BAD_STATE;
508 goto err;
509 }
510
511 max = group_info->grp_first;
512 if (data->nntp_max_articles != 0) {
513 if (group_info->grp_last - data->nntp_max_articles + 1 > max)
514 max = group_info->grp_last - data->nntp_max_articles + 1;
515 }
516
517 tab = carray_new(128);
518 if (tab == NULL) {
519 res = MAIL_ERROR_MEMORY;
520 goto err;
521 }
522
523 for(i = max ; i <= group_info->grp_last ; i++) {
524 mailmessage * msg;
525
526 msg = mailmessage_new();
527 if (msg == NULL) {
528 res = MAIL_ERROR_MEMORY;
529 goto free_list;
530 }
531
532 r = mailmessage_init(msg, session, driver, i, 0);
533 if (r != MAIL_NO_ERROR) {
534 mailmessage_free(msg);
535 res = r;
536 goto free_list;
537 }
538
539 r = carray_add(tab, msg, NULL);
540 if (r < 0) {
541 mailmessage_free(msg);
542 res = MAIL_ERROR_MEMORY;
543 goto free_list;
544 }
545 }
546
547 env_list = mailmessage_list_new(tab);
548 if (env_list == NULL) {
549 res = MAIL_ERROR_MEMORY;
550 goto free_list;
551 }
552
553 * result = env_list;
554
555 return MAIL_NO_ERROR;
556
557 free_list:
558 for(cur = 0 ; cur < carray_count(tab) ; cur ++)
559 mailmessage_free(carray_get(tab, cur));
560 carray_free(tab);
561 err:
562 return res;
563}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_TOOLS_H
37
38#define NNTPDRIVER_TOOLS_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mail_cache_db_types.h"
45#include "nntpdriver_types.h"
46
47int nntpdriver_nntp_error_to_mail_error(int error);
48
49int nntpdriver_authenticate_password(mailsession * session);
50
51int nntpdriver_authenticate_user(mailsession * session);
52
53int nntpdriver_article(mailsession * session, uint32_t index,
54 char ** result, size_t * result_len);
55
56int nntpdriver_head(mailsession * session, uint32_t index,
57 char ** result,
58 size_t * result_len);
59
60int nntpdriver_size(mailsession * session, uint32_t index,
61 size_t * result);
62
63int
64nntpdriver_get_cached_flags(struct mail_cache_db * cache_db,
65 MMAPString * mmapstr,
66 uint32_t num,
67 struct mail_flags ** result);
68
69int
70nntpdriver_write_cached_flags(struct mail_cache_db * cache_db,
71 MMAPString * mmapstr,
72 uint32_t num,
73 struct mail_flags * flags);
74
75int nntpdriver_select_folder(mailsession * session, char * mb);
76
77int nntp_get_messages_list(mailsession * nntp_session,
78 mailsession * session,
79 mailmessage_driver * driver,
80 struct mailmessage_list ** result);
81
82int nntpdriver_mode_reader(mailsession * session);
83
84#ifdef __cplusplus
85}
86#endif
87
88#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_TYPES_H
37
38#define NNTPDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/newsnntp.h>
44#include <libetpan/clist.h>
45#include <libetpan/generic_cache_types.h>
46#include <libetpan/mailstorage_types.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52/* NNTP driver for session */
53
54enum {
55 NNTPDRIVER_SET_MAX_ARTICLES = 1,
56};
57
58struct nntp_session_state_data {
59 newsnntp * nntp_session;
60 char * nntp_userid;
61 char * nntp_password;
62
63 struct newsnntp_group_info * nntp_group_info;
64 char * nntp_group_name;
65
66 clist * nntp_subscribed_list;
67
68 uint32_t nntp_max_articles;
69
70 int nntp_mode_reader;
71};
72
73/* cached NNTP driver for session */
74
75enum {
76 /* the mapping of the parameters should be the same as for nntp */
77 NNTPDRIVER_CACHED_SET_MAX_ARTICLES = 1,
78 /* cache specific */
79 NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY,
80 NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY,
81};
82
83struct nntp_cached_session_state_data {
84 mailsession * nntp_ancestor;
85 char nntp_cache_directory[PATH_MAX];
86 char nntp_flags_directory[PATH_MAX];
87 struct mail_flags_store * nntp_flags_store;
88};
89
90
91/* nntp storage */
92
93/*
94 nntp_mailstorage is the state data specific to the IMAP4rev1 storage.
95
96 - storage this is the storage to initialize.
97
98 - servername this is the name of the NNTP server
99
100 - port is the port to connect to, on the server.
101 you give 0 to use the default port.
102
103 - connection_type is the type of socket layer to use.
104 The value can be CONNECTION_TYPE_PLAIN or CONNECTION_TYPE_TLS.
105
106 - auth_type is the authenticate mechanism to use.
107 The value can be NNTP_AUTH_TYPE_PLAIN.
108
109 - login is the login of the POP3 account.
110
111 - password is the password of the POP3 account.
112
113 - cached if this value is != 0, a persistant cache will be
114 stored on local system.
115
116 - cache_directory is the location of the cache
117
118 - flags_directory is the location of the flags
119*/
120
121struct nntp_mailstorage {
122 char * nntp_servername;
123 uint16_t nntp_port;
124 char * nntp_command;
125 int nntp_connection_type;
126
127 int nntp_auth_type;
128 char * nntp_login;
129 char * nntp_password;
130
131 int nntp_cached;
132 char * nntp_cache_directory;
133 char * nntp_flags_directory;
134};
135
136/* this is the type of NNTP authentication */
137
138enum {
139 NNTP_AUTH_TYPE_PLAIN, /* plain text authentication */
140};
141
142#ifdef __cplusplus
143}
144#endif
145
146#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpstorage.h"
37
38#include <stdlib.h>
39#include <string.h>
40
41#include "maildriver.h"
42#include "nntpdriver.h"
43#include "nntpdriver_cached.h"
44#include "mailstorage_tools.h"
45#include "mail.h"
46
47/* nntp storage */
48
49#define NNTP_DEFAULT_PORT 119
50#define NNTPS_DEFAULT_PORT 563
51
52static int nntp_mailstorage_connect(struct mailstorage * storage);
53static int nntp_mailstorage_get_folder_session(struct mailstorage * storage,
54 char * pathname, mailsession ** result);
55static void nntp_mailstorage_uninitialize(struct mailstorage * storage);
56
57static mailstorage_driver nntp_mailstorage_driver = {
58 .sto_name = "nntp",
59 .sto_connect = nntp_mailstorage_connect,
60 .sto_get_folder_session = nntp_mailstorage_get_folder_session,
61 .sto_uninitialize = nntp_mailstorage_uninitialize,
62};
63
64int nntp_mailstorage_init(struct mailstorage * storage,
65 char * nn_servername, uint16_t nn_port,
66 char * nn_command,
67 int nn_connection_type, int nn_auth_type,
68 char * nn_login, char * nn_password,
69 int nn_cached, char * nn_cache_directory, char * nn_flags_directory)
70{
71 struct nntp_mailstorage * nntp_storage;
72 int res;
73
74 nntp_storage = malloc(sizeof(* nntp_storage));
75 if (nntp_storage == NULL) {
76 res = MAIL_ERROR_MEMORY;
77 goto err;
78 }
79
80 nntp_storage->nntp_servername = strdup(nn_servername);
81 if (nntp_storage->nntp_servername == NULL) {
82 res = MAIL_ERROR_MEMORY;
83 goto free;
84 }
85
86 nntp_storage->nntp_connection_type = nn_connection_type;
87
88 if (nn_port == 0) {
89 switch (nn_connection_type) {
90 case CONNECTION_TYPE_PLAIN:
91 case CONNECTION_TYPE_COMMAND:
92 nn_port = NNTP_DEFAULT_PORT;
93 break;
94
95 case CONNECTION_TYPE_TLS:
96 case CONNECTION_TYPE_COMMAND_TLS:
97 nn_port = NNTPS_DEFAULT_PORT;
98 break;
99
100 default:
101 res = MAIL_ERROR_INVAL;
102 goto free_servername;
103 }
104 }
105
106 nntp_storage->nntp_port = nn_port;
107
108 if (nn_command != NULL) {
109 nntp_storage->nntp_command = strdup(nn_command);
110 if (nntp_storage->nntp_command == NULL) {
111 res = MAIL_ERROR_MEMORY;
112 goto free_servername;
113 }
114 }
115 else
116 nntp_storage->nntp_command = NULL;
117
118 nntp_storage->nntp_auth_type = nn_auth_type;
119
120 if (nn_login != NULL) {
121 nntp_storage->nntp_login = strdup(nn_login);
122 if (nntp_storage->nntp_login == NULL) {
123 res = MAIL_ERROR_MEMORY;
124 goto free_command;
125 }
126 }
127 else
128 nntp_storage->nntp_login = NULL;
129
130 if (nn_password != NULL) {
131 nntp_storage->nntp_password = strdup(nn_password);
132 if (nntp_storage->nntp_password == NULL) {
133 res = MAIL_ERROR_MEMORY;
134 goto free_login;
135 }
136 }
137 else
138 nntp_storage->nntp_password = NULL;
139
140 nntp_storage->nntp_cached = nn_cached;
141
142 if (nn_cached && (nn_cache_directory != NULL) &&
143 (nn_flags_directory != NULL)) {
144 nntp_storage->nntp_cache_directory = strdup(nn_cache_directory);
145 if (nntp_storage->nntp_cache_directory == NULL) {
146 res = MAIL_ERROR_MEMORY;
147 goto free_password;
148 }
149 nntp_storage->nntp_flags_directory = strdup(nn_flags_directory);
150 if (nntp_storage->nntp_flags_directory == NULL) {
151 res = MAIL_ERROR_MEMORY;
152 goto free_cache_directory;
153 }
154 }
155 else {
156 nntp_storage->nntp_cached = FALSE;
157 nntp_storage->nntp_cache_directory = NULL;
158 nntp_storage->nntp_flags_directory = NULL;
159 }
160
161 storage->sto_data = nntp_storage;
162 storage->sto_driver = &nntp_mailstorage_driver;
163
164 return MAIL_NO_ERROR;
165
166 free_cache_directory:
167 free(nntp_storage->nntp_cache_directory);
168 free_password:
169 free(nntp_storage->nntp_password);
170 free_login:
171 free(nntp_storage->nntp_login);
172 free_command:
173 free(nn_command);
174 free_servername:
175 free(nntp_storage->nntp_servername);
176 free:
177 free(nntp_storage);
178 err:
179 return res;
180}
181
182static void nntp_mailstorage_uninitialize(struct mailstorage * storage)
183{
184 struct nntp_mailstorage * nntp_storage;
185
186 nntp_storage = storage->sto_data;
187
188 if (nntp_storage->nntp_flags_directory != NULL)
189 free(nntp_storage->nntp_flags_directory);
190 if (nntp_storage->nntp_cache_directory != NULL)
191 free(nntp_storage->nntp_cache_directory);
192 if (nntp_storage->nntp_password != NULL)
193 free(nntp_storage->nntp_password);
194 if (nntp_storage->nntp_login != NULL)
195 free(nntp_storage->nntp_login);
196 if (nntp_storage->nntp_command != NULL)
197 free(nntp_storage->nntp_command);
198 free(nntp_storage->nntp_servername);
199 free(nntp_storage);
200
201 storage->sto_data = NULL;
202}
203
204static int nntp_mailstorage_connect(struct mailstorage * storage)
205{
206 struct nntp_mailstorage * nntp_storage;
207 mailsession_driver * driver;
208 int r;
209 int res;
210 mailsession * session;
211
212 nntp_storage = storage->sto_data;
213
214 if (nntp_storage->nntp_cached)
215 driver = nntp_cached_session_driver;
216 else
217 driver = nntp_session_driver;
218
219 r = mailstorage_generic_connect(driver,
220 nntp_storage->nntp_servername,
221 nntp_storage->nntp_port, nntp_storage->nntp_command,
222 nntp_storage->nntp_connection_type,
223 NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY,
224 nntp_storage->nntp_cache_directory,
225 NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY,
226 nntp_storage->nntp_flags_directory,
227 &session);
228 switch (r) {
229 case MAIL_NO_ERROR_NON_AUTHENTICATED:
230 case MAIL_NO_ERROR_AUTHENTICATED:
231 case MAIL_NO_ERROR:
232 break;
233 default:
234 res = r;
235 goto err;
236 }
237
238 r = mailstorage_generic_auth(session, r,
239 nntp_storage->nntp_connection_type,
240 nntp_storage->nntp_login,
241 nntp_storage->nntp_password);
242 if (r != MAIL_NO_ERROR) {
243 res = r;
244 goto free;
245 }
246
247 storage->sto_session = session;
248
249 return MAIL_NO_ERROR;
250
251 free:
252 mailsession_free(session);
253 err:
254 return res;
255}
256
257static int nntp_mailstorage_get_folder_session(struct mailstorage * storage,
258 char * pathname, mailsession ** result)
259{
260 int r;
261
262 r = mailsession_select_folder(storage->sto_session, pathname);
263
264 * result = storage->sto_session;
265
266 return MAIL_NO_ERROR;
267}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPSTORAGE_H
37
38#define NNTPSTORAGE_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46
47/*
48 nntp_mailstorage_init is the constructor for a NNTP storage
49
50 @param storage this is the storage to initialize.
51
52 @param servername this is the name of the NNTP server
53
54 @param port is the port to connect to, on the server.
55 you give 0 to use the default port.
56
57 @param command the command used to connect to the server instead of
58 allowing normal TCP connections to be used.
59
60 @param connection_type is the type of socket layer to use.
61 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
62 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
63 CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
64 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
65
66 @param auth_type is the authenticate mechanism to use.
67 The value can be NNTP_AUTH_TYPE_PLAIN.
68
69 @param login is the login of the POP3 account.
70
71 @param password is the password of the POP3 account.
72
73 @param cached if this value is != 0, a persistant cache will be
74 stored on local system.
75
76 @param cache_directory is the location of the cache
77
78 @param flags_directory is the location of the flags
79*/
80
81int nntp_mailstorage_init(struct mailstorage * storage,
82 char * nntp_servername, uint16_t nntp_port,
83 char * nntp_command,
84 int nntp_connection_type, int nntp_auth_type,
85 char * nntp_login, char * nntp_password,
86 int nntp_cached, char * nntp_cache_directory,
87 char * nntp_flags_directory);
88
89#ifdef __cplusplus
90}
91#endif
92
93#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3driver.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "pop3driver_message.h"
42#include "maildriver_tools.h"
43#include "pop3driver_tools.h"
44#include "mailmessage.h"
45
46static int pop3driver_initialize(mailsession * session);
47
48static void pop3driver_uninitialize(mailsession * session);
49
50static int pop3driver_parameters(mailsession * session,
51 int id, void * value);
52
53static int pop3driver_connect_stream(mailsession * session, mailstream * s);
54
55static int pop3driver_starttls(mailsession * session);
56
57static int pop3driver_login(mailsession * session,
58 char * userid, char * password);
59
60static int pop3driver_logout(mailsession * session);
61
62static int pop3driver_noop(mailsession * session);
63
64static int pop3driver_status_folder(mailsession * session, char * mb,
65 uint32_t * result_messages, uint32_t * result_recent,
66 uint32_t * result_unseen);
67
68static int pop3driver_messages_number(mailsession * session, char * mb,
69 uint32_t * result);
70
71static int pop3driver_remove_message(mailsession * session, uint32_t num);
72
73static int pop3driver_get_messages_list(mailsession * session,
74 struct mailmessage_list ** result);
75
76static int pop3driver_get_message(mailsession * session,
77 uint32_t num, mailmessage ** result);
78
79static mailsession_driver local_pop3_session_driver = {
80 .sess_name = "pop3",
81
82 .sess_initialize = pop3driver_initialize,
83 .sess_uninitialize = pop3driver_uninitialize,
84
85 .sess_parameters = pop3driver_parameters,
86
87 .sess_connect_stream = pop3driver_connect_stream,
88 .sess_connect_path = NULL,
89 .sess_starttls = pop3driver_starttls,
90 .sess_login = pop3driver_login,
91 .sess_logout = pop3driver_logout,
92 .sess_noop = pop3driver_noop,
93
94 .sess_build_folder_name = NULL,
95 .sess_create_folder = NULL,
96 .sess_delete_folder = NULL,
97 .sess_rename_folder = NULL,
98 .sess_check_folder = NULL,
99 .sess_examine_folder = NULL,
100 .sess_select_folder = NULL,
101 .sess_expunge_folder = NULL,
102 .sess_status_folder = pop3driver_status_folder,
103 .sess_messages_number = pop3driver_messages_number,
104 .sess_recent_number = pop3driver_messages_number,
105 .sess_unseen_number = pop3driver_messages_number,
106 .sess_list_folders = NULL,
107 .sess_lsub_folders = NULL,
108 .sess_subscribe_folder = NULL,
109 .sess_unsubscribe_folder = NULL,
110
111 .sess_append_message = NULL,
112 .sess_append_message_flags = NULL,
113 .sess_copy_message = NULL,
114 .sess_move_message = NULL,
115
116 .sess_get_messages_list = pop3driver_get_messages_list,
117 .sess_get_envelopes_list = maildriver_generic_get_envelopes_list,
118 .sess_remove_message = pop3driver_remove_message,
119#if 0
120 .sess_search_messages = maildriver_generic_search_messages,
121#endif
122
123 .sess_get_message = pop3driver_get_message,
124 .sess_get_message_by_uid = NULL,
125};
126
127mailsession_driver * pop3_session_driver = &local_pop3_session_driver;
128
129static inline struct pop3_session_state_data *
130get_data(mailsession * session)
131{
132 return session->sess_data;
133}
134
135static mailpop3 * get_pop3_session(mailsession * session)
136{
137 return get_data(session)->pop3_session;
138}
139
140static int pop3driver_initialize(mailsession * session)
141{
142 struct pop3_session_state_data * data;
143 mailpop3 * pop3;
144
145 pop3 = mailpop3_new(0, NULL);
146 if (session == NULL)
147 goto err;
148
149 data = malloc(sizeof(* data));
150 if (data == NULL)
151 goto free;
152
153 data->pop3_session = pop3;
154 data->pop3_auth_type = POP3DRIVER_AUTH_TYPE_PLAIN;
155
156 session->sess_data = data;
157
158 return MAIL_NO_ERROR;
159
160 free:
161 mailpop3_free(pop3);
162 err:
163 return MAIL_ERROR_MEMORY;
164}
165
166static void pop3driver_uninitialize(mailsession * session)
167{
168 struct pop3_session_state_data * data;
169
170 data = get_data(session);
171
172 mailpop3_free(data->pop3_session);
173 free(data);
174
175 session->sess_data = data;
176}
177
178static int pop3driver_connect_stream(mailsession * session, mailstream * s)
179{
180 int r;
181
182 r = mailpop3_connect(get_pop3_session(session), s);
183
184 switch (r) {
185 case MAILPOP3_NO_ERROR:
186 return MAIL_NO_ERROR_NON_AUTHENTICATED;
187
188 default:
189 return pop3driver_pop3_error_to_mail_error(r);
190 }
191}
192
193static int pop3driver_starttls(mailsession * session)
194{
195 int r;
196 int fd;
197 mailstream_low * low;
198 mailstream_low * new_low;
199 mailpop3 * pop3;
200
201 pop3 = get_pop3_session(session);
202
203 r = mailpop3_stls(pop3);
204
205 switch (r) {
206 case MAILPOP3_NO_ERROR:
207 break;
208 default:
209 return pop3driver_pop3_error_to_mail_error(r);
210 }
211
212 low = mailstream_get_low(pop3->pop3_stream);
213 fd = mailstream_low_get_fd(low);
214 if (fd == -1)
215 return MAIL_ERROR_STREAM;
216
217 new_low = mailstream_low_ssl_open(fd);
218 if (new_low == NULL)
219 return MAIL_ERROR_STREAM;
220 mailstream_low_free(low);
221 mailstream_set_low(pop3->pop3_stream, new_low);
222
223 return MAIL_NO_ERROR;
224}
225
226static int pop3driver_parameters(mailsession * session,
227 int id, void * value)
228{
229 struct pop3_session_state_data * data;
230
231 data = get_data(session);
232
233 switch (id) {
234 case POP3DRIVER_SET_AUTH_TYPE:
235 {
236 int * param;
237
238 param = value;
239
240 data->pop3_auth_type = * param;
241 return MAIL_NO_ERROR;
242 }
243 }
244
245 return MAIL_ERROR_INVAL;
246}
247
248static int pop3driver_login(mailsession * session,
249 char * userid, char * password)
250{
251 int r;
252 carray * msg_tab;
253 struct pop3_session_state_data * data;
254
255 data = get_data(session);
256
257 switch (data->pop3_auth_type) {
258 case POP3DRIVER_AUTH_TYPE_TRY_APOP:
259 r = mailpop3_login_apop(get_pop3_session(session), userid, password);
260 if (r != MAILPOP3_NO_ERROR)
261 r = mailpop3_login(get_pop3_session(session), userid, password);
262 break;
263
264 case POP3DRIVER_AUTH_TYPE_APOP:
265 r = mailpop3_login_apop(get_pop3_session(session), userid, password);
266 break;
267
268 default:
269 case POP3DRIVER_AUTH_TYPE_PLAIN:
270 r = mailpop3_login(get_pop3_session(session), userid, password);
271 break;
272 }
273
274 mailpop3_list(get_pop3_session(session), &msg_tab);
275
276 return pop3driver_pop3_error_to_mail_error(r);
277}
278
279static int pop3driver_logout(mailsession * session)
280{
281 int r;
282
283 r = mailpop3_quit(get_pop3_session(session));
284
285 return pop3driver_pop3_error_to_mail_error(r);
286}
287
288static int pop3driver_noop(mailsession * session)
289{
290 int r;
291
292 r = mailpop3_noop(get_pop3_session(session));
293
294 return pop3driver_pop3_error_to_mail_error(r);
295}
296
297static int pop3driver_status_folder(mailsession * session, char * mb,
298 uint32_t * result_messages,
299 uint32_t * result_recent,
300 uint32_t * result_unseen)
301{
302 uint32_t count;
303 int r;
304
305 r = pop3driver_messages_number(session, mb, &count);
306 if (r != MAIL_NO_ERROR)
307 return r;
308
309 * result_messages = count;
310 * result_recent = count;
311 * result_unseen = count;
312
313 return MAIL_NO_ERROR;
314}
315
316static int pop3driver_messages_number(mailsession * session, char * mb,
317 uint32_t * result)
318{
319 carray * msg_tab;
320
321 mailpop3_list(get_pop3_session(session), &msg_tab);
322
323 * result = carray_count(msg_tab) -
324 get_pop3_session(session)->pop3_deleted_count;
325
326 return MAIL_NO_ERROR;
327}
328
329
330/* messages operations */
331
332static int pop3driver_remove_message(mailsession * session, uint32_t num)
333{
334 mailpop3 * pop3;
335 int r;
336
337 pop3 = get_pop3_session(session);
338
339 r = mailpop3_dele(pop3, num);
340 switch (r) {
341 case MAILPOP3_ERROR_BAD_STATE:
342 return MAIL_ERROR_BAD_STATE;
343
344 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
345 return MAIL_ERROR_MSG_NOT_FOUND;
346
347 case MAILPOP3_ERROR_STREAM:
348 return MAIL_ERROR_STREAM;
349
350 case MAILPOP3_NO_ERROR:
351 return MAIL_NO_ERROR;
352
353 default:
354 return MAIL_ERROR_REMOVE;
355 }
356}
357
358static int pop3driver_get_messages_list(mailsession * session,
359 struct mailmessage_list ** result)
360{
361 mailpop3 * pop3;
362
363 pop3 = get_pop3_session(session);
364
365 return pop3_get_messages_list(pop3, session,
366 pop3_message_driver, result);
367}
368
369static int pop3driver_get_message(mailsession * session,
370 uint32_t num, mailmessage ** result)
371{
372 mailmessage * msg_info;
373 int r;
374
375 msg_info = mailmessage_new();
376 if (msg_info == NULL)
377 return MAIL_ERROR_MEMORY;
378
379 r = mailmessage_init(msg_info, session, pop3_message_driver, num, 0);
380 if (r != MAIL_NO_ERROR) {
381 mailmessage_free(msg_info);
382 return r;
383 }
384
385 * result = msg_info;
386
387 return MAIL_NO_ERROR;
388}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_H
37
38#define POP3DRIVER_H
39
40#include <libetpan/pop3driver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * pop3_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3driver_cached.h"
37
38#include "libetpan-config.h"
39
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <fcntl.h>
43#include <string.h>
44#include <unistd.h>
45#include <stdlib.h>
46
47#include "mail.h"
48#include "mail_cache_db.h"
49
50#include "maildriver.h"
51#include "mailmessage.h"
52#include "pop3driver.h"
53#include "mailpop3.h"
54#include "generic_cache.h"
55#include "imfcache.h"
56#include "pop3driver_cached_message.h"
57#include "pop3driver_tools.h"
58#include "maildriver_tools.h"
59
60static int pop3driver_cached_initialize(mailsession * session);
61
62static void pop3driver_cached_uninitialize(mailsession * session);
63
64static int pop3driver_cached_parameters(mailsession * session,
65 int id, void * value);
66
67static int pop3driver_cached_connect_stream(mailsession * session,
68 mailstream * s);
69
70static int pop3driver_cached_starttls(mailsession * session);
71
72static int pop3driver_cached_login(mailsession * session,
73 char * userid, char * password);
74
75static int pop3driver_cached_logout(mailsession * session);
76
77static int pop3driver_cached_check_folder(mailsession * session);
78
79static int pop3driver_cached_noop(mailsession * session);
80
81static int pop3driver_cached_expunge_folder(mailsession * session);
82
83static int pop3driver_cached_status_folder(mailsession * session,
84 char * mb, uint32_t * result_messages, uint32_t * result_recent,
85 uint32_t * result_unseen);
86
87static int pop3driver_cached_messages_number(mailsession * session,
88 char * mb,
89 uint32_t * result);
90
91static int pop3driver_cached_recent_number(mailsession * session,
92 char * mb,
93 uint32_t * result);
94
95static int pop3driver_cached_unseen_number(mailsession * session,
96 char * mb,
97 uint32_t * result);
98
99static int pop3driver_cached_remove_message(mailsession * session,
100 uint32_t num);
101
102static int
103pop3driver_cached_get_messages_list(mailsession * session,
104 struct mailmessage_list ** result);
105
106static int
107pop3driver_cached_get_envelopes_list(mailsession * session,
108 struct mailmessage_list * env_list);
109
110static int pop3driver_cached_get_message(mailsession * session,
111 uint32_t num, mailmessage ** result);
112
113static int pop3driver_cached_get_message_by_uid(mailsession * session,
114 const char * uid, mailmessage ** result);
115
116static mailsession_driver local_pop3_cached_session_driver = {
117 .sess_name = "pop3-cached",
118
119 .sess_initialize = pop3driver_cached_initialize,
120 .sess_uninitialize = pop3driver_cached_uninitialize,
121
122 .sess_parameters = pop3driver_cached_parameters,
123
124 .sess_connect_stream = pop3driver_cached_connect_stream,
125 .sess_connect_path = NULL,
126 .sess_starttls = pop3driver_cached_starttls,
127 .sess_login = pop3driver_cached_login,
128 .sess_logout = pop3driver_cached_logout,
129 .sess_noop = pop3driver_cached_noop,
130
131 .sess_build_folder_name = NULL,
132 .sess_create_folder = NULL,
133 .sess_delete_folder = NULL,
134 .sess_rename_folder = NULL,
135 .sess_check_folder = pop3driver_cached_check_folder,
136 .sess_examine_folder = NULL,
137 .sess_select_folder = NULL,
138 .sess_expunge_folder = pop3driver_cached_expunge_folder,
139 .sess_status_folder = pop3driver_cached_status_folder,
140 .sess_messages_number = pop3driver_cached_messages_number,
141 .sess_recent_number = pop3driver_cached_recent_number,
142 .sess_unseen_number = pop3driver_cached_unseen_number,
143 .sess_list_folders = NULL,
144 .sess_lsub_folders = NULL,
145 .sess_subscribe_folder = NULL,
146 .sess_unsubscribe_folder = NULL,
147
148 .sess_append_message = NULL,
149 .sess_append_message_flags = NULL,
150 .sess_copy_message = NULL,
151 .sess_move_message = NULL,
152
153 .sess_get_messages_list = pop3driver_cached_get_messages_list,
154 .sess_get_envelopes_list = pop3driver_cached_get_envelopes_list,
155 .sess_remove_message = pop3driver_cached_remove_message,
156#if 0
157 .sess_search_messages = maildriver_generic_search_messages,
158#endif
159
160 .sess_get_message = pop3driver_cached_get_message,
161 .sess_get_message_by_uid = pop3driver_cached_get_message_by_uid,
162};
163
164mailsession_driver * pop3_cached_session_driver =
165&local_pop3_cached_session_driver;
166
167#define ENV_NAME "env.db"
168#define FLAGS_NAME "flags.db"
169
170
171static inline struct pop3_cached_session_state_data *
172get_cached_data(mailsession * session)
173{
174 return session->sess_data;
175}
176
177static inline mailsession * get_ancestor(mailsession * session)
178{
179 return get_cached_data(session)->pop3_ancestor;
180}
181
182static inline struct pop3_session_state_data *
183get_ancestor_data(mailsession * session)
184{
185 return get_ancestor(session)->sess_data;
186}
187
188static inline mailpop3 * get_pop3_session(mailsession * session)
189{
190 return get_ancestor_data(session)->pop3_session;
191}
192
193static int pop3driver_cached_initialize(mailsession * session)
194{
195 struct pop3_cached_session_state_data * data;
196
197 data = malloc(sizeof(* data));
198 if (data == NULL)
199 goto err;
200
201 data->pop3_flags_store = mail_flags_store_new();
202 if (data->pop3_flags_store == NULL)
203 goto free_data;
204
205 data->pop3_ancestor = mailsession_new(pop3_session_driver);
206 if (data->pop3_ancestor == NULL)
207 goto free_store;
208
209 data->pop3_flags_hash = chash_new(128, CHASH_COPYNONE);
210 if (data->pop3_flags_hash == NULL)
211 goto free_session;
212
213 session->sess_data = data;
214
215 return MAIL_NO_ERROR;
216
217 free_session:
218 mailsession_free(data->pop3_ancestor);
219 free_store:
220 mail_flags_store_free(data->pop3_flags_store);
221 free_data:
222 free(data);
223 err:
224 return MAIL_ERROR_MEMORY;
225}
226
227static int pop3_flags_store_process(char * flags_directory,
228 struct mail_flags_store * flags_store)
229{
230 char filename_flags[PATH_MAX];
231 struct mail_cache_db * cache_db_flags;
232 MMAPString * mmapstr;
233 unsigned int i;
234 int r;
235 int res;
236
237 if (carray_count(flags_store->fls_tab) == 0)
238 return MAIL_NO_ERROR;
239
240 snprintf(filename_flags, PATH_MAX, "%s/%s",
241 flags_directory, FLAGS_NAME);
242
243 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
244 if (r < 0) {
245 res = MAIL_ERROR_FILE;
246 goto err;
247 }
248
249 mmapstr = mmap_string_new("");
250 if (mmapstr == NULL) {
251 res = MAIL_ERROR_MEMORY;
252 goto close_db_flags;
253 }
254
255 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
256 mailmessage * msg;
257
258 msg = carray_get(flags_store->fls_tab, i);
259
260 r = pop3driver_write_cached_flags(cache_db_flags, mmapstr,
261 msg->msg_uid, msg->msg_flags);
262 }
263
264 mmap_string_free(mmapstr);
265 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
266
267 mail_flags_store_clear(flags_store);
268
269 return MAIL_NO_ERROR;
270
271 close_db_flags:
272 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
273 err:
274 return res;
275}
276
277static void pop3driver_cached_uninitialize(mailsession * session)
278{
279 struct pop3_cached_session_state_data * data;
280
281 data = get_cached_data(session);
282
283 pop3_flags_store_process(data->pop3_flags_directory,
284 data->pop3_flags_store);
285
286 mail_flags_store_free(data->pop3_flags_store);
287
288 chash_free(data->pop3_flags_hash);
289 mailsession_free(data->pop3_ancestor);
290 free(data);
291
292 session->sess_data = data;
293}
294
295static int pop3driver_cached_check_folder(mailsession * session)
296{
297 struct pop3_cached_session_state_data * pop3_data;
298
299 pop3_data = get_cached_data(session);
300
301 pop3_flags_store_process(pop3_data->pop3_flags_directory,
302 pop3_data->pop3_flags_store);
303
304 return MAIL_NO_ERROR;
305}
306
307static int pop3driver_cached_parameters(mailsession * session,
308 int id, void * value)
309{
310 struct pop3_cached_session_state_data * data;
311 int r;
312
313 data = get_cached_data(session);
314
315 switch (id) {
316 case POP3DRIVER_CACHED_SET_CACHE_DIRECTORY:
317 strncpy(data->pop3_cache_directory, value, PATH_MAX);
318 data->pop3_cache_directory[PATH_MAX - 1] = '\0';
319
320 r = generic_cache_create_dir(data->pop3_cache_directory);
321 if (r != MAIL_NO_ERROR)
322 return r;
323
324 return MAIL_NO_ERROR;
325
326 case POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY:
327 strncpy(data->pop3_flags_directory, value, PATH_MAX);
328 data->pop3_flags_directory[PATH_MAX - 1] = '\0';
329
330 r = generic_cache_create_dir(data->pop3_flags_directory);
331 if (r != MAIL_NO_ERROR)
332 return r;
333
334 return MAIL_NO_ERROR;
335
336 default:
337 return mailsession_parameters(data->pop3_ancestor, id, value);
338 }
339}
340
341static int pop3driver_cached_connect_stream(mailsession * session,
342 mailstream * s)
343{
344 int r;
345
346 r = mailsession_connect_stream(get_ancestor(session), s);
347 if (r != MAIL_NO_ERROR)
348 return r;
349
350 return MAIL_NO_ERROR;
351}
352
353static int pop3driver_cached_starttls(mailsession * session)
354{
355 return mailsession_starttls(get_ancestor(session));
356}
357
358
359static int pop3driver_cached_login(mailsession * session,
360 char * userid, char * password)
361{
362 return mailsession_login(get_ancestor(session), userid, password);
363}
364
365static int pop3driver_cached_logout(mailsession * session)
366{
367 struct pop3_cached_session_state_data * cached_data;
368
369 cached_data = get_cached_data(session);
370
371 pop3_flags_store_process(cached_data->pop3_flags_directory,
372 cached_data->pop3_flags_store);
373
374 return mailsession_logout(get_ancestor(session));
375}
376
377static int pop3driver_cached_noop(mailsession * session)
378{
379 return mailsession_noop(get_ancestor(session));
380}
381
382static int pop3driver_cached_expunge_folder(mailsession * session)
383{
384 int res;
385 struct pop3_cached_session_state_data * cached_data;
386 char filename_flags[PATH_MAX];
387 struct mail_cache_db * cache_db_flags;
388 MMAPString * mmapstr;
389 unsigned int i;
390 int r;
391 carray * msg_tab;
392 mailpop3 * pop3;
393
394 pop3 = get_pop3_session(session);
395
396 cached_data = get_cached_data(session);
397
398 pop3_flags_store_process(cached_data->pop3_flags_directory,
399 cached_data->pop3_flags_store);
400
401 snprintf(filename_flags, PATH_MAX, "%s/%s",
402 cached_data->pop3_flags_directory, FLAGS_NAME);
403
404 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
405 if (r < 0) {
406 res = MAIL_ERROR_MEMORY;
407 goto err;
408 }
409
410 mmapstr = mmap_string_new("");
411 if (mmapstr == NULL) {
412 res = MAIL_ERROR_MEMORY;
413 goto close_db_flags;
414 }
415
416 mailpop3_list(pop3, &msg_tab);
417
418 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
419 struct mailpop3_msg_info * pop3_info;
420 struct mail_flags * flags;
421
422 pop3_info = carray_get(msg_tab, i);
423 if (pop3_info == NULL)
424 continue;
425
426 if (pop3_info->msg_deleted)
427 continue;
428
429 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
430 session, pop3_info->msg_index, &flags);
431 if (r != MAIL_NO_ERROR)
432 continue;
433
434 if (flags->fl_flags & MAIL_FLAG_DELETED) {
435 r = mailpop3_dele(pop3, pop3_info->msg_index);
436 }
437
438 mail_flags_free(flags);
439 }
440
441 mmap_string_free(mmapstr);
442 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
443
444 return MAIL_NO_ERROR;
445
446 close_db_flags:
447 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
448 err:
449 return res;
450}
451
452static int pop3driver_cached_status_folder(mailsession * session,
453 char * mb, uint32_t * result_messages, uint32_t * result_recent,
454 uint32_t * result_unseen)
455{
456 int res;
457 struct pop3_cached_session_state_data * cached_data;
458 char filename_flags[PATH_MAX];
459 struct mail_cache_db * cache_db_flags;
460 MMAPString * mmapstr;
461 unsigned int i;
462 int r;
463 carray * msg_tab;
464 mailpop3 * pop3;
465 uint32_t recent;
466 uint32_t unseen;
467
468 recent = 0;
469 unseen = 0;
470
471 pop3 = get_pop3_session(session);
472
473 cached_data = get_cached_data(session);
474
475 pop3_flags_store_process(cached_data->pop3_flags_directory,
476 cached_data->pop3_flags_store);
477
478 snprintf(filename_flags, PATH_MAX, "%s/%s",
479 cached_data->pop3_flags_directory, FLAGS_NAME);
480
481 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
482 if (r < 0) {
483 res = MAIL_ERROR_MEMORY;
484 goto err;
485 }
486
487 mmapstr = mmap_string_new("");
488 if (mmapstr == NULL) {
489 res = MAIL_ERROR_MEMORY;
490 goto close_db_flags;
491 }
492
493 mailpop3_list(pop3, &msg_tab);
494
495 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
496 struct mailpop3_msg_info * pop3_info;
497 struct mail_flags * flags;
498
499 pop3_info = carray_get(msg_tab, i);
500 if (pop3_info == NULL)
501 continue;
502
503 if (pop3_info->msg_deleted)
504 continue;
505
506 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
507 session, pop3_info->msg_index, &flags);
508 if (r != MAIL_NO_ERROR) {
509 recent ++;
510 unseen ++;
511 continue;
512 }
513
514 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
515 recent ++;
516 }
517 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
518 unseen ++;
519 }
520 mail_flags_free(flags);
521
522 }
523
524 mmap_string_free(mmapstr);
525 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
526
527 * result_messages = carray_count(msg_tab) - pop3->pop3_deleted_count;
528 * result_recent = recent;
529 * result_unseen = unseen;
530
531 return MAIL_NO_ERROR;
532
533 close_db_flags:
534 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
535 err:
536 return res;
537}
538
539static int pop3driver_cached_messages_number(mailsession * session,
540 char * mb,
541 uint32_t * result)
542{
543 return mailsession_messages_number(get_ancestor(session), mb, result);
544}
545
546static int pop3driver_cached_recent_number(mailsession * session,
547 char * mb,
548 uint32_t * result)
549{
550 uint32_t messages;
551 uint32_t recent;
552 uint32_t unseen;
553 int r;
554
555 r = pop3driver_cached_status_folder(session, mb,
556 &messages, &recent, &unseen);
557 if (r != MAIL_NO_ERROR)
558 return r;
559
560 * result = recent;
561
562 return MAIL_NO_ERROR;
563}
564
565static int pop3driver_cached_unseen_number(mailsession * session,
566 char * mb,
567 uint32_t * result)
568{
569 uint32_t messages;
570 uint32_t recent;
571 uint32_t unseen;
572 int r;
573
574 r = pop3driver_cached_status_folder(session, mb,
575 &messages, &recent, &unseen);
576 if (r != MAIL_NO_ERROR)
577 return r;
578
579 * result = unseen;
580
581 return MAIL_NO_ERROR;
582}
583
584/* messages operations */
585
586static int pop3driver_cached_remove_message(mailsession * session,
587 uint32_t num)
588{
589 return mailsession_remove_message(get_ancestor(session), num);
590}
591
592static int
593pop3driver_cached_get_messages_list(mailsession * session,
594 struct mailmessage_list ** result)
595{
596 mailpop3 * pop3;
597
598 pop3 = get_pop3_session(session);
599
600 return pop3_get_messages_list(pop3, session,
601 pop3_cached_message_driver, result);
602}
603
604
605static int
606get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
607 mailsession * session, uint32_t num,
608 struct mailimf_fields ** result)
609{
610 int r;
611 char keyname[PATH_MAX];
612 struct mailpop3_msg_info * info;
613 struct mailimf_fields * fields;
614 int res;
615 mailpop3 * pop3;
616
617 pop3 = get_pop3_session(session);
618
619 r = mailpop3_get_msg_info(pop3, num, &info);
620 switch (r) {
621 case MAILPOP3_ERROR_BAD_STATE:
622 return MAIL_ERROR_BAD_STATE;
623 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
624 return MAIL_ERROR_MSG_NOT_FOUND;
625 case MAILPOP3_NO_ERROR:
626 break;
627 default:
628 return MAIL_ERROR_FETCH;
629 }
630
631 snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl);
632
633 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
634 if (r != MAIL_NO_ERROR) {
635 res = r;
636 goto err;
637 }
638
639 * result = fields;
640
641 return MAIL_NO_ERROR;
642
643 err:
644 return res;
645}
646
647static int
648write_cached_envelope(struct mail_cache_db * cache_db,
649 MMAPString * mmapstr,
650 mailsession * session, uint32_t num,
651 struct mailimf_fields * fields)
652{
653 int r;
654 char keyname[PATH_MAX];
655 int res;
656 struct mailpop3_msg_info * info;
657 mailpop3 * pop3;
658
659 pop3 = get_pop3_session(session);
660
661 r = mailpop3_get_msg_info(pop3, num, &info);
662 switch (r) {
663 case MAILPOP3_ERROR_BAD_STATE:
664 return MAIL_ERROR_BAD_STATE;
665 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
666 return MAIL_ERROR_MSG_NOT_FOUND;
667 case MAILPOP3_NO_ERROR:
668 break;
669 default:
670 return MAIL_ERROR_FETCH;
671 }
672
673 snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl);
674
675 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
676 if (r != MAIL_NO_ERROR) {
677 res = r;
678 goto err;
679 }
680
681 return MAIL_NO_ERROR;
682
683 err:
684 return res;
685}
686
687static void get_uid_from_filename(char * filename)
688{
689 char * p;
690
691 p = strstr(filename, "-header");
692 if (p != NULL)
693 * p = 0;
694}
695
696static int
697pop3driver_cached_get_envelopes_list(mailsession * session,
698 struct mailmessage_list * env_list)
699{
700 int r;
701 unsigned int i;
702 struct pop3_cached_session_state_data * cached_data;
703 char filename_env[PATH_MAX];
704 char filename_flags[PATH_MAX];
705 struct mail_cache_db * cache_db_env;
706 struct mail_cache_db * cache_db_flags;
707 MMAPString * mmapstr;
708 int res;
709
710 cached_data = get_cached_data(session);
711
712 pop3_flags_store_process(cached_data->pop3_flags_directory,
713 cached_data->pop3_flags_store);
714
715 snprintf(filename_env, PATH_MAX, "%s/%s",
716 cached_data->pop3_cache_directory, ENV_NAME);
717
718 mmapstr = mmap_string_new("");
719 if (mmapstr == NULL) {
720 res = MAIL_ERROR_MEMORY;
721 goto err;
722 }
723
724 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
725 if (r < 0) {
726 res = MAIL_ERROR_MEMORY;
727 goto free_mmapstr;
728 }
729
730 snprintf(filename_flags, PATH_MAX, "%s/%s",
731 cached_data->pop3_flags_directory, FLAGS_NAME);
732
733 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
734 if (r < 0) {
735 res = MAIL_ERROR_MEMORY;
736 goto close_db_env;
737 }
738
739 /* fill with cached */
740
741 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
742 mailmessage * msg;
743 struct mailimf_fields * fields;
744 struct mail_flags * flags;
745
746 msg = carray_get(env_list->msg_tab, i);
747
748 if (msg->msg_fields == NULL) {
749 r = get_cached_envelope(cache_db_env, mmapstr,
750 session, msg->msg_index, &fields);
751 if (r == MAIL_NO_ERROR) {
752 msg->msg_cached = TRUE;
753 msg->msg_fields = fields;
754 }
755 }
756
757 if (msg->msg_flags == NULL) {
758 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
759 session, msg->msg_index, &flags);
760 if (r == MAIL_NO_ERROR) {
761 msg->msg_flags = flags;
762 }
763 }
764 }
765
766 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
767 mail_cache_db_close_unlock(filename_env, cache_db_env);
768
769 r = maildriver_generic_get_envelopes_list(session, env_list);
770
771 if (r != MAIL_NO_ERROR) {
772 res = r;
773 goto free_mmapstr;
774 }
775
776 /* add flags */
777
778 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
779 mailmessage * msg;
780
781 msg = carray_get(env_list->msg_tab, i);
782
783 if (msg->msg_flags == NULL)
784 msg->msg_flags = mail_flags_new_empty();
785 }
786
787 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
788 if (r < 0) {
789 res = MAIL_ERROR_MEMORY;
790 goto free_mmapstr;
791 }
792
793 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
794 if (r < 0) {
795 res = MAIL_ERROR_MEMORY;
796 goto close_db_env;
797 }
798
799 /* must write cache */
800
801 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
802 mailmessage * msg;
803
804 msg = carray_get(env_list->msg_tab, i);
805
806 if (msg->msg_fields != NULL) {
807 if (!msg->msg_cached) {
808 r = write_cached_envelope(cache_db_env, mmapstr,
809 session, msg->msg_index, msg->msg_fields);
810 }
811 }
812
813 if (msg->msg_flags != NULL) {
814 r = pop3driver_write_cached_flags(cache_db_flags, mmapstr,
815 msg->msg_uid, msg->msg_flags);
816 }
817 }
818
819 /* flush cache */
820
821 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
822
823 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
824 mail_cache_db_close_unlock(filename_env, cache_db_env);
825 mmap_string_free(mmapstr);
826
827 /* remove cache files */
828
829 maildriver_message_cache_clean_up(cached_data->pop3_cache_directory,
830 env_list, get_uid_from_filename);
831
832 return MAIL_NO_ERROR;
833
834 close_db_env:
835 mail_cache_db_close_unlock(filename_env, cache_db_env);
836 free_mmapstr:
837 mmap_string_free(mmapstr);
838 err:
839 return res;
840}
841
842static int pop3driver_cached_get_message(mailsession * session,
843 uint32_t num, mailmessage ** result)
844{
845 mailmessage * msg_info;
846 int r;
847
848 msg_info = mailmessage_new();
849 if (msg_info == NULL)
850 return MAIL_ERROR_MEMORY;
851
852 r = mailmessage_init(msg_info, session, pop3_cached_message_driver, num, 0);
853 if (r != MAIL_NO_ERROR) {
854 mailmessage_free(msg_info);
855 return r;
856 }
857
858 * result = msg_info;
859
860 return MAIL_NO_ERROR;
861}
862
863static int pop3driver_cached_get_message_by_uid(mailsession * session,
864 const char * uid, mailmessage ** result)
865{
866 mailpop3 * pop3;
867 struct mailpop3_msg_info * msg_info;
868 int found;
869 unsigned int i;
870
871 if (uid == NULL)
872 return MAIL_ERROR_INVAL;
873
874 pop3 = get_pop3_session(session);
875
876 found = 0;
877
878 /* iterate all messages and look for uid */
879 for(i = 0 ; i < carray_count(pop3->pop3_msg_tab) ; i++) {
880 msg_info = carray_get(pop3->pop3_msg_tab, i);
881
882 if (msg_info == NULL)
883 continue;
884
885 if (msg_info->msg_deleted)
886 continue;
887
888 /* uid found, stop looking */
889 if (strcmp(msg_info->msg_uidl, uid) == 0) {
890 found = 1;
891 break;
892 }
893 }
894
895 if (!found)
896 return MAIL_ERROR_MSG_NOT_FOUND;
897
898 return pop3driver_cached_get_message(session, msg_info->msg_index, result);
899}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_CACHED_H
37
38#define POP3DRIVER_CACHED_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/pop3driver_types.h>
45
46extern mailsession_driver * pop3_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3driver_cached_message.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "mail_cache_db.h"
42
43#include "mailmessage.h"
44#include "mailmessage_tools.h"
45#include "pop3driver.h"
46#include "pop3driver_tools.h"
47#include "pop3driver_cached.h"
48#include "pop3driver_message.h"
49#include "generic_cache.h"
50
51static int pop3_prefetch(mailmessage * msg_info);
52
53static void pop3_prefetch_free(struct generic_message_t * msg);
54
55static int pop3_initialize(mailmessage * msg_info);
56
57static void pop3_flush(mailmessage * msg_info);
58
59static void pop3_check(mailmessage * msg_info);
60
61static int pop3_fetch_header(mailmessage * msg_info,
62 char ** result,
63 size_t * result_len);
64
65static int pop3_fetch_size(mailmessage * msg_info,
66 size_t * result);
67
68static int pop3_get_flags(mailmessage * msg_info,
69 struct mail_flags ** result);
70
71static void pop3_uninitialize(mailmessage * msg_info);
72
73static mailmessage_driver local_pop3_cached_message_driver = {
74 .msg_name = "pop3-cached",
75
76 .msg_initialize = pop3_initialize,
77 .msg_uninitialize = pop3_uninitialize,
78
79 .msg_flush = pop3_flush,
80 .msg_check = pop3_check,
81
82 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
83
84 .msg_fetch = mailmessage_generic_fetch,
85 .msg_fetch_header = pop3_fetch_header,
86 .msg_fetch_body = mailmessage_generic_fetch_body,
87 .msg_fetch_size = pop3_fetch_size,
88 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
89 .msg_fetch_section = mailmessage_generic_fetch_section,
90 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
91 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
92 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
93 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
94
95 .msg_get_flags = pop3_get_flags,
96};
97
98mailmessage_driver * pop3_cached_message_driver =
99&local_pop3_cached_message_driver;
100
101
102static inline struct pop3_cached_session_state_data *
103get_cached_session_data(mailmessage * msg)
104{
105 return msg->msg_session->sess_data;
106}
107
108static inline mailsession * get_ancestor_session(mailmessage * msg)
109{
110 return get_cached_session_data(msg)->pop3_ancestor;
111}
112
113static inline struct pop3_session_state_data *
114get_ancestor_session_data(mailmessage * msg)
115{
116 return get_ancestor_session(msg)->sess_data;
117}
118
119static inline mailpop3 * get_pop3_session(mailmessage * msg)
120{
121 return get_ancestor_session_data(msg)->pop3_session;
122}
123
124
125static int pop3_prefetch(mailmessage * msg_info)
126{
127 char * msg_content;
128 size_t msg_length;
129 struct generic_message_t * msg;
130 int r;
131 struct pop3_cached_session_state_data * cached_data;
132 char filename[PATH_MAX];
133
134 /* we try the cached message */
135
136 cached_data = get_cached_session_data(msg_info);
137
138 snprintf(filename, PATH_MAX, "%s/%s",
139 cached_data->pop3_cache_directory, msg_info->msg_uid);
140
141 r = generic_cache_read(filename, &msg_content, &msg_length);
142 if (r == MAIL_NO_ERROR) {
143 msg = msg_info->msg_data;
144
145 msg->msg_message = msg_content;
146 msg->msg_length = msg_length;
147
148 return MAIL_NO_ERROR;
149 }
150
151 /* we get the message through the network */
152
153 r = pop3driver_retr(get_ancestor_session(msg_info), msg_info->msg_index,
154 &msg_content, &msg_length);
155 if (r != MAIL_NO_ERROR)
156 return r;
157
158 /* we write the message cache */
159
160 generic_cache_store(filename, msg_content, msg_length);
161
162 msg = msg_info->msg_data;
163
164 msg->msg_message = msg_content;
165 msg->msg_length = msg_length;
166
167 return MAIL_NO_ERROR;
168}
169
170static void pop3_prefetch_free(struct generic_message_t * msg)
171{
172 if (msg->msg_message != NULL) {
173 mmap_string_unref(msg->msg_message);
174 msg->msg_message = NULL;
175 }
176}
177
178static int pop3_initialize(mailmessage * msg_info)
179{
180 struct generic_message_t * msg;
181 int r;
182 char * uid;
183 struct mailpop3_msg_info * info;
184 mailpop3 * pop3;
185
186 pop3 = get_pop3_session(msg_info);
187
188 r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info);
189 switch (r) {
190 case MAILPOP3_NO_ERROR:
191 break;
192 default:
193 return pop3driver_pop3_error_to_mail_error(r);
194 }
195
196 uid = strdup(info->msg_uidl);
197 if (uid == NULL)
198 return MAIL_ERROR_MEMORY;
199
200 r = mailmessage_generic_initialize(msg_info);
201 if (r != MAIL_NO_ERROR) {
202 free(uid);
203 return r;
204 }
205
206 msg = msg_info->msg_data;
207 msg->msg_prefetch = pop3_prefetch;
208 msg->msg_prefetch_free = pop3_prefetch_free;
209 msg_info->msg_uid = uid;
210
211 return MAIL_NO_ERROR;
212}
213
214static void pop3_uninitialize(mailmessage * msg_info)
215{
216 mailmessage_generic_uninitialize(msg_info);
217}
218
219#define FLAGS_NAME "flags.db"
220
221static void pop3_flush(mailmessage * msg_info)
222{
223 mailmessage_generic_flush(msg_info);
224}
225
226static void pop3_check(mailmessage * msg_info)
227{
228 int r;
229
230 if (msg_info->msg_flags != NULL) {
231 r = mail_flags_store_set(get_cached_session_data(msg_info)->pop3_flags_store,
232 msg_info);
233 }
234}
235
236
237static int pop3_fetch_header(mailmessage * msg_info,
238 char ** result,
239 size_t * result_len)
240{
241 struct generic_message_t * msg;
242 char * headers;
243 size_t headers_length;
244 int r;
245 struct pop3_cached_session_state_data * cached_data;
246 char filename[PATH_MAX];
247
248 msg = msg_info->msg_data;
249
250 if (msg->msg_message != NULL)
251 return mailmessage_generic_fetch_header(msg_info,
252 result, result_len);
253
254 /* we try the cached message */
255
256 cached_data = get_cached_session_data(msg_info);
257
258 snprintf(filename, PATH_MAX, "%s/%s-header",
259 cached_data->pop3_cache_directory, msg_info->msg_uid);
260
261 r = generic_cache_read(filename, &headers, &headers_length);
262 if (r == MAIL_NO_ERROR) {
263 * result = headers;
264 * result_len = headers_length;
265
266 return MAIL_NO_ERROR;
267 }
268
269 /* we get the message trough the network */
270
271 r = pop3driver_header(get_ancestor_session(msg_info), msg_info->msg_index,
272 &headers, &headers_length);
273 if (r != MAIL_NO_ERROR)
274 return r;
275
276 generic_cache_store(filename, headers, headers_length);
277
278 * result = headers;
279 * result_len = headers_length;
280
281 return MAIL_NO_ERROR;
282}
283
284static int pop3_fetch_size(mailmessage * msg_info,
285 size_t * result)
286{
287 return pop3driver_size(get_ancestor_session(msg_info),
288 msg_info->msg_index, result);
289}
290
291static int pop3_get_flags(mailmessage * msg_info,
292 struct mail_flags ** result)
293{
294 int r;
295 struct mail_flags * flags;
296 struct mail_cache_db * cache_db_flags;
297 char filename_flags[PATH_MAX];
298 int res;
299 struct pop3_cached_session_state_data * cached_data;
300 MMAPString * mmapstr;
301
302 if (msg_info->msg_flags != NULL) {
303 * result = msg_info->msg_flags;
304
305 return MAIL_NO_ERROR;
306 }
307
308 cached_data = get_cached_session_data(msg_info);
309
310 flags = mail_flags_store_get(cached_data->pop3_flags_store,
311 msg_info->msg_index);
312
313 if (flags == NULL) {
314 snprintf(filename_flags, PATH_MAX, "%s/%s",
315 cached_data->pop3_flags_directory, FLAGS_NAME);
316
317 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
318 if (r < 0) {
319 res = MAIL_ERROR_MEMORY;
320 goto err;
321 }
322
323 mmapstr = mmap_string_new("");
324 if (mmapstr == NULL) {
325 res = MAIL_ERROR_MEMORY;
326 goto close_db_flags;
327 }
328
329 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
330 msg_info->msg_session, msg_info->msg_index, &flags);
331 if (r != MAIL_NO_ERROR) {
332 flags = mail_flags_new_empty();
333 if (flags == NULL) {
334 res = MAIL_ERROR_MEMORY;
335 goto free_mmapstr;
336 }
337 }
338
339 mmap_string_free(mmapstr);
340 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
341 }
342
343 msg_info->msg_flags = flags;
344
345 * result = flags;
346
347 return MAIL_NO_ERROR;
348
349 free_mmapstr:
350 mmap_string_free(mmapstr);
351 close_db_flags:
352 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
353 err:
354 return res;
355}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_CACHED_MESSAGE_H
37
38#define POP3DRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/pop3driver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * pop3_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3driver_message.h"
37
38#include "mailmessage_tools.h"
39#include "pop3driver_tools.h"
40#include "pop3driver.h"
41#include "mailpop3.h"
42#include <stdlib.h>
43#include <string.h>
44
45static int pop3_prefetch(mailmessage * msg_info);
46
47static void pop3_prefetch_free(struct generic_message_t * msg);
48
49static int pop3_initialize(mailmessage * msg_info);
50
51static int pop3_fetch_header(mailmessage * msg_info,
52 char ** result,
53 size_t * result_len);
54
55static int pop3_fetch_size(mailmessage * msg_info,
56 size_t * result);
57
58static mailmessage_driver local_pop3_message_driver = {
59 .msg_name = "pop3",
60
61 .msg_initialize = pop3_initialize,
62 .msg_uninitialize = mailmessage_generic_uninitialize,
63
64 .msg_flush = mailmessage_generic_flush,
65 .msg_check = NULL,
66
67 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
68
69 .msg_fetch = mailmessage_generic_fetch,
70 .msg_fetch_header = pop3_fetch_header,
71 .msg_fetch_body = mailmessage_generic_fetch_body,
72 .msg_fetch_size = pop3_fetch_size,
73 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
74 .msg_fetch_section = mailmessage_generic_fetch_section,
75 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
76 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
77 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
78 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
79
80 .msg_get_flags = NULL,
81};
82
83mailmessage_driver * pop3_message_driver = &local_pop3_message_driver;
84
85static inline struct pop3_session_state_data *
86get_data(mailsession * session)
87{
88 return session->sess_data;
89}
90
91
92static mailpop3 * get_pop3_session(mailsession * session)
93{
94 return get_data(session)->pop3_session;
95}
96
97
98static int pop3_prefetch(mailmessage * msg_info)
99{
100 char * msg_content;
101 size_t msg_length;
102 struct generic_message_t * msg;
103 int r;
104
105 r = pop3driver_retr(msg_info->msg_session, msg_info->msg_index,
106 &msg_content, &msg_length);
107 if (r != MAIL_NO_ERROR)
108 return r;
109
110 msg = msg_info->msg_data;
111
112 msg->msg_message = msg_content;
113 msg->msg_length = msg_length;
114
115 return MAIL_NO_ERROR;
116}
117
118static void pop3_prefetch_free(struct generic_message_t * msg)
119{
120 if (msg->msg_message != NULL) {
121 mmap_string_unref(msg->msg_message);
122 msg->msg_message = NULL;
123 }
124}
125
126static int pop3_initialize(mailmessage * msg_info)
127{
128 struct generic_message_t * msg;
129 int r;
130 char * uid;
131 struct mailpop3_msg_info * info;
132 mailpop3 * pop3;
133
134 pop3 = get_pop3_session(msg_info->msg_session);
135
136 r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info);
137 switch (r) {
138 case MAILPOP3_NO_ERROR:
139 break;
140 default:
141 return pop3driver_pop3_error_to_mail_error(r);
142 }
143
144 uid = strdup(info->msg_uidl);
145 if (uid == NULL)
146 return MAIL_ERROR_MEMORY;
147
148 r = mailmessage_generic_initialize(msg_info);
149 if (r != MAIL_NO_ERROR) {
150 free(uid);
151 return r;
152 }
153
154 msg = msg_info->msg_data;
155 msg->msg_prefetch = pop3_prefetch;
156 msg->msg_prefetch_free = pop3_prefetch_free;
157 msg_info->msg_uid = uid;
158
159 return MAIL_NO_ERROR;
160}
161
162
163static int pop3_fetch_header(mailmessage * msg_info,
164 char ** result,
165 size_t * result_len)
166{
167 struct generic_message_t * msg;
168 char * headers;
169 size_t headers_length;
170 int r;
171
172 msg = msg_info->msg_data;
173
174 if (msg->msg_message != NULL)
175 return mailmessage_generic_fetch_header(msg_info,
176 result, result_len);
177
178 r = pop3driver_header(msg_info->msg_session, msg_info->msg_index,
179 &headers, &headers_length);
180 if (r != MAIL_NO_ERROR)
181 return r;
182
183 * result = headers;
184 * result_len = headers_length;
185
186 return MAIL_NO_ERROR;
187}
188
189static int pop3_fetch_size(mailmessage * msg_info,
190 size_t * result)
191{
192 return pop3driver_size(msg_info->msg_session, msg_info->msg_index, result);
193}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_MESSAGE_H
37
38#define POP3DRIVER_MESSAGE_H
39
40#include <libetpan/pop3driver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * pop3_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3driver_tools.h"
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <unistd.h>
42
43#include "maildriver_types.h"
44#include "mailpop3.h"
45#include "pop3driver.h"
46#include "pop3driver_cached.h"
47#include "generic_cache.h"
48#include "imfcache.h"
49#include "mailmessage.h"
50#include "mail_cache_db.h"
51
52int pop3driver_pop3_error_to_mail_error(int error)
53{
54 switch (error) {
55 case MAILPOP3_NO_ERROR:
56 return MAIL_NO_ERROR;
57
58 case MAILPOP3_ERROR_BAD_STATE:
59 return MAIL_ERROR_BAD_STATE;
60
61 case MAILPOP3_ERROR_UNAUTHORIZED:
62 return MAIL_ERROR_CONNECT;
63
64 case MAILPOP3_ERROR_STREAM:
65 return MAIL_ERROR_STREAM;
66
67 case MAILPOP3_ERROR_DENIED:
68 return MAIL_ERROR_CONNECT;
69
70 case MAILPOP3_ERROR_BAD_USER:
71 case MAILPOP3_ERROR_BAD_PASSWORD:
72 return MAIL_ERROR_LOGIN;
73
74 case MAILPOP3_ERROR_CANT_LIST:
75 return MAIL_ERROR_LIST;
76
77 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
78 return MAIL_ERROR_MSG_NOT_FOUND;
79
80 case MAILPOP3_ERROR_MEMORY:
81 return MAIL_ERROR_MEMORY;
82
83 case MAILPOP3_ERROR_CONNECTION_REFUSED:
84 return MAIL_ERROR_CONNECT;
85
86 case MAILPOP3_ERROR_APOP_NOT_SUPPORTED:
87 return MAIL_ERROR_NO_APOP;
88
89 case MAILPOP3_ERROR_CAPA_NOT_SUPPORTED:
90 return MAIL_ERROR_CAPABILITY;
91
92 case MAILPOP3_ERROR_STLS_NOT_SUPPORTED:
93 return MAIL_ERROR_NO_TLS;
94
95 default:
96 return MAIL_ERROR_INVAL;
97 }
98};
99
100static inline struct pop3_session_state_data *
101session_get_data(mailsession * session)
102{
103 return session->sess_data;
104}
105
106static inline mailpop3 * session_get_pop3_session(mailsession * session)
107{
108 return session_get_data(session)->pop3_session;
109}
110
111static inline struct pop3_cached_session_state_data *
112cached_session_get_data(mailsession * session)
113{
114 return session->sess_data;
115}
116
117static inline mailsession *
118cached_session_get_ancestor(mailsession * session)
119{
120 return cached_session_get_data(session)->pop3_ancestor;
121}
122
123static inline struct pop3_session_state_data *
124cached_session_get_ancestor_data(mailsession * session)
125{
126 return session_get_data(cached_session_get_ancestor(session));
127}
128
129static inline mailpop3 *
130cached_session_get_pop3_session(mailsession * session)
131{
132 return session_get_pop3_session(cached_session_get_ancestor(session));
133}
134
135
136int pop3driver_retr(mailsession * session, uint32_t index,
137 char ** result, size_t * result_len)
138{
139 char * msg_content;
140 size_t msg_length;
141 int r;
142
143 r = mailpop3_retr(session_get_pop3_session(session), index,
144 &msg_content, &msg_length);
145
146 switch (r) {
147 case MAILPOP3_NO_ERROR:
148 break;
149 default:
150 return pop3driver_pop3_error_to_mail_error(r);
151 }
152
153 * result = msg_content;
154 * result_len = msg_length;
155
156 return MAIL_NO_ERROR;
157}
158
159int pop3driver_header(mailsession * session, uint32_t index,
160 char ** result,
161 size_t * result_len)
162{
163 char * headers;
164 size_t headers_length;
165 int r;
166
167 r = mailpop3_header(session_get_pop3_session(session),
168 index, &headers, &headers_length);
169
170 switch (r) {
171 case MAILPOP3_NO_ERROR:
172 break;
173 default:
174 return pop3driver_pop3_error_to_mail_error(r);
175 }
176
177 * result = headers;
178 * result_len = headers_length;
179
180 return MAIL_NO_ERROR;
181}
182
183int pop3driver_size(mailsession * session, uint32_t index,
184 size_t * result)
185{
186 mailpop3 * pop3;
187 carray * msg_tab;
188 struct mailpop3_msg_info * info;
189 int r;
190
191 pop3 = session_get_pop3_session(session);
192
193 mailpop3_list(pop3, &msg_tab);
194
195 r = mailpop3_get_msg_info(pop3, index, &info);
196 switch (r) {
197 case MAILPOP3_NO_ERROR:
198 break;
199 default:
200 return pop3driver_pop3_error_to_mail_error(r);
201 }
202
203 * result = info->msg_size;
204
205 return MAIL_NO_ERROR;
206}
207
208int
209pop3driver_get_cached_flags(struct mail_cache_db * cache_db,
210 MMAPString * mmapstr,
211 mailsession * session,
212 uint32_t num,
213 struct mail_flags ** result)
214{
215 int r;
216 char keyname[PATH_MAX];
217 struct mail_flags * flags;
218 int res;
219 struct mailpop3_msg_info * info;
220
221 r = mailpop3_get_msg_info(cached_session_get_pop3_session(session),
222 num, &info);
223 switch (r) {
224 case MAILPOP3_ERROR_BAD_STATE:
225 return MAIL_ERROR_BAD_STATE;
226 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
227 return MAIL_ERROR_MSG_NOT_FOUND;
228 case MAILPOP3_NO_ERROR:
229 break;
230 default:
231 return MAIL_ERROR_FETCH;
232 }
233
234 snprintf(keyname, PATH_MAX, "%s-flags", info->msg_uidl);
235
236 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
237 if (r != MAIL_NO_ERROR) {
238 res = r;
239 goto err;
240 }
241
242 * result = flags;
243
244 return MAIL_NO_ERROR;
245
246 err:
247 return res;
248}
249
250int
251pop3driver_write_cached_flags(struct mail_cache_db * cache_db,
252 MMAPString * mmapstr,
253 char * uid,
254 struct mail_flags * flags)
255{
256 int r;
257 char keyname[PATH_MAX];
258 int res;
259
260 snprintf(keyname, PATH_MAX, "%s-flags", uid);
261
262 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
263 if (r != MAIL_NO_ERROR) {
264 res = r;
265 goto err;
266 }
267
268 return MAIL_NO_ERROR;
269
270 err:
271 return res;
272}
273
274int pop3_get_messages_list(mailpop3 * pop3,
275 mailsession * session,
276 mailmessage_driver * driver,
277 struct mailmessage_list ** result)
278{
279 carray * msg_tab;
280 carray * tab;
281 struct mailmessage_list * env_list;
282 unsigned int i;
283 int res;
284 int r;
285
286 mailpop3_list(pop3, &msg_tab);
287
288 tab = carray_new(128);
289 if (tab == NULL) {
290 res = MAIL_ERROR_MEMORY;
291 goto err;
292 }
293
294 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
295 struct mailpop3_msg_info * pop3_info;
296 mailmessage * msg;
297
298 pop3_info = carray_get(msg_tab, i);
299
300 if (pop3_info == NULL)
301 continue;
302
303 if (pop3_info->msg_deleted)
304 continue;
305
306 msg = mailmessage_new();
307 if (msg == NULL) {
308 res = MAIL_ERROR_MEMORY;
309 goto free_list;
310 }
311
312 r = mailmessage_init(msg, session, driver,
313 (uint32_t) pop3_info->msg_index, pop3_info->msg_size);
314 if (r != MAIL_NO_ERROR) {
315 mailmessage_free(msg);
316 res = r;
317 goto free_list;
318 }
319
320 r = carray_add(tab, msg, NULL);
321 if (r < 0) {
322 mailmessage_free(msg);
323 res = MAIL_ERROR_MEMORY;
324 goto free_list;
325 }
326 }
327
328 env_list = mailmessage_list_new(/*list*/ tab);
329 if (env_list == NULL) {
330 res = MAIL_ERROR_MEMORY;
331 goto free_list;
332 }
333
334 * result = env_list;
335
336 return MAIL_NO_ERROR;
337
338 free_list:
339 for(i = 0 ; i < carray_count(tab) ; i ++)
340 mailmessage_free(carray_get(tab, i));
341 carray_free(tab);
342 err:
343 return res;
344}
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_TOOLS_H
37
38#define POP3DRIVER_TOOLS_H
39
40#include "mail_cache_db_types.h"
41#include "pop3driver_types.h"
42#include "mailpop3.h"
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48int pop3driver_pop3_error_to_mail_error(int error);
49
50int pop3driver_retr(mailsession * session, uint32_t index,
51 char ** result, size_t * result_len);
52
53int pop3driver_header(mailsession * session, uint32_t index,
54 char ** result,
55 size_t * result_len);
56
57int pop3driver_size(mailsession * session, uint32_t index,
58 size_t * result);
59
60int
61pop3driver_get_cached_flags(struct mail_cache_db * cache_db,
62 MMAPString * mmapstr,
63 mailsession * session,
64 uint32_t num,
65 struct mail_flags ** result);
66
67int
68pop3driver_write_cached_flags(struct mail_cache_db * cache_db,
69 MMAPString * mmapstr,
70 char * uid,
71 struct mail_flags * flags);
72
73int pop3_get_messages_list(mailpop3 * pop3,
74 mailsession * session,
75 mailmessage_driver * driver,
76 struct mailmessage_list ** result);
77
78#ifdef __cplusplus
79}
80#endif
81
82#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_TYPES_H
37
38#define POP3DRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/mailpop3.h>
44#include <libetpan/maildriver_types.h>
45#include <libetpan/chash.h>
46#include <libetpan/mailstorage_types.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52/* POP3 driver for session */
53
54enum {
55 POP3DRIVER_SET_AUTH_TYPE = 1,
56};
57
58enum {
59 POP3DRIVER_AUTH_TYPE_PLAIN = 0,
60 POP3DRIVER_AUTH_TYPE_APOP,
61 POP3DRIVER_AUTH_TYPE_TRY_APOP,
62};
63
64struct pop3_session_state_data {
65 int pop3_auth_type;
66 mailpop3 * pop3_session;
67};
68
69/* cached POP3 driver for session */
70
71enum {
72 /* the mapping of the parameters should be the same as for pop3 */
73 POP3DRIVER_CACHED_SET_AUTH_TYPE = 1,
74 /* cache specific */
75 POP3DRIVER_CACHED_SET_CACHE_DIRECTORY,
76 POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY,
77};
78
79struct pop3_cached_session_state_data {
80 mailsession * pop3_ancestor;
81 char pop3_cache_directory[PATH_MAX];
82 char pop3_flags_directory[PATH_MAX];
83 chash * pop3_flags_hash;
84 carray * pop3_flags_array;
85 struct mail_flags_store * pop3_flags_store;
86};
87
88/* pop3 storage */
89
90/*
91 pop3_mailstorage is the state data specific to the POP3 storage.
92
93 - servername this is the name of the POP3 server
94
95 - port is the port to connect to, on the server.
96 you give 0 to use the default port.
97
98 - connection_type is the type of socket layer to use.
99 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
100 CONNECTION_TYPE_TRY_STARTTLS or CONNECTION_TYPE_TLS.
101
102 - auth_type is the authenticate mechanism to use.
103 The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP
104 or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented.
105
106 - login is the login of the POP3 account.
107
108 - password is the password of the POP3 account.
109
110 - cached if this value is != 0, a persistant cache will be
111 stored on local system.
112
113 - cache_directory is the location of the cache.
114
115 - flags_directory is the location of the flags.
116*/
117
118struct pop3_mailstorage {
119 char * pop3_servername;
120 uint16_t pop3_port;
121 char * pop3_command;
122 int pop3_connection_type;
123
124 int pop3_auth_type;
125 char * pop3_login;
126 char * pop3_password;
127
128 int pop3_cached;
129 char * pop3_cache_directory;
130 char * pop3_flags_directory;
131};
132
133/* this is the type of POP3 authentication */
134
135enum {
136 POP3_AUTH_TYPE_PLAIN, /* plain text authentication */
137 POP3_AUTH_TYPE_APOP, /* APOP authentication */
138 POP3_AUTH_TYPE_TRY_APOP, /* first, try APOP, if it fails,
139 try plain text */
140 POP3_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */
141 POP3_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */
142 POP3_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */
143 POP3_AUTH_TYPE_SASL_PLAIN, /* SASL plain */
144 POP3_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */
145 POP3_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */
146 POP3_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */
147};
148
149#ifdef __cplusplus
150}
151#endif
152
153#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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3storage.h"
37
38#include <stdlib.h>
39#include <string.h>
40
41#include "mail.h"
42#include "mailstorage_tools.h"
43#include "maildriver.h"
44
45/* pop3 storage */
46
47#define POP3_DEFAULT_PORT 110
48#define POP3S_DEFAULT_PORT 995
49
50static int pop3_mailstorage_connect(struct mailstorage * storage);
51static int pop3_mailstorage_get_folder_session(struct mailstorage * storage,
52 char * pathname, mailsession ** result);
53static void pop3_mailstorage_uninitialize(struct mailstorage * storage);
54
55static mailstorage_driver pop3_mailstorage_driver = {
56 .sto_name = "pop3",
57 .sto_connect = pop3_mailstorage_connect,
58 .sto_get_folder_session = pop3_mailstorage_get_folder_session,
59 .sto_uninitialize = pop3_mailstorage_uninitialize,
60};
61
62int pop3_mailstorage_init(struct mailstorage * storage,
63 char * pop3_servername, uint16_t pop3_port,
64 char * pop3_command,
65 int pop3_connection_type, int pop3_auth_type,
66 char * pop3_login, char * pop3_password,
67 int pop3_cached, char * pop3_cache_directory, char * pop3_flags_directory)
68{
69 struct pop3_mailstorage * pop3_storage;
70
71 pop3_storage = malloc(sizeof(* pop3_storage));
72 if (pop3_storage == NULL)
73 goto err;
74
75 pop3_storage->pop3_servername = strdup(pop3_servername);
76 if (pop3_storage->pop3_servername == NULL)
77 goto free;
78
79 pop3_storage->pop3_connection_type = pop3_connection_type;
80
81 if (pop3_port == 0) {
82 switch (pop3_connection_type) {
83 case CONNECTION_TYPE_PLAIN:
84 case CONNECTION_TYPE_TRY_STARTTLS:
85 case CONNECTION_TYPE_STARTTLS:
86 case CONNECTION_TYPE_COMMAND:
87 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
88 case CONNECTION_TYPE_COMMAND_STARTTLS:
89 pop3_port = POP3_DEFAULT_PORT;
90 break;
91
92 case CONNECTION_TYPE_TLS:
93 case CONNECTION_TYPE_COMMAND_TLS:
94 pop3_port = POP3S_DEFAULT_PORT;
95 break;
96 }
97 }
98
99 pop3_storage->pop3_port = pop3_port;
100
101 if (pop3_command != NULL) {
102 pop3_storage->pop3_command = strdup(pop3_command);
103 if (pop3_storage->pop3_command == NULL)
104 goto free_servername;
105 }
106 else
107 pop3_storage->pop3_command = NULL;
108
109 pop3_storage->pop3_auth_type = pop3_auth_type;
110
111 if (pop3_login != NULL) {
112 pop3_storage->pop3_login = strdup(pop3_login);
113 if (pop3_storage->pop3_login == NULL)
114 goto free_command;
115 }
116 else
117 pop3_storage->pop3_login = NULL;
118
119 if (pop3_password != NULL) {
120 pop3_storage->pop3_password = strdup(pop3_password);
121 if (pop3_storage->pop3_password == NULL)
122 goto free_login;
123 }
124 else
125 pop3_storage->pop3_password = NULL;
126
127 pop3_storage->pop3_cached = pop3_cached;
128
129 if (pop3_cached && (pop3_cache_directory != NULL) &&
130 (pop3_flags_directory != NULL)) {
131 pop3_storage->pop3_cache_directory = strdup(pop3_cache_directory);
132 if (pop3_storage->pop3_cache_directory == NULL)
133 goto free_password;
134 pop3_storage->pop3_flags_directory = strdup(pop3_flags_directory);
135 if (pop3_storage->pop3_flags_directory == NULL)
136 goto free_cache_directory;
137 }
138 else {
139 pop3_storage->pop3_cached = FALSE;
140 pop3_storage->pop3_cache_directory = NULL;
141 pop3_storage->pop3_flags_directory = NULL;
142 }
143
144 storage->sto_data = pop3_storage;
145 storage->sto_driver = &pop3_mailstorage_driver;
146
147 return MAIL_NO_ERROR;
148
149 free_cache_directory:
150 free(pop3_storage->pop3_cache_directory);
151 free_password:
152 if (pop3_storage->pop3_password != NULL)
153 free(pop3_storage->pop3_password);
154 free_login:
155 if (pop3_storage->pop3_login != NULL)
156 free(pop3_storage->pop3_login);
157 free_command:
158 if (pop3_storage->pop3_command != NULL)
159 free(pop3_storage->pop3_command);
160 free_servername:
161 if (pop3_storage->pop3_servername != NULL)
162 free(pop3_storage->pop3_servername);
163 free:
164 free(pop3_storage);
165 err:
166 return MAIL_ERROR_MEMORY;
167}
168
169static void pop3_mailstorage_uninitialize(struct mailstorage * storage)
170{
171 struct pop3_mailstorage * pop3_storage;
172
173 pop3_storage = storage->sto_data;
174
175 if (pop3_storage->pop3_flags_directory != NULL)
176 free(pop3_storage->pop3_flags_directory);
177 if (pop3_storage->pop3_cache_directory != NULL)
178 free(pop3_storage->pop3_cache_directory);
179 if (pop3_storage->pop3_password != NULL)
180 free(pop3_storage->pop3_password);
181 if (pop3_storage->pop3_login != NULL)
182 free(pop3_storage->pop3_login);
183 if (pop3_storage->pop3_command != NULL)
184 free(pop3_storage->pop3_command);
185 free(pop3_storage->pop3_servername);
186 free(pop3_storage);
187
188 storage->sto_data = pop3_storage;
189}
190
191static int pop3_mailstorage_connect(struct mailstorage * storage)
192{
193 struct pop3_mailstorage * pop3_storage;
194 mailsession_driver * driver;
195 int r;
196 int res;
197 mailsession * session;
198 int auth_type;
199
200 pop3_storage = storage->sto_data;
201
202 if (pop3_storage->pop3_cached)
203 driver = pop3_cached_session_driver;
204 else
205 driver = pop3_session_driver;
206
207 r = mailstorage_generic_connect(driver,
208 pop3_storage->pop3_servername,
209 pop3_storage->pop3_port, pop3_storage->pop3_command,
210 pop3_storage->pop3_connection_type,
211 POP3DRIVER_CACHED_SET_CACHE_DIRECTORY,
212 pop3_storage->pop3_cache_directory,
213 POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY,
214 pop3_storage->pop3_flags_directory,
215 &session);
216 switch (r) {
217 case MAIL_NO_ERROR_NON_AUTHENTICATED:
218 case MAIL_NO_ERROR_AUTHENTICATED:
219 case MAIL_NO_ERROR:
220 break;
221 default:
222 res = r;
223 goto err;
224 }
225
226 auth_type = -1;
227 switch (pop3_storage->pop3_auth_type) {
228 case POP3_AUTH_TYPE_PLAIN:
229 auth_type = POP3DRIVER_AUTH_TYPE_PLAIN;
230 break;
231 case POP3_AUTH_TYPE_APOP:
232 auth_type = POP3DRIVER_AUTH_TYPE_APOP;
233 break;
234 case POP3_AUTH_TYPE_TRY_APOP:
235 auth_type = POP3DRIVER_AUTH_TYPE_TRY_APOP;
236 break;
237 }
238
239 if (auth_type != -1) {
240 mailsession_parameters(session, POP3DRIVER_SET_AUTH_TYPE, &auth_type);
241 }
242
243 r = mailstorage_generic_auth(session, r,
244 pop3_storage->pop3_auth_type,
245 pop3_storage->pop3_login,
246 pop3_storage->pop3_password);
247 if (r != MAIL_NO_ERROR) {
248 if (pop3_storage->pop3_auth_type == POP3_AUTH_TYPE_TRY_APOP) {
249 /* try in clear authentication */
250 mailsession_free(session);
251
252 pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_PLAIN;
253 r = mailstorage_connect(storage);
254 if (r != MAIL_NO_ERROR) {
255 res = r;
256 return res;
257 }
258 pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_TRY_APOP;
259
260 return MAIL_NO_ERROR;
261 }
262
263 res = r;
264 goto free;
265 }
266
267 storage->sto_session = session;
268
269 return MAIL_NO_ERROR;
270
271 free:
272 mailsession_free(session);
273 err:
274 return res;
275}
276
277static int pop3_mailstorage_get_folder_session(struct mailstorage * storage,
278 char * pathname, mailsession ** result)
279{
280 * result = storage->sto_session;
281
282 return MAIL_NO_ERROR;
283}
284
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 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3STORAGE_H
37
38#define POP3STORAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/pop3driver_types.h>
45#include <libetpan/pop3driver.h>
46#include <libetpan/pop3driver_cached.h>
47
48/*
49 pop3_mailstorage_init is the constructor for a POP3 storage
50
51 @param storage this is the storage to initialize.
52
53 @param servername this is the name of the POP3 server
54
55 @param port is the port to connect to, on the server.
56 you give 0 to use the default port.
57
58 @param command the command used to connect to the server instead of
59 allowing normal TCP connections to be used.
60
61 @param connection_type is the type of socket layer to use.
62 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
63 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
64 CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
65 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
66
67 @param auth_type is the authenticate mechanism to use.
68 The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP
69 or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented.
70
71 @param login is the login of the POP3 account.
72
73 @param password is the password of the POP3 account.
74
75 @param cached if this value is != 0, a persistant cache will be
76 stored on local system.
77
78 @param cache_directory is the location of the cache
79
80 @param flags_directory is the location of the flags
81*/
82
83int pop3_mailstorage_init(struct mailstorage * storage,
84 char * pop3_servername, uint16_t pop3_port,
85 char * pop3_command,
86 int pop3_connection_type, int pop3_auth_type,
87 char * pop3_login, char * pop3_password,
88 int pop3_cached, char * pop3_cache_directory,
89 char * pop3_flags_directory);
90
91#ifdef __cplusplus
92}
93#endif
94
95#endif
diff --git a/libetpan/src/driver/interface/maildriver.c b/libetpan/src/driver/interface/maildriver.c
new file mode 100644
index 0000000..5b6c4f2
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver.c
@@ -0,0 +1,383 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildriver.h"
37#include <ctype.h>
38#include <string.h>
39#include <stdlib.h>
40
41/* *********************************************************************** */
42/* mail session */
43
44mailsession * mailsession_new(mailsession_driver * sess_driver)
45{
46 mailsession * session;
47 int r;
48
49 session = malloc(sizeof(* session));
50
51 session->sess_data = NULL;
52
53 if (sess_driver->sess_initialize != NULL) {
54 r = sess_driver->sess_initialize(session);
55 if (r != MAIL_NO_ERROR)
56 goto free;
57 }
58
59 session->sess_driver = sess_driver;
60
61 return session;
62
63 free:
64 free(session);
65 return NULL;
66}
67
68void mailsession_free(mailsession * session)
69{
70 if (session->sess_driver->sess_uninitialize != NULL)
71 session->sess_driver->sess_uninitialize(session);
72 free(session);
73}
74
75int mailsession_parameters(mailsession * session,
76 int id, void * value)
77{
78 if (session->sess_driver->sess_parameters == NULL)
79 return MAIL_ERROR_NOT_IMPLEMENTED;
80
81 return session->sess_driver->sess_parameters(session, id, value);
82}
83
84int mailsession_connect_stream(mailsession * session, mailstream * s)
85{
86 if (session->sess_driver->sess_connect_stream == NULL)
87 return MAIL_ERROR_NOT_IMPLEMENTED;
88
89 return session->sess_driver->sess_connect_stream(session, s);
90}
91
92int mailsession_connect_path(mailsession * session, char * path)
93{
94 if (session->sess_driver->sess_connect_path == NULL)
95 return MAIL_ERROR_NOT_IMPLEMENTED;
96
97 return session->sess_driver->sess_connect_path(session, path);
98}
99
100int mailsession_starttls(mailsession * session)
101{
102 if (session->sess_driver->sess_starttls == NULL)
103 return MAIL_ERROR_NOT_IMPLEMENTED;
104
105 return session->sess_driver->sess_starttls(session);
106}
107
108int mailsession_login(mailsession * session,
109 char * userid, char * password)
110{
111 if (session->sess_driver->sess_login == NULL)
112 return MAIL_ERROR_NOT_IMPLEMENTED;
113
114 return session->sess_driver->sess_login(session, userid, password);
115}
116
117int mailsession_logout(mailsession * session)
118{
119 if (session->sess_driver->sess_logout == NULL)
120 return MAIL_ERROR_NOT_IMPLEMENTED;
121
122 return session->sess_driver->sess_logout(session);
123}
124
125int mailsession_noop(mailsession * session)
126{
127 if (session->sess_driver->sess_noop == NULL)
128 return MAIL_ERROR_NOT_IMPLEMENTED;
129
130 return session->sess_driver->sess_noop(session);
131}
132
133/* folders operations */
134
135int mailsession_build_folder_name(mailsession * session, char * mb,
136 char * name, char ** result)
137{
138 if (session->sess_driver->sess_build_folder_name == NULL)
139 return MAIL_ERROR_NOT_IMPLEMENTED;
140
141 return session->sess_driver->sess_build_folder_name(session,
142 mb, name, result);
143}
144
145int mailsession_create_folder(mailsession * session, char * mb)
146{
147 if (session->sess_driver->sess_create_folder == NULL)
148 return MAIL_ERROR_NOT_IMPLEMENTED;
149
150 return session->sess_driver->sess_create_folder(session, mb);
151}
152
153int mailsession_delete_folder(mailsession * session, char * mb)
154{
155 if (session->sess_driver->sess_delete_folder == NULL)
156 return MAIL_ERROR_NOT_IMPLEMENTED;
157
158 return session->sess_driver->sess_delete_folder(session, mb);
159}
160
161int mailsession_rename_folder(mailsession * session,
162 char * mb, char * new_name)
163{
164 if (session->sess_driver->sess_rename_folder == NULL)
165 return MAIL_ERROR_NOT_IMPLEMENTED;
166
167 return session->sess_driver->sess_rename_folder(session, mb, new_name);
168}
169
170int mailsession_check_folder(mailsession * session)
171{
172 if (session->sess_driver->sess_check_folder == NULL)
173 return MAIL_ERROR_NOT_IMPLEMENTED;
174
175 return session->sess_driver->sess_check_folder(session);
176}
177
178int mailsession_examine_folder(mailsession * session, char * mb)
179{
180 if (session->sess_driver->sess_examine_folder == NULL)
181 return MAIL_ERROR_NOT_IMPLEMENTED;
182
183 return session->sess_driver->sess_examine_folder(session, mb);
184}
185
186int mailsession_select_folder(mailsession * session, char * mb)
187{
188 if (session->sess_driver->sess_select_folder == NULL)
189 return MAIL_ERROR_NOT_IMPLEMENTED;
190
191 return session->sess_driver->sess_select_folder(session, mb);
192}
193
194int mailsession_expunge_folder(mailsession * session)
195{
196 if (session->sess_driver->sess_expunge_folder == NULL)
197 return MAIL_ERROR_NOT_IMPLEMENTED;
198
199 return session->sess_driver->sess_expunge_folder(session);
200}
201
202int mailsession_status_folder(mailsession * session, char * mb,
203 uint32_t * result_messages, uint32_t * result_recent,
204 uint32_t * result_unseen)
205{
206 if (session->sess_driver->sess_status_folder == NULL)
207 return MAIL_ERROR_NOT_IMPLEMENTED;
208
209 return session->sess_driver->sess_status_folder(session, mb,
210 result_messages, result_recent, result_unseen);
211}
212
213int mailsession_messages_number(mailsession * session, char * mb,
214 uint32_t * result)
215{
216 if (session->sess_driver->sess_messages_number == NULL)
217 return MAIL_ERROR_NOT_IMPLEMENTED;
218
219 return session->sess_driver->sess_messages_number(session, mb, result);
220}
221
222int mailsession_recent_number(mailsession * session, char * mb,
223 uint32_t * result)
224{
225 if (session->sess_driver->sess_recent_number == NULL)
226 return MAIL_ERROR_NOT_IMPLEMENTED;
227
228 return session->sess_driver->sess_recent_number(session, mb, result);
229}
230
231int mailsession_unseen_number(mailsession * session, char * mb,
232 uint32_t * result)
233{
234 if (session->sess_driver->sess_unseen_number == NULL)
235 return MAIL_ERROR_NOT_IMPLEMENTED;
236
237 return session->sess_driver->sess_recent_number(session, mb, result);
238}
239
240int mailsession_list_folders(mailsession * session, char * mb,
241 struct mail_list ** result)
242{
243 if (session->sess_driver->sess_list_folders == NULL)
244 return MAIL_ERROR_NOT_IMPLEMENTED;
245
246 return session->sess_driver->sess_list_folders(session, mb, result);
247}
248
249int mailsession_lsub_folders(mailsession * session, char * mb,
250 struct mail_list ** result)
251{
252 if (session->sess_driver->sess_lsub_folders == NULL)
253 return MAIL_ERROR_NOT_IMPLEMENTED;
254
255 return session->sess_driver->sess_lsub_folders(session, mb, result);
256}
257
258int mailsession_subscribe_folder(mailsession * session, char * mb)
259{
260 if (session->sess_driver->sess_subscribe_folder == NULL)
261 return MAIL_ERROR_NOT_IMPLEMENTED;
262
263 return session->sess_driver->sess_subscribe_folder(session, mb);
264}
265
266int mailsession_unsubscribe_folder(mailsession * session, char * mb)
267{
268 if (session->sess_driver->sess_unsubscribe_folder == NULL)
269 return MAIL_ERROR_NOT_IMPLEMENTED;
270
271 return session->sess_driver->sess_unsubscribe_folder(session, mb);
272}
273
274/* message */
275
276int mailsession_append_message(mailsession * session,
277 char * message, size_t size)
278{
279 if (session->sess_driver->sess_append_message == NULL)
280 return MAIL_ERROR_NOT_IMPLEMENTED;
281
282 return session->sess_driver->sess_append_message(session, message, size);
283}
284
285int mailsession_append_message_flags(mailsession * session,
286 char * message, size_t size, struct mail_flags * flags)
287{
288 if (session->sess_driver->sess_append_message_flags == NULL)
289 return MAIL_ERROR_NOT_IMPLEMENTED;
290
291 return session->sess_driver->sess_append_message_flags(session,
292 message, size, flags);
293}
294
295int mailsession_copy_message(mailsession * session,
296 uint32_t num, char * mb)
297{
298 if (session->sess_driver->sess_copy_message == NULL)
299 return MAIL_ERROR_NOT_IMPLEMENTED;
300
301 return session->sess_driver->sess_copy_message(session, num, mb);
302}
303
304int mailsession_move_message(mailsession * session,
305 uint32_t num, char * mb)
306{
307 if (session->sess_driver->sess_move_message == NULL) {
308 int r;
309
310 if ((session->sess_driver->sess_copy_message == NULL) &&
311 (session->sess_driver->sess_remove_message == NULL))
312 return MAIL_ERROR_NOT_IMPLEMENTED;
313
314 r = mailsession_copy_message(session, num, mb);
315 if (r != MAIL_NO_ERROR)
316 return r;
317
318 r = mailsession_remove_message(session, num);
319 if (r != MAIL_NO_ERROR)
320 return r;
321
322 return MAIL_NO_ERROR;
323 }
324
325 return session->sess_driver->sess_move_message(session, num, mb);
326}
327
328int mailsession_get_envelopes_list(mailsession * session,
329 struct mailmessage_list * env_list)
330{
331 if (session->sess_driver->sess_get_envelopes_list == NULL)
332 return MAIL_ERROR_NOT_IMPLEMENTED;
333
334 return session->sess_driver->sess_get_envelopes_list(session, env_list);
335}
336
337int mailsession_get_messages_list(mailsession * session,
338 struct mailmessage_list ** result)
339{
340 if (session->sess_driver->sess_get_messages_list == NULL)
341 return MAIL_ERROR_NOT_IMPLEMENTED;
342
343 return session->sess_driver->sess_get_messages_list(session, result);
344}
345
346int mailsession_remove_message(mailsession * session, uint32_t num)
347{
348 if (session->sess_driver->sess_remove_message == NULL)
349 return MAIL_ERROR_NOT_IMPLEMENTED;
350
351 return session->sess_driver->sess_remove_message(session, num);
352}
353
354#if 0
355int mailsession_search_messages(mailsession * session, char * charset,
356 struct mail_search_key * key,
357 struct mail_search_result ** result)
358{
359 if (session->sess_driver->sess_search_messages == NULL)
360 return MAIL_ERROR_NOT_IMPLEMENTED;
361
362 return session->sess_driver->sess_search_messages(session,
363 charset, key, result);
364}
365#endif
366
367int mailsession_get_message(mailsession * session,
368 uint32_t num, mailmessage ** result)
369{
370 if (session->sess_driver->sess_get_message == NULL)
371 return MAIL_ERROR_NOT_IMPLEMENTED;
372
373 return session->sess_driver->sess_get_message(session, num, result);
374}
375
376int mailsession_get_message_by_uid(mailsession * session,
377 const char * uid, mailmessage ** result)
378{
379 if (session->sess_driver->sess_get_message_by_uid == NULL)
380 return MAIL_ERROR_NOT_IMPLEMENTED;
381
382 return session->sess_driver->sess_get_message_by_uid(session, uid, result);
383}
diff --git a/libetpan/src/driver/interface/maildriver.h b/libetpan/src/driver/interface/maildriver.h
new file mode 100644
index 0000000..16e830b
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver.h
@@ -0,0 +1,546 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_H
37
38#define MAILDRIVER_H
39
40#include <libetpan/maildriver_types.h>
41#include <libetpan/maildriver_types_helper.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47/* mailsession */
48
49/*
50 mailsession_new creates a new session, using the given driver
51
52 @return the created session is returned
53*/
54
55mailsession * mailsession_new(mailsession_driver * sess_driver);
56
57/*
58 mailsession_free release the memory used by the session
59*/
60
61void mailsession_free(mailsession * session);
62
63/*
64 mailsession_parameters is used to make calls specific to the driver
65
66 @param id is the command to send to the driver,
67 usually, commands can be found in the header of the driver
68
69 @param value is the parameter of the specific call
70
71 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
72 on error
73*/
74
75int mailsession_parameters(mailsession * session,
76 int id, void * value);
77
78/*
79 There are drivers of two kinds : stream drivers (driver that connects
80 to servers through TCP or other means of connection) and file drivers
81 (driver that are based on filesystem)
82
83 The following function can only be used by stream drivers.
84 mailsession_connect_stream connects a stream to the session
85
86 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
87 on error
88*/
89
90int mailsession_connect_stream(mailsession * session, mailstream * s);
91
92/*
93 The following function can only be used by file drivers.
94 mailsession_connect_path selects the main path of the session
95
96 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
97 on error
98*/
99
100int mailsession_connect_path(mailsession * session, char * path);
101
102/*
103 NOTE: works only on stream drivers
104
105 mailsession_starttls switches the current connection to TLS (secure layer)
106
107 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
108 on error
109*/
110
111int mailsession_starttls(mailsession * session);
112
113/*
114 mailsession_login notifies the login and the password to authenticate
115 to the session
116
117 @param userid the given string is only needed at this function call
118 (it will be duplicated if necessary)
119 @param password the given string is only needed at this function call
120 (it will be duplicated if necessary)
121
122 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
123 on error
124*/
125
126int mailsession_login(mailsession * session,
127 char * userid, char * password);
128
129/*
130 NOTE: this function doesn't often work on filsystem drivers
131
132 mailsession_logout deconnects the session and closes the stream.
133
134 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
135 on error
136*/
137
138int mailsession_logout(mailsession * session);
139
140/*
141 mailsession_noop does no operation on the session, but it can be
142 used to poll for the status of the connection.
143
144 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
145 on error
146*/
147
148int mailsession_noop(mailsession * session);
149
150/*
151 NOTE: driver's specific should be used
152
153 mailsession_build_folder_name will return an allocated string with
154 that contains the complete path of the folder to create
155
156 @param session the sesion
157 @param mb is the parent mailbox
158 @param name is the name of the folder to create
159 @param result the complete path of the folder to create will be
160 stored in (* result), this name have to be freed with free()
161
162 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
163 on error
164*/
165
166int mailsession_build_folder_name(mailsession * session, char * mb,
167 char * name, char ** result);
168
169/*
170 NOTE: driver's specific should be used
171
172 mailsession_create_folder creates the folder that corresponds to the
173 given name
174
175 @param session the session
176 @param mb is the name of the mailbox
177
178 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
179 on error
180*/
181
182int mailsession_create_folder(mailsession * session, char * mb);
183
184
185/*
186 NOTE: driver's specific should be used
187
188 mailsession_delete_folder deletes the folder that corresponds to the
189 given name
190
191 @param session the session
192 @param mb is the name of the mailbox
193
194 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
195 on error
196*/
197
198int mailsession_delete_folder(mailsession * session, char * mb);
199
200
201/*
202 mailsession_rename_folder changes the name of the folder
203
204 @param session the session
205 @param mb is the name of the mailbox whose name has to be changed
206 @param new_name is the destination name (the parent
207 of the new folder folder can be other)
208
209 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
210 on error
211*/
212
213int mailsession_rename_folder(mailsession * session,
214 char * mb, char * new_name);
215
216/*
217 mailsession_check_folder makes a checkpoint of the session
218
219 @param session the session
220
221 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
222 on error
223*/
224
225int mailsession_check_folder(mailsession * session);
226
227
228/*
229 NOTE: this function is not implemented in most drivers
230
231 mailsession_examine_folder selects a mailbox as readonly
232
233 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
234 on error
235*/
236
237int mailsession_examine_folder(mailsession * session, char * mb);
238
239
240/*
241 mailsession_select_folder selects a mailbox
242
243 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
244 on error
245*/
246
247int mailsession_select_folder(mailsession * session, char * mb);
248
249
250/*
251 mailsession_expunge_folder deletes all messages marked \Deleted
252
253 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
254 on error
255*/
256
257int mailsession_expunge_folder(mailsession * session);
258
259
260/*
261 mailsession_status_folder queries the status of the folder
262 (number of messages, number of recent messages, number of unseen messages)
263
264 @param session the session
265 @param mb mailbox to query
266 @param result_messages the number of messages is stored
267 in (* result_messages)
268 @param result_recent the number of messages is stored
269 in (* result_recent)
270 @param result_unseen the number of messages is stored
271 in (* result_unseen)
272
273 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
274 on error
275*/
276
277int mailsession_status_folder(mailsession * session, char * mb,
278 uint32_t * result_messages, uint32_t * result_recent,
279 uint32_t * result_unseen);
280
281
282/*
283 mailsession_messages_number queries the number of messages in the folder
284
285 @param session the session
286 @param mb mailbox to query
287 @param result the number of messages is stored in (* result)
288
289 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
290 on error
291*/
292
293int mailsession_messages_number(mailsession * session, char * mb,
294 uint32_t * result);
295
296/*
297 mailsession_recent_number queries the number of recent messages in the folder
298
299 @param session the session
300 @param mb mailbox to query
301 @param result the number of recent messages is stored in (* result)
302
303 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
304 on error
305*/
306
307int mailsession_recent_number(mailsession * session,
308 char * mb, uint32_t * result);
309
310/*
311 mailsession_unseen_number queries the number of unseen messages in the folder
312
313 @param session the session
314 @param mb mailbox to query
315 @param result the number of unseen messages is stored in (* result)
316
317 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
318 on error
319*/
320
321int mailsession_unseen_number(mailsession * session, char * mb,
322 uint32_t * result);
323
324/*
325 NOTE: driver's specific should be used
326
327 mailsession_list_folders returns the list of all sub-mailboxes
328 of the given mailbox
329
330 @param session the session
331 @param mb the mailbox
332 @param result list of mailboxes if stored in (* result),
333 this structure have to be freed with mail_list_free()
334
335 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
336 on error
337*/
338
339int mailsession_list_folders(mailsession * session, char * mb,
340 struct mail_list ** result);
341
342/*
343 NOTE: driver's specific should be used
344
345 mailsession_lsub_folders returns the list of subscribed
346 sub-mailboxes of the given mailbox
347
348 @param session the session
349 @param mb the mailbox
350 @param result list of mailboxes if stored in (* result),
351 this structure have to be freed with mail_list_free()
352
353 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
354 on error
355*/
356
357int mailsession_lsub_folders(mailsession * session, char * mb,
358 struct mail_list ** result);
359
360/*
361 NOTE: driver's specific should be used
362
363 mailsession_subscribe_folder subscribes to the given mailbox
364
365 @param session the session
366 @param mb the mailbox
367
368 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
369 on error
370*/
371
372int mailsession_subscribe_folder(mailsession * session, char * mb);
373
374/*
375 NOTE: driver's specific should be used
376
377 mailsession_unsubscribe_folder unsubscribes to the given mailbox
378
379 @param session the session
380 @param mb the mailbox
381
382 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
383 on error
384*/
385
386int mailsession_unsubscribe_folder(mailsession * session, char * mb);
387
388/*
389 mailsession_append_message adds a RFC 2822 message to the current
390 given mailbox
391
392 @param session the session
393 @param message is a string that contains the RFC 2822 message
394 @param size this is the size of the message
395
396 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
397 on error
398*/
399
400int mailsession_append_message(mailsession * session,
401 char * message, size_t size);
402
403int mailsession_append_message_flags(mailsession * session,
404 char * message, size_t size, struct mail_flags * flags);
405
406/*
407 NOTE: some drivers does not implement this
408
409 mailsession_copy_message copies a message whose number is given to
410 a given mailbox. The mailbox must be accessible from the same session.
411
412 @param session the session
413 @param num the message number
414 @param mb the destination mailbox
415
416 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
417 on error
418*/
419
420int mailsession_copy_message(mailsession * session,
421 uint32_t num, char * mb);
422
423/*
424 NOTE: some drivers does not implement this
425
426 mailsession_move_message copies a message whose number is given to
427 a given mailbox. The mailbox must be accessible from the same session.
428
429 @param session the session
430 @param num the message number
431 @param mb the destination mailbox
432
433 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
434 on error
435*/
436
437int mailsession_move_message(mailsession * session,
438 uint32_t num, char * mb);
439
440/*
441 mailsession_get_messages_list returns the list of message numbers
442 of the current mailbox.
443
444 @param session the session
445 @param result the list of message numbers will be stored in (* result),
446 this structure have to be freed with mailmessage_list_free()
447
448 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
449 on error
450*/
451
452int mailsession_get_messages_list(mailsession * session,
453 struct mailmessage_list ** result);
454
455/*
456 mailsession_get_envelopes_list fills the parsed fields in the
457 mailmessage structures of the mailmessage_list.
458
459 @param session the session
460 @param result this is the list of mailmessage structures
461
462 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
463 on error
464*/
465
466int mailsession_get_envelopes_list(mailsession * session,
467 struct mailmessage_list * result);
468
469/*
470 NOTE: some drivers does not implement this
471
472 mailsession_remove_message removes the given message from the mailbox.
473 The message is permanently deleted.
474
475 @param session the session
476 @param num is the message number
477
478 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
479 on error
480*/
481
482int mailsession_remove_message(mailsession * session, uint32_t num);
483
484
485/*
486 NOTE: this function is not implemented in most drivers
487
488 mailsession_search_message returns a list of message numbers that
489 corresponds to the given criteria.
490
491 @param session the session
492 @param charset is the charset to use (it can be NULL)
493 @param key is the list of criteria
494 @param result the search result is stored in (* result),
495 this structure have to be freed with mail_search_result_free()
496
497 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
498 on error
499*/
500
501#if 0
502int mailsession_search_messages(mailsession * session, char * charset,
503 struct mail_search_key * key,
504 struct mail_search_result ** result);
505#endif
506
507/*
508 mailsession_get_message returns a mailmessage structure that corresponds
509 to the given message number.
510 * WARNING * mailsession_get_message_by_uid() should be used instead.
511
512 @param session the session
513 @param num the message number
514 @param result the allocated mailmessage structure will be stored
515 in (* result), this structure have to be freed with mailmessage_free()
516
517 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
518 on error
519*/
520
521int mailsession_get_message(mailsession * session,
522 uint32_t num, mailmessage ** result);
523
524/*
525 mailsession_get_message_by_uid returns a mailmessage structure
526 that corresponds to the given message unique identifier.
527 This is currently implemented only for cached drivers.
528 * WARNING * That will deprecates the use of mailsession_get_message()
529
530 @param session the session
531 @param uid the message unique identifier
532 @param result the allocated mailmessage structure will be stored
533 in (* result), this structure have to be freed with mailmessage_free()
534
535 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
536 on error
537*/
538
539int mailsession_get_message_by_uid(mailsession * session,
540 const char * uid, mailmessage ** result);
541
542#ifdef __cplusplus
543}
544#endif
545
546#endif
diff --git a/libetpan/src/driver/interface/maildriver_errors.h b/libetpan/src/driver/interface/maildriver_errors.h
new file mode 100644
index 0000000..99ec25c
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_errors.h
@@ -0,0 +1,102 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_ERRORS_H
37
38#define MAILDRIVER_ERRORS_H
39
40enum {
41 MAIL_NO_ERROR = 0,
42 MAIL_NO_ERROR_AUTHENTICATED,
43 MAIL_NO_ERROR_NON_AUTHENTICATED,
44 MAIL_ERROR_NOT_IMPLEMENTED,
45 MAIL_ERROR_UNKNOWN,
46 MAIL_ERROR_CONNECT,
47 MAIL_ERROR_BAD_STATE,
48 MAIL_ERROR_FILE,
49 MAIL_ERROR_STREAM,
50 MAIL_ERROR_LOGIN,
51 MAIL_ERROR_CREATE, /* 10 */
52 MAIL_ERROR_DELETE,
53 MAIL_ERROR_LOGOUT,
54 MAIL_ERROR_NOOP,
55 MAIL_ERROR_RENAME,
56 MAIL_ERROR_CHECK,
57 MAIL_ERROR_EXAMINE,
58 MAIL_ERROR_SELECT,
59 MAIL_ERROR_MEMORY,
60 MAIL_ERROR_STATUS,
61 MAIL_ERROR_SUBSCRIBE, /* 20 */
62 MAIL_ERROR_UNSUBSCRIBE,
63 MAIL_ERROR_LIST,
64 MAIL_ERROR_LSUB,
65 MAIL_ERROR_APPEND,
66 MAIL_ERROR_COPY,
67 MAIL_ERROR_FETCH,
68 MAIL_ERROR_STORE,
69 MAIL_ERROR_SEARCH,
70 MAIL_ERROR_DISKSPACE,
71 MAIL_ERROR_MSG_NOT_FOUND, /* 30 */
72 MAIL_ERROR_PARSE,
73 MAIL_ERROR_INVAL,
74 MAIL_ERROR_PART_NOT_FOUND,
75 MAIL_ERROR_REMOVE,
76 MAIL_ERROR_FOLDER_NOT_FOUND,
77 MAIL_ERROR_MOVE,
78 MAIL_ERROR_STARTTLS,
79 MAIL_ERROR_CACHE_MISS,
80 MAIL_ERROR_NO_TLS,
81 MAIL_ERROR_EXPUNGE, /* 40 */
82 /* misc errors */
83 MAIL_ERROR_MISC,
84 MAIL_ERROR_PROTOCOL,
85 MAIL_ERROR_CAPABILITY,
86 MAIL_ERROR_CLOSE,
87 MAIL_ERROR_FATAL,
88 MAIL_ERROR_READONLY,
89 MAIL_ERROR_NO_APOP,
90 MAIL_ERROR_COMMAND_NOT_SUPPORTED,
91 MAIL_ERROR_NO_PERMISSION,
92 MAIL_ERROR_PROGRAM_ERROR, /* 50 */
93 MAIL_ERROR_SUBJECT_NOT_FOUND,
94 MAIL_ERROR_CHAR_ENCODING_FAILED,
95 MAIL_ERROR_SEND,
96 MAIL_ERROR_COMMAND,
97 MAIL_ERROR_SYSTEM,
98 MAIL_ERROR_UNABLE,
99 MAIL_ERROR_FOLDER,
100};
101
102#endif
diff --git a/libetpan/src/driver/interface/maildriver_tools.c b/libetpan/src/driver/interface/maildriver_tools.c
new file mode 100644
index 0000000..4501b23
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_tools.c
@@ -0,0 +1,841 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildriver_tools.h"
37
38#include "libetpan-config.h"
39
40#include <stdlib.h>
41#include <ctype.h>
42#include <string.h>
43#include <dirent.h>
44#include <unistd.h>
45
46#include "maildriver.h"
47#include "mailmessage.h"
48#include "mailstream.h"
49#include "mailmime.h"
50#include "mail_cache_db.h"
51
52/* ********************************************************************* */
53/* tools */
54
55
56int
57maildriver_generic_get_envelopes_list(mailsession * session,
58 struct mailmessage_list * env_list)
59{
60 int r;
61 unsigned i;
62#if 0
63 uint32_t j;
64 uint32_t last_msg;
65
66 last_msg = 0;
67#endif
68
69#if 0
70 j = 0;
71 i = 0;
72 while (i < env_list->tab->len) {
73 mailmessage * msg;
74 uint32_t index;
75
76 msg = carray_get(env_list->tab, i);
77
78 index = msg->index;
79
80 if (msg->fields == NULL) {
81 struct mailimf_fields * fields;
82
83 r = mailmessage_fetch_envelope(msg, &fields);
84 if (r != MAIL_NO_ERROR) {
85 /* do nothing */
86 }
87 else {
88 msg->fields = fields;
89
90 carray_set(env_list->tab, j, msg);
91
92 j ++;
93 last_msg = i + 1;
94 }
95 mailmessage_flush(msg);
96 }
97 else {
98 j ++;
99 last_msg = i + 1;
100 }
101
102 i ++;
103 }
104
105 for(i = last_msg ; i < env_list->tab->len ; i ++) {
106 mailmessage_free(carray_get(env_list->tab, i));
107 carray_set(env_list->tab, i, NULL);
108 }
109
110 r = carray_set_size(env_list->tab, j);
111 if (r < 0)
112 return MAIL_ERROR_MEMORY;
113#endif
114
115 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
116 mailmessage * msg;
117
118 msg = carray_get(env_list->msg_tab, i);
119
120 if (msg->msg_fields == NULL) {
121 struct mailimf_fields * fields;
122
123 r = mailmessage_fetch_envelope(msg, &fields);
124 if (r != MAIL_NO_ERROR) {
125 /* do nothing */
126 }
127 else {
128 msg->msg_fields = fields;
129 }
130 mailmessage_flush(msg);
131 }
132 }
133
134 return MAIL_NO_ERROR;
135}
136
137
138#if 0
139static int is_search_header_only(struct mail_search_key * key)
140{
141 clistiter * cur;
142 int result;
143
144 switch (key->type) {
145 case MAIL_SEARCH_KEY_ANSWERED:
146 case MAIL_SEARCH_KEY_BCC:
147 case MAIL_SEARCH_KEY_BEFORE:
148 case MAIL_SEARCH_KEY_CC:
149 case MAIL_SEARCH_KEY_DELETED:
150 case MAIL_SEARCH_KEY_FLAGGED:
151 case MAIL_SEARCH_KEY_FROM:
152 case MAIL_SEARCH_KEY_NEW:
153 case MAIL_SEARCH_KEY_OLD:
154 case MAIL_SEARCH_KEY_ON:
155 case MAIL_SEARCH_KEY_RECENT:
156 case MAIL_SEARCH_KEY_SEEN:
157 case MAIL_SEARCH_KEY_SINCE:
158 case MAIL_SEARCH_KEY_SUBJECT:
159 case MAIL_SEARCH_KEY_TO:
160 case MAIL_SEARCH_KEY_UNANSWERED:
161 case MAIL_SEARCH_KEY_UNDELETED:
162 case MAIL_SEARCH_KEY_UNFLAGGED:
163 case MAIL_SEARCH_KEY_UNSEEN:
164 case MAIL_SEARCH_KEY_HEADER:
165 case MAIL_SEARCH_KEY_LARGER:
166 case MAIL_SEARCH_KEY_NOT:
167 case MAIL_SEARCH_KEY_SMALLER:
168 case MAIL_SEARCH_KEY_ALL:
169 return TRUE;
170
171 case MAIL_SEARCH_KEY_BODY:
172 case MAIL_SEARCH_KEY_TEXT:
173 return FALSE;
174
175 case MAIL_SEARCH_KEY_OR:
176 return (is_search_header_only(key->or1) &&
177 is_search_header_only(key->or2));
178
179 case MAIL_SEARCH_KEY_MULTIPLE:
180 result = TRUE;
181 for (cur = clist_begin(key->multiple) ; cur != NULL ;
182 cur = clist_next(cur))
183 result = result && is_search_header_only(clist_content(cur));
184 return result;
185
186 default:
187 return TRUE;
188 }
189}
190
191static int match_header(struct mailimf_fields * fields,
192 char * name, char * value)
193{
194 clistiter * cur;
195
196 for(cur = clist_begin(fields->list) ; cur != NULL ;
197 cur = clist_content(cur)) {
198 struct mailimf_field * field;
199 struct mailimf_optional_field * opt_field;
200
201 field = clist_content(cur);
202 opt_field = field->optional_field;
203 if ((char) toupper((unsigned char) opt_field->name[0]) ==
204 (char) toupper((unsigned char) name[0])) {
205 if (strcasecmp(opt_field->name, name) == 0)
206 if (strstr(opt_field->value, value) != NULL)
207 return TRUE;
208 }
209 }
210 return FALSE;
211}
212
213static int comp_date(struct mailimf_fields * fields,
214 struct mailimf_date_time * ref_date)
215{
216 clistiter * cur;
217 struct mailimf_date_time * date;
218 int r;
219
220 date = NULL;
221 for(cur = clist_begin(fields->list) ; cur != NULL ;
222 cur = clist_content(cur)) {
223 struct mailimf_field * field;
224 struct mailimf_optional_field * opt_field;
225
226 field = clist_content(cur);
227 opt_field = field->optional_field;
228 if ((char) toupper((unsigned char) opt_field->name[0]) == 'D') {
229 if (strcasecmp(opt_field->name, "Date") == 0) {
230 size_t cur_token;
231
232 cur_token = 0;
233 r = mailimf_date_time_parse(opt_field->value, strlen(opt_field->value),
234 &cur_token, &date);
235 if (r == MAILIMF_NO_ERROR)
236 break;
237 else if (r == MAILIMF_ERROR_PARSE) {
238 /* do nothing */
239 }
240 else
241 break;
242 }
243 }
244 }
245
246 if (date == NULL)
247 return 0;
248
249 return mailimf_date_time_comp(date, ref_date);
250}
251
252static int match_messages(char * message,
253 size_t size,
254 struct mailimf_fields * fields,
255 int32_t flags,
256 char * charset,
257 struct mail_search_key * key)
258{
259 clistiter * cur;
260 size_t length;
261 size_t cur_token;
262 int r;
263
264 switch (key->type) {
265
266 /* flags */
267 case MAIL_SEARCH_KEY_ANSWERED:
268 return ((flags & MAIL_FLAG_ANSWERED) != 0);
269
270 case MAIL_SEARCH_KEY_FLAGGED:
271 return ((flags & MAIL_FLAG_FLAGGED) != 0);
272
273 case MAIL_SEARCH_KEY_DELETED:
274 return ((flags & MAIL_FLAG_DELETED) != 0);
275
276 case MAIL_SEARCH_KEY_RECENT:
277 return ((flags & MAIL_FLAG_NEW) != 0) &&
278 ((flags & MAIL_FLAG_SEEN) == 0);
279
280 case MAIL_SEARCH_KEY_SEEN:
281 return ((flags & MAIL_FLAG_SEEN) != 0);
282
283 case MAIL_SEARCH_KEY_NEW:
284 return ((flags & MAIL_FLAG_NEW) != 0);
285
286 case MAIL_SEARCH_KEY_OLD:
287 return ((flags & MAIL_FLAG_NEW) == 0);
288
289 case MAIL_SEARCH_KEY_UNANSWERED:
290 return ((flags & MAIL_FLAG_ANSWERED) == 0);
291
292 case MAIL_SEARCH_KEY_UNDELETED:
293 return ((flags & MAIL_FLAG_DELETED) == 0);
294
295 case MAIL_SEARCH_KEY_UNFLAGGED:
296 return ((flags & MAIL_FLAG_FLAGGED) == 0);
297
298 case MAIL_SEARCH_KEY_UNSEEN:
299 return ((flags & MAIL_FLAG_SEEN) == 0);
300
301 /* headers */
302 case MAIL_SEARCH_KEY_BCC:
303 return match_header(fields, "Bcc", key->bcc);
304
305 case MAIL_SEARCH_KEY_CC:
306 return match_header(fields, "Cc", key->cc);
307
308 case MAIL_SEARCH_KEY_FROM:
309 return match_header(fields, "From", key->from);
310
311 case MAIL_SEARCH_KEY_SUBJECT:
312 return match_header(fields, "Subject", key->subject);
313
314 case MAIL_SEARCH_KEY_TO:
315 return match_header(fields, "To", key->to);
316
317 case MAIL_SEARCH_KEY_HEADER:
318 return match_header(fields, key->header_name, key->header_value);
319
320 /* date */
321 case MAIL_SEARCH_KEY_BEFORE:
322 return (comp_date(fields, key->before) <= 0);
323
324 case MAIL_SEARCH_KEY_ON:
325 return (comp_date(fields, key->before) == 0);
326
327 case MAIL_SEARCH_KEY_SINCE:
328 return (comp_date(fields, key->before) >= 0);
329
330 /* boolean */
331 case MAIL_SEARCH_KEY_NOT:
332 return (!match_messages(message, size, fields, flags, charset, key->not));
333 case MAIL_SEARCH_KEY_OR:
334 return (match_messages(message, size, fields, flags, charset, key->or1) ||
335 match_messages(message, size, fields, flags, charset, key->or2));
336
337 case MAIL_SEARCH_KEY_MULTIPLE:
338 for(cur = clist_begin(key->multiple) ; cur != NULL ;
339 cur = clist_next(cur)) {
340 if (!match_messages(message, size, fields, flags, charset,
341 clist_content(cur)))
342 return FALSE;
343 }
344
345 return TRUE;
346
347 /* size */
348 case MAIL_SEARCH_KEY_SMALLER:
349 return (size <= key->smaller);
350
351 case MAIL_SEARCH_KEY_LARGER:
352 return (size >= key->larger);
353
354 case MAIL_SEARCH_KEY_BODY:
355 length = strlen(message);
356
357 cur_token = 0;
358 while (1) {
359 r = mailimf_ignore_field_parse(message, length, &cur_token);
360 if (r == MAILIMF_NO_ERROR) {
361 /* do nothing */
362 }
363 else
364 break;
365 }
366
367 return (strstr(message + cur_token, key->body) != NULL);
368
369 case MAIL_SEARCH_KEY_TEXT:
370 return (strstr(message, key->body) != NULL);
371
372 case MAIL_SEARCH_KEY_ALL:
373 default:
374 return TRUE;
375 }
376}
377
378int maildriver_generic_search_messages(mailsession * session, char * charset,
379 struct mail_search_key * key,
380 struct mail_search_result ** result)
381{
382 int header;
383 clist * list;
384 struct mail_search_result * search_result;
385 int r;
386 struct mailmessage_list * env_list;
387 int res;
388 unsigned int i;
389
390 header = is_search_header_only(key);
391
392 r = mailsession_get_messages_list(session, &env_list);
393 if (r != MAIL_NO_ERROR)
394 return r;
395
396 list = NULL;
397 for(i = 0 ; i < carray_count(env_list->tab) ; i ++) {
398 char * message;
399 size_t length;
400 struct mail_info * info;
401 uint32_t flags;
402 struct mailimf_fields * fields;
403 size_t cur_token;
404
405 info = carray_get(env_list->tab, i);
406
407 if (!header) {
408 r = mailsession_fetch_message(session, info->index, &message, &length);
409 if (r != MAIL_NO_ERROR) {
410 res = r;
411 goto free_list;
412 }
413
414 cur_token = 0;
415 r = mailimf_optional_fields_parse(message, length,
416 &cur_token, &fields);
417 if (r != MAILIMF_NO_ERROR) {
418 res = MAIL_ERROR_PARSE;
419 goto free_list;
420 }
421 }
422 else {
423 char * msg_header;
424 int r;
425 size_t cur_token;
426 size_t header_len;
427
428 r = mailsession_fetch_message_header(session, info->index, &msg_header,
429 &header_len);
430 if (r != MAIL_NO_ERROR) {
431 res = r;
432 goto free_list;
433 }
434
435 message = NULL;
436 cur_token = 0;
437 r = mailimf_optional_fields_parse(msg_header, header_len,
438 &cur_token, &fields);
439 if (r != MAILIMF_NO_ERROR) {
440 res = MAIL_ERROR_PARSE;
441 goto free_list;
442 }
443
444 mailsession_fetch_result_free(session, msg_header);
445 }
446
447 r = mailsession_get_message_flags(session, info->index, &flags);
448 if (r != MAIL_NO_ERROR) {
449 res = r;
450 goto free_list;
451 }
452
453 if (match_messages(message, info->size, fields, flags,
454 charset, key)) {
455 uint32_t * pnum;
456
457 pnum = malloc(sizeof(* pnum));
458 if (pnum == NULL) {
459 if (message != NULL)
460 mailsession_fetch_result_free(session, message);
461 res = MAIL_ERROR_MEMORY;
462 goto free_list;
463 }
464
465 * pnum = info->index;
466
467 r = clist_append(list, pnum);
468 if (r < 0) {
469 free(pnum);
470 if (message != NULL)
471 mailsession_fetch_result_free(session, message);
472 res = MAIL_ERROR_MEMORY;
473 goto free_list;
474 }
475 }
476
477 if (message != NULL)
478 mailsession_fetch_result_free(session, message);
479 }
480
481 search_result = mail_search_result_new(list);
482 if (search_result == NULL) {
483 res = MAIL_ERROR_MEMORY;
484 goto free_list;
485 }
486
487 * result = search_result;
488
489 return MAIL_NO_ERROR;
490
491 free_list:
492 clist_foreach(list, (clist_func) free, NULL);
493 clist_free(list);
494 mailmessage_list_free(env_list);
495 return res;
496}
497#endif
498
499#if 0
500int maildriver_generic_search_messages(mailsession * session, char * charset,
501 struct mail_search_key * key,
502 struct mail_search_result ** result)
503{
504 return MAIL_ERROR_NOT_IMPLEMENTED;
505}
506#endif
507
508int
509maildriver_env_list_to_msg_list(struct mailmessage_list * env_list,
510 clist ** result)
511{
512 clist * msg_list;
513 int r;
514 int res;
515 unsigned int i;
516
517 msg_list = clist_new();
518 if (msg_list == NULL) {
519 res = MAIL_ERROR_MEMORY;
520 goto err;
521 }
522
523 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
524 mailmessage * msg;
525
526 msg = carray_get(env_list->msg_tab, i);
527
528 if (msg->msg_fields == NULL) {
529 uint32_t * pindex;
530
531 pindex = malloc(sizeof(* pindex));
532 if (pindex == NULL) {
533 res = MAIL_ERROR_MEMORY;
534 goto free_msg_list;
535 }
536
537 * pindex = msg->msg_index;
538
539 r = clist_append(msg_list, pindex);
540 if (r < 0) {
541 free(pindex);
542 res = MAIL_ERROR_MEMORY;
543 goto free_msg_list;
544 }
545
546 }
547 }
548
549 * result = msg_list;
550
551 return MAIL_NO_ERROR;
552
553 free_msg_list:
554 clist_foreach(msg_list, (clist_func) free, NULL);
555 clist_free(msg_list);
556 err:
557 return res;
558}
559
560
561int
562maildriver_env_list_to_msg_list_no_flags(struct mailmessage_list * env_list,
563 clist ** result)
564{
565 clist * msg_list;
566 int r;
567 int res;
568 unsigned int i;
569
570 msg_list = clist_new();
571 if (msg_list == NULL) {
572 res = MAIL_ERROR_MEMORY;
573 goto err;
574 }
575
576 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
577 mailmessage * msg;
578
579 msg = carray_get(env_list->msg_tab, i);
580
581 if (msg->msg_flags == NULL) {
582 uint32_t * pindex;
583
584 pindex = malloc(sizeof(* pindex));
585 if (pindex == NULL) {
586 res = MAIL_ERROR_MEMORY;
587 goto free_msg_list;
588 }
589
590 * pindex = msg->msg_index;
591
592 r = clist_append(msg_list, pindex);
593 if (r < 0) {
594 free(pindex);
595 res = MAIL_ERROR_MEMORY;
596 goto free_msg_list;
597 }
598
599 }
600 }
601
602 * result = msg_list;
603
604 return MAIL_NO_ERROR;
605
606 free_msg_list:
607 clist_foreach(msg_list, (clist_func) free, NULL);
608 clist_free(msg_list);
609 err:
610 return res;
611}
612
613
614
615int maildriver_imf_error_to_mail_error(int error)
616{
617 switch (error) {
618 case MAILIMF_NO_ERROR:
619 return MAIL_NO_ERROR;
620
621 case MAILIMF_ERROR_PARSE:
622 return MAIL_ERROR_PARSE;
623
624 case MAILIMF_ERROR_MEMORY:
625 return MAIL_ERROR_MEMORY;
626
627 case MAILIMF_ERROR_INVAL:
628 return MAIL_ERROR_INVAL;
629
630 case MAILIMF_ERROR_FILE:
631 return MAIL_ERROR_FILE;
632
633 default:
634 return MAIL_ERROR_INVAL;
635 }
636}
637
638char * maildriver_quote_mailbox(char * mb)
639{
640 MMAPString * gstr;
641 char * str;
642
643 gstr = mmap_string_new("");
644 if (gstr == NULL)
645 return NULL;
646
647 while (* mb != 0) {
648 char hex[3];
649
650 if (((* mb >= 'a') && (* mb <= 'z')) ||
651 ((* mb >= 'A') && (* mb <= 'Z')) ||
652 ((* mb >= '0') && (* mb <= '9')))
653 mmap_string_append_c(gstr, * mb);
654 else {
655 if (mmap_string_append_c(gstr, '%') == NULL)
656 goto free;
657 snprintf(hex, 3, "%02x", (unsigned char) (* mb));
658 if (mmap_string_append(gstr, hex) == NULL)
659 goto free;
660 }
661 mb ++;
662 }
663
664 str = strdup(gstr->str);
665 if (str == NULL)
666 goto free;
667
668 mmap_string_free(gstr);
669
670 return str;
671
672 free:
673 mmap_string_free(gstr);
674 return NULL;
675}
676
677
678
679int maildriver_cache_clean_up(struct mail_cache_db * cache_db_env,
680 struct mail_cache_db * cache_db_flags,
681 struct mailmessage_list * env_list)
682{
683 chash * hash_exist;
684 int res;
685 int r;
686 char keyname[PATH_MAX];
687 unsigned int i;
688
689 /* flush cache */
690
691 hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL);
692 if (hash_exist == NULL) {
693 res = MAIL_ERROR_MEMORY;
694 goto err;
695 }
696
697 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
698 mailmessage * msg;
699 chashdatum key;
700 chashdatum value;
701
702 msg = carray_get(env_list->msg_tab, i);
703
704 value.data = NULL;
705 value.len = 0;
706
707 if (cache_db_env != NULL) {
708 snprintf(keyname, PATH_MAX, "%s-envelope", msg->msg_uid);
709
710 key.data = keyname;
711 key.len = strlen(keyname);
712 r = chash_set(hash_exist, &key, &value, NULL);
713 if (r < 0) {
714 res = MAIL_ERROR_MEMORY;
715 goto free;
716 }
717 }
718
719 if (cache_db_flags != NULL) {
720 snprintf(keyname, PATH_MAX, "%s-flags", msg->msg_uid);
721
722 key.data = keyname;
723 key.len = strlen(keyname);
724 r = chash_set(hash_exist, &key, &value, NULL);
725 if (r < 0) {
726 res = MAIL_ERROR_MEMORY;
727 goto free;
728 }
729 }
730 }
731
732 /* clean up */
733 if (cache_db_env != NULL)
734 mail_cache_db_clean_up(cache_db_env, hash_exist);
735 if (cache_db_flags != NULL)
736 mail_cache_db_clean_up(cache_db_flags, hash_exist);
737
738 chash_free(hash_exist);
739
740 return MAIL_NO_ERROR;
741
742 free:
743 chash_free(hash_exist);
744 err:
745 return res;
746}
747
748
749/*
750 maildriver_message_cache_clean_up()
751
752 remove files in cache_dir that does not correspond to a message.
753
754 get_uid_from_filename() modifies the given filename so that it
755 is a uid when returning from the function. If get_uid_from_filename()
756 clears the content of file (set to empty string), this means that
757 this file should not be deleted.
758*/
759
760int maildriver_message_cache_clean_up(char * cache_dir,
761 struct mailmessage_list * env_list,
762 void (* get_uid_from_filename)(char *))
763{
764 chash * hash_exist;
765 DIR * d;
766 char cached_filename[PATH_MAX];
767 struct dirent * ent;
768 char keyname[PATH_MAX];
769 unsigned int i;
770 int res;
771 int r;
772
773 /* remove files */
774
775 hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL);
776 if (hash_exist == NULL) {
777 res = MAIL_ERROR_MEMORY;
778 goto err;
779 }
780
781 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
782 mailmessage * msg;
783 chashdatum key;
784 chashdatum value;
785
786 msg = carray_get(env_list->msg_tab, i);
787
788 key.data = msg->msg_uid;
789 key.len = strlen(msg->msg_uid);
790 value.data = NULL;
791 value.len = 0;
792 r = chash_set(hash_exist, &key, &value, NULL);
793 if (r < 0) {
794 res = MAIL_ERROR_MEMORY;
795 goto free;
796 }
797 }
798
799 d = opendir(cache_dir);
800 while ((ent = readdir(d)) != NULL) {
801 chashdatum key;
802 chashdatum value;
803
804 if (strcmp(ent->d_name, ".") == 0)
805 continue;
806
807 if (strcmp(ent->d_name, "..") == 0)
808 continue;
809
810 if (strstr(ent->d_name, ".db") != NULL)
811 continue;
812
813 strncpy(keyname, ent->d_name, sizeof(keyname));
814 keyname[sizeof(keyname) - 1] = '\0';
815
816 get_uid_from_filename(keyname);
817
818 if (* keyname == '\0')
819 continue;
820
821 key.data = keyname;
822 key.len = strlen(keyname);
823
824 r = chash_get(hash_exist, &key, &value);
825 if (r < 0) {
826 snprintf(cached_filename, sizeof(cached_filename),
827 "%s/%s", cache_dir, ent->d_name);
828 unlink(cached_filename);
829 }
830 }
831 closedir(d);
832
833 chash_free(hash_exist);
834
835 return MAIL_NO_ERROR;
836
837 free:
838 chash_free(hash_exist);
839 err:
840 return res;
841}
diff --git a/libetpan/src/driver/interface/maildriver_tools.h b/libetpan/src/driver/interface/maildriver_tools.h
new file mode 100644
index 0000000..a92af42
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_tools.h
@@ -0,0 +1,81 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_TOOLS_H
37
38#define MAILDRIVER_TOOLS_H
39
40#include "maildriver_types.h"
41#include "mail_cache_db_types.h"
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47int
48maildriver_generic_get_envelopes_list(mailsession * session,
49 struct mailmessage_list * env_list);
50
51#if 0
52int maildriver_generic_search_messages(mailsession * session, char * charset,
53 struct mail_search_key * key,
54 struct mail_search_result ** result);
55#endif
56
57int
58maildriver_env_list_to_msg_list(struct mailmessage_list * env_list,
59 clist ** result);
60
61int maildriver_imf_error_to_mail_error(int error);
62
63char * maildriver_quote_mailbox(char * mb);
64
65int
66maildriver_env_list_to_msg_list_no_flags(struct mailmessage_list * env_list,
67 clist ** result);
68
69int maildriver_cache_clean_up(struct mail_cache_db * cache_db_env,
70 struct mail_cache_db * cache_db_flags,
71 struct mailmessage_list * env_list);
72
73int maildriver_message_cache_clean_up(char * cache_dir,
74 struct mailmessage_list * env_list,
75 void (* get_uid_from_filename)(char *));
76
77#ifdef __cplusplus
78}
79#endif
80
81#endif
diff --git a/libetpan/src/driver/interface/maildriver_types.c b/libetpan/src/driver/interface/maildriver_types.c
new file mode 100644
index 0000000..43f5c4f
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_types.c
@@ -0,0 +1,340 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildriver_types.h"
37#include <time.h>
38#include <stdlib.h>
39#include "mailmessage.h"
40
41struct mailmessage_list * mailmessage_list_new(carray * msg_tab)
42{
43 struct mailmessage_list * env_list;
44
45 env_list = malloc(sizeof(* env_list));
46 if (env_list == NULL)
47 return NULL;
48
49 env_list->msg_tab = msg_tab;
50
51 return env_list;
52}
53
54void mailmessage_list_free(struct mailmessage_list * env_list)
55{
56 unsigned int i;
57
58 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
59 mailmessage * msg;
60
61 msg = carray_get(env_list->msg_tab, i);
62 if (msg != NULL)
63 mailmessage_free(msg);
64 }
65 carray_free(env_list->msg_tab);
66 free(env_list);
67}
68
69struct mail_list * mail_list_new(clist * list)
70{
71 struct mail_list * resp;
72
73 resp = malloc(sizeof(* resp));
74 if (resp == NULL)
75 return NULL;
76 resp->mb_list = list;
77
78 return resp;
79}
80
81void mail_list_free(struct mail_list * resp)
82{
83 clist_foreach(resp->mb_list, (clist_func) free, NULL);
84 clist_free(resp->mb_list);
85 free(resp);
86}
87
88static int32_t mailimf_date_time_to_int(struct mailimf_date_time * date)
89{
90 return date->dt_year * 12 * 30 * 24 * 60 * 60 +
91 date->dt_month * 30 * 24 * 60 * 60 + date->dt_day * 24 * 60 * 60 +
92 (date->dt_hour - date->dt_zone) * 60 * 60 +
93 date->dt_min * 60 + date->dt_sec;
94}
95
96int32_t mailimf_date_time_comp(struct mailimf_date_time * date1,
97 struct mailimf_date_time * date2)
98{
99 return mailimf_date_time_to_int(date1) - mailimf_date_time_to_int(date2);
100}
101
102
103
104
105
106
107
108#if 0
109struct mail_search_key *
110mail_search_key_new(int sk_type,
111 char * sk_bcc,
112 struct mailimf_date_time * sk_before,
113 char * sk_body,
114 char * sk_cc,
115 char * sk_from,
116 struct mailimf_date_time * sk_on,
117 struct mailimf_date_time * sk_since,
118 char * sk_subject,
119 char * sk_text,
120 char * sk_to,
121 char * sk_header_name,
122 char * sk_header_value,
123 size_t sk_larger,
124 struct mail_search_key * sk_not,
125 struct mail_search_key * sk_or1,
126 struct mail_search_key * sk_or2,
127 size_t sk_smaller,
128 clist * sk_multiple)
129{
130 struct mail_search_key * key;
131
132 key = malloc(sizeof(* key));
133 if (key == NULL)
134 return NULL;
135
136 key->sk_type = sk_type;
137 key->sk_bcc = sk_bcc;
138 key->sk_before = sk_before;
139 key->sk_body = sk_body;
140 key->sk_cc = sk_cc;
141 key->sk_from = sk_from;
142 key->sk_on = sk_on;
143 key->sk_since = sk_since;
144 key->sk_subject = sk_subject;
145 key->sk_text = sk_text;
146 key->sk_to = sk_to;
147 key->sk_header_name = sk_header_name;
148 key->sk_header_value = sk_header_value;
149 key->sk_larger = sk_larger;
150 key->sk_not = sk_not;
151 key->sk_or1 = sk_or1;
152 key->sk_or2 = sk_or2;
153 key->sk_smaller = sk_smaller;
154 key->sk_multiple = sk_multiple;
155
156 return key;
157}
158
159
160void mail_search_key_free(struct mail_search_key * key)
161{
162 if (key->sk_bcc)
163 free(key->sk_bcc);
164 if (key->sk_before)
165 mailimf_date_time_free(key->sk_before);
166 if (key->sk_body)
167 free(key->sk_body);
168 if (key->sk_cc)
169 free(key->sk_cc);
170 if (key->sk_from)
171 free(key->sk_from);
172 if (key->sk_on)
173 mailimf_date_time_free(key->sk_on);
174 if (key->sk_since)
175 mailimf_date_time_free(key->sk_since);
176 if (key->sk_subject)
177 free(key->sk_subject);
178 if (key->sk_text)
179 free(key->sk_text);
180 if (key->sk_to)
181 free(key->sk_to);
182 if (key->sk_header_name)
183 free(key->sk_header_name);
184 if (key->sk_header_value)
185 free(key->sk_header_value);
186 if (key->sk_not)
187 mail_search_key_free(key->sk_not);
188 if (key->sk_or1)
189 mail_search_key_free(key->sk_or1);
190 if (key->sk_or2)
191 mail_search_key_free(key->sk_or2);
192 if (key->sk_multiple) {
193 clist_foreach(key->sk_multiple, (clist_func) mail_search_key_free, NULL);
194 clist_free(key->sk_multiple);
195 }
196
197 free(key);
198}
199
200
201struct mail_search_result * mail_search_result_new(clist * list)
202{
203 struct mail_search_result * search_result;
204
205 search_result = malloc(sizeof(* search_result));
206 if (search_result == NULL)
207 return NULL;
208 search_result->list = list;
209
210 return search_result;
211}
212
213void mail_search_result_free(struct mail_search_result * search_result)
214{
215 clist_foreach(search_result->list, (clist_func) free, NULL);
216 clist_free(search_result->list);
217 free(search_result);
218}
219#endif
220
221struct error_message {
222 int code;
223 char * message;
224};
225
226static struct error_message message_tab[] = {
227{ MAIL_NO_ERROR, "no error" },
228{ MAIL_NO_ERROR_AUTHENTICATED, "no error - authenticated" },
229{ MAIL_NO_ERROR_NON_AUTHENTICATED, "no error - not authenticated" },
230{ MAIL_ERROR_NOT_IMPLEMENTED, "not implemented" },
231{ MAIL_ERROR_UNKNOWN, "unknown"},
232{ MAIL_ERROR_CONNECT, "connect"},
233{ MAIL_ERROR_BAD_STATE, "bad state"},
234{ MAIL_ERROR_FILE, "file error - file could not be accessed" },
235{ MAIL_ERROR_STREAM, "stream error - socket could not be read or written" },
236{ MAIL_ERROR_LOGIN, "login error" },
237{ MAIL_ERROR_CREATE, "create error" },
238{ MAIL_ERROR_DELETE, /* 10 */ "delete error" },
239{ MAIL_ERROR_LOGOUT, "logout error" },
240{ MAIL_ERROR_NOOP, "noop error" },
241{ MAIL_ERROR_RENAME, "rename error" },
242{ MAIL_ERROR_CHECK, "check error" },
243{ MAIL_ERROR_EXAMINE, "examine error" },
244{ MAIL_ERROR_SELECT, "select error - folder does not exist" },
245{ MAIL_ERROR_MEMORY, "not enough memory" },
246{ MAIL_ERROR_STATUS, "status error" },
247{ MAIL_ERROR_SUBSCRIBE, "subscribe error" },
248{ MAIL_ERROR_UNSUBSCRIBE, /* 20 */ "unsubscribe error" },
249{ MAIL_ERROR_LIST, "list error" },
250{ MAIL_ERROR_LSUB, "lsub error" },
251{ MAIL_ERROR_APPEND, "append error - mail could not be appended" },
252{ MAIL_ERROR_COPY, "copy error" },
253{ MAIL_ERROR_FETCH, "fetch error" },
254{ MAIL_ERROR_STORE, "store error" },
255{ MAIL_ERROR_SEARCH, "search error" },
256{ MAIL_ERROR_DISKSPACE, " error: not enough diskspace" },
257{ MAIL_ERROR_MSG_NOT_FOUND, "message not found" },
258{ MAIL_ERROR_PARSE, /* 30 */ "parse error" },
259{ MAIL_ERROR_INVAL, "invalid parameter for the function" },
260{ MAIL_ERROR_PART_NOT_FOUND, "mime part of the message is not found" },
261{ MAIL_ERROR_REMOVE, "remove error - the message did not exist" },
262{ MAIL_ERROR_FOLDER_NOT_FOUND, "folder not found" },
263{ MAIL_ERROR_MOVE, "move error" },
264{ MAIL_ERROR_STARTTLS, "starttls error" },
265{ MAIL_ERROR_CACHE_MISS, "mail cache missed" },
266{ MAIL_ERROR_NO_TLS, "no starttls" },
267{ MAIL_ERROR_EXPUNGE, "expunge error" },
268{ MAIL_ERROR_PROTOCOL, "protocol error - server did not respect the protocol" },
269{ MAIL_ERROR_CAPABILITY, "capability error" },
270{ MAIL_ERROR_CLOSE, "close error" },
271{ MAIL_ERROR_FATAL, "fatal error" },
272{ MAIL_ERROR_READONLY, "mailbox is readonly" },
273{ MAIL_ERROR_NO_APOP, "pop3 error - no apop" },
274{ MAIL_ERROR_COMMAND_NOT_SUPPORTED, "nntp error - command not supported" },
275{ MAIL_ERROR_NO_PERMISSION, "nntp error - no permission" },
276{ MAIL_ERROR_PROGRAM_ERROR, "nntp error - program error" },
277{ MAIL_ERROR_SUBJECT_NOT_FOUND, "internal threading error - subject not found" }};
278
279const char * maildriver_strerror(int err)
280{
281 int count;
282 int i;
283
284 count = sizeof(message_tab) / sizeof(struct error_message);
285
286 for(i = 0 ; i < count ; i++) {
287 if (message_tab[i].code == err) {
288 return message_tab[i].message;
289 }
290 }
291
292 return "unknown error";
293}
294
295
296struct mail_flags * mail_flags_new_empty(void)
297{
298 struct mail_flags * flags;
299
300 flags = malloc(sizeof(* flags));
301 if (flags == NULL)
302 goto err;
303
304 flags->fl_flags = MAIL_FLAG_NEW;
305 flags->fl_extension = clist_new();
306 if (flags->fl_extension == NULL)
307 goto free;
308
309 return flags;
310
311 free:
312 free(flags);
313 err:
314 return NULL;
315}
316
317struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_extension)
318{
319 struct mail_flags * flags;
320
321 flags = malloc(sizeof(* flags));
322 if (flags == NULL)
323 goto err;
324
325 flags->fl_flags = fl_flags;
326 flags->fl_extension = fl_extension;
327
328 return flags;
329
330err:
331 return NULL;
332}
333
334void mail_flags_free(struct mail_flags * flags)
335{
336 clist_foreach(flags->fl_extension, (clist_func) free, NULL);
337 clist_free(flags->fl_extension);
338 free(flags);
339}
340
diff --git a/libetpan/src/driver/interface/maildriver_types.h b/libetpan/src/driver/interface/maildriver_types.h
new file mode 100644
index 0000000..2225236
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_types.h
@@ -0,0 +1,795 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_TYPES_H
37
38#define MAILDRIVER_TYPES_H
39
40#include <inttypes.h>
41#include <sys/types.h>
42
43#include <libetpan/mailstream.h>
44#include <libetpan/mailimf.h>
45#include <libetpan/mailmime.h>
46#include <libetpan/carray.h>
47
48#include <libetpan/mailthread_types.h>
49#include <libetpan/maildriver_errors.h>
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54
55typedef struct mailsession_driver mailsession_driver;
56
57typedef struct mailsession mailsession;
58
59typedef struct mailmessage_driver mailmessage_driver;
60
61typedef struct mailmessage mailmessage;
62
63
64/*
65 mailmessage_list is a list of mailmessage
66
67 - tab is an array of mailmessage structures
68*/
69
70struct mailmessage_list {
71 carray * msg_tab; /* elements are (mailmessage *) */
72};
73
74struct mailmessage_list * mailmessage_list_new(carray * msg_tab);
75void mailmessage_list_free(struct mailmessage_list * env_list);
76
77/*
78 mail_list is a list of mailbox names
79
80 - list is a list of mailbox names
81*/
82
83struct mail_list {
84 clist * mb_list; /* elements are (char *) */
85};
86
87struct mail_list * mail_list_new(clist * mb_list);
88void mail_list_free(struct mail_list * resp);
89
90/*
91 This is a flag value.
92 Flags can be combined with OR operation
93*/
94
95enum {
96 MAIL_FLAG_NEW = 1 << 0,
97 MAIL_FLAG_SEEN = 1 << 1,
98 MAIL_FLAG_FLAGGED = 1 << 2,
99 MAIL_FLAG_DELETED = 1 << 3,
100 MAIL_FLAG_ANSWERED = 1 << 4,
101 MAIL_FLAG_FORWARDED = 1 << 5,
102 MAIL_FLAG_CANCELLED = 1 << 6,
103};
104
105/*
106 mail_flags is the value of a flag related to a message.
107
108 - flags is the standard flags value
109
110 - extension is a list of unknown flags for libEtPan!
111*/
112
113struct mail_flags {
114 uint32_t fl_flags;
115 clist * fl_extension; /* elements are (char *) */
116};
117
118struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext);
119void mail_flags_free(struct mail_flags * flags);
120
121/*
122 This function creates a flag for a new message
123*/
124
125struct mail_flags * mail_flags_new_empty(void);
126
127
128/*
129 mailimf_date_time_comp compares two dates
130
131
132*/
133
134int32_t mailimf_date_time_comp(struct mailimf_date_time * date1,
135 struct mailimf_date_time * date2);
136
137/*
138 this is type type of the search criteria
139*/
140
141enum {
142 MAIL_SEARCH_KEY_ALL, /* all messages correspond */
143 MAIL_SEARCH_KEY_ANSWERED, /* messages with flag \Answered */
144 MAIL_SEARCH_KEY_BCC, /* messages which Bcc field contains
145 a given string */
146 MAIL_SEARCH_KEY_BEFORE, /* messages which internal date is earlier
147 than the specified date */
148 MAIL_SEARCH_KEY_BODY, /* message that contains the given string
149 (in header and text parts) */
150 MAIL_SEARCH_KEY_CC, /* messages whose Cc field contains the
151 given string */
152 MAIL_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */
153 MAIL_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */
154 MAIL_SEARCH_KEY_FROM, /* messages whose From field contains the
155 given string */
156 MAIL_SEARCH_KEY_NEW, /* messages with the flag \Recent and not
157 the \Seen flag */
158 MAIL_SEARCH_KEY_OLD, /* messages that do not have the
159 \Recent flag set */
160 MAIL_SEARCH_KEY_ON, /* messages whose internal date is the
161 specified date */
162 MAIL_SEARCH_KEY_RECENT, /* messages with the flag \Recent */
163 MAIL_SEARCH_KEY_SEEN, /* messages with the flag \Seen */
164 MAIL_SEARCH_KEY_SINCE, /* messages whose internal date is later
165 than specified date */
166 MAIL_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the
167 given string */
168 MAIL_SEARCH_KEY_TEXT, /* messages whose text part contains the
169 given string */
170 MAIL_SEARCH_KEY_TO, /* messages whose To field contains the
171 given string */
172 MAIL_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */
173 MAIL_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */
174 MAIL_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */
175 MAIL_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */
176 MAIL_SEARCH_KEY_HEADER, /* messages whose given field
177 contains the given string */
178 MAIL_SEARCH_KEY_LARGER, /* messages whose size is larger then
179 the given size */
180 MAIL_SEARCH_KEY_NOT, /* not operation of the condition */
181 MAIL_SEARCH_KEY_OR, /* or operation between two conditions */
182 MAIL_SEARCH_KEY_SMALLER, /* messages whose size is smaller than
183 the given size */
184 MAIL_SEARCH_KEY_MULTIPLE /* the boolean operator between the
185 conditions is AND */
186};
187
188/*
189 mail_search_key is the condition on the messages to return
190
191 - type is the type of the condition
192
193 - bcc is the text to search in the Bcc field when type is
194 MAIL_SEARCH_KEY_BCC, should be allocated with malloc()
195
196 - before is a date when type is MAIL_SEARCH_KEY_BEFORE
197
198 - body is the text to search in the message when type is
199 MAIL_SEARCH_KEY_BODY, should be allocated with malloc()
200
201 - cc is the text to search in the Cc field when type is
202 MAIL_SEARCH_KEY_CC, should be allocated with malloc()
203
204 - from is the text to search in the From field when type is
205 MAIL_SEARCH_KEY_FROM, should be allocated with malloc()
206
207 - on is a date when type is MAIL_SEARCH_KEY_ON
208
209 - since is a date when type is MAIL_SEARCH_KEY_SINCE
210
211 - subject is the text to search in the Subject field when type is
212 MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc()
213
214 - text is the text to search in the text part of the message when
215 type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc()
216
217 - to is the text to search in the To field when type is
218 MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc()
219
220 - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER,
221 should be allocated with malloc()
222
223 - header_value is the text to search in the given header when type is
224 MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc()
225
226 - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER
227
228 - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT
229
230 - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR
231
232 - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR
233
234 - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE
235
236 - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON
237
238 - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE
239
240 - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER
241
242 - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE
243*/
244
245#if 0
246struct mail_search_key {
247 int sk_type;
248 union {
249 char * sk_bcc;
250 struct mailimf_date_time * sk_before;
251 char * sk_body;
252 char * sk_cc;
253 char * sk_from;
254 struct mailimf_date_time * sk_on;
255 struct mailimf_date_time * sk_since;
256 char * sk_subject;
257 char * sk_text;
258 char * sk_to;
259 char * sk_header_name;
260 char * sk_header_value;
261 size_t sk_larger;
262 struct mail_search_key * sk_not;
263 struct mail_search_key * sk_or1;
264 struct mail_search_key * sk_or2;
265 size_t sk_smaller;
266 clist * sk_multiple; /* list of (struct mailimap_search_key *) */
267 } sk_data;
268};
269
270
271struct mail_search_key *
272mail_search_key_new(int sk_type,
273 char * sk_bcc, struct mailimf_date_time * sk_before,
274 char * sk_body, char * sk_cc, char * sk_from,
275 struct mailimf_date_time * sk_on, struct mailimf_date_time * sk_since,
276 char * sk_subject, char * sk_text, char * sk_to,
277 char * sk_header_name, char * sk_header_value, size_t sk_larger,
278 struct mail_search_key * sk_not, struct mail_search_key * sk_or1,
279 struct mail_search_key * sk_or2, size_t sk_smaller,
280 clist * sk_multiple);
281
282void mail_search_key_free(struct mail_search_key * key);
283#endif
284
285/*
286 mail_search_result is a list of message numbers that is returned
287 by the mailsession_search_messages function()
288*/
289
290#if 0
291struct mail_search_result {
292 clist * sr_list; /* list of (uint32_t *) */
293};
294
295struct mail_search_result * mail_search_result_new(clist * sr_list);
296
297void mail_search_result_free(struct mail_search_result * search_result);
298#endif
299
300
301/*
302 There is three kinds of identities :
303 - storage
304 - folders
305 - session
306
307 A storage (struct mailstorage) represents whether a server or
308 a main path,
309
310 A storage can be an IMAP server, the root path of a MH or a mbox file.
311
312 Folders (struct mailfolder) are the mailboxes we can
313 choose in the server or as sub-folder of the main path.
314
315 Folders for IMAP are the IMAP mailboxes, for MH this is one of the
316 folder of the MH storage, for mbox, there is only one folder, the
317 mbox file content;
318
319 A mail session (struct mailsession) is whether a connection to a server
320 or a path that is open. It is the abstraction lower folders and storage.
321 It allow us to send commands.
322
323 We have a session driver for mail session for each kind of storage.
324
325 From a session, we can get a message (struct mailmessage) to read.
326 We have a message driver for each kind of storage.
327*/
328
329/*
330 maildriver is the driver structure for mail sessions
331
332 - name is the name of the driver
333
334 - initialize() is the function that will initializes a data structure
335 specific to the driver, it returns a value that will be stored
336 in the field data of the session.
337 The field data of the session is the state of the session,
338 the internal data structure used by the driver.
339 It is called when creating the mailsession structure with
340 mailsession_new().
341
342 - uninitialize() frees the structure created with initialize()
343
344 - parameters() implements functions specific to the given mail access
345
346 - connect_stream() connects a stream to the session
347
348 - connect_path() notify a main path to the session
349
350 - starttls() changes the current stream to a TLS stream
351
352 - login() notifies the user and the password to authenticate to the
353 session
354
355 - logout() exits the session and closes the stream
356
357 - noop() does no operation on the session, but it can be
358 used to poll for the status of the connection.
359
360 - build_folder_name() will return an allocated string with
361 that contains the complete path of the folder to create
362
363 - create_folder() creates the folder that corresponds to the
364 given name
365
366 - delete_folder() deletes the folder that corresponds to the
367 given name
368
369 - rename_folder() change the name of the folder
370
371 - check_folder() makes a checkpoint of the session
372
373 - examine_folder() selects a mailbox as readonly
374
375 - select_folder() selects a mailbox
376
377 - expunge_folder() deletes all messages marked \Deleted
378
379 - status_folder() queries the status of the folder
380 (number of messages, number of recent messages, number of
381 unseen messages)
382
383 - messages_number() queries the number of messages in the folder
384
385 - recent_number() queries the number of recent messages in the folder
386
387 - unseen_number() queries the number of unseen messages in the folder
388
389 - list_folders() returns the list of all sub-mailboxes
390 of the given mailbox
391
392 - lsub_folders() returns the list of subscribed
393 sub-mailboxes of the given mailbox
394
395 - subscribe_folder() subscribes to the given mailbox
396
397 - unsubscribe_folder() unsubscribes to the given mailbox
398
399 - append_message() adds a RFC 2822 message to the current
400 given mailbox
401
402 - copy_message() copies a message whose number is given to
403 a given mailbox. The mailbox must be accessible from
404 the same session.
405
406 - move_message() copies a message whose number is given to
407 a given mailbox. The mailbox must be accessible from the
408 same session.
409
410 - get_messages_list() returns the list of message numbers
411 of the current mailbox.
412
413 - get_envelopes_list() fills the parsed fields in the
414 mailmessage structures of the mailmessage_list.
415
416 - remove_message() removes the given message from the mailbox.
417 The message is permanently deleted.
418
419 - search_message() returns a list of message numbers that
420 corresponds to the given criteria.
421
422 - get_message returns a mailmessage structure that corresponds
423 to the given message number.
424
425 - get_message_by_uid returns a mailmessage structure that corresponds
426 to the given message unique identifier.
427
428 * mandatory functions are the following :
429
430 - connect_stream() of connect_path()
431 - logout()
432 - get_messages_list()
433 - get_envelopes_list()
434
435 * we advise you to implement these functions :
436
437 - select_folder() (in case a session can access several folders)
438 - noop() (to check if the server is responding)
439 - check_folder() (to make a checkpoint of the session)
440 - status_folder(), messages_number(), recent_number(), unseen_number()
441 (to get stat of the folder)
442 - append_message() (but can't be done in the case of POP3 at least)
443 - login() in a case of an authenticated driver.
444 - starttls() in a case of a stream driver, if the procotol supports
445 STARTTLS.
446 - get_message_by_uid() so that the application can remember the message
447 by UID and build its own list of messages.
448
449 * drivers' specific :
450
451 Everything that is specific to the driver will be implemented in this
452 function :
453
454 - parameters()
455*/
456
457struct mailsession_driver {
458 char * sess_name;
459
460 int (* sess_initialize)(mailsession * session);
461 void (* sess_uninitialize)(mailsession * session);
462
463 int (* sess_parameters)(mailsession * session,
464 int id, void * value);
465
466 int (* sess_connect_stream)(mailsession * session, mailstream * s);
467 int (* sess_connect_path)(mailsession * session, char * path);
468
469 int (* sess_starttls)(mailsession * session);
470
471 int (* sess_login)(mailsession * session, char * userid, char * password);
472 int (* sess_logout)(mailsession * session);
473 int (* sess_noop)(mailsession * session);
474
475 /* folders operations */
476
477 int (* sess_build_folder_name)(mailsession * session, char * mb,
478 char * name, char ** result);
479
480 int (* sess_create_folder)(mailsession * session, char * mb);
481 int (* sess_delete_folder)(mailsession * session, char * mb);
482 int (* sess_rename_folder)(mailsession * session, char * mb,
483 char * new_name);
484 int (* sess_check_folder)(mailsession * session);
485 int (* sess_examine_folder)(mailsession * session, char * mb);
486 int (* sess_select_folder)(mailsession * session, char * mb);
487 int (* sess_expunge_folder)(mailsession * session);
488 int (* sess_status_folder)(mailsession * session, char * mb,
489 uint32_t * result_num, uint32_t * result_recent,
490 uint32_t * result_unseen);
491 int (* sess_messages_number)(mailsession * session, char * mb,
492 uint32_t * result);
493 int (* sess_recent_number)(mailsession * session, char * mb,
494 uint32_t * result);
495 int (* sess_unseen_number)(mailsession * session, char * mb,
496 uint32_t * result);
497
498 int (* sess_list_folders)(mailsession * session, char * mb,
499 struct mail_list ** result);
500 int (* sess_lsub_folders)(mailsession * session, char * mb,
501 struct mail_list ** result);
502
503 int (* sess_subscribe_folder)(mailsession * session, char * mb);
504 int (* sess_unsubscribe_folder)(mailsession * session, char * mb);
505
506 /* messages operations */
507
508 int (* sess_append_message)(mailsession * session,
509 char * message, size_t size);
510 int (* sess_append_message_flags)(mailsession * session,
511 char * message, size_t size, struct mail_flags * flags);
512 int (* sess_copy_message)(mailsession * session,
513 uint32_t num, char * mb);
514 int (* sess_move_message)(mailsession * session,
515 uint32_t num, char * mb);
516
517 int (* sess_get_message)(mailsession * session,
518 uint32_t num, mailmessage ** result);
519
520 int (* sess_get_message_by_uid)(mailsession * session,
521 const char * uid, mailmessage ** result);
522
523 int (* sess_get_messages_list)(mailsession * session,
524 struct mailmessage_list ** result);
525 int (* sess_get_envelopes_list)(mailsession * session,
526 struct mailmessage_list * env_list);
527 int (* sess_remove_message)(mailsession * session, uint32_t num);
528#if 0
529 int (* sess_search_messages)(mailsession * session, char * charset,
530 struct mail_search_key * key,
531 struct mail_search_result ** result);
532#endif
533};
534
535
536/*
537 session is the data structure for a mail session.
538
539 - data is the internal data structure used by the driver
540 It is called when initializing the mailsession structure.
541
542 - driver is the driver used for the session
543*/
544
545struct mailsession {
546 void * sess_data;
547 mailsession_driver * sess_driver;
548};
549
550
551
552
553/*
554 mailmessage_driver is the driver structure to get information from messages.
555
556 - name is the name of the driver
557
558 - initialize() is the function that will initializes a data structure
559 specific to the driver, it returns a value that will be stored
560 in the field data of the mailsession.
561 The field data of the session is the state of the session,
562 the internal data structure used by the driver.
563 It is called when initializing the mailmessage structure with
564 mailmessage_init().
565
566 - uninitialize() frees the structure created with initialize().
567 It will be called by mailmessage_free().
568
569 - flush() will free from memory all temporary structures of the message
570 (for example, the MIME structure of the message).
571
572 - fetch_result_free() will free all strings resulted by fetch() or
573 any fetch_xxx() functions that returns a string.
574
575 - fetch() returns the content of the message (headers and text).
576
577 - fetch_header() returns the content of the headers.
578
579 - fetch_body() returns the message text (message content without headers)
580
581 - fetch_size() returns the size of the message content.
582
583 - get_bodystructure() returns the MIME structure of the message.
584
585 - fetch_section() returns the content of a given MIME part
586
587 - fetch_section_header() returns the header of the message
588 contained by the given MIME part.
589
590 - fetch_section_mime() returns the MIME headers of the
591 given MIME part.
592
593 - fetch_section_body() returns the text (if this is a message, this is the
594 message content without headers) of the given MIME part.
595
596 - fetch_envelope() returns a mailimf_fields structure, with a list of
597 fields chosen by the driver.
598
599 - get_flags() returns a the flags related to the message.
600 When you want to get flags of a message, you have to make sure to
601 call get_flags() at least once before using directly message->flags.
602*/
603
604#define LIBETPAN_MAIL_MESSAGE_CHECK
605
606struct mailmessage_driver {
607 char * msg_name;
608
609 int (* msg_initialize)(mailmessage * msg_info);
610
611 void (* msg_uninitialize)(mailmessage * msg_info);
612
613 void (* msg_flush)(mailmessage * msg_info);
614
615 void (* msg_check)(mailmessage * msg_info);
616
617 void (* msg_fetch_result_free)(mailmessage * msg_info,
618 char * msg);
619
620 int (* msg_fetch)(mailmessage * msg_info,
621 char ** result,
622 size_t * result_len);
623
624 int (* msg_fetch_header)(mailmessage * msg_info,
625 char ** result,
626 size_t * result_len);
627
628 int (* msg_fetch_body)(mailmessage * msg_info,
629 char ** result, size_t * result_len);
630
631 int (* msg_fetch_size)(mailmessage * msg_info,
632 size_t * result);
633
634 int (* msg_get_bodystructure)(mailmessage * msg_info,
635 struct mailmime ** result);
636
637 int (* msg_fetch_section)(mailmessage * msg_info,
638 struct mailmime * mime,
639 char ** result, size_t * result_len);
640
641 int (* msg_fetch_section_header)(mailmessage * msg_info,
642 struct mailmime * mime,
643 char ** result,
644 size_t * result_len);
645
646 int (* msg_fetch_section_mime)(mailmessage * msg_info,
647 struct mailmime * mime,
648 char ** result,
649 size_t * result_len);
650
651 int (* msg_fetch_section_body)(mailmessage * msg_info,
652 struct mailmime * mime,
653 char ** result,
654 size_t * result_len);
655
656 int (* msg_fetch_envelope)(mailmessage * msg_info,
657 struct mailimf_fields ** result);
658
659 int (* msg_get_flags)(mailmessage * msg_info,
660 struct mail_flags ** result);
661};
662
663
664/*
665 mailmessage is a data structure to get information from messages
666
667 - session is the session linked to the given message, it can be NULL
668
669 - driver is the message driver
670
671 - index is the message number
672
673 - uid, when it is not NULL, it means that the folder
674 the folder has persistant message numbers, the string is
675 the unique message number in the folder.
676 uid should be implemented if possible.
677 for drivers where we cannot generate real uid,
678 a suggestion is "AAAA-IIII" where AAAA is some
679 random session number and IIII the content of index field.
680
681 - size, when it is not 0, is the size of the message content.
682
683 - fields, when it is not NULL, are the header fields of the message.
684
685 - flags, when it is not NULL, are the flags related to the message.
686
687 - single_fields, when resolved != 0, is filled with the data of fields.
688
689 - mime, when it is not NULL
690
691 - cached is != 0 when the header fields were read from the cache.
692
693 - data is data specific to the driver, this is internal data structure,
694 some state of the message.
695*/
696
697struct mailmessage {
698 mailsession * msg_session;
699 mailmessage_driver * msg_driver;
700 uint32_t msg_index;
701 char * msg_uid;
702
703 size_t msg_size;
704 struct mailimf_fields * msg_fields;
705 struct mail_flags * msg_flags;
706
707 int msg_resolved;
708 struct mailimf_single_fields msg_single_fields;
709 struct mailmime * msg_mime;
710
711 /* internal data */
712
713 int msg_cached;
714 void * msg_data;
715
716 /*
717 msg_folder field :
718 used to reference the mailfolder, this is a workaround due
719 to the problem with initial conception, where folder notion
720 did not exist.
721 */
722 void * msg_folder;
723 /* user data */
724 void * msg_user_data;
725};
726
727
728/*
729 mailmessage_tree is a node in the messages tree (thread)
730
731 - parent is the parent of the message, it is NULL if the message
732 is the root of the message tree.
733
734 - date is the date of the message in number of second elapsed
735 since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC).
736
737 - msg is the message structure that is stored referenced by the node.
738 is msg is NULL, this is a dummy node.
739
740 - children is an array that contains all the children of the node.
741 children are mailmessage_tree structures.
742
743 - is_reply is != 0 when the message is a reply or a forward
744
745 - base_subject is the extracted subject of the message.
746
747 - index is the message number.
748*/
749
750struct mailmessage_tree {
751 struct mailmessage_tree * node_parent;
752 char * node_msgid;
753 time_t node_date;
754 mailmessage * node_msg;
755 carray * node_children; /* array of (struct mailmessage_tree *) */
756
757 /* private, used for threading */
758 int node_is_reply;
759 char * node_base_subject;
760};
761
762
763struct mailmessage_tree *
764mailmessage_tree_new(char * node_msgid, time_t node_date,
765 mailmessage * node_msg);
766
767void mailmessage_tree_free(struct mailmessage_tree * tree);
768
769/*
770 mailmessage_tree_free_recursive
771
772 if you want to release memory of the given tree and all the sub-trees,
773 you can use this function.
774*/
775
776void mailmessage_tree_free_recursive(struct mailmessage_tree * tree);
777
778
779struct generic_message_t {
780 int (* msg_prefetch)(mailmessage * msg_info);
781 void (* msg_prefetch_free)(struct generic_message_t * msg);
782 int msg_fetched;
783 char * msg_message;
784 size_t msg_length;
785 void * msg_data;
786};
787
788
789const char * maildriver_strerror(int err);
790
791#ifdef __cplusplus
792}
793#endif
794
795#endif
diff --git a/libetpan/src/driver/interface/maildriver_types_helper.c b/libetpan/src/driver/interface/maildriver_types_helper.c
new file mode 100644
index 0000000..6e3abf4
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_types_helper.c
@@ -0,0 +1,104 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 200 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildriver_types_helper.h"
37
38#include "mail.h"
39
40#include "clist.h"
41#include <string.h>
42#include <stdlib.h>
43
44int mail_flags_add_extension(struct mail_flags * flags,
45 char * ext_flag)
46{
47 char * str;
48 int r;
49
50 if (mail_flags_has_extension(flags, ext_flag))
51 return MAIL_NO_ERROR;
52
53 str = strdup(ext_flag);
54 if (str == NULL)
55 return MAIL_ERROR_MEMORY;
56
57 r = clist_append(flags->fl_extension, str);
58 if (r < 0) {
59 free(str);
60 return MAIL_ERROR_MEMORY;
61 }
62
63 return MAIL_NO_ERROR;
64}
65
66int mail_flags_remove_extension(struct mail_flags * flags,
67 char * ext_flag)
68{
69 clistiter * cur;
70
71 cur = clist_begin(flags->fl_extension);
72 while (cur != NULL) {
73 char * flag_name;
74
75 flag_name = clist_content(cur);
76
77 if (strcasecmp(flag_name, ext_flag) == 0) {
78 free(flag_name);
79 cur = clist_delete(flags->fl_extension, cur);
80 }
81 else
82 cur = clist_next(cur);
83 }
84
85 return MAIL_NO_ERROR;
86}
87
88int mail_flags_has_extension(struct mail_flags * flags,
89 char * ext_flag)
90{
91 clistiter * cur;
92
93 for(cur = clist_begin(flags->fl_extension) ; cur != NULL ;
94 cur = clist_next(cur)) {
95 char * flag_name;
96
97 flag_name = clist_content(cur);
98
99 if (strcasecmp(flag_name, ext_flag) == 0)
100 return TRUE;
101 }
102
103 return FALSE;
104}
diff --git a/libetpan/src/driver/interface/maildriver_types_helper.h b/libetpan/src/driver/interface/maildriver_types_helper.h
new file mode 100644
index 0000000..50ccc70
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_types_helper.h
@@ -0,0 +1,99 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_TYPES_HELPER_H
37
38#define MAILDRIVER_TYPES_HELPER_H
39
40#include <libetpan/maildriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mail_flags_add_extension adds the given flag if it does not exists in
48 the flags.
49
50 @param flags this is the flag to change
51
52 @param ext_flag this is the name of an extension flag
53 the given flag name is duplicated and is no more needed after
54 the function call.
55
56 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
57 on error
58*/
59
60int mail_flags_add_extension(struct mail_flags * flags,
61 char * ext_flag);
62
63/*
64 mail_flags_remove_extension removes the given flag if it does not exists in
65 the flags.
66
67 @param flags this is the flag to change
68
69 @param ext_flag this is the name of an extension flag
70 the given flag name is no more needed after the function call.
71
72 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
73 on error
74*/
75
76int mail_flags_remove_extension(struct mail_flags * flags,
77 char * ext_flag);
78
79/*
80 mail_flags_has_extension returns 1 if the flags is in the given flags,
81 0 is returned otherwise.
82
83 @param flags this is the flag to change
84
85 @param ext_flag this is the name of an extension flag
86 the given flag name is no more needed after the function call.
87
88 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
89 on error
90*/
91
92int mail_flags_has_extension(struct mail_flags * flags,
93 char * ext_flag);
94
95#ifdef __cplusplus
96}
97#endif
98
99#endif
diff --git a/libetpan/src/driver/interface/mailfolder.c b/libetpan/src/driver/interface/mailfolder.c
new file mode 100644
index 0000000..eb69d7f
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailfolder.c
@@ -0,0 +1,138 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailfolder.h"
37
38#include "maildriver.h"
39
40int mailfolder_noop(struct mailfolder * folder)
41{
42 return mailsession_noop(folder->fld_session);
43}
44
45int mailfolder_check(struct mailfolder * folder)
46{
47 return mailsession_check_folder(folder->fld_session);
48}
49
50int mailfolder_expunge(struct mailfolder * folder)
51{
52 return mailsession_expunge_folder(folder->fld_session);
53}
54
55int mailfolder_status(struct mailfolder * folder,
56 uint32_t * result_messages, uint32_t * result_recent,
57 uint32_t * result_unseen)
58{
59 return mailsession_status_folder(folder->fld_session,
60 folder->fld_pathname, result_messages,
61 result_recent, result_unseen);
62}
63
64int mailfolder_append_message(struct mailfolder * folder,
65 char * message, size_t size)
66{
67 return mailsession_append_message(folder->fld_session, message, size);
68}
69
70int mailfolder_append_message_flags(struct mailfolder * folder,
71 char * message, size_t size, struct mail_flags * flags)
72{
73 return mailsession_append_message_flags(folder->fld_session, message,
74 size, flags);
75}
76
77int mailfolder_get_messages_list(struct mailfolder * folder,
78 struct mailmessage_list ** result)
79{
80 int r;
81 struct mailmessage_list * msg_list;
82 unsigned int i;
83
84 r = mailsession_get_messages_list(folder->fld_session, &msg_list);
85 if (r != MAIL_NO_ERROR)
86 return r;
87
88 for(i = 0 ; i < carray_count(msg_list->msg_tab) ; i ++) {
89 mailmessage * msg;
90
91 msg = carray_get(msg_list->msg_tab, i);
92 msg->msg_folder = folder;
93 }
94
95 * result = msg_list;
96
97 return MAIL_NO_ERROR;
98}
99
100int mailfolder_get_envelopes_list(struct mailfolder * folder,
101 struct mailmessage_list * result)
102{
103 return mailsession_get_envelopes_list(folder->fld_session, result);
104}
105
106int mailfolder_get_message(struct mailfolder * folder,
107 uint32_t num, mailmessage ** result)
108{
109 mailmessage * msg;
110 int r;
111
112 r = mailsession_get_message(folder->fld_session, num, &msg);
113 if (r != MAIL_NO_ERROR)
114 return r;
115
116 msg->msg_folder = folder;
117
118 * result = msg;
119
120 return MAIL_NO_ERROR;
121}
122
123int mailfolder_get_message_by_uid(struct mailfolder * folder,
124 const char * uid, mailmessage ** result)
125{
126 mailmessage * msg;
127 int r;
128
129 r = mailsession_get_message_by_uid(folder->fld_session, uid, &msg);
130 if (r != MAIL_NO_ERROR)
131 return r;
132
133 msg->msg_folder = folder;
134
135 * result = msg;
136
137 return MAIL_NO_ERROR;
138}
diff --git a/libetpan/src/driver/interface/mailfolder.h b/libetpan/src/driver/interface/mailfolder.h
new file mode 100644
index 0000000..55ea3be
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailfolder.h
@@ -0,0 +1,70 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILFOLDER_H
37
38#define MAILFOLDER_H
39
40#include "mailstorage_types.h"
41
42int mailfolder_noop(struct mailfolder * folder);
43
44int mailfolder_check(struct mailfolder * folder);
45
46int mailfolder_expunge(struct mailfolder * folder);
47
48int mailfolder_status(struct mailfolder * folder,
49 uint32_t * result_messages, uint32_t * result_recent,
50 uint32_t * result_unseen);
51
52int mailfolder_append_message(struct mailfolder * folder,
53 char * message, size_t size);
54
55int mailfolder_append_message_flags(struct mailfolder * folder,
56 char * message, size_t size, struct mail_flags * flags);
57
58int mailfolder_get_messages_list(struct mailfolder * folder,
59 struct mailmessage_list ** result);
60
61int mailfolder_get_envelopes_list(struct mailfolder * folder,
62 struct mailmessage_list * result);
63
64int mailfolder_get_message(struct mailfolder * folder,
65 uint32_t num, mailmessage ** result);
66
67int mailfolder_get_message_by_uid(struct mailfolder * folder,
68 const char * uid, mailmessage ** result);
69
70#endif
diff --git a/libetpan/src/driver/interface/mailmessage.c b/libetpan/src/driver/interface/mailmessage.c
new file mode 100644
index 0000000..b4921e5
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage.c
@@ -0,0 +1,240 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmessage.h"
37
38#include "mail.h"
39
40#include <string.h>
41
42int mailmessage_init(mailmessage * msg_info,
43 mailsession * msg_session,
44 mailmessage_driver * msg_driver,
45 uint32_t msg_index, size_t msg_size)
46{
47 int r;
48 int res;
49
50 msg_info->msg_driver = msg_driver;
51 msg_info->msg_session = msg_session;
52 msg_info->msg_index = msg_index;
53 msg_info->msg_uid = NULL;
54
55 msg_info->msg_cached = FALSE;
56 msg_info->msg_size = msg_size;
57 msg_info->msg_fields = NULL;
58 memset(&msg_info->msg_single_fields, 0,
59 sizeof(struct mailimf_single_fields));
60 msg_info->msg_resolved = FALSE;
61 msg_info->msg_flags = NULL;
62
63 msg_info->msg_mime = NULL;
64 msg_info->msg_data = NULL;
65 msg_info->msg_folder = NULL;
66 msg_info->msg_user_data = NULL;
67
68 if (msg_driver->msg_initialize != NULL) {
69 r = msg_driver->msg_initialize(msg_info);
70 if (r != MAIL_NO_ERROR) {
71 res = r;
72 goto err;
73 }
74 }
75
76 return MAIL_NO_ERROR;
77
78 err:
79 msg_info->msg_driver = NULL;
80 msg_info->msg_session = NULL;
81 return res;
82}
83
84int mailmessage_flush(mailmessage * msg_info)
85{
86 if (msg_info->msg_driver->msg_flush == NULL)
87 return MAIL_ERROR_NOT_IMPLEMENTED;
88
89 msg_info->msg_driver->msg_flush(msg_info);
90
91 return MAIL_NO_ERROR;
92}
93
94int mailmessage_check(mailmessage * msg_info)
95{
96 if (msg_info->msg_driver->msg_check == NULL)
97 return MAIL_ERROR_NOT_IMPLEMENTED;
98
99 msg_info->msg_driver->msg_check(msg_info);
100
101 return MAIL_NO_ERROR;
102}
103
104int mailmessage_fetch_result_free(mailmessage * msg_info,
105 char * msg)
106{
107 if (msg_info->msg_driver->msg_fetch_result_free == NULL)
108 return MAIL_ERROR_NOT_IMPLEMENTED;
109
110 msg_info->msg_driver->msg_fetch_result_free(msg_info, msg);
111
112 return MAIL_NO_ERROR;
113}
114
115int mailmessage_fetch(mailmessage * msg_info,
116 char ** result,
117 size_t * result_len)
118{
119 if (msg_info->msg_driver->msg_fetch == NULL)
120 return MAIL_ERROR_NOT_IMPLEMENTED;
121
122 return msg_info->msg_driver->msg_fetch(msg_info, result, result_len);
123}
124
125int mailmessage_fetch_header(mailmessage * msg_info,
126 char ** result,
127 size_t * result_len)
128{
129 if (msg_info->msg_driver->msg_fetch_header == NULL)
130 return MAIL_ERROR_NOT_IMPLEMENTED;
131
132 return msg_info->msg_driver->msg_fetch_header(msg_info, result, result_len);
133}
134
135int mailmessage_fetch_body(mailmessage * msg_info,
136 char ** result, size_t * result_len)
137{
138 if (msg_info->msg_driver->msg_fetch_body == NULL)
139 return MAIL_ERROR_NOT_IMPLEMENTED;
140
141 return msg_info->msg_driver->msg_fetch_body(msg_info, result, result_len);
142}
143
144int mailmessage_fetch_size(mailmessage * msg_info,
145 size_t * result)
146{
147 if (msg_info->msg_driver->msg_fetch_size == NULL)
148 return MAIL_ERROR_NOT_IMPLEMENTED;
149
150 return msg_info->msg_driver->msg_fetch_size(msg_info, result);
151}
152
153int mailmessage_get_bodystructure(mailmessage * msg_info,
154 struct mailmime ** result)
155{
156 if (msg_info->msg_driver->msg_get_bodystructure == NULL)
157 return MAIL_ERROR_NOT_IMPLEMENTED;
158
159 return msg_info->msg_driver->msg_get_bodystructure(msg_info, result);
160}
161
162int mailmessage_fetch_section(mailmessage * msg_info,
163 struct mailmime * mime,
164 char ** result, size_t * result_len)
165{
166 if (msg_info->msg_driver->msg_fetch_section == NULL)
167 return MAIL_ERROR_NOT_IMPLEMENTED;
168
169 return msg_info->msg_driver->msg_fetch_section(msg_info, mime, result, result_len);
170}
171
172int mailmessage_fetch_section_header(mailmessage * msg_info,
173 struct mailmime * mime,
174 char ** result,
175 size_t * result_len)
176{
177 if (msg_info->msg_driver->msg_fetch_section_header == NULL)
178 return MAIL_ERROR_NOT_IMPLEMENTED;
179
180 return msg_info->msg_driver->msg_fetch_section_header(msg_info, mime,
181 result, result_len);
182}
183
184int mailmessage_fetch_section_mime(mailmessage * msg_info,
185 struct mailmime * mime,
186 char ** result,
187 size_t * result_len)
188{
189 if (msg_info->msg_driver->msg_fetch_section_mime == NULL)
190 return MAIL_ERROR_NOT_IMPLEMENTED;
191
192 return msg_info->msg_driver->msg_fetch_section_mime(msg_info, mime,
193 result, result_len);
194}
195
196int mailmessage_fetch_section_body(mailmessage * msg_info,
197 struct mailmime * mime,
198 char ** result,
199 size_t * result_len)
200{
201 if (msg_info->msg_driver->msg_fetch_section_body == NULL)
202 return MAIL_ERROR_NOT_IMPLEMENTED;
203
204 return msg_info->msg_driver->msg_fetch_section_body(msg_info, mime,
205 result, result_len);
206}
207
208int mailmessage_fetch_envelope(mailmessage * msg_info,
209 struct mailimf_fields ** result)
210{
211 if (msg_info->msg_driver->msg_fetch_envelope == NULL)
212 return MAIL_ERROR_NOT_IMPLEMENTED;
213
214 return msg_info->msg_driver->msg_fetch_envelope(msg_info, result);
215}
216
217int mailmessage_get_flags(mailmessage * msg_info,
218 struct mail_flags ** result)
219{
220 struct mail_flags * dummy;
221
222 if (msg_info->msg_driver->msg_get_flags == NULL)
223 return MAIL_ERROR_NOT_IMPLEMENTED;
224
225 if (result != NULL)
226 return msg_info->msg_driver->msg_get_flags(msg_info, result);
227 else
228 return msg_info->msg_driver->msg_get_flags(msg_info, &dummy);
229}
230
231void mailmessage_resolve_single_fields(mailmessage * msg_info)
232{
233 if (!msg_info->msg_resolved) {
234 if (msg_info->msg_fields != NULL) {
235 mailimf_single_fields_init(&msg_info->msg_single_fields,
236 msg_info->msg_fields);
237 msg_info->msg_resolved = TRUE;
238 }
239 }
240}
diff --git a/libetpan/src/driver/interface/mailmessage.h b/libetpan/src/driver/interface/mailmessage.h
new file mode 100644
index 0000000..02b351b
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage.h
@@ -0,0 +1,379 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include <libetpan/mailmessage_types.h>
37
38#ifndef MAILMESSAGE_H
39
40#define MAILMESSAGE_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mailmessage_new
48
49 This function will initializes a new empty message.
50
51 @return a new empty message will be returned.
52*/
53
54mailmessage * mailmessage_new(void);
55
56/*
57 mailmessage_free
58
59 This function will release the memory used by this message.
60*/
61
62void mailmessage_free(mailmessage * info);
63
64/*
65 mailmessage_init
66
67 This function will initializes a mailmessage structure
68 with a message from a given session.
69
70 @param msg_info This is the message to initialize.
71
72 @param session This is the source session of the message. It
73 can be NULL if the message does not get the information
74 through the session.
75
76 @param driver This is the driver to use for the message.
77
78 @param index This is the message number in the session. 0 can
79 be given if the message is not attached to a session.
80
81 @param size is an optional parameter, 0 can be given.
82 This is informational. This is the size of message content.
83
84 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
85 on error
86*/
87
88int mailmessage_init(mailmessage * msg_info,
89 mailsession * session,
90 mailmessage_driver * driver,
91 uint32_t index, size_t size);
92
93/*
94 mailmessage_flush
95
96 This function will release all the temporary resources that are not
97 necessary to use the mailmessage structure from memory. These
98 resources are for example cached information, such as the MIME
99 structure.
100
101 @param info is the message to clean.
102
103 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
104 on error. We can assume that MAIL_NO_ERROR is always returned.
105*/
106
107int mailmessage_flush(mailmessage * info);
108
109/*
110 mailmessage_check
111
112 This function will notify the new value of the flags to the session,
113 it must be called before mailsession_check_folder() in case the flags have
114 been changed.
115
116 @param info is the message to checkpoint.
117
118 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
119 on error. We can assume that MAIL_NO_ERROR is always returned.
120*/
121
122int mailmessage_check(mailmessage * info);
123
124/*
125 mailmessage_fetch_result_free
126
127 This function releases the memory used by a message returned
128 by any of the fetch function that returns a (char *).
129
130 @param msg_info is the message which the given buffer is from.
131
132 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
133 on error. We can assume that MAIL_NO_ERROR is always returned.
134*/
135
136int mailmessage_fetch_result_free(mailmessage * msg_info,
137 char * msg);
138
139/*
140 mailmessage_fetch
141
142 This function returns the content of the message (headers and text).
143
144 @param msg_info is the message from which we want to fetch information.
145
146 @param result The content of the message is returned in (* result)
147
148 @param result_len The length of the returned string is stored
149 in (* result_len).
150
151 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
152 on error.
153*/
154
155int mailmessage_fetch(mailmessage * msg_info,
156 char ** result,
157 size_t * result_len);
158
159/*
160 mailmessage_fetch_header
161
162 This function returns the header of the message as a string.
163
164 @param msg_info is the message from which we want to fetch information.
165
166 @param result The header of the message is returned in (* result)
167
168 @param result_len The length of the returned string is stored
169 in (* result_len).
170
171 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
172 on error.
173*/
174
175int mailmessage_fetch_header(mailmessage * msg_info,
176 char ** result,
177 size_t * result_len);
178
179/*
180 mailmessage_fetch_body
181
182 This function returns the content of the message (without headers).
183
184 @param msg_info is the message from which we want to fetch information.
185 @param result The message text (without headers) is returned
186 in (* result)
187 @param result_len The length of the returned string is stored
188 in (* result_len).
189
190 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
191 on error.
192*/
193
194int mailmessage_fetch_body(mailmessage * msg_info,
195 char ** result, size_t * result_len);
196
197/*
198 mailmessage_fetch_size
199
200 This function returns the size of the message content.
201
202 @param msg_info is the message from which we want to fetch information.
203
204 @param result The length of the message content is stored in (* result).
205
206 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
207 on error.
208*/
209
210int mailmessage_fetch_size(mailmessage * msg_info,
211 size_t * result);
212
213/*
214 mailmessage_get_bodystructure
215
216 This functions returns the MIME structure of the message.
217 The returned information MUST not be freed by hand. It is freed by
218 mailmessage_flush() or mailmessage_free().
219
220 @param msg_info is the message from which we want to fetch information.
221
222 @param result The MIME structure is stored in (* result).
223
224 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
225 on error.
226*/
227
228int mailmessage_get_bodystructure(mailmessage * msg_info,
229 struct mailmime ** result);
230
231/*
232 mailmessage_fetch_section
233
234 This function returns the content of a MIME part.
235
236 @param msg_info is the message from which we want to fetch information.
237
238 @param mime is the MIME part identifier.
239
240 @param result The content is returned in (* result)
241
242 @param result_len The length of the returned string is stored
243 in (* result_len).
244
245 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
246 on error.
247 */
248
249int mailmessage_fetch_section(mailmessage * msg_info,
250 struct mailmime * mime,
251 char ** result, size_t * result_len);
252
253/*
254 mailmessage_fetch_section_header
255
256 This function returns the header of the message contained
257 in the given MIME part.
258
259 @param msg_info is the message from which we want to fetch information.
260
261 @param mime is the MIME part identifier.
262
263 @param result The header is returned in (* result)
264
265 @param result_len The length of the returned string is stored
266 in (* result_len).
267
268 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
269 on error.
270*/
271
272int mailmessage_fetch_section_header(mailmessage * msg_info,
273 struct mailmime * mime,
274 char ** result,
275 size_t * result_len);
276
277/*
278 mailmessage_fetch_section_mime
279
280 This function returns the MIME header of the given MIME part.
281
282 @param msg_info is the message from which we want to fetch information.
283
284 @param mime is the MIME part identifier.
285
286 @param result The MIME header is returned in (* result)
287
288 @param result_len The length of the returned string is stored
289 in (* result_len).
290
291 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
292 on error.
293*/
294
295int mailmessage_fetch_section_mime(mailmessage * msg_info,
296 struct mailmime * mime,
297 char ** result,
298 size_t * result_len);
299
300/*
301 mailmessage_fetch_section_body
302
303 This function returns the text part of the message contained
304 in the given MIME part.
305
306 @param msg_info is the message from which we want to fetch information.
307
308 @param mime is the MIME part identifier.
309
310 @param result The message text is returned in (* result)
311
312 @param result_len The length of the returned string is stored
313 in (* result_len).
314
315 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
316 on error.
317 */
318
319int mailmessage_fetch_section_body(mailmessage * msg_info,
320 struct mailmime * mime,
321 char ** result,
322 size_t * result_len);
323
324/*
325 mailmessage_fetch_envelope
326
327 This function returns a list of parsed fields of the message,
328 chosen by the driver.
329 The returned structure must be freed with mailimf_fields_free().
330
331 @param msg_info is the message from which we want to fetch information.
332
333 @param result The headers list is returned in (* result)
334
335 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
336 on error.
337 */
338
339int mailmessage_fetch_envelope(mailmessage * msg_info,
340 struct mailimf_fields ** result);
341
342
343/*
344 mailmessage_get_flags
345
346 This function returns the flags related to the message.
347 The returned information MUST not be freed by hand. It is freed by
348 mailmessage_free().
349
350 @param msg_info is the message from which we want to fetch information.
351
352 @param result The flags are stored in (* result).
353
354 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
355 on error.
356*/
357
358int mailmessage_get_flags(mailmessage * msg_info,
359 struct mail_flags ** result);
360
361/*
362 mailmessage_resolve_single_fields
363
364 This function will use the fields information to fill the single_fields
365 structure in the mailmessage structure.
366
367 @param msg_info This is the msg_info to process.
368
369 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
370 on error.
371*/
372
373void mailmessage_resolve_single_fields(mailmessage * msg_info);
374
375#ifdef __cplusplus
376}
377#endif
378
379#endif
diff --git a/libetpan/src/driver/interface/mailmessage_tools.c b/libetpan/src/driver/interface/mailmessage_tools.c
new file mode 100644
index 0000000..9e53173
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage_tools.c
@@ -0,0 +1,600 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmessage_tools.h"
37#include "mailmessage.h"
38
39#include <stdlib.h>
40
41#include "maildriver.h"
42#include "maildriver_tools.h"
43
44int
45mailmessage_generic_initialize(mailmessage * msg_info)
46{
47 struct generic_message_t * msg;
48
49 msg = malloc(sizeof(* msg));
50
51 if (msg == NULL) {
52 return MAIL_ERROR_MEMORY;
53 }
54
55 msg->msg_fetched = 0;
56 msg->msg_message = NULL;
57 msg->msg_length = 0;
58
59 msg->msg_prefetch = NULL;
60 msg->msg_prefetch_free = NULL;
61 msg->msg_data = NULL;
62
63 msg_info->msg_data = msg;
64
65 return MAIL_NO_ERROR;
66}
67
68void mailmessage_generic_flush(mailmessage * msg_info)
69{
70 struct generic_message_t * msg;
71
72 if (msg_info->msg_mime != NULL) {
73 mailmime_free(msg_info->msg_mime);
74 msg_info->msg_mime = NULL;
75 }
76 msg = msg_info->msg_data;
77 if (msg != NULL) {
78 if (msg->msg_prefetch_free != NULL)
79 msg->msg_prefetch_free(msg);
80 msg->msg_fetched = 0;
81 }
82}
83
84void mailmessage_generic_uninitialize(mailmessage * msg_info)
85{
86 struct generic_message_t * msg;
87
88 mailmessage_generic_flush(msg_info);
89
90 msg = msg_info->msg_data;
91 msg_info->msg_data = NULL;
92 free(msg);
93}
94
95static inline int
96mailmessage_generic_prefetch(mailmessage * msg_info)
97{
98 struct generic_message_t * msg;
99 int r;
100
101 msg = msg_info->msg_data;
102
103 if (msg->msg_fetched)
104 return MAIL_NO_ERROR;
105
106#if 0
107 if (msg->message != NULL)
108 return MAIL_NO_ERROR;
109#endif
110
111 r = msg->msg_prefetch(msg_info);
112 if (r != MAIL_NO_ERROR)
113 return r;
114
115 msg->msg_fetched = 1;
116
117 return MAIL_NO_ERROR;
118}
119
120static int
121mailmessage_generic_prefetch_bodystructure(mailmessage * msg_info)
122{
123 size_t length;
124 char * message;
125 size_t cur_token;
126 struct mailmime * mime;
127 int r;
128 int res;
129 struct generic_message_t * msg;
130
131 if (msg_info->msg_mime != NULL) {
132 /* it has already been fetched */
133 return MAIL_NO_ERROR;
134 }
135
136#if 0
137 msg = msg_info->data;
138 if (msg->message == NULL) {
139 r = mailmessage_generic_prefetch(msg_info);
140 if (r != MAIL_NO_ERROR) {
141 res = r;
142 goto err;
143 }
144 }
145#endif
146 r = mailmessage_generic_prefetch(msg_info);
147 if (r != MAIL_NO_ERROR) {
148 res = r;
149 goto err;
150 }
151
152 msg = msg_info->msg_data;
153 message = msg->msg_message;
154 length = msg->msg_length;
155 cur_token = 0;
156 r = mailmime_parse(message, length, &cur_token, &mime);
157 if (r != MAILIMF_NO_ERROR) {
158 res = MAIL_ERROR_PARSE;
159 goto err;
160 }
161
162 msg_info->msg_mime = mime;
163
164 return MAIL_NO_ERROR;
165
166 err:
167 return res;
168}
169
170void
171mailmessage_generic_fetch_result_free(mailmessage * msg_info, char * msg)
172{
173 int r;
174
175 r = mmap_string_unref(msg);
176}
177
178int mailmessage_generic_fetch(mailmessage * msg_info,
179 char ** result,
180 size_t * result_len)
181{
182 int r;
183 char * message;
184 size_t cur_token;
185 size_t length;
186 MMAPString * mmapstr;
187 int res;
188 struct generic_message_t * msg;
189
190 msg = msg_info->msg_data;
191 r = mailmessage_generic_prefetch(msg_info);
192 if (r != MAIL_NO_ERROR) {
193 res = r;
194 goto err;
195 }
196
197 message = msg->msg_message;
198 length = msg->msg_length;
199 cur_token = 0;
200
201 mmapstr = mmap_string_new_len(message, length);
202 if (mmapstr == NULL) {
203 res = MAIL_ERROR_MEMORY;
204 goto err;
205 }
206
207 r = mmap_string_ref(mmapstr);
208 if (r < 0) {
209 res = MAIL_ERROR_MEMORY;
210 goto free_mmap;
211 }
212
213 * result = mmapstr->str;
214 * result_len = length;
215
216 return MAIL_NO_ERROR;
217
218 free_mmap:
219 mmap_string_free(mmapstr);
220 err:
221 return res;
222}
223
224int mailmessage_generic_fetch_header(mailmessage * msg_info,
225 char ** result,
226 size_t * result_len)
227{
228 int r;
229 char * message;
230 size_t cur_token;
231 size_t length;
232 MMAPString * mmapstr;
233 char * headers;
234 int res;
235 struct generic_message_t * msg;
236
237 msg = msg_info->msg_data;
238 r = mailmessage_generic_prefetch(msg_info);
239 if (r != MAIL_NO_ERROR) {
240 res = r;
241 goto err;
242 }
243
244 message = msg->msg_message;
245 length = msg->msg_length;
246 cur_token = 0;
247
248 while (1) {
249 r = mailimf_ignore_field_parse(message, length, &cur_token);
250 if (r == MAILIMF_NO_ERROR) {
251 /* do nothing */
252 }
253 else
254 break;
255 }
256 mailimf_crlf_parse(message, length, &cur_token);
257
258 mmapstr = mmap_string_new_len(message, cur_token);
259 if (mmapstr == NULL) {
260 res = MAIL_ERROR_MEMORY;
261 goto err;
262 }
263
264 r = mmap_string_ref(mmapstr);
265 if (r < 0) {
266 res = MAIL_ERROR_MEMORY;
267 goto free_mmap;
268 }
269
270 headers = mmapstr->str;
271
272 * result = headers;
273 * result_len = cur_token;
274
275 return MAIL_NO_ERROR;
276
277 free_mmap:
278 mmap_string_free(mmapstr);
279 err:
280 return res;
281}
282
283int mailmessage_generic_fetch_body(mailmessage * msg_info,
284 char ** result, size_t * result_len)
285{
286 int r;
287 char * message;
288 size_t cur_token;
289 MMAPString * mmapstr;
290 size_t length;
291 int res;
292 struct generic_message_t * msg;
293
294 msg = msg_info->msg_data;
295 r = mailmessage_generic_prefetch(msg_info);
296 if (r != MAIL_NO_ERROR) {
297 res = r;
298 goto err;
299 }
300
301 message = msg->msg_message;
302 length = msg->msg_length;
303 cur_token = 0;
304
305 while (1) {
306 r = mailimf_ignore_field_parse(message, length, &cur_token);
307 if (r == MAILIMF_NO_ERROR) {
308 /* do nothing */
309 }
310 else
311 break;
312 }
313 mailimf_crlf_parse(message, length, &cur_token);
314
315 mmapstr = mmap_string_new_len(message + cur_token, length - cur_token);
316 if (mmapstr == NULL) {
317 res = MAIL_ERROR_MEMORY;
318 goto err;
319 }
320
321 r = mmap_string_ref(mmapstr);
322 if (r < 0) {
323 res = MAIL_ERROR_MEMORY;
324 goto free_mmap;
325 }
326
327 * result = mmapstr->str;
328 * result_len = length - cur_token;
329
330 return MAIL_NO_ERROR;
331
332 free_mmap:
333 mmap_string_free(mmapstr);
334 err:
335 return res;
336}
337
338
339
340
341int
342mailmessage_generic_get_bodystructure(mailmessage * msg_info,
343 struct mailmime ** result)
344{
345 int r;
346
347 r = mailmessage_generic_prefetch_bodystructure(msg_info);
348 if (r != MAIL_NO_ERROR)
349 return r;
350
351 * result = msg_info->msg_mime;
352
353 return MAIL_NO_ERROR;
354}
355
356
357
358
359int
360mailmessage_generic_fetch_section(mailmessage * msg_info,
361 struct mailmime * mime,
362 char ** result, size_t * result_len)
363{
364 MMAPString * mmapstr;
365 int r;
366 int res;
367
368 mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data,
369 mime->mm_body->dt_data.dt_text.dt_length);
370 if (mmapstr == NULL) {
371 res = MAIL_ERROR_MEMORY;
372 goto err;
373 }
374
375 r = mmap_string_ref(mmapstr);
376 if (r < 0) {
377 res = MAIL_ERROR_MEMORY;
378 goto free_mmap;
379 }
380
381 * result = mmapstr->str;
382 * result_len = mmapstr->len;
383
384 return MAIL_NO_ERROR;
385
386 free_mmap:
387 mmap_string_free(mmapstr);
388 err:
389 return res;
390}
391
392int
393mailmessage_generic_fetch_section_header(mailmessage * msg_info,
394 struct mailmime * mime,
395 char ** result,
396 size_t * result_len)
397{
398 MMAPString * mmapstr;
399 int r;
400 int res;
401 size_t cur_token;
402
403 /* skip mime */
404
405 cur_token = 0;
406
407 if (mime->mm_type == MAILMIME_MESSAGE) {
408
409 while (1) {
410 r = mailimf_ignore_field_parse(mime->mm_body->dt_data.dt_text.dt_data,
411 mime->mm_body->dt_data.dt_text.dt_length, &cur_token);
412 if (r == MAILIMF_NO_ERROR) {
413 /* do nothing */
414 }
415 else
416 break;
417 }
418
419 r = mailimf_crlf_parse(mime->mm_body->dt_data.dt_text.dt_data,
420 mime->mm_body->dt_data.dt_text.dt_length, &cur_token);
421 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
422 res = maildriver_imf_error_to_mail_error(r);
423 goto err;
424 }
425 }
426
427 mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data,
428 cur_token);
429 if (mmapstr == NULL) {
430 res = MAIL_ERROR_MEMORY;
431 goto err;
432 }
433
434 r = mmap_string_ref(mmapstr);
435 if (r < 0) {
436 res = MAIL_ERROR_MEMORY;
437 goto free_mmap;
438 }
439
440 * result = mmapstr->str;
441 * result_len = mmapstr->len;
442
443 return MAIL_NO_ERROR;
444
445 free_mmap:
446 mmap_string_free(mmapstr);
447 err:
448 return res;
449}
450
451int
452mailmessage_generic_fetch_section_mime(mailmessage * msg_info,
453 struct mailmime * mime,
454 char ** result,
455 size_t * result_len)
456{
457 MMAPString * mmapstr;
458 int r;
459 int res;
460 size_t cur_token;
461
462 cur_token = 0;
463
464 /* skip header */
465
466 while (1) {
467 r = mailimf_ignore_field_parse(mime->mm_mime_start,
468 mime->mm_length, &cur_token);
469 if (r == MAILIMF_NO_ERROR) {
470 /* do nothing */
471 }
472 else
473 break;
474 }
475
476 r = mailimf_crlf_parse(mime->mm_mime_start, mime->mm_length, &cur_token);
477 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
478 res = maildriver_imf_error_to_mail_error(r);
479 goto err;
480 }
481
482 mmapstr = mmap_string_new_len(mime->mm_mime_start, cur_token);
483 if (mmapstr == NULL) {
484 res = MAIL_ERROR_MEMORY;
485 goto err;
486 }
487
488 r = mmap_string_ref(mmapstr);
489 if (r < 0) {
490 res = MAIL_ERROR_MEMORY;
491 goto free_mmap;
492 }
493
494 * result = mmapstr->str;
495 * result_len = mmapstr->len;
496
497 return MAIL_NO_ERROR;
498
499 free_mmap:
500 mmap_string_free(mmapstr);
501 err:
502 return res;
503}
504
505int
506mailmessage_generic_fetch_section_body(mailmessage * msg_info,
507 struct mailmime * mime,
508 char ** result,
509 size_t * result_len)
510{
511 MMAPString * mmapstr;
512 int r;
513 int res;
514 size_t cur_token;
515
516 cur_token = 0;
517
518 if (mime->mm_type == MAILMIME_MESSAGE) {
519
520 /* skip header */
521
522 while (1) {
523 r = mailimf_ignore_field_parse(mime->mm_body->dt_data.dt_text.dt_data,
524 mime->mm_body->dt_data.dt_text.dt_length, &cur_token);
525 if (r == MAILIMF_NO_ERROR) {
526 /* do nothing */
527 }
528 else
529 break;
530 }
531
532 r = mailimf_crlf_parse(mime->mm_body->dt_data.dt_text.dt_data,
533 mime->mm_body->dt_data.dt_text.dt_length, &cur_token);
534 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
535 res = maildriver_imf_error_to_mail_error(r);
536 goto err;
537 }
538 }
539
540 mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data +
541 cur_token, mime->mm_body->dt_data.dt_text.dt_length - cur_token);
542 if (mmapstr == NULL) {
543 res = MAIL_ERROR_MEMORY;
544 goto err;
545 }
546
547 r = mmap_string_ref(mmapstr);
548 if (r < 0) {
549 res = MAIL_ERROR_MEMORY;
550 goto free_mmap;
551 }
552
553 * result = mmapstr->str;
554 * result_len = mmapstr->len;
555
556 return MAIL_NO_ERROR;
557
558 free_mmap:
559 mmap_string_free(mmapstr);
560 err:
561 return res;
562}
563
564int mailmessage_generic_fetch_envelope(mailmessage * msg_info,
565 struct mailimf_fields ** result)
566{
567 int r;
568 int res;
569 size_t cur_token;
570 char * header;
571 size_t length;
572 struct mailimf_fields * fields;
573
574 r = mailmessage_fetch_header(msg_info, &header, &length);
575 if (r != MAIL_NO_ERROR) {
576 res = r;
577 goto err;
578 }
579
580 cur_token = 0;
581
582 r = mailimf_envelope_fields_parse(header, length, &cur_token,
583 &fields);
584 if (r != MAILIMF_NO_ERROR) {
585 res = maildriver_imf_error_to_mail_error(r);
586 goto free;
587 /* do nothing */
588 }
589
590 mailmessage_fetch_result_free(msg_info, header);
591
592 * result = fields;
593
594 return MAIL_NO_ERROR;
595
596 free:
597 mailmessage_fetch_result_free(msg_info, header);
598 err:
599 return res;
600}
diff --git a/libetpan/src/driver/interface/mailmessage_tools.h b/libetpan/src/driver/interface/mailmessage_tools.h
new file mode 100644
index 0000000..fd055c7
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage_tools.h
@@ -0,0 +1,103 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMESSAGE_TOOLS_H
37
38#define MAILMESSAGE_TOOLS_H
39
40#include "mailmessage_types.h"
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46int
47mailmessage_generic_initialize(mailmessage *
48 msg_info);
49
50void mailmessage_generic_uninitialize(mailmessage *
51 msg_info);
52
53void mailmessage_generic_flush(mailmessage * msg_info);
54
55void mailmessage_generic_fetch_result_free(mailmessage * msg_info,
56 char * msg);
57
58int mailmessage_generic_fetch(mailmessage * msg_info,
59 char ** result,
60 size_t * result_len);
61
62int mailmessage_generic_fetch_header(mailmessage * msg_info,
63 char ** result,
64 size_t * result_len);
65
66int mailmessage_generic_fetch_body(mailmessage * msg_info,
67 char ** result, size_t * result_len);
68
69int mailmessage_generic_get_bodystructure(mailmessage *
70 msg_info,
71 struct mailmime ** result);
72
73int
74mailmessage_generic_fetch_section(mailmessage * msg_info,
75 struct mailmime * mime,
76 char ** result, size_t * result_len);
77
78int
79mailmessage_generic_fetch_section_header(mailmessage * msg_info,
80 struct mailmime * mime,
81 char ** result,
82 size_t * result_len);
83
84int
85mailmessage_generic_fetch_section_mime(mailmessage * msg_info,
86 struct mailmime * mime,
87 char ** result,
88 size_t * result_len);
89
90int
91mailmessage_generic_fetch_section_body(mailmessage * msg_info,
92 struct mailmime * mime,
93 char ** result,
94 size_t * result_len);
95
96int mailmessage_generic_fetch_envelope(mailmessage * msg_info,
97 struct mailimf_fields ** result);
98
99#ifdef __cplusplus
100}
101#endif
102
103#endif
diff --git a/libetpan/src/driver/interface/mailmessage_types.c b/libetpan/src/driver/interface/mailmessage_types.c
new file mode 100644
index 0000000..e0955e4
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage_types.c
@@ -0,0 +1,92 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmessage_types.h"
37
38#include "mail.h"
39
40#include <stdlib.h>
41#include <string.h>
42
43mailmessage * mailmessage_new(void)
44{
45 mailmessage * msg_info;
46
47 msg_info = malloc(sizeof(* msg_info));
48 if (msg_info == NULL)
49 goto err;
50
51 msg_info->msg_driver = NULL;
52 msg_info->msg_session = NULL;
53 msg_info->msg_index = 0;
54 msg_info->msg_uid = NULL;
55
56 msg_info->msg_cached = FALSE;
57 msg_info->msg_size = 0;
58 msg_info->msg_fields = NULL;
59 memset(&msg_info->msg_single_fields,
60 0, sizeof(struct mailimf_single_fields));
61 msg_info->msg_resolved = FALSE;
62 msg_info->msg_flags = NULL;
63
64 msg_info->msg_mime = NULL;
65 msg_info->msg_data = NULL;
66
67 msg_info->msg_folder = NULL;
68 msg_info->msg_user_data = NULL;
69
70 return msg_info;
71
72 err:
73 return NULL;
74}
75
76void mailmessage_free(mailmessage * msg_info)
77{
78 if (msg_info->msg_driver != NULL) {
79 if (msg_info->msg_driver->msg_uninitialize != NULL)
80 msg_info->msg_driver->msg_uninitialize(msg_info);
81 }
82
83 if (msg_info->msg_fields != NULL)
84 mailimf_fields_free(msg_info->msg_fields);
85 if (msg_info->msg_mime != NULL)
86 mailmime_free(msg_info->msg_mime);
87 if (msg_info->msg_flags != NULL)
88 mail_flags_free(msg_info->msg_flags);
89 if (msg_info->msg_uid != NULL)
90 free(msg_info->msg_uid);
91 free(msg_info);
92}
diff --git a/libetpan/src/driver/interface/mailmessage_types.h b/libetpan/src/driver/interface/mailmessage_types.h
new file mode 100644
index 0000000..c3ed2c4
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage_types.h
@@ -0,0 +1,50 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMESSAGE_TYPES_H
37
38#define MAILMESSAGE_TYPES_H
39
40#include <libetpan/maildriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46#ifdef __cplusplus
47}
48#endif
49
50#endif
diff --git a/libetpan/src/driver/interface/mailstorage.c b/libetpan/src/driver/interface/mailstorage.c
new file mode 100644
index 0000000..2e2ddcb
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailstorage.c
@@ -0,0 +1,341 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstorage.h"
37
38#include "maildriver.h"
39
40#include <stdlib.h>
41#include <string.h>
42
43static int mailstorage_get_folder(struct mailstorage * storage,
44 char * pathname, mailsession ** result);
45
46struct mailfolder * mailfolder_new(struct mailstorage * storage,
47 char * pathname, char * virtual_name)
48{
49 struct mailfolder * folder;
50
51 folder = malloc(sizeof(struct mailfolder));
52 if (folder == NULL)
53 goto err;
54
55 if (pathname != NULL) {
56 folder->fld_pathname = strdup(pathname);
57 if (folder->fld_pathname == NULL)
58 goto free;
59 }
60 else
61 folder->fld_pathname = NULL;
62
63 if (virtual_name != NULL) {
64 folder->fld_virtual_name = strdup(virtual_name);
65 if (folder->fld_virtual_name == NULL)
66 goto free_pathname;
67 }
68 else
69 folder->fld_virtual_name = NULL;
70
71 folder->fld_storage = storage;
72
73 folder->fld_session = NULL;
74 folder->fld_shared_session = 0;
75 folder->fld_pos = NULL;
76
77 folder->fld_parent = NULL;
78 folder->fld_sibling_index = 0;
79 folder->fld_children = carray_new(128);
80 if (folder->fld_children == NULL)
81 goto free_virtualname;
82
83 return folder;
84
85free_virtualname:
86 if (folder->fld_virtual_name != NULL)
87 free(folder->fld_virtual_name);
88free_pathname:
89 if (folder->fld_pathname != NULL)
90 free(folder->fld_pathname);
91free:
92 free(folder);
93err:
94 return NULL;
95}
96
97void mailfolder_free(struct mailfolder * folder)
98{
99 if (folder->fld_parent != NULL)
100 mailfolder_detach_parent(folder);
101
102 while (carray_count(folder->fld_children) > 0) {
103 struct mailfolder * child;
104
105 child = carray_get(folder->fld_children, 0);
106 mailfolder_detach_parent(child);
107 }
108
109 carray_free(folder->fld_children);
110
111 if (folder->fld_session != NULL)
112 mailfolder_disconnect(folder);
113
114 if (folder->fld_virtual_name != NULL)
115 free(folder->fld_virtual_name);
116 if (folder->fld_pathname != NULL)
117 free(folder->fld_pathname);
118 free(folder);
119}
120
121int mailfolder_connect(struct mailfolder * folder)
122{
123 mailsession * session;
124 int res;
125 int r;
126
127 if (folder->fld_storage == NULL) {
128 res = MAIL_ERROR_INVAL;
129 goto err;
130 }
131
132 if (folder->fld_storage->sto_session == NULL) {
133 r = mailstorage_connect(folder->fld_storage);
134 if (r != MAIL_NO_ERROR) {
135 res = r;
136 goto err;
137 }
138 }
139
140 if (folder->fld_session != NULL) {
141 if ((folder->fld_pathname != NULL) && (folder->fld_shared_session)) {
142 if (folder->fld_session->sess_driver->sess_select_folder != NULL) {
143 r = mailsession_select_folder(folder->fld_session,
144 folder->fld_pathname);
145 if (r != MAIL_NO_ERROR) {
146 res = r;
147 goto err;
148 }
149 }
150 }
151
152 return MAIL_NO_ERROR;
153 }
154
155 r = mailstorage_get_folder(folder->fld_storage, folder->fld_pathname,
156 &session);
157 if (r != MAIL_NO_ERROR) {
158 res = r;
159 goto err;
160 }
161 folder->fld_session = session;
162 folder->fld_shared_session = (session == folder->fld_storage->sto_session);
163 if (folder->fld_shared_session) {
164 r = clist_append(folder->fld_storage->sto_shared_folders, folder);
165 if (r < 0) {
166 folder->fld_session = NULL;
167 res = MAIL_ERROR_MEMORY;
168 goto err;
169 }
170 folder->fld_pos = clist_end(folder->fld_storage->sto_shared_folders);
171 }
172
173 return MAIL_NO_ERROR;
174
175err:
176 return res;
177}
178
179void mailfolder_disconnect(struct mailfolder * folder)
180{
181 if (folder->fld_session == NULL)
182 return;
183
184 if (folder->fld_shared_session) {
185 clist_delete(folder->fld_storage->sto_shared_folders, folder->fld_pos);
186 folder->fld_pos = NULL;
187 }
188 else {
189 mailsession_logout(folder->fld_session);
190 mailsession_free(folder->fld_session);
191 }
192
193 folder->fld_session = NULL;
194}
195
196int mailfolder_add_child(struct mailfolder * parent,
197 struct mailfolder * child)
198{
199 unsigned int index;
200 int r;
201
202 r = carray_add(parent->fld_children, child, &index);
203 if (r < 0)
204 return MAIL_ERROR_MEMORY;
205
206 child->fld_sibling_index = index;
207 child->fld_parent = parent;
208
209 return MAIL_NO_ERROR;
210}
211
212int mailfolder_detach_parent(struct mailfolder * folder)
213{
214 unsigned int i;
215 int r;
216
217 if (folder->fld_parent == NULL)
218 return MAIL_ERROR_INVAL;
219
220 r = carray_delete_slow(folder->fld_parent->fld_children,
221 folder->fld_sibling_index);
222 if (r < 0)
223 return MAIL_ERROR_INVAL;
224
225 for(i = 0 ; i < carray_count(folder->fld_parent->fld_children) ; i ++) {
226 struct mailfolder * child;
227
228 child = carray_get(folder->fld_parent->fld_children, i);
229 child->fld_sibling_index = i;
230 }
231
232 folder->fld_parent = NULL;
233 folder->fld_sibling_index = 0;
234
235 return MAIL_NO_ERROR;
236}
237
238struct mailstorage * mailstorage_new(char * sto_id)
239{
240 struct mailstorage * storage;
241
242 storage = malloc(sizeof(struct mailstorage));
243 if (storage == NULL)
244 goto err;
245
246 if (sto_id != NULL) {
247 storage->sto_id = strdup(sto_id);
248 if (storage->sto_id == NULL)
249 goto free;
250 }
251 else
252 storage->sto_id = NULL;
253
254 storage->sto_data = NULL;
255 storage->sto_session = NULL;
256 storage->sto_driver = NULL;
257 storage->sto_shared_folders = clist_new();
258 if (storage->sto_shared_folders == NULL)
259 goto free_id;
260
261 return storage;
262
263 free_id:
264 if (storage->sto_id != NULL)
265 free(storage->sto_id);
266 free:
267 free(storage);
268 err:
269 return NULL;
270}
271
272void mailstorage_free(struct mailstorage * storage)
273{
274 if (storage->sto_session != NULL)
275 mailstorage_disconnect(storage);
276
277 if (storage->sto_driver != NULL) {
278 if (storage->sto_driver->sto_uninitialize != NULL)
279 storage->sto_driver->sto_uninitialize(storage);
280 }
281
282 clist_free(storage->sto_shared_folders);
283
284 if (storage->sto_id != NULL)
285 free(storage->sto_id);
286
287 free(storage);
288}
289
290int mailstorage_connect(struct mailstorage * storage)
291{
292 if (storage->sto_session != NULL)
293 return MAIL_NO_ERROR;
294
295 if (!clist_isempty(storage->sto_shared_folders))
296 return MAIL_ERROR_BAD_STATE;
297
298 if (storage->sto_driver->sto_connect == NULL)
299 return MAIL_ERROR_NOT_IMPLEMENTED;
300
301 return storage->sto_driver->sto_connect(storage);
302}
303
304
305void mailstorage_disconnect(struct mailstorage * storage)
306{
307 int r;
308 clistiter * cur;
309
310 while ((cur = clist_begin(storage->sto_shared_folders)) != NULL) {
311 struct mailfolder * folder;
312
313 folder = cur->data;
314 mailfolder_disconnect(folder);
315 }
316
317 if (storage->sto_session == NULL)
318 return;
319
320 r = mailsession_logout(storage->sto_session);
321
322 mailsession_free(storage->sto_session);
323 storage->sto_session = NULL;
324}
325
326
327int mailstorage_noop(struct mailstorage * storage)
328{
329 return mailsession_noop(storage->sto_session);
330}
331
332
333static int mailstorage_get_folder(struct mailstorage * storage,
334 char * pathname, mailsession ** result)
335{
336 if (storage->sto_driver->sto_get_folder_session == NULL)
337 return MAIL_ERROR_NOT_IMPLEMENTED;
338
339 return storage->sto_driver->sto_get_folder_session(storage,
340 pathname, result);
341}
diff --git a/libetpan/src/driver/interface/mailstorage.h b/libetpan/src/driver/interface/mailstorage.h
new file mode 100644
index 0000000..e8cbda3
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailstorage.h
@@ -0,0 +1,99 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_STORAGE_H
37
38#define MAIL_STORAGE_H
39
40#include <libetpan/maildriver_types.h>
41#include <libetpan/mailstorage_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47/* storage */
48
49/*
50 mailstorage_new
51
52 This function creates an empty storage. This storage have to be initialized.
53 The "driver" and "data" fields should be initialized.
54
55 @param id is the name of the storage. It can be NULL.
56 The given parameter is no more needed when the creation is finished.
57 The given string is duplicated.
58
59 @return The mail storage is returned.
60*/
61
62struct mailstorage * mailstorage_new(char * sto_id);
63
64void mailstorage_free(struct mailstorage * storage);
65
66/*
67 session will be initialized on success.
68*/
69
70int mailstorage_connect(struct mailstorage * storage);
71
72void mailstorage_disconnect(struct mailstorage * storage);
73
74int mailstorage_noop(struct mailstorage * storage);
75
76
77/* folder */
78
79struct mailfolder * mailfolder_new(struct mailstorage * fld_storage,
80 char * fld_pathname, char * fld_virtual_name);
81
82void mailfolder_free(struct mailfolder * folder);
83
84int mailfolder_add_child(struct mailfolder * parent,
85 struct mailfolder * child);
86
87int mailfolder_detach_parent(struct mailfolder * folder);
88
89int mailfolder_connect(struct mailfolder * folder);
90
91void mailfolder_disconnect(struct mailfolder * folder);
92
93#ifdef __cplusplus
94}
95#endif
96
97#endif
98
99
diff --git a/libetpan/src/driver/interface/mailstorage_tools.c b/libetpan/src/driver/interface/mailstorage_tools.c
new file mode 100644
index 0000000..9d39cab
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailstorage_tools.c
@@ -0,0 +1,372 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstorage_tools.h"
37
38#include "libetpan-config.h"
39
40#include <sys/types.h>
41#include <netdb.h>
42#include <netinet/in.h>
43#include <sys/socket.h>
44#include <unistd.h>
45#include <stdlib.h>
46#include <sys/wait.h>
47#include <sys/ioctl.h>
48#include <fcntl.h>
49#include <string.h>
50
51#include "mail.h"
52#include "mailmessage.h"
53#include "maildriver.h"
54
55/* tools */
56
57/* connection to TCP/IP server */
58
59static int tcp_connect(char * server, uint16_t port)
60{
61 struct hostent * remotehost;
62 struct sockaddr_in sa;
63 int s;
64 int r;
65
66 s = socket(PF_INET, SOCK_STREAM, 0);
67 if (s == -1)
68 goto err;
69
70 remotehost = gethostbyname(server);
71 if (remotehost == NULL)
72 goto close_socket;
73
74 sa.sin_family = AF_INET;
75 sa.sin_port = htons(port);
76 memcpy(&sa.sin_addr, remotehost->h_addr, remotehost->h_length);
77
78 r = connect(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in));
79 if (r == -1)
80 goto close_socket;
81
82 return s;
83
84 close_socket:
85 close(s);
86 err:
87 return -1;
88}
89
90
91/* connection through a shell command */
92
93static void do_exec_command(int fd, const char *command,
94 char *servername, uint16_t port)
95{
96 int i, maxopen;
97
98 if (fork() > 0) {
99 /* Fork again to become a child of init rather than
100 the etpan client. */
101 exit(0);
102 }
103
104 if (servername)
105 setenv("ETPANSERVER", servername, 1);
106 else
107 unsetenv("ETPANSERVER");
108
109 if (port) {
110 char porttext[20];
111
112 snprintf(porttext, sizeof(porttext), "%d", port);
113 setenv("ETPANPORT", porttext, 1);
114 }
115 else {
116 unsetenv("ETPANPORT");
117 }
118
119 /* Not a lot we can do if there's an error other than bail. */
120 if (dup2(fd, 0) == -1)
121 exit(1);
122 if (dup2(fd, 1) == -1)
123 exit(1);
124
125 /* Should we close stderr and reopen /dev/null? */
126
127 maxopen = sysconf(_SC_OPEN_MAX);
128 for (i=3; i < maxopen; i++)
129 close(i);
130
131#ifdef TIOCNOTTY
132 /* Detach from the controlling tty if we have one. Otherwise,
133 SSH might do something stupid like trying to use it instead
134 of running $SSH_ASKPASS. Doh. */
135 fd = open("/dev/tty", O_RDONLY);
136 if (fd != -1) {
137 ioctl(fd, TIOCNOTTY, NULL);
138 close(fd);
139 }
140#endif /* TIOCNOTTY */
141
142 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
143
144 /* Eep. Shouldn't reach this */
145 exit(1);
146}
147
148static int subcommand_connect(char *command, char *servername, uint16_t port)
149{
150 int sockfds[2];
151 pid_t childpid;
152
153 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds))
154 return -1;
155
156 childpid = fork();
157 if (!childpid) {
158 do_exec_command(sockfds[1], command, servername, port);
159 }
160 else if (childpid == -1) {
161 close(sockfds[0]);
162 close(sockfds[1]);
163 return -1;
164 }
165
166 close(sockfds[1]);
167
168 /* Reap child, leaving grandchild process to run */
169 waitpid(childpid, NULL, 0);
170
171 return sockfds[0];
172}
173
174int mailstorage_generic_connect(mailsession_driver * driver,
175 char * servername,
176 uint16_t port,
177 char * command,
178 int connection_type,
179 int cache_function_id,
180 char * cache_directory,
181 int flags_function_id,
182 char * flags_directory,
183 mailsession ** result)
184{
185 int r;
186 int res;
187 mailstream * stream;
188 int fd;
189 mailsession * session;
190 int connect_result;
191
192 switch (connection_type) {
193 case CONNECTION_TYPE_PLAIN:
194 case CONNECTION_TYPE_TRY_STARTTLS:
195 case CONNECTION_TYPE_STARTTLS:
196 case CONNECTION_TYPE_TLS:
197 fd = tcp_connect(servername, port);
198 if (fd == -1) {
199 res = MAIL_ERROR_CONNECT;
200 goto err;
201 }
202 break;
203
204 case CONNECTION_TYPE_COMMAND:
205 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
206 case CONNECTION_TYPE_COMMAND_STARTTLS:
207 case CONNECTION_TYPE_COMMAND_TLS:
208 fd = subcommand_connect(command, servername, port);
209 break;
210
211 default:
212 fd = -1;
213 break;
214 }
215
216 if (fd == -1) {
217 res = MAIL_ERROR_INVAL;
218 goto err;
219 }
220
221 switch (connection_type) {
222 case CONNECTION_TYPE_PLAIN:
223 case CONNECTION_TYPE_TRY_STARTTLS:
224 case CONNECTION_TYPE_STARTTLS:
225 case CONNECTION_TYPE_COMMAND:
226 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
227 case CONNECTION_TYPE_COMMAND_STARTTLS:
228 stream = mailstream_socket_open(fd);
229 break;
230
231 case CONNECTION_TYPE_TLS:
232 case CONNECTION_TYPE_COMMAND_TLS:
233 stream = mailstream_ssl_open(fd);
234 break;
235
236 default:
237 stream = NULL;
238 break;
239 }
240
241 if (stream == NULL) {
242 res = MAIL_ERROR_STREAM;
243 close(fd);
244 goto err;
245 }
246
247 session = mailsession_new(driver);
248 if (session == NULL) {
249 res = MAIL_ERROR_MEMORY;
250 goto close_stream;
251 }
252
253 if (cache_directory != NULL) {
254 char cache_directory_server[PATH_MAX];
255
256 snprintf(cache_directory_server, PATH_MAX, "%s/%s",
257 cache_directory, servername);
258
259 r = mailsession_parameters(session,
260 cache_function_id,
261 cache_directory_server);
262 if (r != MAIL_NO_ERROR) {
263 res = r;
264 goto close_stream;
265 }
266 }
267
268 if (flags_directory != NULL) {
269 char flags_directory_server[PATH_MAX];
270
271 snprintf(flags_directory_server, PATH_MAX, "%s/%s",
272 flags_directory, servername);
273
274 r = mailsession_parameters(session,
275 flags_function_id,
276 flags_directory_server);
277 if (r != MAIL_NO_ERROR) {
278 res = r;
279 goto close_stream;
280 }
281 }
282
283 r = mailsession_connect_stream(session, stream);
284 switch (r) {
285 case MAIL_NO_ERROR_NON_AUTHENTICATED:
286 case MAIL_NO_ERROR_AUTHENTICATED:
287 case MAIL_NO_ERROR:
288 break;
289 default:
290 res = r;
291 goto free;
292 }
293
294 connect_result = r;
295
296 switch (connection_type) {
297 case CONNECTION_TYPE_TRY_STARTTLS:
298 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
299 r = mailsession_starttls(session);
300 if ((r != MAIL_NO_ERROR) && (r != MAIL_ERROR_NO_TLS)) {
301 res = r;
302 goto free;
303 }
304 break;
305
306 case CONNECTION_TYPE_STARTTLS:
307 case CONNECTION_TYPE_COMMAND_STARTTLS:
308 r = mailsession_starttls(session);
309 if (r != MAIL_NO_ERROR) {
310 res = r;
311 goto free;
312 }
313 }
314
315 * result = session;
316
317 return connect_result;
318
319 close_stream:
320 mailstream_close(stream);
321 free:
322 mailsession_free(session);
323 err:
324 return res;
325}
326
327
328
329
330
331int mailstorage_generic_auth(mailsession * session,
332 int connect_result,
333 int auth_type,
334 char * login,
335 char * password)
336{
337 int must_auth;
338 int r;
339 int res;
340
341 r = connect_result;
342
343 must_auth = FALSE;
344 switch (r) {
345 case MAIL_NO_ERROR_NON_AUTHENTICATED:
346 must_auth = TRUE;
347 break;
348 case MAIL_NO_ERROR_AUTHENTICATED:
349 case MAIL_NO_ERROR:
350 break;
351 default:
352 res = r;
353 goto err;
354 }
355
356 if ((login == NULL) || (password == NULL))
357 must_auth = FALSE;
358
359 if (must_auth) {
360 r = mailsession_login(session, login, password);
361 if (r != MAIL_NO_ERROR) {
362 mailsession_logout(session);
363 res = r;
364 goto err;
365 }
366 }
367
368 return MAIL_NO_ERROR;
369
370 err:
371 return res;
372}
diff --git a/libetpan/src/driver/interface/mailstorage_tools.h b/libetpan/src/driver/interface/mailstorage_tools.h
new file mode 100644
index 0000000..113dcdf
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailstorage_tools.h
@@ -0,0 +1,67 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstorage.h"
37
38#ifndef MAILSTORAGE_TOOLS_H
39
40#define MAILSTORAGE_TOOLS_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46int mailstorage_generic_connect(mailsession_driver * driver,
47 char * servername,
48 uint16_t port,
49 char * command,
50 int connection_type,
51 int cache_function_id,
52 char * cache_directory,
53 int flags_function_id,
54 char * flags_directory,
55 mailsession ** result);
56
57int mailstorage_generic_auth(mailsession * session,
58 int connect_result,
59 int auth_type,
60 char * login,
61 char * password);
62
63#ifdef __cplusplus
64}
65#endif
66
67#endif
diff --git a/libetpan/src/driver/interface/mailstorage_types.h b/libetpan/src/driver/interface/mailstorage_types.h
new file mode 100644
index 0000000..d0d18c8
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailstorage_types.h
@@ -0,0 +1,203 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTORAGE_TYPES_H
37
38#define MAILSTORAGE_TYPES_H
39
40#include <libetpan/maildriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46struct mailstorage;
47
48typedef struct mailstorage_driver mailstorage_driver;
49
50
51/*
52 There is three kinds of identities :
53 - storage
54 - folders
55 - session
56
57 A storage (struct mailstorage) represents whether a server or
58 a main path,
59
60 A storage can be an IMAP server, the root path of a MH or a mbox file.
61
62 Folders (struct mailfolder) are the mailboxes we can
63 choose in the server or as sub-folder of the main path.
64
65 Folders for IMAP are the IMAP mailboxes, for MH this is one of the
66 folder of the MH storage, for mbox, there is only one folder, the
67 mbox file content;
68
69 A mail session (struct mailsession) is whether a connection to a server
70 or a path that is open. It is the abstraction lower folders and storage.
71 It allow us to send commands.
72
73 We have a session driver for mail session for each kind of storage.
74
75 From a session, we can get a message (struct mailmessage) to read.
76 We have a message driver for each kind of storage.
77*/
78
79/*
80 mailstorage_driver is the driver structure for mail storages
81
82 - name is the name of the driver
83
84 - connect() connects the storage to the remote access or to
85 the path in the local filesystem.
86
87 - get_folder() can have two kinds of behaviour.
88 Either it creates a new session and independant from the session
89 used by the storage and select the given mailbox or
90 it selects the given mailbox in the current session.
91 It depends on the efficiency of the mail driver.
92
93 - uninitialize() frees the data created with mailstorage constructor.
94*/
95
96struct mailstorage_driver {
97 char * sto_name;
98 int (* sto_connect)(struct mailstorage * storage);
99 int (* sto_get_folder_session)(struct mailstorage * storage,
100 char * pathname, mailsession ** result);
101 void (* sto_uninitialize)(struct mailstorage * storage);
102};
103
104/*
105 mailstorage is the data structure for a storage
106
107 - id is the name of the storage, it can be NULL.
108
109 - data is the data specific to the driver.
110 This is the internal state of the storage.
111
112 - session is the session related to the storage.
113
114 - driver is the driver for the storage.
115
116 - shared_folders is the list of folders returned by the storage.
117*/
118
119struct mailstorage {
120 char * sto_id;
121 void * sto_data;
122 mailsession * sto_session;
123 mailstorage_driver * sto_driver;
124 clist * sto_shared_folders; /* list of (struct mailfolder *) */
125
126 void * sto_user_data;
127};
128
129
130
131/*
132 mailfolder is the data structure for a mailbox
133
134 - pathname is the path of the mailbox on the storage
135
136 - virtual_name is the folder identifier, it can be a path,
137 a name or NULL.
138
139 - storage is the storage to which the folder belongs to.
140
141 - session is the session related to the folder. It can be
142 different of the session of the storage.
143
144 - shared_session is != 0 if the session is the same as the
145 session of the storage.
146
147 - pos is the position of the folder in the "shared_folders" field
148 of the storage.
149
150 folders can be chained into a tree.
151
152 - parent is the parent of the folder.
153
154 - sibling_index is the index of the folder in the list of children
155 of the parent.
156
157 - children is the folder.
158*/
159
160struct mailfolder {
161 char * fld_pathname;
162 char * fld_virtual_name;
163
164 struct mailstorage * fld_storage;
165
166 mailsession * fld_session;
167 int fld_shared_session;
168 clistiter * fld_pos;
169
170 struct mailfolder * fld_parent;
171 unsigned int fld_sibling_index;
172 carray * fld_children; /* array of (struct mailfolder *) */
173
174 void * fld_user_data;
175};
176
177/*
178 this is the type of socket connection
179*/
180
181enum {
182 CONNECTION_TYPE_PLAIN, /* when the connection is plain text */
183 CONNECTION_TYPE_STARTTLS, /* when the connection is first plain,
184 then, we want to switch to
185 TLS (secure connection) */
186 CONNECTION_TYPE_TRY_STARTTLS, /* the connection is first plain,
187 then, we will try to switch to TLS */
188 CONNECTION_TYPE_TLS, /* the connection is over TLS */
189 CONNECTION_TYPE_COMMAND, /* the connection is over a shell command */
190 CONNECTION_TYPE_COMMAND_STARTTLS, /* the connection is over a shell
191 command and STARTTLS will be used */
192 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, /* the connection is over
193 a shell command and STARTTLS will
194 be tried */
195 CONNECTION_TYPE_COMMAND_TLS, /* the connection is over a shell
196 command in TLS */
197};
198
199#ifdef __cplusplus
200}
201#endif
202
203#endif
diff --git a/libetpan/src/driver/tools/generic_cache.c b/libetpan/src/driver/tools/generic_cache.c
new file mode 100644
index 0000000..3ff6e43
--- a/dev/null
+++ b/libetpan/src/driver/tools/generic_cache.c
@@ -0,0 +1,729 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "generic_cache.h"
37
38#include "libetpan-config.h"
39
40#include <unistd.h>
41#include <string.h>
42#include <sys/mman.h>
43#include <stdio.h>
44#include <sys/types.h>
45#include <sys/stat.h>
46#include <fcntl.h>
47#include <unistd.h>
48#include <stdlib.h>
49
50#include "maildriver_types.h"
51#include "imfcache.h"
52#include "chash.h"
53#include "mailmessage.h"
54#include "mail_cache_db.h"
55
56int generic_cache_create_dir(char * dirname)
57{
58 struct stat buf;
59 int r;
60
61 r = stat(dirname, &buf);
62 if (r != 0) {
63 r = mkdir(dirname, 0700);
64
65 if (r < 0)
66 return MAIL_ERROR_FILE;
67 }
68 else {
69 if (!S_ISDIR(buf.st_mode))
70 return MAIL_ERROR_FILE;
71 }
72
73 return MAIL_NO_ERROR;
74}
75
76int generic_cache_store(char * filename, char * content, size_t length)
77{
78 int fd;
79 char * str;
80
81 fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
82 if (fd == -1)
83 return MAIL_ERROR_FILE;
84
85 if (ftruncate(fd, length) < 0)
86 return MAIL_ERROR_FILE;
87
88 str = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
89 if (str == MAP_FAILED)
90 return MAIL_ERROR_FILE;
91
92 memcpy(str, content, length);
93 msync(str, length, MS_SYNC);
94 munmap(str, length);
95
96 close(fd);
97
98 return MAIL_NO_ERROR;
99}
100
101int generic_cache_read(char * filename, char ** result, size_t * result_len)
102{
103 int fd;
104 char * str;
105 struct stat buf;
106 MMAPString * mmapstr;
107 char * content;
108 int res;
109
110 if (stat(filename, &buf) < 0) {
111 res = MAIL_ERROR_CACHE_MISS;
112 goto err;
113 }
114
115 fd = open(filename, O_RDONLY);
116 if (fd == -1) {
117 res = MAIL_ERROR_CACHE_MISS;
118 goto err;
119 }
120
121 str = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
122 if (str == MAP_FAILED) {
123 res = MAIL_ERROR_FILE;
124 goto close;
125 }
126
127 mmapstr = mmap_string_new_len(str, buf.st_size);
128 if (mmapstr == NULL) {
129 res = MAIL_ERROR_MEMORY;
130 goto unmap;
131 }
132
133 if (mmap_string_ref(mmapstr) < 0) {
134 res = MAIL_ERROR_MEMORY;
135 goto free;
136 }
137
138 content = mmapstr->str;
139
140 munmap(str, buf.st_size);
141 close(fd);
142
143 * result = content;
144 * result_len = buf.st_size;
145
146 return MAIL_NO_ERROR;
147
148 free:
149 mmap_string_free(mmapstr);
150 unmap:
151 munmap(str, buf.st_size);
152 close:
153 close(fd);
154 err:
155 return res;
156}
157
158static int flags_extension_read(MMAPString * mmapstr, size_t * index,
159 clist ** result)
160{
161 clist * list;
162 int r;
163 uint32_t count;
164 uint32_t i;
165 int res;
166
167 r = mailimf_cache_int_read(mmapstr, index, &count);
168 if (r != MAIL_NO_ERROR) {
169 res = r;
170 goto err;
171 }
172
173 list = clist_new();
174 if (list == NULL) {
175 res = MAIL_ERROR_MEMORY;
176 goto err;
177 }
178
179 for(i = 0 ; i < count ; i++) {
180 char * str;
181
182 r = mailimf_cache_string_read(mmapstr, index, &str);
183 if (r != MAIL_NO_ERROR) {
184 res = r;
185 goto free_list;
186 }
187
188 r = clist_append(list, str);
189 if (r < 0) {
190 free(str);
191 res = MAIL_ERROR_MEMORY;
192 goto free_list;
193 }
194 }
195
196 * result = list;
197
198 return MAIL_NO_ERROR;
199
200 free_list:
201 clist_foreach(list, (clist_func) free, NULL);
202 clist_free(list);
203 err:
204 return res;
205}
206
207static int generic_flags_read(MMAPString * mmapstr, size_t * index,
208 struct mail_flags ** result)
209{
210 clist * ext;
211 int r;
212 struct mail_flags * flags;
213 uint32_t value;
214 int res;
215
216 r = mailimf_cache_int_read(mmapstr, index, &value);
217 if (r != MAIL_NO_ERROR) {
218 res = r;
219 goto err;
220 }
221
222 r = flags_extension_read(mmapstr, index, &ext);
223 if (r != MAIL_NO_ERROR) {
224 res = r;
225 goto err;
226 }
227
228 flags = mail_flags_new(value, ext);
229 if (flags == NULL) {
230 res = r;
231 goto free;
232 }
233
234 * result = flags;
235
236 return MAIL_NO_ERROR;
237
238 free:
239 clist_foreach(ext, (clist_func) free, NULL);
240 clist_free(ext);
241 err:
242 return res;
243}
244
245static int flags_extension_write(MMAPString * mmapstr, size_t * index,
246 clist * ext)
247{
248 int r;
249 clistiter * cur;
250
251 r = mailimf_cache_int_write(mmapstr, index, clist_count(ext));
252 if (r != MAIL_NO_ERROR)
253 return r;
254
255 for(cur = clist_begin(ext) ; cur != NULL ; cur = clist_next(cur)) {
256 r = mailimf_cache_string_write(mmapstr, index,
257 clist_content(cur), strlen(clist_content(cur)));
258 if (r != MAIL_NO_ERROR)
259 return r;
260 }
261
262 return MAIL_NO_ERROR;
263}
264
265static int generic_flags_write(MMAPString * mmapstr, size_t * index,
266 struct mail_flags * flags)
267{
268 int r;
269
270 r = mailimf_cache_int_write(mmapstr, index,
271 flags->fl_flags & ~MAIL_FLAG_NEW);
272 if (r != MAIL_NO_ERROR)
273 return r;
274
275 r = flags_extension_write(mmapstr, index,
276 flags->fl_extension);
277 if (r != MAIL_NO_ERROR)
278 return r;
279
280 return MAIL_NO_ERROR;
281}
282
283
284
285
286static struct mail_flags * mail_flags_dup(struct mail_flags * flags)
287{
288 clist * list;
289 struct mail_flags * new_flags;
290 int r;
291 clistiter * cur;
292
293 list = clist_new();
294 if (list == NULL) {
295 goto err;
296 }
297
298 for(cur = clist_begin(flags->fl_extension) ; cur != NULL ;
299 cur = clist_next(cur)) {
300 char * ext;
301
302 ext = strdup(clist_content(cur));
303 if (ext == NULL) {
304 goto free;
305 }
306
307 r = clist_append(list, ext);
308 if (r < 0) {
309 free(ext);
310 goto free;
311 }
312 }
313
314 new_flags = mail_flags_new(flags->fl_flags, list);
315 if (new_flags == NULL) {
316 goto free;
317 }
318
319 return new_flags;
320
321 free:
322 clist_foreach(list, (clist_func) free, NULL);
323 clist_free(list);
324 err:
325 return NULL;
326}
327
328static mailmessage * mailmessage_build(mailmessage * msg)
329{
330 mailmessage * new_msg;
331
332 new_msg = malloc(sizeof(* new_msg));
333 if (new_msg == NULL)
334 goto err;
335
336 new_msg->msg_session = msg->msg_session;
337 new_msg->msg_driver = msg->msg_driver;
338 new_msg->msg_index = msg->msg_index;
339 if (msg->msg_uid == NULL)
340 new_msg->msg_uid = NULL;
341 else {
342 new_msg->msg_uid = strdup(msg->msg_uid);
343 if (new_msg->msg_uid == NULL)
344 goto free;
345 }
346
347 new_msg->msg_cached = msg->msg_cached;
348 new_msg->msg_size = msg->msg_size;
349 new_msg->msg_fields = NULL;
350 new_msg->msg_flags = mail_flags_dup(msg->msg_flags);
351 if (new_msg->msg_flags == NULL) {
352 free(new_msg->msg_uid);
353 goto free;
354 }
355
356 new_msg->msg_mime = NULL;
357 new_msg->msg_data = NULL;
358
359 return new_msg;
360
361 free:
362 free(new_msg);
363 err:
364 return NULL;
365}
366
367struct mail_flags_store * mail_flags_store_new(void)
368{
369 struct mail_flags_store * flags_store;
370
371 flags_store = malloc(sizeof(struct mail_flags_store));
372 if (flags_store == NULL)
373 goto err;
374
375 flags_store->fls_tab = carray_new(128);
376 if (flags_store->fls_tab == NULL)
377 goto free;
378
379 flags_store->fls_hash = chash_new(128, CHASH_COPYALL);
380 if (flags_store->fls_hash == NULL)
381 goto free_tab;
382
383 return flags_store;
384
385 free_tab:
386 carray_free(flags_store->fls_tab);
387 free:
388 free(flags_store);
389 err:
390 return NULL;
391}
392
393void mail_flags_store_clear(struct mail_flags_store * flags_store)
394{
395 unsigned int i;
396
397 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
398 chashdatum key;
399 mailmessage * msg;
400
401 msg = carray_get(flags_store->fls_tab, i);
402
403 key.data = &msg->msg_index;
404 key.len = sizeof(msg->msg_index);
405 chash_delete(flags_store->fls_hash, &key, NULL);
406
407 mailmessage_free(msg);
408 }
409 carray_set_size(flags_store->fls_tab, 0);
410}
411
412void mail_flags_store_free(struct mail_flags_store * flags_store)
413{
414 mail_flags_store_clear(flags_store);
415 chash_free(flags_store->fls_hash);
416 carray_free(flags_store->fls_tab);
417 free(flags_store);
418}
419
420int mail_flags_store_set(struct mail_flags_store * flags_store,
421 mailmessage * msg)
422{
423 chashdatum key;
424 chashdatum value;
425 unsigned int index;
426 int res;
427 int r;
428 mailmessage * new_msg;
429
430 if (msg->msg_flags == NULL) {
431 res = MAIL_NO_ERROR;
432 goto err;
433 }
434
435 /* duplicate needed message info */
436 new_msg = mailmessage_build(msg);
437 if (new_msg == NULL) {
438 res = MAIL_ERROR_MEMORY;
439 goto err;
440 }
441
442 key.data = &new_msg->msg_index;
443 key.len = sizeof(new_msg->msg_index);
444
445 r = chash_get(flags_store->fls_hash, &key, &value);
446 if (r == 0) {
447 mailmessage * old_msg;
448
449 index = * (unsigned int *) value.data;
450 old_msg = carray_get(flags_store->fls_tab, index);
451 mailmessage_free(old_msg);
452 }
453 else {
454 r = carray_set_size(flags_store->fls_tab,
455 carray_count(flags_store->fls_tab) + 1);
456 if (r != 0) {
457 res = MAIL_ERROR_MEMORY;
458 goto err;
459 }
460 index = carray_count(flags_store->fls_tab) - 1;
461 }
462
463 carray_set(flags_store->fls_tab, index, new_msg);
464
465 value.data = &index;
466 value.len = sizeof(index);
467
468 r = chash_set(flags_store->fls_hash, &key, &value, NULL);
469 if (r < 0) {
470 carray_delete(flags_store->fls_tab, index);
471 res = MAIL_ERROR_MEMORY;
472 goto free;
473 }
474
475 return MAIL_NO_ERROR;
476
477 free:
478 mailmessage_free(new_msg);
479 err:
480 return res;
481}
482
483static int msg_index_compare(mailmessage ** msg1, mailmessage ** msg2)
484{
485 return (* msg1)->msg_index - (* msg2)->msg_index;
486}
487
488void mail_flags_store_sort(struct mail_flags_store * flags_store)
489{
490 qsort(carray_data(flags_store->fls_tab),
491 carray_count(flags_store->fls_tab), sizeof(mailmessage *),
492 (int (*)(const void *, const void *)) msg_index_compare);
493}
494
495struct mail_flags *
496mail_flags_store_get(struct mail_flags_store * flags_store, uint32_t index)
497{
498 struct mail_flags * flags;
499 chashdatum key;
500 chashdatum value;
501 int r;
502 unsigned int tab_index;
503 mailmessage * msg;
504
505 key.data = &index;
506 key.len = sizeof(index);
507
508 r = chash_get(flags_store->fls_hash, &key, &value);
509
510 if (r < 0)
511 return NULL;
512
513#if 0
514 flags = mail_flags_dup((struct mail_flags *) value.data);
515#endif
516 tab_index = * (unsigned int *) value.data;
517 msg = carray_get(flags_store->fls_tab, tab_index);
518 if (msg->msg_flags == NULL)
519 return NULL;
520
521 flags = mail_flags_dup(msg->msg_flags);
522
523 return flags;
524}
525
526int mail_flags_compare(struct mail_flags * flags1, struct mail_flags * flags2)
527{
528 clistiter * cur1;
529
530 if (clist_count(flags1->fl_extension) != clist_count(flags2->fl_extension))
531 return -1;
532
533 for(cur1 = clist_begin(flags1->fl_extension) ; cur1 != NULL ;
534 cur1 = clist_next(cur1)) {
535 char * flag1;
536 clistiter * cur2;
537 int found;
538
539 flag1 = clist_content(cur1);
540
541 found = 0;
542 for(cur2 = clist_begin(flags2->fl_extension) ; cur2 != NULL ;
543 cur2 = clist_next(cur2)) {
544 char * flag2;
545
546 flag2 = clist_content(cur2);
547
548 if (strcasecmp(flag1, flag2) == 0) {
549 found = 1;
550 break;
551 }
552 }
553
554 if (!found)
555 return -1;
556 }
557
558 return flags1->fl_flags - flags2->fl_flags;
559}
560
561
562int generic_cache_fields_read(struct mail_cache_db * cache_db,
563 MMAPString * mmapstr,
564 char * keyname, struct mailimf_fields ** result)
565{
566 int r;
567 int res;
568 size_t cur_token;
569 struct mailimf_fields * fields;
570 void * data;
571 size_t data_len;
572
573 r = mail_cache_db_get(cache_db, keyname, strlen(keyname), &data, &data_len);
574 if (r != 0) {
575 res = MAIL_ERROR_CACHE_MISS;
576 goto err;
577 }
578
579 r = mail_serialize_clear(mmapstr, &cur_token);
580 if (r != MAIL_NO_ERROR) {
581 res = r;
582 goto err;
583 }
584
585 if (mmap_string_append_len(mmapstr, data, data_len) == NULL) {
586 res = MAIL_ERROR_MEMORY;
587 goto err;
588 }
589
590 r = mailimf_cache_fields_read(mmapstr, &cur_token, &fields);
591 if (r != MAIL_NO_ERROR) {
592 res = r;
593 goto err;
594 }
595
596 * result = fields;
597
598 return MAIL_NO_ERROR;
599
600 err:
601 return res;
602}
603
604int generic_cache_fields_write(struct mail_cache_db * cache_db,
605 MMAPString * mmapstr,
606 char * keyname, struct mailimf_fields * fields)
607{
608 int r;
609 int res;
610 size_t cur_token;
611
612 r = mail_serialize_clear(mmapstr, &cur_token);
613 if (r != MAIL_NO_ERROR) {
614 res = r;
615 goto err;
616 }
617
618 r = mailimf_cache_fields_write(mmapstr, &cur_token, fields);
619 if (r != MAIL_NO_ERROR) {
620 res = r;
621 goto err;
622 }
623
624 r = mail_cache_db_put(cache_db, keyname, strlen(keyname),
625 mmapstr->str, mmapstr->len);
626 if (r != 0) {
627 res = MAIL_ERROR_FILE;
628 goto err;
629 }
630
631 return MAIL_NO_ERROR;
632
633 err:
634 return res;
635}
636
637int generic_cache_flags_read(struct mail_cache_db * cache_db,
638 MMAPString * mmapstr,
639 char * keyname, struct mail_flags ** result)
640{
641 int r;
642 int res;
643 size_t cur_token;
644 struct mail_flags * flags;
645 void * data;
646 size_t data_len;
647
648 r = mail_cache_db_get(cache_db, keyname, strlen(keyname), &data, &data_len);
649 if (r != 0) {
650 res = MAIL_ERROR_CACHE_MISS;
651 goto err;
652 }
653
654 r = mail_serialize_clear(mmapstr, &cur_token);
655 if (r != MAIL_NO_ERROR) {
656 res = r;
657 goto err;
658 }
659
660 if (mmap_string_append_len(mmapstr, data, data_len) == NULL) {
661 res = MAIL_ERROR_MEMORY;
662 goto err;
663 }
664
665 r = generic_flags_read(mmapstr, &cur_token, &flags);
666 if (r != MAIL_NO_ERROR) {
667 res = r;
668 goto err;
669 }
670
671 * result = flags;
672
673 return MAIL_NO_ERROR;
674
675 err:
676 return res;
677}
678
679int generic_cache_flags_write(struct mail_cache_db * cache_db,
680 MMAPString * mmapstr,
681 char * keyname, struct mail_flags * flags)
682{
683 int r;
684 int res;
685 size_t cur_token;
686
687 r = mail_serialize_clear(mmapstr, &cur_token);
688 if (r != MAIL_NO_ERROR) {
689 res = r;
690 goto err;
691 }
692
693 r = generic_flags_write(mmapstr, &cur_token, flags);
694 if (r != MAIL_NO_ERROR) {
695 res = r;
696 goto err;
697 }
698
699 r = mail_cache_db_put(cache_db, keyname, strlen(keyname),
700 mmapstr->str, mmapstr->len);
701 if (r != 0) {
702 res = MAIL_ERROR_FILE;
703 goto err;
704 }
705
706 return MAIL_NO_ERROR;
707
708 err:
709 return res;
710}
711
712
713int generic_cache_delete(struct mail_cache_db * cache_db,
714 char * keyname)
715{
716 int r;
717 int res;
718
719 r = mail_cache_db_del(cache_db, keyname, strlen(keyname));
720 if (r != 0) {
721 res = MAIL_ERROR_FILE;
722 goto err;
723 }
724
725 return MAIL_NO_ERROR;
726
727 err:
728 return res;
729}
diff --git a/libetpan/src/driver/tools/generic_cache.h b/libetpan/src/driver/tools/generic_cache.h
new file mode 100644
index 0000000..934a53d
--- a/dev/null
+++ b/libetpan/src/driver/tools/generic_cache.h
@@ -0,0 +1,109 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef GENERIC_CACHE_H
37
38#define GENERIC_CACHE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "generic_cache_types.h"
45#include "mailmessage_types.h"
46#include "chash.h"
47#include "carray.h"
48#include "mail_cache_db_types.h"
49
50int generic_cache_create_dir(char * dirname);
51
52int generic_cache_store(char * filename, char * content, size_t length);
53int generic_cache_read(char * filename, char ** result, size_t * result_len);
54
55int generic_cache_fields_read(struct mail_cache_db * cache_db,
56 MMAPString * mmapstr,
57 char * keyname, struct mailimf_fields ** result);
58
59int generic_cache_fields_write(struct mail_cache_db * cache_db,
60 MMAPString * mmapstr,
61 char * keyname, struct mailimf_fields * fields);
62
63int generic_cache_flags_read(struct mail_cache_db * cache_db,
64 MMAPString * mmapstr,
65 char * keyname, struct mail_flags ** result);
66
67int generic_cache_flags_write(struct mail_cache_db * cache_db,
68 MMAPString * mmapstr,
69 char * keyname, struct mail_flags * flags);
70
71int generic_cache_delete(struct mail_cache_db * cache_db, char * keyname);
72
73#if 0
74int generic_cache_fields_read(DB * dbp, MMAPString * mmapstr,
75 char * keyname, struct mailimf_fields ** result);
76
77int generic_cache_fields_write(DB * dbp, MMAPString * mmapstr,
78 char * keyname, struct mailimf_fields * fields);
79
80int generic_cache_flags_read(DB * dbp, MMAPString * mmapstr,
81 char * keyname, struct mail_flags ** result);
82
83int generic_cache_flags_write(DB * dbp, MMAPString * mmapstr,
84 char * keyname, struct mail_flags * flags);
85
86int generic_cache_delete(DB * dbp, char * keyname);
87#endif
88
89struct mail_flags_store * mail_flags_store_new(void);
90
91void mail_flags_store_clear(struct mail_flags_store * flags_store);
92
93void mail_flags_store_free(struct mail_flags_store * flags_store);
94
95int mail_flags_store_set(struct mail_flags_store * flags_store,
96 mailmessage * msg);
97
98void mail_flags_store_sort(struct mail_flags_store * flags_store);
99
100struct mail_flags *
101mail_flags_store_get(struct mail_flags_store * flags_store, uint32_t index);
102
103int mail_flags_compare(struct mail_flags * flags1, struct mail_flags * flags2);
104
105#ifdef __cplusplus
106}
107#endif
108
109#endif
diff --git a/libetpan/src/driver/tools/generic_cache_types.h b/libetpan/src/driver/tools/generic_cache_types.h
new file mode 100644
index 0000000..bc69b3c
--- a/dev/null
+++ b/libetpan/src/driver/tools/generic_cache_types.h
@@ -0,0 +1,56 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef GENERIC_CACHE_TYPE_H
37
38#define GENERIC_CACHE_TYPE_H
39
40#include <libetpan/carray.h>
41#include <libetpan/chash.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47struct mail_flags_store {
48 carray * fls_tab;
49 chash * fls_hash;
50};
51
52#ifdef __cplusplus
53}
54#endif
55
56#endif
diff --git a/libetpan/src/driver/tools/imfcache.c b/libetpan/src/driver/tools/imfcache.c
new file mode 100644
index 0000000..7c6a5be
--- a/dev/null
+++ b/libetpan/src/driver/tools/imfcache.c
@@ -0,0 +1,1429 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imfcache.h"
37
38#include <stdlib.h>
39#include <string.h>
40
41static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * index,
42 struct mailimf_field * field);
43static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * index,
44 struct mailimf_orig_date * date);
45static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * index,
46 struct mailimf_date_time * date_time);
47static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * index,
48 struct mailimf_from * from);
49static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * index,
50 struct mailimf_sender * sender);
51static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * index,
52 struct mailimf_reply_to * reply_to);
53static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * index,
54 struct mailimf_to * to);
55static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * index,
56 struct mailimf_cc * to);
57static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * index,
58 struct mailimf_bcc * to);
59static int mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * index,
60 struct mailimf_message_id * message_id);
61static int mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * index,
62 clist * list);
63static int mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * index,
64 struct mailimf_in_reply_to *
65 in_reply_to);
66static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * index,
67 struct mailimf_references * references);
68static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * index,
69 struct mailimf_subject * subject);
70static int mailimf_cache_address_list_write(MMAPString * mmapstr,
71 size_t * index,
72 struct mailimf_address_list *
73 addr_list);
74static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * index,
75 struct mailimf_address * addr);
76static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * index,
77 struct mailimf_group * group);
78static int mailimf_cache_mailbox_list_write(MMAPString * mmapstr,
79 size_t * index,
80 struct mailimf_mailbox_list * mb_list);
81static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * index,
82 struct mailimf_mailbox * mb);
83
84
85static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * index,
86 struct mailimf_field ** result);
87static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * index,
88 struct mailimf_orig_date ** result);
89static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * index,
90 struct mailimf_date_time ** result);
91static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * index,
92 struct mailimf_from ** result);
93static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * index,
94 struct mailimf_sender ** result);
95static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * index,
96 struct mailimf_reply_to ** result);
97static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * index,
98 struct mailimf_to ** result);
99static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * index,
100 struct mailimf_cc ** result);
101static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * index,
102 struct mailimf_bcc ** result);
103static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * index,
104 struct mailimf_message_id ** result);
105static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * index,
106 clist ** result);
107static int
108mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * index,
109 struct mailimf_in_reply_to ** result);
110
111static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * index,
112 struct mailimf_references ** result);
113static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * index,
114 struct mailimf_subject ** result);
115static int mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * index,
116 struct mailimf_address_list ** result);
117static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * index,
118 struct mailimf_address ** result);
119static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * index,
120 struct mailimf_group ** result);
121static int
122mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * index,
123 struct mailimf_mailbox_list ** result);
124static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * index,
125 struct mailimf_mailbox ** result);
126
127enum {
128 CACHE_NULL_POINTER = 0,
129 CACHE_NOT_NULL = 1,
130};
131
132int mail_serialize_clear(MMAPString * mmapstr, size_t * index)
133{
134 if (mmap_string_set_size(mmapstr, 0) == NULL)
135 return MAIL_ERROR_MEMORY;
136
137 * index = 0;
138
139 return MAIL_NO_ERROR;
140}
141
142int mail_serialize_write(MMAPString * mmapstr, size_t * index,
143 char * buf, size_t size)
144{
145 if (mmap_string_append_len(mmapstr, buf, size) == NULL)
146 return MAIL_ERROR_MEMORY;
147
148 * index = * index + size;
149
150 return MAIL_NO_ERROR;
151}
152
153int mail_serialize_read(MMAPString * mmapstr, size_t * index,
154 char * buf, size_t size)
155{
156 size_t cur_token;
157
158 cur_token = * index;
159
160 if (cur_token + size > mmapstr->len)
161 return MAIL_ERROR_STREAM;
162
163 memcpy(buf, mmapstr->str + cur_token, size);
164 * index = cur_token + size;
165
166 return MAIL_NO_ERROR;
167}
168
169int mailimf_cache_int_write(MMAPString * mmapstr, size_t * index,
170 uint32_t value)
171{
172 unsigned char ch;
173 int r;
174 int i;
175
176 for(i = 0 ; i < 4 ; i ++) {
177 ch = value % 256;
178
179 r = mail_serialize_write(mmapstr, index, &ch, 1);
180 if (r != MAIL_NO_ERROR)
181 return r;
182 value /= 256;
183 }
184
185 return MAIL_NO_ERROR;
186}
187
188int mailimf_cache_int_read(MMAPString * mmapstr, size_t * index,
189 uint32_t * result)
190{
191 unsigned char ch;
192 uint32_t value;
193 int i;
194 int r;
195
196 value = 0;
197 for(i = 0 ; i < 4 ; i ++) {
198 r = mail_serialize_read(mmapstr, index, &ch, 1);
199 if (r != MAIL_NO_ERROR)
200 return r;
201 value = value | ch << (i << 3);
202 }
203
204 * result = value;
205
206 return MAIL_NO_ERROR;
207}
208
209
210int mailimf_cache_string_write(MMAPString * mmapstr, size_t * index,
211 char * str, size_t length)
212{
213 int r;
214
215 if (str == NULL) {
216 r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER);
217 if (r != MAIL_NO_ERROR)
218 return r;
219 }
220 else {
221 r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL);
222 if (r != MAIL_NO_ERROR)
223 return r;
224
225 r = mailimf_cache_int_write(mmapstr, index, length);
226 if (r != MAIL_NO_ERROR)
227 return r;
228
229 if (length != 0) {
230 r = mail_serialize_write(mmapstr, index, str, length);
231 if (r != MAIL_NO_ERROR)
232 return MAIL_ERROR_FILE;
233 }
234 }
235
236 return MAIL_NO_ERROR;
237}
238
239int mailimf_cache_string_read(MMAPString * mmapstr, size_t * index,
240 char ** result)
241{
242 int r;
243 uint32_t length;
244 char * str;
245 uint32_t type;
246
247 r = mailimf_cache_int_read(mmapstr, index, &type);
248 if (r != MAIL_NO_ERROR)
249 return r;
250
251 if (type == CACHE_NULL_POINTER) {
252 str = NULL;
253 }
254 else {
255 r = mailimf_cache_int_read(mmapstr, index, &length);
256 if (r != MAIL_NO_ERROR)
257 return r;
258
259 str = malloc(length + 1);
260 if (str == NULL)
261 return MAIL_ERROR_MEMORY;
262
263 r = mail_serialize_read(mmapstr, index, str, length);
264 if (r != MAIL_NO_ERROR)
265 return MAIL_ERROR_FILE;
266
267 str[length] = 0;
268 }
269
270 * result = str;
271
272 return MAIL_NO_ERROR;
273}
274
275int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * index,
276 struct mailimf_fields * fields)
277{
278 clistiter * cur;
279 int r;
280
281 r = mailimf_cache_int_write(mmapstr, index,
282 clist_count(fields->fld_list));
283 if (r != MAIL_NO_ERROR)
284 return r;
285
286 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
287 cur = clist_next(cur)) {
288 r = mailimf_cache_field_write(mmapstr, index, clist_content(cur));
289 if (r != MAIL_NO_ERROR)
290 return r;
291 }
292
293 return MAIL_NO_ERROR;
294}
295
296int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * index,
297 struct mailimf_fields ** result)
298{
299 clist * list;
300 int r;
301 uint32_t count;
302 uint32_t i;
303 struct mailimf_fields * fields;
304 int res;
305
306 r = mailimf_cache_int_read(mmapstr, index, &count);
307 if (r != MAIL_NO_ERROR) {
308 res = r;
309 goto err;
310 }
311
312 list = clist_new();
313 if (list == NULL) {
314 res = MAIL_ERROR_MEMORY;
315 goto err;
316 }
317
318 for(i = 0 ; i < count ; i++) {
319 struct mailimf_field * field;
320
321 r = mailimf_cache_field_read(mmapstr, index, &field);
322 if (r != MAIL_NO_ERROR) {
323 res = r;
324 goto free_list;
325 }
326
327 r = clist_append(list, field);
328 if (r < 0) {
329 mailimf_field_free(field);
330 res = MAIL_ERROR_MEMORY;
331 goto free_list;
332 }
333 }
334
335 fields = mailimf_fields_new(list);
336 if (fields == NULL) {
337 res = MAIL_ERROR_MEMORY;
338 goto free_list;
339 }
340
341 * result = fields;
342
343 return MAIL_NO_ERROR;
344
345 free_list:
346 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
347 clist_free(list);
348 err:
349 return res;
350}
351
352
353static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * index,
354 struct mailimf_field * field)
355{
356 int r;
357
358 r = mailimf_cache_int_write(mmapstr, index, field->fld_type);
359 if (r != MAIL_NO_ERROR)
360 return r;
361
362 switch (field->fld_type) {
363 case MAILIMF_FIELD_ORIG_DATE:
364 r = mailimf_cache_orig_date_write(mmapstr, index,
365 field->fld_data.fld_orig_date);
366 break;
367 case MAILIMF_FIELD_FROM:
368 r = mailimf_cache_from_write(mmapstr, index,
369 field->fld_data.fld_from);
370 break;
371 case MAILIMF_FIELD_SENDER:
372 r = mailimf_cache_sender_write(mmapstr, index,
373 field->fld_data.fld_sender);
374 break;
375 case MAILIMF_FIELD_REPLY_TO:
376 r = mailimf_cache_reply_to_write(mmapstr, index,
377 field->fld_data.fld_reply_to);
378 break;
379 case MAILIMF_FIELD_TO:
380 r = mailimf_cache_to_write(mmapstr, index,
381 field->fld_data.fld_to);
382 break;
383 case MAILIMF_FIELD_CC:
384 r = mailimf_cache_cc_write(mmapstr, index,
385 field->fld_data.fld_cc);
386 break;
387 case MAILIMF_FIELD_BCC:
388 r = mailimf_cache_bcc_write(mmapstr, index,
389 field->fld_data.fld_bcc);
390 break;
391 case MAILIMF_FIELD_MESSAGE_ID:
392 r = mailimf_cache_message_id_write(mmapstr, index,
393 field->fld_data.fld_message_id);
394 break;
395 case MAILIMF_FIELD_IN_REPLY_TO:
396 r = mailimf_cache_in_reply_to_write(mmapstr, index,
397 field->fld_data.fld_in_reply_to);
398 break;
399 case MAILIMF_FIELD_REFERENCES:
400 r = mailimf_cache_references_write(mmapstr, index,
401 field->fld_data.fld_references);
402 break;
403 case MAILIMF_FIELD_SUBJECT:
404 r = mailimf_cache_subject_write(mmapstr, index,
405 field->fld_data.fld_subject);
406 break;
407 default:
408 r = 0;
409 break;
410 }
411
412 if (r != MAIL_NO_ERROR)
413 return r;
414
415 return MAIL_NO_ERROR;
416}
417
418
419static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * index,
420 struct mailimf_field ** result)
421{
422 int r;
423 uint32_t type;
424 struct mailimf_orig_date * orig_date;
425 struct mailimf_from * from;
426 struct mailimf_sender * sender;
427 struct mailimf_to * to;
428 struct mailimf_reply_to * reply_to;
429 struct mailimf_cc * cc;
430 struct mailimf_bcc * bcc;
431 struct mailimf_message_id * message_id;
432 struct mailimf_in_reply_to * in_reply_to;
433 struct mailimf_references * references;
434 struct mailimf_subject * subject;
435 struct mailimf_field * field;
436 int res;
437
438 orig_date = NULL;
439 from = NULL;
440 sender = NULL;
441 to = NULL;
442 reply_to = NULL;
443 cc = NULL;
444 bcc = NULL;
445 message_id = NULL;
446 in_reply_to = NULL;
447 references = NULL;
448 subject = NULL;
449 field = NULL;
450
451 r = mailimf_cache_int_read(mmapstr, index, &type);
452 if (r != MAIL_NO_ERROR) {
453 res = r;
454 goto err;
455 }
456
457 switch (type) {
458 case MAILIMF_FIELD_ORIG_DATE:
459 r = mailimf_cache_orig_date_read(mmapstr, index, &orig_date);
460 break;
461 case MAILIMF_FIELD_FROM:
462 r = mailimf_cache_from_read(mmapstr, index, &from);
463 break;
464 case MAILIMF_FIELD_SENDER:
465 r = mailimf_cache_sender_read(mmapstr, index, &sender);
466 break;
467 case MAILIMF_FIELD_REPLY_TO:
468 r = mailimf_cache_reply_to_read(mmapstr, index, &reply_to);
469 break;
470 case MAILIMF_FIELD_TO:
471 r = mailimf_cache_to_read(mmapstr, index, &to);
472 break;
473 case MAILIMF_FIELD_CC:
474 r = mailimf_cache_cc_read(mmapstr, index, &cc);
475 break;
476 case MAILIMF_FIELD_BCC:
477 r = mailimf_cache_bcc_read(mmapstr, index, &bcc);
478 break;
479 case MAILIMF_FIELD_MESSAGE_ID:
480 r = mailimf_cache_message_id_read(mmapstr, index, &message_id);
481 break;
482 case MAILIMF_FIELD_IN_REPLY_TO:
483 r = mailimf_cache_in_reply_to_read(mmapstr, index, &in_reply_to);
484 break;
485 case MAILIMF_FIELD_REFERENCES:
486 r = mailimf_cache_references_read(mmapstr, index, &references);
487 break;
488 case MAILIMF_FIELD_SUBJECT:
489 r = mailimf_cache_subject_read(mmapstr, index, &subject);
490 break;
491 default:
492 r = MAIL_ERROR_INVAL;
493 break;
494 }
495
496 if (r != MAIL_NO_ERROR) {
497 res = r;
498 goto free;
499 }
500
501 field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
502 NULL, NULL, NULL, orig_date, from, sender, reply_to,
503 to, cc, bcc, message_id,
504 in_reply_to, references,
505 subject, NULL, NULL, NULL);
506 if (field == NULL) {
507 res = MAIL_ERROR_MEMORY;
508 goto free;
509 }
510
511 * result = field;
512
513 return MAIL_NO_ERROR;
514
515 free:
516 if (orig_date != NULL)
517 mailimf_orig_date_free(orig_date);
518 if (from != NULL)
519 mailimf_from_free(from);
520 if (sender != NULL)
521 mailimf_sender_free(sender);
522 if (reply_to != NULL)
523 mailimf_reply_to_free(reply_to);
524 if (to != NULL)
525 mailimf_to_free(to);
526 if (cc != NULL)
527 mailimf_cc_free(cc);
528 if (bcc != NULL)
529 mailimf_bcc_free(bcc);
530 if (message_id != NULL)
531 mailimf_message_id_free(message_id);
532 if (in_reply_to != NULL)
533 mailimf_in_reply_to_free(in_reply_to);
534 if (references != NULL)
535 mailimf_references_free(references);
536 if (subject != NULL)
537 mailimf_subject_free(subject);
538 err:
539 return res;
540}
541
542static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * index,
543 struct mailimf_orig_date * date)
544{
545 return mailimf_cache_date_time_write(mmapstr, index, date->dt_date_time);
546}
547
548static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * index,
549 struct mailimf_orig_date ** result)
550{
551 int r;
552 struct mailimf_date_time * date_time;
553 struct mailimf_orig_date * orig_date;
554
555 r = mailimf_cache_date_time_read(mmapstr, index, &date_time);
556 if (r != MAIL_NO_ERROR)
557 return r;
558
559 orig_date = mailimf_orig_date_new(date_time);
560 if (orig_date == NULL) {
561 mailimf_date_time_free(date_time);
562 return MAIL_ERROR_MEMORY;
563 }
564
565 * result = orig_date;
566
567 return MAIL_NO_ERROR;
568}
569
570static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * index,
571 struct mailimf_date_time * date_time)
572{
573 int r;
574
575 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_day);
576 if (r != MAIL_NO_ERROR)
577 return r;
578
579 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_month);
580 if (r != MAIL_NO_ERROR)
581 return r;
582
583 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_year);
584 if (r != MAIL_NO_ERROR)
585 return r;
586
587 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_hour);
588 if (r != MAIL_NO_ERROR)
589 return r;
590
591 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_min);
592 if (r != MAIL_NO_ERROR)
593 return r;
594
595 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_sec);
596 if (r != MAIL_NO_ERROR)
597 return r;
598
599 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_zone);
600 if (r != MAIL_NO_ERROR)
601 return r;
602
603 return MAIL_NO_ERROR;
604}
605
606static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * index,
607 struct mailimf_date_time ** result)
608{
609 int r;
610 uint32_t day;
611 uint32_t month;
612 uint32_t year;
613 uint32_t hour;
614 uint32_t min;
615 uint32_t sec;
616 uint32_t zone;
617 struct mailimf_date_time * date_time;
618
619 r = mailimf_cache_int_read(mmapstr, index, &day);
620 if (r != MAIL_NO_ERROR)
621 return r;
622
623 r = mailimf_cache_int_read(mmapstr, index, &month);
624 if (r != MAIL_NO_ERROR)
625 return r;
626
627 r = mailimf_cache_int_read(mmapstr, index, &year);
628 if (r != MAIL_NO_ERROR)
629 return r;
630
631 r = mailimf_cache_int_read(mmapstr, index, &hour);
632 if (r != MAIL_NO_ERROR)
633 return r;
634
635 r = mailimf_cache_int_read(mmapstr, index, &min);
636 if (r != MAIL_NO_ERROR)
637 return r;
638
639 r = mailimf_cache_int_read(mmapstr, index, &sec);
640 if (r != MAIL_NO_ERROR)
641 return r;
642
643 r = mailimf_cache_int_read(mmapstr, index, &zone);
644 if (r != MAIL_NO_ERROR)
645 return r;
646
647 date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone);
648 if (date_time == NULL)
649 return MAIL_ERROR_MEMORY;
650
651 * result = date_time;
652
653 return MAIL_NO_ERROR;
654
655}
656
657
658static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * index,
659 struct mailimf_from * from)
660{
661 return mailimf_cache_mailbox_list_write(mmapstr, index, from->frm_mb_list);
662}
663
664static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * index,
665 struct mailimf_from ** result)
666{
667 struct mailimf_mailbox_list * mb_list;
668 struct mailimf_from * from;
669 int r;
670
671 r = mailimf_cache_mailbox_list_read(mmapstr, index, &mb_list);
672 if (r != MAIL_NO_ERROR)
673 return r;
674
675 from = mailimf_from_new(mb_list);
676 if (from == NULL) {
677 mailimf_mailbox_list_free(mb_list);
678 return MAIL_ERROR_MEMORY;
679 }
680
681 * result = from;
682
683 return MAIL_NO_ERROR;
684}
685
686static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * index,
687 struct mailimf_sender * sender)
688{
689 return mailimf_cache_mailbox_write(mmapstr, index, sender->snd_mb);
690}
691
692static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * index,
693 struct mailimf_sender ** result)
694{
695 int r;
696 struct mailimf_mailbox * mb;
697 struct mailimf_sender * sender;
698
699 r = mailimf_cache_mailbox_read(mmapstr, index, &mb);
700 if (r != MAIL_NO_ERROR)
701 return r;
702
703 sender = mailimf_sender_new(mb);
704 if (sender == NULL) {
705 mailimf_mailbox_free(mb);
706 return MAIL_ERROR_MEMORY;
707 }
708
709 * result = sender;
710
711 return MAIL_NO_ERROR;
712}
713
714static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * index,
715 struct mailimf_reply_to * reply_to)
716{
717 return mailimf_cache_address_list_write(mmapstr, index,
718 reply_to->rt_addr_list);
719}
720
721static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * index,
722 struct mailimf_reply_to ** result)
723{
724 int r;
725 struct mailimf_address_list * addr_list;
726 struct mailimf_reply_to * reply_to;
727
728 r = mailimf_cache_address_list_read(mmapstr, index, &addr_list);
729 if (r != MAIL_NO_ERROR)
730 return r;
731
732 reply_to = mailimf_reply_to_new(addr_list);
733 if (reply_to == NULL) {
734 mailimf_address_list_free(addr_list);
735 return MAIL_ERROR_MEMORY;
736 }
737
738 * result = reply_to;
739
740 return MAIL_NO_ERROR;
741}
742
743static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * index,
744 struct mailimf_to * to)
745{
746 return mailimf_cache_address_list_write(mmapstr, index, to->to_addr_list);
747}
748
749static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * index,
750 struct mailimf_to ** result)
751{
752 int r;
753 struct mailimf_address_list * addr_list;
754 struct mailimf_to * to;
755
756 r = mailimf_cache_address_list_read(mmapstr, index, &addr_list);
757 if (r != MAIL_NO_ERROR)
758 return r;
759
760 to = mailimf_to_new(addr_list);
761 if (to == NULL) {
762 mailimf_address_list_free(addr_list);
763 return MAIL_ERROR_MEMORY;
764 }
765
766 * result = to;
767
768 return MAIL_NO_ERROR;
769}
770
771static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * index,
772 struct mailimf_cc * cc)
773{
774 return mailimf_cache_address_list_write(mmapstr, index, cc->cc_addr_list);
775}
776
777static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * index,
778 struct mailimf_cc ** result)
779{
780 int r;
781 struct mailimf_address_list * addr_list;
782 struct mailimf_cc * cc;
783
784 r = mailimf_cache_address_list_read(mmapstr, index, &addr_list);
785 if (r != MAIL_NO_ERROR)
786 return r;
787
788 cc = mailimf_cc_new(addr_list);
789 if (cc == NULL) {
790 mailimf_address_list_free(addr_list);
791 return MAIL_ERROR_MEMORY;
792 }
793
794 * result = cc;
795
796 return MAIL_NO_ERROR;
797}
798
799static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * index,
800 struct mailimf_bcc * bcc)
801{
802 return mailimf_cache_address_list_write(mmapstr, index, bcc->bcc_addr_list);
803}
804
805static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * index,
806 struct mailimf_bcc ** result)
807{
808 int r;
809 struct mailimf_address_list * addr_list;
810 struct mailimf_bcc * bcc;
811
812 r = mailimf_cache_address_list_read(mmapstr, index, &addr_list);
813 if (r != MAIL_NO_ERROR)
814 return r;
815
816 bcc = mailimf_bcc_new(addr_list);
817 if (bcc == NULL) {
818 mailimf_address_list_free(addr_list);
819 return MAIL_ERROR_MEMORY;
820 }
821
822 * result = bcc;
823
824 return MAIL_NO_ERROR;
825}
826
827static int
828mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * index,
829 struct mailimf_message_id * message_id)
830{
831 return mailimf_cache_string_write(mmapstr, index,
832 message_id->mid_value, strlen(message_id->mid_value));
833}
834
835static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * index,
836 struct mailimf_message_id ** result)
837{
838 struct mailimf_message_id * message_id;
839 char * str;
840 int r;
841
842 r = mailimf_cache_string_read(mmapstr, index, &str);
843 if (r != MAIL_NO_ERROR)
844 return r;
845
846 message_id = mailimf_message_id_new(str);
847 if (message_id == NULL) {
848 free(str);
849 return MAIL_ERROR_MEMORY;
850 }
851
852 * result = message_id;
853
854 return MAIL_NO_ERROR;
855}
856
857static int
858mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * index,
859 clist * list)
860{
861 clistiter * cur;
862 int r;
863
864 r = mailimf_cache_int_write(mmapstr, index, clist_count(list));
865 if (r != MAIL_NO_ERROR)
866 return r;
867
868 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
869 char * msgid;
870
871 msgid = clist_content(cur);
872
873 r = mailimf_cache_string_write(mmapstr, index, msgid, strlen(msgid));
874 if (r != MAIL_NO_ERROR)
875 return r;
876 }
877
878 return MAIL_NO_ERROR;
879}
880
881static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * index,
882 clist ** result)
883{
884 clist * list;
885 int r;
886 uint32_t count;
887 uint32_t i;
888 int res;
889
890 r = mailimf_cache_int_read(mmapstr, index, &count);
891 if (r != MAIL_NO_ERROR) {
892 res = r;
893 goto err;
894 }
895
896 list = clist_new();
897 if (list == NULL) {
898 res = MAIL_ERROR_MEMORY;
899 goto err;
900 }
901
902 for(i = 0 ; i < count ; i++) {
903 char * msgid;
904
905 r = mailimf_cache_string_read(mmapstr, index, &msgid);
906 if (r != MAIL_NO_ERROR) {
907 res = r;
908 goto err;
909 }
910
911 r = clist_append(list, msgid);
912 if (r < 0) {
913 free(msgid);
914 res = MAIL_ERROR_MEMORY;
915 goto free_list;
916 }
917 }
918
919 * result = list;
920
921 return MAIL_NO_ERROR;
922
923 free_list:
924 clist_foreach(list, (clist_func) free, NULL);
925 clist_free(list);
926 err:
927 return res;
928}
929
930static int
931mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * index,
932 struct mailimf_in_reply_to * in_reply_to)
933{
934 return mailimf_cache_msg_id_list_write(mmapstr, index,
935 in_reply_to->mid_list);
936}
937
938static int mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * index,
939 struct mailimf_in_reply_to ** result)
940{
941 int r;
942 clist * msg_id_list;
943 struct mailimf_in_reply_to * in_reply_to;
944
945 r = mailimf_cache_msg_id_list_read(mmapstr, index, &msg_id_list);
946 if (r != MAIL_NO_ERROR)
947 return r;
948
949 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
950 if (in_reply_to == NULL) {
951 clist_foreach(msg_id_list, (clist_func) free, NULL);
952 clist_free(msg_id_list);
953 return MAIL_ERROR_MEMORY;
954 }
955
956 * result = in_reply_to;
957
958 return MAIL_NO_ERROR;
959}
960
961static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * index,
962 struct mailimf_references * references)
963{
964 return mailimf_cache_msg_id_list_write(mmapstr, index,
965 references->mid_list);
966}
967
968static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * index,
969 struct mailimf_references ** result)
970{
971 int r;
972 clist * msg_id_list;
973 struct mailimf_references * references;
974
975 r = mailimf_cache_msg_id_list_read(mmapstr, index, &msg_id_list);
976 if (r != MAIL_NO_ERROR)
977 return r;
978
979 references = mailimf_references_new(msg_id_list);
980 if (references == NULL) {
981 clist_foreach(msg_id_list, (clist_func) free, NULL);
982 clist_free(msg_id_list);
983 return MAIL_ERROR_MEMORY;
984 }
985
986 * result = references;
987
988 return MAIL_NO_ERROR;
989}
990
991
992static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * index,
993 struct mailimf_subject * subject)
994{
995 return mailimf_cache_string_write(mmapstr, index,
996 subject->sbj_value, strlen(subject->sbj_value));
997}
998
999static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * index,
1000 struct mailimf_subject ** result)
1001{
1002 char * str;
1003 struct mailimf_subject * subject;
1004 int r;
1005
1006 r = mailimf_cache_string_read(mmapstr, index, &str);
1007 if (r != MAIL_NO_ERROR)
1008 return r;
1009
1010 if (str == NULL) {
1011 str = strdup("");
1012 if (str == NULL)
1013 return MAIL_ERROR_MEMORY;
1014 }
1015
1016 subject = mailimf_subject_new(str);
1017 if (subject == NULL) {
1018 free(str);
1019 return MAIL_ERROR_MEMORY;
1020 }
1021
1022 * result = subject;
1023
1024 return MAIL_NO_ERROR;
1025}
1026
1027
1028static int
1029mailimf_cache_address_list_write(MMAPString * mmapstr, size_t * index,
1030 struct mailimf_address_list * addr_list)
1031{
1032 clistiter * cur;
1033 int r;
1034
1035 if (addr_list == NULL) {
1036 r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER);
1037 if (r != MAIL_NO_ERROR)
1038 return r;
1039 }
1040 else {
1041 r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL);
1042 if (r != MAIL_NO_ERROR)
1043 return r;
1044
1045 r = mailimf_cache_int_write(mmapstr, index,
1046 clist_count(addr_list->ad_list));
1047 if (r != MAIL_NO_ERROR)
1048 return r;
1049
1050 for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
1051 cur = clist_next(cur)) {
1052 struct mailimf_address * addr;
1053
1054 addr = clist_content(cur);
1055
1056 r = mailimf_cache_address_write(mmapstr, index, addr);
1057 if (r != MAIL_NO_ERROR)
1058 return r;
1059 }
1060 }
1061
1062 return MAIL_NO_ERROR;
1063}
1064
1065static int
1066mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * index,
1067 struct mailimf_address_list ** result)
1068{
1069 struct mailimf_address_list * addr_list;
1070 uint32_t count;
1071 uint32_t i;
1072 int r;
1073 clist * list;
1074 int res;
1075 uint32_t type;
1076
1077 r = mailimf_cache_int_read(mmapstr, index, &type);
1078 if (r != MAIL_NO_ERROR) {
1079 res = r;
1080 goto err;
1081 }
1082
1083 if (type == CACHE_NULL_POINTER) {
1084 * result = NULL;
1085 return MAIL_NO_ERROR;
1086 }
1087
1088 r = mailimf_cache_int_read(mmapstr, index, &count);
1089 if (r != MAIL_NO_ERROR) {
1090 res = r;
1091 goto err;
1092 }
1093
1094 list = clist_new();
1095 if (list == NULL) {
1096 res = MAIL_ERROR_MEMORY;
1097 goto err;
1098 }
1099
1100 for(i = 0 ; i < count ; i++) {
1101 struct mailimf_address * addr;
1102
1103 r = mailimf_cache_address_read(mmapstr, index, &addr);
1104 if (r != MAIL_NO_ERROR) {
1105 res = r;
1106 goto free_list;
1107 }
1108
1109 r = clist_append(list, addr);
1110 if (r < 0) {
1111 mailimf_address_free(addr);
1112 res = MAIL_ERROR_MEMORY;
1113 goto free_list;
1114 }
1115 }
1116
1117 addr_list = mailimf_address_list_new(list);
1118 if (addr_list == NULL) {
1119 res = MAIL_ERROR_MEMORY;
1120 goto free_list;
1121 }
1122
1123 * result = addr_list;
1124
1125 return MAIL_NO_ERROR;
1126
1127 free_list:
1128 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
1129 clist_free(list);
1130 err:
1131 return res;
1132}
1133
1134static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * index,
1135 struct mailimf_address * addr)
1136{
1137 int r;
1138
1139 r = mailimf_cache_int_write(mmapstr, index, addr->ad_type);
1140 if (r != MAIL_NO_ERROR)
1141 return r;
1142
1143 switch(addr->ad_type) {
1144 case MAILIMF_ADDRESS_MAILBOX:
1145 r = mailimf_cache_mailbox_write(mmapstr, index, addr->ad_data.ad_mailbox);
1146 if (r != MAIL_NO_ERROR)
1147 return r;
1148
1149 break;
1150
1151 case MAILIMF_ADDRESS_GROUP:
1152 r = mailimf_cache_group_write(mmapstr, index, addr->ad_data.ad_group);
1153 if (r != MAIL_NO_ERROR)
1154 return r;
1155
1156 break;
1157 }
1158
1159 return MAIL_NO_ERROR;
1160}
1161
1162static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * index,
1163 struct mailimf_address ** result)
1164{
1165 uint32_t type;
1166 int r;
1167 struct mailimf_mailbox * mailbox;
1168 struct mailimf_group * group;
1169 struct mailimf_address * addr;
1170
1171 r = mailimf_cache_int_read(mmapstr, index, &type);
1172 if (r != MAIL_NO_ERROR)
1173 return r;
1174
1175 mailbox = NULL;
1176 group = NULL;
1177
1178 switch (type) {
1179 case MAILIMF_ADDRESS_MAILBOX:
1180 r = mailimf_cache_mailbox_read(mmapstr, index, &mailbox);
1181 if (r != MAIL_NO_ERROR)
1182 return r;
1183
1184 break;
1185
1186 case MAILIMF_ADDRESS_GROUP:
1187 r = mailimf_cache_group_read(mmapstr, index, &group);
1188 if (r != MAIL_NO_ERROR)
1189 return r;
1190
1191 break;
1192 }
1193
1194 addr = mailimf_address_new(type, mailbox, group);
1195 if (addr == NULL)
1196 goto free;
1197
1198 * result = addr;
1199
1200 return MAIL_NO_ERROR;
1201
1202 free:
1203 if (mailbox != NULL)
1204 mailimf_mailbox_free(mailbox);
1205 if (group != NULL)
1206 mailimf_group_free(group);
1207 return MAIL_ERROR_MEMORY;
1208}
1209
1210static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * index,
1211 struct mailimf_group * group)
1212{
1213 int r;
1214
1215 r = mailimf_cache_string_write(mmapstr, index, group->grp_display_name,
1216 strlen(group->grp_display_name));
1217 if (r != MAIL_NO_ERROR)
1218 return r;
1219
1220 r = mailimf_cache_mailbox_list_write(mmapstr, index, group->grp_mb_list);
1221 if (r != MAIL_NO_ERROR)
1222 return r;
1223
1224 return MAIL_NO_ERROR;
1225}
1226
1227static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * index,
1228 struct mailimf_group ** result)
1229{
1230 int r;
1231 char * display_name;
1232 struct mailimf_mailbox_list * mb_list;
1233 struct mailimf_group * group;
1234 int res;
1235
1236 r = mailimf_cache_string_read(mmapstr, index, &display_name);
1237 if (r != MAIL_NO_ERROR) {
1238 res = r;
1239 goto err;
1240 }
1241
1242 r = mailimf_cache_mailbox_list_read(mmapstr, index, &mb_list);
1243 if (r != MAIL_NO_ERROR) {
1244 res = r;
1245 goto free_dsp_name;
1246 }
1247
1248 group = mailimf_group_new(display_name, mb_list);
1249 if (group == NULL) {
1250 res = MAIL_ERROR_MEMORY;
1251 goto free_mb_list;
1252 }
1253
1254 * result = group;
1255
1256 return MAIL_NO_ERROR;
1257
1258 free_mb_list:
1259 mailimf_mailbox_list_free(mb_list);
1260 free_dsp_name:
1261 free(display_name);
1262 err:
1263 return res;
1264}
1265
1266static int
1267mailimf_cache_mailbox_list_write(MMAPString * mmapstr, size_t * index,
1268 struct mailimf_mailbox_list * mb_list)
1269{
1270 clistiter * cur;
1271 int r;
1272
1273 if (mb_list == NULL) {
1274 r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER);
1275 if (r != MAIL_NO_ERROR)
1276 return r;
1277 }
1278 else {
1279 r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL);
1280 if (r != MAIL_NO_ERROR)
1281 return r;
1282
1283 r = mailimf_cache_int_write(mmapstr, index,
1284 clist_count(mb_list->mb_list));
1285 if (r != MAIL_NO_ERROR)
1286 return r;
1287
1288 for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
1289 cur = clist_next(cur)) {
1290 struct mailimf_mailbox * mb;
1291
1292 mb = clist_content(cur);
1293
1294 r = mailimf_cache_mailbox_write(mmapstr, index, mb);
1295 if (r != MAIL_NO_ERROR)
1296 return r;
1297 }
1298 }
1299
1300 return MAIL_NO_ERROR;
1301}
1302
1303static int
1304mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * index,
1305 struct mailimf_mailbox_list ** result)
1306{
1307 clist * list;
1308 int r;
1309 uint32_t count;
1310 uint32_t i;
1311 struct mailimf_mailbox_list * mb_list;
1312 int res;
1313 uint32_t type;
1314
1315 r = mailimf_cache_int_read(mmapstr, index, &type);
1316 if (r != MAIL_NO_ERROR) {
1317 res = r;
1318 goto err;
1319 }
1320
1321 if (type == CACHE_NULL_POINTER) {
1322 * result = NULL;
1323 return MAIL_NO_ERROR;
1324 }
1325
1326 r = mailimf_cache_int_read(mmapstr, index, &count);
1327 if (r != MAIL_NO_ERROR) {
1328 res = r;
1329 goto err;
1330 }
1331
1332 list = clist_new();
1333 if (list == NULL) {
1334 res = MAIL_ERROR_MEMORY;
1335 goto err;
1336 }
1337
1338 for(i = 0 ; i < count ; i++) {
1339 struct mailimf_mailbox * mb;
1340
1341 r = mailimf_cache_mailbox_read(mmapstr, index, &mb);
1342 if (r != MAIL_NO_ERROR) {
1343 res = r;
1344 goto free_list;
1345 }
1346
1347 r = clist_append(list, mb);
1348 if (r < 0) {
1349 mailimf_mailbox_free(mb);
1350 res = MAIL_ERROR_MEMORY;
1351 goto free_list;
1352 }
1353 }
1354
1355 mb_list = mailimf_mailbox_list_new(list);
1356 if (mb_list == NULL) {
1357 res = MAIL_ERROR_MEMORY;
1358 goto free_list;
1359 }
1360
1361 * result = mb_list;
1362
1363 return MAIL_NO_ERROR;
1364
1365 free_list:
1366 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
1367 clist_free(list);
1368 err:
1369 return res;
1370}
1371
1372static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * index,
1373 struct mailimf_mailbox * mb)
1374{
1375 int r;
1376
1377 if (mb->mb_display_name) {
1378 r = mailimf_cache_string_write(mmapstr, index,
1379 mb->mb_display_name, strlen(mb->mb_display_name));
1380 if (r != MAIL_NO_ERROR)
1381 return r;
1382 }
1383 else {
1384 r = mailimf_cache_string_write(mmapstr, index, NULL, 0);
1385 if (r != MAIL_NO_ERROR)
1386 return r;
1387 }
1388
1389 r = mailimf_cache_string_write(mmapstr, index,
1390 mb->mb_addr_spec, strlen(mb->mb_addr_spec));
1391 if (r != MAIL_NO_ERROR)
1392 return r;
1393
1394 return MAIL_NO_ERROR;
1395}
1396
1397static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * index,
1398 struct mailimf_mailbox ** result)
1399{
1400 int r;
1401 char * dsp_name;
1402 char * addr_spec;
1403 struct mailimf_mailbox * mb;
1404
1405 dsp_name = NULL;
1406
1407 r = mailimf_cache_string_read(mmapstr, index, &dsp_name);
1408 if (r != MAIL_NO_ERROR)
1409 return r;
1410
1411 r = mailimf_cache_string_read(mmapstr, index, &addr_spec);
1412 if (r != MAIL_NO_ERROR)
1413 goto free_dsp_name;
1414
1415 mb = mailimf_mailbox_new(dsp_name, addr_spec);
1416 if (mb == NULL)
1417 goto free_addr;
1418
1419 * result = mb;
1420
1421 return MAIL_NO_ERROR;
1422
1423 free_addr:
1424 free(addr_spec);
1425 free_dsp_name:
1426 if (dsp_name != NULL)
1427 free(dsp_name);
1428 return MAIL_ERROR_MEMORY;
1429}
diff --git a/libetpan/src/driver/tools/imfcache.h b/libetpan/src/driver/tools/imfcache.h
new file mode 100644
index 0000000..f054a12
--- a/dev/null
+++ b/libetpan/src/driver/tools/imfcache.h
@@ -0,0 +1,75 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMFCACHE_H
37
38#define IMFCACHE_H
39
40#include <stdio.h>
41#include "mailimf.h"
42#include "maildriver_types.h"
43#include "mmapstring.h"
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
49int mail_serialize_clear(MMAPString * mmapstr, size_t * index);
50
51int mail_serialize_write(MMAPString * mmapstr, size_t * index,
52 char * buf, size_t size);
53
54int mail_serialize_read(MMAPString * mmapstr, size_t * index,
55 char * buf, size_t size);
56
57int mailimf_cache_int_write(MMAPString * mmapstr, size_t * index,
58 uint32_t value);
59int mailimf_cache_string_write(MMAPString * mmapstr, size_t * index,
60 char * str, size_t length);
61int mailimf_cache_int_read(MMAPString * mmapstr, size_t * index,
62 uint32_t * result);
63int mailimf_cache_string_read(MMAPString * mmapstr, size_t * index,
64 char ** result);
65
66int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * index,
67 struct mailimf_fields * fields);
68int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * index,
69 struct mailimf_fields ** result);
70
71#ifdef __cplusplus
72}
73#endif
74
75#endif
diff --git a/libetpan/src/driver/tools/mailthread.c b/libetpan/src/driver/tools/mailthread.c
new file mode 100644
index 0000000..32f73cd
--- a/dev/null
+++ b/libetpan/src/driver/tools/mailthread.c
@@ -0,0 +1,1742 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailthread.h"
37#include "mailthread_types.h"
38
39#include <string.h>
40#include <time.h>
41#include <stdlib.h>
42#include <ctype.h>
43
44#include "mail.h"
45#include "chash.h"
46#include "carray.h"
47#include "clist.h"
48#include "mailmessage.h"
49
50static inline char * get_msg_id(mailmessage * msg)
51{
52 if (msg->msg_single_fields.fld_message_id != NULL)
53 return msg->msg_single_fields.fld_message_id->mid_value;
54 else
55 return NULL;
56}
57
58static inline clist * get_ref(mailmessage * msg)
59{
60 if (msg->msg_single_fields.fld_references != NULL)
61 return msg->msg_single_fields.fld_references->mid_list;
62 else
63 return NULL;
64}
65
66static inline clist * get_in_reply_to(mailmessage * msg)
67{
68 if (msg->msg_single_fields.fld_in_reply_to != NULL)
69 return msg->msg_single_fields.fld_in_reply_to->mid_list;
70 else
71 return NULL;
72}
73
74static inline int skip_subj_blob(char * subj, size_t * begin,
75 size_t length)
76{
77 /* subj-blob = "[" *BLOBCHAR "]" *WSP */
78 size_t cur_token;
79
80 cur_token = * begin;
81
82 if (subj[cur_token] != '[')
83 return FALSE;
84
85 cur_token ++;
86
87 while (1) {
88 if (cur_token >= length)
89 return FALSE;
90
91 if (subj[cur_token] == '[')
92 return FALSE;
93
94 if (subj[cur_token] == ']')
95 break;
96
97 cur_token ++;
98 }
99
100 cur_token ++;
101
102 while (1) {
103 if (cur_token >= length)
104 break;
105
106 if (subj[cur_token] != ' ')
107 break;
108
109 cur_token ++;
110 }
111
112 * begin = cur_token;
113
114 return TRUE;
115}
116
117static inline int skip_subj_refwd(char * subj, size_t * begin,
118 size_t length)
119{
120 /* subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":" */
121 size_t cur_token;
122 int prefix;
123
124 cur_token = * begin;
125
126 prefix = FALSE;
127 if (length >= 3) {
128 if (strncasecmp(subj + cur_token, "fwd", 3) == 0) {
129 cur_token += 3;
130 prefix = TRUE;
131 }
132 }
133 if (!prefix) {
134 if (length >= 2) {
135 if (strncasecmp(subj + cur_token, "fw", 2) == 0) {
136 cur_token += 2;
137 prefix = TRUE;
138 }
139 else if (strncasecmp(subj + cur_token, "re", 2) == 0) {
140 cur_token += 2;
141 prefix = TRUE;
142 }
143 }
144 }
145
146 if (!prefix)
147 return FALSE;
148
149 while (1) {
150 if (cur_token >= length)
151 break;
152
153 if (subj[cur_token] != ' ')
154 break;
155
156 cur_token ++;
157 }
158
159 skip_subj_blob(subj, &cur_token, length);
160
161 if (subj[cur_token] != ':')
162 return FALSE;
163
164 cur_token ++;
165
166 * begin = cur_token;
167
168 return TRUE;
169}
170
171static inline int skip_subj_leader(struct mailmessage_tree * tree,
172 char * subj, size_t * begin,
173 size_t length)
174{
175 size_t cur_token;
176
177 cur_token = * begin;
178
179 /* subj-leader = (*subj-blob subj-refwd) / WSP */
180
181 if (subj[cur_token] == ' ') {
182 cur_token ++;
183 }
184 else {
185 while (cur_token < length) {
186 if (!skip_subj_blob(subj, &cur_token, length))
187 break;
188 }
189 if (!skip_subj_refwd(subj, &cur_token, length))
190 return FALSE;
191 tree->node_is_reply = TRUE;
192 }
193
194 * begin = cur_token;
195
196 return TRUE;
197}
198
199
200static char * extract_subject(char * default_from,
201 struct mailmessage_tree * tree,
202 char * str)
203{
204 char * subj;
205 char * cur;
206 char * write_pos;
207 size_t len;
208 size_t begin;
209
210 char * decoded;
211 size_t cur_token;
212
213 int do_repeat_5;
214 int do_repeat_6;
215 int r;
216
217 /*
218 (1) Convert any RFC 2047 encoded-words in the subject to
219 UTF-8.
220 */
221
222 decoded = NULL;
223
224 cur_token = 0;
225 r = mailmime_encoded_phrase_parse(default_from, str, strlen(str),
226 &cur_token, "utf-8",
227 &decoded);
228
229 if (r == MAILIMF_NO_ERROR) {
230 subj = decoded;
231 }
232 else
233 subj = strdup(str);
234
235 len = strlen(subj);
236
237 /*
238 Convert all tabs and continuations to space.
239 Convert all multiple spaces to a single space.
240 */
241
242 cur = subj;
243 write_pos = subj;
244 while (* cur != '\0') {
245 int cont;
246
247 switch (* cur) {
248 case '\t':
249 case '\r':
250 case '\n':
251 cont = TRUE;
252
253 cur ++;
254 while (* cur && cont) {
255 switch (* cur) {
256 case '\t':
257 case '\r':
258 case '\n':
259 cont = TRUE;
260 break;
261 default:
262 cont = FALSE;
263 break;
264 }
265 cur ++;
266 }
267
268 * write_pos = ' ';
269 write_pos ++;
270
271 break;
272
273 default:
274 * write_pos = * cur;
275 write_pos ++;
276
277 cur ++;
278
279 break;
280 }
281 }
282 * write_pos = '\0';
283
284 begin = 0;
285
286 do {
287 do_repeat_6 = FALSE;
288
289 /*
290 (2) Remove all trailing text of the subject that matches
291 the subj-trailer ABNF, repeat until no more matches are
292 possible.
293 */
294
295 while (len > 0) {
296 int chg;
297
298 chg = FALSE;
299
300 /* subj-trailer = "(fwd)" / WSP */
301 if (subj[len - 1] == ' ') {
302 subj[len - 1] = '\0';
303 len --;
304 }
305 else {
306 if (len < 5)
307 break;
308
309 if (strncasecmp(subj + len - 5, "(fwd)", 5) != 0)
310 break;
311
312 subj[len - 5] = '\0';
313 len -= 5;
314 tree->node_is_reply = TRUE;
315 }
316 }
317
318 do {
319 size_t saved_begin;
320
321 do_repeat_5 = FALSE;
322
323 /*
324 (3) Remove all prefix text of the subject that matches the
325 subj-leader ABNF.
326 */
327
328 if (skip_subj_leader(tree, subj, &begin, len))
329 do_repeat_5 = TRUE;
330
331 /*
332 (4) If there is prefix text of the subject that matches the
333 subj-blob ABNF, and removing that prefix leaves a non-empty
334 subj-base, then remove the prefix text.
335 */
336
337 saved_begin = begin;
338 if (skip_subj_blob(subj, &begin, len)) {
339 if (begin == len) {
340 /* this will leave a empty subject base */
341 begin = saved_begin;
342 }
343 else
344 do_repeat_5 = TRUE;
345 }
346
347 /*
348 (5) Repeat (3) and (4) until no matches remain.
349 Note: it is possible to defer step (2) until step (6),
350 but this requires checking for subj-trailer in step (4).
351 */
352
353 }
354 while (do_repeat_5);
355
356 /*
357 (6) If the resulting text begins with the subj-fwd-hdr ABNF
358 and ends with the subj-fwd-trl ABNF, remove the
359 subj-fwd-hdr and subj-fwd-trl and repeat from step (2).
360 */
361
362 if (len >= 5) {
363 size_t saved_begin;
364
365 saved_begin = begin;
366 if (strncasecmp(subj + begin, "[fwd:", 5) == 0) {
367 begin += 5;
368
369 if (subj[len - 1] != ']')
370 saved_begin = begin;
371 else {
372 tree->node_is_reply = TRUE;
373
374 subj[len - 1] = '\0';
375 len --;
376 do_repeat_6 = TRUE;
377 }
378 }
379 }
380
381 }
382 while (do_repeat_6);
383
384 /*
385 (7) The resulting text is the "base subject" used in
386 threading.
387 */
388
389 /* convert to upper case */
390
391 cur = subj + begin;
392 write_pos = subj;
393
394 while (* cur != '\0') {
395 * write_pos = (char) toupper((unsigned char) * cur);
396 cur ++;
397 write_pos ++;
398 }
399 * write_pos = '\0';
400
401 return subj;
402}
403
404static int get_extracted_subject(char * default_from,
405 struct mailmessage_tree * tree,
406 char ** result)
407{
408 if (tree->node_msg->msg_single_fields.fld_subject != NULL) {
409 char * subj;
410
411 subj = extract_subject(default_from,
412 tree, tree->node_msg->msg_single_fields.fld_subject->sbj_value);
413 if (subj == NULL)
414 return MAIL_ERROR_MEMORY;
415
416 * result = subj;
417
418 return MAIL_NO_ERROR;
419 }
420
421 return MAIL_ERROR_SUBJECT_NOT_FOUND;
422}
423
424static int get_thread_subject(char * default_from,
425 struct mailmessage_tree * tree,
426 char ** result)
427{
428 char * thread_subject;
429 int r;
430 unsigned int i;
431
432 if (tree->node_msg != NULL) {
433 if (tree->node_msg->msg_fields != NULL) {
434 r = get_extracted_subject(default_from, tree, &thread_subject);
435
436 if (r != MAIL_NO_ERROR)
437 return r;
438
439 * result = thread_subject;
440 return MAIL_NO_ERROR;
441 }
442 }
443
444 for(i = 0 ; i < carray_count(tree->node_children) ; i ++) {
445 struct mailmessage_tree * child;
446
447 child = carray_get(tree->node_children, i);
448
449 r = get_thread_subject(default_from, child, &thread_subject);
450
451 switch (r) {
452 case MAIL_NO_ERROR:
453 * result = thread_subject;
454 return MAIL_NO_ERROR;
455
456 case MAIL_ERROR_SUBJECT_NOT_FOUND:
457 /* do nothing */
458 break;
459
460 default:
461 return r;
462 }
463 }
464
465 return MAIL_ERROR_SUBJECT_NOT_FOUND;
466}
467
468
469
470#ifndef WRONG
471 #define WRONG(-1)
472#endif /* !defined WRONG */
473
474static int tmcomp(struct tm * atmp, struct tm * btmp)
475{
476 register intresult;
477
478 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
479 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
480 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
481 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
482 (result = (atmp->tm_min - btmp->tm_min)) == 0)
483 result = atmp->tm_sec - btmp->tm_sec;
484 return result;
485}
486
487static time_t mkgmtime(struct tm * tmp)
488{
489 register int dir;
490 register int bits;
491 register int saved_seconds;
492 time_t t;
493 struct tm yourtm, *mytm;
494
495 yourtm = *tmp;
496 saved_seconds = yourtm.tm_sec;
497 yourtm.tm_sec = 0;
498 /*
499 ** Calculate the number of magnitude bits in a time_t
500 ** (this works regardless of whether time_t is
501 ** signed or unsigned, though lint complains if unsigned).
502 */
503 for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
504 ;
505 /*
506 ** If time_t is signed, then 0 is the median value,
507 ** if time_t is unsigned, then 1 << bits is median.
508 */
509 t = (t < 0) ? 0 : ((time_t) 1 << bits);
510 for ( ; ; ) {
511 mytm = gmtime(&t);
512 dir = tmcomp(mytm, &yourtm);
513 if (dir != 0) {
514 if (bits-- < 0)
515 return WRONG;
516 if (bits < 0)
517 --t;
518 else if (dir > 0)
519 t -= (time_t) 1 << bits;
520 elset += (time_t) 1 << bits;
521 continue;
522 }
523 break;
524 }
525 t += saved_seconds;
526 return t;
527}
528
529static inline time_t get_date(mailmessage * msg)
530{
531 struct tm tmval;
532 time_t timeval;
533 struct mailimf_date_time * date_time;
534
535 if (msg->msg_single_fields.fld_orig_date == NULL)
536 return (time_t) -1;
537
538 date_time = msg->msg_single_fields.fld_orig_date->dt_date_time;
539
540 tmval.tm_sec = date_time->dt_sec;
541 tmval.tm_min = date_time->dt_min;
542 tmval.tm_hour = date_time->dt_hour;
543 tmval.tm_sec = date_time->dt_sec;
544 tmval.tm_mday = date_time->dt_day;
545 tmval.tm_mon = date_time->dt_month - 1;
546 tmval.tm_year = date_time->dt_year - 1900;
547
548 timeval = mkgmtime(&tmval);
549
550 timeval -= date_time->dt_zone * 36;
551
552 return timeval;
553}
554
555static inline int is_descendant(struct mailmessage_tree * node,
556 struct mailmessage_tree * maybe_child)
557{
558 unsigned int i;
559
560 for(i = 0 ; i < carray_count(node->node_children) ; i++) {
561 struct mailmessage_tree * tree;
562
563 tree = carray_get(node->node_children, i);
564 if (tree == maybe_child)
565 return TRUE;
566 if (carray_count(tree->node_children) != 0)
567 if (is_descendant(tree, maybe_child))
568 return TRUE;
569 }
570
571 return FALSE;
572}
573
574static int delete_dummy(carray * rootlist, carray * sibling_list,
575 unsigned int cur, unsigned int * pnext)
576{
577 struct mailmessage_tree * env_tree;
578 int res;
579 int r;
580 unsigned int cur_child;
581 unsigned int next;
582
583 env_tree = carray_get(sibling_list, cur);
584
585 cur_child = 0;
586 while (cur_child < carray_count(env_tree->node_children)) {
587 delete_dummy(rootlist, env_tree->node_children, cur_child, &cur_child);
588 }
589
590 if (env_tree->node_msg == NULL) {
591 if (carray_count(env_tree->node_children) == 0) {
592
593 /* If it is a dummy message with NO children, delete it. */
594 mailmessage_tree_free(env_tree);
595 carray_delete(sibling_list, cur);
596 next = cur;
597 }
598 else {
599 /* If it is a dummy message with children, delete it, but
600 promote its children to the current level. */
601
602 /*
603 Do not promote the children if doing so would make them
604 children of the root, unless there is only one child.
605 */
606
607 cur_child = 0;
608 if ((sibling_list != rootlist) ||
609 (carray_count(env_tree->node_children) == 1)) {
610 while (cur_child < carray_count(env_tree->node_children)) {
611 struct mailmessage_tree * child;
612
613 child = carray_get(env_tree->node_children, cur_child);
614 r = carray_add(sibling_list, child, NULL);
615 if (r < 0) {
616 res = MAIL_ERROR_MEMORY;
617 goto err;
618 }
619 /* set new parent of the children */
620 child->node_parent = env_tree->node_parent;
621
622 carray_delete(env_tree->node_children, cur_child);
623 }
624 mailmessage_tree_free(env_tree);
625 carray_delete(sibling_list, cur);
626 next = cur;
627 }
628 else
629 next = cur + 1;
630 }
631 }
632 else
633 next = cur + 1;
634
635 * pnext = next;
636
637 return MAIL_NO_ERROR;
638
639 err:
640 return res;
641}
642
643static inline time_t tree_get_date(struct mailmessage_tree * tree)
644{
645 if (tree->node_msg != NULL) {
646 return tree->node_date;
647 }
648 else {
649 struct mailmessage_tree * subtree;
650
651 if (carray_count(tree->node_children) == 0)
652 return (time_t) -1;
653
654 subtree = carray_get(tree->node_children, 0);
655
656 return subtree->node_date;
657 }
658}
659
660static inline uint32_t tree_get_index(struct mailmessage_tree * tree)
661{
662 if (tree->node_msg == NULL)
663 return 0;
664
665 return tree->node_msg->msg_index;
666}
667
668int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1,
669 struct mailmessage_tree ** ptree2)
670{
671 time_t date1;
672 time_t date2;
673
674 date1 = tree_get_date(* ptree1);
675 date2 = tree_get_date(* ptree2);
676
677 if ((date1 == (time_t) -1) || (date2 == (time_t) -1)) {
678 uint32_t index1;
679 uint32_t index2;
680
681 index1 = tree_get_index(* ptree1);
682 index2 = tree_get_index(* ptree2);
683 return (int) ((long) index1 - (long) index2);
684 }
685
686 return (int) ((long) date1 - (long) date2);
687}
688
689static int tree_subj_time_comp(struct mailmessage_tree ** ptree1,
690 struct mailmessage_tree ** ptree2)
691{
692 char * subj1;
693 char * subj2;
694 time_t date1;
695 time_t date2;
696 int r;
697
698 subj1 = (* ptree1)->node_base_subject;
699 subj2 = (* ptree2)->node_base_subject;
700
701 if ((subj1 != NULL) && (subj2 != NULL))
702 r = strcmp(subj1, subj2);
703 else {
704 if ((subj1 == NULL) && (subj2 == NULL))
705 r = 0;
706 else if (subj1 == NULL)
707 r = -1;
708 else /* subj2 == NULL */
709 r = 1;
710 }
711
712 if (r != 0)
713 return r;
714
715 date1 = (* ptree1)->node_date;
716 date2 = (* ptree2)->node_date;
717
718 if ((date1 == (time_t) -1) || (date2 == (time_t) -1))
719 return ((int32_t) (* ptree1)->node_msg->msg_index) -
720 ((int32_t) (* ptree2)->node_msg->msg_index);
721
722 return (int) ((long) date1 - (long) date2);
723}
724
725
726
727int mail_thread_sort(struct mailmessage_tree * tree,
728 int (* comp_func)(struct mailmessage_tree **,
729 struct mailmessage_tree **),
730 int sort_sub)
731{
732 unsigned int cur;
733 int r;
734 int res;
735
736 for(cur = 0 ; cur < carray_count(tree->node_children) ; cur ++) {
737 struct mailmessage_tree * subtree;
738
739 subtree = carray_get(tree->node_children, cur);
740
741 if (sort_sub) {
742 r = mail_thread_sort(subtree, comp_func, sort_sub);
743 if (r != MAIL_NO_ERROR) {
744 res = r;
745 goto err;
746 }
747 }
748 }
749
750 qsort(carray_data(tree->node_children), carray_count(tree->node_children),
751 sizeof(struct mailmessage_tree *),
752 (int (*)(const void *, const void *)) comp_func);
753
754 return MAIL_NO_ERROR;
755
756 err:
757 return res;
758}
759
760
761static int
762mail_build_thread_references(char * default_from,
763 struct mailmessage_list * env_list,
764 struct mailmessage_tree ** result,
765 int use_subject,
766 int (* comp_func)(struct mailmessage_tree **,
767 struct mailmessage_tree **))
768{
769 int r;
770 int res;
771 chash * msg_id_hash;
772 unsigned int cur;
773 struct mailmessage_tree * root;
774 carray * rootlist;
775 carray * msg_list;
776 unsigned int i;
777 chash * subject_hash;
778
779 msg_id_hash = chash_new(128, CHASH_COPYNONE);
780 if (msg_id_hash == NULL) {
781 res = MAIL_ERROR_MEMORY;
782 goto err;
783 }
784
785 root = mailmessage_tree_new(NULL, (time_t) -1, NULL);
786 if (root == NULL) {
787 res = MAIL_ERROR_MEMORY;
788 goto free_hash;
789 }
790 rootlist = root->node_children;
791
792 msg_list = carray_new(128);
793 if (msg_list == NULL) {
794 res = MAIL_ERROR_MEMORY;
795 goto free_root;
796 }
797
798 /* collect message-ID */
799 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
800 mailmessage * msg;
801 char * msgid;
802 struct mailmessage_tree * env_tree;
803 chashdatum hashkey;
804 chashdatum hashdata;
805 chashdatum hashold;
806 time_t date;
807
808 msg = carray_get(env_list->msg_tab, i);
809
810 if (msg == NULL)
811 continue;
812
813 if (msg->msg_fields != NULL) {
814 msgid = get_msg_id(msg);
815
816 if (msgid == NULL) {
817 msgid = mailimf_get_message_id();
818 }
819 else {
820 hashkey.data = msgid;
821 hashkey.len = strlen(msgid);
822
823 if (chash_get(msg_id_hash, &hashkey, &hashdata) == 0)
824 msgid = mailimf_get_message_id();
825 else
826 msgid = strdup(msgid);
827 }
828
829 if (msgid == NULL) {
830 res = MAIL_ERROR_MEMORY;
831 goto free_list;
832 }
833
834 date = get_date(msg);
835
836 env_tree = mailmessage_tree_new(msgid, date, msg);
837 if (env_tree == NULL) {
838 res = MAIL_ERROR_MEMORY;
839 goto free_list;
840 }
841
842 r = carray_add(msg_list, env_tree, NULL);
843 if (r < 0) {
844 mailmessage_tree_free(env_tree);
845 res = MAIL_ERROR_MEMORY;
846 goto free_list;
847 }
848
849 hashkey.data = msgid;
850 hashkey.len = strlen(msgid);
851
852 hashdata.data = env_tree;
853 hashdata.len = 0;
854
855 r = chash_set(msg_id_hash, &hashkey, &hashdata, &hashold);
856 if (r < 0) {
857 res = MAIL_ERROR_MEMORY;
858 goto free_list;
859 }
860 }
861 }
862
863 /* (1) for all messages */
864
865 for(cur = 0 ; cur < carray_count(msg_list) ; cur ++) {
866 struct mailmessage_tree * env_tree;
867 mailmessage * msg;
868 clist * ref;
869
870 env_tree = carray_get(msg_list, cur);
871
872 msg = env_tree->node_msg;
873
874 ref = NULL;
875 if (msg != NULL) {
876 ref = get_ref(msg);
877 if (ref == NULL)
878 ref = get_in_reply_to(msg);
879 }
880
881 /* (A) Using the Message IDs in the message's references, link
882 the corresponding messages (those whose Message-ID header
883 line contains the given reference Message ID) together as
884 parent/child.
885 */
886
887 if (ref != NULL) {
888 /* try to start a tree */
889
890 clistiter * cur_ref;
891 chashdatum hashkey;
892 chashdatum hashdata;
893 chashdatum hashold;
894 struct mailmessage_tree * env_cur_tree;
895 struct mailmessage_tree * last_env_cur_tree;
896
897 env_cur_tree = NULL;
898 for(cur_ref = clist_begin(ref) ; cur_ref != NULL ;
899 cur_ref = clist_next(cur_ref)) {
900 char * msgid;
901
902 last_env_cur_tree = env_cur_tree;
903
904 msgid = clist_content(cur_ref);
905
906 hashkey.data = msgid;
907 hashkey.len = strlen(msgid);
908
909 r = chash_get(msg_id_hash, &hashkey, &hashdata);
910 if (r < 0) {
911 /* not found, create a dummy message */
912 msgid = strdup(msgid);
913 if (msgid == NULL) {
914 res = MAIL_ERROR_MEMORY;
915 goto free_list;
916 }
917
918 env_cur_tree = mailmessage_tree_new(msgid, (time_t) -1, NULL);
919 if (env_cur_tree == NULL) {
920 free(msgid);
921 res = MAIL_ERROR_MEMORY;
922 goto free_list;
923 }
924
925 r = carray_add(msg_list, env_cur_tree, NULL);
926 if (r < 0) {
927 mailmessage_tree_free(env_cur_tree);
928 res = MAIL_ERROR_MEMORY;
929 goto free_list;
930 }
931
932 hashkey.data = msgid;
933 hashkey.len = strlen(msgid);
934
935 hashdata.data = env_cur_tree;
936 hashdata.len = 0;
937
938 r = chash_set(msg_id_hash, &hashkey, &hashdata, &hashold);
939 if (r < 0) {
940 res = MAIL_ERROR_MEMORY;
941 goto free_list;
942 }
943 }
944 else {
945 env_cur_tree = hashdata.data;
946 }
947
948 if (last_env_cur_tree != NULL) {
949 if (env_cur_tree->node_parent == NULL) {
950 /* make it one child */
951 if (env_cur_tree != last_env_cur_tree) {
952 if (!is_descendant(env_cur_tree, last_env_cur_tree)) {
953 /* set parent */
954 env_cur_tree->node_parent = last_env_cur_tree;
955 r = carray_add(last_env_cur_tree->node_children,
956 env_cur_tree, NULL);
957 if (r < 0) {
958 res = MAIL_ERROR_MEMORY;
959 goto free_list;
960 }
961 }
962 }
963 }
964 }
965 }
966
967 /* (B) Create a parent/child link between the last reference
968 (or NIL if there are no references) and the current message.
969 If the current message already has a parent, it is probably
970 the result of a truncated References header line, so break
971 the current parent/child link before creating the new
972 correct one.
973 */
974
975 last_env_cur_tree = env_cur_tree;
976
977 if (last_env_cur_tree != NULL) {
978 if (env_tree->node_parent == NULL) {
979 if (last_env_cur_tree != env_tree) {
980 if (!is_descendant(env_tree, last_env_cur_tree)) {
981 /* set parent */
982 env_tree->node_parent = last_env_cur_tree;
983 r = carray_add(last_env_cur_tree->node_children, env_tree, NULL);
984 if (r < 0) {
985 res = MAIL_ERROR_MEMORY;
986 goto free_list;
987 }
988 }
989 }
990 }
991 }
992 }
993 }
994
995 chash_free(msg_id_hash);
996 msg_id_hash = NULL;
997
998 /* (2) Gather together all of the messages that have no parents
999 and make them all children (siblings of one another) of a dummy
1000 parent (the "root").
1001 */
1002
1003 for(cur = 0 ; cur < carray_count(msg_list) ; cur ++) {
1004 struct mailmessage_tree * env_tree;
1005
1006 env_tree = carray_get(msg_list, cur);
1007 if (env_tree->node_parent == NULL) {
1008 r = carray_add(rootlist, env_tree, NULL);
1009 if (r < 0) {
1010 res = MAIL_ERROR_MEMORY;
1011 goto free_list;
1012 }
1013 /* set parent */
1014 env_tree->node_parent = root;
1015 }
1016 }
1017
1018 carray_free(msg_list);
1019 msg_list = NULL;
1020
1021 /* (3) Prune dummy messages from the thread tree.
1022 */
1023
1024 cur = 0;
1025 while (cur < carray_count(rootlist)) {
1026 r = delete_dummy(rootlist, rootlist, cur, &cur);
1027 if (r != MAIL_NO_ERROR) {
1028 res = r;
1029 goto free_list;
1030 }
1031 }
1032
1033 /* (4) Sort the messages under the root (top-level siblings only)
1034 by sent date.
1035 */
1036
1037 r = mail_thread_sort(root, mailthread_tree_timecomp, FALSE);
1038 if (r != MAIL_NO_ERROR) {
1039 res = r;
1040 goto free_list;
1041 }
1042
1043 if (use_subject) {
1044
1045 /* (5) Gather together messages under the root that have the same
1046 extracted subject text.
1047
1048 (A) Create a table for associating extracted subjects with
1049 messages.
1050 */
1051
1052 subject_hash = chash_new(128, CHASH_COPYVALUE);
1053 if (subject_hash == NULL) {
1054 res = MAIL_ERROR_MEMORY;
1055 goto free_list;
1056 }
1057
1058 /*
1059 (B) Populate the subject table with one message per
1060 extracted subject. For each child of the root:
1061 */
1062
1063 for(cur = 0 ; cur < carray_count(rootlist) ; cur ++) {
1064 struct mailmessage_tree * env_tree;
1065 chashdatum key;
1066 chashdatum data;
1067 char * base_subject;
1068 int r;
1069
1070 env_tree = carray_get(rootlist, cur);
1071
1072 /*
1073 (i) Find the subject of this thread by extracting the
1074 base subject from the current message, or its first child
1075 if the current message is a dummy.
1076 */
1077
1078 r = get_thread_subject(default_from, env_tree, &base_subject);
1079
1080 /*
1081 (ii) If the extracted subject is empty, skip this
1082 message.
1083 */
1084
1085 if (r == MAIL_ERROR_SUBJECT_NOT_FOUND) {
1086 /* no subject found */
1087 continue;
1088 }
1089 else if (r == MAIL_NO_ERROR) {
1090 if (* base_subject == '\0') {
1091 /* subject empty */
1092 free(base_subject);
1093 continue;
1094 }
1095 else {
1096 /* do nothing */
1097 }
1098 }
1099 else {
1100 res = r;
1101 goto free_subject_hash;
1102 }
1103
1104 env_tree->node_base_subject = base_subject;
1105
1106 /*
1107 (iii) Lookup the message associated with this extracted
1108 subject in the table.
1109 */
1110
1111 key.data = base_subject;
1112 key.len = strlen(base_subject);
1113
1114 r = chash_get(subject_hash, &key, &data);
1115
1116 if (r < 0) {
1117 /*
1118 (iv) If there is no message in the table with this
1119 subject, add the current message and the extracted
1120 subject to the subject table.
1121 */
1122
1123 data.data = &cur;
1124 data.len = sizeof(cur);
1125
1126 r = chash_set(subject_hash, &key, &data, NULL);
1127 if (r < 0) {
1128 res = MAIL_ERROR_MEMORY;
1129 goto free_subject_hash;
1130 }
1131 }
1132 else {
1133 /*
1134 Otherwise, replace the message in the table with the
1135 current message if the message in the table is not a
1136 dummy AND either of the following criteria are true:
1137 The current message is a dummy, OR
1138 The message in the table is a reply or forward (its
1139 original subject contains a subj-refwd part and/or a
1140 "(fwd)" subj-trailer) and the current message is not.
1141 */
1142 struct mailmessage_tree * msg_in_table;
1143 unsigned int * iter_in_table;
1144 int replace;
1145
1146 iter_in_table = data.data;
1147 msg_in_table = carray_get(rootlist, cur);
1148
1149 replace = FALSE;
1150 /* message is dummy if info is NULL */
1151 if (msg_in_table->node_msg != NULL) {
1152
1153 if (env_tree->node_msg == NULL)
1154 replace = TRUE;
1155 else {
1156 if (env_tree->node_is_reply && !env_tree->node_is_reply)
1157 replace = TRUE;
1158 }
1159 }
1160
1161 if (replace) {
1162 data.data = &cur;
1163 data.len = sizeof(cur);
1164
1165 r = chash_set(subject_hash, &key, &data, NULL);
1166 if (r < 0) {
1167 res = MAIL_ERROR_MEMORY;
1168 goto free_subject_hash;
1169 }
1170 }
1171 }
1172 }
1173
1174 /*
1175 (C) Merge threads with the same subject. For each child of
1176 the root:
1177 */
1178
1179 cur = 0;
1180 while (cur < carray_count(rootlist)) {
1181 struct mailmessage_tree * env_tree;
1182 chashdatum key;
1183 chashdatum data;
1184 int r;
1185 struct mailmessage_tree * main_tree;
1186 unsigned int * main_cur;
1187
1188 env_tree = carray_get(rootlist, cur);
1189
1190 if (env_tree == NULL)
1191 goto next_msg;
1192
1193 /*
1194 (i) Find the subject of this thread as in step 4.B.i
1195 above.
1196 */
1197
1198 /* already done in tree->node_base_subject */
1199
1200 /*
1201 (ii) If the extracted subject is empty, skip this
1202 message.
1203 */
1204
1205 if (env_tree->node_base_subject == NULL)
1206 goto next_msg;
1207
1208 if (* env_tree->node_base_subject == '\0')
1209 goto next_msg;
1210
1211 /*
1212 (iii) Lookup the message associated with this extracted
1213 subject in the table.
1214 */
1215
1216 key.data = env_tree->node_base_subject;
1217 key.len = strlen(env_tree->node_base_subject);
1218
1219 r = chash_get(subject_hash, &key, &data);
1220 if (r < 0)
1221 goto next_msg;
1222
1223 /*
1224 (iv) If the message in the table is the current message,
1225 skip this message.
1226 */
1227
1228 main_cur = data.data;
1229 if (* main_cur == cur)
1230 goto next_msg;
1231
1232 /*
1233 Otherwise, merge the current message with the one in the
1234 table using the following rules:
1235 */
1236
1237 main_tree = carray_get(rootlist, * main_cur);
1238
1239 /*
1240 If both messages are dummies, append the current
1241 message's children to the children of the message in
1242 the table (the children of both messages become
1243 siblings), and then delete the current message.
1244 */
1245
1246 if ((env_tree->node_msg == NULL) && (main_tree->node_msg == NULL)) {
1247 unsigned int old_size;
1248
1249 old_size = carray_count(main_tree->node_children);
1250
1251 r = carray_set_size(main_tree->node_children, old_size +
1252 carray_count(env_tree->node_children));
1253 if (r < 0) {
1254 res = MAIL_ERROR_MEMORY;
1255 goto free_subject_hash;
1256 }
1257
1258 for(i = 0 ; i < carray_count(env_tree->node_children) ; i ++) {
1259 struct mailmessage_tree * child;
1260
1261 child = carray_get(env_tree->node_children, i);
1262 carray_set(main_tree->node_children, old_size + i, child);
1263 /* set parent */
1264 child->node_parent = main_tree;
1265 }
1266 carray_set_size(env_tree->node_children, 0);
1267 /* this is the only case where children can be NULL,
1268 this is before freeing it */
1269 mailmessage_tree_free(env_tree);
1270 carray_delete_fast(rootlist, cur);
1271 }
1272
1273 /*
1274 If the message in the table is a dummy and the current
1275 message is not, make the current message a child of
1276 the message in the table (a sibling of it's children).
1277 */
1278
1279 else if (main_tree->node_msg == NULL) {
1280 r = carray_add(main_tree->node_children, env_tree, NULL);
1281 if (r < 0) {
1282 res = MAIL_ERROR_MEMORY;
1283 goto free_subject_hash;
1284 }
1285 /* set parent */
1286 env_tree->node_parent = main_tree;
1287
1288 carray_delete_fast(rootlist, cur);
1289 }
1290
1291 /*
1292 If the current message is a reply or forward and the
1293 message in the table is not, make the current message
1294 a child of the message in the table (a sibling of it's
1295 children).
1296 */
1297
1298 else if (env_tree->node_is_reply && !main_tree->node_is_reply) {
1299 r = carray_add(main_tree->node_children, env_tree, NULL);
1300 if (r < 0) {
1301 res = MAIL_ERROR_MEMORY;
1302 goto free_subject_hash;
1303 }
1304 /* set parent */
1305 env_tree->node_parent = main_tree;
1306
1307 carray_delete_fast(rootlist, cur);
1308 }
1309
1310 /*
1311 Otherwise, create a new dummy message and make both
1312 the current message and the message in the table
1313 children of the dummy. Then replace the message in
1314 the table with the dummy message.
1315 Note: Subject comparisons are case-insensitive, as
1316 described under "Internationalization
1317 Considerations."
1318 */
1319
1320 else {
1321 struct mailmessage_tree * new_main_tree;
1322 char * base_subject;
1323 unsigned int last;
1324
1325 new_main_tree = mailmessage_tree_new(NULL, (time_t) -1, NULL);
1326 if (new_main_tree == NULL) {
1327 res = MAIL_ERROR_MEMORY;
1328 goto free_subject_hash;
1329 }
1330
1331 /* main_tree->node_base_subject is never NULL */
1332
1333 base_subject = strdup(main_tree->node_base_subject);
1334 if (base_subject == NULL) {
1335 mailmessage_tree_free(new_main_tree);
1336 res = MAIL_ERROR_MEMORY;
1337 goto free_subject_hash;
1338 }
1339
1340 new_main_tree->node_base_subject = base_subject;
1341
1342 r = carray_add(rootlist, new_main_tree, &last);
1343 if (r < 0) {
1344 mailmessage_tree_free(new_main_tree);
1345 res = MAIL_ERROR_MEMORY;
1346 goto free_subject_hash;
1347 }
1348
1349 r = carray_add(new_main_tree->node_children, main_tree, NULL);
1350 if (r < 0) {
1351 res = MAIL_ERROR_MEMORY;
1352 goto free_subject_hash;
1353 }
1354 /* set parent */
1355 main_tree->node_parent = new_main_tree;
1356
1357 carray_delete_fast(rootlist, * main_cur);
1358
1359 r = carray_add(new_main_tree->node_children, env_tree, NULL);
1360 if (r < 0) {
1361 res = MAIL_ERROR_MEMORY;
1362 goto free_subject_hash;
1363 }
1364 /* set parent */
1365 env_tree->node_parent = new_main_tree;
1366
1367 carray_delete_fast(rootlist, cur);
1368
1369 data.data = &last;
1370 data.len = sizeof(last);
1371
1372 r = chash_set(subject_hash, &key, &data, NULL);
1373
1374 if (r < 0) {
1375 res = MAIL_ERROR_MEMORY;
1376 goto free_subject_hash;
1377 }
1378 }
1379
1380 continue;
1381
1382 next_msg:
1383 cur ++;
1384 continue;
1385 }
1386
1387 i = 0;
1388 for(cur = 0 ; cur < carray_count(rootlist) ; cur ++) {
1389 struct mailmessage_tree * env_tree;
1390
1391 env_tree = carray_get(rootlist, cur);
1392 if (env_tree == NULL)
1393 continue;
1394
1395 carray_set(rootlist, i, env_tree);
1396 i ++;
1397 }
1398 carray_set_size(rootlist, i);
1399
1400 chash_free(subject_hash);
1401 }
1402
1403 /*
1404 (6) Traverse the messages under the root and sort each set of
1405 siblings by sent date. Traverse the messages in such a way
1406 that the "youngest" set of siblings are sorted first, and the
1407 "oldest" set of siblings are sorted last (grandchildren are
1408 sorted before children, etc).
1409
1410 In the case of an exact match on
1411 sent date or if either of the Date: headers used in a
1412 comparison can not be parsed, use the order in which the
1413 messages appear in the mailbox (that is, by sequence number) to
1414 determine the order. In the case of a dummy message (which can
1415 only occur with top-level siblings), use its first child for
1416 sorting.
1417 */
1418
1419#if 0
1420 if (comp_func != NULL) {
1421 r = mail_thread_sort(root, comp_func, TRUE);
1422 if (r != MAIL_NO_ERROR) {
1423 res = r;
1424 goto free_list;
1425 }
1426 }
1427#endif
1428 if (comp_func == NULL)
1429 comp_func = mailthread_tree_timecomp;
1430
1431 r = mail_thread_sort(root, comp_func, TRUE);
1432 if (r != MAIL_NO_ERROR) {
1433 res = r;
1434 goto free_list;
1435 }
1436
1437 * result = root;
1438
1439 return MAIL_NO_ERROR;
1440
1441 free_subject_hash:
1442 chash_free(subject_hash);
1443 free_list:
1444 if (msg_list != NULL) {
1445 for(i = 0 ; i < carray_count(msg_list) ; i ++)
1446 mailmessage_tree_free(carray_get(msg_list, i));
1447 carray_free(msg_list);
1448 }
1449 free_root:
1450 mailmessage_tree_free_recursive(root);
1451 free_hash:
1452 if (msg_id_hash != NULL)
1453 chash_free(msg_id_hash);
1454 err:
1455 return res;
1456}
1457
1458
1459
1460static int
1461mail_build_thread_orderedsubject(char * default_from,
1462 struct mailmessage_list * env_list,
1463 struct mailmessage_tree ** result,
1464 int (* comp_func)(struct mailmessage_tree **,
1465 struct mailmessage_tree **))
1466{
1467 unsigned int i;
1468 carray * rootlist;
1469 unsigned int cur;
1470 struct mailmessage_tree * root;
1471 int res;
1472 int r;
1473 struct mailmessage_tree * current_thread;
1474
1475 root = mailmessage_tree_new(NULL, (time_t) -1, NULL);
1476 if (root == NULL) {
1477 res = MAIL_ERROR_MEMORY;
1478 goto err;
1479 }
1480 rootlist = root->node_children;
1481
1482 /*
1483 The ORDEREDSUBJECT threading algorithm is also referred to as
1484 "poor man's threading."
1485 */
1486
1487 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1488 mailmessage * msg;
1489 struct mailmessage_tree * env_tree;
1490 char * base_subject;
1491 time_t date;
1492
1493 msg = carray_get(env_list->msg_tab, i);
1494
1495 if (msg == NULL)
1496 continue;
1497
1498 if (msg->msg_fields != NULL) {
1499
1500 date = get_date(msg);
1501
1502 env_tree = mailmessage_tree_new(NULL, date, msg);
1503 if (env_tree == NULL) {
1504 res = MAIL_ERROR_MEMORY;
1505 goto free;
1506 }
1507
1508 /* set parent */
1509 env_tree->node_parent = root;
1510 r = carray_add(rootlist, env_tree, NULL);
1511 if (r < 0) {
1512 mailmessage_tree_free(env_tree);
1513 res = MAIL_ERROR_MEMORY;
1514 goto free;
1515 }
1516
1517 r = get_extracted_subject(default_from, env_tree, &base_subject);
1518 switch (r) {
1519 case MAIL_NO_ERROR:
1520 env_tree->node_base_subject = base_subject;
1521 break;
1522
1523 case MAIL_ERROR_SUBJECT_NOT_FOUND:
1524 break;
1525
1526 default:
1527 res = r;
1528 goto free;
1529 }
1530 }
1531 }
1532
1533 /*
1534 The searched messages are sorted by
1535 subject and then by the sent date.
1536 */
1537
1538 r = mail_thread_sort(root, tree_subj_time_comp, FALSE);
1539 if (r != MAIL_NO_ERROR) {
1540 res = r;
1541 goto free;
1542 }
1543
1544 /*
1545 The messages are then split
1546 into separate threads, with each thread containing messages
1547 with the same extracted subject text.
1548 */
1549
1550 current_thread = NULL;
1551
1552 cur = 0;
1553 while (cur < carray_count(rootlist)) {
1554 struct mailmessage_tree * cur_env_tree;
1555
1556 cur_env_tree = carray_get(rootlist, cur);
1557 if (current_thread == NULL) {
1558 current_thread = cur_env_tree;
1559 cur ++;
1560 continue;
1561 }
1562
1563 if ((cur_env_tree->node_base_subject == NULL) ||
1564 (current_thread->node_base_subject == NULL)) {
1565 current_thread = cur_env_tree;
1566 cur ++;
1567 continue;
1568 }
1569
1570 if (strcmp(cur_env_tree->node_base_subject,
1571 current_thread->node_base_subject) == 0) {
1572
1573 /* set parent */
1574 cur_env_tree->node_parent = current_thread;
1575 r = carray_add(current_thread->node_children, cur_env_tree, NULL);
1576 if (r < 0) {
1577 res = MAIL_ERROR_MEMORY;
1578 goto free;
1579 }
1580
1581 carray_delete(rootlist, cur);
1582 }
1583 else
1584 cur ++;
1585 current_thread = cur_env_tree;
1586 }
1587
1588 /*
1589 Finally, the threads are
1590 sorted by the sent date of the first message in the thread.
1591 Note that each message in a thread is a child (as opposed to a
1592 sibling) of the previous message.
1593 */
1594
1595#if 0
1596 if (comp_func != NULL) {
1597 r = mail_thread_sort(root, comp_func, FALSE);
1598 if (r != MAIL_NO_ERROR) {
1599 res = r;
1600 goto free;
1601 }
1602 }
1603#endif
1604
1605 if (comp_func == NULL)
1606 comp_func = mailthread_tree_timecomp;
1607
1608 r = mail_thread_sort(root, comp_func, FALSE);
1609 if (r != MAIL_NO_ERROR) {
1610 res = r;
1611 goto free;
1612 }
1613
1614 * result = root;
1615
1616 return MAIL_NO_ERROR;
1617
1618 free:
1619 mailmessage_tree_free_recursive(root);
1620 err:
1621 return res;
1622}
1623
1624
1625static int
1626mail_build_thread_none(char * default_from,
1627 struct mailmessage_list * env_list,
1628 struct mailmessage_tree ** result,
1629 int (* comp_func)(struct mailmessage_tree **,
1630 struct mailmessage_tree **))
1631{
1632 unsigned int i;
1633 carray * rootlist;
1634 struct mailmessage_tree * root;
1635 int res;
1636 int r;
1637
1638 root = mailmessage_tree_new(NULL, (time_t) -1, NULL);
1639 if (root == NULL) {
1640 res = MAIL_ERROR_MEMORY;
1641 goto err;
1642 }
1643 rootlist = root->node_children;
1644
1645 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1646 mailmessage * msg;
1647 struct mailmessage_tree * env_tree;
1648 char * base_subject;
1649 time_t date;
1650
1651 msg = carray_get(env_list->msg_tab, i);
1652
1653 if (msg == NULL)
1654 continue;
1655
1656 if (msg->msg_fields != NULL) {
1657
1658 date = get_date(msg);
1659
1660 env_tree = mailmessage_tree_new(NULL, date, msg);
1661 if (env_tree == NULL) {
1662 res = MAIL_ERROR_MEMORY;
1663 goto free;
1664 }
1665
1666 /* set parent */
1667 env_tree->node_parent = root;
1668 r = carray_add(rootlist, env_tree, NULL);
1669 if (r < 0) {
1670 mailmessage_tree_free(env_tree);
1671 res = MAIL_ERROR_MEMORY;
1672 goto free;
1673 }
1674
1675 r = get_extracted_subject(default_from, env_tree, &base_subject);
1676 switch (r) {
1677 case MAIL_NO_ERROR:
1678 env_tree->node_base_subject = base_subject;
1679 break;
1680
1681 case MAIL_ERROR_SUBJECT_NOT_FOUND:
1682 break;
1683
1684 default:
1685 res = r;
1686 goto free;
1687 }
1688 }
1689 }
1690
1691 if (comp_func == NULL)
1692 comp_func = mailthread_tree_timecomp;
1693
1694 r = mail_thread_sort(root, comp_func, FALSE);
1695 if (r != MAIL_NO_ERROR) {
1696 res = r;
1697 goto free;
1698 }
1699
1700 * result = root;
1701
1702 return MAIL_NO_ERROR;
1703
1704 free:
1705 mailmessage_tree_free_recursive(root);
1706 err:
1707 return res;
1708}
1709
1710
1711int mail_build_thread(int type, char * default_from,
1712 struct mailmessage_list * env_list,
1713 struct mailmessage_tree ** result,
1714 int (* comp_func)(struct mailmessage_tree **,
1715 struct mailmessage_tree **))
1716{
1717 unsigned int i;
1718
1719 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++)
1720 mailmessage_resolve_single_fields(carray_get(env_list->msg_tab, i));
1721
1722 switch (type) {
1723 case MAIL_THREAD_REFERENCES:
1724 return mail_build_thread_references(default_from,
1725 env_list, result, TRUE, comp_func);
1726
1727 case MAIL_THREAD_REFERENCES_NO_SUBJECT:
1728 return mail_build_thread_references(default_from,
1729 env_list, result, FALSE, comp_func);
1730
1731 case MAIL_THREAD_ORDEREDSUBJECT:
1732 return mail_build_thread_orderedsubject(default_from,
1733 env_list, result, comp_func);
1734
1735 case MAIL_THREAD_NONE:
1736 return mail_build_thread_none(default_from,
1737 env_list, result, comp_func);
1738
1739 default:
1740 return MAIL_ERROR_NOT_IMPLEMENTED;
1741 }
1742}
diff --git a/libetpan/src/driver/tools/mailthread.h b/libetpan/src/driver/tools/mailthread.h
new file mode 100644
index 0000000..fa2f4bc
--- a/dev/null
+++ b/libetpan/src/driver/tools/mailthread.h
@@ -0,0 +1,108 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILTHREAD_H
37
38#define MAILTHREAD_H
39
40#include <libetpan/mailthread_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mail_build_thread constructs a tree with the message using the
48 given style.
49
50 @param type is the type of threading to apply, the value can be
51 MAIL_THREAD_REFERENCES, MAIL_THREAD_REFERENCES_NO_SUBJECT,
52 MAIL_THREAD_ORDEREDSUBJECT or MAIL_THREAD_NONE,
53
54 @param default_from is the default charset to use whenever the
55 subject is not tagged with a charset. "US-ASCII" can be used
56 if you don't know what to use.
57
58 @param env_list is the message list (with header fields fetched)
59 to use to build the message tree.
60
61 @param result * result) will contain the resulting message tree.
62
63 @param if comp_func is NULL, no sorting algorithm is used.
64
65 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
66 on error
67*/
68
69int mail_build_thread(int type, char * default_from,
70 struct mailmessage_list * env_list,
71 struct mailmessage_tree ** result,
72 int (* comp_func)(struct mailmessage_tree **,
73 struct mailmessage_tree **));
74
75/*
76 mail_thread_sort sort the messages in the message tree, using the
77 given sort function.
78
79 @param tree is the message tree to sort.
80
81 @param comp_func is the sort function to use (this is the same kind of
82 functions than those used for qsort()). mailthread_tree_timecomp can be
83 used for default sort.
84
85 @param sort_sub if this value is 0, only the children of the root message
86 are sorted.
87*/
88
89int mail_thread_sort(struct mailmessage_tree * tree,
90 int (* comp_func)(struct mailmessage_tree **,
91 struct mailmessage_tree **),
92 int sort_sub);
93
94/*
95 mailthread_tree_timecomp is the default sort function.
96
97 The message are compared by date, then by message numbers.
98 The tree are given in (* ptree1) and (* ptree2).
99*/
100
101int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1,
102 struct mailmessage_tree ** ptree2);
103
104#ifdef __cplusplus
105}
106#endif
107
108#endif
diff --git a/libetpan/src/driver/tools/mailthread_types.c b/libetpan/src/driver/tools/mailthread_types.c
new file mode 100644
index 0000000..dc2a4ca
--- a/dev/null
+++ b/libetpan/src/driver/tools/mailthread_types.c
@@ -0,0 +1,90 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailthread_types.h"
37
38#include "mail.h"
39#include <stdlib.h>
40
41struct mailmessage_tree *
42mailmessage_tree_new(char * node_msgid, time_t node_date,
43 mailmessage * node_msg)
44{
45 struct mailmessage_tree * tree;
46 carray * array;
47
48 array = carray_new(16);
49 if (array == NULL)
50 return NULL;
51
52 tree = malloc(sizeof(* tree));
53 tree->node_parent = NULL;
54 tree->node_date = node_date;
55 tree->node_msgid = node_msgid;
56 tree->node_msg = node_msg;
57 tree->node_children = array;
58 tree->node_base_subject = NULL;
59 tree->node_is_reply = FALSE;
60
61 return tree;
62}
63
64void mailmessage_tree_free(struct mailmessage_tree * tree)
65{
66 if (tree->node_base_subject != NULL)
67 free(tree->node_base_subject);
68
69 if (tree->node_children != NULL)
70 carray_free(tree->node_children);
71 if (tree->node_msgid != NULL)
72 free(tree->node_msgid);
73
74 free(tree);
75}
76
77void mailmessage_tree_free_recursive(struct mailmessage_tree * tree)
78{
79 unsigned int i;
80
81 for(i = 0 ; i < carray_count(tree->node_children) ; i++) {
82 struct mailmessage_tree * child;
83
84 child = carray_get(tree->node_children, i);
85
86 mailmessage_tree_free_recursive(child);
87 }
88
89 mailmessage_tree_free(tree);
90}
diff --git a/libetpan/src/driver/tools/mailthread_types.h b/libetpan/src/driver/tools/mailthread_types.h
new file mode 100644
index 0000000..3325904
--- a/dev/null
+++ b/libetpan/src/driver/tools/mailthread_types.h
@@ -0,0 +1,64 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILTHREAD_TYPES_H
37
38#define MAILTHREAD_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/maildriver_types.h>
45#include <libetpan/mailmessage_types.h>
46
47/*
48 This is the type of tree construction to apply.
49*/
50
51enum {
52 MAIL_THREAD_REFERENCES, /* this is threading using
53 References fields only) */
54 MAIL_THREAD_REFERENCES_NO_SUBJECT, /* this is threading using References
55 fields, then subject */
56 MAIL_THREAD_ORDEREDSUBJECT, /* this is threading using only subject */
57 MAIL_THREAD_NONE, /* no thread */
58};
59
60#ifdef __cplusplus
61}
62#endif
63
64#endif