summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/generic/nntpdriver_cached.c
Unidiff
Diffstat (limited to 'kmicromail/libetpan/generic/nntpdriver_cached.c') (more/less context) (show whitespace changes)
-rw-r--r--kmicromail/libetpan/generic/nntpdriver_cached.c1048
1 files changed, 1048 insertions, 0 deletions
diff --git a/kmicromail/libetpan/generic/nntpdriver_cached.c b/kmicromail/libetpan/generic/nntpdriver_cached.c
new file mode 100644
index 0000000..1f8a8af
--- a/dev/null
+++ b/kmicromail/libetpan/generic/nntpdriver_cached.c
@@ -0,0 +1,1048 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpdriver_cached.h"
37
38#include "libetpan-config.h"
39
40#include <string.h>
41#include <stdio.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <fcntl.h>
45#include <unistd.h>
46#include <stdlib.h>
47
48#include "mail_cache_db.h"
49
50#include "mail.h"
51#include "mailmessage.h"
52#include "maildriver_tools.h"
53#include "nntpdriver.h"
54#include "maildriver.h"
55#include "newsnntp.h"
56#include "generic_cache.h"
57#include "imfcache.h"
58#include "maillock.h"
59#include "nntpdriver_cached_message.h"
60#include "nntpdriver_tools.h"
61
62static int nntpdriver_cached_initialize(mailsession * session);
63
64static void nntpdriver_cached_uninitialize(mailsession * session);
65
66static int nntpdriver_cached_parameters(mailsession * session,
67 int id, void * value);
68
69static int nntpdriver_cached_connect_stream(mailsession * session,
70 mailstream * s);
71
72static int nntpdriver_cached_login(mailsession * session,
73 char * userid, char * password);
74
75static int nntpdriver_cached_logout(mailsession * session);
76
77static int nntpdriver_cached_check_folder(mailsession * session);
78
79static int nntpdriver_cached_select_folder(mailsession * session, char * mb);
80
81static int nntpdriver_cached_status_folder(mailsession * session,
82 char * mb,
83 uint32_t * result_messages,
84 uint32_t * result_recent,
85 uint32_t * result_unseen);
86
87static int nntpdriver_cached_messages_number(mailsession * session, char * mb,
88 uint32_t * result);
89
90static int nntpdriver_cached_recent_number(mailsession * session, char * mb,
91 uint32_t * result);
92
93static int nntpdriver_cached_unseen_number(mailsession * session, char * mb,
94 uint32_t * result);
95
96static int nntpdriver_cached_append_message(mailsession * session,
97 char * message, size_t size);
98
99static int
100nntpdriver_cached_get_envelopes_list(mailsession * session,
101 struct mailmessage_list * env_list);
102
103
104static int
105nntpdriver_cached_get_messages_list(mailsession * session,
106 struct mailmessage_list ** result);
107
108static int nntpdriver_cached_list_folders(mailsession * session, char * mb,
109 struct mail_list ** result);
110
111static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb,
112 struct mail_list ** result);
113
114static int nntpdriver_cached_subscribe_folder(mailsession * session,
115 char * mb);
116
117static int nntpdriver_cached_unsubscribe_folder(mailsession * session,
118 char * mb);
119
120static int nntpdriver_cached_get_message(mailsession * session,
121 uint32_t num, mailmessage ** result);
122
123static int nntpdriver_cached_noop(mailsession * session);
124
125static int nntpdriver_cached_get_message_by_uid(mailsession * session,
126 const char * uid,
127 mailmessage ** result);
128
129static mailsession_driver local_nntp_cached_session_driver = {
130 .sess_name = "nntp-cached",
131
132 .sess_initialize = nntpdriver_cached_initialize,
133 .sess_uninitialize = nntpdriver_cached_uninitialize,
134
135 .sess_parameters = nntpdriver_cached_parameters,
136
137 .sess_connect_stream = nntpdriver_cached_connect_stream,
138 .sess_connect_path = NULL,
139 .sess_starttls = NULL,
140 .sess_login = nntpdriver_cached_login,
141 .sess_logout = nntpdriver_cached_logout,
142 .sess_noop = nntpdriver_cached_noop,
143
144 .sess_build_folder_name = NULL,
145 .sess_create_folder = NULL,
146 .sess_delete_folder = NULL,
147 .sess_rename_folder = NULL,
148 .sess_check_folder = nntpdriver_cached_check_folder,
149 .sess_examine_folder = NULL,
150 .sess_select_folder = nntpdriver_cached_select_folder,
151 .sess_expunge_folder = NULL,
152 .sess_status_folder = nntpdriver_cached_status_folder,
153 .sess_messages_number = nntpdriver_cached_messages_number,
154 .sess_recent_number = nntpdriver_cached_recent_number,
155 .sess_unseen_number = nntpdriver_cached_unseen_number,
156 .sess_list_folders = nntpdriver_cached_list_folders,
157 .sess_lsub_folders = nntpdriver_cached_lsub_folders,
158 .sess_subscribe_folder = nntpdriver_cached_subscribe_folder,
159 .sess_unsubscribe_folder = nntpdriver_cached_unsubscribe_folder,
160
161 .sess_append_message = nntpdriver_cached_append_message,
162 .sess_copy_message = NULL,
163 .sess_move_message = NULL,
164
165 .sess_get_messages_list = nntpdriver_cached_get_messages_list,
166 .sess_get_envelopes_list = nntpdriver_cached_get_envelopes_list,
167 .sess_remove_message = NULL,
168#if 0
169 .sess_search_messages = maildriver_generic_search_messages,
170#endif
171
172 .sess_get_message = nntpdriver_cached_get_message,
173 .sess_get_message_by_uid = nntpdriver_cached_get_message_by_uid,
174};
175
176
177mailsession_driver * nntp_cached_session_driver =
178&local_nntp_cached_session_driver;
179
180#define ENV_NAME "env.db"
181#define FLAGS_NAME "flags.db"
182
183
184
185static void read_article_seq(mailsession * session,
186 uint32_t * pfirst, uint32_t * plast);
187
188static void write_article_seq(mailsession * session,
189 uint32_t first, uint32_t last);
190
191
192static inline struct nntp_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)->nntp_ancestor;
201}
202
203static inline struct nntp_session_state_data *
204get_ancestor_data(mailsession * session)
205{
206 return get_ancestor(session)->sess_data;
207}
208
209static inline newsnntp * get_nntp_session(mailsession * session)
210{
211 return get_ancestor_data(session)->nntp_session;
212}
213
214static int nntpdriver_cached_initialize(mailsession * session)
215{
216 struct nntp_cached_session_state_data * data;
217
218 data = malloc(sizeof(* data));
219 if (data == NULL)
220 goto err;
221
222 data->nntp_flags_store = mail_flags_store_new();
223 if (data->nntp_flags_store == NULL)
224 goto free;
225
226 data->nntp_ancestor = mailsession_new(nntp_session_driver);
227 if (data->nntp_ancestor == NULL)
228 goto free_store;
229
230 session->sess_data = data;
231
232 return MAIL_NO_ERROR;
233
234 free_store:
235 mail_flags_store_free(data->nntp_flags_store);
236 free:
237 free(data);
238 err:
239 return MAIL_ERROR_MEMORY;
240}
241
242static int nntp_flags_store_process(char * flags_directory, char * group_name,
243 struct mail_flags_store * flags_store)
244{
245 char filename_flags[PATH_MAX];
246 struct mail_cache_db * cache_db_flags;
247 MMAPString * mmapstr;
248 unsigned int i;
249 int r;
250 int res;
251
252 if (carray_count(flags_store->fls_tab) == 0)
253 return MAIL_NO_ERROR;
254
255 if (group_name == NULL)
256 return MAIL_NO_ERROR;
257
258 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
259 flags_directory, group_name, FLAGS_NAME);
260
261 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
262 if (r < 0) {
263 res = MAIL_ERROR_FILE;
264 goto err;
265 }
266
267 mmapstr = mmap_string_new("");
268 if (mmapstr == NULL) {
269 res = MAIL_ERROR_MEMORY;
270 goto close_db_flags;
271 }
272
273 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
274 mailmessage * msg;
275
276 msg = carray_get(flags_store->fls_tab, i);
277
278 r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr,
279 msg->msg_index, msg->msg_flags);
280 }
281
282 mmap_string_free(mmapstr);
283 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
284
285 mail_flags_store_clear(flags_store);
286
287 return MAIL_NO_ERROR;
288
289 close_db_flags:
290 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
291 err:
292 return res;
293}
294
295static void nntpdriver_cached_uninitialize(mailsession * session)
296{
297 struct nntp_cached_session_state_data * cached_data;
298 struct nntp_session_state_data * ancestor_data;
299
300 cached_data = get_cached_data(session);
301 ancestor_data = get_ancestor_data(session);
302
303 nntp_flags_store_process(cached_data->nntp_flags_directory,
304 ancestor_data->nntp_group_name,
305 cached_data->nntp_flags_store);
306
307 mail_flags_store_free(cached_data->nntp_flags_store);
308
309 mailsession_free(cached_data->nntp_ancestor);
310 free(cached_data);
311
312 session->sess_data = NULL;
313}
314
315static int nntpdriver_cached_parameters(mailsession * session,
316 int id, void * value)
317{
318 struct nntp_cached_session_state_data * cached_data;
319 int r;
320
321 cached_data = get_cached_data(session);
322
323 switch (id) {
324 case NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY:
325 strncpy(cached_data->nntp_cache_directory, value, PATH_MAX);
326 cached_data->nntp_cache_directory[PATH_MAX - 1] = '\0';
327
328 r = generic_cache_create_dir(cached_data->nntp_cache_directory);
329 if (r != MAIL_NO_ERROR)
330 return r;
331
332 return MAIL_NO_ERROR;
333
334 case NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY:
335 strncpy(cached_data->nntp_flags_directory, value, PATH_MAX);
336 cached_data->nntp_flags_directory[PATH_MAX - 1] = '\0';
337
338 r = generic_cache_create_dir(cached_data->nntp_flags_directory);
339 if (r != MAIL_NO_ERROR)
340 return r;
341
342 return MAIL_NO_ERROR;
343
344 default:
345 return mailsession_parameters(get_ancestor(session), id, value);
346 }
347}
348
349static int nntpdriver_cached_connect_stream(mailsession * session,
350 mailstream * s)
351{
352 return mailsession_connect_stream(get_ancestor(session), s);
353}
354
355static int nntpdriver_cached_login(mailsession * session,
356 char * userid, char * password)
357{
358 return mailsession_login(get_ancestor(session), userid, password);
359}
360
361static int nntpdriver_cached_logout(mailsession * session)
362{
363 struct nntp_cached_session_state_data * cached_data;
364 struct nntp_session_state_data * ancestor_data;
365
366 cached_data = get_cached_data(session);
367 ancestor_data = get_ancestor_data(session);
368
369 nntp_flags_store_process(cached_data->nntp_flags_directory,
370 ancestor_data->nntp_group_name,
371 cached_data->nntp_flags_store);
372
373 return mailsession_logout(get_ancestor(session));
374}
375
376static int nntpdriver_cached_select_folder(mailsession * session, char * mb)
377{
378 int r;
379 struct nntp_session_state_data * ancestor_data;
380 struct nntp_cached_session_state_data * cached_data;
381 int res;
382 char key[PATH_MAX];
383
384 cached_data = get_cached_data(session);
385 ancestor_data = get_ancestor_data(session);
386
387 nntp_flags_store_process(cached_data->nntp_flags_directory,
388 ancestor_data->nntp_group_name,
389 cached_data->nntp_flags_store);
390
391 r = mailsession_select_folder(get_ancestor(session), mb);
392 if (r != MAIL_NO_ERROR)
393 return r;
394
395 if (ancestor_data->nntp_group_name == NULL)
396 return MAIL_ERROR_BAD_STATE;
397
398 snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_cache_directory,
399 ancestor_data->nntp_group_name);
400
401 r = generic_cache_create_dir(key);
402 if (r != MAIL_NO_ERROR) {
403 res = r;
404 goto err;
405 }
406
407 snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_flags_directory,
408 ancestor_data->nntp_group_name);
409
410 r = generic_cache_create_dir(key);
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
422static int nntpdriver_cached_check_folder(mailsession * session)
423{
424 struct nntp_session_state_data * ancestor_data;
425 struct nntp_cached_session_state_data * cached_data;
426
427 cached_data = get_cached_data(session);
428 ancestor_data = get_ancestor_data(session);
429
430 nntp_flags_store_process(cached_data->nntp_flags_directory,
431 ancestor_data->nntp_group_name,
432 cached_data->nntp_flags_store);
433
434 return MAIL_NO_ERROR;
435}
436
437
438static int nntpdriver_cached_status_folder(mailsession * session,
439 char * mb, uint32_t * result_messages, uint32_t * result_recent,
440 uint32_t * result_unseen)
441{
442 int res;
443 struct nntp_cached_session_state_data * cached_data;
444 struct nntp_session_state_data * ancestor_data;
445 char filename_flags[PATH_MAX];
446 struct mail_cache_db * cache_db_flags;
447 MMAPString * mmapstr;
448 uint32_t i;
449 int r;
450 uint32_t recent;
451 uint32_t unseen;
452 uint32_t first;
453 uint32_t last;
454 uint32_t count;
455 uint32_t additionnal;
456
457 r = nntpdriver_cached_select_folder(session, mb);
458 if (r != MAIL_NO_ERROR) {
459 res = r;
460 goto err;
461 }
462
463 read_article_seq(session, &first, &last);
464
465 count = 0;
466 recent = 0;
467 unseen = 0;
468
469 ancestor_data = get_ancestor_data(session);
470 cached_data = get_cached_data(session);
471 if (ancestor_data->nntp_group_name == NULL) {
472 res = MAIL_ERROR_BAD_STATE;
473 goto err;
474 }
475
476 if (ancestor_data->nntp_group_info->grp_first > first)
477 first = ancestor_data->nntp_group_info->grp_first;
478 if (last < first)
479 last = ancestor_data->nntp_group_info->grp_last;
480
481 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
482 cached_data->nntp_flags_directory,
483 ancestor_data->nntp_group_name, FLAGS_NAME);
484
485 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
486 if (r < 0) {
487 res = MAIL_ERROR_MEMORY;
488 goto err;
489 }
490
491 mmapstr = mmap_string_new("");
492 if (mmapstr == NULL) {
493 res = MAIL_ERROR_MEMORY;
494 goto close_db_flags;
495 }
496
497 for(i = first ; i <= last ; i++) {
498 struct mail_flags * flags;
499
500 r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
501 i, &flags);
502 if (r == MAIL_NO_ERROR) {
503 if ((flags->fl_flags & MAIL_FLAG_CANCELLED) != 0) {
504 continue;
505 }
506
507 count ++;
508 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
509 recent ++;
510 }
511 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
512 unseen ++;
513 }
514 mail_flags_free(flags);
515 }
516 }
517
518 if ((count == 0) && (first != last)) {
519 count = last - first + 1;
520 recent = count;
521 unseen = count;
522 }
523
524 additionnal = ancestor_data->nntp_group_info->grp_last - last;
525 recent += additionnal;
526 unseen += additionnal;
527
528 mmap_string_free(mmapstr);
529 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
530
531 * result_messages = count;
532 * result_recent = recent;
533 * result_unseen = unseen;
534
535 return MAIL_NO_ERROR;
536
537 close_db_flags:
538 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
539 err:
540 return res;
541}
542
543static int nntpdriver_cached_messages_number(mailsession * session,
544 char * mb,
545 uint32_t * result)
546{
547 uint32_t messages;
548 uint32_t recent;
549 uint32_t unseen;
550 int r;
551
552 r = nntpdriver_cached_status_folder(session, mb,
553 &messages, &recent, &unseen);
554 if (r != MAIL_NO_ERROR)
555 return r;
556
557 * result = messages;
558
559 return MAIL_NO_ERROR;
560}
561
562static int nntpdriver_cached_recent_number(mailsession * session,
563 char * mb,
564 uint32_t * result)
565{
566 uint32_t messages;
567 uint32_t recent;
568 uint32_t unseen;
569 int r;
570
571 r = nntpdriver_cached_status_folder(session, mb,
572 &messages, &recent, &unseen);
573 if (r != MAIL_NO_ERROR)
574 return r;
575
576 * result = recent;
577
578 return MAIL_NO_ERROR;
579}
580
581static int nntpdriver_cached_unseen_number(mailsession * session,
582 char * mb,
583 uint32_t * result)
584{
585 uint32_t messages;
586 uint32_t recent;
587 uint32_t unseen;
588 int r;
589
590 r = nntpdriver_cached_status_folder(session, mb,
591 &messages, &recent, &unseen);
592 if (r != MAIL_NO_ERROR)
593 return r;
594
595 * result = unseen;
596
597 return MAIL_NO_ERROR;
598}
599
600static int nntpdriver_cached_list_folders(mailsession * session, char * mb,
601 struct mail_list ** result)
602{
603 return mailsession_list_folders(get_ancestor(session), mb, result);
604}
605
606static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb,
607 struct mail_list ** result)
608{
609 return mailsession_lsub_folders(get_ancestor(session), mb, result);
610}
611
612static int nntpdriver_cached_subscribe_folder(mailsession * session,
613 char * mb)
614{
615 return mailsession_subscribe_folder(get_ancestor(session), mb);
616}
617
618static int nntpdriver_cached_unsubscribe_folder(mailsession * session,
619 char * mb)
620{
621 return mailsession_unsubscribe_folder(get_ancestor(session), mb);
622}
623
624
625
626/* messages operations */
627
628static int nntpdriver_cached_append_message(mailsession * session,
629 char * message, size_t size)
630{
631 return mailsession_append_message(get_ancestor(session), message, size);
632}
633
634
635
636static int
637get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
638 mailsession * session, uint32_t num,
639 struct mailimf_fields ** result)
640{
641 char keyname[PATH_MAX];
642 int r;
643 struct mailimf_fields * fields;
644 int res;
645
646 snprintf(keyname, PATH_MAX, "%i-envelope", num);
647
648 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
649 if (r != MAIL_NO_ERROR) {
650 res = r;
651 goto err;
652 }
653
654 * result = fields;
655
656 return MAIL_NO_ERROR;
657
658 err:
659 return res;
660}
661
662static int
663write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
664 mailsession * session, uint32_t num,
665 struct mailimf_fields * fields)
666{
667 int r;
668 int res;
669 char keyname[PATH_MAX];
670
671 snprintf(keyname, PATH_MAX, "%i-envelope", num);
672
673 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
674 if (r != MAIL_NO_ERROR) {
675 res = r;
676 goto err;
677 }
678
679 return MAIL_NO_ERROR;
680
681 err:
682 return res;
683}
684
685#define SEQ_FILENAME "articles-seq"
686
687static void read_article_seq(mailsession * session,
688 uint32_t * pfirst, uint32_t * plast)
689{
690 FILE * f;
691 struct nntp_session_state_data * ancestor_data;
692 uint32_t first;
693 uint32_t last;
694 char seq_filename[PATH_MAX];
695 struct nntp_cached_session_state_data * cached_data;
696 int r;
697
698 first = 0;
699 last = 0;
700
701 cached_data = get_cached_data(session);
702 ancestor_data = get_ancestor_data(session);
703
704 if (ancestor_data->nntp_group_name == NULL)
705 return;
706
707 snprintf(seq_filename, PATH_MAX, "%s/%s/%s",
708 cached_data->nntp_cache_directory,
709 ancestor_data->nntp_group_name, SEQ_FILENAME);
710 f = fopen(seq_filename, "r");
711
712 if (f != NULL) {
713 int fd;
714
715 fd = fileno(f);
716
717 r = maillock_read_lock(seq_filename, fd);
718 if (r == 0) {
719 MMAPString * mmapstr;
720 size_t cur_token;
721 char buf[sizeof(uint32_t) * 2];
722 size_t read_size;
723
724 read_size = fread(buf, 1, sizeof(uint32_t) * 2, f);
725 mmapstr = mmap_string_new_len(buf, read_size);
726 if (mmapstr != NULL) {
727 cur_token = 0;
728 r = mailimf_cache_int_read(mmapstr, &cur_token, &first);
729 r = mailimf_cache_int_read(mmapstr, &cur_token, &last);
730
731 mmap_string_free(mmapstr);
732 }
733
734 maillock_read_unlock(seq_filename, fd);
735 }
736 fclose(f);
737 }
738
739 * pfirst = first;
740 * plast = last;
741}
742
743static void write_article_seq(mailsession * session,
744 uint32_t first, uint32_t last)
745{
746 FILE * f;
747 struct nntp_session_state_data * ancestor_data;
748 char seq_filename[PATH_MAX];
749 struct nntp_cached_session_state_data * cached_data;
750 int r;
751 int fd;
752
753 cached_data = get_cached_data(session);
754 ancestor_data = get_ancestor_data(session);
755
756 if (ancestor_data->nntp_group_name == NULL)
757 return;
758
759 snprintf(seq_filename, PATH_MAX, "%s/%s/%s",
760 cached_data->nntp_cache_directory,
761 ancestor_data->nntp_group_name, SEQ_FILENAME);
762
763 fd = creat(seq_filename, S_IRUSR | S_IWUSR);
764 if (fd < 0)
765 return;
766
767 f = fdopen(fd, "w");
768 if (f != NULL) {
769 r = maillock_write_lock(seq_filename, fd);
770 if (r == 0) {
771 MMAPString * mmapstr;
772 size_t cur_token;
773
774 mmapstr = mmap_string_new("");
775 if (mmapstr != NULL) {
776 r = mail_serialize_clear(mmapstr, &cur_token);
777 if (r == MAIL_NO_ERROR) {
778 r = mailimf_cache_int_write(mmapstr, &cur_token, first);
779 r = mailimf_cache_int_write(mmapstr, &cur_token, last);
780
781 fwrite(mmapstr->str, 1, mmapstr->len, f);
782 }
783
784 mmap_string_free(mmapstr);
785 }
786
787 maillock_write_unlock(seq_filename, fd);
788 }
789 fclose(f);
790 }
791 else
792 close(fd);
793}
794
795
796static void get_uid_from_filename(char * filename)
797{
798 char * p;
799
800 if (strcmp(filename, SEQ_FILENAME) == 0)
801 * filename = 0;
802
803 p = strstr(filename, "-header");
804 if (p != NULL)
805 * p = 0;
806}
807
808static int
809nntpdriver_cached_get_envelopes_list(mailsession * session,
810 struct mailmessage_list * env_list)
811{
812 int r;
813 unsigned int i;
814 struct nntp_cached_session_state_data * cached_data;
815 uint32_t first;
816 uint32_t last;
817 struct nntp_session_state_data * ancestor_data;
818 char filename_env[PATH_MAX];
819 char filename_flags[PATH_MAX];
820 struct mail_cache_db * cache_db_env;
821 struct mail_cache_db * cache_db_flags;
822 MMAPString * mmapstr;
823 int res;
824 char cache_dir[PATH_MAX];
825
826 cached_data = get_cached_data(session);
827 ancestor_data = get_ancestor_data(session);
828
829 nntp_flags_store_process(cached_data->nntp_flags_directory,
830 ancestor_data->nntp_group_name,
831 cached_data->nntp_flags_store);
832
833 if (ancestor_data->nntp_group_name == NULL) {
834 res = MAIL_ERROR_BAD_STATE;
835 goto err;
836 }
837
838 /* read articles sequence */
839
840 read_article_seq(session, &first, &last);
841
842 mmapstr = mmap_string_new("");
843 if (mmapstr == NULL) {
844 res = MAIL_ERROR_MEMORY;
845 goto err;
846 }
847
848 snprintf(filename_env, PATH_MAX, "%s/%s/%s",
849 cached_data->nntp_cache_directory,
850 ancestor_data->nntp_group_name, ENV_NAME);
851
852 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
853 if (r < 0) {
854 res = MAIL_ERROR_MEMORY;
855 goto free_mmapstr;
856 }
857
858 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
859 cached_data->nntp_flags_directory,
860 ancestor_data->nntp_group_name, FLAGS_NAME);
861
862 /* fill with cached */
863
864 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
865 mailmessage * msg;
866 struct mailimf_fields * fields;
867
868 msg = carray_get(env_list->msg_tab, i);
869
870 if ((msg->msg_index < first) || (msg->msg_index > last))
871 continue;
872
873 if (msg->msg_fields == NULL) {
874 r = get_cached_envelope(cache_db_env, mmapstr,
875 session, msg->msg_index, &fields);
876 if (r == MAIL_NO_ERROR) {
877 msg->msg_fields = fields;
878 msg->msg_cached = TRUE;
879 }
880 }
881 }
882
883 mail_cache_db_close_unlock(filename_env, cache_db_env);
884
885 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
886
887 if (r != MAIL_NO_ERROR) {
888 res = r;
889 goto free_mmapstr;
890 }
891
892 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
893 if (r < 0) {
894 res = MAIL_ERROR_MEMORY;
895 goto free_mmapstr;
896 }
897
898 /* add flags */
899
900 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
901 mailmessage * msg;
902
903 msg = carray_get(env_list->msg_tab, i);
904
905 if (msg->msg_flags == NULL) {
906 struct mail_flags * flags;
907
908 r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
909 msg->msg_index, &flags);
910 if (r == MAIL_NO_ERROR) {
911 msg->msg_flags = flags;
912 }
913 else {
914 msg->msg_flags = mail_flags_new_empty();
915 if (msg->msg_fields == NULL) {
916 msg->msg_flags->fl_flags |= MAIL_FLAG_CANCELLED;
917 mailmessage_check(msg);
918 }
919 }
920 }
921 }
922
923 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
924
925 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
926 if (r < 0) {
927 res = MAIL_ERROR_MEMORY;
928 goto free_mmapstr;
929 }
930
931 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
932 if (r < 0) {
933 res = MAIL_ERROR_MEMORY;
934 goto close_db_env;
935 }
936
937 /* must write cache */
938
939 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
940 mailmessage * msg;
941
942 msg = carray_get(env_list->msg_tab, i);
943
944 if (msg->msg_fields != NULL) {
945 if (!msg->msg_cached) {
946 r = write_cached_envelope(cache_db_env, mmapstr,
947 session, msg->msg_index, msg->msg_fields);
948 }
949 }
950
951 if (msg->msg_flags != NULL) {
952 r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr,
953 msg->msg_index, msg->msg_flags);
954 }
955 }
956
957 first = 0;
958 last = 0;
959 if (carray_count(env_list->msg_tab) > 0) {
960 mailmessage * msg;
961
962 msg = carray_get(env_list->msg_tab, 0);
963 first = msg->msg_index;
964
965 msg = carray_get(env_list->msg_tab, carray_count(env_list->msg_tab) - 1);
966 last = msg->msg_index;
967 }
968
969 /* write articles sequence */
970
971 write_article_seq(session, first, last);
972
973 /* flush cache */
974
975 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
976
977 /* remove cache files */
978
979 snprintf(cache_dir, PATH_MAX, "%s/%s",
980 cached_data->nntp_cache_directory, ancestor_data->nntp_group_name);
981
982 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
983 mail_cache_db_close_unlock(filename_env, cache_db_env);
984 mmap_string_free(mmapstr);
985
986 maildriver_message_cache_clean_up(cache_dir, env_list,
987 get_uid_from_filename);
988
989 return MAIL_NO_ERROR;
990
991 close_db_env:
992 mail_cache_db_close_unlock(filename_env, cache_db_env);
993 free_mmapstr:
994 mmap_string_free(mmapstr);
995 err:
996 return res;
997}
998
999static int
1000nntpdriver_cached_get_messages_list(mailsession * session,
1001 struct mailmessage_list ** result)
1002{
1003 return nntp_get_messages_list(get_ancestor(session), session,
1004 nntp_cached_message_driver, result);
1005}
1006
1007static int nntpdriver_cached_get_message(mailsession * session,
1008 uint32_t num, mailmessage ** result)
1009{
1010 mailmessage * msg_info;
1011 int r;
1012
1013 msg_info = mailmessage_new();
1014 if (msg_info == NULL)
1015 return MAIL_ERROR_MEMORY;
1016
1017 r = mailmessage_init(msg_info, session, nntp_cached_message_driver, num, 0);
1018 if (r != MAIL_NO_ERROR) {
1019 mailmessage_free(msg_info);
1020 return r;
1021 }
1022
1023 * result = msg_info;
1024
1025 return MAIL_NO_ERROR;
1026}
1027
1028static int nntpdriver_cached_noop(mailsession * session)
1029{
1030 return mailsession_noop(get_ancestor(session));
1031}
1032
1033static int nntpdriver_cached_get_message_by_uid(mailsession * session,
1034 const char * uid,
1035 mailmessage ** result)
1036{
1037 uint32_t num;
1038 char * p;
1039
1040 if (uid == NULL)
1041 return MAIL_ERROR_INVAL;
1042
1043 num = strtoul(uid, &p, 10);
1044 if ((p == uid) || (* p != '\0'))
1045 return MAIL_ERROR_INVAL;
1046
1047 return nntpdriver_cached_get_message(session, num, result);
1048}