2 * libEtPan! -- a mail stuff library
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
38 #include "claws-features.h"
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.
57 #include <mmapstring.h>
75 static inline int is_dtext(char ch);
77 static int mailimf_quoted_pair_parse(const char * message, size_t length,
78 size_t * index, char * result);
80 static int mailimf_ccontent_parse(const char * message, size_t length,
84 mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
87 static inline int mailimf_comment_parse(const char * message, size_t length,
90 static int mailimf_qcontent_parse(const char * message, size_t length,
91 size_t * index, char * ch);
93 static int mailimf_phrase_parse(const char * message, size_t length,
94 size_t * index, char ** result);
96 static int mailimf_unstructured_parse(const char * message, size_t length,
97 size_t * index, char ** result);
99 static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
102 static int mailimf_day_of_week_parse(const char * message, size_t length,
103 size_t * index, int * result);
105 static int mailimf_day_name_parse(const char * message, size_t length,
106 size_t * index, int * result);
108 static int mailimf_date_parse(const char * message, size_t length,
110 int * pday, int * pmonth, int * pyear);
112 static int mailimf_year_parse(const char * message, size_t length,
113 size_t * index, int * result);
115 static int mailimf_month_parse(const char * message, size_t length,
116 size_t * index, int * result);
118 static int mailimf_month_name_parse(const char * message, size_t length,
119 size_t * index, int * result);
121 static int mailimf_day_parse(const char * message, size_t length,
122 size_t * index, int * result);
124 static int mailimf_time_parse(const char * message, size_t length,
126 int * phour, int * pmin,
129 static int mailimf_time_of_day_parse(const char * message, size_t length,
131 int * phour, int * pmin,
134 static int mailimf_hour_parse(const char * message, size_t length,
135 size_t * index, int * result);
137 static int mailimf_minute_parse(const char * message, size_t length,
138 size_t * index, int * result);
140 static int mailimf_second_parse(const char * message, size_t length,
141 size_t * index, int * result);
143 static int mailimf_zone_parse(const char * message, size_t length,
144 size_t * index, int * result);
146 static int mailimf_name_addr_parse(const char * message, size_t length,
148 char ** pdisplay_name,
149 char ** pangle_addr);
151 static int mailimf_angle_addr_parse(const char * message, size_t length,
152 size_t * index, char ** result);
154 static int mailimf_group_parse(const char * message, size_t length,
156 struct mailimf_group ** result);
158 static int mailimf_display_name_parse(const char * message, size_t length,
159 size_t * index, char ** result);
161 static int mailimf_addr_spec_parse(const char * message, size_t length,
166 static int mailimf_local_part_parse(const char * message, size_t length,
170 static int mailimf_domain_parse(const char * message, size_t length,
176 static int mailimf_domain_literal_parse(const char * message, size_t length,
177 size_t * index, char ** result);
181 static int mailimf_dcontent_parse(const char * message, size_t length,
182 size_t * index, char * result);
186 mailimf_orig_date_parse(const char * message, size_t length,
187 size_t * index, struct mailimf_orig_date ** result);
190 mailimf_from_parse(const char * message, size_t length,
191 size_t * index, struct mailimf_from ** result);
194 mailimf_sender_parse(const char * message, size_t length,
195 size_t * index, struct mailimf_sender ** result);
198 mailimf_reply_to_parse(const char * message, size_t length,
199 size_t * index, struct mailimf_reply_to ** result);
202 mailimf_to_parse(const char * message, size_t length,
203 size_t * index, struct mailimf_to ** result);
206 mailimf_cc_parse(const char * message, size_t length,
207 size_t * index, struct mailimf_cc ** result);
210 mailimf_bcc_parse(const char * message, size_t length,
211 size_t * index, struct mailimf_bcc ** result);
213 static int mailimf_message_id_parse(const char * message, size_t length,
215 struct mailimf_message_id ** result);
218 mailimf_in_reply_to_parse(const char * message, size_t length,
220 struct mailimf_in_reply_to ** result);
223 static int mailimf_references_parse(const char * message, size_t length,
225 struct mailimf_references **
229 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
234 static int mailimf_id_left_parse(const char * message, size_t length,
235 size_t * index, char ** result);
237 static int mailimf_id_right_parse(const char * message, size_t length,
238 size_t * index, char ** result);
242 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
243 size_t * index, char ** result);
245 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
246 size_t * index, char ** result);
249 static int mailimf_subject_parse(const char * message, size_t length,
251 struct mailimf_subject ** result);
253 static int mailimf_comments_parse(const char * message, size_t length,
255 struct mailimf_comments ** result);
257 static int mailimf_keywords_parse(const char * message, size_t length,
259 struct mailimf_keywords ** result);
262 mailimf_resent_date_parse(const char * message, size_t length,
263 size_t * index, struct mailimf_orig_date ** result);
266 mailimf_resent_from_parse(const char * message, size_t length,
267 size_t * index, struct mailimf_from ** result);
270 mailimf_resent_sender_parse(const char * message, size_t length,
271 size_t * index, struct mailimf_sender ** result);
274 mailimf_resent_to_parse(const char * message, size_t length,
275 size_t * index, struct mailimf_to ** result);
278 mailimf_resent_cc_parse(const char * message, size_t length,
279 size_t * index, struct mailimf_cc ** result);
282 mailimf_resent_bcc_parse(const char * message, size_t length,
283 size_t * index, struct mailimf_bcc ** result);
286 mailimf_resent_msg_id_parse(const char * message, size_t length,
288 struct mailimf_message_id ** result);
290 static int mailimf_return_parse(const char * message, size_t length,
292 struct mailimf_return ** result);
295 mailimf_path_parse(const char * message, size_t length,
296 size_t * index, struct mailimf_path ** result);
299 mailimf_optional_field_parse(const char * message, size_t length,
301 struct mailimf_optional_field ** result);
303 static int mailimf_field_name_parse(const char * message, size_t length,
304 size_t * index, char ** result);
330 /* *************************************************************** */
332 static inline int is_digit(char ch)
334 return (ch >= '0') && (ch <= '9');
337 static int mailimf_digit_parse(const char * message, size_t length,
338 size_t * index, int * result)
344 if (cur_token >= length)
345 return MAILIMF_ERROR_PARSE;
347 if (is_digit(message[cur_token])) {
348 * result = message[cur_token] - '0';
351 return MAILIMF_NO_ERROR;
354 return MAILIMF_ERROR_PARSE;
358 mailimf_number_parse(const char * message, size_t length,
359 size_t * index, uint32_t * result)
372 r = mailimf_digit_parse(message, length, &cur_token, &digit);
373 if (r != MAILIMF_NO_ERROR) {
374 if (r == MAILIMF_ERROR_PARSE)
385 return MAILIMF_ERROR_PARSE;
390 return MAILIMF_NO_ERROR;
393 int mailimf_char_parse(const char * message, size_t length,
394 size_t * index, char token)
400 if (cur_token >= length)
401 return MAILIMF_ERROR_PARSE;
403 if (message[cur_token] == token) {
406 return MAILIMF_NO_ERROR;
409 return MAILIMF_ERROR_PARSE;
412 int mailimf_unstrict_char_parse(const char * message, size_t length,
413 size_t * index, char token)
420 r = mailimf_cfws_parse(message, length, &cur_token);
421 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
424 r = mailimf_char_parse(message, length, &cur_token, token);
425 if (r != MAILIMF_NO_ERROR)
430 return MAILIMF_NO_ERROR;
434 mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
435 size_t * index, char * token,
442 if (cur_token + token_length - 1 >= length)
443 return MAILIMF_ERROR_PARSE;
445 if (strncasecmp(message + cur_token, token, token_length) == 0) {
446 cur_token += token_length;
448 return MAILIMF_NO_ERROR;
451 return MAILIMF_ERROR_PARSE;
454 static int mailimf_oparenth_parse(const char * message, size_t length,
457 return mailimf_char_parse(message, length, index, '(');
460 static int mailimf_cparenth_parse(const char * message, size_t length,
463 return mailimf_char_parse(message, length, index, ')');
466 static int mailimf_comma_parse(const char * message, size_t length,
469 return mailimf_unstrict_char_parse(message, length, index, ',');
472 static int mailimf_dquote_parse(const char * message, size_t length,
475 return mailimf_char_parse(message, length, index, '\"');
478 static int mailimf_colon_parse(const char * message, size_t length,
481 return mailimf_unstrict_char_parse(message, length, index, ':');
484 static int mailimf_semi_colon_parse(const char * message, size_t length,
487 return mailimf_unstrict_char_parse(message, length, index, ';');
490 static int mailimf_plus_parse(const char * message, size_t length,
493 return mailimf_unstrict_char_parse(message, length, index, '+');
496 static int mailimf_minus_parse(const char * message, size_t length,
499 return mailimf_unstrict_char_parse(message, length, index, '-');
502 static int mailimf_lower_parse(const char * message, size_t length,
505 return mailimf_unstrict_char_parse(message, length, index, '<');
508 static int mailimf_greater_parse(const char * message, size_t length,
511 return mailimf_unstrict_char_parse(message, length, index, '>');
515 static int mailimf_obracket_parse(const char * message, size_t length,
518 return mailimf_unstrict_char_parse(message, length, index, '[');
521 static int mailimf_cbracket_parse(const char * message, size_t length,
524 return mailimf_unstrict_char_parse(message, length, index, ']');
528 static int mailimf_at_sign_parse(const char * message, size_t length,
531 return mailimf_unstrict_char_parse(message, length, index, '@');
534 static int mailimf_point_parse(const char * message, size_t length,
537 return mailimf_unstrict_char_parse(message, length, index, '.');
541 mailimf_custom_string_parse(const char * message, size_t length,
542 size_t * index, char ** result,
543 int (* is_custom_char)(char))
554 return MAILIMF_ERROR_PARSE;
556 while (is_custom_char(message[end])) {
564 gstr = strndup(message + begin, end - begin);
566 gstr = malloc(end - begin + 1);
568 return MAILIMF_ERROR_MEMORY;
569 strncpy(gstr, message + begin, end - begin);
570 gstr[end - begin] = '\0';
574 return MAILIMF_NO_ERROR;
577 return MAILIMF_ERROR_PARSE;
586 typedef int mailimf_struct_parser(const char * message, size_t length,
587 size_t * index, void * result);
589 typedef int mailimf_struct_destructor(void * result);
593 mailimf_struct_multiple_parse(const char * message, size_t length,
594 size_t * index, clist ** result,
595 mailimf_struct_parser * parser,
596 mailimf_struct_destructor * destructor)
606 r = parser(message, length, &cur_token, &value);
607 if (r != MAILIMF_NO_ERROR) {
612 struct_list = clist_new();
613 if (struct_list == NULL) {
615 res = MAILIMF_ERROR_MEMORY;
619 r = clist_append(struct_list, value);
622 res = MAILIMF_ERROR_MEMORY;
627 r = parser(message, length, &cur_token, &value);
628 if (r != MAILIMF_NO_ERROR) {
629 if (r == MAILIMF_ERROR_PARSE)
636 r = clist_append(struct_list, value);
638 (* destructor)(value);
639 res = MAILIMF_ERROR_MEMORY;
644 * result = struct_list;
647 return MAILIMF_NO_ERROR;
650 clist_foreach(struct_list, (clist_func) destructor, NULL);
651 clist_free(struct_list);
659 mailimf_struct_list_parse(const char * message, size_t length,
660 size_t * index, clist ** result,
662 mailimf_struct_parser * parser,
663 mailimf_struct_destructor * destructor)
674 r = parser(message, length, &cur_token, &value);
675 if (r != MAILIMF_NO_ERROR) {
680 struct_list = clist_new();
681 if (struct_list == NULL) {
683 res = MAILIMF_ERROR_MEMORY;
687 r = clist_append(struct_list, value);
690 res = MAILIMF_ERROR_MEMORY;
694 final_token = cur_token;
697 r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol);
698 if (r != MAILIMF_NO_ERROR) {
699 if (r == MAILIMF_ERROR_PARSE)
707 r = parser(message, length, &cur_token, &value);
708 if (r != MAILIMF_NO_ERROR) {
709 if (r == MAILIMF_ERROR_PARSE)
717 r = clist_append(struct_list, value);
720 res = MAILIMF_ERROR_MEMORY;
724 final_token = cur_token;
727 * result = struct_list;
728 * index = final_token;
730 return MAILIMF_NO_ERROR;
733 clist_foreach(struct_list, (clist_func) destructor, NULL);
734 clist_free(struct_list);
739 static inline int mailimf_wsp_parse(const char * message, size_t length,
746 if (cur_token >= length)
747 return MAILIMF_ERROR_PARSE;
749 if ((message[cur_token] != ' ') && (message[cur_token] != '\t'))
750 return MAILIMF_ERROR_PARSE;
755 return MAILIMF_NO_ERROR;
759 int mailimf_crlf_parse(const char * message, size_t length, size_t * index)
766 r = mailimf_char_parse(message, length, &cur_token, '\r');
767 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
770 r = mailimf_char_parse(message, length, &cur_token, '\n');
771 if (r != MAILIMF_NO_ERROR)
775 return MAILIMF_NO_ERROR;
778 static int mailimf_unstrict_crlf_parse(const char * message,
779 size_t length, size_t * index)
786 mailimf_cfws_parse(message, length, &cur_token);
788 r = mailimf_char_parse(message, length, &cur_token, '\r');
789 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
792 r = mailimf_char_parse(message, length, &cur_token, '\n');
793 if (r != MAILIMF_NO_ERROR)
797 return MAILIMF_NO_ERROR;
800 /* ************************************************************************ */
804 /* RFC 2822 grammar */
807 NO-WS-CTL = %d1-8 / ; US-ASCII control characters
808 %d11 / ; that do not include the
809 %d12 / ; carriage return, line feed,
810 %d14-31 / ; and white space characters
814 static inline int is_no_ws_ctl(char ch)
816 if ((ch == 9) || (ch == 10) || (ch == 13))
822 return (ch >= 1) && (ch <= 31);
826 text = %d1-9 / ; Characters excluding CR and LF
834 specials = "(" / ")" / ; Special characters used in
835 "<" / ">" / ; other parts of the syntax
844 quoted-pair = ("\" text) / obs-qp
847 static inline int mailimf_quoted_pair_parse(const char * message, size_t length,
848 size_t * index, char * result)
854 if (cur_token + 1 >= length)
855 return MAILIMF_ERROR_PARSE;
857 if (message[cur_token] != '\\')
858 return MAILIMF_ERROR_PARSE;
861 * result = message[cur_token];
865 return MAILIMF_NO_ERROR;
869 FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
873 int mailimf_fws_parse(const char * message, size_t length, size_t * index)
886 r = mailimf_wsp_parse(message, length, &cur_token);
887 if (r != MAILIMF_NO_ERROR) {
888 if (r == MAILIMF_ERROR_PARSE)
895 final_token = cur_token;
897 r = mailimf_crlf_parse(message, length, &cur_token);
899 case MAILIMF_NO_ERROR:
902 case MAILIMF_ERROR_PARSE:
912 r = mailimf_wsp_parse(message, length, &cur_token);
913 if (r != MAILIMF_NO_ERROR) {
914 if (r == MAILIMF_ERROR_PARSE)
923 if ((!fws_1) && (!fws_3))
924 return MAILIMF_ERROR_PARSE;
927 cur_token = final_token;
931 return MAILIMF_NO_ERROR;
936 ctext = NO-WS-CTL / ; Non white space controls
938 %d33-39 / ; The rest of the US-ASCII
939 %d42-91 / ; characters not including "(",
940 %d93-126 ; ")", or "\"
943 static inline int is_ctext(char ch)
945 unsigned char uch = (unsigned char) ch;
947 if (is_no_ws_ctl(ch))
953 if ((uch == 40) || (uch == 41))
966 ccontent = ctext / quoted-pair / comment
969 static inline int mailimf_ccontent_parse(const char * message, size_t length,
978 if (cur_token >= length)
979 return MAILIMF_ERROR_PARSE;
981 if (is_ctext(message[cur_token])) {
985 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
987 if (r == MAILIMF_ERROR_PARSE)
988 r = mailimf_comment_parse(message, length, &cur_token);
990 if (r == MAILIMF_ERROR_PARSE)
996 return MAILIMF_NO_ERROR;
1004 mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
1010 cur_token = * index;
1012 r = mailimf_fws_parse(message, length, &cur_token);
1013 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1016 r = mailimf_ccontent_parse(message, length, &cur_token);
1017 if (r != MAILIMF_NO_ERROR)
1020 * index = cur_token;
1022 return MAILIMF_NO_ERROR;
1026 comment = "(" *([FWS] ccontent) [FWS] ")"
1029 static inline int mailimf_comment_parse(const char * message, size_t length,
1035 cur_token = * index;
1037 r = mailimf_oparenth_parse(message, length, &cur_token);
1038 if (r != MAILIMF_NO_ERROR)
1042 r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token);
1043 if (r != MAILIMF_NO_ERROR) {
1044 if (r == MAILIMF_ERROR_PARSE)
1051 r = mailimf_fws_parse(message, length, &cur_token);
1052 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1055 r = mailimf_cparenth_parse(message, length, &cur_token);
1056 if (r != MAILIMF_NO_ERROR)
1059 * index = cur_token;
1061 return MAILIMF_NO_ERROR;
1068 static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length,
1074 cur_token = * index;
1076 r = mailimf_fws_parse(message, length, &cur_token);
1077 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1080 r = mailimf_comment_parse(message, length, &cur_token);
1081 if (r != MAILIMF_NO_ERROR)
1084 * index = cur_token;
1086 return MAILIMF_NO_ERROR;
1090 CFWS = *([FWS] comment) (([FWS] comment) / FWS)
1093 int mailimf_cfws_parse(const char * message, size_t length,
1100 cur_token = * index;
1102 has_comment = FALSE;
1104 r = mailimf_cfws_fws_comment_parse(message, length, &cur_token);
1105 if (r != MAILIMF_NO_ERROR) {
1106 if (r == MAILIMF_ERROR_PARSE)
1115 r = mailimf_fws_parse(message, length, &cur_token);
1116 if (r != MAILIMF_NO_ERROR)
1120 * index = cur_token;
1122 return MAILIMF_NO_ERROR;
1126 atext = ALPHA / DIGIT / ; Any character except controls,
1127 "!" / "#" / ; SP, and specials.
1128 "$" / "%" / ; Used for atoms
1139 static inline int is_atext(char ch)
1166 atom = [CFWS] 1*atext [CFWS]
1169 int mailimf_atom_parse(const char * message, size_t length,
1170 size_t * index, char ** result)
1178 cur_token = * index;
1180 r = mailimf_cfws_parse(message, length, &cur_token);
1181 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1187 if (end >= length) {
1188 res = MAILIMF_ERROR_PARSE;
1192 while (is_atext(message[end])) {
1197 if (end == cur_token) {
1198 res = MAILIMF_ERROR_PARSE;
1202 atom = malloc(end - cur_token + 1);
1204 res = MAILIMF_ERROR_MEMORY;
1207 strncpy(atom, message + cur_token, end - cur_token);
1208 atom[end - cur_token] = '\0';
1212 * index = cur_token;
1215 return MAILIMF_NO_ERROR;
1221 int mailimf_fws_atom_parse(const char * message, size_t length,
1222 size_t * index, char ** result)
1230 cur_token = * index;
1232 r = mailimf_fws_parse(message, length, &cur_token);
1233 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1239 if (end >= length) {
1240 res = MAILIMF_ERROR_PARSE;
1244 while (is_atext(message[end])) {
1249 if (end == cur_token) {
1250 res = MAILIMF_ERROR_PARSE;
1254 atom = malloc(end - cur_token + 1);
1256 res = MAILIMF_ERROR_MEMORY;
1259 strncpy(atom, message + cur_token, end - cur_token);
1260 atom[end - cur_token] = '\0';
1264 * index = cur_token;
1267 return MAILIMF_NO_ERROR;
1274 dot-atom = [CFWS] dot-atom-text [CFWS]
1278 static int mailimf_dot_atom_parse(const char * message, size_t length,
1279 size_t * index, char ** result)
1281 return mailimf_atom_parse(message, length, index, result);
1286 dot-atom-text = 1*atext *("." 1*atext)
1291 mailimf_dot_atom_text_parse(const char * message, size_t length,
1292 size_t * index, char ** result)
1294 return mailimf_atom_parse(message, length, index, result);
1299 qtext = NO-WS-CTL / ; Non white space controls
1301 %d33 / ; The rest of the US-ASCII
1302 %d35-91 / ; characters not including "\"
1303 %d93-126 ; or the quote character
1306 static inline int is_qtext(char ch)
1308 unsigned char uch = (unsigned char) ch;
1310 if (is_no_ws_ctl(ch))
1329 qcontent = qtext / quoted-pair
1332 static int mailimf_qcontent_parse(const char * message, size_t length,
1333 size_t * index, char * result)
1339 cur_token = * index;
1341 if (cur_token >= length)
1342 return MAILIMF_ERROR_PARSE;
1344 if (is_qtext(message[cur_token])) {
1345 ch = message[cur_token];
1349 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
1351 if (r != MAILIMF_NO_ERROR)
1356 * index = cur_token;
1358 return MAILIMF_NO_ERROR;
1362 quoted-string = [CFWS]
1363 DQUOTE *([FWS] qcontent) [FWS] DQUOTE
1367 int mailimf_quoted_string_parse(const char * message, size_t length,
1368 size_t * index, char ** result)
1377 cur_token = * index;
1379 r = mailimf_cfws_parse(message, length, &cur_token);
1380 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1385 r = mailimf_dquote_parse(message, length, &cur_token);
1386 if (r != MAILIMF_NO_ERROR) {
1391 gstr = mmap_string_new("");
1393 res = MAILIMF_ERROR_MEMORY;
1398 if (mmap_string_append_c(gstr, '\"') == NULL) {
1399 res = MAILIMF_ERROR_MEMORY;
1405 r = mailimf_fws_parse(message, length, &cur_token);
1406 if (r == MAILIMF_NO_ERROR) {
1407 if (mmap_string_append_c(gstr, ' ') == NULL) {
1408 res = MAILIMF_ERROR_MEMORY;
1412 else if (r != MAILIMF_ERROR_PARSE) {
1417 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1418 if (r == MAILIMF_NO_ERROR) {
1419 if (mmap_string_append_c(gstr, ch) == NULL) {
1420 res = MAILIMF_ERROR_MEMORY;
1424 else if (r == MAILIMF_ERROR_PARSE)
1432 r = mailimf_dquote_parse(message, length, &cur_token);
1433 if (r != MAILIMF_NO_ERROR) {
1439 if (mmap_string_append_c(gstr, '\"') == NULL) {
1440 res = MAILIMF_ERROR_MEMORY;
1445 str = strdup(gstr->str);
1447 res = MAILIMF_ERROR_MEMORY;
1450 mmap_string_free(gstr);
1452 * index = cur_token;
1455 return MAILIMF_NO_ERROR;
1458 mmap_string_free(gstr);
1463 int mailimf_fws_quoted_string_parse(const char * message, size_t length,
1464 size_t * index, char ** result)
1473 cur_token = * index;
1475 r = mailimf_fws_parse(message, length, &cur_token);
1476 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1481 r = mailimf_dquote_parse(message, length, &cur_token);
1482 if (r != MAILIMF_NO_ERROR) {
1487 gstr = mmap_string_new("");
1489 res = MAILIMF_ERROR_MEMORY;
1494 if (mmap_string_append_c(gstr, '\"') == NULL) {
1495 res = MAILIMF_ERROR_MEMORY;
1501 r = mailimf_fws_parse(message, length, &cur_token);
1502 if (r == MAILIMF_NO_ERROR) {
1503 if (mmap_string_append_c(gstr, ' ') == NULL) {
1504 res = MAILIMF_ERROR_MEMORY;
1508 else if (r != MAILIMF_ERROR_PARSE) {
1513 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1514 if (r == MAILIMF_NO_ERROR) {
1515 if (mmap_string_append_c(gstr, ch) == NULL) {
1516 res = MAILIMF_ERROR_MEMORY;
1520 else if (r == MAILIMF_ERROR_PARSE)
1528 r = mailimf_dquote_parse(message, length, &cur_token);
1529 if (r != MAILIMF_NO_ERROR) {
1535 if (mmap_string_append_c(gstr, '\"') == NULL) {
1536 res = MAILIMF_ERROR_MEMORY;
1541 str = strdup(gstr->str);
1543 res = MAILIMF_ERROR_MEMORY;
1546 mmap_string_free(gstr);
1548 * index = cur_token;
1551 return MAILIMF_NO_ERROR;
1554 mmap_string_free(gstr);
1560 word = atom / quoted-string
1563 int mailimf_word_parse(const char * message, size_t length,
1564 size_t * index, char ** result)
1570 cur_token = * index;
1572 r = mailimf_atom_parse(message, length, &cur_token, &word);
1574 if (r == MAILIMF_ERROR_PARSE)
1575 r = mailimf_quoted_string_parse(message, length, &cur_token, &word);
1577 if (r != MAILIMF_NO_ERROR)
1581 * index = cur_token;
1583 return MAILIMF_NO_ERROR;
1586 int mailimf_fws_word_parse(const char * message, size_t length,
1587 size_t * index, char ** result)
1593 cur_token = * index;
1595 r = mailimf_fws_atom_parse(message, length, &cur_token, &word);
1597 if (r == MAILIMF_ERROR_PARSE)
1598 r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word);
1600 if (r != MAILIMF_NO_ERROR)
1604 * index = cur_token;
1606 return MAILIMF_NO_ERROR;
1610 phrase = 1*word / obs-phrase
1613 static int mailimf_phrase_parse(const char * message, size_t length,
1614 size_t * index, char ** result)
1616 MMAPString * gphrase;
1624 cur_token = * index;
1626 gphrase = mmap_string_new("");
1627 if (gphrase == NULL) {
1628 res = MAILIMF_ERROR_MEMORY;
1635 r = mailimf_fws_word_parse(message, length, &cur_token, &word);
1636 if (r == MAILIMF_NO_ERROR) {
1638 if (mmap_string_append_c(gphrase, ' ') == NULL) {
1639 mailimf_word_free(word);
1640 res = MAILIMF_ERROR_MEMORY;
1644 if (mmap_string_append(gphrase, word) == NULL) {
1645 mailimf_word_free(word);
1646 res = MAILIMF_ERROR_MEMORY;
1649 mailimf_word_free(word);
1652 else if (r == MAILIMF_ERROR_PARSE)
1661 res = MAILIMF_ERROR_PARSE;
1665 str = strdup(gphrase->str);
1667 res = MAILIMF_ERROR_MEMORY;
1670 mmap_string_free(gphrase);
1673 * index = cur_token;
1675 return MAILIMF_NO_ERROR;
1678 mmap_string_free(gphrase);
1684 utext = NO-WS-CTL / ; Non white space controls
1685 %d33-126 / ; The rest of US-ASCII
1699 static int mailimf_unstructured_parse(const char * message, size_t length,
1700 size_t * index, char ** result)
1708 cur_token = * index;
1714 r = mailimf_wsp_parse(message, length, &cur_token);
1715 if (r == MAILIMF_NO_ERROR) {
1718 else if (r == MAILIMF_ERROR_PARSE)
1725 state = UNSTRUCTURED_START;
1727 terminal = cur_token;
1729 while (state != UNSTRUCTURED_OUT) {
1732 case UNSTRUCTURED_START:
1733 if (cur_token >= length)
1734 return MAILIMF_ERROR_PARSE;
1736 terminal = cur_token;
1737 switch(message[cur_token]) {
1739 state = UNSTRUCTURED_CR;
1742 state = UNSTRUCTURED_LF;
1745 state = UNSTRUCTURED_START;
1749 case UNSTRUCTURED_CR:
1750 if (cur_token >= length)
1751 return MAILIMF_ERROR_PARSE;
1753 switch(message[cur_token]) {
1755 state = UNSTRUCTURED_LF;
1758 state = UNSTRUCTURED_START;
1763 case UNSTRUCTURED_LF:
1764 if (cur_token >= length) {
1765 state = UNSTRUCTURED_OUT;
1769 switch(message[cur_token]) {
1772 state = UNSTRUCTURED_WSP;
1775 state = UNSTRUCTURED_OUT;
1779 case UNSTRUCTURED_WSP:
1780 if (cur_token >= length)
1781 return MAILIMF_ERROR_PARSE;
1783 switch(message[cur_token]) {
1785 state = UNSTRUCTURED_CR;
1788 state = UNSTRUCTURED_LF;
1791 state = UNSTRUCTURED_START;
1800 str = malloc(terminal - begin + 1);
1802 return MAILIMF_ERROR_MEMORY;
1803 strncpy(str, message + begin, terminal - begin);
1804 str[terminal - begin] = '\0';
1809 return MAILIMF_NO_ERROR;
1813 static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
1820 cur_token = * index;
1822 state = UNSTRUCTURED_START;
1823 terminal = cur_token;
1825 while (state != UNSTRUCTURED_OUT) {
1828 case UNSTRUCTURED_START:
1829 if (cur_token >= length)
1830 return MAILIMF_ERROR_PARSE;
1831 terminal = cur_token;
1832 switch(message[cur_token]) {
1834 state = UNSTRUCTURED_CR;
1837 state = UNSTRUCTURED_LF;
1840 state = UNSTRUCTURED_START;
1844 case UNSTRUCTURED_CR:
1845 if (cur_token >= length)
1846 return MAILIMF_ERROR_PARSE;
1847 switch(message[cur_token]) {
1849 state = UNSTRUCTURED_LF;
1852 state = UNSTRUCTURED_START;
1856 case UNSTRUCTURED_LF:
1857 if (cur_token >= length) {
1858 state = UNSTRUCTURED_OUT;
1861 switch(message[cur_token]) {
1864 state = UNSTRUCTURED_WSP;
1867 state = UNSTRUCTURED_OUT;
1871 case UNSTRUCTURED_WSP:
1872 if (cur_token >= length)
1873 return MAILIMF_ERROR_PARSE;
1874 switch(message[cur_token]) {
1876 state = UNSTRUCTURED_CR;
1879 state = UNSTRUCTURED_LF;
1882 state = UNSTRUCTURED_START;
1893 return MAILIMF_NO_ERROR;
1897 int mailimf_ignore_field_parse(const char * message, size_t length,
1906 cur_token = * index;
1908 terminal = cur_token;
1909 state = UNSTRUCTURED_START;
1911 /* check if this is not a beginning CRLF */
1913 if (cur_token >= length)
1914 return MAILIMF_ERROR_PARSE;
1916 switch (message[cur_token]) {
1918 return MAILIMF_ERROR_PARSE;
1920 return MAILIMF_ERROR_PARSE;
1923 while (state != UNSTRUCTURED_OUT) {
1926 case UNSTRUCTURED_START:
1927 if (cur_token >= length)
1928 return MAILIMF_ERROR_PARSE;
1930 switch(message[cur_token]) {
1932 state = UNSTRUCTURED_CR;
1935 state = UNSTRUCTURED_LF;
1939 state = UNSTRUCTURED_START;
1942 state = UNSTRUCTURED_START;
1946 case UNSTRUCTURED_CR:
1947 if (cur_token >= length)
1948 return MAILIMF_ERROR_PARSE;
1950 switch(message[cur_token]) {
1952 state = UNSTRUCTURED_LF;
1956 state = UNSTRUCTURED_START;
1959 state = UNSTRUCTURED_START;
1963 case UNSTRUCTURED_LF:
1964 if (cur_token >= length) {
1965 terminal = cur_token;
1966 state = UNSTRUCTURED_OUT;
1970 switch(message[cur_token]) {
1973 state = UNSTRUCTURED_WSP;
1976 terminal = cur_token;
1977 state = UNSTRUCTURED_OUT;
1981 case UNSTRUCTURED_WSP:
1982 if (cur_token >= length)
1983 return MAILIMF_ERROR_PARSE;
1985 switch(message[cur_token]) {
1987 state = UNSTRUCTURED_CR;
1990 state = UNSTRUCTURED_LF;
1994 state = UNSTRUCTURED_START;
1997 state = UNSTRUCTURED_START;
2007 return MAILIMF_ERROR_PARSE;
2011 return MAILIMF_NO_ERROR;
2016 date-time = [ day-of-week "," ] date FWS time [CFWS]
2019 int mailimf_date_time_parse(const char * message, size_t length,
2021 struct mailimf_date_time ** result)
2025 struct mailimf_date_time * date_time;
2035 cur_token = * index;
2038 r = mailimf_day_of_week_parse(message, length, &cur_token, &day_of_week);
2039 if (r == MAILIMF_NO_ERROR) {
2040 r = mailimf_comma_parse(message, length, &cur_token);
2041 if (r != MAILIMF_NO_ERROR)
2044 else if (r != MAILIMF_ERROR_PARSE)
2047 r = mailimf_date_parse(message, length, &cur_token, &day, &month, &year);
2048 if (r != MAILIMF_NO_ERROR)
2051 r = mailimf_fws_parse(message, length, &cur_token);
2052 if (r != MAILIMF_NO_ERROR)
2055 r = mailimf_time_parse(message, length, &cur_token,
2056 &hour, &min, &sec, &zone);
2057 if (r != MAILIMF_NO_ERROR)
2060 date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone);
2061 if (date_time == NULL)
2062 return MAILIMF_ERROR_MEMORY;
2064 * index = cur_token;
2065 * result = date_time;
2067 return MAILIMF_NO_ERROR;
2071 day-of-week = ([FWS] day-name) / obs-day-of-week
2074 static int mailimf_day_of_week_parse(const char * message, size_t length,
2075 size_t * index, int * result)
2081 cur_token = * index;
2083 r = mailimf_cfws_parse(message, length, &cur_token);
2084 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2087 r = mailimf_day_name_parse(message, length, &cur_token, &day_of_week);
2088 if (r != MAILIMF_NO_ERROR)
2091 * index = cur_token;
2092 * result = day_of_week;
2094 return MAILIMF_NO_ERROR;
2098 day-name = "Mon" / "Tue" / "Wed" / "Thu" /
2099 "Fri" / "Sat" / "Sun"
2102 struct mailimf_token_value {
2107 static struct mailimf_token_value day_names[] = {
2123 static int guess_day_name(const char * message, size_t length, size_t index)
2127 state = DAY_NAME_START;
2131 if (index >= length)
2135 case DAY_NAME_START:
2136 switch((char) toupper((unsigned char) message[index])) {
2140 case 'T': /* Tue Thu */
2147 case 'S': /* Sat Sun */
2155 switch((char) toupper((unsigned char) message[index])) {
2165 switch((char) toupper((unsigned char) message[index])) {
2180 static int mailimf_day_name_parse(const char * message, size_t length,
2181 size_t * index, int * result)
2188 cur_token = * index;
2190 guessed_day = guess_day_name(message, length, cur_token);
2191 if (guessed_day == -1)
2192 return MAILIMF_ERROR_PARSE;
2194 r = mailimf_token_case_insensitive_parse(message, length,
2196 day_names[guessed_day - 1].str);
2197 if (r != MAILIMF_NO_ERROR)
2200 day_of_week = guessed_day;
2202 * result = day_of_week;
2203 * index = cur_token;
2205 return MAILIMF_NO_ERROR;
2209 date = day month year
2212 static int mailimf_date_parse(const char * message, size_t length,
2214 int * pday, int * pmonth, int * pyear)
2222 cur_token = * index;
2224 r = mailimf_day_parse(message, length, &cur_token, &day);
2225 if (r != MAILIMF_NO_ERROR)
2228 r = mailimf_month_parse(message, length, &cur_token, &month);
2229 if (r != MAILIMF_NO_ERROR)
2232 r = mailimf_year_parse(message, length, &cur_token, &year);
2233 if (r != MAILIMF_NO_ERROR)
2240 * index = cur_token;
2242 return MAILIMF_NO_ERROR;
2246 year = 4*DIGIT / obs-year
2249 static int mailimf_year_parse(const char * message, size_t length,
2250 size_t * index, int * result)
2256 cur_token = * index;
2258 r = mailimf_cfws_parse(message, length, &cur_token);
2259 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2262 r = mailimf_number_parse(message, length, &cur_token, &number);
2263 if (r != MAILIMF_NO_ERROR)
2266 * index = cur_token;
2269 return MAILIMF_NO_ERROR;
2273 month = (FWS month-name FWS) / obs-month
2276 static int mailimf_month_parse(const char * message, size_t length,
2277 size_t * index, int * result)
2283 cur_token = * index;
2285 r = mailimf_cfws_parse(message, length, &cur_token);
2286 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2289 r = mailimf_month_name_parse(message, length, &cur_token, &month);
2290 if (r != MAILIMF_NO_ERROR)
2294 * index = cur_token;
2296 return MAILIMF_NO_ERROR;
2300 month-name = "Jan" / "Feb" / "Mar" / "Apr" /
2301 "May" / "Jun" / "Jul" / "Aug" /
2302 "Sep" / "Oct" / "Nov" / "Dec"
2305 static struct mailimf_token_value month_names[] = {
2329 static int guess_month(const char * message, size_t length, size_t index)
2333 state = MONTH_START;
2337 if (index >= length)
2342 switch((char) toupper((unsigned char) message[index])) {
2343 case 'J': /* Jan Jun Jul */
2348 case 'M': /* Mar May */
2351 case 'A': /* Apr Aug */
2367 switch((char) toupper((unsigned char) message[index])) {
2378 switch((char) toupper((unsigned char) message[index])) {
2388 switch((char) toupper((unsigned char) message[index])) {
2397 switch((char) toupper((unsigned char) message[index])) {
2407 switch((char) toupper((unsigned char) message[index])) {
2422 static int mailimf_month_name_parse(const char * message, size_t length,
2423 size_t * index, int * result)
2430 cur_token = * index;
2432 guessed_month = guess_month(message, length, cur_token);
2433 if (guessed_month == -1)
2434 return MAILIMF_ERROR_PARSE;
2436 r = mailimf_token_case_insensitive_parse(message, length,
2438 month_names[guessed_month - 1].str);
2439 if (r != MAILIMF_NO_ERROR)
2442 month = guessed_month;
2445 * index = cur_token;
2447 return MAILIMF_NO_ERROR;
2451 day = ([FWS] 1*2DIGIT) / obs-day
2454 static int mailimf_day_parse(const char * message, size_t length,
2455 size_t * index, int * result)
2461 cur_token = * index;
2463 r = mailimf_cfws_parse(message, length, &cur_token);
2464 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2467 r = mailimf_number_parse(message, length, &cur_token, &day);
2468 if (r != MAILIMF_NO_ERROR)
2472 * index = cur_token;
2474 return MAILIMF_NO_ERROR;
2478 time = time-of-day FWS zone
2481 static int mailimf_time_parse(const char * message, size_t length,
2483 int * phour, int * pmin,
2494 cur_token = * index;
2496 r = mailimf_cfws_parse(message, length, &cur_token);
2497 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2500 r = mailimf_time_of_day_parse(message, length, &cur_token,
2502 if (r != MAILIMF_NO_ERROR)
2505 r = mailimf_fws_parse(message, length, &cur_token);
2506 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2509 r = mailimf_zone_parse(message, length, &cur_token, &zone);
2510 if (r == MAILIMF_NO_ERROR) {
2513 else if (r == MAILIMF_ERROR_PARSE) {
2525 * index = cur_token;
2527 return MAILIMF_NO_ERROR;
2531 time-of-day = hour ":" minute [ ":" second ]
2534 static int mailimf_time_of_day_parse(const char * message, size_t length,
2536 int * phour, int * pmin,
2545 cur_token = * index;
2547 r = mailimf_hour_parse(message, length, &cur_token, &hour);
2548 if (r != MAILIMF_NO_ERROR)
2551 r = mailimf_colon_parse(message, length, &cur_token);
2552 if (r != MAILIMF_NO_ERROR)
2555 r = mailimf_minute_parse(message, length, &cur_token, &min);
2556 if (r != MAILIMF_NO_ERROR)
2559 r = mailimf_colon_parse(message, length, &cur_token);
2560 if (r == MAILIMF_NO_ERROR) {
2561 r = mailimf_second_parse(message, length, &cur_token, &sec);
2562 if (r != MAILIMF_NO_ERROR)
2565 else if (r == MAILIMF_ERROR_PARSE)
2573 * index = cur_token;
2575 return MAILIMF_NO_ERROR;
2579 hour = 2DIGIT / obs-hour
2582 static int mailimf_hour_parse(const char * message, size_t length,
2583 size_t * index, int * result)
2588 r = mailimf_number_parse(message, length, index, &hour);
2589 if (r != MAILIMF_NO_ERROR)
2594 return MAILIMF_NO_ERROR;
2598 minute = 2DIGIT / obs-minute
2601 static int mailimf_minute_parse(const char * message, size_t length,
2602 size_t * index, int * result)
2607 r = mailimf_number_parse(message, length, index, &minute);
2608 if (r != MAILIMF_NO_ERROR)
2613 return MAILIMF_NO_ERROR;
2617 second = 2DIGIT / obs-second
2620 static int mailimf_second_parse(const char * message, size_t length,
2621 size_t * index, int * result)
2626 r = mailimf_number_parse(message, length, index, &second);
2627 if (r != MAILIMF_NO_ERROR)
2632 return MAILIMF_NO_ERROR;
2636 zone = (( "+" / "-" ) 4DIGIT) / obs-zone
2640 obs-zone = "UT" / "GMT" / ; Universal Time
2643 "EST" / "EDT" / ; Eastern: - 5/ - 4
2644 "CST" / "CDT" / ; Central: - 6/ - 5
2645 "MST" / "MDT" / ; Mountain: - 7/ - 6
2646 "PST" / "PDT" / ; Pacific: - 8/ - 7
2648 %d65-73 / ; Military zones - "A"
2649 %d75-90 / ; through "I" and "K"
2650 %d97-105 / ; through "Z", both
2651 %d107-122 ; upper and lower case
2660 STATE_ZONE_CONT = 5,
2663 static int mailimf_zone_parse(const char * message, size_t length,
2664 size_t * index, int * result)
2671 cur_token = * index;
2673 if (cur_token + 1 < length) {
2674 if ((message[cur_token] == 'U') && (message[cur_token + 1] == 'T')) {
2676 * index = cur_token + 2;
2678 return MAILIMF_NO_ERROR;
2682 if (cur_token + 2 < length) {
2685 state = STATE_ZONE_1;
2687 while (state <= 2) {
2690 switch (message[cur_token]) {
2692 if (message[cur_token + 1] == 'M' && message[cur_token + 2] == 'T') {
2694 state = STATE_ZONE_OK;
2697 state = STATE_ZONE_ERR;
2702 state = STATE_ZONE_2;
2706 state = STATE_ZONE_2;
2710 state = STATE_ZONE_2;
2714 state = STATE_ZONE_2;
2717 state = STATE_ZONE_CONT;
2722 switch (message[cur_token + 1]) {
2724 state = STATE_ZONE_3;
2728 state = STATE_ZONE_3;
2731 state = STATE_ZONE_ERR;
2736 if (message[cur_token + 2] == 'T') {
2738 state = STATE_ZONE_OK;
2741 state = STATE_ZONE_ERR;
2749 * index = cur_token + 3;
2750 return MAILIMF_NO_ERROR;
2752 case STATE_ZONE_ERR:
2753 return MAILIMF_ERROR_PARSE;
2758 r = mailimf_plus_parse(message, length, &cur_token);
2759 if (r == MAILIMF_NO_ERROR)
2762 if (r == MAILIMF_ERROR_PARSE) {
2763 r = mailimf_minus_parse(message, length, &cur_token);
2764 if (r == MAILIMF_NO_ERROR)
2768 if (r == MAILIMF_NO_ERROR) {
2771 else if (r == MAILIMF_ERROR_PARSE)
2776 r = mailimf_number_parse(message, length, &cur_token, &zone);
2777 if (r != MAILIMF_NO_ERROR)
2782 * index = cur_token;
2785 return MAILIMF_NO_ERROR;
2789 address = mailbox / group
2792 int mailimf_address_parse(const char * message, size_t length,
2794 struct mailimf_address ** result)
2798 struct mailimf_mailbox * mailbox;
2799 struct mailimf_group * group;
2800 struct mailimf_address * address;
2804 cur_token = * index;
2809 type = MAILIMF_ADDRESS_ERROR; /* XXX - removes a gcc warning */
2810 r = mailimf_group_parse(message, length, &cur_token, &group);
2811 if (r == MAILIMF_NO_ERROR)
2812 type = MAILIMF_ADDRESS_GROUP;
2814 if (r == MAILIMF_ERROR_PARSE) {
2815 r = mailimf_mailbox_parse(message, length, &cur_token, &mailbox);
2816 if (r == MAILIMF_NO_ERROR)
2817 type = MAILIMF_ADDRESS_MAILBOX;
2820 if (r != MAILIMF_NO_ERROR) {
2825 address = mailimf_address_new(type, mailbox, group);
2826 if (address == NULL) {
2827 res = MAILIMF_ERROR_MEMORY;
2832 * index = cur_token;
2834 return MAILIMF_NO_ERROR;
2837 if (mailbox != NULL)
2838 mailimf_mailbox_free(mailbox);
2840 mailimf_group_free(group);
2847 mailbox = name-addr / addr-spec
2851 int mailimf_mailbox_parse(const char * message, size_t length,
2853 struct mailimf_mailbox ** result)
2856 char * display_name;
2857 struct mailimf_mailbox * mailbox;
2862 cur_token = * index;
2863 display_name = NULL;
2866 r = mailimf_name_addr_parse(message, length, &cur_token,
2867 &display_name, &addr_spec);
2868 if (r == MAILIMF_ERROR_PARSE)
2869 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2871 if (r != MAILIMF_NO_ERROR) {
2876 mailbox = mailimf_mailbox_new(display_name, addr_spec);
2877 if (mailbox == NULL) {
2878 res = MAILIMF_ERROR_MEMORY;
2883 * index = cur_token;
2885 return MAILIMF_NO_ERROR;
2888 if (display_name != NULL)
2889 mailimf_display_name_free(display_name);
2890 if (addr_spec != NULL)
2891 mailimf_addr_spec_free(addr_spec);
2897 name-addr = [display-name] angle-addr
2900 static int mailimf_name_addr_parse(const char * message, size_t length,
2902 char ** pdisplay_name,
2903 char ** pangle_addr)
2905 char * display_name;
2911 cur_token = * index;
2913 display_name = NULL;
2916 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
2917 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
2922 r = mailimf_angle_addr_parse(message, length, &cur_token, &angle_addr);
2923 if (r != MAILIMF_NO_ERROR) {
2925 goto free_display_name;
2928 * pdisplay_name = display_name;
2929 * pangle_addr = angle_addr;
2930 * index = cur_token;
2932 return MAILIMF_NO_ERROR;
2935 if (display_name != NULL)
2936 mailimf_display_name_free(display_name);
2942 angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
2945 static int mailimf_angle_addr_parse(const char * message, size_t length,
2946 size_t * index, char ** result)
2952 cur_token = * index;
2954 r = mailimf_cfws_parse(message, length, &cur_token);
2955 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2958 r = mailimf_lower_parse(message, length, &cur_token);
2959 if (r != MAILIMF_NO_ERROR)
2962 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2963 if (r != MAILIMF_NO_ERROR)
2966 r = mailimf_greater_parse(message, length, &cur_token);
2967 if (r != MAILIMF_NO_ERROR) {
2972 * result = addr_spec;
2973 * index = cur_token;
2975 return MAILIMF_NO_ERROR;
2979 group = display-name ":" [mailbox-list / CFWS] ";"
2983 static int mailimf_group_parse(const char * message, size_t length,
2985 struct mailimf_group ** result)
2988 char * display_name;
2989 struct mailimf_mailbox_list * mailbox_list;
2990 struct mailimf_group * group;
2995 cur_token = * index;
2997 mailbox_list = NULL;
2999 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
3000 if (r != MAILIMF_NO_ERROR) {
3005 r = mailimf_colon_parse(message, length, &cur_token);
3006 if (r != MAILIMF_NO_ERROR) {
3008 goto free_display_name;
3011 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list);
3013 case MAILIMF_NO_ERROR:
3015 case MAILIMF_ERROR_PARSE:
3016 r = mailimf_cfws_parse(message, length, &cur_token);
3017 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3019 goto free_display_name;
3023 res = MAILIMF_ERROR_MEMORY;
3024 goto free_display_name;
3026 mailbox_list = mailimf_mailbox_list_new(list);
3027 if (mailbox_list == NULL) {
3028 res = MAILIMF_ERROR_MEMORY;
3030 goto free_display_name;
3035 goto free_display_name;
3038 r = mailimf_semi_colon_parse(message, length, &cur_token);
3039 if (r != MAILIMF_NO_ERROR) {
3041 goto free_mailbox_list;
3044 group = mailimf_group_new(display_name, mailbox_list);
3045 if (group == NULL) {
3046 res = MAILIMF_ERROR_MEMORY;
3047 goto free_mailbox_list;
3050 * index = cur_token;
3053 return MAILIMF_NO_ERROR;
3056 mailimf_mailbox_list_free(mailbox_list);
3058 mailimf_display_name_free(display_name);
3064 display-name = phrase
3067 static int mailimf_display_name_parse(const char * message, size_t length,
3068 size_t * index, char ** result)
3070 return mailimf_phrase_parse(message, length, index, result);
3074 mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
3078 mailimf_mailbox_list_parse(const char * message, size_t length,
3080 struct mailimf_mailbox_list ** result)
3084 struct mailimf_mailbox_list * mailbox_list;
3088 cur_token = * index;
3090 r = mailimf_struct_list_parse(message, length,
3091 &cur_token, &list, ',',
3092 (mailimf_struct_parser *)
3093 mailimf_mailbox_parse,
3094 (mailimf_struct_destructor *)
3095 mailimf_mailbox_free);
3096 if (r != MAILIMF_NO_ERROR) {
3101 mailbox_list = mailimf_mailbox_list_new(list);
3102 if (mailbox_list == NULL) {
3103 res = MAILIMF_ERROR_MEMORY;
3107 * result = mailbox_list;
3108 * index = cur_token;
3110 return MAILIMF_NO_ERROR;
3113 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
3120 address-list = (address *("," address)) / obs-addr-list
3125 mailimf_address_list_parse(const char * message, size_t length,
3127 struct mailimf_address_list ** result)
3131 struct mailimf_address_list * address_list;
3135 cur_token = * index;
3137 r = mailimf_struct_list_parse(message, length,
3138 &cur_token, &list, ',',
3139 (mailimf_struct_parser *)
3140 mailimf_address_parse,
3141 (mailimf_struct_destructor *)
3142 mailimf_address_free);
3143 if (r != MAILIMF_NO_ERROR) {
3148 address_list = mailimf_address_list_new(list);
3149 if (address_list == NULL) {
3150 res = MAILIMF_ERROR_MEMORY;
3154 * result = address_list;
3155 * index = cur_token;
3157 return MAILIMF_NO_ERROR;
3160 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
3167 addr-spec = local-part "@" domain
3171 static int mailimf_addr_spec_parse(const char * message, size_t length,
3191 cur_token = * index;
3193 r = mailimf_cfws_parse(message, length, &cur_token);
3194 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3200 if (end >= length) {
3201 res = MAILIMF_ERROR_PARSE;
3209 switch (message[end]) {
3231 res = MAILIMF_ERROR_PARSE;
3235 addr_spec = malloc(end - cur_token + 1);
3236 if (addr_spec == NULL) {
3237 res = MAILIMF_ERROR_MEMORY;
3241 count = end - cur_token;
3242 src = message + cur_token;
3244 for(i = 0 ; i < count ; i ++) {
3245 if ((* src != ' ') && (* src != '\t')) {
3254 strncpy(addr_spec, message + cur_token, end - cur_token);
3255 addr_spec[end - cur_token] = '\0';
3261 r = mailimf_local_part_parse(message, length, &cur_token, &local_part);
3262 if (r != MAILIMF_NO_ERROR) {
3267 r = mailimf_at_sign_parse(message, length, &cur_token);
3269 case MAILIMF_NO_ERROR:
3270 r = mailimf_domain_parse(message, length, &cur_token, &domain);
3271 if (r != MAILIMF_NO_ERROR) {
3273 goto free_local_part;
3277 case MAILIMF_ERROR_PARSE:
3283 goto free_local_part;
3287 addr_spec = malloc(strlen(local_part) + strlen(domain) + 2);
3288 if (addr_spec == NULL) {
3289 res = MAILIMF_ERROR_MEMORY;
3293 strcpy(addr_spec, local_part);
3294 strcat(addr_spec, "@");
3295 strcat(addr_spec, domain);
3297 mailimf_domain_free(domain);
3298 mailimf_local_part_free(local_part);
3301 addr_spec = local_part;
3305 * result = addr_spec;
3306 * index = cur_token;
3308 return MAILIMF_NO_ERROR;
3312 mailimf_domain_free(domain);
3314 mailimf_local_part_free(local_part);
3321 local-part = dot-atom / quoted-string / obs-local-part
3325 static int mailimf_local_part_parse(const char * message, size_t length,
3331 r = mailimf_dot_atom_parse(message, length, index, result);
3333 case MAILIMF_NO_ERROR:
3335 case MAILIMF_ERROR_PARSE:
3341 r = mailimf_quoted_string_parse(message, length, index, result);
3342 if (r != MAILIMF_NO_ERROR)
3345 return MAILIMF_NO_ERROR;
3350 domain = dot-atom / domain-literal / obs-domain
3354 static int mailimf_domain_parse(const char * message, size_t length,
3360 r = mailimf_dot_atom_parse(message, length, index, result);
3362 case MAILIMF_NO_ERROR:
3364 case MAILIMF_ERROR_PARSE:
3370 r = mailimf_domain_literal_parse(message, length, index, result);
3371 if (r != MAILIMF_NO_ERROR)
3374 return MAILIMF_NO_ERROR;
3384 mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length,
3391 cur_token = * index;
3393 r = mailimf_cfws_parse(message, length, &cur_token);
3394 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3397 r = mailimf_dcontent_parse(message, length, &cur_token, &ch);
3398 if (r != MAILIMF_NO_ERROR)
3401 * index = cur_token;
3403 return MAILIMF_NO_ERROR;
3408 domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
3412 static int mailimf_domain_literal_parse(const char * message, size_t length,
3413 size_t * index, char ** result)
3418 char * domain_literal;
3421 cur_token = * index;
3423 r = mailimf_cfws_parse(message, length, &cur_token);
3424 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3428 r = mailimf_obracket_parse(message, length, &cur_token);
3429 if (r != MAILIMF_NO_ERROR)
3433 r = mailimf_domain_literal_fws_dcontent_parse(message, length,
3435 if (r == MAILIMF_NO_ERROR) {
3438 else if (r == MAILIMF_ERROR_PARSE)
3444 r = mailimf_fws_parse(message, length, &cur_token);
3445 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3448 r = mailimf_cbracket_parse(message, length, &cur_token);
3449 if (r != MAILIMF_NO_ERROR)
3452 len = cur_token - begin;
3454 domain_literal = malloc(len + 1);
3455 if (domain_literal == NULL)
3456 return MAILIMF_ERROR_MEMORY;
3457 strncpy(domain_literal, message + begin, len);
3458 domain_literal[len] = '\0';
3460 * result = domain_literal;
3461 * index = cur_token;
3463 return MAILIMF_NO_ERROR;
3468 dcontent = dtext / quoted-pair
3472 static int mailimf_dcontent_parse(const char * message, size_t length,
3473 size_t * index, char * result)
3479 cur_token = * index;
3481 if (cur_token >= length)
3482 return MAILIMF_ERROR_PARSE;
3484 if (is_dtext(message[cur_token])) {
3485 ch = message[cur_token];
3489 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
3491 if (r != MAILIMF_NO_ERROR)
3495 * index = cur_token;
3498 return MAILIMF_NO_ERROR;
3504 dtext = NO-WS-CTL / ; Non white space controls
3506 %d33-90 / ; The rest of the US-ASCII
3507 %d94-126 ; characters not including "[",
3511 static inline int is_dtext(char ch)
3513 unsigned char uch = (unsigned char) ch;
3515 if (is_no_ws_ctl(ch))
3521 if ((uch >= 91) && (uch <= 93))
3531 message = (fields / obs-fields)
3535 int mailimf_message_parse(const char * message, size_t length,
3537 struct mailimf_message ** result)
3539 struct mailimf_fields * fields;
3540 struct mailimf_body * body;
3541 struct mailimf_message * msg;
3546 cur_token = * index;
3548 r = mailimf_fields_parse(message, length, &cur_token, &fields);
3549 if (r != MAILIMF_NO_ERROR) {
3554 r = mailimf_crlf_parse(message, length, &cur_token);
3555 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3560 r = mailimf_body_parse(message, length, &cur_token, &body);
3561 if (r != MAILIMF_NO_ERROR) {
3566 msg = mailimf_message_new(fields, body);
3568 res = MAILIMF_ERROR_MEMORY;
3572 * index = cur_token;
3575 return MAILIMF_NO_ERROR;
3578 mailimf_body_free(body);
3580 mailimf_fields_free(fields);
3586 body = *(*998text CRLF) *998text
3589 int mailimf_body_parse(const char * message, size_t length,
3591 struct mailimf_body ** result)
3594 struct mailimf_body * body;
3596 cur_token = * index;
3598 body = mailimf_body_new(message + cur_token, length - cur_token);
3600 return MAILIMF_ERROR_MEMORY;
3605 * index = cur_token;
3607 return MAILIMF_NO_ERROR;
3611 CHANGE TO THE RFC 2822
3638 INTO THE FOLLOWING :
3642 resent-fields-list = *(resent-date /
3653 RESENT_HEADER_START,
3656 static int guess_resent_header_type(char * message,
3657 size_t length, size_t index)
3661 r = mailimf_token_case_insensitive_parse(message,
3662 length, &index, "Resent-");
3663 if (r != MAILIMF_NO_ERROR)
3664 return MAILIMF_RESENT_FIELD_NONE;
3666 if (index >= length)
3667 return MAILIMF_RESENT_FIELD_NONE;
3669 switch(toupper(message[index])) {
3671 return MAILIMF_RESENT_FIELD_DATE;
3673 return MAILIMF_RESENT_FIELD_FROM;
3675 return MAILIMF_RESENT_FIELD_SENDER;
3677 return MAILIMF_RESENT_FIELD_TO;
3679 return MAILIMF_RESENT_FIELD_CC;
3681 return MAILIMF_RESENT_FIELD_BCC;
3683 return MAILIMF_RESENT_FIELD_MSG_ID;
3685 return MAILIMF_RESENT_FIELD_NONE;
3692 mailimf_resent_field_parse(const char * message, size_t length,
3694 struct mailimf_resent_field ** result)
3696 struct mailimf_orig_date * resent_date;
3697 struct mailimf_from * resent_from;
3698 struct mailimf_sender * resent_sender;
3699 struct mailimf_to* resent_to;
3700 struct mailimf_cc * resent_cc;
3701 struct mailimf_bcc * resent_bcc;
3702 struct mailimf_message_id * resent_msg_id;
3705 struct mailimf_resent_field * resent_field;
3709 cur_token = * index;
3713 resent_sender = NULL;
3717 resent_msg_id = NULL;
3719 type = guess_resent_header_type(message, length, cur_token);
3722 case MAILIMF_RESENT_FIELD_DATE:
3723 r = mailimf_resent_date_parse(message, length, &cur_token,
3725 if (r != MAILIMF_NO_ERROR) {
3730 case MAILIMF_RESENT_FIELD_FROM:
3731 r = mailimf_resent_from_parse(message, length, &cur_token,
3733 if (r != MAILIMF_NO_ERROR) {
3738 case MAILIMF_RESENT_FIELD_SENDER:
3739 r = mailimf_resent_sender_parse(message, length, &cur_token,
3741 if (r != MAILIMF_NO_ERROR) {
3746 case MAILIMF_RESENT_FIELD_TO:
3747 r = mailimf_resent_to_parse(message, length, &cur_token,
3749 if (r != MAILIMF_NO_ERROR) {
3754 case MAILIMF_RESENT_FIELD_CC:
3755 r= mailimf_resent_cc_parse(message, length, &cur_token,
3757 if (r != MAILIMF_NO_ERROR) {
3762 case MAILIMF_RESENT_FIELD_BCC:
3763 r = mailimf_resent_bcc_parse(message, length, &cur_token,
3765 if (r != MAILIMF_NO_ERROR) {
3770 case MAILIMF_RESENT_FIELD_MSG_ID:
3771 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
3773 if (r != MAILIMF_NO_ERROR) {
3779 res = MAILIMF_ERROR_PARSE;
3783 resent_field = mailimf_resent_field_new(type, resent_date,
3784 resent_from, resent_sender,
3785 resent_to, resent_cc,
3786 resent_bcc, resent_msg_id);
3787 if (resent_field == NULL) {
3788 res = MAILIMF_ERROR_MEMORY;
3792 * result = resent_field;
3793 * index = cur_token;
3795 return MAILIMF_NO_ERROR;
3798 if (resent_msg_id != NULL)
3799 mailimf_message_id_free(resent_msg_id);
3800 if (resent_bcc != NULL)
3801 mailimf_bcc_free(resent_bcc);
3802 if (resent_cc != NULL)
3803 mailimf_cc_free(resent_cc);
3804 if (resent_to != NULL)
3805 mailimf_to_free(resent_to);
3806 if (resent_sender != NULL)
3807 mailimf_sender_free(resent_sender);
3808 if (resent_from != NULL)
3809 mailimf_from_free(resent_from);
3810 if (resent_date != NULL)
3811 mailimf_orig_date_free(resent_date);
3819 mailimf_resent_fields_list_parse(const char * message, size_t length,
3821 struct mailimf_resent_fields_list ** result)
3825 struct mailimf_resent_fields_list * resent_fields_list;
3829 cur_token = * index;
3832 r = mailimf_struct_multiple_parse(message, length, &cur_token, &list,
3833 (mailimf_struct_parser *)
3834 mailimf_resent_field_parse,
3835 (mailimf_struct_destructor *)
3836 mailimf_resent_field_free);
3837 if (r != MAILIMF_NO_ERROR) {
3842 resent_fields_list = mailimf_resent_fields_list_new(list);
3843 if (resent_fields_list == NULL) {
3844 res = MAILIMF_ERROR_MEMORY;
3848 * result = resent_fields_list;
3849 * index = cur_token;
3851 return MAILIMF_NO_ERROR;
3854 clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL);
3863 [resent-fields-list])
3868 mailimf_trace_resent_fields_parse(const char * message, size_t length,
3870 struct mailimf_trace_resent_fields ** result)
3873 struct mailimf_return * return_path;
3874 struct mailimf_resent_fields_list * resent_fields;
3875 struct mailimf_trace_resent_fields * trace_resent_fields;
3879 cur_token = * index;
3882 resent_fields = NULL;
3884 r = mailimf_return_parse(message, length, &cur_token,
3886 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3891 r = mailimf_resent_fields_list_parse(message, length, &cur_token,
3893 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3898 if ((return_path == NULL) && (resent_fields == NULL)) {
3899 res = MAILIMF_ERROR_PARSE;
3903 trace_resent_fields = mailimf_trace_resent_fields_new(return_path,
3905 if (trace_resent_fields == NULL) {
3906 res = MAILIMF_ERROR_MEMORY;
3907 goto free_resent_fields;
3910 * result = trace_resent_fields;
3911 * index = cur_token;
3913 return MAILIMF_NO_ERROR;
3916 if (resent_fields != NULL)
3917 mailimf_resent_fields_list_free(resent_fields);
3918 if (return_path != NULL)
3919 mailimf_return_free(return_path);
3926 delivering-info = *([trace]
3927 [resent-fields-list])
3932 mailimf_delivering_info_parse(const char * message, size_t length,
3934 struct mailimf_delivering_info ** result)
3938 struct mailimf_delivering_info * delivering_info;
3942 cur_token = * index;
3944 r = mailimf_struct_multiple_parse(message, length, &cur_token,
3946 (mailimf_struct_parser *)
3947 mailimf_trace_resent_fields_parse,
3948 (mailimf_struct_destructor *)
3949 mailimf_trace_resent_fields_free);
3950 if (r != MAILIMF_NO_ERROR) {
3955 delivering_info = mailimf_delivering_info_new(list);
3956 if (delivering_info == NULL) {
3957 res = MAILIMF_ERROR_MEMORY;
3961 * result = delivering_info;
3962 * index = cur_token;
3964 return MAILIMF_NO_ERROR;
3967 clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL);
3975 field = delivering-info /
4001 static int guess_header_type(const char * message, size_t length, size_t index)
4006 state = HEADER_START;
4010 if (index >= length)
4011 return MAILIMF_FIELD_NONE;
4015 switch((char) toupper((unsigned char) message[index])) {
4017 return MAILIMF_FIELD_BCC;
4022 return MAILIMF_FIELD_ORIG_DATE;
4024 return MAILIMF_FIELD_FROM;
4026 return MAILIMF_FIELD_IN_REPLY_TO;
4028 return MAILIMF_FIELD_KEYWORDS;
4030 return MAILIMF_FIELD_MESSAGE_ID;
4035 return MAILIMF_FIELD_TO;
4041 return MAILIMF_FIELD_NONE;
4045 switch((char) toupper((unsigned char) message[index])) {
4047 return MAILIMF_FIELD_COMMENTS;
4049 return MAILIMF_FIELD_CC;
4051 return MAILIMF_FIELD_NONE;
4055 switch((char) toupper((unsigned char) message[index])) {
4060 return MAILIMF_FIELD_NONE;
4064 switch((char) toupper((unsigned char) message[index])) {
4066 return MAILIMF_FIELD_REFERENCES;
4068 return MAILIMF_FIELD_REPLY_TO;
4073 return MAILIMF_FIELD_RETURN_PATH;
4075 return MAILIMF_FIELD_NONE;
4079 switch((char) toupper((unsigned char) message[index])) {
4081 return MAILIMF_FIELD_SENDER;
4083 return MAILIMF_FIELD_SUBJECT;
4085 return MAILIMF_FIELD_NONE;
4090 r = mailimf_token_case_insensitive_parse(message,
4091 length, &index, "ent-");
4092 if (r != MAILIMF_NO_ERROR)
4093 return MAILIMF_FIELD_NONE;
4095 if (index >= length)
4096 return MAILIMF_FIELD_NONE;
4098 switch((char) toupper((unsigned char) message[index])) {
4100 return MAILIMF_FIELD_RESENT_DATE;
4102 return MAILIMF_FIELD_RESENT_FROM;
4104 return MAILIMF_FIELD_RESENT_SENDER;
4106 return MAILIMF_FIELD_RESENT_TO;
4108 return MAILIMF_FIELD_RESENT_CC;
4110 return MAILIMF_FIELD_RESENT_BCC;
4112 return MAILIMF_FIELD_RESENT_MSG_ID;
4114 return MAILIMF_FIELD_NONE;
4122 static int mailimf_field_parse(const char * message, size_t length,
4124 struct mailimf_field ** result)
4128 struct mailimf_return * return_path;
4129 struct mailimf_orig_date * resent_date;
4130 struct mailimf_from * resent_from;
4131 struct mailimf_sender * resent_sender;
4132 struct mailimf_to* resent_to;
4133 struct mailimf_cc * resent_cc;
4134 struct mailimf_bcc * resent_bcc;
4135 struct mailimf_message_id * resent_msg_id;
4136 struct mailimf_orig_date * orig_date;
4137 struct mailimf_from * from;
4138 struct mailimf_sender * sender;
4139 struct mailimf_reply_to * reply_to;
4140 struct mailimf_to * to;
4141 struct mailimf_cc * cc;
4142 struct mailimf_bcc * bcc;
4143 struct mailimf_message_id * message_id;
4144 struct mailimf_in_reply_to * in_reply_to;
4145 struct mailimf_references * references;
4146 struct mailimf_subject * subject;
4147 struct mailimf_comments * comments;
4148 struct mailimf_keywords * keywords;
4149 struct mailimf_optional_field * optional_field;
4150 struct mailimf_field * field;
4155 cur_token = * index;
4160 resent_sender = NULL;
4164 resent_msg_id = NULL;
4178 optional_field = NULL;
4180 guessed_type = guess_header_type(message, length, cur_token);
4181 type = MAILIMF_FIELD_NONE;
4183 switch (guessed_type) {
4184 case MAILIMF_FIELD_ORIG_DATE:
4185 r = mailimf_orig_date_parse(message, length, &cur_token,
4187 if (r == MAILIMF_NO_ERROR)
4188 type = MAILIMF_FIELD_ORIG_DATE;
4189 else if (r == MAILIMF_ERROR_PARSE) {
4197 case MAILIMF_FIELD_FROM:
4198 r = mailimf_from_parse(message, length, &cur_token,
4200 if (r == MAILIMF_NO_ERROR)
4201 type = guessed_type;
4202 else if (r == MAILIMF_ERROR_PARSE) {
4210 case MAILIMF_FIELD_SENDER:
4211 r = mailimf_sender_parse(message, length, &cur_token,
4213 if (r == MAILIMF_NO_ERROR)
4214 type = guessed_type;
4215 else if (r == MAILIMF_ERROR_PARSE) {
4223 case MAILIMF_FIELD_REPLY_TO:
4224 r = mailimf_reply_to_parse(message, length, &cur_token,
4226 if (r == MAILIMF_NO_ERROR)
4227 type = guessed_type;
4228 else if (r == MAILIMF_ERROR_PARSE) {
4236 case MAILIMF_FIELD_TO:
4237 r = mailimf_to_parse(message, length, &cur_token,
4239 if (r == MAILIMF_NO_ERROR)
4240 type = guessed_type;
4241 else if (r == MAILIMF_ERROR_PARSE) {
4249 case MAILIMF_FIELD_CC:
4250 r = mailimf_cc_parse(message, length, &cur_token,
4252 if (r == MAILIMF_NO_ERROR)
4253 type = guessed_type;
4254 else if (r == MAILIMF_ERROR_PARSE) {
4262 case MAILIMF_FIELD_BCC:
4263 r = mailimf_bcc_parse(message, length, &cur_token,
4265 if (r == MAILIMF_NO_ERROR)
4266 type = guessed_type;
4267 else if (r == MAILIMF_ERROR_PARSE) {
4275 case MAILIMF_FIELD_MESSAGE_ID:
4276 r = mailimf_message_id_parse(message, length, &cur_token,
4278 if (r == MAILIMF_NO_ERROR)
4279 type = guessed_type;
4280 else if (r == MAILIMF_ERROR_PARSE) {
4288 case MAILIMF_FIELD_IN_REPLY_TO:
4289 r = mailimf_in_reply_to_parse(message, length, &cur_token,
4291 if (r == MAILIMF_NO_ERROR)
4292 type = guessed_type;
4293 else if (r == MAILIMF_ERROR_PARSE) {
4301 case MAILIMF_FIELD_REFERENCES:
4302 r = mailimf_references_parse(message, length, &cur_token,
4304 if (r == MAILIMF_NO_ERROR)
4305 type = guessed_type;
4306 else if (r == MAILIMF_ERROR_PARSE) {
4314 case MAILIMF_FIELD_SUBJECT:
4315 r = mailimf_subject_parse(message, length, &cur_token,
4317 if (r == MAILIMF_NO_ERROR)
4318 type = guessed_type;
4319 else if (r == MAILIMF_ERROR_PARSE) {
4327 case MAILIMF_FIELD_COMMENTS:
4328 r = mailimf_comments_parse(message, length, &cur_token,
4330 if (r == MAILIMF_NO_ERROR)
4331 type = guessed_type;
4332 else if (r == MAILIMF_ERROR_PARSE) {
4340 case MAILIMF_FIELD_KEYWORDS:
4341 r = mailimf_keywords_parse(message, length, &cur_token,
4343 if (r == MAILIMF_NO_ERROR)
4344 type = guessed_type;
4345 else if (r == MAILIMF_ERROR_PARSE) {
4353 case MAILIMF_FIELD_RETURN_PATH:
4354 r = mailimf_return_parse(message, length, &cur_token,
4356 if (r == MAILIMF_NO_ERROR)
4357 type = guessed_type;
4358 else if (r == MAILIMF_ERROR_PARSE) {
4366 case MAILIMF_FIELD_RESENT_DATE:
4367 r = mailimf_resent_date_parse(message, length, &cur_token,
4369 if (r == MAILIMF_NO_ERROR)
4370 type = guessed_type;
4371 else if (r == MAILIMF_ERROR_PARSE) {
4379 case MAILIMF_FIELD_RESENT_FROM:
4380 r = mailimf_resent_from_parse(message, length, &cur_token,
4382 if (r == MAILIMF_NO_ERROR)
4383 type = guessed_type;
4384 else if (r == MAILIMF_ERROR_PARSE) {
4392 case MAILIMF_FIELD_RESENT_SENDER:
4393 r = mailimf_resent_sender_parse(message, length, &cur_token,
4395 if (r == MAILIMF_NO_ERROR)
4396 type = guessed_type;
4397 else if (r == MAILIMF_ERROR_PARSE) {
4405 case MAILIMF_FIELD_RESENT_TO:
4406 r = mailimf_resent_to_parse(message, length, &cur_token,
4408 if (r == MAILIMF_NO_ERROR)
4409 type = guessed_type;
4410 else if (r == MAILIMF_ERROR_PARSE) {
4418 case MAILIMF_FIELD_RESENT_CC:
4419 r= mailimf_resent_cc_parse(message, length, &cur_token,
4421 if (r == MAILIMF_NO_ERROR)
4422 type = guessed_type;
4423 else if (r == MAILIMF_ERROR_PARSE) {
4431 case MAILIMF_FIELD_RESENT_BCC:
4432 r = mailimf_resent_bcc_parse(message, length, &cur_token,
4434 if (r == MAILIMF_NO_ERROR)
4435 type = guessed_type;
4436 else if (r == MAILIMF_ERROR_PARSE) {
4444 case MAILIMF_FIELD_RESENT_MSG_ID:
4445 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
4447 if (r == MAILIMF_NO_ERROR)
4448 type = guessed_type;
4449 else if (r == MAILIMF_ERROR_PARSE) {
4459 if (type == MAILIMF_FIELD_NONE) {
4460 r = mailimf_optional_field_parse(message, length, &cur_token,
4462 if (r != MAILIMF_NO_ERROR) {
4467 type = MAILIMF_FIELD_OPTIONAL_FIELD;
4470 field = mailimf_field_new(type, return_path, resent_date,
4471 resent_from, resent_sender, resent_to, resent_cc, resent_bcc,
4472 resent_msg_id, orig_date, from, sender, reply_to, to,
4473 cc, bcc, message_id, in_reply_to, references,
4474 subject, comments, keywords, optional_field);
4475 if (field == NULL) {
4476 res = MAILIMF_ERROR_MEMORY;
4481 * index = cur_token;
4483 return MAILIMF_NO_ERROR;
4486 if (return_path != NULL)
4487 mailimf_return_free(return_path);
4488 if (resent_date != NULL)
4489 mailimf_orig_date_free(resent_date);
4490 if (resent_from != NULL)
4491 mailimf_from_free(resent_from);
4492 if (resent_sender != NULL)
4493 mailimf_sender_free(resent_sender);
4494 if (resent_to != NULL)
4495 mailimf_to_free(resent_to);
4496 if (resent_cc != NULL)
4497 mailimf_cc_free(resent_cc);
4498 if (resent_bcc != NULL)
4499 mailimf_bcc_free(resent_bcc);
4500 if (resent_msg_id != NULL)
4501 mailimf_message_id_free(resent_msg_id);
4502 if (orig_date != NULL)
4503 mailimf_orig_date_free(orig_date);
4505 mailimf_from_free(from);
4507 mailimf_sender_free(sender);
4508 if (reply_to != NULL)
4509 mailimf_reply_to_free(reply_to);
4511 mailimf_to_free(to);
4513 mailimf_cc_free(cc);
4515 mailimf_bcc_free(bcc);
4516 if (message_id != NULL)
4517 mailimf_message_id_free(message_id);
4518 if (in_reply_to != NULL)
4519 mailimf_in_reply_to_free(in_reply_to);
4520 if (references != NULL)
4521 mailimf_references_free(references);
4522 if (subject != NULL)
4523 mailimf_subject_free(subject);
4524 if (comments != NULL)
4525 mailimf_comments_free(comments);
4526 if (keywords != NULL)
4527 mailimf_keywords_free(keywords);
4528 if (optional_field != NULL)
4529 mailimf_optional_field_free(optional_field);
4535 fields = *(delivering-info /
4554 mailimf_unparsed_fields_parse(const char * message, size_t length,
4556 struct mailimf_unparsed_fields ** result)
4560 struct mailimf_unparsed_fields * fields;
4564 cur_token = * index;
4568 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4570 (mailimf_struct_parser *)
4571 mailimf_optional_field_parse,
4572 (mailimf_struct_destructor *)
4573 mailimf_optional_field_free);
4575 if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4582 case MAILIMF_NO_ERROR:
4586 case MAILIMF_ERROR_PARSE:
4589 res = MAILIMF_ERROR_MEMORY;
4599 fields = mailimf_unparsed_fields_new(list);
4600 if (fields == NULL) {
4601 res = MAILIMF_ERROR_MEMORY;
4606 * index = cur_token;
4608 return MAILIMF_NO_ERROR;
4612 clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL);
4620 int mailimf_fields_parse(const char * message, size_t length,
4622 struct mailimf_fields ** result)
4626 struct mailimf_fields * fields;
4630 cur_token = * index;
4634 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4636 (mailimf_struct_parser *)
4637 mailimf_field_parse,
4638 (mailimf_struct_destructor *)
4639 mailimf_field_free);
4641 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4648 case MAILIMF_NO_ERROR:
4652 case MAILIMF_ERROR_PARSE:
4655 res = MAILIMF_ERROR_MEMORY;
4665 fields = mailimf_fields_new(list);
4666 if (fields == NULL) {
4667 res = MAILIMF_ERROR_MEMORY;
4672 * index = cur_token;
4674 return MAILIMF_NO_ERROR;
4678 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
4686 orig-date = "Date:" date-time CRLF
4691 mailimf_orig_date_parse(const char * message, size_t length,
4692 size_t * index, struct mailimf_orig_date ** result)
4694 struct mailimf_date_time * date_time;
4695 struct mailimf_orig_date * orig_date;
4700 cur_token = * index;
4702 r = mailimf_token_case_insensitive_parse(message, length,
4703 &cur_token, "Date:");
4704 if (r != MAILIMF_NO_ERROR) {
4709 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
4710 if (r != MAILIMF_NO_ERROR) {
4715 r = mailimf_ignore_unstructured_parse(message, length, &cur_token);
4716 if (r != MAILIMF_NO_ERROR) {
4718 goto free_date_time;
4721 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4722 if (r != MAILIMF_NO_ERROR) {
4724 goto free_date_time;
4727 orig_date = mailimf_orig_date_new(date_time);
4728 if (orig_date == NULL) {
4729 res = MAILIMF_ERROR_MEMORY;
4730 goto free_date_time;
4733 * result = orig_date;
4734 * index = cur_token;
4736 return MAILIMF_NO_ERROR;
4739 mailimf_date_time_free(date_time);
4745 from = "From:" mailbox-list CRLF
4749 mailimf_from_parse(const char * message, size_t length,
4750 size_t * index, struct mailimf_from ** result)
4752 struct mailimf_mailbox_list * mb_list;
4753 struct mailimf_from * from;
4758 cur_token = * index;
4760 r = mailimf_token_case_insensitive_parse(message, length,
4761 &cur_token, "From");
4762 if (r != MAILIMF_NO_ERROR) {
4767 r = mailimf_colon_parse(message, length, &cur_token);
4768 if (r != MAILIMF_NO_ERROR) {
4773 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
4775 if (r != MAILIMF_NO_ERROR) {
4780 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4781 if (r != MAILIMF_NO_ERROR) {
4786 from = mailimf_from_new(mb_list);
4788 res = MAILIMF_ERROR_MEMORY;
4793 * index = cur_token;
4795 return MAILIMF_NO_ERROR;
4798 mailimf_mailbox_list_free(mb_list);
4804 sender = "Sender:" mailbox CRLF
4808 mailimf_sender_parse(const char * message, size_t length,
4809 size_t * index, struct mailimf_sender ** result)
4811 struct mailimf_mailbox * mb;
4812 struct mailimf_sender * sender;
4817 cur_token = * index;
4819 r = mailimf_token_case_insensitive_parse(message, length,
4820 &cur_token, "Sender");
4821 if (r != MAILIMF_NO_ERROR) {
4826 r = mailimf_colon_parse(message, length, &cur_token);
4827 if (r != MAILIMF_NO_ERROR) {
4832 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
4833 if (r != MAILIMF_NO_ERROR) {
4838 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4839 if (r != MAILIMF_NO_ERROR) {
4844 sender = mailimf_sender_new(mb);
4845 if (sender == NULL) {
4846 res = MAILIMF_ERROR_MEMORY;
4851 * index = cur_token;
4853 return MAILIMF_NO_ERROR;
4856 mailimf_mailbox_free(mb);
4862 reply-to = "Reply-To:" address-list CRLF
4867 mailimf_reply_to_parse(const char * message, size_t length,
4868 size_t * index, struct mailimf_reply_to ** result)
4870 struct mailimf_address_list * addr_list;
4871 struct mailimf_reply_to * reply_to;
4876 cur_token = * index;
4878 r = mailimf_token_case_insensitive_parse(message, length,
4879 &cur_token, "Reply-To");
4880 if (r != MAILIMF_NO_ERROR) {
4885 r = mailimf_colon_parse(message, length, &cur_token);
4886 if (r != MAILIMF_NO_ERROR) {
4891 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4892 if (r != MAILIMF_NO_ERROR) {
4897 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4898 if (r != MAILIMF_NO_ERROR) {
4900 goto free_addr_list;
4903 reply_to = mailimf_reply_to_new(addr_list);
4904 if (reply_to == NULL) {
4905 res = MAILIMF_ERROR_MEMORY;
4906 goto free_addr_list;
4909 * result = reply_to;
4910 * index = cur_token;
4912 return MAILIMF_NO_ERROR;
4915 mailimf_address_list_free(addr_list);
4921 to = "To:" address-list CRLF
4925 mailimf_to_parse(const char * message, size_t length,
4926 size_t * index, struct mailimf_to ** result)
4928 struct mailimf_address_list * addr_list;
4929 struct mailimf_to * to;
4934 cur_token = * index;
4936 r = mailimf_token_case_insensitive_parse(message, length,
4938 if (r != MAILIMF_NO_ERROR) {
4943 r = mailimf_colon_parse(message, length, &cur_token);
4944 if (r != MAILIMF_NO_ERROR) {
4949 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4950 if (r != MAILIMF_NO_ERROR) {
4955 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4956 if (r != MAILIMF_NO_ERROR) {
4958 goto free_addr_list;
4961 to = mailimf_to_new(addr_list);
4963 res = MAILIMF_ERROR_MEMORY;
4964 goto free_addr_list;
4968 * index = cur_token;
4970 return MAILIMF_NO_ERROR;
4973 mailimf_address_list_free(addr_list);
4979 cc = "Cc:" address-list CRLF
4984 mailimf_cc_parse(const char * message, size_t length,
4985 size_t * index, struct mailimf_cc ** result)
4987 struct mailimf_address_list * addr_list;
4988 struct mailimf_cc * cc;
4993 cur_token = * index;
4995 r = mailimf_token_case_insensitive_parse(message, length,
4997 if (r != MAILIMF_NO_ERROR) {
5002 r = mailimf_colon_parse(message, length, &cur_token);
5003 if (r != MAILIMF_NO_ERROR) {
5008 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5009 if (r != MAILIMF_NO_ERROR) {
5014 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5015 if (r != MAILIMF_NO_ERROR) {
5017 goto free_addr_list;
5020 cc = mailimf_cc_new(addr_list);
5022 res = MAILIMF_ERROR_MEMORY;
5023 goto free_addr_list;
5027 * index = cur_token;
5029 return MAILIMF_NO_ERROR;
5032 mailimf_address_list_free(addr_list);
5038 bcc = "Bcc:" (address-list / [CFWS]) CRLF
5043 mailimf_bcc_parse(const char * message, size_t length,
5044 size_t * index, struct mailimf_bcc ** result)
5046 struct mailimf_address_list * addr_list;
5047 struct mailimf_bcc * bcc;
5052 cur_token = * index;
5055 r = mailimf_token_case_insensitive_parse(message, length,
5057 if (r != MAILIMF_NO_ERROR) {
5062 r = mailimf_colon_parse(message, length, &cur_token);
5063 if (r != MAILIMF_NO_ERROR) {
5068 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5070 case MAILIMF_NO_ERROR:
5073 case MAILIMF_ERROR_PARSE:
5074 r = mailimf_cfws_parse(message, length, &cur_token);
5075 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
5085 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5086 if (r != MAILIMF_NO_ERROR) {
5088 goto free_addr_list;
5091 bcc = mailimf_bcc_new(addr_list);
5093 res = MAILIMF_ERROR_MEMORY;
5094 goto free_addr_list;
5098 * index = cur_token;
5100 return MAILIMF_NO_ERROR;
5103 mailimf_address_list_free(addr_list);
5109 message-id = "Message-ID:" msg-id CRLF
5112 static int mailimf_message_id_parse(const char * message, size_t length,
5114 struct mailimf_message_id ** result)
5118 struct mailimf_message_id * message_id;
5122 cur_token = * index;
5124 r = mailimf_token_case_insensitive_parse(message, length,
5125 &cur_token, "Message-ID");
5126 if (r != MAILIMF_NO_ERROR) {
5131 r = mailimf_colon_parse(message, length, &cur_token);
5132 if (r != MAILIMF_NO_ERROR) {
5137 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
5138 if (r != MAILIMF_NO_ERROR) {
5143 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5144 if (r != MAILIMF_NO_ERROR) {
5149 message_id = mailimf_message_id_new(value);
5150 if (message_id == NULL) {
5151 res = MAILIMF_ERROR_MEMORY;
5155 * result = message_id;
5156 * index = cur_token;
5158 return MAILIMF_NO_ERROR;
5161 mailimf_msg_id_free(value);
5167 in-reply-to = "In-Reply-To:" 1*msg-id CRLF
5170 int mailimf_msg_id_list_parse(const char * message, size_t length,
5171 size_t * index, clist ** result)
5173 return mailimf_struct_multiple_parse(message, length, index,
5175 (mailimf_struct_parser *)
5176 mailimf_unstrict_msg_id_parse,
5177 (mailimf_struct_destructor *)
5178 mailimf_msg_id_free);
5181 static int mailimf_in_reply_to_parse(const char * message, size_t length,
5183 struct mailimf_in_reply_to ** result)
5185 struct mailimf_in_reply_to * in_reply_to;
5187 clist * msg_id_list;
5191 cur_token = * index;
5193 r = mailimf_token_case_insensitive_parse(message, length,
5194 &cur_token, "In-Reply-To");
5195 if (r != MAILIMF_NO_ERROR) {
5200 r = mailimf_colon_parse(message, length, &cur_token);
5201 if (r != MAILIMF_NO_ERROR) {
5206 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5207 if (r != MAILIMF_NO_ERROR) {
5212 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5213 if (r != MAILIMF_NO_ERROR) {
5218 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
5219 if (in_reply_to == NULL) {
5220 res = MAILIMF_ERROR_MEMORY;
5224 * result = in_reply_to;
5225 * index = cur_token;
5227 return MAILIMF_NO_ERROR;
5230 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5231 clist_free(msg_id_list);
5237 references = "References:" 1*msg-id CRLF
5240 int mailimf_references_parse(const char * message, size_t length,
5242 struct mailimf_references ** result)
5244 struct mailimf_references * references;
5246 clist * msg_id_list;
5250 cur_token = * index;
5252 r = mailimf_token_case_insensitive_parse(message, length,
5253 &cur_token, "References");
5254 if (r != MAILIMF_NO_ERROR) {
5259 r = mailimf_colon_parse(message, length, &cur_token);
5260 if (r != MAILIMF_NO_ERROR) {
5265 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5266 if (r != MAILIMF_NO_ERROR) {
5271 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5272 if (r != MAILIMF_NO_ERROR) {
5277 references = mailimf_references_new(msg_id_list);
5278 if (references == NULL) {
5279 res = MAILIMF_ERROR_MEMORY;
5283 * result = references;
5284 * index = cur_token;
5286 return MAILIMF_NO_ERROR;
5289 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5290 clist_free(msg_id_list);
5296 msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
5299 int mailimf_msg_id_parse(const char * message, size_t length,
5312 cur_token = * index;
5314 r = mailimf_cfws_parse(message, length, &cur_token);
5315 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5318 r = mailimf_lower_parse(message, length, &cur_token);
5319 if (r != MAILIMF_NO_ERROR) {
5324 r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id);
5325 if (r != MAILIMF_NO_ERROR) {
5330 r = mailimf_greater_parse(message, length, &cur_token);
5331 if (r != MAILIMF_NO_ERROR) {
5338 r = mailimf_id_left_parse(message, length, &cur_token, &id_left);
5339 if (r != MAILIMF_NO_ERROR) {
5344 r = mailimf_at_sign_parse(message, length, &cur_token);
5345 if (r != MAILIMF_NO_ERROR) {
5350 r = mailimf_id_right_parse(message, length, &cur_token, &id_right);
5351 if (r != MAILIMF_NO_ERROR) {
5356 r = mailimf_greater_parse(message, length, &cur_token);
5357 if (r != MAILIMF_NO_ERROR) {
5362 msg_id = malloc(strlen(id_left) + strlen(id_right) + 2);
5363 if (msg_id == NULL) {
5364 res = MAILIMF_ERROR_MEMORY;
5367 strcpy(msg_id, id_left);
5368 strcat(msg_id, "@");
5369 strcat(msg_id, id_right);
5371 mailimf_id_left_free(id_left);
5372 mailimf_id_right_free(id_right);
5376 * index = cur_token;
5378 return MAILIMF_NO_ERROR;
5382 mailimf_id_right_free(id_right);
5384 mailimf_id_left_free(id_left);
5388 mailimf_atom_free(msg_id);
5394 static int mailimf_parse_unwanted_msg_id(const char * message, size_t length,
5402 cur_token = * index;
5404 token_parsed = TRUE;
5405 while (token_parsed) {
5406 token_parsed = FALSE;
5407 r = mailimf_word_parse(message, length, &cur_token, &word);
5408 if (r == MAILIMF_NO_ERROR) {
5409 mailimf_word_free(word);
5410 token_parsed = TRUE;
5412 else if (r == MAILIMF_ERROR_PARSE) {
5417 r = mailimf_semi_colon_parse(message, length, &cur_token);
5418 if (r == MAILIMF_NO_ERROR)
5419 token_parsed = TRUE;
5420 else if (r == MAILIMF_ERROR_PARSE) {
5425 r = mailimf_comma_parse(message, length, &cur_token);
5426 if (r == MAILIMF_NO_ERROR)
5427 token_parsed = TRUE;
5428 else if (r == MAILIMF_ERROR_PARSE) {
5433 r = mailimf_plus_parse(message, length, &cur_token);
5434 if (r == MAILIMF_NO_ERROR)
5435 token_parsed = TRUE;
5436 else if (r == MAILIMF_ERROR_PARSE) {
5441 r = mailimf_colon_parse(message, length, &cur_token);
5442 if (r == MAILIMF_NO_ERROR)
5443 token_parsed = TRUE;
5444 else if (r == MAILIMF_ERROR_PARSE) {
5449 r = mailimf_point_parse(message, length, &cur_token);
5450 if (r == MAILIMF_NO_ERROR)
5451 token_parsed = TRUE;
5452 else if (r == MAILIMF_ERROR_PARSE) {
5457 r = mailimf_at_sign_parse(message, length, &cur_token);
5458 if (r == MAILIMF_NO_ERROR)
5459 token_parsed = TRUE;
5460 else if (r == MAILIMF_ERROR_PARSE) {
5467 return MAILIMF_NO_ERROR;
5470 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
5474 char * msgid = NULL;
5478 cur_token = * index;
5480 r = mailimf_cfws_parse(message, length, &cur_token);
5481 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5484 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5485 if (r != MAILIMF_NO_ERROR)
5488 r = mailimf_msg_id_parse(message, length, &cur_token, &msgid);
5489 if (r != MAILIMF_NO_ERROR)
5492 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5493 if (r != MAILIMF_NO_ERROR) {
5499 * index = cur_token;
5501 return MAILIMF_NO_ERROR;
5505 id-left = dot-atom-text / no-fold-quote / obs-id-left
5509 static int mailimf_id_left_parse(const char * message, size_t length,
5510 size_t * index, char ** result)
5514 r = mailimf_dot_atom_text_parse(message, length, index, result);
5516 case MAILIMF_NO_ERROR:
5517 return MAILIMF_NO_ERROR;
5518 case MAILIMF_ERROR_PARSE:
5524 r = mailimf_no_fold_quote_parse(message, length, index, result);
5525 if (r != MAILIMF_NO_ERROR)
5528 return MAILIMF_NO_ERROR;
5533 id-right = dot-atom-text / no-fold-literal / obs-id-right
5537 static int mailimf_id_right_parse(const char * message, size_t length,
5538 size_t * index, char ** result)
5542 r = mailimf_dot_atom_text_parse(message, length, index, result);
5544 case MAILIMF_NO_ERROR:
5545 return MAILIMF_NO_ERROR;
5546 case MAILIMF_ERROR_PARSE:
5552 r = mailimf_no_fold_literal_parse(message, length, index, result);
5553 if (r != MAILIMF_NO_ERROR)
5556 return MAILIMF_NO_ERROR;
5561 no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
5565 static int mailimf_no_fold_quote_char_parse(const char * message, size_t length,
5566 size_t * index, char * result)
5572 cur_token = * index;
5575 r = mailimf_qtext_parse(message, length, &cur_token, &ch);
5578 if (cur_token >= length)
5579 return MAILIMF_ERROR_PARSE;
5581 if (is_qtext(message[cur_token])) {
5582 ch = message[cur_token];
5586 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5588 if (r != MAILIMF_NO_ERROR)
5592 * index = cur_token;
5595 return MAILIMF_NO_ERROR;
5600 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
5601 size_t * index, char ** result)
5606 char * no_fold_quote;
5611 r = mailimf_dquote_parse(message, length, &cur_token);
5612 if (r != MAILIMF_NO_ERROR) {
5618 r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch);
5619 if (r == MAILIMF_NO_ERROR) {
5622 else if (r == MAILIMF_ERROR_PARSE)
5630 r = mailimf_dquote_parse(message, length, &cur_token);
5631 if (r != MAILIMF_NO_ERROR) {
5636 /* no_fold_quote = strndup(message + begin, cur_token - begin); */
5637 no_fold_quote = malloc(cur_token - begin + 1);
5638 if (no_fold_quote == NULL) {
5639 res = MAILIMF_ERROR_MEMORY;
5642 strncpy(no_fold_quote, message + begin, cur_token - begin);
5643 no_fold_quote[cur_token - begin] = '\0';
5645 * result = no_fold_quote;
5646 * index = cur_token;
5648 return MAILIMF_NO_ERROR;
5656 no-fold-literal = "[" *(dtext / quoted-pair) "]"
5661 mailimf_no_fold_literal_char_parse(const char * message, size_t length,
5662 size_t * index, char * result)
5668 cur_token = * index;
5671 r = mailimf_dtext_parse(message, length, &cur_token, &ch);
5673 if (cur_token >= length)
5674 return MAILIMF_ERROR_PARSE;
5676 if (is_dtext(message[cur_token])) {
5677 ch = message[cur_token];
5681 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5683 if (r != MAILIMF_NO_ERROR)
5687 * index = cur_token;
5690 return MAILIMF_NO_ERROR;
5695 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
5696 size_t * index, char ** result)
5701 char * no_fold_literal;
5706 r = mailimf_obracket_parse(message, length, &cur_token);
5707 if (r != MAILIMF_NO_ERROR) {
5713 r = mailimf_no_fold_literal_char_parse(message, length,
5715 if (r == MAILIMF_NO_ERROR) {
5718 else if (r == MAILIMF_ERROR_PARSE)
5726 r = mailimf_cbracket_parse(message, length, &cur_token);
5727 if (r != MAILIMF_NO_ERROR) {
5733 no_fold_literal = strndup(message + begin, cur_token - begin);
5735 no_fold_literal = malloc(cur_token - begin + 1);
5736 if (no_fold_literal == NULL) {
5737 res = MAILIMF_NO_ERROR;
5740 strncpy(no_fold_literal, message + begin, cur_token - begin);
5741 no_fold_literal[cur_token - begin] = '\0';
5743 * result = no_fold_literal;
5744 * index = cur_token;
5746 return MAILIMF_NO_ERROR;
5754 subject = "Subject:" unstructured CRLF
5757 static int mailimf_subject_parse(const char * message, size_t length,
5759 struct mailimf_subject ** result)
5761 struct mailimf_subject * subject;
5767 cur_token = * index;
5769 r = mailimf_token_case_insensitive_parse(message, length,
5770 &cur_token, "Subject");
5771 if (r != MAILIMF_NO_ERROR) {
5776 r = mailimf_colon_parse(message, length, &cur_token);
5777 if (r != MAILIMF_NO_ERROR) {
5782 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5783 if (r != MAILIMF_NO_ERROR) {
5788 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5789 if (r != MAILIMF_NO_ERROR) {
5794 subject = mailimf_subject_new(value);
5795 if (subject == NULL) {
5796 res = MAILIMF_ERROR_MEMORY;
5801 * index = cur_token;
5803 return MAILIMF_NO_ERROR;
5806 mailimf_unstructured_free(value);
5812 comments = "Comments:" unstructured CRLF
5815 static int mailimf_comments_parse(const char * message, size_t length,
5817 struct mailimf_comments ** result)
5819 struct mailimf_comments * comments;
5825 cur_token = * index;
5827 r = mailimf_token_case_insensitive_parse(message, length,
5828 &cur_token, "Comments");
5829 if (r != MAILIMF_NO_ERROR) {
5834 r = mailimf_colon_parse(message, length, &cur_token);
5835 if (r != MAILIMF_NO_ERROR) {
5840 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5841 if (r != MAILIMF_NO_ERROR) {
5846 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5847 if (r != MAILIMF_NO_ERROR) {
5852 comments = mailimf_comments_new(value);
5853 if (comments == NULL) {
5854 res = MAILIMF_ERROR_MEMORY;
5858 * result = comments;
5859 * index = cur_token;
5861 return MAILIMF_NO_ERROR;
5864 mailimf_unstructured_free(value);
5870 keywords = "Keywords:" phrase *("," phrase) CRLF
5873 static int mailimf_keywords_parse(const char * message, size_t length,
5875 struct mailimf_keywords ** result)
5877 struct mailimf_keywords * keywords;
5883 cur_token = * index;
5885 r = mailimf_token_case_insensitive_parse(message, length,
5886 &cur_token, "Keywords");
5887 if (r != MAILIMF_NO_ERROR) {
5892 r = mailimf_colon_parse(message, length, &cur_token);
5893 if (r != MAILIMF_NO_ERROR) {
5898 r = mailimf_struct_list_parse(message, length, &cur_token,
5900 (mailimf_struct_parser *)
5901 mailimf_phrase_parse,
5902 (mailimf_struct_destructor *)
5903 mailimf_phrase_free);
5904 if (r != MAILIMF_NO_ERROR) {
5909 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5910 if (r != MAILIMF_NO_ERROR) {
5915 keywords = mailimf_keywords_new(list);
5916 if (keywords == NULL) {
5917 res = MAILIMF_ERROR_MEMORY;
5921 * result = keywords;
5922 * index = cur_token;
5924 return MAILIMF_NO_ERROR;
5927 clist_foreach(list, (clist_func) mailimf_phrase_free, NULL);
5934 resent-date = "Resent-Date:" date-time CRLF
5938 mailimf_resent_date_parse(const char * message, size_t length,
5939 size_t * index, struct mailimf_orig_date ** result)
5941 struct mailimf_orig_date * orig_date;
5942 struct mailimf_date_time * date_time;
5947 cur_token = * index;
5949 r = mailimf_token_case_insensitive_parse(message, length,
5950 &cur_token, "Resent-Date");
5951 if (r != MAILIMF_NO_ERROR) {
5956 r = mailimf_colon_parse(message, length, &cur_token);
5957 if (r != MAILIMF_NO_ERROR) {
5962 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
5963 if (r != MAILIMF_NO_ERROR) {
5968 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5969 if (r != MAILIMF_NO_ERROR) {
5971 goto free_date_time;
5974 orig_date = mailimf_orig_date_new(date_time);
5975 if (orig_date == NULL) {
5976 res = MAILIMF_ERROR_MEMORY;
5977 goto free_date_time;
5980 * result = orig_date;
5981 * index = cur_token;
5983 return MAILIMF_NO_ERROR;
5986 mailimf_date_time_free(date_time);
5992 resent-from = "Resent-From:" mailbox-list CRLF
5996 mailimf_resent_from_parse(const char * message, size_t length,
5997 size_t * index, struct mailimf_from ** result)
5999 struct mailimf_mailbox_list * mb_list;
6000 struct mailimf_from * from;
6005 cur_token = * index;
6007 r = mailimf_token_case_insensitive_parse(message, length,
6008 &cur_token, "Resent-From");
6009 if (r != MAILIMF_NO_ERROR) {
6014 r = mailimf_colon_parse(message, length, &cur_token);
6015 if (r != MAILIMF_NO_ERROR) {
6020 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
6021 if (r != MAILIMF_NO_ERROR) {
6026 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6027 if (r != MAILIMF_NO_ERROR) {
6032 from = mailimf_from_new(mb_list);
6034 res = MAILIMF_ERROR_MEMORY;
6039 * index = cur_token;
6041 return MAILIMF_NO_ERROR;
6044 mailimf_mailbox_list_free(mb_list);
6050 resent-sender = "Resent-Sender:" mailbox CRLF
6054 mailimf_resent_sender_parse(const char * message, size_t length,
6055 size_t * index, struct mailimf_sender ** result)
6057 struct mailimf_mailbox * mb;
6058 struct mailimf_sender * sender;
6065 r = mailimf_token_case_insensitive_parse(message, length,
6066 &cur_token, "Resent-Sender");
6067 if (r != MAILIMF_NO_ERROR) {
6072 r = mailimf_colon_parse(message, length, &cur_token);
6073 if (r != MAILIMF_NO_ERROR) {
6078 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
6079 if (r != MAILIMF_NO_ERROR) {
6084 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6085 if (r != MAILIMF_NO_ERROR) {
6090 sender = mailimf_sender_new(mb);
6091 if (sender == NULL) {
6092 res = MAILIMF_ERROR_MEMORY;
6097 * index = cur_token;
6099 return MAILIMF_NO_ERROR;
6102 mailimf_mailbox_free(mb);
6108 resent-to = "Resent-To:" address-list CRLF
6112 mailimf_resent_to_parse(const char * message, size_t length,
6113 size_t * index, struct mailimf_to ** result)
6115 struct mailimf_address_list * addr_list;
6116 struct mailimf_to * to;
6121 cur_token = * index;
6123 r = mailimf_token_case_insensitive_parse(message, length,
6124 &cur_token, "Resent-To");
6125 if (r != MAILIMF_NO_ERROR) {
6130 r = mailimf_colon_parse(message, length, &cur_token);
6131 if (r != MAILIMF_NO_ERROR) {
6136 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6137 if (r != MAILIMF_NO_ERROR) {
6142 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6143 if (r != MAILIMF_NO_ERROR) {
6145 goto free_addr_list;
6148 to = mailimf_to_new(addr_list);
6150 res = MAILIMF_ERROR_MEMORY;
6151 goto free_addr_list;
6155 * index = cur_token;
6157 return MAILIMF_NO_ERROR;
6160 mailimf_address_list_free(addr_list);
6166 resent-cc = "Resent-Cc:" address-list CRLF
6170 mailimf_resent_cc_parse(const char * message, size_t length,
6171 size_t * index, struct mailimf_cc ** result)
6173 struct mailimf_address_list * addr_list;
6174 struct mailimf_cc * cc;
6179 cur_token = * index;
6181 r = mailimf_token_case_insensitive_parse(message, length,
6182 &cur_token, "Resent-Cc");
6183 if (r != MAILIMF_NO_ERROR) {
6188 r = mailimf_colon_parse(message, length, &cur_token);
6189 if (r != MAILIMF_NO_ERROR) {
6194 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6195 if (r != MAILIMF_NO_ERROR) {
6200 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6201 if (r != MAILIMF_NO_ERROR) {
6203 goto free_addr_list;
6206 cc = mailimf_cc_new(addr_list);
6208 res = MAILIMF_ERROR_MEMORY;
6209 goto free_addr_list;
6213 * index = cur_token;
6215 return MAILIMF_NO_ERROR;
6218 mailimf_address_list_free(addr_list);
6224 resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF
6228 mailimf_resent_bcc_parse(const char * message, size_t length,
6229 size_t * index, struct mailimf_bcc ** result)
6231 struct mailimf_address_list * addr_list;
6232 struct mailimf_bcc * bcc;
6237 cur_token = * index;
6240 r = mailimf_token_case_insensitive_parse(message, length,
6241 &cur_token, "Resent-Bcc");
6242 if (r != MAILIMF_NO_ERROR) {
6247 r = mailimf_colon_parse(message, length, &cur_token);
6248 if (r != MAILIMF_NO_ERROR) {
6253 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6254 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6259 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6260 if (r != MAILIMF_NO_ERROR) {
6262 goto free_addr_list;
6265 bcc = mailimf_bcc_new(addr_list);
6267 res = MAILIMF_ERROR_MEMORY;
6268 goto free_addr_list;
6272 * index = cur_token;
6277 mailimf_address_list_free(addr_list);
6283 resent-msg-id = "Resent-Message-ID:" msg-id CRLF
6287 mailimf_resent_msg_id_parse(const char * message, size_t length,
6289 struct mailimf_message_id ** result)
6293 struct mailimf_message_id * message_id;
6297 cur_token = * index;
6299 r = mailimf_token_case_insensitive_parse(message, length,
6300 &cur_token, "Resent-Message-ID");
6301 if (r != MAILIMF_NO_ERROR) {
6306 r = mailimf_colon_parse(message, length, &cur_token);
6307 if (r != MAILIMF_NO_ERROR) {
6312 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
6313 if (r != MAILIMF_NO_ERROR) {
6318 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6319 if (r != MAILIMF_NO_ERROR) {
6324 message_id = mailimf_message_id_new(value);
6325 if (message_id == NULL) {
6326 res = MAILIMF_ERROR_MEMORY;
6330 * result = message_id;
6331 * index = cur_token;
6333 return MAILIMF_NO_ERROR;
6336 mailimf_msg_id_free(value);
6347 static int mailimf_trace_parse(const char * message, size_t length,
6349 struct mailimf_trace ** result)
6352 struct mailimf_return * return_path;
6353 clist * received_list;
6354 struct mailimf_trace * trace;
6358 cur_token = * index;
6360 received_list = NULL;
6362 r = mailimf_return_parse(message, length, &cur_token, &return_path);
6363 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6368 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6370 (mailimf_struct_parser *)
6371 mailimf_received_parse,
6372 (mailimf_struct_destructor *)
6373 mailimf_received_free);
6374 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6379 if ((received_list == NULL) && (return_path == NULL)) {
6380 res = MAILIMF_ERROR_PARSE;
6384 trace = mailimf_trace_new(return_path, received_list);
6385 if (trace == NULL) {
6386 res = MAILIMF_ERROR_MEMORY;
6391 * index = cur_token;
6393 return MAILIMF_NO_ERROR;
6396 clist_foreach(received_list, (clist_func) mailimf_received_free, NULL);
6397 clist_free(received_list);
6399 if (return_path != NULL)
6400 mailimf_return_free(return_path);
6407 return = "Return-Path:" path CRLF
6410 static int mailimf_return_parse(const char * message, size_t length,
6412 struct mailimf_return ** result)
6414 struct mailimf_path * path = NULL;
6415 struct mailimf_return * return_path;
6420 cur_token = * index;
6422 r = mailimf_token_case_insensitive_parse(message, length,
6423 &cur_token, "Return-Path");
6424 if (r != MAILIMF_NO_ERROR) {
6429 r = mailimf_colon_parse(message, length, &cur_token);
6430 if (r != MAILIMF_NO_ERROR) {
6435 r = mailimf_path_parse(message, length, &cur_token, &path);
6436 if ( r!= MAILIMF_NO_ERROR) {
6441 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6442 if (r != MAILIMF_NO_ERROR) {
6447 return_path = mailimf_return_new(path);
6448 if (return_path == NULL) {
6449 res = MAILIMF_ERROR_MEMORY;
6453 * result = return_path;
6454 * index = cur_token;
6456 return MAILIMF_NO_ERROR;
6459 mailimf_path_free(path);
6465 path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
6469 static int mailimf_path_parse(const char * message, size_t length,
6470 size_t * index, struct mailimf_path ** result)
6474 struct mailimf_path * path;
6478 cur_token = * index;
6481 r = mailimf_cfws_parse(message, length, &cur_token);
6482 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6487 r = mailimf_lower_parse(message, length, &cur_token);
6488 if (r != MAILIMF_NO_ERROR) {
6493 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
6495 case MAILIMF_NO_ERROR:
6497 case MAILIMF_ERROR_PARSE:
6498 r = mailimf_cfws_parse(message, length, &cur_token);
6499 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6508 r = mailimf_greater_parse(message, length, &cur_token);
6509 if (r != MAILIMF_NO_ERROR) {
6511 goto free_addr_spec;
6514 path = mailimf_path_new(addr_spec);
6516 res = MAILIMF_ERROR_MEMORY;
6517 goto free_addr_spec;
6520 * index = cur_token;
6523 return MAILIMF_NO_ERROR;
6526 if (addr_spec != NULL)
6527 mailimf_addr_spec_free(addr_spec);
6533 received = "Received:" name-val-list ";" date-time CRLF
6537 static int mailimf_received_parse(const char * message, size_t length,
6539 struct mailimf_received ** result)
6542 struct mailimf_received * received;
6543 struct mailimf_name_val_list * name_val_list;
6544 struct mailimf_date_time * date_time;
6548 cur_token = * index;
6550 r = mailimf_token_case_insensitive_parse(message, length,
6551 &cur_token, "Received");
6552 if (r != MAILIMF_NO_ERROR) {
6557 r = mailimf_colon_parse(message, length, &cur_token);
6558 if (r != MAILIMF_NO_ERROR) {
6563 r = mailimf_name_val_list_parse(message, length,
6564 &cur_token, &name_val_list);
6565 if (r != MAILIMF_NO_ERROR) {
6570 r = mailimf_semi_colon_parse(message, length, &cur_token);
6571 if (r != MAILIMF_NO_ERROR) {
6573 goto free_name_val_list;
6576 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
6577 if (r != MAILIMF_NO_ERROR) {
6579 goto free_name_val_list;
6582 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6583 if (r != MAILIMF_NO_ERROR) {
6585 goto free_date_time;
6588 received = mailimf_received_new(name_val_list, date_time);
6589 if (received == NULL) {
6590 res = MAILIMF_ERROR_MEMORY;
6591 goto free_date_time;
6594 * index = cur_token;
6595 * result = received;
6597 return MAILIMF_NO_ERROR;
6600 mailimf_date_time_free(date_time);
6602 mailimf_name_val_list_free(name_val_list);
6609 name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
6614 mailimf_name_val_list_parse(const char * message, size_t length,
6616 struct mailimf_name_val_list ** result)
6619 struct mailimf_name_val_pair * pair;
6620 struct mailimf_name_val_list * name_val_list;
6625 cur_token = * index;
6628 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6630 if (r == MAILIMF_NO_ERROR){
6635 mailimf_name_val_pair_free(pair);
6636 res = MAILIMF_ERROR_MEMORY;
6640 r = clist_append(list, pair);
6642 mailimf_name_val_pair_free(pair);
6643 res = MAILIMF_ERROR_MEMORY;
6647 final_token = cur_token;
6650 r = mailimf_cfws_parse(message, length, &cur_token);
6651 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6656 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6657 if (r == MAILIMF_NO_ERROR) {
6660 else if (r == MAILIMF_ERROR_PARSE)
6667 r = clist_append(list, pair);
6669 mailimf_name_val_pair_free(pair);
6670 res = MAILIMF_ERROR_MEMORY;
6674 final_token = cur_token;
6676 cur_token = final_token;
6679 name_val_list = mailimf_name_val_list_new(list);
6680 if (name_val_list == NULL) {
6681 res = MAILIMF_ERROR_MEMORY;
6685 * index = cur_token;
6686 * result = name_val_list;
6688 return MAILIMF_NO_ERROR;
6692 clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL);
6701 name-val-pair = item-name CFWS item-value
6706 mailimf_name_val_pair_parse(const char * message, size_t length,
6708 struct mailimf_name_val_pair ** result)
6712 struct mailimf_item_value * item_value;
6713 struct mailimf_name_val_pair * name_val_pair;
6717 cur_token = * index;
6719 r = mailimf_cfws_parse(message, length, &cur_token);
6720 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6725 r = mailimf_item_name_parse(message, length, &cur_token, &item_name);
6726 if (r != MAILIMF_NO_ERROR) {
6731 r = mailimf_cfws_parse(message, length, &cur_token);
6732 if (r != MAILIMF_NO_ERROR) {
6734 goto free_item_name;
6737 r = mailimf_item_value_parse(message, length, &cur_token, &item_value);
6738 if (r != MAILIMF_NO_ERROR) {
6740 goto free_item_name;
6743 name_val_pair = mailimf_name_val_pair_new(item_name, item_value);
6744 if (name_val_pair == NULL) {
6745 res = MAILIMF_ERROR_MEMORY;
6746 goto free_item_value;
6749 * result = name_val_pair;
6750 * index = cur_token;
6752 return MAILIMF_NO_ERROR;
6755 mailimf_item_value_free(item_value);
6757 mailimf_item_name_free(item_name);
6764 item-name = ALPHA *(["-"] (ALPHA / DIGIT))
6768 static int mailimf_item_name_parse(const char * message, size_t length,
6769 size_t * index, char ** result)
6779 cur_token = * index;
6783 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6784 if (r != MAILIMF_NO_ERROR) {
6792 minus_sign = mailimf_minus_parse(message, length, &cur_token);
6794 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6795 if (r == MAILIMF_ERROR_PARSE)
6796 r = mailimf_digit_parse(message, length, &cur_token, &digit);
6798 if (r == MAILIMF_NO_ERROR) {
6801 if (r == MAILIMF_ERROR_PARSE)
6803 else if (r != MAILIMF_NO_ERROR) {
6809 item_name = strndup(message + begin, cur_token - begin);
6810 if (item_name == NULL) {
6811 res = MAILIMF_ERROR_MEMORY;
6815 * index = cur_token;
6816 * result = item_name;
6818 return MAILIMF_NO_ERROR;
6826 item-value = 1*angle-addr / addr-spec /
6827 atom / domain / msg-id
6831 static int is_item_value_atext(char ch)
6845 static int mailimf_item_value_atom_parse(const char * message, size_t length,
6846 size_t * index, char ** result)
6852 cur_token = * index;
6854 r = mailimf_cfws_parse(message, length, &cur_token);
6855 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6858 r = mailimf_custom_string_parse(message, length, &cur_token,
6859 &atom, is_item_value_atext);
6860 if (r != MAILIMF_NO_ERROR)
6863 r = mailimf_cfws_parse(message, length, &cur_token);
6864 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6867 * index = cur_token;
6870 return MAILIMF_NO_ERROR;
6873 static int mailimf_item_value_parse(const char * message, size_t length,
6875 struct mailimf_item_value ** result)
6878 clist * angle_addr_list;
6884 struct mailimf_item_value * item_value;
6888 cur_token = * index;
6890 angle_addr_list = NULL;
6896 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6898 (mailimf_struct_parser *)
6899 mailimf_angle_addr_parse,
6900 (mailimf_struct_destructor *)
6901 mailimf_angle_addr_free);
6902 if (r == MAILIMF_NO_ERROR)
6903 type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST;
6905 if (r == MAILIMF_ERROR_PARSE) {
6906 r = mailimf_addr_spec_parse(message, length, &cur_token,
6908 if (r == MAILIMF_NO_ERROR)
6909 type = MAILIMF_ITEM_VALUE_ADDR_SPEC;
6912 if (r == MAILIMF_ERROR_PARSE) {
6913 r = mailimf_msg_id_parse(message, length, &cur_token,
6915 if (r == MAILIMF_NO_ERROR)
6916 type = MAILIMF_ITEM_VALUE_MSG_ID;
6920 else if (mailimf_domain_parse(message, length, &cur_token,
6922 type = MAILIMF_ITEM_VALUE_DOMAIN;
6925 else if (mailimf_atom_parse(message, length, &cur_token,
6927 type = MAILIMF_ITEM_VALUE_ATOM;
6930 if (r == MAILIMF_ERROR_PARSE) {
6931 r = mailimf_item_value_atom_parse(message, length, &cur_token,
6933 if (r == MAILIMF_NO_ERROR)
6934 type = MAILIMF_ITEM_VALUE_ATOM;
6937 if (r != MAILIMF_NO_ERROR) {
6942 item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec,
6943 atom, domain, msg_id);
6944 if (item_value == NULL) {
6945 res = MAILIMF_ERROR_MEMORY;
6949 * result = item_value;
6950 * index = cur_token;
6952 return MAILIMF_NO_ERROR;
6955 if (angle_addr_list != NULL) {
6956 clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL);
6957 clist_free(angle_addr_list);
6959 if (addr_spec != NULL)
6960 mailimf_addr_spec_free(addr_spec);
6962 mailimf_atom_free(atom);
6964 mailimf_domain_free(domain);
6966 mailimf_msg_id_free(msg_id);
6973 optional-field = field-name ":" unstructured CRLF
6977 mailimf_optional_field_parse(const char * message, size_t length,
6979 struct mailimf_optional_field ** result)
6983 struct mailimf_optional_field * optional_field;
6990 optional_field = NULL;
6992 cur_token = * index;
6994 r = mailimf_field_name_parse(message, length, &cur_token, &name);
6995 if (r != MAILIMF_NO_ERROR) {
7000 r = mailimf_colon_parse(message, length, &cur_token);
7001 if (r != MAILIMF_NO_ERROR) {
7006 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
7007 if (r != MAILIMF_NO_ERROR) {
7012 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
7013 if (r != MAILIMF_NO_ERROR) {
7018 optional_field = mailimf_optional_field_new(name, value);
7019 if (optional_field == NULL) {
7020 res = MAILIMF_ERROR_MEMORY;
7024 * result = optional_field;
7025 * index = cur_token;
7027 return MAILIMF_NO_ERROR;
7031 mailimf_unstructured_free(value);
7033 mailimf_field_name_free(name);
7040 field-name = 1*ftext
7043 static inline int is_ftext(char ch);
7045 static int mailimf_field_name_parse(const char * message, size_t length,
7046 size_t * index, char ** result)
7052 cur_token = * index;
7055 if (end >= length) {
7056 return MAILIMF_ERROR_PARSE;
7059 while (is_ftext(message[end])) {
7064 if (end == cur_token) {
7065 return MAILIMF_ERROR_PARSE;
7068 /* field_name = strndup(message + cur_token, end - cur_token); */
7069 field_name = malloc(end - cur_token + 1);
7070 if (field_name == NULL) {
7071 return MAILIMF_ERROR_MEMORY;
7073 strncpy(field_name, message + cur_token, end - cur_token);
7074 field_name[end - cur_token] = '\0';
7078 * index = cur_token;
7079 * result = field_name;
7081 return MAILIMF_NO_ERROR;
7085 ftext = %d33-57 / ; Any character except
7086 %d59-126 ; controls, SP, and
7090 static inline int is_ftext(char ch)
7092 unsigned char uch = (unsigned char) ch;
7104 static int mailimf_ftext_parse(const char * message, size_t length,
7105 size_t * index, gchar * result)
7107 return mailimf_typed_text_parse(message, length, index, result, is_ftext);
7114 static int mailimf_envelope_field_parse(const char * message, size_t length,
7116 struct mailimf_field ** result)
7120 struct mailimf_orig_date * orig_date;
7121 struct mailimf_from * from;
7122 struct mailimf_sender * sender;
7123 struct mailimf_reply_to * reply_to;
7124 struct mailimf_to * to;
7125 struct mailimf_cc * cc;
7126 struct mailimf_bcc * bcc;
7127 struct mailimf_message_id * message_id;
7128 struct mailimf_in_reply_to * in_reply_to;
7129 struct mailimf_references * references;
7130 struct mailimf_subject * subject;
7131 struct mailimf_field * field;
7136 cur_token = * index;
7150 guessed_type = guess_header_type(message, length, cur_token);
7151 type = MAILIMF_FIELD_NONE;
7153 switch (guessed_type) {
7154 case MAILIMF_FIELD_ORIG_DATE:
7155 r = mailimf_orig_date_parse(message, length, &cur_token,
7157 if (r == MAILIMF_NO_ERROR)
7158 type = guessed_type;
7159 else if (r == MAILIMF_ERROR_PARSE) {
7167 case MAILIMF_FIELD_FROM:
7168 r = mailimf_from_parse(message, length, &cur_token,
7170 if (r == MAILIMF_NO_ERROR)
7171 type = guessed_type;
7172 else if (r == MAILIMF_ERROR_PARSE) {
7180 case MAILIMF_FIELD_SENDER:
7181 r = mailimf_sender_parse(message, length, &cur_token,
7183 if (r == MAILIMF_NO_ERROR)
7184 type = guessed_type;
7185 else if (r == MAILIMF_ERROR_PARSE) {
7193 case MAILIMF_FIELD_REPLY_TO:
7194 r = mailimf_reply_to_parse(message, length, &cur_token,
7196 if (r == MAILIMF_NO_ERROR)
7197 type = guessed_type;
7198 else if (r == MAILIMF_ERROR_PARSE) {
7206 case MAILIMF_FIELD_TO:
7207 r = mailimf_to_parse(message, length, &cur_token,
7209 if (r == MAILIMF_NO_ERROR)
7210 type = guessed_type;
7211 else if (r == MAILIMF_ERROR_PARSE) {
7219 case MAILIMF_FIELD_CC:
7220 r = mailimf_cc_parse(message, length, &cur_token,
7222 if (r == MAILIMF_NO_ERROR)
7223 type = guessed_type;
7224 else if (r == MAILIMF_ERROR_PARSE) {
7232 case MAILIMF_FIELD_BCC:
7233 r = mailimf_bcc_parse(message, length, &cur_token,
7235 if (r == MAILIMF_NO_ERROR)
7236 type = guessed_type;
7237 else if (r == MAILIMF_ERROR_PARSE) {
7245 case MAILIMF_FIELD_MESSAGE_ID:
7246 r = mailimf_message_id_parse(message, length, &cur_token,
7248 if (r == MAILIMF_NO_ERROR)
7249 type = guessed_type;
7250 else if (r == MAILIMF_ERROR_PARSE) {
7258 case MAILIMF_FIELD_IN_REPLY_TO:
7259 r = mailimf_in_reply_to_parse(message, length, &cur_token,
7261 if (r == MAILIMF_NO_ERROR)
7262 type = guessed_type;
7263 else if (r == MAILIMF_ERROR_PARSE) {
7271 case MAILIMF_FIELD_REFERENCES:
7272 r = mailimf_references_parse(message, length, &cur_token,
7274 if (r == MAILIMF_NO_ERROR)
7275 type = guessed_type;
7276 else if (r == MAILIMF_ERROR_PARSE) {
7284 case MAILIMF_FIELD_SUBJECT:
7285 r = mailimf_subject_parse(message, length, &cur_token,
7287 if (r == MAILIMF_NO_ERROR)
7288 type = guessed_type;
7289 else if (r == MAILIMF_ERROR_PARSE) {
7299 if (type == MAILIMF_FIELD_NONE) {
7300 res = MAILIMF_ERROR_PARSE;
7304 field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
7306 orig_date, from, sender, reply_to, to,
7307 cc, bcc, message_id, in_reply_to, references,
7308 subject, NULL, NULL, NULL);
7309 if (field == NULL) {
7310 res = MAILIMF_ERROR_MEMORY;
7315 * index = cur_token;
7317 return MAILIMF_NO_ERROR;
7320 if (orig_date != NULL)
7321 mailimf_orig_date_free(orig_date);
7323 mailimf_from_free(from);
7325 mailimf_sender_free(sender);
7326 if (reply_to != NULL)
7327 mailimf_reply_to_free(reply_to);
7329 mailimf_to_free(to);
7331 mailimf_cc_free(cc);
7333 mailimf_bcc_free(bcc);
7334 if (message_id != NULL)
7335 mailimf_message_id_free(message_id);
7336 if (in_reply_to != NULL)
7337 mailimf_in_reply_to_free(in_reply_to);
7338 if (references != NULL)
7339 mailimf_references_free(references);
7340 if (subject != NULL)
7341 mailimf_subject_free(subject);
7346 int mailimf_envelope_fields_parse(const char * message, size_t length,
7348 struct mailimf_fields ** result)
7352 struct mailimf_fields * fields;
7356 cur_token = * index;
7360 res = MAILIMF_ERROR_MEMORY;
7365 struct mailimf_field * elt;
7367 r = mailimf_envelope_field_parse(message, length, &cur_token, &elt);
7368 if (r == MAILIMF_NO_ERROR) {
7369 r = clist_append(list, elt);
7371 res = MAILIMF_ERROR_MEMORY;
7375 else if (r == MAILIMF_ERROR_PARSE) {
7376 r = mailimf_ignore_field_parse(message, length, &cur_token);
7377 if (r == MAILIMF_NO_ERROR) {
7380 else if (r == MAILIMF_ERROR_PARSE) {
7394 fields = mailimf_fields_new(list);
7395 if (fields == NULL) {
7396 res = MAILIMF_ERROR_MEMORY;
7401 * index = cur_token;
7403 return MAILIMF_NO_ERROR;
7407 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7416 mailimf_envelope_or_optional_field_parse(const char * message,
7419 struct mailimf_field ** result)
7423 struct mailimf_optional_field * optional_field;
7424 struct mailimf_field * field;
7426 r = mailimf_envelope_field_parse(message, length, index, result);
7427 if (r == MAILIMF_NO_ERROR)
7428 return MAILIMF_NO_ERROR;
7430 cur_token = * index;
7432 r = mailimf_optional_field_parse(message, length, &cur_token,
7434 if (r != MAILIMF_NO_ERROR)
7437 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL,
7442 NULL, NULL, NULL, NULL, NULL,
7443 NULL, NULL, NULL, optional_field);
7444 if (field == NULL) {
7445 mailimf_optional_field_free(optional_field);
7446 return MAILIMF_ERROR_MEMORY;
7450 * index = cur_token;
7452 return MAILIMF_NO_ERROR;
7457 mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
7459 struct mailimf_fields ** result)
7463 struct mailimf_fields * fields;
7467 cur_token = * index;
7471 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7473 (mailimf_struct_parser *)
7474 mailimf_envelope_or_optional_field_parse,
7475 (mailimf_struct_destructor *)
7476 mailimf_field_free);
7478 case MAILIMF_NO_ERROR:
7482 case MAILIMF_ERROR_PARSE:
7485 res = MAILIMF_ERROR_MEMORY;
7495 fields = mailimf_fields_new(list);
7496 if (fields == NULL) {
7497 res = MAILIMF_ERROR_MEMORY;
7502 * index = cur_token;
7504 return MAILIMF_NO_ERROR;
7508 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7518 mailimf_only_optional_field_parse(const char * message,
7521 struct mailimf_field ** result)
7525 struct mailimf_optional_field * optional_field;
7526 struct mailimf_field * field;
7528 cur_token = * index;
7530 r = mailimf_optional_field_parse(message, length, &cur_token,
7532 if (r != MAILIMF_NO_ERROR)
7535 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL,
7536 NULL, NULL, NULL, NULL, NULL,
7537 NULL, NULL, NULL, NULL, NULL,
7538 NULL, NULL, NULL, NULL, NULL,
7539 NULL, NULL, NULL, optional_field);
7540 if (field == NULL) {
7541 mailimf_optional_field_free(optional_field);
7542 return MAILIMF_ERROR_MEMORY;
7546 * index = cur_token;
7548 return MAILIMF_NO_ERROR;
7553 mailimf_optional_fields_parse(const char * message, size_t length,
7555 struct mailimf_fields ** result)
7559 struct mailimf_fields * fields;
7563 cur_token = * index;
7567 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7569 (mailimf_struct_parser *)
7570 mailimf_only_optional_field_parse,
7571 (mailimf_struct_destructor *)
7572 mailimf_field_free);
7574 case MAILIMF_NO_ERROR:
7578 case MAILIMF_ERROR_PARSE:
7581 res = MAILIMF_ERROR_MEMORY;
7591 fields = mailimf_fields_new(list);
7592 if (fields == NULL) {
7593 res = MAILIMF_ERROR_MEMORY;
7598 * index = cur_token;
7600 return MAILIMF_NO_ERROR;
7604 clist_foreach(list, (clist_func) mailimf_field_free, NULL);