Diffstat (limited to 'kmicromail/libetpan/generic/nntpdriver.c') (more/less context) (show whitespace changes)
-rw-r--r-- | kmicromail/libetpan/generic/nntpdriver.c | 1170 |
1 files changed, 1170 insertions, 0 deletions
diff --git a/kmicromail/libetpan/generic/nntpdriver.c b/kmicromail/libetpan/generic/nntpdriver.c new file mode 100644 index 0000000..fde5f1a --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver.c | |||
@@ -0,0 +1,1170 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #include "nntpdriver.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 | |||
47 | static int nntpdriver_initialize(mailsession * session); | ||
48 | |||
49 | static void nntpdriver_uninitialize(mailsession * session); | ||
50 | |||
51 | static int nntpdriver_parameters(mailsession * session, | ||
52 | int id, void * value); | ||
53 | |||
54 | static int nntpdriver_connect_stream(mailsession * session, mailstream * s); | ||
55 | |||
56 | static int nntpdriver_login(mailsession * session, | ||
57 | char * userid, char * password); | ||
58 | |||
59 | static int nntpdriver_logout(mailsession * session); | ||
60 | |||
61 | static int nntpdriver_status_folder(mailsession * session, char * mb, | ||
62 | uint32_t * result_messages, | ||
63 | uint32_t * result_recent, | ||
64 | uint32_t * result_unseen); | ||
65 | |||
66 | static int nntpdriver_messages_number(mailsession * session, char * mb, | ||
67 | uint32_t * result); | ||
68 | |||
69 | static int nntpdriver_append_message(mailsession * session, | ||
70 | char * message, size_t size); | ||
71 | |||
72 | static int | ||
73 | nntpdriver_get_envelopes_list(mailsession * session, | ||
74 | struct mailmessage_list * env_list); | ||
75 | |||
76 | |||
77 | static int nntpdriver_get_messages_list(mailsession * session, | ||
78 | struct mailmessage_list ** result); | ||
79 | |||
80 | static int nntpdriver_list_folders(mailsession * session, char * mb, | ||
81 | struct mail_list ** result); | ||
82 | |||
83 | static int nntpdriver_lsub_folders(mailsession * session, char * mb, | ||
84 | struct mail_list ** result); | ||
85 | |||
86 | static int nntpdriver_subscribe_folder(mailsession * session, char * mb); | ||
87 | |||
88 | static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb); | ||
89 | |||
90 | static int nntpdriver_get_message(mailsession * session, | ||
91 | uint32_t num, mailmessage ** result); | ||
92 | |||
93 | static int nntpdriver_get_message_by_uid(mailsession * session, | ||
94 | const char * uid, | ||
95 | mailmessage ** result); | ||
96 | |||
97 | static int nntpdriver_noop(mailsession * session); | ||
98 | |||
99 | static mailsession_driver local_nntp_session_driver = { | ||
100 | .sess_name = "nntp", | ||
101 | |||
102 | .sess_initialize = nntpdriver_initialize, | ||
103 | .sess_uninitialize = nntpdriver_uninitialize, | ||
104 | |||
105 | .sess_parameters = nntpdriver_parameters, | ||
106 | |||
107 | .sess_connect_stream = nntpdriver_connect_stream, | ||
108 | .sess_connect_path = NULL, | ||
109 | .sess_starttls = NULL, | ||
110 | .sess_login = nntpdriver_login, | ||
111 | .sess_logout = nntpdriver_logout, | ||
112 | .sess_noop = nntpdriver_noop, | ||
113 | |||
114 | .sess_build_folder_name = NULL, | ||
115 | .sess_create_folder = NULL, | ||
116 | .sess_delete_folder = NULL, | ||
117 | .sess_rename_folder = NULL, | ||
118 | .sess_check_folder = NULL, | ||
119 | .sess_examine_folder = NULL, | ||
120 | .sess_select_folder = nntpdriver_select_folder, | ||
121 | .sess_expunge_folder = NULL, | ||
122 | .sess_status_folder = nntpdriver_status_folder, | ||
123 | .sess_messages_number = nntpdriver_messages_number, | ||
124 | .sess_recent_number = nntpdriver_messages_number, | ||
125 | .sess_unseen_number = nntpdriver_messages_number, | ||
126 | .sess_list_folders = nntpdriver_list_folders, | ||
127 | .sess_lsub_folders = nntpdriver_lsub_folders, | ||
128 | .sess_subscribe_folder = nntpdriver_subscribe_folder, | ||
129 | .sess_unsubscribe_folder = nntpdriver_unsubscribe_folder, | ||
130 | |||
131 | .sess_append_message = nntpdriver_append_message, | ||
132 | .sess_copy_message = NULL, | ||
133 | .sess_move_message = NULL, | ||
134 | |||
135 | .sess_get_messages_list = nntpdriver_get_messages_list, | ||
136 | .sess_get_envelopes_list = nntpdriver_get_envelopes_list, | ||
137 | .sess_remove_message = NULL, | ||
138 | #if 0 | ||
139 | .sess_search_messages = maildriver_generic_search_messages, | ||
140 | #endif | ||
141 | |||
142 | .sess_get_message = nntpdriver_get_message, | ||
143 | .sess_get_message_by_uid = nntpdriver_get_message_by_uid, | ||
144 | }; | ||
145 | |||
146 | |||
147 | mailsession_driver * nntp_session_driver = &local_nntp_session_driver; | ||
148 | |||
149 | static inline struct nntp_session_state_data * | ||
150 | get_data(mailsession * session) | ||
151 | { | ||
152 | return session->sess_data; | ||
153 | } | ||
154 | |||
155 | static inline newsnntp * get_nntp_session(mailsession * session) | ||
156 | { | ||
157 | return get_data(session)->nntp_session; | ||
158 | } | ||
159 | |||
160 | static int nntpdriver_initialize(mailsession * session) | ||
161 | { | ||
162 | struct nntp_session_state_data * data; | ||
163 | newsnntp * nntp; | ||
164 | |||
165 | nntp = newsnntp_new(0, NULL); | ||
166 | if (nntp == NULL) | ||
167 | goto err; | ||
168 | |||
169 | data = malloc(sizeof(* data)); | ||
170 | if (data == NULL) | ||
171 | goto free; | ||
172 | |||
173 | data->nntp_session = nntp; | ||
174 | |||
175 | data->nntp_userid = NULL; | ||
176 | data->nntp_password = NULL; | ||
177 | |||
178 | data->nntp_group_info = NULL; | ||
179 | data->nntp_group_name = NULL; | ||
180 | |||
181 | data->nntp_subscribed_list = clist_new(); | ||
182 | if (data->nntp_subscribed_list == NULL) | ||
183 | goto free_data; | ||
184 | |||
185 | data->nntp_max_articles = 0; | ||
186 | |||
187 | data->nntp_mode_reader = FALSE; | ||
188 | |||
189 | session->sess_data = data; | ||
190 | |||
191 | return MAIL_NO_ERROR; | ||
192 | |||
193 | free_data: | ||
194 | free(data); | ||
195 | free: | ||
196 | newsnntp_free(nntp); | ||
197 | err: | ||
198 | return MAIL_ERROR_MEMORY; | ||
199 | } | ||
200 | |||
201 | static void nntpdriver_uninitialize(mailsession * session) | ||
202 | { | ||
203 | struct nntp_session_state_data * data; | ||
204 | |||
205 | data = get_data(session); | ||
206 | |||
207 | clist_foreach(data->nntp_subscribed_list, (clist_func) free, NULL); | ||
208 | clist_free(data->nntp_subscribed_list); | ||
209 | |||
210 | if (data->nntp_group_info != NULL) | ||
211 | newsnntp_group_free(data->nntp_group_info); | ||
212 | |||
213 | if (data->nntp_group_name != NULL) | ||
214 | free(data->nntp_group_name); | ||
215 | |||
216 | if (data->nntp_userid != NULL) | ||
217 | free(data->nntp_userid); | ||
218 | |||
219 | if (data->nntp_password != NULL) | ||
220 | free(data->nntp_password); | ||
221 | |||
222 | newsnntp_free(data->nntp_session); | ||
223 | free(data); | ||
224 | |||
225 | session->sess_data = NULL; | ||
226 | } | ||
227 | |||
228 | |||
229 | static int nntpdriver_parameters(mailsession * session, | ||
230 | int id, void * value) | ||
231 | { | ||
232 | struct nntp_session_state_data * data; | ||
233 | |||
234 | data = get_data(session); | ||
235 | |||
236 | switch (id) { | ||
237 | case NNTPDRIVER_SET_MAX_ARTICLES: | ||
238 | { | ||
239 | uint32_t * param; | ||
240 | |||
241 | param = value; | ||
242 | |||
243 | data->nntp_max_articles = * param; | ||
244 | return MAIL_NO_ERROR; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | return MAIL_ERROR_INVAL; | ||
249 | } | ||
250 | |||
251 | |||
252 | static int add_to_list(mailsession * session, char * mb) | ||
253 | { | ||
254 | char * new_mb; | ||
255 | int r; | ||
256 | struct nntp_session_state_data * data; | ||
257 | |||
258 | data = get_data(session); | ||
259 | |||
260 | new_mb = strdup(mb); | ||
261 | if (new_mb == NULL) | ||
262 | return -1; | ||
263 | |||
264 | r = clist_append(data->nntp_subscribed_list, new_mb); | ||
265 | if (r < 0) { | ||
266 | free(mb); | ||
267 | return -1; | ||
268 | } | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int remove_from_list(mailsession * session, char * mb) | ||
274 | { | ||
275 | clistiter * cur; | ||
276 | struct nntp_session_state_data * data; | ||
277 | |||
278 | data = get_data(session); | ||
279 | |||
280 | for(cur = clist_begin(data->nntp_subscribed_list) ; cur != NULL ; | ||
281 | cur = clist_next(cur)) { | ||
282 | char * cur_name; | ||
283 | |||
284 | cur_name = clist_content(cur); | ||
285 | if (strcmp(cur_name, mb) == 0) { | ||
286 | clist_delete(data->nntp_subscribed_list, cur); | ||
287 | free(cur_name); | ||
288 | return 0; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | return -1; | ||
293 | } | ||
294 | |||
295 | |||
296 | static int nntpdriver_connect_stream(mailsession * session, mailstream * s) | ||
297 | { | ||
298 | int r; | ||
299 | |||
300 | r = newsnntp_connect(get_nntp_session(session), s); | ||
301 | |||
302 | switch (r) { | ||
303 | case NEWSNNTP_NO_ERROR: | ||
304 | return MAIL_NO_ERROR_NON_AUTHENTICATED; | ||
305 | |||
306 | default: | ||
307 | return nntpdriver_nntp_error_to_mail_error(r); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | static int nntpdriver_login(mailsession * session, | ||
312 | char * userid, char * password) | ||
313 | { | ||
314 | struct nntp_session_state_data * data; | ||
315 | char * new_userid; | ||
316 | char * new_password; | ||
317 | |||
318 | data = get_data(session); | ||
319 | |||
320 | if (userid != NULL) { | ||
321 | new_userid = strdup(userid); | ||
322 | if (new_userid == NULL) | ||
323 | goto err; | ||
324 | } | ||
325 | else | ||
326 | new_userid = NULL; | ||
327 | |||
328 | if (password != NULL) { | ||
329 | new_password = strdup(password); | ||
330 | if (new_password == NULL) | ||
331 | goto free_uid; | ||
332 | } | ||
333 | else | ||
334 | new_password = NULL; | ||
335 | |||
336 | data->nntp_userid = new_userid; | ||
337 | data->nntp_password = new_password; | ||
338 | |||
339 | return MAIL_NO_ERROR; | ||
340 | |||
341 | free_uid: | ||
342 | if (new_userid != NULL) | ||
343 | free(new_userid); | ||
344 | err: | ||
345 | return MAIL_ERROR_MEMORY; | ||
346 | } | ||
347 | |||
348 | static int nntpdriver_logout(mailsession * session) | ||
349 | { | ||
350 | int r; | ||
351 | |||
352 | r = newsnntp_quit(get_nntp_session(session)); | ||
353 | |||
354 | return nntpdriver_nntp_error_to_mail_error(r); | ||
355 | } | ||
356 | |||
357 | |||
358 | static int nntpdriver_status_folder(mailsession * session, char * mb, | ||
359 | uint32_t * result_messages, | ||
360 | uint32_t * result_recent, | ||
361 | uint32_t * result_unseen) | ||
362 | { | ||
363 | uint32_t count; | ||
364 | int r; | ||
365 | |||
366 | r = nntpdriver_select_folder(session, mb); | ||
367 | if (r != MAIL_NO_ERROR) | ||
368 | return r; | ||
369 | |||
370 | r = nntpdriver_messages_number(session, mb, &count); | ||
371 | if (r != MAIL_NO_ERROR) | ||
372 | return r; | ||
373 | |||
374 | * result_messages = count; | ||
375 | * result_recent = count; | ||
376 | * result_unseen = count; | ||
377 | |||
378 | return MAIL_NO_ERROR; | ||
379 | } | ||
380 | |||
381 | static int nntpdriver_messages_number(mailsession * session, char * mb, | ||
382 | uint32_t * result) | ||
383 | { | ||
384 | int r; | ||
385 | struct nntp_session_state_data * data; | ||
386 | |||
387 | if (mb != NULL) { | ||
388 | r = nntpdriver_select_folder(session, mb); | ||
389 | if (r != MAIL_NO_ERROR) | ||
390 | return r; | ||
391 | } | ||
392 | |||
393 | data = get_data(session); | ||
394 | |||
395 | if (data->nntp_group_info == NULL) | ||
396 | return MAIL_ERROR_FOLDER_NOT_FOUND; | ||
397 | |||
398 | * result = data->nntp_group_info->grp_last - | ||
399 | data->nntp_group_info->grp_first + 1; | ||
400 | |||
401 | return MAIL_NO_ERROR; | ||
402 | } | ||
403 | |||
404 | static int nntpdriver_list_folders(mailsession * session, char * mb, | ||
405 | struct mail_list ** result) | ||
406 | { | ||
407 | int r; | ||
408 | clist * group_list; | ||
409 | newsnntp * nntp; | ||
410 | clistiter * cur; | ||
411 | char * new_mb; | ||
412 | int done; | ||
413 | clist * list; | ||
414 | struct mail_list * ml; | ||
415 | int res; | ||
416 | |||
417 | nntp = get_nntp_session(session); | ||
418 | |||
419 | new_mb = NULL; | ||
420 | if ((mb != NULL) && (*mb != '\0')) { | ||
421 | new_mb = malloc(strlen(mb) + 3); | ||
422 | if (new_mb == NULL) { | ||
423 | res = MAIL_ERROR_MEMORY; | ||
424 | goto err; | ||
425 | } | ||
426 | strcpy(new_mb, mb); | ||
427 | strcat(new_mb, ".*"); | ||
428 | } | ||
429 | |||
430 | done = FALSE; | ||
431 | do { | ||
432 | if (new_mb != NULL) | ||
433 | r = newsnntp_list_active(nntp, new_mb, &group_list); | ||
434 | else | ||
435 | r = newsnntp_list(nntp, &group_list); | ||
436 | |||
437 | switch (r) { | ||
438 | case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: | ||
439 | r = nntpdriver_authenticate_user(session); | ||
440 | if (r != MAIL_NO_ERROR) { | ||
441 | res = r; | ||
442 | goto err; | ||
443 | } | ||
444 | break; | ||
445 | |||
446 | case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: | ||
447 | r = nntpdriver_authenticate_password(session); | ||
448 | if (r != MAIL_NO_ERROR) { | ||
449 | res = r; | ||
450 | goto err; | ||
451 | } | ||
452 | break; | ||
453 | |||
454 | case NEWSNNTP_NO_ERROR: | ||
455 | if (new_mb != NULL) | ||
456 | free(new_mb); | ||
457 | done = TRUE; | ||
458 | break; | ||
459 | |||
460 | default: | ||
461 | if (new_mb != NULL) | ||
462 | free(new_mb); | ||
463 | return nntpdriver_nntp_error_to_mail_error(r); | ||
464 | } | ||
465 | } | ||
466 | while (!done); | ||
467 | |||
468 | list = clist_new(); | ||
469 | if (list == NULL) { | ||
470 | res = MAIL_ERROR_MEMORY; | ||
471 | goto err; | ||
472 | } | ||
473 | |||
474 | for(cur = clist_begin(group_list) ; cur != NULL ; | ||
475 | cur = clist_next(cur)) { | ||
476 | struct newsnntp_group_info * info; | ||
477 | char * new_name; | ||
478 | |||
479 | info = clist_content(cur); | ||
480 | new_name = strdup(info->grp_name); | ||
481 | if (new_name == NULL) { | ||
482 | res = MAIL_ERROR_MEMORY; | ||
483 | goto free_list; | ||
484 | } | ||
485 | |||
486 | r = clist_append(list, new_name); | ||
487 | if (r < 0) { | ||
488 | free(new_name); | ||
489 | res = MAIL_ERROR_MEMORY; | ||
490 | goto free_list; | ||
491 | } | ||
492 | } | ||
493 | |||
494 | ml = mail_list_new(list); | ||
495 | if (ml == NULL) { | ||
496 | res = MAIL_ERROR_MEMORY; | ||
497 | goto free_list; | ||
498 | } | ||
499 | |||
500 | newsnntp_list_free(group_list); | ||
501 | |||
502 | * result = ml; | ||
503 | |||
504 | return MAIL_NO_ERROR; | ||
505 | |||
506 | free_list: | ||
507 | clist_foreach(list, (clist_func) free, NULL); | ||
508 | clist_free(list); | ||
509 | newsnntp_list_free(group_list); | ||
510 | err: | ||
511 | return res; | ||
512 | } | ||
513 | |||
514 | static int nntpdriver_lsub_folders(mailsession * session, char * mb, | ||
515 | struct mail_list ** result) | ||
516 | { | ||
517 | clist * subscribed; | ||
518 | clist * lsub_result; | ||
519 | clistiter * cur; | ||
520 | struct mail_list * lsub; | ||
521 | size_t length; | ||
522 | int res; | ||
523 | int r; | ||
524 | struct nntp_session_state_data * data; | ||
525 | |||
526 | length = strlen(mb); | ||
527 | |||
528 | data = get_data(session); | ||
529 | |||
530 | subscribed = data->nntp_subscribed_list; | ||
531 | lsub_result = clist_new(); | ||
532 | if (lsub_result == NULL) { | ||
533 | res = MAIL_ERROR_MEMORY; | ||
534 | goto err; | ||
535 | } | ||
536 | |||
537 | for(cur = clist_begin(subscribed) ; cur != NULL ; | ||
538 | cur = clist_next(cur)) { | ||
539 | char * cur_mb; | ||
540 | char * new_mb; | ||
541 | |||
542 | cur_mb = clist_content(cur); | ||
543 | |||
544 | if (strncmp(mb, cur_mb, length) == 0) { | ||
545 | new_mb = strdup(cur_mb); | ||
546 | if (new_mb == NULL) { | ||
547 | res = MAIL_ERROR_MEMORY; | ||
548 | goto free_list; | ||
549 | } | ||
550 | |||
551 | r = clist_append(lsub_result, new_mb); | ||
552 | if (r < 0) { | ||
553 | free(new_mb); | ||
554 | res = MAIL_ERROR_MEMORY; | ||
555 | goto free_list; | ||
556 | } | ||
557 | } | ||
558 | } | ||
559 | |||
560 | lsub = mail_list_new(lsub_result); | ||
561 | if (lsub == NULL) { | ||
562 | res = MAIL_ERROR_MEMORY; | ||
563 | goto free_list; | ||
564 | } | ||
565 | |||
566 | * result = lsub; | ||
567 | |||
568 | return MAIL_NO_ERROR; | ||
569 | |||
570 | free_list: | ||
571 | clist_foreach(lsub_result, (clist_func) free, NULL); | ||
572 | clist_free(lsub_result); | ||
573 | err: | ||
574 | return res; | ||
575 | } | ||
576 | |||
577 | static int nntpdriver_subscribe_folder(mailsession * session, char * mb) | ||
578 | { | ||
579 | int r; | ||
580 | |||
581 | r = add_to_list(session, mb); | ||
582 | if (r < 0) | ||
583 | return MAIL_ERROR_SUBSCRIBE; | ||
584 | |||
585 | return MAIL_NO_ERROR; | ||
586 | } | ||
587 | |||
588 | static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb) | ||
589 | { | ||
590 | int r; | ||
591 | |||
592 | r = remove_from_list(session, mb); | ||
593 | if (r < 0) | ||
594 | return MAIL_ERROR_UNSUBSCRIBE; | ||
595 | |||
596 | return MAIL_NO_ERROR; | ||
597 | } | ||
598 | |||
599 | |||
600 | |||
601 | /* messages operations */ | ||
602 | |||
603 | static int nntpdriver_append_message(mailsession * session, | ||
604 | char * message, size_t size) | ||
605 | { | ||
606 | int r; | ||
607 | struct nntp_session_state_data * data; | ||
608 | |||
609 | data = get_data(session); | ||
610 | |||
611 | do { | ||
612 | r = newsnntp_post(get_nntp_session(session), message, size); | ||
613 | switch (r) { | ||
614 | case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: | ||
615 | r = nntpdriver_authenticate_user(session); | ||
616 | if (r != MAIL_NO_ERROR) | ||
617 | return r; | ||
618 | break; | ||
619 | |||
620 | case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: | ||
621 | r = nntpdriver_authenticate_password(session); | ||
622 | if (r != MAIL_NO_ERROR) | ||
623 | return r; | ||
624 | break; | ||
625 | |||
626 | default: | ||
627 | return nntpdriver_nntp_error_to_mail_error(r); | ||
628 | } | ||
629 | } | ||
630 | while (1); | ||
631 | } | ||
632 | |||
633 | |||
634 | static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, | ||
635 | struct mailimf_fields ** result); | ||
636 | |||
637 | |||
638 | static int | ||
639 | nntpdriver_get_envelopes_list(mailsession * session, | ||
640 | struct mailmessage_list * env_list) | ||
641 | { | ||
642 | newsnntp * nntp; | ||
643 | int r; | ||
644 | struct nntp_session_state_data * data; | ||
645 | clist * list; | ||
646 | int done; | ||
647 | clistiter * cur; | ||
648 | uint32_t first_seq; | ||
649 | unsigned int i; | ||
650 | |||
651 | nntp = get_nntp_session(session); | ||
652 | |||
653 | data = get_data(session); | ||
654 | |||
655 | if (data->nntp_group_info == NULL) | ||
656 | return MAIL_ERROR_BAD_STATE; | ||
657 | |||
658 | first_seq = data->nntp_group_info->grp_first; | ||
659 | |||
660 | if (carray_count(env_list->msg_tab) > 0) { | ||
661 | mailmessage * msg; | ||
662 | |||
663 | msg = carray_get(env_list->msg_tab, 0); | ||
664 | |||
665 | first_seq = msg->msg_index; | ||
666 | } | ||
667 | |||
668 | if (carray_count(env_list->msg_tab) > 0) { | ||
669 | i = carray_count(env_list->msg_tab) - 1; | ||
670 | while (1) { | ||
671 | mailmessage * msg; | ||
672 | |||
673 | msg = carray_get(env_list->msg_tab, i); | ||
674 | |||
675 | if (msg->msg_fields != NULL) { | ||
676 | first_seq = msg->msg_index + 1; | ||
677 | break; | ||
678 | } | ||
679 | |||
680 | if (i == 0) | ||
681 | break; | ||
682 | |||
683 | i --; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | if (first_seq > data->nntp_group_info->grp_last) { | ||
688 | list = NULL; | ||
689 | } | ||
690 | else { | ||
691 | done = FALSE; | ||
692 | do { | ||
693 | r = newsnntp_xover_range(nntp, first_seq, | ||
694 | data->nntp_group_info->grp_last, &list); | ||
695 | |||
696 | switch (r) { | ||
697 | case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: | ||
698 | r = nntpdriver_authenticate_user(session); | ||
699 | if (r != MAIL_NO_ERROR) | ||
700 | return r; | ||
701 | break; | ||
702 | |||
703 | case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: | ||
704 | r = nntpdriver_authenticate_password(session); | ||
705 | if (r != MAIL_NO_ERROR) | ||
706 | return r; | ||
707 | break; | ||
708 | |||
709 | case NEWSNNTP_NO_ERROR: | ||
710 | done = TRUE; | ||
711 | break; | ||
712 | |||
713 | default: | ||
714 | return nntpdriver_nntp_error_to_mail_error(r); | ||
715 | } | ||
716 | } | ||
717 | while (!done); | ||
718 | } | ||
719 | |||
720 | #if 0 | ||
721 | i = 0; | ||
722 | j = 0; | ||
723 | |||
724 | if (list != NULL) { | ||
725 | for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { | ||
726 | struct newsnntp_xover_resp_item * item; | ||
727 | struct mailimf_fields * fields; | ||
728 | |||
729 | item = clist_content(cur); | ||
730 | |||
731 | while (i < carray_count(env_list->msg_tab)) { | ||
732 | mailmessage * info; | ||
733 | |||
734 | info = carray_get(env_list->msg_tab, i); | ||
735 | |||
736 | if (item->ovr_article == info->msg_index) { | ||
737 | |||
738 | if (info->fields == NULL) { | ||
739 | r = xover_resp_to_fields(item, &fields); | ||
740 | if (r == MAIL_NO_ERROR) { | ||
741 | info->fields = fields; | ||
742 | } | ||
743 | |||
744 | info->size = item->ovr_size; | ||
745 | |||
746 | carray_set(env_list->msg_tab, j, info); | ||
747 | j ++; | ||
748 | i ++; | ||
749 | break; | ||
750 | } | ||
751 | else { | ||
752 | carray_set(env_list->msg_tab, j, info); | ||
753 | j ++; | ||
754 | } | ||
755 | } | ||
756 | else { | ||
757 | if (info->fields != NULL) { | ||
758 | carray_set(env_list->msg_tab, j, info); | ||
759 | j ++; | ||
760 | } | ||
761 | else { | ||
762 | if (info->flags != NULL) { | ||
763 | info->flags->flags &= ~MAIL_FLAG_NEW; | ||
764 | info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED; | ||
765 | mailmessage_check(info); | ||
766 | } | ||
767 | mailmessage_free(info); | ||
768 | carray_set(env_list->msg_tab, i, NULL); | ||
769 | } | ||
770 | } | ||
771 | |||
772 | i ++; | ||
773 | } | ||
774 | } | ||
775 | } | ||
776 | |||
777 | while (i < carray_count(env_list->msg_tab)) { | ||
778 | mailmessage * info; | ||
779 | |||
780 | info = carray_get(env_list->msg_tab, i); | ||
781 | if (info->fields != NULL) { | ||
782 | carray_set(env_list->msg_tab, j, info); | ||
783 | j ++; | ||
784 | } | ||
785 | else { | ||
786 | if (info->flags != NULL) { | ||
787 | info->flags->flags &= ~MAIL_FLAG_NEW; | ||
788 | info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED; | ||
789 | mailmessage_check(info); | ||
790 | } | ||
791 | mailmessage_free(info); | ||
792 | carray_set(env_list->msg_tab, i, NULL); | ||
793 | } | ||
794 | |||
795 | i ++; | ||
796 | } | ||
797 | |||
798 | r = carray_set_size(env_list->msg_tab, j); | ||
799 | if (r < 0) { | ||
800 | if (list != NULL) | ||
801 | newsnntp_xover_resp_list_free(list); | ||
802 | return MAIL_ERROR_MEMORY; | ||
803 | } | ||
804 | #endif | ||
805 | i = 0; | ||
806 | |||
807 | if (list != NULL) { | ||
808 | for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { | ||
809 | struct newsnntp_xover_resp_item * item; | ||
810 | struct mailimf_fields * fields; | ||
811 | |||
812 | item = clist_content(cur); | ||
813 | |||
814 | while (i < carray_count(env_list->msg_tab)) { | ||
815 | mailmessage * info; | ||
816 | |||
817 | info = carray_get(env_list->msg_tab, i); | ||
818 | |||
819 | if (item->ovr_article == info->msg_index) { | ||
820 | |||
821 | if (info->msg_fields == NULL) { | ||
822 | r = xover_resp_to_fields(item, &fields); | ||
823 | if (r == MAIL_NO_ERROR) { | ||
824 | info->msg_fields = fields; | ||
825 | } | ||
826 | |||
827 | info->msg_size = item->ovr_size; | ||
828 | |||
829 | i ++; | ||
830 | break; | ||
831 | } | ||
832 | } | ||
833 | #if 0 | ||
834 | else if ((info->fields == NULL) && (info->flags != NULL)) { | ||
835 | info->flags->flags &= ~MAIL_FLAG_NEW; | ||
836 | info->flags->flags |= MAIL_FLAG_CANCELLED; | ||
837 | mailmessage_check(info); | ||
838 | } | ||
839 | #endif | ||
840 | |||
841 | i ++; | ||
842 | } | ||
843 | } | ||
844 | } | ||
845 | |||
846 | #if 0 | ||
847 | while (i < env_list->msg_tab->len) { | ||
848 | mailmessage * info; | ||
849 | |||
850 | info = carray_get(env_list->msg_tab, i); | ||
851 | if ((info->fields == NULL) && (info->flags != NULL)) { | ||
852 | info->flags->flags &= ~MAIL_FLAG_NEW; | ||
853 | info->flags->flags |= MAIL_FLAG_CANCELLED; | ||
854 | mailmessage_check(info); | ||
855 | } | ||
856 | |||
857 | i ++; | ||
858 | } | ||
859 | #endif | ||
860 | |||
861 | if (list != NULL) | ||
862 | newsnntp_xover_resp_list_free(list); | ||
863 | |||
864 | return MAIL_NO_ERROR; | ||
865 | } | ||
866 | |||
867 | |||
868 | static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, | ||
869 | struct mailimf_fields ** result) | ||
870 | { | ||
871 | size_t cur_token; | ||
872 | clist * list; | ||
873 | int r; | ||
874 | struct mailimf_fields * fields; | ||
875 | int res; | ||
876 | |||
877 | list = clist_new(); | ||
878 | if (list == NULL) { | ||
879 | res = MAIL_ERROR_MEMORY; | ||
880 | goto err; | ||
881 | } | ||
882 | |||
883 | if (item->ovr_subject != NULL) { | ||
884 | char * subject_str; | ||
885 | struct mailimf_subject * subject; | ||
886 | struct mailimf_field * field; | ||
887 | |||
888 | subject_str = strdup(item->ovr_subject); | ||
889 | if (subject_str == NULL) { | ||
890 | res = MAIL_ERROR_MEMORY; | ||
891 | goto free_list; | ||
892 | } | ||
893 | |||
894 | subject = mailimf_subject_new(subject_str); | ||
895 | if (subject == NULL) { | ||
896 | free(subject_str); | ||
897 | res = MAIL_ERROR_MEMORY; | ||
898 | goto free_list; | ||
899 | } | ||
900 | |||
901 | field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, | ||
902 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
903 | NULL, NULL, NULL, | ||
904 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
905 | NULL, subject, NULL, NULL, NULL); | ||
906 | if (field == NULL) { | ||
907 | mailimf_subject_free(subject); | ||
908 | res = MAIL_ERROR_MEMORY; | ||
909 | goto free_list; | ||
910 | } | ||
911 | |||
912 | r = clist_append(list, field); | ||
913 | if (r < 0) { | ||
914 | mailimf_field_free(field); | ||
915 | res = MAIL_ERROR_MEMORY; | ||
916 | goto free_list; | ||
917 | } | ||
918 | } | ||
919 | |||
920 | if (item->ovr_author != NULL) { | ||
921 | struct mailimf_mailbox_list * mb_list; | ||
922 | struct mailimf_from * from; | ||
923 | struct mailimf_field * field; | ||
924 | |||
925 | cur_token = 0; | ||
926 | r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author), | ||
927 | &cur_token, &mb_list); | ||
928 | switch (r) { | ||
929 | case MAILIMF_NO_ERROR: | ||
930 | from = mailimf_from_new(mb_list); | ||
931 | if (from == NULL) { | ||
932 | mailimf_mailbox_list_free(mb_list); | ||
933 | res = MAIL_ERROR_MEMORY; | ||
934 | goto free_list; | ||
935 | } | ||
936 | |||
937 | field = mailimf_field_new(MAILIMF_FIELD_FROM, | ||
938 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
939 | NULL, NULL, from, | ||
940 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
941 | NULL, NULL, NULL, NULL, NULL); | ||
942 | if (field == NULL) { | ||
943 | mailimf_from_free(from); | ||
944 | res = MAIL_ERROR_MEMORY; | ||
945 | goto free_list; | ||
946 | } | ||
947 | |||
948 | r = clist_append(list, field); | ||
949 | if (r < 0) { | ||
950 | mailimf_field_free(field); | ||
951 | res = MAIL_ERROR_MEMORY; | ||
952 | goto free_list; | ||
953 | } | ||
954 | break; | ||
955 | |||
956 | case MAILIMF_ERROR_PARSE: | ||
957 | break; | ||
958 | |||
959 | default: | ||
960 | res = maildriver_imf_error_to_mail_error(r); | ||
961 | goto free_list; | ||
962 | } | ||
963 | } | ||
964 | |||
965 | if (item->ovr_date != NULL) { | ||
966 | struct mailimf_date_time * date_time; | ||
967 | struct mailimf_orig_date * orig_date; | ||
968 | struct mailimf_field * field; | ||
969 | |||
970 | cur_token = 0; | ||
971 | r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date), | ||
972 | &cur_token, &date_time); | ||
973 | switch (r) { | ||
974 | case MAILIMF_NO_ERROR: | ||
975 | orig_date = mailimf_orig_date_new(date_time); | ||
976 | if (orig_date == NULL) { | ||
977 | mailimf_date_time_free(date_time); | ||
978 | res = MAIL_ERROR_MEMORY; | ||
979 | goto free_list; | ||
980 | } | ||
981 | |||
982 | field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, | ||
983 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
984 | NULL, orig_date, NULL, | ||
985 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
986 | NULL, NULL, NULL, NULL, NULL); | ||
987 | if (field == NULL) { | ||
988 | mailimf_orig_date_free(orig_date); | ||
989 | res = MAIL_ERROR_MEMORY; | ||
990 | goto free_list; | ||
991 | } | ||
992 | |||
993 | r = clist_append(list, field); | ||
994 | if (r < 0) { | ||
995 | mailimf_field_free(field); | ||
996 | res = MAIL_ERROR_MEMORY; | ||
997 | goto free_list; | ||
998 | } | ||
999 | break; | ||
1000 | |||
1001 | case MAILIMF_ERROR_PARSE: | ||
1002 | break; | ||
1003 | |||
1004 | default: | ||
1005 | res = maildriver_imf_error_to_mail_error(r); | ||
1006 | goto free_list; | ||
1007 | } | ||
1008 | } | ||
1009 | |||
1010 | if (item->ovr_message_id != NULL) { | ||
1011 | char * msgid_str; | ||
1012 | struct mailimf_message_id * msgid; | ||
1013 | struct mailimf_field * field; | ||
1014 | |||
1015 | cur_token = 0; | ||
1016 | r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id), | ||
1017 | &cur_token, &msgid_str); | ||
1018 | |||
1019 | switch (r) { | ||
1020 | case MAILIMF_NO_ERROR: | ||
1021 | msgid = mailimf_message_id_new(msgid_str); | ||
1022 | if (msgid == NULL) { | ||
1023 | mailimf_msg_id_free(msgid_str); | ||
1024 | res = MAIL_ERROR_MEMORY; | ||
1025 | goto free_list; | ||
1026 | } | ||
1027 | |||
1028 | field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, | ||
1029 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
1030 | NULL, NULL, NULL, | ||
1031 | NULL, NULL, NULL, NULL, NULL, msgid, NULL, | ||
1032 | NULL, NULL, NULL, NULL, NULL); | ||
1033 | |||
1034 | r = clist_append(list, field); | ||
1035 | if (r < 0) { | ||
1036 | mailimf_field_free(field); | ||
1037 | res = MAIL_ERROR_MEMORY; | ||
1038 | goto free_list; | ||
1039 | } | ||
1040 | break; | ||
1041 | |||
1042 | case MAILIMF_ERROR_PARSE: | ||
1043 | break; | ||
1044 | |||
1045 | default: | ||
1046 | res = maildriver_imf_error_to_mail_error(r); | ||
1047 | goto free_list; | ||
1048 | } | ||
1049 | } | ||
1050 | |||
1051 | if (item->ovr_references != NULL) { | ||
1052 | clist * msgid_list; | ||
1053 | struct mailimf_references * references; | ||
1054 | struct mailimf_field * field; | ||
1055 | |||
1056 | cur_token = 0; | ||
1057 | |||
1058 | r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references), | ||
1059 | &cur_token, &msgid_list); | ||
1060 | |||
1061 | switch (r) { | ||
1062 | case MAILIMF_NO_ERROR: | ||
1063 | references = mailimf_references_new(msgid_list); | ||
1064 | if (references == NULL) { | ||
1065 | clist_foreach(msgid_list, | ||
1066 | (clist_func) mailimf_msg_id_free, NULL); | ||
1067 | clist_free(msgid_list); | ||
1068 | res = MAIL_ERROR_MEMORY; | ||
1069 | goto free_list; | ||
1070 | } | ||
1071 | |||
1072 | field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, | ||
1073 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
1074 | NULL, NULL, NULL, | ||
1075 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
1076 | references, NULL, NULL, NULL, NULL); | ||
1077 | |||
1078 | r = clist_append(list, field); | ||
1079 | if (r < 0) { | ||
1080 | mailimf_field_free(field); | ||
1081 | res = MAIL_ERROR_MEMORY; | ||
1082 | goto free_list; | ||
1083 | } | ||
1084 | |||
1085 | case MAILIMF_ERROR_PARSE: | ||
1086 | break; | ||
1087 | |||
1088 | default: | ||
1089 | res = maildriver_imf_error_to_mail_error(r); | ||
1090 | goto free_list; | ||
1091 | } | ||
1092 | } | ||
1093 | |||
1094 | fields = mailimf_fields_new(list); | ||
1095 | if (fields == NULL) { | ||
1096 | res = MAIL_ERROR_MEMORY; | ||
1097 | goto free_list; | ||
1098 | } | ||
1099 | |||
1100 | * result = fields; | ||
1101 | |||
1102 | return MAIL_NO_ERROR; | ||
1103 | |||
1104 | free_list: | ||
1105 | clist_foreach(list, (clist_func) mailimf_field_free, NULL); | ||
1106 | clist_free(list); | ||
1107 | err: | ||
1108 | return res; | ||
1109 | } | ||
1110 | |||
1111 | |||
1112 | /* get messages list with group info */ | ||
1113 | |||
1114 | static int nntpdriver_get_messages_list(mailsession * session, | ||
1115 | struct mailmessage_list ** result) | ||
1116 | { | ||
1117 | return nntp_get_messages_list(session, session, nntp_message_driver, result); | ||
1118 | |||
1119 | } | ||
1120 | |||
1121 | static int nntpdriver_get_message(mailsession * session, | ||
1122 | uint32_t num, mailmessage ** result) | ||
1123 | { | ||
1124 | mailmessage * msg_info; | ||
1125 | int r; | ||
1126 | |||
1127 | msg_info = mailmessage_new(); | ||
1128 | if (msg_info == NULL) | ||
1129 | return MAIL_ERROR_MEMORY; | ||
1130 | |||
1131 | r = mailmessage_init(msg_info, session, nntp_message_driver, num, 0); | ||
1132 | if (r != MAIL_NO_ERROR) { | ||
1133 | mailmessage_free(msg_info); | ||
1134 | return r; | ||
1135 | } | ||
1136 | |||
1137 | * result = msg_info; | ||
1138 | |||
1139 | return MAIL_NO_ERROR; | ||
1140 | } | ||
1141 | |||
1142 | static int nntpdriver_noop(mailsession * session) | ||
1143 | { | ||
1144 | newsnntp * nntp; | ||
1145 | int r; | ||
1146 | struct tm tm; | ||
1147 | |||
1148 | nntp = get_nntp_session(session); | ||
1149 | |||
1150 | r = newsnntp_date(nntp, &tm); | ||
1151 | |||
1152 | return nntpdriver_nntp_error_to_mail_error(r); | ||
1153 | } | ||
1154 | |||
1155 | static int nntpdriver_get_message_by_uid(mailsession * session, | ||
1156 | const char * uid, | ||
1157 | mailmessage ** result) | ||
1158 | { | ||
1159 | uint32_t num; | ||
1160 | char * p; | ||
1161 | |||
1162 | if (uid == NULL) | ||
1163 | return MAIL_ERROR_INVAL; | ||
1164 | |||
1165 | num = strtoul(uid, &p, 10); | ||
1166 | if ((p == uid) || (* p != '\0')) | ||
1167 | return MAIL_ERROR_INVAL; | ||
1168 | |||
1169 | return nntpdriver_get_message(session, num, result); | ||
1170 | } | ||