summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/nntp/nntpdriver_tools.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_tools.c563
1 files changed, 563 insertions, 0 deletions
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}