Remove inclusion of sys/socket.h from nntp-thread.c
[claws.git] / src / plugins / mailmbox / mailimf.c
bloba861004a6f757d73b8c6fcaa6c3ea60970e90855
1 /*
2 * libEtPan! -- a mail stuff library
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
5 * All rights reserved.
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.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
33 * $Id$
36 #ifdef HAVE_CONFIG_H
37 # include "config.h"
38 #include "claws-features.h"
39 #endif
41 #include "mailimf.h"
42 #include "file-utils.h"
45 RFC 2822
47 RFC 2821 ...
48 A message-originating SMTP system SHOULD NOT send a message that
49 already contains a Return-path header. SMTP servers performing a
50 relay function MUST NOT inspect the message data, and especially not
51 to the extent needed to determine if Return-path headers are present.
52 SMTP servers making final delivery MAY remove Return-path headers
53 before adding their own.
56 #include <ctype.h>
57 #include <mmapstring.h>
58 #include <stdlib.h>
59 #include <string.h>
61 #ifndef TRUE
62 #define TRUE 1
63 #endif
65 #ifndef FALSE
66 #define FALSE 0
67 #endif
74 #if 0
75 static inline int is_dtext(char ch);
76 #endif
78 static int mailimf_quoted_pair_parse(const char * message, size_t length,
79 size_t * index, char * result);
81 static int mailimf_ccontent_parse(const char * message, size_t length,
82 size_t * index);
84 static int
85 mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
86 size_t * index);
88 static inline int mailimf_comment_parse(const char * message, size_t length,
89 size_t * index);
91 static int mailimf_qcontent_parse(const char * message, size_t length,
92 size_t * index, char * ch);
94 static int mailimf_phrase_parse(const char * message, size_t length,
95 size_t * index, char ** result);
97 static int mailimf_unstructured_parse(const char * message, size_t length,
98 size_t * index, char ** result);
100 static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
101 size_t * index);
103 static int mailimf_day_of_week_parse(const char * message, size_t length,
104 size_t * index, int * result);
106 static int mailimf_day_name_parse(const char * message, size_t length,
107 size_t * index, int * result);
109 static int mailimf_date_parse(const char * message, size_t length,
110 size_t * index,
111 int * pday, int * pmonth, int * pyear);
113 static int mailimf_year_parse(const char * message, size_t length,
114 size_t * index, int * result);
116 static int mailimf_month_parse(const char * message, size_t length,
117 size_t * index, int * result);
119 static int mailimf_month_name_parse(const char * message, size_t length,
120 size_t * index, int * result);
122 static int mailimf_day_parse(const char * message, size_t length,
123 size_t * index, int * result);
125 static int mailimf_time_parse(const char * message, size_t length,
126 size_t * index,
127 int * phour, int * pmin,
128 int * psec,
129 int * zone);
130 static int mailimf_time_of_day_parse(const char * message, size_t length,
131 size_t * index,
132 int * phour, int * pmin,
133 int * psec);
135 static int mailimf_hour_parse(const char * message, size_t length,
136 size_t * index, int * result);
138 static int mailimf_minute_parse(const char * message, size_t length,
139 size_t * index, int * result);
141 static int mailimf_second_parse(const char * message, size_t length,
142 size_t * index, int * result);
144 static int mailimf_zone_parse(const char * message, size_t length,
145 size_t * index, int * result);
147 static int mailimf_name_addr_parse(const char * message, size_t length,
148 size_t * index,
149 char ** pdisplay_name,
150 char ** pangle_addr);
152 static int mailimf_angle_addr_parse(const char * message, size_t length,
153 size_t * index, char ** result);
155 static int mailimf_group_parse(const char * message, size_t length,
156 size_t * index,
157 struct mailimf_group ** result);
159 static int mailimf_display_name_parse(const char * message, size_t length,
160 size_t * index, char ** result);
162 static int mailimf_addr_spec_parse(const char * message, size_t length,
163 size_t * index,
164 char ** address);
166 #if 0
167 static int mailimf_local_part_parse(const char * message, size_t length,
168 size_t * index,
169 char ** result);
171 static int mailimf_domain_parse(const char * message, size_t length,
172 size_t * index,
173 char ** result);
174 #endif
176 #if 0
177 static int mailimf_domain_literal_parse(const char * message, size_t length,
178 size_t * index, char ** result);
179 #endif
181 #if 0
182 static int mailimf_dcontent_parse(const char * message, size_t length,
183 size_t * index, char * result);
184 #endif
186 static int
187 mailimf_orig_date_parse(const char * message, size_t length,
188 size_t * index, struct mailimf_orig_date ** result);
190 static int
191 mailimf_from_parse(const char * message, size_t length,
192 size_t * index, struct mailimf_from ** result);
194 static int
195 mailimf_sender_parse(const char * message, size_t length,
196 size_t * index, struct mailimf_sender ** result);
198 static int
199 mailimf_reply_to_parse(const char * message, size_t length,
200 size_t * index, struct mailimf_reply_to ** result);
202 static int
203 mailimf_to_parse(const char * message, size_t length,
204 size_t * index, struct mailimf_to ** result);
206 static int
207 mailimf_cc_parse(const char * message, size_t length,
208 size_t * index, struct mailimf_cc ** result);
210 static int
211 mailimf_bcc_parse(const char * message, size_t length,
212 size_t * index, struct mailimf_bcc ** result);
214 static int mailimf_message_id_parse(const char * message, size_t length,
215 size_t * index,
216 struct mailimf_message_id ** result);
218 static int
219 mailimf_in_reply_to_parse(const char * message, size_t length,
220 size_t * index,
221 struct mailimf_in_reply_to ** result);
223 #if 0
224 static int mailimf_references_parse(const char * message, size_t length,
225 size_t * index,
226 struct mailimf_references **
227 result);
228 #endif
230 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
231 size_t * index,
232 char ** result);
234 #if 0
235 static int mailimf_id_left_parse(const char * message, size_t length,
236 size_t * index, char ** result);
238 static int mailimf_id_right_parse(const char * message, size_t length,
239 size_t * index, char ** result);
240 #endif
242 #if 0
243 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
244 size_t * index, char ** result);
246 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
247 size_t * index, char ** result);
248 #endif
250 static int mailimf_subject_parse(const char * message, size_t length,
251 size_t * index,
252 struct mailimf_subject ** result);
254 static int mailimf_comments_parse(const char * message, size_t length,
255 size_t * index,
256 struct mailimf_comments ** result);
258 static int mailimf_keywords_parse(const char * message, size_t length,
259 size_t * index,
260 struct mailimf_keywords ** result);
262 static int
263 mailimf_resent_date_parse(const char * message, size_t length,
264 size_t * index, struct mailimf_orig_date ** result);
266 static int
267 mailimf_resent_from_parse(const char * message, size_t length,
268 size_t * index, struct mailimf_from ** result);
270 static int
271 mailimf_resent_sender_parse(const char * message, size_t length,
272 size_t * index, struct mailimf_sender ** result);
274 static int
275 mailimf_resent_to_parse(const char * message, size_t length,
276 size_t * index, struct mailimf_to ** result);
278 static int
279 mailimf_resent_cc_parse(const char * message, size_t length,
280 size_t * index, struct mailimf_cc ** result);
282 static int
283 mailimf_resent_bcc_parse(const char * message, size_t length,
284 size_t * index, struct mailimf_bcc ** result);
286 static int
287 mailimf_resent_msg_id_parse(const char * message, size_t length,
288 size_t * index,
289 struct mailimf_message_id ** result);
291 static int mailimf_return_parse(const char * message, size_t length,
292 size_t * index,
293 struct mailimf_return ** result);
295 static int
296 mailimf_path_parse(const char * message, size_t length,
297 size_t * index, struct mailimf_path ** result);
299 static int
300 mailimf_optional_field_parse(const char * message, size_t length,
301 size_t * index,
302 struct mailimf_optional_field ** result);
304 static int mailimf_field_name_parse(const char * message, size_t length,
305 size_t * index, char ** result);
331 /* *************************************************************** */
333 static inline int is_digit(char ch)
335 return (ch >= '0') && (ch <= '9');
338 static int mailimf_digit_parse(const char * message, size_t length,
339 size_t * index, int * result)
341 size_t cur_token;
343 cur_token = * index;
345 if (cur_token >= length)
346 return MAILIMF_ERROR_PARSE;
348 if (is_digit(message[cur_token])) {
349 * result = message[cur_token] - '0';
350 cur_token ++;
351 * index = cur_token;
352 return MAILIMF_NO_ERROR;
354 else
355 return MAILIMF_ERROR_PARSE;
359 mailimf_number_parse(const char * message, size_t length,
360 size_t * index, uint32_t * result)
362 size_t cur_token;
363 int digit;
364 uint32_t number;
365 int parsed;
366 int r;
368 cur_token = * index;
369 parsed = FALSE;
371 number = 0;
372 while (1) {
373 r = mailimf_digit_parse(message, length, &cur_token, &digit);
374 if (r != MAILIMF_NO_ERROR) {
375 if (r == MAILIMF_ERROR_PARSE)
376 break;
377 else
378 return r;
380 number *= 10;
381 number += digit;
382 parsed = TRUE;
385 if (!parsed)
386 return MAILIMF_ERROR_PARSE;
388 * result = number;
389 * index = cur_token;
391 return MAILIMF_NO_ERROR;
394 int mailimf_char_parse(const char * message, size_t length,
395 size_t * index, char token)
397 size_t cur_token;
399 cur_token = * index;
401 if (cur_token >= length)
402 return MAILIMF_ERROR_PARSE;
404 if (message[cur_token] == token) {
405 cur_token ++;
406 * index = cur_token;
407 return MAILIMF_NO_ERROR;
409 else
410 return MAILIMF_ERROR_PARSE;
413 int mailimf_unstrict_char_parse(const char * message, size_t length,
414 size_t * index, char token)
416 size_t cur_token;
417 int r;
419 cur_token = * index;
421 r = mailimf_cfws_parse(message, length, &cur_token);
422 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
423 return r;
425 r = mailimf_char_parse(message, length, &cur_token, token);
426 if (r != MAILIMF_NO_ERROR)
427 return r;
429 * index = cur_token;
431 return MAILIMF_NO_ERROR;
435 mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
436 size_t * index, char * token,
437 size_t token_length)
439 size_t cur_token;
441 cur_token = * index;
443 if (cur_token + token_length - 1 >= length)
444 return MAILIMF_ERROR_PARSE;
446 if (strncasecmp(message + cur_token, token, token_length) == 0) {
447 cur_token += token_length;
448 * index = cur_token;
449 return MAILIMF_NO_ERROR;
451 else
452 return MAILIMF_ERROR_PARSE;
455 static int mailimf_oparenth_parse(const char * message, size_t length,
456 size_t * index)
458 return mailimf_char_parse(message, length, index, '(');
461 static int mailimf_cparenth_parse(const char * message, size_t length,
462 size_t * index)
464 return mailimf_char_parse(message, length, index, ')');
467 static int mailimf_comma_parse(const char * message, size_t length,
468 size_t * index)
470 return mailimf_unstrict_char_parse(message, length, index, ',');
473 static int mailimf_dquote_parse(const char * message, size_t length,
474 size_t * index)
476 return mailimf_char_parse(message, length, index, '\"');
479 static int mailimf_colon_parse(const char * message, size_t length,
480 size_t * index)
482 return mailimf_unstrict_char_parse(message, length, index, ':');
485 static int mailimf_semi_colon_parse(const char * message, size_t length,
486 size_t * index)
488 return mailimf_unstrict_char_parse(message, length, index, ';');
491 static int mailimf_plus_parse(const char * message, size_t length,
492 size_t * index)
494 return mailimf_unstrict_char_parse(message, length, index, '+');
497 static int mailimf_minus_parse(const char * message, size_t length,
498 size_t * index)
500 return mailimf_unstrict_char_parse(message, length, index, '-');
503 static int mailimf_lower_parse(const char * message, size_t length,
504 size_t * index)
506 return mailimf_unstrict_char_parse(message, length, index, '<');
509 static int mailimf_greater_parse(const char * message, size_t length,
510 size_t * index)
512 return mailimf_unstrict_char_parse(message, length, index, '>');
515 #if 0
516 static int mailimf_obracket_parse(const char * message, size_t length,
517 size_t * index)
519 return mailimf_unstrict_char_parse(message, length, index, '[');
522 static int mailimf_cbracket_parse(const char * message, size_t length,
523 size_t * index)
525 return mailimf_unstrict_char_parse(message, length, index, ']');
527 #endif
529 static int mailimf_at_sign_parse(const char * message, size_t length,
530 size_t * index)
532 return mailimf_unstrict_char_parse(message, length, index, '@');
535 static int mailimf_point_parse(const char * message, size_t length,
536 size_t * index)
538 return mailimf_unstrict_char_parse(message, length, index, '.');
542 mailimf_custom_string_parse(const char * message, size_t length,
543 size_t * index, char ** result,
544 int (* is_custom_char)(char))
546 size_t begin;
547 size_t end;
548 char * gstr;
550 begin = * index;
552 end = begin;
554 if (end >= length)
555 return MAILIMF_ERROR_PARSE;
557 while (is_custom_char(message[end])) {
558 end ++;
559 if (end >= length)
560 break;
563 if (end != begin) {
565 gstr = strndup(message + begin, end - begin);
567 gstr = malloc(end - begin + 1);
568 if (gstr == NULL)
569 return MAILIMF_ERROR_MEMORY;
570 strncpy(gstr, message + begin, end - begin);
571 gstr[end - begin] = '\0';
573 * index = end;
574 * result = gstr;
575 return MAILIMF_NO_ERROR;
577 else
578 return MAILIMF_ERROR_PARSE;
587 typedef int mailimf_struct_parser(const char * message, size_t length,
588 size_t * index, void * result);
590 typedef int mailimf_struct_destructor(void * result);
593 static int
594 mailimf_struct_multiple_parse(const char * message, size_t length,
595 size_t * index, clist ** result,
596 mailimf_struct_parser * parser,
597 mailimf_struct_destructor * destructor)
599 clist * struct_list;
600 size_t cur_token;
601 void * value;
602 int r;
603 int res;
605 cur_token = * index;
607 r = parser(message, length, &cur_token, &value);
608 if (r != MAILIMF_NO_ERROR) {
609 res = r;
610 goto err;
613 struct_list = clist_new();
614 if (struct_list == NULL) {
615 destructor(value);
616 res = MAILIMF_ERROR_MEMORY;
617 goto err;
620 r = clist_append(struct_list, value);
621 if (r < 0) {
622 destructor(value);
623 res = MAILIMF_ERROR_MEMORY;
624 goto free;
627 while (1) {
628 r = parser(message, length, &cur_token, &value);
629 if (r != MAILIMF_NO_ERROR) {
630 if (r == MAILIMF_ERROR_PARSE)
631 break;
632 else {
633 res = r;
634 goto free;
637 r = clist_append(struct_list, value);
638 if (r < 0) {
639 (* destructor)(value);
640 res = MAILIMF_ERROR_MEMORY;
641 goto free;
645 * result = struct_list;
646 * index = cur_token;
648 return MAILIMF_NO_ERROR;
650 free:
651 clist_foreach(struct_list, (clist_func) destructor, NULL);
652 clist_free(struct_list);
653 err:
654 return res;
659 static int
660 mailimf_struct_list_parse(const char * message, size_t length,
661 size_t * index, clist ** result,
662 char symbol,
663 mailimf_struct_parser * parser,
664 mailimf_struct_destructor * destructor)
666 clist * struct_list;
667 size_t cur_token;
668 void * value;
669 size_t final_token;
670 int r;
671 int res;
673 cur_token = * index;
675 r = parser(message, length, &cur_token, &value);
676 if (r != MAILIMF_NO_ERROR) {
677 res = r;
678 goto err;
681 struct_list = clist_new();
682 if (struct_list == NULL) {
683 destructor(value);
684 res = MAILIMF_ERROR_MEMORY;
685 goto err;
688 r = clist_append(struct_list, value);
689 if (r < 0) {
690 destructor(value);
691 res = MAILIMF_ERROR_MEMORY;
692 goto free;
695 final_token = cur_token;
697 while (1) {
698 r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol);
699 if (r != MAILIMF_NO_ERROR) {
700 if (r == MAILIMF_ERROR_PARSE)
701 break;
702 else {
703 res = r;
704 goto free;
708 r = parser(message, length, &cur_token, &value);
709 if (r != MAILIMF_NO_ERROR) {
710 if (r == MAILIMF_ERROR_PARSE)
711 break;
712 else {
713 res = r;
714 goto free;
718 r = clist_append(struct_list, value);
719 if (r < 0) {
720 destructor(value);
721 res = MAILIMF_ERROR_MEMORY;
722 goto free;
725 final_token = cur_token;
728 * result = struct_list;
729 * index = final_token;
731 return MAILIMF_NO_ERROR;
733 free:
734 clist_foreach(struct_list, (clist_func) destructor, NULL);
735 clist_free(struct_list);
736 err:
737 return res;
740 static inline int mailimf_wsp_parse(const char * message, size_t length,
741 size_t * index)
743 size_t cur_token;
745 cur_token = * index;
747 if (cur_token >= length)
748 return MAILIMF_ERROR_PARSE;
750 if ((message[cur_token] != ' ') && (message[cur_token] != '\t'))
751 return MAILIMF_ERROR_PARSE;
753 cur_token ++;
754 * index = cur_token;
756 return MAILIMF_NO_ERROR;
760 int mailimf_crlf_parse(const char * message, size_t length, size_t * index)
762 size_t cur_token;
763 int r;
765 cur_token = * index;
767 r = mailimf_char_parse(message, length, &cur_token, '\r');
768 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
769 return r;
771 r = mailimf_char_parse(message, length, &cur_token, '\n');
772 if (r != MAILIMF_NO_ERROR)
773 return r;
775 * index = cur_token;
776 return MAILIMF_NO_ERROR;
779 static int mailimf_unstrict_crlf_parse(const char * message,
780 size_t length, size_t * index)
782 size_t cur_token;
783 int r;
785 cur_token = * index;
787 mailimf_cfws_parse(message, length, &cur_token);
789 r = mailimf_char_parse(message, length, &cur_token, '\r');
790 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
791 return r;
793 r = mailimf_char_parse(message, length, &cur_token, '\n');
794 if (r != MAILIMF_NO_ERROR)
795 return r;
797 * index = cur_token;
798 return MAILIMF_NO_ERROR;
801 /* ************************************************************************ */
805 /* RFC 2822 grammar */
808 NO-WS-CTL = %d1-8 / ; US-ASCII control characters
809 %d11 / ; that do not include the
810 %d12 / ; carriage return, line feed,
811 %d14-31 / ; and white space characters
812 %d127
815 static inline int is_no_ws_ctl(char ch)
817 if ((ch == 9) || (ch == 10) || (ch == 13))
818 return FALSE;
820 if (ch == 127)
821 return TRUE;
823 return (ch >= 1) && (ch <= 31);
827 text = %d1-9 / ; Characters excluding CR and LF
828 %d11 /
829 %d12 /
830 %d14-127 /
831 obs-text
835 specials = "(" / ")" / ; Special characters used in
836 "<" / ">" / ; other parts of the syntax
837 "[" / "]" /
838 ":" / ";" /
839 "@" / "\" /
840 "," / "." /
841 DQUOTE
845 quoted-pair = ("\" text) / obs-qp
848 static inline int mailimf_quoted_pair_parse(const char * message, size_t length,
849 size_t * index, char * result)
851 size_t cur_token;
853 cur_token = * index;
855 if (cur_token + 1 >= length)
856 return MAILIMF_ERROR_PARSE;
858 if (message[cur_token] != '\\')
859 return MAILIMF_ERROR_PARSE;
861 cur_token ++;
862 * result = message[cur_token];
863 cur_token ++;
864 * index = cur_token;
866 return MAILIMF_NO_ERROR;
870 FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
871 obs-FWS
874 int mailimf_fws_parse(const char * message, size_t length, size_t * index)
876 size_t cur_token;
877 size_t final_token;
878 int fws_1;
879 int fws_2;
880 int fws_3;
881 int r;
883 cur_token = * index;
885 fws_1 = FALSE;
886 while (1) {
887 r = mailimf_wsp_parse(message, length, &cur_token);
888 if (r != MAILIMF_NO_ERROR) {
889 if (r == MAILIMF_ERROR_PARSE)
890 break;
891 else
892 return r;
894 fws_1 = TRUE;
896 final_token = cur_token;
898 r = mailimf_crlf_parse(message, length, &cur_token);
899 switch (r) {
900 case MAILIMF_NO_ERROR:
901 fws_2 = TRUE;
902 break;
903 case MAILIMF_ERROR_PARSE:
904 fws_2 = FALSE;
905 break;
906 default:
907 return r;
910 fws_3 = FALSE;
911 if (fws_2) {
912 while (1) {
913 r = mailimf_wsp_parse(message, length, &cur_token);
914 if (r != MAILIMF_NO_ERROR) {
915 if (r == MAILIMF_ERROR_PARSE)
916 break;
917 else
918 return r;
920 fws_3 = TRUE;
924 if ((!fws_1) && (!fws_3))
925 return MAILIMF_ERROR_PARSE;
927 if (!fws_3)
928 cur_token = final_token;
930 * index = cur_token;
932 return MAILIMF_NO_ERROR;
937 ctext = NO-WS-CTL / ; Non white space controls
939 %d33-39 / ; The rest of the US-ASCII
940 %d42-91 / ; characters not including "(",
941 %d93-126 ; ")", or "\"
944 static inline int is_ctext(char ch)
946 unsigned char uch = (unsigned char) ch;
948 if (is_no_ws_ctl(ch))
949 return TRUE;
951 if (uch < 33)
952 return FALSE;
954 if ((uch == 40) || (uch == 41))
955 return FALSE;
957 if (uch == 92)
958 return FALSE;
960 if (uch == 127)
961 return FALSE;
963 return TRUE;
967 ccontent = ctext / quoted-pair / comment
970 static inline int mailimf_ccontent_parse(const char * message, size_t length,
971 size_t * index)
973 size_t cur_token;
974 char ch;
975 int r;
977 cur_token = * index;
979 if (cur_token >= length)
980 return MAILIMF_ERROR_PARSE;
982 if (is_ctext(message[cur_token])) {
983 cur_token ++;
985 else {
986 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
988 if (r == MAILIMF_ERROR_PARSE)
989 r = mailimf_comment_parse(message, length, &cur_token);
991 if (r == MAILIMF_ERROR_PARSE)
992 return r;
995 * index = cur_token;
997 return MAILIMF_NO_ERROR;
1001 [FWS] ccontent
1004 static inline int
1005 mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
1006 size_t * index)
1008 size_t cur_token;
1009 int r;
1011 cur_token = * index;
1013 r = mailimf_fws_parse(message, length, &cur_token);
1014 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1015 return r;
1017 r = mailimf_ccontent_parse(message, length, &cur_token);
1018 if (r != MAILIMF_NO_ERROR)
1019 return r;
1021 * index = cur_token;
1023 return MAILIMF_NO_ERROR;
1027 comment = "(" *([FWS] ccontent) [FWS] ")"
1030 static inline int mailimf_comment_parse(const char * message, size_t length,
1031 size_t * index)
1033 size_t cur_token;
1034 int r;
1036 cur_token = * index;
1038 r = mailimf_oparenth_parse(message, length, &cur_token);
1039 if (r != MAILIMF_NO_ERROR)
1040 return r;
1042 while (1) {
1043 r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token);
1044 if (r != MAILIMF_NO_ERROR) {
1045 if (r == MAILIMF_ERROR_PARSE)
1046 break;
1047 else
1048 return r;
1052 r = mailimf_fws_parse(message, length, &cur_token);
1053 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1054 return r;
1056 r = mailimf_cparenth_parse(message, length, &cur_token);
1057 if (r != MAILIMF_NO_ERROR)
1058 return r;
1060 * index = cur_token;
1062 return MAILIMF_NO_ERROR;
1066 [FWS] comment
1069 static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length,
1070 size_t * index)
1072 size_t cur_token;
1073 int r;
1075 cur_token = * index;
1077 r = mailimf_fws_parse(message, length, &cur_token);
1078 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1079 return r;
1081 r = mailimf_comment_parse(message, length, &cur_token);
1082 if (r != MAILIMF_NO_ERROR)
1083 return r;
1085 * index = cur_token;
1087 return MAILIMF_NO_ERROR;
1091 CFWS = *([FWS] comment) (([FWS] comment) / FWS)
1094 int mailimf_cfws_parse(const char * message, size_t length,
1095 size_t * index)
1097 size_t cur_token;
1098 int has_comment;
1099 int r;
1101 cur_token = * index;
1103 has_comment = FALSE;
1104 while (1) {
1105 r = mailimf_cfws_fws_comment_parse(message, length, &cur_token);
1106 if (r != MAILIMF_NO_ERROR) {
1107 if (r == MAILIMF_ERROR_PARSE)
1108 break;
1109 else
1110 return r;
1112 has_comment = TRUE;
1115 if (!has_comment) {
1116 r = mailimf_fws_parse(message, length, &cur_token);
1117 if (r != MAILIMF_NO_ERROR)
1118 return r;
1121 * index = cur_token;
1123 return MAILIMF_NO_ERROR;
1127 atext = ALPHA / DIGIT / ; Any character except controls,
1128 "!" / "#" / ; SP, and specials.
1129 "$" / "%" / ; Used for atoms
1130 "&" / "'" /
1131 "*" / "+" /
1132 "-" / "/" /
1133 "=" / "?" /
1134 "^" / "_" /
1135 "`" / "{" /
1136 "|" / "}" /
1140 static inline int is_atext(char ch)
1142 switch (ch) {
1143 case ' ':
1144 case '\t':
1145 case '\n':
1146 case '\r':
1147 #if 0
1148 case '(':
1149 case ')':
1150 #endif
1151 case '<':
1152 case '>':
1153 #if 0
1154 case '@':
1155 #endif
1156 case ',':
1157 case '"':
1158 case ':':
1159 case ';':
1160 return FALSE;
1161 default:
1162 return TRUE;
1167 atom = [CFWS] 1*atext [CFWS]
1170 int mailimf_atom_parse(const char * message, size_t length,
1171 size_t * index, char ** result)
1173 size_t cur_token;
1174 int r;
1175 int res;
1176 char * atom;
1177 size_t end;
1179 cur_token = * index;
1181 r = mailimf_cfws_parse(message, length, &cur_token);
1182 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1183 res = r;
1184 goto err;
1187 end = cur_token;
1188 if (end >= length) {
1189 res = MAILIMF_ERROR_PARSE;
1190 goto err;
1193 while (is_atext(message[end])) {
1194 end ++;
1195 if (end >= length)
1196 break;
1198 if (end == cur_token) {
1199 res = MAILIMF_ERROR_PARSE;
1200 goto err;
1203 atom = malloc(end - cur_token + 1);
1204 if (atom == NULL) {
1205 res = MAILIMF_ERROR_MEMORY;
1206 goto err;
1208 strncpy(atom, message + cur_token, end - cur_token);
1209 atom[end - cur_token] = '\0';
1211 cur_token = end;
1213 * index = cur_token;
1214 * result = atom;
1216 return MAILIMF_NO_ERROR;
1218 err:
1219 return res;
1222 int mailimf_fws_atom_parse(const char * message, size_t length,
1223 size_t * index, char ** result)
1225 size_t cur_token;
1226 int r;
1227 int res;
1228 char * atom;
1229 size_t end;
1231 cur_token = * index;
1233 r = mailimf_fws_parse(message, length, &cur_token);
1234 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1235 res = r;
1236 goto err;
1239 end = cur_token;
1240 if (end >= length) {
1241 res = MAILIMF_ERROR_PARSE;
1242 goto err;
1245 while (is_atext(message[end])) {
1246 end ++;
1247 if (end >= length)
1248 break;
1250 if (end == cur_token) {
1251 res = MAILIMF_ERROR_PARSE;
1252 goto err;
1255 atom = malloc(end - cur_token + 1);
1256 if (atom == NULL) {
1257 res = MAILIMF_ERROR_MEMORY;
1258 goto err;
1260 strncpy(atom, message + cur_token, end - cur_token);
1261 atom[end - cur_token] = '\0';
1263 cur_token = end;
1265 * index = cur_token;
1266 * result = atom;
1268 return MAILIMF_NO_ERROR;
1270 err:
1271 return res;
1275 dot-atom = [CFWS] dot-atom-text [CFWS]
1278 #if 0
1279 static int mailimf_dot_atom_parse(const char * message, size_t length,
1280 size_t * index, char ** result)
1282 return mailimf_atom_parse(message, length, index, result);
1284 #endif
1287 dot-atom-text = 1*atext *("." 1*atext)
1290 #if 0
1291 static int
1292 mailimf_dot_atom_text_parse(const char * message, size_t length,
1293 size_t * index, char ** result)
1295 return mailimf_atom_parse(message, length, index, result);
1297 #endif
1300 qtext = NO-WS-CTL / ; Non white space controls
1302 %d33 / ; The rest of the US-ASCII
1303 %d35-91 / ; characters not including "\"
1304 %d93-126 ; or the quote character
1307 static inline int is_qtext(char ch)
1309 unsigned char uch = (unsigned char) ch;
1311 if (is_no_ws_ctl(ch))
1312 return TRUE;
1314 if (uch < 33)
1315 return FALSE;
1317 if (uch == 34)
1318 return FALSE;
1320 if (uch == 92)
1321 return FALSE;
1323 if (uch == 127)
1324 return FALSE;
1326 return TRUE;
1330 qcontent = qtext / quoted-pair
1333 static int mailimf_qcontent_parse(const char * message, size_t length,
1334 size_t * index, char * result)
1336 size_t cur_token;
1337 char ch;
1338 int r;
1340 cur_token = * index;
1342 if (cur_token >= length)
1343 return MAILIMF_ERROR_PARSE;
1345 if (is_qtext(message[cur_token])) {
1346 ch = message[cur_token];
1347 cur_token ++;
1349 else {
1350 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
1352 if (r != MAILIMF_NO_ERROR)
1353 return r;
1356 * result = ch;
1357 * index = cur_token;
1359 return MAILIMF_NO_ERROR;
1363 quoted-string = [CFWS]
1364 DQUOTE *([FWS] qcontent) [FWS] DQUOTE
1365 [CFWS]
1368 int mailimf_quoted_string_parse(const char * message, size_t length,
1369 size_t * index, char ** result)
1371 size_t cur_token;
1372 MMAPString * gstr;
1373 char ch;
1374 char * str;
1375 int r;
1376 int res;
1378 cur_token = * index;
1380 r = mailimf_cfws_parse(message, length, &cur_token);
1381 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1382 res = r;
1383 goto err;
1386 r = mailimf_dquote_parse(message, length, &cur_token);
1387 if (r != MAILIMF_NO_ERROR) {
1388 res = r;
1389 goto err;
1392 gstr = mmap_string_new("");
1393 if (gstr == NULL) {
1394 res = MAILIMF_ERROR_MEMORY;
1395 goto err;
1398 #if 0
1399 if (mmap_string_append_c(gstr, '\"') == NULL) {
1400 res = MAILIMF_ERROR_MEMORY;
1401 goto free_gstr;
1403 #endif
1405 while (1) {
1406 r = mailimf_fws_parse(message, length, &cur_token);
1407 if (r == MAILIMF_NO_ERROR) {
1408 if (mmap_string_append_c(gstr, ' ') == NULL) {
1409 res = MAILIMF_ERROR_MEMORY;
1410 goto free_gstr;
1413 else if (r != MAILIMF_ERROR_PARSE) {
1414 res = r;
1415 goto free_gstr;
1418 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1419 if (r == MAILIMF_NO_ERROR) {
1420 if (mmap_string_append_c(gstr, ch) == NULL) {
1421 res = MAILIMF_ERROR_MEMORY;
1422 goto free_gstr;
1425 else if (r == MAILIMF_ERROR_PARSE)
1426 break;
1427 else {
1428 res = r;
1429 goto free_gstr;
1433 r = mailimf_dquote_parse(message, length, &cur_token);
1434 if (r != MAILIMF_NO_ERROR) {
1435 res = r;
1436 goto free_gstr;
1439 #if 0
1440 if (mmap_string_append_c(gstr, '\"') == NULL) {
1441 res = MAILIMF_ERROR_MEMORY;
1442 goto free_gstr;
1444 #endif
1446 str = strdup(gstr->str);
1447 if (str == NULL) {
1448 res = MAILIMF_ERROR_MEMORY;
1449 goto free_gstr;
1451 mmap_string_free(gstr);
1453 * index = cur_token;
1454 * result = str;
1456 return MAILIMF_NO_ERROR;
1458 free_gstr:
1459 mmap_string_free(gstr);
1460 err:
1461 return res;
1464 int mailimf_fws_quoted_string_parse(const char * message, size_t length,
1465 size_t * index, char ** result)
1467 size_t cur_token;
1468 MMAPString * gstr;
1469 char ch;
1470 char * str;
1471 int r;
1472 int res;
1474 cur_token = * index;
1476 r = mailimf_fws_parse(message, length, &cur_token);
1477 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1478 res = r;
1479 goto err;
1482 r = mailimf_dquote_parse(message, length, &cur_token);
1483 if (r != MAILIMF_NO_ERROR) {
1484 res = r;
1485 goto err;
1488 gstr = mmap_string_new("");
1489 if (gstr == NULL) {
1490 res = MAILIMF_ERROR_MEMORY;
1491 goto err;
1494 #if 0
1495 if (mmap_string_append_c(gstr, '\"') == NULL) {
1496 res = MAILIMF_ERROR_MEMORY;
1497 goto free_gstr;
1499 #endif
1501 while (1) {
1502 r = mailimf_fws_parse(message, length, &cur_token);
1503 if (r == MAILIMF_NO_ERROR) {
1504 if (mmap_string_append_c(gstr, ' ') == NULL) {
1505 res = MAILIMF_ERROR_MEMORY;
1506 goto free_gstr;
1509 else if (r != MAILIMF_ERROR_PARSE) {
1510 res = r;
1511 goto free_gstr;
1514 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1515 if (r == MAILIMF_NO_ERROR) {
1516 if (mmap_string_append_c(gstr, ch) == NULL) {
1517 res = MAILIMF_ERROR_MEMORY;
1518 goto free_gstr;
1521 else if (r == MAILIMF_ERROR_PARSE)
1522 break;
1523 else {
1524 res = r;
1525 goto free_gstr;
1529 r = mailimf_dquote_parse(message, length, &cur_token);
1530 if (r != MAILIMF_NO_ERROR) {
1531 res = r;
1532 goto free_gstr;
1535 #if 0
1536 if (mmap_string_append_c(gstr, '\"') == NULL) {
1537 res = MAILIMF_ERROR_MEMORY;
1538 goto free_gstr;
1540 #endif
1542 str = strdup(gstr->str);
1543 if (str == NULL) {
1544 res = MAILIMF_ERROR_MEMORY;
1545 goto free_gstr;
1547 mmap_string_free(gstr);
1549 * index = cur_token;
1550 * result = str;
1552 return MAILIMF_NO_ERROR;
1554 free_gstr:
1555 mmap_string_free(gstr);
1556 err:
1557 return res;
1561 word = atom / quoted-string
1564 int mailimf_word_parse(const char * message, size_t length,
1565 size_t * index, char ** result)
1567 size_t cur_token;
1568 char * word;
1569 int r;
1571 cur_token = * index;
1573 r = mailimf_atom_parse(message, length, &cur_token, &word);
1575 if (r == MAILIMF_ERROR_PARSE)
1576 r = mailimf_quoted_string_parse(message, length, &cur_token, &word);
1578 if (r != MAILIMF_NO_ERROR)
1579 return r;
1581 * result = word;
1582 * index = cur_token;
1584 return MAILIMF_NO_ERROR;
1587 int mailimf_fws_word_parse(const char * message, size_t length,
1588 size_t * index, char ** result)
1590 size_t cur_token;
1591 char * word;
1592 int r;
1594 cur_token = * index;
1596 r = mailimf_fws_atom_parse(message, length, &cur_token, &word);
1598 if (r == MAILIMF_ERROR_PARSE)
1599 r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word);
1601 if (r != MAILIMF_NO_ERROR)
1602 return r;
1604 * result = word;
1605 * index = cur_token;
1607 return MAILIMF_NO_ERROR;
1611 phrase = 1*word / obs-phrase
1614 static int mailimf_phrase_parse(const char * message, size_t length,
1615 size_t * index, char ** result)
1617 MMAPString * gphrase;
1618 char * word;
1619 int first;
1620 size_t cur_token;
1621 int r;
1622 int res;
1623 char * str;
1625 cur_token = * index;
1627 gphrase = mmap_string_new("");
1628 if (gphrase == NULL) {
1629 res = MAILIMF_ERROR_MEMORY;
1630 goto err;
1633 first = TRUE;
1635 while (1) {
1636 r = mailimf_fws_word_parse(message, length, &cur_token, &word);
1637 if (r == MAILIMF_NO_ERROR) {
1638 if (!first) {
1639 if (mmap_string_append_c(gphrase, ' ') == NULL) {
1640 mailimf_word_free(word);
1641 res = MAILIMF_ERROR_MEMORY;
1642 goto free;
1645 if (mmap_string_append(gphrase, word) == NULL) {
1646 mailimf_word_free(word);
1647 res = MAILIMF_ERROR_MEMORY;
1648 goto free;
1650 mailimf_word_free(word);
1651 first = FALSE;
1653 else if (r == MAILIMF_ERROR_PARSE)
1654 break;
1655 else {
1656 res = r;
1657 goto free;
1661 if (first) {
1662 res = MAILIMF_ERROR_PARSE;
1663 goto free;
1666 str = strdup(gphrase->str);
1667 if (str == NULL) {
1668 res = MAILIMF_ERROR_MEMORY;
1669 goto free;
1671 mmap_string_free(gphrase);
1673 * result = str;
1674 * index = cur_token;
1676 return MAILIMF_NO_ERROR;
1678 free:
1679 mmap_string_free(gphrase);
1680 err:
1681 return res;
1685 utext = NO-WS-CTL / ; Non white space controls
1686 %d33-126 / ; The rest of US-ASCII
1687 obs-utext
1689 added : WSP
1692 enum {
1693 UNSTRUCTURED_START,
1694 UNSTRUCTURED_CR,
1695 UNSTRUCTURED_LF,
1696 UNSTRUCTURED_WSP,
1697 UNSTRUCTURED_OUT
1700 static int mailimf_unstructured_parse(const char * message, size_t length,
1701 size_t * index, char ** result)
1703 size_t cur_token;
1704 int state;
1705 size_t begin;
1706 size_t terminal;
1707 char * str;
1709 cur_token = * index;
1712 while (1) {
1713 int r;
1715 r = mailimf_wsp_parse(message, length, &cur_token);
1716 if (r == MAILIMF_NO_ERROR) {
1717 /* do nothing */
1719 else if (r == MAILIMF_ERROR_PARSE)
1720 break;
1721 else {
1722 return r;
1726 state = UNSTRUCTURED_START;
1727 begin = cur_token;
1728 terminal = cur_token;
1730 while (state != UNSTRUCTURED_OUT) {
1732 switch(state) {
1733 case UNSTRUCTURED_START:
1734 if (cur_token >= length)
1735 return MAILIMF_ERROR_PARSE;
1737 terminal = cur_token;
1738 switch(message[cur_token]) {
1739 case '\r':
1740 state = UNSTRUCTURED_CR;
1741 break;
1742 case '\n':
1743 state = UNSTRUCTURED_LF;
1744 break;
1745 default:
1746 state = UNSTRUCTURED_START;
1747 break;
1749 break;
1750 case UNSTRUCTURED_CR:
1751 if (cur_token >= length)
1752 return MAILIMF_ERROR_PARSE;
1754 switch(message[cur_token]) {
1755 case '\n':
1756 state = UNSTRUCTURED_LF;
1757 break;
1758 default:
1759 state = UNSTRUCTURED_START;
1760 break;
1762 break;
1764 case UNSTRUCTURED_LF:
1765 if (cur_token >= length) {
1766 state = UNSTRUCTURED_OUT;
1767 break;
1770 switch(message[cur_token]) {
1771 case '\t':
1772 case ' ':
1773 state = UNSTRUCTURED_WSP;
1774 break;
1775 default:
1776 state = UNSTRUCTURED_OUT;
1777 break;
1779 break;
1780 case UNSTRUCTURED_WSP:
1781 if (cur_token >= length)
1782 return MAILIMF_ERROR_PARSE;
1784 switch(message[cur_token]) {
1785 case '\r':
1786 state = UNSTRUCTURED_CR;
1787 break;
1788 case '\n':
1789 state = UNSTRUCTURED_LF;
1790 break;
1791 default:
1792 state = UNSTRUCTURED_START;
1793 break;
1795 break;
1798 cur_token ++;
1801 str = malloc(terminal - begin + 1);
1802 if (str == NULL)
1803 return MAILIMF_ERROR_MEMORY;
1804 strncpy(str, message + begin, terminal - begin);
1805 str[terminal - begin] = '\0';
1807 * index = terminal;
1808 * result = str;
1810 return MAILIMF_NO_ERROR;
1814 static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
1815 size_t * index)
1817 size_t cur_token;
1818 int state;
1819 size_t terminal;
1821 cur_token = * index;
1823 state = UNSTRUCTURED_START;
1824 terminal = cur_token;
1826 while (state != UNSTRUCTURED_OUT) {
1828 switch(state) {
1829 case UNSTRUCTURED_START:
1830 if (cur_token >= length)
1831 return MAILIMF_ERROR_PARSE;
1832 terminal = cur_token;
1833 switch(message[cur_token]) {
1834 case '\r':
1835 state = UNSTRUCTURED_CR;
1836 break;
1837 case '\n':
1838 state = UNSTRUCTURED_LF;
1839 break;
1840 default:
1841 state = UNSTRUCTURED_START;
1842 break;
1844 break;
1845 case UNSTRUCTURED_CR:
1846 if (cur_token >= length)
1847 return MAILIMF_ERROR_PARSE;
1848 switch(message[cur_token]) {
1849 case '\n':
1850 state = UNSTRUCTURED_LF;
1851 break;
1852 default:
1853 state = UNSTRUCTURED_START;
1854 break;
1856 break;
1857 case UNSTRUCTURED_LF:
1858 if (cur_token >= length) {
1859 state = UNSTRUCTURED_OUT;
1860 break;
1862 switch(message[cur_token]) {
1863 case '\t':
1864 case ' ':
1865 state = UNSTRUCTURED_WSP;
1866 break;
1867 default:
1868 state = UNSTRUCTURED_OUT;
1869 break;
1871 break;
1872 case UNSTRUCTURED_WSP:
1873 if (cur_token >= length)
1874 return MAILIMF_ERROR_PARSE;
1875 switch(message[cur_token]) {
1876 case '\r':
1877 state = UNSTRUCTURED_CR;
1878 break;
1879 case '\n':
1880 state = UNSTRUCTURED_LF;
1881 break;
1882 default:
1883 state = UNSTRUCTURED_START;
1884 break;
1886 break;
1889 cur_token ++;
1892 * index = terminal;
1894 return MAILIMF_NO_ERROR;
1898 int mailimf_ignore_field_parse(const char * message, size_t length,
1899 size_t * index)
1901 int has_field;
1902 size_t cur_token;
1903 int state;
1904 size_t terminal;
1906 has_field = FALSE;
1907 cur_token = * index;
1909 terminal = cur_token;
1910 state = UNSTRUCTURED_START;
1912 /* check if this is not a beginning CRLF */
1914 if (cur_token >= length)
1915 return MAILIMF_ERROR_PARSE;
1917 switch (message[cur_token]) {
1918 case '\r':
1919 return MAILIMF_ERROR_PARSE;
1920 case '\n':
1921 return MAILIMF_ERROR_PARSE;
1924 while (state != UNSTRUCTURED_OUT) {
1926 switch(state) {
1927 case UNSTRUCTURED_START:
1928 if (cur_token >= length)
1929 return MAILIMF_ERROR_PARSE;
1931 switch(message[cur_token]) {
1932 case '\r':
1933 state = UNSTRUCTURED_CR;
1934 break;
1935 case '\n':
1936 state = UNSTRUCTURED_LF;
1937 break;
1938 case ':':
1939 has_field = TRUE;
1940 state = UNSTRUCTURED_START;
1941 break;
1942 default:
1943 state = UNSTRUCTURED_START;
1944 break;
1946 break;
1947 case UNSTRUCTURED_CR:
1948 if (cur_token >= length)
1949 return MAILIMF_ERROR_PARSE;
1951 switch(message[cur_token]) {
1952 case '\n':
1953 state = UNSTRUCTURED_LF;
1954 break;
1955 case ':':
1956 has_field = TRUE;
1957 state = UNSTRUCTURED_START;
1958 break;
1959 default:
1960 state = UNSTRUCTURED_START;
1961 break;
1963 break;
1964 case UNSTRUCTURED_LF:
1965 if (cur_token >= length) {
1966 terminal = cur_token;
1967 state = UNSTRUCTURED_OUT;
1968 break;
1971 switch(message[cur_token]) {
1972 case '\t':
1973 case ' ':
1974 state = UNSTRUCTURED_WSP;
1975 break;
1976 default:
1977 terminal = cur_token;
1978 state = UNSTRUCTURED_OUT;
1979 break;
1981 break;
1982 case UNSTRUCTURED_WSP:
1983 if (cur_token >= length)
1984 return MAILIMF_ERROR_PARSE;
1986 switch(message[cur_token]) {
1987 case '\r':
1988 state = UNSTRUCTURED_CR;
1989 break;
1990 case '\n':
1991 state = UNSTRUCTURED_LF;
1992 break;
1993 case ':':
1994 has_field = TRUE;
1995 state = UNSTRUCTURED_START;
1996 break;
1997 default:
1998 state = UNSTRUCTURED_START;
1999 break;
2001 break;
2004 cur_token ++;
2007 if (!has_field)
2008 return MAILIMF_ERROR_PARSE;
2010 * index = terminal;
2012 return MAILIMF_NO_ERROR;
2017 date-time = [ day-of-week "," ] date FWS time [CFWS]
2020 int mailimf_date_time_parse(const char * message, size_t length,
2021 size_t * index,
2022 struct mailimf_date_time ** result)
2024 size_t cur_token;
2025 int day_of_week;
2026 struct mailimf_date_time * date_time;
2027 int day;
2028 int month;
2029 int year;
2030 int hour;
2031 int min;
2032 int sec;
2033 int zone;
2034 int r;
2036 cur_token = * index;
2038 day_of_week = -1;
2039 r = mailimf_day_of_week_parse(message, length, &cur_token, &day_of_week);
2040 if (r == MAILIMF_NO_ERROR) {
2041 r = mailimf_comma_parse(message, length, &cur_token);
2042 if (r != MAILIMF_NO_ERROR)
2043 return r;
2045 else if (r != MAILIMF_ERROR_PARSE)
2046 return r;
2048 r = mailimf_date_parse(message, length, &cur_token, &day, &month, &year);
2049 if (r != MAILIMF_NO_ERROR)
2050 return r;
2052 r = mailimf_fws_parse(message, length, &cur_token);
2053 if (r != MAILIMF_NO_ERROR)
2054 return r;
2056 r = mailimf_time_parse(message, length, &cur_token,
2057 &hour, &min, &sec, &zone);
2058 if (r != MAILIMF_NO_ERROR)
2059 return r;
2061 date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone);
2062 if (date_time == NULL)
2063 return MAILIMF_ERROR_MEMORY;
2065 * index = cur_token;
2066 * result = date_time;
2068 return MAILIMF_NO_ERROR;
2072 day-of-week = ([FWS] day-name) / obs-day-of-week
2075 static int mailimf_day_of_week_parse(const char * message, size_t length,
2076 size_t * index, int * result)
2078 size_t cur_token;
2079 int day_of_week;
2080 int r;
2082 cur_token = * index;
2084 r = mailimf_cfws_parse(message, length, &cur_token);
2085 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2086 return r;
2088 r = mailimf_day_name_parse(message, length, &cur_token, &day_of_week);
2089 if (r != MAILIMF_NO_ERROR)
2090 return r;
2092 * index = cur_token;
2093 * result = day_of_week;
2095 return MAILIMF_NO_ERROR;
2099 day-name = "Mon" / "Tue" / "Wed" / "Thu" /
2100 "Fri" / "Sat" / "Sun"
2103 struct mailimf_token_value {
2104 int value;
2105 char * str;
2108 static struct mailimf_token_value day_names[] = {
2109 {1, "Mon"},
2110 {2, "Tue"},
2111 {3, "Wed"},
2112 {4, "Thu"},
2113 {5, "Fri"},
2114 {6, "Sat"},
2115 {7, "Sun"},
2118 enum {
2119 DAY_NAME_START,
2120 DAY_NAME_T,
2121 DAY_NAME_S
2124 static int guess_day_name(const char * message, size_t length, size_t index)
2126 int state;
2128 state = DAY_NAME_START;
2130 while (1) {
2132 if (index >= length)
2133 return -1;
2135 switch(state) {
2136 case DAY_NAME_START:
2137 switch((char) toupper((unsigned char) message[index])) {
2138 case 'M': /* Mon */
2139 return 1;
2140 break;
2141 case 'T': /* Tue Thu */
2142 state = DAY_NAME_T;
2143 break;
2144 case 'W': /* Wed */
2145 return 3;
2146 case 'F':
2147 return 5;
2148 case 'S': /* Sat Sun */
2149 state = DAY_NAME_S;
2150 break;
2151 default:
2152 return -1;
2154 break;
2155 case DAY_NAME_T:
2156 switch((char) toupper((unsigned char) message[index])) {
2157 case 'U':
2158 return 2;
2159 case 'H':
2160 return 4;
2161 default:
2162 return -1;
2164 break;
2165 case DAY_NAME_S:
2166 switch((char) toupper((unsigned char) message[index])) {
2167 case 'A':
2168 return 6;
2169 case 'U':
2170 return 7;
2171 default:
2172 return -1;
2174 break;
2177 index ++;
2181 static int mailimf_day_name_parse(const char * message, size_t length,
2182 size_t * index, int * result)
2184 size_t cur_token;
2185 int day_of_week;
2186 int guessed_day;
2187 int r;
2189 cur_token = * index;
2191 guessed_day = guess_day_name(message, length, cur_token);
2192 if (guessed_day == -1)
2193 return MAILIMF_ERROR_PARSE;
2195 r = mailimf_token_case_insensitive_parse(message, length,
2196 &cur_token,
2197 day_names[guessed_day - 1].str);
2198 if (r != MAILIMF_NO_ERROR)
2199 return r;
2201 day_of_week = guessed_day;
2203 * result = day_of_week;
2204 * index = cur_token;
2206 return MAILIMF_NO_ERROR;
2210 date = day month year
2213 static int mailimf_date_parse(const char * message, size_t length,
2214 size_t * index,
2215 int * pday, int * pmonth, int * pyear)
2217 size_t cur_token;
2218 int day;
2219 int month;
2220 int year;
2221 int r;
2223 cur_token = * index;
2225 r = mailimf_day_parse(message, length, &cur_token, &day);
2226 if (r != MAILIMF_NO_ERROR)
2227 return r;
2229 r = mailimf_month_parse(message, length, &cur_token, &month);
2230 if (r != MAILIMF_NO_ERROR)
2231 return r;
2233 r = mailimf_year_parse(message, length, &cur_token, &year);
2234 if (r != MAILIMF_NO_ERROR)
2235 return r;
2237 * pday = day;
2238 * pmonth = month;
2239 * pyear = year;
2241 * index = cur_token;
2243 return MAILIMF_NO_ERROR;
2247 year = 4*DIGIT / obs-year
2250 static int mailimf_year_parse(const char * message, size_t length,
2251 size_t * index, int * result)
2253 uint32_t number;
2254 size_t cur_token;
2255 int r;
2257 cur_token = * index;
2259 r = mailimf_cfws_parse(message, length, &cur_token);
2260 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2261 return r;
2263 r = mailimf_number_parse(message, length, &cur_token, &number);
2264 if (r != MAILIMF_NO_ERROR)
2265 return r;
2267 * index = cur_token;
2268 * result = number;
2270 return MAILIMF_NO_ERROR;
2274 month = (FWS month-name FWS) / obs-month
2277 static int mailimf_month_parse(const char * message, size_t length,
2278 size_t * index, int * result)
2280 size_t cur_token;
2281 int month;
2282 int r;
2284 cur_token = * index;
2286 r = mailimf_cfws_parse(message, length, &cur_token);
2287 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2288 return r;
2290 r = mailimf_month_name_parse(message, length, &cur_token, &month);
2291 if (r != MAILIMF_NO_ERROR)
2292 return r;
2294 * result = month;
2295 * index = cur_token;
2297 return MAILIMF_NO_ERROR;
2301 month-name = "Jan" / "Feb" / "Mar" / "Apr" /
2302 "May" / "Jun" / "Jul" / "Aug" /
2303 "Sep" / "Oct" / "Nov" / "Dec"
2306 static struct mailimf_token_value month_names[] = {
2307 {1, "Jan"},
2308 {2, "Feb"},
2309 {3, "Mar"},
2310 {4, "Apr"},
2311 {5, "May"},
2312 {6, "Jun"},
2313 {7, "Jul"},
2314 {8, "Aug"},
2315 {9, "Sep"},
2316 {10, "Oct"},
2317 {11, "Nov"},
2318 {12, "Dec"},
2321 enum {
2322 MONTH_START,
2323 MONTH_J,
2324 MONTH_JU,
2325 MONTH_M,
2326 MONTH_MA,
2327 MONTH_A
2330 static int guess_month(const char * message, size_t length, size_t index)
2332 int state;
2334 state = MONTH_START;
2336 while (1) {
2338 if (index >= length)
2339 return -1;
2341 switch(state) {
2342 case MONTH_START:
2343 switch((char) toupper((unsigned char) message[index])) {
2344 case 'J': /* Jan Jun Jul */
2345 state = MONTH_J;
2346 break;
2347 case 'F': /* Feb */
2348 return 2;
2349 case 'M': /* Mar May */
2350 state = MONTH_M;
2351 break;
2352 case 'A': /* Apr Aug */
2353 state = MONTH_A;
2354 break;
2355 case 'S': /* Sep */
2356 return 9;
2357 case 'O': /* Oct */
2358 return 10;
2359 case 'N': /* Nov */
2360 return 11;
2361 case 'D': /* Dec */
2362 return 12;
2363 default:
2364 return -1;
2366 break;
2367 case MONTH_J:
2368 switch((char) toupper((unsigned char) message[index])) {
2369 case 'A':
2370 return 1;
2371 case 'U':
2372 state = MONTH_JU;
2373 break;
2374 default:
2375 return -1;
2377 break;
2378 case MONTH_JU:
2379 switch((char) toupper((unsigned char) message[index])) {
2380 case 'N':
2381 return 6;
2382 case 'L':
2383 return 7;
2384 default:
2385 return -1;
2387 break;
2388 case MONTH_M:
2389 switch((char) toupper((unsigned char) message[index])) {
2390 case 'A':
2391 state = MONTH_MA;
2392 break;
2393 default:
2394 return -1;
2396 break;
2397 case MONTH_MA:
2398 switch((char) toupper((unsigned char) message[index])) {
2399 case 'Y':
2400 return 5;
2401 case 'R':
2402 return 3;
2403 default:
2404 return -1;
2406 break;
2407 case MONTH_A:
2408 switch((char) toupper((unsigned char) message[index])) {
2409 case 'P':
2410 return 4;
2411 case 'U':
2412 return 8;
2413 default:
2414 return -1;
2416 break;
2419 index ++;
2423 static int mailimf_month_name_parse(const char * message, size_t length,
2424 size_t * index, int * result)
2426 size_t cur_token;
2427 int month;
2428 int guessed_month;
2429 int r;
2431 cur_token = * index;
2433 guessed_month = guess_month(message, length, cur_token);
2434 if (guessed_month == -1)
2435 return MAILIMF_ERROR_PARSE;
2437 r = mailimf_token_case_insensitive_parse(message, length,
2438 &cur_token,
2439 month_names[guessed_month - 1].str);
2440 if (r != MAILIMF_NO_ERROR)
2441 return r;
2443 month = guessed_month;
2445 * result = month;
2446 * index = cur_token;
2448 return MAILIMF_NO_ERROR;
2452 day = ([FWS] 1*2DIGIT) / obs-day
2455 static int mailimf_day_parse(const char * message, size_t length,
2456 size_t * index, int * result)
2458 size_t cur_token;
2459 uint32_t day;
2460 int r;
2462 cur_token = * index;
2464 r = mailimf_cfws_parse(message, length, &cur_token);
2465 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2466 return r;
2468 r = mailimf_number_parse(message, length, &cur_token, &day);
2469 if (r != MAILIMF_NO_ERROR)
2470 return r;
2472 * result = day;
2473 * index = cur_token;
2475 return MAILIMF_NO_ERROR;
2479 time = time-of-day FWS zone
2482 static int mailimf_time_parse(const char * message, size_t length,
2483 size_t * index,
2484 int * phour, int * pmin,
2485 int * psec,
2486 int * pzone)
2488 size_t cur_token;
2489 int hour;
2490 int min;
2491 int sec;
2492 int zone;
2493 int r;
2495 cur_token = * index;
2497 r = mailimf_cfws_parse(message, length, &cur_token);
2498 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2499 return r;
2501 r = mailimf_time_of_day_parse(message, length, &cur_token,
2502 &hour, &min, &sec);
2503 if (r != MAILIMF_NO_ERROR)
2504 return r;
2506 r = mailimf_fws_parse(message, length, &cur_token);
2507 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2508 return r;
2510 r = mailimf_zone_parse(message, length, &cur_token, &zone);
2511 if (r == MAILIMF_NO_ERROR) {
2512 /* do nothing */
2514 else if (r == MAILIMF_ERROR_PARSE) {
2515 zone = 0;
2517 else {
2518 return r;
2521 * phour = hour;
2522 * pmin = min;
2523 * psec = sec;
2524 * pzone = zone;
2526 * index = cur_token;
2528 return MAILIMF_NO_ERROR;
2532 time-of-day = hour ":" minute [ ":" second ]
2535 static int mailimf_time_of_day_parse(const char * message, size_t length,
2536 size_t * index,
2537 int * phour, int * pmin,
2538 int * psec)
2540 int hour;
2541 int min;
2542 int sec;
2543 size_t cur_token;
2544 int r;
2546 cur_token = * index;
2548 r = mailimf_hour_parse(message, length, &cur_token, &hour);
2549 if (r != MAILIMF_NO_ERROR)
2550 return r;
2552 r = mailimf_colon_parse(message, length, &cur_token);
2553 if (r != MAILIMF_NO_ERROR)
2554 return r;
2556 r = mailimf_minute_parse(message, length, &cur_token, &min);
2557 if (r != MAILIMF_NO_ERROR)
2558 return r;
2560 r = mailimf_colon_parse(message, length, &cur_token);
2561 if (r == MAILIMF_NO_ERROR) {
2562 r = mailimf_second_parse(message, length, &cur_token, &sec);
2563 if (r != MAILIMF_NO_ERROR)
2564 return r;
2566 else if (r == MAILIMF_ERROR_PARSE)
2567 sec = 0;
2568 else
2569 return r;
2571 * phour = hour;
2572 * pmin = min;
2573 * psec = sec;
2574 * index = cur_token;
2576 return MAILIMF_NO_ERROR;
2580 hour = 2DIGIT / obs-hour
2583 static int mailimf_hour_parse(const char * message, size_t length,
2584 size_t * index, int * result)
2586 uint32_t hour;
2587 int r;
2589 r = mailimf_number_parse(message, length, index, &hour);
2590 if (r != MAILIMF_NO_ERROR)
2591 return r;
2593 * result = hour;
2595 return MAILIMF_NO_ERROR;
2599 minute = 2DIGIT / obs-minute
2602 static int mailimf_minute_parse(const char * message, size_t length,
2603 size_t * index, int * result)
2605 uint32_t minute;
2606 int r;
2608 r = mailimf_number_parse(message, length, index, &minute);
2609 if (r != MAILIMF_NO_ERROR)
2610 return r;
2612 * result = minute;
2614 return MAILIMF_NO_ERROR;
2618 second = 2DIGIT / obs-second
2621 static int mailimf_second_parse(const char * message, size_t length,
2622 size_t * index, int * result)
2624 uint32_t second;
2625 int r;
2627 r = mailimf_number_parse(message, length, index, &second);
2628 if (r != MAILIMF_NO_ERROR)
2629 return r;
2631 * result = second;
2633 return MAILIMF_NO_ERROR;
2637 zone = (( "+" / "-" ) 4DIGIT) / obs-zone
2641 obs-zone = "UT" / "GMT" / ; Universal Time
2642 ; North American UT
2643 ; offsets
2644 "EST" / "EDT" / ; Eastern: - 5/ - 4
2645 "CST" / "CDT" / ; Central: - 6/ - 5
2646 "MST" / "MDT" / ; Mountain: - 7/ - 6
2647 "PST" / "PDT" / ; Pacific: - 8/ - 7
2649 %d65-73 / ; Military zones - "A"
2650 %d75-90 / ; through "I" and "K"
2651 %d97-105 / ; through "Z", both
2652 %d107-122 ; upper and lower case
2655 enum {
2656 STATE_ZONE_1 = 0,
2657 STATE_ZONE_2 = 1,
2658 STATE_ZONE_3 = 2,
2659 STATE_ZONE_OK = 3,
2660 STATE_ZONE_ERR = 4,
2661 STATE_ZONE_CONT = 5,
2664 static int mailimf_zone_parse(const char * message, size_t length,
2665 size_t * index, int * result)
2667 uint32_t zone;
2668 int sign;
2669 size_t cur_token;
2670 int r;
2672 cur_token = * index;
2674 if (cur_token + 1 < length) {
2675 if ((message[cur_token] == 'U') && (message[cur_token + 1] == 'T')) {
2676 * result = TRUE;
2677 * index = cur_token + 2;
2679 return MAILIMF_NO_ERROR;
2683 if (cur_token + 2 < length) {
2684 int state;
2686 state = STATE_ZONE_1;
2688 while (state <= 2) {
2689 switch (state) {
2690 case STATE_ZONE_1:
2691 switch (message[cur_token]) {
2692 case 'G':
2693 if (message[cur_token + 1] == 'M' && message[cur_token + 2] == 'T') {
2694 zone = 0;
2695 state = STATE_ZONE_OK;
2697 else {
2698 state = STATE_ZONE_ERR;
2700 break;
2701 case 'E':
2702 zone = -5;
2703 state = STATE_ZONE_2;
2704 break;
2705 case 'C':
2706 zone = -6;
2707 state = STATE_ZONE_2;
2708 break;
2709 case 'M':
2710 zone = -7;
2711 state = STATE_ZONE_2;
2712 break;
2713 case 'P':
2714 zone = -8;
2715 state = STATE_ZONE_2;
2716 break;
2717 default:
2718 state = STATE_ZONE_CONT;
2719 break;
2721 break;
2722 case STATE_ZONE_2:
2723 switch (message[cur_token + 1]) {
2724 case 'S':
2725 state = STATE_ZONE_3;
2726 break;
2727 case 'D':
2728 zone ++;
2729 state = STATE_ZONE_3;
2730 break;
2731 default:
2732 state = STATE_ZONE_ERR;
2733 break;
2735 break;
2736 case STATE_ZONE_3:
2737 if (message[cur_token + 2] == 'T') {
2738 zone *= 100;
2739 state = STATE_ZONE_OK;
2741 else
2742 state = STATE_ZONE_ERR;
2743 break;
2747 switch (state) {
2748 case STATE_ZONE_OK:
2749 * result = zone;
2750 * index = cur_token + 3;
2751 return MAILIMF_NO_ERROR;
2753 case STATE_ZONE_ERR:
2754 return MAILIMF_ERROR_PARSE;
2758 sign = 1;
2759 r = mailimf_plus_parse(message, length, &cur_token);
2760 if (r == MAILIMF_NO_ERROR)
2761 sign = 1;
2763 if (r == MAILIMF_ERROR_PARSE) {
2764 r = mailimf_minus_parse(message, length, &cur_token);
2765 if (r == MAILIMF_NO_ERROR)
2766 sign = -1;
2769 if (r == MAILIMF_NO_ERROR) {
2770 /* do nothing */
2772 else if (r == MAILIMF_ERROR_PARSE)
2773 sign = 1;
2774 else
2775 return r;
2777 r = mailimf_number_parse(message, length, &cur_token, &zone);
2778 if (r != MAILIMF_NO_ERROR)
2779 return r;
2781 zone = zone * sign;
2783 * index = cur_token;
2784 * result = zone;
2786 return MAILIMF_NO_ERROR;
2790 address = mailbox / group
2793 int mailimf_address_parse(const char * message, size_t length,
2794 size_t * index,
2795 struct mailimf_address ** result)
2797 int type;
2798 size_t cur_token;
2799 struct mailimf_mailbox * mailbox;
2800 struct mailimf_group * group;
2801 struct mailimf_address * address;
2802 int r;
2803 int res;
2805 cur_token = * index;
2807 mailbox = NULL;
2808 group = NULL;
2810 type = MAILIMF_ADDRESS_ERROR; /* XXX - removes a gcc warning */
2811 r = mailimf_group_parse(message, length, &cur_token, &group);
2812 if (r == MAILIMF_NO_ERROR)
2813 type = MAILIMF_ADDRESS_GROUP;
2815 if (r == MAILIMF_ERROR_PARSE) {
2816 r = mailimf_mailbox_parse(message, length, &cur_token, &mailbox);
2817 if (r == MAILIMF_NO_ERROR)
2818 type = MAILIMF_ADDRESS_MAILBOX;
2821 if (r != MAILIMF_NO_ERROR) {
2822 res = r;
2823 goto err;
2826 address = mailimf_address_new(type, mailbox, group);
2827 if (address == NULL) {
2828 res = MAILIMF_ERROR_MEMORY;
2829 goto free;
2832 * result = address;
2833 * index = cur_token;
2835 return MAILIMF_NO_ERROR;
2837 free:
2838 if (mailbox != NULL)
2839 mailimf_mailbox_free(mailbox);
2840 if (group != NULL)
2841 mailimf_group_free(group);
2842 err:
2843 return res;
2848 mailbox = name-addr / addr-spec
2852 int mailimf_mailbox_parse(const char * message, size_t length,
2853 size_t * index,
2854 struct mailimf_mailbox ** result)
2856 size_t cur_token;
2857 char * display_name;
2858 struct mailimf_mailbox * mailbox;
2859 char * addr_spec;
2860 int r;
2861 int res;
2863 cur_token = * index;
2864 display_name = NULL;
2865 addr_spec = NULL;
2867 r = mailimf_name_addr_parse(message, length, &cur_token,
2868 &display_name, &addr_spec);
2869 if (r == MAILIMF_ERROR_PARSE)
2870 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2872 if (r != MAILIMF_NO_ERROR) {
2873 res = r;
2874 goto err;
2877 mailbox = mailimf_mailbox_new(display_name, addr_spec);
2878 if (mailbox == NULL) {
2879 res = MAILIMF_ERROR_MEMORY;
2880 goto free;
2883 * result = mailbox;
2884 * index = cur_token;
2886 return MAILIMF_NO_ERROR;
2888 free:
2889 if (display_name != NULL)
2890 mailimf_display_name_free(display_name);
2891 if (addr_spec != NULL)
2892 mailimf_addr_spec_free(addr_spec);
2893 err:
2894 return res;
2898 name-addr = [display-name] angle-addr
2901 static int mailimf_name_addr_parse(const char * message, size_t length,
2902 size_t * index,
2903 char ** pdisplay_name,
2904 char ** pangle_addr)
2906 char * display_name;
2907 char * angle_addr;
2908 size_t cur_token;
2909 int r;
2910 int res;
2912 cur_token = * index;
2914 display_name = NULL;
2915 angle_addr = NULL;
2917 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
2918 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
2919 res = r;
2920 goto err;
2923 r = mailimf_angle_addr_parse(message, length, &cur_token, &angle_addr);
2924 if (r != MAILIMF_NO_ERROR) {
2925 res = r;
2926 goto free_display_name;
2929 * pdisplay_name = display_name;
2930 * pangle_addr = angle_addr;
2931 * index = cur_token;
2933 return MAILIMF_NO_ERROR;
2935 free_display_name:
2936 if (display_name != NULL)
2937 mailimf_display_name_free(display_name);
2938 err:
2939 return res;
2943 angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
2946 static int mailimf_angle_addr_parse(const char * message, size_t length,
2947 size_t * index, char ** result)
2949 size_t cur_token;
2950 char * addr_spec;
2951 int r;
2953 cur_token = * index;
2955 r = mailimf_cfws_parse(message, length, &cur_token);
2956 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2957 return r;
2959 r = mailimf_lower_parse(message, length, &cur_token);
2960 if (r != MAILIMF_NO_ERROR)
2961 return r;
2963 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2964 if (r != MAILIMF_NO_ERROR)
2965 return r;
2967 r = mailimf_greater_parse(message, length, &cur_token);
2968 if (r != MAILIMF_NO_ERROR) {
2969 free(addr_spec);
2970 return r;
2973 * result = addr_spec;
2974 * index = cur_token;
2976 return MAILIMF_NO_ERROR;
2980 group = display-name ":" [mailbox-list / CFWS] ";"
2981 [CFWS]
2984 static int mailimf_group_parse(const char * message, size_t length,
2985 size_t * index,
2986 struct mailimf_group ** result)
2988 size_t cur_token;
2989 char * display_name;
2990 struct mailimf_mailbox_list * mailbox_list;
2991 struct mailimf_group * group;
2992 int r;
2993 int res;
2994 clist * list;
2996 cur_token = * index;
2998 mailbox_list = NULL;
3000 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
3001 if (r != MAILIMF_NO_ERROR) {
3002 res = r;
3003 goto err;
3006 r = mailimf_colon_parse(message, length, &cur_token);
3007 if (r != MAILIMF_NO_ERROR) {
3008 res = r;
3009 goto free_display_name;
3012 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list);
3013 switch (r) {
3014 case MAILIMF_NO_ERROR:
3015 break;
3016 case MAILIMF_ERROR_PARSE:
3017 r = mailimf_cfws_parse(message, length, &cur_token);
3018 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3019 res = r;
3020 goto free_display_name;
3022 list = clist_new();
3023 if (list == NULL) {
3024 res = MAILIMF_ERROR_MEMORY;
3025 goto free_display_name;
3027 mailbox_list = mailimf_mailbox_list_new(list);
3028 if (mailbox_list == NULL) {
3029 res = MAILIMF_ERROR_MEMORY;
3030 clist_free(list);
3031 goto free_display_name;
3033 break;
3034 default:
3035 res = r;
3036 goto free_display_name;
3039 r = mailimf_semi_colon_parse(message, length, &cur_token);
3040 if (r != MAILIMF_NO_ERROR) {
3041 res = r;
3042 goto free_mailbox_list;
3045 group = mailimf_group_new(display_name, mailbox_list);
3046 if (group == NULL) {
3047 res = MAILIMF_ERROR_MEMORY;
3048 goto free_mailbox_list;
3051 * index = cur_token;
3052 * result = group;
3054 return MAILIMF_NO_ERROR;
3056 free_mailbox_list:
3057 mailimf_mailbox_list_free(mailbox_list);
3058 free_display_name:
3059 mailimf_display_name_free(display_name);
3060 err:
3061 return res;
3065 display-name = phrase
3068 static int mailimf_display_name_parse(const char * message, size_t length,
3069 size_t * index, char ** result)
3071 return mailimf_phrase_parse(message, length, index, result);
3075 mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
3079 mailimf_mailbox_list_parse(const char * message, size_t length,
3080 size_t * index,
3081 struct mailimf_mailbox_list ** result)
3083 size_t cur_token;
3084 clist * list;
3085 struct mailimf_mailbox_list * mailbox_list;
3086 int r;
3087 int res;
3089 cur_token = * index;
3091 r = mailimf_struct_list_parse(message, length,
3092 &cur_token, &list, ',',
3093 (mailimf_struct_parser *)
3094 mailimf_mailbox_parse,
3095 (mailimf_struct_destructor *)
3096 mailimf_mailbox_free);
3097 if (r != MAILIMF_NO_ERROR) {
3098 res = r;
3099 goto err;
3102 mailbox_list = mailimf_mailbox_list_new(list);
3103 if (mailbox_list == NULL) {
3104 res = MAILIMF_ERROR_MEMORY;
3105 goto free_list;
3108 * result = mailbox_list;
3109 * index = cur_token;
3111 return MAILIMF_NO_ERROR;
3113 free_list:
3114 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
3115 clist_free(list);
3116 err:
3117 return res;
3121 address-list = (address *("," address)) / obs-addr-list
3126 mailimf_address_list_parse(const char * message, size_t length,
3127 size_t * index,
3128 struct mailimf_address_list ** result)
3130 size_t cur_token;
3131 clist * list;
3132 struct mailimf_address_list * address_list;
3133 int r;
3134 int res;
3136 cur_token = * index;
3138 r = mailimf_struct_list_parse(message, length,
3139 &cur_token, &list, ',',
3140 (mailimf_struct_parser *)
3141 mailimf_address_parse,
3142 (mailimf_struct_destructor *)
3143 mailimf_address_free);
3144 if (r != MAILIMF_NO_ERROR) {
3145 res = r;
3146 goto err;
3149 address_list = mailimf_address_list_new(list);
3150 if (address_list == NULL) {
3151 res = MAILIMF_ERROR_MEMORY;
3152 goto free_list;
3155 * result = address_list;
3156 * index = cur_token;
3158 return MAILIMF_NO_ERROR;
3160 free_list:
3161 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
3162 clist_free(list);
3163 err:
3164 return res;
3168 addr-spec = local-part "@" domain
3172 static int mailimf_addr_spec_parse(const char * message, size_t length,
3173 size_t * index,
3174 char ** result)
3176 size_t cur_token;
3177 #if 0
3178 char * local_part;
3179 char * domain;
3180 #endif
3181 char * addr_spec;
3182 int r;
3183 int res;
3184 size_t begin;
3185 size_t end;
3186 int final;
3187 size_t count;
3188 const char * src;
3189 char * dest;
3190 size_t i;
3192 cur_token = * index;
3194 r = mailimf_cfws_parse(message, length, &cur_token);
3195 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3196 res = r;
3197 goto err;
3200 end = cur_token;
3201 if (end >= length) {
3202 res = MAILIMF_ERROR_PARSE;
3203 goto err;
3206 begin = cur_token;
3208 final = FALSE;
3209 while (1) {
3210 switch (message[end]) {
3211 case '>':
3212 case ',':
3213 case '\r':
3214 case '\n':
3215 case '(':
3216 case ')':
3217 case ':':
3218 case ';':
3219 final = TRUE;
3220 break;
3223 if (final)
3224 break;
3226 end ++;
3227 if (end >= length)
3228 break;
3231 if (end == begin) {
3232 res = MAILIMF_ERROR_PARSE;
3233 goto err;
3236 addr_spec = malloc(end - cur_token + 1);
3237 if (addr_spec == NULL) {
3238 res = MAILIMF_ERROR_MEMORY;
3239 goto err;
3242 count = end - cur_token;
3243 src = message + cur_token;
3244 dest = addr_spec;
3245 for(i = 0 ; i < count ; i ++) {
3246 if ((* src != ' ') && (* src != '\t')) {
3247 * dest = * src;
3248 dest ++;
3250 src ++;
3252 * dest = '\0';
3254 #if 0
3255 strncpy(addr_spec, message + cur_token, end - cur_token);
3256 addr_spec[end - cur_token] = '\0';
3257 #endif
3259 cur_token = end;
3261 #if 0
3262 r = mailimf_local_part_parse(message, length, &cur_token, &local_part);
3263 if (r != MAILIMF_NO_ERROR) {
3264 res = r;
3265 goto err;
3268 r = mailimf_at_sign_parse(message, length, &cur_token);
3269 switch (r) {
3270 case MAILIMF_NO_ERROR:
3271 r = mailimf_domain_parse(message, length, &cur_token, &domain);
3272 if (r != MAILIMF_NO_ERROR) {
3273 res = r;
3274 goto free_local_part;
3276 break;
3278 case MAILIMF_ERROR_PARSE:
3279 domain = NULL;
3280 break;
3282 default:
3283 res = r;
3284 goto free_local_part;
3287 if (domain) {
3288 addr_spec = malloc(strlen(local_part) + strlen(domain) + 2);
3289 if (addr_spec == NULL) {
3290 res = MAILIMF_ERROR_MEMORY;
3291 goto free_domain;
3294 strcpy(addr_spec, local_part);
3295 strcat(addr_spec, "@");
3296 strcat(addr_spec, domain);
3298 mailimf_domain_free(domain);
3299 mailimf_local_part_free(local_part);
3301 else {
3302 addr_spec = local_part;
3304 #endif
3306 * result = addr_spec;
3307 * index = cur_token;
3309 return MAILIMF_NO_ERROR;
3311 #if 0
3312 free_domain:
3313 mailimf_domain_free(domain);
3314 free_local_part:
3315 mailimf_local_part_free(local_part);
3316 #endif
3317 err:
3318 return res;
3322 local-part = dot-atom / quoted-string / obs-local-part
3325 #if 0
3326 static int mailimf_local_part_parse(const char * message, size_t length,
3327 size_t * index,
3328 char ** result)
3330 int r;
3332 r = mailimf_dot_atom_parse(message, length, index, result);
3333 switch (r) {
3334 case MAILIMF_NO_ERROR:
3335 return r;
3336 case MAILIMF_ERROR_PARSE:
3337 break;
3338 default:
3339 return r;
3342 r = mailimf_quoted_string_parse(message, length, index, result);
3343 if (r != MAILIMF_NO_ERROR)
3344 return r;
3346 return MAILIMF_NO_ERROR;
3348 #endif
3351 domain = dot-atom / domain-literal / obs-domain
3354 #if 0
3355 static int mailimf_domain_parse(const char * message, size_t length,
3356 size_t * index,
3357 char ** result)
3359 int r;
3361 r = mailimf_dot_atom_parse(message, length, index, result);
3362 switch (r) {
3363 case MAILIMF_NO_ERROR:
3364 return r;
3365 case MAILIMF_ERROR_PARSE:
3366 break;
3367 default:
3368 return r;
3371 r = mailimf_domain_literal_parse(message, length, index, result);
3372 if (r != MAILIMF_NO_ERROR)
3373 return r;
3375 return MAILIMF_NO_ERROR;
3377 #endif
3380 [FWS] dcontent
3383 #if 0
3384 static int
3385 mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length,
3386 size_t * index)
3388 size_t cur_token;
3389 char ch;
3390 int r;
3392 cur_token = * index;
3394 r = mailimf_cfws_parse(message, length, &cur_token);
3395 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3396 return r;
3398 r = mailimf_dcontent_parse(message, length, &cur_token, &ch);
3399 if (r != MAILIMF_NO_ERROR)
3400 return r;
3402 * index = cur_token;
3404 return MAILIMF_NO_ERROR;
3406 #endif
3409 domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
3412 #if 0
3413 static int mailimf_domain_literal_parse(const char * message, size_t length,
3414 size_t * index, char ** result)
3416 size_t cur_token;
3417 int len;
3418 int begin;
3419 char * domain_literal;
3420 int r;
3422 cur_token = * index;
3424 r = mailimf_cfws_parse(message, length, &cur_token);
3425 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3426 return r;
3428 begin = cur_token;
3429 r = mailimf_obracket_parse(message, length, &cur_token);
3430 if (r != MAILIMF_NO_ERROR)
3431 return r;
3433 while (1) {
3434 r = mailimf_domain_literal_fws_dcontent_parse(message, length,
3435 &cur_token);
3436 if (r == MAILIMF_NO_ERROR) {
3437 /* do nothing */
3439 else if (r == MAILIMF_ERROR_PARSE)
3440 break;
3441 else
3442 return r;
3445 r = mailimf_fws_parse(message, length, &cur_token);
3446 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3447 return r;
3449 r = mailimf_cbracket_parse(message, length, &cur_token);
3450 if (r != MAILIMF_NO_ERROR)
3451 return r;
3453 len = cur_token - begin;
3455 domain_literal = malloc(len + 1);
3456 if (domain_literal == NULL)
3457 return MAILIMF_ERROR_MEMORY;
3458 strncpy(domain_literal, message + begin, len);
3459 domain_literal[len] = '\0';
3461 * result = domain_literal;
3462 * index = cur_token;
3464 return MAILIMF_NO_ERROR;
3466 #endif
3469 dcontent = dtext / quoted-pair
3472 #if 0
3473 static int mailimf_dcontent_parse(const char * message, size_t length,
3474 size_t * index, char * result)
3476 size_t cur_token;
3477 char ch;
3478 int r;
3480 cur_token = * index;
3482 if (cur_token >= length)
3483 return MAILIMF_ERROR_PARSE;
3485 if (is_dtext(message[cur_token])) {
3486 ch = message[cur_token];
3487 cur_token ++;
3489 else {
3490 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
3492 if (r != MAILIMF_NO_ERROR)
3493 return r;
3496 * index = cur_token;
3497 * result = ch;
3499 return MAILIMF_NO_ERROR;
3501 #endif
3505 dtext = NO-WS-CTL / ; Non white space controls
3507 %d33-90 / ; The rest of the US-ASCII
3508 %d94-126 ; characters not including "[",
3509 ; "]", or "\"
3512 #if 0
3513 static inline int is_dtext(char ch)
3515 unsigned char uch = (unsigned char) ch;
3517 if (is_no_ws_ctl(ch))
3518 return TRUE;
3520 if (uch < 33)
3521 return FALSE;
3523 if ((uch >= 91) && (uch <= 93))
3524 return FALSE;
3526 if (uch == 127)
3527 return FALSE;
3529 return TRUE;
3531 #endif
3534 message = (fields / obs-fields)
3535 [CRLF body]
3538 int mailimf_message_parse(const char * message, size_t length,
3539 size_t * index,
3540 struct mailimf_message ** result)
3542 struct mailimf_fields * fields;
3543 struct mailimf_body * body;
3544 struct mailimf_message * msg;
3545 size_t cur_token;
3546 int r;
3547 int res;
3549 cur_token = * index;
3551 r = mailimf_fields_parse(message, length, &cur_token, &fields);
3552 if (r != MAILIMF_NO_ERROR) {
3553 res = r;
3554 goto err;
3557 r = mailimf_crlf_parse(message, length, &cur_token);
3558 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3559 res = r;
3560 goto err;
3563 r = mailimf_body_parse(message, length, &cur_token, &body);
3564 if (r != MAILIMF_NO_ERROR) {
3565 res = r;
3566 goto free_fields;
3569 msg = mailimf_message_new(fields, body);
3570 if (msg == NULL) {
3571 res = MAILIMF_ERROR_MEMORY;
3572 goto free_body;
3575 * index = cur_token;
3576 * result = msg;
3578 return MAILIMF_NO_ERROR;
3580 free_body:
3581 mailimf_body_free(body);
3582 free_fields:
3583 mailimf_fields_free(fields);
3584 err:
3585 return res;
3589 body = *(*998text CRLF) *998text
3592 int mailimf_body_parse(const char * message, size_t length,
3593 size_t * index,
3594 struct mailimf_body ** result)
3596 size_t cur_token;
3597 struct mailimf_body * body;
3599 cur_token = * index;
3601 body = mailimf_body_new(message + cur_token, length - cur_token);
3602 if (body == NULL)
3603 return MAILIMF_ERROR_MEMORY;
3605 cur_token = length;
3607 * result = body;
3608 * index = cur_token;
3610 return MAILIMF_NO_ERROR;
3614 CHANGE TO THE RFC 2822
3616 original :
3618 fields = *(trace
3619 *(resent-date /
3620 resent-from /
3621 resent-sender /
3622 resent-to /
3623 resent-cc /
3624 resent-bcc /
3625 resent-msg-id))
3626 *(orig-date /
3627 from /
3628 sender /
3629 reply-to /
3630 to /
3631 cc /
3632 bcc /
3633 message-id /
3634 in-reply-to /
3635 references /
3636 subject /
3637 comments /
3638 keywords /
3639 optional-field)
3641 INTO THE FOLLOWING :
3645 resent-fields-list = *(resent-date /
3646 resent-from /
3647 resent-sender /
3648 resent-to /
3649 resent-cc /
3650 resent-bcc /
3651 resent-msg-id))
3654 #if 0
3655 enum {
3656 RESENT_HEADER_START,
3659 static int guess_resent_header_type(char * message,
3660 size_t length, size_t index)
3662 int r;
3664 r = mailimf_token_case_insensitive_parse(message,
3665 length, &index, "Resent-");
3666 if (r != MAILIMF_NO_ERROR)
3667 return MAILIMF_RESENT_FIELD_NONE;
3669 if (index >= length)
3670 return MAILIMF_RESENT_FIELD_NONE;
3672 switch(toupper(message[index])) {
3673 case 'D':
3674 return MAILIMF_RESENT_FIELD_DATE;
3675 case 'F':
3676 return MAILIMF_RESENT_FIELD_FROM;
3677 case 'S':
3678 return MAILIMF_RESENT_FIELD_SENDER;
3679 case 'T':
3680 return MAILIMF_RESENT_FIELD_TO;
3681 case 'C':
3682 return MAILIMF_RESENT_FIELD_CC;
3683 case 'B':
3684 return MAILIMF_RESENT_FIELD_BCC;
3685 case 'M':
3686 return MAILIMF_RESENT_FIELD_MSG_ID;
3687 default:
3688 return MAILIMF_RESENT_FIELD_NONE;
3691 #endif
3693 #if 0
3694 static int
3695 mailimf_resent_field_parse(const char * message, size_t length,
3696 size_t * index,
3697 struct mailimf_resent_field ** result)
3699 struct mailimf_orig_date * resent_date;
3700 struct mailimf_from * resent_from;
3701 struct mailimf_sender * resent_sender;
3702 struct mailimf_to* resent_to;
3703 struct mailimf_cc * resent_cc;
3704 struct mailimf_bcc * resent_bcc;
3705 struct mailimf_message_id * resent_msg_id;
3706 size_t cur_token;
3707 int type;
3708 struct mailimf_resent_field * resent_field;
3709 int r;
3710 int res;
3712 cur_token = * index;
3714 resent_date = NULL;
3715 resent_from = NULL;
3716 resent_sender = NULL;
3717 resent_to = NULL;
3718 resent_cc = NULL;
3719 resent_bcc = NULL;
3720 resent_msg_id = NULL;
3722 type = guess_resent_header_type(message, length, cur_token);
3724 switch(type) {
3725 case MAILIMF_RESENT_FIELD_DATE:
3726 r = mailimf_resent_date_parse(message, length, &cur_token,
3727 &resent_date);
3728 if (r != MAILIMF_NO_ERROR) {
3729 res = r;
3730 goto free_resent;
3732 break;
3733 case MAILIMF_RESENT_FIELD_FROM:
3734 r = mailimf_resent_from_parse(message, length, &cur_token,
3735 &resent_from);
3736 if (r != MAILIMF_NO_ERROR) {
3737 res = r;
3738 goto free_resent;
3740 break;
3741 case MAILIMF_RESENT_FIELD_SENDER:
3742 r = mailimf_resent_sender_parse(message, length, &cur_token,
3743 &resent_sender);
3744 if (r != MAILIMF_NO_ERROR) {
3745 res = r;
3746 goto free_resent;
3748 break;
3749 case MAILIMF_RESENT_FIELD_TO:
3750 r = mailimf_resent_to_parse(message, length, &cur_token,
3751 &resent_to);
3752 if (r != MAILIMF_NO_ERROR) {
3753 res = r;
3754 goto free_resent;
3756 break;
3757 case MAILIMF_RESENT_FIELD_CC:
3758 r= mailimf_resent_cc_parse(message, length, &cur_token,
3759 &resent_cc);
3760 if (r != MAILIMF_NO_ERROR) {
3761 res = r;
3762 goto free_resent;
3764 break;
3765 case MAILIMF_RESENT_FIELD_BCC:
3766 r = mailimf_resent_bcc_parse(message, length, &cur_token,
3767 &resent_bcc);
3768 if (r != MAILIMF_NO_ERROR) {
3769 res = r;
3770 goto free_resent;
3772 break;
3773 case MAILIMF_RESENT_FIELD_MSG_ID:
3774 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
3775 &resent_msg_id);
3776 if (r != MAILIMF_NO_ERROR) {
3777 res = r;
3778 goto free_resent;
3780 break;
3781 default:
3782 res = MAILIMF_ERROR_PARSE;
3783 goto free_resent;
3786 resent_field = mailimf_resent_field_new(type, resent_date,
3787 resent_from, resent_sender,
3788 resent_to, resent_cc,
3789 resent_bcc, resent_msg_id);
3790 if (resent_field == NULL) {
3791 res = MAILIMF_ERROR_MEMORY;
3792 goto free_resent;
3795 * result = resent_field;
3796 * index = cur_token;
3798 return MAILIMF_NO_ERROR;
3800 free_resent:
3801 if (resent_msg_id != NULL)
3802 mailimf_message_id_free(resent_msg_id);
3803 if (resent_bcc != NULL)
3804 mailimf_bcc_free(resent_bcc);
3805 if (resent_cc != NULL)
3806 mailimf_cc_free(resent_cc);
3807 if (resent_to != NULL)
3808 mailimf_to_free(resent_to);
3809 if (resent_sender != NULL)
3810 mailimf_sender_free(resent_sender);
3811 if (resent_from != NULL)
3812 mailimf_from_free(resent_from);
3813 if (resent_date != NULL)
3814 mailimf_orig_date_free(resent_date);
3815 err:
3816 return res;
3818 #endif
3820 #if 0
3821 static int
3822 mailimf_resent_fields_list_parse(const char * message, size_t length,
3823 size_t * index,
3824 struct mailimf_resent_fields_list ** result)
3826 clist * list;
3827 size_t cur_token;
3828 struct mailimf_resent_fields_list * resent_fields_list;
3829 int r;
3830 int res;
3832 cur_token = * index;
3833 list = NULL;
3835 r = mailimf_struct_multiple_parse(message, length, &cur_token, &list,
3836 (mailimf_struct_parser *)
3837 mailimf_resent_field_parse,
3838 (mailimf_struct_destructor *)
3839 mailimf_resent_field_free);
3840 if (r != MAILIMF_NO_ERROR) {
3841 res = r;
3842 goto err;
3845 resent_fields_list = mailimf_resent_fields_list_new(list);
3846 if (resent_fields_list == NULL) {
3847 res = MAILIMF_ERROR_MEMORY;
3848 goto free_list;
3851 * result = resent_fields_list;
3852 * index = cur_token;
3854 return MAILIMF_NO_ERROR;
3856 free_list:
3857 clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL);
3858 clist_free(list);
3859 err:
3860 return res;
3862 #endif
3865 ([trace]
3866 [resent-fields-list])
3869 #if 0
3870 static int
3871 mailimf_trace_resent_fields_parse(const char * message, size_t length,
3872 size_t * index,
3873 struct mailimf_trace_resent_fields ** result)
3875 size_t cur_token;
3876 struct mailimf_return * return_path;
3877 struct mailimf_resent_fields_list * resent_fields;
3878 struct mailimf_trace_resent_fields * trace_resent_fields;
3879 int res;
3880 int r;
3882 cur_token = * index;
3884 return_path = NULL;
3885 resent_fields = NULL;
3887 r = mailimf_return_parse(message, length, &cur_token,
3888 &return_path);
3889 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3890 res = r;
3891 goto err;
3894 r = mailimf_resent_fields_list_parse(message, length, &cur_token,
3895 &resent_fields);
3896 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3897 res = r;
3898 goto err;
3901 if ((return_path == NULL) && (resent_fields == NULL)) {
3902 res = MAILIMF_ERROR_PARSE;
3903 goto err;
3906 trace_resent_fields = mailimf_trace_resent_fields_new(return_path,
3907 resent_fields);
3908 if (trace_resent_fields == NULL) {
3909 res = MAILIMF_ERROR_MEMORY;
3910 goto free_resent_fields;
3913 * result = trace_resent_fields;
3914 * index = cur_token;
3916 return MAILIMF_NO_ERROR;
3918 free_resent_fields:
3919 if (resent_fields != NULL)
3920 mailimf_resent_fields_list_free(resent_fields);
3921 if (return_path != NULL)
3922 mailimf_return_free(return_path);
3923 err:
3924 return res;
3926 #endif
3929 delivering-info = *([trace]
3930 [resent-fields-list])
3933 #if 0
3934 static int
3935 mailimf_delivering_info_parse(const char * message, size_t length,
3936 size_t * index,
3937 struct mailimf_delivering_info ** result)
3939 size_t cur_token;
3940 clist * list;
3941 struct mailimf_delivering_info * delivering_info;
3942 int r;
3943 int res;
3945 cur_token = * index;
3947 r = mailimf_struct_multiple_parse(message, length, &cur_token,
3948 &list,
3949 (mailimf_struct_parser *)
3950 mailimf_trace_resent_fields_parse,
3951 (mailimf_struct_destructor *)
3952 mailimf_trace_resent_fields_free);
3953 if (r != MAILIMF_NO_ERROR) {
3954 res = r;
3955 goto err;
3958 delivering_info = mailimf_delivering_info_new(list);
3959 if (delivering_info == NULL) {
3960 res = MAILIMF_ERROR_MEMORY;
3961 goto free_list;
3964 * result = delivering_info;
3965 * index = cur_token;
3967 return MAILIMF_NO_ERROR;
3969 free_list:
3970 clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL);
3971 clist_free(list);
3972 err:
3973 return res;
3975 #endif
3978 field = delivering-info /
3979 orig-date /
3980 from /
3981 sender /
3982 reply-to /
3983 to /
3984 cc /
3985 bcc /
3986 message-id /
3987 in-reply-to /
3988 references /
3989 subject /
3990 comments /
3991 keywords /
3992 optional-field
3995 enum {
3996 HEADER_START,
3997 HEADER_C,
3998 HEADER_R,
3999 HEADER_RE,
4000 HEADER_S,
4001 HEADER_RES,
4004 static int guess_header_type(const char * message, size_t length, size_t index)
4006 int state;
4007 int r;
4009 state = HEADER_START;
4011 while (1) {
4013 if (index >= length)
4014 return MAILIMF_FIELD_NONE;
4016 switch(state) {
4017 case HEADER_START:
4018 switch((char) toupper((unsigned char) message[index])) {
4019 case 'B':
4020 return MAILIMF_FIELD_BCC;
4021 case 'C':
4022 state = HEADER_C;
4023 break;
4024 case 'D':
4025 return MAILIMF_FIELD_ORIG_DATE;
4026 case 'F':
4027 return MAILIMF_FIELD_FROM;
4028 case 'I':
4029 return MAILIMF_FIELD_IN_REPLY_TO;
4030 case 'K':
4031 return MAILIMF_FIELD_KEYWORDS;
4032 case 'M':
4033 return MAILIMF_FIELD_MESSAGE_ID;
4034 case 'R':
4035 state = HEADER_R;
4036 break;
4037 case 'T':
4038 return MAILIMF_FIELD_TO;
4039 break;
4040 case 'S':
4041 state = HEADER_S;
4042 break;
4043 default:
4044 return MAILIMF_FIELD_NONE;
4046 break;
4047 case HEADER_C:
4048 switch((char) toupper((unsigned char) message[index])) {
4049 case 'O':
4050 return MAILIMF_FIELD_COMMENTS;
4051 case 'C':
4052 return MAILIMF_FIELD_CC;
4053 default:
4054 return MAILIMF_FIELD_NONE;
4056 break;
4057 case HEADER_R:
4058 switch((char) toupper((unsigned char) message[index])) {
4059 case 'E':
4060 state = HEADER_RE;
4061 break;
4062 default:
4063 return MAILIMF_FIELD_NONE;
4065 break;
4066 case HEADER_RE:
4067 switch((char) toupper((unsigned char) message[index])) {
4068 case 'F':
4069 return MAILIMF_FIELD_REFERENCES;
4070 case 'P':
4071 return MAILIMF_FIELD_REPLY_TO;
4072 case 'S':
4073 state = HEADER_RES;
4074 break;
4075 case 'T':
4076 return MAILIMF_FIELD_RETURN_PATH;
4077 default:
4078 return MAILIMF_FIELD_NONE;
4080 break;
4081 case HEADER_S:
4082 switch((char) toupper((unsigned char) message[index])) {
4083 case 'E':
4084 return MAILIMF_FIELD_SENDER;
4085 case 'U':
4086 return MAILIMF_FIELD_SUBJECT;
4087 default:
4088 return MAILIMF_FIELD_NONE;
4090 break;
4092 case HEADER_RES:
4093 r = mailimf_token_case_insensitive_parse(message,
4094 length, &index, "ent-");
4095 if (r != MAILIMF_NO_ERROR)
4096 return MAILIMF_FIELD_NONE;
4098 if (index >= length)
4099 return MAILIMF_FIELD_NONE;
4101 switch((char) toupper((unsigned char) message[index])) {
4102 case 'D':
4103 return MAILIMF_FIELD_RESENT_DATE;
4104 case 'F':
4105 return MAILIMF_FIELD_RESENT_FROM;
4106 case 'S':
4107 return MAILIMF_FIELD_RESENT_SENDER;
4108 case 'T':
4109 return MAILIMF_FIELD_RESENT_TO;
4110 case 'C':
4111 return MAILIMF_FIELD_RESENT_CC;
4112 case 'B':
4113 return MAILIMF_FIELD_RESENT_BCC;
4114 case 'M':
4115 return MAILIMF_FIELD_RESENT_MSG_ID;
4116 default:
4117 return MAILIMF_FIELD_NONE;
4119 break;
4121 index ++;
4125 static int mailimf_field_parse(const char * message, size_t length,
4126 size_t * index,
4127 struct mailimf_field ** result)
4129 size_t cur_token;
4130 int type;
4131 struct mailimf_return * return_path;
4132 struct mailimf_orig_date * resent_date;
4133 struct mailimf_from * resent_from;
4134 struct mailimf_sender * resent_sender;
4135 struct mailimf_to* resent_to;
4136 struct mailimf_cc * resent_cc;
4137 struct mailimf_bcc * resent_bcc;
4138 struct mailimf_message_id * resent_msg_id;
4139 struct mailimf_orig_date * orig_date;
4140 struct mailimf_from * from;
4141 struct mailimf_sender * sender;
4142 struct mailimf_reply_to * reply_to;
4143 struct mailimf_to * to;
4144 struct mailimf_cc * cc;
4145 struct mailimf_bcc * bcc;
4146 struct mailimf_message_id * message_id;
4147 struct mailimf_in_reply_to * in_reply_to;
4148 struct mailimf_references * references;
4149 struct mailimf_subject * subject;
4150 struct mailimf_comments * comments;
4151 struct mailimf_keywords * keywords;
4152 struct mailimf_optional_field * optional_field;
4153 struct mailimf_field * field;
4154 int guessed_type;
4155 int r;
4156 int res;
4158 cur_token = * index;
4160 return_path = NULL;
4161 resent_date = NULL;
4162 resent_from = NULL;
4163 resent_sender = NULL;
4164 resent_to = NULL;
4165 resent_cc = NULL;
4166 resent_bcc = NULL;
4167 resent_msg_id = NULL;
4168 orig_date = NULL;
4169 from = NULL;
4170 sender = NULL;
4171 reply_to = NULL;
4172 to = NULL;
4173 cc = NULL;
4174 bcc = NULL;
4175 message_id = NULL;
4176 in_reply_to = NULL;
4177 references = NULL;
4178 subject = NULL;
4179 comments = NULL;
4180 keywords = NULL;
4181 optional_field = NULL;
4183 guessed_type = guess_header_type(message, length, cur_token);
4184 type = MAILIMF_FIELD_NONE;
4186 switch (guessed_type) {
4187 case MAILIMF_FIELD_ORIG_DATE:
4188 r = mailimf_orig_date_parse(message, length, &cur_token,
4189 &orig_date);
4190 if (r == MAILIMF_NO_ERROR)
4191 type = MAILIMF_FIELD_ORIG_DATE;
4192 else if (r == MAILIMF_ERROR_PARSE) {
4193 /* do nothing */
4195 else {
4196 res = r;
4197 goto free_fields;
4199 break;
4200 case MAILIMF_FIELD_FROM:
4201 r = mailimf_from_parse(message, length, &cur_token,
4202 &from);
4203 if (r == MAILIMF_NO_ERROR)
4204 type = guessed_type;
4205 else if (r == MAILIMF_ERROR_PARSE) {
4206 /* do nothing */
4208 else {
4209 res = r;
4210 goto free_fields;
4212 break;
4213 case MAILIMF_FIELD_SENDER:
4214 r = mailimf_sender_parse(message, length, &cur_token,
4215 &sender);
4216 if (r == MAILIMF_NO_ERROR)
4217 type = guessed_type;
4218 else if (r == MAILIMF_ERROR_PARSE) {
4219 /* do nothing */
4221 else {
4222 res = r;
4223 goto free_fields;
4225 break;
4226 case MAILIMF_FIELD_REPLY_TO:
4227 r = mailimf_reply_to_parse(message, length, &cur_token,
4228 &reply_to);
4229 if (r == MAILIMF_NO_ERROR)
4230 type = guessed_type;
4231 else if (r == MAILIMF_ERROR_PARSE) {
4232 /* do nothing */
4234 else {
4235 res = r;
4236 goto free_fields;
4238 break;
4239 case MAILIMF_FIELD_TO:
4240 r = mailimf_to_parse(message, length, &cur_token,
4241 &to);
4242 if (r == MAILIMF_NO_ERROR)
4243 type = guessed_type;
4244 else if (r == MAILIMF_ERROR_PARSE) {
4245 /* do nothing */
4247 else {
4248 res = r;
4249 goto free_fields;
4251 break;
4252 case MAILIMF_FIELD_CC:
4253 r = mailimf_cc_parse(message, length, &cur_token,
4254 &cc);
4255 if (r == MAILIMF_NO_ERROR)
4256 type = guessed_type;
4257 else if (r == MAILIMF_ERROR_PARSE) {
4258 /* do nothing */
4260 else {
4261 res = r;
4262 goto free_fields;
4264 break;
4265 case MAILIMF_FIELD_BCC:
4266 r = mailimf_bcc_parse(message, length, &cur_token,
4267 &bcc);
4268 if (r == MAILIMF_NO_ERROR)
4269 type = guessed_type;
4270 else if (r == MAILIMF_ERROR_PARSE) {
4271 /* do nothing */
4273 else {
4274 res = r;
4275 goto free_fields;
4277 break;
4278 case MAILIMF_FIELD_MESSAGE_ID:
4279 r = mailimf_message_id_parse(message, length, &cur_token,
4280 &message_id);
4281 if (r == MAILIMF_NO_ERROR)
4282 type = guessed_type;
4283 else if (r == MAILIMF_ERROR_PARSE) {
4284 /* do nothing */
4286 else {
4287 res = r;
4288 goto free_fields;
4290 break;
4291 case MAILIMF_FIELD_IN_REPLY_TO:
4292 r = mailimf_in_reply_to_parse(message, length, &cur_token,
4293 &in_reply_to);
4294 if (r == MAILIMF_NO_ERROR)
4295 type = guessed_type;
4296 else if (r == MAILIMF_ERROR_PARSE) {
4297 /* do nothing */
4299 else {
4300 res = r;
4301 goto free_fields;
4303 break;
4304 case MAILIMF_FIELD_REFERENCES:
4305 r = mailimf_references_parse(message, length, &cur_token,
4306 &references);
4307 if (r == MAILIMF_NO_ERROR)
4308 type = guessed_type;
4309 else if (r == MAILIMF_ERROR_PARSE) {
4310 /* do nothing */
4312 else {
4313 res = r;
4314 goto free_fields;
4316 break;
4317 case MAILIMF_FIELD_SUBJECT:
4318 r = mailimf_subject_parse(message, length, &cur_token,
4319 &subject);
4320 if (r == MAILIMF_NO_ERROR)
4321 type = guessed_type;
4322 else if (r == MAILIMF_ERROR_PARSE) {
4323 /* do nothing */
4325 else {
4326 res = r;
4327 goto free_fields;
4329 break;
4330 case MAILIMF_FIELD_COMMENTS:
4331 r = mailimf_comments_parse(message, length, &cur_token,
4332 &comments);
4333 if (r == MAILIMF_NO_ERROR)
4334 type = guessed_type;
4335 else if (r == MAILIMF_ERROR_PARSE) {
4336 /* do nothing */
4338 else {
4339 res = r;
4340 goto free_fields;
4342 break;
4343 case MAILIMF_FIELD_KEYWORDS:
4344 r = mailimf_keywords_parse(message, length, &cur_token,
4345 &keywords);
4346 if (r == MAILIMF_NO_ERROR)
4347 type = guessed_type;
4348 else if (r == MAILIMF_ERROR_PARSE) {
4349 /* do nothing */
4351 else {
4352 res = r;
4353 goto free_fields;
4355 break;
4356 case MAILIMF_FIELD_RETURN_PATH:
4357 r = mailimf_return_parse(message, length, &cur_token,
4358 &return_path);
4359 if (r == MAILIMF_NO_ERROR)
4360 type = guessed_type;
4361 else if (r == MAILIMF_ERROR_PARSE) {
4362 /* do nothing */
4364 else {
4365 res = r;
4366 goto free_fields;
4368 break;
4369 case MAILIMF_FIELD_RESENT_DATE:
4370 r = mailimf_resent_date_parse(message, length, &cur_token,
4371 &resent_date);
4372 if (r == MAILIMF_NO_ERROR)
4373 type = guessed_type;
4374 else if (r == MAILIMF_ERROR_PARSE) {
4375 /* do nothing */
4377 else {
4378 res = r;
4379 goto free_fields;
4381 break;
4382 case MAILIMF_FIELD_RESENT_FROM:
4383 r = mailimf_resent_from_parse(message, length, &cur_token,
4384 &resent_from);
4385 if (r == MAILIMF_NO_ERROR)
4386 type = guessed_type;
4387 else if (r == MAILIMF_ERROR_PARSE) {
4388 /* do nothing */
4390 else {
4391 res = r;
4392 goto free_fields;
4394 break;
4395 case MAILIMF_FIELD_RESENT_SENDER:
4396 r = mailimf_resent_sender_parse(message, length, &cur_token,
4397 &resent_sender);
4398 if (r == MAILIMF_NO_ERROR)
4399 type = guessed_type;
4400 else if (r == MAILIMF_ERROR_PARSE) {
4401 /* do nothing */
4403 else {
4404 res = r;
4405 goto free_fields;
4407 break;
4408 case MAILIMF_FIELD_RESENT_TO:
4409 r = mailimf_resent_to_parse(message, length, &cur_token,
4410 &resent_to);
4411 if (r == MAILIMF_NO_ERROR)
4412 type = guessed_type;
4413 else if (r == MAILIMF_ERROR_PARSE) {
4414 /* do nothing */
4416 else {
4417 res = r;
4418 goto free_fields;
4420 break;
4421 case MAILIMF_FIELD_RESENT_CC:
4422 r= mailimf_resent_cc_parse(message, length, &cur_token,
4423 &resent_cc);
4424 if (r == MAILIMF_NO_ERROR)
4425 type = guessed_type;
4426 else if (r == MAILIMF_ERROR_PARSE) {
4427 /* do nothing */
4429 else {
4430 res = r;
4431 goto free_fields;
4433 break;
4434 case MAILIMF_FIELD_RESENT_BCC:
4435 r = mailimf_resent_bcc_parse(message, length, &cur_token,
4436 &resent_bcc);
4437 if (r == MAILIMF_NO_ERROR)
4438 type = guessed_type;
4439 else if (r == MAILIMF_ERROR_PARSE) {
4440 /* do nothing */
4442 else {
4443 res = r;
4444 goto free_fields;
4446 break;
4447 case MAILIMF_FIELD_RESENT_MSG_ID:
4448 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
4449 &resent_msg_id);
4450 if (r == MAILIMF_NO_ERROR)
4451 type = guessed_type;
4452 else if (r == MAILIMF_ERROR_PARSE) {
4453 /* do nothing */
4455 else {
4456 res = r;
4457 goto free_fields;
4459 break;
4462 if (type == MAILIMF_FIELD_NONE) {
4463 r = mailimf_optional_field_parse(message, length, &cur_token,
4464 &optional_field);
4465 if (r != MAILIMF_NO_ERROR) {
4466 res = r;
4467 goto free_fields;
4470 type = MAILIMF_FIELD_OPTIONAL_FIELD;
4473 field = mailimf_field_new(type, return_path, resent_date,
4474 resent_from, resent_sender, resent_to, resent_cc, resent_bcc,
4475 resent_msg_id, orig_date, from, sender, reply_to, to,
4476 cc, bcc, message_id, in_reply_to, references,
4477 subject, comments, keywords, optional_field);
4478 if (field == NULL) {
4479 res = MAILIMF_ERROR_MEMORY;
4480 goto free_fields;
4483 * result = field;
4484 * index = cur_token;
4486 return MAILIMF_NO_ERROR;
4488 free_fields:
4489 if (return_path != NULL)
4490 mailimf_return_free(return_path);
4491 if (resent_date != NULL)
4492 mailimf_orig_date_free(resent_date);
4493 if (resent_from != NULL)
4494 mailimf_from_free(resent_from);
4495 if (resent_sender != NULL)
4496 mailimf_sender_free(resent_sender);
4497 if (resent_to != NULL)
4498 mailimf_to_free(resent_to);
4499 if (resent_cc != NULL)
4500 mailimf_cc_free(resent_cc);
4501 if (resent_bcc != NULL)
4502 mailimf_bcc_free(resent_bcc);
4503 if (resent_msg_id != NULL)
4504 mailimf_message_id_free(resent_msg_id);
4505 if (orig_date != NULL)
4506 mailimf_orig_date_free(orig_date);
4507 if (from != NULL)
4508 mailimf_from_free(from);
4509 if (sender != NULL)
4510 mailimf_sender_free(sender);
4511 if (reply_to != NULL)
4512 mailimf_reply_to_free(reply_to);
4513 if (to != NULL)
4514 mailimf_to_free(to);
4515 if (cc != NULL)
4516 mailimf_cc_free(cc);
4517 if (bcc != NULL)
4518 mailimf_bcc_free(bcc);
4519 if (message_id != NULL)
4520 mailimf_message_id_free(message_id);
4521 if (in_reply_to != NULL)
4522 mailimf_in_reply_to_free(in_reply_to);
4523 if (references != NULL)
4524 mailimf_references_free(references);
4525 if (subject != NULL)
4526 mailimf_subject_free(subject);
4527 if (comments != NULL)
4528 mailimf_comments_free(comments);
4529 if (keywords != NULL)
4530 mailimf_keywords_free(keywords);
4531 if (optional_field != NULL)
4532 mailimf_optional_field_free(optional_field);
4533 return res;
4538 fields = *(delivering-info /
4539 orig-date /
4540 from /
4541 sender /
4542 reply-to /
4543 to /
4544 cc /
4545 bcc /
4546 message-id /
4547 in-reply-to /
4548 references /
4549 subject /
4550 comments /
4551 keywords /
4552 optional-field)
4555 #if 0
4557 mailimf_unparsed_fields_parse(const char * message, size_t length,
4558 size_t * index,
4559 struct mailimf_unparsed_fields ** result)
4561 size_t cur_token;
4562 clist * list;
4563 struct mailimf_unparsed_fields * fields;
4564 int r;
4565 int res;
4567 cur_token = * index;
4569 list = NULL;
4571 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4572 &list,
4573 (mailimf_struct_parser *)
4574 mailimf_optional_field_parse,
4575 (mailimf_struct_destructor *)
4576 mailimf_optional_field_free);
4578 if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4579 res = r;
4580 goto err;
4584 switch (r) {
4585 case MAILIMF_NO_ERROR:
4586 /* do nothing */
4587 break;
4589 case MAILIMF_ERROR_PARSE:
4590 list = clist_new();
4591 if (list == NULL) {
4592 res = MAILIMF_ERROR_MEMORY;
4593 goto err;
4595 break;
4597 default:
4598 res = r;
4599 goto err;
4602 fields = mailimf_unparsed_fields_new(list);
4603 if (fields == NULL) {
4604 res = MAILIMF_ERROR_MEMORY;
4605 goto free;
4608 * result = fields;
4609 * index = cur_token;
4611 return MAILIMF_NO_ERROR;
4613 free:
4614 if (list != NULL) {
4615 clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL);
4616 clist_free(list);
4618 err:
4619 return res;
4621 #endif
4623 int mailimf_fields_parse(const char * message, size_t length,
4624 size_t * index,
4625 struct mailimf_fields ** result)
4627 size_t cur_token;
4628 clist * list;
4629 struct mailimf_fields * fields;
4630 int r;
4631 int res;
4633 cur_token = * index;
4635 list = NULL;
4637 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4638 &list,
4639 (mailimf_struct_parser *)
4640 mailimf_field_parse,
4641 (mailimf_struct_destructor *)
4642 mailimf_field_free);
4644 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4645 res = r;
4646 goto err;
4650 switch (r) {
4651 case MAILIMF_NO_ERROR:
4652 /* do nothing */
4653 break;
4655 case MAILIMF_ERROR_PARSE:
4656 list = clist_new();
4657 if (list == NULL) {
4658 res = MAILIMF_ERROR_MEMORY;
4659 goto err;
4661 break;
4663 default:
4664 res = r;
4665 goto err;
4668 fields = mailimf_fields_new(list);
4669 if (fields == NULL) {
4670 res = MAILIMF_ERROR_MEMORY;
4671 goto free;
4674 * result = fields;
4675 * index = cur_token;
4677 return MAILIMF_NO_ERROR;
4679 free:
4680 if (list != NULL) {
4681 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
4682 clist_free(list);
4684 err:
4685 return res;
4689 orig-date = "Date:" date-time CRLF
4693 static int
4694 mailimf_orig_date_parse(const char * message, size_t length,
4695 size_t * index, struct mailimf_orig_date ** result)
4697 struct mailimf_date_time * date_time;
4698 struct mailimf_orig_date * orig_date;
4699 size_t cur_token;
4700 int r;
4701 int res;
4703 cur_token = * index;
4705 r = mailimf_token_case_insensitive_parse(message, length,
4706 &cur_token, "Date:");
4707 if (r != MAILIMF_NO_ERROR) {
4708 res = r;
4709 goto err;
4712 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
4713 if (r != MAILIMF_NO_ERROR) {
4714 res = r;
4715 goto err;
4718 r = mailimf_ignore_unstructured_parse(message, length, &cur_token);
4719 if (r != MAILIMF_NO_ERROR) {
4720 res = r;
4721 goto free_date_time;
4724 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4725 if (r != MAILIMF_NO_ERROR) {
4726 res = r;
4727 goto free_date_time;
4730 orig_date = mailimf_orig_date_new(date_time);
4731 if (orig_date == NULL) {
4732 res = MAILIMF_ERROR_MEMORY;
4733 goto free_date_time;
4736 * result = orig_date;
4737 * index = cur_token;
4739 return MAILIMF_NO_ERROR;
4741 free_date_time:
4742 mailimf_date_time_free(date_time);
4743 err:
4744 return res;
4748 from = "From:" mailbox-list CRLF
4751 static int
4752 mailimf_from_parse(const char * message, size_t length,
4753 size_t * index, struct mailimf_from ** result)
4755 struct mailimf_mailbox_list * mb_list;
4756 struct mailimf_from * from;
4757 size_t cur_token;
4758 int r;
4759 int res;
4761 cur_token = * index;
4763 r = mailimf_token_case_insensitive_parse(message, length,
4764 &cur_token, "From");
4765 if (r != MAILIMF_NO_ERROR) {
4766 res = r;
4767 goto err;
4770 r = mailimf_colon_parse(message, length, &cur_token);
4771 if (r != MAILIMF_NO_ERROR) {
4772 res = r;
4773 goto err;
4776 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
4778 if (r != MAILIMF_NO_ERROR) {
4779 res = r;
4780 goto err;
4783 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4784 if (r != MAILIMF_NO_ERROR) {
4785 res = r;
4786 goto free_mb_list;
4789 from = mailimf_from_new(mb_list);
4790 if (from == NULL) {
4791 res = MAILIMF_ERROR_MEMORY;
4792 goto free_mb_list;
4795 * result = from;
4796 * index = cur_token;
4798 return MAILIMF_NO_ERROR;
4800 free_mb_list:
4801 mailimf_mailbox_list_free(mb_list);
4802 err:
4803 return res;
4807 sender = "Sender:" mailbox CRLF
4810 static int
4811 mailimf_sender_parse(const char * message, size_t length,
4812 size_t * index, struct mailimf_sender ** result)
4814 struct mailimf_mailbox * mb;
4815 struct mailimf_sender * sender;
4816 size_t cur_token;
4817 int r;
4818 int res;
4820 cur_token = * index;
4822 r = mailimf_token_case_insensitive_parse(message, length,
4823 &cur_token, "Sender");
4824 if (r != MAILIMF_NO_ERROR) {
4825 res = r;
4826 goto err;
4829 r = mailimf_colon_parse(message, length, &cur_token);
4830 if (r != MAILIMF_NO_ERROR) {
4831 res = r;
4832 goto err;
4835 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
4836 if (r != MAILIMF_NO_ERROR) {
4837 res = r;
4838 goto err;
4841 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4842 if (r != MAILIMF_NO_ERROR) {
4843 res = r;
4844 goto free_mb;
4847 sender = mailimf_sender_new(mb);
4848 if (sender == NULL) {
4849 res = MAILIMF_ERROR_MEMORY;
4850 goto free_mb;
4853 * result = sender;
4854 * index = cur_token;
4856 return MAILIMF_NO_ERROR;
4858 free_mb:
4859 mailimf_mailbox_free(mb);
4860 err:
4861 return res;
4865 reply-to = "Reply-To:" address-list CRLF
4869 static int
4870 mailimf_reply_to_parse(const char * message, size_t length,
4871 size_t * index, struct mailimf_reply_to ** result)
4873 struct mailimf_address_list * addr_list;
4874 struct mailimf_reply_to * reply_to;
4875 size_t cur_token;
4876 int r;
4877 int res;
4879 cur_token = * index;
4881 r = mailimf_token_case_insensitive_parse(message, length,
4882 &cur_token, "Reply-To");
4883 if (r != MAILIMF_NO_ERROR) {
4884 res = r;
4885 goto err;
4888 r = mailimf_colon_parse(message, length, &cur_token);
4889 if (r != MAILIMF_NO_ERROR) {
4890 res = r;
4891 goto err;
4894 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4895 if (r != MAILIMF_NO_ERROR) {
4896 res = r;
4897 goto err;
4900 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4901 if (r != MAILIMF_NO_ERROR) {
4902 res = r;
4903 goto free_addr_list;
4906 reply_to = mailimf_reply_to_new(addr_list);
4907 if (reply_to == NULL) {
4908 res = MAILIMF_ERROR_MEMORY;
4909 goto free_addr_list;
4912 * result = reply_to;
4913 * index = cur_token;
4915 return MAILIMF_NO_ERROR;
4917 free_addr_list:
4918 mailimf_address_list_free(addr_list);
4919 err:
4920 return res;
4924 to = "To:" address-list CRLF
4927 static int
4928 mailimf_to_parse(const char * message, size_t length,
4929 size_t * index, struct mailimf_to ** result)
4931 struct mailimf_address_list * addr_list;
4932 struct mailimf_to * to;
4933 size_t cur_token;
4934 int r;
4935 int res;
4937 cur_token = * index;
4939 r = mailimf_token_case_insensitive_parse(message, length,
4940 &cur_token, "To");
4941 if (r != MAILIMF_NO_ERROR) {
4942 res = r;
4943 goto err;
4946 r = mailimf_colon_parse(message, length, &cur_token);
4947 if (r != MAILIMF_NO_ERROR) {
4948 res = r;
4949 goto err;
4952 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4953 if (r != MAILIMF_NO_ERROR) {
4954 res = r;
4955 goto err;
4958 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4959 if (r != MAILIMF_NO_ERROR) {
4960 res = r;
4961 goto free_addr_list;
4964 to = mailimf_to_new(addr_list);
4965 if (to == NULL) {
4966 res = MAILIMF_ERROR_MEMORY;
4967 goto free_addr_list;
4970 * result = to;
4971 * index = cur_token;
4973 return MAILIMF_NO_ERROR;
4975 free_addr_list:
4976 mailimf_address_list_free(addr_list);
4977 err:
4978 return res;
4982 cc = "Cc:" address-list CRLF
4986 static int
4987 mailimf_cc_parse(const char * message, size_t length,
4988 size_t * index, struct mailimf_cc ** result)
4990 struct mailimf_address_list * addr_list;
4991 struct mailimf_cc * cc;
4992 size_t cur_token;
4993 int r;
4994 int res;
4996 cur_token = * index;
4998 r = mailimf_token_case_insensitive_parse(message, length,
4999 &cur_token, "Cc");
5000 if (r != MAILIMF_NO_ERROR) {
5001 res = r;
5002 goto err;
5005 r = mailimf_colon_parse(message, length, &cur_token);
5006 if (r != MAILIMF_NO_ERROR) {
5007 res = r;
5008 goto err;
5011 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5012 if (r != MAILIMF_NO_ERROR) {
5013 res = r;
5014 goto err;
5017 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5018 if (r != MAILIMF_NO_ERROR) {
5019 res = r;
5020 goto free_addr_list;
5023 cc = mailimf_cc_new(addr_list);
5024 if (cc == NULL) {
5025 res = MAILIMF_ERROR_MEMORY;
5026 goto free_addr_list;
5029 * result = cc;
5030 * index = cur_token;
5032 return MAILIMF_NO_ERROR;
5034 free_addr_list:
5035 mailimf_address_list_free(addr_list);
5036 err:
5037 return res;
5041 bcc = "Bcc:" (address-list / [CFWS]) CRLF
5045 static int
5046 mailimf_bcc_parse(const char * message, size_t length,
5047 size_t * index, struct mailimf_bcc ** result)
5049 struct mailimf_address_list * addr_list;
5050 struct mailimf_bcc * bcc;
5051 size_t cur_token;
5052 int r;
5053 int res;
5055 cur_token = * index;
5056 addr_list = NULL;
5058 r = mailimf_token_case_insensitive_parse(message, length,
5059 &cur_token, "Bcc");
5060 if (r != MAILIMF_NO_ERROR) {
5061 res = r;
5062 goto err;
5065 r = mailimf_colon_parse(message, length, &cur_token);
5066 if (r != MAILIMF_NO_ERROR) {
5067 res = r;
5068 goto err;
5071 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5072 switch (r) {
5073 case MAILIMF_NO_ERROR:
5074 /* do nothing */
5075 break;
5076 case MAILIMF_ERROR_PARSE:
5077 r = mailimf_cfws_parse(message, length, &cur_token);
5078 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
5079 res = r;
5080 goto err;
5082 break;
5083 default:
5084 res = r;
5085 goto err;
5088 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5089 if (r != MAILIMF_NO_ERROR) {
5090 res = r;
5091 goto free_addr_list;
5094 bcc = mailimf_bcc_new(addr_list);
5095 if (bcc == NULL) {
5096 res = MAILIMF_ERROR_MEMORY;
5097 goto free_addr_list;
5100 * result = bcc;
5101 * index = cur_token;
5103 return MAILIMF_NO_ERROR;
5105 free_addr_list:
5106 mailimf_address_list_free(addr_list);
5107 err:
5108 return res;
5112 message-id = "Message-ID:" msg-id CRLF
5115 static int mailimf_message_id_parse(const char * message, size_t length,
5116 size_t * index,
5117 struct mailimf_message_id ** result)
5119 char * value;
5120 size_t cur_token;
5121 struct mailimf_message_id * message_id;
5122 int r;
5123 int res;
5125 cur_token = * index;
5127 r = mailimf_token_case_insensitive_parse(message, length,
5128 &cur_token, "Message-ID");
5129 if (r != MAILIMF_NO_ERROR) {
5130 res = r;
5131 goto err;
5134 r = mailimf_colon_parse(message, length, &cur_token);
5135 if (r != MAILIMF_NO_ERROR) {
5136 res = r;
5137 goto err;
5140 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
5141 if (r != MAILIMF_NO_ERROR) {
5142 res = r;
5143 goto err;
5146 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5147 if (r != MAILIMF_NO_ERROR) {
5148 res = r;
5149 goto free_value;
5152 message_id = mailimf_message_id_new(value);
5153 if (message_id == NULL) {
5154 res = MAILIMF_ERROR_MEMORY;
5155 goto free_value;
5158 * result = message_id;
5159 * index = cur_token;
5161 return MAILIMF_NO_ERROR;
5163 free_value:
5164 mailimf_msg_id_free(value);
5165 err:
5166 return res;
5170 in-reply-to = "In-Reply-To:" 1*msg-id CRLF
5173 int mailimf_msg_id_list_parse(const char * message, size_t length,
5174 size_t * index, clist ** result)
5176 return mailimf_struct_multiple_parse(message, length, index,
5177 result,
5178 (mailimf_struct_parser *)
5179 mailimf_unstrict_msg_id_parse,
5180 (mailimf_struct_destructor *)
5181 mailimf_msg_id_free);
5184 static int mailimf_in_reply_to_parse(const char * message, size_t length,
5185 size_t * index,
5186 struct mailimf_in_reply_to ** result)
5188 struct mailimf_in_reply_to * in_reply_to;
5189 size_t cur_token;
5190 clist * msg_id_list;
5191 int res;
5192 int r;
5194 cur_token = * index;
5196 r = mailimf_token_case_insensitive_parse(message, length,
5197 &cur_token, "In-Reply-To");
5198 if (r != MAILIMF_NO_ERROR) {
5199 res = r;
5200 goto err;
5203 r = mailimf_colon_parse(message, length, &cur_token);
5204 if (r != MAILIMF_NO_ERROR) {
5205 res = r;
5206 goto err;
5209 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5210 if (r != MAILIMF_NO_ERROR) {
5211 res = r;
5212 goto err;
5215 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5216 if (r != MAILIMF_NO_ERROR) {
5217 res = r;
5218 goto free_list;
5221 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
5222 if (in_reply_to == NULL) {
5223 res = MAILIMF_ERROR_MEMORY;
5224 goto free_list;
5227 * result = in_reply_to;
5228 * index = cur_token;
5230 return MAILIMF_NO_ERROR;
5232 free_list:
5233 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5234 clist_free(msg_id_list);
5235 err:
5236 return res;
5240 references = "References:" 1*msg-id CRLF
5243 int mailimf_references_parse(const char * message, size_t length,
5244 size_t * index,
5245 struct mailimf_references ** result)
5247 struct mailimf_references * references;
5248 size_t cur_token;
5249 clist * msg_id_list;
5250 int r;
5251 int res;
5253 cur_token = * index;
5255 r = mailimf_token_case_insensitive_parse(message, length,
5256 &cur_token, "References");
5257 if (r != MAILIMF_NO_ERROR) {
5258 res = r;
5259 goto err;
5262 r = mailimf_colon_parse(message, length, &cur_token);
5263 if (r != MAILIMF_NO_ERROR) {
5264 res = r;
5265 goto err;
5268 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5269 if (r != MAILIMF_NO_ERROR) {
5270 res = r;
5271 goto err;
5274 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5275 if (r != MAILIMF_NO_ERROR) {
5276 res = r;
5277 goto free_list;
5280 references = mailimf_references_new(msg_id_list);
5281 if (references == NULL) {
5282 res = MAILIMF_ERROR_MEMORY;
5283 goto free_list;
5286 * result = references;
5287 * index = cur_token;
5289 return MAILIMF_NO_ERROR;
5291 free_list:
5292 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5293 clist_free(msg_id_list);
5294 err:
5295 return res;
5299 msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
5302 int mailimf_msg_id_parse(const char * message, size_t length,
5303 size_t * index,
5304 char ** result)
5306 size_t cur_token;
5307 #if 0
5308 char * id_left;
5309 char * id_right;
5310 #endif
5311 char * msg_id;
5312 int r;
5313 int res;
5315 cur_token = * index;
5317 r = mailimf_cfws_parse(message, length, &cur_token);
5318 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5319 return r;
5321 r = mailimf_lower_parse(message, length, &cur_token);
5322 if (r != MAILIMF_NO_ERROR) {
5323 res = r;
5324 goto err;
5327 r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id);
5328 if (r != MAILIMF_NO_ERROR) {
5329 res = r;
5330 goto err;
5333 r = mailimf_greater_parse(message, length, &cur_token);
5334 if (r != MAILIMF_NO_ERROR) {
5335 free(msg_id);
5336 res = r;
5337 goto err;
5340 #if 0
5341 r = mailimf_id_left_parse(message, length, &cur_token, &id_left);
5342 if (r != MAILIMF_NO_ERROR) {
5343 res = r;
5344 goto err;
5347 r = mailimf_at_sign_parse(message, length, &cur_token);
5348 if (r != MAILIMF_NO_ERROR) {
5349 res = r;
5350 goto free_id_left;
5353 r = mailimf_id_right_parse(message, length, &cur_token, &id_right);
5354 if (r != MAILIMF_NO_ERROR) {
5355 res = r;
5356 goto free_id_left;
5359 r = mailimf_greater_parse(message, length, &cur_token);
5360 if (r != MAILIMF_NO_ERROR) {
5361 res = r;
5362 goto free_id_right;
5365 msg_id = malloc(strlen(id_left) + strlen(id_right) + 2);
5366 if (msg_id == NULL) {
5367 res = MAILIMF_ERROR_MEMORY;
5368 goto free_id_right;
5370 strcpy(msg_id, id_left);
5371 strcat(msg_id, "@");
5372 strcat(msg_id, id_right);
5374 mailimf_id_left_free(id_left);
5375 mailimf_id_right_free(id_right);
5376 #endif
5378 * result = msg_id;
5379 * index = cur_token;
5381 return MAILIMF_NO_ERROR;
5383 #if 0
5384 free_id_right:
5385 mailimf_id_right_free(id_right);
5386 free_id_left:
5387 mailimf_id_left_free(id_left);
5388 #endif
5390 free:
5391 mailimf_atom_free(msg_id);
5393 err:
5394 return res;
5397 static int mailimf_parse_unwanted_msg_id(const char * message, size_t length,
5398 size_t * index)
5400 size_t cur_token;
5401 int r;
5402 char * word;
5403 int token_parsed;
5405 cur_token = * index;
5407 token_parsed = TRUE;
5408 while (token_parsed) {
5409 token_parsed = FALSE;
5410 r = mailimf_word_parse(message, length, &cur_token, &word);
5411 if (r == MAILIMF_NO_ERROR) {
5412 mailimf_word_free(word);
5413 token_parsed = TRUE;
5415 else if (r == MAILIMF_ERROR_PARSE) {
5416 /* do nothing */
5418 else
5419 return r;
5420 r = mailimf_semi_colon_parse(message, length, &cur_token);
5421 if (r == MAILIMF_NO_ERROR)
5422 token_parsed = TRUE;
5423 else if (r == MAILIMF_ERROR_PARSE) {
5424 /* do nothing */
5426 else
5427 return r;
5428 r = mailimf_comma_parse(message, length, &cur_token);
5429 if (r == MAILIMF_NO_ERROR)
5430 token_parsed = TRUE;
5431 else if (r == MAILIMF_ERROR_PARSE) {
5432 /* do nothing */
5434 else
5435 return r;
5436 r = mailimf_plus_parse(message, length, &cur_token);
5437 if (r == MAILIMF_NO_ERROR)
5438 token_parsed = TRUE;
5439 else if (r == MAILIMF_ERROR_PARSE) {
5440 /* do nothing */
5442 else
5443 return r;
5444 r = mailimf_colon_parse(message, length, &cur_token);
5445 if (r == MAILIMF_NO_ERROR)
5446 token_parsed = TRUE;
5447 else if (r == MAILIMF_ERROR_PARSE) {
5448 /* do nothing */
5450 else
5451 return r;
5452 r = mailimf_point_parse(message, length, &cur_token);
5453 if (r == MAILIMF_NO_ERROR)
5454 token_parsed = TRUE;
5455 else if (r == MAILIMF_ERROR_PARSE) {
5456 /* do nothing */
5458 else
5459 return r;
5460 r = mailimf_at_sign_parse(message, length, &cur_token);
5461 if (r == MAILIMF_NO_ERROR)
5462 token_parsed = TRUE;
5463 else if (r == MAILIMF_ERROR_PARSE) {
5464 /* do nothing */
5466 else
5467 return r;
5470 return MAILIMF_NO_ERROR;
5473 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
5474 size_t * index,
5475 char ** result)
5477 char * msgid = NULL;
5478 size_t cur_token;
5479 int r;
5481 cur_token = * index;
5483 r = mailimf_cfws_parse(message, length, &cur_token);
5484 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5485 return r;
5487 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5488 if (r != MAILIMF_NO_ERROR)
5489 return r;
5491 r = mailimf_msg_id_parse(message, length, &cur_token, &msgid);
5492 if (r != MAILIMF_NO_ERROR)
5493 return r;
5495 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5496 if (r != MAILIMF_NO_ERROR) {
5497 free(msgid);
5498 return r;
5501 * result = msgid;
5502 * index = cur_token;
5504 return MAILIMF_NO_ERROR;
5508 id-left = dot-atom-text / no-fold-quote / obs-id-left
5511 #if 0
5512 static int mailimf_id_left_parse(const char * message, size_t length,
5513 size_t * index, char ** result)
5515 int r;
5517 r = mailimf_dot_atom_text_parse(message, length, index, result);
5518 switch (r) {
5519 case MAILIMF_NO_ERROR:
5520 return MAILIMF_NO_ERROR;
5521 case MAILIMF_ERROR_PARSE:
5522 break;
5523 default:
5524 return r;
5527 r = mailimf_no_fold_quote_parse(message, length, index, result);
5528 if (r != MAILIMF_NO_ERROR)
5529 return r;
5531 return MAILIMF_NO_ERROR;
5533 #endif
5536 id-right = dot-atom-text / no-fold-literal / obs-id-right
5539 #if 0
5540 static int mailimf_id_right_parse(const char * message, size_t length,
5541 size_t * index, char ** result)
5543 int r;
5545 r = mailimf_dot_atom_text_parse(message, length, index, result);
5546 switch (r) {
5547 case MAILIMF_NO_ERROR:
5548 return MAILIMF_NO_ERROR;
5549 case MAILIMF_ERROR_PARSE:
5550 break;
5551 default:
5552 return r;
5555 r = mailimf_no_fold_literal_parse(message, length, index, result);
5556 if (r != MAILIMF_NO_ERROR)
5557 return r;
5559 return MAILIMF_NO_ERROR;
5561 #endif
5564 no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
5567 #if 0
5568 static int mailimf_no_fold_quote_char_parse(const char * message, size_t length,
5569 size_t * index, char * result)
5571 char ch;
5572 size_t cur_token;
5573 int r;
5575 cur_token = * index;
5577 #if 0
5578 r = mailimf_qtext_parse(message, length, &cur_token, &ch);
5579 #endif
5581 if (cur_token >= length)
5582 return MAILIMF_ERROR_PARSE;
5584 if (is_qtext(message[cur_token])) {
5585 ch = message[cur_token];
5586 cur_token ++;
5588 else {
5589 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5591 if (r != MAILIMF_NO_ERROR)
5592 return r;
5595 * index = cur_token;
5596 * result = ch;
5598 return MAILIMF_NO_ERROR;
5600 #endif
5602 #if 0
5603 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
5604 size_t * index, char ** result)
5606 size_t cur_token;
5607 size_t begin;
5608 char ch;
5609 char * no_fold_quote;
5610 int r;
5611 int res;
5613 begin = cur_token;
5614 r = mailimf_dquote_parse(message, length, &cur_token);
5615 if (r != MAILIMF_NO_ERROR) {
5616 res = r;
5617 goto err;
5620 while (1) {
5621 r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch);
5622 if (r == MAILIMF_NO_ERROR) {
5623 /* do nothing */
5625 else if (r == MAILIMF_ERROR_PARSE)
5626 break;
5627 else {
5628 res = r;
5629 goto err;
5633 r = mailimf_dquote_parse(message, length, &cur_token);
5634 if (r != MAILIMF_NO_ERROR) {
5635 res = r;
5636 goto err;
5639 /* no_fold_quote = strndup(message + begin, cur_token - begin); */
5640 no_fold_quote = malloc(cur_token - begin + 1);
5641 if (no_fold_quote == NULL) {
5642 res = MAILIMF_ERROR_MEMORY;
5643 goto err;
5645 strncpy(no_fold_quote, message + begin, cur_token - begin);
5646 no_fold_quote[cur_token - begin] = '\0';
5648 * result = no_fold_quote;
5649 * index = cur_token;
5651 return MAILIMF_NO_ERROR;
5653 err:
5654 return res;
5656 #endif
5659 no-fold-literal = "[" *(dtext / quoted-pair) "]"
5662 #if 0
5663 static inline int
5664 mailimf_no_fold_literal_char_parse(const char * message, size_t length,
5665 size_t * index, char * result)
5667 char ch;
5668 size_t cur_token;
5669 int r;
5671 cur_token = * index;
5673 #if 0
5674 r = mailimf_dtext_parse(message, length, &cur_token, &ch);
5675 #endif
5676 if (cur_token >= length)
5677 return MAILIMF_ERROR_PARSE;
5679 if (is_dtext(message[cur_token])) {
5680 ch = message[cur_token];
5681 cur_token ++;
5683 else {
5684 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5686 if (r != MAILIMF_NO_ERROR)
5687 return r;
5690 * index = cur_token;
5691 * result = ch;
5693 return MAILIMF_NO_ERROR;
5695 #endif
5697 #if 0
5698 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
5699 size_t * index, char ** result)
5701 size_t cur_token;
5702 size_t begin;
5703 char ch;
5704 char * no_fold_literal;
5705 int r;
5706 int res;
5708 begin = cur_token;
5709 r = mailimf_obracket_parse(message, length, &cur_token);
5710 if (r != MAILIMF_NO_ERROR) {
5711 res = r;
5712 goto err;
5715 while (1) {
5716 r = mailimf_no_fold_literal_char_parse(message, length,
5717 &cur_token, &ch);
5718 if (r == MAILIMF_NO_ERROR) {
5719 /* do nothing */
5721 else if (r == MAILIMF_ERROR_PARSE)
5722 break;
5723 else {
5724 res = r;
5725 goto err;
5729 r = mailimf_cbracket_parse(message, length, &cur_token);
5730 if (r != MAILIMF_NO_ERROR) {
5731 res = r;
5732 goto err;
5736 no_fold_literal = strndup(message + begin, cur_token - begin);
5738 no_fold_literal = malloc(cur_token - begin + 1);
5739 if (no_fold_literal == NULL) {
5740 res = MAILIMF_NO_ERROR;
5741 goto err;
5743 strncpy(no_fold_literal, message + begin, cur_token - begin);
5744 no_fold_literal[cur_token - begin] = '\0';
5746 * result = no_fold_literal;
5747 * index = cur_token;
5749 return MAILIMF_NO_ERROR;
5751 err:
5752 return res;
5754 #endif
5757 subject = "Subject:" unstructured CRLF
5760 static int mailimf_subject_parse(const char * message, size_t length,
5761 size_t * index,
5762 struct mailimf_subject ** result)
5764 struct mailimf_subject * subject;
5765 char * value;
5766 size_t cur_token;
5767 int r;
5768 int res;
5770 cur_token = * index;
5772 r = mailimf_token_case_insensitive_parse(message, length,
5773 &cur_token, "Subject");
5774 if (r != MAILIMF_NO_ERROR) {
5775 res = r;
5776 goto err;
5779 r = mailimf_colon_parse(message, length, &cur_token);
5780 if (r != MAILIMF_NO_ERROR) {
5781 res = r;
5782 goto err;
5785 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5786 if (r != MAILIMF_NO_ERROR) {
5787 res = r;
5788 goto err;
5791 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5792 if (r != MAILIMF_NO_ERROR) {
5793 res = r;
5794 goto free_value;
5797 subject = mailimf_subject_new(value);
5798 if (subject == NULL) {
5799 res = MAILIMF_ERROR_MEMORY;
5800 goto free_value;
5803 * result = subject;
5804 * index = cur_token;
5806 return MAILIMF_NO_ERROR;
5808 free_value:
5809 mailimf_unstructured_free(value);
5810 err:
5811 return res;
5815 comments = "Comments:" unstructured CRLF
5818 static int mailimf_comments_parse(const char * message, size_t length,
5819 size_t * index,
5820 struct mailimf_comments ** result)
5822 struct mailimf_comments * comments;
5823 char * value;
5824 size_t cur_token;
5825 int r;
5826 int res;
5828 cur_token = * index;
5830 r = mailimf_token_case_insensitive_parse(message, length,
5831 &cur_token, "Comments");
5832 if (r != MAILIMF_NO_ERROR) {
5833 res = r;
5834 goto err;
5837 r = mailimf_colon_parse(message, length, &cur_token);
5838 if (r != MAILIMF_NO_ERROR) {
5839 res = r;
5840 goto err;
5843 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5844 if (r != MAILIMF_NO_ERROR) {
5845 res = r;
5846 goto err;
5849 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5850 if (r != MAILIMF_NO_ERROR) {
5851 res = r;
5852 goto free_value;
5855 comments = mailimf_comments_new(value);
5856 if (comments == NULL) {
5857 res = MAILIMF_ERROR_MEMORY;
5858 goto free_value;
5861 * result = comments;
5862 * index = cur_token;
5864 return MAILIMF_NO_ERROR;
5866 free_value:
5867 mailimf_unstructured_free(value);
5868 err:
5869 return res;
5873 keywords = "Keywords:" phrase *("," phrase) CRLF
5876 static int mailimf_keywords_parse(const char * message, size_t length,
5877 size_t * index,
5878 struct mailimf_keywords ** result)
5880 struct mailimf_keywords * keywords;
5881 clist * list;
5882 size_t cur_token;
5883 int r;
5884 int res;
5886 cur_token = * index;
5888 r = mailimf_token_case_insensitive_parse(message, length,
5889 &cur_token, "Keywords");
5890 if (r != MAILIMF_NO_ERROR) {
5891 res = r;
5892 goto err;
5895 r = mailimf_colon_parse(message, length, &cur_token);
5896 if (r != MAILIMF_NO_ERROR) {
5897 res = r;
5898 goto err;
5901 r = mailimf_struct_list_parse(message, length, &cur_token,
5902 &list, ',',
5903 (mailimf_struct_parser *)
5904 mailimf_phrase_parse,
5905 (mailimf_struct_destructor *)
5906 mailimf_phrase_free);
5907 if (r != MAILIMF_NO_ERROR) {
5908 res = r;
5909 goto err;
5912 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5913 if (r != MAILIMF_NO_ERROR) {
5914 res = r;
5915 goto free_list;
5918 keywords = mailimf_keywords_new(list);
5919 if (keywords == NULL) {
5920 res = MAILIMF_ERROR_MEMORY;
5921 goto free_list;
5924 * result = keywords;
5925 * index = cur_token;
5927 return MAILIMF_NO_ERROR;
5929 free_list:
5930 clist_foreach(list, (clist_func) mailimf_phrase_free, NULL);
5931 clist_free(list);
5932 err:
5933 return res;
5937 resent-date = "Resent-Date:" date-time CRLF
5940 static int
5941 mailimf_resent_date_parse(const char * message, size_t length,
5942 size_t * index, struct mailimf_orig_date ** result)
5944 struct mailimf_orig_date * orig_date;
5945 struct mailimf_date_time * date_time;
5946 size_t cur_token;
5947 int r;
5948 int res;
5950 cur_token = * index;
5952 r = mailimf_token_case_insensitive_parse(message, length,
5953 &cur_token, "Resent-Date");
5954 if (r != MAILIMF_NO_ERROR) {
5955 res = r;
5956 goto err;
5959 r = mailimf_colon_parse(message, length, &cur_token);
5960 if (r != MAILIMF_NO_ERROR) {
5961 res = r;
5962 goto err;
5965 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
5966 if (r != MAILIMF_NO_ERROR) {
5967 res = r;
5968 goto err;
5971 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5972 if (r != MAILIMF_NO_ERROR) {
5973 res = r;
5974 goto free_date_time;
5977 orig_date = mailimf_orig_date_new(date_time);
5978 if (orig_date == NULL) {
5979 res = MAILIMF_ERROR_MEMORY;
5980 goto free_date_time;
5983 * result = orig_date;
5984 * index = cur_token;
5986 return MAILIMF_NO_ERROR;
5988 free_date_time:
5989 mailimf_date_time_free(date_time);
5990 err:
5991 return res;
5995 resent-from = "Resent-From:" mailbox-list CRLF
5998 static int
5999 mailimf_resent_from_parse(const char * message, size_t length,
6000 size_t * index, struct mailimf_from ** result)
6002 struct mailimf_mailbox_list * mb_list;
6003 struct mailimf_from * from;
6004 size_t cur_token;
6005 int r;
6006 int res;
6008 cur_token = * index;
6010 r = mailimf_token_case_insensitive_parse(message, length,
6011 &cur_token, "Resent-From");
6012 if (r != MAILIMF_NO_ERROR) {
6013 res = r;
6014 goto err;
6017 r = mailimf_colon_parse(message, length, &cur_token);
6018 if (r != MAILIMF_NO_ERROR) {
6019 res = r;
6020 goto err;
6023 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
6024 if (r != MAILIMF_NO_ERROR) {
6025 res = r;
6026 goto err;
6029 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6030 if (r != MAILIMF_NO_ERROR) {
6031 res = r;
6032 goto free_mb_list;
6035 from = mailimf_from_new(mb_list);
6036 if (from == NULL) {
6037 res = MAILIMF_ERROR_MEMORY;
6038 goto free_mb_list;
6041 * result = from;
6042 * index = cur_token;
6044 return MAILIMF_NO_ERROR;
6046 free_mb_list:
6047 mailimf_mailbox_list_free(mb_list);
6048 err:
6049 return res;
6053 resent-sender = "Resent-Sender:" mailbox CRLF
6056 static int
6057 mailimf_resent_sender_parse(const char * message, size_t length,
6058 size_t * index, struct mailimf_sender ** result)
6060 struct mailimf_mailbox * mb;
6061 struct mailimf_sender * sender;
6062 size_t cur_token;
6063 int r;
6064 int res;
6066 cur_token = length;
6068 r = mailimf_token_case_insensitive_parse(message, length,
6069 &cur_token, "Resent-Sender");
6070 if (r != MAILIMF_NO_ERROR) {
6071 res = r;
6072 goto err;
6075 r = mailimf_colon_parse(message, length, &cur_token);
6076 if (r != MAILIMF_NO_ERROR) {
6077 res = r;
6078 goto err;
6081 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
6082 if (r != MAILIMF_NO_ERROR) {
6083 res = r;
6084 goto err;
6087 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6088 if (r != MAILIMF_NO_ERROR) {
6089 res = r;
6090 goto free_mb;
6093 sender = mailimf_sender_new(mb);
6094 if (sender == NULL) {
6095 res = MAILIMF_ERROR_MEMORY;
6096 goto free_mb;
6099 * result = sender;
6100 * index = cur_token;
6102 return MAILIMF_NO_ERROR;
6104 free_mb:
6105 mailimf_mailbox_free(mb);
6106 err:
6107 return res;
6111 resent-to = "Resent-To:" address-list CRLF
6114 static int
6115 mailimf_resent_to_parse(const char * message, size_t length,
6116 size_t * index, struct mailimf_to ** result)
6118 struct mailimf_address_list * addr_list;
6119 struct mailimf_to * to;
6120 size_t cur_token;
6121 int r;
6122 int res;
6124 cur_token = * index;
6126 r = mailimf_token_case_insensitive_parse(message, length,
6127 &cur_token, "Resent-To");
6128 if (r != MAILIMF_NO_ERROR) {
6129 res = r;
6130 goto err;
6133 r = mailimf_colon_parse(message, length, &cur_token);
6134 if (r != MAILIMF_NO_ERROR) {
6135 res = r;
6136 goto err;
6139 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6140 if (r != MAILIMF_NO_ERROR) {
6141 res = r;
6142 goto err;
6145 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6146 if (r != MAILIMF_NO_ERROR) {
6147 res = r;
6148 goto free_addr_list;
6151 to = mailimf_to_new(addr_list);
6152 if (to == NULL) {
6153 res = MAILIMF_ERROR_MEMORY;
6154 goto free_addr_list;
6157 * result = to;
6158 * index = cur_token;
6160 return MAILIMF_NO_ERROR;
6162 free_addr_list:
6163 mailimf_address_list_free(addr_list);
6164 err:
6165 return res;
6169 resent-cc = "Resent-Cc:" address-list CRLF
6172 static int
6173 mailimf_resent_cc_parse(const char * message, size_t length,
6174 size_t * index, struct mailimf_cc ** result)
6176 struct mailimf_address_list * addr_list;
6177 struct mailimf_cc * cc;
6178 size_t cur_token;
6179 int r;
6180 int res;
6182 cur_token = * index;
6184 r = mailimf_token_case_insensitive_parse(message, length,
6185 &cur_token, "Resent-Cc");
6186 if (r != MAILIMF_NO_ERROR) {
6187 res = r;
6188 goto err;
6191 r = mailimf_colon_parse(message, length, &cur_token);
6192 if (r != MAILIMF_NO_ERROR) {
6193 res = r;
6194 goto err;
6197 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6198 if (r != MAILIMF_NO_ERROR) {
6199 res = r;
6200 goto err;
6203 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6204 if (r != MAILIMF_NO_ERROR) {
6205 res = r;
6206 goto free_addr_list;
6209 cc = mailimf_cc_new(addr_list);
6210 if (cc == NULL) {
6211 res = MAILIMF_ERROR_MEMORY;
6212 goto free_addr_list;
6215 * result = cc;
6216 * index = cur_token;
6218 return MAILIMF_NO_ERROR;
6220 free_addr_list:
6221 mailimf_address_list_free(addr_list);
6222 err:
6223 return res;
6227 resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF
6230 static int
6231 mailimf_resent_bcc_parse(const char * message, size_t length,
6232 size_t * index, struct mailimf_bcc ** result)
6234 struct mailimf_address_list * addr_list;
6235 struct mailimf_bcc * bcc;
6236 size_t cur_token;
6237 int r;
6238 int res;
6240 cur_token = * index;
6241 bcc = NULL;
6243 r = mailimf_token_case_insensitive_parse(message, length,
6244 &cur_token, "Resent-Bcc");
6245 if (r != MAILIMF_NO_ERROR) {
6246 res = r;
6247 goto err;
6250 r = mailimf_colon_parse(message, length, &cur_token);
6251 if (r != MAILIMF_NO_ERROR) {
6252 res = r;
6253 goto err;
6256 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6257 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6258 res = r;
6259 goto err;
6262 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6263 if (r != MAILIMF_NO_ERROR) {
6264 res = r;
6265 goto free_addr_list;
6268 bcc = mailimf_bcc_new(addr_list);
6269 if (bcc == NULL) {
6270 res = MAILIMF_ERROR_MEMORY;
6271 goto free_addr_list;
6274 * result = bcc;
6275 * index = cur_token;
6277 return TRUE;
6279 free_addr_list:
6280 mailimf_address_list_free(addr_list);
6281 err:
6282 return res;
6286 resent-msg-id = "Resent-Message-ID:" msg-id CRLF
6289 static int
6290 mailimf_resent_msg_id_parse(const char * message, size_t length,
6291 size_t * index,
6292 struct mailimf_message_id ** result)
6294 char * value;
6295 size_t cur_token;
6296 struct mailimf_message_id * message_id;
6297 int r;
6298 int res;
6300 cur_token = * index;
6302 r = mailimf_token_case_insensitive_parse(message, length,
6303 &cur_token, "Resent-Message-ID");
6304 if (r != MAILIMF_NO_ERROR) {
6305 res = r;
6306 goto err;
6309 r = mailimf_colon_parse(message, length, &cur_token);
6310 if (r != MAILIMF_NO_ERROR) {
6311 res = r;
6312 goto err;
6315 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
6316 if (r != MAILIMF_NO_ERROR) {
6317 res = r;
6318 goto err;
6321 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6322 if (r != MAILIMF_NO_ERROR) {
6323 res = r;
6324 goto free_value;
6327 message_id = mailimf_message_id_new(value);
6328 if (message_id == NULL) {
6329 res = MAILIMF_ERROR_MEMORY;
6330 goto free_value;
6333 * result = message_id;
6334 * index = cur_token;
6336 return MAILIMF_NO_ERROR;
6338 free_value:
6339 mailimf_msg_id_free(value);
6340 err:
6341 return res;
6345 trace = [return]
6346 1*received
6349 #if 0
6350 static int mailimf_trace_parse(const char * message, size_t length,
6351 size_t * index,
6352 struct mailimf_trace ** result)
6354 size_t cur_token;
6355 struct mailimf_return * return_path;
6356 clist * received_list;
6357 struct mailimf_trace * trace;
6358 int r;
6359 int res;
6361 cur_token = * index;
6362 return_path = NULL;
6363 received_list = NULL;
6365 r = mailimf_return_parse(message, length, &cur_token, &return_path);
6366 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6367 res = r;
6368 goto err;
6371 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6372 &received_list,
6373 (mailimf_struct_parser *)
6374 mailimf_received_parse,
6375 (mailimf_struct_destructor *)
6376 mailimf_received_free);
6377 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6378 res = r;
6379 goto err;
6382 if ((received_list == NULL) && (return_path == NULL)) {
6383 res = MAILIMF_ERROR_PARSE;
6384 goto free_return;
6387 trace = mailimf_trace_new(return_path, received_list);
6388 if (trace == NULL) {
6389 res = MAILIMF_ERROR_MEMORY;
6390 goto free_list;
6393 * result = trace;
6394 * index = cur_token;
6396 return MAILIMF_NO_ERROR;
6398 free_list:
6399 clist_foreach(received_list, (clist_func) mailimf_received_free, NULL);
6400 clist_free(received_list);
6401 free_return:
6402 if (return_path != NULL)
6403 mailimf_return_free(return_path);
6404 err:
6405 return res;
6407 #endif
6410 return = "Return-Path:" path CRLF
6413 static int mailimf_return_parse(const char * message, size_t length,
6414 size_t * index,
6415 struct mailimf_return ** result)
6417 struct mailimf_path * path = NULL;
6418 struct mailimf_return * return_path;
6419 size_t cur_token;
6420 int r;
6421 int res;
6423 cur_token = * index;
6425 r = mailimf_token_case_insensitive_parse(message, length,
6426 &cur_token, "Return-Path");
6427 if (r != MAILIMF_NO_ERROR) {
6428 res = r;
6429 goto err;
6432 r = mailimf_colon_parse(message, length, &cur_token);
6433 if (r != MAILIMF_NO_ERROR) {
6434 res = r;
6435 goto err;
6438 r = mailimf_path_parse(message, length, &cur_token, &path);
6439 if ( r!= MAILIMF_NO_ERROR) {
6440 res = r;
6441 goto err;
6444 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6445 if (r != MAILIMF_NO_ERROR) {
6446 res = r;
6447 goto free_path;
6450 return_path = mailimf_return_new(path);
6451 if (return_path == NULL) {
6452 res = MAILIMF_ERROR_MEMORY;
6453 goto free_path;
6456 * result = return_path;
6457 * index = cur_token;
6459 return MAILIMF_NO_ERROR;
6461 free_path:
6462 mailimf_path_free(path);
6463 err:
6464 return res;
6468 path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
6469 obs-path
6472 static int mailimf_path_parse(const char * message, size_t length,
6473 size_t * index, struct mailimf_path ** result)
6475 size_t cur_token;
6476 char * addr_spec;
6477 struct mailimf_path * path;
6478 int res;
6479 int r;
6481 cur_token = * index;
6482 addr_spec = NULL;
6484 r = mailimf_cfws_parse(message, length, &cur_token);
6485 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6486 res = r;
6487 goto err;
6490 r = mailimf_lower_parse(message, length, &cur_token);
6491 if (r != MAILIMF_NO_ERROR) {
6492 res = r;
6493 goto err;
6496 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
6497 switch (r) {
6498 case MAILIMF_NO_ERROR:
6499 break;
6500 case MAILIMF_ERROR_PARSE:
6501 r = mailimf_cfws_parse(message, length, &cur_token);
6502 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6503 res = r;
6504 goto err;
6506 break;
6507 default:
6508 return r;
6511 r = mailimf_greater_parse(message, length, &cur_token);
6512 if (r != MAILIMF_NO_ERROR) {
6513 res = r;
6514 goto free_addr_spec;
6517 path = mailimf_path_new(addr_spec);
6518 if (path == NULL) {
6519 res = MAILIMF_ERROR_MEMORY;
6520 goto free_addr_spec;
6523 * index = cur_token;
6524 * result = path;
6526 return MAILIMF_NO_ERROR;
6528 free_addr_spec:
6529 if (addr_spec != NULL)
6530 mailimf_addr_spec_free(addr_spec);
6531 err:
6532 return res;
6536 received = "Received:" name-val-list ";" date-time CRLF
6539 #if 0
6540 static int mailimf_received_parse(const char * message, size_t length,
6541 size_t * index,
6542 struct mailimf_received ** result)
6544 size_t cur_token;
6545 struct mailimf_received * received;
6546 struct mailimf_name_val_list * name_val_list;
6547 struct mailimf_date_time * date_time;
6548 int r;
6549 int res;
6551 cur_token = * index;
6553 r = mailimf_token_case_insensitive_parse(message, length,
6554 &cur_token, "Received");
6555 if (r != MAILIMF_NO_ERROR) {
6556 res = r;
6557 goto err;
6560 r = mailimf_colon_parse(message, length, &cur_token);
6561 if (r != MAILIMF_NO_ERROR) {
6562 res = r;
6563 goto err;
6566 r = mailimf_name_val_list_parse(message, length,
6567 &cur_token, &name_val_list);
6568 if (r != MAILIMF_NO_ERROR) {
6569 res = r;
6570 goto err;
6573 r = mailimf_semi_colon_parse(message, length, &cur_token);
6574 if (r != MAILIMF_NO_ERROR) {
6575 res = r;
6576 goto free_name_val_list;
6579 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
6580 if (r != MAILIMF_NO_ERROR) {
6581 res = r;
6582 goto free_name_val_list;
6585 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6586 if (r != MAILIMF_NO_ERROR) {
6587 res = r;
6588 goto free_date_time;
6591 received = mailimf_received_new(name_val_list, date_time);
6592 if (received == NULL) {
6593 res = MAILIMF_ERROR_MEMORY;
6594 goto free_date_time;
6597 * index = cur_token;
6598 * result = received;
6600 return MAILIMF_NO_ERROR;
6602 free_date_time:
6603 mailimf_date_time_free(date_time);
6604 free_name_val_list:
6605 mailimf_name_val_list_free(name_val_list);
6606 err:
6607 return res;
6609 #endif
6612 name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
6615 #if 0
6616 static int
6617 mailimf_name_val_list_parse(const char * message, size_t length,
6618 size_t * index,
6619 struct mailimf_name_val_list ** result)
6621 size_t cur_token;
6622 struct mailimf_name_val_pair * pair;
6623 struct mailimf_name_val_list * name_val_list;
6624 clist* list;
6625 int res;
6626 int r;
6628 cur_token = * index;
6629 list = NULL;
6631 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6633 if (r == MAILIMF_NO_ERROR){
6634 size_t final_token;
6636 list = clist_new();
6637 if (list == NULL) {
6638 mailimf_name_val_pair_free(pair);
6639 res = MAILIMF_ERROR_MEMORY;
6640 goto err;
6643 r = clist_append(list, pair);
6644 if (r < 0) {
6645 mailimf_name_val_pair_free(pair);
6646 res = MAILIMF_ERROR_MEMORY;
6647 goto free_list;
6650 final_token = cur_token;
6652 while (1) {
6653 r = mailimf_cfws_parse(message, length, &cur_token);
6654 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6655 res = r;
6656 goto free_list;
6659 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6660 if (r == MAILIMF_NO_ERROR) {
6661 /* do nothing */
6663 else if (r == MAILIMF_ERROR_PARSE)
6664 break;
6665 else {
6666 res = r;
6667 goto free_list;
6670 r = clist_append(list, pair);
6671 if (r < 0) {
6672 mailimf_name_val_pair_free(pair);
6673 res = MAILIMF_ERROR_MEMORY;
6674 goto free_list;
6677 final_token = cur_token;
6679 cur_token = final_token;
6682 name_val_list = mailimf_name_val_list_new(list);
6683 if (name_val_list == NULL) {
6684 res = MAILIMF_ERROR_MEMORY;
6685 goto free_list;
6688 * index = cur_token;
6689 * result = name_val_list;
6691 return MAILIMF_NO_ERROR;
6693 free_list:
6694 if (list != NULL) {
6695 clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL);
6696 clist_free(list);
6698 err:
6699 return res;
6701 #endif
6704 name-val-pair = item-name CFWS item-value
6707 #if 0
6708 static int
6709 mailimf_name_val_pair_parse(const char * message, size_t length,
6710 size_t * index,
6711 struct mailimf_name_val_pair ** result)
6713 size_t cur_token;
6714 char * item_name;
6715 struct mailimf_item_value * item_value;
6716 struct mailimf_name_val_pair * name_val_pair;
6717 int r;
6718 int res;
6720 cur_token = * index;
6722 r = mailimf_cfws_parse(message, length, &cur_token);
6723 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6724 res = r;
6725 goto err;
6728 r = mailimf_item_name_parse(message, length, &cur_token, &item_name);
6729 if (r != MAILIMF_NO_ERROR) {
6730 res = r;
6731 goto err;
6734 r = mailimf_cfws_parse(message, length, &cur_token);
6735 if (r != MAILIMF_NO_ERROR) {
6736 res = r;
6737 goto free_item_name;
6740 r = mailimf_item_value_parse(message, length, &cur_token, &item_value);
6741 if (r != MAILIMF_NO_ERROR) {
6742 res = r;
6743 goto free_item_name;
6746 name_val_pair = mailimf_name_val_pair_new(item_name, item_value);
6747 if (name_val_pair == NULL) {
6748 res = MAILIMF_ERROR_MEMORY;
6749 goto free_item_value;
6752 * result = name_val_pair;
6753 * index = cur_token;
6755 return MAILIMF_NO_ERROR;
6757 free_item_value:
6758 mailimf_item_value_free(item_value);
6759 free_item_name:
6760 mailimf_item_name_free(item_name);
6761 err:
6762 return res;
6764 #endif
6767 item-name = ALPHA *(["-"] (ALPHA / DIGIT))
6770 #if 0
6771 static int mailimf_item_name_parse(const char * message, size_t length,
6772 size_t * index, char ** result)
6774 size_t cur_token;
6775 size_t begin;
6776 char * item_name;
6777 char ch;
6778 int digit;
6779 int r;
6780 int res;
6782 cur_token = * index;
6784 begin = cur_token;
6786 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6787 if (r != MAILIMF_NO_ERROR) {
6788 res = r;
6789 goto err;
6792 while (1) {
6793 int minus_sign;
6795 minus_sign = mailimf_minus_parse(message, length, &cur_token);
6797 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6798 if (r == MAILIMF_ERROR_PARSE)
6799 r = mailimf_digit_parse(message, length, &cur_token, &digit);
6801 if (r == MAILIMF_NO_ERROR) {
6802 /* do nothing */
6804 if (r == MAILIMF_ERROR_PARSE)
6805 break;
6806 else if (r != MAILIMF_NO_ERROR) {
6807 res = r;
6808 goto err;
6812 item_name = strndup(message + begin, cur_token - begin);
6813 if (item_name == NULL) {
6814 res = MAILIMF_ERROR_MEMORY;
6815 goto err;
6818 * index = cur_token;
6819 * result = item_name;
6821 return MAILIMF_NO_ERROR;
6823 err:
6824 return res;
6826 #endif
6829 item-value = 1*angle-addr / addr-spec /
6830 atom / domain / msg-id
6833 #if 0
6834 static int is_item_value_atext(char ch)
6836 switch (ch) {
6837 case '\t':
6838 case ' ':
6839 case '\r':
6840 case '\n':
6841 case ';':
6842 return FALSE;
6843 default:
6844 return TRUE;
6848 static int mailimf_item_value_atom_parse(const char * message, size_t length,
6849 size_t * index, char ** result)
6851 char * atom;
6852 size_t cur_token;
6853 int r;
6855 cur_token = * index;
6857 r = mailimf_cfws_parse(message, length, &cur_token);
6858 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6859 return r;
6861 r = mailimf_custom_string_parse(message, length, &cur_token,
6862 &atom, is_item_value_atext);
6863 if (r != MAILIMF_NO_ERROR)
6864 return r;
6866 r = mailimf_cfws_parse(message, length, &cur_token);
6867 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6868 return r;
6870 * index = cur_token;
6871 * result = atom;
6873 return MAILIMF_NO_ERROR;
6876 static int mailimf_item_value_parse(const char * message, size_t length,
6877 size_t * index,
6878 struct mailimf_item_value ** result)
6880 size_t cur_token;
6881 clist * angle_addr_list;
6882 char * addr_spec;
6883 char * atom;
6884 char * domain;
6885 char * msg_id;
6886 int type;
6887 struct mailimf_item_value * item_value;
6888 int r;
6889 int res;
6891 cur_token = * index;
6893 angle_addr_list = NULL;
6894 addr_spec = NULL;
6895 atom = NULL;
6896 domain = NULL;
6897 msg_id = NULL;
6899 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6900 &angle_addr_list,
6901 (mailimf_struct_parser *)
6902 mailimf_angle_addr_parse,
6903 (mailimf_struct_destructor *)
6904 mailimf_angle_addr_free);
6905 if (r == MAILIMF_NO_ERROR)
6906 type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST;
6908 if (r == MAILIMF_ERROR_PARSE) {
6909 r = mailimf_addr_spec_parse(message, length, &cur_token,
6910 &addr_spec);
6911 if (r == MAILIMF_NO_ERROR)
6912 type = MAILIMF_ITEM_VALUE_ADDR_SPEC;
6915 if (r == MAILIMF_ERROR_PARSE) {
6916 r = mailimf_msg_id_parse(message, length, &cur_token,
6917 &msg_id);
6918 if (r == MAILIMF_NO_ERROR)
6919 type = MAILIMF_ITEM_VALUE_MSG_ID;
6923 else if (mailimf_domain_parse(message, length, &cur_token,
6924 &domain))
6925 type = MAILIMF_ITEM_VALUE_DOMAIN;
6928 else if (mailimf_atom_parse(message, length, &cur_token,
6929 &atom))
6930 type = MAILIMF_ITEM_VALUE_ATOM;
6933 if (r == MAILIMF_ERROR_PARSE) {
6934 r = mailimf_item_value_atom_parse(message, length, &cur_token,
6935 &atom);
6936 if (r == MAILIMF_NO_ERROR)
6937 type = MAILIMF_ITEM_VALUE_ATOM;
6940 if (r != MAILIMF_NO_ERROR) {
6941 res = r;
6942 goto err;
6945 item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec,
6946 atom, domain, msg_id);
6947 if (item_value == NULL) {
6948 res = MAILIMF_ERROR_MEMORY;
6949 goto free;
6952 * result = item_value;
6953 * index = cur_token;
6955 return MAILIMF_NO_ERROR;
6957 free:
6958 if (angle_addr_list != NULL) {
6959 clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL);
6960 clist_free(angle_addr_list);
6962 if (addr_spec != NULL)
6963 mailimf_addr_spec_free(addr_spec);
6964 if (atom != NULL)
6965 mailimf_atom_free(atom);
6966 if (domain != NULL)
6967 mailimf_domain_free(domain);
6968 if (msg_id != NULL)
6969 mailimf_msg_id_free(msg_id);
6970 err:
6971 return res;
6973 #endif
6976 optional-field = field-name ":" unstructured CRLF
6979 static int
6980 mailimf_optional_field_parse(const char * message, size_t length,
6981 size_t * index,
6982 struct mailimf_optional_field ** result)
6984 char * name;
6985 char * value;
6986 struct mailimf_optional_field * optional_field;
6987 size_t cur_token;
6988 int r;
6989 int res;
6991 name = NULL;
6992 value = NULL;
6993 optional_field = NULL;
6995 cur_token = * index;
6997 r = mailimf_field_name_parse(message, length, &cur_token, &name);
6998 if (r != MAILIMF_NO_ERROR) {
6999 res = r;
7000 goto err;
7003 r = mailimf_colon_parse(message, length, &cur_token);
7004 if (r != MAILIMF_NO_ERROR) {
7005 res = r;
7006 goto free_fields;
7009 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
7010 if (r != MAILIMF_NO_ERROR) {
7011 res = r;
7012 goto free_fields;
7015 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
7016 if (r != MAILIMF_NO_ERROR) {
7017 res = r;
7018 goto free_fields;
7021 optional_field = mailimf_optional_field_new(name, value);
7022 if (optional_field == NULL) {
7023 res = MAILIMF_ERROR_MEMORY;
7024 goto free_fields;
7027 * result = optional_field;
7028 * index = cur_token;
7030 return MAILIMF_NO_ERROR;
7032 free_fields:
7033 if (value)
7034 mailimf_unstructured_free(value);
7035 if (name)
7036 mailimf_field_name_free(name);
7038 err:
7039 return res;
7043 field-name = 1*ftext
7046 static inline int is_ftext(char ch);
7048 static int mailimf_field_name_parse(const char * message, size_t length,
7049 size_t * index, char ** result)
7051 char * field_name;
7052 size_t cur_token;
7053 size_t end;
7055 cur_token = * index;
7057 end = cur_token;
7058 if (end >= length) {
7059 return MAILIMF_ERROR_PARSE;
7062 while (is_ftext(message[end])) {
7063 end ++;
7064 if (end >= length)
7065 break;
7067 if (end == cur_token) {
7068 return MAILIMF_ERROR_PARSE;
7071 /* field_name = strndup(message + cur_token, end - cur_token); */
7072 field_name = malloc(end - cur_token + 1);
7073 if (field_name == NULL) {
7074 return MAILIMF_ERROR_MEMORY;
7076 strncpy(field_name, message + cur_token, end - cur_token);
7077 field_name[end - cur_token] = '\0';
7079 cur_token = end;
7081 * index = cur_token;
7082 * result = field_name;
7084 return MAILIMF_NO_ERROR;
7088 ftext = %d33-57 / ; Any character except
7089 %d59-126 ; controls, SP, and
7090 ; ":".
7093 static inline int is_ftext(char ch)
7095 unsigned char uch = (unsigned char) ch;
7097 if (uch < 33)
7098 return FALSE;
7100 if (uch == 58)
7101 return FALSE;
7103 return TRUE;
7107 static int mailimf_ftext_parse(const char * message, size_t length,
7108 size_t * index, gchar * result)
7110 return mailimf_typed_text_parse(message, length, index, result, is_ftext);
7117 static int mailimf_envelope_field_parse(const char * message, size_t length,
7118 size_t * index,
7119 struct mailimf_field ** result)
7121 size_t cur_token;
7122 int type;
7123 struct mailimf_orig_date * orig_date;
7124 struct mailimf_from * from;
7125 struct mailimf_sender * sender;
7126 struct mailimf_reply_to * reply_to;
7127 struct mailimf_to * to;
7128 struct mailimf_cc * cc;
7129 struct mailimf_bcc * bcc;
7130 struct mailimf_message_id * message_id;
7131 struct mailimf_in_reply_to * in_reply_to;
7132 struct mailimf_references * references;
7133 struct mailimf_subject * subject;
7134 struct mailimf_field * field;
7135 int guessed_type;
7136 int r;
7137 int res;
7139 cur_token = * index;
7141 orig_date = NULL;
7142 from = NULL;
7143 sender = NULL;
7144 reply_to = NULL;
7145 to = NULL;
7146 cc = NULL;
7147 bcc = NULL;
7148 message_id = NULL;
7149 in_reply_to = NULL;
7150 references = NULL;
7151 subject = NULL;
7153 guessed_type = guess_header_type(message, length, cur_token);
7154 type = MAILIMF_FIELD_NONE;
7156 switch (guessed_type) {
7157 case MAILIMF_FIELD_ORIG_DATE:
7158 r = mailimf_orig_date_parse(message, length, &cur_token,
7159 &orig_date);
7160 if (r == MAILIMF_NO_ERROR)
7161 type = guessed_type;
7162 else if (r == MAILIMF_ERROR_PARSE) {
7163 /* do nothing */
7165 else {
7166 res = r;
7167 goto err;
7169 break;
7170 case MAILIMF_FIELD_FROM:
7171 r = mailimf_from_parse(message, length, &cur_token,
7172 &from);
7173 if (r == MAILIMF_NO_ERROR)
7174 type = guessed_type;
7175 else if (r == MAILIMF_ERROR_PARSE) {
7176 /* do nothing */
7178 else {
7179 res = r;
7180 goto err;
7182 break;
7183 case MAILIMF_FIELD_SENDER:
7184 r = mailimf_sender_parse(message, length, &cur_token,
7185 &sender);
7186 if (r == MAILIMF_NO_ERROR)
7187 type = guessed_type;
7188 else if (r == MAILIMF_ERROR_PARSE) {
7189 /* do nothing */
7191 else {
7192 res = r;
7193 goto err;
7195 break;
7196 case MAILIMF_FIELD_REPLY_TO:
7197 r = mailimf_reply_to_parse(message, length, &cur_token,
7198 &reply_to);
7199 if (r == MAILIMF_NO_ERROR)
7200 type = guessed_type;
7201 else if (r == MAILIMF_ERROR_PARSE) {
7202 /* do nothing */
7204 else {
7205 res = r;
7206 goto err;
7208 break;
7209 case MAILIMF_FIELD_TO:
7210 r = mailimf_to_parse(message, length, &cur_token,
7211 &to);
7212 if (r == MAILIMF_NO_ERROR)
7213 type = guessed_type;
7214 else if (r == MAILIMF_ERROR_PARSE) {
7215 /* do nothing */
7217 else {
7218 res = r;
7219 goto err;
7221 break;
7222 case MAILIMF_FIELD_CC:
7223 r = mailimf_cc_parse(message, length, &cur_token,
7224 &cc);
7225 if (r == MAILIMF_NO_ERROR)
7226 type = guessed_type;
7227 else if (r == MAILIMF_ERROR_PARSE) {
7228 /* do nothing */
7230 else {
7231 res = r;
7232 goto err;
7234 break;
7235 case MAILIMF_FIELD_BCC:
7236 r = mailimf_bcc_parse(message, length, &cur_token,
7237 &bcc);
7238 if (r == MAILIMF_NO_ERROR)
7239 type = guessed_type;
7240 else if (r == MAILIMF_ERROR_PARSE) {
7241 /* do nothing */
7243 else {
7244 res = r;
7245 goto err;
7247 break;
7248 case MAILIMF_FIELD_MESSAGE_ID:
7249 r = mailimf_message_id_parse(message, length, &cur_token,
7250 &message_id);
7251 if (r == MAILIMF_NO_ERROR)
7252 type = guessed_type;
7253 else if (r == MAILIMF_ERROR_PARSE) {
7254 /* do nothing */
7256 else {
7257 res = r;
7258 goto err;
7260 break;
7261 case MAILIMF_FIELD_IN_REPLY_TO:
7262 r = mailimf_in_reply_to_parse(message, length, &cur_token,
7263 &in_reply_to);
7264 if (r == MAILIMF_NO_ERROR)
7265 type = guessed_type;
7266 else if (r == MAILIMF_ERROR_PARSE) {
7267 /* do nothing */
7269 else {
7270 res = r;
7271 goto err;
7273 break;
7274 case MAILIMF_FIELD_REFERENCES:
7275 r = mailimf_references_parse(message, length, &cur_token,
7276 &references);
7277 if (r == MAILIMF_NO_ERROR)
7278 type = guessed_type;
7279 else if (r == MAILIMF_ERROR_PARSE) {
7280 /* do nothing */
7282 else {
7283 res = r;
7284 goto err;
7286 break;
7287 case MAILIMF_FIELD_SUBJECT:
7288 r = mailimf_subject_parse(message, length, &cur_token,
7289 &subject);
7290 if (r == MAILIMF_NO_ERROR)
7291 type = guessed_type;
7292 else if (r == MAILIMF_ERROR_PARSE) {
7293 /* do nothing */
7295 else {
7296 res = r;
7297 goto err;
7299 break;
7302 if (type == MAILIMF_FIELD_NONE) {
7303 res = MAILIMF_ERROR_PARSE;
7304 goto err;
7307 field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
7308 NULL, NULL, NULL,
7309 orig_date, from, sender, reply_to, to,
7310 cc, bcc, message_id, in_reply_to, references,
7311 subject, NULL, NULL, NULL);
7312 if (field == NULL) {
7313 res = MAILIMF_ERROR_MEMORY;
7314 goto free_fields;
7317 * result = field;
7318 * index = cur_token;
7320 return MAILIMF_NO_ERROR;
7322 free_fields:
7323 if (orig_date != NULL)
7324 mailimf_orig_date_free(orig_date);
7325 if (from != NULL)
7326 mailimf_from_free(from);
7327 if (sender != NULL)
7328 mailimf_sender_free(sender);
7329 if (reply_to != NULL)
7330 mailimf_reply_to_free(reply_to);
7331 if (to != NULL)
7332 mailimf_to_free(to);
7333 if (cc != NULL)
7334 mailimf_cc_free(cc);
7335 if (bcc != NULL)
7336 mailimf_bcc_free(bcc);
7337 if (message_id != NULL)
7338 mailimf_message_id_free(message_id);
7339 if (in_reply_to != NULL)
7340 mailimf_in_reply_to_free(in_reply_to);
7341 if (references != NULL)
7342 mailimf_references_free(references);
7343 if (subject != NULL)
7344 mailimf_subject_free(subject);
7345 err:
7346 return res;
7349 int mailimf_envelope_fields_parse(const char * message, size_t length,
7350 size_t * index,
7351 struct mailimf_fields ** result)
7353 size_t cur_token;
7354 clist * list;
7355 struct mailimf_fields * fields;
7356 int r;
7357 int res;
7359 cur_token = * index;
7361 list = clist_new();
7362 if (list == NULL) {
7363 res = MAILIMF_ERROR_MEMORY;
7364 goto err;
7367 while (1) {
7368 struct mailimf_field * elt;
7370 r = mailimf_envelope_field_parse(message, length, &cur_token, &elt);
7371 if (r == MAILIMF_NO_ERROR) {
7372 r = clist_append(list, elt);
7373 if (r < 0) {
7374 res = MAILIMF_ERROR_MEMORY;
7375 goto free;
7378 else if (r == MAILIMF_ERROR_PARSE) {
7379 r = mailimf_ignore_field_parse(message, length, &cur_token);
7380 if (r == MAILIMF_NO_ERROR) {
7381 /* do nothing */
7383 else if (r == MAILIMF_ERROR_PARSE) {
7384 break;
7386 else {
7387 res = r;
7388 goto free;
7391 else {
7392 res = r;
7393 goto free;
7397 fields = mailimf_fields_new(list);
7398 if (fields == NULL) {
7399 res = MAILIMF_ERROR_MEMORY;
7400 goto free;
7403 * result = fields;
7404 * index = cur_token;
7406 return MAILIMF_NO_ERROR;
7408 free:
7409 if (list != NULL) {
7410 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7411 clist_free(list);
7413 err:
7414 return res;
7418 static int
7419 mailimf_envelope_or_optional_field_parse(const char * message,
7420 size_t length,
7421 size_t * index,
7422 struct mailimf_field ** result)
7424 int r;
7425 size_t cur_token;
7426 struct mailimf_optional_field * optional_field;
7427 struct mailimf_field * field;
7429 r = mailimf_envelope_field_parse(message, length, index, result);
7430 if (r == MAILIMF_NO_ERROR)
7431 return MAILIMF_NO_ERROR;
7433 cur_token = * index;
7435 r = mailimf_optional_field_parse(message, length, &cur_token,
7436 &optional_field);
7437 if (r != MAILIMF_NO_ERROR)
7438 return r;
7440 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL,
7441 NULL, NULL, NULL,
7442 NULL, NULL, NULL,
7443 NULL, NULL, NULL,
7444 NULL, NULL, NULL,
7445 NULL, NULL, NULL, NULL, NULL,
7446 NULL, NULL, NULL, optional_field);
7447 if (field == NULL) {
7448 mailimf_optional_field_free(optional_field);
7449 return MAILIMF_ERROR_MEMORY;
7452 * result = field;
7453 * index = cur_token;
7455 return MAILIMF_NO_ERROR;
7460 mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
7461 size_t * index,
7462 struct mailimf_fields ** result)
7464 size_t cur_token;
7465 clist * list;
7466 struct mailimf_fields * fields;
7467 int r;
7468 int res;
7470 cur_token = * index;
7472 list = NULL;
7474 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7475 &list,
7476 (mailimf_struct_parser *)
7477 mailimf_envelope_or_optional_field_parse,
7478 (mailimf_struct_destructor *)
7479 mailimf_field_free);
7480 switch (r) {
7481 case MAILIMF_NO_ERROR:
7482 /* do nothing */
7483 break;
7485 case MAILIMF_ERROR_PARSE:
7486 list = clist_new();
7487 if (list == NULL) {
7488 res = MAILIMF_ERROR_MEMORY;
7489 goto err;
7491 break;
7493 default:
7494 res = r;
7495 goto err;
7498 fields = mailimf_fields_new(list);
7499 if (fields == NULL) {
7500 res = MAILIMF_ERROR_MEMORY;
7501 goto free;
7504 * result = fields;
7505 * index = cur_token;
7507 return MAILIMF_NO_ERROR;
7509 free:
7510 if (list != NULL) {
7511 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7512 clist_free(list);
7514 err:
7515 return res;
7520 static int
7521 mailimf_only_optional_field_parse(const char * message,
7522 size_t length,
7523 size_t * index,
7524 struct mailimf_field ** result)
7526 int r;
7527 size_t cur_token;
7528 struct mailimf_optional_field * optional_field;
7529 struct mailimf_field * field;
7531 cur_token = * index;
7533 r = mailimf_optional_field_parse(message, length, &cur_token,
7534 &optional_field);
7535 if (r != MAILIMF_NO_ERROR)
7536 return r;
7538 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL,
7539 NULL, NULL, NULL, NULL, NULL,
7540 NULL, NULL, NULL, NULL, NULL,
7541 NULL, NULL, NULL, NULL, NULL,
7542 NULL, NULL, NULL, optional_field);
7543 if (field == NULL) {
7544 mailimf_optional_field_free(optional_field);
7545 return MAILIMF_ERROR_MEMORY;
7548 * result = field;
7549 * index = cur_token;
7551 return MAILIMF_NO_ERROR;
7556 mailimf_optional_fields_parse(const char * message, size_t length,
7557 size_t * index,
7558 struct mailimf_fields ** result)
7560 size_t cur_token;
7561 clist * list;
7562 struct mailimf_fields * fields;
7563 int r;
7564 int res;
7566 cur_token = * index;
7568 list = NULL;
7570 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7571 &list,
7572 (mailimf_struct_parser *)
7573 mailimf_only_optional_field_parse,
7574 (mailimf_struct_destructor *)
7575 mailimf_field_free);
7576 switch (r) {
7577 case MAILIMF_NO_ERROR:
7578 /* do nothing */
7579 break;
7581 case MAILIMF_ERROR_PARSE:
7582 list = clist_new();
7583 if (list == NULL) {
7584 res = MAILIMF_ERROR_MEMORY;
7585 goto err;
7587 break;
7589 default:
7590 res = r;
7591 goto err;
7594 fields = mailimf_fields_new(list);
7595 if (fields == NULL) {
7596 res = MAILIMF_ERROR_MEMORY;
7597 goto free;
7600 * result = fields;
7601 * index = cur_token;
7603 return MAILIMF_NO_ERROR;
7605 free:
7606 if (list != NULL) {
7607 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7608 clist_free(list);
7610 err:
7611 return res;