summaryrefslogtreecommitdiffabout
path: root/libetpan/src/low-level/imf
Unidiff
Diffstat (limited to 'libetpan/src/low-level/imf') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/low-level/imf/TODO12
-rw-r--r--libetpan/src/low-level/imf/mailimf.c7585
-rw-r--r--libetpan/src/low-level/imf/mailimf.h347
-rw-r--r--libetpan/src/low-level/imf/mailimf_types.c868
-rw-r--r--libetpan/src/low-level/imf/mailimf_types.h793
-rw-r--r--libetpan/src/low-level/imf/mailimf_types_helper.c1636
-rw-r--r--libetpan/src/low-level/imf/mailimf_types_helper.h370
-rw-r--r--libetpan/src/low-level/imf/mailimf_write.c2021
-rw-r--r--libetpan/src/low-level/imf/mailimf_write.h134
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_file.c149
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_file.h169
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_generic.c2028
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_generic.h142
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_mem.c98
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_mem.h135
15 files changed, 16487 insertions, 0 deletions
diff --git a/libetpan/src/low-level/imf/TODO b/libetpan/src/low-level/imf/TODO
new file mode 100644
index 0000000..f36f55f
--- a/dev/null
+++ b/libetpan/src/low-level/imf/TODO
@@ -0,0 +1,12 @@
1- define a EP_parserstate_s
2- remove clist usage
3- add a errorcode to string function
4- error codes are EP_errornr_s
5- prefix everything with EP_
6- mailimf_dot_atom_text_free
7- mailimf_address_XX -> _new(void) _init(&addr, ...) _free(addr)
8- in fact that data structure should then also contain a
9 'dynamically' allocated flag
10
11- RFC 822 : test the examples
12- RFC 2822 : obsolete syntax
diff --git a/libetpan/src/low-level/imf/mailimf.c b/libetpan/src/low-level/imf/mailimf.c
new file mode 100644
index 0000000..333767a
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf.c
@@ -0,0 +1,7585 @@
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 "mailimf.h"
37
38/*
39 RFC 2822
40
41 RFC 2821 ...
42 A message-originating SMTP system SHOULD NOT send a message that
43 already contains a Return-path header. SMTP servers performing a
44 relay function MUST NOT inspect the message data, and especially not
45 to the extent needed to determine if Return-path headers are present.
46 SMTP servers making final delivery MAY remove Return-path headers
47 before adding their own.
48*/
49
50#include <ctype.h>
51#include "mmapstring.h"
52#include <stdlib.h>
53#include <string.h>
54
55#ifndef TRUE
56#define TRUE 1
57#endif
58
59#ifndef FALSE
60#define FALSE 0
61#endif
62
63
64
65
66
67
68
69static inline int is_dtext(char ch);
70
71static int mailimf_quoted_pair_parse(const char * message, size_t length,
72 size_t * index, char * result);
73
74static int mailimf_ccontent_parse(const char * message, size_t length,
75 size_t * index);
76
77static int
78mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
79 size_t * index);
80
81static inline int mailimf_comment_parse(const char * message, size_t length,
82 size_t * index);
83
84static int mailimf_qcontent_parse(const char * message, size_t length,
85 size_t * index, char * ch);
86
87static int mailimf_phrase_parse(const char * message, size_t length,
88 size_t * index, char ** result);
89
90static int mailimf_unstructured_parse(const char * message, size_t length,
91 size_t * index, char ** result);
92
93static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
94 size_t * index);
95
96static int mailimf_day_of_week_parse(const char * message, size_t length,
97 size_t * index, int * result);
98
99static int mailimf_day_name_parse(const char * message, size_t length,
100 size_t * index, int * result);
101
102static int mailimf_date_parse(const char * message, size_t length,
103 size_t * index,
104 int * pday, int * pmonth, int * pyear);
105
106static int mailimf_year_parse(const char * message, size_t length,
107 size_t * index, int * result);
108
109static int mailimf_month_parse(const char * message, size_t length,
110 size_t * index, int * result);
111
112static int mailimf_month_name_parse(const char * message, size_t length,
113 size_t * index, int * result);
114
115static int mailimf_day_parse(const char * message, size_t length,
116 size_t * index, int * result);
117
118static int mailimf_time_parse(const char * message, size_t length,
119 size_t * index,
120 int * phour, int * pmin,
121 int * psec,
122 int * zone);
123static int mailimf_time_of_day_parse(const char * message, size_t length,
124 size_t * index,
125 int * phour, int * pmin,
126 int * psec);
127
128static int mailimf_hour_parse(const char * message, size_t length,
129 size_t * index, int * result);
130
131static int mailimf_minute_parse(const char * message, size_t length,
132 size_t * index, int * result);
133
134static int mailimf_second_parse(const char * message, size_t length,
135 size_t * index, int * result);
136
137static int mailimf_zone_parse(const char * message, size_t length,
138 size_t * index, int * result);
139
140static int mailimf_name_addr_parse(const char * message, size_t length,
141 size_t * index,
142 char ** pdisplay_name,
143 char ** pangle_addr);
144
145static int mailimf_angle_addr_parse(const char * message, size_t length,
146 size_t * index, char ** result);
147
148static int mailimf_group_parse(const char * message, size_t length,
149 size_t * index,
150 struct mailimf_group ** result);
151
152static int mailimf_display_name_parse(const char * message, size_t length,
153 size_t * index, char ** result);
154
155static int mailimf_addr_spec_parse(const char * message, size_t length,
156 size_t * index,
157 char ** address);
158
159#if 0
160static int mailimf_local_part_parse(const char * message, size_t length,
161 size_t * index,
162 char ** result);
163
164static int mailimf_domain_parse(const char * message, size_t length,
165 size_t * index,
166 char ** result);
167#endif
168
169#if 0
170static int mailimf_domain_literal_parse(const char * message, size_t length,
171 size_t * index, char ** result);
172#endif
173
174#if 0
175static int mailimf_dcontent_parse(const char * message, size_t length,
176 size_t * index, char * result);
177#endif
178
179static int
180mailimf_orig_date_parse(const char * message, size_t length,
181 size_t * index, struct mailimf_orig_date ** result);
182
183static int
184mailimf_from_parse(const char * message, size_t length,
185 size_t * index, struct mailimf_from ** result);
186
187static int
188mailimf_sender_parse(const char * message, size_t length,
189 size_t * index, struct mailimf_sender ** result);
190
191static int
192mailimf_reply_to_parse(const char * message, size_t length,
193 size_t * index, struct mailimf_reply_to ** result);
194
195static int
196mailimf_to_parse(const char * message, size_t length,
197 size_t * index, struct mailimf_to ** result);
198
199static int
200mailimf_cc_parse(const char * message, size_t length,
201 size_t * index, struct mailimf_cc ** result);
202
203static int
204mailimf_bcc_parse(const char * message, size_t length,
205 size_t * index, struct mailimf_bcc ** result);
206
207static int mailimf_message_id_parse(const char * message, size_t length,
208 size_t * index,
209 struct mailimf_message_id ** result);
210
211static int
212mailimf_in_reply_to_parse(const char * message, size_t length,
213 size_t * index,
214 struct mailimf_in_reply_to ** result);
215
216#if 0
217static int mailimf_references_parse(const char * message, size_t length,
218 size_t * index,
219 struct mailimf_references **
220 result);
221#endif
222
223static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
224 size_t * index,
225 char ** result);
226
227#if 0
228static int mailimf_id_left_parse(const char * message, size_t length,
229 size_t * index, char ** result);
230
231static int mailimf_id_right_parse(const char * message, size_t length,
232 size_t * index, char ** result);
233#endif
234
235#if 0
236static int mailimf_no_fold_quote_parse(const char * message, size_t length,
237 size_t * index, char ** result);
238
239static int mailimf_no_fold_literal_parse(const char * message, size_t length,
240 size_t * index, char ** result);
241#endif
242
243static int mailimf_subject_parse(const char * message, size_t length,
244 size_t * index,
245 struct mailimf_subject ** result);
246
247static int mailimf_comments_parse(const char * message, size_t length,
248 size_t * index,
249 struct mailimf_comments ** result);
250
251static int mailimf_keywords_parse(const char * message, size_t length,
252 size_t * index,
253 struct mailimf_keywords ** result);
254
255static int
256mailimf_resent_date_parse(const char * message, size_t length,
257 size_t * index, struct mailimf_orig_date ** result);
258
259static int
260mailimf_resent_from_parse(const char * message, size_t length,
261 size_t * index, struct mailimf_from ** result);
262
263static int
264mailimf_resent_sender_parse(const char * message, size_t length,
265 size_t * index, struct mailimf_sender ** result);
266
267static int
268mailimf_resent_to_parse(const char * message, size_t length,
269 size_t * index, struct mailimf_to ** result);
270
271static int
272mailimf_resent_cc_parse(const char * message, size_t length,
273 size_t * index, struct mailimf_cc ** result);
274
275static int
276mailimf_resent_bcc_parse(const char * message, size_t length,
277 size_t * index, struct mailimf_bcc ** result);
278
279static int
280mailimf_resent_msg_id_parse(const char * message, size_t length,
281 size_t * index,
282 struct mailimf_message_id ** result);
283
284static int mailimf_return_parse(const char * message, size_t length,
285 size_t * index,
286 struct mailimf_return ** result);
287
288static int
289mailimf_path_parse(const char * message, size_t length,
290 size_t * index, struct mailimf_path ** result);
291
292static int
293mailimf_optional_field_parse(const char * message, size_t length,
294 size_t * index,
295 struct mailimf_optional_field ** result);
296
297static int mailimf_field_name_parse(const char * message, size_t length,
298 size_t * index, char ** result);
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324/* *************************************************************** */
325
326static inline int is_digit(char ch)
327{
328 return (ch >= '0') && (ch <= '9');
329}
330
331static int mailimf_digit_parse(const char * message, size_t length,
332 size_t * index, int * result)
333{
334 size_t cur_token;
335
336 cur_token = * index;
337
338 if (cur_token >= length)
339 return MAILIMF_ERROR_PARSE;
340
341 if (is_digit(message[cur_token])) {
342 * result = message[cur_token] - '0';
343 cur_token ++;
344 * index = cur_token;
345 return MAILIMF_NO_ERROR;
346 }
347 else
348 return MAILIMF_ERROR_PARSE;
349}
350
351int
352mailimf_number_parse(const char * message, size_t length,
353 size_t * index, uint32_t * result)
354{
355 size_t cur_token;
356 int digit;
357 uint32_t number;
358 int parsed;
359 int r;
360
361 cur_token = * index;
362 parsed = FALSE;
363
364 number = 0;
365 while (1) {
366 r = mailimf_digit_parse(message, length, &cur_token, &digit);
367 if (r != MAILIMF_NO_ERROR) {
368 if (r == MAILIMF_ERROR_PARSE)
369 break;
370 else
371 return r;
372 }
373 number *= 10;
374 number += digit;
375 parsed = TRUE;
376 }
377
378 if (!parsed)
379 return MAILIMF_ERROR_PARSE;
380
381 * result = number;
382 * index = cur_token;
383
384 return MAILIMF_NO_ERROR;
385}
386
387int mailimf_char_parse(const char * message, size_t length,
388 size_t * index, char token)
389{
390 size_t cur_token;
391
392 cur_token = * index;
393
394 if (cur_token >= length)
395 return MAILIMF_ERROR_PARSE;
396
397 if (message[cur_token] == token) {
398 cur_token ++;
399 * index = cur_token;
400 return MAILIMF_NO_ERROR;
401 }
402 else
403 return MAILIMF_ERROR_PARSE;
404}
405
406int mailimf_unstrict_char_parse(const char * message, size_t length,
407 size_t * index, char token)
408{
409 size_t cur_token;
410 int r;
411
412 cur_token = * index;
413
414 r = mailimf_cfws_parse(message, length, &cur_token);
415 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
416 return r;
417
418 r = mailimf_char_parse(message, length, &cur_token, token);
419 if (r != MAILIMF_NO_ERROR)
420 return r;
421
422 * index = cur_token;
423
424 return MAILIMF_NO_ERROR;
425}
426
427int
428mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
429 size_t * index, char * token,
430 size_t token_length)
431{
432 size_t cur_token;
433
434 cur_token = * index;
435
436 if (cur_token + token_length - 1 >= length)
437 return MAILIMF_ERROR_PARSE;
438
439 if (strncasecmp(message + cur_token, token, token_length) == 0) {
440 cur_token += token_length;
441 * index = cur_token;
442 return MAILIMF_NO_ERROR;
443 }
444 else
445 return MAILIMF_ERROR_PARSE;
446}
447
448static int mailimf_oparenth_parse(const char * message, size_t length,
449 size_t * index)
450{
451 return mailimf_char_parse(message, length, index, '(');
452}
453
454static int mailimf_cparenth_parse(const char * message, size_t length,
455 size_t * index)
456{
457 return mailimf_char_parse(message, length, index, ')');
458}
459
460static int mailimf_comma_parse(const char * message, size_t length,
461 size_t * index)
462{
463 return mailimf_unstrict_char_parse(message, length, index, ',');
464}
465
466static int mailimf_dquote_parse(const char * message, size_t length,
467 size_t * index)
468{
469 return mailimf_char_parse(message, length, index, '\"');
470}
471
472static int mailimf_colon_parse(const char * message, size_t length,
473 size_t * index)
474{
475 return mailimf_unstrict_char_parse(message, length, index, ':');
476}
477
478static int mailimf_semi_colon_parse(const char * message, size_t length,
479 size_t * index)
480{
481 return mailimf_unstrict_char_parse(message, length, index, ';');
482}
483
484static int mailimf_plus_parse(const char * message, size_t length,
485 size_t * index)
486{
487 return mailimf_unstrict_char_parse(message, length, index, '+');
488}
489
490static int mailimf_minus_parse(const char * message, size_t length,
491 size_t * index)
492{
493 return mailimf_unstrict_char_parse(message, length, index, '-');
494}
495
496static int mailimf_lower_parse(const char * message, size_t length,
497 size_t * index)
498{
499 return mailimf_unstrict_char_parse(message, length, index, '<');
500}
501
502static int mailimf_greater_parse(const char * message, size_t length,
503 size_t * index)
504{
505 return mailimf_unstrict_char_parse(message, length, index, '>');
506}
507
508#if 0
509static int mailimf_obracket_parse(const char * message, size_t length,
510 size_t * index)
511{
512 return mailimf_unstrict_char_parse(message, length, index, '[');
513}
514
515static int mailimf_cbracket_parse(const char * message, size_t length,
516 size_t * index)
517{
518 return mailimf_unstrict_char_parse(message, length, index, ']');
519}
520#endif
521
522static int mailimf_at_sign_parse(const char * message, size_t length,
523 size_t * index)
524{
525 return mailimf_unstrict_char_parse(message, length, index, '@');
526}
527
528static int mailimf_point_parse(const char * message, size_t length,
529 size_t * index)
530{
531 return mailimf_unstrict_char_parse(message, length, index, '.');
532}
533
534int
535mailimf_custom_string_parse(const char * message, size_t length,
536 size_t * index, char ** result,
537 int (* is_custom_char)(char))
538{
539 size_t begin;
540 size_t end;
541 char * gstr;
542
543 begin = * index;
544
545 end = begin;
546
547 if (end >= length)
548 return MAILIMF_ERROR_PARSE;
549
550 while (is_custom_char(message[end])) {
551 end ++;
552 if (end >= length)
553 break;
554 }
555
556 if (end != begin) {
557 /*
558 gstr = strndup(message + begin, end - begin);
559 */
560 gstr = malloc(end - begin + 1);
561 if (gstr == NULL)
562 return MAILIMF_ERROR_MEMORY;
563 strncpy(gstr, message + begin, end - begin);
564 gstr[end - begin] = '\0';
565
566 * index = end;
567 * result = gstr;
568 return MAILIMF_NO_ERROR;
569 }
570 else
571 return MAILIMF_ERROR_PARSE;
572}
573
574
575
576
577
578
579
580typedef int mailimf_struct_parser(const char * message, size_t length,
581 size_t * index, void * result);
582
583typedef int mailimf_struct_destructor(void * result);
584
585
586static int
587mailimf_struct_multiple_parse(const char * message, size_t length,
588 size_t * index, clist ** result,
589 mailimf_struct_parser * parser,
590 mailimf_struct_destructor * destructor)
591{
592 clist * struct_list;
593 size_t cur_token;
594 void * value;
595 int r;
596 int res;
597
598 cur_token = * index;
599
600 r = parser(message, length, &cur_token, &value);
601 if (r != MAILIMF_NO_ERROR) {
602 res = r;
603 goto err;
604 }
605
606 struct_list = clist_new();
607 if (struct_list == NULL) {
608 destructor(value);
609 res = MAILIMF_ERROR_MEMORY;
610 goto err;
611 }
612
613 r = clist_append(struct_list, value);
614 if (r < 0) {
615 destructor(value);
616 res = MAILIMF_ERROR_MEMORY;
617 goto free;
618 }
619
620 while (1) {
621 r = parser(message, length, &cur_token, &value);
622 if (r != MAILIMF_NO_ERROR) {
623 if (r == MAILIMF_ERROR_PARSE)
624 break;
625 else {
626 res = r;
627 goto free;
628 }
629 }
630 r = clist_append(struct_list, value);
631 if (r < 0) {
632 (* destructor)(value);
633 res = MAILIMF_ERROR_MEMORY;
634 goto free;
635 }
636 }
637
638 * result = struct_list;
639 * index = cur_token;
640
641 return MAILIMF_NO_ERROR;
642
643 free:
644 clist_foreach(struct_list, (clist_func) destructor, NULL);
645 clist_free(struct_list);
646 err:
647 return res;
648}
649
650
651
652static int
653mailimf_struct_list_parse(const char * message, size_t length,
654 size_t * index, clist ** result,
655 char symbol,
656 mailimf_struct_parser * parser,
657 mailimf_struct_destructor * destructor)
658{
659 clist * struct_list;
660 size_t cur_token;
661 void * value;
662 size_t final_token;
663 int r;
664 int res;
665
666 cur_token = * index;
667
668 r = parser(message, length, &cur_token, &value);
669 if (r != MAILIMF_NO_ERROR) {
670 res = r;
671 goto err;
672 }
673
674 struct_list = clist_new();
675 if (struct_list == NULL) {
676 destructor(value);
677 res = MAILIMF_ERROR_MEMORY;
678 goto err;
679 }
680
681 r = clist_append(struct_list, value);
682 if (r < 0) {
683 destructor(value);
684 res = MAILIMF_ERROR_MEMORY;
685 goto free;
686 }
687
688 final_token = cur_token;
689
690 while (1) {
691 r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol);
692 if (r != MAILIMF_NO_ERROR) {
693 if (r == MAILIMF_ERROR_PARSE)
694 break;
695 else {
696 res = r;
697 goto free;
698 }
699 }
700
701 r = parser(message, length, &cur_token, &value);
702 if (r != MAILIMF_NO_ERROR) {
703 if (r == MAILIMF_ERROR_PARSE)
704 break;
705 else {
706 res = r;
707 goto free;
708 }
709 }
710
711 r = clist_append(struct_list, value);
712 if (r < 0) {
713 destructor(value);
714 res = MAILIMF_ERROR_MEMORY;
715 goto free;
716 }
717
718 final_token = cur_token;
719 }
720
721 * result = struct_list;
722 * index = final_token;
723
724 return MAILIMF_NO_ERROR;
725
726 free:
727 clist_foreach(struct_list, (clist_func) destructor, NULL);
728 clist_free(struct_list);
729 err:
730 return res;
731}
732
733static inline int mailimf_wsp_parse(const char * message, size_t length,
734 size_t * index)
735{
736 size_t cur_token;
737
738 cur_token = * index;
739
740 if (cur_token >= length)
741 return MAILIMF_ERROR_PARSE;
742
743 if ((message[cur_token] != ' ') && (message[cur_token] != '\t'))
744 return MAILIMF_ERROR_PARSE;
745
746 cur_token ++;
747 * index = cur_token;
748
749 return MAILIMF_NO_ERROR;
750}
751
752
753int mailimf_crlf_parse(const char * message, size_t length, size_t * index)
754{
755 size_t cur_token;
756 int r;
757
758 cur_token = * index;
759
760 r = mailimf_char_parse(message, length, &cur_token, '\r');
761 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
762 return r;
763
764 r = mailimf_char_parse(message, length, &cur_token, '\n');
765 if (r != MAILIMF_NO_ERROR)
766 return r;
767
768 * index = cur_token;
769 return MAILIMF_NO_ERROR;
770}
771
772static int mailimf_unstrict_crlf_parse(const char * message,
773 size_t length, size_t * index)
774{
775 size_t cur_token;
776 int r;
777
778 cur_token = * index;
779
780 mailimf_cfws_parse(message, length, &cur_token);
781
782 r = mailimf_char_parse(message, length, &cur_token, '\r');
783 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
784 return r;
785
786 r = mailimf_char_parse(message, length, &cur_token, '\n');
787 if (r != MAILIMF_NO_ERROR)
788 return r;
789
790 * index = cur_token;
791 return MAILIMF_NO_ERROR;
792}
793
794/* ************************************************************************ */
795
796
797
798/* RFC 2822 grammar */
799
800/*
801NO-WS-CTL = %d1-8 / ; US-ASCII control characters
802 %d11 / ; that do not include the
803 %d12 / ; carriage return, line feed,
804 %d14-31 / ; and white space characters
805 %d127
806*/
807
808static inline int is_no_ws_ctl(char ch)
809{
810 if ((ch == 9) || (ch == 10) || (ch == 13))
811 return FALSE;
812
813 if (ch == 127)
814 return TRUE;
815
816 return (ch >= 1) && (ch <= 31);
817}
818
819/*
820text = %d1-9 / ; Characters excluding CR and LF
821 %d11 /
822 %d12 /
823 %d14-127 /
824 obs-text
825*/
826
827/*
828specials = "(" / ")" / ; Special characters used in
829 "<" / ">" / ; other parts of the syntax
830 "[" / "]" /
831 ":" / ";" /
832 "@" / "\" /
833 "," / "." /
834 DQUOTE
835*/
836
837/*
838quoted-pair = ("\" text) / obs-qp
839*/
840
841static inline int mailimf_quoted_pair_parse(const char * message, size_t length,
842 size_t * index, char * result)
843{
844 size_t cur_token;
845
846 cur_token = * index;
847
848 if (cur_token + 1 >= length)
849 return MAILIMF_ERROR_PARSE;
850
851 if (message[cur_token] != '\\')
852 return MAILIMF_ERROR_PARSE;
853
854 cur_token ++;
855 * result = message[cur_token];
856 cur_token ++;
857 * index = cur_token;
858
859 return MAILIMF_NO_ERROR;
860}
861
862/*
863FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
864 obs-FWS
865*/
866
867int mailimf_fws_parse(const char * message, size_t length, size_t * index)
868{
869 size_t cur_token;
870 size_t final_token;
871 int fws_1;
872 int fws_2;
873 int fws_3;
874 int r;
875
876 cur_token = * index;
877
878 fws_1 = FALSE;
879 while (1) {
880 r = mailimf_wsp_parse(message, length, &cur_token);
881 if (r != MAILIMF_NO_ERROR) {
882 if (r == MAILIMF_ERROR_PARSE)
883 break;
884 else
885 return r;
886 }
887 fws_1 = TRUE;
888 }
889 final_token = cur_token;
890
891 r = mailimf_crlf_parse(message, length, &cur_token);
892 switch (r) {
893 case MAILIMF_NO_ERROR:
894 fws_2 = TRUE;
895 break;
896 case MAILIMF_ERROR_PARSE:
897 fws_2 = FALSE;
898 break;
899 default:
900 return r;
901 }
902
903 fws_3 = FALSE;
904 if (fws_2) {
905 while (1) {
906 r = mailimf_wsp_parse(message, length, &cur_token);
907 if (r != MAILIMF_NO_ERROR) {
908 if (r == MAILIMF_ERROR_PARSE)
909 break;
910 else
911 return r;
912 }
913 fws_3 = TRUE;
914 }
915 }
916
917 if ((!fws_1) && (!fws_3))
918 return MAILIMF_ERROR_PARSE;
919
920 if (!fws_3)
921 cur_token = final_token;
922
923 * index = cur_token;
924
925 return MAILIMF_NO_ERROR;
926}
927
928
929/*
930ctext = NO-WS-CTL / ; Non white space controls
931
932 %d33-39 / ; The rest of the US-ASCII
933 %d42-91 / ; characters not including "(",
934 %d93-126 ; ")", or "\"
935*/
936
937static inline int is_ctext(char ch)
938{
939 unsigned char uch = (unsigned char) ch;
940
941 if (is_no_ws_ctl(ch))
942 return TRUE;
943
944 if (uch < 33)
945 return FALSE;
946
947 if ((uch == 40) || (uch == 41))
948 return FALSE;
949
950 if (uch == 92)
951 return FALSE;
952
953 if (uch == 127)
954 return FALSE;
955
956 return TRUE;
957}
958
959/*
960ccontent = ctext / quoted-pair / comment
961*/
962
963static inline int mailimf_ccontent_parse(const char * message, size_t length,
964 size_t * index)
965{
966 size_t cur_token;
967 char ch;
968 int r;
969
970 cur_token = * index;
971
972 if (cur_token >= length)
973 return MAILIMF_ERROR_PARSE;
974
975 if (is_ctext(message[cur_token])) {
976 cur_token ++;
977 }
978 else {
979 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
980
981 if (r == MAILIMF_ERROR_PARSE)
982 r = mailimf_comment_parse(message, length, &cur_token);
983
984 if (r == MAILIMF_ERROR_PARSE)
985 return r;
986 }
987
988 * index = cur_token;
989
990 return MAILIMF_NO_ERROR;
991}
992
993/*
994[FWS] ccontent
995*/
996
997static inline int
998mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
999 size_t * index)
1000{
1001 size_t cur_token;
1002 int r;
1003
1004 cur_token = * index;
1005
1006 r = mailimf_fws_parse(message, length, &cur_token);
1007 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1008 return r;
1009
1010 r = mailimf_ccontent_parse(message, length, &cur_token);
1011 if (r != MAILIMF_NO_ERROR)
1012 return r;
1013
1014 * index = cur_token;
1015
1016 return MAILIMF_NO_ERROR;
1017}
1018
1019/*
1020comment = "(" *([FWS] ccontent) [FWS] ")"
1021*/
1022
1023static inline int mailimf_comment_parse(const char * message, size_t length,
1024 size_t * index)
1025{
1026 size_t cur_token;
1027 int r;
1028
1029 cur_token = * index;
1030
1031 r = mailimf_oparenth_parse(message, length, &cur_token);
1032 if (r != MAILIMF_NO_ERROR)
1033 return r;
1034
1035 while (1) {
1036 r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token);
1037 if (r != MAILIMF_NO_ERROR) {
1038 if (r == MAILIMF_ERROR_PARSE)
1039 break;
1040 else
1041 return r;
1042 }
1043 }
1044
1045 r = mailimf_fws_parse(message, length, &cur_token);
1046 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1047 return r;
1048
1049 r = mailimf_cparenth_parse(message, length, &cur_token);
1050 if (r != MAILIMF_NO_ERROR)
1051 return r;
1052
1053 * index = cur_token;
1054
1055 return MAILIMF_NO_ERROR;
1056}
1057
1058/*
1059[FWS] comment
1060*/
1061
1062static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length,
1063 size_t * index)
1064{
1065 size_t cur_token;
1066 int r;
1067
1068 cur_token = * index;
1069
1070 r = mailimf_fws_parse(message, length, &cur_token);
1071 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1072 return r;
1073
1074 r = mailimf_comment_parse(message, length, &cur_token);
1075 if (r != MAILIMF_NO_ERROR)
1076 return r;
1077
1078 * index = cur_token;
1079
1080 return MAILIMF_NO_ERROR;
1081}
1082
1083/*
1084CFWS = *([FWS] comment) (([FWS] comment) / FWS)
1085*/
1086
1087int mailimf_cfws_parse(const char * message, size_t length,
1088 size_t * index)
1089{
1090 size_t cur_token;
1091 int has_comment;
1092 int r;
1093
1094 cur_token = * index;
1095
1096 has_comment = FALSE;
1097 while (1) {
1098 r = mailimf_cfws_fws_comment_parse(message, length, &cur_token);
1099 if (r != MAILIMF_NO_ERROR) {
1100 if (r == MAILIMF_ERROR_PARSE)
1101 break;
1102 else
1103 return r;
1104 }
1105 has_comment = TRUE;
1106 }
1107
1108 if (!has_comment) {
1109 r = mailimf_fws_parse(message, length, &cur_token);
1110 if (r != MAILIMF_NO_ERROR)
1111 return r;
1112 }
1113
1114 * index = cur_token;
1115
1116 return MAILIMF_NO_ERROR;
1117}
1118
1119/*
1120atext = ALPHA / DIGIT / ; Any character except controls,
1121 "!" / "#" / ; SP, and specials.
1122 "$" / "%" / ; Used for atoms
1123 "&" / "'" /
1124 "*" / "+" /
1125 "-" / "/" /
1126 "=" / "?" /
1127 "^" / "_" /
1128 "`" / "{" /
1129 "|" / "}" /
1130 "~"
1131*/
1132
1133static inline int is_atext(char ch)
1134{
1135 switch (ch) {
1136 case ' ':
1137 case '\t':
1138 case '\n':
1139 case '\r':
1140#if 0
1141 case '(':
1142 case ')':
1143#endif
1144 case '<':
1145 case '>':
1146#if 0
1147 case '@':
1148#endif
1149 case ',':
1150 case '"':
1151 case ':':
1152 case ';':
1153 return FALSE;
1154 default:
1155 return TRUE;
1156 }
1157}
1158
1159/*
1160atom = [CFWS] 1*atext [CFWS]
1161*/
1162
1163int mailimf_atom_parse(const char * message, size_t length,
1164 size_t * index, char ** result)
1165{
1166 size_t cur_token;
1167 int r;
1168 int res;
1169 char * atom;
1170 size_t end;
1171
1172 cur_token = * index;
1173
1174 r = mailimf_cfws_parse(message, length, &cur_token);
1175 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1176 res = r;
1177 goto err;
1178 }
1179
1180 end = cur_token;
1181 if (end >= length) {
1182 res = MAILIMF_ERROR_PARSE;
1183 goto err;
1184 }
1185
1186 while (is_atext(message[end])) {
1187 end ++;
1188 if (end >= length)
1189 break;
1190 }
1191 if (end == cur_token) {
1192 res = MAILIMF_ERROR_PARSE;
1193 goto err;
1194 }
1195
1196 atom = malloc(end - cur_token + 1);
1197 if (atom == NULL) {
1198 res = MAILIMF_ERROR_MEMORY;
1199 goto err;
1200 }
1201 strncpy(atom, message + cur_token, end - cur_token);
1202 atom[end - cur_token] = '\0';
1203
1204 cur_token = end;
1205
1206 * index = cur_token;
1207 * result = atom;
1208
1209 return MAILIMF_NO_ERROR;
1210
1211 err:
1212 return res;
1213}
1214
1215int mailimf_fws_atom_parse(const char * message, size_t length,
1216 size_t * index, char ** result)
1217{
1218 size_t cur_token;
1219 int r;
1220 int res;
1221 char * atom;
1222 size_t end;
1223
1224 cur_token = * index;
1225
1226 r = mailimf_fws_parse(message, length, &cur_token);
1227 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1228 res = r;
1229 goto err;
1230 }
1231
1232 end = cur_token;
1233 if (end >= length) {
1234 res = MAILIMF_ERROR_PARSE;
1235 goto err;
1236 }
1237
1238 while (is_atext(message[end])) {
1239 end ++;
1240 if (end >= length)
1241 break;
1242 }
1243 if (end == cur_token) {
1244 res = MAILIMF_ERROR_PARSE;
1245 goto err;
1246 }
1247
1248 atom = malloc(end - cur_token + 1);
1249 if (atom == NULL) {
1250 res = MAILIMF_ERROR_MEMORY;
1251 goto err;
1252 }
1253 strncpy(atom, message + cur_token, end - cur_token);
1254 atom[end - cur_token] = '\0';
1255
1256 cur_token = end;
1257
1258 * index = cur_token;
1259 * result = atom;
1260
1261 return MAILIMF_NO_ERROR;
1262
1263 err:
1264 return res;
1265}
1266
1267/*
1268dot-atom = [CFWS] dot-atom-text [CFWS]
1269*/
1270
1271#if 0
1272static int mailimf_dot_atom_parse(const char * message, size_t length,
1273 size_t * index, char ** result)
1274{
1275 return mailimf_atom_parse(message, length, index, result);
1276}
1277#endif
1278
1279/*
1280dot-atom-text = 1*atext *("." 1*atext)
1281*/
1282
1283#if 0
1284static int
1285mailimf_dot_atom_text_parse(const char * message, size_t length,
1286 size_t * index, char ** result)
1287{
1288 return mailimf_atom_parse(message, length, index, result);
1289}
1290#endif
1291
1292/*
1293qtext = NO-WS-CTL / ; Non white space controls
1294
1295 %d33 / ; The rest of the US-ASCII
1296 %d35-91 / ; characters not including "\"
1297 %d93-126 ; or the quote character
1298*/
1299
1300static inline int is_qtext(char ch)
1301{
1302 unsigned char uch = (unsigned char) ch;
1303
1304 if (is_no_ws_ctl(ch))
1305 return TRUE;
1306
1307 if (uch < 33)
1308 return FALSE;
1309
1310 if (uch == 34)
1311 return FALSE;
1312
1313 if (uch == 92)
1314 return FALSE;
1315
1316 if (uch == 127)
1317 return FALSE;
1318
1319 return TRUE;
1320}
1321
1322/*
1323qcontent = qtext / quoted-pair
1324*/
1325
1326static int mailimf_qcontent_parse(const char * message, size_t length,
1327 size_t * index, char * result)
1328{
1329 size_t cur_token;
1330 char ch;
1331 int r;
1332
1333 cur_token = * index;
1334
1335 if (cur_token >= length)
1336 return MAILIMF_ERROR_PARSE;
1337
1338 if (is_qtext(message[cur_token])) {
1339 ch = message[cur_token];
1340 cur_token ++;
1341 }
1342 else {
1343 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
1344
1345 if (r != MAILIMF_NO_ERROR)
1346 return r;
1347 }
1348
1349 * result = ch;
1350 * index = cur_token;
1351
1352 return MAILIMF_NO_ERROR;
1353}
1354
1355/*
1356quoted-string = [CFWS]
1357 DQUOTE *([FWS] qcontent) [FWS] DQUOTE
1358 [CFWS]
1359*/
1360
1361int mailimf_quoted_string_parse(const char * message, size_t length,
1362 size_t * index, char ** result)
1363{
1364 size_t cur_token;
1365 MMAPString * gstr;
1366 char ch;
1367 char * str;
1368 int r;
1369 int res;
1370
1371 cur_token = * index;
1372
1373 r = mailimf_cfws_parse(message, length, &cur_token);
1374 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1375 res = r;
1376 goto err;
1377 }
1378
1379 r = mailimf_dquote_parse(message, length, &cur_token);
1380 if (r != MAILIMF_NO_ERROR) {
1381 res = r;
1382 goto err;
1383 }
1384
1385 gstr = mmap_string_new("");
1386 if (gstr == NULL) {
1387 res = MAILIMF_ERROR_MEMORY;
1388 goto err;
1389 }
1390
1391#if 0
1392 if (mmap_string_append_c(gstr, '\"') == NULL) {
1393 res = MAILIMF_ERROR_MEMORY;
1394 goto free_gstr;
1395 }
1396#endif
1397
1398 while (1) {
1399 r = mailimf_fws_parse(message, length, &cur_token);
1400 if (r == MAILIMF_NO_ERROR) {
1401 if (mmap_string_append_c(gstr, ' ') == NULL) {
1402 res = MAILIMF_ERROR_MEMORY;
1403 goto free_gstr;
1404 }
1405 }
1406 else if (r != MAILIMF_ERROR_PARSE) {
1407 res = r;
1408 goto free_gstr;
1409 }
1410
1411 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1412 if (r == MAILIMF_NO_ERROR) {
1413 if (mmap_string_append_c(gstr, ch) == NULL) {
1414 res = MAILIMF_ERROR_MEMORY;
1415 goto free_gstr;
1416 }
1417 }
1418 else if (r == MAILIMF_ERROR_PARSE)
1419 break;
1420 else {
1421 res = r;
1422 goto free_gstr;
1423 }
1424 }
1425
1426 r = mailimf_dquote_parse(message, length, &cur_token);
1427 if (r != MAILIMF_NO_ERROR) {
1428 res = r;
1429 goto free_gstr;
1430 }
1431
1432#if 0
1433 if (mmap_string_append_c(gstr, '\"') == NULL) {
1434 res = MAILIMF_ERROR_MEMORY;
1435 goto free_gstr;
1436 }
1437#endif
1438
1439 str = strdup(gstr->str);
1440 if (str == NULL) {
1441 res = MAILIMF_ERROR_MEMORY;
1442 goto free_gstr;
1443 }
1444 mmap_string_free(gstr);
1445
1446 * index = cur_token;
1447 * result = str;
1448
1449 return MAILIMF_NO_ERROR;
1450
1451 free_gstr:
1452 mmap_string_free(gstr);
1453 err:
1454 return res;
1455}
1456
1457int mailimf_fws_quoted_string_parse(const char * message, size_t length,
1458 size_t * index, char ** result)
1459{
1460 size_t cur_token;
1461 MMAPString * gstr;
1462 char ch;
1463 char * str;
1464 int r;
1465 int res;
1466
1467 cur_token = * index;
1468
1469 r = mailimf_fws_parse(message, length, &cur_token);
1470 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1471 res = r;
1472 goto err;
1473 }
1474
1475 r = mailimf_dquote_parse(message, length, &cur_token);
1476 if (r != MAILIMF_NO_ERROR) {
1477 res = r;
1478 goto err;
1479 }
1480
1481 gstr = mmap_string_new("");
1482 if (gstr == NULL) {
1483 res = MAILIMF_ERROR_MEMORY;
1484 goto err;
1485 }
1486
1487#if 0
1488 if (mmap_string_append_c(gstr, '\"') == NULL) {
1489 res = MAILIMF_ERROR_MEMORY;
1490 goto free_gstr;
1491 }
1492#endif
1493
1494 while (1) {
1495 r = mailimf_fws_parse(message, length, &cur_token);
1496 if (r == MAILIMF_NO_ERROR) {
1497 if (mmap_string_append_c(gstr, ' ') == NULL) {
1498 res = MAILIMF_ERROR_MEMORY;
1499 goto free_gstr;
1500 }
1501 }
1502 else if (r != MAILIMF_ERROR_PARSE) {
1503 res = r;
1504 goto free_gstr;
1505 }
1506
1507 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1508 if (r == MAILIMF_NO_ERROR) {
1509 if (mmap_string_append_c(gstr, ch) == NULL) {
1510 res = MAILIMF_ERROR_MEMORY;
1511 goto free_gstr;
1512 }
1513 }
1514 else if (r == MAILIMF_ERROR_PARSE)
1515 break;
1516 else {
1517 res = r;
1518 goto free_gstr;
1519 }
1520 }
1521
1522 r = mailimf_dquote_parse(message, length, &cur_token);
1523 if (r != MAILIMF_NO_ERROR) {
1524 res = r;
1525 goto free_gstr;
1526 }
1527
1528#if 0
1529 if (mmap_string_append_c(gstr, '\"') == NULL) {
1530 res = MAILIMF_ERROR_MEMORY;
1531 goto free_gstr;
1532 }
1533#endif
1534
1535 str = strdup(gstr->str);
1536 if (str == NULL) {
1537 res = MAILIMF_ERROR_MEMORY;
1538 goto free_gstr;
1539 }
1540 mmap_string_free(gstr);
1541
1542 * index = cur_token;
1543 * result = str;
1544
1545 return MAILIMF_NO_ERROR;
1546
1547 free_gstr:
1548 mmap_string_free(gstr);
1549 err:
1550 return res;
1551}
1552
1553/*
1554word = atom / quoted-string
1555*/
1556
1557int mailimf_word_parse(const char * message, size_t length,
1558 size_t * index, char ** result)
1559{
1560 size_t cur_token;
1561 char * word;
1562 int r;
1563
1564 cur_token = * index;
1565
1566 r = mailimf_atom_parse(message, length, &cur_token, &word);
1567
1568 if (r == MAILIMF_ERROR_PARSE)
1569 r = mailimf_quoted_string_parse(message, length, &cur_token, &word);
1570
1571 if (r != MAILIMF_NO_ERROR)
1572 return r;
1573
1574 * result = word;
1575 * index = cur_token;
1576
1577 return MAILIMF_NO_ERROR;
1578}
1579
1580int mailimf_fws_word_parse(const char * message, size_t length,
1581 size_t * index, char ** result)
1582{
1583 size_t cur_token;
1584 char * word;
1585 int r;
1586
1587 cur_token = * index;
1588
1589 r = mailimf_fws_atom_parse(message, length, &cur_token, &word);
1590
1591 if (r == MAILIMF_ERROR_PARSE)
1592 r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word);
1593
1594 if (r != MAILIMF_NO_ERROR)
1595 return r;
1596
1597 * result = word;
1598 * index = cur_token;
1599
1600 return MAILIMF_NO_ERROR;
1601}
1602
1603/*
1604phrase = 1*word / obs-phrase
1605*/
1606
1607static int mailimf_phrase_parse(const char * message, size_t length,
1608 size_t * index, char ** result)
1609{
1610 MMAPString * gphrase;
1611 char * word;
1612 int first;
1613 size_t cur_token;
1614 int r;
1615 int res;
1616 char * str;
1617
1618 cur_token = * index;
1619
1620 gphrase = mmap_string_new("");
1621 if (gphrase == NULL) {
1622 res = MAILIMF_ERROR_MEMORY;
1623 goto err;
1624 }
1625
1626 first = TRUE;
1627
1628 while (1) {
1629 r = mailimf_fws_word_parse(message, length, &cur_token, &word);
1630 if (r == MAILIMF_NO_ERROR) {
1631 if (!first) {
1632 if (mmap_string_append_c(gphrase, ' ') == NULL) {
1633 mailimf_word_free(word);
1634 res = MAILIMF_ERROR_MEMORY;
1635 goto free;
1636 }
1637 }
1638 if (mmap_string_append(gphrase, word) == NULL) {
1639 mailimf_word_free(word);
1640 res = MAILIMF_ERROR_MEMORY;
1641 goto free;
1642 }
1643 mailimf_word_free(word);
1644 first = FALSE;
1645 }
1646 else if (r == MAILIMF_ERROR_PARSE)
1647 break;
1648 else {
1649 res = r;
1650 goto free;
1651 }
1652 }
1653
1654 if (first) {
1655 res = MAILIMF_ERROR_PARSE;
1656 goto free;
1657 }
1658
1659 str = strdup(gphrase->str);
1660 if (str == NULL) {
1661 res = MAILIMF_ERROR_MEMORY;
1662 goto free;
1663 }
1664 mmap_string_free(gphrase);
1665
1666 * result = str;
1667 * index = cur_token;
1668
1669 return MAILIMF_NO_ERROR;
1670
1671 free:
1672 mmap_string_free(gphrase);
1673 err:
1674 return res;
1675}
1676
1677/*
1678utext = NO-WS-CTL / ; Non white space controls
1679 %d33-126 / ; The rest of US-ASCII
1680 obs-utext
1681
1682added : WSP
1683*/
1684
1685enum {
1686 UNSTRUCTURED_START,
1687 UNSTRUCTURED_CR,
1688 UNSTRUCTURED_LF,
1689 UNSTRUCTURED_WSP,
1690 UNSTRUCTURED_OUT
1691};
1692
1693static int mailimf_unstructured_parse(const char * message, size_t length,
1694 size_t * index, char ** result)
1695{
1696 size_t cur_token;
1697 int state;
1698 size_t begin;
1699 size_t terminal;
1700 char * str;
1701
1702 cur_token = * index;
1703
1704
1705 while (1) {
1706 int r;
1707
1708 r = mailimf_wsp_parse(message, length, &cur_token);
1709 if (r == MAILIMF_NO_ERROR) {
1710 /* do nothing */
1711 }
1712 else if (r == MAILIMF_ERROR_PARSE)
1713 break;
1714 else {
1715 return r;
1716 }
1717 }
1718
1719 state = UNSTRUCTURED_START;
1720 begin = cur_token;
1721 terminal = cur_token;
1722
1723 while (state != UNSTRUCTURED_OUT) {
1724
1725 switch(state) {
1726 case UNSTRUCTURED_START:
1727 if (cur_token >= length)
1728 return MAILIMF_ERROR_PARSE;
1729
1730 terminal = cur_token;
1731 switch(message[cur_token]) {
1732 case '\r':
1733 state = UNSTRUCTURED_CR;
1734 break;
1735 case '\n':
1736 state = UNSTRUCTURED_LF;
1737 break;
1738 default:
1739 state = UNSTRUCTURED_START;
1740 break;
1741 }
1742 break;
1743 case UNSTRUCTURED_CR:
1744 if (cur_token >= length)
1745 return MAILIMF_ERROR_PARSE;
1746
1747 switch(message[cur_token]) {
1748 case '\n':
1749 state = UNSTRUCTURED_LF;
1750 break;
1751 default:
1752 state = UNSTRUCTURED_START;
1753 break;
1754 }
1755 break;
1756
1757 case UNSTRUCTURED_LF:
1758 if (cur_token >= length) {
1759 state = UNSTRUCTURED_OUT;
1760 break;
1761 }
1762
1763 switch(message[cur_token]) {
1764 case '\t':
1765 case ' ':
1766 state = UNSTRUCTURED_WSP;
1767 break;
1768 default:
1769 state = UNSTRUCTURED_OUT;
1770 break;
1771 }
1772 break;
1773 case UNSTRUCTURED_WSP:
1774 if (cur_token >= length)
1775 return MAILIMF_ERROR_PARSE;
1776
1777 switch(message[cur_token]) {
1778 case '\r':
1779 state = UNSTRUCTURED_CR;
1780 break;
1781 case '\n':
1782 state = UNSTRUCTURED_LF;
1783 break;
1784 default:
1785 state = UNSTRUCTURED_START;
1786 break;
1787 }
1788 break;
1789 }
1790
1791 cur_token ++;
1792 }
1793
1794 str = malloc(terminal - begin + 1);
1795 if (str == NULL)
1796 return MAILIMF_ERROR_MEMORY;
1797 strncpy(str, message + begin, terminal - begin);
1798 str[terminal - begin] = '\0';
1799
1800 * index = terminal;
1801 * result = str;
1802
1803 return MAILIMF_NO_ERROR;
1804}
1805
1806
1807static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
1808 size_t * index)
1809{
1810 size_t cur_token;
1811 int state;
1812 size_t terminal;
1813
1814 cur_token = * index;
1815
1816 state = UNSTRUCTURED_START;
1817 terminal = cur_token;
1818
1819 while (state != UNSTRUCTURED_OUT) {
1820
1821 switch(state) {
1822 case UNSTRUCTURED_START:
1823 if (cur_token >= length)
1824 return MAILIMF_ERROR_PARSE;
1825 terminal = cur_token;
1826 switch(message[cur_token]) {
1827 case '\r':
1828 state = UNSTRUCTURED_CR;
1829 break;
1830 case '\n':
1831 state = UNSTRUCTURED_LF;
1832 break;
1833 default:
1834 state = UNSTRUCTURED_START;
1835 break;
1836 }
1837 break;
1838 case UNSTRUCTURED_CR:
1839 if (cur_token >= length)
1840 return MAILIMF_ERROR_PARSE;
1841 switch(message[cur_token]) {
1842 case '\n':
1843 state = UNSTRUCTURED_LF;
1844 break;
1845 default:
1846 state = UNSTRUCTURED_START;
1847 break;
1848 }
1849 break;
1850 case UNSTRUCTURED_LF:
1851 if (cur_token >= length) {
1852 state = UNSTRUCTURED_OUT;
1853 break;
1854 }
1855 switch(message[cur_token]) {
1856 case '\t':
1857 case ' ':
1858 state = UNSTRUCTURED_WSP;
1859 break;
1860 default:
1861 state = UNSTRUCTURED_OUT;
1862 break;
1863 }
1864 break;
1865 case UNSTRUCTURED_WSP:
1866 if (cur_token >= length)
1867 return MAILIMF_ERROR_PARSE;
1868 switch(message[cur_token]) {
1869 case '\r':
1870 state = UNSTRUCTURED_CR;
1871 break;
1872 case '\n':
1873 state = UNSTRUCTURED_LF;
1874 break;
1875 default:
1876 state = UNSTRUCTURED_START;
1877 break;
1878 }
1879 break;
1880 }
1881
1882 cur_token ++;
1883 }
1884
1885 * index = terminal;
1886
1887 return MAILIMF_NO_ERROR;
1888}
1889
1890
1891int mailimf_ignore_field_parse(const char * message, size_t length,
1892 size_t * index)
1893{
1894 int has_field;
1895 size_t cur_token;
1896 int state;
1897 size_t terminal;
1898
1899 has_field = FALSE;
1900 cur_token = * index;
1901
1902 terminal = cur_token;
1903 state = UNSTRUCTURED_START;
1904
1905 /* check if this is not a beginning CRLF */
1906
1907 if (cur_token >= length)
1908 return MAILIMF_ERROR_PARSE;
1909
1910 switch (message[cur_token]) {
1911 case '\r':
1912 return MAILIMF_ERROR_PARSE;
1913 case '\n':
1914 return MAILIMF_ERROR_PARSE;
1915 }
1916
1917 while (state != UNSTRUCTURED_OUT) {
1918
1919 switch(state) {
1920 case UNSTRUCTURED_START:
1921 if (cur_token >= length)
1922 return MAILIMF_ERROR_PARSE;
1923
1924 switch(message[cur_token]) {
1925 case '\r':
1926 state = UNSTRUCTURED_CR;
1927 break;
1928 case '\n':
1929 state = UNSTRUCTURED_LF;
1930 break;
1931 case ':':
1932 has_field = TRUE;
1933 state = UNSTRUCTURED_START;
1934 break;
1935 default:
1936 state = UNSTRUCTURED_START;
1937 break;
1938 }
1939 break;
1940 case UNSTRUCTURED_CR:
1941 if (cur_token >= length)
1942 return MAILIMF_ERROR_PARSE;
1943
1944 switch(message[cur_token]) {
1945 case '\n':
1946 state = UNSTRUCTURED_LF;
1947 break;
1948 case ':':
1949 has_field = TRUE;
1950 state = UNSTRUCTURED_START;
1951 break;
1952 default:
1953 state = UNSTRUCTURED_START;
1954 break;
1955 }
1956 break;
1957 case UNSTRUCTURED_LF:
1958 if (cur_token >= length) {
1959 terminal = cur_token;
1960 state = UNSTRUCTURED_OUT;
1961 break;
1962 }
1963
1964 switch(message[cur_token]) {
1965 case '\t':
1966 case ' ':
1967 state = UNSTRUCTURED_WSP;
1968 break;
1969 default:
1970 terminal = cur_token;
1971 state = UNSTRUCTURED_OUT;
1972 break;
1973 }
1974 break;
1975 case UNSTRUCTURED_WSP:
1976 if (cur_token >= length)
1977 return MAILIMF_ERROR_PARSE;
1978
1979 switch(message[cur_token]) {
1980 case '\r':
1981 state = UNSTRUCTURED_CR;
1982 break;
1983 case '\n':
1984 state = UNSTRUCTURED_LF;
1985 break;
1986 case ':':
1987 has_field = TRUE;
1988 state = UNSTRUCTURED_START;
1989 break;
1990 default:
1991 state = UNSTRUCTURED_START;
1992 break;
1993 }
1994 break;
1995 }
1996
1997 cur_token ++;
1998 }
1999
2000 if (!has_field)
2001 return MAILIMF_ERROR_PARSE;
2002
2003 * index = terminal;
2004
2005 return MAILIMF_NO_ERROR;
2006}
2007
2008
2009/*
2010date-time = [ day-of-week "," ] date FWS time [CFWS]
2011*/
2012
2013int mailimf_date_time_parse(const char * message, size_t length,
2014 size_t * index,
2015 struct mailimf_date_time ** result)
2016{
2017 size_t cur_token;
2018 int day_of_week;
2019 struct mailimf_date_time * date_time;
2020 int day;
2021 int month;
2022 int year;
2023 int hour;
2024 int min;
2025 int sec;
2026 int zone;
2027 int r;
2028
2029 cur_token = * index;
2030
2031 day_of_week = -1;
2032 r = mailimf_day_of_week_parse(message, length, &cur_token, &day_of_week);
2033 if (r == MAILIMF_NO_ERROR) {
2034 r = mailimf_comma_parse(message, length, &cur_token);
2035 if (r != MAILIMF_NO_ERROR)
2036 return r;
2037 }
2038 else if (r != MAILIMF_ERROR_PARSE)
2039 return r;
2040
2041 r = mailimf_date_parse(message, length, &cur_token, &day, &month, &year);
2042 if (r != MAILIMF_NO_ERROR)
2043 return r;
2044
2045 r = mailimf_fws_parse(message, length, &cur_token);
2046 if (r != MAILIMF_NO_ERROR)
2047 return r;
2048
2049 r = mailimf_time_parse(message, length, &cur_token,
2050 &hour, &min, &sec, &zone);
2051 if (r != MAILIMF_NO_ERROR)
2052 return r;
2053
2054 date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone);
2055 if (date_time == NULL)
2056 return MAILIMF_ERROR_MEMORY;
2057
2058 * index = cur_token;
2059 * result = date_time;
2060
2061 return MAILIMF_NO_ERROR;
2062}
2063
2064/*
2065day-of-week = ([FWS] day-name) / obs-day-of-week
2066*/
2067
2068static int mailimf_day_of_week_parse(const char * message, size_t length,
2069 size_t * index, int * result)
2070{
2071 size_t cur_token;
2072 int day_of_week;
2073 int r;
2074
2075 cur_token = * index;
2076
2077 r = mailimf_cfws_parse(message, length, &cur_token);
2078 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2079 return r;
2080
2081 r = mailimf_day_name_parse(message, length, &cur_token, &day_of_week);
2082 if (r != MAILIMF_NO_ERROR)
2083 return r;
2084
2085 * index = cur_token;
2086 * result = day_of_week;
2087
2088 return MAILIMF_NO_ERROR;
2089}
2090
2091/*
2092day-name = "Mon" / "Tue" / "Wed" / "Thu" /
2093 "Fri" / "Sat" / "Sun"
2094*/
2095
2096struct mailimf_token_value {
2097 int value;
2098 char * str;
2099};
2100
2101static struct mailimf_token_value day_names[] = {
2102 {1, "Mon"},
2103 {2, "Tue"},
2104 {3, "Wed"},
2105 {4, "Thu"},
2106 {5, "Fri"},
2107 {6, "Sat"},
2108 {7, "Sun"},
2109};
2110
2111enum {
2112 DAY_NAME_START,
2113 DAY_NAME_T,
2114 DAY_NAME_S
2115};
2116
2117static int guess_day_name(const char * message, size_t length, size_t index)
2118{
2119 int state;
2120
2121 state = DAY_NAME_START;
2122
2123 while (1) {
2124
2125 if (index >= length)
2126 return -1;
2127
2128 switch(state) {
2129 case DAY_NAME_START:
2130 switch((char) toupper((unsigned char) message[index])) {
2131 case 'M': /* Mon */
2132 return 1;
2133 break;
2134 case 'T': /* Tue Thu */
2135 state = DAY_NAME_T;
2136 break;
2137 case 'W': /* Wed */
2138 return 3;
2139 case 'F':
2140 return 5;
2141 case 'S': /* Sat Sun */
2142 state = DAY_NAME_S;
2143 break;
2144 default:
2145 return -1;
2146 }
2147 break;
2148 case DAY_NAME_T:
2149 switch((char) toupper((unsigned char) message[index])) {
2150 case 'U':
2151 return 2;
2152 case 'H':
2153 return 4;
2154 default:
2155 return -1;
2156 }
2157 break;
2158 case DAY_NAME_S:
2159 switch((char) toupper((unsigned char) message[index])) {
2160 case 'A':
2161 return 6;
2162 case 'U':
2163 return 7;
2164 default:
2165 return -1;
2166 }
2167 break;
2168 }
2169
2170 index ++;
2171 }
2172}
2173
2174static int mailimf_day_name_parse(const char * message, size_t length,
2175 size_t * index, int * result)
2176{
2177 size_t cur_token;
2178 int day_of_week;
2179 int guessed_day;
2180 int r;
2181
2182 cur_token = * index;
2183
2184 guessed_day = guess_day_name(message, length, cur_token);
2185 if (guessed_day == -1)
2186 return MAILIMF_ERROR_PARSE;
2187
2188 r = mailimf_token_case_insensitive_parse(message, length,
2189 &cur_token,
2190 day_names[guessed_day - 1].str);
2191 if (r != MAILIMF_NO_ERROR)
2192 return r;
2193
2194 day_of_week = guessed_day;
2195
2196 * result = day_of_week;
2197 * index = cur_token;
2198
2199 return MAILIMF_NO_ERROR;
2200}
2201
2202/*
2203date = day month year
2204*/
2205
2206static int mailimf_date_parse(const char * message, size_t length,
2207 size_t * index,
2208 int * pday, int * pmonth, int * pyear)
2209{
2210 size_t cur_token;
2211 int day;
2212 int month;
2213 int year;
2214 int r;
2215
2216 cur_token = * index;
2217
2218 r = mailimf_day_parse(message, length, &cur_token, &day);
2219 if (r != MAILIMF_NO_ERROR)
2220 return r;
2221
2222 r = mailimf_month_parse(message, length, &cur_token, &month);
2223 if (r != MAILIMF_NO_ERROR)
2224 return r;
2225
2226 r = mailimf_year_parse(message, length, &cur_token, &year);
2227 if (r != MAILIMF_NO_ERROR)
2228 return r;
2229
2230 * pday = day;
2231 * pmonth = month;
2232 * pyear = year;
2233
2234 * index = cur_token;
2235
2236 return MAILIMF_NO_ERROR;
2237}
2238
2239/*
2240year = 4*DIGIT / obs-year
2241*/
2242
2243static int mailimf_year_parse(const char * message, size_t length,
2244 size_t * index, int * result)
2245{
2246 uint32_t number;
2247 size_t cur_token;
2248 int r;
2249
2250 cur_token = * index;
2251
2252 r = mailimf_cfws_parse(message, length, &cur_token);
2253 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2254 return r;
2255
2256 r = mailimf_number_parse(message, length, &cur_token, &number);
2257 if (r != MAILIMF_NO_ERROR)
2258 return r;
2259
2260 * index = cur_token;
2261 * result = number;
2262
2263 return MAILIMF_NO_ERROR;
2264}
2265
2266/*
2267month = (FWS month-name FWS) / obs-month
2268*/
2269
2270static int mailimf_month_parse(const char * message, size_t length,
2271 size_t * index, int * result)
2272{
2273 size_t cur_token;
2274 int month;
2275 int r;
2276
2277 cur_token = * index;
2278
2279 r = mailimf_cfws_parse(message, length, &cur_token);
2280 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2281 return r;
2282
2283 r = mailimf_month_name_parse(message, length, &cur_token, &month);
2284 if (r != MAILIMF_NO_ERROR)
2285 return r;
2286
2287 * result = month;
2288 * index = cur_token;
2289
2290 return MAILIMF_NO_ERROR;
2291}
2292
2293/*
2294month-name = "Jan" / "Feb" / "Mar" / "Apr" /
2295 "May" / "Jun" / "Jul" / "Aug" /
2296 "Sep" / "Oct" / "Nov" / "Dec"
2297*/
2298
2299static struct mailimf_token_value month_names[] = {
2300 {1, "Jan"},
2301 {2, "Feb"},
2302 {3, "Mar"},
2303 {4, "Apr"},
2304 {5, "May"},
2305 {6, "Jun"},
2306 {7, "Jul"},
2307 {8, "Aug"},
2308 {9, "Sep"},
2309 {10, "Oct"},
2310 {11, "Nov"},
2311 {12, "Dec"},
2312};
2313
2314enum {
2315 MONTH_START,
2316 MONTH_J,
2317 MONTH_JU,
2318 MONTH_M,
2319 MONTH_MA,
2320 MONTH_A
2321};
2322
2323static int guess_month(const char * message, size_t length, size_t index)
2324{
2325 int state;
2326
2327 state = MONTH_START;
2328
2329 while (1) {
2330
2331 if (index >= length)
2332 return -1;
2333
2334 switch(state) {
2335 case MONTH_START:
2336 switch((char) toupper((unsigned char) message[index])) {
2337 case 'J': /* Jan Jun Jul */
2338 state = MONTH_J;
2339 break;
2340 case 'F': /* Feb */
2341 return 2;
2342 case 'M': /* Mar May */
2343 state = MONTH_M;
2344 break;
2345 case 'A': /* Apr Aug */
2346 state = MONTH_A;
2347 break;
2348 case 'S': /* Sep */
2349 return 9;
2350 case 'O': /* Oct */
2351 return 10;
2352 case 'N': /* Nov */
2353 return 11;
2354 case 'D': /* Dec */
2355 return 12;
2356 default:
2357 return -1;
2358 }
2359 break;
2360 case MONTH_J:
2361 switch((char) toupper((unsigned char) message[index])) {
2362 case 'A':
2363 return 1;
2364 case 'U':
2365 state = MONTH_JU;
2366 break;
2367 default:
2368 return -1;
2369 }
2370 break;
2371 case MONTH_JU:
2372 switch((char) toupper((unsigned char) message[index])) {
2373 case 'N':
2374 return 6;
2375 case 'L':
2376 return 7;
2377 default:
2378 return -1;
2379 }
2380 break;
2381 case MONTH_M:
2382 switch((char) toupper((unsigned char) message[index])) {
2383 case 'A':
2384 state = MONTH_MA;
2385 break;
2386 default:
2387 return -1;
2388 }
2389 break;
2390 case MONTH_MA:
2391 switch((char) toupper((unsigned char) message[index])) {
2392 case 'Y':
2393 return 5;
2394 case 'R':
2395 return 3;
2396 default:
2397 return -1;
2398 }
2399 break;
2400 case MONTH_A:
2401 switch((char) toupper((unsigned char) message[index])) {
2402 case 'P':
2403 return 4;
2404 case 'U':
2405 return 8;
2406 default:
2407 return -1;
2408 }
2409 break;
2410 }
2411
2412 index ++;
2413 }
2414}
2415
2416static int mailimf_month_name_parse(const char * message, size_t length,
2417 size_t * index, int * result)
2418{
2419 size_t cur_token;
2420 int month;
2421 int guessed_month;
2422 int r;
2423
2424 cur_token = * index;
2425
2426 guessed_month = guess_month(message, length, cur_token);
2427 if (guessed_month == -1)
2428 return MAILIMF_ERROR_PARSE;
2429
2430 r = mailimf_token_case_insensitive_parse(message, length,
2431 &cur_token,
2432 month_names[guessed_month - 1].str);
2433 if (r != MAILIMF_NO_ERROR)
2434 return r;
2435
2436 month = guessed_month;
2437
2438 * result = month;
2439 * index = cur_token;
2440
2441 return MAILIMF_NO_ERROR;
2442}
2443
2444/*
2445day = ([FWS] 1*2DIGIT) / obs-day
2446*/
2447
2448static int mailimf_day_parse(const char * message, size_t length,
2449 size_t * index, int * result)
2450{
2451 size_t cur_token;
2452 uint32_t day;
2453 int r;
2454
2455 cur_token = * index;
2456
2457 r = mailimf_cfws_parse(message, length, &cur_token);
2458 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2459 return r;
2460
2461 r = mailimf_number_parse(message, length, &cur_token, &day);
2462 if (r != MAILIMF_NO_ERROR)
2463 return r;
2464
2465 * result = day;
2466 * index = cur_token;
2467
2468 return MAILIMF_NO_ERROR;
2469}
2470
2471/*
2472time = time-of-day FWS zone
2473*/
2474
2475static int mailimf_time_parse(const char * message, size_t length,
2476 size_t * index,
2477 int * phour, int * pmin,
2478 int * psec,
2479 int * pzone)
2480{
2481 size_t cur_token;
2482 int hour;
2483 int min;
2484 int sec;
2485 int zone;
2486 int r;
2487
2488 cur_token = * index;
2489
2490 r = mailimf_cfws_parse(message, length, &cur_token);
2491 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2492 return r;
2493
2494 r = mailimf_time_of_day_parse(message, length, &cur_token,
2495 &hour, &min, &sec);
2496 if (r != MAILIMF_NO_ERROR)
2497 return r;
2498
2499 r = mailimf_fws_parse(message, length, &cur_token);
2500 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2501 return r;
2502
2503 r = mailimf_zone_parse(message, length, &cur_token, &zone);
2504 if (r == MAILIMF_NO_ERROR) {
2505 /* do nothing */
2506 }
2507 else if (r == MAILIMF_ERROR_PARSE) {
2508 zone = 0;
2509 }
2510 else {
2511 return r;
2512 }
2513
2514 * phour = hour;
2515 * pmin = min;
2516 * psec = sec;
2517 * pzone = zone;
2518
2519 * index = cur_token;
2520
2521 return MAILIMF_NO_ERROR;
2522}
2523
2524/*
2525time-of-day = hour ":" minute [ ":" second ]
2526*/
2527
2528static int mailimf_time_of_day_parse(const char * message, size_t length,
2529 size_t * index,
2530 int * phour, int * pmin,
2531 int * psec)
2532{
2533 int hour;
2534 int min;
2535 int sec;
2536 size_t cur_token;
2537 int r;
2538
2539 cur_token = * index;
2540
2541 r = mailimf_hour_parse(message, length, &cur_token, &hour);
2542 if (r != MAILIMF_NO_ERROR)
2543 return r;
2544
2545 r = mailimf_colon_parse(message, length, &cur_token);
2546 if (r != MAILIMF_NO_ERROR)
2547 return r;
2548
2549 r = mailimf_minute_parse(message, length, &cur_token, &min);
2550 if (r != MAILIMF_NO_ERROR)
2551 return r;
2552
2553 r = mailimf_colon_parse(message, length, &cur_token);
2554 if (r == MAILIMF_NO_ERROR) {
2555 r = mailimf_second_parse(message, length, &cur_token, &sec);
2556 if (r != MAILIMF_NO_ERROR)
2557 return r;
2558 }
2559 else if (r == MAILIMF_ERROR_PARSE)
2560 sec = 0;
2561 else
2562 return r;
2563
2564 * phour = hour;
2565 * pmin = min;
2566 * psec = sec;
2567 * index = cur_token;
2568
2569 return MAILIMF_NO_ERROR;
2570}
2571
2572/*
2573hour = 2DIGIT / obs-hour
2574*/
2575
2576static int mailimf_hour_parse(const char * message, size_t length,
2577 size_t * index, int * result)
2578{
2579 uint32_t hour;
2580 int r;
2581
2582 r = mailimf_number_parse(message, length, index, &hour);
2583 if (r != MAILIMF_NO_ERROR)
2584 return r;
2585
2586 * result = hour;
2587
2588 return MAILIMF_NO_ERROR;
2589}
2590
2591/*
2592minute = 2DIGIT / obs-minute
2593*/
2594
2595static int mailimf_minute_parse(const char * message, size_t length,
2596 size_t * index, int * result)
2597{
2598 uint32_t minute;
2599 int r;
2600
2601 r = mailimf_number_parse(message, length, index, &minute);
2602 if (r != MAILIMF_NO_ERROR)
2603 return r;
2604
2605 * result = minute;
2606
2607 return MAILIMF_NO_ERROR;
2608}
2609
2610/*
2611second = 2DIGIT / obs-second
2612*/
2613
2614static int mailimf_second_parse(const char * message, size_t length,
2615 size_t * index, int * result)
2616{
2617 uint32_t second;
2618 int r;
2619
2620 r = mailimf_number_parse(message, length, index, &second);
2621 if (r != MAILIMF_NO_ERROR)
2622 return r;
2623
2624 * result = second;
2625
2626 return MAILIMF_NO_ERROR;
2627}
2628
2629/*
2630zone = (( "+" / "-" ) 4DIGIT) / obs-zone
2631*/
2632
2633/*
2634obs-zone = "UT" / "GMT" / ; Universal Time
2635 ; North American UT
2636 ; offsets
2637 "EST" / "EDT" / ; Eastern: - 5/ - 4
2638 "CST" / "CDT" / ; Central: - 6/ - 5
2639 "MST" / "MDT" / ; Mountain: - 7/ - 6
2640 "PST" / "PDT" / ; Pacific: - 8/ - 7
2641
2642 %d65-73 / ; Military zones - "A"
2643 %d75-90 / ; through "I" and "K"
2644 %d97-105 / ; through "Z", both
2645 %d107-122 ; upper and lower case
2646*/
2647
2648enum {
2649 STATE_ZONE_1 = 0,
2650 STATE_ZONE_2 = 1,
2651 STATE_ZONE_3 = 2,
2652 STATE_ZONE_OK = 3,
2653 STATE_ZONE_ERR = 4,
2654 STATE_ZONE_CONT = 5,
2655};
2656
2657static int mailimf_zone_parse(const char * message, size_t length,
2658 size_t * index, int * result)
2659{
2660 uint32_t zone;
2661 int sign;
2662 size_t cur_token;
2663 int r;
2664
2665 cur_token = * index;
2666
2667 if (cur_token + 1 < length) {
2668 if ((message[cur_token] == 'U') && (message[cur_token] == 'T')) {
2669 * result = TRUE;
2670 * index = cur_token + 2;
2671
2672 return MAILIMF_NO_ERROR;
2673 }
2674 }
2675
2676 if (cur_token + 2 < length) {
2677 int state;
2678
2679 state = STATE_ZONE_1;
2680
2681 while (state <= 2) {
2682 switch (state) {
2683 case STATE_ZONE_1:
2684 switch (message[cur_token]) {
2685 case 'G':
2686 if (message[cur_token + 1] == 'M' && message[cur_token + 2] == 'T') {
2687 zone = 0;
2688 state = STATE_ZONE_OK;
2689 }
2690 else {
2691 state = STATE_ZONE_ERR;
2692 }
2693 break;
2694 case 'E':
2695 zone = -5;
2696 state = STATE_ZONE_2;
2697 break;
2698 case 'C':
2699 zone = -6;
2700 state = STATE_ZONE_2;
2701 break;
2702 case 'M':
2703 zone = -7;
2704 state = STATE_ZONE_2;
2705 break;
2706 case 'P':
2707 zone = -8;
2708 state = STATE_ZONE_2;
2709 break;
2710 default:
2711 state = STATE_ZONE_CONT;
2712 break;
2713 }
2714 break;
2715 case STATE_ZONE_2:
2716 switch (message[cur_token + 1]) {
2717 case 'S':
2718 state = STATE_ZONE_3;
2719 break;
2720 case 'D':
2721 zone ++;
2722 state = STATE_ZONE_3;
2723 break;
2724 default:
2725 state = STATE_ZONE_ERR;
2726 break;
2727 }
2728 break;
2729 case STATE_ZONE_3:
2730 if (message[cur_token + 2] == 'T') {
2731 zone *= 100;
2732 state = STATE_ZONE_OK;
2733 }
2734 else
2735 state = STATE_ZONE_ERR;
2736 break;
2737 }
2738 }
2739
2740 switch (state) {
2741 case STATE_ZONE_OK:
2742 * result = zone;
2743 * index = cur_token + 3;
2744 return MAILIMF_NO_ERROR;
2745
2746 case STATE_ZONE_ERR:
2747 return MAILIMF_ERROR_PARSE;
2748 }
2749 }
2750
2751 sign = 1;
2752 r = mailimf_plus_parse(message, length, &cur_token);
2753 if (r == MAILIMF_NO_ERROR)
2754 sign = 1;
2755
2756 if (r == MAILIMF_ERROR_PARSE) {
2757 r = mailimf_minus_parse(message, length, &cur_token);
2758 if (r == MAILIMF_NO_ERROR)
2759 sign = -1;
2760 }
2761
2762 if (r == MAILIMF_NO_ERROR) {
2763 /* do nothing */
2764 }
2765 else if (r == MAILIMF_ERROR_PARSE)
2766 sign = 1;
2767 else
2768 return r;
2769
2770 r = mailimf_number_parse(message, length, &cur_token, &zone);
2771 if (r != MAILIMF_NO_ERROR)
2772 return r;
2773
2774 zone = zone * sign;
2775
2776 * index = cur_token;
2777 * result = zone;
2778
2779 return MAILIMF_NO_ERROR;
2780}
2781
2782/*
2783address = mailbox / group
2784*/
2785
2786int mailimf_address_parse(const char * message, size_t length,
2787 size_t * index,
2788 struct mailimf_address ** result)
2789{
2790 int type;
2791 size_t cur_token;
2792 struct mailimf_mailbox * mailbox;
2793 struct mailimf_group * group;
2794 struct mailimf_address * address;
2795 int r;
2796 int res;
2797
2798 cur_token = * index;
2799
2800 mailbox = NULL;
2801 group = NULL;
2802
2803 type = MAILIMF_ADDRESS_ERROR; /* XXX - removes a gcc warning */
2804 r = mailimf_group_parse(message, length, &cur_token, &group);
2805 if (r == MAILIMF_NO_ERROR)
2806 type = MAILIMF_ADDRESS_GROUP;
2807
2808 if (r == MAILIMF_ERROR_PARSE) {
2809 r = mailimf_mailbox_parse(message, length, &cur_token, &mailbox);
2810 if (r == MAILIMF_NO_ERROR)
2811 type = MAILIMF_ADDRESS_MAILBOX;
2812 }
2813
2814 if (r != MAILIMF_NO_ERROR) {
2815 res = r;
2816 goto err;
2817 }
2818
2819 address = mailimf_address_new(type, mailbox, group);
2820 if (address == NULL) {
2821 res = MAILIMF_ERROR_MEMORY;
2822 goto free;
2823 }
2824
2825 * result = address;
2826 * index = cur_token;
2827
2828 return MAILIMF_NO_ERROR;
2829
2830 free:
2831 if (mailbox != NULL)
2832 mailimf_mailbox_free(mailbox);
2833 if (group != NULL)
2834 mailimf_group_free(group);
2835 err:
2836 return res;
2837}
2838
2839
2840/*
2841mailbox = name-addr / addr-spec
2842*/
2843
2844
2845int mailimf_mailbox_parse(const char * message, size_t length,
2846 size_t * index,
2847 struct mailimf_mailbox ** result)
2848{
2849 size_t cur_token;
2850 char * display_name;
2851 struct mailimf_mailbox * mailbox;
2852 char * addr_spec;
2853 int r;
2854 int res;
2855
2856 cur_token = * index;
2857 display_name = NULL;
2858 addr_spec = NULL;
2859
2860 r = mailimf_name_addr_parse(message, length, &cur_token,
2861 &display_name, &addr_spec);
2862 if (r == MAILIMF_ERROR_PARSE)
2863 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2864
2865 if (r != MAILIMF_NO_ERROR) {
2866 res = r;
2867 goto err;
2868 }
2869
2870 mailbox = mailimf_mailbox_new(display_name, addr_spec);
2871 if (mailbox == NULL) {
2872 res = MAILIMF_ERROR_MEMORY;
2873 goto free;
2874 }
2875
2876 * result = mailbox;
2877 * index = cur_token;
2878
2879 return MAILIMF_NO_ERROR;
2880
2881 free:
2882 if (display_name != NULL)
2883 mailimf_display_name_free(display_name);
2884 if (addr_spec != NULL)
2885 mailimf_addr_spec_free(addr_spec);
2886 err:
2887 return res;
2888}
2889
2890/*
2891name-addr = [display-name] angle-addr
2892*/
2893
2894static int mailimf_name_addr_parse(const char * message, size_t length,
2895 size_t * index,
2896 char ** pdisplay_name,
2897 char ** pangle_addr)
2898{
2899 char * display_name;
2900 char * angle_addr;
2901 size_t cur_token;
2902 int r;
2903 int res;
2904
2905 cur_token = * index;
2906
2907 display_name = NULL;
2908 angle_addr = NULL;
2909
2910 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
2911 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
2912 res = r;
2913 goto err;
2914 }
2915
2916 r = mailimf_angle_addr_parse(message, length, &cur_token, &angle_addr);
2917 if (r != MAILIMF_NO_ERROR) {
2918 res = r;
2919 goto free_display_name;
2920 }
2921
2922 * pdisplay_name = display_name;
2923 * pangle_addr = angle_addr;
2924 * index = cur_token;
2925
2926 return MAILIMF_NO_ERROR;
2927
2928 free_display_name:
2929 if (display_name != NULL)
2930 mailimf_display_name_free(display_name);
2931 err:
2932 return res;
2933}
2934
2935/*
2936angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
2937*/
2938
2939static int mailimf_angle_addr_parse(const char * message, size_t length,
2940 size_t * index, char ** result)
2941{
2942 size_t cur_token;
2943 char * addr_spec;
2944 int r;
2945
2946 cur_token = * index;
2947
2948 r = mailimf_cfws_parse(message, length, &cur_token);
2949 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2950 return r;
2951
2952 r = mailimf_lower_parse(message, length, &cur_token);
2953 if (r != MAILIMF_NO_ERROR)
2954 return r;
2955
2956 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2957 if (r != MAILIMF_NO_ERROR)
2958 return r;
2959
2960 r = mailimf_greater_parse(message, length, &cur_token);
2961 if (r != MAILIMF_NO_ERROR) {
2962 free(addr_spec);
2963 return r;
2964 }
2965
2966 * result = addr_spec;
2967 * index = cur_token;
2968
2969 return MAILIMF_NO_ERROR;
2970}
2971
2972/*
2973group = display-name ":" [mailbox-list / CFWS] ";"
2974 [CFWS]
2975*/
2976
2977static int mailimf_group_parse(const char * message, size_t length,
2978 size_t * index,
2979 struct mailimf_group ** result)
2980{
2981 size_t cur_token;
2982 char * display_name;
2983 struct mailimf_mailbox_list * mailbox_list;
2984 struct mailimf_group * group;
2985 int r;
2986 int res;
2987
2988 cur_token = * index;
2989
2990 mailbox_list = NULL;
2991
2992 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
2993 if (r != MAILIMF_NO_ERROR) {
2994 res = r;
2995 goto err;
2996 }
2997
2998 r = mailimf_colon_parse(message, length, &cur_token);
2999 if (r != MAILIMF_NO_ERROR) {
3000 res = r;
3001 goto free_display_name;
3002 }
3003
3004 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list);
3005 switch (r) {
3006 case MAILIMF_NO_ERROR:
3007 break;
3008 case MAILIMF_ERROR_PARSE:
3009 r = mailimf_cfws_parse(message, length, &cur_token);
3010 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3011 return r;
3012 break;
3013 default:
3014 return r;
3015 }
3016
3017 r = mailimf_semi_colon_parse(message, length, &cur_token);
3018 if (r != MAILIMF_NO_ERROR) {
3019 res = r;
3020 goto free_mailbox_list;
3021 }
3022
3023 group = mailimf_group_new(display_name, mailbox_list);
3024 if (group == NULL) {
3025 res = MAILIMF_ERROR_MEMORY;
3026 goto free_mailbox_list;
3027 }
3028
3029 * index = cur_token;
3030 * result = group;
3031
3032 return MAILIMF_NO_ERROR;
3033
3034 free_mailbox_list:
3035 mailimf_mailbox_list_free(mailbox_list);
3036 free_display_name:
3037 mailimf_display_name_free(display_name);
3038 err:
3039 return res;
3040}
3041
3042/*
3043display-name = phrase
3044*/
3045
3046static int mailimf_display_name_parse(const char * message, size_t length,
3047 size_t * index, char ** result)
3048{
3049 return mailimf_phrase_parse(message, length, index, result);
3050}
3051
3052/*
3053mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
3054*/
3055
3056int
3057mailimf_mailbox_list_parse(const char * message, size_t length,
3058 size_t * index,
3059 struct mailimf_mailbox_list ** result)
3060{
3061 size_t cur_token;
3062 clist * list;
3063 struct mailimf_mailbox_list * mailbox_list;
3064 int r;
3065 int res;
3066
3067 cur_token = * index;
3068
3069 r = mailimf_struct_list_parse(message, length,
3070 &cur_token, &list, ',',
3071 (mailimf_struct_parser *)
3072 mailimf_mailbox_parse,
3073 (mailimf_struct_destructor *)
3074 mailimf_mailbox_free);
3075 if (r != MAILIMF_NO_ERROR) {
3076 res = r;
3077 goto err;
3078 }
3079
3080 mailbox_list = mailimf_mailbox_list_new(list);
3081 if (mailbox_list == NULL) {
3082 res = MAILIMF_ERROR_MEMORY;
3083 goto free_list;
3084 }
3085
3086 * result = mailbox_list;
3087 * index = cur_token;
3088
3089 return MAILIMF_NO_ERROR;
3090
3091 free_list:
3092 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
3093 clist_free(list);
3094 err:
3095 return res;
3096 }
3097
3098/*
3099address-list = (address *("," address)) / obs-addr-list
3100*/
3101
3102
3103int
3104mailimf_address_list_parse(const char * message, size_t length,
3105 size_t * index,
3106 struct mailimf_address_list ** result)
3107{
3108 size_t cur_token;
3109 clist * list;
3110 struct mailimf_address_list * address_list;
3111 int r;
3112 int res;
3113
3114 cur_token = * index;
3115
3116 r = mailimf_struct_list_parse(message, length,
3117 &cur_token, &list, ',',
3118 (mailimf_struct_parser *)
3119 mailimf_address_parse,
3120 (mailimf_struct_destructor *)
3121 mailimf_address_free);
3122 if (r != MAILIMF_NO_ERROR) {
3123 res = r;
3124 goto err;
3125 }
3126
3127 address_list = mailimf_address_list_new(list);
3128 if (address_list == NULL) {
3129 res = MAILIMF_ERROR_MEMORY;
3130 goto free_list;
3131 }
3132
3133 * result = address_list;
3134 * index = cur_token;
3135
3136 return MAILIMF_NO_ERROR;
3137
3138 free_list:
3139 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
3140 clist_free(list);
3141 err:
3142 return res;
3143 }
3144
3145/*
3146addr-spec = local-part "@" domain
3147*/
3148
3149
3150static int mailimf_addr_spec_parse(const char * message, size_t length,
3151 size_t * index,
3152 char ** result)
3153{
3154 size_t cur_token;
3155#if 0
3156 char * local_part;
3157 char * domain;
3158#endif
3159 char * addr_spec;
3160 int r;
3161 int res;
3162 size_t begin;
3163 size_t end;
3164 int final;
3165 size_t count;
3166 const char * src;
3167 char * dest;
3168 size_t i;
3169
3170 cur_token = * index;
3171
3172 r = mailimf_cfws_parse(message, length, &cur_token);
3173 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3174 res = r;
3175 goto err;
3176 }
3177
3178 end = cur_token;
3179 if (end >= length) {
3180 res = MAILIMF_ERROR_PARSE;
3181 goto err;
3182 }
3183
3184 begin = cur_token;
3185
3186 final = FALSE;
3187 while (1) {
3188 switch (message[end]) {
3189 case '>':
3190 case ',':
3191 case '\r':
3192 case '\n':
3193 case '(':
3194 case ')':
3195 case ':':
3196 case ';':
3197 final = TRUE;
3198 break;
3199 }
3200
3201 if (final)
3202 break;
3203
3204 end ++;
3205 if (end >= length)
3206 break;
3207 }
3208
3209 if (end == begin) {
3210 res = MAILIMF_ERROR_PARSE;
3211 goto err;
3212 }
3213
3214 addr_spec = malloc(end - cur_token + 1);
3215 if (addr_spec == NULL) {
3216 res = MAILIMF_ERROR_MEMORY;
3217 goto err;
3218 }
3219
3220 count = end - cur_token;
3221 src = message + cur_token;
3222 dest = addr_spec;
3223 for(i = 0 ; i < count ; i ++) {
3224 if ((* src != ' ') && (* src != '\t')) {
3225 * dest = * src;
3226 dest ++;
3227 }
3228 src ++;
3229 }
3230 * dest = '\0';
3231
3232#if 0
3233 strncpy(addr_spec, message + cur_token, end - cur_token);
3234 addr_spec[end - cur_token] = '\0';
3235#endif
3236
3237 cur_token = end;
3238
3239#if 0
3240 r = mailimf_local_part_parse(message, length, &cur_token, &local_part);
3241 if (r != MAILIMF_NO_ERROR) {
3242 res = r;
3243 goto err;
3244 }
3245
3246 r = mailimf_at_sign_parse(message, length, &cur_token);
3247 switch (r) {
3248 case MAILIMF_NO_ERROR:
3249 r = mailimf_domain_parse(message, length, &cur_token, &domain);
3250 if (r != MAILIMF_NO_ERROR) {
3251 res = r;
3252 goto free_local_part;
3253 }
3254 break;
3255
3256 case MAILIMF_ERROR_PARSE:
3257 domain = NULL;
3258 break;
3259
3260 default:
3261 res = r;
3262 goto free_local_part;
3263 }
3264
3265 if (domain) {
3266 addr_spec = malloc(strlen(local_part) + strlen(domain) + 2);
3267 if (addr_spec == NULL) {
3268 res = MAILIMF_ERROR_MEMORY;
3269 goto free_domain;
3270 }
3271
3272 strcpy(addr_spec, local_part);
3273 strcat(addr_spec, "@");
3274 strcat(addr_spec, domain);
3275
3276 mailimf_domain_free(domain);
3277 mailimf_local_part_free(local_part);
3278 }
3279 else {
3280 addr_spec = local_part;
3281 }
3282#endif
3283
3284 * result = addr_spec;
3285 * index = cur_token;
3286
3287 return MAILIMF_NO_ERROR;
3288
3289#if 0
3290 free_domain:
3291 mailimf_domain_free(domain);
3292 free_local_part:
3293 mailimf_local_part_free(local_part);
3294#endif
3295 err:
3296 return res;
3297}
3298
3299/*
3300local-part = dot-atom / quoted-string / obs-local-part
3301*/
3302
3303#if 0
3304static int mailimf_local_part_parse(const char * message, size_t length,
3305 size_t * index,
3306 char ** result)
3307{
3308 int r;
3309
3310 r = mailimf_dot_atom_parse(message, length, index, result);
3311 switch (r) {
3312 case MAILIMF_NO_ERROR:
3313 return r;
3314 case MAILIMF_ERROR_PARSE:
3315 break;
3316 default:
3317 return r;
3318 }
3319
3320 r = mailimf_quoted_string_parse(message, length, index, result);
3321 if (r != MAILIMF_NO_ERROR)
3322 return r;
3323
3324 return MAILIMF_NO_ERROR;
3325}
3326#endif
3327
3328/*
3329domain = dot-atom / domain-literal / obs-domain
3330*/
3331
3332#if 0
3333static int mailimf_domain_parse(const char * message, size_t length,
3334 size_t * index,
3335 char ** result)
3336{
3337 int r;
3338
3339 r = mailimf_dot_atom_parse(message, length, index, result);
3340 switch (r) {
3341 case MAILIMF_NO_ERROR:
3342 return r;
3343 case MAILIMF_ERROR_PARSE:
3344 break;
3345 default:
3346 return r;
3347 }
3348
3349 r = mailimf_domain_literal_parse(message, length, index, result);
3350 if (r != MAILIMF_NO_ERROR)
3351 return r;
3352
3353 return MAILIMF_NO_ERROR;
3354}
3355#endif
3356
3357/*
3358[FWS] dcontent
3359*/
3360
3361#if 0
3362static int
3363mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length,
3364 size_t * index)
3365{
3366 size_t cur_token;
3367 char ch;
3368 int r;
3369
3370 cur_token = * index;
3371
3372 r = mailimf_cfws_parse(message, length, &cur_token);
3373 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3374 return r;
3375
3376 r = mailimf_dcontent_parse(message, length, &cur_token, &ch);
3377 if (r != MAILIMF_NO_ERROR)
3378 return r;
3379
3380 * index = cur_token;
3381
3382 return MAILIMF_NO_ERROR;
3383}
3384#endif
3385
3386/*
3387domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
3388*/
3389
3390#if 0
3391static int mailimf_domain_literal_parse(const char * message, size_t length,
3392 size_t * index, char ** result)
3393{
3394 size_t cur_token;
3395 int len;
3396 int begin;
3397 char * domain_literal;
3398 int r;
3399
3400 cur_token = * index;
3401
3402 r = mailimf_cfws_parse(message, length, &cur_token);
3403 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3404 return r;
3405
3406 begin = cur_token;
3407 r = mailimf_obracket_parse(message, length, &cur_token);
3408 if (r != MAILIMF_NO_ERROR)
3409 return r;
3410
3411 while (1) {
3412 r = mailimf_domain_literal_fws_dcontent_parse(message, length,
3413 &cur_token);
3414 if (r == MAILIMF_NO_ERROR) {
3415 /* do nothing */
3416 }
3417 else if (r == MAILIMF_ERROR_PARSE)
3418 break;
3419 else
3420 return r;
3421 }
3422
3423 r = mailimf_fws_parse(message, length, &cur_token);
3424 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3425 return r;
3426
3427 r = mailimf_cbracket_parse(message, length, &cur_token);
3428 if (r != MAILIMF_NO_ERROR)
3429 return r;
3430
3431 len = cur_token - begin;
3432
3433 domain_literal = malloc(len + 1);
3434 if (domain_literal == NULL)
3435 return MAILIMF_ERROR_MEMORY;
3436 strncpy(domain_literal, message + begin, len);
3437 domain_literal[len] = '\0';
3438
3439 * result = domain_literal;
3440 * index = cur_token;
3441
3442 return MAILIMF_NO_ERROR;
3443}
3444#endif
3445
3446/*
3447dcontent = dtext / quoted-pair
3448*/
3449
3450#if 0
3451static int mailimf_dcontent_parse(const char * message, size_t length,
3452 size_t * index, char * result)
3453{
3454 size_t cur_token;
3455 char ch;
3456 int r;
3457
3458 cur_token = * index;
3459
3460 if (cur_token >= length)
3461 return MAILIMF_ERROR_PARSE;
3462
3463 if (is_dtext(message[cur_token])) {
3464 ch = message[cur_token];
3465 cur_token ++;
3466 }
3467 else {
3468 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
3469
3470 if (r != MAILIMF_NO_ERROR)
3471 return r;
3472 }
3473
3474 * index = cur_token;
3475 * result = ch;
3476
3477 return MAILIMF_NO_ERROR;
3478}
3479#endif
3480
3481
3482/*
3483dtext = NO-WS-CTL / ; Non white space controls
3484
3485 %d33-90 / ; The rest of the US-ASCII
3486 %d94-126 ; characters not including "[",
3487 ; "]", or "\"
3488*/
3489
3490static inline int is_dtext(char ch)
3491{
3492 unsigned char uch = (unsigned char) ch;
3493
3494 if (is_no_ws_ctl(ch))
3495 return TRUE;
3496
3497 if (uch < 33)
3498 return FALSE;
3499
3500 if ((uch >= 91) && (uch <= 93))
3501 return FALSE;
3502
3503 if (uch == 127)
3504 return FALSE;
3505
3506 return TRUE;
3507}
3508
3509/*
3510message = (fields / obs-fields)
3511 [CRLF body]
3512*/
3513
3514int mailimf_message_parse(const char * message, size_t length,
3515 size_t * index,
3516 struct mailimf_message ** result)
3517{
3518 struct mailimf_fields * fields;
3519 struct mailimf_body * body;
3520 struct mailimf_message * msg;
3521 size_t cur_token;
3522 int r;
3523 int res;
3524
3525 cur_token = * index;
3526
3527 r = mailimf_fields_parse(message, length, &cur_token, &fields);
3528 if (r != MAILIMF_NO_ERROR) {
3529 res = r;
3530 goto err;
3531 }
3532
3533 r = mailimf_crlf_parse(message, length, &cur_token);
3534 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3535 res = r;
3536 goto err;
3537 }
3538
3539 r = mailimf_body_parse(message, length, &cur_token, &body);
3540 if (r != MAILIMF_NO_ERROR) {
3541 res = r;
3542 goto free_fields;
3543 }
3544
3545 msg = mailimf_message_new(fields, body);
3546 if (msg == NULL) {
3547 res = MAILIMF_ERROR_MEMORY;
3548 goto free_body;
3549 }
3550
3551 * index = cur_token;
3552 * result = msg;
3553
3554 return MAILIMF_NO_ERROR;
3555
3556 free_body:
3557 mailimf_body_free(body);
3558 free_fields:
3559 mailimf_fields_free(fields);
3560 err:
3561 return res;
3562}
3563
3564/*
3565body = *(*998text CRLF) *998text
3566*/
3567
3568int mailimf_body_parse(const char * message, size_t length,
3569 size_t * index,
3570 struct mailimf_body ** result)
3571{
3572 size_t cur_token;
3573 struct mailimf_body * body;
3574
3575 cur_token = * index;
3576
3577 body = mailimf_body_new(message + cur_token, length - cur_token);
3578 if (body == NULL)
3579 return MAILIMF_ERROR_MEMORY;
3580
3581 cur_token = length;
3582
3583 * result = body;
3584 * index = cur_token;
3585
3586 return MAILIMF_NO_ERROR;
3587}
3588
3589/*
3590CHANGE TO THE RFC 2822
3591
3592original :
3593
3594fields = *(trace
3595 *(resent-date /
3596 resent-from /
3597 resent-sender /
3598 resent-to /
3599 resent-cc /
3600 resent-bcc /
3601 resent-msg-id))
3602 *(orig-date /
3603 from /
3604 sender /
3605 reply-to /
3606 to /
3607 cc /
3608 bcc /
3609 message-id /
3610 in-reply-to /
3611 references /
3612 subject /
3613 comments /
3614 keywords /
3615 optional-field)
3616
3617INTO THE FOLLOWING :
3618*/
3619
3620/*
3621resent-fields-list = *(resent-date /
3622 resent-from /
3623 resent-sender /
3624 resent-to /
3625 resent-cc /
3626 resent-bcc /
3627 resent-msg-id))
3628*/
3629
3630#if 0
3631enum {
3632 RESENT_HEADER_START,
3633};
3634
3635static int guess_resent_header_type(char * message,
3636 size_t length, size_t index)
3637{
3638 int r;
3639
3640 r = mailimf_token_case_insensitive_parse(message,
3641 length, &index, "Resent-");
3642 if (r != MAILIMF_NO_ERROR)
3643 return MAILIMF_RESENT_FIELD_NONE;
3644
3645 if (index >= length)
3646 return MAILIMF_RESENT_FIELD_NONE;
3647
3648 switch(toupper(message[index])) {
3649 case 'D':
3650 return MAILIMF_RESENT_FIELD_DATE;
3651 case 'F':
3652 return MAILIMF_RESENT_FIELD_FROM;
3653 case 'S':
3654 return MAILIMF_RESENT_FIELD_SENDER;
3655 case 'T':
3656 return MAILIMF_RESENT_FIELD_TO;
3657 case 'C':
3658 return MAILIMF_RESENT_FIELD_CC;
3659 case 'B':
3660 return MAILIMF_RESENT_FIELD_BCC;
3661 case 'M':
3662 return MAILIMF_RESENT_FIELD_MSG_ID;
3663 default:
3664 return MAILIMF_RESENT_FIELD_NONE;
3665 }
3666}
3667#endif
3668
3669#if 0
3670static int
3671mailimf_resent_field_parse(const char * message, size_t length,
3672 size_t * index,
3673 struct mailimf_resent_field ** result)
3674{
3675 struct mailimf_orig_date * resent_date;
3676 struct mailimf_from * resent_from;
3677 struct mailimf_sender * resent_sender;
3678 struct mailimf_to* resent_to;
3679 struct mailimf_cc * resent_cc;
3680 struct mailimf_bcc * resent_bcc;
3681 struct mailimf_message_id * resent_msg_id;
3682 size_t cur_token;
3683 int type;
3684 struct mailimf_resent_field * resent_field;
3685 int r;
3686 int res;
3687
3688 cur_token = * index;
3689
3690 resent_date = NULL;
3691 resent_from = NULL;
3692 resent_sender = NULL;
3693 resent_to = NULL;
3694 resent_cc = NULL;
3695 resent_bcc = NULL;
3696 resent_msg_id = NULL;
3697
3698 type = guess_resent_header_type(message, length, cur_token);
3699
3700 switch(type) {
3701 case MAILIMF_RESENT_FIELD_DATE:
3702 r = mailimf_resent_date_parse(message, length, &cur_token,
3703 &resent_date);
3704 if (r != MAILIMF_NO_ERROR) {
3705 res = r;
3706 goto err;
3707 }
3708 break;
3709 case MAILIMF_RESENT_FIELD_FROM:
3710 r = mailimf_resent_from_parse(message, length, &cur_token,
3711 &resent_from);
3712 if (r != MAILIMF_NO_ERROR) {
3713 res = r;
3714 goto err;
3715 }
3716 break;
3717 case MAILIMF_RESENT_FIELD_SENDER:
3718 r = mailimf_resent_sender_parse(message, length, &cur_token,
3719 &resent_sender);
3720 if (r != MAILIMF_NO_ERROR) {
3721 res = r;
3722 goto err;
3723 }
3724 break;
3725 case MAILIMF_RESENT_FIELD_TO:
3726 r = mailimf_resent_to_parse(message, length, &cur_token,
3727 &resent_to);
3728 if (r != MAILIMF_NO_ERROR) {
3729 res = r;
3730 goto err;
3731 }
3732 break;
3733 case MAILIMF_RESENT_FIELD_CC:
3734 r= mailimf_resent_cc_parse(message, length, &cur_token,
3735 &resent_cc);
3736 if (r != MAILIMF_NO_ERROR) {
3737 res = r;
3738 goto err;
3739 }
3740 break;
3741 case MAILIMF_RESENT_FIELD_BCC:
3742 r = mailimf_resent_bcc_parse(message, length, &cur_token,
3743 &resent_bcc);
3744 if (r != MAILIMF_NO_ERROR) {
3745 res = r;
3746 goto err;
3747 }
3748 break;
3749 case MAILIMF_RESENT_FIELD_MSG_ID:
3750 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
3751 &resent_msg_id);
3752 if (r != MAILIMF_NO_ERROR) {
3753 res = r;
3754 goto err;
3755 }
3756 break;
3757 default:
3758 res = MAILIMF_ERROR_PARSE;
3759 goto err;
3760 }
3761
3762 resent_field = mailimf_resent_field_new(type, resent_date,
3763 resent_from, resent_sender,
3764 resent_to, resent_cc,
3765 resent_bcc, resent_msg_id);
3766 if (resent_field == NULL) {
3767 res = MAILIMF_ERROR_MEMORY;
3768 goto free_resent;
3769 }
3770
3771 * result = resent_field;
3772 * index = cur_token;
3773
3774 return MAILIMF_NO_ERROR;
3775
3776 free_resent:
3777 if (resent_msg_id != NULL)
3778 mailimf_message_id_free(resent_msg_id);
3779 if (resent_bcc != NULL)
3780 mailimf_bcc_free(resent_bcc);
3781 if (resent_cc != NULL)
3782 mailimf_cc_free(resent_cc);
3783 if (resent_to != NULL)
3784 mailimf_to_free(resent_to);
3785 if (resent_sender != NULL)
3786 mailimf_sender_free(resent_sender);
3787 if (resent_from != NULL)
3788 mailimf_from_free(resent_from);
3789 if (resent_date != NULL)
3790 mailimf_orig_date_free(resent_date);
3791 err:
3792 return res;
3793}
3794#endif
3795
3796#if 0
3797static int
3798mailimf_resent_fields_list_parse(const char * message, size_t length,
3799 size_t * index,
3800 struct mailimf_resent_fields_list ** result)
3801{
3802 clist * list;
3803 size_t cur_token;
3804 struct mailimf_resent_fields_list * resent_fields_list;
3805 int r;
3806 int res;
3807
3808 cur_token = * index;
3809 list = NULL;
3810
3811 r = mailimf_struct_multiple_parse(message, length, &cur_token, &list,
3812 (mailimf_struct_parser *)
3813 mailimf_resent_field_parse,
3814 (mailimf_struct_destructor *)
3815 mailimf_resent_field_free);
3816 if (r != MAILIMF_NO_ERROR) {
3817 res = r;
3818 goto err;
3819 }
3820
3821 resent_fields_list = mailimf_resent_fields_list_new(list);
3822 if (resent_fields_list == NULL) {
3823 res = MAILIMF_ERROR_MEMORY;
3824 goto free_list;
3825 }
3826
3827 * result = resent_fields_list;
3828 * index = cur_token;
3829
3830 return MAILIMF_NO_ERROR;
3831
3832 free_list:
3833 clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL);
3834 clist_free(list);
3835 err:
3836 return res;
3837}
3838#endif
3839
3840/*
3841 ([trace]
3842 [resent-fields-list])
3843*/
3844
3845#if 0
3846static int
3847mailimf_trace_resent_fields_parse(const char * message, size_t length,
3848 size_t * index,
3849 struct mailimf_trace_resent_fields ** result)
3850{
3851 size_t cur_token;
3852 struct mailimf_return * return_path;
3853 struct mailimf_resent_fields_list * resent_fields;
3854 struct mailimf_trace_resent_fields * trace_resent_fields;
3855 int res;
3856 int r;
3857
3858 cur_token = * index;
3859
3860 return_path = NULL;
3861 resent_fields = NULL;
3862
3863 r = mailimf_return_parse(message, length, &cur_token,
3864 &return_path);
3865 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3866 res = r;
3867 goto err;
3868 }
3869
3870 r = mailimf_resent_fields_list_parse(message, length, &cur_token,
3871 &resent_fields);
3872 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3873 res = r;
3874 goto err;
3875 }
3876
3877 if ((return_path == NULL) && (resent_fields == NULL)) {
3878 res = MAILIMF_ERROR_PARSE;
3879 goto err;
3880 }
3881
3882 trace_resent_fields = mailimf_trace_resent_fields_new(return_path,
3883 resent_fields);
3884 if (trace_resent_fields == NULL) {
3885 res = MAILIMF_ERROR_MEMORY;
3886 goto free_resent_fields;
3887 }
3888
3889 * result = trace_resent_fields;
3890 * index = cur_token;
3891
3892 return MAILIMF_NO_ERROR;
3893
3894 free_resent_fields:
3895 if (resent_fields != NULL)
3896 mailimf_resent_fields_list_free(resent_fields);
3897 if (return_path != NULL)
3898 mailimf_return_free(return_path);
3899 err:
3900 return res;
3901}
3902#endif
3903
3904/*
3905delivering-info = *([trace]
3906 [resent-fields-list])
3907*/
3908
3909#if 0
3910static int
3911mailimf_delivering_info_parse(const char * message, size_t length,
3912 size_t * index,
3913 struct mailimf_delivering_info ** result)
3914{
3915 size_t cur_token;
3916 clist * list;
3917 struct mailimf_delivering_info * delivering_info;
3918 int r;
3919 int res;
3920
3921 cur_token = * index;
3922
3923 r = mailimf_struct_multiple_parse(message, length, &cur_token,
3924 &list,
3925 (mailimf_struct_parser *)
3926 mailimf_trace_resent_fields_parse,
3927 (mailimf_struct_destructor *)
3928 mailimf_trace_resent_fields_free);
3929 if (r != MAILIMF_NO_ERROR) {
3930 res = r;
3931 goto err;
3932 }
3933
3934 delivering_info = mailimf_delivering_info_new(list);
3935 if (delivering_info == NULL) {
3936 res = MAILIMF_ERROR_MEMORY;
3937 goto free_list;
3938 }
3939
3940 * result = delivering_info;
3941 * index = cur_token;
3942
3943 return MAILIMF_NO_ERROR;
3944
3945 free_list:
3946 clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL);
3947 clist_free(list);
3948 err:
3949 return res;
3950}
3951#endif
3952
3953/*
3954field = delivering-info /
3955 orig-date /
3956 from /
3957 sender /
3958 reply-to /
3959 to /
3960 cc /
3961 bcc /
3962 message-id /
3963 in-reply-to /
3964 references /
3965 subject /
3966 comments /
3967 keywords /
3968 optional-field
3969*/
3970
3971enum {
3972 HEADER_START,
3973 HEADER_C,
3974 HEADER_R,
3975 HEADER_RE,
3976 HEADER_S,
3977 HEADER_RES,
3978};
3979
3980static int guess_header_type(const char * message, size_t length, size_t index)
3981{
3982 int state;
3983 int r;
3984
3985 state = HEADER_START;
3986
3987 while (1) {
3988
3989 if (index >= length)
3990 return MAILIMF_FIELD_NONE;
3991
3992 switch(state) {
3993 case HEADER_START:
3994 switch((char) toupper((unsigned char) message[index])) {
3995 case 'B':
3996 return MAILIMF_FIELD_BCC;
3997 case 'C':
3998 state = HEADER_C;
3999 break;
4000 case 'D':
4001 return MAILIMF_FIELD_ORIG_DATE;
4002 case 'F':
4003 return MAILIMF_FIELD_FROM;
4004 case 'I':
4005 return MAILIMF_FIELD_IN_REPLY_TO;
4006 case 'K':
4007 return MAILIMF_FIELD_KEYWORDS;
4008 case 'M':
4009 return MAILIMF_FIELD_MESSAGE_ID;
4010 case 'R':
4011 state = HEADER_R;
4012 break;
4013 case 'T':
4014 return MAILIMF_FIELD_TO;
4015 break;
4016 case 'S':
4017 state = HEADER_S;
4018 break;
4019 default:
4020 return MAILIMF_FIELD_NONE;
4021 }
4022 break;
4023 case HEADER_C:
4024 switch((char) toupper((unsigned char) message[index])) {
4025 case 'O':
4026 return MAILIMF_FIELD_COMMENTS;
4027 case 'C':
4028 return MAILIMF_FIELD_CC;
4029 default:
4030 return MAILIMF_FIELD_NONE;
4031 }
4032 break;
4033 case HEADER_R:
4034 switch((char) toupper((unsigned char) message[index])) {
4035 case 'E':
4036 state = HEADER_RE;
4037 break;
4038 default:
4039 return MAILIMF_FIELD_NONE;
4040 }
4041 break;
4042 case HEADER_RE:
4043 switch((char) toupper((unsigned char) message[index])) {
4044 case 'F':
4045 return MAILIMF_FIELD_REFERENCES;
4046 case 'P':
4047 return MAILIMF_FIELD_REPLY_TO;
4048 case 'S':
4049 state = HEADER_RES;
4050 break;
4051 case 'T':
4052 return MAILIMF_FIELD_RETURN_PATH;
4053 default:
4054 return MAILIMF_FIELD_NONE;
4055 }
4056 break;
4057 case HEADER_S:
4058 switch((char) toupper((unsigned char) message[index])) {
4059 case 'E':
4060 return MAILIMF_FIELD_SENDER;
4061 case 'U':
4062 return MAILIMF_FIELD_SUBJECT;
4063 default:
4064 return MAILIMF_FIELD_NONE;
4065 }
4066 break;
4067
4068 case HEADER_RES:
4069 r = mailimf_token_case_insensitive_parse(message,
4070 length, &index, "ent-");
4071 if (r != MAILIMF_NO_ERROR)
4072 return MAILIMF_FIELD_NONE;
4073
4074 if (index >= length)
4075 return MAILIMF_FIELD_NONE;
4076
4077 switch((char) toupper((unsigned char) message[index])) {
4078 case 'D':
4079 return MAILIMF_FIELD_RESENT_DATE;
4080 case 'F':
4081 return MAILIMF_FIELD_RESENT_FROM;
4082 case 'S':
4083 return MAILIMF_FIELD_RESENT_SENDER;
4084 case 'T':
4085 return MAILIMF_FIELD_RESENT_TO;
4086 case 'C':
4087 return MAILIMF_FIELD_RESENT_CC;
4088 case 'B':
4089 return MAILIMF_FIELD_RESENT_BCC;
4090 case 'M':
4091 return MAILIMF_FIELD_RESENT_MSG_ID;
4092 default:
4093 return MAILIMF_FIELD_NONE;
4094 }
4095 break;
4096 }
4097 index ++;
4098 }
4099}
4100
4101static int mailimf_field_parse(const char * message, size_t length,
4102 size_t * index,
4103 struct mailimf_field ** result)
4104{
4105 size_t cur_token;
4106 int type;
4107 struct mailimf_return * return_path;
4108 struct mailimf_orig_date * resent_date;
4109 struct mailimf_from * resent_from;
4110 struct mailimf_sender * resent_sender;
4111 struct mailimf_to* resent_to;
4112 struct mailimf_cc * resent_cc;
4113 struct mailimf_bcc * resent_bcc;
4114 struct mailimf_message_id * resent_msg_id;
4115 struct mailimf_orig_date * orig_date;
4116 struct mailimf_from * from;
4117 struct mailimf_sender * sender;
4118 struct mailimf_reply_to * reply_to;
4119 struct mailimf_to * to;
4120 struct mailimf_cc * cc;
4121 struct mailimf_bcc * bcc;
4122 struct mailimf_message_id * message_id;
4123 struct mailimf_in_reply_to * in_reply_to;
4124 struct mailimf_references * references;
4125 struct mailimf_subject * subject;
4126 struct mailimf_comments * comments;
4127 struct mailimf_keywords * keywords;
4128 struct mailimf_optional_field * optional_field;
4129 struct mailimf_field * field;
4130 int guessed_type;
4131 int r;
4132 int res;
4133
4134 cur_token = * index;
4135
4136 return_path = NULL;
4137 resent_date = NULL;
4138 resent_from = NULL;
4139 resent_sender = NULL;
4140 resent_to = NULL;
4141 resent_cc = NULL;
4142 resent_bcc = NULL;
4143 resent_msg_id = NULL;
4144 orig_date = NULL;
4145 from = NULL;
4146 sender = NULL;
4147 reply_to = NULL;
4148 to = NULL;
4149 cc = NULL;
4150 bcc = NULL;
4151 message_id = NULL;
4152 in_reply_to = NULL;
4153 references = NULL;
4154 subject = NULL;
4155 comments = NULL;
4156 keywords = NULL;
4157 optional_field = NULL;
4158
4159 guessed_type = guess_header_type(message, length, cur_token);
4160 type = MAILIMF_FIELD_NONE;
4161
4162 switch (guessed_type) {
4163 case MAILIMF_FIELD_ORIG_DATE:
4164 r = mailimf_orig_date_parse(message, length, &cur_token,
4165 &orig_date);
4166 if (r == MAILIMF_NO_ERROR)
4167 type = MAILIMF_FIELD_ORIG_DATE;
4168 else if (r == MAILIMF_ERROR_PARSE) {
4169 /* do nothing */
4170 }
4171 else {
4172 res = r;
4173 goto err;
4174 }
4175 break;
4176 case MAILIMF_FIELD_FROM:
4177 r = mailimf_from_parse(message, length, &cur_token,
4178 &from);
4179 if (r == MAILIMF_NO_ERROR)
4180 type = guessed_type;
4181 else if (r == MAILIMF_ERROR_PARSE) {
4182 /* do nothing */
4183 }
4184 else {
4185 res = r;
4186 goto err;
4187 }
4188 break;
4189 case MAILIMF_FIELD_SENDER:
4190 r = mailimf_sender_parse(message, length, &cur_token,
4191 &sender);
4192 if (r == MAILIMF_NO_ERROR)
4193 type = guessed_type;
4194 else if (r == MAILIMF_ERROR_PARSE) {
4195 /* do nothing */
4196 }
4197 else {
4198 res = r;
4199 goto err;
4200 }
4201 break;
4202 case MAILIMF_FIELD_REPLY_TO:
4203 r = mailimf_reply_to_parse(message, length, &cur_token,
4204 &reply_to);
4205 if (r == MAILIMF_NO_ERROR)
4206 type = guessed_type;
4207 else if (r == MAILIMF_ERROR_PARSE) {
4208 /* do nothing */
4209 }
4210 else {
4211 res = r;
4212 goto err;
4213 }
4214 break;
4215 case MAILIMF_FIELD_TO:
4216 r = mailimf_to_parse(message, length, &cur_token,
4217 &to);
4218 if (r == MAILIMF_NO_ERROR)
4219 type = guessed_type;
4220 else if (r == MAILIMF_ERROR_PARSE) {
4221 /* do nothing */
4222 }
4223 else {
4224 res = r;
4225 goto err;
4226 }
4227 break;
4228 case MAILIMF_FIELD_CC:
4229 r = mailimf_cc_parse(message, length, &cur_token,
4230 &cc);
4231 if (r == MAILIMF_NO_ERROR)
4232 type = guessed_type;
4233 else if (r == MAILIMF_ERROR_PARSE) {
4234 /* do nothing */
4235 }
4236 else {
4237 res = r;
4238 goto err;
4239 }
4240 break;
4241 case MAILIMF_FIELD_BCC:
4242 r = mailimf_bcc_parse(message, length, &cur_token,
4243 &bcc);
4244 if (r == MAILIMF_NO_ERROR)
4245 type = guessed_type;
4246 else if (r == MAILIMF_ERROR_PARSE) {
4247 /* do nothing */
4248 }
4249 else {
4250 res = r;
4251 goto err;
4252 }
4253 break;
4254 case MAILIMF_FIELD_MESSAGE_ID:
4255 r = mailimf_message_id_parse(message, length, &cur_token,
4256 &message_id);
4257 if (r == MAILIMF_NO_ERROR)
4258 type = guessed_type;
4259 else if (r == MAILIMF_ERROR_PARSE) {
4260 /* do nothing */
4261 }
4262 else {
4263 res = r;
4264 goto err;
4265 }
4266 break;
4267 case MAILIMF_FIELD_IN_REPLY_TO:
4268 r = mailimf_in_reply_to_parse(message, length, &cur_token,
4269 &in_reply_to);
4270 if (r == MAILIMF_NO_ERROR)
4271 type = guessed_type;
4272 else if (r == MAILIMF_ERROR_PARSE) {
4273 /* do nothing */
4274 }
4275 else {
4276 res = r;
4277 goto err;
4278 }
4279 break;
4280 case MAILIMF_FIELD_REFERENCES:
4281 r = mailimf_references_parse(message, length, &cur_token,
4282 &references);
4283 if (r == MAILIMF_NO_ERROR)
4284 type = guessed_type;
4285 else if (r == MAILIMF_ERROR_PARSE) {
4286 /* do nothing */
4287 }
4288 else {
4289 res = r;
4290 goto err;
4291 }
4292 break;
4293 case MAILIMF_FIELD_SUBJECT:
4294 r = mailimf_subject_parse(message, length, &cur_token,
4295 &subject);
4296 if (r == MAILIMF_NO_ERROR)
4297 type = guessed_type;
4298 else if (r == MAILIMF_ERROR_PARSE) {
4299 /* do nothing */
4300 }
4301 else {
4302 res = r;
4303 goto err;
4304 }
4305 break;
4306 case MAILIMF_FIELD_COMMENTS:
4307 r = mailimf_comments_parse(message, length, &cur_token,
4308 &comments);
4309 if (r == MAILIMF_NO_ERROR)
4310 type = guessed_type;
4311 else if (r == MAILIMF_ERROR_PARSE) {
4312 /* do nothing */
4313 }
4314 else {
4315 res = r;
4316 goto err;
4317 }
4318 break;
4319 case MAILIMF_FIELD_KEYWORDS:
4320 r = mailimf_keywords_parse(message, length, &cur_token,
4321 &keywords);
4322 if (r == MAILIMF_NO_ERROR)
4323 type = guessed_type;
4324 else if (r == MAILIMF_ERROR_PARSE) {
4325 /* do nothing */
4326 }
4327 else {
4328 res = r;
4329 goto err;
4330 }
4331 break;
4332 case MAILIMF_FIELD_RETURN_PATH:
4333 r = mailimf_return_parse(message, length, &cur_token,
4334 &return_path);
4335 if (r == MAILIMF_NO_ERROR)
4336 type = guessed_type;
4337 else if (r == MAILIMF_ERROR_PARSE) {
4338 /* do nothing */
4339 }
4340 else {
4341 res = r;
4342 goto err;
4343 }
4344 break;
4345 case MAILIMF_FIELD_RESENT_DATE:
4346 r = mailimf_resent_date_parse(message, length, &cur_token,
4347 &resent_date);
4348 if (r == MAILIMF_NO_ERROR)
4349 type = guessed_type;
4350 else if (r == MAILIMF_ERROR_PARSE) {
4351 /* do nothing */
4352 }
4353 else {
4354 res = r;
4355 goto err;
4356 }
4357 break;
4358 case MAILIMF_FIELD_RESENT_FROM:
4359 r = mailimf_resent_from_parse(message, length, &cur_token,
4360 &resent_from);
4361 if (r == MAILIMF_NO_ERROR)
4362 type = guessed_type;
4363 else if (r == MAILIMF_ERROR_PARSE) {
4364 /* do nothing */
4365 }
4366 else {
4367 res = r;
4368 goto err;
4369 }
4370 break;
4371 case MAILIMF_FIELD_RESENT_SENDER:
4372 r = mailimf_resent_sender_parse(message, length, &cur_token,
4373 &resent_sender);
4374 if (r == MAILIMF_NO_ERROR)
4375 type = guessed_type;
4376 else if (r == MAILIMF_ERROR_PARSE) {
4377 /* do nothing */
4378 }
4379 else {
4380 res = r;
4381 goto err;
4382 }
4383 break;
4384 case MAILIMF_FIELD_RESENT_TO:
4385 r = mailimf_resent_to_parse(message, length, &cur_token,
4386 &resent_to);
4387 if (r == MAILIMF_NO_ERROR)
4388 type = guessed_type;
4389 else if (r == MAILIMF_ERROR_PARSE) {
4390 /* do nothing */
4391 }
4392 else {
4393 res = r;
4394 goto err;
4395 }
4396 break;
4397 case MAILIMF_FIELD_RESENT_CC:
4398 r= mailimf_resent_cc_parse(message, length, &cur_token,
4399 &resent_cc);
4400 if (r == MAILIMF_NO_ERROR)
4401 type = guessed_type;
4402 else if (r == MAILIMF_ERROR_PARSE) {
4403 /* do nothing */
4404 }
4405 else {
4406 res = r;
4407 goto err;
4408 }
4409 break;
4410 case MAILIMF_FIELD_RESENT_BCC:
4411 r = mailimf_resent_bcc_parse(message, length, &cur_token,
4412 &resent_bcc);
4413 if (r == MAILIMF_NO_ERROR)
4414 type = guessed_type;
4415 else if (r == MAILIMF_ERROR_PARSE) {
4416 /* do nothing */
4417 }
4418 else {
4419 res = r;
4420 goto err;
4421 }
4422 break;
4423 case MAILIMF_FIELD_RESENT_MSG_ID:
4424 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
4425 &resent_msg_id);
4426 if (r == MAILIMF_NO_ERROR)
4427 type = guessed_type;
4428 else if (r == MAILIMF_ERROR_PARSE) {
4429 /* do nothing */
4430 }
4431 else {
4432 res = r;
4433 goto err;
4434 }
4435 break;
4436 }
4437
4438 if (type == MAILIMF_FIELD_NONE) {
4439 r = mailimf_optional_field_parse(message, length, &cur_token,
4440 &optional_field);
4441 if (r != MAILIMF_NO_ERROR) {
4442 res = r;
4443 goto err;
4444 }
4445
4446 type = MAILIMF_FIELD_OPTIONAL_FIELD;
4447 }
4448
4449 field = mailimf_field_new(type, return_path, resent_date,
4450 resent_from, resent_sender, resent_to, resent_cc, resent_bcc,
4451 resent_msg_id, orig_date, from, sender, reply_to, to,
4452 cc, bcc, message_id, in_reply_to, references,
4453 subject, comments, keywords, optional_field);
4454 if (field == NULL) {
4455 res = MAILIMF_ERROR_MEMORY;
4456 goto free_field;
4457 }
4458
4459 * result = field;
4460 * index = cur_token;
4461
4462 return MAILIMF_NO_ERROR;
4463
4464 free_field:
4465 if (return_path != NULL)
4466 mailimf_return_free(return_path);
4467 if (resent_date != NULL)
4468 mailimf_orig_date_free(resent_date);
4469 if (resent_from != NULL)
4470 mailimf_from_free(resent_from);
4471 if (resent_sender != NULL)
4472 mailimf_sender_free(resent_sender);
4473 if (resent_to != NULL)
4474 mailimf_to_free(resent_to);
4475 if (resent_cc != NULL)
4476 mailimf_cc_free(resent_cc);
4477 if (resent_bcc != NULL)
4478 mailimf_bcc_free(resent_bcc);
4479 if (resent_msg_id != NULL)
4480 mailimf_message_id_free(resent_msg_id);
4481 if (orig_date != NULL)
4482 mailimf_orig_date_free(orig_date);
4483 if (from != NULL)
4484 mailimf_from_free(from);
4485 if (sender != NULL)
4486 mailimf_sender_free(sender);
4487 if (reply_to != NULL)
4488 mailimf_reply_to_free(reply_to);
4489 if (to != NULL)
4490 mailimf_to_free(to);
4491 if (cc != NULL)
4492 mailimf_cc_free(cc);
4493 if (bcc != NULL)
4494 mailimf_bcc_free(bcc);
4495 if (message_id != NULL)
4496 mailimf_message_id_free(message_id);
4497 if (in_reply_to != NULL)
4498 mailimf_in_reply_to_free(in_reply_to);
4499 if (references != NULL)
4500 mailimf_references_free(references);
4501 if (subject != NULL)
4502 mailimf_subject_free(subject);
4503 if (comments != NULL)
4504 mailimf_comments_free(comments);
4505 if (keywords != NULL)
4506 mailimf_keywords_free(keywords);
4507 if (optional_field != NULL)
4508 mailimf_optional_field_free(optional_field);
4509 err:
4510 return res;
4511}
4512
4513
4514/*
4515fields = *(delivering-info /
4516 orig-date /
4517 from /
4518 sender /
4519 reply-to /
4520 to /
4521 cc /
4522 bcc /
4523 message-id /
4524 in-reply-to /
4525 references /
4526 subject /
4527 comments /
4528 keywords /
4529 optional-field)
4530*/
4531
4532#if 0
4533int
4534mailimf_unparsed_fields_parse(const char * message, size_t length,
4535 size_t * index,
4536 struct mailimf_unparsed_fields ** result)
4537{
4538 size_t cur_token;
4539 clist * list;
4540 struct mailimf_unparsed_fields * fields;
4541 int r;
4542 int res;
4543
4544 cur_token = * index;
4545
4546 list = NULL;
4547
4548 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4549 &list,
4550 (mailimf_struct_parser *)
4551 mailimf_optional_field_parse,
4552 (mailimf_struct_destructor *)
4553 mailimf_optional_field_free);
4554 /*
4555 if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4556 res = r;
4557 goto err;
4558 }
4559 */
4560
4561 switch (r) {
4562 case MAILIMF_NO_ERROR:
4563 /* do nothing */
4564 break;
4565
4566 case MAILIMF_ERROR_PARSE:
4567 list = clist_new();
4568 if (list == NULL) {
4569 res = MAILIMF_ERROR_MEMORY;
4570 goto err;
4571 }
4572 break;
4573
4574 default:
4575 res = r;
4576 goto err;
4577 }
4578
4579 fields = mailimf_unparsed_fields_new(list);
4580 if (fields == NULL) {
4581 res = MAILIMF_ERROR_MEMORY;
4582 goto free;
4583 }
4584
4585 * result = fields;
4586 * index = cur_token;
4587
4588 return MAILIMF_NO_ERROR;
4589
4590 free:
4591 if (list != NULL) {
4592 clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL);
4593 clist_free(list);
4594 }
4595 err:
4596 return res;
4597}
4598#endif
4599
4600int mailimf_fields_parse(const char * message, size_t length,
4601 size_t * index,
4602 struct mailimf_fields ** result)
4603{
4604 size_t cur_token;
4605 clist * list;
4606 struct mailimf_fields * fields;
4607 int r;
4608 int res;
4609
4610 cur_token = * index;
4611
4612 list = NULL;
4613
4614 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4615 &list,
4616 (mailimf_struct_parser *)
4617 mailimf_field_parse,
4618 (mailimf_struct_destructor *)
4619 mailimf_field_free);
4620 /*
4621 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4622 res = r;
4623 goto err;
4624 }
4625 */
4626
4627 switch (r) {
4628 case MAILIMF_NO_ERROR:
4629 /* do nothing */
4630 break;
4631
4632 case MAILIMF_ERROR_PARSE:
4633 list = clist_new();
4634 if (list == NULL) {
4635 res = MAILIMF_ERROR_MEMORY;
4636 goto err;
4637 }
4638 break;
4639
4640 default:
4641 res = r;
4642 goto err;
4643 }
4644
4645 fields = mailimf_fields_new(list);
4646 if (fields == NULL) {
4647 res = MAILIMF_ERROR_MEMORY;
4648 goto free;
4649 }
4650
4651 * result = fields;
4652 * index = cur_token;
4653
4654 return MAILIMF_NO_ERROR;
4655
4656 free:
4657 if (list != NULL) {
4658 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
4659 clist_free(list);
4660 }
4661 err:
4662 return res;
4663}
4664
4665/*
4666orig-date = "Date:" date-time CRLF
4667*/
4668
4669
4670static int
4671mailimf_orig_date_parse(const char * message, size_t length,
4672 size_t * index, struct mailimf_orig_date ** result)
4673{
4674 struct mailimf_date_time * date_time;
4675 struct mailimf_orig_date * orig_date;
4676 size_t cur_token;
4677 int r;
4678 int res;
4679
4680 cur_token = * index;
4681
4682 r = mailimf_token_case_insensitive_parse(message, length,
4683 &cur_token, "Date:");
4684 if (r != MAILIMF_NO_ERROR) {
4685 res = r;
4686 goto err;
4687 }
4688
4689 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
4690 if (r != MAILIMF_NO_ERROR) {
4691 res = r;
4692 goto err;
4693 }
4694
4695 r = mailimf_ignore_unstructured_parse(message, length, &cur_token);
4696 if (r != MAILIMF_NO_ERROR) {
4697 res = r;
4698 goto free_date_time;
4699 }
4700
4701 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4702 if (r != MAILIMF_NO_ERROR) {
4703 res = r;
4704 goto free_date_time;
4705 }
4706
4707 orig_date = mailimf_orig_date_new(date_time);
4708 if (orig_date == NULL) {
4709 res = MAILIMF_ERROR_MEMORY;
4710 goto free_date_time;
4711 }
4712
4713 * result = orig_date;
4714 * index = cur_token;
4715
4716 return MAILIMF_NO_ERROR;
4717
4718 free_date_time:
4719 mailimf_date_time_free(date_time);
4720 err:
4721 return res;
4722}
4723
4724/*
4725from = "From:" mailbox-list CRLF
4726*/
4727
4728static int
4729mailimf_from_parse(const char * message, size_t length,
4730 size_t * index, struct mailimf_from ** result)
4731{
4732 struct mailimf_mailbox_list * mb_list;
4733 struct mailimf_from * from;
4734 size_t cur_token;
4735 int r;
4736 int res;
4737
4738 cur_token = * index;
4739
4740 r = mailimf_token_case_insensitive_parse(message, length,
4741 &cur_token, "From");
4742 if (r != MAILIMF_NO_ERROR) {
4743 res = r;
4744 goto err;
4745 }
4746
4747 r = mailimf_colon_parse(message, length, &cur_token);
4748 if (r != MAILIMF_NO_ERROR) {
4749 res = r;
4750 goto err;
4751 }
4752
4753 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
4754
4755 if (r != MAILIMF_NO_ERROR) {
4756 res = r;
4757 goto err;
4758 }
4759
4760 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4761 if (r != MAILIMF_NO_ERROR) {
4762 res = r;
4763 goto free_mb_list;
4764 }
4765
4766 from = mailimf_from_new(mb_list);
4767 if (from == NULL) {
4768 res = MAILIMF_ERROR_MEMORY;
4769 goto free_mb_list;
4770 }
4771
4772 * result = from;
4773 * index = cur_token;
4774
4775 return MAILIMF_NO_ERROR;
4776
4777 free_mb_list:
4778 mailimf_mailbox_list_free(mb_list);
4779 err:
4780 return res;
4781}
4782
4783/*
4784sender = "Sender:" mailbox CRLF
4785*/
4786
4787static int
4788mailimf_sender_parse(const char * message, size_t length,
4789 size_t * index, struct mailimf_sender ** result)
4790{
4791 struct mailimf_mailbox * mb;
4792 struct mailimf_sender * sender;
4793 size_t cur_token;
4794 int r;
4795 int res;
4796
4797 cur_token = * index;
4798
4799 r = mailimf_token_case_insensitive_parse(message, length,
4800 &cur_token, "Sender");
4801 if (r != MAILIMF_NO_ERROR) {
4802 res = r;
4803 goto err;
4804 }
4805
4806 r = mailimf_colon_parse(message, length, &cur_token);
4807 if (r != MAILIMF_NO_ERROR) {
4808 res = r;
4809 goto err;
4810 }
4811
4812 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
4813 if (r != MAILIMF_NO_ERROR) {
4814 res = r;
4815 goto err;
4816 }
4817
4818 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4819 if (r != MAILIMF_NO_ERROR) {
4820 res = r;
4821 goto free_mb;
4822 }
4823
4824 sender = mailimf_sender_new(mb);
4825 if (sender == NULL) {
4826 res = MAILIMF_ERROR_MEMORY;
4827 goto free_mb;
4828 }
4829
4830 * result = sender;
4831 * index = cur_token;
4832
4833 return MAILIMF_NO_ERROR;
4834
4835 free_mb:
4836 mailimf_mailbox_free(mb);
4837 err:
4838 return res;
4839}
4840
4841/*
4842reply-to = "Reply-To:" address-list CRLF
4843*/
4844
4845
4846static int
4847mailimf_reply_to_parse(const char * message, size_t length,
4848 size_t * index, struct mailimf_reply_to ** result)
4849{
4850 struct mailimf_address_list * addr_list;
4851 struct mailimf_reply_to * reply_to;
4852 size_t cur_token;
4853 int r;
4854 int res;
4855
4856 cur_token = * index;
4857
4858 r = mailimf_token_case_insensitive_parse(message, length,
4859 &cur_token, "Reply-To");
4860 if (r != MAILIMF_NO_ERROR) {
4861 res = r;
4862 goto err;
4863 }
4864
4865 r = mailimf_colon_parse(message, length, &cur_token);
4866 if (r != MAILIMF_NO_ERROR) {
4867 res = r;
4868 goto err;
4869 }
4870
4871 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4872 if (r != MAILIMF_NO_ERROR) {
4873 res = r;
4874 goto err;
4875 }
4876
4877 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4878 if (r != MAILIMF_NO_ERROR) {
4879 res = r;
4880 goto free_addr_list;
4881 }
4882
4883 reply_to = mailimf_reply_to_new(addr_list);
4884 if (reply_to == NULL) {
4885 res = MAILIMF_ERROR_MEMORY;
4886 goto free_addr_list;
4887 }
4888
4889 * result = reply_to;
4890 * index = cur_token;
4891
4892 return MAILIMF_NO_ERROR;
4893
4894 free_addr_list:
4895 mailimf_address_list_free(addr_list);
4896 err:
4897 return res;
4898}
4899
4900/*
4901to = "To:" address-list CRLF
4902*/
4903
4904static int
4905mailimf_to_parse(const char * message, size_t length,
4906 size_t * index, struct mailimf_to ** result)
4907{
4908 struct mailimf_address_list * addr_list;
4909 struct mailimf_to * to;
4910 size_t cur_token;
4911 int r;
4912 int res;
4913
4914 cur_token = * index;
4915
4916 r = mailimf_token_case_insensitive_parse(message, length,
4917 &cur_token, "To");
4918 if (r != MAILIMF_NO_ERROR) {
4919 res = r;
4920 goto err;
4921 }
4922
4923 r = mailimf_colon_parse(message, length, &cur_token);
4924 if (r != MAILIMF_NO_ERROR) {
4925 res = r;
4926 goto err;
4927 }
4928
4929 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4930 if (r != MAILIMF_NO_ERROR) {
4931 res = r;
4932 goto err;
4933 }
4934
4935 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4936 if (r != MAILIMF_NO_ERROR) {
4937 res = r;
4938 goto free_addr_list;
4939 }
4940
4941 to = mailimf_to_new(addr_list);
4942 if (to == NULL) {
4943 res = MAILIMF_ERROR_MEMORY;
4944 goto free_addr_list;
4945 }
4946
4947 * result = to;
4948 * index = cur_token;
4949
4950 return MAILIMF_NO_ERROR;
4951
4952 free_addr_list:
4953 mailimf_address_list_free(addr_list);
4954 err:
4955 return res;
4956}
4957
4958/*
4959cc = "Cc:" address-list CRLF
4960*/
4961
4962
4963static int
4964mailimf_cc_parse(const char * message, size_t length,
4965 size_t * index, struct mailimf_cc ** result)
4966{
4967 struct mailimf_address_list * addr_list;
4968 struct mailimf_cc * cc;
4969 size_t cur_token;
4970 int r;
4971 int res;
4972
4973 cur_token = * index;
4974
4975 r = mailimf_token_case_insensitive_parse(message, length,
4976 &cur_token, "Cc");
4977 if (r != MAILIMF_NO_ERROR) {
4978 res = r;
4979 goto err;
4980 }
4981
4982 r = mailimf_colon_parse(message, length, &cur_token);
4983 if (r != MAILIMF_NO_ERROR) {
4984 res = r;
4985 goto err;
4986 }
4987
4988 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4989 if (r != MAILIMF_NO_ERROR) {
4990 res = r;
4991 goto err;
4992 }
4993
4994 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4995 if (r != MAILIMF_NO_ERROR) {
4996 res = r;
4997 goto free_addr_list;
4998 }
4999
5000 cc = mailimf_cc_new(addr_list);
5001 if (cc == NULL) {
5002 res = MAILIMF_ERROR_MEMORY;
5003 goto free_addr_list;
5004 }
5005
5006 * result = cc;
5007 * index = cur_token;
5008
5009 return MAILIMF_NO_ERROR;
5010
5011 free_addr_list:
5012 mailimf_address_list_free(addr_list);
5013 err:
5014 return res;
5015}
5016
5017/*
5018bcc = "Bcc:" (address-list / [CFWS]) CRLF
5019*/
5020
5021
5022static int
5023mailimf_bcc_parse(const char * message, size_t length,
5024 size_t * index, struct mailimf_bcc ** result)
5025{
5026 struct mailimf_address_list * addr_list;
5027 struct mailimf_bcc * bcc;
5028 size_t cur_token;
5029 int r;
5030 int res;
5031
5032 cur_token = * index;
5033 addr_list = NULL;
5034
5035 r = mailimf_token_case_insensitive_parse(message, length,
5036 &cur_token, "Bcc");
5037 if (r != MAILIMF_NO_ERROR) {
5038 res = r;
5039 goto err;
5040 }
5041
5042 r = mailimf_colon_parse(message, length, &cur_token);
5043 if (r != MAILIMF_NO_ERROR) {
5044 res = r;
5045 goto err;
5046 }
5047
5048 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5049 switch (r) {
5050 case MAILIMF_NO_ERROR:
5051 /* do nothing */
5052 break;
5053 case MAILIMF_ERROR_PARSE:
5054 r = mailimf_cfws_parse(message, length, &cur_token);
5055 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
5056 res = r;
5057 goto err;
5058 }
5059 break;
5060 default:
5061 res = r;
5062 goto err;
5063 }
5064
5065 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5066 if (r != MAILIMF_NO_ERROR) {
5067 res = r;
5068 goto free_addr_list;
5069 }
5070
5071 bcc = mailimf_bcc_new(addr_list);
5072 if (bcc == NULL) {
5073 res = MAILIMF_ERROR_MEMORY;
5074 goto free_addr_list;
5075 }
5076
5077 * result = bcc;
5078 * index = cur_token;
5079
5080 return MAILIMF_NO_ERROR;
5081
5082 free_addr_list:
5083 mailimf_address_list_free(addr_list);
5084 err:
5085 return res;
5086}
5087
5088/*
5089message-id = "Message-ID:" msg-id CRLF
5090*/
5091
5092static int mailimf_message_id_parse(const char * message, size_t length,
5093 size_t * index,
5094 struct mailimf_message_id ** result)
5095{
5096 char * value;
5097 size_t cur_token;
5098 struct mailimf_message_id * message_id;
5099 int r;
5100 int res;
5101
5102 cur_token = * index;
5103
5104 r = mailimf_token_case_insensitive_parse(message, length,
5105 &cur_token, "Message-ID");
5106 if (r != MAILIMF_NO_ERROR) {
5107 res = r;
5108 goto err;
5109 }
5110
5111 r = mailimf_colon_parse(message, length, &cur_token);
5112 if (r != MAILIMF_NO_ERROR) {
5113 res = r;
5114 goto err;
5115 }
5116
5117 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
5118 if (r != MAILIMF_NO_ERROR) {
5119 res = r;
5120 goto err;
5121 }
5122
5123 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5124 if (r != MAILIMF_NO_ERROR) {
5125 res = r;
5126 goto free_value;
5127 }
5128
5129 message_id = mailimf_message_id_new(value);
5130 if (message_id == NULL) {
5131 res = MAILIMF_ERROR_MEMORY;
5132 goto free_value;
5133 }
5134
5135 * result = message_id;
5136 * index = cur_token;
5137
5138 return MAILIMF_NO_ERROR;
5139
5140 free_value:
5141 mailimf_msg_id_free(value);
5142 err:
5143 return res;
5144}
5145
5146/*
5147in-reply-to = "In-Reply-To:" 1*msg-id CRLF
5148*/
5149
5150int mailimf_msg_id_list_parse(const char * message, size_t length,
5151 size_t * index, clist ** result)
5152{
5153 return mailimf_struct_multiple_parse(message, length, index,
5154 result,
5155 (mailimf_struct_parser *)
5156 mailimf_unstrict_msg_id_parse,
5157 (mailimf_struct_destructor *)
5158 mailimf_msg_id_free);
5159}
5160
5161static int mailimf_in_reply_to_parse(const char * message, size_t length,
5162 size_t * index,
5163 struct mailimf_in_reply_to ** result)
5164{
5165 struct mailimf_in_reply_to * in_reply_to;
5166 size_t cur_token;
5167 clist * msg_id_list;
5168 int res;
5169 int r;
5170
5171 cur_token = * index;
5172
5173 r = mailimf_token_case_insensitive_parse(message, length,
5174 &cur_token, "In-Reply-To");
5175 if (r != MAILIMF_NO_ERROR) {
5176 res = r;
5177 goto err;
5178 }
5179
5180 r = mailimf_colon_parse(message, length, &cur_token);
5181 if (r != MAILIMF_NO_ERROR) {
5182 res = r;
5183 goto err;
5184 }
5185
5186 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5187 if (r != MAILIMF_NO_ERROR) {
5188 res = r;
5189 goto err;
5190 }
5191
5192 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5193 if (r != MAILIMF_NO_ERROR) {
5194 res = r;
5195 goto free_list;
5196 }
5197
5198 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
5199 if (in_reply_to == NULL) {
5200 res = MAILIMF_ERROR_MEMORY;
5201 goto free_list;
5202 }
5203
5204 * result = in_reply_to;
5205 * index = cur_token;
5206
5207 return MAILIMF_NO_ERROR;
5208
5209 free_list:
5210 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5211 clist_free(msg_id_list);
5212 err:
5213 return res;
5214}
5215
5216/*
5217references = "References:" 1*msg-id CRLF
5218*/
5219
5220int mailimf_references_parse(const char * message, size_t length,
5221 size_t * index,
5222 struct mailimf_references ** result)
5223{
5224 struct mailimf_references * references;
5225 size_t cur_token;
5226 clist * msg_id_list;
5227 int r;
5228 int res;
5229
5230 cur_token = * index;
5231
5232 r = mailimf_token_case_insensitive_parse(message, length,
5233 &cur_token, "References");
5234 if (r != MAILIMF_NO_ERROR) {
5235 res = r;
5236 goto err;
5237 }
5238
5239 r = mailimf_colon_parse(message, length, &cur_token);
5240 if (r != MAILIMF_NO_ERROR) {
5241 res = r;
5242 goto err;
5243 }
5244
5245 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5246 if (r != MAILIMF_NO_ERROR) {
5247 res = r;
5248 goto err;
5249 }
5250
5251 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5252 if (r != MAILIMF_NO_ERROR) {
5253 res = r;
5254 goto free_list;
5255 }
5256
5257 references = mailimf_references_new(msg_id_list);
5258 if (references == NULL) {
5259 res = MAILIMF_ERROR_MEMORY;
5260 goto free_list;
5261 }
5262
5263 * result = references;
5264 * index = cur_token;
5265
5266 return MAILIMF_NO_ERROR;
5267
5268 free_list:
5269 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5270 clist_free(msg_id_list);
5271 err:
5272 return res;
5273}
5274
5275/*
5276msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
5277*/
5278
5279int mailimf_msg_id_parse(const char * message, size_t length,
5280 size_t * index,
5281 char ** result)
5282{
5283 size_t cur_token;
5284#if 0
5285 char * id_left;
5286 char * id_right;
5287#endif
5288 char * msg_id;
5289 int r;
5290 int res;
5291
5292 cur_token = * index;
5293
5294 r = mailimf_cfws_parse(message, length, &cur_token);
5295 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5296 return r;
5297
5298 r = mailimf_lower_parse(message, length, &cur_token);
5299 if (r != MAILIMF_NO_ERROR) {
5300 res = r;
5301 goto err;
5302 }
5303
5304 r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id);
5305 if (r != MAILIMF_NO_ERROR) {
5306 res = r;
5307 goto err;
5308 }
5309
5310 r = mailimf_greater_parse(message, length, &cur_token);
5311 if (r != MAILIMF_NO_ERROR) {
5312 free(msg_id);
5313 res = r;
5314 goto err;
5315 }
5316
5317#if 0
5318 r = mailimf_id_left_parse(message, length, &cur_token, &id_left);
5319 if (r != MAILIMF_NO_ERROR) {
5320 res = r;
5321 goto err;
5322 }
5323
5324 r = mailimf_at_sign_parse(message, length, &cur_token);
5325 if (r != MAILIMF_NO_ERROR) {
5326 res = r;
5327 goto free_id_left;
5328 }
5329
5330 r = mailimf_id_right_parse(message, length, &cur_token, &id_right);
5331 if (r != MAILIMF_NO_ERROR) {
5332 res = r;
5333 goto free_id_left;
5334 }
5335
5336 r = mailimf_greater_parse(message, length, &cur_token);
5337 if (r != MAILIMF_NO_ERROR) {
5338 res = r;
5339 goto free_id_right;
5340 }
5341
5342 msg_id = malloc(strlen(id_left) + strlen(id_right) + 2);
5343 if (msg_id == NULL) {
5344 res = MAILIMF_ERROR_MEMORY;
5345 goto free_id_right;
5346 }
5347 strcpy(msg_id, id_left);
5348 strcat(msg_id, "@");
5349 strcat(msg_id, id_right);
5350
5351 mailimf_id_left_free(id_left);
5352 mailimf_id_right_free(id_right);
5353#endif
5354
5355 * result = msg_id;
5356 * index = cur_token;
5357
5358 return MAILIMF_NO_ERROR;
5359
5360#if 0
5361 free_id_right:
5362 mailimf_id_right_free(id_right);
5363 free_id_left:
5364 mailimf_id_left_free(id_left);
5365#endif
5366 /*
5367 free:
5368 mailimf_atom_free(msg_id);
5369 */
5370 err:
5371 return res;
5372}
5373
5374static int mailimf_parse_unwanted_msg_id(const char * message, size_t length,
5375 size_t * index)
5376{
5377 size_t cur_token;
5378 int r;
5379 char * word;
5380 int token_parsed;
5381
5382 cur_token = * index;
5383
5384 token_parsed = TRUE;
5385 while (token_parsed) {
5386 token_parsed = FALSE;
5387 r = mailimf_word_parse(message, length, &cur_token, &word);
5388 if (r == MAILIMF_NO_ERROR) {
5389 mailimf_word_free(word);
5390 token_parsed = TRUE;
5391 }
5392 else if (r == MAILIMF_ERROR_PARSE) {
5393 /* do nothing */
5394 }
5395 else
5396 return r;
5397 r = mailimf_semi_colon_parse(message, length, &cur_token);
5398 if (r == MAILIMF_NO_ERROR)
5399 token_parsed = TRUE;
5400 else if (r == MAILIMF_ERROR_PARSE) {
5401 /* do nothing */
5402 }
5403 else
5404 return r;
5405 r = mailimf_comma_parse(message, length, &cur_token);
5406 if (r == MAILIMF_NO_ERROR)
5407 token_parsed = TRUE;
5408 else if (r == MAILIMF_ERROR_PARSE) {
5409 /* do nothing */
5410 }
5411 else
5412 return r;
5413 r = mailimf_plus_parse(message, length, &cur_token);
5414 if (r == MAILIMF_NO_ERROR)
5415 token_parsed = TRUE;
5416 else if (r == MAILIMF_ERROR_PARSE) {
5417 /* do nothing */
5418 }
5419 else
5420 return r;
5421 r = mailimf_colon_parse(message, length, &cur_token);
5422 if (r == MAILIMF_NO_ERROR)
5423 token_parsed = TRUE;
5424 else if (r == MAILIMF_ERROR_PARSE) {
5425 /* do nothing */
5426 }
5427 else
5428 return r;
5429 r = mailimf_point_parse(message, length, &cur_token);
5430 if (r == MAILIMF_NO_ERROR)
5431 token_parsed = TRUE;
5432 else if (r == MAILIMF_ERROR_PARSE) {
5433 /* do nothing */
5434 }
5435 else
5436 return r;
5437 r = mailimf_at_sign_parse(message, length, &cur_token);
5438 if (r == MAILIMF_NO_ERROR)
5439 token_parsed = TRUE;
5440 else if (r == MAILIMF_ERROR_PARSE) {
5441 /* do nothing */
5442 }
5443 else
5444 return r;
5445 }
5446
5447 return MAILIMF_NO_ERROR;
5448}
5449
5450static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
5451 size_t * index,
5452 char ** result)
5453{
5454 char * msgid;
5455 size_t cur_token;
5456 int r;
5457
5458 cur_token = * index;
5459
5460 r = mailimf_cfws_parse(message, length, &cur_token);
5461 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5462 return r;
5463
5464 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5465 if (r != MAILIMF_NO_ERROR)
5466 return r;
5467
5468 r = mailimf_msg_id_parse(message, length, &cur_token, &msgid);
5469 if (r != MAILIMF_NO_ERROR)
5470 return r;
5471
5472 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5473 if (r != MAILIMF_NO_ERROR)
5474 return r;
5475
5476 * result = msgid;
5477 * index = cur_token;
5478
5479 return MAILIMF_NO_ERROR;
5480}
5481
5482/*
5483id-left = dot-atom-text / no-fold-quote / obs-id-left
5484*/
5485
5486#if 0
5487static int mailimf_id_left_parse(const char * message, size_t length,
5488 size_t * index, char ** result)
5489{
5490 int r;
5491
5492 r = mailimf_dot_atom_text_parse(message, length, index, result);
5493 switch (r) {
5494 case MAILIMF_NO_ERROR:
5495 return MAILIMF_NO_ERROR;
5496 case MAILIMF_ERROR_PARSE:
5497 break;
5498 default:
5499 return r;
5500 }
5501
5502 r = mailimf_no_fold_quote_parse(message, length, index, result);
5503 if (r != MAILIMF_NO_ERROR)
5504 return r;
5505
5506 return MAILIMF_NO_ERROR;
5507}
5508#endif
5509
5510/*
5511id-right = dot-atom-text / no-fold-literal / obs-id-right
5512*/
5513
5514#if 0
5515static int mailimf_id_right_parse(const char * message, size_t length,
5516 size_t * index, char ** result)
5517{
5518 int r;
5519
5520 r = mailimf_dot_atom_text_parse(message, length, index, result);
5521 switch (r) {
5522 case MAILIMF_NO_ERROR:
5523 return MAILIMF_NO_ERROR;
5524 case MAILIMF_ERROR_PARSE:
5525 break;
5526 default:
5527 return r;
5528 }
5529
5530 r = mailimf_no_fold_literal_parse(message, length, index, result);
5531 if (r != MAILIMF_NO_ERROR)
5532 return r;
5533
5534 return MAILIMF_NO_ERROR;
5535}
5536#endif
5537
5538/*
5539no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
5540*/
5541
5542#if 0
5543static int mailimf_no_fold_quote_char_parse(const char * message, size_t length,
5544 size_t * index, char * result)
5545{
5546 char ch;
5547 size_t cur_token;
5548 int r;
5549
5550 cur_token = * index;
5551
5552#if 0
5553 r = mailimf_qtext_parse(message, length, &cur_token, &ch);
5554#endif
5555
5556 if (cur_token >= length)
5557 return MAILIMF_ERROR_PARSE;
5558
5559 if (is_qtext(message[cur_token])) {
5560 ch = message[cur_token];
5561 cur_token ++;
5562 }
5563 else {
5564 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5565
5566 if (r != MAILIMF_NO_ERROR)
5567 return r;
5568 }
5569
5570 * index = cur_token;
5571 * result = ch;
5572
5573 return MAILIMF_NO_ERROR;
5574}
5575#endif
5576
5577#if 0
5578static int mailimf_no_fold_quote_parse(const char * message, size_t length,
5579 size_t * index, char ** result)
5580{
5581 size_t cur_token;
5582 size_t begin;
5583 char ch;
5584 char * no_fold_quote;
5585 int r;
5586 int res;
5587
5588 begin = cur_token;
5589 r = mailimf_dquote_parse(message, length, &cur_token);
5590 if (r != MAILIMF_NO_ERROR) {
5591 res = r;
5592 goto err;
5593 }
5594
5595 while (1) {
5596 r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch);
5597 if (r == MAILIMF_NO_ERROR) {
5598 /* do nothing */
5599 }
5600 else if (r == MAILIMF_ERROR_PARSE)
5601 break;
5602 else {
5603 res = r;
5604 goto err;
5605 }
5606 }
5607
5608 r = mailimf_dquote_parse(message, length, &cur_token);
5609 if (r != MAILIMF_NO_ERROR) {
5610 res = r;
5611 goto err;
5612 }
5613
5614 /* no_fold_quote = strndup(message + begin, cur_token - begin); */
5615 no_fold_quote = malloc(cur_token - begin + 1);
5616 if (no_fold_quote == NULL) {
5617 res = MAILIMF_ERROR_MEMORY;
5618 goto err;
5619 }
5620 strncpy(no_fold_quote, message + begin, cur_token - begin);
5621 no_fold_quote[cur_token - begin] = '\0';
5622
5623 * result = no_fold_quote;
5624 * index = cur_token;
5625
5626 return MAILIMF_NO_ERROR;
5627
5628 err:
5629 return res;
5630}
5631#endif
5632
5633/*
5634no-fold-literal = "[" *(dtext / quoted-pair) "]"
5635*/
5636
5637#if 0
5638static inline int
5639mailimf_no_fold_literal_char_parse(const char * message, size_t length,
5640 size_t * index, char * result)
5641{
5642 char ch;
5643 size_t cur_token;
5644 int r;
5645
5646 cur_token = * index;
5647
5648#if 0
5649 r = mailimf_dtext_parse(message, length, &cur_token, &ch);
5650#endif
5651 if (cur_token >= length)
5652 return MAILIMF_ERROR_PARSE;
5653
5654 if (is_dtext(message[cur_token])) {
5655 ch = message[cur_token];
5656 cur_token ++;
5657 }
5658 else {
5659 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5660
5661 if (r != MAILIMF_NO_ERROR)
5662 return r;
5663 }
5664
5665 * index = cur_token;
5666 * result = ch;
5667
5668 return MAILIMF_NO_ERROR;
5669}
5670#endif
5671
5672#if 0
5673static int mailimf_no_fold_literal_parse(const char * message, size_t length,
5674 size_t * index, char ** result)
5675{
5676 size_t cur_token;
5677 size_t begin;
5678 char ch;
5679 char * no_fold_literal;
5680 int r;
5681 int res;
5682
5683 begin = cur_token;
5684 r = mailimf_obracket_parse(message, length, &cur_token);
5685 if (r != MAILIMF_NO_ERROR) {
5686 res = r;
5687 goto err;
5688 }
5689
5690 while (1) {
5691 r = mailimf_no_fold_literal_char_parse(message, length,
5692 &cur_token, &ch);
5693 if (r == MAILIMF_NO_ERROR) {
5694 /* do nothing */
5695 }
5696 else if (r == MAILIMF_ERROR_PARSE)
5697 break;
5698 else {
5699 res = r;
5700 goto err;
5701 }
5702 }
5703
5704 r = mailimf_cbracket_parse(message, length, &cur_token);
5705 if (r != MAILIMF_NO_ERROR) {
5706 res = r;
5707 goto err;
5708 }
5709
5710 /*
5711 no_fold_literal = strndup(message + begin, cur_token - begin);
5712 */
5713 no_fold_literal = malloc(cur_token - begin + 1);
5714 if (no_fold_literal == NULL) {
5715 res = MAILIMF_NO_ERROR;
5716 goto err;
5717 }
5718 strncpy(no_fold_literal, message + begin, cur_token - begin);
5719 no_fold_literal[cur_token - begin] = '\0';
5720
5721 * result = no_fold_literal;
5722 * index = cur_token;
5723
5724 return MAILIMF_NO_ERROR;
5725
5726 err:
5727 return res;
5728}
5729#endif
5730
5731/*
5732subject = "Subject:" unstructured CRLF
5733*/
5734
5735static int mailimf_subject_parse(const char * message, size_t length,
5736 size_t * index,
5737 struct mailimf_subject ** result)
5738{
5739 struct mailimf_subject * subject;
5740 char * value;
5741 size_t cur_token;
5742 int r;
5743 int res;
5744
5745 cur_token = * index;
5746
5747 r = mailimf_token_case_insensitive_parse(message, length,
5748 &cur_token, "Subject");
5749 if (r != MAILIMF_NO_ERROR) {
5750 res = r;
5751 goto err;
5752 }
5753
5754 r = mailimf_colon_parse(message, length, &cur_token);
5755 if (r != MAILIMF_NO_ERROR) {
5756 res = r;
5757 goto err;
5758 }
5759
5760 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5761 if (r != MAILIMF_NO_ERROR) {
5762 res = r;
5763 goto err;
5764 }
5765
5766 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5767 if (r != MAILIMF_NO_ERROR) {
5768 res = r;
5769 goto free_value;
5770 }
5771
5772 subject = mailimf_subject_new(value);
5773 if (subject == NULL) {
5774 res = MAILIMF_ERROR_MEMORY;
5775 goto free_value;
5776 }
5777
5778 * result = subject;
5779 * index = cur_token;
5780
5781 return MAILIMF_NO_ERROR;
5782
5783 free_value:
5784 mailimf_unstructured_free(value);
5785 err:
5786 return res;
5787}
5788
5789/*
5790comments = "Comments:" unstructured CRLF
5791*/
5792
5793static int mailimf_comments_parse(const char * message, size_t length,
5794 size_t * index,
5795 struct mailimf_comments ** result)
5796{
5797 struct mailimf_comments * comments;
5798 char * value;
5799 size_t cur_token;
5800 int r;
5801 int res;
5802
5803 cur_token = * index;
5804
5805 r = mailimf_token_case_insensitive_parse(message, length,
5806 &cur_token, "Comments");
5807 if (r != MAILIMF_NO_ERROR) {
5808 res = r;
5809 goto err;
5810 }
5811
5812 r = mailimf_colon_parse(message, length, &cur_token);
5813 if (r != MAILIMF_NO_ERROR) {
5814 res = r;
5815 goto err;
5816 }
5817
5818 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5819 if (r != MAILIMF_NO_ERROR) {
5820 res = r;
5821 goto err;
5822 }
5823
5824 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5825 if (r != MAILIMF_NO_ERROR) {
5826 res = r;
5827 goto free_value;
5828 }
5829
5830 comments = mailimf_comments_new(value);
5831 if (comments == NULL) {
5832 res = MAILIMF_ERROR_MEMORY;
5833 goto free_value;
5834 }
5835
5836 * result = comments;
5837 * index = cur_token;
5838
5839 return MAILIMF_NO_ERROR;
5840
5841 free_value:
5842 mailimf_unstructured_free(value);
5843 err:
5844 return res;
5845}
5846
5847/*
5848keywords = "Keywords:" phrase *("," phrase) CRLF
5849*/
5850
5851static int mailimf_keywords_parse(const char * message, size_t length,
5852 size_t * index,
5853 struct mailimf_keywords ** result)
5854{
5855 struct mailimf_keywords * keywords;
5856 clist * list;
5857 size_t cur_token;
5858 int r;
5859 int res;
5860
5861 cur_token = * index;
5862
5863 r = mailimf_token_case_insensitive_parse(message, length,
5864 &cur_token, "Keywords");
5865 if (r != MAILIMF_NO_ERROR) {
5866 res = r;
5867 goto err;
5868 }
5869
5870 r = mailimf_colon_parse(message, length, &cur_token);
5871 if (r != MAILIMF_NO_ERROR) {
5872 res = r;
5873 goto err;
5874 }
5875
5876 r = mailimf_struct_list_parse(message, length, &cur_token,
5877 &list, ',',
5878 (mailimf_struct_parser *)
5879 mailimf_phrase_parse,
5880 (mailimf_struct_destructor *)
5881 mailimf_phrase_free);
5882 if (r != MAILIMF_NO_ERROR) {
5883 res = r;
5884 goto err;
5885 }
5886
5887 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5888 if (r != MAILIMF_NO_ERROR) {
5889 res = r;
5890 goto free_list;
5891 }
5892
5893 keywords = mailimf_keywords_new(list);
5894 if (keywords == NULL) {
5895 res = MAILIMF_ERROR_MEMORY;
5896 goto free_list;
5897 }
5898
5899 * result = keywords;
5900 * index = cur_token;
5901
5902 return MAILIMF_NO_ERROR;
5903
5904 free_list:
5905 clist_foreach(list, (clist_func) mailimf_phrase_free, NULL);
5906 clist_free(list);
5907 err:
5908 return res;
5909}
5910
5911/*
5912resent-date = "Resent-Date:" date-time CRLF
5913*/
5914
5915static int
5916mailimf_resent_date_parse(const char * message, size_t length,
5917 size_t * index, struct mailimf_orig_date ** result)
5918{
5919 struct mailimf_orig_date * orig_date;
5920 struct mailimf_date_time * date_time;
5921 size_t cur_token;
5922 int r;
5923 int res;
5924
5925 cur_token = * index;
5926
5927 r = mailimf_token_case_insensitive_parse(message, length,
5928 &cur_token, "Resent-Date");
5929 if (r != MAILIMF_NO_ERROR) {
5930 res = r;
5931 goto err;
5932 }
5933
5934 r = mailimf_colon_parse(message, length, &cur_token);
5935 if (r != MAILIMF_NO_ERROR) {
5936 res = r;
5937 goto err;
5938 }
5939
5940 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
5941 if (r != MAILIMF_NO_ERROR) {
5942 res = r;
5943 goto err;
5944 }
5945
5946 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5947 if (r != MAILIMF_NO_ERROR) {
5948 res = r;
5949 goto free_date_time;
5950 }
5951
5952 orig_date = mailimf_orig_date_new(date_time);
5953 if (orig_date == NULL) {
5954 res = MAILIMF_ERROR_MEMORY;
5955 goto free_date_time;
5956 }
5957
5958 * result = orig_date;
5959 * index = cur_token;
5960
5961 return MAILIMF_NO_ERROR;
5962
5963 free_date_time:
5964 mailimf_date_time_free(date_time);
5965 err:
5966 return res;
5967}
5968
5969/*
5970resent-from = "Resent-From:" mailbox-list CRLF
5971*/
5972
5973static int
5974mailimf_resent_from_parse(const char * message, size_t length,
5975 size_t * index, struct mailimf_from ** result)
5976{
5977 struct mailimf_mailbox_list * mb_list;
5978 struct mailimf_from * from;
5979 size_t cur_token;
5980 int r;
5981 int res;
5982
5983 cur_token = * index;
5984
5985 r = mailimf_token_case_insensitive_parse(message, length,
5986 &cur_token, "Resent-From");
5987 if (r != MAILIMF_NO_ERROR) {
5988 res = r;
5989 goto err;
5990 }
5991
5992 r = mailimf_colon_parse(message, length, &cur_token);
5993 if (r != MAILIMF_NO_ERROR) {
5994 res = r;
5995 goto err;
5996 }
5997
5998 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
5999 if (r != MAILIMF_NO_ERROR) {
6000 res = r;
6001 goto err;
6002 }
6003
6004 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6005 if (r != MAILIMF_NO_ERROR) {
6006 res = r;
6007 goto free_mb_list;
6008 }
6009
6010 from = mailimf_from_new(mb_list);
6011 if (from == NULL) {
6012 res = MAILIMF_ERROR_MEMORY;
6013 goto free_mb_list;
6014 }
6015
6016 * result = from;
6017 * index = cur_token;
6018
6019 return MAILIMF_NO_ERROR;
6020
6021 free_mb_list:
6022 mailimf_mailbox_list_free(mb_list);
6023 err:
6024 return res;
6025}
6026
6027/*
6028resent-sender = "Resent-Sender:" mailbox CRLF
6029*/
6030
6031static int
6032mailimf_resent_sender_parse(const char * message, size_t length,
6033 size_t * index, struct mailimf_sender ** result)
6034{
6035 struct mailimf_mailbox * mb;
6036 struct mailimf_sender * sender;
6037 size_t cur_token;
6038 int r;
6039 int res;
6040
6041 cur_token = length;
6042
6043 r = mailimf_token_case_insensitive_parse(message, length,
6044 &cur_token, "Resent-Sender");
6045 if (r != MAILIMF_NO_ERROR) {
6046 res = r;
6047 goto err;
6048 }
6049
6050 r = mailimf_colon_parse(message, length, &cur_token);
6051 if (r != MAILIMF_NO_ERROR) {
6052 res = r;
6053 goto err;
6054 }
6055
6056 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
6057 if (r != MAILIMF_NO_ERROR) {
6058 res = r;
6059 goto err;
6060 }
6061
6062 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6063 if (r != MAILIMF_NO_ERROR) {
6064 res = r;
6065 goto free_mb;
6066 }
6067
6068 sender = mailimf_sender_new(mb);
6069 if (sender == NULL) {
6070 res = MAILIMF_ERROR_MEMORY;
6071 goto free_mb;
6072 }
6073
6074 * result = sender;
6075 * index = cur_token;
6076
6077 return MAILIMF_NO_ERROR;
6078
6079 free_mb:
6080 mailimf_mailbox_free(mb);
6081 err:
6082 return res;
6083}
6084
6085/*
6086resent-to = "Resent-To:" address-list CRLF
6087*/
6088
6089static int
6090mailimf_resent_to_parse(const char * message, size_t length,
6091 size_t * index, struct mailimf_to ** result)
6092{
6093 struct mailimf_address_list * addr_list;
6094 struct mailimf_to * to;
6095 size_t cur_token;
6096 int r;
6097 int res;
6098
6099 cur_token = * index;
6100
6101 r = mailimf_token_case_insensitive_parse(message, length,
6102 &cur_token, "Resent-To");
6103 if (r != MAILIMF_NO_ERROR) {
6104 res = r;
6105 goto err;
6106 }
6107
6108 r = mailimf_colon_parse(message, length, &cur_token);
6109 if (r != MAILIMF_NO_ERROR) {
6110 res = r;
6111 goto err;
6112 }
6113
6114 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6115 if (r != MAILIMF_NO_ERROR) {
6116 res = r;
6117 goto err;
6118 }
6119
6120 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6121 if (r != MAILIMF_NO_ERROR) {
6122 res = r;
6123 goto free_addr_list;
6124 }
6125
6126 to = mailimf_to_new(addr_list);
6127 if (to == NULL) {
6128 res = MAILIMF_ERROR_MEMORY;
6129 goto free_addr_list;
6130 }
6131
6132 * result = to;
6133 * index = cur_token;
6134
6135 return MAILIMF_NO_ERROR;
6136
6137 free_addr_list:
6138 mailimf_address_list_free(addr_list);
6139 err:
6140 return res;
6141}
6142
6143/*
6144resent-cc = "Resent-Cc:" address-list CRLF
6145*/
6146
6147static int
6148mailimf_resent_cc_parse(const char * message, size_t length,
6149 size_t * index, struct mailimf_cc ** result)
6150{
6151 struct mailimf_address_list * addr_list;
6152 struct mailimf_cc * cc;
6153 size_t cur_token;
6154 int r;
6155 int res;
6156
6157 cur_token = * index;
6158
6159 r = mailimf_token_case_insensitive_parse(message, length,
6160 &cur_token, "Resent-Cc");
6161 if (r != MAILIMF_NO_ERROR) {
6162 res = r;
6163 goto err;
6164 }
6165
6166 r = mailimf_colon_parse(message, length, &cur_token);
6167 if (r != MAILIMF_NO_ERROR) {
6168 res = r;
6169 goto err;
6170 }
6171
6172 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6173 if (r != MAILIMF_NO_ERROR) {
6174 res = r;
6175 goto err;
6176 }
6177
6178 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6179 if (r != MAILIMF_NO_ERROR) {
6180 res = r;
6181 goto free_addr_list;
6182 }
6183
6184 cc = mailimf_cc_new(addr_list);
6185 if (cc == NULL) {
6186 res = MAILIMF_ERROR_MEMORY;
6187 goto free_addr_list;
6188 }
6189
6190 * result = cc;
6191 * index = cur_token;
6192
6193 return MAILIMF_NO_ERROR;
6194
6195 free_addr_list:
6196 mailimf_address_list_free(addr_list);
6197 err:
6198 return res;
6199}
6200
6201/*
6202resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF
6203*/
6204
6205static int
6206mailimf_resent_bcc_parse(const char * message, size_t length,
6207 size_t * index, struct mailimf_bcc ** result)
6208{
6209 struct mailimf_address_list * addr_list;
6210 struct mailimf_bcc * bcc;
6211 size_t cur_token;
6212 int r;
6213 int res;
6214
6215 cur_token = * index;
6216 bcc = NULL;
6217
6218 r = mailimf_token_case_insensitive_parse(message, length,
6219 &cur_token, "Resent-Bcc");
6220 if (r != MAILIMF_NO_ERROR) {
6221 res = r;
6222 goto err;
6223 }
6224
6225 r = mailimf_colon_parse(message, length, &cur_token);
6226 if (r != MAILIMF_NO_ERROR) {
6227 res = r;
6228 goto err;
6229 }
6230
6231 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6232 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6233 res = r;
6234 goto err;
6235 }
6236
6237 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6238 if (r != MAILIMF_NO_ERROR) {
6239 res = r;
6240 goto free_addr_list;
6241 }
6242
6243 bcc = mailimf_bcc_new(addr_list);
6244 if (bcc == NULL) {
6245 res = MAILIMF_ERROR_MEMORY;
6246 goto free_addr_list;
6247 }
6248
6249 * result = bcc;
6250 * index = cur_token;
6251
6252 return TRUE;
6253
6254 free_addr_list:
6255 mailimf_address_list_free(addr_list);
6256 err:
6257 return res;
6258}
6259
6260/*
6261resent-msg-id = "Resent-Message-ID:" msg-id CRLF
6262*/
6263
6264static int
6265mailimf_resent_msg_id_parse(const char * message, size_t length,
6266 size_t * index,
6267 struct mailimf_message_id ** result)
6268{
6269 char * value;
6270 size_t cur_token;
6271 struct mailimf_message_id * message_id;
6272 int r;
6273 int res;
6274
6275 cur_token = * index;
6276
6277 r = mailimf_token_case_insensitive_parse(message, length,
6278 &cur_token, "Resent-Message-ID");
6279 if (r != MAILIMF_NO_ERROR) {
6280 res = r;
6281 goto err;
6282 }
6283
6284 r = mailimf_colon_parse(message, length, &cur_token);
6285 if (r != MAILIMF_NO_ERROR) {
6286 res = r;
6287 goto err;
6288 }
6289
6290 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
6291 if (r != MAILIMF_NO_ERROR) {
6292 res = r;
6293 goto err;
6294 }
6295
6296 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6297 if (r != MAILIMF_NO_ERROR) {
6298 res = r;
6299 goto free_value;
6300 }
6301
6302 message_id = mailimf_message_id_new(value);
6303 if (message_id == NULL) {
6304 res = MAILIMF_ERROR_MEMORY;
6305 goto free_value;
6306 }
6307
6308 * result = message_id;
6309 * index = cur_token;
6310
6311 return MAILIMF_NO_ERROR;
6312
6313 free_value:
6314 mailimf_msg_id_free(value);
6315 err:
6316 return res;
6317}
6318
6319/*
6320trace = [return]
6321 1*received
6322*/
6323
6324#if 0
6325static int mailimf_trace_parse(const char * message, size_t length,
6326 size_t * index,
6327 struct mailimf_trace ** result)
6328{
6329 size_t cur_token;
6330 struct mailimf_return * return_path;
6331 clist * received_list;
6332 struct mailimf_trace * trace;
6333 int r;
6334 int res;
6335
6336 cur_token = * index;
6337 return_path = NULL;
6338 received_list = NULL;
6339
6340 r = mailimf_return_parse(message, length, &cur_token, &return_path);
6341 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6342 res = r;
6343 goto err;
6344 }
6345
6346 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6347 &received_list,
6348 (mailimf_struct_parser *)
6349 mailimf_received_parse,
6350 (mailimf_struct_destructor *)
6351 mailimf_received_free);
6352 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6353 res = r;
6354 goto err;
6355 }
6356
6357 if ((received_list == NULL) && (return_path == NULL)) {
6358 res = MAILIMF_ERROR_PARSE;
6359 goto free_return;
6360 }
6361
6362 trace = mailimf_trace_new(return_path, received_list);
6363 if (trace == NULL) {
6364 res = MAILIMF_ERROR_MEMORY;
6365 goto free_list;
6366 }
6367
6368 * result = trace;
6369 * index = cur_token;
6370
6371 return MAILIMF_NO_ERROR;
6372
6373 free_list:
6374 clist_foreach(received_list, (clist_func) mailimf_received_free, NULL);
6375 clist_free(received_list);
6376 free_return:
6377 if (return_path != NULL)
6378 mailimf_return_free(return_path);
6379 err:
6380 return res;
6381}
6382#endif
6383
6384/*
6385return = "Return-Path:" path CRLF
6386*/
6387
6388static int mailimf_return_parse(const char * message, size_t length,
6389 size_t * index,
6390 struct mailimf_return ** result)
6391{
6392 struct mailimf_path * path;
6393 struct mailimf_return * return_path;
6394 size_t cur_token;
6395 int r;
6396 int res;
6397
6398 cur_token = * index;
6399
6400 r = mailimf_token_case_insensitive_parse(message, length,
6401 &cur_token, "Return-Path");
6402 if (r != MAILIMF_NO_ERROR) {
6403 res = r;
6404 goto err;
6405 }
6406
6407 r = mailimf_colon_parse(message, length, &cur_token);
6408 if (r != MAILIMF_NO_ERROR) {
6409 res = r;
6410 goto err;
6411 }
6412
6413 r = mailimf_path_parse(message, length, &cur_token, &path);
6414 if ( r!= MAILIMF_NO_ERROR) {
6415 res = r;
6416 goto err;
6417 }
6418
6419 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6420 if (r != MAILIMF_NO_ERROR) {
6421 res = r;
6422 goto free_path;
6423 }
6424
6425 return_path = mailimf_return_new(path);
6426 if (return_path == NULL) {
6427 res = MAILIMF_ERROR_MEMORY;
6428 goto free_path;
6429 }
6430
6431 * result = return_path;
6432 * index = cur_token;
6433
6434 return MAILIMF_NO_ERROR;
6435
6436 free_path:
6437 mailimf_path_free(path);
6438 err:
6439 return res;
6440}
6441
6442/*
6443path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
6444 obs-path
6445*/
6446
6447static int mailimf_path_parse(const char * message, size_t length,
6448 size_t * index, struct mailimf_path ** result)
6449{
6450 size_t cur_token;
6451 char * addr_spec;
6452 struct mailimf_path * path;
6453 int res;
6454 int r;
6455
6456 cur_token = * index;
6457 addr_spec = NULL;
6458
6459 r = mailimf_cfws_parse(message, length, &cur_token);
6460 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6461 res = r;
6462 goto err;
6463 }
6464
6465 r = mailimf_lower_parse(message, length, &cur_token);
6466 if (r != MAILIMF_NO_ERROR) {
6467 res = r;
6468 goto err;
6469 }
6470
6471 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
6472 switch (r) {
6473 case MAILIMF_NO_ERROR:
6474 break;
6475 case MAILIMF_ERROR_PARSE:
6476 r = mailimf_cfws_parse(message, length, &cur_token);
6477 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6478 res = r;
6479 goto err;
6480 }
6481 break;
6482 default:
6483 return r;
6484 }
6485
6486 r = mailimf_greater_parse(message, length, &cur_token);
6487 if (r != MAILIMF_NO_ERROR) {
6488 res = r;
6489 goto err;
6490 }
6491
6492 path = mailimf_path_new(addr_spec);
6493 if (path == NULL) {
6494 res = MAILIMF_ERROR_MEMORY;
6495 goto free_addr_spec;
6496 }
6497
6498 * index = cur_token;
6499 * result = path;
6500
6501 return MAILIMF_NO_ERROR;
6502
6503 free_addr_spec:
6504 if (addr_spec == NULL)
6505 mailimf_addr_spec_free(addr_spec);
6506 err:
6507 return res;
6508}
6509
6510/*
6511received = "Received:" name-val-list ";" date-time CRLF
6512*/
6513
6514#if 0
6515static int mailimf_received_parse(const char * message, size_t length,
6516 size_t * index,
6517 struct mailimf_received ** result)
6518{
6519 size_t cur_token;
6520 struct mailimf_received * received;
6521 struct mailimf_name_val_list * name_val_list;
6522 struct mailimf_date_time * date_time;
6523 int r;
6524 int res;
6525
6526 cur_token = * index;
6527
6528 r = mailimf_token_case_insensitive_parse(message, length,
6529 &cur_token, "Received");
6530 if (r != MAILIMF_NO_ERROR) {
6531 res = r;
6532 goto err;
6533 }
6534
6535 r = mailimf_colon_parse(message, length, &cur_token);
6536 if (r != MAILIMF_NO_ERROR) {
6537 res = r;
6538 goto err;
6539 }
6540
6541 r = mailimf_name_val_list_parse(message, length,
6542 &cur_token, &name_val_list);
6543 if (r != MAILIMF_NO_ERROR) {
6544 res = r;
6545 goto err;
6546 }
6547
6548 r = mailimf_semi_colon_parse(message, length, &cur_token);
6549 if (r != MAILIMF_NO_ERROR) {
6550 res = r;
6551 goto free_name_val_list;
6552 }
6553
6554 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
6555 if (r != MAILIMF_NO_ERROR) {
6556 res = r;
6557 goto free_name_val_list;
6558 }
6559
6560 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6561 if (r != MAILIMF_NO_ERROR) {
6562 res = r;
6563 goto free_date_time;
6564 }
6565
6566 received = mailimf_received_new(name_val_list, date_time);
6567 if (received == NULL) {
6568 res = MAILIMF_ERROR_MEMORY;
6569 goto free_date_time;
6570 }
6571
6572 * index = cur_token;
6573 * result = received;
6574
6575 return MAILIMF_NO_ERROR;
6576
6577 free_date_time:
6578 mailimf_date_time_free(date_time);
6579 free_name_val_list:
6580 mailimf_name_val_list_free(name_val_list);
6581 err:
6582 return res;
6583}
6584#endif
6585
6586/*
6587name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
6588*/
6589
6590#if 0
6591static int
6592mailimf_name_val_list_parse(const char * message, size_t length,
6593 size_t * index,
6594 struct mailimf_name_val_list ** result)
6595{
6596 size_t cur_token;
6597 struct mailimf_name_val_pair * pair;
6598 struct mailimf_name_val_list * name_val_list;
6599 clist* list;
6600 int res;
6601 int r;
6602
6603 cur_token = * index;
6604 list = NULL;
6605
6606 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6607
6608 if (r == MAILIMF_NO_ERROR){
6609 size_t final_token;
6610
6611 list = clist_new();
6612 if (list == NULL) {
6613 mailimf_name_val_pair_free(pair);
6614 res = MAILIMF_ERROR_MEMORY;
6615 goto err;
6616 }
6617
6618 r = clist_append(list, pair);
6619 if (r < 0) {
6620 mailimf_name_val_pair_free(pair);
6621 res = MAILIMF_ERROR_MEMORY;
6622 goto free_list;
6623 }
6624
6625 final_token = cur_token;
6626
6627 while (1) {
6628 r = mailimf_cfws_parse(message, length, &cur_token);
6629 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6630 res = r;
6631 goto free_list;
6632 }
6633
6634 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6635 if (r == MAILIMF_NO_ERROR) {
6636 /* do nothing */
6637 }
6638 else if (r == MAILIMF_ERROR_PARSE)
6639 break;
6640 else {
6641 res = r;
6642 goto free_list;
6643 }
6644
6645 r = clist_append(list, pair);
6646 if (r < 0) {
6647 mailimf_name_val_pair_free(pair);
6648 res = MAILIMF_ERROR_MEMORY;
6649 goto free_list;
6650 }
6651
6652 final_token = cur_token;
6653 }
6654 cur_token = final_token;
6655 }
6656
6657 name_val_list = mailimf_name_val_list_new(list);
6658 if (name_val_list == NULL) {
6659 res = MAILIMF_ERROR_MEMORY;
6660 goto free_list;
6661 }
6662
6663 * index = cur_token;
6664 * result = name_val_list;
6665
6666 return MAILIMF_NO_ERROR;
6667
6668 free_list:
6669 if (list != NULL) {
6670 clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL);
6671 clist_free(list);
6672 }
6673 err:
6674 return res;
6675}
6676#endif
6677
6678/*
6679name-val-pair = item-name CFWS item-value
6680*/
6681
6682#if 0
6683static int
6684mailimf_name_val_pair_parse(const char * message, size_t length,
6685 size_t * index,
6686 struct mailimf_name_val_pair ** result)
6687{
6688 size_t cur_token;
6689 char * item_name;
6690 struct mailimf_item_value * item_value;
6691 struct mailimf_name_val_pair * name_val_pair;
6692 int r;
6693 int res;
6694
6695 cur_token = * index;
6696
6697 r = mailimf_cfws_parse(message, length, &cur_token);
6698 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6699 res = r;
6700 goto err;
6701 }
6702
6703 r = mailimf_item_name_parse(message, length, &cur_token, &item_name);
6704 if (r != MAILIMF_NO_ERROR) {
6705 res = r;
6706 goto err;
6707 }
6708
6709 r = mailimf_cfws_parse(message, length, &cur_token);
6710 if (r != MAILIMF_NO_ERROR) {
6711 res = r;
6712 goto free_item_name;
6713 }
6714
6715 r = mailimf_item_value_parse(message, length, &cur_token, &item_value);
6716 if (r != MAILIMF_NO_ERROR) {
6717 res = r;
6718 goto free_item_name;
6719 }
6720
6721 name_val_pair = mailimf_name_val_pair_new(item_name, item_value);
6722 if (name_val_pair == NULL) {
6723 res = MAILIMF_ERROR_MEMORY;
6724 goto free_item_value;
6725 }
6726
6727 * result = name_val_pair;
6728 * index = cur_token;
6729
6730 return MAILIMF_NO_ERROR;
6731
6732 free_item_value:
6733 mailimf_item_value_free(item_value);
6734 free_item_name:
6735 mailimf_item_name_free(item_name);
6736 err:
6737 return res;
6738}
6739#endif
6740
6741/*
6742item-name = ALPHA *(["-"] (ALPHA / DIGIT))
6743*/
6744
6745#if 0
6746static int mailimf_item_name_parse(const char * message, size_t length,
6747 size_t * index, char ** result)
6748{
6749 size_t cur_token;
6750 size_t begin;
6751 char * item_name;
6752 char ch;
6753 int digit;
6754 int r;
6755 int res;
6756
6757 cur_token = * index;
6758
6759 begin = cur_token;
6760
6761 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6762 if (r != MAILIMF_NO_ERROR) {
6763 res = r;
6764 goto err;
6765 }
6766
6767 while (1) {
6768 int minus_sign;
6769
6770 minus_sign = mailimf_minus_parse(message, length, &cur_token);
6771
6772 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6773 if (r == MAILIMF_ERROR_PARSE)
6774 r = mailimf_digit_parse(message, length, &cur_token, &digit);
6775
6776 if (r == MAILIMF_NO_ERROR) {
6777 /* do nothing */
6778 }
6779 if (r == MAILIMF_ERROR_PARSE)
6780 break;
6781 else if (r != MAILIMF_NO_ERROR) {
6782 res = r;
6783 goto err;
6784 }
6785 }
6786
6787 item_name = strndup(message + begin, cur_token - begin);
6788 if (item_name == NULL) {
6789 res = MAILIMF_ERROR_MEMORY;
6790 goto err;
6791 }
6792
6793 * index = cur_token;
6794 * result = item_name;
6795
6796 return MAILIMF_NO_ERROR;
6797
6798 err:
6799 return res;
6800}
6801#endif
6802
6803/*
6804item-value = 1*angle-addr / addr-spec /
6805 atom / domain / msg-id
6806*/
6807
6808#if 0
6809static int is_item_value_atext(char ch)
6810{
6811 switch (ch) {
6812 case '\t':
6813 case ' ':
6814 case '\r':
6815 case '\n':
6816 case ';':
6817 return FALSE;
6818 default:
6819 return TRUE;
6820 }
6821}
6822
6823static int mailimf_item_value_atom_parse(const char * message, size_t length,
6824 size_t * index, char ** result)
6825{
6826 char * atom;
6827 size_t cur_token;
6828 int r;
6829
6830 cur_token = * index;
6831
6832 r = mailimf_cfws_parse(message, length, &cur_token);
6833 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6834 return r;
6835
6836 r = mailimf_custom_string_parse(message, length, &cur_token,
6837 &atom, is_item_value_atext);
6838 if (r != MAILIMF_NO_ERROR)
6839 return r;
6840
6841 r = mailimf_cfws_parse(message, length, &cur_token);
6842 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6843 return r;
6844
6845 * index = cur_token;
6846 * result = atom;
6847
6848 return MAILIMF_NO_ERROR;
6849}
6850
6851static int mailimf_item_value_parse(const char * message, size_t length,
6852 size_t * index,
6853 struct mailimf_item_value ** result)
6854{
6855 size_t cur_token;
6856 clist * angle_addr_list;
6857 char * addr_spec;
6858 char * atom;
6859 char * domain;
6860 char * msg_id;
6861 int type;
6862 struct mailimf_item_value * item_value;
6863 int r;
6864 int res;
6865
6866 cur_token = * index;
6867
6868 angle_addr_list = NULL;
6869 addr_spec = NULL;
6870 atom = NULL;
6871 domain = NULL;
6872 msg_id = NULL;
6873
6874 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6875 &angle_addr_list,
6876 (mailimf_struct_parser *)
6877 mailimf_angle_addr_parse,
6878 (mailimf_struct_destructor *)
6879 mailimf_angle_addr_free);
6880 if (r == MAILIMF_NO_ERROR)
6881 type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST;
6882
6883 if (r == MAILIMF_ERROR_PARSE) {
6884 r = mailimf_addr_spec_parse(message, length, &cur_token,
6885 &addr_spec);
6886 if (r == MAILIMF_NO_ERROR)
6887 type = MAILIMF_ITEM_VALUE_ADDR_SPEC;
6888 }
6889
6890 if (r == MAILIMF_ERROR_PARSE) {
6891 r = mailimf_msg_id_parse(message, length, &cur_token,
6892 &msg_id);
6893 if (r == MAILIMF_NO_ERROR)
6894 type = MAILIMF_ITEM_VALUE_MSG_ID;
6895 }
6896
6897 /*
6898 else if (mailimf_domain_parse(message, length, &cur_token,
6899 &domain))
6900 type = MAILIMF_ITEM_VALUE_DOMAIN;
6901 */
6902 /*
6903 else if (mailimf_atom_parse(message, length, &cur_token,
6904 &atom))
6905 type = MAILIMF_ITEM_VALUE_ATOM;
6906 */
6907
6908 if (r == MAILIMF_ERROR_PARSE) {
6909 r = mailimf_item_value_atom_parse(message, length, &cur_token,
6910 &atom);
6911 if (r == MAILIMF_NO_ERROR)
6912 type = MAILIMF_ITEM_VALUE_ATOM;
6913 }
6914
6915 if (r != MAILIMF_NO_ERROR) {
6916 res = r;
6917 goto err;
6918 }
6919
6920 item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec,
6921 atom, domain, msg_id);
6922 if (item_value == NULL) {
6923 res = MAILIMF_ERROR_MEMORY;
6924 goto free;
6925 }
6926
6927 * result = item_value;
6928 * index = cur_token;
6929
6930 return MAILIMF_NO_ERROR;
6931
6932 free:
6933 if (angle_addr_list != NULL) {
6934 clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL);
6935 clist_free(angle_addr_list);
6936 }
6937 if (addr_spec != NULL)
6938 mailimf_addr_spec_free(addr_spec);
6939 if (atom != NULL)
6940 mailimf_atom_free(atom);
6941 if (domain != NULL)
6942 mailimf_domain_free(domain);
6943 if (msg_id != NULL)
6944 mailimf_msg_id_free(msg_id);
6945 err:
6946 return res;
6947}
6948#endif
6949
6950/*
6951optional-field = field-name ":" unstructured CRLF
6952*/
6953
6954static int
6955mailimf_optional_field_parse(const char * message, size_t length,
6956 size_t * index,
6957 struct mailimf_optional_field ** result)
6958{
6959 char * name;
6960 char * value;
6961 struct mailimf_optional_field * optional_field;
6962 size_t cur_token;
6963 int r;
6964 int res;
6965
6966 cur_token = * index;
6967
6968 r = mailimf_field_name_parse(message, length, &cur_token, &name);
6969 if (r != MAILIMF_NO_ERROR) {
6970 res = r;
6971 goto err;
6972 }
6973
6974 r = mailimf_colon_parse(message, length, &cur_token);
6975 if (r != MAILIMF_NO_ERROR) {
6976 res = r;
6977 goto free_name;
6978 }
6979
6980 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
6981 if (r != MAILIMF_NO_ERROR) {
6982 res = r;
6983 goto free_name;
6984 }
6985
6986 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6987 if (r != MAILIMF_NO_ERROR) {
6988 res = r;
6989 goto free_value;
6990 }
6991
6992 optional_field = mailimf_optional_field_new(name, value);
6993 if (optional_field == NULL) {
6994 res = MAILIMF_ERROR_MEMORY;
6995 goto free_value;
6996 }
6997
6998 * result = optional_field;
6999 * index = cur_token;
7000
7001 return MAILIMF_NO_ERROR;
7002
7003 free_value:
7004 mailimf_unstructured_free(value);
7005 free_name:
7006 mailimf_field_name_free(name);
7007 err:
7008 return res;
7009}
7010
7011/*
7012field-name = 1*ftext
7013*/
7014
7015static inline int is_ftext(char ch);
7016
7017static int mailimf_field_name_parse(const char * message, size_t length,
7018 size_t * index, char ** result)
7019{
7020 char * field_name;
7021 size_t cur_token;
7022 size_t end;
7023
7024 cur_token = * index;
7025
7026 end = cur_token;
7027 if (end >= length) {
7028 return MAILIMF_ERROR_PARSE;
7029 }
7030
7031 while (is_ftext(message[end])) {
7032 end ++;
7033 if (end >= length)
7034 break;
7035 }
7036 if (end == cur_token) {
7037 return MAILIMF_ERROR_PARSE;
7038 }
7039
7040 /* field_name = strndup(message + cur_token, end - cur_token); */
7041 field_name = malloc(end - cur_token + 1);
7042 if (field_name == NULL) {
7043 return MAILIMF_ERROR_MEMORY;
7044 }
7045 strncpy(field_name, message + cur_token, end - cur_token);
7046 field_name[end - cur_token] = '\0';
7047
7048 cur_token = end;
7049
7050 * index = cur_token;
7051 * result = field_name;
7052
7053 return MAILIMF_NO_ERROR;
7054}
7055
7056/*
7057ftext = %d33-57 / ; Any character except
7058 %d59-126 ; controls, SP, and
7059 ; ":".
7060*/
7061
7062static inline int is_ftext(char ch)
7063{
7064 unsigned char uch = (unsigned char) ch;
7065
7066 if (uch < 33)
7067 return FALSE;
7068
7069 if (uch == 58)
7070 return FALSE;
7071
7072 return TRUE;
7073}
7074
7075/*
7076static int mailimf_ftext_parse(const char * message, size_t length,
7077 size_t * index, gchar * result)
7078{
7079 return mailimf_typed_text_parse(message, length, index, result, is_ftext);
7080}
7081*/
7082
7083
7084
7085
7086static int mailimf_envelope_field_parse(const char * message, size_t length,
7087 size_t * index,
7088 struct mailimf_field ** result)
7089{
7090 size_t cur_token;
7091 int type;
7092 struct mailimf_orig_date * orig_date;
7093 struct mailimf_from * from;
7094 struct mailimf_sender * sender;
7095 struct mailimf_reply_to * reply_to;
7096 struct mailimf_to * to;
7097 struct mailimf_cc * cc;
7098 struct mailimf_bcc * bcc;
7099 struct mailimf_message_id * message_id;
7100 struct mailimf_in_reply_to * in_reply_to;
7101 struct mailimf_references * references;
7102 struct mailimf_subject * subject;
7103 struct mailimf_optional_field * optional_field;
7104 struct mailimf_field * field;
7105 int guessed_type;
7106 int r;
7107 int res;
7108
7109 cur_token = * index;
7110
7111 orig_date = NULL;
7112 from = NULL;
7113 sender = NULL;
7114 reply_to = NULL;
7115 to = NULL;
7116 cc = NULL;
7117 bcc = NULL;
7118 message_id = NULL;
7119 in_reply_to = NULL;
7120 references = NULL;
7121 subject = NULL;
7122 optional_field = NULL;
7123
7124 guessed_type = guess_header_type(message, length, cur_token);
7125 type = MAILIMF_FIELD_NONE;
7126
7127 switch (guessed_type) {
7128 case MAILIMF_FIELD_ORIG_DATE:
7129 r = mailimf_orig_date_parse(message, length, &cur_token,
7130 &orig_date);
7131 if (r == MAILIMF_NO_ERROR)
7132 type = guessed_type;
7133 else if (r == MAILIMF_ERROR_PARSE) {
7134 /* do nothing */
7135 }
7136 else {
7137 res = r;
7138 goto err;
7139 }
7140 break;
7141 case MAILIMF_FIELD_FROM:
7142 r = mailimf_from_parse(message, length, &cur_token,
7143 &from);
7144 if (r == MAILIMF_NO_ERROR)
7145 type = guessed_type;
7146 else if (r == MAILIMF_ERROR_PARSE) {
7147 /* do nothing */
7148 }
7149 else {
7150 res = r;
7151 goto err;
7152 }
7153 break;
7154 case MAILIMF_FIELD_SENDER:
7155 r = mailimf_sender_parse(message, length, &cur_token,
7156 &sender);
7157 if (r == MAILIMF_NO_ERROR)
7158 type = guessed_type;
7159 else if (r == MAILIMF_ERROR_PARSE) {
7160 /* do nothing */
7161 }
7162 else {
7163 res = r;
7164 goto err;
7165 }
7166 break;
7167 case MAILIMF_FIELD_REPLY_TO:
7168 r = mailimf_reply_to_parse(message, length, &cur_token,
7169 &reply_to);
7170 if (r == MAILIMF_NO_ERROR)
7171 type = guessed_type;
7172 else if (r == MAILIMF_ERROR_PARSE) {
7173 /* do nothing */
7174 }
7175 else {
7176 res = r;
7177 goto err;
7178 }
7179 break;
7180 case MAILIMF_FIELD_TO:
7181 r = mailimf_to_parse(message, length, &cur_token,
7182 &to);
7183 if (r == MAILIMF_NO_ERROR)
7184 type = guessed_type;
7185 else if (r == MAILIMF_ERROR_PARSE) {
7186 /* do nothing */
7187 }
7188 else {
7189 res = r;
7190 goto err;
7191 }
7192 break;
7193 case MAILIMF_FIELD_CC:
7194 r = mailimf_cc_parse(message, length, &cur_token,
7195 &cc);
7196 if (r == MAILIMF_NO_ERROR)
7197 type = guessed_type;
7198 else if (r == MAILIMF_ERROR_PARSE) {
7199 /* do nothing */
7200 }
7201 else {
7202 res = r;
7203 goto err;
7204 }
7205 break;
7206 case MAILIMF_FIELD_BCC:
7207 r = mailimf_bcc_parse(message, length, &cur_token,
7208 &bcc);
7209 if (r == MAILIMF_NO_ERROR)
7210 type = guessed_type;
7211 else if (r == MAILIMF_ERROR_PARSE) {
7212 /* do nothing */
7213 }
7214 else {
7215 res = r;
7216 goto err;
7217 }
7218 break;
7219 case MAILIMF_FIELD_MESSAGE_ID:
7220 r = mailimf_message_id_parse(message, length, &cur_token,
7221 &message_id);
7222 if (r == MAILIMF_NO_ERROR)
7223 type = guessed_type;
7224 else if (r == MAILIMF_ERROR_PARSE) {
7225 /* do nothing */
7226 }
7227 else {
7228 res = r;
7229 goto err;
7230 }
7231 break;
7232 case MAILIMF_FIELD_IN_REPLY_TO:
7233 r = mailimf_in_reply_to_parse(message, length, &cur_token,
7234 &in_reply_to);
7235 if (r == MAILIMF_NO_ERROR)
7236 type = guessed_type;
7237 else if (r == MAILIMF_ERROR_PARSE) {
7238 /* do nothing */
7239 }
7240 else {
7241 res = r;
7242 goto err;
7243 }
7244 break;
7245 case MAILIMF_FIELD_REFERENCES:
7246 r = mailimf_references_parse(message, length, &cur_token,
7247 &references);
7248 if (r == MAILIMF_NO_ERROR)
7249 type = guessed_type;
7250 else if (r == MAILIMF_ERROR_PARSE) {
7251 /* do nothing */
7252 }
7253 else {
7254 res = r;
7255 goto err;
7256 }
7257 break;
7258 case MAILIMF_FIELD_SUBJECT:
7259 r = mailimf_subject_parse(message, length, &cur_token,
7260 &subject);
7261 if (r == MAILIMF_NO_ERROR)
7262 type = guessed_type;
7263 else if (r == MAILIMF_ERROR_PARSE) {
7264 /* do nothing */
7265 }
7266 else {
7267 res = r;
7268 goto err;
7269 }
7270 break;
7271 }
7272
7273 if (type == MAILIMF_FIELD_NONE) {
7274 res = MAILIMF_ERROR_PARSE;
7275 goto err;
7276 }
7277
7278 field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
7279 NULL, NULL, NULL,
7280 orig_date, from, sender, reply_to, to,
7281 cc, bcc, message_id, in_reply_to, references,
7282 subject, NULL, NULL, optional_field);
7283 if (field == NULL) {
7284 res = MAILIMF_ERROR_MEMORY;
7285 goto free_field;
7286 }
7287
7288 * result = field;
7289 * index = cur_token;
7290
7291 return MAILIMF_NO_ERROR;
7292
7293 free_field:
7294 if (orig_date != NULL)
7295 mailimf_orig_date_free(orig_date);
7296 if (from != NULL)
7297 mailimf_from_free(from);
7298 if (sender != NULL)
7299 mailimf_sender_free(sender);
7300 if (reply_to != NULL)
7301 mailimf_reply_to_free(reply_to);
7302 if (to != NULL)
7303 mailimf_to_free(to);
7304 if (cc != NULL)
7305 mailimf_cc_free(cc);
7306 if (bcc != NULL)
7307 mailimf_bcc_free(bcc);
7308 if (message_id != NULL)
7309 mailimf_message_id_free(message_id);
7310 if (in_reply_to != NULL)
7311 mailimf_in_reply_to_free(in_reply_to);
7312 if (references != NULL)
7313 mailimf_references_free(references);
7314 if (subject != NULL)
7315 mailimf_subject_free(subject);
7316 if (optional_field != NULL)
7317 mailimf_optional_field_free(optional_field);
7318 err:
7319 return res;
7320}
7321
7322int mailimf_envelope_fields_parse(const char * message, size_t length,
7323 size_t * index,
7324 struct mailimf_fields ** result)
7325{
7326 size_t cur_token;
7327 clist * list;
7328 struct mailimf_fields * fields;
7329 int r;
7330 int res;
7331
7332 cur_token = * index;
7333
7334 list = clist_new();
7335 if (list == NULL) {
7336 res = MAILIMF_ERROR_MEMORY;
7337 goto err;
7338 }
7339
7340 while (1) {
7341 struct mailimf_field * elt;
7342
7343 r = mailimf_envelope_field_parse(message, length, &cur_token, &elt);
7344 if (r == MAILIMF_NO_ERROR) {
7345 r = clist_append(list, elt);
7346 if (r < 0) {
7347 res = MAILIMF_ERROR_MEMORY;
7348 goto free;
7349 }
7350 }
7351 else if (r == MAILIMF_ERROR_PARSE) {
7352 r = mailimf_ignore_field_parse(message, length, &cur_token);
7353 if (r == MAILIMF_NO_ERROR) {
7354 /* do nothing */
7355 }
7356 else if (r == MAILIMF_ERROR_PARSE) {
7357 break;
7358 }
7359 else {
7360 res = r;
7361 goto free;
7362 }
7363 }
7364 else {
7365 res = r;
7366 goto free;
7367 }
7368 }
7369
7370 fields = mailimf_fields_new(list);
7371 if (fields == NULL) {
7372 res = MAILIMF_ERROR_MEMORY;
7373 goto free;
7374 }
7375
7376 * result = fields;
7377 * index = cur_token;
7378
7379 return MAILIMF_NO_ERROR;
7380
7381 free:
7382 if (list != NULL) {
7383 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7384 clist_free(list);
7385 }
7386 err:
7387 return res;
7388}
7389
7390
7391static int
7392mailimf_envelope_or_optional_field_parse(const char * message,
7393 size_t length,
7394 size_t * index,
7395 struct mailimf_field ** result)
7396{
7397 int r;
7398 size_t cur_token;
7399 struct mailimf_optional_field * optional_field;
7400 struct mailimf_field * field;
7401
7402 r = mailimf_envelope_field_parse(message, length, index, result);
7403 if (r == MAILIMF_NO_ERROR)
7404 return MAILIMF_NO_ERROR;
7405
7406 cur_token = * index;
7407
7408 r = mailimf_optional_field_parse(message, length, &cur_token,
7409 &optional_field);
7410 if (r != MAILIMF_NO_ERROR)
7411 return r;
7412
7413 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL,
7414 NULL, NULL, NULL,
7415 NULL, NULL, NULL,
7416 NULL, NULL, NULL,
7417 NULL, NULL, NULL,
7418 NULL, NULL, NULL, NULL, NULL,
7419 NULL, NULL, NULL, optional_field);
7420 if (field == NULL) {
7421 mailimf_optional_field_free(optional_field);
7422 return MAILIMF_ERROR_MEMORY;
7423 }
7424
7425 * result = field;
7426 * index = cur_token;
7427
7428 return MAILIMF_NO_ERROR;
7429}
7430
7431
7432int
7433mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
7434 size_t * index,
7435 struct mailimf_fields ** result)
7436{
7437 size_t cur_token;
7438 clist * list;
7439 struct mailimf_fields * fields;
7440 int r;
7441 int res;
7442
7443 cur_token = * index;
7444
7445 list = NULL;
7446
7447 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7448 &list,
7449 (mailimf_struct_parser *)
7450 mailimf_envelope_or_optional_field_parse,
7451 (mailimf_struct_destructor *)
7452 mailimf_field_free);
7453 switch (r) {
7454 case MAILIMF_NO_ERROR:
7455 /* do nothing */
7456 break;
7457
7458 case MAILIMF_ERROR_PARSE:
7459 list = clist_new();
7460 if (list == NULL) {
7461 res = MAILIMF_ERROR_MEMORY;
7462 goto err;
7463 }
7464 break;
7465
7466 default:
7467 res = r;
7468 goto err;
7469 }
7470
7471 fields = mailimf_fields_new(list);
7472 if (fields == NULL) {
7473 res = MAILIMF_ERROR_MEMORY;
7474 goto free;
7475 }
7476
7477 * result = fields;
7478 * index = cur_token;
7479
7480 return MAILIMF_NO_ERROR;
7481
7482 free:
7483 if (list != NULL) {
7484 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7485 clist_free(list);
7486 }
7487 err:
7488 return res;
7489}
7490
7491
7492
7493static int
7494mailimf_only_optional_field_parse(const char * message,
7495 size_t length,
7496 size_t * index,
7497 struct mailimf_field ** result)
7498{
7499 int r;
7500 size_t cur_token;
7501 struct mailimf_optional_field * optional_field;
7502 struct mailimf_field * field;
7503
7504 cur_token = * index;
7505
7506 r = mailimf_optional_field_parse(message, length, &cur_token,
7507 &optional_field);
7508 if (r != MAILIMF_NO_ERROR)
7509 return r;
7510
7511 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL,
7512 NULL, NULL, NULL, NULL, NULL,
7513 NULL, NULL, NULL, NULL, NULL,
7514 NULL, NULL, NULL, NULL, NULL,
7515 NULL, NULL, NULL, optional_field);
7516 if (field == NULL) {
7517 mailimf_optional_field_free(optional_field);
7518 return MAILIMF_ERROR_MEMORY;
7519 }
7520
7521 * result = field;
7522 * index = cur_token;
7523
7524 return MAILIMF_NO_ERROR;
7525}
7526
7527
7528int
7529mailimf_optional_fields_parse(const char * message, size_t length,
7530 size_t * index,
7531 struct mailimf_fields ** result)
7532{
7533 size_t cur_token;
7534 clist * list;
7535 struct mailimf_fields * fields;
7536 int r;
7537 int res;
7538
7539 cur_token = * index;
7540
7541 list = NULL;
7542
7543 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7544 &list,
7545 (mailimf_struct_parser *)
7546 mailimf_only_optional_field_parse,
7547 (mailimf_struct_destructor *)
7548 mailimf_field_free);
7549 switch (r) {
7550 case MAILIMF_NO_ERROR:
7551 /* do nothing */
7552 break;
7553
7554 case MAILIMF_ERROR_PARSE:
7555 list = clist_new();
7556 if (list == NULL) {
7557 res = MAILIMF_ERROR_MEMORY;
7558 goto err;
7559 }
7560 break;
7561
7562 default:
7563 res = r;
7564 goto err;
7565 }
7566
7567 fields = mailimf_fields_new(list);
7568 if (fields == NULL) {
7569 res = MAILIMF_ERROR_MEMORY;
7570 goto free;
7571 }
7572
7573 * result = fields;
7574 * index = cur_token;
7575
7576 return MAILIMF_NO_ERROR;
7577
7578 free:
7579 if (list != NULL) {
7580 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7581 clist_free(list);
7582 }
7583 err:
7584 return res;
7585}
diff --git a/libetpan/src/low-level/imf/mailimf.h b/libetpan/src/low-level/imf/mailimf.h
new file mode 100644
index 0000000..c2231dd
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf.h
@@ -0,0 +1,347 @@
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 MAILIMF_H
37
38#define MAILIMF_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimf_types.h>
45#include <libetpan/mailimf_write_generic.h>
46#include <libetpan/mailimf_write_file.h>
47#include <libetpan/mailimf_write_mem.h>
48#include <libetpan/mailimf_types_helper.h>
49
50#include <inttypes.h>
51#include <sys/types.h>
52
53/*
54 mailimf_message_parse will parse the given message
55
56 @param message this is a string containing the message content
57 @param length this is the size of the given string
58 @param index this is a pointer to the start of the message in
59 the given string, (* index) is modified to point at the end
60 of the parsed data
61 @param result the result of the parse operation is stored in
62 (* result)
63
64 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
65*/
66
67int mailimf_message_parse(const char * message, size_t length,
68 size_t * index,
69 struct mailimf_message ** result);
70
71/*
72 mailimf_body_parse will parse the given text part of a message
73
74 @param message this is a string containing the message text part
75 @param length this is the size of the given string
76 @param index this is a pointer to the start of the message text part in
77 the given string, (* index) is modified to point at the end
78 of the parsed data
79 @param result the result of the parse operation is stored in
80 (* result)
81
82 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
83*/
84
85int mailimf_body_parse(const char * message, size_t length,
86 size_t * index,
87 struct mailimf_body ** result);
88
89/*
90 mailimf_fields_parse will parse the given header fields
91
92 @param message this is a string containing the header fields
93 @param length this is the size of the given string
94 @param index this is a pointer to the start of the header fields in
95 the given string, (* index) is modified to point at the end
96 of the parsed data
97 @param result the result of the parse operation is stored in
98 (* result)
99
100 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
101*/
102
103int mailimf_fields_parse(const char * message, size_t length,
104 size_t * index,
105 struct mailimf_fields ** result);
106
107/*
108 mailimf_mailbox_list_parse will parse the given mailbox list
109
110 @param message this is a string containing the mailbox list
111 @param length this is the size of the given string
112 @param index this is a pointer to the start of the mailbox list in
113 the given string, (* index) is modified to point at the end
114 of the parsed data
115 @param result the result of the parse operation is stored in
116 (* result)
117
118 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
119*/
120
121int
122mailimf_mailbox_list_parse(const char * message, size_t length,
123 size_t * index,
124 struct mailimf_mailbox_list ** result);
125
126/*
127 mailimf_address_list_parse will parse the given address list
128
129 @param message this is a string containing the address list
130 @param length this is the size of the given string
131 @param index this is a pointer to the start of the address list in
132 the given string, (* index) is modified to point at the end
133 of the parsed data
134 @param result the result of the parse operation is stored in
135 (* result)
136
137 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
138*/
139
140int
141mailimf_address_list_parse(const char * message, size_t length,
142 size_t * index,
143 struct mailimf_address_list ** result);
144
145/*
146 mailimf_address_parse will parse the given address
147
148 @param message this is a string containing the address
149 @param length this is the size of the given string
150 @param index this is a pointer to the start of the address in
151 the given string, (* index) is modified to point at the end
152 of the parsed data
153 @param result the result of the parse operation is stored in
154 (* result)
155
156 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
157*/
158
159int mailimf_address_parse(const char * message, size_t length,
160 size_t * index,
161 struct mailimf_address ** result);
162
163/*
164 mailimf_mailbox_parse will parse the given address
165
166 @param message this is a string containing the mailbox
167 @param length this is the size of the given string
168 @param index this is a pointer to the start of the mailbox in
169 the given string, (* index) is modified to point at the end
170 of the parsed data
171 @param result the result of the parse operation is stored in
172 (* result)
173
174 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
175*/
176
177int mailimf_mailbox_parse(const char * message, size_t length,
178 size_t * index,
179 struct mailimf_mailbox ** result);
180
181/*
182 mailimf_date_time_parse will parse the given RFC 2822 date
183
184 @param message this is a string containing the date
185 @param length this is the size of the given string
186 @param index this is a pointer to the start of the date in
187 the given string, (* index) is modified to point at the end
188 of the parsed data
189 @param result the result of the parse operation is stored in
190 (* result)
191
192 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
193*/
194
195int mailimf_date_time_parse(const char * message, size_t length,
196 size_t * index,
197 struct mailimf_date_time ** result);
198
199/*
200 mailimf_envelope_fields_parse will parse the given fields (Date,
201 From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To,
202 References and Subject)
203
204 @param message this is a string containing the header fields
205 @param length this is the size of the given string
206 @param index this is a pointer to the start of the header fields in
207 the given string, (* index) is modified to point at the end
208 of the parsed data
209 @param result the result of the parse operation is stored in
210 (* result)
211
212 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
213*/
214
215int mailimf_envelope_fields_parse(const char * message, size_t length,
216 size_t * index,
217 struct mailimf_fields ** result);
218
219/*
220 mailimf_ignore_field_parse will skip the given field
221
222 @param message this is a string containing the header field
223 @param length this is the size of the given string
224 @param index this is a pointer to the start of the header field in
225 the given string, (* index) is modified to point at the end
226 of the parsed data
227
228 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
229*/
230
231
232int mailimf_ignore_field_parse(const char * message, size_t length,
233 size_t * index);
234
235/*
236 mailimf_envelope_fields will parse the given fields (Date,
237 From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To,
238 References and Subject), other fields will be added as optional
239 fields.
240
241 @param message this is a string containing the header fields
242 @param length this is the size of the given string
243 @param index this is a pointer to the start of the header fields in
244 the given string, (* index) is modified to point at the end
245 of the parsed data
246 @param result the result of the parse operation is stored in
247 (* result)
248
249 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
250*/
251
252
253int
254mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
255 size_t * index,
256 struct mailimf_fields ** result);
257
258/*
259 mailimf_envelope_fields will parse the given fields as optional
260 fields.
261
262 @param message this is a string containing the header fields
263 @param length this is the size of the given string
264 @param index this is a pointer to the start of the header fields in
265 the given string, (* index) is modified to point at the end
266 of the parsed data
267 @param result the result of the parse operation is stored in
268 (* result)
269
270 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
271*/
272
273int
274mailimf_optional_fields_parse(const char * message, size_t length,
275 size_t * index,
276 struct mailimf_fields ** result);
277
278
279/* internal use, exported for MIME */
280
281int mailimf_fws_parse(const char * message, size_t length, size_t * index);
282
283int mailimf_cfws_parse(const char * message, size_t length,
284 size_t * index);
285
286int mailimf_char_parse(const char * message, size_t length,
287 size_t * index, char token);
288
289int mailimf_unstrict_char_parse(const char * message, size_t length,
290 size_t * index, char token);
291
292int mailimf_crlf_parse(const char * message, size_t length, size_t * index);
293
294int
295mailimf_custom_string_parse(const char * message, size_t length,
296 size_t * index, char ** result,
297 int (* is_custom_char)(char));
298
299int
300mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
301 size_t * index, char * token,
302 size_t token_length);
303
304#define mailimf_token_case_insensitive_parse(message, length, index, token) \
305 mailimf_token_case_insensitive_len_parse(message, length, index, token, \
306 sizeof(token) - 1)
307
308int mailimf_quoted_string_parse(const char * message, size_t length,
309 size_t * index, char ** result);
310
311int
312mailimf_number_parse(const char * message, size_t length,
313 size_t * index, uint32_t * result);
314
315int mailimf_msg_id_parse(const char * message, size_t length,
316 size_t * index,
317 char ** result);
318
319int mailimf_msg_id_list_parse(const char * message, size_t length,
320 size_t * index, clist ** result);
321
322int mailimf_word_parse(const char * message, size_t length,
323 size_t * index, char ** result);
324
325int mailimf_atom_parse(const char * message, size_t length,
326 size_t * index, char ** result);
327
328int mailimf_fws_atom_parse(const char * message, size_t length,
329 size_t * index, char ** result);
330
331int mailimf_fws_word_parse(const char * message, size_t length,
332 size_t * index, char ** result);
333
334int mailimf_fws_quoted_string_parse(const char * message, size_t length,
335 size_t * index, char ** result);
336
337/* exported for IMAP */
338
339int mailimf_references_parse(const char * message, size_t length,
340 size_t * index,
341 struct mailimf_references ** result);
342
343#ifdef __cplusplus
344}
345#endif
346
347#endif
diff --git a/libetpan/src/low-level/imf/mailimf_types.c b/libetpan/src/low-level/imf/mailimf_types.c
new file mode 100644
index 0000000..a6e4db9
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_types.c
@@ -0,0 +1,868 @@
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 "mailimf_types.h"
37#include "mmapstring.h"
38#include <stdlib.h>
39
40void mailimf_atom_free(char * atom)
41{
42 free(atom);
43}
44
45void mailimf_dot_atom_free(char * dot_atom)
46{
47 free(dot_atom);
48}
49
50void mailimf_dot_atom_text_free(char * dot_atom)
51{
52 free(dot_atom);
53}
54
55void mailimf_quoted_string_free(char * quoted_string)
56{
57 free(quoted_string);
58}
59
60void mailimf_word_free(char * word)
61{
62 free(word);
63}
64
65void mailimf_phrase_free(char * phrase)
66{
67 free(phrase);
68}
69
70void mailimf_unstructured_free(char * unstructured)
71{
72 free(unstructured);
73}
74
75
76struct mailimf_date_time *
77mailimf_date_time_new(int dt_day, int dt_month, int dt_year,
78 int dt_hour, int dt_min, int dt_sec, int dt_zone)
79{
80 struct mailimf_date_time * date_time;
81
82 date_time = malloc(sizeof(* date_time));
83 if (date_time == NULL)
84 return NULL;
85
86 date_time->dt_day = dt_day;
87 date_time->dt_month = dt_month;
88 date_time->dt_year = dt_year;
89 date_time->dt_hour = dt_hour;
90 date_time->dt_min = dt_min;
91 date_time->dt_sec = dt_sec;
92 date_time->dt_zone = dt_zone;
93
94 return date_time;
95}
96
97
98void mailimf_date_time_free(struct mailimf_date_time * date_time)
99{
100 free(date_time);
101}
102
103
104
105
106struct mailimf_address *
107mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox,
108 struct mailimf_group * ad_group)
109{
110 struct mailimf_address * address;
111
112 address = malloc(sizeof(* address));
113 if (address == NULL)
114 return NULL;
115
116 address->ad_type = ad_type;
117 switch (ad_type) {
118 case MAILIMF_ADDRESS_MAILBOX:
119 address->ad_data.ad_mailbox = ad_mailbox;
120 break;
121 case MAILIMF_ADDRESS_GROUP:
122 address->ad_data.ad_group = ad_group;
123 break;
124 }
125
126 return address;
127}
128
129void mailimf_address_free(struct mailimf_address * address)
130{
131 switch (address->ad_type) {
132 case MAILIMF_ADDRESS_MAILBOX:
133 mailimf_mailbox_free(address->ad_data.ad_mailbox);
134 break;
135 case MAILIMF_ADDRESS_GROUP:
136 mailimf_group_free(address->ad_data.ad_group);
137 }
138 free(address);
139}
140
141struct mailimf_mailbox *
142mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec)
143{
144 struct mailimf_mailbox * mb;
145
146 mb = malloc(sizeof(* mb));
147 if (mb == NULL)
148 return NULL;
149
150 mb->mb_display_name = mb_display_name;
151 mb->mb_addr_spec = mb_addr_spec;
152
153 return mb;
154}
155
156void mailimf_mailbox_free(struct mailimf_mailbox * mailbox)
157{
158 if (mailbox->mb_display_name != NULL)
159 mailimf_display_name_free(mailbox->mb_display_name);
160 mailimf_addr_spec_free(mailbox->mb_addr_spec);
161 free(mailbox);
162}
163
164
165void mailimf_angle_addr_free(char * angle_addr)
166{
167 free(angle_addr);
168}
169
170
171struct mailimf_group *
172mailimf_group_new(char * grp_display_name,
173 struct mailimf_mailbox_list * grp_mb_list)
174{
175 struct mailimf_group * group;
176
177 group = malloc(sizeof(* group));
178 if (group == NULL)
179 return NULL;
180
181 group->grp_display_name = grp_display_name;
182 group->grp_mb_list = grp_mb_list;
183
184 return group;
185}
186
187void mailimf_group_free(struct mailimf_group * group)
188{
189 if (group->grp_mb_list)
190 mailimf_mailbox_list_free(group->grp_mb_list);
191 mailimf_display_name_free(group->grp_display_name);
192 free(group);
193}
194
195void mailimf_display_name_free(char * display_name)
196{
197 mailimf_phrase_free(display_name);
198}
199
200
201struct mailimf_mailbox_list *
202mailimf_mailbox_list_new(clist * mb_list)
203{
204 struct mailimf_mailbox_list * mbl;
205
206 mbl = malloc(sizeof(* mbl));
207 if (mbl == NULL)
208 return NULL;
209
210 mbl->mb_list = mb_list;
211
212 return mbl;
213}
214
215void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list)
216{
217 clist_foreach(mb_list->mb_list, (clist_func) mailimf_mailbox_free, NULL);
218 clist_free(mb_list->mb_list);
219 free(mb_list);
220}
221
222
223
224struct mailimf_address_list *
225mailimf_address_list_new(clist * ad_list)
226{
227 struct mailimf_address_list * addr_list;
228
229 addr_list = malloc(sizeof(* addr_list));
230 if (addr_list == NULL)
231 return NULL;
232
233 addr_list->ad_list = ad_list;
234
235 return addr_list;
236}
237
238void mailimf_address_list_free(struct mailimf_address_list * addr_list)
239{
240 clist_foreach(addr_list->ad_list, (clist_func) mailimf_address_free, NULL);
241 clist_free(addr_list->ad_list);
242 free(addr_list);
243}
244
245
246void mailimf_addr_spec_free(char * addr_spec)
247{
248 free(addr_spec);
249}
250
251void mailimf_local_part_free(char * local_part)
252{
253 free(local_part);
254}
255
256void mailimf_domain_free(char * domain)
257{
258 free(domain);
259}
260
261void mailimf_domain_literal_free(char * domain_literal)
262{
263 free(domain_literal);
264}
265
266
267
268struct mailimf_message *
269mailimf_message_new(struct mailimf_fields * msg_fields,
270 struct mailimf_body * msg_body)
271{
272 struct mailimf_message * message;
273
274 message = malloc(sizeof(* message));
275 if (message == NULL)
276 return NULL;
277
278 message->msg_fields = msg_fields;
279 message->msg_body = msg_body;
280
281 return message;
282}
283
284void mailimf_message_free(struct mailimf_message * message)
285{
286 mailimf_body_free(message->msg_body);
287 mailimf_fields_free(message->msg_fields);
288 free(message);
289}
290
291
292struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size)
293{
294 struct mailimf_body * body;
295
296 body = malloc(sizeof(* body));
297 if (body == NULL)
298 return NULL;
299 body->bd_text = bd_text;
300 body->bd_size = bd_size;
301
302 return body;
303}
304
305void mailimf_body_free(struct mailimf_body * body)
306{
307 free(body);
308}
309
310
311
312struct mailimf_field *
313mailimf_field_new(int fld_type,
314 struct mailimf_return * fld_return_path,
315 struct mailimf_orig_date * fld_resent_date,
316 struct mailimf_from * fld_resent_from,
317 struct mailimf_sender * fld_resent_sender,
318 struct mailimf_to * fld_resent_to,
319 struct mailimf_cc * fld_resent_cc,
320 struct mailimf_bcc * fld_resent_bcc,
321 struct mailimf_message_id * fld_resent_msg_id,
322 struct mailimf_orig_date * fld_orig_date,
323 struct mailimf_from * fld_from,
324 struct mailimf_sender * fld_sender,
325 struct mailimf_reply_to * fld_reply_to,
326 struct mailimf_to * fld_to,
327 struct mailimf_cc * fld_cc,
328 struct mailimf_bcc * fld_bcc,
329 struct mailimf_message_id * fld_message_id,
330 struct mailimf_in_reply_to * fld_in_reply_to,
331 struct mailimf_references * fld_references,
332 struct mailimf_subject * fld_subject,
333 struct mailimf_comments * fld_comments,
334 struct mailimf_keywords * fld_keywords,
335 struct mailimf_optional_field * fld_optional_field)
336{
337 struct mailimf_field * field;
338
339 field = malloc(sizeof(* field));
340 if (field == NULL)
341 return NULL;
342
343 field->fld_type = fld_type;
344 switch (fld_type) {
345 case MAILIMF_FIELD_RETURN_PATH:
346 field->fld_data.fld_return_path = fld_return_path;
347 break;
348 case MAILIMF_FIELD_RESENT_DATE:
349 field->fld_data.fld_resent_date = fld_resent_date;
350 break;
351 case MAILIMF_FIELD_RESENT_FROM:
352 field->fld_data.fld_resent_from = fld_resent_from;
353 break;
354 case MAILIMF_FIELD_RESENT_SENDER:
355 field->fld_data.fld_resent_sender = fld_resent_sender;
356 break;
357 case MAILIMF_FIELD_RESENT_TO:
358 field->fld_data.fld_resent_to = fld_resent_to;
359 break;
360 case MAILIMF_FIELD_RESENT_CC:
361 field->fld_data.fld_resent_cc = fld_resent_cc;
362 break;
363 case MAILIMF_FIELD_RESENT_BCC:
364 field->fld_data.fld_resent_bcc = fld_resent_bcc;
365 break;
366 case MAILIMF_FIELD_RESENT_MSG_ID:
367 field->fld_data.fld_resent_msg_id = fld_resent_msg_id;
368 break;
369 case MAILIMF_FIELD_ORIG_DATE:
370 field->fld_data.fld_orig_date = fld_orig_date;
371 break;
372 case MAILIMF_FIELD_FROM:
373 field->fld_data.fld_from = fld_from;
374 break;
375 case MAILIMF_FIELD_SENDER:
376 field->fld_data.fld_sender = fld_sender;
377 break;
378 case MAILIMF_FIELD_REPLY_TO:
379 field->fld_data.fld_reply_to = fld_reply_to;
380 break;
381 case MAILIMF_FIELD_TO:
382 field->fld_data.fld_to = fld_to;
383 break;
384 case MAILIMF_FIELD_CC:
385 field->fld_data.fld_cc = fld_cc;
386 break;
387 case MAILIMF_FIELD_BCC:
388 field->fld_data.fld_bcc = fld_bcc;
389 break;
390 case MAILIMF_FIELD_MESSAGE_ID:
391 field->fld_data.fld_message_id = fld_message_id;
392 break;
393 case MAILIMF_FIELD_IN_REPLY_TO:
394 field->fld_data.fld_in_reply_to = fld_in_reply_to;
395 break;
396 case MAILIMF_FIELD_REFERENCES:
397 field->fld_data.fld_references = fld_references;
398 break;
399 case MAILIMF_FIELD_SUBJECT:
400 field->fld_data.fld_subject = fld_subject;
401 break;
402 case MAILIMF_FIELD_COMMENTS:
403 field->fld_data.fld_comments = fld_comments;
404 break;
405 case MAILIMF_FIELD_KEYWORDS:
406 field->fld_data.fld_keywords = fld_keywords;
407 break;
408 case MAILIMF_FIELD_OPTIONAL_FIELD:
409 field->fld_data.fld_optional_field = fld_optional_field;
410 break;
411 }
412
413 return field;
414}
415
416void mailimf_field_free(struct mailimf_field * field)
417{
418 switch (field->fld_type) {
419 case MAILIMF_FIELD_RETURN_PATH:
420 mailimf_return_free(field->fld_data.fld_return_path);
421 break;
422 case MAILIMF_FIELD_RESENT_DATE:
423 mailimf_orig_date_free(field->fld_data.fld_resent_date);
424 break;
425 case MAILIMF_FIELD_RESENT_FROM:
426 mailimf_from_free(field->fld_data.fld_resent_from);
427 break;
428 case MAILIMF_FIELD_RESENT_SENDER:
429 mailimf_sender_free(field->fld_data.fld_resent_sender);
430 break;
431 case MAILIMF_FIELD_RESENT_TO:
432 mailimf_to_free(field->fld_data.fld_resent_to);
433 break;
434 case MAILIMF_FIELD_RESENT_CC:
435 mailimf_cc_free(field->fld_data.fld_resent_cc);
436 break;
437 case MAILIMF_FIELD_RESENT_BCC:
438 mailimf_bcc_free(field->fld_data.fld_resent_bcc);
439 break;
440 case MAILIMF_FIELD_RESENT_MSG_ID:
441 mailimf_message_id_free(field->fld_data.fld_resent_msg_id);
442 break;
443 case MAILIMF_FIELD_ORIG_DATE:
444 mailimf_orig_date_free(field->fld_data.fld_orig_date);
445 break;
446 case MAILIMF_FIELD_FROM:
447 mailimf_from_free(field->fld_data.fld_from);
448 break;
449 case MAILIMF_FIELD_SENDER:
450 mailimf_sender_free(field->fld_data.fld_sender);
451 break;
452 case MAILIMF_FIELD_REPLY_TO:
453 mailimf_reply_to_free(field->fld_data.fld_reply_to);
454 break;
455 case MAILIMF_FIELD_TO:
456 mailimf_to_free(field->fld_data.fld_to);
457 break;
458 case MAILIMF_FIELD_CC:
459 mailimf_cc_free(field->fld_data.fld_cc);
460 break;
461 case MAILIMF_FIELD_BCC:
462 mailimf_bcc_free(field->fld_data.fld_bcc);
463 break;
464 case MAILIMF_FIELD_MESSAGE_ID:
465 mailimf_message_id_free(field->fld_data.fld_message_id);
466 break;
467 case MAILIMF_FIELD_IN_REPLY_TO:
468 mailimf_in_reply_to_free(field->fld_data.fld_in_reply_to);
469 break;
470 case MAILIMF_FIELD_REFERENCES:
471 mailimf_references_free(field->fld_data.fld_references);
472 break;
473 case MAILIMF_FIELD_SUBJECT:
474 mailimf_subject_free(field->fld_data.fld_subject);
475 break;
476 case MAILIMF_FIELD_COMMENTS:
477 mailimf_comments_free(field->fld_data.fld_comments);
478 break;
479 case MAILIMF_FIELD_KEYWORDS:
480 mailimf_keywords_free(field->fld_data.fld_keywords);
481 break;
482 case MAILIMF_FIELD_OPTIONAL_FIELD:
483 mailimf_optional_field_free(field->fld_data.fld_optional_field);
484 break;
485 }
486
487 free(field);
488}
489
490struct mailimf_fields * mailimf_fields_new(clist * fld_list)
491{
492 struct mailimf_fields * fields;
493
494 fields = malloc(sizeof(* fields));
495 if (fields == NULL)
496 return NULL;
497
498 fields->fld_list = fld_list;
499
500 return fields;
501}
502
503void mailimf_fields_free(struct mailimf_fields * fields)
504{
505 if (fields->fld_list != NULL) {
506 clist_foreach(fields->fld_list, (clist_func) mailimf_field_free, NULL);
507 clist_free(fields->fld_list);
508 }
509 free(fields);
510}
511
512
513struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time *
514 dt_date_time)
515{
516 struct mailimf_orig_date * orig_date;
517
518 orig_date = malloc(sizeof(* orig_date));
519 if (orig_date == NULL)
520 return NULL;
521
522 orig_date->dt_date_time = dt_date_time;
523
524 return orig_date;
525}
526
527void mailimf_orig_date_free(struct mailimf_orig_date * orig_date)
528{
529 if (orig_date->dt_date_time != NULL)
530 mailimf_date_time_free(orig_date->dt_date_time);
531 free(orig_date);
532}
533
534struct mailimf_from *
535mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list)
536{
537 struct mailimf_from * from;
538
539 from = malloc(sizeof(* from));
540 if (from == NULL)
541 return NULL;
542
543 from->frm_mb_list = frm_mb_list;
544
545 return from;
546}
547
548void mailimf_from_free(struct mailimf_from * from)
549{
550 if (from->frm_mb_list != NULL)
551 mailimf_mailbox_list_free(from->frm_mb_list);
552 free(from);
553}
554
555struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb)
556{
557 struct mailimf_sender * sender;
558
559 sender = malloc(sizeof(* sender));
560 if (sender == NULL)
561 return NULL;
562
563 sender->snd_mb = snd_mb;
564
565 return sender;
566}
567
568void mailimf_sender_free(struct mailimf_sender * sender)
569{
570 if (sender->snd_mb != NULL)
571 mailimf_mailbox_free(sender->snd_mb);
572 free(sender);
573}
574
575struct mailimf_reply_to *
576mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list)
577{
578 struct mailimf_reply_to * reply_to;
579
580 reply_to = malloc(sizeof(* reply_to));
581 if (reply_to == NULL)
582 return NULL;
583
584 reply_to->rt_addr_list = rt_addr_list;
585
586 return reply_to;
587}
588
589void mailimf_reply_to_free(struct mailimf_reply_to * reply_to)
590{
591 if (reply_to->rt_addr_list != NULL)
592 mailimf_address_list_free(reply_to->rt_addr_list);
593 free(reply_to);
594}
595
596struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list)
597{
598 struct mailimf_to * to;
599
600 to = malloc(sizeof(* to));
601 if (to == NULL)
602 return NULL;
603
604 to->to_addr_list = to_addr_list;
605
606 return to;
607}
608
609void mailimf_to_free(struct mailimf_to * to)
610{
611 if (to->to_addr_list != NULL)
612 mailimf_address_list_free(to->to_addr_list);
613 free(to);
614}
615
616struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list)
617{
618 struct mailimf_cc * cc;
619
620 cc = malloc(sizeof(* cc));
621 if (cc == NULL)
622 return NULL;
623
624 cc->cc_addr_list = cc_addr_list;
625
626 return cc;
627}
628
629void mailimf_cc_free(struct mailimf_cc * cc)
630{
631 if (cc->cc_addr_list != NULL)
632 mailimf_address_list_free(cc->cc_addr_list);
633 free(cc);
634}
635
636struct mailimf_bcc *
637mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list)
638{
639 struct mailimf_bcc * bcc;
640
641 bcc = malloc(sizeof(* bcc));
642 if (bcc == NULL)
643 return NULL;
644
645 bcc->bcc_addr_list = bcc_addr_list;
646
647 return bcc;
648}
649
650void mailimf_bcc_free(struct mailimf_bcc * bcc)
651{
652 if (bcc->bcc_addr_list != NULL)
653 mailimf_address_list_free(bcc->bcc_addr_list);
654 free(bcc);
655}
656
657struct mailimf_message_id * mailimf_message_id_new(char * mid_value)
658{
659 struct mailimf_message_id * message_id;
660
661 message_id = malloc(sizeof(* message_id));
662 if (message_id == NULL)
663 return NULL;
664
665 message_id->mid_value = mid_value;
666
667 return message_id;
668}
669
670void mailimf_message_id_free(struct mailimf_message_id * message_id)
671{
672 if (message_id->mid_value != NULL)
673 mailimf_msg_id_free(message_id->mid_value);
674 free(message_id);
675}
676
677struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list)
678{
679 struct mailimf_in_reply_to * in_reply_to;
680
681 in_reply_to = malloc(sizeof(* in_reply_to));
682 if (in_reply_to == NULL)
683 return NULL;
684
685 in_reply_to->mid_list = mid_list;
686
687 return in_reply_to;
688}
689
690void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to)
691{
692 clist_foreach(in_reply_to->mid_list,
693 (clist_func) mailimf_msg_id_free, NULL);
694 clist_free(in_reply_to->mid_list);
695 free(in_reply_to);
696}
697
698struct mailimf_references * mailimf_references_new(clist * mid_list)
699{
700 struct mailimf_references * ref;
701
702 ref = malloc(sizeof(* ref));
703 if (ref == NULL)
704 return NULL;
705
706 ref->mid_list = mid_list;
707
708 return ref;
709}
710
711void mailimf_references_free(struct mailimf_references * references)
712{
713 clist_foreach(references->mid_list,
714 (clist_func) mailimf_msg_id_free, NULL);
715 clist_free(references->mid_list);
716 free(references);
717}
718
719void mailimf_msg_id_free(char * msg_id)
720{
721 free(msg_id);
722}
723
724void mailimf_id_left_free(char * id_left)
725{
726 free(id_left);
727}
728
729void mailimf_id_right_free(char * id_right)
730{
731 free(id_right);
732}
733
734void mailimf_no_fold_quote_free(char * nfq)
735{
736 free(nfq);
737}
738
739void mailimf_no_fold_literal_free(char * nfl)
740{
741 free(nfl);
742}
743
744struct mailimf_subject * mailimf_subject_new(char * sbj_value)
745{
746 struct mailimf_subject * subject;
747
748 subject = malloc(sizeof(* subject));
749 if (subject == NULL)
750 return NULL;
751
752 subject->sbj_value = sbj_value;
753
754 return subject;
755}
756
757void mailimf_subject_free(struct mailimf_subject * subject)
758{
759 mailimf_unstructured_free(subject->sbj_value);
760 free(subject);
761}
762
763struct mailimf_comments * mailimf_comments_new(char * cm_value)
764{
765 struct mailimf_comments * comments;
766
767 comments = malloc(sizeof(* comments));
768 if (comments == NULL)
769 return NULL;
770
771 comments->cm_value = cm_value;
772
773 return comments;
774}
775
776void mailimf_comments_free(struct mailimf_comments * comments)
777{
778 mailimf_unstructured_free(comments->cm_value);
779 free(comments);
780}
781
782struct mailimf_keywords * mailimf_keywords_new(clist * kw_list)
783{
784 struct mailimf_keywords * keywords;
785
786 keywords = malloc(sizeof(* keywords));
787 if (keywords == NULL)
788 return NULL;
789
790 keywords->kw_list = kw_list;
791
792 return keywords;
793}
794
795void mailimf_keywords_free(struct mailimf_keywords * keywords)
796{
797 clist_foreach(keywords->kw_list, (clist_func) mailimf_phrase_free, NULL);
798 clist_free(keywords->kw_list);
799 free(keywords);
800}
801
802struct mailimf_return *
803mailimf_return_new(struct mailimf_path * ret_path)
804{
805 struct mailimf_return * return_path;
806
807 return_path = malloc(sizeof(* return_path));
808 if (return_path == NULL)
809 return NULL;
810
811 return_path->ret_path = ret_path;
812
813 return return_path;
814}
815
816void mailimf_return_free(struct mailimf_return * return_path)
817{
818 mailimf_path_free(return_path->ret_path);
819 free(return_path);
820}
821
822
823struct mailimf_path * mailimf_path_new(char * pt_addr_spec)
824{
825 struct mailimf_path * path;
826
827 path = malloc(sizeof(* path));
828 if (path == NULL)
829 return NULL;
830
831 path->pt_addr_spec = pt_addr_spec;
832
833 return path;
834}
835
836void mailimf_path_free(struct mailimf_path * path)
837{
838 if (path->pt_addr_spec != NULL)
839 mailimf_addr_spec_free(path->pt_addr_spec);
840 free(path);
841}
842
843struct mailimf_optional_field *
844mailimf_optional_field_new(char * fld_name, char * fld_value)
845{
846 struct mailimf_optional_field * opt_field;
847
848 opt_field = malloc(sizeof(* opt_field));
849 if (opt_field == NULL)
850 return NULL;
851
852 opt_field->fld_name = fld_name;
853 opt_field->fld_value = fld_value;
854
855 return opt_field;
856}
857
858void mailimf_optional_field_free(struct mailimf_optional_field * opt_field)
859{
860 mailimf_field_name_free(opt_field->fld_name);
861 mailimf_unstructured_free(opt_field->fld_value);
862 free(opt_field);
863}
864
865void mailimf_field_name_free(char * field_name)
866{
867 free(field_name);
868}
diff --git a/libetpan/src/low-level/imf/mailimf_types.h b/libetpan/src/low-level/imf/mailimf_types.h
new file mode 100644
index 0000000..e73db48
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_types.h
@@ -0,0 +1,793 @@
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/*
34 * $Id$
35 */
36
37#ifndef MAILIMF_TYPES_H
38
39#define MAILIMF_TYPES_H
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
45#include <libetpan/clist.h>
46#include <sys/types.h>
47
48/*
49 IMPORTANT NOTE:
50
51 All allocation functions will take as argument allocated data
52 and will store these data in the structure they will allocate.
53 Data should be persistant during all the use of the structure
54 and will be freed by the free function of the structure
55
56 allocation functions will return NULL on failure
57*/
58
59/*
60 mailimf_date_time is a date
61
62 - day is the day of month (1 to 31)
63
64 - month (1 to 12)
65
66 - year (4 digits)
67
68 - hour (0 to 23)
69
70 - min (0 to 59)
71
72 - sec (0 to 59)
73
74 - zone (this is the decimal value that we can read, for example:
75 for "-0200", the value is -200)
76*/
77
78struct mailimf_date_time {
79 int dt_day;
80 int dt_month;
81 int dt_year;
82 int dt_hour;
83 int dt_min;
84 int dt_sec;
85 int dt_zone;
86};
87
88struct mailimf_date_time *
89mailimf_date_time_new(int dt_day, int dt_month, int dt_year,
90 int dt_hour, int dt_min, int dt_sec, int dt_zone);
91
92void mailimf_date_time_free(struct mailimf_date_time * date_time);
93
94
95
96/* this is the type of address */
97
98enum {
99 MAILIMF_ADDRESS_ERROR, /* on parse error */
100 MAILIMF_ADDRESS_MAILBOX, /* if this is a mailbox (mailbox@domain) */
101 MAILIMF_ADDRESS_GROUP, /* if this is a group
102 (group_name: address1@domain1,
103 address2@domain2; ) */
104};
105
106/*
107 mailimf_address is an address
108
109 - type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP
110
111 - mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX
112
113 - group is a group if type is MAILIMF_ADDRESS_GROUP
114*/
115
116struct mailimf_address {
117 int ad_type;
118 union {
119 struct mailimf_mailbox * ad_mailbox; /* can be NULL */
120 struct mailimf_group * ad_group; /* can be NULL */
121 } ad_data;
122};
123
124
125struct mailimf_address *
126mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox,
127 struct mailimf_group * ad_group);
128
129void mailimf_address_free(struct mailimf_address * address);
130
131
132
133/*
134 mailimf_mailbox is a mailbox
135
136 - display_name is the name that will be displayed for this mailbox,
137 for example 'name' in '"name" <mailbox@domain>,
138 should be allocated with malloc()
139
140 - addr_spec is the mailbox, for example 'mailbox@domain'
141 in '"name" <mailbox@domain>, should be allocated with malloc()
142*/
143
144struct mailimf_mailbox {
145 char * mb_display_name; /* can be NULL */
146 char * mb_addr_spec; /* != NULL */
147};
148
149struct mailimf_mailbox *
150mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec);
151
152void mailimf_mailbox_free(struct mailimf_mailbox * mailbox);
153
154
155
156/*
157 mailimf_group is a group
158
159 - display_name is the name that will be displayed for this group,
160 for example 'group_name' in
161 'group_name: address1@domain1, address2@domain2;', should be allocated
162 with malloc()
163
164 - mb_list is a list of mailboxes
165*/
166
167struct mailimf_group {
168 char * grp_display_name; /* != NULL */
169 struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */
170};
171
172struct mailimf_group *
173mailimf_group_new(char * grp_display_name,
174 struct mailimf_mailbox_list * grp_mb_list);
175
176void mailimf_group_free(struct mailimf_group * group);
177
178
179
180/*
181 mailimf_mailbox_list is a list of mailboxes
182
183 - list is a list of mailboxes
184*/
185
186struct mailimf_mailbox_list {
187 clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */
188};
189
190struct mailimf_mailbox_list *
191mailimf_mailbox_list_new(clist * mb_list);
192
193void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list);
194
195
196
197/*
198 mailimf_address_list is a list of addresses
199
200 - list is a list of addresses
201*/
202
203struct mailimf_address_list {
204 clist * ad_list; /* list of (struct mailimf_address *), != NULL */
205};
206
207struct mailimf_address_list *
208mailimf_address_list_new(clist * ad_list);
209
210void mailimf_address_list_free(struct mailimf_address_list * addr_list);
211
212
213
214
215
216/*
217 mailimf_body is the text part of a message
218
219 - text is the beginning of the text part, it is a substring
220 of an other string
221
222 - size is the size of the text part
223*/
224
225struct mailimf_body {
226 const char * bd_text; /* != NULL */
227 size_t bd_size;
228};
229
230struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size);
231
232void mailimf_body_free(struct mailimf_body * body);
233
234
235
236
237/*
238 mailimf_message is the content of the message
239
240 - msg_fields is the header fields of the message
241
242 - msg_body is the text part of the message
243*/
244
245struct mailimf_message {
246 struct mailimf_fields * msg_fields; /* != NULL */
247 struct mailimf_body * msg_body; /* != NULL */
248};
249
250struct mailimf_message *
251mailimf_message_new(struct mailimf_fields * msg_fields,
252 struct mailimf_body * msg_body);
253
254void mailimf_message_free(struct mailimf_message * message);
255
256
257
258
259/*
260 mailimf_fields is a list of header fields
261
262 - fld_list is a list of header fields
263*/
264
265struct mailimf_fields {
266 clist * fld_list; /* list of (struct mailimf_field *), != NULL */
267};
268
269struct mailimf_fields * mailimf_fields_new(clist * fld_list);
270
271void mailimf_fields_free(struct mailimf_fields * fields);
272
273
274
275/* this is a type of field */
276
277enum {
278 MAILIMF_FIELD_NONE, /* on parse error */
279 MAILIMF_FIELD_RETURN_PATH, /* Return-Path */
280 MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */
281 MAILIMF_FIELD_RESENT_FROM, /* Resent-From */
282 MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */
283 MAILIMF_FIELD_RESENT_TO, /* Resent-To */
284 MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */
285 MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */
286 MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */
287 MAILIMF_FIELD_ORIG_DATE, /* Date */
288 MAILIMF_FIELD_FROM, /* From */
289 MAILIMF_FIELD_SENDER, /* Sender */
290 MAILIMF_FIELD_REPLY_TO, /* Reply-To */
291 MAILIMF_FIELD_TO, /* To */
292 MAILIMF_FIELD_CC, /* Cc */
293 MAILIMF_FIELD_BCC, /* Bcc */
294 MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */
295 MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */
296 MAILIMF_FIELD_REFERENCES, /* References */
297 MAILIMF_FIELD_SUBJECT, /* Subject */
298 MAILIMF_FIELD_COMMENTS, /* Comments */
299 MAILIMF_FIELD_KEYWORDS, /* Keywords */
300 MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */
301};
302
303/*
304 mailimf_field is a field
305
306 - fld_type is the type of the field
307
308 - fld_data.fld_return_path is the parsed content of the Return-Path
309 field if type is MAILIMF_FIELD_RETURN_PATH
310
311 - fld_data.fld_resent_date is the parsed content of the Resent-Date field
312 if type is MAILIMF_FIELD_RESENT_DATE
313
314 - fld_data.fld_resent_from is the parsed content of the Resent-From field
315
316 - fld_data.fld_resent_sender is the parsed content of the Resent-Sender field
317
318 - fld_data.fld_resent_to is the parsed content of the Resent-To field
319
320 - fld_data.fld_resent_cc is the parsed content of the Resent-Cc field
321
322 - fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc field
323
324 - fld_data.fld_resent_msg_id is the parsed content of the Resent-Message-ID
325 field
326
327 - fld_data.fld_orig_date is the parsed content of the Date field
328
329 - fld_data.fld_from is the parsed content of the From field
330
331 - fld_data.fld_sender is the parsed content of the Sender field
332
333 - fld_data.fld_reply_to is the parsed content of the Reply-To field
334
335 - fld_data.fld_to is the parsed content of the To field
336
337 - fld_data.fld_cc is the parsed content of the Cc field
338
339 - fld_data.fld_bcc is the parsed content of the Bcc field
340
341 - fld_data.fld_message_id is the parsed content of the Message-ID field
342
343 - fld_data.fld_in_reply_to is the parsed content of the In-Reply-To field
344
345 - fld_data.fld_references is the parsed content of the References field
346
347 - fld_data.fld_subject is the content of the Subject field
348
349 - fld_data.fld_comments is the content of the Comments field
350
351 - fld_data.fld_keywords is the parsed content of the Keywords field
352
353 - fld_data.fld_optional_field is an other field and is not parsed
354*/
355
356#define LIBETPAN_MAILIMF_FIELD_UNION
357
358struct mailimf_field {
359 int fld_type;
360 union {
361 struct mailimf_return * fld_return_path; /* can be NULL */
362 struct mailimf_orig_date * fld_resent_date; /* can be NULL */
363 struct mailimf_from * fld_resent_from; /* can be NULL */
364 struct mailimf_sender * fld_resent_sender; /* can be NULL */
365 struct mailimf_to * fld_resent_to; /* can be NULL */
366 struct mailimf_cc * fld_resent_cc; /* can be NULL */
367 struct mailimf_bcc * fld_resent_bcc; /* can be NULL */
368 struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */
369 struct mailimf_orig_date * fld_orig_date; /* can be NULL */
370 struct mailimf_from * fld_from; /* can be NULL */
371 struct mailimf_sender * fld_sender; /* can be NULL */
372 struct mailimf_reply_to * fld_reply_to; /* can be NULL */
373 struct mailimf_to * fld_to; /* can be NULL */
374 struct mailimf_cc * fld_cc; /* can be NULL */
375 struct mailimf_bcc * fld_bcc; /* can be NULL */
376 struct mailimf_message_id * fld_message_id; /* can be NULL */
377 struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */
378 struct mailimf_references * fld_references; /* can be NULL */
379 struct mailimf_subject * fld_subject; /* can be NULL */
380 struct mailimf_comments * fld_comments; /* can be NULL */
381 struct mailimf_keywords * fld_keywords; /* can be NULL */
382 struct mailimf_optional_field * fld_optional_field; /* can be NULL */
383 } fld_data;
384};
385
386struct mailimf_field *
387mailimf_field_new(int fld_type,
388 struct mailimf_return * fld_return_path,
389 struct mailimf_orig_date * fld_resent_date,
390 struct mailimf_from * fld_resent_from,
391 struct mailimf_sender * fld_resent_sender,
392 struct mailimf_to * fld_resent_to,
393 struct mailimf_cc * fld_resent_cc,
394 struct mailimf_bcc * fld_resent_bcc,
395 struct mailimf_message_id * fld_resent_msg_id,
396 struct mailimf_orig_date * fld_orig_date,
397 struct mailimf_from * fld_from,
398 struct mailimf_sender * fld_sender,
399 struct mailimf_reply_to * fld_reply_to,
400 struct mailimf_to * fld_to,
401 struct mailimf_cc * fld_cc,
402 struct mailimf_bcc * fld_bcc,
403 struct mailimf_message_id * fld_message_id,
404 struct mailimf_in_reply_to * fld_in_reply_to,
405 struct mailimf_references * fld_references,
406 struct mailimf_subject * fld_subject,
407 struct mailimf_comments * fld_comments,
408 struct mailimf_keywords * fld_keywords,
409 struct mailimf_optional_field * fld_optional_field);
410
411void mailimf_field_free(struct mailimf_field * field);
412
413
414
415/*
416 mailimf_orig_date is the parsed Date field
417
418 - date_time is the parsed date
419*/
420
421struct mailimf_orig_date {
422 struct mailimf_date_time * dt_date_time; /* != NULL */
423};
424
425struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time *
426 dt_date_time);
427
428void mailimf_orig_date_free(struct mailimf_orig_date * orig_date);
429
430
431
432
433/*
434 mailimf_from is the parsed From field
435
436 - mb_list is the parsed mailbox list
437*/
438
439struct mailimf_from {
440 struct mailimf_mailbox_list * frm_mb_list; /* != NULL */
441};
442
443struct mailimf_from *
444mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list);
445
446void mailimf_from_free(struct mailimf_from * from);
447
448
449
450/*
451 mailimf_sender is the parsed Sender field
452
453 - snd_mb is the parsed mailbox
454*/
455
456struct mailimf_sender {
457 struct mailimf_mailbox * snd_mb; /* != NULL */
458};
459
460struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb);
461
462void mailimf_sender_free(struct mailimf_sender * sender);
463
464
465
466
467/*
468 mailimf_reply_to is the parsed Reply-To field
469
470 - rt_addr_list is the parsed address list
471 */
472
473struct mailimf_reply_to {
474 struct mailimf_address_list * rt_addr_list; /* != NULL */
475};
476
477struct mailimf_reply_to *
478mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list);
479
480void mailimf_reply_to_free(struct mailimf_reply_to * reply_to);
481
482
483
484
485/*
486 mailimf_to is the parsed To field
487
488 - to_addr_list is the parsed address list
489*/
490
491struct mailimf_to {
492 struct mailimf_address_list * to_addr_list; /* != NULL */
493};
494
495struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list);
496
497void mailimf_to_free(struct mailimf_to * to);
498
499
500
501
502/*
503 mailimf_cc is the parsed Cc field
504
505 - cc_addr_list is the parsed addres list
506*/
507
508struct mailimf_cc {
509 struct mailimf_address_list * cc_addr_list; /* != NULL */
510};
511
512struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list);
513
514void mailimf_cc_free(struct mailimf_cc * cc);
515
516
517
518
519/*
520 mailimf_bcc is the parsed Bcc field
521
522 - bcc_addr_list is the parsed addres list
523*/
524
525struct mailimf_bcc {
526 struct mailimf_address_list * bcc_addr_list; /* can be NULL */
527};
528
529struct mailimf_bcc *
530mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list);
531
532void mailimf_bcc_free(struct mailimf_bcc * bcc);
533
534
535
536/*
537 mailimf_message_id is the parsed Message-ID field
538
539 - mid_value is the message identifier
540*/
541
542struct mailimf_message_id {
543 char * mid_value; /* != NULL */
544};
545
546struct mailimf_message_id * mailimf_message_id_new(char * mid_value);
547
548void mailimf_message_id_free(struct mailimf_message_id * message_id);
549
550
551
552
553/*
554 mailimf_in_reply_to is the parsed In-Reply-To field
555
556 - mid_list is the list of message identifers
557*/
558
559struct mailimf_in_reply_to {
560 clist * mid_list; /* list of (char *), != NULL */
561};
562
563struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list);
564
565void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to);
566
567
568
569/*
570 mailimf_references is the parsed References field
571
572 - msg_id_list is the list of message identifiers
573 */
574
575struct mailimf_references {
576 clist * mid_list; /* list of (char *) */
577 /* != NULL */
578};
579
580struct mailimf_references * mailimf_references_new(clist * mid_list);
581
582void mailimf_references_free(struct mailimf_references * references);
583
584
585
586/*
587 mailimf_subject is the parsed Subject field
588
589 - sbj_value is the value of the field
590*/
591
592struct mailimf_subject {
593 char * sbj_value; /* != NULL */
594};
595
596struct mailimf_subject * mailimf_subject_new(char * sbj_value);
597
598void mailimf_subject_free(struct mailimf_subject * subject);
599
600
601/*
602 mailimf_comments is the parsed Comments field
603
604 - cm_value is the value of the field
605*/
606
607struct mailimf_comments {
608 char * cm_value; /* != NULL */
609};
610
611struct mailimf_comments * mailimf_comments_new(char * cm_value);
612
613void mailimf_comments_free(struct mailimf_comments * comments);
614
615
616/*
617 mailimf_keywords is the parsed Keywords field
618
619 - kw_list is the list of keywords
620*/
621
622struct mailimf_keywords {
623 clist * kw_list; /* list of (char *), != NULL */
624};
625
626struct mailimf_keywords * mailimf_keywords_new(clist * kw_list);
627
628void mailimf_keywords_free(struct mailimf_keywords * keywords);
629
630
631/*
632 mailimf_return is the parsed Return-Path field
633
634 - ret_path is the parsed value of Return-Path
635*/
636
637struct mailimf_return {
638 struct mailimf_path * ret_path; /* != NULL */
639};
640
641struct mailimf_return *
642mailimf_return_new(struct mailimf_path * ret_path);
643
644void mailimf_return_free(struct mailimf_return * return_path);
645
646
647/*
648 mailimf_path is the parsed value of Return-Path
649
650 - pt_addr_spec is a mailbox
651*/
652
653struct mailimf_path {
654 char * pt_addr_spec; /* can be NULL */
655};
656
657struct mailimf_path * mailimf_path_new(char * pt_addr_spec);
658
659void mailimf_path_free(struct mailimf_path * path);
660
661
662/*
663 mailimf_optional_field is a non-parsed field
664
665 - fld_name is the name of the field
666
667 - fld_value is the value of the field
668*/
669
670struct mailimf_optional_field {
671 char * fld_name; /* != NULL */
672 char * fld_value; /* != NULL */
673};
674
675struct mailimf_optional_field *
676mailimf_optional_field_new(char * fld_name, char * fld_value);
677
678void mailimf_optional_field_free(struct mailimf_optional_field * opt_field);
679
680
681/*
682 mailimf_fields is the native structure that IMF module will use,
683 this module will provide an easier structure to use when parsing fields.
684
685 mailimf_single_fields is an easier structure to get parsed fields,
686 rather than iteration over the list of fields
687
688 - fld_orig_date is the parsed "Date" field
689
690 - fld_from is the parsed "From" field
691
692 - fld_sender is the parsed "Sender "field
693
694 - fld_reply_to is the parsed "Reply-To" field
695
696 - fld_to is the parsed "To" field
697
698 - fld_cc is the parsed "Cc" field
699
700 - fld_bcc is the parsed "Bcc" field
701
702 - fld_message_id is the parsed "Message-ID" field
703
704 - fld_in_reply_to is the parsed "In-Reply-To" field
705
706 - fld_references is the parsed "References" field
707
708 - fld_subject is the parsed "Subject" field
709
710 - fld_comments is the parsed "Comments" field
711
712 - fld_keywords is the parsed "Keywords" field
713*/
714
715struct mailimf_single_fields {
716 struct mailimf_orig_date * fld_orig_date; /* can be NULL */
717 struct mailimf_from * fld_from; /* can be NULL */
718 struct mailimf_sender * fld_sender; /* can be NULL */
719 struct mailimf_reply_to * fld_reply_to; /* can be NULL */
720 struct mailimf_to * fld_to; /* can be NULL */
721 struct mailimf_cc * fld_cc; /* can be NULL */
722 struct mailimf_bcc * fld_bcc; /* can be NULL */
723 struct mailimf_message_id * fld_message_id; /* can be NULL */
724 struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */
725 struct mailimf_references * fld_references; /* can be NULL */
726 struct mailimf_subject * fld_subject; /* can be NULL */
727 struct mailimf_comments * fld_comments; /* can be NULL */
728 struct mailimf_keywords * fld_keywords; /* can be NULL */
729};
730
731
732
733
734
735
736/* internal use */
737
738void mailimf_atom_free(char * atom);
739
740void mailimf_dot_atom_free(char * dot_atom);
741
742void mailimf_dot_atom_text_free(char * dot_atom);
743
744void mailimf_quoted_string_free(char * quoted_string);
745
746void mailimf_word_free(char * word);
747
748void mailimf_phrase_free(char * phrase);
749
750void mailimf_unstructured_free(char * unstructured);
751
752void mailimf_angle_addr_free(char * angle_addr);
753
754void mailimf_display_name_free(char * display_name);
755
756void mailimf_addr_spec_free(char * addr_spec);
757
758void mailimf_local_part_free(char * local_part);
759
760void mailimf_domain_free(char * domain);
761
762void mailimf_domain_literal_free(char * domain);
763
764void mailimf_msg_id_free(char * msg_id);
765
766void mailimf_id_left_free(char * id_left);
767
768void mailimf_id_right_free(char * id_right);
769
770void mailimf_no_fold_quote_free(char * nfq);
771
772void mailimf_no_fold_literal_free(char * nfl);
773
774void mailimf_field_name_free(char * field_name);
775
776
777
778/* these are the possible returned error codes */
779
780enum {
781 MAILIMF_NO_ERROR = 0,
782 MAILIMF_ERROR_PARSE,
783 MAILIMF_ERROR_MEMORY,
784 MAILIMF_ERROR_INVAL,
785 MAILIMF_ERROR_FILE,
786};
787
788
789#ifdef __cplusplus
790}
791#endif
792
793#endif
diff --git a/libetpan/src/low-level/imf/mailimf_types_helper.c b/libetpan/src/low-level/imf/mailimf_types_helper.c
new file mode 100644
index 0000000..a4f669c
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_types_helper.c
@@ -0,0 +1,1636 @@
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#include "mailimf_types_helper.h"
33
34#include <stdlib.h>
35#include <string.h>
36#include <time.h>
37#include <unistd.h>
38
39#include "mailimf.h"
40
41struct mailimf_mailbox_list *
42mailimf_mailbox_list_new_empty()
43{
44 clist * list;
45 struct mailimf_mailbox_list * mb_list;
46
47 list = clist_new();
48 if (list == NULL)
49 return NULL;
50
51 mb_list = mailimf_mailbox_list_new(list);
52 if (mb_list == NULL)
53 return NULL;
54
55 return mb_list;
56}
57
58int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list,
59 struct mailimf_mailbox * mb)
60{
61 int r;
62
63 r = clist_append(mailbox_list->mb_list, mb);
64 if (r < 0)
65 return MAILIMF_ERROR_MEMORY;
66
67 return MAILIMF_NO_ERROR;
68}
69
70int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list,
71 char * mb_str)
72{
73 int r;
74 size_t cur_token;
75 struct mailimf_mailbox * mb;
76 int res;
77
78 cur_token = 0;
79 r = mailimf_mailbox_parse(mb_str, strlen(mb_str), &cur_token, &mb);
80 if (r != MAILIMF_NO_ERROR) {
81 res = r;
82 goto err;
83 }
84
85 r = mailimf_mailbox_list_add(mailbox_list, mb);
86 if (r != MAILIMF_NO_ERROR) {
87 res = r;
88 goto free;
89 }
90
91 return MAILIMF_NO_ERROR;
92
93 free:
94 mailimf_mailbox_free(mb);
95 err:
96 return res;
97}
98
99int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list,
100 char * display_name, char * address)
101{
102 int r;
103 struct mailimf_mailbox * mb;
104 int res;
105
106 mb = mailimf_mailbox_new(display_name, address);
107 if (mb == NULL) {
108 res = MAILIMF_ERROR_MEMORY;
109 goto err;
110 }
111
112 r = mailimf_mailbox_list_add(mailbox_list, mb);
113 if (r != MAILIMF_NO_ERROR) {
114 res = r;
115 goto free;
116 }
117
118 return MAILIMF_NO_ERROR;
119
120 free:
121 mailimf_mailbox_free(mb);
122 err:
123 return res;
124}
125
126
127
128struct mailimf_address_list *
129mailimf_address_list_new_empty()
130{
131 clist * list;
132 struct mailimf_address_list * addr_list;
133
134 list = clist_new();
135 if (list == NULL)
136 return NULL;
137
138 addr_list = mailimf_address_list_new(list);
139 if (addr_list == NULL)
140 return NULL;
141
142 return addr_list;
143}
144
145int mailimf_address_list_add(struct mailimf_address_list * address_list,
146 struct mailimf_address * addr)
147{
148 int r;
149
150 r = clist_append(address_list->ad_list, addr);
151 if (r < 0)
152 return MAILIMF_ERROR_MEMORY;
153
154 return MAILIMF_NO_ERROR;
155}
156
157int mailimf_address_list_add_parse(struct mailimf_address_list * address_list,
158 char * addr_str)
159{
160 int r;
161 size_t cur_token;
162 struct mailimf_address * addr;
163 int res;
164
165 cur_token = 0;
166 r = mailimf_address_parse(addr_str, strlen(addr_str), &cur_token, &addr);
167 if (r != MAILIMF_NO_ERROR) {
168 res = r;
169 goto err;
170 }
171
172 r = mailimf_address_list_add(address_list, addr);
173 if (r != MAILIMF_NO_ERROR) {
174 res = r;
175 goto free;
176 }
177
178 return MAILIMF_NO_ERROR;
179
180 free:
181 mailimf_address_free(addr);
182 err:
183 return res;
184}
185
186int mailimf_address_list_add_mb(struct mailimf_address_list * address_list,
187 char * display_name, char * address)
188{
189 int r;
190 struct mailimf_mailbox * mb;
191 struct mailimf_address * addr;
192 int res;
193
194 mb = mailimf_mailbox_new(display_name, address);
195 if (mb == NULL) {
196 res = MAILIMF_ERROR_MEMORY;
197 goto err;
198 }
199
200 addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
201 if (addr == NULL) {
202 res = MAILIMF_ERROR_MEMORY;
203 goto free_mb;
204 }
205
206 r = mailimf_address_list_add(address_list, addr);
207 if (r != MAILIMF_NO_ERROR) {
208 res = r;
209 goto free_addr;
210 }
211
212 return MAILIMF_NO_ERROR;
213
214 free_addr:
215 mailimf_address_free(addr);
216 free_mb:
217 mailimf_mailbox_free(mb);
218 err:
219 return res;
220}
221
222
223#if 0
224struct mailimf_resent_fields_list *
225mailimf_resent_fields_list_new_empty()
226{
227 clist * list;
228 struct mailimf_resent_fields_list * rf_list;
229
230 list = clist_new();
231 if (list == NULL)
232 return NULL;
233
234 rf_list = mailimf_resent_fields_list_new(list);
235 if (rf_list == NULL)
236 return NULL;
237
238 return rf_list;
239}
240
241int mailimf_resent_fields_add(struct mailimf_resent_fields_list * fields,
242 struct mailimf_resent_field * field)
243{
244 int r;
245
246 r = clist_append(fields->list, field);
247 if (r < 0)
248 return MAILIMF_ERROR_MEMORY;
249
250 return MAILIMF_NO_ERROR;
251}
252#endif
253
254
255static void detach_free_common_fields(struct mailimf_orig_date * imf_date,
256 struct mailimf_from * imf_from,
257 struct mailimf_sender * imf_sender,
258 struct mailimf_to * imf_to,
259 struct mailimf_cc * imf_cc,
260 struct mailimf_bcc * imf_bcc,
261 struct mailimf_message_id * imf_msg_id)
262{
263 if (imf_date != NULL) {
264 imf_date->dt_date_time = NULL;
265 mailimf_orig_date_free(imf_date);
266 }
267 if (imf_from != NULL) {
268 imf_from->frm_mb_list = NULL;
269 mailimf_from_free(imf_from);
270 }
271 if (imf_sender != NULL) {
272 imf_sender->snd_mb = NULL;
273 mailimf_sender_free(imf_sender);
274 }
275 if (imf_to != NULL) {
276 imf_to->to_addr_list = NULL;
277 mailimf_to_free(imf_to);
278 }
279 if (imf_cc != NULL) {
280 imf_cc->cc_addr_list = NULL;
281 mailimf_to_free(imf_to);
282 }
283 if (imf_bcc != NULL) {
284 imf_bcc->bcc_addr_list = NULL;
285 mailimf_bcc_free(imf_bcc);
286 }
287 if (imf_msg_id != NULL) {
288 imf_msg_id->mid_value = NULL;
289 mailimf_message_id_free(imf_msg_id);
290 }
291}
292
293static void detach_resent_field(struct mailimf_field * field)
294{
295 field->fld_type = MAILIMF_FIELD_NONE;
296 mailimf_field_free(field);
297}
298
299int
300mailimf_resent_fields_add_data(struct mailimf_fields * fields,
301 struct mailimf_date_time * resent_date,
302 struct mailimf_mailbox_list * resent_from,
303 struct mailimf_mailbox * resent_sender,
304 struct mailimf_address_list * resent_to,
305 struct mailimf_address_list * resent_cc,
306 struct mailimf_address_list * resent_bcc,
307 char * resent_msg_id)
308{
309 struct mailimf_orig_date * imf_resent_date;
310 struct mailimf_from * imf_resent_from;
311 struct mailimf_sender * imf_resent_sender;
312 struct mailimf_to * imf_resent_to;
313 struct mailimf_cc * imf_resent_cc;
314 struct mailimf_bcc * imf_resent_bcc;
315 struct mailimf_message_id * imf_resent_msg_id;
316 struct mailimf_field * field;
317 int r;
318
319 imf_resent_date = NULL;
320 imf_resent_from = NULL;
321 imf_resent_sender = NULL;
322 imf_resent_to = NULL;
323 imf_resent_cc = NULL;
324 imf_resent_bcc = NULL;
325 imf_resent_msg_id = NULL;
326 field = NULL;
327
328 if (resent_date != NULL) {
329 imf_resent_date = mailimf_orig_date_new(resent_date);
330 if (imf_resent_date == NULL)
331 goto free;
332 field = mailimf_field_new(MAILIMF_FIELD_RESENT_DATE,
333 NULL /* return-path */,
334 imf_resent_date /* resent date */,
335 NULL /* resent from */,
336 NULL /* resent sender */,
337 NULL /* resent to */,
338 NULL /* resent cc */,
339 NULL /* resent bcc */,
340 NULL /* resent msg id */,
341 NULL /* date */,
342 NULL /* from */,
343 NULL /* sender */,
344 NULL /* reply-to */,
345 NULL /* to */,
346 NULL /* cc */,
347 NULL /* bcc */,
348 NULL /* message id */,
349 NULL /* in reply to */,
350 NULL /* references */,
351 NULL /* subject */,
352 NULL /* comments */,
353 NULL /* keywords */,
354 NULL /* optional field */);
355 if (field == NULL)
356 goto free;
357 r = mailimf_fields_add(fields, field);
358 if (r != MAILIMF_NO_ERROR)
359 goto free_field;
360 }
361
362 if (resent_from != NULL) {
363 imf_resent_from = mailimf_from_new(resent_from);
364 if (imf_resent_from == NULL)
365 goto free_field;
366 field = mailimf_field_new(MAILIMF_FIELD_RESENT_FROM,
367 NULL /* return-path */,
368 NULL /* resent date */,
369 imf_resent_from /* resent from */,
370 NULL /* resent sender */,
371 NULL /* resent to */,
372 NULL /* resent cc */,
373 NULL /* resent bcc */,
374 NULL /* resent msg id */,
375 NULL /* date */,
376 NULL /* from */,
377 NULL /* sender */,
378 NULL /* reply-to */,
379 NULL /* to */,
380 NULL /* cc */,
381 NULL /* bcc */,
382 NULL /* message id */,
383 NULL /* in reply to */,
384 NULL /* references */,
385 NULL /* subject */,
386 NULL /* comments */,
387 NULL /* keywords */,
388 NULL /* optional field */);
389 if (field == NULL)
390 goto free;
391 r = mailimf_fields_add(fields, field);
392 if (r != MAILIMF_NO_ERROR)
393 goto free_field;
394 }
395
396 if (resent_sender != NULL) {
397 imf_resent_sender = mailimf_sender_new(resent_sender);
398 if (imf_resent_sender == NULL)
399 goto free;
400 field = mailimf_field_new(MAILIMF_FIELD_RESENT_SENDER,
401 NULL /* return-path */,
402 NULL /* resent date */,
403 NULL /* resent from */,
404 imf_resent_sender /* resent sender */,
405 NULL /* resent to */,
406 NULL /* resent cc */,
407 NULL /* resent bcc */,
408 NULL /* resent msg id */,
409 NULL /* date */,
410 NULL /* from */,
411 NULL /* sender */,
412 NULL /* reply-to */,
413 NULL /* to */,
414 NULL /* cc */,
415 NULL /* bcc */,
416 NULL /* message id */,
417 NULL /* in reply to */,
418 NULL /* references */,
419 NULL /* subject */,
420 NULL /* comments */,
421 NULL /* keywords */,
422 NULL /* optional field */);
423 if (field == NULL)
424 goto free;
425 r = mailimf_fields_add(fields, field);
426 if (r != MAILIMF_NO_ERROR)
427 goto free_field;
428 }
429
430 if (resent_to != NULL) {
431 imf_resent_to = mailimf_to_new(resent_to);
432 if (imf_resent_to == NULL)
433 goto free;
434 field = mailimf_field_new(MAILIMF_FIELD_RESENT_TO,
435 NULL /* return-path */,
436 NULL /* resent date */,
437 NULL /* resent from */,
438 NULL /* resent sender */,
439 imf_resent_to /* resent to */,
440 NULL /* resent cc */,
441 NULL /* resent bcc */,
442 NULL /* resent msg id */,
443 NULL /* date */,
444 NULL /* from */,
445 NULL /* sender */,
446 NULL /* reply-to */,
447 NULL /* to */,
448 NULL /* cc */,
449 NULL /* bcc */,
450 NULL /* message id */,
451 NULL /* in reply to */,
452 NULL /* references */,
453 NULL /* subject */,
454 NULL /* comments */,
455 NULL /* keywords */,
456 NULL /* optional field */);
457 if (field == NULL)
458 goto free;
459 r = mailimf_fields_add(fields, field);
460 if (r != MAILIMF_NO_ERROR)
461 goto free_field;
462 }
463
464 if (resent_cc != NULL) {
465 imf_resent_cc = mailimf_cc_new(resent_cc);
466 if (imf_resent_cc == NULL)
467 goto free;
468 field = mailimf_field_new(MAILIMF_FIELD_RESENT_CC,
469 NULL /* return-path */,
470 NULL /* resent date */,
471 NULL /* resent from */,
472 NULL /* resent sender */,
473 NULL /* resent to */,
474 imf_resent_cc /* resent cc */,
475 NULL /* resent bcc */,
476 NULL /* resent msg id */,
477 NULL /* date */,
478 NULL /* from */,
479 NULL /* sender */,
480 NULL /* reply-to */,
481 NULL /* to */,
482 NULL /* cc */,
483 NULL /* bcc */,
484 NULL /* message id */,
485 NULL /* in reply to */,
486 NULL /* references */,
487 NULL /* subject */,
488 NULL /* comments */,
489 NULL /* keywords */,
490 NULL /* optional field */);
491 if (field == NULL)
492 goto free;
493 r = mailimf_fields_add(fields, field);
494 if (r != MAILIMF_NO_ERROR)
495 goto free_field;
496 }
497
498 if (resent_bcc != NULL) {
499 imf_resent_bcc = mailimf_bcc_new(resent_bcc);
500 if (imf_resent_bcc == NULL)
501 goto free;
502 field = mailimf_field_new(MAILIMF_FIELD_RESENT_BCC,
503 NULL /* return-path */,
504 NULL /* resent date */,
505 NULL /* resent from */,
506 NULL /* resent sender */,
507 NULL /* resent to */,
508 NULL /* resent cc */,
509 imf_resent_bcc /* resent bcc */,
510 NULL /* resent msg id */,
511 NULL /* date */,
512 NULL /* from */,
513 NULL /* sender */,
514 NULL /* reply-to */,
515 NULL /* to */,
516 NULL /* cc */,
517 NULL /* bcc */,
518 NULL /* message id */,
519 NULL /* in reply to */,
520 NULL /* references */,
521 NULL /* subject */,
522 NULL /* comments */,
523 NULL /* keywords */,
524 NULL /* optional field */);
525 if (field == NULL)
526 goto free;
527 r = mailimf_fields_add(fields, field);
528 if (r != MAILIMF_NO_ERROR)
529 goto free_field;
530 }
531
532 if (resent_msg_id != NULL) {
533 imf_resent_msg_id = mailimf_message_id_new(resent_msg_id);
534 if (imf_resent_msg_id == NULL)
535 goto free;
536 field = mailimf_field_new(MAILIMF_FIELD_RESENT_MSG_ID,
537 NULL /* return-path */,
538 NULL /* resent date */,
539 NULL /* resent from */,
540 NULL /* resent sender */,
541 NULL /* resent to */,
542 NULL /* resent cc */,
543 NULL /* resent bcc */,
544 imf_resent_msg_id /* resent msg id */,
545 NULL /* date */,
546 NULL /* from */,
547 NULL /* sender */,
548 NULL /* reply-to */,
549 NULL /* to */,
550 NULL /* cc */,
551 NULL /* bcc */,
552 NULL /* message id */,
553 NULL /* in reply to */,
554 NULL /* references */,
555 NULL /* subject */,
556 NULL /* comments */,
557 NULL /* keywords */,
558 NULL /* optional field */);
559 if (field == NULL)
560 goto free;
561 r = mailimf_fields_add(fields, field);
562 if (r != MAILIMF_NO_ERROR)
563 goto free_field;
564 }
565
566 return MAILIMF_NO_ERROR;
567
568 free_field:
569 if (field != NULL) {
570 detach_resent_field(field);
571 mailimf_field_free(field);
572 }
573 free:
574 detach_free_common_fields(imf_resent_date,
575 imf_resent_from,
576 imf_resent_sender,
577 imf_resent_to,
578 imf_resent_cc,
579 imf_resent_bcc,
580 imf_resent_msg_id);
581 return MAILIMF_ERROR_MEMORY;
582}
583
584struct mailimf_fields *
585mailimf_resent_fields_new_with_data_all(struct mailimf_date_time *
586 resent_date,
587 struct mailimf_mailbox_list *
588 resent_from,
589 struct mailimf_mailbox *
590 resent_sender,
591 struct mailimf_address_list *
592 resent_to,
593 struct mailimf_address_list *
594 resent_cc,
595 struct mailimf_address_list *
596 resent_bcc,
597 char * resent_msg_id)
598{
599 struct mailimf_fields * resent_fields;
600 int r;
601
602 resent_fields = mailimf_fields_new_empty();
603 if (resent_fields == NULL)
604 goto err;
605
606 r = mailimf_resent_fields_add_data(resent_fields,
607 resent_date, resent_from,
608 resent_sender, resent_to,
609 resent_cc, resent_bcc,
610 resent_msg_id);
611 if (r != MAILIMF_NO_ERROR)
612 goto free;
613
614 return resent_fields;
615
616 free:
617 mailimf_fields_free(resent_fields);
618 err:
619 return NULL;
620}
621
622
623struct mailimf_fields *
624mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from,
625 struct mailimf_mailbox * sender,
626 struct mailimf_address_list * to,
627 struct mailimf_address_list * cc,
628 struct mailimf_address_list * bcc)
629{
630 struct mailimf_date_time * date;
631 char * msg_id;
632 struct mailimf_fields * fields;
633
634 date = mailimf_get_current_date();
635 if (date == NULL)
636 goto err;
637
638 msg_id = mailimf_get_message_id();
639 if (msg_id == NULL)
640 goto free_date;
641
642 fields = mailimf_resent_fields_new_with_data_all(date,
643 from, sender, to, cc, bcc, msg_id);
644 if (fields == NULL)
645 goto free_msg_id;
646
647 return fields;
648
649 free_msg_id:
650 free(msg_id);
651 free_date:
652 mailimf_date_time_free(date);
653 err:
654 return NULL;
655}
656
657
658struct mailimf_fields *
659mailimf_fields_new_empty(void)
660{
661 clist * list;
662 struct mailimf_fields * fields_list;
663
664 list = clist_new();
665 if (list == NULL)
666 return NULL;
667
668 fields_list = mailimf_fields_new(list);
669 if (fields_list == NULL)
670 return NULL;
671
672 return fields_list;
673}
674
675int mailimf_fields_add(struct mailimf_fields * fields,
676 struct mailimf_field * field)
677{
678 int r;
679
680 r = clist_append(fields->fld_list, field);
681 if (r < 0)
682 return MAILIMF_ERROR_MEMORY;
683
684 return MAILIMF_NO_ERROR;
685}
686
687static void detach_free_fields(struct mailimf_orig_date * date,
688 struct mailimf_from * from,
689 struct mailimf_sender * sender,
690 struct mailimf_reply_to * reply_to,
691 struct mailimf_to * to,
692 struct mailimf_cc * cc,
693 struct mailimf_bcc * bcc,
694 struct mailimf_message_id * msg_id,
695 struct mailimf_in_reply_to * in_reply_to,
696 struct mailimf_references * references,
697 struct mailimf_subject * subject)
698{
699 detach_free_common_fields(date,
700 from,
701 sender,
702 to,
703 cc,
704 bcc,
705 msg_id);
706
707 if (reply_to != NULL) {
708 reply_to->rt_addr_list = NULL;
709 mailimf_reply_to_free(reply_to);
710 }
711
712 if (in_reply_to != NULL) {
713 in_reply_to->mid_list = NULL;
714 mailimf_in_reply_to_free(in_reply_to);
715 }
716
717 if (references != NULL) {
718 references->mid_list = NULL;
719 mailimf_references_free(references);
720 }
721
722 if (subject != NULL) {
723 subject->sbj_value = NULL;
724 mailimf_subject_free(subject);
725 }
726}
727
728
729static void detach_field(struct mailimf_field * field)
730{
731 field->fld_type = MAILIMF_FIELD_NONE;
732 mailimf_field_free(field);
733}
734
735int mailimf_fields_add_data(struct mailimf_fields * fields,
736 struct mailimf_date_time * date,
737 struct mailimf_mailbox_list * from,
738 struct mailimf_mailbox * sender,
739 struct mailimf_address_list * reply_to,
740 struct mailimf_address_list * to,
741 struct mailimf_address_list * cc,
742 struct mailimf_address_list * bcc,
743 char * msg_id,
744 clist * in_reply_to,
745 clist * references,
746 char * subject)
747{
748 struct mailimf_orig_date * imf_date;
749 struct mailimf_from * imf_from;
750 struct mailimf_sender * imf_sender;
751 struct mailimf_reply_to * imf_reply_to;
752 struct mailimf_to * imf_to;
753 struct mailimf_cc * imf_cc;
754 struct mailimf_bcc * imf_bcc;
755 struct mailimf_message_id * imf_msg_id;
756 struct mailimf_references * imf_references;
757 struct mailimf_in_reply_to * imf_in_reply_to;
758 struct mailimf_subject * imf_subject;
759 struct mailimf_field * field;
760 int r;
761
762 imf_date = NULL;
763 imf_from = NULL;
764 imf_sender = NULL;
765 imf_reply_to = NULL;
766 imf_to = NULL;
767 imf_cc = NULL;
768 imf_bcc = NULL;
769 imf_msg_id = NULL;
770 imf_references = NULL;
771 imf_in_reply_to = NULL;
772 imf_subject =NULL;
773 field = NULL;
774
775 if (date != NULL) {
776 imf_date = mailimf_orig_date_new(date);
777 if (imf_date == NULL)
778 goto free;
779 field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE,
780 NULL /* return-path */,
781 NULL /* resent date */,
782 NULL /* resent from */,
783 NULL /* resent sender */,
784 NULL /* resent to */,
785 NULL /* resent cc */,
786 NULL /* resent bcc */,
787 NULL /* resent msg id */,
788 imf_date /* date */,
789 NULL /* from */,
790 NULL /* sender */,
791 NULL /* reply-to */,
792 NULL /* to */,
793 NULL /* cc */,
794 NULL /* bcc */,
795 NULL /* message id */,
796 NULL /* in reply to */,
797 NULL /* references */,
798 NULL /* subject */,
799 NULL /* comments */,
800 NULL /* keywords */,
801 NULL /* optional field */);
802 if (field == NULL)
803 goto free;
804 r = mailimf_fields_add(fields, field);
805 if (r != MAILIMF_NO_ERROR)
806 goto free_field;
807 }
808
809 if (from != NULL) {
810 imf_from = mailimf_from_new(from);
811 if (imf_from == NULL)
812 goto free_field;
813 field = mailimf_field_new(MAILIMF_FIELD_FROM,
814 NULL /* return-path */,
815 NULL /* resent date */,
816 NULL /* resent from */,
817 NULL /* resent sender */,
818 NULL /* resent to */,
819 NULL /* resent cc */,
820 NULL /* resent bcc */,
821 NULL /* resent msg id */,
822 NULL /* date */,
823 imf_from /* from */,
824 NULL /* sender */,
825 NULL /* reply-to */,
826 NULL /* to */,
827 NULL /* cc */,
828 NULL /* bcc */,
829 NULL /* message id */,
830 NULL /* in reply to */,
831 NULL /* references */,
832 NULL /* subject */,
833 NULL /* comments */,
834 NULL /* keywords */,
835 NULL /* optional field */);
836 if (field == NULL)
837 goto free;
838 r = mailimf_fields_add(fields, field);
839 if (r != MAILIMF_NO_ERROR)
840 goto free_field;
841 }
842
843 if (sender != NULL) {
844 imf_sender = mailimf_sender_new(sender);
845 if (imf_sender == NULL)
846 goto free;
847 field = mailimf_field_new(MAILIMF_FIELD_SENDER,
848 NULL /* return-path */,
849 NULL /* resent date */,
850 NULL /* resent from */,
851 NULL /* resent sender */,
852 NULL /* resent to */,
853 NULL /* resent cc */,
854 NULL /* resent bcc */,
855 NULL /* resent msg id */,
856 NULL /* date */,
857 NULL /* from */,
858 imf_sender /* sender */,
859 NULL /* reply-to */,
860 NULL /* to */,
861 NULL /* cc */,
862 NULL /* bcc */,
863 NULL /* message id */,
864 NULL /* in reply to */,
865 NULL /* references */,
866 NULL /* subject */,
867 NULL /* comments */,
868 NULL /* keywords */,
869 NULL /* optional field */);
870 if (field == NULL)
871 goto free;
872 r = mailimf_fields_add(fields, field);
873 if (r != MAILIMF_NO_ERROR)
874 goto free_field;
875 }
876
877 if (reply_to != NULL) {
878 imf_reply_to = mailimf_reply_to_new(reply_to);
879 if (imf_reply_to == NULL)
880 goto free;
881 field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO,
882 NULL /* return-path */,
883 NULL /* resent date */,
884 NULL /* resent from */,
885 NULL /* resent sender */,
886 NULL /* resent to */,
887 NULL /* resent cc */,
888 NULL /* resent bcc */,
889 NULL /* resent msg id */,
890 NULL /* date */,
891 NULL /* from */,
892 NULL /* sender */,
893 imf_reply_to /* reply-to */,
894 NULL /* to */,
895 NULL /* cc */,
896 NULL /* bcc */,
897 NULL /* message id */,
898 NULL /* in reply to */,
899 NULL /* references */,
900 NULL /* subject */,
901 NULL /* comments */,
902 NULL /* keywords */,
903 NULL /* optional field */);
904 if (field == NULL)
905 goto free;
906 r = mailimf_fields_add(fields, field);
907 if (r != MAILIMF_NO_ERROR)
908 goto free_field;
909 }
910
911 if (to != NULL) {
912 imf_to = mailimf_to_new(to);
913 if (imf_to == NULL)
914 goto free;
915 field = mailimf_field_new(MAILIMF_FIELD_TO,
916 NULL /* return-path */,
917 NULL /* resent date */,
918 NULL /* resent from */,
919 NULL /* resent sender */,
920 NULL /* resent to */,
921 NULL /* resent cc */,
922 NULL /* resent bcc */,
923 NULL /* resent msg id */,
924 NULL /* date */,
925 NULL /* from */,
926 NULL /* sender */,
927 NULL /* reply-to */,
928 imf_to /* to */,
929 NULL /* cc */,
930 NULL /* bcc */,
931 NULL /* message id */,
932 NULL /* in reply to */,
933 NULL /* references */,
934 NULL /* subject */,
935 NULL /* comments */,
936 NULL /* keywords */,
937 NULL /* optional field */);
938 if (field == NULL)
939 goto free;
940 r = mailimf_fields_add(fields, field);
941 if (r != MAILIMF_NO_ERROR)
942 goto free_field;
943 }
944
945 if (cc != NULL) {
946 imf_cc = mailimf_cc_new(cc);
947 if (imf_cc == NULL)
948 goto free;
949 field = mailimf_field_new(MAILIMF_FIELD_CC,
950 NULL /* return-path */,
951 NULL /* resent date */,
952 NULL /* resent from */,
953 NULL /* resent sender */,
954 NULL /* resent to */,
955 NULL /* resent cc */,
956 NULL /* resent bcc */,
957 NULL /* resent msg id */,
958 NULL /* date */,
959 NULL /* from */,
960 NULL /* sender */,
961 NULL /* reply-to */,
962 NULL /* to */,
963 imf_cc /* cc */,
964 NULL /* bcc */,
965 NULL /* message id */,
966 NULL /* in reply to */,
967 NULL /* references */,
968 NULL /* subject */,
969 NULL /* comments */,
970 NULL /* keywords */,
971 NULL /* optional field */);
972 if (field == NULL)
973 goto free;
974 r = mailimf_fields_add(fields, field);
975 if (r != MAILIMF_NO_ERROR)
976 goto free_field;
977 }
978
979 if (bcc != NULL) {
980 imf_bcc = mailimf_bcc_new(bcc);
981 if (imf_bcc == NULL)
982 goto free;
983 field = mailimf_field_new(MAILIMF_FIELD_BCC,
984 NULL /* return-path */,
985 NULL /* resent date */,
986 NULL /* resent from */,
987 NULL /* resent sender */,
988 NULL /* resent to */,
989 NULL /* resent cc */,
990 NULL /* resent bcc */,
991 NULL /* resent msg id */,
992 NULL /* date */,
993 NULL /* from */,
994 NULL /* sender */,
995 NULL /* reply-to */,
996 NULL /* to */,
997 NULL /* cc */,
998 imf_bcc /* bcc */,
999 NULL /* message id */,
1000 NULL /* in reply to */,
1001 NULL /* references */,
1002 NULL /* subject */,
1003 NULL /* comments */,
1004 NULL /* keywords */,
1005 NULL /* optional field */);
1006 if (field == NULL)
1007 goto free;
1008 r = mailimf_fields_add(fields, field);
1009 if (r != MAILIMF_NO_ERROR)
1010 goto free_field;
1011 }
1012
1013 if (msg_id != NULL) {
1014 imf_msg_id = mailimf_message_id_new(msg_id);
1015 if (imf_msg_id == NULL)
1016 goto free;
1017 field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID,
1018 NULL /* return-path */,
1019 NULL /* resent date */,
1020 NULL /* resent from */,
1021 NULL /* resent sender */,
1022 NULL /* resent to */,
1023 NULL /* resent cc */,
1024 NULL /* resent bcc */,
1025 NULL /* resent msg id */,
1026 NULL /* date */,
1027 NULL /* from */,
1028 NULL /* sender */,
1029 NULL /* reply-to */,
1030 NULL /* to */,
1031 NULL /* cc */,
1032 NULL /* bcc */,
1033 imf_msg_id /* message id */,
1034 NULL /* in reply to */,
1035 NULL /* references */,
1036 NULL /* subject */,
1037 NULL /* comments */,
1038 NULL /* keywords */,
1039 NULL /* optional field */);
1040 if (field == NULL)
1041 goto free;
1042 r = mailimf_fields_add(fields, field);
1043 if (r != MAILIMF_NO_ERROR)
1044 goto free_field;
1045 }
1046
1047 if (in_reply_to != NULL) {
1048 imf_in_reply_to = mailimf_in_reply_to_new(in_reply_to);
1049 if (imf_in_reply_to == NULL)
1050 goto free;
1051 field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO,
1052 NULL /* return-path */,
1053 NULL /* resent date */,
1054 NULL /* resent from */,
1055 NULL /* resent sender */,
1056 NULL /* resent to */,
1057 NULL /* resent cc */,
1058 NULL /* resent bcc */,
1059 NULL /* resent msg id */,
1060 NULL /* date */,
1061 NULL /* from */,
1062 NULL /* sender */,
1063 NULL /* reply-to */,
1064 NULL /* to */,
1065 NULL /* cc */,
1066 NULL /* bcc */,
1067 NULL /* message id */,
1068 imf_in_reply_to /* in reply to */,
1069 NULL /* references */,
1070 NULL /* subject */,
1071 NULL /* comments */,
1072 NULL /* keywords */,
1073 NULL /* optional field */);
1074 if (field == NULL)
1075 goto free;
1076 r = mailimf_fields_add(fields, field);
1077 if (r != MAILIMF_NO_ERROR)
1078 goto free_field;
1079 }
1080
1081 if (references != NULL) {
1082 imf_references = mailimf_references_new(references);
1083 if (imf_references == NULL)
1084 goto free;
1085 field = mailimf_field_new(MAILIMF_FIELD_REFERENCES,
1086 NULL /* return-path */,
1087 NULL /* resent date */,
1088 NULL /* resent from */,
1089 NULL /* resent sender */,
1090 NULL /* resent to */,
1091 NULL /* resent cc */,
1092 NULL /* resent bcc */,
1093 NULL /* resent msg id */,
1094 NULL /* date */,
1095 NULL /* from */,
1096 NULL /* sender */,
1097 NULL /* reply-to */,
1098 NULL /* to */,
1099 NULL /* cc */,
1100 NULL /* bcc */,
1101 NULL /* message id */,
1102 NULL /* in reply to */,
1103 imf_references /* references */,
1104 NULL /* subject */,
1105 NULL /* comments */,
1106 NULL /* keywords */,
1107 NULL /* optional field */);
1108 if (field == NULL)
1109 goto free;
1110 r = mailimf_fields_add(fields, field);
1111 if (r != MAILIMF_NO_ERROR)
1112 goto free_field;
1113 }
1114
1115 if (subject != NULL) {
1116 imf_subject = mailimf_subject_new(subject);
1117 if (imf_subject == NULL)
1118 goto free;
1119 field = mailimf_field_new(MAILIMF_FIELD_SUBJECT,
1120 NULL /* return-path */,
1121 NULL /* resent date */,
1122 NULL /* resent from */,
1123 NULL /* resent sender */,
1124 NULL /* resent to */,
1125 NULL /* resent cc */,
1126 NULL /* resent bcc */,
1127 NULL /* resent msg id */,
1128 NULL /* date */,
1129 NULL /* from */,
1130 NULL /* sender */,
1131 NULL /* reply-to */,
1132 NULL /* to */,
1133 NULL /* cc */,
1134 NULL /* bcc */,
1135 NULL /* message id */,
1136 NULL /* in reply to */,
1137 NULL /* references */,
1138 imf_subject /* subject */,
1139 NULL /* comments */,
1140 NULL /* keywords */,
1141 NULL /* optional field */);
1142 if (field == NULL)
1143 goto free;
1144 r = mailimf_fields_add(fields, field);
1145 if (r != MAILIMF_NO_ERROR)
1146 goto free_field;
1147 }
1148
1149 return MAILIMF_NO_ERROR;
1150
1151 free_field:
1152 if (field != NULL) {
1153 detach_field(field);
1154 mailimf_field_free(field);
1155 }
1156 free:
1157 detach_free_fields(imf_date,
1158 imf_from,
1159 imf_sender,
1160 imf_reply_to,
1161 imf_to,
1162 imf_cc,
1163 imf_bcc,
1164 imf_msg_id,
1165 imf_in_reply_to,
1166 imf_references,
1167 imf_subject);
1168
1169 return MAILIMF_ERROR_MEMORY;
1170}
1171
1172struct mailimf_fields *
1173mailimf_fields_new_with_data_all(struct mailimf_date_time * date,
1174 struct mailimf_mailbox_list * from,
1175 struct mailimf_mailbox * sender,
1176 struct mailimf_address_list * reply_to,
1177 struct mailimf_address_list * to,
1178 struct mailimf_address_list * cc,
1179 struct mailimf_address_list * bcc,
1180 char * message_id,
1181 clist * in_reply_to,
1182 clist * references,
1183 char * subject)
1184{
1185 struct mailimf_fields * fields;
1186 int r;
1187
1188 fields = mailimf_fields_new_empty();
1189 if (fields == NULL)
1190 goto err;
1191
1192 r = mailimf_fields_add_data(fields,
1193 date,
1194 from,
1195 sender,
1196 reply_to,
1197 to,
1198 cc,
1199 bcc,
1200 message_id,
1201 in_reply_to,
1202 references,
1203 subject);
1204 if (r != MAILIMF_NO_ERROR)
1205 goto free;
1206
1207 return fields;
1208
1209 free:
1210 mailimf_fields_free(fields);
1211 err:
1212 return NULL;
1213}
1214
1215struct mailimf_fields *
1216mailimf_fields_new_with_data(struct mailimf_mailbox_list * from,
1217 struct mailimf_mailbox * sender,
1218 struct mailimf_address_list * reply_to,
1219 struct mailimf_address_list * to,
1220 struct mailimf_address_list * cc,
1221 struct mailimf_address_list * bcc,
1222 clist * in_reply_to,
1223 clist * references,
1224 char * subject)
1225{
1226 struct mailimf_date_time * date;
1227 char * msg_id;
1228 struct mailimf_fields * fields;
1229
1230 date = mailimf_get_current_date();
1231 if (date == NULL)
1232 goto err;
1233
1234 msg_id = mailimf_get_message_id();
1235 if (msg_id == NULL)
1236 goto free_date;
1237
1238 fields = mailimf_fields_new_with_data_all(date,
1239 from, sender, reply_to,
1240 to, cc, bcc,
1241 msg_id,
1242 in_reply_to, references,
1243 subject);
1244 if (fields == NULL)
1245 goto free_msg_id;
1246
1247 return fields;
1248
1249 free_msg_id:
1250 free(msg_id);
1251 free_date:
1252 mailimf_date_time_free(date);
1253 err:
1254 return NULL;
1255}
1256
1257
1258
1259#define MAX_MESSAGE_ID 512
1260
1261char * mailimf_get_message_id(void)
1262{
1263 char id[MAX_MESSAGE_ID];
1264 time_t now;
1265 char name[MAX_MESSAGE_ID];
1266 long value;
1267
1268 now = time(NULL);
1269 value = random();
1270
1271 gethostname(name, MAX_MESSAGE_ID);
1272 snprintf(id, MAX_MESSAGE_ID, "etPan.%lx.%lx.%x@%s",
1273 now, value, getpid(), name);
1274
1275 return strdup(id);
1276}
1277
1278
1279
1280static time_t mkgmtime(struct tm * tmp);
1281
1282
1283struct mailimf_date_time * mailimf_get_current_date(void)
1284{
1285 struct tm gmt;
1286 struct tm lt;
1287 int off;
1288 time_t now;
1289 struct mailimf_date_time * date_time;
1290
1291 now = time(NULL);
1292
1293 if (gmtime_r(&now, &gmt) == NULL)
1294 return NULL;
1295
1296 if (localtime_r(&now, &lt) == NULL)
1297 return NULL;
1298
1299 off = (mkgmtime(&lt) - mkgmtime(&gmt)) / (60 * 60) * 100;
1300
1301 date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900,
1302 lt.tm_hour, lt.tm_min, lt.tm_sec,
1303 off);
1304
1305 return date_time;
1306}
1307
1308
1309
1310/* mkgmtime.c - make time corresponding to a GMT timeval struct
1311 $Id$
1312
1313 * Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved.
1314 *
1315 * Redistribution and use in source and binary forms, with or without
1316 * modification, are permitted provided that the following conditions
1317 * are met:
1318 *
1319 * 1. Redistributions of source code must retain the above copyright
1320 * notice, this list of conditions and the following disclaimer.
1321 *
1322 * 2. Redistributions in binary form must reproduce the above copyright
1323 * notice, this list of conditions and the following disclaimer in
1324 * the documentation and/or other materials provided with the
1325 * distribution.
1326 *
1327 * 3. The name "Carnegie Mellon University" must not be used to
1328 * endorse or promote products derived from this software without
1329 * prior written permission. For permission or any other legal
1330 * details, please contact
1331 * Office of Technology Transfer
1332 * Carnegie Mellon University
1333 * 5000 Forbes Avenue
1334 * Pittsburgh, PA 15213-3890
1335 * (412) 268-4387, fax: (412) 268-7395
1336 * tech-transfer@andrew.cmu.edu
1337 *
1338 * 4. Redistributions of any form whatsoever must retain the following
1339 * acknowledgment:
1340 * "This product includes software developed by Computing Services
1341 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
1342 *
1343 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
1344 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1345 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
1346 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1347 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
1348 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
1349 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1350 *
1351 *
1352 */
1353/*
1354 * Copyright (c) 1987, 1989, 1993
1355 *The Regents of the University of California. All rights reserved.
1356 *
1357 * This code is derived from software contributed to Berkeley by
1358 * Arthur David Olson of the National Cancer Institute.
1359 *
1360 * Redistribution and use in source and binary forms, with or without
1361 * modification, are permitted provided that the following conditions
1362 * are met:
1363 * 1. Redistributions of source code must retain the above copyright
1364 * notice, this list of conditions and the following disclaimer.
1365 * 2. Redistributions in binary form must reproduce the above copyright
1366 * notice, this list of conditions and the following disclaimer in the
1367 * documentation and/or other materials provided with the distribution.
1368 * 3. All advertising materials mentioning features or use of this software
1369 * must display the following acknowledgement:
1370 *This product includes software developed by the University of
1371 *California, Berkeley and its contributors.
1372 * 4. Neither the name of the University nor the names of its contributors
1373 * may be used to endorse or promote products derived from this software
1374 * without specific prior written permission.
1375 *
1376 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1377 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1378 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1379 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1380 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1381 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1382 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1383 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1384 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1385 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1386 * SUCH DAMAGE.
1387 */
1388
1389/*
1390** Adapted from code provided by Robert Elz, who writes:
1391 **The "best" way to do mktime I think is based on an idea of Bob
1392 **Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
1393 **It does a binary search of the time_t space. Since time_t's are
1394 **just 32 bits, its a max of 32 iterations (even at 64 bits it
1395 **would still be very reasonable).
1396*/
1397
1398/*
1399 adapted for libEtPan! by DINH V. Hoa
1400*/
1401
1402#ifndef WRONG
1403 #define WRONG(-1)
1404#endif /* !defined WRONG */
1405
1406static int tmcomp(struct tm * atmp, struct tm * btmp)
1407{
1408 register intresult;
1409
1410 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1411 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1412 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1413 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1414 (result = (atmp->tm_min - btmp->tm_min)) == 0)
1415 result = atmp->tm_sec - btmp->tm_sec;
1416 return result;
1417}
1418
1419static time_t mkgmtime(struct tm * tmp)
1420{
1421 register int dir;
1422 register int bits;
1423 register int saved_seconds;
1424 time_t t;
1425 struct tm yourtm, *mytm;
1426
1427 yourtm = *tmp;
1428 saved_seconds = yourtm.tm_sec;
1429 yourtm.tm_sec = 0;
1430 /*
1431 ** Calculate the number of magnitude bits in a time_t
1432 ** (this works regardless of whether time_t is
1433 ** signed or unsigned, though lint complains if unsigned).
1434 */
1435 for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
1436 ;
1437 /*
1438 ** If time_t is signed, then 0 is the median value,
1439 ** if time_t is unsigned, then 1 << bits is median.
1440 */
1441 t = (t < 0) ? 0 : ((time_t) 1 << bits);
1442 for ( ; ; ) {
1443 mytm = gmtime(&t);
1444 dir = tmcomp(mytm, &yourtm);
1445 if (dir != 0) {
1446 if (bits-- < 0)
1447 return WRONG;
1448 if (bits < 0)
1449 --t;
1450 else if (dir > 0)
1451 t -= (time_t) 1 << bits;
1452 elset += (time_t) 1 << bits;
1453 continue;
1454 }
1455 break;
1456 }
1457 t += saved_seconds;
1458 return t;
1459}
1460
1461
1462
1463
1464
1465
1466
1467void mailimf_single_fields_init(struct mailimf_single_fields * single_fields,
1468 struct mailimf_fields * fields)
1469{
1470 clistiter * cur;
1471
1472 memset(single_fields, 0, sizeof(struct mailimf_single_fields));
1473
1474 cur = clist_begin(fields->fld_list);
1475 while (cur != NULL) {
1476 struct mailimf_field * field;
1477
1478 field = clist_content(cur);
1479
1480 switch (field->fld_type) {
1481 case MAILIMF_FIELD_ORIG_DATE:
1482 if (single_fields->fld_orig_date == NULL)
1483 single_fields->fld_orig_date = field->fld_data.fld_orig_date;
1484 cur = clist_next(cur);
1485 break;
1486 case MAILIMF_FIELD_FROM:
1487 if (single_fields->fld_from == NULL) {
1488 single_fields->fld_from = field->fld_data.fld_from;
1489 cur = clist_next(cur);
1490 }
1491 else {
1492 clist_concat(single_fields->fld_from->frm_mb_list->mb_list,
1493 field->fld_data.fld_from->frm_mb_list->mb_list);
1494 mailimf_field_free(field);
1495 cur = clist_delete(fields->fld_list, cur);
1496 }
1497 break;
1498 case MAILIMF_FIELD_SENDER:
1499 if (single_fields->fld_sender == NULL)
1500 single_fields->fld_sender = field->fld_data.fld_sender;
1501 cur = clist_next(cur);
1502 break;
1503 case MAILIMF_FIELD_REPLY_TO:
1504 if (single_fields->fld_reply_to == NULL) {
1505 single_fields->fld_reply_to = field->fld_data.fld_reply_to;
1506 cur = clist_next(cur);
1507 }
1508 else {
1509 clist_concat(single_fields->fld_reply_to->rt_addr_list->ad_list,
1510 field->fld_data.fld_reply_to->rt_addr_list->ad_list);
1511 mailimf_field_free(field);
1512 cur = clist_delete(fields->fld_list, cur);
1513 }
1514 break;
1515 case MAILIMF_FIELD_TO:
1516 if (single_fields->fld_to == NULL) {
1517 single_fields->fld_to = field->fld_data.fld_to;
1518 cur = clist_next(cur);
1519 }
1520 else {
1521 clist_concat(single_fields->fld_to->to_addr_list->ad_list,
1522 field->fld_data.fld_to->to_addr_list->ad_list);
1523 mailimf_field_free(field);
1524 cur = clist_delete(fields->fld_list, cur);
1525 }
1526 break;
1527 case MAILIMF_FIELD_CC:
1528 if (single_fields->fld_cc == NULL) {
1529 single_fields->fld_cc = field->fld_data.fld_cc;
1530 cur = clist_next(cur);
1531 }
1532 else {
1533 clist_concat(single_fields->fld_cc->cc_addr_list->ad_list,
1534 field->fld_data.fld_cc->cc_addr_list->ad_list);
1535 mailimf_field_free(field);
1536 cur = clist_delete(fields->fld_list, cur);
1537 }
1538 break;
1539 case MAILIMF_FIELD_BCC:
1540 if (single_fields->fld_bcc == NULL) {
1541 single_fields->fld_bcc = field->fld_data.fld_bcc;
1542 cur = clist_next(cur);
1543 }
1544 else {
1545 clist_concat(single_fields->fld_bcc->bcc_addr_list->ad_list,
1546 field->fld_data.fld_bcc->bcc_addr_list->ad_list);
1547 mailimf_field_free(field);
1548 cur = clist_delete(fields->fld_list, cur);
1549 }
1550 break;
1551 case MAILIMF_FIELD_MESSAGE_ID:
1552 if (single_fields->fld_message_id == NULL)
1553 single_fields->fld_message_id = field->fld_data.fld_message_id;
1554 cur = clist_next(cur);
1555 break;
1556 case MAILIMF_FIELD_IN_REPLY_TO:
1557 if (single_fields->fld_in_reply_to == NULL)
1558 single_fields->fld_in_reply_to = field->fld_data.fld_in_reply_to;
1559 cur = clist_next(cur);
1560 break;
1561 case MAILIMF_FIELD_REFERENCES:
1562 if (single_fields->fld_references == NULL)
1563 single_fields->fld_references = field->fld_data.fld_references;
1564 cur = clist_next(cur);
1565 break;
1566 case MAILIMF_FIELD_SUBJECT:
1567 if (single_fields->fld_subject == NULL)
1568 single_fields->fld_subject = field->fld_data.fld_subject;
1569 cur = clist_next(cur);
1570 break;
1571 case MAILIMF_FIELD_COMMENTS:
1572 if (single_fields->fld_comments == NULL)
1573 single_fields->fld_comments = field->fld_data.fld_comments;
1574 cur = clist_next(cur);
1575 break;
1576 case MAILIMF_FIELD_KEYWORDS:
1577 if (single_fields->fld_keywords == NULL)
1578 single_fields->fld_keywords = field->fld_data.fld_keywords;
1579 cur = clist_next(cur);
1580 break;
1581 default:
1582 cur = clist_next(cur);
1583 break;
1584 }
1585 }
1586}
1587
1588
1589struct mailimf_single_fields *
1590mailimf_single_fields_new(struct mailimf_fields * fields)
1591{
1592 struct mailimf_single_fields * single_fields;
1593
1594 single_fields = malloc(sizeof(struct mailimf_single_fields));
1595 if (single_fields == NULL)
1596 goto err;
1597
1598 mailimf_single_fields_init(single_fields, fields);
1599
1600 return single_fields;
1601
1602 err:
1603 return NULL;
1604}
1605
1606void mailimf_single_fields_free(struct mailimf_single_fields *
1607 single_fields)
1608{
1609 free(single_fields);
1610}
1611
1612struct mailimf_field * mailimf_field_new_custom(char * name, char * value)
1613{
1614 struct mailimf_optional_field * opt_field;
1615 struct mailimf_field * field;
1616
1617 opt_field = mailimf_optional_field_new(name, value);
1618 if (opt_field == NULL)
1619 goto err;
1620
1621 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD,
1622 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1623 NULL, NULL, NULL, NULL,
1624 NULL, NULL, NULL, NULL,
1625 NULL, NULL, NULL, NULL,
1626 NULL, NULL, opt_field);
1627 if (field == NULL)
1628 goto free_opt_field;
1629
1630 return field;
1631
1632 free_opt_field:
1633 mailimf_optional_field_free(opt_field);
1634 err:
1635 return NULL;
1636}
diff --git a/libetpan/src/low-level/imf/mailimf_types_helper.h b/libetpan/src/low-level/imf/mailimf_types_helper.h
new file mode 100644
index 0000000..337b1d0
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_types_helper.h
@@ -0,0 +1,370 @@
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 MAILIMF_TYPES_HELPER
37
38#define MAILIMF_TYPES_HELPER
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimf_types.h>
45
46/*
47 IMPORTANT NOTE:
48
49 All allocation functions will take as argument allocated data
50 and will store these data in the structure they will allocate.
51 Data should be persistant during all the use of the structure
52 and will be freed by the free function of the structure
53
54 allocation functions will return NULL on failure
55*/
56
57/*
58 mailimf_mailbox_list_new_empty creates an empty list of mailboxes
59*/
60
61struct mailimf_mailbox_list *
62mailimf_mailbox_list_new_empty();
63
64/*
65 mailimf_mailbox_list_add adds a mailbox to the list of mailboxes
66
67 @return MAILIMF_NO_ERROR will be returned on success,
68 other code will be returned otherwise
69*/
70
71int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list,
72 struct mailimf_mailbox * mb);
73
74/*
75 mailimf_mailbox_list_add_parse parse the given string
76 into a mailimf_mailbox structure and adds it to the list of mailboxes
77
78 @return MAILIMF_NO_ERROR will be returned on success,
79 other code will be returned otherwise
80*/
81
82int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list,
83 char * mb_str);
84
85/*
86 mailimf_mailbox creates a mailimf_mailbox structure with the given
87 arguments and adds it to the list of mailboxes
88
89 - display_name is the name that will be displayed for this mailbox,
90 for example 'name' in '"name" <mailbox@domain>,
91 should be allocated with malloc()
92
93 - address is the mailbox, for example 'mailbox@domain'
94 in '"name" <mailbox@domain>, should be allocated with malloc()
95
96 @return MAILIMF_NO_ERROR will be returned on success,
97 other code will be returned otherwise
98*/
99
100int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list,
101 char * display_name, char * address);
102
103/*
104 mailimf_address_list_new_empty creates an empty list of addresses
105*/
106
107struct mailimf_address_list *
108mailimf_address_list_new_empty();
109
110/*
111 mailimf_address_list_add adds a mailbox to the list of addresses
112
113 @return MAILIMF_NO_ERROR will be returned on success,
114 other code will be returned otherwise
115*/
116
117int mailimf_address_list_add(struct mailimf_address_list * address_list,
118 struct mailimf_address * addr);
119
120/*
121 mailimf_address_list_add_parse parse the given string
122 into a mailimf_address structure and adds it to the list of addresses
123
124 @return MAILIMF_NO_ERROR will be returned on success,
125 other code will be returned otherwise
126*/
127
128int mailimf_address_list_add_parse(struct mailimf_address_list * address_list,
129 char * addr_str);
130
131/*
132 mailimf_address_list_add_mb creates a mailbox mailimf_address
133 with the given arguments and adds it to the list of addresses
134
135 - display_name is the name that will be displayed for this mailbox,
136 for example 'name' in '"name" <mailbox@domain>,
137 should be allocated with malloc()
138
139 - address is the mailbox, for example 'mailbox@domain'
140 in '"name" <mailbox@domain>, should be allocated with malloc()
141
142 @return MAILIMF_NO_ERROR will be returned on success,
143 other code will be returned otherwise
144*/
145
146int mailimf_address_list_add_mb(struct mailimf_address_list * address_list,
147 char * display_name, char * address);
148
149/*
150 mailimf_resent_fields_add_data adds a set of resent fields in the
151 given mailimf_fields structure.
152
153 if you don't want a given field in the set to be added in the list
154 of fields, you can give NULL as argument
155
156 @param resent_msg_id sould be allocated with malloc()
157
158 @return MAILIMF_NO_ERROR will be returned on success,
159 other code will be returned otherwise
160*/
161
162int
163mailimf_resent_fields_add_data(struct mailimf_fields * fields,
164 struct mailimf_date_time * resent_date,
165 struct mailimf_mailbox_list * resent_from,
166 struct mailimf_mailbox * resent_sender,
167 struct mailimf_address_list * resent_to,
168 struct mailimf_address_list * resent_cc,
169 struct mailimf_address_list * resent_bcc,
170 char * resent_msg_id);
171
172/*
173 mailimf_resent_fields_new_with_data_all creates a new mailimf_fields
174 structure with a set of resent fields
175
176 if you don't want a given field in the set to be added in the list
177 of fields, you can give NULL as argument
178
179 @param resent_msg_id sould be allocated with malloc()
180
181 @return MAILIMF_NO_ERROR will be returned on success,
182 other code will be returned otherwise
183*/
184
185struct mailimf_fields *
186mailimf_resent_fields_new_with_data_all(struct mailimf_date_time *
187 resent_date, struct mailimf_mailbox_list * resent_from,
188 struct mailimf_mailbox * resent_sender,
189 struct mailimf_address_list * resent_to,
190 struct mailimf_address_list * resent_cc,
191 struct mailimf_address_list * resent_bcc,
192 char * resent_msg_id);
193
194/*
195 mailimf_resent_fields_new_with_data_all creates a new mailimf_fields
196 structure with a set of resent fields.
197 Resent-Date and Resent-Message-ID fields will be generated for you.
198
199 if you don't want a given field in the set to be added in the list
200 of fields, you can give NULL as argument
201
202 @return MAILIMF_NO_ERROR will be returned on success,
203 other code will be returned otherwise
204*/
205
206struct mailimf_fields *
207mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from,
208 struct mailimf_mailbox * sender,
209 struct mailimf_address_list * to,
210 struct mailimf_address_list * cc,
211 struct mailimf_address_list * bcc);
212
213/*
214 this function creates a new mailimf_fields structure with no fields
215*/
216
217struct mailimf_fields *
218mailimf_fields_new_empty(void);
219
220
221/*
222 this function adds a field to the mailimf_fields structure
223
224 @return MAILIMF_NO_ERROR will be returned on success,
225 other code will be returned otherwise
226*/
227
228int mailimf_fields_add(struct mailimf_fields * fields,
229 struct mailimf_field * field);
230
231
232/*
233 mailimf_fields_add_data adds a set of fields in the
234 given mailimf_fields structure.
235
236 if you don't want a given field in the set to be added in the list
237 of fields, you can give NULL as argument
238
239 @param msg_id sould be allocated with malloc()
240 @param subject should be allocated with malloc()
241 @param in_reply_to each elements of this list should be allocated
242 with malloc()
243 @param references each elements of this list should be allocated
244 with malloc()
245
246 @return MAILIMF_NO_ERROR will be returned on success,
247 other code will be returned otherwise
248*/
249
250int mailimf_fields_add_data(struct mailimf_fields * fields,
251 struct mailimf_date_time * date,
252 struct mailimf_mailbox_list * from,
253 struct mailimf_mailbox * sender,
254 struct mailimf_address_list * reply_to,
255 struct mailimf_address_list * to,
256 struct mailimf_address_list * cc,
257 struct mailimf_address_list * bcc,
258 char * msg_id,
259 clist * in_reply_to,
260 clist * references,
261 char * subject);
262
263/*
264 mailimf_fields_new_with_data_all creates a new mailimf_fields
265 structure with a set of fields
266
267 if you don't want a given field in the set to be added in the list
268 of fields, you can give NULL as argument
269
270 @param message_id sould be allocated with malloc()
271 @param subject should be allocated with malloc()
272 @param in_reply_to each elements of this list should be allocated
273 with malloc()
274 @param references each elements of this list should be allocated
275 with malloc()
276
277 @return MAILIMF_NO_ERROR will be returned on success,
278 other code will be returned otherwise
279*/
280
281struct mailimf_fields *
282mailimf_fields_new_with_data_all(struct mailimf_date_time * date,
283 struct mailimf_mailbox_list * from,
284 struct mailimf_mailbox * sender,
285 struct mailimf_address_list * reply_to,
286 struct mailimf_address_list * to,
287 struct mailimf_address_list * cc,
288 struct mailimf_address_list * bcc,
289 char * message_id,
290 clist * in_reply_to,
291 clist * references,
292 char * subject);
293
294/*
295 mailimf_fields_new_with_data creates a new mailimf_fields
296 structure with a set of fields
297 Date and Message-ID fields will be generated for you.
298
299 if you don't want a given field in the set to be added in the list
300 of fields, you can give NULL as argument
301
302 @param subject should be allocated with malloc()
303 @param in_reply_to each elements of this list should be allocated
304 with malloc()
305 @param references each elements of this list should be allocated
306 with malloc()
307
308 @return MAILIMF_NO_ERROR will be returned on success,
309 other code will be returned otherwise
310*/
311
312struct mailimf_fields *
313mailimf_fields_new_with_data(struct mailimf_mailbox_list * from,
314 struct mailimf_mailbox * sender,
315 struct mailimf_address_list * reply_to,
316 struct mailimf_address_list * to,
317 struct mailimf_address_list * cc,
318 struct mailimf_address_list * bcc,
319 clist * in_reply_to,
320 clist * references,
321 char * subject);
322
323/*
324 this function returns an allocated message identifier to
325 use in a Message-ID or Resent-Message-ID field
326*/
327
328char * mailimf_get_message_id(void);
329
330/*
331 this function returns a mailimf_date_time structure to
332 use in a Date or Resent-Date field
333*/
334
335struct mailimf_date_time * mailimf_get_current_date(void);
336
337
338/*
339 mailimf_single_fields_init fills a mailimf_single_fields structure
340 with the content of a mailimf_fields structure
341*/
342
343void mailimf_single_fields_init(struct mailimf_single_fields * single_fields,
344 struct mailimf_fields * fields);
345
346/*
347 mailimf_single_fields_new creates a new mailimf_single_fields and
348 fills the structure with mailimf_fields
349*/
350
351struct mailimf_single_fields *
352mailimf_single_fields_new(struct mailimf_fields * fields);
353
354void mailimf_single_fields_free(struct mailimf_single_fields *
355 single_fields);
356
357/*
358 mailimf_field_new_custom creates a new field of type optional
359
360 @param name should be allocated with malloc()
361 @param value should be allocated with malloc()
362*/
363
364struct mailimf_field * mailimf_field_new_custom(char * name, char * value);
365
366#ifdef __cplusplus
367}
368#endif
369
370#endif
diff --git a/libetpan/src/low-level/imf/mailimf_write.c b/libetpan/src/low-level/imf/mailimf_write.c
new file mode 100644
index 0000000..7301f37
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write.c
@@ -0,0 +1,2021 @@
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 "mailimf_write.h"
37
38#include <time.h>
39#include <string.h>
40#include <ctype.h>
41
42#define MAX_MAIL_COL 72
43
44#ifndef TRUE
45#define TRUE 1
46#endif
47
48#ifndef FALSE
49#define FALSE 0
50#endif
51
52#define MAX_VALID_IMF_LINE 998
53
54static int mailimf_orig_date_write(FILE * f, int * col,
55 struct mailimf_orig_date * date);
56static int mailimf_date_time_write(FILE * f, int * col,
57 struct mailimf_date_time * date_time);
58static int mailimf_from_write(FILE * f, int * col,
59 struct mailimf_from * from);
60static int mailimf_sender_write(FILE * f, int * col,
61 struct mailimf_sender * sender);
62static int mailimf_reply_to_write(FILE * f, int * col,
63 struct mailimf_reply_to * reply_to);
64static int mailimf_to_write(FILE * f, int * col,
65 struct mailimf_to * to);
66static int mailimf_cc_write(FILE * f, int * col,
67 struct mailimf_cc * to);
68static int mailimf_bcc_write(FILE * f, int * col,
69 struct mailimf_bcc * to);
70static int mailimf_message_id_write(FILE * f, int * col,
71 struct mailimf_message_id * message_id);
72static int mailimf_msg_id_list_write(FILE * f, int * col,
73 clist * list);
74static int mailimf_in_reply_to_write(FILE * f, int * col,
75 struct mailimf_in_reply_to *
76 in_reply_to);
77static int mailimf_references_write(FILE * f, int * col,
78 struct mailimf_references * references);
79static int mailimf_subject_write(FILE * f, int * col,
80 struct mailimf_subject * subject);
81
82static int mailimf_address_write(FILE * f, int * col,
83 struct mailimf_address * addr);
84static int mailimf_group_write(FILE * f, int * col,
85 struct mailimf_group * group);
86
87static int mailimf_mailbox_write(FILE * f, int * col,
88 struct mailimf_mailbox * mb);
89
90static int mailimf_comments_write(FILE * f, int * col,
91 struct mailimf_comments * comments);
92
93static int mailimf_optional_field_write(FILE * f, int * col,
94 struct mailimf_optional_field * field);
95
96static int mailimf_keywords_write(FILE * f, int * col,
97 struct mailimf_keywords * keywords);
98
99static int mailimf_return_write(FILE * f, int * col,
100 struct mailimf_return * return_path);
101
102static int mailimf_path_write(FILE * f, int * col,
103 struct mailimf_path * path);
104
105static int mailimf_resent_date_write(FILE * f, int * col,
106 struct mailimf_orig_date * date);
107
108static int mailimf_resent_from_write(FILE * f, int * col,
109 struct mailimf_from * from);
110
111static int mailimf_resent_sender_write(FILE * f, int * col,
112 struct mailimf_sender * sender);
113
114static int mailimf_resent_to_write(FILE * f, int * col,
115 struct mailimf_to * to);
116
117static int mailimf_resent_cc_write(FILE * f, int * col,
118 struct mailimf_cc * cc);
119
120static int mailimf_resent_bcc_write(FILE * f, int * col,
121 struct mailimf_bcc * bcc);
122
123static int
124mailimf_resent_msg_id_write(FILE * f, int * col,
125 struct mailimf_message_id * message_id);
126
127
128
129/* ************************ */
130
131#if 0
132int mailimf_string_write(FILE * f, int * col,
133 char * str, size_t length)
134{
135 int r;
136
137 if (length != 0) {
138 r = fwrite(str, sizeof(char), length, f);
139 if (r < 0)
140 return MAILIMF_ERROR_FILE;
141 * col += length;
142 }
143
144 return MAILIMF_NO_ERROR;
145}
146#endif
147
148#define CRLF "\r\n"
149#define HEADER_FOLD "\r\n "
150
151static inline int flush_buf(FILE * f, const char * str, size_t length)
152{
153 if (length != 0) {
154 int r;
155
156 r = fwrite(str, 1, length, f);
157 if (r == 0)
158 return MAILIMF_ERROR_FILE;
159 }
160 return MAILIMF_NO_ERROR;
161}
162
163#define CUT_AT_MAX_VALID_IMF_LINE
164
165int mailimf_string_write(FILE * f, int * col,
166 const char * str, size_t length)
167{
168 int r;
169 size_t count;
170 const char * block_begin;
171 const char * p;
172 int done;
173
174 p = str;
175 block_begin = str;
176 count = 0;
177
178 while (length > 0) {
179#ifdef CUT_AT_MAX_VALID_IMF_LINE
180 if (count >= 998) {
181 /*
182 cut lines at maximum valid length for internet message
183 format standard (currently RFC 2822)
184
185 This should not happen.
186 In case there are some lines larger than 998 in body,
187 the encoding must be changed into base64 or quoted-printable
188 so that wrapping to 72 columns is done.
189 */
190
191 r = flush_buf(f, block_begin, count);
192 if (r != MAILIMF_NO_ERROR)
193 return r;
194
195 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
196 if (r == 0)
197 return MAILIMF_ERROR_FILE;
198
199 count = 0;
200 block_begin = p;
201
202 * col = 0;
203 }
204#endif
205 switch (* p) {
206 case '\n':
207 r = flush_buf(f, block_begin, count);
208 if (r != MAILIMF_NO_ERROR)
209 return r;
210
211 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
212 if (r == 0)
213 return MAILIMF_ERROR_FILE;
214
215 p ++;
216 length --;
217 count = 0;
218 block_begin = p;
219
220 * col = 0;
221 break;
222
223 case '\r':
224 done = 0;
225 if (length >= 2) {
226 if (* (p + 1) == '\n') {
227 r = flush_buf(f, block_begin, count);
228 if (r != MAILIMF_NO_ERROR)
229 return r;
230
231 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
232 if (r == 0)
233 return MAILIMF_ERROR_FILE;
234
235 p += 2;
236 length -= 2;
237 count = 0;
238 block_begin = p;
239
240 * col = 0;
241
242 done = 1;
243 }
244 }
245 if (!done) {
246 r = flush_buf(f, block_begin, count);
247 if (r != MAILIMF_NO_ERROR)
248 return r;
249
250 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
251 if (r == 0)
252 return MAILIMF_ERROR_FILE;
253
254 p ++;
255 length --;
256 count = 0;
257 block_begin = p;
258
259 * col = 0;
260 }
261 break;
262
263 default:
264 p ++;
265 count ++;
266 length --;
267 break;
268 }
269 }
270
271 r = flush_buf(f, block_begin, count);
272 if (r != MAILIMF_NO_ERROR)
273 return r;
274 * col += count;
275
276 return MAILIMF_NO_ERROR;
277}
278
279#if 0
280int mailimf_header_string_write(FILE * f, int * col,
281 char * str, size_t length)
282{
283 char * p;
284 char * block_begin;
285 int current_col;
286 char * last_cut;
287 int r;
288 int first;
289
290 if (* col + length < MAX_MAIL_COL)
291 return mailimf_string_write(f, col, str, length);
292
293 first = 1;
294 p = str;
295 block_begin = p;
296 last_cut = block_begin;
297 current_col = * col;
298
299 while (1) {
300 if (current_col >= MAX_MAIL_COL) {
301 /* if we reach the maximum recommanded size of line */
302 if (last_cut == block_begin) {
303 /* if we could not find any place to cut */
304 if (first) {
305 /* fold the header */
306 r = mailimf_string_write(f, col, HEADER_FOLD,
307 sizeof(HEADER_FOLD) - 1);
308 if (r != MAILIMF_NO_ERROR)
309 return r;
310 current_col = * col + p - block_begin;
311 first = 0;
312 }
313 else {
314 /* cut the header */
315 r = mailimf_string_write(f, col, block_begin, p - block_begin);
316 if (r != MAILIMF_NO_ERROR)
317 return r;
318 r = mailimf_string_write(f, col, HEADER_FOLD,
319 sizeof(HEADER_FOLD) - 1);
320 if (r != MAILIMF_NO_ERROR)
321 return r;
322 first = 0;
323 block_begin = p;
324 last_cut = block_begin;
325 current_col = * col + p - block_begin;
326 }
327 }
328 else {
329 /* if we found a place to cut */
330 r = mailimf_string_write(f, col, block_begin, last_cut - block_begin);
331 if (r != MAILIMF_NO_ERROR)
332 return r;
333 r = mailimf_string_write(f, col, HEADER_FOLD,
334 sizeof(HEADER_FOLD) - 1);
335 if (r != MAILIMF_NO_ERROR)
336 return r;
337 first = 0;
338 block_begin = last_cut;
339 last_cut = block_begin;
340 current_col = * col + p - block_begin;
341 continue;
342 }
343 }
344 else {
345 if (length == 0)
346 break;
347
348 switch (* p) {
349 case ' ':
350 case '\t':
351 last_cut = p;
352 current_col ++;
353 break;
354
355 case '\r':
356 case '\n':
357 current_col = 0;
358 break;
359
360 default:
361 current_col ++;
362 break;
363 }
364
365 p ++;
366 length --;
367 }
368 }
369
370 return mailimf_string_write(f, col, block_begin, p - block_begin);
371}
372#endif
373
374#if 0
375enum {
376 STATE_LOWER_72,
377 STATE_LOWER_72_CUT,
378 STATE_EQUAL_72,
379 STATE_LOWER_998,
380 STATE_EQUAL_998,
381};
382
383int mailimf_header_string_write(FILE * f, int * col,
384 const char * str, size_t length)
385{
386 int state;
387 const char * p;
388 const char * block_begin;
389 size_t size;
390 const char * cut;
391 int r;
392
393 if (* col < MAX_MAIL_COL)
394 state = STATE_LOWER_72_CUT;
395 else if (* col == MAX_MAIL_COL)
396 state = STATE_EQUAL_72;
397 else if (* col < MAX_VALID_IMF_LINE)
398 state = STATE_LOWER_998;
399 else
400 state = STATE_EQUAL_998;
401
402 p = str;
403 block_begin = p;
404 size = * col;
405 cut = p;
406
407 while (length > 0) {
408 switch (state) {
409 case STATE_LOWER_72:
410 switch (* p) {
411 case '\r':
412 case '\n':
413 p ++;
414 length --;
415 size = 0;
416 break;
417
418 case ' ':
419 case '\t':
420 cut = p;
421 p ++;
422 length --;
423 size ++;
424 state = STATE_LOWER_72_CUT;
425 break;
426
427 default:
428 if (size < MAX_MAIL_COL - 1) {
429 p ++;
430 length --;
431 size ++;
432 }
433 else {
434 state = STATE_EQUAL_72;
435 p ++;
436 length --;
437 size ++;
438 }
439 break;
440 }
441 break; /* end of STATE_LOWER_72 */
442
443 case STATE_LOWER_72_CUT:
444 switch (* p) {
445 case '\r':
446 case '\n':
447 p ++;
448 length --;
449 size = 0;
450 state = STATE_LOWER_72;
451 break;
452
453 case ' ':
454 case '\t':
455 cut = p;
456 p ++;
457 length --;
458 size ++;
459 break;
460
461 default:
462 if (size < MAX_MAIL_COL) {
463 p ++;
464 length --;
465 size ++;
466 }
467 else {
468 r = mailimf_string_write(f, col, block_begin, cut - block_begin);
469 if (r != MAILIMF_NO_ERROR)
470 return r;
471 r = mailimf_string_write(f, col, HEADER_FOLD,
472 sizeof(HEADER_FOLD) - 1);
473 if (r != MAILIMF_NO_ERROR)
474 return r;
475 p ++;
476 length --;
477 block_begin = cut;
478 if ((* block_begin == ' ') || (* block_begin == '\t'))
479 block_begin ++;
480 size = p - block_begin + * col;
481 state = STATE_LOWER_72;
482 }
483 break;
484 }
485 break; /* end of STATE_LOWER_72_CUT */
486
487 case STATE_EQUAL_72:
488 switch (* p) {
489 case '\r':
490 case '\n':
491 p ++;
492 length --;
493 size = 0;
494 state = STATE_LOWER_72;
495 break;
496
497 case ' ':
498 case '\t':
499 r = mailimf_string_write(f, col, block_begin, p - block_begin);
500 if (r != MAILIMF_NO_ERROR)
501 return r;
502 r = mailimf_string_write(f, col, HEADER_FOLD,
503 sizeof(HEADER_FOLD) - 1);
504 if (r != MAILIMF_NO_ERROR)
505 return r;
506 p ++;
507 length --;
508 block_begin = p;
509 size = p - block_begin + * col;
510 state = STATE_LOWER_72;
511 break;
512
513 default:
514 p ++;
515 length --;
516 size ++;
517 state = STATE_LOWER_998;
518 break;
519 }
520 break; /* end of STATE_EQUAL_72 */
521
522 case STATE_LOWER_998:
523 switch (* p) {
524 case '\r':
525 case '\n':
526 p ++;
527 length --;
528 size = 0;
529 state = STATE_LOWER_72;
530 break;
531
532 case ' ':
533 case '\t':
534 r = mailimf_string_write(f, col, block_begin, p - block_begin);
535 if (r != MAILIMF_NO_ERROR)
536 return r;
537 r = mailimf_string_write(f, col, HEADER_FOLD,
538 sizeof(HEADER_FOLD) - 1);
539 if (r != MAILIMF_NO_ERROR)
540 return r;
541 p ++;
542 length --;
543 block_begin = p;
544 size = p - block_begin + * col;
545 state = STATE_LOWER_72;
546 break;
547
548 default:
549 if (size < MAX_VALID_IMF_LINE - 1) {
550 p ++;
551 length --;
552 size ++;
553 }
554 else {
555 p ++;
556 length --;
557 size = 0;
558 state = STATE_EQUAL_998;
559 }
560 break;
561 }
562 break; /* end of STATE_LOWER_998 */
563
564 case STATE_EQUAL_998:
565 switch (* p) {
566 case '\r':
567 case '\n':
568 p ++;
569 length --;
570 size = 0;
571 state = STATE_LOWER_72;
572 break;
573
574 case ' ':
575 case '\t':
576 r = mailimf_string_write(f, col, block_begin, p - block_begin);
577 if (r != MAILIMF_NO_ERROR)
578 return r;
579 r = mailimf_string_write(f, col, HEADER_FOLD,
580 sizeof(HEADER_FOLD) - 1);
581 if (r != MAILIMF_NO_ERROR)
582 return r;
583 p ++;
584 length --;
585 block_begin = p;
586 size = p - block_begin + * col;
587 state = STATE_LOWER_72;
588 break;
589
590 default:
591#ifdef CUT_AT_MAX_VALID_IMF_LINE
592 r = mailimf_string_write(f, col, block_begin, p - block_begin);
593 if (r != MAILIMF_NO_ERROR)
594 return r;
595 r = mailimf_string_write(f, col, HEADER_FOLD,
596 sizeof(HEADER_FOLD) - 1);
597 if (r != MAILIMF_NO_ERROR)
598 return r;
599 p ++;
600 length --;
601 block_begin = p;
602 size = p - block_begin + * col;
603 state = STATE_LOWER_72;
604#else
605 p ++;
606 length --;
607 size ++;
608#endif
609 break;
610 }
611 break; /* end of STATE_EQUAL_998 */
612 }
613 }
614
615 r = mailimf_string_write(f, col, block_begin, p - block_begin);
616 if (r != MAILIMF_NO_ERROR)
617 return r;
618
619 return MAILIMF_NO_ERROR;
620}
621#endif
622
623enum {
624 STATE_BEGIN,
625 STATE_WORD,
626 STATE_SPACE,
627};
628
629int mailimf_header_string_write(FILE * f, int * col,
630 const char * str, size_t length)
631{
632 int state;
633 const char * p;
634 const char * word_begin;
635 const char * word_end;
636 const char * next_word;
637 int first;
638
639 state = STATE_BEGIN;
640
641 p = str;
642 word_begin = p;
643 word_end = p;
644 next_word = p;
645 first = 1;
646
647 while (length > 0) {
648 switch (state) {
649 case STATE_BEGIN:
650 switch (* p) {
651 case '\r':
652 case '\n':
653 case ' ':
654 case '\t':
655 p ++;
656 length --;
657 break;
658
659 default:
660 word_begin = p;
661 state = STATE_WORD;
662 break;
663 }
664 break;
665
666 case STATE_SPACE:
667 switch (* p) {
668 case '\r':
669 case '\n':
670 case ' ':
671 case '\t':
672 p ++;
673 length --;
674 break;
675
676 default:
677 word_begin = p;
678 state = STATE_WORD;
679 break;
680 }
681 break;
682
683 case STATE_WORD:
684 switch (* p) {
685 case '\r':
686 case '\n':
687 case ' ':
688 case '\t':
689 if (p - word_begin + (* col) + 1 > MAX_MAIL_COL)
690 mailimf_string_write(f, col, HEADER_FOLD,
691 sizeof(HEADER_FOLD) - 1);
692 else {
693 if (!first)
694 mailimf_string_write(f, col, " ", 1);
695 }
696 first = 0;
697 mailimf_string_write(f, col, word_begin, p - word_begin);
698 state = STATE_SPACE;
699 break;
700
701 default:
702 if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) {
703 mailimf_string_write(f, col, word_begin, p - word_begin);
704 mailimf_string_write(f, col, HEADER_FOLD,
705 sizeof(HEADER_FOLD) - 1);
706 word_begin = p;
707 }
708 p ++;
709 length --;
710 break;
711 }
712 break;
713 }
714 }
715
716 if (state == STATE_WORD) {
717 if (p - word_begin + (* col) >= MAX_MAIL_COL)
718 mailimf_string_write(f, col, HEADER_FOLD,
719 sizeof(HEADER_FOLD) - 1);
720 else {
721 if (!first)
722 mailimf_string_write(f, col, " ", 1);
723 }
724 first = 0;
725 mailimf_string_write(f, col, word_begin, p - word_begin);
726 }
727
728 return MAILIMF_NO_ERROR;
729}
730
731int mailimf_envelope_fields_write(FILE * f, int * col,
732 struct mailimf_fields * fields)
733{
734 clistiter * cur;
735
736 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
737 cur = clist_next(cur)) {
738 int r;
739 struct mailimf_field * field;
740
741 field = clist_content(cur);
742 if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) {
743 r = mailimf_field_write(f, col, field);
744 if (r != MAILIMF_NO_ERROR)
745 return r;
746 }
747 }
748
749 return MAILIMF_NO_ERROR;
750}
751
752int mailimf_fields_write(FILE * f, int * col,
753 struct mailimf_fields * fields)
754{
755 clistiter * cur;
756
757 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
758 cur = clist_next(cur)) {
759 int r;
760
761 r = mailimf_field_write(f, col, clist_content(cur));
762 if (r != MAILIMF_NO_ERROR)
763 return r;
764 }
765
766 return MAILIMF_NO_ERROR;
767}
768
769#if 0
770int mailimf_unparsed_fields_write(FILE * f, int * col,
771 struct mailimf_unparsed_fields * fields)
772{
773 clistiter * cur;
774
775 for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) {
776 int r;
777
778 r = mailimf_optional_field_write(f, col, cur->data);
779 if (r != MAILIMF_NO_ERROR)
780 return r;
781 }
782
783 return MAILIMF_NO_ERROR;
784}
785#endif
786
787int mailimf_field_write(FILE * f, int * col,
788 struct mailimf_field * field)
789{
790 int r;
791
792 switch (field->fld_type) {
793 case MAILIMF_FIELD_RETURN_PATH:
794 r = mailimf_return_write(f, col, field->fld_data.fld_return_path);
795 break;
796 case MAILIMF_FIELD_RESENT_DATE:
797 r = mailimf_resent_date_write(f, col, field->fld_data.fld_resent_date);
798 break;
799 case MAILIMF_FIELD_RESENT_FROM:
800 r = mailimf_resent_from_write(f, col, field->fld_data.fld_resent_from);
801 break;
802 case MAILIMF_FIELD_RESENT_SENDER:
803 r = mailimf_resent_sender_write(f, col, field->fld_data.fld_resent_sender);
804 break;
805 case MAILIMF_FIELD_RESENT_TO:
806 r = mailimf_resent_to_write(f, col, field->fld_data.fld_resent_to);
807 break;
808 case MAILIMF_FIELD_RESENT_CC:
809 r = mailimf_resent_cc_write(f, col, field->fld_data.fld_resent_cc);
810 break;
811 case MAILIMF_FIELD_RESENT_BCC:
812 r = mailimf_resent_bcc_write(f, col, field->fld_data.fld_resent_bcc);
813 break;
814 case MAILIMF_FIELD_RESENT_MSG_ID:
815 r = mailimf_resent_msg_id_write(f, col, field->fld_data.fld_resent_msg_id);
816 break;
817 case MAILIMF_FIELD_ORIG_DATE:
818 r = mailimf_orig_date_write(f, col, field->fld_data.fld_orig_date);
819 break;
820 case MAILIMF_FIELD_FROM:
821 r = mailimf_from_write(f, col, field->fld_data.fld_from);
822 break;
823 case MAILIMF_FIELD_SENDER:
824 r = mailimf_sender_write(f, col, field->fld_data.fld_sender);
825 break;
826 case MAILIMF_FIELD_REPLY_TO:
827 r = mailimf_reply_to_write(f, col, field->fld_data.fld_reply_to);
828 break;
829 case MAILIMF_FIELD_TO:
830 r = mailimf_to_write(f, col, field->fld_data.fld_to);
831 break;
832 case MAILIMF_FIELD_CC:
833 r = mailimf_cc_write(f, col, field->fld_data.fld_cc);
834 break;
835 case MAILIMF_FIELD_BCC:
836 r = mailimf_bcc_write(f, col, field->fld_data.fld_bcc);
837 break;
838 case MAILIMF_FIELD_MESSAGE_ID:
839 r = mailimf_message_id_write(f, col, field->fld_data.fld_message_id);
840 break;
841 case MAILIMF_FIELD_IN_REPLY_TO:
842 r = mailimf_in_reply_to_write(f, col, field->fld_data.fld_in_reply_to);
843 break;
844 case MAILIMF_FIELD_REFERENCES:
845 r = mailimf_references_write(f, col, field->fld_data.fld_references);
846 break;
847 case MAILIMF_FIELD_SUBJECT:
848 r = mailimf_subject_write(f, col, field->fld_data.fld_subject);
849 break;
850 case MAILIMF_FIELD_COMMENTS:
851 r = mailimf_comments_write(f, col, field->fld_data.fld_comments);
852 break;
853 case MAILIMF_FIELD_KEYWORDS:
854 r = mailimf_keywords_write(f, col, field->fld_data.fld_keywords);
855 break;
856 case MAILIMF_FIELD_OPTIONAL_FIELD:
857 r = mailimf_optional_field_write(f, col, field->fld_data.fld_optional_field);
858 break;
859 default:
860 r = MAILIMF_ERROR_INVAL;
861 break;
862 }
863
864 if (r != MAILIMF_NO_ERROR)
865 return r;
866
867 return MAILIMF_NO_ERROR;
868}
869
870
871static int mailimf_orig_date_write(FILE * f, int * col,
872 struct mailimf_orig_date * date)
873{
874 int r;
875
876 r = mailimf_string_write(f, col, "Date: ", 6);
877 if (r != MAILIMF_NO_ERROR)
878 return r;
879
880 r = mailimf_date_time_write(f, col, date->dt_date_time);
881 if (r != MAILIMF_NO_ERROR)
882 return r;
883
884 r = mailimf_string_write(f, col, "\r\n", 2);
885 if (r != MAILIMF_NO_ERROR)
886 return r;
887#if 0
888 * col = 0;
889#endif
890
891 return MAILIMF_NO_ERROR;
892}
893
894#define MAX_DATE_STR 256
895
896/* 0 = Sunday */
897/* y > 1752 */
898
899static int dayofweek(int year, int month, int day)
900{
901 static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
902
903 year -= month < 3;
904
905 return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7;
906}
907
908static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
909 "Fri", "Sat"};
910static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
911 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
912
913static int mailimf_date_time_write(FILE * f, int * col,
914 struct mailimf_date_time * date_time)
915{
916 int r;
917 char date_str[MAX_DATE_STR];
918#if 0
919 struct tm tmval;
920 time_t timeval;
921#endif
922 int wday;
923
924#if 0
925 tmval.tm_sec = date_time->sec;
926 tmval.tm_min = date_time->min;
927 tmval.tm_hour = date_time->hour;
928 tmval.tm_sec = date_time->sec;
929 tmval.tm_mday = date_time->day;
930 tmval.tm_mon = date_time->month - 1;
931 tmval.tm_year = date_time->year - 1900;
932 tmval.tm_isdst = 1;
933
934 timeval = mktime(&tmval);
935
936 localtime_r(&timeval, &tmval);
937#endif
938
939 wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day);
940
941 snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i",
942 week_of_day_str[wday], date_time->dt_day,
943 month_str[date_time->dt_month - 1],
944 date_time->dt_year, date_time->dt_hour,
945 date_time->dt_min, date_time->dt_sec,
946 date_time->dt_zone);
947
948 r = mailimf_string_write(f, col, date_str, strlen(date_str));
949
950 if (r != MAILIMF_NO_ERROR)
951 return r;
952
953 return MAILIMF_NO_ERROR;
954}
955
956static int mailimf_from_write(FILE * f, int * col,
957 struct mailimf_from * from)
958{
959 int r;
960
961 r = mailimf_string_write(f, col, "From: ", 6);
962 if (r != MAILIMF_NO_ERROR)
963 return r;
964
965 r = mailimf_mailbox_list_write(f, col, from->frm_mb_list);
966 if (r != MAILIMF_NO_ERROR)
967 return r;
968
969 r = mailimf_string_write(f, col, "\r\n", 2);
970 if (r != MAILIMF_NO_ERROR)
971 return r;
972#if 0
973 * col = 0;
974#endif
975
976 return MAILIMF_NO_ERROR;
977}
978
979static int mailimf_sender_write(FILE * f, int * col,
980 struct mailimf_sender * sender)
981{
982 int r;
983
984 r = mailimf_string_write(f, col, "Sender: ", 8);
985 if (r != MAILIMF_NO_ERROR)
986 return r;
987
988 r = mailimf_mailbox_write(f, col, sender->snd_mb);
989 if (r != MAILIMF_NO_ERROR)
990 return r;
991
992 r = mailimf_string_write(f, col, "\r\n", 2);
993 if (r != MAILIMF_NO_ERROR)
994 return r;
995#if 0
996 * col = 0;
997#endif
998
999 return MAILIMF_NO_ERROR;
1000}
1001
1002static int mailimf_reply_to_write(FILE * f, int * col,
1003 struct mailimf_reply_to * reply_to)
1004{
1005 int r;
1006
1007 r = mailimf_string_write(f, col, "Reply-To: ", 10);
1008 if (r != MAILIMF_NO_ERROR)
1009 return r;
1010
1011 r = mailimf_address_list_write(f, col, reply_to->rt_addr_list);
1012 if (r != MAILIMF_NO_ERROR)
1013 return r;
1014
1015 r = mailimf_string_write(f, col, "\r\n", 2);
1016 if (r != MAILIMF_NO_ERROR)
1017 return r;
1018#if 0
1019 * col = 0;
1020#endif
1021
1022 return MAILIMF_NO_ERROR;
1023}
1024
1025
1026static int mailimf_to_write(FILE * f, int * col,
1027 struct mailimf_to * to)
1028{
1029 int r;
1030
1031 r = mailimf_string_write(f, col, "To: ", 4);
1032 if (r != MAILIMF_NO_ERROR)
1033 return r;
1034
1035 r = mailimf_address_list_write(f, col, to->to_addr_list);
1036 if (r != MAILIMF_NO_ERROR)
1037 return r;
1038
1039 r = mailimf_string_write(f, col, "\r\n", 2);
1040 if (r != MAILIMF_NO_ERROR)
1041 return r;
1042#if 0
1043 * col = 0;
1044#endif
1045
1046 return MAILIMF_NO_ERROR;
1047}
1048
1049
1050static int mailimf_cc_write(FILE * f, int * col,
1051 struct mailimf_cc * cc)
1052{
1053 int r;
1054
1055 r = mailimf_string_write(f, col, "Cc: ", 4);
1056 if (r != MAILIMF_NO_ERROR)
1057 return r;
1058
1059 r = mailimf_address_list_write(f, col, cc->cc_addr_list);
1060 if (r != MAILIMF_NO_ERROR)
1061 return r;
1062
1063 r = mailimf_string_write(f, col, "\r\n", 2);
1064 if (r != MAILIMF_NO_ERROR)
1065 return r;
1066#if 0
1067 * col = 0;
1068#endif
1069
1070 return MAILIMF_NO_ERROR;
1071}
1072
1073
1074static int mailimf_bcc_write(FILE * f, int * col,
1075 struct mailimf_bcc * bcc)
1076{
1077 int r;
1078
1079 r = mailimf_string_write(f, col, "Bcc: ", 5);
1080 if (r != MAILIMF_NO_ERROR)
1081 return r;
1082
1083 if (bcc->bcc_addr_list != NULL) {
1084 r = mailimf_address_list_write(f, col, bcc->bcc_addr_list);
1085 if (r != MAILIMF_NO_ERROR)
1086 return r;
1087 }
1088
1089 r = mailimf_string_write(f, col, "\r\n", 2);
1090 if (r != MAILIMF_NO_ERROR)
1091 return r;
1092#if 0
1093 * col = 0;
1094#endif
1095
1096 return MAILIMF_NO_ERROR;
1097}
1098
1099
1100static int mailimf_message_id_write(FILE * f, int * col,
1101 struct mailimf_message_id * message_id)
1102{
1103 int r;
1104
1105 r = mailimf_string_write(f, col, "Message-ID: ", 12);
1106 if (r != MAILIMF_NO_ERROR)
1107 return r;
1108
1109 r = mailimf_string_write(f, col, "<", 1);
1110 if (r != MAILIMF_NO_ERROR)
1111 return r;
1112
1113 r = mailimf_string_write(f, col,
1114 message_id->mid_value,
1115 strlen(message_id->mid_value));
1116 if (r != MAILIMF_NO_ERROR)
1117 return r;
1118
1119 r = mailimf_string_write(f, col, ">", 1);
1120 if (r != MAILIMF_NO_ERROR)
1121 return r;
1122
1123 r = mailimf_string_write(f, col, "\r\n", 2);
1124 if (r != MAILIMF_NO_ERROR)
1125 return r;
1126#if 0
1127 * col = 0;
1128#endif
1129
1130 return MAILIMF_NO_ERROR;
1131}
1132
1133
1134static int mailimf_msg_id_list_write(FILE * f, int * col, clist * mid_list)
1135{
1136 clistiter * cur;
1137 int r;
1138 int first;
1139
1140 first = TRUE;
1141
1142 for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) {
1143 char * msgid;
1144 size_t len;
1145
1146 msgid = clist_content(cur);
1147 len = strlen(msgid);
1148
1149 /*
1150 XXX - if this is the first message ID, don't fold.
1151 This is a workaround for a bug of old versions of INN.
1152 */
1153 if (!first) {
1154 if (* col > 1) {
1155
1156 if (* col + len >= MAX_MAIL_COL) {
1157 r = mailimf_string_write(f, col, "\r\n ", 3);
1158 if (r != MAILIMF_NO_ERROR)
1159 return r;
1160#if 0
1161 * col = 1;
1162#endif
1163 first = TRUE;
1164 }
1165 }
1166 }
1167
1168 if (!first) {
1169 r = mailimf_string_write(f, col, " ", 1);
1170 if (r != MAILIMF_NO_ERROR)
1171 return r;
1172 }
1173 else {
1174 first = FALSE;
1175 }
1176
1177 r = mailimf_string_write(f, col, "<", 1);
1178 if (r != MAILIMF_NO_ERROR)
1179 return r;
1180
1181 r = mailimf_string_write(f, col, msgid, len);
1182 if (r != MAILIMF_NO_ERROR)
1183 return r;
1184
1185 r = mailimf_string_write(f, col, ">", 1);
1186 if (r != MAILIMF_NO_ERROR)
1187 return r;
1188 }
1189
1190 return MAILIMF_NO_ERROR;
1191}
1192
1193
1194static int mailimf_in_reply_to_write(FILE * f, int * col,
1195 struct mailimf_in_reply_to * in_reply_to)
1196{
1197 int r;
1198
1199 r = mailimf_string_write(f, col, "In-Reply-To: ", 13);
1200 if (r != MAILIMF_NO_ERROR)
1201 return r;
1202
1203 r = mailimf_msg_id_list_write(f, col, in_reply_to->mid_list);
1204 if (r != MAILIMF_NO_ERROR)
1205 return r;
1206
1207 r = mailimf_string_write(f, col, "\r\n", 2);
1208 if (r != MAILIMF_NO_ERROR)
1209 return r;
1210#if 0
1211 * col = 0;
1212#endif
1213
1214 return MAILIMF_NO_ERROR;
1215}
1216
1217
1218static int mailimf_references_write(FILE * f, int * col,
1219 struct mailimf_references * references)
1220{
1221 int r;
1222
1223 r = mailimf_string_write(f, col, "References: ", 12);
1224 if (r != MAILIMF_NO_ERROR)
1225 return r;
1226
1227 r = mailimf_msg_id_list_write(f, col, references->mid_list);
1228 if (r != MAILIMF_NO_ERROR)
1229 return r;
1230
1231 r = mailimf_string_write(f, col, "\r\n", 2);
1232 if (r != MAILIMF_NO_ERROR)
1233 return r;
1234#if 0
1235 * col = 0;
1236#endif
1237
1238 return MAILIMF_NO_ERROR;
1239}
1240
1241
1242
1243static int mailimf_subject_write(FILE * f, int * col,
1244 struct mailimf_subject * subject)
1245{
1246 int r;
1247
1248 r = mailimf_string_write(f, col, "Subject: ", 9);
1249 if (r != MAILIMF_NO_ERROR)
1250 return r;
1251
1252 r = mailimf_header_string_write(f, col,
1253 subject->sbj_value, strlen(subject->sbj_value));
1254 if (r != MAILIMF_NO_ERROR)
1255 return r;
1256
1257 r = mailimf_string_write(f, col, "\r\n", 2);
1258 if (r != MAILIMF_NO_ERROR)
1259 return r;
1260#if 0
1261 * col = 0;
1262#endif
1263
1264 return MAILIMF_NO_ERROR;
1265}
1266
1267int mailimf_address_list_write(FILE * f, int * col,
1268 struct mailimf_address_list * addr_list)
1269{
1270 clistiter * cur;
1271 int r;
1272 int first;
1273
1274 first = TRUE;
1275
1276 for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
1277 cur = clist_next(cur)) {
1278 struct mailimf_address * addr;
1279
1280 addr = clist_content(cur);
1281
1282 if (!first) {
1283 r = mailimf_string_write(f, col, ", ", 2);
1284 if (r != MAILIMF_NO_ERROR)
1285 return r;
1286 }
1287 else {
1288 first = FALSE;
1289 }
1290
1291 r = mailimf_address_write(f, col, addr);
1292 if (r != MAILIMF_NO_ERROR)
1293 return r;
1294 }
1295
1296 return MAILIMF_NO_ERROR;
1297}
1298
1299
1300static int mailimf_address_write(FILE * f, int * col,
1301 struct mailimf_address * addr)
1302{
1303 int r;
1304
1305 switch(addr->ad_type) {
1306 case MAILIMF_ADDRESS_MAILBOX:
1307 r = mailimf_mailbox_write(f, col, addr->ad_data.ad_mailbox);
1308 if (r != MAILIMF_NO_ERROR)
1309 return r;
1310
1311 break;
1312
1313 case MAILIMF_ADDRESS_GROUP:
1314 r = mailimf_group_write(f, col, addr->ad_data.ad_group);
1315 if (r != MAILIMF_NO_ERROR)
1316 return r;
1317
1318 break;
1319 }
1320
1321 return MAILIMF_NO_ERROR;
1322}
1323
1324
1325static int mailimf_group_write(FILE * f, int * col,
1326 struct mailimf_group * group)
1327{
1328 int r;
1329
1330 r = mailimf_header_string_write(f, col, group->grp_display_name,
1331 strlen(group->grp_display_name));
1332 if (r != MAILIMF_NO_ERROR)
1333 return r;
1334
1335 r = mailimf_string_write(f, col, ": ", 2);
1336 if (r != MAILIMF_NO_ERROR)
1337 return r;
1338
1339 if (group->grp_mb_list != NULL) {
1340 r = mailimf_mailbox_list_write(f, col, group->grp_mb_list);
1341 if (r != MAILIMF_NO_ERROR)
1342 return r;
1343 }
1344
1345 r = mailimf_string_write(f, col, ";", 1);
1346 if (r != MAILIMF_NO_ERROR)
1347 return r;
1348
1349 return MAILIMF_NO_ERROR;
1350}
1351
1352
1353int mailimf_mailbox_list_write(FILE * f, int * col,
1354 struct mailimf_mailbox_list * mb_list)
1355{
1356 clistiter * cur;
1357 int r;
1358 int first;
1359
1360 first = TRUE;
1361
1362 for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
1363 cur = clist_next(cur)) {
1364 struct mailimf_mailbox * mb;
1365
1366 mb = clist_content(cur);
1367
1368 if (!first) {
1369 r = mailimf_string_write(f, col, ", ", 2);
1370 if (r != MAILIMF_NO_ERROR)
1371 return r;
1372 }
1373 else {
1374 first = FALSE;
1375 }
1376
1377 r = mailimf_mailbox_write(f, col, mb);
1378 if (r != MAILIMF_NO_ERROR)
1379 return r;
1380 }
1381
1382 return MAILIMF_NO_ERROR;
1383}
1384
1385
1386int mailimf_quoted_string_write(FILE * f, int * col,
1387 const char * string, size_t len)
1388{
1389 int r;
1390 size_t i;
1391
1392 fputc('\"', f);
1393 for(i = 0 ; i < len ; i ++) {
1394 switch (string[i]) {
1395 case '\\':
1396 case '\"':
1397 r = fputc('\\', f);
1398 if (r < 0)
1399 return MAILIMF_ERROR_FILE;
1400 r = fputc(string[i], f);
1401 if (r < 0)
1402 return MAILIMF_ERROR_FILE;
1403 (* col) += 2;
1404 break;
1405
1406 default:
1407 r = fputc(string[i], f);
1408 if (r < 0)
1409 return MAILIMF_ERROR_FILE;
1410 (* col) ++;
1411 break;
1412 }
1413 }
1414 fputc('\"', f);
1415
1416 return MAILIMF_NO_ERROR;
1417}
1418
1419
1420/*
1421static int
1422atext = ALPHA / DIGIT / ; Any character except controls,
1423 "!" / "#" / ; SP, and specials.
1424 "$" / "%" / ; Used for atoms
1425 "&" / "'" /
1426 "*" / "+" /
1427 "-" / "/" /
1428 "=" / "?" /
1429 "^" / "_" /
1430 "`" / "{" /
1431 "|" / "}" /
1432 "~"
1433*/
1434
1435static int is_atext(const char * s)
1436{
1437 const char * p;
1438
1439 for(p = s ; * p != 0 ; p ++) {
1440 if (isalpha((unsigned char) * p))
1441 continue;
1442 if (isdigit((unsigned char) * p))
1443 continue;
1444 switch (*p) {
1445 case ' ':
1446 case '\t':
1447 case '!':
1448 case '#':
1449 case '$':
1450 case '%':
1451 case '&':
1452 case '\'':
1453 case '*':
1454 case '+':
1455 case '-':
1456 case '/':
1457 case '=':
1458 case '?':
1459 case '^':
1460 case '_':
1461 case '`':
1462 case '{':
1463 case '|':
1464 case '}':
1465 case '~':
1466 break;
1467 default:
1468 return 0;
1469 }
1470 }
1471
1472 return 1;
1473}
1474
1475static int mailimf_mailbox_write(FILE * f, int * col,
1476 struct mailimf_mailbox * mb)
1477{
1478 int r;
1479 int do_fold;
1480
1481#if 0
1482 if (* col > 1) {
1483
1484 if (mb->mb_display_name != NULL) {
1485 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1486 r = mailimf_string_write(f, col, "\r\n ", 3);
1487 if (r != MAILIMF_NO_ERROR)
1488 return r;
1489#if 0
1490 * col = 1;
1491#endif
1492 }
1493 }
1494 }
1495#endif
1496
1497 if (mb->mb_display_name) {
1498
1499 if (is_atext(mb->mb_display_name)) {
1500 r = mailimf_header_string_write(f, col, mb->mb_display_name,
1501 strlen(mb->mb_display_name));
1502 if (r != MAILIMF_NO_ERROR)
1503 return r;
1504 }
1505 else {
1506 if (mb->mb_display_name != NULL) {
1507 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1508 r = mailimf_string_write(f, col, "\r\n ", 3);
1509 if (r != MAILIMF_NO_ERROR)
1510 return r;
1511 }
1512 }
1513
1514 if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2)
1515 return MAILIMF_ERROR_INVAL;
1516
1517 r = mailimf_quoted_string_write(f, col, mb->mb_display_name,
1518 strlen(mb->mb_display_name));
1519 if (r != MAILIMF_NO_ERROR)
1520 return r;
1521 }
1522
1523 do_fold = 0;
1524 if (* col > 1) {
1525
1526 if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) {
1527 r = mailimf_string_write(f, col, "\r\n ", 3);
1528 if (r != MAILIMF_NO_ERROR)
1529 return r;
1530#if 0
1531 * col = 1;
1532#endif
1533 do_fold = 1;
1534 }
1535 }
1536
1537 if (do_fold)
1538 r = mailimf_string_write(f, col, "<", 1);
1539 else
1540 r = mailimf_string_write(f, col, " <", 2);
1541 if (r != MAILIMF_NO_ERROR)
1542 return r;
1543
1544 r = mailimf_string_write(f, col, mb->mb_addr_spec,
1545 strlen(mb->mb_addr_spec));
1546 if (r != MAILIMF_NO_ERROR)
1547 return r;
1548
1549 r = mailimf_string_write(f, col, ">", 1);
1550 if (r != MAILIMF_NO_ERROR)
1551 return r;
1552 }
1553 else {
1554 if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) {
1555 r = mailimf_string_write(f, col, "\r\n ", 3);
1556 if (r != MAILIMF_NO_ERROR)
1557 return r;
1558 }
1559
1560 r = mailimf_string_write(f, col,
1561 mb->mb_addr_spec, strlen(mb->mb_addr_spec));
1562 if (r != MAILIMF_NO_ERROR)
1563 return r;
1564 }
1565
1566
1567 return MAILIMF_NO_ERROR;
1568}
1569
1570static int mailimf_comments_write(FILE * f, int * col,
1571 struct mailimf_comments * comments)
1572{
1573 int r;
1574
1575 r = mailimf_string_write(f, col, "Comments: ", 10);
1576 if (r != MAILIMF_NO_ERROR)
1577 return r;
1578
1579 r = mailimf_header_string_write(f, col,
1580 comments->cm_value, strlen(comments->cm_value));
1581 if (r != MAILIMF_NO_ERROR)
1582 return r;
1583
1584 r = mailimf_string_write(f, col, "\r\n", 2);
1585 if (r != MAILIMF_NO_ERROR)
1586 return r;
1587#if 0
1588 * col = 0;
1589#endif
1590
1591 return MAILIMF_NO_ERROR;
1592}
1593
1594static int mailimf_optional_field_write(FILE * f, int * col,
1595 struct mailimf_optional_field * field)
1596{
1597 int r;
1598
1599 if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE)
1600 return MAILIMF_ERROR_INVAL;
1601
1602 r = mailimf_string_write(f, col, field->fld_name, strlen(field->fld_name));
1603 if (r != MAILIMF_NO_ERROR)
1604 return r;
1605
1606 r = mailimf_string_write(f, col, ": ", 2);
1607 if (r != MAILIMF_NO_ERROR)
1608 return r;
1609
1610 r = mailimf_header_string_write(f, col, field->fld_value,
1611 strlen(field->fld_value));
1612 if (r != MAILIMF_NO_ERROR)
1613 return r;
1614
1615#if 0
1616 /* XXX parsing debug */
1617 mailimf_string_write(f, col, " (X)", 4);
1618#endif
1619
1620 r = mailimf_string_write(f, col, "\r\n", 2);
1621 if (r != MAILIMF_NO_ERROR)
1622 return r;
1623#if 0
1624 * col = 0;
1625#endif
1626
1627 return MAILIMF_NO_ERROR;
1628}
1629
1630static int mailimf_keywords_write(FILE * f, int * col,
1631 struct mailimf_keywords * keywords)
1632{
1633 int r;
1634 clistiter * cur;
1635 int first;
1636
1637 r = mailimf_string_write(f, col, "Keywords: ", 10);
1638 if (r != MAILIMF_NO_ERROR)
1639 return r;
1640
1641 first = TRUE;
1642
1643 for(cur = clist_begin(keywords->kw_list) ; cur != NULL ;
1644 cur = clist_next(cur)) {
1645 char * keyword;
1646 size_t len;
1647
1648 keyword = clist_content(cur);
1649 len = strlen(keyword);
1650
1651 if (!first) {
1652 r = mailimf_string_write(f, col, ", ", 2);
1653 if (r != MAILIMF_NO_ERROR)
1654 return r;
1655 }
1656 else {
1657 first = FALSE;
1658 }
1659
1660#if 0
1661 if (* col > 1) {
1662
1663 if (* col + len >= MAX_MAIL_COL) {
1664 r = mailimf_string_write(f, col, "\r\n ", 3);
1665 if (r != MAILIMF_NO_ERROR)
1666 return r;
1667#if 0
1668 * col = 1;
1669#endif
1670 }
1671 }
1672#endif
1673
1674 r = mailimf_header_string_write(f, col, keyword, len);
1675 if (r != MAILIMF_NO_ERROR)
1676 return r;
1677 }
1678
1679 r = mailimf_string_write(f, col, "\r\n", 2);
1680 if (r != MAILIMF_NO_ERROR)
1681 return r;
1682#if 0
1683 * col = 0;
1684#endif
1685
1686 return MAILIMF_NO_ERROR;
1687}
1688
1689#if 0
1690static int mailimf_delivering_info_write(FILE * f, int * col,
1691 struct mailimf_delivering_info * info)
1692{
1693 clistiter * cur;
1694 int r;
1695
1696 for(cur = clist_begin(info->received_fields) ;
1697 cur != NULL ; cur = cur->next) {
1698 struct mailimf_trace_resent_fields * field;
1699
1700 field = cur->data;
1701
1702 r = mailimf_trace_resent_fields_write(f, col, field);
1703 if (r != MAILIMF_NO_ERROR)
1704 return r;
1705 }
1706
1707 return MAILIMF_NO_ERROR;
1708}
1709
1710
1711static int
1712mailimf_trace_resent_fields_write(FILE * f, int * col,
1713 struct mailimf_trace_resent_fields * field)
1714{
1715 int r;
1716
1717 if (field->return_path != NULL) {
1718 r = mailimf_return_write(f, col, field->return_path);
1719 if (r != MAILIMF_NO_ERROR)
1720 return r;
1721 }
1722
1723 if (field->resent_fields != NULL) {
1724 r = mailimf_resent_fields_write(f, col, field->resent_fields);
1725 if (r != MAILIMF_NO_ERROR)
1726 return r;
1727 }
1728
1729 return MAILIMF_NO_ERROR;
1730}
1731#endif
1732
1733static int mailimf_return_write(FILE * f, int * col,
1734 struct mailimf_return * return_path)
1735{
1736 int r;
1737
1738 r = mailimf_string_write(f, col, "Return-Path: ", 13);
1739 if (r != MAILIMF_NO_ERROR)
1740 return r;
1741
1742 r = mailimf_path_write(f, col, return_path->ret_path);
1743 if (r != MAILIMF_NO_ERROR)
1744 return r;
1745
1746 r = mailimf_string_write(f, col, "\r\n", 2);
1747 if (r != MAILIMF_NO_ERROR)
1748 return r;
1749#if 0
1750 * col = 0;
1751#endif
1752
1753 return MAILIMF_NO_ERROR;
1754}
1755
1756static int mailimf_path_write(FILE * f, int * col,
1757 struct mailimf_path * path)
1758{
1759 int r;
1760
1761 r = mailimf_string_write(f, col, "<", 1);
1762 if (r != MAILIMF_NO_ERROR)
1763 return r;
1764
1765 r = mailimf_string_write(f, col, path->pt_addr_spec,
1766 strlen(path->pt_addr_spec));
1767 if (r != MAILIMF_NO_ERROR)
1768 return r;
1769
1770 r = mailimf_string_write(f, col, ">", 1);
1771 if (r != MAILIMF_NO_ERROR)
1772 return r;
1773
1774 return MAILIMF_NO_ERROR;
1775}
1776
1777#if 0
1778static int mailimf_resent_fields_write(FILE * f, int * col,
1779 struct mailimf_resent_fields_list *
1780 resent_fields)
1781{
1782 clistiter * cur;
1783 int r;
1784
1785 for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) {
1786 struct mailimf_resent_field * field;
1787
1788 field = cur->data;
1789
1790 r = mailimf_resent_field_write(f, col, field);
1791 if (r != MAILIMF_NO_ERROR)
1792 return r;
1793 }
1794
1795 return MAILIMF_NO_ERROR;
1796}
1797
1798
1799
1800static int mailimf_resent_field_write(FILE * f, int * col,
1801 struct mailimf_resent_field *
1802 resent_field)
1803{
1804 int r;
1805
1806 switch (resent_field->type) {
1807 case MAILIMF_RESENT_FIELD_DATE:
1808 r = mailimf_resent_date_write(f, col, resent_field->resent_date);
1809 break;
1810
1811 case MAILIMF_RESENT_FIELD_FROM:
1812 r = mailimf_resent_from_write(f, col, resent_field->resent_from);
1813 break;
1814
1815 case MAILIMF_RESENT_FIELD_SENDER:
1816 r = mailimf_resent_sender_write(f, col, resent_field->resent_sender);
1817 break;
1818
1819 case MAILIMF_RESENT_FIELD_TO:
1820 r = mailimf_resent_to_write(f, col, resent_field->resent_to);
1821 break;
1822
1823 case MAILIMF_RESENT_FIELD_CC:
1824 r = mailimf_resent_cc_write(f, col, resent_field->resent_cc);
1825 break;
1826
1827 case MAILIMF_RESENT_FIELD_BCC:
1828 r = mailimf_resent_bcc_write(f, col, resent_field->resent_bcc);
1829 break;
1830
1831 case MAILIMF_RESENT_FIELD_MSG_ID:
1832 r = mailimf_resent_msg_id_write(f, col, resent_field->resent_msg_id);
1833 break;
1834 default:
1835 r = MAILIMF_ERROR_INVAL;
1836 break;
1837 }
1838
1839
1840 if (r != MAILIMF_NO_ERROR)
1841 return r;
1842
1843 return MAILIMF_NO_ERROR;
1844}
1845#endif
1846
1847static int mailimf_resent_date_write(FILE * f, int * col,
1848 struct mailimf_orig_date * date)
1849{
1850 int r;
1851
1852 r = mailimf_string_write(f, col, "Resent-Date: ", 13);
1853 if (r != MAILIMF_NO_ERROR)
1854 return r;
1855
1856 r = mailimf_date_time_write(f, col, date->dt_date_time);
1857 if (r != MAILIMF_NO_ERROR)
1858 return r;
1859
1860 r = mailimf_string_write(f, col, "\r\n", 2);
1861 if (r != MAILIMF_NO_ERROR)
1862 return r;
1863#if 0
1864 * col = 0;
1865#endif
1866
1867 return MAILIMF_NO_ERROR;
1868}
1869
1870static int mailimf_resent_from_write(FILE * f, int * col,
1871 struct mailimf_from * from)
1872{
1873 int r;
1874
1875 r = mailimf_string_write(f, col, "Resent-From: ", 13);
1876 if (r != MAILIMF_NO_ERROR)
1877 return r;
1878
1879 r = mailimf_mailbox_list_write(f, col, from->frm_mb_list);
1880 if (r != MAILIMF_NO_ERROR)
1881 return r;
1882
1883 r = mailimf_string_write(f, col, "\r\n", 2);
1884 if (r != MAILIMF_NO_ERROR)
1885 return r;
1886#if 0
1887 * col = 0;
1888#endif
1889
1890 return MAILIMF_NO_ERROR;
1891}
1892
1893static int mailimf_resent_sender_write(FILE * f, int * col,
1894 struct mailimf_sender * sender)
1895{
1896 int r;
1897
1898 r = mailimf_string_write(f, col, "Resent-Sender: ", 15);
1899 if (r != MAILIMF_NO_ERROR)
1900 return r;
1901
1902 r = mailimf_mailbox_write(f, col, sender->snd_mb);
1903 if (r != MAILIMF_NO_ERROR)
1904 return r;
1905
1906 r = mailimf_string_write(f, col, "\r\n", 2);
1907 if (r != MAILIMF_NO_ERROR)
1908 return r;
1909#if 0
1910 * col = 0;
1911#endif
1912
1913 return MAILIMF_NO_ERROR;
1914}
1915
1916static int mailimf_resent_to_write(FILE * f, int * col,
1917 struct mailimf_to * to)
1918{
1919 int r;
1920
1921 r = mailimf_string_write(f, col, "Resent-To: ", 11);
1922 if (r != MAILIMF_NO_ERROR)
1923 return r;
1924
1925 r = mailimf_address_list_write(f, col, to->to_addr_list);
1926 if (r != MAILIMF_NO_ERROR)
1927 return r;
1928
1929 r = mailimf_string_write(f, col, "\r\n", 2);
1930 if (r != MAILIMF_NO_ERROR)
1931 return r;
1932#if 0
1933 * col = 0;
1934#endif
1935
1936 return MAILIMF_NO_ERROR;
1937}
1938
1939
1940static int mailimf_resent_cc_write(FILE * f, int * col,
1941 struct mailimf_cc * cc)
1942{
1943 int r;
1944
1945 r = mailimf_string_write(f, col, "Resent-Cc: ", 11);
1946 if (r != MAILIMF_NO_ERROR)
1947 return r;
1948
1949 r = mailimf_address_list_write(f, col, cc->cc_addr_list);
1950 if (r != MAILIMF_NO_ERROR)
1951 return r;
1952
1953 r = mailimf_string_write(f, col, "\r\n", 2);
1954 if (r != MAILIMF_NO_ERROR)
1955 return r;
1956#if 0
1957 * col = 0;
1958#endif
1959
1960 return MAILIMF_NO_ERROR;
1961}
1962
1963
1964static int mailimf_resent_bcc_write(FILE * f, int * col,
1965 struct mailimf_bcc * bcc)
1966{
1967 int r;
1968
1969 r = mailimf_string_write(f, col, "Resent-Bcc: ", 12);
1970 if (r != MAILIMF_NO_ERROR)
1971 return r;
1972
1973 if (bcc->bcc_addr_list != NULL) {
1974 r = mailimf_address_list_write(f, col, bcc->bcc_addr_list);
1975 if (r != MAILIMF_NO_ERROR)
1976 return r;
1977 }
1978
1979 r = mailimf_string_write(f, col, "\r\n", 2);
1980 if (r != MAILIMF_NO_ERROR)
1981 return r;
1982#if 0
1983 * col = 0;
1984#endif
1985
1986 return MAILIMF_NO_ERROR;
1987}
1988
1989
1990static int
1991mailimf_resent_msg_id_write(FILE * f, int * col,
1992 struct mailimf_message_id * message_id)
1993{
1994 int r;
1995
1996 r = mailimf_string_write(f, col, "Resent-Message-ID: ", 19);
1997 if (r != MAILIMF_NO_ERROR)
1998 return r;
1999
2000 r = mailimf_string_write(f, col, "<", 1);
2001 if (r != MAILIMF_NO_ERROR)
2002 return r;
2003
2004 r = mailimf_string_write(f, col,
2005 message_id->mid_value, strlen(message_id->mid_value));
2006 if (r != MAILIMF_NO_ERROR)
2007 return r;
2008
2009 r = mailimf_string_write(f, col, ">", 1);
2010 if (r != MAILIMF_NO_ERROR)
2011 return r;
2012
2013 r = mailimf_string_write(f, col, "\r\n", 2);
2014 if (r != MAILIMF_NO_ERROR)
2015 return r;
2016#if 0
2017 * col = 0;
2018#endif
2019
2020 return MAILIMF_NO_ERROR;
2021}
diff --git a/libetpan/src/low-level/imf/mailimf_write.h b/libetpan/src/low-level/imf/mailimf_write.h
new file mode 100644
index 0000000..a3441dd
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write.h
@@ -0,0 +1,134 @@
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 MAILIMF_WRITE_H
37
38#define MAILIMF_WRITE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <stdio.h>
45#include <libetpan/mailimf_types.h>
46
47/*
48 mailimf_string_write writes a string to a given stream
49
50 @param f is the stream
51 @param col (* col) is the column number where we will start to
52 write the text, the ending column will be stored in (* col)
53 @param str is the string to write
54*/
55
56int mailimf_string_write(FILE * f, int * col,
57 const char * str, size_t length);
58
59
60/*
61 mailimf_fields_write writes the fields to a given stream
62
63 @param f is the stream
64 @param col (* col) is the column number where we will start to
65 write the text, the ending column will be stored in (* col)
66 @param fields is the fields to write
67*/
68
69int mailimf_fields_write(FILE * f, int * col,
70 struct mailimf_fields * fields);
71
72
73/*
74 mailimf_envelope_fields_write writes only some fields to a given stream
75
76 @param f is the stream
77 @param col (* col) is the column number where we will start to
78 write the text, the ending column will be stored in (* col)
79 @param fields is the fields to write
80*/
81
82int mailimf_envelope_fields_write(FILE * f, int * col,
83 struct mailimf_fields * fields);
84
85
86/*
87 mailimf_field_write writes a field to a given stream
88
89 @param f is the stream
90 @param col (* col) is the column number where we will start to
91 write the text, the ending column will be stored in (* col)
92 @param field is the field to write
93*/
94
95int mailimf_field_write(FILE * f, int * col,
96 struct mailimf_field * field);
97
98/*
99 mailimf_quoted_string_write writes a string that is quoted
100 to a given stream
101
102 @param f is the stream
103 @param col (* col) is the column number where we will start to
104 write the text, the ending column will be stored in (* col)
105 @param string is the string to quote and write
106*/
107
108int mailimf_quoted_string_write(FILE * f, int * col,
109 const char * string, size_t len);
110
111int mailimf_address_list_write(FILE * f, int * col,
112 struct mailimf_address_list * addr_list);
113
114int mailimf_mailbox_list_write(FILE * f, int * col,
115 struct mailimf_mailbox_list * mb_list);
116
117/*
118 mailimf_header_string_write writes a header value and fold the header
119 if needed.
120
121 @param f is the stream
122 @param col (* col) is the column number where we will start to
123 write the text, the ending column will be stored in (* col)
124 @param str is the string to write
125*/
126
127int mailimf_header_string_write(FILE * f, int * col,
128 const char * str, size_t length);
129
130#ifdef __cplusplus
131}
132#endif
133
134#endif
diff --git a/libetpan/src/low-level/imf/mailimf_write_file.c b/libetpan/src/low-level/imf/mailimf_write_file.c
new file mode 100644
index 0000000..a1f7187
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_file.c
@@ -0,0 +1,149 @@
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 "mailimf_write_file.h"
37#include "mailimf_write_generic.h"
38
39static int do_write(void * data, const char * str, size_t length)
40{
41 FILE * f;
42
43 f = data;
44
45 return fwrite(str, 1, length, f);
46}
47
48int mailimf_string_write_file(FILE * f, int * col,
49 const char * str, size_t length)
50{
51 return mailimf_string_write_driver(do_write, f, col, str, length);
52}
53
54int mailimf_fields_write_file(FILE * f, int * col,
55 struct mailimf_fields * fields)
56{
57 return mailimf_fields_write_driver(do_write, f, col, fields);
58}
59
60int mailimf_envelope_fields_write_file(FILE * f, int * col,
61 struct mailimf_fields * fields)
62{
63 return mailimf_envelope_fields_write_driver(do_write, f, col, fields);
64}
65
66int mailimf_field_write_file(FILE * f, int * col,
67 struct mailimf_field * field)
68{
69 return mailimf_field_write_driver(do_write, f, col, field);
70}
71
72int mailimf_quoted_string_write_file(FILE * f, int * col,
73 const char * string, size_t len)
74{
75 return mailimf_quoted_string_write_driver(do_write, f, col, string, len);
76}
77
78int mailimf_address_list_write_file(FILE * f, int * col,
79 struct mailimf_address_list * addr_list)
80{
81 return mailimf_address_list_write_driver(do_write, f, col, addr_list);
82}
83
84int mailimf_mailbox_list_write_file(FILE * f, int * col,
85 struct mailimf_mailbox_list * mb_list)
86{
87 return mailimf_mailbox_list_write_driver(do_write, f, col, mb_list);
88}
89
90int mailimf_header_string_write_file(FILE * f, int * col,
91 const char * str, size_t length)
92{
93 return mailimf_header_string_write_driver(do_write, f, col, str, length);
94}
95
96
97/* binary compatibility with 0.34 - begin */
98
99#ifdef MAILIMF_WRITE_COMPATIBILITY
100int mailimf_string_write(FILE * f, int * col,
101 const char * str, size_t length)
102{
103 return mailimf_string_write_file(f, col, str, length);
104}
105
106int mailimf_fields_write(FILE * f, int * col,
107 struct mailimf_fields * fields)
108{
109 return mailimf_fields_write_file(f, col, fields);
110}
111
112int mailimf_envelope_fields_write(FILE * f, int * col,
113 struct mailimf_fields * fields)
114{
115 return mailimf_envelope_fields_write_file(f, col, fields);
116}
117
118int mailimf_field_write(FILE * f, int * col,
119 struct mailimf_field * field)
120{
121 return mailimf_field_write_file(f, col, field);
122}
123
124int mailimf_quoted_string_write(FILE * f, int * col,
125 const char * string, size_t len)
126{
127 return mailimf_quoted_string_write_file(f, col, string, len);
128}
129
130int mailimf_address_list_write(FILE * f, int * col,
131 struct mailimf_address_list * addr_list)
132{
133 return mailimf_address_list_write_file(f, col, addr_list);
134}
135
136int mailimf_mailbox_list_write(FILE * f, int * col,
137 struct mailimf_mailbox_list * mb_list)
138{
139 return mailimf_mailbox_list_write_file(f, col, mb_list);
140}
141
142int mailimf_header_string_write(FILE * f, int * col,
143 const char * str, size_t length)
144{
145 return mailimf_header_string_write_file(f, col, str, length);
146}
147#endif
148
149/* binary compatibility with 0.34 - end */
diff --git a/libetpan/src/low-level/imf/mailimf_write_file.h b/libetpan/src/low-level/imf/mailimf_write_file.h
new file mode 100644
index 0000000..2b7707f
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_file.h
@@ -0,0 +1,169 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_WRITE_H
37
38#define MAILIMF_WRITE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <stdio.h>
45#include <libetpan/mailimf_types.h>
46
47 //#define MAILIMF_WRITE_COMPATIBILITY
48
49/*
50 mailimf_string_write_file writes a string to a given stream
51
52 @param f is the stream
53 @param col (* col) is the column number where we will start to
54 write the text, the ending column will be stored in (* col)
55 @param str is the string to write
56*/
57
58int mailimf_string_write_file(FILE * f, int * col,
59 const char * str, size_t length);
60
61
62/*
63 mailimf_fields_write_file writes the fields to a given stream
64
65 @param f is the stream
66 @param col (* col) is the column number where we will start to
67 write the text, the ending column will be stored in (* col)
68 @param fields is the fields to write
69*/
70
71int mailimf_fields_write_file(FILE * f, int * col,
72 struct mailimf_fields * fields);
73
74
75/*
76 mailimf_envelope_fields_write_file writes only some fields to a given stream
77
78 @param f is the stream
79 @param col (* col) is the column number where we will start to
80 write the text, the ending column will be stored in (* col)
81 @param fields is the fields to write
82*/
83
84int mailimf_envelope_fields_write_file(FILE * f, int * col,
85 struct mailimf_fields * fields);
86
87
88/*
89 mailimf_field_write_file writes a field to a given stream
90
91 @param f is the stream
92 @param col (* col) is the column number where we will start to
93 write the text, the ending column will be stored in (* col)
94 @param field is the field to write
95*/
96
97int mailimf_field_write_file(FILE * f, int * col,
98 struct mailimf_field * field);
99
100/*
101 mailimf_quoted_string_write_file writes a string that is quoted
102 to a given stream
103
104 @param f is the stream
105 @param col (* col) is the column number where we will start to
106 write the text, the ending column will be stored in (* col)
107 @param string is the string to quote and write
108*/
109
110int mailimf_quoted_string_write_file(FILE * f, int * col,
111 const char * string, size_t len);
112
113int mailimf_address_list_write_file(FILE * f, int * col,
114 struct mailimf_address_list * addr_list);
115
116int mailimf_mailbox_list_write_file(FILE * f, int * col,
117 struct mailimf_mailbox_list * mb_list);
118
119/*
120 mailimf_header_string_write_file writes a header value and fold the header
121 if needed.
122
123 @param f is the stream
124 @param col (* col) is the column number where we will start to
125 write the text, the ending column will be stored in (* col)
126 @param str is the string to write
127*/
128
129int mailimf_header_string_write_file(FILE * f, int * col,
130 const char * str, size_t length);
131
132
133
134/* binary compatibility with 0.34 - begin */
135
136#ifdef MAILIMF_WRITE_COMPATIBILITY
137int mailimf_string_write(FILE * f, int * col,
138 const char * str, size_t length);
139
140int mailimf_fields_write(FILE * f, int * col,
141 struct mailimf_fields * fields);
142
143int mailimf_envelope_fields_write(FILE * f, int * col,
144 struct mailimf_fields * fields);
145
146int mailimf_field_write(FILE * f, int * col,
147 struct mailimf_field * field);
148
149int mailimf_quoted_string_write(FILE * f, int * col,
150 const char * string, size_t len);
151
152int mailimf_address_list_write(FILE * f, int * col,
153 struct mailimf_address_list * addr_list);
154
155int mailimf_mailbox_list_write(FILE * f, int * col,
156 struct mailimf_mailbox_list * mb_list);
157
158int mailimf_header_string_write(FILE * f, int * col,
159 const char * str, size_t length);
160#endif
161
162/* binary compatibility with 0.34 - end */
163
164
165#ifdef __cplusplus
166}
167#endif
168
169#endif
diff --git a/libetpan/src/low-level/imf/mailimf_write_generic.c b/libetpan/src/low-level/imf/mailimf_write_generic.c
new file mode 100644
index 0000000..74c1d43
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_generic.c
@@ -0,0 +1,2028 @@
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 "mailimf_write_generic.h"
37
38#include <time.h>
39#include <string.h>
40#include <ctype.h>
41
42#define MAX_MAIL_COL 72
43
44#ifndef TRUE
45#define TRUE 1
46#endif
47
48#ifndef FALSE
49#define FALSE 0
50#endif
51
52#define MAX_VALID_IMF_LINE 998
53
54static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
55 int * col,
56 struct mailimf_orig_date * date);
57static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
58 struct mailimf_date_time * date_time);
59static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
60 struct mailimf_from * from);
61static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
62 struct mailimf_sender * sender);
63static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
64 struct mailimf_reply_to * reply_to);
65static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
66 struct mailimf_to * to);
67static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
68 struct mailimf_cc * to);
69static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
70 struct mailimf_bcc * to);
71static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
72 struct mailimf_message_id * message_id);
73static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
74 clist * list);
75static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
76 struct mailimf_in_reply_to *
77 in_reply_to);
78static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
79 struct mailimf_references * references);
80static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
81 struct mailimf_subject * subject);
82
83static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
84 struct mailimf_address * addr);
85static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
86 struct mailimf_group * group);
87
88static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
89 struct mailimf_mailbox * mb);
90
91static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
92 struct mailimf_comments * comments);
93
94static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
95 struct mailimf_optional_field * field);
96
97static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
98 struct mailimf_keywords * keywords);
99
100static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
101 struct mailimf_return * return_path);
102
103static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
104 struct mailimf_path * path);
105
106static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
107 struct mailimf_orig_date * date);
108
109static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
110 struct mailimf_from * from);
111
112static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
113 struct mailimf_sender * sender);
114
115static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
116 struct mailimf_to * to);
117
118static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
119 struct mailimf_cc * cc);
120
121static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
122 struct mailimf_bcc * bcc);
123
124static int
125mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
126 struct mailimf_message_id * message_id);
127
128
129
130/* ************************ */
131
132#if 0
133int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
134 char * str, size_t length)
135{
136 int r;
137
138 if (length != 0) {
139 r = fwrite(str, sizeof(char), length, f);
140 if (r < 0)
141 return MAILIMF_ERROR_FILE;
142 * col += length;
143 }
144
145 return MAILIMF_NO_ERROR;
146}
147#endif
148
149#define CRLF "\r\n"
150#define HEADER_FOLD "\r\n "
151
152static inline int flush_buf(int (* do_write)(void *, const char *, size_t), void * data, const char * str, size_t length)
153{
154 if (length != 0) {
155 int r;
156
157 if (length > 0) {
158 r = do_write(data, str, length);
159 if (r == 0)
160 return MAILIMF_ERROR_FILE;
161 }
162 }
163 return MAILIMF_NO_ERROR;
164}
165
166#define CUT_AT_MAX_VALID_IMF_LINE
167
168int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
169 const char * str, size_t length)
170{
171 int r;
172 size_t count;
173 const char * block_begin;
174 const char * p;
175 int done;
176
177 p = str;
178 block_begin = str;
179 count = 0;
180
181 while (length > 0) {
182#ifdef CUT_AT_MAX_VALID_IMF_LINE
183 if (count >= 998) {
184 /*
185 cut lines at maximum valid length for internet message
186 format standard (currently RFC 2822)
187
188 This should not happen.
189 In case there are some lines larger than 998 in body,
190 the encoding must be changed into base64 or quoted-printable
191 so that wrapping to 72 columns is done.
192 */
193
194 r = flush_buf(do_write, data, block_begin, count);
195 if (r != MAILIMF_NO_ERROR)
196 return r;
197
198 r = do_write(data, CRLF, sizeof(CRLF) - 1);
199 if (r == 0)
200 return MAILIMF_ERROR_FILE;
201
202 count = 0;
203 block_begin = p;
204
205 * col = 0;
206 }
207#endif
208 switch (* p) {
209 case '\n':
210 r = flush_buf(do_write, data, block_begin, count);
211 if (r != MAILIMF_NO_ERROR)
212 return r;
213
214 r = do_write(data, CRLF, sizeof(CRLF) - 1);
215 if (r == 0)
216 return MAILIMF_ERROR_FILE;
217
218 p ++;
219 length --;
220 count = 0;
221 block_begin = p;
222
223 * col = 0;
224 break;
225
226 case '\r':
227 done = 0;
228 if (length >= 2) {
229 if (* (p + 1) == '\n') {
230 r = flush_buf(do_write, data, block_begin, count);
231 if (r != MAILIMF_NO_ERROR)
232 return r;
233
234 r = do_write(data, CRLF, sizeof(CRLF) - 1);
235 if (r == 0)
236 return MAILIMF_ERROR_FILE;
237
238 p += 2;
239 length -= 2;
240 count = 0;
241 block_begin = p;
242
243 * col = 0;
244
245 done = 1;
246 }
247 }
248 if (!done) {
249 r = flush_buf(do_write, data, block_begin, count);
250 if (r != MAILIMF_NO_ERROR)
251 return r;
252
253 r = do_write(data, CRLF, sizeof(CRLF) - 1);
254 if (r == 0)
255 return MAILIMF_ERROR_FILE;
256
257 p ++;
258 length --;
259 count = 0;
260 block_begin = p;
261
262 * col = 0;
263 }
264 break;
265
266 default:
267 p ++;
268 count ++;
269 length --;
270 break;
271 }
272 }
273
274 r = flush_buf(do_write, data, block_begin, count);
275 if (r != MAILIMF_NO_ERROR)
276 return r;
277 * col += count;
278
279 return MAILIMF_NO_ERROR;
280}
281
282#if 0
283int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
284 char * str, size_t length)
285{
286 char * p;
287 char * block_begin;
288 int current_col;
289 char * last_cut;
290 int r;
291 int first;
292
293 if (* col + length < MAX_MAIL_COL)
294 return mailimf_string_write_driver(do_write, data, col, str, length);
295
296 first = 1;
297 p = str;
298 block_begin = p;
299 last_cut = block_begin;
300 current_col = * col;
301
302 while (1) {
303 if (current_col >= MAX_MAIL_COL) {
304 /* if we reach the maximum recommanded size of line */
305 if (last_cut == block_begin) {
306 /* if we could not find any place to cut */
307 if (first) {
308 /* fold the header */
309 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
310 sizeof(HEADER_FOLD) - 1);
311 if (r != MAILIMF_NO_ERROR)
312 return r;
313 current_col = * col + p - block_begin;
314 first = 0;
315 }
316 else {
317 /* cut the header */
318 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
319 if (r != MAILIMF_NO_ERROR)
320 return r;
321 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
322 sizeof(HEADER_FOLD) - 1);
323 if (r != MAILIMF_NO_ERROR)
324 return r;
325 first = 0;
326 block_begin = p;
327 last_cut = block_begin;
328 current_col = * col + p - block_begin;
329 }
330 }
331 else {
332 /* if we found a place to cut */
333 r = mailimf_string_write_driver(do_write, data, col, block_begin, last_cut - block_begin);
334 if (r != MAILIMF_NO_ERROR)
335 return r;
336 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
337 sizeof(HEADER_FOLD) - 1);
338 if (r != MAILIMF_NO_ERROR)
339 return r;
340 first = 0;
341 block_begin = last_cut;
342 last_cut = block_begin;
343 current_col = * col + p - block_begin;
344 continue;
345 }
346 }
347 else {
348 if (length == 0)
349 break;
350
351 switch (* p) {
352 case ' ':
353 case '\t':
354 last_cut = p;
355 current_col ++;
356 break;
357
358 case '\r':
359 case '\n':
360 current_col = 0;
361 break;
362
363 default:
364 current_col ++;
365 break;
366 }
367
368 p ++;
369 length --;
370 }
371 }
372
373 return mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
374}
375#endif
376
377#if 0
378enum {
379 STATE_LOWER_72,
380 STATE_LOWER_72_CUT,
381 STATE_EQUAL_72,
382 STATE_LOWER_998,
383 STATE_EQUAL_998,
384};
385
386int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
387 const char * str, size_t length)
388{
389 int state;
390 const char * p;
391 const char * block_begin;
392 size_t size;
393 const char * cut;
394 int r;
395
396 if (* col < MAX_MAIL_COL)
397 state = STATE_LOWER_72_CUT;
398 else if (* col == MAX_MAIL_COL)
399 state = STATE_EQUAL_72;
400 else if (* col < MAX_VALID_IMF_LINE)
401 state = STATE_LOWER_998;
402 else
403 state = STATE_EQUAL_998;
404
405 p = str;
406 block_begin = p;
407 size = * col;
408 cut = p;
409
410 while (length > 0) {
411 switch (state) {
412 case STATE_LOWER_72:
413 switch (* p) {
414 case '\r':
415 case '\n':
416 p ++;
417 length --;
418 size = 0;
419 break;
420
421 case ' ':
422 case '\t':
423 cut = p;
424 p ++;
425 length --;
426 size ++;
427 state = STATE_LOWER_72_CUT;
428 break;
429
430 default:
431 if (size < MAX_MAIL_COL - 1) {
432 p ++;
433 length --;
434 size ++;
435 }
436 else {
437 state = STATE_EQUAL_72;
438 p ++;
439 length --;
440 size ++;
441 }
442 break;
443 }
444 break; /* end of STATE_LOWER_72 */
445
446 case STATE_LOWER_72_CUT:
447 switch (* p) {
448 case '\r':
449 case '\n':
450 p ++;
451 length --;
452 size = 0;
453 state = STATE_LOWER_72;
454 break;
455
456 case ' ':
457 case '\t':
458 cut = p;
459 p ++;
460 length --;
461 size ++;
462 break;
463
464 default:
465 if (size < MAX_MAIL_COL) {
466 p ++;
467 length --;
468 size ++;
469 }
470 else {
471 r = mailimf_string_write_driver(do_write, data, col, block_begin, cut - block_begin);
472 if (r != MAILIMF_NO_ERROR)
473 return r;
474 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
475 sizeof(HEADER_FOLD) - 1);
476 if (r != MAILIMF_NO_ERROR)
477 return r;
478 p ++;
479 length --;
480 block_begin = cut;
481 if ((* block_begin == ' ') || (* block_begin == '\t'))
482 block_begin ++;
483 size = p - block_begin + * col;
484 state = STATE_LOWER_72;
485 }
486 break;
487 }
488 break; /* end of STATE_LOWER_72_CUT */
489
490 case STATE_EQUAL_72:
491 switch (* p) {
492 case '\r':
493 case '\n':
494 p ++;
495 length --;
496 size = 0;
497 state = STATE_LOWER_72;
498 break;
499
500 case ' ':
501 case '\t':
502 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
503 if (r != MAILIMF_NO_ERROR)
504 return r;
505 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
506 sizeof(HEADER_FOLD) - 1);
507 if (r != MAILIMF_NO_ERROR)
508 return r;
509 p ++;
510 length --;
511 block_begin = p;
512 size = p - block_begin + * col;
513 state = STATE_LOWER_72;
514 break;
515
516 default:
517 p ++;
518 length --;
519 size ++;
520 state = STATE_LOWER_998;
521 break;
522 }
523 break; /* end of STATE_EQUAL_72 */
524
525 case STATE_LOWER_998:
526 switch (* p) {
527 case '\r':
528 case '\n':
529 p ++;
530 length --;
531 size = 0;
532 state = STATE_LOWER_72;
533 break;
534
535 case ' ':
536 case '\t':
537 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
538 if (r != MAILIMF_NO_ERROR)
539 return r;
540 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
541 sizeof(HEADER_FOLD) - 1);
542 if (r != MAILIMF_NO_ERROR)
543 return r;
544 p ++;
545 length --;
546 block_begin = p;
547 size = p - block_begin + * col;
548 state = STATE_LOWER_72;
549 break;
550
551 default:
552 if (size < MAX_VALID_IMF_LINE - 1) {
553 p ++;
554 length --;
555 size ++;
556 }
557 else {
558 p ++;
559 length --;
560 size = 0;
561 state = STATE_EQUAL_998;
562 }
563 break;
564 }
565 break; /* end of STATE_LOWER_998 */
566
567 case STATE_EQUAL_998:
568 switch (* p) {
569 case '\r':
570 case '\n':
571 p ++;
572 length --;
573 size = 0;
574 state = STATE_LOWER_72;
575 break;
576
577 case ' ':
578 case '\t':
579 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
580 if (r != MAILIMF_NO_ERROR)
581 return r;
582 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
583 sizeof(HEADER_FOLD) - 1);
584 if (r != MAILIMF_NO_ERROR)
585 return r;
586 p ++;
587 length --;
588 block_begin = p;
589 size = p - block_begin + * col;
590 state = STATE_LOWER_72;
591 break;
592
593 default:
594#ifdef CUT_AT_MAX_VALID_IMF_LINE
595 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
596 if (r != MAILIMF_NO_ERROR)
597 return r;
598 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
599 sizeof(HEADER_FOLD) - 1);
600 if (r != MAILIMF_NO_ERROR)
601 return r;
602 p ++;
603 length --;
604 block_begin = p;
605 size = p - block_begin + * col;
606 state = STATE_LOWER_72;
607#else
608 p ++;
609 length --;
610 size ++;
611#endif
612 break;
613 }
614 break; /* end of STATE_EQUAL_998 */
615 }
616 }
617
618 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
619 if (r != MAILIMF_NO_ERROR)
620 return r;
621
622 return MAILIMF_NO_ERROR;
623}
624#endif
625
626enum {
627 STATE_BEGIN,
628 STATE_WORD,
629 STATE_SPACE,
630};
631
632int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
633 const char * str, size_t length)
634{
635 int state;
636 const char * p;
637 const char * word_begin;
638 const char * word_end;
639 const char * next_word;
640 int first;
641
642 state = STATE_BEGIN;
643
644 p = str;
645 word_begin = p;
646 word_end = p;
647 next_word = p;
648 first = 1;
649
650 while (length > 0) {
651 switch (state) {
652 case STATE_BEGIN:
653 switch (* p) {
654 case '\r':
655 case '\n':
656 case ' ':
657 case '\t':
658 p ++;
659 length --;
660 break;
661
662 default:
663 word_begin = p;
664 state = STATE_WORD;
665 break;
666 }
667 break;
668
669 case STATE_SPACE:
670 switch (* p) {
671 case '\r':
672 case '\n':
673 case ' ':
674 case '\t':
675 p ++;
676 length --;
677 break;
678
679 default:
680 word_begin = p;
681 state = STATE_WORD;
682 break;
683 }
684 break;
685
686 case STATE_WORD:
687 switch (* p) {
688 case '\r':
689 case '\n':
690 case ' ':
691 case '\t':
692 if (p - word_begin + (* col) + 1 > MAX_MAIL_COL)
693 mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
694 sizeof(HEADER_FOLD) - 1);
695 else {
696 if (!first)
697 mailimf_string_write_driver(do_write, data, col, " ", 1);
698 }
699 first = 0;
700 mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin);
701 state = STATE_SPACE;
702 break;
703
704 default:
705 if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) {
706 mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin);
707 mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
708 sizeof(HEADER_FOLD) - 1);
709 word_begin = p;
710 }
711 p ++;
712 length --;
713 break;
714 }
715 break;
716 }
717 }
718
719 if (state == STATE_WORD) {
720 if (p - word_begin + (* col) >= MAX_MAIL_COL)
721 mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
722 sizeof(HEADER_FOLD) - 1);
723 else {
724 if (!first)
725 mailimf_string_write_driver(do_write, data, col, " ", 1);
726 }
727 first = 0;
728 mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin);
729 }
730
731 return MAILIMF_NO_ERROR;
732}
733
734int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
735 struct mailimf_fields * fields)
736{
737 clistiter * cur;
738
739 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
740 cur = clist_next(cur)) {
741 int r;
742 struct mailimf_field * field;
743
744 field = clist_content(cur);
745 if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) {
746 r = mailimf_field_write_driver(do_write, data, col, field);
747 if (r != MAILIMF_NO_ERROR)
748 return r;
749 }
750 }
751
752 return MAILIMF_NO_ERROR;
753}
754
755int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
756 struct mailimf_fields * fields)
757{
758 clistiter * cur;
759
760 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
761 cur = clist_next(cur)) {
762 int r;
763
764 r = mailimf_field_write_driver(do_write, data, col, clist_content(cur));
765 if (r != MAILIMF_NO_ERROR)
766 return r;
767 }
768
769 return MAILIMF_NO_ERROR;
770}
771
772#if 0
773int mailimf_unparsed_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
774 struct mailimf_unparsed_fields * fields)
775{
776 clistiter * cur;
777
778 for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) {
779 int r;
780
781 r = mailimf_optional_field_write_driver(do_write, data, col, cur->data);
782 if (r != MAILIMF_NO_ERROR)
783 return r;
784 }
785
786 return MAILIMF_NO_ERROR;
787}
788#endif
789
790int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
791 struct mailimf_field * field)
792{
793 int r;
794
795 switch (field->fld_type) {
796 case MAILIMF_FIELD_RETURN_PATH:
797 r = mailimf_return_write_driver(do_write, data, col, field->fld_data.fld_return_path);
798 break;
799 case MAILIMF_FIELD_RESENT_DATE:
800 r = mailimf_resent_date_write_driver(do_write, data, col, field->fld_data.fld_resent_date);
801 break;
802 case MAILIMF_FIELD_RESENT_FROM:
803 r = mailimf_resent_from_write_driver(do_write, data, col, field->fld_data.fld_resent_from);
804 break;
805 case MAILIMF_FIELD_RESENT_SENDER:
806 r = mailimf_resent_sender_write_driver(do_write, data, col, field->fld_data.fld_resent_sender);
807 break;
808 case MAILIMF_FIELD_RESENT_TO:
809 r = mailimf_resent_to_write_driver(do_write, data, col, field->fld_data.fld_resent_to);
810 break;
811 case MAILIMF_FIELD_RESENT_CC:
812 r = mailimf_resent_cc_write_driver(do_write, data, col, field->fld_data.fld_resent_cc);
813 break;
814 case MAILIMF_FIELD_RESENT_BCC:
815 r = mailimf_resent_bcc_write_driver(do_write, data, col, field->fld_data.fld_resent_bcc);
816 break;
817 case MAILIMF_FIELD_RESENT_MSG_ID:
818 r = mailimf_resent_msg_id_write_driver(do_write, data, col, field->fld_data.fld_resent_msg_id);
819 break;
820 case MAILIMF_FIELD_ORIG_DATE:
821 r = mailimf_orig_date_write_driver(do_write, data, col, field->fld_data.fld_orig_date);
822 break;
823 case MAILIMF_FIELD_FROM:
824 r = mailimf_from_write_driver(do_write, data, col, field->fld_data.fld_from);
825 break;
826 case MAILIMF_FIELD_SENDER:
827 r = mailimf_sender_write_driver(do_write, data, col, field->fld_data.fld_sender);
828 break;
829 case MAILIMF_FIELD_REPLY_TO:
830 r = mailimf_reply_to_write_driver(do_write, data, col, field->fld_data.fld_reply_to);
831 break;
832 case MAILIMF_FIELD_TO:
833 r = mailimf_to_write_driver(do_write, data, col, field->fld_data.fld_to);
834 break;
835 case MAILIMF_FIELD_CC:
836 r = mailimf_cc_write_driver(do_write, data, col, field->fld_data.fld_cc);
837 break;
838 case MAILIMF_FIELD_BCC:
839 r = mailimf_bcc_write_driver(do_write, data, col, field->fld_data.fld_bcc);
840 break;
841 case MAILIMF_FIELD_MESSAGE_ID:
842 r = mailimf_message_id_write_driver(do_write, data, col, field->fld_data.fld_message_id);
843 break;
844 case MAILIMF_FIELD_IN_REPLY_TO:
845 r = mailimf_in_reply_to_write_driver(do_write, data, col, field->fld_data.fld_in_reply_to);
846 break;
847 case MAILIMF_FIELD_REFERENCES:
848 r = mailimf_references_write_driver(do_write, data, col, field->fld_data.fld_references);
849 break;
850 case MAILIMF_FIELD_SUBJECT:
851 r = mailimf_subject_write_driver(do_write, data, col, field->fld_data.fld_subject);
852 break;
853 case MAILIMF_FIELD_COMMENTS:
854 r = mailimf_comments_write_driver(do_write, data, col, field->fld_data.fld_comments);
855 break;
856 case MAILIMF_FIELD_KEYWORDS:
857 r = mailimf_keywords_write_driver(do_write, data, col, field->fld_data.fld_keywords);
858 break;
859 case MAILIMF_FIELD_OPTIONAL_FIELD:
860 r = mailimf_optional_field_write_driver(do_write, data, col, field->fld_data.fld_optional_field);
861 break;
862 default:
863 r = MAILIMF_ERROR_INVAL;
864 break;
865 }
866
867 if (r != MAILIMF_NO_ERROR)
868 return r;
869
870 return MAILIMF_NO_ERROR;
871}
872
873
874static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
875 struct mailimf_orig_date * date)
876{
877 int r;
878
879 r = mailimf_string_write_driver(do_write, data, col, "Date: ", 6);
880 if (r != MAILIMF_NO_ERROR)
881 return r;
882
883 r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time);
884 if (r != MAILIMF_NO_ERROR)
885 return r;
886
887 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
888 if (r != MAILIMF_NO_ERROR)
889 return r;
890#if 0
891 * col = 0;
892#endif
893
894 return MAILIMF_NO_ERROR;
895}
896
897#define MAX_DATE_STR 256
898
899/* 0 = Sunday */
900/* y > 1752 */
901
902static int dayofweek(int year, int month, int day)
903{
904 static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
905
906 year -= month < 3;
907
908 return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7;
909}
910
911static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
912 "Fri", "Sat"};
913static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
914 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
915
916static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
917 struct mailimf_date_time * date_time)
918{
919 int r;
920 char date_str[MAX_DATE_STR];
921#if 0
922 struct tm tmval;
923 time_t timeval;
924#endif
925 int wday;
926
927#if 0
928 tmval.tm_sec = date_time->sec;
929 tmval.tm_min = date_time->min;
930 tmval.tm_hour = date_time->hour;
931 tmval.tm_sec = date_time->sec;
932 tmval.tm_mday = date_time->day;
933 tmval.tm_mon = date_time->month - 1;
934 tmval.tm_year = date_time->year - 1900;
935 tmval.tm_isdst = 1;
936
937 timeval = mktime(&tmval);
938
939 localtime_r(&timeval, &tmval);
940#endif
941
942 wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day);
943
944 snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i",
945 week_of_day_str[wday], date_time->dt_day,
946 month_str[date_time->dt_month - 1],
947 date_time->dt_year, date_time->dt_hour,
948 date_time->dt_min, date_time->dt_sec,
949 date_time->dt_zone);
950
951 r = mailimf_string_write_driver(do_write, data, col, date_str, strlen(date_str));
952
953 if (r != MAILIMF_NO_ERROR)
954 return r;
955
956 return MAILIMF_NO_ERROR;
957}
958
959static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
960 struct mailimf_from * from)
961{
962 int r;
963
964 r = mailimf_string_write_driver(do_write, data, col, "From: ", 6);
965 if (r != MAILIMF_NO_ERROR)
966 return r;
967
968 r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list);
969 if (r != MAILIMF_NO_ERROR)
970 return r;
971
972 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
973 if (r != MAILIMF_NO_ERROR)
974 return r;
975#if 0
976 * col = 0;
977#endif
978
979 return MAILIMF_NO_ERROR;
980}
981
982static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
983 struct mailimf_sender * sender)
984{
985 int r;
986
987 r = mailimf_string_write_driver(do_write, data, col, "Sender: ", 8);
988 if (r != MAILIMF_NO_ERROR)
989 return r;
990
991 r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb);
992 if (r != MAILIMF_NO_ERROR)
993 return r;
994
995 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
996 if (r != MAILIMF_NO_ERROR)
997 return r;
998#if 0
999 * col = 0;
1000#endif
1001
1002 return MAILIMF_NO_ERROR;
1003}
1004
1005static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1006 struct mailimf_reply_to * reply_to)
1007{
1008 int r;
1009
1010 r = mailimf_string_write_driver(do_write, data, col, "Reply-To: ", 10);
1011 if (r != MAILIMF_NO_ERROR)
1012 return r;
1013
1014 r = mailimf_address_list_write_driver(do_write, data, col, reply_to->rt_addr_list);
1015 if (r != MAILIMF_NO_ERROR)
1016 return r;
1017
1018 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1019 if (r != MAILIMF_NO_ERROR)
1020 return r;
1021#if 0
1022 * col = 0;
1023#endif
1024
1025 return MAILIMF_NO_ERROR;
1026}
1027
1028
1029static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1030 struct mailimf_to * to)
1031{
1032 int r;
1033
1034 r = mailimf_string_write_driver(do_write, data, col, "To: ", 4);
1035 if (r != MAILIMF_NO_ERROR)
1036 return r;
1037
1038 r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list);
1039 if (r != MAILIMF_NO_ERROR)
1040 return r;
1041
1042 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1043 if (r != MAILIMF_NO_ERROR)
1044 return r;
1045#if 0
1046 * col = 0;
1047#endif
1048
1049 return MAILIMF_NO_ERROR;
1050}
1051
1052
1053static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1054 struct mailimf_cc * cc)
1055{
1056 int r;
1057
1058 r = mailimf_string_write_driver(do_write, data, col, "Cc: ", 4);
1059 if (r != MAILIMF_NO_ERROR)
1060 return r;
1061
1062 r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list);
1063 if (r != MAILIMF_NO_ERROR)
1064 return r;
1065
1066 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1067 if (r != MAILIMF_NO_ERROR)
1068 return r;
1069#if 0
1070 * col = 0;
1071#endif
1072
1073 return MAILIMF_NO_ERROR;
1074}
1075
1076
1077static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1078 struct mailimf_bcc * bcc)
1079{
1080 int r;
1081
1082 r = mailimf_string_write_driver(do_write, data, col, "Bcc: ", 5);
1083 if (r != MAILIMF_NO_ERROR)
1084 return r;
1085
1086 if (bcc->bcc_addr_list != NULL) {
1087 r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list);
1088 if (r != MAILIMF_NO_ERROR)
1089 return r;
1090 }
1091
1092 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1093 if (r != MAILIMF_NO_ERROR)
1094 return r;
1095#if 0
1096 * col = 0;
1097#endif
1098
1099 return MAILIMF_NO_ERROR;
1100}
1101
1102
1103static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1104 struct mailimf_message_id * message_id)
1105{
1106 int r;
1107
1108 r = mailimf_string_write_driver(do_write, data, col, "Message-ID: ", 12);
1109 if (r != MAILIMF_NO_ERROR)
1110 return r;
1111
1112 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1113 if (r != MAILIMF_NO_ERROR)
1114 return r;
1115
1116 r = mailimf_string_write_driver(do_write, data, col,
1117 message_id->mid_value,
1118 strlen(message_id->mid_value));
1119 if (r != MAILIMF_NO_ERROR)
1120 return r;
1121
1122 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1123 if (r != MAILIMF_NO_ERROR)
1124 return r;
1125
1126 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1127 if (r != MAILIMF_NO_ERROR)
1128 return r;
1129#if 0
1130 * col = 0;
1131#endif
1132
1133 return MAILIMF_NO_ERROR;
1134}
1135
1136
1137static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, clist * mid_list)
1138{
1139 clistiter * cur;
1140 int r;
1141 int first;
1142
1143 first = TRUE;
1144
1145 for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) {
1146 char * msgid;
1147 size_t len;
1148
1149 msgid = clist_content(cur);
1150 len = strlen(msgid);
1151
1152 /*
1153 XXX - if this is the first message ID, don't fold.
1154 This is a workaround for a bug of old versions of INN.
1155 */
1156 if (!first) {
1157 if (* col > 1) {
1158
1159 if (* col + len >= MAX_MAIL_COL) {
1160 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1161 if (r != MAILIMF_NO_ERROR)
1162 return r;
1163#if 0
1164 * col = 1;
1165#endif
1166 first = TRUE;
1167 }
1168 }
1169 }
1170
1171 if (!first) {
1172 r = mailimf_string_write_driver(do_write, data, col, " ", 1);
1173 if (r != MAILIMF_NO_ERROR)
1174 return r;
1175 }
1176 else {
1177 first = FALSE;
1178 }
1179
1180 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1181 if (r != MAILIMF_NO_ERROR)
1182 return r;
1183
1184 r = mailimf_string_write_driver(do_write, data, col, msgid, len);
1185 if (r != MAILIMF_NO_ERROR)
1186 return r;
1187
1188 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1189 if (r != MAILIMF_NO_ERROR)
1190 return r;
1191 }
1192
1193 return MAILIMF_NO_ERROR;
1194}
1195
1196
1197static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1198 struct mailimf_in_reply_to * in_reply_to)
1199{
1200 int r;
1201
1202 r = mailimf_string_write_driver(do_write, data, col, "In-Reply-To: ", 13);
1203 if (r != MAILIMF_NO_ERROR)
1204 return r;
1205
1206 r = mailimf_msg_id_list_write_driver(do_write, data, col, in_reply_to->mid_list);
1207 if (r != MAILIMF_NO_ERROR)
1208 return r;
1209
1210 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1211 if (r != MAILIMF_NO_ERROR)
1212 return r;
1213#if 0
1214 * col = 0;
1215#endif
1216
1217 return MAILIMF_NO_ERROR;
1218}
1219
1220
1221static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1222 struct mailimf_references * references)
1223{
1224 int r;
1225
1226 r = mailimf_string_write_driver(do_write, data, col, "References: ", 12);
1227 if (r != MAILIMF_NO_ERROR)
1228 return r;
1229
1230 r = mailimf_msg_id_list_write_driver(do_write, data, col, references->mid_list);
1231 if (r != MAILIMF_NO_ERROR)
1232 return r;
1233
1234 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1235 if (r != MAILIMF_NO_ERROR)
1236 return r;
1237#if 0
1238 * col = 0;
1239#endif
1240
1241 return MAILIMF_NO_ERROR;
1242}
1243
1244
1245
1246static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1247 struct mailimf_subject * subject)
1248{
1249 int r;
1250
1251 r = mailimf_string_write_driver(do_write, data, col, "Subject: ", 9);
1252 if (r != MAILIMF_NO_ERROR)
1253 return r;
1254
1255 r = mailimf_header_string_write_driver(do_write, data, col,
1256 subject->sbj_value, strlen(subject->sbj_value));
1257 if (r != MAILIMF_NO_ERROR)
1258 return r;
1259
1260 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1261 if (r != MAILIMF_NO_ERROR)
1262 return r;
1263#if 0
1264 * col = 0;
1265#endif
1266
1267 return MAILIMF_NO_ERROR;
1268}
1269
1270int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1271 struct mailimf_address_list * addr_list)
1272{
1273 clistiter * cur;
1274 int r;
1275 int first;
1276
1277 first = TRUE;
1278
1279 for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
1280 cur = clist_next(cur)) {
1281 struct mailimf_address * addr;
1282
1283 addr = clist_content(cur);
1284
1285 if (!first) {
1286 r = mailimf_string_write_driver(do_write, data, col, ", ", 2);
1287 if (r != MAILIMF_NO_ERROR)
1288 return r;
1289 }
1290 else {
1291 first = FALSE;
1292 }
1293
1294 r = mailimf_address_write_driver(do_write, data, col, addr);
1295 if (r != MAILIMF_NO_ERROR)
1296 return r;
1297 }
1298
1299 return MAILIMF_NO_ERROR;
1300}
1301
1302
1303static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1304 struct mailimf_address * addr)
1305{
1306 int r;
1307
1308 switch(addr->ad_type) {
1309 case MAILIMF_ADDRESS_MAILBOX:
1310 r = mailimf_mailbox_write_driver(do_write, data, col, addr->ad_data.ad_mailbox);
1311 if (r != MAILIMF_NO_ERROR)
1312 return r;
1313
1314 break;
1315
1316 case MAILIMF_ADDRESS_GROUP:
1317 r = mailimf_group_write_driver(do_write, data, col, addr->ad_data.ad_group);
1318 if (r != MAILIMF_NO_ERROR)
1319 return r;
1320
1321 break;
1322 }
1323
1324 return MAILIMF_NO_ERROR;
1325}
1326
1327
1328static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1329 struct mailimf_group * group)
1330{
1331 int r;
1332
1333 r = mailimf_header_string_write_driver(do_write, data, col, group->grp_display_name,
1334 strlen(group->grp_display_name));
1335 if (r != MAILIMF_NO_ERROR)
1336 return r;
1337
1338 r = mailimf_string_write_driver(do_write, data, col, ": ", 2);
1339 if (r != MAILIMF_NO_ERROR)
1340 return r;
1341
1342 if (group->grp_mb_list != NULL) {
1343 r = mailimf_mailbox_list_write_driver(do_write, data, col, group->grp_mb_list);
1344 if (r != MAILIMF_NO_ERROR)
1345 return r;
1346 }
1347
1348 r = mailimf_string_write_driver(do_write, data, col, ";", 1);
1349 if (r != MAILIMF_NO_ERROR)
1350 return r;
1351
1352 return MAILIMF_NO_ERROR;
1353}
1354
1355
1356int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1357 struct mailimf_mailbox_list * mb_list)
1358{
1359 clistiter * cur;
1360 int r;
1361 int first;
1362
1363 first = TRUE;
1364
1365 for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
1366 cur = clist_next(cur)) {
1367 struct mailimf_mailbox * mb;
1368
1369 mb = clist_content(cur);
1370
1371 if (!first) {
1372 r = mailimf_string_write_driver(do_write, data, col, ", ", 2);
1373 if (r != MAILIMF_NO_ERROR)
1374 return r;
1375 }
1376 else {
1377 first = FALSE;
1378 }
1379
1380 r = mailimf_mailbox_write_driver(do_write, data, col, mb);
1381 if (r != MAILIMF_NO_ERROR)
1382 return r;
1383 }
1384
1385 return MAILIMF_NO_ERROR;
1386}
1387
1388
1389int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1390 const char * string, size_t len)
1391{
1392 int r;
1393 size_t i;
1394
1395 r = do_write(data, "\"", 1);
1396 if (r == 0)
1397 return MAILIMF_ERROR_FILE;
1398 for(i = 0 ; i < len ; i ++) {
1399 switch (string[i]) {
1400 case '\\':
1401 case '\"':
1402 r = do_write(data, "\\", 1);
1403 if (r == 0)
1404 return MAILIMF_ERROR_FILE;
1405 r = do_write(data, &string[i], 1);
1406 if (r == 0)
1407 return MAILIMF_ERROR_FILE;
1408 (* col) += 2;
1409 break;
1410
1411 default:
1412 r = do_write(data, &string[i], 1);
1413 if (r == 0)
1414 return MAILIMF_ERROR_FILE;
1415 (* col) ++;
1416 break;
1417 }
1418 }
1419 r = do_write(data, "\"", 1);
1420 if (r == 0)
1421 return MAILIMF_ERROR_FILE;
1422
1423 return MAILIMF_NO_ERROR;
1424}
1425
1426
1427/*
1428static int
1429atext = ALPHA / DIGIT / ; Any character except controls,
1430 "!" / "#" / ; SP, and specials.
1431 "$" / "%" / ; Used for atoms
1432 "&" / "'" /
1433 "*" / "+" /
1434 "-" / "/" /
1435 "=" / "?" /
1436 "^" / "_" /
1437 "`" / "{" /
1438 "|" / "}" /
1439 "~"
1440*/
1441
1442static int is_atext(const char * s)
1443{
1444 const char * p;
1445
1446 for(p = s ; * p != 0 ; p ++) {
1447 if (isalpha((unsigned char) * p))
1448 continue;
1449 if (isdigit((unsigned char) * p))
1450 continue;
1451 switch (*p) {
1452 case ' ':
1453 case '\t':
1454 case '!':
1455 case '#':
1456 case '$':
1457 case '%':
1458 case '&':
1459 case '\'':
1460 case '*':
1461 case '+':
1462 case '-':
1463 case '/':
1464 case '=':
1465 case '?':
1466 case '^':
1467 case '_':
1468 case '`':
1469 case '{':
1470 case '|':
1471 case '}':
1472 case '~':
1473 break;
1474 default:
1475 return 0;
1476 }
1477 }
1478
1479 return 1;
1480}
1481
1482static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1483 struct mailimf_mailbox * mb)
1484{
1485 int r;
1486 int do_fold;
1487
1488#if 0
1489 if (* col > 1) {
1490
1491 if (mb->mb_display_name != NULL) {
1492 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1493 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1494 if (r != MAILIMF_NO_ERROR)
1495 return r;
1496#if 0
1497 * col = 1;
1498#endif
1499 }
1500 }
1501 }
1502#endif
1503
1504 if (mb->mb_display_name) {
1505
1506 if (is_atext(mb->mb_display_name)) {
1507 r = mailimf_header_string_write_driver(do_write, data, col, mb->mb_display_name,
1508 strlen(mb->mb_display_name));
1509 if (r != MAILIMF_NO_ERROR)
1510 return r;
1511 }
1512 else {
1513 if (mb->mb_display_name != NULL) {
1514 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1515 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1516 if (r != MAILIMF_NO_ERROR)
1517 return r;
1518 }
1519 }
1520
1521 if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2)
1522 return MAILIMF_ERROR_INVAL;
1523
1524 r = mailimf_quoted_string_write_driver(do_write, data, col, mb->mb_display_name,
1525 strlen(mb->mb_display_name));
1526 if (r != MAILIMF_NO_ERROR)
1527 return r;
1528 }
1529
1530 do_fold = 0;
1531 if (* col > 1) {
1532
1533 if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) {
1534 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1535 if (r != MAILIMF_NO_ERROR)
1536 return r;
1537#if 0
1538 * col = 1;
1539#endif
1540 do_fold = 1;
1541 }
1542 }
1543
1544 if (do_fold)
1545 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1546 else
1547 r = mailimf_string_write_driver(do_write, data, col, " <", 2);
1548 if (r != MAILIMF_NO_ERROR)
1549 return r;
1550
1551 r = mailimf_string_write_driver(do_write, data, col, mb->mb_addr_spec,
1552 strlen(mb->mb_addr_spec));
1553 if (r != MAILIMF_NO_ERROR)
1554 return r;
1555
1556 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1557 if (r != MAILIMF_NO_ERROR)
1558 return r;
1559 }
1560 else {
1561 if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) {
1562 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1563 if (r != MAILIMF_NO_ERROR)
1564 return r;
1565 }
1566
1567 r = mailimf_string_write_driver(do_write, data, col,
1568 mb->mb_addr_spec, strlen(mb->mb_addr_spec));
1569 if (r != MAILIMF_NO_ERROR)
1570 return r;
1571 }
1572
1573
1574 return MAILIMF_NO_ERROR;
1575}
1576
1577static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1578 struct mailimf_comments * comments)
1579{
1580 int r;
1581
1582 r = mailimf_string_write_driver(do_write, data, col, "Comments: ", 10);
1583 if (r != MAILIMF_NO_ERROR)
1584 return r;
1585
1586 r = mailimf_header_string_write_driver(do_write, data, col,
1587 comments->cm_value, strlen(comments->cm_value));
1588 if (r != MAILIMF_NO_ERROR)
1589 return r;
1590
1591 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1592 if (r != MAILIMF_NO_ERROR)
1593 return r;
1594#if 0
1595 * col = 0;
1596#endif
1597
1598 return MAILIMF_NO_ERROR;
1599}
1600
1601static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1602 struct mailimf_optional_field * field)
1603{
1604 int r;
1605
1606 if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE)
1607 return MAILIMF_ERROR_INVAL;
1608
1609 r = mailimf_string_write_driver(do_write, data, col, field->fld_name, strlen(field->fld_name));
1610 if (r != MAILIMF_NO_ERROR)
1611 return r;
1612
1613 r = mailimf_string_write_driver(do_write, data, col, ": ", 2);
1614 if (r != MAILIMF_NO_ERROR)
1615 return r;
1616
1617 r = mailimf_header_string_write_driver(do_write, data, col, field->fld_value,
1618 strlen(field->fld_value));
1619 if (r != MAILIMF_NO_ERROR)
1620 return r;
1621
1622#if 0
1623 /* XXX parsing debug */
1624 mailimf_string_write_driver(do_write, data, col, " (X)", 4);
1625#endif
1626
1627 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1628 if (r != MAILIMF_NO_ERROR)
1629 return r;
1630#if 0
1631 * col = 0;
1632#endif
1633
1634 return MAILIMF_NO_ERROR;
1635}
1636
1637static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1638 struct mailimf_keywords * keywords)
1639{
1640 int r;
1641 clistiter * cur;
1642 int first;
1643
1644 r = mailimf_string_write_driver(do_write, data, col, "Keywords: ", 10);
1645 if (r != MAILIMF_NO_ERROR)
1646 return r;
1647
1648 first = TRUE;
1649
1650 for(cur = clist_begin(keywords->kw_list) ; cur != NULL ;
1651 cur = clist_next(cur)) {
1652 char * keyword;
1653 size_t len;
1654
1655 keyword = clist_content(cur);
1656 len = strlen(keyword);
1657
1658 if (!first) {
1659 r = mailimf_string_write_driver(do_write, data, col, ", ", 2);
1660 if (r != MAILIMF_NO_ERROR)
1661 return r;
1662 }
1663 else {
1664 first = FALSE;
1665 }
1666
1667#if 0
1668 if (* col > 1) {
1669
1670 if (* col + len >= MAX_MAIL_COL) {
1671 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1672 if (r != MAILIMF_NO_ERROR)
1673 return r;
1674#if 0
1675 * col = 1;
1676#endif
1677 }
1678 }
1679#endif
1680
1681 r = mailimf_header_string_write_driver(do_write, data, col, keyword, len);
1682 if (r != MAILIMF_NO_ERROR)
1683 return r;
1684 }
1685
1686 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1687 if (r != MAILIMF_NO_ERROR)
1688 return r;
1689#if 0
1690 * col = 0;
1691#endif
1692
1693 return MAILIMF_NO_ERROR;
1694}
1695
1696#if 0
1697static int mailimf_delivering_info_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1698 struct mailimf_delivering_info * info)
1699{
1700 clistiter * cur;
1701 int r;
1702
1703 for(cur = clist_begin(info->received_fields) ;
1704 cur != NULL ; cur = cur->next) {
1705 struct mailimf_trace_resent_fields * field;
1706
1707 field = cur->data;
1708
1709 r = mailimf_trace_resent_fields_write_driver(do_write, data, col, field);
1710 if (r != MAILIMF_NO_ERROR)
1711 return r;
1712 }
1713
1714 return MAILIMF_NO_ERROR;
1715}
1716
1717
1718static int
1719mailimf_trace_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1720 struct mailimf_trace_resent_fields * field)
1721{
1722 int r;
1723
1724 if (field->return_path != NULL) {
1725 r = mailimf_return_write_driver(do_write, data, col, field->return_path);
1726 if (r != MAILIMF_NO_ERROR)
1727 return r;
1728 }
1729
1730 if (field->resent_fields != NULL) {
1731 r = mailimf_resent_fields_write_driver(do_write, data, col, field->resent_fields);
1732 if (r != MAILIMF_NO_ERROR)
1733 return r;
1734 }
1735
1736 return MAILIMF_NO_ERROR;
1737}
1738#endif
1739
1740static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1741 struct mailimf_return * return_path)
1742{
1743 int r;
1744
1745 r = mailimf_string_write_driver(do_write, data, col, "Return-Path: ", 13);
1746 if (r != MAILIMF_NO_ERROR)
1747 return r;
1748
1749 r = mailimf_path_write_driver(do_write, data, col, return_path->ret_path);
1750 if (r != MAILIMF_NO_ERROR)
1751 return r;
1752
1753 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1754 if (r != MAILIMF_NO_ERROR)
1755 return r;
1756#if 0
1757 * col = 0;
1758#endif
1759
1760 return MAILIMF_NO_ERROR;
1761}
1762
1763static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1764 struct mailimf_path * path)
1765{
1766 int r;
1767
1768 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1769 if (r != MAILIMF_NO_ERROR)
1770 return r;
1771
1772 r = mailimf_string_write_driver(do_write, data, col, path->pt_addr_spec,
1773 strlen(path->pt_addr_spec));
1774 if (r != MAILIMF_NO_ERROR)
1775 return r;
1776
1777 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1778 if (r != MAILIMF_NO_ERROR)
1779 return r;
1780
1781 return MAILIMF_NO_ERROR;
1782}
1783
1784#if 0
1785static int mailimf_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1786 struct mailimf_resent_fields_list *
1787 resent_fields)
1788{
1789 clistiter * cur;
1790 int r;
1791
1792 for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) {
1793 struct mailimf_resent_field * field;
1794
1795 field = cur->data;
1796
1797 r = mailimf_resent_field_write_driver(do_write, data, col, field);
1798 if (r != MAILIMF_NO_ERROR)
1799 return r;
1800 }
1801
1802 return MAILIMF_NO_ERROR;
1803}
1804
1805
1806
1807static int mailimf_resent_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1808 struct mailimf_resent_field *
1809 resent_field)
1810{
1811 int r;
1812
1813 switch (resent_field->type) {
1814 case MAILIMF_RESENT_FIELD_DATE:
1815 r = mailimf_resent_date_write_driver(do_write, data, col, resent_field->resent_date);
1816 break;
1817
1818 case MAILIMF_RESENT_FIELD_FROM:
1819 r = mailimf_resent_from_write_driver(do_write, data, col, resent_field->resent_from);
1820 break;
1821
1822 case MAILIMF_RESENT_FIELD_SENDER:
1823 r = mailimf_resent_sender_write_driver(do_write, data, col, resent_field->resent_sender);
1824 break;
1825
1826 case MAILIMF_RESENT_FIELD_TO:
1827 r = mailimf_resent_to_write_driver(do_write, data, col, resent_field->resent_to);
1828 break;
1829
1830 case MAILIMF_RESENT_FIELD_CC:
1831 r = mailimf_resent_cc_write_driver(do_write, data, col, resent_field->resent_cc);
1832 break;
1833
1834 case MAILIMF_RESENT_FIELD_BCC:
1835 r = mailimf_resent_bcc_write_driver(do_write, data, col, resent_field->resent_bcc);
1836 break;
1837
1838 case MAILIMF_RESENT_FIELD_MSG_ID:
1839 r = mailimf_resent_msg_id_write_driver(do_write, data, col, resent_field->resent_msg_id);
1840 break;
1841 default:
1842 r = MAILIMF_ERROR_INVAL;
1843 break;
1844 }
1845
1846
1847 if (r != MAILIMF_NO_ERROR)
1848 return r;
1849
1850 return MAILIMF_NO_ERROR;
1851}
1852#endif
1853
1854static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1855 struct mailimf_orig_date * date)
1856{
1857 int r;
1858
1859 r = mailimf_string_write_driver(do_write, data, col, "Resent-Date: ", 13);
1860 if (r != MAILIMF_NO_ERROR)
1861 return r;
1862
1863 r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time);
1864 if (r != MAILIMF_NO_ERROR)
1865 return r;
1866
1867 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1868 if (r != MAILIMF_NO_ERROR)
1869 return r;
1870#if 0
1871 * col = 0;
1872#endif
1873
1874 return MAILIMF_NO_ERROR;
1875}
1876
1877static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1878 struct mailimf_from * from)
1879{
1880 int r;
1881
1882 r = mailimf_string_write_driver(do_write, data, col, "Resent-From: ", 13);
1883 if (r != MAILIMF_NO_ERROR)
1884 return r;
1885
1886 r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list);
1887 if (r != MAILIMF_NO_ERROR)
1888 return r;
1889
1890 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1891 if (r != MAILIMF_NO_ERROR)
1892 return r;
1893#if 0
1894 * col = 0;
1895#endif
1896
1897 return MAILIMF_NO_ERROR;
1898}
1899
1900static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1901 struct mailimf_sender * sender)
1902{
1903 int r;
1904
1905 r = mailimf_string_write_driver(do_write, data, col, "Resent-Sender: ", 15);
1906 if (r != MAILIMF_NO_ERROR)
1907 return r;
1908
1909 r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb);
1910 if (r != MAILIMF_NO_ERROR)
1911 return r;
1912
1913 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1914 if (r != MAILIMF_NO_ERROR)
1915 return r;
1916#if 0
1917 * col = 0;
1918#endif
1919
1920 return MAILIMF_NO_ERROR;
1921}
1922
1923static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1924 struct mailimf_to * to)
1925{
1926 int r;
1927
1928 r = mailimf_string_write_driver(do_write, data, col, "Resent-To: ", 11);
1929 if (r != MAILIMF_NO_ERROR)
1930 return r;
1931
1932 r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list);
1933 if (r != MAILIMF_NO_ERROR)
1934 return r;
1935
1936 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1937 if (r != MAILIMF_NO_ERROR)
1938 return r;
1939#if 0
1940 * col = 0;
1941#endif
1942
1943 return MAILIMF_NO_ERROR;
1944}
1945
1946
1947static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1948 struct mailimf_cc * cc)
1949{
1950 int r;
1951
1952 r = mailimf_string_write_driver(do_write, data, col, "Resent-Cc: ", 11);
1953 if (r != MAILIMF_NO_ERROR)
1954 return r;
1955
1956 r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list);
1957 if (r != MAILIMF_NO_ERROR)
1958 return r;
1959
1960 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1961 if (r != MAILIMF_NO_ERROR)
1962 return r;
1963#if 0
1964 * col = 0;
1965#endif
1966
1967 return MAILIMF_NO_ERROR;
1968}
1969
1970
1971static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1972 struct mailimf_bcc * bcc)
1973{
1974 int r;
1975
1976 r = mailimf_string_write_driver(do_write, data, col, "Resent-Bcc: ", 12);
1977 if (r != MAILIMF_NO_ERROR)
1978 return r;
1979
1980 if (bcc->bcc_addr_list != NULL) {
1981 r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list);
1982 if (r != MAILIMF_NO_ERROR)
1983 return r;
1984 }
1985
1986 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1987 if (r != MAILIMF_NO_ERROR)
1988 return r;
1989#if 0
1990 * col = 0;
1991#endif
1992
1993 return MAILIMF_NO_ERROR;
1994}
1995
1996
1997static int
1998mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1999 struct mailimf_message_id * message_id)
2000{
2001 int r;
2002
2003 r = mailimf_string_write_driver(do_write, data, col, "Resent-Message-ID: ", 19);
2004 if (r != MAILIMF_NO_ERROR)
2005 return r;
2006
2007 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
2008 if (r != MAILIMF_NO_ERROR)
2009 return r;
2010
2011 r = mailimf_string_write_driver(do_write, data, col,
2012 message_id->mid_value, strlen(message_id->mid_value));
2013 if (r != MAILIMF_NO_ERROR)
2014 return r;
2015
2016 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
2017 if (r != MAILIMF_NO_ERROR)
2018 return r;
2019
2020 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
2021 if (r != MAILIMF_NO_ERROR)
2022 return r;
2023#if 0
2024 * col = 0;
2025#endif
2026
2027 return MAILIMF_NO_ERROR;
2028}
diff --git a/libetpan/src/low-level/imf/mailimf_write_generic.h b/libetpan/src/low-level/imf/mailimf_write_generic.h
new file mode 100644
index 0000000..c207d7e
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_generic.h
@@ -0,0 +1,142 @@
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 MAILIMF_WRITE_GENERIC_H
37
38#define MAILIMF_WRITE_GENERIC_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <stdio.h>
45#include <libetpan/mailimf_types.h>
46
47/*
48 mailimf_string_write writes a string to a given stream
49
50 @param f is the stream
51 @param col (* col) is the column number where we will start to
52 write the text, the ending column will be stored in (* col)
53 @param str is the string to write
54*/
55
56int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
57 int * col,
58 const char * str, size_t length);
59
60
61/*
62 mailimf_fields_write writes the fields to a given stream
63
64 @param f is the stream
65 @param col (* col) is the column number where we will start to
66 write the text, the ending column will be stored in (* col)
67 @param fields is the fields to write
68*/
69
70int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
71 int * col,
72 struct mailimf_fields * fields);
73
74
75/*
76 mailimf_envelope_fields_write writes only some fields to a given stream
77
78 @param f is the stream
79 @param col (* col) is the column number where we will start to
80 write the text, the ending column will be stored in (* col)
81 @param fields is the fields to write
82*/
83
84int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
85 int * col,
86 struct mailimf_fields * fields);
87
88
89/*
90 mailimf_field_write writes a field to a given stream
91
92 @param f is the stream
93 @param col (* col) is the column number where we will start to
94 write the text, the ending column will be stored in (* col)
95 @param field is the field to write
96*/
97
98int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
99 int * col,
100 struct mailimf_field * field);
101
102/*
103 mailimf_quoted_string_write writes a string that is quoted
104 to a given stream
105
106 @param f is the stream
107 @param col (* col) is the column number where we will start to
108 write the text, the ending column will be stored in (* col)
109 @param string is the string to quote and write
110*/
111
112int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
113 int * col,
114 const char * string, size_t len);
115
116int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
117 int * col,
118 struct mailimf_address_list * addr_list);
119
120int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
121 int * col,
122 struct mailimf_mailbox_list * mb_list);
123
124/*
125 mailimf_header_string_write writes a header value and fold the header
126 if needed.
127
128 @param f is the stream
129 @param col (* col) is the column number where we will start to
130 write the text, the ending column will be stored in (* col)
131 @param str is the string to write
132*/
133
134int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
135 int * col,
136 const char * str, size_t length);
137
138#ifdef __cplusplus
139}
140#endif
141
142#endif
diff --git a/libetpan/src/low-level/imf/mailimf_write_mem.c b/libetpan/src/low-level/imf/mailimf_write_mem.c
new file mode 100644
index 0000000..00c043f
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_mem.c
@@ -0,0 +1,98 @@
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 "mailimf_write_mem.h"
37#include "mailimf_write_generic.h"
38
39static int do_write(void * data, const char * str, size_t length)
40{
41 MMAPString * f;
42
43 f = data;
44
45 if (mmap_string_append_len(f, str, length) == NULL)
46 return 0;
47 else
48 return length;
49}
50
51int mailimf_string_write_mem(MMAPString * f, int * col,
52 const char * str, size_t length)
53{
54 return mailimf_string_write_driver(do_write, f, col, str, length);
55}
56
57int mailimf_fields_write_mem(MMAPString * f, int * col,
58 struct mailimf_fields * fields)
59{
60 return mailimf_fields_write_driver(do_write, f, col, fields);
61}
62
63int mailimf_envelope_fields_write_mem(MMAPString * f, int * col,
64 struct mailimf_fields * fields)
65{
66 return mailimf_envelope_fields_write_driver(do_write, f, col, fields);
67}
68
69int mailimf_field_write_mem(MMAPString * f, int * col,
70 struct mailimf_field * field)
71{
72 return mailimf_field_write_driver(do_write, f, col, field);
73}
74
75int mailimf_quoted_string_write_mem(MMAPString * f, int * col,
76 const char * string, size_t len)
77{
78 return mailimf_quoted_string_write_driver(do_write, f, col, string, len);
79}
80
81int mailimf_address_list_write_mem(MMAPString * f, int * col,
82 struct mailimf_address_list * addr_list)
83{
84 return mailimf_address_list_write_driver(do_write, f, col, addr_list);
85}
86
87int mailimf_mailbox_list_write_mem(MMAPString * f, int * col,
88 struct mailimf_mailbox_list * mb_list)
89{
90 return mailimf_mailbox_list_write_driver(do_write, f, col, mb_list);
91}
92
93int mailimf_header_string_write_mem(MMAPString * f, int * col,
94 const char * str, size_t length)
95{
96 return mailimf_header_string_write_driver(do_write, f, col, str, length);
97}
98
diff --git a/libetpan/src/low-level/imf/mailimf_write_mem.h b/libetpan/src/low-level/imf/mailimf_write_mem.h
new file mode 100644
index 0000000..796f178
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_mem.h
@@ -0,0 +1,135 @@
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 MAILIMF_WRITE_MEM_H
37
38#define MAILIMF_WRITE_MEM_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <stdio.h>
45#include <libetpan/mailimf_types.h>
46#include <libetpan/mmapstring.h>
47
48/*
49 mailimf_string_write_mem appends a string to a given string
50
51 @param f is the string
52 @param col (* col) is the column number where we will start to
53 write the text, the ending column will be stored in (* col)
54 @param str is the string to write
55*/
56
57int mailimf_string_write_mem(MMAPString * f, int * col,
58 const char * str, size_t length);
59
60
61/*
62 mailimf_fields_write_mem appends the fields to a given string
63
64 @param f is the string
65 @param col (* col) is the column number where we will start to
66 write the text, the ending column will be stored in (* col)
67 @param fields is the fields to write
68*/
69
70int mailimf_fields_write_mem(MMAPString * f, int * col,
71 struct mailimf_fields * fields);
72
73
74/*
75 mailimf_envelope_fields_write_mem appends some fields to a given string
76
77 @param f is the string
78 @param col (* col) is the column number where we will start to
79 write the text, the ending column will be stored in (* col)
80 @param fields is the fields to write
81*/
82
83int mailimf_envelope_fields_write_mem(MMAPString * f, int * col,
84 struct mailimf_fields * fields);
85
86
87/*
88 mailimf_field_write_mem appends a field to a given string
89
90 @param f is the string
91 @param col (* col) is the column number where we will start to
92 write the text, the ending column will be stored in (* col)
93 @param field is the field to write
94*/
95
96int mailimf_field_write_mem(MMAPString * f, int * col,
97 struct mailimf_field * field);
98
99/*
100 mailimf_quoted_string_write_mem appends a string that is quoted
101 to a given string
102
103 @param f is the string
104 @param col (* col) is the column number where we will start to
105 write the text, the ending column will be stored in (* col)
106 @param string is the string to quote and write
107*/
108
109int mailimf_quoted_string_write_mem(MMAPString * f, int * col,
110 const char * string, size_t len);
111
112int mailimf_address_list_write_mem(MMAPString * f, int * col,
113 struct mailimf_address_list * addr_list);
114
115int mailimf_mailbox_list_write_mem(MMAPString * f, int * col,
116 struct mailimf_mailbox_list * mb_list);
117
118/*
119 mailimf_header_string_write_mem appends a header value and fold the header
120 if needed.
121
122 @param f is the string
123 @param col (* col) is the column number where we will start to
124 write the text, the ending column will be stored in (* col)
125 @param str is the string to write
126*/
127
128int mailimf_header_string_write_mem(MMAPString * f, int * col,
129 const char * str, size_t length);
130
131#ifdef __cplusplus
132}
133#endif
134
135#endif