summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/generic/maildirdriver.c
authorzautrix <zautrix>2004-07-03 16:33:12 (UTC)
committer zautrix <zautrix>2004-07-03 16:33:12 (UTC)
commite3b89230f065c48c84b48c88edb6eb088374c487 (patch) (unidiff)
tree162ea2ef909a6f82ccfcedf45d80d6c821174912 /kmicromail/libetpan/generic/maildirdriver.c
parent2dd6ac0b2d24c91d35ce674a6c26351352df2b15 (diff)
downloadkdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.zip
kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.gz
kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.bz2
Initial revision
Diffstat (limited to 'kmicromail/libetpan/generic/maildirdriver.c') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/generic/maildirdriver.c625
1 files changed, 625 insertions, 0 deletions
diff --git a/kmicromail/libetpan/generic/maildirdriver.c b/kmicromail/libetpan/generic/maildirdriver.c
new file mode 100644
index 0000000..7830ceb
--- a/dev/null
+++ b/kmicromail/libetpan/generic/maildirdriver.c
@@ -0,0 +1,625 @@
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
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 get_messages_list(mailsession * session,
89 struct mailmessage_list ** result);
90
91static int get_envelopes_list(mailsession * session,
92 struct mailmessage_list * env_list);
93
94static int check_folder(mailsession * session);
95
96static int get_message_by_uid(mailsession * session,
97 const char * uid, mailmessage ** result);
98
99static mailsession_driver local_maildir_session_driver = {
100 .sess_name = "maildir",
101
102 .sess_initialize = initialize,
103 .sess_uninitialize = uninitialize,
104
105 .sess_parameters = NULL,
106
107 .sess_connect_stream = NULL,
108 .sess_connect_path = connect_path,
109 .sess_starttls = NULL,
110 .sess_login = NULL,
111 .sess_logout = 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 = check_folder,
119 .sess_examine_folder = NULL,
120 .sess_select_folder = NULL,
121 .sess_expunge_folder = expunge_folder,
122 .sess_status_folder = status_folder,
123 .sess_messages_number = messages_number,
124 .sess_recent_number = recent_number,
125 .sess_unseen_number = unseen_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 = append_message,
132 .sess_copy_message = NULL,
133 .sess_move_message = NULL,
134
135 .sess_get_messages_list = get_messages_list,
136 .sess_get_envelopes_list = get_envelopes_list,
137 .sess_remove_message = NULL,
138#if 0
139 .sess_search_messages = maildriver_generic_search_messages,
140#endif
141
142 .sess_get_message = NULL,
143 .sess_get_message_by_uid = get_message_by_uid,
144};
145
146mailsession_driver * maildir_session_driver = &local_maildir_session_driver;
147
148
149static int flags_store_process(struct maildir * md,
150 struct mail_flags_store * flags_store);
151
152
153static inline struct maildir_session_state_data * get_data(mailsession * session)
154{
155 return session->sess_data;
156}
157
158static struct maildir * get_maildir_session(mailsession * session)
159{
160 return get_data(session)->md_session;
161}
162
163static int initialize(mailsession * session)
164{
165 struct maildir_session_state_data * data;
166
167 data = malloc(sizeof(* data));
168 if (data == NULL)
169 goto err;
170
171 data->md_session = NULL;
172
173 data->md_flags_store = mail_flags_store_new();
174 if (data->md_flags_store == NULL)
175 goto free;
176
177 session->sess_data = data;
178
179 return MAIL_NO_ERROR;
180
181 free:
182 free(data);
183 err:
184 return MAIL_ERROR_MEMORY;
185}
186
187static void uninitialize(mailsession * session)
188{
189 struct maildir_session_state_data * data;
190
191 data = get_data(session);
192
193 if (data->md_session != NULL)
194 flags_store_process(data->md_session, data->md_flags_store);
195
196 mail_flags_store_free(data->md_flags_store);
197 if (data->md_session != NULL)
198 maildir_free(data->md_session);
199
200 free(data);
201
202 session->sess_data = NULL;
203}
204
205
206static int connect_path(mailsession * session, char * path)
207{
208 struct maildir * md;
209 int res;
210 int r;
211
212 if (get_maildir_session(session) != NULL) {
213 res = MAIL_ERROR_BAD_STATE;
214 goto err;
215 }
216
217 md = maildir_new(path);
218 if (md == NULL) {
219 res = MAIL_ERROR_MEMORY;
220 goto err;
221 }
222
223 r = maildir_update(md);
224 if (r != MAILDIR_NO_ERROR) {
225 res = maildirdriver_maildir_error_to_mail_error(r);
226 goto free;
227 }
228
229 get_data(session)->md_session = md;
230
231 return MAIL_NO_ERROR;
232
233 free:
234 maildir_free(md);
235 err:
236 return res;
237}
238
239static int logout(mailsession * session)
240{
241 struct maildir * md;
242
243 check_folder(session);
244
245 md = get_maildir_session(session);
246 if (md == NULL)
247 return MAIL_ERROR_BAD_STATE;
248
249 maildir_free(md);
250 get_data(session)->md_session = NULL;
251
252 return MAIL_NO_ERROR;
253}
254
255/* folders operations */
256
257static int status_folder(mailsession * session, char * mb,
258 uint32_t * result_messages, uint32_t * result_recent,
259 uint32_t * result_unseen)
260{
261 int r;
262 struct maildir * md;
263 unsigned int i;
264 uint32_t messages;
265 uint32_t recent;
266 uint32_t unseen;
267
268 check_folder(session);
269
270 md = get_maildir_session(session);
271 if (md == NULL)
272 return MAIL_ERROR_BAD_STATE;
273
274 r = maildir_update(md);
275 if (r != MAILDIR_NO_ERROR)
276 return maildirdriver_maildir_error_to_mail_error(r);
277
278 messages = 0;
279 recent = 0;
280 unseen = 0;
281 for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i ++) {
282 struct maildir_msg * msg;
283
284 msg = carray_get(md->mdir_msg_list, i);
285 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
286 recent ++;
287 if ((msg->msg_flags & MAILDIR_FLAG_SEEN) == 0)
288 unseen ++;
289 messages ++;
290 }
291
292 * result_messages = messages;
293 * result_recent = recent;
294 * result_unseen = unseen;
295
296 return MAIL_NO_ERROR;
297}
298
299static int messages_number(mailsession * session, char * mb,
300 uint32_t * result)
301{
302 struct maildir * md;
303 int r;
304
305 md = get_maildir_session(session);
306 if (md == NULL)
307 return MAIL_ERROR_BAD_STATE;
308
309 r = maildir_update(md);
310 if (r != MAILDIR_NO_ERROR)
311 return maildirdriver_maildir_error_to_mail_error(r);
312
313 * result = carray_count(md->mdir_msg_list);
314
315 return MAIL_NO_ERROR;
316}
317
318static int unseen_number(mailsession * session, char * mb,
319 uint32_t * result)
320{
321 uint32_t messages;
322 uint32_t recent;
323 uint32_t unseen;
324 int r;
325
326 r = status_folder(session, mb, &messages, &recent, &unseen);
327 if (r != MAIL_NO_ERROR)
328 return r;
329
330 * result = unseen;
331
332 return MAIL_NO_ERROR;
333}
334
335static int recent_number(mailsession * session, char * mb,
336 uint32_t * result)
337{
338 uint32_t messages;
339 uint32_t recent;
340 uint32_t unseen;
341 int r;
342
343 r = status_folder(session, mb, &messages, &recent, &unseen);
344 if (r != MAIL_NO_ERROR)
345 return r;
346
347 * result = recent;
348
349 return MAIL_NO_ERROR;
350}
351
352
353/* messages operations */
354
355static int append_message(mailsession * session,
356 char * message, size_t size)
357{
358 struct maildir * md;
359 int r;
360
361 md = get_maildir_session(session);
362 if (md == NULL)
363 return MAIL_ERROR_BAD_STATE;
364
365 r = maildir_message_add(md, message, size);
366 if (r != MAILDIR_NO_ERROR)
367 return maildirdriver_maildir_error_to_mail_error(r);
368
369 return MAIL_NO_ERROR;
370}
371
372static int get_messages_list(mailsession * session,
373 struct mailmessage_list ** result)
374{
375 struct maildir * md;
376 int r;
377 struct mailmessage_list * env_list;
378 int res;
379
380 md = get_maildir_session(session);
381 if (md == NULL)
382 return MAIL_ERROR_BAD_STATE;
383
384 r = maildir_update(md);
385 if (r != MAILDIR_NO_ERROR) {
386 res = maildirdriver_maildir_error_to_mail_error(r);
387 goto err;
388 }
389
390 r = maildir_get_messages_list(session, md,
391 maildir_message_driver, &env_list);
392 if (r != MAILDIR_NO_ERROR) {
393 res = r;
394 goto free_list;
395 }
396
397 * result = env_list;
398
399 return MAIL_NO_ERROR;
400
401 free_list:
402 mailmessage_list_free(env_list);
403 err:
404 return res;
405}
406
407static int get_envelopes_list(mailsession * session,
408 struct mailmessage_list * env_list)
409{
410 int r;
411 struct maildir * md;
412 unsigned int i;
413 int res;
414
415 check_folder(session);
416
417 md = get_maildir_session(session);
418 if (md == NULL) {
419 res = MAIL_ERROR_BAD_STATE;
420 goto err;
421 }
422
423 r = maildir_update(md);
424 if (r != MAILDIR_NO_ERROR) {
425 res = maildirdriver_maildir_error_to_mail_error(r);
426 goto err;
427 }
428
429 r = maildriver_generic_get_envelopes_list(session, env_list);
430 if (r != MAIL_NO_ERROR) {
431 res = r;
432 goto err;
433 }
434
435 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) {
436 struct maildir_msg * md_msg;
437 mailmessage * msg;
438 uint32_t driver_flags;
439 clist * ext;
440 chashdatum key;
441 chashdatum value;
442
443 msg = carray_get(env_list->msg_tab, i);
444
445 key.data = msg->msg_uid;
446 key.len = strlen(msg->msg_uid);
447 r = chash_get(md->mdir_msg_hash, &key, &value);
448 if (r < 0)
449 continue;
450
451 md_msg = value.data;
452
453 driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags);
454
455 if (msg->msg_flags == NULL) {
456 ext = clist_new();
457 if (ext == NULL) {
458 res = MAIL_ERROR_MEMORY;
459 continue;
460 }
461
462 msg->msg_flags = mail_flags_new(driver_flags, ext);
463 if (msg->msg_flags == NULL) {
464 clist_free(ext);
465 res = MAIL_ERROR_MEMORY;
466 continue;
467 }
468
469 if ((md_msg->msg_flags & MAILDIR_FLAG_NEW) != 0) {
470 mail_flags_store_set(get_data(session)->md_flags_store, msg);
471 }
472 }
473 else {
474 msg->msg_flags->fl_flags &= MAIL_FLAG_FORWARDED;
475 msg->msg_flags->fl_flags |= driver_flags;
476 }
477 }
478
479 return MAIL_NO_ERROR;
480
481 err:
482 return res;
483}
484
485
486static int expunge_folder(mailsession * session)
487{
488 unsigned int i;
489 int r;
490 int res;
491 struct maildir * md;
492
493 check_folder(session);
494
495 md = get_maildir_session(session);
496 if (md == NULL)
497 return MAIL_ERROR_BAD_STATE;
498
499 r = maildir_update(md);
500 if (r != MAILDIR_NO_ERROR) {
501 res = maildirdriver_maildir_error_to_mail_error(r);
502 goto err;
503 }
504
505 for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) {
506 struct maildir_msg * md_msg;
507
508 md_msg = carray_get(md->mdir_msg_list, i);
509
510 if ((md_msg->msg_flags & MAILDIR_FLAG_TRASHED) != 0)
511 maildir_message_remove(md, md_msg->msg_uid);
512 }
513
514 return MAIL_NO_ERROR;
515
516 err:
517 return res;
518}
519
520
521static int flags_store_process(struct maildir * md,
522 struct mail_flags_store * flags_store)
523{
524 unsigned int i;
525
526 if (carray_count(flags_store->fls_tab) == 0)
527 return MAIL_NO_ERROR;
528
529 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
530 mailmessage * msg;
531 uint32_t md_flags;
532
533 msg = carray_get(flags_store->fls_tab, i);
534 md_flags = maildirdriver_flags_to_maildir_flags(msg->msg_flags->fl_flags);
535 md_flags &= ~MAILDIR_FLAG_NEW;
536
537 maildir_message_change_flags(md, msg->msg_uid, md_flags);
538 }
539
540 mail_flags_store_clear(flags_store);
541
542 return MAIL_NO_ERROR;
543}
544
545
546
547static int check_folder(mailsession * session)
548{
549 struct mail_flags_store * flags_store;
550 struct maildir_session_state_data * data;
551 struct maildir * md;
552
553 md = get_maildir_session(session);
554 if (md == NULL)
555 return MAIL_ERROR_BAD_STATE;
556
557 data = get_data(session);
558 flags_store = data->md_flags_store;
559
560 return flags_store_process(md, flags_store);
561}
562
563static int get_message_by_uid(mailsession * session,
564 const char * uid, mailmessage ** result)
565{
566 int r;
567 struct maildir * md;
568 int res;
569 mailmessage * msg;
570 char * msg_filename;
571 struct stat stat_info;
572
573 md = get_maildir_session(session);
574
575 /* update maildir data */
576
577 r = maildir_update(md);
578 if (r != MAILDIR_NO_ERROR) {
579 res = maildirdriver_maildir_error_to_mail_error(r);
580 goto err;
581 }
582
583 msg_filename = maildir_message_get(md, uid);
584 if (msg_filename == NULL) {
585 res = MAIL_ERROR_INVAL;
586 goto err;
587 }
588
589 r = stat(msg_filename, &stat_info);
590 free(msg_filename);
591 if (r < 0) {
592 res = MAIL_ERROR_INVAL;
593 goto err;
594 }
595
596 /* create message */
597
598 msg = mailmessage_new();
599 if (msg == NULL) {
600 res = MAIL_ERROR_MEMORY;
601 goto err;
602 }
603
604 r = mailmessage_init(msg, session, maildir_message_driver,
605 0, stat_info.st_size);
606 if (r != MAIL_NO_ERROR) {
607 mailmessage_free(msg);
608 res = r;
609 goto err;
610 }
611
612 msg->msg_uid = strdup(uid);
613 if (msg->msg_uid == NULL) {
614 mailmessage_free(msg);
615 res = r;
616 goto err;
617 }
618
619 * result = msg;
620
621 return MAIL_NO_ERROR;
622
623 err:
624 return res;
625}