summaryrefslogtreecommitdiffabout
path: root/libetpan/src/low-level/imf/mailimf.c
Unidiff
Diffstat (limited to 'libetpan/src/low-level/imf/mailimf.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/low-level/imf/mailimf.c7585
1 files changed, 7585 insertions, 0 deletions
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}