summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/mh
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/mh') (more/less context) (ignore whitespace changes)
-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
13 files changed, 3872 insertions, 0 deletions
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