summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/nntp
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/nntp') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver.c1180
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached.c1059
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c365
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_message.c169
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_tools.c563
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_tools.h88
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_types.h146
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpstorage.c267
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpstorage.h93
13 files changed, 4138 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver.c b/libetpan/src/driver/implementation/nntp/nntpdriver.c
new file mode 100644
index 0000000..15b764f
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver.c
@@ -0,0 +1,1180 @@
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.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "mail.h"
42#include "mailmessage.h"
43#include "nntpdriver_tools.h"
44#include "maildriver_tools.h"
45#include "nntpdriver_message.h"
46
47static int nntpdriver_initialize(mailsession * session);
48
49static void nntpdriver_uninitialize(mailsession * session);
50
51static int nntpdriver_parameters(mailsession * session,
52 int id, void * value);
53
54static int nntpdriver_connect_stream(mailsession * session, mailstream * s);
55
56static int nntpdriver_login(mailsession * session,
57 char * userid, char * password);
58
59static int nntpdriver_logout(mailsession * session);
60
61static int nntpdriver_status_folder(mailsession * session, char * mb,
62 uint32_t * result_messages,
63 uint32_t * result_recent,
64 uint32_t * result_unseen);
65
66static int nntpdriver_messages_number(mailsession * session, char * mb,
67 uint32_t * result);
68
69static int nntpdriver_append_message(mailsession * session,
70 char * message, size_t size);
71
72static int nntpdriver_append_message_flags(mailsession * session,
73 char * message, size_t size, struct mail_flags * flags);
74
75static int
76nntpdriver_get_envelopes_list(mailsession * session,
77 struct mailmessage_list * env_list);
78
79
80static int nntpdriver_get_messages_list(mailsession * session,
81 struct mailmessage_list ** result);
82
83static int nntpdriver_list_folders(mailsession * session, char * mb,
84 struct mail_list ** result);
85
86static int nntpdriver_lsub_folders(mailsession * session, char * mb,
87 struct mail_list ** result);
88
89static int nntpdriver_subscribe_folder(mailsession * session, char * mb);
90
91static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb);
92
93static int nntpdriver_get_message(mailsession * session,
94 uint32_t num, mailmessage ** result);
95
96static int nntpdriver_get_message_by_uid(mailsession * session,
97 const char * uid,
98 mailmessage ** result);
99
100static int nntpdriver_noop(mailsession * session);
101
102static mailsession_driver local_nntp_session_driver = {
103 .sess_name = "nntp",
104
105 .sess_initialize = nntpdriver_initialize,
106 .sess_uninitialize = nntpdriver_uninitialize,
107
108 .sess_parameters = nntpdriver_parameters,
109
110 .sess_connect_stream = nntpdriver_connect_stream,
111 .sess_connect_path = NULL,
112 .sess_starttls = NULL,
113 .sess_login = nntpdriver_login,
114 .sess_logout = nntpdriver_logout,
115 .sess_noop = nntpdriver_noop,
116
117 .sess_build_folder_name = NULL,
118 .sess_create_folder = NULL,
119 .sess_delete_folder = NULL,
120 .sess_rename_folder = NULL,
121 .sess_check_folder = NULL,
122 .sess_examine_folder = NULL,
123 .sess_select_folder = nntpdriver_select_folder,
124 .sess_expunge_folder = NULL,
125 .sess_status_folder = nntpdriver_status_folder,
126 .sess_messages_number = nntpdriver_messages_number,
127 .sess_recent_number = nntpdriver_messages_number,
128 .sess_unseen_number = nntpdriver_messages_number,
129 .sess_list_folders = nntpdriver_list_folders,
130 .sess_lsub_folders = nntpdriver_lsub_folders,
131 .sess_subscribe_folder = nntpdriver_subscribe_folder,
132 .sess_unsubscribe_folder = nntpdriver_unsubscribe_folder,
133
134 .sess_append_message = nntpdriver_append_message,
135 .sess_append_message_flags = nntpdriver_append_message_flags,
136 .sess_copy_message = NULL,
137 .sess_move_message = NULL,
138
139 .sess_get_messages_list = nntpdriver_get_messages_list,
140 .sess_get_envelopes_list = nntpdriver_get_envelopes_list,
141 .sess_remove_message = NULL,
142#if 0
143 .sess_search_messages = maildriver_generic_search_messages,
144#endif
145
146 .sess_get_message = nntpdriver_get_message,
147 .sess_get_message_by_uid = nntpdriver_get_message_by_uid,
148};
149
150
151mailsession_driver * nntp_session_driver = &local_nntp_session_driver;
152
153static inline struct nntp_session_state_data *
154get_data(mailsession * session)
155{
156 return session->sess_data;
157}
158
159static inline newsnntp * get_nntp_session(mailsession * session)
160{
161 return get_data(session)->nntp_session;
162}
163
164static int nntpdriver_initialize(mailsession * session)
165{
166 struct nntp_session_state_data * data;
167 newsnntp * nntp;
168
169 nntp = newsnntp_new(0, NULL);
170 if (nntp == NULL)
171 goto err;
172
173 data = malloc(sizeof(* data));
174 if (data == NULL)
175 goto free;
176
177 data->nntp_session = nntp;
178
179 data->nntp_userid = NULL;
180 data->nntp_password = NULL;
181
182 data->nntp_group_info = NULL;
183 data->nntp_group_name = NULL;
184
185 data->nntp_subscribed_list = clist_new();
186 if (data->nntp_subscribed_list == NULL)
187 goto free_data;
188
189 data->nntp_max_articles = 0;
190
191 data->nntp_mode_reader = FALSE;
192
193 session->sess_data = data;
194
195 return MAIL_NO_ERROR;
196
197 free_data:
198 free(data);
199 free:
200 newsnntp_free(nntp);
201 err:
202 return MAIL_ERROR_MEMORY;
203}
204
205static void nntpdriver_uninitialize(mailsession * session)
206{
207 struct nntp_session_state_data * data;
208
209 data = get_data(session);
210
211 clist_foreach(data->nntp_subscribed_list, (clist_func) free, NULL);
212 clist_free(data->nntp_subscribed_list);
213
214 if (data->nntp_group_info != NULL)
215 newsnntp_group_free(data->nntp_group_info);
216
217 if (data->nntp_group_name != NULL)
218 free(data->nntp_group_name);
219
220 if (data->nntp_userid != NULL)
221 free(data->nntp_userid);
222
223 if (data->nntp_password != NULL)
224 free(data->nntp_password);
225
226 newsnntp_free(data->nntp_session);
227 free(data);
228
229 session->sess_data = NULL;
230}
231
232
233static int nntpdriver_parameters(mailsession * session,
234 int id, void * value)
235{
236 struct nntp_session_state_data * data;
237
238 data = get_data(session);
239
240 switch (id) {
241 case NNTPDRIVER_SET_MAX_ARTICLES:
242 {
243 uint32_t * param;
244
245 param = value;
246
247 data->nntp_max_articles = * param;
248 return MAIL_NO_ERROR;
249 }
250 }
251
252 return MAIL_ERROR_INVAL;
253}
254
255
256static int add_to_list(mailsession * session, char * mb)
257{
258 char * new_mb;
259 int r;
260 struct nntp_session_state_data * data;
261
262 data = get_data(session);
263
264 new_mb = strdup(mb);
265 if (new_mb == NULL)
266 return -1;
267
268 r = clist_append(data->nntp_subscribed_list, new_mb);
269 if (r < 0) {
270 free(mb);
271 return -1;
272 }
273
274 return 0;
275}
276
277static int remove_from_list(mailsession * session, char * mb)
278{
279 clistiter * cur;
280 struct nntp_session_state_data * data;
281
282 data = get_data(session);
283
284 for(cur = clist_begin(data->nntp_subscribed_list) ; cur != NULL ;
285 cur = clist_next(cur)) {
286 char * cur_name;
287
288 cur_name = clist_content(cur);
289 if (strcmp(cur_name, mb) == 0) {
290 clist_delete(data->nntp_subscribed_list, cur);
291 free(cur_name);
292 return 0;
293 }
294 }
295
296 return -1;
297}
298
299
300static int nntpdriver_connect_stream(mailsession * session, mailstream * s)
301{
302 int r;
303
304 r = newsnntp_connect(get_nntp_session(session), s);
305
306 switch (r) {
307 case NEWSNNTP_NO_ERROR:
308 return MAIL_NO_ERROR_NON_AUTHENTICATED;
309
310 default:
311 return nntpdriver_nntp_error_to_mail_error(r);
312 }
313}
314
315static int nntpdriver_login(mailsession * session,
316 char * userid, char * password)
317{
318 struct nntp_session_state_data * data;
319 char * new_userid;
320 char * new_password;
321
322 data = get_data(session);
323
324 if (userid != NULL) {
325 new_userid = strdup(userid);
326 if (new_userid == NULL)
327 goto err;
328 }
329 else
330 new_userid = NULL;
331
332 if (password != NULL) {
333 new_password = strdup(password);
334 if (new_password == NULL)
335 goto free_uid;
336 }
337 else
338 new_password = NULL;
339
340 data->nntp_userid = new_userid;
341 data->nntp_password = new_password;
342
343 return MAIL_NO_ERROR;
344
345 free_uid:
346 if (new_userid != NULL)
347 free(new_userid);
348 err:
349 return MAIL_ERROR_MEMORY;
350}
351
352static int nntpdriver_logout(mailsession * session)
353{
354 int r;
355
356 r = newsnntp_quit(get_nntp_session(session));
357
358 return nntpdriver_nntp_error_to_mail_error(r);
359}
360
361
362static int nntpdriver_status_folder(mailsession * session, char * mb,
363 uint32_t * result_messages,
364 uint32_t * result_recent,
365 uint32_t * result_unseen)
366{
367 uint32_t count;
368 int r;
369
370 r = nntpdriver_select_folder(session, mb);
371 if (r != MAIL_NO_ERROR)
372 return r;
373
374 r = nntpdriver_messages_number(session, mb, &count);
375 if (r != MAIL_NO_ERROR)
376 return r;
377
378 * result_messages = count;
379 * result_recent = count;
380 * result_unseen = count;
381
382 return MAIL_NO_ERROR;
383}
384
385static int nntpdriver_messages_number(mailsession * session, char * mb,
386 uint32_t * result)
387{
388 int r;
389 struct nntp_session_state_data * data;
390
391 if (mb != NULL) {
392 r = nntpdriver_select_folder(session, mb);
393 if (r != MAIL_NO_ERROR)
394 return r;
395 }
396
397 data = get_data(session);
398
399 if (data->nntp_group_info == NULL)
400 return MAIL_ERROR_FOLDER_NOT_FOUND;
401
402 * result = data->nntp_group_info->grp_last -
403 data->nntp_group_info->grp_first + 1;
404
405 return MAIL_NO_ERROR;
406}
407
408static int nntpdriver_list_folders(mailsession * session, char * mb,
409 struct mail_list ** result)
410{
411 int r;
412 clist * group_list;
413 newsnntp * nntp;
414 clistiter * cur;
415 char * new_mb;
416 int done;
417 clist * list;
418 struct mail_list * ml;
419 int res;
420
421 nntp = get_nntp_session(session);
422
423 new_mb = NULL;
424 if ((mb != NULL) && (*mb != '\0')) {
425 new_mb = malloc(strlen(mb) + 3);
426 if (new_mb == NULL) {
427 res = MAIL_ERROR_MEMORY;
428 goto err;
429 }
430 strcpy(new_mb, mb);
431 strcat(new_mb, ".*");
432 }
433
434 done = FALSE;
435 do {
436 if (new_mb != NULL)
437 r = newsnntp_list_active(nntp, new_mb, &group_list);
438 else
439 r = newsnntp_list(nntp, &group_list);
440
441 switch (r) {
442 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
443 r = nntpdriver_authenticate_user(session);
444 if (r != MAIL_NO_ERROR) {
445 res = r;
446 goto err;
447 }
448 break;
449
450 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
451 r = nntpdriver_authenticate_password(session);
452 if (r != MAIL_NO_ERROR) {
453 res = r;
454 goto err;
455 }
456 break;
457
458 case NEWSNNTP_NO_ERROR:
459 if (new_mb != NULL)
460 free(new_mb);
461 done = TRUE;
462 break;
463
464 default:
465 if (new_mb != NULL)
466 free(new_mb);
467 return nntpdriver_nntp_error_to_mail_error(r);
468 }
469 }
470 while (!done);
471
472 list = clist_new();
473 if (list == NULL) {
474 res = MAIL_ERROR_MEMORY;
475 goto err;
476 }
477
478 for(cur = clist_begin(group_list) ; cur != NULL ;
479 cur = clist_next(cur)) {
480 struct newsnntp_group_info * info;
481 char * new_name;
482
483 info = clist_content(cur);
484 new_name = strdup(info->grp_name);
485 if (new_name == NULL) {
486 res = MAIL_ERROR_MEMORY;
487 goto free_list;
488 }
489
490 r = clist_append(list, new_name);
491 if (r < 0) {
492 free(new_name);
493 res = MAIL_ERROR_MEMORY;
494 goto free_list;
495 }
496 }
497
498 ml = mail_list_new(list);
499 if (ml == NULL) {
500 res = MAIL_ERROR_MEMORY;
501 goto free_list;
502 }
503
504 newsnntp_list_free(group_list);
505
506 * result = ml;
507
508 return MAIL_NO_ERROR;
509
510 free_list:
511 clist_foreach(list, (clist_func) free, NULL);
512 clist_free(list);
513 newsnntp_list_free(group_list);
514 err:
515 return res;
516}
517
518static int nntpdriver_lsub_folders(mailsession * session, char * mb,
519 struct mail_list ** result)
520{
521 clist * subscribed;
522 clist * lsub_result;
523 clistiter * cur;
524 struct mail_list * lsub;
525 size_t length;
526 int res;
527 int r;
528 struct nntp_session_state_data * data;
529
530 length = strlen(mb);
531
532 data = get_data(session);
533
534 subscribed = data->nntp_subscribed_list;
535 lsub_result = clist_new();
536 if (lsub_result == NULL) {
537 res = MAIL_ERROR_MEMORY;
538 goto err;
539 }
540
541 for(cur = clist_begin(subscribed) ; cur != NULL ;
542 cur = clist_next(cur)) {
543 char * cur_mb;
544 char * new_mb;
545
546 cur_mb = clist_content(cur);
547
548 if (strncmp(mb, cur_mb, length) == 0) {
549 new_mb = strdup(cur_mb);
550 if (new_mb == NULL) {
551 res = MAIL_ERROR_MEMORY;
552 goto free_list;
553 }
554
555 r = clist_append(lsub_result, new_mb);
556 if (r < 0) {
557 free(new_mb);
558 res = MAIL_ERROR_MEMORY;
559 goto free_list;
560 }
561 }
562 }
563
564 lsub = mail_list_new(lsub_result);
565 if (lsub == NULL) {
566 res = MAIL_ERROR_MEMORY;
567 goto free_list;
568 }
569
570 * result = lsub;
571
572 return MAIL_NO_ERROR;
573
574 free_list:
575 clist_foreach(lsub_result, (clist_func) free, NULL);
576 clist_free(lsub_result);
577 err:
578 return res;
579}
580
581static int nntpdriver_subscribe_folder(mailsession * session, char * mb)
582{
583 int r;
584
585 r = add_to_list(session, mb);
586 if (r < 0)
587 return MAIL_ERROR_SUBSCRIBE;
588
589 return MAIL_NO_ERROR;
590}
591
592static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb)
593{
594 int r;
595
596 r = remove_from_list(session, mb);
597 if (r < 0)
598 return MAIL_ERROR_UNSUBSCRIBE;
599
600 return MAIL_NO_ERROR;
601}
602
603
604
605/* messages operations */
606
607static int nntpdriver_append_message(mailsession * session,
608 char * message, size_t size)
609{
610 int r;
611 struct nntp_session_state_data * data;
612
613 data = get_data(session);
614
615 do {
616 r = newsnntp_post(get_nntp_session(session), message, size);
617 switch (r) {
618 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
619 r = nntpdriver_authenticate_user(session);
620 if (r != MAIL_NO_ERROR)
621 return r;
622 break;
623
624 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
625 r = nntpdriver_authenticate_password(session);
626 if (r != MAIL_NO_ERROR)
627 return r;
628 break;
629
630 default:
631 return nntpdriver_nntp_error_to_mail_error(r);
632 }
633 }
634 while (1);
635}
636
637static int nntpdriver_append_message_flags(mailsession * session,
638 char * message, size_t size, struct mail_flags * flags)
639{
640 return nntpdriver_append_message(session, message, size);
641}
642
643
644static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item,
645 struct mailimf_fields ** result);
646
647
648static int
649nntpdriver_get_envelopes_list(mailsession * session,
650 struct mailmessage_list * env_list)
651{
652 newsnntp * nntp;
653 int r;
654 struct nntp_session_state_data * data;
655 clist * list;
656 int done;
657 clistiter * cur;
658 uint32_t first_seq;
659 unsigned int i;
660
661 nntp = get_nntp_session(session);
662
663 data = get_data(session);
664
665 if (data->nntp_group_info == NULL)
666 return MAIL_ERROR_BAD_STATE;
667
668 first_seq = data->nntp_group_info->grp_first;
669
670 if (carray_count(env_list->msg_tab) > 0) {
671 mailmessage * msg;
672
673 msg = carray_get(env_list->msg_tab, 0);
674
675 first_seq = msg->msg_index;
676 }
677
678 if (carray_count(env_list->msg_tab) > 0) {
679 i = carray_count(env_list->msg_tab) - 1;
680 while (1) {
681 mailmessage * msg;
682
683 msg = carray_get(env_list->msg_tab, i);
684
685 if (msg->msg_fields != NULL) {
686 first_seq = msg->msg_index + 1;
687 break;
688 }
689
690 if (i == 0)
691 break;
692
693 i --;
694 }
695 }
696
697 if (first_seq > data->nntp_group_info->grp_last) {
698 list = NULL;
699 }
700 else {
701 done = FALSE;
702 do {
703 r = newsnntp_xover_range(nntp, first_seq,
704 data->nntp_group_info->grp_last, &list);
705
706 switch (r) {
707 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
708 r = nntpdriver_authenticate_user(session);
709 if (r != MAIL_NO_ERROR)
710 return r;
711 break;
712
713 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
714 r = nntpdriver_authenticate_password(session);
715 if (r != MAIL_NO_ERROR)
716 return r;
717 break;
718
719 case NEWSNNTP_NO_ERROR:
720 done = TRUE;
721 break;
722
723 default:
724 return nntpdriver_nntp_error_to_mail_error(r);
725 }
726 }
727 while (!done);
728 }
729
730#if 0
731 i = 0;
732 j = 0;
733
734 if (list != NULL) {
735 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
736 struct newsnntp_xover_resp_item * item;
737 struct mailimf_fields * fields;
738
739 item = clist_content(cur);
740
741 while (i < carray_count(env_list->msg_tab)) {
742 mailmessage * info;
743
744 info = carray_get(env_list->msg_tab, i);
745
746 if (item->ovr_article == info->msg_index) {
747
748 if (info->fields == NULL) {
749 r = xover_resp_to_fields(item, &fields);
750 if (r == MAIL_NO_ERROR) {
751 info->fields = fields;
752 }
753
754 info->size = item->ovr_size;
755
756 carray_set(env_list->msg_tab, j, info);
757 j ++;
758 i ++;
759 break;
760 }
761 else {
762 carray_set(env_list->msg_tab, j, info);
763 j ++;
764 }
765 }
766 else {
767 if (info->fields != NULL) {
768 carray_set(env_list->msg_tab, j, info);
769 j ++;
770 }
771 else {
772 if (info->flags != NULL) {
773 info->flags->flags &= ~MAIL_FLAG_NEW;
774 info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED;
775 mailmessage_check(info);
776 }
777 mailmessage_free(info);
778 carray_set(env_list->msg_tab, i, NULL);
779 }
780 }
781
782 i ++;
783 }
784 }
785 }
786
787 while (i < carray_count(env_list->msg_tab)) {
788 mailmessage * info;
789
790 info = carray_get(env_list->msg_tab, i);
791 if (info->fields != NULL) {
792 carray_set(env_list->msg_tab, j, info);
793 j ++;
794 }
795 else {
796 if (info->flags != NULL) {
797 info->flags->flags &= ~MAIL_FLAG_NEW;
798 info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED;
799 mailmessage_check(info);
800 }
801 mailmessage_free(info);
802 carray_set(env_list->msg_tab, i, NULL);
803 }
804
805 i ++;
806 }
807
808 r = carray_set_size(env_list->msg_tab, j);
809 if (r < 0) {
810 if (list != NULL)
811 newsnntp_xover_resp_list_free(list);
812 return MAIL_ERROR_MEMORY;
813 }
814#endif
815 i = 0;
816
817 if (list != NULL) {
818 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
819 struct newsnntp_xover_resp_item * item;
820 struct mailimf_fields * fields;
821
822 item = clist_content(cur);
823
824 while (i < carray_count(env_list->msg_tab)) {
825 mailmessage * info;
826
827 info = carray_get(env_list->msg_tab, i);
828
829 if (item->ovr_article == info->msg_index) {
830
831 if (info->msg_fields == NULL) {
832 r = xover_resp_to_fields(item, &fields);
833 if (r == MAIL_NO_ERROR) {
834 info->msg_fields = fields;
835 }
836
837 info->msg_size = item->ovr_size;
838
839 i ++;
840 break;
841 }
842 }
843#if 0
844 else if ((info->fields == NULL) && (info->flags != NULL)) {
845 info->flags->flags &= ~MAIL_FLAG_NEW;
846 info->flags->flags |= MAIL_FLAG_CANCELLED;
847 mailmessage_check(info);
848 }
849#endif
850
851 i ++;
852 }
853 }
854 }
855
856#if 0
857 while (i < env_list->msg_tab->len) {
858 mailmessage * info;
859
860 info = carray_get(env_list->msg_tab, i);
861 if ((info->fields == NULL) && (info->flags != NULL)) {
862 info->flags->flags &= ~MAIL_FLAG_NEW;
863 info->flags->flags |= MAIL_FLAG_CANCELLED;
864 mailmessage_check(info);
865 }
866
867 i ++;
868 }
869#endif
870
871 if (list != NULL)
872 newsnntp_xover_resp_list_free(list);
873
874 return MAIL_NO_ERROR;
875}
876
877
878static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item,
879 struct mailimf_fields ** result)
880{
881 size_t cur_token;
882 clist * list;
883 int r;
884 struct mailimf_fields * fields;
885 int res;
886
887 list = clist_new();
888 if (list == NULL) {
889 res = MAIL_ERROR_MEMORY;
890 goto err;
891 }
892
893 if (item->ovr_subject != NULL) {
894 char * subject_str;
895 struct mailimf_subject * subject;
896 struct mailimf_field * field;
897
898 subject_str = strdup(item->ovr_subject);
899 if (subject_str == NULL) {
900 res = MAIL_ERROR_MEMORY;
901 goto free_list;
902 }
903
904 subject = mailimf_subject_new(subject_str);
905 if (subject == NULL) {
906 free(subject_str);
907 res = MAIL_ERROR_MEMORY;
908 goto free_list;
909 }
910
911 field = mailimf_field_new(MAILIMF_FIELD_SUBJECT,
912 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
913 NULL, NULL, NULL,
914 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
915 NULL, subject, NULL, NULL, NULL);
916 if (field == NULL) {
917 mailimf_subject_free(subject);
918 res = MAIL_ERROR_MEMORY;
919 goto free_list;
920 }
921
922 r = clist_append(list, field);
923 if (r < 0) {
924 mailimf_field_free(field);
925 res = MAIL_ERROR_MEMORY;
926 goto free_list;
927 }
928 }
929
930 if (item->ovr_author != NULL) {
931 struct mailimf_mailbox_list * mb_list;
932 struct mailimf_from * from;
933 struct mailimf_field * field;
934
935 cur_token = 0;
936 r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author),
937 &cur_token, &mb_list);
938 switch (r) {
939 case MAILIMF_NO_ERROR:
940 from = mailimf_from_new(mb_list);
941 if (from == NULL) {
942 mailimf_mailbox_list_free(mb_list);
943 res = MAIL_ERROR_MEMORY;
944 goto free_list;
945 }
946
947 field = mailimf_field_new(MAILIMF_FIELD_FROM,
948 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
949 NULL, NULL, from,
950 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
951 NULL, NULL, NULL, NULL, NULL);
952 if (field == NULL) {
953 mailimf_from_free(from);
954 res = MAIL_ERROR_MEMORY;
955 goto free_list;
956 }
957
958 r = clist_append(list, field);
959 if (r < 0) {
960 mailimf_field_free(field);
961 res = MAIL_ERROR_MEMORY;
962 goto free_list;
963 }
964 break;
965
966 case MAILIMF_ERROR_PARSE:
967 break;
968
969 default:
970 res = maildriver_imf_error_to_mail_error(r);
971 goto free_list;
972 }
973 }
974
975 if (item->ovr_date != NULL) {
976 struct mailimf_date_time * date_time;
977 struct mailimf_orig_date * orig_date;
978 struct mailimf_field * field;
979
980 cur_token = 0;
981 r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date),
982 &cur_token, &date_time);
983 switch (r) {
984 case MAILIMF_NO_ERROR:
985 orig_date = mailimf_orig_date_new(date_time);
986 if (orig_date == NULL) {
987 mailimf_date_time_free(date_time);
988 res = MAIL_ERROR_MEMORY;
989 goto free_list;
990 }
991
992 field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE,
993 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
994 NULL, orig_date, NULL,
995 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
996 NULL, NULL, NULL, NULL, NULL);
997 if (field == NULL) {
998 mailimf_orig_date_free(orig_date);
999 res = MAIL_ERROR_MEMORY;
1000 goto free_list;
1001 }
1002
1003 r = clist_append(list, field);
1004 if (r < 0) {
1005 mailimf_field_free(field);
1006 res = MAIL_ERROR_MEMORY;
1007 goto free_list;
1008 }
1009 break;
1010
1011 case MAILIMF_ERROR_PARSE:
1012 break;
1013
1014 default:
1015 res = maildriver_imf_error_to_mail_error(r);
1016 goto free_list;
1017 }
1018 }
1019
1020 if (item->ovr_message_id != NULL) {
1021 char * msgid_str;
1022 struct mailimf_message_id * msgid;
1023 struct mailimf_field * field;
1024
1025 cur_token = 0;
1026 r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id),
1027 &cur_token, &msgid_str);
1028
1029 switch (r) {
1030 case MAILIMF_NO_ERROR:
1031 msgid = mailimf_message_id_new(msgid_str);
1032 if (msgid == NULL) {
1033 mailimf_msg_id_free(msgid_str);
1034 res = MAIL_ERROR_MEMORY;
1035 goto free_list;
1036 }
1037
1038 field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID,
1039 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1040 NULL, NULL, NULL,
1041 NULL, NULL, NULL, NULL, NULL, msgid, NULL,
1042 NULL, NULL, NULL, NULL, NULL);
1043
1044 r = clist_append(list, field);
1045 if (r < 0) {
1046 mailimf_field_free(field);
1047 res = MAIL_ERROR_MEMORY;
1048 goto free_list;
1049 }
1050 break;
1051
1052 case MAILIMF_ERROR_PARSE:
1053 break;
1054
1055 default:
1056 res = maildriver_imf_error_to_mail_error(r);
1057 goto free_list;
1058 }
1059 }
1060
1061 if (item->ovr_references != NULL) {
1062 clist * msgid_list;
1063 struct mailimf_references * references;
1064 struct mailimf_field * field;
1065
1066 cur_token = 0;
1067
1068 r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references),
1069 &cur_token, &msgid_list);
1070
1071 switch (r) {
1072 case MAILIMF_NO_ERROR:
1073 references = mailimf_references_new(msgid_list);
1074 if (references == NULL) {
1075 clist_foreach(msgid_list,
1076 (clist_func) mailimf_msg_id_free, NULL);
1077 clist_free(msgid_list);
1078 res = MAIL_ERROR_MEMORY;
1079 goto free_list;
1080 }
1081
1082 field = mailimf_field_new(MAILIMF_FIELD_REFERENCES,
1083 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1084 NULL, NULL, NULL,
1085 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1086 references, NULL, NULL, NULL, NULL);
1087
1088 r = clist_append(list, field);
1089 if (r < 0) {
1090 mailimf_field_free(field);
1091 res = MAIL_ERROR_MEMORY;
1092 goto free_list;
1093 }
1094
1095 case MAILIMF_ERROR_PARSE:
1096 break;
1097
1098 default:
1099 res = maildriver_imf_error_to_mail_error(r);
1100 goto free_list;
1101 }
1102 }
1103
1104 fields = mailimf_fields_new(list);
1105 if (fields == NULL) {
1106 res = MAIL_ERROR_MEMORY;
1107 goto free_list;
1108 }
1109
1110 * result = fields;
1111
1112 return MAIL_NO_ERROR;
1113
1114 free_list:
1115 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
1116 clist_free(list);
1117 err:
1118 return res;
1119}
1120
1121
1122/* get messages list with group info */
1123
1124static int nntpdriver_get_messages_list(mailsession * session,
1125 struct mailmessage_list ** result)
1126{
1127 return nntp_get_messages_list(session, session, nntp_message_driver, result);
1128
1129}
1130
1131static int nntpdriver_get_message(mailsession * session,
1132 uint32_t num, mailmessage ** result)
1133{
1134 mailmessage * msg_info;
1135 int r;
1136
1137 msg_info = mailmessage_new();
1138 if (msg_info == NULL)
1139 return MAIL_ERROR_MEMORY;
1140
1141 r = mailmessage_init(msg_info, session, nntp_message_driver, num, 0);
1142 if (r != MAIL_NO_ERROR) {
1143 mailmessage_free(msg_info);
1144 return r;
1145 }
1146
1147 * result = msg_info;
1148
1149 return MAIL_NO_ERROR;
1150}
1151
1152static int nntpdriver_noop(mailsession * session)
1153{
1154 newsnntp * nntp;
1155 int r;
1156 struct tm tm;
1157
1158 nntp = get_nntp_session(session);
1159
1160 r = newsnntp_date(nntp, &tm);
1161
1162 return nntpdriver_nntp_error_to_mail_error(r);
1163}
1164
1165static int nntpdriver_get_message_by_uid(mailsession * session,
1166 const char * uid,
1167 mailmessage ** result)
1168{
1169 uint32_t num;
1170 char * p;
1171
1172 if (uid == NULL)
1173 return MAIL_ERROR_INVAL;
1174
1175 num = strtoul(uid, &p, 10);
1176 if ((p == uid) || (* p != '\0'))
1177 return MAIL_ERROR_INVAL;
1178
1179 return nntpdriver_get_message(session, num, result);
1180 }
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver.h b/libetpan/src/driver/implementation/nntp/nntpdriver.h
new file mode 100644
index 0000000..56aaa39
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver.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 NNTPDRIVER_H
37
38#define NNTPDRIVER_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * nntp_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
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}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h
new file mode 100644
index 0000000..c0264de
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_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 NNTPDRIVER_CACHED_H
37
38#define NNTPDRIVER_CACHED_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * nntp_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c
new file mode 100644
index 0000000..131b689
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c
@@ -0,0 +1,365 @@
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_message.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "mail_cache_db.h"
42
43#include "mailmessage.h"
44#include "mailmessage_tools.h"
45#include "nntpdriver.h"
46#include "nntpdriver_tools.h"
47#include "nntpdriver_cached.h"
48#include "nntpdriver_message.h"
49#include "generic_cache.h"
50
51static int nntp_prefetch(mailmessage * msg_info);
52
53static void nntp_prefetch_free(struct generic_message_t * msg);
54
55static int nntp_initialize(mailmessage * msg_info);
56
57static int nntp_fetch_header(mailmessage * msg_info,
58 char ** result,
59 size_t * result_len);
60
61static int nntp_fetch_size(mailmessage * msg_info,
62 size_t * result);
63
64static void nntp_uninitialize(mailmessage * msg_info);
65
66static void nntp_flush(mailmessage * msg_info);
67
68static void nntp_check(mailmessage * msg_info);
69
70static int nntp_get_flags(mailmessage * msg_info,
71 struct mail_flags ** result);
72
73static mailmessage_driver local_nntp_cached_message_driver = {
74 .msg_name = "nntp-cached",
75
76 .msg_initialize = nntp_initialize,
77 .msg_uninitialize = nntp_uninitialize,
78
79 .msg_flush = nntp_flush,
80 .msg_check = nntp_check,
81
82 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
83
84 .msg_fetch = mailmessage_generic_fetch,
85 .msg_fetch_header = nntp_fetch_header,
86 .msg_fetch_body = mailmessage_generic_fetch_body,
87 .msg_fetch_size = nntp_fetch_size,
88 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
89 .msg_fetch_section = mailmessage_generic_fetch_section,
90 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
91 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
92 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
93 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
94
95 .msg_get_flags = nntp_get_flags,
96};
97
98mailmessage_driver * nntp_cached_message_driver =
99&local_nntp_cached_message_driver;
100
101static inline struct nntp_cached_session_state_data *
102get_cached_session_data(mailmessage * msg)
103{
104 return msg->msg_session->sess_data;
105}
106
107static inline mailsession * get_ancestor_session(mailmessage * msg)
108{
109 return get_cached_session_data(msg)->nntp_ancestor;
110}
111
112static inline struct nntp_session_state_data *
113get_ancestor_session_data(mailmessage * msg)
114{
115 return get_ancestor_session(msg)->sess_data;
116}
117
118static inline newsnntp *
119get_nntp_session(mailmessage * msg)
120{
121 return get_ancestor_session_data(msg)->nntp_session;
122}
123
124static int nntp_prefetch(mailmessage * msg_info)
125{
126 char * msg_content;
127 size_t msg_length;
128 struct generic_message_t * msg;
129 int r;
130 struct nntp_cached_session_state_data * cached_data;
131 struct nntp_session_state_data * ancestor_data;
132 char filename[PATH_MAX];
133
134 /* we try the cached message */
135
136 cached_data = get_cached_session_data(msg_info);
137
138 ancestor_data = get_ancestor_session_data(msg_info);
139
140 snprintf(filename, PATH_MAX, "%s/%s/%i", cached_data->nntp_cache_directory,
141 ancestor_data->nntp_group_name, msg_info->msg_index);
142
143 r = generic_cache_read(filename, &msg_content, &msg_length);
144 if (r == MAIL_NO_ERROR) {
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
153 /* we get the message through the network */
154
155 r = nntpdriver_article(get_ancestor_session(msg_info),
156 msg_info->msg_index, &msg_content,
157 &msg_length);
158
159 if (r != MAIL_NO_ERROR)
160 return r;
161
162 /* we write the message cache */
163
164 generic_cache_store(filename, msg_content, msg_length);
165
166 msg = msg_info->msg_data;
167
168 msg->msg_message = msg_content;
169 msg->msg_length = msg_length;
170
171 return MAIL_NO_ERROR;
172}
173
174static void nntp_prefetch_free(struct generic_message_t * msg)
175{
176 if (msg->msg_message != NULL) {
177 mmap_string_unref(msg->msg_message);
178 msg->msg_message = NULL;
179 }
180}
181
182static int nntp_initialize(mailmessage * msg_info)
183{
184 struct generic_message_t * msg;
185 int r;
186 char * uid;
187 char static_uid[20];
188
189 snprintf(static_uid, 20, "%u", msg_info->msg_index);
190 uid = strdup(static_uid);
191 if (uid == NULL)
192 return MAIL_ERROR_MEMORY;
193
194 r = mailmessage_generic_initialize(msg_info);
195 if (r != MAIL_NO_ERROR) {
196 free(uid);
197 return r;
198 }
199
200 msg = msg_info->msg_data;
201 msg->msg_prefetch = nntp_prefetch;
202 msg->msg_prefetch_free = nntp_prefetch_free;
203 msg_info->msg_uid = uid;
204
205 return MAIL_NO_ERROR;
206}
207
208
209static void nntp_uninitialize(mailmessage * msg_info)
210{
211 mailmessage_generic_uninitialize(msg_info);
212}
213
214#define FLAGS_NAME "flags.db"
215
216static void nntp_flush(mailmessage * msg_info)
217{
218 mailmessage_generic_flush(msg_info);
219}
220
221
222static void nntp_check(mailmessage * msg_info)
223{
224 int r;
225
226 if (msg_info->msg_flags != NULL) {
227 r = mail_flags_store_set(get_cached_session_data(msg_info)->nntp_flags_store,
228 msg_info);
229 /* ignore errors */
230 }
231}
232
233static int nntp_fetch_header(mailmessage * msg_info,
234 char ** result,
235 size_t * result_len)
236{
237 struct generic_message_t * msg;
238 char * headers;
239 size_t headers_length;
240 struct nntp_cached_session_state_data * cached_data;
241 struct nntp_session_state_data * ancestor_data;
242 int r;
243 char filename[PATH_MAX];
244
245 msg = msg_info->msg_data;
246
247 if (msg->msg_message != NULL)
248 return mailmessage_generic_fetch_header(msg_info,
249 result, result_len);
250
251 /* we try the cached message */
252
253 cached_data = get_cached_session_data(msg_info);
254
255 ancestor_data = get_ancestor_session_data(msg_info);
256
257 snprintf(filename, PATH_MAX, "%s/%s/%i-header",
258 cached_data->nntp_cache_directory,
259 ancestor_data->nntp_group_name, msg_info->msg_index);
260
261 r = generic_cache_read(filename, &headers, &headers_length);
262 if (r == MAIL_NO_ERROR) {
263 * result = headers;
264 * result_len = headers_length;
265
266 return MAIL_NO_ERROR;
267 }
268
269 /* we get the message through the network */
270
271 r = nntpdriver_head(get_ancestor_session(msg_info), msg_info->msg_index,
272 &headers, &headers_length);
273 if (r != MAIL_NO_ERROR)
274 return r;
275
276 /* we write the message cache */
277
278 generic_cache_store(filename, headers, headers_length);
279
280 * result = headers;
281 * result_len = headers_length;
282
283 return MAIL_NO_ERROR;
284}
285
286static int nntp_fetch_size(mailmessage * msg_info,
287 size_t * result)
288{
289 return nntpdriver_size(get_ancestor_session(msg_info),
290 msg_info->msg_index, result);
291}
292
293static int nntp_get_flags(mailmessage * msg_info,
294 struct mail_flags ** result)
295{
296 int r;
297 struct mail_flags * flags;
298 struct mail_cache_db * cache_db_flags;
299 char filename_flags[PATH_MAX];
300 int res;
301 MMAPString * mmapstr;
302
303 if (msg_info->msg_flags != NULL) {
304 * result = msg_info->msg_flags;
305
306 return MAIL_NO_ERROR;
307 }
308
309 flags = mail_flags_store_get(get_cached_session_data(msg_info)->nntp_flags_store, msg_info->msg_index);
310
311 if (flags == NULL) {
312 struct nntp_cached_session_state_data * cached_data;
313 struct nntp_session_state_data * ancestor_data;
314
315 cached_data = get_cached_session_data(msg_info);
316
317 ancestor_data = get_ancestor_session_data(msg_info);
318 if (ancestor_data->nntp_group_name == NULL) {
319 res = MAIL_ERROR_BAD_STATE;
320 goto err;
321 }
322
323 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
324 cached_data->nntp_flags_directory,
325 ancestor_data->nntp_group_name, FLAGS_NAME);
326
327 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
328 if (r < 0) {
329 res = MAIL_ERROR_MEMORY;
330 goto err;
331 }
332
333 mmapstr = mmap_string_new("");
334 if (mmapstr == NULL) {
335 res = MAIL_ERROR_MEMORY;
336 goto close_db_flags;
337 }
338
339 r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
340 msg_info->msg_index, &flags);
341 if (r != MAIL_NO_ERROR) {
342 flags = mail_flags_new_empty();
343 if (flags == NULL) {
344 res = MAIL_ERROR_MEMORY;
345 goto free_mmapstr;
346 }
347 }
348
349 mmap_string_free(mmapstr);
350 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
351 }
352
353 msg_info->msg_flags = flags;
354
355 * result = flags;
356
357 return MAIL_NO_ERROR;
358
359 free_mmapstr:
360 mmap_string_free(mmapstr);
361 close_db_flags:
362 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
363 err:
364 return res;
365}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h
new file mode 100644
index 0000000..f515d48
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_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#include <libetpan/mailmessage_types.h>
37
38#ifndef NNTPDRIVER_CACHED_MESSAGE_H
39
40#define NNTPDRIVER_CACHED_MESSAGE_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * nntp_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_message.c b/libetpan/src/driver/implementation/nntp/nntpdriver_message.c
new file mode 100644
index 0000000..117bc56
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_message.c
@@ -0,0 +1,169 @@
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_message.h"
37
38#include "mailmessage_tools.h"
39#include "nntpdriver_tools.h"
40#include "nntpdriver.h"
41#include "newsnntp.h"
42#include <string.h>
43#include <stdlib.h>
44
45static int nntp_prefetch(mailmessage * msg_info);
46
47static void nntp_prefetch_free(struct generic_message_t * msg);
48
49static int nntp_initialize(mailmessage * msg_info);
50
51static int nntp_fetch_header(mailmessage * msg_info,
52 char ** result,
53 size_t * result_len);
54
55static int nntp_fetch_size(mailmessage * msg_info,
56 size_t * result);
57
58static mailmessage_driver local_nntp_message_driver = {
59 .msg_name = "nntp",
60
61 .msg_initialize = nntp_initialize,
62 .msg_uninitialize = mailmessage_generic_uninitialize,
63
64 .msg_flush = mailmessage_generic_flush,
65 .msg_check = NULL,
66
67 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
68
69 .msg_fetch = mailmessage_generic_fetch,
70 .msg_fetch_header = nntp_fetch_header,
71 .msg_fetch_body = mailmessage_generic_fetch_body,
72 .msg_fetch_size = nntp_fetch_size,
73 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
74 .msg_fetch_section = mailmessage_generic_fetch_section,
75 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
76 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
77 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
78 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
79
80 .msg_get_flags = NULL,
81};
82
83mailmessage_driver * nntp_message_driver = &local_nntp_message_driver;
84
85static int nntp_prefetch(mailmessage * msg_info)
86{
87 char * msg_content;
88 size_t msg_length;
89 struct generic_message_t * msg;
90 int r;
91
92 r = nntpdriver_article(msg_info->msg_session, msg_info->msg_index,
93 &msg_content, &msg_length);
94 if (r != MAIL_NO_ERROR)
95 return r;
96
97 msg = msg_info->msg_data;
98
99 msg->msg_message = msg_content;
100 msg->msg_length = msg_length;
101
102 return MAIL_NO_ERROR;
103}
104
105static void nntp_prefetch_free(struct generic_message_t * msg)
106{
107 if (msg->msg_message != NULL) {
108 mmap_string_unref(msg->msg_message);
109 msg->msg_message = NULL;
110 }
111}
112
113static int nntp_initialize(mailmessage * msg_info)
114{
115 struct generic_message_t * msg;
116 int r;
117 char * uid;
118 char static_uid[20];
119
120 snprintf(static_uid, 20, "%u", msg_info->msg_index);
121 uid = strdup(static_uid);
122 if (uid == NULL)
123 return MAIL_ERROR_MEMORY;
124
125 r = mailmessage_generic_initialize(msg_info);
126 if (r != MAIL_NO_ERROR) {
127 free(uid);
128 return r;
129 }
130
131 msg = msg_info->msg_data;
132 msg->msg_prefetch = nntp_prefetch;
133 msg->msg_prefetch_free = nntp_prefetch_free;
134 msg_info->msg_uid = uid;
135
136 return MAIL_NO_ERROR;
137}
138
139static int nntp_fetch_header(mailmessage * msg_info,
140 char ** result,
141 size_t * result_len)
142{
143 struct generic_message_t * msg;
144 char * headers;
145 size_t headers_length;
146 int r;
147
148 msg = msg_info->msg_data;
149
150 if (msg->msg_message != NULL)
151 return mailmessage_generic_fetch_header(msg_info,
152 result, result_len);
153
154 r = nntpdriver_head(msg_info->msg_session, msg_info->msg_index,
155 &headers, &headers_length);
156 if (r != MAIL_NO_ERROR)
157 return r;
158
159 * result = headers;
160 * result_len = headers_length;
161
162 return MAIL_NO_ERROR;
163}
164
165static int nntp_fetch_size(mailmessage * msg_info,
166 size_t * result)
167{
168 return nntpdriver_size(msg_info->msg_session, msg_info->msg_index, result);
169}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_message.h b/libetpan/src/driver/implementation/nntp/nntpdriver_message.h
new file mode 100644
index 0000000..15e80b7
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_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 NNTPDRIVER_MESSAGE_H
37
38#define NNTPDRIVER_MESSAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/nntpdriver_types.h>
45
46extern mailmessage_driver * nntp_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c
new file mode 100644
index 0000000..eef0953
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c
@@ -0,0 +1,563 @@
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_tools.h"
37
38#include "mail.h"
39#include "nntpdriver.h"
40#include "nntpdriver_cached.h"
41#include "newsnntp.h"
42#include "maildriver_types.h"
43#include "generic_cache.h"
44#include "imfcache.h"
45#include "mailmessage.h"
46#include "mail_cache_db.h"
47
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <unistd.h>
52#include <string.h>
53#include <stdlib.h>
54
55int nntpdriver_nntp_error_to_mail_error(int error)
56{
57 switch (error) {
58 case NEWSNNTP_NO_ERROR:
59 return MAIL_NO_ERROR;
60
61 case NEWSNNTP_ERROR_STREAM:
62 return MAIL_ERROR_STREAM;
63
64 case NEWSNNTP_ERROR_UNEXPECTED:
65 return MAIL_ERROR_PROGRAM_ERROR;
66
67 case NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED:
68 return MAIL_ERROR_FOLDER_NOT_FOUND;
69
70 case NEWSNNTP_ERROR_NO_ARTICLE_SELECTED:
71 case NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER:
72 case NEWSNNTP_ERROR_ARTICLE_NOT_FOUND:
73 return MAIL_ERROR_MSG_NOT_FOUND;
74
75 case NEWSNNTP_ERROR_UNEXPECTED_RESPONSE:
76 case NEWSNNTP_ERROR_INVALID_RESPONSE:
77 return MAIL_ERROR_PARSE;
78
79 case NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP:
80 return MAIL_ERROR_FOLDER_NOT_FOUND;
81
82 case NEWSNNTP_ERROR_POSTING_NOT_ALLOWED:
83 return MAIL_ERROR_READONLY;
84
85 case NEWSNNTP_ERROR_POSTING_FAILED:
86 return MAIL_ERROR_APPEND;
87
88 case NEWSNNTP_ERROR_PROGRAM_ERROR:
89 return MAIL_ERROR_PROGRAM_ERROR;
90
91 case NEWSNNTP_ERROR_NO_PERMISSION:
92 return MAIL_ERROR_NO_PERMISSION;
93
94 case NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD:
95 case NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED:
96 return MAIL_ERROR_COMMAND_NOT_SUPPORTED;
97
98 case NEWSNNTP_ERROR_CONNECTION_REFUSED:
99 return MAIL_ERROR_CONNECT;
100
101 case NEWSNNTP_ERROR_MEMORY:
102 return MAIL_ERROR_MEMORY;
103
104 case NEWSNNTP_ERROR_AUTHENTICATION_REJECTED:
105 return MAIL_ERROR_LOGIN;
106
107 case NEWSNNTP_ERROR_BAD_STATE:
108 return MAIL_ERROR_BAD_STATE;
109
110 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
111 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
112 default:
113 return MAIL_ERROR_INVAL;
114 }
115}
116
117static inline struct nntp_session_state_data *
118session_get_data(mailsession * session)
119{
120 return session->sess_data;
121}
122
123static inline newsnntp * session_get_nntp_session(mailsession * session)
124{
125 return session_get_data(session)->nntp_session;
126}
127
128static inline struct nntp_cached_session_state_data *
129cached_session_get_data(mailsession * session)
130{
131 return session->sess_data;
132}
133
134static inline mailsession * cached_session_get_ancestor(mailsession * session)
135{
136 return cached_session_get_data(session)->nntp_ancestor;
137}
138
139static inline struct nntp_session_state_data *
140cached_session_get_ancestor_data(mailsession * session)
141{
142 return session_get_data(cached_session_get_ancestor(session));
143}
144
145static inline newsnntp * cached_session_get_nntp_session(mailsession * session)
146{
147 return session_get_nntp_session(cached_session_get_ancestor(session));
148}
149
150
151int nntpdriver_authenticate_password(mailsession * session)
152{
153 struct nntp_session_state_data * data;
154 int r;
155
156 data = session_get_data(session);
157
158 if (data->nntp_password == NULL)
159 return MAIL_ERROR_LOGIN;
160
161 r = newsnntp_authinfo_password(session_get_nntp_session(session),
162 data->nntp_password);
163
164 return nntpdriver_nntp_error_to_mail_error(r);
165}
166
167int nntpdriver_mode_reader(mailsession * session)
168{
169 int done;
170 int r;
171
172 done = FALSE;
173
174 do {
175 r = newsnntp_mode_reader(session_get_nntp_session(session));
176
177 switch (r) {
178 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
179 r = nntpdriver_authenticate_user(session);
180 if (r != MAIL_NO_ERROR)
181 return r;
182 break;
183
184 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
185 r = nntpdriver_authenticate_password(session);
186 if (r != MAIL_NO_ERROR)
187 return r;
188 break;
189
190 case NEWSNNTP_NO_ERROR:
191 done = TRUE;
192 break;
193
194 default:
195 done = TRUE;
196 break;
197 }
198 }
199 while (!done);
200
201 return MAIL_NO_ERROR;
202}
203
204int nntpdriver_authenticate_user(mailsession * session)
205{
206 struct nntp_session_state_data * data;
207 int r;
208
209 data = session_get_data(session);
210
211 if (data->nntp_userid == NULL)
212 return MAIL_ERROR_LOGIN;
213
214 r = newsnntp_authinfo_username(session_get_nntp_session(session),
215 data->nntp_userid);
216
217 switch (r) {
218 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
219 return nntpdriver_authenticate_password(session);
220
221 default:
222 return nntpdriver_nntp_error_to_mail_error(r);
223 }
224}
225
226int nntpdriver_article(mailsession * session, uint32_t index,
227 char ** result,
228 size_t * result_len)
229{
230 char * msg_content;
231 size_t msg_length;
232 int r;
233 int done;
234
235 done = FALSE;
236 do {
237 r = newsnntp_article(session_get_nntp_session(session),
238 index, &msg_content, &msg_length);
239
240 switch (r) {
241 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
242 r = nntpdriver_authenticate_user(session);
243 if (r != MAIL_NO_ERROR)
244 return r;
245 break;
246
247 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
248 r = nntpdriver_authenticate_password(session);
249 if (r != MAIL_NO_ERROR)
250 return r;
251 break;
252
253 case NEWSNNTP_NO_ERROR:
254 done = TRUE;
255 break;
256
257 default:
258 return nntpdriver_nntp_error_to_mail_error(r);
259 }
260 }
261 while (!done);
262
263 * result = msg_content;
264 * result_len = msg_length;
265
266 return MAIL_NO_ERROR;
267}
268
269int nntpdriver_head(mailsession * session, uint32_t index,
270 char ** result,
271 size_t * result_len)
272{
273 char * headers;
274 size_t headers_length;
275 int r;
276 int done;
277
278 done = FALSE;
279 do {
280 r = newsnntp_head(session_get_nntp_session(session),
281 index, &headers, &headers_length);
282
283 switch (r) {
284 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
285 r = nntpdriver_authenticate_user(session);
286 if (r != MAIL_NO_ERROR)
287 return r;
288 break;
289
290 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
291 r = nntpdriver_authenticate_password(session);
292 if (r != MAIL_NO_ERROR)
293 return r;
294 break;
295
296 case NEWSNNTP_NO_ERROR:
297 done = TRUE;
298 break;
299
300 default:
301 return nntpdriver_nntp_error_to_mail_error(r);
302 }
303 }
304 while (!done);
305
306 * result = headers;
307 * result_len = headers_length;
308
309 return MAIL_NO_ERROR;
310}
311
312int nntpdriver_size(mailsession * session, uint32_t index,
313 size_t * result)
314{
315 newsnntp * nntp;
316 struct newsnntp_xover_resp_item * item;
317 int r;
318 int done;
319
320 nntp = session_get_nntp_session(session);
321
322 done = FALSE;
323 do {
324 r = newsnntp_xover_single(nntp, index, &item);
325 switch (r) {
326 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
327 r = nntpdriver_authenticate_user(session);
328 if (r != MAIL_NO_ERROR)
329 return r;
330 break;
331
332 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
333 r = nntpdriver_authenticate_password(session);
334 if (r != MAIL_NO_ERROR)
335 return r;
336 break;
337
338 case NEWSNNTP_NO_ERROR:
339 done = TRUE;
340 break;
341
342 default:
343 return nntpdriver_nntp_error_to_mail_error(r);
344 }
345 }
346 while (!done);
347
348 * result = item->ovr_size;
349
350 xover_resp_item_free(item);
351
352 return MAIL_NO_ERROR;
353}
354
355int
356nntpdriver_get_cached_flags(struct mail_cache_db * cache_db,
357 MMAPString * mmapstr,
358 uint32_t num,
359 struct mail_flags ** result)
360{
361 int r;
362 char keyname[PATH_MAX];
363 struct mail_flags * flags;
364 int res;
365
366 snprintf(keyname, PATH_MAX, "%u-flags", num);
367
368 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
369 if (r != MAIL_NO_ERROR) {
370 res = r;
371 goto err;
372 }
373
374 * result = flags;
375
376 return MAIL_NO_ERROR;
377
378 err:
379 return res;
380}
381
382int
383nntpdriver_write_cached_flags(struct mail_cache_db * cache_db,
384 MMAPString * mmapstr,
385 uint32_t num,
386 struct mail_flags * flags)
387{
388 int r;
389 char keyname[PATH_MAX];
390 int res;
391
392 snprintf(keyname, PATH_MAX, "%u-flags", num);
393
394 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
395 if (r != MAIL_NO_ERROR) {
396 res = r;
397 goto err;
398 }
399
400 return MAIL_NO_ERROR;
401
402 err:
403 return res;
404}
405
406
407
408int nntpdriver_select_folder(mailsession * session, char * mb)
409{
410 int r;
411 struct newsnntp_group_info * info;
412 newsnntp * nntp_session;
413 struct nntp_session_state_data * data;
414 char * new_name;
415 int done;
416
417 data = session_get_data(session);
418
419 if (!data->nntp_mode_reader) {
420 r = nntpdriver_mode_reader(session);
421 if (r != MAIL_NO_ERROR)
422 return r;
423
424 data->nntp_mode_reader = TRUE;
425 }
426
427 if (data->nntp_group_name != NULL)
428 if (strcmp(data->nntp_group_name, mb) == 0)
429 return MAIL_NO_ERROR;
430
431 nntp_session = session_get_nntp_session(session);
432
433 done = FALSE;
434 do {
435 r = newsnntp_group(nntp_session, mb, &info);
436
437 switch (r) {
438 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
439 r = nntpdriver_authenticate_user(session);
440 if (r != MAIL_NO_ERROR)
441 return r;
442 break;
443
444 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
445 r = nntpdriver_authenticate_password(session);
446 if (r != MAIL_NO_ERROR)
447 return r;
448 break;
449
450 case NEWSNNTP_NO_ERROR:
451 done = TRUE;
452 break;
453
454 default:
455 return nntpdriver_nntp_error_to_mail_error(r);
456 }
457
458 }
459 while (!done);
460
461 new_name = strdup(mb);
462 if (new_name == NULL)
463 return MAIL_ERROR_MEMORY;
464
465 if (data->nntp_group_name != NULL)
466 free(data->nntp_group_name);
467 data->nntp_group_name = new_name;
468 if (data->nntp_group_info != NULL)
469 newsnntp_group_free(data->nntp_group_info);
470 data->nntp_group_info = info;
471
472 return MAIL_NO_ERROR;
473}
474
475
476int nntp_get_messages_list(mailsession * nntp_session,
477 mailsession * session,
478 mailmessage_driver * driver,
479 struct mailmessage_list ** result)
480{
481 carray * tab;
482 struct mailmessage_list * env_list;
483 uint32_t i;
484 int res;
485 int r;
486 struct nntp_session_state_data * data;
487 struct newsnntp_group_info * group_info;
488 uint32_t max;
489 unsigned int cur;
490
491 data = session_get_data(nntp_session);
492
493 if (data->nntp_group_name == NULL) {
494 res = MAIL_ERROR_BAD_STATE;
495 goto err;
496 }
497
498 r = nntpdriver_select_folder(nntp_session, data->nntp_group_name);
499 if (r != MAIL_NO_ERROR) {
500 res = r;
501 goto err;
502 }
503
504 group_info = data->nntp_group_info;
505
506 if (group_info == NULL) {
507 res = MAIL_ERROR_BAD_STATE;
508 goto err;
509 }
510
511 max = group_info->grp_first;
512 if (data->nntp_max_articles != 0) {
513 if (group_info->grp_last - data->nntp_max_articles + 1 > max)
514 max = group_info->grp_last - data->nntp_max_articles + 1;
515 }
516
517 tab = carray_new(128);
518 if (tab == NULL) {
519 res = MAIL_ERROR_MEMORY;
520 goto err;
521 }
522
523 for(i = max ; i <= group_info->grp_last ; i++) {
524 mailmessage * msg;
525
526 msg = mailmessage_new();
527 if (msg == NULL) {
528 res = MAIL_ERROR_MEMORY;
529 goto free_list;
530 }
531
532 r = mailmessage_init(msg, session, driver, i, 0);
533 if (r != MAIL_NO_ERROR) {
534 mailmessage_free(msg);
535 res = r;
536 goto free_list;
537 }
538
539 r = carray_add(tab, msg, NULL);
540 if (r < 0) {
541 mailmessage_free(msg);
542 res = MAIL_ERROR_MEMORY;
543 goto free_list;
544 }
545 }
546
547 env_list = mailmessage_list_new(tab);
548 if (env_list == NULL) {
549 res = MAIL_ERROR_MEMORY;
550 goto free_list;
551 }
552
553 * result = env_list;
554
555 return MAIL_NO_ERROR;
556
557 free_list:
558 for(cur = 0 ; cur < carray_count(tab) ; cur ++)
559 mailmessage_free(carray_get(tab, cur));
560 carray_free(tab);
561 err:
562 return res;
563}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h
new file mode 100644
index 0000000..8ca9d16
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h
@@ -0,0 +1,88 @@
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 NNTPDRIVER_TOOLS_H
37
38#define NNTPDRIVER_TOOLS_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mail_cache_db_types.h"
45#include "nntpdriver_types.h"
46
47int nntpdriver_nntp_error_to_mail_error(int error);
48
49int nntpdriver_authenticate_password(mailsession * session);
50
51int nntpdriver_authenticate_user(mailsession * session);
52
53int nntpdriver_article(mailsession * session, uint32_t index,
54 char ** result, size_t * result_len);
55
56int nntpdriver_head(mailsession * session, uint32_t index,
57 char ** result,
58 size_t * result_len);
59
60int nntpdriver_size(mailsession * session, uint32_t index,
61 size_t * result);
62
63int
64nntpdriver_get_cached_flags(struct mail_cache_db * cache_db,
65 MMAPString * mmapstr,
66 uint32_t num,
67 struct mail_flags ** result);
68
69int
70nntpdriver_write_cached_flags(struct mail_cache_db * cache_db,
71 MMAPString * mmapstr,
72 uint32_t num,
73 struct mail_flags * flags);
74
75int nntpdriver_select_folder(mailsession * session, char * mb);
76
77int nntp_get_messages_list(mailsession * nntp_session,
78 mailsession * session,
79 mailmessage_driver * driver,
80 struct mailmessage_list ** result);
81
82int nntpdriver_mode_reader(mailsession * session);
83
84#ifdef __cplusplus
85}
86#endif
87
88#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_types.h b/libetpan/src/driver/implementation/nntp/nntpdriver_types.h
new file mode 100644
index 0000000..7d4b74d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_types.h
@@ -0,0 +1,146 @@
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 NNTPDRIVER_TYPES_H
37
38#define NNTPDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/newsnntp.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
52/* NNTP driver for session */
53
54enum {
55 NNTPDRIVER_SET_MAX_ARTICLES = 1,
56};
57
58struct nntp_session_state_data {
59 newsnntp * nntp_session;
60 char * nntp_userid;
61 char * nntp_password;
62
63 struct newsnntp_group_info * nntp_group_info;
64 char * nntp_group_name;
65
66 clist * nntp_subscribed_list;
67
68 uint32_t nntp_max_articles;
69
70 int nntp_mode_reader;
71};
72
73/* cached NNTP driver for session */
74
75enum {
76 /* the mapping of the parameters should be the same as for nntp */
77 NNTPDRIVER_CACHED_SET_MAX_ARTICLES = 1,
78 /* cache specific */
79 NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY,
80 NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY,
81};
82
83struct nntp_cached_session_state_data {
84 mailsession * nntp_ancestor;
85 char nntp_cache_directory[PATH_MAX];
86 char nntp_flags_directory[PATH_MAX];
87 struct mail_flags_store * nntp_flags_store;
88};
89
90
91/* nntp storage */
92
93/*
94 nntp_mailstorage is the state data specific to the IMAP4rev1 storage.
95
96 - storage this is the storage to initialize.
97
98 - servername this is the name of the NNTP server
99
100 - port is the port to connect to, on the server.
101 you give 0 to use the default port.
102
103 - connection_type is the type of socket layer to use.
104 The value can be CONNECTION_TYPE_PLAIN or CONNECTION_TYPE_TLS.
105
106 - auth_type is the authenticate mechanism to use.
107 The value can be NNTP_AUTH_TYPE_PLAIN.
108
109 - login is the login of the POP3 account.
110
111 - password is the password of the POP3 account.
112
113 - cached if this value is != 0, a persistant cache will be
114 stored on local system.
115
116 - cache_directory is the location of the cache
117
118 - flags_directory is the location of the flags
119*/
120
121struct nntp_mailstorage {
122 char * nntp_servername;
123 uint16_t nntp_port;
124 char * nntp_command;
125 int nntp_connection_type;
126
127 int nntp_auth_type;
128 char * nntp_login;
129 char * nntp_password;
130
131 int nntp_cached;
132 char * nntp_cache_directory;
133 char * nntp_flags_directory;
134};
135
136/* this is the type of NNTP authentication */
137
138enum {
139 NNTP_AUTH_TYPE_PLAIN, /* plain text authentication */
140};
141
142#ifdef __cplusplus
143}
144#endif
145
146#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpstorage.c b/libetpan/src/driver/implementation/nntp/nntpstorage.c
new file mode 100644
index 0000000..8d0e4ff
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpstorage.c
@@ -0,0 +1,267 @@
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 "nntpstorage.h"
37
38#include <stdlib.h>
39#include <string.h>
40
41#include "maildriver.h"
42#include "nntpdriver.h"
43#include "nntpdriver_cached.h"
44#include "mailstorage_tools.h"
45#include "mail.h"
46
47/* nntp storage */
48
49#define NNTP_DEFAULT_PORT 119
50#define NNTPS_DEFAULT_PORT 563
51
52static int nntp_mailstorage_connect(struct mailstorage * storage);
53static int nntp_mailstorage_get_folder_session(struct mailstorage * storage,
54 char * pathname, mailsession ** result);
55static void nntp_mailstorage_uninitialize(struct mailstorage * storage);
56
57static mailstorage_driver nntp_mailstorage_driver = {
58 .sto_name = "nntp",
59 .sto_connect = nntp_mailstorage_connect,
60 .sto_get_folder_session = nntp_mailstorage_get_folder_session,
61 .sto_uninitialize = nntp_mailstorage_uninitialize,
62};
63
64int nntp_mailstorage_init(struct mailstorage * storage,
65 char * nn_servername, uint16_t nn_port,
66 char * nn_command,
67 int nn_connection_type, int nn_auth_type,
68 char * nn_login, char * nn_password,
69 int nn_cached, char * nn_cache_directory, char * nn_flags_directory)
70{
71 struct nntp_mailstorage * nntp_storage;
72 int res;
73
74 nntp_storage = malloc(sizeof(* nntp_storage));
75 if (nntp_storage == NULL) {
76 res = MAIL_ERROR_MEMORY;
77 goto err;
78 }
79
80 nntp_storage->nntp_servername = strdup(nn_servername);
81 if (nntp_storage->nntp_servername == NULL) {
82 res = MAIL_ERROR_MEMORY;
83 goto free;
84 }
85
86 nntp_storage->nntp_connection_type = nn_connection_type;
87
88 if (nn_port == 0) {
89 switch (nn_connection_type) {
90 case CONNECTION_TYPE_PLAIN:
91 case CONNECTION_TYPE_COMMAND:
92 nn_port = NNTP_DEFAULT_PORT;
93 break;
94
95 case CONNECTION_TYPE_TLS:
96 case CONNECTION_TYPE_COMMAND_TLS:
97 nn_port = NNTPS_DEFAULT_PORT;
98 break;
99
100 default:
101 res = MAIL_ERROR_INVAL;
102 goto free_servername;
103 }
104 }
105
106 nntp_storage->nntp_port = nn_port;
107
108 if (nn_command != NULL) {
109 nntp_storage->nntp_command = strdup(nn_command);
110 if (nntp_storage->nntp_command == NULL) {
111 res = MAIL_ERROR_MEMORY;
112 goto free_servername;
113 }
114 }
115 else
116 nntp_storage->nntp_command = NULL;
117
118 nntp_storage->nntp_auth_type = nn_auth_type;
119
120 if (nn_login != NULL) {
121 nntp_storage->nntp_login = strdup(nn_login);
122 if (nntp_storage->nntp_login == NULL) {
123 res = MAIL_ERROR_MEMORY;
124 goto free_command;
125 }
126 }
127 else
128 nntp_storage->nntp_login = NULL;
129
130 if (nn_password != NULL) {
131 nntp_storage->nntp_password = strdup(nn_password);
132 if (nntp_storage->nntp_password == NULL) {
133 res = MAIL_ERROR_MEMORY;
134 goto free_login;
135 }
136 }
137 else
138 nntp_storage->nntp_password = NULL;
139
140 nntp_storage->nntp_cached = nn_cached;
141
142 if (nn_cached && (nn_cache_directory != NULL) &&
143 (nn_flags_directory != NULL)) {
144 nntp_storage->nntp_cache_directory = strdup(nn_cache_directory);
145 if (nntp_storage->nntp_cache_directory == NULL) {
146 res = MAIL_ERROR_MEMORY;
147 goto free_password;
148 }
149 nntp_storage->nntp_flags_directory = strdup(nn_flags_directory);
150 if (nntp_storage->nntp_flags_directory == NULL) {
151 res = MAIL_ERROR_MEMORY;
152 goto free_cache_directory;
153 }
154 }
155 else {
156 nntp_storage->nntp_cached = FALSE;
157 nntp_storage->nntp_cache_directory = NULL;
158 nntp_storage->nntp_flags_directory = NULL;
159 }
160
161 storage->sto_data = nntp_storage;
162 storage->sto_driver = &nntp_mailstorage_driver;
163
164 return MAIL_NO_ERROR;
165
166 free_cache_directory:
167 free(nntp_storage->nntp_cache_directory);
168 free_password:
169 free(nntp_storage->nntp_password);
170 free_login:
171 free(nntp_storage->nntp_login);
172 free_command:
173 free(nn_command);
174 free_servername:
175 free(nntp_storage->nntp_servername);
176 free:
177 free(nntp_storage);
178 err:
179 return res;
180}
181
182static void nntp_mailstorage_uninitialize(struct mailstorage * storage)
183{
184 struct nntp_mailstorage * nntp_storage;
185
186 nntp_storage = storage->sto_data;
187
188 if (nntp_storage->nntp_flags_directory != NULL)
189 free(nntp_storage->nntp_flags_directory);
190 if (nntp_storage->nntp_cache_directory != NULL)
191 free(nntp_storage->nntp_cache_directory);
192 if (nntp_storage->nntp_password != NULL)
193 free(nntp_storage->nntp_password);
194 if (nntp_storage->nntp_login != NULL)
195 free(nntp_storage->nntp_login);
196 if (nntp_storage->nntp_command != NULL)
197 free(nntp_storage->nntp_command);
198 free(nntp_storage->nntp_servername);
199 free(nntp_storage);
200
201 storage->sto_data = NULL;
202}
203
204static int nntp_mailstorage_connect(struct mailstorage * storage)
205{
206 struct nntp_mailstorage * nntp_storage;
207 mailsession_driver * driver;
208 int r;
209 int res;
210 mailsession * session;
211
212 nntp_storage = storage->sto_data;
213
214 if (nntp_storage->nntp_cached)
215 driver = nntp_cached_session_driver;
216 else
217 driver = nntp_session_driver;
218
219 r = mailstorage_generic_connect(driver,
220 nntp_storage->nntp_servername,
221 nntp_storage->nntp_port, nntp_storage->nntp_command,
222 nntp_storage->nntp_connection_type,
223 NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY,
224 nntp_storage->nntp_cache_directory,
225 NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY,
226 nntp_storage->nntp_flags_directory,
227 &session);
228 switch (r) {
229 case MAIL_NO_ERROR_NON_AUTHENTICATED:
230 case MAIL_NO_ERROR_AUTHENTICATED:
231 case MAIL_NO_ERROR:
232 break;
233 default:
234 res = r;
235 goto err;
236 }
237
238 r = mailstorage_generic_auth(session, r,
239 nntp_storage->nntp_connection_type,
240 nntp_storage->nntp_login,
241 nntp_storage->nntp_password);
242 if (r != MAIL_NO_ERROR) {
243 res = r;
244 goto free;
245 }
246
247 storage->sto_session = session;
248
249 return MAIL_NO_ERROR;
250
251 free:
252 mailsession_free(session);
253 err:
254 return res;
255}
256
257static int nntp_mailstorage_get_folder_session(struct mailstorage * storage,
258 char * pathname, mailsession ** result)
259{
260 int r;
261
262 r = mailsession_select_folder(storage->sto_session, pathname);
263
264 * result = storage->sto_session;
265
266 return MAIL_NO_ERROR;
267}
diff --git a/libetpan/src/driver/implementation/nntp/nntpstorage.h b/libetpan/src/driver/implementation/nntp/nntpstorage.h
new file mode 100644
index 0000000..7b046f4
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpstorage.h
@@ -0,0 +1,93 @@
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 NNTPSTORAGE_H
37
38#define NNTPSTORAGE_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46
47/*
48 nntp_mailstorage_init is the constructor for a NNTP storage
49
50 @param storage this is the storage to initialize.
51
52 @param servername this is the name of the NNTP server
53
54 @param port is the port to connect to, on the server.
55 you give 0 to use the default port.
56
57 @param command the command used to connect to the server instead of
58 allowing normal TCP connections to be used.
59
60 @param connection_type is the type of socket layer to use.
61 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
62 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
63 CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
64 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
65
66 @param auth_type is the authenticate mechanism to use.
67 The value can be NNTP_AUTH_TYPE_PLAIN.
68
69 @param login is the login of the POP3 account.
70
71 @param password is the password of the POP3 account.
72
73 @param cached if this value is != 0, a persistant cache will be
74 stored on local system.
75
76 @param cache_directory is the location of the cache
77
78 @param flags_directory is the location of the flags
79*/
80
81int nntp_mailstorage_init(struct mailstorage * storage,
82 char * nntp_servername, uint16_t nntp_port,
83 char * nntp_command,
84 int nntp_connection_type, int nntp_auth_type,
85 char * nntp_login, char * nntp_password,
86 int nntp_cached, char * nntp_cache_directory,
87 char * nntp_flags_directory);
88
89#ifdef __cplusplus
90}
91#endif
92
93#endif