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