summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/data-message/data_message_driver.c119
-rw-r--r--libetpan/src/driver/implementation/data-message/data_message_driver.h50
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver.c1134
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver.h53
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver_message.c308
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver_types.h71
-rw-r--r--libetpan/src/driver/implementation/db/dbstorage.c144
-rw-r--r--libetpan/src/driver/implementation/db/dbstorage.h61
-rw-r--r--libetpan/src/driver/implementation/hotmail/hotmailstorage.c62
-rw-r--r--libetpan/src/driver/implementation/hotmail/hotmailstorage.h56
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver.c1226
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached.c1370
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached_message.c664
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_message.c1239
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_tools.c3623
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_tools.h116
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_types.h144
-rw-r--r--libetpan/src/driver/implementation/imap/imapstorage.c297
-rw-r--r--libetpan/src/driver/implementation/imap/imapstorage.h90
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver.c676
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver.h53
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached.c1158
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached.h53
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c334
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_message.c255
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_tools.c198
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_tools.h53
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_types.h96
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirstorage.c193
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirstorage.h69
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver.c515
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver.h52
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached.c1337
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached.h54
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c361
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_message.c225
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_tools.c435
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_tools.h85
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_types.h107
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxstorage.c192
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxstorage.h69
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver.c875
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached.c1315
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached_message.c338
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_message.c213
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_tools.c484
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_tools.h80
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_types.h100
-rw-r--r--libetpan/src/driver/implementation/mh/mhstorage.c192
-rw-r--r--libetpan/src/driver/implementation/mh/mhstorage.h67
-rw-r--r--libetpan/src/driver/implementation/mime-message/mime_message_driver.c914
-rw-r--r--libetpan/src/driver/implementation/mime-message/mime_message_driver.h53
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver.c1180
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached.c1059
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c365
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_message.c169
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_tools.c563
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_tools.h88
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_types.h146
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpstorage.c267
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpstorage.h93
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver.c388
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached.c899
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c355
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_message.c193
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_message.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_tools.c344
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_tools.h82
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_types.h153
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3storage.c284
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3storage.h95
91 files changed, 29843 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/data-message/data_message_driver.c b/libetpan/src/driver/implementation/data-message/data_message_driver.c
new file mode 100644
index 0000000..fbdffcd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/data-message/data_message_driver.c
@@ -0,0 +1,119 @@
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