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;
2988 cur_token = * index;
2990 mailbox_list = NULL;
2992 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
2993 if (r != MAILIMF_NO_ERROR) {
2998 r = mailimf_colon_parse(message, length, &cur_token);
2999 if (r != MAILIMF_NO_ERROR) {
3001 goto free_display_name;
3004 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list);
3006 case MAILIMF_NO_ERROR:
3008 case MAILIMF_ERROR_PARSE:
3009 r = mailimf_cfws_parse(message, length, &cur_token);
3010 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3012 goto free_display_name;
3017 goto free_display_name;
3020 r = mailimf_semi_colon_parse(message, length, &cur_token);
3021 if (r != MAILIMF_NO_ERROR) {
3023 goto free_mailbox_list;
3026 group = mailimf_group_new(display_name, mailbox_list);
3027 if (group == NULL) {
3028 res = MAILIMF_ERROR_MEMORY;
3029 goto free_mailbox_list;
3032 * index = cur_token;
3035 return MAILIMF_NO_ERROR;
3038 mailimf_mailbox_list_free(mailbox_list);
3040 mailimf_display_name_free(display_name);
3046 display-name = phrase
3049 static int mailimf_display_name_parse(const char * message, size_t length,
3050 size_t * index, char ** result)
3052 return mailimf_phrase_parse(message, length, index, result);
3056 mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
3060 mailimf_mailbox_list_parse(const char * message, size_t length,
3062 struct mailimf_mailbox_list ** result)
3066 struct mailimf_mailbox_list * mailbox_list;
3070 cur_token = * index;
3072 r = mailimf_struct_list_parse(message, length,
3073 &cur_token, &list, ',',
3074 (mailimf_struct_parser *)
3075 mailimf_mailbox_parse,
3076 (mailimf_struct_destructor *)
3077 mailimf_mailbox_free);
3078 if (r != MAILIMF_NO_ERROR) {
3083 mailbox_list = mailimf_mailbox_list_new(list);
3084 if (mailbox_list == NULL) {
3085 res = MAILIMF_ERROR_MEMORY;
3089 * result = mailbox_list;
3090 * index = cur_token;
3092 return MAILIMF_NO_ERROR;
3095 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
3102 address-list = (address *("," address)) / obs-addr-list
3107 mailimf_address_list_parse(const char * message, size_t length,
3109 struct mailimf_address_list ** result)
3113 struct mailimf_address_list * address_list;
3117 cur_token = * index;
3119 r = mailimf_struct_list_parse(message, length,
3120 &cur_token, &list, ',',
3121 (mailimf_struct_parser *)
3122 mailimf_address_parse,
3123 (mailimf_struct_destructor *)
3124 mailimf_address_free);
3125 if (r != MAILIMF_NO_ERROR) {
3130 address_list = mailimf_address_list_new(list);
3131 if (address_list == NULL) {
3132 res = MAILIMF_ERROR_MEMORY;
3136 * result = address_list;
3137 * index = cur_token;
3139 return MAILIMF_NO_ERROR;
3142 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
3149 addr-spec = local-part "@" domain
3153 static int mailimf_addr_spec_parse(const char * message, size_t length,
3173 cur_token = * index;
3175 r = mailimf_cfws_parse(message, length, &cur_token);
3176 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3182 if (end >= length) {
3183 res = MAILIMF_ERROR_PARSE;
3191 switch (message[end]) {
3213 res = MAILIMF_ERROR_PARSE;
3217 addr_spec = malloc(end - cur_token + 1);
3218 if (addr_spec == NULL) {
3219 res = MAILIMF_ERROR_MEMORY;
3223 count = end - cur_token;
3224 src = message + cur_token;
3226 for(i = 0 ; i < count ; i ++) {
3227 if ((* src != ' ') && (* src != '\t')) {
3236 strncpy(addr_spec, message + cur_token, end - cur_token);
3237 addr_spec[end - cur_token] = '\0';
3243 r = mailimf_local_part_parse(message, length, &cur_token, &local_part);
3244 if (r != MAILIMF_NO_ERROR) {
3249 r = mailimf_at_sign_parse(message, length, &cur_token);
3251 case MAILIMF_NO_ERROR:
3252 r = mailimf_domain_parse(message, length, &cur_token, &domain);
3253 if (r != MAILIMF_NO_ERROR) {
3255 goto free_local_part;
3259 case MAILIMF_ERROR_PARSE:
3265 goto free_local_part;
3269 addr_spec = malloc(strlen(local_part) + strlen(domain) + 2);
3270 if (addr_spec == NULL) {
3271 res = MAILIMF_ERROR_MEMORY;
3275 strcpy(addr_spec, local_part);
3276 strcat(addr_spec, "@");
3277 strcat(addr_spec, domain);
3279 mailimf_domain_free(domain);
3280 mailimf_local_part_free(local_part);
3283 addr_spec = local_part;
3287 * result = addr_spec;
3288 * index = cur_token;
3290 return MAILIMF_NO_ERROR;
3294 mailimf_domain_free(domain);
3296 mailimf_local_part_free(local_part);
3303 local-part = dot-atom / quoted-string / obs-local-part
3307 static int mailimf_local_part_parse(const char * message, size_t length,
3313 r = mailimf_dot_atom_parse(message, length, index, result);
3315 case MAILIMF_NO_ERROR:
3317 case MAILIMF_ERROR_PARSE:
3323 r = mailimf_quoted_string_parse(message, length, index, result);
3324 if (r != MAILIMF_NO_ERROR)
3327 return MAILIMF_NO_ERROR;
3332 domain = dot-atom / domain-literal / obs-domain
3336 static int mailimf_domain_parse(const char * message, size_t length,
3342 r = mailimf_dot_atom_parse(message, length, index, result);
3344 case MAILIMF_NO_ERROR:
3346 case MAILIMF_ERROR_PARSE:
3352 r = mailimf_domain_literal_parse(message, length, index, result);
3353 if (r != MAILIMF_NO_ERROR)
3356 return MAILIMF_NO_ERROR;
3366 mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length,
3373 cur_token = * index;
3375 r = mailimf_cfws_parse(message, length, &cur_token);
3376 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3379 r = mailimf_dcontent_parse(message, length, &cur_token, &ch);
3380 if (r != MAILIMF_NO_ERROR)
3383 * index = cur_token;
3385 return MAILIMF_NO_ERROR;
3390 domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
3394 static int mailimf_domain_literal_parse(const char * message, size_t length,
3395 size_t * index, char ** result)
3400 char * domain_literal;
3403 cur_token = * index;
3405 r = mailimf_cfws_parse(message, length, &cur_token);
3406 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3410 r = mailimf_obracket_parse(message, length, &cur_token);
3411 if (r != MAILIMF_NO_ERROR)
3415 r = mailimf_domain_literal_fws_dcontent_parse(message, length,
3417 if (r == MAILIMF_NO_ERROR) {
3420 else if (r == MAILIMF_ERROR_PARSE)
3426 r = mailimf_fws_parse(message, length, &cur_token);
3427 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3430 r = mailimf_cbracket_parse(message, length, &cur_token);
3431 if (r != MAILIMF_NO_ERROR)
3434 len = cur_token - begin;
3436 domain_literal = malloc(len + 1);
3437 if (domain_literal == NULL)
3438 return MAILIMF_ERROR_MEMORY;
3439 strncpy(domain_literal, message + begin, len);
3440 domain_literal[len] = '\0';
3442 * result = domain_literal;
3443 * index = cur_token;
3445 return MAILIMF_NO_ERROR;
3450 dcontent = dtext / quoted-pair
3454 static int mailimf_dcontent_parse(const char * message, size_t length,
3455 size_t * index, char * result)
3461 cur_token = * index;
3463 if (cur_token >= length)
3464 return MAILIMF_ERROR_PARSE;
3466 if (is_dtext(message[cur_token])) {
3467 ch = message[cur_token];
3471 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
3473 if (r != MAILIMF_NO_ERROR)
3477 * index = cur_token;
3480 return MAILIMF_NO_ERROR;
3486 dtext = NO-WS-CTL / ; Non white space controls
3488 %d33-90 / ; The rest of the US-ASCII
3489 %d94-126 ; characters not including "[",
3493 static inline int is_dtext(char ch)
3495 unsigned char uch = (unsigned char) ch;
3497 if (is_no_ws_ctl(ch))
3503 if ((uch >= 91) && (uch <= 93))
3513 message = (fields / obs-fields)
3517 int mailimf_message_parse(const char * message, size_t length,
3519 struct mailimf_message ** result)
3521 struct mailimf_fields * fields;
3522 struct mailimf_body * body;
3523 struct mailimf_message * msg;
3528 cur_token = * index;
3530 r = mailimf_fields_parse(message, length, &cur_token, &fields);
3531 if (r != MAILIMF_NO_ERROR) {
3536 r = mailimf_crlf_parse(message, length, &cur_token);
3537 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3542 r = mailimf_body_parse(message, length, &cur_token, &body);
3543 if (r != MAILIMF_NO_ERROR) {
3548 msg = mailimf_message_new(fields, body);
3550 res = MAILIMF_ERROR_MEMORY;
3554 * index = cur_token;
3557 return MAILIMF_NO_ERROR;
3560 mailimf_body_free(body);
3562 mailimf_fields_free(fields);
3568 body = *(*998text CRLF) *998text
3571 int mailimf_body_parse(const char * message, size_t length,
3573 struct mailimf_body ** result)
3576 struct mailimf_body * body;
3578 cur_token = * index;
3580 body = mailimf_body_new(message + cur_token, length - cur_token);
3582 return MAILIMF_ERROR_MEMORY;
3587 * index = cur_token;
3589 return MAILIMF_NO_ERROR;
3593 CHANGE TO THE RFC 2822
3620 INTO THE FOLLOWING :
3624 resent-fields-list = *(resent-date /
3635 RESENT_HEADER_START,
3638 static int guess_resent_header_type(char * message,
3639 size_t length, size_t index)
3643 r = mailimf_token_case_insensitive_parse(message,
3644 length, &index, "Resent-");
3645 if (r != MAILIMF_NO_ERROR)
3646 return MAILIMF_RESENT_FIELD_NONE;
3648 if (index >= length)
3649 return MAILIMF_RESENT_FIELD_NONE;
3651 switch(toupper(message[index])) {
3653 return MAILIMF_RESENT_FIELD_DATE;
3655 return MAILIMF_RESENT_FIELD_FROM;
3657 return MAILIMF_RESENT_FIELD_SENDER;
3659 return MAILIMF_RESENT_FIELD_TO;
3661 return MAILIMF_RESENT_FIELD_CC;
3663 return MAILIMF_RESENT_FIELD_BCC;
3665 return MAILIMF_RESENT_FIELD_MSG_ID;
3667 return MAILIMF_RESENT_FIELD_NONE;
3674 mailimf_resent_field_parse(const char * message, size_t length,
3676 struct mailimf_resent_field ** result)
3678 struct mailimf_orig_date * resent_date;
3679 struct mailimf_from * resent_from;
3680 struct mailimf_sender * resent_sender;
3681 struct mailimf_to* resent_to;
3682 struct mailimf_cc * resent_cc;
3683 struct mailimf_bcc * resent_bcc;
3684 struct mailimf_message_id * resent_msg_id;
3687 struct mailimf_resent_field * resent_field;
3691 cur_token = * index;
3695 resent_sender = NULL;
3699 resent_msg_id = NULL;
3701 type = guess_resent_header_type(message, length, cur_token);
3704 case MAILIMF_RESENT_FIELD_DATE:
3705 r = mailimf_resent_date_parse(message, length, &cur_token,
3707 if (r != MAILIMF_NO_ERROR) {
3712 case MAILIMF_RESENT_FIELD_FROM:
3713 r = mailimf_resent_from_parse(message, length, &cur_token,
3715 if (r != MAILIMF_NO_ERROR) {
3720 case MAILIMF_RESENT_FIELD_SENDER:
3721 r = mailimf_resent_sender_parse(message, length, &cur_token,
3723 if (r != MAILIMF_NO_ERROR) {
3728 case MAILIMF_RESENT_FIELD_TO:
3729 r = mailimf_resent_to_parse(message, length, &cur_token,
3731 if (r != MAILIMF_NO_ERROR) {
3736 case MAILIMF_RESENT_FIELD_CC:
3737 r= mailimf_resent_cc_parse(message, length, &cur_token,
3739 if (r != MAILIMF_NO_ERROR) {
3744 case MAILIMF_RESENT_FIELD_BCC:
3745 r = mailimf_resent_bcc_parse(message, length, &cur_token,
3747 if (r != MAILIMF_NO_ERROR) {
3752 case MAILIMF_RESENT_FIELD_MSG_ID:
3753 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
3755 if (r != MAILIMF_NO_ERROR) {
3761 res = MAILIMF_ERROR_PARSE;
3765 resent_field = mailimf_resent_field_new(type, resent_date,
3766 resent_from, resent_sender,
3767 resent_to, resent_cc,
3768 resent_bcc, resent_msg_id);
3769 if (resent_field == NULL) {
3770 res = MAILIMF_ERROR_MEMORY;
3774 * result = resent_field;
3775 * index = cur_token;
3777 return MAILIMF_NO_ERROR;
3780 if (resent_msg_id != NULL)
3781 mailimf_message_id_free(resent_msg_id);
3782 if (resent_bcc != NULL)
3783 mailimf_bcc_free(resent_bcc);
3784 if (resent_cc != NULL)
3785 mailimf_cc_free(resent_cc);
3786 if (resent_to != NULL)
3787 mailimf_to_free(resent_to);
3788 if (resent_sender != NULL)
3789 mailimf_sender_free(resent_sender);
3790 if (resent_from != NULL)
3791 mailimf_from_free(resent_from);
3792 if (resent_date != NULL)
3793 mailimf_orig_date_free(resent_date);
3801 mailimf_resent_fields_list_parse(const char * message, size_t length,
3803 struct mailimf_resent_fields_list ** result)
3807 struct mailimf_resent_fields_list * resent_fields_list;
3811 cur_token = * index;
3814 r = mailimf_struct_multiple_parse(message, length, &cur_token, &list,
3815 (mailimf_struct_parser *)
3816 mailimf_resent_field_parse,
3817 (mailimf_struct_destructor *)
3818 mailimf_resent_field_free);
3819 if (r != MAILIMF_NO_ERROR) {
3824 resent_fields_list = mailimf_resent_fields_list_new(list);
3825 if (resent_fields_list == NULL) {
3826 res = MAILIMF_ERROR_MEMORY;
3830 * result = resent_fields_list;
3831 * index = cur_token;
3833 return MAILIMF_NO_ERROR;
3836 clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL);
3845 [resent-fields-list])
3850 mailimf_trace_resent_fields_parse(const char * message, size_t length,
3852 struct mailimf_trace_resent_fields ** result)
3855 struct mailimf_return * return_path;
3856 struct mailimf_resent_fields_list * resent_fields;
3857 struct mailimf_trace_resent_fields * trace_resent_fields;
3861 cur_token = * index;
3864 resent_fields = NULL;
3866 r = mailimf_return_parse(message, length, &cur_token,
3868 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3873 r = mailimf_resent_fields_list_parse(message, length, &cur_token,
3875 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3880 if ((return_path == NULL) && (resent_fields == NULL)) {
3881 res = MAILIMF_ERROR_PARSE;
3885 trace_resent_fields = mailimf_trace_resent_fields_new(return_path,
3887 if (trace_resent_fields == NULL) {
3888 res = MAILIMF_ERROR_MEMORY;
3889 goto free_resent_fields;
3892 * result = trace_resent_fields;
3893 * index = cur_token;
3895 return MAILIMF_NO_ERROR;
3898 if (resent_fields != NULL)
3899 mailimf_resent_fields_list_free(resent_fields);
3900 if (return_path != NULL)
3901 mailimf_return_free(return_path);
3908 delivering-info = *([trace]
3909 [resent-fields-list])
3914 mailimf_delivering_info_parse(const char * message, size_t length,
3916 struct mailimf_delivering_info ** result)
3920 struct mailimf_delivering_info * delivering_info;
3924 cur_token = * index;
3926 r = mailimf_struct_multiple_parse(message, length, &cur_token,
3928 (mailimf_struct_parser *)
3929 mailimf_trace_resent_fields_parse,
3930 (mailimf_struct_destructor *)
3931 mailimf_trace_resent_fields_free);
3932 if (r != MAILIMF_NO_ERROR) {
3937 delivering_info = mailimf_delivering_info_new(list);
3938 if (delivering_info == NULL) {
3939 res = MAILIMF_ERROR_MEMORY;
3943 * result = delivering_info;
3944 * index = cur_token;
3946 return MAILIMF_NO_ERROR;
3949 clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL);
3957 field = delivering-info /
3983 static int guess_header_type(const char * message, size_t length, size_t index)
3988 state = HEADER_START;
3992 if (index >= length)
3993 return MAILIMF_FIELD_NONE;
3997 switch((char) toupper((unsigned char) message[index])) {
3999 return MAILIMF_FIELD_BCC;
4004 return MAILIMF_FIELD_ORIG_DATE;
4006 return MAILIMF_FIELD_FROM;
4008 return MAILIMF_FIELD_IN_REPLY_TO;
4010 return MAILIMF_FIELD_KEYWORDS;
4012 return MAILIMF_FIELD_MESSAGE_ID;
4017 return MAILIMF_FIELD_TO;
4023 return MAILIMF_FIELD_NONE;
4027 switch((char) toupper((unsigned char) message[index])) {
4029 return MAILIMF_FIELD_COMMENTS;
4031 return MAILIMF_FIELD_CC;
4033 return MAILIMF_FIELD_NONE;
4037 switch((char) toupper((unsigned char) message[index])) {
4042 return MAILIMF_FIELD_NONE;
4046 switch((char) toupper((unsigned char) message[index])) {
4048 return MAILIMF_FIELD_REFERENCES;
4050 return MAILIMF_FIELD_REPLY_TO;
4055 return MAILIMF_FIELD_RETURN_PATH;
4057 return MAILIMF_FIELD_NONE;
4061 switch((char) toupper((unsigned char) message[index])) {
4063 return MAILIMF_FIELD_SENDER;
4065 return MAILIMF_FIELD_SUBJECT;
4067 return MAILIMF_FIELD_NONE;
4072 r = mailimf_token_case_insensitive_parse(message,
4073 length, &index, "ent-");
4074 if (r != MAILIMF_NO_ERROR)
4075 return MAILIMF_FIELD_NONE;
4077 if (index >= length)
4078 return MAILIMF_FIELD_NONE;
4080 switch((char) toupper((unsigned char) message[index])) {
4082 return MAILIMF_FIELD_RESENT_DATE;
4084 return MAILIMF_FIELD_RESENT_FROM;
4086 return MAILIMF_FIELD_RESENT_SENDER;
4088 return MAILIMF_FIELD_RESENT_TO;
4090 return MAILIMF_FIELD_RESENT_CC;
4092 return MAILIMF_FIELD_RESENT_BCC;
4094 return MAILIMF_FIELD_RESENT_MSG_ID;
4096 return MAILIMF_FIELD_NONE;
4104 static int mailimf_field_parse(const char * message, size_t length,
4106 struct mailimf_field ** result)
4110 struct mailimf_return * return_path;
4111 struct mailimf_orig_date * resent_date;
4112 struct mailimf_from * resent_from;
4113 struct mailimf_sender * resent_sender;
4114 struct mailimf_to* resent_to;
4115 struct mailimf_cc * resent_cc;
4116 struct mailimf_bcc * resent_bcc;
4117 struct mailimf_message_id * resent_msg_id;
4118 struct mailimf_orig_date * orig_date;
4119 struct mailimf_from * from;
4120 struct mailimf_sender * sender;
4121 struct mailimf_reply_to * reply_to;
4122 struct mailimf_to * to;
4123 struct mailimf_cc * cc;
4124 struct mailimf_bcc * bcc;
4125 struct mailimf_message_id * message_id;
4126 struct mailimf_in_reply_to * in_reply_to;
4127 struct mailimf_references * references;
4128 struct mailimf_subject * subject;
4129 struct mailimf_comments * comments;
4130 struct mailimf_keywords * keywords;
4131 struct mailimf_optional_field * optional_field;
4132 struct mailimf_field * field;
4137 cur_token = * index;
4142 resent_sender = NULL;
4146 resent_msg_id = NULL;
4160 optional_field = NULL;
4162 guessed_type = guess_header_type(message, length, cur_token);
4163 type = MAILIMF_FIELD_NONE;
4165 switch (guessed_type) {
4166 case MAILIMF_FIELD_ORIG_DATE:
4167 r = mailimf_orig_date_parse(message, length, &cur_token,
4169 if (r == MAILIMF_NO_ERROR)
4170 type = MAILIMF_FIELD_ORIG_DATE;
4171 else if (r == MAILIMF_ERROR_PARSE) {
4179 case MAILIMF_FIELD_FROM:
4180 r = mailimf_from_parse(message, length, &cur_token,
4182 if (r == MAILIMF_NO_ERROR)
4183 type = guessed_type;
4184 else if (r == MAILIMF_ERROR_PARSE) {
4192 case MAILIMF_FIELD_SENDER:
4193 r = mailimf_sender_parse(message, length, &cur_token,
4195 if (r == MAILIMF_NO_ERROR)
4196 type = guessed_type;
4197 else if (r == MAILIMF_ERROR_PARSE) {
4205 case MAILIMF_FIELD_REPLY_TO:
4206 r = mailimf_reply_to_parse(message, length, &cur_token,
4208 if (r == MAILIMF_NO_ERROR)
4209 type = guessed_type;
4210 else if (r == MAILIMF_ERROR_PARSE) {
4218 case MAILIMF_FIELD_TO:
4219 r = mailimf_to_parse(message, length, &cur_token,
4221 if (r == MAILIMF_NO_ERROR)
4222 type = guessed_type;
4223 else if (r == MAILIMF_ERROR_PARSE) {
4231 case MAILIMF_FIELD_CC:
4232 r = mailimf_cc_parse(message, length, &cur_token,
4234 if (r == MAILIMF_NO_ERROR)
4235 type = guessed_type;
4236 else if (r == MAILIMF_ERROR_PARSE) {
4244 case MAILIMF_FIELD_BCC:
4245 r = mailimf_bcc_parse(message, length, &cur_token,
4247 if (r == MAILIMF_NO_ERROR)
4248 type = guessed_type;
4249 else if (r == MAILIMF_ERROR_PARSE) {
4257 case MAILIMF_FIELD_MESSAGE_ID:
4258 r = mailimf_message_id_parse(message, length, &cur_token,
4260 if (r == MAILIMF_NO_ERROR)
4261 type = guessed_type;
4262 else if (r == MAILIMF_ERROR_PARSE) {
4270 case MAILIMF_FIELD_IN_REPLY_TO:
4271 r = mailimf_in_reply_to_parse(message, length, &cur_token,
4273 if (r == MAILIMF_NO_ERROR)
4274 type = guessed_type;
4275 else if (r == MAILIMF_ERROR_PARSE) {
4283 case MAILIMF_FIELD_REFERENCES:
4284 r = mailimf_references_parse(message, length, &cur_token,
4286 if (r == MAILIMF_NO_ERROR)
4287 type = guessed_type;
4288 else if (r == MAILIMF_ERROR_PARSE) {
4296 case MAILIMF_FIELD_SUBJECT:
4297 r = mailimf_subject_parse(message, length, &cur_token,
4299 if (r == MAILIMF_NO_ERROR)
4300 type = guessed_type;
4301 else if (r == MAILIMF_ERROR_PARSE) {
4309 case MAILIMF_FIELD_COMMENTS:
4310 r = mailimf_comments_parse(message, length, &cur_token,
4312 if (r == MAILIMF_NO_ERROR)
4313 type = guessed_type;
4314 else if (r == MAILIMF_ERROR_PARSE) {
4322 case MAILIMF_FIELD_KEYWORDS:
4323 r = mailimf_keywords_parse(message, length, &cur_token,
4325 if (r == MAILIMF_NO_ERROR)
4326 type = guessed_type;
4327 else if (r == MAILIMF_ERROR_PARSE) {
4335 case MAILIMF_FIELD_RETURN_PATH:
4336 r = mailimf_return_parse(message, length, &cur_token,
4338 if (r == MAILIMF_NO_ERROR)
4339 type = guessed_type;
4340 else if (r == MAILIMF_ERROR_PARSE) {
4348 case MAILIMF_FIELD_RESENT_DATE:
4349 r = mailimf_resent_date_parse(message, length, &cur_token,
4351 if (r == MAILIMF_NO_ERROR)
4352 type = guessed_type;
4353 else if (r == MAILIMF_ERROR_PARSE) {
4361 case MAILIMF_FIELD_RESENT_FROM:
4362 r = mailimf_resent_from_parse(message, length, &cur_token,
4364 if (r == MAILIMF_NO_ERROR)
4365 type = guessed_type;
4366 else if (r == MAILIMF_ERROR_PARSE) {
4374 case MAILIMF_FIELD_RESENT_SENDER:
4375 r = mailimf_resent_sender_parse(message, length, &cur_token,
4377 if (r == MAILIMF_NO_ERROR)
4378 type = guessed_type;
4379 else if (r == MAILIMF_ERROR_PARSE) {
4387 case MAILIMF_FIELD_RESENT_TO:
4388 r = mailimf_resent_to_parse(message, length, &cur_token,
4390 if (r == MAILIMF_NO_ERROR)
4391 type = guessed_type;
4392 else if (r == MAILIMF_ERROR_PARSE) {
4400 case MAILIMF_FIELD_RESENT_CC:
4401 r= mailimf_resent_cc_parse(message, length, &cur_token,
4403 if (r == MAILIMF_NO_ERROR)
4404 type = guessed_type;
4405 else if (r == MAILIMF_ERROR_PARSE) {
4413 case MAILIMF_FIELD_RESENT_BCC:
4414 r = mailimf_resent_bcc_parse(message, length, &cur_token,
4416 if (r == MAILIMF_NO_ERROR)
4417 type = guessed_type;
4418 else if (r == MAILIMF_ERROR_PARSE) {
4426 case MAILIMF_FIELD_RESENT_MSG_ID:
4427 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
4429 if (r == MAILIMF_NO_ERROR)
4430 type = guessed_type;
4431 else if (r == MAILIMF_ERROR_PARSE) {
4441 if (type == MAILIMF_FIELD_NONE) {
4442 r = mailimf_optional_field_parse(message, length, &cur_token,
4444 if (r != MAILIMF_NO_ERROR) {
4449 type = MAILIMF_FIELD_OPTIONAL_FIELD;
4452 field = mailimf_field_new(type, return_path, resent_date,
4453 resent_from, resent_sender, resent_to, resent_cc, resent_bcc,
4454 resent_msg_id, orig_date, from, sender, reply_to, to,
4455 cc, bcc, message_id, in_reply_to, references,
4456 subject, comments, keywords, optional_field);
4457 if (field == NULL) {
4458 res = MAILIMF_ERROR_MEMORY;
4463 * index = cur_token;
4465 return MAILIMF_NO_ERROR;
4468 if (return_path != NULL)
4469 mailimf_return_free(return_path);
4470 if (resent_date != NULL)
4471 mailimf_orig_date_free(resent_date);
4472 if (resent_from != NULL)
4473 mailimf_from_free(resent_from);
4474 if (resent_sender != NULL)
4475 mailimf_sender_free(resent_sender);
4476 if (resent_to != NULL)
4477 mailimf_to_free(resent_to);
4478 if (resent_cc != NULL)
4479 mailimf_cc_free(resent_cc);
4480 if (resent_bcc != NULL)
4481 mailimf_bcc_free(resent_bcc);
4482 if (resent_msg_id != NULL)
4483 mailimf_message_id_free(resent_msg_id);
4484 if (orig_date != NULL)
4485 mailimf_orig_date_free(orig_date);
4487 mailimf_from_free(from);
4489 mailimf_sender_free(sender);
4490 if (reply_to != NULL)
4491 mailimf_reply_to_free(reply_to);
4493 mailimf_to_free(to);
4495 mailimf_cc_free(cc);
4497 mailimf_bcc_free(bcc);
4498 if (message_id != NULL)
4499 mailimf_message_id_free(message_id);
4500 if (in_reply_to != NULL)
4501 mailimf_in_reply_to_free(in_reply_to);
4502 if (references != NULL)
4503 mailimf_references_free(references);
4504 if (subject != NULL)
4505 mailimf_subject_free(subject);
4506 if (comments != NULL)
4507 mailimf_comments_free(comments);
4508 if (keywords != NULL)
4509 mailimf_keywords_free(keywords);
4510 if (optional_field != NULL)
4511 mailimf_optional_field_free(optional_field);
4518 fields = *(delivering-info /
4537 mailimf_unparsed_fields_parse(const char * message, size_t length,
4539 struct mailimf_unparsed_fields ** result)
4543 struct mailimf_unparsed_fields * fields;
4547 cur_token = * index;
4551 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4553 (mailimf_struct_parser *)
4554 mailimf_optional_field_parse,
4555 (mailimf_struct_destructor *)
4556 mailimf_optional_field_free);
4558 if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4565 case MAILIMF_NO_ERROR:
4569 case MAILIMF_ERROR_PARSE:
4572 res = MAILIMF_ERROR_MEMORY;
4582 fields = mailimf_unparsed_fields_new(list);
4583 if (fields == NULL) {
4584 res = MAILIMF_ERROR_MEMORY;
4589 * index = cur_token;
4591 return MAILIMF_NO_ERROR;
4595 clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL);
4603 int mailimf_fields_parse(const char * message, size_t length,
4605 struct mailimf_fields ** result)
4609 struct mailimf_fields * fields;
4613 cur_token = * index;
4617 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4619 (mailimf_struct_parser *)
4620 mailimf_field_parse,
4621 (mailimf_struct_destructor *)
4622 mailimf_field_free);
4624 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4631 case MAILIMF_NO_ERROR:
4635 case MAILIMF_ERROR_PARSE:
4638 res = MAILIMF_ERROR_MEMORY;
4648 fields = mailimf_fields_new(list);
4649 if (fields == NULL) {
4650 res = MAILIMF_ERROR_MEMORY;
4655 * index = cur_token;
4657 return MAILIMF_NO_ERROR;
4661 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
4669 orig-date = "Date:" date-time CRLF
4674 mailimf_orig_date_parse(const char * message, size_t length,
4675 size_t * index, struct mailimf_orig_date ** result)
4677 struct mailimf_date_time * date_time;
4678 struct mailimf_orig_date * orig_date;
4683 cur_token = * index;
4685 r = mailimf_token_case_insensitive_parse(message, length,
4686 &cur_token, "Date:");
4687 if (r != MAILIMF_NO_ERROR) {
4692 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
4693 if (r != MAILIMF_NO_ERROR) {
4698 r = mailimf_ignore_unstructured_parse(message, length, &cur_token);
4699 if (r != MAILIMF_NO_ERROR) {
4701 goto free_date_time;
4704 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4705 if (r != MAILIMF_NO_ERROR) {
4707 goto free_date_time;
4710 orig_date = mailimf_orig_date_new(date_time);
4711 if (orig_date == NULL) {
4712 res = MAILIMF_ERROR_MEMORY;
4713 goto free_date_time;
4716 * result = orig_date;
4717 * index = cur_token;
4719 return MAILIMF_NO_ERROR;
4722 mailimf_date_time_free(date_time);
4728 from = "From:" mailbox-list CRLF
4732 mailimf_from_parse(const char * message, size_t length,
4733 size_t * index, struct mailimf_from ** result)
4735 struct mailimf_mailbox_list * mb_list;
4736 struct mailimf_from * from;
4741 cur_token = * index;
4743 r = mailimf_token_case_insensitive_parse(message, length,
4744 &cur_token, "From");
4745 if (r != MAILIMF_NO_ERROR) {
4750 r = mailimf_colon_parse(message, length, &cur_token);
4751 if (r != MAILIMF_NO_ERROR) {
4756 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
4758 if (r != MAILIMF_NO_ERROR) {
4763 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4764 if (r != MAILIMF_NO_ERROR) {
4769 from = mailimf_from_new(mb_list);
4771 res = MAILIMF_ERROR_MEMORY;
4776 * index = cur_token;
4778 return MAILIMF_NO_ERROR;
4781 mailimf_mailbox_list_free(mb_list);
4787 sender = "Sender:" mailbox CRLF
4791 mailimf_sender_parse(const char * message, size_t length,
4792 size_t * index, struct mailimf_sender ** result)
4794 struct mailimf_mailbox * mb;
4795 struct mailimf_sender * sender;
4800 cur_token = * index;
4802 r = mailimf_token_case_insensitive_parse(message, length,
4803 &cur_token, "Sender");
4804 if (r != MAILIMF_NO_ERROR) {
4809 r = mailimf_colon_parse(message, length, &cur_token);
4810 if (r != MAILIMF_NO_ERROR) {
4815 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
4816 if (r != MAILIMF_NO_ERROR) {
4821 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4822 if (r != MAILIMF_NO_ERROR) {
4827 sender = mailimf_sender_new(mb);
4828 if (sender == NULL) {
4829 res = MAILIMF_ERROR_MEMORY;
4834 * index = cur_token;
4836 return MAILIMF_NO_ERROR;
4839 mailimf_mailbox_free(mb);
4845 reply-to = "Reply-To:" address-list CRLF
4850 mailimf_reply_to_parse(const char * message, size_t length,
4851 size_t * index, struct mailimf_reply_to ** result)
4853 struct mailimf_address_list * addr_list;
4854 struct mailimf_reply_to * reply_to;
4859 cur_token = * index;
4861 r = mailimf_token_case_insensitive_parse(message, length,
4862 &cur_token, "Reply-To");
4863 if (r != MAILIMF_NO_ERROR) {
4868 r = mailimf_colon_parse(message, length, &cur_token);
4869 if (r != MAILIMF_NO_ERROR) {
4874 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4875 if (r != MAILIMF_NO_ERROR) {
4880 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4881 if (r != MAILIMF_NO_ERROR) {
4883 goto free_addr_list;
4886 reply_to = mailimf_reply_to_new(addr_list);
4887 if (reply_to == NULL) {
4888 res = MAILIMF_ERROR_MEMORY;
4889 goto free_addr_list;
4892 * result = reply_to;
4893 * index = cur_token;
4895 return MAILIMF_NO_ERROR;
4898 mailimf_address_list_free(addr_list);
4904 to = "To:" address-list CRLF
4908 mailimf_to_parse(const char * message, size_t length,
4909 size_t * index, struct mailimf_to ** result)
4911 struct mailimf_address_list * addr_list;
4912 struct mailimf_to * to;
4917 cur_token = * index;
4919 r = mailimf_token_case_insensitive_parse(message, length,
4921 if (r != MAILIMF_NO_ERROR) {
4926 r = mailimf_colon_parse(message, length, &cur_token);
4927 if (r != MAILIMF_NO_ERROR) {
4932 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4933 if (r != MAILIMF_NO_ERROR) {
4938 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4939 if (r != MAILIMF_NO_ERROR) {
4941 goto free_addr_list;
4944 to = mailimf_to_new(addr_list);
4946 res = MAILIMF_ERROR_MEMORY;
4947 goto free_addr_list;
4951 * index = cur_token;
4953 return MAILIMF_NO_ERROR;
4956 mailimf_address_list_free(addr_list);
4962 cc = "Cc:" address-list CRLF
4967 mailimf_cc_parse(const char * message, size_t length,
4968 size_t * index, struct mailimf_cc ** result)
4970 struct mailimf_address_list * addr_list;
4971 struct mailimf_cc * cc;
4976 cur_token = * index;
4978 r = mailimf_token_case_insensitive_parse(message, length,
4980 if (r != MAILIMF_NO_ERROR) {
4985 r = mailimf_colon_parse(message, length, &cur_token);
4986 if (r != MAILIMF_NO_ERROR) {
4991 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4992 if (r != MAILIMF_NO_ERROR) {
4997 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4998 if (r != MAILIMF_NO_ERROR) {
5000 goto free_addr_list;
5003 cc = mailimf_cc_new(addr_list);
5005 res = MAILIMF_ERROR_MEMORY;
5006 goto free_addr_list;
5010 * index = cur_token;
5012 return MAILIMF_NO_ERROR;
5015 mailimf_address_list_free(addr_list);
5021 bcc = "Bcc:" (address-list / [CFWS]) CRLF
5026 mailimf_bcc_parse(const char * message, size_t length,
5027 size_t * index, struct mailimf_bcc ** result)
5029 struct mailimf_address_list * addr_list;
5030 struct mailimf_bcc * bcc;
5035 cur_token = * index;
5038 r = mailimf_token_case_insensitive_parse(message, length,
5040 if (r != MAILIMF_NO_ERROR) {
5045 r = mailimf_colon_parse(message, length, &cur_token);
5046 if (r != MAILIMF_NO_ERROR) {
5051 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5053 case MAILIMF_NO_ERROR:
5056 case MAILIMF_ERROR_PARSE:
5057 r = mailimf_cfws_parse(message, length, &cur_token);
5058 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
5068 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5069 if (r != MAILIMF_NO_ERROR) {
5071 goto free_addr_list;
5074 bcc = mailimf_bcc_new(addr_list);
5076 res = MAILIMF_ERROR_MEMORY;
5077 goto free_addr_list;
5081 * index = cur_token;
5083 return MAILIMF_NO_ERROR;
5086 mailimf_address_list_free(addr_list);
5092 message-id = "Message-ID:" msg-id CRLF
5095 static int mailimf_message_id_parse(const char * message, size_t length,
5097 struct mailimf_message_id ** result)
5101 struct mailimf_message_id * message_id;
5105 cur_token = * index;
5107 r = mailimf_token_case_insensitive_parse(message, length,
5108 &cur_token, "Message-ID");
5109 if (r != MAILIMF_NO_ERROR) {
5114 r = mailimf_colon_parse(message, length, &cur_token);
5115 if (r != MAILIMF_NO_ERROR) {
5120 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
5121 if (r != MAILIMF_NO_ERROR) {
5126 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5127 if (r != MAILIMF_NO_ERROR) {
5132 message_id = mailimf_message_id_new(value);
5133 if (message_id == NULL) {
5134 res = MAILIMF_ERROR_MEMORY;
5138 * result = message_id;
5139 * index = cur_token;
5141 return MAILIMF_NO_ERROR;
5144 mailimf_msg_id_free(value);
5150 in-reply-to = "In-Reply-To:" 1*msg-id CRLF
5153 int mailimf_msg_id_list_parse(const char * message, size_t length,
5154 size_t * index, clist ** result)
5156 return mailimf_struct_multiple_parse(message, length, index,
5158 (mailimf_struct_parser *)
5159 mailimf_unstrict_msg_id_parse,
5160 (mailimf_struct_destructor *)
5161 mailimf_msg_id_free);
5164 static int mailimf_in_reply_to_parse(const char * message, size_t length,
5166 struct mailimf_in_reply_to ** result)
5168 struct mailimf_in_reply_to * in_reply_to;
5170 clist * msg_id_list;
5174 cur_token = * index;
5176 r = mailimf_token_case_insensitive_parse(message, length,
5177 &cur_token, "In-Reply-To");
5178 if (r != MAILIMF_NO_ERROR) {
5183 r = mailimf_colon_parse(message, length, &cur_token);
5184 if (r != MAILIMF_NO_ERROR) {
5189 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5190 if (r != MAILIMF_NO_ERROR) {
5195 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5196 if (r != MAILIMF_NO_ERROR) {
5201 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
5202 if (in_reply_to == NULL) {
5203 res = MAILIMF_ERROR_MEMORY;
5207 * result = in_reply_to;
5208 * index = cur_token;
5210 return MAILIMF_NO_ERROR;
5213 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5214 clist_free(msg_id_list);
5220 references = "References:" 1*msg-id CRLF
5223 int mailimf_references_parse(const char * message, size_t length,
5225 struct mailimf_references ** result)
5227 struct mailimf_references * references;
5229 clist * msg_id_list;
5233 cur_token = * index;
5235 r = mailimf_token_case_insensitive_parse(message, length,
5236 &cur_token, "References");
5237 if (r != MAILIMF_NO_ERROR) {
5242 r = mailimf_colon_parse(message, length, &cur_token);
5243 if (r != MAILIMF_NO_ERROR) {
5248 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5249 if (r != MAILIMF_NO_ERROR) {
5254 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5255 if (r != MAILIMF_NO_ERROR) {
5260 references = mailimf_references_new(msg_id_list);
5261 if (references == NULL) {
5262 res = MAILIMF_ERROR_MEMORY;
5266 * result = references;
5267 * index = cur_token;
5269 return MAILIMF_NO_ERROR;
5272 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5273 clist_free(msg_id_list);
5279 msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
5282 int mailimf_msg_id_parse(const char * message, size_t length,
5295 cur_token = * index;
5297 r = mailimf_cfws_parse(message, length, &cur_token);
5298 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5301 r = mailimf_lower_parse(message, length, &cur_token);
5302 if (r != MAILIMF_NO_ERROR) {
5307 r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id);
5308 if (r != MAILIMF_NO_ERROR) {
5313 r = mailimf_greater_parse(message, length, &cur_token);
5314 if (r != MAILIMF_NO_ERROR) {
5321 r = mailimf_id_left_parse(message, length, &cur_token, &id_left);
5322 if (r != MAILIMF_NO_ERROR) {
5327 r = mailimf_at_sign_parse(message, length, &cur_token);
5328 if (r != MAILIMF_NO_ERROR) {
5333 r = mailimf_id_right_parse(message, length, &cur_token, &id_right);
5334 if (r != MAILIMF_NO_ERROR) {
5339 r = mailimf_greater_parse(message, length, &cur_token);
5340 if (r != MAILIMF_NO_ERROR) {
5345 msg_id = malloc(strlen(id_left) + strlen(id_right) + 2);
5346 if (msg_id == NULL) {
5347 res = MAILIMF_ERROR_MEMORY;
5350 strcpy(msg_id, id_left);
5351 strcat(msg_id, "@");
5352 strcat(msg_id, id_right);
5354 mailimf_id_left_free(id_left);
5355 mailimf_id_right_free(id_right);
5359 * index = cur_token;
5361 return MAILIMF_NO_ERROR;
5365 mailimf_id_right_free(id_right);
5367 mailimf_id_left_free(id_left);
5371 mailimf_atom_free(msg_id);
5377 static int mailimf_parse_unwanted_msg_id(const char * message, size_t length,
5385 cur_token = * index;
5387 token_parsed = TRUE;
5388 while (token_parsed) {
5389 token_parsed = FALSE;
5390 r = mailimf_word_parse(message, length, &cur_token, &word);
5391 if (r == MAILIMF_NO_ERROR) {
5392 mailimf_word_free(word);
5393 token_parsed = TRUE;
5395 else if (r == MAILIMF_ERROR_PARSE) {
5400 r = mailimf_semi_colon_parse(message, length, &cur_token);
5401 if (r == MAILIMF_NO_ERROR)
5402 token_parsed = TRUE;
5403 else if (r == MAILIMF_ERROR_PARSE) {
5408 r = mailimf_comma_parse(message, length, &cur_token);
5409 if (r == MAILIMF_NO_ERROR)
5410 token_parsed = TRUE;
5411 else if (r == MAILIMF_ERROR_PARSE) {
5416 r = mailimf_plus_parse(message, length, &cur_token);
5417 if (r == MAILIMF_NO_ERROR)
5418 token_parsed = TRUE;
5419 else if (r == MAILIMF_ERROR_PARSE) {
5424 r = mailimf_colon_parse(message, length, &cur_token);
5425 if (r == MAILIMF_NO_ERROR)
5426 token_parsed = TRUE;
5427 else if (r == MAILIMF_ERROR_PARSE) {
5432 r = mailimf_point_parse(message, length, &cur_token);
5433 if (r == MAILIMF_NO_ERROR)
5434 token_parsed = TRUE;
5435 else if (r == MAILIMF_ERROR_PARSE) {
5440 r = mailimf_at_sign_parse(message, length, &cur_token);
5441 if (r == MAILIMF_NO_ERROR)
5442 token_parsed = TRUE;
5443 else if (r == MAILIMF_ERROR_PARSE) {
5450 return MAILIMF_NO_ERROR;
5453 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
5457 char * msgid = NULL;
5461 cur_token = * index;
5463 r = mailimf_cfws_parse(message, length, &cur_token);
5464 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5467 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5468 if (r != MAILIMF_NO_ERROR)
5471 r = mailimf_msg_id_parse(message, length, &cur_token, &msgid);
5472 if (r != MAILIMF_NO_ERROR)
5475 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5476 if (r != MAILIMF_NO_ERROR) {
5482 * index = cur_token;
5484 return MAILIMF_NO_ERROR;
5488 id-left = dot-atom-text / no-fold-quote / obs-id-left
5492 static int mailimf_id_left_parse(const char * message, size_t length,
5493 size_t * index, char ** result)
5497 r = mailimf_dot_atom_text_parse(message, length, index, result);
5499 case MAILIMF_NO_ERROR:
5500 return MAILIMF_NO_ERROR;
5501 case MAILIMF_ERROR_PARSE:
5507 r = mailimf_no_fold_quote_parse(message, length, index, result);
5508 if (r != MAILIMF_NO_ERROR)
5511 return MAILIMF_NO_ERROR;
5516 id-right = dot-atom-text / no-fold-literal / obs-id-right
5520 static int mailimf_id_right_parse(const char * message, size_t length,
5521 size_t * index, char ** result)
5525 r = mailimf_dot_atom_text_parse(message, length, index, result);
5527 case MAILIMF_NO_ERROR:
5528 return MAILIMF_NO_ERROR;
5529 case MAILIMF_ERROR_PARSE:
5535 r = mailimf_no_fold_literal_parse(message, length, index, result);
5536 if (r != MAILIMF_NO_ERROR)
5539 return MAILIMF_NO_ERROR;
5544 no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
5548 static int mailimf_no_fold_quote_char_parse(const char * message, size_t length,
5549 size_t * index, char * result)
5555 cur_token = * index;
5558 r = mailimf_qtext_parse(message, length, &cur_token, &ch);
5561 if (cur_token >= length)
5562 return MAILIMF_ERROR_PARSE;
5564 if (is_qtext(message[cur_token])) {
5565 ch = message[cur_token];
5569 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5571 if (r != MAILIMF_NO_ERROR)
5575 * index = cur_token;
5578 return MAILIMF_NO_ERROR;
5583 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
5584 size_t * index, char ** result)
5589 char * no_fold_quote;
5594 r = mailimf_dquote_parse(message, length, &cur_token);
5595 if (r != MAILIMF_NO_ERROR) {
5601 r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch);
5602 if (r == MAILIMF_NO_ERROR) {
5605 else if (r == MAILIMF_ERROR_PARSE)
5613 r = mailimf_dquote_parse(message, length, &cur_token);
5614 if (r != MAILIMF_NO_ERROR) {
5619 /* no_fold_quote = strndup(message + begin, cur_token - begin); */
5620 no_fold_quote = malloc(cur_token - begin + 1);
5621 if (no_fold_quote == NULL) {
5622 res = MAILIMF_ERROR_MEMORY;
5625 strncpy(no_fold_quote, message + begin, cur_token - begin);
5626 no_fold_quote[cur_token - begin] = '\0';
5628 * result = no_fold_quote;
5629 * index = cur_token;
5631 return MAILIMF_NO_ERROR;
5639 no-fold-literal = "[" *(dtext / quoted-pair) "]"
5644 mailimf_no_fold_literal_char_parse(const char * message, size_t length,
5645 size_t * index, char * result)
5651 cur_token = * index;
5654 r = mailimf_dtext_parse(message, length, &cur_token, &ch);
5656 if (cur_token >= length)
5657 return MAILIMF_ERROR_PARSE;
5659 if (is_dtext(message[cur_token])) {
5660 ch = message[cur_token];
5664 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5666 if (r != MAILIMF_NO_ERROR)
5670 * index = cur_token;
5673 return MAILIMF_NO_ERROR;
5678 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
5679 size_t * index, char ** result)
5684 char * no_fold_literal;
5689 r = mailimf_obracket_parse(message, length, &cur_token);
5690 if (r != MAILIMF_NO_ERROR) {
5696 r = mailimf_no_fold_literal_char_parse(message, length,
5698 if (r == MAILIMF_NO_ERROR) {
5701 else if (r == MAILIMF_ERROR_PARSE)
5709 r = mailimf_cbracket_parse(message, length, &cur_token);
5710 if (r != MAILIMF_NO_ERROR) {
5716 no_fold_literal = strndup(message + begin, cur_token - begin);
5718 no_fold_literal = malloc(cur_token - begin + 1);
5719 if (no_fold_literal == NULL) {
5720 res = MAILIMF_NO_ERROR;
5723 strncpy(no_fold_literal, message + begin, cur_token - begin);
5724 no_fold_literal[cur_token - begin] = '\0';
5726 * result = no_fold_literal;
5727 * index = cur_token;
5729 return MAILIMF_NO_ERROR;
5737 subject = "Subject:" unstructured CRLF
5740 static int mailimf_subject_parse(const char * message, size_t length,
5742 struct mailimf_subject ** result)
5744 struct mailimf_subject * subject;
5750 cur_token = * index;
5752 r = mailimf_token_case_insensitive_parse(message, length,
5753 &cur_token, "Subject");
5754 if (r != MAILIMF_NO_ERROR) {
5759 r = mailimf_colon_parse(message, length, &cur_token);
5760 if (r != MAILIMF_NO_ERROR) {
5765 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5766 if (r != MAILIMF_NO_ERROR) {
5771 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5772 if (r != MAILIMF_NO_ERROR) {
5777 subject = mailimf_subject_new(value);
5778 if (subject == NULL) {
5779 res = MAILIMF_ERROR_MEMORY;
5784 * index = cur_token;
5786 return MAILIMF_NO_ERROR;
5789 mailimf_unstructured_free(value);
5795 comments = "Comments:" unstructured CRLF
5798 static int mailimf_comments_parse(const char * message, size_t length,
5800 struct mailimf_comments ** result)
5802 struct mailimf_comments * comments;
5808 cur_token = * index;
5810 r = mailimf_token_case_insensitive_parse(message, length,
5811 &cur_token, "Comments");
5812 if (r != MAILIMF_NO_ERROR) {
5817 r = mailimf_colon_parse(message, length, &cur_token);
5818 if (r != MAILIMF_NO_ERROR) {
5823 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5824 if (r != MAILIMF_NO_ERROR) {
5829 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5830 if (r != MAILIMF_NO_ERROR) {
5835 comments = mailimf_comments_new(value);
5836 if (comments == NULL) {
5837 res = MAILIMF_ERROR_MEMORY;
5841 * result = comments;
5842 * index = cur_token;
5844 return MAILIMF_NO_ERROR;
5847 mailimf_unstructured_free(value);
5853 keywords = "Keywords:" phrase *("," phrase) CRLF
5856 static int mailimf_keywords_parse(const char * message, size_t length,
5858 struct mailimf_keywords ** result)
5860 struct mailimf_keywords * keywords;
5866 cur_token = * index;
5868 r = mailimf_token_case_insensitive_parse(message, length,
5869 &cur_token, "Keywords");
5870 if (r != MAILIMF_NO_ERROR) {
5875 r = mailimf_colon_parse(message, length, &cur_token);
5876 if (r != MAILIMF_NO_ERROR) {
5881 r = mailimf_struct_list_parse(message, length, &cur_token,
5883 (mailimf_struct_parser *)
5884 mailimf_phrase_parse,
5885 (mailimf_struct_destructor *)
5886 mailimf_phrase_free);
5887 if (r != MAILIMF_NO_ERROR) {
5892 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5893 if (r != MAILIMF_NO_ERROR) {
5898 keywords = mailimf_keywords_new(list);
5899 if (keywords == NULL) {
5900 res = MAILIMF_ERROR_MEMORY;
5904 * result = keywords;
5905 * index = cur_token;
5907 return MAILIMF_NO_ERROR;
5910 clist_foreach(list, (clist_func) mailimf_phrase_free, NULL);
5917 resent-date = "Resent-Date:" date-time CRLF
5921 mailimf_resent_date_parse(const char * message, size_t length,
5922 size_t * index, struct mailimf_orig_date ** result)
5924 struct mailimf_orig_date * orig_date;
5925 struct mailimf_date_time * date_time;
5930 cur_token = * index;
5932 r = mailimf_token_case_insensitive_parse(message, length,
5933 &cur_token, "Resent-Date");
5934 if (r != MAILIMF_NO_ERROR) {
5939 r = mailimf_colon_parse(message, length, &cur_token);
5940 if (r != MAILIMF_NO_ERROR) {
5945 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
5946 if (r != MAILIMF_NO_ERROR) {
5951 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5952 if (r != MAILIMF_NO_ERROR) {
5954 goto free_date_time;
5957 orig_date = mailimf_orig_date_new(date_time);
5958 if (orig_date == NULL) {
5959 res = MAILIMF_ERROR_MEMORY;
5960 goto free_date_time;
5963 * result = orig_date;
5964 * index = cur_token;
5966 return MAILIMF_NO_ERROR;
5969 mailimf_date_time_free(date_time);
5975 resent-from = "Resent-From:" mailbox-list CRLF
5979 mailimf_resent_from_parse(const char * message, size_t length,
5980 size_t * index, struct mailimf_from ** result)
5982 struct mailimf_mailbox_list * mb_list;
5983 struct mailimf_from * from;
5988 cur_token = * index;
5990 r = mailimf_token_case_insensitive_parse(message, length,
5991 &cur_token, "Resent-From");
5992 if (r != MAILIMF_NO_ERROR) {
5997 r = mailimf_colon_parse(message, length, &cur_token);
5998 if (r != MAILIMF_NO_ERROR) {
6003 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
6004 if (r != MAILIMF_NO_ERROR) {
6009 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6010 if (r != MAILIMF_NO_ERROR) {
6015 from = mailimf_from_new(mb_list);
6017 res = MAILIMF_ERROR_MEMORY;
6022 * index = cur_token;
6024 return MAILIMF_NO_ERROR;
6027 mailimf_mailbox_list_free(mb_list);
6033 resent-sender = "Resent-Sender:" mailbox CRLF
6037 mailimf_resent_sender_parse(const char * message, size_t length,
6038 size_t * index, struct mailimf_sender ** result)
6040 struct mailimf_mailbox * mb;
6041 struct mailimf_sender * sender;
6048 r = mailimf_token_case_insensitive_parse(message, length,
6049 &cur_token, "Resent-Sender");
6050 if (r != MAILIMF_NO_ERROR) {
6055 r = mailimf_colon_parse(message, length, &cur_token);
6056 if (r != MAILIMF_NO_ERROR) {
6061 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
6062 if (r != MAILIMF_NO_ERROR) {
6067 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6068 if (r != MAILIMF_NO_ERROR) {
6073 sender = mailimf_sender_new(mb);
6074 if (sender == NULL) {
6075 res = MAILIMF_ERROR_MEMORY;
6080 * index = cur_token;
6082 return MAILIMF_NO_ERROR;
6085 mailimf_mailbox_free(mb);
6091 resent-to = "Resent-To:" address-list CRLF
6095 mailimf_resent_to_parse(const char * message, size_t length,
6096 size_t * index, struct mailimf_to ** result)
6098 struct mailimf_address_list * addr_list;
6099 struct mailimf_to * to;
6104 cur_token = * index;
6106 r = mailimf_token_case_insensitive_parse(message, length,
6107 &cur_token, "Resent-To");
6108 if (r != MAILIMF_NO_ERROR) {
6113 r = mailimf_colon_parse(message, length, &cur_token);
6114 if (r != MAILIMF_NO_ERROR) {
6119 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6120 if (r != MAILIMF_NO_ERROR) {
6125 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6126 if (r != MAILIMF_NO_ERROR) {
6128 goto free_addr_list;
6131 to = mailimf_to_new(addr_list);
6133 res = MAILIMF_ERROR_MEMORY;
6134 goto free_addr_list;
6138 * index = cur_token;
6140 return MAILIMF_NO_ERROR;
6143 mailimf_address_list_free(addr_list);
6149 resent-cc = "Resent-Cc:" address-list CRLF
6153 mailimf_resent_cc_parse(const char * message, size_t length,
6154 size_t * index, struct mailimf_cc ** result)
6156 struct mailimf_address_list * addr_list;
6157 struct mailimf_cc * cc;
6162 cur_token = * index;
6164 r = mailimf_token_case_insensitive_parse(message, length,
6165 &cur_token, "Resent-Cc");
6166 if (r != MAILIMF_NO_ERROR) {
6171 r = mailimf_colon_parse(message, length, &cur_token);
6172 if (r != MAILIMF_NO_ERROR) {
6177 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6178 if (r != MAILIMF_NO_ERROR) {
6183 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6184 if (r != MAILIMF_NO_ERROR) {
6186 goto free_addr_list;
6189 cc = mailimf_cc_new(addr_list);
6191 res = MAILIMF_ERROR_MEMORY;
6192 goto free_addr_list;
6196 * index = cur_token;
6198 return MAILIMF_NO_ERROR;
6201 mailimf_address_list_free(addr_list);
6207 resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF
6211 mailimf_resent_bcc_parse(const char * message, size_t length,
6212 size_t * index, struct mailimf_bcc ** result)
6214 struct mailimf_address_list * addr_list;
6215 struct mailimf_bcc * bcc;
6220 cur_token = * index;
6223 r = mailimf_token_case_insensitive_parse(message, length,
6224 &cur_token, "Resent-Bcc");
6225 if (r != MAILIMF_NO_ERROR) {
6230 r = mailimf_colon_parse(message, length, &cur_token);
6231 if (r != MAILIMF_NO_ERROR) {
6236 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6237 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6242 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6243 if (r != MAILIMF_NO_ERROR) {
6245 goto free_addr_list;
6248 bcc = mailimf_bcc_new(addr_list);
6250 res = MAILIMF_ERROR_MEMORY;
6251 goto free_addr_list;
6255 * index = cur_token;
6260 mailimf_address_list_free(addr_list);
6266 resent-msg-id = "Resent-Message-ID:" msg-id CRLF
6270 mailimf_resent_msg_id_parse(const char * message, size_t length,
6272 struct mailimf_message_id ** result)
6276 struct mailimf_message_id * message_id;
6280 cur_token = * index;
6282 r = mailimf_token_case_insensitive_parse(message, length,
6283 &cur_token, "Resent-Message-ID");
6284 if (r != MAILIMF_NO_ERROR) {
6289 r = mailimf_colon_parse(message, length, &cur_token);
6290 if (r != MAILIMF_NO_ERROR) {
6295 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
6296 if (r != MAILIMF_NO_ERROR) {
6301 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6302 if (r != MAILIMF_NO_ERROR) {
6307 message_id = mailimf_message_id_new(value);
6308 if (message_id == NULL) {
6309 res = MAILIMF_ERROR_MEMORY;
6313 * result = message_id;
6314 * index = cur_token;
6316 return MAILIMF_NO_ERROR;
6319 mailimf_msg_id_free(value);
6330 static int mailimf_trace_parse(const char * message, size_t length,
6332 struct mailimf_trace ** result)
6335 struct mailimf_return * return_path;
6336 clist * received_list;
6337 struct mailimf_trace * trace;
6341 cur_token = * index;
6343 received_list = NULL;
6345 r = mailimf_return_parse(message, length, &cur_token, &return_path);
6346 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6351 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6353 (mailimf_struct_parser *)
6354 mailimf_received_parse,
6355 (mailimf_struct_destructor *)
6356 mailimf_received_free);
6357 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6362 if ((received_list == NULL) && (return_path == NULL)) {
6363 res = MAILIMF_ERROR_PARSE;
6367 trace = mailimf_trace_new(return_path, received_list);
6368 if (trace == NULL) {
6369 res = MAILIMF_ERROR_MEMORY;
6374 * index = cur_token;
6376 return MAILIMF_NO_ERROR;
6379 clist_foreach(received_list, (clist_func) mailimf_received_free, NULL);
6380 clist_free(received_list);
6382 if (return_path != NULL)
6383 mailimf_return_free(return_path);
6390 return = "Return-Path:" path CRLF
6393 static int mailimf_return_parse(const char * message, size_t length,
6395 struct mailimf_return ** result)
6397 struct mailimf_path * path = NULL;
6398 struct mailimf_return * return_path;
6403 cur_token = * index;
6405 r = mailimf_token_case_insensitive_parse(message, length,
6406 &cur_token, "Return-Path");
6407 if (r != MAILIMF_NO_ERROR) {
6412 r = mailimf_colon_parse(message, length, &cur_token);
6413 if (r != MAILIMF_NO_ERROR) {
6418 r = mailimf_path_parse(message, length, &cur_token, &path);
6419 if ( r!= MAILIMF_NO_ERROR) {
6424 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6425 if (r != MAILIMF_NO_ERROR) {
6430 return_path = mailimf_return_new(path);
6431 if (return_path == NULL) {
6432 res = MAILIMF_ERROR_MEMORY;
6436 * result = return_path;
6437 * index = cur_token;
6439 return MAILIMF_NO_ERROR;
6442 mailimf_path_free(path);
6448 path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
6452 static int mailimf_path_parse(const char * message, size_t length,
6453 size_t * index, struct mailimf_path ** result)
6457 struct mailimf_path * path;
6461 cur_token = * index;
6464 r = mailimf_cfws_parse(message, length, &cur_token);
6465 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6470 r = mailimf_lower_parse(message, length, &cur_token);
6471 if (r != MAILIMF_NO_ERROR) {
6476 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
6478 case MAILIMF_NO_ERROR:
6480 case MAILIMF_ERROR_PARSE:
6481 r = mailimf_cfws_parse(message, length, &cur_token);
6482 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6491 r = mailimf_greater_parse(message, length, &cur_token);
6492 if (r != MAILIMF_NO_ERROR) {
6494 goto free_addr_spec;
6497 path = mailimf_path_new(addr_spec);
6499 res = MAILIMF_ERROR_MEMORY;
6500 goto free_addr_spec;
6503 * index = cur_token;
6506 return MAILIMF_NO_ERROR;
6509 if (addr_spec != NULL)
6510 mailimf_addr_spec_free(addr_spec);
6516 received = "Received:" name-val-list ";" date-time CRLF
6520 static int mailimf_received_parse(const char * message, size_t length,
6522 struct mailimf_received ** result)
6525 struct mailimf_received * received;
6526 struct mailimf_name_val_list * name_val_list;
6527 struct mailimf_date_time * date_time;
6531 cur_token = * index;
6533 r = mailimf_token_case_insensitive_parse(message, length,
6534 &cur_token, "Received");
6535 if (r != MAILIMF_NO_ERROR) {
6540 r = mailimf_colon_parse(message, length, &cur_token);
6541 if (r != MAILIMF_NO_ERROR) {
6546 r = mailimf_name_val_list_parse(message, length,
6547 &cur_token, &name_val_list);
6548 if (r != MAILIMF_NO_ERROR) {
6553 r = mailimf_semi_colon_parse(message, length, &cur_token);
6554 if (r != MAILIMF_NO_ERROR) {
6556 goto free_name_val_list;
6559 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
6560 if (r != MAILIMF_NO_ERROR) {
6562 goto free_name_val_list;
6565 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6566 if (r != MAILIMF_NO_ERROR) {
6568 goto free_date_time;
6571 received = mailimf_received_new(name_val_list, date_time);
6572 if (received == NULL) {
6573 res = MAILIMF_ERROR_MEMORY;
6574 goto free_date_time;
6577 * index = cur_token;
6578 * result = received;
6580 return MAILIMF_NO_ERROR;
6583 mailimf_date_time_free(date_time);
6585 mailimf_name_val_list_free(name_val_list);
6592 name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
6597 mailimf_name_val_list_parse(const char * message, size_t length,
6599 struct mailimf_name_val_list ** result)
6602 struct mailimf_name_val_pair * pair;
6603 struct mailimf_name_val_list * name_val_list;
6608 cur_token = * index;
6611 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6613 if (r == MAILIMF_NO_ERROR){
6618 mailimf_name_val_pair_free(pair);
6619 res = MAILIMF_ERROR_MEMORY;
6623 r = clist_append(list, pair);
6625 mailimf_name_val_pair_free(pair);
6626 res = MAILIMF_ERROR_MEMORY;
6630 final_token = cur_token;
6633 r = mailimf_cfws_parse(message, length, &cur_token);
6634 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6639 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6640 if (r == MAILIMF_NO_ERROR) {
6643 else if (r == MAILIMF_ERROR_PARSE)
6650 r = clist_append(list, pair);
6652 mailimf_name_val_pair_free(pair);
6653 res = MAILIMF_ERROR_MEMORY;
6657 final_token = cur_token;
6659 cur_token = final_token;
6662 name_val_list = mailimf_name_val_list_new(list);
6663 if (name_val_list == NULL) {
6664 res = MAILIMF_ERROR_MEMORY;
6668 * index = cur_token;
6669 * result = name_val_list;
6671 return MAILIMF_NO_ERROR;
6675 clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL);
6684 name-val-pair = item-name CFWS item-value
6689 mailimf_name_val_pair_parse(const char * message, size_t length,
6691 struct mailimf_name_val_pair ** result)
6695 struct mailimf_item_value * item_value;
6696 struct mailimf_name_val_pair * name_val_pair;
6700 cur_token = * index;
6702 r = mailimf_cfws_parse(message, length, &cur_token);
6703 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6708 r = mailimf_item_name_parse(message, length, &cur_token, &item_name);
6709 if (r != MAILIMF_NO_ERROR) {
6714 r = mailimf_cfws_parse(message, length, &cur_token);
6715 if (r != MAILIMF_NO_ERROR) {
6717 goto free_item_name;
6720 r = mailimf_item_value_parse(message, length, &cur_token, &item_value);
6721 if (r != MAILIMF_NO_ERROR) {
6723 goto free_item_name;
6726 name_val_pair = mailimf_name_val_pair_new(item_name, item_value);
6727 if (name_val_pair == NULL) {
6728 res = MAILIMF_ERROR_MEMORY;
6729 goto free_item_value;
6732 * result = name_val_pair;
6733 * index = cur_token;
6735 return MAILIMF_NO_ERROR;
6738 mailimf_item_value_free(item_value);
6740 mailimf_item_name_free(item_name);
6747 item-name = ALPHA *(["-"] (ALPHA / DIGIT))
6751 static int mailimf_item_name_parse(const char * message, size_t length,
6752 size_t * index, char ** result)
6762 cur_token = * index;
6766 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6767 if (r != MAILIMF_NO_ERROR) {
6775 minus_sign = mailimf_minus_parse(message, length, &cur_token);
6777 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6778 if (r == MAILIMF_ERROR_PARSE)
6779 r = mailimf_digit_parse(message, length, &cur_token, &digit);
6781 if (r == MAILIMF_NO_ERROR) {
6784 if (r == MAILIMF_ERROR_PARSE)
6786 else if (r != MAILIMF_NO_ERROR) {
6792 item_name = strndup(message + begin, cur_token - begin);
6793 if (item_name == NULL) {
6794 res = MAILIMF_ERROR_MEMORY;
6798 * index = cur_token;
6799 * result = item_name;
6801 return MAILIMF_NO_ERROR;
6809 item-value = 1*angle-addr / addr-spec /
6810 atom / domain / msg-id
6814 static int is_item_value_atext(char ch)
6828 static int mailimf_item_value_atom_parse(const char * message, size_t length,
6829 size_t * index, char ** result)
6835 cur_token = * index;
6837 r = mailimf_cfws_parse(message, length, &cur_token);
6838 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6841 r = mailimf_custom_string_parse(message, length, &cur_token,
6842 &atom, is_item_value_atext);
6843 if (r != MAILIMF_NO_ERROR)
6846 r = mailimf_cfws_parse(message, length, &cur_token);
6847 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6850 * index = cur_token;
6853 return MAILIMF_NO_ERROR;
6856 static int mailimf_item_value_parse(const char * message, size_t length,
6858 struct mailimf_item_value ** result)
6861 clist * angle_addr_list;
6867 struct mailimf_item_value * item_value;
6871 cur_token = * index;
6873 angle_addr_list = NULL;
6879 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6881 (mailimf_struct_parser *)
6882 mailimf_angle_addr_parse,
6883 (mailimf_struct_destructor *)
6884 mailimf_angle_addr_free);
6885 if (r == MAILIMF_NO_ERROR)
6886 type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST;
6888 if (r == MAILIMF_ERROR_PARSE) {
6889 r = mailimf_addr_spec_parse(message, length, &cur_token,
6891 if (r == MAILIMF_NO_ERROR)
6892 type = MAILIMF_ITEM_VALUE_ADDR_SPEC;
6895 if (r == MAILIMF_ERROR_PARSE) {
6896 r = mailimf_msg_id_parse(message, length, &cur_token,
6898 if (r == MAILIMF_NO_ERROR)
6899 type = MAILIMF_ITEM_VALUE_MSG_ID;
6903 else if (mailimf_domain_parse(message, length, &cur_token,
6905 type = MAILIMF_ITEM_VALUE_DOMAIN;
6908 else if (mailimf_atom_parse(message, length, &cur_token,
6910 type = MAILIMF_ITEM_VALUE_ATOM;
6913 if (r == MAILIMF_ERROR_PARSE) {
6914 r = mailimf_item_value_atom_parse(message, length, &cur_token,
6916 if (r == MAILIMF_NO_ERROR)
6917 type = MAILIMF_ITEM_VALUE_ATOM;
6920 if (r != MAILIMF_NO_ERROR) {
6925 item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec,
6926 atom, domain, msg_id);
6927 if (item_value == NULL) {
6928 res = MAILIMF_ERROR_MEMORY;
6932 * result = item_value;
6933 * index = cur_token;
6935 return MAILIMF_NO_ERROR;
6938 if (angle_addr_list != NULL) {
6939 clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL);
6940 clist_free(angle_addr_list);
6942 if (addr_spec != NULL)
6943 mailimf_addr_spec_free(addr_spec);
6945 mailimf_atom_free(atom);
6947 mailimf_domain_free(domain);
6949 mailimf_msg_id_free(msg_id);
6956 optional-field = field-name ":" unstructured CRLF
6960 mailimf_optional_field_parse(const char * message, size_t length,
6962 struct mailimf_optional_field ** result)
6966 struct mailimf_optional_field * optional_field;
6971 cur_token = * index;
6973 r = mailimf_field_name_parse(message, length, &cur_token, &name);
6974 if (r != MAILIMF_NO_ERROR) {
6979 r = mailimf_colon_parse(message, length, &cur_token);
6980 if (r != MAILIMF_NO_ERROR) {
6985 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
6986 if (r != MAILIMF_NO_ERROR) {
6991 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6992 if (r != MAILIMF_NO_ERROR) {
6997 optional_field = mailimf_optional_field_new(name, value);
6998 if (optional_field == NULL) {
6999 res = MAILIMF_ERROR_MEMORY;
7003 * result = optional_field;
7004 * index = cur_token;
7006 return MAILIMF_NO_ERROR;
7009 mailimf_unstructured_free(value);
7011 mailimf_field_name_free(name);
7017 field-name = 1*ftext
7020 static inline int is_ftext(char ch);
7022 static int mailimf_field_name_parse(const char * message, size_t length,
7023 size_t * index, char ** result)
7029 cur_token = * index;
7032 if (end >= length) {
7033 return MAILIMF_ERROR_PARSE;
7036 while (is_ftext(message[end])) {
7041 if (end == cur_token) {
7042 return MAILIMF_ERROR_PARSE;
7045 /* field_name = strndup(message + cur_token, end - cur_token); */
7046 field_name = malloc(end - cur_token + 1);
7047 if (field_name == NULL) {
7048 return MAILIMF_ERROR_MEMORY;
7050 strncpy(field_name, message + cur_token, end - cur_token);
7051 field_name[end - cur_token] = '\0';
7055 * index = cur_token;
7056 * result = field_name;
7058 return MAILIMF_NO_ERROR;
7062 ftext = %d33-57 / ; Any character except
7063 %d59-126 ; controls, SP, and
7067 static inline int is_ftext(char ch)
7069 unsigned char uch = (unsigned char) ch;
7081 static int mailimf_ftext_parse(const char * message, size_t length,
7082 size_t * index, gchar * result)
7084 return mailimf_typed_text_parse(message, length, index, result, is_ftext);
7091 static int mailimf_envelope_field_parse(const char * message, size_t length,
7093 struct mailimf_field ** result)
7097 struct mailimf_orig_date * orig_date;
7098 struct mailimf_from * from;
7099 struct mailimf_sender * sender;
7100 struct mailimf_reply_to * reply_to;
7101 struct mailimf_to * to;
7102 struct mailimf_cc * cc;
7103 struct mailimf_bcc * bcc;
7104 struct mailimf_message_id * message_id;
7105 struct mailimf_in_reply_to * in_reply_to;
7106 struct mailimf_references * references;
7107 struct mailimf_subject * subject;
7108 struct mailimf_optional_field * optional_field;
7109 struct mailimf_field * field;
7114 cur_token = * index;
7127 optional_field = NULL;
7129 guessed_type = guess_header_type(message, length, cur_token);
7130 type = MAILIMF_FIELD_NONE;
7132 switch (guessed_type) {
7133 case MAILIMF_FIELD_ORIG_DATE:
7134 r = mailimf_orig_date_parse(message, length, &cur_token,
7136 if (r == MAILIMF_NO_ERROR)
7137 type = guessed_type;
7138 else if (r == MAILIMF_ERROR_PARSE) {
7146 case MAILIMF_FIELD_FROM:
7147 r = mailimf_from_parse(message, length, &cur_token,
7149 if (r == MAILIMF_NO_ERROR)
7150 type = guessed_type;
7151 else if (r == MAILIMF_ERROR_PARSE) {
7159 case MAILIMF_FIELD_SENDER:
7160 r = mailimf_sender_parse(message, length, &cur_token,
7162 if (r == MAILIMF_NO_ERROR)
7163 type = guessed_type;
7164 else if (r == MAILIMF_ERROR_PARSE) {
7172 case MAILIMF_FIELD_REPLY_TO:
7173 r = mailimf_reply_to_parse(message, length, &cur_token,
7175 if (r == MAILIMF_NO_ERROR)
7176 type = guessed_type;
7177 else if (r == MAILIMF_ERROR_PARSE) {
7185 case MAILIMF_FIELD_TO:
7186 r = mailimf_to_parse(message, length, &cur_token,
7188 if (r == MAILIMF_NO_ERROR)
7189 type = guessed_type;
7190 else if (r == MAILIMF_ERROR_PARSE) {
7198 case MAILIMF_FIELD_CC:
7199 r = mailimf_cc_parse(message, length, &cur_token,
7201 if (r == MAILIMF_NO_ERROR)
7202 type = guessed_type;
7203 else if (r == MAILIMF_ERROR_PARSE) {
7211 case MAILIMF_FIELD_BCC:
7212 r = mailimf_bcc_parse(message, length, &cur_token,
7214 if (r == MAILIMF_NO_ERROR)
7215 type = guessed_type;
7216 else if (r == MAILIMF_ERROR_PARSE) {
7224 case MAILIMF_FIELD_MESSAGE_ID:
7225 r = mailimf_message_id_parse(message, length, &cur_token,
7227 if (r == MAILIMF_NO_ERROR)
7228 type = guessed_type;
7229 else if (r == MAILIMF_ERROR_PARSE) {
7237 case MAILIMF_FIELD_IN_REPLY_TO:
7238 r = mailimf_in_reply_to_parse(message, length, &cur_token,
7240 if (r == MAILIMF_NO_ERROR)
7241 type = guessed_type;
7242 else if (r == MAILIMF_ERROR_PARSE) {
7250 case MAILIMF_FIELD_REFERENCES:
7251 r = mailimf_references_parse(message, length, &cur_token,
7253 if (r == MAILIMF_NO_ERROR)
7254 type = guessed_type;
7255 else if (r == MAILIMF_ERROR_PARSE) {
7263 case MAILIMF_FIELD_SUBJECT:
7264 r = mailimf_subject_parse(message, length, &cur_token,
7266 if (r == MAILIMF_NO_ERROR)
7267 type = guessed_type;
7268 else if (r == MAILIMF_ERROR_PARSE) {
7278 if (type == MAILIMF_FIELD_NONE) {
7279 res = MAILIMF_ERROR_PARSE;
7283 field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
7285 orig_date, from, sender, reply_to, to,
7286 cc, bcc, message_id, in_reply_to, references,
7287 subject, NULL, NULL, optional_field);
7288 if (field == NULL) {
7289 res = MAILIMF_ERROR_MEMORY;
7294 * index = cur_token;
7296 return MAILIMF_NO_ERROR;
7299 if (orig_date != NULL)
7300 mailimf_orig_date_free(orig_date);
7302 mailimf_from_free(from);
7304 mailimf_sender_free(sender);
7305 if (reply_to != NULL)
7306 mailimf_reply_to_free(reply_to);
7308 mailimf_to_free(to);
7310 mailimf_cc_free(cc);
7312 mailimf_bcc_free(bcc);
7313 if (message_id != NULL)
7314 mailimf_message_id_free(message_id);
7315 if (in_reply_to != NULL)
7316 mailimf_in_reply_to_free(in_reply_to);
7317 if (references != NULL)
7318 mailimf_references_free(references);
7319 if (subject != NULL)
7320 mailimf_subject_free(subject);
7321 if (optional_field != NULL)
7322 mailimf_optional_field_free(optional_field);
7327 int mailimf_envelope_fields_parse(const char * message, size_t length,
7329 struct mailimf_fields ** result)
7333 struct mailimf_fields * fields;
7337 cur_token = * index;
7341 res = MAILIMF_ERROR_MEMORY;
7346 struct mailimf_field * elt;
7348 r = mailimf_envelope_field_parse(message, length, &cur_token, &elt);
7349 if (r == MAILIMF_NO_ERROR) {
7350 r = clist_append(list, elt);
7352 res = MAILIMF_ERROR_MEMORY;
7356 else if (r == MAILIMF_ERROR_PARSE) {
7357 r = mailimf_ignore_field_parse(message, length, &cur_token);
7358 if (r == MAILIMF_NO_ERROR) {
7361 else if (r == MAILIMF_ERROR_PARSE) {
7375 fields = mailimf_fields_new(list);
7376 if (fields == NULL) {
7377 res = MAILIMF_ERROR_MEMORY;
7382 * index = cur_token;
7384 return MAILIMF_NO_ERROR;
7388 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7397 mailimf_envelope_or_optional_field_parse(const char * message,
7400 struct mailimf_field ** result)
7404 struct mailimf_optional_field * optional_field;
7405 struct mailimf_field * field;
7407 r = mailimf_envelope_field_parse(message, length, index, result);
7408 if (r == MAILIMF_NO_ERROR)
7409 return MAILIMF_NO_ERROR;
7411 cur_token = * index;
7413 r = mailimf_optional_field_parse(message, length, &cur_token,
7415 if (r != MAILIMF_NO_ERROR)
7418 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL,
7423 NULL, NULL, NULL, NULL, NULL,
7424 NULL, NULL, NULL, optional_field);
7425 if (field == NULL) {
7426 mailimf_optional_field_free(optional_field);
7427 return MAILIMF_ERROR_MEMORY;
7431 * index = cur_token;
7433 return MAILIMF_NO_ERROR;
7438 mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
7440 struct mailimf_fields ** result)
7444 struct mailimf_fields * fields;
7448 cur_token = * index;
7452 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7454 (mailimf_struct_parser *)
7455 mailimf_envelope_or_optional_field_parse,
7456 (mailimf_struct_destructor *)
7457 mailimf_field_free);
7459 case MAILIMF_NO_ERROR:
7463 case MAILIMF_ERROR_PARSE:
7466 res = MAILIMF_ERROR_MEMORY;
7476 fields = mailimf_fields_new(list);
7477 if (fields == NULL) {
7478 res = MAILIMF_ERROR_MEMORY;
7483 * index = cur_token;
7485 return MAILIMF_NO_ERROR;
7489 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7499 mailimf_only_optional_field_parse(const char * message,
7502 struct mailimf_field ** result)
7506 struct mailimf_optional_field * optional_field;
7507 struct mailimf_field * field;
7509 cur_token = * index;
7511 r = mailimf_optional_field_parse(message, length, &cur_token,
7513 if (r != MAILIMF_NO_ERROR)
7516 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL,
7517 NULL, NULL, NULL, NULL, NULL,
7518 NULL, NULL, NULL, NULL, NULL,
7519 NULL, NULL, NULL, NULL, NULL,
7520 NULL, NULL, NULL, optional_field);
7521 if (field == NULL) {
7522 mailimf_optional_field_free(optional_field);
7523 return MAILIMF_ERROR_MEMORY;
7527 * index = cur_token;
7529 return MAILIMF_NO_ERROR;
7534 mailimf_optional_fields_parse(const char * message, size_t length,
7536 struct mailimf_fields ** result)
7540 struct mailimf_fields * fields;
7544 cur_token = * index;
7548 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7550 (mailimf_struct_parser *)
7551 mailimf_only_optional_field_parse,
7552 (mailimf_struct_destructor *)
7553 mailimf_field_free);
7555 case MAILIMF_NO_ERROR:
7559 case MAILIMF_ERROR_PARSE:
7562 res = MAILIMF_ERROR_MEMORY;
7572 fields = mailimf_fields_new(list);
7573 if (fields == NULL) {
7574 res = MAILIMF_ERROR_MEMORY;
7579 * index = cur_token;
7581 return MAILIMF_NO_ERROR;
7585 clist_foreach(list, (clist_func) mailimf_field_free, NULL);