summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/generic/mboxdriver.c
Unidiff
Diffstat (limited to 'kmicromail/libetpan/generic/mboxdriver.c') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/generic/mboxdriver.c505
1 files changed, 505 insertions, 0 deletions
diff --git a/kmicromail/libetpan/generic/mboxdriver.c b/kmicromail/libetpan/generic/mboxdriver.c
new file mode 100644
index 0000000..fa3e2ea
--- a/dev/null
+++ b/kmicromail/libetpan/generic/mboxdriver.c
@@ -0,0 +1,505 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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_get_messages_list(mailsession * session,
81 struct mailmessage_list ** result);
82
83static int
84mboxdriver_get_envelopes_list(mailsession * session,
85 struct mailmessage_list * env_list);
86
87static int mboxdriver_remove_message(mailsession * session, uint32_t num);
88
89static int mboxdriver_get_message(mailsession * session,
90 uint32_t num, mailmessage ** result);
91
92static int mboxdriver_get_message_by_uid(mailsession * session,
93 const char * uid,
94 mailmessage ** result);
95
96static mailsession_driver local_mbox_session_driver = {
97 .sess_name = "mbox",
98
99 .sess_initialize = mboxdriver_initialize,
100 .sess_uninitialize = mboxdriver_uninitialize,
101
102 .sess_parameters = mboxdriver_parameters,
103
104 .sess_connect_path = mboxdriver_connect_path,
105 .sess_connect_stream = NULL,
106 .sess_starttls = NULL,
107 .sess_login = NULL,
108 .sess_logout = mboxdriver_logout,
109 .sess_noop = NULL,
110
111 .sess_build_folder_name = NULL,
112 .sess_create_folder = NULL,
113 .sess_delete_folder = NULL,
114 .sess_rename_folder = NULL,
115 .sess_check_folder = NULL,
116 .sess_examine_folder = NULL,
117 .sess_select_folder = NULL,
118 .sess_expunge_folder = mboxdriver_expunge_folder,
119 .sess_status_folder = mboxdriver_status_folder,
120 .sess_messages_number = mboxdriver_messages_number,
121 .sess_recent_number = mboxdriver_messages_number,
122 .sess_unseen_number = mboxdriver_messages_number,
123 .sess_list_folders = NULL,
124 .sess_lsub_folders = NULL,
125 .sess_subscribe_folder = NULL,
126 .sess_unsubscribe_folder = NULL,
127
128 .sess_append_message = mboxdriver_append_message,
129 .sess_copy_message = NULL,
130 .sess_move_message = NULL,
131
132 .sess_get_messages_list = mboxdriver_get_messages_list,
133 .sess_get_envelopes_list = mboxdriver_get_envelopes_list,
134 .sess_remove_message = mboxdriver_remove_message,
135#if 0
136 .sess_search_messages = maildriver_generic_search_messages,
137#endif
138
139 .sess_get_message = mboxdriver_get_message,
140 .sess_get_message_by_uid = mboxdriver_get_message_by_uid,
141};
142
143mailsession_driver * mbox_session_driver = &local_mbox_session_driver;
144
145static inline struct mbox_session_state_data * get_data(mailsession * session)
146{
147 return session->sess_data;
148}
149
150static inline struct mailmbox_folder * get_mbox_session(mailsession * session)
151{
152 return get_data(session)->mbox_folder;
153}
154
155static int mboxdriver_initialize(mailsession * session)
156{
157 struct mbox_session_state_data * data;
158
159 data = malloc(sizeof(* data));
160 if (data == NULL)
161 goto err;
162
163 data->mbox_folder = NULL;
164
165 data->mbox_force_read_only = FALSE;
166 data->mbox_force_no_uid = TRUE;
167
168 session->sess_data = data;
169
170 return MAIL_NO_ERROR;
171
172 err:
173 return MAIL_ERROR_MEMORY;
174}
175
176static void free_state(struct mbox_session_state_data * mbox_data)
177{
178 if (mbox_data->mbox_folder != NULL) {
179 mailmbox_done(mbox_data->mbox_folder);
180 mbox_data->mbox_folder = NULL;
181 }
182}
183
184static void mboxdriver_uninitialize(mailsession * session)
185{
186 struct mbox_session_state_data * data;
187
188 data = get_data(session);
189
190 free_state(data);
191
192 free(data);
193}
194
195static int mboxdriver_parameters(mailsession * session,
196 int id, void * value)
197{
198 struct mbox_session_state_data * data;
199
200 data = get_data(session);
201
202 switch (id) {
203 case MBOXDRIVER_SET_READ_ONLY:
204 {
205 int * param;
206
207 param = value;
208
209 data->mbox_force_read_only = * param;
210 return MAIL_NO_ERROR;
211 }
212
213 case MBOXDRIVER_SET_NO_UID:
214 {
215 int * param;
216
217 param = value;
218
219 data->mbox_force_no_uid = * param;
220 return MAIL_NO_ERROR;
221 }
222 }
223
224 return MAIL_ERROR_INVAL;
225}
226
227
228static int mboxdriver_connect_path(mailsession * session, char * path)
229{
230 struct mbox_session_state_data * mbox_data;
231 struct mailmbox_folder * folder;
232 int r;
233
234 mbox_data = get_data(session);
235
236 if (mbox_data->mbox_folder != NULL)
237 return MAIL_ERROR_BAD_STATE;
238
239 r = mailmbox_init(path,
240 mbox_data->mbox_force_read_only,
241 mbox_data->mbox_force_no_uid,
242 0,
243 &folder);
244
245 if (r != MAILMBOX_NO_ERROR)
246 return mboxdriver_mbox_error_to_mail_error(r);
247
248 mbox_data->mbox_folder = folder;
249
250 return MAIL_NO_ERROR;
251}
252
253static int mboxdriver_logout(mailsession * session)
254{
255 struct mbox_session_state_data * mbox_data;
256
257 mbox_data = get_data(session);
258
259 if (mbox_data->mbox_folder == NULL)
260 return MAIL_ERROR_BAD_STATE;
261
262 free_state(mbox_data);
263
264 mbox_data->mbox_folder = NULL;
265
266 return MAIL_NO_ERROR;
267}
268
269static int mboxdriver_expunge_folder(mailsession * session)
270{
271 int r;
272 struct mbox_session_state_data * mbox_data;
273
274 mbox_data = get_data(session);
275
276 if (mbox_data->mbox_folder == NULL)
277 return MAIL_ERROR_BAD_STATE;
278
279 r = mailmbox_expunge(mbox_data->mbox_folder);
280 if (r != MAILMBOX_NO_ERROR)
281 return mboxdriver_mbox_error_to_mail_error(r);
282
283 return MAIL_NO_ERROR;
284}
285
286static int mboxdriver_status_folder(mailsession * session, char * mb,
287 uint32_t * result_messages, uint32_t * result_recent,
288 uint32_t * result_unseen)
289{
290 uint32_t count;
291 int r;
292
293 r = mboxdriver_messages_number(session, mb, &count);
294 if (r != MAIL_NO_ERROR)
295 return r;
296
297 * result_messages = count;
298 * result_recent = count;
299 * result_unseen = count;
300
301 return MAIL_NO_ERROR;
302}
303
304static int mboxdriver_messages_number(mailsession * session, char * mb,
305 uint32_t * result)
306{
307 struct mailmbox_folder * folder;
308 int r;
309
310 folder = get_mbox_session(session);
311 if (folder == NULL)
312 return MAIL_ERROR_STATUS;
313
314 r = mailmbox_validate_read_lock(folder);
315 if (r != MAIL_NO_ERROR)
316 return r;
317
318 mailmbox_read_unlock(folder);
319
320 * result = carray_count(folder->mb_tab) - folder->mb_deleted_count;
321
322 return MAILMBOX_NO_ERROR;
323}
324
325/* messages operations */
326
327static int mboxdriver_append_message(mailsession * session,
328 char * message, size_t size)
329{
330 int r;
331 struct mailmbox_folder * folder;
332
333 folder = get_mbox_session(session);
334 if (folder == NULL)
335 return MAIL_ERROR_APPEND;
336
337 r = mailmbox_append_message(folder, message, size);
338
339 switch (r) {
340 case MAILMBOX_ERROR_FILE:
341 return MAIL_ERROR_DISKSPACE;
342 default:
343 return mboxdriver_mbox_error_to_mail_error(r);
344 }
345}
346
347static int mboxdriver_get_messages_list(mailsession * session,
348 struct mailmessage_list ** result)
349{
350 struct mailmbox_folder * folder;
351 int res;
352
353 folder = get_mbox_session(session);
354 if (folder == NULL) {
355 res = MAIL_ERROR_BAD_STATE;
356 goto err;
357 }
358
359 return mbox_get_messages_list(folder, session, mbox_message_driver, result);
360
361 err:
362 return res;
363}
364
365static int
366mboxdriver_get_envelopes_list(mailsession * session,
367 struct mailmessage_list * env_list)
368{
369 struct mailmbox_folder * folder;
370 unsigned int i;
371 int r;
372 int res;
373
374 folder = get_mbox_session(session);
375 if (folder == NULL) {
376 res = MAIL_ERROR_BAD_STATE;
377 goto err;
378 }
379
380 r = mailmbox_validate_read_lock(folder);
381 if (r != MAILMBOX_NO_ERROR) {
382 res = mboxdriver_mbox_error_to_mail_error(r);
383 goto err;
384 }
385
386 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
387 mailmessage * msg;
388 struct mailimf_fields * fields;
389 char * headers;
390 size_t headers_len;
391 size_t cur_token;
392
393 msg = carray_get(env_list->msg_tab, i);
394 if (msg == NULL)
395 continue;
396
397 if (msg->msg_fields != NULL)
398 continue;
399
400 r = mailmbox_fetch_msg_headers_no_lock(folder,
401 msg->msg_index, &headers, &headers_len);
402 if (r != MAILMBOX_NO_ERROR) {
403 res = mboxdriver_mbox_error_to_mail_error(r);
404 goto unlock;
405 }
406
407 cur_token = 0;
408 r = mailimf_envelope_fields_parse(headers, headers_len,
409 &cur_token, &fields);
410
411 if (r != MAILIMF_NO_ERROR)
412 continue;
413
414 msg->msg_fields = fields;
415 }
416
417 mailmbox_read_unlock(folder);
418
419 return MAIL_NO_ERROR;
420
421 unlock:
422 mailmbox_read_unlock(folder);
423 err:
424 return res;
425}
426
427
428static int mboxdriver_remove_message(mailsession * session, uint32_t num)
429{
430 int r;
431 struct mailmbox_folder * folder;
432
433 folder = get_mbox_session(session);
434 if (folder == NULL)
435 return MAIL_ERROR_DELETE;
436
437 r = mailmbox_delete_msg(folder, num);
438
439 return mboxdriver_mbox_error_to_mail_error(r);
440}
441
442static int mboxdriver_get_message(mailsession * session,
443 uint32_t num, mailmessage ** result)
444{
445 mailmessage * msg_info;
446 int r;
447
448 msg_info = mailmessage_new();
449 if (msg_info == NULL)
450 return MAIL_ERROR_MEMORY;
451
452 r = mailmessage_init(msg_info, session, mbox_message_driver, num, 0);
453 if (r != MAIL_NO_ERROR) {
454 mailmessage_free(msg_info);
455 return r;
456 }
457
458 * result = msg_info;
459
460 return MAIL_NO_ERROR;
461}
462
463static int mboxdriver_get_message_by_uid(mailsession * session,
464 const char * uid,
465 mailmessage ** result)
466{
467 uint32_t num;
468 char * p;
469 chashdatum key;
470 chashdatum data;
471 struct mailmbox_msg_info * info;
472 struct mailmbox_folder * folder;
473 int r;
474
475 if (uid == NULL)
476 return MAIL_ERROR_INVAL;
477
478 num = strtoul(uid, &p, 10);
479 if (p == uid || * p != '-')
480 return MAIL_ERROR_INVAL;
481
482 folder = get_mbox_session(session);
483 if (folder == NULL)
484 return MAIL_ERROR_BAD_STATE;
485
486 key.data = &num;
487 key.len = sizeof(num);
488
489 r = chash_get(folder->mb_hash, &key, &data);
490 if (r == 0) {
491 char * body_len_p = p + 1;
492 size_t body_len;
493
494 info = data.data;
495 /* Check if the cached message has the same UID */
496 body_len = strtoul(body_len_p, &p, 10);
497 if (p == body_len_p || * p != '\0')
498 return MAIL_ERROR_INVAL;
499
500 if (body_len == info->msg_body_len)
501 return mboxdriver_get_message(session, num, result);
502 }
503
504 return MAIL_ERROR_MSG_NOT_FOUND;
505}