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
42 A message-originating SMTP system SHOULD NOT send a message that
43 already contains a Return-path header. SMTP servers performing a
44 relay function MUST NOT inspect the message data, and especially not
45 to the extent needed to determine if Return-path headers are present.
46 SMTP servers making final delivery MAY remove Return-path headers
47 before adding their own.
51 #include <mmapstring.h>
69 static inline int is_dtext(char ch);
71 static int mailimf_quoted_pair_parse(const char * message, size_t length,
72 size_t * index, char * result);
74 static int mailimf_ccontent_parse(const char * message, size_t length,
78 mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
81 static inline int mailimf_comment_parse(const char * message, size_t length,
84 static int mailimf_qcontent_parse(const char * message, size_t length,
85 size_t * index, char * ch);
87 static int mailimf_phrase_parse(const char * message, size_t length,
88 size_t * index, char ** result);
90 static int mailimf_unstructured_parse(const char * message, size_t length,
91 size_t * index, char ** result);
93 static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
96 static int mailimf_day_of_week_parse(const char * message, size_t length,
97 size_t * index, int * result);
99 static int mailimf_day_name_parse(const char * message, size_t length,
100 size_t * index, int * result);
102 static int mailimf_date_parse(const char * message, size_t length,
104 int * pday, int * pmonth, int * pyear);
106 static int mailimf_year_parse(const char * message, size_t length,
107 size_t * index, int * result);
109 static int mailimf_month_parse(const char * message, size_t length,
110 size_t * index, int * result);
112 static int mailimf_month_name_parse(const char * message, size_t length,
113 size_t * index, int * result);
115 static int mailimf_day_parse(const char * message, size_t length,
116 size_t * index, int * result);
118 static int mailimf_time_parse(const char * message, size_t length,
120 int * phour, int * pmin,
123 static int mailimf_time_of_day_parse(const char * message, size_t length,
125 int * phour, int * pmin,
128 static int mailimf_hour_parse(const char * message, size_t length,
129 size_t * index, int * result);
131 static int mailimf_minute_parse(const char * message, size_t length,
132 size_t * index, int * result);
134 static int mailimf_second_parse(const char * message, size_t length,
135 size_t * index, int * result);
137 static int mailimf_zone_parse(const char * message, size_t length,
138 size_t * index, int * result);
140 static int mailimf_name_addr_parse(const char * message, size_t length,
142 char ** pdisplay_name,
143 char ** pangle_addr);
145 static int mailimf_angle_addr_parse(const char * message, size_t length,
146 size_t * index, char ** result);
148 static int mailimf_group_parse(const char * message, size_t length,
150 struct mailimf_group ** result);
152 static int mailimf_display_name_parse(const char * message, size_t length,
153 size_t * index, char ** result);
155 static int mailimf_addr_spec_parse(const char * message, size_t length,
160 static int mailimf_local_part_parse(const char * message, size_t length,
164 static int mailimf_domain_parse(const char * message, size_t length,
170 static int mailimf_domain_literal_parse(const char * message, size_t length,
171 size_t * index, char ** result);
175 static int mailimf_dcontent_parse(const char * message, size_t length,
176 size_t * index, char * result);
180 mailimf_orig_date_parse(const char * message, size_t length,
181 size_t * index, struct mailimf_orig_date ** result);
184 mailimf_from_parse(const char * message, size_t length,
185 size_t * index, struct mailimf_from ** result);
188 mailimf_sender_parse(const char * message, size_t length,
189 size_t * index, struct mailimf_sender ** result);
192 mailimf_reply_to_parse(const char * message, size_t length,
193 size_t * index, struct mailimf_reply_to ** result);
196 mailimf_to_parse(const char * message, size_t length,
197 size_t * index, struct mailimf_to ** result);
200 mailimf_cc_parse(const char * message, size_t length,
201 size_t * index, struct mailimf_cc ** result);
204 mailimf_bcc_parse(const char * message, size_t length,
205 size_t * index, struct mailimf_bcc ** result);
207 static int mailimf_message_id_parse(const char * message, size_t length,
209 struct mailimf_message_id ** result);
212 mailimf_in_reply_to_parse(const char * message, size_t length,
214 struct mailimf_in_reply_to ** result);
217 static int mailimf_references_parse(const char * message, size_t length,
219 struct mailimf_references **
223 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
228 static int mailimf_id_left_parse(const char * message, size_t length,
229 size_t * index, char ** result);
231 static int mailimf_id_right_parse(const char * message, size_t length,
232 size_t * index, char ** result);
236 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
237 size_t * index, char ** result);
239 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
240 size_t * index, char ** result);
243 static int mailimf_subject_parse(const char * message, size_t length,
245 struct mailimf_subject ** result);
247 static int mailimf_comments_parse(const char * message, size_t length,
249 struct mailimf_comments ** result);
251 static int mailimf_keywords_parse(const char * message, size_t length,
253 struct mailimf_keywords ** result);
256 mailimf_resent_date_parse(const char * message, size_t length,
257 size_t * index, struct mailimf_orig_date ** result);
260 mailimf_resent_from_parse(const char * message, size_t length,
261 size_t * index, struct mailimf_from ** result);
264 mailimf_resent_sender_parse(const char * message, size_t length,
265 size_t * index, struct mailimf_sender ** result);
268 mailimf_resent_to_parse(const char * message, size_t length,
269 size_t * index, struct mailimf_to ** result);
272 mailimf_resent_cc_parse(const char * message, size_t length,
273 size_t * index, struct mailimf_cc ** result);
276 mailimf_resent_bcc_parse(const char * message, size_t length,
277 size_t * index, struct mailimf_bcc ** result);
280 mailimf_resent_msg_id_parse(const char * message, size_t length,
282 struct mailimf_message_id ** result);
284 static int mailimf_return_parse(const char * message, size_t length,
286 struct mailimf_return ** result);
289 mailimf_path_parse(const char * message, size_t length,
290 size_t * index, struct mailimf_path ** result);
293 mailimf_optional_field_parse(const char * message, size_t length,
295 struct mailimf_optional_field ** result);
297 static int mailimf_field_name_parse(const char * message, size_t length,
298 size_t * index, char ** result);
324 /* *************************************************************** */
326 static inline int is_digit(char ch)
328 return (ch >= '0') && (ch <= '9');
331 static int mailimf_digit_parse(const char * message, size_t length,
332 size_t * index, int * result)
338 if (cur_token >= length)
339 return MAILIMF_ERROR_PARSE;
341 if (is_digit(message[cur_token])) {
342 * result = message[cur_token] - '0';
345 return MAILIMF_NO_ERROR;
348 return MAILIMF_ERROR_PARSE;
352 mailimf_number_parse(const char * message, size_t length,
353 size_t * index, uint32_t * result)
366 r = mailimf_digit_parse(message, length, &cur_token, &digit);
367 if (r != MAILIMF_NO_ERROR) {
368 if (r == MAILIMF_ERROR_PARSE)
379 return MAILIMF_ERROR_PARSE;
384 return MAILIMF_NO_ERROR;
387 int mailimf_char_parse(const char * message, size_t length,
388 size_t * index, char token)
394 if (cur_token >= length)
395 return MAILIMF_ERROR_PARSE;
397 if (message[cur_token] == token) {
400 return MAILIMF_NO_ERROR;
403 return MAILIMF_ERROR_PARSE;
406 int mailimf_unstrict_char_parse(const char * message, size_t length,
407 size_t * index, char token)
414 r = mailimf_cfws_parse(message, length, &cur_token);
415 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
418 r = mailimf_char_parse(message, length, &cur_token, token);
419 if (r != MAILIMF_NO_ERROR)
424 return MAILIMF_NO_ERROR;
428 mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
429 size_t * index, char * token,
436 if (cur_token + token_length - 1 >= length)
437 return MAILIMF_ERROR_PARSE;
439 if (strncasecmp(message + cur_token, token, token_length) == 0) {
440 cur_token += token_length;
442 return MAILIMF_NO_ERROR;
445 return MAILIMF_ERROR_PARSE;
448 static int mailimf_oparenth_parse(const char * message, size_t length,
451 return mailimf_char_parse(message, length, index, '(');
454 static int mailimf_cparenth_parse(const char * message, size_t length,
457 return mailimf_char_parse(message, length, index, ')');
460 static int mailimf_comma_parse(const char * message, size_t length,
463 return mailimf_unstrict_char_parse(message, length, index, ',');
466 static int mailimf_dquote_parse(const char * message, size_t length,
469 return mailimf_char_parse(message, length, index, '\"');
472 static int mailimf_colon_parse(const char * message, size_t length,
475 return mailimf_unstrict_char_parse(message, length, index, ':');
478 static int mailimf_semi_colon_parse(const char * message, size_t length,
481 return mailimf_unstrict_char_parse(message, length, index, ';');
484 static int mailimf_plus_parse(const char * message, size_t length,
487 return mailimf_unstrict_char_parse(message, length, index, '+');
490 static int mailimf_minus_parse(const char * message, size_t length,
493 return mailimf_unstrict_char_parse(message, length, index, '-');
496 static int mailimf_lower_parse(const char * message, size_t length,
499 return mailimf_unstrict_char_parse(message, length, index, '<');
502 static int mailimf_greater_parse(const char * message, size_t length,
505 return mailimf_unstrict_char_parse(message, length, index, '>');
509 static int mailimf_obracket_parse(const char * message, size_t length,
512 return mailimf_unstrict_char_parse(message, length, index, '[');
515 static int mailimf_cbracket_parse(const char * message, size_t length,
518 return mailimf_unstrict_char_parse(message, length, index, ']');
522 static int mailimf_at_sign_parse(const char * message, size_t length,
525 return mailimf_unstrict_char_parse(message, length, index, '@');
528 static int mailimf_point_parse(const char * message, size_t length,
531 return mailimf_unstrict_char_parse(message, length, index, '.');
535 mailimf_custom_string_parse(const char * message, size_t length,
536 size_t * index, char ** result,
537 int (* is_custom_char)(char))
548 return MAILIMF_ERROR_PARSE;
550 while (is_custom_char(message[end])) {
558 gstr = strndup(message + begin, end - begin);
560 gstr = malloc(end - begin + 1);
562 return MAILIMF_ERROR_MEMORY;
563 strncpy(gstr, message + begin, end - begin);
564 gstr[end - begin] = '\0';
568 return MAILIMF_NO_ERROR;
571 return MAILIMF_ERROR_PARSE;
580 typedef int mailimf_struct_parser(const char * message, size_t length,
581 size_t * index, void * result);
583 typedef int mailimf_struct_destructor(void * result);
587 mailimf_struct_multiple_parse(const char * message, size_t length,
588 size_t * index, clist ** result,
589 mailimf_struct_parser * parser,
590 mailimf_struct_destructor * destructor)
600 r = parser(message, length, &cur_token, &value);
601 if (r != MAILIMF_NO_ERROR) {
606 struct_list = clist_new();
607 if (struct_list == NULL) {
609 res = MAILIMF_ERROR_MEMORY;
613 r = clist_append(struct_list, value);
616 res = MAILIMF_ERROR_MEMORY;
621 r = parser(message, length, &cur_token, &value);
622 if (r != MAILIMF_NO_ERROR) {
623 if (r == MAILIMF_ERROR_PARSE)
630 r = clist_append(struct_list, value);
632 (* destructor)(value);
633 res = MAILIMF_ERROR_MEMORY;
638 * result = struct_list;
641 return MAILIMF_NO_ERROR;
644 clist_foreach(struct_list, (clist_func) destructor, NULL);
645 clist_free(struct_list);
653 mailimf_struct_list_parse(const char * message, size_t length,
654 size_t * index, clist ** result,
656 mailimf_struct_parser * parser,
657 mailimf_struct_destructor * destructor)
668 r = parser(message, length, &cur_token, &value);
669 if (r != MAILIMF_NO_ERROR) {
674 struct_list = clist_new();
675 if (struct_list == NULL) {
677 res = MAILIMF_ERROR_MEMORY;
681 r = clist_append(struct_list, value);
684 res = MAILIMF_ERROR_MEMORY;
688 final_token = cur_token;
691 r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol);
692 if (r != MAILIMF_NO_ERROR) {
693 if (r == MAILIMF_ERROR_PARSE)
701 r = parser(message, length, &cur_token, &value);
702 if (r != MAILIMF_NO_ERROR) {
703 if (r == MAILIMF_ERROR_PARSE)
711 r = clist_append(struct_list, value);
714 res = MAILIMF_ERROR_MEMORY;
718 final_token = cur_token;
721 * result = struct_list;
722 * index = final_token;
724 return MAILIMF_NO_ERROR;
727 clist_foreach(struct_list, (clist_func) destructor, NULL);
728 clist_free(struct_list);
733 static inline int mailimf_wsp_parse(const char * message, size_t length,
740 if (cur_token >= length)
741 return MAILIMF_ERROR_PARSE;
743 if ((message[cur_token] != ' ') && (message[cur_token] != '\t'))
744 return MAILIMF_ERROR_PARSE;
749 return MAILIMF_NO_ERROR;
753 int mailimf_crlf_parse(const char * message, size_t length, size_t * index)
760 r = mailimf_char_parse(message, length, &cur_token, '\r');
761 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
764 r = mailimf_char_parse(message, length, &cur_token, '\n');
765 if (r != MAILIMF_NO_ERROR)
769 return MAILIMF_NO_ERROR;
772 static int mailimf_unstrict_crlf_parse(const char * message,
773 size_t length, size_t * index)
780 mailimf_cfws_parse(message, length, &cur_token);
782 r = mailimf_char_parse(message, length, &cur_token, '\r');
783 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
786 r = mailimf_char_parse(message, length, &cur_token, '\n');
787 if (r != MAILIMF_NO_ERROR)
791 return MAILIMF_NO_ERROR;
794 /* ************************************************************************ */
798 /* RFC 2822 grammar */
801 NO-WS-CTL = %d1-8 / ; US-ASCII control characters
802 %d11 / ; that do not include the
803 %d12 / ; carriage return, line feed,
804 %d14-31 / ; and white space characters
808 static inline int is_no_ws_ctl(char ch)
810 if ((ch == 9) || (ch == 10) || (ch == 13))
816 return (ch >= 1) && (ch <= 31);
820 text = %d1-9 / ; Characters excluding CR and LF
828 specials = "(" / ")" / ; Special characters used in
829 "<" / ">" / ; other parts of the syntax
838 quoted-pair = ("\" text) / obs-qp
841 static inline int mailimf_quoted_pair_parse(const char * message, size_t length,
842 size_t * index, char * result)
848 if (cur_token + 1 >= length)
849 return MAILIMF_ERROR_PARSE;
851 if (message[cur_token] != '\\')
852 return MAILIMF_ERROR_PARSE;
855 * result = message[cur_token];
859 return MAILIMF_NO_ERROR;
863 FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
867 int mailimf_fws_parse(const char * message, size_t length, size_t * index)
880 r = mailimf_wsp_parse(message, length, &cur_token);
881 if (r != MAILIMF_NO_ERROR) {
882 if (r == MAILIMF_ERROR_PARSE)
889 final_token = cur_token;
891 r = mailimf_crlf_parse(message, length, &cur_token);
893 case MAILIMF_NO_ERROR:
896 case MAILIMF_ERROR_PARSE:
906 r = mailimf_wsp_parse(message, length, &cur_token);
907 if (r != MAILIMF_NO_ERROR) {
908 if (r == MAILIMF_ERROR_PARSE)
917 if ((!fws_1) && (!fws_3))
918 return MAILIMF_ERROR_PARSE;
921 cur_token = final_token;
925 return MAILIMF_NO_ERROR;
930 ctext = NO-WS-CTL / ; Non white space controls
932 %d33-39 / ; The rest of the US-ASCII
933 %d42-91 / ; characters not including "(",
934 %d93-126 ; ")", or "\"
937 static inline int is_ctext(char ch)
939 unsigned char uch = (unsigned char) ch;
941 if (is_no_ws_ctl(ch))
947 if ((uch == 40) || (uch == 41))
960 ccontent = ctext / quoted-pair / comment
963 static inline int mailimf_ccontent_parse(const char * message, size_t length,
972 if (cur_token >= length)
973 return MAILIMF_ERROR_PARSE;
975 if (is_ctext(message[cur_token])) {
979 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
981 if (r == MAILIMF_ERROR_PARSE)
982 r = mailimf_comment_parse(message, length, &cur_token);
984 if (r == MAILIMF_ERROR_PARSE)
990 return MAILIMF_NO_ERROR;
998 mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
1004 cur_token = * index;
1006 r = mailimf_fws_parse(message, length, &cur_token);
1007 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1010 r = mailimf_ccontent_parse(message, length, &cur_token);
1011 if (r != MAILIMF_NO_ERROR)
1014 * index = cur_token;
1016 return MAILIMF_NO_ERROR;
1020 comment = "(" *([FWS] ccontent) [FWS] ")"
1023 static inline int mailimf_comment_parse(const char * message, size_t length,
1029 cur_token = * index;
1031 r = mailimf_oparenth_parse(message, length, &cur_token);
1032 if (r != MAILIMF_NO_ERROR)
1036 r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token);
1037 if (r != MAILIMF_NO_ERROR) {
1038 if (r == MAILIMF_ERROR_PARSE)
1045 r = mailimf_fws_parse(message, length, &cur_token);
1046 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1049 r = mailimf_cparenth_parse(message, length, &cur_token);
1050 if (r != MAILIMF_NO_ERROR)
1053 * index = cur_token;
1055 return MAILIMF_NO_ERROR;
1062 static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length,
1068 cur_token = * index;
1070 r = mailimf_fws_parse(message, length, &cur_token);
1071 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1074 r = mailimf_comment_parse(message, length, &cur_token);
1075 if (r != MAILIMF_NO_ERROR)
1078 * index = cur_token;
1080 return MAILIMF_NO_ERROR;
1084 CFWS = *([FWS] comment) (([FWS] comment) / FWS)
1087 int mailimf_cfws_parse(const char * message, size_t length,
1094 cur_token = * index;
1096 has_comment = FALSE;
1098 r = mailimf_cfws_fws_comment_parse(message, length, &cur_token);
1099 if (r != MAILIMF_NO_ERROR) {
1100 if (r == MAILIMF_ERROR_PARSE)
1109 r = mailimf_fws_parse(message, length, &cur_token);
1110 if (r != MAILIMF_NO_ERROR)
1114 * index = cur_token;
1116 return MAILIMF_NO_ERROR;
1120 atext = ALPHA / DIGIT / ; Any character except controls,
1121 "!" / "#" / ; SP, and specials.
1122 "$" / "%" / ; Used for atoms
1133 static inline int is_atext(char ch)
1160 atom = [CFWS] 1*atext [CFWS]
1163 int mailimf_atom_parse(const char * message, size_t length,
1164 size_t * index, char ** result)
1172 cur_token = * index;
1174 r = mailimf_cfws_parse(message, length, &cur_token);
1175 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1181 if (end >= length) {
1182 res = MAILIMF_ERROR_PARSE;
1186 while (is_atext(message[end])) {
1191 if (end == cur_token) {
1192 res = MAILIMF_ERROR_PARSE;
1196 atom = malloc(end - cur_token + 1);
1198 res = MAILIMF_ERROR_MEMORY;
1201 strncpy(atom, message + cur_token, end - cur_token);
1202 atom[end - cur_token] = '\0';
1206 * index = cur_token;
1209 return MAILIMF_NO_ERROR;
1215 int mailimf_fws_atom_parse(const char * message, size_t length,
1216 size_t * index, char ** result)
1224 cur_token = * index;
1226 r = mailimf_fws_parse(message, length, &cur_token);
1227 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1233 if (end >= length) {
1234 res = MAILIMF_ERROR_PARSE;
1238 while (is_atext(message[end])) {
1243 if (end == cur_token) {
1244 res = MAILIMF_ERROR_PARSE;
1248 atom = malloc(end - cur_token + 1);
1250 res = MAILIMF_ERROR_MEMORY;
1253 strncpy(atom, message + cur_token, end - cur_token);
1254 atom[end - cur_token] = '\0';
1258 * index = cur_token;
1261 return MAILIMF_NO_ERROR;
1268 dot-atom = [CFWS] dot-atom-text [CFWS]
1272 static int mailimf_dot_atom_parse(const char * message, size_t length,
1273 size_t * index, char ** result)
1275 return mailimf_atom_parse(message, length, index, result);
1280 dot-atom-text = 1*atext *("." 1*atext)
1285 mailimf_dot_atom_text_parse(const char * message, size_t length,
1286 size_t * index, char ** result)
1288 return mailimf_atom_parse(message, length, index, result);
1293 qtext = NO-WS-CTL / ; Non white space controls
1295 %d33 / ; The rest of the US-ASCII
1296 %d35-91 / ; characters not including "\"
1297 %d93-126 ; or the quote character
1300 static inline int is_qtext(char ch)
1302 unsigned char uch = (unsigned char) ch;
1304 if (is_no_ws_ctl(ch))
1323 qcontent = qtext / quoted-pair
1326 static int mailimf_qcontent_parse(const char * message, size_t length,
1327 size_t * index, char * result)
1333 cur_token = * index;
1335 if (cur_token >= length)
1336 return MAILIMF_ERROR_PARSE;
1338 if (is_qtext(message[cur_token])) {
1339 ch = message[cur_token];
1343 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
1345 if (r != MAILIMF_NO_ERROR)
1350 * index = cur_token;
1352 return MAILIMF_NO_ERROR;
1356 quoted-string = [CFWS]
1357 DQUOTE *([FWS] qcontent) [FWS] DQUOTE
1361 int mailimf_quoted_string_parse(const char * message, size_t length,
1362 size_t * index, char ** result)
1371 cur_token = * index;
1373 r = mailimf_cfws_parse(message, length, &cur_token);
1374 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1379 r = mailimf_dquote_parse(message, length, &cur_token);
1380 if (r != MAILIMF_NO_ERROR) {
1385 gstr = mmap_string_new("");
1387 res = MAILIMF_ERROR_MEMORY;
1392 if (mmap_string_append_c(gstr, '\"') == NULL) {
1393 res = MAILIMF_ERROR_MEMORY;
1399 r = mailimf_fws_parse(message, length, &cur_token);
1400 if (r == MAILIMF_NO_ERROR) {
1401 if (mmap_string_append_c(gstr, ' ') == NULL) {
1402 res = MAILIMF_ERROR_MEMORY;
1406 else if (r != MAILIMF_ERROR_PARSE) {
1411 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1412 if (r == MAILIMF_NO_ERROR) {
1413 if (mmap_string_append_c(gstr, ch) == NULL) {
1414 res = MAILIMF_ERROR_MEMORY;
1418 else if (r == MAILIMF_ERROR_PARSE)
1426 r = mailimf_dquote_parse(message, length, &cur_token);
1427 if (r != MAILIMF_NO_ERROR) {
1433 if (mmap_string_append_c(gstr, '\"') == NULL) {
1434 res = MAILIMF_ERROR_MEMORY;
1439 str = strdup(gstr->str);
1441 res = MAILIMF_ERROR_MEMORY;
1444 mmap_string_free(gstr);
1446 * index = cur_token;
1449 return MAILIMF_NO_ERROR;
1452 mmap_string_free(gstr);
1457 int mailimf_fws_quoted_string_parse(const char * message, size_t length,
1458 size_t * index, char ** result)
1467 cur_token = * index;
1469 r = mailimf_fws_parse(message, length, &cur_token);
1470 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1475 r = mailimf_dquote_parse(message, length, &cur_token);
1476 if (r != MAILIMF_NO_ERROR) {
1481 gstr = mmap_string_new("");
1483 res = MAILIMF_ERROR_MEMORY;
1488 if (mmap_string_append_c(gstr, '\"') == NULL) {
1489 res = MAILIMF_ERROR_MEMORY;
1495 r = mailimf_fws_parse(message, length, &cur_token);
1496 if (r == MAILIMF_NO_ERROR) {
1497 if (mmap_string_append_c(gstr, ' ') == NULL) {
1498 res = MAILIMF_ERROR_MEMORY;
1502 else if (r != MAILIMF_ERROR_PARSE) {
1507 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1508 if (r == MAILIMF_NO_ERROR) {
1509 if (mmap_string_append_c(gstr, ch) == NULL) {
1510 res = MAILIMF_ERROR_MEMORY;
1514 else if (r == MAILIMF_ERROR_PARSE)
1522 r = mailimf_dquote_parse(message, length, &cur_token);
1523 if (r != MAILIMF_NO_ERROR) {
1529 if (mmap_string_append_c(gstr, '\"') == NULL) {
1530 res = MAILIMF_ERROR_MEMORY;
1535 str = strdup(gstr->str);
1537 res = MAILIMF_ERROR_MEMORY;
1540 mmap_string_free(gstr);
1542 * index = cur_token;
1545 return MAILIMF_NO_ERROR;
1548 mmap_string_free(gstr);
1554 word = atom / quoted-string
1557 int mailimf_word_parse(const char * message, size_t length,
1558 size_t * index, char ** result)
1564 cur_token = * index;
1566 r = mailimf_atom_parse(message, length, &cur_token, &word);
1568 if (r == MAILIMF_ERROR_PARSE)
1569 r = mailimf_quoted_string_parse(message, length, &cur_token, &word);
1571 if (r != MAILIMF_NO_ERROR)
1575 * index = cur_token;
1577 return MAILIMF_NO_ERROR;
1580 int mailimf_fws_word_parse(const char * message, size_t length,
1581 size_t * index, char ** result)
1587 cur_token = * index;
1589 r = mailimf_fws_atom_parse(message, length, &cur_token, &word);
1591 if (r == MAILIMF_ERROR_PARSE)
1592 r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word);
1594 if (r != MAILIMF_NO_ERROR)
1598 * index = cur_token;
1600 return MAILIMF_NO_ERROR;
1604 phrase = 1*word / obs-phrase
1607 static int mailimf_phrase_parse(const char * message, size_t length,
1608 size_t * index, char ** result)
1610 MMAPString * gphrase;
1618 cur_token = * index;
1620 gphrase = mmap_string_new("");
1621 if (gphrase == NULL) {
1622 res = MAILIMF_ERROR_MEMORY;
1629 r = mailimf_fws_word_parse(message, length, &cur_token, &word);
1630 if (r == MAILIMF_NO_ERROR) {
1632 if (mmap_string_append_c(gphrase, ' ') == NULL) {
1633 mailimf_word_free(word);
1634 res = MAILIMF_ERROR_MEMORY;
1638 if (mmap_string_append(gphrase, word) == NULL) {
1639 mailimf_word_free(word);
1640 res = MAILIMF_ERROR_MEMORY;
1643 mailimf_word_free(word);
1646 else if (r == MAILIMF_ERROR_PARSE)
1655 res = MAILIMF_ERROR_PARSE;
1659 str = strdup(gphrase->str);
1661 res = MAILIMF_ERROR_MEMORY;
1664 mmap_string_free(gphrase);
1667 * index = cur_token;
1669 return MAILIMF_NO_ERROR;
1672 mmap_string_free(gphrase);
1678 utext = NO-WS-CTL / ; Non white space controls
1679 %d33-126 / ; The rest of US-ASCII
1693 static int mailimf_unstructured_parse(const char * message, size_t length,
1694 size_t * index, char ** result)
1702 cur_token = * index;
1708 r = mailimf_wsp_parse(message, length, &cur_token);
1709 if (r == MAILIMF_NO_ERROR) {
1712 else if (r == MAILIMF_ERROR_PARSE)
1719 state = UNSTRUCTURED_START;
1721 terminal = cur_token;
1723 while (state != UNSTRUCTURED_OUT) {
1726 case UNSTRUCTURED_START:
1727 if (cur_token >= length)
1728 return MAILIMF_ERROR_PARSE;
1730 terminal = cur_token;
1731 switch(message[cur_token]) {
1733 state = UNSTRUCTURED_CR;
1736 state = UNSTRUCTURED_LF;
1739 state = UNSTRUCTURED_START;
1743 case UNSTRUCTURED_CR:
1744 if (cur_token >= length)
1745 return MAILIMF_ERROR_PARSE;
1747 switch(message[cur_token]) {
1749 state = UNSTRUCTURED_LF;
1752 state = UNSTRUCTURED_START;
1757 case UNSTRUCTURED_LF:
1758 if (cur_token >= length) {
1759 state = UNSTRUCTURED_OUT;
1763 switch(message[cur_token]) {
1766 state = UNSTRUCTURED_WSP;
1769 state = UNSTRUCTURED_OUT;
1773 case UNSTRUCTURED_WSP:
1774 if (cur_token >= length)
1775 return MAILIMF_ERROR_PARSE;
1777 switch(message[cur_token]) {
1779 state = UNSTRUCTURED_CR;
1782 state = UNSTRUCTURED_LF;
1785 state = UNSTRUCTURED_START;
1794 str = malloc(terminal - begin + 1);
1796 return MAILIMF_ERROR_MEMORY;
1797 strncpy(str, message + begin, terminal - begin);
1798 str[terminal - begin] = '\0';
1803 return MAILIMF_NO_ERROR;
1807 static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
1814 cur_token = * index;
1816 state = UNSTRUCTURED_START;
1817 terminal = cur_token;
1819 while (state != UNSTRUCTURED_OUT) {
1822 case UNSTRUCTURED_START:
1823 if (cur_token >= length)
1824 return MAILIMF_ERROR_PARSE;
1825 terminal = cur_token;
1826 switch(message[cur_token]) {
1828 state = UNSTRUCTURED_CR;
1831 state = UNSTRUCTURED_LF;
1834 state = UNSTRUCTURED_START;
1838 case UNSTRUCTURED_CR:
1839 if (cur_token >= length)
1840 return MAILIMF_ERROR_PARSE;
1841 switch(message[cur_token]) {
1843 state = UNSTRUCTURED_LF;
1846 state = UNSTRUCTURED_START;
1850 case UNSTRUCTURED_LF:
1851 if (cur_token >= length) {
1852 state = UNSTRUCTURED_OUT;
1855 switch(message[cur_token]) {
1858 state = UNSTRUCTURED_WSP;
1861 state = UNSTRUCTURED_OUT;
1865 case UNSTRUCTURED_WSP:
1866 if (cur_token >= length)
1867 return MAILIMF_ERROR_PARSE;
1868 switch(message[cur_token]) {
1870 state = UNSTRUCTURED_CR;
1873 state = UNSTRUCTURED_LF;
1876 state = UNSTRUCTURED_START;
1887 return MAILIMF_NO_ERROR;
1891 int mailimf_ignore_field_parse(const char * message, size_t length,
1900 cur_token = * index;
1902 terminal = cur_token;
1903 state = UNSTRUCTURED_START;
1905 /* check if this is not a beginning CRLF */
1907 if (cur_token >= length)
1908 return MAILIMF_ERROR_PARSE;
1910 switch (message[cur_token]) {
1912 return MAILIMF_ERROR_PARSE;
1914 return MAILIMF_ERROR_PARSE;
1917 while (state != UNSTRUCTURED_OUT) {
1920 case UNSTRUCTURED_START:
1921 if (cur_token >= length)
1922 return MAILIMF_ERROR_PARSE;
1924 switch(message[cur_token]) {
1926 state = UNSTRUCTURED_CR;
1929 state = UNSTRUCTURED_LF;
1933 state = UNSTRUCTURED_START;
1936 state = UNSTRUCTURED_START;
1940 case UNSTRUCTURED_CR:
1941 if (cur_token >= length)
1942 return MAILIMF_ERROR_PARSE;
1944 switch(message[cur_token]) {
1946 state = UNSTRUCTURED_LF;
1950 state = UNSTRUCTURED_START;
1953 state = UNSTRUCTURED_START;
1957 case UNSTRUCTURED_LF:
1958 if (cur_token >= length) {
1959 terminal = cur_token;
1960 state = UNSTRUCTURED_OUT;
1964 switch(message[cur_token]) {
1967 state = UNSTRUCTURED_WSP;
1970 terminal = cur_token;
1971 state = UNSTRUCTURED_OUT;
1975 case UNSTRUCTURED_WSP:
1976 if (cur_token >= length)
1977 return MAILIMF_ERROR_PARSE;
1979 switch(message[cur_token]) {
1981 state = UNSTRUCTURED_CR;
1984 state = UNSTRUCTURED_LF;
1988 state = UNSTRUCTURED_START;
1991 state = UNSTRUCTURED_START;
2001 return MAILIMF_ERROR_PARSE;
2005 return MAILIMF_NO_ERROR;
2010 date-time = [ day-of-week "," ] date FWS time [CFWS]
2013 int mailimf_date_time_parse(const char * message, size_t length,
2015 struct mailimf_date_time ** result)
2019 struct mailimf_date_time * date_time;
2029 cur_token = * index;
2032 r = mailimf_day_of_week_parse(message, length, &cur_token, &day_of_week);
2033 if (r == MAILIMF_NO_ERROR) {
2034 r = mailimf_comma_parse(message, length, &cur_token);
2035 if (r != MAILIMF_NO_ERROR)
2038 else if (r != MAILIMF_ERROR_PARSE)
2041 r = mailimf_date_parse(message, length, &cur_token, &day, &month, &year);
2042 if (r != MAILIMF_NO_ERROR)
2045 r = mailimf_fws_parse(message, length, &cur_token);
2046 if (r != MAILIMF_NO_ERROR)
2049 r = mailimf_time_parse(message, length, &cur_token,
2050 &hour, &min, &sec, &zone);
2051 if (r != MAILIMF_NO_ERROR)
2054 date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone);
2055 if (date_time == NULL)
2056 return MAILIMF_ERROR_MEMORY;
2058 * index = cur_token;
2059 * result = date_time;
2061 return MAILIMF_NO_ERROR;
2065 day-of-week = ([FWS] day-name) / obs-day-of-week
2068 static int mailimf_day_of_week_parse(const char * message, size_t length,
2069 size_t * index, int * result)
2075 cur_token = * index;
2077 r = mailimf_cfws_parse(message, length, &cur_token);
2078 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2081 r = mailimf_day_name_parse(message, length, &cur_token, &day_of_week);
2082 if (r != MAILIMF_NO_ERROR)
2085 * index = cur_token;
2086 * result = day_of_week;
2088 return MAILIMF_NO_ERROR;
2092 day-name = "Mon" / "Tue" / "Wed" / "Thu" /
2093 "Fri" / "Sat" / "Sun"
2096 struct mailimf_token_value {
2101 static struct mailimf_token_value day_names[] = {
2117 static int guess_day_name(const char * message, size_t length, size_t index)
2121 state = DAY_NAME_START;
2125 if (index >= length)
2129 case DAY_NAME_START:
2130 switch((char) toupper((unsigned char) message[index])) {
2134 case 'T': /* Tue Thu */
2141 case 'S': /* Sat Sun */
2149 switch((char) toupper((unsigned char) message[index])) {
2159 switch((char) toupper((unsigned char) message[index])) {
2174 static int mailimf_day_name_parse(const char * message, size_t length,
2175 size_t * index, int * result)
2182 cur_token = * index;
2184 guessed_day = guess_day_name(message, length, cur_token);
2185 if (guessed_day == -1)
2186 return MAILIMF_ERROR_PARSE;
2188 r = mailimf_token_case_insensitive_parse(message, length,
2190 day_names[guessed_day - 1].str);
2191 if (r != MAILIMF_NO_ERROR)
2194 day_of_week = guessed_day;
2196 * result = day_of_week;
2197 * index = cur_token;
2199 return MAILIMF_NO_ERROR;
2203 date = day month year
2206 static int mailimf_date_parse(const char * message, size_t length,
2208 int * pday, int * pmonth, int * pyear)
2216 cur_token = * index;
2218 r = mailimf_day_parse(message, length, &cur_token, &day);
2219 if (r != MAILIMF_NO_ERROR)
2222 r = mailimf_month_parse(message, length, &cur_token, &month);
2223 if (r != MAILIMF_NO_ERROR)
2226 r = mailimf_year_parse(message, length, &cur_token, &year);
2227 if (r != MAILIMF_NO_ERROR)
2234 * index = cur_token;
2236 return MAILIMF_NO_ERROR;
2240 year = 4*DIGIT / obs-year
2243 static int mailimf_year_parse(const char * message, size_t length,
2244 size_t * index, int * result)
2250 cur_token = * index;
2252 r = mailimf_cfws_parse(message, length, &cur_token);
2253 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2256 r = mailimf_number_parse(message, length, &cur_token, &number);
2257 if (r != MAILIMF_NO_ERROR)
2260 * index = cur_token;
2263 return MAILIMF_NO_ERROR;
2267 month = (FWS month-name FWS) / obs-month
2270 static int mailimf_month_parse(const char * message, size_t length,
2271 size_t * index, int * result)
2277 cur_token = * index;
2279 r = mailimf_cfws_parse(message, length, &cur_token);
2280 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2283 r = mailimf_month_name_parse(message, length, &cur_token, &month);
2284 if (r != MAILIMF_NO_ERROR)
2288 * index = cur_token;
2290 return MAILIMF_NO_ERROR;
2294 month-name = "Jan" / "Feb" / "Mar" / "Apr" /
2295 "May" / "Jun" / "Jul" / "Aug" /
2296 "Sep" / "Oct" / "Nov" / "Dec"
2299 static struct mailimf_token_value month_names[] = {
2323 static int guess_month(const char * message, size_t length, size_t index)
2327 state = MONTH_START;
2331 if (index >= length)
2336 switch((char) toupper((unsigned char) message[index])) {
2337 case 'J': /* Jan Jun Jul */
2342 case 'M': /* Mar May */
2345 case 'A': /* Apr Aug */
2361 switch((char) toupper((unsigned char) message[index])) {
2372 switch((char) toupper((unsigned char) message[index])) {
2382 switch((char) toupper((unsigned char) message[index])) {
2391 switch((char) toupper((unsigned char) message[index])) {
2401 switch((char) toupper((unsigned char) message[index])) {
2416 static int mailimf_month_name_parse(const char * message, size_t length,
2417 size_t * index, int * result)
2424 cur_token = * index;
2426 guessed_month = guess_month(message, length, cur_token);
2427 if (guessed_month == -1)
2428 return MAILIMF_ERROR_PARSE;
2430 r = mailimf_token_case_insensitive_parse(message, length,
2432 month_names[guessed_month - 1].str);
2433 if (r != MAILIMF_NO_ERROR)
2436 month = guessed_month;
2439 * index = cur_token;
2441 return MAILIMF_NO_ERROR;
2445 day = ([FWS] 1*2DIGIT) / obs-day
2448 static int mailimf_day_parse(const char * message, size_t length,
2449 size_t * index, int * result)
2455 cur_token = * index;
2457 r = mailimf_cfws_parse(message, length, &cur_token);
2458 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2461 r = mailimf_number_parse(message, length, &cur_token, &day);
2462 if (r != MAILIMF_NO_ERROR)
2466 * index = cur_token;
2468 return MAILIMF_NO_ERROR;
2472 time = time-of-day FWS zone
2475 static int mailimf_time_parse(const char * message, size_t length,
2477 int * phour, int * pmin,
2488 cur_token = * index;
2490 r = mailimf_cfws_parse(message, length, &cur_token);
2491 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2494 r = mailimf_time_of_day_parse(message, length, &cur_token,
2496 if (r != MAILIMF_NO_ERROR)
2499 r = mailimf_fws_parse(message, length, &cur_token);
2500 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2503 r = mailimf_zone_parse(message, length, &cur_token, &zone);
2504 if (r == MAILIMF_NO_ERROR) {
2507 else if (r == MAILIMF_ERROR_PARSE) {
2519 * index = cur_token;
2521 return MAILIMF_NO_ERROR;
2525 time-of-day = hour ":" minute [ ":" second ]
2528 static int mailimf_time_of_day_parse(const char * message, size_t length,
2530 int * phour, int * pmin,
2539 cur_token = * index;
2541 r = mailimf_hour_parse(message, length, &cur_token, &hour);
2542 if (r != MAILIMF_NO_ERROR)
2545 r = mailimf_colon_parse(message, length, &cur_token);
2546 if (r != MAILIMF_NO_ERROR)
2549 r = mailimf_minute_parse(message, length, &cur_token, &min);
2550 if (r != MAILIMF_NO_ERROR)
2553 r = mailimf_colon_parse(message, length, &cur_token);
2554 if (r == MAILIMF_NO_ERROR) {
2555 r = mailimf_second_parse(message, length, &cur_token, &sec);
2556 if (r != MAILIMF_NO_ERROR)
2559 else if (r == MAILIMF_ERROR_PARSE)
2567 * index = cur_token;
2569 return MAILIMF_NO_ERROR;
2573 hour = 2DIGIT / obs-hour
2576 static int mailimf_hour_parse(const char * message, size_t length,
2577 size_t * index, int * result)
2582 r = mailimf_number_parse(message, length, index, &hour);
2583 if (r != MAILIMF_NO_ERROR)
2588 return MAILIMF_NO_ERROR;
2592 minute = 2DIGIT / obs-minute
2595 static int mailimf_minute_parse(const char * message, size_t length,
2596 size_t * index, int * result)
2601 r = mailimf_number_parse(message, length, index, &minute);
2602 if (r != MAILIMF_NO_ERROR)
2607 return MAILIMF_NO_ERROR;
2611 second = 2DIGIT / obs-second
2614 static int mailimf_second_parse(const char * message, size_t length,
2615 size_t * index, int * result)
2620 r = mailimf_number_parse(message, length, index, &second);
2621 if (r != MAILIMF_NO_ERROR)
2626 return MAILIMF_NO_ERROR;
2630 zone = (( "+" / "-" ) 4DIGIT) / obs-zone
2634 obs-zone = "UT" / "GMT" / ; Universal Time
2637 "EST" / "EDT" / ; Eastern: - 5/ - 4
2638 "CST" / "CDT" / ; Central: - 6/ - 5
2639 "MST" / "MDT" / ; Mountain: - 7/ - 6
2640 "PST" / "PDT" / ; Pacific: - 8/ - 7
2642 %d65-73 / ; Military zones - "A"
2643 %d75-90 / ; through "I" and "K"
2644 %d97-105 / ; through "Z", both
2645 %d107-122 ; upper and lower case
2654 STATE_ZONE_CONT = 5,
2657 static int mailimf_zone_parse(const char * message, size_t length,
2658 size_t * index, int * result)
2665 cur_token = * index;
2667 if (cur_token + 1 < length) {
2668 if ((message[cur_token] == 'U') && (message[cur_token + 1] == 'T')) {
2670 * index = cur_token + 2;
2672 return MAILIMF_NO_ERROR;
2676 if (cur_token + 2 < length) {
2679 state = STATE_ZONE_1;
2681 while (state <= 2) {
2684 switch (message[cur_token]) {
2686 if (message[cur_token + 1] == 'M' && message[cur_token + 2] == 'T') {
2688 state = STATE_ZONE_OK;
2691 state = STATE_ZONE_ERR;
2696 state = STATE_ZONE_2;
2700 state = STATE_ZONE_2;
2704 state = STATE_ZONE_2;
2708 state = STATE_ZONE_2;
2711 state = STATE_ZONE_CONT;
2716 switch (message[cur_token + 1]) {
2718 state = STATE_ZONE_3;
2722 state = STATE_ZONE_3;
2725 state = STATE_ZONE_ERR;
2730 if (message[cur_token + 2] == 'T') {
2732 state = STATE_ZONE_OK;
2735 state = STATE_ZONE_ERR;
2743 * index = cur_token + 3;
2744 return MAILIMF_NO_ERROR;
2746 case STATE_ZONE_ERR:
2747 return MAILIMF_ERROR_PARSE;
2752 r = mailimf_plus_parse(message, length, &cur_token);
2753 if (r == MAILIMF_NO_ERROR)
2756 if (r == MAILIMF_ERROR_PARSE) {
2757 r = mailimf_minus_parse(message, length, &cur_token);
2758 if (r == MAILIMF_NO_ERROR)
2762 if (r == MAILIMF_NO_ERROR) {
2765 else if (r == MAILIMF_ERROR_PARSE)
2770 r = mailimf_number_parse(message, length, &cur_token, &zone);
2771 if (r != MAILIMF_NO_ERROR)
2776 * index = cur_token;
2779 return MAILIMF_NO_ERROR;
2783 address = mailbox / group
2786 int mailimf_address_parse(const char * message, size_t length,
2788 struct mailimf_address ** result)
2792 struct mailimf_mailbox * mailbox;
2793 struct mailimf_group * group;
2794 struct mailimf_address * address;
2798 cur_token = * index;
2803 type = MAILIMF_ADDRESS_ERROR; /* XXX - removes a gcc warning */
2804 r = mailimf_group_parse(message, length, &cur_token, &group);
2805 if (r == MAILIMF_NO_ERROR)
2806 type = MAILIMF_ADDRESS_GROUP;
2808 if (r == MAILIMF_ERROR_PARSE) {
2809 r = mailimf_mailbox_parse(message, length, &cur_token, &mailbox);
2810 if (r == MAILIMF_NO_ERROR)
2811 type = MAILIMF_ADDRESS_MAILBOX;
2814 if (r != MAILIMF_NO_ERROR) {
2819 address = mailimf_address_new(type, mailbox, group);
2820 if (address == NULL) {
2821 res = MAILIMF_ERROR_MEMORY;
2826 * index = cur_token;
2828 return MAILIMF_NO_ERROR;
2831 if (mailbox != NULL)
2832 mailimf_mailbox_free(mailbox);
2834 mailimf_group_free(group);
2841 mailbox = name-addr / addr-spec
2845 int mailimf_mailbox_parse(const char * message, size_t length,
2847 struct mailimf_mailbox ** result)
2850 char * display_name;
2851 struct mailimf_mailbox * mailbox;
2856 cur_token = * index;
2857 display_name = NULL;
2860 r = mailimf_name_addr_parse(message, length, &cur_token,
2861 &display_name, &addr_spec);
2862 if (r == MAILIMF_ERROR_PARSE)
2863 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2865 if (r != MAILIMF_NO_ERROR) {
2870 mailbox = mailimf_mailbox_new(display_name, addr_spec);
2871 if (mailbox == NULL) {
2872 res = MAILIMF_ERROR_MEMORY;
2877 * index = cur_token;
2879 return MAILIMF_NO_ERROR;
2882 if (display_name != NULL)
2883 mailimf_display_name_free(display_name);
2884 if (addr_spec != NULL)
2885 mailimf_addr_spec_free(addr_spec);
2891 name-addr = [display-name] angle-addr
2894 static int mailimf_name_addr_parse(const char * message, size_t length,
2896 char ** pdisplay_name,
2897 char ** pangle_addr)
2899 char * display_name;
2905 cur_token = * index;
2907 display_name = NULL;
2910 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
2911 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
2916 r = mailimf_angle_addr_parse(message, length, &cur_token, &angle_addr);
2917 if (r != MAILIMF_NO_ERROR) {
2919 goto free_display_name;
2922 * pdisplay_name = display_name;
2923 * pangle_addr = angle_addr;
2924 * index = cur_token;
2926 return MAILIMF_NO_ERROR;
2929 if (display_name != NULL)
2930 mailimf_display_name_free(display_name);
2936 angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
2939 static int mailimf_angle_addr_parse(const char * message, size_t length,
2940 size_t * index, char ** result)
2946 cur_token = * index;
2948 r = mailimf_cfws_parse(message, length, &cur_token);
2949 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2952 r = mailimf_lower_parse(message, length, &cur_token);
2953 if (r != MAILIMF_NO_ERROR)
2956 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2957 if (r != MAILIMF_NO_ERROR)
2960 r = mailimf_greater_parse(message, length, &cur_token);
2961 if (r != MAILIMF_NO_ERROR) {
2966 * result = addr_spec;
2967 * index = cur_token;
2969 return MAILIMF_NO_ERROR;
2973 group = display-name ":" [mailbox-list / CFWS] ";"
2977 static int mailimf_group_parse(const char * message, size_t length,
2979 struct mailimf_group ** result)
2982 char * display_name;
2983 struct mailimf_mailbox_list * mailbox_list;
2984 struct mailimf_group * group;
2989 cur_token = * index;
2991 mailbox_list = NULL;
2993 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
2994 if (r != MAILIMF_NO_ERROR) {
2999 r = mailimf_colon_parse(message, length, &cur_token);
3000 if (r != MAILIMF_NO_ERROR) {
3002 goto free_display_name;
3005 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list);
3007 case MAILIMF_NO_ERROR:
3009 case MAILIMF_ERROR_PARSE:
3010 r = mailimf_cfws_parse(message, length, &cur_token);
3011 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3013 goto free_display_name;
3017 res = MAILIMF_ERROR_MEMORY;
3018 goto free_display_name;
3020 mailbox_list = mailimf_mailbox_list_new(list);
3021 if (mailbox_list == NULL) {
3022 res = MAILIMF_ERROR_MEMORY;
3024 goto free_display_name;
3029 goto free_display_name;
3032 r = mailimf_semi_colon_parse(message, length, &cur_token);
3033 if (r != MAILIMF_NO_ERROR) {
3035 goto free_mailbox_list;
3038 group = mailimf_group_new(display_name, mailbox_list);
3039 if (group == NULL) {
3040 res = MAILIMF_ERROR_MEMORY;
3041 goto free_mailbox_list;
3044 * index = cur_token;
3047 return MAILIMF_NO_ERROR;
3050 mailimf_mailbox_list_free(mailbox_list);
3052 mailimf_display_name_free(display_name);
3058 display-name = phrase
3061 static int mailimf_display_name_parse(const char * message, size_t length,
3062 size_t * index, char ** result)
3064 return mailimf_phrase_parse(message, length, index, result);
3068 mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
3072 mailimf_mailbox_list_parse(const char * message, size_t length,
3074 struct mailimf_mailbox_list ** result)
3078 struct mailimf_mailbox_list * mailbox_list;
3082 cur_token = * index;
3084 r = mailimf_struct_list_parse(message, length,
3085 &cur_token, &list, ',',
3086 (mailimf_struct_parser *)
3087 mailimf_mailbox_parse,
3088 (mailimf_struct_destructor *)
3089 mailimf_mailbox_free);
3090 if (r != MAILIMF_NO_ERROR) {
3095 mailbox_list = mailimf_mailbox_list_new(list);
3096 if (mailbox_list == NULL) {
3097 res = MAILIMF_ERROR_MEMORY;
3101 * result = mailbox_list;
3102 * index = cur_token;
3104 return MAILIMF_NO_ERROR;
3107 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
3114 address-list = (address *("," address)) / obs-addr-list
3119 mailimf_address_list_parse(const char * message, size_t length,
3121 struct mailimf_address_list ** result)
3125 struct mailimf_address_list * address_list;
3129 cur_token = * index;
3131 r = mailimf_struct_list_parse(message, length,
3132 &cur_token, &list, ',',
3133 (mailimf_struct_parser *)
3134 mailimf_address_parse,
3135 (mailimf_struct_destructor *)
3136 mailimf_address_free);
3137 if (r != MAILIMF_NO_ERROR) {
3142 address_list = mailimf_address_list_new(list);
3143 if (address_list == NULL) {
3144 res = MAILIMF_ERROR_MEMORY;
3148 * result = address_list;
3149 * index = cur_token;
3151 return MAILIMF_NO_ERROR;
3154 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
3161 addr-spec = local-part "@" domain
3165 static int mailimf_addr_spec_parse(const char * message, size_t length,
3185 cur_token = * index;
3187 r = mailimf_cfws_parse(message, length, &cur_token);
3188 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3194 if (end >= length) {
3195 res = MAILIMF_ERROR_PARSE;
3203 switch (message[end]) {
3225 res = MAILIMF_ERROR_PARSE;
3229 addr_spec = malloc(end - cur_token + 1);
3230 if (addr_spec == NULL) {
3231 res = MAILIMF_ERROR_MEMORY;
3235 count = end - cur_token;
3236 src = message + cur_token;
3238 for(i = 0 ; i < count ; i ++) {
3239 if ((* src != ' ') && (* src != '\t')) {
3248 strncpy(addr_spec, message + cur_token, end - cur_token);
3249 addr_spec[end - cur_token] = '\0';
3255 r = mailimf_local_part_parse(message, length, &cur_token, &local_part);
3256 if (r != MAILIMF_NO_ERROR) {
3261 r = mailimf_at_sign_parse(message, length, &cur_token);
3263 case MAILIMF_NO_ERROR:
3264 r = mailimf_domain_parse(message, length, &cur_token, &domain);
3265 if (r != MAILIMF_NO_ERROR) {
3267 goto free_local_part;
3271 case MAILIMF_ERROR_PARSE:
3277 goto free_local_part;
3281 addr_spec = malloc(strlen(local_part) + strlen(domain) + 2);
3282 if (addr_spec == NULL) {
3283 res = MAILIMF_ERROR_MEMORY;
3287 strcpy(addr_spec, local_part);
3288 strcat(addr_spec, "@");
3289 strcat(addr_spec, domain);
3291 mailimf_domain_free(domain);
3292 mailimf_local_part_free(local_part);
3295 addr_spec = local_part;
3299 * result = addr_spec;
3300 * index = cur_token;
3302 return MAILIMF_NO_ERROR;
3306 mailimf_domain_free(domain);
3308 mailimf_local_part_free(local_part);
3315 local-part = dot-atom / quoted-string / obs-local-part
3319 static int mailimf_local_part_parse(const char * message, size_t length,
3325 r = mailimf_dot_atom_parse(message, length, index, result);
3327 case MAILIMF_NO_ERROR:
3329 case MAILIMF_ERROR_PARSE:
3335 r = mailimf_quoted_string_parse(message, length, index, result);
3336 if (r != MAILIMF_NO_ERROR)
3339 return MAILIMF_NO_ERROR;
3344 domain = dot-atom / domain-literal / obs-domain
3348 static int mailimf_domain_parse(const char * message, size_t length,
3354 r = mailimf_dot_atom_parse(message, length, index, result);
3356 case MAILIMF_NO_ERROR:
3358 case MAILIMF_ERROR_PARSE:
3364 r = mailimf_domain_literal_parse(message, length, index, result);
3365 if (r != MAILIMF_NO_ERROR)
3368 return MAILIMF_NO_ERROR;
3378 mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length,
3385 cur_token = * index;
3387 r = mailimf_cfws_parse(message, length, &cur_token);
3388 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3391 r = mailimf_dcontent_parse(message, length, &cur_token, &ch);
3392 if (r != MAILIMF_NO_ERROR)
3395 * index = cur_token;
3397 return MAILIMF_NO_ERROR;
3402 domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
3406 static int mailimf_domain_literal_parse(const char * message, size_t length,
3407 size_t * index, char ** result)
3412 char * domain_literal;
3415 cur_token = * index;
3417 r = mailimf_cfws_parse(message, length, &cur_token);
3418 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3422 r = mailimf_obracket_parse(message, length, &cur_token);
3423 if (r != MAILIMF_NO_ERROR)
3427 r = mailimf_domain_literal_fws_dcontent_parse(message, length,
3429 if (r == MAILIMF_NO_ERROR) {
3432 else if (r == MAILIMF_ERROR_PARSE)
3438 r = mailimf_fws_parse(message, length, &cur_token);
3439 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3442 r = mailimf_cbracket_parse(message, length, &cur_token);
3443 if (r != MAILIMF_NO_ERROR)
3446 len = cur_token - begin;
3448 domain_literal = malloc(len + 1);
3449 if (domain_literal == NULL)
3450 return MAILIMF_ERROR_MEMORY;
3451 strncpy(domain_literal, message + begin, len);
3452 domain_literal[len] = '\0';
3454 * result = domain_literal;
3455 * index = cur_token;
3457 return MAILIMF_NO_ERROR;
3462 dcontent = dtext / quoted-pair
3466 static int mailimf_dcontent_parse(const char * message, size_t length,
3467 size_t * index, char * result)
3473 cur_token = * index;
3475 if (cur_token >= length)
3476 return MAILIMF_ERROR_PARSE;
3478 if (is_dtext(message[cur_token])) {
3479 ch = message[cur_token];
3483 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
3485 if (r != MAILIMF_NO_ERROR)
3489 * index = cur_token;
3492 return MAILIMF_NO_ERROR;
3498 dtext = NO-WS-CTL / ; Non white space controls
3500 %d33-90 / ; The rest of the US-ASCII
3501 %d94-126 ; characters not including "[",
3505 static inline int is_dtext(char ch)
3507 unsigned char uch = (unsigned char) ch;
3509 if (is_no_ws_ctl(ch))
3515 if ((uch >= 91) && (uch <= 93))
3525 message = (fields / obs-fields)
3529 int mailimf_message_parse(const char * message, size_t length,
3531 struct mailimf_message ** result)
3533 struct mailimf_fields * fields;
3534 struct mailimf_body * body;
3535 struct mailimf_message * msg;
3540 cur_token = * index;
3542 r = mailimf_fields_parse(message, length, &cur_token, &fields);
3543 if (r != MAILIMF_NO_ERROR) {
3548 r = mailimf_crlf_parse(message, length, &cur_token);
3549 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3554 r = mailimf_body_parse(message, length, &cur_token, &body);
3555 if (r != MAILIMF_NO_ERROR) {
3560 msg = mailimf_message_new(fields, body);
3562 res = MAILIMF_ERROR_MEMORY;
3566 * index = cur_token;
3569 return MAILIMF_NO_ERROR;
3572 mailimf_body_free(body);
3574 mailimf_fields_free(fields);
3580 body = *(*998text CRLF) *998text
3583 int mailimf_body_parse(const char * message, size_t length,
3585 struct mailimf_body ** result)
3588 struct mailimf_body * body;
3590 cur_token = * index;
3592 body = mailimf_body_new(message + cur_token, length - cur_token);
3594 return MAILIMF_ERROR_MEMORY;
3599 * index = cur_token;
3601 return MAILIMF_NO_ERROR;
3605 CHANGE TO THE RFC 2822
3632 INTO THE FOLLOWING :
3636 resent-fields-list = *(resent-date /
3647 RESENT_HEADER_START,
3650 static int guess_resent_header_type(char * message,
3651 size_t length, size_t index)
3655 r = mailimf_token_case_insensitive_parse(message,
3656 length, &index, "Resent-");
3657 if (r != MAILIMF_NO_ERROR)
3658 return MAILIMF_RESENT_FIELD_NONE;
3660 if (index >= length)
3661 return MAILIMF_RESENT_FIELD_NONE;
3663 switch(toupper(message[index])) {
3665 return MAILIMF_RESENT_FIELD_DATE;
3667 return MAILIMF_RESENT_FIELD_FROM;
3669 return MAILIMF_RESENT_FIELD_SENDER;
3671 return MAILIMF_RESENT_FIELD_TO;
3673 return MAILIMF_RESENT_FIELD_CC;
3675 return MAILIMF_RESENT_FIELD_BCC;
3677 return MAILIMF_RESENT_FIELD_MSG_ID;
3679 return MAILIMF_RESENT_FIELD_NONE;
3686 mailimf_resent_field_parse(const char * message, size_t length,
3688 struct mailimf_resent_field ** result)
3690 struct mailimf_orig_date * resent_date;
3691 struct mailimf_from * resent_from;
3692 struct mailimf_sender * resent_sender;
3693 struct mailimf_to* resent_to;
3694 struct mailimf_cc * resent_cc;
3695 struct mailimf_bcc * resent_bcc;
3696 struct mailimf_message_id * resent_msg_id;
3699 struct mailimf_resent_field * resent_field;
3703 cur_token = * index;
3707 resent_sender = NULL;
3711 resent_msg_id = NULL;
3713 type = guess_resent_header_type(message, length, cur_token);
3716 case MAILIMF_RESENT_FIELD_DATE:
3717 r = mailimf_resent_date_parse(message, length, &cur_token,
3719 if (r != MAILIMF_NO_ERROR) {
3724 case MAILIMF_RESENT_FIELD_FROM:
3725 r = mailimf_resent_from_parse(message, length, &cur_token,
3727 if (r != MAILIMF_NO_ERROR) {
3732 case MAILIMF_RESENT_FIELD_SENDER:
3733 r = mailimf_resent_sender_parse(message, length, &cur_token,
3735 if (r != MAILIMF_NO_ERROR) {
3740 case MAILIMF_RESENT_FIELD_TO:
3741 r = mailimf_resent_to_parse(message, length, &cur_token,
3743 if (r != MAILIMF_NO_ERROR) {
3748 case MAILIMF_RESENT_FIELD_CC:
3749 r= mailimf_resent_cc_parse(message, length, &cur_token,
3751 if (r != MAILIMF_NO_ERROR) {
3756 case MAILIMF_RESENT_FIELD_BCC:
3757 r = mailimf_resent_bcc_parse(message, length, &cur_token,
3759 if (r != MAILIMF_NO_ERROR) {
3764 case MAILIMF_RESENT_FIELD_MSG_ID:
3765 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
3767 if (r != MAILIMF_NO_ERROR) {
3773 res = MAILIMF_ERROR_PARSE;
3777 resent_field = mailimf_resent_field_new(type, resent_date,
3778 resent_from, resent_sender,
3779 resent_to, resent_cc,
3780 resent_bcc, resent_msg_id);
3781 if (resent_field == NULL) {
3782 res = MAILIMF_ERROR_MEMORY;
3786 * result = resent_field;
3787 * index = cur_token;
3789 return MAILIMF_NO_ERROR;
3792 if (resent_msg_id != NULL)
3793 mailimf_message_id_free(resent_msg_id);
3794 if (resent_bcc != NULL)
3795 mailimf_bcc_free(resent_bcc);
3796 if (resent_cc != NULL)
3797 mailimf_cc_free(resent_cc);
3798 if (resent_to != NULL)
3799 mailimf_to_free(resent_to);
3800 if (resent_sender != NULL)
3801 mailimf_sender_free(resent_sender);
3802 if (resent_from != NULL)
3803 mailimf_from_free(resent_from);
3804 if (resent_date != NULL)
3805 mailimf_orig_date_free(resent_date);
3813 mailimf_resent_fields_list_parse(const char * message, size_t length,
3815 struct mailimf_resent_fields_list ** result)
3819 struct mailimf_resent_fields_list * resent_fields_list;
3823 cur_token = * index;
3826 r = mailimf_struct_multiple_parse(message, length, &cur_token, &list,
3827 (mailimf_struct_parser *)
3828 mailimf_resent_field_parse,
3829 (mailimf_struct_destructor *)
3830 mailimf_resent_field_free);
3831 if (r != MAILIMF_NO_ERROR) {
3836 resent_fields_list = mailimf_resent_fields_list_new(list);
3837 if (resent_fields_list == NULL) {
3838 res = MAILIMF_ERROR_MEMORY;
3842 * result = resent_fields_list;
3843 * index = cur_token;
3845 return MAILIMF_NO_ERROR;
3848 clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL);
3857 [resent-fields-list])
3862 mailimf_trace_resent_fields_parse(const char * message, size_t length,
3864 struct mailimf_trace_resent_fields ** result)
3867 struct mailimf_return * return_path;
3868 struct mailimf_resent_fields_list * resent_fields;
3869 struct mailimf_trace_resent_fields * trace_resent_fields;
3873 cur_token = * index;
3876 resent_fields = NULL;
3878 r = mailimf_return_parse(message, length, &cur_token,
3880 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3885 r = mailimf_resent_fields_list_parse(message, length, &cur_token,
3887 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3892 if ((return_path == NULL) && (resent_fields == NULL)) {
3893 res = MAILIMF_ERROR_PARSE;
3897 trace_resent_fields = mailimf_trace_resent_fields_new(return_path,
3899 if (trace_resent_fields == NULL) {
3900 res = MAILIMF_ERROR_MEMORY;
3901 goto free_resent_fields;
3904 * result = trace_resent_fields;
3905 * index = cur_token;
3907 return MAILIMF_NO_ERROR;
3910 if (resent_fields != NULL)
3911 mailimf_resent_fields_list_free(resent_fields);
3912 if (return_path != NULL)
3913 mailimf_return_free(return_path);
3920 delivering-info = *([trace]
3921 [resent-fields-list])
3926 mailimf_delivering_info_parse(const char * message, size_t length,
3928 struct mailimf_delivering_info ** result)
3932 struct mailimf_delivering_info * delivering_info;
3936 cur_token = * index;
3938 r = mailimf_struct_multiple_parse(message, length, &cur_token,
3940 (mailimf_struct_parser *)
3941 mailimf_trace_resent_fields_parse,
3942 (mailimf_struct_destructor *)
3943 mailimf_trace_resent_fields_free);
3944 if (r != MAILIMF_NO_ERROR) {
3949 delivering_info = mailimf_delivering_info_new(list);
3950 if (delivering_info == NULL) {
3951 res = MAILIMF_ERROR_MEMORY;
3955 * result = delivering_info;
3956 * index = cur_token;
3958 return MAILIMF_NO_ERROR;
3961 clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL);
3969 field = delivering-info /
3995 static int guess_header_type(const char * message, size_t length, size_t index)
4000 state = HEADER_START;
4004 if (index >= length)
4005 return MAILIMF_FIELD_NONE;
4009 switch((char) toupper((unsigned char) message[index])) {
4011 return MAILIMF_FIELD_BCC;
4016 return MAILIMF_FIELD_ORIG_DATE;
4018 return MAILIMF_FIELD_FROM;
4020 return MAILIMF_FIELD_IN_REPLY_TO;
4022 return MAILIMF_FIELD_KEYWORDS;
4024 return MAILIMF_FIELD_MESSAGE_ID;
4029 return MAILIMF_FIELD_TO;
4035 return MAILIMF_FIELD_NONE;
4039 switch((char) toupper((unsigned char) message[index])) {
4041 return MAILIMF_FIELD_COMMENTS;
4043 return MAILIMF_FIELD_CC;
4045 return MAILIMF_FIELD_NONE;
4049 switch((char) toupper((unsigned char) message[index])) {
4054 return MAILIMF_FIELD_NONE;
4058 switch((char) toupper((unsigned char) message[index])) {
4060 return MAILIMF_FIELD_REFERENCES;
4062 return MAILIMF_FIELD_REPLY_TO;
4067 return MAILIMF_FIELD_RETURN_PATH;
4069 return MAILIMF_FIELD_NONE;
4073 switch((char) toupper((unsigned char) message[index])) {
4075 return MAILIMF_FIELD_SENDER;
4077 return MAILIMF_FIELD_SUBJECT;
4079 return MAILIMF_FIELD_NONE;
4084 r = mailimf_token_case_insensitive_parse(message,
4085 length, &index, "ent-");
4086 if (r != MAILIMF_NO_ERROR)
4087 return MAILIMF_FIELD_NONE;
4089 if (index >= length)
4090 return MAILIMF_FIELD_NONE;
4092 switch((char) toupper((unsigned char) message[index])) {
4094 return MAILIMF_FIELD_RESENT_DATE;
4096 return MAILIMF_FIELD_RESENT_FROM;
4098 return MAILIMF_FIELD_RESENT_SENDER;
4100 return MAILIMF_FIELD_RESENT_TO;
4102 return MAILIMF_FIELD_RESENT_CC;
4104 return MAILIMF_FIELD_RESENT_BCC;
4106 return MAILIMF_FIELD_RESENT_MSG_ID;
4108 return MAILIMF_FIELD_NONE;
4116 static int mailimf_field_parse(const char * message, size_t length,
4118 struct mailimf_field ** result)
4122 struct mailimf_return * return_path;
4123 struct mailimf_orig_date * resent_date;
4124 struct mailimf_from * resent_from;
4125 struct mailimf_sender * resent_sender;
4126 struct mailimf_to* resent_to;
4127 struct mailimf_cc * resent_cc;
4128 struct mailimf_bcc * resent_bcc;
4129 struct mailimf_message_id * resent_msg_id;
4130 struct mailimf_orig_date * orig_date;
4131 struct mailimf_from * from;
4132 struct mailimf_sender * sender;
4133 struct mailimf_reply_to * reply_to;
4134 struct mailimf_to * to;
4135 struct mailimf_cc * cc;
4136 struct mailimf_bcc * bcc;
4137 struct mailimf_message_id * message_id;
4138 struct mailimf_in_reply_to * in_reply_to;
4139 struct mailimf_references * references;
4140 struct mailimf_subject * subject;
4141 struct mailimf_comments * comments;
4142 struct mailimf_keywords * keywords;
4143 struct mailimf_optional_field * optional_field;
4144 struct mailimf_field * field;
4149 cur_token = * index;
4154 resent_sender = NULL;
4158 resent_msg_id = NULL;
4172 optional_field = NULL;
4174 guessed_type = guess_header_type(message, length, cur_token);
4175 type = MAILIMF_FIELD_NONE;
4177 switch (guessed_type) {
4178 case MAILIMF_FIELD_ORIG_DATE:
4179 r = mailimf_orig_date_parse(message, length, &cur_token,
4181 if (r == MAILIMF_NO_ERROR)
4182 type = MAILIMF_FIELD_ORIG_DATE;
4183 else if (r == MAILIMF_ERROR_PARSE) {
4191 case MAILIMF_FIELD_FROM:
4192 r = mailimf_from_parse(message, length, &cur_token,
4194 if (r == MAILIMF_NO_ERROR)
4195 type = guessed_type;
4196 else if (r == MAILIMF_ERROR_PARSE) {
4204 case MAILIMF_FIELD_SENDER:
4205 r = mailimf_sender_parse(message, length, &cur_token,
4207 if (r == MAILIMF_NO_ERROR)
4208 type = guessed_type;
4209 else if (r == MAILIMF_ERROR_PARSE) {
4217 case MAILIMF_FIELD_REPLY_TO:
4218 r = mailimf_reply_to_parse(message, length, &cur_token,
4220 if (r == MAILIMF_NO_ERROR)
4221 type = guessed_type;
4222 else if (r == MAILIMF_ERROR_PARSE) {
4230 case MAILIMF_FIELD_TO:
4231 r = mailimf_to_parse(message, length, &cur_token,
4233 if (r == MAILIMF_NO_ERROR)
4234 type = guessed_type;
4235 else if (r == MAILIMF_ERROR_PARSE) {
4243 case MAILIMF_FIELD_CC:
4244 r = mailimf_cc_parse(message, length, &cur_token,
4246 if (r == MAILIMF_NO_ERROR)
4247 type = guessed_type;
4248 else if (r == MAILIMF_ERROR_PARSE) {
4256 case MAILIMF_FIELD_BCC:
4257 r = mailimf_bcc_parse(message, length, &cur_token,
4259 if (r == MAILIMF_NO_ERROR)
4260 type = guessed_type;
4261 else if (r == MAILIMF_ERROR_PARSE) {
4269 case MAILIMF_FIELD_MESSAGE_ID:
4270 r = mailimf_message_id_parse(message, length, &cur_token,
4272 if (r == MAILIMF_NO_ERROR)
4273 type = guessed_type;
4274 else if (r == MAILIMF_ERROR_PARSE) {
4282 case MAILIMF_FIELD_IN_REPLY_TO:
4283 r = mailimf_in_reply_to_parse(message, length, &cur_token,
4285 if (r == MAILIMF_NO_ERROR)
4286 type = guessed_type;
4287 else if (r == MAILIMF_ERROR_PARSE) {
4295 case MAILIMF_FIELD_REFERENCES:
4296 r = mailimf_references_parse(message, length, &cur_token,
4298 if (r == MAILIMF_NO_ERROR)
4299 type = guessed_type;
4300 else if (r == MAILIMF_ERROR_PARSE) {
4308 case MAILIMF_FIELD_SUBJECT:
4309 r = mailimf_subject_parse(message, length, &cur_token,
4311 if (r == MAILIMF_NO_ERROR)
4312 type = guessed_type;
4313 else if (r == MAILIMF_ERROR_PARSE) {
4321 case MAILIMF_FIELD_COMMENTS:
4322 r = mailimf_comments_parse(message, length, &cur_token,
4324 if (r == MAILIMF_NO_ERROR)
4325 type = guessed_type;
4326 else if (r == MAILIMF_ERROR_PARSE) {
4334 case MAILIMF_FIELD_KEYWORDS:
4335 r = mailimf_keywords_parse(message, length, &cur_token,
4337 if (r == MAILIMF_NO_ERROR)
4338 type = guessed_type;
4339 else if (r == MAILIMF_ERROR_PARSE) {
4347 case MAILIMF_FIELD_RETURN_PATH:
4348 r = mailimf_return_parse(message, length, &cur_token,
4350 if (r == MAILIMF_NO_ERROR)
4351 type = guessed_type;
4352 else if (r == MAILIMF_ERROR_PARSE) {
4360 case MAILIMF_FIELD_RESENT_DATE:
4361 r = mailimf_resent_date_parse(message, length, &cur_token,
4363 if (r == MAILIMF_NO_ERROR)
4364 type = guessed_type;
4365 else if (r == MAILIMF_ERROR_PARSE) {
4373 case MAILIMF_FIELD_RESENT_FROM:
4374 r = mailimf_resent_from_parse(message, length, &cur_token,
4376 if (r == MAILIMF_NO_ERROR)
4377 type = guessed_type;
4378 else if (r == MAILIMF_ERROR_PARSE) {
4386 case MAILIMF_FIELD_RESENT_SENDER:
4387 r = mailimf_resent_sender_parse(message, length, &cur_token,
4389 if (r == MAILIMF_NO_ERROR)
4390 type = guessed_type;
4391 else if (r == MAILIMF_ERROR_PARSE) {
4399 case MAILIMF_FIELD_RESENT_TO:
4400 r = mailimf_resent_to_parse(message, length, &cur_token,
4402 if (r == MAILIMF_NO_ERROR)
4403 type = guessed_type;
4404 else if (r == MAILIMF_ERROR_PARSE) {
4412 case MAILIMF_FIELD_RESENT_CC:
4413 r= mailimf_resent_cc_parse(message, length, &cur_token,
4415 if (r == MAILIMF_NO_ERROR)
4416 type = guessed_type;
4417 else if (r == MAILIMF_ERROR_PARSE) {
4425 case MAILIMF_FIELD_RESENT_BCC:
4426 r = mailimf_resent_bcc_parse(message, length, &cur_token,
4428 if (r == MAILIMF_NO_ERROR)
4429 type = guessed_type;
4430 else if (r == MAILIMF_ERROR_PARSE) {
4438 case MAILIMF_FIELD_RESENT_MSG_ID:
4439 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
4441 if (r == MAILIMF_NO_ERROR)
4442 type = guessed_type;
4443 else if (r == MAILIMF_ERROR_PARSE) {
4453 if (type == MAILIMF_FIELD_NONE) {
4454 r = mailimf_optional_field_parse(message, length, &cur_token,
4456 if (r != MAILIMF_NO_ERROR) {
4461 type = MAILIMF_FIELD_OPTIONAL_FIELD;
4464 field = mailimf_field_new(type, return_path, resent_date,
4465 resent_from, resent_sender, resent_to, resent_cc, resent_bcc,
4466 resent_msg_id, orig_date, from, sender, reply_to, to,
4467 cc, bcc, message_id, in_reply_to, references,
4468 subject, comments, keywords, optional_field);
4469 if (field == NULL) {
4470 res = MAILIMF_ERROR_MEMORY;
4475 * index = cur_token;
4477 return MAILIMF_NO_ERROR;
4480 if (return_path != NULL)
4481 mailimf_return_free(return_path);
4482 if (resent_date != NULL)
4483 mailimf_orig_date_free(resent_date);
4484 if (resent_from != NULL)
4485 mailimf_from_free(resent_from);
4486 if (resent_sender != NULL)
4487 mailimf_sender_free(resent_sender);
4488 if (resent_to != NULL)
4489 mailimf_to_free(resent_to);
4490 if (resent_cc != NULL)
4491 mailimf_cc_free(resent_cc);
4492 if (resent_bcc != NULL)
4493 mailimf_bcc_free(resent_bcc);
4494 if (resent_msg_id != NULL)
4495 mailimf_message_id_free(resent_msg_id);
4496 if (orig_date != NULL)
4497 mailimf_orig_date_free(orig_date);
4499 mailimf_from_free(from);
4501 mailimf_sender_free(sender);
4502 if (reply_to != NULL)
4503 mailimf_reply_to_free(reply_to);
4505 mailimf_to_free(to);
4507 mailimf_cc_free(cc);
4509 mailimf_bcc_free(bcc);
4510 if (message_id != NULL)
4511 mailimf_message_id_free(message_id);
4512 if (in_reply_to != NULL)
4513 mailimf_in_reply_to_free(in_reply_to);
4514 if (references != NULL)
4515 mailimf_references_free(references);
4516 if (subject != NULL)
4517 mailimf_subject_free(subject);
4518 if (comments != NULL)
4519 mailimf_comments_free(comments);
4520 if (keywords != NULL)
4521 mailimf_keywords_free(keywords);
4522 if (optional_field != NULL)
4523 mailimf_optional_field_free(optional_field);
4529 fields = *(delivering-info /
4548 mailimf_unparsed_fields_parse(const char * message, size_t length,
4550 struct mailimf_unparsed_fields ** result)
4554 struct mailimf_unparsed_fields * fields;
4558 cur_token = * index;
4562 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4564 (mailimf_struct_parser *)
4565 mailimf_optional_field_parse,
4566 (mailimf_struct_destructor *)
4567 mailimf_optional_field_free);
4569 if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4576 case MAILIMF_NO_ERROR:
4580 case MAILIMF_ERROR_PARSE:
4583 res = MAILIMF_ERROR_MEMORY;
4593 fields = mailimf_unparsed_fields_new(list);
4594 if (fields == NULL) {
4595 res = MAILIMF_ERROR_MEMORY;
4600 * index = cur_token;
4602 return MAILIMF_NO_ERROR;
4606 clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL);
4614 int mailimf_fields_parse(const char * message, size_t length,
4616 struct mailimf_fields ** result)
4620 struct mailimf_fields * fields;
4624 cur_token = * index;
4628 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4630 (mailimf_struct_parser *)
4631 mailimf_field_parse,
4632 (mailimf_struct_destructor *)
4633 mailimf_field_free);
4635 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4642 case MAILIMF_NO_ERROR:
4646 case MAILIMF_ERROR_PARSE:
4649 res = MAILIMF_ERROR_MEMORY;
4659 fields = mailimf_fields_new(list);
4660 if (fields == NULL) {
4661 res = MAILIMF_ERROR_MEMORY;
4666 * index = cur_token;
4668 return MAILIMF_NO_ERROR;
4672 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
4680 orig-date = "Date:" date-time CRLF
4685 mailimf_orig_date_parse(const char * message, size_t length,
4686 size_t * index, struct mailimf_orig_date ** result)
4688 struct mailimf_date_time * date_time;
4689 struct mailimf_orig_date * orig_date;
4694 cur_token = * index;
4696 r = mailimf_token_case_insensitive_parse(message, length,
4697 &cur_token, "Date:");
4698 if (r != MAILIMF_NO_ERROR) {
4703 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
4704 if (r != MAILIMF_NO_ERROR) {
4709 r = mailimf_ignore_unstructured_parse(message, length, &cur_token);
4710 if (r != MAILIMF_NO_ERROR) {
4712 goto free_date_time;
4715 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4716 if (r != MAILIMF_NO_ERROR) {
4718 goto free_date_time;
4721 orig_date = mailimf_orig_date_new(date_time);
4722 if (orig_date == NULL) {
4723 res = MAILIMF_ERROR_MEMORY;
4724 goto free_date_time;
4727 * result = orig_date;
4728 * index = cur_token;
4730 return MAILIMF_NO_ERROR;
4733 mailimf_date_time_free(date_time);
4739 from = "From:" mailbox-list CRLF
4743 mailimf_from_parse(const char * message, size_t length,
4744 size_t * index, struct mailimf_from ** result)
4746 struct mailimf_mailbox_list * mb_list;
4747 struct mailimf_from * from;
4752 cur_token = * index;
4754 r = mailimf_token_case_insensitive_parse(message, length,
4755 &cur_token, "From");
4756 if (r != MAILIMF_NO_ERROR) {
4761 r = mailimf_colon_parse(message, length, &cur_token);
4762 if (r != MAILIMF_NO_ERROR) {
4767 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
4769 if (r != MAILIMF_NO_ERROR) {
4774 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4775 if (r != MAILIMF_NO_ERROR) {
4780 from = mailimf_from_new(mb_list);
4782 res = MAILIMF_ERROR_MEMORY;
4787 * index = cur_token;
4789 return MAILIMF_NO_ERROR;
4792 mailimf_mailbox_list_free(mb_list);
4798 sender = "Sender:" mailbox CRLF
4802 mailimf_sender_parse(const char * message, size_t length,
4803 size_t * index, struct mailimf_sender ** result)
4805 struct mailimf_mailbox * mb;
4806 struct mailimf_sender * sender;
4811 cur_token = * index;
4813 r = mailimf_token_case_insensitive_parse(message, length,
4814 &cur_token, "Sender");
4815 if (r != MAILIMF_NO_ERROR) {
4820 r = mailimf_colon_parse(message, length, &cur_token);
4821 if (r != MAILIMF_NO_ERROR) {
4826 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
4827 if (r != MAILIMF_NO_ERROR) {
4832 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4833 if (r != MAILIMF_NO_ERROR) {
4838 sender = mailimf_sender_new(mb);
4839 if (sender == NULL) {
4840 res = MAILIMF_ERROR_MEMORY;
4845 * index = cur_token;
4847 return MAILIMF_NO_ERROR;
4850 mailimf_mailbox_free(mb);
4856 reply-to = "Reply-To:" address-list CRLF
4861 mailimf_reply_to_parse(const char * message, size_t length,
4862 size_t * index, struct mailimf_reply_to ** result)
4864 struct mailimf_address_list * addr_list;
4865 struct mailimf_reply_to * reply_to;
4870 cur_token = * index;
4872 r = mailimf_token_case_insensitive_parse(message, length,
4873 &cur_token, "Reply-To");
4874 if (r != MAILIMF_NO_ERROR) {
4879 r = mailimf_colon_parse(message, length, &cur_token);
4880 if (r != MAILIMF_NO_ERROR) {
4885 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4886 if (r != MAILIMF_NO_ERROR) {
4891 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4892 if (r != MAILIMF_NO_ERROR) {
4894 goto free_addr_list;
4897 reply_to = mailimf_reply_to_new(addr_list);
4898 if (reply_to == NULL) {
4899 res = MAILIMF_ERROR_MEMORY;
4900 goto free_addr_list;
4903 * result = reply_to;
4904 * index = cur_token;
4906 return MAILIMF_NO_ERROR;
4909 mailimf_address_list_free(addr_list);
4915 to = "To:" address-list CRLF
4919 mailimf_to_parse(const char * message, size_t length,
4920 size_t * index, struct mailimf_to ** result)
4922 struct mailimf_address_list * addr_list;
4923 struct mailimf_to * to;
4928 cur_token = * index;
4930 r = mailimf_token_case_insensitive_parse(message, length,
4932 if (r != MAILIMF_NO_ERROR) {
4937 r = mailimf_colon_parse(message, length, &cur_token);
4938 if (r != MAILIMF_NO_ERROR) {
4943 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4944 if (r != MAILIMF_NO_ERROR) {
4949 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4950 if (r != MAILIMF_NO_ERROR) {
4952 goto free_addr_list;
4955 to = mailimf_to_new(addr_list);
4957 res = MAILIMF_ERROR_MEMORY;
4958 goto free_addr_list;
4962 * index = cur_token;
4964 return MAILIMF_NO_ERROR;
4967 mailimf_address_list_free(addr_list);
4973 cc = "Cc:" address-list CRLF
4978 mailimf_cc_parse(const char * message, size_t length,
4979 size_t * index, struct mailimf_cc ** result)
4981 struct mailimf_address_list * addr_list;
4982 struct mailimf_cc * cc;
4987 cur_token = * index;
4989 r = mailimf_token_case_insensitive_parse(message, length,
4991 if (r != MAILIMF_NO_ERROR) {
4996 r = mailimf_colon_parse(message, length, &cur_token);
4997 if (r != MAILIMF_NO_ERROR) {
5002 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5003 if (r != MAILIMF_NO_ERROR) {
5008 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5009 if (r != MAILIMF_NO_ERROR) {
5011 goto free_addr_list;
5014 cc = mailimf_cc_new(addr_list);
5016 res = MAILIMF_ERROR_MEMORY;
5017 goto free_addr_list;
5021 * index = cur_token;
5023 return MAILIMF_NO_ERROR;
5026 mailimf_address_list_free(addr_list);
5032 bcc = "Bcc:" (address-list / [CFWS]) CRLF
5037 mailimf_bcc_parse(const char * message, size_t length,
5038 size_t * index, struct mailimf_bcc ** result)
5040 struct mailimf_address_list * addr_list;
5041 struct mailimf_bcc * bcc;
5046 cur_token = * index;
5049 r = mailimf_token_case_insensitive_parse(message, length,
5051 if (r != MAILIMF_NO_ERROR) {
5056 r = mailimf_colon_parse(message, length, &cur_token);
5057 if (r != MAILIMF_NO_ERROR) {
5062 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5064 case MAILIMF_NO_ERROR:
5067 case MAILIMF_ERROR_PARSE:
5068 r = mailimf_cfws_parse(message, length, &cur_token);
5069 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
5079 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5080 if (r != MAILIMF_NO_ERROR) {
5082 goto free_addr_list;
5085 bcc = mailimf_bcc_new(addr_list);
5087 res = MAILIMF_ERROR_MEMORY;
5088 goto free_addr_list;
5092 * index = cur_token;
5094 return MAILIMF_NO_ERROR;
5097 mailimf_address_list_free(addr_list);
5103 message-id = "Message-ID:" msg-id CRLF
5106 static int mailimf_message_id_parse(const char * message, size_t length,
5108 struct mailimf_message_id ** result)
5112 struct mailimf_message_id * message_id;
5116 cur_token = * index;
5118 r = mailimf_token_case_insensitive_parse(message, length,
5119 &cur_token, "Message-ID");
5120 if (r != MAILIMF_NO_ERROR) {
5125 r = mailimf_colon_parse(message, length, &cur_token);
5126 if (r != MAILIMF_NO_ERROR) {
5131 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
5132 if (r != MAILIMF_NO_ERROR) {
5137 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5138 if (r != MAILIMF_NO_ERROR) {
5143 message_id = mailimf_message_id_new(value);
5144 if (message_id == NULL) {
5145 res = MAILIMF_ERROR_MEMORY;
5149 * result = message_id;
5150 * index = cur_token;
5152 return MAILIMF_NO_ERROR;
5155 mailimf_msg_id_free(value);
5161 in-reply-to = "In-Reply-To:" 1*msg-id CRLF
5164 int mailimf_msg_id_list_parse(const char * message, size_t length,
5165 size_t * index, clist ** result)
5167 return mailimf_struct_multiple_parse(message, length, index,
5169 (mailimf_struct_parser *)
5170 mailimf_unstrict_msg_id_parse,
5171 (mailimf_struct_destructor *)
5172 mailimf_msg_id_free);
5175 static int mailimf_in_reply_to_parse(const char * message, size_t length,
5177 struct mailimf_in_reply_to ** result)
5179 struct mailimf_in_reply_to * in_reply_to;
5181 clist * msg_id_list;
5185 cur_token = * index;
5187 r = mailimf_token_case_insensitive_parse(message, length,
5188 &cur_token, "In-Reply-To");
5189 if (r != MAILIMF_NO_ERROR) {
5194 r = mailimf_colon_parse(message, length, &cur_token);
5195 if (r != MAILIMF_NO_ERROR) {
5200 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5201 if (r != MAILIMF_NO_ERROR) {
5206 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5207 if (r != MAILIMF_NO_ERROR) {
5212 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
5213 if (in_reply_to == NULL) {
5214 res = MAILIMF_ERROR_MEMORY;
5218 * result = in_reply_to;
5219 * index = cur_token;
5221 return MAILIMF_NO_ERROR;
5224 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5225 clist_free(msg_id_list);
5231 references = "References:" 1*msg-id CRLF
5234 int mailimf_references_parse(const char * message, size_t length,
5236 struct mailimf_references ** result)
5238 struct mailimf_references * references;
5240 clist * msg_id_list;
5244 cur_token = * index;
5246 r = mailimf_token_case_insensitive_parse(message, length,
5247 &cur_token, "References");
5248 if (r != MAILIMF_NO_ERROR) {
5253 r = mailimf_colon_parse(message, length, &cur_token);
5254 if (r != MAILIMF_NO_ERROR) {
5259 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5260 if (r != MAILIMF_NO_ERROR) {
5265 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5266 if (r != MAILIMF_NO_ERROR) {
5271 references = mailimf_references_new(msg_id_list);
5272 if (references == NULL) {
5273 res = MAILIMF_ERROR_MEMORY;
5277 * result = references;
5278 * index = cur_token;
5280 return MAILIMF_NO_ERROR;
5283 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5284 clist_free(msg_id_list);
5290 msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
5293 int mailimf_msg_id_parse(const char * message, size_t length,
5306 cur_token = * index;
5308 r = mailimf_cfws_parse(message, length, &cur_token);
5309 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5312 r = mailimf_lower_parse(message, length, &cur_token);
5313 if (r != MAILIMF_NO_ERROR) {
5318 r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id);
5319 if (r != MAILIMF_NO_ERROR) {
5324 r = mailimf_greater_parse(message, length, &cur_token);
5325 if (r != MAILIMF_NO_ERROR) {
5332 r = mailimf_id_left_parse(message, length, &cur_token, &id_left);
5333 if (r != MAILIMF_NO_ERROR) {
5338 r = mailimf_at_sign_parse(message, length, &cur_token);
5339 if (r != MAILIMF_NO_ERROR) {
5344 r = mailimf_id_right_parse(message, length, &cur_token, &id_right);
5345 if (r != MAILIMF_NO_ERROR) {
5350 r = mailimf_greater_parse(message, length, &cur_token);
5351 if (r != MAILIMF_NO_ERROR) {
5356 msg_id = malloc(strlen(id_left) + strlen(id_right) + 2);
5357 if (msg_id == NULL) {
5358 res = MAILIMF_ERROR_MEMORY;
5361 strcpy(msg_id, id_left);
5362 strcat(msg_id, "@");
5363 strcat(msg_id, id_right);
5365 mailimf_id_left_free(id_left);
5366 mailimf_id_right_free(id_right);
5370 * index = cur_token;
5372 return MAILIMF_NO_ERROR;
5376 mailimf_id_right_free(id_right);
5378 mailimf_id_left_free(id_left);
5382 mailimf_atom_free(msg_id);
5388 static int mailimf_parse_unwanted_msg_id(const char * message, size_t length,
5396 cur_token = * index;
5398 token_parsed = TRUE;
5399 while (token_parsed) {
5400 token_parsed = FALSE;
5401 r = mailimf_word_parse(message, length, &cur_token, &word);
5402 if (r == MAILIMF_NO_ERROR) {
5403 mailimf_word_free(word);
5404 token_parsed = TRUE;
5406 else if (r == MAILIMF_ERROR_PARSE) {
5411 r = mailimf_semi_colon_parse(message, length, &cur_token);
5412 if (r == MAILIMF_NO_ERROR)
5413 token_parsed = TRUE;
5414 else if (r == MAILIMF_ERROR_PARSE) {
5419 r = mailimf_comma_parse(message, length, &cur_token);
5420 if (r == MAILIMF_NO_ERROR)
5421 token_parsed = TRUE;
5422 else if (r == MAILIMF_ERROR_PARSE) {
5427 r = mailimf_plus_parse(message, length, &cur_token);
5428 if (r == MAILIMF_NO_ERROR)
5429 token_parsed = TRUE;
5430 else if (r == MAILIMF_ERROR_PARSE) {
5435 r = mailimf_colon_parse(message, length, &cur_token);
5436 if (r == MAILIMF_NO_ERROR)
5437 token_parsed = TRUE;
5438 else if (r == MAILIMF_ERROR_PARSE) {
5443 r = mailimf_point_parse(message, length, &cur_token);
5444 if (r == MAILIMF_NO_ERROR)
5445 token_parsed = TRUE;
5446 else if (r == MAILIMF_ERROR_PARSE) {
5451 r = mailimf_at_sign_parse(message, length, &cur_token);
5452 if (r == MAILIMF_NO_ERROR)
5453 token_parsed = TRUE;
5454 else if (r == MAILIMF_ERROR_PARSE) {
5461 return MAILIMF_NO_ERROR;
5464 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
5468 char * msgid = NULL;
5472 cur_token = * index;
5474 r = mailimf_cfws_parse(message, length, &cur_token);
5475 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5478 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5479 if (r != MAILIMF_NO_ERROR)
5482 r = mailimf_msg_id_parse(message, length, &cur_token, &msgid);
5483 if (r != MAILIMF_NO_ERROR)
5486 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5487 if (r != MAILIMF_NO_ERROR) {
5493 * index = cur_token;
5495 return MAILIMF_NO_ERROR;
5499 id-left = dot-atom-text / no-fold-quote / obs-id-left
5503 static int mailimf_id_left_parse(const char * message, size_t length,
5504 size_t * index, char ** result)
5508 r = mailimf_dot_atom_text_parse(message, length, index, result);
5510 case MAILIMF_NO_ERROR:
5511 return MAILIMF_NO_ERROR;
5512 case MAILIMF_ERROR_PARSE:
5518 r = mailimf_no_fold_quote_parse(message, length, index, result);
5519 if (r != MAILIMF_NO_ERROR)
5522 return MAILIMF_NO_ERROR;
5527 id-right = dot-atom-text / no-fold-literal / obs-id-right
5531 static int mailimf_id_right_parse(const char * message, size_t length,
5532 size_t * index, char ** result)
5536 r = mailimf_dot_atom_text_parse(message, length, index, result);
5538 case MAILIMF_NO_ERROR:
5539 return MAILIMF_NO_ERROR;
5540 case MAILIMF_ERROR_PARSE:
5546 r = mailimf_no_fold_literal_parse(message, length, index, result);
5547 if (r != MAILIMF_NO_ERROR)
5550 return MAILIMF_NO_ERROR;
5555 no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
5559 static int mailimf_no_fold_quote_char_parse(const char * message, size_t length,
5560 size_t * index, char * result)
5566 cur_token = * index;
5569 r = mailimf_qtext_parse(message, length, &cur_token, &ch);
5572 if (cur_token >= length)
5573 return MAILIMF_ERROR_PARSE;
5575 if (is_qtext(message[cur_token])) {
5576 ch = message[cur_token];
5580 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5582 if (r != MAILIMF_NO_ERROR)
5586 * index = cur_token;
5589 return MAILIMF_NO_ERROR;
5594 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
5595 size_t * index, char ** result)
5600 char * no_fold_quote;
5605 r = mailimf_dquote_parse(message, length, &cur_token);
5606 if (r != MAILIMF_NO_ERROR) {
5612 r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch);
5613 if (r == MAILIMF_NO_ERROR) {
5616 else if (r == MAILIMF_ERROR_PARSE)
5624 r = mailimf_dquote_parse(message, length, &cur_token);
5625 if (r != MAILIMF_NO_ERROR) {
5630 /* no_fold_quote = strndup(message + begin, cur_token - begin); */
5631 no_fold_quote = malloc(cur_token - begin + 1);
5632 if (no_fold_quote == NULL) {
5633 res = MAILIMF_ERROR_MEMORY;
5636 strncpy(no_fold_quote, message + begin, cur_token - begin);
5637 no_fold_quote[cur_token - begin] = '\0';
5639 * result = no_fold_quote;
5640 * index = cur_token;
5642 return MAILIMF_NO_ERROR;
5650 no-fold-literal = "[" *(dtext / quoted-pair) "]"
5655 mailimf_no_fold_literal_char_parse(const char * message, size_t length,
5656 size_t * index, char * result)
5662 cur_token = * index;
5665 r = mailimf_dtext_parse(message, length, &cur_token, &ch);
5667 if (cur_token >= length)
5668 return MAILIMF_ERROR_PARSE;
5670 if (is_dtext(message[cur_token])) {
5671 ch = message[cur_token];
5675 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5677 if (r != MAILIMF_NO_ERROR)
5681 * index = cur_token;
5684 return MAILIMF_NO_ERROR;
5689 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
5690 size_t * index, char ** result)
5695 char * no_fold_literal;
5700 r = mailimf_obracket_parse(message, length, &cur_token);
5701 if (r != MAILIMF_NO_ERROR) {
5707 r = mailimf_no_fold_literal_char_parse(message, length,
5709 if (r == MAILIMF_NO_ERROR) {
5712 else if (r == MAILIMF_ERROR_PARSE)
5720 r = mailimf_cbracket_parse(message, length, &cur_token);
5721 if (r != MAILIMF_NO_ERROR) {
5727 no_fold_literal = strndup(message + begin, cur_token - begin);
5729 no_fold_literal = malloc(cur_token - begin + 1);
5730 if (no_fold_literal == NULL) {
5731 res = MAILIMF_NO_ERROR;
5734 strncpy(no_fold_literal, message + begin, cur_token - begin);
5735 no_fold_literal[cur_token - begin] = '\0';
5737 * result = no_fold_literal;
5738 * index = cur_token;
5740 return MAILIMF_NO_ERROR;
5748 subject = "Subject:" unstructured CRLF
5751 static int mailimf_subject_parse(const char * message, size_t length,
5753 struct mailimf_subject ** result)
5755 struct mailimf_subject * subject;
5761 cur_token = * index;
5763 r = mailimf_token_case_insensitive_parse(message, length,
5764 &cur_token, "Subject");
5765 if (r != MAILIMF_NO_ERROR) {
5770 r = mailimf_colon_parse(message, length, &cur_token);
5771 if (r != MAILIMF_NO_ERROR) {
5776 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5777 if (r != MAILIMF_NO_ERROR) {
5782 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5783 if (r != MAILIMF_NO_ERROR) {
5788 subject = mailimf_subject_new(value);
5789 if (subject == NULL) {
5790 res = MAILIMF_ERROR_MEMORY;
5795 * index = cur_token;
5797 return MAILIMF_NO_ERROR;
5800 mailimf_unstructured_free(value);
5806 comments = "Comments:" unstructured CRLF
5809 static int mailimf_comments_parse(const char * message, size_t length,
5811 struct mailimf_comments ** result)
5813 struct mailimf_comments * comments;
5819 cur_token = * index;
5821 r = mailimf_token_case_insensitive_parse(message, length,
5822 &cur_token, "Comments");
5823 if (r != MAILIMF_NO_ERROR) {
5828 r = mailimf_colon_parse(message, length, &cur_token);
5829 if (r != MAILIMF_NO_ERROR) {
5834 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5835 if (r != MAILIMF_NO_ERROR) {
5840 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5841 if (r != MAILIMF_NO_ERROR) {
5846 comments = mailimf_comments_new(value);
5847 if (comments == NULL) {
5848 res = MAILIMF_ERROR_MEMORY;
5852 * result = comments;
5853 * index = cur_token;
5855 return MAILIMF_NO_ERROR;
5858 mailimf_unstructured_free(value);
5864 keywords = "Keywords:" phrase *("," phrase) CRLF
5867 static int mailimf_keywords_parse(const char * message, size_t length,
5869 struct mailimf_keywords ** result)
5871 struct mailimf_keywords * keywords;
5877 cur_token = * index;
5879 r = mailimf_token_case_insensitive_parse(message, length,
5880 &cur_token, "Keywords");
5881 if (r != MAILIMF_NO_ERROR) {
5886 r = mailimf_colon_parse(message, length, &cur_token);
5887 if (r != MAILIMF_NO_ERROR) {
5892 r = mailimf_struct_list_parse(message, length, &cur_token,
5894 (mailimf_struct_parser *)
5895 mailimf_phrase_parse,
5896 (mailimf_struct_destructor *)
5897 mailimf_phrase_free);
5898 if (r != MAILIMF_NO_ERROR) {
5903 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5904 if (r != MAILIMF_NO_ERROR) {
5909 keywords = mailimf_keywords_new(list);
5910 if (keywords == NULL) {
5911 res = MAILIMF_ERROR_MEMORY;
5915 * result = keywords;
5916 * index = cur_token;
5918 return MAILIMF_NO_ERROR;
5921 clist_foreach(list, (clist_func) mailimf_phrase_free, NULL);
5928 resent-date = "Resent-Date:" date-time CRLF
5932 mailimf_resent_date_parse(const char * message, size_t length,
5933 size_t * index, struct mailimf_orig_date ** result)
5935 struct mailimf_orig_date * orig_date;
5936 struct mailimf_date_time * date_time;
5941 cur_token = * index;
5943 r = mailimf_token_case_insensitive_parse(message, length,
5944 &cur_token, "Resent-Date");
5945 if (r != MAILIMF_NO_ERROR) {
5950 r = mailimf_colon_parse(message, length, &cur_token);
5951 if (r != MAILIMF_NO_ERROR) {
5956 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
5957 if (r != MAILIMF_NO_ERROR) {
5962 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5963 if (r != MAILIMF_NO_ERROR) {
5965 goto free_date_time;
5968 orig_date = mailimf_orig_date_new(date_time);
5969 if (orig_date == NULL) {
5970 res = MAILIMF_ERROR_MEMORY;
5971 goto free_date_time;
5974 * result = orig_date;
5975 * index = cur_token;
5977 return MAILIMF_NO_ERROR;
5980 mailimf_date_time_free(date_time);
5986 resent-from = "Resent-From:" mailbox-list CRLF
5990 mailimf_resent_from_parse(const char * message, size_t length,
5991 size_t * index, struct mailimf_from ** result)
5993 struct mailimf_mailbox_list * mb_list;
5994 struct mailimf_from * from;
5999 cur_token = * index;
6001 r = mailimf_token_case_insensitive_parse(message, length,
6002 &cur_token, "Resent-From");
6003 if (r != MAILIMF_NO_ERROR) {
6008 r = mailimf_colon_parse(message, length, &cur_token);
6009 if (r != MAILIMF_NO_ERROR) {
6014 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
6015 if (r != MAILIMF_NO_ERROR) {
6020 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6021 if (r != MAILIMF_NO_ERROR) {
6026 from = mailimf_from_new(mb_list);
6028 res = MAILIMF_ERROR_MEMORY;
6033 * index = cur_token;
6035 return MAILIMF_NO_ERROR;
6038 mailimf_mailbox_list_free(mb_list);
6044 resent-sender = "Resent-Sender:" mailbox CRLF
6048 mailimf_resent_sender_parse(const char * message, size_t length,
6049 size_t * index, struct mailimf_sender ** result)
6051 struct mailimf_mailbox * mb;
6052 struct mailimf_sender * sender;
6059 r = mailimf_token_case_insensitive_parse(message, length,
6060 &cur_token, "Resent-Sender");
6061 if (r != MAILIMF_NO_ERROR) {
6066 r = mailimf_colon_parse(message, length, &cur_token);
6067 if (r != MAILIMF_NO_ERROR) {
6072 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
6073 if (r != MAILIMF_NO_ERROR) {
6078 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6079 if (r != MAILIMF_NO_ERROR) {
6084 sender = mailimf_sender_new(mb);
6085 if (sender == NULL) {
6086 res = MAILIMF_ERROR_MEMORY;
6091 * index = cur_token;
6093 return MAILIMF_NO_ERROR;
6096 mailimf_mailbox_free(mb);
6102 resent-to = "Resent-To:" address-list CRLF
6106 mailimf_resent_to_parse(const char * message, size_t length,
6107 size_t * index, struct mailimf_to ** result)
6109 struct mailimf_address_list * addr_list;
6110 struct mailimf_to * to;
6115 cur_token = * index;
6117 r = mailimf_token_case_insensitive_parse(message, length,
6118 &cur_token, "Resent-To");
6119 if (r != MAILIMF_NO_ERROR) {
6124 r = mailimf_colon_parse(message, length, &cur_token);
6125 if (r != MAILIMF_NO_ERROR) {
6130 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6131 if (r != MAILIMF_NO_ERROR) {
6136 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6137 if (r != MAILIMF_NO_ERROR) {
6139 goto free_addr_list;
6142 to = mailimf_to_new(addr_list);
6144 res = MAILIMF_ERROR_MEMORY;
6145 goto free_addr_list;
6149 * index = cur_token;
6151 return MAILIMF_NO_ERROR;
6154 mailimf_address_list_free(addr_list);
6160 resent-cc = "Resent-Cc:" address-list CRLF
6164 mailimf_resent_cc_parse(const char * message, size_t length,
6165 size_t * index, struct mailimf_cc ** result)
6167 struct mailimf_address_list * addr_list;
6168 struct mailimf_cc * cc;
6173 cur_token = * index;
6175 r = mailimf_token_case_insensitive_parse(message, length,
6176 &cur_token, "Resent-Cc");
6177 if (r != MAILIMF_NO_ERROR) {
6182 r = mailimf_colon_parse(message, length, &cur_token);
6183 if (r != MAILIMF_NO_ERROR) {
6188 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6189 if (r != MAILIMF_NO_ERROR) {
6194 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6195 if (r != MAILIMF_NO_ERROR) {
6197 goto free_addr_list;
6200 cc = mailimf_cc_new(addr_list);
6202 res = MAILIMF_ERROR_MEMORY;
6203 goto free_addr_list;
6207 * index = cur_token;
6209 return MAILIMF_NO_ERROR;
6212 mailimf_address_list_free(addr_list);
6218 resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF
6222 mailimf_resent_bcc_parse(const char * message, size_t length,
6223 size_t * index, struct mailimf_bcc ** result)
6225 struct mailimf_address_list * addr_list;
6226 struct mailimf_bcc * bcc;
6231 cur_token = * index;
6234 r = mailimf_token_case_insensitive_parse(message, length,
6235 &cur_token, "Resent-Bcc");
6236 if (r != MAILIMF_NO_ERROR) {
6241 r = mailimf_colon_parse(message, length, &cur_token);
6242 if (r != MAILIMF_NO_ERROR) {
6247 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6248 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6253 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6254 if (r != MAILIMF_NO_ERROR) {
6256 goto free_addr_list;
6259 bcc = mailimf_bcc_new(addr_list);
6261 res = MAILIMF_ERROR_MEMORY;
6262 goto free_addr_list;
6266 * index = cur_token;
6271 mailimf_address_list_free(addr_list);
6277 resent-msg-id = "Resent-Message-ID:" msg-id CRLF
6281 mailimf_resent_msg_id_parse(const char * message, size_t length,
6283 struct mailimf_message_id ** result)
6287 struct mailimf_message_id * message_id;
6291 cur_token = * index;
6293 r = mailimf_token_case_insensitive_parse(message, length,
6294 &cur_token, "Resent-Message-ID");
6295 if (r != MAILIMF_NO_ERROR) {
6300 r = mailimf_colon_parse(message, length, &cur_token);
6301 if (r != MAILIMF_NO_ERROR) {
6306 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
6307 if (r != MAILIMF_NO_ERROR) {
6312 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6313 if (r != MAILIMF_NO_ERROR) {
6318 message_id = mailimf_message_id_new(value);
6319 if (message_id == NULL) {
6320 res = MAILIMF_ERROR_MEMORY;
6324 * result = message_id;
6325 * index = cur_token;
6327 return MAILIMF_NO_ERROR;
6330 mailimf_msg_id_free(value);
6341 static int mailimf_trace_parse(const char * message, size_t length,
6343 struct mailimf_trace ** result)
6346 struct mailimf_return * return_path;
6347 clist * received_list;
6348 struct mailimf_trace * trace;
6352 cur_token = * index;
6354 received_list = NULL;
6356 r = mailimf_return_parse(message, length, &cur_token, &return_path);
6357 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6362 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6364 (mailimf_struct_parser *)
6365 mailimf_received_parse,
6366 (mailimf_struct_destructor *)
6367 mailimf_received_free);
6368 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6373 if ((received_list == NULL) && (return_path == NULL)) {
6374 res = MAILIMF_ERROR_PARSE;
6378 trace = mailimf_trace_new(return_path, received_list);
6379 if (trace == NULL) {
6380 res = MAILIMF_ERROR_MEMORY;
6385 * index = cur_token;
6387 return MAILIMF_NO_ERROR;
6390 clist_foreach(received_list, (clist_func) mailimf_received_free, NULL);
6391 clist_free(received_list);
6393 if (return_path != NULL)
6394 mailimf_return_free(return_path);
6401 return = "Return-Path:" path CRLF
6404 static int mailimf_return_parse(const char * message, size_t length,
6406 struct mailimf_return ** result)
6408 struct mailimf_path * path = NULL;
6409 struct mailimf_return * return_path;
6414 cur_token = * index;
6416 r = mailimf_token_case_insensitive_parse(message, length,
6417 &cur_token, "Return-Path");
6418 if (r != MAILIMF_NO_ERROR) {
6423 r = mailimf_colon_parse(message, length, &cur_token);
6424 if (r != MAILIMF_NO_ERROR) {
6429 r = mailimf_path_parse(message, length, &cur_token, &path);
6430 if ( r!= MAILIMF_NO_ERROR) {
6435 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6436 if (r != MAILIMF_NO_ERROR) {
6441 return_path = mailimf_return_new(path);
6442 if (return_path == NULL) {
6443 res = MAILIMF_ERROR_MEMORY;
6447 * result = return_path;
6448 * index = cur_token;
6450 return MAILIMF_NO_ERROR;
6453 mailimf_path_free(path);
6459 path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
6463 static int mailimf_path_parse(const char * message, size_t length,
6464 size_t * index, struct mailimf_path ** result)
6468 struct mailimf_path * path;
6472 cur_token = * index;
6475 r = mailimf_cfws_parse(message, length, &cur_token);
6476 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6481 r = mailimf_lower_parse(message, length, &cur_token);
6482 if (r != MAILIMF_NO_ERROR) {
6487 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
6489 case MAILIMF_NO_ERROR:
6491 case MAILIMF_ERROR_PARSE:
6492 r = mailimf_cfws_parse(message, length, &cur_token);
6493 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6502 r = mailimf_greater_parse(message, length, &cur_token);
6503 if (r != MAILIMF_NO_ERROR) {
6505 goto free_addr_spec;
6508 path = mailimf_path_new(addr_spec);
6510 res = MAILIMF_ERROR_MEMORY;
6511 goto free_addr_spec;
6514 * index = cur_token;
6517 return MAILIMF_NO_ERROR;
6520 if (addr_spec != NULL)
6521 mailimf_addr_spec_free(addr_spec);
6527 received = "Received:" name-val-list ";" date-time CRLF
6531 static int mailimf_received_parse(const char * message, size_t length,
6533 struct mailimf_received ** result)
6536 struct mailimf_received * received;
6537 struct mailimf_name_val_list * name_val_list;
6538 struct mailimf_date_time * date_time;
6542 cur_token = * index;
6544 r = mailimf_token_case_insensitive_parse(message, length,
6545 &cur_token, "Received");
6546 if (r != MAILIMF_NO_ERROR) {
6551 r = mailimf_colon_parse(message, length, &cur_token);
6552 if (r != MAILIMF_NO_ERROR) {
6557 r = mailimf_name_val_list_parse(message, length,
6558 &cur_token, &name_val_list);
6559 if (r != MAILIMF_NO_ERROR) {
6564 r = mailimf_semi_colon_parse(message, length, &cur_token);
6565 if (r != MAILIMF_NO_ERROR) {
6567 goto free_name_val_list;
6570 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
6571 if (r != MAILIMF_NO_ERROR) {
6573 goto free_name_val_list;
6576 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6577 if (r != MAILIMF_NO_ERROR) {
6579 goto free_date_time;
6582 received = mailimf_received_new(name_val_list, date_time);
6583 if (received == NULL) {
6584 res = MAILIMF_ERROR_MEMORY;
6585 goto free_date_time;
6588 * index = cur_token;
6589 * result = received;
6591 return MAILIMF_NO_ERROR;
6594 mailimf_date_time_free(date_time);
6596 mailimf_name_val_list_free(name_val_list);
6603 name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
6608 mailimf_name_val_list_parse(const char * message, size_t length,
6610 struct mailimf_name_val_list ** result)
6613 struct mailimf_name_val_pair * pair;
6614 struct mailimf_name_val_list * name_val_list;
6619 cur_token = * index;
6622 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6624 if (r == MAILIMF_NO_ERROR){
6629 mailimf_name_val_pair_free(pair);
6630 res = MAILIMF_ERROR_MEMORY;
6634 r = clist_append(list, pair);
6636 mailimf_name_val_pair_free(pair);
6637 res = MAILIMF_ERROR_MEMORY;
6641 final_token = cur_token;
6644 r = mailimf_cfws_parse(message, length, &cur_token);
6645 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6650 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6651 if (r == MAILIMF_NO_ERROR) {
6654 else if (r == MAILIMF_ERROR_PARSE)
6661 r = clist_append(list, pair);
6663 mailimf_name_val_pair_free(pair);
6664 res = MAILIMF_ERROR_MEMORY;
6668 final_token = cur_token;
6670 cur_token = final_token;
6673 name_val_list = mailimf_name_val_list_new(list);
6674 if (name_val_list == NULL) {
6675 res = MAILIMF_ERROR_MEMORY;
6679 * index = cur_token;
6680 * result = name_val_list;
6682 return MAILIMF_NO_ERROR;
6686 clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL);
6695 name-val-pair = item-name CFWS item-value
6700 mailimf_name_val_pair_parse(const char * message, size_t length,
6702 struct mailimf_name_val_pair ** result)
6706 struct mailimf_item_value * item_value;
6707 struct mailimf_name_val_pair * name_val_pair;
6711 cur_token = * index;
6713 r = mailimf_cfws_parse(message, length, &cur_token);
6714 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6719 r = mailimf_item_name_parse(message, length, &cur_token, &item_name);
6720 if (r != MAILIMF_NO_ERROR) {
6725 r = mailimf_cfws_parse(message, length, &cur_token);
6726 if (r != MAILIMF_NO_ERROR) {
6728 goto free_item_name;
6731 r = mailimf_item_value_parse(message, length, &cur_token, &item_value);
6732 if (r != MAILIMF_NO_ERROR) {
6734 goto free_item_name;
6737 name_val_pair = mailimf_name_val_pair_new(item_name, item_value);
6738 if (name_val_pair == NULL) {
6739 res = MAILIMF_ERROR_MEMORY;
6740 goto free_item_value;
6743 * result = name_val_pair;
6744 * index = cur_token;
6746 return MAILIMF_NO_ERROR;
6749 mailimf_item_value_free(item_value);
6751 mailimf_item_name_free(item_name);
6758 item-name = ALPHA *(["-"] (ALPHA / DIGIT))
6762 static int mailimf_item_name_parse(const char * message, size_t length,
6763 size_t * index, char ** result)
6773 cur_token = * index;
6777 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6778 if (r != MAILIMF_NO_ERROR) {
6786 minus_sign = mailimf_minus_parse(message, length, &cur_token);
6788 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6789 if (r == MAILIMF_ERROR_PARSE)
6790 r = mailimf_digit_parse(message, length, &cur_token, &digit);
6792 if (r == MAILIMF_NO_ERROR) {
6795 if (r == MAILIMF_ERROR_PARSE)
6797 else if (r != MAILIMF_NO_ERROR) {
6803 item_name = strndup(message + begin, cur_token - begin);
6804 if (item_name == NULL) {
6805 res = MAILIMF_ERROR_MEMORY;
6809 * index = cur_token;
6810 * result = item_name;
6812 return MAILIMF_NO_ERROR;
6820 item-value = 1*angle-addr / addr-spec /
6821 atom / domain / msg-id
6825 static int is_item_value_atext(char ch)
6839 static int mailimf_item_value_atom_parse(const char * message, size_t length,
6840 size_t * index, char ** result)
6846 cur_token = * index;
6848 r = mailimf_cfws_parse(message, length, &cur_token);
6849 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6852 r = mailimf_custom_string_parse(message, length, &cur_token,
6853 &atom, is_item_value_atext);
6854 if (r != MAILIMF_NO_ERROR)
6857 r = mailimf_cfws_parse(message, length, &cur_token);
6858 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6861 * index = cur_token;
6864 return MAILIMF_NO_ERROR;
6867 static int mailimf_item_value_parse(const char * message, size_t length,
6869 struct mailimf_item_value ** result)
6872 clist * angle_addr_list;
6878 struct mailimf_item_value * item_value;
6882 cur_token = * index;
6884 angle_addr_list = NULL;
6890 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6892 (mailimf_struct_parser *)
6893 mailimf_angle_addr_parse,
6894 (mailimf_struct_destructor *)
6895 mailimf_angle_addr_free);
6896 if (r == MAILIMF_NO_ERROR)
6897 type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST;
6899 if (r == MAILIMF_ERROR_PARSE) {
6900 r = mailimf_addr_spec_parse(message, length, &cur_token,
6902 if (r == MAILIMF_NO_ERROR)
6903 type = MAILIMF_ITEM_VALUE_ADDR_SPEC;
6906 if (r == MAILIMF_ERROR_PARSE) {
6907 r = mailimf_msg_id_parse(message, length, &cur_token,
6909 if (r == MAILIMF_NO_ERROR)
6910 type = MAILIMF_ITEM_VALUE_MSG_ID;
6914 else if (mailimf_domain_parse(message, length, &cur_token,
6916 type = MAILIMF_ITEM_VALUE_DOMAIN;
6919 else if (mailimf_atom_parse(message, length, &cur_token,
6921 type = MAILIMF_ITEM_VALUE_ATOM;
6924 if (r == MAILIMF_ERROR_PARSE) {
6925 r = mailimf_item_value_atom_parse(message, length, &cur_token,
6927 if (r == MAILIMF_NO_ERROR)
6928 type = MAILIMF_ITEM_VALUE_ATOM;
6931 if (r != MAILIMF_NO_ERROR) {
6936 item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec,
6937 atom, domain, msg_id);
6938 if (item_value == NULL) {
6939 res = MAILIMF_ERROR_MEMORY;
6943 * result = item_value;
6944 * index = cur_token;
6946 return MAILIMF_NO_ERROR;
6949 if (angle_addr_list != NULL) {
6950 clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL);
6951 clist_free(angle_addr_list);
6953 if (addr_spec != NULL)
6954 mailimf_addr_spec_free(addr_spec);
6956 mailimf_atom_free(atom);
6958 mailimf_domain_free(domain);
6960 mailimf_msg_id_free(msg_id);
6967 optional-field = field-name ":" unstructured CRLF
6971 mailimf_optional_field_parse(const char * message, size_t length,
6973 struct mailimf_optional_field ** result)
6977 struct mailimf_optional_field * optional_field;
6984 optional_field = NULL;
6986 cur_token = * index;
6988 r = mailimf_field_name_parse(message, length, &cur_token, &name);
6989 if (r != MAILIMF_NO_ERROR) {
6994 r = mailimf_colon_parse(message, length, &cur_token);
6995 if (r != MAILIMF_NO_ERROR) {
7000 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
7001 if (r != MAILIMF_NO_ERROR) {
7006 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
7007 if (r != MAILIMF_NO_ERROR) {
7012 optional_field = mailimf_optional_field_new(name, value);
7013 if (optional_field == NULL) {
7014 res = MAILIMF_ERROR_MEMORY;
7018 * result = optional_field;
7019 * index = cur_token;
7021 return MAILIMF_NO_ERROR;
7025 mailimf_unstructured_free(value);
7027 mailimf_field_name_free(name);
7034 field-name = 1*ftext
7037 static inline int is_ftext(char ch);
7039 static int mailimf_field_name_parse(const char * message, size_t length,
7040 size_t * index, char ** result)
7046 cur_token = * index;
7049 if (end >= length) {
7050 return MAILIMF_ERROR_PARSE;
7053 while (is_ftext(message[end])) {
7058 if (end == cur_token) {
7059 return MAILIMF_ERROR_PARSE;
7062 /* field_name = strndup(message + cur_token, end - cur_token); */
7063 field_name = malloc(end - cur_token + 1);
7064 if (field_name == NULL) {
7065 return MAILIMF_ERROR_MEMORY;
7067 strncpy(field_name, message + cur_token, end - cur_token);
7068 field_name[end - cur_token] = '\0';
7072 * index = cur_token;
7073 * result = field_name;
7075 return MAILIMF_NO_ERROR;
7079 ftext = %d33-57 / ; Any character except
7080 %d59-126 ; controls, SP, and
7084 static inline int is_ftext(char ch)
7086 unsigned char uch = (unsigned char) ch;
7098 static int mailimf_ftext_parse(const char * message, size_t length,
7099 size_t * index, gchar * result)
7101 return mailimf_typed_text_parse(message, length, index, result, is_ftext);
7108 static int mailimf_envelope_field_parse(const char * message, size_t length,
7110 struct mailimf_field ** result)
7114 struct mailimf_orig_date * orig_date;
7115 struct mailimf_from * from;
7116 struct mailimf_sender * sender;
7117 struct mailimf_reply_to * reply_to;
7118 struct mailimf_to * to;
7119 struct mailimf_cc * cc;
7120 struct mailimf_bcc * bcc;
7121 struct mailimf_message_id * message_id;
7122 struct mailimf_in_reply_to * in_reply_to;
7123 struct mailimf_references * references;
7124 struct mailimf_subject * subject;
7125 struct mailimf_field * field;
7130 cur_token = * index;
7144 guessed_type = guess_header_type(message, length, cur_token);
7145 type = MAILIMF_FIELD_NONE;
7147 switch (guessed_type) {
7148 case MAILIMF_FIELD_ORIG_DATE:
7149 r = mailimf_orig_date_parse(message, length, &cur_token,
7151 if (r == MAILIMF_NO_ERROR)
7152 type = guessed_type;
7153 else if (r == MAILIMF_ERROR_PARSE) {
7161 case MAILIMF_FIELD_FROM:
7162 r = mailimf_from_parse(message, length, &cur_token,
7164 if (r == MAILIMF_NO_ERROR)
7165 type = guessed_type;
7166 else if (r == MAILIMF_ERROR_PARSE) {
7174 case MAILIMF_FIELD_SENDER:
7175 r = mailimf_sender_parse(message, length, &cur_token,
7177 if (r == MAILIMF_NO_ERROR)
7178 type = guessed_type;
7179 else if (r == MAILIMF_ERROR_PARSE) {
7187 case MAILIMF_FIELD_REPLY_TO:
7188 r = mailimf_reply_to_parse(message, length, &cur_token,
7190 if (r == MAILIMF_NO_ERROR)
7191 type = guessed_type;
7192 else if (r == MAILIMF_ERROR_PARSE) {
7200 case MAILIMF_FIELD_TO:
7201 r = mailimf_to_parse(message, length, &cur_token,
7203 if (r == MAILIMF_NO_ERROR)
7204 type = guessed_type;
7205 else if (r == MAILIMF_ERROR_PARSE) {
7213 case MAILIMF_FIELD_CC:
7214 r = mailimf_cc_parse(message, length, &cur_token,
7216 if (r == MAILIMF_NO_ERROR)
7217 type = guessed_type;
7218 else if (r == MAILIMF_ERROR_PARSE) {
7226 case MAILIMF_FIELD_BCC:
7227 r = mailimf_bcc_parse(message, length, &cur_token,
7229 if (r == MAILIMF_NO_ERROR)
7230 type = guessed_type;
7231 else if (r == MAILIMF_ERROR_PARSE) {
7239 case MAILIMF_FIELD_MESSAGE_ID:
7240 r = mailimf_message_id_parse(message, length, &cur_token,
7242 if (r == MAILIMF_NO_ERROR)
7243 type = guessed_type;
7244 else if (r == MAILIMF_ERROR_PARSE) {
7252 case MAILIMF_FIELD_IN_REPLY_TO:
7253 r = mailimf_in_reply_to_parse(message, length, &cur_token,
7255 if (r == MAILIMF_NO_ERROR)
7256 type = guessed_type;
7257 else if (r == MAILIMF_ERROR_PARSE) {
7265 case MAILIMF_FIELD_REFERENCES:
7266 r = mailimf_references_parse(message, length, &cur_token,
7268 if (r == MAILIMF_NO_ERROR)
7269 type = guessed_type;
7270 else if (r == MAILIMF_ERROR_PARSE) {
7278 case MAILIMF_FIELD_SUBJECT:
7279 r = mailimf_subject_parse(message, length, &cur_token,
7281 if (r == MAILIMF_NO_ERROR)
7282 type = guessed_type;
7283 else if (r == MAILIMF_ERROR_PARSE) {
7293 if (type == MAILIMF_FIELD_NONE) {
7294 res = MAILIMF_ERROR_PARSE;
7298 field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
7300 orig_date, from, sender, reply_to, to,
7301 cc, bcc, message_id, in_reply_to, references,
7302 subject, NULL, NULL, NULL);
7303 if (field == NULL) {
7304 res = MAILIMF_ERROR_MEMORY;
7309 * index = cur_token;
7311 return MAILIMF_NO_ERROR;
7314 if (orig_date != NULL)
7315 mailimf_orig_date_free(orig_date);
7317 mailimf_from_free(from);
7319 mailimf_sender_free(sender);
7320 if (reply_to != NULL)
7321 mailimf_reply_to_free(reply_to);
7323 mailimf_to_free(to);
7325 mailimf_cc_free(cc);
7327 mailimf_bcc_free(bcc);
7328 if (message_id != NULL)
7329 mailimf_message_id_free(message_id);
7330 if (in_reply_to != NULL)
7331 mailimf_in_reply_to_free(in_reply_to);
7332 if (references != NULL)
7333 mailimf_references_free(references);
7334 if (subject != NULL)
7335 mailimf_subject_free(subject);
7340 int mailimf_envelope_fields_parse(const char * message, size_t length,
7342 struct mailimf_fields ** result)
7346 struct mailimf_fields * fields;
7350 cur_token = * index;
7354 res = MAILIMF_ERROR_MEMORY;
7359 struct mailimf_field * elt;
7361 r = mailimf_envelope_field_parse(message, length, &cur_token, &elt);
7362 if (r == MAILIMF_NO_ERROR) {
7363 r = clist_append(list, elt);
7365 res = MAILIMF_ERROR_MEMORY;
7369 else if (r == MAILIMF_ERROR_PARSE) {
7370 r = mailimf_ignore_field_parse(message, length, &cur_token);
7371 if (r == MAILIMF_NO_ERROR) {
7374 else if (r == MAILIMF_ERROR_PARSE) {
7388 fields = mailimf_fields_new(list);
7389 if (fields == NULL) {
7390 res = MAILIMF_ERROR_MEMORY;
7395 * index = cur_token;
7397 return MAILIMF_NO_ERROR;
7401 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7410 mailimf_envelope_or_optional_field_parse(const char * message,
7413 struct mailimf_field ** result)
7417 struct mailimf_optional_field * optional_field;
7418 struct mailimf_field * field;
7420 r = mailimf_envelope_field_parse(message, length, index, result);
7421 if (r == MAILIMF_NO_ERROR)
7422 return MAILIMF_NO_ERROR;
7424 cur_token = * index;
7426 r = mailimf_optional_field_parse(message, length, &cur_token,
7428 if (r != MAILIMF_NO_ERROR)
7431 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL,
7436 NULL, NULL, NULL, NULL, NULL,
7437 NULL, NULL, NULL, optional_field);
7438 if (field == NULL) {
7439 mailimf_optional_field_free(optional_field);
7440 return MAILIMF_ERROR_MEMORY;
7444 * index = cur_token;
7446 return MAILIMF_NO_ERROR;
7451 mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
7453 struct mailimf_fields ** result)
7457 struct mailimf_fields * fields;
7461 cur_token = * index;
7465 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7467 (mailimf_struct_parser *)
7468 mailimf_envelope_or_optional_field_parse,
7469 (mailimf_struct_destructor *)
7470 mailimf_field_free);
7472 case MAILIMF_NO_ERROR:
7476 case MAILIMF_ERROR_PARSE:
7479 res = MAILIMF_ERROR_MEMORY;
7489 fields = mailimf_fields_new(list);
7490 if (fields == NULL) {
7491 res = MAILIMF_ERROR_MEMORY;
7496 * index = cur_token;
7498 return MAILIMF_NO_ERROR;
7502 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7512 mailimf_only_optional_field_parse(const char * message,
7515 struct mailimf_field ** result)
7519 struct mailimf_optional_field * optional_field;
7520 struct mailimf_field * field;
7522 cur_token = * index;
7524 r = mailimf_optional_field_parse(message, length, &cur_token,
7526 if (r != MAILIMF_NO_ERROR)
7529 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL,
7530 NULL, NULL, NULL, NULL, NULL,
7531 NULL, NULL, NULL, NULL, NULL,
7532 NULL, NULL, NULL, NULL, NULL,
7533 NULL, NULL, NULL, optional_field);
7534 if (field == NULL) {
7535 mailimf_optional_field_free(optional_field);
7536 return MAILIMF_ERROR_MEMORY;
7540 * index = cur_token;
7542 return MAILIMF_NO_ERROR;
7547 mailimf_optional_fields_parse(const char * message, size_t length,
7549 struct mailimf_fields ** result)
7553 struct mailimf_fields * fields;
7557 cur_token = * index;
7561 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7563 (mailimf_struct_parser *)
7564 mailimf_only_optional_field_parse,
7565 (mailimf_struct_destructor *)
7566 mailimf_field_free);
7568 case MAILIMF_NO_ERROR:
7572 case MAILIMF_ERROR_PARSE:
7575 res = MAILIMF_ERROR_MEMORY;
7585 fields = mailimf_fields_new(list);
7586 if (fields == NULL) {
7587 res = MAILIMF_ERROR_MEMORY;
7592 * index = cur_token;
7594 return MAILIMF_NO_ERROR;
7598 clist_foreach(list, (clist_func) mailimf_field_free, NULL);