-rw-r--r-- | libetpan/src/low-level/nntp/newsnntp.c | 2486 | ||||
-rw-r--r-- | libetpan/src/low-level/nntp/newsnntp.h | 187 | ||||
-rw-r--r-- | libetpan/src/low-level/nntp/newsnntp_socket.c | 74 | ||||
-rw-r--r-- | libetpan/src/low-level/nntp/newsnntp_socket.h | 55 | ||||
-rw-r--r-- | libetpan/src/low-level/nntp/newsnntp_ssl.c | 73 | ||||
-rw-r--r-- | libetpan/src/low-level/nntp/newsnntp_ssl.h | 55 | ||||
-rw-r--r-- | libetpan/src/low-level/nntp/newsnntp_types.h | 144 |
7 files changed, 3074 insertions, 0 deletions
diff --git a/libetpan/src/low-level/nntp/newsnntp.c b/libetpan/src/low-level/nntp/newsnntp.c new file mode 100644 index 0000000..bf2312c --- a/dev/null +++ b/libetpan/src/low-level/nntp/newsnntp.c | |||
@@ -0,0 +1,2486 @@ | |||
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 "newsnntp.h" | ||
37 | |||
38 | |||
39 | #include <unistd.h> | ||
40 | #include <stdio.h> | ||
41 | #include <netinet/in.h> | ||
42 | #include <netdb.h> | ||
43 | #include <string.h> | ||
44 | #include <stdlib.h> | ||
45 | #include <time.h> | ||
46 | |||
47 | #include "connect.h" | ||
48 | #include "mail.h" | ||
49 | #include "clist.h" | ||
50 | |||
51 | /* | ||
52 | NNTP Protocol | ||
53 | |||
54 | RFC 977 | ||
55 | RFC 2980 | ||
56 | |||
57 | TODO : | ||
58 | |||
59 | XPAT header range|<message-id> pat [pat...] | ||
60 | |||
61 | |||
62 | */ | ||
63 | |||
64 | |||
65 | |||
66 | |||
67 | #define NNTP_STRING_SIZE 513 | ||
68 | |||
69 | |||
70 | |||
71 | static char * read_line(newsnntp * f); | ||
72 | static char * read_multiline(newsnntp * f, size_t size, | ||
73 | MMAPString * multiline_buffer); | ||
74 | static int parse_response(newsnntp * f, char * response); | ||
75 | |||
76 | static int send_command(newsnntp * f, char * command); | ||
77 | |||
78 | newsnntp * newsnntp_new(size_t progr_rate, progress_function * progr_fun) | ||
79 | { | ||
80 | newsnntp * f; | ||
81 | |||
82 | f = malloc(sizeof(* f)); | ||
83 | if (f == NULL) | ||
84 | goto err; | ||
85 | |||
86 | f->nntp_stream = NULL; | ||
87 | f->nntp_readonly = FALSE; | ||
88 | |||
89 | f->nntp_progr_rate = progr_rate; | ||
90 | f->nntp_progr_fun = progr_fun; | ||
91 | |||
92 | f->nntp_stream_buffer = mmap_string_new(""); | ||
93 | if (f->nntp_stream_buffer == NULL) | ||
94 | goto free_f; | ||
95 | |||
96 | f->nntp_response_buffer = mmap_string_new(""); | ||
97 | if (f->nntp_response_buffer == NULL) | ||
98 | goto free_stream_buffer; | ||
99 | |||
100 | return f; | ||
101 | |||
102 | free_stream_buffer: | ||
103 | mmap_string_free(f->nntp_stream_buffer); | ||
104 | free_f: | ||
105 | free(f); | ||
106 | err: | ||
107 | return NULL; | ||
108 | } | ||
109 | |||
110 | void newsnntp_free(newsnntp * f) | ||
111 | { | ||
112 | if (f->nntp_stream) | ||
113 | newsnntp_quit(f); | ||
114 | |||
115 | mmap_string_free(f->nntp_response_buffer); | ||
116 | mmap_string_free(f->nntp_stream_buffer); | ||
117 | |||
118 | free(f); | ||
119 | } | ||
120 | |||
121 | |||
122 | |||
123 | |||
124 | |||
125 | |||
126 | |||
127 | |||
128 | |||
129 | |||
130 | |||
131 | |||
132 | |||
133 | |||
134 | |||
135 | |||
136 | int newsnntp_quit(newsnntp * f) | ||
137 | { | ||
138 | char command[NNTP_STRING_SIZE]; | ||
139 | char * response; | ||
140 | int r; | ||
141 | int res; | ||
142 | |||
143 | if (f->nntp_stream == NULL) | ||
144 | return NEWSNNTP_ERROR_BAD_STATE; | ||
145 | |||
146 | snprintf(command, NNTP_STRING_SIZE, "QUIT\r\n"); | ||
147 | r = send_command(f, command); | ||
148 | if (r == -1) { | ||
149 | res = NEWSNNTP_ERROR_STREAM; | ||
150 | goto close; | ||
151 | } | ||
152 | |||
153 | response = read_line(f); | ||
154 | if (response == NULL) { | ||
155 | res = NEWSNNTP_ERROR_STREAM; | ||
156 | goto close; | ||
157 | } | ||
158 | |||
159 | parse_response(f, response); | ||
160 | |||
161 | res = NEWSNNTP_NO_ERROR; | ||
162 | |||
163 | close: | ||
164 | |||
165 | mailstream_close(f->nntp_stream); | ||
166 | |||
167 | f->nntp_stream = NULL; | ||
168 | |||
169 | return res; | ||
170 | } | ||
171 | |||
172 | int newsnntp_connect(newsnntp * f, mailstream * s) | ||
173 | { | ||
174 | char * response; | ||
175 | int r; | ||
176 | |||
177 | if (f->nntp_stream != NULL) | ||
178 | return NEWSNNTP_ERROR_BAD_STATE; | ||
179 | |||
180 | f->nntp_stream = s; | ||
181 | |||
182 | response = read_line(f); | ||
183 | if (response == NULL) | ||
184 | return NEWSNNTP_ERROR_STREAM; | ||
185 | |||
186 | r = parse_response(f, response); | ||
187 | |||
188 | switch (r) { | ||
189 | case 200: | ||
190 | f->nntp_readonly = FALSE; | ||
191 | return NEWSNNTP_NO_ERROR; | ||
192 | |||
193 | case 201: | ||
194 | f->nntp_readonly = TRUE; | ||
195 | return NEWSNNTP_NO_ERROR; | ||
196 | |||
197 | default: | ||
198 | f->nntp_stream = NULL; | ||
199 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | |||
204 | |||
205 | |||
206 | |||
207 | |||
208 | |||
209 | |||
210 | |||
211 | |||
212 | |||
213 | |||
214 | |||
215 | |||
216 | |||
217 | |||
218 | |||
219 | |||
220 | |||
221 | |||
222 | /* | ||
223 | static struct newsnntp_xover_resp_item * get_xover_info(newsnntp * f, | ||
224 | guint32 article); | ||
225 | */ | ||
226 | |||
227 | static void newsnntp_multiline_response_free(char * str) | ||
228 | { | ||
229 | mmap_string_unref(str); | ||
230 | } | ||
231 | |||
232 | void newsnntp_head_free(char * str) | ||
233 | { | ||
234 | newsnntp_multiline_response_free(str); | ||
235 | } | ||
236 | |||
237 | void newsnntp_article_free(char * str) | ||
238 | { | ||
239 | newsnntp_multiline_response_free(str); | ||
240 | } | ||
241 | |||
242 | void newsnntp_body_free(char * str) | ||
243 | { | ||
244 | newsnntp_multiline_response_free(str); | ||
245 | } | ||
246 | |||
247 | /* ******************** HEADER ******************************** */ | ||
248 | |||
249 | /* | ||
250 | message content in (* result) is still there until the | ||
251 | next retrieve or top operation on the mailpop3 structure | ||
252 | */ | ||
253 | |||
254 | static int newsnntp_get_content(newsnntp * f, char ** result, | ||
255 | size_t * result_len) | ||
256 | { | ||
257 | int r; | ||
258 | char * response; | ||
259 | MMAPString * buffer; | ||
260 | char * result_multiline; | ||
261 | |||
262 | response = read_line(f); | ||
263 | if (response == NULL) | ||
264 | return NEWSNNTP_ERROR_STREAM; | ||
265 | |||
266 | r = parse_response(f, response); | ||
267 | |||
268 | switch (r) { | ||
269 | case 480: | ||
270 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
271 | |||
272 | case 381: | ||
273 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
274 | |||
275 | case 220: | ||
276 | case 221: | ||
277 | case 222: | ||
278 | case 223: | ||
279 | buffer = mmap_string_new(""); | ||
280 | if (buffer == NULL) | ||
281 | return NEWSNNTP_ERROR_MEMORY; | ||
282 | |||
283 | result_multiline = read_multiline(f, 0, buffer); | ||
284 | if (result_multiline == NULL) { | ||
285 | mmap_string_free(buffer); | ||
286 | return NEWSNNTP_ERROR_MEMORY; | ||
287 | } | ||
288 | else { | ||
289 | r = mmap_string_ref(buffer); | ||
290 | if (r < 0) { | ||
291 | mmap_string_free(buffer); | ||
292 | return NEWSNNTP_ERROR_MEMORY; | ||
293 | } | ||
294 | |||
295 | * result = result_multiline; | ||
296 | * result_len = buffer->len; | ||
297 | return NEWSNNTP_NO_ERROR; | ||
298 | } | ||
299 | |||
300 | case 412: | ||
301 | return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; | ||
302 | |||
303 | case 420: | ||
304 | return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; | ||
305 | |||
306 | case 423: | ||
307 | return NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER; | ||
308 | |||
309 | case 430: | ||
310 | return NEWSNNTP_ERROR_ARTICLE_NOT_FOUND; | ||
311 | |||
312 | default: | ||
313 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | int newsnntp_head(newsnntp * f, uint32_t index, char ** result, | ||
318 | size_t * result_len) | ||
319 | { | ||
320 | char command[NNTP_STRING_SIZE]; | ||
321 | int r; | ||
322 | |||
323 | snprintf(command, NNTP_STRING_SIZE, "HEAD %i\r\n", index); | ||
324 | r = send_command(f, command); | ||
325 | if (r == -1) | ||
326 | return NEWSNNTP_ERROR_STREAM; | ||
327 | |||
328 | return newsnntp_get_content(f, result, result_len); | ||
329 | } | ||
330 | |||
331 | /* ******************** ARTICLE ******************************** */ | ||
332 | |||
333 | int newsnntp_article(newsnntp * f, uint32_t index, char ** result, | ||
334 | size_t * result_len) | ||
335 | { | ||
336 | char command[NNTP_STRING_SIZE]; | ||
337 | int r; | ||
338 | |||
339 | snprintf(command, NNTP_STRING_SIZE, "ARTICLE %i\r\n", index); | ||
340 | r = send_command(f, command); | ||
341 | if (r == -1) | ||
342 | return NEWSNNTP_ERROR_STREAM; | ||
343 | |||
344 | return newsnntp_get_content(f, result, result_len); | ||
345 | } | ||
346 | |||
347 | /* ******************** BODY ******************************** */ | ||
348 | |||
349 | int newsnntp_body(newsnntp * f, uint32_t index, char ** result, | ||
350 | size_t * result_len) | ||
351 | { | ||
352 | char command[NNTP_STRING_SIZE]; | ||
353 | int r; | ||
354 | |||
355 | snprintf(command, NNTP_STRING_SIZE, "BODY %i\r\n", index); | ||
356 | r = send_command(f, command); | ||
357 | if (r == -1) | ||
358 | return NEWSNNTP_ERROR_STREAM; | ||
359 | |||
360 | return newsnntp_get_content(f, result, result_len); | ||
361 | } | ||
362 | |||
363 | /* ******************** GROUP ******************************** */ | ||
364 | |||
365 | static struct newsnntp_group_info * | ||
366 | group_info_init(char * name, uint32_t first, uint32_t last, uint32_t count, | ||
367 | char type) | ||
368 | { | ||
369 | struct newsnntp_group_info * n; | ||
370 | |||
371 | n = malloc(sizeof(* n)); | ||
372 | |||
373 | if (n == NULL) | ||
374 | return NULL; | ||
375 | |||
376 | n->grp_name = strdup(name); | ||
377 | if (n->grp_name == NULL) { | ||
378 | free(n); | ||
379 | return NULL; | ||
380 | } | ||
381 | |||
382 | n->grp_first = first; | ||
383 | n->grp_last = last; | ||
384 | n->grp_count = count; | ||
385 | n->grp_type = type; | ||
386 | |||
387 | return n; | ||
388 | } | ||
389 | |||
390 | static void group_info_free(struct newsnntp_group_info * n) | ||
391 | { | ||
392 | if (n->grp_name) | ||
393 | free(n->grp_name); | ||
394 | free(n); | ||
395 | } | ||
396 | |||
397 | static void group_info_list_free(clist * l) | ||
398 | { | ||
399 | clist_foreach(l, (clist_func) group_info_free, NULL); | ||
400 | clist_free(l); | ||
401 | } | ||
402 | |||
403 | static int parse_group_info(char * response, | ||
404 | struct newsnntp_group_info ** info); | ||
405 | |||
406 | int newsnntp_group(newsnntp * f, const char * groupname, | ||
407 | struct newsnntp_group_info ** info) | ||
408 | { | ||
409 | char command[NNTP_STRING_SIZE]; | ||
410 | int r; | ||
411 | char * response; | ||
412 | |||
413 | snprintf(command, NNTP_STRING_SIZE, "GROUP %s\r\n", groupname); | ||
414 | r = send_command(f, command); | ||
415 | if (r == -1) | ||
416 | return NEWSNNTP_ERROR_STREAM; | ||
417 | |||
418 | response = read_line(f); | ||
419 | if (response == NULL) | ||
420 | return NEWSNNTP_ERROR_STREAM; | ||
421 | |||
422 | r = parse_response(f, response); | ||
423 | |||
424 | switch (r) { | ||
425 | case 480: | ||
426 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
427 | |||
428 | case 381: | ||
429 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
430 | |||
431 | case 211: | ||
432 | if (!parse_group_info(f->nntp_response, info)) | ||
433 | return NEWSNNTP_ERROR_INVALID_RESPONSE; | ||
434 | return NEWSNNTP_NO_ERROR; | ||
435 | |||
436 | case 411: | ||
437 | return NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP; | ||
438 | |||
439 | default: | ||
440 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
441 | } | ||
442 | } | ||
443 | |||
444 | void newsnntp_group_free(struct newsnntp_group_info * info) | ||
445 | { | ||
446 | group_info_free(info); | ||
447 | } | ||
448 | |||
449 | /* ******************** LIST ******************************** */ | ||
450 | |||
451 | static clist * read_groups_list(newsnntp * f); | ||
452 | |||
453 | int newsnntp_list(newsnntp * f, clist ** result) | ||
454 | { | ||
455 | char command[NNTP_STRING_SIZE]; | ||
456 | int r; | ||
457 | char * response; | ||
458 | |||
459 | snprintf(command, NNTP_STRING_SIZE, "LIST\r\n"); | ||
460 | r = send_command(f, command); | ||
461 | if (r == -1) | ||
462 | return NEWSNNTP_ERROR_STREAM; | ||
463 | |||
464 | response = read_line(f); | ||
465 | if (response == NULL) | ||
466 | return NEWSNNTP_ERROR_STREAM; | ||
467 | |||
468 | r = parse_response(f, response); | ||
469 | |||
470 | switch (r) { | ||
471 | case 480: | ||
472 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
473 | |||
474 | case 381: | ||
475 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
476 | |||
477 | case 215: | ||
478 | * result = read_groups_list(f); | ||
479 | return NEWSNNTP_NO_ERROR; | ||
480 | |||
481 | default: | ||
482 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | void newsnntp_list_free(clist * l) | ||
487 | { | ||
488 | group_info_list_free(l); | ||
489 | } | ||
490 | |||
491 | /* ******************** POST ******************************** */ | ||
492 | |||
493 | static void send_data(newsnntp * f, const char * message, uint32_t size) | ||
494 | { | ||
495 | mailstream_send_data(f->nntp_stream, message, size, | ||
496 | f->nntp_progr_rate, f->nntp_progr_fun); | ||
497 | } | ||
498 | |||
499 | |||
500 | int newsnntp_post(newsnntp * f, const char * message, size_t size) | ||
501 | { | ||
502 | char command[NNTP_STRING_SIZE]; | ||
503 | int r; | ||
504 | char * response; | ||
505 | |||
506 | snprintf(command, NNTP_STRING_SIZE, "POST\r\n"); | ||
507 | r = send_command(f, command); | ||
508 | if (r == -1) | ||
509 | return NEWSNNTP_ERROR_STREAM; | ||
510 | |||
511 | response = read_line(f); | ||
512 | if (response == NULL) | ||
513 | return NEWSNNTP_ERROR_STREAM; | ||
514 | |||
515 | r = parse_response(f, response); | ||
516 | |||
517 | switch (r) { | ||
518 | case 480: | ||
519 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
520 | |||
521 | case 381: | ||
522 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
523 | |||
524 | case 340: | ||
525 | break; | ||
526 | |||
527 | case 440: | ||
528 | return NEWSNNTP_ERROR_POSTING_NOT_ALLOWED; | ||
529 | |||
530 | default: | ||
531 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
532 | } | ||
533 | |||
534 | send_data(f, message, size); | ||
535 | |||
536 | response = read_line(f); | ||
537 | if (response == NULL) | ||
538 | return NEWSNNTP_ERROR_STREAM; | ||
539 | |||
540 | r = parse_response(f, response); | ||
541 | |||
542 | switch (r) { | ||
543 | case 480: | ||
544 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
545 | |||
546 | case 381: | ||
547 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
548 | |||
549 | case 240: | ||
550 | return NEWSNNTP_NO_ERROR; | ||
551 | return 1; | ||
552 | |||
553 | case 441: | ||
554 | return NEWSNNTP_ERROR_POSTING_FAILED; | ||
555 | |||
556 | default: | ||
557 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | |||
562 | /* ******************** AUTHINFO ******************************** */ | ||
563 | |||
564 | int newsnntp_authinfo_username(newsnntp * f, const char * username) | ||
565 | { | ||
566 | char command[NNTP_STRING_SIZE]; | ||
567 | int r; | ||
568 | char * response; | ||
569 | |||
570 | snprintf(command, NNTP_STRING_SIZE, "AUTHINFO USER %s\r\n", username); | ||
571 | r = send_command(f, command); | ||
572 | if (r == -1) | ||
573 | return NEWSNNTP_ERROR_STREAM; | ||
574 | |||
575 | response = read_line(f); | ||
576 | if (response == NULL) | ||
577 | return NEWSNNTP_ERROR_STREAM; | ||
578 | |||
579 | r = parse_response(f, response); | ||
580 | |||
581 | switch (r) { | ||
582 | case 480: | ||
583 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
584 | |||
585 | case 482: | ||
586 | return NEWSNNTP_ERROR_AUTHENTICATION_REJECTED; | ||
587 | |||
588 | case 381: | ||
589 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
590 | |||
591 | case 281: | ||
592 | return NEWSNNTP_NO_ERROR; | ||
593 | |||
594 | default: | ||
595 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
596 | } | ||
597 | } | ||
598 | |||
599 | int newsnntp_authinfo_password(newsnntp * f, const char * password) | ||
600 | { | ||
601 | char command[NNTP_STRING_SIZE]; | ||
602 | int r; | ||
603 | char * response; | ||
604 | |||
605 | snprintf(command, NNTP_STRING_SIZE, "AUTHINFO PASS %s\r\n", password); | ||
606 | r = send_command(f, command); | ||
607 | if (r == -1) | ||
608 | return NEWSNNTP_ERROR_STREAM; | ||
609 | |||
610 | response = read_line(f); | ||
611 | if (response == NULL) | ||
612 | return NEWSNNTP_ERROR_STREAM; | ||
613 | |||
614 | r = parse_response(f, response); | ||
615 | |||
616 | switch (r) { | ||
617 | case 480: | ||
618 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
619 | |||
620 | case 482: | ||
621 | return NEWSNNTP_ERROR_AUTHENTICATION_REJECTED; | ||
622 | |||
623 | case 381: | ||
624 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
625 | |||
626 | case 281: | ||
627 | return NEWSNNTP_NO_ERROR; | ||
628 | |||
629 | default: | ||
630 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | /* ******************** LIST OVERVIEW.FMT ******************************** */ | ||
635 | |||
636 | static clist * read_headers_list(newsnntp * f); | ||
637 | |||
638 | static void headers_list_free(clist * l) | ||
639 | { | ||
640 | clist_foreach(l, (clist_func) free, NULL); | ||
641 | clist_free(l); | ||
642 | } | ||
643 | |||
644 | int newsnntp_list_overview_fmt(newsnntp * f, clist ** result) | ||
645 | { | ||
646 | char command[NNTP_STRING_SIZE]; | ||
647 | int r; | ||
648 | char * response; | ||
649 | |||
650 | snprintf(command, NNTP_STRING_SIZE, "LIST OVERVIEW.FMT\r\n"); | ||
651 | r = send_command(f, command); | ||
652 | if (r == -1) | ||
653 | return NEWSNNTP_ERROR_STREAM; | ||
654 | |||
655 | response = read_line(f); | ||
656 | if (response == NULL) | ||
657 | return NEWSNNTP_ERROR_STREAM; | ||
658 | |||
659 | r = parse_response(f, response); | ||
660 | |||
661 | switch (r) { | ||
662 | case 480: | ||
663 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
664 | |||
665 | case 381: | ||
666 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
667 | |||
668 | case 215: | ||
669 | * result = read_headers_list(f); | ||
670 | return NEWSNNTP_NO_ERROR; | ||
671 | |||
672 | case 503: | ||
673 | return NEWSNNTP_ERROR_PROGRAM_ERROR; | ||
674 | |||
675 | default: | ||
676 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
677 | } | ||
678 | } | ||
679 | |||
680 | void newsnntp_list_overview_fmt_free(clist * l) | ||
681 | { | ||
682 | headers_list_free(l); | ||
683 | } | ||
684 | |||
685 | |||
686 | |||
687 | |||
688 | |||
689 | |||
690 | /* ******************** LIST ACTIVE ******************************** */ | ||
691 | |||
692 | int newsnntp_list_active(newsnntp * f, const char * wildcard, clist ** result) | ||
693 | { | ||
694 | char command[NNTP_STRING_SIZE]; | ||
695 | int r; | ||
696 | char * response; | ||
697 | |||
698 | if (wildcard != NULL) | ||
699 | snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE %s\r\n", wildcard); | ||
700 | else | ||
701 | snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE\r\n"); | ||
702 | r = send_command(f, command); | ||
703 | if (r == -1) | ||
704 | return NEWSNNTP_ERROR_STREAM; | ||
705 | |||
706 | response = read_line(f); | ||
707 | if (response == NULL) | ||
708 | return NEWSNNTP_ERROR_STREAM; | ||
709 | |||
710 | r = parse_response(f, response); | ||
711 | |||
712 | switch (r) { | ||
713 | case 480: | ||
714 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
715 | |||
716 | case 381: | ||
717 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
718 | |||
719 | case 215: | ||
720 | * result = read_groups_list(f); | ||
721 | return NEWSNNTP_NO_ERROR; | ||
722 | |||
723 | default: | ||
724 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
725 | } | ||
726 | } | ||
727 | |||
728 | void newsnntp_list_active_free(clist * l) | ||
729 | { | ||
730 | group_info_list_free(l); | ||
731 | } | ||
732 | |||
733 | |||
734 | |||
735 | |||
736 | |||
737 | |||
738 | /* ******************** LIST ACTIVE.TIMES ******************************** */ | ||
739 | |||
740 | static struct newsnntp_group_time * | ||
741 | group_time_new(char * group_name, time_t date, char * email) | ||
742 | { | ||
743 | struct newsnntp_group_time * n; | ||
744 | |||
745 | n = malloc(sizeof(* n)); | ||
746 | |||
747 | if (n == NULL) | ||
748 | return NULL; | ||
749 | |||
750 | n->grp_name = strdup(group_name); | ||
751 | if (n->grp_name == NULL) { | ||
752 | free(n); | ||
753 | return NULL; | ||
754 | } | ||
755 | |||
756 | n->grp_email = strdup(email); | ||
757 | if (n->grp_email == NULL) { | ||
758 | free(n->grp_name); | ||
759 | free(n); | ||
760 | return NULL; | ||
761 | } | ||
762 | |||
763 | n->grp_date = date; | ||
764 | |||
765 | return n; | ||
766 | } | ||
767 | |||
768 | static void group_time_free(struct newsnntp_group_time * n) | ||
769 | { | ||
770 | if (n->grp_name) | ||
771 | free(n->grp_name); | ||
772 | if (n->grp_email) | ||
773 | free(n->grp_email); | ||
774 | free(n); | ||
775 | } | ||
776 | |||
777 | static void group_time_list_free(clist * l) | ||
778 | { | ||
779 | clist_foreach(l, (clist_func) group_time_free, NULL); | ||
780 | clist_free(l); | ||
781 | } | ||
782 | |||
783 | |||
784 | |||
785 | |||
786 | |||
787 | |||
788 | |||
789 | static clist * read_group_time_list(newsnntp * f); | ||
790 | |||
791 | |||
792 | int newsnntp_list_active_times(newsnntp * f, clist ** result) | ||
793 | { | ||
794 | char command[NNTP_STRING_SIZE]; | ||
795 | int r; | ||
796 | char * response; | ||
797 | |||
798 | snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE.TIMES\r\n"); | ||
799 | r = send_command(f, command); | ||
800 | if (r == -1) | ||
801 | return NEWSNNTP_ERROR_STREAM; | ||
802 | |||
803 | response = read_line(f); | ||
804 | if (response == NULL) | ||
805 | return NEWSNNTP_ERROR_STREAM; | ||
806 | |||
807 | r = parse_response(f, response); | ||
808 | |||
809 | switch (r) { | ||
810 | case 480: | ||
811 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
812 | |||
813 | case 381: | ||
814 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
815 | |||
816 | case 215: | ||
817 | * result = read_group_time_list(f); | ||
818 | return NEWSNNTP_NO_ERROR; | ||
819 | |||
820 | case 503: | ||
821 | return NEWSNNTP_ERROR_PROGRAM_ERROR; | ||
822 | |||
823 | default: | ||
824 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
825 | } | ||
826 | } | ||
827 | |||
828 | void newsnntp_list_active_times_free(clist * l) | ||
829 | { | ||
830 | group_time_list_free(l); | ||
831 | } | ||
832 | |||
833 | |||
834 | |||
835 | |||
836 | |||
837 | |||
838 | |||
839 | |||
840 | /* ********************** LIST DISTRIBUTION ***************************** */ | ||
841 | |||
842 | static struct newsnntp_distrib_value_meaning * | ||
843 | distrib_value_meaning_new(char * value, char * meaning) | ||
844 | { | ||
845 | struct newsnntp_distrib_value_meaning * n; | ||
846 | |||
847 | n = malloc(sizeof(* n)); | ||
848 | |||
849 | if (n == NULL) | ||
850 | return NULL; | ||
851 | |||
852 | n->dst_value = strdup(value); | ||
853 | if (n->dst_value == NULL) { | ||
854 | free(n); | ||
855 | return NULL; | ||
856 | } | ||
857 | |||
858 | n->dst_meaning = strdup(meaning); | ||
859 | if (n->dst_meaning == NULL) { | ||
860 | free(n->dst_value); | ||
861 | free(n); | ||
862 | return NULL; | ||
863 | } | ||
864 | |||
865 | return n; | ||
866 | } | ||
867 | |||
868 | |||
869 | static void | ||
870 | distrib_value_meaning_free(struct newsnntp_distrib_value_meaning * n) | ||
871 | { | ||
872 | if (n->dst_value) | ||
873 | free(n->dst_value); | ||
874 | if (n->dst_meaning) | ||
875 | free(n->dst_meaning); | ||
876 | free(n); | ||
877 | } | ||
878 | |||
879 | static void distrib_value_meaning_list_free(clist * l) | ||
880 | { | ||
881 | clist_foreach(l, (clist_func) distrib_value_meaning_free, NULL); | ||
882 | clist_free(l); | ||
883 | } | ||
884 | |||
885 | static clist * read_distrib_value_meaning_list(newsnntp * f); | ||
886 | |||
887 | |||
888 | int newsnntp_list_distribution(newsnntp * f, clist ** result) | ||
889 | { | ||
890 | char command[NNTP_STRING_SIZE]; | ||
891 | int r; | ||
892 | char * response; | ||
893 | |||
894 | snprintf(command, NNTP_STRING_SIZE, "LIST DISTRIBUTION\r\n"); | ||
895 | r = send_command(f, command); | ||
896 | if (r == -1) | ||
897 | return NEWSNNTP_ERROR_STREAM; | ||
898 | |||
899 | response = read_line(f); | ||
900 | if (response == NULL) | ||
901 | return NEWSNNTP_ERROR_STREAM; | ||
902 | |||
903 | r = parse_response(f, response); | ||
904 | |||
905 | switch (r) { | ||
906 | case 480: | ||
907 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
908 | |||
909 | case 381: | ||
910 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
911 | |||
912 | case 215: | ||
913 | * result = read_distrib_value_meaning_list(f); | ||
914 | return NEWSNNTP_NO_ERROR; | ||
915 | |||
916 | case 503: | ||
917 | return NEWSNNTP_ERROR_PROGRAM_ERROR; | ||
918 | |||
919 | default: | ||
920 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
921 | } | ||
922 | } | ||
923 | |||
924 | |||
925 | void newsnntp_list_distribution_free(clist * l) | ||
926 | { | ||
927 | distrib_value_meaning_list_free(l); | ||
928 | } | ||
929 | |||
930 | |||
931 | |||
932 | |||
933 | |||
934 | |||
935 | |||
936 | |||
937 | |||
938 | |||
939 | |||
940 | /* ********************** LIST DISTRIB.PATS ***************************** */ | ||
941 | |||
942 | static struct newsnntp_distrib_default_value * | ||
943 | distrib_default_value_new(uint32_t weight, char * group_pattern, char * value) | ||
944 | { | ||
945 | struct newsnntp_distrib_default_value * n; | ||
946 | |||
947 | n = malloc(sizeof(* n)); | ||
948 | if (n == NULL) | ||
949 | return NULL; | ||
950 | |||
951 | n->dst_group_pattern = strdup(group_pattern); | ||
952 | if (n->dst_group_pattern == NULL) { | ||
953 | free(n); | ||
954 | return NULL; | ||
955 | } | ||
956 | |||
957 | n->dst_value = strdup(value); | ||
958 | if (n->dst_value == NULL) { | ||
959 | free(n->dst_group_pattern); | ||
960 | free(n); | ||
961 | return NULL; | ||
962 | } | ||
963 | |||
964 | n->dst_weight = weight; | ||
965 | |||
966 | return n; | ||
967 | } | ||
968 | |||
969 | static void | ||
970 | distrib_default_value_free(struct newsnntp_distrib_default_value * n) | ||
971 | { | ||
972 | if (n->dst_group_pattern) | ||
973 | free(n->dst_group_pattern); | ||
974 | if (n->dst_value) | ||
975 | free(n->dst_value); | ||
976 | free(n); | ||
977 | } | ||
978 | |||
979 | static void distrib_default_value_list_free(clist * l) | ||
980 | { | ||
981 | clist_foreach(l, (clist_func) distrib_default_value_free, NULL); | ||
982 | clist_free(l); | ||
983 | } | ||
984 | |||
985 | static clist * read_distrib_default_value_list(newsnntp * f); | ||
986 | |||
987 | int newsnntp_list_distrib_pats(newsnntp * f, clist ** result) | ||
988 | { | ||
989 | char command[NNTP_STRING_SIZE]; | ||
990 | int r; | ||
991 | char * response; | ||
992 | |||
993 | snprintf(command, NNTP_STRING_SIZE, "LIST DISTRIB.PATS\r\n"); | ||
994 | r = send_command(f, command); | ||
995 | if (r == -1) | ||
996 | return NEWSNNTP_ERROR_STREAM; | ||
997 | |||
998 | response = read_line(f); | ||
999 | if (response == NULL) | ||
1000 | return NEWSNNTP_ERROR_STREAM; | ||
1001 | |||
1002 | r = parse_response(f, response); | ||
1003 | |||
1004 | switch (r) { | ||
1005 | case 480: | ||
1006 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
1007 | |||
1008 | case 381: | ||
1009 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
1010 | |||
1011 | case 215: | ||
1012 | * result = read_distrib_default_value_list(f); | ||
1013 | return NEWSNNTP_NO_ERROR; | ||
1014 | |||
1015 | case 503: | ||
1016 | return NEWSNNTP_ERROR_PROGRAM_ERROR; | ||
1017 | |||
1018 | default: | ||
1019 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | void newsnntp_list_distrib_pats_free(clist * l) | ||
1024 | { | ||
1025 | distrib_default_value_list_free(l); | ||
1026 | } | ||
1027 | |||
1028 | |||
1029 | |||
1030 | |||
1031 | |||
1032 | |||
1033 | |||
1034 | |||
1035 | |||
1036 | |||
1037 | |||
1038 | |||
1039 | /* ********************** LIST NEWSGROUPS ***************************** */ | ||
1040 | |||
1041 | static struct newsnntp_group_description * | ||
1042 | group_description_new(char * group_name, char * description) | ||
1043 | { | ||
1044 | struct newsnntp_group_description * n; | ||
1045 | |||
1046 | n = malloc(sizeof(* n)); | ||
1047 | if (n == NULL) | ||
1048 | return NULL; | ||
1049 | |||
1050 | n->grp_name = strdup(group_name); | ||
1051 | if (n->grp_name == NULL) { | ||
1052 | free(n); | ||
1053 | return NULL; | ||
1054 | } | ||
1055 | |||
1056 | n->grp_description = strdup(description); | ||
1057 | if (n->grp_description == NULL) { | ||
1058 | free(n->grp_name); | ||
1059 | free(n); | ||
1060 | return NULL; | ||
1061 | } | ||
1062 | |||
1063 | return n; | ||
1064 | } | ||
1065 | |||
1066 | static void group_description_free(struct newsnntp_group_description * n) | ||
1067 | { | ||
1068 | if (n->grp_name) | ||
1069 | free(n->grp_name); | ||
1070 | if (n->grp_description) | ||
1071 | free(n->grp_description); | ||
1072 | free(n); | ||
1073 | } | ||
1074 | |||
1075 | static void group_description_list_free(clist * l) | ||
1076 | { | ||
1077 | clist_foreach(l, (clist_func) group_description_free, NULL); | ||
1078 | clist_free(l); | ||
1079 | } | ||
1080 | |||
1081 | static clist * read_group_description_list(newsnntp * f); | ||
1082 | |||
1083 | int newsnntp_list_newsgroups(newsnntp * f, const char * pattern, | ||
1084 | clist ** result) | ||
1085 | { | ||
1086 | char command[NNTP_STRING_SIZE]; | ||
1087 | int r; | ||
1088 | char * response; | ||
1089 | |||
1090 | if (pattern) | ||
1091 | snprintf(command, NNTP_STRING_SIZE, "LIST NEWSGROUPS %s\r\n", pattern); | ||
1092 | else | ||
1093 | snprintf(command, NNTP_STRING_SIZE, "LIST NEWSGROUPS\r\n"); | ||
1094 | |||
1095 | r = send_command(f, command); | ||
1096 | if (r == -1) | ||
1097 | return NEWSNNTP_ERROR_STREAM; | ||
1098 | |||
1099 | response = read_line(f); | ||
1100 | if (response == NULL) | ||
1101 | return NEWSNNTP_ERROR_STREAM; | ||
1102 | |||
1103 | r = parse_response(f, response); | ||
1104 | |||
1105 | switch (r) { | ||
1106 | case 480: | ||
1107 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
1108 | |||
1109 | case 381: | ||
1110 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
1111 | |||
1112 | case 215: | ||
1113 | * result = read_group_description_list(f); | ||
1114 | return NEWSNNTP_NO_ERROR; | ||
1115 | |||
1116 | case 503: | ||
1117 | return NEWSNNTP_ERROR_PROGRAM_ERROR; | ||
1118 | |||
1119 | default: | ||
1120 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
1121 | } | ||
1122 | } | ||
1123 | |||
1124 | void newsnntp_list_newsgroups_free(clist * l) | ||
1125 | { | ||
1126 | group_description_list_free(l); | ||
1127 | } | ||
1128 | |||
1129 | |||
1130 | |||
1131 | |||
1132 | |||
1133 | |||
1134 | |||
1135 | |||
1136 | |||
1137 | |||
1138 | |||
1139 | |||
1140 | /* ******************** LIST SUBSCRIPTIONS ******************************** */ | ||
1141 | |||
1142 | static void subscriptions_list_free(clist * l) | ||
1143 | { | ||
1144 | clist_foreach(l, (clist_func) free, NULL); | ||
1145 | clist_free(l); | ||
1146 | } | ||
1147 | |||
1148 | static clist * read_subscriptions_list(newsnntp * f); | ||
1149 | |||
1150 | int newsnntp_list_subscriptions(newsnntp * f, clist ** result) | ||
1151 | { | ||
1152 | char command[NNTP_STRING_SIZE]; | ||
1153 | int r; | ||
1154 | char * response; | ||
1155 | |||
1156 | snprintf(command, NNTP_STRING_SIZE, "LIST SUBSCRIPTIONS\r\n"); | ||
1157 | r = send_command(f, command); | ||
1158 | if (r == -1) | ||
1159 | return NEWSNNTP_ERROR_STREAM; | ||
1160 | |||
1161 | response = read_line(f); | ||
1162 | if (response == NULL) | ||
1163 | return NEWSNNTP_ERROR_STREAM; | ||
1164 | |||
1165 | r = parse_response(f, response); | ||
1166 | |||
1167 | switch (r) { | ||
1168 | case 480: | ||
1169 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
1170 | |||
1171 | case 381: | ||
1172 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
1173 | |||
1174 | case 215: | ||
1175 | * result = read_subscriptions_list(f); | ||
1176 | return NEWSNNTP_NO_ERROR; | ||
1177 | |||
1178 | case 503: | ||
1179 | return NEWSNNTP_ERROR_PROGRAM_ERROR; | ||
1180 | |||
1181 | default: | ||
1182 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
1183 | } | ||
1184 | } | ||
1185 | |||
1186 | void newsnntp_list_subscriptions_free(clist * l) | ||
1187 | { | ||
1188 | subscriptions_list_free(l); | ||
1189 | } | ||
1190 | |||
1191 | |||
1192 | |||
1193 | |||
1194 | |||
1195 | |||
1196 | |||
1197 | |||
1198 | |||
1199 | |||
1200 | |||
1201 | |||
1202 | /* ******************** LISTGROUP ******************************** */ | ||
1203 | |||
1204 | static void articles_list_free(clist * l) | ||
1205 | { | ||
1206 | clist_foreach(l, (clist_func) free, NULL); | ||
1207 | clist_free(l); | ||
1208 | } | ||
1209 | |||
1210 | static clist * read_articles_list(newsnntp * f); | ||
1211 | |||
1212 | int newsnntp_listgroup(newsnntp * f, const char * group_name, | ||
1213 | clist ** result) | ||
1214 | { | ||
1215 | char command[NNTP_STRING_SIZE]; | ||
1216 | int r; | ||
1217 | char * response; | ||
1218 | |||
1219 | if (group_name) | ||
1220 | snprintf(command, NNTP_STRING_SIZE, "LISTGROUP %s\r\n", group_name); | ||
1221 | else | ||
1222 | snprintf(command, NNTP_STRING_SIZE, "LISTGROUP\r\n"); | ||
1223 | r = send_command(f, command); | ||
1224 | if (r == -1) | ||
1225 | return NEWSNNTP_ERROR_STREAM; | ||
1226 | |||
1227 | response = read_line(f); | ||
1228 | if (response == NULL) | ||
1229 | return NEWSNNTP_ERROR_STREAM; | ||
1230 | |||
1231 | r = parse_response(f, response); | ||
1232 | |||
1233 | switch (r) { | ||
1234 | case 480: | ||
1235 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
1236 | |||
1237 | case 381: | ||
1238 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
1239 | |||
1240 | case 211: | ||
1241 | * result = read_articles_list(f); | ||
1242 | return NEWSNNTP_NO_ERROR; | ||
1243 | |||
1244 | case 412: | ||
1245 | return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; | ||
1246 | |||
1247 | case 502: | ||
1248 | return NEWSNNTP_ERROR_NO_PERMISSION; | ||
1249 | |||
1250 | default: | ||
1251 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
1252 | } | ||
1253 | } | ||
1254 | |||
1255 | void newsnntp_listgroup_free(clist * l) | ||
1256 | { | ||
1257 | articles_list_free(l); | ||
1258 | } | ||
1259 | |||
1260 | |||
1261 | |||
1262 | |||
1263 | |||
1264 | |||
1265 | |||
1266 | /* ********************** MODE READER ***************************** */ | ||
1267 | |||
1268 | int newsnntp_mode_reader(newsnntp * f) | ||
1269 | { | ||
1270 | char command[NNTP_STRING_SIZE]; | ||
1271 | char * response; | ||
1272 | int r; | ||
1273 | |||
1274 | snprintf(command, NNTP_STRING_SIZE, "MODE READER\r\n"); | ||
1275 | |||
1276 | r = send_command(f, command); | ||
1277 | if (r == -1) | ||
1278 | return NEWSNNTP_ERROR_STREAM; | ||
1279 | |||
1280 | response = read_line(f); | ||
1281 | if (response == NULL) | ||
1282 | return NEWSNNTP_ERROR_STREAM; | ||
1283 | |||
1284 | r = parse_response(f, response); | ||
1285 | switch (r) { | ||
1286 | case 480: | ||
1287 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
1288 | |||
1289 | case 381: | ||
1290 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
1291 | |||
1292 | case 200: | ||
1293 | return NEWSNNTP_NO_ERROR; | ||
1294 | |||
1295 | default: | ||
1296 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
1297 | } | ||
1298 | } | ||
1299 | |||
1300 | /* ********************** DATE ***************************** */ | ||
1301 | |||
1302 | #define strfcpy(a,b,c) {if (c) {strncpy(a,b,c);a[c-1]=0;}} | ||
1303 | |||
1304 | int newsnntp_date(newsnntp * f, struct tm * tm) | ||
1305 | { | ||
1306 | char command[NNTP_STRING_SIZE]; | ||
1307 | int r; | ||
1308 | char * response; | ||
1309 | char year[5]; | ||
1310 | char month[3]; | ||
1311 | char day[3]; | ||
1312 | char hour[3]; | ||
1313 | char minute[3]; | ||
1314 | char second[3]; | ||
1315 | |||
1316 | snprintf(command, NNTP_STRING_SIZE, "DATE\r\n"); | ||
1317 | r = send_command(f, command); | ||
1318 | if (r == -1) | ||
1319 | return NEWSNNTP_ERROR_STREAM; | ||
1320 | |||
1321 | response = read_line(f); | ||
1322 | if (response == NULL) | ||
1323 | return NEWSNNTP_ERROR_STREAM; | ||
1324 | |||
1325 | r = parse_response(f, response); | ||
1326 | |||
1327 | switch (r) { | ||
1328 | case 111: | ||
1329 | strfcpy(year, f->nntp_response, 4); | ||
1330 | strfcpy(month, f->nntp_response + 4, 2); | ||
1331 | strfcpy(day, f->nntp_response + 6, 2); | ||
1332 | strfcpy(hour, f->nntp_response + 8, 2); | ||
1333 | strfcpy(minute, f->nntp_response + 10, 2); | ||
1334 | strfcpy(second, f->nntp_response + 12, 2); | ||
1335 | |||
1336 | tm->tm_year = atoi(year); | ||
1337 | tm->tm_mon = atoi(month); | ||
1338 | tm->tm_mday = atoi(day); | ||
1339 | tm->tm_hour = atoi(hour); | ||
1340 | tm->tm_min = atoi(minute); | ||
1341 | tm->tm_sec = atoi(second); | ||
1342 | |||
1343 | return NEWSNNTP_NO_ERROR; | ||
1344 | |||
1345 | default: | ||
1346 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
1347 | } | ||
1348 | } | ||
1349 | |||
1350 | |||
1351 | |||
1352 | |||
1353 | |||
1354 | |||
1355 | |||
1356 | |||
1357 | |||
1358 | /* ********************** XHDR ***************************** */ | ||
1359 | |||
1360 | static struct newsnntp_xhdr_resp_item * xhdr_resp_item_new(uint32_t article, | ||
1361 | char * value) | ||
1362 | { | ||
1363 | struct newsnntp_xhdr_resp_item * n; | ||
1364 | |||
1365 | n = malloc(sizeof(* n)); | ||
1366 | if (n == NULL) | ||
1367 | return NULL; | ||
1368 | |||
1369 | n->hdr_value = strdup(value); | ||
1370 | if (n->hdr_value == NULL) { | ||
1371 | free(n); | ||
1372 | return NULL; | ||
1373 | } | ||
1374 | |||
1375 | n->hdr_article = article; | ||
1376 | |||
1377 | return n; | ||
1378 | } | ||
1379 | |||
1380 | static void xhdr_resp_item_free(struct newsnntp_xhdr_resp_item * n) | ||
1381 | { | ||
1382 | if (n->hdr_value) | ||
1383 | free(n->hdr_value); | ||
1384 | free(n); | ||
1385 | } | ||
1386 | |||
1387 | static void xhdr_resp_list_free(clist * l) | ||
1388 | { | ||
1389 | clist_foreach(l, (clist_func) xhdr_resp_item_free, NULL); | ||
1390 | clist_free(l); | ||
1391 | } | ||
1392 | |||
1393 | static clist * read_xhdr_resp_list(newsnntp * f); | ||
1394 | |||
1395 | static int newsnntp_xhdr_resp(newsnntp * f, clist ** result); | ||
1396 | |||
1397 | int newsnntp_xhdr_single(newsnntp * f, const char * header, uint32_t article, | ||
1398 | clist ** result) | ||
1399 | { | ||
1400 | char command[NNTP_STRING_SIZE]; | ||
1401 | int r; | ||
1402 | |||
1403 | snprintf(command, NNTP_STRING_SIZE, "XHDR %s %i\r\n", header, article); | ||
1404 | r = send_command(f, command); | ||
1405 | if (r == -1) | ||
1406 | return NEWSNNTP_ERROR_STREAM; | ||
1407 | |||
1408 | return newsnntp_xhdr_resp(f, result); | ||
1409 | } | ||
1410 | |||
1411 | int newsnntp_xhdr_range(newsnntp * f, const char * header, | ||
1412 | uint32_t rangeinf, uint32_t rangesup, | ||
1413 | clist ** result) | ||
1414 | { | ||
1415 | char command[NNTP_STRING_SIZE]; | ||
1416 | int r; | ||
1417 | |||
1418 | snprintf(command, NNTP_STRING_SIZE, "XHDR %s %i-%i\r\n", header, | ||
1419 | rangeinf, rangesup); | ||
1420 | r = send_command(f, command); | ||
1421 | if (r == -1) | ||
1422 | return NEWSNNTP_ERROR_STREAM; | ||
1423 | |||
1424 | return newsnntp_xhdr_resp(f, result); | ||
1425 | } | ||
1426 | |||
1427 | void newsnntp_xhdr_free(clist * l) | ||
1428 | { | ||
1429 | xhdr_resp_list_free(l); | ||
1430 | } | ||
1431 | |||
1432 | static int newsnntp_xhdr_resp(newsnntp * f, clist ** result) | ||
1433 | { | ||
1434 | int r; | ||
1435 | char * response; | ||
1436 | |||
1437 | response = read_line(f); | ||
1438 | if (response == NULL) | ||
1439 | return NEWSNNTP_ERROR_STREAM; | ||
1440 | |||
1441 | r = parse_response(f, response); | ||
1442 | |||
1443 | switch (r) { | ||
1444 | case 480: | ||
1445 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
1446 | |||
1447 | case 381: | ||
1448 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
1449 | |||
1450 | case 221: | ||
1451 | * result = read_xhdr_resp_list(f); | ||
1452 | return NEWSNNTP_NO_ERROR; | ||
1453 | |||
1454 | case 412: | ||
1455 | return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; | ||
1456 | |||
1457 | case 420: | ||
1458 | return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; | ||
1459 | |||
1460 | case 430: | ||
1461 | return NEWSNNTP_ERROR_ARTICLE_NOT_FOUND; | ||
1462 | |||
1463 | case 502: | ||
1464 | return NEWSNNTP_ERROR_NO_PERMISSION; | ||
1465 | |||
1466 | default: | ||
1467 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
1468 | } | ||
1469 | } | ||
1470 | |||
1471 | |||
1472 | |||
1473 | |||
1474 | |||
1475 | |||
1476 | |||
1477 | |||
1478 | |||
1479 | |||
1480 | |||
1481 | |||
1482 | |||
1483 | |||
1484 | /* ********************** XOVER ***************************** */ | ||
1485 | |||
1486 | static struct newsnntp_xover_resp_item * | ||
1487 | xover_resp_item_new(uint32_t article, | ||
1488 | char * subject, | ||
1489 | char * author, | ||
1490 | char * date, | ||
1491 | char * message_id, | ||
1492 | char * references, | ||
1493 | size_t size, | ||
1494 | uint32_t line_count, | ||
1495 | clist * others) | ||
1496 | { | ||
1497 | struct newsnntp_xover_resp_item * n; | ||
1498 | |||
1499 | n = malloc(sizeof(* n)); | ||
1500 | if (n == NULL) | ||
1501 | return NULL; | ||
1502 | |||
1503 | n->ovr_subject = strdup(subject); | ||
1504 | if (n->ovr_subject == NULL) { | ||
1505 | free(n); | ||
1506 | return NULL; | ||
1507 | } | ||
1508 | |||
1509 | n->ovr_author = strdup(author); | ||
1510 | if (n->ovr_author == NULL) { | ||
1511 | free(n->ovr_subject); | ||
1512 | free(n); | ||
1513 | return NULL; | ||
1514 | } | ||
1515 | |||
1516 | n->ovr_date = strdup(date); | ||
1517 | if (n->ovr_date == NULL) { | ||
1518 | free(n->ovr_subject); | ||
1519 | free(n->ovr_author); | ||
1520 | free(n); | ||
1521 | return NULL; | ||
1522 | } | ||
1523 | |||
1524 | n->ovr_message_id = strdup(message_id); | ||
1525 | if (n->ovr_message_id == NULL) { | ||
1526 | free(n->ovr_subject); | ||
1527 | free(n->ovr_author); | ||
1528 | free(n->ovr_date); | ||
1529 | free(n); | ||
1530 | return NULL; | ||
1531 | } | ||
1532 | |||
1533 | n->ovr_references = strdup(references); | ||
1534 | if (n->ovr_references == NULL) { | ||
1535 | free(n->ovr_subject); | ||
1536 | free(n->ovr_author); | ||
1537 | free(n->ovr_date); | ||
1538 | free(n->ovr_message_id); | ||
1539 | free(n); | ||
1540 | return NULL; | ||
1541 | } | ||
1542 | |||
1543 | n->ovr_article = article; | ||
1544 | n->ovr_size = size; | ||
1545 | n->ovr_line_count = line_count; | ||
1546 | n->ovr_others = others; | ||
1547 | |||
1548 | return n; | ||
1549 | } | ||
1550 | |||
1551 | void xover_resp_item_free(struct newsnntp_xover_resp_item * n) | ||
1552 | { | ||
1553 | if (n->ovr_subject) | ||
1554 | free(n->ovr_subject); | ||
1555 | if (n->ovr_author) | ||
1556 | free(n->ovr_author); | ||
1557 | if (n->ovr_date) | ||
1558 | free(n->ovr_date); | ||
1559 | if (n->ovr_message_id) | ||
1560 | free(n->ovr_message_id); | ||
1561 | if (n->ovr_references) | ||
1562 | free(n->ovr_references); | ||
1563 | clist_foreach(n->ovr_others, (clist_func) free, NULL); | ||
1564 | clist_free(n->ovr_others); | ||
1565 | |||
1566 | free(n); | ||
1567 | } | ||
1568 | |||
1569 | void newsnntp_xover_resp_list_free(clist * l) | ||
1570 | { | ||
1571 | clist_foreach(l, (clist_func) xover_resp_item_free, NULL); | ||
1572 | clist_free(l); | ||
1573 | } | ||
1574 | |||
1575 | static clist * read_xover_resp_list(newsnntp * f); | ||
1576 | |||
1577 | |||
1578 | static int newsnntp_xover_resp(newsnntp * f, clist ** result); | ||
1579 | |||
1580 | int newsnntp_xover_single(newsnntp * f, uint32_t article, | ||
1581 | struct newsnntp_xover_resp_item ** result) | ||
1582 | { | ||
1583 | char command[NNTP_STRING_SIZE]; | ||
1584 | int r; | ||
1585 | clist * list; | ||
1586 | clistiter * cur; | ||
1587 | struct newsnntp_xover_resp_item * item; | ||
1588 | |||
1589 | snprintf(command, NNTP_STRING_SIZE, "XOVER %i\r\n", article); | ||
1590 | r = send_command(f, command); | ||
1591 | if (r == -1) | ||
1592 | return NEWSNNTP_ERROR_STREAM; | ||
1593 | |||
1594 | r = newsnntp_xover_resp(f, &list); | ||
1595 | if (r != NEWSNNTP_NO_ERROR) | ||
1596 | return r; | ||
1597 | |||
1598 | cur = clist_begin(list); | ||
1599 | item = clist_content(cur); | ||
1600 | clist_free(list); | ||
1601 | |||
1602 | * result = item; | ||
1603 | |||
1604 | return r; | ||
1605 | } | ||
1606 | |||
1607 | int newsnntp_xover_range(newsnntp * f, uint32_t rangeinf, uint32_t rangesup, | ||
1608 | clist ** result) | ||
1609 | { | ||
1610 | int r; | ||
1611 | char command[NNTP_STRING_SIZE]; | ||
1612 | |||
1613 | snprintf(command, NNTP_STRING_SIZE, "XOVER %i-%i\r\n", rangeinf, rangesup); | ||
1614 | r = send_command(f, command); | ||
1615 | if (r == -1) | ||
1616 | return NEWSNNTP_ERROR_STREAM; | ||
1617 | |||
1618 | return newsnntp_xover_resp(f, result); | ||
1619 | } | ||
1620 | |||
1621 | static int newsnntp_xover_resp(newsnntp * f, clist ** result) | ||
1622 | { | ||
1623 | int r; | ||
1624 | char * response; | ||
1625 | |||
1626 | response = read_line(f); | ||
1627 | if (response == NULL) | ||
1628 | return NEWSNNTP_ERROR_STREAM; | ||
1629 | |||
1630 | r = parse_response(f, response); | ||
1631 | |||
1632 | switch (r) { | ||
1633 | case 480: | ||
1634 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
1635 | |||
1636 | case 381: | ||
1637 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
1638 | |||
1639 | case 224: | ||
1640 | * result = read_xover_resp_list(f); | ||
1641 | return NEWSNNTP_NO_ERROR; | ||
1642 | |||
1643 | case 412: | ||
1644 | return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; | ||
1645 | |||
1646 | case 420: | ||
1647 | return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; | ||
1648 | |||
1649 | case 502: | ||
1650 | return NEWSNNTP_ERROR_NO_PERMISSION; | ||
1651 | |||
1652 | default: | ||
1653 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
1654 | } | ||
1655 | } | ||
1656 | |||
1657 | |||
1658 | |||
1659 | |||
1660 | |||
1661 | |||
1662 | |||
1663 | /* ********************** AUTHINFO GENERIC ***************************** */ | ||
1664 | |||
1665 | int newsnntp_authinfo_generic(newsnntp * f, const char * authentificator, | ||
1666 | const char * arguments) | ||
1667 | { | ||
1668 | char command[NNTP_STRING_SIZE]; | ||
1669 | int r; | ||
1670 | char * response; | ||
1671 | |||
1672 | snprintf(command, NNTP_STRING_SIZE, "AUTHINFO GENERIC %s %s\r\n", | ||
1673 | authentificator, arguments); | ||
1674 | r = send_command(f, command); | ||
1675 | if (r == -1) | ||
1676 | return NEWSNNTP_ERROR_STREAM; | ||
1677 | |||
1678 | response = read_line(f); | ||
1679 | if (response == NULL) | ||
1680 | return NEWSNNTP_ERROR_STREAM; | ||
1681 | |||
1682 | r = parse_response(f, response); | ||
1683 | |||
1684 | switch (r) { | ||
1685 | case 480: | ||
1686 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; | ||
1687 | |||
1688 | case 381: | ||
1689 | return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; | ||
1690 | |||
1691 | case 281: | ||
1692 | return NEWSNNTP_NO_ERROR; | ||
1693 | |||
1694 | case 500: | ||
1695 | return NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD; | ||
1696 | |||
1697 | case 501: | ||
1698 | return NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED; | ||
1699 | |||
1700 | case 502: | ||
1701 | return NEWSNNTP_ERROR_NO_PERMISSION; | ||
1702 | |||
1703 | case 503: | ||
1704 | return NEWSNNTP_ERROR_PROGRAM_ERROR; | ||
1705 | |||
1706 | default: | ||
1707 | return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; | ||
1708 | } | ||
1709 | } | ||
1710 | |||
1711 | |||
1712 | |||
1713 | |||
1714 | |||
1715 | |||
1716 | |||
1717 | |||
1718 | |||
1719 | |||
1720 | |||
1721 | |||
1722 | |||
1723 | |||
1724 | |||
1725 | |||
1726 | |||
1727 | |||
1728 | |||
1729 | static int parse_space(char ** line) | ||
1730 | { | ||
1731 | char * p; | ||
1732 | |||
1733 | p = * line; | ||
1734 | |||
1735 | while ((* p == ' ') || (* p == '\t')) | ||
1736 | p ++; | ||
1737 | |||
1738 | if (p != * line) { | ||
1739 | * line = p; | ||
1740 | return TRUE; | ||
1741 | } | ||
1742 | else | ||
1743 | return FALSE; | ||
1744 | } | ||
1745 | |||
1746 | static char * cut_token(char * line) | ||
1747 | { | ||
1748 | char * p; | ||
1749 | char * p_tab; | ||
1750 | char * p_space; | ||
1751 | |||
1752 | p = line; | ||
1753 | |||
1754 | p_space = strchr(line, ' '); | ||
1755 | p_tab = strchr(line, '\t'); | ||
1756 | if (p_tab == NULL) | ||
1757 | p = p_space; | ||
1758 | else if (p_space == NULL) | ||
1759 | p = p_tab; | ||
1760 | else { | ||
1761 | if (p_tab < p_space) | ||
1762 | p = p_tab; | ||
1763 | else | ||
1764 | p = p_space; | ||
1765 | } | ||
1766 | if (p == NULL) | ||
1767 | return NULL; | ||
1768 | * p = 0; | ||
1769 | p ++; | ||
1770 | |||
1771 | return p; | ||
1772 | } | ||
1773 | |||
1774 | static int parse_response(newsnntp * f, char * response) | ||
1775 | { | ||
1776 | int code; | ||
1777 | |||
1778 | code = strtol(response, &response, 10); | ||
1779 | |||
1780 | if (response == NULL) { | ||
1781 | f->nntp_response = NULL; | ||
1782 | return code; | ||
1783 | } | ||
1784 | |||
1785 | parse_space(&response); | ||
1786 | |||
1787 | if (mmap_string_assign(f->nntp_response_buffer, response) != NULL) | ||
1788 | f->nntp_response = f->nntp_response_buffer->str; | ||
1789 | else | ||
1790 | f->nntp_response = NULL; | ||
1791 | |||
1792 | return code; | ||
1793 | } | ||
1794 | |||
1795 | |||
1796 | static char * read_line(newsnntp * f) | ||
1797 | { | ||
1798 | return mailstream_read_line_remove_eol(f->nntp_stream, f->nntp_stream_buffer); | ||
1799 | } | ||
1800 | |||
1801 | static char * read_multiline(newsnntp * f, size_t size, | ||
1802 | MMAPString * multiline_buffer) | ||
1803 | { | ||
1804 | return mailstream_read_multiline(f->nntp_stream, size, | ||
1805 | f->nntp_stream_buffer, multiline_buffer, | ||
1806 | f->nntp_progr_rate, f->nntp_progr_fun); | ||
1807 | } | ||
1808 | |||
1809 | |||
1810 | |||
1811 | |||
1812 | |||
1813 | |||
1814 | |||
1815 | static int parse_group_info(char * response, | ||
1816 | struct newsnntp_group_info ** result) | ||
1817 | { | ||
1818 | char * line; | ||
1819 | uint32_t first; | ||
1820 | uint32_t last; | ||
1821 | uint32_t count; | ||
1822 | char * name; | ||
1823 | struct newsnntp_group_info * info; | ||
1824 | |||
1825 | line = response; | ||
1826 | |||
1827 | count = strtoul(line, &line, 10); | ||
1828 | if (!parse_space(&line)) | ||
1829 | return FALSE; | ||
1830 | |||
1831 | first = strtoul(line, &line, 10); | ||
1832 | if (!parse_space(&line)) | ||
1833 | return FALSE; | ||
1834 | |||
1835 | last = strtoul(line, &line, 10); | ||
1836 | if (!parse_space(&line)) | ||
1837 | return FALSE; | ||
1838 | |||
1839 | name = line; | ||
1840 | |||
1841 | info = group_info_init(name, first, last, count, FALSE); | ||
1842 | if (info == NULL) | ||
1843 | return FALSE; | ||
1844 | |||
1845 | * result = info; | ||
1846 | |||
1847 | return TRUE; | ||
1848 | } | ||
1849 | |||
1850 | |||
1851 | static clist * read_groups_list(newsnntp * f) | ||
1852 | { | ||
1853 | char * line; | ||
1854 | char * group_name; | ||
1855 | uint32_t first; | ||
1856 | uint32_t last; | ||
1857 | uint32_t count; | ||
1858 | int type; | ||
1859 | clist * groups_list; | ||
1860 | struct newsnntp_group_info * n; | ||
1861 | int r; | ||
1862 | |||
1863 | groups_list = clist_new(); | ||
1864 | if (groups_list == NULL) | ||
1865 | goto err; | ||
1866 | |||
1867 | while (1) { | ||
1868 | char * p; | ||
1869 | |||
1870 | line = read_line(f); | ||
1871 | if (line == NULL) | ||
1872 | goto free_list; | ||
1873 | |||
1874 | if (mailstream_is_end_multiline(line)) | ||
1875 | break; | ||
1876 | |||
1877 | p = cut_token(line); | ||
1878 | if (p == NULL) | ||
1879 | continue; | ||
1880 | |||
1881 | group_name = line; | ||
1882 | line = p; | ||
1883 | |||
1884 | last = strtol(line, &line, 10); | ||
1885 | if (!parse_space(&line)) | ||
1886 | continue; | ||
1887 | |||
1888 | first = strtol(line, &line, 10); | ||
1889 | if (!parse_space(&line)) | ||
1890 | continue; | ||
1891 | |||
1892 | count = last - first + 1; | ||
1893 | |||
1894 | type = * line; | ||
1895 | |||
1896 | n = group_info_init(group_name, first, last, count, type); | ||
1897 | if (n == NULL) | ||
1898 | goto free_list; | ||
1899 | |||
1900 | r = clist_append(groups_list, n); | ||
1901 | if (r < 0) { | ||
1902 | group_info_free(n); | ||
1903 | goto free_list; | ||
1904 | } | ||
1905 | } | ||
1906 | |||
1907 | return groups_list; | ||
1908 | |||
1909 | free_list: | ||
1910 | group_info_list_free(groups_list); | ||
1911 | err: | ||
1912 | return NULL; | ||
1913 | } | ||
1914 | |||
1915 | |||
1916 | static clist * read_headers_list(newsnntp * f) | ||
1917 | { | ||
1918 | char * line; | ||
1919 | clist * headers_list; | ||
1920 | char * header; | ||
1921 | int r; | ||
1922 | |||
1923 | headers_list = clist_new(); | ||
1924 | if (headers_list == NULL) | ||
1925 | goto err; | ||
1926 | |||
1927 | while (1) { | ||
1928 | line = read_line(f); | ||
1929 | |||
1930 | if (line == NULL) | ||
1931 | goto free_list; | ||
1932 | |||
1933 | if (mailstream_is_end_multiline(line)) | ||
1934 | break; | ||
1935 | |||
1936 | header = strdup(line); | ||
1937 | if (header == NULL) | ||
1938 | goto free_list; | ||
1939 | |||
1940 | r = clist_append(headers_list, header); | ||
1941 | if (r < 0) { | ||
1942 | free(header); | ||
1943 | goto free_list; | ||
1944 | } | ||
1945 | } | ||
1946 | |||
1947 | return headers_list; | ||
1948 | |||
1949 | free_list: | ||
1950 | headers_list_free(headers_list); | ||
1951 | err: | ||
1952 | return NULL; | ||
1953 | } | ||
1954 | |||
1955 | |||
1956 | |||
1957 | |||
1958 | static clist * read_group_time_list(newsnntp * f) | ||
1959 | { | ||
1960 | char * line; | ||
1961 | char * group_name; | ||
1962 | time_t date; | ||
1963 | char * email; | ||
1964 | clist * group_time_list; | ||
1965 | struct newsnntp_group_time * n; | ||
1966 | int r; | ||
1967 | |||
1968 | group_time_list = clist_new(); | ||
1969 | if (group_time_list == NULL) | ||
1970 | goto err; | ||
1971 | |||
1972 | while (1) { | ||
1973 | char * p; | ||
1974 | char * remaining; | ||
1975 | |||
1976 | line = read_line(f); | ||
1977 | |||
1978 | if (line == NULL) | ||
1979 | goto free_list; | ||
1980 | |||
1981 | if (mailstream_is_end_multiline(line)) | ||
1982 | break; | ||
1983 | |||
1984 | p = cut_token(line); | ||
1985 | if (p == NULL) | ||
1986 | continue; | ||
1987 | |||
1988 | date = strtoul(p, &remaining, 10); | ||
1989 | |||
1990 | p = remaining; | ||
1991 | parse_space(&p); | ||
1992 | |||
1993 | email = p; | ||
1994 | |||
1995 | group_name = line; | ||
1996 | |||
1997 | n = group_time_new(group_name, date, email); | ||
1998 | if (n == NULL) | ||
1999 | goto free_list; | ||
2000 | |||
2001 | r = clist_append(group_time_list, n); | ||
2002 | if (r < 0) { | ||
2003 | group_time_free(n); | ||
2004 | goto free_list; | ||
2005 | } | ||
2006 | } | ||
2007 | |||
2008 | return group_time_list; | ||
2009 | |||
2010 | free_list: | ||
2011 | group_time_list_free(group_time_list); | ||
2012 | err: | ||
2013 | return NULL; | ||
2014 | } | ||
2015 | |||
2016 | |||
2017 | |||
2018 | |||
2019 | static clist * read_distrib_value_meaning_list(newsnntp * f) | ||
2020 | { | ||
2021 | char * line; | ||
2022 | char * value; | ||
2023 | char * meaning; | ||
2024 | clist * distrib_value_meaning_list; | ||
2025 | struct newsnntp_distrib_value_meaning * n; | ||
2026 | int r; | ||
2027 | |||
2028 | distrib_value_meaning_list = clist_new(); | ||
2029 | if (distrib_value_meaning_list == NULL) | ||
2030 | goto err; | ||
2031 | |||
2032 | while (1) { | ||
2033 | char * p; | ||
2034 | |||
2035 | line = read_line(f); | ||
2036 | if (line == NULL) | ||
2037 | goto free_list; | ||
2038 | |||
2039 | if (mailstream_is_end_multiline(line)) | ||
2040 | break; | ||
2041 | |||
2042 | p = cut_token(line); | ||
2043 | if (p == NULL) | ||
2044 | continue; | ||
2045 | |||
2046 | meaning = p; | ||
2047 | |||
2048 | value = line; | ||
2049 | |||
2050 | n = distrib_value_meaning_new(value, meaning); | ||
2051 | if (n == NULL) | ||
2052 | goto free_list; | ||
2053 | |||
2054 | r = clist_append(distrib_value_meaning_list, n); | ||
2055 | if (r < 0) { | ||
2056 | distrib_value_meaning_free(n); | ||
2057 | goto free_list; | ||
2058 | } | ||
2059 | } | ||
2060 | |||
2061 | return distrib_value_meaning_list; | ||
2062 | |||
2063 | free_list: | ||
2064 | distrib_value_meaning_list_free(distrib_value_meaning_list); | ||
2065 | err: | ||
2066 | return NULL; | ||
2067 | } | ||
2068 | |||
2069 | |||
2070 | |||
2071 | |||
2072 | static clist * read_distrib_default_value_list(newsnntp * f) | ||
2073 | { | ||
2074 | char * line; | ||
2075 | uint32_t weight; | ||
2076 | char * group_pattern; | ||
2077 | char * meaning; | ||
2078 | clist * distrib_default_value_list; | ||
2079 | struct newsnntp_distrib_default_value * n; | ||
2080 | int r; | ||
2081 | |||
2082 | distrib_default_value_list = clist_new(); | ||
2083 | if (distrib_default_value_list == NULL) | ||
2084 | goto err; | ||
2085 | |||
2086 | while (1) { | ||
2087 | char * p; | ||
2088 | char * remaining; | ||
2089 | |||
2090 | line = read_line(f); | ||
2091 | if (line == NULL) | ||
2092 | goto free_list; | ||
2093 | |||
2094 | if (mailstream_is_end_multiline(line)) | ||
2095 | break; | ||
2096 | |||
2097 | p = line; | ||
2098 | |||
2099 | weight = strtoul(p, &remaining, 10); | ||
2100 | p = remaining; | ||
2101 | parse_space(&p); | ||
2102 | |||
2103 | p = cut_token(line); | ||
2104 | if (p == NULL) | ||
2105 | continue; | ||
2106 | |||
2107 | meaning = p; | ||
2108 | group_pattern = line; | ||
2109 | |||
2110 | n = distrib_default_value_new(weight, group_pattern, meaning); | ||
2111 | if (n == NULL) | ||
2112 | goto free_list; | ||
2113 | |||
2114 | r = clist_append(distrib_default_value_list, n); | ||
2115 | if (r < 0) { | ||
2116 | distrib_default_value_free(n); | ||
2117 | goto free_list; | ||
2118 | } | ||
2119 | } | ||
2120 | |||
2121 | return distrib_default_value_list; | ||
2122 | |||
2123 | free_list: | ||
2124 | distrib_default_value_list_free(distrib_default_value_list); | ||
2125 | err: | ||
2126 | return NULL; | ||
2127 | } | ||
2128 | |||
2129 | |||
2130 | |||
2131 | static clist * read_group_description_list(newsnntp * f) | ||
2132 | { | ||
2133 | char * line; | ||
2134 | char * group_name; | ||
2135 | char * description; | ||
2136 | clist * group_description_list; | ||
2137 | struct newsnntp_group_description * n; | ||
2138 | int r; | ||
2139 | |||
2140 | group_description_list = clist_new(); | ||
2141 | if (group_description_list == NULL) | ||
2142 | goto err; | ||
2143 | |||
2144 | while (1) { | ||
2145 | char * p; | ||
2146 | |||
2147 | line = read_line(f); | ||
2148 | if (line == NULL) | ||
2149 | goto free_list; | ||
2150 | |||
2151 | if (mailstream_is_end_multiline(line)) | ||
2152 | break; | ||
2153 | |||
2154 | p = cut_token(line); | ||
2155 | if (p == NULL) | ||
2156 | continue; | ||
2157 | |||
2158 | description = p; | ||
2159 | |||
2160 | group_name = line; | ||
2161 | |||
2162 | n = group_description_new(group_name, description); | ||
2163 | if (n == NULL) | ||
2164 | goto free_list; | ||
2165 | |||
2166 | r = clist_append(group_description_list, n); | ||
2167 | if (r < 0) { | ||
2168 | group_description_free(n); | ||
2169 | goto free_list; | ||
2170 | } | ||
2171 | } | ||
2172 | |||
2173 | return group_description_list; | ||
2174 | |||
2175 | free_list: | ||
2176 | group_description_list_free(group_description_list); | ||
2177 | err: | ||
2178 | return NULL; | ||
2179 | } | ||
2180 | |||
2181 | |||
2182 | |||
2183 | static clist * read_subscriptions_list(newsnntp * f) | ||
2184 | { | ||
2185 | char * line; | ||
2186 | clist * subscriptions_list; | ||
2187 | char * group_name; | ||
2188 | int r; | ||
2189 | |||
2190 | subscriptions_list = clist_new(); | ||
2191 | if (subscriptions_list == NULL) | ||
2192 | goto err; | ||
2193 | |||
2194 | while (1) { | ||
2195 | line = read_line(f); | ||
2196 | |||
2197 | if (line == NULL) | ||
2198 | goto free_list; | ||
2199 | |||
2200 | if (mailstream_is_end_multiline(line)) | ||
2201 | break; | ||
2202 | |||
2203 | group_name = strdup(line); | ||
2204 | if (group_name == NULL) | ||
2205 | goto free_list; | ||
2206 | |||
2207 | r = clist_append(subscriptions_list, group_name); | ||
2208 | if (r < 0) { | ||
2209 | free(group_name); | ||
2210 | goto free_list; | ||
2211 | } | ||
2212 | } | ||
2213 | |||
2214 | return subscriptions_list; | ||
2215 | |||
2216 | free_list: | ||
2217 | subscriptions_list_free(subscriptions_list); | ||
2218 | err: | ||
2219 | return NULL; | ||
2220 | } | ||
2221 | |||
2222 | |||
2223 | |||
2224 | static clist * read_articles_list(newsnntp * f) | ||
2225 | { | ||
2226 | char * line; | ||
2227 | clist * articles_list; | ||
2228 | uint32_t * article_num; | ||
2229 | int r; | ||
2230 | |||
2231 | articles_list = clist_new(); | ||
2232 | if (articles_list == NULL) | ||
2233 | goto err; | ||
2234 | |||
2235 | while (1) { | ||
2236 | line = read_line(f); | ||
2237 | if (line == NULL) | ||
2238 | goto free_list; | ||
2239 | |||
2240 | if (mailstream_is_end_multiline(line)) | ||
2241 | break; | ||
2242 | |||
2243 | article_num = malloc(sizeof(* article_num)); | ||
2244 | if (article_num == NULL) | ||
2245 | goto free_list; | ||
2246 | * article_num = atoi(line); | ||
2247 | |||
2248 | r = clist_append(articles_list, article_num); | ||
2249 | if (r < 0) { | ||
2250 | free(article_num); | ||
2251 | goto free_list; | ||
2252 | } | ||
2253 | } | ||
2254 | |||
2255 | return articles_list; | ||
2256 | |||
2257 | free_list: | ||
2258 | articles_list_free(articles_list); | ||
2259 | err: | ||
2260 | return NULL; | ||
2261 | } | ||
2262 | |||
2263 | static clist * read_xhdr_resp_list(newsnntp * f) | ||
2264 | { | ||
2265 | char * line; | ||
2266 | uint32_t article; | ||
2267 | char * value; | ||
2268 | clist * xhdr_resp_list; | ||
2269 | struct newsnntp_xhdr_resp_item * n; | ||
2270 | int r; | ||
2271 | |||
2272 | xhdr_resp_list = clist_new(); | ||
2273 | if (xhdr_resp_list == NULL) | ||
2274 | goto err; | ||
2275 | |||
2276 | while (1) { | ||
2277 | line = read_line(f); | ||
2278 | |||
2279 | if (line == NULL) | ||
2280 | goto free_list; | ||
2281 | |||
2282 | if (mailstream_is_end_multiline(line)) | ||
2283 | break; | ||
2284 | |||
2285 | article = strtoul(line, &line, 10); | ||
2286 | if (!parse_space(&line)) | ||
2287 | continue; | ||
2288 | |||
2289 | value = line; | ||
2290 | |||
2291 | n = xhdr_resp_item_new(article, value); | ||
2292 | if (n == NULL) | ||
2293 | goto free_list; | ||
2294 | |||
2295 | r = clist_append(xhdr_resp_list, n); | ||
2296 | if (r < 0) { | ||
2297 | xhdr_resp_item_free(n); | ||
2298 | goto free_list; | ||
2299 | } | ||
2300 | } | ||
2301 | |||
2302 | return xhdr_resp_list; | ||
2303 | |||
2304 | free_list: | ||
2305 | xhdr_resp_list_free(xhdr_resp_list); | ||
2306 | err: | ||
2307 | return NULL; | ||
2308 | } | ||
2309 | |||
2310 | |||
2311 | static clist * read_xover_resp_list(newsnntp * f) | ||
2312 | { | ||
2313 | char * line; | ||
2314 | clist * xover_resp_list; | ||
2315 | struct newsnntp_xover_resp_item * n; | ||
2316 | clist * values_list; | ||
2317 | clistiter * current; | ||
2318 | uint32_t article; | ||
2319 | char * subject; | ||
2320 | char * author; | ||
2321 | char * date; | ||
2322 | char * message_id; | ||
2323 | char * references; | ||
2324 | size_t size; | ||
2325 | uint32_t line_count; | ||
2326 | clist * others; | ||
2327 | int r; | ||
2328 | |||
2329 | xover_resp_list = clist_new(); | ||
2330 | if (xover_resp_list == NULL) | ||
2331 | goto err; | ||
2332 | |||
2333 | while (1) { | ||
2334 | char * p; | ||
2335 | |||
2336 | line = read_line(f); | ||
2337 | |||
2338 | if (line == NULL) | ||
2339 | goto free_list; | ||
2340 | |||
2341 | if (mailstream_is_end_multiline(line)) | ||
2342 | break; | ||
2343 | |||
2344 | /* parse the data separated with \t */ | ||
2345 | |||
2346 | values_list = clist_new(); | ||
2347 | if (values_list == NULL) | ||
2348 | goto free_list; | ||
2349 | |||
2350 | while ((p = strchr(line, '\t')) != NULL) { | ||
2351 | * p = 0; | ||
2352 | p ++; | ||
2353 | |||
2354 | r = clist_append(values_list, line); | ||
2355 | if (r < 0) | ||
2356 | goto free_values_list; | ||
2357 | line = p; | ||
2358 | } | ||
2359 | |||
2360 | r = clist_append(values_list, line); | ||
2361 | if (r < 0) | ||
2362 | goto free_values_list; | ||
2363 | |||
2364 | /* set the known data */ | ||
2365 | current = clist_begin(values_list); | ||
2366 | article = atoi((char *) clist_content(current)); | ||
2367 | |||
2368 | current = clist_next(current); | ||
2369 | if (current == NULL) { | ||
2370 | clist_free(values_list); | ||
2371 | continue; | ||
2372 | } | ||
2373 | subject = clist_content(current); | ||
2374 | |||
2375 | current = clist_next(current); | ||
2376 | if (current == NULL) { | ||
2377 | clist_free(values_list); | ||
2378 | continue; | ||
2379 | } | ||
2380 | author = clist_content(current); | ||
2381 | |||
2382 | current = clist_next(current); | ||
2383 | if (current == NULL) { | ||
2384 | clist_free(values_list); | ||
2385 | continue; | ||
2386 | } | ||
2387 | date = clist_content(current); | ||
2388 | |||
2389 | current = clist_next(current); | ||
2390 | if (current == NULL) { | ||
2391 | clist_free(values_list); | ||
2392 | continue; | ||
2393 | } | ||
2394 | message_id = clist_content(current); | ||
2395 | |||
2396 | current = clist_next(current); | ||
2397 | if (current == NULL) { | ||
2398 | clist_free(values_list); | ||
2399 | continue; | ||
2400 | } | ||
2401 | references = clist_content(current); | ||
2402 | |||
2403 | current = clist_next(current); | ||
2404 | if (current == NULL) { | ||
2405 | clist_free(values_list); | ||
2406 | continue; | ||
2407 | } | ||
2408 | size = atoi((char *) clist_content(current)); | ||
2409 | |||
2410 | current = clist_next(current); | ||
2411 | if (current == NULL) { | ||
2412 | clist_free(values_list); | ||
2413 | continue; | ||
2414 | } | ||
2415 | line_count = atoi((char *) clist_content(current)); | ||
2416 | |||
2417 | current = clist_next(current); | ||
2418 | |||
2419 | /* make a copy of the other data */ | ||
2420 | others = clist_new(); | ||
2421 | if (others == NULL) { | ||
2422 | goto free_values_list; | ||
2423 | } | ||
2424 | |||
2425 | while (current) { | ||
2426 | char * val; | ||
2427 | |||
2428 | val = strdup(clist_content(current)); | ||
2429 | if (val == NULL) { | ||
2430 | clist_foreach(others, (clist_func) free, NULL); | ||
2431 | clist_free(others); | ||
2432 | goto free_list; | ||
2433 | } | ||
2434 | |||
2435 | r = clist_append(others, val); | ||
2436 | if (r < 0) { | ||
2437 | goto free_list; | ||
2438 | } | ||
2439 | |||
2440 | current = clist_next(current); | ||
2441 | } | ||
2442 | |||
2443 | clist_free(values_list); | ||
2444 | |||
2445 | n = xover_resp_item_new(article, subject, author, date, message_id, | ||
2446 | references, size, line_count, others); | ||
2447 | if (n == NULL) { | ||
2448 | clist_foreach(others, (clist_func) free, NULL); | ||
2449 | clist_free(others); | ||
2450 | goto free_list; | ||
2451 | } | ||
2452 | |||
2453 | r = clist_append(xover_resp_list, n); | ||
2454 | if (r < 0) { | ||
2455 | xover_resp_item_free(n); | ||
2456 | goto free_list; | ||
2457 | } | ||
2458 | } | ||
2459 | |||
2460 | return xover_resp_list; | ||
2461 | |||
2462 | free_list: | ||
2463 | newsnntp_xover_resp_list_free(xover_resp_list); | ||
2464 | err: | ||
2465 | return NULL; | ||
2466 | |||
2467 | free_values_list: | ||
2468 | clist_foreach(values_list, (clist_func) free, NULL); | ||
2469 | clist_free(values_list); | ||
2470 | return NULL; | ||
2471 | } | ||
2472 | |||
2473 | static int send_command(newsnntp * f, char * command) | ||
2474 | { | ||
2475 | ssize_t r; | ||
2476 | |||
2477 | r = mailstream_write(f->nntp_stream, command, strlen(command)); | ||
2478 | if (r == -1) | ||
2479 | return -1; | ||
2480 | |||
2481 | r = mailstream_flush(f->nntp_stream); | ||
2482 | if (r == -1) | ||
2483 | return -1; | ||
2484 | |||
2485 | return 0; | ||
2486 | } | ||
diff --git a/libetpan/src/low-level/nntp/newsnntp.h b/libetpan/src/low-level/nntp/newsnntp.h new file mode 100644 index 0000000..dd65ee2 --- a/dev/null +++ b/libetpan/src/low-level/nntp/newsnntp.h | |||
@@ -0,0 +1,187 @@ | |||
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 NEWSNNTP_H | ||
37 | |||
38 | #define NEWSNNTP_H | ||
39 | |||
40 | #ifdef __cplusplus | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | #include <inttypes.h> | ||
45 | #include <sys/types.h> | ||
46 | #include <time.h> | ||
47 | |||
48 | #include <libetpan/clist.h> | ||
49 | #include <libetpan/mailstream.h> | ||
50 | #include <libetpan/newsnntp_socket.h> | ||
51 | #include <libetpan/newsnntp_ssl.h> | ||
52 | #include <libetpan/newsnntp_types.h> | ||
53 | |||
54 | |||
55 | newsnntp * newsnntp_new(size_t nntp_progr_rate, | ||
56 | progress_function * nntp_progr_fun); | ||
57 | void newsnntp_free(newsnntp * f); | ||
58 | |||
59 | int newsnntp_quit(newsnntp * f); | ||
60 | int newsnntp_connect(newsnntp * f, mailstream * s); | ||
61 | |||
62 | int newsnntp_head(newsnntp * f, uint32_t index, char ** result, | ||
63 | size_t * result_len); | ||
64 | int newsnntp_article(newsnntp * f, uint32_t index, char ** result, | ||
65 | size_t * result_len); | ||
66 | int newsnntp_body(newsnntp * f, uint32_t index, char ** result, | ||
67 | size_t * result_len); | ||
68 | |||
69 | void newsnntp_head_free(char * str); | ||
70 | void newsnntp_article_free(char * str); | ||
71 | void newsnntp_body_free(char * str); | ||
72 | |||
73 | int newsnntp_mode_reader(newsnntp * f); | ||
74 | |||
75 | int newsnntp_date(newsnntp * f, struct tm * tm); | ||
76 | |||
77 | int newsnntp_authinfo_generic(newsnntp * f, const char * authentificator, | ||
78 | const char * arguments); | ||
79 | |||
80 | int newsnntp_authinfo_username(newsnntp * f, const char * username); | ||
81 | int newsnntp_authinfo_password(newsnntp * f, const char * password); | ||
82 | |||
83 | int newsnntp_post(newsnntp * f, const char * message, size_t size); | ||
84 | |||
85 | |||
86 | |||
87 | |||
88 | |||
89 | |||
90 | /******************* requests ******************************/ | ||
91 | |||
92 | int newsnntp_group(newsnntp * f, const char * groupname, | ||
93 | struct newsnntp_group_info ** info); | ||
94 | void newsnntp_group_free(struct newsnntp_group_info * info); | ||
95 | |||
96 | /* | ||
97 | elements are struct newsnntp_group_info * | ||
98 | */ | ||
99 | |||
100 | int newsnntp_list(newsnntp * f, clist ** result); | ||
101 | void newsnntp_list_free(clist * l); | ||
102 | |||
103 | /* | ||
104 | elements are char * | ||
105 | */ | ||
106 | |||
107 | int newsnntp_list_overview_fmt(newsnntp * f, clist ** result); | ||
108 | void newsnntp_list_overview_fmt_free(clist * l); | ||
109 | |||
110 | /* | ||
111 | elements are struct newsnntp_group_info * | ||
112 | */ | ||
113 | |||
114 | int newsnntp_list_active(newsnntp * f, const char * wildcard, clist ** result); | ||
115 | void newsnntp_list_active_free(clist * l); | ||
116 | |||
117 | /* | ||
118 | elements are struct newsnntp_group_time * | ||
119 | */ | ||
120 | |||
121 | int newsnntp_list_active_times(newsnntp * f, clist ** result); | ||
122 | void newsnntp_list_active_times_free(clist * l); | ||
123 | |||
124 | /* | ||
125 | elements are struct newsnntp_distrib_value_meaning * | ||
126 | */ | ||
127 | |||
128 | int newsnntp_list_distribution(newsnntp * f, clist ** result); | ||
129 | void newsnntp_list_distribution_free(clist * l); | ||
130 | |||
131 | /* | ||
132 | elements are struct newsnntp_distrib_default_value * | ||
133 | */ | ||
134 | |||
135 | int newsnntp_list_distrib_pats(newsnntp * f, clist ** result); | ||
136 | void newsnntp_list_distrib_pats_free(clist * l); | ||
137 | |||
138 | /* | ||
139 | elements are struct newsnntp_group_description * | ||
140 | */ | ||
141 | |||
142 | int newsnntp_list_newsgroups(newsnntp * f, const char * pattern, | ||
143 | clist ** result); | ||
144 | void newsnntp_list_newsgroups_free(clist * l); | ||
145 | |||
146 | /* | ||
147 | elements are char * | ||
148 | */ | ||
149 | |||
150 | int newsnntp_list_subscriptions(newsnntp * f, clist ** result); | ||
151 | void newsnntp_list_subscriptions_free(clist * l); | ||
152 | |||
153 | /* | ||
154 | elements are uint32_t * | ||
155 | */ | ||
156 | |||
157 | int newsnntp_listgroup(newsnntp * f, const char * group_name, | ||
158 | clist ** result); | ||
159 | void newsnntp_listgroup_free(clist * l); | ||
160 | |||
161 | /* | ||
162 | elements are struct newsnntp_xhdr_resp_item * | ||
163 | */ | ||
164 | |||
165 | int newsnntp_xhdr_single(newsnntp * f, const char * header, uint32_t article, | ||
166 | clist ** result); | ||
167 | int newsnntp_xhdr_range(newsnntp * f, const char * header, | ||
168 | uint32_t rangeinf, uint32_t rangesup, | ||
169 | clist ** result); | ||
170 | void newsnntp_xhdr_free(clist * l); | ||
171 | |||
172 | /* | ||
173 | elements are struct newsnntp_xover_resp_item * | ||
174 | */ | ||
175 | |||
176 | int newsnntp_xover_single(newsnntp * f, uint32_t article, | ||
177 | struct newsnntp_xover_resp_item ** result); | ||
178 | int newsnntp_xover_range(newsnntp * f, uint32_t rangeinf, uint32_t rangesup, | ||
179 | clist ** result); | ||
180 | void xover_resp_item_free(struct newsnntp_xover_resp_item * n); | ||
181 | void newsnntp_xover_resp_list_free(clist * l); | ||
182 | |||
183 | #ifdef __cplusplus | ||
184 | } | ||
185 | #endif | ||
186 | |||
187 | #endif | ||
diff --git a/libetpan/src/low-level/nntp/newsnntp_socket.c b/libetpan/src/low-level/nntp/newsnntp_socket.c new file mode 100644 index 0000000..3fdd219 --- a/dev/null +++ b/libetpan/src/low-level/nntp/newsnntp_socket.c | |||
@@ -0,0 +1,74 @@ | |||
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 "newsnntp_socket.h" | ||
37 | |||
38 | #include "newsnntp.h" | ||
39 | |||
40 | #include "connect.h" | ||
41 | |||
42 | #include <netinet/in.h> | ||
43 | #include <unistd.h> | ||
44 | |||
45 | #define DEFAULT_NNTP_PORT 119 | ||
46 | #define SERVICE_NAME_NNTP "nntp" | ||
47 | #define SERVICE_TYPE_TCP "tcp" | ||
48 | |||
49 | int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port) | ||
50 | { | ||
51 | int s; | ||
52 | mailstream * stream; | ||
53 | |||
54 | if (port == 0) { | ||
55 | port = mail_get_service_port(SERVICE_NAME_NNTP, SERVICE_TYPE_TCP); | ||
56 | if (port == 0) | ||
57 | port = DEFAULT_NNTP_PORT; | ||
58 | port = ntohs(port); | ||
59 | } | ||
60 | |||
61 | /* Connection */ | ||
62 | |||
63 | s = mail_tcp_connect(server, port); | ||
64 | if (s == -1) | ||
65 | return NEWSNNTP_ERROR_CONNECTION_REFUSED; | ||
66 | |||
67 | stream = mailstream_socket_open(s); | ||
68 | if (stream == NULL) { | ||
69 | close(s); | ||
70 | return NEWSNNTP_ERROR_MEMORY; | ||
71 | } | ||
72 | |||
73 | return newsnntp_connect(f, stream); | ||
74 | } | ||
diff --git a/libetpan/src/low-level/nntp/newsnntp_socket.h b/libetpan/src/low-level/nntp/newsnntp_socket.h new file mode 100644 index 0000000..4a52f73 --- a/dev/null +++ b/libetpan/src/low-level/nntp/newsnntp_socket.h | |||
@@ -0,0 +1,55 @@ | |||
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 NEWSNNTP_SOCKET_H | ||
37 | |||
38 | #define NEWSNNTP_SOCKET_H | ||
39 | |||
40 | #ifdef __cplusplus | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | #include <sys/types.h> | ||
45 | #include <inttypes.h> | ||
46 | |||
47 | #include <libetpan/newsnntp_types.h> | ||
48 | |||
49 | int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port); | ||
50 | |||
51 | #ifdef __cplusplus | ||
52 | } | ||
53 | #endif | ||
54 | |||
55 | #endif | ||
diff --git a/libetpan/src/low-level/nntp/newsnntp_ssl.c b/libetpan/src/low-level/nntp/newsnntp_ssl.c new file mode 100644 index 0000000..d2e2c5f --- a/dev/null +++ b/libetpan/src/low-level/nntp/newsnntp_ssl.c | |||
@@ -0,0 +1,73 @@ | |||
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 "newsnntp_ssl.h" | ||
37 | |||
38 | #include "newsnntp.h" | ||
39 | |||
40 | #include "connect.h" | ||
41 | #include <netinet/in.h> | ||
42 | #include <unistd.h> | ||
43 | |||
44 | #define DEFAULT_NNTPS_PORT 563 | ||
45 | #define SERVICE_NAME_NNTPS "nntps" | ||
46 | #define SERVICE_TYPE_TCP "tcp" | ||
47 | |||
48 | int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port) | ||
49 | { | ||
50 | int s; | ||
51 | mailstream * stream; | ||
52 | |||
53 | if (port == 0) { | ||
54 | port = mail_get_service_port(SERVICE_NAME_NNTPS, SERVICE_TYPE_TCP); | ||
55 | if (port == 0) | ||
56 | port = DEFAULT_NNTPS_PORT; | ||
57 | port = ntohs(port); | ||
58 | } | ||
59 | |||
60 | /* Connection */ | ||
61 | |||
62 | s = mail_tcp_connect(server, port); | ||
63 | if (s == -1) | ||
64 | return NEWSNNTP_ERROR_CONNECTION_REFUSED; | ||
65 | |||
66 | stream = mailstream_ssl_open(s); | ||
67 | if (stream == NULL) { | ||
68 | close(s); | ||
69 | return NEWSNNTP_ERROR_CONNECTION_REFUSED; | ||
70 | } | ||
71 | |||
72 | return newsnntp_connect(f, stream); | ||
73 | } | ||
diff --git a/libetpan/src/low-level/nntp/newsnntp_ssl.h b/libetpan/src/low-level/nntp/newsnntp_ssl.h new file mode 100644 index 0000000..845484f --- a/dev/null +++ b/libetpan/src/low-level/nntp/newsnntp_ssl.h | |||
@@ -0,0 +1,55 @@ | |||
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 NEWSNNTP_SSL_H | ||
37 | |||
38 | #define NEWSNNTP_SSL_H | ||
39 | |||
40 | #ifdef __cplusplus | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | #include <sys/types.h> | ||
45 | #include <inttypes.h> | ||
46 | |||
47 | #include <libetpan/newsnntp_types.h> | ||
48 | |||
49 | int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port); | ||
50 | |||
51 | #ifdef __cplusplus | ||
52 | } | ||
53 | #endif | ||
54 | |||
55 | #endif | ||
diff --git a/libetpan/src/low-level/nntp/newsnntp_types.h b/libetpan/src/low-level/nntp/newsnntp_types.h new file mode 100644 index 0000000..821df46 --- a/dev/null +++ b/libetpan/src/low-level/nntp/newsnntp_types.h | |||
@@ -0,0 +1,144 @@ | |||
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 NEWSNNTP_TYPES_H | ||
37 | |||
38 | #define NEWSNNTP_TYPES_H | ||
39 | |||
40 | #ifdef __cplusplus | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | #include <inttypes.h> | ||
45 | #include <libetpan/clist.h> | ||
46 | |||
47 | #include <libetpan/mailstream.h> | ||
48 | #include <libetpan/mmapstring.h> | ||
49 | |||
50 | enum { | ||
51 | NEWSNNTP_NO_ERROR = 0, | ||
52 | NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME, | ||
53 | NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD, | ||
54 | NEWSNNTP_ERROR_STREAM, | ||
55 | NEWSNNTP_ERROR_UNEXPECTED, | ||
56 | NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED, | ||
57 | NEWSNNTP_ERROR_NO_ARTICLE_SELECTED, | ||
58 | NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER, | ||
59 | NEWSNNTP_ERROR_ARTICLE_NOT_FOUND, | ||
60 | NEWSNNTP_ERROR_UNEXPECTED_RESPONSE, | ||
61 | NEWSNNTP_ERROR_INVALID_RESPONSE, | ||
62 | NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP, | ||
63 | NEWSNNTP_ERROR_POSTING_NOT_ALLOWED, | ||
64 | NEWSNNTP_ERROR_POSTING_FAILED, | ||
65 | NEWSNNTP_ERROR_PROGRAM_ERROR, | ||
66 | NEWSNNTP_ERROR_NO_PERMISSION, | ||
67 | NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD, | ||
68 | NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED, | ||
69 | NEWSNNTP_ERROR_CONNECTION_REFUSED, | ||
70 | NEWSNNTP_ERROR_MEMORY, | ||
71 | NEWSNNTP_ERROR_AUTHENTICATION_REJECTED, | ||
72 | NEWSNNTP_ERROR_BAD_STATE, | ||
73 | }; | ||
74 | |||
75 | struct newsnntp | ||
76 | { | ||
77 | mailstream * nntp_stream; | ||
78 | |||
79 | int nntp_readonly; | ||
80 | |||
81 | uint32_t nntp_progr_rate; | ||
82 | progress_function * nntp_progr_fun; | ||
83 | |||
84 | MMAPString * nntp_stream_buffer; | ||
85 | MMAPString * nntp_response_buffer; | ||
86 | |||
87 | char * nntp_response; | ||
88 | }; | ||
89 | |||
90 | typedef struct newsnntp newsnntp; | ||
91 | |||
92 | struct newsnntp_group_info | ||
93 | { | ||
94 | char * grp_name; | ||
95 | uint32_t grp_first; | ||
96 | uint32_t grp_last; | ||
97 | uint32_t grp_count; | ||
98 | char grp_type; | ||
99 | }; | ||
100 | |||
101 | struct newsnntp_group_time { | ||
102 | char * grp_name; | ||
103 | uint32_t grp_date; | ||
104 | char * grp_email; | ||
105 | }; | ||
106 | |||
107 | struct newsnntp_distrib_value_meaning { | ||
108 | char * dst_value; | ||
109 | char * dst_meaning; | ||
110 | }; | ||
111 | |||
112 | struct newsnntp_distrib_default_value { | ||
113 | uint32_t dst_weight; | ||
114 | char * dst_group_pattern; | ||
115 | char * dst_value; | ||
116 | }; | ||
117 | |||
118 | struct newsnntp_group_description { | ||
119 | char * grp_name; | ||
120 | char * grp_description; | ||
121 | }; | ||
122 | |||
123 | struct newsnntp_xhdr_resp_item { | ||
124 | uint32_t hdr_article; | ||
125 | char * hdr_value; | ||
126 | }; | ||
127 | |||
128 | struct newsnntp_xover_resp_item { | ||
129 | uint32_t ovr_article; | ||
130 | char * ovr_subject; | ||
131 | char * ovr_author; | ||
132 | char * ovr_date; | ||
133 | char * ovr_message_id; | ||
134 | char * ovr_references; | ||
135 | size_t ovr_size; | ||
136 | uint32_t ovr_line_count; | ||
137 | clist * ovr_others; | ||
138 | }; | ||
139 | |||
140 | #ifdef __cplusplus | ||
141 | } | ||
142 | #endif | ||
143 | |||
144 | #endif | ||