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))
3017 r = mailimf_semi_colon_parse(message, length, &cur_token);
3018 if (r != MAILIMF_NO_ERROR) {
3020 goto free_mailbox_list;
3023 group = mailimf_group_new(display_name, mailbox_list);
3024 if (group == NULL) {
3025 res = MAILIMF_ERROR_MEMORY;
3026 goto free_mailbox_list;
3029 * index = cur_token;
3032 return MAILIMF_NO_ERROR;
3035 mailimf_mailbox_list_free(mailbox_list);
3037 mailimf_display_name_free(display_name);
3043 display-name = phrase
3046 static int mailimf_display_name_parse(const char * message, size_t length,
3047 size_t * index, char ** result)
3049 return mailimf_phrase_parse(message, length, index, result);
3053 mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
3057 mailimf_mailbox_list_parse(const char * message, size_t length,
3059 struct mailimf_mailbox_list ** result)
3063 struct mailimf_mailbox_list * mailbox_list;
3067 cur_token = * index;
3069 r = mailimf_struct_list_parse(message, length,
3070 &cur_token, &list, ',',
3071 (mailimf_struct_parser *)
3072 mailimf_mailbox_parse,
3073 (mailimf_struct_destructor *)
3074 mailimf_mailbox_free);
3075 if (r != MAILIMF_NO_ERROR) {
3080 mailbox_list = mailimf_mailbox_list_new(list);
3081 if (mailbox_list == NULL) {
3082 res = MAILIMF_ERROR_MEMORY;
3086 * result = mailbox_list;
3087 * index = cur_token;
3089 return MAILIMF_NO_ERROR;
3092 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
3099 address-list = (address *("," address)) / obs-addr-list
3104 mailimf_address_list_parse(const char * message, size_t length,
3106 struct mailimf_address_list ** result)
3110 struct mailimf_address_list * address_list;
3114 cur_token = * index;
3116 r = mailimf_struct_list_parse(message, length,
3117 &cur_token, &list, ',',
3118 (mailimf_struct_parser *)
3119 mailimf_address_parse,
3120 (mailimf_struct_destructor *)
3121 mailimf_address_free);
3122 if (r != MAILIMF_NO_ERROR) {
3127 address_list = mailimf_address_list_new(list);
3128 if (address_list == NULL) {
3129 res = MAILIMF_ERROR_MEMORY;
3133 * result = address_list;
3134 * index = cur_token;
3136 return MAILIMF_NO_ERROR;
3139 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
3146 addr-spec = local-part "@" domain
3150 static int mailimf_addr_spec_parse(const char * message, size_t length,
3170 cur_token = * index;
3172 r = mailimf_cfws_parse(message, length, &cur_token);
3173 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3179 if (end >= length) {
3180 res = MAILIMF_ERROR_PARSE;
3188 switch (message[end]) {
3210 res = MAILIMF_ERROR_PARSE;
3214 addr_spec = malloc(end - cur_token + 1);
3215 if (addr_spec == NULL) {
3216 res = MAILIMF_ERROR_MEMORY;
3220 count = end - cur_token;
3221 src = message + cur_token;
3223 for(i = 0 ; i < count ; i ++) {
3224 if ((* src != ' ') && (* src != '\t')) {
3233 strncpy(addr_spec, message + cur_token, end - cur_token);
3234 addr_spec[end - cur_token] = '\0';
3240 r = mailimf_local_part_parse(message, length, &cur_token, &local_part);
3241 if (r != MAILIMF_NO_ERROR) {
3246 r = mailimf_at_sign_parse(message, length, &cur_token);
3248 case MAILIMF_NO_ERROR:
3249 r = mailimf_domain_parse(message, length, &cur_token, &domain);
3250 if (r != MAILIMF_NO_ERROR) {
3252 goto free_local_part;
3256 case MAILIMF_ERROR_PARSE:
3262 goto free_local_part;
3266 addr_spec = malloc(strlen(local_part) + strlen(domain) + 2);
3267 if (addr_spec == NULL) {
3268 res = MAILIMF_ERROR_MEMORY;
3272 strcpy(addr_spec, local_part);
3273 strcat(addr_spec, "@");
3274 strcat(addr_spec, domain);
3276 mailimf_domain_free(domain);
3277 mailimf_local_part_free(local_part);
3280 addr_spec = local_part;
3284 * result = addr_spec;
3285 * index = cur_token;
3287 return MAILIMF_NO_ERROR;
3291 mailimf_domain_free(domain);
3293 mailimf_local_part_free(local_part);
3300 local-part = dot-atom / quoted-string / obs-local-part
3304 static int mailimf_local_part_parse(const char * message, size_t length,
3310 r = mailimf_dot_atom_parse(message, length, index, result);
3312 case MAILIMF_NO_ERROR:
3314 case MAILIMF_ERROR_PARSE:
3320 r = mailimf_quoted_string_parse(message, length, index, result);
3321 if (r != MAILIMF_NO_ERROR)
3324 return MAILIMF_NO_ERROR;
3329 domain = dot-atom / domain-literal / obs-domain
3333 static int mailimf_domain_parse(const char * message, size_t length,
3339 r = mailimf_dot_atom_parse(message, length, index, result);
3341 case MAILIMF_NO_ERROR:
3343 case MAILIMF_ERROR_PARSE:
3349 r = mailimf_domain_literal_parse(message, length, index, result);
3350 if (r != MAILIMF_NO_ERROR)
3353 return MAILIMF_NO_ERROR;
3363 mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length,
3370 cur_token = * index;
3372 r = mailimf_cfws_parse(message, length, &cur_token);
3373 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3376 r = mailimf_dcontent_parse(message, length, &cur_token, &ch);
3377 if (r != MAILIMF_NO_ERROR)
3380 * index = cur_token;
3382 return MAILIMF_NO_ERROR;
3387 domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
3391 static int mailimf_domain_literal_parse(const char * message, size_t length,
3392 size_t * index, char ** result)
3397 char * domain_literal;
3400 cur_token = * index;
3402 r = mailimf_cfws_parse(message, length, &cur_token);
3403 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3407 r = mailimf_obracket_parse(message, length, &cur_token);
3408 if (r != MAILIMF_NO_ERROR)
3412 r = mailimf_domain_literal_fws_dcontent_parse(message, length,
3414 if (r == MAILIMF_NO_ERROR) {
3417 else if (r == MAILIMF_ERROR_PARSE)
3423 r = mailimf_fws_parse(message, length, &cur_token);
3424 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3427 r = mailimf_cbracket_parse(message, length, &cur_token);
3428 if (r != MAILIMF_NO_ERROR)
3431 len = cur_token - begin;
3433 domain_literal = malloc(len + 1);
3434 if (domain_literal == NULL)
3435 return MAILIMF_ERROR_MEMORY;
3436 strncpy(domain_literal, message + begin, len);
3437 domain_literal[len] = '\0';
3439 * result = domain_literal;
3440 * index = cur_token;
3442 return MAILIMF_NO_ERROR;
3447 dcontent = dtext / quoted-pair
3451 static int mailimf_dcontent_parse(const char * message, size_t length,
3452 size_t * index, char * result)
3458 cur_token = * index;
3460 if (cur_token >= length)
3461 return MAILIMF_ERROR_PARSE;
3463 if (is_dtext(message[cur_token])) {
3464 ch = message[cur_token];
3468 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
3470 if (r != MAILIMF_NO_ERROR)
3474 * index = cur_token;
3477 return MAILIMF_NO_ERROR;
3483 dtext = NO-WS-CTL / ; Non white space controls
3485 %d33-90 / ; The rest of the US-ASCII
3486 %d94-126 ; characters not including "[",
3490 static inline int is_dtext(char ch)
3492 unsigned char uch = (unsigned char) ch;
3494 if (is_no_ws_ctl(ch))
3500 if ((uch >= 91) && (uch <= 93))
3510 message = (fields / obs-fields)
3514 int mailimf_message_parse(const char * message, size_t length,
3516 struct mailimf_message ** result)
3518 struct mailimf_fields * fields;
3519 struct mailimf_body * body;
3520 struct mailimf_message * msg;
3525 cur_token = * index;
3527 r = mailimf_fields_parse(message, length, &cur_token, &fields);
3528 if (r != MAILIMF_NO_ERROR) {
3533 r = mailimf_crlf_parse(message, length, &cur_token);
3534 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3539 r = mailimf_body_parse(message, length, &cur_token, &body);
3540 if (r != MAILIMF_NO_ERROR) {
3545 msg = mailimf_message_new(fields, body);
3547 res = MAILIMF_ERROR_MEMORY;
3551 * index = cur_token;
3554 return MAILIMF_NO_ERROR;
3557 mailimf_body_free(body);
3559 mailimf_fields_free(fields);
3565 body = *(*998text CRLF) *998text
3568 int mailimf_body_parse(const char * message, size_t length,
3570 struct mailimf_body ** result)
3573 struct mailimf_body * body;
3575 cur_token = * index;
3577 body = mailimf_body_new(message + cur_token, length - cur_token);
3579 return MAILIMF_ERROR_MEMORY;
3584 * index = cur_token;
3586 return MAILIMF_NO_ERROR;
3590 CHANGE TO THE RFC 2822
3617 INTO THE FOLLOWING :
3621 resent-fields-list = *(resent-date /
3632 RESENT_HEADER_START,
3635 static int guess_resent_header_type(char * message,
3636 size_t length, size_t index)
3640 r = mailimf_token_case_insensitive_parse(message,
3641 length, &index, "Resent-");
3642 if (r != MAILIMF_NO_ERROR)
3643 return MAILIMF_RESENT_FIELD_NONE;
3645 if (index >= length)
3646 return MAILIMF_RESENT_FIELD_NONE;
3648 switch(toupper(message[index])) {
3650 return MAILIMF_RESENT_FIELD_DATE;
3652 return MAILIMF_RESENT_FIELD_FROM;
3654 return MAILIMF_RESENT_FIELD_SENDER;
3656 return MAILIMF_RESENT_FIELD_TO;
3658 return MAILIMF_RESENT_FIELD_CC;
3660 return MAILIMF_RESENT_FIELD_BCC;
3662 return MAILIMF_RESENT_FIELD_MSG_ID;
3664 return MAILIMF_RESENT_FIELD_NONE;
3671 mailimf_resent_field_parse(const char * message, size_t length,
3673 struct mailimf_resent_field ** result)
3675 struct mailimf_orig_date * resent_date;
3676 struct mailimf_from * resent_from;
3677 struct mailimf_sender * resent_sender;
3678 struct mailimf_to* resent_to;
3679 struct mailimf_cc * resent_cc;
3680 struct mailimf_bcc * resent_bcc;
3681 struct mailimf_message_id * resent_msg_id;
3684 struct mailimf_resent_field * resent_field;
3688 cur_token = * index;
3692 resent_sender = NULL;
3696 resent_msg_id = NULL;
3698 type = guess_resent_header_type(message, length, cur_token);
3701 case MAILIMF_RESENT_FIELD_DATE:
3702 r = mailimf_resent_date_parse(message, length, &cur_token,
3704 if (r != MAILIMF_NO_ERROR) {
3709 case MAILIMF_RESENT_FIELD_FROM:
3710 r = mailimf_resent_from_parse(message, length, &cur_token,
3712 if (r != MAILIMF_NO_ERROR) {
3717 case MAILIMF_RESENT_FIELD_SENDER:
3718 r = mailimf_resent_sender_parse(message, length, &cur_token,
3720 if (r != MAILIMF_NO_ERROR) {
3725 case MAILIMF_RESENT_FIELD_TO:
3726 r = mailimf_resent_to_parse(message, length, &cur_token,
3728 if (r != MAILIMF_NO_ERROR) {
3733 case MAILIMF_RESENT_FIELD_CC:
3734 r= mailimf_resent_cc_parse(message, length, &cur_token,
3736 if (r != MAILIMF_NO_ERROR) {
3741 case MAILIMF_RESENT_FIELD_BCC:
3742 r = mailimf_resent_bcc_parse(message, length, &cur_token,
3744 if (r != MAILIMF_NO_ERROR) {
3749 case MAILIMF_RESENT_FIELD_MSG_ID:
3750 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
3752 if (r != MAILIMF_NO_ERROR) {
3758 res = MAILIMF_ERROR_PARSE;
3762 resent_field = mailimf_resent_field_new(type, resent_date,
3763 resent_from, resent_sender,
3764 resent_to, resent_cc,
3765 resent_bcc, resent_msg_id);
3766 if (resent_field == NULL) {
3767 res = MAILIMF_ERROR_MEMORY;
3771 * result = resent_field;
3772 * index = cur_token;
3774 return MAILIMF_NO_ERROR;
3777 if (resent_msg_id != NULL)
3778 mailimf_message_id_free(resent_msg_id);
3779 if (resent_bcc != NULL)
3780 mailimf_bcc_free(resent_bcc);
3781 if (resent_cc != NULL)
3782 mailimf_cc_free(resent_cc);
3783 if (resent_to != NULL)
3784 mailimf_to_free(resent_to);
3785 if (resent_sender != NULL)
3786 mailimf_sender_free(resent_sender);
3787 if (resent_from != NULL)
3788 mailimf_from_free(resent_from);
3789 if (resent_date != NULL)
3790 mailimf_orig_date_free(resent_date);
3798 mailimf_resent_fields_list_parse(const char * message, size_t length,
3800 struct mailimf_resent_fields_list ** result)
3804 struct mailimf_resent_fields_list * resent_fields_list;
3808 cur_token = * index;
3811 r = mailimf_struct_multiple_parse(message, length, &cur_token, &list,
3812 (mailimf_struct_parser *)
3813 mailimf_resent_field_parse,
3814 (mailimf_struct_destructor *)
3815 mailimf_resent_field_free);
3816 if (r != MAILIMF_NO_ERROR) {
3821 resent_fields_list = mailimf_resent_fields_list_new(list);
3822 if (resent_fields_list == NULL) {
3823 res = MAILIMF_ERROR_MEMORY;
3827 * result = resent_fields_list;
3828 * index = cur_token;
3830 return MAILIMF_NO_ERROR;
3833 clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL);
3842 [resent-fields-list])
3847 mailimf_trace_resent_fields_parse(const char * message, size_t length,
3849 struct mailimf_trace_resent_fields ** result)
3852 struct mailimf_return * return_path;
3853 struct mailimf_resent_fields_list * resent_fields;
3854 struct mailimf_trace_resent_fields * trace_resent_fields;
3858 cur_token = * index;
3861 resent_fields = NULL;
3863 r = mailimf_return_parse(message, length, &cur_token,
3865 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3870 r = mailimf_resent_fields_list_parse(message, length, &cur_token,
3872 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3877 if ((return_path == NULL) && (resent_fields == NULL)) {
3878 res = MAILIMF_ERROR_PARSE;
3882 trace_resent_fields = mailimf_trace_resent_fields_new(return_path,
3884 if (trace_resent_fields == NULL) {
3885 res = MAILIMF_ERROR_MEMORY;
3886 goto free_resent_fields;
3889 * result = trace_resent_fields;
3890 * index = cur_token;
3892 return MAILIMF_NO_ERROR;
3895 if (resent_fields != NULL)
3896 mailimf_resent_fields_list_free(resent_fields);
3897 if (return_path != NULL)
3898 mailimf_return_free(return_path);
3905 delivering-info = *([trace]
3906 [resent-fields-list])
3911 mailimf_delivering_info_parse(const char * message, size_t length,
3913 struct mailimf_delivering_info ** result)
3917 struct mailimf_delivering_info * delivering_info;
3921 cur_token = * index;
3923 r = mailimf_struct_multiple_parse(message, length, &cur_token,
3925 (mailimf_struct_parser *)
3926 mailimf_trace_resent_fields_parse,
3927 (mailimf_struct_destructor *)
3928 mailimf_trace_resent_fields_free);
3929 if (r != MAILIMF_NO_ERROR) {
3934 delivering_info = mailimf_delivering_info_new(list);
3935 if (delivering_info == NULL) {
3936 res = MAILIMF_ERROR_MEMORY;
3940 * result = delivering_info;
3941 * index = cur_token;
3943 return MAILIMF_NO_ERROR;
3946 clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL);
3954 field = delivering-info /
3980 static int guess_header_type(const char * message, size_t length, size_t index)
3985 state = HEADER_START;
3989 if (index >= length)
3990 return MAILIMF_FIELD_NONE;
3994 switch((char) toupper((unsigned char) message[index])) {
3996 return MAILIMF_FIELD_BCC;
4001 return MAILIMF_FIELD_ORIG_DATE;
4003 return MAILIMF_FIELD_FROM;
4005 return MAILIMF_FIELD_IN_REPLY_TO;
4007 return MAILIMF_FIELD_KEYWORDS;
4009 return MAILIMF_FIELD_MESSAGE_ID;
4014 return MAILIMF_FIELD_TO;
4020 return MAILIMF_FIELD_NONE;
4024 switch((char) toupper((unsigned char) message[index])) {
4026 return MAILIMF_FIELD_COMMENTS;
4028 return MAILIMF_FIELD_CC;
4030 return MAILIMF_FIELD_NONE;
4034 switch((char) toupper((unsigned char) message[index])) {
4039 return MAILIMF_FIELD_NONE;
4043 switch((char) toupper((unsigned char) message[index])) {
4045 return MAILIMF_FIELD_REFERENCES;
4047 return MAILIMF_FIELD_REPLY_TO;
4052 return MAILIMF_FIELD_RETURN_PATH;
4054 return MAILIMF_FIELD_NONE;
4058 switch((char) toupper((unsigned char) message[index])) {
4060 return MAILIMF_FIELD_SENDER;
4062 return MAILIMF_FIELD_SUBJECT;
4064 return MAILIMF_FIELD_NONE;
4069 r = mailimf_token_case_insensitive_parse(message,
4070 length, &index, "ent-");
4071 if (r != MAILIMF_NO_ERROR)
4072 return MAILIMF_FIELD_NONE;
4074 if (index >= length)
4075 return MAILIMF_FIELD_NONE;
4077 switch((char) toupper((unsigned char) message[index])) {
4079 return MAILIMF_FIELD_RESENT_DATE;
4081 return MAILIMF_FIELD_RESENT_FROM;
4083 return MAILIMF_FIELD_RESENT_SENDER;
4085 return MAILIMF_FIELD_RESENT_TO;
4087 return MAILIMF_FIELD_RESENT_CC;
4089 return MAILIMF_FIELD_RESENT_BCC;
4091 return MAILIMF_FIELD_RESENT_MSG_ID;
4093 return MAILIMF_FIELD_NONE;
4101 static int mailimf_field_parse(const char * message, size_t length,
4103 struct mailimf_field ** result)
4107 struct mailimf_return * return_path;
4108 struct mailimf_orig_date * resent_date;
4109 struct mailimf_from * resent_from;
4110 struct mailimf_sender * resent_sender;
4111 struct mailimf_to* resent_to;
4112 struct mailimf_cc * resent_cc;
4113 struct mailimf_bcc * resent_bcc;
4114 struct mailimf_message_id * resent_msg_id;
4115 struct mailimf_orig_date * orig_date;
4116 struct mailimf_from * from;
4117 struct mailimf_sender * sender;
4118 struct mailimf_reply_to * reply_to;
4119 struct mailimf_to * to;
4120 struct mailimf_cc * cc;
4121 struct mailimf_bcc * bcc;
4122 struct mailimf_message_id * message_id;
4123 struct mailimf_in_reply_to * in_reply_to;
4124 struct mailimf_references * references;
4125 struct mailimf_subject * subject;
4126 struct mailimf_comments * comments;
4127 struct mailimf_keywords * keywords;
4128 struct mailimf_optional_field * optional_field;
4129 struct mailimf_field * field;
4134 cur_token = * index;
4139 resent_sender = NULL;
4143 resent_msg_id = NULL;
4157 optional_field = NULL;
4159 guessed_type = guess_header_type(message, length, cur_token);
4160 type = MAILIMF_FIELD_NONE;
4162 switch (guessed_type) {
4163 case MAILIMF_FIELD_ORIG_DATE:
4164 r = mailimf_orig_date_parse(message, length, &cur_token,
4166 if (r == MAILIMF_NO_ERROR)
4167 type = MAILIMF_FIELD_ORIG_DATE;
4168 else if (r == MAILIMF_ERROR_PARSE) {
4176 case MAILIMF_FIELD_FROM:
4177 r = mailimf_from_parse(message, length, &cur_token,
4179 if (r == MAILIMF_NO_ERROR)
4180 type = guessed_type;
4181 else if (r == MAILIMF_ERROR_PARSE) {
4189 case MAILIMF_FIELD_SENDER:
4190 r = mailimf_sender_parse(message, length, &cur_token,
4192 if (r == MAILIMF_NO_ERROR)
4193 type = guessed_type;
4194 else if (r == MAILIMF_ERROR_PARSE) {
4202 case MAILIMF_FIELD_REPLY_TO:
4203 r = mailimf_reply_to_parse(message, length, &cur_token,
4205 if (r == MAILIMF_NO_ERROR)
4206 type = guessed_type;
4207 else if (r == MAILIMF_ERROR_PARSE) {
4215 case MAILIMF_FIELD_TO:
4216 r = mailimf_to_parse(message, length, &cur_token,
4218 if (r == MAILIMF_NO_ERROR)
4219 type = guessed_type;
4220 else if (r == MAILIMF_ERROR_PARSE) {
4228 case MAILIMF_FIELD_CC:
4229 r = mailimf_cc_parse(message, length, &cur_token,
4231 if (r == MAILIMF_NO_ERROR)
4232 type = guessed_type;
4233 else if (r == MAILIMF_ERROR_PARSE) {
4241 case MAILIMF_FIELD_BCC:
4242 r = mailimf_bcc_parse(message, length, &cur_token,
4244 if (r == MAILIMF_NO_ERROR)
4245 type = guessed_type;
4246 else if (r == MAILIMF_ERROR_PARSE) {
4254 case MAILIMF_FIELD_MESSAGE_ID:
4255 r = mailimf_message_id_parse(message, length, &cur_token,
4257 if (r == MAILIMF_NO_ERROR)
4258 type = guessed_type;
4259 else if (r == MAILIMF_ERROR_PARSE) {
4267 case MAILIMF_FIELD_IN_REPLY_TO:
4268 r = mailimf_in_reply_to_parse(message, length, &cur_token,
4270 if (r == MAILIMF_NO_ERROR)
4271 type = guessed_type;
4272 else if (r == MAILIMF_ERROR_PARSE) {
4280 case MAILIMF_FIELD_REFERENCES:
4281 r = mailimf_references_parse(message, length, &cur_token,
4283 if (r == MAILIMF_NO_ERROR)
4284 type = guessed_type;
4285 else if (r == MAILIMF_ERROR_PARSE) {
4293 case MAILIMF_FIELD_SUBJECT:
4294 r = mailimf_subject_parse(message, length, &cur_token,
4296 if (r == MAILIMF_NO_ERROR)
4297 type = guessed_type;
4298 else if (r == MAILIMF_ERROR_PARSE) {
4306 case MAILIMF_FIELD_COMMENTS:
4307 r = mailimf_comments_parse(message, length, &cur_token,
4309 if (r == MAILIMF_NO_ERROR)
4310 type = guessed_type;
4311 else if (r == MAILIMF_ERROR_PARSE) {
4319 case MAILIMF_FIELD_KEYWORDS:
4320 r = mailimf_keywords_parse(message, length, &cur_token,
4322 if (r == MAILIMF_NO_ERROR)
4323 type = guessed_type;
4324 else if (r == MAILIMF_ERROR_PARSE) {
4332 case MAILIMF_FIELD_RETURN_PATH:
4333 r = mailimf_return_parse(message, length, &cur_token,
4335 if (r == MAILIMF_NO_ERROR)
4336 type = guessed_type;
4337 else if (r == MAILIMF_ERROR_PARSE) {
4345 case MAILIMF_FIELD_RESENT_DATE:
4346 r = mailimf_resent_date_parse(message, length, &cur_token,
4348 if (r == MAILIMF_NO_ERROR)
4349 type = guessed_type;
4350 else if (r == MAILIMF_ERROR_PARSE) {
4358 case MAILIMF_FIELD_RESENT_FROM:
4359 r = mailimf_resent_from_parse(message, length, &cur_token,
4361 if (r == MAILIMF_NO_ERROR)
4362 type = guessed_type;
4363 else if (r == MAILIMF_ERROR_PARSE) {
4371 case MAILIMF_FIELD_RESENT_SENDER:
4372 r = mailimf_resent_sender_parse(message, length, &cur_token,
4374 if (r == MAILIMF_NO_ERROR)
4375 type = guessed_type;
4376 else if (r == MAILIMF_ERROR_PARSE) {
4384 case MAILIMF_FIELD_RESENT_TO:
4385 r = mailimf_resent_to_parse(message, length, &cur_token,
4387 if (r == MAILIMF_NO_ERROR)
4388 type = guessed_type;
4389 else if (r == MAILIMF_ERROR_PARSE) {
4397 case MAILIMF_FIELD_RESENT_CC:
4398 r= mailimf_resent_cc_parse(message, length, &cur_token,
4400 if (r == MAILIMF_NO_ERROR)
4401 type = guessed_type;
4402 else if (r == MAILIMF_ERROR_PARSE) {
4410 case MAILIMF_FIELD_RESENT_BCC:
4411 r = mailimf_resent_bcc_parse(message, length, &cur_token,
4413 if (r == MAILIMF_NO_ERROR)
4414 type = guessed_type;
4415 else if (r == MAILIMF_ERROR_PARSE) {
4423 case MAILIMF_FIELD_RESENT_MSG_ID:
4424 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
4426 if (r == MAILIMF_NO_ERROR)
4427 type = guessed_type;
4428 else if (r == MAILIMF_ERROR_PARSE) {
4438 if (type == MAILIMF_FIELD_NONE) {
4439 r = mailimf_optional_field_parse(message, length, &cur_token,
4441 if (r != MAILIMF_NO_ERROR) {
4446 type = MAILIMF_FIELD_OPTIONAL_FIELD;
4449 field = mailimf_field_new(type, return_path, resent_date,
4450 resent_from, resent_sender, resent_to, resent_cc, resent_bcc,
4451 resent_msg_id, orig_date, from, sender, reply_to, to,
4452 cc, bcc, message_id, in_reply_to, references,
4453 subject, comments, keywords, optional_field);
4454 if (field == NULL) {
4455 res = MAILIMF_ERROR_MEMORY;
4460 * index = cur_token;
4462 return MAILIMF_NO_ERROR;
4465 if (return_path != NULL)
4466 mailimf_return_free(return_path);
4467 if (resent_date != NULL)
4468 mailimf_orig_date_free(resent_date);
4469 if (resent_from != NULL)
4470 mailimf_from_free(resent_from);
4471 if (resent_sender != NULL)
4472 mailimf_sender_free(resent_sender);
4473 if (resent_to != NULL)
4474 mailimf_to_free(resent_to);
4475 if (resent_cc != NULL)
4476 mailimf_cc_free(resent_cc);
4477 if (resent_bcc != NULL)
4478 mailimf_bcc_free(resent_bcc);
4479 if (resent_msg_id != NULL)
4480 mailimf_message_id_free(resent_msg_id);
4481 if (orig_date != NULL)
4482 mailimf_orig_date_free(orig_date);
4484 mailimf_from_free(from);
4486 mailimf_sender_free(sender);
4487 if (reply_to != NULL)
4488 mailimf_reply_to_free(reply_to);
4490 mailimf_to_free(to);
4492 mailimf_cc_free(cc);
4494 mailimf_bcc_free(bcc);
4495 if (message_id != NULL)
4496 mailimf_message_id_free(message_id);
4497 if (in_reply_to != NULL)
4498 mailimf_in_reply_to_free(in_reply_to);
4499 if (references != NULL)
4500 mailimf_references_free(references);
4501 if (subject != NULL)
4502 mailimf_subject_free(subject);
4503 if (comments != NULL)
4504 mailimf_comments_free(comments);
4505 if (keywords != NULL)
4506 mailimf_keywords_free(keywords);
4507 if (optional_field != NULL)
4508 mailimf_optional_field_free(optional_field);
4515 fields = *(delivering-info /
4534 mailimf_unparsed_fields_parse(const char * message, size_t length,
4536 struct mailimf_unparsed_fields ** result)
4540 struct mailimf_unparsed_fields * fields;
4544 cur_token = * index;
4548 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4550 (mailimf_struct_parser *)
4551 mailimf_optional_field_parse,
4552 (mailimf_struct_destructor *)
4553 mailimf_optional_field_free);
4555 if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4562 case MAILIMF_NO_ERROR:
4566 case MAILIMF_ERROR_PARSE:
4569 res = MAILIMF_ERROR_MEMORY;
4579 fields = mailimf_unparsed_fields_new(list);
4580 if (fields == NULL) {
4581 res = MAILIMF_ERROR_MEMORY;
4586 * index = cur_token;
4588 return MAILIMF_NO_ERROR;
4592 clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL);
4600 int mailimf_fields_parse(const char * message, size_t length,
4602 struct mailimf_fields ** result)
4606 struct mailimf_fields * fields;
4610 cur_token = * index;
4614 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4616 (mailimf_struct_parser *)
4617 mailimf_field_parse,
4618 (mailimf_struct_destructor *)
4619 mailimf_field_free);
4621 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4628 case MAILIMF_NO_ERROR:
4632 case MAILIMF_ERROR_PARSE:
4635 res = MAILIMF_ERROR_MEMORY;
4645 fields = mailimf_fields_new(list);
4646 if (fields == NULL) {
4647 res = MAILIMF_ERROR_MEMORY;
4652 * index = cur_token;
4654 return MAILIMF_NO_ERROR;
4658 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
4666 orig-date = "Date:" date-time CRLF
4671 mailimf_orig_date_parse(const char * message, size_t length,
4672 size_t * index, struct mailimf_orig_date ** result)
4674 struct mailimf_date_time * date_time;
4675 struct mailimf_orig_date * orig_date;
4680 cur_token = * index;
4682 r = mailimf_token_case_insensitive_parse(message, length,
4683 &cur_token, "Date:");
4684 if (r != MAILIMF_NO_ERROR) {
4689 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
4690 if (r != MAILIMF_NO_ERROR) {
4695 r = mailimf_ignore_unstructured_parse(message, length, &cur_token);
4696 if (r != MAILIMF_NO_ERROR) {
4698 goto free_date_time;
4701 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4702 if (r != MAILIMF_NO_ERROR) {
4704 goto free_date_time;
4707 orig_date = mailimf_orig_date_new(date_time);
4708 if (orig_date == NULL) {
4709 res = MAILIMF_ERROR_MEMORY;
4710 goto free_date_time;
4713 * result = orig_date;
4714 * index = cur_token;
4716 return MAILIMF_NO_ERROR;
4719 mailimf_date_time_free(date_time);
4725 from = "From:" mailbox-list CRLF
4729 mailimf_from_parse(const char * message, size_t length,
4730 size_t * index, struct mailimf_from ** result)
4732 struct mailimf_mailbox_list * mb_list;
4733 struct mailimf_from * from;
4738 cur_token = * index;
4740 r = mailimf_token_case_insensitive_parse(message, length,
4741 &cur_token, "From");
4742 if (r != MAILIMF_NO_ERROR) {
4747 r = mailimf_colon_parse(message, length, &cur_token);
4748 if (r != MAILIMF_NO_ERROR) {
4753 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
4755 if (r != MAILIMF_NO_ERROR) {
4760 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4761 if (r != MAILIMF_NO_ERROR) {
4766 from = mailimf_from_new(mb_list);
4768 res = MAILIMF_ERROR_MEMORY;
4773 * index = cur_token;
4775 return MAILIMF_NO_ERROR;
4778 mailimf_mailbox_list_free(mb_list);
4784 sender = "Sender:" mailbox CRLF
4788 mailimf_sender_parse(const char * message, size_t length,
4789 size_t * index, struct mailimf_sender ** result)
4791 struct mailimf_mailbox * mb;
4792 struct mailimf_sender * sender;
4797 cur_token = * index;
4799 r = mailimf_token_case_insensitive_parse(message, length,
4800 &cur_token, "Sender");
4801 if (r != MAILIMF_NO_ERROR) {
4806 r = mailimf_colon_parse(message, length, &cur_token);
4807 if (r != MAILIMF_NO_ERROR) {
4812 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
4813 if (r != MAILIMF_NO_ERROR) {
4818 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4819 if (r != MAILIMF_NO_ERROR) {
4824 sender = mailimf_sender_new(mb);
4825 if (sender == NULL) {
4826 res = MAILIMF_ERROR_MEMORY;
4831 * index = cur_token;
4833 return MAILIMF_NO_ERROR;
4836 mailimf_mailbox_free(mb);
4842 reply-to = "Reply-To:" address-list CRLF
4847 mailimf_reply_to_parse(const char * message, size_t length,
4848 size_t * index, struct mailimf_reply_to ** result)
4850 struct mailimf_address_list * addr_list;
4851 struct mailimf_reply_to * reply_to;
4856 cur_token = * index;
4858 r = mailimf_token_case_insensitive_parse(message, length,
4859 &cur_token, "Reply-To");
4860 if (r != MAILIMF_NO_ERROR) {
4865 r = mailimf_colon_parse(message, length, &cur_token);
4866 if (r != MAILIMF_NO_ERROR) {
4871 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4872 if (r != MAILIMF_NO_ERROR) {
4877 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4878 if (r != MAILIMF_NO_ERROR) {
4880 goto free_addr_list;
4883 reply_to = mailimf_reply_to_new(addr_list);
4884 if (reply_to == NULL) {
4885 res = MAILIMF_ERROR_MEMORY;
4886 goto free_addr_list;
4889 * result = reply_to;
4890 * index = cur_token;
4892 return MAILIMF_NO_ERROR;
4895 mailimf_address_list_free(addr_list);
4901 to = "To:" address-list CRLF
4905 mailimf_to_parse(const char * message, size_t length,
4906 size_t * index, struct mailimf_to ** result)
4908 struct mailimf_address_list * addr_list;
4909 struct mailimf_to * to;
4914 cur_token = * index;
4916 r = mailimf_token_case_insensitive_parse(message, length,
4918 if (r != MAILIMF_NO_ERROR) {
4923 r = mailimf_colon_parse(message, length, &cur_token);
4924 if (r != MAILIMF_NO_ERROR) {
4929 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4930 if (r != MAILIMF_NO_ERROR) {
4935 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4936 if (r != MAILIMF_NO_ERROR) {
4938 goto free_addr_list;
4941 to = mailimf_to_new(addr_list);
4943 res = MAILIMF_ERROR_MEMORY;
4944 goto free_addr_list;
4948 * index = cur_token;
4950 return MAILIMF_NO_ERROR;
4953 mailimf_address_list_free(addr_list);
4959 cc = "Cc:" address-list CRLF
4964 mailimf_cc_parse(const char * message, size_t length,
4965 size_t * index, struct mailimf_cc ** result)
4967 struct mailimf_address_list * addr_list;
4968 struct mailimf_cc * cc;
4973 cur_token = * index;
4975 r = mailimf_token_case_insensitive_parse(message, length,
4977 if (r != MAILIMF_NO_ERROR) {
4982 r = mailimf_colon_parse(message, length, &cur_token);
4983 if (r != MAILIMF_NO_ERROR) {
4988 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4989 if (r != MAILIMF_NO_ERROR) {
4994 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4995 if (r != MAILIMF_NO_ERROR) {
4997 goto free_addr_list;
5000 cc = mailimf_cc_new(addr_list);
5002 res = MAILIMF_ERROR_MEMORY;
5003 goto free_addr_list;
5007 * index = cur_token;
5009 return MAILIMF_NO_ERROR;
5012 mailimf_address_list_free(addr_list);
5018 bcc = "Bcc:" (address-list / [CFWS]) CRLF
5023 mailimf_bcc_parse(const char * message, size_t length,
5024 size_t * index, struct mailimf_bcc ** result)
5026 struct mailimf_address_list * addr_list;
5027 struct mailimf_bcc * bcc;
5032 cur_token = * index;
5035 r = mailimf_token_case_insensitive_parse(message, length,
5037 if (r != MAILIMF_NO_ERROR) {
5042 r = mailimf_colon_parse(message, length, &cur_token);
5043 if (r != MAILIMF_NO_ERROR) {
5048 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5050 case MAILIMF_NO_ERROR:
5053 case MAILIMF_ERROR_PARSE:
5054 r = mailimf_cfws_parse(message, length, &cur_token);
5055 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
5065 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5066 if (r != MAILIMF_NO_ERROR) {
5068 goto free_addr_list;
5071 bcc = mailimf_bcc_new(addr_list);
5073 res = MAILIMF_ERROR_MEMORY;
5074 goto free_addr_list;
5078 * index = cur_token;
5080 return MAILIMF_NO_ERROR;
5083 mailimf_address_list_free(addr_list);
5089 message-id = "Message-ID:" msg-id CRLF
5092 static int mailimf_message_id_parse(const char * message, size_t length,
5094 struct mailimf_message_id ** result)
5098 struct mailimf_message_id * message_id;
5102 cur_token = * index;
5104 r = mailimf_token_case_insensitive_parse(message, length,
5105 &cur_token, "Message-ID");
5106 if (r != MAILIMF_NO_ERROR) {
5111 r = mailimf_colon_parse(message, length, &cur_token);
5112 if (r != MAILIMF_NO_ERROR) {
5117 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
5118 if (r != MAILIMF_NO_ERROR) {
5123 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5124 if (r != MAILIMF_NO_ERROR) {
5129 message_id = mailimf_message_id_new(value);
5130 if (message_id == NULL) {
5131 res = MAILIMF_ERROR_MEMORY;
5135 * result = message_id;
5136 * index = cur_token;
5138 return MAILIMF_NO_ERROR;
5141 mailimf_msg_id_free(value);
5147 in-reply-to = "In-Reply-To:" 1*msg-id CRLF
5150 int mailimf_msg_id_list_parse(const char * message, size_t length,
5151 size_t * index, clist ** result)
5153 return mailimf_struct_multiple_parse(message, length, index,
5155 (mailimf_struct_parser *)
5156 mailimf_unstrict_msg_id_parse,
5157 (mailimf_struct_destructor *)
5158 mailimf_msg_id_free);
5161 static int mailimf_in_reply_to_parse(const char * message, size_t length,
5163 struct mailimf_in_reply_to ** result)
5165 struct mailimf_in_reply_to * in_reply_to;
5167 clist * msg_id_list;
5171 cur_token = * index;
5173 r = mailimf_token_case_insensitive_parse(message, length,
5174 &cur_token, "In-Reply-To");
5175 if (r != MAILIMF_NO_ERROR) {
5180 r = mailimf_colon_parse(message, length, &cur_token);
5181 if (r != MAILIMF_NO_ERROR) {
5186 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5187 if (r != MAILIMF_NO_ERROR) {
5192 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5193 if (r != MAILIMF_NO_ERROR) {
5198 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
5199 if (in_reply_to == NULL) {
5200 res = MAILIMF_ERROR_MEMORY;
5204 * result = in_reply_to;
5205 * index = cur_token;
5207 return MAILIMF_NO_ERROR;
5210 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5211 clist_free(msg_id_list);
5217 references = "References:" 1*msg-id CRLF
5220 int mailimf_references_parse(const char * message, size_t length,
5222 struct mailimf_references ** result)
5224 struct mailimf_references * references;
5226 clist * msg_id_list;
5230 cur_token = * index;
5232 r = mailimf_token_case_insensitive_parse(message, length,
5233 &cur_token, "References");
5234 if (r != MAILIMF_NO_ERROR) {
5239 r = mailimf_colon_parse(message, length, &cur_token);
5240 if (r != MAILIMF_NO_ERROR) {
5245 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5246 if (r != MAILIMF_NO_ERROR) {
5251 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5252 if (r != MAILIMF_NO_ERROR) {
5257 references = mailimf_references_new(msg_id_list);
5258 if (references == NULL) {
5259 res = MAILIMF_ERROR_MEMORY;
5263 * result = references;
5264 * index = cur_token;
5266 return MAILIMF_NO_ERROR;
5269 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5270 clist_free(msg_id_list);
5276 msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
5279 int mailimf_msg_id_parse(const char * message, size_t length,
5292 cur_token = * index;
5294 r = mailimf_cfws_parse(message, length, &cur_token);
5295 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5298 r = mailimf_lower_parse(message, length, &cur_token);
5299 if (r != MAILIMF_NO_ERROR) {
5304 r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id);
5305 if (r != MAILIMF_NO_ERROR) {
5310 r = mailimf_greater_parse(message, length, &cur_token);
5311 if (r != MAILIMF_NO_ERROR) {
5318 r = mailimf_id_left_parse(message, length, &cur_token, &id_left);
5319 if (r != MAILIMF_NO_ERROR) {
5324 r = mailimf_at_sign_parse(message, length, &cur_token);
5325 if (r != MAILIMF_NO_ERROR) {
5330 r = mailimf_id_right_parse(message, length, &cur_token, &id_right);
5331 if (r != MAILIMF_NO_ERROR) {
5336 r = mailimf_greater_parse(message, length, &cur_token);
5337 if (r != MAILIMF_NO_ERROR) {
5342 msg_id = malloc(strlen(id_left) + strlen(id_right) + 2);
5343 if (msg_id == NULL) {
5344 res = MAILIMF_ERROR_MEMORY;
5347 strcpy(msg_id, id_left);
5348 strcat(msg_id, "@");
5349 strcat(msg_id, id_right);
5351 mailimf_id_left_free(id_left);
5352 mailimf_id_right_free(id_right);
5356 * index = cur_token;
5358 return MAILIMF_NO_ERROR;
5362 mailimf_id_right_free(id_right);
5364 mailimf_id_left_free(id_left);
5368 mailimf_atom_free(msg_id);
5374 static int mailimf_parse_unwanted_msg_id(const char * message, size_t length,
5382 cur_token = * index;
5384 token_parsed = TRUE;
5385 while (token_parsed) {
5386 token_parsed = FALSE;
5387 r = mailimf_word_parse(message, length, &cur_token, &word);
5388 if (r == MAILIMF_NO_ERROR) {
5389 mailimf_word_free(word);
5390 token_parsed = TRUE;
5392 else if (r == MAILIMF_ERROR_PARSE) {
5397 r = mailimf_semi_colon_parse(message, length, &cur_token);
5398 if (r == MAILIMF_NO_ERROR)
5399 token_parsed = TRUE;
5400 else if (r == MAILIMF_ERROR_PARSE) {
5405 r = mailimf_comma_parse(message, length, &cur_token);
5406 if (r == MAILIMF_NO_ERROR)
5407 token_parsed = TRUE;
5408 else if (r == MAILIMF_ERROR_PARSE) {
5413 r = mailimf_plus_parse(message, length, &cur_token);
5414 if (r == MAILIMF_NO_ERROR)
5415 token_parsed = TRUE;
5416 else if (r == MAILIMF_ERROR_PARSE) {
5421 r = mailimf_colon_parse(message, length, &cur_token);
5422 if (r == MAILIMF_NO_ERROR)
5423 token_parsed = TRUE;
5424 else if (r == MAILIMF_ERROR_PARSE) {
5429 r = mailimf_point_parse(message, length, &cur_token);
5430 if (r == MAILIMF_NO_ERROR)
5431 token_parsed = TRUE;
5432 else if (r == MAILIMF_ERROR_PARSE) {
5437 r = mailimf_at_sign_parse(message, length, &cur_token);
5438 if (r == MAILIMF_NO_ERROR)
5439 token_parsed = TRUE;
5440 else if (r == MAILIMF_ERROR_PARSE) {
5447 return MAILIMF_NO_ERROR;
5450 static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
5458 cur_token = * index;
5460 r = mailimf_cfws_parse(message, length, &cur_token);
5461 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5464 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5465 if (r != MAILIMF_NO_ERROR)
5468 r = mailimf_msg_id_parse(message, length, &cur_token, &msgid);
5469 if (r != MAILIMF_NO_ERROR)
5472 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5473 if (r != MAILIMF_NO_ERROR)
5477 * index = cur_token;
5479 return MAILIMF_NO_ERROR;
5483 id-left = dot-atom-text / no-fold-quote / obs-id-left
5487 static int mailimf_id_left_parse(const char * message, size_t length,
5488 size_t * index, char ** result)
5492 r = mailimf_dot_atom_text_parse(message, length, index, result);
5494 case MAILIMF_NO_ERROR:
5495 return MAILIMF_NO_ERROR;
5496 case MAILIMF_ERROR_PARSE:
5502 r = mailimf_no_fold_quote_parse(message, length, index, result);
5503 if (r != MAILIMF_NO_ERROR)
5506 return MAILIMF_NO_ERROR;
5511 id-right = dot-atom-text / no-fold-literal / obs-id-right
5515 static int mailimf_id_right_parse(const char * message, size_t length,
5516 size_t * index, char ** result)
5520 r = mailimf_dot_atom_text_parse(message, length, index, result);
5522 case MAILIMF_NO_ERROR:
5523 return MAILIMF_NO_ERROR;
5524 case MAILIMF_ERROR_PARSE:
5530 r = mailimf_no_fold_literal_parse(message, length, index, result);
5531 if (r != MAILIMF_NO_ERROR)
5534 return MAILIMF_NO_ERROR;
5539 no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
5543 static int mailimf_no_fold_quote_char_parse(const char * message, size_t length,
5544 size_t * index, char * result)
5550 cur_token = * index;
5553 r = mailimf_qtext_parse(message, length, &cur_token, &ch);
5556 if (cur_token >= length)
5557 return MAILIMF_ERROR_PARSE;
5559 if (is_qtext(message[cur_token])) {
5560 ch = message[cur_token];
5564 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5566 if (r != MAILIMF_NO_ERROR)
5570 * index = cur_token;
5573 return MAILIMF_NO_ERROR;
5578 static int mailimf_no_fold_quote_parse(const char * message, size_t length,
5579 size_t * index, char ** result)
5584 char * no_fold_quote;
5589 r = mailimf_dquote_parse(message, length, &cur_token);
5590 if (r != MAILIMF_NO_ERROR) {
5596 r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch);
5597 if (r == MAILIMF_NO_ERROR) {
5600 else if (r == MAILIMF_ERROR_PARSE)
5608 r = mailimf_dquote_parse(message, length, &cur_token);
5609 if (r != MAILIMF_NO_ERROR) {
5614 /* no_fold_quote = strndup(message + begin, cur_token - begin); */
5615 no_fold_quote = malloc(cur_token - begin + 1);
5616 if (no_fold_quote == NULL) {
5617 res = MAILIMF_ERROR_MEMORY;
5620 strncpy(no_fold_quote, message + begin, cur_token - begin);
5621 no_fold_quote[cur_token - begin] = '\0';
5623 * result = no_fold_quote;
5624 * index = cur_token;
5626 return MAILIMF_NO_ERROR;
5634 no-fold-literal = "[" *(dtext / quoted-pair) "]"
5639 mailimf_no_fold_literal_char_parse(const char * message, size_t length,
5640 size_t * index, char * result)
5646 cur_token = * index;
5649 r = mailimf_dtext_parse(message, length, &cur_token, &ch);
5651 if (cur_token >= length)
5652 return MAILIMF_ERROR_PARSE;
5654 if (is_dtext(message[cur_token])) {
5655 ch = message[cur_token];
5659 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5661 if (r != MAILIMF_NO_ERROR)
5665 * index = cur_token;
5668 return MAILIMF_NO_ERROR;
5673 static int mailimf_no_fold_literal_parse(const char * message, size_t length,
5674 size_t * index, char ** result)
5679 char * no_fold_literal;
5684 r = mailimf_obracket_parse(message, length, &cur_token);
5685 if (r != MAILIMF_NO_ERROR) {
5691 r = mailimf_no_fold_literal_char_parse(message, length,
5693 if (r == MAILIMF_NO_ERROR) {
5696 else if (r == MAILIMF_ERROR_PARSE)
5704 r = mailimf_cbracket_parse(message, length, &cur_token);
5705 if (r != MAILIMF_NO_ERROR) {
5711 no_fold_literal = strndup(message + begin, cur_token - begin);
5713 no_fold_literal = malloc(cur_token - begin + 1);
5714 if (no_fold_literal == NULL) {
5715 res = MAILIMF_NO_ERROR;
5718 strncpy(no_fold_literal, message + begin, cur_token - begin);
5719 no_fold_literal[cur_token - begin] = '\0';
5721 * result = no_fold_literal;
5722 * index = cur_token;
5724 return MAILIMF_NO_ERROR;
5732 subject = "Subject:" unstructured CRLF
5735 static int mailimf_subject_parse(const char * message, size_t length,
5737 struct mailimf_subject ** result)
5739 struct mailimf_subject * subject;
5745 cur_token = * index;
5747 r = mailimf_token_case_insensitive_parse(message, length,
5748 &cur_token, "Subject");
5749 if (r != MAILIMF_NO_ERROR) {
5754 r = mailimf_colon_parse(message, length, &cur_token);
5755 if (r != MAILIMF_NO_ERROR) {
5760 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5761 if (r != MAILIMF_NO_ERROR) {
5766 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5767 if (r != MAILIMF_NO_ERROR) {
5772 subject = mailimf_subject_new(value);
5773 if (subject == NULL) {
5774 res = MAILIMF_ERROR_MEMORY;
5779 * index = cur_token;
5781 return MAILIMF_NO_ERROR;
5784 mailimf_unstructured_free(value);
5790 comments = "Comments:" unstructured CRLF
5793 static int mailimf_comments_parse(const char * message, size_t length,
5795 struct mailimf_comments ** result)
5797 struct mailimf_comments * comments;
5803 cur_token = * index;
5805 r = mailimf_token_case_insensitive_parse(message, length,
5806 &cur_token, "Comments");
5807 if (r != MAILIMF_NO_ERROR) {
5812 r = mailimf_colon_parse(message, length, &cur_token);
5813 if (r != MAILIMF_NO_ERROR) {
5818 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5819 if (r != MAILIMF_NO_ERROR) {
5824 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5825 if (r != MAILIMF_NO_ERROR) {
5830 comments = mailimf_comments_new(value);
5831 if (comments == NULL) {
5832 res = MAILIMF_ERROR_MEMORY;
5836 * result = comments;
5837 * index = cur_token;
5839 return MAILIMF_NO_ERROR;
5842 mailimf_unstructured_free(value);
5848 keywords = "Keywords:" phrase *("," phrase) CRLF
5851 static int mailimf_keywords_parse(const char * message, size_t length,
5853 struct mailimf_keywords ** result)
5855 struct mailimf_keywords * keywords;
5861 cur_token = * index;
5863 r = mailimf_token_case_insensitive_parse(message, length,
5864 &cur_token, "Keywords");
5865 if (r != MAILIMF_NO_ERROR) {
5870 r = mailimf_colon_parse(message, length, &cur_token);
5871 if (r != MAILIMF_NO_ERROR) {
5876 r = mailimf_struct_list_parse(message, length, &cur_token,
5878 (mailimf_struct_parser *)
5879 mailimf_phrase_parse,
5880 (mailimf_struct_destructor *)
5881 mailimf_phrase_free);
5882 if (r != MAILIMF_NO_ERROR) {
5887 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5888 if (r != MAILIMF_NO_ERROR) {
5893 keywords = mailimf_keywords_new(list);
5894 if (keywords == NULL) {
5895 res = MAILIMF_ERROR_MEMORY;
5899 * result = keywords;
5900 * index = cur_token;
5902 return MAILIMF_NO_ERROR;
5905 clist_foreach(list, (clist_func) mailimf_phrase_free, NULL);
5912 resent-date = "Resent-Date:" date-time CRLF
5916 mailimf_resent_date_parse(const char * message, size_t length,
5917 size_t * index, struct mailimf_orig_date ** result)
5919 struct mailimf_orig_date * orig_date;
5920 struct mailimf_date_time * date_time;
5925 cur_token = * index;
5927 r = mailimf_token_case_insensitive_parse(message, length,
5928 &cur_token, "Resent-Date");
5929 if (r != MAILIMF_NO_ERROR) {
5934 r = mailimf_colon_parse(message, length, &cur_token);
5935 if (r != MAILIMF_NO_ERROR) {
5940 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
5941 if (r != MAILIMF_NO_ERROR) {
5946 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5947 if (r != MAILIMF_NO_ERROR) {
5949 goto free_date_time;
5952 orig_date = mailimf_orig_date_new(date_time);
5953 if (orig_date == NULL) {
5954 res = MAILIMF_ERROR_MEMORY;
5955 goto free_date_time;
5958 * result = orig_date;
5959 * index = cur_token;
5961 return MAILIMF_NO_ERROR;
5964 mailimf_date_time_free(date_time);
5970 resent-from = "Resent-From:" mailbox-list CRLF
5974 mailimf_resent_from_parse(const char * message, size_t length,
5975 size_t * index, struct mailimf_from ** result)
5977 struct mailimf_mailbox_list * mb_list;
5978 struct mailimf_from * from;
5983 cur_token = * index;
5985 r = mailimf_token_case_insensitive_parse(message, length,
5986 &cur_token, "Resent-From");
5987 if (r != MAILIMF_NO_ERROR) {
5992 r = mailimf_colon_parse(message, length, &cur_token);
5993 if (r != MAILIMF_NO_ERROR) {
5998 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
5999 if (r != MAILIMF_NO_ERROR) {
6004 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6005 if (r != MAILIMF_NO_ERROR) {
6010 from = mailimf_from_new(mb_list);
6012 res = MAILIMF_ERROR_MEMORY;
6017 * index = cur_token;
6019 return MAILIMF_NO_ERROR;
6022 mailimf_mailbox_list_free(mb_list);
6028 resent-sender = "Resent-Sender:" mailbox CRLF
6032 mailimf_resent_sender_parse(const char * message, size_t length,
6033 size_t * index, struct mailimf_sender ** result)
6035 struct mailimf_mailbox * mb;
6036 struct mailimf_sender * sender;
6043 r = mailimf_token_case_insensitive_parse(message, length,
6044 &cur_token, "Resent-Sender");
6045 if (r != MAILIMF_NO_ERROR) {
6050 r = mailimf_colon_parse(message, length, &cur_token);
6051 if (r != MAILIMF_NO_ERROR) {
6056 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
6057 if (r != MAILIMF_NO_ERROR) {
6062 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6063 if (r != MAILIMF_NO_ERROR) {
6068 sender = mailimf_sender_new(mb);
6069 if (sender == NULL) {
6070 res = MAILIMF_ERROR_MEMORY;
6075 * index = cur_token;
6077 return MAILIMF_NO_ERROR;
6080 mailimf_mailbox_free(mb);
6086 resent-to = "Resent-To:" address-list CRLF
6090 mailimf_resent_to_parse(const char * message, size_t length,
6091 size_t * index, struct mailimf_to ** result)
6093 struct mailimf_address_list * addr_list;
6094 struct mailimf_to * to;
6099 cur_token = * index;
6101 r = mailimf_token_case_insensitive_parse(message, length,
6102 &cur_token, "Resent-To");
6103 if (r != MAILIMF_NO_ERROR) {
6108 r = mailimf_colon_parse(message, length, &cur_token);
6109 if (r != MAILIMF_NO_ERROR) {
6114 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6115 if (r != MAILIMF_NO_ERROR) {
6120 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6121 if (r != MAILIMF_NO_ERROR) {
6123 goto free_addr_list;
6126 to = mailimf_to_new(addr_list);
6128 res = MAILIMF_ERROR_MEMORY;
6129 goto free_addr_list;
6133 * index = cur_token;
6135 return MAILIMF_NO_ERROR;
6138 mailimf_address_list_free(addr_list);
6144 resent-cc = "Resent-Cc:" address-list CRLF
6148 mailimf_resent_cc_parse(const char * message, size_t length,
6149 size_t * index, struct mailimf_cc ** result)
6151 struct mailimf_address_list * addr_list;
6152 struct mailimf_cc * cc;
6157 cur_token = * index;
6159 r = mailimf_token_case_insensitive_parse(message, length,
6160 &cur_token, "Resent-Cc");
6161 if (r != MAILIMF_NO_ERROR) {
6166 r = mailimf_colon_parse(message, length, &cur_token);
6167 if (r != MAILIMF_NO_ERROR) {
6172 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6173 if (r != MAILIMF_NO_ERROR) {
6178 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6179 if (r != MAILIMF_NO_ERROR) {
6181 goto free_addr_list;
6184 cc = mailimf_cc_new(addr_list);
6186 res = MAILIMF_ERROR_MEMORY;
6187 goto free_addr_list;
6191 * index = cur_token;
6193 return MAILIMF_NO_ERROR;
6196 mailimf_address_list_free(addr_list);
6202 resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF
6206 mailimf_resent_bcc_parse(const char * message, size_t length,
6207 size_t * index, struct mailimf_bcc ** result)
6209 struct mailimf_address_list * addr_list;
6210 struct mailimf_bcc * bcc;
6215 cur_token = * index;
6218 r = mailimf_token_case_insensitive_parse(message, length,
6219 &cur_token, "Resent-Bcc");
6220 if (r != MAILIMF_NO_ERROR) {
6225 r = mailimf_colon_parse(message, length, &cur_token);
6226 if (r != MAILIMF_NO_ERROR) {
6231 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6232 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6237 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6238 if (r != MAILIMF_NO_ERROR) {
6240 goto free_addr_list;
6243 bcc = mailimf_bcc_new(addr_list);
6245 res = MAILIMF_ERROR_MEMORY;
6246 goto free_addr_list;
6250 * index = cur_token;
6255 mailimf_address_list_free(addr_list);
6261 resent-msg-id = "Resent-Message-ID:" msg-id CRLF
6265 mailimf_resent_msg_id_parse(const char * message, size_t length,
6267 struct mailimf_message_id ** result)
6271 struct mailimf_message_id * message_id;
6275 cur_token = * index;
6277 r = mailimf_token_case_insensitive_parse(message, length,
6278 &cur_token, "Resent-Message-ID");
6279 if (r != MAILIMF_NO_ERROR) {
6284 r = mailimf_colon_parse(message, length, &cur_token);
6285 if (r != MAILIMF_NO_ERROR) {
6290 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
6291 if (r != MAILIMF_NO_ERROR) {
6296 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6297 if (r != MAILIMF_NO_ERROR) {
6302 message_id = mailimf_message_id_new(value);
6303 if (message_id == NULL) {
6304 res = MAILIMF_ERROR_MEMORY;
6308 * result = message_id;
6309 * index = cur_token;
6311 return MAILIMF_NO_ERROR;
6314 mailimf_msg_id_free(value);
6325 static int mailimf_trace_parse(const char * message, size_t length,
6327 struct mailimf_trace ** result)
6330 struct mailimf_return * return_path;
6331 clist * received_list;
6332 struct mailimf_trace * trace;
6336 cur_token = * index;
6338 received_list = NULL;
6340 r = mailimf_return_parse(message, length, &cur_token, &return_path);
6341 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6346 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6348 (mailimf_struct_parser *)
6349 mailimf_received_parse,
6350 (mailimf_struct_destructor *)
6351 mailimf_received_free);
6352 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6357 if ((received_list == NULL) && (return_path == NULL)) {
6358 res = MAILIMF_ERROR_PARSE;
6362 trace = mailimf_trace_new(return_path, received_list);
6363 if (trace == NULL) {
6364 res = MAILIMF_ERROR_MEMORY;
6369 * index = cur_token;
6371 return MAILIMF_NO_ERROR;
6374 clist_foreach(received_list, (clist_func) mailimf_received_free, NULL);
6375 clist_free(received_list);
6377 if (return_path != NULL)
6378 mailimf_return_free(return_path);
6385 return = "Return-Path:" path CRLF
6388 static int mailimf_return_parse(const char * message, size_t length,
6390 struct mailimf_return ** result)
6392 struct mailimf_path * path = NULL;
6393 struct mailimf_return * return_path;
6398 cur_token = * index;
6400 r = mailimf_token_case_insensitive_parse(message, length,
6401 &cur_token, "Return-Path");
6402 if (r != MAILIMF_NO_ERROR) {
6407 r = mailimf_colon_parse(message, length, &cur_token);
6408 if (r != MAILIMF_NO_ERROR) {
6413 r = mailimf_path_parse(message, length, &cur_token, &path);
6414 if ( r!= MAILIMF_NO_ERROR) {
6419 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6420 if (r != MAILIMF_NO_ERROR) {
6425 return_path = mailimf_return_new(path);
6426 if (return_path == NULL) {
6427 res = MAILIMF_ERROR_MEMORY;
6431 * result = return_path;
6432 * index = cur_token;
6434 return MAILIMF_NO_ERROR;
6437 mailimf_path_free(path);
6443 path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
6447 static int mailimf_path_parse(const char * message, size_t length,
6448 size_t * index, struct mailimf_path ** result)
6452 struct mailimf_path * path;
6456 cur_token = * index;
6459 r = mailimf_cfws_parse(message, length, &cur_token);
6460 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6465 r = mailimf_lower_parse(message, length, &cur_token);
6466 if (r != MAILIMF_NO_ERROR) {
6471 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
6473 case MAILIMF_NO_ERROR:
6475 case MAILIMF_ERROR_PARSE:
6476 r = mailimf_cfws_parse(message, length, &cur_token);
6477 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6486 r = mailimf_greater_parse(message, length, &cur_token);
6487 if (r != MAILIMF_NO_ERROR) {
6492 path = mailimf_path_new(addr_spec);
6494 res = MAILIMF_ERROR_MEMORY;
6495 goto free_addr_spec;
6498 * index = cur_token;
6501 return MAILIMF_NO_ERROR;
6504 if (addr_spec == NULL)
6505 mailimf_addr_spec_free(addr_spec);
6511 received = "Received:" name-val-list ";" date-time CRLF
6515 static int mailimf_received_parse(const char * message, size_t length,
6517 struct mailimf_received ** result)
6520 struct mailimf_received * received;
6521 struct mailimf_name_val_list * name_val_list;
6522 struct mailimf_date_time * date_time;
6526 cur_token = * index;
6528 r = mailimf_token_case_insensitive_parse(message, length,
6529 &cur_token, "Received");
6530 if (r != MAILIMF_NO_ERROR) {
6535 r = mailimf_colon_parse(message, length, &cur_token);
6536 if (r != MAILIMF_NO_ERROR) {
6541 r = mailimf_name_val_list_parse(message, length,
6542 &cur_token, &name_val_list);
6543 if (r != MAILIMF_NO_ERROR) {
6548 r = mailimf_semi_colon_parse(message, length, &cur_token);
6549 if (r != MAILIMF_NO_ERROR) {
6551 goto free_name_val_list;
6554 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
6555 if (r != MAILIMF_NO_ERROR) {
6557 goto free_name_val_list;
6560 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6561 if (r != MAILIMF_NO_ERROR) {
6563 goto free_date_time;
6566 received = mailimf_received_new(name_val_list, date_time);
6567 if (received == NULL) {
6568 res = MAILIMF_ERROR_MEMORY;
6569 goto free_date_time;
6572 * index = cur_token;
6573 * result = received;
6575 return MAILIMF_NO_ERROR;
6578 mailimf_date_time_free(date_time);
6580 mailimf_name_val_list_free(name_val_list);
6587 name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
6592 mailimf_name_val_list_parse(const char * message, size_t length,
6594 struct mailimf_name_val_list ** result)
6597 struct mailimf_name_val_pair * pair;
6598 struct mailimf_name_val_list * name_val_list;
6603 cur_token = * index;
6606 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6608 if (r == MAILIMF_NO_ERROR){
6613 mailimf_name_val_pair_free(pair);
6614 res = MAILIMF_ERROR_MEMORY;
6618 r = clist_append(list, pair);
6620 mailimf_name_val_pair_free(pair);
6621 res = MAILIMF_ERROR_MEMORY;
6625 final_token = cur_token;
6628 r = mailimf_cfws_parse(message, length, &cur_token);
6629 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6634 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6635 if (r == MAILIMF_NO_ERROR) {
6638 else if (r == MAILIMF_ERROR_PARSE)
6645 r = clist_append(list, pair);
6647 mailimf_name_val_pair_free(pair);
6648 res = MAILIMF_ERROR_MEMORY;
6652 final_token = cur_token;
6654 cur_token = final_token;
6657 name_val_list = mailimf_name_val_list_new(list);
6658 if (name_val_list == NULL) {
6659 res = MAILIMF_ERROR_MEMORY;
6663 * index = cur_token;
6664 * result = name_val_list;
6666 return MAILIMF_NO_ERROR;
6670 clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL);
6679 name-val-pair = item-name CFWS item-value
6684 mailimf_name_val_pair_parse(const char * message, size_t length,
6686 struct mailimf_name_val_pair ** result)
6690 struct mailimf_item_value * item_value;
6691 struct mailimf_name_val_pair * name_val_pair;
6695 cur_token = * index;
6697 r = mailimf_cfws_parse(message, length, &cur_token);
6698 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6703 r = mailimf_item_name_parse(message, length, &cur_token, &item_name);
6704 if (r != MAILIMF_NO_ERROR) {
6709 r = mailimf_cfws_parse(message, length, &cur_token);
6710 if (r != MAILIMF_NO_ERROR) {
6712 goto free_item_name;
6715 r = mailimf_item_value_parse(message, length, &cur_token, &item_value);
6716 if (r != MAILIMF_NO_ERROR) {
6718 goto free_item_name;
6721 name_val_pair = mailimf_name_val_pair_new(item_name, item_value);
6722 if (name_val_pair == NULL) {
6723 res = MAILIMF_ERROR_MEMORY;
6724 goto free_item_value;
6727 * result = name_val_pair;
6728 * index = cur_token;
6730 return MAILIMF_NO_ERROR;
6733 mailimf_item_value_free(item_value);
6735 mailimf_item_name_free(item_name);
6742 item-name = ALPHA *(["-"] (ALPHA / DIGIT))
6746 static int mailimf_item_name_parse(const char * message, size_t length,
6747 size_t * index, char ** result)
6757 cur_token = * index;
6761 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6762 if (r != MAILIMF_NO_ERROR) {
6770 minus_sign = mailimf_minus_parse(message, length, &cur_token);
6772 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6773 if (r == MAILIMF_ERROR_PARSE)
6774 r = mailimf_digit_parse(message, length, &cur_token, &digit);
6776 if (r == MAILIMF_NO_ERROR) {
6779 if (r == MAILIMF_ERROR_PARSE)
6781 else if (r != MAILIMF_NO_ERROR) {
6787 item_name = strndup(message + begin, cur_token - begin);
6788 if (item_name == NULL) {
6789 res = MAILIMF_ERROR_MEMORY;
6793 * index = cur_token;
6794 * result = item_name;
6796 return MAILIMF_NO_ERROR;
6804 item-value = 1*angle-addr / addr-spec /
6805 atom / domain / msg-id
6809 static int is_item_value_atext(char ch)
6823 static int mailimf_item_value_atom_parse(const char * message, size_t length,
6824 size_t * index, char ** result)
6830 cur_token = * index;
6832 r = mailimf_cfws_parse(message, length, &cur_token);
6833 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6836 r = mailimf_custom_string_parse(message, length, &cur_token,
6837 &atom, is_item_value_atext);
6838 if (r != MAILIMF_NO_ERROR)
6841 r = mailimf_cfws_parse(message, length, &cur_token);
6842 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6845 * index = cur_token;
6848 return MAILIMF_NO_ERROR;
6851 static int mailimf_item_value_parse(const char * message, size_t length,
6853 struct mailimf_item_value ** result)
6856 clist * angle_addr_list;
6862 struct mailimf_item_value * item_value;
6866 cur_token = * index;
6868 angle_addr_list = NULL;
6874 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6876 (mailimf_struct_parser *)
6877 mailimf_angle_addr_parse,
6878 (mailimf_struct_destructor *)
6879 mailimf_angle_addr_free);
6880 if (r == MAILIMF_NO_ERROR)
6881 type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST;
6883 if (r == MAILIMF_ERROR_PARSE) {
6884 r = mailimf_addr_spec_parse(message, length, &cur_token,
6886 if (r == MAILIMF_NO_ERROR)
6887 type = MAILIMF_ITEM_VALUE_ADDR_SPEC;
6890 if (r == MAILIMF_ERROR_PARSE) {
6891 r = mailimf_msg_id_parse(message, length, &cur_token,
6893 if (r == MAILIMF_NO_ERROR)
6894 type = MAILIMF_ITEM_VALUE_MSG_ID;
6898 else if (mailimf_domain_parse(message, length, &cur_token,
6900 type = MAILIMF_ITEM_VALUE_DOMAIN;
6903 else if (mailimf_atom_parse(message, length, &cur_token,
6905 type = MAILIMF_ITEM_VALUE_ATOM;
6908 if (r == MAILIMF_ERROR_PARSE) {
6909 r = mailimf_item_value_atom_parse(message, length, &cur_token,
6911 if (r == MAILIMF_NO_ERROR)
6912 type = MAILIMF_ITEM_VALUE_ATOM;
6915 if (r != MAILIMF_NO_ERROR) {
6920 item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec,
6921 atom, domain, msg_id);
6922 if (item_value == NULL) {
6923 res = MAILIMF_ERROR_MEMORY;
6927 * result = item_value;
6928 * index = cur_token;
6930 return MAILIMF_NO_ERROR;
6933 if (angle_addr_list != NULL) {
6934 clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL);
6935 clist_free(angle_addr_list);
6937 if (addr_spec != NULL)
6938 mailimf_addr_spec_free(addr_spec);
6940 mailimf_atom_free(atom);
6942 mailimf_domain_free(domain);
6944 mailimf_msg_id_free(msg_id);
6951 optional-field = field-name ":" unstructured CRLF
6955 mailimf_optional_field_parse(const char * message, size_t length,
6957 struct mailimf_optional_field ** result)
6961 struct mailimf_optional_field * optional_field;
6966 cur_token = * index;
6968 r = mailimf_field_name_parse(message, length, &cur_token, &name);
6969 if (r != MAILIMF_NO_ERROR) {
6974 r = mailimf_colon_parse(message, length, &cur_token);
6975 if (r != MAILIMF_NO_ERROR) {
6980 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
6981 if (r != MAILIMF_NO_ERROR) {
6986 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6987 if (r != MAILIMF_NO_ERROR) {
6992 optional_field = mailimf_optional_field_new(name, value);
6993 if (optional_field == NULL) {
6994 res = MAILIMF_ERROR_MEMORY;
6998 * result = optional_field;
6999 * index = cur_token;
7001 return MAILIMF_NO_ERROR;
7004 mailimf_unstructured_free(value);
7006 mailimf_field_name_free(name);
7012 field-name = 1*ftext
7015 static inline int is_ftext(char ch);
7017 static int mailimf_field_name_parse(const char * message, size_t length,
7018 size_t * index, char ** result)
7024 cur_token = * index;
7027 if (end >= length) {
7028 return MAILIMF_ERROR_PARSE;
7031 while (is_ftext(message[end])) {
7036 if (end == cur_token) {
7037 return MAILIMF_ERROR_PARSE;
7040 /* field_name = strndup(message + cur_token, end - cur_token); */
7041 field_name = malloc(end - cur_token + 1);
7042 if (field_name == NULL) {
7043 return MAILIMF_ERROR_MEMORY;
7045 strncpy(field_name, message + cur_token, end - cur_token);
7046 field_name[end - cur_token] = '\0';
7050 * index = cur_token;
7051 * result = field_name;
7053 return MAILIMF_NO_ERROR;
7057 ftext = %d33-57 / ; Any character except
7058 %d59-126 ; controls, SP, and
7062 static inline int is_ftext(char ch)
7064 unsigned char uch = (unsigned char) ch;
7076 static int mailimf_ftext_parse(const char * message, size_t length,
7077 size_t * index, gchar * result)
7079 return mailimf_typed_text_parse(message, length, index, result, is_ftext);
7086 static int mailimf_envelope_field_parse(const char * message, size_t length,
7088 struct mailimf_field ** result)
7092 struct mailimf_orig_date * orig_date;
7093 struct mailimf_from * from;
7094 struct mailimf_sender * sender;
7095 struct mailimf_reply_to * reply_to;
7096 struct mailimf_to * to;
7097 struct mailimf_cc * cc;
7098 struct mailimf_bcc * bcc;
7099 struct mailimf_message_id * message_id;
7100 struct mailimf_in_reply_to * in_reply_to;
7101 struct mailimf_references * references;
7102 struct mailimf_subject * subject;
7103 struct mailimf_optional_field * optional_field;
7104 struct mailimf_field * field;
7109 cur_token = * index;
7122 optional_field = NULL;
7124 guessed_type = guess_header_type(message, length, cur_token);
7125 type = MAILIMF_FIELD_NONE;
7127 switch (guessed_type) {
7128 case MAILIMF_FIELD_ORIG_DATE:
7129 r = mailimf_orig_date_parse(message, length, &cur_token,
7131 if (r == MAILIMF_NO_ERROR)
7132 type = guessed_type;
7133 else if (r == MAILIMF_ERROR_PARSE) {
7141 case MAILIMF_FIELD_FROM:
7142 r = mailimf_from_parse(message, length, &cur_token,
7144 if (r == MAILIMF_NO_ERROR)
7145 type = guessed_type;
7146 else if (r == MAILIMF_ERROR_PARSE) {
7154 case MAILIMF_FIELD_SENDER:
7155 r = mailimf_sender_parse(message, length, &cur_token,
7157 if (r == MAILIMF_NO_ERROR)
7158 type = guessed_type;
7159 else if (r == MAILIMF_ERROR_PARSE) {
7167 case MAILIMF_FIELD_REPLY_TO:
7168 r = mailimf_reply_to_parse(message, length, &cur_token,
7170 if (r == MAILIMF_NO_ERROR)
7171 type = guessed_type;
7172 else if (r == MAILIMF_ERROR_PARSE) {
7180 case MAILIMF_FIELD_TO:
7181 r = mailimf_to_parse(message, length, &cur_token,
7183 if (r == MAILIMF_NO_ERROR)
7184 type = guessed_type;
7185 else if (r == MAILIMF_ERROR_PARSE) {
7193 case MAILIMF_FIELD_CC:
7194 r = mailimf_cc_parse(message, length, &cur_token,
7196 if (r == MAILIMF_NO_ERROR)
7197 type = guessed_type;
7198 else if (r == MAILIMF_ERROR_PARSE) {
7206 case MAILIMF_FIELD_BCC:
7207 r = mailimf_bcc_parse(message, length, &cur_token,
7209 if (r == MAILIMF_NO_ERROR)
7210 type = guessed_type;
7211 else if (r == MAILIMF_ERROR_PARSE) {
7219 case MAILIMF_FIELD_MESSAGE_ID:
7220 r = mailimf_message_id_parse(message, length, &cur_token,
7222 if (r == MAILIMF_NO_ERROR)
7223 type = guessed_type;
7224 else if (r == MAILIMF_ERROR_PARSE) {
7232 case MAILIMF_FIELD_IN_REPLY_TO:
7233 r = mailimf_in_reply_to_parse(message, length, &cur_token,
7235 if (r == MAILIMF_NO_ERROR)
7236 type = guessed_type;
7237 else if (r == MAILIMF_ERROR_PARSE) {
7245 case MAILIMF_FIELD_REFERENCES:
7246 r = mailimf_references_parse(message, length, &cur_token,
7248 if (r == MAILIMF_NO_ERROR)
7249 type = guessed_type;
7250 else if (r == MAILIMF_ERROR_PARSE) {
7258 case MAILIMF_FIELD_SUBJECT:
7259 r = mailimf_subject_parse(message, length, &cur_token,
7261 if (r == MAILIMF_NO_ERROR)
7262 type = guessed_type;
7263 else if (r == MAILIMF_ERROR_PARSE) {
7273 if (type == MAILIMF_FIELD_NONE) {
7274 res = MAILIMF_ERROR_PARSE;
7278 field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
7280 orig_date, from, sender, reply_to, to,
7281 cc, bcc, message_id, in_reply_to, references,
7282 subject, NULL, NULL, optional_field);
7283 if (field == NULL) {
7284 res = MAILIMF_ERROR_MEMORY;
7289 * index = cur_token;
7291 return MAILIMF_NO_ERROR;
7294 if (orig_date != NULL)
7295 mailimf_orig_date_free(orig_date);
7297 mailimf_from_free(from);
7299 mailimf_sender_free(sender);
7300 if (reply_to != NULL)
7301 mailimf_reply_to_free(reply_to);
7303 mailimf_to_free(to);
7305 mailimf_cc_free(cc);
7307 mailimf_bcc_free(bcc);
7308 if (message_id != NULL)
7309 mailimf_message_id_free(message_id);
7310 if (in_reply_to != NULL)
7311 mailimf_in_reply_to_free(in_reply_to);
7312 if (references != NULL)
7313 mailimf_references_free(references);
7314 if (subject != NULL)
7315 mailimf_subject_free(subject);
7316 if (optional_field != NULL)
7317 mailimf_optional_field_free(optional_field);
7322 int mailimf_envelope_fields_parse(const char * message, size_t length,
7324 struct mailimf_fields ** result)
7328 struct mailimf_fields * fields;
7332 cur_token = * index;
7336 res = MAILIMF_ERROR_MEMORY;
7341 struct mailimf_field * elt;
7343 r = mailimf_envelope_field_parse(message, length, &cur_token, &elt);
7344 if (r == MAILIMF_NO_ERROR) {
7345 r = clist_append(list, elt);
7347 res = MAILIMF_ERROR_MEMORY;
7351 else if (r == MAILIMF_ERROR_PARSE) {
7352 r = mailimf_ignore_field_parse(message, length, &cur_token);
7353 if (r == MAILIMF_NO_ERROR) {
7356 else if (r == MAILIMF_ERROR_PARSE) {
7370 fields = mailimf_fields_new(list);
7371 if (fields == NULL) {
7372 res = MAILIMF_ERROR_MEMORY;
7377 * index = cur_token;
7379 return MAILIMF_NO_ERROR;
7383 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7392 mailimf_envelope_or_optional_field_parse(const char * message,
7395 struct mailimf_field ** result)
7399 struct mailimf_optional_field * optional_field;
7400 struct mailimf_field * field;
7402 r = mailimf_envelope_field_parse(message, length, index, result);
7403 if (r == MAILIMF_NO_ERROR)
7404 return MAILIMF_NO_ERROR;
7406 cur_token = * index;
7408 r = mailimf_optional_field_parse(message, length, &cur_token,
7410 if (r != MAILIMF_NO_ERROR)
7413 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL,
7418 NULL, NULL, NULL, NULL, NULL,
7419 NULL, NULL, NULL, optional_field);
7420 if (field == NULL) {
7421 mailimf_optional_field_free(optional_field);
7422 return MAILIMF_ERROR_MEMORY;
7426 * index = cur_token;
7428 return MAILIMF_NO_ERROR;
7433 mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
7435 struct mailimf_fields ** result)
7439 struct mailimf_fields * fields;
7443 cur_token = * index;
7447 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7449 (mailimf_struct_parser *)
7450 mailimf_envelope_or_optional_field_parse,
7451 (mailimf_struct_destructor *)
7452 mailimf_field_free);
7454 case MAILIMF_NO_ERROR:
7458 case MAILIMF_ERROR_PARSE:
7461 res = MAILIMF_ERROR_MEMORY;
7471 fields = mailimf_fields_new(list);
7472 if (fields == NULL) {
7473 res = MAILIMF_ERROR_MEMORY;
7478 * index = cur_token;
7480 return MAILIMF_NO_ERROR;
7484 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7494 mailimf_only_optional_field_parse(const char * message,
7497 struct mailimf_field ** result)
7501 struct mailimf_optional_field * optional_field;
7502 struct mailimf_field * field;
7504 cur_token = * index;
7506 r = mailimf_optional_field_parse(message, length, &cur_token,
7508 if (r != MAILIMF_NO_ERROR)
7511 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL,
7512 NULL, NULL, NULL, NULL, NULL,
7513 NULL, NULL, NULL, NULL, NULL,
7514 NULL, NULL, NULL, NULL, NULL,
7515 NULL, NULL, NULL, optional_field);
7516 if (field == NULL) {
7517 mailimf_optional_field_free(optional_field);
7518 return MAILIMF_ERROR_MEMORY;
7522 * index = cur_token;
7524 return MAILIMF_NO_ERROR;
7529 mailimf_optional_fields_parse(const char * message, size_t length,
7531 struct mailimf_fields ** result)
7535 struct mailimf_fields * fields;
7539 cur_token = * index;
7543 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7545 (mailimf_struct_parser *)
7546 mailimf_only_optional_field_parse,
7547 (mailimf_struct_destructor *)
7548 mailimf_field_free);
7550 case MAILIMF_NO_ERROR:
7554 case MAILIMF_ERROR_PARSE:
7557 res = MAILIMF_ERROR_MEMORY;
7567 fields = mailimf_fields_new(list);
7568 if (fields == NULL) {
7569 res = MAILIMF_ERROR_MEMORY;
7574 * index = cur_token;
7576 return MAILIMF_NO_ERROR;
7580 clist_foreach(list, (clist_func) mailimf_field_free, NULL);